mirror of
https://github.com/ZDoom/Raze.git
synced 2025-03-13 20:42:11 +00:00
- backend update from GZDoom without adapting other code.
This commit is contained in:
parent
5eee7b80b1
commit
cf19d75242
80 changed files with 743 additions and 2707 deletions
|
@ -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} )
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#include "i_sound.h"
|
||||
#include "i_music.h"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ enum EJoyAxis
|
|||
};
|
||||
|
||||
// Generic configuration interface for a controller.
|
||||
struct NOVTABLE IJoystickConfig
|
||||
struct IJoystickConfig
|
||||
{
|
||||
virtual ~IJoystickConfig() = 0;
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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; }
|
||||
};
|
||||
|
||||
|
|
|
@ -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)" : "");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "utf8.h"
|
||||
#include "fontchars.h"
|
||||
#include "texturemanager.h"
|
||||
#include "m_swap.h"
|
||||
|
||||
#include "fontinternals.h"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "model_md3.h"
|
||||
#include "texturemanager.h"
|
||||
#include "modelrenderer.h"
|
||||
#include "m_swap.h"
|
||||
|
||||
#define MAX_QPATH 64
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "zstring.h"
|
||||
#include "tarray.h"
|
||||
|
||||
enum class PostProcessUniformType
|
||||
{
|
||||
Undefined,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "basics.h"
|
||||
|
||||
|
||||
struct FModelVertex
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
//****************************************************************************
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "printf.h"
|
||||
#include "texturemanager.h"
|
||||
#include "filesystem.h"
|
||||
#include "m_swap.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "bitmap.h"
|
||||
#include "imagehelpers.h"
|
||||
#include "image.h"
|
||||
#include "m_swap.h"
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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+
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
1
source/common/thirdparty/richpresence.cpp
vendored
1
source/common/thirdparty/richpresence.cpp
vendored
|
@ -36,6 +36,7 @@
|
|||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/engine/printf.h"
|
||||
#include "discord_rpc.h"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "files.h"
|
||||
#include "filesystem.h"
|
||||
#include "printf.h"
|
||||
#include "m_swap.h"
|
||||
|
||||
#include "m_png.h"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue