pkgsrc-WIP-changes archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
doomlegacy-devel: Partial UMAPINFO support
Module Name: pkgsrc-wip
Committed By: Michael Baeuerle <micha%NetBSD.org@localhost>
Pushed By: micha
Date: Mon Jan 23 11:45:19 2023 +0100
Changeset: 9e5dd03bcf1b83678b510581284349538d073ce0
Modified Files:
doomlegacy-devel/TODO
doomlegacy-devel/distinfo
doomlegacy-devel/files/umapinfo.c
doomlegacy-devel/files/umapinfo.h
doomlegacy-devel/patches/patch-make__options__nix
Added Files:
doomlegacy-devel/patches/patch-src_d__player.h
doomlegacy-devel/patches/patch-src_doomstat.h
doomlegacy-devel/patches/patch-src_g__game.c
doomlegacy-devel/patches/patch-src_p__info.c
doomlegacy-devel/patches/patch-src_w__wad.h
Log Message:
doomlegacy-devel: Partial UMAPINFO support
Build works now.
UMAPINFO keys 'label', "levelname', 'next' and 'nextsecret' should work.
(the default prefix for 'levelname' does not work yet).
To see a diff of this commit:
https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=9e5dd03bcf1b83678b510581284349538d073ce0
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
diffstat:
doomlegacy-devel/TODO | 9 +-
doomlegacy-devel/distinfo | 7 +-
doomlegacy-devel/files/umapinfo.c | 549 +++++++++++++++++++---
doomlegacy-devel/files/umapinfo.h | 54 ++-
doomlegacy-devel/patches/patch-make__options__nix | 2 +-
doomlegacy-devel/patches/patch-src_d__player.h | 29 ++
doomlegacy-devel/patches/patch-src_doomstat.h | 28 ++
doomlegacy-devel/patches/patch-src_g__game.c | 148 ++++++
doomlegacy-devel/patches/patch-src_p__info.c | 68 +++
doomlegacy-devel/patches/patch-src_w__wad.h | 17 +
10 files changed, 818 insertions(+), 93 deletions(-)
diffs:
diff --git a/doomlegacy-devel/TODO b/doomlegacy-devel/TODO
index 434fb263c0..b8387400cc 100644
--- a/doomlegacy-devel/TODO
+++ b/doomlegacy-devel/TODO
@@ -1,13 +1,16 @@
-Part 24: Mid-texture rendering
-==============================
-[ ] Some mid-textures are rendered wrong in Pagodia
+Part 24: Middle-texture rendering
+=================================
+[ ] Some middle-textures are rendered wrong in Pagodia
=> Reported upstream in ticket #687
Part 25: Add UMAPINFO support
=============================
[ ] Based on libdoom-umapinfo
+ => Module to parse and import data added
+ => Hooked in keys 'label', "levelname', 'next' and 'nextsecret'
+ The default prefix for 'levelname' does not work yet
EOF
diff --git a/doomlegacy-devel/distinfo b/doomlegacy-devel/distinfo
index 284b22dfe3..b2081ff970 100644
--- a/doomlegacy-devel/distinfo
+++ b/doomlegacy-devel/distinfo
@@ -3,7 +3,12 @@ $NetBSD$
BLAKE2s (doomlegacy_1.48.12_common.zip) = de8830301f433bc091804e8eaa0452fc574b99bc1d7e0021a71ba81aa6d90b76
SHA512 (doomlegacy_1.48.12_common.zip) = 955dd60058a4676c5d16b8058754ed9a5e33fe36d7605ed09518ce7c8c675ca6345f793db40f0328e8c78bfbe707880970f442b3a0c355c507ae7cf8a5f908be
Size (doomlegacy_1.48.12_common.zip) = 1055689 bytes
-SHA1 (patch-make__options__nix) = d8f7f3bd351e66e9cafe3b8e6093878d959fbc51
+SHA1 (patch-make__options__nix) = 666e4242f07d4d3e42da3b395cf95f07ed3b4c70
SHA1 (patch-src_Makefile) = 7921393b6c4941fd02d9644836991c30b0fb3188
SHA1 (patch-src_am__map.c) = 14b3c8b70c63778ad043827ab2f0b6f4fe07bcde
+SHA1 (patch-src_d__player.h) = 5975ea8a714aeb10dcecc7fd42fffcb8f9a2e51b
+SHA1 (patch-src_doomstat.h) = baa7387b6271d3064c12e24aaadf40cdb383e395
+SHA1 (patch-src_g__game.c) = bd31af700dd5ba7ffee84bec1a7caf7d37ab2d84
+SHA1 (patch-src_p__info.c) = e492f67a4c8f04779b267d6ef3b7faa75ef7779c
SHA1 (patch-src_w__wad.c) = 237489b5d19e89e36dbf6720467d910cd7b72aa9
+SHA1 (patch-src_w__wad.h) = 683283a32222e96a6472f103d3dc51e7229e4753
diff --git a/doomlegacy-devel/files/umapinfo.c b/doomlegacy-devel/files/umapinfo.c
index 37c054441f..cf52841985 100644
--- a/doomlegacy-devel/files/umapinfo.c
+++ b/doomlegacy-devel/files/umapinfo.c
@@ -17,7 +17,7 @@
//
//----------------------------------------------------------------------------
-// [MB] 2023-01-20: Support for Rev 2.2 added
+// [MB] 2023-01-21: Support for Rev 2.2 added
// Description of UMAPINFO lump format:
// https://doomwiki.org/wiki/UMAPINFO
@@ -27,6 +27,8 @@
#include <assert.h>
#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
#include "libdoom-umapinfo-0/doom_umi.h"
@@ -48,11 +50,12 @@ static void *UMI_Malloc(size_t memsize)
static void UMI_Free(void *ptr)
{
- Z_Free(ptr);
+ if (NULL != ptr)
+ Z_Free(ptr);
}
-static void UMI_InitMapEntry(umapinfo_t *entry,
+static void UMI_InitMapEntry(mapentry_t *entry,
unsigned int episode, unsigned int map)
{
entry->next = NULL;
@@ -74,57 +77,95 @@ static void UMI_InitMapEntry(umapinfo_t *entry,
entry->enterpic = NULL;
entry->emenu = NULL;
entry->bossactions = NULL;
+ entry->endgame = unchanged;
entry->episode = episode;
entry->map = map;
entry->partime = 0;
entry->emenu_clear = false;
entry->bossactions_clear = false;
entry->nointermission = false;
+ entry->endbunny = false;
+ entry->endcast = false;
}
-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)
+static void UMI_InitBossActionEntry(bossaction_t *entry)
+{
+ entry->next = NULL;
+
+ entry->thing = 0;
+ entry->special = 0;
+ entry->tag = 0;
+}
+
+
+static void UMI_InitEpisodeMenuEntry(emenu_t *entry)
+{
+ entry->next = NULL;
+
+ entry->patch = NULL;
+ entry->name = NULL;
+ entry->key = NULL;
+}
+
+
+static void UMI_DestroyEpisodeMenu(emenu_t *entry)
+{
+ while (NULL != entry)
{
- emenu_t *tmp = e->next;
+ emenu_t *tmp = entry->next;
- UMI_Free((void*) e->patch);
- UMI_Free((void*) e->name);
- UMI_Free((void*) e->key);
- UMI_Free(e);
- e = tmp;
+ UMI_Free((void*) entry->patch);
+ UMI_Free((void*) entry->name);
+ UMI_Free((void*) entry->key);
+ UMI_Free(entry);
+ entry = tmp;
}
- while (NULL != b)
+}
+
+
+static void UMI_DestroyBossActions(bossaction_t *entry)
+{
+ while (NULL != entry)
{
- bossaction_t *tmp = b->next;
+ bossaction_t *tmp = entry->next;
- UMI_Free(b);
- b = tmp
+ UMI_Free(entry);
+ entry = tmp;
}
+}
+
- UMI_Free(entry);
+static void UMI_DestroyMaps(mapentry_t *entry)
+{
+ while (NULL != entry)
+ {
+ mapentry_t *tmp = entry->next;
+
+ 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);
+ UMI_DestroyEpisodeMenu(entry->emenu);
+ UMI_DestroyBossActions(entry->bossactions);
+ UMI_Free(entry);
+ entry = tmp;
+ }
}
+// On error, 0 is returned
static unsigned int UMI_GetNumber(doom_umi0_ts_state state)
{
unsigned int number = 0;
@@ -140,67 +181,340 @@ static unsigned int UMI_GetNumber(doom_umi0_ts_state state)
}
-// Accepts only printable ASCII characters, others are replaced with '?'
-static void UMI_ConvertToASCII(char *t, const unsigned char *s, size_t len)
+// On error, NULL is returned (and nothing is written via 'len')
+// On success a pointer to the string is returned
+// A termination with NUL is appended, but not counted for 'len'
+// Attention: libdoom-umapinfo supports arbitrary encodings for quoted strings,
+// the result must be post-processed!
+static char *UMI_GetQString(doom_umi0_ts_state state, size_t *len)
{
- size_t i = 0;
+ char *result = NULL;
+ size_t length = 0;
+ const unsigned char *qstring = NULL;
+ int retval = DOOM_UMI0_ERROR_NOTFOUND;
- for (i = 0; len > i; ++i)
+ retval = doom_umi0_ts_value_read_qstring(state, &length, &qstring);
+ if (0 > retval || 0 == length + 1u)
+ GenPrintf(EMSG_warn, "UMAPINFO: Error while reading value (qstring)\n");
+ else
{
- if (0x20u > s[i] || 0x7Eu < s[i])
- t[i] = '?';
+ result = UMI_Malloc(length + 1u);
+
+ if (NULL == result)
+ GenPrintf(EMSG_warn, "UMAPINFO: Not enough memory for string\n");
else
- t[i] = s[i];
+ {
+ memcpy(result, qstring, length);
+ result[length] = 0;
+ *len = length;
+ }
+ }
+
+ return result;
+}
+
+
+// Accept only printable ASCII characters. Others are replaced with '?'
+// If parameter 'multiline' is true, LF control characters are accepted too
+static void UMI_ConvertToASCII(char *str, size_t length, boolean multiline)
+{
+ size_t i = 0;
+
+ for (i = 0; length > i; ++i)
+ {
+ if (multiline && 0x0A != str[i])
+ continue;
+
+ if (0x20u > str[i] || 0x7Eu < str[i])
+ str[i] = '?';
}
}
+// Control characters (e.g. line breaks) are not allowed
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;
+ size_t length = 0;
+ char *string = UMI_GetQString(state, &length);
- 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");
+ if (NULL != string)
+ {
+ UMI_ConvertToASCII(string, length, false);
+ UMI_Free((void*) *str);
+ *str = string;
+ }
+}
+
+
+static const char* UMI_CreateEmptyString()
+{
+ char *string = UMI_Malloc(1);
+
+ if (NULL == string)
+ GenPrintf(EMSG_warn, "UMAPINFO: Not enough memory for empty string\n");
else
+ string[0] = 0;
+
+ return string;
+}
+
+
+// Same as UMI_ReplaceString(), but 'clear' identifier gives empty string
+static void UMI_ReplaceStringClear(doom_umi0_ts_state state, const char** str)
+{
+ int type = DOOM_UMI0_TYPE_INVALID;
+ int retval = doom_umi0_ts_value_type(state, &type);
+
+ if (0 <= retval && DOOM_UMI0_TYPE_CLEAR == type)
{
- char *s = UMI_Malloc(length + 1u);
+ const char *string = UMI_CreateEmptyString();
- if (NULL == s)
- GenPrintf(EMSG_warn, "UMAPINFO: Not enough memory for string\n");
- else
+ if (NULL != string)
+ *str = string;
+ }
+ else
+ UMI_ReplaceString(state, str);
+}
+
+
+// It is allowed that multiple lines are contained in one value
+static void UMI_ReplaceMultiString(doom_umi0_ts_state state,
+ const char** str, size_t valcount)
+{
+ char *multi = NULL;
+ size_t multi_length = 0;
+ size_t val = 0;
+
+ for (val = 0; valcount > val; ++val)
+ {
+ size_t length = 0;
+ char *string = UMI_GetQString(state, &length);
+ int retval = DOOM_UMI0_ERROR_NOTFOUND;
+
+ if (NULL == string)
+ break;
+
+ if (NULL == multi)
+ {
+ multi = string;
+ multi_length = length;
+ }
+ else // Append
{
- // libdoom-umapinfo supports arbitrary encoding for quoted strings
- UMI_ConvertToASCII(s, qstring, length);
- s[length] = 0;
+ char *tmp = NULL;
+ size_t tmp_length = multi_length + length;
+
+ if (multi_length > tmp_length || 0 == tmp_length + 1u)
+ break;
+ tmp = UMI_Malloc(tmp_length + 1u);
+ if (NULL == tmp)
+ break;
+ memcpy(tmp, multi, multi_length);
+ memcpy(&tmp[multi_length], string, length + 1u);
+ UMI_Free(multi);
+ multi = tmp;
+ multi_length = tmp_length;
+ }
- UMI_Free((void*) *str);
- *str = s;
+ if (valcount - 1u != val)
+ {
+ retval = doom_umi0_ts_value_next(state);
+ if (0 > retval)
+ break;
}
}
+
+ if (0 == valcount || valcount != val)
+ GenPrintf(EMSG_warn, "UMAPINFO: Incomplete multi-line string\n");
+
+ if (NULL != multi)
+ {
+ UMI_ConvertToASCII(multi, multi_length, true);
+ UMI_Free((void*) *str);
+ *str = multi;
+ }
}
-static void UMI_ReplaceMultiString(doom_umi0_ts_state state,
- const char** str, size_t valcount)
+// Same as UMI_ReplaceMultiString(), but 'clear' identifier gives empty string
+static void UMI_ReplaceMultiStringClear(doom_umi0_ts_state state,
+ const char** str, size_t valcount)
{
- /* TBD */
+ int type = DOOM_UMI0_TYPE_INVALID;
+ int retval = doom_umi0_ts_value_type(state, &type);
+
+ if (0 <= retval && DOOM_UMI0_TYPE_CLEAR == type)
+ {
+ const char *string = UMI_CreateEmptyString();
+
+ if (NULL != string)
+ *str = string;
+ }
+ else
+ UMI_ReplaceMultiString(state, str, valcount);
}
-static void UMI_AppendMenuEntry(doom_umi0_ts_state state,
- emenu_t** em, size_t valcount)
+// Returns true on success
+static boolean UMI_PopulateEpisodeMenuEntry(doom_umi0_ts_state state,
+ emenu_t *entry)
{
- /* TBD */
+ boolean result = false;
+ size_t length = 0;
+ int retval = DOOM_UMI0_ERROR_NOTFOUND;
+ char *tmp = NULL;
+
+ tmp = UMI_GetQString(state, &length);
+ if (NULL != tmp)
+ {
+ UMI_ConvertToASCII(tmp, length, false);
+ entry->patch = tmp;
+ retval = doom_umi0_ts_value_next(state);
+ }
+
+ if (0 <= retval)
+ {
+ tmp = UMI_GetQString(state, &length);
+ if (NULL != tmp)
+ {
+ UMI_ConvertToASCII(tmp, length, false);
+ entry->name = tmp;
+ retval = doom_umi0_ts_value_next(state);
+ }
+ }
+
+ if (0 <= retval)
+ {
+ tmp = UMI_GetQString(state, &length);
+ if (NULL != tmp)
+ {
+ UMI_ConvertToASCII(tmp, length, false);
+ entry->key = tmp;
+ result = true;
+ }
+ }
+
+ return result;
+}
+
+
+// Returns true if identifier 'clear' was detected
+static boolean UMI_AppendEpisodeMenuEntry(doom_umi0_ts_state state,
+ emenu_t** em, size_t valcount)
+{
+ boolean result = false;
+ int type = DOOM_UMI0_TYPE_INVALID;
+ int retval = doom_umi0_ts_value_type(state, &type);
+
+ if (0 <= retval && DOOM_UMI0_TYPE_CLEAR == type)
+ {
+ UMI_DestroyEpisodeMenu(*em);
+ *em = NULL;
+ result = true;
+ }
+ else
+ {
+ emenu_t *entry = UMI_Malloc(sizeof(emenu_t));
+
+ if (NULL != entry)
+ {
+ UMI_InitEpisodeMenuEntry(entry);
+ if (false == UMI_PopulateEpisodeMenuEntry(state, entry))
+ {
+ GenPrintf(EMSG_warn,
+ "UMAPINFO: Error while reading episode menu entry\n");
+ UMI_DestroyEpisodeMenu(entry);
+ }
+ else
+ {
+ if (NULL == *em)
+ *em = entry;
+ else
+ {
+ emenu_t *tmp = *em;
+
+ while (NULL != tmp->next)
+ tmp = tmp->next;
+ tmp->next = entry;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+
+// Returns true on success
+static boolean UMI_PopulateBossActionEntry(doom_umi0_ts_state state,
+ bossaction_t *entry)
+{
+ boolean result = false;
+ size_t thing_index = 0;
+ int retval = DOOM_UMI0_ERROR_NOTFOUND;
+
+ retval = doom_umi0_ts_value_read_thing(state, NULL, &thing_index);
+ if (0 <= retval && (size_t) INT_MAX >= thing_index)
+ {
+ entry->thing = thing_index;
+ retval = doom_umi0_ts_value_next(state);
+ if (0 <= retval)
+ retval = doom_umi0_ts_value_read_number(state, &entry->special);
+ if (0 <= retval)
+ retval = doom_umi0_ts_value_next(state);
+ if (0 <= retval)
+ retval = doom_umi0_ts_value_read_number(state, &entry->tag);
+ if (0 <= retval)
+ result = true;
+ }
+
+ return result;
}
-static void UMI_MergeBossAction(doom_umi0_ts_state state,
- bossaction_t** ba, size_t valcount)
+static boolean UMI_MergeBossAction(doom_umi0_ts_state state,
+ bossaction_t** ba, size_t valcount)
{
- /* TBD */
+ boolean result = false;
+ int type = DOOM_UMI0_TYPE_INVALID;
+ int retval = doom_umi0_ts_value_type(state, &type);
+
+ if (0 <= retval && DOOM_UMI0_TYPE_CLEAR == type)
+ {
+ UMI_DestroyBossActions(*ba);
+ *ba = NULL;
+ result = true;
+ }
+ else if (DOOM_UMI0_TYPE_THING == type)
+ {
+ bossaction_t *entry = UMI_Malloc(sizeof(bossaction_t));
+
+ if (NULL != entry)
+ {
+ UMI_InitBossActionEntry(entry);
+ if (false == UMI_PopulateBossActionEntry(state, entry))
+ {
+ GenPrintf(EMSG_warn,
+ "UMAPINFO: Error while reading boss action\n");
+ UMI_DestroyBossActions(entry);
+ }
+ else
+ {
+ if (NULL == *ba)
+ *ba = entry;
+ else
+ {
+ bossaction_t *tmp = *ba;
+
+ while (NULL != tmp->next)
+ tmp = tmp->next;
+ tmp->next = entry;
+ }
+ }
+ }
+ }
+
+ return result;
}
@@ -229,16 +543,17 @@ static void UMI_StoreKeyData(doom_umi0_ts_state state, mapentry_t *entry)
UMI_ReplaceString(state, &entry->author);
break;
case DOOM_UMI0_KEY_LABEL:
- UMI_ReplaceString(state, &entry->label);
+ UMI_ReplaceStringClear(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);
+ UMI_ReplaceMultiStringClear(state, &entry->intertext, valcount);
break;
case DOOM_UMI0_KEY_INTERTEXTSECRET:
- UMI_ReplaceMultiString(state, &entry->intertextsecret, valcount);
+ UMI_ReplaceMultiStringClear(state,
+ &entry->intertextsecret, valcount);
break;
case DOOM_UMI0_KEY_INTERBACKDROP:
UMI_ReplaceString(state, &entry->interbackdrop);
@@ -246,7 +561,7 @@ static void UMI_StoreKeyData(doom_umi0_ts_state state, mapentry_t *entry)
case DOOM_UMI0_KEY_INTERMUSIC:
UMI_ReplaceString(state, &entry->intermusic);
break;
- case DOOM_UMI0_KEY_NEXTMAP:
+ case DOOM_UMI0_KEY_NEXT:
UMI_ReplaceString(state, &entry->nextmap);
break;
case DOOM_UMI0_KEY_NEXTSECRET:
@@ -271,12 +586,15 @@ static void UMI_StoreKeyData(doom_umi0_ts_state state, mapentry_t *entry)
UMI_ReplaceString(state, &entry->enterpic);
break;
case DOOM_UMI0_KEY_EPISODE:
- UMI_AppendMenuEntry(state, &entry->emenu, valcount);
- entry->emenu_clear = false;
+ entry->emenu_clear =
+ UMI_AppendEpisodeMenuEntry(state, &entry->emenu, valcount);
break;
case DOOM_UMI0_KEY_BOSSACTION:
- UMI_MergeBossAction(&entry->bossactions, valcount);
- entry->bossactions_clear = false;
+ entry->bossactions_clear =
+ UMI_MergeBossAction(state, &entry->bossactions, valcount);
+ break;
+ case DOOM_UMI0_KEY_ENDGAME:
+ entry->endgame = UMI_GetNumber(state) ? enabled : disabled;
break;
case DOOM_UMI0_KEY_PARTIME:
entry->partime = UMI_GetNumber(state);
@@ -284,6 +602,12 @@ static void UMI_StoreKeyData(doom_umi0_ts_state state, mapentry_t *entry)
case DOOM_UMI0_KEY_NOINTERMISSION:
entry->nointermission = UMI_GetNumber(state) ? true : false;
break;
+ case DOOM_UMI0_KEY_ENDBUNNY:
+ entry->endbunny = UMI_GetNumber(state) ? true : false;
+ break;
+ case DOOM_UMI0_KEY_ENDCAST:
+ entry->endcast = UMI_GetNumber(state) ? true : false;
+ break;
default:
GenPrintf(EMSG_warn, "UMAPINFO: Unknown key ignored\n");
break;
@@ -325,7 +649,7 @@ static mapentry_t *UMI_GetMapEntry(unsigned int episode, unsigned int map)
static void UMI_MergeMapEntry(doom_umi0_ts_state state)
{
- mapentry_t *entry = NULL
+ mapentry_t *entry = NULL;
unsigned int episode = 0;
unsigned int map = 0;
int retval = doom_umi0_ts_map_read(state, &episode, &map);
@@ -354,7 +678,7 @@ static void UMI_MergeMapEntry(doom_umi0_ts_state state)
}
-static void UMI_ImportUMapInfo(umapinfo *umi, doom_umi0_handle data)
+static void UMI_ImportUMapInfo(umapinfo_t *umi, doom_umi0_handle data)
{
doom_umi0_ts_state state = NULL;
size_t mapcount = 0; // Number of toplevel map entries
@@ -410,6 +734,58 @@ void UMI_LoadUMapInfoLump(lumpnum_t lumpnum)
}
+void UMI_DestroyUMapInfo(void)
+{
+ UMI_DestroyMaps(umapinfo.entry);
+ umapinfo.entry = NULL;
+}
+
+
+boolean UMI_ParseMapName(const char *name, byte *episode, byte *map)
+{
+ boolean result = false;
+ int retval = 0;
+ unsigned int e = 0;
+ unsigned int m = 0;
+
+ retval = sscanf(name, "%*[Mm]%*[Aa]%*[Pp]%u", &m);
+ if (1 == retval && 255u >= m)
+ result = true;
+
+ if (false == result)
+ {
+ retval = sscanf(name, "%*[Ee]%u%*[Mm]%u", &e, &m);
+ if (2 == retval && 255u >= e && 255u >= m)
+ result = true;
+ }
+
+ if (true == result)
+ {
+ *episode = e;
+ *map = m;
+ }
+
+ return result;
+}
+
+
+// DooM Legacy uses an unsigned type for 'byte'
+mapentry_t *UMI_LookupUMapInfo(byte episode, byte map)
+{
+ mapentry_t *entry = umapinfo.entry;
+
+ while (NULL != entry)
+ {
+ // Entries with numbers beyond the range of 'byte' will never match
+ if (entry->episode == episode && entry->map == map)
+ break;
+ entry = entry->next;
+ }
+
+ return entry;
+}
+
+
#else // HAVE_LIBDOOM_UMAPINFO
@@ -423,4 +799,25 @@ void UMI_LoadUMapInfoLump(lumpnum_t lumpnum)
}
+// Stub if libdoom-umapinfo is not available
+void UMI_DestroyUMapInfo(void)
+{
+ return;
+}
+
+
+// Stub if libdoom-umapinfo is not available
+boolean UMI_ParseMapName(const char *mapname, byte *episode, byte * map)
+{
+ return false;
+}
+
+
+// Stub if libdoom-umapinfo is not available
+mapentry_t *UMI_LookupUMapinfo(byte episode, byte map)
+{
+ return NULL;
+}
+
+
#endif // HAVE_LIBDOOM_UMAPINFO
diff --git a/doomlegacy-devel/files/umapinfo.h b/doomlegacy-devel/files/umapinfo.h
index 482ce4b68f..b0087b744b 100644
--- a/doomlegacy-devel/files/umapinfo.h
+++ b/doomlegacy-devel/files/umapinfo.h
@@ -24,28 +24,40 @@
// Entry for episode menu
-typedef struct
+typedef struct emenu_t emenu_t;
+struct emenu_t
{
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
+typedef struct bossaction_t bossaction_t;
+struct bossaction_t
{
bossaction_t *next;
- int thing; // Thing type
- int special; // Line special type
- int tag; // Sector tag
-} bossaction_t;
+ unsigned int thing; // Thing type (index for table of specification)
+ unsigned int special; // Line special type
+ unsigned int tag; // Sector tag
+};
-typedef struct
+typedef enum tristate_t tristate_t;
+enum tristate_t
+{
+ disabled, // Similar to false
+ enabled, // Similar to true
+ unchanged // Default behaviour
+};
+
+
+typedef struct mapentry_t mapentry_t;
+struct mapentry_t
{
mapentry_t *next;
@@ -66,13 +78,16 @@ typedef struct
const char *enterpic;
emenu_t *emenu; // Linked list
bossaction_t *bossactions; // Linked list
+ tristate_t endgame; // Can be undefined, false or true
unsigned int episode;
unsigned int map;
unsigned int partime;
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;
+ boolean endbunny; // End game after level, show bunny
+ boolean endcast; // End game after lavel, show cast call
+};
typedef struct
@@ -81,13 +96,28 @@ typedef struct
} umapinfo_t;
-// Current UMAPINFO data
+// Current data
extern umapinfo_t umapinfo;
-// Import UMAPINFO lump
-// If some keys are already present in current data, they are overwritten
+// Import and merge UMAPINFO lump into current data
+// If parts of the new data are already present, they overwrite the current data
void UMI_LoadUMapInfoLump(lumpnum_t lumpnum);
+// Destory current data
+void UMI_DestroyUMapInfo(void);
+
+
+// Extract episode and map numbers from map name
+// For Doom 2 map names zero is returned for episode
+// Returns true on success (numbers are valid)
+boolean UMI_ParseMapName(const char *mapname, byte *episode, byte * map);
+
+
+// Search for UMAPINFO map entry that matches episode and map parameters
+// NULL is returned if nothing was found
+mapentry_t *UMI_LookupUMapInfo(byte episode, byte map);
+
+
#endif // UMAPINFO_H
diff --git a/doomlegacy-devel/patches/patch-make__options__nix b/doomlegacy-devel/patches/patch-make__options__nix
index 4aaf9840d6..89130aefc8 100644
--- a/doomlegacy-devel/patches/patch-make__options__nix
+++ b/doomlegacy-devel/patches/patch-make__options__nix
@@ -9,7 +9,7 @@ Add support for libdoom-umapinfo.
# HAVE_LIBZIP=3
+# Support for UMAPINFO lump needs libdoom-umapinfo.
-+HAVE_LIBDOOM_UMAPINFO=0
++HAVE_LIBDOOM_UMAPINFO=1
+
# Extended nodes require zlib.
HAVE_ZLIB=1
diff --git a/doomlegacy-devel/patches/patch-src_d__player.h b/doomlegacy-devel/patches/patch-src_d__player.h
new file mode 100644
index 0000000000..3908846199
--- /dev/null
+++ b/doomlegacy-devel/patches/patch-src_d__player.h
@@ -0,0 +1,29 @@
+$NetBSD$
+
+Add support for UMAPINFO.
+
+--- src/d_player.h.orig 2023-01-10 10:38:38.000000000 +0000
++++ src/d_player.h
+@@ -63,6 +63,10 @@
+
+ #include "b_bot.h" //added by AC for acbot
+
++// [MB] 2023-01-22: Support for UMAPINFO added
++#include "umapinfo.h"
++
++
+ //
+ // Player states.
+ //
+@@ -266,6 +270,11 @@ typedef struct
+ int lev_prev;
+ int lev_next;
+
++ // [MB] 2023-01-22: Support for UMAPINFO added
++ int epsd_next; // Progression may cross into another episode
++ mapentry_t *lastmapinfo;
++ mapentry_t *nextmapinfo;
++
+ int maxkills;
+ int maxitems;
+ int maxsecret;
diff --git a/doomlegacy-devel/patches/patch-src_doomstat.h b/doomlegacy-devel/patches/patch-src_doomstat.h
new file mode 100644
index 0000000000..e7f0e14be1
--- /dev/null
+++ b/doomlegacy-devel/patches/patch-src_doomstat.h
@@ -0,0 +1,28 @@
+$NetBSD$
+
+Add support for UMAPINFO.
+
+--- src/doomstat.h.orig 2023-01-22 09:51:41.258749604 +0000
++++ src/doomstat.h
+@@ -75,6 +75,9 @@
+ #include "d_player.h"
+ #include "d_clisrv.h"
+
++// [MB] 2023-01-22: Support for UMAPINFO added
++#include "umapinfo.h"
++
+
+ // Game mode handling - identify IWAD version,
+ // handle IWAD dependend animations etc.
+@@ -234,6 +237,11 @@ extern skill_e gameskill; // ea
+ extern byte gameepisode; // Doom episode, 1..4
+ extern byte gamemap; // level 1..32
+
++// [MB] 2023-01-22: Support for UMAPINFO added
++// If this pointer is NULL, no additional UMAPINFO data is available
++// Otherwise it points to a UMAPINFO map entry structure
++extern mapentry_t * gamemapinfo;
++
+ // Nightmare mode flag, single player.
+ // extern boolean respawnmonsters;
+
diff --git a/doomlegacy-devel/patches/patch-src_g__game.c b/doomlegacy-devel/patches/patch-src_g__game.c
new file mode 100644
index 0000000000..53a3135fd1
--- /dev/null
+++ b/doomlegacy-devel/patches/patch-src_g__game.c
@@ -0,0 +1,148 @@
+$NetBSD$
+
+Add support for UMAPINFO.
+
+--- src/g_game.c.orig 2023-01-10 10:38:23.000000000 +0000
++++ src/g_game.c
+@@ -225,6 +225,7 @@ uint16_t demoversion_rev; // dem
+ skill_e gameskill;
+ byte gameepisode; // current game episode number 1..4
+ byte gamemap; // current game map number 1..31
++mapentry_t * gamemapinfo; // [MB] 2023-01-22: Support for UMAPINFO added
+ char game_map_filename[MAX_WADPATH]; // an external wad filename
+
+
+@@ -2384,10 +2385,69 @@ void G_DoCompleted (void)
+ automapactive = false;
+ }
+
++
++// [MB] 2023-01-22: Support for UMAPINFO added
++// Returns true if default setup should be skipped
++static boolean G_DoUMapInfo(void)
++{
++ boolean result = false;
++
++ wminfo.epsd_next = wminfo.epsd;
++ wminfo.lastmapinfo = gamemapinfo;
++ wminfo.nextmapinfo = NULL;
++
++ if (gamemapinfo)
++ {
++ const char *mapname = NULL;
++
++ // 'nextmap' or 'nextsecret' key overrides default behaviour
++ if (secretexit && gamemapinfo->nextsecret)
++ mapname = gamemapinfo->nextsecret;
++ else if (gamemapinfo->nextmap)
++ mapname = gamemapinfo->nextmap;
++
++ if (mapname)
++ {
++ result = true;
++
++ {
++ byte e = 0;
++ byte m = 0;
++
++ UMI_ParseMapName(mapname, &e, &m);
++ wminfo.epsd_next = e;
++ wminfo.lev_next = m;
++ }
++ wminfo.epsd_next--;
++ wminfo.lev_next--;
++
++ if (wminfo.epsd_next != wminfo.epsd)
++ {
++ // Jump to different episode
++ int i;
++
++ for (i = 0; MAXPLAYERS > i; ++i)
++ players[i].didsecret = false;
++ }
++ }
++ }
++
++ return result;
++}
++
++
+ void G_Start_Intermission( void )
+ {
+ int i;
+
++ // [MB] 2023-01-22: Support for UMAPINFO added
++ {
++ boolean skip = G_DoUMapInfo();
++
++ if (skip)
++ goto beyond_default_setup;
++ }
++
+ if (gamemode != doom2_commercial)
+ {
+ switch(gamemap)
+@@ -2436,7 +2496,7 @@ void G_Start_Intermission( void )
+ // go to next level
+ // wminfo.lev_next is 0 biased, unlike gamemap
+ wminfo.lev_next = gamemap;
+-
++
+ // overwrite next level in some cases
+ if (gamemode == doom2_commercial)
+ {
+@@ -2490,6 +2550,21 @@ void G_Start_Intermission( void )
+ wminfo.lev_next = 0; // wrap around in deathmatch
+ }
+ }
++beyond_default_setup:
++
++ // [MB] 2023-01-22: Support for UMAPINFO added
++ {
++ int e = wminfo.epsd_next + 1;
++ int m = wminfo.lev_next + 1;
++
++ if (0 <= e && 256 > e && 0 < m && 256 > m)
++ {
++ byte epsd = e;
++ byte map = m;
++
++ wminfo.nextmapinfo = UMI_LookupUMapInfo(epsd, map);
++ }
++ }
+
+ wminfo.maxkills = totalkills;
+ wminfo.maxitems = totalitems;
+@@ -2566,6 +2641,22 @@ void G_NextLevel (void)
+
+ void G_DoWorldDone (void)
+ {
++ // [MB] 2023-01-22: Support for UMAPINFO added
++ {
++ int e = wminfo.epsd_next + 1;
++ int m = wminfo.lev_next + 1;
++
++ if (0 <= e && 256 > e && 0 < m && 256 > m)
++ {
++ byte epsd = e;
++ byte map = m;
++
++ gameepisode = epsd;
++ gamemap = map;
++ gamemapinfo = UMI_LookupUMapInfo(gameepisode, gamemap);
++ }
++ }
++
+ if( demoversion<129 )
+ {
+ gamemap = wminfo.lev_next+1;
+@@ -2880,6 +2971,9 @@ void G_InitNew (skill_e skill, const cha
+ playerdeadview = false;
+ automapactive = false;
+
++ // [MB] 2023-01-22: Support for UMAPINFO added
++ gamemapinfo = UMI_LookupUMapInfo(gameepisode, gamemap);
++
+ G_DoLoadLevel (resetplayer);
+ }
+
diff --git a/doomlegacy-devel/patches/patch-src_p__info.c b/doomlegacy-devel/patches/patch-src_p__info.c
new file mode 100644
index 0000000000..51e1899d8e
--- /dev/null
+++ b/doomlegacy-devel/patches/patch-src_p__info.c
@@ -0,0 +1,68 @@
+$NetBSD$
+
+Add support for UMAPINFO.
+
+--- src/p_info.c.orig 2023-01-10 10:38:38.000000000 +0000
++++ src/p_info.c
+@@ -471,11 +471,50 @@ static char * levelname;
+ // Called by P_Load_LevelInfo
+ void P_FindLevelName(void)
+ {
++ // [MB] 2023-01-22: Common buffer
++ // Size is unchanged, but only 44 characters are displayed in worst case
++#define P_NEWLEVELSTR_SIZE 50u
++ static char newlevelstr[P_NEWLEVELSTR_SIZE];
++
+ // Determine the level name.
+ // There are a number of sources from which it can come from,
+ // getting the right one is the tricky bit =).
+-
+- if(*info_levelname)
++
++ // [MB] 2023-01-22: Support for UMAPINFO added
++ if (gamemapinfo && gamemapinfo->levelname)
++ {
++ size_t remaining = P_NEWLEVELSTR_SIZE - 1; // -1 for NUL-termination
++
++ newlevelstr[0] = 0;
++ if (gamemapinfo->label)
++ {
++ // The key 'label' contains a prefix for key 'levelname'
++ size_t len_label = strlen(gamemapinfo->label);
++ size_t len_level = strlen(gamemapinfo->levelname);
++
++ if (remaining < len_label)
++ len_label = remaining;
++ remaining -= len_label;
++ if (remaining < len_level)
++ len_level = remaining;
++
++ memcpy(newlevelstr, gamemapinfo->label, len_label);
++ memcpy(&newlevelstr[len_label], gamemapinfo->levelname, len_level);
++ newlevelstr[len_label + len_level] = 0;
++ }
++ else
++ {
++ size_t len_level = strlen(gamemapinfo->levelname);
++
++ if (remaining < len_level)
++ len_level = remaining;
++
++ memcpy(newlevelstr, gamemapinfo->levelname, len_level);
++ newlevelstr[len_level] = 0;
++ }
++ levelname = newlevelstr;
++ }
++ else if(*info_levelname)
+ {
+ // info level name from level lump (p_info.c) ?
+ levelname = info_levelname;
+@@ -516,8 +555,6 @@ void P_FindLevelName(void)
+ }
+ else // otherwise just put "new level"
+ {
+- static char newlevelstr[50];
+-
+ sprintf(newlevelstr, "%s: new level", level_mapname);
+ levelname = newlevelstr;
+ }
diff --git a/doomlegacy-devel/patches/patch-src_w__wad.h b/doomlegacy-devel/patches/patch-src_w__wad.h
new file mode 100644
index 0000000000..8ce0e32fad
--- /dev/null
+++ b/doomlegacy-devel/patches/patch-src_w__wad.h
@@ -0,0 +1,17 @@
+$NetBSD$
+
+Add support for UMAPINFO.
+
+--- src/w_wad.h.orig 2023-01-10 10:38:38.000000000 +0000
++++ src/w_wad.h
+@@ -308,8 +308,9 @@ typedef struct {
+ int firstlump;
+ int numlumps;
+ } lumplist_t;
+-
++
+ void W_Load_DehackedLumps( int wadnum );
++void W_Load_UMapInfoLumps( int wadnum );
+
+
+
Home |
Main Index |
Thread Index |
Old Index