From cf19d75242d318d03ea175c80fc62e7559c60aa7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Aug 2023 16:57:37 +0200 Subject: [PATCH] - backend update from GZDoom without adapting other code. --- source/CMakeLists.txt | 34 +- source/common/2d/v_2ddrawer.cpp | 2 +- source/common/audio/music/i_music.cpp | 6 +- source/common/audio/music/i_soundfont.cpp | 24 +- source/common/audio/music/music.cpp | 1 + source/common/audio/sound/s_sound.cpp | 19 +- source/common/audio/sound/s_soundinternal.h | 2 +- source/common/console/c_enginecmds.cpp | 5 +- source/common/cutscenes/movieplayer.cpp | 5 +- source/common/engine/m_joy.h | 2 +- source/common/engine/sc_man.cpp | 4 +- source/common/engine/sc_man.h | 5 + source/common/engine/serializer.cpp | 3 +- source/common/engine/stringtable.cpp | 12 +- source/common/engine/stringtable.h | 9 +- source/common/filesystem/ancientzip.cpp | 2 +- source/common/filesystem/ancientzip.h | 7 - source/common/filesystem/file_7z.cpp | 74 +- source/common/filesystem/file_directory.cpp | 127 ++-- source/common/filesystem/file_grp.cpp | 12 +- source/common/filesystem/file_lump.cpp | 18 +- source/common/filesystem/file_pak.cpp | 19 +- source/common/filesystem/file_rff.cpp | 15 +- source/common/filesystem/file_ssi.cpp | 9 +- source/common/filesystem/file_wad.cpp | 84 +-- source/common/filesystem/file_whres.cpp | 65 +- source/common/filesystem/file_zip.cpp | 195 +++--- source/common/filesystem/file_zip.h | 4 +- source/common/filesystem/filesystem.cpp | 142 ++-- source/common/filesystem/filesystem.h | 21 +- source/common/filesystem/resourcefile.cpp | 184 +++-- source/common/filesystem/resourcefile.h | 65 +- source/common/filesystem/w_zip.h | 15 +- source/common/fonts/singlelumpfont.cpp | 1 + source/common/menu/savegamemanager.cpp | 4 +- source/common/models/models_md2.cpp | 1 + source/common/models/models_md3.cpp | 1 + .../common/platform/posix/cocoa/i_system.mm | 11 - source/common/platform/posix/sdl/i_system.cpp | 17 - source/common/platform/win32/i_input.h | 2 +- source/common/platform/win32/i_system.cpp | 19 - source/common/platform/win32/i_system.h | 2 - .../rendering/hwrenderer/data/hw_vrmodes.cpp | 12 +- .../postprocessing/hw_postprocessshader.h | 3 + source/common/rendering/i_modelvertexbuffer.h | 1 + .../vulkan/textures/vk_hwtexture.cpp | 2 +- source/common/scripting/core/symbols.h | 10 + .../common/scripting/interface/vmnatives.cpp | 2 +- source/common/textures/animlib.cpp | 2 +- source/common/textures/animlib.h | 2 +- source/common/textures/formats/anmtexture.cpp | 2 +- source/common/textures/formats/ddstexture.cpp | 1 + .../common/textures/formats/jpegtexture.cpp | 1 + .../common/textures/formats/patchtexture.cpp | 5 +- source/common/textures/formats/pcxtexture.cpp | 13 +- source/common/textures/formats/pngtexture.cpp | 1 + .../textures/formats/rawpagetexture.cpp | 3 +- source/common/textures/formats/tgatexture.cpp | 1 + source/common/textures/gametexture.cpp | 4 +- source/common/textures/image.cpp | 2 + .../textures/multipatchtexturebuilder.cpp | 1 + source/common/textures/texturemanager.cpp | 39 +- source/common/textures/texturemanager.h | 9 + source/common/textures/textures.h | 9 + source/common/thirdparty/richpresence.cpp | 1 + source/common/utility/basics.h | 56 -- source/common/utility/cmdlib.cpp | 85 +-- source/common/utility/cmdlib.h | 8 - source/common/utility/engineerrors.h | 4 +- source/common/utility/files.cpp | 489 ------------- source/common/utility/files.h | 377 ---------- source/common/utility/files_decompress.cpp | 654 ------------------ source/common/utility/findfile.cpp | 232 +------ source/common/utility/findfile.h | 85 --- source/common/utility/palette.cpp | 1 + source/common/utility/utf8.cpp | 14 + source/common/utility/utf8.h | 7 + source/common/utility/vectors.h | 45 +- source/common/utility/zstring.cpp | 13 - source/common/utility/zstring.h | 5 +- 80 files changed, 743 insertions(+), 2707 deletions(-) delete mode 100644 source/common/utility/files.cpp delete mode 100644 source/common/utility/files.h delete mode 100644 source/common/utility/files_decompress.cpp diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 01cc510c3..ace4e05f4 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1108,8 +1108,6 @@ set (PCH_SOURCES common/utility/m_alloc.cpp common/utility/utf8.cpp common/utility/palette.cpp - common/utility/files.cpp - common/utility/files_decompress.cpp common/utility/memarena.cpp common/utility/cmdlib.cpp common/utility/configfile.cpp @@ -1126,19 +1124,6 @@ set (PCH_SOURCES common/thirdparty/libsmackerdec/src/HuffmanVLC.cpp common/thirdparty/libsmackerdec/src/LogError.cpp common/thirdparty/libsmackerdec/src/SmackerDecoder.cpp - common/filesystem/filesystem.cpp - common/filesystem/ancientzip.cpp - common/filesystem/file_7z.cpp - common/filesystem/file_grp.cpp - common/filesystem/file_lump.cpp - common/filesystem/file_rff.cpp - common/filesystem/file_wad.cpp - common/filesystem/file_zip.cpp - common/filesystem/file_pak.cpp - common/filesystem/file_whres.cpp - common/filesystem/file_ssi.cpp - common/filesystem/file_directory.cpp - common/filesystem/resourcefile.cpp common/engine/cycler.cpp common/engine/d_event.cpp common/engine/date.cpp @@ -1201,6 +1186,7 @@ set (PCH_SOURCES common/rendering/gl/gl_samplers.cpp common/rendering/gl/gl_shader.cpp common/rendering/gl/gl_shaderprogram.cpp + common/scripting/core/maps.cpp common/scripting/core/dictionary.cpp common/scripting/core/dynarrays.cpp common/scripting/core/symbols.cpp @@ -1285,6 +1271,24 @@ add_executable( ${PROJECT_NAME} WIN32 MACOSX_BUNDLE common/thirdparty/math/tan.c common/thirdparty/math/tanh.c common/thirdparty/math/fastsin.cpp + + common/filesystem/filesystem.cpp + common/filesystem/ancientzip.cpp + common/filesystem/file_7z.cpp + common/filesystem/file_grp.cpp + common/filesystem/file_lump.cpp + common/filesystem/file_rff.cpp + common/filesystem/file_wad.cpp + common/filesystem/file_zip.cpp + common/filesystem/file_pak.cpp + common/filesystem/file_whres.cpp + common/filesystem/file_ssi.cpp + common/filesystem/file_directory.cpp + common/filesystem/resourcefile.cpp + common/filesystem/files.cpp + common/filesystem/files_decompress.cpp + common/filesystem/fs_findfile.cpp + ) #set_source_files_properties( ${FASTMATH_SOURCES} PROPERTIES COMPILE_FLAGS ${DEM_FASTMATH_FLAG} ) diff --git a/source/common/2d/v_2ddrawer.cpp b/source/common/2d/v_2ddrawer.cpp index 4de396962..d6cf06af0 100644 --- a/source/common/2d/v_2ddrawer.cpp +++ b/source/common/2d/v_2ddrawer.cpp @@ -68,7 +68,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, Clear, Shape2DTransform_Clear) static void Shape2DTransform_Rotate(DShape2DTransform* self, double angle) { - self->transform = DMatrix3x3::Rotate2D(DEG2RAD(angle)) * self->transform; + self->transform = DMatrix3x3::Rotate2D(angle) * self->transform; } DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, Rotate, Shape2DTransform_Rotate) diff --git a/source/common/audio/music/i_music.cpp b/source/common/audio/music/i_music.cpp index 6b8580724..fd9395970 100644 --- a/source/common/audio/music/i_music.cpp +++ b/source/common/audio/music/i_music.cpp @@ -182,8 +182,8 @@ static void SetupGenMidi() auto data = fileSystem.OpenFileReader(lump); auto genmidi = data.Read(); - if (genmidi.Size() < 8 + 175 * 36 || memcmp(genmidi.Data(), "#OPL_II#", 8)) return; - ZMusic_SetGenMidi(genmidi.Data()+8); + if (genmidi.size() < 8 + 175 * 36 || memcmp(genmidi.data(), "#OPL_II#", 8)) return; + ZMusic_SetGenMidi(genmidi.data()+8); } static void SetupWgOpn() @@ -337,7 +337,7 @@ static ZMusic_MidiSource GetMIDISource(const char *fn) } auto data = wlump.Read(); - auto source = ZMusic_CreateMIDISource(data.Data(), data.Size(), type); + auto source = ZMusic_CreateMIDISource(data.data(), data.size(), type); if (source == nullptr) { diff --git a/source/common/audio/music/i_soundfont.cpp b/source/common/audio/music/i_soundfont.cpp index af1c5634c..da6424829 100644 --- a/source/common/audio/music/i_soundfont.cpp +++ b/source/common/audio/music/i_soundfont.cpp @@ -42,7 +42,8 @@ #include #include "resourcefile.h" #include "version.h" -#include "findfile.h" +#include "fs_findfile.h" +#include "resourcefile.h" #include "i_interface.h" #include "configfile.h" #include "printf.h" @@ -197,7 +198,7 @@ FileReader FSF2Reader::OpenFile(const char *name) FZipPatReader::FZipPatReader(const char *filename) { mAllowAbsolutePaths = true; - resf = FResourceFile::OpenResourceFile(filename, true); + resf = FResourceFile::OpenResourceFile(filename); } FZipPatReader::~FZipPatReader() @@ -391,9 +392,6 @@ void FSoundFontManager::ProcessOneFile(const FString &fn) void FSoundFontManager::CollectSoundfonts() { - findstate_t c_file; - void *file; - FConfigFile* GameConfig = sysCallbacks.GetConfig ? sysCallbacks.GetConfig() : nullptr; if (GameConfig != NULL && GameConfig->SetSection ("SoundfontSearch.Directories")) { @@ -404,25 +402,23 @@ void FSoundFontManager::CollectSoundfonts() { if (stricmp (key, "Path") == 0) { + FileList list; + FString dir; dir = NicePath(value); FixPathSeperator(dir); if (dir.IsNotEmpty()) { - if (dir.Back() != '/') dir += '/'; - FString mask = dir + '*'; - if ((file = I_FindFirst(mask, &c_file)) != ((void *)(-1))) + if (ScanDirectory(list, dir.GetChars(), "*", true)) { - do + for(auto& entry : list) { - if (!(I_FindAttr(&c_file) & FA_DIREC)) + if (!entry.isDirectory) { - FStringf name("%s%s", dir.GetChars(), I_FindName(&c_file)); - ProcessOneFile(name); + ProcessOneFile(entry.FilePath.c_str()); } - } while (I_FindNext(file, &c_file) == 0); - I_FindClose(file); + } } } } diff --git a/source/common/audio/music/music.cpp b/source/common/audio/music/music.cpp index 6101dc1cc..d9b99fc2b 100644 --- a/source/common/audio/music/music.cpp +++ b/source/common/audio/music/music.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include "i_sound.h" #include "i_music.h" diff --git a/source/common/audio/sound/s_sound.cpp b/source/common/audio/sound/s_sound.cpp index 2544d1f87..f2c44a1c1 100644 --- a/source/common/audio/sound/s_sound.cpp +++ b/source/common/audio/sound/s_sound.cpp @@ -744,32 +744,33 @@ sfxinfo_t *SoundEngine::LoadSound(sfxinfo_t *sfx) DPrintf(DMSG_NOTIFY, "Loading sound \"%s\" (%td)\n", sfx->name.GetChars(), sfx - &S_sfx[0]); auto sfxdata = ReadSound(sfx->lumpnum); - int size = sfxdata.Size(); + int size = (int)sfxdata.size(); if (size > 8) { - int32_t dmxlen = LittleLong(((int32_t *)sfxdata.Data())[1]); + auto sfxp = sfxdata.data(); + int32_t dmxlen = LittleLong(((int32_t *)sfxp)[1]); // If the sound is voc, use the custom loader. - if (strncmp ((const char *)sfxdata.Data(), "Creative Voice File", 19) == 0) + if (memcmp (sfxp, "Creative Voice File", 19) == 0) { - sfx->data = GSnd->LoadSoundVoc(sfxdata.Data(), size); + sfx->data = GSnd->LoadSoundVoc(sfxp, size); } // If the sound is raw, just load it as such. else if (sfx->bLoadRAW) { - sfx->data = GSnd->LoadSoundRaw(sfxdata.Data(), size, sfx->RawRate, 1, 8, sfx->LoopStart); + sfx->data = GSnd->LoadSoundRaw(sfxp, size, sfx->RawRate, 1, 8, sfx->LoopStart); } // Otherwise, try the sound as DMX format. - else if (((uint8_t *)sfxdata.Data())[0] == 3 && ((uint8_t *)sfxdata.Data())[1] == 0 && dmxlen <= size - 8) + else if (((uint8_t *)sfxp)[0] == 3 && ((uint8_t *)sfxp)[1] == 0 && dmxlen <= size - 8) { - int frequency = LittleShort(((uint16_t *)sfxdata.Data())[1]); + int frequency = LittleShort(((uint16_t *)sfxp)[1]); if (frequency == 0) frequency = 11025; - sfx->data = GSnd->LoadSoundRaw(sfxdata.Data()+8, dmxlen, frequency, 1, 8, sfx->LoopStart); + sfx->data = GSnd->LoadSoundRaw(sfxp+8, dmxlen, frequency, 1, 8, sfx->LoopStart); } // If that fails, let the sound system try and figure it out. else { - sfx->data = GSnd->LoadSound(sfxdata.Data(), size, sfx->LoopStart, sfx->LoopEnd); + sfx->data = GSnd->LoadSound(sfxp, size, sfx->LoopStart, sfx->LoopEnd); } } diff --git a/source/common/audio/sound/s_soundinternal.h b/source/common/audio/sound/s_soundinternal.h index dabd8e729..55ee82285 100644 --- a/source/common/audio/sound/s_soundinternal.h +++ b/source/common/audio/sound/s_soundinternal.h @@ -216,7 +216,7 @@ private: // Checks if a copy of this sound is already playing. bool CheckSingular(FSoundID sound_id); - virtual TArray ReadSound(int lumpnum) = 0; + virtual std::vector ReadSound(int lumpnum) = 0; protected: virtual bool CheckSoundLimit(sfxinfo_t* sfx, const FVector3& pos, int near_limit, float limit_range, int sourcetype, const void* actor, int channel, float attenuation); diff --git a/source/common/console/c_enginecmds.cpp b/source/common/console/c_enginecmds.cpp index 13593cb32..92b8cea53 100644 --- a/source/common/console/c_enginecmds.cpp +++ b/source/common/console/c_enginecmds.cpp @@ -50,7 +50,7 @@ #include "filesystem.h" #include "gstrings.h" #include "version.h" -#include "findfile.h" +#include "fs_findfile.h" #include "md5.h" #include "i_specialpaths.h" #include "i_system.h" @@ -176,6 +176,8 @@ UNSAFE_CCMD (crashout) #endif +// commented out because it's very poorly implemented (it should not abuse I_ChDir like this!) +#if 0 UNSAFE_CCMD (dir) { FString dir, path; @@ -248,6 +250,7 @@ UNSAFE_CCMD (dir) I_ChDir(curdir); } +#endif //========================================================================== // diff --git a/source/common/cutscenes/movieplayer.cpp b/source/common/cutscenes/movieplayer.cpp index 94a7e4c60..ac915bfb0 100644 --- a/source/common/cutscenes/movieplayer.cpp +++ b/source/common/cutscenes/movieplayer.cpp @@ -153,7 +153,7 @@ class AnmPlayer : public MoviePlayer { // This doesn't need its own class type anim_t anim; - TArray buffer; + std::vector buffer; int numframes = 0; int curframe = 1; int frametime = 0; @@ -173,7 +173,7 @@ public: buffer = fr.ReadPadded(1); fr.Close(); - if (ANIM_LoadAnim(&anim, buffer.Data(), buffer.Size() - 1) < 0) + if (ANIM_LoadAnim(&anim, buffer.data(), buffer.size() - 1) < 0) { return; } @@ -231,7 +231,6 @@ public: ~AnmPlayer() { - buffer.Reset(); animtex.Clean(); } diff --git a/source/common/engine/m_joy.h b/source/common/engine/m_joy.h index 650e32506..088d5bd6d 100644 --- a/source/common/engine/m_joy.h +++ b/source/common/engine/m_joy.h @@ -18,7 +18,7 @@ enum EJoyAxis }; // Generic configuration interface for a controller. -struct NOVTABLE IJoystickConfig +struct IJoystickConfig { virtual ~IJoystickConfig() = 0; diff --git a/source/common/engine/sc_man.cpp b/source/common/engine/sc_man.cpp index 1568f677b..98de9f0b1 100644 --- a/source/common/engine/sc_man.cpp +++ b/source/common/engine/sc_man.cpp @@ -148,9 +148,9 @@ bool FScanner::OpenFile (const char *name) if (!fr.OpenFile(name)) return false; auto filesize = fr.GetLength(); auto filebuff = fr.Read(); - if (filebuff.Size() == 0 && filesize > 0) return false; + if (filebuff.size() == 0 && filesize > 0) return false; - ScriptBuffer = FString((const char *)filebuff.Data(), filesize); + ScriptBuffer = FString((const char *)filebuff.data(), filesize); ScriptName = name; // This is used for error messages so the full file name is preferable LumpNum = -1; PrepareScript (); diff --git a/source/common/engine/sc_man.h b/source/common/engine/sc_man.h index 4d66b5f21..307831dba 100644 --- a/source/common/engine/sc_man.h +++ b/source/common/engine/sc_man.h @@ -1,6 +1,7 @@ #ifndef __SC_MAN_H__ #define __SC_MAN_H__ +#include #include "zstring.h" #include "tarray.h" #include "name.h" @@ -74,6 +75,10 @@ public: { OpenMem(name, (const char*)buffer.Data(), buffer.Size()); } + void OpenMem(const char* name, const std::vector& buffer) + { + OpenMem(name, (const char*)buffer.data(), (int)buffer.size()); + } void OpenString(const char *name, FString buffer); void OpenLumpNum(int lump); void Close(); diff --git a/source/common/engine/serializer.cpp b/source/common/engine/serializer.cpp index ec84a5fee..571a314d0 100644 --- a/source/common/engine/serializer.cpp +++ b/source/common/engine/serializer.cpp @@ -747,6 +747,7 @@ FCompressedBuffer FSerializer::GetCompressedOutput() FCompressedBuffer buff; WriteObjects(); EndObject(); + buff.filename = nullptr; buff.mSize = (unsigned)w->mOutString.GetSize(); buff.mZipFlags = 0; buff.mCRC32 = crc32(0, (const Bytef*)w->mOutString.GetString(), buff.mSize); @@ -1135,7 +1136,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe const char *name; auto lump = pic->GetSourceLump(); - if (fileSystem.GetLinkedTexture(lump) == pic) + if (TexMan.GetLinkedTexture(lump) == pic) { name = fileSystem.GetFileFullName(lump); } diff --git a/source/common/engine/stringtable.cpp b/source/common/engine/stringtable.cpp index 92819c144..97ba64d27 100644 --- a/source/common/engine/stringtable.cpp +++ b/source/common/engine/stringtable.cpp @@ -77,9 +77,9 @@ void FStringTable::LoadStrings (const char *language) //========================================================================== -TArray> FStringTable::parseCSV(const TArray &buffer) +TArray> FStringTable::parseCSV(const std::vector &buffer) { - const size_t bufLength = buffer.Size(); + const size_t bufLength = buffer.size(); TArray> data; TArray row; TArray cell; @@ -186,10 +186,10 @@ bool FStringTable::readMacros(int lumpnum) // //========================================================================== -bool FStringTable::ParseLanguageCSV(int lumpnum, const TArray &buffer) +bool FStringTable::ParseLanguageCSV(int lumpnum, const std::vector &buffer) { - if (buffer.Size() < 11) return false; - if (strnicmp((const char*)buffer.Data(), "default,", 8) && strnicmp((const char*)buffer.Data(), "identifier,", 11 )) return false; + if (buffer.size() < 11) return false; + if (strnicmp((const char*)buffer.data(), "default,", 8) && strnicmp((const char*)buffer.data(), "identifier,", 11 )) return false; auto data = parseCSV(buffer); int labelcol = -1; @@ -282,7 +282,7 @@ bool FStringTable::ParseLanguageCSV(int lumpnum, const TArray &buffer) // //========================================================================== -void FStringTable::LoadLanguage (int lumpnum, const TArray &buffer) +void FStringTable::LoadLanguage (int lumpnum, const std::vector &buffer) { bool errordone = false; TArray activeMaps; diff --git a/source/common/engine/stringtable.h b/source/common/engine/stringtable.h index d75864303..6b083ce5c 100644 --- a/source/common/engine/stringtable.h +++ b/source/common/engine/stringtable.h @@ -44,6 +44,7 @@ #include +#include #include "basics.h" #include "zstring.h" #include "tarray.h" @@ -111,11 +112,11 @@ private: LangMap allStrings; TArray> currentLanguageSet; - void LoadLanguage (int lumpnum, const TArray &buffer); - TArray> parseCSV(const TArray &buffer); - bool ParseLanguageCSV(int lumpnum, const TArray &buffer); + void LoadLanguage (int lumpnum, const std::vector &buffer); + TArray> parseCSV(const std::vector &buffer); + bool ParseLanguageCSV(int lumpnum, const std::vector &buffer); - bool LoadLanguageFromSpreadsheet(int lumpnum, const TArray &buffer); + bool LoadLanguageFromSpreadsheet(int lumpnum, const std::vector &buffer); bool readMacros(int lumpnum); void DeleteString(int langid, FName label); void DeleteForLabel(int lumpnum, FName label); diff --git a/source/common/filesystem/ancientzip.cpp b/source/common/filesystem/ancientzip.cpp index 0088d1f00..80f0c6093 100644 --- a/source/common/filesystem/ancientzip.cpp +++ b/source/common/filesystem/ancientzip.cpp @@ -310,7 +310,7 @@ int FZipExploder::Explode(unsigned char *out, unsigned int outsize, len += minMatchLen; dist++; if (bIdx + len > outsize) { - throw CExplosionError("Not enough output space"); + return -1; } if ((unsigned int)dist > bIdx) { /* Anything before the first input byte is zero. */ diff --git a/source/common/filesystem/ancientzip.h b/source/common/filesystem/ancientzip.h index 6241f775d..57b0f3584 100644 --- a/source/common/filesystem/ancientzip.h +++ b/source/common/filesystem/ancientzip.h @@ -1,6 +1,5 @@ #pragma once #include "files.h" -#include "engineerrors.h" class FZipExploder { @@ -42,10 +41,4 @@ public: int Explode(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize, int flags); }; -class CExplosionError : public CRecoverableError -{ -public: - CExplosionError(const char *message) : CRecoverableError(message) {} -}; - int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize); \ No newline at end of file diff --git a/source/common/filesystem/file_7z.cpp b/source/common/filesystem/file_7z.cpp index f207702d0..5539d5448 100644 --- a/source/common/filesystem/file_7z.cpp +++ b/source/common/filesystem/file_7z.cpp @@ -36,10 +36,8 @@ // Note that 7z made the unwise decision to include windows.h :( #include "7z.h" #include "7zCrc.h" - #include "resourcefile.h" -#include "cmdlib.h" -#include "printf.h" +#include "fs_findfile.h" @@ -169,7 +167,7 @@ struct F7ZLump : public FResourceLump { int Position; - virtual int FillCache(); + virtual int FillCache() override; }; @@ -189,7 +187,7 @@ class F7ZFile : public FResourceFile public: F7ZFile(const char * filename, FileReader &filer); - bool Open(bool quiet, LumpFilterInfo* filter); + bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); virtual ~F7ZFile(); virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } }; @@ -216,7 +214,7 @@ F7ZFile::F7ZFile(const char * filename, FileReader &filer) // //========================================================================== -bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter) +bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf) { Archive = new C7zArchive(Reader); int skipped = 0; @@ -227,25 +225,21 @@ bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter) { delete Archive; Archive = NULL; - if (!quiet) + if (res == SZ_ERROR_UNSUPPORTED) { - Printf("\n" TEXTCOLOR_RED "%s: ", FileName.GetChars()); - if (res == SZ_ERROR_UNSUPPORTED) - { - Printf("Decoder does not support this archive\n"); - } - else if (res == SZ_ERROR_MEM) - { - Printf("Cannot allocate memory\n"); - } - else if (res == SZ_ERROR_CRC) - { - Printf("CRC error\n"); - } - else - { - Printf("error #%d\n", res); - } + Printf(FSMessageLevel::Error, "%s: Decoder does not support this archive\n", FileName.c_str()); + } + else if (res == SZ_ERROR_MEM) + { + Printf(FSMessageLevel::Error, "Cannot allocate memory\n"); + } + else if (res == SZ_ERROR_CRC) + { + Printf(FSMessageLevel::Error, "CRC error\n"); + } + else + { + Printf(FSMessageLevel::Error, "error #%d\n", res); } return false; } @@ -256,8 +250,8 @@ bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter) Lumps = new F7ZLump[NumLumps]; F7ZLump *lump_p = Lumps; - TArray nameUTF16; - TArray nameASCII; + std::u16string nameUTF16; + std::string nameASCII; for (uint32_t i = 0; i < NumLumps; ++i) { @@ -276,19 +270,17 @@ bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter) continue; } - nameUTF16.Resize((unsigned)nameLength); - nameASCII.Resize((unsigned)nameLength); - SzArEx_GetFileNameUtf16(archPtr, i, &nameUTF16[0]); + nameUTF16.resize((unsigned)nameLength); + nameASCII.resize((unsigned)nameLength); + // note that the file system is not equipped to handle non-ASCII, so don't bother with proper Unicode conversion here. + SzArEx_GetFileNameUtf16(archPtr, i, (UInt16*)nameUTF16.data()); for (size_t c = 0; c < nameLength; ++c) { - nameASCII[c] = static_cast(nameUTF16[c]); + nameASCII[c] = tolower(static_cast(nameUTF16[c])); } - FixPathSeperator(&nameASCII[0]); + FixPathSeparator(&nameASCII.front()); - FString name = &nameASCII[0]; - name.ToLower(); - - lump_p->LumpNameSetup(name); + lump_p->LumpNameSetup(nameASCII.c_str()); lump_p->LumpSize = static_cast(SzArEx_GetFileSize(archPtr, i)); lump_p->Owner = this; lump_p->Flags = LUMPF_FULLPATH|LUMPF_COMPRESSED; @@ -308,7 +300,7 @@ bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter) if (SZ_OK != Archive->Extract(Lumps[0].Position, &temp[0])) { - if (!quiet) Printf("\n%s: unsupported 7z/LZMA file!\n", FileName.GetChars()); + Printf(FSMessageLevel::Error, "%s: unsupported 7z/LZMA file!\n", FileName.c_str()); return false; } } @@ -345,7 +337,11 @@ F7ZFile::~F7ZFile() int F7ZLump::FillCache() { Cache = new char[LumpSize]; - static_cast(Owner)->Archive->Extract(Position, Cache); + SRes code = static_cast(Owner)->Archive->Extract(Position, Cache); + if (code != SZ_OK) + { + throw FileSystemException("Error %d reading from 7z archive", code); + } RefCount = 1; return 1; } @@ -356,7 +352,7 @@ int F7ZLump::FillCache() // //========================================================================== -FResourceFile *Check7Z(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { char head[k7zSignatureSize]; @@ -368,7 +364,7 @@ FResourceFile *Check7Z(const char *filename, FileReader &file, bool quiet, LumpF if (!memcmp(head, k7zSignature, k7zSignatureSize)) { auto rf = new F7ZFile(filename, file); - if (rf->Open(quiet, filter)) return rf; + if (rf->Open(filter, Printf)) return rf; file = std::move(rf->Reader); // to avoid destruction of reader delete rf; diff --git a/source/common/filesystem/file_directory.cpp b/source/common/filesystem/file_directory.cpp index 80b9f6e57..882b615cf 100644 --- a/source/common/filesystem/file_directory.cpp +++ b/source/common/filesystem/file_directory.cpp @@ -37,9 +37,13 @@ #include #include "resourcefile.h" -#include "cmdlib.h" -#include "printf.h" -#include "findfile.h" +#include "fs_findfile.h" + +std::string FS_FullPath(const char* directory); + +#ifdef _WIN32 +std::wstring toWide(const char* str); +#endif //========================================================================== // @@ -52,7 +56,7 @@ struct FDirectoryLump : public FResourceLump FileReader NewReader() override; int FillCache() override; - FString mFullPath; + std::string mFullPath; }; @@ -67,12 +71,12 @@ class FDirectory : public FResourceFile TArray Lumps; const bool nosubdir; - int AddDirectory(const char *dirpath); + int AddDirectory(const char* dirpath, LumpFilterInfo* filter, FileSystemMessageFunc Printf); void AddEntry(const char *fullpath, int size); public: FDirectory(const char * dirname, bool nosubdirflag = false); - bool Open(bool quiet, LumpFilterInfo* filter); + bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } }; @@ -87,102 +91,50 @@ public: FDirectory::FDirectory(const char * directory, bool nosubdirflag) : FResourceFile(NULL), nosubdir(nosubdirflag) { - FString dirname; - - #ifdef _WIN32 - directory = _fullpath(NULL, directory, _MAX_PATH); - #else - // Todo for Linux: Resolve the path before using it - #endif - dirname = directory; -#ifdef _WIN32 - free((void *)directory); -#endif - dirname.Substitute("\\", "/"); - if (dirname[dirname.Len()-1] != '/') dirname += '/'; - FileName = dirname; + FileName = FS_FullPath(directory); + if (FileName[FileName.length()-1] != '/') FileName += '/'; } - //========================================================================== // // Windows version // //========================================================================== -int FDirectory::AddDirectory(const char *dirpath) +int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { - void * handle; int count = 0; - FString dirmatch = dirpath; - findstate_t find; - dirmatch += '*'; - - handle = I_FindFirst(dirmatch.GetChars(), &find); - if (handle == ((void *)(-1))) + FileList list; + if (!ScanDirectory(list, dirpath, "*")) { - Printf("Could not scan '%s': %s\n", dirpath, strerror(errno)); + Printf(FSMessageLevel::Error, "Could not scan '%s': %s\n", dirpath, strerror(errno)); } else { - do + for(auto& entry : list) { - // I_FindName only returns the file's name and not its full path - auto attr = I_FindAttr(&find); - if (attr & FA_HIDDEN) + if (!entry.isDirectory) { - // Skip hidden files and directories. (Prevents SVN bookkeeping - // info from being included.) - continue; - } - FString fi = I_FindName(&find); - if (attr & FA_DIREC) - { - if (nosubdir || (fi[0] == '.' && - (fi[1] == '\0' || - (fi[1] == '.' && fi[2] == '\0')))) - { - // Do not record . and .. directories. - continue; - } - FString newdir = dirpath; - newdir << fi << '/'; - count += AddDirectory(newdir); - } - else - { - if (strstr(fi, ".orig") || strstr(fi, ".bak") || strstr(fi, ".cache")) + auto fi = entry.FileName; + for (auto& c : fi) c = tolower(c); + if (strstr(fi.c_str(), ".orig") || strstr(fi.c_str(), ".bak") || strstr(fi.c_str(), ".cache")) { // We shouldn't add backup files to the file system continue; } - size_t size = 0; - FString fn = FString(dirpath) + fi; - // The next one is courtesy of EDuke32. :( - // Putting cache files in the application directory is very bad style. - // Unfortunately, having a garbage file named "texture" present will cause serious problems down the line. - if (!stricmp(fi, "textures")) + if (filter->filenamecheck == nullptr || filter->filenamecheck(fi.c_str(), entry.FilePath.c_str())) { - FILE* f = fopen(fn, "rb"); - if (f) + if (entry.Length > 0x7fffffff) { - char check[3]{}; - fread(check, 1, 3, f); - if (!memcmp(check, "LZ4", 3)) continue; + Printf(FSMessageLevel::Warning, "%s is larger than 2GB and will be ignored\n", entry.FilePath.c_str()); } - } - - if (GetFileInfo(fn, &size, nullptr)) - { - AddEntry(fn, (int)size); + AddEntry(entry.FilePathRel.c_str(), (int)entry.Length); count++; } } - - } while (I_FindNext (handle, &find) == 0); - I_FindClose (handle); + } } return count; } @@ -193,9 +145,9 @@ int FDirectory::AddDirectory(const char *dirpath) // //========================================================================== -bool FDirectory::Open(bool quiet, LumpFilterInfo* filter) +bool FDirectory::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf) { - NumLumps = AddDirectory(FileName); + NumLumps = AddDirectory(FileName.c_str(), filter, Printf); PostProcessArchive(&Lumps[0], sizeof(FDirectoryLump), filter); return true; } @@ -214,11 +166,11 @@ void FDirectory::AddEntry(const char *fullpath, int size) lump_p->mFullPath = fullpath; // [mxd] Convert name to lowercase - FString name = fullpath + strlen(FileName); - name.ToLower(); + std::string name = fullpath + FileName; + for (auto& c : name) c = tolower(c); // The lump's name is only the part relative to the main directory - lump_p->LumpNameSetup(name); + lump_p->LumpNameSetup(name.c_str()); lump_p->LumpSize = size; lump_p->Owner = this; lump_p->Flags = 0; @@ -235,7 +187,7 @@ void FDirectory::AddEntry(const char *fullpath, int size) FileReader FDirectoryLump::NewReader() { FileReader fr; - fr.OpenFile(mFullPath); + fr.OpenFile(mFullPath.c_str()); return fr; } @@ -249,12 +201,15 @@ int FDirectoryLump::FillCache() { FileReader fr; Cache = new char[LumpSize]; - if (!fr.OpenFile(mFullPath)) + if (!fr.OpenFile(mFullPath.c_str())) { - memset(Cache, 0, LumpSize); - return 0; + throw FileSystemException("unable to open file"); + } + auto read = fr.Read(Cache, LumpSize); + if (read != LumpSize) + { + throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize); } - fr.Read(Cache, LumpSize); RefCount = 1; return 1; } @@ -265,10 +220,10 @@ int FDirectoryLump::FillCache() // //========================================================================== -FResourceFile *CheckDir(const char *filename, bool quiet, bool nosubdirflag, LumpFilterInfo* filter) +FResourceFile *CheckDir(const char *filename, bool nosubdirflag, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { auto rf = new FDirectory(filename, nosubdirflag); - if (rf->Open(quiet, filter)) return rf; + if (rf->Open(filter, Printf)) return rf; delete rf; return nullptr; } diff --git a/source/common/filesystem/file_grp.cpp b/source/common/filesystem/file_grp.cpp index 7128c1307..4765bcde0 100644 --- a/source/common/filesystem/file_grp.cpp +++ b/source/common/filesystem/file_grp.cpp @@ -34,7 +34,9 @@ */ #include "resourcefile.h" -#include "printf.h" +#include "fs_swap.h" + +using namespace fs_private; //========================================================================== // @@ -72,7 +74,7 @@ class FGrpFile : public FUncompressedFile { public: FGrpFile(const char * filename, FileReader &file); - bool Open(bool quiet, LumpFilterInfo* filter); + bool Open(LumpFilterInfo* filter); }; @@ -93,7 +95,7 @@ FGrpFile::FGrpFile(const char *filename, FileReader &file) // //========================================================================== -bool FGrpFile::Open(bool quiet, LumpFilterInfo*) +bool FGrpFile::Open(LumpFilterInfo* filter) { GrpHeader header; @@ -129,7 +131,7 @@ bool FGrpFile::Open(bool quiet, LumpFilterInfo*) // //========================================================================== -FResourceFile *CheckGRP(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { char head[12]; @@ -141,7 +143,7 @@ FResourceFile *CheckGRP(const char *filename, FileReader &file, bool quiet, Lump if (!memcmp(head, "KenSilverman", 12)) { auto rf = new FGrpFile(filename, file); - if (rf->Open(quiet, filter)) return rf; + if (rf->Open(filter)) return rf; file = std::move(rf->Reader); // to avoid destruction of reader delete rf; diff --git a/source/common/filesystem/file_lump.cpp b/source/common/filesystem/file_lump.cpp index abeb9cf71..60c957081 100644 --- a/source/common/filesystem/file_lump.cpp +++ b/source/common/filesystem/file_lump.cpp @@ -33,8 +33,6 @@ */ #include "resourcefile.h" -#include "cmdlib.h" -#include "printf.h" //========================================================================== // @@ -46,7 +44,7 @@ class FLumpFile : public FUncompressedFile { public: FLumpFile(const char * filename, FileReader &file); - bool Open(bool quiet, LumpFilterInfo* filter); + bool Open(LumpFilterInfo* filter); }; @@ -67,21 +65,15 @@ FLumpFile::FLumpFile(const char *filename, FileReader &file) // //========================================================================== -bool FLumpFile::Open(bool quiet, LumpFilterInfo*) +bool FLumpFile::Open(LumpFilterInfo*) { - FString name(ExtractFileBase(FileName, true)); - Lumps.Resize(1); - Lumps[0].LumpNameSetup(name); + Lumps[0].LumpNameSetup(ExtractBaseName(FileName.c_str(), true).c_str()); Lumps[0].Owner = this; Lumps[0].Position = 0; Lumps[0].LumpSize = (int)Reader.GetLength(); Lumps[0].Flags = 0; NumLumps = 1; - if (!quiet) - { - Printf("\n"); - } return true; } @@ -91,11 +83,11 @@ bool FLumpFile::Open(bool quiet, LumpFilterInfo*) // //========================================================================== -FResourceFile *CheckLump(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *CheckLump(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { // always succeeds auto rf = new FLumpFile(filename, file); - if (rf->Open(quiet, filter)) return rf; + if (rf->Open(filter)) return rf; file = std::move(rf->Reader); // to avoid destruction of reader delete rf; return NULL; diff --git a/source/common/filesystem/file_pak.cpp b/source/common/filesystem/file_pak.cpp index 3a868766c..4003ce396 100644 --- a/source/common/filesystem/file_pak.cpp +++ b/source/common/filesystem/file_pak.cpp @@ -33,7 +33,8 @@ */ #include "resourcefile.h" -#include "printf.h" + +using namespace fs_private; //========================================================================== // @@ -44,14 +45,14 @@ struct dpackfile_t { char name[56]; - int filepos, filelen; + uint32_t filepos, filelen; } ; struct dpackheader_t { - int ident; // == IDPAKHEADER - int dirofs; - int dirlen; + uint32_t ident; // == IDPAKHEADER + uint32_t dirofs; + uint32_t dirlen; } ; @@ -65,7 +66,7 @@ class FPakFile : public FUncompressedFile { public: FPakFile(const char * filename, FileReader &file); - bool Open(bool quiet, LumpFilterInfo* filter); + bool Open(LumpFilterInfo* filter); }; @@ -88,7 +89,7 @@ FPakFile::FPakFile(const char *filename, FileReader &file) // //========================================================================== -bool FPakFile::Open(bool quiet, LumpFilterInfo* filter) +bool FPakFile::Open(LumpFilterInfo* filter) { dpackheader_t header; @@ -123,7 +124,7 @@ bool FPakFile::Open(bool quiet, LumpFilterInfo* filter) // //========================================================================== -FResourceFile *CheckPak(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { char head[4]; @@ -135,7 +136,7 @@ FResourceFile *CheckPak(const char *filename, FileReader &file, bool quiet, Lump if (!memcmp(head, "PACK", 4)) { auto rf = new FPakFile(filename, file); - if (rf->Open(quiet, filter)) return rf; + if (rf->Open(filter)) return rf; file = std::move(rf->Reader); // to avoid destruction of reader delete rf; diff --git a/source/common/filesystem/file_rff.cpp b/source/common/filesystem/file_rff.cpp index 3e512b62d..723d184e6 100644 --- a/source/common/filesystem/file_rff.cpp +++ b/source/common/filesystem/file_rff.cpp @@ -34,8 +34,9 @@ */ #include "resourcefile.h" +#include "fs_swap.h" -#include "printf.h" +using namespace fs_private; //========================================================================== // @@ -74,7 +75,7 @@ struct RFFLump struct FRFFLump : public FUncompressedLump { virtual FileReader *GetReader(); - virtual int FillCache(); + virtual int FillCache() override; uint32_t IndexNum; @@ -111,7 +112,7 @@ class FRFFFile : public FResourceFile public: FRFFFile(const char * filename, FileReader &file); virtual ~FRFFFile(); - virtual bool Open(bool quiet, LumpFilterInfo* filter); + virtual bool Open(LumpFilterInfo* filter); virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } }; @@ -134,7 +135,7 @@ FRFFFile::FRFFFile(const char *filename, FileReader &file) // //========================================================================== -bool FRFFFile::Open(bool quiet, LumpFilterInfo*) +bool FRFFFile::Open(LumpFilterInfo*) { RFFLump *lumps; RFFInfo header; @@ -219,7 +220,7 @@ int FRFFLump::FillCache() if (Flags & LUMPF_COMPRESSED) { - int cryptlen = min (LumpSize, 256); + int cryptlen = std::min (LumpSize, 256); uint8_t *data = (uint8_t *)Cache; for (int i = 0; i < cryptlen; ++i) @@ -237,7 +238,7 @@ int FRFFLump::FillCache() // //========================================================================== -FResourceFile *CheckRFF(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { char head[4]; @@ -249,7 +250,7 @@ FResourceFile *CheckRFF(const char *filename, FileReader &file, bool quiet, Lump if (!memcmp(head, "RFF\x1a", 4)) { auto rf = new FRFFFile(filename, file); - if (rf->Open(quiet, filter)) return rf; + if (rf->Open(filter)) return rf; file = std::move(rf->Reader); // to avoid destruction of reader delete rf; diff --git a/source/common/filesystem/file_ssi.cpp b/source/common/filesystem/file_ssi.cpp index 64623e805..6bf60cc1e 100644 --- a/source/common/filesystem/file_ssi.cpp +++ b/source/common/filesystem/file_ssi.cpp @@ -34,7 +34,6 @@ */ #include "resourcefile.h" -#include "printf.h" //========================================================================== // @@ -46,7 +45,7 @@ class FSSIFile : public FUncompressedFile { public: FSSIFile(const char * filename, FileReader &file); - bool Open(bool quiet, int version, int lumpcount, LumpFilterInfo* filter); + bool Open(int version, int lumpcount, LumpFilterInfo* filter); }; @@ -68,7 +67,7 @@ FSSIFile::FSSIFile(const char *filename, FileReader &file) // //========================================================================== -bool FSSIFile::Open(bool quiet, int version, int lumpcount, LumpFilterInfo*) +bool FSSIFile::Open(int version, int lumpcount, LumpFilterInfo*) { NumLumps = lumpcount*2; Lumps.Resize(lumpcount*2); @@ -115,7 +114,7 @@ bool FSSIFile::Open(bool quiet, int version, int lumpcount, LumpFilterInfo*) // //========================================================================== -FResourceFile* CheckSSI(const char* filename, FileReader& file, bool quiet, LumpFilterInfo* filter) +FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { char zerobuf[72]; char buf[72]; @@ -146,7 +145,7 @@ FResourceFile* CheckSSI(const char* filename, FileReader& file, bool quiet, Lump if (!skipstring(70)) return nullptr; } auto ssi = new FSSIFile(filename, file); - if (ssi->Open(filename, version, numfiles, filter)) return ssi; + if (ssi->Open(version, numfiles, filter)) return ssi; file = std::move(ssi->Reader); // to avoid destruction of reader delete ssi; } diff --git a/source/common/filesystem/file_wad.cpp b/source/common/filesystem/file_wad.cpp index 8af39b5f8..beab51476 100644 --- a/source/common/filesystem/file_wad.cpp +++ b/source/common/filesystem/file_wad.cpp @@ -35,9 +35,10 @@ #include #include "resourcefile.h" -#include "v_text.h" #include "filesystem.h" -#include "engineerrors.h" +#include "fs_swap.h" + +using namespace fs_private; struct wadinfo_t @@ -101,13 +102,19 @@ public: if(Compressed) { FileReader lzss; - if (lzss.OpenDecompressor(Owner->Reader, LumpSize, METHOD_LZSS, false, [](const char* err) { I_Error("%s", err); })) + if (lzss.OpenDecompressor(Owner->Reader, LumpSize, METHOD_LZSS, false, true)) { lzss.Read(Cache, LumpSize); } } else - Owner->Reader.Read(Cache, LumpSize); + { + auto read = Owner->Reader.Read(Cache, LumpSize); + if (read != LumpSize) + { + throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize); + } + } RefCount = 1; return 1; @@ -125,13 +132,13 @@ class FWadFile : public FResourceFile TArray Lumps; bool IsMarker(int lump, const char *marker); - void SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, bool flathack=false); - void SkinHack (); + 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); FResourceLump *GetLump(int lump) { return &Lumps[lump]; } - bool Open(bool quiet, LumpFilterInfo* filter); + bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); }; @@ -154,7 +161,7 @@ FWadFile::FWadFile(const char *filename, FileReader &file) // //========================================================================== -bool FWadFile::Open(bool quiet, LumpFilterInfo*) +bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf) { wadinfo_t header; uint32_t InfoTableOfs; @@ -176,7 +183,8 @@ bool FWadFile::Open(bool quiet, LumpFilterInfo*) // Check again to detect broken wads if (InfoTableOfs + NumLumps*sizeof(wadlump_t) > (unsigned)wadSize) { - I_Error("Cannot load broken WAD file %s\n", FileName.GetChars()); + Printf(FSMessageLevel::Error, "%s: Bad directory offset.\n", FileName.c_str()); + return false; } } @@ -195,10 +203,10 @@ bool FWadFile::Open(bool quiet, LumpFilterInfo*) // This requires explicit toggling for precisely the files that need it. #if 0 Lumps[i].Compressed = !(gameinfo.flags & GI_SHAREWARE) && (n[0] & 0x80) == 0x80; + n[0] &= ~0x80; #else Lumps[i].Compressed = false; #endif - n[0] &= ~0x80; Lumps[i].LumpNameSetup(n); Lumps[i].Owner = this; @@ -212,7 +220,7 @@ bool FWadFile::Open(bool quiet, LumpFilterInfo*) { if (Lumps[i].LumpSize != 0) { - Printf(PRINT_HIGH, "%s: Lump %s contains invalid positioning info and will be ignored\n", FileName.GetChars(), Lumps[i].getName()); + Printf(FSMessageLevel::Warning, "%s: Lump %s contains invalid positioning info and will be ignored\n", FileName.c_str(), Lumps[i].getName()); Lumps[i].LumpNameSetup(""); } Lumps[i].LumpSize = Lumps[i].Position = 0; @@ -221,18 +229,15 @@ bool FWadFile::Open(bool quiet, LumpFilterInfo*) GenerateHash(); // Do this before the lump processing below. - if (!quiet) // don't bother with namespaces in quiet mode. We won't need them. - { - SetNamespace("S_START", "S_END", ns_sprites); - SetNamespace("F_START", "F_END", ns_flats, true); - SetNamespace("C_START", "C_END", ns_colormaps); - SetNamespace("A_START", "A_END", ns_acslibrary); - SetNamespace("TX_START", "TX_END", ns_newtextures); - SetNamespace("V_START", "V_END", ns_strifevoices); - SetNamespace("HI_START", "HI_END", ns_hires); - SetNamespace("VX_START", "VX_END", ns_voxels); - SkinHack(); - } + 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); return true; } @@ -273,7 +278,7 @@ struct Marker unsigned int index; }; -void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, bool flathack) +void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, FileSystemMessageFunc Printf, bool flathack) { bool warned = false; int numstartmarkers = 0, numendmarkers = 0; @@ -300,7 +305,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name { if (numendmarkers == 0) return; // no markers found - Printf(TEXTCOLOR_YELLOW"WARNING: %s marker without corresponding %s found.\n", endmarker, startmarker); + Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.c_str(), endmarker, startmarker); if (flathack) @@ -314,7 +319,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name { // We can't add this to the flats namespace but // it needs to be flagged for the texture manager. - DPrintf(DMSG_NOTIFY, "Marking %s as potential flat\n", Lumps[ii].getName()); + Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName.c_str(), Lumps[ii].getName()); Lumps[ii].Flags |= LUMPF_MAYBEFLAT; } } @@ -328,7 +333,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name int start, end; if (markers[i].markertype != 0) { - Printf(TEXTCOLOR_YELLOW"WARNING: %s marker without corresponding %s found.\n", endmarker, startmarker); + Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.c_str(), endmarker, startmarker); i++; continue; } @@ -337,21 +342,21 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name // skip over subsequent x_START markers while (i < markers.Size() && markers[i].markertype == 0) { - Printf(TEXTCOLOR_YELLOW"WARNING: duplicate %s marker found.\n", startmarker); + Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName.c_str(), startmarker); i++; continue; } // same for x_END markers while (i < markers.Size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1)) { - Printf(TEXTCOLOR_YELLOW"WARNING: duplicate %s marker found.\n", endmarker); + Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName.c_str(), endmarker); i++; continue; } // We found a starting marker but no end marker. Ignore this block. if (i >= markers.Size()) { - Printf(TEXTCOLOR_YELLOW"WARNING: %s marker without corresponding %s found.\n", startmarker, endmarker); + Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.c_str(), startmarker, endmarker); end = NumLumps; } else @@ -360,14 +365,14 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name } // we found a marked block - DPrintf(DMSG_NOTIFY, "Found %s block at (%d-%d)\n", startmarker, markers[start].index, end); + Printf(FSMessageLevel::DebugNotify, "%s: Found %s block at (%d-%d)\n", FileName.c_str(), startmarker, markers[start].index, end); for(int j = markers[start].index + 1; j < end; j++) { if (Lumps[j].Namespace != ns_global) { if (!warned) { - Printf(TEXTCOLOR_YELLOW"WARNING: Overlapping namespaces found (lump %d)\n", j); + Printf(FSMessageLevel::Warning, "%s: Overlapping namespaces found (lump %d)\n", FileName.c_str(), j); } warned = true; } @@ -377,7 +382,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name // ignore sprite lumps smaller than 8 bytes (the smallest possible) // in size -- this was used by some dmadds wads // as an 'empty' graphics resource - DPrintf(DMSG_WARNING, " Skipped empty sprite %s (lump %d)\n", Lumps[j].getName(), j); + Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName.c_str(), Lumps[j].getName(), j); } else { @@ -401,7 +406,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name // //========================================================================== -void FWadFile::SkinHack () +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; @@ -447,11 +452,8 @@ void FWadFile::SkinHack () } if (skinned && hasmap) { - Printf (TEXTCOLOR_BLUE - "The maps in %s will not be loaded because it has a skin.\n" - TEXTCOLOR_BLUE - "You should remove the skin from the wad to play these maps.\n", - FileName.GetChars()); + Printf(FSMessageLevel::Attention, "%s: The maps will not be loaded because it has a skin.\n", FileName.c_str()); + Printf(FSMessageLevel::Attention, "You should remove the skin from the wad to play these maps.\n"); } } @@ -462,7 +464,7 @@ void FWadFile::SkinHack () // //========================================================================== -FResourceFile *CheckWad(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { char head[4]; @@ -474,7 +476,7 @@ FResourceFile *CheckWad(const char *filename, FileReader &file, bool quiet, Lump if (!memcmp(head, "IWAD", 4) || !memcmp(head, "PWAD", 4)) { auto rf = new FWadFile(filename, file); - if (rf->Open(quiet, filter)) return rf; + if (rf->Open(filter, Printf)) return rf; file = std::move(rf->Reader); // to avoid destruction of reader delete rf; diff --git a/source/common/filesystem/file_whres.cpp b/source/common/filesystem/file_whres.cpp index 969aaafab..d7149f116 100644 --- a/source/common/filesystem/file_whres.cpp +++ b/source/common/filesystem/file_whres.cpp @@ -35,55 +35,35 @@ */ #include "resourcefile.h" -#include "printf.h" -#include "cmdlib.h" +#include "fs_swap.h" + +using namespace fs_private; //========================================================================== // -// -// -//========================================================================== - -struct whresentry -{ - int filepospage, filelen, priority; -} ; - -struct dpackheader_t -{ - int ident; // == IDPAKHEADER - int dirofs; - int dirlen; -} ; - - -//========================================================================== -// -// Wad file +// WH resource file // //========================================================================== class FWHResFile : public FUncompressedFile { - FString basename; + std::string basename; public: FWHResFile(const char * filename, FileReader &file); - bool Open(bool quiet, LumpFilterInfo* filter); + bool Open(LumpFilterInfo* filter); }; //========================================================================== // -// FWadFile::FWadFile // -// Initializes a WAD file // //========================================================================== FWHResFile::FWHResFile(const char *filename, FileReader &file) : FUncompressedFile(filename, file) { - basename = ExtractFileBase(filename, false); + basename = ExtractBaseName(filename, false); } //========================================================================== @@ -92,9 +72,9 @@ FWHResFile::FWHResFile(const char *filename, FileReader &file) // //========================================================================== -bool FWHResFile::Open(bool quiet, LumpFilterInfo*) +bool FWHResFile::Open(LumpFilterInfo*) { - int directory[1024]; + uint32_t directory[1024]; Reader.Seek(-4096, FileReader::SeekEnd); Reader.Read(directory, 4096); @@ -106,11 +86,13 @@ bool FWHResFile::Open(bool quiet, LumpFilterInfo*) int i = 0; for(int k = 0; k < nl; k++) { - int offset = LittleLong(directory[k*3]) * 4096; - int length = LittleLong(directory[k*3+1]); - if (length <= 0) break; - FStringf synthname("%s/%04d", basename.GetChars(), k); - Lumps[i].LumpNameSetup(synthname); + uint32_t offset = LittleLong(directory[k*3]) * 4096; + uint32_t length = LittleLong(directory[k*3+1]); + if (length == 0) break; + char num[5]; + snprintf(num, 5, "/%04d", k); + std::string synthname = basename + num; + Lumps[i].LumpNameSetup(synthname.c_str()); Lumps[i].Owner = this; Lumps[i].Position = offset; Lumps[i].LumpSize = length; @@ -129,27 +111,28 @@ bool FWHResFile::Open(bool quiet, LumpFilterInfo*) // //========================================================================== -FResourceFile *CheckWHRes(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *CheckWHRes(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { if (file.GetLength() >= 8192) // needs to be at least 8192 to contain one file and the directory. { - int directory[1024]; + unsigned directory[1024]; int nl =1024/3; file.Seek(-4096, FileReader::SeekEnd); file.Read(directory, 4096); + auto size = file.GetLength(); - int checkpos = 0; + uint32_t checkpos = 0; for(int k = 0; k < nl; k++) { - int offset = LittleLong(directory[k*3]); - int length = LittleLong(directory[k*3+1]); + unsigned offset = LittleLong(directory[k*3]); + unsigned length = LittleLong(directory[k*3+1]); if (length <= 0 && offset == 0) break; - if (offset != checkpos || length <= 0) return nullptr; + if (offset != checkpos || length == 0 || offset + length >= (size_t)size - 4096 ) return nullptr; checkpos += (length+4095) / 4096; } auto rf = new FWHResFile(filename, file); - if (rf->Open(quiet, filter)) return rf; + if (rf->Open(filter)) return rf; file = std::move(rf->Reader); // to avoid destruction of reader delete rf; } diff --git a/source/common/filesystem/file_zip.cpp b/source/common/filesystem/file_zip.cpp index e14305b52..4237e0f8a 100644 --- a/source/common/filesystem/file_zip.cpp +++ b/source/common/filesystem/file_zip.cpp @@ -34,13 +34,14 @@ */ #include +#include #include "file_zip.h" -#include "cmdlib.h" - -#include "printf.h" #include "w_zip.h" - #include "ancientzip.h" +#include "fs_findfile.h" +#include "fs_swap.h" + +using namespace fs_private; #define BUFREADCOMMENT (0x400) @@ -50,52 +51,48 @@ // //========================================================================== -static bool UncompressZipLump(char *Cache, FileReader &Reader, int Method, int LumpSize, int CompressedSize, int GPFlags) +static bool UncompressZipLump(char *Cache, FileReader &Reader, int Method, int LumpSize, int CompressedSize, int GPFlags, bool exceptions) { - try + switch (Method) { - switch (Method) - { - case METHOD_STORED: - { - Reader.Read(Cache, LumpSize); - break; - } - - case METHOD_DEFLATE: - case METHOD_BZIP2: - case METHOD_LZMA: - { - FileReader frz; - if (frz.OpenDecompressor(Reader, LumpSize, Method, false, [](const char* err) { I_Error("%s", err); })) - { - frz.Read(Cache, LumpSize); - } - break; - } - - // Fixme: These should also use a stream - case METHOD_IMPLODE: - { - FZipExploder exploder; - exploder.Explode((unsigned char *)Cache, LumpSize, Reader, CompressedSize, GPFlags); - break; - } - - case METHOD_SHRINK: - { - ShrinkLoop((unsigned char *)Cache, LumpSize, Reader, CompressedSize); - break; - } - - default: - assert(0); - return false; - } + case METHOD_STORED: + { + Reader.Read(Cache, LumpSize); + break; } - catch (CRecoverableError &err) + + case METHOD_DEFLATE: + case METHOD_BZIP2: + case METHOD_LZMA: { - Printf("%s\n", err.GetMessage()); + FileReader frz; + if (frz.OpenDecompressor(Reader, LumpSize, Method, false, exceptions)) + { + frz.Read(Cache, LumpSize); + } + break; + } + + // Fixme: These should also use a stream + case METHOD_IMPLODE: + { + FZipExploder exploder; + if (exploder.Explode((unsigned char*)Cache, LumpSize, Reader, CompressedSize, GPFlags) == -1) + { + // decompression failed so zero the cache. + memset(Cache, 0, LumpSize); + } + break; + } + + case METHOD_SHRINK: + { + ShrinkLoop((unsigned char *)Cache, LumpSize, Reader, CompressedSize); + break; + } + + default: + assert(0); return false; } return true; @@ -105,7 +102,7 @@ bool FCompressedBuffer::Decompress(char *destbuffer) { FileReader mr; mr.OpenMemory(mBuffer, mCompressedSize); - return UncompressZipLump(destbuffer, mr, mMethod, mSize, mCompressedSize, mZipFlags); + return UncompressZipLump(destbuffer, mr, mMethod, mSize, mCompressedSize, mZipFlags, false); } //----------------------------------------------------------------------- @@ -124,7 +121,7 @@ static uint32_t Zip_FindCentralDir(FileReader &fin, bool* zip64) uint32_t uPosFound=0; FileSize = (uint32_t)fin.GetLength(); - uMaxBack = min(0xffff, FileSize); + uMaxBack = std::min(0xffff, FileSize); uBackRead = 4; while (uBackRead < uMaxBack) @@ -137,7 +134,7 @@ static uint32_t Zip_FindCentralDir(FileReader &fin, bool* zip64) uBackRead += BUFREADCOMMENT; uReadPos = FileSize - uBackRead; - uReadSize = min((BUFREADCOMMENT + 4), (FileSize - uReadPos)); + uReadSize = std::min((BUFREADCOMMENT + 4), (FileSize - uReadPos)); if (fin.Seek(uReadPos, FileReader::SeekSet) != 0) break; @@ -173,7 +170,7 @@ FZipFile::FZipFile(const char * filename, FileReader &file) Lumps = NULL; } -bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) +bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf) { bool zip64 = false; uint32_t centraldir = Zip_FindCentralDir(Reader, &zip64); @@ -183,7 +180,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) if (centraldir == 0) { - if (!quiet) Printf(TEXTCOLOR_RED "\n%s: ZIP file corrupt!\n", FileName.GetChars()); + Printf(FSMessageLevel::Error, "%s: ZIP file corrupt!\n", FileName.c_str()); return false; } @@ -199,7 +196,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) if (info.NumEntries != info.NumEntriesOnAllDisks || info.FirstDisk != 0 || info.DiskNumber != 0) { - if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", FileName.GetChars()); + Printf(FSMessageLevel::Error, "%s: Multipart Zip files are not supported.\n", FileName.c_str()); return false; } @@ -218,7 +215,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) if (info.NumEntries != info.NumEntriesOnAllDisks || info.FirstDisk != 0 || info.DiskNumber != 0) { - if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", FileName.GetChars()); + Printf(FSMessageLevel::Error, "%s: Multipart Zip files are not supported.\n", FileName.c_str()); return false; } @@ -236,7 +233,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) char *dirptr = (char*)directory; FZipLump *lump_p = Lumps; - FString name0, name1; + std::string name0, name1; bool foundspeciallump = false; bool foundprefix = false; @@ -247,7 +244,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr; int len = LittleShort(zip_fh->NameLength); - FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len); + std::string name(dirptr + sizeof(FZipCentralDirectoryInfo), len); dirptr += sizeof(FZipCentralDirectoryInfo) + LittleShort(zip_fh->NameLength) + @@ -257,38 +254,40 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file. { free(directory); - if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", FileName.GetChars()); + Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName.c_str()); return false; } - name.ToLower(); - if (name.IndexOf("filter/") == 0) + for (auto& c : name) c = tolower(c); + + if (name.find_first_of("filter/") == 0) continue; // 'filter' is a reserved name of the file system. - if (name.IndexOf("__macosx") == 0) + if (name.find_first_of("__macosx") == 0) continue; // skip Apple garbage. At this stage only the root folder matters. - if (name.IndexOf(".bat") >= 0 || name.IndexOf(".exe") >= 0) + if (name.find_first_of(".bat") != std::string::npos || name.find_first_of(".exe") != std::string::npos) continue; // also ignore executables for this. if (!foundprefix) { // check for special names, if one of these gets found this must be treated as a normal zip. - bool isspecial = name.IndexOf("/") < 0 || (filter && filter->reservedFolders.Find(name) < filter->reservedFolders.Size()); + bool isspecial = name.find_first_of("/") == std::string::npos || + (filter && std::find(filter->reservedFolders.begin(), filter->reservedFolders.end(), name) != filter->reservedFolders.end()); if (isspecial) break; - name0 = name.Left(name.LastIndexOf("/")+1); - name1 = name.Left(name.IndexOf("/") + 1); + name0 = std::string(name, 0, name.find_last_of("/")+1); + name1 = std::string(name, 0, name.find_first_of("/") + 1); foundprefix = true; } - if (name.IndexOf(name0) != 0) + if (name.find_first_of(name0) != 0) { - if (name1.IsNotEmpty()) + if (!name1.empty()) { name0 = name1; - if (name.IndexOf(name0) != 0) + if (name.find_first_of(name0) != 0) { name0 = ""; } } - if (name0.IsEmpty()) + if (name0.empty()) break; } if (!foundspeciallump && filter) @@ -296,7 +295,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) // at least one of the more common definition lumps must be present. for (auto &p : filter->requiredPrefixes) { - if (name.IndexOf(name0 + p) == 0 || name.LastIndexOf(p) == ptrdiff_t(name.Len() - strlen(p))) + if (name.find_first_of(name0 + p) == 0 || name.find_last_of(p) == ptrdiff_t(name.length() - p.length())) { foundspeciallump = true; break; @@ -314,7 +313,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr; int len = LittleShort(zip_fh->NameLength); - FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len); + std::string name(dirptr + sizeof(FZipCentralDirectoryInfo), len); dirptr += sizeof(FZipCentralDirectoryInfo) + LittleShort(zip_fh->NameLength) + LittleShort(zip_fh->ExtraLength) + @@ -323,19 +322,19 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file. { free(directory); - if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", FileName.GetChars()); + Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName.c_str()); return false; } - if (name.IndexOf("__macosx") == 0 || name.IndexOf("__MACOSX") == 0) + if (name.find_first_of("__macosx") == 0 || name.find_first_of("__MACOSX") == 0) { skipped++; continue; // Weed out Apple's resource fork garbage right here because it interferes with safe operation. } - if (name0.IsNotEmpty()) name = name.Mid(name0.Len()); + if (!name0.empty()) name = std::string(name, name0.length()); // skip Directories - if (name.IsEmpty() || (name.Back() == '/' && LittleLong(zip_fh->UncompressedSize32) == 0)) + if (name.empty() || (name.back() == '/' && LittleLong(zip_fh->UncompressedSize32) == 0)) { skipped++; continue; @@ -350,7 +349,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) zip_fh->Method != METHOD_IMPLODE && zip_fh->Method != METHOD_SHRINK) { - if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' uses an unsupported compression algorithm (#%d).\n", FileName.GetChars(), name.GetChars(), zip_fh->Method); + Printf(FSMessageLevel::Error, "%s: '%s' uses an unsupported compression algorithm (#%d).\n", FileName.c_str(), name.c_str(), zip_fh->Method); skipped++; continue; } @@ -358,14 +357,14 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) zip_fh->Flags = LittleShort(zip_fh->Flags); if (zip_fh->Flags & ZF_ENCRYPTED) { - if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' is encrypted. Encryption is not supported.\n", FileName.GetChars(), name.GetChars()); + Printf(FSMessageLevel::Error, "%s: '%s' is encrypted. Encryption is not supported.\n", FileName.c_str(), name.c_str()); skipped++; continue; } - FixPathSeperator(name); - name.ToLower(); - + FixPathSeparator(&name.front()); + for (auto& c : name) c = tolower(c); + uint32_t UncompressedSize =LittleLong(zip_fh->UncompressedSize32); uint32_t CompressedSize = LittleLong(zip_fh->CompressedSize32); uint64_t LocalHeaderOffset = LittleLong(zip_fh->LocalHeaderOffset32); @@ -385,7 +384,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) if (zip_64->CompressedSize > 0x7fffffff || zip_64->UncompressedSize > 0x7fffffff) { // The file system is limited to 32 bit file sizes; - if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' is too large.\n", FileName.GetChars(), name.GetChars()); + Printf(FSMessageLevel::Warning, "%s: '%s' is too large.\n", FileName.c_str(), name.c_str()); skipped++; continue; } @@ -396,7 +395,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) } } - lump_p->LumpNameSetup(name); + lump_p->LumpNameSetup(name.c_str()); lump_p->LumpSize = UncompressedSize; lump_p->Owner = this; // The start of the Reader will be determined the first time it is accessed. @@ -508,7 +507,7 @@ int FZipLump::FillCache() Owner->Reader.Seek(Position, FileReader::SeekSet); Cache = new char[LumpSize]; - UncompressZipLump(Cache, Owner->Reader, Method, LumpSize, CompressedSize, GPFlags); + UncompressZipLump(Cache, Owner->Reader, Method, LumpSize, CompressedSize, GPFlags, true); RefCount = 1; return 1; } @@ -532,7 +531,7 @@ int FZipLump::GetFileOffset() // //========================================================================== -FResourceFile *CheckZip(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter) +FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { char head[4]; @@ -544,7 +543,7 @@ FResourceFile *CheckZip(const char *filename, FileReader &file, bool quiet, Lump if (!memcmp(head, "PK\x3\x4", 4)) { auto rf = new FZipFile(filename, file); - if (rf->Open(quiet, filter)) return rf; + if (rf->Open(filter, Printf)) return rf; file = std::move(rf->Reader); // to avoid destruction of reader delete rf; @@ -590,7 +589,7 @@ static std::pair time_to_dos(struct tm *time) // //========================================================================== -int AppendToZip(FileWriter *zip_file, const char *filename, FCompressedBuffer &content, std::pair &dostime) +static int AppendToZip(FileWriter *zip_file, const FCompressedBuffer &content, std::pair &dostime) { FZipLocalFileHeader local; int position; @@ -605,7 +604,7 @@ int AppendToZip(FileWriter *zip_file, const char *filename, FCompressedBuffer &c local.CRC32 = content.mCRC32; local.UncompressedSize = LittleLong(content.mSize); local.CompressedSize = LittleLong(content.mCompressedSize); - local.NameLength = LittleShort((unsigned short)strlen(filename)); + local.NameLength = LittleShort((unsigned short)strlen(content.filename)); local.ExtraLength = 0; // Fill in local directory header. @@ -614,7 +613,7 @@ int AppendToZip(FileWriter *zip_file, const char *filename, FCompressedBuffer &c // Write out the header, file name, and file data. if (zip_file->Write(&local, sizeof(local)) != sizeof(local) || - zip_file->Write(filename, strlen(filename)) != strlen(filename) || + zip_file->Write(content.filename, strlen(content.filename)) != strlen(content.filename) || zip_file->Write(content.mBuffer, content.mCompressedSize) != content.mCompressedSize) { return -1; @@ -631,7 +630,7 @@ int AppendToZip(FileWriter *zip_file, const char *filename, FCompressedBuffer &c // //========================================================================== -int AppendCentralDirectory(FileWriter *zip_file, const char *filename, FCompressedBuffer &content, std::pair &dostime, int position) +int AppendCentralDirectory(FileWriter *zip_file, const FCompressedBuffer &content, std::pair &dostime, int position) { FZipCentralDirectoryInfo dir; @@ -647,23 +646,23 @@ int AppendCentralDirectory(FileWriter *zip_file, const char *filename, FCompress dir.CRC32 = content.mCRC32; dir.CompressedSize32 = LittleLong(content.mCompressedSize); dir.UncompressedSize32 = LittleLong(content.mSize); - dir.NameLength = LittleShort((unsigned short)strlen(filename)); + dir.NameLength = LittleShort((unsigned short)strlen(content.filename)); dir.ExtraLength = 0; dir.CommentLength = 0; dir.StartingDiskNumber = 0; dir.InternalAttributes = 0; dir.ExternalAttributes = 0; - dir.LocalHeaderOffset32 = LittleLong(position); + dir.LocalHeaderOffset32 = LittleLong((unsigned)position); if (zip_file->Write(&dir, sizeof(dir)) != sizeof(dir) || - zip_file->Write(filename, strlen(filename)) != strlen(filename)) + zip_file->Write(content.filename, strlen(content.filename)) != strlen(content.filename)) { return -1; } return 0; } -bool WriteZip(const char *filename, TArray &filenames, TArray &content) +bool WriteZip(const char* filename, const FCompressedBuffer* content, size_t contentcount) { // try to determine local time struct tm *ltime; @@ -674,14 +673,12 @@ bool WriteZip(const char *filename, TArray &filenames, TArray positions; - if (filenames.Size() != content.Size()) return false; - auto f = FileWriter::Open(filename); if (f != nullptr) { - for (unsigned i = 0; i < filenames.Size(); i++) + for (size_t i = 0; i < contentcount; i++) { - int pos = AppendToZip(f, filenames[i], content[i], dostime); + int pos = AppendToZip(f, content[i], dostime); if (pos == -1) { delete f; @@ -692,9 +689,9 @@ bool WriteZip(const char *filename, TArray &filenames, TArrayTell(); - for (unsigned i = 0; i < filenames.Size(); i++) + for (size_t i = 0; i < contentcount; i++) { - if (AppendCentralDirectory(f, filenames[i], content[i], dostime, positions[i]) < 0) + if (AppendCentralDirectory(f, content[i], dostime, positions[i]) < 0) { delete f; remove(filename); @@ -707,8 +704,8 @@ bool WriteZip(const char *filename, TArray &filenames, TArrayTell() - dirofs)); dirend.ZipCommentLength = 0; if (f->Write(&dirend, sizeof(dirend)) != sizeof(dirend)) diff --git a/source/common/filesystem/file_zip.h b/source/common/filesystem/file_zip.h index c6a42d9a4..028731f28 100644 --- a/source/common/filesystem/file_zip.h +++ b/source/common/filesystem/file_zip.h @@ -19,7 +19,7 @@ struct FZipLump : public FResourceLump unsigned CRC32; virtual FileReader *GetReader(); - virtual int FillCache(); + virtual int FillCache() override; private: void SetLumpAddress(); @@ -41,7 +41,7 @@ class FZipFile : public FResourceFile public: FZipFile(const char * filename, FileReader &file); virtual ~FZipFile(); - bool Open(bool quiet, LumpFilterInfo* filter); + bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } }; diff --git a/source/common/filesystem/filesystem.cpp b/source/common/filesystem/filesystem.cpp index 6b60e8e68..c86d5b145 100644 --- a/source/common/filesystem/filesystem.cpp +++ b/source/common/filesystem/filesystem.cpp @@ -55,7 +55,6 @@ struct FileSystem::LumpRecord { FResourceLump *lump; - FGameTexture* linkedTexture; LumpShortName shortName; FString longName; int rfnum; @@ -67,7 +66,6 @@ struct FileSystem::LumpRecord { lump = lmp; rfnum = filenum; - linkedTexture = nullptr; flags = 0; if (lump->Flags & LUMPF_SHORTNAME) @@ -152,7 +150,7 @@ struct FileSystem::LumpRecord // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- -static void PrintLastError (); +static void PrintLastError (FileSystemMessageFunc Printf); // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -162,7 +160,7 @@ FileSystem fileSystem; FileSystem::FileSystem() { - // This is needed to initialize the LumpRecord array, which depends on data only available here. + // Cannot be defaulted! This is needed to initialize the LumpRecord array, which depends on data only available here. } FileSystem::~FileSystem () @@ -199,14 +197,14 @@ void FileSystem::DeleteAll () // //========================================================================== -void FileSystem::InitSingleFile(const char* filename, bool quiet) +bool FileSystem::InitSingleFile(const char* filename, FileSystemMessageFunc Printf) { TArray filenames; filenames.Push(filename); - InitMultipleFiles(filenames, true); + return InitMultipleFiles(filenames, nullptr, Printf); } -void FileSystem::InitMultipleFiles (TArray &filenames, bool quiet, LumpFilterInfo* filter, bool allowduplicates, FILE* hashfile) +bool FileSystem::InitMultipleFiles (TArray &filenames, LumpFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates, FILE* hashfile) { int numfiles; @@ -232,23 +230,23 @@ void FileSystem::InitMultipleFiles (TArray &filenames, bool quiet, Lump for(unsigned i=0;iGetHash().GetChars()); + FStringf path("filter/%s", Files.Last()->GetHash()); MoveLumpsInFolder(path); } NumEntries = FileInfo.Size(); if (NumEntries == 0) { - if (!quiet) I_FatalError("W_InitMultipleFiles: no files found"); - else return; + return false; } if (filter && filter->postprocessFunc) filter->postprocessFunc(); // [RH] Set up hash table InitHashChains (); + return true; } //========================================================================== @@ -308,7 +306,7 @@ int FileSystem::AddFromBuffer(const char* name, const char* type, char* data, in // [RH] Removed reload hack //========================================================================== -void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, LumpFilterInfo* filter, FILE* hashfile) +void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInfo* filter, FileSystemMessageFunc Printf, FILE* hashfile) { int startlump; bool isdir = false; @@ -319,10 +317,10 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L // Does this exist? If so, is it a directory? if (!DirEntryExists(filename, &isdir)) { - if (!quiet) + if (Printf) { - Printf(TEXTCOLOR_RED "%s: File or Directory not found\n", filename); - PrintLastError(); + Printf(FSMessageLevel::Error, "%s: File or Directory not found\n", filename); + PrintLastError(Printf); } return; } @@ -331,10 +329,10 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L { if (!filereader.OpenFile(filename)) { // Didn't find file - if (!quiet) + if (Printf) { - Printf(TEXTCOLOR_RED "%s: File not found\n", filename); - PrintLastError(); + Printf(FSMessageLevel::Error, "%s: File not found\n", filename); + PrintLastError(Printf); } return; } @@ -342,19 +340,20 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L } else filereader = std::move(*filer); - if (!batchrun && !quiet) Printf (" adding %s", filename); startlump = NumEntries; FResourceFile *resfile; + if (!isdir) - resfile = FResourceFile::OpenResourceFile(filename, filereader, quiet, false, filter); + resfile = FResourceFile::OpenResourceFile(filename, filereader, false, filter, Printf); else - resfile = FResourceFile::OpenDirectory(filename, quiet, filter); + resfile = FResourceFile::OpenDirectory(filename, filter, Printf); if (resfile != NULL) { - if (!quiet && !batchrun) Printf(", %d lumps\n", resfile->LumpCount()); + if (!batchrun && Printf) + Printf(FSMessageLevel::Message, "adding %s, %d lumps\n", filename, resfile->LumpCount()); uint32_t lumpstart = FileInfo.Size(); @@ -376,11 +375,11 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L FString path; path.Format("%s:%s", filename, lump->getName()); auto embedded = lump->NewReader(); - AddFile(path, &embedded, quiet, filter, hashfile); + AddFile(path, &embedded, filter, Printf, hashfile); } } - if (hashfile && !quiet) + if (hashfile) { uint8_t cksum[16]; char cksumout[33]; @@ -568,7 +567,7 @@ int FileSystem::GetNumForName (const char *name, int space) i = CheckNumForName (name, space); if (i == -1) - I_Error ("GetNumForName: %s not found!", name); + throw FileSystemException("GetNumForName: %s not found!", name); return i; } @@ -652,7 +651,7 @@ int FileSystem::GetNumForFullName (const char *name) i = CheckNumForFullName (name); if (i == -1) - I_Error ("GetNumForFullName: %s not found!", name); + throw FileSystemException("GetNumForFullName: %s not found!", name); return i; } @@ -742,40 +741,11 @@ int FileSystem::GetResource (int resid, const char *type, int filenum) const if (i == -1) { - I_Error("GetResource: %d of type %s not found!", resid, type); + throw FileSystemException("GetResource: %d of type %s not found!", resid, type); } return i; } -//========================================================================== -// -// link a texture with a given lump -// -//========================================================================== - -void FileSystem::SetLinkedTexture(int lump, FGameTexture *tex) -{ - if ((size_t)lump < NumEntries) - { - FileInfo[lump].linkedTexture = tex; - } -} - -//========================================================================== -// -// retrieve linked texture -// -//========================================================================== - -FGameTexture *FileSystem::GetLinkedTexture(int lump) -{ - if ((size_t)lump < NumEntries) - { - return FileInfo[lump].linkedTexture; - } - return NULL; -} - //========================================================================== // // FileLength @@ -921,19 +891,19 @@ void FileSystem::InitHashChains (void) LumpShortName& FileSystem::GetShortName(int i) { - if ((unsigned)i >= NumEntries) I_Error("GetShortName: Invalid index"); + if ((unsigned)i >= NumEntries) throw FileSystemException("GetShortName: Invalid index"); return FileInfo[i].shortName; } FString& FileSystem::GetLongName(int i) { - if ((unsigned)i >= NumEntries) I_Error("GetLongName: Invalid index"); + if ((unsigned)i >= NumEntries) throw FileSystemException("GetLongName: Invalid index"); return FileInfo[i].longName; } void FileSystem::RenameFile(int num, const char* newfn) { - if ((unsigned)num >= NumEntries) I_Error("RenameFile: Invalid index"); + if ((unsigned)num >= NumEntries) throw FileSystemException("RenameFile: Invalid index"); FileInfo[num].longName = newfn; // This does not alter the short name - call GetShortname to do that! } @@ -1332,19 +1302,21 @@ unsigned FileSystem::GetFilesInFolder(const char *inpath, TArray &r // //========================================================================== -TArray FileSystem::GetFileData(int lump, int pad) +std::vector FileSystem::GetFileData(int lump, int pad) { + std::vector data; + if ((size_t)lump >= FileInfo.Size()) - return TArray(); + return data; auto lumpr = OpenFileReader(lump); auto size = lumpr.GetLength(); - TArray data(size + pad, true); - auto numread = lumpr.Read(data.Data(), size); + data.resize(size + pad); + auto numread = lumpr.Read(data.data(), size); if (numread != size) { - I_Error("GetFileData: only read %ld of %ld on lump %i\n", + throw FileSystemException("GetFileData: only read %ld of %ld on lump %i\n", numread, size, lump); } if (pad > 0) memset(&data[size], 0, pad); @@ -1366,8 +1338,8 @@ void FileSystem::ReadFile (int lump, void *dest) if (numread != size) { - I_Error ("W_ReadFile: only read %ld of %ld on lump %i\n", - numread, size, lump); + throw FileSystemException("W_ReadFile: only read %ld of %ld on '%s'\n", + numread, size, GetLongName(lump).GetChars()); } } @@ -1398,7 +1370,7 @@ FileReader FileSystem::OpenFileReader(int lump) { if ((unsigned)lump >= (unsigned)FileInfo.Size()) { - I_Error("OpenFileReader: %u >= NumEntries", lump); + throw FileSystemException("OpenFileReader: %u >= NumEntries", lump); } auto rl = FileInfo[lump].lump; @@ -1417,7 +1389,7 @@ FileReader FileSystem::ReopenFileReader(int lump, bool alwayscache) { if ((unsigned)lump >= (unsigned)FileInfo.Size()) { - I_Error("ReopenFileReader: %u >= NumEntries", lump); + throw FileSystemException("ReopenFileReader: %u >= NumEntries", lump); } auto rl = FileInfo[lump].lump; @@ -1479,9 +1451,9 @@ const char *FileSystem::GetResourceFileName (int rfnum) const noexcept return NULL; } - name = Files[rfnum]->FileName; + name = Files[rfnum]->FileName.c_str(); slash = strrchr (name, '/'); - return (slash != NULL && slash[1] != 0) ? slash+1 : name; + return (slash != nullptr && slash[1] != 0) ? slash+1 : name; } //========================================================================== @@ -1545,7 +1517,7 @@ const char *FileSystem::GetResourceFileFullName (int rfnum) const noexcept return nullptr; } - return Files[rfnum]->FileName; + return Files[rfnum]->FileName.c_str(); } @@ -1618,7 +1590,7 @@ FString::FString (ELumpNum lumpnum) if (numread != size) { - I_Error ("ConstructStringFromLump: Only read %ld of %ld bytes on lump %i (%s)\n", + throw FileSystemException("ConstructStringFromLump: Only read %ld of %ld bytes on lump %i (%s)\n", numread, size, lumpnum, fileSystem.GetFileFullName((int)lumpnum)); } } @@ -1647,7 +1619,7 @@ __declspec(dllimport) void * __stdcall LocalFree (void *); __declspec(dllimport) unsigned long __stdcall GetLastError (); } -static void PrintLastError () +static void PrintLastError (FileSystemMessageFunc Printf) { char *lpMsgBuf; FormatMessageA(0x1300 /*FORMAT_MESSAGE_ALLOCATE_BUFFER | @@ -1660,14 +1632,14 @@ static void PrintLastError () 0, NULL ); - Printf (TEXTCOLOR_RED " %s\n", lpMsgBuf); + Printf (FSMessageLevel::Error, " %s\n", lpMsgBuf); // Free the buffer. LocalFree( lpMsgBuf ); } #else -static void PrintLastError () +static void PrintLastError (FileSystemMessageFunc Printf) { - Printf (TEXTCOLOR_RED " %s\n", strerror(errno)); + Printf(FSMessageLevel::Error, " %s\n", strerror(errno)); } #endif @@ -1681,21 +1653,3 @@ FResourceLump* FileSystem::GetFileAt(int no) { return FileInfo[no].lump; } - -#include "c_dispatch.h" - -CCMD(fs_dir) -{ - int numfiles = fileSystem.GetNumEntries(); - - for (int i = 0; i < numfiles; i++) - { - auto container = fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(i)); - auto fn1 = fileSystem.GetFileFullName(i); - auto fns = fileSystem.GetFileShortName(i); - auto fnid = fileSystem.GetResourceId(i); - auto length = fileSystem.FileLength(i); - bool hidden = fileSystem.FindFile(fn1) != i; - Printf(PRINT_HIGH | PRINT_NONOTIFY, "%s%-64s %-15s (%5d) %10d %s %s\n", hidden ? TEXTCOLOR_RED : TEXTCOLOR_UNTRANSLATED, fn1, fns, fnid, length, container, hidden ? "(h)" : ""); - } -} diff --git a/source/common/filesystem/filesystem.h b/source/common/filesystem/filesystem.h index 2dc80f7ff..da1bd95bb 100644 --- a/source/common/filesystem/filesystem.h +++ b/source/common/filesystem/filesystem.h @@ -16,7 +16,6 @@ class FResourceFile; struct FResourceLump; -class FGameTexture; union LumpShortName { @@ -57,7 +56,7 @@ struct FolderEntry class FileSystem { public: - FileSystem (); + FileSystem(); ~FileSystem (); // The wadnum for the IWAD @@ -67,9 +66,9 @@ public: int GetMaxIwadNum() { return MaxIwadIndex; } void SetMaxIwadNum(int x) { MaxIwadIndex = x; } - void InitSingleFile(const char *filename, bool quiet = false); - void InitMultipleFiles (TArray &filenames, bool quiet = false, LumpFilterInfo* filter = nullptr, bool allowduplicates = false, FILE* hashfile = nullptr); - void AddFile (const char *filename, FileReader *wadinfo, bool quiet, LumpFilterInfo* filter, FILE* hashfile); + bool InitSingleFile(const char *filename, FileSystemMessageFunc Printf = nullptr); + bool InitMultipleFiles (TArray &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) {} @@ -125,19 +124,15 @@ public: inline int CheckNumForFullName (const FString &name, int wadfile) { return CheckNumForFullName(name.GetChars(), wadfile); } inline int GetNumForFullName (const FString &name) { return GetNumForFullName(name.GetChars()); } - void SetLinkedTexture(int lump, FGameTexture *tex); - FGameTexture *GetLinkedTexture(int lump); - - void ReadFile (int lump, void *dest); - TArray GetFileData(int lump, int pad = 0); // reads lump into a writable buffer and optionally adds some padding at the end. (FileData isn't writable!) + std::vector GetFileData(int lump, int pad = 0); // reads lump into a writable buffer and optionally adds some padding at the end. (FileData isn't writable!) + std::vector GetFileData(const char* name, int pad = 0) { return GetFileData(GetNumForName(name), pad); } FileData ReadFile (int lump); FileData ReadFile (const char *name) { return ReadFile (GetNumForName (name)); } - inline TArray LoadFile(const char* name, int padding = 0) + inline std::vector LoadFile(const char* name, int padding = 0) { - auto lump = FindFile(name); - if (lump < 0) return TArray(); + auto lump = GetNumForFullName(name); return GetFileData(lump, padding); } diff --git a/source/common/filesystem/resourcefile.cpp b/source/common/filesystem/resourcefile.cpp index 3b8e39915..06122e156 100644 --- a/source/common/filesystem/resourcefile.cpp +++ b/source/common/filesystem/resourcefile.cpp @@ -36,9 +36,47 @@ #include #include "resourcefile.h" -#include "cmdlib.h" -#include "md5.h" +// hashing is optional. +#if __has_include("md5.h") +#include "md5.h" +#endif + +std::string ExtractBaseName(const char* path, bool include_extension) +{ + const char* src, * dot; + + src = path + strlen(path) - 1; + + if (src >= path) + { + // back up until a / or the start + while (src != path && src[-1] != '/' && src[-1] != '\\') // check both on all systems for consistent behavior with archives. + src--; + + if (!include_extension && (dot = strrchr(src, '.'))) + { + return std::string(src, dot - src); + } + else + { + return std::string(src); + } + } + return std::string(); +} + +void strReplace(std::string& str, const char *from, const char* to) +{ + if (*from == 0) + return; + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != std::string::npos) + { + str.replace(start_pos, strlen(from), to); + start_pos += strlen(to); + } +} //========================================================================== // @@ -88,10 +126,10 @@ FResourceLump::~FResourceLump() // //========================================================================== -void FResourceLump::LumpNameSetup(FString iname) +void FResourceLump::LumpNameSetup(const char *iname) { // this causes interference with real Dehacked lumps. - if (!iname.CompareNoCase("dehacked.exe")) + if (!stricmp(iname, "dehacked.exe")) { iname = ""; } @@ -115,24 +153,24 @@ static bool IsWadInFolder(const FResourceFile* const archive, const char* const return false; } - const FString dirName = ExtractFileBase(archive->FileName); - const FString fileName = ExtractFileBase(resPath, true); - const FString filePath = dirName + '/' + fileName; + const auto dirName = ExtractBaseName(archive->FileName.c_str()); + const auto fileName = ExtractBaseName(resPath, true); + const std::string filePath = dirName + '/' + fileName; - return 0 == filePath.CompareNoCase(resPath); + return 0 == stricmp(filePath.c_str(), resPath); } void FResourceLump::CheckEmbedded(LumpFilterInfo* lfi) { // Checks for embedded archives - const char *c = strstr(FullName, ".wad"); - if (c && strlen(c) == 4 && (!strchr(FullName, '/') || IsWadInFolder(Owner, FullName))) + const char *c = strstr(FullName.c_str(), ".wad"); + if (c && strlen(c) == 4 && (!strchr(FullName.c_str(), '/') || IsWadInFolder(Owner, FullName.c_str()))) { Flags |= LUMPF_EMBEDDED; } else if (lfi) for (auto& fstr : lfi->embeddings) { - if (!stricmp(FullName, fstr)) + if (!stricmp(FullName.c_str(), fstr.c_str())) { Flags |= LUMPF_EMBEDDED; } @@ -193,7 +231,15 @@ void *FResourceLump::Lock() } else if (LumpSize > 0) { - FillCache(); + try + { + FillCache(); + } + catch (const FileSystemException& err) + { + // enrich the message with info about this lump. + throw FileSystemException("%s, file '%s': %s", getName(), Owner->FileName.c_str(), err.what()); + } } return Cache; } @@ -223,46 +269,55 @@ int FResourceLump::Unlock() // //========================================================================== -typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter); +typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); -FResourceFile *CheckWad(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter); -FResourceFile *CheckGRP(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter); -FResourceFile *CheckRFF(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter); -FResourceFile *CheckPak(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter); -FResourceFile *CheckZip(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter); -FResourceFile *Check7Z(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter); -FResourceFile* CheckSSI(const char* filename, FileReader& file, bool quiet, LumpFilterInfo* filter); -FResourceFile *CheckLump(const char *filename,FileReader &file, bool quiet, LumpFilterInfo* filter); -FResourceFile *CheckDir(const char *filename, bool quiet, bool nosub, LumpFilterInfo* filter); +FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); +FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); +FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); +FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); +FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); +FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); +FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); +FResourceFile* CheckWHRes(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); +FResourceFile *CheckLump(const char *filename,FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); +FResourceFile *CheckDir(const char *filename, bool nosub, LumpFilterInfo* filter, FileSystemMessageFunc Printf); -static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckSSI, CheckLump }; +static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckSSI, CheckWHRes, CheckLump }; -FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool quiet, bool containeronly, LumpFilterInfo* filter) +static int nulPrintf(FSMessageLevel msg, const char* fmt, ...) { - for(size_t i = 0; i < countof(funcs) - containeronly; i++) + return 0; +} + +FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf) +{ + if (Printf == nullptr) Printf = nulPrintf; + for(auto func : funcs) { - FResourceFile *resfile = funcs[i](filename, file, quiet, filter); + if (containeronly && func == CheckLump) break; + FResourceFile *resfile = func(filename, file, filter, Printf); if (resfile != NULL) return resfile; } return NULL; } -FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool quiet, bool containeronly, LumpFilterInfo* filter) +FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { - return DoOpenResourceFile(filename, file, quiet, containeronly, filter); + return DoOpenResourceFile(filename, file, containeronly, filter, Printf); } -FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool quiet, bool containeronly, LumpFilterInfo* filter) +FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { FileReader file; if (!file.OpenFile(filename)) return nullptr; - return DoOpenResourceFile(filename, file, quiet, containeronly, filter); + return DoOpenResourceFile(filename, file, containeronly, filter, Printf); } -FResourceFile *FResourceFile::OpenDirectory(const char *filename, bool quiet, LumpFilterInfo* filter) +FResourceFile *FResourceFile::OpenDirectory(const char *filename, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { - return CheckDir(filename, quiet, false, filter); + if (Printf == nullptr) Printf = nulPrintf; + return CheckDir(filename, false, filter, Printf); } //========================================================================== @@ -305,9 +360,10 @@ int lumpcmp(const void * a, const void * b) void FResourceFile::GenerateHash() { +#if __has_include("md5.h") // hash the lump directory after sorting - Hash.Format(("%08X-%04X-"), (unsigned)Reader.GetLength(), NumLumps); + auto n = snprintf(Hash, 48, "%08X-%04X-", (unsigned)Reader.GetLength(), NumLumps); MD5Context md5; @@ -315,14 +371,15 @@ void FResourceFile::GenerateHash() for(uint32_t i = 0; i < NumLumps; i++) { auto lump = GetLump(i); - md5.Update((const uint8_t*)lump->FullName.GetChars(), (unsigned)lump->FullName.Len() + 1); + md5.Update((const uint8_t*)lump->FullName.c_str(), (unsigned)lump->FullName.length() + 1); md5.Update((const uint8_t*)&lump->LumpSize, 4); } md5.Final(digest); for (auto c : digest) { - Hash.AppendFormat("%02X", c); + n += snprintf(Hash + n, 3, "%02X", c); } +#endif } //========================================================================== @@ -350,11 +407,11 @@ void FResourceFile::PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterI ptrdiff_t len; ptrdiff_t lastpos = -1; - FString file; - FString LumpFilter = filter->dotFilter; - while ((len = LumpFilter.IndexOf('.', lastpos+1)) > 0) + std::string file; + std::string& LumpFilter = filter->dotFilter; + while ((len = LumpFilter.find_first_of('.', lastpos+1)) != LumpFilter.npos) { - max -= FilterLumps(LumpFilter.Left(len), lumps, lumpsize, max); + max -= FilterLumps(std::string(LumpFilter, 0, len), lumps, lumpsize, max); lastpos = len; } max -= FilterLumps(LumpFilter, lumps, lumpsize, max); @@ -372,24 +429,23 @@ void FResourceFile::PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterI // //========================================================================== -int FResourceFile::FilterLumps(FString filtername, void *lumps, size_t lumpsize, uint32_t max) +int FResourceFile::FilterLumps(const std::string& filtername, void *lumps, size_t lumpsize, uint32_t max) { - FString filter; uint32_t start, end; - if (filtername.IsEmpty()) + if (filtername.empty()) { return 0; } - filter << "filter/" << filtername << '/'; + std::string filter = "filter/" + filtername + '/'; - bool found = FindPrefixRange(filter, lumps, lumpsize, max, start, end); + bool found = FindPrefixRange(filter.c_str(), lumps, lumpsize, max, start, end); - // Workaround for old Doom filter names. - if (!found && filtername.IndexOf("doom.id.doom") == 0) + // Workaround for old Doom filter names (todo: move out of here.) + if (!found && filtername.find_first_of("doom.id.doom") == 0) { - filter.Substitute("doom.id.doom", "doom.doom"); - found = FindPrefixRange(filter, lumps, lumpsize, max, start, end); + strReplace(filter, "doom.id.doom", "doom.doom"); + found = FindPrefixRange(filter.c_str(), lumps, lumpsize, max, start, end); } if (found) @@ -401,8 +457,8 @@ int FResourceFile::FilterLumps(FString filtername, void *lumps, size_t lumpsize, for (uint32_t i = start; i < end; ++i, lump_p = (uint8_t *)lump_p + lumpsize) { FResourceLump *lump = (FResourceLump *)lump_p; - assert(lump->FullName.CompareNoCase(filter, (int)filter.Len()) == 0); - lump->LumpNameSetup(lump->FullName.Mid(filter.Len())); + assert(strnicmp(lump->FullName.c_str(), filter.c_str(), filter.length()) == 0); + lump->LumpNameSetup(lump->FullName.c_str() + filter.length()); } // Move filtered lumps to the end of the lump list. @@ -486,7 +542,7 @@ void FResourceFile::JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t m // //========================================================================== -bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize, uint32_t maxlump, uint32_t &start, uint32_t &end) +bool FResourceFile::FindPrefixRange(const char* filter, void *lumps, size_t lumpsize, uint32_t maxlump, uint32_t &start, uint32_t &end) { uint32_t min, max, mid, inside; FResourceLump *lump; @@ -504,7 +560,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize { mid = min + (max - min) / 2; lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize); - cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len()); + cmp = strnicmp(lump->FullName.c_str(), filter, (int)strlen(filter)); if (cmp == 0) break; else if (cmp < 0) @@ -524,7 +580,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize { mid = min + (max - min) / 2; lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize); - cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len()); + cmp = strnicmp(lump->FullName.c_str(), filter, (int)strlen(filter)); // Go left on matches and right on misses. if (cmp == 0) max = mid - 1; @@ -539,7 +595,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize { mid = min + (max - min) / 2; lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize); - cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len()); + cmp = strnicmp(lump->FullName.c_str(), filter, (int)strlen(filter)); // Go right on matches and left on misses. if (cmp == 0) min = mid + 1; @@ -561,7 +617,7 @@ FResourceLump *FResourceFile::FindLump(const char *name) for (unsigned i = 0; i < NumLumps; i++) { FResourceLump *lump = GetLump(i); - if (!stricmp(name, lump->FullName)) + if (!stricmp(name, lump->FullName.c_str())) { return lump; } @@ -601,7 +657,13 @@ int FUncompressedLump::FillCache() Owner->Reader.Seek(Position, FileReader::SeekSet); Cache = new char[LumpSize]; - Owner->Reader.Read(Cache, LumpSize); + + auto read = Owner->Reader.Read(Cache, LumpSize); + if (read != LumpSize) + { + throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize); + } + RefCount = 1; return 1; } @@ -662,13 +724,17 @@ int FExternalLump::FillCache() Cache = new char[LumpSize]; FileReader f; - if (f.OpenFile(Filename)) + if (f.OpenFile(Filename.c_str())) { - f.Read(Cache, LumpSize); + auto read = f.Read(Cache, LumpSize); + if (read != LumpSize) + { + throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize); + } } else { - memset(Cache, 0, LumpSize); + throw FileSystemException("unable to open file"); } RefCount = 1; return 1; diff --git a/source/common/filesystem/resourcefile.h b/source/common/filesystem/resourcefile.h index d64c278e8..c40e1c598 100644 --- a/source/common/filesystem/resourcefile.h +++ b/source/common/filesystem/resourcefile.h @@ -4,22 +4,42 @@ #define __RESFILE_H #include - +#include +#include #include "files.h" -#include "zstring.h" +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 { - TArray gameTypeFilter; // this can contain multiple entries - FString dotFilter; + std::vector gameTypeFilter; // this can contain multiple entries + std::string dotFilter; // The following are for checking if the root directory of a zip can be removed. - TArray reservedFolders; - TArray requiredPrefixes; - TArray embeddings; + std::vector reservedFolders; + std::vector requiredPrefixes; + std::vector embeddings; + std::vector blockednames; // File names that will never be accepted (e.g. dehacked.exe for Doom) + std::function filenamecheck; // for scanning directories, this allows to eliminate unwanted content. std::function postprocessFunc; }; +enum class FSMessageLevel +{ + Error = 1, + Warning = 2, + Attention = 3, + Message = 4, + DebugWarn = 5, + DebugNotify = 6, +}; + +// pass the text output function as parameter to avoid a hard dependency on higher level code. +using FileSystemMessageFunc = int(*)(FSMessageLevel msglevel, const char* format, ...); + + class FResourceFile; // [RH] Namespaces from BOOM. @@ -71,6 +91,7 @@ struct FCompressedBuffer int mZipFlags; unsigned mCRC32; char *mBuffer; + const char* filename; bool Decompress(char *destbuffer); void Clean() @@ -92,7 +113,7 @@ struct FResourceLump int LumpSize; int RefCount; protected: - FString FullName; + std::string FullName; public: uint8_t Flags; char * Cache; @@ -112,7 +133,7 @@ public: virtual int GetFileOffset() { return -1; } virtual int GetIndexNum() const { return -1; } virtual int GetNamespace() const { return 0; } - void LumpNameSetup(FString iname); + void LumpNameSetup(const char* iname); void CheckEmbedded(LumpFilterInfo* lfi); virtual FCompressedBuffer GetRawData(); @@ -121,7 +142,7 @@ public: unsigned Size() const{ return LumpSize; } int LockCount() const { return RefCount; } - const char* getName() { return FullName.GetChars(); } + const char* getName() { return FullName.c_str(); } protected: virtual int FillCache() { return -1; } @@ -132,10 +153,10 @@ class FResourceFile { public: FileReader Reader; - FString FileName; + std::string FileName; protected: uint32_t NumLumps; - FString Hash; + char Hash[48]; FResourceFile(const char *filename); FResourceFile(const char *filename, FileReader &r); @@ -147,23 +168,23 @@ protected: private: uint32_t FirstLump; - int FilterLumps(FString filtername, void *lumps, size_t lumpsize, uint32_t max); + int FilterLumps(const std::string& filtername, void *lumps, size_t lumpsize, uint32_t max); int FilterLumpsByGameType(LumpFilterInfo *filter, void *lumps, size_t lumpsize, uint32_t max); - bool FindPrefixRange(FString filter, void *lumps, size_t lumpsize, uint32_t max, uint32_t &start, uint32_t &end); + bool FindPrefixRange(const char* filter, void *lumps, size_t lumpsize, uint32_t max, uint32_t &start, uint32_t &end); void JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t max); - static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool quiet, bool containeronly, LumpFilterInfo* filter); + static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf); public: - static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool quiet = false, bool containeronly = false, LumpFilterInfo* filter = nullptr); - static FResourceFile *OpenResourceFile(const char *filename, bool quiet = false, bool containeronly = false, LumpFilterInfo* filter = nullptr); - static FResourceFile *OpenDirectory(const char *filename, bool quiet = false, LumpFilterInfo* filter = nullptr); + static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr); + static FResourceFile *OpenResourceFile(const char *filename, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr); + static FResourceFile *OpenDirectory(const char *filename, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr); virtual ~FResourceFile(); // If this FResourceFile represents a directory, the Reader object is not usable so don't return it. FileReader *GetReader() { return Reader.isOpen()? &Reader : nullptr; } uint32_t LumpCount() const { return NumLumps; } uint32_t GetFirstEntry() const { return FirstLump; } void SetFirstLump(uint32_t f) { FirstLump = f; } - const FString &GetHash() const { return Hash; } + const char* GetHash() const { return Hash; } virtual FResourceLump *GetLump(int no) = 0; @@ -175,7 +196,7 @@ struct FUncompressedLump : public FResourceLump int Position; virtual FileReader *GetReader(); - virtual int FillCache(); + virtual int FillCache() override; virtual int GetFileOffset() { return Position; } }; @@ -195,10 +216,10 @@ protected: struct FExternalLump : public FResourceLump { - FString Filename; + std::string Filename; FExternalLump(const char *_filename, int filesize = -1); - virtual int FillCache(); + virtual int FillCache() override; }; diff --git a/source/common/filesystem/w_zip.h b/source/common/filesystem/w_zip.h index ddc065f07..c0905cd20 100644 --- a/source/common/filesystem/w_zip.h +++ b/source/common/filesystem/w_zip.h @@ -1,7 +1,11 @@ #ifndef __W_ZIP #define __W_ZIP -#include "basics.h" +#if defined(__GNUC__) +#define FORCE_PACKED __attribute__((__packed__)) +#else +#define FORCE_PACKED +#endif #pragma pack(1) // FZipCentralInfo @@ -85,6 +89,15 @@ struct FZipLocalFileHeader #pragma pack() +#ifndef MAKE_ID +#ifndef __BIG_ENDIAN__ +#define MAKE_ID(a,b,c,d) ((uint32_t)((a)|((b)<<8)|((c)<<16)|((d)<<24))) +#else +#define MAKE_ID(a,b,c,d) ((uint32_t)((d)|((c)<<8)|((b)<<16)|((a)<<24))) +#endif +#endif + + #define ZIP_LOCALFILE MAKE_ID('P','K',3,4) #define ZIP_CENTRALFILE MAKE_ID('P','K',1,2) #define ZIP_ENDOFDIR MAKE_ID('P','K',5,6) diff --git a/source/common/fonts/singlelumpfont.cpp b/source/common/fonts/singlelumpfont.cpp index d3bee25a3..94cbd18ec 100644 --- a/source/common/fonts/singlelumpfont.cpp +++ b/source/common/fonts/singlelumpfont.cpp @@ -41,6 +41,7 @@ #include "utf8.h" #include "fontchars.h" #include "texturemanager.h" +#include "m_swap.h" #include "fontinternals.h" diff --git a/source/common/menu/savegamemanager.cpp b/source/common/menu/savegamemanager.cpp index 5dc22ec76..7e948267d 100644 --- a/source/common/menu/savegamemanager.cpp +++ b/source/common/menu/savegamemanager.cpp @@ -320,10 +320,10 @@ unsigned FSavegameManagerBase::ExtractSaveData(int index) { FileReader picreader; - picreader.OpenMemoryArray([=](TArray &array) + picreader.OpenMemoryArray([=](std::vector &array) { auto cache = pic->Lock(); - array.Resize(pic->LumpSize); + array.resize(pic->LumpSize); memcpy(&array[0], cache, pic->LumpSize); pic->Unlock(); return true; diff --git a/source/common/models/models_md2.cpp b/source/common/models/models_md2.cpp index 4f2a12d4e..56ab6274c 100644 --- a/source/common/models/models_md2.cpp +++ b/source/common/models/models_md2.cpp @@ -31,6 +31,7 @@ #include "texturemanager.h" #include "modelrenderer.h" #include "printf.h" +#include "m_swap.h" #ifdef _MSC_VER #pragma warning(disable:4244) // warning C4244: conversion from 'double' to 'float', possible loss of data diff --git a/source/common/models/models_md3.cpp b/source/common/models/models_md3.cpp index e716a6f26..2337a3897 100644 --- a/source/common/models/models_md3.cpp +++ b/source/common/models/models_md3.cpp @@ -25,6 +25,7 @@ #include "model_md3.h" #include "texturemanager.h" #include "modelrenderer.h" +#include "m_swap.h" #define MAX_QPATH 64 diff --git a/source/common/platform/posix/cocoa/i_system.mm b/source/common/platform/posix/cocoa/i_system.mm index 3338f54db..c2002ab7d 100644 --- a/source/common/platform/posix/cocoa/i_system.mm +++ b/source/common/platform/posix/cocoa/i_system.mm @@ -171,17 +171,6 @@ unsigned int I_MakeRNGSeed() return static_cast(arc4random()); } -FString I_GetCWD() -{ - NSString *currentpath = [[NSFileManager defaultManager] currentDirectoryPath]; - return currentpath.UTF8String; -} - -bool I_ChDir(const char* path) -{ - return [[NSFileManager defaultManager] changeCurrentDirectoryPath:[NSString stringWithUTF8String:path]]; -} - void I_OpenShellFolder(const char* folder) { NSFileManager *filemgr = [NSFileManager defaultManager]; diff --git a/source/common/platform/posix/sdl/i_system.cpp b/source/common/platform/posix/sdl/i_system.cpp index 96b707749..b2bd33fc2 100644 --- a/source/common/platform/posix/sdl/i_system.cpp +++ b/source/common/platform/posix/sdl/i_system.cpp @@ -406,23 +406,6 @@ FString I_GetFromClipboard (bool use_primary_selection) return ""; } -FString I_GetCWD() -{ - char* curdir = getcwd(NULL,0); - if (!curdir) - { - return ""; - } - FString ret(curdir); - free(curdir); - return ret; -} - -bool I_ChDir(const char* path) -{ - return chdir(path) == 0; -} - // Return a random seed, preferably one with lots of entropy. unsigned int I_MakeRNGSeed() { diff --git a/source/common/platform/win32/i_input.h b/source/common/platform/win32/i_input.h index 643cc65b3..16a276ce8 100644 --- a/source/common/platform/win32/i_input.h +++ b/source/common/platform/win32/i_input.h @@ -115,7 +115,7 @@ protected: void PostKeyEvent(int keynum, INTBOOL down, bool foreground); }; -class NOVTABLE FJoystickCollection : public FInputDevice +class FJoystickCollection : public FInputDevice { public: virtual void AddAxes(float axes[NUM_JOYAXIS]) = 0; diff --git a/source/common/platform/win32/i_system.cpp b/source/common/platform/win32/i_system.cpp index 8b39061a6..42909ed87 100644 --- a/source/common/platform/win32/i_system.cpp +++ b/source/common/platform/win32/i_system.cpp @@ -958,25 +958,6 @@ void I_SetThreadNumaNode(std::thread &thread, int numaNode) } } -FString I_GetCWD() -{ - auto len = GetCurrentDirectoryW(0, nullptr); - TArray curdir(len + 1, true); - if (!GetCurrentDirectoryW(len + 1, curdir.Data())) - { - return ""; - } - FString returnv(curdir.Data()); - FixPathSeperator(returnv); - return returnv; -} - -bool I_ChDir(const char* path) -{ - return SetCurrentDirectoryW(WideString(path).c_str()); -} - - void I_OpenShellFolder(const char* infolder) { auto len = GetCurrentDirectoryW(0, nullptr); diff --git a/source/common/platform/win32/i_system.h b/source/common/platform/win32/i_system.h index 9d360b55a..163db04be 100644 --- a/source/common/platform/win32/i_system.h +++ b/source/common/platform/win32/i_system.h @@ -80,7 +80,5 @@ int I_GetNumaNodeThreadCount(int numaNode); void I_SetThreadNumaNode(std::thread &thread, int numaNode); void I_OpenShellFolder(const char*); -FString I_GetCWD(); -bool I_ChDir(const char* path); #endif diff --git a/source/common/rendering/hwrenderer/data/hw_vrmodes.cpp b/source/common/rendering/hwrenderer/data/hw_vrmodes.cpp index ac80eec54..c51ce2ee9 100644 --- a/source/common/rendering/hwrenderer/data/hw_vrmodes.cpp +++ b/source/common/rendering/hwrenderer/data/hw_vrmodes.cpp @@ -34,7 +34,7 @@ ** */ -#include "vectors.h" // RAD2DEG +#include "vectors.h" #include "hw_cvars.h" #include "hw_vrmodes.h" #include "v_video.h" @@ -67,6 +67,16 @@ static VRMode vrmi_righteye = { 1, 1.f, 1.f, 1.f,{ { .5f, 1.f },{ 0.f, 0.f } } } static VRMode vrmi_topbottom = { 2, 1.f, .5f, 1.f,{ { -.5f, 1.f },{ .5f, 1.f } } }; static VRMode vrmi_checker = { 2, isqrt2, isqrt2, 1.f,{ { -.5f, 1.f },{ .5f, 1.f } } }; +static float DEG2RAD(float deg) +{ + return deg * float(M_PI / 180.0); +} + +static float RAD2DEG(float rad) +{ + return rad * float(180. / M_PI); +} + const VRMode *VRMode::GetVRMode(bool toscreen) { int mode = !toscreen || (sysCallbacks.DisableTextureFilter && sysCallbacks.DisableTextureFilter()) ? 0 : vr_mode; diff --git a/source/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h b/source/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h index 523b8d8d0..7ecbd4f84 100644 --- a/source/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h +++ b/source/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h @@ -1,5 +1,8 @@ #pragma once +#include "zstring.h" +#include "tarray.h" + enum class PostProcessUniformType { Undefined, diff --git a/source/common/rendering/i_modelvertexbuffer.h b/source/common/rendering/i_modelvertexbuffer.h index f68d4e117..927fcfbf3 100644 --- a/source/common/rendering/i_modelvertexbuffer.h +++ b/source/common/rendering/i_modelvertexbuffer.h @@ -1,5 +1,6 @@ #pragma once +#include "basics.h" struct FModelVertex diff --git a/source/common/rendering/vulkan/textures/vk_hwtexture.cpp b/source/common/rendering/vulkan/textures/vk_hwtexture.cpp index b42a45a19..a4975b792 100644 --- a/source/common/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/source/common/rendering/vulkan/textures/vk_hwtexture.cpp @@ -113,7 +113,7 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) } else { - VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; + VkFormat format = tex->IsHDR() ? VK_FORMAT_R32G32B32A32_SFLOAT : VK_FORMAT_R8G8B8A8_UNORM; int w = tex->GetWidth(); int h = tex->GetHeight(); diff --git a/source/common/scripting/core/symbols.h b/source/common/scripting/core/symbols.h index de5caaae9..15d547f7d 100644 --- a/source/common/scripting/core/symbols.h +++ b/source/common/scripting/core/symbols.h @@ -9,6 +9,16 @@ class PPrototype; struct ZCC_TreeNode; class PContainerType; +// This is needed in common code, despite being Doom specific. +enum EStateUseFlags +{ + SUF_ACTOR = 1, + SUF_OVERLAY = 2, + SUF_WEAPON = 4, + SUF_ITEM = 8, +}; + + // Symbol information ------------------------------------------------------- class PTypeBase diff --git a/source/common/scripting/interface/vmnatives.cpp b/source/common/scripting/interface/vmnatives.cpp index 54cc0d2a9..f04e39d45 100644 --- a/source/common/scripting/interface/vmnatives.cpp +++ b/source/common/scripting/interface/vmnatives.cpp @@ -424,7 +424,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 (fileSystem.GetLinkedTexture(lump) == tex) + if (TexMan.GetLinkedTexture(lump) == tex) retval = fileSystem.GetFileFullName(lump); } } diff --git a/source/common/textures/animlib.cpp b/source/common/textures/animlib.cpp index e42386bd9..949027786 100644 --- a/source/common/textures/animlib.cpp +++ b/source/common/textures/animlib.cpp @@ -217,7 +217,7 @@ static inline void drawframe(anim_t *anim, uint16_t framenumber) } // is the file size, for consistency checking. -int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, int32_t length) +int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, size_t length) { if (memcmp(buffer, "LPF ", 4)) return -1; diff --git a/source/common/textures/animlib.h b/source/common/textures/animlib.h index 661f00fb2..1fdaa354f 100644 --- a/source/common/textures/animlib.h +++ b/source/common/textures/animlib.h @@ -105,7 +105,7 @@ struct anim_t // //**************************************************************************** -int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, int32_t length); +int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, size_t length); //**************************************************************************** // diff --git a/source/common/textures/formats/anmtexture.cpp b/source/common/textures/formats/anmtexture.cpp index eeea41a89..f4fb332f0 100644 --- a/source/common/textures/formats/anmtexture.cpp +++ b/source/common/textures/formats/anmtexture.cpp @@ -73,7 +73,7 @@ FImageSource *AnmImage_TryCreate(FileReader & file, int lumpnum) auto buffer = file.ReadPadded(1); anim_t anim; - if (ANIM_LoadAnim(&anim, buffer.Data(), buffer.Size() - 1) < 0) + if (ANIM_LoadAnim(&anim, buffer.data(), buffer.size() - 1) < 0) { return nullptr; } diff --git a/source/common/textures/formats/ddstexture.cpp b/source/common/textures/formats/ddstexture.cpp index 8a3d0ba74..5ccf309b9 100644 --- a/source/common/textures/formats/ddstexture.cpp +++ b/source/common/textures/formats/ddstexture.cpp @@ -54,6 +54,7 @@ #include "bitmap.h" #include "imagehelpers.h" #include "image.h" +#include "m_swap.h" // Since we want this to compile under Linux too, we need to define this // stuff ourselves instead of including a DirectX header. diff --git a/source/common/textures/formats/jpegtexture.cpp b/source/common/textures/formats/jpegtexture.cpp index b1e5163b3..79ba53671 100644 --- a/source/common/textures/formats/jpegtexture.cpp +++ b/source/common/textures/formats/jpegtexture.cpp @@ -46,6 +46,7 @@ extern "C" #include "bitmap.h" #include "imagehelpers.h" #include "image.h" +#include "m_swap.h" struct FLumpSourceMgr : public jpeg_source_mgr diff --git a/source/common/textures/formats/patchtexture.cpp b/source/common/textures/formats/patchtexture.cpp index 2fe36efe7..d64e003e2 100644 --- a/source/common/textures/formats/patchtexture.cpp +++ b/source/common/textures/formats/patchtexture.cpp @@ -38,6 +38,7 @@ #include "bitmap.h" #include "image.h" #include "imagehelpers.h" +#include "m_swap.h" // posts are runs of non masked source pixels @@ -80,7 +81,7 @@ static bool CheckIfPatch(FileReader & file, bool &isalpha) file.Seek(0, FileReader::SeekSet); auto data = file.Read(file.GetLength()); - const patch_t *foo = (const patch_t *)data.Data(); + const patch_t *foo = (const patch_t *)data.data(); int height = LittleShort(foo->height); int width = LittleShort(foo->width); @@ -110,7 +111,7 @@ static bool CheckIfPatch(FileReader & file, bool &isalpha) { // only check this if the texture passed validation. // Here is a good point because we already have a valid buffer of the lump's data. - isalpha = checkPatchForAlpha(data.Data(), (uint32_t)file.GetLength()); + isalpha = checkPatchForAlpha(data.data(), (uint32_t)file.GetLength()); } return !gapAtStart; } diff --git a/source/common/textures/formats/pcxtexture.cpp b/source/common/textures/formats/pcxtexture.cpp index 60e2f4aba..bc014659f 100644 --- a/source/common/textures/formats/pcxtexture.cpp +++ b/source/common/textures/formats/pcxtexture.cpp @@ -39,6 +39,7 @@ #include "bitmap.h" #include "imagehelpers.h" #include "image.h" +#include "m_swap.h" //========================================================================== // @@ -159,8 +160,8 @@ void FPCXTexture::ReadPCX1bit (uint8_t *dst, FileReader & lump, PCXHeader *hdr) int rle_count = 0; uint8_t rle_value = 0; - TArray srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader)); - uint8_t * src = srcp.Data(); + auto srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader)); + uint8_t * src = srcp.data(); for (y = 0; y < Height; ++y) { @@ -209,8 +210,8 @@ void FPCXTexture::ReadPCX4bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr) TArray line(hdr->bytesPerScanLine, true); TArray colorIndex(Width, true); - TArray srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader)); - uint8_t * src = srcp.Data(); + auto srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader)); + uint8_t * src = srcp.data(); for (y = 0; y < Height; ++y) { @@ -264,7 +265,7 @@ void FPCXTexture::ReadPCX8bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr) int y, bytes; auto srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader)); - uint8_t * src = srcp.Data(); + uint8_t * src = srcp.data(); for (y = 0; y < Height; ++y) { @@ -305,7 +306,7 @@ void FPCXTexture::ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr int bytes; auto srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader)); - uint8_t * src = srcp.Data(); + uint8_t * src = srcp.data(); for (y = 0; y < Height; ++y) { diff --git a/source/common/textures/formats/pngtexture.cpp b/source/common/textures/formats/pngtexture.cpp index f9e39fc8c..cdf14c15c 100644 --- a/source/common/textures/formats/pngtexture.cpp +++ b/source/common/textures/formats/pngtexture.cpp @@ -43,6 +43,7 @@ #include "printf.h" #include "texturemanager.h" #include "filesystem.h" +#include "m_swap.h" //========================================================================== // diff --git a/source/common/textures/formats/rawpagetexture.cpp b/source/common/textures/formats/rawpagetexture.cpp index 19d3f4587..d28714d81 100644 --- a/source/common/textures/formats/rawpagetexture.cpp +++ b/source/common/textures/formats/rawpagetexture.cpp @@ -38,6 +38,7 @@ #include "bitmap.h" #include "imagehelpers.h" #include "image.h" +#include "m_swap.h" //========================================================================== @@ -73,7 +74,7 @@ bool CheckIfRaw(FileReader & data, unsigned desiredsize) data.Seek(0, FileReader::SeekSet); auto bits = data.Read(data.GetLength()); - foo = (patch_t *)bits.Data(); + foo = (patch_t *)bits.data(); height = LittleShort(foo->height); width = LittleShort(foo->width); diff --git a/source/common/textures/formats/tgatexture.cpp b/source/common/textures/formats/tgatexture.cpp index 932eeeaf1..daa70cfa4 100644 --- a/source/common/textures/formats/tgatexture.cpp +++ b/source/common/textures/formats/tgatexture.cpp @@ -39,6 +39,7 @@ #include "bitmap.h" #include "imagehelpers.h" #include "image.h" +#include "m_swap.h" //========================================================================== diff --git a/source/common/textures/gametexture.cpp b/source/common/textures/gametexture.cpp index be4063213..3ddc8dd1b 100644 --- a/source/common/textures/gametexture.cpp +++ b/source/common/textures/gametexture.cpp @@ -98,8 +98,8 @@ FGameTexture::~FGameTexture() { if (Base != nullptr) { - FGameTexture* link = fileSystem.GetLinkedTexture(GetSourceLump()); - if (link == this) fileSystem.SetLinkedTexture(GetSourceLump(), nullptr); + FGameTexture* link = TexMan.GetLinkedTexture(GetSourceLump()); + if (link == this) TexMan.SetLinkedTexture(GetSourceLump(), nullptr); } if (SoftwareTexture != nullptr) { diff --git a/source/common/textures/image.cpp b/source/common/textures/image.cpp index b32634948..e1939dfe1 100644 --- a/source/common/textures/image.cpp +++ b/source/common/textures/image.cpp @@ -322,6 +322,7 @@ FImageSource *DDSImage_TryCreate(FileReader &, int lumpnum); FImageSource *PCXImage_TryCreate(FileReader &, int lumpnum); FImageSource *TGAImage_TryCreate(FileReader &, int lumpnum); FImageSource *StbImage_TryCreate(FileReader &, int lumpnum); +FImageSource *QOIImage_TryCreate(FileReader &, int lumpnum); FImageSource *AnmImage_TryCreate(FileReader &, int lumpnum); FImageSource *RawPageImage_TryCreate(FileReader &, int lumpnum); FImageSource *FlatImage_TryCreate(FileReader &, int lumpnum); @@ -342,6 +343,7 @@ FImageSource * FImageSource::GetImage(int lumpnum, bool isflat) { DDSImage_TryCreate, false }, { PCXImage_TryCreate, false }, { StbImage_TryCreate, false }, + { QOIImage_TryCreate, false }, { TGAImage_TryCreate, false }, { AnmImage_TryCreate, false }, { StartupPageImage_TryCreate, false }, diff --git a/source/common/textures/multipatchtexturebuilder.cpp b/source/common/textures/multipatchtexturebuilder.cpp index 2a8b77fea..201398ee8 100644 --- a/source/common/textures/multipatchtexturebuilder.cpp +++ b/source/common/textures/multipatchtexturebuilder.cpp @@ -44,6 +44,7 @@ #include "image.h" #include "formats/multipatchtexture.h" #include "texturemanager.h" +#include "m_swap.h" // On the Alpha, accessing the shorts directly if they aren't aligned on a diff --git a/source/common/textures/texturemanager.cpp b/source/common/textures/texturemanager.cpp index 988498408..c149d99b2 100644 --- a/source/common/textures/texturemanager.cpp +++ b/source/common/textures/texturemanager.cpp @@ -244,11 +244,11 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset // Any graphic being placed in the zip's root directory can not be found by this. if (strchr(name, '/') || (flags & TEXMAN_ForceLookup)) { - FGameTexture *const NO_TEXTURE = (FGameTexture*)-1; + FGameTexture *const NO_TEXTURE = (FGameTexture*)-1; // marker for lumps we already checked that do not map to a texture. int lump = fileSystem.CheckNumForFullName(name); if (lump >= 0) { - FGameTexture *tex = fileSystem.GetLinkedTexture(lump); + FGameTexture *tex = GetLinkedTexture(lump); if (tex == NO_TEXTURE) return FTextureID(-1); if (tex != NULL) return tex->GetID(); if (flags & TEXMAN_DontCreate) return FTextureID(-1); // we only want to check, there's no need to create a texture if we don't have one yet. @@ -256,13 +256,13 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset if (tex != NULL) { tex->AddAutoMaterials(); - fileSystem.SetLinkedTexture(lump, tex); + SetLinkedTexture(lump, tex); return AddGameTexture(tex); } else { // mark this lump as having no valid texture so that we don't have to retry creating one later. - fileSystem.SetLinkedTexture(lump, NO_TEXTURE); + SetLinkedTexture(lump, NO_TEXTURE); } } } @@ -1627,6 +1627,37 @@ void FTextureManager::Listaliases() } } +//========================================================================== +// +// link a texture with a given lump +// +//========================================================================== + +void FTextureManager::SetLinkedTexture(int lump, FGameTexture* tex) +{ + if ((size_t)lump < fileSystem.GetNumEntries()) + { + linkedMap.Insert(lump, tex); + } +} + +//========================================================================== +// +// retrieve linked texture +// +//========================================================================== + +FGameTexture* FTextureManager::GetLinkedTexture(int lump) +{ + if ((size_t)lump < fileSystem.GetNumEntries()) + { + auto check = linkedMap.CheckKey(lump); + if (check) return *check; + } + return nullptr; +} + + //========================================================================== // // FTextureID::operator+ diff --git a/source/common/textures/texturemanager.h b/source/common/textures/texturemanager.h index 3f80514f3..cf799153f 100644 --- a/source/common/textures/texturemanager.h +++ b/source/common/textures/texturemanager.h @@ -88,6 +88,15 @@ public: } } + //========================================================================== + // + // link a texture with a given lump + // + //========================================================================== + + TMap linkedMap; + void SetLinkedTexture(int lump, FGameTexture* tex); + FGameTexture* GetLinkedTexture(int lump); enum { diff --git a/source/common/textures/textures.h b/source/common/textures/textures.h index da2c7a167..0d88f3843 100644 --- a/source/common/textures/textures.h +++ b/source/common/textures/textures.h @@ -217,6 +217,7 @@ protected: bool Masked = false; // Texture (might) have holes bool bHasCanvas = false; + bool bHdr = false; // only canvas textures for now. int8_t bTranslucent = -1; int8_t areacount = 0; // this is capped at 4 sections. @@ -253,6 +254,8 @@ public: bool isHardwareCanvas() const { return bHasCanvas; } // There's two here so that this can deal with software canvases in the hardware renderer later. bool isCanvas() const { return bHasCanvas; } + bool IsHDR() const { return bHdr; } + int GetSourceLump() { return SourceLump; } // needed by the scripted GetName method. void SetSourceLump(int sl) { SourceLump = sl; } bool FindHoles(const unsigned char * buffer, int w, int h); @@ -345,6 +348,12 @@ public: float aspectRatio; friend struct FCanvasTextureInfo; + friend class FTextureAnimator; + +private: + void SetHDR(bool hdr) { + bHdr = hdr; + } }; diff --git a/source/common/thirdparty/richpresence.cpp b/source/common/thirdparty/richpresence.cpp index 7a081adac..a8d8e8115 100644 --- a/source/common/thirdparty/richpresence.cpp +++ b/source/common/thirdparty/richpresence.cpp @@ -36,6 +36,7 @@ */ #include +#include #include "common/engine/printf.h" #include "discord_rpc.h" diff --git a/source/common/utility/basics.h b/source/common/utility/basics.h index 6655ede2c..0dbb47c67 100644 --- a/source/common/utility/basics.h +++ b/source/common/utility/basics.h @@ -3,7 +3,6 @@ #include #include #include -#include "xs_Float.h" #define MAXWIDTH 12000 #define MAXHEIGHT 5000 @@ -22,7 +21,6 @@ typedef int32_t fixed_t; // the last remnants of tables.h #define ANGLE_90 (0x40000000) #define ANGLE_180 (0x80000000) -#define ANGLE_270 (0xc0000000) #define ANGLE_MAX (0xffffffff) typedef uint32_t angle_t; @@ -39,14 +37,6 @@ typedef uint32_t angle_t; #define FORCE_PACKED #endif -// Todo: get rid of this. Static file name buffers suck. -#ifndef PATH_MAX -#define BMAX_PATH 256 -#else -#define BMAX_PATH PATH_MAX -#endif - - #ifdef __GNUC__ #define GCCPRINTF(stri,firstargi) __attribute__((format(printf,stri,firstargi))) #define GCCFORMAT(stri) __attribute__((format(printf,stri,0))) @@ -69,12 +59,6 @@ using INTBOOL = int; using BITFIELD = uint32_t; -#if defined(_MSC_VER) -#define NOVTABLE __declspec(novtable) -#else -#define NOVTABLE -#endif - // always use our own definition for consistency. #ifdef M_PI #undef M_PI @@ -82,46 +66,6 @@ using BITFIELD = uint32_t; const double M_PI = 3.14159265358979323846; // matches value in gcc v2 math.h -inline float DEG2RAD(float deg) -{ - return deg * float(M_PI / 180.0); -} - -inline double DEG2RAD(double deg) -{ - return deg * (M_PI / 180.0); -} - -inline float RAD2DEG(float rad) -{ - return rad * float(180. / M_PI); -} - -inline double RAD2DEG(double rad) -{ - return rad * (180. / M_PI); -} - -inline angle_t RAD2BAM(float rad) -{ - return angle_t(xs_RoundToUInt(rad * float(0x80000000u / M_PI))); -} - -inline angle_t RAD2BAM(double rad) -{ - return angle_t(xs_RoundToUInt(rad * (0x80000000u / M_PI))); -} - - -// This is needed in common code, despite being Doom specific. -enum EStateUseFlags -{ - SUF_ACTOR = 1, - SUF_OVERLAY = 2, - SUF_WEAPON = 4, - SUF_ITEM = 8, -}; - using std::min; using std::max; using std::clamp; diff --git a/source/common/utility/cmdlib.cpp b/source/common/utility/cmdlib.cpp index 02ab18959..1e906e69c 100644 --- a/source/common/utility/cmdlib.cpp +++ b/source/common/utility/cmdlib.cpp @@ -35,7 +35,7 @@ #include "cmdlib.h" -#include "findfile.h" +#include "fs_findfile.h" #include "files.h" #include "md5.h" @@ -122,25 +122,6 @@ char *copystring (const char *s) return b; } -//========================================================================== -// -// ReplaceString -// -// Do not use in new code. -// -//========================================================================== - -void ReplaceString (char **ptr, const char *str) -{ - if (*ptr) - { - if (*ptr == str) - return; - delete[] *ptr; - } - *ptr = copystring (str); -} - /* ============================================================================= @@ -913,68 +894,6 @@ FString NicePath(const char *path) } -//========================================================================== -// -// ScanDirectory -// -//========================================================================== - -bool ScanDirectory(TArray &list, const char *dirpath) -{ - findstate_t find; - FString dirmatch; - - dirmatch << dirpath << "*"; - - auto handle = I_FindFirst(dirmatch.GetChars(), &find); - if (handle == ((void*)(-1))) - { - return false; - } - else - { - do - { - auto attr = I_FindAttr(&find); - if (attr & FA_HIDDEN) - { - // Skip hidden files and directories. (Prevents SVN bookkeeping - // info from being included.) - continue; - } - auto fn = I_FindName(&find); - - if (attr & FA_DIREC) - { - if (fn[0] == '.' && - (fn[1] == '\0' || - (fn[1] == '.' && fn[2] == '\0'))) - { - // Do not record . and .. directories. - continue; - } - - FFileList* fl = &list[list.Reserve(1)]; - fl->Filename << dirpath << fn; - fl->isDirectory = true; - FString newdir = fl->Filename; - newdir << "/"; - ScanDirectory(list, newdir); - } - else - { - FFileList* fl = &list[list.Reserve(1)]; - fl->Filename << dirpath << fn; - fl->isDirectory = false; - } - } - while (I_FindNext(handle, &find) == 0); - I_FindClose(handle); - } - return true; -} - - //========================================================================== // // @@ -1064,7 +983,7 @@ void md5Update(FileReader& file, MD5Context& md5, unsigned len) while (len > 0) { - t = min(len, sizeof(readbuf)); + t = std::min(len, sizeof(readbuf)); len -= t; t = (long)file.Read(readbuf, t); md5.Update(readbuf, t); diff --git a/source/common/utility/cmdlib.h b/source/common/utility/cmdlib.h index 392d0f46d..e2e4aadbd 100644 --- a/source/common/utility/cmdlib.h +++ b/source/common/utility/cmdlib.h @@ -54,7 +54,6 @@ struct FScriptPosition; bool IsNum (const char *str); // [RH] added char *copystring(const char *s); -void ReplaceString (char **ptr, const char *str); bool CheckWildcards (const char *pattern, const char *text); @@ -70,13 +69,6 @@ void CreatePath(const char * fn); FString ExpandEnvVars(const char *searchpathstring); FString NicePath(const char *path); -struct FFileList -{ - FString Filename; - bool isDirectory; -}; - -bool ScanDirectory(TArray &list, const char *dirpath); bool IsAbsPath(const char*); FString M_ZLibError(int zerrnum); diff --git a/source/common/utility/engineerrors.h b/source/common/utility/engineerrors.h index 18fe849bc..a8d439f7a 100644 --- a/source/common/utility/engineerrors.h +++ b/source/common/utility/engineerrors.h @@ -59,13 +59,13 @@ public: strncpy (m_Message, message, MAX_ERRORTEXT-1); m_Message[MAX_ERRORTEXT-1] = '\0'; } - void AppendMessage(const char *message) + void AppendMessage(const char *message) noexcept { size_t len = strlen(m_Message); strncpy(m_Message + len, message, MAX_ERRORTEXT - 1 - len); m_Message[MAX_ERRORTEXT - 1] = '\0'; } - const char *GetMessage (void) const + const char *GetMessage (void) const noexcept { if (m_Message[0] != '\0') return (const char *)m_Message; diff --git a/source/common/utility/files.cpp b/source/common/utility/files.cpp deleted file mode 100644 index 6f915a2ce..000000000 --- a/source/common/utility/files.cpp +++ /dev/null @@ -1,489 +0,0 @@ -/* -** files.cpp -** Implements classes for reading from files or memory blocks -** -**--------------------------------------------------------------------------- -** Copyright 1998-2008 Randy Heit -** Copyright 2005-2008 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 "files.h" - // just for 'clamp' -#include "zstring.h" - - -FILE *myfopen(const char *filename, const char *flags) -{ -#ifndef _WIN32 - return fopen(filename, flags); -#else - auto widename = WideString(filename); - auto wideflags = WideString(flags); - return _wfopen(widename.c_str(), wideflags.c_str()); -#endif -} - - -//========================================================================== -// -// StdFileReader -// -// reads data from an stdio FILE* or part of it. -// -//========================================================================== - -class StdFileReader : public FileReaderInterface -{ - FILE *File = nullptr; - long StartPos = 0; - long FilePos = 0; - -public: - StdFileReader() - {} - - ~StdFileReader() - { - if (File != nullptr) - { - fclose(File); - } - File = nullptr; - } - - bool Open(const char *filename, long startpos = 0, long len = -1) - { - File = myfopen(filename, "rb"); - if (File == nullptr) return false; - FilePos = startpos; - StartPos = startpos; - Length = CalcFileLen(); - if (len >= 0 && len < Length) Length = len; - if (startpos > 0) Seek(0, SEEK_SET); - return true; - } - - long Tell() const override - { - return FilePos - StartPos; - } - - long Seek(long offset, int origin) override - { - if (origin == SEEK_SET) - { - offset += StartPos; - } - else if (origin == SEEK_CUR) - { - offset += FilePos; - } - else if (origin == SEEK_END) - { - offset += StartPos + Length; - } - if (offset < StartPos || offset > StartPos + Length) return -1; // out of scope - - if (0 == fseek(File, offset, SEEK_SET)) - { - FilePos = offset; - return 0; - } - return -1; - } - - long Read(void *buffer, long len) override - { - assert(len >= 0); - if (len <= 0) return 0; - if (FilePos + len > StartPos + Length) - { - len = Length - FilePos + StartPos; - } - len = (long)fread(buffer, 1, len, File); - FilePos += len; - return len; - } - - char *Gets(char *strbuf, int len) override - { - if (len <= 0 || FilePos >= StartPos + Length) return NULL; - char *p = fgets(strbuf, len, File); - if (p != NULL) - { - int old = FilePos; - FilePos = ftell(File); - if (FilePos - StartPos > Length) - { - strbuf[Length - old + StartPos] = 0; - } - } - return p; - } - -private: - long CalcFileLen() const - { - long endpos; - - fseek(File, 0, SEEK_END); - endpos = ftell(File); - fseek(File, 0, SEEK_SET); - return endpos; - } -}; - -//========================================================================== -// -// FileReaderRedirect -// -// like the above, but uses another File reader as its backing data -// -//========================================================================== - -class FileReaderRedirect : public FileReaderInterface -{ - FileReader *mReader = nullptr; - long StartPos = 0; - long FilePos = 0; - -public: - FileReaderRedirect(FileReader &parent, long start, long length) - { - mReader = &parent; - FilePos = start; - StartPos = start; - Length = length; - Seek(0, SEEK_SET); - } - - virtual long Tell() const override - { - return FilePos - StartPos; - } - - virtual long Seek(long offset, int origin) override - { - switch (origin) - { - case SEEK_SET: - offset += StartPos; - break; - - case SEEK_END: - offset += StartPos + Length; - break; - - case SEEK_CUR: - offset += (long)mReader->Tell(); - break; - } - if (offset < StartPos || offset > StartPos + Length) return -1; // out of scope - if (mReader->Seek(offset, FileReader::SeekSet) == 0) - { - FilePos = offset; - return 0; - } - return -1; - } - - virtual long Read(void *buffer, long len) override - { - assert(len >= 0); - if (len <= 0) return 0; - if (FilePos + len > StartPos + Length) - { - len = Length - FilePos + StartPos; - } - len = (long)mReader->Read(buffer, len); - FilePos += len; - return len; - } - - virtual char *Gets(char *strbuf, int len) override - { - if (len <= 0 || FilePos >= StartPos + Length) return NULL; - char *p = mReader->Gets(strbuf, len); - if (p != NULL) - { - int old = FilePos; - FilePos = (long)mReader->Tell(); - if (FilePos - StartPos > Length) - { - strbuf[Length - old + StartPos] = 0; - } - } - return p; - } - -}; - -//========================================================================== -// -// MemoryReader -// -// reads data from a block of memory -// -//========================================================================== - -long MemoryReader::Tell() const -{ - return FilePos; -} - -long MemoryReader::Seek(long offset, int origin) -{ - switch (origin) - { - case SEEK_CUR: - offset += FilePos; - break; - - case SEEK_END: - offset += Length; - break; - - } - if (offset < 0 || offset > Length) return -1; - FilePos = clamp(offset, 0, Length); - return 0; -} - -long MemoryReader::Read(void *buffer, long len) -{ - if (len>Length - FilePos) len = Length - FilePos; - if (len<0) len = 0; - memcpy(buffer, bufptr + FilePos, len); - FilePos += len; - return len; -} - -char *MemoryReader::Gets(char *strbuf, int len) -{ - if (len>Length - FilePos) len = Length - FilePos; - if (len <= 0) return NULL; - - char *p = strbuf; - while (len > 1) - { - if (bufptr[FilePos] == 0) - { - FilePos++; - break; - } - if (bufptr[FilePos] != '\r') - { - *p++ = bufptr[FilePos]; - len--; - if (bufptr[FilePos] == '\n') - { - FilePos++; - break; - } - } - FilePos++; - } - if (p == strbuf) return NULL; - *p++ = 0; - return strbuf; -} - -//========================================================================== -// -// MemoryArrayReader -// -// reads data from an array of memory -// -//========================================================================== - -class MemoryArrayReader : public MemoryReader -{ - TArray buf; - -public: - MemoryArrayReader(const char *buffer, long length) - { - if (length > 0) - { - buf.Resize(length); - memcpy(&buf[0], buffer, length); - } - UpdateBuffer(); - } - - TArray &GetArray() { return buf; } - - void UpdateBuffer() - { - bufptr = (const char*)&buf[0]; - FilePos = 0; - Length = buf.Size(); - } -}; - - - -//========================================================================== -// -// FileReader -// -// this wraps the different reader types in an object with value semantics. -// -//========================================================================== - -bool FileReader::OpenFile(const char *filename, FileReader::Size start, FileReader::Size length) -{ - auto reader = new StdFileReader; - if (!reader->Open(filename, (long)start, (long)length)) - { - delete reader; - return false; - } - Close(); - mReader = reader; - return true; -} - -bool FileReader::OpenFilePart(FileReader &parent, FileReader::Size start, FileReader::Size length) -{ - auto reader = new FileReaderRedirect(parent, (long)start, (long)length); - Close(); - mReader = reader; - return true; -} - -bool FileReader::OpenMemory(const void *mem, FileReader::Size length) -{ - Close(); - mReader = new MemoryReader((const char *)mem, (long)length); - return true; -} - -bool FileReader::OpenMemoryArray(const void *mem, FileReader::Size length) -{ - Close(); - mReader = new MemoryArrayReader((const char *)mem, (long)length); - return true; -} - -bool FileReader::OpenMemoryArray(std::function&)> getter) -{ - auto reader = new MemoryArrayReader(nullptr, 0); - if (getter(reader->GetArray())) - { - Close(); - reader->UpdateBuffer(); - mReader = reader; - return true; - } - else - { - // This will keep the old buffer, if one existed - delete reader; - return false; - } -} - - -//========================================================================== -// -// FileWriter (the motivation here is to have a buffer writing subclass) -// -//========================================================================== - -bool FileWriter::OpenDirect(const char *filename) -{ - File = myfopen(filename, "wb"); - return (File != NULL); -} - -FileWriter *FileWriter::Open(const char *filename) -{ - FileWriter *fwrit = new FileWriter(); - if (fwrit->OpenDirect(filename)) - { - return fwrit; - } - delete fwrit; - return NULL; -} - -size_t FileWriter::Write(const void *buffer, size_t len) -{ - if (File != NULL) - { - return fwrite(buffer, 1, len, File); - } - else - { - return 0; - } -} - -long FileWriter::Tell() -{ - if (File != NULL) - { - return ftell(File); - } - else - { - return 0; - } -} - -long FileWriter::Seek(long offset, int mode) -{ - if (File != NULL) - { - return fseek(File, offset, mode); - } - else - { - return 0; - } -} - -size_t FileWriter::Printf(const char *fmt, ...) -{ - va_list ap; - FString out; - - va_start(ap, fmt); - out.VFormat(fmt, ap); - va_end(ap); - return Write(out.GetChars(), out.Len()); -} - -size_t BufferWriter::Write(const void *buffer, size_t len) -{ - unsigned int ofs = mBuffer.Reserve((unsigned)len); - memcpy(&mBuffer[ofs], buffer, len); - return len; -} diff --git a/source/common/utility/files.h b/source/common/utility/files.h deleted file mode 100644 index 24d66e1d7..000000000 --- a/source/common/utility/files.h +++ /dev/null @@ -1,377 +0,0 @@ -/* -** files.h -** Implements classes for reading from files or memory blocks -** -**--------------------------------------------------------------------------- -** Copyright 1998-2008 Randy Heit -** Copyright 2005-2008 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. -**--------------------------------------------------------------------------- -** -*/ - -#ifndef FILES_H -#define FILES_H - -#include -#include -#include -#include -#include "basics.h" -#include "m_swap.h" -#include "tarray.h" - -// Zip compression methods, extended by some internal types to be passed to OpenDecompressor -enum -{ - METHOD_STORED = 0, - METHOD_SHRINK = 1, - METHOD_IMPLODE = 6, - METHOD_DEFLATE = 8, - METHOD_BZIP2 = 12, - METHOD_LZMA = 14, - METHOD_PPMD = 98, - METHOD_LZSS = 1337, // not used in Zips - this is for Console Doom compression - METHOD_ZLIB = 1338, // Zlib stream with header, used by compressed nodes. - METHOD_TRANSFEROWNER = 0x8000, -}; - -class FileReader; - -class FileReaderInterface -{ -public: - long Length = -1; - virtual ~FileReaderInterface() {} - virtual long Tell () const = 0; - virtual long Seek (long offset, int origin) = 0; - virtual long Read (void *buffer, long len) = 0; - virtual char *Gets(char *strbuf, int len) = 0; - virtual const char *GetBuffer() const { return nullptr; } - long GetLength () const { return Length; } -}; - -class MemoryReader : public FileReaderInterface -{ -protected: - const char * bufptr = nullptr; - long FilePos = 0; - - MemoryReader() - {} - -public: - MemoryReader(const char *buffer, long length) - { - bufptr = buffer; - Length = length; - FilePos = 0; - } - - long Tell() const override; - long Seek(long offset, int origin) override; - long Read(void *buffer, long len) override; - char *Gets(char *strbuf, int len) override; - virtual const char *GetBuffer() const override { return bufptr; } -}; - - -struct FResourceLump; - -class FileReader -{ - friend struct FResourceLump; // needs access to the private constructor. - - FileReaderInterface *mReader = nullptr; - - FileReader(const FileReader &r) = delete; - FileReader &operator=(const FileReader &r) = delete; - -public: - - explicit FileReader(FileReaderInterface *r) - { - mReader = r; - } - - enum ESeek - { - SeekSet = SEEK_SET, - SeekCur = SEEK_CUR, - SeekEnd = SEEK_END - }; - - typedef ptrdiff_t Size; // let's not use 'long' here. - - FileReader() {} - - FileReader(FileReader &&r) - { - mReader = r.mReader; - r.mReader = nullptr; - } - - FileReader& operator =(FileReader &&r) - { - Close(); - mReader = r.mReader; - r.mReader = nullptr; - return *this; - } - - // This is for wrapping the actual reader for custom access where a managed FileReader won't work. - FileReaderInterface* GetInterface() - { - auto i = mReader; - mReader = nullptr; - return i; - } - - - ~FileReader() - { - Close(); - } - - bool isOpen() const - { - return mReader != nullptr; - } - - void Close() - { - if (mReader != nullptr) delete mReader; - mReader = nullptr; - } - - bool OpenFile(const char *filename, Size start = 0, Size length = -1); - bool OpenFilePart(FileReader &parent, Size start, Size length); - bool OpenMemory(const void *mem, Size length); // read directly from the buffer - bool OpenMemoryArray(const void *mem, Size length); // read from a copy of the buffer. - bool OpenMemoryArray(std::function&)> getter); // read contents to a buffer and return a reader to it - bool OpenDecompressor(FileReader &parent, Size length, int method, bool seekable, const std::function& cb); // creates a decompressor stream. 'seekable' uses a buffered version so that the Seek and Tell methods can be used. - - Size Tell() const - { - return mReader->Tell(); - } - - Size Seek(Size offset, ESeek origin) - { - return mReader->Seek((long)offset, origin); - } - - Size Read(void *buffer, Size len) const - { - return mReader->Read(buffer, (long)len); - } - - TArray Read(size_t len) - { - TArray buffer((int)len, true); - Size length = mReader->Read(&buffer[0], (long)len); - buffer.Clamp((int)length); - return buffer; - } - - TArray Read() - { - TArray buffer(mReader->Length, true); - Size length = mReader->Read(&buffer[0], mReader->Length); - if (length < mReader->Length) buffer.Clear(); - return buffer; - } - - TArray ReadPadded(int padding) - { - TArray buffer(mReader->Length + padding, true); - Size length = mReader->Read(&buffer[0], mReader->Length); - if (length < mReader->Length) buffer.Clear(); - else memset(buffer.Data() + mReader->Length, 0, padding); - return buffer; - } - - char *Gets(char *strbuf, Size len) - { - return mReader->Gets(strbuf, (int)len); - } - - const char *GetBuffer() - { - return mReader->GetBuffer(); - } - - Size GetLength() const - { - return mReader->GetLength(); - } - - uint8_t ReadUInt8() - { - uint8_t v = 0; - Read(&v, 1); - return v; - } - - int8_t ReadInt8() - { - int8_t v = 0; - Read(&v, 1); - return v; - } - - uint16_t ReadUInt16() - { - uint16_t v = 0; - Read(&v, 2); - return LittleShort(v); - } - - int16_t ReadInt16() - { - int16_t v = 0; - Read(&v, 2); - return LittleShort(v); - } - - int16_t ReadInt16BE() - { - int16_t v = 0; - Read(&v, 2); - return BigShort(v); - } - - uint32_t ReadUInt32() - { - uint32_t v = 0; - Read(&v, 4); - return LittleLong(v); - } - - int32_t ReadInt32() - { - int32_t v = 0; - Read(&v, 4); - return LittleLong(v); - } - - uint32_t ReadUInt32BE() - { - uint32_t v = 0; - Read(&v, 4); - return BigLong(v); - } - - int32_t ReadInt32BE() - { - int32_t v = 0; - Read(&v, 4); - return BigLong(v); - } - - uint64_t ReadUInt64() - { - uint64_t v = 0; - Read(&v, 8); - // Prove to me that there's a relevant 64 bit Big Endian architecture and I fix this! :P - return v; - } - - - friend class FileSystem; -}; - -class DecompressorBase : public FileReaderInterface -{ - std::function ErrorCallback = nullptr; -public: - // These do not work but need to be defined to satisfy the FileReaderInterface. - // They will just error out when called. - long Tell() const override; - long Seek(long offset, int origin) override; - char* Gets(char* strbuf, int len) override; - void DecompressionError(const char* error, ...) const; - void SetErrorCallback(const std::function& cb) - { - ErrorCallback = cb; - } - void SetOwnsReader(); - -protected: - FileReader* File = nullptr; - FileReader OwnedFile; -}; - - -class FileWriter -{ -protected: - bool OpenDirect(const char *filename); - -public: - FileWriter(FILE *f = nullptr) // if passed, this writer will take over the file. - { - File = f; - } - virtual ~FileWriter() - { - Close(); - } - - static FileWriter *Open(const char *filename); - - virtual size_t Write(const void *buffer, size_t len); - virtual long Tell(); - virtual long Seek(long offset, int mode); - size_t Printf(const char *fmt, ...) GCCPRINTF(2,3); - virtual void Close() - { - if (File != NULL) fclose(File); - File = nullptr; - } - -protected: - - FILE *File; - -protected: - bool CloseOnDestruct; -}; - -class BufferWriter : public FileWriter -{ -protected: - TArray mBuffer; -public: - - BufferWriter() {} - virtual size_t Write(const void *buffer, size_t len) override; - TArray *GetBuffer() { return &mBuffer; } - TArray&& TakeBuffer() { return std::move(mBuffer); } -}; - - -#endif diff --git a/source/common/utility/files_decompress.cpp b/source/common/utility/files_decompress.cpp deleted file mode 100644 index cd2e36ed7..000000000 --- a/source/common/utility/files_decompress.cpp +++ /dev/null @@ -1,654 +0,0 @@ -/* -** files.cpp -** Implements classes for reading from files or memory blocks -** -**--------------------------------------------------------------------------- -** Copyright 1998-2008 Randy Heit -** Copyright 2005-2008 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. -**--------------------------------------------------------------------------- -** -*/ - -// Caution: LzmaDec also pulls in windows.h! -#define NOMINMAX -#include "LzmaDec.h" -#include -#include -#include -#include - -#include "files.h" - -#include "zstring.h" -#include "cmdlib.h" - -//========================================================================== -// -// I_Error -// -// Throw an error that will send us to the console if we are far enough -// along in the startup process. -// -//========================================================================== - -void DecompressorBase::DecompressionError(const char *error, ...) const -{ - const int MAX_ERRORTEXT = 300; - va_list argptr; - char errortext[MAX_ERRORTEXT]; - - va_start(argptr, error); - vsnprintf(errortext, MAX_ERRORTEXT, error, argptr); - va_end(argptr); - - if (ErrorCallback != nullptr) ErrorCallback(errortext); - else throw std::runtime_error(errortext); -} - -long DecompressorBase::Tell () const -{ - DecompressionError("Cannot get position of decompressor stream"); - return 0; -} -long DecompressorBase::Seek (long offset, int origin) -{ - DecompressionError("Cannot seek in decompressor stream"); - return 0; -} -char *DecompressorBase::Gets(char *strbuf, int len) -{ - DecompressionError("Cannot use Gets on decompressor stream"); - return nullptr; -} - -void DecompressorBase::SetOwnsReader() -{ - OwnedFile = std::move(*File); - File = &OwnedFile; -} - -//========================================================================== -// -// DecompressorZ -// -// The zlib wrapper -// reads data from a ZLib compressed stream -// -//========================================================================== - -class DecompressorZ : public DecompressorBase -{ - enum { BUFF_SIZE = 4096 }; - - bool SawEOF; - z_stream Stream; - uint8_t InBuff[BUFF_SIZE]; - -public: - DecompressorZ (FileReader *file, bool zip, const std::function& cb) - : SawEOF(false) - { - int err; - - File = file; - SetErrorCallback(cb); - FillBuffer (); - - Stream.zalloc = Z_NULL; - Stream.zfree = Z_NULL; - - if (!zip) err = inflateInit (&Stream); - else err = inflateInit2 (&Stream, -MAX_WBITS); - - if (err != Z_OK) - { - DecompressionError ("DecompressorZ: inflateInit failed: %s\n", M_ZLibError(err).GetChars()); - } - } - - ~DecompressorZ () - { - inflateEnd (&Stream); - } - - long Read (void *buffer, long len) override - { - int err; - - Stream.next_out = (Bytef *)buffer; - Stream.avail_out = len; - - do - { - err = inflate (&Stream, Z_SYNC_FLUSH); - if (Stream.avail_in == 0 && !SawEOF) - { - FillBuffer (); - } - } while (err == Z_OK && Stream.avail_out != 0); - - if (err != Z_OK && err != Z_STREAM_END) - { - DecompressionError ("Corrupt zlib stream"); - } - - if (Stream.avail_out != 0) - { - DecompressionError ("Ran out of data in zlib stream"); - } - - return len - Stream.avail_out; - } - - void FillBuffer () - { - auto numread = File->Read (InBuff, BUFF_SIZE); - - if (numread < BUFF_SIZE) - { - SawEOF = true; - } - Stream.next_in = InBuff; - Stream.avail_in = (uInt)numread; - } -}; - - -//========================================================================== -// -// DecompressorZ -// -// The bzip2 wrapper -// reads data from a libbzip2 compressed stream -// -//========================================================================== - -class DecompressorBZ2; -static DecompressorBZ2 * stupidGlobal; // Why does that dumb global error callback not pass the decompressor state? - // Thanks to that brain-dead interface we have to use a global variable to get the error to the proper handler. - -class DecompressorBZ2 : public DecompressorBase -{ - enum { BUFF_SIZE = 4096 }; - - bool SawEOF; - bz_stream Stream; - uint8_t InBuff[BUFF_SIZE]; - -public: - DecompressorBZ2 (FileReader *file, const std::function& cb) - : SawEOF(false) - { - int err; - - File = file; - SetErrorCallback(cb); - stupidGlobal = this; - FillBuffer (); - - Stream.bzalloc = NULL; - Stream.bzfree = NULL; - Stream.opaque = NULL; - - err = BZ2_bzDecompressInit(&Stream, 0, 0); - - if (err != BZ_OK) - { - DecompressionError ("DecompressorBZ2: bzDecompressInit failed: %d\n", err); - } - } - - ~DecompressorBZ2 () - { - stupidGlobal = this; - BZ2_bzDecompressEnd (&Stream); - } - - long Read (void *buffer, long len) override - { - int err; - - stupidGlobal = this; - Stream.next_out = (char *)buffer; - Stream.avail_out = len; - - do - { - err = BZ2_bzDecompress(&Stream); - if (Stream.avail_in == 0 && !SawEOF) - { - FillBuffer (); - } - } while (err == BZ_OK && Stream.avail_out != 0); - - if (err != BZ_OK && err != BZ_STREAM_END) - { - DecompressionError ("Corrupt bzip2 stream"); - } - - if (Stream.avail_out != 0) - { - DecompressionError ("Ran out of data in bzip2 stream"); - } - - return len - Stream.avail_out; - } - - void FillBuffer () - { - auto numread = File->Read(InBuff, BUFF_SIZE); - - if (numread < BUFF_SIZE) - { - SawEOF = true; - } - Stream.next_in = (char *)InBuff; - Stream.avail_in = (unsigned)numread; - } - -}; - -//========================================================================== -// -// bz_internal_error -// -// libbzip2 wants this, since we build it with BZ_NO_STDIO set. -// -//========================================================================== - -extern "C" void bz_internal_error (int errcode) -{ - if (stupidGlobal) stupidGlobal->DecompressionError("libbzip2: internal error number %d\n", errcode); - else std::terminate(); -} - -//========================================================================== -// -// DecompressorLZMA -// -// The lzma wrapper -// reads data from a LZMA compressed stream -// -//========================================================================== - -static void *SzAlloc(ISzAllocPtr, size_t size) { return malloc(size); } -static void SzFree(ISzAllocPtr, void *address) { free(address); } -ISzAlloc g_Alloc = { SzAlloc, SzFree }; - -// Wraps around a Decompressor to decompress a lzma stream -class DecompressorLZMA : public DecompressorBase -{ - enum { BUFF_SIZE = 4096 }; - - bool SawEOF; - CLzmaDec Stream; - size_t Size; - size_t InPos, InSize; - size_t OutProcessed; - uint8_t InBuff[BUFF_SIZE]; - -public: - - DecompressorLZMA (FileReader *file, size_t uncompressed_size, const std::function& cb) - : SawEOF(false) - { - uint8_t header[4 + LZMA_PROPS_SIZE]; - int err; - File = file; - SetErrorCallback(cb); - - Size = uncompressed_size; - OutProcessed = 0; - - // Read zip LZMA properties header - if (File->Read(header, sizeof(header)) < (long)sizeof(header)) - { - DecompressionError("DecompressorLZMA: File too short\n"); - } - if (header[2] + header[3] * 256 != LZMA_PROPS_SIZE) - { - DecompressionError("DecompressorLZMA: LZMA props size is %d (expected %d)\n", - header[2] + header[3] * 256, LZMA_PROPS_SIZE); - } - - FillBuffer(); - - LzmaDec_Construct(&Stream); - err = LzmaDec_Allocate(&Stream, header + 4, LZMA_PROPS_SIZE, &g_Alloc); - - if (err != SZ_OK) - { - DecompressionError("DecompressorLZMA: LzmaDec_Allocate failed: %d\n", err); - } - - LzmaDec_Init(&Stream); - } - - ~DecompressorLZMA () - { - LzmaDec_Free(&Stream, &g_Alloc); - } - - long Read (void *buffer, long len) override - { - int err; - Byte *next_out = (Byte *)buffer; - - do - { - ELzmaFinishMode finish_mode = LZMA_FINISH_ANY; - ELzmaStatus status; - size_t out_processed = len; - size_t in_processed = InSize; - - err = LzmaDec_DecodeToBuf(&Stream, next_out, &out_processed, InBuff + InPos, &in_processed, finish_mode, &status); - InPos += in_processed; - InSize -= in_processed; - next_out += out_processed; - len = (long)(len - out_processed); - if (err != SZ_OK) - { - DecompressionError ("Corrupt LZMA stream"); - } - if (in_processed == 0 && out_processed == 0) - { - if (status != LZMA_STATUS_FINISHED_WITH_MARK) - { - DecompressionError ("Corrupt LZMA stream"); - } - } - if (InSize == 0 && !SawEOF) - { - FillBuffer (); - } - } while (err == SZ_OK && len != 0); - - if (err != Z_OK && err != Z_STREAM_END) - { - DecompressionError ("Corrupt LZMA stream"); - } - - if (len != 0) - { - DecompressionError ("Ran out of data in LZMA stream"); - } - - return (long)(next_out - (Byte *)buffer); - } - - void FillBuffer () - { - auto numread = File->Read(InBuff, BUFF_SIZE); - - if (numread < BUFF_SIZE) - { - SawEOF = true; - } - InPos = 0; - InSize = numread; - } - -}; - -//========================================================================== -// -// Console Doom LZSS wrapper. -// -//========================================================================== - -class DecompressorLZSS : public DecompressorBase -{ - enum { BUFF_SIZE = 4096, WINDOW_SIZE = 4096, INTERNAL_BUFFER_SIZE = 128 }; - - bool SawEOF; - uint8_t InBuff[BUFF_SIZE]; - - enum StreamState - { - STREAM_EMPTY, - STREAM_BITS, - STREAM_FLUSH, - STREAM_FINAL - }; - struct - { - StreamState State; - - uint8_t *In; - unsigned int AvailIn; - unsigned int InternalOut; - - uint8_t CFlags, Bits; - - uint8_t Window[WINDOW_SIZE+INTERNAL_BUFFER_SIZE]; - const uint8_t *WindowData; - uint8_t *InternalBuffer; - } Stream; - - void FillBuffer() - { - if(Stream.AvailIn) - memmove(InBuff, Stream.In, Stream.AvailIn); - - auto numread = File->Read(InBuff+Stream.AvailIn, BUFF_SIZE-Stream.AvailIn); - - if (numread < BUFF_SIZE) - { - SawEOF = true; - } - Stream.In = InBuff; - Stream.AvailIn = (unsigned)numread+Stream.AvailIn; - } - - // Reads a flag byte. - void PrepareBlocks() - { - assert(Stream.InternalBuffer == Stream.WindowData); - Stream.CFlags = *Stream.In++; - --Stream.AvailIn; - Stream.Bits = 0xFF; - Stream.State = STREAM_BITS; - } - - // Reads the next chunk in the block. Returns true if successful and - // returns false if it ran out of input data. - bool UncompressBlock() - { - if(Stream.CFlags & 1) - { - // Check to see if we have enough input - if(Stream.AvailIn < 2) - return false; - Stream.AvailIn -= 2; - - uint16_t pos = BigShort(*(uint16_t*)Stream.In); - uint8_t len = (pos & 0xF)+1; - pos >>= 4; - Stream.In += 2; - if(len == 1) - { - // We've reached the end of the stream. - Stream.State = STREAM_FINAL; - return true; - } - - const uint8_t* copyStart = Stream.InternalBuffer-pos-1; - - // Complete overlap: Single byte repeated - if(pos == 0) - memset(Stream.InternalBuffer, *copyStart, len); - // No overlap: One copy - else if(pos >= len) - memcpy(Stream.InternalBuffer, copyStart, len); - else - { - // Partial overlap: Copy in 2 or 3 chunks. - do - { - unsigned int copy = min(len, pos+1); - memcpy(Stream.InternalBuffer, copyStart, copy); - Stream.InternalBuffer += copy; - Stream.InternalOut += copy; - len -= copy; - pos += copy; // Increase our position since we can copy twice as much the next round. - } - while(len); - } - - Stream.InternalOut += len; - Stream.InternalBuffer += len; - } - else - { - // Uncompressed byte. - *Stream.InternalBuffer++ = *Stream.In++; - --Stream.AvailIn; - ++Stream.InternalOut; - } - - Stream.CFlags >>= 1; - Stream.Bits >>= 1; - - // If we're done with this block, flush the output - if(Stream.Bits == 0) - Stream.State = STREAM_FLUSH; - - return true; - } - -public: - DecompressorLZSS(FileReader *file, const std::function& cb) : SawEOF(false) - { - File = file; - SetErrorCallback(cb); - Stream.State = STREAM_EMPTY; - Stream.WindowData = Stream.InternalBuffer = Stream.Window+WINDOW_SIZE; - Stream.InternalOut = 0; - Stream.AvailIn = 0; - - FillBuffer(); - } - - ~DecompressorLZSS() - { - } - - long Read(void *buffer, long len) override - { - - uint8_t *Out = (uint8_t*)buffer; - long AvailOut = len; - - do - { - while(Stream.AvailIn) - { - if(Stream.State == STREAM_EMPTY) - PrepareBlocks(); - else if(Stream.State == STREAM_BITS && !UncompressBlock()) - break; - else - break; - } - - unsigned int copy = min(Stream.InternalOut, AvailOut); - if(copy > 0) - { - memcpy(Out, Stream.WindowData, copy); - Out += copy; - AvailOut -= copy; - - // Slide our window - memmove(Stream.Window, Stream.Window+copy, WINDOW_SIZE+INTERNAL_BUFFER_SIZE-copy); - Stream.InternalBuffer -= copy; - Stream.InternalOut -= copy; - } - - if(Stream.State == STREAM_FINAL) - break; - - if(Stream.InternalOut == 0 && Stream.State == STREAM_FLUSH) - Stream.State = STREAM_EMPTY; - - if(Stream.AvailIn < 2) - FillBuffer(); - } - while(AvailOut && Stream.State != STREAM_FINAL); - - assert(AvailOut == 0); - return (long)(Out - (uint8_t*)buffer); - } -}; - - -bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, bool seekable, const std::function& cb) -{ - DecompressorBase *dec = nullptr; - FileReader *p = &parent; - switch (method & ~METHOD_TRANSFEROWNER) - { - case METHOD_DEFLATE: - case METHOD_ZLIB: - dec = new DecompressorZ(p, method == METHOD_DEFLATE, cb); - break; - - case METHOD_BZIP2: - dec = new DecompressorBZ2(p, cb); - break; - - case METHOD_LZMA: - dec = new DecompressorLZMA(p, length, cb); - break; - - case METHOD_LZSS: - dec = new DecompressorLZSS(p, cb); - break; - - // todo: METHOD_IMPLODE, METHOD_SHRINK - default: - return false; - } - if (method & METHOD_TRANSFEROWNER) - { - dec->SetOwnsReader(); - } - - dec->Length = (long)length; - if (!seekable) - { - Close(); - mReader = dec; - return true; - } - else - { - // todo: create a wrapper. for now this fails - delete dec; - return false; - } -} - diff --git a/source/common/utility/findfile.cpp b/source/common/utility/findfile.cpp index 0da6a97ff..eb169bc58 100644 --- a/source/common/utility/findfile.cpp +++ b/source/common/utility/findfile.cpp @@ -38,160 +38,8 @@ #include "printf.h" #include "configfile.h" #include "i_system.h" +#include "fs_findfile.h" -#ifndef _WIN32 - -#include -#include -#include - -#include "cmdlib.h" - -static const char *pattern; - -static int matchfile(const struct dirent *ent) -{ - return fnmatch(pattern, ent->d_name, FNM_NOESCAPE) == 0; -} - -void *I_FindFirst(const char *const filespec, findstate_t *const fileinfo) -{ - FString dir; - - const char *const slash = strrchr(filespec, '/'); - - if (slash) - { - pattern = slash + 1; - dir = FString(filespec, slash - filespec + 1); - fileinfo->path = dir; - } - else - { - pattern = filespec; - dir = "."; - } - - fileinfo->current = 0; - fileinfo->count = scandir(dir.GetChars(), &fileinfo->namelist, matchfile, alphasort); - - if (fileinfo->count > 0) - { - return fileinfo; - } - - return (void *)-1; -} - -int I_FindNext(void *const handle, findstate_t *const fileinfo) -{ - findstate_t *const state = static_cast(handle); - - if (state->current < fileinfo->count) - { - return ++state->current < fileinfo->count ? 0 : -1; - } - - return -1; -} - -int I_FindClose(void *const handle) -{ - findstate_t *const state = static_cast(handle); - - if (handle != (void *)-1 && state->count > 0) - { - for (int i = 0; i < state->count; ++i) - { - free(state->namelist[i]); - } - - free(state->namelist); - state->namelist = nullptr; - state->count = 0; - } - - return 0; -} - -int I_FindAttr(findstate_t *const fileinfo) -{ - dirent *const ent = fileinfo->namelist[fileinfo->current]; - const FString path = fileinfo->path + ent->d_name; - bool isdir; - - if (DirEntryExists(path, &isdir)) - { - return isdir ? FA_DIREC : 0; - } - - return 0; -} - -#else - -#include -#include - -//========================================================================== -// -// I_FindFirst -// -// Start a pattern matching sequence. -// -//========================================================================== - - -void *I_FindFirst(const char *filespec, findstate_t *fileinfo) -{ - static_assert(sizeof(WIN32_FIND_DATAW) == sizeof(fileinfo->FindData), "FindData size mismatch"); - auto widespec = WideString(filespec); - fileinfo->UTF8Name = ""; - return FindFirstFileW(widespec.c_str(), (LPWIN32_FIND_DATAW)&fileinfo->FindData); -} - -//========================================================================== -// -// I_FindNext -// -// Return the next file in a pattern matching sequence. -// -//========================================================================== - -int I_FindNext(void *handle, findstate_t *fileinfo) -{ - fileinfo->UTF8Name = ""; - return !FindNextFileW((HANDLE)handle, (LPWIN32_FIND_DATAW)&fileinfo->FindData); -} - -//========================================================================== -// -// I_FindClose -// -// Finish a pattern matching sequence. -// -//========================================================================== - -int I_FindClose(void *handle) -{ - return FindClose((HANDLE)handle); -} - -//========================================================================== -// -// I_FindName -// -// Returns the name for an entry -// -//========================================================================== - -const char *I_FindName(findstate_t *fileinfo) -{ - if (fileinfo->UTF8Name.IsEmpty()) fileinfo->UTF8Name = fileinfo->FindData.Name; - return fileinfo->UTF8Name.GetChars(); -} - -#endif //========================================================================== // @@ -288,45 +136,17 @@ void D_AddWildFile(TArray& wadfiles, const char* value, const char *ext { D_AddFile(wadfiles, wadfile, true, -1, config); } - else - { // Try pattern matching - findstate_t findstate; - char path[ZPATH_MAX]; - char* sep; - void* handle = I_FindFirst(value, &findstate); - - strcpy(path, value); - sep = strrchr(path, '/'); - if (sep == nullptr) - { - sep = strrchr(path, '\\'); -#ifdef _WIN32 - if (sep == nullptr && path[1] == ':') + else + { + // Try pattern matching + FileList list; + if (ScanDirectory(list, value, "*", true)) + { + for(auto& entry : list) { - sep = path + 1; + D_AddFile(wadfiles, entry.FilePath.c_str(), true, -1, config); } -#endif } - - if (handle != ((void*)-1)) - { - do - { - if (!(I_FindAttr(&findstate) & FA_DIREC)) - { - if (sep == nullptr) - { - D_AddFile(wadfiles, I_FindName(&findstate), true, -1, config); - } - else - { - strcpy(sep + 1, I_FindName(&findstate)); - D_AddFile(wadfiles, path, true, -1, config); - } - } - } while (I_FindNext(handle, &findstate) == 0); - } - I_FindClose(handle); } } @@ -370,40 +190,16 @@ void D_AddConfigFiles(TArray& wadfiles, const char* section, const char void D_AddDirectory(TArray& wadfiles, const char* dir, const char *filespec, FConfigFile* config) { - FString curdir = I_GetCWD(); - if (curdir.IsNotEmpty()) + FileList list; + if (ScanDirectory(list, dir, "*.wad", true)) { - char skindir[ZPATH_MAX]; - findstate_t findstate; - void* handle; - size_t stuffstart; - - stuffstart = strlen(dir); - memcpy(skindir, dir, stuffstart * sizeof(*dir)); - skindir[stuffstart] = 0; - - if (skindir[stuffstart - 1] == '/') + for (auto& entry : list) { - skindir[--stuffstart] = 0; - } - - if (I_ChDir(skindir)) - { - skindir[stuffstart++] = '/'; - if ((handle = I_FindFirst(filespec, &findstate)) != (void*)-1) + if (!entry.isDirectory) { - do - { - if (!(I_FindAttr(&findstate) & FA_DIREC)) - { - strcpy(skindir + stuffstart, I_FindName(&findstate)); - D_AddFile(wadfiles, skindir, true, -1, config); - } - } while (I_FindNext(handle, &findstate) == 0); - I_FindClose(handle); + D_AddFile(wadfiles, entry.FilePath.c_str(), true, -1, config); } } - I_ChDir(curdir); } } diff --git a/source/common/utility/findfile.h b/source/common/utility/findfile.h index 44bee1a35..31f8bd65b 100644 --- a/source/common/utility/findfile.h +++ b/source/common/utility/findfile.h @@ -4,91 +4,6 @@ #include #include "zstring.h" -enum -{ - ZPATH_MAX = 260 -}; - -#ifndef _WIN32 - -#include - -struct findstate_t -{ -private: - FString path; - struct dirent **namelist; - int current; - int count; - - friend void *I_FindFirst(const char *filespec, findstate_t *fileinfo); - friend int I_FindNext(void *handle, findstate_t *fileinfo); - friend const char *I_FindName(findstate_t *fileinfo); - friend int I_FindAttr(findstate_t *fileinfo); - friend int I_FindClose(void *handle); -}; - -int I_FindAttr (findstate_t *fileinfo); - -inline const char *I_FindName(findstate_t *fileinfo) -{ - return (fileinfo->namelist[fileinfo->current]->d_name); -} - -#define FA_RDONLY 1 -#define FA_HIDDEN 2 -#define FA_SYSTEM 4 -#define FA_DIREC 8 -#define FA_ARCH 16 - - -#else - -// Mirror WIN32_FIND_DATAW in - -struct findstate_t -{ -private: - struct FileTime - { - uint32_t lo, hi; - }; - struct WinData - { - uint32_t Attribs; - FileTime Times[3]; - uint32_t Size[2]; - uint32_t Reserved[2]; - wchar_t Name[ZPATH_MAX]; - wchar_t AltName[14]; - }; - WinData FindData; - FString UTF8Name; - - friend void *I_FindFirst(const char *filespec, findstate_t *fileinfo); - friend int I_FindNext(void *handle, findstate_t *fileinfo); - friend const char *I_FindName(findstate_t *fileinfo); - friend int I_FindAttr(findstate_t *fileinfo); -}; - - -const char *I_FindName(findstate_t *fileinfo); -inline int I_FindAttr(findstate_t *fileinfo) -{ - return fileinfo->FindData.Attribs; -} - -#define FA_RDONLY 0x00000001 -#define FA_HIDDEN 0x00000002 -#define FA_SYSTEM 0x00000004 -#define FA_DIREC 0x00000010 -#define FA_ARCH 0x00000020 - -#endif - -void *I_FindFirst (const char *filespec, findstate_t *fileinfo); -int I_FindNext (void *handle, findstate_t *fileinfo); -int I_FindClose (void *handle); class FConfigFile; diff --git a/source/common/utility/palette.cpp b/source/common/utility/palette.cpp index e7bc61f09..527d1cd17 100644 --- a/source/common/utility/palette.cpp +++ b/source/common/utility/palette.cpp @@ -39,6 +39,7 @@ #include "files.h" #include "filesystem.h" #include "printf.h" +#include "m_swap.h" #include "m_png.h" diff --git a/source/common/utility/utf8.cpp b/source/common/utility/utf8.cpp index 100c06a13..1ac6ea62b 100644 --- a/source/common/utility/utf8.cpp +++ b/source/common/utility/utf8.cpp @@ -1157,3 +1157,17 @@ bool myisupper(int code) return false; } +std::wstring WideString(const char* cin) +{ + std::wstring buildbuffer; + if (cin) + { + // This is a bit tricky because we need to support both UTF-8 and legacy content in ISO-8859-1 / Windows 1252 + // and thanks to user-side string manipulation it can be that a text mixes both. + // To convert the string this uses the same function as all text printing in the engine. + const uint8_t* in = (const uint8_t*)cin; + while (*in) buildbuffer.push_back((wchar_t)GetCharFromString(in)); + } + return buildbuffer; +} + diff --git a/source/common/utility/utf8.h b/source/common/utility/utf8.h index 7ca8a5f32..0b5e4ae0a 100644 --- a/source/common/utility/utf8.h +++ b/source/common/utility/utf8.h @@ -1,5 +1,7 @@ #pragma once +#include + int utf8_encode(int32_t codepoint, uint8_t *buffer, int *size); int utf8_decode(const uint8_t *src, int *size); int GetCharFromString(const uint8_t *&string); @@ -18,3 +20,8 @@ int getAlternative(int code); extern uint16_t win1252map[]; extern uint16_t lowerforupper[65536]; extern uint16_t upperforlower[65536]; + +// make this only visible on Windows, on other platforms this should not be called. +#ifdef _WIN32 +std::wstring WideString(const char*); +#endif diff --git a/source/common/utility/vectors.h b/source/common/utility/vectors.h index bfe692286..a7bc2b2f3 100644 --- a/source/common/utility/vectors.h +++ b/source/common/utility/vectors.h @@ -1043,44 +1043,9 @@ struct TMatrix3x3 // Construct a rotation matrix about an arbitrary axis. // (The axis vector must be normalized.) - TMatrix3x3(const Vector3 &axis, double radians) + TMatrix3x3(const Vector3 &axis, double degrees) + : TMatrix3x3(axis, g_sindeg(degrees), g_cosdeg(degrees)) { - double c = g_cos(radians), s = g_sin(radians), t = 1 - c; -/* In comments: A more readable version of the matrix setup. -This was found in Diana Gruber's article "The Mathematics of the -3D Rotation Matrix" at and is -attributed to Graphics Gems (Glassner, Academic Press, 1990). - - Cells[0][0] = t*axis.X*axis.X + c; - Cells[0][1] = t*axis.X*axis.Y - s*axis.Z; - Cells[0][2] = t*axis.X*axis.Z + s*axis.Y; - - Cells[1][0] = t*axis.Y*axis.X + s*axis.Z; - Cells[1][1] = t*axis.Y*axis.Y + c; - Cells[1][2] = t*axis.Y*axis.Z - s*axis.X; - - Cells[2][0] = t*axis.Z*axis.X - s*axis.Y; - Cells[2][1] = t*axis.Z*axis.Y + s*axis.X; - Cells[2][2] = t*axis.Z*axis.Z + c; - -Outside comments: A faster version with only 10 (not 24) multiplies. -*/ - double sx = s*axis.X, sy = s*axis.Y, sz = s*axis.Z; - double tx, ty, txx, tyy, u, v; - - tx = t*axis.X; - Cells[0][0] = vec_t( (txx=tx*axis.X) + c ); - Cells[0][1] = vec_t( (u=tx*axis.Y) - sz); - Cells[0][2] = vec_t( (v=tx*axis.Z) + sy); - - ty = t*axis.Y; - Cells[1][0] = vec_t( u + sz); - Cells[1][1] = vec_t( (tyy=ty*axis.Y) + c ); - Cells[1][2] = vec_t( (u=ty*axis.Z) - sx); - - Cells[2][0] = vec_t( v - sy); - Cells[2][1] = vec_t( u + sx); - Cells[2][2] = vec_t( (t-txx-tyy) + c ); } TMatrix3x3(const Vector3 &axis, double c/*cosine*/, double s/*sine*/) @@ -1106,10 +1071,10 @@ Outside comments: A faster version with only 10 (not 24) multiplies. TMatrix3x3(const Vector3 &axis, TAngle degrees); - static TMatrix3x3 Rotate2D(double radians) + static TMatrix3x3 Rotate2D(double degrees) { - double c = g_cos(radians); - double s = g_sin(radians); + double c = g_cosdeg(degrees); + double s = g_sindeg(degrees); TMatrix3x3 ret; ret.Cells[0][0] = c; ret.Cells[0][1] = -s; ret.Cells[0][2] = 0; ret.Cells[1][0] = s; ret.Cells[1][1] = c; ret.Cells[1][2] = 0; diff --git a/source/common/utility/zstring.cpp b/source/common/utility/zstring.cpp index cd9adb314..e32dd97a0 100644 --- a/source/common/utility/zstring.cpp +++ b/source/common/utility/zstring.cpp @@ -1326,19 +1326,6 @@ FString &FString::operator=(const wchar_t *copyStr) return *this; } -std::wstring WideString(const char *cin) -{ - if (!cin) return L""; - const uint8_t *in = (const uint8_t*)cin; - // This is a bit tricky because we need to support both UTF-8 and legacy content in ISO-8859-1 - // and thanks to user-side string manipulation it can be that a text mixes both. - // To convert the string this uses the same function as all text printing in the engine. - TArray buildbuffer; - while (*in) buildbuffer.Push((wchar_t)GetCharFromString(in)); - buildbuffer.Push(0); - return std::wstring(buildbuffer.Data()); -} - static HANDLE StringHeap; const SIZE_T STRING_HEAP_SIZE = 64*1024; #endif diff --git a/source/common/utility/zstring.h b/source/common/utility/zstring.h index 68a29980e..50e41d9c6 100644 --- a/source/common/utility/zstring.h +++ b/source/common/utility/zstring.h @@ -39,6 +39,7 @@ #include #include #include "tarray.h" +#include "utf8.h" #ifdef __GNUC__ #define PRINTFISH(x) __attribute__((format(printf, 2, x))) @@ -57,10 +58,6 @@ #define IGNORE_FORMAT_POST #endif -#ifdef _WIN32 -std::wstring WideString(const char *); -#endif - struct FStringData { unsigned int Len; // Length of string, excluding terminating null