mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-03-20 01:41:27 +00:00
- transition to new FileReader interface complete, but untested.
This commit is contained in:
parent
247785bca2
commit
b14ee50d0d
31 changed files with 1352 additions and 1807 deletions
|
@ -886,6 +886,7 @@ set (PCH_SOURCES
|
|||
edata.cpp
|
||||
f_wipe.cpp
|
||||
files.cpp
|
||||
files_decompress.cpp
|
||||
g_doomedmap.cpp
|
||||
g_game.cpp
|
||||
g_hub.cpp
|
||||
|
|
|
@ -243,7 +243,7 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize,
|
|||
|
||||
FIWadManager::FIWadManager(const char *fn)
|
||||
{
|
||||
FResourceFile *resfile = FResourceFile::OpenResourceFile(fn, NULL, true);
|
||||
FResourceFile *resfile = FResourceFile::OpenResourceFile(fn, true);
|
||||
if (resfile != NULL)
|
||||
{
|
||||
uint32_t cnt = resfile->LumpCount();
|
||||
|
@ -276,7 +276,7 @@ FIWadManager::FIWadManager(const char *fn)
|
|||
|
||||
int FIWadManager::ScanIWAD (const char *iwad)
|
||||
{
|
||||
FResourceFile *iwadfile = FResourceFile::OpenResourceFile(iwad, NULL, true);
|
||||
FResourceFile *iwadfile = FResourceFile::OpenResourceFile(iwad, true);
|
||||
|
||||
mLumpsFound.Resize(mIWadInfos.Size());
|
||||
|
||||
|
@ -332,7 +332,7 @@ int FIWadManager::ScanIWAD (const char *iwad)
|
|||
|
||||
int FIWadManager::CheckIWADInfo(const char *fn)
|
||||
{
|
||||
FResourceFile *resfile = FResourceFile::OpenResourceFile(fn, NULL, true);
|
||||
FResourceFile *resfile = FResourceFile::OpenResourceFile(fn, true);
|
||||
if (resfile != NULL)
|
||||
{
|
||||
uint32_t cnt = resfile->LumpCount();
|
||||
|
|
|
@ -1947,7 +1947,6 @@ static FString CheckGameInfo(TArray<FString> & pwads)
|
|||
for(int i=pwads.Size()-1; i>=0; i--)
|
||||
{
|
||||
bool isdir = false;
|
||||
FileReader *wadinfo;
|
||||
FResourceFile *resfile;
|
||||
const char *filename = pwads[i];
|
||||
|
||||
|
@ -1960,16 +1959,13 @@ static FString CheckGameInfo(TArray<FString> & pwads)
|
|||
|
||||
if (!isdir)
|
||||
{
|
||||
try
|
||||
{
|
||||
wadinfo = new FileReader(filename);
|
||||
}
|
||||
catch (CRecoverableError &)
|
||||
FileRdr fr;
|
||||
if (!fr.OpenFile(filename))
|
||||
{
|
||||
// Didn't find file
|
||||
continue;
|
||||
}
|
||||
resfile = FResourceFile::OpenResourceFile(filename, wadinfo, true);
|
||||
resfile = FResourceFile::OpenResourceFile(filename, fr, true);
|
||||
}
|
||||
else
|
||||
resfile = FResourceFile::OpenDirectory(filename, true);
|
||||
|
|
822
src/files.cpp
822
src/files.cpp
|
@ -33,150 +33,252 @@
|
|||
**
|
||||
*/
|
||||
|
||||
// This also pulls in windows.h
|
||||
#include "LzmaDec.h"
|
||||
|
||||
#include "files.h"
|
||||
#include "i_system.h"
|
||||
#include "templates.h"
|
||||
#include "m_misc.h"
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FileReader
|
||||
// StdFileReader
|
||||
//
|
||||
// reads data from an uncompressed file or part of it
|
||||
// reads data from an stdio FILE* or part of it.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FILE *FileReader::openfd(const char *filename)
|
||||
class StdFileReader : public FileReaderInterface
|
||||
{
|
||||
return fopen(filename, "rb");
|
||||
}
|
||||
FILE *File = nullptr;
|
||||
long Length = 0;
|
||||
long StartPos = 0;
|
||||
long FilePos = 0;
|
||||
|
||||
FileReader::FileReader ()
|
||||
: File(NULL), Length(0), StartPos(0), FilePos(0), CloseOnDestruct(false)
|
||||
{
|
||||
}
|
||||
public:
|
||||
StdFileReader()
|
||||
{}
|
||||
|
||||
FileReader::FileReader (const FileReader &other, long length)
|
||||
: File(other.File), Length(length), CloseOnDestruct(false)
|
||||
{
|
||||
FilePos = StartPos = ftell (other.File);
|
||||
}
|
||||
|
||||
FileReader::FileReader (const char *filename)
|
||||
: File(NULL), Length(0), StartPos(0), FilePos(0), CloseOnDestruct(false)
|
||||
{
|
||||
if (!Open(filename))
|
||||
~StdFileReader()
|
||||
{
|
||||
I_Error ("Could not open %s", filename);
|
||||
if (File != nullptr)
|
||||
{
|
||||
fclose(File);
|
||||
}
|
||||
File = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
FileReader::FileReader (FILE *file)
|
||||
: File(file), Length(0), StartPos(0), FilePos(0), CloseOnDestruct(false)
|
||||
{
|
||||
Length = CalcFileLen();
|
||||
}
|
||||
|
||||
FileReader::FileReader (FILE *file, long length)
|
||||
: File(file), Length(length), CloseOnDestruct(true)
|
||||
{
|
||||
FilePos = StartPos = ftell (file);
|
||||
}
|
||||
|
||||
FileReader::~FileReader()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void FileReader::Close()
|
||||
{
|
||||
if (CloseOnDestruct && File != NULL)
|
||||
bool Open(const char *filename, long startpos = 0, long len = -1)
|
||||
{
|
||||
fclose (File);
|
||||
File = fopen(filename, "rb");
|
||||
if (File == nullptr) return false;
|
||||
FilePos = startpos;
|
||||
StartPos = startpos;
|
||||
Length = CalcFileLen();
|
||||
if (len >= 0 && len < Length) Length = len;
|
||||
if (startpos > 0) Seek(startpos, SEEK_SET);
|
||||
return true;
|
||||
}
|
||||
File = NULL;
|
||||
}
|
||||
|
||||
bool FileReader::Open (const char *filename)
|
||||
{
|
||||
File = openfd (filename);
|
||||
if (File == NULL) return false;
|
||||
FilePos = 0;
|
||||
StartPos = 0;
|
||||
CloseOnDestruct = true;
|
||||
Length = CalcFileLen();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void FileReader::ResetFilePtr ()
|
||||
{
|
||||
FilePos = ftell (File);
|
||||
}
|
||||
|
||||
long FileReader::Tell () const
|
||||
{
|
||||
return FilePos - StartPos;
|
||||
}
|
||||
|
||||
long FileReader::Seek (long offset, int origin)
|
||||
{
|
||||
if (origin == SEEK_SET)
|
||||
long Tell() const override
|
||||
{
|
||||
offset += StartPos;
|
||||
return FilePos - StartPos;
|
||||
}
|
||||
else if (origin == SEEK_CUR)
|
||||
|
||||
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
|
||||
{
|
||||
FileRdr *mReader = nullptr;
|
||||
long Length = 0;
|
||||
long StartPos = 0;
|
||||
long FilePos = 0;
|
||||
|
||||
public:
|
||||
FileReaderRedirect(FileRdr &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)
|
||||
{
|
||||
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, FileRdr::SeekSet) == 0)
|
||||
{
|
||||
FilePos = offset;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual long Read(void *buffer, long len)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
}
|
||||
else if (origin == SEEK_END)
|
||||
{
|
||||
offset += StartPos + Length;
|
||||
}
|
||||
if (0 == fseek (File, offset, SEEK_SET))
|
||||
{
|
||||
FilePos = offset;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
if (offset < 0 || offset >= Length) return -1;
|
||||
FilePos = clamp<long>(offset, 0, Length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
long FileReader::Read (void *buffer, long len)
|
||||
long MemoryReader::Read(void *buffer, long len)
|
||||
{
|
||||
assert(len >= 0);
|
||||
if (len <= 0) return 0;
|
||||
if (FilePos + len > StartPos + Length)
|
||||
{
|
||||
len = Length - FilePos + StartPos;
|
||||
}
|
||||
len = (long)fread (buffer, 1, len, File);
|
||||
if (len>Length - FilePos) len = Length - FilePos;
|
||||
if (len<0) len = 0;
|
||||
memcpy(buffer, bufptr + FilePos, len);
|
||||
FilePos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
char *FileReader::Gets(char *strbuf, int len)
|
||||
char *MemoryReader::Gets(char *strbuf, int len)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
char *FileReader::GetsFromBuffer(const char * bufptr, char *strbuf, int len)
|
||||
{
|
||||
if (len>Length-FilePos) len=Length-FilePos;
|
||||
if (len>Length - FilePos) len = Length - FilePos;
|
||||
if (len <= 0) return NULL;
|
||||
|
||||
char *p = strbuf;
|
||||
|
@ -191,7 +293,7 @@ char *FileReader::GetsFromBuffer(const char * bufptr, char *strbuf, int len)
|
|||
{
|
||||
*p++ = bufptr[FilePos];
|
||||
len--;
|
||||
if (bufptr[FilePos] == '\n')
|
||||
if (bufptr[FilePos] == '\n')
|
||||
{
|
||||
FilePos++;
|
||||
break;
|
||||
|
@ -199,360 +301,11 @@ char *FileReader::GetsFromBuffer(const char * bufptr, char *strbuf, int len)
|
|||
}
|
||||
FilePos++;
|
||||
}
|
||||
if (p==strbuf) return NULL;
|
||||
*p++=0;
|
||||
if (p == strbuf) return NULL;
|
||||
*p++ = 0;
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
long FileReader::CalcFileLen() const
|
||||
{
|
||||
long endpos;
|
||||
|
||||
fseek (File, 0, SEEK_END);
|
||||
endpos = ftell (File);
|
||||
fseek (File, 0, SEEK_SET);
|
||||
return endpos;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FileReaderZ
|
||||
//
|
||||
// The zlib wrapper
|
||||
// reads data from a ZLib compressed stream
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FileReaderZ::FileReaderZ (FileReader &file, bool zip)
|
||||
: File(file), SawEOF(false)
|
||||
{
|
||||
int err;
|
||||
|
||||
FillBuffer ();
|
||||
|
||||
Stream.zalloc = Z_NULL;
|
||||
Stream.zfree = Z_NULL;
|
||||
|
||||
if (!zip) err = inflateInit (&Stream);
|
||||
else err = inflateInit2 (&Stream, -MAX_WBITS);
|
||||
|
||||
if (err != Z_OK)
|
||||
{
|
||||
I_Error ("FileReaderZ: inflateInit failed: %s\n", M_ZLibError(err).GetChars());
|
||||
}
|
||||
}
|
||||
|
||||
FileReaderZ::~FileReaderZ ()
|
||||
{
|
||||
inflateEnd (&Stream);
|
||||
}
|
||||
|
||||
long FileReaderZ::Read (void *buffer, long len)
|
||||
{
|
||||
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)
|
||||
{
|
||||
I_Error ("Corrupt zlib stream");
|
||||
}
|
||||
|
||||
if (Stream.avail_out != 0)
|
||||
{
|
||||
I_Error ("Ran out of data in zlib stream");
|
||||
}
|
||||
|
||||
return len - Stream.avail_out;
|
||||
}
|
||||
|
||||
void FileReaderZ::FillBuffer ()
|
||||
{
|
||||
long numread = File.Read (InBuff, BUFF_SIZE);
|
||||
|
||||
if (numread < BUFF_SIZE)
|
||||
{
|
||||
SawEOF = true;
|
||||
}
|
||||
Stream.next_in = InBuff;
|
||||
Stream.avail_in = numread;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FileReaderZ
|
||||
//
|
||||
// The bzip2 wrapper
|
||||
// reads data from a libbzip2 compressed stream
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FileReaderBZ2::FileReaderBZ2 (FileReader &file)
|
||||
: File(file), SawEOF(false)
|
||||
{
|
||||
int err;
|
||||
|
||||
FillBuffer ();
|
||||
|
||||
Stream.bzalloc = NULL;
|
||||
Stream.bzfree = NULL;
|
||||
Stream.opaque = NULL;
|
||||
|
||||
err = BZ2_bzDecompressInit(&Stream, 0, 0);
|
||||
|
||||
if (err != BZ_OK)
|
||||
{
|
||||
I_Error ("FileReaderBZ2: bzDecompressInit failed: %d\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
FileReaderBZ2::~FileReaderBZ2 ()
|
||||
{
|
||||
BZ2_bzDecompressEnd (&Stream);
|
||||
}
|
||||
|
||||
long FileReaderBZ2::Read (void *buffer, long len)
|
||||
{
|
||||
int err;
|
||||
|
||||
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)
|
||||
{
|
||||
I_Error ("Corrupt bzip2 stream");
|
||||
}
|
||||
|
||||
if (Stream.avail_out != 0)
|
||||
{
|
||||
I_Error ("Ran out of data in bzip2 stream");
|
||||
}
|
||||
|
||||
return len - Stream.avail_out;
|
||||
}
|
||||
|
||||
void FileReaderBZ2::FillBuffer ()
|
||||
{
|
||||
long numread = File.Read(InBuff, BUFF_SIZE);
|
||||
|
||||
if (numread < BUFF_SIZE)
|
||||
{
|
||||
SawEOF = true;
|
||||
}
|
||||
Stream.next_in = (char *)InBuff;
|
||||
Stream.avail_in = numread;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// bz_internal_error
|
||||
//
|
||||
// libbzip2 wants this, since we build it with BZ_NO_STDIO set.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
extern "C" void bz_internal_error (int errcode)
|
||||
{
|
||||
I_FatalError("libbzip2: internal error number %d\n", errcode);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FileReaderLZMA
|
||||
//
|
||||
// The lzma wrapper
|
||||
// reads data from a LZMA compressed stream
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
// This is retarded but necessary to work around the inclusion of windows.h in recent
|
||||
// LZMA versions, meaning it's no longer possible to include the LZMA headers in files.h.
|
||||
// As a result we cannot declare the CLzmaDec member in the header so we work around
|
||||
// it my wrapping it into another struct that can be declared anonymously in the header.
|
||||
struct FileReaderLZMA::StreamPointer
|
||||
{
|
||||
CLzmaDec Stream;
|
||||
};
|
||||
|
||||
static void *SzAlloc(ISzAllocPtr, size_t size) { return malloc(size); }
|
||||
static void SzFree(ISzAllocPtr, void *address) { free(address); }
|
||||
ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
FileReaderLZMA::FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip)
|
||||
: File(file), SawEOF(false)
|
||||
{
|
||||
uint8_t header[4 + LZMA_PROPS_SIZE];
|
||||
int err;
|
||||
|
||||
assert(zip == true);
|
||||
|
||||
Size = uncompressed_size;
|
||||
OutProcessed = 0;
|
||||
|
||||
// Read zip LZMA properties header
|
||||
if (File.Read(header, sizeof(header)) < (long)sizeof(header))
|
||||
{
|
||||
I_Error("FileReaderLZMA: File too shart\n");
|
||||
}
|
||||
if (header[2] + header[3] * 256 != LZMA_PROPS_SIZE)
|
||||
{
|
||||
I_Error("FileReaderLZMA: LZMA props size is %d (expected %d)\n",
|
||||
header[2] + header[3] * 256, LZMA_PROPS_SIZE);
|
||||
}
|
||||
|
||||
FillBuffer();
|
||||
|
||||
Streamp = new StreamPointer;
|
||||
LzmaDec_Construct(&Streamp->Stream);
|
||||
err = LzmaDec_Allocate(&Streamp->Stream, header + 4, LZMA_PROPS_SIZE, &g_Alloc);
|
||||
|
||||
if (err != SZ_OK)
|
||||
{
|
||||
I_Error("FileReaderLZMA: LzmaDec_Allocate failed: %d\n", err);
|
||||
}
|
||||
|
||||
LzmaDec_Init(&Streamp->Stream);
|
||||
}
|
||||
|
||||
FileReaderLZMA::~FileReaderLZMA ()
|
||||
{
|
||||
LzmaDec_Free(&Streamp->Stream, &g_Alloc);
|
||||
delete Streamp;
|
||||
}
|
||||
|
||||
long FileReaderLZMA::Read (void *buffer, long len)
|
||||
{
|
||||
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(&Streamp->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)
|
||||
{
|
||||
I_Error ("Corrupt LZMA stream");
|
||||
}
|
||||
if (in_processed == 0 && out_processed == 0)
|
||||
{
|
||||
if (status != LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
I_Error ("Corrupt LZMA stream");
|
||||
}
|
||||
}
|
||||
if (InSize == 0 && !SawEOF)
|
||||
{
|
||||
FillBuffer ();
|
||||
}
|
||||
} while (err == SZ_OK && len != 0);
|
||||
|
||||
if (err != Z_OK && err != Z_STREAM_END)
|
||||
{
|
||||
I_Error ("Corrupt LZMA stream");
|
||||
}
|
||||
|
||||
if (len != 0)
|
||||
{
|
||||
I_Error ("Ran out of data in LZMA stream");
|
||||
}
|
||||
|
||||
return (long)(next_out - (Byte *)buffer);
|
||||
}
|
||||
|
||||
void FileReaderLZMA::FillBuffer ()
|
||||
{
|
||||
long numread = File.Read(InBuff, BUFF_SIZE);
|
||||
|
||||
if (numread < BUFF_SIZE)
|
||||
{
|
||||
SawEOF = true;
|
||||
}
|
||||
InPos = 0;
|
||||
InSize = numread;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MemoryReader
|
||||
//
|
||||
// reads data from a block of memory
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
MemoryReader::MemoryReader (const char *buffer, long length)
|
||||
{
|
||||
bufptr=buffer;
|
||||
Length=length;
|
||||
FilePos=0;
|
||||
}
|
||||
|
||||
MemoryReader::~MemoryReader ()
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
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)
|
||||
{
|
||||
return GetsFromBuffer(bufptr, strbuf, len);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MemoryArrayReader
|
||||
|
@ -561,57 +314,88 @@ char *MemoryReader::Gets(char *strbuf, int len)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
MemoryArrayReader::MemoryArrayReader (const char *buffer, long length)
|
||||
class MemoryArrayReader : public MemoryReader
|
||||
{
|
||||
if (length > 0)
|
||||
TArray<uint8_t> buf;
|
||||
|
||||
public:
|
||||
MemoryArrayReader(const char *buffer, long length)
|
||||
{
|
||||
buf.Resize(length);
|
||||
memcpy(&buf[0], buffer, length);
|
||||
if (length > 0)
|
||||
{
|
||||
buf.Resize(length);
|
||||
memcpy(&buf[0], buffer, length);
|
||||
}
|
||||
Length = length;
|
||||
FilePos = 0;
|
||||
bufptr = (const char *)&buf[0];
|
||||
}
|
||||
Length = length;
|
||||
FilePos=0;
|
||||
}
|
||||
|
||||
MemoryArrayReader::~MemoryArrayReader ()
|
||||
TArray<uint8_t> &GetArray() { return buf; }
|
||||
|
||||
void UpdateLength() { Length = buf.Size(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FileReader
|
||||
//
|
||||
// this wraps the different reader types in an object with value semantics.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FileRdr::OpenFile(const char *filename, FileRdr::Size start, FileRdr::Size length)
|
||||
{
|
||||
auto reader = new StdFileReader;
|
||||
if (!reader->Open(filename, (long)start, (long)length)) return false;
|
||||
Close();
|
||||
mReader = reader;
|
||||
return true;
|
||||
}
|
||||
|
||||
long MemoryArrayReader::Tell () const
|
||||
bool FileRdr::OpenFilePart(FileRdr &parent, FileRdr::Size start, FileRdr::Size length)
|
||||
{
|
||||
return FilePos;
|
||||
auto reader = new FileReaderRedirect(parent, (long)start, (long)length);
|
||||
Close();
|
||||
mReader = reader;
|
||||
return true;
|
||||
}
|
||||
|
||||
long MemoryArrayReader::Seek (long offset, int origin)
|
||||
bool FileRdr::OpenMemory(const void *mem, FileRdr::Size length)
|
||||
{
|
||||
switch (origin)
|
||||
{
|
||||
case SEEK_CUR:
|
||||
offset+=FilePos;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
offset+=Length;
|
||||
break;
|
||||
|
||||
}
|
||||
FilePos=clamp<long>(offset,0,Length);
|
||||
return 0;
|
||||
Close();
|
||||
mReader = new MemoryReader((const char *)mem, (long)length);
|
||||
return true;
|
||||
}
|
||||
|
||||
long MemoryArrayReader::Read (void *buffer, long len)
|
||||
bool FileRdr::OpenMemoryArray(const void *mem, FileRdr::Size length)
|
||||
{
|
||||
if (len>Length-FilePos) len=Length-FilePos;
|
||||
if (len<0) len=0;
|
||||
memcpy(buffer,&buf[FilePos],len);
|
||||
FilePos+=len;
|
||||
return len;
|
||||
Close();
|
||||
mReader = new MemoryArrayReader((const char *)mem, (long)length);
|
||||
return true;
|
||||
}
|
||||
|
||||
char *MemoryArrayReader::Gets(char *strbuf, int len)
|
||||
bool FileRdr::OpenMemoryArray(std::function<bool(TArray<uint8_t>&)> getter)
|
||||
{
|
||||
return GetsFromBuffer((char*)&buf[0], strbuf, len);
|
||||
auto reader = new MemoryArrayReader(nullptr, 0);
|
||||
if (getter(reader->GetArray()))
|
||||
{
|
||||
Close();
|
||||
reader->UpdateLength();
|
||||
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)
|
||||
|
@ -671,7 +455,6 @@ long FileWriter::Seek(long offset, int mode)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
size_t FileWriter::Printf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
@ -689,52 +472,3 @@ size_t BufferWriter::Write(const void *buffer, size_t len)
|
|||
memcpy(&mBuffer[ofs], buffer, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
//
|
||||
// The new wrapper
|
||||
//
|
||||
//////////////////////////////////////
|
||||
|
||||
bool FileRdr::OpenFile(const char *filename)
|
||||
{
|
||||
auto reader = new FileReader;
|
||||
if (!reader->Open(filename)) return false;
|
||||
Close();
|
||||
mReader = reader;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileRdr::OpenMemory(const void *mem, FileRdr::Size length)
|
||||
{
|
||||
Close();
|
||||
mReader = new MemoryReader((const char *)mem, (long)length);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileRdr::OpenMemoryArray(const void *mem, FileRdr::Size length)
|
||||
{
|
||||
Close();
|
||||
mReader = new MemoryArrayReader((const char *)mem, (long)length);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileRdr::OpenMemoryArray(std::function<bool(TArray<uint8_t>&)> getter)
|
||||
{
|
||||
auto reader = new MemoryArrayReader(nullptr, 0);
|
||||
if (getter(reader->GetArray()))
|
||||
{
|
||||
Close();
|
||||
reader->UpdateLength();
|
||||
mReader = reader;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This will keep the old
|
||||
delete reader;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
628
src/files.h
628
src/files.h
|
@ -43,411 +43,197 @@
|
|||
#include "doomtype.h"
|
||||
#include "m_swap.h"
|
||||
|
||||
class FileReaderBase
|
||||
// Zip compression methods, extended by some internal types to be passed to FileReader::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.
|
||||
};
|
||||
|
||||
class FileReaderInterface
|
||||
{
|
||||
public:
|
||||
virtual ~FileReaderBase() {}
|
||||
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;
|
||||
|
||||
FileReaderBase &operator>> (uint8_t &v)
|
||||
{
|
||||
Read (&v, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderBase &operator>> (int8_t &v)
|
||||
{
|
||||
Read (&v, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderBase &operator>> (uint16_t &v)
|
||||
{
|
||||
Read (&v, 2);
|
||||
v = LittleShort(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderBase &operator>> (int16_t &v)
|
||||
{
|
||||
Read (&v, 2);
|
||||
v = LittleShort(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderBase &operator>> (uint32_t &v)
|
||||
{
|
||||
Read (&v, 4);
|
||||
v = LittleLong(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderBase &operator>> (int &v)
|
||||
{
|
||||
Read (&v, 4);
|
||||
v = LittleLong(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class FileReader : public FileReaderBase
|
||||
{
|
||||
protected:
|
||||
FILE *openfd(const char *filename);
|
||||
public:
|
||||
FileReader ();
|
||||
FileReader (const char *filename);
|
||||
FileReader (FILE *file);
|
||||
FileReader (FILE *file, long length);
|
||||
bool Open (const char *filename);
|
||||
void Close();
|
||||
virtual ~FileReader ();
|
||||
|
||||
virtual long Tell () const;
|
||||
virtual long Seek (long offset, int origin);
|
||||
virtual long Read (void *buffer, long len);
|
||||
virtual char *Gets(char *strbuf, int len);
|
||||
virtual char *Gets(char *strbuf, int len) = 0;
|
||||
virtual const char *GetBuffer() const { return nullptr; }
|
||||
long GetLength () const { return Length; }
|
||||
|
||||
// If you use the underlying FILE without going through this class,
|
||||
// you must call ResetFilePtr() before using this class again.
|
||||
void ResetFilePtr ();
|
||||
|
||||
FILE *GetFile () const { return File; }
|
||||
virtual const char *GetBuffer() const { return NULL; }
|
||||
|
||||
FileReader &operator>> (uint8_t &v)
|
||||
{
|
||||
Read (&v, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReader &operator>> (int8_t &v)
|
||||
{
|
||||
Read (&v, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReader &operator>> (uint16_t &v)
|
||||
{
|
||||
Read (&v, 2);
|
||||
v = LittleShort(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReader &operator>> (int16_t &v)
|
||||
{
|
||||
Read (&v, 2);
|
||||
v = LittleShort(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReader &operator>> (uint32_t &v)
|
||||
{
|
||||
Read (&v, 4);
|
||||
v = LittleLong(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
FileReader (const FileReader &other, long length);
|
||||
|
||||
char *GetsFromBuffer(const char * bufptr, char *strbuf, int len);
|
||||
|
||||
FILE *File;
|
||||
long Length;
|
||||
long StartPos;
|
||||
long FilePos;
|
||||
|
||||
private:
|
||||
long CalcFileLen () const;
|
||||
protected:
|
||||
bool CloseOnDestruct;
|
||||
};
|
||||
|
||||
// This will need a cleaner implementation once the outer interface is done.
|
||||
// As a first step this only needs to work properly in the non-error case.
|
||||
class FileReaderRedirect : public FileReader
|
||||
class MemoryReader : public FileReaderInterface
|
||||
{
|
||||
FileReader *mReader;
|
||||
protected:
|
||||
const char * bufptr = nullptr;
|
||||
long FilePos = 0;
|
||||
|
||||
MemoryReader()
|
||||
{}
|
||||
|
||||
public:
|
||||
FileReaderRedirect(FileReader *parent, long start, long length)
|
||||
MemoryReader(const char *buffer, long length)
|
||||
{
|
||||
mReader = parent;
|
||||
StartPos = start;
|
||||
bufptr = buffer;
|
||||
Length = length;
|
||||
FilePos = 0;
|
||||
}
|
||||
|
||||
virtual long Tell() const
|
||||
{
|
||||
auto l = mReader->Tell() - StartPos;
|
||||
if (l < StartPos || l >= StartPos + Length) return -1; // out of scope
|
||||
return l - StartPos;
|
||||
}
|
||||
|
||||
virtual long Seek(long offset, int origin)
|
||||
{
|
||||
switch (origin)
|
||||
{
|
||||
case SEEK_SET:
|
||||
offset += StartPos;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
offset += StartPos + Length;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
offset += mReader->Tell();
|
||||
break;
|
||||
}
|
||||
if (offset < StartPos || offset >= StartPos + Length) return -1; // out of scope
|
||||
return mReader->Seek(offset, SEEK_SET);
|
||||
}
|
||||
|
||||
virtual long Read(void *buffer, long len)
|
||||
{
|
||||
// This still needs better range checks
|
||||
return mReader->Read(buffer, len);
|
||||
}
|
||||
virtual char *Gets(char *strbuf, int len)
|
||||
{
|
||||
return mReader->Gets(strbuf, len);
|
||||
}
|
||||
|
||||
long GetLength() const { return Length; }
|
||||
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; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Wraps around a FileReader to decompress a zlib stream
|
||||
class FileReaderZ : public FileReaderBase
|
||||
class FileRdr // this is just a temporary name, until the old FileReader hierarchy can be made private.
|
||||
{
|
||||
public:
|
||||
FileReaderZ (FileReader &file, bool zip=false);
|
||||
~FileReaderZ ();
|
||||
FileReaderInterface *mReader = nullptr;
|
||||
|
||||
virtual long Read (void *buffer, long len);
|
||||
|
||||
FileReaderZ &operator>> (uint8_t &v)
|
||||
{
|
||||
Read (&v, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderZ &operator>> (int8_t &v)
|
||||
{
|
||||
Read (&v, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderZ &operator>> (uint16_t &v)
|
||||
{
|
||||
Read (&v, 2);
|
||||
v = LittleShort(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderZ &operator>> (int16_t &v)
|
||||
{
|
||||
Read (&v, 2);
|
||||
v = LittleShort(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderZ &operator>> (uint32_t &v)
|
||||
{
|
||||
Read (&v, 4);
|
||||
v = LittleLong(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderZ &operator>> (int &v)
|
||||
{
|
||||
Read (&v, 4);
|
||||
v = LittleLong(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
enum { BUFF_SIZE = 4096 };
|
||||
|
||||
FileReader &File;
|
||||
bool SawEOF;
|
||||
z_stream Stream;
|
||||
uint8_t InBuff[BUFF_SIZE];
|
||||
|
||||
void FillBuffer ();
|
||||
|
||||
FileReaderZ &operator= (const FileReaderZ &) { return *this; }
|
||||
};
|
||||
|
||||
// Wraps around a FileReader to decompress a bzip2 stream
|
||||
class FileReaderBZ2 : public FileReaderBase
|
||||
{
|
||||
public:
|
||||
FileReaderBZ2 (FileReader &file);
|
||||
~FileReaderBZ2 ();
|
||||
|
||||
long Read (void *buffer, long len);
|
||||
|
||||
FileReaderBZ2 &operator>> (uint8_t &v)
|
||||
{
|
||||
Read (&v, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderBZ2 &operator>> (int8_t &v)
|
||||
{
|
||||
Read (&v, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderBZ2 &operator>> (uint16_t &v)
|
||||
{
|
||||
Read (&v, 2);
|
||||
v = LittleShort(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderBZ2 &operator>> (int16_t &v)
|
||||
{
|
||||
Read (&v, 2);
|
||||
v = LittleShort(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderBZ2 &operator>> (uint32_t &v)
|
||||
{
|
||||
Read (&v, 4);
|
||||
v = LittleLong(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderBZ2 &operator>> (int &v)
|
||||
{
|
||||
Read (&v, 4);
|
||||
v = LittleLong(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
enum { BUFF_SIZE = 4096 };
|
||||
|
||||
FileReader &File;
|
||||
bool SawEOF;
|
||||
bz_stream Stream;
|
||||
uint8_t InBuff[BUFF_SIZE];
|
||||
|
||||
void FillBuffer ();
|
||||
|
||||
FileReaderBZ2 &operator= (const FileReaderBZ2 &) { return *this; }
|
||||
};
|
||||
|
||||
// Wraps around a FileReader to decompress a lzma stream
|
||||
class FileReaderLZMA : public FileReaderBase
|
||||
{
|
||||
struct StreamPointer;
|
||||
FileRdr(const FileRdr &r) = delete;
|
||||
FileRdr &operator=(const FileRdr &r) = delete;
|
||||
|
||||
public:
|
||||
FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip);
|
||||
~FileReaderLZMA ();
|
||||
|
||||
long Read (void *buffer, long len);
|
||||
|
||||
FileReaderLZMA &operator>> (uint8_t &v)
|
||||
enum ESeek
|
||||
{
|
||||
Read (&v, 1);
|
||||
SeekSet = SEEK_SET,
|
||||
SeekCur = SEEK_CUR,
|
||||
SeekEnd = SEEK_END
|
||||
};
|
||||
|
||||
typedef ptrdiff_t Size; // let's not use 'long' here.
|
||||
|
||||
FileRdr() {}
|
||||
|
||||
// These two functions are only needed as long as the FileReader has not been fully replaced throughout the code.
|
||||
explicit FileRdr(FileReaderInterface *r)
|
||||
{
|
||||
mReader = r;
|
||||
}
|
||||
|
||||
FileRdr(FileRdr &&r)
|
||||
{
|
||||
mReader = r.mReader;
|
||||
r.mReader = nullptr;
|
||||
}
|
||||
|
||||
FileRdr& operator =(FileRdr &&r)
|
||||
{
|
||||
Close();
|
||||
mReader = r.mReader;
|
||||
r.mReader = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderLZMA &operator>> (int8_t &v)
|
||||
|
||||
~FileRdr()
|
||||
{
|
||||
Read (&v, 1);
|
||||
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(FileRdr &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(FileRdr &parent, Size length, int method, bool seekable); // 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)
|
||||
{
|
||||
return mReader->Read(buffer, (long)len);
|
||||
}
|
||||
|
||||
char *Gets(char *strbuf, Size len)
|
||||
{
|
||||
return mReader->Gets(strbuf, (int)len);
|
||||
}
|
||||
|
||||
const char *GetBuffer()
|
||||
{
|
||||
return mReader->GetBuffer();
|
||||
}
|
||||
|
||||
Size GetLength() const
|
||||
{
|
||||
return mReader->GetLength();
|
||||
}
|
||||
|
||||
// Note: These need to go because they are fundamentally unsafe to use on a binary stream.
|
||||
FileRdr &operator>> (uint8_t &v)
|
||||
{
|
||||
mReader->Read(&v, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderLZMA &operator>> (uint16_t &v)
|
||||
FileRdr &operator>> (int8_t &v)
|
||||
{
|
||||
Read (&v, 2);
|
||||
mReader->Read(&v, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileRdr &operator>> (uint16_t &v)
|
||||
{
|
||||
mReader->Read(&v, 2);
|
||||
v = LittleShort(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderLZMA &operator>> (int16_t &v)
|
||||
FileRdr &operator>> (int16_t &v)
|
||||
{
|
||||
Read (&v, 2);
|
||||
mReader->Read(&v, 2);
|
||||
v = LittleShort(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderLZMA &operator>> (uint32_t &v)
|
||||
FileRdr &operator>> (uint32_t &v)
|
||||
{
|
||||
Read (&v, 4);
|
||||
mReader->Read(&v, 4);
|
||||
v = LittleLong(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileReaderLZMA &operator>> (int &v)
|
||||
FileRdr &operator>> (int32_t &v)
|
||||
{
|
||||
Read (&v, 4);
|
||||
mReader->Read(&v, 4);
|
||||
v = LittleLong(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
enum { BUFF_SIZE = 4096 };
|
||||
|
||||
FileReader &File;
|
||||
bool SawEOF;
|
||||
StreamPointer *Streamp; // anonymous pointer to LKZA decoder struct - to avoid including the LZMA headers globally
|
||||
size_t Size;
|
||||
size_t InPos, InSize;
|
||||
size_t OutProcessed;
|
||||
uint8_t InBuff[BUFF_SIZE];
|
||||
|
||||
void FillBuffer ();
|
||||
|
||||
FileReaderLZMA &operator= (const FileReaderLZMA &) { return *this; }
|
||||
friend class FWadCollection;
|
||||
};
|
||||
|
||||
class MemoryReader : public FileReader
|
||||
{
|
||||
public:
|
||||
MemoryReader (const char *buffer, long length);
|
||||
~MemoryReader ();
|
||||
|
||||
virtual long Tell () const;
|
||||
virtual long Seek (long offset, int origin);
|
||||
virtual long Read (void *buffer, long len);
|
||||
virtual char *Gets(char *strbuf, int len);
|
||||
virtual const char *GetBuffer() const { return bufptr; }
|
||||
|
||||
protected:
|
||||
const char * bufptr;
|
||||
};
|
||||
|
||||
class MemoryArrayReader : public FileReader
|
||||
{
|
||||
public:
|
||||
MemoryArrayReader (const char *buffer, long length);
|
||||
~MemoryArrayReader ();
|
||||
|
||||
virtual long Tell () const;
|
||||
virtual long Seek (long offset, int origin);
|
||||
virtual long Read (void *buffer, long len);
|
||||
virtual char *Gets(char *strbuf, int len);
|
||||
virtual const char *GetBuffer() const { return (char*)&buf[0]; }
|
||||
TArray<uint8_t> &GetArray() { return buf; }
|
||||
|
||||
void UpdateLength() { Length = buf.Size(); }
|
||||
|
||||
protected:
|
||||
TArray<uint8_t> buf;
|
||||
};
|
||||
|
||||
|
||||
class FileWriter
|
||||
|
@ -491,138 +277,4 @@ public:
|
|||
TArray<unsigned char> *GetBuffer() { return &mBuffer; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class FileRdr // this is just a temporary name, until the old FileReader hierarchy can be made private.
|
||||
{
|
||||
FileReader *mReader = nullptr;
|
||||
|
||||
FileRdr(const FileRdr &r) = delete;
|
||||
FileRdr &operator=(const FileRdr &r) = delete;
|
||||
public:
|
||||
enum ESeek
|
||||
{
|
||||
SeekSet = SEEK_SET,
|
||||
SeekCur = SEEK_CUR,
|
||||
SeekEnd = SEEK_END
|
||||
};
|
||||
|
||||
typedef ptrdiff_t Size; // let's not use 'long' here.
|
||||
|
||||
FileRdr() {}
|
||||
|
||||
// These two functions are only needed as long as the FileReader has not been fully replaced throughout the code.
|
||||
explicit FileRdr(FileReader *r)
|
||||
{
|
||||
mReader = r;
|
||||
}
|
||||
FileReader *Reader()
|
||||
{
|
||||
auto r = mReader;
|
||||
mReader = nullptr;
|
||||
return r;
|
||||
}
|
||||
|
||||
FileRdr(FileRdr &&r)
|
||||
{
|
||||
mReader = r.mReader;
|
||||
r.mReader = nullptr;
|
||||
}
|
||||
|
||||
FileRdr& operator =(FileRdr &&r)
|
||||
{
|
||||
Close();
|
||||
mReader = r.mReader;
|
||||
r.mReader = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
~FileRdr()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
bool isOpen() const
|
||||
{
|
||||
return mReader != nullptr;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
if (mReader != nullptr) delete mReader;
|
||||
mReader = nullptr;
|
||||
}
|
||||
|
||||
bool OpenFile(const char *filename);
|
||||
bool OpenFilePart(FileReader *parent, Size start, Size length); // later
|
||||
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
|
||||
|
||||
Size Tell() const
|
||||
{
|
||||
return mReader->Tell();
|
||||
}
|
||||
|
||||
Size Seek(Size offset, ESeek origin)
|
||||
{
|
||||
return mReader->Seek((long)offset, origin);
|
||||
}
|
||||
|
||||
Size Read(void *buffer, Size len)
|
||||
{
|
||||
return mReader->Read(buffer, (long)len);
|
||||
}
|
||||
|
||||
char *Gets(char *strbuf, Size len)
|
||||
{
|
||||
return mReader->Gets(strbuf, (int)len);
|
||||
}
|
||||
|
||||
Size GetLength() const
|
||||
{
|
||||
return mReader->GetLength();
|
||||
}
|
||||
|
||||
FileRdr &operator>> (uint8_t &v)
|
||||
{
|
||||
mReader->Read(&v, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileRdr &operator>> (int8_t &v)
|
||||
{
|
||||
mReader->Read(&v, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileRdr &operator>> (uint16_t &v)
|
||||
{
|
||||
mReader->Read(&v, 2);
|
||||
v = LittleShort(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileRdr &operator>> (int16_t &v)
|
||||
{
|
||||
mReader->Read(&v, 2);
|
||||
v = LittleShort(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileRdr &operator>> (uint32_t &v)
|
||||
{
|
||||
mReader->Read(&v, 4);
|
||||
v = LittleLong(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend class FWadCollection;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
607
src/files_decompress.cpp
Normal file
607
src/files_decompress.cpp
Normal file
|
@ -0,0 +1,607 @@
|
|||
/*
|
||||
** 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.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
// This also pulls in windows.h
|
||||
#include "LzmaDec.h"
|
||||
|
||||
#include "files.h"
|
||||
#include "i_system.h"
|
||||
#include "templates.h"
|
||||
#include "m_misc.h"
|
||||
|
||||
|
||||
class DecompressorBase : public FileReaderInterface
|
||||
{
|
||||
public:
|
||||
// These do not work but need to be defined to satisfy the FileReader interface
|
||||
long Tell () const override
|
||||
{
|
||||
I_Error("Cannot get position of decompressor stream");
|
||||
return 0;
|
||||
}
|
||||
virtual long Seek (long offset, int origin) override
|
||||
{
|
||||
I_Error("Cannot seek in decompressor stream");
|
||||
return 0;
|
||||
}
|
||||
virtual char *Gets(char *strbuf, int len) override
|
||||
{
|
||||
I_Error("Cannot use Gets on decompressor stream");
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DecompressorZ
|
||||
//
|
||||
// The zlib wrapper
|
||||
// reads data from a ZLib compressed stream
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class DecompressorZ : public DecompressorBase
|
||||
{
|
||||
enum { BUFF_SIZE = 4096 };
|
||||
|
||||
FileRdr &File;
|
||||
bool SawEOF;
|
||||
z_stream Stream;
|
||||
uint8_t InBuff[BUFF_SIZE];
|
||||
|
||||
public:
|
||||
DecompressorZ (FileRdr &file, bool zip)
|
||||
: File(file), SawEOF(false)
|
||||
{
|
||||
int err;
|
||||
|
||||
FillBuffer ();
|
||||
|
||||
Stream.zalloc = Z_NULL;
|
||||
Stream.zfree = Z_NULL;
|
||||
|
||||
if (!zip) err = inflateInit (&Stream);
|
||||
else err = inflateInit2 (&Stream, -MAX_WBITS);
|
||||
|
||||
if (err != Z_OK)
|
||||
{
|
||||
I_Error ("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)
|
||||
{
|
||||
I_Error ("Corrupt zlib stream");
|
||||
}
|
||||
|
||||
if (Stream.avail_out != 0)
|
||||
{
|
||||
I_Error ("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 : public DecompressorBase
|
||||
{
|
||||
enum { BUFF_SIZE = 4096 };
|
||||
|
||||
FileRdr &File;
|
||||
bool SawEOF;
|
||||
bz_stream Stream;
|
||||
uint8_t InBuff[BUFF_SIZE];
|
||||
|
||||
public:
|
||||
DecompressorBZ2 (FileRdr &file)
|
||||
: File(file), SawEOF(false)
|
||||
{
|
||||
int err;
|
||||
|
||||
FillBuffer ();
|
||||
|
||||
Stream.bzalloc = NULL;
|
||||
Stream.bzfree = NULL;
|
||||
Stream.opaque = NULL;
|
||||
|
||||
err = BZ2_bzDecompressInit(&Stream, 0, 0);
|
||||
|
||||
if (err != BZ_OK)
|
||||
{
|
||||
I_Error ("DecompressorBZ2: bzDecompressInit failed: %d\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
~DecompressorBZ2 ()
|
||||
{
|
||||
BZ2_bzDecompressEnd (&Stream);
|
||||
}
|
||||
|
||||
long Read (void *buffer, long len) override
|
||||
{
|
||||
int err;
|
||||
|
||||
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)
|
||||
{
|
||||
I_Error ("Corrupt bzip2 stream");
|
||||
}
|
||||
|
||||
if (Stream.avail_out != 0)
|
||||
{
|
||||
I_Error ("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)
|
||||
{
|
||||
I_FatalError("libbzip2: internal error number %d\n", errcode);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// 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 };
|
||||
|
||||
FileRdr &File;
|
||||
bool SawEOF;
|
||||
CLzmaDec Stream;
|
||||
size_t Size;
|
||||
size_t InPos, InSize;
|
||||
size_t OutProcessed;
|
||||
uint8_t InBuff[BUFF_SIZE];
|
||||
|
||||
public:
|
||||
|
||||
DecompressorLZMA (FileRdr &file, size_t uncompressed_size)
|
||||
: File(file), SawEOF(false)
|
||||
{
|
||||
uint8_t header[4 + LZMA_PROPS_SIZE];
|
||||
int err;
|
||||
|
||||
Size = uncompressed_size;
|
||||
OutProcessed = 0;
|
||||
|
||||
// Read zip LZMA properties header
|
||||
if (File.Read(header, sizeof(header)) < (long)sizeof(header))
|
||||
{
|
||||
I_Error("DecompressorLZMA: File too short\n");
|
||||
}
|
||||
if (header[2] + header[3] * 256 != LZMA_PROPS_SIZE)
|
||||
{
|
||||
I_Error("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)
|
||||
{
|
||||
I_Error("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)
|
||||
{
|
||||
I_Error ("Corrupt LZMA stream");
|
||||
}
|
||||
if (in_processed == 0 && out_processed == 0)
|
||||
{
|
||||
if (status != LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
I_Error ("Corrupt LZMA stream");
|
||||
}
|
||||
}
|
||||
if (InSize == 0 && !SawEOF)
|
||||
{
|
||||
FillBuffer ();
|
||||
}
|
||||
} while (err == SZ_OK && len != 0);
|
||||
|
||||
if (err != Z_OK && err != Z_STREAM_END)
|
||||
{
|
||||
I_Error ("Corrupt LZMA stream");
|
||||
}
|
||||
|
||||
if (len != 0)
|
||||
{
|
||||
I_Error ("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 };
|
||||
|
||||
FileRdr &File;
|
||||
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(FileRdr &file) : File(file), SawEOF(false)
|
||||
{
|
||||
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 FileRdr::OpenDecompressor(FileRdr &parent, Size length, int method, bool seekable)
|
||||
{
|
||||
DecompressorBase *dec = nullptr;
|
||||
switch (method)
|
||||
{
|
||||
case METHOD_DEFLATE:
|
||||
case METHOD_ZLIB:
|
||||
dec = new DecompressorZ(parent, method == METHOD_DEFLATE);
|
||||
break;
|
||||
|
||||
case METHOD_BZIP2:
|
||||
dec = new DecompressorBZ2(parent);
|
||||
break;
|
||||
|
||||
case METHOD_LZMA:
|
||||
dec = new DecompressorLZMA(parent, length);
|
||||
break;
|
||||
|
||||
case METHOD_LZSS:
|
||||
dec = new DecompressorLZSS(parent);
|
||||
break;
|
||||
|
||||
// todo: METHOD_IMPLODE, METHOD_SHRINK
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
dec->Length = (long)length;
|
||||
if (!seekable)
|
||||
{
|
||||
Close();
|
||||
mReader = dec;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// todo: create a wrapper. for now this fails
|
||||
delete dec;
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1930,7 +1930,7 @@ void G_DoLoadGame ()
|
|||
hidecon = gameaction == ga_loadgamehidecon;
|
||||
gameaction = ga_nothing;
|
||||
|
||||
std::unique_ptr<FResourceFile> resfile(FResourceFile::OpenResourceFile(savename.GetChars(), nullptr, true, true));
|
||||
std::unique_ptr<FResourceFile> resfile(FResourceFile::OpenResourceFile(savename.GetChars(), true, true));
|
||||
if (resfile == nullptr)
|
||||
{
|
||||
Printf ("Could not read savegame '%s'\n", savename.GetChars());
|
||||
|
@ -2372,7 +2372,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
|
|||
savegame_content[2].Clean();
|
||||
|
||||
// Check whether the file is ok by trying to open it.
|
||||
FResourceFile *test = FResourceFile::OpenResourceFile(filename, nullptr, true);
|
||||
FResourceFile *test = FResourceFile::OpenResourceFile(filename, true);
|
||||
if (test != nullptr)
|
||||
{
|
||||
delete test;
|
||||
|
|
|
@ -269,8 +269,8 @@ CCMD (md5sum)
|
|||
}
|
||||
for (int i = 1; i < argv.argc(); ++i)
|
||||
{
|
||||
FileReader fr;
|
||||
if (!fr.Open(argv[i]))
|
||||
FileRdr fr;
|
||||
if (!fr.OpenFile(argv[i]))
|
||||
{
|
||||
Printf("%s: %s\n", argv[i], strerror(errno));
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ void FSavegameManager::ReadSaveStrings()
|
|||
// I_FindName only returns the file's name and not its full path
|
||||
FString filepath = G_BuildSaveName(I_FindName(&c_file), -1);
|
||||
|
||||
FResourceFile *savegame = FResourceFile::OpenResourceFile(filepath, nullptr, true, true);
|
||||
FResourceFile *savegame = FResourceFile::OpenResourceFile(filepath, true, true);
|
||||
if (savegame != nullptr)
|
||||
{
|
||||
bool oldVer = false;
|
||||
|
@ -469,7 +469,7 @@ unsigned FSavegameManager::ExtractSaveData(int index)
|
|||
(node = SaveGames[index]) &&
|
||||
!node->Filename.IsEmpty() &&
|
||||
!node->bOldVersion &&
|
||||
(resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), nullptr, true)) != nullptr)
|
||||
(resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), true)) != nullptr)
|
||||
{
|
||||
FResourceLump *info = resf->FindLump("info.json");
|
||||
if (info == nullptr)
|
||||
|
|
|
@ -77,7 +77,7 @@ void P_ResumeConversation ();
|
|||
|
||||
void P_ConversationCommand (int netcode, int player, uint8_t **stream);
|
||||
|
||||
class FileReader;
|
||||
class FileRdr;
|
||||
bool P_ParseUSDF(int lumpnum, FileRdr &lump, int lumplen);
|
||||
|
||||
|
||||
|
|
|
@ -215,18 +215,18 @@ bool P_CheckForGLNodes()
|
|||
static int firstglvertex;
|
||||
static bool format5;
|
||||
|
||||
static bool LoadGLVertexes(FileReader * lump)
|
||||
static bool LoadGLVertexes(FileRdr &lump)
|
||||
{
|
||||
uint8_t *gldata;
|
||||
int i;
|
||||
|
||||
firstglvertex = level.vertexes.Size();
|
||||
|
||||
int gllen=lump->GetLength();
|
||||
auto gllen=lump.GetLength();
|
||||
|
||||
gldata = new uint8_t[gllen];
|
||||
lump->Seek(0, SEEK_SET);
|
||||
lump->Read(gldata, gllen);
|
||||
lump.Seek(0, FileRdr::SeekSet);
|
||||
lump.Read(gldata, gllen);
|
||||
|
||||
if (*(int *)gldata == gNd5)
|
||||
{
|
||||
|
@ -246,7 +246,7 @@ static bool LoadGLVertexes(FileReader * lump)
|
|||
else format5=false;
|
||||
|
||||
mapglvertex_t* mgl = (mapglvertex_t *)(gldata + GL_VERT_OFFSET);
|
||||
unsigned numvertexes = firstglvertex + (gllen - GL_VERT_OFFSET)/sizeof(mapglvertex_t);
|
||||
unsigned numvertexes = (unsigned)(firstglvertex + (gllen - GL_VERT_OFFSET)/sizeof(mapglvertex_t));
|
||||
|
||||
auto oldvertexes = &level.vertexes[0];
|
||||
level.vertexes.Resize(numvertexes);
|
||||
|
@ -293,16 +293,16 @@ static inline int checkGLVertex3(int num)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool LoadGLSegs(FileReader * lump)
|
||||
static bool LoadGLSegs(FileRdr &lump)
|
||||
{
|
||||
char *data;
|
||||
int i;
|
||||
line_t *ldef=NULL;
|
||||
|
||||
int numsegs = lump->GetLength();
|
||||
int numsegs = (int)lump.GetLength();
|
||||
data= new char[numsegs];
|
||||
lump->Seek(0, SEEK_SET);
|
||||
lump->Read(data, numsegs);
|
||||
lump.Seek(0, FileRdr::SeekSet);
|
||||
lump.Read(data, numsegs);
|
||||
auto &segs = level.segs;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -437,15 +437,15 @@ static bool LoadGLSegs(FileReader * lump)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool LoadGLSubsectors(FileReader * lump)
|
||||
static bool LoadGLSubsectors(FileRdr &lump)
|
||||
{
|
||||
char * datab;
|
||||
int i;
|
||||
|
||||
auto numsubsectors = lump->GetLength();
|
||||
int numsubsectors = (int)lump.GetLength();
|
||||
datab = new char[numsubsectors];
|
||||
lump->Seek(0, SEEK_SET);
|
||||
lump->Read(datab, numsubsectors);
|
||||
lump.Seek(0, FileRdr::SeekSet);
|
||||
lump.Read(datab, numsubsectors);
|
||||
|
||||
if (numsubsectors == 0)
|
||||
{
|
||||
|
@ -521,7 +521,7 @@ static bool LoadGLSubsectors(FileReader * lump)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool LoadNodes (FileReader * lump)
|
||||
static bool LoadNodes (FileRdr &lump)
|
||||
{
|
||||
const int NF_SUBSECTOR = 0x8000;
|
||||
const int GL5_NF_SUBSECTOR = (1 << 31);
|
||||
|
@ -534,15 +534,15 @@ static bool LoadNodes (FileReader * lump)
|
|||
if (!format5)
|
||||
{
|
||||
mapnode_t* mn, * basemn;
|
||||
unsigned numnodes = unsigned(lump->GetLength() / sizeof(mapnode_t));
|
||||
unsigned numnodes = unsigned(lump.GetLength() / sizeof(mapnode_t));
|
||||
|
||||
if (numnodes == 0) return false;
|
||||
|
||||
level.nodes.Alloc(numnodes);
|
||||
lump->Seek(0, SEEK_SET);
|
||||
lump.Seek(0, FileRdr::SeekSet);
|
||||
|
||||
basemn = mn = new mapnode_t[numnodes];
|
||||
lump->Read(mn, lump->GetLength());
|
||||
lump.Read(mn, lump.GetLength());
|
||||
|
||||
used = (uint16_t *)alloca (sizeof(uint16_t)*numnodes);
|
||||
memset (used, 0, sizeof(uint16_t)*numnodes);
|
||||
|
@ -594,15 +594,15 @@ static bool LoadNodes (FileReader * lump)
|
|||
else
|
||||
{
|
||||
gl5_mapnode_t* mn, * basemn;
|
||||
auto numnodes = unsigned(lump->GetLength() / sizeof(gl5_mapnode_t));
|
||||
auto numnodes = unsigned(lump.GetLength() / sizeof(gl5_mapnode_t));
|
||||
|
||||
if (numnodes == 0) return false;
|
||||
|
||||
level.nodes.Alloc(numnodes);
|
||||
lump->Seek(0, SEEK_SET);
|
||||
lump.Seek(0, FileRdr::SeekSet);
|
||||
|
||||
basemn = mn = new gl5_mapnode_t[numnodes];
|
||||
lump->Read(mn, lump->GetLength());
|
||||
lump.Read(mn, lump.GetLength());
|
||||
|
||||
used = (uint16_t *)alloca (sizeof(uint16_t)*numnodes);
|
||||
memset (used, 0, sizeof(uint16_t)*numnodes);
|
||||
|
@ -660,7 +660,7 @@ static bool LoadNodes (FileReader * lump)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool DoLoadGLNodes(FileReader ** lumps)
|
||||
static bool DoLoadGLNodes(FileRdr * lumps)
|
||||
{
|
||||
int missing = 0;
|
||||
|
||||
|
@ -803,7 +803,7 @@ static int FindGLNodesInFile(FResourceFile * f, const char * label)
|
|||
if (mustcheck)
|
||||
{
|
||||
char check[16]={0};
|
||||
FileReader *fr = f->GetLump(i)->GetReader();
|
||||
auto fr = f->GetLump(i)->GetReader();
|
||||
fr->Read(check, 16);
|
||||
if (MatchHeader(label, check)) return i;
|
||||
}
|
||||
|
@ -857,7 +857,7 @@ bool P_LoadGLNodes(MapData * map)
|
|||
|
||||
if (!CheckCachedNodes(map))
|
||||
{
|
||||
FileReader *gwalumps[4] = { NULL, NULL, NULL, NULL };
|
||||
FileRdr gwalumps[4];
|
||||
char path[256];
|
||||
int li;
|
||||
int lumpfile = Wads.GetLumpFile(map->lumpnum);
|
||||
|
@ -875,7 +875,7 @@ bool P_LoadGLNodes(MapData * map)
|
|||
// GL nodes are loaded with a WAD
|
||||
for(int i=0;i<4;i++)
|
||||
{
|
||||
gwalumps[i]=Wads.ReopenLumpNum(li+i+1);
|
||||
gwalumps[i]=Wads.ReopenLumpReader(li+i+1);
|
||||
}
|
||||
return DoLoadGLNodes(gwalumps);
|
||||
}
|
||||
|
@ -889,7 +889,7 @@ bool P_LoadGLNodes(MapData * map)
|
|||
strcpy(ext, ".gwa");
|
||||
// Todo: Compare file dates
|
||||
|
||||
f_gwa = FResourceFile::OpenResourceFile(path, NULL, true);
|
||||
f_gwa = FResourceFile::OpenResourceFile(path, true);
|
||||
if (f_gwa==NULL) return false;
|
||||
|
||||
strncpy(map->MapLumps[0].Name, Wads.GetLumpFullName(map->lumpnum), 8);
|
||||
|
@ -918,8 +918,6 @@ bool P_LoadGLNodes(MapData * map)
|
|||
|
||||
if (f_gwa != map->resource)
|
||||
delete f_gwa;
|
||||
for(unsigned int i = 0;i < 4;++i)
|
||||
delete gwalumps[i];
|
||||
return result;
|
||||
}
|
||||
else return true;
|
||||
|
|
|
@ -240,7 +240,7 @@ static int GetMapIndex(const char *mapname, int lastindex, const char *lumpname,
|
|||
MapData *P_OpenMapData(const char * mapname, bool justcheck)
|
||||
{
|
||||
MapData * map = new MapData;
|
||||
FileReader * wadReader = NULL;
|
||||
FileRdr * wadReader = nullptr;
|
||||
bool externalfile = !strnicmp(mapname, "file:", 5);
|
||||
|
||||
if (externalfile)
|
||||
|
@ -251,7 +251,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck)
|
|||
delete map;
|
||||
return NULL;
|
||||
}
|
||||
map->resource = FResourceFile::OpenResourceFile(mapname, NULL, true);
|
||||
map->resource = FResourceFile::OpenResourceFile(mapname, true);
|
||||
wadReader = map->resource->GetReader();
|
||||
}
|
||||
else
|
||||
|
@ -396,7 +396,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck)
|
|||
return NULL;
|
||||
}
|
||||
map->lumpnum = lump_wad;
|
||||
map->resource = FResourceFile::OpenResourceFile(Wads.GetLumpFullName(lump_wad), Wads.ReopenLumpNum(lump_wad), true);
|
||||
map->resource = FResourceFile::OpenResourceFile(Wads.GetLumpFullName(lump_wad), Wads.ReopenLumpReader(lump_wad), true);
|
||||
wadReader = map->resource->GetReader();
|
||||
}
|
||||
}
|
||||
|
@ -404,7 +404,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck)
|
|||
|
||||
// Although we're using the resource system, we still want to be sure we're
|
||||
// reading from a wad file.
|
||||
wadReader->Seek(0, SEEK_SET);
|
||||
wadReader->Seek(0, FileRdr::SeekSet);
|
||||
wadReader->Read(&id, sizeof(id));
|
||||
|
||||
if (id == IWAD_ID || id == PWAD_ID)
|
||||
|
@ -412,7 +412,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck)
|
|||
char maplabel[9]="";
|
||||
int index=0;
|
||||
|
||||
map->MapLumps[0].Reader = FileRdr(map->resource->GetLump(0)->NewReader());
|
||||
map->MapLumps[0].Reader = map->resource->GetLump(0)->NewReader();
|
||||
strncpy(map->MapLumps[0].Name, map->resource->GetLump(0)->Name, 8);
|
||||
|
||||
for(uint32_t i = 1; i < map->resource->LumpCount(); i++)
|
||||
|
@ -422,7 +422,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck)
|
|||
if (i == 1 && !strnicmp(lumpname, "TEXTMAP", 8))
|
||||
{
|
||||
map->isText = true;
|
||||
map->MapLumps[ML_TEXTMAP].Reader = FileRdr(map->resource->GetLump(i)->NewReader());
|
||||
map->MapLumps[ML_TEXTMAP].Reader = map->resource->GetLump(i)->NewReader();
|
||||
strncpy(map->MapLumps[ML_TEXTMAP].Name, lumpname, 8);
|
||||
for(int i = 2;; i++)
|
||||
{
|
||||
|
@ -454,7 +454,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck)
|
|||
return map;
|
||||
}
|
||||
else continue;
|
||||
map->MapLumps[index].Reader = FileRdr(map->resource->GetLump(i)->NewReader());
|
||||
map->MapLumps[index].Reader = map->resource->GetLump(i)->NewReader();
|
||||
strncpy(map->MapLumps[index].Name, lumpname, 8);
|
||||
}
|
||||
}
|
||||
|
@ -486,7 +486,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck)
|
|||
maplabel[8]=0;
|
||||
}
|
||||
|
||||
map->MapLumps[index].Reader = FileRdr(map->resource->GetLump(i)->NewReader());
|
||||
map->MapLumps[index].Reader = map->resource->GetLump(i)->NewReader();
|
||||
strncpy(map->MapLumps[index].Name, lumpname, 8);
|
||||
}
|
||||
}
|
||||
|
@ -855,7 +855,7 @@ void P_LoadVertexes (MapData * map)
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
void P_LoadZSegs (FileReaderBase &data)
|
||||
void P_LoadZSegs (FileRdr &data)
|
||||
{
|
||||
for (auto &seg : level.segs)
|
||||
{
|
||||
|
@ -891,7 +891,7 @@ void P_LoadZSegs (FileReaderBase &data)
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
void P_LoadGLZSegs (FileReaderBase &data, int type)
|
||||
void P_LoadGLZSegs (FileRdr &data, int type)
|
||||
{
|
||||
for (unsigned i = 0; i < level.subsectors.Size(); ++i)
|
||||
{
|
||||
|
@ -961,7 +961,7 @@ void P_LoadGLZSegs (FileReaderBase &data, int type)
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
void LoadZNodes(FileReaderBase &data, int glnodes)
|
||||
void LoadZNodes(FileRdr &data, int glnodes)
|
||||
{
|
||||
// Read extra vertices added during node building
|
||||
uint32_t orgVerts, newVerts;
|
||||
|
@ -980,7 +980,7 @@ void LoadZNodes(FileReaderBase &data, int glnodes)
|
|||
}
|
||||
for (i = 0; i < newVerts; ++i)
|
||||
{
|
||||
fixed_t x, y;
|
||||
int32_t x, y;
|
||||
data >> x >> y;
|
||||
level.vertexes[i + orgVerts].set(x, y);
|
||||
}
|
||||
|
@ -1145,15 +1145,17 @@ void P_LoadZNodes (FileRdr &dalump, uint32_t id)
|
|||
return;
|
||||
}
|
||||
|
||||
auto daptr = dalump.Reader();
|
||||
if (compressed)
|
||||
{
|
||||
FileReaderZ data (*daptr);
|
||||
LoadZNodes(data, type);
|
||||
FileRdr zip;
|
||||
if (zip.OpenDecompressor(dalump, -1, METHOD_ZLIB, false))
|
||||
{
|
||||
LoadZNodes(zip, type);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadZNodes(*daptr, type);
|
||||
LoadZNodes(dalump, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
if (bs < be) \
|
||||
c = ReadBuf[bs++]; \
|
||||
else { \
|
||||
be = In->Read(&ReadBuf, sizeof(ReadBuf)); \
|
||||
be = (decltype(be))In->Read(&ReadBuf, sizeof(ReadBuf)); \
|
||||
c = ReadBuf[0]; \
|
||||
bs = 1; \
|
||||
} \
|
||||
|
@ -259,7 +259,7 @@ int FZipExploder::DecodeSF(TArray<HuffNode> &decoder, int numvals)
|
|||
}
|
||||
|
||||
int FZipExploder::Explode(unsigned char *out, unsigned int outsize,
|
||||
FileReader *in, unsigned int insize,
|
||||
FileRdr &in, unsigned int insize,
|
||||
int flags)
|
||||
{
|
||||
int c, i, minMatchLen = 3, len, dist;
|
||||
|
@ -268,7 +268,7 @@ int FZipExploder::Explode(unsigned char *out, unsigned int outsize,
|
|||
|
||||
Hold = 0;
|
||||
Bits = 0;
|
||||
In = in;
|
||||
In = ∈
|
||||
InLeft = insize;
|
||||
bs = be = 0;
|
||||
|
||||
|
@ -337,9 +337,9 @@ int FZipExploder::Explode(unsigned char *out, unsigned int outsize,
|
|||
#define FREE_CODE HSIZE /* 0x2000 (code is unused or was cleared) */
|
||||
#define HAS_CHILD (HSIZE << 1) /* 0x4000 (code has a child--do not clear) */
|
||||
|
||||
int ShrinkLoop(unsigned char *out, unsigned int outsize,
|
||||
FileReader *In, unsigned int InLeft)
|
||||
int ShrinkLoop(unsigned char *out, unsigned int outsize, FileRdr &_In, unsigned int InLeft)
|
||||
{
|
||||
FileRdr *In = &_In;
|
||||
unsigned char ReadBuf[256];
|
||||
unsigned short Parent[HSIZE];
|
||||
unsigned char Value[HSIZE], Stack[HSIZE];
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
class FZipExploder
|
||||
{
|
||||
unsigned int Hold, Bits;
|
||||
FileReader *In;
|
||||
FileRdr *In;
|
||||
unsigned int InLeft;
|
||||
|
||||
/****************************************************************
|
||||
|
@ -38,7 +38,7 @@ class FZipExploder
|
|||
int DecodeSFValue(const TArray<HuffNode> ¤tTree);
|
||||
int DecodeSF(TArray<HuffNode> &decoder, int numvals);
|
||||
public:
|
||||
int Explode(unsigned char *out, unsigned int outsize, FileReader *in, unsigned int insize, int flags);
|
||||
int Explode(unsigned char *out, unsigned int outsize, FileRdr &in, unsigned int insize, int flags);
|
||||
};
|
||||
|
||||
class CExplosionError : CRecoverableError
|
||||
|
@ -47,4 +47,4 @@ public:
|
|||
CExplosionError(const char *message) : CRecoverableError(message) {}
|
||||
};
|
||||
|
||||
int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader *in, unsigned int insize);
|
||||
int ShrinkLoop(unsigned char *out, unsigned int outsize, FileRdr &in, unsigned int insize);
|
|
@ -58,19 +58,19 @@ extern ISzAlloc g_Alloc;
|
|||
struct CZDFileInStream
|
||||
{
|
||||
ISeekInStream s;
|
||||
FileReader *File;
|
||||
FileRdr &File;
|
||||
|
||||
CZDFileInStream(FileReader *_file)
|
||||
CZDFileInStream(FileRdr &_file)
|
||||
: File(_file)
|
||||
{
|
||||
s.Read = Read;
|
||||
s.Seek = Seek;
|
||||
File = _file;
|
||||
}
|
||||
|
||||
static SRes Read(const ISeekInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CZDFileInStream *p = (CZDFileInStream *)pp;
|
||||
long numread = p->File->Read(buf, (long)*size);
|
||||
auto numread = p->File.Read(buf, (long)*size);
|
||||
if (numread < 0)
|
||||
{
|
||||
*size = 0;
|
||||
|
@ -83,26 +83,26 @@ struct CZDFileInStream
|
|||
static SRes Seek(const ISeekInStream *pp, Int64 *pos, ESzSeek origin)
|
||||
{
|
||||
CZDFileInStream *p = (CZDFileInStream *)pp;
|
||||
int move_method;
|
||||
FileRdr::ESeek move_method;
|
||||
int res;
|
||||
if (origin == SZ_SEEK_SET)
|
||||
{
|
||||
move_method = SEEK_SET;
|
||||
move_method = FileRdr::SeekSet;
|
||||
}
|
||||
else if (origin == SZ_SEEK_CUR)
|
||||
{
|
||||
move_method = SEEK_CUR;
|
||||
move_method = FileRdr::SeekCur;
|
||||
}
|
||||
else if (origin == SZ_SEEK_END)
|
||||
{
|
||||
move_method = SEEK_END;
|
||||
move_method = FileRdr::SeekEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
res = p->File->Seek((long)*pos, move_method);
|
||||
*pos = p->File->Tell();
|
||||
res = (int)p->File.Seek((long)*pos, move_method);
|
||||
*pos = p->File.Tell();
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
@ -117,13 +117,13 @@ struct C7zArchive
|
|||
Byte *OutBuffer;
|
||||
size_t OutBufferSize;
|
||||
|
||||
C7zArchive(FileReader *file) : ArchiveStream(file)
|
||||
C7zArchive(FileRdr &file) : ArchiveStream(file)
|
||||
{
|
||||
if (g_CrcTable[1] == 0)
|
||||
{
|
||||
CrcGenerateTable();
|
||||
}
|
||||
file->Seek(0, SEEK_SET);
|
||||
file.Seek(0, FileRdr::SeekSet);
|
||||
LookToRead2_CreateVTable(&LookStream, false);
|
||||
LookStream.realStream = &ArchiveStream.s;
|
||||
LookToRead2_Init(&LookStream);
|
||||
|
@ -192,7 +192,7 @@ class F7ZFile : public FResourceFile
|
|||
C7zArchive *Archive;
|
||||
|
||||
public:
|
||||
F7ZFile(const char * filename, FileReader *filer);
|
||||
F7ZFile(const char * filename, FileRdr &filer);
|
||||
bool Open(bool quiet);
|
||||
virtual ~F7ZFile();
|
||||
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
|
||||
|
@ -206,7 +206,7 @@ public:
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
F7ZFile::F7ZFile(const char * filename, FileReader *filer)
|
||||
F7ZFile::F7ZFile(const char * filename, FileRdr &filer)
|
||||
: FResourceFile(filename, filer)
|
||||
{
|
||||
Lumps = NULL;
|
||||
|
@ -295,7 +295,7 @@ bool F7ZFile::Open(bool quiet)
|
|||
lump_p->LumpNameSetup(name);
|
||||
lump_p->LumpSize = static_cast<int>(SzArEx_GetFileSize(archPtr, i));
|
||||
lump_p->Owner = this;
|
||||
lump_p->Flags = LUMPF_ZIPFILE;
|
||||
lump_p->Flags = LUMPF_ZIPFILE|LUMPF_COMPRESSED;
|
||||
lump_p->Position = i;
|
||||
lump_p->CheckEmbedded();
|
||||
lump_p++;
|
||||
|
@ -361,21 +361,21 @@ int F7ZLump::FillCache()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *Check7Z(const char *filename, FileReader *file, bool quiet)
|
||||
FResourceFile *Check7Z(const char *filename, FileRdr &file, bool quiet)
|
||||
{
|
||||
char head[k7zSignatureSize];
|
||||
|
||||
if (file->GetLength() >= k7zSignatureSize)
|
||||
if (file.GetLength() >= k7zSignatureSize)
|
||||
{
|
||||
file->Seek(0, SEEK_SET);
|
||||
file->Read(&head, k7zSignatureSize);
|
||||
file->Seek(0, SEEK_SET);
|
||||
file.Seek(0, FileRdr::SeekSet);
|
||||
file.Read(&head, k7zSignatureSize);
|
||||
file.Seek(0, FileRdr::SeekSet);
|
||||
if (!memcmp(head, k7zSignature, k7zSignatureSize))
|
||||
{
|
||||
FResourceFile *rf = new F7ZFile(filename, file);
|
||||
if (rf->Open(quiet)) return rf;
|
||||
|
||||
rf->Reader = NULL; // to avoid destruction of reader
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
delete rf;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
|
||||
struct FDirectoryLump : public FResourceLump
|
||||
{
|
||||
virtual FileReader *NewReader();
|
||||
virtual FileRdr NewReader();
|
||||
virtual int FillCache();
|
||||
|
||||
FString mFullPath;
|
||||
|
@ -90,7 +90,7 @@ public:
|
|||
//==========================================================================
|
||||
|
||||
FDirectory::FDirectory(const char * directory)
|
||||
: FResourceFile(NULL, NULL)
|
||||
: FResourceFile(NULL, FileRdr())
|
||||
{
|
||||
FString dirname;
|
||||
|
||||
|
@ -287,16 +287,11 @@ void FDirectory::AddEntry(const char *fullpath, int size)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FileReader *FDirectoryLump::NewReader()
|
||||
FileRdr FDirectoryLump::NewReader()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new FileReader(mFullPath);
|
||||
}
|
||||
catch (CRecoverableError &)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
FileRdr fr;
|
||||
fr.OpenFile(mFullPath);
|
||||
return fr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -307,15 +302,14 @@ FileReader *FDirectoryLump::NewReader()
|
|||
|
||||
int FDirectoryLump::FillCache()
|
||||
{
|
||||
FileRdr fr;
|
||||
Cache = new char[LumpSize];
|
||||
FileReader *reader = NewReader();
|
||||
if (reader == NULL)
|
||||
if (!fr.OpenFile(mFullPath))
|
||||
{
|
||||
memset(Cache, 0, LumpSize);
|
||||
return 0;
|
||||
}
|
||||
reader->Read(Cache, LumpSize);
|
||||
delete reader;
|
||||
fr.Read(Cache, LumpSize);
|
||||
RefCount = 1;
|
||||
return 1;
|
||||
}
|
||||
|
@ -326,7 +320,7 @@ int FDirectoryLump::FillCache()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckDir(const char *filename, FileReader *file, bool quiet)
|
||||
FResourceFile *CheckDir(const char *filename, bool quiet)
|
||||
{
|
||||
FResourceFile *rf = new FDirectory(filename);
|
||||
if (rf->Open(quiet)) return rf;
|
||||
|
|
|
@ -73,7 +73,7 @@ struct GrpLump
|
|||
class FGrpFile : public FUncompressedFile
|
||||
{
|
||||
public:
|
||||
FGrpFile(const char * filename, FileReader *file);
|
||||
FGrpFile(const char * filename, FileRdr &file);
|
||||
bool Open(bool quiet);
|
||||
};
|
||||
|
||||
|
@ -84,7 +84,7 @@ public:
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FGrpFile::FGrpFile(const char *filename, FileReader *file)
|
||||
FGrpFile::FGrpFile(const char *filename, FileRdr &file)
|
||||
: FUncompressedFile(filename, file)
|
||||
{
|
||||
Lumps = NULL;
|
||||
|
@ -100,11 +100,11 @@ bool FGrpFile::Open(bool quiet)
|
|||
{
|
||||
GrpInfo header;
|
||||
|
||||
Reader->Read(&header, sizeof(header));
|
||||
Reader.Read(&header, sizeof(header));
|
||||
NumLumps = LittleLong(header.NumLumps);
|
||||
|
||||
GrpLump *fileinfo = new GrpLump[NumLumps];
|
||||
Reader->Read (fileinfo, NumLumps * sizeof(GrpLump));
|
||||
Reader.Read (fileinfo, NumLumps * sizeof(GrpLump));
|
||||
|
||||
Lumps = new FUncompressedLump[NumLumps];
|
||||
|
||||
|
@ -134,21 +134,21 @@ bool FGrpFile::Open(bool quiet)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckGRP(const char *filename, FileReader *file, bool quiet)
|
||||
FResourceFile *CheckGRP(const char *filename, FileRdr &file, bool quiet)
|
||||
{
|
||||
char head[12];
|
||||
|
||||
if (file->GetLength() >= 12)
|
||||
if (file.GetLength() >= 12)
|
||||
{
|
||||
file->Seek(0, SEEK_SET);
|
||||
file->Read(&head, 12);
|
||||
file->Seek(0, SEEK_SET);
|
||||
file.Seek(0, FileRdr::SeekSet);
|
||||
file.Read(&head, 12);
|
||||
file.Seek(0, FileRdr::SeekSet);
|
||||
if (!memcmp(head, "KenSilverman", 12))
|
||||
{
|
||||
FResourceFile *rf = new FGrpFile(filename, file);
|
||||
if (rf->Open(quiet)) return rf;
|
||||
|
||||
rf->Reader = NULL; // to avoid destruction of reader
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
delete rf;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
class FLumpFile : public FUncompressedFile
|
||||
{
|
||||
public:
|
||||
FLumpFile(const char * filename, FileReader *file);
|
||||
FLumpFile(const char * filename, FileRdr &file);
|
||||
bool Open(bool quiet);
|
||||
};
|
||||
|
||||
|
@ -57,7 +57,8 @@ public:
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FLumpFile::FLumpFile(const char *filename, FileReader *file) : FUncompressedFile(filename, file)
|
||||
FLumpFile::FLumpFile(const char *filename, FileRdr &file)
|
||||
: FUncompressedFile(filename, file)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -76,7 +77,7 @@ bool FLumpFile::Open(bool quiet)
|
|||
Lumps->Name[8] = 0;
|
||||
Lumps->Owner = this;
|
||||
Lumps->Position = 0;
|
||||
Lumps->LumpSize = Reader->GetLength();
|
||||
Lumps->LumpSize = (int)Reader.GetLength();
|
||||
Lumps->Namespace = ns_global;
|
||||
Lumps->Flags = 0;
|
||||
Lumps->FullName = NULL;
|
||||
|
@ -94,11 +95,12 @@ bool FLumpFile::Open(bool quiet)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckLump(const char *filename, FileReader *file, bool quiet)
|
||||
FResourceFile *CheckLump(const char *filename, FileRdr &file, bool quiet)
|
||||
{
|
||||
// always succeeds
|
||||
FResourceFile *rf = new FLumpFile(filename, file);
|
||||
if (rf->Open(quiet)) return rf;
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
delete rf;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ struct dpackheader_t
|
|||
class FPakFile : public FUncompressedFile
|
||||
{
|
||||
public:
|
||||
FPakFile(const char * filename, FileReader *file);
|
||||
FPakFile(const char * filename, FileRdr &file);
|
||||
bool Open(bool quiet);
|
||||
};
|
||||
|
||||
|
@ -79,7 +79,8 @@ public:
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FPakFile::FPakFile(const char *filename, FileReader *file) : FUncompressedFile(filename, file)
|
||||
FPakFile::FPakFile(const char *filename, FileRdr &file)
|
||||
: FUncompressedFile(filename, file)
|
||||
{
|
||||
Lumps = NULL;
|
||||
}
|
||||
|
@ -94,13 +95,13 @@ bool FPakFile::Open(bool quiet)
|
|||
{
|
||||
dpackheader_t header;
|
||||
|
||||
Reader->Read(&header, sizeof(header));
|
||||
Reader.Read(&header, sizeof(header));
|
||||
NumLumps = LittleLong(header.dirlen) / sizeof(dpackfile_t);
|
||||
header.dirofs = LittleLong(header.dirofs);
|
||||
|
||||
dpackfile_t *fileinfo = new dpackfile_t[NumLumps];
|
||||
Reader->Seek (header.dirofs, SEEK_SET);
|
||||
Reader->Read (fileinfo, NumLumps * sizeof(dpackfile_t));
|
||||
Reader.Seek (header.dirofs, FileRdr::SeekSet);
|
||||
Reader.Read (fileinfo, NumLumps * sizeof(dpackfile_t));
|
||||
|
||||
Lumps = new FUncompressedLump[NumLumps];
|
||||
|
||||
|
@ -126,21 +127,21 @@ bool FPakFile::Open(bool quiet)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckPak(const char *filename, FileReader *file, bool quiet)
|
||||
FResourceFile *CheckPak(const char *filename, FileRdr &file, bool quiet)
|
||||
{
|
||||
char head[4];
|
||||
|
||||
if (file->GetLength() >= 12)
|
||||
if (file.GetLength() >= 12)
|
||||
{
|
||||
file->Seek(0, SEEK_SET);
|
||||
file->Read(&head, 4);
|
||||
file->Seek(0, SEEK_SET);
|
||||
file.Seek(0, FileRdr::SeekSet);
|
||||
file.Read(&head, 4);
|
||||
file.Seek(0, FileRdr::SeekSet);
|
||||
if (!memcmp(head, "PACK", 4))
|
||||
{
|
||||
FResourceFile *rf = new FPakFile(filename, file);
|
||||
if (rf->Open(quiet)) return rf;
|
||||
|
||||
rf->Reader = NULL; // to avoid destruction of reader
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
delete rf;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ struct RFFLump
|
|||
|
||||
struct FRFFLump : public FUncompressedLump
|
||||
{
|
||||
virtual FileReader *GetReader();
|
||||
virtual FileRdr *GetReader();
|
||||
virtual int FillCache();
|
||||
|
||||
uint32_t IndexNum;
|
||||
|
@ -111,7 +111,7 @@ class FRFFFile : public FResourceFile
|
|||
FRFFLump *Lumps;
|
||||
|
||||
public:
|
||||
FRFFFile(const char * filename, FileReader *file);
|
||||
FRFFFile(const char * filename, FileRdr &file);
|
||||
virtual ~FRFFFile();
|
||||
virtual bool Open(bool quiet);
|
||||
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
|
||||
|
@ -124,7 +124,7 @@ public:
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FRFFFile::FRFFFile(const char *filename, FileReader *file)
|
||||
FRFFFile::FRFFFile(const char *filename, FileRdr &file)
|
||||
: FResourceFile(filename, file)
|
||||
{
|
||||
Lumps = NULL;
|
||||
|
@ -141,13 +141,13 @@ bool FRFFFile::Open(bool quiet)
|
|||
RFFLump *lumps;
|
||||
RFFInfo header;
|
||||
|
||||
Reader->Read(&header, sizeof(header));
|
||||
Reader.Read(&header, sizeof(header));
|
||||
|
||||
NumLumps = LittleLong(header.NumLumps);
|
||||
header.DirOfs = LittleLong(header.DirOfs);
|
||||
lumps = new RFFLump[header.NumLumps];
|
||||
Reader->Seek (header.DirOfs, SEEK_SET);
|
||||
Reader->Read (lumps, header.NumLumps * sizeof(RFFLump));
|
||||
Reader.Seek (header.DirOfs, FileRdr::SeekSet);
|
||||
Reader.Read (lumps, header.NumLumps * sizeof(RFFLump));
|
||||
BloodCrypt (lumps, header.DirOfs, header.NumLumps * sizeof(RFFLump));
|
||||
|
||||
Lumps = new FRFFLump[NumLumps];
|
||||
|
@ -203,7 +203,7 @@ FRFFFile::~FRFFFile()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FileReader *FRFFLump::GetReader()
|
||||
FileRdr *FRFFLump::GetReader()
|
||||
{
|
||||
// Don't return the reader if this lump is encrypted
|
||||
// In that case always force caching of the lump
|
||||
|
@ -247,21 +247,21 @@ int FRFFLump::FillCache()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckRFF(const char *filename, FileReader *file, bool quiet)
|
||||
FResourceFile *CheckRFF(const char *filename, FileRdr &file, bool quiet)
|
||||
{
|
||||
char head[4];
|
||||
|
||||
if (file->GetLength() >= 16)
|
||||
if (file.GetLength() >= 16)
|
||||
{
|
||||
file->Seek(0, SEEK_SET);
|
||||
file->Read(&head, 4);
|
||||
file->Seek(0, SEEK_SET);
|
||||
file.Seek(0, FileRdr::SeekSet);
|
||||
file.Read(&head, 4);
|
||||
file.Seek(0, FileRdr::SeekSet);
|
||||
if (!memcmp(head, "RFF\x1a", 4))
|
||||
{
|
||||
FResourceFile *rf = new FRFFFile(filename, file);
|
||||
if (rf->Open(quiet)) return rf;
|
||||
|
||||
rf->Reader = NULL; // to avoid destruction of reader
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
delete rf;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,191 +40,7 @@
|
|||
#include "w_wad.h"
|
||||
#include "gi.h"
|
||||
#include "i_system.h"
|
||||
|
||||
// Console Doom LZSS wrapper.
|
||||
class FileReaderLZSS : public FileReaderBase
|
||||
{
|
||||
private:
|
||||
enum { BUFF_SIZE = 4096, WINDOW_SIZE = 4096, INTERNAL_BUFFER_SIZE = 128 };
|
||||
|
||||
FileReader &File;
|
||||
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);
|
||||
|
||||
long numread = File.Read(InBuff+Stream.AvailIn, BUFF_SIZE-Stream.AvailIn);
|
||||
|
||||
if (numread < BUFF_SIZE)
|
||||
{
|
||||
SawEOF = true;
|
||||
}
|
||||
Stream.In = InBuff;
|
||||
Stream.AvailIn = 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:
|
||||
FileReaderLZSS(FileReader &file) : File(file), SawEOF(false)
|
||||
{
|
||||
Stream.State = STREAM_EMPTY;
|
||||
Stream.WindowData = Stream.InternalBuffer = Stream.Window+WINDOW_SIZE;
|
||||
Stream.InternalOut = 0;
|
||||
Stream.AvailIn = 0;
|
||||
|
||||
FillBuffer();
|
||||
}
|
||||
|
||||
~FileReaderLZSS()
|
||||
{
|
||||
}
|
||||
|
||||
long Read(void *buffer, long len)
|
||||
{
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
#include "w_zip.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -239,12 +55,12 @@ public:
|
|||
int Position;
|
||||
|
||||
int GetFileOffset() { return Position; }
|
||||
FileReader *GetReader()
|
||||
FileRdr *GetReader()
|
||||
{
|
||||
if(!Compressed)
|
||||
{
|
||||
Owner->Reader->Seek(Position, SEEK_SET);
|
||||
return Owner->Reader;
|
||||
Owner->Reader.Seek(Position, FileRdr::SeekSet);
|
||||
return &Owner->Reader;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -252,7 +68,7 @@ public:
|
|||
{
|
||||
if(!Compressed)
|
||||
{
|
||||
const char * buffer = Owner->Reader->GetBuffer();
|
||||
const char * buffer = Owner->Reader.GetBuffer();
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
|
@ -263,16 +79,19 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
Owner->Reader->Seek(Position, SEEK_SET);
|
||||
Owner->Reader.Seek(Position, FileRdr::SeekSet);
|
||||
Cache = new char[LumpSize];
|
||||
|
||||
if(Compressed)
|
||||
{
|
||||
FileReaderLZSS lzss(*Owner->Reader);
|
||||
lzss.Read(Cache, LumpSize);
|
||||
FileRdr lzss;
|
||||
if (lzss.OpenDecompressor(Owner->Reader, LumpSize, METHOD_LZSS, false))
|
||||
{
|
||||
lzss.Read(Cache, LumpSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
Owner->Reader->Read(Cache, LumpSize);
|
||||
Owner->Reader.Read(Cache, LumpSize);
|
||||
|
||||
RefCount = 1;
|
||||
return 1;
|
||||
|
@ -294,7 +113,7 @@ class FWadFile : public FResourceFile
|
|||
void SkinHack ();
|
||||
|
||||
public:
|
||||
FWadFile(const char * filename, FileReader *file);
|
||||
FWadFile(const char * filename, FileRdr &file);
|
||||
~FWadFile();
|
||||
void FindStrifeTeaserVoices ();
|
||||
FResourceLump *GetLump(int lump) { return &Lumps[lump]; }
|
||||
|
@ -310,7 +129,8 @@ public:
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FWadFile::FWadFile(const char *filename, FileReader *file) : FResourceFile(filename, file)
|
||||
FWadFile::FWadFile(const char *filename, FileRdr &file)
|
||||
: FResourceFile(filename, file)
|
||||
{
|
||||
Lumps = NULL;
|
||||
}
|
||||
|
@ -331,9 +151,9 @@ bool FWadFile::Open(bool quiet)
|
|||
wadinfo_t header;
|
||||
uint32_t InfoTableOfs;
|
||||
bool isBigEndian = false; // Little endian is assumed until proven otherwise
|
||||
const long wadSize = Reader->GetLength();
|
||||
auto wadSize = Reader.GetLength();
|
||||
|
||||
Reader->Read(&header, sizeof(header));
|
||||
Reader.Read(&header, sizeof(header));
|
||||
NumLumps = LittleLong(header.NumLumps);
|
||||
InfoTableOfs = LittleLong(header.InfoTableOfs);
|
||||
|
||||
|
@ -353,8 +173,8 @@ bool FWadFile::Open(bool quiet)
|
|||
}
|
||||
|
||||
wadlump_t *fileinfo = new wadlump_t[NumLumps];
|
||||
Reader->Seek (InfoTableOfs, SEEK_SET);
|
||||
Reader->Read (fileinfo, NumLumps * sizeof(wadlump_t));
|
||||
Reader.Seek (InfoTableOfs, FileRdr::SeekSet);
|
||||
Reader.Read (fileinfo, NumLumps * sizeof(wadlump_t));
|
||||
|
||||
Lumps = new FWadFileLump[NumLumps];
|
||||
|
||||
|
@ -369,7 +189,7 @@ bool FWadFile::Open(bool quiet)
|
|||
Lumps[i].Position = isBigEndian ? BigLong(fileinfo[i].FilePos) : LittleLong(fileinfo[i].FilePos);
|
||||
Lumps[i].LumpSize = isBigEndian ? BigLong(fileinfo[i].Size) : LittleLong(fileinfo[i].Size);
|
||||
Lumps[i].Namespace = ns_global;
|
||||
Lumps[i].Flags = 0;
|
||||
Lumps[i].Flags = Lumps[i].Compressed? LUMPF_COMPRESSED : 0;
|
||||
Lumps[i].FullName = NULL;
|
||||
}
|
||||
|
||||
|
@ -655,21 +475,21 @@ void FWadFile::FindStrifeTeaserVoices ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckWad(const char *filename, FileReader *file, bool quiet)
|
||||
FResourceFile *CheckWad(const char *filename, FileRdr &file, bool quiet)
|
||||
{
|
||||
char head[4];
|
||||
|
||||
if (file->GetLength() >= 12)
|
||||
if (file.GetLength() >= 12)
|
||||
{
|
||||
file->Seek(0, SEEK_SET);
|
||||
file->Read(&head, 4);
|
||||
file->Seek(0, SEEK_SET);
|
||||
file.Seek(0, FileRdr::SeekSet);
|
||||
file.Read(&head, 4);
|
||||
file.Seek(0, FileRdr::SeekSet);
|
||||
if (!memcmp(head, "IWAD", 4) || !memcmp(head, "PWAD", 4))
|
||||
{
|
||||
FResourceFile *rf = new FWadFile(filename, file);
|
||||
if (rf->Open(quiet)) return rf;
|
||||
|
||||
rf->Reader = NULL; // to avoid destruction of reader
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
delete rf;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool UncompressZipLump(char *Cache, FileReader *Reader, int Method, int LumpSize, int CompressedSize, int GPFlags)
|
||||
static bool UncompressZipLump(char *Cache, FileRdr &Reader, int Method, int LumpSize, int CompressedSize, int GPFlags)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -59,31 +59,23 @@ static bool UncompressZipLump(char *Cache, FileReader *Reader, int Method, int L
|
|||
{
|
||||
case METHOD_STORED:
|
||||
{
|
||||
Reader->Read(Cache, LumpSize);
|
||||
Reader.Read(Cache, LumpSize);
|
||||
break;
|
||||
}
|
||||
|
||||
case METHOD_DEFLATE:
|
||||
{
|
||||
FileReaderZ frz(*Reader, true);
|
||||
frz.Read(Cache, LumpSize);
|
||||
break;
|
||||
}
|
||||
|
||||
case METHOD_BZIP2:
|
||||
{
|
||||
FileReaderBZ2 frz(*Reader);
|
||||
frz.Read(Cache, LumpSize);
|
||||
break;
|
||||
}
|
||||
|
||||
case METHOD_LZMA:
|
||||
{
|
||||
FileReaderLZMA frz(*Reader, LumpSize, true);
|
||||
frz.Read(Cache, LumpSize);
|
||||
FileRdr frz;
|
||||
if (frz.OpenDecompressor(Reader, LumpSize, Method, false))
|
||||
{
|
||||
frz.Read(Cache, LumpSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Fixme: These should also use a stream
|
||||
case METHOD_IMPLODE:
|
||||
{
|
||||
FZipExploder exploder;
|
||||
|
@ -112,8 +104,9 @@ static bool UncompressZipLump(char *Cache, FileReader *Reader, int Method, int L
|
|||
|
||||
bool FCompressedBuffer::Decompress(char *destbuffer)
|
||||
{
|
||||
MemoryReader mr(mBuffer, mCompressedSize);
|
||||
return UncompressZipLump(destbuffer, &mr, mMethod, mSize, mCompressedSize, mZipFlags);
|
||||
FileRdr mr;
|
||||
mr.OpenMemory(mBuffer, mCompressedSize);
|
||||
return UncompressZipLump(destbuffer, mr, mMethod, mSize, mCompressedSize, mZipFlags);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
@ -123,7 +116,7 @@ bool FCompressedBuffer::Decompress(char *destbuffer)
|
|||
//
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
static uint32_t Zip_FindCentralDir(FileReader * fin)
|
||||
static uint32_t Zip_FindCentralDir(FileRdr &fin)
|
||||
{
|
||||
unsigned char buf[BUFREADCOMMENT + 4];
|
||||
uint32_t FileSize;
|
||||
|
@ -131,9 +124,9 @@ static uint32_t Zip_FindCentralDir(FileReader * fin)
|
|||
uint32_t uMaxBack; // maximum size of global comment
|
||||
uint32_t uPosFound=0;
|
||||
|
||||
fin->Seek(0, SEEK_END);
|
||||
fin.Seek(0, FileRdr::SeekEnd);
|
||||
|
||||
FileSize = fin->Tell();
|
||||
FileSize = (uint32_t)fin.Tell();
|
||||
uMaxBack = MIN<uint32_t>(0xffff, FileSize);
|
||||
|
||||
uBackRead = 4;
|
||||
|
@ -149,9 +142,9 @@ static uint32_t Zip_FindCentralDir(FileReader * fin)
|
|||
|
||||
uReadSize = MIN<uint32_t>((BUFREADCOMMENT + 4), (FileSize - uReadPos));
|
||||
|
||||
if (fin->Seek(uReadPos, SEEK_SET) != 0) break;
|
||||
if (fin.Seek(uReadPos, FileRdr::SeekSet) != 0) break;
|
||||
|
||||
if (fin->Read(buf, (int32_t)uReadSize) != (int32_t)uReadSize) break;
|
||||
if (fin.Read(buf, (int32_t)uReadSize) != (int32_t)uReadSize) break;
|
||||
|
||||
for (i = (int)uReadSize - 3; (i--) > 0;)
|
||||
{
|
||||
|
@ -174,7 +167,7 @@ static uint32_t Zip_FindCentralDir(FileReader * fin)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FZipFile::FZipFile(const char * filename, FileReader *file)
|
||||
FZipFile::FZipFile(const char * filename, FileRdr &file)
|
||||
: FResourceFile(filename, file)
|
||||
{
|
||||
Lumps = NULL;
|
||||
|
@ -195,8 +188,8 @@ bool FZipFile::Open(bool quiet)
|
|||
}
|
||||
|
||||
// Read the central directory info.
|
||||
Reader->Seek(centraldir, SEEK_SET);
|
||||
Reader->Read(&info, sizeof(FZipEndOfCentralDirectory));
|
||||
Reader.Seek(centraldir, FileRdr::SeekSet);
|
||||
Reader.Read(&info, sizeof(FZipEndOfCentralDirectory));
|
||||
|
||||
// No multi-disk zips!
|
||||
if (info.NumEntries != info.NumEntriesOnAllDisks ||
|
||||
|
@ -212,8 +205,8 @@ bool FZipFile::Open(bool quiet)
|
|||
// Load the entire central directory. Too bad that this contains variable length entries...
|
||||
int dirsize = LittleLong(info.DirectorySize);
|
||||
void *directory = malloc(dirsize);
|
||||
Reader->Seek(LittleLong(info.DirectoryOffset), SEEK_SET);
|
||||
Reader->Read(directory, dirsize);
|
||||
Reader.Seek(LittleLong(info.DirectoryOffset), FileRdr::SeekSet);
|
||||
Reader.Read(directory, dirsize);
|
||||
|
||||
char *dirptr = (char*)directory;
|
||||
FZipLump *lump_p = Lumps;
|
||||
|
@ -349,6 +342,7 @@ bool FZipFile::Open(bool quiet)
|
|||
// The start of the Reader will be determined the first time it is accessed.
|
||||
lump_p->Flags = LUMPF_ZIPFILE | LUMPFZIP_NEEDFILESTART;
|
||||
lump_p->Method = uint8_t(zip_fh->Method);
|
||||
if (lump_p->Method != METHOD_STORED) lump_p->Flags |= LUMPF_COMPRESSED;
|
||||
lump_p->GPFlags = zip_fh->Flags;
|
||||
lump_p->CRC32 = zip_fh->CRC32;
|
||||
lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize);
|
||||
|
@ -394,8 +388,8 @@ FCompressedBuffer FZipLump::GetRawData()
|
|||
{
|
||||
FCompressedBuffer cbuf = { (unsigned)LumpSize, (unsigned)CompressedSize, Method, GPFlags, CRC32, new char[CompressedSize] };
|
||||
if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress();
|
||||
Owner->Reader->Seek(Position, SEEK_SET);
|
||||
Owner->Reader->Read(cbuf.mBuffer, CompressedSize);
|
||||
Owner->Reader.Seek(Position, FileRdr::SeekSet);
|
||||
Owner->Reader.Read(cbuf.mBuffer, CompressedSize);
|
||||
return cbuf;
|
||||
}
|
||||
|
||||
|
@ -413,10 +407,8 @@ void FZipLump::SetLumpAddress()
|
|||
FZipLocalFileHeader localHeader;
|
||||
int skiplen;
|
||||
|
||||
FileReader *file = Owner->Reader;
|
||||
|
||||
file->Seek(Position, SEEK_SET);
|
||||
file->Read(&localHeader, sizeof(localHeader));
|
||||
Owner->Reader.Seek(Position, FileRdr::SeekSet);
|
||||
Owner->Reader.Read(&localHeader, sizeof(localHeader));
|
||||
skiplen = LittleShort(localHeader.NameLength) + LittleShort(localHeader.ExtraLength);
|
||||
Position += sizeof(localHeader) + skiplen;
|
||||
Flags &= ~LUMPFZIP_NEEDFILESTART;
|
||||
|
@ -428,15 +420,15 @@ void FZipLump::SetLumpAddress()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FileReader *FZipLump::GetReader()
|
||||
FileRdr *FZipLump::GetReader()
|
||||
{
|
||||
// Don't return the reader if this lump is encrypted
|
||||
// In that case always force caching of the lump
|
||||
if (Method == METHOD_STORED)
|
||||
{
|
||||
if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress();
|
||||
Owner->Reader->Seek(Position, SEEK_SET);
|
||||
return Owner->Reader;
|
||||
Owner->Reader.Seek(Position, FileRdr::SeekSet);
|
||||
return &Owner->Reader;
|
||||
}
|
||||
else return NULL;
|
||||
}
|
||||
|
@ -452,7 +444,7 @@ int FZipLump::FillCache()
|
|||
if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress();
|
||||
const char *buffer;
|
||||
|
||||
if (Method == METHOD_STORED && (buffer = Owner->Reader->GetBuffer()) != NULL)
|
||||
if (Method == METHOD_STORED && (buffer = Owner->Reader.GetBuffer()) != NULL)
|
||||
{
|
||||
// This is an in-memory file so the cache can point directly to the file's data.
|
||||
Cache = const_cast<char*>(buffer) + Position;
|
||||
|
@ -460,7 +452,7 @@ int FZipLump::FillCache()
|
|||
return -1;
|
||||
}
|
||||
|
||||
Owner->Reader->Seek(Position, SEEK_SET);
|
||||
Owner->Reader.Seek(Position, FileRdr::SeekSet);
|
||||
Cache = new char[LumpSize];
|
||||
UncompressZipLump(Cache, Owner->Reader, Method, LumpSize, CompressedSize, GPFlags);
|
||||
RefCount = 1;
|
||||
|
@ -486,21 +478,21 @@ int FZipLump::GetFileOffset()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile *CheckZip(const char *filename, FileReader *file, bool quiet)
|
||||
FResourceFile *CheckZip(const char *filename, FileRdr &file, bool quiet)
|
||||
{
|
||||
char head[4];
|
||||
|
||||
if (file->GetLength() >= (long)sizeof(FZipLocalFileHeader))
|
||||
if (file.GetLength() >= (long)sizeof(FZipLocalFileHeader))
|
||||
{
|
||||
file->Seek(0, SEEK_SET);
|
||||
file->Read(&head, 4);
|
||||
file->Seek(0, SEEK_SET);
|
||||
file.Seek(0, FileRdr::SeekSet);
|
||||
file.Read(&head, 4);
|
||||
file.Seek(0, FileRdr::SeekSet);
|
||||
if (!memcmp(head, "PK\x3\x4", 4))
|
||||
{
|
||||
FResourceFile *rf = new FZipFile(filename, file);
|
||||
if (rf->Open(quiet)) return rf;
|
||||
|
||||
rf->Reader = NULL; // to avoid destruction of reader
|
||||
file = std::move(rf->Reader); // to avoid destruction of reader
|
||||
delete rf;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ struct FZipLump : public FResourceLump
|
|||
int Position;
|
||||
unsigned CRC32;
|
||||
|
||||
virtual FileReader *GetReader();
|
||||
virtual FileRdr *GetReader();
|
||||
virtual int FillCache();
|
||||
|
||||
private:
|
||||
|
@ -43,7 +43,7 @@ class FZipFile : public FResourceFile
|
|||
FZipLump *Lumps;
|
||||
|
||||
public:
|
||||
FZipFile(const char * filename, FileReader *file);
|
||||
FZipFile(const char * filename, FileRdr &file);
|
||||
virtual ~FZipFile();
|
||||
bool Open(bool quiet);
|
||||
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// FileReader that reads from a lump's cache
|
||||
// File reader that reads from a lump's cache
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
|
@ -212,11 +212,11 @@ FCompressedBuffer FResourceLump::GetRawData()
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// Returns the owner's FileReader if it can be used to access this lump
|
||||
// Returns the owner's FileRdr if it can be used to access this lump
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FileReader *FResourceLump::GetReader()
|
||||
FileRdr *FResourceLump::GetReader()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -227,9 +227,9 @@ FileReader *FResourceLump::GetReader()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FileReader *FResourceLump::NewReader()
|
||||
FileRdr FResourceLump::NewReader()
|
||||
{
|
||||
return new FLumpReader(this);
|
||||
return FileRdr(new FLumpReader(this));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -276,46 +276,45 @@ int FResourceLump::ReleaseCache()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader *file, bool quiet);
|
||||
typedef FResourceFile * (*CheckFunc)(const char *filename, FileRdr &file, bool quiet);
|
||||
|
||||
FResourceFile *CheckWad(const char *filename, FileReader *file, bool quiet);
|
||||
FResourceFile *CheckGRP(const char *filename, FileReader *file, bool quiet);
|
||||
FResourceFile *CheckRFF(const char *filename, FileReader *file, bool quiet);
|
||||
FResourceFile *CheckPak(const char *filename, FileReader *file, bool quiet);
|
||||
FResourceFile *CheckZip(const char *filename, FileReader *file, bool quiet);
|
||||
FResourceFile *Check7Z(const char *filename, FileReader *file, bool quiet);
|
||||
FResourceFile *CheckLump(const char *filename, FileReader *file, bool quiet);
|
||||
FResourceFile *CheckDir(const char *filename, FileReader *file, bool quiet);
|
||||
FResourceFile *CheckWad(const char *filename, FileRdr &file, bool quiet);
|
||||
FResourceFile *CheckGRP(const char *filename, FileRdr &file, bool quiet);
|
||||
FResourceFile *CheckRFF(const char *filename, FileRdr &file, bool quiet);
|
||||
FResourceFile *CheckPak(const char *filename, FileRdr &file, bool quiet);
|
||||
FResourceFile *CheckZip(const char *filename, FileRdr &file, bool quiet);
|
||||
FResourceFile *Check7Z(const char *filename, FileRdr &file, bool quiet);
|
||||
FResourceFile *CheckLump(const char *filename,FileRdr &file, bool quiet);
|
||||
FResourceFile *CheckDir(const char *filename, bool quiet);
|
||||
|
||||
static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckLump };
|
||||
|
||||
FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader *file, bool quiet, bool containeronly)
|
||||
FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileRdr &file, bool quiet, bool containeronly)
|
||||
{
|
||||
bool mustclose = false;
|
||||
if (file == NULL)
|
||||
{
|
||||
try
|
||||
{
|
||||
file = new FileReader(filename);
|
||||
mustclose = true;
|
||||
}
|
||||
catch (CRecoverableError &)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
for(size_t i = 0; i < countof(funcs) - containeronly; i++)
|
||||
{
|
||||
FResourceFile *resfile = funcs[i](filename, file, quiet);
|
||||
if (resfile != NULL) return resfile;
|
||||
}
|
||||
if (mustclose) delete file;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileRdr &file, bool quiet, bool containeronly)
|
||||
{
|
||||
return DoOpenResourceFile(filename, file, quiet, containeronly);
|
||||
}
|
||||
|
||||
|
||||
FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool quiet, bool containeronly)
|
||||
{
|
||||
FileRdr file;
|
||||
if (!file.OpenFile(filename)) return nullptr;
|
||||
return DoOpenResourceFile(filename, file, quiet, containeronly);
|
||||
}
|
||||
|
||||
FResourceFile *FResourceFile::OpenDirectory(const char *filename, bool quiet)
|
||||
{
|
||||
return CheckDir(filename, NULL, quiet);
|
||||
return CheckDir(filename, quiet);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -324,18 +323,17 @@ FResourceFile *FResourceFile::OpenDirectory(const char *filename, bool quiet)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FResourceFile::FResourceFile(const char *filename, FileReader *r)
|
||||
FResourceFile::FResourceFile(const char *filename, FileRdr &r)
|
||||
{
|
||||
if (filename != NULL) Filename = copystring(filename);
|
||||
else Filename = NULL;
|
||||
Reader = r;
|
||||
Reader = std::move(r);
|
||||
}
|
||||
|
||||
|
||||
FResourceFile::~FResourceFile()
|
||||
{
|
||||
if (Filename != NULL) delete [] Filename;
|
||||
delete Reader;
|
||||
}
|
||||
|
||||
int lumpcmp(const void * a, const void * b)
|
||||
|
@ -607,10 +605,10 @@ FResourceLump *FResourceFile::FindLump(const char *name)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FileReader *FUncompressedLump::GetReader()
|
||||
FileRdr *FUncompressedLump::GetReader()
|
||||
{
|
||||
Owner->Reader->Seek(Position, SEEK_SET);
|
||||
return Owner->Reader;
|
||||
Owner->Reader.Seek(Position, FileRdr::SeekSet);
|
||||
return &Owner->Reader;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -621,7 +619,7 @@ FileReader *FUncompressedLump::GetReader()
|
|||
|
||||
int FUncompressedLump::FillCache()
|
||||
{
|
||||
const char * buffer = Owner->Reader->GetBuffer();
|
||||
const char * buffer = Owner->Reader.GetBuffer();
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
|
@ -631,9 +629,9 @@ int FUncompressedLump::FillCache()
|
|||
return -1;
|
||||
}
|
||||
|
||||
Owner->Reader->Seek(Position, SEEK_SET);
|
||||
Owner->Reader.Seek(Position, FileRdr::SeekSet);
|
||||
Cache = new char[LumpSize];
|
||||
Owner->Reader->Read(Cache, LumpSize);
|
||||
Owner->Reader.Read(Cache, LumpSize);
|
||||
RefCount = 1;
|
||||
return 1;
|
||||
}
|
||||
|
@ -644,7 +642,7 @@ int FUncompressedLump::FillCache()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FUncompressedFile::FUncompressedFile(const char *filename, FileReader *r)
|
||||
FUncompressedFile::FUncompressedFile(const char *filename, FileRdr &r)
|
||||
: FResourceFile(filename, r)
|
||||
{
|
||||
Lumps = NULL;
|
||||
|
@ -669,11 +667,11 @@ FExternalLump::FExternalLump(const char *_filename, int filesize)
|
|||
|
||||
if (filesize == -1)
|
||||
{
|
||||
FileReader f;
|
||||
FileRdr f;
|
||||
|
||||
if (f.Open(_filename))
|
||||
if (f.OpenFile(_filename))
|
||||
{
|
||||
LumpSize = f.GetLength();
|
||||
LumpSize = (int)f.GetLength();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -702,9 +700,9 @@ FExternalLump::~FExternalLump()
|
|||
int FExternalLump::FillCache()
|
||||
{
|
||||
Cache = new char[LumpSize];
|
||||
FileReader f;
|
||||
FileRdr f;
|
||||
|
||||
if (f.Open(filename))
|
||||
if (f.OpenFile(filename))
|
||||
{
|
||||
f.Read(Cache, LumpSize);
|
||||
}
|
||||
|
@ -728,7 +726,7 @@ bool FMemoryFile::Open(bool quiet)
|
|||
Lumps->FullName = fname;
|
||||
Lumps->Owner = this;
|
||||
Lumps->Position = 0;
|
||||
Lumps->LumpSize = Reader->GetLength();
|
||||
Lumps->LumpSize = (int)Reader.GetLength();
|
||||
Lumps->Namespace = ns_global;
|
||||
Lumps->Flags = 0;
|
||||
Lumps->FullName = NULL;
|
||||
|
|
|
@ -62,8 +62,8 @@ struct FResourceLump
|
|||
}
|
||||
|
||||
virtual ~FResourceLump();
|
||||
virtual FileReader *GetReader();
|
||||
virtual FileReader *NewReader();
|
||||
virtual FileRdr *GetReader();
|
||||
virtual FileRdr NewReader();
|
||||
virtual int GetFileOffset() { return -1; }
|
||||
virtual int GetIndexNum() const { return 0; }
|
||||
void LumpNameSetup(FString iname);
|
||||
|
@ -81,12 +81,12 @@ protected:
|
|||
class FResourceFile
|
||||
{
|
||||
public:
|
||||
FileReader *Reader;
|
||||
FileRdr Reader;
|
||||
const char *Filename;
|
||||
protected:
|
||||
uint32_t NumLumps;
|
||||
|
||||
FResourceFile(const char *filename, FileReader *r);
|
||||
FResourceFile(const char *filename, FileRdr &r);
|
||||
|
||||
// for archives that can contain directories
|
||||
void PostProcessArchive(void *lumps, size_t lumpsize);
|
||||
|
@ -98,12 +98,14 @@ private:
|
|||
int FilterLumpsByGameType(int gametype, 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);
|
||||
void JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t max);
|
||||
static FResourceFile *DoOpenResourceFile(const char *filename, FileRdr &file, bool quiet, bool containeronly);
|
||||
|
||||
public:
|
||||
static FResourceFile *OpenResourceFile(const char *filename, FileReader *file, bool quiet = false, bool containeronly = false);
|
||||
static FResourceFile *OpenResourceFile(const char *filename, FileRdr &file, bool quiet = false, bool containeronly = false);
|
||||
static FResourceFile *OpenResourceFile(const char *filename, bool quiet = false, bool containeronly = false);
|
||||
static FResourceFile *OpenDirectory(const char *filename, bool quiet = false);
|
||||
virtual ~FResourceFile();
|
||||
FileReader *GetReader() const { return Reader; }
|
||||
FileRdr *GetReader() { return &Reader; }
|
||||
uint32_t LumpCount() const { return NumLumps; }
|
||||
uint32_t GetFirstLump() const { return FirstLump; }
|
||||
void SetFirstLump(uint32_t f) { FirstLump = f; }
|
||||
|
@ -118,7 +120,7 @@ struct FUncompressedLump : public FResourceLump
|
|||
{
|
||||
int Position;
|
||||
|
||||
virtual FileReader *GetReader();
|
||||
virtual FileRdr *GetReader();
|
||||
virtual int FillCache();
|
||||
virtual int GetFileOffset() { return Position; }
|
||||
|
||||
|
@ -132,7 +134,7 @@ protected:
|
|||
FUncompressedLump * Lumps;
|
||||
|
||||
|
||||
FUncompressedFile(const char *filename, FileReader *r);
|
||||
FUncompressedFile(const char *filename, FileRdr &r);
|
||||
virtual ~FUncompressedFile();
|
||||
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
|
||||
|
||||
|
@ -152,12 +154,10 @@ struct FExternalLump : public FResourceLump
|
|||
|
||||
struct FMemoryFile : public FUncompressedFile
|
||||
{
|
||||
MemoryArrayReader mr;
|
||||
|
||||
FMemoryFile(const char *_filename, const void *sdata, int length)
|
||||
: FUncompressedFile(_filename, nullptr), mr((const char *)sdata, length)
|
||||
: FUncompressedFile(_filename, FileRdr())
|
||||
{
|
||||
Reader = &mr;
|
||||
Reader.OpenMemoryArray(sdata, length);
|
||||
}
|
||||
|
||||
bool Open(bool quiet);
|
||||
|
|
|
@ -145,7 +145,7 @@ FileRdr FSF2Reader::OpenFile(const char *name)
|
|||
|
||||
FZipPatReader::FZipPatReader(const char *filename)
|
||||
{
|
||||
resf = FResourceFile::OpenResourceFile(filename, nullptr, true);
|
||||
resf = FResourceFile::OpenResourceFile(filename, true);
|
||||
}
|
||||
|
||||
FZipPatReader::~FZipPatReader()
|
||||
|
@ -166,7 +166,7 @@ FileRdr FZipPatReader::OpenFile(const char *name)
|
|||
auto lump = resf->FindLump(name);
|
||||
if (lump != nullptr)
|
||||
{
|
||||
return FileRdr(lump->NewReader()); // temporary workaround
|
||||
return lump->NewReader();
|
||||
}
|
||||
}
|
||||
return fr;
|
||||
|
@ -306,7 +306,7 @@ void FSoundFontManager::ProcessOneFile(const FString &fn)
|
|||
}
|
||||
else if (!memcmp(head, "PK", 2))
|
||||
{
|
||||
auto zip = FResourceFile::OpenResourceFile(fn, nullptr, true);
|
||||
auto zip = FResourceFile::OpenResourceFile(fn, true);
|
||||
if (zip != nullptr)
|
||||
{
|
||||
if (zip->LumpCount() > 1) // Anything with just one lump cannot possibly be a packed GUS patch set so skip it right away and simplify the lookup code
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include "textures/textures.h"
|
||||
#include "v_palette.h"
|
||||
|
||||
typedef bool (*CheckFunc)(FileReader & file);
|
||||
typedef FTexture * (*CreateFunc)(FileRdr & file, int lumpnum);
|
||||
|
||||
struct TexCreateInfo
|
||||
|
|
|
@ -147,8 +147,6 @@ struct patch_t
|
|||
// the [0] is &columnofs[width]
|
||||
};
|
||||
|
||||
class FileReader;
|
||||
|
||||
// All FTextures present their data to the world in 8-bit format, but if
|
||||
// the source data is something else, this is it.
|
||||
enum FTextureFormat
|
||||
|
|
326
src/w_wad.cpp
326
src/w_wad.cpp
|
@ -225,12 +225,13 @@ int FWadCollection::AddExternalFile(const char *filename)
|
|||
// [RH] Removed reload hack
|
||||
//==========================================================================
|
||||
|
||||
void FWadCollection::AddFile (const char *filename, FileReader *wadinfo)
|
||||
void FWadCollection::AddFile (const char *filename, FileRdr *wadr)
|
||||
{
|
||||
int startlump;
|
||||
bool isdir = false;
|
||||
FileRdr wadreader;
|
||||
|
||||
if (wadinfo == NULL)
|
||||
if (wadr == nullptr)
|
||||
{
|
||||
// Does this exist? If so, is it a directory?
|
||||
if (!DirEntryExists(filename, &isdir))
|
||||
|
@ -242,18 +243,15 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo)
|
|||
|
||||
if (!isdir)
|
||||
{
|
||||
try
|
||||
{
|
||||
wadinfo = new FileReader(filename);
|
||||
}
|
||||
catch (CRecoverableError &err)
|
||||
if (!wadreader.OpenFile(filename))
|
||||
{ // Didn't find file
|
||||
Printf (TEXTCOLOR_RED "%s\n", err.GetMessage());
|
||||
Printf (TEXTCOLOR_RED "%s: File not found\n", filename);
|
||||
PrintLastError ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else wadreader = std::move(*wadr);
|
||||
|
||||
if (!batchrun) Printf (" adding %s", filename);
|
||||
startlump = NumLumps;
|
||||
|
@ -261,7 +259,7 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo)
|
|||
FResourceFile *resfile;
|
||||
|
||||
if (!isdir)
|
||||
resfile = FResourceFile::OpenResourceFile(filename, wadinfo);
|
||||
resfile = FResourceFile::OpenResourceFile(filename, wadreader);
|
||||
else
|
||||
resfile = FResourceFile::OpenDirectory(filename);
|
||||
|
||||
|
@ -292,8 +290,8 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo)
|
|||
{
|
||||
FString path;
|
||||
path.Format("%s:%s", filename, lump->FullName.GetChars());
|
||||
FileReader *embedded = lump->NewReader();
|
||||
AddFile(path, embedded);
|
||||
auto embedded = lump->NewReader();
|
||||
AddFile(path, &embedded);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,14 +301,11 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo)
|
|||
char cksumout[33];
|
||||
memset(cksumout, 0, sizeof(cksumout));
|
||||
|
||||
FileReader *reader = wadinfo;
|
||||
|
||||
if (reader != NULL)
|
||||
if (wadreader.isOpen())
|
||||
{
|
||||
MD5Context md5;
|
||||
reader->Seek(0, SEEK_SET);
|
||||
#pragma message("This does not work!");
|
||||
//md5.Update(FileRdr(reader), reader->GetLength());
|
||||
wadreader.Seek(0, FileRdr::SeekSet);
|
||||
md5.Update(wadreader, (unsigned)wadreader.GetLength());
|
||||
md5.Final(cksum);
|
||||
|
||||
for (size_t j = 0; j < sizeof(cksum); ++j)
|
||||
|
@ -318,7 +313,7 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo)
|
|||
sprintf(cksumout + (j * 2), "%02X", cksum[j]);
|
||||
}
|
||||
|
||||
fprintf(hashfile, "file: %s, hash: %s, size: %ld\n", filename, cksumout, reader->GetLength());
|
||||
fprintf(hashfile, "file: %s, hash: %s, size: %lld\n", filename, cksumout, (int64_t)wadreader.GetLength());
|
||||
}
|
||||
|
||||
else
|
||||
|
@ -331,7 +326,7 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo)
|
|||
if (!(lump->Flags & LUMPF_EMBEDDED))
|
||||
{
|
||||
MD5Context md5;
|
||||
md5.Update(FileRdr(lump->NewReader()), lump->LumpSize);
|
||||
md5.Update(lump->NewReader(), lump->LumpSize);
|
||||
md5.Final(cksum);
|
||||
|
||||
for (size_t j = 0; j < sizeof(cksum); ++j)
|
||||
|
@ -926,7 +921,7 @@ void FWadCollection::RenameNerve ()
|
|||
int w = GetIwadNum();
|
||||
while (++w < GetNumWads())
|
||||
{
|
||||
FileReader *fr = GetFileReader(w);
|
||||
auto fr = GetFileReader(w);
|
||||
if (fr == NULL)
|
||||
{
|
||||
continue;
|
||||
|
@ -937,10 +932,9 @@ void FWadCollection::RenameNerve ()
|
|||
// cheaper way to know this is not the file
|
||||
continue;
|
||||
}
|
||||
fr->Seek(0, SEEK_SET);
|
||||
fr->Seek(0, FileRdr::SeekSet);
|
||||
MD5Context md5;
|
||||
#pragma message("This does not work yet!");
|
||||
//md5.Update(fr, fr->GetLength());
|
||||
md5.Update(*fr, (unsigned)fr->GetLength());
|
||||
md5.Final(cksum);
|
||||
if (memcmp(nerve, cksum, 16) == 0)
|
||||
{
|
||||
|
@ -988,8 +982,8 @@ void FWadCollection::FixMacHexen()
|
|||
return;
|
||||
}
|
||||
|
||||
FileReader* const reader = GetFileReader(GetIwadNum());
|
||||
const long iwadSize = reader->GetLength();
|
||||
FileRdr *reader = GetFileReader(GetIwadNum());
|
||||
auto iwadSize = reader->GetLength();
|
||||
|
||||
static const long DEMO_SIZE = 13596228;
|
||||
static const long BETA_SIZE = 13749984;
|
||||
|
@ -1002,13 +996,12 @@ void FWadCollection::FixMacHexen()
|
|||
return;
|
||||
}
|
||||
|
||||
reader->Seek(0, SEEK_SET);
|
||||
reader->Seek(0, FileRdr::SeekSet);
|
||||
|
||||
uint8_t checksum[16];
|
||||
MD5Context md5;
|
||||
|
||||
#pragma message("This does not work yet!");
|
||||
//md5.Update(reader, iwadSize);
|
||||
md5.Update(*reader, (unsigned)iwadSize);
|
||||
md5.Final(checksum);
|
||||
|
||||
static const uint8_t HEXEN_DEMO_MD5[16] =
|
||||
|
@ -1271,9 +1264,9 @@ int FWadCollection::GetLumpFile (int lump) const
|
|||
|
||||
void FWadCollection::ReadLump (int lump, void *dest)
|
||||
{
|
||||
FWadLump lumpr = OpenLumpNum (lump);
|
||||
long size = lumpr.GetLength ();
|
||||
long numread = lumpr.Read (dest, size);
|
||||
auto lumpr = OpenLumpReader (lump);
|
||||
auto size = lumpr.GetLength ();
|
||||
auto numread = lumpr.Read (dest, size);
|
||||
|
||||
if (numread != size)
|
||||
{
|
||||
|
@ -1303,55 +1296,6 @@ DEFINE_ACTION_FUNCTION(_Wads, ReadLump)
|
|||
ACTION_RETURN_STRING(isLumpValid ? Wads.ReadLump(lump).GetString() : FString());
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenLumpNum
|
||||
//
|
||||
// Returns a copy of the file object for a lump's wad and positions its
|
||||
// file pointer at the beginning of the lump.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FWadLump FWadCollection::OpenLumpNum (int lump)
|
||||
{
|
||||
if ((unsigned)lump >= (unsigned)LumpInfo.Size())
|
||||
{
|
||||
I_Error ("W_OpenLumpNum: %u >= NumLumps", lump);
|
||||
}
|
||||
|
||||
return FWadLump(LumpInfo[lump].lump);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ReopenLumpNum
|
||||
//
|
||||
// Similar to OpenLumpNum, except a new, independant file object is created
|
||||
// for the lump's wad. Use this when you won't read the lump's data all at
|
||||
// once (e.g. for streaming an Ogg Vorbis stream from a wad as music).
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FWadLump *FWadCollection::ReopenLumpNum (int lump)
|
||||
{
|
||||
if ((unsigned)lump >= (unsigned)LumpInfo.Size())
|
||||
{
|
||||
I_Error ("W_ReopenLumpNum: %u >= NumLumps", lump);
|
||||
}
|
||||
|
||||
return new FWadLump(LumpInfo[lump].lump, true);
|
||||
}
|
||||
|
||||
FWadLump *FWadCollection::ReopenLumpNumNewFile (int lump)
|
||||
{
|
||||
if ((unsigned)lump >= (unsigned)LumpInfo.Size())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new FWadLump(lump, LumpInfo[lump].lump);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenLumpReader
|
||||
|
@ -1363,34 +1307,56 @@ FWadLump *FWadCollection::ReopenLumpNumNewFile (int lump)
|
|||
|
||||
FileRdr FWadCollection::OpenLumpReader(int lump)
|
||||
{
|
||||
FileRdr rdr;
|
||||
|
||||
if ((unsigned)lump >= (unsigned)LumpInfo.Size())
|
||||
{
|
||||
I_Error("W_OpenLumpNum: %u >= NumLumps", lump);
|
||||
}
|
||||
|
||||
rdr.mReader = new FWadLump(LumpInfo[lump].lump);
|
||||
return rdr;
|
||||
auto rl = LumpInfo[lump].lump;
|
||||
auto rd = rl->GetReader();
|
||||
|
||||
if (rl->RefCount == 0 && rd != nullptr && !rd->GetBuffer() && !(rl->Flags & (LUMPF_BLOODCRYPT | LUMPF_COMPRESSED)))
|
||||
{
|
||||
FileRdr rdr;
|
||||
rdr.OpenFilePart(*rd, rl->GetFileOffset(), rl->LumpSize);
|
||||
return rdr;
|
||||
}
|
||||
return rl->NewReader(); // This always gets a reader to the cache
|
||||
}
|
||||
|
||||
FileRdr FWadCollection::ReopenLumpReader(int lump, bool alwayscache)
|
||||
{
|
||||
FileRdr rdr;
|
||||
rdr.mReader = alwayscache ? ReopenLumpNumNewFile(lump) : ReopenLumpNum(lump);
|
||||
return rdr;
|
||||
if ((unsigned)lump >= (unsigned)LumpInfo.Size())
|
||||
{
|
||||
I_Error("ReopenLumpReader: %u >= NumLumps", lump);
|
||||
}
|
||||
|
||||
auto rl = LumpInfo[lump].lump;
|
||||
auto rd = rl->GetReader();
|
||||
|
||||
if (rl->RefCount == 0 && rd != nullptr && !rd->GetBuffer() && !alwayscache && !(rl->Flags & (LUMPF_BLOODCRYPT|LUMPF_COMPRESSED)))
|
||||
{
|
||||
int fileno = Wads.GetLumpFile(lump);
|
||||
const char *filename = Wads.GetWadFullName(fileno);
|
||||
FileRdr fr;
|
||||
if (fr.OpenFile(filename, rl->GetFileOffset(), rl->LumpSize))
|
||||
{
|
||||
return fr;
|
||||
}
|
||||
}
|
||||
return rl->NewReader(); // This always gets a reader to the cache
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetFileReader
|
||||
//
|
||||
// Retrieves the FileReader object to access the given WAD
|
||||
// Retrieves the File reader object to access the given WAD
|
||||
// Careful: This is only useful for real WAD files!
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FileReader *FWadCollection::GetFileReader(int wadnum)
|
||||
FileRdr *FWadCollection::GetFileReader(int wadnum)
|
||||
{
|
||||
if ((uint32_t)wadnum >= Files.Size())
|
||||
{
|
||||
|
@ -1486,31 +1452,6 @@ const char *FWadCollection::GetWadFullName (int wadnum) const
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// IsUncompressedFile
|
||||
//
|
||||
// Returns true when the lump is available as an uncompressed portion of
|
||||
// a file. The music player can play such lumps by streaming but anything
|
||||
// else has to be loaded into memory first.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FWadCollection::IsUncompressedFile(int lump) const
|
||||
{
|
||||
if ((unsigned)lump >= (unsigned)NumLumps)
|
||||
{
|
||||
I_Error ("IsUncompressedFile: %u >= NumLumps",lump);
|
||||
}
|
||||
|
||||
FResourceLump *l = LumpInfo[lump].lump;
|
||||
FileReader *f = l->GetReader();
|
||||
|
||||
// We can access the file only if we get the FILE pointer from the FileReader here.
|
||||
// Any other case means it won't work.
|
||||
return (f != NULL && f->GetFile() != NULL);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// IsEncryptedFile
|
||||
|
@ -1529,157 +1470,6 @@ bool FWadCollection::IsEncryptedFile(int lump) const
|
|||
}
|
||||
|
||||
|
||||
// FWadLump -----------------------------------------------------------------
|
||||
|
||||
FWadLump::FWadLump ()
|
||||
: FileReader(), Lump(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
FWadLump::FWadLump (const FWadLump ©)
|
||||
: FileReader()
|
||||
{
|
||||
// This must be defined isn't called.
|
||||
File = copy.File;
|
||||
Length = copy.Length;
|
||||
FilePos = copy.FilePos;
|
||||
StartPos = copy.StartPos;
|
||||
CloseOnDestruct = false;
|
||||
if ((Lump = copy.Lump)) Lump->CacheLump();
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
FWadLump & FWadLump::operator= (const FWadLump ©)
|
||||
{
|
||||
// Only the debug build actually calls this!
|
||||
File = copy.File;
|
||||
Length = copy.Length;
|
||||
FilePos = copy.FilePos;
|
||||
StartPos = copy.StartPos;
|
||||
CloseOnDestruct = false;
|
||||
if ((Lump = copy.Lump)) Lump->CacheLump();
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
FWadLump::FWadLump(FResourceLump *lump, bool alwayscache)
|
||||
: FileReader()
|
||||
{
|
||||
FileReader *f = lump->GetReader();
|
||||
|
||||
if (f != NULL && f->GetFile() != NULL && !alwayscache)
|
||||
{
|
||||
// Uncompressed lump in a file
|
||||
File = f->GetFile();
|
||||
Length = lump->LumpSize;
|
||||
StartPos = FilePos = lump->GetFileOffset();
|
||||
Lump = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
File = NULL;
|
||||
Length = lump->LumpSize;
|
||||
StartPos = FilePos = 0;
|
||||
Lump = lump;
|
||||
Lump->CacheLump();
|
||||
}
|
||||
}
|
||||
|
||||
FWadLump::FWadLump(int lumpnum, FResourceLump *lump)
|
||||
: FileReader()
|
||||
{
|
||||
FileReader *f = lump->GetReader();
|
||||
|
||||
if (f != NULL && f->GetFile() != NULL)
|
||||
{
|
||||
// Uncompressed lump in a file. For this we will have to open a new FILE, since we need it for streaming
|
||||
int fileno = Wads.GetLumpFile(lumpnum);
|
||||
const char *filename = Wads.GetWadFullName(fileno);
|
||||
File = openfd(filename);
|
||||
if (File != NULL)
|
||||
{
|
||||
Length = lump->LumpSize;
|
||||
StartPos = FilePos = lump->GetFileOffset();
|
||||
Lump = NULL;
|
||||
CloseOnDestruct = true;
|
||||
Seek(0, SEEK_SET);
|
||||
return;
|
||||
}
|
||||
}
|
||||
File = NULL;
|
||||
Length = lump->LumpSize;
|
||||
StartPos = FilePos = 0;
|
||||
Lump = lump;
|
||||
Lump->CacheLump();
|
||||
}
|
||||
|
||||
FWadLump::~FWadLump()
|
||||
{
|
||||
if (Lump != NULL)
|
||||
{
|
||||
Lump->ReleaseCache();
|
||||
}
|
||||
}
|
||||
|
||||
long FWadLump::Seek (long offset, int origin)
|
||||
{
|
||||
if (Lump != NULL)
|
||||
{
|
||||
switch (origin)
|
||||
{
|
||||
case SEEK_CUR:
|
||||
offset += FilePos;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
offset += Length;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
FilePos = clamp<long> (offset, 0, Length);
|
||||
return 0;
|
||||
}
|
||||
return FileReader::Seek(offset, origin);
|
||||
}
|
||||
|
||||
long FWadLump::Read (void *buffer, long len)
|
||||
{
|
||||
long numread;
|
||||
long startread = FilePos;
|
||||
|
||||
if (Lump != NULL)
|
||||
{
|
||||
if (FilePos + len > Length)
|
||||
{
|
||||
len = Length - FilePos;
|
||||
}
|
||||
memcpy(buffer, Lump->Cache + FilePos, len);
|
||||
FilePos += len;
|
||||
numread = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
numread = FileReader::Read(buffer, len);
|
||||
}
|
||||
return numread;
|
||||
}
|
||||
|
||||
char *FWadLump::Gets(char *strbuf, int len)
|
||||
{
|
||||
if (Lump != NULL)
|
||||
{
|
||||
return GetsFromBuffer(Lump->Cache, strbuf, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FileReader::Gets(strbuf, len);
|
||||
}
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
// FMemLump -----------------------------------------------------------------
|
||||
|
||||
FMemLump::FMemLump ()
|
||||
|
@ -1708,10 +1498,10 @@ FMemLump::~FMemLump ()
|
|||
|
||||
FString::FString (ELumpNum lumpnum)
|
||||
{
|
||||
FWadLump lumpr = Wads.OpenLumpNum ((int)lumpnum);
|
||||
long size = lumpr.GetLength ();
|
||||
auto lumpr = Wads.OpenLumpReader ((int)lumpnum);
|
||||
auto size = lumpr.GetLength ();
|
||||
AllocBuffer (1 + size);
|
||||
long numread = lumpr.Read (&Chars[0], size);
|
||||
auto numread = lumpr.Read (&Chars[0], size);
|
||||
Chars[size] = '\0';
|
||||
|
||||
if (numread != size)
|
||||
|
|
47
src/w_wad.h
47
src/w_wad.h
|
@ -68,44 +68,18 @@ typedef enum {
|
|||
|
||||
enum ELumpFlags
|
||||
{
|
||||
LUMPF_MAYBEFLAT=1,
|
||||
LUMPF_ZIPFILE=2,
|
||||
LUMPF_EMBEDDED=4,
|
||||
LUMPF_BLOODCRYPT = 8,
|
||||
LUMPF_MAYBEFLAT=1, // might be a flat outside F_START/END
|
||||
LUMPF_ZIPFILE=2, // contains a full path
|
||||
LUMPF_EMBEDDED=4, // from an embedded WAD
|
||||
LUMPF_BLOODCRYPT = 8, // encrypted
|
||||
LUMPF_COMPRESSED = 16, // compressed
|
||||
LUMPF_SEQUENTIAL = 32, // compressed but a sequential reader can be retrieved.
|
||||
};
|
||||
|
||||
|
||||
// [RH] Copy an 8-char string and uppercase it.
|
||||
void uppercopy (char *to, const char *from);
|
||||
|
||||
// A very loose reference to a lump on disk. This is really just a wrapper
|
||||
// around the main wad's FILE object with a different length recorded. Since
|
||||
// two lumps from the same wad share the same FILE, you cannot read from
|
||||
// both of them independantly.
|
||||
class FWadLump : public FileReader
|
||||
{
|
||||
public:
|
||||
FWadLump ();
|
||||
FWadLump (const FWadLump ©);
|
||||
#ifdef _DEBUG
|
||||
FWadLump & operator= (const FWadLump ©);
|
||||
#endif
|
||||
~FWadLump();
|
||||
|
||||
long Seek (long offset, int origin);
|
||||
long Read (void *buffer, long len);
|
||||
char *Gets(char *strbuf, int len);
|
||||
|
||||
private:
|
||||
FWadLump (FResourceLump *Lump, bool alwayscache = false);
|
||||
FWadLump(int lumpnum, FResourceLump *lump);
|
||||
|
||||
FResourceLump *Lump;
|
||||
|
||||
friend class FWadCollection;
|
||||
};
|
||||
|
||||
|
||||
// A lump in memory.
|
||||
class FMemLump
|
||||
{
|
||||
|
@ -138,7 +112,7 @@ public:
|
|||
void SetIwadNum(int x) { IwadIndex = x; }
|
||||
|
||||
void InitMultipleFiles (TArray<FString> &filenames);
|
||||
void AddFile (const char *filename, FileReader *wadinfo = NULL);
|
||||
void AddFile (const char *filename, FileRdr *wadinfo = NULL);
|
||||
int CheckIfWadLoaded (const char *name);
|
||||
|
||||
const char *GetWadName (int wadnum) const;
|
||||
|
@ -180,10 +154,6 @@ public:
|
|||
FileRdr OpenLumpReader(int lump); // opens a reader that redirects to the containing file's one.
|
||||
FileRdr ReopenLumpReader(int lump, bool alwayscache = false); // opens an independent reader.
|
||||
|
||||
FWadLump OpenLumpNum (int lump);
|
||||
FWadLump *ReopenLumpNum (int lump); // Opens a new, independent FILE
|
||||
FWadLump *ReopenLumpNumNewFile (int lump); // Opens a new, independent FILE
|
||||
|
||||
int FindLump (const char *name, int *lastlump, bool anyns=false); // [RH] Find lumps with duplication
|
||||
int FindLumpMulti (const char **names, int *lastlump, bool anyns = false, int *nameindex = NULL); // same with multiple possible names
|
||||
bool CheckLumpName (int lump, const char *name); // [RH] True if lump's name == name
|
||||
|
@ -202,7 +172,6 @@ public:
|
|||
int GetLumpIndexNum (int lump) const; // Returns the RFF index number for this lump
|
||||
bool CheckLumpName (int lump, const char *name) const; // [RH] Returns true if the names match
|
||||
|
||||
bool IsUncompressedFile(int lump) const;
|
||||
bool IsEncryptedFile(int lump) const;
|
||||
|
||||
int GetNumLumps () const;
|
||||
|
@ -237,7 +206,7 @@ private:
|
|||
void RenameNerve();
|
||||
void FixMacHexen();
|
||||
void DeleteAll();
|
||||
FileReader * GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD
|
||||
FileRdr * GetFileReader(int wadnum); // Gets a FileRdr object to the entire WAD
|
||||
};
|
||||
|
||||
extern FWadCollection Wads;
|
||||
|
|
|
@ -62,14 +62,6 @@ struct FZipLocalFileHeader
|
|||
#define ZIP_CENTRALFILE MAKE_ID('P','K',1,2)
|
||||
#define ZIP_ENDOFDIR MAKE_ID('P','K',5,6)
|
||||
|
||||
#define METHOD_STORED 0
|
||||
#define METHOD_SHRINK 1
|
||||
#define METHOD_IMPLODE 6
|
||||
#define METHOD_DEFLATE 8
|
||||
#define METHOD_BZIP2 12
|
||||
#define METHOD_LZMA 14
|
||||
#define METHOD_PPMD 98
|
||||
|
||||
// File header flags.
|
||||
#define ZF_ENCRYPTED 0x1
|
||||
|
||||
|
|
Loading…
Reference in a new issue