mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-03-22 02:41:07 +00:00
take OpenDecompressor out of FileReader and fixed exploding decompression
This commit is contained in:
parent
6f8c3c60c4
commit
9bcbdfa09c
6 changed files with 79 additions and 71 deletions
62
src/common/filesystem/include/fs_decompress.h
Normal file
62
src/common/filesystem/include/fs_decompress.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
#pragma once
|
||||
#include "fs_files.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
// Zip compression methods, extended by some internal types to be passed to OpenDecompressor
|
||||
enum ECompressionMethod
|
||||
{
|
||||
METHOD_STORED = 0,
|
||||
METHOD_SHRINK = 1,
|
||||
METHOD_IMPLODE = 6,
|
||||
METHOD_DEFLATE = 8,
|
||||
METHOD_BZIP2 = 12,
|
||||
METHOD_LZMA = 14,
|
||||
METHOD_XZ = 95,
|
||||
METHOD_PPMD = 98,
|
||||
METHOD_LZSS = 1337, // not used in Zips - this is for Console Doom compression
|
||||
METHOD_ZLIB = 1338, // Zlib stream with header, used by compressed nodes.
|
||||
METHOD_RFFCRYPT = 1339, // not actual compression but can be put in here to make handling easier.
|
||||
METHOD_IMPLODE_MIN = 1000, // having discrete types for these avoids keeping around the GPFlags word in Zips.
|
||||
METHOD_IMPLODE_0 = 1000,
|
||||
METHOD_IMPLODE_2 = 1002,
|
||||
METHOD_IMPLODE_4 = 1004,
|
||||
METHOD_IMPLODE_6 = 1006,
|
||||
METHOD_IMPLODE_MAX = 1006,
|
||||
METHOD_INVALID = 0x7fff,
|
||||
METHOD_TRANSFEROWNER = 0x8000,
|
||||
};
|
||||
|
||||
enum EDecompressFlags
|
||||
{
|
||||
DCF_TRANSFEROWNER = 1,
|
||||
DCF_SEEKABLE = 2,
|
||||
DCF_EXCEPTIONS = 4
|
||||
};
|
||||
|
||||
bool OpenDecompressor(FileReader& self, FileReader &parent, FileReader::Size length, int method, int flags = 0); // creates a decompressor stream. 'seekable' uses a buffered version so that the Seek and Tell methods can be used.
|
||||
|
||||
// This holds a compresed Zip entry with all needed info to decompress it.
|
||||
struct FCompressedBuffer
|
||||
{
|
||||
size_t mSize;
|
||||
size_t mCompressedSize;
|
||||
int mMethod;
|
||||
unsigned mCRC32;
|
||||
char* mBuffer;
|
||||
const char* filename;
|
||||
|
||||
bool Decompress(char* destbuffer);
|
||||
void Clean()
|
||||
{
|
||||
mSize = mCompressedSize = 0;
|
||||
if (mBuffer != nullptr)
|
||||
{
|
||||
delete[] mBuffer;
|
||||
mBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -72,37 +72,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// Zip compression methods, extended by some internal types to be passed to OpenDecompressor
|
||||
enum ECompressionMethod
|
||||
{
|
||||
METHOD_STORED = 0,
|
||||
METHOD_SHRINK = 1,
|
||||
METHOD_IMPLODE = 6,
|
||||
METHOD_DEFLATE = 8,
|
||||
METHOD_BZIP2 = 12,
|
||||
METHOD_LZMA = 14,
|
||||
METHOD_XZ = 95,
|
||||
METHOD_PPMD = 98,
|
||||
METHOD_LZSS = 1337, // not used in Zips - this is for Console Doom compression
|
||||
METHOD_ZLIB = 1338, // Zlib stream with header, used by compressed nodes.
|
||||
METHOD_RFFCRYPT = 1339, // not actual compression but can be put in here to make handling easier.
|
||||
METHOD_IMPLODE_MIN = 1000, // having discrete types for these avoids keeping around the GPFlags word in Zips.
|
||||
METHOD_IMPLODE_0 = 1000,
|
||||
METHOD_IMPLODE_2 = 1002,
|
||||
METHOD_IMPLODE_4 = 1004,
|
||||
METHOD_IMPLODE_6 = 1006,
|
||||
METHOD_IMPLODE_MAX = 1006,
|
||||
METHOD_INVALID = 0x7fff,
|
||||
METHOD_TRANSFEROWNER = 0x8000,
|
||||
};
|
||||
|
||||
enum EDecompressFlags
|
||||
{
|
||||
DCF_TRANSFEROWNER = 1,
|
||||
DCF_SEEKABLE = 2,
|
||||
DCF_EXCEPTIONS = 4
|
||||
};
|
||||
|
||||
class FileReader;
|
||||
|
||||
// an opaque memory buffer to the file's content. Can either own the memory or just point to an external buffer.
|
||||
|
@ -183,28 +152,6 @@ public:
|
|||
|
||||
};
|
||||
|
||||
// This holds a compresed Zip entry with all needed info to decompress it.
|
||||
struct FCompressedBuffer
|
||||
{
|
||||
size_t mSize;
|
||||
size_t mCompressedSize;
|
||||
int mMethod;
|
||||
unsigned mCRC32;
|
||||
char* mBuffer;
|
||||
const char* filename;
|
||||
|
||||
bool Decompress(char* destbuffer);
|
||||
void Clean()
|
||||
{
|
||||
mSize = mCompressedSize = 0;
|
||||
if (mBuffer != nullptr)
|
||||
{
|
||||
delete[] mBuffer;
|
||||
mBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class FileReaderInterface
|
||||
{
|
||||
|
@ -290,7 +237,6 @@ public:
|
|||
bool OpenMemoryArray(std::vector<uint8_t>& data); // take the given array
|
||||
bool OpenMemoryArray(FileData& data); // take the given array
|
||||
bool OpenMemoryArray(std::function<bool(std::vector<uint8_t>&)> getter); // read contents to a buffer and return a reader to it
|
||||
bool OpenDecompressor(FileReader &parent, Size length, int method, int flags = 0); // creates a decompressor stream. 'seekable' uses a buffered version so that the Seek and Tell methods can be used.
|
||||
|
||||
Size Tell() const
|
||||
{
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include "fs_files.h"
|
||||
#include "fs_decompress.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "fs_files.h"
|
||||
#include "files_internal.h"
|
||||
#include "ancientzip.h"
|
||||
#include "fs_decompress.h"
|
||||
|
||||
namespace FileSys {
|
||||
using namespace byteswap;
|
||||
|
@ -849,7 +850,7 @@ public:
|
|||
};
|
||||
|
||||
|
||||
bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, int flags)
|
||||
bool OpenDecompressor(FileReader& self, FileReader &parent, FileReader::Size length, int method, int flags)
|
||||
{
|
||||
FileReaderInterface* fr = nullptr;
|
||||
DecompressorBase* dec = nullptr;
|
||||
|
@ -923,7 +924,7 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, i
|
|||
}
|
||||
|
||||
// The decoders for these legacy formats can only handle the full data in one go so we have to perform the entire decompression here.
|
||||
case METHOD_IMPLODE:
|
||||
case METHOD_IMPLODE_0:
|
||||
case METHOD_IMPLODE_2:
|
||||
case METHOD_IMPLODE_4:
|
||||
case METHOD_IMPLODE_6:
|
||||
|
@ -933,7 +934,7 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, i
|
|||
auto& buffer = idec->GetArray();
|
||||
auto bufr = (uint8_t*)buffer.allocate(length);
|
||||
FZipExploder exploder;
|
||||
if (exploder.Explode(bufr, length, *p, p->GetLength(), method) == -1)
|
||||
if (exploder.Explode(bufr, length, *p, p->GetLength(), method - METHOD_IMPLODE_MIN) == -1)
|
||||
{
|
||||
if (exceptions)
|
||||
{
|
||||
|
@ -964,9 +965,9 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, i
|
|||
auto bufr = (uint8_t*)buffer.allocate(length);
|
||||
p->Read(bufr, length);
|
||||
|
||||
Size cryptlen = std::min<Size>(length, 256);
|
||||
FileReader::Size cryptlen = std::min<FileReader::Size>(length, 256);
|
||||
|
||||
for (Size i = 0; i < cryptlen; ++i)
|
||||
for (FileReader::Size i = 0; i < cryptlen; ++i)
|
||||
{
|
||||
bufr[i] ^= i >> 1;
|
||||
}
|
||||
|
@ -984,16 +985,12 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, i
|
|||
}
|
||||
dec->Length = length;
|
||||
}
|
||||
if (!(flags & DCF_SEEKABLE))
|
||||
{
|
||||
Close();
|
||||
mReader = fr;
|
||||
}
|
||||
else
|
||||
if ((flags & DCF_SEEKABLE))
|
||||
{
|
||||
// create a wrapper that can buffer the content so that seeking is possible
|
||||
mReader = new BufferingReader(fr);
|
||||
fr = new BufferingReader(fr);
|
||||
}
|
||||
self = FileReader(fr);
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
|
@ -1001,7 +998,7 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, i
|
|||
if (fr) delete fr;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool FCompressedBuffer::Decompress(char* destbuffer)
|
||||
|
@ -1016,7 +1013,7 @@ bool FCompressedBuffer::Decompress(char* destbuffer)
|
|||
FileReader mr;
|
||||
mr.OpenMemory(mBuffer, mCompressedSize);
|
||||
FileReader frz;
|
||||
if (frz.OpenDecompressor(mr, mSize, mMethod))
|
||||
if (OpenDecompressor(frz, mr, mSize, mMethod))
|
||||
{
|
||||
return frz.Read(destbuffer, mSize) != mSize;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "files_internal.h"
|
||||
#include "unicode.h"
|
||||
#include "fs_findfile.h"
|
||||
#include "fs_decompress.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
|
@ -565,7 +566,7 @@ FileReader FResourceFile::GetEntryReader(uint32_t entry, bool newreader)
|
|||
{
|
||||
FileReader fri;
|
||||
fri.OpenFilePart(Reader, Entries[entry].Position, Entries[entry].CompressedSize);
|
||||
fr.OpenDecompressor(fri, Entries[entry].Length, Entries[entry].Method, FileSys::DCF_TRANSFEROWNER | FileSys::DCF_SEEKABLE | FileSys::DCF_EXCEPTIONS);
|
||||
OpenDecompressor(fr, fri, Entries[entry].Length, Entries[entry].Method, FileSys::DCF_TRANSFEROWNER | FileSys::DCF_SEEKABLE | FileSys::DCF_EXCEPTIONS);
|
||||
}
|
||||
}
|
||||
return fr;
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
#include "texturemanager.h"
|
||||
#include "hw_vertexbuilder.h"
|
||||
#include "version.h"
|
||||
#include "fs_decompress.h"
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -738,7 +739,7 @@ bool MapLoader::LoadExtendedNodes (FileReader &dalump, uint32_t id)
|
|||
if (compressed)
|
||||
{
|
||||
FileReader zip;
|
||||
if (zip.OpenDecompressor(dalump, -1, FileSys::METHOD_ZLIB, FileSys::DCF_EXCEPTIONS))
|
||||
if (OpenDecompressor(zip, dalump, -1, FileSys::METHOD_ZLIB, FileSys::DCF_EXCEPTIONS))
|
||||
{
|
||||
LoadZNodes(zip, type);
|
||||
return true;
|
||||
|
@ -3344,7 +3345,7 @@ void MapLoader::LoadLightmap(MapData *map)
|
|||
return;
|
||||
|
||||
FileReader fr;
|
||||
if (!fr.OpenDecompressor(map->Reader(ML_LIGHTMAP), -1, FileSys::METHOD_ZLIB))
|
||||
if (!OpenDecompressor(fr, map->Reader(ML_LIGHTMAP), -1, FileSys::METHOD_ZLIB))
|
||||
return;
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue