- backend update from GZDoom without adapting other code.

This commit is contained in:
Christoph Oelckers 2023-08-19 16:57:37 +02:00
parent 5eee7b80b1
commit cf19d75242
80 changed files with 743 additions and 2707 deletions

View file

@ -1108,8 +1108,6 @@ set (PCH_SOURCES
common/utility/m_alloc.cpp
common/utility/utf8.cpp
common/utility/palette.cpp
common/utility/files.cpp
common/utility/files_decompress.cpp
common/utility/memarena.cpp
common/utility/cmdlib.cpp
common/utility/configfile.cpp
@ -1126,19 +1124,6 @@ set (PCH_SOURCES
common/thirdparty/libsmackerdec/src/HuffmanVLC.cpp
common/thirdparty/libsmackerdec/src/LogError.cpp
common/thirdparty/libsmackerdec/src/SmackerDecoder.cpp
common/filesystem/filesystem.cpp
common/filesystem/ancientzip.cpp
common/filesystem/file_7z.cpp
common/filesystem/file_grp.cpp
common/filesystem/file_lump.cpp
common/filesystem/file_rff.cpp
common/filesystem/file_wad.cpp
common/filesystem/file_zip.cpp
common/filesystem/file_pak.cpp
common/filesystem/file_whres.cpp
common/filesystem/file_ssi.cpp
common/filesystem/file_directory.cpp
common/filesystem/resourcefile.cpp
common/engine/cycler.cpp
common/engine/d_event.cpp
common/engine/date.cpp
@ -1201,6 +1186,7 @@ set (PCH_SOURCES
common/rendering/gl/gl_samplers.cpp
common/rendering/gl/gl_shader.cpp
common/rendering/gl/gl_shaderprogram.cpp
common/scripting/core/maps.cpp
common/scripting/core/dictionary.cpp
common/scripting/core/dynarrays.cpp
common/scripting/core/symbols.cpp
@ -1285,6 +1271,24 @@ add_executable( ${PROJECT_NAME} WIN32 MACOSX_BUNDLE
common/thirdparty/math/tan.c
common/thirdparty/math/tanh.c
common/thirdparty/math/fastsin.cpp
common/filesystem/filesystem.cpp
common/filesystem/ancientzip.cpp
common/filesystem/file_7z.cpp
common/filesystem/file_grp.cpp
common/filesystem/file_lump.cpp
common/filesystem/file_rff.cpp
common/filesystem/file_wad.cpp
common/filesystem/file_zip.cpp
common/filesystem/file_pak.cpp
common/filesystem/file_whres.cpp
common/filesystem/file_ssi.cpp
common/filesystem/file_directory.cpp
common/filesystem/resourcefile.cpp
common/filesystem/files.cpp
common/filesystem/files_decompress.cpp
common/filesystem/fs_findfile.cpp
)
#set_source_files_properties( ${FASTMATH_SOURCES} PROPERTIES COMPILE_FLAGS ${DEM_FASTMATH_FLAG} )

View file

@ -68,7 +68,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, Clear, Shape2DTransform_Clear)
static void Shape2DTransform_Rotate(DShape2DTransform* self, double angle)
{
self->transform = DMatrix3x3::Rotate2D(DEG2RAD(angle)) * self->transform;
self->transform = DMatrix3x3::Rotate2D(angle) * self->transform;
}
DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, Rotate, Shape2DTransform_Rotate)

View file

@ -182,8 +182,8 @@ static void SetupGenMidi()
auto data = fileSystem.OpenFileReader(lump);
auto genmidi = data.Read();
if (genmidi.Size() < 8 + 175 * 36 || memcmp(genmidi.Data(), "#OPL_II#", 8)) return;
ZMusic_SetGenMidi(genmidi.Data()+8);
if (genmidi.size() < 8 + 175 * 36 || memcmp(genmidi.data(), "#OPL_II#", 8)) return;
ZMusic_SetGenMidi(genmidi.data()+8);
}
static void SetupWgOpn()
@ -337,7 +337,7 @@ static ZMusic_MidiSource GetMIDISource(const char *fn)
}
auto data = wlump.Read();
auto source = ZMusic_CreateMIDISource(data.Data(), data.Size(), type);
auto source = ZMusic_CreateMIDISource(data.data(), data.size(), type);
if (source == nullptr)
{

View file

@ -42,7 +42,8 @@
#include <zmusic.h>
#include "resourcefile.h"
#include "version.h"
#include "findfile.h"
#include "fs_findfile.h"
#include "resourcefile.h"
#include "i_interface.h"
#include "configfile.h"
#include "printf.h"
@ -197,7 +198,7 @@ FileReader FSF2Reader::OpenFile(const char *name)
FZipPatReader::FZipPatReader(const char *filename)
{
mAllowAbsolutePaths = true;
resf = FResourceFile::OpenResourceFile(filename, true);
resf = FResourceFile::OpenResourceFile(filename);
}
FZipPatReader::~FZipPatReader()
@ -391,9 +392,6 @@ void FSoundFontManager::ProcessOneFile(const FString &fn)
void FSoundFontManager::CollectSoundfonts()
{
findstate_t c_file;
void *file;
FConfigFile* GameConfig = sysCallbacks.GetConfig ? sysCallbacks.GetConfig() : nullptr;
if (GameConfig != NULL && GameConfig->SetSection ("SoundfontSearch.Directories"))
{
@ -404,25 +402,23 @@ void FSoundFontManager::CollectSoundfonts()
{
if (stricmp (key, "Path") == 0)
{
FileList list;
FString dir;
dir = NicePath(value);
FixPathSeperator(dir);
if (dir.IsNotEmpty())
{
if (dir.Back() != '/') dir += '/';
FString mask = dir + '*';
if ((file = I_FindFirst(mask, &c_file)) != ((void *)(-1)))
if (ScanDirectory(list, dir.GetChars(), "*", true))
{
do
for(auto& entry : list)
{
if (!(I_FindAttr(&c_file) & FA_DIREC))
if (!entry.isDirectory)
{
FStringf name("%s%s", dir.GetChars(), I_FindName(&c_file));
ProcessOneFile(name);
ProcessOneFile(entry.FilePath.c_str());
}
} while (I_FindNext(file, &c_file) == 0);
I_FindClose(file);
}
}
}
}

View file

@ -38,6 +38,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdexcept>
#include <memory>
#include "i_sound.h"
#include "i_music.h"

View file

@ -744,32 +744,33 @@ sfxinfo_t *SoundEngine::LoadSound(sfxinfo_t *sfx)
DPrintf(DMSG_NOTIFY, "Loading sound \"%s\" (%td)\n", sfx->name.GetChars(), sfx - &S_sfx[0]);
auto sfxdata = ReadSound(sfx->lumpnum);
int size = sfxdata.Size();
int size = (int)sfxdata.size();
if (size > 8)
{
int32_t dmxlen = LittleLong(((int32_t *)sfxdata.Data())[1]);
auto sfxp = sfxdata.data();
int32_t dmxlen = LittleLong(((int32_t *)sfxp)[1]);
// If the sound is voc, use the custom loader.
if (strncmp ((const char *)sfxdata.Data(), "Creative Voice File", 19) == 0)
if (memcmp (sfxp, "Creative Voice File", 19) == 0)
{
sfx->data = GSnd->LoadSoundVoc(sfxdata.Data(), size);
sfx->data = GSnd->LoadSoundVoc(sfxp, size);
}
// If the sound is raw, just load it as such.
else if (sfx->bLoadRAW)
{
sfx->data = GSnd->LoadSoundRaw(sfxdata.Data(), size, sfx->RawRate, 1, 8, sfx->LoopStart);
sfx->data = GSnd->LoadSoundRaw(sfxp, size, sfx->RawRate, 1, 8, sfx->LoopStart);
}
// Otherwise, try the sound as DMX format.
else if (((uint8_t *)sfxdata.Data())[0] == 3 && ((uint8_t *)sfxdata.Data())[1] == 0 && dmxlen <= size - 8)
else if (((uint8_t *)sfxp)[0] == 3 && ((uint8_t *)sfxp)[1] == 0 && dmxlen <= size - 8)
{
int frequency = LittleShort(((uint16_t *)sfxdata.Data())[1]);
int frequency = LittleShort(((uint16_t *)sfxp)[1]);
if (frequency == 0) frequency = 11025;
sfx->data = GSnd->LoadSoundRaw(sfxdata.Data()+8, dmxlen, frequency, 1, 8, sfx->LoopStart);
sfx->data = GSnd->LoadSoundRaw(sfxp+8, dmxlen, frequency, 1, 8, sfx->LoopStart);
}
// If that fails, let the sound system try and figure it out.
else
{
sfx->data = GSnd->LoadSound(sfxdata.Data(), size, sfx->LoopStart, sfx->LoopEnd);
sfx->data = GSnd->LoadSound(sfxp, size, sfx->LoopStart, sfx->LoopEnd);
}
}

View file

@ -216,7 +216,7 @@ private:
// Checks if a copy of this sound is already playing.
bool CheckSingular(FSoundID sound_id);
virtual TArray<uint8_t> ReadSound(int lumpnum) = 0;
virtual std::vector<uint8_t> ReadSound(int lumpnum) = 0;
protected:
virtual bool CheckSoundLimit(sfxinfo_t* sfx, const FVector3& pos, int near_limit, float limit_range, int sourcetype, const void* actor, int channel, float attenuation);

View file

@ -50,7 +50,7 @@
#include "filesystem.h"
#include "gstrings.h"
#include "version.h"
#include "findfile.h"
#include "fs_findfile.h"
#include "md5.h"
#include "i_specialpaths.h"
#include "i_system.h"
@ -176,6 +176,8 @@ UNSAFE_CCMD (crashout)
#endif
// commented out because it's very poorly implemented (it should not abuse I_ChDir like this!)
#if 0
UNSAFE_CCMD (dir)
{
FString dir, path;
@ -248,6 +250,7 @@ UNSAFE_CCMD (dir)
I_ChDir(curdir);
}
#endif
//==========================================================================
//

View file

@ -153,7 +153,7 @@ class AnmPlayer : public MoviePlayer
{
// This doesn't need its own class type
anim_t anim;
TArray<uint8_t> buffer;
std::vector<uint8_t> buffer;
int numframes = 0;
int curframe = 1;
int frametime = 0;
@ -173,7 +173,7 @@ public:
buffer = fr.ReadPadded(1);
fr.Close();
if (ANIM_LoadAnim(&anim, buffer.Data(), buffer.Size() - 1) < 0)
if (ANIM_LoadAnim(&anim, buffer.data(), buffer.size() - 1) < 0)
{
return;
}
@ -231,7 +231,6 @@ public:
~AnmPlayer()
{
buffer.Reset();
animtex.Clean();
}

View file

@ -18,7 +18,7 @@ enum EJoyAxis
};
// Generic configuration interface for a controller.
struct NOVTABLE IJoystickConfig
struct IJoystickConfig
{
virtual ~IJoystickConfig() = 0;

View file

@ -148,9 +148,9 @@ bool FScanner::OpenFile (const char *name)
if (!fr.OpenFile(name)) return false;
auto filesize = fr.GetLength();
auto filebuff = fr.Read();
if (filebuff.Size() == 0 && filesize > 0) return false;
if (filebuff.size() == 0 && filesize > 0) return false;
ScriptBuffer = FString((const char *)filebuff.Data(), filesize);
ScriptBuffer = FString((const char *)filebuff.data(), filesize);
ScriptName = name; // This is used for error messages so the full file name is preferable
LumpNum = -1;
PrepareScript ();

View file

@ -1,6 +1,7 @@
#ifndef __SC_MAN_H__
#define __SC_MAN_H__
#include <vector>
#include "zstring.h"
#include "tarray.h"
#include "name.h"
@ -74,6 +75,10 @@ public:
{
OpenMem(name, (const char*)buffer.Data(), buffer.Size());
}
void OpenMem(const char* name, const std::vector<uint8_t>& buffer)
{
OpenMem(name, (const char*)buffer.data(), (int)buffer.size());
}
void OpenString(const char *name, FString buffer);
void OpenLumpNum(int lump);
void Close();

View file

@ -747,6 +747,7 @@ FCompressedBuffer FSerializer::GetCompressedOutput()
FCompressedBuffer buff;
WriteObjects();
EndObject();
buff.filename = nullptr;
buff.mSize = (unsigned)w->mOutString.GetSize();
buff.mZipFlags = 0;
buff.mCRC32 = crc32(0, (const Bytef*)w->mOutString.GetString(), buff.mSize);
@ -1135,7 +1136,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe
const char *name;
auto lump = pic->GetSourceLump();
if (fileSystem.GetLinkedTexture(lump) == pic)
if (TexMan.GetLinkedTexture(lump) == pic)
{
name = fileSystem.GetFileFullName(lump);
}

View file

@ -77,9 +77,9 @@ void FStringTable::LoadStrings (const char *language)
//==========================================================================
TArray<TArray<FString>> FStringTable::parseCSV(const TArray<uint8_t> &buffer)
TArray<TArray<FString>> FStringTable::parseCSV(const std::vector<uint8_t> &buffer)
{
const size_t bufLength = buffer.Size();
const size_t bufLength = buffer.size();
TArray<TArray<FString>> data;
TArray<FString> row;
TArray<char> cell;
@ -186,10 +186,10 @@ bool FStringTable::readMacros(int lumpnum)
//
//==========================================================================
bool FStringTable::ParseLanguageCSV(int lumpnum, const TArray<uint8_t> &buffer)
bool FStringTable::ParseLanguageCSV(int lumpnum, const std::vector<uint8_t> &buffer)
{
if (buffer.Size() < 11) return false;
if (strnicmp((const char*)buffer.Data(), "default,", 8) && strnicmp((const char*)buffer.Data(), "identifier,", 11 )) return false;
if (buffer.size() < 11) return false;
if (strnicmp((const char*)buffer.data(), "default,", 8) && strnicmp((const char*)buffer.data(), "identifier,", 11 )) return false;
auto data = parseCSV(buffer);
int labelcol = -1;
@ -282,7 +282,7 @@ bool FStringTable::ParseLanguageCSV(int lumpnum, const TArray<uint8_t> &buffer)
//
//==========================================================================
void FStringTable::LoadLanguage (int lumpnum, const TArray<uint8_t> &buffer)
void FStringTable::LoadLanguage (int lumpnum, const std::vector<uint8_t> &buffer)
{
bool errordone = false;
TArray<uint32_t> activeMaps;

View file

@ -44,6 +44,7 @@
#include <stdlib.h>
#include <vector>
#include "basics.h"
#include "zstring.h"
#include "tarray.h"
@ -111,11 +112,11 @@ private:
LangMap allStrings;
TArray<std::pair<uint32_t, StringMap*>> currentLanguageSet;
void LoadLanguage (int lumpnum, const TArray<uint8_t> &buffer);
TArray<TArray<FString>> parseCSV(const TArray<uint8_t> &buffer);
bool ParseLanguageCSV(int lumpnum, const TArray<uint8_t> &buffer);
void LoadLanguage (int lumpnum, const std::vector<uint8_t> &buffer);
TArray<TArray<FString>> parseCSV(const std::vector<uint8_t> &buffer);
bool ParseLanguageCSV(int lumpnum, const std::vector<uint8_t> &buffer);
bool LoadLanguageFromSpreadsheet(int lumpnum, const TArray<uint8_t> &buffer);
bool LoadLanguageFromSpreadsheet(int lumpnum, const std::vector<uint8_t> &buffer);
bool readMacros(int lumpnum);
void DeleteString(int langid, FName label);
void DeleteForLabel(int lumpnum, FName label);

View file

@ -310,7 +310,7 @@ int FZipExploder::Explode(unsigned char *out, unsigned int outsize,
len += minMatchLen;
dist++;
if (bIdx + len > outsize) {
throw CExplosionError("Not enough output space");
return -1;
}
if ((unsigned int)dist > bIdx) {
/* Anything before the first input byte is zero. */

View file

@ -1,6 +1,5 @@
#pragma once
#include "files.h"
#include "engineerrors.h"
class FZipExploder
{
@ -42,10 +41,4 @@ public:
int Explode(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize, int flags);
};
class CExplosionError : public CRecoverableError
{
public:
CExplosionError(const char *message) : CRecoverableError(message) {}
};
int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize);

View file

@ -36,10 +36,8 @@
// Note that 7z made the unwise decision to include windows.h :(
#include "7z.h"
#include "7zCrc.h"
#include "resourcefile.h"
#include "cmdlib.h"
#include "printf.h"
#include "fs_findfile.h"
@ -169,7 +167,7 @@ struct F7ZLump : public FResourceLump
{
int Position;
virtual int FillCache();
virtual int FillCache() override;
};
@ -189,7 +187,7 @@ class F7ZFile : public FResourceFile
public:
F7ZFile(const char * filename, FileReader &filer);
bool Open(bool quiet, LumpFilterInfo* filter);
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
virtual ~F7ZFile();
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};
@ -216,7 +214,7 @@ F7ZFile::F7ZFile(const char * filename, FileReader &filer)
//
//==========================================================================
bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter)
bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf)
{
Archive = new C7zArchive(Reader);
int skipped = 0;
@ -227,25 +225,21 @@ bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter)
{
delete Archive;
Archive = NULL;
if (!quiet)
if (res == SZ_ERROR_UNSUPPORTED)
{
Printf("\n" TEXTCOLOR_RED "%s: ", FileName.GetChars());
if (res == SZ_ERROR_UNSUPPORTED)
{
Printf("Decoder does not support this archive\n");
}
else if (res == SZ_ERROR_MEM)
{
Printf("Cannot allocate memory\n");
}
else if (res == SZ_ERROR_CRC)
{
Printf("CRC error\n");
}
else
{
Printf("error #%d\n", res);
}
Printf(FSMessageLevel::Error, "%s: Decoder does not support this archive\n", FileName.c_str());
}
else if (res == SZ_ERROR_MEM)
{
Printf(FSMessageLevel::Error, "Cannot allocate memory\n");
}
else if (res == SZ_ERROR_CRC)
{
Printf(FSMessageLevel::Error, "CRC error\n");
}
else
{
Printf(FSMessageLevel::Error, "error #%d\n", res);
}
return false;
}
@ -256,8 +250,8 @@ bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter)
Lumps = new F7ZLump[NumLumps];
F7ZLump *lump_p = Lumps;
TArray<UInt16> nameUTF16;
TArray<char> nameASCII;
std::u16string nameUTF16;
std::string nameASCII;
for (uint32_t i = 0; i < NumLumps; ++i)
{
@ -276,19 +270,17 @@ bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter)
continue;
}
nameUTF16.Resize((unsigned)nameLength);
nameASCII.Resize((unsigned)nameLength);
SzArEx_GetFileNameUtf16(archPtr, i, &nameUTF16[0]);
nameUTF16.resize((unsigned)nameLength);
nameASCII.resize((unsigned)nameLength);
// note that the file system is not equipped to handle non-ASCII, so don't bother with proper Unicode conversion here.
SzArEx_GetFileNameUtf16(archPtr, i, (UInt16*)nameUTF16.data());
for (size_t c = 0; c < nameLength; ++c)
{
nameASCII[c] = static_cast<char>(nameUTF16[c]);
nameASCII[c] = tolower(static_cast<char>(nameUTF16[c]));
}
FixPathSeperator(&nameASCII[0]);
FixPathSeparator(&nameASCII.front());
FString name = &nameASCII[0];
name.ToLower();
lump_p->LumpNameSetup(name);
lump_p->LumpNameSetup(nameASCII.c_str());
lump_p->LumpSize = static_cast<int>(SzArEx_GetFileSize(archPtr, i));
lump_p->Owner = this;
lump_p->Flags = LUMPF_FULLPATH|LUMPF_COMPRESSED;
@ -308,7 +300,7 @@ bool F7ZFile::Open(bool quiet, LumpFilterInfo *filter)
if (SZ_OK != Archive->Extract(Lumps[0].Position, &temp[0]))
{
if (!quiet) Printf("\n%s: unsupported 7z/LZMA file!\n", FileName.GetChars());
Printf(FSMessageLevel::Error, "%s: unsupported 7z/LZMA file!\n", FileName.c_str());
return false;
}
}
@ -345,7 +337,11 @@ F7ZFile::~F7ZFile()
int F7ZLump::FillCache()
{
Cache = new char[LumpSize];
static_cast<F7ZFile*>(Owner)->Archive->Extract(Position, Cache);
SRes code = static_cast<F7ZFile*>(Owner)->Archive->Extract(Position, Cache);
if (code != SZ_OK)
{
throw FileSystemException("Error %d reading from 7z archive", code);
}
RefCount = 1;
return 1;
}
@ -356,7 +352,7 @@ int F7ZLump::FillCache()
//
//==========================================================================
FResourceFile *Check7Z(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter)
FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
char head[k7zSignatureSize];
@ -368,7 +364,7 @@ FResourceFile *Check7Z(const char *filename, FileReader &file, bool quiet, LumpF
if (!memcmp(head, k7zSignature, k7zSignatureSize))
{
auto rf = new F7ZFile(filename, file);
if (rf->Open(quiet, filter)) return rf;
if (rf->Open(filter, Printf)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader
delete rf;

View file

@ -37,9 +37,13 @@
#include <sys/stat.h>
#include "resourcefile.h"
#include "cmdlib.h"
#include "printf.h"
#include "findfile.h"
#include "fs_findfile.h"
std::string FS_FullPath(const char* directory);
#ifdef _WIN32
std::wstring toWide(const char* str);
#endif
//==========================================================================
//
@ -52,7 +56,7 @@ struct FDirectoryLump : public FResourceLump
FileReader NewReader() override;
int FillCache() override;
FString mFullPath;
std::string mFullPath;
};
@ -67,12 +71,12 @@ class FDirectory : public FResourceFile
TArray<FDirectoryLump> Lumps;
const bool nosubdir;
int AddDirectory(const char *dirpath);
int AddDirectory(const char* dirpath, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
void AddEntry(const char *fullpath, int size);
public:
FDirectory(const char * dirname, bool nosubdirflag = false);
bool Open(bool quiet, LumpFilterInfo* filter);
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};
@ -87,102 +91,50 @@ public:
FDirectory::FDirectory(const char * directory, bool nosubdirflag)
: FResourceFile(NULL), nosubdir(nosubdirflag)
{
FString dirname;
#ifdef _WIN32
directory = _fullpath(NULL, directory, _MAX_PATH);
#else
// Todo for Linux: Resolve the path before using it
#endif
dirname = directory;
#ifdef _WIN32
free((void *)directory);
#endif
dirname.Substitute("\\", "/");
if (dirname[dirname.Len()-1] != '/') dirname += '/';
FileName = dirname;
FileName = FS_FullPath(directory);
if (FileName[FileName.length()-1] != '/') FileName += '/';
}
//==========================================================================
//
// Windows version
//
//==========================================================================
int FDirectory::AddDirectory(const char *dirpath)
int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
void * handle;
int count = 0;
FString dirmatch = dirpath;
findstate_t find;
dirmatch += '*';
handle = I_FindFirst(dirmatch.GetChars(), &find);
if (handle == ((void *)(-1)))
FileList list;
if (!ScanDirectory(list, dirpath, "*"))
{
Printf("Could not scan '%s': %s\n", dirpath, strerror(errno));
Printf(FSMessageLevel::Error, "Could not scan '%s': %s\n", dirpath, strerror(errno));
}
else
{
do
for(auto& entry : list)
{
// I_FindName only returns the file's name and not its full path
auto attr = I_FindAttr(&find);
if (attr & FA_HIDDEN)
if (!entry.isDirectory)
{
// Skip hidden files and directories. (Prevents SVN bookkeeping
// info from being included.)
continue;
}
FString fi = I_FindName(&find);
if (attr & FA_DIREC)
{
if (nosubdir || (fi[0] == '.' &&
(fi[1] == '\0' ||
(fi[1] == '.' && fi[2] == '\0'))))
{
// Do not record . and .. directories.
continue;
}
FString newdir = dirpath;
newdir << fi << '/';
count += AddDirectory(newdir);
}
else
{
if (strstr(fi, ".orig") || strstr(fi, ".bak") || strstr(fi, ".cache"))
auto fi = entry.FileName;
for (auto& c : fi) c = tolower(c);
if (strstr(fi.c_str(), ".orig") || strstr(fi.c_str(), ".bak") || strstr(fi.c_str(), ".cache"))
{
// We shouldn't add backup files to the file system
continue;
}
size_t size = 0;
FString fn = FString(dirpath) + fi;
// The next one is courtesy of EDuke32. :(
// Putting cache files in the application directory is very bad style.
// Unfortunately, having a garbage file named "texture" present will cause serious problems down the line.
if (!stricmp(fi, "textures"))
if (filter->filenamecheck == nullptr || filter->filenamecheck(fi.c_str(), entry.FilePath.c_str()))
{
FILE* f = fopen(fn, "rb");
if (f)
if (entry.Length > 0x7fffffff)
{
char check[3]{};
fread(check, 1, 3, f);
if (!memcmp(check, "LZ4", 3)) continue;
Printf(FSMessageLevel::Warning, "%s is larger than 2GB and will be ignored\n", entry.FilePath.c_str());
}
}
if (GetFileInfo(fn, &size, nullptr))
{
AddEntry(fn, (int)size);
AddEntry(entry.FilePathRel.c_str(), (int)entry.Length);
count++;
}
}
} while (I_FindNext (handle, &find) == 0);
I_FindClose (handle);
}
}
return count;
}
@ -193,9 +145,9 @@ int FDirectory::AddDirectory(const char *dirpath)
//
//==========================================================================
bool FDirectory::Open(bool quiet, LumpFilterInfo* filter)
bool FDirectory::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
NumLumps = AddDirectory(FileName);
NumLumps = AddDirectory(FileName.c_str(), filter, Printf);
PostProcessArchive(&Lumps[0], sizeof(FDirectoryLump), filter);
return true;
}
@ -214,11 +166,11 @@ void FDirectory::AddEntry(const char *fullpath, int size)
lump_p->mFullPath = fullpath;
// [mxd] Convert name to lowercase
FString name = fullpath + strlen(FileName);
name.ToLower();
std::string name = fullpath + FileName;
for (auto& c : name) c = tolower(c);
// The lump's name is only the part relative to the main directory
lump_p->LumpNameSetup(name);
lump_p->LumpNameSetup(name.c_str());
lump_p->LumpSize = size;
lump_p->Owner = this;
lump_p->Flags = 0;
@ -235,7 +187,7 @@ void FDirectory::AddEntry(const char *fullpath, int size)
FileReader FDirectoryLump::NewReader()
{
FileReader fr;
fr.OpenFile(mFullPath);
fr.OpenFile(mFullPath.c_str());
return fr;
}
@ -249,12 +201,15 @@ int FDirectoryLump::FillCache()
{
FileReader fr;
Cache = new char[LumpSize];
if (!fr.OpenFile(mFullPath))
if (!fr.OpenFile(mFullPath.c_str()))
{
memset(Cache, 0, LumpSize);
return 0;
throw FileSystemException("unable to open file");
}
auto read = fr.Read(Cache, LumpSize);
if (read != LumpSize)
{
throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize);
}
fr.Read(Cache, LumpSize);
RefCount = 1;
return 1;
}
@ -265,10 +220,10 @@ int FDirectoryLump::FillCache()
//
//==========================================================================
FResourceFile *CheckDir(const char *filename, bool quiet, bool nosubdirflag, LumpFilterInfo* filter)
FResourceFile *CheckDir(const char *filename, bool nosubdirflag, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
auto rf = new FDirectory(filename, nosubdirflag);
if (rf->Open(quiet, filter)) return rf;
if (rf->Open(filter, Printf)) return rf;
delete rf;
return nullptr;
}

