pkgsrc-WIP-changes archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
doomlegacy-devel: Some more work for UMAPINFO support
Module Name: pkgsrc-wip
Committed By: Michael Baeuerle <micha%NetBSD.org@localhost>
Pushed By: micha
Date: Fri Jan 20 18:45:28 2023 +0100
Changeset: 39eb6050647e28421787d40030f6c5ea1c1f7166
Modified Files:
doomlegacy-devel/Makefile
doomlegacy-devel/files/umapinfo.c
doomlegacy-devel/files/umapinfo.h
Log Message:
doomlegacy-devel: Some more work for UMAPINFO support
To see a diff of this commit:
https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=39eb6050647e28421787d40030f6c5ea1c1f7166
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
diffstat:
doomlegacy-devel/Makefile | 1 +
doomlegacy-devel/files/umapinfo.c | 393 +++++++++++++++++++++++++++++++-------
doomlegacy-devel/files/umapinfo.h | 77 ++++----
3 files changed, 369 insertions(+), 102 deletions(-)
diffs:
diff --git a/doomlegacy-devel/Makefile b/doomlegacy-devel/Makefile
index ba205e916b..a0bbd93672 100644
--- a/doomlegacy-devel/Makefile
+++ b/doomlegacy-devel/Makefile
@@ -139,5 +139,6 @@ BUILDLINK_API_DEPENDS.SDL_mixer+= SDL_mixer>=1.2.7
.include "../../audio/SDL_mixer/buildlink3.mk"
BUILDLINK_API_DEPENDS.SDL+= SDL>=1.2.10
.include "../../devel/SDL/buildlink3.mk"
+.include "../../wip/libdoom-umapinfo/buildlink3.mk"
.include "../../mk/bsd.pkg.mk"
diff --git a/doomlegacy-devel/files/umapinfo.c b/doomlegacy-devel/files/umapinfo.c
index 3809a67dee..37c054441f 100644
--- a/doomlegacy-devel/files/umapinfo.c
+++ b/doomlegacy-devel/files/umapinfo.c
@@ -13,11 +13,12 @@
// GNU General Public License for more details.
//
// DESCRIPTION:
-// Support maps with additional information in UMAPINFO format.
+// Support for additional map information in UMAPINFO format.
//
//----------------------------------------------------------------------------
-//
-// [MB] 2023-01-10: Description of UMAPINFO lump format:
+
+// [MB] 2023-01-20: Support for Rev 2.2 added
+// Description of UMAPINFO lump format:
// https://doomwiki.org/wiki/UMAPINFO
@@ -27,7 +28,7 @@
#include <assert.h>
#include <stddef.h>
-#include "libdoom-umapinfo-0/doom_umi.h" // libdoom-umapinfo
+#include "libdoom-umapinfo-0/doom_umi.h"
#include "doomincl.h"
#include "umapinfo.h"
@@ -36,95 +37,347 @@
// UMAPINFO data in local format
-umapinfo_t umapinfo = { NULL, 0 };
+umapinfo_t umapinfo = { NULL };
-// Initialize map entry
-static void UMI_InitializeMapEntry(umapinfo_t *entry,
- unsigned int episode, unsigned int map)
+static void *UMI_Malloc(size_t memsize)
{
- entry->episode = episode;
- entry->map = map;
+ return Z_Malloc(memsize, PU_STATIC, 0);
+}
+
- entry->levelname = NULL;
- entry->label = NULL;
- entry->intertext = NULL;
- entry->intertextsecret = NULL;
- entry->levelpic = NULL;
- entry->nextmap = NULL;
- entry->nextsecret = NULL;
- entry->music = NULL;
- entry->skytexture = NULL;
- entry->endpic = NULL;
- entry->exitpic = NULL;
- entry->enterpic = NULL;
- entry->interbackdrop = NULL;
- entry->intermusic = NULL;
- entry->bossactions = NULL;
- entry->numbossactions = 0;
- entry->partime = 0;
- entry->nointermission = false;
+static void UMI_Free(void *ptr)
+{
+ Z_Free(ptr);
}
-// Populate map entry
-static int UMI_PopulateMapEntry(doom_umi0_ts_state state, size_t index)
+static void UMI_InitMapEntry(umapinfo_t *entry,
+ unsigned int episode, unsigned int map)
{
- unsigned int episode, map;
- int res = doom_umi0_ts_map_read(state, &episode, &map);
+ entry->next = NULL;
+
+ entry->author = NULL;
+ entry->label = NULL;
+ entry->levelname = NULL;
+ entry->intertext = NULL;
+ entry->intertextsecret = NULL;
+ entry->interbackdrop = NULL;
+ entry->intermusic = NULL;
+ entry->nextmap = NULL;
+ entry->nextsecret = NULL;
+ entry->music = NULL;
+ entry->skytexture = NULL;
+ entry->levelpic = NULL;
+ entry->endpic = NULL;
+ entry->exitpic = NULL;
+ entry->enterpic = NULL;
+ entry->emenu = NULL;
+ entry->bossactions = NULL;
+ entry->episode = episode;
+ entry->map = map;
+ entry->partime = 0;
+ entry->emenu_clear = false;
+ entry->bossactions_clear = false;
+ entry->nointermission = false;
+}
+
- if (0 == res)
+static void UMI_DestroyMapEntry(umapinfo_t *entry)
+{
+ emenu_t *e = entry->emenu;
+ bossaction_t *b = entry->bossactions;
+
+ UMI_Free((void*) entry->author);
+ UMI_Free((void*) entry->label);
+ UMI_Free((void*) entry->levelname);
+ UMI_Free((void*) entry->intertext);
+ UMI_Free((void*) entry->intertextsecret);
+ UMI_Free((void*) entry->interbackdrop);
+ UMI_Free((void*) entry->intermusic);
+ UMI_Free((void*) entry->nextmap);
+ UMI_Free((void*) entry->nextsecret);
+ UMI_Free((void*) entry->music);
+ UMI_Free((void*) entry->skytexture);
+ UMI_Free((void*) entry->levelpic);
+ UMI_Free((void*) entry->endpic);
+ UMI_Free((void*) entry->exitpic);
+ UMI_Free((void*) entry->enterpic);
+ while (NULL != e)
+ {
+ emenu_t *tmp = e->next;
+
+ UMI_Free((void*) e->patch);
+ UMI_Free((void*) e->name);
+ UMI_Free((void*) e->key);
+ UMI_Free(e);
+ e = tmp;
+ }
+ while (NULL != b)
{
- UMI_InitializeMapEntry(&umapinfo.map[index], episode, map);
+ bossaction_t *tmp = b->next;
+
+ UMI_Free(b);
+ b = tmp
+ }
+
+ UMI_Free(entry);
+}
+
+
+static unsigned int UMI_GetNumber(doom_umi0_ts_state state)
+{
+ unsigned int number = 0;
+ int retval = doom_umi0_ts_value_read_number(state, &number);
+
+ if (0 > retval)
+ {
+ GenPrintf(EMSG_warn, "UMAPINFO: Error while reading value (number)\n");
+ number = 0;
+ }
+
+ return number;
+}
+
- rets = doom_umi0_ts_key_first(state);
- while (0 == retval)
+// Accepts only printable ASCII characters, others are replaced with '?'
+static void UMI_ConvertToASCII(char *t, const unsigned char *s, size_t len)
+{
+ size_t i = 0;
+
+ for (i = 0; len > i; ++i)
+ {
+ if (0x20u > s[i] || 0x7Eu < s[i])
+ t[i] = '?';
+ else
+ t[i] = s[i];
+ }
+}
+
+
+static void UMI_ReplaceString(doom_umi0_ts_state state, const char** str)
+{
+ size_t length = 0;
+ const unsigned char *qstring = NULL;
+ int retval = DOOM_UMI0_ERROR_NOTFOUND;
+
+ retval = doom_umi0_ts_value_read_qstring(state, &length, &qstring);
+ if (0 > retval || length + 1u)
+ GenPrintf(EMSG_warn, "UMAPINFO: Error while reading value (qstring)\n");
+ else
+ {
+ char *s = UMI_Malloc(length + 1u);
+
+ if (NULL == s)
+ GenPrintf(EMSG_warn, "UMAPINFO: Not enough memory for string\n");
+ else
{
-XXX Insert key data
- res = doom_umi0_ts_key_next(state);
+ // libdoom-umapinfo supports arbitrary encoding for quoted strings
+ UMI_ConvertToASCII(s, qstring, length);
+ s[length] = 0;
+
+ UMI_Free((void*) *str);
+ *str = s;
}
}
+}
+
+
+static void UMI_ReplaceMultiString(doom_umi0_ts_state state,
+ const char** str, size_t valcount)
+{
+ /* TBD */
+}
+
+
+static void UMI_AppendMenuEntry(doom_umi0_ts_state state,
+ emenu_t** em, size_t valcount)
+{
+ /* TBD */
+}
+
+
+static void UMI_MergeBossAction(doom_umi0_ts_state state,
+ bossaction_t** ba, size_t valcount)
+{
+ /* TBD */
+}
+
+
+static void UMI_StoreKeyData(doom_umi0_ts_state state, mapentry_t *entry)
+{
+ size_t key = 0;
+ int retval = doom_umi0_ts_key_read(state, NULL, &key);
+ size_t valcount = 0;
+
+ if (0 > retval)
+ {
+ GenPrintf(EMSG_warn, "UMAPINFO: Error while reading key\n");
+ return;
+ }
+
+ retval = doom_umi0_ts_value_count(state, &valcount);
+ if (0 > retval || 0 == valcount)
+ {
+ GenPrintf(EMSG_warn, "UMAPINFO: Error while reading value\n");
+ return;
+ }
- // Only count successfully populated maps
- if (0 == res)
+ switch (key)
{
- ++umapinfo.mapnum;
+ case DOOM_UMI0_KEY_AUTHOR:
+ UMI_ReplaceString(state, &entry->author);
+ break;
+ case DOOM_UMI0_KEY_LABEL:
+ UMI_ReplaceString(state, &entry->label);
+ break;
+ case DOOM_UMI0_KEY_LEVELNAME:
+ UMI_ReplaceString(state, &entry->levelname);
+ break;
+ case DOOM_UMI0_KEY_INTERTEXT:
+ UMI_ReplaceMultiString(state, &entry->intertext, valcount);
+ break;
+ case DOOM_UMI0_KEY_INTERTEXTSECRET:
+ UMI_ReplaceMultiString(state, &entry->intertextsecret, valcount);
+ break;
+ case DOOM_UMI0_KEY_INTERBACKDROP:
+ UMI_ReplaceString(state, &entry->interbackdrop);
+ break;
+ case DOOM_UMI0_KEY_INTERMUSIC:
+ UMI_ReplaceString(state, &entry->intermusic);
+ break;
+ case DOOM_UMI0_KEY_NEXTMAP:
+ UMI_ReplaceString(state, &entry->nextmap);
+ break;
+ case DOOM_UMI0_KEY_NEXTSECRET:
+ UMI_ReplaceString(state, &entry->nextsecret);
+ break;
+ case DOOM_UMI0_KEY_MUSIC:
+ UMI_ReplaceString(state, &entry->music);
+ break;
+ case DOOM_UMI0_KEY_SKYTEXTURE:
+ UMI_ReplaceString(state, &entry->skytexture);
+ break;
+ case DOOM_UMI0_KEY_LEVELPIC:
+ UMI_ReplaceString(state, &entry->levelpic);
+ break;
+ case DOOM_UMI0_KEY_ENDPIC:
+ UMI_ReplaceString(state, &entry->endpic);
+ break;
+ case DOOM_UMI0_KEY_EXITPIC:
+ UMI_ReplaceString(state, &entry->exitpic);
+ break;
+ case DOOM_UMI0_KEY_ENTERPIC:
+ UMI_ReplaceString(state, &entry->enterpic);
+ break;
+ case DOOM_UMI0_KEY_EPISODE:
+ UMI_AppendMenuEntry(state, &entry->emenu, valcount);
+ entry->emenu_clear = false;
+ break;
+ case DOOM_UMI0_KEY_BOSSACTION:
+ UMI_MergeBossAction(&entry->bossactions, valcount);
+ entry->bossactions_clear = false;
+ break;
+ case DOOM_UMI0_KEY_PARTIME:
+ entry->partime = UMI_GetNumber(state);
+ break;
+ case DOOM_UMI0_KEY_NOINTERMISSION:
+ entry->nointermission = UMI_GetNumber(state) ? true : false;
+ break;
+ default:
+ GenPrintf(EMSG_warn, "UMAPINFO: Unknown key ignored\n");
+ break;
}
}
-// Import UMAPINFO data
-static void UMI_ImportUMapInfo(umapinfo *umi, doom_umi0_handle data)
+static mapentry_t *UMI_GetMapEntry(unsigned int episode, unsigned int map)
{
- doom_umi0_ts_state state = NULL;
- int retval = doom_umi0_ts_state_create(&state, data);
+ mapentry_t *entry = umapinfo.entry;
+ mapentry_t *entry_last = NULL;
- if (0 > retval)
- GenPrintf(EMSG_warn, "Importing UMAPINFO data failed\n");
- else
+ while (NULL != entry)
{
- size_t mapnum = doom_umi0_ts_map_count(state);
- size_t memsize = sizeof(umapinfo_t) * mapnum;
- size_t i = 0;
+ entry_last = entry;
+ if (episode == entry->episode && map == entry->map)
+ break;
- assert(memsize / mapnum == mapnum);
- umapinfo.map = Z_Malloc(memsize, PU_LEVEL, 0);
- umapinfo.mapnum = 0;
+ entry = entry->next;
+ }
- retval = doom_umi0_ts_map_first(state);
- while (0 == retval && mapnum)
+ if (NULL == entry)
+ {
+ // Not found, create new entry
+ entry = UMI_Malloc(sizeof(mapentry_t));
+ if (NULL != entry)
{
- retval = UMI_PopulateMapEntry(state, i++);
- if (0 == retval)
- retval = doom_umi0_ts_map_first(state);
+ UMI_InitMapEntry(entry, episode, map);
+ if (NULL == umapinfo.entry)
+ umapinfo.entry = entry;
+ else
+ entry_last->next = entry;
}
}
+ return entry;
+}
+
+
+static void UMI_MergeMapEntry(doom_umi0_ts_state state)
+{
+ mapentry_t *entry = NULL
+ unsigned int episode = 0;
+ unsigned int map = 0;
+ int retval = doom_umi0_ts_map_read(state, &episode, &map);
+
+ if (0 <= retval)
+ entry = UMI_GetMapEntry(episode, map);
+
+ if (NULL == entry)
+ retval = DOOM_UMI0_ERROR_NOTFOUND;
+ else
+ {
+ size_t keycount = 0;
+
+ retval = doom_umi0_ts_key_count(state, &keycount);
+ while (0 <= retval && keycount)
+ {
+ UMI_StoreKeyData(state, entry);
+
+ if (--keycount)
+ retval = doom_umi0_ts_key_next(state);
+ }
+ }
+
+ if (0 > retval)
+ GenPrintf(EMSG_warn, "UMAPINFO: Error while importing keys\n");
+}
+
+
+static void UMI_ImportUMapInfo(umapinfo *umi, doom_umi0_handle data)
+{
+ doom_umi0_ts_state state = NULL;
+ size_t mapcount = 0; // Number of toplevel map entries
+ int retval = doom_umi0_ts_state_create(&state, data);
+
+ if (0 <= retval)
+ retval = doom_umi0_ts_map_count(state, &mapcount);
+
+ while (0 <= retval && mapcount)
+ {
+ UMI_MergeMapEntry(state);
+
+ if (--mapcount)
+ retval = doom_umi0_ts_map_next(state);
+ }
+
doom_umi0_ts_state_destroy(&state);
+
+ if (0 > retval)
+ GenPrintf(EMSG_warn, "UMAPINFO: Error while importing map entry\n");
}
-// Load and parse UMAPINFO lump
void UMI_LoadUMapInfoLump(lumpnum_t lumpnum)
{
doom_umi0_handle data = NULL; // libdoom-umapinfo UMAPINFO object handle
@@ -133,19 +386,21 @@ void UMI_LoadUMapInfoLump(lumpnum_t lumpnum)
assert(0 <= len);
{
- unsigned char *lump = Z_Malloc(len, PU_IN_USE, 0);
+ int retval = DOOM_UMI0_ERROR_MEMORY;
+ unsigned char *lump = UMI_Malloc(len);
size_t length = len;
int verbose = 0;
- int retval = doom_umi0_create(&data, lump, length, verbose);
-
- W_ReadLump(lumpnum, lump);
+ if (NULL != lump)
+ {
+ W_ReadLump(lumpnum, lump);
+ retval = doom_umi0_create(&data, lump, length, verbose);
+ UMI_Free(lump);
+ }
if (0 > retval)
- GenPrintf(EMSG_warn, "Parsing UMAPINFO data failed\n");
+ GenPrintf(EMSG_warn, "UMAPINFO: Parsing data failed\n");
else if (0 < retval)
- GenPrintf(EMSG_warn, "Error in UMAPINFO, data may be incomplete\n");
-
- Z_Free(lump);
+ GenPrintf(EMSG_warn, "UMAPINFO: Warning: Data may be incomplete\n");
if (0 <= retval)
UMI_ImportUMapInfo(&umapinfo, data);
@@ -164,7 +419,7 @@ void UMI_LoadUMapInfoLump(lumpnum_t lumpnum)
// Stub if libdoom-umapinfo is not available
void UMI_LoadUMapInfoLump(lumpnum_t lumpnum)
{
- GenPrintf(EMSG_warn, "UMAPINFO ignored (libdoom-umapinfo not available)\n");
+ GenPrintf(EMSG_warn, "UMAPINFO: Ignored (libdoom-umapinfo is required)\n");
}
diff --git a/doomlegacy-devel/files/umapinfo.h b/doomlegacy-devel/files/umapinfo.h
index 8c723ba60b..482ce4b68f 100644
--- a/doomlegacy-devel/files/umapinfo.h
+++ b/doomlegacy-devel/files/umapinfo.h
@@ -13,7 +13,7 @@
// GNU General Public License for more details.
//
// DESCRIPTION:
-// Support maps with additional information in UMAPINFO format.
+// Support for additional map information in UMAPINFO format.
//
//----------------------------------------------------------------------------
@@ -23,60 +23,71 @@
#include "doomtype.h"
+// Entry for episode menu
typedef struct
{
- int thing; // Thing type
- int special; // Line special type
- int tag; // Sector tag
+ emenu_t *next;
+
+ const char *patch; // Used only if valid for all menu entries
+ const char *name; // Episode name (used with HUD font without patch)
+ const char *key; // Keyboard key
+} emenu_t;
+
+
+// Usable only for monsters that call A_BossDeath
+typedef struct
+{
+ bossaction_t *next;
+
+ int thing; // Thing type
+ int special; // Line special type
+ int tag; // Sector tag
} bossaction_t;
-// UMAPINFO data for a single map
typedef struct
{
+ mapentry_t *next;
+
+ const char *author;
+ const char *label; // NULL: default, Empty: clear
+ const char *levelname;
+ const char *intertext; // NULL: default, Empty: clear
+ const char *intertextsecret; // NULL: default, Empty: clear
+ const char *interbackdrop;
+ const char *intermusic;
+ const char *nextmap;
+ const char *nextsecret;
+ const char *music;
+ const char *skytexture;
+ const char *levelpic;
+ const char *endpic;
+ const char *exitpic;
+ const char *enterpic;
+ emenu_t *emenu; // Linked list
+ bossaction_t *bossactions; // Linked list
unsigned int episode;
unsigned int map;
-
- char *levelname;
- char *label;
- char *intertext;
- char *intertextsecret;
- char *levelpic;
- char *nextmap;
- char *nextsecret;
- char *music;
- char *skytexture;
- char *endpic;
- char *exitpic;
- char *enterpic;
- char *interbackdrop;
- char *intermusic;
- bossaction_t *bossactions;
- unsigned int numbossactions;
unsigned int partime;
- boolean nointermission;
+ boolean emenu_clear; // Clear all default episode menu entries
+ boolean bossactions_clear; // Clear all default boss actions
+ boolean nointermission; // Skip the 'level finished' screen
} mapentry_t;
typedef struct
{
- mapentry_t *map;
- unsigned int mapnum;
+ mapentry_t *entry; // Linked list
} umapinfo_t;
+// Current UMAPINFO data
extern umapinfo_t umapinfo;
+// Import UMAPINFO lump
+// If some keys are already present in current data, they are overwritten
void UMI_LoadUMapInfoLump(lumpnum_t lumpnum);
-#if 0
-extern boolean EpiCustom;
-mapentry_t *G_LookupMapinfo(int episode, int map);
-
-boolean UMI_CheckField(char *str);
-#endif
-
-
#endif // UMAPINFO_H
Home |
Main Index |
Thread Index |
Old Index