mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-12-13 19:49:36 +00:00
Add house export to room editor
This commit is contained in:
@@ -75,6 +75,8 @@ namespace PortabilityLayer
|
|||||||
#define iObjectWindow 20
|
#define iObjectWindow 20
|
||||||
#define iCoordinateWindow 21
|
#define iCoordinateWindow 21
|
||||||
|
|
||||||
|
#define iExportGliderPROHouse 1
|
||||||
|
|
||||||
//-------------------------------------------------------------- Structs
|
//-------------------------------------------------------------- Structs
|
||||||
/*
|
/*
|
||||||
typedef short SICN[16];
|
typedef short SICN[16];
|
||||||
|
|||||||
@@ -187,6 +187,7 @@
|
|||||||
#define kGameMenuID 129
|
#define kGameMenuID 129
|
||||||
#define kOptionsMenuID 130
|
#define kOptionsMenuID 130
|
||||||
#define kHouseMenuID 131
|
#define kHouseMenuID 131
|
||||||
|
#define kExportMenuID 132
|
||||||
|
|
||||||
#define kSplashMode 0
|
#define kSplashMode 0
|
||||||
#define kEditMode 1
|
#define kEditMode 1
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ void GenerateRetroLinks (void);
|
|||||||
void DoGoToDialog (void);
|
void DoGoToDialog (void);
|
||||||
void ConvertHouseVer1To2 (void);
|
void ConvertHouseVer1To2 (void);
|
||||||
void ShiftWholeHouse (SInt16);
|
void ShiftWholeHouse (SInt16);
|
||||||
|
void ExportHouse (void);
|
||||||
|
|
||||||
void DoHouseInfo (void); // --- HouseInfo.c
|
void DoHouseInfo (void); // --- HouseInfo.c
|
||||||
|
|
||||||
|
|||||||
1283
GpApp/HouseIO.cpp
1283
GpApp/HouseIO.cpp
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,7 @@ extern WindowPtr mapWindow, toolsWindow, linkWindow;
|
|||||||
extern Rect boardSrcRect, localRoomsDest[];
|
extern Rect boardSrcRect, localRoomsDest[];
|
||||||
extern IGpCursor *handCursor, *vertCursor, *horiCursor;
|
extern IGpCursor *handCursor, *vertCursor, *horiCursor;
|
||||||
extern IGpCursor *diagCursor;
|
extern IGpCursor *diagCursor;
|
||||||
extern MenuHandle appleMenu, gameMenu, optionsMenu, houseMenu;
|
extern MenuHandle appleMenu, gameMenu, optionsMenu, houseMenu, exportMenu;
|
||||||
extern long incrementModeTime;
|
extern long incrementModeTime;
|
||||||
extern UInt32 doubleTime;
|
extern UInt32 doubleTime;
|
||||||
extern short fadeInSequence[], idleMode;
|
extern short fadeInSequence[], idleMode;
|
||||||
@@ -50,6 +50,8 @@ extern Boolean twoPlayerGame, paused, hasMirror, splashDrawn;
|
|||||||
|
|
||||||
void InitializeMenus (void)
|
void InitializeMenus (void)
|
||||||
{
|
{
|
||||||
|
PortabilityLayer::MenuManager *mm = PortabilityLayer::MenuManager::GetInstance();
|
||||||
|
|
||||||
appleMenu = GetMenu(kAppleMenuID);
|
appleMenu = GetMenu(kAppleMenuID);
|
||||||
if (appleMenu == nil)
|
if (appleMenu == nil)
|
||||||
RedAlert(kErrFailedResourceLoad);
|
RedAlert(kErrFailedResourceLoad);
|
||||||
@@ -70,12 +72,15 @@ void InitializeMenus (void)
|
|||||||
if (!thisMac.isTouchscreen)
|
if (!thisMac.isTouchscreen)
|
||||||
{
|
{
|
||||||
menusUp = true;
|
menusUp = true;
|
||||||
PortabilityLayer::MenuManager::GetInstance()->SetMenuVisible(true);
|
mm->SetMenuVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
houseMenu = GetMenu(kHouseMenuID);
|
houseMenu = GetMenu(kHouseMenuID);
|
||||||
if (houseMenu == nil)
|
if (houseMenu == nil)
|
||||||
RedAlert(kErrFailedResourceLoad);
|
RedAlert(kErrFailedResourceLoad);
|
||||||
|
|
||||||
|
exportMenu = mm->CreateMenu(PSTR("Export"), kExportMenuID, true, 100, 16, 0);
|
||||||
|
mm->AppendMenuItem(exportMenu, 0, 0, 0, 0, true, false, PSTR("Export Glider PRO\xaa House..."));
|
||||||
|
|
||||||
UpdateMenus(false);
|
UpdateMenus(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ void UpdateMenusHouseClosed (void);
|
|||||||
void HeyYourPissingAHighScore (void);
|
void HeyYourPissingAHighScore (void);
|
||||||
|
|
||||||
|
|
||||||
MenuHandle appleMenu, gameMenu, optionsMenu, houseMenu;
|
MenuHandle appleMenu, gameMenu, optionsMenu, houseMenu, exportMenu;
|
||||||
Boolean menusUp, resumedSavedGame;
|
Boolean menusUp, resumedSavedGame;
|
||||||
|
|
||||||
|
|
||||||
@@ -141,6 +141,11 @@ void UpdateMenusHouseOpen (void)
|
|||||||
EnableMenuItem(houseMenu, iSendBack);
|
EnableMenuItem(houseMenu, iSendBack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (houseUnlocked)
|
||||||
|
EnableMenuItem(exportMenu, iExportGliderPROHouse);
|
||||||
|
else
|
||||||
|
DisableMenuItem(exportMenu, iExportGliderPROHouse);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------- UpdateMenusHouseClosed
|
//-------------------------------------------------------------- UpdateMenusHouseClosed
|
||||||
@@ -159,6 +164,8 @@ void UpdateMenusHouseClosed (void)
|
|||||||
DisableMenuItem(houseMenu, iPaste);
|
DisableMenuItem(houseMenu, iPaste);
|
||||||
DisableMenuItem(houseMenu, iClear);
|
DisableMenuItem(houseMenu, iClear);
|
||||||
DisableMenuItem(houseMenu, iDuplicate);
|
DisableMenuItem(houseMenu, iDuplicate);
|
||||||
|
|
||||||
|
DisableMenuItem(exportMenu, iExportGliderPROHouse);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------- UpdateClipboardMenus
|
//-------------------------------------------------------------- UpdateClipboardMenus
|
||||||
@@ -254,12 +261,19 @@ void UpdateMenus (Boolean newMode)
|
|||||||
{
|
{
|
||||||
PortabilityLayer::MenuManager *mm = PortabilityLayer::MenuManager::GetInstance();
|
PortabilityLayer::MenuManager *mm = PortabilityLayer::MenuManager::GetInstance();
|
||||||
if (theMode == kEditMode)
|
if (theMode == kEditMode)
|
||||||
|
{
|
||||||
InsertMenu(houseMenu, 0);
|
InsertMenu(houseMenu, 0);
|
||||||
|
InsertMenu(exportMenu, 0);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
THandle<Menu> houseMenu = mm->GetMenuByID(kHouseMenuID);
|
THandle<Menu> houseMenu = mm->GetMenuByID(kHouseMenuID);
|
||||||
if (houseMenu)
|
if (houseMenu)
|
||||||
mm->RemoveMenu(houseMenu);
|
mm->RemoveMenu(houseMenu);
|
||||||
|
|
||||||
|
THandle<Menu> exportMenu = mm->GetMenuByID(kExportMenuID);
|
||||||
|
if (exportMenu)
|
||||||
|
mm->RemoveMenu(exportMenu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,6 +479,19 @@ void DoOptionsMenu (short theItem)
|
|||||||
//-------------------------------------------------------------- DoHouseMenu
|
//-------------------------------------------------------------- DoHouseMenu
|
||||||
// Handle the user selecting an item from the House menu (only in Edit mode).
|
// Handle the user selecting an item from the House menu (only in Edit mode).
|
||||||
|
|
||||||
|
void DoExportMenu(short theItem)
|
||||||
|
{
|
||||||
|
switch (theItem)
|
||||||
|
{
|
||||||
|
case iExportGliderPROHouse:
|
||||||
|
ExportHouse();
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------- DoHouseMenu
|
||||||
|
// Handle the user selecting an item from the House menu (only in Edit mode).
|
||||||
|
|
||||||
void DoHouseMenu (short theItem)
|
void DoHouseMenu (short theItem)
|
||||||
{
|
{
|
||||||
#ifndef COMPILEDEMO
|
#ifndef COMPILEDEMO
|
||||||
@@ -647,6 +674,10 @@ void DoMenuChoice (long menuChoice)
|
|||||||
case kHouseMenuID:
|
case kHouseMenuID:
|
||||||
DoHouseMenu(theItem);
|
DoHouseMenu(theItem);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kExportMenuID:
|
||||||
|
DoExportMenu(theItem);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -404,23 +404,23 @@ void TellHerNoSounds (void)
|
|||||||
|
|
||||||
//-------------------------------------------------------------- ParseAndConvertSound
|
//-------------------------------------------------------------- ParseAndConvertSound
|
||||||
|
|
||||||
IGpAudioBuffer *ParseAndConvertSoundChecked(const THandle<void> &handle)
|
bool ParseAndConvertSoundChecked(const THandle<void> &handle, void const*& outDataContents, size_t &outDataSize)
|
||||||
{
|
{
|
||||||
const uint8_t *dataStart = static_cast<const uint8_t*>(*handle);
|
const uint8_t *dataStart = static_cast<const uint8_t*>(*handle);
|
||||||
const size_t size = handle.MMBlock()->m_size;
|
const size_t size = handle.MMBlock()->m_size;
|
||||||
|
|
||||||
if (size < sizeof(PortabilityLayer::RIFFTag))
|
if (size < sizeof(PortabilityLayer::RIFFTag))
|
||||||
return nullptr;
|
return false;
|
||||||
|
|
||||||
PortabilityLayer::RIFFTag mainRiffTag;
|
PortabilityLayer::RIFFTag mainRiffTag;
|
||||||
memcpy(&mainRiffTag, dataStart, sizeof(PortabilityLayer::RIFFTag));
|
memcpy(&mainRiffTag, dataStart, sizeof(PortabilityLayer::RIFFTag));
|
||||||
|
|
||||||
if (mainRiffTag.m_tag != PortabilityLayer::WaveConstants::kRiffChunkID)
|
if (mainRiffTag.m_tag != PortabilityLayer::WaveConstants::kRiffChunkID)
|
||||||
return nullptr;
|
return false;
|
||||||
|
|
||||||
const uint32_t riffSize = mainRiffTag.m_chunkSize;
|
const uint32_t riffSize = mainRiffTag.m_chunkSize;
|
||||||
if (riffSize < 4 || riffSize - 4 > size - sizeof(PortabilityLayer::RIFFTag))
|
if (riffSize < 4 || riffSize - 4 > size - sizeof(PortabilityLayer::RIFFTag))
|
||||||
return nullptr;
|
return false;
|
||||||
|
|
||||||
const uint8_t *riffStart = dataStart + sizeof(PortabilityLayer::RIFFTag);
|
const uint8_t *riffStart = dataStart + sizeof(PortabilityLayer::RIFFTag);
|
||||||
const uint8_t *riffEnd = riffStart + riffSize;
|
const uint8_t *riffEnd = riffStart + riffSize;
|
||||||
@@ -432,7 +432,7 @@ IGpAudioBuffer *ParseAndConvertSoundChecked(const THandle<void> &handle)
|
|||||||
memcpy(&waveMarker, riffStart, 4);
|
memcpy(&waveMarker, riffStart, 4);
|
||||||
|
|
||||||
if (waveMarker != PortabilityLayer::WaveConstants::kWaveChunkID)
|
if (waveMarker != PortabilityLayer::WaveConstants::kWaveChunkID)
|
||||||
return nullptr;
|
return false;
|
||||||
|
|
||||||
const uint8_t *tagSearchLoc = riffStart + 4;
|
const uint8_t *tagSearchLoc = riffStart + 4;
|
||||||
|
|
||||||
@@ -440,7 +440,7 @@ IGpAudioBuffer *ParseAndConvertSoundChecked(const THandle<void> &handle)
|
|||||||
while (tagSearchLoc != riffEnd)
|
while (tagSearchLoc != riffEnd)
|
||||||
{
|
{
|
||||||
if (riffEnd - tagSearchLoc < sizeof(PortabilityLayer::RIFFTag))
|
if (riffEnd - tagSearchLoc < sizeof(PortabilityLayer::RIFFTag))
|
||||||
return nullptr;
|
return false;
|
||||||
|
|
||||||
PortabilityLayer::RIFFTag riffTag;
|
PortabilityLayer::RIFFTag riffTag;
|
||||||
memcpy(&riffTag, tagSearchLoc, sizeof(PortabilityLayer::RIFFTag));
|
memcpy(&riffTag, tagSearchLoc, sizeof(PortabilityLayer::RIFFTag));
|
||||||
@@ -453,20 +453,20 @@ IGpAudioBuffer *ParseAndConvertSoundChecked(const THandle<void> &handle)
|
|||||||
const uint32_t riffTagSizeUnpadded = riffTag.m_chunkSize;
|
const uint32_t riffTagSizeUnpadded = riffTag.m_chunkSize;
|
||||||
|
|
||||||
if (riffTagSizeUnpadded == 0xffffffffU)
|
if (riffTagSizeUnpadded == 0xffffffffU)
|
||||||
return nullptr;
|
return false;
|
||||||
|
|
||||||
const uint32_t riffTagSizePadded = riffTagSizeUnpadded + (riffTagSizeUnpadded & 1);
|
const uint32_t riffTagSizePadded = riffTagSizeUnpadded + (riffTagSizeUnpadded & 1);
|
||||||
|
|
||||||
tagSearchLoc += sizeof(PortabilityLayer::RIFFTag);
|
tagSearchLoc += sizeof(PortabilityLayer::RIFFTag);
|
||||||
|
|
||||||
if (riffEnd - tagSearchLoc < riffTagSizePadded)
|
if (riffEnd - tagSearchLoc < riffTagSizePadded)
|
||||||
return nullptr;
|
return false;
|
||||||
|
|
||||||
tagSearchLoc += riffTagSizePadded;
|
tagSearchLoc += riffTagSizePadded;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formatTagLoc == nullptr || dataTagLoc == nullptr)
|
if (formatTagLoc == nullptr || dataTagLoc == nullptr)
|
||||||
return nullptr;
|
return false;
|
||||||
|
|
||||||
PortabilityLayer::RIFFTag fmtTag;
|
PortabilityLayer::RIFFTag fmtTag;
|
||||||
memcpy(&fmtTag, formatTagLoc, sizeof(PortabilityLayer::RIFFTag));
|
memcpy(&fmtTag, formatTagLoc, sizeof(PortabilityLayer::RIFFTag));
|
||||||
@@ -500,7 +500,7 @@ IGpAudioBuffer *ParseAndConvertSoundChecked(const THandle<void> &handle)
|
|||||||
copyableSize = sizeof(PortabilityLayer::WaveFormatChunkV1);
|
copyableSize = sizeof(PortabilityLayer::WaveFormatChunkV1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return nullptr;
|
return false;
|
||||||
|
|
||||||
memcpy(&formatChunkV3, formatContents, copyableSize);
|
memcpy(&formatChunkV3, formatContents, copyableSize);
|
||||||
|
|
||||||
@@ -508,23 +508,22 @@ IGpAudioBuffer *ParseAndConvertSoundChecked(const THandle<void> &handle)
|
|||||||
const PortabilityLayer::WaveFormatChunkV1 formatChunkV1 = formatChunkV2.m_v1;
|
const PortabilityLayer::WaveFormatChunkV1 formatChunkV1 = formatChunkV2.m_v1;
|
||||||
|
|
||||||
if (formatChunkV1.m_bitsPerSample != 8)
|
if (formatChunkV1.m_bitsPerSample != 8)
|
||||||
return nullptr;
|
return false;
|
||||||
|
|
||||||
if (formatChunkV1.m_formatCode != PortabilityLayer::WaveConstants::kFormatPCM ||
|
if (formatChunkV1.m_formatCode != PortabilityLayer::WaveConstants::kFormatPCM ||
|
||||||
formatChunkV1.m_numChannels != 1 ||
|
formatChunkV1.m_numChannels != 1 ||
|
||||||
formatChunkV1.m_blockAlignmentBytes != 1 ||
|
formatChunkV1.m_blockAlignmentBytes != 1 ||
|
||||||
formatChunkV1.m_bitsPerSample != 8)
|
formatChunkV1.m_bitsPerSample != 8)
|
||||||
return nullptr;
|
return false;
|
||||||
|
|
||||||
uint32_t dataSize = dataTag.m_chunkSize;
|
uint32_t dataSize = dataTag.m_chunkSize;
|
||||||
if (dataSize > 0x1000000 || dataSize < 1)
|
if (dataSize > 0x1000000 || dataSize < 1)
|
||||||
return nullptr;
|
return false;
|
||||||
|
|
||||||
IGpAudioDriver *audioDriver = PLDrivers::GetAudioDriver();
|
outDataContents = dataContents;
|
||||||
if (!audioDriver)
|
outDataSize = dataSize;
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return audioDriver->CreateBuffer(dataContents, dataSize);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
IGpAudioBuffer *ParseAndConvertSound(const THandle<void> &handle)
|
IGpAudioBuffer *ParseAndConvertSound(const THandle<void> &handle)
|
||||||
@@ -532,6 +531,14 @@ IGpAudioBuffer *ParseAndConvertSound(const THandle<void> &handle)
|
|||||||
if (!handle)
|
if (!handle)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
IGpAudioBuffer *buffer = ParseAndConvertSoundChecked(handle);
|
IGpAudioDriver *audioDriver = PLDrivers::GetAudioDriver();
|
||||||
return buffer;
|
if (!audioDriver)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const void *dataContents = nullptr;
|
||||||
|
size_t dataSize = 0;
|
||||||
|
if (!ParseAndConvertSoundChecked(handle, dataContents, dataSize))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return audioDriver->CreateBuffer(dataContents, dataSize);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,12 @@ public:
|
|||||||
const T &operator[](size_t index) const;
|
const T &operator[](size_t index) const;
|
||||||
|
|
||||||
bool Resize(size_t newSize);
|
bool Resize(size_t newSize);
|
||||||
|
bool Reserve(size_t newSize);
|
||||||
bool ResizeNoConstruct(size_t newSize);
|
bool ResizeNoConstruct(size_t newSize);
|
||||||
|
|
||||||
|
bool Append(const T &item);
|
||||||
|
bool Append(T &&item);
|
||||||
|
|
||||||
T *Buffer();
|
T *Buffer();
|
||||||
const T *Buffer() const;
|
const T *Buffer() const;
|
||||||
|
|
||||||
@@ -148,7 +152,6 @@ const T &GpVector<T, TStaticSize>::operator[](size_t index) const
|
|||||||
return m_elements[index];
|
return m_elements[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, size_t TStaticSize>
|
template<class T, size_t TStaticSize>
|
||||||
bool GpVector<T, TStaticSize>::Resize(size_t newSize)
|
bool GpVector<T, TStaticSize>::Resize(size_t newSize)
|
||||||
{
|
{
|
||||||
@@ -163,6 +166,21 @@ bool GpVector<T, TStaticSize>::Resize(size_t newSize)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, size_t TStaticSize>
|
||||||
|
bool GpVector<T, TStaticSize>::Reserve(size_t newSize)
|
||||||
|
{
|
||||||
|
const size_t oldCount = m_count;
|
||||||
|
|
||||||
|
if (!ResizeNoConstruct(newSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_count = oldCount;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template<class T, size_t TStaticSize>
|
template<class T, size_t TStaticSize>
|
||||||
bool GpVector<T, TStaticSize>::ResizeNoConstruct(size_t newSize)
|
bool GpVector<T, TStaticSize>::ResizeNoConstruct(size_t newSize)
|
||||||
{
|
{
|
||||||
@@ -211,6 +229,53 @@ bool GpVector<T, TStaticSize>::ResizeNoConstruct(size_t newSize)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T, size_t TStaticSize>
|
||||||
|
bool GpVector<T, TStaticSize>::Append(const T &item)
|
||||||
|
{
|
||||||
|
const size_t oldCount = m_count;
|
||||||
|
|
||||||
|
if (m_count == m_capacity)
|
||||||
|
{
|
||||||
|
size_t newCapacity = m_capacity * 2;
|
||||||
|
if (newCapacity < 8)
|
||||||
|
newCapacity = 8;
|
||||||
|
|
||||||
|
if (!Reserve(newCapacity))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ResizeNoConstruct(oldCount + 1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
new (m_elements + oldCount) T(item);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, size_t TStaticSize>
|
||||||
|
bool GpVector<T, TStaticSize>::Append(T &&item)
|
||||||
|
{
|
||||||
|
const size_t oldCount = m_count;
|
||||||
|
|
||||||
|
if (m_count == m_capacity)
|
||||||
|
{
|
||||||
|
size_t newCapacity = m_capacity * 2;
|
||||||
|
if (newCapacity < 8)
|
||||||
|
newCapacity = 8;
|
||||||
|
|
||||||
|
if (!Reserve(newCapacity))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ResizeNoConstruct(oldCount + 1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
new (m_elements + oldCount) T(static_cast<T&&>(item));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, size_t TStaticSize>
|
template<class T, size_t TStaticSize>
|
||||||
const size_t GpVector<T, TStaticSize>::Count() const
|
const size_t GpVector<T, TStaticSize>::Count() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -91,9 +91,8 @@ namespace PortabilityLayer
|
|||||||
return output;
|
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))
|
if (l < sizeof(m_id))
|
||||||
{
|
{
|
||||||
memcpy(m_id, str, l);
|
memcpy(m_id, str, l);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
namespace PortabilityLayer
|
namespace PortabilityLayer
|
||||||
{
|
{
|
||||||
class ResTypeID;
|
class ResTypeID;
|
||||||
@@ -10,7 +12,7 @@ namespace PortabilityLayer
|
|||||||
|
|
||||||
static GpArcResourceTypeTag Encode(const ResTypeID &tag);
|
static GpArcResourceTypeTag Encode(const ResTypeID &tag);
|
||||||
|
|
||||||
bool Load(const char *str);
|
bool Load(const char *str, size_t strLen);
|
||||||
bool Decode(ResTypeID &outTag);
|
bool Decode(ResTypeID &outTag);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,13 +40,9 @@ namespace
|
|||||||
|
|
||||||
namespace PortabilityLayer
|
namespace PortabilityLayer
|
||||||
{
|
{
|
||||||
void MacBinary2::WriteBin(const MacFileMem *file, GpIOStream *stream)
|
void MacBinary2::SerializeHeader(unsigned char *mb2Header, const MacFileInfo &fileInfo)
|
||||||
{
|
{
|
||||||
const MacFileInfo &fileInfo = file->FileInfo();
|
memset(mb2Header, 0, kHeaderSize);
|
||||||
|
|
||||||
uint8_t mb2Header[128];
|
|
||||||
|
|
||||||
memset(mb2Header, 0, sizeof(mb2Header));
|
|
||||||
|
|
||||||
mb2Header[MB2FileOffsets::Version] = 0;
|
mb2Header[MB2FileOffsets::Version] = 0;
|
||||||
|
|
||||||
@@ -87,7 +83,15 @@ namespace PortabilityLayer
|
|||||||
mb2Header[MB2FileOffsets::MinVersion] = 129;
|
mb2Header[MB2FileOffsets::MinVersion] = 129;
|
||||||
|
|
||||||
BytePack::BigUInt16(mb2Header + MB2FileOffsets::Checksum, XModemCRC(mb2Header, 124, 0));
|
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);
|
stream->Write(mb2Header, 128);
|
||||||
|
|
||||||
uint8_t *padding = mb2Header;
|
uint8_t *padding = mb2Header;
|
||||||
|
|||||||
@@ -5,9 +5,14 @@ class GpIOStream;
|
|||||||
namespace PortabilityLayer
|
namespace PortabilityLayer
|
||||||
{
|
{
|
||||||
class MacFileMem;
|
class MacFileMem;
|
||||||
|
struct MacFileInfo;
|
||||||
|
|
||||||
namespace MacBinary2
|
namespace MacBinary2
|
||||||
{
|
{
|
||||||
|
static const int kHeaderSize = 128;
|
||||||
|
|
||||||
|
void SerializeHeader(unsigned char *headerBytes, const MacFileInfo &macFileInfo);
|
||||||
|
|
||||||
void WriteBin(const MacFileMem *file, GpIOStream *stream);
|
void WriteBin(const MacFileMem *file, GpIOStream *stream);
|
||||||
MacFileMem *ReadBin(GpIOStream *stream);
|
MacFileMem *ReadBin(GpIOStream *stream);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ namespace PortabilityLayer
|
|||||||
virtual void Init() override;
|
virtual void Init() override;
|
||||||
virtual void Shutdown() 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> DeserializeMenu(const void *resData) const override;
|
||||||
THandle<Menu> GetMenuByID(int id) const override;
|
THandle<Menu> GetMenuByID(int id) const override;
|
||||||
|
|
||||||
@@ -294,6 +295,60 @@ namespace PortabilityLayer
|
|||||||
// GP TODO: Dispose of menus properly
|
// 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
|
THandle<Menu> MenuManagerImpl::DeserializeMenu(const void *resData) const
|
||||||
{
|
{
|
||||||
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ namespace PortabilityLayer
|
|||||||
virtual void Init() = 0;
|
virtual void Init() = 0;
|
||||||
virtual void Shutdown() = 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> DeserializeMenu(const void *resData) const = 0;
|
||||||
virtual THandle<Menu> GetMenuByID(int id) const = 0;
|
virtual THandle<Menu> GetMenuByID(int id) const = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds, bool errorDiffusion)
|
||||||
{
|
{
|
||||||
if (!pictHdl)
|
if (!pictHdl)
|
||||||
@@ -572,9 +637,9 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
|||||||
memcpy(&fileHeader, bmpBytes, sizeof(fileHeader));
|
memcpy(&fileHeader, bmpBytes, sizeof(fileHeader));
|
||||||
memcpy(&infoHeader, bmpBytes + sizeof(fileHeader), sizeof(infoHeader));
|
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;
|
return;
|
||||||
|
|
||||||
uint32_t numColors = infoHeader.m_numColors;
|
uint32_t numColors = infoHeader.m_numColors;
|
||||||
@@ -584,6 +649,18 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
|||||||
if (numColors == 0 && bpp <= 8)
|
if (numColors == 0 && bpp <= 8)
|
||||||
numColors = (1 << bpp);
|
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 uint8_t *ctabLoc = bmpBytes + sizeof(fileHeader) + infoHeader.m_thisStructureSize;
|
||||||
|
|
||||||
const size_t ctabSize = numColors * sizeof(PortabilityLayer::BitmapColorTableEntry);
|
const size_t ctabSize = numColors * sizeof(PortabilityLayer::BitmapColorTableEntry);
|
||||||
@@ -592,6 +669,57 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
|||||||
if (ctabSize > availCTabBytes)
|
if (ctabSize > availCTabBytes)
|
||||||
return;
|
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)
|
if (bpp <= 8)
|
||||||
{
|
{
|
||||||
// Perform palette mapping
|
// Perform palette mapping
|
||||||
@@ -672,7 +800,7 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
|||||||
int16_t *errorDiffusionNextRow = nullptr;
|
int16_t *errorDiffusionNextRow = nullptr;
|
||||||
int16_t *errorDiffusionCurrentRow = 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));
|
errorDiffusionBuffer = static_cast<int16_t*>(memManager->Alloc(sizeof(int16_t) * numCopyCols * 2 * 3));
|
||||||
if (!errorDiffusionBuffer)
|
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 srcLow = currentSourceRow[srcColIndex * 2 + 0];
|
||||||
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
|
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
|
||||||
|
|
||||||
const unsigned int combinedValue = srcLow | (srcHigh << 8);
|
const uint32_t 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)
|
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;
|
currentDestRow[destColIndex] = 0;
|
||||||
else
|
else
|
||||||
currentDestRow[destColIndex] = 1;
|
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 uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
|
||||||
|
|
||||||
const unsigned int combinedValue = srcLow | (srcHigh << 8);
|
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);
|
uint8_t rgb[3];
|
||||||
const unsigned int xg = (g << 5) | (g >> 2);
|
for (unsigned int ch = 0; ch < 3; ch++)
|
||||||
const unsigned int xb = (b << 5) | (b >> 2);
|
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;
|
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 uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
|
||||||
|
|
||||||
const unsigned int combinedValue = srcLow | (srcHigh << 8);
|
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);
|
uint8_t rgb[3];
|
||||||
const unsigned int xg = (g << 5) | (g >> 2);
|
for (unsigned int ch = 0; ch < 3; ch++)
|
||||||
const unsigned int xb = (b << 5) | (b >> 2);
|
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));
|
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];
|
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 srcColIndex = col + firstSourceCol;
|
||||||
const size_t destColIndex = col + firstDestCol;
|
const size_t destColIndex = col + firstDestCol;
|
||||||
|
|
||||||
const uint8_t srcLow = currentSourceRow[srcColIndex * 2 + 0];
|
const uint8_t r = currentSourceRow[srcColIndex * 3 + 2];
|
||||||
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
|
const uint8_t g = currentSourceRow[srcColIndex * 3 + 1];
|
||||||
|
const uint8_t b = currentSourceRow[srcColIndex * 3 + 0];
|
||||||
|
|
||||||
const unsigned int combinedValue = srcLow | (srcHigh << 8);
|
if (r + g + b > 382)
|
||||||
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)
|
|
||||||
currentDestRow[destColIndex] = 0;
|
currentDestRow[destColIndex] = 0;
|
||||||
else
|
else
|
||||||
currentDestRow[destColIndex] = 1;
|
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;
|
currentSourceRow -= sourcePitch;
|
||||||
currentDestRow += destPitch;
|
currentDestRow += destPitch;
|
||||||
@@ -907,7 +1082,7 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
|||||||
const size_t destColIndex = col + firstDestCol;
|
const size_t destColIndex = col + firstDestCol;
|
||||||
|
|
||||||
const unsigned int srcIndex = (currentSourceRow[srcColIndex / 8] >> (8 - ((srcColIndex & 7) + 1))) & 0x01;
|
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)
|
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 uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
|
||||||
|
|
||||||
const unsigned int combinedValue = srcLow | (srcHigh << 8);
|
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);
|
for (unsigned int ch = 0; ch < 3; ch++)
|
||||||
const unsigned int xg = (g << 5) | (g >> 2);
|
currentDestRowBytes[destColIndex * 4 + ch] = (((combinedValue & masks[ch]) >> maskRShift1[ch]) * maskMultiplier[ch]) >> maskRShift2[ch];
|
||||||
const unsigned int xb = (b << 5) | (b >> 2);
|
|
||||||
|
|
||||||
currentDestRowBytes[destColIndex * 4 + 0] = xr;
|
|
||||||
currentDestRowBytes[destColIndex * 4 + 1] = xg;
|
|
||||||
currentDestRowBytes[destColIndex * 4 + 2] = xb;
|
|
||||||
currentDestRowBytes[destColIndex * 4 + 3] = 255;
|
currentDestRowBytes[destColIndex * 4 + 3] = 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -970,6 +1138,19 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
|||||||
currentDestRowBytes[destColIndex * 4 + 3] = 255;
|
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;
|
currentSourceRow -= sourcePitch;
|
||||||
currentDestRowBytes += destPitch;
|
currentDestRowBytes += destPitch;
|
||||||
|
|||||||
@@ -40,6 +40,61 @@ static const char *kPICTExtension = ".bmp";
|
|||||||
|
|
||||||
typedef ResourceValidationRules::ResourceValidationRule ResourceValidationRule_t;
|
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
|
namespace
|
||||||
{
|
{
|
||||||
// Validation here is only intended to be minimal, to ensure later checks can determine the format size and do certain operations
|
// 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;
|
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
|
bool ResourceArchiveZipFile::IndexResource(const ResTypeID &resTypeID, int id, size_t &outIndex, int &outValidationRule) const
|
||||||
{
|
{
|
||||||
const char *extension = GetFileExtensionForResType(resTypeID, outValidationRule);
|
const char *extension = GetFileExtensionForResType(resTypeID, outValidationRule);
|
||||||
@@ -461,6 +603,11 @@ namespace PortabilityLayer
|
|||||||
handle = ref->m_handle;
|
handle = ref->m_handle;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
const size_t resSize = m_zipFileProxy->GetFileSize(index);
|
||||||
|
|
||||||
|
if (resSize > kMaxResourceSize)
|
||||||
|
return THandle<void>();
|
||||||
|
|
||||||
handle = MemoryManager::GetInstance()->AllocHandle(0);
|
handle = MemoryManager::GetInstance()->AllocHandle(0);
|
||||||
if (!handle)
|
if (!handle)
|
||||||
return THandle<void>();
|
return THandle<void>();
|
||||||
@@ -468,7 +615,7 @@ namespace PortabilityLayer
|
|||||||
handle->m_rmSelfRef = ref;
|
handle->m_rmSelfRef = ref;
|
||||||
ref->m_handle = handle;
|
ref->m_handle = handle;
|
||||||
ref->m_resID = static_cast<int16_t>(id);
|
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)
|
if (handle->m_contents == nullptr && load)
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ namespace PortabilityLayer
|
|||||||
memcpy(&v2Version, v2Header + 4, 2);
|
memcpy(&v2Version, v2Header + 4, 2);
|
||||||
|
|
||||||
// In version 2 header, v2Version == -1
|
// 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
|
// 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
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ namespace PortabilityLayer
|
|||||||
int16_t m_resID;
|
int16_t m_resID;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct IResourceIterator
|
||||||
|
{
|
||||||
|
virtual void Destroy() = 0;
|
||||||
|
virtual bool GetOne(ResTypeID &resTypeID, int16_t &outID) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct IResourceArchive
|
struct IResourceArchive
|
||||||
{
|
{
|
||||||
virtual void Destroy() = 0;
|
virtual void Destroy() = 0;
|
||||||
@@ -35,6 +41,8 @@ namespace PortabilityLayer
|
|||||||
|
|
||||||
virtual bool HasAnyResourcesOfType(const ResTypeID &resTypeID) const = 0;
|
virtual bool HasAnyResourcesOfType(const ResTypeID &resTypeID) const = 0;
|
||||||
virtual bool FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const = 0;
|
virtual bool FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const = 0;
|
||||||
|
|
||||||
|
virtual IResourceIterator *EnumerateResources() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceArchiveBase : public IResourceArchive
|
class ResourceArchiveBase : public IResourceArchive
|
||||||
@@ -43,9 +51,13 @@ namespace PortabilityLayer
|
|||||||
static const char *GetFileExtensionForResType(const ResTypeID &resTypeID, int &outValidationRule);
|
static const char *GetFileExtensionForResType(const ResTypeID &resTypeID, int &outValidationRule);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ResourceArchiveZipFileIterator;
|
||||||
|
|
||||||
class ResourceArchiveZipFile final : public ResourceArchiveBase
|
class ResourceArchiveZipFile final : public ResourceArchiveBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
friend class ResourceArchiveZipFileIterator;
|
||||||
|
|
||||||
static ResourceArchiveZipFile *Create(ZipFileProxy *zipFileProxy, bool proxyIsShared, GpIOStream *stream);
|
static ResourceArchiveZipFile *Create(ZipFileProxy *zipFileProxy, bool proxyIsShared, GpIOStream *stream);
|
||||||
void Destroy() override;
|
void Destroy() override;
|
||||||
|
|
||||||
@@ -54,7 +66,14 @@ namespace PortabilityLayer
|
|||||||
bool HasAnyResourcesOfType(const ResTypeID &resTypeID) const override;
|
bool HasAnyResourcesOfType(const ResTypeID &resTypeID) const override;
|
||||||
bool FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) 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:
|
private:
|
||||||
|
static const size_t kMaxResourceSize = 32 * 1024 * 1024;
|
||||||
|
|
||||||
ResourceArchiveZipFile(ZipFileProxy *zipFileProxy, bool proxyIsShared, GpIOStream *stream, ResourceArchiveRef *resourceHandles);
|
ResourceArchiveZipFile(ZipFileProxy *zipFileProxy, bool proxyIsShared, GpIOStream *stream, ResourceArchiveRef *resourceHandles);
|
||||||
~ResourceArchiveZipFile();
|
~ResourceArchiveZipFile();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user