View file

@ -34,7 +34,9 @@
*/
#include "resourcefile.h"
#include "printf.h"
#include "fs_swap.h"
using namespace fs_private;
//==========================================================================
//
@ -72,7 +74,7 @@ class FGrpFile : public FUncompressedFile
{
public:
FGrpFile(const char * filename, FileReader &file);
bool Open(bool quiet, LumpFilterInfo* filter);
bool Open(LumpFilterInfo* filter);
};
@ -93,7 +95,7 @@ FGrpFile::FGrpFile(const char *filename, FileReader &file)
//
//==========================================================================
bool FGrpFile::Open(bool quiet, LumpFilterInfo*)
bool FGrpFile::Open(LumpFilterInfo* filter)
{
GrpHeader header;
@ -129,7 +131,7 @@ bool FGrpFile::Open(bool quiet, LumpFilterInfo*)
//
//==========================================================================
FResourceFile *CheckGRP(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter)
FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
char head[12];
@ -141,7 +143,7 @@ FResourceFile *CheckGRP(const char *filename, FileReader &file, bool quiet, Lump
if (!memcmp(head, "KenSilverman", 12))
{
auto rf = new FGrpFile(filename, file);
if (rf->Open(quiet, filter)) return rf;
if (rf->Open(filter)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader
delete rf;

View file

@ -33,8 +33,6 @@
*/
#include "resourcefile.h"
#include "cmdlib.h"
#include "printf.h"
//==========================================================================
//
@ -46,7 +44,7 @@ class FLumpFile : public FUncompressedFile
{
public:
FLumpFile(const char * filename, FileReader &file);
bool Open(bool quiet, LumpFilterInfo* filter);
bool Open(LumpFilterInfo* filter);
};
@ -67,21 +65,15 @@ FLumpFile::FLumpFile(const char *filename, FileReader &file)
//
//==========================================================================
bool FLumpFile::Open(bool quiet, LumpFilterInfo*)
bool FLumpFile::Open(LumpFilterInfo*)
{
FString name(ExtractFileBase(FileName, true));
Lumps.Resize(1);
Lumps[0].LumpNameSetup(name);
Lumps[0].LumpNameSetup(ExtractBaseName(FileName.c_str(), true).c_str());
Lumps[0].Owner = this;
Lumps[0].Position = 0;
Lumps[0].LumpSize = (int)Reader.GetLength();
Lumps[0].Flags = 0;
NumLumps = 1;
if (!quiet)
{
Printf("\n");
}
return true;
}
@ -91,11 +83,11 @@ bool FLumpFile::Open(bool quiet, LumpFilterInfo*)
//
//==========================================================================
FResourceFile *CheckLump(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter)
FResourceFile *CheckLump(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
// always succeeds
auto rf = new FLumpFile(filename, file);
if (rf->Open(quiet, filter)) return rf;
if (rf->Open(filter)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader
delete rf;
return NULL;

View file

@ -33,7 +33,8 @@
*/
#include "resourcefile.h"
#include "printf.h"
using namespace fs_private;
//==========================================================================
//
@ -44,14 +45,14 @@
struct dpackfile_t
{
char name[56];
int filepos, filelen;
uint32_t filepos, filelen;
} ;
struct dpackheader_t
{
int ident; // == IDPAKHEADER
int dirofs;
int dirlen;
uint32_t ident; // == IDPAKHEADER
uint32_t dirofs;
uint32_t dirlen;
} ;
@ -65,7 +66,7 @@ class FPakFile : public FUncompressedFile
{
public:
FPakFile(const char * filename, FileReader &file);
bool Open(bool quiet, LumpFilterInfo* filter);
bool Open(LumpFilterInfo* filter);
};
@ -88,7 +89,7 @@ FPakFile::FPakFile(const char *filename, FileReader &file)
//
//==========================================================================
bool FPakFile::Open(bool quiet, LumpFilterInfo* filter)
bool FPakFile::Open(LumpFilterInfo* filter)
{
dpackheader_t header;
@ -123,7 +124,7 @@ bool FPakFile::Open(bool quiet, LumpFilterInfo* filter)
//
//==========================================================================
FResourceFile *CheckPak(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter)
FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
char head[4];
@ -135,7 +136,7 @@ FResourceFile *CheckPak(const char *filename, FileReader &file, bool quiet, Lump
if (!memcmp(head, "PACK", 4))
{
auto rf = new FPakFile(filename, file);
if (rf->Open(quiet, filter)) return rf;
if (rf->Open(filter)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader
delete rf;

View file

@ -34,8 +34,9 @@
*/
#include "resourcefile.h"
#include "fs_swap.h"
#include "printf.h"
using namespace fs_private;
//==========================================================================
//
@ -74,7 +75,7 @@ struct RFFLump
struct FRFFLump : public FUncompressedLump
{
virtual FileReader *GetReader();
virtual int FillCache();
virtual int FillCache() override;
uint32_t IndexNum;
@ -111,7 +112,7 @@ class FRFFFile : public FResourceFile
public:
FRFFFile(const char * filename, FileReader &file);
virtual ~FRFFFile();
virtual bool Open(bool quiet, LumpFilterInfo* filter);
virtual bool Open(LumpFilterInfo* filter);
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};
@ -134,7 +135,7 @@ FRFFFile::FRFFFile(const char *filename, FileReader &file)
//
//==========================================================================
bool FRFFFile::Open(bool quiet, LumpFilterInfo*)
bool FRFFFile::Open(LumpFilterInfo*)
{
RFFLump *lumps;
RFFInfo header;
@ -219,7 +220,7 @@ int FRFFLump::FillCache()
if (Flags & LUMPF_COMPRESSED)
{
int cryptlen = min<int> (LumpSize, 256);
int cryptlen = std::min<int> (LumpSize, 256);
uint8_t *data = (uint8_t *)Cache;
for (int i = 0; i < cryptlen; ++i)
@ -237,7 +238,7 @@ int FRFFLump::FillCache()
//
//==========================================================================
FResourceFile *CheckRFF(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter)
FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
char head[4];
@ -249,7 +250,7 @@ FResourceFile *CheckRFF(const char *filename, FileReader &file, bool quiet, Lump
if (!memcmp(head, "RFF\x1a", 4))
{
auto rf = new FRFFFile(filename, file);
if (rf->Open(quiet, filter)) return rf;
if (rf->Open(filter)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader
delete rf;

View file

@ -34,7 +34,6 @@
*/
#include "resourcefile.h"
#include "printf.h"
//==========================================================================
//
@ -46,7 +45,7 @@ class FSSIFile : public FUncompressedFile
{
public:
FSSIFile(const char * filename, FileReader &file);
bool Open(bool quiet, int version, int lumpcount, LumpFilterInfo* filter);
bool Open(int version, int lumpcount, LumpFilterInfo* filter);
};
@ -68,7 +67,7 @@ FSSIFile::FSSIFile(const char *filename, FileReader &file)
//
//==========================================================================
bool FSSIFile::Open(bool quiet, int version, int lumpcount, LumpFilterInfo*)
bool FSSIFile::Open(int version, int lumpcount, LumpFilterInfo*)
{
NumLumps = lumpcount*2;
Lumps.Resize(lumpcount*2);
@ -115,7 +114,7 @@ bool FSSIFile::Open(bool quiet, int version, int lumpcount, LumpFilterInfo*)
//
//==========================================================================
FResourceFile* CheckSSI(const char* filename, FileReader& file, bool quiet, LumpFilterInfo* filter)
FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
char zerobuf[72];
char buf[72];
@ -146,7 +145,7 @@ FResourceFile* CheckSSI(const char* filename, FileReader& file, bool quiet, Lump
if (!skipstring(70)) return nullptr;
}
auto ssi = new FSSIFile(filename, file);
if (ssi->Open(filename, version, numfiles, filter)) return ssi;
if (ssi->Open(version, numfiles, filter)) return ssi;
file = std::move(ssi->Reader); // to avoid destruction of reader
delete ssi;
}

View file

@ -35,9 +35,10 @@
#include <ctype.h>
#include "resourcefile.h"
#include "v_text.h"
#include "filesystem.h"
#include "engineerrors.h"
#include "fs_swap.h"
using namespace fs_private;
struct wadinfo_t
@ -101,13 +102,19 @@ public:
if(Compressed)
{
FileReader lzss;
if (lzss.OpenDecompressor(Owner->Reader, LumpSize, METHOD_LZSS, false, [](const char* err) { I_Error("%s", err); }))
if (lzss.OpenDecompressor(Owner->Reader, LumpSize, METHOD_LZSS, false, true))
{
lzss.Read(Cache, LumpSize);
}
}
else
Owner->Reader.Read(Cache, LumpSize);
{
auto read = Owner->Reader.Read(Cache, LumpSize);
if (read != LumpSize)
{
throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize);
}
}
RefCount = 1;
return 1;
@ -125,13 +132,13 @@ class FWadFile : public FResourceFile
TArray<FWadFileLump> Lumps;
bool IsMarker(int lump, const char *marker);
void SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, bool flathack=false);
void SkinHack ();
void SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, FileSystemMessageFunc Printf, bool flathack=false);
void SkinHack (FileSystemMessageFunc Printf);
public:
FWadFile(const char * filename, FileReader &file);
FResourceLump *GetLump(int lump) { return &Lumps[lump]; }
bool Open(bool quiet, LumpFilterInfo* filter);
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
};
@ -154,7 +161,7 @@ FWadFile::FWadFile(const char *filename, FileReader &file)
//
//==========================================================================
bool FWadFile::Open(bool quiet, LumpFilterInfo*)
bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf)
{
wadinfo_t header;
uint32_t InfoTableOfs;
@ -176,7 +183,8 @@ bool FWadFile::Open(bool quiet, LumpFilterInfo*)
// Check again to detect broken wads
if (InfoTableOfs + NumLumps*sizeof(wadlump_t) > (unsigned)wadSize)
{
I_Error("Cannot load broken WAD file %s\n", FileName.GetChars());
Printf(FSMessageLevel::Error, "%s: Bad directory offset.\n", FileName.c_str());
return false;
}
}
@ -195,10 +203,10 @@ bool FWadFile::Open(bool quiet, LumpFilterInfo*)
// This requires explicit toggling for precisely the files that need it.
#if 0
Lumps[i].Compressed = !(gameinfo.flags & GI_SHAREWARE) && (n[0] & 0x80) == 0x80;
n[0] &= ~0x80;
#else
Lumps[i].Compressed = false;
#endif
n[0] &= ~0x80;
Lumps[i].LumpNameSetup(n);
Lumps[i].Owner = this;
@ -212,7 +220,7 @@ bool FWadFile::Open(bool quiet, LumpFilterInfo*)
{
if (Lumps[i].LumpSize != 0)
{
Printf(PRINT_HIGH, "%s: Lump %s contains invalid positioning info and will be ignored\n", FileName.GetChars(), Lumps[i].getName());
Printf(FSMessageLevel::Warning, "%s: Lump %s contains invalid positioning info and will be ignored\n", FileName.c_str(), Lumps[i].getName());
Lumps[i].LumpNameSetup("");
}
Lumps[i].LumpSize = Lumps[i].Position = 0;
@ -221,18 +229,15 @@ bool FWadFile::Open(bool quiet, LumpFilterInfo*)
GenerateHash(); // Do this before the lump processing below.
if (!quiet) // don't bother with namespaces in quiet mode. We won't need them.
{
SetNamespace("S_START", "S_END", ns_sprites);
SetNamespace("F_START", "F_END", ns_flats, true);
SetNamespace("C_START", "C_END", ns_colormaps);
SetNamespace("A_START", "A_END", ns_acslibrary);
SetNamespace("TX_START", "TX_END", ns_newtextures);
SetNamespace("V_START", "V_END", ns_strifevoices);
SetNamespace("HI_START", "HI_END", ns_hires);
SetNamespace("VX_START", "VX_END", ns_voxels);
SkinHack();
}
SetNamespace("S_START", "S_END", ns_sprites, Printf);
SetNamespace("F_START", "F_END", ns_flats, Printf, true);
SetNamespace("C_START", "C_END", ns_colormaps, Printf);
SetNamespace("A_START", "A_END", ns_acslibrary, Printf);
SetNamespace("TX_START", "TX_END", ns_newtextures, Printf);
SetNamespace("V_START", "V_END", ns_strifevoices, Printf);
SetNamespace("HI_START", "HI_END", ns_hires, Printf);
SetNamespace("VX_START", "VX_END", ns_voxels, Printf);
SkinHack(Printf);
return true;
}
@ -273,7 +278,7 @@ struct Marker
unsigned int index;
};
void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, bool flathack)
void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, FileSystemMessageFunc Printf, bool flathack)
{
bool warned = false;
int numstartmarkers = 0, numendmarkers = 0;
@ -300,7 +305,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
{
if (numendmarkers == 0) return; // no markers found
Printf(TEXTCOLOR_YELLOW"WARNING: %s marker without corresponding %s found.\n", endmarker, startmarker);
Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.c_str(), endmarker, startmarker);
if (flathack)
@ -314,7 +319,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
{
// We can't add this to the flats namespace but
// it needs to be flagged for the texture manager.
DPrintf(DMSG_NOTIFY, "Marking %s as potential flat\n", Lumps[ii].getName());
Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName.c_str(), Lumps[ii].getName());
Lumps[ii].Flags |= LUMPF_MAYBEFLAT;
}
}
@ -328,7 +333,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
int start, end;
if (markers[i].markertype != 0)
{
Printf(TEXTCOLOR_YELLOW"WARNING: %s marker without corresponding %s found.\n", endmarker, startmarker);
Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.c_str(), endmarker, startmarker);
i++;
continue;
}
@ -337,21 +342,21 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
// skip over subsequent x_START markers
while (i < markers.Size() && markers[i].markertype == 0)
{
Printf(TEXTCOLOR_YELLOW"WARNING: duplicate %s marker found.\n", startmarker);
Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName.c_str(), startmarker);
i++;
continue;
}
// same for x_END markers
while (i < markers.Size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1))
{
Printf(TEXTCOLOR_YELLOW"WARNING: duplicate %s marker found.\n", endmarker);
Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName.c_str(), endmarker);
i++;
continue;
}
// We found a starting marker but no end marker. Ignore this block.
if (i >= markers.Size())
{
Printf(TEXTCOLOR_YELLOW"WARNING: %s marker without corresponding %s found.\n", startmarker, endmarker);
Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.c_str(), startmarker, endmarker);
end = NumLumps;
}
else
@ -360,14 +365,14 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
}
// we found a marked block
DPrintf(DMSG_NOTIFY, "Found %s block at (%d-%d)\n", startmarker, markers[start].index, end);
Printf(FSMessageLevel::DebugNotify, "%s: Found %s block at (%d-%d)\n", FileName.c_str(), startmarker, markers[start].index, end);
for(int j = markers[start].index + 1; j < end; j++)
{
if (Lumps[j].Namespace != ns_global)
{
if (!warned)
{
Printf(TEXTCOLOR_YELLOW"WARNING: Overlapping namespaces found (lump %d)\n", j);
Printf(FSMessageLevel::Warning, "%s: Overlapping namespaces found (lump %d)\n", FileName.c_str(), j);
}
warned = true;
}
@ -377,7 +382,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
// ignore sprite lumps smaller than 8 bytes (the smallest possible)
// in size -- this was used by some dmadds wads
// as an 'empty' graphics resource
DPrintf(DMSG_WARNING, " Skipped empty sprite %s (lump %d)\n", Lumps[j].getName(), j);
Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName.c_str(), Lumps[j].getName(), j);
}
else
{
@ -401,7 +406,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
//
//==========================================================================
void FWadFile::SkinHack ()
void FWadFile::SkinHack (FileSystemMessageFunc Printf)
{
// this being static is not a problem. The only relevant thing is that each skin gets a different number.
static int namespc = ns_firstskin;
@ -447,11 +452,8 @@ void FWadFile::SkinHack ()
}
if (skinned && hasmap)
{
Printf (TEXTCOLOR_BLUE
"The maps in %s will not be loaded because it has a skin.\n"
TEXTCOLOR_BLUE
"You should remove the skin from the wad to play these maps.\n",
FileName.GetChars());
Printf(FSMessageLevel::Attention, "%s: The maps will not be loaded because it has a skin.\n", FileName.c_str());
Printf(FSMessageLevel::Attention, "You should remove the skin from the wad to play these maps.\n");
}
}
@ -462,7 +464,7 @@ void FWadFile::SkinHack ()
//
//==========================================================================
FResourceFile *CheckWad(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter)
FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
char head[4];
@ -474,7 +476,7 @@ FResourceFile *CheckWad(const char *filename, FileReader &file, bool quiet, Lump
if (!memcmp(head, "IWAD", 4) || !memcmp(head, "PWAD", 4))
{
auto rf = new FWadFile(filename, file);
if (rf->Open(quiet, filter)) return rf;
if (rf->Open(filter, Printf)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader
delete rf;

View file

@ -35,55 +35,35 @@
*/
#include "resourcefile.h"
#include "printf.h"
#include "cmdlib.h"
#include "fs_swap.h"
using namespace fs_private;
//==========================================================================
//
//
//
//==========================================================================
struct whresentry
{
int filepospage, filelen, priority;
} ;
struct dpackheader_t
{
int ident; // == IDPAKHEADER
int dirofs;
int dirlen;
} ;
//==========================================================================
//
// Wad file
// WH resource file
//
//==========================================================================
class FWHResFile : public FUncompressedFile
{
FString basename;
std::string basename;
public:
FWHResFile(const char * filename, FileReader &file);
bool Open(bool quiet, LumpFilterInfo* filter);
bool Open(LumpFilterInfo* filter);
};
//==========================================================================
//
// FWadFile::FWadFile
//
// Initializes a WAD file
//
//==========================================================================
FWHResFile::FWHResFile(const char *filename, FileReader &file)
: FUncompressedFile(filename, file)
{
basename = ExtractFileBase(filename, false);
basename = ExtractBaseName(filename, false);
}
//==========================================================================
@ -92,9 +72,9 @@ FWHResFile::FWHResFile(const char *filename, FileReader &file)
//
//==========================================================================
bool FWHResFile::Open(bool quiet, LumpFilterInfo*)
bool FWHResFile::Open(LumpFilterInfo*)
{
int directory[1024];
uint32_t directory[1024];
Reader.Seek(-4096, FileReader::SeekEnd);
Reader.Read(directory, 4096);
@ -106,11 +86,13 @@ bool FWHResFile::Open(bool quiet, LumpFilterInfo*)
int i = 0;
for(int k = 0; k < nl; k++)
{
int offset = LittleLong(directory[k*3]) * 4096;
int length = LittleLong(directory[k*3+1]);
if (length <= 0) break;
FStringf synthname("%s/%04d", basename.GetChars(), k);
Lumps[i].LumpNameSetup(synthname);
uint32_t offset = LittleLong(directory[k*3]) * 4096;
uint32_t length = LittleLong(directory[k*3+1]);
if (length == 0) break;
char num[5];
snprintf(num, 5, "/%04d", k);
std::string synthname = basename + num;
Lumps[i].LumpNameSetup(synthname.c_str());
Lumps[i].Owner = this;
Lumps[i].Position = offset;
Lumps[i].LumpSize = length;
@ -129,27 +111,28 @@ bool FWHResFile::Open(bool quiet, LumpFilterInfo*)
//
//==========================================================================
FResourceFile *CheckWHRes(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter)
FResourceFile *CheckWHRes(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
if (file.GetLength() >= 8192) // needs to be at least 8192 to contain one file and the directory.
{
int directory[1024];
unsigned directory[1024];
int nl =1024/3;
file.Seek(-4096, FileReader::SeekEnd);
file.Read(directory, 4096);
auto size = file.GetLength();
int checkpos = 0;
uint32_t checkpos = 0;
for(int k = 0; k < nl; k++)
{
int offset = LittleLong(directory[k*3]);
int length = LittleLong(directory[k*3+1]);
unsigned offset = LittleLong(directory[k*3]);
unsigned length = LittleLong(directory[k*3+1]);
if (length <= 0 && offset == 0) break;
if (offset != checkpos || length <= 0) return nullptr;
if (offset != checkpos || length == 0 || offset + length >= (size_t)size - 4096 ) return nullptr;
checkpos += (length+4095) / 4096;
}
auto rf = new FWHResFile(filename, file);
if (rf->Open(quiet, filter)) return rf;
if (rf->Open(filter)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader
delete rf;
}

View file

@ -34,13 +34,14 @@
*/
#include <time.h>
#include <stdexcept>
#include "file_zip.h"
#include "cmdlib.h"
#include "printf.h"
#include "w_zip.h"
#include "ancientzip.h"
#include "fs_findfile.h"
#include "fs_swap.h"
using namespace fs_private;
#define BUFREADCOMMENT (0x400)
@ -50,52 +51,48 @@
//
//==========================================================================
static bool UncompressZipLump(char *Cache, FileReader &Reader, int Method, int LumpSize, int CompressedSize, int GPFlags)
static bool UncompressZipLump(char *Cache, FileReader &Reader, int Method, int LumpSize, int CompressedSize, int GPFlags, bool exceptions)
{
try
switch (Method)
{
switch (Method)
{
case METHOD_STORED:
{
Reader.Read(Cache, LumpSize);
break;
}
case METHOD_DEFLATE:
case METHOD_BZIP2:
case METHOD_LZMA:
{
FileReader frz;
if (frz.OpenDecompressor(Reader, LumpSize, Method, false, [](const char* err) { I_Error("%s", err); }))
{
frz.Read(Cache, LumpSize);
}
break;
}
// Fixme: These should also use a stream
case METHOD_IMPLODE:
{
FZipExploder exploder;
exploder.Explode((unsigned char *)Cache, LumpSize, Reader, CompressedSize, GPFlags);
break;
}
case METHOD_SHRINK:
{
ShrinkLoop((unsigned char *)Cache, LumpSize, Reader, CompressedSize);
break;
}
default:
assert(0);
return false;
}
case METHOD_STORED:
{
Reader.Read(Cache, LumpSize);
break;
}
catch (CRecoverableError &err)
case METHOD_DEFLATE:
case METHOD_BZIP2:
case METHOD_LZMA:
{
Printf("%s\n", err.GetMessage());
FileReader frz;
if (frz.OpenDecompressor(Reader, LumpSize, Method, false, exceptions))
{
frz.Read(Cache, LumpSize);
}
break;
}
// Fixme: These should also use a stream
case METHOD_IMPLODE:
{
FZipExploder exploder;
if (exploder.Explode((unsigned char*)Cache, LumpSize, Reader, CompressedSize, GPFlags) == -1)
{
// decompression failed so zero the cache.
memset(Cache, 0, LumpSize);
}
break;
}
case METHOD_SHRINK:
{
ShrinkLoop((unsigned char *)Cache, LumpSize, Reader, CompressedSize);
break;
}
default:
assert(0);
return false;
}
return true;
@ -105,7 +102,7 @@ bool FCompressedBuffer::Decompress(char *destbuffer)
{
FileReader mr;
mr.OpenMemory(mBuffer, mCompressedSize);
return UncompressZipLump(destbuffer, mr, mMethod, mSize, mCompressedSize, mZipFlags);
return UncompressZipLump(destbuffer, mr, mMethod, mSize, mCompressedSize, mZipFlags, false);
}
//-----------------------------------------------------------------------
@ -124,7 +121,7 @@ static uint32_t Zip_FindCentralDir(FileReader &fin, bool* zip64)
uint32_t uPosFound=0;
FileSize = (uint32_t)fin.GetLength();
uMaxBack = min<uint32_t>(0xffff, FileSize);
uMaxBack = std::min<uint32_t>(0xffff, FileSize);
uBackRead = 4;
while (uBackRead < uMaxBack)
@ -137,7 +134,7 @@ static uint32_t Zip_FindCentralDir(FileReader &fin, bool* zip64)
uBackRead += BUFREADCOMMENT;
uReadPos = FileSize - uBackRead;
uReadSize = min<uint32_t>((BUFREADCOMMENT + 4), (FileSize - uReadPos));
uReadSize = std::min<uint32_t>((BUFREADCOMMENT + 4), (FileSize - uReadPos));
if (fin.Seek(uReadPos, FileReader::SeekSet) != 0) break;
@ -173,7 +170,7 @@ FZipFile::FZipFile(const char * filename, FileReader &file)
Lumps = NULL;
}
bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
bool zip64 = false;
uint32_t centraldir = Zip_FindCentralDir(Reader, &zip64);
@ -183,7 +180,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
if (centraldir == 0)
{
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: ZIP file corrupt!\n", FileName.GetChars());
Printf(FSMessageLevel::Error, "%s: ZIP file corrupt!\n", FileName.c_str());
return false;
}
@ -199,7 +196,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
if (info.NumEntries != info.NumEntriesOnAllDisks ||
info.FirstDisk != 0 || info.DiskNumber != 0)
{
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", FileName.GetChars());
Printf(FSMessageLevel::Error, "%s: Multipart Zip files are not supported.\n", FileName.c_str());
return false;
}
@ -218,7 +215,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
if (info.NumEntries != info.NumEntriesOnAllDisks ||
info.FirstDisk != 0 || info.DiskNumber != 0)
{
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", FileName.GetChars());
Printf(FSMessageLevel::Error, "%s: Multipart Zip files are not supported.\n", FileName.c_str());
return false;
}
@ -236,7 +233,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
char *dirptr = (char*)directory;
FZipLump *lump_p = Lumps;
FString name0, name1;
std::string name0, name1;
bool foundspeciallump = false;
bool foundprefix = false;
@ -247,7 +244,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr;
int len = LittleShort(zip_fh->NameLength);
FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len);
std::string name(dirptr + sizeof(FZipCentralDirectoryInfo), len);
dirptr += sizeof(FZipCentralDirectoryInfo) +
LittleShort(zip_fh->NameLength) +
@ -257,38 +254,40 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file.
{
free(directory);
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", FileName.GetChars());
Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName.c_str());
return false;
}
name.ToLower();
if (name.IndexOf("filter/") == 0)
for (auto& c : name) c = tolower(c);
if (name.find_first_of("filter/") == 0)
continue; // 'filter' is a reserved name of the file system.
if (name.IndexOf("__macosx") == 0)
if (name.find_first_of("__macosx") == 0)
continue; // skip Apple garbage. At this stage only the root folder matters.
if (name.IndexOf(".bat") >= 0 || name.IndexOf(".exe") >= 0)
if (name.find_first_of(".bat") != std::string::npos || name.find_first_of(".exe") != std::string::npos)
continue; // also ignore executables for this.
if (!foundprefix)
{
// check for special names, if one of these gets found this must be treated as a normal zip.
bool isspecial = name.IndexOf("/") < 0 || (filter && filter->reservedFolders.Find(name) < filter->reservedFolders.Size());
bool isspecial = name.find_first_of("/") == std::string::npos ||
(filter && std::find(filter->reservedFolders.begin(), filter->reservedFolders.end(), name) != filter->reservedFolders.end());
if (isspecial) break;
name0 = name.Left(name.LastIndexOf("/")+1);
name1 = name.Left(name.IndexOf("/") + 1);
name0 = std::string(name, 0, name.find_last_of("/")+1);
name1 = std::string(name, 0, name.find_first_of("/") + 1);
foundprefix = true;
}
if (name.IndexOf(name0) != 0)
if (name.find_first_of(name0) != 0)
{
if (name1.IsNotEmpty())
if (!name1.empty())
{
name0 = name1;
if (name.IndexOf(name0) != 0)
if (name.find_first_of(name0) != 0)
{
name0 = "";
}
}
if (name0.IsEmpty())
if (name0.empty())
break;
}
if (!foundspeciallump && filter)
@ -296,7 +295,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
// at least one of the more common definition lumps must be present.
for (auto &p : filter->requiredPrefixes)
{
if (name.IndexOf(name0 + p) == 0 || name.LastIndexOf(p) == ptrdiff_t(name.Len() - strlen(p)))
if (name.find_first_of(name0 + p) == 0 || name.find_last_of(p) == ptrdiff_t(name.length() - p.length()))
{
foundspeciallump = true;
break;
@ -314,7 +313,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr;
int len = LittleShort(zip_fh->NameLength);
FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len);
std::string name(dirptr + sizeof(FZipCentralDirectoryInfo), len);
dirptr += sizeof(FZipCentralDirectoryInfo) +
LittleShort(zip_fh->NameLength) +
LittleShort(zip_fh->ExtraLength) +
@ -323,19 +322,19 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file.
{
free(directory);
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", FileName.GetChars());
Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName.c_str());
return false;
}
if (name.IndexOf("__macosx") == 0 || name.IndexOf("__MACOSX") == 0)
if (name.find_first_of("__macosx") == 0 || name.find_first_of("__MACOSX") == 0)
{
skipped++;
continue; // Weed out Apple's resource fork garbage right here because it interferes with safe operation.
}
if (name0.IsNotEmpty()) name = name.Mid(name0.Len());
if (!name0.empty()) name = std::string(name, name0.length());
// skip Directories
if (name.IsEmpty() || (name.Back() == '/' && LittleLong(zip_fh->UncompressedSize32) == 0))
if (name.empty() || (name.back() == '/' && LittleLong(zip_fh->UncompressedSize32) == 0))
{
skipped++;
continue;
@ -350,7 +349,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
zip_fh->Method != METHOD_IMPLODE &&
zip_fh->Method != METHOD_SHRINK)
{
if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' uses an unsupported compression algorithm (#%d).\n", FileName.GetChars(), name.GetChars(), zip_fh->Method);
Printf(FSMessageLevel::Error, "%s: '%s' uses an unsupported compression algorithm (#%d).\n", FileName.c_str(), name.c_str(), zip_fh->Method);
skipped++;
continue;
}
@ -358,14 +357,14 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
zip_fh->Flags = LittleShort(zip_fh->Flags);
if (zip_fh->Flags & ZF_ENCRYPTED)
{
if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' is encrypted. Encryption is not supported.\n", FileName.GetChars(), name.GetChars());
Printf(FSMessageLevel::Error, "%s: '%s' is encrypted. Encryption is not supported.\n", FileName.c_str(), name.c_str());
skipped++;
continue;
}
FixPathSeperator(name);
name.ToLower();
FixPathSeparator(&name.front());
for (auto& c : name) c = tolower(c);
uint32_t UncompressedSize =LittleLong(zip_fh->UncompressedSize32);
uint32_t CompressedSize = LittleLong(zip_fh->CompressedSize32);
uint64_t LocalHeaderOffset = LittleLong(zip_fh->LocalHeaderOffset32);
@ -385,7 +384,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
if (zip_64->CompressedSize > 0x7fffffff || zip_64->UncompressedSize > 0x7fffffff)
{
// The file system is limited to 32 bit file sizes;
if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' is too large.\n", FileName.GetChars(), name.GetChars());
Printf(FSMessageLevel::Warning, "%s: '%s' is too large.\n", FileName.c_str(), name.c_str());
skipped++;
continue;
}
@ -396,7 +395,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
}
}
lump_p->LumpNameSetup(name);
lump_p->LumpNameSetup(name.c_str());
lump_p->LumpSize = UncompressedSize;
lump_p->Owner = this;
// The start of the Reader will be determined the first time it is accessed.
@ -508,7 +507,7 @@ int FZipLump::FillCache()
Owner->Reader.Seek(Position, FileReader::SeekSet);
Cache = new char[LumpSize];
UncompressZipLump(Cache, Owner->Reader, Method, LumpSize, CompressedSize, GPFlags);
UncompressZipLump(Cache, Owner->Reader, Method, LumpSize, CompressedSize, GPFlags, true);
RefCount = 1;
return 1;
}
@ -532,7 +531,7 @@ int FZipLump::GetFileOffset()
//
//==========================================================================
FResourceFile *CheckZip(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter)
FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
char head[4];
@ -544,7 +543,7 @@ FResourceFile *CheckZip(const char *filename, FileReader &file, bool quiet, Lump
if (!memcmp(head, "PK\x3\x4", 4))
{
auto rf = new FZipFile(filename, file);
if (rf->Open(quiet, filter)) return rf;
if (rf->Open(filter, Printf)) return rf;
file = std::move(rf->Reader); // to avoid destruction of reader
delete rf;
@ -590,7 +589,7 @@ static std::pair<uint16_t, uint16_t> time_to_dos(struct tm *time)
//
//==========================================================================
int AppendToZip(FileWriter *zip_file, const char *filename, FCompressedBuffer &content, std::pair<uint16_t, uint16_t> &dostime)
static int AppendToZip(FileWriter *zip_file, const FCompressedBuffer &content, std::pair<uint16_t, uint16_t> &dostime)
{
FZipLocalFileHeader local;
int position;
@ -605,7 +604,7 @@ int AppendToZip(FileWriter *zip_file, const char *filename, FCompressedBuffer &c
local.CRC32 = content.mCRC32;
local.UncompressedSize = LittleLong(content.mSize);
local.CompressedSize = LittleLong(content.mCompressedSize);
local.NameLength = LittleShort((unsigned short)strlen(filename));
local.NameLength = LittleShort((unsigned short)strlen(content.filename));
local.ExtraLength = 0;
// Fill in local directory header.
@ -614,7 +613,7 @@ int AppendToZip(FileWriter *zip_file, const char *filename, FCompressedBuffer &c
// Write out the header, file name, and file data.
if (zip_file->Write(&local, sizeof(local)) != sizeof(local) ||
zip_file->Write(filename, strlen(filename)) != strlen(filename) ||
zip_file->Write(content.filename, strlen(content.filename)) != strlen(content.filename) ||
zip_file->Write(content.mBuffer, content.mCompressedSize) != content.mCompressedSize)
{
return -1;
@ -631,7 +630,7 @@ int AppendToZip(FileWriter *zip_file, const char *filename, FCompressedBuffer &c
//
//==========================================================================
int AppendCentralDirectory(FileWriter *zip_file, const char *filename, FCompressedBuffer &content, std::pair<uint16_t, uint16_t> &dostime, int position)
int AppendCentralDirectory(FileWriter *zip_file, const FCompressedBuffer &content, std::pair<uint16_t, uint16_t> &dostime, int position)
{
FZipCentralDirectoryInfo dir;
@ -647,23 +646,23 @@ int AppendCentralDirectory(FileWriter *zip_file, const char *filename, FCompress
dir.CRC32 = content.mCRC32;
dir.CompressedSize32 = LittleLong(content.mCompressedSize);
dir.UncompressedSize32 = LittleLong(content.mSize);
dir.NameLength = LittleShort((unsigned short)strlen(filename));
dir.NameLength = LittleShort((unsigned short)strlen(content.filename));
dir.ExtraLength = 0;
dir.CommentLength = 0;
dir.StartingDiskNumber = 0;
dir.InternalAttributes = 0;
dir.ExternalAttributes = 0;
dir.LocalHeaderOffset32 = LittleLong(position);
dir.LocalHeaderOffset32 = LittleLong((unsigned)position);
if (zip_file->Write(&dir, sizeof(dir)) != sizeof(dir) ||
zip_file->Write(filename, strlen(filename)) != strlen(filename))
zip_file->Write(content.filename, strlen(content.filename)) != strlen(content.filename))
{
return -1;
}
return 0;
}
bool WriteZip(const char *filename, TArray<FString> &filenames, TArray<FCompressedBuffer> &content)
bool WriteZip(const char* filename, const FCompressedBuffer* content, size_t contentcount)
{
// try to determine local time
struct tm *ltime;
@ -674,14 +673,12 @@ bool WriteZip(const char *filename, TArray<FString> &filenames, TArray<FCompress
TArray<int> positions;
if (filenames.Size() != content.Size()) return false;
auto f = FileWriter::Open(filename);
if (f != nullptr)
{
for (unsigned i = 0; i < filenames.Size(); i++)
for (size_t i = 0; i < contentcount; i++)
{
int pos = AppendToZip(f, filenames[i], content[i], dostime);
int pos = AppendToZip(f, content[i], dostime);
if (pos == -1)
{
delete f;
@ -692,9 +689,9 @@ bool WriteZip(const char *filename, TArray<FString> &filenames, TArray<FCompress
}
int dirofs = (int)f->Tell();
for (unsigned i = 0; i < filenames.Size(); i++)
for (size_t i = 0; i < contentcount; i++)
{
if (AppendCentralDirectory(f, filenames[i], content[i], dostime, positions[i]) < 0)
if (AppendCentralDirectory(f, content[i], dostime, positions[i]) < 0)
{
delete f;
remove(filename);
@ -707,8 +704,8 @@ bool WriteZip(const char *filename, TArray<FString> &filenames, TArray<FCompress
dirend.Magic = ZIP_ENDOFDIR;
dirend.DiskNumber = 0;
dirend.FirstDisk = 0;
dirend.NumEntriesOnAllDisks = dirend.NumEntries = LittleShort((uint16_t)filenames.Size());
dirend.DirectoryOffset = LittleLong(dirofs);
dirend.NumEntriesOnAllDisks = dirend.NumEntries = LittleShort((uint16_t)contentcount);
dirend.DirectoryOffset = LittleLong((unsigned)dirofs);
dirend.DirectorySize = LittleLong((uint32_t)(f->Tell() - dirofs));
dirend.ZipCommentLength = 0;
if (f->Write(&dirend, sizeof(dirend)) != sizeof(dirend))

View file

@ -19,7 +19,7 @@ struct FZipLump : public FResourceLump
unsigned CRC32;
virtual FileReader *GetReader();
virtual int FillCache();
virtual int FillCache() override;
private:
void SetLumpAddress();
@ -41,7 +41,7 @@ class FZipFile : public FResourceFile
public:
FZipFile(const char * filename, FileReader &file);
virtual ~FZipFile();
bool Open(bool quiet, LumpFilterInfo* filter);
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};

View file

@ -55,7 +55,6 @@
struct FileSystem::LumpRecord
{
FResourceLump *lump;
FGameTexture* linkedTexture;
LumpShortName shortName;
FString longName;
int rfnum;
@ -67,7 +66,6 @@ struct FileSystem::LumpRecord
{
lump = lmp;
rfnum = filenum;
linkedTexture = nullptr;
flags = 0;
if (lump->Flags & LUMPF_SHORTNAME)
@ -152,7 +150,7 @@ struct FileSystem::LumpRecord
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void PrintLastError ();
static void PrintLastError (FileSystemMessageFunc Printf);
// PUBLIC DATA DEFINITIONS -------------------------------------------------
@ -162,7 +160,7 @@ FileSystem fileSystem;
FileSystem::FileSystem()
{
// This is needed to initialize the LumpRecord array, which depends on data only available here.
// Cannot be defaulted! This is needed to initialize the LumpRecord array, which depends on data only available here.
}
FileSystem::~FileSystem ()
@ -199,14 +197,14 @@ void FileSystem::DeleteAll ()
//
//==========================================================================
void FileSystem::InitSingleFile(const char* filename, bool quiet)
bool FileSystem::InitSingleFile(const char* filename, FileSystemMessageFunc Printf)
{
TArray<FString> filenames;
filenames.Push(filename);
InitMultipleFiles(filenames, true);
return InitMultipleFiles(filenames, nullptr, Printf);
}
void FileSystem::InitMultipleFiles (TArray<FString> &filenames, bool quiet, LumpFilterInfo* filter, bool allowduplicates, FILE* hashfile)
bool FileSystem::InitMultipleFiles (TArray<FString> &filenames, LumpFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates, FILE* hashfile)
{
int numfiles;
@ -232,23 +230,23 @@ void FileSystem::InitMultipleFiles (TArray<FString> &filenames, bool quiet, Lump
for(unsigned i=0;i<filenames.Size(); i++)
{
AddFile (filenames[i], nullptr, quiet, filter, hashfile);
AddFile (filenames[i], nullptr, filter, Printf, hashfile);
if (i == (unsigned)MaxIwadIndex) MoveLumpsInFolder("after_iwad/");
FStringf path("filter/%s", Files.Last()->GetHash().GetChars());
FStringf path("filter/%s", Files.Last()->GetHash());
MoveLumpsInFolder(path);
}
NumEntries = FileInfo.Size();
if (NumEntries == 0)
{
if (!quiet) I_FatalError("W_InitMultipleFiles: no files found");
else return;
return false;
}
if (filter && filter->postprocessFunc) filter->postprocessFunc();
// [RH] Set up hash table
InitHashChains ();
return true;
}
//==========================================================================
@ -308,7 +306,7 @@ int FileSystem::AddFromBuffer(const char* name, const char* type, char* data, in
// [RH] Removed reload hack
//==========================================================================
void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, LumpFilterInfo* filter, FILE* hashfile)
void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInfo* filter, FileSystemMessageFunc Printf, FILE* hashfile)
{
int startlump;
bool isdir = false;
@ -319,10 +317,10 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L
// Does this exist? If so, is it a directory?
if (!DirEntryExists(filename, &isdir))
{
if (!quiet)
if (Printf)
{
Printf(TEXTCOLOR_RED "%s: File or Directory not found\n", filename);
PrintLastError();
Printf(FSMessageLevel::Error, "%s: File or Directory not found\n", filename);
PrintLastError(Printf);
}
return;
}
@ -331,10 +329,10 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L
{
if (!filereader.OpenFile(filename))
{ // Didn't find file
if (!quiet)
if (Printf)
{
Printf(TEXTCOLOR_RED "%s: File not found\n", filename);
PrintLastError();
Printf(FSMessageLevel::Error, "%s: File not found\n", filename);
PrintLastError(Printf);
}
return;
}
@ -342,19 +340,20 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L
}
else filereader = std::move(*filer);
if (!batchrun && !quiet) Printf (" adding %s", filename);
startlump = NumEntries;
FResourceFile *resfile;
if (!isdir)
resfile = FResourceFile::OpenResourceFile(filename, filereader, quiet, false, filter);
resfile = FResourceFile::OpenResourceFile(filename, filereader, false, filter, Printf);
else
resfile = FResourceFile::OpenDirectory(filename, quiet, filter);
resfile = FResourceFile::OpenDirectory(filename, filter, Printf);
if (resfile != NULL)
{
if (!quiet && !batchrun) Printf(", %d lumps\n", resfile->LumpCount());
if (!batchrun && Printf)
Printf(FSMessageLevel::Message, "adding %s, %d lumps\n", filename, resfile->LumpCount());
uint32_t lumpstart = FileInfo.Size();
@ -376,11 +375,11 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L
FString path;
path.Format("%s:%s", filename, lump->getName());
auto embedded = lump->NewReader();
AddFile(path, &embedded, quiet, filter, hashfile);
AddFile(path, &embedded, filter, Printf, hashfile);
}
}
if (hashfile && !quiet)
if (hashfile)
{
uint8_t cksum[16];
char cksumout[33];
@ -568,7 +567,7 @@ int FileSystem::GetNumForName (const char *name, int space)
i = CheckNumForName (name, space);
if (i == -1)
I_Error ("GetNumForName: %s not found!", name);
throw FileSystemException("GetNumForName: %s not found!", name);
return i;
}
@ -652,7 +651,7 @@ int FileSystem::GetNumForFullName (const char *name)
i = CheckNumForFullName (name);
if (i == -1)
I_Error ("GetNumForFullName: %s not found!", name);
throw FileSystemException("GetNumForFullName: %s not found!", name);
return i;
}
@ -742,40 +741,11 @@ int FileSystem::GetResource (int resid, const char *type, int filenum) const
if (i == -1)
{
I_Error("GetResource: %d of type %s not found!", resid, type);
throw FileSystemException("GetResource: %d of type %s not found!", resid, type);
}
return i;
}
//==========================================================================
//
// link a texture with a given lump
//
//==========================================================================
void FileSystem::SetLinkedTexture(int lump, FGameTexture *tex)
{
if ((size_t)lump < NumEntries)
{
FileInfo[lump].linkedTexture = tex;
}
}
//==========================================================================
//
// retrieve linked texture
//
//==========================================================================
FGameTexture *FileSystem::GetLinkedTexture(int lump)
{
if ((size_t)lump < NumEntries)
{
return FileInfo[lump].linkedTexture;
}
return NULL;
}
//==========================================================================
//
// FileLength
@ -921,19 +891,19 @@ void FileSystem::InitHashChains (void)
LumpShortName& FileSystem::GetShortName(int i)
{
if ((unsigned)i >= NumEntries) I_Error("GetShortName: Invalid index");
if ((unsigned)i >= NumEntries) throw FileSystemException("GetShortName: Invalid index");
return FileInfo[i].shortName;
}
FString& FileSystem::GetLongName(int i)
{
if ((unsigned)i >= NumEntries) I_Error("GetLongName: Invalid index");
if ((unsigned)i >= NumEntries) throw FileSystemException("GetLongName: Invalid index");
return FileInfo[i].longName;
}
void FileSystem::RenameFile(int num, const char* newfn)
{
if ((unsigned)num >= NumEntries) I_Error("RenameFile: Invalid index");
if ((unsigned)num >= NumEntries) throw FileSystemException("RenameFile: Invalid index");
FileInfo[num].longName = newfn;
// This does not alter the short name - call GetShortname to do that!
}
@ -1332,19 +1302,21 @@ unsigned FileSystem::GetFilesInFolder(const char *inpath, TArray<FolderEntry> &r
//
//==========================================================================
TArray<uint8_t> FileSystem::GetFileData(int lump, int pad)
std::vector<uint8_t> FileSystem::GetFileData(int lump, int pad)
{
std::vector<uint8_t> data;
if ((size_t)lump >= FileInfo.Size())
return TArray<uint8_t>();
return data;
auto lumpr = OpenFileReader(lump);
auto size = lumpr.GetLength();
TArray<uint8_t> data(size + pad, true);
auto numread = lumpr.Read(data.Data(), size);
data.resize(size + pad);
auto numread = lumpr.Read(data.data(), size);
if (numread != size)
{
I_Error("GetFileData: only read %ld of %ld on lump %i\n",
throw FileSystemException("GetFileData: only read %ld of %ld on lump %i\n",
numread, size, lump);
}
if (pad > 0) memset(&data[size], 0, pad);
@ -1366,8 +1338,8 @@ void FileSystem::ReadFile (int lump, void *dest)
if (numread != size)
{
I_Error ("W_ReadFile: only read %ld of %ld on lump %i\n",
numread, size, lump);
throw FileSystemException("W_ReadFile: only read %ld of %ld on '%s'\n",
numread, size, GetLongName(lump).GetChars());
}
}
@ -1398,7 +1370,7 @@ FileReader FileSystem::OpenFileReader(int lump)
{
if ((unsigned)lump >= (unsigned)FileInfo.Size())
{
I_Error("OpenFileReader: %u >= NumEntries", lump);
throw FileSystemException("OpenFileReader: %u >= NumEntries", lump);
}
auto rl = FileInfo[lump].lump;
@ -1417,7 +1389,7 @@ FileReader FileSystem::ReopenFileReader(int lump, bool alwayscache)
{
if ((unsigned)lump >= (unsigned)FileInfo.Size())
{
I_Error("ReopenFileReader: %u >= NumEntries", lump);
throw FileSystemException("ReopenFileReader: %u >= NumEntries", lump);
}
auto rl = FileInfo[lump].lump;
@ -1479,9 +1451,9 @@ const char *FileSystem::GetResourceFileName (int rfnum) const noexcept
return NULL;
}
name = Files[rfnum]->FileName;
name = Files[rfnum]->FileName.c_str();
slash = strrchr (name, '/');
return (slash != NULL && slash[1] != 0) ? slash+1 : name;
return (slash != nullptr && slash[1] != 0) ? slash+1 : name;
}
//==========================================================================
@ -1545,7 +1517,7 @@ const char *FileSystem::GetResourceFileFullName (int rfnum) const noexcept
return nullptr;
}
return Files[rfnum]->FileName;
return Files[rfnum]->FileName.c_str();
}
@ -1618,7 +1590,7 @@ FString::FString (ELumpNum lumpnum)
if (numread != size)
{
I_Error ("ConstructStringFromLump: Only read %ld of %ld bytes on lump %i (%s)\n",
throw FileSystemException("ConstructStringFromLump: Only read %ld of %ld bytes on lump %i (%s)\n",
numread, size, lumpnum, fileSystem.GetFileFullName((int)lumpnum));
}
}
@ -1647,7 +1619,7 @@ __declspec(dllimport) void * __stdcall LocalFree (void *);
__declspec(dllimport) unsigned long __stdcall GetLastError ();
}
static void PrintLastError ()
static void PrintLastError (FileSystemMessageFunc Printf)
{
char *lpMsgBuf;
FormatMessageA(0x1300 /*FORMAT_MESSAGE_ALLOCATE_BUFFER |
@ -1660,14 +1632,14 @@ static void PrintLastError ()
0,
NULL
);
Printf (TEXTCOLOR_RED " %s\n", lpMsgBuf);
Printf (FSMessageLevel::Error, " %s\n", lpMsgBuf);
// Free the buffer.
LocalFree( lpMsgBuf );
}
#else
static void PrintLastError ()
static void PrintLastError (FileSystemMessageFunc Printf)
{
Printf (TEXTCOLOR_RED " %s\n", strerror(errno));
Printf(FSMessageLevel::Error, " %s\n", strerror(errno));
}
#endif
@ -1681,21 +1653,3 @@ FResourceLump* FileSystem::GetFileAt(int no)
{
return FileInfo[no].lump;
}
#include "c_dispatch.h"
CCMD(fs_dir)
{
int numfiles = fileSystem.GetNumEntries();
for (int i = 0; i < numfiles; i++)
{
auto container = fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(i));
auto fn1 = fileSystem.GetFileFullName(i);
auto fns = fileSystem.GetFileShortName(i);
auto fnid = fileSystem.GetResourceId(i);
auto length = fileSystem.FileLength(i);
bool hidden = fileSystem.FindFile(fn1) != i;
Printf(PRINT_HIGH | PRINT_NONOTIFY, "%s%-64s %-15s (%5d) %10d %s %s\n", hidden ? TEXTCOLOR_RED : TEXTCOLOR_UNTRANSLATED, fn1, fns, fnid, length, container, hidden ? "(h)" : "");
}
}

View file

@ -16,7 +16,6 @@
class FResourceFile;
struct FResourceLump;
class FGameTexture;
union LumpShortName
{
@ -57,7 +56,7 @@ struct FolderEntry
class FileSystem
{
public:
FileSystem ();
FileSystem();
~FileSystem ();
// The wadnum for the IWAD
@ -67,9 +66,9 @@ public:
int GetMaxIwadNum() { return MaxIwadIndex; }
void SetMaxIwadNum(int x) { MaxIwadIndex = x; }
void InitSingleFile(const char *filename, bool quiet = false);
void InitMultipleFiles (TArray<FString> &filenames, bool quiet = false, LumpFilterInfo* filter = nullptr, bool allowduplicates = false, FILE* hashfile = nullptr);
void AddFile (const char *filename, FileReader *wadinfo, bool quiet, LumpFilterInfo* filter, FILE* hashfile);
bool InitSingleFile(const char *filename, FileSystemMessageFunc Printf = nullptr);
bool InitMultipleFiles (TArray<FString> &filenames, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false, FILE* hashfile = nullptr);
void AddFile (const char *filename, FileReader *wadinfo, LumpFilterInfo* filter, FileSystemMessageFunc Printf, FILE* hashfile);
int CheckIfResourceFileLoaded (const char *name) noexcept;
void AddAdditionalFile(const char* filename, FileReader* wadinfo = NULL) {}
@ -125,19 +124,15 @@ public:
inline int CheckNumForFullName (const FString &name, int wadfile) { return CheckNumForFullName(name.GetChars(), wadfile); }
inline int GetNumForFullName (const FString &name) { return GetNumForFullName(name.GetChars()); }
void SetLinkedTexture(int lump, FGameTexture *tex);
FGameTexture *GetLinkedTexture(int lump);
void ReadFile (int lump, void *dest);
TArray<uint8_t> GetFileData(int lump, int pad = 0); // reads lump into a writable buffer and optionally adds some padding at the end. (FileData isn't writable!)
std::vector<uint8_t> GetFileData(int lump, int pad = 0); // reads lump into a writable buffer and optionally adds some padding at the end. (FileData isn't writable!)
std::vector<uint8_t> GetFileData(const char* name, int pad = 0) { return GetFileData(GetNumForName(name), pad); }
FileData ReadFile (int lump);
FileData ReadFile (const char *name) { return ReadFile (GetNumForName (name)); }
inline TArray<uint8_t> LoadFile(const char* name, int padding = 0)
inline std::vector<uint8_t> LoadFile(const char* name, int padding = 0)
{
auto lump = FindFile(name);
if (lump < 0) return TArray<uint8_t>();
auto lump = GetNumForFullName(name);
return GetFileData(lump, padding);
}

View file

@ -36,9 +36,47 @@
#include <zlib.h>
#include "resourcefile.h"
#include "cmdlib.h"
#include "md5.h"
// hashing is optional.
#if __has_include("md5.h")
#include "md5.h"
#endif
std::string ExtractBaseName(const char* path, bool include_extension)
{
const char* src, * dot;
src = path + strlen(path) - 1;
if (src >= path)
{
// back up until a / or the start
while (src != path && src[-1] != '/' && src[-1] != '\\') // check both on all systems for consistent behavior with archives.
src--;
if (!include_extension && (dot = strrchr(src, '.')))
{
return std::string(src, dot - src);
}
else
{
return std::string(src);
}
}
return std::string();
}
void strReplace(std::string& str, const char *from, const char* to)
{
if (*from == 0)
return;
size_t start_pos = 0;
while ((start_pos = str.find(from, start_pos)) != std::string::npos)
{
str.replace(start_pos, strlen(from), to);
start_pos += strlen(to);
}
}
//==========================================================================
//
@ -88,10 +126,10 @@ FResourceLump::~FResourceLump()
//
//==========================================================================
void FResourceLump::LumpNameSetup(FString iname)
void FResourceLump::LumpNameSetup(const char *iname)
{
// this causes interference with real Dehacked lumps.
if (!iname.CompareNoCase("dehacked.exe"))
if (!stricmp(iname, "dehacked.exe"))
{
iname = "";
}
@ -115,24 +153,24 @@ static bool IsWadInFolder(const FResourceFile* const archive, const char* const
return false;
}
const FString dirName = ExtractFileBase(archive->FileName);
const FString fileName = ExtractFileBase(resPath, true);
const FString filePath = dirName + '/' + fileName;
const auto dirName = ExtractBaseName(archive->FileName.c_str());
const auto fileName = ExtractBaseName(resPath, true);
const std::string filePath = dirName + '/' + fileName;
return 0 == filePath.CompareNoCase(resPath);
return 0 == stricmp(filePath.c_str(), resPath);
}
void FResourceLump::CheckEmbedded(LumpFilterInfo* lfi)
{
// Checks for embedded archives
const char *c = strstr(FullName, ".wad");
if (c && strlen(c) == 4 && (!strchr(FullName, '/') || IsWadInFolder(Owner, FullName)))
const char *c = strstr(FullName.c_str(), ".wad");
if (c && strlen(c) == 4 && (!strchr(FullName.c_str(), '/') || IsWadInFolder(Owner, FullName.c_str())))
{
Flags |= LUMPF_EMBEDDED;
}
else if (lfi) for (auto& fstr : lfi->embeddings)
{
if (!stricmp(FullName, fstr))
if (!stricmp(FullName.c_str(), fstr.c_str()))
{
Flags |= LUMPF_EMBEDDED;
}
@ -193,7 +231,15 @@ void *FResourceLump::Lock()
}
else if (LumpSize > 0)
{
FillCache();
try
{
FillCache();
}
catch (const FileSystemException& err)
{
// enrich the message with info about this lump.
throw FileSystemException("%s, file '%s': %s", getName(), Owner->FileName.c_str(), err.what());
}
}
return Cache;
}
@ -223,46 +269,55 @@ int FResourceLump::Unlock()
//
//==========================================================================
typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter);
typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
FResourceFile *CheckWad(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter);
FResourceFile *CheckGRP(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter);
FResourceFile *CheckRFF(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter);
FResourceFile *CheckPak(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter);
FResourceFile *CheckZip(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter);
FResourceFile *Check7Z(const char *filename, FileReader &file, bool quiet, LumpFilterInfo* filter);
FResourceFile* CheckSSI(const char* filename, FileReader& file, bool quiet, LumpFilterInfo* filter);
FResourceFile *CheckLump(const char *filename,FileReader &file, bool quiet, LumpFilterInfo* filter);
FResourceFile *CheckDir(const char *filename, bool quiet, bool nosub, LumpFilterInfo* filter);
FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
FResourceFile* CheckWHRes(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
FResourceFile *CheckLump(const char *filename,FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
FResourceFile *CheckDir(const char *filename, bool nosub, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckSSI, CheckLump };
static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckSSI, CheckWHRes, CheckLump };
FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool quiet, bool containeronly, LumpFilterInfo* filter)
static int nulPrintf(FSMessageLevel msg, const char* fmt, ...)
{
for(size_t i = 0; i < countof(funcs) - containeronly; i++)
return 0;
}
FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
if (Printf == nullptr) Printf = nulPrintf;
for(auto func : funcs)
{
FResourceFile *resfile = funcs[i](filename, file, quiet, filter);
if (containeronly && func == CheckLump) break;
FResourceFile *resfile = func(filename, file, filter, Printf);
if (resfile != NULL) return resfile;
}
return NULL;
}
FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool quiet, bool containeronly, LumpFilterInfo* filter)
FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
return DoOpenResourceFile(filename, file, quiet, containeronly, filter);
return DoOpenResourceFile(filename, file, containeronly, filter, Printf);
}
FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool quiet, bool containeronly, LumpFilterInfo* filter)
FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
FileReader file;
if (!file.OpenFile(filename)) return nullptr;
return DoOpenResourceFile(filename, file, quiet, containeronly, filter);
return DoOpenResourceFile(filename, file, containeronly, filter, Printf);
}
FResourceFile *FResourceFile::OpenDirectory(const char *filename, bool quiet, LumpFilterInfo* filter)
FResourceFile *FResourceFile::OpenDirectory(const char *filename, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
return CheckDir(filename, quiet, false, filter);
if (Printf == nullptr) Printf = nulPrintf;
return CheckDir(filename, false, filter, Printf);
}
//==========================================================================
@ -305,9 +360,10 @@ int lumpcmp(const void * a, const void * b)
void FResourceFile::GenerateHash()
{
#if __has_include("md5.h")
// hash the lump directory after sorting
Hash.Format(("%08X-%04X-"), (unsigned)Reader.GetLength(), NumLumps);
auto n = snprintf(Hash, 48, "%08X-%04X-", (unsigned)Reader.GetLength(), NumLumps);
MD5Context md5;
@ -315,14 +371,15 @@ void FResourceFile::GenerateHash()
for(uint32_t i = 0; i < NumLumps; i++)
{
auto lump = GetLump(i);
md5.Update((const uint8_t*)lump->FullName.GetChars(), (unsigned)lump->FullName.Len() + 1);
md5.Update((const uint8_t*)lump->FullName.c_str(), (unsigned)lump->FullName.length() + 1);
md5.Update((const uint8_t*)&lump->LumpSize, 4);
}
md5.Final(digest);
for (auto c : digest)
{
Hash.AppendFormat("%02X", c);
n += snprintf(Hash + n, 3, "%02X", c);
}
#endif
}
//==========================================================================
@ -350,11 +407,11 @@ void FResourceFile::PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterI
ptrdiff_t len;
ptrdiff_t lastpos = -1;
FString file;
FString LumpFilter = filter->dotFilter;
while ((len = LumpFilter.IndexOf('.', lastpos+1)) > 0)
std::string file;
std::string& LumpFilter = filter->dotFilter;
while ((len = LumpFilter.find_first_of('.', lastpos+1)) != LumpFilter.npos)
{
max -= FilterLumps(LumpFilter.Left(len), lumps, lumpsize, max);
max -= FilterLumps(std::string(LumpFilter, 0, len), lumps, lumpsize, max);
lastpos = len;
}
max -= FilterLumps(LumpFilter, lumps, lumpsize, max);
@ -372,24 +429,23 @@ void FResourceFile::PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterI
//
//==========================================================================
int FResourceFile::FilterLumps(FString filtername, void *lumps, size_t lumpsize, uint32_t max)
int FResourceFile::FilterLumps(const std::string& filtername, void *lumps, size_t lumpsize, uint32_t max)
{
FString filter;
uint32_t start, end;
if (filtername.IsEmpty())
if (filtername.empty())
{
return 0;
}
filter << "filter/" << filtername << '/';
std::string filter = "filter/" + filtername + '/';
bool found = FindPrefixRange(filter, lumps, lumpsize, max, start, end);
bool found = FindPrefixRange(filter.c_str(), lumps, lumpsize, max, start, end);
// Workaround for old Doom filter names.
if (!found && filtername.IndexOf("doom.id.doom") == 0)
// Workaround for old Doom filter names (todo: move out of here.)
if (!found && filtername.find_first_of("doom.id.doom") == 0)
{
filter.Substitute("doom.id.doom", "doom.doom");
found = FindPrefixRange(filter, lumps, lumpsize, max, start, end);
strReplace(filter, "doom.id.doom", "doom.doom");
found = FindPrefixRange(filter.c_str(), lumps, lumpsize, max, start, end);
}
if (found)
@ -401,8 +457,8 @@ int FResourceFile::FilterLumps(FString filtername, void *lumps, size_t lumpsize,
for (uint32_t i = start; i < end; ++i, lump_p = (uint8_t *)lump_p + lumpsize)
{
FResourceLump *lump = (FResourceLump *)lump_p;
assert(lump->FullName.CompareNoCase(filter, (int)filter.Len()) == 0);
lump->LumpNameSetup(lump->FullName.Mid(filter.Len()));
assert(strnicmp(lump->FullName.c_str(), filter.c_str(), filter.length()) == 0);
lump->LumpNameSetup(lump->FullName.c_str() + filter.length());
}
// Move filtered lumps to the end of the lump list.
@ -486,7 +542,7 @@ void FResourceFile::JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t m
//
//==========================================================================
bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize, uint32_t maxlump, uint32_t &start, uint32_t &end)
bool FResourceFile::FindPrefixRange(const char* filter, void *lumps, size_t lumpsize, uint32_t maxlump, uint32_t &start, uint32_t &end)
{
uint32_t min, max, mid, inside;
FResourceLump *lump;
@ -504,7 +560,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize
{
mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len());
cmp = strnicmp(lump->FullName.c_str(), filter, (int)strlen(filter));
if (cmp == 0)
break;
else if (cmp < 0)
@ -524,7 +580,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize
{
mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len());
cmp = strnicmp(lump->FullName.c_str(), filter, (int)strlen(filter));
// Go left on matches and right on misses.
if (cmp == 0)
max = mid - 1;
@ -539,7 +595,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize
{
mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len());
cmp = strnicmp(lump->FullName.c_str(), filter, (int)strlen(filter));
// Go right on matches and left on misses.
if (cmp == 0)
min = mid + 1;
@ -561,7 +617,7 @@ FResourceLump *FResourceFile::FindLump(const char *name)
for (unsigned i = 0; i < NumLumps; i++)
{
FResourceLump *lump = GetLump(i);
if (!stricmp(name, lump->FullName))
if (!stricmp(name, lump->FullName.c_str()))
{
return lump;
}
@ -601,7 +657,13 @@ int FUncompressedLump::FillCache()
Owner->Reader.Seek(Position, FileReader::SeekSet);
Cache = new char[LumpSize];
Owner->Reader.Read(Cache, LumpSize);
auto read = Owner->Reader.Read(Cache, LumpSize);
if (read != LumpSize)
{
throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize);
}
RefCount = 1;
return 1;
}
@ -662,13 +724,17 @@ int FExternalLump::FillCache()
Cache = new char[LumpSize];
FileReader f;
if (f.OpenFile(Filename))
if (f.OpenFile(Filename.c_str()))
{
f.Read(Cache, LumpSize);
auto read = f.Read(Cache, LumpSize);
if (read != LumpSize)
{
throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize);
}
}
else
{
memset(Cache, 0, LumpSize);
throw FileSystemException("unable to open file");
}
RefCount = 1;
return 1;

View file

@ -4,22 +4,42 @@
#define __RESFILE_H
#include <limits.h>
#include <vector>
#include <string>
#include "files.h"
#include "zstring.h"
std::string ExtractBaseName(const char* path, bool include_extension = false);
void strReplace(std::string& str, const char* from, const char* to);
// user context in which the file system gets opened. This also contains a few callbacks to avoid direct dependencies on the engine.
struct LumpFilterInfo
{
TArray<FString> gameTypeFilter; // this can contain multiple entries
FString dotFilter;
std::vector<std::string> gameTypeFilter; // this can contain multiple entries
std::string dotFilter;
// The following are for checking if the root directory of a zip can be removed.
TArray<FString> reservedFolders;
TArray<FString> requiredPrefixes;
TArray<FString> embeddings;
std::vector<std::string> reservedFolders;
std::vector<std::string> requiredPrefixes;
std::vector<std::string> embeddings;
std::vector<std::string> blockednames; // File names that will never be accepted (e.g. dehacked.exe for Doom)
std::function<bool(const char*, const char*)> filenamecheck; // for scanning directories, this allows to eliminate unwanted content.
std::function<void()> postprocessFunc;
};
enum class FSMessageLevel
{
Error = 1,
Warning = 2,
Attention = 3,
Message = 4,
DebugWarn = 5,
DebugNotify = 6,
};
// pass the text output function as parameter to avoid a hard dependency on higher level code.
using FileSystemMessageFunc = int(*)(FSMessageLevel msglevel, const char* format, ...);
class FResourceFile;
// [RH] Namespaces from BOOM.
@ -71,6 +91,7 @@ struct FCompressedBuffer
int mZipFlags;
unsigned mCRC32;
char *mBuffer;
const char* filename;
bool Decompress(char *destbuffer);
void Clean()
@ -92,7 +113,7 @@ struct FResourceLump
int LumpSize;
int RefCount;
protected:
FString FullName;
std::string FullName;
public:
uint8_t Flags;
char * Cache;
@ -112,7 +133,7 @@ public:
virtual int GetFileOffset() { return -1; }
virtual int GetIndexNum() const { return -1; }
virtual int GetNamespace() const { return 0; }
void LumpNameSetup(FString iname);
void LumpNameSetup(const char* iname);
void CheckEmbedded(LumpFilterInfo* lfi);
virtual FCompressedBuffer GetRawData();
@ -121,7 +142,7 @@ public:
unsigned Size() const{ return LumpSize; }
int LockCount() const { return RefCount; }
const char* getName() { return FullName.GetChars(); }
const char* getName() { return FullName.c_str(); }
protected:
virtual int FillCache() { return -1; }
@ -132,10 +153,10 @@ class FResourceFile
{
public:
FileReader Reader;
FString FileName;
std::string FileName;
protected:
uint32_t NumLumps;
FString Hash;
char Hash[48];
FResourceFile(const char *filename);
FResourceFile(const char *filename, FileReader &r);
@ -147,23 +168,23 @@ protected:
private:
uint32_t FirstLump;
int FilterLumps(FString filtername, void *lumps, size_t lumpsize, uint32_t max);
int FilterLumps(const std::string& filtername, void *lumps, size_t lumpsize, uint32_t max);
int FilterLumpsByGameType(LumpFilterInfo *filter, void *lumps, size_t lumpsize, uint32_t max);
bool FindPrefixRange(FString filter, void *lumps, size_t lumpsize, uint32_t max, uint32_t &start, uint32_t &end);
bool FindPrefixRange(const char* filter, void *lumps, size_t lumpsize, uint32_t max, uint32_t &start, uint32_t &end);
void JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t max);
static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool quiet, bool containeronly, LumpFilterInfo* filter);
static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
public:
static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool quiet = false, bool containeronly = false, LumpFilterInfo* filter = nullptr);
static FResourceFile *OpenResourceFile(const char *filename, bool quiet = false, bool containeronly = false, LumpFilterInfo* filter = nullptr);
static FResourceFile *OpenDirectory(const char *filename, bool quiet = false, LumpFilterInfo* filter = nullptr);
static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr);
static FResourceFile *OpenResourceFile(const char *filename, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr);
static FResourceFile *OpenDirectory(const char *filename, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr);
virtual ~FResourceFile();
// If this FResourceFile represents a directory, the Reader object is not usable so don't return it.
FileReader *GetReader() { return Reader.isOpen()? &Reader : nullptr; }
uint32_t LumpCount() const { return NumLumps; }
uint32_t GetFirstEntry() const { return FirstLump; }
void SetFirstLump(uint32_t f) { FirstLump = f; }
const FString &GetHash() const { return Hash; }
const char* GetHash() const { return Hash; }
virtual FResourceLump *GetLump(int no) = 0;
@ -175,7 +196,7 @@ struct FUncompressedLump : public FResourceLump
int Position;
virtual FileReader *GetReader();
virtual int FillCache();
virtual int FillCache() override;
virtual int GetFileOffset() { return Position; }
};
@ -195,10 +216,10 @@ protected:
struct FExternalLump : public FResourceLump
{
FString Filename;
std::string Filename;
FExternalLump(const char *_filename, int filesize = -1);
virtual int FillCache();
virtual int FillCache() override;
};

View file

@ -1,7 +1,11 @@
#ifndef __W_ZIP
#define __W_ZIP
#include "basics.h"
#if defined(__GNUC__)
#define FORCE_PACKED __attribute__((__packed__))
#else
#define FORCE_PACKED
#endif
#pragma pack(1)
// FZipCentralInfo
@ -85,6 +89,15 @@ struct FZipLocalFileHeader
#pragma pack()
#ifndef MAKE_ID
#ifndef __BIG_ENDIAN__
#define MAKE_ID(a,b,c,d) ((uint32_t)((a)|((b)<<8)|((c)<<16)|((d)<<24)))
#else
#define MAKE_ID(a,b,c,d) ((uint32_t)((d)|((c)<<8)|((b)<<16)|((a)<<24)))
#endif
#endif
#define ZIP_LOCALFILE MAKE_ID('P','K',3,4)
#define ZIP_CENTRALFILE MAKE_ID('P','K',1,2)
#define ZIP_ENDOFDIR MAKE_ID('P','K',5,6)

View file

@ -41,6 +41,7 @@
#include "utf8.h"
#include "fontchars.h"
#include "texturemanager.h"
#include "m_swap.h"
#include "fontinternals.h"

View file

@ -320,10 +320,10 @@ unsigned FSavegameManagerBase::ExtractSaveData(int index)
{
FileReader picreader;
picreader.OpenMemoryArray([=](TArray<uint8_t> &array)
picreader.OpenMemoryArray([=](std::vector<uint8_t> &array)
{
auto cache = pic->Lock();
array.Resize(pic->LumpSize);
array.resize(pic->LumpSize);
memcpy(&array[0], cache, pic->LumpSize);
pic->Unlock();
return true;

View file

@ -31,6 +31,7 @@
#include "texturemanager.h"
#include "modelrenderer.h"
#include "printf.h"
#include "m_swap.h"
#ifdef _MSC_VER
#pragma warning(disable:4244) // warning C4244: conversion from 'double' to 'float', possible loss of data

View file

@ -25,6 +25,7 @@
#include "model_md3.h"
#include "texturemanager.h"
#include "modelrenderer.h"
#include "m_swap.h"
#define MAX_QPATH 64

View file

@ -171,17 +171,6 @@ unsigned int I_MakeRNGSeed()
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)
{
NSFileManager *filemgr = [NSFileManager defaultManager];

View file

@ -406,23 +406,6 @@ FString I_GetFromClipboard (bool use_primary_selection)
return "";
}
FString I_GetCWD()
{
char* curdir = getcwd(NULL,0);
if (!curdir)
{
return "";
}
FString ret(curdir);
free(curdir);
return ret;
}
bool I_ChDir(const char* path)
{
return chdir(path) == 0;
}
// Return a random seed, preferably one with lots of entropy.
unsigned int I_MakeRNGSeed()
{

View file

@ -115,7 +115,7 @@ protected:
void PostKeyEvent(int keynum, INTBOOL down, bool foreground);
};
class NOVTABLE FJoystickCollection : public FInputDevice
class FJoystickCollection : public FInputDevice
{
public:
virtual void AddAxes(float axes[NUM_JOYAXIS]) = 0;

View file

@ -958,25 +958,6 @@ 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)
{
auto len = GetCurrentDirectoryW(0, nullptr);

View file

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

View file

@ -34,7 +34,7 @@
**
*/
#include "vectors.h" // RAD2DEG
#include "vectors.h"
#include "hw_cvars.h"
#include "hw_vrmodes.h"
#include "v_video.h"
@ -67,6 +67,16 @@ static VRMode vrmi_righteye = { 1, 1.f, 1.f, 1.f,{ { .5f, 1.f },{ 0.f, 0.f } } }
static VRMode vrmi_topbottom = { 2, 1.f, .5f, 1.f,{ { -.5f, 1.f },{ .5f, 1.f } } };
static VRMode vrmi_checker = { 2, isqrt2, isqrt2, 1.f,{ { -.5f, 1.f },{ .5f, 1.f } } };
static float DEG2RAD(float deg)
{
return deg * float(M_PI / 180.0);
}
static float RAD2DEG(float rad)
{
return rad * float(180. / M_PI);
}
const VRMode *VRMode::GetVRMode(bool toscreen)
{
int mode = !toscreen || (sysCallbacks.DisableTextureFilter && sysCallbacks.DisableTextureFilter()) ? 0 : vr_mode;

View file

@ -1,5 +1,8 @@
#pragma once
#include "zstring.h"
#include "tarray.h"
enum class PostProcessUniformType
{
Undefined,

View file

@ -1,5 +1,6 @@
#pragma once
#include "basics.h"
struct FModelVertex

View file

@ -113,7 +113,7 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
}
else
{
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
VkFormat format = tex->IsHDR() ? VK_FORMAT_R32G32B32A32_SFLOAT : VK_FORMAT_R8G8B8A8_UNORM;
int w = tex->GetWidth();
int h = tex->GetHeight();

View file

@ -9,6 +9,16 @@ class PPrototype;
struct ZCC_TreeNode;
class PContainerType;
// This is needed in common code, despite being Doom specific.
enum EStateUseFlags
{
SUF_ACTOR = 1,
SUF_OVERLAY = 2,
SUF_WEAPON = 4,
SUF_ITEM = 8,
};
// Symbol information -------------------------------------------------------
class PTypeBase

View file

@ -424,7 +424,7 @@ DEFINE_ACTION_FUNCTION(_TexMan, GetName)
{
// Textures for full path names do not have their own name, they merely link to the source lump.
auto lump = tex->GetSourceLump();
if (fileSystem.GetLinkedTexture(lump) == tex)
if (TexMan.GetLinkedTexture(lump) == tex)
retval = fileSystem.GetFileFullName(lump);
}
}

View file

@ -217,7 +217,7 @@ static inline void drawframe(anim_t *anim, uint16_t framenumber)
}
// <length> is the file size, for consistency checking.
int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, int32_t length)
int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, size_t length)
{
if (memcmp(buffer, "LPF ", 4)) return -1;

View file

@ -105,7 +105,7 @@ struct anim_t
//
//****************************************************************************
int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, int32_t length);
int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, size_t length);
//****************************************************************************
//

View file

@ -73,7 +73,7 @@ FImageSource *AnmImage_TryCreate(FileReader & file, int lumpnum)
auto buffer = file.ReadPadded(1);
anim_t anim;
if (ANIM_LoadAnim(&anim, buffer.Data(), buffer.Size() - 1) < 0)
if (ANIM_LoadAnim(&anim, buffer.data(), buffer.size() - 1) < 0)
{
return nullptr;
}

View file

@ -54,6 +54,7 @@
#include "bitmap.h"
#include "imagehelpers.h"
#include "image.h"
#include "m_swap.h"
// Since we want this to compile under Linux too, we need to define this
// stuff ourselves instead of including a DirectX header.

View file

@ -46,6 +46,7 @@ extern "C"
#include "bitmap.h"
#include "imagehelpers.h"
#include "image.h"
#include "m_swap.h"
struct FLumpSourceMgr : public jpeg_source_mgr

View file

@ -38,6 +38,7 @@
#include "bitmap.h"
#include "image.h"
#include "imagehelpers.h"
#include "m_swap.h"
// posts are runs of non masked source pixels
@ -80,7 +81,7 @@ static bool CheckIfPatch(FileReader & file, bool &isalpha)
file.Seek(0, FileReader::SeekSet);
auto data = file.Read(file.GetLength());
const patch_t *foo = (const patch_t *)data.Data();
const patch_t *foo = (const patch_t *)data.data();
int height = LittleShort(foo->height);
int width = LittleShort(foo->width);
@ -110,7 +111,7 @@ static bool CheckIfPatch(FileReader & file, bool &isalpha)
{
// only check this if the texture passed validation.
// Here is a good point because we already have a valid buffer of the lump's data.
isalpha = checkPatchForAlpha(data.Data(), (uint32_t)file.GetLength());
isalpha = checkPatchForAlpha(data.data(), (uint32_t)file.GetLength());
}
return !gapAtStart;
}

View file

@ -39,6 +39,7 @@
#include "bitmap.h"
#include "imagehelpers.h"
#include "image.h"
#include "m_swap.h"
//==========================================================================
//
@ -159,8 +160,8 @@ void FPCXTexture::ReadPCX1bit (uint8_t *dst, FileReader & lump, PCXHeader *hdr)
int rle_count = 0;
uint8_t rle_value = 0;
TArray<uint8_t> srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader));
uint8_t * src = srcp.Data();
auto srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader));
uint8_t * src = srcp.data();
for (y = 0; y < Height; ++y)
{
@ -209,8 +210,8 @@ void FPCXTexture::ReadPCX4bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr)
TArray<uint8_t> line(hdr->bytesPerScanLine, true);
TArray<uint8_t> colorIndex(Width, true);
TArray<uint8_t> srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader));
uint8_t * src = srcp.Data();
auto srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader));
uint8_t * src = srcp.data();
for (y = 0; y < Height; ++y)
{
@ -264,7 +265,7 @@ void FPCXTexture::ReadPCX8bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr)
int y, bytes;
auto srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader));
uint8_t * src = srcp.Data();
uint8_t * src = srcp.data();
for (y = 0; y < Height; ++y)
{
@ -305,7 +306,7 @@ void FPCXTexture::ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr
int bytes;
auto srcp = lump.Read(lump.GetLength() - sizeof(PCXHeader));
uint8_t * src = srcp.Data();
uint8_t * src = srcp.data();
for (y = 0; y < Height; ++y)
{

View file

@ -43,6 +43,7 @@
#include "printf.h"
#include "texturemanager.h"
#include "filesystem.h"
#include "m_swap.h"
//==========================================================================
//

View file

@ -38,6 +38,7 @@
#include "bitmap.h"
#include "imagehelpers.h"
#include "image.h"
#include "m_swap.h"
//==========================================================================
@ -73,7 +74,7 @@ bool CheckIfRaw(FileReader & data, unsigned desiredsize)
data.Seek(0, FileReader::SeekSet);
auto bits = data.Read(data.GetLength());
foo = (patch_t *)bits.Data();
foo = (patch_t *)bits.data();
height = LittleShort(foo->height);
width = LittleShort(foo->width);

View file

@ -39,6 +39,7 @@
#include "bitmap.h"
#include "imagehelpers.h"
#include "image.h"
#include "m_swap.h"
//==========================================================================

View file

@ -98,8 +98,8 @@ FGameTexture::~FGameTexture()
{
if (Base != nullptr)
{
FGameTexture* link = fileSystem.GetLinkedTexture(GetSourceLump());
if (link == this) fileSystem.SetLinkedTexture(GetSourceLump(), nullptr);
FGameTexture* link = TexMan.GetLinkedTexture(GetSourceLump());
if (link == this) TexMan.SetLinkedTexture(GetSourceLump(), nullptr);
}
if (SoftwareTexture != nullptr)
{

View file

@ -322,6 +322,7 @@ FImageSource *DDSImage_TryCreate(FileReader &, int lumpnum);
FImageSource *PCXImage_TryCreate(FileReader &, int lumpnum);
FImageSource *TGAImage_TryCreate(FileReader &, int lumpnum);
FImageSource *StbImage_TryCreate(FileReader &, int lumpnum);
FImageSource *QOIImage_TryCreate(FileReader &, int lumpnum);
FImageSource *AnmImage_TryCreate(FileReader &, int lumpnum);
FImageSource *RawPageImage_TryCreate(FileReader &, int lumpnum);
FImageSource *FlatImage_TryCreate(FileReader &, int lumpnum);
@ -342,6 +343,7 @@ FImageSource * FImageSource::GetImage(int lumpnum, bool isflat)
{ DDSImage_TryCreate, false },
{ PCXImage_TryCreate, false },
{ StbImage_TryCreate, false },
{ QOIImage_TryCreate, false },
{ TGAImage_TryCreate, false },
{ AnmImage_TryCreate, false },
{ StartupPageImage_TryCreate, false },

View file

@ -44,6 +44,7 @@
#include "image.h"
#include "formats/multipatchtexture.h"
#include "texturemanager.h"
#include "m_swap.h"
// On the Alpha, accessing the shorts directly if they aren't aligned on a

View file

@ -244,11 +244,11 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset
// Any graphic being placed in the zip's root directory can not be found by this.
if (strchr(name, '/') || (flags & TEXMAN_ForceLookup))
{
FGameTexture *const NO_TEXTURE = (FGameTexture*)-1;
FGameTexture *const NO_TEXTURE = (FGameTexture*)-1; // marker for lumps we already checked that do not map to a texture.
int lump = fileSystem.CheckNumForFullName(name);
if (lump >= 0)
{
FGameTexture *tex = fileSystem.GetLinkedTexture(lump);
FGameTexture *tex = GetLinkedTexture(lump);
if (tex == NO_TEXTURE) return FTextureID(-1);
if (tex != NULL) return tex->GetID();
if (flags & TEXMAN_DontCreate) return FTextureID(-1); // we only want to check, there's no need to create a texture if we don't have one yet.
@ -256,13 +256,13 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset
if (tex != NULL)
{
tex->AddAutoMaterials();
fileSystem.SetLinkedTexture(lump, tex);
SetLinkedTexture(lump, tex);
return AddGameTexture(tex);
}
else
{
// mark this lump as having no valid texture so that we don't have to retry creating one later.
fileSystem.SetLinkedTexture(lump, NO_TEXTURE);
SetLinkedTexture(lump, NO_TEXTURE);
}
}
}
@ -1627,6 +1627,37 @@ void FTextureManager::Listaliases()
}
}
//==========================================================================
//
// link a texture with a given lump
//
//==========================================================================
void FTextureManager::SetLinkedTexture(int lump, FGameTexture* tex)
{
if ((size_t)lump < fileSystem.GetNumEntries())
{
linkedMap.Insert(lump, tex);
}
}
//==========================================================================
//
// retrieve linked texture
//
//==========================================================================
FGameTexture* FTextureManager::GetLinkedTexture(int lump)
{
if ((size_t)lump < fileSystem.GetNumEntries())
{
auto check = linkedMap.CheckKey(lump);
if (check) return *check;
}
return nullptr;
}
//==========================================================================
//
// FTextureID::operator+

View file

@ -88,6 +88,15 @@ public:
}
}
//==========================================================================
//
// link a texture with a given lump
//
//==========================================================================
TMap<int, FGameTexture*> linkedMap;
void SetLinkedTexture(int lump, FGameTexture* tex);
FGameTexture* GetLinkedTexture(int lump);
enum
{

View file

@ -217,6 +217,7 @@ protected:
bool Masked = false; // Texture (might) have holes
bool bHasCanvas = false;
bool bHdr = false; // only canvas textures for now.
int8_t bTranslucent = -1;
int8_t areacount = 0; // this is capped at 4 sections.
@ -253,6 +254,8 @@ public:
bool isHardwareCanvas() const { return bHasCanvas; } // There's two here so that this can deal with software canvases in the hardware renderer later.
bool isCanvas() const { return bHasCanvas; }
bool IsHDR() const { return bHdr; }
int GetSourceLump() { return SourceLump; } // needed by the scripted GetName method.
void SetSourceLump(int sl) { SourceLump = sl; }
bool FindHoles(const unsigned char * buffer, int w, int h);
@ -345,6 +348,12 @@ public:
float aspectRatio;
friend struct FCanvasTextureInfo;
friend class FTextureAnimator;
private:
void SetHDR(bool hdr) {
bHdr = hdr;
}
};

View file

@ -36,6 +36,7 @@
*/
#include <time.h>
#include <string.h>
#include "common/engine/printf.h"
#include "discord_rpc.h"

View file

@ -3,7 +3,6 @@
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include "xs_Float.h"
#define MAXWIDTH 12000
#define MAXHEIGHT 5000
@ -22,7 +21,6 @@ typedef int32_t fixed_t;
// the last remnants of tables.h
#define ANGLE_90 (0x40000000)
#define ANGLE_180 (0x80000000)
#define ANGLE_270 (0xc0000000)
#define ANGLE_MAX (0xffffffff)
typedef uint32_t angle_t;
@ -39,14 +37,6 @@ typedef uint32_t angle_t;
#define FORCE_PACKED
#endif
// Todo: get rid of this. Static file name buffers suck.
#ifndef PATH_MAX
#define BMAX_PATH 256
#else
#define BMAX_PATH PATH_MAX
#endif
#ifdef __GNUC__
#define GCCPRINTF(stri,firstargi) __attribute__((format(printf,stri,firstargi)))
#define GCCFORMAT(stri) __attribute__((format(printf,stri,0)))
@ -69,12 +59,6 @@ using INTBOOL = int;
using BITFIELD = uint32_t;
#if defined(_MSC_VER)
#define NOVTABLE __declspec(novtable)
#else
#define NOVTABLE
#endif
// always use our own definition for consistency.
#ifdef M_PI
#undef M_PI
@ -82,46 +66,6 @@ using BITFIELD = uint32_t;
const double M_PI = 3.14159265358979323846; // matches value in gcc v2 math.h
inline float DEG2RAD(float deg)
{
return deg * float(M_PI / 180.0);
}
inline double DEG2RAD(double deg)
{
return deg * (M_PI / 180.0);
}
inline float RAD2DEG(float rad)
{
return rad * float(180. / M_PI);
}
inline double RAD2DEG(double rad)
{
return rad * (180. / M_PI);
}
inline angle_t RAD2BAM(float rad)
{
return angle_t(xs_RoundToUInt(rad * float(0x80000000u / M_PI)));
}
inline angle_t RAD2BAM(double rad)
{
return angle_t(xs_RoundToUInt(rad * (0x80000000u / M_PI)));
}
// This is needed in common code, despite being Doom specific.
enum EStateUseFlags
{
SUF_ACTOR = 1,
SUF_OVERLAY = 2,
SUF_WEAPON = 4,
SUF_ITEM = 8,
};
using std::min;
using std::max;
using std::clamp;

View file

@ -35,7 +35,7 @@
#include "cmdlib.h"
#include "findfile.h"
#include "fs_findfile.h"
#include "files.h"
#include "md5.h"
@ -122,25 +122,6 @@ char *copystring (const char *s)
return b;
}
//==========================================================================
//
// ReplaceString
//
// Do not use in new code.
//
//==========================================================================
void ReplaceString (char **ptr, const char *str)
{
if (*ptr)
{
if (*ptr == str)
return;
delete[] *ptr;
}
*ptr = copystring (str);
}
/*
=============================================================================
@ -913,68 +894,6 @@ FString NicePath(const char *path)
}
//==========================================================================
//
// ScanDirectory
//
//==========================================================================
bool ScanDirectory(TArray<FFileList> &list, const char *dirpath)
{
findstate_t find;
FString dirmatch;
dirmatch << dirpath << "*";
auto handle = I_FindFirst(dirmatch.GetChars(), &find);
if (handle == ((void*)(-1)))
{
return false;
}
else
{
do
{
auto attr = I_FindAttr(&find);
if (attr & FA_HIDDEN)
{
// Skip hidden files and directories. (Prevents SVN bookkeeping
// info from being included.)
continue;
}
auto fn = I_FindName(&find);
if (attr & FA_DIREC)
{
if (fn[0] == '.' &&
(fn[1] == '\0' ||
(fn[1] == '.' && fn[2] == '\0')))
{
// Do not record . and .. directories.
continue;
}
FFileList* fl = &list[list.Reserve(1)];
fl->Filename << dirpath << fn;
fl->isDirectory = true;
FString newdir = fl->Filename;
newdir << "/";
ScanDirectory(list, newdir);
}
else
{
FFileList* fl = &list[list.Reserve(1)];
fl->Filename << dirpath << fn;
fl->isDirectory = false;
}
}
while (I_FindNext(handle, &find) == 0);
I_FindClose(handle);
}
return true;
}
//==========================================================================
//
//
@ -1064,7 +983,7 @@ void md5Update(FileReader& file, MD5Context& md5, unsigned len)
while (len > 0)
{
t = min<unsigned>(len, sizeof(readbuf));
t = std::min<unsigned>(len, sizeof(readbuf));
len -= t;
t = (long)file.Read(readbuf, t);
md5.Update(readbuf, t);

View file

@ -54,7 +54,6 @@ struct FScriptPosition;
bool IsNum (const char *str); // [RH] added
char *copystring(const char *s);
void ReplaceString (char **ptr, const char *str);
bool CheckWildcards (const char *pattern, const char *text);
@ -70,13 +69,6 @@ void CreatePath(const char * fn);
FString ExpandEnvVars(const char *searchpathstring);
FString NicePath(const char *path);
struct FFileList
{
FString Filename;
bool isDirectory;
};
bool ScanDirectory(TArray<FFileList> &list, const char *dirpath);
bool IsAbsPath(const char*);
FString M_ZLibError(int zerrnum);

View file

@ -59,13 +59,13 @@ public:
strncpy (m_Message, message, MAX_ERRORTEXT-1);
m_Message[MAX_ERRORTEXT-1] = '\0';
}
void AppendMessage(const char *message)
void AppendMessage(const char *message) noexcept
{
size_t len = strlen(m_Message);
strncpy(m_Message + len, message, MAX_ERRORTEXT - 1 - len);
m_Message[MAX_ERRORTEXT - 1] = '\0';
}
const char *GetMessage (void) const
const char *GetMessage (void) const noexcept
{
if (m_Message[0] != '\0')
return (const char *)m_Message;

View file

@ -1,489 +0,0 @@
/*
** files.cpp
** Implements classes for reading from files or memory blocks
**
**---------------------------------------------------------------------------
** Copyright 1998-2008 Randy Heit
** Copyright 2005-2008 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "files.h"
// just for 'clamp'
#include "zstring.h"
FILE *myfopen(const char *filename, const char *flags)
{
#ifndef _WIN32
return fopen(filename, flags);
#else
auto widename = WideString(filename);
auto wideflags = WideString(flags);
return _wfopen(widename.c_str(), wideflags.c_str());
#endif
}
//==========================================================================
//
// StdFileReader
//
// reads data from an stdio FILE* or part of it.
//
//==========================================================================
class StdFileReader : public FileReaderInterface
{
FILE *File = nullptr;
long StartPos = 0;
long FilePos = 0;
public:
StdFileReader()
{}
~StdFileReader()
{
if (File != nullptr)
{
fclose(File);
}
File = nullptr;
}
bool Open(const char *filename, long startpos = 0, long len = -1)
{
File = myfopen(filename, "rb");
if (File == nullptr) return false;
FilePos = startpos;
StartPos = startpos;
Length = CalcFileLen();
if (len >= 0 && len < Length) Length = len;
if (startpos > 0) Seek(0, SEEK_SET);
return true;
}
long Tell() const override
{
return FilePos - StartPos;
}
long Seek(long offset, int origin) override
{
if (origin == SEEK_SET)
{
offset += StartPos;
}
else if (origin == SEEK_CUR)
{
offset += FilePos;
}
else if (origin == SEEK_END)
{
offset += StartPos + Length;
}
if (offset < StartPos || offset > StartPos + Length) return -1; // out of scope
if (0 == fseek(File, offset, SEEK_SET))
{
FilePos = offset;
return 0;
}
return -1;
}
long Read(void *buffer, long len) override
{
assert(len >= 0);
if (len <= 0) return 0;
if (FilePos + len > StartPos + Length)
{
len = Length - FilePos + StartPos;
}
len = (long)fread(buffer, 1, len, File);
FilePos += len;
return len;
}
char *Gets(char *strbuf, int len) override
{
if (len <= 0 || FilePos >= StartPos + Length) return NULL;
char *p = fgets(strbuf, len, File);
if (p != NULL)
{
int old = FilePos;
FilePos = ftell(File);
if (FilePos - StartPos > Length)
{
strbuf[Length - old + StartPos] = 0;
}
}
return p;
}
private:
long CalcFileLen() const
{
long endpos;
fseek(File, 0, SEEK_END);
endpos = ftell(File);
fseek(File, 0, SEEK_SET);
return endpos;
}
};
//==========================================================================
//
// FileReaderRedirect
//
// like the above, but uses another File reader as its backing data
//
//==========================================================================
class FileReaderRedirect : public FileReaderInterface
{
FileReader *mReader = nullptr;
long StartPos = 0;
long FilePos = 0;
public:
FileReaderRedirect(FileReader &parent, long start, long length)
{
mReader = &parent;
FilePos = start;
StartPos = start;
Length = length;
Seek(0, SEEK_SET);
}
virtual long Tell() const override
{
return FilePos - StartPos;
}
virtual long Seek(long offset, int origin) override
{
switch (origin)
{
case SEEK_SET:
offset += StartPos;
break;
case SEEK_END:
offset += StartPos + Length;
break;
case SEEK_CUR:
offset += (long)mReader->Tell();
break;
}
if (offset < StartPos || offset > StartPos + Length) return -1; // out of scope
if (mReader->Seek(offset, FileReader::SeekSet) == 0)
{
FilePos = offset;
return 0;
}
return -1;
}
virtual long Read(void *buffer, long len) override
{
assert(len >= 0);
if (len <= 0) return 0;
if (FilePos + len > StartPos + Length)
{
len = Length - FilePos + StartPos;
}
len = (long)mReader->Read(buffer, len);
FilePos += len;
return len;
}
virtual char *Gets(char *strbuf, int len) override
{
if (len <= 0 || FilePos >= StartPos + Length) return NULL;
char *p = mReader->Gets(strbuf, len);
if (p != NULL)
{
int old = FilePos;
FilePos = (long)mReader->Tell();
if (FilePos - StartPos > Length)
{
strbuf[Length - old + StartPos] = 0;
}
}
return p;
}
};
//==========================================================================
//
// MemoryReader
//
// reads data from a block of memory
//
//==========================================================================
long MemoryReader::Tell() const
{
return FilePos;
}
long MemoryReader::Seek(long offset, int origin)
{
switch (origin)
{
case SEEK_CUR:
offset += FilePos;
break;
case SEEK_END:
offset += Length;
break;
}
if (offset < 0 || offset > Length) return -1;
FilePos = clamp<long>(offset, 0, Length);
return 0;
}
long MemoryReader::Read(void *buffer, long len)
{
if (len>Length - FilePos) len = Length - FilePos;
if (len<0) len = 0;
memcpy(buffer, bufptr + FilePos, len);
FilePos += len;
return len;
}
char *MemoryReader::Gets(char *strbuf, int len)
{
if (len>Length - FilePos) len = Length - FilePos;
if (len <= 0) return NULL;
char *p = strbuf;
while (len > 1)
{
if (bufptr[FilePos] == 0)
{
FilePos++;
break;
}
if (bufptr[FilePos] != '\r')
{
*p++ = bufptr[FilePos];
len--;
if (bufptr[FilePos] == '\n')
{
FilePos++;
break;
}
}
FilePos++;
}
if (p == strbuf) return NULL;
*p++ = 0;
return strbuf;
}
//==========================================================================
//
// MemoryArrayReader
//
// reads data from an array of memory
//
//==========================================================================
class MemoryArrayReader : public MemoryReader
{
TArray<uint8_t> buf;
public:
MemoryArrayReader(const char *buffer, long length)
{
if (length > 0)
{
buf.Resize(length);
memcpy(&buf[0], buffer, length);
}
UpdateBuffer();
}
TArray<uint8_t> &GetArray() { return buf; }
void UpdateBuffer()
{
bufptr = (const char*)&buf[0];
FilePos = 0;
Length = buf.Size();
}
};
//==========================================================================
//
// FileReader
//
// this wraps the different reader types in an object with value semantics.
//
//==========================================================================
bool FileReader::OpenFile(const char *filename, FileReader::Size start, FileReader::Size length)
{
auto reader = new StdFileReader;
if (!reader->Open(filename, (long)start, (long)length))
{
delete reader;
return false;
}
Close();
mReader = reader;
return true;
}
bool FileReader::OpenFilePart(FileReader &parent, FileReader::Size start, FileReader::Size length)
{
auto reader = new FileReaderRedirect(parent, (long)start, (long)length);
Close();
mReader = reader;
return true;
}
bool FileReader::OpenMemory(const void *mem, FileReader::Size length)
{
Close();
mReader = new MemoryReader((const char *)mem, (long)length);
return true;
}
bool FileReader::OpenMemoryArray(const void *mem, FileReader::Size length)
{
Close();
mReader = new MemoryArrayReader((const char *)mem, (long)length);
return true;
}
bool FileReader::OpenMemoryArray(std::function<bool(TArray<uint8_t>&)> getter)
{
auto reader = new MemoryArrayReader(nullptr, 0);
if (getter(reader->GetArray()))
{
Close();
reader->UpdateBuffer();
mReader = reader;
return true;
}
else
{
// This will keep the old buffer, if one existed
delete reader;
return false;
}
}
//==========================================================================
//
// FileWriter (the motivation here is to have a buffer writing subclass)
//
//==========================================================================
bool FileWriter::OpenDirect(const char *filename)
{
File = myfopen(filename, "wb");
return (File != NULL);
}
FileWriter *FileWriter::Open(const char *filename)
{
FileWriter *fwrit = new FileWriter();
if (fwrit->OpenDirect(filename))
{
return fwrit;
}
delete fwrit;
return NULL;
}
size_t FileWriter::Write(const void *buffer, size_t len)
{
if (File != NULL)
{
return fwrite(buffer, 1, len, File);
}
else
{
return 0;
}
}
long FileWriter::Tell()
{
if (File != NULL)
{
return ftell(File);
}
else
{
return 0;
}
}
long FileWriter::Seek(long offset, int mode)
{
if (File != NULL)
{
return fseek(File, offset, mode);
}
else
{
return 0;
}
}
size_t FileWriter::Printf(const char *fmt, ...)
{
va_list ap;
FString out;
va_start(ap, fmt);
out.VFormat(fmt, ap);
va_end(ap);
return Write(out.GetChars(), out.Len());
}
size_t BufferWriter::Write(const void *buffer, size_t len)
{
unsigned int ofs = mBuffer.Reserve((unsigned)len);
memcpy(&mBuffer[ofs], buffer, len);
return len;
}

View file

@ -1,377 +0,0 @@
/*
** files.h
** Implements classes for reading from files or memory blocks
**
**---------------------------------------------------------------------------
** Copyright 1998-2008 Randy Heit
** Copyright 2005-2008 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#ifndef FILES_H
#define FILES_H
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <functional>
#include "basics.h"
#include "m_swap.h"
#include "tarray.h"
// Zip compression methods, extended by some internal types to be passed to OpenDecompressor
enum
{
METHOD_STORED = 0,
METHOD_SHRINK = 1,
METHOD_IMPLODE = 6,
METHOD_DEFLATE = 8,
METHOD_BZIP2 = 12,
METHOD_LZMA = 14,
METHOD_PPMD = 98,
METHOD_LZSS = 1337, // not used in Zips - this is for Console Doom compression
METHOD_ZLIB = 1338, // Zlib stream with header, used by compressed nodes.
METHOD_TRANSFEROWNER = 0x8000,
};
class FileReader;
class FileReaderInterface
{
public:
long Length = -1;
virtual ~FileReaderInterface() {}
virtual long Tell () const = 0;
virtual long Seek (long offset, int origin) = 0;
virtual long Read (void *buffer, long len) = 0;
virtual char *Gets(char *strbuf, int len) = 0;
virtual const char *GetBuffer() const { return nullptr; }
long GetLength () const { return Length; }
};
class MemoryReader : public FileReaderInterface
{
protected:
const char * bufptr = nullptr;
long FilePos = 0;
MemoryReader()
{}
public:
MemoryReader(const char *buffer, long length)
{
bufptr = buffer;
Length = length;
FilePos = 0;
}
long Tell() const override;
long Seek(long offset, int origin) override;
long Read(void *buffer, long len) override;
char *Gets(char *strbuf, int len) override;
virtual const char *GetBuffer() const override { return bufptr; }
};
struct FResourceLump;
class FileReader
{
friend struct FResourceLump; // needs access to the private constructor.
FileReaderInterface *mReader = nullptr;
FileReader(const FileReader &r) = delete;
FileReader &operator=(const FileReader &r) = delete;
public:
explicit FileReader(FileReaderInterface *r)
{
mReader = r;
}
enum ESeek
{
SeekSet = SEEK_SET,
SeekCur = SEEK_CUR,
SeekEnd = SEEK_END
};
typedef ptrdiff_t Size; // let's not use 'long' here.
FileReader() {}
FileReader(FileReader &&r)
{
mReader = r.mReader;
r.mReader = nullptr;
}
FileReader& operator =(FileReader &&r)
{
Close();
mReader = r.mReader;
r.mReader = nullptr;
return *this;
}
// This is for wrapping the actual reader for custom access where a managed FileReader won't work.
FileReaderInterface* GetInterface()
{
auto i = mReader;
mReader = nullptr;
return i;
}
~FileReader()
{
Close();
}
bool isOpen() const
{
return mReader != nullptr;
}
void Close()
{
if (mReader != nullptr) delete mReader;
mReader = nullptr;
}
bool OpenFile(const char *filename, Size start = 0, Size length = -1);
bool OpenFilePart(FileReader &parent, Size start, Size length);
bool OpenMemory(const void *mem, Size length); // read directly from the buffer
bool OpenMemoryArray(const void *mem, Size length); // read from a copy of the buffer.
bool OpenMemoryArray(std::function<bool(TArray<uint8_t>&)> getter); // read contents to a buffer and return a reader to it
bool OpenDecompressor(FileReader &parent, Size length, int method, bool seekable, const std::function<void(const char*)>& cb); // creates a decompressor stream. 'seekable' uses a buffered version so that the Seek and Tell methods can be used.
Size Tell() const
{
return mReader->Tell();
}
Size Seek(Size offset, ESeek origin)
{
return mReader->Seek((long)offset, origin);
}
Size Read(void *buffer, Size len) const
{
return mReader->Read(buffer, (long)len);
}
TArray<uint8_t> Read(size_t len)
{
TArray<uint8_t> buffer((int)len, true);
Size length = mReader->Read(&buffer[0], (long)len);
buffer.Clamp((int)length);
return buffer;
}
TArray<uint8_t> Read()
{
TArray<uint8_t> buffer(mReader->Length, true);
Size length = mReader->Read(&buffer[0], mReader->Length);
if (length < mReader->Length) buffer.Clear();
return buffer;
}
TArray<uint8_t> ReadPadded(int padding)
{
TArray<uint8_t> buffer(mReader->Length + padding, true);
Size length = mReader->Read(&buffer[0], mReader->Length);
if (length < mReader->Length) buffer.Clear();
else memset(buffer.Data() + mReader->Length, 0, padding);
return buffer;
}
char *Gets(char *strbuf, Size len)
{
return mReader->Gets(strbuf, (int)len);
}
const char *GetBuffer()
{
return mReader->GetBuffer();
}
Size GetLength() const
{
return mReader->GetLength();
}
uint8_t ReadUInt8()
{
uint8_t v = 0;
Read(&v, 1);
return v;
}
int8_t ReadInt8()
{
int8_t v = 0;
Read(&v, 1);
return v;
}
uint16_t ReadUInt16()
{
uint16_t v = 0;
Read(&v, 2);
return LittleShort(v);
}
int16_t ReadInt16()
{
int16_t v = 0;
Read(&v, 2);
return LittleShort(v);
}
int16_t ReadInt16BE()
{
int16_t v = 0;
Read(&v, 2);
return BigShort(v);
}
uint32_t ReadUInt32()
{
uint32_t v = 0;
Read(&v, 4);
return LittleLong(v);
}
int32_t ReadInt32()
{
int32_t v = 0;
Read(&v, 4);
return LittleLong(v);
}
uint32_t ReadUInt32BE()
{
uint32_t v = 0;
Read(&v, 4);
return BigLong(v);
}
int32_t ReadInt32BE()
{
int32_t v = 0;
Read(&v, 4);
return BigLong(v);
}
uint64_t ReadUInt64()
{
uint64_t v = 0;
Read(&v, 8);
// Prove to me that there's a relevant 64 bit Big Endian architecture and I fix this! :P
return v;
}
friend class FileSystem;
};
class DecompressorBase : public FileReaderInterface
{
std::function<void(const char*)> ErrorCallback = nullptr;
public:
// These do not work but need to be defined to satisfy the FileReaderInterface.
// They will just error out when called.
long Tell() const override;
long Seek(long offset, int origin) override;
char* Gets(char* strbuf, int len) override;
void DecompressionError(const char* error, ...) const;
void SetErrorCallback(const std::function<void(const char*)>& cb)
{
ErrorCallback = cb;
}
void SetOwnsReader();
protected:
FileReader* File = nullptr;
FileReader OwnedFile;
};
class FileWriter
{
protected:
bool OpenDirect(const char *filename);
public:
FileWriter(FILE *f = nullptr) // if passed, this writer will take over the file.
{
File = f;
}
virtual ~FileWriter()
{
Close();
}
static FileWriter *Open(const char *filename);
virtual size_t Write(const void *buffer, size_t len);
virtual long Tell();
virtual long Seek(long offset, int mode);
size_t Printf(const char *fmt, ...) GCCPRINTF(2,3);
virtual void Close()
{
if (File != NULL) fclose(File);
File = nullptr;
}
protected:
FILE *File;
protected:
bool CloseOnDestruct;
};
class BufferWriter : public FileWriter
{
protected:
TArray<unsigned char> mBuffer;
public:
BufferWriter() {}
virtual size_t Write(const void *buffer, size_t len) override;
TArray<unsigned char> *GetBuffer() { return &mBuffer; }
TArray<unsigned char>&& TakeBuffer() { return std::move(mBuffer); }
};
#endif

View file

@ -1,654 +0,0 @@
/*
** files.cpp
** Implements classes for reading from files or memory blocks
**
**---------------------------------------------------------------------------
** Copyright 1998-2008 Randy Heit
** Copyright 2005-2008 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
// Caution: LzmaDec also pulls in windows.h!
#define NOMINMAX
#include "LzmaDec.h"
#include <zlib.h>
#include <bzlib.h>
#include <algorithm>
#include <stdexcept>
#include "files.h"
#include "zstring.h"
#include "cmdlib.h"
//==========================================================================
//
// I_Error
//
// Throw an error that will send us to the console if we are far enough
// along in the startup process.
//
//==========================================================================
void DecompressorBase::DecompressionError(const char *error, ...) const
{
const int MAX_ERRORTEXT = 300;
va_list argptr;
char errortext[MAX_ERRORTEXT];
va_start(argptr, error);
vsnprintf(errortext, MAX_ERRORTEXT, error, argptr);
va_end(argptr);
if (ErrorCallback != nullptr) ErrorCallback(errortext);
else throw std::runtime_error(errortext);
}
long DecompressorBase::Tell () const
{
DecompressionError("Cannot get position of decompressor stream");
return 0;
}
long DecompressorBase::Seek (long offset, int origin)
{
DecompressionError("Cannot seek in decompressor stream");
return 0;
}
char *DecompressorBase::Gets(char *strbuf, int len)
{
DecompressionError("Cannot use Gets on decompressor stream");
return nullptr;
}
void DecompressorBase::SetOwnsReader()
{
OwnedFile = std::move(*File);
File = &OwnedFile;
}
//==========================================================================
//
// DecompressorZ
//
// The zlib wrapper
// reads data from a ZLib compressed stream
//
//==========================================================================
class DecompressorZ : public DecompressorBase
{
enum { BUFF_SIZE = 4096 };
bool SawEOF;
z_stream Stream;
uint8_t InBuff[BUFF_SIZE];
public:
DecompressorZ (FileReader *file, bool zip, const std::function<void(const char*)>& cb)
: SawEOF(false)
{
int err;
File = file;
SetErrorCallback(cb);
FillBuffer ();
Stream.zalloc = Z_NULL;
Stream.zfree = Z_NULL;
if (!zip) err = inflateInit (&Stream);
else err = inflateInit2 (&Stream, -MAX_WBITS);
if (err != Z_OK)
{
DecompressionError ("DecompressorZ: inflateInit failed: %s\n", M_ZLibError(err).GetChars());
}
}
~DecompressorZ ()
{
inflateEnd (&Stream);
}
long Read (void *buffer, long len) override
{
int err;
Stream.next_out = (Bytef *)buffer;
Stream.avail_out = len;
do
{
err = inflate (&Stream, Z_SYNC_FLUSH);
if (Stream.avail_in == 0 && !SawEOF)
{
FillBuffer ();
}
} while (err == Z_OK && Stream.avail_out != 0);
if (err != Z_OK && err != Z_STREAM_END)
{
DecompressionError ("Corrupt zlib stream");
}
if (Stream.avail_out != 0)
{
DecompressionError ("Ran out of data in zlib stream");
}
return len - Stream.avail_out;
}
void FillBuffer ()
{
auto numread = File->Read (InBuff, BUFF_SIZE);
if (numread < BUFF_SIZE)
{
SawEOF = true;
}
Stream.next_in = InBuff;
Stream.avail_in = (uInt)numread;
}
};
//==========================================================================
//
// DecompressorZ
//
// The bzip2 wrapper
// reads data from a libbzip2 compressed stream
//
//==========================================================================
class DecompressorBZ2;
static DecompressorBZ2 * stupidGlobal; // Why does that dumb global error callback not pass the decompressor state?
// Thanks to that brain-dead interface we have to use a global variable to get the error to the proper handler.
class DecompressorBZ2 : public DecompressorBase
{
enum { BUFF_SIZE = 4096 };
bool SawEOF;
bz_stream Stream;
uint8_t InBuff[BUFF_SIZE];
public:
DecompressorBZ2 (FileReader *file, const std::function<void(const char*)>& cb)
: SawEOF(false)
{
int err;
File = file;
SetErrorCallback(cb);
stupidGlobal = this;
FillBuffer ();
Stream.bzalloc = NULL;
Stream.bzfree = NULL;
Stream.opaque = NULL;
err = BZ2_bzDecompressInit(&Stream, 0, 0);
if (err != BZ_OK)
{
DecompressionError ("DecompressorBZ2: bzDecompressInit failed: %d\n", err);
}
}
~DecompressorBZ2 ()
{
stupidGlobal = this;
BZ2_bzDecompressEnd (&Stream);
}
long Read (void *buffer, long len) override
{
int err;
stupidGlobal = this;
Stream.next_out = (char *)buffer;
Stream.avail_out = len;
do
{
err = BZ2_bzDecompress(&Stream);
if (Stream.avail_in == 0 && !SawEOF)
{
FillBuffer ();
}
} while (err == BZ_OK && Stream.avail_out != 0);
if (err != BZ_OK && err != BZ_STREAM_END)
{
DecompressionError ("Corrupt bzip2 stream");
}
if (Stream.avail_out != 0)
{
DecompressionError ("Ran out of data in bzip2 stream");
}
return len - Stream.avail_out;
}
void FillBuffer ()
{
auto numread = File->Read(InBuff, BUFF_SIZE);
if (numread < BUFF_SIZE)
{
SawEOF = true;
}
Stream.next_in = (char *)InBuff;
Stream.avail_in = (unsigned)numread;
}
};
//==========================================================================
//
// bz_internal_error
//
// libbzip2 wants this, since we build it with BZ_NO_STDIO set.
//
//==========================================================================
extern "C" void bz_internal_error (int errcode)
{
if (stupidGlobal) stupidGlobal->DecompressionError("libbzip2: internal error number %d\n", errcode);
else std::terminate();
}
//==========================================================================
//
// DecompressorLZMA
//
// The lzma wrapper
// reads data from a LZMA compressed stream
//
//==========================================================================
static void *SzAlloc(ISzAllocPtr, size_t size) { return malloc(size); }
static void SzFree(ISzAllocPtr, void *address) { free(address); }
ISzAlloc g_Alloc = { SzAlloc, SzFree };
// Wraps around a Decompressor to decompress a lzma stream
class DecompressorLZMA : public DecompressorBase
{
enum { BUFF_SIZE = 4096 };
bool SawEOF;
CLzmaDec Stream;
size_t Size;
size_t InPos, InSize;
size_t OutProcessed;
uint8_t InBuff[BUFF_SIZE];
public:
DecompressorLZMA (FileReader *file, size_t uncompressed_size, const std::function<void(const char*)>& cb)
: SawEOF(false)
{
uint8_t header[4 + LZMA_PROPS_SIZE];
int err;
File = file;
SetErrorCallback(cb);
Size = uncompressed_size;
OutProcessed = 0;
// Read zip LZMA properties header
if (File->Read(header, sizeof(header)) < (long)sizeof(header))
{
DecompressionError("DecompressorLZMA: File too short\n");
}
if (header[2] + header[3] * 256 != LZMA_PROPS_SIZE)
{
DecompressionError("DecompressorLZMA: LZMA props size is %d (expected %d)\n",
header[2] + header[3] * 256, LZMA_PROPS_SIZE);
}
FillBuffer();
LzmaDec_Construct(&Stream);
err = LzmaDec_Allocate(&Stream, header + 4, LZMA_PROPS_SIZE, &g_Alloc);
if (err != SZ_OK)
{
DecompressionError("DecompressorLZMA: LzmaDec_Allocate failed: %d\n", err);
}
LzmaDec_Init(&Stream);
}
~DecompressorLZMA ()
{
LzmaDec_Free(&Stream, &g_Alloc);
}
long Read (void *buffer, long len) override
{
int err;
Byte *next_out = (Byte *)buffer;
do
{
ELzmaFinishMode finish_mode = LZMA_FINISH_ANY;
ELzmaStatus status;
size_t out_processed = len;
size_t in_processed = InSize;
err = LzmaDec_DecodeToBuf(&Stream, next_out, &out_processed, InBuff + InPos, &in_processed, finish_mode, &status);
InPos += in_processed;
InSize -= in_processed;
next_out += out_processed;
len = (long)(len - out_processed);
if (err != SZ_OK)
{
DecompressionError ("Corrupt LZMA stream");
}
if (in_processed == 0 && out_processed == 0)
{
if (status != LZMA_STATUS_FINISHED_WITH_MARK)
{
DecompressionError ("Corrupt LZMA stream");
}
}
if (InSize == 0 && !SawEOF)
{
FillBuffer ();
}
} while (err == SZ_OK && len != 0);
if (err != Z_OK && err != Z_STREAM_END)
{
DecompressionError ("Corrupt LZMA stream");
}
if (len != 0)
{
DecompressionError ("Ran out of data in LZMA stream");
}
return (long)(next_out - (Byte *)buffer);
}
void FillBuffer ()
{
auto numread = File->Read(InBuff, BUFF_SIZE);
if (numread < BUFF_SIZE)
{
SawEOF = true;
}
InPos = 0;
InSize = numread;
}
};
//==========================================================================
//
// Console Doom LZSS wrapper.
//
//==========================================================================
class DecompressorLZSS : public DecompressorBase
{
enum { BUFF_SIZE = 4096, WINDOW_SIZE = 4096, INTERNAL_BUFFER_SIZE = 128 };
bool SawEOF;
uint8_t InBuff[BUFF_SIZE];
enum StreamState
{
STREAM_EMPTY,
STREAM_BITS,
STREAM_FLUSH,
STREAM_FINAL
};
struct
{
StreamState State;
uint8_t *In;
unsigned int AvailIn;
unsigned int InternalOut;
uint8_t CFlags, Bits;
uint8_t Window[WINDOW_SIZE+INTERNAL_BUFFER_SIZE];
const uint8_t *WindowData;
uint8_t *InternalBuffer;
} Stream;
void FillBuffer()
{
if(Stream.AvailIn)
memmove(InBuff, Stream.In, Stream.AvailIn);
auto numread = File->Read(InBuff+Stream.AvailIn, BUFF_SIZE-Stream.AvailIn);
if (numread < BUFF_SIZE)
{
SawEOF = true;
}
Stream.In = InBuff;
Stream.AvailIn = (unsigned)numread+Stream.AvailIn;
}
// Reads a flag byte.
void PrepareBlocks()
{
assert(Stream.InternalBuffer == Stream.WindowData);
Stream.CFlags = *Stream.In++;
--Stream.AvailIn;
Stream.Bits = 0xFF;
Stream.State = STREAM_BITS;
}
// Reads the next chunk in the block. Returns true if successful and
// returns false if it ran out of input data.
bool UncompressBlock()
{
if(Stream.CFlags & 1)
{
// Check to see if we have enough input
if(Stream.AvailIn < 2)
return false;
Stream.AvailIn -= 2;
uint16_t pos = BigShort(*(uint16_t*)Stream.In);
uint8_t len = (pos & 0xF)+1;
pos >>= 4;
Stream.In += 2;
if(len == 1)
{
// We've reached the end of the stream.
Stream.State = STREAM_FINAL;
return true;
}
const uint8_t* copyStart = Stream.InternalBuffer-pos-1;
// Complete overlap: Single byte repeated
if(pos == 0)
memset(Stream.InternalBuffer, *copyStart, len);
// No overlap: One copy
else if(pos >= len)
memcpy(Stream.InternalBuffer, copyStart, len);
else
{
// Partial overlap: Copy in 2 or 3 chunks.
do
{
unsigned int copy = min<unsigned int>(len, pos+1);
memcpy(Stream.InternalBuffer, copyStart, copy);
Stream.InternalBuffer += copy;
Stream.InternalOut += copy;
len -= copy;
pos += copy; // Increase our position since we can copy twice as much the next round.
}
while(len);
}
Stream.InternalOut += len;
Stream.InternalBuffer += len;
}
else
{
// Uncompressed byte.
*Stream.InternalBuffer++ = *Stream.In++;
--Stream.AvailIn;
++Stream.InternalOut;
}
Stream.CFlags >>= 1;
Stream.Bits >>= 1;
// If we're done with this block, flush the output
if(Stream.Bits == 0)
Stream.State = STREAM_FLUSH;
return true;
}
public:
DecompressorLZSS(FileReader *file, const std::function<void(const char*)>& cb) : SawEOF(false)
{
File = file;
SetErrorCallback(cb);
Stream.State = STREAM_EMPTY;
Stream.WindowData = Stream.InternalBuffer = Stream.Window+WINDOW_SIZE;
Stream.InternalOut = 0;
Stream.AvailIn = 0;
FillBuffer();
}
~DecompressorLZSS()
{
}
long Read(void *buffer, long len) override
{
uint8_t *Out = (uint8_t*)buffer;
long AvailOut = len;
do
{
while(Stream.AvailIn)
{
if(Stream.State == STREAM_EMPTY)
PrepareBlocks();
else if(Stream.State == STREAM_BITS && !UncompressBlock())
break;
else
break;
}
unsigned int copy = min<unsigned int>(Stream.InternalOut, AvailOut);
if(copy > 0)
{
memcpy(Out, Stream.WindowData, copy);
Out += copy;
AvailOut -= copy;
// Slide our window
memmove(Stream.Window, Stream.Window+copy, WINDOW_SIZE+INTERNAL_BUFFER_SIZE-copy);
Stream.InternalBuffer -= copy;
Stream.InternalOut -= copy;
}
if(Stream.State == STREAM_FINAL)
break;
if(Stream.InternalOut == 0 && Stream.State == STREAM_FLUSH)
Stream.State = STREAM_EMPTY;
if(Stream.AvailIn < 2)
FillBuffer();
}
while(AvailOut && Stream.State != STREAM_FINAL);
assert(AvailOut == 0);
return (long)(Out - (uint8_t*)buffer);
}
};
bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, bool seekable, const std::function<void(const char*)>& cb)
{
DecompressorBase *dec = nullptr;
FileReader *p = &parent;
switch (method & ~METHOD_TRANSFEROWNER)
{
case METHOD_DEFLATE:
case METHOD_ZLIB:
dec = new DecompressorZ(p, method == METHOD_DEFLATE, cb);
break;
case METHOD_BZIP2:
dec = new DecompressorBZ2(p, cb);
break;
case METHOD_LZMA:
dec = new DecompressorLZMA(p, length, cb);
break;
case METHOD_LZSS:
dec = new DecompressorLZSS(p, cb);
break;
// todo: METHOD_IMPLODE, METHOD_SHRINK
default:
return false;
}
if (method & METHOD_TRANSFEROWNER)
{
dec->SetOwnsReader();
}
dec->Length = (long)length;
if (!seekable)
{
Close();
mReader = dec;
return true;
}
else
{
// todo: create a wrapper. for now this fails
delete dec;
return false;
}
}

View file

@ -38,160 +38,8 @@
#include "printf.h"
#include "configfile.h"
#include "i_system.h"
#include "fs_findfile.h"
#ifndef _WIN32
#include <unistd.h>
#include <fnmatch.h>
#include <sys/stat.h>
#include "cmdlib.h"
static const char *pattern;
static int matchfile(const struct dirent *ent)
{
return fnmatch(pattern, ent->d_name, FNM_NOESCAPE) == 0;
}
void *I_FindFirst(const char *const filespec, findstate_t *const fileinfo)
{
FString dir;
const char *const slash = strrchr(filespec, '/');
if (slash)
{
pattern = slash + 1;
dir = FString(filespec, slash - filespec + 1);
fileinfo->path = dir;
}
else
{
pattern = filespec;
dir = ".";
}
fileinfo->current = 0;
fileinfo->count = scandir(dir.GetChars(), &fileinfo->namelist, matchfile, alphasort);
if (fileinfo->count > 0)
{
return fileinfo;
}
return (void *)-1;
}
int I_FindNext(void *const handle, findstate_t *const fileinfo)
{
findstate_t *const state = static_cast<findstate_t *>(handle);
if (state->current < fileinfo->count)
{
return ++state->current < fileinfo->count ? 0 : -1;
}
return -1;
}
int I_FindClose(void *const handle)
{
findstate_t *const state = static_cast<findstate_t *>(handle);
if (handle != (void *)-1 && state->count > 0)
{
for (int i = 0; i < state->count; ++i)
{
free(state->namelist[i]);
}
free(state->namelist);
state->namelist = nullptr;
state->count = 0;
}
return 0;
}
int I_FindAttr(findstate_t *const fileinfo)
{
dirent *const ent = fileinfo->namelist[fileinfo->current];
const FString path = fileinfo->path + ent->d_name;
bool isdir;
if (DirEntryExists(path, &isdir))
{
return isdir ? FA_DIREC : 0;
}
return 0;
}
#else
#include <windows.h>
#include <direct.h>
//==========================================================================
//
// I_FindFirst
//
// Start a pattern matching sequence.
//
//==========================================================================
void *I_FindFirst(const char *filespec, findstate_t *fileinfo)
{
static_assert(sizeof(WIN32_FIND_DATAW) == sizeof(fileinfo->FindData), "FindData size mismatch");
auto widespec = WideString(filespec);
fileinfo->UTF8Name = "";
return FindFirstFileW(widespec.c_str(), (LPWIN32_FIND_DATAW)&fileinfo->FindData);
}
//==========================================================================
//
// I_FindNext
//
// Return the next file in a pattern matching sequence.
//
//==========================================================================
int I_FindNext(void *handle, findstate_t *fileinfo)
{
fileinfo->UTF8Name = "";
return !FindNextFileW((HANDLE)handle, (LPWIN32_FIND_DATAW)&fileinfo->FindData);
}
//==========================================================================
//
// I_FindClose
//
// Finish a pattern matching sequence.
//
//==========================================================================
int I_FindClose(void *handle)
{
return FindClose((HANDLE)handle);
}
//==========================================================================
//
// I_FindName
//
// Returns the name for an entry
//
//==========================================================================
const char *I_FindName(findstate_t *fileinfo)
{
if (fileinfo->UTF8Name.IsEmpty()) fileinfo->UTF8Name = fileinfo->FindData.Name;
return fileinfo->UTF8Name.GetChars();
}
#endif
//==========================================================================
//
@ -288,45 +136,17 @@ void D_AddWildFile(TArray<FString>& wadfiles, const char* value, const char *ext
{
D_AddFile(wadfiles, wadfile, true, -1, config);
}
else
{ // Try pattern matching
findstate_t findstate;
char path[ZPATH_MAX];
char* sep;
void* handle = I_FindFirst(value, &findstate);
strcpy(path, value);
sep = strrchr(path, '/');
if (sep == nullptr)
{
sep = strrchr(path, '\\');
#ifdef _WIN32
if (sep == nullptr && path[1] == ':')
else
{
// Try pattern matching
FileList list;
if (ScanDirectory(list, value, "*", true))
{
for(auto& entry : list)
{
sep = path + 1;
D_AddFile(wadfiles, entry.FilePath.c_str(), true, -1, config);
}
#endif
}
if (handle != ((void*)-1))
{
do
{
if (!(I_FindAttr(&findstate) & FA_DIREC))
{
if (sep == nullptr)
{
D_AddFile(wadfiles, I_FindName(&findstate), true, -1, config);
}
else
{
strcpy(sep + 1, I_FindName(&findstate));
D_AddFile(wadfiles, path, true, -1, config);
}
}
} while (I_FindNext(handle, &findstate) == 0);
}
I_FindClose(handle);
}
}
@ -370,40 +190,16 @@ void D_AddConfigFiles(TArray<FString>& wadfiles, const char* section, const char
void D_AddDirectory(TArray<FString>& wadfiles, const char* dir, const char *filespec, FConfigFile* config)
{
FString curdir = I_GetCWD();
if (curdir.IsNotEmpty())
FileList list;
if (ScanDirectory(list, dir, "*.wad", true))
{
char skindir[ZPATH_MAX];
findstate_t findstate;
void* handle;
size_t stuffstart;
stuffstart = strlen(dir);
memcpy(skindir, dir, stuffstart * sizeof(*dir));
skindir[stuffstart] = 0;
if (skindir[stuffstart - 1] == '/')
for (auto& entry : list)
{
skindir[--stuffstart] = 0;
}
if (I_ChDir(skindir))
{
skindir[stuffstart++] = '/';
if ((handle = I_FindFirst(filespec, &findstate)) != (void*)-1)
if (!entry.isDirectory)
{
do
{
if (!(I_FindAttr(&findstate) & FA_DIREC))
{
strcpy(skindir + stuffstart, I_FindName(&findstate));
D_AddFile(wadfiles, skindir, true, -1, config);
}
} while (I_FindNext(handle, &findstate) == 0);
I_FindClose(handle);
D_AddFile(wadfiles, entry.FilePath.c_str(), true, -1, config);
}
}
I_ChDir(curdir);
}
}

View file

@ -4,91 +4,6 @@
#include <stdint.h>
#include "zstring.h"
enum
{
ZPATH_MAX = 260
};
#ifndef _WIN32
#include <dirent.h>
struct findstate_t
{
private:
FString path;
struct dirent **namelist;
int current;
int count;
friend void *I_FindFirst(const char *filespec, findstate_t *fileinfo);
friend int I_FindNext(void *handle, findstate_t *fileinfo);
friend const char *I_FindName(findstate_t *fileinfo);
friend int I_FindAttr(findstate_t *fileinfo);
friend int I_FindClose(void *handle);
};
int I_FindAttr (findstate_t *fileinfo);
inline const char *I_FindName(findstate_t *fileinfo)
{
return (fileinfo->namelist[fileinfo->current]->d_name);
}
#define FA_RDONLY 1
#define FA_HIDDEN 2
#define FA_SYSTEM 4
#define FA_DIREC 8
#define FA_ARCH 16
#else
// Mirror WIN32_FIND_DATAW in <winbase.h>
struct findstate_t
{
private:
struct FileTime
{
uint32_t lo, hi;
};
struct WinData
{
uint32_t Attribs;
FileTime Times[3];
uint32_t Size[2];
uint32_t Reserved[2];
wchar_t Name[ZPATH_MAX];
wchar_t AltName[14];
};
WinData FindData;
FString UTF8Name;
friend void *I_FindFirst(const char *filespec, findstate_t *fileinfo);
friend int I_FindNext(void *handle, findstate_t *fileinfo);
friend const char *I_FindName(findstate_t *fileinfo);
friend int I_FindAttr(findstate_t *fileinfo);
};
const char *I_FindName(findstate_t *fileinfo);
inline int I_FindAttr(findstate_t *fileinfo)
{
return fileinfo->FindData.Attribs;
}
#define FA_RDONLY 0x00000001
#define FA_HIDDEN 0x00000002
#define FA_SYSTEM 0x00000004
#define FA_DIREC 0x00000010
#define FA_ARCH 0x00000020
#endif
void *I_FindFirst (const char *filespec, findstate_t *fileinfo);
int I_FindNext (void *handle, findstate_t *fileinfo);
int I_FindClose (void *handle);
class FConfigFile;

View file

@ -39,6 +39,7 @@
#include "files.h"
#include "filesystem.h"
#include "printf.h"
#include "m_swap.h"
#include "m_png.h"

View file

@ -1157,3 +1157,17 @@ bool myisupper(int code)
return false;
}
std::wstring WideString(const char* cin)
{
std::wstring buildbuffer;
if (cin)
{
// This is a bit tricky because we need to support both UTF-8 and legacy content in ISO-8859-1 / Windows 1252
// and thanks to user-side string manipulation it can be that a text mixes both.
// To convert the string this uses the same function as all text printing in the engine.
const uint8_t* in = (const uint8_t*)cin;
while (*in) buildbuffer.push_back((wchar_t)GetCharFromString(in));
}
return buildbuffer;
}

View file

@ -1,5 +1,7 @@
#pragma once
#include <string>
int utf8_encode(int32_t codepoint, uint8_t *buffer, int *size);
int utf8_decode(const uint8_t *src, int *size);
int GetCharFromString(const uint8_t *&string);
@ -18,3 +20,8 @@ int getAlternative(int code);
extern uint16_t win1252map[];
extern uint16_t lowerforupper[65536];
extern uint16_t upperforlower[65536];
// make this only visible on Windows, on other platforms this should not be called.
#ifdef _WIN32
std::wstring WideString(const char*);
#endif

View file

@ -1043,44 +1043,9 @@ struct TMatrix3x3
// Construct a rotation matrix about an arbitrary axis.
// (The axis vector must be normalized.)
TMatrix3x3(const Vector3 &axis, double radians)
TMatrix3x3(const Vector3 &axis, double degrees)
: TMatrix3x3(axis, g_sindeg(degrees), g_cosdeg(degrees))
{
double c = g_cos(radians), s = g_sin(radians), t = 1 - c;
/* In comments: A more readable version of the matrix setup.
This was found in Diana Gruber's article "The Mathematics of the
3D Rotation Matrix" at <http://www.makegames.com/3drotation/> and is
attributed to Graphics Gems (Glassner, Academic Press, 1990).
Cells[0][0] = t*axis.X*axis.X + c;
Cells[0][1] = t*axis.X*axis.Y - s*axis.Z;
Cells[0][2] = t*axis.X*axis.Z + s*axis.Y;
Cells[1][0] = t*axis.Y*axis.X + s*axis.Z;
Cells[1][1] = t*axis.Y*axis.Y + c;
Cells[1][2] = t*axis.Y*axis.Z - s*axis.X;
Cells[2][0] = t*axis.Z*axis.X - s*axis.Y;
Cells[2][1] = t*axis.Z*axis.Y + s*axis.X;
Cells[2][2] = t*axis.Z*axis.Z + c;
Outside comments: A faster version with only 10 (not 24) multiplies.
*/
double sx = s*axis.X, sy = s*axis.Y, sz = s*axis.Z;
double tx, ty, txx, tyy, u, v;
tx = t*axis.X;
Cells[0][0] = vec_t( (txx=tx*axis.X) + c );
Cells[0][1] = vec_t( (u=tx*axis.Y) - sz);
Cells[0][2] = vec_t( (v=tx*axis.Z) + sy);
ty = t*axis.Y;
Cells[1][0] = vec_t( u + sz);
Cells[1][1] = vec_t( (tyy=ty*axis.Y) + c );
Cells[1][2] = vec_t( (u=ty*axis.Z) - sx);
Cells[2][0] = vec_t( v - sy);
Cells[2][1] = vec_t( u + sx);
Cells[2][2] = vec_t( (t-txx-tyy) + c );
}
TMatrix3x3(const Vector3 &axis, double c/*cosine*/, double s/*sine*/)
@ -1106,10 +1071,10 @@ Outside comments: A faster version with only 10 (not 24) multiplies.
TMatrix3x3(const Vector3 &axis, TAngle<vec_t> degrees);
static TMatrix3x3 Rotate2D(double radians)
static TMatrix3x3 Rotate2D(double degrees)
{
double c = g_cos(radians);
double s = g_sin(radians);
double c = g_cosdeg(degrees);
double s = g_sindeg(degrees);
TMatrix3x3 ret;
ret.Cells[0][0] = c; ret.Cells[0][1] = -s; ret.Cells[0][2] = 0;
ret.Cells[1][0] = s; ret.Cells[1][1] = c; ret.Cells[1][2] = 0;

View file

@ -1326,19 +1326,6 @@ FString &FString::operator=(const wchar_t *copyStr)
return *this;
}
std::wstring WideString(const char *cin)
{
if (!cin) return L"";
const uint8_t *in = (const uint8_t*)cin;
// This is a bit tricky because we need to support both UTF-8 and legacy content in ISO-8859-1
// and thanks to user-side string manipulation it can be that a text mixes both.
// To convert the string this uses the same function as all text printing in the engine.
TArray<wchar_t> buildbuffer;
while (*in) buildbuffer.Push((wchar_t)GetCharFromString(in));
buildbuffer.Push(0);
return std::wstring(buildbuffer.Data());
}
static HANDLE StringHeap;
const SIZE_T STRING_HEAP_SIZE = 64*1024;
#endif

View file

@ -39,6 +39,7 @@
#include <stddef.h>
#include <string>
#include "tarray.h"
#include "utf8.h"
#ifdef __GNUC__
#define PRINTFISH(x) __attribute__((format(printf, 2, x)))
@ -57,10 +58,6 @@
#define IGNORE_FORMAT_POST
#endif
#ifdef _WIN32
std::wstring WideString(const char *);
#endif
struct FStringData
{
unsigned int Len; // Length of string, excluding terminating null