From 7e7bd266015839ed9ca084d8499b5586a3e529db Mon Sep 17 00:00:00 2001 From: Jonny Paton Date: Tue, 26 Nov 2024 13:43:02 +0000 Subject: [PATCH] Change menu message handlers to use sfml keyboard types and fix quit message handler, bit of formatting --- linuxdoom-1.10/r_draw.h | 7 + src/doom/main.ixx | 1390 +++++++++++++++++++++------------------ src/doom/menu.ixx | 61 +- src/doom/wad.ixx | 501 +++++++------- src/engine/system.ixx | 265 ++++---- 5 files changed, 1184 insertions(+), 1040 deletions(-) diff --git a/linuxdoom-1.10/r_draw.h b/linuxdoom-1.10/r_draw.h index b318fd2..ab330d2 100644 --- a/linuxdoom-1.10/r_draw.h +++ b/linuxdoom-1.10/r_draw.h @@ -21,6 +21,13 @@ #pragma once +// This could be wider for >8 bit display. +// Indeed, true color support is posibble +// precalculating 24bpp lightmap/colormap LUT. +// from darkening PLAYPAL to all black. +// Could even us emore than 32 levels. +typedef std::byte lighttable_t; + extern lighttable_t *dc_colormap; extern int dc_x; extern int dc_yl; diff --git a/src/doom/main.ixx b/src/doom/main.ixx index 1f63d23..9c812ff 100644 --- a/src/doom/main.ixx +++ b/src/doom/main.ixx @@ -20,13 +20,13 @@ // //----------------------------------------------------------------------------- module; -#include "i_video.h" #include "g_game.h" -#include "r_main.h" +#include "i_video.h" #include "r_draw.h" +#include "r_main.h" #include -#include #include +#include export module main; import system; @@ -77,8 +77,8 @@ export bool autostart; export bool advancedemo; -char wadfile[1024]; // primary wad file -char mapdir[1024]; // directory of development maps +char wadfile[1024]; // primary wad file +char mapdir[1024]; // directory of development maps // // EVENT HANDLING @@ -94,26 +94,29 @@ export int eventtail; // D_PostEvent // Called by the I/O functions when input is detected // -export void D_PostEvent(const sf::Event &ev) { - events[eventhead] = std::make_unique(ev); - eventhead = (++eventhead) & (MAXEVENTS - 1); +export void D_PostEvent(const sf::Event &ev) +{ + events[eventhead] = std::make_unique(ev); + eventhead = (++eventhead) & (MAXEVENTS - 1); } // // D_ProcessEvents // Send all the events of the given timestamp down the responder chain // -export void D_ProcessEvents(void) { - // IF STORE DEMO, DO NOT ACCEPT INPUT - if ((gamemode == commercial) && (W_CheckNumForName("map01") < 0)) - return; - - for (; eventtail != eventhead; eventtail = (++eventtail) & (MAXEVENTS - 1)) { - auto &ev = events[eventtail]; - if (M_Responder(*ev)) - continue; // menu ate the event - G_Responder(*ev); - } +export void D_ProcessEvents(void) +{ + // IF STORE DEMO, DO NOT ACCEPT INPUT + if ((gamemode == commercial) && (W_CheckNumForName("map01") < 0)) + return; + + for (; eventtail != eventhead; eventtail = (++eventtail) & (MAXEVENTS - 1)) + { + auto &ev = events[eventtail]; + if (M_Responder(*ev)) + continue; // menu ate the event + G_Responder(*ev); + } } std::string pagename; @@ -121,9 +124,9 @@ std::string pagename; // // D_PageDrawer // -void D_PageDrawer(void) { - V_DrawPatch(0, 0, 0, - static_cast(W_CacheLumpName(pagename))); +void D_PageDrawer(void) +{ + V_DrawPatch(0, 0, 0, static_cast(W_CacheLumpName(pagename))); } // @@ -135,143 +138,155 @@ void D_PageDrawer(void) { export gamestate_t wipegamestate = GS_DEMOSCREEN; export bool setsizeneeded; -void D_Display(void) { - static bool viewactivestate = false; - static bool menuactivestate = false; - static bool inhelpscreensstate = false; - static bool fullscreen = false; - static gamestate_t oldgamestate = static_cast(-1); - static int borderdrawcount; - int nowtime; - int tics; - int wipestart; - int y; - bool done; - bool wipe; - bool redrawsbar; - - if (nodrawers) - return; // for comparative timing / profiling - - redrawsbar = false; - - // change the view size if needed - if (setsizeneeded) { - R_ExecuteSetViewSize(); - oldgamestate = static_cast(-1); // force background redraw - borderdrawcount = 3; - } - - // save the current screen if about to wipe - if (gamestate != wipegamestate) { - wipe = true; - wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); - } else - wipe = false; - - if (gamestate == GS_LEVEL && gametic) - HU_Erase(); - - // do buffered drawing - switch (gamestate) { - case GS_LEVEL: - if (!gametic) - break; - if (automapactive) - AM_Drawer(); - if (wipe || (viewheight != 200 && fullscreen)) - redrawsbar = true; - if (inhelpscreensstate && !inhelpscreens) - redrawsbar = true; // just put away the help screen - ST_Drawer(viewheight == 200, redrawsbar); - fullscreen = viewheight == 200; - break; - - case GS_INTERMISSION: - WI_Drawer(); - break; - - case GS_FINALE: - F_Drawer(); - break; - - case GS_DEMOSCREEN: - D_PageDrawer(); - break; - } - - // draw buffered stuff to screen - I_UpdateNoBlit(); - - // draw the view directly - if (gamestate == GS_LEVEL && !automapactive && gametic) - R_RenderPlayerView(&players[displayplayer]); - - if (gamestate == GS_LEVEL && gametic) - HU_Drawer(); - - // clean up border stuff - if (gamestate != oldgamestate && gamestate != GS_LEVEL) - I_SetPalette(static_cast(W_CacheLumpName("PLAYPAL"))); - - // see if the border needs to be initially drawn - if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL) { - viewactivestate = false; // view was not active - R_FillBackScreen(); // draw the pattern into the back screen - } - - // see if the border needs to be updated to the screen - if (gamestate == GS_LEVEL && !automapactive && scaledviewwidth != 320) { - if (menuactive || menuactivestate || !viewactivestate) - borderdrawcount = 3; - if (borderdrawcount) { - R_DrawViewBorder(); // erase old menu stuff - borderdrawcount--; - } - } - - menuactivestate = menuactive; - viewactivestate = viewactive; - inhelpscreensstate = inhelpscreens; - oldgamestate = wipegamestate = gamestate; - - // draw pause pic - if (paused) { - if (automapactive) - y = 4; +void D_Display(void) +{ + static bool viewactivestate = false; + static bool menuactivestate = false; + static bool inhelpscreensstate = false; + static bool fullscreen = false; + static gamestate_t oldgamestate = static_cast(-1); + static int borderdrawcount; + int nowtime; + int tics; + int wipestart; + int y; + bool done; + bool wipe; + bool redrawsbar; + + if (nodrawers) + return; // for comparative timing / profiling + + redrawsbar = false; + + // change the view size if needed + if (setsizeneeded) + { + R_ExecuteSetViewSize(); + oldgamestate = static_cast(-1); // force background redraw + borderdrawcount = 3; + } + + // save the current screen if about to wipe + if (gamestate != wipegamestate) + { + wipe = true; + wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); + } else - y = viewwindowy + 4; - V_DrawPatchDirect( - viewwindowx + (scaledviewwidth - 68) / 2, y, 0, - static_cast(W_CacheLumpName("M_PAUSE"))); - } - - // menus go directly to the screen - M_Drawer(); // menu is drawn even on top of everything - NetUpdate(); // send out any new accumulation - - // normal update - if (!wipe) { - I_FinishUpdate(); // page flip or blit buffer - return; - } - - // wipe update - wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); - - wipestart = I_GetTime() - 1; - - do { - do { - nowtime = I_GetTime(); - tics = nowtime - wipestart; - } while (!tics); - wipestart = nowtime; - done = wipe_ScreenWipe(wipe_Melt, 0, 0, SCREENWIDTH, SCREENHEIGHT, tics); + wipe = false; + + if (gamestate == GS_LEVEL && gametic) + HU_Erase(); + + // do buffered drawing + switch (gamestate) + { + case GS_LEVEL: + if (!gametic) + break; + if (automapactive) + AM_Drawer(); + if (wipe || (viewheight != 200 && fullscreen)) + redrawsbar = true; + if (inhelpscreensstate && !inhelpscreens) + redrawsbar = true; // just put away the help screen + ST_Drawer(viewheight == 200, redrawsbar); + fullscreen = viewheight == 200; + break; + + case GS_INTERMISSION: + WI_Drawer(); + break; + + case GS_FINALE: + F_Drawer(); + break; + + case GS_DEMOSCREEN: + D_PageDrawer(); + break; + } + + // draw buffered stuff to screen I_UpdateNoBlit(); - M_Drawer(); // menu is drawn even on top of wipes - I_FinishUpdate(); // page flip or blit buffer - } while (!done); + + // draw the view directly + if (gamestate == GS_LEVEL && !automapactive && gametic) + R_RenderPlayerView(&players[displayplayer]); + + if (gamestate == GS_LEVEL && gametic) + HU_Drawer(); + + // clean up border stuff + if (gamestate != oldgamestate && gamestate != GS_LEVEL) + I_SetPalette(static_cast(W_CacheLumpName("PLAYPAL"))); + + // see if the border needs to be initially drawn + if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL) + { + viewactivestate = false; // view was not active + R_FillBackScreen(); // draw the pattern into the back screen + } + + // see if the border needs to be updated to the screen + if (gamestate == GS_LEVEL && !automapactive && scaledviewwidth != 320) + { + if (menuactive || menuactivestate || !viewactivestate) + borderdrawcount = 3; + if (borderdrawcount) + { + R_DrawViewBorder(); // erase old menu stuff + borderdrawcount--; + } + } + + menuactivestate = menuactive; + viewactivestate = viewactive; + inhelpscreensstate = inhelpscreens; + oldgamestate = wipegamestate = gamestate; + + // draw pause pic + if (paused) + { + if (automapactive) + y = 4; + else + y = viewwindowy + 4; + V_DrawPatchDirect(viewwindowx + (scaledviewwidth - 68) / 2, y, 0, + static_cast(W_CacheLumpName("M_PAUSE"))); + } + + // menus go directly to the screen + M_Drawer(); // menu is drawn even on top of everything + NetUpdate(); // send out any new accumulation + + // normal update + if (!wipe) + { + I_FinishUpdate(); // page flip or blit buffer + return; + } + + // wipe update + wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); + + wipestart = I_GetTime() - 1; + + do + { + do + { + nowtime = I_GetTime(); + tics = nowtime - wipestart; + } while (!tics); + wipestart = nowtime; + done = + wipe_ScreenWipe(wipe_Melt, 0, 0, SCREENWIDTH, SCREENHEIGHT, tics); + I_UpdateNoBlit(); + M_Drawer(); // menu is drawn even on top of wipes + I_FinishUpdate(); // page flip or blit buffer + } while (!done); } // @@ -284,72 +299,78 @@ int pagetic; // This cycles through the demo sequences. // FIXME - version dependend demo numbers? // -export void D_DoAdvanceDemo(void) { - players[consoleplayer].playerstate = PST_LIVE; // not reborn - advancedemo = false; - usergame = false; // no save / end game here - paused = false; - gameaction = gameaction_t::ga_nothing; - - if (gamemode == retail) - demosequence = (demosequence + 1) % 7; - else - demosequence = (demosequence + 1) % 6; - - switch (demosequence) { - case 0: - if (gamemode == commercial) - pagetic = 35 * 11; - else - pagetic = 170; - gamestate = GS_DEMOSCREEN; - pagename = "TITLEPIC"; - if (gamemode == commercial) - S_StartMusic(mus_dm2ttl); +export void D_DoAdvanceDemo(void) +{ + players[consoleplayer].playerstate = PST_LIVE; // not reborn + advancedemo = false; + usergame = false; // no save / end game here + paused = false; + gameaction = gameaction_t::ga_nothing; + + if (gamemode == retail) + demosequence = (demosequence + 1) % 7; else - S_StartMusic(mus_intro); - break; - case 1: - G_DeferedPlayDemo("demo1"); - break; - case 2: - pagetic = 200; - gamestate = GS_DEMOSCREEN; - pagename = "CREDIT"; - break; - case 3: - G_DeferedPlayDemo("demo2"); - break; - case 4: - gamestate = GS_DEMOSCREEN; - if (gamemode == commercial) { - pagetic = 35 * 11; - pagename = "TITLEPIC"; - S_StartMusic(mus_dm2ttl); - } else { - pagetic = 200; - - if (gamemode == retail) + demosequence = (demosequence + 1) % 6; + + switch (demosequence) + { + case 0: + if (gamemode == commercial) + pagetic = 35 * 11; + else + pagetic = 170; + gamestate = GS_DEMOSCREEN; + pagename = "TITLEPIC"; + if (gamemode == commercial) + S_StartMusic(mus_dm2ttl); + else + S_StartMusic(mus_intro); + break; + case 1: + G_DeferedPlayDemo("demo1"); + break; + case 2: + pagetic = 200; + gamestate = GS_DEMOSCREEN; pagename = "CREDIT"; - else - pagename = "HELP2"; - } - break; - case 5: - G_DeferedPlayDemo("demo3"); - break; - // THE DEFINITIVE DOOM Special Edition demo - case 6: - G_DeferedPlayDemo("demo4"); - break; - } + break; + case 3: + G_DeferedPlayDemo("demo2"); + break; + case 4: + gamestate = GS_DEMOSCREEN; + if (gamemode == commercial) + { + pagetic = 35 * 11; + pagename = "TITLEPIC"; + S_StartMusic(mus_dm2ttl); + } + else + { + pagetic = 200; + + if (gamemode == retail) + pagename = "CREDIT"; + else + pagename = "HELP2"; + } + break; + case 5: + G_DeferedPlayDemo("demo3"); + break; + // THE DEFINITIVE DOOM Special Edition demo + case 6: + G_DeferedPlayDemo("demo4"); + break; + } } // // I_StartFrame // -void I_StartFrame(void) { - // er? +void I_StartFrame(void) +{ + // er? } // @@ -361,39 +382,44 @@ void I_StartFrame(void) { // export bool demorecording; -void D_DoomLoop(void) { - if (demorecording) - G_BeginRecording(); - - I_InitGraphics(); - - while (1) { - // frame syncronous IO operations - I_StartFrame(); - - // process one or more tics - if (singletics) { - I_StartTic(); - D_ProcessEvents(); - G_BuildTiccmd(&netcmds[consoleplayer][maketic % BACKUPTICS]); - if (advancedemo) - D_DoAdvanceDemo(); - M_Ticker(); - G_Ticker(); - gametic++; - maketic++; - } else { - if (advancedemo) - D_DoAdvanceDemo(); - D_ProcessEvents(); - TryRunTics(); // will run at least one tic - } - - S_UpdateSounds(players[consoleplayer].mo); // move positional sounds - - // Update display, next frame, with current state. - D_Display(); - } +void D_DoomLoop(void) +{ + if (demorecording) + G_BeginRecording(); + + I_InitGraphics(); + + while (1) + { + // frame syncronous IO operations + I_StartFrame(); + + // process one or more tics + if (singletics) + { + I_StartTic(); + D_ProcessEvents(); + G_BuildTiccmd(&netcmds[consoleplayer][maketic % BACKUPTICS]); + if (advancedemo) + D_DoAdvanceDemo(); + M_Ticker(); + G_Ticker(); + gametic++; + maketic++; + } + else + { + if (advancedemo) + D_DoAdvanceDemo(); + D_ProcessEvents(); + TryRunTics(); // will run at least one tic + } + + S_UpdateSounds(players[consoleplayer].mo); // move positional sounds + + // Update display, next frame, with current state. + D_Display(); + } } // @@ -406,18 +432,20 @@ export void D_AdvanceDemo(void) { advancedemo = true; } // D_PageTicker // Handles timing for warped projection // -export void D_PageTicker(void) { - if (--pagetic < 0) - D_AdvanceDemo(); +export void D_PageTicker(void) +{ + if (--pagetic < 0) + D_AdvanceDemo(); } // // D_StartTitle // -export void D_StartTitle(void) { - gameaction = gameaction_t::ga_nothing; - demosequence = -1; - D_AdvanceDemo(); +export void D_StartTitle(void) +{ + gameaction = gameaction_t::ga_nothing; + demosequence = -1; + D_AdvanceDemo(); } // @@ -426,116 +454,128 @@ export void D_StartTitle(void) { // to determine whether registered/commercial features // should be executed (notably loading PWAD's). // -void IdentifyVersion(void) { - std::string waddir = "wads"; - - spdlog::info("WAD directory: {}", (std::filesystem::current_path() / waddir).string()); - - // Commercial. - const auto doom2wad = waddir + "/doom2.wad"; - - // Retail. - const auto doomuwad = waddir + "/doomu.wad"; - - // Registered. - const auto doomwad = waddir + "/doom.wad"; - - // Shareware. - const auto doom1wad = waddir + "/doom1.wad"; - - // Plutonia. - const auto plutoniawad = waddir + "/plutonia.wad"; - - // TNT. - const auto tntwad = waddir + "/tnt.wad"; - - // French stuff. - const auto doom2fwad = waddir + "/doom2f.wad"; - - if (arguments::has("-shdev")) { - gamemode = shareware; - wadfilenames.emplace_back( "doom1.wad"); - wadfilenames.emplace_back( "data_se/texture1.lmp"); - wadfilenames.emplace_back( "data_se/pnames.lmp"); - return; - } - - if (arguments::has("-regdev")) { - gamemode = registered; - wadfilenames.emplace_back( "doom.wad"); - wadfilenames.emplace_back( "data_se/texture1.lmp"); - wadfilenames.emplace_back( "data_se/texture2.lmp"); - wadfilenames.emplace_back( "data_se/pnames.lmp"); - return; - } - - if (arguments::has("-comdev")) { - gamemode = commercial; - /* I don't bother - if(plutonia) - wadfilenames.emplace_back ("plutonia.wad"); - else if(tnt) - wadfilenames.emplace_back ("tnt.wad"); - else*/ - wadfilenames.emplace_back( "doom2.wad"); - - wadfilenames.emplace_back( "cdata/texture1.lmp"); - wadfilenames.emplace_back( "cdata/pnames.lmp"); - return; - } - - if (std::filesystem::exists(doom2fwad)) { - gamemode = commercial; - // C'est ridicule! - // Let's handle languages in config files, okay? - language = french; - printf("French version\n"); - wadfilenames.emplace_back(doom2fwad.c_str()); - return; - } - - if (std::filesystem::exists(doom2wad)) { - gamemode = commercial; - wadfilenames.emplace_back(doom2wad.c_str()); - return; - } - - if (std::filesystem::exists(plutoniawad)) { - gamemode = commercial; - wadfilenames.emplace_back(plutoniawad.c_str()); - return; - } - - if (std::filesystem::exists(tntwad)) { - gamemode = commercial; - wadfilenames.emplace_back(tntwad.c_str()); - return; - } - - if (std::filesystem::exists(doomuwad)) { - gamemode = retail; - wadfilenames.emplace_back(doomuwad.c_str()); - return; - } - - if (std::filesystem::exists(doomwad)) { - gamemode = registered; - wadfilenames.emplace_back(doomwad.c_str()); - return; - } - - if (std::filesystem::exists(doom1wad)) { - gamemode = shareware; - wadfilenames.emplace_back(doom1wad.c_str()); - return; - } - - printf("Game mode indeterminate.\n"); - gamemode = indetermined; - - // We don't abort. Let's see what the PWAD contains. - // exit(1); - // I_Error ("Game mode indeterminate\n"); +void IdentifyVersion(void) +{ + std::string waddir = "wads"; + + spdlog::info("WAD directory: {}", + (std::filesystem::current_path() / waddir).string()); + + // Commercial. + const auto doom2wad = waddir + "/doom2.wad"; + + // Retail. + const auto doomuwad = waddir + "/doomu.wad"; + + // Registered. + const auto doomwad = waddir + "/doom.wad"; + + // Shareware. + const auto doom1wad = waddir + "/doom1.wad"; + + // Plutonia. + const auto plutoniawad = waddir + "/plutonia.wad"; + + // TNT. + const auto tntwad = waddir + "/tnt.wad"; + + // French stuff. + const auto doom2fwad = waddir + "/doom2f.wad"; + + if (arguments::has("-shdev")) + { + gamemode = shareware; + wadfilenames.emplace_back("doom1.wad"); + wadfilenames.emplace_back("data_se/texture1.lmp"); + wadfilenames.emplace_back("data_se/pnames.lmp"); + return; + } + + if (arguments::has("-regdev")) + { + gamemode = registered; + wadfilenames.emplace_back("doom.wad"); + wadfilenames.emplace_back("data_se/texture1.lmp"); + wadfilenames.emplace_back("data_se/texture2.lmp"); + wadfilenames.emplace_back("data_se/pnames.lmp"); + return; + } + + if (arguments::has("-comdev")) + { + gamemode = commercial; + /* I don't bother + if(plutonia) + wadfilenames.emplace_back ("plutonia.wad"); + else if(tnt) + wadfilenames.emplace_back ("tnt.wad"); + else*/ + wadfilenames.emplace_back("doom2.wad"); + + wadfilenames.emplace_back("cdata/texture1.lmp"); + wadfilenames.emplace_back("cdata/pnames.lmp"); + return; + } + + if (std::filesystem::exists(doom2fwad)) + { + gamemode = commercial; + // C'est ridicule! + // Let's handle languages in config files, okay? + language = french; + printf("French version\n"); + wadfilenames.emplace_back(doom2fwad.c_str()); + return; + } + + if (std::filesystem::exists(doom2wad)) + { + gamemode = commercial; + wadfilenames.emplace_back(doom2wad.c_str()); + return; + } + + if (std::filesystem::exists(plutoniawad)) + { + gamemode = commercial; + wadfilenames.emplace_back(plutoniawad.c_str()); + return; + } + + if (std::filesystem::exists(tntwad)) + { + gamemode = commercial; + wadfilenames.emplace_back(tntwad.c_str()); + return; + } + + if (std::filesystem::exists(doomuwad)) + { + gamemode = retail; + wadfilenames.emplace_back(doomuwad.c_str()); + return; + } + + if (std::filesystem::exists(doomwad)) + { + gamemode = registered; + wadfilenames.emplace_back(doomwad.c_str()); + return; + } + + if (std::filesystem::exists(doom1wad)) + { + gamemode = shareware; + wadfilenames.emplace_back(doom1wad.c_str()); + return; + } + + printf("Game mode indeterminate.\n"); + gamemode = indetermined; + + // We don't abort. Let's see what the PWAD contains. + // exit(1); + // I_Error ("Game mode indeterminate\n"); } export fixed_t forwardmove[2] = {0x19, 0x32}; @@ -547,313 +587,351 @@ export fixed_t sidemove[2] = {0x18, 0x28}; // calls all startup code, parses command line options. // If not overrided by user input, calls N_AdvanceDemo. // -export void D_DoomMain(void) { - int p; - std::string file; - - IdentifyVersion(); - - modifiedgame = false; - - nomonsters = arguments::has("-nomonsters"); - respawnparm = arguments::has("-respawn"); - fastparm = arguments::has("-fast"); - if (arguments::has("-altdeath")) - deathmatch = 2; - else if (arguments::has("-deathmatch")) - deathmatch = 1; - - switch (gamemode) { - case retail: - spdlog::info("The Ultimate DOOM Startup v{}.{}", VERSION / 100, VERSION % 100); - break; - case shareware: - spdlog::info("DOOM Shareware Startup v{}.{}", VERSION / 100, VERSION % 100); - break; - case registered: - spdlog::info("DOOM Registered Startup v{}.{}", VERSION / 100, VERSION % 100); - break; - case commercial: - spdlog::info("DOOM 2: Hell on Earth v{}.{}", VERSION / 100, VERSION % 100); - break; - /*FIXME - case pack_plut: - sprintf (title, - " " - "DOOM 2: Plutonia Experiment v%i.%i" - " ", - VERSION/100,VERSION%100); - break; - case pack_tnt: - sprintf (title, - " " - "DOOM 2: TNT - Evilution v%i.%i" - " ", - VERSION/100,VERSION%100); - break; - */ - default: - spdlog::info("Public DOOM v{}.{}", VERSION / 100, VERSION % 100); - break; - } +export void D_DoomMain(void) +{ + int p; + std::string file; + + IdentifyVersion(); + + modifiedgame = false; + + nomonsters = arguments::has("-nomonsters"); + respawnparm = arguments::has("-respawn"); + fastparm = arguments::has("-fast"); + if (arguments::has("-altdeath")) + deathmatch = 2; + else if (arguments::has("-deathmatch")) + deathmatch = 1; + + switch (gamemode) + { + case retail: + spdlog::info("The Ultimate DOOM Startup v{}.{}", VERSION / 100, + VERSION % 100); + break; + case shareware: + spdlog::info("DOOM Shareware Startup v{}.{}", VERSION / 100, + VERSION % 100); + break; + case registered: + spdlog::info("DOOM Registered Startup v{}.{}", VERSION / 100, + VERSION % 100); + break; + case commercial: + spdlog::info("DOOM 2: Hell on Earth v{}.{}", VERSION / 100, + VERSION % 100); + break; + /*FIXME + case pack_plut: + sprintf (title, + " " + "DOOM 2: Plutonia Experiment v%i.%i" + " ", + VERSION/100,VERSION%100); + break; + case pack_tnt: + sprintf (title, + " " + "DOOM 2: TNT - Evilution v%i.%i" + " ", + VERSION/100,VERSION%100); + break; + */ + default: + spdlog::info("Public DOOM v{}.{}", VERSION / 100, VERSION % 100); + break; + } #if !NDEBUG printf(D_DEVSTR); #endif - // turbo option - if ((p = arguments::has("-turbo"))) { - int scale = 200; - - if (p < arguments::count() - 1) - scale = atoi(arguments::at(p + 1).data()); - if (scale < 10) - scale = 10; - if (scale > 400) - scale = 400; - spdlog::info("turbo scale: {}%%\n", scale); - forwardmove[0] = forwardmove[0] * scale / 100; - forwardmove[1] = forwardmove[1] * scale / 100; - sidemove[0] = sidemove[0] * scale / 100; - sidemove[1] = sidemove[1] * scale / 100; - } - - // add any files specified on the command line with -file wadfile - // to the wad list - // - // convenience hack to allow -wart e m to add a wad file - // prepend a tilde to the filename so wadfile will be reloadable - p = arguments::has("-wart"); - if (p) { - // @TODO JONNY - //arguments::at(p)[4] = 'p'; // big hack, change to -warp - - // Map name handling. - switch (gamemode) { + // turbo option + if ((p = arguments::has("-turbo"))) + { + int scale = 200; + + if (p < arguments::count() - 1) + scale = atoi(arguments::at(p + 1).data()); + if (scale < 10) + scale = 10; + if (scale > 400) + scale = 400; + spdlog::info("turbo scale: {}%%\n", scale); + forwardmove[0] = forwardmove[0] * scale / 100; + forwardmove[1] = forwardmove[1] * scale / 100; + sidemove[0] = sidemove[0] * scale / 100; + sidemove[1] = sidemove[1] * scale / 100; + } + + // add any files specified on the command line with -file wadfile + // to the wad list + // + // convenience hack to allow -wart e m to add a wad file + // prepend a tilde to the filename so wadfile will be reloadable + p = arguments::has("-wart"); + if (p) + { + // @TODO JONNY + // arguments::at(p)[4] = 'p'; // big hack, change to -warp + + // Map name handling. + switch (gamemode) + { + case shareware: + case retail: + case registered: + // snprintf(file, 256, "~/E%cM%c.wad", arguments::at(p + 1)[0], + // arguments::at(p + 2)[0]); + // printf("Warping to Episode %s, Map %s.\n", arguments::at(p + + // 1).c_str(), + // arguments::at(p + 2).c_str()); + break; + + case commercial: + default: + p = atoi(arguments::at(p + 1).data()); + if (p < 10) + { + } + // snprintf(file, 256, "~/cdata/map0%i.wad", p); + else + { + } + // snprintf(file, 256, "~/cdata/map%i.wad", p); + break; + } + wadfilenames.emplace_back(file); + } + + p = arguments::has("-file"); + if (p) + { + // the parms after p are wadfile/lump names, + // until end of parms or another - preceded parm + modifiedgame = true; // homebrew levels + while (++p != arguments::count() && arguments::at(p)[0] != '-') + wadfilenames.emplace_back(arguments::at(p).data()); + } + + p = arguments::has("-playdemo"); + + if (!p) + p = arguments::has("-timedemo"); + + if (p && p < arguments::count() - 1) + { + // snprintf(file, 256, "%s.lmp", arguments::at(p + 1).c_str()); + wadfilenames.emplace_back(file); + printf("Playing demo %s.lmp.\n", arguments::at(p + 1).data()); + } + + // get skill / episode / map from parms + startskill = sk_medium; + startepisode = 1; + startmap = 1; + autostart = false; + + p = arguments::has("-skill"); + if (p && p < arguments::count() - 1) + { + startskill = static_cast(arguments::at(p + 1)[0] - '1'); + autostart = true; + } + + p = arguments::has("-episode"); + if (p && p < arguments::count() - 1) + { + startepisode = arguments::at(p + 1)[0] - '0'; + startmap = 1; + autostart = true; + } + + p = arguments::has("-timer"); + if (p && p < arguments::count() - 1 && deathmatch) + { + int time; + time = atoi(arguments::at(p + 1).data()); + printf("Levels will end after %d minute", time); + if (time > 1) + printf("s"); + printf(".\n"); + } + + p = arguments::has("-avg"); + if (p && p < arguments::count() - 1 && deathmatch) + printf("Austin Virtual Gaming: Levels will end after 20 minutes\n"); + + p = arguments::has("-warp"); + if (p && p < arguments::count() - 1) + { + if (gamemode == commercial) + startmap = atoi(arguments::at(p + 1).data()); + else + { + startepisode = arguments::at(p + 1)[0] - '0'; + startmap = arguments::at(p + 2)[0] - '0'; + } + autostart = true; + } + + // init subsystems + M_LoadDefaults(); // load before initing other systems + + spdlog::info("W_Init: Init WADfiles."); + W_InitMultipleFiles(wadfilenames); + + // Check for -file in shareware + if (modifiedgame) + { + // These are the lumps that will be checked in IWAD, + // if any one is not present, execution will be aborted. + std::array name = {"e2m1", "e2m2", "e2m3", "e2m4", "e2m5", + "e2m6", "e2m7", "e2m8", "e2m9", "e3m1", + "e3m3", "e3m3", "e3m4", "e3m5", "e3m6", + "e3m7", "e3m8", "e3m9", "dphoof", "bfgga0", + "heada1", "cybra1", "spida1d1"}; + int i; + + if (gamemode == shareware) + I_Error("\nYou cannot -file with the shareware " + "version. Register!"); + + // Check for fake IWAD with right name, + // but w/o all the lumps of the registered version. + if (gamemode == registered) + for (i = 0; i < 23; i++) + if (W_CheckNumForName(name[i]) < 0) + I_Error("\nThis is not the registered version."); + } + + // Iff additonal PWAD files are used, print modified banner + if (modifiedgame) + { + /*m*/ printf( + "==================================================================" + "====" + "=====\n" + "ATTENTION: This version of DOOM has been modified. If you would " + "like to\n" + "get a copy of the original game, call 1-800-IDGAMES or see the " + "readme " + "file.\n" + " You will not receive technical support for modified " + "games.\n" + " press enter to continue\n" + "==================================================================" + "====" + "=====\n"); + getchar(); + } + + // Check and print which version is executed. + switch (gamemode) + { case shareware: - case retail: + case indetermined: + printf("===============================================================" + "====" + "========\n" + " Shareware!\n" + "===============================================================" + "====" + "========\n"); + break; case registered: - //snprintf(file, 256, "~/E%cM%c.wad", arguments::at(p + 1)[0], - // arguments::at(p + 2)[0]); - //printf("Warping to Episode %s, Map %s.\n", arguments::at(p + 1).c_str(), - // arguments::at(p + 2).c_str()); - break; - + case retail: case commercial: + printf("===============================================================" + "====" + "========\n" + " Commercial product - do not distribute!\n" + " Please report software piracy to the SPA: " + "1-800-388-PIR8\n" + "===============================================================" + "====" + "========\n"); + break; + default: - p = atoi( arguments::at(p + 1).data()); - if (p < 10){} - //snprintf(file, 256, "~/cdata/map0%i.wad", p); - else{} - //snprintf(file, 256, "~/cdata/map%i.wad", p); - break; - } - wadfilenames.emplace_back(file); - } - - p = arguments::has("-file"); - if (p) { - // the parms after p are wadfile/lump names, - // until end of parms or another - preceded parm - modifiedgame = true; // homebrew levels - while (++p != arguments::count() && arguments::at(p)[0] != '-') - wadfilenames.emplace_back( arguments::at(p).data()); - } - - p = arguments::has("-playdemo"); - - if (!p) - p = arguments::has("-timedemo"); + // Ouch. + break; + } - if (p && p < arguments::count() - 1) { - //snprintf(file, 256, "%s.lmp", arguments::at(p + 1).c_str()); - wadfilenames.emplace_back(file); - printf("Playing demo %s.lmp.\n", arguments::at(p + 1).data()); - } - - // get skill / episode / map from parms - startskill = sk_medium; - startepisode = 1; - startmap = 1; - autostart = false; - - p = arguments::has("-skill"); - if (p && p < arguments::count() - 1) { - startskill = static_cast(arguments::at(p + 1)[0] - '1'); - autostart = true; - } - - p = arguments::has("-episode"); - if (p && p < arguments::count() - 1) { - startepisode = arguments::at(p + 1)[0] - '0'; - startmap = 1; - autostart = true; - } - - p = arguments::has("-timer"); - if (p && p < arguments::count() - 1 && deathmatch) { - int time; - time = atoi(arguments::at(p + 1).data()); - printf("Levels will end after %d minute", time); - if (time > 1) - printf("s"); - printf(".\n"); - } - - p = arguments::has("-avg"); - if (p && p < arguments::count() - 1 && deathmatch) - printf("Austin Virtual Gaming: Levels will end after 20 minutes\n"); - - p = arguments::has("-warp"); - if (p && p < arguments::count() - 1) { - if (gamemode == commercial) - startmap = atoi(arguments::at(p + 1).data()); - else { - startepisode = arguments::at(p + 1)[0] - '0'; - startmap = arguments::at(p + 2)[0] - '0'; - } - autostart = true; - } - - // init subsystems - M_LoadDefaults(); // load before initing other systems - - spdlog::info("W_Init: Init WADfiles."); - W_InitMultipleFiles(wadfilenames); - - // Check for -file in shareware - if (modifiedgame) { - // These are the lumps that will be checked in IWAD, - // if any one is not present, execution will be aborted. - std::array name = {"e2m1", "e2m2", "e2m3", "e2m4", "e2m5", - "e2m6", "e2m7", "e2m8", "e2m9", "e3m1", - "e3m3", "e3m3", "e3m4", "e3m5", "e3m6", - "e3m7", "e3m8", "e3m9", "dphoof", "bfgga0", - "heada1", "cybra1", "spida1d1"}; - int i; - - if (gamemode == shareware) - I_Error("\nYou cannot -file with the shareware " - "version. Register!"); - - // Check for fake IWAD with right name, - // but w/o all the lumps of the registered version. - if (gamemode == registered) - for (i = 0; i < 23; i++) - if (W_CheckNumForName(name[i]) < 0) - I_Error("\nThis is not the registered version."); - } - - // Iff additonal PWAD files are used, print modified banner - if (modifiedgame) { - /*m*/ printf( - "======================================================================" - "=====\n" - "ATTENTION: This version of DOOM has been modified. If you would " - "like to\n" - "get a copy of the original game, call 1-800-IDGAMES or see the readme " - "file.\n" - " You will not receive technical support for modified games.\n" - " press enter to continue\n" - "======================================================================" - "=====\n"); - getchar(); - } - - // Check and print which version is executed. - switch (gamemode) { - case shareware: - case indetermined: - printf("===================================================================" - "========\n" - " Shareware!\n" - "===================================================================" - "========\n"); - break; - case registered: - case retail: - case commercial: - printf("===================================================================" - "========\n" - " Commercial product - do not distribute!\n" - " Please report software piracy to the SPA: 1-800-388-PIR8\n" - "===================================================================" - "========\n"); - break; - - default: - // Ouch. - break; - } - - M_Init(); - - printf("R_Init: Init DOOM refresh daemon - "); - R_Init(); - - printf("\nP_Init: Init Playloop state.\n"); - P_Init(); - - I_InitSound(); - - printf("I_Init: Setting up machine state.\n"); - I_Init(); - - printf("D_CheckNetGame: Checking network game status.\n"); - D_CheckNetGame(); - - printf("S_Init: Setting up sound.\n"); - S_Init(snd_SfxVolume /* *8 */, snd_MusicVolume /* *8*/); - - printf("HU_Init: Setting up heads up display.\n"); - HU_Init(); - - printf("ST_Init: Init status bar.\n"); - ST_Init(); - - // start the apropriate game based on parms - p = arguments::has("-record"); - - if (p && p < arguments::count() - 1) { - G_RecordDemo(arguments::at(p + 1)); - autostart = true; - } - - p = arguments::has("-playdemo"); - if (p && p < arguments::count() - 1) { - singledemo = true; // quit after one demo - G_DeferedPlayDemo(arguments::at(p + 1)); - D_DoomLoop(); // never returns - } + M_Init(); - p = arguments::has("-timedemo"); - if (p && p < arguments::count() - 1) { - G_TimeDemo(arguments::at(p + 1)); - D_DoomLoop(); // never returns - } + printf("R_Init: Init DOOM refresh daemon - "); + R_Init(); - p = arguments::has("-loadgame"); - if (p && p < arguments::count() - 1) { - file = std::format("{}{}.dsg",SAVEGAMENAME,arguments::at(p+1)[0]); - G_LoadGame(file); - } + printf("\nP_Init: Init Playloop state.\n"); + P_Init(); - if (gameaction != gameaction_t::ga_loadgame) { - if (autostart || netgame) - G_InitNew(startskill, startepisode, startmap); - else - D_StartTitle(); // start up intro loop - } + I_InitSound(); + + printf("I_Init: Setting up machine state.\n"); + I_Init(); + + printf("D_CheckNetGame: Checking network game status.\n"); + D_CheckNetGame(); + + printf("S_Init: Setting up sound.\n"); + S_Init(snd_SfxVolume /* *8 */, snd_MusicVolume /* *8*/); - D_DoomLoop(); // never returns + printf("HU_Init: Setting up heads up display.\n"); + HU_Init(); + + printf("ST_Init: Init status bar.\n"); + ST_Init(); + + // start the apropriate game based on parms + p = arguments::has("-record"); + + if (p && p < arguments::count() - 1) + { + G_RecordDemo(arguments::at(p + 1)); + autostart = true; + } + + p = arguments::has("-playdemo"); + if (p && p < arguments::count() - 1) + { + singledemo = true; // quit after one demo + G_DeferedPlayDemo(arguments::at(p + 1)); + D_DoomLoop(); // never returns + } + + p = arguments::has("-timedemo"); + if (p && p < arguments::count() - 1) + { + G_TimeDemo(arguments::at(p + 1)); + D_DoomLoop(); // never returns + } + + p = arguments::has("-loadgame"); + if (p && p < arguments::count() - 1) + { + file = std::format("{}{}.dsg", SAVEGAMENAME, arguments::at(p + 1)[0]); + G_LoadGame(file); + } + + if (gameaction != gameaction_t::ga_loadgame) + { + if (autostart || netgame) + G_InitNew(startskill, startepisode, startmap); + else + D_StartTitle(); // start up intro loop + } + + D_DoomLoop(); // never returns } // Main entry point, read arguments and call doom main -export int main(int argc, char **argv) { - arguments::parse( argc, argv ); +export int main(int argc, char **argv) +{ + arguments::parse(argc, argv); - D_DoomMain(); + D_DoomMain(); - return 0; + return 0; } - diff --git a/src/doom/menu.ixx b/src/doom/menu.ixx index f0a5aa5..8039a89 100644 --- a/src/doom/menu.ixx +++ b/src/doom/menu.ixx @@ -108,7 +108,8 @@ int messageLastMenuActive; // timed message = no input from user bool messageNeedsInput; -std::function messageRoutine; +using message_routine = std::function; +message_routine messageRoutine; #define SAVESTRINGSIZE 24 @@ -258,7 +259,7 @@ int M_StringWidth(char *string); int M_StringHeight(char *string); -void M_StartMessage(const std::string &string, std::function routine, +void M_StartMessage(const std::string &string, message_routine routine, bool input); void M_StopMessage(void); @@ -591,9 +592,9 @@ void M_SaveGame(int choice) // char tempstring[80]; -void M_QuickSaveResponse(int ch) +void M_QuickSaveResponse(sf::Keyboard::Key ch) { - if (ch == 'y') + if (ch == sf::Keyboard::Key::Y) { M_DoSave(quickSaveSlot); S_StartSound(NULL, sfx_swtchx); @@ -637,9 +638,9 @@ void M_QuickSave(void) // // M_QuickLoad // -void M_QuickLoadResponse(int ch) +void M_QuickLoadResponse(sf::Keyboard::Key ch) { - if (ch == 'y') + if (ch == sf::Keyboard::Key::Y) { M_LoadSelect(quickSaveSlot); S_StartSound(NULL, sfx_swtchx); @@ -809,9 +810,9 @@ void M_DrawEpisode(void) static_cast(W_CacheLumpName("M_EPISOD"))); } -void M_VerifyNightmare(int ch) +void M_VerifyNightmare(sf::Keyboard::Key ch) { - if (ch != 'y') + if (ch != sf::Keyboard::Key::Y) return; G_DeferedInitNew(static_cast(nightmare), epi + 1, 1); @@ -898,9 +899,9 @@ void M_ChangeMessages(int choice) // // M_EndGame // -void M_EndGameResponse(int ch) +void M_EndGameResponse(sf::Keyboard::Key ch) { - if (ch != 'y') + if (ch != sf::Keyboard::Key::Y) return; currentMenu->lastOn = itemOn; @@ -957,9 +958,9 @@ int quitsounds[8] = {sfx_pldeth, sfx_dmpain, sfx_popain, sfx_slop, int quitsounds2[8] = {sfx_vilact, sfx_getpow, sfx_boscub, sfx_slop, sfx_skeswg, sfx_kntdth, sfx_bspact, sfx_sgtatk}; -void M_QuitResponse(int ch) +void M_QuitResponse(sf::Keyboard::Key ch) { - if (ch != 'y') + if (ch != sf::Keyboard::Key::Y) return; if (!netgame) { @@ -1077,8 +1078,8 @@ void M_DrawSelCell(menu_t *menu, int item) static_cast(W_CacheLumpName("M_CELL2"))); } -void M_StartMessage(const std::string &message, - std::function routine, bool input) +void M_StartMessage(const std::string &message, message_routine routine, + bool input) { messageLastMenuActive = menuactive; messageToPrint = 1; @@ -1332,22 +1333,22 @@ export bool M_Responder(const sf::Event &ev) } // Take care of any messages that need input - // JONNY TODO - // if (messageToPrint) - // { - // if (messageNeedsInput == true && - // !(ch == ' ' || ch == 'n' || ch == 'y' || ch == KEY_ESCAPE)) - // return false; - // - // menuactive = messageLastMenuActive; - // messageToPrint = 0; - // if (messageRoutine) - // messageRoutine(ch); - // - // menuactive = false; - // S_StartSound(NULL,sfx_swtchx); - // return true; - // } + if (messageToPrint) + { + if (messageNeedsInput == true && + !(key == sf::Keyboard::Key::Space || key == sf::Keyboard::Key::N || + key == sf::Keyboard::Key::Y || key == sf::Keyboard::Key::Escape)) + return false; + + menuactive = messageLastMenuActive; + messageToPrint = 0; + if (messageRoutine) + messageRoutine(key); + + menuactive = false; + S_StartSound(NULL, sfx_swtchx); + return true; + } // F-Keys if (!menuactive) diff --git a/src/doom/wad.ixx b/src/doom/wad.ixx index 626baf1..0819331 100644 --- a/src/doom/wad.ixx +++ b/src/doom/wad.ixx @@ -39,37 +39,41 @@ import system; // // TYPES // -struct wadinfo_t { - // Should be "IWAD" or "PWAD". - char identification[4]; - int32_t numlumps; - int32_t infotableofs; +struct wadinfo_t +{ + // Should be "IWAD" or "PWAD". + char identification[4]; + int32_t numlumps; + int32_t infotableofs; }; -typedef struct { - int32_t filepos; - int32_t size; - std::array name; +typedef struct +{ + int32_t filepos; + int32_t size; + std::array name; } filelump_t; // // WADFILE I/O related stuff. // -struct lumpinfo_t { - char name[8] = {}; - int32_t handle = {}; - int32_t position = {}; - int32_t size = {}; +struct lumpinfo_t +{ + char name[8] = {}; + int32_t handle = {}; + int32_t position = {}; + int32_t size = {}; }; -typedef struct memblock_s { - int size; // including the header and possibly tiny fragments - void **user; // NULL if a free block - int tag; // purgelevel - int id; // should be ZONEID - struct memblock_s *next; - struct memblock_s *prev; +typedef struct memblock_s +{ + int size; // including the header and possibly tiny fragments + void **user; // NULL if a free block + int tag; // purgelevel + int id; // should be ZONEID + struct memblock_s *next; + struct memblock_s *prev; } memblock_t; // @@ -85,26 +89,29 @@ std::vector wadfiles; #define strcmpi strcasecmp -void ExtractFileBase(const char *path, char *dest) { - int length; +void ExtractFileBase(const char *path, char *dest) +{ + int length; - const char *src = path + strlen(path) - 1; + const char *src = path + strlen(path) - 1; - // back up until a \ or the start - while (src != path && *(src - 1) != '\\' && *(src - 1) != '/') { - src--; - } + // back up until a \ or the start + while (src != path && *(src - 1) != '\\' && *(src - 1) != '/') + { + src--; + } - // copy up to eight characters - memset(dest, 0, 8); - length = 0; + // copy up to eight characters + memset(dest, 0, 8); + length = 0; - while (*src && *src != '.') { - if (++length == 9) - I_Error("Filename base of %s >8 chars", path); + while (*src && *src != '.') + { + if (++length == 9) + I_Error("Filename base of %s >8 chars", path); - *dest++ = toupper((int)*src++); - } + *dest++ = toupper((int)*src++); + } } // @@ -127,79 +134,92 @@ void ExtractFileBase(const char *path, char *dest) { size_t reloadlump; std::filesystem::path reloadpath; -void W_AddFile(const std::filesystem::path &filepath) { - if (filepath.empty()) { - printf("Cannot add empty file path\n"); - return; - } - - if (!std::filesystem::exists(filepath)) { - printf("File not found: %s\n", filepath.string().c_str()); - return; - } - - auto filename = filepath.filename(); - - wadinfo_t header; - int length; - std::vector fileinfo; - filelump_t singleinfo{}; - - // open the file and add to directory - - // handle reload indicator. - if (filename.string()[0] == '~') { - filename = filename.string().substr(1); - reloadpath = filepath; - reloadlump = lumpinfo.size(); - } - - wadfiles.emplace_back(filepath.string(), std::ios::binary); - if (!wadfiles.back().is_open()) { - spdlog::error(" couldn't open {}", filepath.string()); - wadfiles.pop_back(); - return; - } - - spdlog::info(" adding {}", filename.string()); - - if (filename.extension() != ".wad") { - // single lump file - fileinfo = {singleinfo}; - singleinfo.filepos = 0; - singleinfo.size = static_cast(std::filesystem::file_size(filepath)); - std::copy(filename.string().begin(), filename.string().end(), - singleinfo.name.begin()); - lumpinfo.emplace_back(); - } else { - // WAD file - wadfiles.back().read(reinterpret_cast(&header), sizeof(header)); - if (strncmp(header.identification, "IWAD", 4)) { - // Homebrew levels? - if (strncmp(header.identification, "PWAD", 4)) { - I_Error("Wad file {} doesn't have or PWAD id\n", filename.string()); - } - - // ???modifiedgame = true; +void W_AddFile(const std::filesystem::path &filepath) +{ + if (filepath.empty()) + { + printf("Cannot add empty file path\n"); + return; + } + + if (!std::filesystem::exists(filepath)) + { + printf("File not found: %s\n", filepath.string().c_str()); + return; + } + + auto filename = filepath.filename(); + + wadinfo_t header; + int length; + std::vector fileinfo; + filelump_t singleinfo{}; + + // open the file and add to directory + + // handle reload indicator. + if (filename.string()[0] == '~') + { + filename = filename.string().substr(1); + reloadpath = filepath; + reloadlump = lumpinfo.size(); + } + + wadfiles.emplace_back(filepath.string(), std::ios::binary); + if (!wadfiles.back().is_open()) + { + spdlog::error(" couldn't open {}", filepath.string()); + wadfiles.pop_back(); + return; + } + + spdlog::info(" adding {}", filename.string()); + + if (filename.extension() != ".wad") + { + // single lump file + fileinfo = {singleinfo}; + singleinfo.filepos = 0; + singleinfo.size = + static_cast(std::filesystem::file_size(filepath)); + std::copy(filename.string().begin(), filename.string().end(), + singleinfo.name.begin()); + lumpinfo.emplace_back(); + } + else + { + // WAD file + wadfiles.back().read(reinterpret_cast(&header), sizeof(header)); + if (strncmp(header.identification, "IWAD", 4)) + { + // Homebrew levels? + if (strncmp(header.identification, "PWAD", 4)) + { + I_Error("Wad file {} doesn't have or PWAD id\n", + filename.string()); + } + + // ???modifiedgame = true; + } + header.numlumps = header.numlumps; + header.infotableofs = header.infotableofs; + length = header.numlumps * sizeof(filelump_t); + fileinfo.resize(header.numlumps); + wadfiles.back().seekg(header.infotableofs, std::ios::beg); + wadfiles.back().read(reinterpret_cast(fileinfo.data()), length); + lumpinfo.reserve(lumpinfo.size() + header.numlumps); + } + + for (auto i = 0; i < header.numlumps; ++i) + { + const auto fileIndex = reloadpath.empty() ? wadfiles.size() - 1 : -1; + lumpinfo.emplace_back(); + std::copy(fileinfo[i].name.begin(), fileinfo[i].name.end(), + lumpinfo.back().name); + lumpinfo.back().handle = static_cast(fileIndex); + lumpinfo.back().position = fileinfo[i].filepos; + lumpinfo.back().size = fileinfo[i].size; } - header.numlumps = header.numlumps; - header.infotableofs = header.infotableofs; - length = header.numlumps * sizeof(filelump_t); - fileinfo.resize(header.numlumps); - wadfiles.back().seekg(header.infotableofs, std::ios::beg); - wadfiles.back().read(reinterpret_cast(fileinfo.data()), length); - lumpinfo.reserve(lumpinfo.size() + header.numlumps); - } - - for (auto i = 0; i < header.numlumps; ++i) { - const auto fileIndex = reloadpath.empty() ? wadfiles.size() - 1 : -1; - lumpinfo.emplace_back(); - std::copy(fileinfo[i].name.begin(), fileinfo[i].name.end(), - lumpinfo.back().name); - lumpinfo.back().handle = static_cast(fileIndex); - lumpinfo.back().position = fileinfo[i].filepos; - lumpinfo.back().size = fileinfo[i].size; - } } // @@ -207,41 +227,43 @@ void W_AddFile(const std::filesystem::path &filepath) { // Flushes any of the reloadable lumps in memory // and reloads the directory. // -export void W_Reload(void) { - int lumpcount{}; - lumpinfo_t *lump_p; - filelump_t *fileinfo{}; - - if (reloadpath.empty()) - return; - - // JONNY TODO - // if ( (handle = open (reloadname,O_RDONLY | O_BINARY)) == -1) - // I_Error ("W_Reload: couldn't open %s",reloadname); - - // JONNY TODO - // read (handle, &header, sizeof(header)); - // lumpcount = header.numlumps; - // header.infotableofs = header.infotableofs; - // length = lumpcount*sizeof(filelump_t); - // fileinfo = alloca (length); - // lseek (handle, header.infotableofs, SEEK_SET); - // read (handle, fileinfo, length); - - // Fill in lumpinfo - lump_p = &lumpinfo[reloadlump]; - - for (auto i = reloadlump; i < reloadlump + lumpcount; - i++, lump_p++, fileinfo++) { - if (lumpcache[i]) - free(lumpcache[i]); - - lump_p->position = fileinfo->filepos; - lump_p->size = fileinfo->size; - } - - // JONNY TODO - // close (handle); +export void W_Reload(void) +{ + int lumpcount{}; + lumpinfo_t *lump_p; + filelump_t *fileinfo{}; + + if (reloadpath.empty()) + return; + + // JONNY TODO + // if ( (handle = open (reloadname,O_RDONLY | O_BINARY)) == -1) + // I_Error ("W_Reload: couldn't open %s",reloadname); + + // JONNY TODO + // read (handle, &header, sizeof(header)); + // lumpcount = header.numlumps; + // header.infotableofs = header.infotableofs; + // length = lumpcount*sizeof(filelump_t); + // fileinfo = alloca (length); + // lseek (handle, header.infotableofs, SEEK_SET); + // read (handle, fileinfo, length); + + // Fill in lumpinfo + lump_p = &lumpinfo[reloadlump]; + + for (auto i = reloadlump; i < reloadlump + lumpcount; + i++, lump_p++, fileinfo++) + { + if (lumpcache[i]) + free(lumpcache[i]); + + lump_p->position = fileinfo->filepos; + lump_p->size = fileinfo->size; + } + + // JONNY TODO + // close (handle); } // @@ -257,29 +279,33 @@ export void W_Reload(void) { // The name searcher looks backwards, so a later file // does override all earlier ones. // -export void W_InitMultipleFiles(std::vector &filenames) { - // open all the files, load headers, and count lumps - lumpinfo.clear(); +export void W_InitMultipleFiles(std::vector &filenames) +{ + // open all the files, load headers, and count lumps + lumpinfo.clear(); - for (const auto &name : filenames) { - W_AddFile(name); - } + for (const auto &name : filenames) + { + W_AddFile(name); + } - if (lumpinfo.empty()) { - I_Error("W_InitFiles: no files found"); - } + if (lumpinfo.empty()) + { + I_Error("W_InitFiles: no files found"); + } - // set up caching - lumpcache.resize(lumpinfo.size()); + // set up caching + lumpcache.resize(lumpinfo.size()); } // // W_InitFile // Just initialize from a single file. // -void W_InitFile(std::string filename) { - std::vector names{filename}; - W_InitMultipleFiles(names); +void W_InitFile(std::string filename) +{ + std::vector names{filename}; + W_InitMultipleFiles(names); } // @@ -287,46 +313,53 @@ void W_InitFile(std::string filename) { // Returns -1 if name not found. // -export int W_CheckNumForName(const std::string &name) { - // scan backwards so patch lump files take precedence - auto upper_name = name; - std::transform(std::begin(upper_name), std::end(upper_name), - std::begin(upper_name), toupper); - for (auto lump = lumpinfo.rbegin(); lump != lumpinfo.rend(); ++lump) { - if (lump->name == upper_name) { - return static_cast(std::distance(lumpinfo.begin(), lump.base()) - 1); +export int W_CheckNumForName(const std::string &name) +{ + // scan backwards so patch lump files take precedence + auto upper_name = name; + std::transform(std::begin(upper_name), std::end(upper_name), + std::begin(upper_name), toupper); + for (auto lump = lumpinfo.rbegin(); lump != lumpinfo.rend(); ++lump) + { + if (lump->name == upper_name) + { + return static_cast( + std::distance(lumpinfo.begin(), lump.base()) - 1); + } } - } - // TFB. Not found. - return -1; + // TFB. Not found. + return -1; } // // W_GetNumForName // Calls W_CheckNumForName, but bombs out if not found. // -export int W_GetNumForName(const std::string &name) { - int i; +export int W_GetNumForName(const std::string &name) +{ + int i; - i = W_CheckNumForName(name); + i = W_CheckNumForName(name); - if (i == -1) - I_Error("W_GetNumForName: {} not found!", name); + if (i == -1) + I_Error("W_GetNumForName: {} not found!", name); - return i; + return i; } // // W_LumpLength // Returns the buffer size needed to load the given lump. // -export int W_LumpLength(int lump) { - if (lump >= lumpinfo.size()) { - I_Error("W_LumpLength: {} out of bounds", lump); - } +export int W_LumpLength(int lump) +{ + if (lump >= lumpinfo.size()) + { + I_Error("W_LumpLength: {} out of bounds", lump); + } - return lumpinfo[lump].size; + return lumpinfo[lump].size; } // @@ -334,68 +367,84 @@ export int W_LumpLength(int lump) { // Loads the lump into the given buffer, // which must be >= W_LumpLength(). // -export void W_ReadLump(int lump, void *dest) { - - if (lump >= lumpinfo.size()) { - I_Error("W_ReadLump: {} out of bounds", lump); - } - - const auto &l = lumpinfo[lump]; +export void W_ReadLump(int lump, void *dest) +{ - // ??? I_BeginRead (); - - if (l.handle == -1) { - // reloadable file, so use open / read / close - if (std::ifstream file{reloadpath.c_str(), std::ios::binary}; - !file.is_open()) { - I_Error("W_ReadLump: couldn't open {}", reloadpath.string()); - } else { - file.seekg(l.position, std::ios::beg); - file.read(reinterpret_cast(dest), l.size); - - if (!file) { - I_Error("W_ReadLump: only read {} of {} on lump {}", file.gcount(), - l.size, lump); - } + if (lump >= lumpinfo.size()) + { + I_Error("W_ReadLump: {} out of bounds", lump); } - } else { - auto &file = wadfiles[l.handle]; - file.seekg(l.position, std::ios::beg); - file.read(reinterpret_cast(dest), l.size); - - if (!file) { - I_Error("W_ReadLump: only read {} of {} on lump {}", file.gcount(), - l.size, lump); + const auto &l = lumpinfo[lump]; + + // ??? I_BeginRead (); + + if (l.handle == -1) + { + // reloadable file, so use open / read / close + if (std::ifstream file{reloadpath.c_str(), std::ios::binary}; + !file.is_open()) + { + I_Error("W_ReadLump: couldn't open {}", reloadpath.string()); + } + else + { + file.seekg(l.position, std::ios::beg); + file.read(reinterpret_cast(dest), l.size); + + if (!file) + { + I_Error("W_ReadLump: only read {} of {} on lump {}", + file.gcount(), l.size, lump); + } + } + } + else + { + auto &file = wadfiles[l.handle]; + + file.seekg(l.position, std::ios::beg); + file.read(reinterpret_cast(dest), l.size); + + if (!file) + { + I_Error("W_ReadLump: only read {} of {} on lump {}", file.gcount(), + l.size, lump); + } } - } } // // W_CacheLumpNum // -export void *W_CacheLumpNum(uint32_t lump) { - if (lump >= lumpinfo.size()) { - I_Error("W_CacheLumpNum: {} out of bounds", lump); - } +export void *W_CacheLumpNum(uint32_t lump) +{ + if (lump >= lumpinfo.size()) + { + I_Error("W_CacheLumpNum: {} out of bounds", lump); + } - if (!lumpcache[lump]) { - // read the lump in + if (!lumpcache[lump]) + { + // read the lump in - // printf ("cache miss on lump {}\n",lump); - const auto size = W_LumpLength(lump); - lumpcache[lump] = static_cast(malloc(size)); - W_ReadLump(lump, lumpcache[lump]); - } else { - // printf ("cache hit on lump {}\n",lump); - } + // printf ("cache miss on lump {}\n",lump); + const auto size = W_LumpLength(lump); + lumpcache[lump] = static_cast(malloc(size)); + W_ReadLump(lump, lumpcache[lump]); + } + else + { + // printf ("cache hit on lump {}\n",lump); + } - return lumpcache[lump]; + return lumpcache[lump]; } // // W_CacheLumpName // -export void *W_CacheLumpName(const std::string &name) { - return W_CacheLumpNum(W_GetNumForName(name)); +export void *W_CacheLumpName(const std::string &name) +{ + return W_CacheLumpNum(W_GetNumForName(name)); } \ No newline at end of file diff --git a/src/engine/system.ixx b/src/engine/system.ixx index bb17fb4..82d99c6 100644 --- a/src/engine/system.ixx +++ b/src/engine/system.ixx @@ -18,8 +18,8 @@ module; #include "i_video.h" #include #include -#include #include +#include // For debug break on error #if WIN32 @@ -36,70 +36,74 @@ import engine; // I_GetTime // returns time in 1/70th second tics // -export int I_GetTime( void ) { - using namespace std::chrono; - using tic = duration>; - const auto now = steady_clock::now(); - static const auto basetime = now; - const auto tics = duration_cast(now - basetime).count(); - return tics; +export int I_GetTime(void) +{ + using namespace std::chrono; + using tic = duration>; + const auto now = steady_clock::now(); + static const auto basetime = now; + const auto tics = duration_cast(now - basetime).count(); + return tics; } // // I_Error // export template -void I_Error( spdlog::format_string_t fmt, Args &&...args ) { - spdlog::error( fmt, std::forward( args )... ); +void I_Error(spdlog::format_string_t fmt, Args &&...args) +{ + spdlog::error(fmt, std::forward(args)...); #if WIN32 - DebugBreak(); + DebugBreak(); #else - raise( SIGTRAP ); + raise(SIGTRAP); #endif - exit( -1 ); + exit(-1); } // // I_Debug // export template -void I_Log( spdlog::format_string_t fmt, Args &&...args ) { - spdlog::info( fmt, std::forward( args )... ); +void I_Log(spdlog::format_string_t fmt, Args &&...args) +{ + spdlog::info(fmt, std::forward(args)...); } // // I_Debug // export template -void I_Debug( spdlog::format_string_t fmt, Args &&...args ) { - spdlog::debug( fmt, std::forward( args )... ); +void I_Debug(spdlog::format_string_t fmt, Args &&...args) +{ + spdlog::debug(fmt, std::forward(args)...); } // // I_Init // -export void I_Init( void ) { - //I_InitSound(); - I_InitGraphics(); +export void I_Init(void) +{ + // I_InitSound(); + I_InitGraphics(); } // // I_Quit // -export void I_Quit( void ) { - // TODO JONNY circular dependency - //D_QuitNetGame(); - //I_ShutdownSound(); - //I_ShutdownMusic(); - // @TODO JONNY circular dependency - //M_SaveDefaults(); - exit( 0 ); +export void I_Quit(void) +{ + // TODO JONNY circular dependency + // D_QuitNetGame(); + // I_ShutdownSound(); + // I_ShutdownMusic(); + // @TODO JONNY circular dependency + // M_SaveDefaults(); + exit(0); } - - // // DEFAULTS // @@ -121,58 +125,58 @@ export int numChannels = 3; extern char *chat_macros[]; -std::map defaults = { - {"mouse_sensitivity", mouseSensitivity}, - //{"sfx_volume", &snd_SfxVolume}, - //{"music_volume", &snd_MusicVolume}, - {"show_messages", showMessages}, - //{"key_right", &key_right}, - //{"key_left", &key_left}, - //{"key_up", &key_up}, - //{"key_down", &key_down}, - //{"key_strafeleft", &key_strafeleft}, - //{"key_straferight", &key_straferight}, - //{"key_fire", &key_fire}, - //{"key_use", &key_use}, - //{"key_strafe", &key_strafe}, - //{"key_speed", &key_speed}, - //{"mouseb_fire", &mousebfire, 0}, - //{"mouseb_strafe", &mousebstrafe, 1}, - //{"mouseb_forward", &mousebforward, 2}, - - //{"use_joystick", &usejoystick, 0}, - //{"joyb_fire", &joybfire, 0}, - //{"joyb_strafe", &joybstrafe, 1}, - //{"joyb_use", &joybuse, 3}, - //{"joyb_speed", &joybspeed, 2}, - - {"screenblocks", screenblocks}, - {"detaillevel", detailLevel}, - - {"snd_channels", numChannels}, - - //{"usegamma", usegamma}, - /* - {"chatmacro0", (int *) &chat_macros[0], - reinterpret_cast(HUSTR_CHATMACRO0) }, - {"chatmacro1", (int *) &chat_macros[1], - reinterpret_cast(HUSTR_CHATMACRO1) }, - {"chatmacro2", (int *) &chat_macros[2], - reinterpret_cast(HUSTR_CHATMACRO2) }, - {"chatmacro3", (int *) &chat_macros[3], - reinterpret_cast(HUSTR_CHATMACRO3) }, - {"chatmacro4", (int *) &chat_macros[4], - reinterpret_cast(HUSTR_CHATMACRO4) }, - {"chatmacro5", (int *) &chat_macros[5], - reinterpret_cast(HUSTR_CHATMACRO5) }, - {"chatmacro6", (int *) &chat_macros[6], - reinterpret_cast(HUSTR_CHATMACRO6) }, - {"chatmacro7", (int *) &chat_macros[7], - reinterpret_cast(HUSTR_CHATMACRO7) }, - {"chatmacro8", (int *) &chat_macros[8], - reinterpret_cast(HUSTR_CHATMACRO8) }, - {"chatmacro9", (int *) &chat_macros[9], - reinterpret_cast(HUSTR_CHATMACRO9) }*/ +std::map defaults = { + {"mouse_sensitivity", mouseSensitivity}, + //{"sfx_volume", &snd_SfxVolume}, + //{"music_volume", &snd_MusicVolume}, + {"show_messages", showMessages}, + //{"key_right", &key_right}, + //{"key_left", &key_left}, + //{"key_up", &key_up}, + //{"key_down", &key_down}, + //{"key_strafeleft", &key_strafeleft}, + //{"key_straferight", &key_straferight}, + //{"key_fire", &key_fire}, + //{"key_use", &key_use}, + //{"key_strafe", &key_strafe}, + //{"key_speed", &key_speed}, + //{"mouseb_fire", &mousebfire, 0}, + //{"mouseb_strafe", &mousebstrafe, 1}, + //{"mouseb_forward", &mousebforward, 2}, + + //{"use_joystick", &usejoystick, 0}, + //{"joyb_fire", &joybfire, 0}, + //{"joyb_strafe", &joybstrafe, 1}, + //{"joyb_use", &joybuse, 3}, + //{"joyb_speed", &joybspeed, 2}, + + {"screenblocks", screenblocks}, + {"detaillevel", detailLevel}, + + {"snd_channels", numChannels}, + + //{"usegamma", usegamma}, + /* + {"chatmacro0", (int *) &chat_macros[0], + reinterpret_cast(HUSTR_CHATMACRO0) }, + {"chatmacro1", (int *) &chat_macros[1], + reinterpret_cast(HUSTR_CHATMACRO1) }, + {"chatmacro2", (int *) &chat_macros[2], + reinterpret_cast(HUSTR_CHATMACRO2) }, + {"chatmacro3", (int *) &chat_macros[3], + reinterpret_cast(HUSTR_CHATMACRO3) }, + {"chatmacro4", (int *) &chat_macros[4], + reinterpret_cast(HUSTR_CHATMACRO4) }, + {"chatmacro5", (int *) &chat_macros[5], + reinterpret_cast(HUSTR_CHATMACRO5) }, + {"chatmacro6", (int *) &chat_macros[6], + reinterpret_cast(HUSTR_CHATMACRO6) }, + {"chatmacro7", (int *) &chat_macros[7], + reinterpret_cast(HUSTR_CHATMACRO7) }, + {"chatmacro8", (int *) &chat_macros[8], + reinterpret_cast(HUSTR_CHATMACRO8) }, + {"chatmacro9", (int *) &chat_macros[9], + reinterpret_cast(HUSTR_CHATMACRO9) }*/ }; @@ -185,15 +189,16 @@ std::filesystem::path defaults_file_path; // // M_SaveDefaults // -export void M_SaveDefaults( void ) { - std::ofstream file( defaults_file_path ); - if ( file ) - { - for ( const auto& [key, value] : defaults ) - { - file << key << " " << value << std::endl; - } - } +export void M_SaveDefaults(void) +{ + std::ofstream file(defaults_file_path); + if (file) + { + for (const auto &[key, value] : defaults) + { + file << key << " " << value << std::endl; + } + } } // @@ -201,41 +206,45 @@ export void M_SaveDefaults( void ) { // extern std::byte scantokey[128]; -export void M_LoadDefaults( void ) { - - // check for a custom default file - if ( constexpr auto arg = "-config"; arguments::has(arg) ) - { - defaults_file_path = arguments::at(arguments::index_of(arg) + 1); - spdlog::info( "Defaults config set on command line: {}", defaults_file_path.string() ); - } - else if ( const auto home_var = getenv( "HOME" ); home_var ) - { - const std::filesystem::path home_path = home_var; - defaults_file_path = home_path / defaults_file_name; - } - - if ( std::filesystem::exists( defaults_file_path ) ) - { - spdlog::info( "Defaults config found at: {}", defaults_file_path.string() ); - - if ( std::ifstream config( defaults_file_path ); config ) - { - std::string key, value; - while ( config >> key >> value ) - { - spdlog::info( "Read default from config: {} = {}", key, value ); - assert( defaults.contains( key ) ); - defaults.find( key )->second = std::stoi( value ); - } - } - else - { - spdlog::error( "Failed to open config: {}", defaults_file_path.string() ); - } - } - else - { - spdlog::info( "No default config file found" ); - } +export void M_LoadDefaults(void) +{ + + // check for a custom default file + if (constexpr auto arg = "-config"; arguments::has(arg)) + { + defaults_file_path = arguments::at(arguments::index_of(arg) + 1); + spdlog::info("Defaults config set on command line: {}", + defaults_file_path.string()); + } + else if (const auto home_var = getenv("HOME"); home_var) + { + const std::filesystem::path home_path = home_var; + defaults_file_path = home_path / defaults_file_name; + } + + if (std::filesystem::exists(defaults_file_path)) + { + spdlog::info("Defaults config found at: {}", + defaults_file_path.string()); + + if (std::ifstream config(defaults_file_path); config) + { + std::string key, value; + while (config >> key >> value) + { + spdlog::info("Read default from config: {} = {}", key, value); + assert(defaults.contains(key)); + defaults.find(key)->second = std::stoi(value); + } + } + else + { + spdlog::error("Failed to open config: {}", + defaults_file_path.string()); + } + } + else + { + spdlog::info("No default config file found"); + } } \ No newline at end of file