- Backend update from GZDoom-

This compiles but doesn't run.
This commit is contained in:
Christoph Oelckers 2023-08-23 20:36:19 +02:00
parent f2740e434a
commit 82057bcd5a
117 changed files with 1218 additions and 763 deletions

View file

@ -576,7 +576,8 @@ file( GLOB HEADER_FILES
common/statusbar/*.h common/statusbar/*.h
common/fonts/*.h common/fonts/*.h
common/objects/*.h common/objects/*.h
common/filesystem/*.h common/filesystem/include/*.h
common/filesystem/source/*.h
common/platform/posix/cocoa/*.h common/platform/posix/cocoa/*.h
common/platform/posix/sdl/*.h common/platform/posix/sdl/*.h
common/platform/win32/*.h common/platform/win32/*.h
@ -1232,18 +1233,7 @@ else()
set( NOT_COMPILED_SOURCE_FILES ${NOT_COMPILED_SOURCE_FILES} ${VM_JIT_SOURCES} ) set( NOT_COMPILED_SOURCE_FILES ${NOT_COMPILED_SOURCE_FILES} ${VM_JIT_SOURCES} )
endif() endif()
macro( use_precompiled_header ) set( GAME_SOURCES
if( MSVC )
enable_precompiled_headers( "${ARGV0}/g_pch.h" PCH_SOURCES )
else()
# Temporary solution for compilers other than MSVC
set_source_files_properties( ${PCH_SOURCES} PROPERTIES COMPILE_FLAGS "-include g_pch.h" )
endif()
endmacro()
use_precompiled_header(".")
add_executable( ${PROJECT_NAME} WIN32 MACOSX_BUNDLE
${HEADER_FILES} ${HEADER_FILES}
${NOT_COMPILED_SOURCE_FILES} ${NOT_COMPILED_SOURCE_FILES}
${SYSTEM_SOURCES} ${SYSTEM_SOURCES}
@ -1273,29 +1263,37 @@ add_executable( ${PROJECT_NAME} WIN32 MACOSX_BUNDLE
common/thirdparty/math/tanh.c common/thirdparty/math/tanh.c
common/thirdparty/math/fastsin.cpp common/thirdparty/math/fastsin.cpp
common/filesystem/filesystem.cpp common/filesystem/source/filesystem.cpp
common/filesystem/ancientzip.cpp common/filesystem/source/ancientzip.cpp
common/filesystem/file_7z.cpp common/filesystem/source/file_7z.cpp
common/filesystem/file_grp.cpp common/filesystem/source/file_grp.cpp
common/filesystem/file_lump.cpp common/filesystem/source/file_lump.cpp
common/filesystem/file_rff.cpp common/filesystem/source/file_rff.cpp
common/filesystem/file_wad.cpp common/filesystem/source/file_wad.cpp
common/filesystem/file_zip.cpp common/filesystem/source/file_zip.cpp
common/filesystem/file_pak.cpp common/filesystem/source/file_pak.cpp
common/filesystem/file_whres.cpp common/filesystem/source/file_whres.cpp
common/filesystem/file_ssi.cpp common/filesystem/source/file_ssi.cpp
common/filesystem/file_directory.cpp common/filesystem/source/file_directory.cpp
common/filesystem/resourcefile.cpp common/filesystem/source/resourcefile.cpp
common/filesystem/files.cpp common/filesystem/source/files.cpp
common/filesystem/files_decompress.cpp common/filesystem/source/files_decompress.cpp
common/filesystem/fs_findfile.cpp common/filesystem/source/fs_findfile.cpp
common/filesystem/source/fs_stringpool.cpp
) )
set( GAME_NONPCH_SOURCES ${GAME_SOURCES} )
list( REMOVE_ITEM GAME_NONPCH_SOURCES ${PCH_SOURCES} )
add_executable( ${PROJECT_NAME} WIN32 MACOSX_BUNDLE ${GAME_SOURCES} )
target_precompile_headers( ${PROJECT_NAME} PRIVATE g_pch.h )
#set_source_files_properties( ${FASTMATH_SOURCES} PROPERTIES COMPILE_FLAGS ${DEM_FASTMATH_FLAG} ) #set_source_files_properties( ${FASTMATH_SOURCES} PROPERTIES COMPILE_FLAGS ${DEM_FASTMATH_FLAG} )
set_source_files_properties( xlat/parse_xlat.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c" )
set_source_files_properties( common/engine/sc_man.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h" ) set_source_files_properties( common/engine/sc_man.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h" )
set_source_files_properties( ${NOT_COMPILED_SOURCE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE ) set_source_files_properties( ${NOT_COMPILED_SOURCE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE )
set_source_files_properties( ${GAME_NONPCH_SOURCES} common/textures/hires/hqresize.cpp PROPERTIES SKIP_PRECOMPILE_HEADERS TRUE )
if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS")
@ -1345,7 +1343,7 @@ include_directories(
common/textures/hires common/textures/hires
common/textures common/textures
common/models common/models
common/filesystem common/filesystem/include
common/utility common/utility
common/console common/console
common/engine common/engine
@ -1510,6 +1508,8 @@ source_group("Common\\Objects" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/
source_group("Common\\Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/menu/.+") source_group("Common\\Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/menu/.+")
source_group("Common\\Fonts" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/fonts/.+") source_group("Common\\Fonts" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/fonts/.+")
source_group("Common\\File System" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/filesystem/.+") source_group("Common\\File System" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/filesystem/.+")
source_group("Common\\File System\\Include" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/filesystem/include/.+")
source_group("Common\\File System\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/filesystem/source/.+")
source_group("Common\\Scripting" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/scripting/.+") source_group("Common\\Scripting" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/scripting/.+")
source_group("Common\\Scripting\\Interface" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/scripting/interface/.+") source_group("Common\\Scripting\\Interface" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/scripting/interface/.+")
source_group("Common\\Scripting\\Frontend" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/scripting/frontend/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.c ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.h) source_group("Common\\Scripting\\Frontend" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/scripting/frontend/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.c ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.h)

View file

@ -53,6 +53,7 @@
#include "s_music.h" #include "s_music.h"
#include "filereadermusicinterface.h" #include "filereadermusicinterface.h"
using namespace FileSys;
void I_InitSoundFonts(); void I_InitSoundFonts();
@ -182,7 +183,7 @@ static void SetupGenMidi()
auto genmidi = fileSystem.ReadFile(lump); auto genmidi = fileSystem.ReadFile(lump);
if (genmidi.GetSize() < 8 + 175 * 36 || memcmp(genmidi.GetMem(), "#OPL_II#", 8)) return; if (genmidi.GetSize() < 8 + 175 * 36 || memcmp(genmidi.GetMem(), "#OPL_II#", 8)) return;
ZMusic_SetGenMidi(genmidi.GetBytes()+8); ZMusic_SetGenMidi(genmidi.GetBytes() + 8);
} }
static void SetupWgOpn() static void SetupWgOpn()
@ -192,7 +193,7 @@ static void SetupWgOpn()
{ {
return; return;
} }
FileData data = fileSystem.ReadFile(lump); auto data = fileSystem.ReadFile(lump);
ZMusic_SetWgOpn(data.GetMem(), (uint32_t)data.GetSize()); ZMusic_SetWgOpn(data.GetMem(), (uint32_t)data.GetSize());
} }
@ -204,7 +205,7 @@ static void SetupDMXGUS()
{ {
return; return;
} }
FileData data = fileSystem.ReadFile(lump); auto data = fileSystem.ReadFile(lump);
ZMusic_SetDmxGus(data.GetMem(), (uint32_t)data.GetSize()); ZMusic_SetDmxGus(data.GetMem(), (uint32_t)data.GetSize());
} }

View file

@ -40,10 +40,9 @@
#include "i_system.h" #include "i_system.h"
#include "filereadermusicinterface.h" #include "filereadermusicinterface.h"
#include <zmusic.h> #include <zmusic.h>
#include "resourcefile.h" #include "fs_filesystem.h"
#include "version.h" #include "version.h"
#include "fs_findfile.h" #include "fs_findfile.h"
#include "resourcefile.h"
#include "i_interface.h" #include "i_interface.h"
#include "configfile.h" #include "configfile.h"
#include "printf.h" #include "printf.h"
@ -332,7 +331,7 @@ FileReader FLumpPatchSetReader::OpenFile(const char *name)
// //
//========================================================================== //==========================================================================
void FSoundFontManager::ProcessOneFile(const FString &fn) void FSoundFontManager::ProcessOneFile(const char* fn)
{ {
auto fb = ExtractFileBase(fn, false); auto fb = ExtractFileBase(fn, false);
auto fbe = ExtractFileBase(fn, true); auto fbe = ExtractFileBase(fn, true);
@ -402,7 +401,7 @@ void FSoundFontManager::CollectSoundfonts()
{ {
if (stricmp (key, "Path") == 0) if (stricmp (key, "Path") == 0)
{ {
FileList list; FileSys::FileList list;
FString dir; FString dir;
@ -410,7 +409,7 @@ void FSoundFontManager::CollectSoundfonts()
FixPathSeperator(dir); FixPathSeperator(dir);
if (dir.IsNotEmpty()) if (dir.IsNotEmpty())
{ {
if (ScanDirectory(list, dir.GetChars(), "*", true)) if (FileSys::ScanDirectory(list, dir.GetChars(), "*", true))
{ {
for(auto& entry : list) for(auto& entry : list)
{ {

View file

@ -148,7 +148,7 @@ class FSoundFontManager
{ {
TArray<FSoundFontInfo> soundfonts; TArray<FSoundFontInfo> soundfonts;
void ProcessOneFile(const FString & fn); void ProcessOneFile(const char* fn);
public: public:
void CollectSoundfonts(); void CollectSoundfonts();

View file

@ -55,6 +55,7 @@
#include "i_specialpaths.h" #include "i_specialpaths.h"
#include "configfile.h" #include "configfile.h"
#include "c_cvars.h" #include "c_cvars.h"
#include "md5.h"
// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------

View file

@ -5,9 +5,9 @@
#include "zstring.h" #include "zstring.h"
#include "tarray.h" #include "tarray.h"
#include "name.h" #include "name.h"
#include "files.h"
#include <zmusic.h> #include <zmusic.h>
class FileReader;
class SoundStream; class SoundStream;

View file

@ -40,8 +40,8 @@
#include "i_soundinternal.h" #include "i_soundinternal.h"
#include "zstring.h" #include "zstring.h"
#include <zmusic.h> #include <zmusic.h>
#include "files.h"
class FileReader;
struct FSoundChan; struct FSoundChan;
enum EStartSoundFlags enum EStartSoundFlags

View file

@ -177,81 +177,47 @@ UNSAFE_CCMD (crashout)
#endif #endif
// commented out because it's very poorly implemented (it should not abuse I_ChDir like this!)
#if 0
UNSAFE_CCMD (dir) UNSAFE_CCMD (dir)
{ {
FString dir, path; FString path;
const char *match;
findstate_t c_file;
void *file;
FString curdir = I_GetCWD();
if (curdir.IsEmpty())
{
Printf ("Current path too long\n");
return;
}
if (argv.argc() > 1) if (argv.argc() > 1)
{ {
path = NicePath(argv[1]); path = NicePath(argv[1]);
if (!I_ChDir(path))
{
match = path;
dir = ExtractFilePath(path);
if (dir[0] != '\0')
{
match += dir.Len();
} }
else else
{ {
dir = "./"; path = I_GetCWD();;
} }
if (match[0] == '\0') auto base = ExtractFileBase(path, true);
FString bpath;
if (base.IndexOfAny("*?") >= 0)
{ {
match = "*"; bpath = ExtractFilePath(path);
}
if (!I_ChDir(dir))
{
Printf ("%s not found\n", dir.GetChars());
return;
}
} }
else else
{ {
match = "*"; base = "*";
dir = path; bpath = path;
}
}
else
{
match = "*";
dir = curdir;
}
if (dir[dir.Len()-1] != '/')
{
dir += '/';
} }
if ( (file = I_FindFirst (match, &c_file)) == ((void *)(-1))) FileSys::FileList list;
Printf ("Nothing matching %s%s\n", dir.GetChars(), match); if (!FileSys::ScanDirectory(list, bpath, base, true))
else
{ {
Printf ("Listing of %s%s:\n", dir.GetChars(), match); Printf ("Nothing matching %s\n", path.GetChars());
do }
{ else
if (I_FindAttr (&c_file) & FA_DIREC) {
Printf (PRINT_BOLD, "%s <dir>\n", I_FindName (&c_file)); Printf ("Listing of %s:\n", path.GetChars());
else for(auto& entry : list)
Printf ("%s\n", I_FindName (&c_file)); {
} while (I_FindNext (file, &c_file) == 0); if (entry.isDirectory)
I_FindClose (file); Printf (PRINT_BOLD, "%s <dir>\n", entry.FileName.c_str());
else
Printf ("%s\n", entry.FileName.c_str());
}
} }
I_ChDir(curdir);
} }
#endif
//========================================================================== //==========================================================================
// //

View file

@ -0,0 +1,6 @@
#pragma once
#include "fs_files.h"
using FileSys::FileReader;
using FileSys::FileWriter;
using FileSys::BufferWriter;

View file

@ -0,0 +1,7 @@
#pragma once
#include "fs_filesystem.h"
using FileSys::FileSystem;
using FileSys::FResourceFile;
inline FileSys::FileSystem fileSystem;

View file

@ -3,8 +3,7 @@
#include <stdint.h> #include <stdint.h>
#include "memarena.h" #include "memarena.h"
#include "palentry.h" #include "palentry.h"
#include "files.h"
class FileReader;
enum enum
{ {

View file

@ -57,6 +57,8 @@
#include "base64.h" #include "base64.h"
#include "vm.h" #include "vm.h"
using namespace FileSys;
extern DObject *WP_NOCHANGE; extern DObject *WP_NOCHANGE;
bool save_full = false; // for testing. Should be removed afterward. bool save_full = false; // for testing. Should be removed afterward.

View file

@ -4,7 +4,6 @@
#include <stdint.h> #include <stdint.h>
#include <type_traits> #include <type_traits>
#include "tarray.h" #include "tarray.h"
#include "file_zip.h"
#include "tflags.h" #include "tflags.h"
#include "vectors.h" #include "vectors.h"
#include "palentry.h" #include "palentry.h"
@ -80,7 +79,7 @@ public:
void SetUniqueSoundNames() { soundNamesAreUnique = true; } void SetUniqueSoundNames() { soundNamesAreUnique = true; }
bool OpenWriter(bool pretty = true); bool OpenWriter(bool pretty = true);
bool OpenReader(const char *buffer, size_t length); bool OpenReader(const char *buffer, size_t length);
bool OpenReader(FCompressedBuffer *input); bool OpenReader(FileSys::FCompressedBuffer *input);
void Close(); void Close();
void ReadObjects(bool hubtravel); void ReadObjects(bool hubtravel);
bool BeginObject(const char *name); bool BeginObject(const char *name);
@ -91,7 +90,7 @@ public:
unsigned GetSize(const char *group); unsigned GetSize(const char *group);
const char *GetKey(); const char *GetKey();
const char *GetOutput(unsigned *len = nullptr); const char *GetOutput(unsigned *len = nullptr);
FCompressedBuffer GetCompressedOutput(); FileSys::FCompressedBuffer GetCompressedOutput();
// The sprite serializer is a special case because it is needed by the VM to handle its 'spriteid' type. // The sprite serializer is a special case because it is needed by the VM to handle its 'spriteid' type.
virtual FSerializer &Sprite(const char *key, int32_t &spritenum, int32_t *def); virtual FSerializer &Sprite(const char *key, int32_t &spritenum, int32_t *def);
// This is only needed by the type system. // This is only needed by the type system.

View file

@ -41,10 +41,13 @@
#include <stdint.h> #include <stdint.h>
#include <stdarg.h> #include <stdarg.h>
#include <functional> #include <functional>
#include <vector>
#include "fs_swap.h" #include "fs_swap.h"
#include "tarray.h" #include "tarray.h"
namespace FileSys {
class FileSystemException : public std::exception class FileSystemException : public std::exception
{ {
protected: protected:
@ -99,31 +102,6 @@ public:
long GetLength () const { return Length; } 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; struct FResourceLump;
class FileReader class FileReader
@ -217,8 +195,11 @@ public:
std::vector<uint8_t> Read(size_t len) std::vector<uint8_t> Read(size_t len)
{ {
std::vector<uint8_t> buffer(len); std::vector<uint8_t> buffer(len);
if (len > 0)
{
Size length = mReader->Read(&buffer[0], (long)len); Size length = mReader->Read(&buffer[0], (long)len);
buffer.resize((size_t)length); buffer.resize((size_t)length);
}
return buffer; return buffer;
} }
@ -231,9 +212,13 @@ public:
{ {
auto len = GetLength(); auto len = GetLength();
std::vector<uint8_t> buffer(len + padding); std::vector<uint8_t> buffer(len + padding);
if (len > 0)
{
Size length = mReader->Read(&buffer[0], (long)len); Size length = mReader->Read(&buffer[0], (long)len);
if (length < len) buffer.clear(); if (length < len) buffer.clear();
else memset(buffer.data() + len, 0, padding); else memset(buffer.data() + len, 0, padding);
}
else buffer[0] = 0;
return buffer; return buffer;
} }
@ -271,7 +256,7 @@ public:
{ {
uint16_t v = 0; uint16_t v = 0;
Read(&v, 2); Read(&v, 2);
return fs_private::LittleShort(v); return byteswap::LittleShort(v);
} }
int16_t ReadInt16() int16_t ReadInt16()
@ -283,7 +268,7 @@ public:
{ {
uint16_t v = 0; uint16_t v = 0;
Read(&v, 2); Read(&v, 2);
return fs_private::BigShort(v); return byteswap::BigShort(v);
} }
int16_t ReadInt16BE() int16_t ReadInt16BE()
@ -295,7 +280,7 @@ public:
{ {
uint32_t v = 0; uint32_t v = 0;
Read(&v, 4); Read(&v, 4);
return fs_private::LittleLong(v); return byteswap::LittleLong(v);
} }
int32_t ReadInt32() int32_t ReadInt32()
@ -307,7 +292,7 @@ public:
{ {
uint32_t v = 0; uint32_t v = 0;
Read(&v, 4); Read(&v, 4);
return fs_private::BigLong(v); return byteswap::BigLong(v);
} }
int32_t ReadInt32BE() int32_t ReadInt32BE()
@ -327,24 +312,6 @@ public:
friend class FileSystem; friend class FileSystem;
}; };
class DecompressorBase : public FileReaderInterface
{
bool exceptions = false;
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 SetOwnsReader();
void EnableExceptions(bool on) { exceptions = on; }
protected:
FileReader* File = nullptr;
FileReader OwnedFile;
};
class FileWriter class FileWriter
{ {
@ -394,5 +361,6 @@ public:
TArray<unsigned char>&& TakeBuffer() { return std::move(mBuffer); } TArray<unsigned char>&& TakeBuffer() { return std::move(mBuffer); }
}; };
}
#endif #endif

View file

@ -8,11 +8,10 @@
#include "files.h" #include "fs_files.h"
#include "resourcefile.h" #include "resourcefile.h"
class FResourceFile; namespace FileSys {
struct FResourceLump;
union LumpShortName union LumpShortName
{ {
@ -91,31 +90,31 @@ public:
int GetLastEntry(int wadnum) const noexcept; int GetLastEntry(int wadnum) const noexcept;
int GetEntryCount(int wadnum) const noexcept; int GetEntryCount(int wadnum) const noexcept;
int CheckNumForName (const char *name, int namespc); int CheckNumForName (const char *name, int namespc) const;
int CheckNumForName (const char *name, int namespc, int wadfile, bool exact = true); int CheckNumForName (const char *name, int namespc, int wadfile, bool exact = true) const;
int GetNumForName (const char *name, int namespc); int GetNumForName (const char *name, int namespc) const;
inline int CheckNumForName (const uint8_t *name) { return CheckNumForName ((const char *)name, ns_global); } inline int CheckNumForName (const uint8_t *name) const { return CheckNumForName ((const char *)name, ns_global); }
inline int CheckNumForName (const char *name) { return CheckNumForName (name, ns_global); } inline int CheckNumForName (const char *name) const { return CheckNumForName (name, ns_global); }
inline int CheckNumForName (const uint8_t *name, int ns) { return CheckNumForName ((const char *)name, ns); } inline int CheckNumForName (const uint8_t *name, int ns) const { return CheckNumForName ((const char *)name, ns); }
inline int GetNumForName (const char *name) { return GetNumForName (name, ns_global); } inline int GetNumForName (const char *name) const { return GetNumForName (name, ns_global); }
inline int GetNumForName (const uint8_t *name) { return GetNumForName ((const char *)name); } inline int GetNumForName (const uint8_t *name) const { return GetNumForName ((const char *)name); }
inline int GetNumForName (const uint8_t *name, int ns) { return GetNumForName ((const char *)name, ns); } inline int GetNumForName (const uint8_t *name, int ns) const { return GetNumForName ((const char *)name, ns); }
int CheckNumForFullName (const char *name, bool trynormal = false, int namespc = ns_global, bool ignoreext = false); int CheckNumForFullName (const char *cname, bool trynormal = false, int namespc = ns_global, bool ignoreext = false) const;
int CheckNumForFullName (const char *name, int wadfile); int CheckNumForFullName (const char *name, int wadfile) const;
int GetNumForFullName (const char *name); int GetNumForFullName (const char *name) const;
int FindFile(const char* name) int FindFile(const char* name) const
{ {
return CheckNumForFullName(name); return CheckNumForFullName(name);
} }
bool FileExists(const char* name) bool FileExists(const char* name) const
{ {
return FindFile(name) >= 0; return FindFile(name) >= 0;
} }
bool FileExists(const std::string& name) bool FileExists(const std::string& name) const
{ {
return FindFile(name.c_str()) >= 0; return FindFile(name.c_str()) >= 0;
} }
@ -139,10 +138,13 @@ public:
int FindLumpFullName(const char* name, int* lastlump, bool noext = false); int FindLumpFullName(const char* name, int* lastlump, bool noext = false);
bool CheckFileName (int lump, const char *name); // [RH] True if lump's name == name bool CheckFileName (int lump, const char *name); // [RH] True if lump's name == name
int FindFileWithExtensions(const char* name, const char* const* exts, int count); int FindFileWithExtensions(const char* name, const char* const* exts, int count) const;
int FindResource(int resid, const char* type, int filenum = -1) const noexcept; int FindResource(int resid, const char* type, int filenum = -1) const noexcept;
int GetResource(int resid, const char* type, int filenum = -1) const; int GetResource(int resid, const char* type, int filenum = -1) const;
static uint32_t LumpNameHash (const char *name); // [RH] Create hash key from an 8-char name
int FileLength (int lump) const; int FileLength (int lump) const;
int GetFileOffset (int lump); // [RH] Returns offset of lump in the wadfile int GetFileOffset (int lump); // [RH] Returns offset of lump in the wadfile
int GetFileFlags (int lump); // Return the flags for this lump int GetFileFlags (int lump); // Return the flags for this lump
@ -200,11 +202,12 @@ protected:
int IwadIndex = -1; int IwadIndex = -1;
int MaxIwadIndex = -1; int MaxIwadIndex = -1;
StringPool* stringpool;
private: private:
void DeleteAll(); void DeleteAll();
void MoveLumpsInFolder(const char *); void MoveLumpsInFolder(const char *);
}; };
extern FileSystem fileSystem; }

View file

@ -5,6 +5,8 @@
#include <vector> #include <vector>
#include <string> #include <string>
namespace FileSys {
struct FileListEntry struct FileListEntry
{ {
std::string FileName; // file name only std::string FileName; // file name only
@ -34,3 +36,4 @@ inline void FixPathSeparator(char* path)
} }
} }
}

View file

@ -17,8 +17,8 @@
#include <libkern/OSByteOrder.h> #include <libkern/OSByteOrder.h>
#endif #endif
namespace fs_private namespace FileSys {
{ namespace byteswap {
#ifdef __APPLE__ #ifdef __APPLE__
@ -117,5 +117,6 @@ inline unsigned int BigLong (unsigned int x)
#endif // __BIG_ENDIAN__ #endif // __BIG_ENDIAN__
} }
}
#endif // __M_SWAP_H__ #endif // __M_SWAP_H__

View file

@ -6,8 +6,11 @@
#include <limits.h> #include <limits.h>
#include <vector> #include <vector>
#include <string> #include <string>
#include "files.h" #include "fs_files.h"
namespace FileSys {
class StringPool;
std::string ExtractBaseName(const char* path, bool include_extension = false); std::string ExtractBaseName(const char* path, bool include_extension = false);
void strReplace(std::string& str, const char* from, const char* to); void strReplace(std::string& str, const char* from, const char* to);
@ -113,7 +116,7 @@ struct FResourceLump
int LumpSize; int LumpSize;
int RefCount; int RefCount;
protected: protected:
std::string FullName; const char* FullName;
public: public:
uint8_t Flags; uint8_t Flags;
char * Cache; char * Cache;
@ -125,6 +128,7 @@ public:
Owner = NULL; Owner = NULL;
Flags = 0; Flags = 0;
RefCount = 0; RefCount = 0;
FullName = "";
} }
virtual ~FResourceLump(); virtual ~FResourceLump();
@ -133,7 +137,7 @@ public:
virtual int GetFileOffset() { return -1; } virtual int GetFileOffset() { return -1; }
virtual int GetIndexNum() const { return -1; } virtual int GetIndexNum() const { return -1; }
virtual int GetNamespace() const { return 0; } virtual int GetNamespace() const { return 0; }
void LumpNameSetup(const char* iname); void LumpNameSetup(const char* iname, StringPool* allocator);
void CheckEmbedded(LumpFilterInfo* lfi); void CheckEmbedded(LumpFilterInfo* lfi);
virtual FCompressedBuffer GetRawData(); virtual FCompressedBuffer GetRawData();
@ -142,7 +146,8 @@ public:
unsigned Size() const{ return LumpSize; } unsigned Size() const{ return LumpSize; }
int LockCount() const { return RefCount; } int LockCount() const { return RefCount; }
const char* getName() { return FullName.c_str(); } const char* getName() { return FullName; }
void clearName() { FullName = ""; }
protected: protected:
virtual int FillCache() { return -1; } virtual int FillCache() { return -1; }
@ -153,13 +158,14 @@ class FResourceFile
{ {
public: public:
FileReader Reader; FileReader Reader;
std::string FileName; const char* FileName;
protected: protected:
uint32_t NumLumps; uint32_t NumLumps;
char Hash[48]; char Hash[48];
StringPool* stringpool;
FResourceFile(const char *filename); FResourceFile(const char *filename, StringPool* sp);
FResourceFile(const char *filename, FileReader &r); FResourceFile(const char *filename, FileReader &r, StringPool* sp);
// for archives that can contain directories // for archives that can contain directories
void GenerateHash(); void GenerateHash();
@ -172,12 +178,12 @@ private:
int FilterLumpsByGameType(LumpFilterInfo *filter, void *lumps, size_t lumpsize, uint32_t max); int FilterLumpsByGameType(LumpFilterInfo *filter, void *lumps, size_t lumpsize, uint32_t max);
bool FindPrefixRange(const char* 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); void JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t max);
static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf); static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
public: public:
static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr); static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr);
static FResourceFile *OpenResourceFile(const char *filename, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr); static FResourceFile *OpenResourceFile(const char *filename, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr);
static FResourceFile *OpenDirectory(const char *filename, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr); static FResourceFile *OpenDirectory(const char *filename, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr);
virtual ~FResourceFile(); virtual ~FResourceFile();
// If this FResourceFile represents a directory, the Reader object is not usable so don't return it. // If this FResourceFile represents a directory, the Reader object is not usable so don't return it.
FileReader *GetReader() { return Reader.isOpen()? &Reader : nullptr; } FileReader *GetReader() { return Reader.isOpen()? &Reader : nullptr; }
@ -191,57 +197,7 @@ public:
FResourceLump *FindLump(const char *name); FResourceLump *FindLump(const char *name);
}; };
struct FUncompressedLump : public FResourceLump
{
int Position;
virtual FileReader *GetReader();
virtual int FillCache() override;
virtual int GetFileOffset() { return Position; }
};
// Base class for uncompressed resource files (WAD, GRP, PAK and single lumps)
class FUncompressedFile : public FResourceFile
{
protected:
TArray<FUncompressedLump> Lumps;
FUncompressedFile(const char *filename);
FUncompressedFile(const char *filename, FileReader &r);
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};
struct FExternalLump : public FResourceLump
{
std::string Filename;
FExternalLump(const char *_filename, int filesize = -1);
virtual int FillCache() override;
};
struct FMemoryLump : public FResourceLump
{
FMemoryLump(const void* data, int length)
{
RefCount = INT_MAX / 2;
LumpSize = length;
Cache = new char[length];
memcpy(Cache, data, length);
}
virtual int FillCache() override
{
RefCount = INT_MAX / 2; // Make sure it never counts down to 0 by resetting it to something high each time it is used.
return 1;
}
};
}
#endif #endif

View file

@ -46,6 +46,8 @@
#include <stdlib.h> #include <stdlib.h>
#include "ancientzip.h" #include "ancientzip.h"
namespace FileSys {
/**************************************************************** /****************************************************************
Bit-I/O variables and routines/macros Bit-I/O variables and routines/macros
@ -433,3 +435,5 @@ int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader &_In, unsign
} }
return 0; return 0;
} }
}

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "files.h" #include "fs_files.h"
namespace FileSys {
class FZipExploder class FZipExploder
{ {
@ -42,3 +44,4 @@ public:
}; };
int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize); int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize);
}

View file

@ -40,6 +40,7 @@
#include "fs_findfile.h" #include "fs_findfile.h"
namespace FileSys {
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
// //
@ -186,7 +187,7 @@ class F7ZFile : public FResourceFile
C7zArchive *Archive; C7zArchive *Archive;
public: public:
F7ZFile(const char * filename, FileReader &filer); F7ZFile(const char * filename, FileReader &filer, StringPool* sp);
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
virtual ~F7ZFile(); virtual ~F7ZFile();
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
@ -200,8 +201,8 @@ public:
// //
//========================================================================== //==========================================================================
F7ZFile::F7ZFile(const char * filename, FileReader &filer) F7ZFile::F7ZFile(const char * filename, FileReader &filer, StringPool* sp)
: FResourceFile(filename, filer) : FResourceFile(filename, filer, sp)
{ {
Lumps = NULL; Lumps = NULL;
Archive = NULL; Archive = NULL;
@ -227,7 +228,7 @@ bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf)
Archive = NULL; Archive = NULL;
if (res == SZ_ERROR_UNSUPPORTED) if (res == SZ_ERROR_UNSUPPORTED)
{ {
Printf(FSMessageLevel::Error, "%s: Decoder does not support this archive\n", FileName.c_str()); Printf(FSMessageLevel::Error, "%s: Decoder does not support this archive\n", FileName);
} }
else if (res == SZ_ERROR_MEM) else if (res == SZ_ERROR_MEM)
{ {
@ -280,7 +281,7 @@ bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf)
} }
FixPathSeparator(&nameASCII.front()); FixPathSeparator(&nameASCII.front());
lump_p->LumpNameSetup(nameASCII.c_str()); lump_p->LumpNameSetup(nameASCII.c_str(), stringpool);
lump_p->LumpSize = static_cast<int>(SzArEx_GetFileSize(archPtr, i)); lump_p->LumpSize = static_cast<int>(SzArEx_GetFileSize(archPtr, i));
lump_p->Owner = this; lump_p->Owner = this;
lump_p->Flags = LUMPF_FULLPATH|LUMPF_COMPRESSED; lump_p->Flags = LUMPF_FULLPATH|LUMPF_COMPRESSED;
@ -300,7 +301,7 @@ bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf)
if (SZ_OK != Archive->Extract(Lumps[0].Position, &temp[0])) if (SZ_OK != Archive->Extract(Lumps[0].Position, &temp[0]))
{ {
Printf(FSMessageLevel::Error, "%s: unsupported 7z/LZMA file!\n", FileName.c_str()); Printf(FSMessageLevel::Error, "%s: unsupported 7z/LZMA file!\n", FileName);
return false; return false;
} }
} }
@ -352,7 +353,7 @@ int F7ZLump::FillCache()
// //
//========================================================================== //==========================================================================
FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{ {
char head[k7zSignatureSize]; char head[k7zSignatureSize];
@ -363,7 +364,7 @@ FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* f
file.Seek(0, FileReader::SeekSet); file.Seek(0, FileReader::SeekSet);
if (!memcmp(head, k7zSignature, k7zSignatureSize)) if (!memcmp(head, k7zSignature, k7zSignatureSize))
{ {
auto rf = new F7ZFile(filename, file); auto rf = new F7ZFile(filename, file, sp);
if (rf->Open(filter, Printf)) return rf; if (rf->Open(filter, Printf)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader file = std::move(rf->Reader); // to avoid destruction of reader
@ -374,4 +375,4 @@ FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* f
} }
}

View file

@ -38,6 +38,9 @@
#include "resourcefile.h" #include "resourcefile.h"
#include "fs_findfile.h" #include "fs_findfile.h"
#include "fs_stringpool.h"
namespace FileSys {
std::string FS_FullPath(const char* directory); std::string FS_FullPath(const char* directory);
@ -75,7 +78,7 @@ class FDirectory : public FResourceFile
void AddEntry(const char *fullpath, int size); void AddEntry(const char *fullpath, int size);
public: public:
FDirectory(const char * dirname, bool nosubdirflag = false); FDirectory(const char * dirname, StringPool* sp, bool nosubdirflag = false);
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
}; };
@ -88,11 +91,12 @@ public:
// //
//========================================================================== //==========================================================================
FDirectory::FDirectory(const char * directory, bool nosubdirflag) FDirectory::FDirectory(const char * directory, StringPool* sp, bool nosubdirflag)
: FResourceFile(NULL), nosubdir(nosubdirflag) : FResourceFile("", sp), nosubdir(nosubdirflag)
{ {
FileName = FS_FullPath(directory); auto fn = FS_FullPath(directory);
if (FileName[FileName.length()-1] != '/') FileName += '/'; if (fn.back() != '/') fn += '/';
FileName = sp->Strdup(fn.c_str());
} }
//========================================================================== //==========================================================================
@ -129,6 +133,7 @@ int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSy
if (entry.Length > 0x7fffffff) if (entry.Length > 0x7fffffff)
{ {
Printf(FSMessageLevel::Warning, "%s is larger than 2GB and will be ignored\n", entry.FilePath.c_str()); Printf(FSMessageLevel::Warning, "%s is larger than 2GB and will be ignored\n", entry.FilePath.c_str());
continue;
} }
AddEntry(entry.FilePathRel.c_str(), (int)entry.Length); AddEntry(entry.FilePathRel.c_str(), (int)entry.Length);
count++; count++;
@ -147,7 +152,7 @@ int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSy
bool FDirectory::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf) bool FDirectory::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{ {
NumLumps = AddDirectory(FileName.c_str(), filter, Printf); NumLumps = AddDirectory(FileName, filter, Printf);
PostProcessArchive(&Lumps[0], sizeof(FDirectoryLump), filter); PostProcessArchive(&Lumps[0], sizeof(FDirectoryLump), filter);
return true; return true;
} }
@ -166,11 +171,11 @@ void FDirectory::AddEntry(const char *fullpath, int size)
lump_p->mFullPath = fullpath; lump_p->mFullPath = fullpath;
// [mxd] Convert name to lowercase // [mxd] Convert name to lowercase
std::string name = fullpath + FileName; std::string name = fullpath + strlen(FileName);
for (auto& c : name) c = tolower(c); for (auto& c : name) c = tolower(c);
// The lump's name is only the part relative to the main directory // The lump's name is only the part relative to the main directory
lump_p->LumpNameSetup(name.c_str()); lump_p->LumpNameSetup(name.c_str(), stringpool);
lump_p->LumpSize = size; lump_p->LumpSize = size;
lump_p->Owner = this; lump_p->Owner = this;
lump_p->Flags = 0; lump_p->Flags = 0;
@ -220,11 +225,12 @@ int FDirectoryLump::FillCache()
// //
//========================================================================== //==========================================================================
FResourceFile *CheckDir(const char *filename, bool nosubdirflag, LumpFilterInfo* filter, FileSystemMessageFunc Printf) FResourceFile *CheckDir(const char *filename, bool nosubdirflag, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{ {
auto rf = new FDirectory(filename, nosubdirflag); auto rf = new FDirectory(filename, sp, nosubdirflag);
if (rf->Open(filter, Printf)) return rf; if (rf->Open(filter, Printf)) return rf;
delete rf; delete rf;
return nullptr; return nullptr;
} }
}

View file

@ -33,10 +33,11 @@
** **
*/ */
#include "resourcefile.h" #include "resourcefile_internal.h"
#include "fs_swap.h" #include "fs_swap.h"
using namespace fs_private; namespace FileSys {
using namespace byteswap;
//========================================================================== //==========================================================================
// //
@ -73,7 +74,7 @@ struct GrpLump
class FGrpFile : public FUncompressedFile class FGrpFile : public FUncompressedFile
{ {
public: public:
FGrpFile(const char * filename, FileReader &file); FGrpFile(const char * filename, FileReader &file, StringPool* sp);
bool Open(LumpFilterInfo* filter); bool Open(LumpFilterInfo* filter);
}; };
@ -84,8 +85,8 @@ public:
// //
//========================================================================== //==========================================================================
FGrpFile::FGrpFile(const char *filename, FileReader &file) FGrpFile::FGrpFile(const char *filename, FileReader &file, StringPool* sp)
: FUncompressedFile(filename, file) : FUncompressedFile(filename, file, sp)
{ {
} }
@ -117,7 +118,7 @@ bool FGrpFile::Open(LumpFilterInfo* filter)
Position += fileinfo[i].Size; Position += fileinfo[i].Size;
Lumps[i].Flags = 0; Lumps[i].Flags = 0;
fileinfo[i].NameWithZero[12] = '\0'; // Be sure filename is null-terminated fileinfo[i].NameWithZero[12] = '\0'; // Be sure filename is null-terminated
Lumps[i].LumpNameSetup(fileinfo[i].NameWithZero); Lumps[i].LumpNameSetup(fileinfo[i].NameWithZero, stringpool);
} }
GenerateHash(); GenerateHash();
delete[] fileinfo; delete[] fileinfo;
@ -131,7 +132,7 @@ bool FGrpFile::Open(LumpFilterInfo* filter)
// //
//========================================================================== //==========================================================================
FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{ {
char head[12]; char head[12];
@ -142,7 +143,7 @@ FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo*
file.Seek(0, FileReader::SeekSet); file.Seek(0, FileReader::SeekSet);
if (!memcmp(head, "KenSilverman", 12)) if (!memcmp(head, "KenSilverman", 12))
{ {
auto rf = new FGrpFile(filename, file); auto rf = new FGrpFile(filename, file, sp);
if (rf->Open(filter)) return rf; if (rf->Open(filter)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader file = std::move(rf->Reader); // to avoid destruction of reader
@ -152,3 +153,4 @@ FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo*
return NULL; return NULL;
} }
}

View file

@ -32,8 +32,9 @@
** **
*/ */
#include "resourcefile.h" #include "resourcefile_internal.h"
namespace FileSys {
//========================================================================== //==========================================================================
// //
// Single lump // Single lump
@ -43,7 +44,7 @@
class FLumpFile : public FUncompressedFile class FLumpFile : public FUncompressedFile
{ {
public: public:
FLumpFile(const char * filename, FileReader &file); FLumpFile(const char * filename, FileReader &file, StringPool* sp);
bool Open(LumpFilterInfo* filter); bool Open(LumpFilterInfo* filter);
}; };
@ -54,8 +55,8 @@ public:
// //
//========================================================================== //==========================================================================
FLumpFile::FLumpFile(const char *filename, FileReader &file) FLumpFile::FLumpFile(const char *filename, FileReader &file, StringPool* sp)
: FUncompressedFile(filename, file) : FUncompressedFile(filename, file, sp)
{ {
} }
@ -68,7 +69,7 @@ FLumpFile::FLumpFile(const char *filename, FileReader &file)
bool FLumpFile::Open(LumpFilterInfo*) bool FLumpFile::Open(LumpFilterInfo*)
{ {
Lumps.Resize(1); Lumps.Resize(1);
Lumps[0].LumpNameSetup(ExtractBaseName(FileName.c_str(), true).c_str()); Lumps[0].LumpNameSetup(ExtractBaseName(FileName, true).c_str(), stringpool);
Lumps[0].Owner = this; Lumps[0].Owner = this;
Lumps[0].Position = 0; Lumps[0].Position = 0;
Lumps[0].LumpSize = (int)Reader.GetLength(); Lumps[0].LumpSize = (int)Reader.GetLength();
@ -83,13 +84,14 @@ bool FLumpFile::Open(LumpFilterInfo*)
// //
//========================================================================== //==========================================================================
FResourceFile *CheckLump(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) FResourceFile *CheckLump(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{ {
// always succeeds // always succeeds
auto rf = new FLumpFile(filename, file); auto rf = new FLumpFile(filename, file, sp);
if (rf->Open(filter)) return rf; if (rf->Open(filter)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader file = std::move(rf->Reader); // to avoid destruction of reader
delete rf; delete rf;
return NULL; return NULL;
} }
}

View file

@ -32,10 +32,11 @@
** **
*/ */
#include "resourcefile.h" #include "resourcefile_internal.h"
using namespace fs_private; namespace FileSys {
using namespace byteswap;
//========================================================================== //==========================================================================
// //
// //
@ -65,7 +66,7 @@ struct dpackheader_t
class FPakFile : public FUncompressedFile class FPakFile : public FUncompressedFile
{ {
public: public:
FPakFile(const char * filename, FileReader &file); FPakFile(const char * filename, FileReader &file, StringPool* sp);
bool Open(LumpFilterInfo* filter); bool Open(LumpFilterInfo* filter);
}; };
@ -78,8 +79,8 @@ public:
// //
//========================================================================== //==========================================================================
FPakFile::FPakFile(const char *filename, FileReader &file) FPakFile::FPakFile(const char *filename, FileReader &file, StringPool* sp)
: FUncompressedFile(filename, file) : FUncompressedFile(filename, file, sp)
{ {
} }
@ -105,7 +106,7 @@ bool FPakFile::Open(LumpFilterInfo* filter)
for(uint32_t i = 0; i < NumLumps; i++) for(uint32_t i = 0; i < NumLumps; i++)
{ {
Lumps[i].LumpNameSetup(fileinfo[i].name); Lumps[i].LumpNameSetup(fileinfo[i].name, stringpool);
Lumps[i].Flags = LUMPF_FULLPATH; Lumps[i].Flags = LUMPF_FULLPATH;
Lumps[i].Owner = this; Lumps[i].Owner = this;
Lumps[i].Position = LittleLong(fileinfo[i].filepos); Lumps[i].Position = LittleLong(fileinfo[i].filepos);
@ -124,7 +125,7 @@ bool FPakFile::Open(LumpFilterInfo* filter)
// //
//========================================================================== //==========================================================================
FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{ {
char head[4]; char head[4];
@ -135,7 +136,7 @@ FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo*
file.Seek(0, FileReader::SeekSet); file.Seek(0, FileReader::SeekSet);
if (!memcmp(head, "PACK", 4)) if (!memcmp(head, "PACK", 4))
{ {
auto rf = new FPakFile(filename, file); auto rf = new FPakFile(filename, file, sp);
if (rf->Open(filter)) return rf; if (rf->Open(filter)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader file = std::move(rf->Reader); // to avoid destruction of reader
@ -145,3 +146,4 @@ FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo*
return NULL; return NULL;
} }
}

View file

@ -33,10 +33,11 @@
** **
*/ */
#include "resourcefile.h" #include "resourcefile_internal.h"
#include "fs_swap.h" #include "fs_swap.h"
using namespace fs_private; namespace FileSys {
using namespace byteswap;
//========================================================================== //==========================================================================
// //
@ -110,7 +111,7 @@ class FRFFFile : public FResourceFile
FRFFLump *Lumps; FRFFLump *Lumps;
public: public:
FRFFFile(const char * filename, FileReader &file); FRFFFile(const char * filename, FileReader &file, StringPool* sp);
virtual ~FRFFFile(); virtual ~FRFFFile();
virtual bool Open(LumpFilterInfo* filter); virtual bool Open(LumpFilterInfo* filter);
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
@ -123,8 +124,8 @@ public:
// //
//========================================================================== //==========================================================================
FRFFFile::FRFFFile(const char *filename, FileReader &file) FRFFFile::FRFFFile(const char *filename, FileReader &file, StringPool* sp)
: FResourceFile(filename, file) : FResourceFile(filename, file, sp)
{ {
Lumps = NULL; Lumps = NULL;
} }
@ -172,7 +173,7 @@ bool FRFFFile::Open(LumpFilterInfo*)
name[len+2] = lumps[i].Extension[1]; name[len+2] = lumps[i].Extension[1];
name[len+3] = lumps[i].Extension[2]; name[len+3] = lumps[i].Extension[2];
name[len+4] = 0; name[len+4] = 0;
Lumps[i].LumpNameSetup(name); Lumps[i].LumpNameSetup(name, stringpool);
} }
delete[] lumps; delete[] lumps;
GenerateHash(); GenerateHash();
@ -238,7 +239,7 @@ int FRFFLump::FillCache()
// //
//========================================================================== //==========================================================================
FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{ {
char head[4]; char head[4];
@ -249,7 +250,7 @@ FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo*
file.Seek(0, FileReader::SeekSet); file.Seek(0, FileReader::SeekSet);
if (!memcmp(head, "RFF\x1a", 4)) if (!memcmp(head, "RFF\x1a", 4))
{ {
auto rf = new FRFFFile(filename, file); auto rf = new FRFFFile(filename, file, sp);
if (rf->Open(filter)) return rf; if (rf->Open(filter)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader file = std::move(rf->Reader); // to avoid destruction of reader
@ -260,4 +261,4 @@ FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo*
} }
}

View file

@ -33,8 +33,9 @@
** **
*/ */
#include "resourcefile.h" #include "resourcefile_internal.h"
namespace FileSys {
//========================================================================== //==========================================================================
// //
// Build GRP file // Build GRP file
@ -44,7 +45,7 @@
class FSSIFile : public FUncompressedFile class FSSIFile : public FUncompressedFile
{ {
public: public:
FSSIFile(const char * filename, FileReader &file); FSSIFile(const char * filename, FileReader &file, StringPool* sp);
bool Open(int version, int lumpcount, LumpFilterInfo* filter); bool Open(int version, int lumpcount, LumpFilterInfo* filter);
}; };
@ -55,8 +56,8 @@ public:
// //
//========================================================================== //==========================================================================
FSSIFile::FSSIFile(const char *filename, FileReader &file) FSSIFile::FSSIFile(const char *filename, FileReader &file, StringPool* sp)
: FUncompressedFile(filename, file) : FUncompressedFile(filename, file, sp)
{ {
} }
@ -85,7 +86,7 @@ bool FSSIFile::Open(int version, int lumpcount, LumpFilterInfo*)
int flength = Reader.ReadInt32(); int flength = Reader.ReadInt32();
Lumps[i].LumpNameSetup(fn); Lumps[i].LumpNameSetup(fn, stringpool);
Lumps[i].Position = j; Lumps[i].Position = j;
Lumps[i].LumpSize = flength; Lumps[i].LumpSize = flength;
Lumps[i].Owner = this; Lumps[i].Owner = this;
@ -94,7 +95,7 @@ bool FSSIFile::Open(int version, int lumpcount, LumpFilterInfo*)
// SSI files can swap the order of the extension's characters - but there's no reliable detection for this and it can be mixed inside the same container, // SSI files can swap the order of the extension's characters - but there's no reliable detection for this and it can be mixed inside the same container,
// so we have no choice but to create another file record for the altered name. // so we have no choice but to create another file record for the altered name.
std::swap(fn[strlength - 1], fn[strlength - 3]); std::swap(fn[strlength - 1], fn[strlength - 3]);
Lumps[i+1].LumpNameSetup(fn); Lumps[i+1].LumpNameSetup(fn, stringpool);
Lumps[i+1].Position = j; Lumps[i+1].Position = j;
Lumps[i+1].LumpSize = flength; Lumps[i+1].LumpSize = flength;
Lumps[i+1].Owner = this; Lumps[i+1].Owner = this;
@ -114,7 +115,7 @@ bool FSSIFile::Open(int version, int lumpcount, LumpFilterInfo*)
// //
//========================================================================== //==========================================================================
FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{ {
char zerobuf[72]; char zerobuf[72];
char buf[72]; char buf[72];
@ -144,7 +145,7 @@ FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo*
{ {
if (!skipstring(70)) return nullptr; if (!skipstring(70)) return nullptr;
} }
auto ssi = new FSSIFile(filename, file); auto ssi = new FSSIFile(filename, file, sp);
if (ssi->Open(version, numfiles, filter)) return ssi; if (ssi->Open(version, numfiles, filter)) return ssi;
file = std::move(ssi->Reader); // to avoid destruction of reader file = std::move(ssi->Reader); // to avoid destruction of reader
delete ssi; delete ssi;
@ -152,3 +153,5 @@ FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo*
} }
return nullptr; return nullptr;
} }
}

View file

@ -35,11 +35,11 @@
#include <ctype.h> #include <ctype.h>
#include "resourcefile.h" #include "resourcefile.h"
#include "filesystem.h" #include "fs_filesystem.h"
#include "fs_swap.h" #include "fs_swap.h"
using namespace fs_private; namespace FileSys {
using namespace byteswap;
struct wadinfo_t struct wadinfo_t
{ {
@ -136,7 +136,7 @@ class FWadFile : public FResourceFile
void SkinHack (FileSystemMessageFunc Printf); void SkinHack (FileSystemMessageFunc Printf);
public: public:
FWadFile(const char * filename, FileReader &file); FWadFile(const char * filename, FileReader &file, StringPool* sp);
FResourceLump *GetLump(int lump) { return &Lumps[lump]; } FResourceLump *GetLump(int lump) { return &Lumps[lump]; }
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
}; };
@ -150,8 +150,8 @@ public:
// //
//========================================================================== //==========================================================================
FWadFile::FWadFile(const char *filename, FileReader &file) FWadFile::FWadFile(const char *filename, FileReader &file, StringPool* sp)
: FResourceFile(filename, file) : FResourceFile(filename, file, sp)
{ {
} }
@ -183,7 +183,7 @@ bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf)
// Check again to detect broken wads // Check again to detect broken wads
if (InfoTableOfs + NumLumps*sizeof(wadlump_t) > (unsigned)wadSize) if (InfoTableOfs + NumLumps*sizeof(wadlump_t) > (unsigned)wadSize)
{ {
Printf(FSMessageLevel::Error, "%s: Bad directory offset.\n", FileName.c_str()); Printf(FSMessageLevel::Error, "%s: Bad directory offset.\n", FileName);
return false; return false;
} }
} }
@ -207,7 +207,7 @@ bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf)
#else #else
Lumps[i].Compressed = false; Lumps[i].Compressed = false;
#endif #endif
Lumps[i].LumpNameSetup(n); Lumps[i].LumpNameSetup(n, stringpool);
Lumps[i].Owner = this; Lumps[i].Owner = this;
Lumps[i].Position = isBigEndian ? BigLong(fileinfo[i].FilePos) : LittleLong(fileinfo[i].FilePos); Lumps[i].Position = isBigEndian ? BigLong(fileinfo[i].FilePos) : LittleLong(fileinfo[i].FilePos);
@ -220,8 +220,8 @@ bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf)
{ {
if (Lumps[i].LumpSize != 0) if (Lumps[i].LumpSize != 0)
{ {
Printf(FSMessageLevel::Warning, "%s: Lump %s contains invalid positioning info and will be ignored\n", FileName.c_str(), Lumps[i].getName()); Printf(FSMessageLevel::Warning, "%s: Lump %s contains invalid positioning info and will be ignored\n", FileName, Lumps[i].getName());
Lumps[i].LumpNameSetup(""); Lumps[i].clearName();
} }
Lumps[i].LumpSize = Lumps[i].Position = 0; Lumps[i].LumpSize = Lumps[i].Position = 0;
} }
@ -305,7 +305,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
{ {
if (numendmarkers == 0) return; // no markers found if (numendmarkers == 0) return; // no markers found
Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.c_str(), endmarker, startmarker); Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker);
if (flathack) if (flathack)
@ -319,7 +319,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
{ {
// We can't add this to the flats namespace but // We can't add this to the flats namespace but
// it needs to be flagged for the texture manager. // it needs to be flagged for the texture manager.
Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName.c_str(), Lumps[ii].getName()); Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName, Lumps[ii].getName());
Lumps[ii].Flags |= LUMPF_MAYBEFLAT; Lumps[ii].Flags |= LUMPF_MAYBEFLAT;
} }
} }
@ -333,7 +333,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
int start, end; int start, end;
if (markers[i].markertype != 0) if (markers[i].markertype != 0)
{ {
Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.c_str(), endmarker, startmarker); Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker);
i++; i++;
continue; continue;
} }
@ -342,21 +342,21 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
// skip over subsequent x_START markers // skip over subsequent x_START markers
while (i < markers.Size() && markers[i].markertype == 0) while (i < markers.Size() && markers[i].markertype == 0)
{ {
Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName.c_str(), startmarker); Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, startmarker);
i++; i++;
continue; continue;
} }
// same for x_END markers // same for x_END markers
while (i < markers.Size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1)) while (i < markers.Size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1))
{ {
Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName.c_str(), endmarker); Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, endmarker);
i++; i++;
continue; continue;
} }
// We found a starting marker but no end marker. Ignore this block. // We found a starting marker but no end marker. Ignore this block.
if (i >= markers.Size()) if (i >= markers.Size())
{ {
Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.c_str(), startmarker, endmarker); Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, startmarker, endmarker);
end = NumLumps; end = NumLumps;
} }
else else
@ -365,14 +365,14 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
} }
// we found a marked block // we found a marked block
Printf(FSMessageLevel::DebugNotify, "%s: Found %s block at (%d-%d)\n", FileName.c_str(), startmarker, markers[start].index, end); Printf(FSMessageLevel::DebugNotify, "%s: Found %s block at (%d-%d)\n", FileName, startmarker, markers[start].index, end);
for(int j = markers[start].index + 1; j < end; j++) for(int j = markers[start].index + 1; j < end; j++)
{ {
if (Lumps[j].Namespace != ns_global) if (Lumps[j].Namespace != ns_global)
{ {
if (!warned) if (!warned)
{ {
Printf(FSMessageLevel::Warning, "%s: Overlapping namespaces found (lump %d)\n", FileName.c_str(), j); Printf(FSMessageLevel::Warning, "%s: Overlapping namespaces found (lump %d)\n", FileName, j);
} }
warned = true; warned = true;
} }
@ -382,7 +382,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
// ignore sprite lumps smaller than 8 bytes (the smallest possible) // ignore sprite lumps smaller than 8 bytes (the smallest possible)
// in size -- this was used by some dmadds wads // in size -- this was used by some dmadds wads
// as an 'empty' graphics resource // as an 'empty' graphics resource
Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName.c_str(), Lumps[j].getName(), j); Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName, Lumps[j].getName(), j);
} }
else else
{ {
@ -420,7 +420,7 @@ void FWadFile::SkinHack (FileSystemMessageFunc Printf)
if (!strnicmp(lump->getName(), "S_SKIN", 6)) if (!strnicmp(lump->getName(), "S_SKIN", 6))
{ // Wad has at least one skin. { // Wad has at least one skin.
lump->LumpNameSetup("S_SKIN"); lump->LumpNameSetup("S_SKIN", nullptr);
if (!skinned) if (!skinned)
{ {
skinned = true; skinned = true;
@ -452,7 +452,7 @@ void FWadFile::SkinHack (FileSystemMessageFunc Printf)
} }
if (skinned && hasmap) if (skinned && hasmap)
{ {
Printf(FSMessageLevel::Attention, "%s: The maps will not be loaded because it has a skin.\n", FileName.c_str()); Printf(FSMessageLevel::Attention, "%s: The maps will not be loaded because it has a skin.\n", FileName);
Printf(FSMessageLevel::Attention, "You should remove the skin from the wad to play these maps.\n"); Printf(FSMessageLevel::Attention, "You should remove the skin from the wad to play these maps.\n");
} }
} }
@ -464,7 +464,7 @@ void FWadFile::SkinHack (FileSystemMessageFunc Printf)
// //
//========================================================================== //==========================================================================
FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{ {
char head[4]; char head[4];
@ -475,7 +475,7 @@ FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo*
file.Seek(0, FileReader::SeekSet); file.Seek(0, FileReader::SeekSet);
if (!memcmp(head, "IWAD", 4) || !memcmp(head, "PWAD", 4)) if (!memcmp(head, "IWAD", 4) || !memcmp(head, "PWAD", 4))
{ {
auto rf = new FWadFile(filename, file); auto rf = new FWadFile(filename, file, sp);
if (rf->Open(filter, Printf)) return rf; if (rf->Open(filter, Printf)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader file = std::move(rf->Reader); // to avoid destruction of reader
@ -485,3 +485,4 @@ FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo*
return NULL; return NULL;
} }
}

View file

@ -34,10 +34,12 @@
** **
*/ */
#include "resourcefile.h" #include "resourcefile_internal.h"
#include "fs_stringpool.h"
#include "fs_swap.h" #include "fs_swap.h"
using namespace fs_private; namespace FileSys {
using namespace byteswap;
//========================================================================== //==========================================================================
// //
@ -47,9 +49,9 @@ using namespace fs_private;
class FWHResFile : public FUncompressedFile class FWHResFile : public FUncompressedFile
{ {
std::string basename; const char* BaseName;
public: public:
FWHResFile(const char * filename, FileReader &file); FWHResFile(const char * filename, FileReader &file, StringPool* sp);
bool Open(LumpFilterInfo* filter); bool Open(LumpFilterInfo* filter);
}; };
@ -60,10 +62,10 @@ public:
// //
//========================================================================== //==========================================================================
FWHResFile::FWHResFile(const char *filename, FileReader &file) FWHResFile::FWHResFile(const char *filename, FileReader &file, StringPool* sp)
: FUncompressedFile(filename, file) : FUncompressedFile(filename, file, sp)
{ {
basename = ExtractBaseName(filename, false); BaseName = stringpool->Strdup(ExtractBaseName(filename, false).c_str());
} }
//========================================================================== //==========================================================================
@ -91,8 +93,9 @@ bool FWHResFile::Open(LumpFilterInfo*)
if (length == 0) break; if (length == 0) break;
char num[5]; char num[5];
snprintf(num, 5, "/%04d", k); snprintf(num, 5, "/%04d", k);
std::string synthname = basename + num; std::string synthname = BaseName;
Lumps[i].LumpNameSetup(synthname.c_str()); synthname += num;
Lumps[i].LumpNameSetup(synthname.c_str(), stringpool);
Lumps[i].Owner = this; Lumps[i].Owner = this;
Lumps[i].Position = offset; Lumps[i].Position = offset;
Lumps[i].LumpSize = length; Lumps[i].LumpSize = length;
@ -111,7 +114,7 @@ bool FWHResFile::Open(LumpFilterInfo*)
// //
//========================================================================== //==========================================================================
FResourceFile *CheckWHRes(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) FResourceFile *CheckWHRes(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{ {
if (file.GetLength() >= 8192) // needs to be at least 8192 to contain one file and the directory. if (file.GetLength() >= 8192) // needs to be at least 8192 to contain one file and the directory.
{ {
@ -131,7 +134,7 @@ FResourceFile *CheckWHRes(const char *filename, FileReader &file, LumpFilterInfo
if (offset != checkpos || length == 0 || offset + length >= (size_t)size - 4096 ) return nullptr; if (offset != checkpos || length == 0 || offset + length >= (size_t)size - 4096 ) return nullptr;
checkpos += (length+4095) / 4096; checkpos += (length+4095) / 4096;
} }
auto rf = new FWHResFile(filename, file); auto rf = new FWHResFile(filename, file, sp);
if (rf->Open(filter)) return rf; if (rf->Open(filter)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader file = std::move(rf->Reader); // to avoid destruction of reader
delete rf; delete rf;
@ -139,3 +142,4 @@ FResourceFile *CheckWHRes(const char *filename, FileReader &file, LumpFilterInfo
return NULL; return NULL;
} }
}

View file

@ -41,7 +41,8 @@
#include "fs_findfile.h" #include "fs_findfile.h"
#include "fs_swap.h" #include "fs_swap.h"
using namespace fs_private; namespace FileSys {
using namespace byteswap;
#define BUFREADCOMMENT (0x400) #define BUFREADCOMMENT (0x400)
@ -164,8 +165,8 @@ static uint32_t Zip_FindCentralDir(FileReader &fin, bool* zip64)
// //
//========================================================================== //==========================================================================
FZipFile::FZipFile(const char * filename, FileReader &file) FZipFile::FZipFile(const char * filename, FileReader &file, StringPool* sp)
: FResourceFile(filename, file) : FResourceFile(filename, file, sp)
{ {
Lumps = NULL; Lumps = NULL;
} }
@ -180,7 +181,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
if (centraldir == 0) if (centraldir == 0)
{ {
Printf(FSMessageLevel::Error, "%s: ZIP file corrupt!\n", FileName.c_str()); Printf(FSMessageLevel::Error, "%s: ZIP file corrupt!\n", FileName);
return false; return false;
} }
@ -196,7 +197,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
if (info.NumEntries != info.NumEntriesOnAllDisks || if (info.NumEntries != info.NumEntriesOnAllDisks ||
info.FirstDisk != 0 || info.DiskNumber != 0) info.FirstDisk != 0 || info.DiskNumber != 0)
{ {
Printf(FSMessageLevel::Error, "%s: Multipart Zip files are not supported.\n", FileName.c_str()); Printf(FSMessageLevel::Error, "%s: Multipart Zip files are not supported.\n", FileName);
return false; return false;
} }
@ -215,7 +216,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
if (info.NumEntries != info.NumEntriesOnAllDisks || if (info.NumEntries != info.NumEntriesOnAllDisks ||
info.FirstDisk != 0 || info.DiskNumber != 0) info.FirstDisk != 0 || info.DiskNumber != 0)
{ {
Printf(FSMessageLevel::Error, "%s: Multipart Zip files are not supported.\n", FileName.c_str()); Printf(FSMessageLevel::Error, "%s: Multipart Zip files are not supported.\n", FileName);
return false; return false;
} }
@ -254,35 +255,36 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file. if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file.
{ {
free(directory); free(directory);
Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName.c_str()); Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName);
return false; return false;
} }
for (auto& c : name) c = tolower(c); for (auto& c : name) c = tolower(c);
if (name.find_first_of("filter/") == 0) auto vv = name.find("__macosx");
if (name.find("filter/") == 0)
continue; // 'filter' is a reserved name of the file system. continue; // 'filter' is a reserved name of the file system.
if (name.find_first_of("__macosx") == 0) if (name.find("__macosx") == 0)
continue; // skip Apple garbage. At this stage only the root folder matters. continue; // skip Apple garbage. At this stage only the root folder matters.
if (name.find_first_of(".bat") != std::string::npos || name.find_first_of(".exe") != std::string::npos) if (name.find(".bat") != std::string::npos || name.find(".exe") != std::string::npos)
continue; // also ignore executables for this. continue; // also ignore executables for this.
if (!foundprefix) if (!foundprefix)
{ {
// check for special names, if one of these gets found this must be treated as a normal zip. // check for special names, if one of these gets found this must be treated as a normal zip.
bool isspecial = name.find_first_of("/") == std::string::npos || bool isspecial = name.find("/") == std::string::npos ||
(filter && std::find(filter->reservedFolders.begin(), filter->reservedFolders.end(), name) != filter->reservedFolders.end()); (filter && std::find(filter->reservedFolders.begin(), filter->reservedFolders.end(), name) != filter->reservedFolders.end());
if (isspecial) break; if (isspecial) break;
name0 = std::string(name, 0, name.find_last_of("/")+1); name0 = std::string(name, 0, name.rfind("/")+1);
name1 = std::string(name, 0, name.find_first_of("/") + 1); name1 = std::string(name, 0, name.find("/") + 1);
foundprefix = true; foundprefix = true;
} }
if (name.find_first_of(name0) != 0) if (name.find(name0) != 0)
{ {
if (!name1.empty()) if (!name1.empty())
{ {
name0 = name1; name0 = name1;
if (name.find_first_of(name0) != 0) if (name.find(name0) != 0)
{ {
name0 = ""; name0 = "";
} }
@ -295,7 +297,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
// at least one of the more common definition lumps must be present. // at least one of the more common definition lumps must be present.
for (auto &p : filter->requiredPrefixes) for (auto &p : filter->requiredPrefixes)
{ {
if (name.find_first_of(name0 + p) == 0 || name.find_last_of(p) == ptrdiff_t(name.length() - p.length())) if (name.find(name0 + p) == 0 || name.rfind(p) == ptrdiff_t(name.length() - p.length()))
{ {
foundspeciallump = true; foundspeciallump = true;
break; break;
@ -322,11 +324,11 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file. if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file.
{ {
free(directory); free(directory);
Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName.c_str()); Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName);
return false; return false;
} }
if (name.find_first_of("__macosx") == 0 || name.find_first_of("__MACOSX") == 0) if (name.find("__macosx") == 0 || name.find("__MACOSX") == 0)
{ {
skipped++; skipped++;
continue; // Weed out Apple's resource fork garbage right here because it interferes with safe operation. continue; // Weed out Apple's resource fork garbage right here because it interferes with safe operation.
@ -349,7 +351,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
zip_fh->Method != METHOD_IMPLODE && zip_fh->Method != METHOD_IMPLODE &&
zip_fh->Method != METHOD_SHRINK) zip_fh->Method != METHOD_SHRINK)
{ {
Printf(FSMessageLevel::Error, "%s: '%s' uses an unsupported compression algorithm (#%d).\n", FileName.c_str(), name.c_str(), zip_fh->Method); Printf(FSMessageLevel::Error, "%s: '%s' uses an unsupported compression algorithm (#%d).\n", FileName, name.c_str(), zip_fh->Method);
skipped++; skipped++;
continue; continue;
} }
@ -357,7 +359,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
zip_fh->Flags = LittleShort(zip_fh->Flags); zip_fh->Flags = LittleShort(zip_fh->Flags);
if (zip_fh->Flags & ZF_ENCRYPTED) if (zip_fh->Flags & ZF_ENCRYPTED)
{ {
Printf(FSMessageLevel::Error, "%s: '%s' is encrypted. Encryption is not supported.\n", FileName.c_str(), name.c_str()); Printf(FSMessageLevel::Error, "%s: '%s' is encrypted. Encryption is not supported.\n", FileName, name.c_str());
skipped++; skipped++;
continue; continue;
} }
@ -384,7 +386,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
if (zip_64->CompressedSize > 0x7fffffff || zip_64->UncompressedSize > 0x7fffffff) if (zip_64->CompressedSize > 0x7fffffff || zip_64->UncompressedSize > 0x7fffffff)
{ {
// The file system is limited to 32 bit file sizes; // The file system is limited to 32 bit file sizes;
Printf(FSMessageLevel::Warning, "%s: '%s' is too large.\n", FileName.c_str(), name.c_str()); Printf(FSMessageLevel::Warning, "%s: '%s' is too large.\n", FileName, name.c_str());
skipped++; skipped++;
continue; continue;
} }
@ -395,7 +397,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
} }
} }
lump_p->LumpNameSetup(name.c_str()); lump_p->LumpNameSetup(name.c_str(), stringpool);
lump_p->LumpSize = UncompressedSize; lump_p->LumpSize = UncompressedSize;
lump_p->Owner = this; lump_p->Owner = this;
// The start of the Reader will be determined the first time it is accessed. // The start of the Reader will be determined the first time it is accessed.
@ -531,7 +533,7 @@ int FZipLump::GetFileOffset()
// //
//========================================================================== //==========================================================================
FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf) FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{ {
char head[4]; char head[4];
@ -542,7 +544,7 @@ FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo*
file.Seek(0, FileReader::SeekSet); file.Seek(0, FileReader::SeekSet);
if (!memcmp(head, "PK\x3\x4", 4)) if (!memcmp(head, "PK\x3\x4", 4))
{ {
auto rf = new FZipFile(filename, file); auto rf = new FZipFile(filename, file, sp);
if (rf->Open(filter, Printf)) return rf; if (rf->Open(filter, Printf)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader file = std::move(rf->Reader); // to avoid destruction of reader
@ -719,3 +721,5 @@ bool WriteZip(const char* filename, const FCompressedBuffer* content, size_t con
} }
return false; return false;
} }
}

View file

@ -3,6 +3,7 @@
#include "resourcefile.h" #include "resourcefile.h"
namespace FileSys {
//========================================================================== //==========================================================================
// //
// Zip Lump // Zip Lump
@ -39,11 +40,12 @@ class FZipFile : public FResourceFile
FZipLump *Lumps; FZipLump *Lumps;
public: public:
FZipFile(const char * filename, FileReader &file); FZipFile(const char * filename, FileReader &file, StringPool* sp);
virtual ~FZipFile(); virtual ~FZipFile();
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
}; };
}
#endif #endif

View file

@ -34,9 +34,9 @@
*/ */
#include <string> #include <string>
#include "files.h" #include "files_internal.h"
using namespace fs_private; namespace FileSys {
#ifdef _WIN32 #ifdef _WIN32
std::wstring toWide(const char* str); std::wstring toWide(const char* str);
@ -345,7 +345,7 @@ public:
void UpdateBuffer() void UpdateBuffer()
{ {
bufptr = (const char*)&buf[0]; bufptr = (const char*)buf.data();
FilePos = 0; FilePos = 0;
Length = (long)buf.size(); Length = (long)buf.size();
} }
@ -476,12 +476,14 @@ long FileWriter::Seek(long offset, int mode)
size_t FileWriter::Printf(const char *fmt, ...) size_t FileWriter::Printf(const char *fmt, ...)
{ {
char c[300];
va_list arglist; va_list arglist;
va_start(arglist, fmt); va_start(arglist, fmt);
auto n = snprintf(nullptr, 0, fmt, arglist); auto n = vsnprintf(c, 300, fmt, arglist);
std::string buf; std::string buf;
buf.resize(n); buf.resize(n);
snprintf(&buf.front(), n, fmt, arglist); va_start(arglist, fmt);
vsnprintf(&buf.front(), n, fmt, arglist);
va_end(arglist); va_end(arglist);
return Write(buf.c_str(), n); return Write(buf.c_str(), n);
} }
@ -492,3 +494,5 @@ size_t BufferWriter::Write(const void *buffer, size_t len)
memcpy(&mBuffer[ofs], buffer, len); memcpy(&mBuffer[ofs], buffer, len);
return len; return len;
} }
}

View file

@ -41,7 +41,30 @@
#include <algorithm> #include <algorithm>
#include <stdexcept> #include <stdexcept>
#include "files.h" #include "fs_files.h"
namespace FileSys {
using namespace byteswap;
class DecompressorBase : public FileReaderInterface
{
bool exceptions = false;
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 SetOwnsReader();
void EnableExceptions(bool on) { exceptions = on; }
protected:
FileReader* File = nullptr;
FileReader OwnedFile;
};
//========================================================================== //==========================================================================
// //
@ -538,7 +561,7 @@ class DecompressorLZSS : public DecompressorBase
return false; return false;
Stream.AvailIn -= 2; Stream.AvailIn -= 2;
uint16_t pos = fs_private::BigShort(*(uint16_t*)Stream.In); uint16_t pos = BigShort(*(uint16_t*)Stream.In);
uint8_t len = (pos & 0xF)+1; uint8_t len = (pos & 0xF)+1;
pos >>= 4; pos >>= 4;
Stream.In += 2; Stream.In += 2;
@ -752,3 +775,4 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, b
} }
} }
}

