Add house export to room editor

This commit is contained in:
elasota
2021-05-07 02:16:25 -04:00
parent c3b2a7e8af
commit 6d12b6ff1a
18 changed files with 1883 additions and 75 deletions

View File

@@ -91,9 +91,8 @@ namespace PortabilityLayer
return output;
}
bool GpArcResourceTypeTag::Load(const char *str)
bool GpArcResourceTypeTag::Load(const char *str, size_t l)
{
size_t l = strlen(str);
if (l < sizeof(m_id))
{
memcpy(m_id, str, l);

View File

@@ -1,5 +1,7 @@
#pragma once
#include <stddef.h>
namespace PortabilityLayer
{
class ResTypeID;
@@ -10,7 +12,7 @@ namespace PortabilityLayer
static GpArcResourceTypeTag Encode(const ResTypeID &tag);
bool Load(const char *str);
bool Load(const char *str, size_t strLen);
bool Decode(ResTypeID &outTag);
};
}

View File

@@ -40,13 +40,9 @@ namespace
namespace PortabilityLayer
{
void MacBinary2::WriteBin(const MacFileMem *file, GpIOStream *stream)
void MacBinary2::SerializeHeader(unsigned char *mb2Header, const MacFileInfo &fileInfo)
{
const MacFileInfo &fileInfo = file->FileInfo();
uint8_t mb2Header[128];
memset(mb2Header, 0, sizeof(mb2Header));
memset(mb2Header, 0, kHeaderSize);
mb2Header[MB2FileOffsets::Version] = 0;
@@ -87,7 +83,15 @@ namespace PortabilityLayer
mb2Header[MB2FileOffsets::MinVersion] = 129;
BytePack::BigUInt16(mb2Header + MB2FileOffsets::Checksum, XModemCRC(mb2Header, 124, 0));
}
void MacBinary2::WriteBin(const MacFileMem *file, GpIOStream *stream)
{
const MacFileInfo &fileInfo = file->FileInfo();
uint8_t mb2Header[128];
SerializeHeader(mb2Header, fileInfo);
stream->Write(mb2Header, 128);
uint8_t *padding = mb2Header;

View File

@@ -5,9 +5,14 @@ class GpIOStream;
namespace PortabilityLayer
{
class MacFileMem;
struct MacFileInfo;
namespace MacBinary2
{
static const int kHeaderSize = 128;
void SerializeHeader(unsigned char *headerBytes, const MacFileInfo &macFileInfo);
void WriteBin(const MacFileMem *file, GpIOStream *stream);
MacFileMem *ReadBin(GpIOStream *stream);
};

View File

@@ -128,6 +128,7 @@ namespace PortabilityLayer
virtual void Init() override;
virtual void Shutdown() override;
THandle<Menu> CreateMenu(const PLPasStr &title, uint16_t menuID, bool enabled, uint16_t width, uint16_t height, uint16_t commandID) const override;
THandle<Menu> DeserializeMenu(const void *resData) const override;
THandle<Menu> GetMenuByID(int id) const override;
@@ -294,6 +295,60 @@ namespace PortabilityLayer
// GP TODO: Dispose of menus properly
}
THandle<Menu> MenuManagerImpl::CreateMenu(const PLPasStr &title, uint16_t menuID, bool enabled, uint16_t width, uint16_t height, uint16_t commandID) const
{
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
const uint8_t titleLength = title.Length();
size_t stringDataLength = 1 + titleLength;
size_t numMenuItems = 0;
MMHandleBlock *stringData = mm->AllocHandle(stringDataLength);
if (!stringData)
{
mm->ReleaseHandle(stringData);
return nullptr;
}
MMHandleBlock *menuData = mm->AllocHandle(sizeof(Menu) + sizeof(MenuItem) * (numMenuItems - 1));
if (!menuData)
{
mm->ReleaseHandle(stringData);
return nullptr;
}
Menu *menu = static_cast<Menu*>(menuData->m_contents);
menu->menuID = menuID;
menu->width = width;
menu->height = height;
menu->commandID = commandID;
menu->enabled = true;
menu->menuIndex = 0;
menu->cumulativeOffset = 0;
menu->unpaddedTitleWidth = 0;
menu->isIcon = false;
menu->haveMenuLayout = false;
uint8_t *stringDataStart = static_cast<uint8_t*>(stringData->m_contents);
uint8_t *stringDest = stringDataStart;
stringDest[0] = title.Length();
memcpy(stringDest + 1, title.UChars(), title.Length());
menu->numMenuItems = numMenuItems;
menu->stringBlobHandle = stringData;
menu->prevMenu = nullptr;
menu->nextMenu = nullptr;
menu->layoutHintHorizontalOffset = 0;
menu->layoutWidth = 0;
menu->layoutBaseHeight = 0;
menu->layoutFinalHeight = 0;
menu->bottomItemsTruncated = 0;
menu->topItemsTruncated = 0;
return THandle<Menu>(menuData);
}
THandle<Menu> MenuManagerImpl::DeserializeMenu(const void *resData) const
{
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();

View File

@@ -23,6 +23,7 @@ namespace PortabilityLayer
virtual void Init() = 0;
virtual void Shutdown() = 0;
virtual THandle<Menu> CreateMenu(const PLPasStr &title, uint16_t menuID, bool enabled, uint16_t width, uint16_t height, uint16_t commandID) const = 0;
virtual THandle<Menu> DeserializeMenu(const void *resData) const = 0;
virtual THandle<Menu> GetMenuByID(int id) const = 0;

View File

@@ -493,6 +493,71 @@ static void RedistributeError(int16_t *errorDiffusionNextRow, int16_t *errorDiff
}
}
namespace PortabilityLayer
{
bool FindBitSpan(uint32_t mask, int &outLowBit, int &outHighBit)
{
bool haveAnyBits = false;
for (int i = 0; i < 32; i++)
{
if (mask & (1 << i))
{
if (!haveAnyBits)
{
haveAnyBits = true;
outLowBit = i;
}
outHighBit = i;
}
}
return haveAnyBits;
}
int DecodeMaskRShift1(uint32_t mask)
{
int lowBit, highBit;
if (!FindBitSpan(mask, lowBit, highBit))
return 0;
return lowBit;
}
int DecodeMaskRShift2(uint32_t mask)
{
int lowBit, highBit;
if (!FindBitSpan(mask, lowBit, highBit))
return 0;
int numBits = highBit - lowBit + 1;
int expandedBits = numBits;
while (expandedBits < 8)
expandedBits += numBits;
return expandedBits - 8;
}
int DecodeMaskMultiplier(uint32_t mask)
{
int lowBit, highBit;
if (!FindBitSpan(mask, lowBit, highBit))
return 0;
int numBits = highBit - lowBit + 1;
int expandedBits = numBits;
int expansionFactor = 1;
while (expandedBits < 8)
{
expandedBits += numBits;
expansionFactor = (expansionFactor << numBits) | 1;
}
return expansionFactor;
}
}
void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds, bool errorDiffusion)
{
if (!pictHdl)
@@ -572,9 +637,9 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
memcpy(&fileHeader, bmpBytes, sizeof(fileHeader));
memcpy(&infoHeader, bmpBytes + sizeof(fileHeader), sizeof(infoHeader));
const uint16_t bpp = infoHeader.m_bitsPerPixel;
uint16_t bpp = infoHeader.m_bitsPerPixel;
if (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24)
if (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32)
return;
uint32_t numColors = infoHeader.m_numColors;
@@ -584,6 +649,18 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
if (numColors == 0 && bpp <= 8)
numColors = (1 << bpp);
LEUInt32_t masks[4];
int maskRShift1[4];
int maskRShift2[4];
int maskMultiplier[4];
bool haveMasks = false;
if (infoHeader.m_thisStructureSize >= sizeof(PortabilityLayer::BitmapInfoHeader) + sizeof(uint32_t) * 4)
{
const uint8_t *masksLoc = bmpBytes + sizeof(fileHeader) + sizeof(PortabilityLayer::BitmapInfoHeader);
memcpy(masks, masksLoc, 16);
haveMasks = true;
}
const uint8_t *ctabLoc = bmpBytes + sizeof(fileHeader) + infoHeader.m_thisStructureSize;
const size_t ctabSize = numColors * sizeof(PortabilityLayer::BitmapColorTableEntry);
@@ -592,6 +669,57 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
if (ctabSize > availCTabBytes)
return;
const uint32_t compressionCode = static_cast<uint32_t>(infoHeader.m_compression);
if (bpp == 16)
{
if (compressionCode == 0)
{
haveMasks = true;
masks[0] = (0x1f << 10);
masks[1] = (0x1f << 5);
masks[2] = (0x1f << 0);
masks[3] = (1 << 15);
}
else if (compressionCode == 3)
{
if (!haveMasks)
return;
}
else
return;
}
else if (bpp == 32)
{
if (compressionCode == 0)
{
haveMasks = true;
masks[0] = (0xff << 16);
masks[1] = (0xff << 8);
masks[2] = (0xff << 0);
masks[3] = (0xff << 24);
}
if (compressionCode == 3)
{
if (!haveMasks)
return;
}
}
else
{
if (compressionCode != 0)
return;
}
if (haveMasks)
{
for (int mi = 0; mi < 4; mi++)
{
maskRShift1[mi] = PortabilityLayer::DecodeMaskRShift1(masks[mi]);
maskRShift2[mi] = PortabilityLayer::DecodeMaskRShift2(masks[mi]);
maskMultiplier[mi] = PortabilityLayer::DecodeMaskMultiplier(masks[mi]);
}
}
if (bpp <= 8)
{
// Perform palette mapping
@@ -672,7 +800,7 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
int16_t *errorDiffusionNextRow = nullptr;
int16_t *errorDiffusionCurrentRow = nullptr;
if ((bpp == 16 || bpp == 24) && errorDiffusion)
if ((bpp == 16 || bpp == 24 || bpp == 32) && errorDiffusion)
{
errorDiffusionBuffer = static_cast<int16_t*>(memManager->Alloc(sizeof(int16_t) * numCopyCols * 2 * 3));
if (!errorDiffusionBuffer)
@@ -739,12 +867,13 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
const uint8_t srcLow = currentSourceRow[srcColIndex * 2 + 0];
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
const unsigned int combinedValue = srcLow | (srcHigh << 8);
const unsigned int b = (combinedValue & 0x1f);
const unsigned int g = ((combinedValue >> 5) & 0x1f);
const unsigned int r = ((combinedValue >> 10) & 0x1f);
const uint32_t combinedValue = srcLow | (srcHigh << 8);
if (r + g + b > 46)
uint8_t rgb[3];
for (unsigned int ch = 0; ch < 3; ch++)
rgb[ch] = (((combinedValue & masks[ch]) >> maskRShift1[ch]) * maskMultiplier[ch]) >> maskRShift2[ch];
if (rgb[0] + rgb[1] + rgb[2] > 382)
currentDestRow[destColIndex] = 0;
else
currentDestRow[destColIndex] = 1;
@@ -763,15 +892,12 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
const unsigned int combinedValue = srcLow | (srcHigh << 8);
const unsigned int b = (combinedValue & 0x1f);
const unsigned int g = ((combinedValue >> 5) & 0x1f);
const unsigned int r = ((combinedValue >> 10) & 0x1f);
const unsigned int xr = (r << 5) | (r >> 2);
const unsigned int xg = (g << 5) | (g >> 2);
const unsigned int xb = (b << 5) | (b >> 2);
uint8_t rgb[3];
for (unsigned int ch = 0; ch < 3; ch++)
rgb[ch] = (((combinedValue & masks[ch]) >> maskRShift1[ch]) * maskMultiplier[ch]) >> maskRShift2[ch];
uint8_t colorIndex = stdPalette->MapColorLUT(PortabilityLayer::RGBAColor::Create(xr, xg, xb, 255));
uint8_t colorIndex = stdPalette->MapColorLUT(PortabilityLayer::RGBAColor::Create(rgb[0], rgb[1], rgb[2], 255));
currentDestRow[destColIndex] = colorIndex;
}
@@ -787,15 +913,12 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
const unsigned int combinedValue = srcLow | (srcHigh << 8);
const unsigned int b = (combinedValue & 0x1f);
const unsigned int g = ((combinedValue >> 5) & 0x1f);
const unsigned int r = ((combinedValue >> 10) & 0x1f);
const unsigned int xr = (r << 5) | (r >> 2);
const unsigned int xg = (g << 5) | (g >> 2);
const unsigned int xb = (b << 5) | (b >> 2);
uint8_t rgb[3];
for (unsigned int ch = 0; ch < 3; ch++)
rgb[ch] = (((combinedValue & masks[ch]) >> maskRShift1[ch]) * maskMultiplier[ch]) >> maskRShift2[ch];
ErrorDiffusionWorkPixel wp = ApplyErrorDiffusion(errorDiffusionCurrentRow, xr, xg, xb, col, numCopyCols);
ErrorDiffusionWorkPixel wp = ApplyErrorDiffusion(errorDiffusionCurrentRow, rgb[0], rgb[1], rgb[2], col, numCopyCols);
uint8_t colorIndex = stdPalette->MapColorLUT(PortabilityLayer::RGBAColor::Create(wp.m_8[0], wp.m_8[1], wp.m_8[2], 255));
PortabilityLayer::RGBAColor resultColor = stdPalette->GetColors()[colorIndex];
@@ -816,15 +939,11 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
const size_t srcColIndex = col + firstSourceCol;
const size_t destColIndex = col + firstDestCol;
const uint8_t srcLow = currentSourceRow[srcColIndex * 2 + 0];
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
const uint8_t r = currentSourceRow[srcColIndex * 3 + 2];
const uint8_t g = currentSourceRow[srcColIndex * 3 + 1];
const uint8_t b = currentSourceRow[srcColIndex * 3 + 0];
const unsigned int combinedValue = srcLow | (srcHigh << 8);
const unsigned int b = (combinedValue & 0x1f);
const unsigned int g = ((combinedValue >> 5) & 0x1f);
const unsigned int r = ((combinedValue >> 10) & 0x1f);
if (r + g + b > 46)
if (r + g + b > 382)
currentDestRow[destColIndex] = 0;
else
currentDestRow[destColIndex] = 1;
@@ -867,6 +986,62 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
}
}
}
else if (bpp == 32)
{
if (destFormat == GpPixelFormats::kBW1)
{
for (size_t col = 0; col < numCopyCols; col++)
{
const size_t srcColIndex = col + firstSourceCol;
const size_t destColIndex = col + firstDestCol;
const uint8_t r = currentSourceRow[srcColIndex * 4 + 2];
const uint8_t g = currentSourceRow[srcColIndex * 4 + 1];
const uint8_t b = currentSourceRow[srcColIndex * 4 + 0];
if (r + g + b > 382)
currentDestRow[destColIndex] = 0;
else
currentDestRow[destColIndex] = 1;
}
}
else
{
if (!errorDiffusion)
{
for (size_t col = 0; col < numCopyCols; col++)
{
const size_t srcColIndex = col + firstSourceCol;
const size_t destColIndex = col + firstDestCol;
const uint8_t r = currentSourceRow[srcColIndex * 4 + 2];
const uint8_t g = currentSourceRow[srcColIndex * 4 + 1];
const uint8_t b = currentSourceRow[srcColIndex * 4 + 0];
uint8_t colorIndex = stdPalette->MapColorLUT(PortabilityLayer::RGBAColor::Create(r, g, b, 255));
currentDestRow[destColIndex] = colorIndex;
}
}
else
{
for (size_t col = 0; col < numCopyCols; col++)
{
const size_t srcColIndex = col + firstSourceCol;
const size_t destColIndex = col + firstDestCol;
ErrorDiffusionWorkPixel wp = ApplyErrorDiffusion(errorDiffusionCurrentRow, currentSourceRow[srcColIndex * 4 + 2], currentSourceRow[srcColIndex * 4 + 1], currentSourceRow[srcColIndex * 4 + 0], col, numCopyCols);
uint8_t colorIndex = stdPalette->MapColorLUT(PortabilityLayer::RGBAColor::Create(wp.m_8[0], wp.m_8[1], wp.m_8[2], 255));
PortabilityLayer::RGBAColor resultColor = stdPalette->GetColors()[colorIndex];
RedistributeError(errorDiffusionNextRow, errorDiffusionCurrentRow, wp.m_16[0], wp.m_16[1], wp.m_16[2], resultColor.r, resultColor.g, resultColor.b, col, numCopyCols);
currentDestRow[destColIndex] = colorIndex;
}
}
}
}
currentSourceRow -= sourcePitch;
currentDestRow += destPitch;
@@ -907,7 +1082,7 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
const size_t destColIndex = col + firstDestCol;
const unsigned int srcIndex = (currentSourceRow[srcColIndex / 8] >> (8 - ((srcColIndex & 7) + 1))) & 0x01;
currentDestRow32[destColIndex] = srcIndex ? blackColor32 : whiteColor32;
currentDestRow32[destColIndex] = unpackedColors[srcIndex];
}
}
else if (bpp == 4)
@@ -943,17 +1118,10 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
const unsigned int combinedValue = srcLow | (srcHigh << 8);
const unsigned int b = (combinedValue & 0x1f);
const unsigned int g = ((combinedValue >> 5) & 0x1f);
const unsigned int r = ((combinedValue >> 10) & 0x1f);
const unsigned int xr = (r << 5) | (r >> 2);
const unsigned int xg = (g << 5) | (g >> 2);
const unsigned int xb = (b << 5) | (b >> 2);
for (unsigned int ch = 0; ch < 3; ch++)
currentDestRowBytes[destColIndex * 4 + ch] = (((combinedValue & masks[ch]) >> maskRShift1[ch]) * maskMultiplier[ch]) >> maskRShift2[ch];
currentDestRowBytes[destColIndex * 4 + 0] = xr;
currentDestRowBytes[destColIndex * 4 + 1] = xg;
currentDestRowBytes[destColIndex * 4 + 2] = xb;
currentDestRowBytes[destColIndex * 4 + 3] = 255;
}
}
@@ -970,6 +1138,19 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
currentDestRowBytes[destColIndex * 4 + 3] = 255;
}
}
else if (bpp == 32)
{
for (size_t col = 0; col < numCopyCols; col++)
{
const size_t srcColIndex = col + firstSourceCol;
const size_t destColIndex = col + firstDestCol;
currentDestRowBytes[destColIndex * 4 + 0] = currentSourceRow[srcColIndex * 4 + 2];
currentDestRowBytes[destColIndex * 4 + 1] = currentSourceRow[srcColIndex * 4 + 1];
currentDestRowBytes[destColIndex * 4 + 2] = currentSourceRow[srcColIndex * 4 + 0];
currentDestRowBytes[destColIndex * 4 + 3] = 255;
}
}
currentSourceRow -= sourcePitch;
currentDestRowBytes += destPitch;

