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