pkgsrc-WIP-changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

oomlegacy-devel: Update to SVN revision 1660



Module Name:	pkgsrc-wip
Committed By:	Michael Baeuerle <micha%NetBSD.org@localhost>
Pushed By:	micha
Date:		Wed Jan 17 13:52:03 2024 +0100
Changeset:	cd9ab802ab03252f0d44dd61ad9cf6a48dd752ca

Modified Files:
	doomlegacy-devel/Makefile
	doomlegacy-devel/TODO
	doomlegacy-devel/distinfo
Removed Files:
	doomlegacy-devel/files/umapinfo.c
	doomlegacy-devel/files/umapinfo.h
	doomlegacy-devel/patches/patch-make__options__nix
	doomlegacy-devel/patches/patch-src_Makefile
	doomlegacy-devel/patches/patch-src_d__main.c
	doomlegacy-devel/patches/patch-src_d__player.h
	doomlegacy-devel/patches/patch-src_doomstat.h
	doomlegacy-devel/patches/patch-src_f__finale.c
	doomlegacy-devel/patches/patch-src_f__finale.h
	doomlegacy-devel/patches/patch-src_g__game.c
	doomlegacy-devel/patches/patch-src_m__menu.c
	doomlegacy-devel/patches/patch-src_p__enemy.c
	doomlegacy-devel/patches/patch-src_p__info.c
	doomlegacy-devel/patches/patch-src_p__info.h
	doomlegacy-devel/patches/patch-src_p__setup.c
	doomlegacy-devel/patches/patch-src_w__wad.c
	doomlegacy-devel/patches/patch-src_w__wad.h
	doomlegacy-devel/patches/patch-src_wi__stuff.c

Log Message:
oomlegacy-devel: Update to SVN revision 1660

- commit revision 1666
  Add much better version and option reporting for the DoomLegacy binary.
  Changes the header to be a string that is composed at compile time.
  Moved the version and SVN settings to doomdef.h, because only from
  there can the COMPONENT_VERSION be set automatically.
  The COMPONENT_VERSION allows musserver and sndserver to identify their
  version of DoomLegacy.

  Can search the binary for the version strings.
  Do not have to run it, so windows binary can be searched for version on
  Linux.
  >> strings bin/doomlegacy | grep "Doom Legacy"
  >> strings bin/doomlegacy | grep "opts"

  DoomLegacy will now report many of the compile options when
  >> doomlegacy --version

- commit revision 1665
  Fix for the grenade launcher, DT-GREN.
  The file MBFONLY.DEH creates a missile that does not have MF_NOBLOCKMAP.
  This triggers a bug inherited from Vanilla Doom, and Boom, that causes
  the program to hang in a tight loop, or otherwise crash.
  The function P_CheckMissileSpawn changes the thing x,y position without
  calling P_UnsetThingPosition first.  This causes the blockmap unlink
  to index the wrong blocklist, and thus corrupt two blocklists.
  The best fix was to create a blockmap unlink that is not dependent
  upon the thing x,y position.  This is very similar to what MBF, and
  PrBoom did.

- commit revision 1664
  Fix the makefile so that FreeBSD, NetBSD, and any others
  supported in the makefile can compile with the zip libraries.

- commit revision 1660
  Fix some compile warnings within linux_x,
  strncpy, variable not used, and function not used.

- commit revision 1656
  Release version 1.48.14.

- commit revision 1656
  Add viewfit control.
  Has settings:
  AUTO: auto select based on actual screen size
  stretch: stretch to fit screen
  fit width: fit to screen width, scale to correct aspect ratio
  fit height: fit to screen height, scale to correct aspect ratio

- commit revision 1654
  UMAPINFO, derived from umapinfo-lib (GPL)
  written by Michael Bauerle, who has allowed us to use
  and modify it in DoomLegacy.
  It got heavily modified, as it was complicated with hiding internal
  structure, and that was not useful when it was embedded in DoomLegacy.
  Errors and messages were rewritten to attach to DoomLegacy error
  reporting.

- commit revision 1653
  Disabled a RANGECHECK in wi_stuff as many wads violate those assumptions.
  Many other typo and ptr declares encountered while working on UMAPINFO.

- commit revision 1652
  Fix error from w104_23. When made BOB_MOM code a standard feature,
  one of the compile tests was missed. Removing the BOB_MOM define,
  also made it active. Removed that code.
  Some other cleanup, ptr declares.

- commit revision 1651
  Fixing complaints from gcc 11.2.
  Also snprintf does not honor string max field size.
  Must copy possibly long strings to some shorter buffer first.
  Make a common send function for send to master_server.
  The code_size seems to have been reduced by 56K, perhaps due to new
  compiler.

- commit revision 1650
  Steven Newbury has been trying to compile for DOS.
  These are changes based on a something he summitted.
  This got delayed for a while, so I can no longer record how complete
  the changes are.  I suspect this is not complete, thus it is part1.
  It covers some network problems with DOS.
  Within djgppdos, there are DOS sound fixes and many fixes to bring the
  the interface up to date.

- commit revision 1649
  Add JOYSTICK_SUPPORT compile-time option, so that joystick code can be
  disabled.  This was necessary due to some port situations not having
  joystick hardware.

To see a diff of this commit:
https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=cd9ab802ab03252f0d44dd61ad9cf6a48dd752ca

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

diffstat:
 doomlegacy-devel/Makefile                         |    8 +-
 doomlegacy-devel/TODO                             |   37 +-
 doomlegacy-devel/distinfo                         |   23 +-
 doomlegacy-devel/files/umapinfo.c                 | 1036 ---------------------
 doomlegacy-devel/files/umapinfo.h                 |  122 ---
 doomlegacy-devel/patches/patch-make__options__nix |   16 -
 doomlegacy-devel/patches/patch-src_Makefile       |   31 -
 doomlegacy-devel/patches/patch-src_d__main.c      |   17 -
 doomlegacy-devel/patches/patch-src_d__player.h    |   29 -
 doomlegacy-devel/patches/patch-src_doomstat.h     |   28 -
 doomlegacy-devel/patches/patch-src_f__finale.c    |  237 -----
 doomlegacy-devel/patches/patch-src_f__finale.h    |   16 -
 doomlegacy-devel/patches/patch-src_g__game.c      |  229 -----
 doomlegacy-devel/patches/patch-src_m__menu.c      |  105 ---
 doomlegacy-devel/patches/patch-src_p__enemy.c     |  203 ----
 doomlegacy-devel/patches/patch-src_p__info.c      |  142 ---
 doomlegacy-devel/patches/patch-src_p__info.h      |   28 -
 doomlegacy-devel/patches/patch-src_p__setup.c     |   24 -
 doomlegacy-devel/patches/patch-src_w__wad.c       |   55 --
 doomlegacy-devel/patches/patch-src_w__wad.h       |   17 -
 doomlegacy-devel/patches/patch-src_wi__stuff.c    |  312 -------
 21 files changed, 16 insertions(+), 2699 deletions(-)

diffs:
diff --git a/doomlegacy-devel/Makefile b/doomlegacy-devel/Makefile
index 6227b9f210..cba952a31f 100644
--- a/doomlegacy-devel/Makefile
+++ b/doomlegacy-devel/Makefile
@@ -1,8 +1,8 @@
 # $NetBSD$
 
-VERS=		1.48.12
+VERS=		1.48.14
 #PKGNAME=	doomlegacy-${VERS}
-SVNVERS=	1648
+SVNVERS=	1666
 DISTNAME=	doomlegacy-devel-0r${SVNVERS}
 CATEGORIES=	games
 
@@ -96,8 +96,6 @@ SUBST_FILES.install=	${WRKDIR}/INSTALL.pkgsrc
 SUBST_SED.install=	-e 's,DOOMWADDIR,${PREFIX}/${DOOMWADDIR},'
 
 pre-configure:
-	${CP} ${FILESDIR}/umapinfo.c ${WRKSRC}/src
-	${CP} ${FILESDIR}/umapinfo.h ${WRKSRC}/src
 	${CP} ${FILESDIR}/INSTALL.pkgsrc ${WRKDIR}
 	${CP} ${FILESDIR}/doomlegacy.sh ${WRKDIR}
 	${CP} ${FILESDIR}/doomlegacy.6.in ${WRKDIR}
@@ -139,7 +137,5 @@ 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"
-BUILDLINK_API_DEPENDS.libdoom-umapinfo+=	libdoom-umapinfo>=1.0.0rc5
-.include "../../wip/libdoom-umapinfo/buildlink3.mk"
 
 .include "../../mk/bsd.pkg.mk"
diff --git a/doomlegacy-devel/TODO b/doomlegacy-devel/TODO
index 8670ad3a8e..4d732ddb77 100644
--- a/doomlegacy-devel/TODO
+++ b/doomlegacy-devel/TODO
@@ -1,37 +1,20 @@
 
-Part 24: Middle-texture rendering
-=================================
-[X] Some middle-textures are rendered wrong in Pagodia
-    => Reported upstream in ticket #687
-    => Fixed with SVN revision 1647
-
-
-Part 25: Add UMAPINFO support
-=============================
-[X] Based on libdoom-umapinfo-1.0.0
-    => Module to parse and import data added
-[X] Hook keys into game engine
-    => All keys should work now, up to the limits of the engine
-[X] Add support for "\n" line breaks in key "intertext".
-[X] Use Doom zone memory as libdoom-umapinfo memory manager
-
-=> Created upstream feature request ticket #100
-
-
-Part 26: Incorrect voodoo doll behaviour
-========================================
-[X] Player stuck in Solar Struggle (map E3M6)
-    Voodoo doll transfers damage to the player, but seems to not take thrust
-    (is not pushed away e.g. from an explosion as expected).
-    => Reported upstream in ticket #688
-    No fix required. Vanilla behaviour can be configured via menu.
+Features and bug fixes up to Part 26 were released with version 1.48.14
+(SVN revision 1660).
 
 
 Part 27: Some bossactions are not Vanilla-compatible
 ====================================================
 [X] Player stuck in Atonement (map 01)
-    => Reported upstream in ticket #690
+    => Reported upstream in bug ticket #690
     Proposed patch may break existing WAD files.
 
 
+Part 28: Some bossactions are not Vanilla-compatible
+====================================================
+[X] Flats are rendered wrong for some viewfit settings
+    => Reported upstream in bug ticket #692
+    Setting "Fit_Width" and "Stretch" are not affected.
+
+
 EOF
diff --git a/doomlegacy-devel/distinfo b/doomlegacy-devel/distinfo
index 400533238e..12da9e2091 100644
--- a/doomlegacy-devel/distinfo
+++ b/doomlegacy-devel/distinfo
@@ -1,23 +1,8 @@
 $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) = 666e4242f07d4d3e42da3b395cf95f07ed3b4c70
-SHA1 (patch-src_Makefile) = 7921393b6c4941fd02d9644836991c30b0fb3188
+SHA1 (doomlegacy_1.48.14_common.zip) = 44d9533321656139a1057c6a0e12eb03a79d6e4d
+RMD160 (doomlegacy_1.48.14_common.zip) = 33422e0242ec00395fc40212f74374b00180320a
+SHA512 (doomlegacy_1.48.14_common.zip) = 69e7c4a004a507ec87c39d31595e11c5a764e470ee59cd231a61dfaad70b77ac8c8c4789cfb333bfa0343aed210d5986136a6fa5cb88bc066af50d8c8fac1ce6
+Size (doomlegacy_1.48.14_common.zip) = 1056545 bytes
 SHA1 (patch-src_am__map.c) = 14b3c8b70c63778ad043827ab2f0b6f4fe07bcde