View File

@@ -40,6 +40,61 @@ static const char *kPICTExtension = ".bmp";
typedef ResourceValidationRules::ResourceValidationRule ResourceValidationRule_t;
namespace PortabilityLayer
{
class ResourceArchiveZipFileIterator : public IResourceIterator
{
public:
explicit ResourceArchiveZipFileIterator(PortabilityLayer::ZipFileProxy *proxy);
void Destroy() override;
bool GetOne(ResTypeID &resTypeID, int16_t &outID) override;
private:
~ResourceArchiveZipFileIterator();
PortabilityLayer::ZipFileProxy *m_proxy;
size_t m_numFiles;
size_t m_currentIndex;
};
}
PortabilityLayer::ResourceArchiveZipFileIterator::ResourceArchiveZipFileIterator(PortabilityLayer::ZipFileProxy *proxy)
: m_proxy(proxy)
, m_numFiles(proxy->NumFiles())
, m_currentIndex(0)
{
}
void PortabilityLayer::ResourceArchiveZipFileIterator::Destroy()
{
this->~ResourceArchiveZipFileIterator();
PortabilityLayer::MemoryManager::GetInstance()->Release(this);
}
bool PortabilityLayer::ResourceArchiveZipFileIterator::GetOne(ResTypeID &resTypeID, int16_t &outID)
{
while (m_currentIndex != m_numFiles)
{
const size_t index = m_currentIndex++;
const char *name = nullptr;
size_t nameLength = 0;
m_proxy->GetFileName(index, name, nameLength);
const bool isParseable = ResourceArchiveZipFile::ParseResFromName(name, nameLength, resTypeID, outID);
if (isParseable)
return true;
}
return false;
}
PortabilityLayer::ResourceArchiveZipFileIterator::~ResourceArchiveZipFileIterator()
{
}
namespace
{
// Validation here is only intended to be minimal, to ensure later checks can determine the format size and do certain operations
@@ -433,6 +488,93 @@ namespace PortabilityLayer
return haveAny;
}
IResourceIterator *ResourceArchiveZipFile::EnumerateResources() const
{
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
void *storage = mm->Alloc(sizeof(ResourceArchiveZipFileIterator));
if (!storage)
return nullptr;
return new (storage) ResourceArchiveZipFileIterator(m_zipFileProxy);
}
bool ResourceArchiveZipFile::ParseResFromName(const char *name, size_t nameLength, ResTypeID &outResTypeID, int16_t &outID)
{
size_t slashPos = nameLength;
for (size_t i = 0; i < nameLength; i++)
{
if (name[i] == '/')
{
slashPos = i;
break;
}
}
if (slashPos == nameLength)
return false;
GpArcResourceTypeTag resTag;
if (!resTag.Load(name, slashPos))
return false;
if (!resTag.Decode(outResTypeID))
return false;
int validationRule = 0;
const char *expectedExtension = GetFileExtensionForResType(outResTypeID, validationRule);
const size_t idStart = slashPos + 1;
if (idStart == nameLength)
return false;
bool isNegative = false;
size_t digitsStart = idStart;
if (name[idStart] == '-')
{
isNegative = true;
digitsStart++;
}
size_t digitsEnd = nameLength;
int32_t resID = 0;
for (size_t i = digitsStart; i < nameLength; i++)
{
if (name[i] == '.')
{
digitsEnd = i;
break;
}
else
{
char digit = name[i];
if (digit < '0' || digit > '9')
return false;
int32_t digitNumber = static_cast<int32_t>(digit) - '0';
resID *= 10;
if (isNegative)
resID -= digitNumber;
else
resID += digitNumber;
if (resID < -32768 || resID > 32767)
return false;
}
}
outID = static_cast<int16_t>(resID);
const size_t extAvailable = nameLength - digitsEnd;
if (strlen(expectedExtension) != extAvailable)
return false;
if (memcmp(name + digitsEnd, expectedExtension, extAvailable) != 0)
return false;
return true;
}
bool ResourceArchiveZipFile::IndexResource(const ResTypeID &resTypeID, int id, size_t &outIndex, int &outValidationRule) const
{
const char *extension = GetFileExtensionForResType(resTypeID, outValidationRule);
@@ -461,6 +603,11 @@ namespace PortabilityLayer
handle = ref->m_handle;
else
{
const size_t resSize = m_zipFileProxy->GetFileSize(index);
if (resSize > kMaxResourceSize)
return THandle<void>();
handle = MemoryManager::GetInstance()->AllocHandle(0);
if (!handle)
return THandle<void>();
@@ -468,7 +615,7 @@ namespace PortabilityLayer
handle->m_rmSelfRef = ref;
ref->m_handle = handle;
ref->m_resID = static_cast<int16_t>(id);
ref->m_size = m_zipFileProxy->GetFileSize(index);
ref->m_size = resSize;
}
if (handle->m_contents == nullptr && load)

View File

@@ -55,9 +55,9 @@ namespace PortabilityLayer
memcpy(&v2Version, v2Header + 4, 2);
// In version 2 header, v2Version == -1
// Followed by fixed-point bounding rectangle (16 bytes) and 4 reserved
// Followed by 2-byte reserved (usually -1), fixed-point bounding rectangle (16 bytes) and 4 reserved (usually 0)
// In ext. version 2 header, v2Version == -2
// Followed by 2-byte reserved, horizontal DPI (fixed point, 4 bytes), vertical DPI (fixed point, 4 bytes) optimal source rect (8 bytes), and 2 reserved
// Followed by 2-byte reserved (0), horizontal DPI (fixed point, 4 bytes), vertical DPI (fixed point, 4 bytes) optimal source rect (8 bytes), and 2 reserved
}
else
return false;

View File

@@ -27,6 +27,12 @@ namespace PortabilityLayer
int16_t m_resID;
};
struct IResourceIterator
{
virtual void Destroy() = 0;
virtual bool GetOne(ResTypeID &resTypeID, int16_t &outID) = 0;
};
struct IResourceArchive
{
virtual void Destroy() = 0;
@@ -35,6 +41,8 @@ namespace PortabilityLayer
virtual bool HasAnyResourcesOfType(const ResTypeID &resTypeID) const = 0;
virtual bool FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const = 0;
virtual IResourceIterator *EnumerateResources() const = 0;
};
class ResourceArchiveBase : public IResourceArchive
@@ -43,9 +51,13 @@ namespace PortabilityLayer
static const char *GetFileExtensionForResType(const ResTypeID &resTypeID, int &outValidationRule);
};
class ResourceArchiveZipFileIterator;
class ResourceArchiveZipFile final : public ResourceArchiveBase
{
public:
friend class ResourceArchiveZipFileIterator;
static ResourceArchiveZipFile *Create(ZipFileProxy *zipFileProxy, bool proxyIsShared, GpIOStream *stream);
void Destroy() override;
@@ -54,7 +66,14 @@ namespace PortabilityLayer
bool HasAnyResourcesOfType(const ResTypeID &resTypeID) const override;
bool FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const override;
IResourceIterator *EnumerateResources() const override;
static bool ParseResFromName(const char *name, size_t nameLength, ResTypeID &outResTypeID, int16_t &outID);
private:
static const size_t kMaxResourceSize = 32 * 1024 * 1024;
ResourceArchiveZipFile(ZipFileProxy *zipFileProxy, bool proxyIsShared, GpIOStream *stream, ResourceArchiveRef *resourceHandles);
~ResourceArchiveZipFile();