From 5eaa53dcc98d96faa42c1554025b8565a9a81d34 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 24 Nov 2024 17:22:47 +0100 Subject: [PATCH] Backend update from GZDoom. Mainly filesystem cleanup. --- source/CMakeLists.txt | 2 + source/common/2d/wipe.cpp | 160 +++- source/common/audio/music/i_music.cpp | 7 +- source/common/audio/music/i_soundfont.cpp | 8 +- source/common/audio/music/music.cpp | 4 +- source/common/audio/sound/s_sound.cpp | 2 +- source/common/console/c_bind.cpp | 10 +- source/common/console/c_commandline.cpp | 2 +- source/common/console/c_commandline.h | 2 +- source/common/console/c_enginecmds.cpp | 6 +- source/common/cutscenes/movieplayer.cpp | 2 +- source/common/engine/filesys_doom.cpp | 648 ++++++++++++++++ source/common/engine/filesystem.h | 126 +++- source/common/engine/i_net.cpp | 55 +- source/common/engine/i_net.h | 1 + source/common/engine/m_random.cpp | 63 +- source/common/engine/m_random.h | 26 +- source/common/engine/namedef.h | 6 + source/common/engine/sc_man.cpp | 2 +- source/common/engine/serializer.cpp | 16 +- source/common/engine/serializer.h | 2 +- source/common/engine/st_start.h | 2 + source/common/engine/stringtable.cpp | 2 +- source/common/engine/stringtable.h | 2 +- .../common/filesystem/include/fs_filesystem.h | 150 ++-- .../common/filesystem/include/resourcefile.h | 74 +- source/common/filesystem/source/file_7z.cpp | 9 +- .../filesystem/source/file_directory.cpp | 13 +- source/common/filesystem/source/file_grp.cpp | 7 +- source/common/filesystem/source/file_hog.cpp | 7 +- source/common/filesystem/source/file_hog2.cpp | 107 +++ source/common/filesystem/source/file_lump.cpp | 7 +- source/common/filesystem/source/file_mvl.cpp | 6 +- source/common/filesystem/source/file_pak.cpp | 7 +- source/common/filesystem/source/file_rff.cpp | 7 +- source/common/filesystem/source/file_ssi.cpp | 8 +- source/common/filesystem/source/file_wad.cpp | 293 +------- .../common/filesystem/source/file_whres.cpp | 7 +- source/common/filesystem/source/file_zip.cpp | 8 +- .../common/filesystem/source/filesystem.cpp | 706 +++++------------- .../common/filesystem/source/resourcefile.cpp | 55 +- source/common/fonts/v_font.cpp | 6 +- source/common/menu/menudef.cpp | 2 +- source/common/models/model.cpp | 12 +- source/common/models/models_ue1.cpp | 6 +- source/common/models/voxels.cpp | 2 +- .../common/platform/posix/cocoa/st_console.h | 1 + .../common/platform/posix/cocoa/st_console.mm | 5 + .../common/platform/posix/cocoa/st_start.mm | 5 + source/common/platform/posix/i_system.h | 11 - source/common/platform/posix/sdl/i_system.cpp | 2 +- source/common/platform/posix/sdl/st_start.cpp | 6 + source/common/platform/win32/i_main.cpp | 55 +- source/common/platform/win32/i_mainwindow.cpp | 5 + source/common/platform/win32/i_mainwindow.h | 1 + source/common/platform/win32/i_system.cpp | 4 +- source/common/platform/win32/st_start.cpp | 5 + source/common/rendering/gl/gl_shader.cpp | 16 +- .../common/rendering/gl/gl_shaderprogram.cpp | 2 +- source/common/rendering/gles/gles_shader.cpp | 14 +- .../rendering/gles/gles_shaderprogram.cpp | 2 +- source/common/rendering/r_videoscale.cpp | 2 +- .../rendering/vulkan/shaders/vk_ppshader.cpp | 2 +- .../rendering/vulkan/shaders/vk_shader.cpp | 6 +- source/common/scripting/backend/codegen.cpp | 47 +- source/common/scripting/backend/vmbuilder.cpp | 16 +- source/common/scripting/core/types.cpp | 2 +- .../common/scripting/frontend/zcc_compile.cpp | 5 + .../common/scripting/frontend/zcc_parser.cpp | 6 +- .../common/scripting/interface/vmnatives.cpp | 14 +- source/common/startscreen/endoom.cpp | 4 +- .../startscreen/startscreen_generic.cpp | 2 +- .../common/startscreen/startscreen_hexen.cpp | 6 +- .../common/startscreen/startscreen_strife.cpp | 2 +- source/common/textures/formats/pngtexture.cpp | 16 +- source/common/textures/gametexture.cpp | 10 +- source/common/textures/gametexture.h | 4 + source/common/textures/texturemanager.cpp | 52 +- source/common/utility/palette.cpp | 6 +- source/common/utility/tarray.h | 2 +- source/common/widgets/netstartwindow.cpp | 6 + source/common/widgets/netstartwindow.h | 1 + source/core/defparser.cpp | 2 +- source/core/g_mapinfo.cpp | 4 +- source/core/gamecontrol.cpp | 6 +- source/core/initfs.cpp | 32 +- source/core/mapinfo.cpp | 4 +- source/core/menu/usermap.cpp | 12 +- source/core/music/s_advsound.cpp | 2 +- source/core/r_data/gldefs.cpp | 4 +- source/core/raze_music.cpp | 4 +- source/core/raze_sound.h | 2 +- source/core/savegamehelp.cpp | 8 +- source/core/statistics.cpp | 2 +- source/games/blood/src/barf.cpp | 2 +- source/games/blood/src/levels.cpp | 10 +- source/games/blood/src/qav.h | 2 +- source/games/blood/src/sound.cpp | 6 +- source/games/duke/src/gamedef.cpp | 12 +- source/games/duke/src/sounds.cpp | 2 +- source/launcher/launcherwindow.cpp | 14 +- source/launcher/launcherwindow.h | 4 +- source/launcher/playgamepage.cpp | 2 - source/launcher/settingspage.cpp | 2 +- source/launcher/settingspage.h | 1 + .../static/zscript/games/blood/ui/screens.zs | 4 +- .../zscript/games/exhumed/ui/screens.zs | 2 +- wadsrc/static/zscript/games/usermapmenu.zs | 2 +- 108 files changed, 1835 insertions(+), 1312 deletions(-) create mode 100644 source/common/engine/filesys_doom.cpp create mode 100644 source/common/filesystem/source/file_hog2.cpp diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 68096178d94..9e61c90e7cb 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1141,6 +1141,7 @@ set (PCH_SOURCES common/engine/cycler.cpp common/engine/d_event.cpp common/engine/date.cpp + common/engine/filesys_doom.cpp common/engine/stats.cpp common/engine/sc_man.cpp common/engine/palettecontainer.cpp @@ -1288,6 +1289,7 @@ set( GAME_SOURCES common/filesystem/source/file_whres.cpp common/filesystem/source/file_ssi.cpp common/filesystem/source/file_hog.cpp + common/filesystem/source/file_hog2.cpp common/filesystem/source/file_mvl.cpp common/filesystem/source/file_directory.cpp common/filesystem/source/resourcefile.cpp diff --git a/source/common/2d/wipe.cpp b/source/common/2d/wipe.cpp index cc57ca29f31..c829f7a8d10 100755 --- a/source/common/2d/wipe.cpp +++ b/source/common/2d/wipe.cpp @@ -43,6 +43,8 @@ #include "s_soundinternal.h" #include "i_time.h" +EXTERN_CVAR(Bool, cl_capfps) + class FBurnTexture : public FTexture { TArray WorkBuffer; @@ -163,6 +165,8 @@ class Wiper public: virtual ~Wiper(); virtual bool Run(int ticks) = 0; + virtual bool RunInterpolated(double ticks) { return true; }; + virtual bool Interpolatable() { return false; } virtual void SetTextures(FGameTexture* startscreen, FGameTexture* endscreen) { startScreen = startscreen; @@ -177,9 +181,11 @@ class Wiper_Crossfade : public Wiper { public: bool Run(int ticks) override; + bool RunInterpolated(double ticks) override; + bool Interpolatable() override { return true; } private: - int Clock = 0; + float Clock = 0; }; class Wiper_Melt : public Wiper @@ -187,10 +193,12 @@ class Wiper_Melt : public Wiper public: Wiper_Melt(); bool Run(int ticks) override; + bool RunInterpolated(double ticks) override; + bool Interpolatable() override { return true; } private: enum { WIDTH = 320, HEIGHT = 200 }; - int y[WIDTH]; + double y[WIDTH]; }; class Wiper_Burn : public Wiper @@ -268,7 +276,23 @@ bool Wiper_Crossfade::Run(int ticks) Clock += ticks; DrawTexture(twod, startScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE); DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, DTA_Alpha, clamp(Clock / 32.f, 0.f, 1.f), TAG_DONE); - return Clock >= 32; + return Clock >= 32.; +} + +//========================================================================== +// +// OpenGLFrameBuffer :: Wiper_Crossfade :: Run +// +// Fades the old screen into the new one over 32 ticks. +// +//========================================================================== + +bool Wiper_Crossfade::RunInterpolated(double ticks) +{ + Clock += ticks; + DrawTexture(twod, startScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE); + DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, DTA_Alpha, clamp(Clock / 32.f, 0.f, 1.f), TAG_DONE); + return Clock >= 32.; } //========================================================================== @@ -282,7 +306,7 @@ Wiper_Melt::Wiper_Melt() y[0] = -(M_Random() & 15); for (int i = 1; i < WIDTH; ++i) { - y[i] = clamp(y[i-1] + (M_Random() % 3) - 1, -15, 0); + y[i] = clamp(y[i-1] + (double)(M_Random() % 3) - 1., -15., 0.); } } @@ -307,25 +331,25 @@ bool Wiper_Melt::Run(int ticks) { if (y[i] < HEIGHT) { - if (y[i] < 0) - y[i]++; - else if (y[i] < 16) - y[i] += y[i] + 1; + if (y[i] < 0.) + y[i] = y[i] + 1.; + else if (y[i] < 16.) + y[i] += y[i] + 1.; else - y[i] = min(y[i] + 8, HEIGHT); + y[i] = min(y[i] + 8., HEIGHT); done = false; } if (ticks == 0) { struct { int32_t x; - int32_t y; + double y; } dpt; struct { int32_t left; - int32_t top; + double top; int32_t right; - int32_t bottom; + double bottom; } rect; // Only draw for the final tick. @@ -333,7 +357,7 @@ bool Wiper_Melt::Run(int ticks) int w = startScreen->GetTexelWidth(); int h = startScreen->GetTexelHeight(); dpt.x = i * w / WIDTH; - dpt.y = max(0, y[i] * h / HEIGHT); + dpt.y = max(0., y[i] * (double)h / (double)HEIGHT); rect.left = dpt.x; rect.top = 0; rect.right = (i + 1) * w / WIDTH; @@ -348,6 +372,77 @@ bool Wiper_Melt::Run(int ticks) return done; } +//========================================================================== +// +// Wiper_Melt :: RunInterpolated +// +// Melts the old screen into the new one over 32 ticks (interpolated). +// +//========================================================================== + +bool Wiper_Melt::RunInterpolated(double ticks) +{ + bool done = false; + DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE); + + // Copy the old screen in vertical strips on top of the new one. + while (ticks > 0.) + { + done = true; + for (int i = 0; i < WIDTH; i++) + { + if (y[i] < (double)HEIGHT) + { + if (ticks > 0. && ticks < 1.) + { + if (y[i] < 0) + y[i] += ticks; + else if (y[i] < 16) + y[i] += (y[i] + 1) * ticks; + else + y[i] = min(y[i] + (8 * ticks), (double)HEIGHT); + } + else if (y[i] < 0.) + y[i] = y[i] + 1.; + else if (y[i] < 16.) + y[i] += y[i] + 1.; + else + y[i] = min(y[i] + 8., HEIGHT); + done = false; + } + } + ticks -= 1.; + } + for (int i = 0; i < WIDTH; i++) + { + struct { + int32_t x; + double y; + } dpt; + struct { + int32_t left; + double top; + int32_t right; + double bottom; + } rect; + + // Only draw for the final tick. + int w = startScreen->GetTexelWidth(); + double h = startScreen->GetTexelHeight(); + dpt.x = i * w / WIDTH; + dpt.y = max(0., y[i] * (double)h / (double)HEIGHT); + rect.left = dpt.x; + rect.top = 0; + rect.right = (i + 1) * w / WIDTH; + rect.bottom = h - dpt.y; + if (rect.bottom > rect.top) + { + DrawTexture(twod, startScreen, 0, dpt.y, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_ClipLeft, rect.left, DTA_ClipRight, rect.right, DTA_Masked, false, TAG_DONE); + } + } + return done; +} + //========================================================================== // // OpenGLFrameBuffer :: Wiper_Burn Constructor @@ -423,6 +518,7 @@ void PerformWipe(FTexture* startimg, FTexture* endimg, int wipe_type, bool stops { // wipe update uint64_t wipestart, nowtime, diff; + double diff_frac; bool done; GSnd->SetSfxPaused(true, 1); @@ -438,20 +534,34 @@ void PerformWipe(FTexture* startimg, FTexture* endimg, int wipe_type, bool stops do { - do + if (wiper->Interpolatable() && !cl_capfps) { - I_WaitVBL(2); nowtime = I_msTime(); - diff = (nowtime - wipestart) * 40 / 1000; // Using 35 here feels too slow. - } while (diff < 1); - wipestart = nowtime; - twod->Begin(screen->GetWidth(), screen->GetHeight()); - done = wiper->Run(1); - if (overlaydrawer) overlaydrawer(); - twod->End(); - screen->Update(); - twod->OnFrameDone(); - + diff_frac = (nowtime - wipestart) * 40. / 1000.; // Using 35 here feels too slow. + wipestart = nowtime; + twod->Begin(screen->GetWidth(), screen->GetHeight()); + done = wiper->RunInterpolated(diff_frac); + if (overlaydrawer) overlaydrawer(); + twod->End(); + screen->Update(); + twod->OnFrameDone(); + } + else + { + do + { + I_WaitVBL(2); + nowtime = I_msTime(); + diff = (nowtime - wipestart) * 40 / 1000; // Using 35 here feels too slow. + } while (diff < 1); + wipestart = nowtime; + twod->Begin(screen->GetWidth(), screen->GetHeight()); + done = wiper->Run(1); + if (overlaydrawer) overlaydrawer(); + twod->End(); + screen->Update(); + twod->OnFrameDone(); + } } while (!done); delete wiper; I_FreezeTime(false); diff --git a/source/common/audio/music/i_music.cpp b/source/common/audio/music/i_music.cpp index d190537d45a..54f66be9ace 100644 --- a/source/common/audio/music/i_music.cpp +++ b/source/common/audio/music/i_music.cpp @@ -53,9 +53,6 @@ #include "s_music.h" #include "filereadermusicinterface.h" -using namespace FileSys; - - void I_InitSoundFonts(); EXTERN_CVAR (Int, snd_samplerate) @@ -188,7 +185,7 @@ static void SetupGenMidi() static void SetupWgOpn() { - int lump = fileSystem.CheckNumForFullName("xg.wopn"); + int lump = fileSystem.FindFile("xg.wopn"); if (lump < 0) { return; @@ -313,7 +310,7 @@ static ZMusic_MidiSource GetMIDISource(const char *fn) if (src.Compare("*") == 0) src = mus_playing.name; auto lump = fileSystem.CheckNumForName(src.GetChars(), ns_music); - if (lump < 0) lump = fileSystem.CheckNumForFullName(src.GetChars()); + if (lump < 0) lump = fileSystem.FindFile(src.GetChars()); if (lump < 0) { Printf("Cannot find MIDI lump %s.\n", src.GetChars()); diff --git a/source/common/audio/music/i_soundfont.cpp b/source/common/audio/music/i_soundfont.cpp index 9737374fc47..3d3a6fd4497 100644 --- a/source/common/audio/music/i_soundfont.cpp +++ b/source/common/audio/music/i_soundfont.cpp @@ -298,7 +298,7 @@ FileReader FPatchSetReader::OpenFile(const char *name) FLumpPatchSetReader::FLumpPatchSetReader(const char *filename) { - mLumpIndex = fileSystem.CheckNumForFullName(filename); + mLumpIndex = fileSystem.FindFile(filename); mBasePath = filename; FixPathSeperator(mBasePath); @@ -314,9 +314,9 @@ FileReader FLumpPatchSetReader::OpenMainConfigFile() FileReader FLumpPatchSetReader::OpenFile(const char *name) { FString path; - if (IsAbsPath(name)) return FileReader(); // no absolute paths in the lump directory. + if (IsAbsPath(name)) return FileReader(); // no absolute paths in the virtual file system. path = mBasePath + name; - auto index = fileSystem.CheckNumForFullName(path.GetChars()); + auto index = fileSystem.FindFile(path.GetChars()); if (index < 0) return FileReader(); return fileSystem.ReopenFileReader(index); } @@ -472,7 +472,7 @@ FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *const name, int a // To avoid clashes this will only be done if the name has the '.cfg' extension. // Sound fonts cannot be loaded this way. const char *p = name + strlen(name) - 4; - if (p > name && !stricmp(p, ".cfg") && fileSystem.CheckNumForFullName(name) >= 0) + if (p > name && !stricmp(p, ".cfg") && fileSystem.FindFile(name) >= 0) { return new FLumpPatchSetReader(name); } diff --git a/source/common/audio/music/music.cpp b/source/common/audio/music/music.cpp index 9664c54585c..3e9202befb4 100644 --- a/source/common/audio/music/music.cpp +++ b/source/common/audio/music/music.cpp @@ -114,7 +114,7 @@ static FileReader OpenMusic(const char* musicname) { int lumpnum; lumpnum = mus_cb.FindMusic(musicname); - if (lumpnum == -1) lumpnum = fileSystem.CheckNumForName(musicname, FileSys::ns_music); + if (lumpnum == -1) lumpnum = fileSystem.CheckNumForName(musicname, ns_music); if (lumpnum == -1) { Printf("Music \"%s\" not found\n", musicname); @@ -143,7 +143,7 @@ bool MusicExists(const char* music_name) { int lumpnum; lumpnum = mus_cb.FindMusic(music_name); - if (lumpnum == -1) lumpnum = fileSystem.CheckNumForName(music_name, FileSys::ns_music); + if (lumpnum == -1) lumpnum = fileSystem.CheckNumForName(music_name, ns_music); if (lumpnum != -1 && fileSystem.FileLength(lumpnum) != 0) return true; } diff --git a/source/common/audio/sound/s_sound.cpp b/source/common/audio/sound/s_sound.cpp index 852d389f5ac..d8ae7fe0017 100644 --- a/source/common/audio/sound/s_sound.cpp +++ b/source/common/audio/sound/s_sound.cpp @@ -61,7 +61,7 @@ enum { DEFAULT_PITCH = 128, }; -static FRandom pr_soundpitch ("SoundPitch"); +static FCRandom pr_soundpitch ("SoundPitch"); SoundEngine* soundEngine; //========================================================================== diff --git a/source/common/console/c_bind.cpp b/source/common/console/c_bind.cpp index fe794c736d6..2d7903298da 100644 --- a/source/common/console/c_bind.cpp +++ b/source/common/console/c_bind.cpp @@ -730,15 +730,15 @@ void ReadBindings(int lump, bool override) void C_SetDefaultKeys(const char* baseconfig) { - auto lump = fileSystem.CheckNumForFullName("engine/commonbinds.txt"); + auto lump = fileSystem.FindFile("engine/commonbinds.txt"); if (lump >= 0) { // Bail out if a mod tries to override this. Main game resources are allowed to do this, though. auto fileno2 = fileSystem.GetFileContainer(lump); - if (fileno2 > fileSystem.GetMaxIwadNum()) + if (fileno2 > fileSystem.GetMaxBaseNum()) { I_FatalError("File %s is overriding core lump %s.", - fileSystem.GetResourceFileFullName(fileno2), "engine/commonbinds.txt"); + fileSystem.GetContainerFullName(fileno2), "engine/commonbinds.txt"); } ReadBindings(lump, true); @@ -748,7 +748,7 @@ void C_SetDefaultKeys(const char* baseconfig) while ((lump = fileSystem.FindLumpFullName(baseconfig, &lastlump)) != -1) { // Read this only from the main game resources. - if (fileSystem.GetFileContainer(lump) <= fileSystem.GetMaxIwadNum()) + if (fileSystem.GetFileContainer(lump) <= fileSystem.GetMaxBaseNum()) ReadBindings(lump, true); } @@ -758,7 +758,7 @@ void C_SetDefaultKeys(const char* baseconfig) // [SW] - We need to check to see the origin of the DEFBINDS... if it // Comes from an IWAD/IPK3/IPK7 allow it to override the users settings... // If it comes from a user mod however, don't. - if (fileSystem.GetFileContainer(lump) > fileSystem.GetMaxIwadNum()) + if (fileSystem.GetFileContainer(lump) > fileSystem.GetMaxBaseNum()) ReadBindings(lump, false); else ReadBindings(lump, true); diff --git a/source/common/console/c_commandline.cpp b/source/common/console/c_commandline.cpp index 4f500ffe668..7fa9d1ff276 100644 --- a/source/common/console/c_commandline.cpp +++ b/source/common/console/c_commandline.cpp @@ -193,7 +193,7 @@ int FCommandLine::argc () return _argc; } -char *FCommandLine::operator[] (int i) +const char *FCommandLine::operator[] (int i) { if (_argv == NULL) { diff --git a/source/common/console/c_commandline.h b/source/common/console/c_commandline.h index dc5466df1cb..4886aa9c717 100644 --- a/source/common/console/c_commandline.h +++ b/source/common/console/c_commandline.h @@ -44,7 +44,7 @@ class FCommandLine FCommandLine (const char *commandline, bool no_escapes = false); ~FCommandLine (); int argc (); - char *operator[] (int i); + const char *operator[] (int i); const char *args () { return cmd; } void Shift(); diff --git a/source/common/console/c_enginecmds.cpp b/source/common/console/c_enginecmds.cpp index d6a2e027e24..8fbee1f20aa 100644 --- a/source/common/console/c_enginecmds.cpp +++ b/source/common/console/c_enginecmds.cpp @@ -233,18 +233,18 @@ CCMD (wdir) if (argv.argc() != 2) wadnum = -1; else { - wadnum = fileSystem.CheckIfResourceFileLoaded (argv[1]); + wadnum = fileSystem.CheckIfContainerLoaded (argv[1]); if (wadnum < 0) { Printf ("%s must be loaded to view its directory.\n", argv[1]); return; } } - for (int i = 0; i < fileSystem.GetNumEntries(); ++i) + for (int i = 0; i < fileSystem.GetFileCount(); ++i) { if (wadnum == -1 || fileSystem.GetFileContainer(i) == wadnum) { - Printf ("%10ld %s\n", fileSystem.FileLength(i), fileSystem.GetFileFullName(i)); + Printf ("%10ld %s\n", fileSystem.FileLength(i), fileSystem.GetFileName(i)); } } } diff --git a/source/common/cutscenes/movieplayer.cpp b/source/common/cutscenes/movieplayer.cpp index a1b04385f61..27d8f727188 100644 --- a/source/common/cutscenes/movieplayer.cpp +++ b/source/common/cutscenes/movieplayer.cpp @@ -508,7 +508,7 @@ class VpxPlayer : public MoviePlayer } if (!MusicStream) { - Printf(PRINT_BOLD, "Failed to decode %s\n", fileSystem.GetFileFullName(soundtrack, false)); + Printf(PRINT_BOLD, "Failed to decode %s\n", fileSystem.GetFileName(soundtrack)); } } animtex.SetSize(AnimTexture::VPX, width, height); diff --git a/source/common/engine/filesys_doom.cpp b/source/common/engine/filesys_doom.cpp new file mode 100644 index 00000000000..b19b99a78b2 --- /dev/null +++ b/source/common/engine/filesys_doom.cpp @@ -0,0 +1,648 @@ +/* +** filesys_doom.cpp +** +** the very special lump name lookup code for Doom's short names. +** Not useful in a generic system. +** +**--------------------------------------------------------------------------- +** Copyright 1998-2016 Randy Heit +** Copyright 2005-2024 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** +*/ + +#include "filesystem.h" +#include "printf.h" + +//========================================================================== +// +// +// +//========================================================================== + +void FileSystem::InitHashChains() +{ + Super::InitHashChains(); + unsigned NumEntries = GetFileCount(); + for (unsigned i = 0; i < (unsigned)NumEntries; i++) + { + files[i].HashFirst = files[i].HashNext = NULL_INDEX; + } + // Now set up the chains + for (unsigned i = 0; i < (unsigned)NumEntries; i++) + { + if (files[i].Namespace == ns_hidden || files[i].ShortName[0] == 0) continue; + unsigned j = FileSys::MakeHash(files[i].ShortName, 8) % NumEntries; + files[i].HashNext = files[j].HashFirst; + files[j].HashFirst = i; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +static void UpperCopy(char* to, const char* from) +{ + int i; + + for (i = 0; i < 8 && from[i]; i++) + to[i] = toupper(from[i]); + for (; i < 8; i++) + to[i] = 0; + to[8] = 0; +} + +//========================================================================== +// +// +// +//========================================================================== + +void FileSystem::SetupName(int fileindex) +{ + const char* name = GetFileName(fileindex); + int containerflags = GetContainerFlags(GetFileContainer(fileindex)); + int lflags = GetFileFlags(fileindex); + + if ((containerflags & wadflags) == wadflags) + { + UpperCopy(files[fileindex].ShortName, name); + } + else if ((lflags & FileSys::RESFF_EMBEDDED) || !*name) + { + files[fileindex].Namespace = ns_hidden; + } + else + { + if (lflags & FileSys::RESFF_FULLPATH) files[fileindex].Flags |= LUMPF_FULLPATH; // copy for easier access in lookup function. + auto slash = strrchr(name, '/'); + auto base = slash ? (slash + 1) : name; + UpperCopy(files[fileindex].ShortName, base); + auto dot = strrchr(files[fileindex].ShortName, '.'); + if (dot) while (*dot) *dot++ = 0; + } +} + + +//========================================================================== +// +// IsMarker +// +// (from BOOM) +// +//========================================================================== + +inline bool FileSystem::IsMarker(int lump, const char* marker) noexcept +{ + auto name = files[lump].ShortName; + if (name[0] == marker[0]) + { + return (!strcmp(name, marker) || + (marker[1] == '_' && !strcmp(name + 1, marker))); + } + else return false; +} + +//========================================================================== +// +// SetNameSpace +// +// Sets namespace information for the lumps. It always looks for the first +// x_START and the last x_END lump, except when loading flats. In this case +// F_START may be absent and if that is the case all lumps with a size of +// 4096 will be flagged appropriately. +// +//========================================================================== + +// This class was supposed to be local in the function but GCC +// does not like that. +struct Marker +{ + int markertype; + int index; +}; + +void FileSystem::SetNamespace(int filenum, const char* startmarker, const char* endmarker, namespace_t space, FileSys::FileSystemMessageFunc Printf, bool flathack) +{ + using FileSys::FSMessageLevel; + bool warned = false; + int numstartmarkers = 0, numendmarkers = 0; + TArray markers; + int FirstLump = GetFirstEntry(filenum); + int LastLump = GetLastEntry(filenum); + auto FileName = GetContainerName(filenum); + + for (int i = FirstLump; i <= LastLump; i++) + { + if (IsMarker(i, startmarker)) + { + Marker m = { 0, i }; + markers.push_back(m); + numstartmarkers++; + } + else if (IsMarker(i, endmarker)) + { + Marker m = { 1, i }; + markers.push_back(m); + numendmarkers++; + } + } + + if (numstartmarkers == 0) + { + if (numendmarkers == 0) return; // no markers found + + if (Printf) + Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker); + + + if (flathack) + { + // We have found no F_START but one or more F_END markers. + // mark all lumps before the last F_END marker as potential flats. + unsigned int end = markers[markers.size() - 1].index; + for (int ii = FirstLump; ii <= LastLump; ii++) + { + if (FileLength(ii) == 4096) + { + // We can't add this to the flats namespace but + // it needs to be flagged for the texture manager. + if (Printf) Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName, files[ii].ShortName); + files[ii].Namespace = ns_maybeflat; + } + } + } + return; + } + + size_t i = 0; + while (i < markers.size()) + { + int start, end; + if (markers[i].markertype != 0) + { + if (Printf) Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker); + i++; + continue; + } + start = int(i++); + + // skip over subsequent x_START markers + while (i < markers.size() && markers[i].markertype == 0) + { + if (Printf) Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, startmarker); + i++; + continue; + } + // same for x_END markers + while (i < markers.size() - 1 && (markers[i].markertype == 1 && markers[i + 1].markertype == 1)) + { + if (Printf) Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, endmarker); + i++; + continue; + } + // We found a starting marker but no end marker. Ignore this block. + if (i >= markers.size()) + { + if (Printf) Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, startmarker, endmarker); + end = LastLump + 1; + } + else + { + end = markers[i++].index; + } + + // we found a marked block + if (Printf) Printf(FSMessageLevel::DebugNotify, "%s: Found %s block at (%d-%d)\n", FileName, startmarker, markers[start].index, end); + for (int j = markers[start].index + 1; j < end; j++) + { + if (files[j].Namespace != ns_global) + { + if (!warned && Printf) + { + Printf(FSMessageLevel::Warning, "%s: Overlapping namespaces found (lump %d)\n", FileName, j); + } + warned = true; + } + else if (space == ns_sprites && FileLength(j) < 8) + { + // sf 26/10/99: + // ignore sprite lumps smaller than 8 bytes (the smallest possible) + // in size -- this was used by some dmadds wads + // as an 'empty' graphics resource + if (Printf) Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName, files[j].ShortName, j); + } + else + { + files[j].Namespace = space; + } + } + } +} + + +//========================================================================== +// +// W_SkinHack +// +// Tests a wad file to see if it contains an S_SKIN marker. If it does, +// every lump in the wad is moved into a new namespace. Because skins are +// only supposed to replace player sprites, sounds, or faces, this should +// not be a problem. Yes, there are skins that replace more than that, but +// they are such a pain, and breaking them like this was done on purpose. +// This also renames any S_SKINxx lumps to just S_SKIN. +// +//========================================================================== + +void FileSystem::SkinHack(int filenum, FileSys::FileSystemMessageFunc Printf) +{ + using FileSys::FSMessageLevel; + // this being static is not a problem. The only relevant thing is that each skin gets a different number. + bool skinned = false; + bool hasmap = false; + + int FirstLump = GetFirstEntry(filenum); + int LastLump = GetLastEntry(filenum); + auto FileName = GetContainerName(filenum); + + for (int i = FirstLump; i <= LastLump; i++) + { + auto lump = &files[i]; + + if (!strnicmp(lump->ShortName, "S_SKIN", 6)) + { // Wad has at least one skin. + lump->ShortName[6] = 0; + lump->ShortName[7] = 0; + if (!skinned) + { + skinned = true; + + for (int j = FirstLump; j <= LastLump; j++) + { + files[j].Namespace = skin_namespc; + } + skin_namespc++; + } + } + // needless to say, this check is entirely useless these days as map names can be more diverse.. + if ((lump->ShortName[0] == 'M' && + lump->ShortName[1] == 'A' && + lump->ShortName[2] == 'P' && + lump->ShortName[3] >= '0' && lump->ShortName[3] <= '9' && + lump->ShortName[4] >= '0' && lump->ShortName[4] <= '9' && + lump->ShortName[5] == '\0') + || + (lump->ShortName[0] == 'E' && + lump->ShortName[1] >= '0' && lump->ShortName[1] <= '9' && + lump->ShortName[2] == 'M' && + lump->ShortName[3] >= '0' && lump->ShortName[3] <= '9' && + lump->ShortName[4] == '\0')) + { + hasmap = true; + } + } + if (skinned && hasmap && Printf) + { + Printf(FSMessageLevel::Attention, "%s: The maps will not be loaded because it has a skin.\n", FileName); + Printf(FSMessageLevel::Attention, "You should remove the skin from the wad to play these maps.\n"); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void FileSystem::SetupNamespace(int filenum, FileSys::FileSystemMessageFunc Printf) +{ + int flags = GetContainerFlags(filenum); + + // Set namespace for entries from WADs. + if ((flags & wadflags) == wadflags) + { + SetNamespace(filenum, "S_START", "S_END", ns_sprites, Printf); + SetNamespace(filenum, "F_START", "F_END", ns_flats, Printf, true); + SetNamespace(filenum, "C_START", "C_END", ns_colormaps, Printf); + SetNamespace(filenum, "A_START", "A_END", ns_acslibrary, Printf); + SetNamespace(filenum, "TX_START", "TX_END", ns_newtextures, Printf); + SetNamespace(filenum, "V_START", "V_END", ns_strifevoices, Printf); + SetNamespace(filenum, "HI_START", "HI_END", ns_hires, Printf); + SetNamespace(filenum, "VX_START", "VX_END", ns_voxels, Printf); + SkinHack(filenum, Printf); + } + else if (!(flags & FResourceFile::NO_FOLDERS)) + { + int FirstLump = GetFirstEntry(filenum); + int LastLump = GetLastEntry(filenum); + auto FileName = GetContainerName(filenum); + + for (int i = FirstLump; i <= LastLump; i++) + { + auto lump = &files[i]; + + auto LongName = GetFileName(i); + // Map some directories to WAD namespaces. + // Note that some of these namespaces don't exist in WADS. + // CheckNumForName will handle any request for these namespaces accordingly. + int Namespace = !strncmp(LongName, "flats/", 6) ? ns_flats : + !strncmp(LongName, "textures/", 9) ? ns_newtextures : + !strncmp(LongName, "hires/", 6) ? ns_hires : + !strncmp(LongName, "sprites/", 8) ? ns_sprites : + !strncmp(LongName, "voxels/", 7) ? ns_voxels : + !strncmp(LongName, "colormaps/", 10) ? ns_colormaps : + !strncmp(LongName, "acs/", 4) ? ns_acslibrary : + !strncmp(LongName, "voices/", 7) ? ns_strifevoices : + !strncmp(LongName, "patches/", 8) ? ns_patches : + !strncmp(LongName, "graphics/", 9) ? ns_graphics : + !strncmp(LongName, "sounds/", 7) ? ns_sounds : + !strncmp(LongName, "music/", 6) ? ns_music : + !strchr(LongName, '/') ? ns_global : + ns_hidden; + + lump->Namespace = Namespace; + + switch (Namespace) + { + case ns_hidden: + memset(lump->ShortName, 0, sizeof(lump->ShortName)); + break; + + case ns_sprites: + case ns_voxels: + case ns_hires: + // Since '\' can't be used as a file name's part inside a ZIP + // we have to work around this for sprites because it is a valid + // frame character. + for (auto& c : lump->ShortName) + { + if (c == '^') c = '\\'; + } + break; + } + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + +bool FileSystem::InitFiles(std::vector& filenames, FileSys::FileSystemFilterInfo* filter, FileSys::FileSystemMessageFunc Printf, bool allowduplicates) +{ + if (!Super::InitFiles(filenames, filter, Printf, allowduplicates)) return false; + files.Resize(GetFileCount()); + memset(files.Data(), 0, sizeof(files[0]) * files.size()); + int numfiles = GetFileCount(); + for (int i = 0; i < numfiles; i++) + { + SetupName(i); + } + + int numresfiles = GetContainerCount(); + for (int i = 0; i < numresfiles; i++) + { + SetupNamespace(i, Printf); + } + return true; +} + +//========================================================================== +// +// CheckNumForName +// +// Returns -1 if name not found. The version with a third parameter will +// look exclusively in the specified wad for the lump. +// +// [RH] Changed to use hash lookup ala BOOM instead of a linear search +// and namespace parameter +//========================================================================== + +int FileSystem::CheckNumForName(const char* name, int space) const +{ + char uname[9]; + uint32_t i; + + if (name == nullptr) + { + return -1; + } + + // Let's not search for names that are longer than 8 characters and contain path separators + // They are almost certainly full path names passed to this function. + if (strlen(name) > 8 && strpbrk(name, "/.")) + { + return -1; + } + + UpperCopy(uname, name); + i = files[FileSys::MakeHash(uname, 8) % files.Size()].HashFirst; + + while (i != NULL_INDEX) + { + auto& lump = files[i]; + + if (!memcmp(lump.ShortName, uname, 8)) + { + if (lump.Namespace == space) break; + // If the lump is from one of the special namespaces exclusive to Zips + // the check has to be done differently: + // If we find a lump with this name in the global namespace that does not come + // from a Zip return that. WADs don't know these namespaces and single lumps must + // work as well. + if (space > ns_specialzipdirectory && lump.Namespace == ns_global && !(lump.Flags & LUMPF_FULLPATH)) + break; + } + i = lump.HashNext; + } + + return i != NULL_INDEX ? i : -1; +} + +int FileSystem::CheckNumForName(const char* name, int space, int rfnum, bool exact) const +{ + char uname[9]; + uint32_t i; + + if (rfnum < 0) + { + return CheckNumForName(name, space); + } + + UpperCopy(uname, name); + i = files[FileSys::MakeHash(uname, 8) % files.Size()].HashFirst; + + // If exact is true if will only find lumps in the same WAD, otherwise + // also those in earlier WADs. + + while (i != NULL_INDEX && + (memcmp(files[i].ShortName, uname, 8) || files[i].Namespace != space || + (exact ? (GetFileContainer(i) != rfnum) : (GetFileContainer(i) > rfnum)))) + { + i = files[i].HashNext; + } + + return i != NULL_INDEX ? i : -1; +} + +//========================================================================== +// +// GetNumForName +// +// Calls CheckNumForName, but bombs out if not found. +// +//========================================================================== + +int FileSystem::GetNumForName(const char* name, int space) const +{ + int i; + + i = CheckNumForName(name, space); + + if (i == -1) + throw FileSys::FileSystemException("GetNumForName: %s not found!", name); + + return i; +} + + + +//========================================================================== +// +// returns a modifiable pointer to the short name +// +// should only be called before the hash chains are set up. +// If done later this needs rehashing. +// +// This is for custom setup through postprocessFunc +// +//========================================================================== + +char* FileSystem::GetShortName(int i) +{ + if ((unsigned)i >= files.Size()) + throw FileSys::FileSystemException("GetShortName: Invalid index"); + return files[i].ShortName; +} + +//========================================================================== +// +// W_FindLump +// +// Find a named lump. Specifically allows duplicates for merging of e.g. +// SNDINFO lumps. +// +//========================================================================== + +int FileSystem::FindLump(const char* name, int* lastlump, bool anyns) +{ + if ((size_t)*lastlump >= files.size()) return -1; + char name8[9]; + UpperCopy(name8, name); + + assert(lastlump != nullptr && *lastlump >= 0); + + const int last = (int)files.size(); + + for(int lump = *lastlump; lump < last; lump++) + { + const FileEntry* const lump_p = &files[lump]; + if ((anyns || lump_p->Namespace == ns_global) && !memcmp(lump_p->ShortName, name8, 8)) + { + *lastlump = lump + 1; + return lump; + } + } + + *lastlump = last; + return -1; +} + +//========================================================================== +// +// W_FindLumpMulti +// +// Find a named lump. Specifically allows duplicates for merging of e.g. +// SNDINFO lumps. Returns everything having one of the passed names. +// +//========================================================================== + +int FileSystem::FindLumpMulti(const char** names, int* lastlump, bool anyns, int* nameindex) +{ + assert(lastlump != nullptr && *lastlump >= 0); + + int last = files.Size(); + + for (int lump = *lastlump; lump < last; lump++) + { + auto lump_p = &files[lump]; + if (anyns || lump_p->Namespace == ns_global) + { + for (const char** name = names; *name != nullptr; name++) + { + if (!strnicmp(*name, lump_p->ShortName, 8)) + { + *lastlump = lump + 1; + if (nameindex != nullptr) *nameindex = int(name - names); + return lump; + } + } + } + } + + *lastlump = last; + return -1; +} + +//========================================================================== +// +// This function combines lookup from regular lists and Doom's special one. +// +//========================================================================== + +int FileSystem::CheckNumForAnyName(const char* name, namespace_t namespc) const +{ + if (name != NULL) + { + // Check short names first to avoid interference from short names in the real file system. + if (strlen(name) <= 8 && !strpbrk(name, "./")) + { + return CheckNumForName(name, namespc); + } + + int lookup = Super::FindFile(name, false); + if (lookup >= 0) return lookup; + } + return -1; +} + diff --git a/source/common/engine/filesystem.h b/source/common/engine/filesystem.h index 53f4916771a..f8a791e7b5d 100644 --- a/source/common/engine/filesystem.h +++ b/source/common/engine/filesystem.h @@ -1,7 +1,129 @@ #pragma once #include "fs_filesystem.h" -using FileSys::FileSystem; using FileSys::FResourceFile; -inline FileSys::FileSystem fileSystem; +// [RH] Namespaces from BOOM. +// These are needed here in the low level part so that WAD files can be properly set up. +enum namespace_t : int { + ns_hidden = -1, + + ns_global = 0, + ns_sprites, + ns_flats, + ns_colormaps, + ns_acslibrary, + ns_newtextures, + ns_bloodraw, // no longer used - kept for ZScript. + ns_bloodsfx, // no longer used - kept for ZScript. + ns_bloodmisc, // no longer used - kept for ZScript. + ns_strifevoices, + ns_hires, + ns_voxels, + ns_maybeflat, + + // These namespaces are only used to mark lumps in special subdirectories + // so that their contents doesn't interfere with the global namespace. + // searching for data in these namespaces works differently for lumps coming + // from Zips or other files. + ns_specialzipdirectory, + ns_sounds, + ns_patches, + ns_graphics, + ns_music, + + ns_firstskin, +}; + + +// extended class that adds Doom's very special short name lookup to the file system. +class FileSystem : public FileSys::FileSystem +{ +private: + struct FileEntry + { + char ShortName[9]; + uint8_t Namespace; + uint8_t Flags; + uint32_t HashFirst; + uint32_t HashNext; + }; + + const int wadflags = FileSys::FResourceFile::NO_EXTENSIONS | FileSys::FResourceFile::NO_FOLDERS | FileSys::FResourceFile::SHORTNAMES; + const uint32_t NULL_INDEX = 0xffffffff; + + TArray files; + int skin_namespc = ns_firstskin; + + + void Start(FileSys::FileSystemMessageFunc Printf); + void SetupName(int fileindex); + bool IsMarker(int lump, const char* marker) noexcept; + void SetNamespace(int filenum, const char* startmarker, const char* endmarker, namespace_t space, FileSys::FileSystemMessageFunc Printf, bool flathack = false); + void SkinHack(int filenum, FileSys::FileSystemMessageFunc Printf); + void SetupNamespace(int filenum, FileSys::FileSystemMessageFunc Printf); + + using Super = FileSys::FileSystem; + +public: + enum + { + LUMPF_MAYBEFLAT = 1, + LUMPF_FULLPATH = 2, + }; + + bool InitFiles(std::vector& filenames, FileSys::FileSystemFilterInfo* filter = nullptr, FileSys::FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false) override; + void InitHashChains() override; + + int CheckNumForAnyName(const char* cname, namespace_t namespc = ns_global) const; + + int CheckNumForName(const char* name, int namespc) const; + int CheckNumForName(const char* name, int namespc, int wadfile, bool exact = true) const; + int GetNumForName(const char* name, int namespc) const; + + inline int CheckNumForName(const uint8_t* name) const { return CheckNumForName((const char*)name, ns_global); } + inline int CheckNumForName(const char* name) const { return CheckNumForName(name, ns_global); } + inline int CheckNumForName(const uint8_t* name, int ns) const { return CheckNumForName((const char*)name, ns); } + inline int GetNumForName(const char* name) const { return GetNumForName(name, ns_global); } + inline int GetNumForName(const uint8_t* name) const { return GetNumForName((const char*)name); } + inline int GetNumForName(const uint8_t* name, int ns) const { return GetNumForName((const char*)name, ns); } + + int FindLump(const char* name, int* lastlump, bool anyns = false); // [RH] Find lumps with duplication + int FindLumpMulti(const char** names, int* lastlump, bool anyns = false, int* nameindex = nullptr); // same with multiple possible names + + bool CheckFileName(int lump, const char* name) const noexcept + { + if ((size_t)lump >= files.size()) + return false; + + return !strnicmp(files[lump].ShortName, name, 8); + } + + const char* GetFileShortName(int lump) const noexcept + { + if ((size_t)lump >= files.size()) + return nullptr; + else + return files[lump].ShortName; + } + + int GetFileNamespace(int lump) const noexcept + { + if ((size_t)lump >= files.size()) + return ns_global; + else + return files[lump].Namespace; + } + + void SetFileNamespace(int lump, int ns) noexcept + { + if ((size_t)lump < files.size()) files[lump].Namespace = ns; + } + + // This is only for code that wants to edit the names before the game starts. + char* GetShortName(int i); + +}; + +inline FileSystem fileSystem; + diff --git a/source/common/engine/i_net.cpp b/source/common/engine/i_net.cpp index 33b4c126711..ad106bbc4a8 100644 --- a/source/common/engine/i_net.cpp +++ b/source/common/engine/i_net.cpp @@ -132,7 +132,8 @@ enum PRE_CONACK, // Sent from host to guest to acknowledge PRE_CONNECT receipt PRE_ALLFULL, // Sent from host to an unwanted guest PRE_ALLHEREACK, // Sent from guest to host to acknowledge PRE_ALLHEREACK receipt - PRE_GO // Sent from host to guest to continue game startup + PRE_GO, // Sent from host to guest to continue game startup + PRE_IN_PROGRESS, // Sent from host to guest if the game has already started }; // Set PreGamePacket.fake to this so that the game rejects any pregame packets @@ -269,6 +270,8 @@ void PacketSend (void) // I_Error ("SendPacket error: %s",strerror(errno)); } +void PreSend(const void* buffer, int bufferlen, const sockaddr_in* to); +void SendConAck(int num_connected, int num_needed); // // PacketGet @@ -303,7 +306,7 @@ void PacketGet (void) GetPlayerName(node).GetChars()); } - doomcom.data[0] = 0x80; // NCMD_EXIT + doomcom.data[0] = NCMD_EXIT; c = 1; } else if (err != WSAEWOULDBLOCK) @@ -341,10 +344,11 @@ void PacketGet (void) } else if (c > 0) { //The packet is not from any in-game node, so we might as well discard it. - // Don't show the message for disconnect notifications. - if (c != 2 || TransmitBuffer[0] != PRE_FAKE || TransmitBuffer[1] != PRE_DISCONNECT) + if (TransmitBuffer[0] == PRE_FAKE) { - DPrintf(DMSG_WARNING, "Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port); + // If it's someone waiting in the lobby, let them know the game already started + uint8_t msg[] = { PRE_FAKE, PRE_IN_PROGRESS }; + PreSend(msg, 2, &fromaddress); } doomcom.remotenode = -1; return; @@ -369,7 +373,22 @@ sockaddr_in *PreGet (void *buffer, int bufferlen, bool noabort) int err = WSAGetLastError(); if (err == WSAEWOULDBLOCK || (noabort && err == WSAECONNRESET)) return NULL; // no packet - I_Error ("PreGet: %s", neterror ()); + + if (doomcom.consoleplayer == 0) + { + int node = FindNode(&fromaddress); + I_NetMessage("Got unexpected disconnect."); + doomcom.numnodes--; + for (; node < doomcom.numnodes; ++node) + sendaddress[node] = sendaddress[node + 1]; + + // Let remaining guests know that somebody left. + SendConAck(doomcom.numnodes, doomcom.numplayers); + } + else + { + I_NetError("The host disbanded the game unexpectedly"); + } } return &fromaddress; } @@ -499,7 +518,7 @@ void SendAbort (void) } } -static void SendConAck (int num_connected, int num_needed) +void SendConAck (int num_connected, int num_needed) { PreGamePacket packet; @@ -708,7 +727,7 @@ bool HostGame (int i) doomcom.numnodes = 1; - I_NetInit ("Waiting for players", numplayers); + I_NetInit ("Hosting game", numplayers); // Wait for numplayers-1 different connections if (!I_NetLoop (Host_CheckForConnects, (void *)(intptr_t)numplayers)) @@ -783,13 +802,15 @@ bool Guest_ContactHost (void *userdata) } else if (packet.Message == PRE_DISCONNECT) { - doomcom.numnodes = 0; - I_FatalError ("The host cancelled the game."); + I_NetError("The host cancelled the game."); } else if (packet.Message == PRE_ALLFULL) { - doomcom.numnodes = 0; - I_FatalError ("The game is full."); + I_NetError("The game is full."); + } + else if (packet.Message == PRE_IN_PROGRESS) + { + I_NetError("The game was already started."); } } } @@ -850,7 +871,7 @@ bool Guest_WaitForOthers (void *userdata) return true; case PRE_DISCONNECT: - I_FatalError ("The host cancelled the game."); + I_NetError("The host cancelled the game."); break; } } @@ -875,6 +896,7 @@ bool JoinGame (int i) BuildAddress (&sendaddress[1], Args->GetArg(i+1)); sendplayer[1] = 0; doomcom.numnodes = 2; + doomcom.consoleplayer = -1; // Let host know we are here @@ -1046,6 +1068,13 @@ void I_NetMessage(const char* text, ...) #endif } +void I_NetError(const char* error) +{ + doomcom.numnodes = 0; + StartWindow->NetClose(); + I_FatalError(error); +} + // todo: later these must be dispatched by the main menu, not the start screen. void I_NetProgress(int val) { diff --git a/source/common/engine/i_net.h b/source/common/engine/i_net.h index c52072c863d..15720374d0b 100644 --- a/source/common/engine/i_net.h +++ b/source/common/engine/i_net.h @@ -7,6 +7,7 @@ int I_InitNetwork (void); void I_NetCmd (void); void I_NetMessage(const char*, ...); +void I_NetError(const char* error); void I_NetProgress(int val); void I_NetInit(const char* msg, int num); bool I_NetLoop(bool (*timer_callback)(void*), void* userdata); diff --git a/source/common/engine/m_random.cpp b/source/common/engine/m_random.cpp index 3af14526bb8..11c4350b762 100644 --- a/source/common/engine/m_random.cpp +++ b/source/common/engine/m_random.cpp @@ -83,7 +83,7 @@ FRandom pr_exrandom("EX_Random"); // PUBLIC DATA DEFINITIONS ------------------------------------------------- -FRandom M_Random; +FCRandom M_Random; // Global seed. This is modified predictably to initialize every RNG. uint32_t rngseed; @@ -126,8 +126,8 @@ CCMD(rngseed) // PRIVATE DATA DEFINITIONS ------------------------------------------------ -FRandom *FRandom::RNGList; -static TDeletingArray NewRNGs; +FRandom *FRandom::RNGList, *FRandom::CRNGList; +static TDeletingArray NewRNGs, NewCRNGs; // CODE -------------------------------------------------------------------- @@ -139,14 +139,22 @@ static TDeletingArray NewRNGs; // //========================================================================== -FRandom::FRandom () -: NameCRC (0) +FRandom::FRandom (bool client) +: NameCRC (0), bClient(client) { #ifndef NDEBUG Name = NULL; #endif - Next = RNGList; - RNGList = this; + if (bClient) + { + Next = CRNGList; + CRNGList = this; + } + else + { + Next = RNGList; + RNGList = this; + } Init(0); } @@ -158,7 +166,7 @@ FRandom::FRandom () // //========================================================================== -FRandom::FRandom (const char *name) +FRandom::FRandom (const char *name, bool client) : bClient(client) { NameCRC = CalcCRC32 ((const uint8_t *)name, (unsigned int)strlen (name)); #ifndef NDEBUG @@ -170,7 +178,7 @@ FRandom::FRandom (const char *name) #endif // Insert the RNG in the list, sorted by CRC - FRandom **prev = &RNGList, *probe = RNGList; + FRandom **prev = (bClient ? &CRNGList : &RNGList), * probe = (bClient ? CRNGList : RNGList); while (probe != NULL && probe->NameCRC < NameCRC) { @@ -205,8 +213,8 @@ FRandom::~FRandom () FRandom *last = NULL; - prev = &RNGList; - rng = RNGList; + prev = bClient ? &CRNGList : &RNGList; + rng = bClient ? CRNGList : RNGList; while (rng != NULL && rng != this) { @@ -237,6 +245,11 @@ void FRandom::StaticClearRandom () { rng->Init(rngseed); } + + for (FRandom* rng = FRandom::CRNGList; rng != NULL; rng = rng->Next) + { + rng->Init(rngseed); + } } //========================================================================== @@ -345,15 +358,15 @@ void FRandom::StaticReadRNGState(FSerializer &arc) // //========================================================================== -FRandom *FRandom::StaticFindRNG (const char *name) +FRandom *FRandom::StaticFindRNG (const char *name, bool client) { uint32_t NameCRC = CalcCRC32 ((const uint8_t *)name, (unsigned int)strlen (name)); // Use the default RNG if this one happens to have a CRC of 0. - if (NameCRC == 0) return &pr_exrandom; + if (NameCRC == 0) return client ? &M_Random : &pr_exrandom; // Find the RNG in the list, sorted by CRC - FRandom **prev = &RNGList, *probe = RNGList; + FRandom **prev = (client ? &CRNGList : &RNGList), *probe = (client ? CRNGList : RNGList); while (probe != NULL && probe->NameCRC < NameCRC) { @@ -364,14 +377,32 @@ FRandom *FRandom::StaticFindRNG (const char *name) if (probe == NULL || probe->NameCRC != NameCRC) { // A matching RNG doesn't exist yet so create it. - probe = new FRandom(name); + probe = new FRandom(name, client); // Store the new RNG for destruction when ZDoom quits. - NewRNGs.Push(probe); + if (client) + NewCRNGs.Push(probe); + else + NewRNGs.Push(probe); } return probe; } +void FRandom::SaveRNGState(TArray& backups) +{ + for (auto cur = RNGList; cur != nullptr; cur = cur->Next) + backups.Push(*cur); +} + +void FRandom::RestoreRNGState(TArray& backups) +{ + unsigned int i = 0u; + for (auto cur = RNGList; cur != nullptr; cur = cur->Next) + *cur = backups[i++]; + + backups.Clear(); +} + //========================================================================== // // FRandom :: StaticPrintSeeds diff --git a/source/common/engine/m_random.h b/source/common/engine/m_random.h index d9eec6c44c0..ba0bcaf626c 100644 --- a/source/common/engine/m_random.h +++ b/source/common/engine/m_random.h @@ -44,9 +44,9 @@ class FSerializer; class FRandom : public SFMTObj { public: - FRandom (); - FRandom (const char *name); - ~FRandom (); + FRandom() : FRandom(false) {} + FRandom(const char* name) : FRandom(name, false) {} + ~FRandom(); int Seed() const { @@ -170,20 +170,34 @@ class FRandom : public SFMTObj static void StaticClearRandom (); static void StaticReadRNGState (FSerializer &arc); static void StaticWriteRNGState (FSerializer &file); - static FRandom *StaticFindRNG(const char *name); + static FRandom *StaticFindRNG(const char *name, bool client); + static void SaveRNGState(TArray& backups); + static void RestoreRNGState(TArray& backups); #ifndef NDEBUG static void StaticPrintSeeds (); #endif +protected: + FRandom(bool client); + FRandom(const char* name, bool client); + private: #ifndef NDEBUG const char *Name; #endif FRandom *Next; uint32_t NameCRC; + bool bClient; + + static FRandom *RNGList, *CRNGList; +}; - static FRandom *RNGList; +class FCRandom : public FRandom +{ +public: + FCRandom() : FRandom(true) {} + FCRandom(const char* name) : FRandom(name, true) {} }; extern uint32_t rngseed; // The starting seed (not part of state) @@ -193,6 +207,6 @@ extern bool use_staticrng; // M_Random can be used for numbers that do not affect gameplay -extern FRandom M_Random; +extern FCRandom M_Random; #endif diff --git a/source/common/engine/namedef.h b/source/common/engine/namedef.h index 13827382c0c..be0c47649ec 100644 --- a/source/common/engine/namedef.h +++ b/source/common/engine/namedef.h @@ -41,6 +41,12 @@ xx(Random2) xx(RandomPick) xx(FRandomPick) xx(SetRandomSeed) +xx(CRandom) +xx(CFRandom) +xx(CRandom2) +xx(CRandomPick) +xx(CFRandomPick) +xx(CSetRandomSeed) xx(BuiltinRandomSeed) xx(BuiltinNew) xx(GetClass) diff --git a/source/common/engine/sc_man.cpp b/source/common/engine/sc_man.cpp index ac7b4799f77..5af08fa5708 100644 --- a/source/common/engine/sc_man.cpp +++ b/source/common/engine/sc_man.cpp @@ -124,7 +124,7 @@ FScanner::FScanner(int lumpnum, TMap* extsymbols) : symbols(extsy void FScanner::Open (const char *name) { - int lump = fileSystem.CheckNumForFullName(name, true); + int lump = fileSystem.CheckNumForAnyName(name); if (lump == -1) { I_Error("Could not find script lump '%s'\n", name); diff --git a/source/common/engine/serializer.cpp b/source/common/engine/serializer.cpp index 97ded1adf8a..5c5c9f56617 100644 --- a/source/common/engine/serializer.cpp +++ b/source/common/engine/serializer.cpp @@ -58,8 +58,6 @@ #include "vm.h" #include "i_interface.h" -using namespace FileSys; - extern DObject *WP_NOCHANGE; bool save_full = false; // for testing. Should be removed afterward. @@ -155,13 +153,13 @@ bool FSerializer::OpenReader(const char *buffer, size_t length) // //========================================================================== -bool FSerializer::OpenReader(FCompressedBuffer *input) +bool FSerializer::OpenReader(FileSys::FCompressedBuffer *input) { if (input->mSize <= 0 || input->mBuffer == nullptr) return false; if (w != nullptr || r != nullptr) return false; mErrors = 0; - if (input->mMethod == METHOD_STORED) + if (input->mMethod == FileSys::METHOD_STORED) { r = new FReader((char*)input->mBuffer, input->mSize); } @@ -785,10 +783,10 @@ const char *FSerializer::GetOutput(unsigned *len) // //========================================================================== -FCompressedBuffer FSerializer::GetCompressedOutput() +FileSys::FCompressedBuffer FSerializer::GetCompressedOutput() { if (isReading()) return{ 0,0,0,0,0,nullptr }; - FCompressedBuffer buff; + FileSys::FCompressedBuffer buff; WriteObjects(); EndObject(); buff.filename = nullptr; @@ -827,7 +825,7 @@ FCompressedBuffer FSerializer::GetCompressedOutput() if (err == Z_OK) { buff.mBuffer = new char[buff.mCompressedSize]; - buff.mMethod = METHOD_DEFLATE; + buff.mMethod = FileSys::METHOD_DEFLATE; memcpy(buff.mBuffer, compressbuf, buff.mCompressedSize); delete[] compressbuf; return buff; @@ -836,7 +834,7 @@ FCompressedBuffer FSerializer::GetCompressedOutput() error: memcpy(compressbuf, w->mOutString.GetString(), buff.mSize + 1); buff.mCompressedSize = buff.mSize; - buff.mMethod = METHOD_STORED; + buff.mMethod = FileSys::METHOD_STORED; return buff; } @@ -1181,7 +1179,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe if (TexMan.GetLinkedTexture(lump) == pic) { - name = fileSystem.GetFileFullName(lump); + name = fileSystem.GetFileName(lump); } else { diff --git a/source/common/engine/serializer.h b/source/common/engine/serializer.h index 40b6ab7062a..fb906aee888 100644 --- a/source/common/engine/serializer.h +++ b/source/common/engine/serializer.h @@ -252,7 +252,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, struct ModelOverride & FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimModelOverride &mo, struct AnimModelOverride *def); FSerializer &Serialize(FSerializer &arc, const char *key, ModelAnim &ao, ModelAnim *def); FSerializer &Serialize(FSerializer &arc, const char *key, ModelAnimFrame &ao, ModelAnimFrame *def); -FSerializer& Serialize(FSerializer& arc, const char* key, FTranslationID& value, FTranslationID* defval); +FSerializer &Serialize(FSerializer& arc, const char* key, FTranslationID& value, FTranslationID* defval); void SerializeFunctionPointer(FSerializer &arc, const char *key, FunctionPointerValue *&p); diff --git a/source/common/engine/st_start.h b/source/common/engine/st_start.h index a8b78aaa838..b09991d04f5 100644 --- a/source/common/engine/st_start.h +++ b/source/common/engine/st_start.h @@ -55,6 +55,7 @@ class FStartupScreen virtual void NetInit(const char *message, int num_players) {} virtual void NetProgress(int count) {} virtual void NetDone() {} + virtual void NetClose() {} virtual bool NetLoop(bool (*timer_callback)(void *), void *userdata) { return false; } virtual void AppendStatusLine(const char* status) {} virtual void LoadingStatus(const char* message, int colors) {} @@ -74,6 +75,7 @@ class FBasicStartupScreen : public FStartupScreen void NetProgress(int count); void NetMessage(const char* format, ...); // cover for printf void NetDone(); + void NetClose(); bool NetLoop(bool (*timer_callback)(void*), void* userdata); protected: int NetMaxPos, NetCurPos; diff --git a/source/common/engine/stringtable.cpp b/source/common/engine/stringtable.cpp index d9d739b57aa..d748157dbae 100644 --- a/source/common/engine/stringtable.cpp +++ b/source/common/engine/stringtable.cpp @@ -47,7 +47,7 @@ // //========================================================================== -void FStringTable::LoadStrings (FileSys::FileSystem& fileSystem, const char *language) +void FStringTable::LoadStrings (FileSystem& fileSystem, const char *language) { int lastlump, lump; diff --git a/source/common/engine/stringtable.h b/source/common/engine/stringtable.h index 181d8c7f399..193045d9fb0 100644 --- a/source/common/engine/stringtable.h +++ b/source/common/engine/stringtable.h @@ -84,7 +84,7 @@ class FStringTable using LangMap = TMap; using StringMacroMap = TMap; - void LoadStrings(FileSys::FileSystem& fileSystem, const char *language); + void LoadStrings(FileSystem& fileSystem, const char *language); void UpdateLanguage(const char* language); StringMap GetDefaultStrings() { return allStrings[default_table]; } // Dehacked needs these for comparison void SetOverrideStrings(StringMap & map) diff --git a/source/common/filesystem/include/fs_filesystem.h b/source/common/filesystem/include/fs_filesystem.h index 858b7483745..8747c249980 100644 --- a/source/common/filesystem/include/fs_filesystem.h +++ b/source/common/filesystem/include/fs_filesystem.h @@ -13,15 +13,6 @@ namespace FileSys { -union LumpShortName -{ - char String[9]; - - uint32_t dword; // These are for accessing the first 4 or 8 chars of - uint64_t qword; // Name as a unit without breaking strict aliasing rules -}; - - struct FolderEntry { const char *name; @@ -32,46 +23,34 @@ class FileSystem { public: FileSystem(); - ~FileSystem (); + virtual ~FileSystem (); + // do not copy! + FileSystem(const FileSystem& other) = delete; + FileSystem& operator =(const FileSystem& other) = delete; - // The wadnum for the IWAD - int GetIwadNum() { return IwadIndex; } - void SetIwadNum(int x) { IwadIndex = x; } + bool Initialize(std::vector& filenames, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false); - int GetMaxIwadNum() { return MaxIwadIndex; } - void SetMaxIwadNum(int x) { MaxIwadIndex = x; } + // The container for the IWAD + int GetBaseNum() { return BaseIndex; } + void SetBaseNum(int x) { BaseIndex = x; } - bool InitSingleFile(const char *filename, FileSystemMessageFunc Printf = nullptr); - bool InitMultipleFiles (std::vector& filenames, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false, FILE* hashfile = nullptr); - void AddFile (const char *filename, FileReader *wadinfo, LumpFilterInfo* filter, FileSystemMessageFunc Printf, FILE* hashfile); - int CheckIfResourceFileLoaded (const char *name) noexcept; - void AddAdditionalFile(const char* filename, FileReader* wadinfo = NULL) {} + int GetMaxBaseNum() { return MaxBaseIndex; } + void SetMaxBaseNum(int x) { MaxBaseIndex = x; } - const char *GetResourceFileName (int filenum) const noexcept; - const char *GetResourceFileFullName (int wadnum) const noexcept; + int CheckIfContainerLoaded (const char *name) noexcept; + void AddAdditionalFile(const char* filename, FileReader* wadinfo = NULL) {} - int GetFirstEntry(int wadnum) const noexcept; - int GetLastEntry(int wadnum) const noexcept; - int GetEntryCount(int wadnum) const noexcept; + const char *GetContainerName (int container) const noexcept; + const char *GetContainerFullName (int container) const noexcept; - int CheckNumForName (const char *name, int namespc) const; - int CheckNumForName (const char *name, int namespc, int wadfile, bool exact = true) const; - int GetNumForName (const char *name, int namespc) const; + int GetFirstEntry(int container) const noexcept; + int GetLastEntry(int container) const noexcept; + int GetEntryCount(int container) const noexcept; + int GetContainerFlags(int container) const noexcept; - inline int CheckNumForName (const uint8_t *name) const { return CheckNumForName ((const char *)name, ns_global); } - inline int CheckNumForName (const char *name) const { return CheckNumForName (name, ns_global); } - inline int CheckNumForName (const uint8_t *name, int ns) const { return CheckNumForName ((const char *)name, ns); } - inline int GetNumForName (const char *name) const { return GetNumForName (name, ns_global); } - inline int GetNumForName (const uint8_t *name) const { return GetNumForName ((const char *)name); } - inline int GetNumForName (const uint8_t *name, int ns) const { return GetNumForName ((const char *)name, ns); } - - int CheckNumForFullName (const char *cname, bool trynormal = false, int namespc = ns_global, bool ignoreext = false) const; - int CheckNumForFullName (const char *name, int wadfile) const; - int GetNumForFullName (const char *name) const; - int FindFile(const char* name) const - { - return CheckNumForFullName(name); - } + int FindFile (const char *cname, bool ignoreext = false) const; + int GetFileInContainer (const char *name, int wadfile) const; + int GetFile (const char *name) const; bool FileExists(const char* name) const { @@ -83,101 +62,106 @@ class FileSystem return FindFile(name.c_str()) >= 0; } - LumpShortName& GetShortName(int i); // may only be called before the hash chains are set up. void RenameFile(int num, const char* fn); bool CreatePathlessCopy(const char* name, int id, int flags); - void ReadFile (int lump, void *dest); + void ReadFile (int filenum, void *dest); // These should only be used if the file data really needs padding. - FileData ReadFile (int lump); - FileData ReadFile (const char *name) { return ReadFile (GetNumForName (name)); } - FileData ReadFileFullName(const char* name) { return ReadFile(GetNumForFullName(name)); } + FileData ReadFile (int filenum); + FileData ReadFileFullName(const char* name) { return ReadFile(GetFile(name)); } - FileReader OpenFileReader(int lump, int readertype, int readerflags); // opens a reader that redirects to the containing file's one. + FileReader OpenFileReader(int filenum, int readertype, int readerflags); // opens a reader that redirects to the containing file's one. FileReader OpenFileReader(const char* name); FileReader ReopenFileReader(const char* name, bool alwayscache = false); - FileReader OpenFileReader(int lump) + FileReader OpenFileReader(int filenum) { - return OpenFileReader(lump, READER_SHARED, READERFLAG_SEEKABLE); + return OpenFileReader(filenum, READER_SHARED, READERFLAG_SEEKABLE); } - FileReader ReopenFileReader(int lump, bool alwayscache = false) + FileReader ReopenFileReader(int filenum, bool alwayscache = false) { - return OpenFileReader(lump, alwayscache ? READER_CACHED : READER_NEW, READERFLAG_SEEKABLE); + return OpenFileReader(filenum, alwayscache ? READER_CACHED : READER_NEW, READERFLAG_SEEKABLE); } - int FindLump (const char *name, int *lastlump, bool anyns=false); // [RH] Find lumps with duplication - int FindLumpMulti (const char **names, int *lastlump, bool anyns = false, int *nameindex = NULL); // same with multiple possible names int FindLumpFullName(const char* name, int* lastlump, bool noext = false); - bool CheckFileName (int lump, const char *name); // [RH] True if lump's name == name int FindFileWithExtensions(const char* name, const char* const* exts, int count) const; int FindResource(int resid, const char* type, int filenum = -1) const noexcept; int GetResource(int resid, const char* type, int filenum = -1) const; - static uint32_t LumpNameHash (const char *name); // [RH] Create hash key from an 8-char name - - ptrdiff_t FileLength (int lump) const; - int GetFileFlags (int lump); // Return the flags for this lump - const char* GetFileShortName(int lump) const; - const char *GetFileFullName (int lump, bool returnshort = true) const; // [RH] Returns the lump's full name - std::string GetFileFullPath (int lump) const; // [RH] Returns wad's name + lump's full name - int GetFileContainer (int lump) const; // [RH] Returns wadnum for a specified lump - int GetFileNamespace (int lump) const; // [RH] Returns the namespace a lump belongs to - void SetFileNamespace(int lump, int ns); - int GetResourceId(int lump) const; // Returns the RFF index number for this lump - const char* GetResourceType(int lump) const; - bool CheckFileName (int lump, const char *name) const; // [RH] Returns true if the names match + ptrdiff_t FileLength(int filenum) const; + int GetFileFlags (int filenum); // Return the flags for this filenum + const char* GetFileName(int filenum) const; // Gets uninterpreted name from the FResourceFile + std::string GetFileFullPath (int filenum) const; // [RH] Returns wad's name + filenum's full name + int GetFileContainer (int filenum) const; + // [RH] Returns container for a specified filenum + int GetResourceId(int filenum) const; // Returns the RFF index number for this filenum + const char* GetResourceType(int filenum) const; unsigned GetFilesInFolder(const char *path, std::vector &result, bool atomic) const; - int GetNumEntries() const + int GetFileCount() const { return NumEntries; } - int GetNumWads() const + int GetContainerCount() const { return (int)Files.size(); } int AddFromBuffer(const char* name, char* data, int size, int id, int flags); - FileReader* GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD - void InitHashChains(); + FileReader* GetFileReader(int container); // Gets a FileReader object to the entire WAD protected: struct LumpRecord; + const uint32_t NULL_INDEX = 0xffffffff; std::vector Files; std::vector FileInfo; std::vector Hashes; // one allocation for all hash lists. - uint32_t *FirstLumpIndex = nullptr; // [RH] Hashing stuff moved out of lumpinfo structure - uint32_t *NextLumpIndex = nullptr; - uint32_t *FirstLumpIndex_FullName = nullptr; // The same information for fully qualified paths from .zips - uint32_t *NextLumpIndex_FullName = nullptr; + uint32_t *FirstFileIndex_FullName = nullptr; // The same information for fully qualified paths from .zips + uint32_t *NextFileIndex_FullName = nullptr; - uint32_t *FirstLumpIndex_NoExt = nullptr; // The same information for fully qualified paths from .zips - uint32_t *NextLumpIndex_NoExt = nullptr; + uint32_t *FirstFileIndex_NoExt = nullptr; // The same information for fully qualified paths from .zips + uint32_t *NextFileIndex_NoExt = nullptr; - uint32_t* FirstLumpIndex_ResId = nullptr; // The same information for fully qualified paths from .zips - uint32_t* NextLumpIndex_ResId = nullptr; + uint32_t* FirstFileIndex_ResId = nullptr; // The same information for fully qualified paths from .zips + uint32_t* NextFileIndex_ResId = nullptr; uint32_t NumEntries = 0; // Not necessarily the same as FileInfo.Size() uint32_t NumWads = 0; - int IwadIndex = -1; - int MaxIwadIndex = -1; + int BaseIndex = -1; + int MaxBaseIndex = -1; StringPool* stringpool = nullptr; private: void DeleteAll(); - void MoveLumpsInFolder(const char *); + void MoveFilesInFolder(const char *); + void AddFile(const char* filename, FileReader* wadinfo, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf); +protected: + + // These two functions must be overridden by subclasses which want to extend the file system. + virtual bool InitFiles(std::vector& filenames, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false); +public: + virtual void InitHashChains(); }; +//djb2 hash algorithm with case insensitivity hack +inline static uint32_t MakeHash(const char* str, size_t length = SIZE_MAX) +{ + uint32_t hash = 5381; + uint32_t c; + while (length-- > 0 && (c = *str++)) hash = hash * 33 + (c | 32); + return hash; +} + + } \ No newline at end of file diff --git a/source/common/filesystem/include/resourcefile.h b/source/common/filesystem/include/resourcefile.h index a23914444ed..982579112f1 100644 --- a/source/common/filesystem/include/resourcefile.h +++ b/source/common/filesystem/include/resourcefile.h @@ -16,7 +16,7 @@ std::string ExtractBaseName(const char* path, bool include_extension = false); void strReplace(std::string& str, const char* from, const char* to); // user context in which the file system gets opened. This also contains a few callbacks to avoid direct dependencies on the engine. -struct LumpFilterInfo +struct FileSystemFilterInfo { std::vector gameTypeFilter; // this can contain multiple entries @@ -45,41 +45,10 @@ using FileSystemMessageFunc = int(*)(FSMessageLevel msglevel, const char* format class FResourceFile; -// [RH] Namespaces from BOOM. -// These are needed here in the low level part so that WAD files can be properly set up. -typedef enum { - ns_hidden = -1, - - ns_global = 0, - ns_sprites, - ns_flats, - ns_colormaps, - ns_acslibrary, - ns_newtextures, - ns_bloodraw, // no longer used - kept for ZScript. - ns_bloodsfx, // no longer used - kept for ZScript. - ns_bloodmisc, // no longer used - kept for ZScript. - ns_strifevoices, - ns_hires, - ns_voxels, - - // These namespaces are only used to mark lumps in special subdirectories - // so that their contents doesn't interfere with the global namespace. - // searching for data in these namespaces works differently for lumps coming - // from Zips or other files. - ns_specialzipdirectory, - ns_sounds, - ns_patches, - ns_graphics, - ns_music, - - ns_firstskin, -} namespace_t; enum ELumpFlags { - RESFF_MAYBEFLAT = 1, // might be a flat inside a WAD outside F_START/END - RESFF_FULLPATH = 2, // contains a full path. This will trigger extended namespace checks when looking up short names. + RESFF_FULLPATH = 2, // contains a full path. RESFF_EMBEDDED = 4, // marks an embedded resource file for later processing. RESFF_SHORTNAME = 8, // the stored name is a short extension-less name RESFF_COMPRESSED = 16, // compressed or encrypted, i.e. cannot be read with the container file's reader. @@ -100,11 +69,10 @@ struct FResourceEntry size_t CompressedSize; const char* FileName; size_t Position; - int ResourceID; + int ResourceID; // Only Blood RFF uses this natively. uint32_t CRC32; uint16_t Flags; uint16_t Method; - int16_t Namespace; }; void SetMainThread(); @@ -112,17 +80,25 @@ void SetMainThread(); class FResourceFile { public: - FResourceFile(const char* filename, StringPool* sp); - FResourceFile(const char* filename, FileReader& r, StringPool* sp); - const char* NormalizeFileName(const char* fn, int fallbackcp = 0); + enum + { + // descibes which kind of limitations this file type has. + NO_FOLDERS = 1, // no paths - only one rpot folder (e.g. Build GRP, Blood RFF, Descent HOG + NO_EXTENSIONS = 2, // no extensions for file names (e.g. Doom WADs.) + SHORTNAMES = 4, // Name is (at most) 8.3 DOS ASCII format, (8.0 in case of WAD) + }; + FResourceFile(const char* filename, StringPool* sp, int flags); + FResourceFile(const char* filename, FileReader& r, StringPool* sp, int flags); + const char* NormalizeFileName(const char* fn, int fallbackcp = 0, bool allowbackslash = false); FResourceEntry* AllocateEntries(int count); void GenerateHash(); - void PostProcessArchive(LumpFilterInfo* filter); + void PostProcessArchive(FileSystemFilterInfo* filter); protected: FileReader Reader; const char* FileName; FResourceEntry* Entries = nullptr; uint32_t NumLumps; + int flags = 0; char Hash[48]; StringPool* stringpool; @@ -132,7 +108,7 @@ class FResourceFile Entries[entry].Flags &= ~RESFF_NEEDFILESTART; } bool IsFileInFolder(const char* const resPath); - void CheckEmbedded(uint32_t entry, LumpFilterInfo* lfi); + void CheckEmbedded(uint32_t entry, FileSystemFilterInfo* lfi); private: uint32_t FirstLump; @@ -140,19 +116,20 @@ class FResourceFile int FilterLumps(const std::string& filtername, uint32_t max); bool FindPrefixRange(const char* filter, uint32_t max, uint32_t &start, uint32_t &end); void JunkLeftoverFilters(uint32_t max); - void FindCommonFolder(LumpFilterInfo* filter); - static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); + void FindCommonFolder(FileSystemFilterInfo* filter); + static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); public: - static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); - static FResourceFile *OpenResourceFile(const char *filename, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); - static FResourceFile *OpenDirectory(const char *filename, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); + static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool containeronly = false, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); + static FResourceFile *OpenResourceFile(const char *filename, bool containeronly = false, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); + static FResourceFile *OpenDirectory(const char *filename, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); virtual ~FResourceFile(); // If this FResourceFile represents a directory, the Reader object is not usable so don't return it. FileReader *GetContainerReader() { return Reader.isOpen()? &Reader : nullptr; } const char* GetFileName() const { return FileName; } uint32_t GetFirstEntry() const { return FirstLump; } - void SetFirstLump(uint32_t f) { FirstLump = f; } + int GetFlags() const noexcept { return flags; } + void SetFirstFile(uint32_t f) { FirstLump = f; } const char* GetHash() const { return Hash; } int EntryCount() const { return NumLumps; } @@ -175,11 +152,6 @@ class FResourceFile return (entry < NumLumps) ? Entries[entry].Flags : 0; } - int GetEntryNamespace(uint32_t entry) - { - return (entry < NumLumps) ? Entries[entry].Namespace : (int)ns_hidden; - } - int GetEntryResourceID(uint32_t entry) { return (entry < NumLumps) ? Entries[entry].ResourceID : -1; diff --git a/source/common/filesystem/source/file_7z.cpp b/source/common/filesystem/source/file_7z.cpp index 21d6049e37d..6a5e135e9f9 100644 --- a/source/common/filesystem/source/file_7z.cpp +++ b/source/common/filesystem/source/file_7z.cpp @@ -177,7 +177,7 @@ class F7ZFile : public FResourceFile public: F7ZFile(const char * filename, FileReader &filer, StringPool* sp); - bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); + bool Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf); virtual ~F7ZFile(); FileData Read(uint32_t entry) override; FileReader GetEntryReader(uint32_t entry, int, int) override; @@ -192,7 +192,7 @@ class F7ZFile : public FResourceFile //========================================================================== F7ZFile::F7ZFile(const char * filename, FileReader &filer, StringPool* sp) - : FResourceFile(filename, filer, sp) + : FResourceFile(filename, filer, sp, 0) { Archive = nullptr; } @@ -204,7 +204,7 @@ F7ZFile::F7ZFile(const char * filename, FileReader &filer, StringPool* sp) // //========================================================================== -bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf) +bool F7ZFile::Open(FileSystemFilterInfo *filter, FileSystemMessageFunc Printf) { Archive = new C7zArchive(Reader); int skipped = 0; @@ -268,7 +268,6 @@ bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf) Entries[j].Length = SzArEx_GetFileSize(archPtr, i); Entries[j].Flags = RESFF_FULLPATH|RESFF_COMPRESSED; Entries[j].ResourceID = -1; - Entries[j].Namespace = ns_global; Entries[j].Method = METHOD_INVALID; Entries[j].Position = i; j++; @@ -351,7 +350,7 @@ FileReader F7ZFile::GetEntryReader(uint32_t entry, int, int) // //========================================================================== -FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *Check7Z(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[k7zSignatureSize]; diff --git a/source/common/filesystem/source/file_directory.cpp b/source/common/filesystem/source/file_directory.cpp index ca87fd9ea00..40b4df2f935 100644 --- a/source/common/filesystem/source/file_directory.cpp +++ b/source/common/filesystem/source/file_directory.cpp @@ -57,11 +57,11 @@ class FDirectory : public FResourceFile const char** SystemFilePath; - int AddDirectory(const char* dirpath, LumpFilterInfo* filter, FileSystemMessageFunc Printf); + int AddDirectory(const char* dirpath, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf); public: FDirectory(const char * dirname, StringPool* sp, bool nosubdirflag = false); - bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); + bool Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf); FileReader GetEntryReader(uint32_t entry, int, int) override; }; @@ -74,7 +74,7 @@ class FDirectory : public FResourceFile //========================================================================== FDirectory::FDirectory(const char * directory, StringPool* sp, bool nosubdirflag) - : FResourceFile("", sp), nosubdir(nosubdirflag) + : FResourceFile("", sp, 0), nosubdir(nosubdirflag) { auto fn = FS_FullPath(directory); if (fn.back() != '/') fn += '/'; @@ -87,7 +87,7 @@ FDirectory::FDirectory(const char * directory, StringPool* sp, bool nosubdirflag // //========================================================================== -int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSystemMessageFunc Printf) +int FDirectory::AddDirectory(const char *dirpath, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf) { int count = 0; @@ -141,7 +141,6 @@ int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSy Entries[count].Flags = RESFF_FULLPATH; Entries[count].ResourceID = -1; Entries[count].Method = METHOD_STORED; - Entries[count].Namespace = ns_global; Entries[count].Position = count; count++; } @@ -157,7 +156,7 @@ int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSy // //========================================================================== -bool FDirectory::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf) +bool FDirectory::Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf) { NumLumps = AddDirectory(FileName, filter, Printf); PostProcessArchive(filter); @@ -193,7 +192,7 @@ FileReader FDirectory::GetEntryReader(uint32_t entry, int readertype, int) // //========================================================================== -FResourceFile *CheckDir(const char *filename, bool nosubdirflag, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckDir(const char *filename, bool nosubdirflag, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { auto rf = new FDirectory(filename, sp, nosubdirflag); if (rf->Open(filter, Printf)) return rf; diff --git a/source/common/filesystem/source/file_grp.cpp b/source/common/filesystem/source/file_grp.cpp index 57206b4b102..25f79c6ec50 100644 --- a/source/common/filesystem/source/file_grp.cpp +++ b/source/common/filesystem/source/file_grp.cpp @@ -71,7 +71,7 @@ struct GrpLump // //========================================================================== -static bool OpenGrp(FResourceFile* file, LumpFilterInfo* filter) +static bool OpenGrp(FResourceFile* file, FileSystemFilterInfo* filter) { GrpHeader header; @@ -91,7 +91,6 @@ static bool OpenGrp(FResourceFile* file, LumpFilterInfo* filter) Entries[i].CompressedSize = Entries[i].Length = LittleLong(fileinfo[i].Size); Position += fileinfo[i].Size; Entries[i].Flags = 0; - Entries[i].Namespace = ns_global; fileinfo[i].NameWithZero[12] = '\0'; // Be sure filename is null-terminated Entries[i].ResourceID = -1; Entries[i].Method = METHOD_STORED; @@ -109,7 +108,7 @@ static bool OpenGrp(FResourceFile* file, LumpFilterInfo* filter) // //========================================================================== -FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckGRP(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[12]; @@ -120,7 +119,7 @@ FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "KenSilverman", 12)) { - auto rf = new FResourceFile(filename, file, sp); + auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES); if (OpenGrp(rf, filter)) return rf; file = rf->Destroy(); } diff --git a/source/common/filesystem/source/file_hog.cpp b/source/common/filesystem/source/file_hog.cpp index d12f7e2d86e..0ed4fa7ce00 100644 --- a/source/common/filesystem/source/file_hog.cpp +++ b/source/common/filesystem/source/file_hog.cpp @@ -44,7 +44,7 @@ namespace FileSys { -static bool OpenHog(FResourceFile* rf, LumpFilterInfo* filter) +static bool OpenHog(FResourceFile* rf, FileSystemFilterInfo* filter) { auto Reader = rf->GetContainerReader(); FileReader::Size length = Reader->GetLength(); @@ -66,7 +66,6 @@ static bool OpenHog(FResourceFile* rf, LumpFilterInfo* filter) Entry.CompressedSize = Entry.Length = elength; Entry.Flags = 0; Entry.CRC32 = 0; - Entry.Namespace = ns_global; Entry.ResourceID = -1; Entry.Method = METHOD_STORED; Entry.FileName = rf->NormalizeFileName(name); @@ -86,7 +85,7 @@ static bool OpenHog(FResourceFile* rf, LumpFilterInfo* filter) // //========================================================================== -FResourceFile* CheckHog(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile* CheckHog(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[3]; @@ -96,7 +95,7 @@ FResourceFile* CheckHog(const char* filename, FileReader& file, LumpFilterInfo* file.Read(&head, 3); if (!memcmp(head, "DHF", 3)) { - auto rf = new FResourceFile(filename, file, sp); + auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES); if (OpenHog(rf, filter)) return rf; file = rf->Destroy(); } diff --git a/source/common/filesystem/source/file_hog2.cpp b/source/common/filesystem/source/file_hog2.cpp new file mode 100644 index 00000000000..10cc327cc39 --- /dev/null +++ b/source/common/filesystem/source/file_hog2.cpp @@ -0,0 +1,107 @@ +/* +** file_hog.cpp +** +** reads Descent 3 .hog2 files +** +**--------------------------------------------------------------------------- +** Copyright 2024 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** +*/ + + +#include "resourcefile.h" +#include "fs_swap.h" + +namespace FileSys { + using namespace byteswap; + + + +static bool OpenHog2(FResourceFile* rf, FileSystemFilterInfo* filter) +{ + auto Reader = rf->GetContainerReader(); + FileReader::Size length = Reader->GetLength(); + + uint32_t numfiles = Reader->ReadUInt32(); + uint32_t offset = Reader->ReadUInt32(); // offset to first file (end of file list) + Reader->Seek(56, FileReader::SeekEnd); // filled with FF + auto Entries = rf->AllocateEntries((int)numfiles); + + for(uint32_t i = 0; i < numfiles; i++) + { + char name[37]; + Reader->Read(name, 36); + name[36] = 0; + Reader->ReadUInt32(); + uint32_t size = Reader->ReadUInt32();; + Reader->ReadUInt32(); + + FResourceEntry& Entry = Entries[i]; + Entry.Position = offset; + Entry.CompressedSize = Entry.Length = size; + Entry.Flags = RESFF_FULLPATH; + Entry.CRC32 = 0; + Entry.ResourceID = -1; + Entry.Method = METHOD_STORED; + Entry.FileName = rf->NormalizeFileName(name); + offset += size; + } + rf->GenerateHash(); + return true; +} + + +//========================================================================== +// +// File open +// +//========================================================================== + +FResourceFile* CheckHog2(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +{ + char head[4]; + + if (file.GetLength() >= 68) + { + file.Seek(0, FileReader::SeekSet); + file.Read(&head, 4); + if (!memcmp(head, "HOG2", 4)) + { + auto rf = new FResourceFile(filename, file, sp, 0); + if (OpenHog2(rf, filter)) return rf; + file = rf->Destroy(); + } + file.Seek(0, FileReader::SeekSet); + } + return nullptr; +} + + +} + diff --git a/source/common/filesystem/source/file_lump.cpp b/source/common/filesystem/source/file_lump.cpp index b01d46b5d36..37dee28bd05 100644 --- a/source/common/filesystem/source/file_lump.cpp +++ b/source/common/filesystem/source/file_lump.cpp @@ -41,11 +41,10 @@ namespace FileSys { // //========================================================================== -static bool OpenLump(FResourceFile* file, LumpFilterInfo*) +static bool OpenLump(FResourceFile* file, FileSystemFilterInfo*) { auto Entries = file->AllocateEntries(1); Entries[0].FileName = file->NormalizeFileName(ExtractBaseName(file->GetFileName(), true).c_str()); - Entries[0].Namespace = ns_global; Entries[0].ResourceID = -1; Entries[0].Position = 0; Entries[0].CompressedSize = Entries[0].Length = file->GetContainerReader()->GetLength(); @@ -60,10 +59,10 @@ static bool OpenLump(FResourceFile* file, LumpFilterInfo*) // //========================================================================== -FResourceFile *CheckLump(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckLump(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { // always succeeds - auto rf = new FResourceFile(filename, file, sp); + auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS); if (OpenLump(rf, filter)) return rf; file = rf->Destroy(); return NULL; diff --git a/source/common/filesystem/source/file_mvl.cpp b/source/common/filesystem/source/file_mvl.cpp index f08db316187..c9ebf0f8ca7 100644 --- a/source/common/filesystem/source/file_mvl.cpp +++ b/source/common/filesystem/source/file_mvl.cpp @@ -43,7 +43,7 @@ namespace FileSys { -static bool OpenMvl(FResourceFile* rf, LumpFilterInfo* filter) +static bool OpenMvl(FResourceFile* rf, FileSystemFilterInfo* filter) { auto Reader = rf->GetContainerReader(); auto count = Reader->ReadUInt32(); @@ -75,7 +75,7 @@ static bool OpenMvl(FResourceFile* rf, LumpFilterInfo* filter) // //========================================================================== -FResourceFile* CheckMvl(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile* CheckMvl(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[4]; @@ -85,7 +85,7 @@ FResourceFile* CheckMvl(const char* filename, FileReader& file, LumpFilterInfo* file.Read(&head, 4); if (!memcmp(head, "DMVL", 4)) { - auto rf = new FResourceFile(filename, file, sp); + auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES); if (OpenMvl(rf, filter)) return rf; file = rf->Destroy(); } diff --git a/source/common/filesystem/source/file_pak.cpp b/source/common/filesystem/source/file_pak.cpp index b66a0f3d99f..84265f2ebe7 100644 --- a/source/common/filesystem/source/file_pak.cpp +++ b/source/common/filesystem/source/file_pak.cpp @@ -63,7 +63,7 @@ struct dpackheader_t // //========================================================================== -static bool OpenPak(FResourceFile* file, LumpFilterInfo* filter) +static bool OpenPak(FResourceFile* file, FileSystemFilterInfo* filter) { dpackheader_t header; @@ -82,7 +82,6 @@ static bool OpenPak(FResourceFile* file, LumpFilterInfo* filter) Entries[i].Position = LittleLong(fileinfo[i].filepos); Entries[i].CompressedSize = Entries[i].Length = LittleLong(fileinfo[i].filelen); Entries[i].Flags = RESFF_FULLPATH; - Entries[i].Namespace = ns_global; Entries[i].ResourceID = -1; Entries[i].Method = METHOD_STORED; Entries[i].FileName = file->NormalizeFileName(fileinfo[i].name); @@ -99,7 +98,7 @@ static bool OpenPak(FResourceFile* file, LumpFilterInfo* filter) // //========================================================================== -FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckPak(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[4]; @@ -110,7 +109,7 @@ FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "PACK", 4)) { - auto rf = new FResourceFile(filename, file, sp); + auto rf = new FResourceFile(filename, file, sp, 0); if (OpenPak(rf, filter)) return rf; file = rf->Destroy(); } diff --git a/source/common/filesystem/source/file_rff.cpp b/source/common/filesystem/source/file_rff.cpp index 673a08ce060..e887b7fd759 100644 --- a/source/common/filesystem/source/file_rff.cpp +++ b/source/common/filesystem/source/file_rff.cpp @@ -91,7 +91,7 @@ void BloodCrypt (void *data, int key, int len) // //========================================================================== -static bool OpenRFF(FResourceFile* file, LumpFilterInfo*) +static bool OpenRFF(FResourceFile* file, FileSystemFilterInfo*) { RFFLump *lumps; RFFInfo header; @@ -123,7 +123,6 @@ static bool OpenRFF(FResourceFile* file, LumpFilterInfo*) Entries[i].Flags = 0; Entries[i].Method = METHOD_STORED; } - Entries[i].Namespace = ns_global; Entries[i].ResourceID = LittleLong(lumps[i].IndexNum); // Rearrange the name and extension to construct the fullname. @@ -150,7 +149,7 @@ static bool OpenRFF(FResourceFile* file, LumpFilterInfo*) // //========================================================================== -FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckRFF(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[4]; @@ -161,7 +160,7 @@ FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "RFF\x1a", 4)) { - auto rf = new FResourceFile(filename, file, sp); + auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES); if (OpenRFF(rf, filter)) return rf; file = rf->Destroy(); } diff --git a/source/common/filesystem/source/file_ssi.cpp b/source/common/filesystem/source/file_ssi.cpp index 82885c6bb7c..47c7b53b032 100644 --- a/source/common/filesystem/source/file_ssi.cpp +++ b/source/common/filesystem/source/file_ssi.cpp @@ -44,7 +44,7 @@ namespace FileSys { // //========================================================================== -static bool OpenSSI(FResourceFile* file, int version, int EntryCount, LumpFilterInfo*) +static bool OpenSSI(FResourceFile* file, int version, int EntryCount, FileSystemFilterInfo*) { uint32_t NumLumps = EntryCount * 2; auto Entries = file->AllocateEntries(NumLumps); @@ -65,7 +65,6 @@ static bool OpenSSI(FResourceFile* file, int version, int EntryCount, LumpFilter Entries[i].Position = j; Entries[i].CompressedSize = Entries[i].Length = flength; Entries[i].Flags = 0; - Entries[i].Namespace = ns_global; Entries[i].Method = METHOD_STORED; Entries[i].ResourceID = -1; Entries[i].FileName = file->NormalizeFileName(fn); @@ -78,7 +77,6 @@ static bool OpenSSI(FResourceFile* file, int version, int EntryCount, LumpFilter Entries[i + 1].Position = j; Entries[i + 1].CompressedSize = Entries[i + 1].Length = flength; Entries[i + 1].Flags = 0; - Entries[i + 1].Namespace = ns_global; Entries[i + 1].ResourceID = -1; Entries[i + 1].FileName = file->NormalizeFileName(fn); Entries[i + 1].Method = METHOD_STORED; @@ -99,7 +97,7 @@ static bool OpenSSI(FResourceFile* file, int version, int EntryCount, LumpFilter // //========================================================================== -FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile* CheckSSI(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char zerobuf[72]; char buf[72]; @@ -129,7 +127,7 @@ FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* { if (!skipstring(70)) return nullptr; } - auto ssi = new FResourceFile(filename, file, sp); + auto ssi = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES); if (OpenSSI(ssi, version, numfiles, filter)) return ssi; file = ssi->Destroy(); } diff --git a/source/common/filesystem/source/file_wad.cpp b/source/common/filesystem/source/file_wad.cpp index 4f8574b73d7..3fe736bb024 100644 --- a/source/common/filesystem/source/file_wad.cpp +++ b/source/common/filesystem/source/file_wad.cpp @@ -58,52 +58,22 @@ struct wadlump_t char Name[8]; }; -//========================================================================== -// -// Wad file -// -//========================================================================== - -class FWadFile : public FResourceFile -{ - bool IsMarker(int lump, const char *marker); - void SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, FileSystemMessageFunc Printf, bool flathack=false); - void SkinHack (FileSystemMessageFunc Printf); - -public: - FWadFile(const char * filename, FileReader &file, StringPool* sp); - bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); -}; - - -//========================================================================== -// -// FWadFile::FWadFile -// -// Initializes a WAD file -// -//========================================================================== - -FWadFile::FWadFile(const char *filename, FileReader &file, StringPool* sp) - : FResourceFile(filename, file, sp) -{ -} - //========================================================================== // // Open it // //========================================================================== -bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf) +static bool OpenWAD(FResourceFile* file, FileSystemFilterInfo*, FileSystemMessageFunc Printf) { wadinfo_t header; uint32_t InfoTableOfs; bool isBigEndian = false; // Little endian is assumed until proven otherwise - auto wadSize = Reader.GetLength(); + auto Reader = file->GetContainerReader(); + auto wadSize = Reader->GetLength(); - Reader.Read(&header, sizeof(header)); - NumLumps = LittleLong(header.NumLumps); + Reader->Read(&header, sizeof(header)); + uint32_t NumLumps = LittleLong(header.NumLumps); InfoTableOfs = LittleLong(header.InfoTableOfs); // Check to see if the little endian interpretation is valid @@ -117,16 +87,16 @@ bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf) // Check again to detect broken wads if (InfoTableOfs + NumLumps*sizeof(wadlump_t) > (unsigned)wadSize) { - Printf(FSMessageLevel::Error, "%s: Bad directory offset.\n", FileName); + Printf(FSMessageLevel::Error, "%s: Bad directory offset.\n", file->GetFileName()); return false; } } - Reader.Seek(InfoTableOfs, FileReader::SeekSet); - auto fd = Reader.Read(NumLumps * sizeof(wadlump_t)); + Reader->Seek(InfoTableOfs, FileReader::SeekSet); + auto fd = Reader->Read(NumLumps * sizeof(wadlump_t)); auto fileinfo = (const wadlump_t*)fd.data(); - AllocateEntries(NumLumps); + auto Entries = file->AllocateEntries(NumLumps); for(uint32_t i = 0; i < NumLumps; i++) { @@ -143,17 +113,17 @@ bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf) else if (ishigh > 1) { // This may not end up printing something proper because we do not know what encoding might have been used. - Printf(FSMessageLevel::Warning, "%s: Lump name %.8s contains invalid characters\n", FileName, fileinfo[i].Name); + Printf(FSMessageLevel::Warning, "%s: Lump name %.8s contains invalid characters\n", file->GetFileName(), fileinfo[i].Name); + n[0] = 0; } Entries[i].FileName = nullptr; Entries[i].Position = isBigEndian ? BigLong(fileinfo[i].FilePos) : LittleLong(fileinfo[i].FilePos); Entries[i].CompressedSize = Entries[i].Length = isBigEndian ? BigLong(fileinfo[i].Size) : LittleLong(fileinfo[i].Size); - Entries[i].Namespace = ns_global; Entries[i].Flags = ishigh? RESFF_SHORTNAME | RESFF_COMPRESSED : RESFF_SHORTNAME; Entries[i].Method = ishigh == 1? METHOD_LZSS : METHOD_STORED; - Entries[i].FileName = stringpool->Strdup(n); + Entries[i].FileName = file->NormalizeFileName(n, 0, true); // This doesn't set up the namespace yet. } for (uint32_t i = 0; i < NumLumps; i++) @@ -161,250 +131,21 @@ bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf) if (Entries[i].Method == METHOD_LZSS) { // compressed size is implicit. - Entries[i].CompressedSize = (i == NumLumps - 1 ? Reader.GetLength() : Entries[i + 1].Position) - Entries[i].Position; + Entries[i].CompressedSize = (i == NumLumps - 1 ? Reader->GetLength() : Entries[i + 1].Position) - Entries[i].Position; } } - - GenerateHash(); // Do this before the lump processing below. - - SetNamespace("s_start", "s_end", ns_sprites, Printf); - SetNamespace("f_start", "f_end", ns_flats, Printf, true); - SetNamespace("c_start", "c_end", ns_colormaps, Printf); - SetNamespace("a_start", "a_end", ns_acslibrary, Printf); - SetNamespace("tx_start", "tx_end", ns_newtextures, Printf); - SetNamespace("v_start", "v_end", ns_strifevoices, Printf); - SetNamespace("hi_start", "hi_end", ns_hires, Printf); - SetNamespace("vx_start", "vx_end", ns_voxels, Printf); - SkinHack(Printf); - + file->GenerateHash(); // Do this before the lump processing below. return true; } -//========================================================================== -// -// IsMarker -// -// (from BOOM) -// -//========================================================================== - -inline bool FWadFile::IsMarker(int lump, const char *marker) -{ - if (Entries[lump].FileName[0] == marker[0]) - { - return (!strcmp(Entries[lump].FileName, marker) || - (marker[1] == '_' && !strcmp(Entries[lump].FileName +1, marker))); - } - else return false; -} - -//========================================================================== -// -// SetNameSpace -// -// Sets namespace information for the lumps. It always looks for the first -// x_START and the last x_END lump, except when loading flats. In this case -// F_START may be absent and if that is the case all lumps with a size of -// 4096 will be flagged appropriately. -// -//========================================================================== - -// This class was supposed to be local in the function but GCC -// does not like that. -struct Marker -{ - int markertype; - unsigned int index; -}; - -void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, FileSystemMessageFunc Printf, bool flathack) -{ - bool warned = false; - int numstartmarkers = 0, numendmarkers = 0; - unsigned int i; - std::vector markers; - - for(i = 0; i < NumLumps; i++) - { - if (IsMarker(i, startmarker)) - { - Marker m = { 0, i }; - markers.push_back(m); - numstartmarkers++; - } - else if (IsMarker(i, endmarker)) - { - Marker m = { 1, i }; - markers.push_back(m); - numendmarkers++; - } - } - - if (numstartmarkers == 0) - { - if (numendmarkers == 0) return; // no markers found - - Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker); - - - if (flathack) - { - // We have found no F_START but one or more F_END markers. - // mark all lumps before the last F_END marker as potential flats. - unsigned int end = markers[markers.size()-1].index; - for(unsigned int ii = 0; ii < end; ii++) - { - if (Entries[ii].Length == 4096) - { - // We can't add this to the flats namespace but - // it needs to be flagged for the texture manager. - Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName, Entries[ii].FileName); - Entries[ii].Flags |= RESFF_MAYBEFLAT; - } - } - } - return; - } - - i = 0; - while (i < markers.size()) - { - int start, end; - if (markers[i].markertype != 0) - { - Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker); - i++; - continue; - } - start = i++; - - // skip over subsequent x_START markers - while (i < markers.size() && markers[i].markertype == 0) - { - Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, startmarker); - i++; - continue; - } - // same for x_END markers - while (i < markers.size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1)) - { - Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, endmarker); - i++; - continue; - } - // We found a starting marker but no end marker. Ignore this block. - if (i >= markers.size()) - { - Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, startmarker, endmarker); - end = NumLumps; - } - else - { - end = markers[i++].index; - } - - // we found a marked block - Printf(FSMessageLevel::DebugNotify, "%s: Found %s block at (%d-%d)\n", FileName, startmarker, markers[start].index, end); - for(int j = markers[start].index + 1; j < end; j++) - { - if (Entries[j].Namespace != ns_global) - { - if (!warned) - { - Printf(FSMessageLevel::Warning, "%s: Overlapping namespaces found (lump %d)\n", FileName, j); - } - warned = true; - } - else if (space == ns_sprites && Entries[j].Length < 8) - { - // sf 26/10/99: - // ignore sprite lumps smaller than 8 bytes (the smallest possible) - // in size -- this was used by some dmadds wads - // as an 'empty' graphics resource - Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName, Entries[j].FileName, j); - } - else - { - Entries[j].Namespace = space; - } - } - } -} - - -//========================================================================== -// -// W_SkinHack -// -// Tests a wad file to see if it contains an S_SKIN marker. If it does, -// every lump in the wad is moved into a new namespace. Because skins are -// only supposed to replace player sprites, sounds, or faces, this should -// not be a problem. Yes, there are skins that replace more than that, but -// they are such a pain, and breaking them like this was done on purpose. -// This also renames any S_SKINxx lumps to just S_SKIN. -// -//========================================================================== - -void FWadFile::SkinHack (FileSystemMessageFunc Printf) -{ - // this being static is not a problem. The only relevant thing is that each skin gets a different number. - static int namespc = ns_firstskin; - bool skinned = false; - bool hasmap = false; - uint32_t i; - - for (i = 0; i < NumLumps; i++) - { - auto lump = &Entries[i]; - - if (!strnicmp(lump->FileName, "S_SKIN", 6)) - { // Wad has at least one skin. - lump->FileName = "S_SKIN"; - if (!skinned) - { - skinned = true; - uint32_t j; - - for (j = 0; j < NumLumps; j++) - { - Entries[j].Namespace = namespc; - } - namespc++; - } - } - // needless to say, this check is entirely useless these days as map names can be more diverse.. - if ((lump->FileName[0] == 'M' && - lump->FileName[1] == 'A' && - lump->FileName[2] == 'P' && - lump->FileName[3] >= '0' && lump->FileName[3] <= '9' && - lump->FileName[4] >= '0' && lump->FileName[4] <= '9' && - lump->FileName[5] == '\0') - || - (lump->FileName[0] == 'E' && - lump->FileName[1] >= '0' && lump->FileName[1] <= '9' && - lump->FileName[2] == 'M' && - lump->FileName[3] >= '0' && lump->FileName[3] <= '9' && - lump->FileName[4] == '\0')) - { - hasmap = true; - } - } - if (skinned && hasmap) - { - Printf(FSMessageLevel::Attention, "%s: The maps will not be loaded because it has a skin.\n", FileName); - Printf(FSMessageLevel::Attention, "You should remove the skin from the wad to play these maps.\n"); - } -} - - //========================================================================== // // File open // //========================================================================== -FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckWad(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[4]; @@ -415,8 +156,8 @@ FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "IWAD", 4) || !memcmp(head, "PWAD", 4)) { - auto rf = new FWadFile(filename, file, sp); - if (rf->Open(filter, Printf)) return rf; + auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::NO_EXTENSIONS | FResourceFile::SHORTNAMES); + if (OpenWAD(rf, filter, Printf)) return rf; file = rf->Destroy(); } diff --git a/source/common/filesystem/source/file_whres.cpp b/source/common/filesystem/source/file_whres.cpp index d1d2d1a508b..a4cc5dd937d 100644 --- a/source/common/filesystem/source/file_whres.cpp +++ b/source/common/filesystem/source/file_whres.cpp @@ -47,7 +47,7 @@ namespace FileSys { // //========================================================================== -bool OpenWHRes(FResourceFile* file, LumpFilterInfo*) +bool OpenWHRes(FResourceFile* file, FileSystemFilterInfo*) { uint32_t directory[1024]; @@ -83,7 +83,6 @@ bool OpenWHRes(FResourceFile* file, LumpFilterInfo*) Entries[i].Position = offset; Entries[i].CompressedSize = Entries[i].Length = length; Entries[i].Flags = RESFF_FULLPATH; - Entries[i].Namespace = ns_global; Entries[i].ResourceID = -1; Entries[i].Method = METHOD_STORED; Entries[i].FileName = file->NormalizeFileName(synthname.c_str()); @@ -99,7 +98,7 @@ bool OpenWHRes(FResourceFile* file, LumpFilterInfo*) // //========================================================================== -FResourceFile *CheckWHRes(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckWHRes(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { if (file.GetLength() >= 8192) // needs to be at least 8192 to contain one file and the directory. { @@ -119,7 +118,7 @@ FResourceFile *CheckWHRes(const char *filename, FileReader &file, LumpFilterInfo if (offset != checkpos || length == 0 || offset + length >= (size_t)size - 4096 ) return nullptr; checkpos += (length+4095) / 4096; } - auto rf = new FResourceFile(filename, file, sp); + auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_EXTENSIONS); if (OpenWHRes(rf, filter)) return rf; file = rf->Destroy(); } diff --git a/source/common/filesystem/source/file_zip.cpp b/source/common/filesystem/source/file_zip.cpp index 8351b714648..d49da9e5e61 100644 --- a/source/common/filesystem/source/file_zip.cpp +++ b/source/common/filesystem/source/file_zip.cpp @@ -113,7 +113,7 @@ class FZipFile : public FResourceFile public: FZipFile(const char* filename, FileReader& file, StringPool* sp); - bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); + bool Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf); FCompressedBuffer GetRawData(uint32_t entry) override; }; @@ -124,11 +124,11 @@ class FZipFile : public FResourceFile //========================================================================== FZipFile::FZipFile(const char * filename, FileReader &file, StringPool* sp) -: FResourceFile(filename, file, sp) +: FResourceFile(filename, file, sp, 0) { } -bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf) +bool FZipFile::Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf) { bool zip64 = false; uint32_t centraldir = Zip_FindCentralDir(Reader, &zip64); @@ -376,7 +376,7 @@ void FZipFile::SetEntryAddress(uint32_t entry) // //========================================================================== -FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckZip(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[4]; diff --git a/source/common/filesystem/source/filesystem.cpp b/source/common/filesystem/source/filesystem.cpp index fee5f101143..104b306a051 100644 --- a/source/common/filesystem/source/filesystem.cpp +++ b/source/common/filesystem/source/filesystem.cpp @@ -52,28 +52,6 @@ namespace FileSys { // MACROS ------------------------------------------------------------------ -#define NULL_INDEX (0xffffffff) - -static void UpperCopy(char* to, const char* from) -{ - int i; - - for (i = 0; i < 8 && from[i]; i++) - to[i] = toupper(from[i]); - for (; i < 8; i++) - to[i] = 0; -} - - -//djb2 -static uint32_t MakeHash(const char* str, size_t length = SIZE_MAX) -{ - uint32_t hash = 5381; - uint32_t c; - while (length-- > 0 && (c = *str++)) hash = hash * 33 + (c | 32); - return hash; -} - static void md5Hash(FileReader& reader, uint8_t* digest) { using namespace md5; @@ -92,15 +70,13 @@ static void md5Hash(FileReader& reader, uint8_t* digest) struct FileSystem::LumpRecord { FResourceFile *resfile; - LumpShortName shortName; - const char* LongName; + const char* Name; int resindex; int16_t rfnum; // this is not necessarily the same as resfile's index! - int16_t Namespace; int resourceId; int flags; - void SetFromLump(FResourceFile* file, int fileindex, int filenum, StringPool* sp, const char* name = nullptr) + void SetFromFile(FResourceFile* file, int fileindex, int filenum, StringPool* sp, const char* name = nullptr) { resfile = file; resindex = fileindex; @@ -109,52 +85,24 @@ struct FileSystem::LumpRecord auto lflags = file->GetEntryFlags(fileindex); if (!name) name = file->getName(fileindex); - if (lflags & RESFF_SHORTNAME) + if ((lflags & RESFF_EMBEDDED) || !name || !*name) { - UpperCopy(shortName.String, name); - shortName.String[8] = 0; - LongName = ""; - Namespace = file->GetEntryNamespace(fileindex); - resourceId = -1; - } - else if ((lflags & RESFF_EMBEDDED) || !name || !*name) - { - shortName.qword = 0; - LongName = ""; - Namespace = ns_hidden; + Name = ""; resourceId = -1; } else { - LongName = name; + Name = name; resourceId = file->GetEntryResourceID(fileindex); - // Map some directories to WAD namespaces. - // Note that some of these namespaces don't exist in WADS. - // CheckNumForName will handle any request for these namespaces accordingly. - Namespace = !strncmp(LongName, "flats/", 6) ? ns_flats : - !strncmp(LongName, "textures/", 9) ? ns_newtextures : - !strncmp(LongName, "hires/", 6) ? ns_hires : - !strncmp(LongName, "sprites/", 8) ? ns_sprites : - !strncmp(LongName, "voxels/", 7) ? ns_voxels : - !strncmp(LongName, "colormaps/", 10) ? ns_colormaps : - !strncmp(LongName, "acs/", 4) ? ns_acslibrary : - !strncmp(LongName, "voices/", 7) ? ns_strifevoices : - !strncmp(LongName, "patches/", 8) ? ns_patches : - !strncmp(LongName, "graphics/", 9) ? ns_graphics : - !strncmp(LongName, "sounds/", 7) ? ns_sounds : - !strncmp(LongName, "music/", 6) ? ns_music : - !strchr(LongName, '/') ? ns_global : - ns_hidden; - - if (Namespace == ns_hidden) shortName.qword = 0; - else if (strstr(LongName, ".{")) + // allow embedding a resource ID in the name - we need to strip that out here. + if (strstr(Name, ".{")) { - std::string longName = LongName; + std::string longName = Name; ptrdiff_t encodedResID = longName.find_last_of(".{"); if (resourceId == -1 && (size_t)encodedResID != std::string::npos) { - const char* p = LongName + encodedResID; + const char* p = Name + encodedResID; char* q; int id = (int)strtoull(p + 2, &q, 10); // only decimal numbers allowed here. if (q[0] == '}' && (q[1] == '.' || q[1] == 0)) @@ -162,27 +110,13 @@ struct FileSystem::LumpRecord longName.erase(longName.begin() + encodedResID, longName.begin() + (q - p) + 1); resourceId = id; } - LongName = sp->Strdup(longName.c_str()); + Name = sp->Strdup(longName.c_str()); } } - auto slash = strrchr(LongName, '/'); - std::string base = slash ? (slash + 1) : LongName; + auto slash = strrchr(Name, '/'); + std::string base = slash ? (slash + 1) : Name; auto dot = base.find_last_of('.'); if (dot != std::string::npos) base.resize(dot); - UpperCopy(shortName.String, base.c_str()); - - // Since '\' can't be used as a file name's part inside a ZIP - // we have to work around this for sprites because it is a valid - // frame character. - if (Namespace == ns_sprites || Namespace == ns_voxels || Namespace == ns_hires) - { - char* c; - - while ((c = (char*)memchr(shortName.String, '^', 8))) - { - *c = '\\'; - } - } } } }; @@ -223,22 +157,16 @@ void FileSystem::DeleteAll () //========================================================================== // -// InitMultipleFiles +// Initialize // -// Pass a null terminated list of files to use. All files are optional, +// Pass a vector of files to use. All files are optional, // but at least one file must be found. File names can appear multiple // times. The name searcher looks backwards, so a later file can // override an earlier one. // //========================================================================== -bool FileSystem::InitSingleFile(const char* filename, FileSystemMessageFunc Printf) -{ - std::vector filenames = { filename }; - return InitMultipleFiles(filenames, nullptr, Printf); -} - -bool FileSystem::InitMultipleFiles (std::vector& filenames, LumpFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates, FILE* hashfile) +bool FileSystem::InitFiles(std::vector& filenames, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates) { int numfiles; @@ -254,9 +182,9 @@ bool FileSystem::InitMultipleFiles (std::vector& filenames, LumpFil // first, check for duplicates if (!allowduplicates) { - for (size_t i=0;i& filenames, LumpFil } } - for(size_t i=0;iGetHash(); - MoveLumpsInFolder(path.c_str()); + MoveFilesInFolder(path.c_str()); } NumEntries = (uint32_t)FileInfo.size(); @@ -282,6 +210,12 @@ bool FileSystem::InitMultipleFiles (std::vector& filenames, LumpFil { return false; } + return true; +} + +bool FileSystem::Initialize(std::vector& filenames, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates) +{ + if (!InitFiles(filenames, filter, Printf, allowduplicates)) return false; if (filter && filter->postprocessFunc) filter->postprocessFunc(); // [RH] Set up hash table @@ -303,8 +237,8 @@ int FileSystem::AddFromBuffer(const char* name, char* data, int size, int id, in FileData blob(data, size); fr.OpenMemoryArray(blob); - // wrap this into a single lump resource file (should be done a little better later.) - auto rf = new FResourceFile(name, fr, stringpool); + // wrap this into a single filenum resource file (should be done a little better later.) + auto rf = new FResourceFile(name, fr, stringpool, 0); auto Entries = rf->AllocateEntries(1); Entries[0].FileName = rf->NormalizeFileName(ExtractBaseName(name, true).c_str()); Entries[0].ResourceID = -1; @@ -312,8 +246,8 @@ int FileSystem::AddFromBuffer(const char* name, char* data, int size, int id, in Files.push_back(rf); FileInfo.resize(FileInfo.size() + 1); - FileSystem::LumpRecord* lump_p = &FileInfo.back(); - lump_p->SetFromLump(rf, 0, (int)Files.size() - 1, stringpool); + FileSystem::LumpRecord* file_p = &FileInfo.back(); + file_p->SetFromFile(rf, 0, (int)Files.size() - 1, stringpool); return (int)FileInfo.size() - 1; } @@ -322,12 +256,12 @@ int FileSystem::AddFromBuffer(const char* name, char* data, int size, int id, in // AddFile // // Files with a .wad extension are wadlink files with multiple lumps, -// other files are single lumps with the base filename for the lump name. +// other files are single lumps with the base filename for the filenum name. // // [RH] Removed reload hack //========================================================================== -void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInfo* filter, FileSystemMessageFunc Printf, FILE* hashfile) +void FileSystem::AddFile (const char *filename, FileReader *filer, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf) { int startlump; bool isdir = false; @@ -374,17 +308,17 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInf if (resfile != NULL) { if (Printf) - Printf(FSMessageLevel::Message, "adding %s, %d lumps\n", filename, resfile->EntryCount()); + Printf(FSMessageLevel::Message, "adding %s, %d files\n", filename, resfile->EntryCount()); uint32_t lumpstart = (uint32_t)FileInfo.size(); - resfile->SetFirstLump(lumpstart); + resfile->SetFirstFile(lumpstart); Files.push_back(resfile); for (int i = 0; i < resfile->EntryCount(); i++) { FileInfo.resize(FileInfo.size() + 1); - FileSystem::LumpRecord* lump_p = &FileInfo.back(); - lump_p->SetFromLump(resfile, i, (int)Files.size() - 1, stringpool); + FileSystem::LumpRecord* file_p = &FileInfo.back(); + file_p->SetFromFile(resfile, i, (int)Files.size() - 1, stringpool); } for (int i = 0; i < resfile->EntryCount(); i++) @@ -396,49 +330,10 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInf path += ':'; path += resfile->getName(i); auto embedded = resfile->GetEntryReader(i, READER_CACHED); - AddFile(path.c_str(), &embedded, filter, Printf, hashfile); + AddFile(path.c_str(), &embedded, filter, Printf); } } - if (hashfile) - { - uint8_t cksum[16]; - char cksumout[33]; - memset(cksumout, 0, sizeof(cksumout)); - - if (filereader.isOpen()) - { - filereader.Seek(0, FileReader::SeekSet); - md5Hash(filereader, cksum); - - for (size_t j = 0; j < sizeof(cksum); ++j) - { - snprintf(cksumout + (j * 2), 3, "%02X", cksum[j]); - } - - fprintf(hashfile, "file: %s, hash: %s, size: %td\n", filename, cksumout, filereader.GetLength()); - } - - else - fprintf(hashfile, "file: %s, Directory structure\n", filename); - - for (int i = 0; i < resfile->EntryCount(); i++) - { - int flags = resfile->GetEntryFlags(i); - if (!(flags & RESFF_EMBEDDED)) - { - auto reader = resfile->GetEntryReader(i, READER_SHARED, 0); - md5Hash(filereader, cksum); - - for (size_t j = 0; j < sizeof(cksum); ++j) - { - snprintf(cksumout + (j * 2), 3, "%02X", cksum[j]); - } - - fprintf(hashfile, "file: %s, lump: %s, hash: %s, size: %zu\n", filename, resfile->getName(i), cksumout, (uint64_t)resfile->Length(i)); - } - } - } return; } } @@ -454,7 +349,7 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInf // //========================================================================== -int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept +int FileSystem::CheckIfContainerLoaded (const char *name) noexcept { unsigned int i; @@ -462,7 +357,7 @@ int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept { for (i = 0; i < (unsigned)Files.size(); ++i) { - if (stricmp (GetResourceFileFullName (i), name) == 0) + if (stricmp (GetContainerFullName (i), name) == 0) { return i; } @@ -472,7 +367,7 @@ int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept { for (i = 0; i < (unsigned)Files.size(); ++i) { - auto pth = ExtractBaseName(GetResourceFileName(i), true); + auto pth = ExtractBaseName(GetContainerName(i), true); if (stricmp (pth.c_str(), name) == 0) { return i; @@ -482,114 +377,6 @@ int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept return -1; } -//========================================================================== -// -// CheckNumForName -// -// Returns -1 if name not found. The version with a third parameter will -// look exclusively in the specified wad for the lump. -// -// [RH] Changed to use hash lookup ala BOOM instead of a linear search -// and namespace parameter -//========================================================================== - -int FileSystem::CheckNumForName (const char *name, int space) const -{ - union - { - char uname[8]; - uint64_t qname; - }; - uint32_t i; - - if (name == NULL) - { - return -1; - } - - // Let's not search for names that are longer than 8 characters and contain path separators - // They are almost certainly full path names passed to this function. - if (strlen(name) > 8 && strpbrk(name, "/.")) - { - return -1; - } - - UpperCopy (uname, name); - i = FirstLumpIndex[MakeHash(uname, 8) % NumEntries]; - - while (i != NULL_INDEX) - { - - if (FileInfo[i].shortName.qword == qname) - { - auto &lump = FileInfo[i]; - if (lump.Namespace == space) break; - // If the lump is from one of the special namespaces exclusive to Zips - // the check has to be done differently: - // If we find a lump with this name in the global namespace that does not come - // from a Zip return that. WADs don't know these namespaces and single lumps must - // work as well. - auto lflags = lump.resfile->GetEntryFlags(lump.resindex); - if (space > ns_specialzipdirectory && lump.Namespace == ns_global && - !((lflags ^lump.flags) & RESFF_FULLPATH)) break; - } - i = NextLumpIndex[i]; - } - - return i != NULL_INDEX ? i : -1; -} - -int FileSystem::CheckNumForName (const char *name, int space, int rfnum, bool exact) const -{ - union - { - char uname[8]; - uint64_t qname; - }; - uint32_t i; - - if (rfnum < 0) - { - return CheckNumForName (name, space); - } - - UpperCopy (uname, name); - i = FirstLumpIndex[MakeHash (uname, 8) % NumEntries]; - - // If exact is true if will only find lumps in the same WAD, otherwise - // also those in earlier WADs. - - while (i != NULL_INDEX && - (FileInfo[i].shortName.qword != qname || FileInfo[i].Namespace != space || - (exact? (FileInfo[i].rfnum != rfnum) : (FileInfo[i].rfnum > rfnum)) )) - { - i = NextLumpIndex[i]; - } - - return i != NULL_INDEX ? i : -1; -} - -//========================================================================== -// -// GetNumForName -// -// Calls CheckNumForName, but bombs out if not found. -// -//========================================================================== - -int FileSystem::GetNumForName (const char *name, int space) const -{ - int i; - - i = CheckNumForName (name, space); - - if (i == -1) - throw FileSystemException("GetNumForName: %s not found!", name); - - return i; -} - - //========================================================================== // // CheckNumForFullName @@ -600,7 +387,7 @@ int FileSystem::GetNumForName (const char *name, int space) const // //========================================================================== -int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int namespc, bool ignoreext) const +int FileSystem::FindFile (const char *name, bool ignoreext) const { uint32_t i; @@ -609,45 +396,40 @@ int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int names return -1; } if (*name == '/') name++; // ignore leading slashes in file names. - uint32_t *fli = ignoreext ? FirstLumpIndex_NoExt : FirstLumpIndex_FullName; - uint32_t *nli = ignoreext ? NextLumpIndex_NoExt : NextLumpIndex_FullName; + uint32_t *fli = ignoreext ? FirstFileIndex_NoExt : FirstFileIndex_FullName; + uint32_t *nli = ignoreext ? NextFileIndex_NoExt : NextFileIndex_FullName; auto len = strlen(name); for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i]) { - if (strnicmp(name, FileInfo[i].LongName, len)) continue; - if (FileInfo[i].LongName[len] == 0) break; // this is a full match - if (ignoreext && FileInfo[i].LongName[len] == '.') + if (strnicmp(name, FileInfo[i].Name, len)) continue; + if (FileInfo[i].Name[len] == 0) break; // this is a full match + if (ignoreext && FileInfo[i].Name[len] == '.') { // is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension? - if (strpbrk(FileInfo[i].LongName + len + 1, "./") == nullptr) break; + if (strpbrk(FileInfo[i].Name + len + 1, "./") == nullptr) break; } } if (i != NULL_INDEX) return i; - - if (trynormal && strlen(name) <= 8 && !strpbrk(name, "./")) - { - return CheckNumForName(name, namespc); - } return -1; } -int FileSystem::CheckNumForFullName (const char *name, int rfnum) const +int FileSystem::GetFileInContainer (const char *name, int rfnum) const { uint32_t i; if (rfnum < 0) { - return CheckNumForFullName (name); + return FindFile (name); } - i = FirstLumpIndex_FullName[MakeHash (name) % NumEntries]; + i = FirstFileIndex_FullName[MakeHash (name) % NumEntries]; while (i != NULL_INDEX && - (stricmp(name, FileInfo[i].LongName) || FileInfo[i].rfnum != rfnum)) + (stricmp(name, FileInfo[i].Name) || FileInfo[i].rfnum != rfnum)) { - i = NextLumpIndex_FullName[i]; + i = NextFileIndex_FullName[i]; } return i != NULL_INDEX ? i : -1; @@ -661,11 +443,11 @@ int FileSystem::CheckNumForFullName (const char *name, int rfnum) const // //========================================================================== -int FileSystem::GetNumForFullName (const char *name) const +int FileSystem::GetFile (const char *name) const { int i; - i = CheckNumForFullName (name); + i = FindFile (name); if (i == -1) throw FileSystemException("GetNumForFullName: %s not found!", name); @@ -690,16 +472,16 @@ int FileSystem::FindFileWithExtensions(const char* name, const char *const *exts return -1; } if (*name == '/') name++; // ignore leading slashes in file names. - uint32_t* fli = FirstLumpIndex_NoExt; - uint32_t* nli = NextLumpIndex_NoExt; + uint32_t* fli = FirstFileIndex_NoExt; + uint32_t* nli = NextFileIndex_NoExt; auto len = strlen(name); for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i]) { - if (strnicmp(name, FileInfo[i].LongName, len)) continue; - if (FileInfo[i].LongName[len] != '.') continue; // we are looking for extensions but this file doesn't have one. + if (strnicmp(name, FileInfo[i].Name, len)) continue; + if (FileInfo[i].Name[len] != '.') continue; // we are looking for extensions but this file doesn't have one. - auto cp = FileInfo[i].LongName + len + 1; + auto cp = FileInfo[i].Name + len + 1; // is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension? if (strpbrk(cp, "./") != nullptr) continue; // No, so it cannot be a valid entry. @@ -728,14 +510,14 @@ int FileSystem::FindResource (int resid, const char *type, int filenum) const no return -1; } - uint32_t* fli = FirstLumpIndex_ResId; - uint32_t* nli = NextLumpIndex_ResId; + uint32_t* fli = FirstFileIndex_ResId; + uint32_t* nli = NextFileIndex_ResId; for (i = fli[resid % NumEntries]; i != NULL_INDEX; i = nli[i]) { if (filenum > 0 && FileInfo[i].rfnum != filenum) continue; if (FileInfo[i].resourceId != resid) continue; - auto extp = strrchr(FileInfo[i].LongName, '.'); + auto extp = strrchr(FileInfo[i].Name, '.'); if (!extp) continue; if (!stricmp(extp + 1, type)) return i; } @@ -767,18 +549,18 @@ int FileSystem::GetResource (int resid, const char *type, int filenum) const // // FileLength // -// Returns the buffer size needed to load the given lump. +// Returns the buffer size needed to load the given filenum. // //========================================================================== -ptrdiff_t FileSystem::FileLength (int lump) const +ptrdiff_t FileSystem::FileLength (int filenum) const { - if ((size_t)lump >= NumEntries) + if ((size_t)filenum >= NumEntries) { return -1; } - const auto &lump_p = FileInfo[lump]; - return (int)lump_p.resfile->Length(lump_p.resindex); + const auto &file_p = FileInfo[filenum]; + return (int)file_p.resfile->Length(file_p.resindex); } //========================================================================== @@ -787,15 +569,15 @@ ptrdiff_t FileSystem::FileLength (int lump) const // //========================================================================== -int FileSystem::GetFileFlags (int lump) +int FileSystem::GetFileFlags (int filenum) { - if ((size_t)lump >= NumEntries) + if ((size_t)filenum >= NumEntries) { return 0; } - const auto& lump_p = FileInfo[lump]; - return lump_p.resfile->GetEntryFlags(lump_p.resindex) ^ lump_p.flags; + const auto& file_p = FileInfo[filenum]; + return file_p.resfile->GetEntryFlags(file_p.resindex) ^ file_p.flags; } //========================================================================== @@ -812,45 +594,39 @@ void FileSystem::InitHashChains (void) unsigned int i, j; NumEntries = (uint32_t)FileInfo.size(); - Hashes.resize(8 * NumEntries); + Hashes.resize(6 * NumEntries); // Mark all buckets as empty memset(Hashes.data(), -1, Hashes.size() * sizeof(Hashes[0])); - FirstLumpIndex = &Hashes[0]; - NextLumpIndex = &Hashes[NumEntries]; - FirstLumpIndex_FullName = &Hashes[NumEntries * 2]; - NextLumpIndex_FullName = &Hashes[NumEntries * 3]; - FirstLumpIndex_NoExt = &Hashes[NumEntries * 4]; - NextLumpIndex_NoExt = &Hashes[NumEntries * 5]; - FirstLumpIndex_ResId = &Hashes[NumEntries * 6]; - NextLumpIndex_ResId = &Hashes[NumEntries * 7]; + FirstFileIndex_FullName = &Hashes[NumEntries * 0]; + NextFileIndex_FullName = &Hashes[NumEntries * 1]; + FirstFileIndex_NoExt = &Hashes[NumEntries * 2]; + NextFileIndex_NoExt = &Hashes[NumEntries * 3]; + FirstFileIndex_ResId = &Hashes[NumEntries * 4]; + NextFileIndex_ResId = &Hashes[NumEntries * 5]; // Now set up the chains for (i = 0; i < (unsigned)NumEntries; i++) { - j = MakeHash (FileInfo[i].shortName.String, 8) % NumEntries; - NextLumpIndex[i] = FirstLumpIndex[j]; - FirstLumpIndex[j] = i; - // Do the same for the full paths - if (FileInfo[i].LongName[0] != 0) + if (FileInfo[i].Name[0] != 0) { - j = MakeHash(FileInfo[i].LongName) % NumEntries; - NextLumpIndex_FullName[i] = FirstLumpIndex_FullName[j]; - FirstLumpIndex_FullName[j] = i; + j = MakeHash(FileInfo[i].Name) % NumEntries; + NextFileIndex_FullName[i] = FirstFileIndex_FullName[j]; + FirstFileIndex_FullName[j] = i; - std::string nameNoExt = FileInfo[i].LongName; + std::string nameNoExt = FileInfo[i].Name; auto dot = nameNoExt.find_last_of('.'); auto slash = nameNoExt.find_last_of('/'); if ((dot > slash || slash == std::string::npos) && dot != std::string::npos) nameNoExt.resize(dot); j = MakeHash(nameNoExt.c_str()) % NumEntries; - NextLumpIndex_NoExt[i] = FirstLumpIndex_NoExt[j]; - FirstLumpIndex_NoExt[j] = i; + NextFileIndex_NoExt[i] = FirstFileIndex_NoExt[j]; + FirstFileIndex_NoExt[j] = i; j = FileInfo[i].resourceId % NumEntries; - NextLumpIndex_ResId[i] = FirstLumpIndex_ResId[j]; - FirstLumpIndex_ResId[j] = i; + NextFileIndex_ResId[i] = FirstFileIndex_ResId[j]; + FirstFileIndex_ResId[j] = i; } } @@ -858,24 +634,10 @@ void FileSystem::InitHashChains (void) Files.shrink_to_fit(); } -//========================================================================== -// -// should only be called before the hash chains are set up. -// If done later this needs rehashing. -// -//========================================================================== - -LumpShortName& FileSystem::GetShortName(int i) -{ - if ((unsigned)i >= NumEntries) throw FileSystemException("GetShortName: Invalid index"); - return FileInfo[i].shortName; -} - void FileSystem::RenameFile(int num, const char* newfn) { if ((unsigned)num >= NumEntries) throw FileSystemException("RenameFile: Invalid index"); - FileInfo[num].LongName = stringpool->Strdup(newfn); - // This does not alter the short name - call GetShortname to do that! + FileInfo[num].Name = stringpool->Strdup(newfn); } //========================================================================== @@ -891,7 +653,7 @@ void FileSystem::RenameFile(int num, const char* newfn) // //========================================================================== -void FileSystem::MoveLumpsInFolder(const char *path) +void FileSystem::MoveFilesInFolder(const char *path) { if (FileInfo.size() == 0) { @@ -905,15 +667,14 @@ void FileSystem::MoveLumpsInFolder(const char *path) for (i = 0; i < FileInfo.size(); i++) { auto& li = FileInfo[i]; - if (li.rfnum >= GetIwadNum()) break; - if (strnicmp(li.LongName, path, len) == 0) + if (li.rfnum >= GetBaseNum()) break; + if (strnicmp(li.Name, path, len) == 0) { auto lic = li; // make a copy before pushing. FileInfo.push_back(lic); - li.LongName = ""; //nuke the name of the old record. - li.shortName.qword = 0; + li.Name = ""; //nuke the name of the old record. auto &ln = FileInfo.back(); - ln.SetFromLump(li.resfile, li.resindex, rfnum, stringpool, ln.LongName + len); + ln.SetFromFile(li.resfile, li.resindex, rfnum, stringpool, ln.Name + len); } } } @@ -922,88 +683,7 @@ void FileSystem::MoveLumpsInFolder(const char *path) // // W_FindLump // -// Find a named lump. Specifically allows duplicates for merging of e.g. -// SNDINFO lumps. -// -//========================================================================== - -int FileSystem::FindLump (const char *name, int *lastlump, bool anyns) -{ - if ((size_t)*lastlump >= FileInfo.size()) return -1; - union - { - char name8[8]; - uint64_t qname; - }; - - UpperCopy (name8, name); - - assert(lastlump != NULL && *lastlump >= 0); - - const LumpRecord * last = FileInfo.data() + FileInfo.size(); - - LumpRecord * lump_p = FileInfo.data() + *lastlump; - - while (lump_p < last) - { - if ((anyns || lump_p->Namespace == ns_global) && lump_p->shortName.qword == qname) - { - int lump = int(lump_p - FileInfo.data()); - *lastlump = lump + 1; - return lump; - } - lump_p++; - } - - *lastlump = NumEntries; - return -1; -} - -//========================================================================== -// -// W_FindLumpMulti -// -// Find a named lump. Specifically allows duplicates for merging of e.g. -// SNDINFO lumps. Returns everything having one of the passed names. -// -//========================================================================== - -int FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, int *nameindex) -{ - assert(lastlump != NULL && *lastlump >= 0); - - const LumpRecord * last = FileInfo.data() + FileInfo.size(); - - LumpRecord * lump_p = FileInfo.data() + *lastlump; - - while (lump_p < last) - { - if (anyns || lump_p->Namespace == ns_global) - { - - for(const char **name = names; *name != NULL; name++) - { - if (!strnicmp(*name, lump_p->shortName.String, 8)) - { - int lump = int(lump_p - FileInfo.data()); - *lastlump = lump + 1; - if (nameindex != NULL) *nameindex = int(name - names); - return lump; - } - } - } - lump_p++; - } - - *lastlump = NumEntries; - return -1; -} - -//========================================================================== -// -// W_FindLump -// -// Find a named lump. Specifically allows duplicates for merging of e.g. +// Find a named filenum. Specifically allows duplicates for merging of e.g. // SNDINFO lumps. // //========================================================================== @@ -1014,38 +694,38 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext) const LumpRecord * last = FileInfo.data() + FileInfo.size(); - LumpRecord * lump_p = FileInfo.data() + *lastlump; + LumpRecord * file_p = FileInfo.data() + *lastlump; if (!noext) { - while (lump_p < last) + while (file_p < last) { - if (!stricmp(name, lump_p->LongName)) + if (!stricmp(name, file_p->Name)) { - int lump = int(lump_p - FileInfo.data()); - *lastlump = lump + 1; - return lump; + int filenum = int(file_p - FileInfo.data()); + *lastlump = filenum + 1; + return filenum; } - lump_p++; + file_p++; } } else { auto len = strlen(name); - while (lump_p <= &FileInfo.back()) + while (file_p <= &FileInfo.back()) { - auto res = strnicmp(name, lump_p->LongName, len); + auto res = strnicmp(name, file_p->Name, len); if (res == 0) { - auto p = lump_p->LongName + len; + auto p = file_p->Name + len; if (*p == 0 || (*p == '.' && strpbrk(p + 1, "./") == 0)) { - int lump = int(lump_p - FileInfo.data()); - *lastlump = lump + 1; - return lump; + int filenum = int(file_p - FileInfo.data()); + *lastlump = filenum + 1; + return filenum; } } - lump_p++; + file_p++; } } @@ -1056,107 +736,56 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext) //========================================================================== // -// W_CheckLumpName +// FileSystem :: GetFileName // -//========================================================================== - -bool FileSystem::CheckFileName (int lump, const char *name) -{ - if ((size_t)lump >= NumEntries) - return false; - - return !strnicmp (FileInfo[lump].shortName.String, name, 8); -} - -//========================================================================== -// -// GetLumpName +// Returns the filenum's internal name // //========================================================================== -const char* FileSystem::GetFileShortName(int lump) const +const char* FileSystem::GetFileName(int filenum) const { - if ((size_t)lump >= NumEntries) - return nullptr; - else - return FileInfo[lump].shortName.String; -} - -//========================================================================== -// -// FileSystem :: GetFileFullName -// -// Returns the lump's full name if it has one or its short name if not. -// -//========================================================================== - -const char *FileSystem::GetFileFullName (int lump, bool returnshort) const -{ - if ((size_t)lump >= NumEntries) + if ((size_t)filenum >= NumEntries) return NULL; - else if (FileInfo[lump].LongName[0] != 0) - return FileInfo[lump].LongName; - else if (returnshort) - return FileInfo[lump].shortName.String; - else return nullptr; + else return FileInfo[filenum].Name; } //========================================================================== // // FileSystem :: GetFileFullPath // -// Returns the name of the lump's wad prefixed to the lump's full name. +// Returns the name of the filenum's wad prefixed to the filenum's full name. // //========================================================================== -std::string FileSystem::GetFileFullPath(int lump) const +std::string FileSystem::GetFileFullPath(int filenum) const { std::string foo; - if ((size_t) lump < NumEntries) + if ((size_t) filenum < NumEntries) { - foo = GetResourceFileName(FileInfo[lump].rfnum); + foo = GetContainerName(FileInfo[filenum].rfnum); foo += ':'; - foo += +GetFileFullName(lump); + foo += +GetFileName(filenum); } return foo; } -//========================================================================== -// -// GetFileNamespace -// -//========================================================================== - -int FileSystem::GetFileNamespace (int lump) const -{ - if ((size_t)lump >= NumEntries) - return ns_global; - else - return FileInfo[lump].Namespace; -} - -void FileSystem::SetFileNamespace(int lump, int ns) -{ - if ((size_t)lump < NumEntries) FileInfo[lump].Namespace = ns; -} - //========================================================================== // // FileSystem :: GetResourceId // -// Returns the index number for this lump. This is *not* the lump's position -// in the lump directory, but rather a special value that RFF can associate +// Returns the index number for this filenum. This is *not* the filenum's position +// in the filenum directory, but rather a special value that RFF can associate // with files. Other archive types will return 0, since they don't have it. // //========================================================================== -int FileSystem::GetResourceId(int lump) const +int FileSystem::GetResourceId(int filenum) const { - if ((size_t)lump >= NumEntries) + if ((size_t)filenum >= NumEntries) return -1; else - return FileInfo[lump].resourceId; + return FileInfo[filenum].resourceId; } //========================================================================== @@ -1167,13 +796,13 @@ int FileSystem::GetResourceId(int lump) const // //========================================================================== -const char *FileSystem::GetResourceType(int lump) const +const char *FileSystem::GetResourceType(int filenum) const { - if ((size_t)lump >= NumEntries) + if ((size_t)filenum >= NumEntries) return nullptr; else { - auto p = strrchr(FileInfo[lump].LongName, '.'); + auto p = strrchr(FileInfo[filenum].Name, '.'); if (!p) return ""; // has no extension if (strchr(p, '/')) return ""; // the '.' is part of a directory. return p + 1; @@ -1186,11 +815,11 @@ const char *FileSystem::GetResourceType(int lump) const // //========================================================================== -int FileSystem::GetFileContainer (int lump) const +int FileSystem::GetFileContainer (int filenum) const { - if ((size_t)lump >= FileInfo.size()) + if ((size_t)filenum >= FileInfo.size()) return -1; - return FileInfo[lump].rfnum; + return FileInfo[filenum].rfnum; } //========================================================================== @@ -1225,12 +854,12 @@ unsigned FileSystem::GetFilesInFolder(const char *inpath, std::vector= W_LumpLength(). +// Loads the filenum into the given buffer, which must be >= W_LumpLength(). // //========================================================================== -void FileSystem::ReadFile (int lump, void *dest) +void FileSystem::ReadFile (int filenum, void *dest) { - auto lumpr = OpenFileReader (lump); + auto lumpr = OpenFileReader (filenum); auto size = lumpr.GetLength (); auto numread = lumpr.Read (dest, size); if (numread != size) { throw FileSystemException("W_ReadFile: only read %td of %td on '%s'\n", - numread, size, FileInfo[lump].LongName); + numread, size, FileInfo[filenum].Name); } } @@ -1283,17 +912,17 @@ void FileSystem::ReadFile (int lump, void *dest) // // ReadFile - variant 2 // -// Loads the lump into a newly created buffer and returns it. +// Loads the filenum into a newly created buffer and returns it. // //========================================================================== -FileData FileSystem::ReadFile (int lump) +FileData FileSystem::ReadFile (int filenum) { - if ((unsigned)lump >= (unsigned)FileInfo.size()) + if ((unsigned)filenum >= (unsigned)FileInfo.size()) { - throw FileSystemException("ReadFile: %u >= NumEntries", lump); + throw FileSystemException("ReadFile: %u >= NumEntries", filenum); } - return FileInfo[lump].resfile->Read(FileInfo[lump].resindex); + return FileInfo[filenum].resfile->Read(FileInfo[filenum].resindex); } //========================================================================== @@ -1305,30 +934,30 @@ FileData FileSystem::ReadFile (int lump) //========================================================================== -FileReader FileSystem::OpenFileReader(int lump, int readertype, int readerflags) +FileReader FileSystem::OpenFileReader(int filenum, int readertype, int readerflags) { - if ((unsigned)lump >= (unsigned)FileInfo.size()) + if ((unsigned)filenum >= (unsigned)FileInfo.size()) { - throw FileSystemException("OpenFileReader: %u >= NumEntries", lump); + throw FileSystemException("OpenFileReader: %u >= NumEntries", filenum); } - auto file = FileInfo[lump].resfile; - return file->GetEntryReader(FileInfo[lump].resindex, readertype, readerflags); + auto file = FileInfo[filenum].resfile; + return file->GetEntryReader(FileInfo[filenum].resindex, readertype, readerflags); } FileReader FileSystem::OpenFileReader(const char* name) { FileReader fr; - auto lump = CheckNumForFullName(name); - if (lump >= 0) fr = OpenFileReader(lump); + auto filenum = FindFile(name); + if (filenum >= 0) fr = OpenFileReader(filenum); return fr; } FileReader FileSystem::ReopenFileReader(const char* name, bool alwayscache) { FileReader fr; - auto lump = CheckNumForFullName(name); - if (lump >= 0) fr = ReopenFileReader(lump, alwayscache); + auto filenum = FindFile(name); + if (filenum >= 0) fr = ReopenFileReader(filenum, alwayscache); return fr; } @@ -1353,13 +982,13 @@ FileReader *FileSystem::GetFileReader(int rfnum) //========================================================================== // -// GetResourceFileName +// GetContainerName // // Returns the name of the given wad. // //========================================================================== -const char *FileSystem::GetResourceFileName (int rfnum) const noexcept +const char *FileSystem::GetContainerName (int rfnum) const noexcept { const char *name, *slash; @@ -1393,6 +1022,21 @@ int FileSystem::GetFirstEntry (int rfnum) const noexcept // //========================================================================== +int FileSystem::GetContainerFlags(int rfnum) const noexcept +{ + if ((uint32_t)rfnum >= Files.size()) + { + return 0; + } + + return Files[rfnum]->GetFlags(); +} + +//========================================================================== +// +// +//========================================================================== + int FileSystem::GetLastEntry (int rfnum) const noexcept { if ((uint32_t)rfnum >= Files.size()) @@ -1427,7 +1071,7 @@ int FileSystem::GetEntryCount (int rfnum) const noexcept // //========================================================================== -const char *FileSystem::GetResourceFileFullName (int rfnum) const noexcept +const char *FileSystem::GetContainerFullName (int rfnum) const noexcept { if ((unsigned int)rfnum >= Files.size()) { @@ -1450,21 +1094,21 @@ bool FileSystem::CreatePathlessCopy(const char *name, int id, int /*flags*/) // The old code said 'filename' and ignored the path, this looked like a bug. FixPathSeparator(&name2.front()); - auto lump = FindFile(name2.c_str()); - if (lump < 0) return false; // Does not exist. + auto filenum = FindFile(name2.c_str()); + if (filenum < 0) return false; // Does not exist. - auto oldlump = FileInfo[lump]; - auto slash = strrchr(oldlump.LongName, '/'); + auto oldlump = FileInfo[filenum]; + auto slash = strrchr(oldlump.Name, '/'); if (slash == nullptr) { - FileInfo[lump].flags = RESFF_FULLPATH; + FileInfo[filenum].flags = RESFF_FULLPATH; return true; // already is pathless. } // just create a new reference to the original data with a different name. - oldlump.LongName = slash + 1; + oldlump.Name = slash + 1; oldlump.resourceId = id; oldlump.flags = RESFF_FULLPATH; FileInfo.push_back(oldlump); diff --git a/source/common/filesystem/source/resourcefile.cpp b/source/common/filesystem/source/resourcefile.cpp index 00a5234ca11..6736cfa7139 100644 --- a/source/common/filesystem/source/resourcefile.cpp +++ b/source/common/filesystem/source/resourcefile.cpp @@ -113,7 +113,7 @@ bool FResourceFile::IsFileInFolder(const char* const resPath) return 0 == stricmp(filePath.c_str(), resPath); } -void FResourceFile::CheckEmbedded(uint32_t entry, LumpFilterInfo* lfi) +void FResourceFile::CheckEmbedded(uint32_t entry, FileSystemFilterInfo* lfi) { // Checks for embedded archives auto FullName = Entries[entry].FileName; @@ -138,29 +138,30 @@ void FResourceFile::CheckEmbedded(uint32_t entry, LumpFilterInfo* lfi) // //========================================================================== -typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile* CheckHog(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile* CheckMvl(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile* CheckWHRes(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *CheckLump(const char *filename,FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *CheckDir(const char *filename, bool nosub, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckWad(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckGRP(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckRFF(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckPak(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckZip(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *Check7Z(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile* CheckSSI(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile* CheckHog(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile* CheckHog2(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile* CheckMvl(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile* CheckWHRes(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckLump(const char *filename,FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckDir(const char *filename, bool nosub, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckSSI, CheckHog, CheckMvl, CheckWHRes, CheckLump }; +static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckHog, CheckMvl, CheckHog2, CheckSSI, CheckWHRes, CheckLump }; static int nulPrintf(FSMessageLevel msg, const char* fmt, ...) { return 0; } -FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { if (!file.isOpen()) return nullptr; if (Printf == nullptr) Printf = nulPrintf; @@ -173,20 +174,20 @@ FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReade return NULL; } -FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool containeronly, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { return DoOpenResourceFile(filename, file, containeronly, filter, Printf, sp); } -FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool containeronly, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { FileReader file; if (!file.OpenFile(filename)) return nullptr; return DoOpenResourceFile(filename, file, containeronly, filter, Printf, sp); } -FResourceFile *FResourceFile::OpenDirectory(const char *filename, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *FResourceFile::OpenDirectory(const char *filename, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { if (Printf == nullptr) Printf = nulPrintf; return CheckDir(filename, false, filter, Printf, sp); @@ -198,14 +199,15 @@ FResourceFile *FResourceFile::OpenDirectory(const char *filename, LumpFilterInfo // //========================================================================== -FResourceFile::FResourceFile(const char *filename, StringPool* sp) +FResourceFile::FResourceFile(const char *filename, StringPool* sp, int flags_) + :flags(flags_) { stringpool = sp ? sp : new StringPool(false); FileName = stringpool->Strdup(filename); } -FResourceFile::FResourceFile(const char *filename, FileReader &r, StringPool* sp) - : FResourceFile(filename,sp) +FResourceFile::FResourceFile(const char *filename, FileReader &r, StringPool* sp, int flags) + : FResourceFile(filename,sp, flags) { Reader = std::move(r); } @@ -250,7 +252,7 @@ FCompressedBuffer FResourceFile::GetRawData(uint32_t entry) // //========================================================================== -const char* FResourceFile::NormalizeFileName(const char* fn, int fallbackcp) +const char* FResourceFile::NormalizeFileName(const char* fn, int fallbackcp, bool allowbackslash) { if (!fn || !*fn) return ""; auto norm = tolower_normalize(fn); @@ -274,7 +276,8 @@ const char* FResourceFile::NormalizeFileName(const char* fn, int fallbackcp) norm = tolower_normalize(&ffn.front()); } } - FixPathSeparator(norm); + // The WAD format can have legal backslashes in its names so this must be optional. + if (!allowbackslash) FixPathSeparator(norm); auto pooled = stringpool->Strdup(norm); free(norm); return pooled; @@ -354,7 +357,7 @@ void FResourceFile::GenerateHash() // //========================================================================== -void FResourceFile::PostProcessArchive(LumpFilterInfo *filter) +void FResourceFile::PostProcessArchive(FileSystemFilterInfo *filter) { // only do this for archive types which contain full file names. All others are assumed to be pre-sorted. if (NumLumps == 0 || !(Entries[0].Flags & RESFF_FULLPATH)) return; @@ -416,7 +419,7 @@ void FResourceFile::PostProcessArchive(LumpFilterInfo *filter) // //========================================================================== -void FResourceFile::FindCommonFolder(LumpFilterInfo* filter) +void FResourceFile::FindCommonFolder(FileSystemFilterInfo* filter) { std::string name0, name1; bool foundspeciallump = false; diff --git a/source/common/fonts/v_font.cpp b/source/common/fonts/v_font.cpp index d838fb18130..9cd5cb2a80c 100644 --- a/source/common/fonts/v_font.cpp +++ b/source/common/fonts/v_font.cpp @@ -120,7 +120,7 @@ FFont *V_GetFont(const char *name, const char *fontlumpname) } - lump = fileSystem.CheckNumForFullName(fontlumpname? fontlumpname : name, true); + lump = fileSystem.CheckNumForAnyName(fontlumpname? fontlumpname : name); if (lump != -1 && fileSystem.GetFileContainer(lump) >= folderfile) { @@ -290,7 +290,7 @@ void V_InitCustomFonts() { *p = TexMan.GetGameTexture(texid); } - else if (fileSystem.GetFileContainer(sc.LumpNum) >= fileSystem.GetIwadNum()) + else if (fileSystem.GetFileContainer(sc.LumpNum) >= fileSystem.GetBaseNum()) { // Print a message only if this isn't in zdoom.pk3 sc.ScriptMessage("%s: Unable to find texture in font definition for %s", sc.String, namebuffer.GetChars()); @@ -871,7 +871,7 @@ void V_InitFonts() FFont *CreateHexLumpFont(const char *fontname, int lump); FFont *CreateHexLumpFont2(const char *fontname, int lump); - auto lump = fileSystem.CheckNumForFullName("newconsolefont.hex", 0); // This is always loaded from gzdoom.pk3 to prevent overriding it with incomplete replacements. + auto lump = fileSystem.GetFileInContainer("newconsolefont.hex", 0); // This is always loaded from gzdoom.pk3 to prevent overriding it with incomplete replacements. if (lump == -1) I_FatalError("newconsolefont.hex not found"); // This font is needed - do not start up without it. NewConsoleFont = CreateHexLumpFont("NewConsoleFont", lump); NewSmallFont = CreateHexLumpFont2("NewSmallFont", lump); diff --git a/source/common/menu/menudef.cpp b/source/common/menu/menudef.cpp index ad02001e0ce..42d006d9d0b 100644 --- a/source/common/menu/menudef.cpp +++ b/source/common/menu/menudef.cpp @@ -1524,7 +1524,7 @@ void M_ParseMenuDefs() DefaultOptionMenuSettings->Reset(); OptionSettings.mLinespacing = 17; - int IWADMenu = fileSystem.CheckNumForName("MENUDEF", FileSys::ns_global, fileSystem.GetIwadNum()); + int IWADMenu = fileSystem.CheckNumForName("MENUDEF", ns_global, fileSystem.GetBaseNum()); while ((lump = fileSystem.FindLump ("MENUDEF", &lastlump)) != -1) { diff --git a/source/common/models/model.cpp b/source/common/models/model.cpp index 0f160341588..ee44e4bca21 100644 --- a/source/common/models/model.cpp +++ b/source/common/models/model.cpp @@ -88,7 +88,7 @@ void FModel::DestroyVertexBuffer() static int FindGFXFile(FString & fn) { - int lump = fileSystem.CheckNumForFullName(fn.GetChars()); // if we find something that matches the name plus the extension, return it and do not enter the substitution logic below. + int lump = fileSystem.FindFile(fn.GetChars()); // if we find something that matches the name plus the extension, return it and do not enter the substitution logic below. if (lump != -1) return lump; int best = -1; @@ -100,7 +100,7 @@ static int FindGFXFile(FString & fn) for (const char ** extp=extensions; *extp; extp++) { - lump = fileSystem.CheckNumForFullName((fn + *extp).GetChars()); + lump = fileSystem.FindFile((fn + *extp).GetChars()); if (lump >= best) best = lump; } return best; @@ -120,7 +120,7 @@ FTextureID LoadSkin(const char * path, const char * fn) buffer.Format("%s%s", path, fn); int texlump = FindGFXFile(buffer); - const char * const texname = texlump < 0 ? fn : fileSystem.GetFileFullName(texlump); + const char * const texname = texlump < 0 ? fn : fileSystem.GetFileName(texlump); return TexMan.CheckForTexture(texname, ETextureType::Any, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ForceLookup); } @@ -148,7 +148,7 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent) if (path) fullname.Format("%s%s", path, modelfile); else fullname = modelfile; - int lump = fileSystem.CheckNumForFullName(fullname.GetChars()); + int lump = fileSystem.FindFile(fullname.GetChars()); if (lump<0) { @@ -175,7 +175,7 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent) { FString anivfile = fullname.GetChars(); anivfile.Substitute("_d.3d","_a.3d"); - if ( fileSystem.CheckNumForFullName(anivfile.GetChars()) > 0 ) + if ( fileSystem.FindFile(anivfile.GetChars()) > 0 ) { model = new FUE1Model; } @@ -184,7 +184,7 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent) { FString datafile = fullname.GetChars(); datafile.Substitute("_a.3d","_d.3d"); - if ( fileSystem.CheckNumForFullName(datafile.GetChars()) > 0 ) + if ( fileSystem.FindFile(datafile.GetChars()) > 0 ) { model = new FUE1Model; } diff --git a/source/common/models/models_ue1.cpp b/source/common/models/models_ue1.cpp index 81065926179..f67d76589d6 100644 --- a/source/common/models/models_ue1.cpp +++ b/source/common/models/models_ue1.cpp @@ -49,18 +49,18 @@ bool FUE1Model::Load( const char *filename, int lumpnum, const char *buffer, int { int lumpnum2; hasSurfaces = true; - FString realfilename = fileSystem.GetFileFullName(lumpnum); + FString realfilename = fileSystem.GetFileName(lumpnum); if ( (size_t)realfilename.IndexOf("_d.3d") == realfilename.Len()-5 ) { realfilename.Substitute("_d.3d","_a.3d"); - lumpnum2 = fileSystem.CheckNumForFullName(realfilename.GetChars()); + lumpnum2 = fileSystem.FindFile(realfilename.GetChars()); mDataLump = lumpnum; mAnivLump = lumpnum2; } else { realfilename.Substitute("_a.3d","_d.3d"); - lumpnum2 = fileSystem.CheckNumForFullName(realfilename.GetChars()); + lumpnum2 = fileSystem.FindFile(realfilename.GetChars()); mAnivLump = lumpnum; mDataLump = lumpnum2; } diff --git a/source/common/models/voxels.cpp b/source/common/models/voxels.cpp index 4d13323530d..af48bd39d7a 100644 --- a/source/common/models/voxels.cpp +++ b/source/common/models/voxels.cpp @@ -309,7 +309,7 @@ FVoxelDef *R_LoadVoxelDef(int lumpnum, int spin) FVoxel *vox = R_LoadKVX(lumpnum); if (vox == NULL) { - Printf("%s is not a valid voxel file\n", fileSystem.GetFileFullName(lumpnum)); + Printf("%s is not a valid voxel file\n", fileSystem.GetFileName(lumpnum)); return NULL; } else diff --git a/source/common/platform/posix/cocoa/st_console.h b/source/common/platform/posix/cocoa/st_console.h index b2af7bade35..91f77d12438 100644 --- a/source/common/platform/posix/cocoa/st_console.h +++ b/source/common/platform/posix/cocoa/st_console.h @@ -66,6 +66,7 @@ class FConsoleWindow void NetInit(const char* message, int playerCount); void NetProgress(int count); void NetDone(); + void NetClose(); private: NSWindow* m_window; diff --git a/source/common/platform/posix/cocoa/st_console.mm b/source/common/platform/posix/cocoa/st_console.mm index 1c45776e6cf..95d0ee11eb5 100644 --- a/source/common/platform/posix/cocoa/st_console.mm +++ b/source/common/platform/posix/cocoa/st_console.mm @@ -531,3 +531,8 @@ static void UpdateTimed(const Function& function) m_netAbortButton = nil; } } + +void FConsoleWindow::NetClose() +{ + // TODO: Implement this +} diff --git a/source/common/platform/posix/cocoa/st_start.mm b/source/common/platform/posix/cocoa/st_start.mm index ee6ea262784..2cd73104d30 100644 --- a/source/common/platform/posix/cocoa/st_start.mm +++ b/source/common/platform/posix/cocoa/st_start.mm @@ -110,6 +110,11 @@ FConsoleWindow::GetInstance().NetDone(); } +void FBasicStartupScreen::NetClose() +{ + FConsoleWindow::GetInstance().NetClose(); +} + bool FBasicStartupScreen::NetLoop(bool (*timerCallback)(void*), void* const userData) { while (true) diff --git a/source/common/platform/posix/i_system.h b/source/common/platform/posix/i_system.h index 4d800d53b3b..5573e26d327 100644 --- a/source/common/platform/posix/i_system.h +++ b/source/common/platform/posix/i_system.h @@ -54,17 +54,6 @@ bool I_WriteIniFailed (const char* filename); class FGameTexture; bool I_SetCursor(FGameTexture *); -static inline char *strlwr(char *str) -{ - char *ptr = str; - while(*ptr) - { - *ptr = tolower(*ptr); - ++ptr; - } - return str; -} - inline int I_GetNumaNodeCount() { return 1; } inline int I_GetNumaNodeThreadCount(int numaNode) { return std::max(std::thread::hardware_concurrency(), 1); } inline void I_SetThreadNumaNode(std::thread &thread, int numaNode) { } diff --git a/source/common/platform/posix/sdl/i_system.cpp b/source/common/platform/posix/sdl/i_system.cpp index 31976ba3cf6..2c28368b005 100644 --- a/source/common/platform/posix/sdl/i_system.cpp +++ b/source/common/platform/posix/sdl/i_system.cpp @@ -308,7 +308,7 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& #ifdef __APPLE__ return I_PickIWad_Cocoa (wads, numwads, showwin, defaultiwad); #else - return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags, extraArgs); + return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags, &extraArgs); #endif } diff --git a/source/common/platform/posix/sdl/st_start.cpp b/source/common/platform/posix/sdl/st_start.cpp index 019a66122b6..5bd88684bba 100644 --- a/source/common/platform/posix/sdl/st_start.cpp +++ b/source/common/platform/posix/sdl/st_start.cpp @@ -57,6 +57,7 @@ class FTTYStartupScreen : public FStartupScreen void NetInit(const char *message, int num_players); void NetProgress(int count); void NetDone(); + void NetClose(); bool NetLoop(bool (*timer_callback)(void *), void *userdata); protected: bool DidNetInit; @@ -237,6 +238,11 @@ void FTTYStartupScreen::NetProgress(int count) } } +void FTTYStartupScreen::NetClose() +{ + // TODO: Implement this +} + //=========================================================================== // // FTTYStartupScreen :: NetLoop diff --git a/source/common/platform/win32/i_main.cpp b/source/common/platform/win32/i_main.cpp index acadc2dc823..c68b5a7aa1e 100644 --- a/source/common/platform/win32/i_main.cpp +++ b/source/common/platform/win32/i_main.cpp @@ -134,6 +134,39 @@ void I_SetIWADInfo() { } +//========================================================================== +// +// isConsoleApp() +// +// runtime detection to detect if this is a console subsystem app. +// +// the reason for doing this is because it is possible to edit a binary directly and change its subsystem +// type via hexedit so in order to gain flexibility it makes no sense to just compile out the unused code. +// +// we may plan to publish tools to allow users to do this manually on their own. +// +//========================================================================== + +bool isConsoleApp() +{ + static bool alreadychecked = false; + static bool returnvalue; + + if (!alreadychecked) + { + DWORD pids[2]; + DWORD num_pids = GetConsoleProcessList(pids, 2); + bool win32con_is_exclusive = (num_pids <= 1); + + returnvalue = ((GetConsoleWindow() != NULL && !win32con_is_exclusive) || (GetStdHandle(STD_OUTPUT_HANDLE) != NULL)); + alreadychecked = true; + } + + //printf("isConsoleApp is %i\n", returnvalue); + + return returnvalue; +} + //========================================================================== // // DoMain @@ -158,7 +191,22 @@ int DoMain (HINSTANCE hInstance) Args->AppendArg(FString(wargv[i])); } - if (Args->CheckParm("-stdout") || Args->CheckParm("-norun")) + if (isConsoleApp()) + { + StdOut = GetStdHandle(STD_OUTPUT_HANDLE); + + SetConsoleCP(CP_UTF8); + SetConsoleOutputCP(CP_UTF8); + + DWORD mode; + + if (GetConsoleMode(StdOut, &mode)) + { + if (SetConsoleMode(StdOut, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) + FancyStdOut = IsWindows10OrGreater(); // Windows 8.1 and lower do not understand ANSI formatting. + } + } + else if (Args->CheckParm("-stdout") || Args->CheckParm("-norun")) { // As a GUI application, we don't normally get a console when we start. // If we were run from the shell and are on XP+, we can attach to its @@ -475,6 +523,11 @@ CUSTOM_CVAR(Bool, disablecrashlog, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // //========================================================================== +int wmain() +{ + return wWinMain(GetModuleHandle(0), 0, GetCommandLineW(), SW_SHOW); +} + int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int nCmdShow) { g_hInst = hInstance; diff --git a/source/common/platform/win32/i_mainwindow.cpp b/source/common/platform/win32/i_mainwindow.cpp index 95dda5031f3..5bdd3569c26 100644 --- a/source/common/platform/win32/i_mainwindow.cpp +++ b/source/common/platform/win32/i_mainwindow.cpp @@ -128,6 +128,11 @@ void MainWindow::HideNetStartPane() NetStartWindow::HideNetStartPane(); } +void MainWindow::CloseNetStartPane() +{ + NetStartWindow::NetClose(); +} + void MainWindow::SetNetStartProgress(int pos) { NetStartWindow::SetNetStartProgress(pos); diff --git a/source/common/platform/win32/i_mainwindow.h b/source/common/platform/win32/i_mainwindow.h index 3c0c7e55df4..83567135cf5 100644 --- a/source/common/platform/win32/i_mainwindow.h +++ b/source/common/platform/win32/i_mainwindow.h @@ -29,6 +29,7 @@ class MainWindow void SetNetStartProgress(int pos); bool RunMessageLoop(bool (*timer_callback)(void*), void* userdata); void HideNetStartPane(); + void CloseNetStartPane(); void SetWindowTitle(const char* caption); diff --git a/source/common/platform/win32/i_system.cpp b/source/common/platform/win32/i_system.cpp index 2c7eed495f8..caed820b0c9 100644 --- a/source/common/platform/win32/i_system.cpp +++ b/source/common/platform/win32/i_system.cpp @@ -102,6 +102,7 @@ // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void DestroyCustomCursor(); +bool isConsoleApp(); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- @@ -306,6 +307,7 @@ static void PrintToStdOut(const char *cpt, HANDLE StdOut) else break; } } + DWORD bytes_written; WriteFile(StdOut, printData.GetChars(), (DWORD)printData.Len(), &bytes_written, NULL); if (terminal) @@ -370,7 +372,7 @@ int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& } if (showwin || (vkey != 0 && GetAsyncKeyState(vkey))) { - return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags, extraArgs); + return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags, &extraArgs); } return defaultiwad; } diff --git a/source/common/platform/win32/st_start.cpp b/source/common/platform/win32/st_start.cpp index 8bc48d26e5a..fceeb3cede3 100644 --- a/source/common/platform/win32/st_start.cpp +++ b/source/common/platform/win32/st_start.cpp @@ -201,3 +201,8 @@ bool FBasicStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata { return mainwindow.RunMessageLoop(timer_callback, userdata); } + +void FBasicStartupScreen::NetClose() +{ + mainwindow.CloseNetStartPane(); +} diff --git a/source/common/rendering/gl/gl_shader.cpp b/source/common/rendering/gl/gl_shader.cpp index bafbf89b8eb..d7fbec23ee9 100644 --- a/source/common/rendering/gl/gl_shader.cpp +++ b/source/common/rendering/gl/gl_shader.cpp @@ -373,10 +373,10 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * i_data += "#define NPOT_EMULATION\nuniform vec2 uNpotEmulation;\n"; #endif - int vp_lump = fileSystem.CheckNumForFullName(vert_prog_lump, 0); + int vp_lump = fileSystem.GetFileInContainer(vert_prog_lump, 0); if (vp_lump == -1) I_Error("Unable to load '%s'", vert_prog_lump); - int fp_lump = fileSystem.CheckNumForFullName(frag_prog_lump, 0); + int fp_lump = fileSystem.GetFileInContainer(frag_prog_lump, 0); if (fp_lump == -1) I_Error("Unable to load '%s'", frag_prog_lump); @@ -418,8 +418,8 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * if (*proc_prog_lump != '#') { - int pp_lump = fileSystem.CheckNumForFullName(proc_prog_lump, 0); // if it's a core shader, ignore overrides by user mods. - if (pp_lump == -1) pp_lump = fileSystem.CheckNumForFullName(proc_prog_lump); + int pp_lump = fileSystem.GetFileInContainer(proc_prog_lump, 0); // if it's a core shader, ignore overrides by user mods. + if (pp_lump == -1) pp_lump = fileSystem.FindFile(proc_prog_lump); if (pp_lump == -1) I_Error("Unable to load '%s'", proc_prog_lump); FString pp_data = GetStringFromLump(pp_lump); @@ -429,13 +429,13 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * if (pp_data.IndexOf("GetTexCoord") >= 0) { - int pl_lump = fileSystem.CheckNumForFullName("shaders/glsl/func_defaultmat2.fp", 0); + int pl_lump = fileSystem.GetFileInContainer("shaders/glsl/func_defaultmat2.fp", 0); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultmat2.fp"); fp_comb << "\n" << GetStringFromLump(pl_lump); } else { - int pl_lump = fileSystem.CheckNumForFullName("shaders/glsl/func_defaultmat.fp", 0); + int pl_lump = fileSystem.GetFileInContainer("shaders/glsl/func_defaultmat.fp", 0); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultmat.fp"); fp_comb << "\n" << GetStringFromLump(pl_lump); @@ -461,7 +461,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * if (pp_data.IndexOf("ProcessLight") < 0) { - int pl_lump = fileSystem.CheckNumForFullName("shaders/glsl/func_defaultlight.fp", 0); + int pl_lump = fileSystem.GetFileInContainer("shaders/glsl/func_defaultlight.fp", 0); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultlight.fp"); fp_comb << "\n" << GetStringFromLump(pl_lump); } @@ -483,7 +483,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * if (light_fragprog) { - int pp_lump = fileSystem.CheckNumForFullName(light_fragprog, 0); + int pp_lump = fileSystem.GetFileInContainer(light_fragprog, 0); if (pp_lump == -1) I_Error("Unable to load '%s'", light_fragprog); fp_comb << GetStringFromLump(pp_lump) << "\n"; } diff --git a/source/common/rendering/gl/gl_shaderprogram.cpp b/source/common/rendering/gl/gl_shaderprogram.cpp index 1c4fd48a4df..b74a1c05916 100644 --- a/source/common/rendering/gl/gl_shaderprogram.cpp +++ b/source/common/rendering/gl/gl_shaderprogram.cpp @@ -87,7 +87,7 @@ void FShaderProgram::CreateShader(ShaderType type) void FShaderProgram::Compile(ShaderType type, const char *lumpName, const char *defines, int maxGlslVersion) { - int lump = fileSystem.CheckNumForFullName(lumpName); + int lump = fileSystem.FindFile(lumpName); if (lump == -1) I_FatalError("Unable to load '%s'", lumpName); FString code = GetStringFromLump(lump); diff --git a/source/common/rendering/gles/gles_shader.cpp b/source/common/rendering/gles/gles_shader.cpp index dba9a233a69..40c12dc64a1 100644 --- a/source/common/rendering/gles/gles_shader.cpp +++ b/source/common/rendering/gles/gles_shader.cpp @@ -381,10 +381,10 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * i_data += "#define NPOT_EMULATION\nuniform vec2 uNpotEmulation;\n"; #endif - int vp_lump = fileSystem.CheckNumForFullName(vert_prog_lump.GetChars(), 0); + int vp_lump = fileSystem.GetFileInContainer(vert_prog_lump.GetChars(), 0); if (vp_lump == -1) I_Error("Unable to load '%s'", vert_prog_lump.GetChars()); - int fp_lump = fileSystem.CheckNumForFullName(frag_prog_lump.GetChars(), 0); + int fp_lump = fileSystem.GetFileInContainer(frag_prog_lump.GetChars(), 0); if (fp_lump == -1) I_Error("Unable to load '%s'", frag_prog_lump.GetChars()); @@ -418,7 +418,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * if (proc_prog_lump[0] != '#') { - int pp_lump = fileSystem.CheckNumForFullName(proc_prog_lump.GetChars()); + int pp_lump = fileSystem.FindFile(proc_prog_lump.GetChars()); if (pp_lump == -1) I_Error("Unable to load '%s'", proc_prog_lump.GetChars()); FString pp_data = GetStringFromLump(pp_lump); @@ -428,13 +428,13 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * if (pp_data.IndexOf("GetTexCoord") >= 0) { - int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultmat2.fp", 0); + int pl_lump = fileSystem.GetFileInContainer("shaders_gles/glsl/func_defaultmat2.fp", 0); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultmat2.fp"); fp_comb << "\n" << GetStringFromLump(pl_lump); } else { - int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultmat.fp", 0); + int pl_lump = fileSystem.GetFileInContainer("shaders_gles/glsl/func_defaultmat.fp", 0); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultmat.fp"); fp_comb << "\n" << GetStringFromLump(pl_lump); @@ -460,7 +460,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * if (pp_data.IndexOf("ProcessLight") < 0) { - int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultlight.fp", 0); + int pl_lump = fileSystem.GetFileInContainer("shaders_gles/glsl/func_defaultlight.fp", 0); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultlight.fp"); fp_comb << "\n" << GetStringFromLump(pl_lump); } @@ -482,7 +482,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * if (light_fragprog.Len()) { - int pp_lump = fileSystem.CheckNumForFullName(light_fragprog.GetChars(), 0); + int pp_lump = fileSystem.GetFileInContainer(light_fragprog.GetChars(), 0); if (pp_lump == -1) I_Error("Unable to load '%s'", light_fragprog.GetChars()); fp_comb << GetStringFromLump(pp_lump) << "\n"; } diff --git a/source/common/rendering/gles/gles_shaderprogram.cpp b/source/common/rendering/gles/gles_shaderprogram.cpp index efc94c71dff..1e107bd1bde 100644 --- a/source/common/rendering/gles/gles_shaderprogram.cpp +++ b/source/common/rendering/gles/gles_shaderprogram.cpp @@ -87,7 +87,7 @@ void FShaderProgram::CreateShader(ShaderType type) void FShaderProgram::Compile(ShaderType type, const char *lumpName, const char *defines, int maxGlslVersion) { - int lump = fileSystem.CheckNumForFullName(lumpName); + int lump = fileSystem.FindFile(lumpName); if (lump == -1) I_FatalError("Unable to load '%s'", lumpName); FString code = GetStringFromLump(lump); Compile(type, lumpName, code, defines, maxGlslVersion); diff --git a/source/common/rendering/r_videoscale.cpp b/source/common/rendering/r_videoscale.cpp index 705fe905f40..bfed3ec73bb 100644 --- a/source/common/rendering/r_videoscale.cpp +++ b/source/common/rendering/r_videoscale.cpp @@ -248,7 +248,7 @@ CCMD (vid_scaletoheight) } } -inline bool atob(char* I) +inline bool atob(const char* I) { if (stricmp (I, "true") == 0 || stricmp (I, "1") == 0) return true; diff --git a/source/common/rendering/vulkan/shaders/vk_ppshader.cpp b/source/common/rendering/vulkan/shaders/vk_ppshader.cpp index dcf72a06d2f..38f2201cbef 100644 --- a/source/common/rendering/vulkan/shaders/vk_ppshader.cpp +++ b/source/common/rendering/vulkan/shaders/vk_ppshader.cpp @@ -67,7 +67,7 @@ void VkPPShader::Reset() FString VkPPShader::LoadShaderCode(const FString &lumpName, const FString &defines, int version) { - int lump = fileSystem.CheckNumForFullName(lumpName.GetChars()); + int lump = fileSystem.FindFile(lumpName.GetChars()); if (lump == -1) I_FatalError("Unable to load '%s'", lumpName.GetChars()); FString code = GetStringFromLump(lump); diff --git a/source/common/rendering/vulkan/shaders/vk_shader.cpp b/source/common/rendering/vulkan/shaders/vk_shader.cpp index 00734ac7f30..0b908bfe58b 100644 --- a/source/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/source/common/rendering/vulkan/shaders/vk_shader.cpp @@ -465,15 +465,15 @@ FString VkShaderManager::GetTargetGlslVersion() FString VkShaderManager::LoadPublicShaderLump(const char *lumpname) { - int lump = fileSystem.CheckNumForFullName(lumpname, 0); - if (lump == -1) lump = fileSystem.CheckNumForFullName(lumpname); + int lump = fileSystem.GetFileInContainer(lumpname, 0); + if (lump == -1) lump = fileSystem.FindFile(lumpname); if (lump == -1) I_Error("Unable to load '%s'", lumpname); return GetStringFromLump(lump); } FString VkShaderManager::LoadPrivateShaderLump(const char *lumpname) { - int lump = fileSystem.CheckNumForFullName(lumpname, 0); + int lump = fileSystem.GetFileInContainer(lumpname, 0); if (lump == -1) I_Error("Unable to load '%s'", lumpname); return GetStringFromLump(lump); } diff --git a/source/common/scripting/backend/codegen.cpp b/source/common/scripting/backend/codegen.cpp index b14fb267cd6..86bd606f9ec 100644 --- a/source/common/scripting/backend/codegen.cpp +++ b/source/common/scripting/backend/codegen.cpp @@ -8268,8 +8268,12 @@ static bool CheckFunctionCompatiblity(FScriptPosition &ScriptPosition, PFunction FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList &&args, const FScriptPosition &pos) : FxExpression(EFX_FunctionCall, pos) { + const bool isClient = methodname == NAME_CRandom || methodname == NAME_CFRandom + || methodname == NAME_CRandomPick || methodname == NAME_CFRandomPick + || methodname == NAME_CRandom2 || methodname == NAME_CSetRandomSeed; + MethodName = methodname; - RNG = &pr_exrandom; + RNG = isClient ? &M_Random : &pr_exrandom; ArgList = std::move(args); if (rngname != NAME_None) { @@ -8281,7 +8285,16 @@ FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList && case NAME_FRandomPick: case NAME_Random2: case NAME_SetRandomSeed: - RNG = FRandom::StaticFindRNG(rngname.GetChars()); + RNG = FRandom::StaticFindRNG(rngname.GetChars(), false); + break; + + case NAME_CRandom: + case NAME_CFRandom: + case NAME_CRandomPick: + case NAME_CFRandomPick: + case NAME_CRandom2: + case NAME_CSetRandomSeed: + RNG = FRandom::StaticFindRNG(rngname.GetChars(), true); break; default: @@ -8547,13 +8560,22 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } break; + case NAME_CSetRandomSeed: + if (CheckArgSize(NAME_CRandom, ArgList, 1, 1, ScriptPosition)) + { + func = new FxRandomSeed(RNG, ArgList[0], ScriptPosition, ctx.FromDecorate); + ArgList[0] = nullptr; + } + break; + case NAME_Random: + case NAME_CRandom: // allow calling Random without arguments to default to (0, 255) if (ArgList.Size() == 0) { func = new FxRandom(RNG, new FxConstant(0, ScriptPosition), new FxConstant(255, ScriptPosition), ScriptPosition, ctx.FromDecorate); } - else if (CheckArgSize(NAME_Random, ArgList, 2, 2, ScriptPosition)) + else if (CheckArgSize(MethodName, ArgList, 2, 2, ScriptPosition)) { func = new FxRandom(RNG, ArgList[0], ArgList[1], ScriptPosition, ctx.FromDecorate); ArgList[0] = ArgList[1] = nullptr; @@ -8561,7 +8583,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) break; case NAME_FRandom: - if (CheckArgSize(NAME_FRandom, ArgList, 2, 2, ScriptPosition)) + case NAME_CFRandom: + if (CheckArgSize(MethodName, ArgList, 2, 2, ScriptPosition)) { func = new FxFRandom(RNG, ArgList[0], ArgList[1], ScriptPosition); ArgList[0] = ArgList[1] = nullptr; @@ -8570,14 +8593,17 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_RandomPick: case NAME_FRandomPick: + case NAME_CRandomPick: + case NAME_CFRandomPick: if (CheckArgSize(MethodName, ArgList, 1, -1, ScriptPosition)) { - func = new FxRandomPick(RNG, ArgList, MethodName == NAME_FRandomPick, ScriptPosition, ctx.FromDecorate); + func = new FxRandomPick(RNG, ArgList, MethodName == NAME_FRandomPick || MethodName == NAME_CFRandomPick, ScriptPosition, ctx.FromDecorate); } break; case NAME_Random2: - if (CheckArgSize(NAME_Random2, ArgList, 0, 1, ScriptPosition)) + case NAME_CRandom2: + if (CheckArgSize(MethodName, ArgList, 0, 1, ScriptPosition)) { func = new FxRandom2(RNG, ArgList.Size() == 0? nullptr : ArgList[0], ScriptPosition, ctx.FromDecorate); if (ArgList.Size() > 0) ArgList[0] = nullptr; @@ -12640,6 +12666,15 @@ FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) if (ValueType->RegType == REGT_NIL && ValueType != TypeAuto) { auto sfunc = static_cast(ctx.Function->Variants[0].Implementation); + + const unsigned MAX_STACK_ALLOC = 512 * 1024; // Windows stack is 1 MB, but we cannot go up there without problems + if (uint64_t(ValueType->Size) + uint64_t(sfunc->ExtraSpace) > MAX_STACK_ALLOC) + { + ScriptPosition.Message(MSG_ERROR, "%s exceeds max. allowed size of 512kb for local variables at variable %s", sfunc->Name.GetChars(), Name.GetChars()); + delete this; + return nullptr; + } + StackOffset = sfunc->AllocExtraStack(ValueType); if (Init != nullptr) diff --git a/source/common/scripting/backend/vmbuilder.cpp b/source/common/scripting/backend/vmbuilder.cpp index 71a766d9a79..5437ca848a5 100644 --- a/source/common/scripting/backend/vmbuilder.cpp +++ b/source/common/scripting/backend/vmbuilder.cpp @@ -879,10 +879,18 @@ void FFunctionBuildList::Build() { if (!item.Code->CheckReturn()) { - auto newcmpd = new FxCompoundStatement(item.Code->ScriptPosition); - newcmpd->Add(item.Code); - newcmpd->Add(new FxReturnStatement(nullptr, item.Code->ScriptPosition)); - item.Code = newcmpd->Resolve(ctx); + if (ctx.ReturnProto == nullptr || !ctx.ReturnProto->ReturnTypes.Size()) + { + auto newcmpd = new FxCompoundStatement(item.Code->ScriptPosition); + newcmpd->Add(item.Code); + newcmpd->Add(new FxReturnStatement(nullptr, item.Code->ScriptPosition)); + item.Code = newcmpd->Resolve(ctx); + } + else + { + item.Code->ScriptPosition.Message(MSG_ERROR, "Missing return statement in %s", item.PrintableName.GetChars()); + continue; + } } item.Proto = ctx.ReturnProto; diff --git a/source/common/scripting/core/types.cpp b/source/common/scripting/core/types.cpp index b70783f3e1e..fef3e6ec2e8 100644 --- a/source/common/scripting/core/types.cpp +++ b/source/common/scripting/core/types.cpp @@ -2585,7 +2585,7 @@ static void PMapValueWriter(FSerializer &ar, const M *map, const PMap *m) if (TexMan.GetLinkedTexture(lump) == tex) { - name = fileSystem.GetFileFullName(lump); + name = fileSystem.GetFileName(lump); } else { diff --git a/source/common/scripting/frontend/zcc_compile.cpp b/source/common/scripting/frontend/zcc_compile.cpp index d109717a32f..faef50959c8 100644 --- a/source/common/scripting/frontend/zcc_compile.cpp +++ b/source/common/scripting/frontend/zcc_compile.cpp @@ -2286,6 +2286,11 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, Error(arraysize, "Array size must be positive"); return TypeError; } + if (uint64_t(size) * baseType->Size > 0x7fffffff) + { + Error(arraysize, "Array size overflow. Total size must be less than 2GB"); + return TypeError; + } baseType = NewArray(baseType, size); } diff --git a/source/common/scripting/frontend/zcc_parser.cpp b/source/common/scripting/frontend/zcc_parser.cpp index 6ea3c316e6b..26bf2539139 100644 --- a/source/common/scripting/frontend/zcc_parser.cpp +++ b/source/common/scripting/frontend/zcc_parser.cpp @@ -304,7 +304,7 @@ static void ParseSingleFile(FScanner *pSC, const char *filename, int lump, void { if (filename != nullptr) { - lump = fileSystem.CheckNumForFullName(filename, true); + lump = fileSystem.CheckNumForAnyName(filename); if (lump >= 0) { lsc.OpenLumpNum(lump); @@ -480,7 +480,7 @@ PNamespace *ParseOneScript(const int baselump, ZCCParseState &state) ParseSingleFile(&sc, nullptr, lumpnum, parser, state); for (unsigned i = 0; i < Includes.Size(); i++) { - lumpnum = fileSystem.CheckNumForFullName(Includes[i].GetChars(), true); + lumpnum = fileSystem.CheckNumForAnyName(Includes[i].GetChars()); if (lumpnum == -1) { IncludeLocs[i].Message(MSG_ERROR, "Include script lump %s not found", Includes[i].GetChars()); @@ -491,7 +491,7 @@ PNamespace *ParseOneScript(const int baselump, ZCCParseState &state) if (fileno == 0 && fileno2 != 0) { I_FatalError("File %s is overriding core lump %s.", - fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(lumpnum)), Includes[i].GetChars()); + fileSystem.GetContainerFullName(fileSystem.GetFileContainer(lumpnum)), Includes[i].GetChars()); } ParseSingleFile(nullptr, nullptr, lumpnum, parser, state); diff --git a/source/common/scripting/interface/vmnatives.cpp b/source/common/scripting/interface/vmnatives.cpp index 2b57ceb25a3..922f56a67e6 100644 --- a/source/common/scripting/interface/vmnatives.cpp +++ b/source/common/scripting/interface/vmnatives.cpp @@ -426,7 +426,7 @@ DEFINE_ACTION_FUNCTION(_TexMan, GetName) // Textures for full path names do not have their own name, they merely link to the source lump. auto lump = tex->GetSourceLump(); if (TexMan.GetLinkedTexture(lump) == tex) - retval = fileSystem.GetFileFullName(lump); + retval = fileSystem.GetFileName(lump); } } ACTION_RETURN_STRING(retval); @@ -799,7 +799,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(FFont, GetChar, ::GetChar) DEFINE_ACTION_FUNCTION(_Wads, GetNumLumps) { PARAM_PROLOGUE; - ACTION_RETURN_INT(fileSystem.GetNumEntries()); + ACTION_RETURN_INT(fileSystem.GetFileCount()); } DEFINE_ACTION_FUNCTION(_Wads, CheckNumForName) @@ -816,7 +816,7 @@ DEFINE_ACTION_FUNCTION(_Wads, CheckNumForFullName) { PARAM_PROLOGUE; PARAM_STRING(name); - ACTION_RETURN_INT(fileSystem.CheckNumForFullName(name.GetChars())); + ACTION_RETURN_INT(fileSystem.FindFile(name.GetChars())); } DEFINE_ACTION_FUNCTION(_Wads, FindLump) @@ -825,7 +825,7 @@ DEFINE_ACTION_FUNCTION(_Wads, FindLump) PARAM_STRING(name); PARAM_INT(startlump); PARAM_INT(ns); - const bool isLumpValid = startlump >= 0 && startlump < fileSystem.GetNumEntries(); + const bool isLumpValid = startlump >= 0 && startlump < fileSystem.GetFileCount(); ACTION_RETURN_INT(isLumpValid ? fileSystem.FindLump(name.GetChars(), &startlump, 0 != ns) : -1); } @@ -835,7 +835,7 @@ DEFINE_ACTION_FUNCTION(_Wads, FindLumpFullName) PARAM_STRING(name); PARAM_INT(startlump); PARAM_BOOL(noext); - const bool isLumpValid = startlump >= 0 && startlump < fileSystem.GetNumEntries(); + const bool isLumpValid = startlump >= 0 && startlump < fileSystem.GetFileCount(); ACTION_RETURN_INT(isLumpValid ? fileSystem.FindLumpFullName(name.GetChars(), &startlump, noext) : -1); } @@ -850,7 +850,7 @@ DEFINE_ACTION_FUNCTION(_Wads, GetLumpFullName) { PARAM_PROLOGUE; PARAM_INT(lump); - ACTION_RETURN_STRING(fileSystem.GetFileFullName(lump)); + ACTION_RETURN_STRING(fileSystem.GetFileName(lump)); } DEFINE_ACTION_FUNCTION(_Wads, GetLumpNamespace) @@ -864,7 +864,7 @@ DEFINE_ACTION_FUNCTION(_Wads, ReadLump) { PARAM_PROLOGUE; PARAM_INT(lump); - const bool isLumpValid = lump >= 0 && lump < fileSystem.GetNumEntries(); + const bool isLumpValid = lump >= 0 && lump < fileSystem.GetFileCount(); ACTION_RETURN_STRING(isLumpValid ? GetStringFromLump(lump, false) : FString()); } diff --git a/source/common/startscreen/endoom.cpp b/source/common/startscreen/endoom.cpp index 6e8e7af353d..7f47829a129 100644 --- a/source/common/startscreen/endoom.cpp +++ b/source/common/startscreen/endoom.cpp @@ -153,14 +153,14 @@ int RunEndoom() return 0; } - int endoom_lump = fileSystem.CheckNumForFullName (endoomName.GetChars(), true); + int endoom_lump = fileSystem.CheckNumForAnyName (endoomName.GetChars()); if (endoom_lump < 0 || fileSystem.FileLength (endoom_lump) != 4000) { return 0; } - if (fileSystem.GetFileContainer(endoom_lump) == fileSystem.GetMaxIwadNum() && showendoom == 2) + if (fileSystem.GetFileContainer(endoom_lump) == fileSystem.GetMaxBaseNum() && showendoom == 2) { // showendoom==2 means to show only lumps from PWADs. return 0; diff --git a/source/common/startscreen/startscreen_generic.cpp b/source/common/startscreen/startscreen_generic.cpp index b76cbd3e250..4c41bc7a836 100644 --- a/source/common/startscreen/startscreen_generic.cpp +++ b/source/common/startscreen/startscreen_generic.cpp @@ -72,7 +72,7 @@ FGenericStartScreen::FGenericStartScreen(int max_progress) : FStartScreen(max_progress) { // at this point we do not have a working texture manager yet, so we have to do the lookup via the file system - int startup_lump = fileSystem.CheckNumForName("BOOTLOGO", FileSys::ns_graphics); + int startup_lump = fileSystem.CheckNumForName("BOOTLOGO", ns_graphics); StartupBitmap.Create(640 * 2, 480 * 2); ClearBlock(StartupBitmap, { 0, 0, 0, 255 }, 0, 0, 640 * 2, 480 * 2); diff --git a/source/common/startscreen/startscreen_hexen.cpp b/source/common/startscreen/startscreen_hexen.cpp index a82e21b3518..6eef7359949 100644 --- a/source/common/startscreen/startscreen_hexen.cpp +++ b/source/common/startscreen/startscreen_hexen.cpp @@ -81,9 +81,9 @@ FHexenStartScreen::FHexenStartScreen(int max_progress) : FStartScreen(max_progress) { // at this point we do not have a working texture manager yet, so we have to do the lookup via the file system - int startup_lump = fileSystem.CheckNumForName("STARTUP", FileSys::ns_graphics); - int netnotch_lump = fileSystem.CheckNumForName("NETNOTCH", FileSys::ns_graphics); - int notch_lump = fileSystem.CheckNumForName("NOTCH", FileSys::ns_graphics); + int startup_lump = fileSystem.CheckNumForName("STARTUP", ns_graphics); + int netnotch_lump = fileSystem.CheckNumForName("NETNOTCH", ns_graphics); + int notch_lump = fileSystem.CheckNumForName("NOTCH", ns_graphics); // For backwards compatibility we also need to look in the default namespace, because these were previously not handled as graphics. if (startup_lump == -1) startup_lump = fileSystem.CheckNumForName("STARTUP"); diff --git a/source/common/startscreen/startscreen_strife.cpp b/source/common/startscreen/startscreen_strife.cpp index df5467f9660..8f02b2022af 100644 --- a/source/common/startscreen/startscreen_strife.cpp +++ b/source/common/startscreen/startscreen_strife.cpp @@ -111,7 +111,7 @@ FStrifeStartScreen::FStrifeStartScreen(int max_progress) // Load the background and animated overlays. for (size_t i = 0; i < countof(StrifeStartupPicNames); ++i) { - int lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i], FileSys::ns_graphics); + int lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i], ns_graphics); if (lumpnum < 0) lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i]); if (lumpnum >= 0) diff --git a/source/common/textures/formats/pngtexture.cpp b/source/common/textures/formats/pngtexture.cpp index 01f210a1c5b..add80bfdff3 100644 --- a/source/common/textures/formats/pngtexture.cpp +++ b/source/common/textures/formats/pngtexture.cpp @@ -119,12 +119,12 @@ FImageSource *PNGImage_TryCreate(FileReader & data, int lumpnum) if (compression != 0 || filter != 0 || interlace > 1) { - Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the compression, filter, or interlace is not supported!\n", fileSystem.GetFileFullName(lumpnum)); + Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the compression, filter, or interlace is not supported!\n", fileSystem.GetFileName(lumpnum)); return NULL; } if (!((1 << colortype) & 0x5D)) { - Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the colortype (%u) is not supported!\n", fileSystem.GetFileFullName(lumpnum), colortype); + Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the colortype (%u) is not supported!\n", fileSystem.GetFileName(lumpnum), colortype); return NULL; } if (!((1 << bitdepth) & 0x116)) @@ -150,12 +150,12 @@ FImageSource *PNGImage_TryCreate(FileReader & data, int lumpnum) int ihoty = data.ReadInt32BE(); if (ihotx < -32768 || ihotx > 32767) { - Printf("X-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileFullName(lumpnum), ihotx, ihotx); + Printf("X-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileName(lumpnum), ihotx, ihotx); ihotx = 0; } if (ihoty < -32768 || ihoty > 32767) { - Printf("Y-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileFullName(lumpnum), ihoty, ihoty); + Printf("Y-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileName(lumpnum), ihoty, ihoty); ihoty = 0; } tex->SetOffsets(ihotx, ihoty); @@ -169,7 +169,7 @@ FImageSource *PNGImage_TryCreate(FileReader & data, int lumpnum) return tex; } - Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the bit-depth (%u) is not supported!\n", fileSystem.GetFileFullName(lumpnum), bitdepth); + Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the bit-depth (%u) is not supported!\n", fileSystem.GetFileName(lumpnum), bitdepth); return NULL; } @@ -180,7 +180,7 @@ FImageSource *PNGImage_TryCreate(FileReader & data, int lumpnum) { if (data.Read(first4bytes.b, 4) != 4 || first4bytes.dw == MAKE_ID('I','E','N','D')) { - Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the file ends immediately after the IHDR.\n", fileSystem.GetFileFullName(lumpnum)); + Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the file ends immediately after the IHDR.\n", fileSystem.GetFileName(lumpnum)); return NULL; } } @@ -231,12 +231,12 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, int width, int height, int ihoty = lump.ReadInt32BE(); if (ihotx < -32768 || ihotx > 32767) { - Printf ("X-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileFullName (lumpnum), ihotx, ihotx); + Printf ("X-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileName (lumpnum), ihotx, ihotx); ihotx = 0; } if (ihoty < -32768 || ihoty > 32767) { - Printf ("Y-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileFullName (lumpnum), ihoty, ihoty); + Printf ("Y-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileName (lumpnum), ihoty, ihoty); ihoty = 0; } LeftOffset = ihotx; diff --git a/source/common/textures/gametexture.cpp b/source/common/textures/gametexture.cpp index 755f48b49e3..546a1200564 100644 --- a/source/common/textures/gametexture.cpp +++ b/source/common/textures/gametexture.cpp @@ -124,7 +124,7 @@ FGameTexture::~FGameTexture() bool FGameTexture::isUserContent() const { int filenum = fileSystem.GetFileContainer(Base->GetSourceLump()); - return (filenum > fileSystem.GetMaxIwadNum()); + return (filenum > fileSystem.GetMaxBaseNum()); } @@ -182,10 +182,10 @@ void FGameTexture::AddAutoMaterials() if (this->*(layer.pointer) == nullptr) // only if no explicit assignment had been done. { FStringf lookup("%s%s%s", layer.path, fullname ? "" : "auto/", searchname.GetChars()); - auto lump = fileSystem.CheckNumForFullName(lookup.GetChars(), false, FileSys::ns_global, true); + auto lump = fileSystem.FindFile(lookup.GetChars(), true); if (lump != -1) { - auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny); + auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny); if (bmtex != nullptr) { this->*(layer.pointer) = bmtex->GetTexture(); @@ -199,10 +199,10 @@ void FGameTexture::AddAutoMaterials() if (!this->Layers || this->Layers.get()->*(layer.pointer) == nullptr) // only if no explicit assignment had been done. { FStringf lookup("%s%s%s", layer.path, fullname ? "" : "auto/", searchname.GetChars()); - auto lump = fileSystem.CheckNumForFullName(lookup.GetChars(), false, FileSys::ns_global, true); + auto lump = fileSystem.FindFile(lookup.GetChars(), true); if (lump != -1) { - auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny); + auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny); if (bmtex != nullptr) { if (this->Layers == nullptr) this->Layers = std::make_unique(); diff --git a/source/common/textures/gametexture.h b/source/common/textures/gametexture.h index 3eb3740a952..a55616e66eb 100644 --- a/source/common/textures/gametexture.h +++ b/source/common/textures/gametexture.h @@ -62,6 +62,7 @@ enum EGameTexFlags GTexf_OffsetsNotForFont = 512, // The offsets must be ignored when using this texture in a font. GTexf_NoTrim = 1024, // Don't perform trimming on this texture. GTexf_Seen = 2048, // Set to true when the texture is being used for rendering. Must be cleared manually if the check is needed. + GTexf_NoMipmap = 4096, // Disable mipmapping for this texture }; struct FMaterialLayers @@ -265,6 +266,9 @@ class FGameTexture void SetGlowing(PalEntry color) { flags = (flags & ~GTexf_AutoGlowing) | GTexf_Glowing; GlowColor = color; } void SetDisableBrightmap() { flags |= GTexf_BrightmapChecked; Brightmap = nullptr; } + bool isNoMipmap() const { return !!(flags & GTexf_NoMipmap); } + void SetNoMipmap(bool set) { if (set) flags |= GTexf_NoMipmap; else flags &= ~GTexf_NoMipmap; } + bool isUserContent() const; int CheckRealHeight() { return xs_RoundToInt(Base->CheckRealHeight() / ScaleY); } void SetSize(int x, int y) diff --git a/source/common/textures/texturemanager.cpp b/source/common/textures/texturemanager.cpp index 1173f61be05..7d279820317 100644 --- a/source/common/textures/texturemanager.cpp +++ b/source/common/textures/texturemanager.cpp @@ -50,7 +50,6 @@ #include "basics.h" #include "cmdlib.h" -using namespace FileSys; FTextureManager TexMan; @@ -248,7 +247,7 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset if (strchr(name, '/') || (flags & TEXMAN_ForceLookup)) { FGameTexture *const NO_TEXTURE = (FGameTexture*)-1; // marker for lumps we already checked that do not map to a texture. - int lump = fileSystem.CheckNumForFullName(name); + int lump = fileSystem.FindFile(name); if (lump >= 0) { FGameTexture *tex = GetLinkedTexture(lump); @@ -395,7 +394,7 @@ bool FTextureManager::OkForLocalization(FTextureID texnum, const char *substitut // Mode 3 must also reject substitutions for non-IWAD content. int file = fileSystem.GetFileContainer(Textures[texnum.GetIndex()].Texture->GetSourceLump()); - if (file > fileSystem.GetMaxIwadNum()) return true; + if (file > fileSystem.GetMaxBaseNum()) return true; return false; } @@ -457,7 +456,7 @@ FTextureID FTextureManager::CreateTexture (int lumpnum, ETextureType usetype) str = fileSystem.GetFileShortName(lumpnum); else { - auto fn = fileSystem.GetFileFullName(lumpnum); + auto fn = fileSystem.GetFileName(lumpnum); str = ExtractFileBase(fn); } auto out = MakeGameTexture(CreateTextureFromLump(lumpnum, usetype == ETextureType::Flat), str.GetChars(), usetype); @@ -585,7 +584,7 @@ void FTextureManager::AddGroup(int wadnum, int ns, ETextureType usetype) } progressFunc(); } - else if (ns == ns_flats && fileSystem.GetFileFlags(firsttx) & RESFF_MAYBEFLAT) + else if (ns == ns_flats && fileSystem.GetFileNamespace(firsttx) == ns_maybeflat) { if (fileSystem.CheckNumForName(Name, ns) < firsttx) { @@ -723,8 +722,8 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build FName texname = sc.String; sc.MustGetString(); - int lumpnum = fileSystem.CheckNumForFullName(sc.String, true, ns_patches); - if (lumpnum == -1) lumpnum = fileSystem.CheckNumForFullName(sc.String, true, ns_graphics); + int lumpnum = fileSystem.CheckNumForAnyName(sc.String, ns_patches); + if (lumpnum == -1) lumpnum = fileSystem.CheckNumForAnyName(sc.String, ns_graphics); if (tlist.Size() == 0) { @@ -779,8 +778,8 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build { FString src = base.Left(8); - int lumpnum = fileSystem.CheckNumForFullName(sc.String, true, ns_patches); - if (lumpnum == -1) lumpnum = fileSystem.CheckNumForFullName(sc.String, true, ns_graphics); + int lumpnum = fileSystem.CheckNumForAnyName(sc.String, ns_patches); + if (lumpnum == -1) lumpnum = fileSystem.CheckNumForAnyName(sc.String, ns_graphics); sc.GetString(); bool is32bit = !!sc.Compare("force32bit"); @@ -854,7 +853,7 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build sc.MustGetString(); // This is not using sc.Open because it can print a more useful error message when done here - int includelump = fileSystem.CheckNumForFullName(sc.String, true); + int includelump = fileSystem.CheckNumForAnyName(sc.String); if (includelump == -1) { sc.ScriptError("Lump '%s' not found", sc.String); @@ -937,7 +936,7 @@ void FTextureManager::LoadTextureX(int wadnum, FMultipatchTextureBuilder &build) void FTextureManager::AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &build) { int firsttexture = Textures.Size(); - bool iwad = wadnum >= fileSystem.GetIwadNum() && wadnum <= fileSystem.GetMaxIwadNum(); + bool iwad = wadnum >= fileSystem.GetBaseNum() && wadnum <= fileSystem.GetMaxBaseNum(); FirstTextureForFile.Push(firsttexture); @@ -971,7 +970,7 @@ void FTextureManager::AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &b if (ns == ns_global) { // In Zips all graphics must be in a separate namespace. - if (fileSystem.GetFileFlags(i) & RESFF_FULLPATH) continue; + if (fileSystem.GetFileFlags(i) & FileSys::RESFF_FULLPATH) continue; // Ignore lumps with empty names. if (fileSystem.CheckFileName(i, "")) continue; @@ -1109,7 +1108,7 @@ void FTextureManager::SortTexturesByType(int start, int end) void FTextureManager::AddLocalizedVariants() { - std::vector content; + std::vector content; fileSystem.GetFilesInFolder("localized/textures/", content, false); for (auto &entry : content) { @@ -1218,7 +1217,7 @@ void FTextureManager::AddTextures(void (*progressFunc_)(), void (*checkForHacks) progressFunc = progressFunc_; //if (BuildTileFiles.Size() == 0) CountBuildTiles (); - int wadcnt = fileSystem.GetNumWads(); + int wadcnt = fileSystem.GetContainerCount(); FMultipatchTextureBuilder build(*this, progressFunc_, checkForHacks); @@ -1410,7 +1409,7 @@ int FTextureManager::GuesstimateNumTextures () { int numtex = 0; - for(int i = fileSystem.GetNumEntries()-1; i>=0; i--) + for(int i = fileSystem.GetFileCount()-1; i>=0; i--) { int space = fileSystem.GetFileNamespace(i); switch(space) @@ -1421,12 +1420,11 @@ int FTextureManager::GuesstimateNumTextures () case ns_hires: case ns_patches: case ns_graphics: + case ns_maybeflat: numtex++; break; default: - if (fileSystem.GetFileFlags(i) & RESFF_MAYBEFLAT) numtex++; - break; } } @@ -1447,7 +1445,7 @@ int FTextureManager::GuesstimateNumTextures () int FTextureManager::CountTexturesX () { int count = 0; - int wadcount = fileSystem.GetNumWads(); + int wadcount = fileSystem.GetContainerCount(); for (int wadnum = 0; wadnum < wadcount; wadnum++) { // Use the most recent PNAMES for this WAD. @@ -1505,16 +1503,16 @@ void FTextureManager::AdjustSpriteOffsets() int sprid; TMap donotprocess; - int numtex = fileSystem.GetNumEntries(); + int numtex = fileSystem.GetFileCount(); for (int i = 0; i < numtex; i++) { - if (fileSystem.GetFileContainer(i) > fileSystem.GetMaxIwadNum()) break; // we are past the IWAD - if (fileSystem.GetFileNamespace(i) == ns_sprites && fileSystem.GetFileContainer(i) >= fileSystem.GetIwadNum() && fileSystem.GetFileContainer(i) <= fileSystem.GetMaxIwadNum()) + if (fileSystem.GetFileContainer(i) > fileSystem.GetMaxBaseNum()) break; // we are past the IWAD + if (fileSystem.GetFileNamespace(i) == ns_sprites && fileSystem.GetFileContainer(i) >= fileSystem.GetBaseNum() && fileSystem.GetFileContainer(i) <= fileSystem.GetMaxBaseNum()) { const char *str = fileSystem.GetFileShortName(i); FTextureID texid = TexMan.CheckForTexture(str, ETextureType::Sprite, 0); - if (texid.isValid() && fileSystem.GetFileContainer(GetGameTexture(texid)->GetSourceLump()) > fileSystem.GetMaxIwadNum()) + if (texid.isValid() && fileSystem.GetFileContainer(GetGameTexture(texid)->GetSourceLump()) > fileSystem.GetMaxBaseNum()) { // This texture has been replaced by some PWAD. memcpy(&sprid, str, 4); @@ -1553,12 +1551,12 @@ void FTextureManager::AdjustSpriteOffsets() int lumpnum = tex->GetSourceLump(); // We only want to change texture offsets for sprites in the IWAD or the file this lump originated from. - if (lumpnum >= 0 && lumpnum < fileSystem.GetNumEntries()) + if (lumpnum >= 0 && lumpnum < fileSystem.GetFileCount()) { int wadno = fileSystem.GetFileContainer(lumpnum); - if ((iwadonly && wadno >= fileSystem.GetIwadNum() && wadno <= fileSystem.GetMaxIwadNum()) || (!iwadonly && wadno == ofslumpno)) + if ((iwadonly && wadno >= fileSystem.GetBaseNum() && wadno <= fileSystem.GetMaxBaseNum()) || (!iwadonly && wadno == ofslumpno)) { - if (wadno >= fileSystem.GetIwadNum() && wadno <= fileSystem.GetMaxIwadNum() && !forced && iwadonly) + if (wadno >= fileSystem.GetBaseNum() && wadno <= fileSystem.GetMaxBaseNum() && !forced && iwadonly) { memcpy(&sprid, tex->GetName().GetChars(), 4); if (donotprocess.CheckKey(sprid)) continue; // do not alter sprites that only get partially replaced. @@ -1632,7 +1630,7 @@ void FTextureManager::Listaliases() void FTextureManager::SetLinkedTexture(int lump, FGameTexture* tex) { - if (lump < fileSystem.GetNumEntries()) + if (lump < fileSystem.GetFileCount()) { linkedMap.Insert(lump, tex); } @@ -1646,7 +1644,7 @@ void FTextureManager::SetLinkedTexture(int lump, FGameTexture* tex) FGameTexture* FTextureManager::GetLinkedTexture(int lump) { - if (lump < fileSystem.GetNumEntries()) + if (lump < fileSystem.GetFileCount()) { auto check = linkedMap.CheckKey(lump); if (check) return *check; diff --git a/source/common/utility/palette.cpp b/source/common/utility/palette.cpp index 03517c1ba55..cf9fbbe62f6 100644 --- a/source/common/utility/palette.cpp +++ b/source/common/utility/palette.cpp @@ -672,7 +672,7 @@ FString V_GetColorStringByName(const char* name, FScriptPosition* sc) int c[3], step; size_t namelen; - if (fileSystem.GetNumEntries() == 0) return FString(); + if (fileSystem.GetFileCount() == 0) return FString(); rgblump = fileSystem.CheckNumForName("X11R6RGB"); if (rgblump == -1) @@ -960,13 +960,13 @@ int ReadPalette(int lumpnum, uint8_t* buffer) id = MAKE_ID('I', 'E', 'N', 'D'); fr.Read(&id, 4); } - I_Error("%s contains no palette", fileSystem.GetFileFullName(lumpnum)); + I_Error("%s contains no palette", fileSystem.GetFileName(lumpnum)); } if (memcmp(lumpmem, "JASC-PAL", 8) == 0) { FScanner sc; - sc.OpenMem(fileSystem.GetFileFullName(lumpnum), (char*)lumpmem, int(lump.size())); + sc.OpenMem(fileSystem.GetFileName(lumpnum), (char*)lumpmem, int(lump.size())); sc.MustGetString(); sc.MustGetNumber(); // version - ignore sc.MustGetNumber(); diff --git a/source/common/utility/tarray.h b/source/common/utility/tarray.h index 3445bd48409..25d6e0e7f5c 100644 --- a/source/common/utility/tarray.h +++ b/source/common/utility/tarray.h @@ -924,7 +924,7 @@ class TDeletingArray : public TArray return *this; } - ~TDeletingArray () + ~TDeletingArray() { for (unsigned int i = 0; i < TArray::Size(); ++i) { diff --git a/source/common/widgets/netstartwindow.cpp b/source/common/widgets/netstartwindow.cpp index 69c83e56542..887f9cc3163 100644 --- a/source/common/widgets/netstartwindow.cpp +++ b/source/common/widgets/netstartwindow.cpp @@ -64,6 +64,12 @@ bool NetStartWindow::RunMessageLoop(bool (*newtimer_callback)(void*), void* newu return Instance->exitreason; } +void NetStartWindow::NetClose() +{ + if (Instance != nullptr) + Instance->OnClose(); +} + NetStartWindow::NetStartWindow() : Widget(nullptr, WidgetType::Window) { SetWindowBackground(Colorf::fromRgba8(51, 51, 51)); diff --git a/source/common/widgets/netstartwindow.h b/source/common/widgets/netstartwindow.h index 5d27b8ebfc7..dcc9d688eac 100644 --- a/source/common/widgets/netstartwindow.h +++ b/source/common/widgets/netstartwindow.h @@ -14,6 +14,7 @@ class NetStartWindow : public Widget static void HideNetStartPane(); static void SetNetStartProgress(int pos); static bool RunMessageLoop(bool (*timer_callback)(void*), void* userdata); + static void NetClose(); private: NetStartWindow(); diff --git a/source/core/defparser.cpp b/source/core/defparser.cpp index 412b4f3099d..b7389b813c6 100644 --- a/source/core/defparser.cpp +++ b/source/core/defparser.cpp @@ -1978,7 +1978,7 @@ void loaddefinitionsfile(TilesetBuildInfo& info, const char* fn, bool cumulative int lump, lastlump = 0; while ((lump = fileSystem.FindLumpFullName(fn, &lastlump)) >= 0) { - if (maingame && fileSystem.GetFileContainer(lump) > fileSystem.GetMaxIwadNum()) break; + if (maingame && fileSystem.GetFileContainer(lump) > fileSystem.GetMaxBaseNum()) break; Printf(PRINT_NONOTIFY, "Loading \"%s\"\n", fileSystem.GetFileFullPath(lump).c_str()); deftimer.Clock(); parseit(lump); diff --git a/source/core/g_mapinfo.cpp b/source/core/g_mapinfo.cpp index c22f87e8db3..2ed2625963a 100644 --- a/source/core/g_mapinfo.cpp +++ b/source/core/g_mapinfo.cpp @@ -1664,7 +1664,7 @@ void FMapInfoParser::ParseMapInfo (int lump, MapRecord &gamedefaults, MapRecord if (sc.Compare("include")) { sc.MustGetString(); - int inclump = fileSystem.CheckNumForFullName(sc.String, true); + int inclump = fileSystem.CheckNumForAnyName(sc.String); if (inclump < 0) { sc.ScriptError("include file '%s' not found", sc.String); @@ -1675,7 +1675,7 @@ void FMapInfoParser::ParseMapInfo (int lump, MapRecord &gamedefaults, MapRecord if (fileSystem.GetFileContainer(sc.LumpNum) == 0) { I_FatalError("File %s is overriding core lump %s.", - fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(inclump)), sc.String); + fileSystem.GetContainerFullName(fileSystem.GetFileContainer(inclump)), sc.String); } } // use a new parser object to parse the include. Otherwise we'd have to save the entire FScanner in a local variable which is a lot more messy. diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index 485f5a3f4da..79b6f1ba829 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -292,7 +292,7 @@ void System_CrashInfo(char* buffer, size_t bufflen, const char *lfstr) buffer += snprintf(buffer, buffend - buffer, " %s", Args->GetArg(i)); } - for (i = 0; (arg = fileSystem.GetResourceFileName(i)) != NULL; ++i) + for (i = 0; (arg = fileSystem.GetContainerName(i)) != NULL; ++i) { buffer += mysnprintf(buffer, buffend - buffer, "%sFile %d: %s", lfstr, i, arg); } @@ -1026,9 +1026,9 @@ int RunGame() InitWidgetResources(wad); // load strings for picker window. - FileSys::FileSystem lang_fs; + FileSystem lang_fs; std::vector base_fn = { wad }; - lang_fs.InitMultipleFiles(base_fn); + lang_fs.Initialize(base_fn); GStrings.LoadStrings(lang_fs, language); // Set up the console before anything else so that it can receive text. diff --git a/source/core/initfs.cpp b/source/core/initfs.cpp index 78b9c98c7e7..7d5ddeef80f 100644 --- a/source/core/initfs.cpp +++ b/source/core/initfs.cpp @@ -49,8 +49,6 @@ #include "startupinfo.h" #include "files.h" -using namespace FileSys; - #ifndef PATH_MAX #define PATH_MAX 260 #endif @@ -268,10 +266,10 @@ static void DeleteStuff(FileSystem &fileSystem, const TArray& deletelum str.Truncate(ndx); } - for (int i = 0; i < fileSystem.GetNumEntries(); i++) + for (int i = 0; i < fileSystem.GetFileCount(); i++) { int cf = fileSystem.GetFileContainer(i); - auto fname = fileSystem.GetFileFullName(i, false); + auto fname = fileSystem.GetFileName(i); if (cf >= 1 && cf <= numgamefiles && !str.CompareNoCase(fname)) { fileSystem.RenameFile(i, renameTo.GetChars()); @@ -296,7 +294,7 @@ const char** iwad_reserved() (g_gameType & GAMEFLAG_BLOOD) ? iwad_reserved_blood : iwad_reserved_duke; } -static int FileSystemPrintf(FSMessageLevel level, const char* fmt, ...) +static int FileSystemPrintf(FileSys::FSMessageLevel level, const char* fmt, ...) { va_list arg; va_start(arg, fmt); @@ -304,22 +302,22 @@ static int FileSystemPrintf(FSMessageLevel level, const char* fmt, ...) text.VFormat(fmt, arg); switch (level) { - case FSMessageLevel::Error: + case FileSys::FSMessageLevel::Error: return Printf(TEXTCOLOR_RED "%s", text.GetChars()); break; - case FSMessageLevel::Warning: + case FileSys::FSMessageLevel::Warning: Printf(TEXTCOLOR_YELLOW "%s", text.GetChars()); break; - case FSMessageLevel::Attention: + case FileSys::FSMessageLevel::Attention: Printf(TEXTCOLOR_BLUE "%s", text.GetChars()); break; - case FSMessageLevel::Message: + case FileSys::FSMessageLevel::Message: Printf("%s", text.GetChars()); break; - case FSMessageLevel::DebugWarn: + case FileSys::FSMessageLevel::DebugWarn: DPrintf(DMSG_WARNING, "%s", text.GetChars()); break; - case FSMessageLevel::DebugNotify: + case FileSys::FSMessageLevel::DebugNotify: DPrintf(DMSG_NOTIFY, "%s", text.GetChars()); break; } @@ -373,8 +371,8 @@ void InitFileSystem(TArray& groups) } i--; } - fileSystem.SetIwadNum(1); - fileSystem.SetMaxIwadNum((int)Files.size() - 1); + fileSystem.SetBaseNum(1); + fileSystem.SetMaxBaseNum((int)Files.size() - 1); if (!Args->CheckParm("-noautoload")) { @@ -428,7 +426,7 @@ void InitFileSystem(TArray& groups) todelete.Append(g.FileInfo.tobedeleted); } todelete.Append(userConfig.toBeDeleted); - LumpFilterInfo lfi; + FileSys::FileSystemFilterInfo lfi; lfi.reservedFolders = { "textures/", "hires/", "sounds/", "music/", "maps/" }; for (auto p = iwad_reserved(); *p; p++) lfi.requiredPrefixes.push_back(*p); #if 0 @@ -446,14 +444,14 @@ void InitFileSystem(TArray& groups) { DeleteStuff(fileSystem, todelete, groups.Size()); }; - fileSystem.InitMultipleFiles(Files, &lfi, FileSystemPrintf); + fileSystem.Initialize(Files, &lfi, FileSystemPrintf); if (Args->CheckParm("-dumpfs")) { FILE* f = fopen("filesystem.dir", "wb"); - for (int num = 0; num < fileSystem.GetNumEntries(); num++) + for (int num = 0; num < fileSystem.GetFileCount(); num++) { auto fd = fileSystem.FileLength(num); - fprintf(f, "%.50s %60s %td\n", fileSystem.GetFileFullName(num), fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(num)), fd); + fprintf(f, "%.50s %60s %td\n", fileSystem.GetFileName(num), fileSystem.GetContainerFullName(fileSystem.GetFileContainer(num)), fd); } fclose(f); } diff --git a/source/core/mapinfo.cpp b/source/core/mapinfo.cpp index 3978c91ca15..8376a56ee9f 100644 --- a/source/core/mapinfo.cpp +++ b/source/core/mapinfo.cpp @@ -63,7 +63,7 @@ CCMD(listmaps) if (lump >= 0) { int rfnum = fileSystem.GetFileContainer(lump); - Printf("%s - %s (%s)\n", map->LabelName(), map->DisplayName(), fileSystem.GetResourceFileName(rfnum)); + Printf("%s - %s (%s)\n", map->LabelName(), map->DisplayName(), fileSystem.GetContainerName(rfnum)); } else { @@ -260,7 +260,7 @@ MapRecord* SetupUserMap(const char* boardfilename, const char *defaultmusic) map->SetFileName(boardfilename); map->flags = MI_USERMAP|MI_FORCEEOG; int lookup = LookupMusic(boardfilename, true); - if (lookup >= 0) map->music = fileSystem.GetFileFullName(lookup); + if (lookup >= 0) map->music = fileSystem.GetFileName(lookup); else map->music = defaultmusic; return map; } diff --git a/source/core/menu/usermap.cpp b/source/core/menu/usermap.cpp index 72873fab3e6..2ff9a4edf15 100644 --- a/source/core/menu/usermap.cpp +++ b/source/core/menu/usermap.cpp @@ -53,7 +53,7 @@ static FUsermapDirectory root; void InsertMap(int lumpnum) { - FString filename = fileSystem.GetFileFullName(lumpnum); + FString filename = fileSystem.GetFileName(lumpnum); auto path = filename.Split("/"); auto current = &root; @@ -69,8 +69,8 @@ void InsertMap(int lumpnum) } current->entries.Reserve(1); current->entries.Last().displayname = path.Last(); - current->entries.Last().filename = fileSystem.GetFileFullName(lumpnum); - current->entries.Last().container = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(lumpnum)); + current->entries.Last().filename = fileSystem.GetFileName(lumpnum); + current->entries.Last().container = fileSystem.GetContainerName(fileSystem.GetFileContainer(lumpnum)); current->entries.Last().size = (int)fileSystem.FileLength(lumpnum); auto mapinfo = FindMapByName(StripExtension(path.Last().GetChars()).GetChars()); if (mapinfo) current->entries.Last().info = mapinfo->name; @@ -78,7 +78,7 @@ void InsertMap(int lumpnum) bool ValidateMap(int lumpnum) { - FString filename = fileSystem.GetFileFullName(lumpnum); + FString filename = fileSystem.GetFileName(lumpnum); if (fileSystem.FindFile(filename.GetChars()) != lumpnum) return false; auto fr = fileSystem.OpenFileReader(lumpnum); @@ -126,11 +126,11 @@ void ReadUserMaps() if (didit) return; didit = true; - int numfiles = fileSystem.GetNumEntries(); + int numfiles = fileSystem.GetFileCount(); for (int i = 0; i < numfiles; i++) { - auto fn1 = fileSystem.GetFileFullName(i); + auto fn1 = fileSystem.GetFileName(i); if (!fn1 || !*fn1) continue; FString lowfn = fn1; if (lowfn.Right(4).CompareNoCase(".map")) continue; diff --git a/source/core/music/s_advsound.cpp b/source/core/music/s_advsound.cpp index 124049cba0c..7f35d8b3fbd 100644 --- a/source/core/music/s_advsound.cpp +++ b/source/core/music/s_advsound.cpp @@ -162,7 +162,7 @@ static FSoundID S_AddSound(const char* logicalname, int lumpnum, FScanner* sc) FSoundID S_AddSound(const char* logicalname, const char* lumpname, FScanner* sc) { int lump = S_LookupSound(lumpname); - if (lump == -1 && sc && fileSystem.GetFileContainer(sc->LumpNum) > fileSystem.GetMaxIwadNum()) + if (lump == -1 && sc && fileSystem.GetFileContainer(sc->LumpNum) > fileSystem.GetMaxBaseNum()) sc->ScriptMessage("%s: sound file not found", sc->String); return S_AddSound(logicalname, lump, sc); } diff --git a/source/core/r_data/gldefs.cpp b/source/core/r_data/gldefs.cpp index 28bda4e4c30..5eff7d40744 100644 --- a/source/core/r_data/gldefs.cpp +++ b/source/core/r_data/gldefs.cpp @@ -136,7 +136,7 @@ static void ParseVavoomSkybox() sc.MustGetStringName("map"); sc.MustGetString(); - maplump = fileSystem.CheckNumForFullName(sc.String, true); + maplump = fileSystem.CheckNumForAnyName(sc.String); auto tex = TexMan.FindGameTexture(sc.String, ETextureType::Wall, FTextureManager::TEXMAN_TryAny); if (tex == NULL) @@ -1888,7 +1888,7 @@ class GLDefsParser { sc.MustGetString(); // This is not using sc.Open because it can print a more useful error message when done here - lump = fileSystem.CheckNumForFullName(sc.String, true); + lump = fileSystem.CheckNumForAnyName(sc.String); if (lump==-1) sc.ScriptError("Lump '%s' not found", sc.String); diff --git a/source/core/raze_music.cpp b/source/core/raze_music.cpp index 3647952c8ab..014f454532a 100644 --- a/source/core/raze_music.cpp +++ b/source/core/raze_music.cpp @@ -104,7 +104,7 @@ int LookupMusic(const char* fn, bool onlyextended) int l = fileSystem.FindFileWithExtensions(name.GetChars(), knownMusicExts, countof(knownMusicExts)); if (l >= 0 || onlyextended) return l; } - return fileSystem.CheckNumForFullName(fn, true, FileSys::ns_music); + return fileSystem.CheckNumForAnyName(fn, ns_music); } //========================================================================== @@ -123,7 +123,7 @@ int FindMusic(const char* musicname) if (lumpnum >= 0) { // EDuke also looks in a subfolder named after the main game resource. Do this as well if extended lookup is active. - auto rfn = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(lumpnum)); + auto rfn = fileSystem.GetContainerName(fileSystem.GetFileContainer(lumpnum)); auto rfbase = ExtractFileBase(rfn); FStringf aliasMusicname("music/%s/%s", rfbase.GetChars(), musicname); int newlumpnum = LookupMusic(aliasMusicname.GetChars()); diff --git a/source/core/raze_sound.h b/source/core/raze_sound.h index bccf5a0e8fe..15fa06979e4 100644 --- a/source/core/raze_sound.h +++ b/source/core/raze_sound.h @@ -42,7 +42,7 @@ class RazeSoundEngine : public SoundEngine RazeSoundEngine() { // add the empty sound right now. - AddSoundLump("no_sound", fileSystem.CheckNumForFullName("engine/dsempty.lmp"), 0); + AddSoundLump("no_sound", fileSystem.FindFile("engine/dsempty.lmp"), 0); } virtual bool SourceIsActor(FSoundChan* chan) { return chan->SourceType == SOURCE_Actor; } virtual int SoundSourceIndex(FSoundChan* chan) { return 0; } diff --git a/source/core/savegamehelp.cpp b/source/core/savegamehelp.cpp index a05952a6a32..7f7f7ac5384 100644 --- a/source/core/savegamehelp.cpp +++ b/source/core/savegamehelp.cpp @@ -205,7 +205,7 @@ bool WriteSavegame(const char* filename, const char *name) savegameinfo.AddString("Software", buf) ("Save Version", savesig.currentsavever) .AddString("Engine", savesig.savesig) - .AddString("Game Resource", fileSystem.GetResourceFileName(1)) + .AddString("Game Resource", fileSystem.GetContainerName(1)) .AddString("Map Name", lev->DisplayName()) .AddString("Creation Time", myasctime()) .AddString("Title", name) @@ -219,7 +219,7 @@ bool WriteSavegame(const char* filename, const char *name) { auto fileno = fileSystem.FindFile(fn); auto mapfile = fileSystem.GetFileContainer(fileno); - auto mapcname = fileSystem.GetResourceFileName(mapfile); + auto mapcname = fileSystem.GetContainerName(mapfile); if (mapcname) savegameinfo.AddString("Map Resource", mapcname); else { @@ -285,7 +285,7 @@ static bool CheckSingleFile (const char *name, bool &printRequires, bool printwa { return FileExists(name + 7); // User maps must be present to be validated. } - if (fileSystem.CheckIfResourceFileLoaded(name) < 0) + if (fileSystem.CheckIfContainerLoaded(name) < 0) { if (printwarn) { @@ -389,7 +389,7 @@ int G_ValidateSavegame(FileReader &fr, FString *savetitle, bool formenu) } else { - auto ggfn = ExtractFileBase(fileSystem.GetResourceFileName(1), true); + auto ggfn = ExtractFileBase(fileSystem.GetContainerName(1), true); if (gamegrp.CompareNoCase(ggfn) == 0) { return G_CheckSaveGameWads(gamegrp.GetChars(), mapgrp.GetChars(), false) ? 1 : -2; diff --git a/source/core/statistics.cpp b/source/core/statistics.cpp index 7e46caf015d..6970d63c398 100644 --- a/source/core/statistics.cpp +++ b/source/core/statistics.cpp @@ -433,7 +433,7 @@ void STAT_Update(bool endofgame) if (lump >= 0) { int file = fileSystem.GetFileContainer(lump); - fn = fileSystem.GetResourceFileName(file); + fn = fileSystem.GetContainerName(file); } FString section = ExtractFileBase(fn) + "." + ExtractFileBase(LevelData[0].Levelname.GetChars()); diff --git a/source/games/blood/src/barf.cpp b/source/games/blood/src/barf.cpp index 2e166231f62..4cea717854b 100644 --- a/source/games/blood/src/barf.cpp +++ b/source/games/blood/src/barf.cpp @@ -954,7 +954,7 @@ void addMemoryResource(const char* filePath, int flags, int ID) void ReadAllRFS() { bool found = false; - auto numf = fileSystem.GetNumEntries(); + auto numf = fileSystem.GetFileCount(); for (int i = 0; i < numf; i++) { auto rl = fileSystem.GetResourceType(i); diff --git a/source/games/blood/src/levels.cpp b/source/games/blood/src/levels.cpp index 44f7c4b1de2..2c80d7c41ef 100644 --- a/source/games/blood/src/levels.cpp +++ b/source/games/blood/src/levels.cpp @@ -93,16 +93,16 @@ static const char* DefFile(void) int found = -1; if (userConfig.DefaultCon.IsEmpty() || userConfig.DefaultCon.CompareNoCase("blood.ini") == 0) { - int numlumps = fileSystem.GetNumEntries(); + int numlumps = fileSystem.GetFileCount(); for (int i = numlumps - 1; i >= 0; i--) { int fileno = fileSystem.GetFileContainer(i); - if (fileno != -1 && fileno <= fileSystem.GetMaxIwadNum()) continue; - FString fn = fileSystem.GetFileFullName(i, false); + if (fileno != -1 && fileno <= fileSystem.GetMaxBaseNum()) continue; + FString fn = fileSystem.GetFileName(i); FString ext = fn.Right(4); if (ext.CompareNoCase(".ini") == 0) { - if (fileSystem.CheckNumForFullName(fn.GetChars()) != i) continue; + if (fileSystem.FindFile(fn.GetChars()) != i) continue; if (found == -1) { IniFile inif(fn.GetChars()); @@ -124,7 +124,7 @@ static const char* DefFile(void) } } } - if (found >= 0) return fileSystem.GetFileFullName(found); + if (found >= 0) return fileSystem.GetFileName(found); // The command line parser stores this in the CON field. return userConfig.DefaultCon.IsNotEmpty() ? userConfig.DefaultCon.GetChars() : "blood.ini"; } diff --git a/source/games/blood/src/qav.h b/source/games/blood/src/qav.h index a251fce42d8..512e8f6046b 100644 --- a/source/games/blood/src/qav.h +++ b/source/games/blood/src/qav.h @@ -241,7 +241,7 @@ void qavProcessTimer(DBloodPlayer* const pPlayer, QAV* const pQAV, int* duration inline bool qavIsOriginal(const int res_id) { auto const lump = fileSystem.FindResource(res_id, "QAV"); - return lump >= 0 && fileSystem.GetFileContainer(lump) < fileSystem.GetMaxIwadNum(); + return lump >= 0 && fileSystem.GetFileContainer(lump) < fileSystem.GetMaxBaseNum(); } inline int qavGetCorrectID(const int res_id) diff --git a/source/games/blood/src/sound.cpp b/source/games/blood/src/sound.cpp index dee1448aa2d..04cca35dd2b 100644 --- a/source/games/blood/src/sound.cpp +++ b/source/games/blood/src/sound.cpp @@ -132,7 +132,7 @@ void GameInterface::StartSoundEngine() void sndInit(void) { soundEngine->AddSoundLump("", 0, 0, -1, 6); // add a dummy entry at index #0 - for (int i = fileSystem.GetNumEntries() - 1; i >= 0; i--) + for (int i = fileSystem.GetFileCount() - 1; i >= 0; i--) { auto type = fileSystem.GetResourceType(i); if (!stricmp(type, "SFX")) @@ -141,8 +141,8 @@ void sndInit(void) } else if (!stricmp(type, "WAV") || !stricmp(type, "OGG") || !stricmp(type, "FLAC") || !stricmp(type, "VOC")) { - if (fileSystem.GetFileNamespace(i) != FileSys::ns_music) - soundEngine->AddSoundLump(fileSystem.GetFileFullName(i), i, 0, fileSystem.GetResourceId(i) | 0x40000000, 6); // mark the resource ID as special. + if (fileSystem.GetFileNamespace(i) != ns_music) + soundEngine->AddSoundLump(fileSystem.GetFileName(i), i, 0, fileSystem.GetResourceId(i) | 0x40000000, 6); // mark the resource ID as special. } } soundEngine->HashSounds(); diff --git a/source/games/duke/src/gamedef.cpp b/source/games/duke/src/gamedef.cpp index 5a258a299d2..c0bcc3bcf29 100644 --- a/source/games/duke/src/gamedef.cpp +++ b/source/games/duke/src/gamedef.cpp @@ -252,7 +252,7 @@ enum void ConCompiler::ReportError(int error) { - const char* fn = fileSystem.GetFileFullName(currentsourcefile); + const char* fn = fileSystem.GetFileName(currentsourcefile); switch (error) { case ERROR_ISAKEYWORD: @@ -642,7 +642,7 @@ int ConCompiler::transword(void) textptr += l; - const char* fn = fileSystem.GetFileFullName(currentsourcefile); + const char* fn = fileSystem.GetFileName(currentsourcefile); if (parsebuf[0] == '{' && parsebuf[1] != 0) Printf(TEXTCOLOR_RED " * ERROR!(%s, line %d) Expecting a SPACE or CR between '{' and '%s'.\n", fn, line_number, parsebuf + 1); else if (parsebuf[0] == '}' && parsebuf[1] != 0) @@ -713,7 +713,7 @@ int ConCompiler::transnum(int type) textptr += l; auto el = translatelabeltype(type); auto gl = translatelabeltype(labels[i].type); - const char* fn = fileSystem.GetFileFullName(currentsourcefile); + const char* fn = fileSystem.GetFileName(currentsourcefile); Printf(TEXTCOLOR_YELLOW " * WARNING.(%s, line %d) %s: Expected a '%s' label but found a '%s' label instead.\n", fn, line_number, labels[i].GetChars(), el.GetChars(), gl.GetChars()); return -1; // valid label name, but wrong type } @@ -748,7 +748,7 @@ int ConCompiler::transnum(int type) if (type != LABEL_DEFINE && value != 0) { - const char* fn = fileSystem.GetFileFullName(currentsourcefile); + const char* fn = fileSystem.GetFileName(currentsourcefile); Printf(TEXTCOLOR_YELLOW " * WARNING.(%s, line %d) Expected an identifier, got a numeric literal %d.\n", fn, line_number, (int)value); } @@ -822,7 +822,7 @@ int ConCompiler::CountCaseStatements() int ConCompiler::parsecommand() { - const char* fn = fileSystem.GetFileFullName(currentsourcefile); + const char* fn = fileSystem.GetFileName(currentsourcefile); int i, j, k; int tempscrptr; uint8_t done, temp_ifelse_check;// , tw; @@ -3293,7 +3293,7 @@ void loadcons() // This cannot be done from an RMAPINFO definition because the conditions are too specific and must not override custom maps. int num = fileSystem.FindFile("e1l7.map"); int file = fileSystem.GetFileContainer(num); - if (file <= fileSystem.GetMaxIwadNum()) + if (file <= fileSystem.GetMaxBaseNum()) { auto maprec = FindMapByName("e1l7"); if (maprec) maprec->NextMap = "e1l5"; diff --git a/source/games/duke/src/sounds.cpp b/source/games/duke/src/sounds.cpp index 3229f4ab6dd..8a55ea9051f 100644 --- a/source/games/duke/src/sounds.cpp +++ b/source/games/duke/src/sounds.cpp @@ -740,7 +740,7 @@ void S_WorldTourMappingsForOldSounds() for(unsigned i = 1; i < maxsnd; i++) { auto sfx = soundEngine->GetSfx(FSoundID::fromInt(i)); - FString fname = fileSystem.GetFileFullName(sfx->lumpnum); + FString fname = fileSystem.GetFileName(sfx->lumpnum); if (!fname.Right(4).CompareNoCase(".ogg")) { // All names here follow the same convention. We must strip the "sound/" folder and replace the extension to get the original VOCs. diff --git a/source/launcher/launcherwindow.cpp b/source/launcher/launcherwindow.cpp index 1cf8335eadd..860d1a109f5 100644 --- a/source/launcher/launcherwindow.cpp +++ b/source/launcher/launcherwindow.cpp @@ -11,22 +11,24 @@ #include #include -int LauncherWindow::ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags, FString& extraArgs) +int LauncherWindow::ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags, FString * extraArgs) { Size screenSize = GetScreenSize(); double windowWidth = 615.0; double windowHeight = 700.0; - auto launcher = std::make_unique(wads, numwads, defaultiwad, autoloadflags, extraArgs); + auto launcher = std::make_unique(wads, numwads, defaultiwad, autoloadflags); launcher->SetFrameGeometry((screenSize.width - windowWidth) * 0.5, (screenSize.height - windowHeight) * 0.5, windowWidth, windowHeight); launcher->Show(); DisplayWindow::RunLoop(); + if(extraArgs) *extraArgs = launcher->PlayGame->GetExtraArgs(); + return launcher->ExecResult; } -LauncherWindow::LauncherWindow(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags, FString& extraArgs) : Widget(nullptr, WidgetType::Window) +LauncherWindow::LauncherWindow(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags) : Widget(nullptr, WidgetType::Window) { SetWindowBackground(Colorf::fromRgba8(51, 51, 51)); SetWindowBorderColor(Colorf::fromRgba8(51, 51, 51)); @@ -54,12 +56,6 @@ void LauncherWindow::Start() { Settings->Save(); - std::string extraargs = PlayGame->GetExtraArgs(); - if (!extraargs.empty()) - { - // To do: restart the process like the cocoa backend is doing? - } - ExecResult = PlayGame->GetSelectedGame(); DisplayWindow::ExitLoop(); } diff --git a/source/launcher/launcherwindow.h b/source/launcher/launcherwindow.h index c64676a467e..8e7c8bbe678 100644 --- a/source/launcher/launcherwindow.h +++ b/source/launcher/launcherwindow.h @@ -14,9 +14,9 @@ struct WadStuff; class LauncherWindow : public Widget { public: - static int ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags, FString& extraArgs); + static int ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags, FString * extraArgs = nullptr); - LauncherWindow(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags, FString& extraArgs); + LauncherWindow(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags); void UpdateLanguage(); void Start(); diff --git a/source/launcher/playgamepage.cpp b/source/launcher/playgamepage.cpp index 972e48d26d4..46bd16a92c0 100644 --- a/source/launcher/playgamepage.cpp +++ b/source/launcher/playgamepage.cpp @@ -85,7 +85,6 @@ void PlayGamePage::OnGeometryChanged() y = GetHeight() - 10.0; -#if 0 // NYI: Additional Parameters double editHeight = 24.0; y -= editHeight; ParametersEdit->SetFrameGeometry(0.0, y, GetWidth(), editHeight); @@ -95,7 +94,6 @@ void PlayGamePage::OnGeometryChanged() y -= labelHeight; ParametersLabel->SetFrameGeometry(0.0, y, GetWidth(), labelHeight); y -= 10.0; -#endif double listViewBottom = y - 10.0; GamesList->SetFrameGeometry(0.0, listViewTop, GetWidth(), std::max(listViewBottom - listViewTop, 0.0)); diff --git a/source/launcher/settingspage.cpp b/source/launcher/settingspage.cpp index 6ddc7667992..feebeaacfaf 100644 --- a/source/launcher/settingspage.cpp +++ b/source/launcher/settingspage.cpp @@ -97,7 +97,7 @@ SettingsPage::SettingsPage(LauncherWindow* launcher, int* autoloadflags) : Widge } } } - catch (const std::exception& ex) + catch (const std::exception& ) { hideLanguage = true; } diff --git a/source/launcher/settingspage.h b/source/launcher/settingspage.h index 5c075319421..a65f4f164f0 100644 --- a/source/launcher/settingspage.h +++ b/source/launcher/settingspage.h @@ -1,6 +1,7 @@ #pragma once #include +#include "gstrings.h" #define RENDER_BACKENDS diff --git a/wadsrc/static/zscript/games/blood/ui/screens.zs b/wadsrc/static/zscript/games/blood/ui/screens.zs index d3c22dea7d9..37aa12c5de9 100644 --- a/wadsrc/static/zscript/games/blood/ui/screens.zs +++ b/wadsrc/static/zscript/games/blood/ui/screens.zs @@ -296,7 +296,7 @@ class BloodCutscenes ui if (!userConfig.nologo) { Array soundinfo; - if (Wads.CheckNumForFullName("logo.smk") != -1) + if (Wads.FindFile("logo.smk") != -1) { String s = "logo.wav"; // sound name must be converted at run-time, not compile time! runner.Append(MoviePlayerJob.CreateWithSound("logo.smk", s, MoviePlayer.FIXEDVIEWPORT)); @@ -305,7 +305,7 @@ class BloodCutscenes ui { runner.Append(new("BloodIntroImage").Init("MonolithScreen", ScreenJob.fadein|ScreenJob.fadeout)); } - if (Wads.CheckNumForFullName("gti.smk") != -1) + if (Wads.FindFile("gti.smk") != -1) { String s = "gt.wav"; runner.Append(MoviePlayerJob.CreateWithSound("gti.smk", s, MoviePlayer.FIXEDVIEWPORT)); diff --git a/wadsrc/static/zscript/games/exhumed/ui/screens.zs b/wadsrc/static/zscript/games/exhumed/ui/screens.zs index de24a16601c..701f801784b 100644 --- a/wadsrc/static/zscript/games/exhumed/ui/screens.zs +++ b/wadsrc/static/zscript/games/exhumed/ui/screens.zs @@ -717,7 +717,7 @@ class ExCredits : ScreenJob { Super.Init(); String text; - int lump = Wads.CheckNumForFullName("credits.txt"); + int lump = Wads.FindFile("credits.txt"); if (lump > -1) text = Wads.ReadLump(lump); text.Substitute("\r", ""); text.Split(credits, "\n\n"); diff --git a/wadsrc/static/zscript/games/usermapmenu.zs b/wadsrc/static/zscript/games/usermapmenu.zs index 17ee2a9799b..0f684c0f802 100644 --- a/wadsrc/static/zscript/games/usermapmenu.zs +++ b/wadsrc/static/zscript/games/usermapmenu.zs @@ -168,7 +168,7 @@ class UsermapMenu : ListMenu { numparent = (currentDir.parent != null); numdirs = currentDir.GetNumDirectories(); - numentries = currentDir.GetNumEntries(); + numentries = currentDir.GetFileCount(); NumTotalEntries = numparent + numdirs + numentries; }