mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-12-13 19:49:36 +00:00
Switch to zip archive format for resource data, prep work for moving from PICT/snd to BMP/WAV
This commit is contained in:
44
PortabilityLayer/BMPFormat.h
Normal file
44
PortabilityLayer/BMPFormat.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "PLLittleEndian.h"
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
namespace BitmapConstants
|
||||
{
|
||||
static const uint32_t kCompressionRGB = 0;
|
||||
static const uint32_t kCompressionBitfields = 3;
|
||||
}
|
||||
|
||||
struct BitmapFileHeader
|
||||
{
|
||||
char m_id[2]; // Normally "BM"
|
||||
LEUInt32_t m_fileSize;
|
||||
LEUInt16_t m_reserved1;
|
||||
LEUInt16_t m_reserved2;
|
||||
LEUInt32_t m_imageDataStart;
|
||||
};
|
||||
|
||||
struct BitmapInfoHeader
|
||||
{
|
||||
LEUInt32_t m_thisStructureSize;
|
||||
LEUInt32_t m_width;
|
||||
LEUInt32_t m_height;
|
||||
LEUInt16_t m_planes; // Must be 1
|
||||
LEUInt16_t m_bitsPerPixel;
|
||||
LEUInt32_t m_compression; // In V1 format, when using bitfields mode, the color table contains three DWORD color masks
|
||||
LEUInt32_t m_imageSize;
|
||||
LEUInt32_t m_xPixelsPerMeter;
|
||||
LEUInt32_t m_yPixelsPerMeter;
|
||||
LEUInt32_t m_numColors;
|
||||
LEUInt32_t m_importantColorCount; // First N colors are important. If 0, all are important.
|
||||
};
|
||||
|
||||
struct BitmapColorTableEntry
|
||||
{
|
||||
uint8_t m_b;
|
||||
uint8_t m_g;
|
||||
uint8_t m_r;
|
||||
uint8_t m_reserved;
|
||||
};
|
||||
}
|
||||
@@ -1,76 +1,127 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __PL_BYTEPACK_H__
|
||||
#define __PL_BYTEPACK_H__
|
||||
|
||||
#include "DataTypes.h"
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
namespace BytePack
|
||||
{
|
||||
void BigUInt64(uint8_t *bytes, uint64_t value);
|
||||
void BigUInt32(uint8_t *bytes, uint32_t value);
|
||||
void BigUInt16(uint8_t *bytes, uint16_t value);
|
||||
}
|
||||
}
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
namespace BytePack
|
||||
{
|
||||
inline void BigUInt64(uint8_t *bytes, uint64_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>((value >> 56) & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>((value >> 48) & 0xff);
|
||||
bytes[2] = static_cast<uint8_t>((value >> 40) & 0xff);
|
||||
bytes[3] = static_cast<uint8_t>((value >> 32) & 0xff);
|
||||
bytes[4] = static_cast<uint8_t>((value >> 24) & 0xff);
|
||||
bytes[5] = static_cast<uint8_t>((value >> 16) & 0xff);
|
||||
bytes[6] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[7] = static_cast<uint8_t>(value & 0xff);
|
||||
}
|
||||
|
||||
inline void BigUInt32(uint8_t *bytes, uint32_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>((value >> 24) & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>((value >> 16) & 0xff);
|
||||
bytes[2] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[3] = static_cast<uint8_t>(value & 0xff);
|
||||
}
|
||||
|
||||
inline void BigUInt16(uint8_t *bytes, uint16_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>(value & 0xff);
|
||||
}
|
||||
|
||||
inline void BigInt64(uint8_t *bytes, int64_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>((value >> 56) & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>((value >> 48) & 0xff);
|
||||
bytes[2] = static_cast<uint8_t>((value >> 40) & 0xff);
|
||||
bytes[3] = static_cast<uint8_t>((value >> 32) & 0xff);
|
||||
bytes[4] = static_cast<uint8_t>((value >> 24) & 0xff);
|
||||
bytes[5] = static_cast<uint8_t>((value >> 16) & 0xff);
|
||||
bytes[6] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[7] = static_cast<uint8_t>(value & 0xff);
|
||||
}
|
||||
|
||||
inline void BigInt32(uint8_t *bytes, uint32_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>((value >> 24) & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>((value >> 16) & 0xff);
|
||||
bytes[2] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[3] = static_cast<uint8_t>(value & 0xff);
|
||||
}
|
||||
|
||||
inline void BigInt16(uint8_t *bytes, uint16_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>(value & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
|
||||
#include "DataTypes.h"
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
namespace BytePack
|
||||
{
|
||||
void BigUInt64(uint8_t *bytes, uint64_t value);
|
||||
void BigUInt32(uint8_t *bytes, uint32_t value);
|
||||
void BigUInt16(uint8_t *bytes, uint16_t value);
|
||||
|
||||
void LittleUInt64(uint8_t *bytes, uint64_t value);
|
||||
void LittleUInt32(uint8_t *bytes, uint32_t value);
|
||||
void LittleUInt16(uint8_t *bytes, uint16_t value);
|
||||
}
|
||||
}
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
namespace BytePack
|
||||
{
|
||||
inline void BigUInt64(uint8_t *bytes, uint64_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>((value >> 56) & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>((value >> 48) & 0xff);
|
||||
bytes[2] = static_cast<uint8_t>((value >> 40) & 0xff);
|
||||
bytes[3] = static_cast<uint8_t>((value >> 32) & 0xff);
|
||||
bytes[4] = static_cast<uint8_t>((value >> 24) & 0xff);
|
||||
bytes[5] = static_cast<uint8_t>((value >> 16) & 0xff);
|
||||
bytes[6] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[7] = static_cast<uint8_t>(value & 0xff);
|
||||
}
|
||||
|
||||
inline void BigUInt32(uint8_t *bytes, uint32_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>((value >> 24) & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>((value >> 16) & 0xff);
|
||||
bytes[2] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[3] = static_cast<uint8_t>(value & 0xff);
|
||||
}
|
||||
|
||||
inline void BigUInt16(uint8_t *bytes, uint16_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>(value & 0xff);
|
||||
}
|
||||
|
||||
inline void BigInt64(uint8_t *bytes, int64_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>((value >> 56) & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>((value >> 48) & 0xff);
|
||||
bytes[2] = static_cast<uint8_t>((value >> 40) & 0xff);
|
||||
bytes[3] = static_cast<uint8_t>((value >> 32) & 0xff);
|
||||
bytes[4] = static_cast<uint8_t>((value >> 24) & 0xff);
|
||||
bytes[5] = static_cast<uint8_t>((value >> 16) & 0xff);
|
||||
bytes[6] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[7] = static_cast<uint8_t>(value & 0xff);
|
||||
}
|
||||
|
||||
inline void BigInt32(uint8_t *bytes, uint32_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>((value >> 24) & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>((value >> 16) & 0xff);
|
||||
bytes[2] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[3] = static_cast<uint8_t>(value & 0xff);
|
||||
}
|
||||
|
||||
inline void BigInt16(uint8_t *bytes, uint16_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>(value & 0xff);
|
||||
}
|
||||
|
||||
inline void LittleUInt64(uint8_t *bytes, uint64_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>(value & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[2] = static_cast<uint8_t>((value >> 16) & 0xff);
|
||||
bytes[3] = static_cast<uint8_t>((value >> 24) & 0xff);
|
||||
bytes[4] = static_cast<uint8_t>((value >> 32) & 0xff);
|
||||
bytes[5] = static_cast<uint8_t>((value >> 40) & 0xff);
|
||||
bytes[6] = static_cast<uint8_t>((value >> 48) & 0xff);
|
||||
bytes[7] = static_cast<uint8_t>((value >> 56) & 0xff);
|
||||
}
|
||||
|
||||
inline void LittleUInt32(uint8_t *bytes, uint32_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>(value & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[2] = static_cast<uint8_t>((value >> 16) & 0xff);
|
||||
bytes[3] = static_cast<uint8_t>((value >> 24) & 0xff);
|
||||
}
|
||||
|
||||
inline void LittleUInt16(uint8_t *bytes, uint16_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>(value & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
}
|
||||
|
||||
inline void LittleInt64(uint8_t *bytes, int64_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>(value & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[2] = static_cast<uint8_t>((value >> 16) & 0xff);
|
||||
bytes[3] = static_cast<uint8_t>((value >> 24) & 0xff);
|
||||
bytes[4] = static_cast<uint8_t>((value >> 32) & 0xff);
|
||||
bytes[5] = static_cast<uint8_t>((value >> 40) & 0xff);
|
||||
bytes[6] = static_cast<uint8_t>((value >> 48) & 0xff);
|
||||
bytes[7] = static_cast<uint8_t>((value >> 56) & 0xff);
|
||||
}
|
||||
|
||||
inline void LittleInt32(uint8_t *bytes, uint32_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>(value & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
bytes[2] = static_cast<uint8_t>((value >> 16) & 0xff);
|
||||
bytes[3] = static_cast<uint8_t>((value >> 24) & 0xff);
|
||||
}
|
||||
|
||||
inline void LittleInt16(uint8_t *bytes, uint16_t value)
|
||||
{
|
||||
bytes[0] = static_cast<uint8_t>(value & 0xff);
|
||||
bytes[1] = static_cast<uint8_t>((value >> 8) & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace PortabilityLayer
|
||||
namespace ByteSwap
|
||||
{
|
||||
template<class TNumberType, class TUnsignedType>
|
||||
void SwapArbitrary(TNumberType &v)
|
||||
void SwapArbitraryBig(TNumberType &v)
|
||||
{
|
||||
GP_STATIC_ASSERT(sizeof(TNumberType) == sizeof(TUnsignedType));
|
||||
|
||||
@@ -21,34 +21,80 @@ namespace PortabilityLayer
|
||||
v = static_cast<TNumberType>(result);
|
||||
}
|
||||
|
||||
template<class TNumberType, class TUnsignedType>
|
||||
void SwapArbitraryLittle(TNumberType &v)
|
||||
{
|
||||
GP_STATIC_ASSERT(sizeof(TNumberType) == sizeof(TUnsignedType));
|
||||
|
||||
uint8_t bytes[sizeof(TNumberType)];
|
||||
for (size_t i = 0; i < sizeof(TNumberType); i++)
|
||||
bytes[i] = reinterpret_cast<const uint8_t*>(&v)[i];
|
||||
|
||||
TUnsignedType result = 0;
|
||||
for (size_t i = 0; i < sizeof(TNumberType); i++)
|
||||
result |= static_cast<TUnsignedType>(bytes[i]) << (i * 8);
|
||||
|
||||
v = static_cast<TNumberType>(result);
|
||||
}
|
||||
|
||||
void BigInt16(int16_t &v)
|
||||
{
|
||||
SwapArbitrary<int16_t, uint16_t>(v);
|
||||
SwapArbitraryBig<int16_t, uint16_t>(v);
|
||||
}
|
||||
|
||||
void BigInt32(int32_t &v)
|
||||
{
|
||||
SwapArbitrary<int32_t, uint32_t>(v);
|
||||
SwapArbitraryBig<int32_t, uint32_t>(v);
|
||||
}
|
||||
|
||||
void BigInt64(int64_t &v)
|
||||
{
|
||||
SwapArbitrary<int64_t, uint64_t>(v);
|
||||
SwapArbitraryBig<int64_t, uint64_t>(v);
|
||||
}
|
||||
|
||||
void BigUInt16(uint16_t &v)
|
||||
{
|
||||
SwapArbitrary<uint16_t, uint16_t>(v);
|
||||
SwapArbitraryBig<uint16_t, uint16_t>(v);
|
||||
}
|
||||
|
||||
void BigUInt32(uint32_t &v)
|
||||
{
|
||||
SwapArbitrary<uint32_t, uint32_t>(v);
|
||||
SwapArbitraryBig<uint32_t, uint32_t>(v);
|
||||
}
|
||||
|
||||
void BigUInt64(uint64_t &v)
|
||||
{
|
||||
SwapArbitrary<uint64_t, uint64_t>(v);
|
||||
SwapArbitraryBig<uint64_t, uint64_t>(v);
|
||||
}
|
||||
|
||||
void LittleInt16(int16_t &v)
|
||||
{
|
||||
SwapArbitraryLittle<int16_t, uint16_t>(v);
|
||||
}
|
||||
|
||||
void LittleInt32(int32_t &v)
|
||||
{
|
||||
SwapArbitraryLittle<int32_t, uint32_t>(v);
|
||||
}
|
||||
|
||||
void LittleInt64(int64_t &v)
|
||||
{
|
||||
SwapArbitraryLittle<int64_t, uint64_t>(v);
|
||||
}
|
||||
|
||||
void LittleUInt16(uint16_t &v)
|
||||
{
|
||||
SwapArbitraryLittle<uint16_t, uint16_t>(v);
|
||||
}
|
||||
|
||||
void LittleUInt32(uint32_t &v)
|
||||
{
|
||||
SwapArbitraryLittle<uint32_t, uint32_t>(v);
|
||||
}
|
||||
|
||||
void LittleUInt64(uint64_t &v)
|
||||
{
|
||||
SwapArbitraryLittle<uint64_t, uint64_t>(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
#pragma once
|
||||
#ifndef __PL_BYTESWAP_H__
|
||||
#define __PL_BYTESWAP_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
namespace ByteSwap
|
||||
{
|
||||
void BigInt16(int16_t &v);
|
||||
void BigInt32(int32_t &v);
|
||||
void BigInt64(int64_t &v);
|
||||
void BigUInt16(uint16_t &v);
|
||||
void BigUInt32(uint32_t &v);
|
||||
void BigUInt64(uint64_t &v);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
namespace ByteSwap
|
||||
{
|
||||
void BigInt16(int16_t &v);
|
||||
void BigInt32(int32_t &v);
|
||||
void BigInt64(int64_t &v);
|
||||
void BigUInt16(uint16_t &v);
|
||||
void BigUInt32(uint32_t &v);
|
||||
void BigUInt64(uint64_t &v);
|
||||
|
||||
void LittleInt16(int16_t &v);
|
||||
void LittleInt32(int32_t &v);
|
||||
void LittleInt64(int64_t &v);
|
||||
void LittleUInt16(uint16_t &v);
|
||||
void LittleUInt32(uint32_t &v);
|
||||
void LittleUInt64(uint64_t &v);
|
||||
}
|
||||
}
|
||||
|
||||
83
PortabilityLayer/DeflateCodec.cpp
Normal file
83
PortabilityLayer/DeflateCodec.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include "DeflateCodec.h"
|
||||
|
||||
#include "IOStream.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
static voidpf ZlibAllocShim(voidpf opaque, uInt items, uInt size)
|
||||
{
|
||||
return static_cast<PortabilityLayer::MemoryManager*>(opaque)->Alloc(items * size);
|
||||
}
|
||||
|
||||
void ZlibFreeShim(voidpf opaque, voidpf address)
|
||||
{
|
||||
static_cast<PortabilityLayer::MemoryManager*>(opaque)->Release(address);
|
||||
}
|
||||
}
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
bool DeflateCodec::DecompressStream(IOStream *stream, size_t inSize, void *outBuffer, size_t outSize)
|
||||
{
|
||||
z_stream zstream;
|
||||
zstream.zalloc = ZlibAllocShim;
|
||||
zstream.zfree = ZlibFreeShim;
|
||||
zstream.opaque = MemoryManager::GetInstance();
|
||||
|
||||
if (inflateInit2(&zstream, -15) != Z_OK)
|
||||
return false;
|
||||
|
||||
const size_t bufferSize = 1024;
|
||||
uint8_t buffer[1024];
|
||||
|
||||
zstream.avail_out = outSize;
|
||||
zstream.next_out = static_cast<Bytef*>(outBuffer);
|
||||
zstream.avail_in = 0;
|
||||
zstream.next_in = buffer;
|
||||
|
||||
bool failed = false;
|
||||
for (;;)
|
||||
{
|
||||
if (zstream.avail_in == 0)
|
||||
{
|
||||
const size_t sizeToRead = (bufferSize < inSize) ? bufferSize : inSize;
|
||||
|
||||
if (sizeToRead == 0)
|
||||
{
|
||||
// Ran out of input
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (stream->Read(buffer, sizeToRead) != sizeToRead)
|
||||
{
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
zstream.avail_in = sizeToRead;
|
||||
zstream.next_in = buffer;
|
||||
}
|
||||
|
||||
int result = inflate(&zstream, Z_NO_FLUSH);
|
||||
if (result == Z_STREAM_END)
|
||||
{
|
||||
failed = (zstream.avail_out != 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (result != Z_OK)
|
||||
{
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inflateEnd(&zstream);
|
||||
|
||||
return !failed;
|
||||
}
|
||||
}
|
||||
14
PortabilityLayer/DeflateCodec.h
Normal file
14
PortabilityLayer/DeflateCodec.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
class IOStream;
|
||||
|
||||
class DeflateCodec
|
||||
{
|
||||
public:
|
||||
static bool DecompressStream(IOStream *stream, size_t inSize, void *outBuffer, size_t outSize);
|
||||
};
|
||||
}
|
||||
@@ -59,7 +59,7 @@ namespace PortabilityLayer
|
||||
|
||||
bool FileManagerImpl::FileLocked(VirtualDirectory_t dirID, const PLPasStr &filename)
|
||||
{
|
||||
const char *exts[3] = { ".gpf", ".gpr", ".gpd" };
|
||||
const char *exts[3] = { ".gpf", ".gpa", ".gpd" };
|
||||
|
||||
for (int extIndex = 0; extIndex < sizeof(exts) / sizeof(exts[0]); extIndex++)
|
||||
{
|
||||
@@ -79,7 +79,7 @@ namespace PortabilityLayer
|
||||
{
|
||||
const size_t numExts = 3;
|
||||
|
||||
const char *exts[numExts] = { ".gpr", ".gpd", ".gpf" };
|
||||
const char *exts[numExts] = { ".gpa", ".gpd", ".gpf" };
|
||||
const bool extMayNotExist[numExts] = { true, true, false };
|
||||
|
||||
for (int extIndex = 0; extIndex < numExts; extIndex++)
|
||||
@@ -143,7 +143,7 @@ namespace PortabilityLayer
|
||||
|
||||
PLError_t FileManagerImpl::OpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission permission, IOStream *&outStream)
|
||||
{
|
||||
return OpenFileFork(dirID, filename, ".gpr", permission, outStream);
|
||||
return OpenFileFork(dirID, filename, ".gpa", permission, outStream);
|
||||
}
|
||||
|
||||
bool FileManagerImpl::ReadFileProperties(VirtualDirectory_t dirID, const PLPasStr &filename, MacFileProperties &properties)
|
||||
@@ -170,7 +170,7 @@ namespace PortabilityLayer
|
||||
|
||||
PLError_t FileManagerImpl::RawOpenFileResources(VirtualDirectory_t dirID, const PLPasStr &filename, EFilePermission permission, bool ignoreMeta, GpFileCreationDisposition_t createDisposition, IOStream *&outStream)
|
||||
{
|
||||
return RawOpenFileFork(dirID, filename, ".gpr", permission, ignoreMeta, createDisposition, outStream);
|
||||
return RawOpenFileFork(dirID, filename, ".gpa", permission, ignoreMeta, createDisposition, outStream);
|
||||
}
|
||||
|
||||
bool FileManagerImpl::PromptSaveFile(VirtualDirectory_t dirID, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &initialFileName)
|
||||
|
||||
84
PortabilityLayer/GPArchive.cpp
Normal file
84
PortabilityLayer/GPArchive.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "GPArchive.h"
|
||||
#include "ResTypeID.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static const char *gs_forbiddenNames[] =
|
||||
{
|
||||
"COM1",
|
||||
"COM2",
|
||||
"COM3",
|
||||
"COM4",
|
||||
"COM5",
|
||||
"COM6",
|
||||
"COM7",
|
||||
"COM8",
|
||||
"COM9",
|
||||
"LPT1",
|
||||
"LPT2",
|
||||
"LPT3",
|
||||
"LPT4",
|
||||
"LPT5",
|
||||
"LPT6",
|
||||
"LPT7",
|
||||
"LPT8",
|
||||
"LPT9",
|
||||
};
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
GpArcResourceTypeTag GpArcResourceTypeTag::Encode(const ResTypeID &tag)
|
||||
{
|
||||
static const char *nibbles = "0123456789abcdef";
|
||||
|
||||
char chars[4];
|
||||
tag.ExportAsChars(chars);
|
||||
|
||||
GpArcResourceTypeTag output;
|
||||
memset(&output, 0, sizeof(output));
|
||||
|
||||
char *outChar = output.m_id;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
char c = chars[i];
|
||||
|
||||
bool isForbidden = (c < ' ' || c == '<' || c == '>' || c == ':' || c == '\"' || c == '/' || c == '\\' || c == '|' || c == '?' || c == '*' || c > '~' || c == '$');
|
||||
|
||||
if (i == 3)
|
||||
{
|
||||
if (c == ' ' || c == '.')
|
||||
isForbidden = true;
|
||||
else
|
||||
{
|
||||
for (int fi = 0; fi < sizeof(gs_forbiddenNames) / sizeof(gs_forbiddenNames[0]); fi++)
|
||||
{
|
||||
if (!memcmp(chars, gs_forbiddenNames[fi], 4))
|
||||
{
|
||||
isForbidden = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isForbidden)
|
||||
{
|
||||
uint8_t byteValue;
|
||||
memcpy(&byteValue, &c, 1);
|
||||
|
||||
*outChar++ = '$';
|
||||
int highNibble = (byteValue >> 4) & 0xf;
|
||||
int lowNibble = (byteValue & 0xf);
|
||||
|
||||
*outChar++ = nibbles[highNibble];
|
||||
*outChar++ = nibbles[lowNibble];
|
||||
}
|
||||
else
|
||||
{
|
||||
*outChar++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
13
PortabilityLayer/GPArchive.h
Normal file
13
PortabilityLayer/GPArchive.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
class ResTypeID;
|
||||
|
||||
struct GpArcResourceTypeTag
|
||||
{
|
||||
char m_id[13];
|
||||
|
||||
static GpArcResourceTypeTag Encode(const ResTypeID &tag);
|
||||
};
|
||||
}
|
||||
@@ -1,29 +1,30 @@
|
||||
#pragma once
|
||||
#ifndef __PL_MM_HANDLE_BLOCK_H__
|
||||
#define __PL_MM_HANDLE_BLOCK_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "CoreDefs.h"
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
struct ResourceCompiledRef;
|
||||
|
||||
struct MMHandleBlock
|
||||
{
|
||||
explicit MMHandleBlock(void *contents, size_t size);
|
||||
|
||||
void **AsHandle();
|
||||
|
||||
void *m_contents; // This must be the first field
|
||||
ResourceCompiledRef *m_rmSelfRef;
|
||||
|
||||
size_t m_size;
|
||||
|
||||
private:
|
||||
MMHandleBlock() GP_DELETED;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
#ifndef __PL_MM_HANDLE_BLOCK_H__
|
||||
#define __PL_MM_HANDLE_BLOCK_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "CoreDefs.h"
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
struct ResourceArchiveRef;
|
||||
struct ResourceCompiledRef;
|
||||
|
||||
struct MMHandleBlock
|
||||
{
|
||||
explicit MMHandleBlock(void *contents, size_t size);
|
||||
|
||||
void **AsHandle();
|
||||
|
||||
void *m_contents; // This must be the first field
|
||||
ResourceArchiveRef *m_rmSelfRef;
|
||||
|
||||
size_t m_size;
|
||||
|
||||
private:
|
||||
MMHandleBlock() GP_DELETED;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -515,6 +515,8 @@ namespace PortabilityLayer
|
||||
PortabilityLayer::MemoryManager::GetInstance()->ReleaseHandle(menuPtr->stringBlobHandle);
|
||||
|
||||
menuPtr->stringBlobHandle = newHandle.MMBlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MenuManagerImpl::IsPointInMenuBar(const Vec2i &point) const
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#pragma once
|
||||
#ifndef __PL_BIG_ENDIAN_H__
|
||||
#define __PL_BIG_ENDIAN_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -251,5 +249,3 @@ struct BEFixed32_t
|
||||
BEInt16_t m_intPart;
|
||||
BEUInt16_t m_fracPart;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
245
PortabilityLayer/PLLittleEndian.h
Normal file
245
PortabilityLayer/PLLittleEndian.h
Normal file
@@ -0,0 +1,245 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
template<class T>
|
||||
struct LEInteger
|
||||
{
|
||||
public:
|
||||
LEInteger();
|
||||
LEInteger(const LEInteger<T> &other);
|
||||
explicit LEInteger(T i);
|
||||
|
||||
operator T() const;
|
||||
LEInteger<T> &operator=(T value);
|
||||
|
||||
template<class TOther>
|
||||
LEInteger<T> &operator+=(TOther value);
|
||||
|
||||
template<class TOther>
|
||||
LEInteger<T> &operator-=(TOther value);
|
||||
|
||||
template<class TOther>
|
||||
LEInteger<T> &operator*=(TOther value);
|
||||
|
||||
template<class TOther>
|
||||
LEInteger<T> &operator/=(TOther value);
|
||||
|
||||
template<class TOther>
|
||||
LEInteger<T> &operator%=(TOther value);
|
||||
|
||||
LEInteger<T>& operator--();
|
||||
LEInteger<T> operator--(int);
|
||||
|
||||
LEInteger<T>& operator++();
|
||||
LEInteger<T> operator++(int);
|
||||
|
||||
private:
|
||||
uint8_t m_leValueBytes[sizeof(T)];
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct LEInteger_SwapHelper
|
||||
{
|
||||
};
|
||||
|
||||
#include "ByteSwap.h"
|
||||
|
||||
template<>
|
||||
struct LEInteger_SwapHelper<int16_t>
|
||||
{
|
||||
inline static void Swap(int16_t &v)
|
||||
{
|
||||
PortabilityLayer::ByteSwap::LittleInt16(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct LEInteger_SwapHelper<int32_t>
|
||||
{
|
||||
inline static void Swap(int32_t &v)
|
||||
{
|
||||
PortabilityLayer::ByteSwap::LittleInt32(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct LEInteger_SwapHelper<uint16_t>
|
||||
{
|
||||
inline static void Swap(uint16_t &v)
|
||||
{
|
||||
PortabilityLayer::ByteSwap::LittleUInt16(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct LEInteger_SwapHelper<uint32_t>
|
||||
{
|
||||
inline static void Swap(uint32_t &v)
|
||||
{
|
||||
PortabilityLayer::ByteSwap::LittleUInt32(v);
|
||||
}
|
||||
};
|
||||
|
||||
#include <string.h>
|
||||
|
||||
template<class T>
|
||||
inline LEInteger<T>::LEInteger()
|
||||
{
|
||||
memset(m_leValueBytes, 0, sizeof(T));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline LEInteger<T>::LEInteger(const LEInteger<T> &other)
|
||||
{
|
||||
memcpy(m_leValueBytes, other.m_leValueBytes, sizeof(T));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline LEInteger<T>::LEInteger(T i)
|
||||
{
|
||||
LEInteger_SwapHelper<T>::Swap(i);
|
||||
memcpy(m_leValueBytes, &i, sizeof(T));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline LEInteger<T>::operator T() const
|
||||
{
|
||||
T result;
|
||||
memcpy(&result, m_leValueBytes, sizeof(T));
|
||||
LEInteger_SwapHelper<T>::Swap(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline LEInteger<T> &LEInteger<T>::operator=(T value)
|
||||
{
|
||||
LEInteger_SwapHelper<T>::Swap(value);
|
||||
memcpy(m_leValueBytes, &value, sizeof(T));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<class TOther>
|
||||
LEInteger<T> &LEInteger<T>::operator+=(TOther value)
|
||||
{
|
||||
T storedValue;
|
||||
memcpy(&storedValue, m_leValueBytes, sizeof(T));
|
||||
|
||||
LEInteger_SwapHelper<T>::Swap(storedValue);
|
||||
storedValue += value;
|
||||
LEInteger_SwapHelper<T>::Swap(storedValue);
|
||||
|
||||
memcpy(m_leValueBytes, &storedValue, sizeof(T));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<class TOther>
|
||||
LEInteger<T> &LEInteger<T>::operator-=(TOther value)
|
||||
{
|
||||
T storedValue;
|
||||
memcpy(&storedValue, m_leValueBytes, sizeof(T));
|
||||
|
||||
LEInteger_SwapHelper<T>::Swap(storedValue);
|
||||
storedValue -= value;
|
||||
LEInteger_SwapHelper<T>::Swap(storedValue);
|
||||
|
||||
memcpy(m_leValueBytes, &storedValue, sizeof(T));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<class TOther>
|
||||
LEInteger<T> &LEInteger<T>::operator*=(TOther value)
|
||||
{
|
||||
T storedValue;
|
||||
memcpy(&storedValue, m_leValueBytes, sizeof(T));
|
||||
|
||||
LEInteger_SwapHelper<T>::Swap(storedValue);
|
||||
storedValue *= value;
|
||||
LEInteger_SwapHelper<T>::Swap(storedValue);
|
||||
|
||||
memcpy(m_leValueBytes, &storedValue, sizeof(T));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<class TOther>
|
||||
LEInteger<T> &LEInteger<T>::operator/=(TOther value)
|
||||
{
|
||||
T storedValue;
|
||||
memcpy(&storedValue, m_leValueBytes, sizeof(T));
|
||||
|
||||
LEInteger_SwapHelper<T>::Swap(storedValue);
|
||||
storedValue /= value;
|
||||
LEInteger_SwapHelper<T>::Swap(storedValue);
|
||||
|
||||
memcpy(m_leValueBytes, &storedValue, sizeof(T));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<class TOther>
|
||||
LEInteger<T> &LEInteger<T>::operator%=(TOther value)
|
||||
{
|
||||
T storedValue;
|
||||
memcpy(&storedValue, m_leValueBytes, sizeof(T));
|
||||
|
||||
LEInteger_SwapHelper<T>::Swap(storedValue);
|
||||
storedValue %= value;
|
||||
LEInteger_SwapHelper<T>::Swap(storedValue);
|
||||
|
||||
memcpy(m_leValueBytes, &storedValue, sizeof(T));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
LEInteger<T>& LEInteger<T>::operator--()
|
||||
{
|
||||
T storedValue;
|
||||
memcpy(&storedValue, m_leValueBytes, sizeof(T));
|
||||
|
||||
LEInteger_SwapHelper<T>::Swap(storedValue);
|
||||
storedValue--;
|
||||
LEInteger_SwapHelper<T>::Swap(storedValue);
|
||||
|
||||
memcpy(m_leValueBytes, &storedValue, sizeof(T));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
LEInteger<T> LEInteger<T>::operator--(int)
|
||||
{
|
||||
LEInteger<T> orig(*this);
|
||||
--(*this);
|
||||
return orig;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
LEInteger<T>& LEInteger<T>::operator++()
|
||||
{
|
||||
T storedValue;
|
||||
memcpy(&storedValue, m_leValueBytes, sizeof(T));
|
||||
|
||||
LEInteger_SwapHelper<T>::Swap(storedValue);
|
||||
storedValue++;
|
||||
LEInteger_SwapHelper<T>::Swap(storedValue);
|
||||
|
||||
memcpy(m_leValueBytes, &storedValue, sizeof(T));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
LEInteger<T> LEInteger<T>::operator++(int)
|
||||
{
|
||||
LEInteger<T> orig(*this);
|
||||
++(*this);
|
||||
return orig;
|
||||
}
|
||||
|
||||
|
||||
typedef LEInteger<int16_t> LEInt16_t;
|
||||
typedef LEInteger<int32_t> LEInt32_t;
|
||||
typedef LEInteger<uint16_t> LEUInt16_t;
|
||||
typedef LEInteger<uint32_t> LEUInt32_t;
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "ResourceManager.h"
|
||||
#include "VirtualDirectory.h"
|
||||
#include "FileManager.h"
|
||||
#include "GPArchive.h"
|
||||
#include "HostFileSystem.h"
|
||||
#include "HostMemoryBuffer.h"
|
||||
#include "IOStream.h"
|
||||
@@ -13,12 +14,14 @@
|
||||
#include "ResourceFile.h"
|
||||
#include "PLPasStr.h"
|
||||
#include "PLErrorCodes.h"
|
||||
#include "ZipFileProxy.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
struct MMHandleBlock;
|
||||
class ResourceArchive;
|
||||
|
||||
class ResourceManagerImpl final : public ResourceManager
|
||||
{
|
||||
@@ -30,7 +33,7 @@ namespace PortabilityLayer
|
||||
|
||||
void SetResLoad(bool load) override;
|
||||
|
||||
ResourceFile *LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const override;
|
||||
ResourceArchive *LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const override;
|
||||
short OpenResFork(VirtualDirectory_t virtualDir, const PLPasStr &filename) override;
|
||||
void CloseResFile(short ref) override;
|
||||
PLError_t CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) override;
|
||||
@@ -41,7 +44,7 @@ namespace PortabilityLayer
|
||||
void SetCurrentResFile(short ref) override;
|
||||
|
||||
void DissociateHandle(MMHandleBlock *hdl) const override;
|
||||
const ResourceCompiledRef *ResourceForHandle(MMHandleBlock *hdl) const override;
|
||||
const ResourceArchiveRef *ResourceForHandle(MMHandleBlock *hdl) const override;
|
||||
|
||||
static ResourceManagerImpl *GetInstance();
|
||||
|
||||
@@ -50,10 +53,10 @@ namespace PortabilityLayer
|
||||
{
|
||||
short m_prevFile;
|
||||
short m_nextFile;
|
||||
ResourceFile *m_resourceFile;
|
||||
ResourceArchive *m_resourceArchive;
|
||||
};
|
||||
|
||||
void UnloadAndDestroyResourceFile(ResourceFile *rf);
|
||||
void UnloadAndDestroyResourceFile(ResourceArchive *rf);
|
||||
|
||||
std::vector<ResFileSlot> m_resFiles;
|
||||
short m_firstResFile;
|
||||
@@ -81,8 +84,8 @@ namespace PortabilityLayer
|
||||
{
|
||||
for (std::vector<ResFileSlot>::iterator it = m_resFiles.begin(), itEnd = m_resFiles.end(); it != itEnd; ++it)
|
||||
{
|
||||
if (it->m_resourceFile)
|
||||
UnloadAndDestroyResourceFile(it->m_resourceFile);
|
||||
if (it->m_resourceArchive)
|
||||
UnloadAndDestroyResourceFile(it->m_resourceArchive);
|
||||
}
|
||||
|
||||
m_resFiles.clear();
|
||||
@@ -106,32 +109,13 @@ namespace PortabilityLayer
|
||||
hdl->m_rmSelfRef = nullptr;
|
||||
}
|
||||
|
||||
const ResourceCompiledRef *ResourceManagerImpl::ResourceForHandle(MMHandleBlock *hdl) const
|
||||
const ResourceArchiveRef *ResourceManagerImpl::ResourceForHandle(MMHandleBlock *hdl) const
|
||||
{
|
||||
return hdl->m_rmSelfRef;
|
||||
}
|
||||
|
||||
void ResourceManagerImpl::UnloadAndDestroyResourceFile(ResourceFile *rf)
|
||||
void ResourceManagerImpl::UnloadAndDestroyResourceFile(ResourceArchive *rf)
|
||||
{
|
||||
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
||||
|
||||
ResourceCompiledTypeList *rtls = nullptr;
|
||||
size_t numRTLs = 0;
|
||||
rf->GetAllResourceTypeLists(rtls, numRTLs);
|
||||
|
||||
for (size_t i = 0; i < numRTLs; i++)
|
||||
{
|
||||
const ResourceCompiledTypeList &rtl = rtls[i];
|
||||
|
||||
const size_t numRefs = rtl.m_numRefs;
|
||||
for (size_t r = 0; r < numRefs; r++)
|
||||
{
|
||||
const ResourceCompiledRef &ref = rtl.m_firstRef[r];
|
||||
if (MMHandleBlock *hdl = ref.m_handle)
|
||||
mm->ReleaseHandle(hdl);
|
||||
}
|
||||
}
|
||||
|
||||
rf->Destroy();
|
||||
}
|
||||
|
||||
@@ -145,26 +129,28 @@ namespace PortabilityLayer
|
||||
m_load = load;
|
||||
}
|
||||
|
||||
ResourceFile *ResourceManagerImpl::LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const
|
||||
ResourceArchive *ResourceManagerImpl::LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const
|
||||
{
|
||||
IOStream *fStream = nullptr;
|
||||
if (FileManager::GetInstance()->RawOpenFileResources(virtualDir, filename, EFilePermission_Read, true, GpFileCreationDispositions::kOpenExisting, fStream) != PLErrors::kNone)
|
||||
return nullptr;
|
||||
|
||||
ResourceFile *resFile = ResourceFile::Create();
|
||||
if (!resFile)
|
||||
return nullptr;
|
||||
|
||||
bool loaded = resFile->Load(fStream);
|
||||
fStream->Close();
|
||||
|
||||
if (!loaded)
|
||||
ZipFileProxy *proxy = ZipFileProxy::Create(fStream);
|
||||
if (!proxy)
|
||||
{
|
||||
resFile->Destroy();
|
||||
fStream->Close();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return resFile;
|
||||
ResourceArchive *archive = ResourceArchive::Create(proxy, fStream);
|
||||
if (!archive)
|
||||
{
|
||||
proxy->Destroy();
|
||||
fStream->Close();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return archive;
|
||||
}
|
||||
|
||||
short ResourceManagerImpl::OpenResFork(VirtualDirectory_t virtualDir, const PLPasStr &filename)
|
||||
@@ -174,7 +160,7 @@ namespace PortabilityLayer
|
||||
|
||||
for (size_t i = 0; i < numSlots; i++)
|
||||
{
|
||||
if (m_resFiles[i].m_resourceFile == nullptr)
|
||||
if (m_resFiles[i].m_resourceArchive == nullptr)
|
||||
{
|
||||
resFileIndex = i;
|
||||
break;
|
||||
@@ -185,13 +171,13 @@ namespace PortabilityLayer
|
||||
return -1;
|
||||
|
||||
|
||||
ResourceFile *resFile = LoadResFile(virtualDir, filename);
|
||||
ResourceArchive *resFile = LoadResFile(virtualDir, filename);
|
||||
|
||||
if (!resFile)
|
||||
return -1;
|
||||
|
||||
ResFileSlot slot;
|
||||
slot.m_resourceFile = resFile;
|
||||
slot.m_resourceArchive = resFile;
|
||||
slot.m_prevFile = m_lastResFile;
|
||||
slot.m_nextFile = -1;
|
||||
|
||||
@@ -218,10 +204,10 @@ namespace PortabilityLayer
|
||||
{
|
||||
ResFileSlot &slot = m_resFiles[ref];
|
||||
|
||||
assert(slot.m_resourceFile != nullptr);
|
||||
assert(slot.m_resourceArchive != nullptr);
|
||||
|
||||
slot.m_resourceFile->Destroy();
|
||||
slot.m_resourceFile = nullptr;
|
||||
slot.m_resourceArchive->Destroy();
|
||||
slot.m_resourceArchive = nullptr;
|
||||
|
||||
if (m_lastResFile == ref)
|
||||
m_lastResFile = slot.m_prevFile;
|
||||
@@ -272,9 +258,9 @@ namespace PortabilityLayer
|
||||
while (searchIndex >= 0)
|
||||
{
|
||||
const ResFileSlot& slot = m_resFiles[searchIndex];
|
||||
assert(slot.m_resourceFile);
|
||||
assert(slot.m_resourceArchive);
|
||||
|
||||
THandle<void> resHdl = slot.m_resourceFile->GetResource(resType, id, m_load);
|
||||
THandle<void> resHdl = slot.m_resourceArchive->GetResource(resType, id, m_load);
|
||||
if (resHdl != nullptr)
|
||||
return resHdl;
|
||||
|
||||
@@ -284,8 +270,122 @@ namespace PortabilityLayer
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
ResourceManagerImpl ResourceManagerImpl::ms_instance;
|
||||
|
||||
ResourceManager *ResourceManager::GetInstance() { return ResourceManagerImpl::GetInstance(); }
|
||||
|
||||
// ===========================================================================================
|
||||
|
||||
ResourceArchiveRef::ResourceArchiveRef()
|
||||
: m_handle(nullptr)
|
||||
, m_size(0)
|
||||
, m_resID(0)
|
||||
{
|
||||
}
|
||||
|
||||
ResourceArchive *ResourceArchive::Create(ZipFileProxy *zipFileProxy, IOStream *stream)
|
||||
{
|
||||
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
||||
|
||||
size_t numFiles = zipFileProxy->NumFiles();
|
||||
|
||||
ResourceArchiveRef *refs = static_cast<ResourceArchiveRef*>(mm->Alloc(sizeof(ResourceArchiveRef) * numFiles));
|
||||
if (!refs)
|
||||
return nullptr;
|
||||
|
||||
for (size_t i = 0; i < numFiles; i++)
|
||||
new (refs + i) ResourceArchiveRef();
|
||||
|
||||
void *storage = mm->Alloc(sizeof(ResourceArchive));
|
||||
if (!storage)
|
||||
{
|
||||
mm->Release(refs);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new (storage) ResourceArchive(zipFileProxy, stream, refs);
|
||||
}
|
||||
|
||||
void ResourceArchive::Destroy()
|
||||
{
|
||||
this->~ResourceArchive();
|
||||
PortabilityLayer::MemoryManager::GetInstance()->Release(this);
|
||||
}
|
||||
|
||||
THandle<void> ResourceArchive::GetResource(const ResTypeID &resTypeID, int id, bool load)
|
||||
{
|
||||
const char *extension = ".bin";
|
||||
char resourceFile[64];
|
||||
|
||||
GpArcResourceTypeTag resTag = GpArcResourceTypeTag::Encode(resTypeID);
|
||||
|
||||
snprintf(resourceFile, sizeof(resourceFile) - 1, "%s/%i%s", resTag.m_id, id, extension);
|
||||
|
||||
size_t index = 0;
|
||||
if (!m_zipFileProxy->IndexFile(resourceFile, index))
|
||||
return THandle<void>();
|
||||
|
||||
ResourceArchiveRef *ref = m_resourceHandles + index;
|
||||
|
||||
MMHandleBlock *handle = nullptr;
|
||||
if (ref->m_handle != nullptr)
|
||||
handle = ref->m_handle;
|
||||
else
|
||||
{
|
||||
handle = MemoryManager::GetInstance()->AllocHandle(0);
|
||||
if (!handle)
|
||||
return THandle<void>();
|
||||
|
||||
handle->m_rmSelfRef = ref;
|
||||
ref->m_handle = handle;
|
||||
ref->m_resID = static_cast<int16_t>(id);
|
||||
ref->m_size = m_zipFileProxy->GetFileSize(index);
|
||||
}
|
||||
|
||||
if (handle->m_contents == nullptr && load)
|
||||
{
|
||||
if (ref->m_size > 0)
|
||||
{
|
||||
void *contents = MemoryManager::GetInstance()->Alloc(ref->m_size);
|
||||
handle->m_contents = contents;
|
||||
handle->m_size = ref->m_size;
|
||||
|
||||
if (!m_zipFileProxy->LoadFile(index, contents))
|
||||
{
|
||||
MemoryManager::GetInstance()->Release(contents);
|
||||
handle->m_contents = nullptr;
|
||||
handle->m_size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return THandle<void>(handle);
|
||||
}
|
||||
|
||||
ResourceArchive::ResourceArchive(ZipFileProxy *zipFileProxy, IOStream *stream, ResourceArchiveRef *resourceHandles)
|
||||
: m_zipFileProxy(zipFileProxy)
|
||||
, m_stream(stream)
|
||||
, m_resourceHandles(resourceHandles)
|
||||
{
|
||||
}
|
||||
|
||||
ResourceArchive::~ResourceArchive()
|
||||
{
|
||||
MemoryManager *mm = MemoryManager::GetInstance();
|
||||
|
||||
const size_t numFiles = m_zipFileProxy->NumFiles();
|
||||
for (size_t i = 0; i < numFiles; i++)
|
||||
{
|
||||
ResourceArchiveRef &ref = m_resourceHandles[numFiles - 1 - i];
|
||||
if (ref.m_handle)
|
||||
mm->ReleaseHandle(ref.m_handle);
|
||||
|
||||
ref.~ResourceArchiveRef();
|
||||
}
|
||||
|
||||
mm->Release(m_resourceHandles);
|
||||
|
||||
m_zipFileProxy->Destroy();
|
||||
m_stream->Close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,8 +53,8 @@ void SetResLoad(Boolean load)
|
||||
long GetMaxResourceSize(Handle res)
|
||||
{
|
||||
const PortabilityLayer::MMHandleBlock *hBlock = res.MMBlock();
|
||||
const PortabilityLayer::ResourceCompiledRef *resRef = hBlock->m_rmSelfRef;
|
||||
return resRef->GetSize();
|
||||
const PortabilityLayer::ResourceArchiveRef *resRef = hBlock->m_rmSelfRef;
|
||||
return resRef->m_size;
|
||||
}
|
||||
|
||||
short HOpenResFile(PortabilityLayer::VirtualDirectory_t dirID, const PLPasStr &name, int permissions)
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
<Import Project="..\GpCommon.props" />
|
||||
<Import Project="..\stb.props" />
|
||||
<Import Project="..\MacRomanConversion.props" />
|
||||
<Import Project="..\zlib.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
@@ -69,6 +70,7 @@
|
||||
<Import Project="..\GpCommon.props" />
|
||||
<Import Project="..\stb.props" />
|
||||
<Import Project="..\MacRomanConversion.props" />
|
||||
<Import Project="..\zlib.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
@@ -76,6 +78,7 @@
|
||||
<Import Project="..\GpCommon.props" />
|
||||
<Import Project="..\stb.props" />
|
||||
<Import Project="..\MacRomanConversion.props" />
|
||||
<Import Project="..\zlib.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
@@ -83,6 +86,7 @@
|
||||
<Import Project="..\GpCommon.props" />
|
||||
<Import Project="..\stb.props" />
|
||||
<Import Project="..\MacRomanConversion.props" />
|
||||
<Import Project="..\zlib.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
@@ -136,12 +140,14 @@
|
||||
<ClInclude Include="AEManager.h" />
|
||||
<ClInclude Include="BinarySearch.h" />
|
||||
<ClInclude Include="BinHex4.h" />
|
||||
<ClInclude Include="BMPFormat.h" />
|
||||
<ClInclude Include="BytePack.h" />
|
||||
<ClInclude Include="ByteSwap.h" />
|
||||
<ClInclude Include="ByteUnpack.h" />
|
||||
<ClInclude Include="CFileStream.h" />
|
||||
<ClInclude Include="ClientAudioChannelContext.h" />
|
||||
<ClInclude Include="DataTypes.h" />
|
||||
<ClInclude Include="DeflateCodec.h" />
|
||||
<ClInclude Include="DialogManager.h" />
|
||||
<ClInclude Include="DisplayDeviceManager.h" />
|
||||
<ClInclude Include="EllipsePlotter.h" />
|
||||
@@ -152,6 +158,7 @@
|
||||
<ClInclude Include="FontManager.h" />
|
||||
<ClInclude Include="FontRenderer.h" />
|
||||
<ClInclude Include="GpAppInterface.h" />
|
||||
<ClInclude Include="GPArchive.h" />
|
||||
<ClInclude Include="HostAudioChannel.h" />
|
||||
<ClInclude Include="HostAudioDriver.h" />
|
||||
<ClInclude Include="HostDirectoryCursor.h" />
|
||||
@@ -206,10 +213,12 @@
|
||||
<ClInclude Include="PLImageWidget.h" />
|
||||
<ClInclude Include="PLInvisibleWidget.h" />
|
||||
<ClInclude Include="PLLabelWidget.h" />
|
||||
<ClInclude Include="PLLittleEndian.h" />
|
||||
<ClInclude Include="PLPopupMenuWidget.h" />
|
||||
<ClInclude Include="PLRadioButtonWidget.h" />
|
||||
<ClInclude Include="PLScrollBarWidget.h" />
|
||||
<ClInclude Include="PLWidgets.h" />
|
||||
<ClInclude Include="ZipFileProxy.h" />
|
||||
<ClInclude Include="SimpleImage.h" />
|
||||
<ClInclude Include="PLKeyEncoding.h" />
|
||||
<ClInclude Include="PLMacTypes.h" />
|
||||
@@ -271,9 +280,11 @@
|
||||
<ClInclude Include="ScopedPtr.h" />
|
||||
<ClInclude Include="SmallestInt.h" />
|
||||
<ClInclude Include="UnsafePascalStr.h" />
|
||||
<ClInclude Include="WaveFormat.h" />
|
||||
<ClInclude Include="WindowDef.h" />
|
||||
<ClInclude Include="WindowManager.h" />
|
||||
<ClInclude Include="XModemCRC.h" />
|
||||
<ClInclude Include="ZipFile.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\stb\stb_image_write.c" />
|
||||
@@ -281,6 +292,7 @@
|
||||
<ClCompile Include="BinHex4.cpp" />
|
||||
<ClCompile Include="ByteSwap.cpp" />
|
||||
<ClCompile Include="CFileStream.cpp" />
|
||||
<ClCompile Include="DeflateCodec.cpp" />
|
||||
<ClCompile Include="DialogManager.cpp" />
|
||||
<ClCompile Include="DisplayDeviceManager.cpp" />
|
||||
<ClCompile Include="EllipsePlotter.cpp" />
|
||||
@@ -288,6 +300,7 @@
|
||||
<ClCompile Include="FontFamily.cpp" />
|
||||
<ClCompile Include="FontManager.cpp" />
|
||||
<ClCompile Include="FontRenderer.cpp" />
|
||||
<ClCompile Include="GPArchive.cpp" />
|
||||
<ClCompile Include="HostAudioDriver.cpp" />
|
||||
<ClCompile Include="HostDisplayDriver.cpp" />
|
||||
<ClCompile Include="HostFileSystem.cpp" />
|
||||
@@ -359,11 +372,15 @@
|
||||
<ClCompile Include="WindowDef.cpp" />
|
||||
<ClCompile Include="WindowManager.cpp" />
|
||||
<ClCompile Include="XModemCRC.cpp" />
|
||||
<ClCompile Include="ZipFileProxy.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MacRomanConversion\MacRomanConversion.vcxproj">
|
||||
<Project>{07351a8e-1f79-42c9-bbab-31f071eaa99e}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\zlib\zlib.vcxproj">
|
||||
<Project>{6ae5c85e-6631-4a12-97a0-a05f812fe9ca}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
@@ -444,6 +444,27 @@
|
||||
<ClInclude Include="PLRadioButtonWidget.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ZipFile.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PLLittleEndian.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GPArchive.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BMPFormat.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WaveFormat.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ZipFileProxy.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DeflateCodec.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CFileStream.cpp">
|
||||
@@ -695,5 +716,14 @@
|
||||
<ClCompile Include="PLKeyEncoding.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GPArchive.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ZipFileProxy.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DeflateCodec.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -9,7 +9,6 @@ namespace PortabilityLayer
|
||||
struct ResourceCompiledRef
|
||||
{
|
||||
const uint8_t *m_resData;
|
||||
MMHandleBlock *m_handle;
|
||||
int16_t m_resID;
|
||||
int16_t m_resNameOffset;
|
||||
uint8_t m_attributes;
|
||||
|
||||
@@ -233,7 +233,6 @@ namespace PortabilityLayer
|
||||
refToCompile->m_resData = m_resDataBlob + dataOffset;
|
||||
refToCompile->m_resID = refListEntry.m_resID;
|
||||
refToCompile->m_resNameOffset = refListEntry.m_resourceNameOffset;
|
||||
refToCompile->m_handle = nullptr;
|
||||
|
||||
uint32_t resSize;
|
||||
memcpy(&resSize, m_resDataBlob + dataSizeOffset, 4);
|
||||
@@ -356,7 +355,7 @@ namespace PortabilityLayer
|
||||
return tl;
|
||||
}
|
||||
|
||||
THandle<void> ResourceFile::GetResource(const ResTypeID &resType, int id, bool load)
|
||||
THandle<void> ResourceFile::LoadResource(const ResTypeID &resType, int id)
|
||||
{
|
||||
const ResourceCompiledTypeList *tl = GetResourceTypeList(resType);
|
||||
if (tl == nullptr)
|
||||
@@ -369,26 +368,15 @@ namespace PortabilityLayer
|
||||
if (ref == refEnd)
|
||||
return THandle<void>();
|
||||
|
||||
MMHandleBlock *handle = nullptr;
|
||||
if (ref->m_handle != nullptr)
|
||||
handle = ref->m_handle;
|
||||
else
|
||||
{
|
||||
handle = MemoryManager::GetInstance()->AllocHandle(0);
|
||||
handle->m_rmSelfRef = ref;
|
||||
ref->m_handle = handle;
|
||||
}
|
||||
MMHandleBlock *handle = MemoryManager::GetInstance()->AllocHandle(0);
|
||||
|
||||
if (handle->m_contents == nullptr && load)
|
||||
const uint32_t resSize = ref->GetSize();
|
||||
if (resSize > 0)
|
||||
{
|
||||
const uint32_t resSize = ref->GetSize();
|
||||
if (resSize > 0)
|
||||
{
|
||||
void *contents = MemoryManager::GetInstance()->Alloc(resSize);
|
||||
handle->m_contents = contents;
|
||||
handle->m_size = resSize;
|
||||
memcpy(handle->m_contents, ref->m_resData, resSize);
|
||||
}
|
||||
void *contents = MemoryManager::GetInstance()->Alloc(resSize);
|
||||
handle->m_contents = contents;
|
||||
handle->m_size = resSize;
|
||||
memcpy(handle->m_contents, ref->m_resData, resSize);
|
||||
}
|
||||
|
||||
return THandle<void>(handle);
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace PortabilityLayer
|
||||
struct ResourceCompiledTypeList;
|
||||
class ResTypeID;
|
||||
|
||||
class ResourceFile
|
||||
class ResourceFile final
|
||||
{
|
||||
public:
|
||||
bool Load(IOStream *stream);
|
||||
@@ -21,7 +21,7 @@ namespace PortabilityLayer
|
||||
void GetAllResourceTypeLists(ResourceCompiledTypeList *&outTypeLists, size_t &outCount) const;
|
||||
|
||||
const ResourceCompiledTypeList *GetResourceTypeList(const ResTypeID &resType);
|
||||
THandle<void> GetResource(const ResTypeID &resType, int id, bool load);
|
||||
THandle<void> LoadResource(const ResTypeID &resType, int id);
|
||||
|
||||
static ResourceFile *Create();
|
||||
void Destroy();
|
||||
|
||||
@@ -8,10 +8,38 @@ class PLPasStr;
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
class IOStream;
|
||||
struct MMHandleBlock;
|
||||
struct ResourceCompiledRef;
|
||||
class ResourceFile;
|
||||
class ResTypeID;
|
||||
class ZipFileProxy;
|
||||
|
||||
struct ResourceArchiveRef
|
||||
{
|
||||
ResourceArchiveRef();
|
||||
|
||||
MMHandleBlock *m_handle;
|
||||
size_t m_size;
|
||||
int16_t m_resID;
|
||||
};
|
||||
|
||||
class ResourceArchive final
|
||||
{
|
||||
public:
|
||||
static ResourceArchive *Create(ZipFileProxy *zipFileProxy, IOStream *stream);
|
||||
void Destroy();
|
||||
|
||||
THandle<void> GetResource(const ResTypeID &resTypeID, int id, bool load);
|
||||
|
||||
private:
|
||||
ResourceArchive(ZipFileProxy *zipFileProxy, IOStream *stream, ResourceArchiveRef *resourceHandles);
|
||||
~ResourceArchive();
|
||||
|
||||
ZipFileProxy *m_zipFileProxy;
|
||||
IOStream *m_stream;
|
||||
ResourceArchiveRef *m_resourceHandles;
|
||||
};
|
||||
|
||||
class ResourceManager
|
||||
{
|
||||
@@ -21,7 +49,7 @@ namespace PortabilityLayer
|
||||
|
||||
virtual void SetResLoad(bool load) = 0;
|
||||
|
||||
virtual ResourceFile *LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const = 0;
|
||||
virtual ResourceArchive *LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const = 0;
|
||||
virtual short OpenResFork(VirtualDirectory_t virtualDir, const PLPasStr &filename) = 0;
|
||||
virtual void CloseResFile(short ref) = 0;
|
||||
virtual PLError_t CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) = 0;
|
||||
@@ -32,7 +60,7 @@ namespace PortabilityLayer
|
||||
virtual void SetCurrentResFile(short ref) = 0;
|
||||
|
||||
virtual void DissociateHandle(MMHandleBlock *hdl) const = 0;
|
||||
virtual const ResourceCompiledRef *ResourceForHandle(MMHandleBlock *hdl) const = 0;
|
||||
virtual const ResourceArchiveRef *ResourceForHandle(MMHandleBlock *hdl) const = 0;
|
||||
|
||||
static ResourceManager *GetInstance();
|
||||
};
|
||||
|
||||
46
PortabilityLayer/WaveFormat.h
Normal file
46
PortabilityLayer/WaveFormat.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "PLLittleEndian.h"
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
namespace WaveConstants
|
||||
{
|
||||
static const uint16_t kFormatPCM = 1;
|
||||
static const uint32_t kRiffChunkID = 0x46464952;
|
||||
static const uint32_t kWaveChunkID = 0x45564157;
|
||||
static const uint32_t kFormatChunkID = 0x20746d66;
|
||||
static const uint32_t kDataChunkID = 0x61746164;
|
||||
}
|
||||
|
||||
struct RIFFTag
|
||||
{
|
||||
LEUInt32_t m_tag;
|
||||
LEUInt32_t m_chunkSize; // Actual size is padded to 2-byte alignment
|
||||
};
|
||||
|
||||
struct WaveFormatChunkV1
|
||||
{
|
||||
LEUInt16_t m_formatCode;
|
||||
LEUInt16_t m_numChannels;
|
||||
LEUInt32_t m_sampleRate;
|
||||
LEUInt32_t m_bytesPerSecond;
|
||||
LEUInt16_t m_blockAlignmentBytes;
|
||||
LEUInt16_t m_bitsPerSample;
|
||||
};
|
||||
|
||||
struct WaveFormatChunkV2
|
||||
{
|
||||
WaveFormatChunkV1 m_v1;
|
||||
LEUInt16_t m_extSize;
|
||||
};
|
||||
|
||||
struct WaveFormatChunkV3
|
||||
{
|
||||
WaveFormatChunkV2 m_v2;
|
||||
|
||||
LEUInt16_t m_validBitsPerSample;
|
||||
LEUInt32_t m_channelMask;
|
||||
uint8_t m_subFormatGUID[16];
|
||||
};
|
||||
}
|
||||
81
PortabilityLayer/ZipFile.h
Normal file
81
PortabilityLayer/ZipFile.h
Normal file
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
#include "PLLittleEndian.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
namespace ZipConstants
|
||||
{
|
||||
static const uint16_t kStoredRequiredVersion = 10;
|
||||
static const uint16_t kDirectoryRequiredVersion = 20;
|
||||
static const uint16_t kCompressedRequiredVersion = 20;
|
||||
|
||||
static const uint32_t kDirectoryAttributes = 0x0010;
|
||||
static const uint32_t kArchivedAttributes = 0x0020;
|
||||
|
||||
static const uint16_t kStoredMethod = 0x0000;
|
||||
static const uint16_t kDeflatedMethod = 0x0008;
|
||||
}
|
||||
|
||||
struct ZipFileLocalHeader
|
||||
{
|
||||
static const uint32_t kSignature = 0x04034b50;
|
||||
|
||||
LEUInt32_t m_signature;
|
||||
LEUInt16_t m_versionRequired;
|
||||
LEUInt16_t m_flags;
|
||||
LEUInt16_t m_method;
|
||||
LEUInt16_t m_modificationTime;
|
||||
LEUInt16_t m_modificationDate;
|
||||
LEUInt32_t m_crc;
|
||||
LEUInt32_t m_compressedSize;
|
||||
LEUInt32_t m_uncompressedSize;
|
||||
LEUInt16_t m_fileNameLength;
|
||||
LEUInt16_t m_extraFieldLength;
|
||||
};
|
||||
|
||||
struct ZipCentralDirectoryFileHeader
|
||||
{
|
||||
static const uint32_t kSignature = 0x02014b50;
|
||||
|
||||
LEUInt32_t m_signature;
|
||||
LEUInt16_t m_versionCreated;
|
||||
LEUInt16_t m_versionRequired;
|
||||
LEUInt16_t m_flags;
|
||||
LEUInt16_t m_method;
|
||||
LEUInt16_t m_modificationTime;
|
||||
LEUInt16_t m_modificationDate;
|
||||
LEUInt32_t m_crc;
|
||||
LEUInt32_t m_compressedSize;
|
||||
LEUInt32_t m_uncompressedSize;
|
||||
LEUInt16_t m_fileNameLength;
|
||||
LEUInt16_t m_extraFieldLength;
|
||||
LEUInt16_t m_commentLength;
|
||||
LEUInt16_t m_diskNumber;
|
||||
LEUInt16_t m_internalAttributes;
|
||||
LEUInt32_t m_externalAttributes;
|
||||
LEUInt32_t m_localHeaderOffset;
|
||||
|
||||
// File name
|
||||
// Extra field
|
||||
// File comment
|
||||
};
|
||||
|
||||
struct ZipEndOfCentralDirectoryRecord
|
||||
{
|
||||
static const uint32_t kSignature = 0x06054b50;
|
||||
|
||||
LEUInt32_t m_signature;
|
||||
LEUInt16_t m_thisDiskNumber;
|
||||
LEUInt16_t m_centralDirDisk;
|
||||
LEUInt16_t m_numCentralDirRecordsThisDisk;
|
||||
LEUInt16_t m_numCentralDirRecords;
|
||||
LEUInt32_t m_centralDirectorySizeBytes;
|
||||
LEUInt32_t m_centralDirStartOffset;
|
||||
LEUInt16_t m_commentLength;
|
||||
|
||||
// Comment
|
||||
};
|
||||
}
|
||||
287
PortabilityLayer/ZipFileProxy.cpp
Normal file
287
PortabilityLayer/ZipFileProxy.cpp
Normal file
@@ -0,0 +1,287 @@
|
||||
#include "ZipFileProxy.h"
|
||||
|
||||
#include "BinarySearch.h"
|
||||
#include "IOStream.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "ZipFile.h"
|
||||
|
||||
#include "DeflateCodec.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
static int ZipDirectorySearchPredicate(const char *path, PortabilityLayer::ZipCentralDirectoryFileHeader *item)
|
||||
{
|
||||
const uint16_t fnameLength = item->m_fileNameLength;
|
||||
const char *itemPath = reinterpret_cast<const char*>(item) + sizeof(PortabilityLayer::ZipCentralDirectoryFileHeader);
|
||||
|
||||
for (size_t i = 0; i < fnameLength; i++)
|
||||
{
|
||||
const uint8_t pathC = static_cast<uint8_t>(path[i] & 0xff);
|
||||
|
||||
if (pathC == 0)
|
||||
return -1;
|
||||
|
||||
const uint8_t itemC = static_cast<uint8_t>(itemPath[i] & 0xff);
|
||||
|
||||
if (pathC < itemC)
|
||||
return -1;
|
||||
if (pathC > itemC)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (path[fnameLength] == 0)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ZipDirectorySortPredicate(const void *a, const void *b)
|
||||
{
|
||||
const PortabilityLayer::ZipCentralDirectoryFileHeader *typedA = *static_cast<PortabilityLayer::ZipCentralDirectoryFileHeader *const*>(a);
|
||||
const PortabilityLayer::ZipCentralDirectoryFileHeader *typedB = *static_cast<PortabilityLayer::ZipCentralDirectoryFileHeader *const*>(b);
|
||||
|
||||
const uint16_t lenA = typedA->m_fileNameLength;
|
||||
const uint16_t lenB = typedB->m_fileNameLength;
|
||||
|
||||
const char *pathA = reinterpret_cast<const char*>(typedA) + sizeof(PortabilityLayer::ZipCentralDirectoryFileHeader);
|
||||
const char *pathB = reinterpret_cast<const char*>(typedB) + sizeof(PortabilityLayer::ZipCentralDirectoryFileHeader);
|
||||
|
||||
const size_t shorterLength = (lenA < lenB) ? lenA : lenB;
|
||||
|
||||
for (size_t i = 0; i < shorterLength; i++)
|
||||
{
|
||||
const uint8_t ca = static_cast<uint8_t>(pathA[i] & 0xff);
|
||||
const uint8_t cb = static_cast<uint8_t>(pathB[i] & 0xff);
|
||||
|
||||
if (ca < cb)
|
||||
return -1;
|
||||
if (ca > cb)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lenA < lenB)
|
||||
return -1;
|
||||
if (lenA > lenB)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool CheckAndFixFileName(uint8_t *fname, size_t length)
|
||||
{
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
if (fname[i] == '\\')
|
||||
fname[i] = '/';
|
||||
else if (fname[i] == 0)
|
||||
return false; // Illegal null in file path, illegal
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
void ZipFileProxy::Destroy()
|
||||
{
|
||||
MemoryManager *mm = MemoryManager::GetInstance();
|
||||
|
||||
this->~ZipFileProxy();
|
||||
mm->Release(this);
|
||||
}
|
||||
|
||||
bool ZipFileProxy::IndexFile(const char *path, size_t &outIndex) const
|
||||
{
|
||||
PortabilityLayer::ZipCentralDirectoryFileHeader **indexLoc = BinarySearch(m_sortedFiles, m_sortedFiles + m_numFiles, path, ZipDirectorySearchPredicate);
|
||||
const size_t index = static_cast<size_t>(indexLoc - m_sortedFiles);
|
||||
|
||||
if (index == m_numFiles)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
outIndex = index;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ZipFileProxy::LoadFile(size_t index, void *outBuffer)
|
||||
{
|
||||
ZipCentralDirectoryFileHeader *centralDirHeader = m_sortedFiles[index];
|
||||
|
||||
if (!m_stream->SeekStart(centralDirHeader->m_localHeaderOffset))
|
||||
return false;
|
||||
|
||||
ZipFileLocalHeader localHeader;
|
||||
if (m_stream->Read(&localHeader, sizeof(ZipFileLocalHeader)) != sizeof(ZipFileLocalHeader))
|
||||
return false;
|
||||
|
||||
if (!m_stream->SeekCurrent(localHeader.m_fileNameLength + localHeader.m_extraFieldLength))
|
||||
return false;
|
||||
|
||||
if (localHeader.m_compressedSize != centralDirHeader->m_compressedSize || localHeader.m_uncompressedSize != centralDirHeader->m_uncompressedSize || localHeader.m_method != centralDirHeader->m_method)
|
||||
return false;
|
||||
|
||||
const size_t uncompressedSize = centralDirHeader->m_uncompressedSize;
|
||||
if (localHeader.m_method == PortabilityLayer::ZipConstants::kStoredMethod)
|
||||
return m_stream->Read(outBuffer, uncompressedSize) == uncompressedSize;
|
||||
else if (localHeader.m_method == PortabilityLayer::ZipConstants::kDeflatedMethod)
|
||||
{
|
||||
const size_t compressedSize = centralDirHeader->m_compressedSize;
|
||||
|
||||
return DeflateCodec::DecompressStream(m_stream, compressedSize, outBuffer, uncompressedSize);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t ZipFileProxy::NumFiles() const
|
||||
{
|
||||
return m_numFiles;
|
||||
}
|
||||
|
||||
size_t ZipFileProxy::GetFileSize(size_t index) const
|
||||
{
|
||||
return m_sortedFiles[index]->m_uncompressedSize;
|
||||
}
|
||||
|
||||
ZipFileProxy *ZipFileProxy::Create(IOStream *stream)
|
||||
{
|
||||
MemoryManager *mm = MemoryManager::GetInstance();
|
||||
|
||||
if (!stream->SeekEnd(sizeof(ZipEndOfCentralDirectoryRecord)))
|
||||
return nullptr;
|
||||
|
||||
ZipEndOfCentralDirectoryRecord eocd;
|
||||
if (stream->Read(&eocd, sizeof(eocd)) != sizeof(eocd))
|
||||
return nullptr;
|
||||
|
||||
if (eocd.m_signature != ZipEndOfCentralDirectoryRecord::kSignature)
|
||||
return nullptr;
|
||||
|
||||
if (!stream->SeekStart(eocd.m_centralDirStartOffset))
|
||||
return nullptr;
|
||||
|
||||
const size_t centralDirSize = eocd.m_centralDirectorySizeBytes;
|
||||
void *centralDirImage = mm->Alloc(centralDirSize);
|
||||
if (!centralDirImage)
|
||||
return nullptr;
|
||||
|
||||
const size_t numFiles = eocd.m_numCentralDirRecords;
|
||||
|
||||
ZipCentralDirectoryFileHeader **centralDirFiles = static_cast<ZipCentralDirectoryFileHeader **>(mm->Alloc(sizeof(ZipCentralDirectoryFileHeader*) * numFiles));
|
||||
if (!centralDirFiles)
|
||||
{
|
||||
mm->Release(centralDirImage);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (stream->Read(centralDirImage, centralDirSize) != centralDirSize)
|
||||
{
|
||||
mm->Release(centralDirFiles);
|
||||
mm->Release(centralDirImage);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool failed = false;
|
||||
|
||||
uint8_t *const centralDirStart = static_cast<uint8_t*>(centralDirImage);
|
||||
uint8_t *const centralDirEnd = centralDirStart + centralDirSize;
|
||||
uint8_t *centralDirCursor = centralDirStart;
|
||||
|
||||
for (size_t i = 0; i < numFiles; i++)
|
||||
{
|
||||
if (centralDirEnd - centralDirCursor < sizeof(ZipCentralDirectoryFileHeader))
|
||||
{
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
ZipCentralDirectoryFileHeader *centralDirHeader = reinterpret_cast<ZipCentralDirectoryFileHeader*>(centralDirCursor);
|
||||
centralDirCursor += sizeof(ZipCentralDirectoryFileHeader);
|
||||
|
||||
if (centralDirHeader->m_signature != ZipCentralDirectoryFileHeader::kSignature)
|
||||
{
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (centralDirEnd - centralDirCursor < centralDirHeader->m_fileNameLength)
|
||||
{
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!CheckAndFixFileName(centralDirCursor, centralDirHeader->m_fileNameLength))
|
||||
{
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
centralDirCursor += centralDirHeader->m_fileNameLength;
|
||||
|
||||
if (centralDirEnd - centralDirCursor < centralDirHeader->m_extraFieldLength)
|
||||
{
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
centralDirCursor += centralDirHeader->m_extraFieldLength;
|
||||
|
||||
if (centralDirEnd - centralDirCursor < centralDirHeader->m_commentLength)
|
||||
{
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
centralDirCursor += centralDirHeader->m_commentLength;
|
||||
|
||||
centralDirFiles[i] = centralDirHeader;
|
||||
}
|
||||
|
||||
if (failed)
|
||||
{
|
||||
mm->Release(centralDirFiles);
|
||||
mm->Release(centralDirImage);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
qsort(centralDirFiles, numFiles, sizeof(ZipCentralDirectoryFileHeader*), ZipDirectorySortPredicate);
|
||||
|
||||
for (size_t i = 1; i < numFiles; i++)
|
||||
{
|
||||
if (ZipDirectorySortPredicate(centralDirFiles + (i - 1), centralDirFiles + i) == 0)
|
||||
{
|
||||
// Duplicate file names
|
||||
mm->Release(centralDirFiles);
|
||||
mm->Release(centralDirImage);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void *storage = mm->Alloc(sizeof(ZipFileProxy));
|
||||
if (!storage)
|
||||
{
|
||||
mm->Release(centralDirFiles);
|
||||
mm->Release(centralDirImage);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new (storage) ZipFileProxy(stream, centralDirImage, centralDirFiles, numFiles);
|
||||
}
|
||||
|
||||
ZipFileProxy::ZipFileProxy(IOStream *stream, void *centralDirImage, ZipCentralDirectoryFileHeader **sortedFiles, size_t numFiles)
|
||||
: m_stream(stream)
|
||||
, m_centralDirImage(centralDirImage)
|
||||
, m_sortedFiles(sortedFiles)
|
||||
, m_numFiles(numFiles)
|
||||
{
|
||||
}
|
||||
|
||||
ZipFileProxy::~ZipFileProxy()
|
||||
{
|
||||
MemoryManager *mm = MemoryManager::GetInstance();
|
||||
mm->Release(m_centralDirImage);
|
||||
mm->Release(m_sortedFiles);
|
||||
}
|
||||
}
|
||||
30
PortabilityLayer/ZipFileProxy.h
Normal file
30
PortabilityLayer/ZipFileProxy.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
class IOStream;
|
||||
struct ZipCentralDirectoryFileHeader;
|
||||
|
||||
class ZipFileProxy
|
||||
{
|
||||
public:
|
||||
void Destroy();
|
||||
|
||||
bool IndexFile(const char *path, size_t &outIndex) const;
|
||||
bool LoadFile(size_t index, void *outBuffer);
|
||||
|
||||
size_t NumFiles() const;
|
||||
size_t GetFileSize(size_t index) const;
|
||||
|
||||
static ZipFileProxy *Create(IOStream *stream);
|
||||
|
||||
private:
|
||||
ZipFileProxy(IOStream *stream, void *centralDirImage, ZipCentralDirectoryFileHeader **sortedFiles, size_t numFiles);
|
||||
~ZipFileProxy();
|
||||
|
||||
IOStream *m_stream;
|
||||
void *m_centralDirImage;
|
||||
ZipCentralDirectoryFileHeader **m_sortedFiles;
|
||||
size_t m_numFiles;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user