-SHA1 (patch-src_d__main.c) = c889d3601230f66a9cd062e80e44497dd5f69e2f
-SHA1 (patch-src_d__player.h) = 5975ea8a714aeb10dcecc7fd42fffcb8f9a2e51b
-SHA1 (patch-src_doomstat.h) = baa7387b6271d3064c12e24aaadf40cdb383e395
-SHA1 (patch-src_f__finale.c) = d9f116f0830fb533fe5f72454cd905d8b289162a
-SHA1 (patch-src_f__finale.h) = 5ba7ae568be4dd97d06e4724dc7e1907f3a09cd8
-SHA1 (patch-src_g__game.c) = 296be562113be189c15ece8fbaffb8c7ae04df56
-SHA1 (patch-src_m__menu.c) = 81ae8b6edd90e039132e28b23fe35ff62bc4bce8
-SHA1 (patch-src_p__enemy.c) = c9ce6dbc275db474281539e7ae48a09d65627d5c
-SHA1 (patch-src_p__info.c) = 9a8061b1d183374f1ea3678c6a0ad762ff12f8bd
-SHA1 (patch-src_p__info.h) = e24772efb6b42ad5b834b1c12477f2a2feb508aa
-SHA1 (patch-src_p__setup.c) = 77ef2316b3d5ac72274ccfcf6bff3229a9245997
-SHA1 (patch-src_w__wad.c) = 9853306fd400ee53a48efa38c31e5dbec5d51d82
-SHA1 (patch-src_w__wad.h) = 683283a32222e96a6472f103d3dc51e7229e4753
-SHA1 (patch-src_wi__stuff.c) = bd577ec36ef5580e65dec3befa7c7c74aeb92de2
 SHA1 (patch-src_z__zone.c) = 13f4ff4a4af836f62779544b72e83b9eb109f7a5
diff --git a/doomlegacy-devel/files/umapinfo.c b/doomlegacy-devel/files/umapinfo.c
deleted file mode 100644
index 3acc6d7431..0000000000
--- a/doomlegacy-devel/files/umapinfo.c
+++ /dev/null
@@ -1,1036 +0,0 @@
-// -----------------------------------------------------------------------------
-//
-// Copyright(C) 2023 by DooM Legacy Team
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// DESCRIPTION:
-//      Support for additional map information in UMAPINFO format.
-//
-// -----------------------------------------------------------------------------
-//
-// [MB] 2023-08-25: Register zone memory as libdoom-umapinfo memory manager
-//
-// [MB] 2023-01-21: Support for Rev 2.2 added
-//      Description of UMAPINFO lump format:
-//      https://doomwiki.org/wiki/UMAPINFO
-
-
-#ifdef HAVE_LIBDOOM_UMAPINFO
-
-
-#include <assert.h>
-#include <limits.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "libdoom-umapinfo-1/doom_umi.h"
-
-#include "dehacked.h"
-#include "doomincl.h"
-#include "doomstat.h"
-#include "p_info.h"
-#include "umapinfo.h"
-#include "w_wad.h"
-#include "z_zone.h"
-
-
-// Internal representation of UMAPINFO data (merged from PWADs)
-umapinfo_t umapinfo = { NULL, NULL, false };
-
-
-// -----------------------------------------------------------------------------
-// C-style API for memory management
-
-static void *UMI_Malloc(size_t memsize)
-{
-    return Z_Malloc(memsize, PU_STATIC, 0);
-}
-
-
-static void *UMI_Realloc(void *ptr_old, size_t memsize_new)
-{
-    void *ptr_new = Z_Malloc(memsize_new, PU_STATIC, 0);
-
-    if (NULL != ptr_new)
-    {
-        if (NULL != ptr_old)
-        {
-            int memsize_tmp = Z_Datasize(ptr_old);
-
-            if (0 > memsize_tmp)
-            {
-                Z_Free(ptr_new);
-                ptr_new = NULL;
-            }
-            else
-            {
-                // Data of type int must fit into size_t
-                size_t memsize_old = memsize_tmp;
-
-                if (memsize_new < memsize_old)
-                    memcpy(ptr_new, ptr_old, memsize_new);
-                else
-                    memcpy(ptr_new, ptr_old, memsize_old);
-                Z_Free(ptr_old);
-            }
-        }
-    }
-
-    return ptr_new;
-}
-
-
-static void UMI_Free(void *ptr)
-{
-    if (NULL != ptr)
-        Z_Free(ptr);
-}
-
-
-// -----------------------------------------------------------------------------
-// Constructors and destructors
-
-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 = entry->next;
-
-        UMI_Free((void*) entry->patch);
-        UMI_Free((void*) entry->name);
-        UMI_Free((void*) entry->key);
-        UMI_Free(entry);
-        entry = tmp;
-    }
-}
-
-
-static void UMI_InitBossActionEntry(bossaction_t *entry)
-{
-    entry->next    = NULL;
-
-    entry->thing   = 0;
-    entry->special = 0;
-    entry->tag     = 0;
-}
-
-
-static void UMI_DestroyBossActions(bossaction_t *entry)
-{
-    while (NULL != entry)
-    {
-        bossaction_t *tmp = entry->next;
-
-        UMI_Free(entry);
-        entry = tmp;
-    }
-}
-
-
-static void UMI_InitMapEntry(mapentry_t *entry,
-                             unsigned int episode, unsigned int 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->exitpic           = NULL;
-    entry->enterpic          = NULL;
-    entry->endpic            = NULL;
-    entry->bossactions       = NULL;
-    entry->endgame           = unchanged;
-    entry->episode           = episode;
-    entry->map               = map;
-    entry->partime           = 0;
-    entry->bossactions_clear = false;
-    entry->nointermission    = false;
-    entry->endbunny          = false;
-    entry->endcast           = false;
-}
-
-
-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->exitpic);
-        UMI_Free((void*) entry->enterpic);
-        UMI_Free((void*) entry->endpic);
-        UMI_DestroyBossActions(entry->bossactions);
-        UMI_Free(entry);
-        entry = tmp;
-    }
-}
-
-
-// -----------------------------------------------------------------------------
-// Access functions for key values
-
-// On error, 0 is returned
-static unsigned int UMI_GetNumber(doom_umi1_ts_state state)
-{
-    unsigned int number = 0;
-    int          retval = doom_umi1_ts_value_read_number(state, &number);
-
-    if (0 > retval)
-    {
-        GenPrintf(EMSG_warn, "UMAPINFO: Error while reading value (number)\n");
-        number = 0;
-    }
-
-    return number;
-}
-
-
-// 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_umi1_ts_state state, size_t *len)
-{
-    char                *result  = NULL;
-    size_t               length  = 0;
-    const unsigned char *qstring = NULL;
-    int                  retval  = DOOM_UMI1_ERROR_NOTFOUND;
-
-    retval = doom_umi1_ts_value_read_qstring(state, &length, &qstring);
-    if (0 > retval || 0 == length + 1u)
-        GenPrintf(EMSG_warn, "UMAPINFO: Error while reading value (qstring)\n");
-    else
-    {
-        result = UMI_Malloc(length + 1u);
-
-        if (NULL == result)
-            GenPrintf(EMSG_warn, "UMAPINFO: Not enough memory for string\n");
-        else
-        {
-            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
-// - Escape sequences "\n" are converted to SP LF
-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 (0 < i && 0x5C == str[i - 1u] && 'n' == str[i])
-        {
-            str[i - 1u] = ' ';
-            str[i] = 0x0A;
-            continue;
-        }
-
-        if (0x20 > str[i] || 0x7E < str[i])
-            str[i] = '?';
-    }
-}
-
-
-// Control characters (e.g. line breaks) are not allowed
-static void UMI_ReplaceString(doom_umi1_ts_state state, const char** str)
-{
-    size_t  length = 0;
-    char   *string = UMI_GetQString(state, &length);
-
-    if (NULL != string)
-    {
-        UMI_ConvertToASCII(string, length, false);
-        UMI_Free((void*) *str);
-        *str = string;
-    }
-}
-
-
-// Like UMI_ReplaceString(), but ignores strings with more than 8 characters
-static void UMI_ReplaceStringMax8(doom_umi1_ts_state state, const char** str)
-{
-    size_t  length = 0;
-    char   *string = UMI_GetQString(state, &length);
-
-    if (NULL != string)
-    {
-        if (8u < length)
-            UMI_Free(string);
-        else
-        {
-            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_umi1_ts_state state, const char** str)
-{
-    int type   = DOOM_UMI1_TYPE_INVALID;
-    int retval = doom_umi1_ts_value_type(state, &type);
-
-    if (0 <= retval && DOOM_UMI1_TYPE_CLEAR == type)
-    {
-        const char *string = UMI_CreateEmptyString();
-
-        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_umi1_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_UMI1_ERROR_NOTFOUND;
-
-        if (NULL == string)
-            break;
-
-        if (NULL == multi)
-        {
-            multi        = string;
-            multi_length = length;
-        }
-        else if (0 != length)  // Append
-        {
-            char   *tmp        = NULL;
-            size_t  tmp_length = multi_length + length;
-
-            tmp_length += 2u;  // For LF and NUL-termination
-            if (multi_length > tmp_length)
-                break;
-            tmp = UMI_Malloc(tmp_length);
-            if (NULL == tmp)
-                break;
-            memcpy(tmp, multi, multi_length);
-            tmp[multi_length] = 0x0A;  // LF
-            memcpy(&tmp[multi_length + 1u], string, length + 1u);
-            UMI_Free(multi);
-            multi        = tmp;
-            multi_length = tmp_length - 1u;  // Without NUL-termination
-        }
-
-        if (valcount - 1u != val)
-        {
-            retval = doom_umi1_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;
-    }
-}
-
-
-// Same as UMI_ReplaceMultiString(), but 'clear' identifier gives empty string
-static void UMI_ReplaceMultiStringClear(doom_umi1_ts_state state,
-                                        const char** str, size_t valcount)
-{
-    int type   = DOOM_UMI1_TYPE_INVALID;
-    int retval = doom_umi1_ts_value_type(state, &type);
-
-    if (0 <= retval && DOOM_UMI1_TYPE_CLEAR == type)
-    {
-        const char *string = UMI_CreateEmptyString();
-
-        if (NULL != string)
-            *str = string;
-    }
-    else
-        UMI_ReplaceMultiString(state, str, valcount);
-}
-
-
-// -----------------------------------------------------------------------------
-// Episode menu
-
-// Returns true on success
-static boolean UMI_PopulateEpisodeMenuEntry(doom_umi1_ts_state state,
-                                            emenu_t *entry)
-{
-    boolean  result = false;
-    size_t   length = 0;
-    int      retval = DOOM_UMI1_ERROR_NOTFOUND;
-    char    *tmp    = NULL;
-
-    tmp = UMI_GetQString(state, &length);
-    if (NULL != tmp)
-    {
-        UMI_ConvertToASCII(tmp, length, false);
-        entry->patch = tmp;
-        retval = doom_umi1_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_umi1_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_umi1_ts_state state,
-                                          emenu_t** em, size_t valcount)
-{
-    boolean  result = false;
-    int      type   = DOOM_UMI1_TYPE_INVALID;
-    int      retval = doom_umi1_ts_value_type(state, &type);
-
-    if (0 <= retval && DOOM_UMI1_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
-            {
-                // Append episode menu entry to list
-                if (NULL == *em)
-                    *em = entry;
-                else
-                {
-                    emenu_t *tmp = *em;
-
-                    while (NULL != tmp->next)
-                        tmp = tmp->next;
-                    tmp->next = entry;
-                }
-            }
-        }
-    }
-
-    return result;
-}
-
-
-// -----------------------------------------------------------------------------
-// Boss actions
-
-// Returns true on success
-static boolean UMI_PopulateBossActionEntry(doom_umi1_ts_state state,
-                                           bossaction_t *entry)
-{
-    boolean result      = false;
-    size_t  thing_index = 0;
-    int     retval      = DOOM_UMI1_ERROR_NOTFOUND;
-
-    retval = doom_umi1_ts_value_read_thing(state, NULL, &thing_index);
-    if (0 <= retval && (size_t) INT_MAX >= thing_index)
-    {
-        entry->thing = thing_index;
-        retval = doom_umi1_ts_value_next(state);
-        if (0 <= retval)
-            retval = doom_umi1_ts_value_read_number(state, &entry->special);
-        if (0 <= retval)
-            retval = doom_umi1_ts_value_next(state);
-        if (0 <= retval)
-            retval = doom_umi1_ts_value_read_number(state, &entry->tag);
-        if (0 <= retval)
-            result = true;
-    }
-
-    return result;
-}
-
-
-// Returns true if identifier 'clear' was detected
-static boolean UMI_MergeBossAction(doom_umi1_ts_state state,
-                                   bossaction_t** ba, size_t valcount)
-{
-    boolean  result = false;
-    int      type   = DOOM_UMI1_TYPE_INVALID;
-    int      retval = doom_umi1_ts_value_type(state, &type);
-
-    if (0 <= retval && DOOM_UMI1_TYPE_CLEAR == type)
-    {
-        UMI_DestroyBossActions(*ba);
-        *ba    = NULL;
-        result = true;
-    }
-    else
-    {
-        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;
-}
-
-
-// -----------------------------------------------------------------------------
-// Import data
-
-// Check whether map entry object for episode/map already exists
-// If not, create an empty map entry object
-static mapentry_t *UMI_GetMapEntry(unsigned int episode, unsigned int map)
-{
-    mapentry_t *entry      = umapinfo.entry_first;
-    mapentry_t *entry_last = NULL;
-
-    while (NULL != entry)
-    {
-        entry_last = entry;
-        if (episode == entry->episode && map == entry->map)
-            break;
-
-        entry = entry->next;
-    }
-
-    if (NULL == entry)
-    {
-        // Not found, create new entry
-        entry = UMI_Malloc(sizeof(mapentry_t));
-        if (NULL != entry)
-        {
-            UMI_InitMapEntry(entry, episode, map);
-            if (NULL == umapinfo.entry_first)
-                umapinfo.entry_first = entry;
-            else
-                entry_last->next = entry;
-        }
-    }
-
-    return entry;
-}
-
-
-static void UMI_StoreKeyData(doom_umi1_ts_state state, mapentry_t *entry)
-{
-    size_t  key      = 0;
-    int     retval   = doom_umi1_ts_key_read(state, NULL, &key);
-    size_t  valcount = 0;
-    boolean emc      = false;  // Episode menu clear request
-
-    if (0 > retval)
-    {
-        GenPrintf(EMSG_warn, "UMAPINFO: Error while reading key\n");
-        return;
-    }
-
-    retval = doom_umi1_ts_value_count(state, &valcount);
-    if (0 > retval || 0 == valcount)
-    {
-        GenPrintf(EMSG_warn, "UMAPINFO: Error while reading value\n");
-        return;
-    }
-
-    switch (key)
-    {
-        case DOOM_UMI1_KEY_AUTHOR:
-            UMI_ReplaceString(state, &entry->author);
-            break;
-        case DOOM_UMI1_KEY_LABEL:
-            UMI_ReplaceStringClear(state, &entry->label);
-            break;
-        case DOOM_UMI1_KEY_LEVELNAME:
-            UMI_ReplaceString(state, &entry->levelname);
-            break;
-        case DOOM_UMI1_KEY_INTERTEXT:
-            UMI_ReplaceMultiStringClear(state, &entry->intertext, valcount);
-            break;
-        case DOOM_UMI1_KEY_INTERTEXTSECRET:
-            UMI_ReplaceMultiStringClear(state,
-                                        &entry->intertextsecret, valcount);
-            break;
-        case DOOM_UMI1_KEY_INTERBACKDROP:
-            UMI_ReplaceStringMax8(state, &entry->interbackdrop);
-            break;
-        case DOOM_UMI1_KEY_INTERMUSIC:
-            UMI_ReplaceStringMax8(state, &entry->intermusic);
-            break;
-        case DOOM_UMI1_KEY_NEXT:
-            UMI_ReplaceStringMax8(state, &entry->nextmap);
-            break;
-        case DOOM_UMI1_KEY_NEXTSECRET:
-            UMI_ReplaceStringMax8(state, &entry->nextsecret);
-            break;
-        case DOOM_UMI1_KEY_MUSIC:
-            UMI_ReplaceStringMax8(state, &entry->music);
-            break;
-        case DOOM_UMI1_KEY_SKYTEXTURE:
-            UMI_ReplaceStringMax8(state, &entry->skytexture);
-            break;
-        case DOOM_UMI1_KEY_LEVELPIC:
-            UMI_ReplaceStringMax8(state, &entry->levelpic);
-            break;
-        case DOOM_UMI1_KEY_EXITPIC:
-            UMI_ReplaceStringMax8(state, &entry->exitpic);
-            break;
-        case DOOM_UMI1_KEY_ENTERPIC:
-            UMI_ReplaceStringMax8(state, &entry->enterpic);
-            break;
-        case DOOM_UMI1_KEY_ENDPIC:
-            UMI_ReplaceStringMax8(state, &entry->endpic);
-            break;
-        case DOOM_UMI1_KEY_EPISODE:
-            // Associated with global episode list (not the map entry object)
-            emc = UMI_AppendEpisodeMenuEntry(state, &umapinfo.emenu, valcount);
-            break;
-        case DOOM_UMI1_KEY_BOSSACTION:
-            if (UMI_MergeBossAction(state, &entry->bossactions, valcount))
-                entry->bossactions_clear = true;
-            break;
-        case DOOM_UMI1_KEY_ENDGAME:
-            entry->endgame = UMI_GetNumber(state) ? enabled : disabled;
-            break;
-        case DOOM_UMI1_KEY_PARTIME:
-            entry->partime = UMI_GetNumber(state);
-            break;
-        case DOOM_UMI1_KEY_NOINTERMISSION:
-            entry->nointermission = UMI_GetNumber(state) ? true : false;
-            break;
-        case DOOM_UMI1_KEY_ENDBUNNY:
-            entry->endbunny = UMI_GetNumber(state) ? true : false;
-            break;
-        case DOOM_UMI1_KEY_ENDCAST:
-            entry->endcast = UMI_GetNumber(state) ? true : false;
-            break;
-        default:
-            GenPrintf(EMSG_warn, "UMAPINFO: Unknown key ignored\n");
-            break;
-    }
-
-    // Store flag that default episode menu must be cleared
-    if (emc)
-       umapinfo.emenu_clear = true;
-}
-
-
-static void UMI_MergeMapEntry(doom_umi1_ts_state state)
-{
-    mapentry_t   *entry   = NULL;
-    unsigned int  episode = 0;
-    unsigned int  map     = 0;
-    int           retval  = doom_umi1_ts_map_read(state, &episode, &map);
-
-    if (0 <= retval)
-        entry = UMI_GetMapEntry(episode, map);
-
-    if (NULL == entry)
-        retval = DOOM_UMI1_ERROR_NOTFOUND;
-    else
-    {
-        size_t keycount = 0;
-
-        retval = doom_umi1_ts_key_count(state, &keycount);
-        while (0 <= retval && keycount)
-        {
-            UMI_StoreKeyData(state, entry);
-
-            if (--keycount)
-                retval = doom_umi1_ts_key_next(state);
-        }
-    }
-
-    if (0 > retval)
-        GenPrintf(EMSG_warn, "UMAPINFO: Error while importing keys\n");
-}
-
-
-static void UMI_ImportUMapInfo(umapinfo_t *umi, doom_umi1_handle data)
-{
-    doom_umi1_ts_state state    = NULL;
-    size_t             mapcount = 0;  // Number of toplevel map entries
-    int                retval   = doom_umi1_ts_state_create(&state, data);
-
-    if (0 <= retval)
-        retval = doom_umi1_ts_map_count(state, &mapcount);
-
-    while (0 <= retval && mapcount)
-    {
-        UMI_MergeMapEntry(state);
-
-        if (--mapcount)
-            retval = doom_umi1_ts_map_next(state);
-    }
-
-    doom_umi1_ts_state_destroy(&state);
-
-    if (0 > retval)
-        GenPrintf(EMSG_warn, "UMAPINFO: Error while importing map entry\n");
-}
-
-
-// -----------------------------------------------------------------------------
-// API
-
-// 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)
-{
-    doom_umi1_handle  data = NULL; // libdoom-umapinfo UMAPINFO object handle
-    int               len  = W_LumpLength(lumpnum);
-
-    assert(0 <= len);
-
-    // libdoom-umapinfo needs a memory manager with realloc() equivalent
-    doom_umi1_register_mmanager(UMI_Realloc, UMI_Free);
-
-    {
-        int            retval  = DOOM_UMI1_ERROR_MEMORY;
-        unsigned char *lump    = UMI_Malloc(len);
-        size_t         length  = len;
-        int            verbose = 0;
-
-        if (NULL != lump)
-        {
-            W_ReadLump(lumpnum, lump);
-            retval = doom_umi1_create(&data, lump, length, verbose);
-            UMI_Free(lump);
-        }
-        if (0 > retval)
-            GenPrintf(EMSG_warn, "UMAPINFO: Parsing data failed\n");
-        else if (0 < retval)
-            GenPrintf(EMSG_warn, "UMAPINFO: Warning: Data may be incomplete\n");
-
-        if (0 <= retval)
-            UMI_ImportUMapInfo(&umapinfo, data);
-
-        doom_umi1_destroy(&data);
-    }
-}
-
-
-void UMI_DestroyUMapInfo(void)
-{
-    UMI_DestroyEpisodeMenu(umapinfo.emenu);
-    umapinfo.emenu       = NULL;
-    umapinfo.emenu_clear = false;
-
-    UMI_DestroyMaps(umapinfo.entry_first);
-    umapinfo.entry_first = NULL;
-}
-
-
-// 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 *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 && 0 < e && 255u >= e && 0 < m && 255u >= m)
-            result = true;
-    }
-
-    if (true == result)
-    {
-        *episode = e;
-        *map     = m;
-    }
-
-    return result;
-}
-
-
-// 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)
-{
-    mapentry_t   *entry = umapinfo.entry_first;
-    unsigned int  e     = episode;
-    unsigned int  m     = map;
-
-    // libdoom-umapinfo uses episode 0 for Doom 2
-    if (doom2_commercial == gamemode)
-        e = 0;
-
-    while (NULL != entry)
-    {
-        // Entries with numbers beyond the range of 'byte' will never match
-        if (entry->episode == e && entry->map == m)
-            break;
-        entry = entry->next;
-    }
-
-    if (NULL != entry)
-        GenPrintf(EMSG_info,
-                  "UMAPINFO: Map entry found for Episode %u, Map %u\n", e, m);
-
-    return entry;
-}
-
-
-// Load UMAPINFO data for current gameepisode/gamemap
-void UMI_Load_LevelInfo(void)
-{
-    gamemapinfo = UMI_LookupUMapInfo(gameepisode, gamemap);
-
-    // SMMU level info is replaced with UMAPINFO data, where possible
-    if (gamemapinfo)
-    {
-        // Key author is handled by WI_Draw_LF() and WI_Draw_EL()
-        // Also mapped to info_creator for COM_MapInfo_f()
-        if (gamemapinfo->author)
-            info_creator = gamemapinfo->author;
-
-        // Keys label and levelname are handled by P_LevelName()
-
-        // Keys intertext and intertextsecret are handled by F_StartFinale()
-
-        // Key interbackdrop is handled by F_StartFinale()
-
-        // Key intermusic is handled by F_StartFinale()
-
-        // Keys nextmap and nextsecret are handled by G_DoUMapInfo()
-
-        // Key music is mapped to info_music
-        if (gamemapinfo->music)
-            info_music = UMI_GetMusicLumpName(gamemapinfo->music);
-
-        // Key skytexture is mapped to info_skyname
-        if (gamemapinfo->skytexture)
-            info_skyname = gamemapinfo->skytexture;
-
-        // Key levelpic is handled by WI_Draw_LF() and WI_Draw_EL()
-
-        // Key exitpic is mapped to info_interpic
-        if (gamemapinfo->exitpic)
-            info_interpic = gamemapinfo->exitpic;
-
-        // Key enterpic is handled by WI_Draw_ShowNextLoc()
-
-        // Key endpic is handled by F_Drawer()
-
-        // Key bossactions is handled by A_Bosstype_Death()
-
-        // Key endgame is handled by G_NextLevel(), WI_Draw_ShowNextLoc(),
-        // F_Ticker() and WI_Draw_ShowNextLoc()
-
-        // Key partime is mapped to info_partime
-        if (gamemapinfo->partime)
-        {
-            if ((unsigned int) INT_MAX < gamemapinfo->partime)
-                info_partime = INT_MAX;
-            else
-                info_partime = gamemapinfo->partime;
-            pars_valid_bex = true;  // Abuse this flag for activation with PWAD
-        }
-
-        // Key nointermission is handled by WI_Start()
-
-        // Key endcast is handled by G_NextLevel, F_Ticker() and
-        // WI_Draw_ShowNextLoc()
-
-        // Key endbunny is handled by G_NextLevel, F_Ticker() and
-        // WI_Draw_ShowNextLoc()
-    }
-}
-
-
-// Strip "d_" prefix from lump name, if present
-// (because the function S_AddMusic() adds a "d_" prefix)
-// Returns a pointer into name
-const char* UMI_GetMusicLumpName(const char* name)
-{
-    if (('d' == name[0] || 'D' == name[0]) && '_' == name[1])
-        return &name[2];
-    else
-        return name;
-}
-
-
-#else  // HAVE_LIBDOOM_UMAPINFO
-
-
-#include "doomincl.h"
-#include "umapinfo.h"
-
-
-umapinfo_t umapinfo = { NULL, NULL, false };
-
-
-// -----------------------------------------------------------------------------
-// API stubs (if libdoom-umapinfo is not available)
-
-void UMI_LoadUMapInfoLump(lumpnum_t lumpnum)
-{
-    GenPrintf(EMSG_warn, "UMAPINFO: Ignored (libdoom-umapinfo is required)\n");
-}
-
-
-void UMI_DestroyUMapInfo(void)
-{
-    return;
-}
-
-
-boolean UMI_ParseMapName(const char *mapname, byte *episode, byte * map)
-{
-    return false;
-}
-
-
-mapentry_t *UMI_LookupUMapInfo(byte episode, byte map)
-{
-    return NULL;
-}
-
-
-void UMI_Load_LevelInfo(void)
-{
-    return;
-}
-
-
-const char* UMI_GetMusicLumpName(const char* name)
-{
-    return name;
-}
-
-#endif  // HAVE_LIBDOOM_UMAPINFO
diff --git a/doomlegacy-devel/files/umapinfo.h b/doomlegacy-devel/files/umapinfo.h
deleted file mode 100644
index 7f0ed9f535..0000000000
--- a/doomlegacy-devel/files/umapinfo.h
+++ /dev/null
@@ -1,122 +0,0 @@
-// -----------------------------------------------------------------------------
-//
-// Copyright(C) 2023 by DooM Legacy Team
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// DESCRIPTION:
-//      Support for additional map information in UMAPINFO format.
-//
-// -----------------------------------------------------------------------------
-
-#ifndef UMAPINFO_H
-#define UMAPINFO_H
-
-#include "doomtype.h"
-
-
-// Entry for episode menu
-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
-};
-
-
-// Usable only for monsters that call A_BossDeath
-typedef struct bossaction_t bossaction_t;
-struct bossaction_t
-{
-    bossaction_t *next;
-
-    unsigned int  thing;    // Thing type (index for table of specification)
-    unsigned int  special;  // Line special type
-    unsigned int  tag;      // Sector tag
-};
-
-
-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;
-
-    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   *exitpic;
-    const char   *enterpic;
-    const char   *endpic;
-    bossaction_t *bossactions;        // Linked list
-    tristate_t    endgame;            // Can be undefined, false or true
-    unsigned int  episode;
-    unsigned int  map;
-    unsigned int  partime;
-    boolean       bossactions_clear;  // Clear all default boss actions
-    boolean       nointermission;     // Skip the 'level finished' screen
-    boolean       endbunny;           // End game after level, show bunny
-    boolean       endcast;            // End game after lavel, show cast call
-};
-
-
-typedef struct umapinfo_t umapinfo_t;
-struct umapinfo_t
-{
-    mapentry_t *entry_first;  // Linked list
-
-    emenu_t    *emenu;        // Linked list
-    boolean     emenu_clear;  // Clear all default episode menu entries
-};
-
-
-extern umapinfo_t umapinfo;
-
-
-void UMI_LoadUMapInfoLump(lumpnum_t lumpnum);
-
-
-void UMI_DestroyUMapInfo(void);
-
-
-boolean UMI_ParseMapName(const char *mapname, byte *episode, byte * map);
-
-
-mapentry_t *UMI_LookupUMapInfo(byte episode, byte map);
-
-
-void UMI_Load_LevelInfo(void);
-
-
-const char* UMI_GetMusicLumpName(const char* name);
-
-
-#endif  // UMAPINFO_H
diff --git a/doomlegacy-devel/patches/patch-make__options__nix b/doomlegacy-devel/patches/patch-make__options__nix
deleted file mode 100644
index 89130aefc8..0000000000
--- a/doomlegacy-devel/patches/patch-make__options__nix
+++ /dev/null
@@ -1,16 +0,0 @@
-$NetBSD$
-
-Add support for libdoom-umapinfo.
-
---- make_options_nix.orig	2023-01-11 14:26:40.000000000 +0000
-+++ make_options_nix
-@@ -79,6 +79,9 @@ HAVE_LIBZIP=1
- # Optional, load with dlopen.
- # HAVE_LIBZIP=3
- 
-+# Support for UMAPINFO lump needs libdoom-umapinfo.
-+HAVE_LIBDOOM_UMAPINFO=1
-+
- # Extended nodes require zlib.
- HAVE_ZLIB=1
- # Optional, load with dlopen.
diff --git a/doomlegacy-devel/patches/patch-src_Makefile b/doomlegacy-devel/patches/patch-src_Makefile
deleted file mode 100644
index edbce0c972..0000000000
--- a/doomlegacy-devel/patches/patch-src_Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-$NetBSD$
-
-Add support for UMAPINFO.
-
---- src/Makefile.orig	2023-01-11 14:26:40.000000000 +0000
-+++ src/Makefile
-@@ -1281,6 +1281,14 @@ ifdef HAVE_ZLIB
-   endif
- endif
- 
-+# LIBDOOM_UMAPINFO
-+ifdef HAVE_LIBDOOM_UMAPINFO
-+  OPTS+=-DHAVE_LIBDOOM_UMAPINFO=$(HAVE_LIBDOOM_UMAPINFO)
-+  ifeq ($(HAVE_LIBDOOM_UMAPINFO), 1)
-+    LIBS+=-ldoom-umapinfo
-+  endif
-+endif
-+
- 
- # compiler and linker flags
- CFLAGS+=$(WFLAGS)
-@@ -1354,7 +1362,8 @@ console.o command.o \
- p_saveg.o \
- tables.o info.o dstrings.o dehacked.o w_wad.o w_zip.o\
- d_netcmd.o d_clisrv.o d_net.o d_netfil.o i_tcp.o \
--d_items.o d_main.o
-+d_items.o d_main.o \
-+umapinfo.o
- 
- # combine all objs ( main, INTERFACE specific, asm, CDMUS )
- OBJS:=$(addprefix $(O)/, $(SMIFOBJS) $(OPTOBJS) $(MOBJS))
diff --git a/doomlegacy-devel/patches/patch-src_d__main.c b/doomlegacy-devel/patches/patch-src_d__main.c
deleted file mode 100644
index fe5fc40cc5..0000000000
--- a/doomlegacy-devel/patches/patch-src_d__main.c
+++ /dev/null
@@ -1,17 +0,0 @@
-$NetBSD$
-
-Add support for UMAPINFO.
-
---- src/d_main.c.orig	2023-03-19 11:31:58.068883902 +0000
-+++ src/d_main.c
-@@ -3570,6 +3570,10 @@ void D_Quit_Save ( quit_severity_e sever
- void I_Quit (void)
- {
-     D_Quit_Save( QUIT_normal );
-+
-+    // [MB] 2023-03-19: Support for UMAPINFO added
-+    UMI_DestroyUMapInfo();
-+
-     I_Quit_System();  // No Return
- }
- 
diff --git a/doomlegacy-devel/patches/patch-src_d__player.h b/doomlegacy-devel/patches/patch-src_d__player.h
deleted file mode 100644
index 3908846199..0000000000
--- a/doomlegacy-devel/patches/patch-src_d__player.h
+++ /dev/null
@@ -1,29 +0,0 @@
-$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
deleted file mode 100644
index e7f0e14be1..0000000000
--- a/doomlegacy-devel/patches/patch-src_doomstat.h
+++ /dev/null
@@ -1,28 +0,0 @@
-$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_f__finale.c b/doomlegacy-devel/patches/patch-src_f__finale.c
deleted file mode 100644
index 508e5daeda..0000000000
--- a/doomlegacy-devel/patches/patch-src_f__finale.c
+++ /dev/null
@@ -1,237 +0,0 @@
-$NetBSD$
-
-Add support for UMAPINFO.
-
---- src/f_finale.c.orig	2023-02-26 17:42:28.000000000 +0000
-+++ src/f_finale.c
-@@ -75,8 +75,8 @@ int             finalecount;
- #define TEXTSPEED       3
- #define TEXTWAIT        250
- 
--char*   finaletext;
--char*   finaleflat;
-+const char*   finaletext;  // [MB] 2023-01-29: Changed to const
-+const char*   finaleflat;  // [MB] 2023-01-29: Changed to const
- static boolean keypressed=false;
- static byte    finale_palette = 0;  // [WDJ] 0 is PLAYPAL
- 
-@@ -84,27 +84,45 @@ void    F_StartCast (void);
- void    F_CastTicker (void);
- boolean F_CastResponder (event_t *ev);
- void    F_CastDrawer (void);
--void    F_Draw_interpic_Name( char * name );
-+// [MB] 2023-02-05: Changed to static and parameter to const for UMAPINFO
-+static void F_Draw_interpic_Name( const char * name );
-+
- 
- //
- // F_StartFinale
- //
--void F_StartFinale (void)
-+void F_StartFinale (boolean secretexit)
- {
-     gamestate = GS_FINALE;
- 
-+    // [MB] 2023-01-29: Provide defaults for flat and text
-+    finaleflat = text[BGFLATE1_NUM];  // Doom E1, FLOOR4_8
-+    finaletext = "";  // Skip text screen
-+
-+    // [MB] 2023-01-29: Support for UMAPINFO added
-+    if(gamemapinfo)
-+    {
-+        if(!secretexit && gamemapinfo->intertext)
-+        {
-+            // An empty string is set for 'clear' identifier
-+            finaletext = gamemapinfo->intertext;
-+            goto beyond_default_setup;
-+        }
-+        else if(secretexit && gamemapinfo->intertextsecret)
-+        {
-+            // An empty string is set for 'clear' identifier
-+            finaletext = gamemapinfo->intertextsecret;
-+            goto beyond_default_setup;
-+        }
-+    }
-+
-     if(info_intertext)
-     {
--      //SoM: Use FS level info intermission.
--      finaletext = info_intertext;
--      if(info_backdrop)
--        finaleflat = info_backdrop;
--      else
--        finaleflat = text[BGFLATE1_NUM]; // Doom E1, FLOOR4_8
--
--      finalestage = 0;
--      finalecount = 0;
--      return;
-+        //SoM: Use FS level info intermission.
-+        finaletext = info_intertext;
-+        if(info_backdrop)
-+            finaleflat = info_backdrop;
-+        goto beyond_default_setup;
-     }
- 
-     // Okay - IWAD dependent stuff.
-@@ -139,7 +157,7 @@ void F_StartFinale (void)
-             finaletext = text[E4TEXT_NUM];
-             break;
-           default:
--            // Ouch.
-+            // [MB] Use defaults
-             break;
-         }
-         break;
-@@ -181,8 +199,8 @@ void F_StartFinale (void)
-               textnum = 5; // text[C6TEXT_NUM];
-               break;
-             default:
--              // Ouch.
--              break;
-+              // [MB] With UMAPINFO game can end after arbitrary level
-+              goto use_defaults;
-           }
-           switch( gamedesc_id )
-           {
-@@ -200,6 +218,7 @@ void F_StartFinale (void)
-              break;
-           }
-           finaletext = text[textnum];
-+use_defaults:
-           break;
-       }
- 
-@@ -248,9 +267,31 @@ void F_StartFinale (void)
-         break;
-     }
- 
-+beyond_default_setup:
-+    // [MB] 2023-01-29: Skip text screen for empty string
-+    if (finaletext[0] == 0)
-+    {
-+        // Fake state when text screen terminates
-+        // Use logic in F_Ticker() to decide what to do next
-+        // FIXME: Screen wipe does not work correctly
-+        finalestage = 0;
-+        finalecount = INT_MAX - 1;
-+        keypressed  = true;
-+        return;
-+    }
-+
-+    // [MB] 2023-01-29: Support for UMAPINFO added
-+    if (gamemapinfo && gamemapinfo->interbackdrop)
-+        finaleflat = gamemapinfo->interbackdrop;
-+    if (gamemapinfo && gamemapinfo->intermusic)
-+    {
-+        const char *mus_umi = UMI_GetMusicLumpName(gamemapinfo->intermusic);
-+
-+        S_ChangeMusicName(mus_umi, true);
-+    }
-+
-     finalestage = 0;
-     finalecount = 0;
--
- }
- 
- 
-@@ -314,7 +355,14 @@ void F_Ticker (void)
-                 {
-                     if (gamemode == doom2_commercial)
-                     {
--                        if (gamemap == 30)
-+                        // [MB] 2023-03-26: Support for UMAPINFO added
-+                        tristate_t endgame = gamemapinfo ? gamemapinfo->endgame
-+                                                         : unchanged;
-+
-+                        if (endgame == enabled
-+                            || (gamemapinfo && gamemapinfo->endcast))
-+                            F_StartCast ();
-+                        else if (gamemap == 30 && endgame != disabled)
-                             F_StartCast ();
-                         else
-                         {
-@@ -328,7 +376,7 @@ void F_Ticker (void)
-                 }
-             }
- 
--            if( gamemode != doom2_commercial)
-+            if( gamemode != doom2_commercial )
-             {
-                 uint32_t  f = finalecount;
-                 if( f >= INT_MAX/2 )
-@@ -339,7 +387,8 @@ void F_Ticker (void)
-                     finalecount = 0;
-                     finalestage = 1;
-                     wipegamestate = GS_FORCEWIPE;             // force a wipe
--                    if (EN_doom_etc && gameepisode == 3)
-+                    if ( (EN_doom_etc && gameepisode == 3)
-+                         || (gamemapinfo && gamemapinfo->endbunny) )
-                         S_StartMusic (mus_bunny);
-                 }
-             }
-@@ -363,7 +412,7 @@ void F_TextWrite (void)
-     // vid : from video setup
-     int         w;
-     int         count;
--    char*       ch;
-+    const char* ch;  // [MB] 2023-01-29: Changed to const
-     int         c;
-     int         cx, cy;
- 
-@@ -840,7 +889,8 @@ credit_page:
- 
- 
- // Called from F_Drawer, to draw full screen
--void F_Draw_interpic_Name( char * name )
-+// [MB] 2023-02-05: Changed to static and parameter to const for UMAPINFO
-+static void F_Draw_interpic_Name( const char * name )
- {
-    patch_t*  pic = W_CachePatchName( name, PU_CACHE );  // endian fix
-    // Intercept some doom pictures that chex.wad left in (a young kids game).
-@@ -858,14 +908,18 @@ void F_Drawer (void)
-     // Draw to screen0, scaled
-     V_SetupDraw( 0 | V_SCALESTART | V_SCALEPATCH | V_CENTERHORZ );
- 
--    if (finalestage == 2)
-+    if( finalestage == 2 )
-     {
--        F_CastDrawer ();
-+        F_CastDrawer();
-         return;
-     }
- 
--    if (!finalestage)
--        F_TextWrite ();
-+    if( !finalestage )
-+    {
-+        // [MB] 2023-03-29: Skip for empty string
-+        if( finaletext[0] )
-+            F_TextWrite();
-+    }
-     else
-     {
-         if( gamemode == heretic )
-@@ -874,10 +928,15 @@ void F_Drawer (void)
-         }
-         else
-         {
--           switch (gameepisode)
-+           // [MB] 2023-03-29: Support for UMAPINFO added
-+           if( gamemapinfo && gamemapinfo->endbunny )
-+               F_BunnyScroll();
-+           else if( gamemapinfo && gamemapinfo->endpic )
-+               F_Draw_interpic_Name( gamemapinfo->endpic );
-+           else switch( gameepisode )
-            {
-             case 1:
--              if ( gamemode == ultdoom_retail || gamemode == chexquest1 )
-+              if( gamemode == ultdoom_retail || gamemode == chexquest1 )
-                 F_Draw_interpic_Name( text[CREDIT_NUM] );
-               else
-                 F_Draw_interpic_Name( text[HELP2_NUM] );
-@@ -894,5 +953,4 @@ void F_Drawer (void)
-            }
-         }
-     }
--
- }
diff --git a/doomlegacy-devel/patches/patch-src_f__finale.h b/doomlegacy-devel/patches/patch-src_f__finale.h
deleted file mode 100644
index 6974aa101e..0000000000
--- a/doomlegacy-devel/patches/patch-src_f__finale.h
+++ /dev/null
@@ -1,16 +0,0 @@
-$NetBSD$
-
-Add support for UMAPINFO.
-
---- src/f_finale.h.orig	2023-01-10 10:38:38.000000000 +0000
-+++ src/f_finale.h
-@@ -48,7 +48,8 @@ void F_Ticker (void);
- void F_Drawer (void);
- 
- 
--void F_StartFinale (void);
-+// 2023-02-04: Added parameter for UMAPINFO support
-+void F_StartFinale (boolean secretexit);
- 
- 
- #endif
diff --git a/doomlegacy-devel/patches/patch-src_g__game.c b/doomlegacy-devel/patches/patch-src_g__game.c
deleted file mode 100644
index 958e5c4383..0000000000
--- a/doomlegacy-devel/patches/patch-src_g__game.c
+++ /dev/null
@@ -1,229 +0,0 @@
-$NetBSD$
-
-Add support for UMAPINFO.
-
---- src/g_game.c.orig	2023-02-26 17:42:09.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,91 @@ 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.lev_next    = wminfo.lev_prev + 1;
-+    wminfo.lastmapinfo = gamemapinfo;
-+    wminfo.nextmapinfo = NULL;
-+
-+    if (gamemapinfo)
-+    {
-+        const char *mapname = NULL;
-+        int         i = 0;
-+
-+        // Keys nextmap and nextsecret overrides default setup
-+        if (secretexit && gamemapinfo->nextsecret)
-+        {
-+            mapname = gamemapinfo->nextsecret;
-+            for (i = 0; MAXPLAYERS > i; ++i)
-+                players[i].didsecret = true;
-+        }
-+        else if (gamemapinfo->nextmap)
-+            mapname = gamemapinfo->nextmap;
-+
-+        if (mapname)
-+        {
-+            result = true;  // UMAPINFO overrides default setup
-+
-+            {
-+                byte e = 0;
-+                byte m = 0;
-+
-+                UMI_ParseMapName(mapname, &e, &m);
-+                wminfo.epsd_next = e;
-+                wminfo.lev_next = m;
-+                GenPrintf(EMSG_info, "UMAPINFO: Go to Episode %d, Map %d\n",
-+                          wminfo.epsd_next, wminfo.lev_next);
-+            }
-+            wminfo.epsd_next--;
-+            wminfo.lev_next--;
-+
-+            if (wminfo.epsd_next != wminfo.epsd)
-+            {
-+                // Jump to different episode
-+                for (i = 0; MAXPLAYERS > i; ++i)
-+                    players[i].didsecret = false;
-+            }
-+        }
-+
-+        // Explicitly check for endgame too
-+        // UMAPINFO may contain nonsense (example from 2022ado.wad map E5M8):
-+        //     next    = "E5M8"
-+        //     endgame = true
-+        // Give endgame priority (and do not skip default setup) in such cases
-+        if ( result == true && (gamemapinfo->endgame == enabled ||
-+             gamemapinfo->endbunny || gamemapinfo->endcast) )
-+        {
-+            result = false;
-+        }
-+    }
-+
-+    return result;
-+}
-+
-+
- void G_Start_Intermission( void )
- {
-     int  i;
- 
-+    // [MB] 2023-01-22: Moved to beginning for G_DoUMapInfo()
-+    // 0 based
-+    wminfo.epsd     = gameepisode - 1;
-+    wminfo.lev_prev = gamemap - 1;
-+
-+    // [MB] 2023-01-22: Support for UMAPINFO added
-+    {
-+        boolean skip = G_DoUMapInfo();
-+
-+        if (skip)
-+            goto beyond_default_setup;
-+    }
-+
-     if (gamemode != doom2_commercial)
-     {
-         switch(gamemap)
-@@ -2401,7 +2483,7 @@ void G_Start_Intermission( void )
-                 // also for heretic
-                 // disconnect from network
-                 CL_Reset();
--                F_StartFinale();
-+                F_StartFinale(secretexit);  // [MB] 2023-03-04: Parameter added
-                 return;
-             }
-             break; // [WDJ] 4/11/2012  map 8 is not secret level, and prboom and boom do not fall thru here.
-@@ -2421,7 +2503,7 @@ void G_Start_Intermission( void )
-             else
-             {
-                 CL_Reset();
--                F_StartFinale();
-+                F_StartFinale(secretexit);  // [MB] 2023-03-04: Parameter added
-                 return;
-             }
-         }
-@@ -2429,14 +2511,11 @@ void G_Start_Intermission( void )
- 
-     if(!dedicated)
-         wminfo.didsecret = consoleplayer_ptr->didsecret;
--    // 0 based
--    wminfo.epsd = gameepisode -1;
--    wminfo.lev_prev = gamemap -1;
- 
-     // 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 +2569,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 && 255u >= e && 0 < m && 255u >= m)
-+        {
-+            byte epsd = e;
-+            byte map  = m;
-+
-+            wminfo.nextmapinfo = UMI_LookupUMapInfo(epsd, map);
-+        }
-+    }
- 
-     wminfo.maxkills = totalkills;
-     wminfo.maxitems = totalitems;
-@@ -2535,7 +2629,31 @@ void G_NextLevel (void)
-     if (secretexit)
-         consoleplayer_ptr->didsecret = true;
- 
--    if ( gamemode == doom2_commercial)
-+    // [MB] 2023-04-01: Support for UMAPINFO added
-+    if( gamemapinfo )
-+    {
-+        boolean finished = false;
-+
-+        if( gamemapinfo->endbunny )
-+            finished = true;
-+        if( gamemapinfo->endcast )
-+            finished = true;
-+        if( gamemapinfo->endgame != unchanged )
-+        {
-+            if( gamemapinfo->endgame == enabled )
-+                finished = true;
-+            // Do nothing for 'disabled'
-+        }
-+
-+        if (finished)
-+        {
-+            CL_Reset (); // end of game disconnect from server
-+            gameaction = ga_nothing;
-+            F_StartFinale (secretexit);  // [MB] 2023-03-04: Parameter added
-+        }
-+    }
-+
-+    if ( gamemode == doom2_commercial )
-     {
-         if( deathmatch )
-         {
-@@ -2555,9 +2673,9 @@ void G_NextLevel (void)
-             case 20:
-             case 30:
-                 if( gamemap == 30 )
--                    CL_Reset(); // end of game disconnect from server
-+                    CL_Reset (); // end of game disconnect from server
-                 gameaction = ga_nothing;
--                F_StartFinale ();
-+                F_StartFinale (secretexit);  // [MB] 2023-03-04: Parameter added
-                 break;
-             }
-         }
-@@ -2574,17 +2692,19 @@ void G_DoWorldDone (void)
-     else
-     {
-         // not in demo because demo have the mapcommand on it
-+        // [MB] 2023-03-26: Replaced gameepisode with wminfo.epsd_next+1
-+        //                  Crossing episodes is possible with UMAPINFO
-         if(server && !demoplayback) 
-         {
-             if( ! deathmatch )
-             {
-                 // don't reset player between maps
--                COM_BufAddText (va("map \"%s\" -noresetplayers\n",G_BuildMapName(gameepisode, wminfo.lev_next+1)));
-+                COM_BufAddText (va("map \"%s\" -noresetplayers\n",G_BuildMapName(wminfo.epsd_next+1, wminfo.lev_next+1)));
-             }
-             else
-             {
-                 // resetplayer in deathmatch for more equality
--                COM_BufAddText (va("map \"%s\"\n",G_BuildMapName(gameepisode, wminfo.lev_next+1)));
-+                COM_BufAddText (va("map \"%s\"\n",G_BuildMapName(wminfo.epsd_next+1, wminfo.lev_next+1)));
-             }
-         }
-     }
diff --git a/doomlegacy-devel/patches/patch-src_m__menu.c b/doomlegacy-devel/patches/patch-src_m__menu.c
deleted file mode 100644
index 99a0975986..0000000000
--- a/doomlegacy-devel/patches/patch-src_m__menu.c
+++ /dev/null
@@ -1,105 +0,0 @@
-$NetBSD$
-
-Add support for UMAPINFO.
-
---- src/m_menu.c.orig	2023-02-10 15:50:57.000000000 +0000
-+++ src/m_menu.c
-@@ -6300,6 +6300,88 @@ void M_Init (void)
-     CV_RegisterVar(&cv_oof_2s);
- }
- 
-+
-+// [MB] 2023-03-23: Modify episode menu with data from UMAPINFO
-+// If clear is false, the new entries are appended to the existing menu
-+static void M_EpisodeMenuFromUMAPINFO (void)
-+{
-+    boolean   modified = false;
-+    emenu_t * episode  = umapinfo.emenu;
-+
-+    // Accept clear only for the first UMAPINFO map entry
-+    if( umapinfo.emenu_clear )
-+    {
-+        modified        = true;
-+        EpiDef.numitems = 0;
-+        GenPrintf(EMSG_debug, "UMAPINFO: Default episode menu cleared\n");
-+    }
-+
-+    while( episode )
-+    {
-+        // UMAPINFO allows 8 episodes, currently only 5 are supported
-+        if( EpiDef.numitems < 5 )
-+        {
-+            // EpisodeMenu[EpiDef.numitems].status is below
-+            // FIXME: Cast to char* is ugly
-+            // Is it possible to declared elements const in menuitem_t?
-+            EpisodeMenu[EpiDef.numitems].patch = (char*)episode->patch;
-+            EpisodeMenu[EpiDef.numitems].text  = (char*)episode->name;
-+            // EpisodeMenu[EpiDef.numitems].itemaction is not changed
-+            if( episode->key[0] )
-+            {
-+                // UMAPINFO value is defined as quoted string
-+                // The first character is used, if string is not empty
-+                byte k = (byte)episode->key[0];
-+
-+                EpisodeMenu[EpiDef.numitems].alphaKey = k;
-+            }
-+            EpiDef.numitems++;
-+            GenPrintf(EMSG_debug, "UMAPINFO: Episode entry added\n");
-+        }
-+        modified = true;
-+        episode  = episode->next;
-+    }
-+
-+    // Use patches only if all episodes have a valid patch
-+    if( modified )
-+    {
-+        boolean  use_patches = true;
-+        uint16_t i;
-+
-+        // FIXME: This should check if patches are really usable
-+        for( i = 0; i < EpiDef.numitems; i++ )
-+        {
-+            if( EpisodeMenu[i].patch == NULL || EpisodeMenu[i].patch[0] == 0 )
-+            {
-+                use_patches = false;
-+                break;
-+            }
-+        }
-+
-+        GenPrintf(EMSG_debug, "UMAPINFO: Modified episode menu ");
-+        if( use_patches )
-+            GenPrintf(EMSG_debug, "(using patches):\n");
-+        else
-+            GenPrintf(EMSG_debug, "(using strings):\n");
-+
-+        for( i = 0; i < EpiDef.numitems; i++ )
-+        {
-+            GenPrintf(EMSG_debug, "    Episode %u: ", (unsigned int) i + 1u);
-+            if( use_patches )
-+                GenPrintf(EMSG_debug, "%s\n", EpisodeMenu[i].patch);
-+            else
-+                GenPrintf(EMSG_debug, "%s\n", EpisodeMenu[i].text);
-+
-+            EpisodeMenu[i].status = IT_CALL;
-+            if( use_patches )
-+                EpisodeMenu[i].status |= IT_PATCH;
-+            else
-+                EpisodeMenu[i].status |= IT_STRING2;
-+        }
-+    }
-+}
-+
-+
- // Called once after gamemode has been determined, game dependent
- void M_Configure (void)
- {
-@@ -6382,6 +6464,9 @@ void M_Configure (void)
-           cv_nextmap.defaultvalue = "11";
-           // We need to remove the fifth episode.
-           EpiDef.numitems--;
-+
-+          // [MB] 2023-03-23: Support for UMAPINFO added
-+          M_EpisodeMenuFromUMAPINFO();
-           break;
-       case heretic:
-           cv_nextmap.PossibleValue = exmy_cons_t;
diff --git a/doomlegacy-devel/patches/patch-src_p__enemy.c b/doomlegacy-devel/patches/patch-src_p__enemy.c
deleted file mode 100644
index 2544544667..0000000000
--- a/doomlegacy-devel/patches/patch-src_p__enemy.c
+++ /dev/null
@@ -1,203 +0,0 @@
-$NetBSD$
-
-Add support for UMAPINFO.
-
---- src/p_enemy.c.orig	2023-02-26 17:42:27.000000000 +0000
-+++ src/p_enemy.c
-@@ -3401,6 +3401,66 @@ static state_t *P_FinalState(statenum_t
-     return &states[state];
- }
- 
-+// [MB] 2023-03-19: Support for UMAPINFO added
-+// Helper function for A_Bosstype_Death(), code is now used more than once
-+// Returns false if no player is alive
-+static boolean A_Player_Alive(void)
-+{
-+    boolean alive = true;
-+    int     i;
-+
-+    for( i = 0 ; i < MAXPLAYERS ; i++ )
-+        if( playeringame[i] && players[i].health > 0 )
-+            break;
-+
-+    if (i == MAXPLAYERS)
-+        alive = false;
-+
-+    return alive;
-+}
-+
-+// [MB] 2023-03-19: Support for UMAPINFO added
-+// Helper function for A_Bosstype_Death(), code is now used more than once
-+// Parameters are forwarded from A_Bosstype_Death().
-+// Returns true if all other bosses (of same type as in parameter mo) are dead
-+static boolean A_All_Bosses_Dead(mobj_t* mo, int boss_type)
-+{
-+    boolean     dead = true;
-+    thinker_t*  th;
-+    mobj_t*     mo2;
-+
-+    for( th = thinkercap.next ; th != &thinkercap ; th = th->next )
-+    {
-+        if( th->function.acp1 != (actionf_p1)P_MobjThinker )
-+            continue;
-+
-+        // Fixes MAP07 bug where if last arachnotron is killed while first
-+        // still in death sequence, then both would trigger this code
-+        // and the floor would be raised twice (bad).
-+        mo2 = (mobj_t *)th;
-+        // Check all boss of the same type
-+        if ( mo2 != mo
-+             && mo2->type == boss_type )
-+        {
-+            // Check if really dead and finished the death sequence.
-+            // [WDJ] Corpse has health < 0.
-+            // If two monsters are killed at the same time, this test may occur
-+            // while first is corpse and second is not.  But the simple health
-+            // test may trigger twice because second monster already has
-+            // health < 0 during the first death test.
-+            if( mo2->health > 0  // the old test (doom original 1.9)
-+                || !(mo2->flags & MF_CORPSE)
-+                || mo2->state != P_FinalState(mo2->info->deathstate) )
-+            {
-+                // other boss not dead
-+                dead = false;
-+            }
-+        }
-+    }
-+
-+    return dead;
-+}
-+
- //
- // A_BossDeath
- // Possibly trigger special effects
-@@ -3412,13 +3472,74 @@ static state_t *P_FinalState(statenum_t
- // [WDJ]  Keen death does not have tests for mo->type and thus allows
- // Dehacked monsters to trigger Keen death and BossDeath effects.
- // Should duplicate that ability in Doom maps.
--void A_Bosstype_Death (mobj_t* mo, int boss_type)
-+static void A_Bosstype_Death (mobj_t* mo, int boss_type)
- {
--    thinker_t*  th;
--    mobj_t*     mo2;
--    line_t      lineop;  // operation performed when all bosses are dead.
--    int         i;
--   
-+    line_t lineop;  // operation performed when all bosses are dead.
-+
-+    // [MB] 2023-03-19: Support for UMAPINFO added
-+    GenPrintf(EMSG_debug, "Boss died (Type: %d)\n", boss_type);
-+    if( gamemapinfo && gamemapinfo->bossactions )
-+    {
-+        struct bossaction_t* umi_ba = gamemapinfo->bossactions;
-+
-+        if( ! A_Player_Alive() )
-+            return;
-+
-+        if( ! A_All_Bosses_Dead(mo, boss_type) )
-+            return;
-+
-+        do
-+        {
-+            if( boss_type >= 0 && (unsigned int)boss_type == umi_ba->thing)
-+            {
-+                GenPrintf(EMSG_debug, "UMAPINFO: Matching bossaction found\n");
-+                GenPrintf(EMSG_debug, "UMAPINFO: (Line: %u, Tag: %u)\n",
-+                          umi_ba->special, umi_ba->tag);
-+
-+                // FIXME: Is this sufficient for the xxxSpecialLine() functions?
-+                memset(&lineop, 0, sizeof(line_t));
-+                if (umi_ba->special > (unsigned int)SHRT_MAX)
-+                    continue;
-+                lineop.special = (short)umi_ba->special;
-+                if (umi_ba->tag > (unsigned int)UINT16_MAX)
-+                    continue;
-+                lineop.tag = (uint16_t)umi_ba->tag;
-+
-+                // Try to use the line first, cross it if not successful
-+                {
-+                    // Prepare fake player (as modified copy of boss map object)
-+                    mobj_t fake_player_mo = *mo;
-+
-+                    fake_player_mo.type   = MT_PLAYER;
-+                    fake_player_mo.player = &players[0];
-+
-+#if 0
-+                    // Does not return false, if there is nothing to use
-+                    if( ! P_UseSpecialLine(&fake_player_mo, &lineop, 0) )
-+                    {
-+                        GenPrintf(EMSG_debug, "UMAPINFO: Cross special line\n");
-+                        P_CrossSpecialLine(&lineop, 0, &fake_player_mo);
-+                    }
-+#else
-+                    // Workaround (do both unconditionally)
-+                    (void)P_UseSpecialLine(&fake_player_mo, &lineop, 0);
-+                    P_CrossSpecialLine(&lineop, 0, &fake_player_mo);
-+#endif
-+                }
-+            }
-+            umi_ba = umi_ba->next;
-+        }
-+        while( umi_ba );
-+        return;
-+    }
-+
-+    if( gamemapinfo && gamemapinfo->bossactions_clear )
-+    {
-+        // Default handling explicitly cleared by UMAPINFO
-+        return;
-+    }
-+
-+    // [MB] Default handling starts here
-     if ( gamemode == doom2_commercial)
-     {
-         // Doom2 MAP07: When last Mancubus is dead,
-@@ -3515,45 +3636,14 @@ void A_Bosstype_Death (mobj_t* mo, int b
- 
-     }
- 
--
-     // make sure there is a player alive for victory
--    for (i=0 ; i<MAXPLAYERS ; i++)
--        if (playeringame[i] && players[i].health > 0)
--            break;
--
--    if (i==MAXPLAYERS)
-+    if( ! A_Player_Alive() )
-         return; // no one left alive, so do not end game
- 
-     // scan the remaining thinkers to see
-     // if all bosses are dead
--    for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
--    {
--        if (th->function.acp1 != (actionf_p1)P_MobjThinker)
--            continue;
--
--        // Fixes MAP07 bug where if last arachnotron is killed while first
--        // still in death sequence, then both would trigger this code
--        // and the floor would be raised twice (bad).
--        mo2 = (mobj_t *)th;
--        // Check all boss of the same type
--        if ( mo2 != mo
--            && mo2->type == boss_type )
--        {
--            // Check if really dead and finished the death sequence.
--            // [WDJ] Corpse has health < 0.
--            // If two monsters are killed at the same time, this test may occur
--            // while first is corpse and second is not.  But the simple health
--            // test may trigger twice because second monster already has
--            // health < 0 during the first death test.
--            if( mo2->health > 0  // the old test (doom original 1.9)
--                || !(mo2->flags & MF_CORPSE)
--                || mo2->state != P_FinalState(mo2->info->deathstate) )
--            {
--                // other boss not dead
--                goto no_action;
--            }
--        }
--    }
-+    if( ! A_All_Bosses_Dead(mo, boss_type) )
-+        goto no_action;
- 
-     // victory!
-     if ( gamemode == doom2_commercial)
diff --git a/doomlegacy-devel/patches/patch-src_p__info.c b/doomlegacy-devel/patches/patch-src_p__info.c
deleted file mode 100644
index cf78581a3d..0000000000
--- a/doomlegacy-devel/patches/patch-src_p__info.c
+++ /dev/null
@@ -1,142 +0,0 @@
-$NetBSD$
-
-Add support for UMAPINFO.
-
---- src/p_info.c.orig	2023-02-26 17:42:27.000000000 +0000
-+++ src/p_info.c
-@@ -79,6 +79,9 @@
- #include "z_zone.h"
- #include "p_local.h"
- 
-+// [MB] 2023-03-12: Size of static buffers used for names of levels, etc.
-+#define NAME_BUFSIZE  50
-+
- //----------------------------------------------------------------------------
- //
- // Helper functions
-@@ -150,13 +153,15 @@ static void P_RemoveEqualses(char *line)
- //  '=' sign is optional: all equals signs are internally turned to spaces
- //
- 
--char *info_interpic;
-+// [MB] 2023-01-22: Changed to const (used for UMAPINFO too)
-+const char *info_creator;
-+const char *info_music;
-+const char *info_skyname;
-+const char *info_interpic;
-+const char *info_levelpic;
-+
- char *info_levelname;
- int info_partime;
--char *info_music;
--char *info_skyname;
--char *info_creator;
--char *info_levelpic;
- char *info_nextlevel;
- char *info_nextsecret;
- char *info_intertext = NULL;
-@@ -295,7 +300,10 @@ not_map:
- 
- void P_Clear_LevelVars(void)
- {
--  info_levelname = info_skyname = info_levelpic = info_interpic = "";
-+  info_levelname = "";
-+  info_skyname = "";
-+  info_levelpic = "";
-+  info_interpic = "";
-   info_music = "";
-   info_creator = "unknown";
-   info_partime = -1;
-@@ -673,7 +681,8 @@ void P_Load_LevelInfo( void )
- 
- void COM_MapInfo_f(void)
- {
--  CONS_Printf("Name: %s\n", levelname);
-+  // [MB] 2023-02-04: Call P_LevelName() to catch levelname from UMAPINFO
-+  CONS_Printf("Name: %s\n", P_LevelName());
-   CONS_Printf("Author: %s\n", info_creator);
- }
- 
-@@ -684,12 +693,81 @@ void P_Register_Info_Commands(void)
- }
- 
- 
-+// [MB] 2023-03-12: Get label (prefix) for UMAPINFO levelname
-+// Helper function for P_LevelName()
-+//
-+// Returns the length of the label, even if larger than buffer size
-+// (but does not write beyond end of buffer).
-+static size_t P_LevelName_GetLabel(char * buffer, size_t size)
-+{
-+    size_t len_label = 0;
-+
-+    if (size > 0)
-+    {
-+        int len = -1;
-+
-+        if(gamemapinfo && gamemapinfo->label)
-+        {
-+            // Empty string, if "clear" was specified in UMAPINFO
-+            const char * label = gamemapinfo->label;
-+
-+            len = snprintf(buffer, size, "%s", label);
-+        }
-+        else
-+        {
-+            // Quoted from UMAPINFO specification Rev 2.2 definition of map
-+            // entry:
-+            // The [episode and map] numbers [...] can exceed their original
-+            // limits, though, so MAP50, E5M6 or even MAP100 or E1M10 are valid
-+            // map names for their respective game.
-+            //
-+            // Quoted from UMAPINFO specification Rev 2.2 definition of label:
-+            // If not specified the mapname will be used by default followed by
-+            // a colon and a space character (e.g. "E1M1: ").
-+            unsigned char e = gameepisode;
-+            unsigned char m = gamemap;
-+
-+            if(gamemode == doom2_commercial)
-+                len = snprintf(buffer, size, "level %u: ", m);
-+            else
-+                len = snprintf(buffer, size, "E%uM%u: ", e, m);
-+
-+        }
-+
-+        if(len > 0)
-+           len_label = len;
-+    }
-+
-+    return len_label;
-+}
-+
- 
- char * P_LevelName(void)
- {
--  return levelname;
-+    // [MB] 2023-01-22: Support for UMAPINFO added
-+    if(gamemapinfo && gamemapinfo->levelname)
-+    {
-+        static char  newlevelstr[NAME_BUFSIZE];
-+        size_t       remaining = NAME_BUFSIZE - 1;  // -1 for NUL-termination
-+
-+        size_t len_label = P_LevelName_GetLabel(newlevelstr, NAME_BUFSIZE);
-+        size_t len_level = strlen(gamemapinfo->levelname);
-+
-+        if(len_label > remaining)
-+            len_label = remaining;
-+        remaining -= len_label;
-+        if(len_level > remaining)
-+            len_level = remaining;
-+
-+        memcpy(&newlevelstr[len_label], gamemapinfo->levelname, len_level);
-+        newlevelstr[len_label + len_level] = 0;
-+        return newlevelstr;
-+    }
-+    else
-+        return levelname;
- }
- 
-+
- // todo : make this use mapinfo lump
- // Called by WI_Draw_EL "Entering <LevelName>"
- // Called by IN_Draw_YAH "NOW ENTERING"
diff --git a/doomlegacy-devel/patches/patch-src_p__info.h b/doomlegacy-devel/patches/patch-src_p__info.h
deleted file mode 100644
index 6d1a9704cd..0000000000
--- a/doomlegacy-devel/patches/patch-src_p__info.h
+++ /dev/null
@@ -1,28 +0,0 @@
-$NetBSD$
-
-Add support for UMAPINFO.
-
---- src/p_info.h.orig	2023-01-10 10:38:38.000000000 +0000
-+++ src/p_info.h
-@@ -50,14 +50,16 @@ void P_Load_LevelInfo(void);
- 
- void P_CleanLine(char *line);
- 
--extern char *info_interpic;
-+// [MB] 2023-01-22: Changed to const (used for UMAPINFO too)
-+extern const char *info_creator;
-+extern const char *info_music;
-+extern const char *info_skyname;
-+extern const char *info_interpic;
-+extern const char *info_levelpic;
-+
- extern char *info_levelname;
--extern char *info_levelpic;
--extern char *info_music;
- extern int info_partime;
- extern char *info_levelcmd[128];
--extern char *info_skyname;
--extern char *info_creator;
- extern char *info_nextlevel;
- extern char *info_nextsecret;
- extern char *info_intertext;
diff --git a/doomlegacy-devel/patches/patch-src_p__setup.c b/doomlegacy-devel/patches/patch-src_p__setup.c
deleted file mode 100644
index 1fc1ab4e1a..0000000000
--- a/doomlegacy-devel/patches/patch-src_p__setup.c
+++ /dev/null
@@ -1,24 +0,0 @@
-$NetBSD$
-
-Add support for UMAPINFO.
-
---- src/p_setup.c.orig	2023-01-10 10:38:38.000000000 +0000
-+++ src/p_setup.c
-@@ -2087,7 +2087,7 @@ fail:
- // The sky texture to be used instead of the F_SKY1 dummy.
- void P_Setup_LevelSky (void)
- {
--    char * sn = "SKY1";
-+    const char * sn = "SKY1";
-     char   skytexname[12];
- 
-     // DOOM determines the sky texture to be used
-@@ -2282,6 +2282,8 @@ boolean P_SetupLevel (int      to_episod
-     // Dependent upon level_mapname, level_lumpnum.
-     P_Load_LevelInfo();
- #endif
-+    // [MB] 2023-01-22: Support for UMAPINFO added
-+    UMI_Load_LevelInfo();
- 
-     //SoM: We've loaded the music lump, start the music.
-     S_Start_LevelSound();
diff --git a/doomlegacy-devel/patches/patch-src_w__wad.c b/doomlegacy-devel/patches/patch-src_w__wad.c
deleted file mode 100644
index 16af1fb5d0..0000000000
--- a/doomlegacy-devel/patches/patch-src_w__wad.c
+++ /dev/null
@@ -1,55 +0,0 @@
-$NetBSD$
-
-Add support for UMAPINFO.
-
---- src/w_wad.c.orig	2023-02-10 15:51:01.000000000 +0000
-+++ src/w_wad.c
-@@ -109,6 +109,9 @@
- #include <unistd.h>
-   // close, read, lseek
- 
-+// [MB] 2023-03-19: Support for UMAPINFO added
-+#include "doomstat.h"
-+
- #include "doomincl.h"
- #include "w_wad.h"
- #include "z_zone.h"
-@@ -589,6 +592,12 @@ int W_Load_WadFile ( const char * filena
- 
-     GenPrintf(EMSG_info, "Added file %s (%i lumps)\n", filenamebuf, numlumps);
-     W_Load_DehackedLumps( filenum );
-+    // [MB] 2023-01-10: Process UMAPINFO last for highest priority
-+    if ( EN_doom_etc )
-+    {
-+        // UMAPINFO is for Doom only (not suitable for Heretic and Hexen)
-+        W_Load_UMapInfoLumps( filenum );
-+    }
- 
-     return filenum;
- 
-@@ -1378,6 +1387,25 @@ void W_Load_DehackedLumps( int wadnum )
-     }
- }
- 
-+
-+// [MB] 2023-01-10: Search for all UMAPINFO lumps in all wads and load them
-+void W_Load_UMapInfoLumps( int wadnum )
-+{
-+    lumpnum_t  clump = 0;
-+
-+    while (1)
-+    {
-+        clump = W_CheckNumForNamePwad("UMAPINFO", wadnum, LUMPNUM(clump));
-+        if( ! VALID_LUMP(clump) )
-+            break;
-+        GenPrintf(EMSG_info, "Loading UMAPINFO from %s\n",
-+                  wadfiles[wadnum]->filename);
-+        UMI_LoadUMapInfoLump(clump);
-+        clump++;
-+    }
-+}
-+
-+
- // [WDJ] Return a sum unique to a lump, to detect replacements.
- // The lumpptr must be to a Z_Malloc lump.
- uint64_t  W_lump_checksum( void* lumpptr )
diff --git a/doomlegacy-devel/patches/patch-src_w__wad.h b/doomlegacy-devel/patches/patch-src_w__wad.h
deleted file mode 100644
index 8ce0e32fad..0000000000
--- a/doomlegacy-devel/patches/patch-src_w__wad.h
+++ /dev/null
@@ -1,17 +0,0 @@
-$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 );
- 
- 
- 
diff --git a/doomlegacy-devel/patches/patch-src_wi__stuff.c b/doomlegacy-devel/patches/patch-src_wi__stuff.c
deleted file mode 100644
index 4ed7156532..0000000000
--- a/doomlegacy-devel/patches/patch-src_wi__stuff.c
+++ /dev/null
@@ -1,312 +0,0 @@
-$NetBSD$
-
-Add support for UMAPINFO.
-
---- src/wi_stuff.c.orig	2023-02-26 17:42:27.000000000 +0000
-+++ src/wi_stuff.c
-@@ -481,6 +481,28 @@ void detect_range_violation( int item, i
- // CODE
- //
- 
-+
-+// [MB] 2023-03-19: Support for UMAPINFO added
-+// Moved out of WI_Load_Data() into separate function because with UMAPINFO
-+// the LF and EL screens can use different background pictures.
-+static void WI_Prepare_Background(void)
-+{
-+    // Prepare new background from bgname for software renderer
-+    if (rendermode == render_soft)
-+    {
-+        memset(screens[0], 0, vid.screen_size);
-+
-+        // clear backbuffer from status bar stuff and borders
-+        memset(screens[1], 0, vid.screen_size);
-+
-+        // Draw background on screen1
-+        V_SetupDraw(1 | V_SCALESTART | V_SCALEPATCH | V_CENTERHORZ); // screen 1
-+        V_DrawScaledPatch(0, 0, W_CachePatchName(bgname, PU_CACHE));
-+        V_SetupDraw(drawinfo.prev_screenflags);  // restore
-+    }
-+}
-+
-+
- // slam background
- // UNUSED static unsigned char *background=0;
- 
-@@ -523,25 +545,79 @@ static void WI_Draw_LF(void)
- {
-     // Hardware or software render.
-     patch_t * pp, * pf;
-+    int x = 0;
-     int y = WI_TITLEY;
- 
--    // draw <LevelName>
--    if( FontBBaseLump )
-+    // [MB] 2023-03-12: Support for UMAPINFO added
-+    //
-+    // Quoted from UMAPINFO specification Rev 2.2 definition of levelpic:
-+    // Specifies the patch that is used on the status screen for 'entering' and
-+    // 'finished'. [...]
-+    // If not given, the status screen will instead print the map's name with a
-+    // suitable font (PrBoom uses STFxxx) to ensure that the proper name is
-+    // used. If the author field is set, it will also be shown.
-+    if (wbs->lastmapinfo && wbs->lastmapinfo->levelpic)
-     {
--        V_DrawTextB(P_LevelName(), (BASEVIDWIDTH - V_TextBWidth(P_LevelName()))/2, y);
--        y += (5*V_TextBHeight(P_LevelName()))/4;
--        V_DrawTextB("Finished", (BASEVIDWIDTH - V_TextBWidth("Finished"))/2, y);
-+        pp = W_CachePatchName(wbs->lastmapinfo->levelpic, PU_CACHE);
-+        pf = V_patch(pp);  // access patch fields
-+        x = (BASEVIDWIDTH - pf->width) / 2;
-+        V_DrawScaledPatch(x, y, pp);
-+
-+        y += (5 * pf->height) / 4;
-+
-+        x = (BASEVIDWIDTH - (V_patch(finished)->width)) / 2;
-+        V_DrawScaledPatch(x, y, finished);
-     }
-+    else if (wbs->lastmapinfo && wbs->lastmapinfo->levelname)
-+    {
-+        const char * level_string = wbs->lastmapinfo->levelname;
-+
-+        x = (BASEVIDWIDTH - V_StringWidth(level_string)) / 2;
-+        V_DrawString(x, y, V_WHITEMAP, level_string);
-+
-+        if (wbs->lastmapinfo && wbs->lastmapinfo->author)
-+        {
-+            const char * author_string = wbs->lastmapinfo->author;
-+
-+            y += (5 * V_FontInfo()->height) / 4;
-+
-+            x = (BASEVIDWIDTH - V_StringWidth(author_string)) / 2;
-+            V_DrawString(x, y, V_WHITEMAP, author_string);
-+        }
-+
-+        y += 2 * V_FontInfo()->height;
-+
-+        x = (BASEVIDWIDTH - (V_patch(finished)->width)) / 2;
-+        V_DrawScaledPatch(x, y, finished);
-+    }
-+    // Normal behaviour without UMAPINFO
-     else
-     {
--        //[segabor]: 'SHORT' BUG !  [WDJ] Patch read does endian conversion
--        pp = lnames[wbs->lev_prev];
--        pf = V_patch( pp );  // access patch fields
--        V_DrawScaledPatch ((BASEVIDWIDTH - pf->width)/2, y, pp);
--        y += (5 * pf->height)/4;
--        // draw "Finished!"
--        V_DrawScaledPatch ((BASEVIDWIDTH - (V_patch(finished)->width))/2,
--                            y, finished);
-+        // draw <LevelName>
-+        if (FontBBaseLump)
-+        {
-+            x = (BASEVIDWIDTH - V_TextBWidth(P_LevelName())) / 2;
-+            V_DrawTextB(P_LevelName(), x, y);
-+
-+            y += (5 * V_TextBHeight(P_LevelName())) / 4;
-+
-+            x = (BASEVIDWIDTH - V_TextBWidth("Finished")) / 2;
-+            V_DrawTextB("Finished", x, y);
-+        }
-+        else
-+        {
-+            //[segabor]: 'SHORT' BUG !  [WDJ] Patch read does endian conversion
-+            pp = lnames[wbs->lev_prev];
-+            pf = V_patch( pp );  // access patch fields
-+            x = (BASEVIDWIDTH - pf->width) / 2;
-+            V_DrawScaledPatch(x, y, pp);
-+
-+            y += (5 * pf->height) / 4;
-+
-+            x = (BASEVIDWIDTH - (V_patch(finished)->width)) / 2;
-+            // draw "Finished!"
-+            V_DrawScaledPatch(x, y, finished);
-+        }
-     }
- }
- 
-@@ -552,31 +628,81 @@ static void WI_Draw_EL(void)
- {
-     // Hardware or software render.
-     patch_t * pp, * pf;
-+    int x = 0;
-     int y = WI_TITLEY;
- 
--    // draw "Entering"
--    if( FontBBaseLump )
-+    // [MB] 2023-03-12: Support for UMAPINFO added
-+    // See WI_Draw_LF() for additional notes about levelpic
-+    if (wbs->nextmapinfo && wbs->nextmapinfo->levelpic)
-     {
--        const char * levname = P_LevelNameByNum(wbs->epsd+1, wbs->lev_next+1);
--        V_DrawTextB("Entering", (BASEVIDWIDTH - V_TextBWidth("Entering"))/2, y);
--        y += (5*V_TextBHeight("Entering"))/4;
--        V_DrawTextB( levname, (BASEVIDWIDTH - V_TextBWidth(levname))/2, y);
-+        x = (BASEVIDWIDTH - (V_patch(entering)->width)) / 2;
-+        V_DrawScaledPatch(x, y, entering);
-+
-+        y += (5 * V_patch(entering)->height) / 4;
-+
-+        pp = W_CachePatchName(wbs->nextmapinfo->levelpic, PU_CACHE);
-+        pf = V_patch(pp);  // access patch fields
-+        x = (BASEVIDWIDTH - pf->width) / 2;
-+        V_DrawScaledPatch(x, y, pp);
-     }
--    else
-+    else if (wbs->nextmapinfo && wbs->nextmapinfo->levelname)
-     {
--        //[segabor]: 'SHORT' BUG !    [WDJ] Patch read does endian conversion
--        V_DrawScaledPatch((BASEVIDWIDTH - (V_patch(entering)->width))/2,
--                          y, entering);
--        // draw level
--        pp = lnames[wbs->lev_next];
--        pf = V_patch( pp );  // access patch fields
--        y += (5 * pf->height)/4;
-+        const char * level_string = wbs->nextmapinfo->levelname;
-+
-+        x = (BASEVIDWIDTH - (V_patch(entering)->width)) / 2;
-+        V_DrawScaledPatch(x, y, entering);
-+
-+        y += V_patch(entering)->height + V_FontInfo()->height;
-+
-+        x = (BASEVIDWIDTH - V_StringWidth(level_string)) / 2;
-+        V_DrawString(x, y, V_WHITEMAP, level_string);
- 
--        V_DrawScaledPatch((BASEVIDWIDTH - pf->width)/2, y, pp);
-+        if (wbs->nextmapinfo && wbs->nextmapinfo->author)
-+        {
-+            const char * author_string = wbs->nextmapinfo->author;
-+
-+            y += (5 * V_FontInfo()->height) / 4;
-+
-+            x = (BASEVIDWIDTH - V_StringWidth(author_string)) / 2;
-+            V_DrawString(x, y, V_WHITEMAP, author_string);
-+        }
-     }
-+    // Normal behaviour without UMAPINFO
-+    else
-+    {
-+        // draw "Entering"
-+        if (FontBBaseLump)
-+        {
-+            const char * level_string = P_LevelNameByNum(wbs->epsd + 1,
-+                                                         wbs->lev_next + 1);
-+
-+            x = (BASEVIDWIDTH - V_TextBWidth("Entering")) / 2;
-+            V_DrawTextB("Entering", x, y);
-+
-+            y += (5 * V_TextBHeight("Entering")) / 4;
-+
-+            x = (BASEVIDWIDTH - V_TextBWidth(level_string)) / 2;
-+            V_DrawTextB(level_string, x, y);
-+        }
-+        else
-+        {
-+            //[segabor]: 'SHORT' BUG !  [WDJ] Patch read does endian conversion
-+            x = (BASEVIDWIDTH - (V_patch(entering)->width)) / 2;
-+            V_DrawScaledPatch(x, y, entering);
-+
-+            // draw level
-+            pp = lnames[wbs->lev_next];
-+            pf = V_patch(pp);  // access patch fields
- 
-+            y += (5 * pf->height) / 4;
-+
-+            x = (BASEVIDWIDTH - pf->width) / 2;
-+            V_DrawScaledPatch(x, y, pp);
-+        }
-+    }
- }
- 
-+
- // [WDJ] Made more resistent to segfault.
- // Doom YAH draw
- //  n : YAH index
-@@ -958,6 +1084,20 @@ static void WI_Draw_ShowNextLoc(void)
-     if (cnt<=0)  // all removed no draw !!!
-         return;
- 
-+    // [MB] 2023-04-01: Support for UMAPINFO added
-+    if (wbs->lastmapinfo)
-+    {
-+        if ( (wbs->lastmapinfo->endgame == enabled) ||
-+             (wbs->lastmapinfo->endbunny) ||
-+             (wbs->lastmapinfo->endcast) )
-+            return;
-+    }
-+    if (wbs->nextmapinfo && wbs->nextmapinfo->enterpic)
-+    {
-+        strcpy(bgname, wbs->nextmapinfo->enterpic);
-+        WI_Prepare_Background();
-+    }
-+
-     WI_Slam_Background();
- 
-     // draw animated background
-@@ -990,10 +1130,16 @@ static void WI_Draw_ShowNextLoc(void)
-     }
- 
-     // draws which level you are entering..
--    if ( EN_doom_etc
--         && !((gamemode == doom2_commercial) && (wbs->lev_next == 30)) )
--        WI_Draw_EL();
--
-+    if (EN_doom_etc)
-+    {
-+        boolean map30 = (gamemode == doom2_commercial) && (wbs->lev_next == 30);
-+        boolean do_el = wbs->lastmapinfo
-+                        && (wbs->lastmapinfo->endgame == disabled);
-+
-+        // [MB] 2023-04-02: Draw EL if UMAPINFO has disabled endgame
-+        if (!map30 || do_el)
-+            WI_Draw_EL();
-+    }
- }
- 
- // Called by WI_Drawer
-@@ -1977,7 +2123,6 @@ static void WI_checkForAccelerate(void)
- }
- 
- 
--
- // Updates stuff each client tick.
- void WI_Ticker(void)
- {
-@@ -2097,20 +2242,8 @@ void WI_Load_Data(void)
-         if (wb_epsd == 3)
-             strcpy(bgname,"INTERPIC");
-     }
--    
--    
--    if( rendermode == render_soft )
--    {
--        memset(screens[0], 0, vid.screen_size);
- 
--        // clear backbuffer from status bar stuff and borders
--        memset(screens[1], 0, vid.screen_size);
--  
--        // Draw background on screen1
--        V_SetupDraw( 1 | V_SCALESTART | V_SCALEPATCH | V_CENTERHORZ ); // screen 1
--        V_DrawScaledPatch(0, 0, W_CachePatchName(bgname, PU_CACHE));
--        V_SetupDraw( drawinfo.prev_screenflags );  // restore
--    }
-+    WI_Prepare_Background();
- 
-     // UNUSED unsigned char *pic = screens[1];
-     // if (gamemode == doom2_commercial)
-@@ -2333,6 +2466,14 @@ void WI_Start(wb_start_t * wb_start)
-         WI_Init_NetgameStats();
-         // wait_game_start_timer will be set by network
-     }
-+    // [MB] 2023-03-29: Support for UMAPINFO added
-+    else if( gamemapinfo && gamemapinfo->nointermission )
-+    {
-+        if ( gamemode == doom2_commercial )
-+            WI_Init_NoState();
-+        else
-+            WI_Init_ShowNextLoc();
-+    }
-     else
-         WI_Init_Stats();
- }



Home | Main Index | Thread Index | Old Index