View file

@ -0,0 +1,31 @@
#pragma once
#include "fs_files.h"
namespace FileSys {
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; }
};
}

View file

@ -41,9 +41,13 @@
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include "filesystem.h" #include "resourcefile_internal.h"
#include "fs_filesystem.h"
#include "fs_findfile.h" #include "fs_findfile.h"
#include "md5.hpp" #include "md5.hpp"
#include "fs_stringpool.h"
namespace FileSys {
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -59,15 +63,19 @@ static void UpperCopy(char* to, const char* from)
to[i] = 0; to[i] = 0;
} }
static int MakeHash(const void* data, unsigned length = -1)
//djb2
static uint32_t MakeHash(const char* str, size_t length = SIZE_MAX)
{ {
if (length == -1) length = (unsigned)strlen((const char*)data); uint32_t hash = 5381;
return crc32(0, (const Bytef*)data, length); uint32_t c;
while (length-- > 0 && (c = *str++)) hash = hash * 33 + (c | 32);
return hash;
} }
static void md5Hash(FileReader& reader, uint8_t* digest) static void md5Hash(FileReader& reader, uint8_t* digest)
{ {
using namespace fs_private::md5; using namespace md5;
md5_state_t state; md5_state_t state;
md5_init(&state); md5_init(&state);
@ -84,13 +92,13 @@ struct FileSystem::LumpRecord
{ {
FResourceLump *lump; FResourceLump *lump;
LumpShortName shortName; LumpShortName shortName;
std::string longName; const char* LongName;
int rfnum; int rfnum;
int Namespace; int Namespace;
int resourceId; int resourceId;
int flags; int flags;
void SetFromLump(int filenum, FResourceLump* lmp) void SetFromLump(int filenum, FResourceLump* lmp, StringPool* sp)
{ {
lump = lmp; lump = lmp;
rfnum = filenum; rfnum = filenum;
@ -100,61 +108,63 @@ struct FileSystem::LumpRecord
{ {
UpperCopy(shortName.String, lump->getName()); UpperCopy(shortName.String, lump->getName());
shortName.String[8] = 0; shortName.String[8] = 0;
longName = ""; LongName = "";
Namespace = lump->GetNamespace(); Namespace = lump->GetNamespace();
resourceId = -1; resourceId = -1;
} }
else if ((lump->Flags & LUMPF_EMBEDDED) || !lump->getName() || !*lump->getName()) else if ((lump->Flags & LUMPF_EMBEDDED) || !lump->getName() || !*lump->getName())
{ {
shortName.qword = 0; shortName.qword = 0;
longName = ""; LongName = "";
Namespace = ns_hidden; Namespace = ns_hidden;
resourceId = -1; resourceId = -1;
} }
else else
{ {
longName = lump->getName(); LongName = lump->getName();
resourceId = lump->GetIndexNum(); resourceId = lump->GetIndexNum();
// Map some directories to WAD namespaces. // Map some directories to WAD namespaces.
// Note that some of these namespaces don't exist in WADS. // Note that some of these namespaces don't exist in WADS.
// CheckNumForName will handle any request for these namespaces accordingly. // CheckNumForName will handle any request for these namespaces accordingly.
Namespace = !strncmp(longName.c_str(), "flats/", 6) ? ns_flats : Namespace = !strncmp(LongName, "flats/", 6) ? ns_flats :
!strncmp(longName.c_str(), "textures/", 9) ? ns_newtextures : !strncmp(LongName, "textures/", 9) ? ns_newtextures :
!strncmp(longName.c_str(), "hires/", 6) ? ns_hires : !strncmp(LongName, "hires/", 6) ? ns_hires :
!strncmp(longName.c_str(), "sprites/", 8) ? ns_sprites : !strncmp(LongName, "sprites/", 8) ? ns_sprites :
!strncmp(longName.c_str(), "voxels/", 7) ? ns_voxels : !strncmp(LongName, "voxels/", 7) ? ns_voxels :
!strncmp(longName.c_str(), "colormaps/", 10) ? ns_colormaps : !strncmp(LongName, "colormaps/", 10) ? ns_colormaps :
!strncmp(longName.c_str(), "acs/", 4) ? ns_acslibrary : !strncmp(LongName, "acs/", 4) ? ns_acslibrary :
!strncmp(longName.c_str(), "voices/", 7) ? ns_strifevoices : !strncmp(LongName, "voices/", 7) ? ns_strifevoices :
!strncmp(longName.c_str(), "patches/", 8) ? ns_patches : !strncmp(LongName, "patches/", 8) ? ns_patches :
!strncmp(longName.c_str(), "graphics/", 9) ? ns_graphics : !strncmp(LongName, "graphics/", 9) ? ns_graphics :
!strncmp(longName.c_str(), "sounds/", 7) ? ns_sounds : !strncmp(LongName, "sounds/", 7) ? ns_sounds :
!strncmp(longName.c_str(), "music/", 6) ? ns_music : !strncmp(LongName, "music/", 6) ? ns_music :
!strchr(longName.c_str(), '/') ? ns_global : !strchr(LongName, '/') ? ns_global :
ns_hidden; ns_hidden;
if (Namespace == ns_hidden) shortName.qword = 0; if (Namespace == ns_hidden) shortName.qword = 0;
else else if (strstr(LongName, ".{"))
{ {
std::string longName = LongName;
ptrdiff_t encodedResID = longName.find_last_of(".{"); ptrdiff_t encodedResID = longName.find_last_of(".{");
if (resourceId == -1 && encodedResID != std::string::npos) if (resourceId == -1 && encodedResID != std::string::npos)
{ {
const char* p = longName.c_str() + encodedResID; const char* p = LongName + encodedResID;
char* q; char* q;
int id = (int)strtoull(p+2, &q, 10); // only decimal numbers allowed here. int id = (int)strtoull(p + 2, &q, 10); // only decimal numbers allowed here.
if (q[0] == '}' && (q[1] == '.' || q[1] == 0)) if (q[0] == '}' && (q[1] == '.' || q[1] == 0))
{ {
longName.erase(longName.begin() + encodedResID, longName.begin() + (q - p) + 1); longName.erase(longName.begin() + encodedResID, longName.begin() + (q - p) + 1);
resourceId = id; resourceId = id;
} }
LongName = sp->Strdup(longName.c_str());
} }
ptrdiff_t slash = longName.find_last_of('/'); }
std::string base = (slash != std::string::npos) ? longName.c_str() + (slash + 1) : longName.c_str(); auto slash = strrchr(LongName, '/');
std::string base = slash ? (slash + 1) : LongName;
auto dot = base.find_last_of('.'); auto dot = base.find_last_of('.');
if (dot != std::string::npos) base.resize(dot); if (dot != std::string::npos) base.resize(dot);
UpperCopy(shortName.String, base.c_str()); UpperCopy(shortName.String, base.c_str());
shortName.String[8] = 0;
// Since '\' can't be used as a file name's part inside a ZIP // Since '\' can't be used as a file name's part inside a ZIP
// we have to work around this for sprites because it is a valid // we have to work around this for sprites because it is a valid
@ -170,7 +180,6 @@ struct FileSystem::LumpRecord
} }
} }
} }
}
}; };
// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -181,13 +190,12 @@ static void PrintLastError (FileSystemMessageFunc Printf);
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // PUBLIC DATA DEFINITIONS -------------------------------------------------
FileSystem fileSystem;
// CODE -------------------------------------------------------------------- // CODE --------------------------------------------------------------------
FileSystem::FileSystem() FileSystem::FileSystem()
{ {
// Cannot be defaulted! This is needed to initialize the LumpRecord array, which depends on data only available here. stringpool = new StringPool;
stringpool->shared = true; // will be used by all owned resource files.
} }
FileSystem::~FileSystem () FileSystem::~FileSystem ()
@ -287,7 +295,7 @@ bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFil
void FileSystem::AddLump(FResourceLump *lump) void FileSystem::AddLump(FResourceLump *lump)
{ {
FileInfo.resize(FileInfo.size() + 1); FileInfo.resize(FileInfo.size() + 1);
FileInfo.back().SetFromLump(-1, lump); FileInfo.back().SetFromLump(-1, lump, stringpool);
} }
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
@ -300,7 +308,7 @@ void FileSystem::AddLump(FResourceLump *lump)
int FileSystem::AddExternalFile(const char *filename) int FileSystem::AddExternalFile(const char *filename)
{ {
FResourceLump *lump = new FExternalLump(filename); FResourceLump *lump = new FExternalLump(filename, -1, stringpool);
AddLump(lump); AddLump(lump);
return (int)FileInfo.size() - 1; // later return (int)FileInfo.size() - 1; // later
} }
@ -313,13 +321,24 @@ int FileSystem::AddExternalFile(const char *filename)
// //
//========================================================================== //==========================================================================
struct FMemoryLump : public FResourceLump
{
FMemoryLump(const void* data, int length)
{
RefCount = -1;
LumpSize = length;
Cache = new char[length];
memcpy(Cache, data, length);
}
};
int FileSystem::AddFromBuffer(const char* name, const char* type, char* data, int size, int id, int flags) int FileSystem::AddFromBuffer(const char* name, const char* type, char* data, int size, int id, int flags)
{ {
std::string fullname = name; std::string fullname = name;
fullname += ':'; fullname += '.';
fullname += type; fullname += type;
auto newlump = new FMemoryLump(data, size); auto newlump = new FMemoryLump(data, size);
newlump->LumpNameSetup(fullname.c_str()); newlump->LumpNameSetup(fullname.c_str(), stringpool);
AddLump(newlump); AddLump(newlump);
FileInfo.back().resourceId = id; FileInfo.back().resourceId = id;
return (int)FileInfo.size()-1; return (int)FileInfo.size()-1;
@ -375,9 +394,9 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInf
if (!isdir) if (!isdir)
resfile = FResourceFile::OpenResourceFile(filename, filereader, false, filter, Printf); resfile = FResourceFile::OpenResourceFile(filename, filereader, false, filter, Printf, stringpool);
else else
resfile = FResourceFile::OpenDirectory(filename, filter, Printf); resfile = FResourceFile::OpenDirectory(filename, filter, Printf, stringpool);
if (resfile != NULL) if (resfile != NULL)
{ {
@ -391,8 +410,8 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInf
{ {
FResourceLump *lump = resfile->GetLump(i); FResourceLump *lump = resfile->GetLump(i);
FileInfo.resize(FileInfo.size() + 1); FileInfo.resize(FileInfo.size() + 1);
FileSystem::LumpRecord *lump_p = &FileInfo.back(); FileSystem::LumpRecord* lump_p = &FileInfo.back();
lump_p->SetFromLump((int)Files.size(), lump); lump_p->SetFromLump((int)Files.size(), lump, stringpool);
} }
Files.push_back(resfile); Files.push_back(resfile);
@ -504,7 +523,7 @@ int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept
// and namespace parameter // and namespace parameter
//========================================================================== //==========================================================================
int FileSystem::CheckNumForName (const char *name, int space) int FileSystem::CheckNumForName (const char *name, int space) const
{ {
union union
{ {
@ -549,7 +568,7 @@ int FileSystem::CheckNumForName (const char *name, int space)
return i != NULL_INDEX ? i : -1; return i != NULL_INDEX ? i : -1;
} }
int FileSystem::CheckNumForName (const char *name, int space, int rfnum, bool exact) int FileSystem::CheckNumForName (const char *name, int space, int rfnum, bool exact) const
{ {
union union
{ {
@ -587,7 +606,7 @@ int FileSystem::CheckNumForName (const char *name, int space, int rfnum, bool ex
// //
//========================================================================== //==========================================================================
int FileSystem::GetNumForName (const char *name, int space) int FileSystem::GetNumForName (const char *name, int space) const
{ {
int i; int i;
@ -610,7 +629,7 @@ int FileSystem::GetNumForName (const char *name, int space)
// //
//========================================================================== //==========================================================================
int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int namespc, bool ignoreext) int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int namespc, bool ignoreext) const
{ {
uint32_t i; uint32_t i;
@ -625,12 +644,12 @@ int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int names
for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i]) for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i])
{ {
if (strnicmp(name, FileInfo[i].longName.c_str(), len)) continue; if (strnicmp(name, FileInfo[i].LongName, len)) continue;
if (FileInfo[i].longName[len] == 0) break; // this is a full match if (FileInfo[i].LongName[len] == 0) break; // this is a full match
if (ignoreext && FileInfo[i].longName[len] == '.') if (ignoreext && FileInfo[i].LongName[len] == '.')
{ {
// is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension? // is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension?
if (strpbrk(FileInfo[i].longName.c_str() + len + 1, "./") == nullptr) break; if (strpbrk(FileInfo[i].LongName + len + 1, "./") == nullptr) break;
} }
} }
@ -643,7 +662,7 @@ int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int names
return -1; return -1;
} }
int FileSystem::CheckNumForFullName (const char *name, int rfnum) int FileSystem::CheckNumForFullName (const char *name, int rfnum) const
{ {
uint32_t i; uint32_t i;
@ -655,7 +674,7 @@ int FileSystem::CheckNumForFullName (const char *name, int rfnum)
i = FirstLumpIndex_FullName[MakeHash (name) % NumEntries]; i = FirstLumpIndex_FullName[MakeHash (name) % NumEntries];
while (i != NULL_INDEX && while (i != NULL_INDEX &&
(stricmp(name, FileInfo[i].longName.c_str()) || FileInfo[i].rfnum != rfnum)) (stricmp(name, FileInfo[i].LongName) || FileInfo[i].rfnum != rfnum))
{ {
i = NextLumpIndex_FullName[i]; i = NextLumpIndex_FullName[i];
} }
@ -671,7 +690,7 @@ int FileSystem::CheckNumForFullName (const char *name, int rfnum)
// //
//========================================================================== //==========================================================================
int FileSystem::GetNumForFullName (const char *name) int FileSystem::GetNumForFullName (const char *name) const
{ {
int i; int i;
@ -691,7 +710,7 @@ int FileSystem::GetNumForFullName (const char *name)
// //
//========================================================================== //==========================================================================
int FileSystem::FindFileWithExtensions(const char* name, const char *const *exts, int count) int FileSystem::FindFileWithExtensions(const char* name, const char *const *exts, int count) const
{ {
uint32_t i; uint32_t i;
@ -706,10 +725,10 @@ int FileSystem::FindFileWithExtensions(const char* name, const char *const *exts
for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i]) for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i])
{ {
if (strnicmp(name, FileInfo[i].longName.c_str(), len)) continue; if (strnicmp(name, FileInfo[i].LongName, len)) continue;
if (FileInfo[i].longName[len] != '.') continue; // we are looking for extensions but this file doesn't have one. if (FileInfo[i].LongName[len] != '.') continue; // we are looking for extensions but this file doesn't have one.
auto cp = FileInfo[i].longName.c_str() + len + 1; auto cp = FileInfo[i].LongName + len + 1;
// is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension? // is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension?
if (strpbrk(cp, "./") != nullptr) continue; // No, so it cannot be a valid entry. if (strpbrk(cp, "./") != nullptr) continue; // No, so it cannot be a valid entry.
@ -745,7 +764,7 @@ int FileSystem::FindResource (int resid, const char *type, int filenum) const no
{ {
if (filenum > 0 && FileInfo[i].rfnum != filenum) continue; if (filenum > 0 && FileInfo[i].rfnum != filenum) continue;
if (FileInfo[i].resourceId != resid) continue; if (FileInfo[i].resourceId != resid) continue;
auto extp = strrchr(FileInfo[i].longName.c_str(), '.'); auto extp = strrchr(FileInfo[i].LongName, '.');
if (!extp) continue; if (!extp) continue;
if (!stricmp(extp + 1, type)) return i; if (!stricmp(extp + 1, type)) return i;
} }
@ -859,13 +878,13 @@ void FileSystem::InitHashChains (void)
FirstLumpIndex[j] = i; FirstLumpIndex[j] = i;
// Do the same for the full paths // Do the same for the full paths
if (!FileInfo[i].longName.empty()) if (FileInfo[i].LongName[0] != 0)
{ {
j = MakeHash(FileInfo[i].longName.c_str()) % NumEntries; j = MakeHash(FileInfo[i].LongName) % NumEntries;
NextLumpIndex_FullName[i] = FirstLumpIndex_FullName[j]; NextLumpIndex_FullName[i] = FirstLumpIndex_FullName[j];
FirstLumpIndex_FullName[j] = i; FirstLumpIndex_FullName[j] = i;
auto nameNoExt = FileInfo[i].longName; std::string nameNoExt = FileInfo[i].LongName;
auto dot = nameNoExt.find_last_of('.'); auto dot = nameNoExt.find_last_of('.');
auto slash = nameNoExt.find_last_of('/'); auto slash = nameNoExt.find_last_of('/');
if ((dot > slash || slash == std::string::npos) && dot != std::string::npos) nameNoExt.resize(dot); if ((dot > slash || slash == std::string::npos) && dot != std::string::npos) nameNoExt.resize(dot);
@ -900,7 +919,7 @@ LumpShortName& FileSystem::GetShortName(int i)
void FileSystem::RenameFile(int num, const char* newfn) void FileSystem::RenameFile(int num, const char* newfn)
{ {
if ((unsigned)num >= NumEntries) throw FileSystemException("RenameFile: Invalid index"); if ((unsigned)num >= NumEntries) throw FileSystemException("RenameFile: Invalid index");
FileInfo[num].longName = newfn; FileInfo[num].LongName = stringpool->Strdup(newfn);
// This does not alter the short name - call GetShortname to do that! // This does not alter the short name - call GetShortname to do that!
} }
@ -934,13 +953,13 @@ void FileSystem::MoveLumpsInFolder(const char *path)
{ {
auto& li = FileInfo[i]; auto& li = FileInfo[i];
if (li.rfnum >= GetIwadNum()) break; if (li.rfnum >= GetIwadNum()) break;
if (strnicmp(li.longName.c_str(), path, len) == 0) if (strnicmp(li.LongName, path, len) == 0)
{ {
FileInfo.push_back(li); FileInfo.push_back(li);
li.lump = &placeholderLump; // Make the old entry point to something empty. We cannot delete the lump record here because it'd require adjustment of all indices in the list. li.lump = &placeholderLump; // Make the old entry point to something empty. We cannot delete the lump record here because it'd require adjustment of all indices in the list.
auto &ln = FileInfo.back(); auto &ln = FileInfo.back();
ln.lump->LumpNameSetup(ln.longName.c_str() + len); ln.lump->LumpNameSetup(ln.LongName + len, stringpool); // may be able to avoid the string allocation!
ln.SetFromLump(rfnum, ln.lump); ln.SetFromLump(rfnum, ln.lump, stringpool);
} }
} }
} }
@ -956,6 +975,7 @@ void FileSystem::MoveLumpsInFolder(const char *path)
int FileSystem::FindLump (const char *name, int *lastlump, bool anyns) int FileSystem::FindLump (const char *name, int *lastlump, bool anyns)
{ {
if (*lastlump >= FileInfo.size()) return -1;
union union
{ {
char name8[8]; char name8[8];
@ -967,11 +987,11 @@ int FileSystem::FindLump (const char *name, int *lastlump, bool anyns)
assert(lastlump != NULL && *lastlump >= 0); assert(lastlump != NULL && *lastlump >= 0);
lump_p = &FileInfo[*lastlump]; lump_p = &FileInfo[*lastlump];
while (lump_p < &FileInfo[NumEntries]) while (lump_p <= &FileInfo.back())
{ {
if ((anyns || lump_p->Namespace == ns_global) && lump_p->shortName.qword == qname) if ((anyns || lump_p->Namespace == ns_global) && lump_p->shortName.qword == qname)
{ {
int lump = int(lump_p - &FileInfo[0]); int lump = int(lump_p - FileInfo.data());
*lastlump = lump + 1; *lastlump = lump + 1;
return lump; return lump;
} }
@ -997,7 +1017,7 @@ int FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, in
assert(lastlump != NULL && *lastlump >= 0); assert(lastlump != NULL && *lastlump >= 0);
lump_p = &FileInfo[*lastlump]; lump_p = &FileInfo[*lastlump];
while (lump_p < &FileInfo[NumEntries]) while (lump_p <= &FileInfo.back())
{ {
if (anyns || lump_p->Namespace == ns_global) if (anyns || lump_p->Namespace == ns_global)
{ {
@ -1006,7 +1026,7 @@ int FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, in
{ {
if (!strnicmp(*name, lump_p->shortName.String, 8)) if (!strnicmp(*name, lump_p->shortName.String, 8))
{ {
int lump = int(lump_p - &FileInfo[0]); int lump = int(lump_p - FileInfo.data());
*lastlump = lump + 1; *lastlump = lump + 1;
if (nameindex != NULL) *nameindex = int(name - names); if (nameindex != NULL) *nameindex = int(name - names);
return lump; return lump;
@ -1036,11 +1056,11 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext)
if (!noext) if (!noext)
{ {
while (lump_p < &FileInfo[NumEntries]) while (lump_p <= &FileInfo.back())
{ {
if (!stricmp(name, lump_p->longName.c_str())) if (!stricmp(name, lump_p->LongName))
{ {
int lump = int(lump_p - &FileInfo[0]); int lump = int(lump_p - FileInfo.data());
*lastlump = lump + 1; *lastlump = lump + 1;
return lump; return lump;
} }
@ -1050,15 +1070,15 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext)
else else
{ {
auto len = strlen(name); auto len = strlen(name);
while (lump_p < &FileInfo[NumEntries]) while (lump_p <= &FileInfo.back())
{ {
auto res = strnicmp(name, lump_p->longName.c_str(), len); auto res = strnicmp(name, lump_p->LongName, len);
if (res == 0) if (res == 0)
{ {
auto p = lump_p->longName.c_str() + len; auto p = lump_p->LongName + len;
if (*p == 0 || (*p == '.' && strpbrk(p + 1, "./") == 0)) if (*p == 0 || (*p == '.' && strpbrk(p + 1, "./") == 0))
{ {
int lump = int(lump_p - &FileInfo[0]); int lump = int(lump_p - FileInfo.data());
*lastlump = lump + 1; *lastlump = lump + 1;
return lump; return lump;
} }
@ -1112,8 +1132,8 @@ const char *FileSystem::GetFileFullName (int lump, bool returnshort) const
{ {
if ((size_t)lump >= NumEntries) if ((size_t)lump >= NumEntries)
return NULL; return NULL;
else if (!FileInfo[lump].longName.empty()) else if (FileInfo[lump].LongName[0] != 0)
return FileInfo[lump].longName.c_str(); return FileInfo[lump].LongName;
else if (returnshort) else if (returnshort)
return FileInfo[lump].shortName.String; return FileInfo[lump].shortName.String;
else return nullptr; else return nullptr;
@ -1191,7 +1211,7 @@ const char *FileSystem::GetResourceType(int lump) const
return nullptr; return nullptr;
else else
{ {
auto p = strrchr(FileInfo[lump].longName.c_str(), '.'); auto p = strrchr(FileInfo[lump].LongName, '.');
if (!p) return ""; // has no extension if (!p) return ""; // has no extension
if (strchr(p, '/')) return ""; // the '.' is part of a directory. if (strchr(p, '/')) return ""; // the '.' is part of a directory.
return p + 1; return p + 1;
@ -1243,12 +1263,12 @@ unsigned FileSystem::GetFilesInFolder(const char *inpath, std::vector<FolderEntr
result.clear(); result.clear();
for (size_t i = 0; i < FileInfo.size(); i++) for (size_t i = 0; i < FileInfo.size(); i++)
{ {
if (FileInfo[i].longName.find_first_of(path) == 0) if (strncmp(FileInfo[i].LongName, path.c_str(), path.length()) == 0)
{ {
// Only if it hasn't been replaced. // Only if it hasn't been replaced.
if ((unsigned)fileSystem.CheckNumForFullName(FileInfo[i].longName.c_str()) == i) if ((unsigned)CheckNumForFullName(FileInfo[i].LongName) == i)
{ {
FolderEntry fe{ FileInfo[i].longName.c_str(), (uint32_t)i }; FolderEntry fe{ FileInfo[i].LongName, (uint32_t)i };
result.push_back(fe); result.push_back(fe);
} }
} }
@ -1261,13 +1281,13 @@ unsigned FileSystem::GetFilesInFolder(const char *inpath, std::vector<FolderEntr
// Find the highest resource file having content in the given folder. // Find the highest resource file having content in the given folder.
for (auto & entry : result) for (auto & entry : result)
{ {
int thisfile = fileSystem.GetFileContainer(entry.lumpnum); int thisfile = GetFileContainer(entry.lumpnum);
if (thisfile > maxfile) maxfile = thisfile; if (thisfile > maxfile) maxfile = thisfile;
} }
// Delete everything from older files. // Delete everything from older files.
for (int i = (int)result.size() - 1; i >= 0; i--) for (int i = (int)result.size() - 1; i >= 0; i--)
{ {
if (fileSystem.GetFileContainer(result[i].lumpnum) != maxfile) result.erase(result.begin() + i); if (GetFileContainer(result[i].lumpnum) != maxfile) result.erase(result.begin() + i);
} }
} }
qsort(result.data(), result.size(), sizeof(FolderEntry), folderentrycmp); qsort(result.data(), result.size(), sizeof(FolderEntry), folderentrycmp);
@ -1292,7 +1312,7 @@ void FileSystem::ReadFile (int lump, void *dest)
if (numread != size) if (numread != size)
{ {
throw FileSystemException("W_ReadFile: only read %ld of %ld on '%s'\n", throw FileSystemException("W_ReadFile: only read %ld of %ld on '%s'\n",
numread, size, FileInfo[lump].longName.c_str()); numread, size, FileInfo[lump].LongName);
} }
} }
@ -1356,8 +1376,8 @@ FileReader FileSystem::ReopenFileReader(int lump, bool alwayscache)
if (rl->RefCount == 0 && rd != nullptr && !rd->GetBuffer() && !alwayscache && !(rl->Flags & LUMPF_COMPRESSED)) if (rl->RefCount == 0 && rd != nullptr && !rd->GetBuffer() && !alwayscache && !(rl->Flags & LUMPF_COMPRESSED))
{ {
int fileno = fileSystem.GetFileContainer(lump); int fileno = GetFileContainer(lump);
const char *filename = fileSystem.GetResourceFileFullName(fileno); const char *filename = GetResourceFileFullName(fileno);
FileReader fr; FileReader fr;
if (fr.OpenFile(filename, rl->GetFileOffset(), rl->LumpSize)) if (fr.OpenFile(filename, rl->GetFileOffset(), rl->LumpSize))
{ {
@ -1410,7 +1430,7 @@ const char *FileSystem::GetResourceFileName (int rfnum) const noexcept
return NULL; return NULL;
} }
name = Files[rfnum]->FileName.c_str(); name = Files[rfnum]->FileName;
slash = strrchr (name, '/'); slash = strrchr (name, '/');
return (slash != nullptr && slash[1] != 0) ? slash+1 : name; return (slash != nullptr && slash[1] != 0) ? slash+1 : name;
} }
@ -1476,7 +1496,7 @@ const char *FileSystem::GetResourceFileFullName (int rfnum) const noexcept
return nullptr; return nullptr;
} }
return Files[rfnum]->FileName.c_str(); return Files[rfnum]->FileName;
} }
@ -1496,9 +1516,9 @@ bool FileSystem::CreatePathlessCopy(const char *name, int id, int /*flags*/)
if (lump < 0) return false; // Does not exist. if (lump < 0) return false; // Does not exist.
auto oldlump = FileInfo[lump]; auto oldlump = FileInfo[lump];
ptrdiff_t slash = oldlump.longName.find_last_of('/'); auto slash = strrchr(oldlump.LongName, '/');
if (slash == std::string::npos) if (slash == nullptr)
{ {
FileInfo[lump].flags = LUMPF_FULLPATH; FileInfo[lump].flags = LUMPF_FULLPATH;
return true; // already is pathless. return true; // already is pathless.
@ -1506,7 +1526,7 @@ bool FileSystem::CreatePathlessCopy(const char *name, int id, int /*flags*/)
// just create a new reference to the original data with a different name. // just create a new reference to the original data with a different name.
oldlump.longName.erase(oldlump.longName.begin(), oldlump.longName.begin() + (slash + 1)); oldlump.LongName = slash + 1;
oldlump.resourceId = id; oldlump.resourceId = id;
oldlump.flags = LUMPF_FULLPATH; oldlump.flags = LUMPF_FULLPATH;
FileInfo.push_back(oldlump); FileInfo.push_back(oldlump);
@ -1571,3 +1591,5 @@ FResourceLump* FileSystem::GetFileAt(int no)
{ {
return FileInfo[no].lump; return FileInfo[no].lump;
} }
}

View file

@ -33,8 +33,10 @@
*/ */
#include "fs_findfile.h" #include "fs_findfile.h"
#include <string.h>
#include <vector> #include <vector>
namespace FileSys {
enum enum
{ {
@ -61,6 +63,8 @@ enum
#ifndef _WIN32 #ifndef _WIN32
#include <limits.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <fnmatch.h> #include <fnmatch.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -163,7 +167,7 @@ static int FS_FindAttr(findstate_t *const fileinfo)
const std::string path = fileinfo->path + ent->d_name; const std::string path = fileinfo->path + ent->d_name;
bool isdir; bool isdir;
if (DirEntryExists(path.c_str(), &isdir)) if (FS_DirEntryExists(path.c_str(), &isdir))
{ {
return isdir ? FA_DIREC : 0; return isdir ? FA_DIREC : 0;
} }
@ -173,8 +177,12 @@ static int FS_FindAttr(findstate_t *const fileinfo)
std::string FS_FullPath(const char* directory) std::string FS_FullPath(const char* directory)
{ {
// todo char fullpath[PATH_MAX];
return directory
if (realpath(directory, fullpath) != nullptr)
return fullpath;
return directory;
} }
static size_t FS_GetFileSize(findstate_t* handle, const char* pathname) static size_t FS_GetFileSize(findstate_t* handle, const char* pathname)
@ -303,7 +311,7 @@ std::string FS_FullPath(const char* directory)
static size_t FS_GetFileSize(findstate_t* handle, const char* pathname) static size_t FS_GetFileSize(findstate_t* handle, const char* pathname)
{ {
return handle->FindData.Size[0] + ((uint64_t)handle->FindData.Size[1] << 32); return handle->FindData.Size[1] + ((uint64_t)handle->FindData.Size[0] << 32);
} }
#endif #endif
@ -315,7 +323,7 @@ static size_t FS_GetFileSize(findstate_t* handle, const char* pathname)
// //
//========================================================================== //==========================================================================
static bool ScanDirectory(FileList& list, const char* dirpath, const char* match, const char* relpath, bool nosubdir, bool readhidden) static bool DoScanDirectory(FileList& list, const char* dirpath, const char* match, const char* relpath, bool nosubdir, bool readhidden)
{ {
findstate_t find; findstate_t find;
@ -323,7 +331,7 @@ static bool ScanDirectory(FileList& list, const char* dirpath, const char* match
FixPathSeparator(&dirpathn.front()); FixPathSeparator(&dirpathn.front());
if (dirpathn[dirpathn.length() - 1] != '/') dirpathn += '/'; if (dirpathn[dirpathn.length() - 1] != '/') dirpathn += '/';
std::string dirmatch = dirpath; std::string dirmatch = dirpathn;
dirmatch += match; dirmatch += match;
auto handle = FS_FindFirst(dirmatch.c_str(), &find); auto handle = FS_FindFirst(dirmatch.c_str(), &find);
@ -353,7 +361,7 @@ static bool ScanDirectory(FileList& list, const char* dirpath, const char* match
fl.FileName = fn; fl.FileName = fn;
fl.FilePath = dirpathn + fn; fl.FilePath = dirpathn + fn;
fl.FilePathRel = relpath; fl.FilePathRel = relpath;
fl.FilePathRel += '/'; if (fl.FilePathRel.length() > 0) fl.FilePathRel += '/';
fl.FilePathRel += fn; fl.FilePathRel += fn;
fl.isDirectory = !!(attr & FA_DIREC); fl.isDirectory = !!(attr & FA_DIREC);
fl.isReadonly = !!(attr & FA_RDONLY); fl.isReadonly = !!(attr & FA_RDONLY);
@ -363,8 +371,7 @@ static bool ScanDirectory(FileList& list, const char* dirpath, const char* match
list.push_back(fl); list.push_back(fl);
if (!nosubdir && (attr & FA_DIREC)) if (!nosubdir && (attr & FA_DIREC))
{ {
std::string rel = relpath + '/' + fl.FileName; DoScanDirectory(list, fl.FilePath.c_str(), match, fl.FilePathRel.c_str(), false, readhidden);
ScanDirectory(list, fl.FilePath.c_str(), match);
fl.Length = 0; fl.Length = 0;
} }
} while (FS_FindNext(handle, &find) == 0); } while (FS_FindNext(handle, &find) == 0);
@ -375,7 +382,7 @@ static bool ScanDirectory(FileList& list, const char* dirpath, const char* match
bool ScanDirectory(std::vector<FileListEntry>& list, const char* dirpath, const char* match, bool nosubdir, bool readhidden) bool ScanDirectory(std::vector<FileListEntry>& list, const char* dirpath, const char* match, bool nosubdir, bool readhidden)
{ {
return ScanDirectory(list, dirpath, match, "", nosubdir, readhidden); return DoScanDirectory(list, dirpath, match, "", nosubdir, readhidden);
} }
//========================================================================== //==========================================================================
@ -405,3 +412,4 @@ bool FS_DirEntryExists(const char* pathname, bool* isdir)
return res; return res;
} }
}

View file

@ -0,0 +1,130 @@
/*
** stringpool.cpp
** allocate static strings from larger blocks
**
**---------------------------------------------------------------------------
** Copyright 2010 Randy Heit
** Copyright 2023 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 <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "fs_stringpool.h"
namespace FileSys {
struct StringPool::Block
{
Block *NextBlock;
void *Limit; // End of this block
void *Avail; // Start of free space in this block
void *alignme; // align to 16 bytes.
void *Alloc(size_t size);
};
//==========================================================================
//
// StringPool Destructor
//
//==========================================================================
StringPool::~StringPool()
{
for (Block *next, *block = TopBlock; block != nullptr; block = next)
{
next = block->NextBlock;
free(block);
}
TopBlock = nullptr;
}
//==========================================================================
//
// StringPool :: Alloc
//
//==========================================================================
void *StringPool::Block::Alloc(size_t size)
{
if ((char *)Avail + size > Limit)
{
return nullptr;
}
void *res = Avail;
Avail = ((char *)Avail + size);
return res;
}
StringPool::Block *StringPool::AddBlock(size_t size)
{
size += sizeof(Block); // Account for header size
// Allocate a new block
if (size < BlockSize)
{
size = BlockSize;
}
auto mem = (Block *)malloc(size);
if (mem == nullptr)
{
}
mem->Limit = (uint8_t *)mem + size;
mem->Avail = &mem[1];
mem->NextBlock = TopBlock;
TopBlock = mem;
return mem;
}
void *StringPool::iAlloc(size_t size)
{
Block *block;
for (block = TopBlock; block != nullptr; block = block->NextBlock)
{
void *res = block->Alloc(size);
if (res != nullptr)
{
return res;
}
}
block = AddBlock(size);
return block->Alloc(size);
}
const char* StringPool::Strdup(const char* str)
{
char* p = (char*)iAlloc((strlen(str) + 8) & ~7 );
strcpy(p, str);
return p;
}
}

View file

@ -0,0 +1,29 @@
#pragma once
namespace FileSys {
// Storage for all the static strings the file system must hold.
class StringPool
{
// do not allow externally defining this.
friend class FileSystem;
friend class FResourceFile;
private:
StringPool(size_t blocksize = 10*1024) : TopBlock(nullptr), FreeBlocks(nullptr), BlockSize(blocksize) {}
public:
~StringPool();
const char* Strdup(const char*);
protected:
struct Block;
Block *AddBlock(size_t size);
void *iAlloc(size_t size);
Block *TopBlock;
Block *FreeBlocks;
size_t BlockSize;
public:
bool shared;
};
}

View file

@ -69,7 +69,7 @@
#include <stddef.h> #include <stddef.h>
#include <cstring> #include <cstring>
namespace fs_private { namespace FileSys {
/// Provides MD5 hashing functionality /// Provides MD5 hashing functionality
namespace md5 { namespace md5 {

View file

@ -35,8 +35,12 @@
*/ */
#include <zlib.h> #include <zlib.h>
#include "resourcefile.h" #include "resourcefile_internal.h"
#include "md5.hpp" #include "md5.hpp"
#include "fs_stringpool.h"
#include "files_internal.h"
namespace FileSys {
std::string ExtractBaseName(const char* path, bool include_extension) std::string ExtractBaseName(const char* path, bool include_extension)
{ {
@ -122,13 +126,17 @@ FResourceLump::~FResourceLump()
// //
//========================================================================== //==========================================================================
void FResourceLump::LumpNameSetup(const char *iname) void FResourceLump::LumpNameSetup(const char *iname, StringPool* allocator)
{ {
// this causes interference with real Dehacked lumps. // this causes interference with real Dehacked lumps.
if (!stricmp(iname, "dehacked.exe")) if (!stricmp(iname, "dehacked.exe"))
{ {
iname = ""; iname = "";
} }
else if (allocator)
{
iname = allocator->Strdup(iname);
}
FullName = iname; FullName = iname;
} }
@ -149,7 +157,7 @@ static bool IsWadInFolder(const FResourceFile* const archive, const char* const
return false; return false;
} }
const auto dirName = ExtractBaseName(archive->FileName.c_str()); const auto dirName = ExtractBaseName(archive->FileName);
const auto fileName = ExtractBaseName(resPath, true); const auto fileName = ExtractBaseName(resPath, true);
const std::string filePath = dirName + '/' + fileName; const std::string filePath = dirName + '/' + fileName;
@ -159,14 +167,14 @@ static bool IsWadInFolder(const FResourceFile* const archive, const char* const
void FResourceLump::CheckEmbedded(LumpFilterInfo* lfi) void FResourceLump::CheckEmbedded(LumpFilterInfo* lfi)
{ {
// Checks for embedded archives // Checks for embedded archives
const char *c = strstr(FullName.c_str(), ".wad"); const char *c = strstr(FullName, ".wad");
if (c && strlen(c) == 4 && (!strchr(FullName.c_str(), '/') || IsWadInFolder(Owner, FullName.c_str()))) if (c && strlen(c) == 4 && (!strchr(FullName, '/') || IsWadInFolder(Owner, FullName)))
{ {
Flags |= LUMPF_EMBEDDED; Flags |= LUMPF_EMBEDDED;
} }
else if (lfi) for (auto& fstr : lfi->embeddings) else if (lfi) for (auto& fstr : lfi->embeddings)
{ {
if (!stricmp(FullName.c_str(), fstr.c_str())) if (!stricmp(FullName, fstr.c_str()))
{ {
Flags |= LUMPF_EMBEDDED; Flags |= LUMPF_EMBEDDED;
} }
@ -234,7 +242,7 @@ void *FResourceLump::Lock()
catch (const FileSystemException& err) catch (const FileSystemException& err)
{ {
// enrich the message with info about this lump. // enrich the message with info about this lump.
throw FileSystemException("%s, file '%s': %s", getName(), Owner->FileName.c_str(), err.what()); throw FileSystemException("%s, file '%s': %s", getName(), Owner->FileName, err.what());
} }
} }
return Cache; return Cache;
@ -265,18 +273,18 @@ int FResourceLump::Unlock()
// //
//========================================================================== //==========================================================================
typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile* CheckWHRes(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); FResourceFile* CheckWHRes(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile *CheckLump(const char *filename,FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf); FResourceFile *CheckLump(const char *filename,FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile *CheckDir(const char *filename, bool nosub, LumpFilterInfo* filter, FileSystemMessageFunc Printf); FResourceFile *CheckDir(const char *filename, bool nosub, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckSSI, CheckWHRes, CheckLump }; static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckSSI, CheckWHRes, CheckLump };
@ -285,35 +293,35 @@ static int nulPrintf(FSMessageLevel msg, const char* fmt, ...)
return 0; return 0;
} }
FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf) FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{ {
if (Printf == nullptr) Printf = nulPrintf; if (Printf == nullptr) Printf = nulPrintf;
for(auto func : funcs) for(auto func : funcs)
{ {
if (containeronly && func == CheckLump) break; if (containeronly && func == CheckLump) break;
FResourceFile *resfile = func(filename, file, filter, Printf); FResourceFile *resfile = func(filename, file, filter, Printf, sp);
if (resfile != NULL) return resfile; if (resfile != NULL) return resfile;
} }
return NULL; return NULL;
} }
FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf) FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{ {
return DoOpenResourceFile(filename, file, containeronly, filter, Printf); return DoOpenResourceFile(filename, file, containeronly, filter, Printf, sp);
} }
FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf) FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{ {
FileReader file; FileReader file;
if (!file.OpenFile(filename)) return nullptr; if (!file.OpenFile(filename)) return nullptr;
return DoOpenResourceFile(filename, file, containeronly, filter, Printf); return DoOpenResourceFile(filename, file, containeronly, filter, Printf, sp);
} }
FResourceFile *FResourceFile::OpenDirectory(const char *filename, LumpFilterInfo* filter, FileSystemMessageFunc Printf) FResourceFile *FResourceFile::OpenDirectory(const char *filename, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{ {
if (Printf == nullptr) Printf = nulPrintf; if (Printf == nullptr) Printf = nulPrintf;
return CheckDir(filename, false, filter, Printf); return CheckDir(filename, false, filter, Printf, sp);
} }
//========================================================================== //==========================================================================
@ -322,19 +330,21 @@ FResourceFile *FResourceFile::OpenDirectory(const char *filename, LumpFilterInfo
// //
//========================================================================== //==========================================================================
FResourceFile::FResourceFile(const char *filename) FResourceFile::FResourceFile(const char *filename, StringPool* sp)
: FileName(filename)
{ {
stringpool = sp ? sp : new StringPool;
FileName = stringpool->Strdup(filename);
} }
FResourceFile::FResourceFile(const char *filename, FileReader &r) FResourceFile::FResourceFile(const char *filename, FileReader &r, StringPool* sp)
: FResourceFile(filename) : FResourceFile(filename,sp)
{ {
Reader = std::move(r); Reader = std::move(r);
} }
FResourceFile::~FResourceFile() FResourceFile::~FResourceFile()
{ {
if (!stringpool->shared) delete stringpool;
} }
int lumpcmp(const void * a, const void * b) int lumpcmp(const void * a, const void * b)
@ -357,7 +367,7 @@ int lumpcmp(const void * a, const void * b)
void FResourceFile::GenerateHash() void FResourceFile::GenerateHash()
{ {
// hash the lump directory after sorting // hash the lump directory after sorting
using namespace fs_private::md5; using namespace FileSys::md5;
auto n = snprintf(Hash, 48, "%08X-%04X-", (unsigned)Reader.GetLength(), NumLumps); auto n = snprintf(Hash, 48, "%08X-%04X-", (unsigned)Reader.GetLength(), NumLumps);
@ -368,7 +378,7 @@ void FResourceFile::GenerateHash()
for(uint32_t i = 0; i < NumLumps; i++) for(uint32_t i = 0; i < NumLumps; i++)
{ {
auto lump = GetLump(i); auto lump = GetLump(i);
md5_append(&state, (const uint8_t*)lump->FullName.c_str(), (unsigned)lump->FullName.length() + 1); md5_append(&state, (const uint8_t*)lump->FullName, (unsigned)strlen(lump->FullName) + 1);
md5_append(&state, (const uint8_t*)&lump->LumpSize, 4); md5_append(&state, (const uint8_t*)&lump->LumpSize, 4);
} }
md5_finish(&state, digest); md5_finish(&state, digest);
@ -438,7 +448,7 @@ int FResourceFile::FilterLumps(const std::string& filtername, void *lumps, size_
bool found = FindPrefixRange(filter.c_str(), lumps, lumpsize, max, start, end); bool found = FindPrefixRange(filter.c_str(), lumps, lumpsize, max, start, end);
// Workaround for old Doom filter names (todo: move out of here.) // Workaround for old Doom filter names (todo: move out of here.)
if (!found && filtername.find_first_of("doom.id.doom") == 0) if (!found && filtername.find("doom.id.doom") == 0)
{ {
strReplace(filter, "doom.id.doom", "doom.doom"); strReplace(filter, "doom.id.doom", "doom.doom");
found = FindPrefixRange(filter.c_str(), lumps, lumpsize, max, start, end); found = FindPrefixRange(filter.c_str(), lumps, lumpsize, max, start, end);
@ -453,8 +463,8 @@ int FResourceFile::FilterLumps(const std::string& filtername, void *lumps, size_
for (uint32_t i = start; i < end; ++i, lump_p = (uint8_t *)lump_p + lumpsize) for (uint32_t i = start; i < end; ++i, lump_p = (uint8_t *)lump_p + lumpsize)
{ {
FResourceLump *lump = (FResourceLump *)lump_p; FResourceLump *lump = (FResourceLump *)lump_p;
assert(strnicmp(lump->FullName.c_str(), filter.c_str(), filter.length()) == 0); assert(strnicmp(lump->FullName, filter.c_str(), filter.length()) == 0);
lump->LumpNameSetup(lump->FullName.c_str() + filter.length()); lump->LumpNameSetup(lump->FullName + filter.length(), nullptr);
} }
// Move filtered lumps to the end of the lump list. // Move filtered lumps to the end of the lump list.
@ -523,7 +533,7 @@ void FResourceFile::JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t m
for (void *p = (uint8_t *)lumps + start * lumpsize; p < stop; p = (uint8_t *)p + lumpsize) for (void *p = (uint8_t *)lumps + start * lumpsize; p < stop; p = (uint8_t *)p + lumpsize)
{ {
FResourceLump *lump = (FResourceLump *)p; FResourceLump *lump = (FResourceLump *)p;
lump->FullName = ""; lump->clearName();
} }
} }
} }
@ -556,7 +566,7 @@ bool FResourceFile::FindPrefixRange(const char* filter, void *lumps, size_t lump
{ {
mid = min + (max - min) / 2; mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize); lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = strnicmp(lump->FullName.c_str(), filter, (int)strlen(filter)); cmp = strnicmp(lump->FullName, filter, (int)strlen(filter));
if (cmp == 0) if (cmp == 0)
break; break;
else if (cmp < 0) else if (cmp < 0)
@ -576,7 +586,7 @@ bool FResourceFile::FindPrefixRange(const char* filter, void *lumps, size_t lump
{ {
mid = min + (max - min) / 2; mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize); lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = strnicmp(lump->FullName.c_str(), filter, (int)strlen(filter)); cmp = strnicmp(lump->FullName, filter, (int)strlen(filter));
// Go left on matches and right on misses. // Go left on matches and right on misses.
if (cmp == 0) if (cmp == 0)
max = mid - 1; max = mid - 1;
@ -591,7 +601,7 @@ bool FResourceFile::FindPrefixRange(const char* filter, void *lumps, size_t lump
{ {
mid = min + (max - min) / 2; mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize); lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = strnicmp(lump->FullName.c_str(), filter, (int)strlen(filter)); cmp = strnicmp(lump->FullName, filter, (int)strlen(filter));
// Go right on matches and left on misses. // Go right on matches and left on misses.
if (cmp == 0) if (cmp == 0)
min = mid + 1; min = mid + 1;
@ -613,7 +623,7 @@ FResourceLump *FResourceFile::FindLump(const char *name)
for (unsigned i = 0; i < NumLumps; i++) for (unsigned i = 0; i < NumLumps; i++)
{ {
FResourceLump *lump = GetLump(i); FResourceLump *lump = GetLump(i);
if (!stricmp(name, lump->FullName.c_str())) if (!stricmp(name, lump->FullName))
{ {
return lump; return lump;
} }
@ -670,12 +680,12 @@ int FUncompressedLump::FillCache()
// //
//========================================================================== //==========================================================================
FUncompressedFile::FUncompressedFile(const char *filename) FUncompressedFile::FUncompressedFile(const char *filename, StringPool* sp)
: FResourceFile(filename) : FResourceFile(filename, sp)
{} {}
FUncompressedFile::FUncompressedFile(const char *filename, FileReader &r) FUncompressedFile::FUncompressedFile(const char *filename, FileReader &r, StringPool* sp)
: FResourceFile(filename, r) : FResourceFile(filename, r, sp)
{} {}
@ -685,9 +695,10 @@ FUncompressedFile::FUncompressedFile(const char *filename, FileReader &r)
// //
//========================================================================== //==========================================================================
FExternalLump::FExternalLump(const char *_filename, int filesize) FExternalLump::FExternalLump(const char *_filename, int filesize, StringPool* stringpool)
: Filename(_filename)
{ {
FileName = stringpool->Strdup(_filename);
if (filesize == -1) if (filesize == -1)
{ {
FileReader f; FileReader f;
@ -720,7 +731,7 @@ int FExternalLump::FillCache()
Cache = new char[LumpSize]; Cache = new char[LumpSize];
FileReader f; FileReader f;
if (f.OpenFile(Filename.c_str())) if (f.OpenFile(FileName))
{ {
auto read = f.Read(Cache, LumpSize); auto read = f.Read(Cache, LumpSize);
if (read != LumpSize) if (read != LumpSize)
@ -737,4 +748,4 @@ int FExternalLump::FillCache()
} }
}

View file

@ -0,0 +1,38 @@
#pragma once
#include "resourcefile.h"
namespace FileSys {
struct FUncompressedLump : public FResourceLump
{
int Position;
virtual FileReader *GetReader();
virtual int FillCache() override;
virtual int GetFileOffset() { return Position; }
};
// Base class for uncompressed resource files (WAD, GRP, PAK and single lumps)
class FUncompressedFile : public FResourceFile
{
protected:
TArray<FUncompressedLump> Lumps;
FUncompressedFile(const char *filename, StringPool* sp);
FUncompressedFile(const char *filename, FileReader &r, StringPool* sp);
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};
// should only be used internally.
struct FExternalLump : public FResourceLump
{
const char* FileName;
FExternalLump(const char *_filename, int filesize, StringPool* sp);
virtual int FillCache() override;
};
}

View file

@ -7,6 +7,8 @@
#define FORCE_PACKED #define FORCE_PACKED
#endif #endif
namespace FileSys {
#pragma pack(1) #pragma pack(1)
// FZipCentralInfo // FZipCentralInfo
struct FZipEndOfCentralDirectory struct FZipEndOfCentralDirectory
@ -105,4 +107,5 @@ struct FZipLocalFileHeader
// File header flags. // File header flags.
#define ZF_ENCRYPTED 0x1 #define ZF_ENCRYPTED 0x1
}
#endif #endif

View file

@ -91,7 +91,7 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla
// Read the font's configuration. // Read the font's configuration.
// This will not be done for the default fonts, because they are not atomic and the default content does not need it. // This will not be done for the default fonts, because they are not atomic and the default content does not need it.
std::vector<FolderEntry> folderdata; std::vector<FileSys::FolderEntry> folderdata;
if (filetemplate != nullptr) if (filetemplate != nullptr)
{ {
FStringf path("fonts/%s/", filetemplate); FStringf path("fonts/%s/", filetemplate);
@ -398,7 +398,7 @@ public:
} }
}; };
void FFont::ReadSheetFont(std::vector<FolderEntry> &folderdata, int width, int height, const DVector2 &Scale) void FFont::ReadSheetFont(std::vector<FileSys::FolderEntry> &folderdata, int width, int height, const DVector2 &Scale)
{ {
TMap<int, FGameTexture*> charMap; TMap<int, FGameTexture*> charMap;
int minchar = INT_MAX; int minchar = INT_MAX;

View file

@ -58,7 +58,7 @@ struct HexDataSource
// //
//========================================================================== //==========================================================================
void ParseDefinition(FResourceLump* font) void ParseDefinition(FileSys::FResourceLump* font)
{ {
FScanner sc; FScanner sc;
@ -109,8 +109,8 @@ class FHexFontChar : public FImageSource
public: public:
FHexFontChar(uint8_t *sourcedata, int swidth, int width, int height); FHexFontChar(uint8_t *sourcedata, int swidth, int width, int height);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
int CopyPixels(FBitmap* bmp, int conversion); int CopyPixels(FBitmap* bmp, int conversion, int frame = 0);
protected: protected:
int SourceWidth; int SourceWidth;
@ -144,7 +144,7 @@ FHexFontChar::FHexFontChar (uint8_t *sourcedata, int swidth, int width, int heig
// //
//========================================================================== //==========================================================================
PalettedPixels FHexFontChar::CreatePalettedPixels(int) PalettedPixels FHexFontChar::CreatePalettedPixels(int, int)
{ {
int destSize = Width * Height; int destSize = Width * Height;
PalettedPixels Pixels(destSize); PalettedPixels Pixels(destSize);
@ -175,7 +175,7 @@ PalettedPixels FHexFontChar::CreatePalettedPixels(int)
return Pixels; return Pixels;
} }
int FHexFontChar::CopyPixels(FBitmap* bmp, int conversion) int FHexFontChar::CopyPixels(FBitmap* bmp, int conversion, int frame)
{ {
if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source. if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source.
PalEntry* palette = hexdata.ConsolePal; PalEntry* palette = hexdata.ConsolePal;
@ -190,8 +190,8 @@ class FHexFontChar2 : public FHexFontChar
public: public:
FHexFontChar2(uint8_t *sourcedata, int swidth, int width, int height); FHexFontChar2(uint8_t *sourcedata, int swidth, int width, int height);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
int CopyPixels(FBitmap* bmp, int conversion); int CopyPixels(FBitmap* bmp, int conversion, int frame = 0);
}; };
@ -216,7 +216,7 @@ FHexFontChar2::FHexFontChar2(uint8_t *sourcedata, int swidth, int width, int hei
// //
//========================================================================== //==========================================================================
PalettedPixels FHexFontChar2::CreatePalettedPixels(int) PalettedPixels FHexFontChar2::CreatePalettedPixels(int, int)
{ {
int destSize = Width * Height; int destSize = Width * Height;
PalettedPixels Pixels(destSize); PalettedPixels Pixels(destSize);
@ -255,7 +255,7 @@ PalettedPixels FHexFontChar2::CreatePalettedPixels(int)
return Pixels; return Pixels;
} }
int FHexFontChar2::CopyPixels(FBitmap* bmp, int conversion) int FHexFontChar2::CopyPixels(FBitmap* bmp, int conversion, int frame)
{ {
if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source. if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source.
PalEntry* palette = hexdata.SmallPal; PalEntry* palette = hexdata.SmallPal;

View file

@ -124,7 +124,7 @@ FSingleLumpFont::FSingleLumpFont (const char *name, int lump) : FFont(lump)
FontName = name; FontName = name;
FileData data1 = fileSystem.ReadFile (lump); auto data1 = fileSystem.ReadFile (lump);
auto data = data1.GetBytes(); auto data = data1.GetBytes();
if (data[0] == 0xE1 && data[1] == 0xE6 && data[2] == 0xD5 && data[3] == 0x1A) if (data[0] == 0xE1 && data[1] == 0xE6 && data[2] == 0xD5 && data[3] == 0x1A)
@ -474,7 +474,7 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
void FSingleLumpFont::CheckFON1Chars() void FSingleLumpFont::CheckFON1Chars()
{ {
FileData memLump = fileSystem.ReadFile(Lump); auto memLump = fileSystem.ReadFile(Lump);
auto data = memLump.GetBytes(); auto data = memLump.GetBytes();
const uint8_t* data_p; const uint8_t* data_p;

View file

@ -109,7 +109,7 @@ FFont *V_GetFont(const char *name, const char *fontlumpname)
int lump = -1; int lump = -1;
int folderfile = -1; int folderfile = -1;
std::vector<FolderEntry> folderdata; std::vector<FileSys::FolderEntry> folderdata;
FStringf path("fonts/%s/", name); FStringf path("fonts/%s/", name);
// Use a folder-based font only if it comes from a later file than the single lump version. // Use a folder-based font only if it comes from a later file than the single lump version.

View file

@ -175,7 +175,7 @@ protected:
void FixXMoves(); void FixXMoves();
void ReadSheetFont(std::vector<FolderEntry> &folderdata, int width, int height, const DVector2 &Scale); void ReadSheetFont(std::vector<FileSys::FolderEntry> &folderdata, int width, int height, const DVector2 &Scale);
EFontType Type = EFontType::Unknown; EFontType Type = EFontType::Unknown;
FName AltFontName = NAME_None; FName AltFontName = NAME_None;

View file

@ -1519,7 +1519,7 @@ void M_ParseMenuDefs()
DefaultOptionMenuSettings->Reset(); DefaultOptionMenuSettings->Reset();
OptionSettings.mLinespacing = 17; OptionSettings.mLinespacing = 17;
int IWADMenu = fileSystem.CheckNumForName("MENUDEF", ns_global, fileSystem.GetIwadNum()); int IWADMenu = fileSystem.CheckNumForName("MENUDEF", FileSys::ns_global, fileSystem.GetIwadNum());
while ((lump = fileSystem.FindLump ("MENUDEF", &lastlump)) != -1) while ((lump = fileSystem.FindLump ("MENUDEF", &lastlump)) != -1)
{ {

View file

@ -297,7 +297,7 @@ unsigned FSavegameManagerBase::ExtractSaveData(int index)
!node->bOldVersion && !node->bOldVersion &&
(resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), true)) != nullptr) (resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), true)) != nullptr)
{ {
FResourceLump *info = resf->FindLump("info.json"); auto info = resf->FindLump("info.json");
if (info == nullptr) if (info == nullptr)
{ {
// this should not happen because the file has already been verified. // this should not happen because the file has already been verified.
@ -315,7 +315,7 @@ unsigned FSavegameManagerBase::ExtractSaveData(int index)
SaveCommentString = ExtractSaveComment(arc); SaveCommentString = ExtractSaveComment(arc);
FResourceLump *pic = resf->FindLump("savepic.png"); auto pic = resf->FindLump("savepic.png");
if (pic != nullptr) if (pic != nullptr)
{ {
FileReader picreader; FileReader picreader;

View file

@ -172,7 +172,7 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent)
} }
int len = fileSystem.FileLength(lump); int len = fileSystem.FileLength(lump);
FileData lumpd = fileSystem.ReadFile(lump); auto lumpd = fileSystem.ReadFile(lump);
const char * buffer = lumpd.GetString(); const char * buffer = lumpd.GetString();
if ( (size_t)fullname.LastIndexOf("_d.3d") == fullname.Len()-5 ) if ( (size_t)fullname.LastIndexOf("_d.3d") == fullname.Len()-5 )

View file

@ -270,7 +270,7 @@ void IQMModel::LoadGeometry()
{ {
try try
{ {
FileData lumpdata = fileSystem.ReadFile(mLumpNum); auto lumpdata = fileSystem.ReadFile(mLumpNum);
IQMFileReader reader(lumpdata.GetMem(), (int)lumpdata.GetSize()); IQMFileReader reader(lumpdata.GetMem(), (int)lumpdata.GetSize());
Vertices.Resize(NumVertices); Vertices.Resize(NumVertices);

View file

@ -177,7 +177,7 @@ bool FDMDModel::Load(const char * path, int lumpnum, const char * buffer, int le
void FDMDModel::LoadGeometry() void FDMDModel::LoadGeometry()
{ {
static int axis[3] = { VX, VY, VZ }; static int axis[3] = { VX, VY, VZ };
FileData lumpdata = fileSystem.ReadFile(mLumpNum); auto lumpdata = fileSystem.ReadFile(mLumpNum);
auto buffer = lumpdata.GetString(); auto buffer = lumpdata.GetString();
texCoords = new FTexCoord[info.numTexCoords]; texCoords = new FTexCoord[info.numTexCoords];
memcpy(texCoords, buffer + info.offsetTexCoords, info.numTexCoords * sizeof(FTexCoord)); memcpy(texCoords, buffer + info.offsetTexCoords, info.numTexCoords * sizeof(FTexCoord));
@ -501,7 +501,7 @@ void FMD2Model::LoadGeometry()
{ {
static int axis[3] = { VX, VY, VZ }; static int axis[3] = { VX, VY, VZ };
uint8_t *md2_frames; uint8_t *md2_frames;
FileData lumpdata = fileSystem.ReadFile(mLumpNum); auto lumpdata = fileSystem.ReadFile(mLumpNum);
auto buffer = lumpdata.GetString(); auto buffer = lumpdata.GetString();
texCoords = new FTexCoord[info.numTexCoords]; texCoords = new FTexCoord[info.numTexCoords];

View file

@ -189,7 +189,7 @@ bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int le
void FMD3Model::LoadGeometry() void FMD3Model::LoadGeometry()
{ {
FileData lumpdata = fileSystem.ReadFile(mLumpNum); auto lumpdata = fileSystem.ReadFile(mLumpNum);
auto buffer = lumpdata.GetString(); auto buffer = lumpdata.GetString();
md3_header_t * hdr = (md3_header_t *)buffer; md3_header_t * hdr = (md3_header_t *)buffer;
md3_surface_t * surf = (md3_surface_t*)(buffer + LittleLong(hdr->Ofs_Surfaces)); md3_surface_t * surf = (md3_surface_t*)(buffer + LittleLong(hdr->Ofs_Surfaces));

View file

@ -70,9 +70,9 @@ bool FUE1Model::Load( const char *filename, int lumpnum, const char *buffer, int
void FUE1Model::LoadGeometry() void FUE1Model::LoadGeometry()
{ {
const char *buffer, *buffer2; const char *buffer, *buffer2;
FileData lump = fileSystem.ReadFile(mDataLump); auto lump = fileSystem.ReadFile(mDataLump);
buffer = lump.GetString(); buffer = lump.GetString();
FileData lump2 = fileSystem.ReadFile(mAnivLump); auto lump2 = fileSystem.ReadFile(mAnivLump);
buffer2 = lump2.GetString(); buffer2 = lump2.GetString();
// map structures // map structures
dhead = (const d3dhead*)(buffer); dhead = (const d3dhead*)(buffer);

View file

@ -57,8 +57,8 @@ class FVoxelTexture : public FImageSource
public: public:
FVoxelTexture(FVoxel *voxel); FVoxelTexture(FVoxel *voxel);
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
protected: protected:
FVoxel *SourceVox; FVoxel *SourceVox;
@ -84,7 +84,7 @@ FVoxelTexture::FVoxelTexture(FVoxel *vox)
// //
//=========================================================================== //===========================================================================
PalettedPixels FVoxelTexture::CreatePalettedPixels(int conversion) PalettedPixels FVoxelTexture::CreatePalettedPixels(int conversion, int frame)
{ {
// GetPixels gets called when a translated palette is used so we still need to implement it here. // GetPixels gets called when a translated palette is used so we still need to implement it here.
PalettedPixels Pixels(256); PalettedPixels Pixels(256);
@ -123,7 +123,7 @@ PalettedPixels FVoxelTexture::CreatePalettedPixels(int conversion)
// //
//=========================================================================== //===========================================================================
int FVoxelTexture::CopyPixels(FBitmap *bmp, int conversion) int FVoxelTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
PalEntry pe[256]; PalEntry pe[256];
uint8_t bitmap[256]; uint8_t bitmap[256];

View file

@ -161,7 +161,7 @@ FVoxel *R_LoadKVX(int lumpnum)
int mip, maxmipsize; int mip, maxmipsize;
int i, j, n; int i, j, n;
FileData lump = fileSystem.ReadFile(lumpnum); // FileData adds an extra 0 byte to the end. auto lump = fileSystem.ReadFile(lumpnum); // FileData adds an extra 0 byte to the end.
auto rawvoxel = lump.GetBytes(); auto rawvoxel = lump.GetBytes();
int voxelsize = (int)(lump.GetSize()-1); int voxelsize = (int)(lump.GetSize()-1);

View file

@ -282,6 +282,7 @@ extern bool AppActive;
{ {
ZD_UNUSED(aNotification); ZD_UNUSED(aNotification);
if (GSnd)
S_SetSoundPaused(1); S_SetSoundPaused(1);
AppActive = true; AppActive = true;
@ -291,6 +292,7 @@ extern bool AppActive;
{ {
ZD_UNUSED(aNotification); ZD_UNUSED(aNotification);
if (GSnd)
S_SetSoundPaused(0); S_SetSoundPaused(0);
AppActive = false; AppActive = false;

View file

@ -171,6 +171,17 @@ unsigned int I_MakeRNGSeed()
return static_cast<unsigned int>(arc4random()); return static_cast<unsigned int>(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) void I_OpenShellFolder(const char* folder)
{ {
NSFileManager *filemgr = [NSFileManager defaultManager]; NSFileManager *filemgr = [NSFileManager defaultManager];

View file

@ -406,6 +406,23 @@ FString I_GetFromClipboard (bool use_primary_selection)
return ""; 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. // Return a random seed, preferably one with lots of entropy.
unsigned int I_MakeRNGSeed() unsigned int I_MakeRNGSeed()
{ {

View file

@ -958,6 +958,25 @@ void I_SetThreadNumaNode(std::thread &thread, int numaNode)
} }
} }
FString I_GetCWD()
{
auto len = GetCurrentDirectoryW(0, nullptr);
TArray<wchar_t> 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) void I_OpenShellFolder(const char* infolder)
{ {
auto len = GetCurrentDirectoryW(0, nullptr); auto len = GetCurrentDirectoryW(0, nullptr);

View file

@ -80,5 +80,7 @@ int I_GetNumaNodeThreadCount(int numaNode);
void I_SetThreadNumaNode(std::thread &thread, int numaNode); void I_SetThreadNumaNode(std::thread &thread, int numaNode);
void I_OpenShellFolder(const char*); void I_OpenShellFolder(const char*);
FString I_GetCWD();
bool I_ChDir(const char* path);
#endif #endif

View file

@ -431,17 +431,13 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
{ {
int pl_lump = fileSystem.CheckNumForFullName("shaders/glsl/func_defaultmat2.fp", 0); int pl_lump = fileSystem.CheckNumForFullName("shaders/glsl/func_defaultmat2.fp", 0);
if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultmat2.fp"); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultmat2.fp");
FileData pl_data = fileSystem.ReadFile(pl_lump); fp_comb << "\n" << GetStringFromLump(pl_lump);
fp_comb << "\n";
fp_comb.AppendCStrPart(pl_data.GetString(), pl_data.GetSize());
} }
else else
{ {
int pl_lump = fileSystem.CheckNumForFullName("shaders/glsl/func_defaultmat.fp", 0); int pl_lump = fileSystem.CheckNumForFullName("shaders/glsl/func_defaultmat.fp", 0);
if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultmat.fp"); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultmat.fp");
FileData pl_data = fileSystem.ReadFile(pl_lump); fp_comb << "\n" << GetStringFromLump(pl_lump);
fp_comb << "\n";
fp_comb.AppendCStrPart(pl_data.GetString(), pl_data.GetSize());
if (pp_data.IndexOf("ProcessTexel") < 0) if (pp_data.IndexOf("ProcessTexel") < 0)
{ {
@ -467,9 +463,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
{ {
int pl_lump = fileSystem.CheckNumForFullName("shaders/glsl/func_defaultlight.fp", 0); int pl_lump = fileSystem.CheckNumForFullName("shaders/glsl/func_defaultlight.fp", 0);
if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultlight.fp"); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultlight.fp");
FileData pl_data = fileSystem.ReadFile(pl_lump); fp_comb << "\n" << GetStringFromLump(pl_lump);
fp_comb << "\n";
fp_comb.AppendCStrPart(pl_data.GetString(), pl_data.GetSize());
} }
// ProcessMaterial must be considered broken because it requires the user to fill in data they possibly cannot know all about. // ProcessMaterial must be considered broken because it requires the user to fill in data they possibly cannot know all about.
@ -491,8 +485,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
{ {
int pp_lump = fileSystem.CheckNumForFullName(light_fragprog, 0); int pp_lump = fileSystem.CheckNumForFullName(light_fragprog, 0);
if (pp_lump == -1) I_Error("Unable to load '%s'", light_fragprog); if (pp_lump == -1) I_Error("Unable to load '%s'", light_fragprog);
FileData pp_data = fileSystem.ReadFile(pp_lump); fp_comb << GetStringFromLump(pp_lump) << "\n";
fp_comb.AppendCStrPart(pp_data.GetString(), pp_data.GetSize()) << "\n";
} }
if (gl.flags & RFL_NO_CLIP_PLANES) if (gl.flags & RFL_NO_CLIP_PLANES)

View file

@ -383,11 +383,11 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char *
int vp_lump = fileSystem.CheckNumForFullName(vert_prog_lump, 0); int vp_lump = fileSystem.CheckNumForFullName(vert_prog_lump, 0);
if (vp_lump == -1) I_Error("Unable to load '%s'", vert_prog_lump.GetChars()); if (vp_lump == -1) I_Error("Unable to load '%s'", vert_prog_lump.GetChars());
FileData vp_data = fileSystem.ReadFile(vp_lump); auto vp_data = fileSystem.ReadFile(vp_lump);
int fp_lump = fileSystem.CheckNumForFullName(frag_prog_lump, 0); int fp_lump = fileSystem.CheckNumForFullName(frag_prog_lump, 0);
if (fp_lump == -1) I_Error("Unable to load '%s'", frag_prog_lump.GetChars()); if (fp_lump == -1) I_Error("Unable to load '%s'", frag_prog_lump.GetChars());
FileData fp_data = fileSystem.ReadFile(fp_lump); auto fp_data = fileSystem.ReadFile(fp_lump);
@ -433,17 +433,13 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char *
{ {
int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultmat2.fp", 0); int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultmat2.fp", 0);
if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultmat2.fp"); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultmat2.fp");
FileData pl_data = fileSystem.ReadFile(pl_lump); fp_comb << "\n" << GetStringFromLump(pl_lump);
fp_comb << "\n";
fp_comb.AppendCStrPart(pl_data.GetString(), pl_data.GetSize());
} }
else else
{ {
int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultmat.fp", 0); int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultmat.fp", 0);
if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultmat.fp"); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultmat.fp");
FileData pl_data = fileSystem.ReadFile(pl_lump); fp_comb << "\n" << GetStringFromLump(pl_lump);
fp_comb << "\n";
fp_comb.AppendCStrPart(pl_data.GetString(), pl_data.GetSize());
if (pp_data.IndexOf("ProcessTexel") < 0) if (pp_data.IndexOf("ProcessTexel") < 0)
{ {
@ -469,9 +465,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char *
{ {
int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultlight.fp", 0); int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultlight.fp", 0);
if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultlight.fp"); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultlight.fp");
FileData pl_data = fileSystem.ReadFile(pl_lump); fp_comb << "\n" << GetStringFromLump(pl_lump);
fp_comb << "\n";
fp_comb.AppendCStrPart(pl_data.GetString(), pl_data.GetSize());
} }
// ProcessMaterial must be considered broken because it requires the user to fill in data they possibly cannot know all about. // ProcessMaterial must be considered broken because it requires the user to fill in data they possibly cannot know all about.
@ -493,8 +487,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char *
{ {
int pp_lump = fileSystem.CheckNumForFullName(light_fragprog, 0); int pp_lump = fileSystem.CheckNumForFullName(light_fragprog, 0);
if (pp_lump == -1) I_Error("Unable to load '%s'", light_fragprog.GetChars()); if (pp_lump == -1) I_Error("Unable to load '%s'", light_fragprog.GetChars());
FileData pp_data = fileSystem.ReadFile(pp_lump); fp_comb << GetStringFromLump(pp_lump) << "\n";
fp_comb.AppendCStrPart(pp_data.GetString(), pp_data.GetSize()) << "\n";
} }
if (gles.flags & RFL_NO_CLIP_PLANES) if (gles.flags & RFL_NO_CLIP_PLANES)

View file

@ -45,6 +45,7 @@
#include "hw_shadowmap.h" #include "hw_shadowmap.h"
#include "hw_levelmesh.h" #include "hw_levelmesh.h"
#include "buffers.h" #include "buffers.h"
#include "files.h"
struct FPortalSceneState; struct FPortalSceneState;
@ -90,7 +91,6 @@ EXTERN_CVAR(Int, win_h)
EXTERN_CVAR(Bool, win_maximized) EXTERN_CVAR(Bool, win_maximized)
struct FColormap; struct FColormap;
class FileWriter;
enum FTextureFormat : uint32_t; enum FTextureFormat : uint32_t;
class FModelRenderer; class FModelRenderer;
struct SamplerUniform; struct SamplerUniform;

View file

@ -473,7 +473,7 @@ FString VkShaderManager::LoadPrivateShaderLump(const char *lumpname)
{ {
int lump = fileSystem.CheckNumForFullName(lumpname, 0); int lump = fileSystem.CheckNumForFullName(lumpname, 0);
if (lump == -1) I_Error("Unable to load '%s'", lumpname); if (lump == -1) I_Error("Unable to load '%s'", lumpname);
FileData data = fileSystem.ReadFile(lump); auto data = fileSystem.ReadFile(lump);
return GetStringFromLump(lump); return GetStringFromLump(lump);
} }

View file

@ -72,7 +72,7 @@ FGenericStartScreen::FGenericStartScreen(int max_progress)
: FStartScreen(max_progress) : FStartScreen(max_progress)
{ {
// at this point we do not have a working texture manager yet, so we have to do the lookup via the file system // at this point we do not have a working texture manager yet, so we have to do the lookup via the file system
int startup_lump = fileSystem.CheckNumForName("GZDOOM", ns_graphics); int startup_lump = fileSystem.CheckNumForName("GZDOOM", FileSys::ns_graphics);
StartupBitmap.Create(640, 480); StartupBitmap.Create(640, 480);
ClearBlock(StartupBitmap, { 0, 0, 0, 255 }, 0, 0, 640, 480); ClearBlock(StartupBitmap, { 0, 0, 0, 255 }, 0, 0, 640, 480);

View file

@ -81,9 +81,9 @@ FHexenStartScreen::FHexenStartScreen(int max_progress)
: FStartScreen(max_progress) : FStartScreen(max_progress)
{ {
// at this point we do not have a working texture manager yet, so we have to do the lookup via the file system // at this point we do not have a working texture manager yet, so we have to do the lookup via the file system
int startup_lump = fileSystem.CheckNumForName("STARTUP", ns_graphics); int startup_lump = fileSystem.CheckNumForName("STARTUP", FileSys::ns_graphics);
int netnotch_lump = fileSystem.CheckNumForName("NETNOTCH", ns_graphics); int netnotch_lump = fileSystem.CheckNumForName("NETNOTCH", FileSys::ns_graphics);
int notch_lump = fileSystem.CheckNumForName("NOTCH", ns_graphics); int notch_lump = fileSystem.CheckNumForName("NOTCH", FileSys::ns_graphics);
// For backwards compatibility we also need to look in the default namespace, because these were previously not handled as graphics. // For backwards compatibility we also need to look in the default namespace, because these were previously not handled as graphics.
if (startup_lump == -1) startup_lump = fileSystem.CheckNumForName("STARTUP"); if (startup_lump == -1) startup_lump = fileSystem.CheckNumForName("STARTUP");

View file

@ -119,7 +119,7 @@ FStrifeStartScreen::FStrifeStartScreen(int max_progress)
// Load the animated overlays. // Load the animated overlays.
for (size_t i = 0; i < countof(StrifeStartupPicNames); ++i) for (size_t i = 0; i < countof(StrifeStartupPicNames); ++i)
{ {
int lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i], ns_graphics); int lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i], FileSys::ns_graphics);
if (lumpnum < 0) lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i]); if (lumpnum < 0) lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i]);
if (lumpnum >= 0) if (lumpnum >= 0)

View file

@ -51,8 +51,8 @@ class FAnmTexture : public FImageSource
public: public:
FAnmTexture (int lumpnum, int w, int h); FAnmTexture (int lumpnum, int w, int h);
void ReadFrame(uint8_t *buffer, uint8_t *palette); void ReadFrame(uint8_t *buffer, uint8_t *palette);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
}; };
@ -103,7 +103,7 @@ FAnmTexture::FAnmTexture (int lumpnum, int w, int h)
void FAnmTexture::ReadFrame(uint8_t *pixels, uint8_t *palette) void FAnmTexture::ReadFrame(uint8_t *pixels, uint8_t *palette)
{ {
FileData lump = fileSystem.ReadFile (SourceLump); auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes(); auto source = lump.GetBytes();
anim_t anim; anim_t anim;
@ -127,7 +127,7 @@ void FAnmTexture::ReadFrame(uint8_t *pixels, uint8_t *palette)
// //
//========================================================================== //==========================================================================
PalettedPixels FAnmTexture::CreatePalettedPixels(int conversion) PalettedPixels FAnmTexture::CreatePalettedPixels(int conversion, int frame)
{ {
PalettedPixels pixels(Width*Height); PalettedPixels pixels(Width*Height);
uint8_t buffer[64000]; uint8_t buffer[64000];
@ -149,7 +149,7 @@ PalettedPixels FAnmTexture::CreatePalettedPixels(int conversion)
// //
//========================================================================== //==========================================================================
int FAnmTexture::CopyPixels(FBitmap *bmp, int conversion) int FAnmTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
uint8_t buffer[64000]; uint8_t buffer[64000];
uint8_t palette[768]; uint8_t palette[768];

View file

@ -50,7 +50,7 @@ class FAutomapTexture : public FImageSource
{ {
public: public:
FAutomapTexture(int lumpnum); FAutomapTexture(int lumpnum);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
}; };
@ -89,10 +89,10 @@ FAutomapTexture::FAutomapTexture (int lumpnum)
// //
//========================================================================== //==========================================================================
PalettedPixels FAutomapTexture::CreatePalettedPixels(int conversion) PalettedPixels FAutomapTexture::CreatePalettedPixels(int conversion, int frame)
{ {
int x, y; int x, y;
FileData data = fileSystem.ReadFile (SourceLump); auto data = fileSystem.ReadFile (SourceLump);
auto indata = data.GetBytes(); auto indata = data.GetBytes();
PalettedPixels Pixels(Width * Height); PalettedPixels Pixels(Width * Height);

View file

@ -43,7 +43,7 @@ class FBrightmapTexture : public FImageSource
public: public:
FBrightmapTexture (FImageSource *source); FBrightmapTexture (FImageSource *source);
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
protected: protected:
FImageSource *SourcePic; FImageSource *SourcePic;
@ -65,7 +65,7 @@ FBrightmapTexture::FBrightmapTexture (FImageSource *source)
bMasked = false; bMasked = false;
} }
int FBrightmapTexture::CopyPixels(FBitmap *bmp, int conversion) int FBrightmapTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
SourcePic->CopyTranslatedPixels(bmp, GPalette.GlobalBrightmap.Palette); SourcePic->CopyTranslatedPixels(bmp, GPalette.GlobalBrightmap.Palette);
return 0; return 0;

View file

@ -55,7 +55,7 @@ FBuildTexture::FBuildTexture(const FString &pathprefix, int tilenum, const uint8
TopOffset = top; TopOffset = top;
} }
PalettedPixels FBuildTexture::CreatePalettedPixels(int conversion) PalettedPixels FBuildTexture::CreatePalettedPixels(int conversion, int frame)
{ {
PalettedPixels Pixels(Width * Height); PalettedPixels Pixels(Width * Height);
FRemapTable *Remap = Translation; FRemapTable *Remap = Translation;
@ -67,7 +67,7 @@ PalettedPixels FBuildTexture::CreatePalettedPixels(int conversion)
return Pixels; return Pixels;
} }
int FBuildTexture::CopyPixels(FBitmap *bmp, int conversion) int FBuildTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
PalEntry *Remap = Translation->Palette; PalEntry *Remap = Translation->Palette;
bmp->CopyPixelData(0, 0, RawPixels, Width, Height, Height, 1, 0, Remap); bmp->CopyPixelData(0, 0, RawPixels, Width, Height, Height, 1, 0, Remap);

View file

@ -164,7 +164,7 @@ class FDDSTexture : public FImageSource
public: public:
FDDSTexture (FileReader &lump, int lumpnum, void *surfdesc); FDDSTexture (FileReader &lump, int lumpnum, void *surfdesc);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
protected: protected:
uint32_t Format; uint32_t Format;
@ -183,7 +183,7 @@ protected:
void DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode); void DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode);
void DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode); void DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode);
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
friend class FTexture; friend class FTexture;
}; };
@ -372,7 +372,7 @@ void FDDSTexture::CalcBitShift (uint32_t mask, uint8_t *lshiftp, uint8_t *rshift
// //
//========================================================================== //==========================================================================
PalettedPixels FDDSTexture::CreatePalettedPixels(int conversion) PalettedPixels FDDSTexture::CreatePalettedPixels(int conversion, int frame)
{ {
auto lump = fileSystem.OpenFileReader (SourceLump); auto lump = fileSystem.OpenFileReader (SourceLump);
@ -781,7 +781,7 @@ void FDDSTexture::DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t
// //
//=========================================================================== //===========================================================================
int FDDSTexture::CopyPixels(FBitmap *bmp, int conversion) int FDDSTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
auto lump = fileSystem.OpenFileReader (SourceLump); auto lump = fileSystem.OpenFileReader (SourceLump);

View file

@ -49,7 +49,7 @@ class FEmptyTexture : public FImageSource
{ {
public: public:
FEmptyTexture (int lumpnum); FEmptyTexture (int lumpnum);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
}; };
//========================================================================== //==========================================================================
@ -94,7 +94,7 @@ FEmptyTexture::FEmptyTexture (int lumpnum)
// //
//========================================================================== //==========================================================================
PalettedPixels FEmptyTexture::CreatePalettedPixels(int conversion) PalettedPixels FEmptyTexture::CreatePalettedPixels(int conversion, int frame)
{ {
static uint8_t p; static uint8_t p;
PalettedPixels Pixel(&p, 1); PalettedPixels Pixel(&p, 1);

View file

@ -48,7 +48,7 @@ class FFlatTexture : public FImageSource
{ {
public: public:
FFlatTexture (int lumpnum); FFlatTexture (int lumpnum);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
}; };
@ -102,7 +102,7 @@ FFlatTexture::FFlatTexture (int lumpnum)
// //
//========================================================================== //==========================================================================
PalettedPixels FFlatTexture::CreatePalettedPixels(int conversion) PalettedPixels FFlatTexture::CreatePalettedPixels(int conversion, int frame)
{ {
auto lump = fileSystem.OpenFileReader (SourceLump); auto lump = fileSystem.OpenFileReader (SourceLump);
PalettedPixels Pixels(Width*Height); PalettedPixels Pixels(Width*Height);

View file

@ -66,7 +66,7 @@ FFontChar2::FFontChar2(int sourcelump, int sourcepos, int width, int height, int
// //
//========================================================================== //==========================================================================
PalettedPixels FFontChar2::CreatePalettedPixels(int) PalettedPixels FFontChar2::CreatePalettedPixels(int, int)
{ {
auto lump = fileSystem.OpenFileReader(SourceLump); auto lump = fileSystem.OpenFileReader(SourceLump);
int destSize = Width * Height; int destSize = Width * Height;
@ -170,7 +170,7 @@ PalettedPixels FFontChar2::CreatePalettedPixels(int)
return Pixels; return Pixels;
} }
int FFontChar2::CopyPixels(FBitmap* bmp, int conversion) int FFontChar2::CopyPixels(FBitmap* bmp, int conversion, int frame)
{ {
if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source. if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source.
auto ppix = CreatePalettedPixels(conversion); auto ppix = CreatePalettedPixels(conversion);

View file

@ -6,8 +6,8 @@ class FFontChar2 : public FImageSource
public: public:
FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs=0, int topofs=0); FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs=0, int topofs=0);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
int CopyPixels(FBitmap* bmp, int conversion); int CopyPixels(FBitmap* bmp, int conversion, int frame = 0);
void SetSourceRemap(const PalEntry* sourceremap) void SetSourceRemap(const PalEntry* sourceremap)
{ {

View file

@ -66,8 +66,8 @@ class FIMGZTexture : public FImageSource
public: public:
FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t, bool isalpha); FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t, bool isalpha);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
}; };
@ -118,9 +118,9 @@ FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int1
// //
//========================================================================== //==========================================================================
PalettedPixels FIMGZTexture::CreatePalettedPixels(int conversion) PalettedPixels FIMGZTexture::CreatePalettedPixels(int conversion, int frame)
{ {
FileData lump = fileSystem.ReadFile (SourceLump); auto lump = fileSystem.ReadFile (SourceLump);
auto imgz = (const ImageHeader *)lump.GetMem(); auto imgz = (const ImageHeader *)lump.GetMem();
const uint8_t *data = (const uint8_t *)&imgz[1]; const uint8_t *data = (const uint8_t *)&imgz[1];
@ -198,7 +198,7 @@ PalettedPixels FIMGZTexture::CreatePalettedPixels(int conversion)
// //
//========================================================================== //==========================================================================
int FIMGZTexture::CopyPixels(FBitmap *bmp, int conversion) int FIMGZTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
if (!isalpha) return FImageSource::CopyPixels(bmp, conversion); if (!isalpha) return FImageSource::CopyPixels(bmp, conversion);
else return CopyTranslatedPixels(bmp, GPalette.GrayscaleMap.Palette); else return CopyTranslatedPixels(bmp, GPalette.GrayscaleMap.Palette);

View file

@ -185,8 +185,8 @@ class FJPEGTexture : public FImageSource
public: public:
FJPEGTexture (int lumpnum, int width, int height); FJPEGTexture (int lumpnum, int width, int height);
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
}; };
//========================================================================== //==========================================================================
@ -260,7 +260,7 @@ FJPEGTexture::FJPEGTexture (int lumpnum, int width, int height)
// //
//========================================================================== //==========================================================================
PalettedPixels FJPEGTexture::CreatePalettedPixels(int conversion) PalettedPixels FJPEGTexture::CreatePalettedPixels(int conversion, int frame)
{ {
auto lump = fileSystem.OpenFileReader (SourceLump); auto lump = fileSystem.OpenFileReader (SourceLump);
JSAMPLE *buff = NULL; JSAMPLE *buff = NULL;
@ -401,7 +401,7 @@ PalettedPixels FJPEGTexture::CreatePalettedPixels(int conversion)
// //
//=========================================================================== //===========================================================================
int FJPEGTexture::CopyPixels(FBitmap *bmp, int conversion) int FJPEGTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
PalEntry pe[256]; PalEntry pe[256];

View file

@ -201,7 +201,7 @@ void FMultiPatchTexture::CopyToBlock(uint8_t *dest, int dwidth, int dheight, FIm
// //
//========================================================================== //==========================================================================
PalettedPixels FMultiPatchTexture::CreatePalettedPixels(int conversion) PalettedPixels FMultiPatchTexture::CreatePalettedPixels(int conversion, int frame)
{ {
int numpix = Width * Height; int numpix = Width * Height;
uint8_t blendwork[256]; uint8_t blendwork[256];
@ -278,7 +278,7 @@ PalettedPixels FMultiPatchTexture::CreatePalettedPixels(int conversion)
// //
//=========================================================================== //===========================================================================
int FMultiPatchTexture::CopyPixels(FBitmap *bmp, int conversion) int FMultiPatchTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
int retv = -1; int retv = -1;

View file

@ -74,8 +74,8 @@ protected:
TexPart *Parts; TexPart *Parts;
// The getters must optionally redirect if it's a simple one-patch texture. // The getters must optionally redirect if it's a simple one-patch texture.
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
void CopyToBlock(uint8_t *dest, int dwidth, int dheight, FImageSource *source, int xpos, int ypos, int rotate, const uint8_t *translation, int style); void CopyToBlock(uint8_t *dest, int dwidth, int dheight, FImageSource *source, int xpos, int ypos, int rotate, const uint8_t *translation, int style);
void CollectForPrecache(PrecacheInfo &info, bool requiretruecolor) override; void CollectForPrecache(PrecacheInfo &info, bool requiretruecolor) override;

View file

@ -62,8 +62,8 @@ class FPatchTexture : public FImageSource
bool isalpha = false; bool isalpha = false;
public: public:
FPatchTexture (int lumpnum, int w, int h, int lo, int to, bool isalphatex); FPatchTexture (int lumpnum, int w, int h, int lo, int to, bool isalphatex);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
bool SupportRemap0() override { return !badflag; } bool SupportRemap0() override { return !badflag; }
void DetectBadPatches(); void DetectBadPatches();
}; };
@ -167,14 +167,14 @@ FPatchTexture::FPatchTexture (int lumpnum, int w, int h, int lo, int to, bool is
// //
//========================================================================== //==========================================================================
PalettedPixels FPatchTexture::CreatePalettedPixels(int conversion) PalettedPixels FPatchTexture::CreatePalettedPixels(int conversion, int frame)
{ {
uint8_t *remap, remaptable[256]; uint8_t *remap, remaptable[256];
int numspans; int numspans;
const column_t *maxcol; const column_t *maxcol;
int x; int x;
FileData lump = fileSystem.ReadFile (SourceLump); auto lump = fileSystem.ReadFile (SourceLump);
const patch_t *patch = (const patch_t *)lump.GetMem(); const patch_t *patch = (const patch_t *)lump.GetMem();
maxcol = (const column_t *)((const uint8_t *)patch + fileSystem.FileLength (SourceLump) - 3); maxcol = (const column_t *)((const uint8_t *)patch + fileSystem.FileLength (SourceLump) - 3);
@ -264,7 +264,7 @@ PalettedPixels FPatchTexture::CreatePalettedPixels(int conversion)
// //
//========================================================================== //==========================================================================
int FPatchTexture::CopyPixels(FBitmap *bmp, int conversion) int FPatchTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
if (!isalpha) return FImageSource::CopyPixels(bmp, conversion); if (!isalpha) return FImageSource::CopyPixels(bmp, conversion);
else return CopyTranslatedPixels(bmp, GPalette.GrayscaleMap.Palette); else return CopyTranslatedPixels(bmp, GPalette.GrayscaleMap.Palette);
@ -284,7 +284,7 @@ void FPatchTexture::DetectBadPatches ()
// Check if this patch is likely to be a problem. // Check if this patch is likely to be a problem.
// It must be 256 pixels tall, and all its columns must have exactly // It must be 256 pixels tall, and all its columns must have exactly
// one post, where each post has a supposed length of 0. // one post, where each post has a supposed length of 0.
FileData lump = fileSystem.ReadFile (SourceLump); auto lump = fileSystem.ReadFile (SourceLump);
const patch_t *realpatch = (patch_t *)lump.GetMem(); const patch_t *realpatch = (patch_t *)lump.GetMem();
const uint32_t *cofs = realpatch->columnofs; const uint32_t *cofs = realpatch->columnofs;
int x, x2 = LittleShort(realpatch->width); int x, x2 = LittleShort(realpatch->width);

View file

@ -84,7 +84,7 @@ class FPCXTexture : public FImageSource
public: public:
FPCXTexture (int lumpnum, PCXHeader &); FPCXTexture (int lumpnum, PCXHeader &);
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
protected: protected:
void ReadPCX1bit (uint8_t *dst, FileReader & lump, PCXHeader *hdr); void ReadPCX1bit (uint8_t *dst, FileReader & lump, PCXHeader *hdr);
@ -92,7 +92,7 @@ protected:
void ReadPCX8bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr); void ReadPCX8bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr);
void ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr, int planes); void ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr, int planes);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
}; };
@ -345,7 +345,7 @@ void FPCXTexture::ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr
// //
//========================================================================== //==========================================================================
PalettedPixels FPCXTexture::CreatePalettedPixels(int conversion) PalettedPixels FPCXTexture::CreatePalettedPixels(int conversion, int frame)
{ {
uint8_t PaletteMap[256]; uint8_t PaletteMap[256];
PCXHeader header; PCXHeader header;
@ -433,7 +433,7 @@ PalettedPixels FPCXTexture::CreatePalettedPixels(int conversion)
// //
//=========================================================================== //===========================================================================
int FPCXTexture::CopyPixels(FBitmap *bmp, int conversion) int FPCXTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
PalEntry pe[256]; PalEntry pe[256];
PCXHeader header; PCXHeader header;

View file

@ -56,8 +56,8 @@ class FPNGTexture : public FImageSource
public: public:
FPNGTexture (FileReader &lump, int lumpnum, int width, int height, uint8_t bitdepth, uint8_t colortype, uint8_t interlace); FPNGTexture (FileReader &lump, int lumpnum, int width, int height, uint8_t bitdepth, uint8_t colortype, uint8_t interlace);
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
protected: protected:
void ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap); void ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap);
@ -412,7 +412,7 @@ void FPNGTexture::ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap)
// //
//========================================================================== //==========================================================================
PalettedPixels FPNGTexture::CreatePalettedPixels(int conversion) PalettedPixels FPNGTexture::CreatePalettedPixels(int conversion, int frame)
{ {
FileReader *lump; FileReader *lump;
FileReader lfr; FileReader lfr;
@ -553,7 +553,7 @@ PalettedPixels FPNGTexture::CreatePalettedPixels(int conversion)
// //
//=========================================================================== //===========================================================================
int FPNGTexture::CopyPixels(FBitmap *bmp, int conversion) int FPNGTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
// Parse pre-IDAT chunks. I skip the CRCs. Is that bad? // Parse pre-IDAT chunks. I skip the CRCs. Is that bad?
PalEntry pe[256]; PalEntry pe[256];

View file

@ -51,8 +51,8 @@ class FQOITexture : public FImageSource
{ {
public: public:
FQOITexture(int lumpnum, QOIHeader& header); FQOITexture(int lumpnum, QOIHeader& header);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
}; };
FImageSource *QOIImage_TryCreate(FileReader &file, int lumpnum) FImageSource *QOIImage_TryCreate(FileReader &file, int lumpnum)
@ -89,7 +89,7 @@ FQOITexture::FQOITexture(int lumpnum, QOIHeader& header)
if (header.channels == 3) bMasked = bTranslucent = false; if (header.channels == 3) bMasked = bTranslucent = false;
} }
PalettedPixels FQOITexture::CreatePalettedPixels(int conversion) PalettedPixels FQOITexture::CreatePalettedPixels(int conversion, int frame)
{ {
FBitmap bitmap; FBitmap bitmap;
bitmap.Create(Width, Height); bitmap.Create(Width, Height);
@ -124,7 +124,7 @@ PalettedPixels FQOITexture::CreatePalettedPixels(int conversion)
return Pixels; return Pixels;
} }
int FQOITexture::CopyPixels(FBitmap *bmp, int conversion) int FQOITexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
enum enum
{ {

View file

@ -52,8 +52,8 @@ class FRawPageTexture : public FImageSource
int mPaletteLump = -1; int mPaletteLump = -1;
public: public:
FRawPageTexture (int lumpnum); FRawPageTexture (int lumpnum);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
}; };
//========================================================================== //==========================================================================
@ -170,9 +170,9 @@ FRawPageTexture::FRawPageTexture (int lumpnum)
// //
//========================================================================== //==========================================================================
PalettedPixels FRawPageTexture::CreatePalettedPixels(int conversion) PalettedPixels FRawPageTexture::CreatePalettedPixels(int conversion, int frame)
{ {
FileData lump = fileSystem.ReadFile (SourceLump); auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes(); auto source = lump.GetBytes();
const uint8_t *source_p = source; const uint8_t *source_p = source;
uint8_t *dest_p; uint8_t *dest_p;
@ -199,13 +199,13 @@ PalettedPixels FRawPageTexture::CreatePalettedPixels(int conversion)
return Pixels; return Pixels;
} }
int FRawPageTexture::CopyPixels(FBitmap *bmp, int conversion) int FRawPageTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
if (mPaletteLump < 0) return FImageSource::CopyPixels(bmp, conversion); if (mPaletteLump < 0) return FImageSource::CopyPixels(bmp, conversion);
else else
{ {
FileData lump = fileSystem.ReadFile(SourceLump); auto lump = fileSystem.ReadFile(SourceLump);
FileData plump = fileSystem.ReadFile(mPaletteLump); auto plump = fileSystem.ReadFile(mPaletteLump);
auto source = lump.GetBytes(); auto source = lump.GetBytes();
auto psource = plump.GetBytes(); auto psource = plump.GetBytes();
PalEntry paldata[256]; PalEntry paldata[256];

View file

@ -98,7 +98,7 @@ public:
} }
} }
PalettedPixels CreatePalettedPixels(int conversion) override PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override
{ {
PalettedPixels Pix(512); PalettedPixels Pix(512);
if (conversion == luminance) if (conversion == luminance)
@ -118,7 +118,7 @@ public:
return Pix; return Pix;
} }
int CopyPixels(FBitmap *bmp, int conversion) override int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override
{ {
bmp->CopyPixelData(0, 0, Pixels, Width, Height, Height, 1, 0, GPalette.GrayRamp.Palette); bmp->CopyPixelData(0, 0, Pixels, Width, Height, Height, 1, 0, GPalette.GrayRamp.Palette);
return 0; return 0;

View file

@ -60,7 +60,7 @@ public:
Height = srcdata.GetHeight(); Height = srcdata.GetHeight();
bUseGamePalette = false; bUseGamePalette = false;
} }
int CopyPixels(FBitmap* bmp, int conversion) int CopyPixels(FBitmap* bmp, int conversion, int frame = 0)
{ {
bmp->Blit(0, 0, info); bmp->Blit(0, 0, info);
return 0; return 0;

View file

@ -77,30 +77,30 @@ class FStartupTexture : public FImageSource
{ {
public: public:
FStartupTexture (int lumpnum); FStartupTexture (int lumpnum);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame) override;
}; };
class FNotchTexture : public FImageSource class FNotchTexture : public FImageSource
{ {
public: public:
FNotchTexture (int lumpnum, int width, int height); FNotchTexture (int lumpnum, int width, int height);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame) override;
}; };
class FStrifeStartupTexture : public FImageSource class FStrifeStartupTexture : public FImageSource
{ {
public: public:
FStrifeStartupTexture (int lumpnum, int w, int h); FStrifeStartupTexture (int lumpnum, int w, int h);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
}; };
class FStrifeStartupBackground : public FImageSource class FStrifeStartupBackground : public FImageSource
{ {
public: public:
FStrifeStartupBackground (int lumpnum); FStrifeStartupBackground (int lumpnum);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
}; };
//========================================================================== //==========================================================================
@ -164,7 +164,7 @@ FStartupTexture::FStartupTexture (int lumpnum)
Height = 480; Height = 480;
bUseGamePalette = false; bUseGamePalette = false;
FileData lump = fileSystem.ReadFile (SourceLump); auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes(); auto source = lump.GetBytes();
// Initialize the bitmap palette. // Initialize the bitmap palette.
@ -231,9 +231,9 @@ void PlanarToChunky(T* dest, const uint8_t* src, const T* remap, int width, int
// //
//========================================================================== //==========================================================================
PalettedPixels FStartupTexture::CreatePalettedPixels(int conversion) PalettedPixels FStartupTexture::CreatePalettedPixels(int conversion, int frame)
{ {
FileData lump = fileSystem.ReadFile (SourceLump); auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes(); auto source = lump.GetBytes();
const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance); const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
@ -251,9 +251,9 @@ PalettedPixels FStartupTexture::CreatePalettedPixels(int conversion)
// //
//========================================================================== //==========================================================================
int FStartupTexture::CopyPixels(FBitmap *bmp, int conversion) int FStartupTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
FileData lump = fileSystem.ReadFile (SourceLump); auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes(); auto source = lump.GetBytes();
PlanarToChunky((uint32_t*)bmp->GetPixels(), source + 48, startuppalette32, Width, Height); PlanarToChunky((uint32_t*)bmp->GetPixels(), source + 48, startuppalette32, Width, Height);
return 0; return 0;
@ -279,9 +279,9 @@ FNotchTexture::FNotchTexture (int lumpnum, int width, int height)
// //
//========================================================================== //==========================================================================
PalettedPixels FNotchTexture::CreatePalettedPixels(int conversion) PalettedPixels FNotchTexture::CreatePalettedPixels(int conversion, int frame)
{ {
FileData lump = fileSystem.ReadFile (SourceLump); auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes(); auto source = lump.GetBytes();
const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance); const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
@ -302,9 +302,9 @@ PalettedPixels FNotchTexture::CreatePalettedPixels(int conversion)
// //
//========================================================================== //==========================================================================
int FNotchTexture::CopyPixels(FBitmap *bmp, int conversion) int FNotchTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
FileData lump = fileSystem.ReadFile (SourceLump); auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes(); auto source = lump.GetBytes();
auto Work = (uint32_t*)bmp->GetPixels(); auto Work = (uint32_t*)bmp->GetPixels();
@ -336,9 +336,9 @@ FStrifeStartupTexture::FStrifeStartupTexture (int lumpnum, int w, int h)
// //
//========================================================================== //==========================================================================
PalettedPixels FStrifeStartupTexture::CreatePalettedPixels(int conversion) PalettedPixels FStrifeStartupTexture::CreatePalettedPixels(int conversion, int frame)
{ {
FileData lump = fileSystem.ReadFile (SourceLump); auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes(); auto source = lump.GetBytes();
PalettedPixels Pixels(Width*Height); PalettedPixels Pixels(Width*Height);
const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance); const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
@ -366,7 +366,7 @@ FStrifeStartupBackground::FStrifeStartupBackground (int lumpnum)
// //
//========================================================================== //==========================================================================
PalettedPixels FStrifeStartupBackground::CreatePalettedPixels(int conversion) PalettedPixels FStrifeStartupBackground::CreatePalettedPixels(int conversion, int frame)
{ {
TArray<uint8_t> source(64000, true); TArray<uint8_t> source(64000, true);
memset(source.Data(), 0xF0, 64000); memset(source.Data(), 0xF0, 64000);

View file

@ -67,8 +67,8 @@ class FStbTexture : public FImageSource
public: public:
FStbTexture (int lumpnum, int w, int h); FStbTexture (int lumpnum, int w, int h);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
}; };
@ -117,7 +117,7 @@ FStbTexture::FStbTexture (int lumpnum, int w, int h)
// //
//========================================================================== //==========================================================================
PalettedPixels FStbTexture::CreatePalettedPixels(int conversion) PalettedPixels FStbTexture::CreatePalettedPixels(int conversion, int frame)
{ {
FBitmap bitmap; FBitmap bitmap;
bitmap.Create(Width, Height); bitmap.Create(Width, Height);
@ -156,7 +156,7 @@ PalettedPixels FStbTexture::CreatePalettedPixels(int conversion)
// //
//========================================================================== //==========================================================================
int FStbTexture::CopyPixels(FBitmap *bmp, int conversion) int FStbTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
auto lump = fileSystem.OpenFileReader (SourceLump); auto lump = fileSystem.OpenFileReader (SourceLump);
int x, y, chan; int x, y, chan;

View file

@ -80,11 +80,11 @@ class FTGATexture : public FImageSource
public: public:
FTGATexture (int lumpnum, TGAHeader *); FTGATexture (int lumpnum, TGAHeader *);
int CopyPixels(FBitmap *bmp, int conversion) override; int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
protected: protected:
void ReadCompressed(FileReader &lump, uint8_t * buffer, int bytesperpixel); void ReadCompressed(FileReader &lump, uint8_t * buffer, int bytesperpixel);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
}; };
//========================================================================== //==========================================================================
@ -178,7 +178,7 @@ void FTGATexture::ReadCompressed(FileReader &lump, uint8_t * buffer, int bytespe
// //
//========================================================================== //==========================================================================
PalettedPixels FTGATexture::CreatePalettedPixels(int conversion) PalettedPixels FTGATexture::CreatePalettedPixels(int conversion, int frame)
{ {
uint8_t PaletteMap[256]; uint8_t PaletteMap[256];
auto lump = fileSystem.OpenFileReader (SourceLump); auto lump = fileSystem.OpenFileReader (SourceLump);
@ -385,7 +385,7 @@ PalettedPixels FTGATexture::CreatePalettedPixels(int conversion)
// //
//=========================================================================== //===========================================================================
int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) int FTGATexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
PalEntry pe[256]; PalEntry pe[256];
auto lump = fileSystem.OpenFileReader (SourceLump); auto lump = fileSystem.OpenFileReader (SourceLump);

View file

@ -0,0 +1,148 @@
/*
** webptexture.cpp
** Texture class for WebP images.
**
**---------------------------------------------------------------------------
** Copyright 2023 Cacodemon345
** 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 "webp/decode.h"
#include "webp/mux.h"
#include "files.h"
#include "filesystem.h"
#include "bitmap.h"
#include "imagehelpers.h"
#include "image.h"
#include "printf.h"
class FWebPTexture : public FImageSource
{
public:
FWebPTexture(int lumpnum, int w, int h, int xoff, int yoff);
PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
int CopyPixels(FBitmap *bmp, int conversion, int frame = 0) override;
};
FImageSource *WebPImage_TryCreate(FileReader &file, int lumpnum)
{
int width = 0, height = 0;
int xoff = 0, yoff = 0;
file.Seek(0, FileReader::SeekSet);
uint8_t header[12];
if (file.Read(header, 12) != 12) return nullptr;
if (memcmp(header, "RIFF", 4) || memcmp(header + 8, "WEBP", 4)) return nullptr;
file.Seek(0, FileReader::SeekSet);
auto bytes = file.Read();
if (WebPGetInfo(bytes.data(), bytes.size(), &width, &height))
{
WebPData data{ bytes.data(), bytes.size() };
WebPData chunk_data;
auto mux = WebPMuxCreate(&data, 0);
if (mux)
{
const char fourcc[4] = { 'g', 'r', 'A', 'b' };
if (WebPMuxGetChunk(mux, fourcc, &chunk_data) == WEBP_MUX_OK && chunk_data.size >= 4)
{
xoff = chunk_data.bytes[0] | (chunk_data.bytes[1] << 8);
yoff = chunk_data.bytes[2] | (chunk_data.bytes[3] << 8);
}
WebPMuxDelete(mux);
}
return new FWebPTexture(lumpnum, width, height, xoff, yoff);
}
return nullptr;
}
FWebPTexture::FWebPTexture(int lumpnum, int w, int h, int xoff, int yoff)
: FImageSource(lumpnum)
{
Width = w;
Height = h;
LeftOffset = xoff;
TopOffset = yoff;
}
PalettedPixels FWebPTexture::CreatePalettedPixels(int conversion, int frame)
{
FBitmap bitmap;
bitmap.Create(Width, Height);
CopyPixels(&bitmap, conversion);
const uint8_t *data = bitmap.GetPixels();
uint8_t *dest_p;
int dest_adv = Height;
int dest_rew = Width * Height - 1;
PalettedPixels Pixels(Width*Height);
dest_p = Pixels.Data();
bool doalpha = conversion == luminance;
// Convert the source image from row-major to column-major format and remap it
for (int y = Height; y != 0; --y)
{
for (int x = Width; x != 0; --x)
{
int b = *data++;
int g = *data++;
int r = *data++;
int a = *data++;
if (a < 128) *dest_p = 0;
else *dest_p = ImageHelpers::RGBToPalette(doalpha, r, g, b);
dest_p += dest_adv;
}
dest_p -= dest_rew;
}
return Pixels;
}
int FWebPTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{
WebPDecoderConfig config;
auto bytes = fileSystem.ReadFile(SourceLump);
if (WebPInitDecoderConfig(&config) == false)
return 0;
config.options.no_fancy_upsampling = 0;
config.output.colorspace = MODE_BGRA;
config.output.u.RGBA.rgba = (uint8_t*)bmp->GetPixels();
config.output.u.RGBA.size = bmp->GetBufferSize();
config.output.u.RGBA.stride = bmp->GetPitch();
config.output.is_external_memory = 1;
(void)WebPDecode(bytes.GetBytes(), bytes.GetSize(), &config);
return 0;
}

View file

@ -182,7 +182,7 @@ void FGameTexture::AddAutoMaterials()
if (this->*(layer.pointer) == nullptr) // only if no explicit assignment had been done. if (this->*(layer.pointer) == nullptr) // only if no explicit assignment had been done.
{ {
FStringf lookup("%s%s%s", layer.path, fullname ? "" : "auto/", searchname.GetChars()); FStringf lookup("%s%s%s", layer.path, fullname ? "" : "auto/", searchname.GetChars());
auto lump = fileSystem.CheckNumForFullName(lookup, false, ns_global, true); auto lump = fileSystem.CheckNumForFullName(lookup, false, FileSys::ns_global, true);
if (lump != -1) if (lump != -1)
{ {
auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny); auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny);
@ -199,7 +199,7 @@ void FGameTexture::AddAutoMaterials()
if (!this->Layers || this->Layers.get()->*(layer.pointer) == nullptr) // only if no explicit assignment had been done. if (!this->Layers || this->Layers.get()->*(layer.pointer) == nullptr) // only if no explicit assignment had been done.
{ {
FStringf lookup("%s%s%s", layer.path, fullname ? "" : "auto/", searchname.GetChars()); FStringf lookup("%s%s%s", layer.path, fullname ? "" : "auto/", searchname.GetChars());
auto lump = fileSystem.CheckNumForFullName(lookup, false, ns_global, true); auto lump = fileSystem.CheckNumForFullName(lookup, false, FileSys::ns_global, true);
if (lump != -1) if (lump != -1)
{ {
auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny); auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny);

View file

@ -51,6 +51,7 @@ struct PrecacheDataPaletted
PalettedPixels Pixels; PalettedPixels Pixels;
int RefCount; int RefCount;
int ImageID; int ImageID;
int Frame;
}; };
struct PrecacheDataRgba struct PrecacheDataRgba
@ -59,6 +60,7 @@ struct PrecacheDataRgba
int TransInfo; int TransInfo;
int RefCount; int RefCount;
int ImageID; int ImageID;
int Frame;
}; };
// TMap doesn't handle this kind of data well. std::map neither. The linear search is still faster, even for a few 100 entries because it doesn't have to access the heap as often.. // TMap doesn't handle this kind of data well. std::map neither. The linear search is still faster, even for a few 100 entries because it doesn't have to access the heap as often..
@ -71,21 +73,21 @@ TArray<PrecacheDataRgba> precacheDataRgba;
// //
//=========================================================================== //===========================================================================
PalettedPixels FImageSource::CreatePalettedPixels(int conversion) PalettedPixels FImageSource::CreatePalettedPixels(int conversion, int frame)
{ {
PalettedPixels Pixels(Width * Height); PalettedPixels Pixels(Width * Height);
memset(Pixels.Data(), 0, Width * Height); memset(Pixels.Data(), 0, Width * Height);
return Pixels; return Pixels;
} }
PalettedPixels FImageSource::GetCachedPalettedPixels(int conversion) PalettedPixels FImageSource::GetCachedPalettedPixels(int conversion, int frame)
{ {
PalettedPixels ret; PalettedPixels ret;
auto imageID = ImageID; auto imageID = ImageID;
// Do we have this image in the cache? // Do we have this image in the cache?
unsigned index = conversion != normal? UINT_MAX : precacheDataPaletted.FindEx([=](PrecacheDataPaletted &entry) { return entry.ImageID == imageID; }); unsigned index = conversion != normal? UINT_MAX : precacheDataPaletted.FindEx([=](PrecacheDataPaletted &entry) { return entry.ImageID == imageID && entry.Frame == frame; });
if (index < precacheDataPaletted.Size()) if (index < precacheDataPaletted.Size())
{ {
auto cache = &precacheDataPaletted[index]; auto cache = &precacheDataPaletted[index];
@ -115,7 +117,7 @@ PalettedPixels FImageSource::GetCachedPalettedPixels(int conversion)
{ {
// This is either the only copy needed or some access outside the caching block. In these cases create a new one and directly return it. // This is either the only copy needed or some access outside the caching block. In these cases create a new one and directly return it.
//Printf("returning fresh copy of %s\n", name.GetChars()); //Printf("returning fresh copy of %s\n", name.GetChars());
return CreatePalettedPixels(conversion); return CreatePalettedPixels(conversion, frame);
} }
else else
{ {
@ -126,16 +128,16 @@ PalettedPixels FImageSource::GetCachedPalettedPixels(int conversion)
pdp->ImageID = imageID; pdp->ImageID = imageID;
pdp->RefCount = info->second - 1; pdp->RefCount = info->second - 1;
info->second = 0; info->second = 0;
pdp->Pixels = CreatePalettedPixels(normal); pdp->Pixels = CreatePalettedPixels(normal, frame);
ret.Pixels.Set(pdp->Pixels.Data(), pdp->Pixels.Size()); ret.Pixels.Set(pdp->Pixels.Data(), pdp->Pixels.Size());
} }
} }
return ret; return ret;
} }
TArray<uint8_t> FImageSource::GetPalettedPixels(int conversion) TArray<uint8_t> FImageSource::GetPalettedPixels(int conversion, int frame)
{ {
auto pix = GetCachedPalettedPixels(conversion); auto pix = GetCachedPalettedPixels(conversion, frame);
if (pix.ownsPixels()) if (pix.ownsPixels())
{ {
// return the pixel store of the returned data directly if this was the last reference. // return the pixel store of the returned data directly if this was the last reference.
@ -165,19 +167,19 @@ TArray<uint8_t> FImageSource::GetPalettedPixels(int conversion)
// //
//=========================================================================== //===========================================================================
int FImageSource::CopyPixels(FBitmap *bmp, int conversion) int FImageSource::CopyPixels(FBitmap *bmp, int conversion, int frame)
{ {
if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source. if (conversion == luminance) conversion = normal; // luminance images have no use as an RGB source.
PalEntry *palette = GPalette.BaseColors; PalEntry *palette = GPalette.BaseColors;
auto ppix = CreatePalettedPixels(conversion); auto ppix = CreatePalettedPixels(conversion, frame);
bmp->CopyPixelData(0, 0, ppix.Data(), Width, Height, Height, 1, 0, palette, nullptr); bmp->CopyPixelData(0, 0, ppix.Data(), Width, Height, Height, 1, 0, palette, nullptr);
return 0; return 0;
} }
int FImageSource::CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap) int FImageSource::CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap, int frame)
{ {
auto ppix = CreatePalettedPixels(normal); auto ppix = CreatePalettedPixels(normal, frame);
bmp->CopyPixelData(0, 0, ppix.Data(), Width, Height, Height, 1, 0, remap, nullptr); bmp->CopyPixelData(0, 0, ppix.Data(), Width, Height, Height, 1, 0, remap, nullptr);
return 0; return 0;
} }
@ -188,26 +190,31 @@ int FImageSource::CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap)
// //
//========================================================================== //==========================================================================
FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int *ptrans) FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int *ptrans, int frame)
{ {
FBitmap ret; FBitmap ret;
int trans = -1; int trans = -1;
auto imageID = ImageID; auto imageID = ImageID;
if (NumOfFrames == 1 && frame == 1)
{
frame = 0;
}
if (remap != nullptr) if (remap != nullptr)
{ {
// Remapped images are never run through the cache because they would complicate matters too much for very little gain. // Remapped images are never run through the cache because they would complicate matters too much for very little gain.
// Translated images are normally sprites which normally just consist of a single image and use no composition. // Translated images are normally sprites which normally just consist of a single image and use no composition.
// Additionally, since translation requires the base palette, the really time consuming stuff will never be subjected to it. // Additionally, since translation requires the base palette, the really time consuming stuff will never be subjected to it.
ret.Create(Width, Height); ret.Create(Width, Height);
trans = CopyTranslatedPixels(&ret, remap); trans = CopyTranslatedPixels(&ret, remap, frame);
} }
else else
{ {
if (conversion == luminance) conversion = normal; // luminance has no meaning for true color. if (conversion == luminance) conversion = normal; // luminance has no meaning for true color.
// Do we have this image in the cache? // Do we have this image in the cache?
unsigned index = conversion != normal? UINT_MAX : precacheDataRgba.FindEx([=](PrecacheDataRgba &entry) { return entry.ImageID == imageID; }); unsigned index = conversion != normal? UINT_MAX : precacheDataRgba.FindEx([=](PrecacheDataRgba &entry) { return entry.ImageID == imageID && entry.Frame == frame; });
if (index < precacheDataRgba.Size()) if (index < precacheDataRgba.Size())
{ {
auto cache = &precacheDataRgba[index]; auto cache = &precacheDataRgba[index];
@ -230,7 +237,7 @@ FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int
// This should never happen if the function is implemented correctly // This should never happen if the function is implemented correctly
//Printf("something bad happened for %s, refcount = %d\n", name.GetChars(), cache->RefCount); //Printf("something bad happened for %s, refcount = %d\n", name.GetChars(), cache->RefCount);
ret.Create(Width, Height); ret.Create(Width, Height);
trans = CopyPixels(&ret, normal); trans = CopyPixels(&ret, normal, frame);
} }
} }
else else
@ -242,7 +249,7 @@ FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int
// This is either the only copy needed or some access outside the caching block. In these cases create a new one and directly return it. // This is either the only copy needed or some access outside the caching block. In these cases create a new one and directly return it.
//Printf("returning fresh copy of %s\n", name.GetChars()); //Printf("returning fresh copy of %s\n", name.GetChars());
ret.Create(Width, Height); ret.Create(Width, Height);
trans = CopyPixels(&ret, conversion); trans = CopyPixels(&ret, conversion, frame);
} }
else else
{ {
@ -251,10 +258,11 @@ FBitmap FImageSource::GetCachedBitmap(const PalEntry *remap, int conversion, int
PrecacheDataRgba *pdr = &precacheDataRgba[precacheDataRgba.Reserve(1)]; PrecacheDataRgba *pdr = &precacheDataRgba[precacheDataRgba.Reserve(1)];
pdr->ImageID = imageID; pdr->ImageID = imageID;
pdr->Frame = frame;
pdr->RefCount = info->first - 1; pdr->RefCount = info->first - 1;
info->first = 0; info->first = 0;
pdr->Pixels.Create(Width, Height); pdr->Pixels.Create(Width, Height);
trans = pdr->TransInfo = CopyPixels(&pdr->Pixels, normal); trans = pdr->TransInfo = CopyPixels(&pdr->Pixels, normal, frame);
ret.Copy(pdr->Pixels, false); ret.Copy(pdr->Pixels, false);
} }
} }

View file

@ -67,12 +67,13 @@ protected:
int LeftOffset = 0, TopOffset = 0; // Offsets stored in the image. int LeftOffset = 0, TopOffset = 0; // Offsets stored in the image.
bool bUseGamePalette = false; // true if this is an image without its own color set. bool bUseGamePalette = false; // true if this is an image without its own color set.
int ImageID = -1; int ImageID = -1;
int NumOfFrames = 1;
// Internal image creation functions. All external access should go through the cache interface, // Internal image creation functions. All external access should go through the cache interface,
// so that all code can benefit from future improvements to that. // so that all code can benefit from future improvements to that.
virtual PalettedPixels CreatePalettedPixels(int conversion); virtual PalettedPixels CreatePalettedPixels(int conversion, int frame = 0);
int CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap); int CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap, int frame = 0);
public: public:
@ -101,19 +102,25 @@ public:
// 'noremap0' will only be looked at by FPatchTexture and forwarded by FMultipatchTexture. // 'noremap0' will only be looked at by FPatchTexture and forwarded by FMultipatchTexture.
// Either returns a reference to the cache, or a newly created item. The return of this has to be considered transient. If you need to store the result, use GetPalettedPixels // Either returns a reference to the cache, or a newly created item. The return of this has to be considered transient. If you need to store the result, use GetPalettedPixels
PalettedPixels GetCachedPalettedPixels(int conversion); PalettedPixels GetCachedPalettedPixels(int conversion, int frame = 0);
// tries to get a buffer from the cache. If not available, create a new one. If further references are pending, create a copy. // tries to get a buffer from the cache. If not available, create a new one. If further references are pending, create a copy.
TArray<uint8_t> GetPalettedPixels(int conversion); TArray<uint8_t> GetPalettedPixels(int conversion, int frame = 0);
virtual int CopyPixels(FBitmap* bmp, int conversion); virtual int CopyPixels(FBitmap* bmp, int conversion, int frame = 0);
FBitmap GetCachedBitmap(const PalEntry *remap, int conversion, int *trans = nullptr); FBitmap GetCachedBitmap(const PalEntry *remap, int conversion, int *trans = nullptr, int frame = 0);
static void ClearImages() { ImageArena.FreeAll(); ImageForLump.Clear(); NextID = 0; } static void ClearImages() { ImageArena.FreeAll(); ImageForLump.Clear(); NextID = 0; }
static FImageSource * GetImage(int lumpnum, bool checkflat); static FImageSource * GetImage(int lumpnum, bool checkflat);
// Frame functions
// Gets number of frames.
int GetNumOfFrames() { return NumOfFrames; }
// Gets duration of frame in miliseconds.
virtual int GetDurationOfFrame(int frame) { return 1000; }
// Conversion option // Conversion option
enum EType enum EType
@ -180,8 +187,8 @@ class FBuildTexture : public FImageSource
{ {
public: public:
FBuildTexture(const FString& pathprefix, int tilenum, const uint8_t* pixels, FRemapTable* translation, int width, int height, int left, int top); FBuildTexture(const FString& pathprefix, int tilenum, const uint8_t* pixels, FRemapTable* translation, int width, int height, int left, int top);
PalettedPixels CreatePalettedPixels(int conversion) override; PalettedPixels CreatePalettedPixels(int conversion, int frame = 0) override;
int CopyPixels(FBitmap* bmp, int conversion) override; int CopyPixels(FBitmap* bmp, int conversion, int frame = 0) override;
protected: protected:
const uint8_t* RawPixels; const uint8_t* RawPixels;
@ -191,4 +198,4 @@ protected:
class FTexture; class FTexture;
FTexture* CreateImageTexture(FImageSource* img) noexcept; FTexture* CreateImageTexture(FImageSource* img, int frame = 0) noexcept;

View file

@ -47,10 +47,11 @@
// //
//========================================================================== //==========================================================================
FImageTexture::FImageTexture(FImageSource *img) noexcept FImageTexture::FImageTexture(FImageSource *img, int frame) noexcept
: FTexture(img? img->LumpNum() : 0) : FTexture(img? img->LumpNum() : 0)
{ {
mImage = img; mImage = img;
TexFrame = frame;
if (img != nullptr) if (img != nullptr)
{ {
SetFromImage(); SetFromImage();
@ -79,7 +80,7 @@ void FImageTexture::SetFromImage()
FBitmap FImageTexture::GetBgraBitmap(const PalEntry *p, int *trans) FBitmap FImageTexture::GetBgraBitmap(const PalEntry *p, int *trans)
{ {
return mImage->GetCachedBitmap(p, bNoRemap0? FImageSource::noremap0 : FImageSource::normal, trans); return mImage->GetCachedBitmap(p, bNoRemap0? FImageSource::noremap0 : FImageSource::normal, trans, TexFrame);
} }
//=========================================================================== //===========================================================================
@ -90,7 +91,7 @@ FBitmap FImageTexture::GetBgraBitmap(const PalEntry *p, int *trans)
TArray<uint8_t> FImageTexture::Get8BitPixels(bool alpha) TArray<uint8_t> FImageTexture::Get8BitPixels(bool alpha)
{ {
return mImage->GetPalettedPixels(alpha? FImageSource::luminance : bNoRemap0 ? FImageSource::noremap0 : FImageSource::normal); return mImage->GetPalettedPixels(alpha? FImageSource::luminance : bNoRemap0 ? FImageSource::noremap0 : FImageSource::normal, TexFrame);
} }
//=========================================================================== //===========================================================================
@ -113,8 +114,8 @@ bool FImageTexture::DetermineTranslucency()
} }
FTexture* CreateImageTexture(FImageSource* img) noexcept FTexture* CreateImageTexture(FImageSource* img, int frame) noexcept
{ {
return new FImageTexture(img); return new FImageTexture(img, frame);
} }

View file

@ -47,7 +47,6 @@ enum ESSType
SS_BGRA SS_BGRA
}; };
class FileWriter;
// PNG Writing -------------------------------------------------------------- // PNG Writing --------------------------------------------------------------
// Start writing an 8-bit palettized PNG file. // Start writing an 8-bit palettized PNG file.
@ -82,13 +81,13 @@ struct PNGHandle
uint32_t Size; uint32_t Size;
}; };
FileReader File; FileSys::FileReader File;
bool bDeleteFilePtr; bool bDeleteFilePtr;
TArray<Chunk> Chunks; TArray<Chunk> Chunks;
TArray<char *> TextChunks; TArray<char *> TextChunks;
unsigned int ChunkPt; unsigned int ChunkPt;
PNGHandle(FileReader &file); PNGHandle(FileSys::FileReader &file);
~PNGHandle(); ~PNGHandle();
}; };
@ -96,7 +95,7 @@ struct PNGHandle
// the signature, but also checking for the IEND chunk. CRC checking of // the signature, but also checking for the IEND chunk. CRC checking of
// each chunk is not done. If it is valid, you get a PNGHandle to pass to // each chunk is not done. If it is valid, you get a PNGHandle to pass to
// the following functions. // the following functions.
PNGHandle *M_VerifyPNG (FileReader &file); PNGHandle *M_VerifyPNG (FileSys::FileReader &file);
// Finds a chunk in a PNG file. The file pointer will be positioned at the // Finds a chunk in a PNG file. The file pointer will be positioned at the
// beginning of the chunk data, and its length will be returned. A return // beginning of the chunk data, and its length will be returned. A return
@ -115,7 +114,7 @@ bool M_GetPNGText (PNGHandle *png, const char *keyword, char *buffer, size_t buf
// The file must be positioned at the start of the first IDAT. It reads // The file must be positioned at the start of the first IDAT. It reads
// image data into the provided buffer. Returns true on success. // image data into the provided buffer. Returns true on success.
bool M_ReadIDAT (FileReader &file, uint8_t *buffer, int width, int height, int pitch, bool M_ReadIDAT (FileSys::FileReader &file, uint8_t *buffer, int width, int height, int pitch,
uint8_t bitdepth, uint8_t colortype, uint8_t interlace, unsigned int idatlen); uint8_t bitdepth, uint8_t colortype, uint8_t interlace, unsigned int idatlen);

View file

@ -397,12 +397,12 @@ void FMultipatchTextureBuilder::AddTexturesLumps(int lump1, int lump2, int patch
if (lump1 >= 0) if (lump1 >= 0)
{ {
FileData texdir = fileSystem.ReadFile(lump1); auto texdir = fileSystem.ReadFile(lump1);
AddTexturesLump(texdir.GetMem(), fileSystem.FileLength(lump1), lump1, patcheslump, firstdup, true); AddTexturesLump(texdir.GetMem(), fileSystem.FileLength(lump1), lump1, patcheslump, firstdup, true);
} }
if (lump2 >= 0) if (lump2 >= 0)
{ {
FileData texdir = fileSystem.ReadFile(lump2); auto texdir = fileSystem.ReadFile(lump2);
AddTexturesLump(texdir.GetMem(), fileSystem.FileLength(lump2), lump2, patcheslump, firstdup, false); AddTexturesLump(texdir.GetMem(), fileSystem.FileLength(lump2), lump2, patcheslump, firstdup, false);
} }
} }

View file

@ -50,6 +50,7 @@
#include "basics.h" #include "basics.h"
#include "cmdlib.h" #include "cmdlib.h"
using namespace FileSys;
FTextureManager TexMan; FTextureManager TexMan;
@ -681,15 +682,15 @@ void FTextureManager::AddHiresTextures (int wadnum)
void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname, FMultipatchTextureBuilder &build) void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname, FMultipatchTextureBuilder &build)
{ {
int remapLump, lastLump; int texLump, lastLump;
lastLump = 0; lastLump = 0;
while ((remapLump = fileSystem.FindLump(lumpname, &lastLump)) != -1) while ((texLump = fileSystem.FindLump(lumpname, &lastLump)) != -1)
{ {
if (fileSystem.GetFileContainer(remapLump) == wadnum) if (fileSystem.GetFileContainer(texLump) == wadnum)
{ {
ParseTextureDef(remapLump, build); ParseTextureDef(texLump, build);
} }
} }
} }

View file

@ -379,10 +379,11 @@ class FImageTexture : public FTexture
{ {
FImageSource* mImage; FImageSource* mImage;
bool bNoRemap0 = false; bool bNoRemap0 = false;
int TexFrame = 0;
protected: protected:
void SetFromImage(); void SetFromImage();
public: public:
FImageTexture(FImageSource* image) noexcept; FImageTexture(FImageSource* image, int frame = 0) noexcept;
~FImageTexture(); ~FImageTexture();
TArray<uint8_t> Get8BitPixels(bool alphatex) override; TArray<uint8_t> Get8BitPixels(bool alphatex) override;

Some files were not shown because too many files have changed in this diff Show more