mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-12-14 12:09:36 +00:00
Add support for unpackaged resources to speed up loads on Android, i.e. so we don't have to decompress entire GPAs to load a single resource.
This commit is contained in:
@@ -183,7 +183,7 @@ bool GpFileSystem_Win32::FileExists(PortabilityLayer::VirtualDirectory_t virtual
|
|||||||
{
|
{
|
||||||
wchar_t winPath[MAX_PATH + 1];
|
wchar_t winPath[MAX_PATH + 1];
|
||||||
|
|
||||||
if (!ResolvePath(virtualDirectory, path, winPath))
|
if (!ResolvePath(virtualDirectory, &path, 1, winPath))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return PathFileExistsW(winPath) != 0;
|
return PathFileExistsW(winPath) != 0;
|
||||||
@@ -193,7 +193,7 @@ bool GpFileSystem_Win32::FileLocked(PortabilityLayer::VirtualDirectory_t virtual
|
|||||||
{
|
{
|
||||||
wchar_t winPath[MAX_PATH + 1];
|
wchar_t winPath[MAX_PATH + 1];
|
||||||
|
|
||||||
if (!ResolvePath(virtualDirectory, path, winPath))
|
if (!ResolvePath(virtualDirectory, &path, 1, winPath))
|
||||||
{
|
{
|
||||||
*exists = false;
|
*exists = false;
|
||||||
return false;
|
return false;
|
||||||
@@ -210,11 +210,11 @@ bool GpFileSystem_Win32::FileLocked(PortabilityLayer::VirtualDirectory_t virtual
|
|||||||
return (attribs & FILE_ATTRIBUTE_READONLY) != 0;
|
return (attribs & FILE_ATTRIBUTE_READONLY) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GpIOStream *GpFileSystem_Win32::OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition)
|
GpIOStream *GpFileSystem_Win32::OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition)
|
||||||
{
|
{
|
||||||
wchar_t winPath[MAX_PATH + 1];
|
wchar_t winPath[MAX_PATH + 1];
|
||||||
|
|
||||||
if (!ResolvePath(virtualDirectory, path, winPath))
|
if (!ResolvePath(virtualDirectory, paths, numPaths, winPath))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const DWORD desiredAccess = writeAccess ? (GENERIC_WRITE | GENERIC_READ) : GENERIC_READ;
|
const DWORD desiredAccess = writeAccess ? (GENERIC_WRITE | GENERIC_READ) : GENERIC_READ;
|
||||||
@@ -252,7 +252,7 @@ bool GpFileSystem_Win32::DeleteFile(PortabilityLayer::VirtualDirectory_t virtual
|
|||||||
{
|
{
|
||||||
wchar_t winPath[MAX_PATH + 1];
|
wchar_t winPath[MAX_PATH + 1];
|
||||||
|
|
||||||
if (!ResolvePath(virtualDirectory, path, winPath))
|
if (!ResolvePath(virtualDirectory, &path, 1, winPath))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (DeleteFileW(winPath))
|
if (DeleteFileW(winPath))
|
||||||
@@ -270,11 +270,22 @@ bool GpFileSystem_Win32::DeleteFile(PortabilityLayer::VirtualDirectory_t virtual
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Win32::ScanDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory)
|
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Win32::ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths)
|
||||||
{
|
{
|
||||||
wchar_t winPath[MAX_PATH + 2];
|
wchar_t winPath[MAX_PATH + 2];
|
||||||
|
|
||||||
if (!ResolvePath(virtualDirectory, "*", winPath))
|
const char **expandedPaths = static_cast<const char**>(malloc(sizeof(const char*) * (numPaths + 1)));
|
||||||
|
if (!expandedPaths)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < numPaths; i++)
|
||||||
|
expandedPaths[i] = paths[i];
|
||||||
|
expandedPaths[numPaths] = "*";
|
||||||
|
|
||||||
|
const bool isPathResolved = ResolvePath(virtualDirectory, expandedPaths, numPaths + 1, winPath);
|
||||||
|
free(expandedPaths);
|
||||||
|
|
||||||
|
if (!isPathResolved)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
WIN32_FIND_DATAW findData;
|
WIN32_FIND_DATAW findData;
|
||||||
@@ -306,6 +317,11 @@ bool GpFileSystem_Win32::ValidateFilePathUnicodeChar(uint32_t c) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GpFileSystem_Win32::IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool GpFileSystem_Win32::ValidateFilePath(const char *str, size_t length) const
|
bool GpFileSystem_Win32::ValidateFilePath(const char *str, size_t length) const
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < length; i++)
|
for (size_t i = 0; i < length; i++)
|
||||||
@@ -407,7 +423,7 @@ GpFileSystem_Win32 *GpFileSystem_Win32::GetInstance()
|
|||||||
return &ms_instance;
|
return &ms_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, wchar_t *outPath)
|
bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, wchar_t *outPath)
|
||||||
{
|
{
|
||||||
const wchar_t *baseDir = nullptr;
|
const wchar_t *baseDir = nullptr;
|
||||||
|
|
||||||
@@ -445,23 +461,39 @@ bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::VirtualDirectory_t virtua
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
const size_t baseDirLen = wcslen(baseDir);
|
const size_t baseDirLen = wcslen(baseDir);
|
||||||
const size_t pathLen = strlen(path);
|
|
||||||
|
|
||||||
if (baseDirLen >= MAX_PATH || MAX_PATH - baseDirLen < pathLen)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
memcpy(outPath, baseDir, sizeof(wchar_t) * baseDirLen);
|
memcpy(outPath, baseDir, sizeof(wchar_t) * baseDirLen);
|
||||||
for (size_t i = 0; i < pathLen; i++)
|
outPath[baseDirLen] = static_cast<wchar_t>(0);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < numPaths; i++)
|
||||||
{
|
{
|
||||||
char c = path[i];
|
size_t outDirLen = wcslen(outPath);
|
||||||
if (c == '/')
|
|
||||||
c = '\\';
|
|
||||||
|
|
||||||
outPath[baseDirLen + i] = static_cast<wchar_t>(c);
|
if (i != 0)
|
||||||
|
{
|
||||||
|
if (baseDirLen >= MAX_PATH || MAX_PATH - baseDirLen < 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
outPath[outDirLen++] = '\\';
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *path = paths[i];
|
||||||
|
const size_t pathLen = strlen(path);
|
||||||
|
|
||||||
|
if (baseDirLen >= MAX_PATH || MAX_PATH - baseDirLen < pathLen)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t j = 0; j < pathLen; j++)
|
||||||
|
{
|
||||||
|
char c = path[j];
|
||||||
|
if (c == '/')
|
||||||
|
c = '\\';
|
||||||
|
|
||||||
|
outPath[outDirLen + j] = static_cast<wchar_t>(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
outPath[outDirLen + pathLen] = static_cast<wchar_t>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
outPath[baseDirLen + pathLen] = static_cast<wchar_t>(0);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,19 +14,21 @@ public:
|
|||||||
|
|
||||||
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
|
bool FileExists(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path) override;
|
||||||
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists) override;
|
bool FileLocked(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool *exists) override;
|
||||||
GpIOStream *OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition) override;
|
GpIOStream *OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition) override;
|
||||||
bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) override;
|
bool DeleteFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool &existed) override;
|
||||||
PortabilityLayer::HostDirectoryCursor *ScanDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory) override;
|
PortabilityLayer::HostDirectoryCursor *ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths) override;
|
||||||
|
|
||||||
bool ValidateFilePath(const char *path, size_t sz) const override;
|
bool ValidateFilePath(const char *path, size_t sz) const override;
|
||||||
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
|
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
|
||||||
|
|
||||||
|
bool IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const override;
|
||||||
|
|
||||||
const wchar_t *GetBasePath() const;
|
const wchar_t *GetBasePath() const;
|
||||||
|
|
||||||
static GpFileSystem_Win32 *GetInstance();
|
static GpFileSystem_Win32 *GetInstance();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, wchar_t *outPath);
|
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, wchar_t *outPath);
|
||||||
|
|
||||||
std::wstring m_prefsDir;
|
std::wstring m_prefsDir;
|
||||||
std::wstring m_scoresDir;
|
std::wstring m_scoresDir;
|
||||||
|
|||||||
1
AerofoilAndroid/.gitignore
vendored
1
AerofoilAndroid/.gitignore
vendored
@@ -2,3 +2,4 @@
|
|||||||
.gradle
|
.gradle
|
||||||
gradle
|
gradle
|
||||||
local.properties
|
local.properties
|
||||||
|
build
|
||||||
|
|||||||
49
AerofoilAndroid/copy_packaged_resources.bat
Normal file
49
AerofoilAndroid/copy_packaged_resources.bat
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
rmdir /S /Q app\src\main\assets\Packaged\ApplicationResources
|
||||||
|
..\Tools\7z.exe x -oapp\src\main\assets\Packaged\ApplicationResources ..\Packaged\ApplicationResources.gpa
|
||||||
|
cd app
|
||||||
|
cd src
|
||||||
|
cd main
|
||||||
|
cd assets
|
||||||
|
cd Packaged
|
||||||
|
rmdir /S /Q Houses
|
||||||
|
mkdir Houses
|
||||||
|
copy ..\..\..\..\..\..\Packaged\Houses\* Houses\
|
||||||
|
cd Houses
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oArt Museum" "Art Museum.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oArt Museum.mov" "Art Museum.mov.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oCalifornia or Bust!" "California or Bust!.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oCastle o' the Air" "Castle o' the Air.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oCastle o' the Air.mov" "Castle o' the Air.mov.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oCD Demo House" "CD Demo House.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oCD Demo House.mov" "CD Demo House.mov.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oDavis Station" "Davis Station.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oDemo House" "Demo House.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oDemo House.mov" "Demo House.mov.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oEmpty House" "Empty House.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oFun House" "Fun House.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oGrand Prix" "Grand Prix.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oGrand Prix.mov" "Grand Prix.mov.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oImagineHouse PRO II" "ImagineHouse PRO II.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oImagineHouse PRO II.mov" "ImagineHouse PRO II.mov.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oIn The Mirror" "In The Mirror.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oLand of Illusion" "Land of Illusion.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oLand of Illusion.mov" "Land of Illusion.mov.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oLeviathan" "Leviathan.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oLeviathan.mov" "Leviathan.mov.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oMetropolis" "Metropolis.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oNemo's Market" "Nemo's Market.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oNemo's Market.mov" "Nemo's Market.mov.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oRainbow's End" "Rainbow's End.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oRainbow's End.mov" "Rainbow's End.mov.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oSampler" "Sampler.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oSlumberland" "Slumberland.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oSlumberland.mov" "Slumberland.mov.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oSpacePods" "SpacePods.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oSpacePods.mov" "SpacePods.mov.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oTeddy World" "Teddy World.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oTeddy World.mov" "Teddy World.mov.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oThe Asylum Pro" "The Asylum Pro.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oTitanic" "Titanic.gpa"
|
||||||
|
..\..\..\..\..\..\..\Tools\7z.exe x "-oTitanic.mov" "Titanic.mov.gpa"
|
||||||
|
del /Q *.gpa
|
||||||
|
cd ..
|
||||||
@@ -17,7 +17,6 @@ mklink /D app\jni\zlib ..\..\..\zlib
|
|||||||
mklink /D app\jni\rapidjson ..\..\..\rapidjson
|
mklink /D app\jni\rapidjson ..\..\..\rapidjson
|
||||||
mklink /D app\jni\MacRomanConversion ..\..\..\MacRomanConversion
|
mklink /D app\jni\MacRomanConversion ..\..\..\MacRomanConversion
|
||||||
mklink /D app\jni\stb ..\..\..\stb
|
mklink /D app\jni\stb ..\..\..\stb
|
||||||
mklink /D app\src\main\assets\Packaged ..\..\..\..\..\Packaged
|
|
||||||
mklink /D app\src\main\assets\Resources ..\..\..\..\..\Resources
|
mklink /D app\src\main\assets\Resources ..\..\..\..\..\Resources
|
||||||
|
|
||||||
pause
|
pause
|
||||||
|
|||||||
@@ -14,5 +14,4 @@ rmdir app\jni\zlib
|
|||||||
rmdir app\jni\rapidjson
|
rmdir app\jni\rapidjson
|
||||||
rmdir app\jni\MacRomanConversion
|
rmdir app\jni\MacRomanConversion
|
||||||
rmdir app\jni\stb
|
rmdir app\jni\stb
|
||||||
rmdir app\src\main\assets\Packaged
|
|
||||||
rmdir app\src\main\assets\Resources
|
rmdir app\src\main\assets\Resources
|
||||||
|
|||||||
@@ -419,110 +419,6 @@ void HandleDepthSwitching (void)
|
|||||||
PortabilityLayer::HostDisplayDriver::GetInstance()->SetUseICCProfile(isUseICCProfile != 0);
|
PortabilityLayer::HostDisplayDriver::GetInstance()->SetUseICCProfile(isUseICCProfile != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------- CheckMemorySize
|
|
||||||
|
|
||||||
// Tests for a specific amount of memory available. If the required memory<72>
|
|
||||||
// is not available, attempts to turn off various game features (music, etc.)<29>
|
|
||||||
// in order to accomodate the constrained memory available.
|
|
||||||
|
|
||||||
void CheckMemorySize (void)
|
|
||||||
{
|
|
||||||
#define kBaseBytesNeeded 614400L // 600K Base memory
|
|
||||||
#define kPaddingBytes 204800L // 200K Padding
|
|
||||||
long bytesNeeded;
|
|
||||||
long soundBytes, musicBytes;
|
|
||||||
|
|
||||||
dontLoadMusic = false;
|
|
||||||
dontLoadSounds = false;
|
|
||||||
|
|
||||||
bytesNeeded = kBaseBytesNeeded; // base memory
|
|
||||||
soundBytes = SoundBytesNeeded(); // sound memory
|
|
||||||
if (soundBytes <= 0L)
|
|
||||||
RedAlert(kErrNoMemory);
|
|
||||||
else
|
|
||||||
bytesNeeded += soundBytes;
|
|
||||||
musicBytes = MusicBytesNeeded(); // music memory
|
|
||||||
if (musicBytes <= 0L)
|
|
||||||
RedAlert(kErrNoMemory);
|
|
||||||
else
|
|
||||||
bytesNeeded += musicBytes;
|
|
||||||
bytesNeeded += 4L * (long)thisMac.constrainedScreen.bottom; // main screen
|
|
||||||
bytesNeeded += (((long)houseRect.right - (long)houseRect.left) *
|
|
||||||
((long)houseRect.bottom + 1 - (long)houseRect.top) *
|
|
||||||
(long)thisMac.isDepth) / 8L; // work map
|
|
||||||
bytesNeeded += 4L * (long)houseRect.bottom;
|
|
||||||
bytesNeeded += (((long)houseRect.right - (long)houseRect.left) *
|
|
||||||
((long)houseRect.bottom + 1 - (long)houseRect.top) *
|
|
||||||
(long)thisMac.isDepth) / 8L; // back map
|
|
||||||
bytesNeeded += 4L * houseRect.bottom;
|
|
||||||
bytesNeeded += (((long)houseRect.right - (long)houseRect.left) * 21 *
|
|
||||||
(long)thisMac.isDepth) / 8L; // scoreboard map
|
|
||||||
bytesNeeded += (6396L * (long)thisMac.isDepth) / 8L; // more scoreboard
|
|
||||||
bytesNeeded += (32112L * (long)thisMac.isDepth) / 8L; // glider map
|
|
||||||
bytesNeeded += (32112L * (long)thisMac.isDepth) / 8L; // glider2 map
|
|
||||||
bytesNeeded += 32064L / 8L; // glider mask
|
|
||||||
bytesNeeded += (912L * (long)thisMac.isDepth) / 8L; // glider shadow
|
|
||||||
bytesNeeded += 864L / 8L; // shadow mask
|
|
||||||
bytesNeeded += (304L * (long)thisMac.isDepth) / 8L; // rubber bands
|
|
||||||
bytesNeeded += 288L / 8L; // bands mask
|
|
||||||
bytesNeeded += (19344L * (long)thisMac.isDepth) / 8L; // blower map
|
|
||||||
bytesNeeded += 19344L / 8L; // blower mask
|
|
||||||
bytesNeeded += (17856L * (long)thisMac.isDepth) / 8L; // furniture map
|
|
||||||
bytesNeeded += 17792L / 8L; // furniture mask
|
|
||||||
bytesNeeded += (33264L * (long)thisMac.isDepth) / 8L; // prizes map
|
|
||||||
bytesNeeded += 33176L / 8L; // prizes mask
|
|
||||||
bytesNeeded += (2904L * (long)thisMac.isDepth) / 8L; // points map
|
|
||||||
bytesNeeded += 2880L / 8L; // points mask
|
|
||||||
bytesNeeded += (1848L * (long)thisMac.isDepth) / 8L; // transport map
|
|
||||||
bytesNeeded += 1792L / 8L; // transport mask
|
|
||||||
bytesNeeded += (3360L * (long)thisMac.isDepth) / 8L; // switches map
|
|
||||||
bytesNeeded += (9144L * (long)thisMac.isDepth) / 8L; // lights map
|
|
||||||
bytesNeeded += 9072L / 8L; // lights mask
|
|
||||||
bytesNeeded += (21600L * (long)thisMac.isDepth) / 8L; // appliances map
|
|
||||||
bytesNeeded += 21520L / 8L; // appliances mask
|
|
||||||
bytesNeeded += (5600L * (long)thisMac.isDepth) / 8L; // toast map
|
|
||||||
bytesNeeded += 5568L / 8L; // toast mask
|
|
||||||
bytesNeeded += (1440L * (long)thisMac.isDepth) / 8L; // shredded map
|
|
||||||
bytesNeeded += 1400L / 8L; // shredded mask
|
|
||||||
bytesNeeded += (5784L * (long)thisMac.isDepth) / 8L; // balloon map
|
|
||||||
bytesNeeded += 5760L / 8L; // balloon mask
|
|
||||||
bytesNeeded += (9632L * (long)thisMac.isDepth) / 8L; // copter map
|
|
||||||
bytesNeeded += 9600L / 8L; // copter mask
|
|
||||||
bytesNeeded += (4928L * (long)thisMac.isDepth) / 8L; // dart map
|
|
||||||
bytesNeeded += 4864L / 8L; // dart mask
|
|
||||||
bytesNeeded += (2080L * (long)thisMac.isDepth) / 8L; // ball map
|
|
||||||
bytesNeeded += 2048L / 8L; // ball mask
|
|
||||||
bytesNeeded += (1168L * (long)thisMac.isDepth) / 8L; // drip map
|
|
||||||
bytesNeeded += 1152L / 8L; // drip mask
|
|
||||||
bytesNeeded += (1224L * (long)thisMac.isDepth) / 8L; // enemy map
|
|
||||||
bytesNeeded += 1188L / 8L; // enemy mask
|
|
||||||
bytesNeeded += (2064L * (long)thisMac.isDepth) / 8L; // fish map
|
|
||||||
bytesNeeded += 2048L / 8L; // fish mask
|
|
||||||
bytesNeeded += (8960L * (long)thisMac.isDepth) / 8L; // clutter map
|
|
||||||
bytesNeeded += 8832L / 8L; // clutter mask
|
|
||||||
bytesNeeded += (23040L * (long)thisMac.isDepth) / 8L; // support map
|
|
||||||
bytesNeeded += (4320L * (long)thisMac.isDepth) / 8L; // angel map
|
|
||||||
bytesNeeded += 4224L / 8L; // angel mask
|
|
||||||
bytesNeeded += sizeof(roomType);
|
|
||||||
bytesNeeded += sizeof(hotObject) * kMaxHotSpots;
|
|
||||||
bytesNeeded += sizeof(sparkleType) * kMaxSparkles;
|
|
||||||
bytesNeeded += sizeof(flyingPtType) * kMaxFlyingPts;
|
|
||||||
bytesNeeded += sizeof(flameType) * kMaxCandles;
|
|
||||||
bytesNeeded += sizeof(flameType) * kMaxTikis;
|
|
||||||
bytesNeeded += sizeof(flameType) * kMaxCoals;
|
|
||||||
bytesNeeded += sizeof(pendulumType) * kMaxPendulums;
|
|
||||||
bytesNeeded += sizeof(savedType) * kMaxSavedMaps;
|
|
||||||
bytesNeeded += sizeof(bandType) * kMaxRubberBands;
|
|
||||||
bytesNeeded += sizeof(greaseType) * kMaxGrease;
|
|
||||||
bytesNeeded += sizeof(starType) * kMaxStars;
|
|
||||||
bytesNeeded += sizeof(shredType) * kMaxShredded;
|
|
||||||
bytesNeeded += sizeof(dynaType) * kMaxDynamicObs;
|
|
||||||
bytesNeeded += sizeof(objDataType) * kMaxMasterObjects;
|
|
||||||
bytesNeeded += kDemoLength; SpinCursor(1);
|
|
||||||
|
|
||||||
SpinCursor(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetDeviceRect(Rect *rect)
|
void GetDeviceRect(Rect *rect)
|
||||||
{
|
{
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
namespace PortabilityLayer
|
namespace PortabilityLayer
|
||||||
{
|
{
|
||||||
class ResolveCachingColor;
|
class ResolveCachingColor;
|
||||||
class ResourceArchive;
|
struct IResourceArchive;
|
||||||
class ScanlineMask;
|
class ScanlineMask;
|
||||||
class ResTypeID;
|
class ResTypeID;
|
||||||
struct RGBAColor;
|
struct RGBAColor;
|
||||||
@@ -169,7 +169,6 @@ void CheckOurEnvirons (void);
|
|||||||
void InstallResolutionHandler (void);
|
void InstallResolutionHandler (void);
|
||||||
//void ReflectSecondMonitorEnvirons (Boolean, Boolean, Boolean);
|
//void ReflectSecondMonitorEnvirons (Boolean, Boolean, Boolean);
|
||||||
void HandleDepthSwitching (void);
|
void HandleDepthSwitching (void);
|
||||||
void CheckMemorySize (void);
|
|
||||||
|
|
||||||
Boolean CheckFileError (short, const PLPasStr &); // --- File Error.c
|
Boolean CheckFileError (short, const PLPasStr &); // --- File Error.c
|
||||||
|
|
||||||
@@ -200,7 +199,7 @@ void LoadGraphic (DrawSurface *surface, short resID); // Only loads from app r
|
|||||||
void LoadGraphicCustom (DrawSurface *surface, short resID); // Supports custom graphics
|
void LoadGraphicCustom (DrawSurface *surface, short resID); // Supports custom graphics
|
||||||
void LoadScaledGraphic (DrawSurface *, short, Rect *); // Only loads from app resources
|
void LoadScaledGraphic (DrawSurface *, short, Rect *); // Only loads from app resources
|
||||||
void LoadScaledGraphicCustom (DrawSurface *, short, Rect *); // Supports custom graphics
|
void LoadScaledGraphicCustom (DrawSurface *, short, Rect *); // Supports custom graphics
|
||||||
bool LargeIconPlot (DrawSurface *, PortabilityLayer::ResourceArchive *, short, const Rect &);
|
bool LargeIconPlot (DrawSurface *, PortabilityLayer::IResourceArchive *, short, const Rect &);
|
||||||
void DrawCIcon (DrawSurface *surface, short, short, short);
|
void DrawCIcon (DrawSurface *surface, short, short, short);
|
||||||
char KeyMapOffsetFromRawKey (char);
|
char KeyMapOffsetFromRawKey (char);
|
||||||
long LongSquareRoot (long);
|
long LongSquareRoot (long);
|
||||||
|
|||||||
@@ -235,7 +235,6 @@ void ToggleMusicWhilePlaying (void);
|
|||||||
void SetMusicalMode (SInt16);
|
void SetMusicalMode (SInt16);
|
||||||
void InitMusic (void);
|
void InitMusic (void);
|
||||||
void KillMusic (void);
|
void KillMusic (void);
|
||||||
long MusicBytesNeeded (void);
|
|
||||||
void TellHerNoMusic (void);
|
void TellHerNoMusic (void);
|
||||||
|
|
||||||
Boolean AddNewObject (Point, SInt16, Boolean); // --- ObjectAdd.c
|
Boolean AddNewObject (Point, SInt16, Boolean); // --- ObjectAdd.c
|
||||||
@@ -456,7 +455,6 @@ PLError_t LoadTriggerSound (SInt16);
|
|||||||
void DumpTriggerSound (void);
|
void DumpTriggerSound (void);
|
||||||
void InitSound (void);
|
void InitSound (void);
|
||||||
void KillSound (void);
|
void KillSound (void);
|
||||||
long SoundBytesNeeded (void);
|
|
||||||
void TellHerNoSounds (void);
|
void TellHerNoSounds (void);
|
||||||
void BitchAboutSM3 (void);
|
void BitchAboutSM3 (void);
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
void UpdateGoToDialog (Dialog *);
|
void UpdateGoToDialog (Dialog *);
|
||||||
int16_t GoToFilter (void *context, Dialog *dial, const TimeTaggedVOSEvent *evt);
|
int16_t GoToFilter (void *context, Dialog *dial, const TimeTaggedVOSEvent *evt);
|
||||||
|
|
||||||
extern PortabilityLayer::ResourceArchive *houseResFork;
|
extern PortabilityLayer::IResourceArchive *houseResFork;
|
||||||
|
|
||||||
|
|
||||||
houseHand thisHouse;
|
houseHand thisHouse;
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ Boolean IsFileReadOnly (const VFileSpec &);
|
|||||||
|
|
||||||
AnimationPlayer theMovie;
|
AnimationPlayer theMovie;
|
||||||
Rect movieRect;
|
Rect movieRect;
|
||||||
PortabilityLayer::ResourceArchive *houseResFork;
|
PortabilityLayer::IResourceArchive *houseResFork;
|
||||||
short wasHouseVersion;
|
short wasHouseVersion;
|
||||||
GpIOStream *houseStream;
|
GpIOStream *houseStream;
|
||||||
Boolean houseOpen, fileDirty, gameDirty;
|
Boolean houseOpen, fileDirty, gameDirty;
|
||||||
|
|||||||
@@ -373,7 +373,6 @@ int gpAppMain()
|
|||||||
// ReflectSecondMonitorEnvirons(false, true, true);
|
// ReflectSecondMonitorEnvirons(false, true, true);
|
||||||
HandleDepthSwitching();
|
HandleDepthSwitching();
|
||||||
VariableInit(); SpinCursor(2);
|
VariableInit(); SpinCursor(2);
|
||||||
CheckMemorySize();
|
|
||||||
GetExtraCursors(); SpinCursor(2);
|
GetExtraCursors(); SpinCursor(2);
|
||||||
InitMarquee();
|
InitMarquee();
|
||||||
CreatePointers(); SpinCursor(2);
|
CreatePointers(); SpinCursor(2);
|
||||||
|
|||||||
@@ -368,25 +368,6 @@ void KillMusic (void)
|
|||||||
musicMutex->Destroy();
|
musicMutex->Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------- MusicBytesNeeded
|
|
||||||
|
|
||||||
long MusicBytesNeeded (void)
|
|
||||||
{
|
|
||||||
size_t totalBytes;
|
|
||||||
short i;
|
|
||||||
|
|
||||||
totalBytes = 0L;
|
|
||||||
for (i = 0; i < kMaxMusic; i++)
|
|
||||||
{
|
|
||||||
size_t resSize = 0;
|
|
||||||
if (!PortabilityLayer::ResourceManager::GetInstance()->GetAppResourceArchive()->GetResourceSize('snd ', i + kBaseBufferMusicID, resSize))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
totalBytes += static_cast<long>(resSize);
|
|
||||||
}
|
|
||||||
return totalBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------- TellHerNoMusic
|
//-------------------------------------------------------------- TellHerNoMusic
|
||||||
|
|
||||||
void TellHerNoMusic (void)
|
void TellHerNoMusic (void)
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ Boolean originalFloor;
|
|||||||
extern IGpCursor *handCursor;
|
extern IGpCursor *handCursor;
|
||||||
extern short lastBackground;
|
extern short lastBackground;
|
||||||
|
|
||||||
extern PortabilityLayer::ResourceArchive *houseResFork;
|
extern PortabilityLayer::IResourceArchive *houseResFork;
|
||||||
|
|
||||||
|
|
||||||
//============================================================== Functions
|
//============================================================== Functions
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ void UpdateLoadDialog (Dialog *theDialog)
|
|||||||
|
|
||||||
if (SectRect(&dialogRect, &tempRect, &dummyRect))
|
if (SectRect(&dialogRect, &tempRect, &dummyRect))
|
||||||
{
|
{
|
||||||
PortabilityLayer::ResourceArchive *resFile = PortabilityLayer::ResourceManager::GetInstance()->LoadResFile(theHousesSpecs[i].m_dir, theHousesSpecs[i].m_name);
|
PortabilityLayer::IResourceArchive *resFile = PortabilityLayer::ResourceManager::GetInstance()->LoadResFile(theHousesSpecs[i].m_dir, theHousesSpecs[i].m_name);
|
||||||
if (resFile != nullptr)
|
if (resFile != nullptr)
|
||||||
{
|
{
|
||||||
if (!LargeIconPlot(surface, resFile, -16455, tempRect))
|
if (!LargeIconPlot(surface, resFile, -16455, tempRect))
|
||||||
|
|||||||
@@ -367,27 +367,6 @@ void KillSound (void)
|
|||||||
DumpBufferSounds();
|
DumpBufferSounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------- SoundBytesNeeded
|
|
||||||
|
|
||||||
long SoundBytesNeeded (void)
|
|
||||||
{
|
|
||||||
long totalBytes;
|
|
||||||
short i;
|
|
||||||
|
|
||||||
totalBytes = 0L;
|
|
||||||
for (i = 0; i < kMaxSounds - 1; i++)
|
|
||||||
{
|
|
||||||
size_t resSize = 0;
|
|
||||||
if (!PortabilityLayer::ResourceManager::GetInstance()->GetAppResourceArchive()->GetResourceSize('snd ', i + kBaseBufferSoundID, resSize))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
totalBytes += static_cast<long>(resSize);
|
|
||||||
// ReleaseResource(theSound);
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------- TellHerNoSounds
|
//-------------------------------------------------------------- TellHerNoSounds
|
||||||
|
|
||||||
void TellHerNoSounds (void)
|
void TellHerNoSounds (void)
|
||||||
|
|||||||
@@ -330,7 +330,7 @@ void LoadScaledGraphicCustom(DrawSurface *surface, short resID, Rect *theRect)
|
|||||||
//-------------------------------------------------------------- LargeIconPlot
|
//-------------------------------------------------------------- LargeIconPlot
|
||||||
// Draws a standard b&w icon (32 x 32) - resource is an 'ICON'.
|
// Draws a standard b&w icon (32 x 32) - resource is an 'ICON'.
|
||||||
|
|
||||||
bool LargeIconPlot (DrawSurface *surface, PortabilityLayer::ResourceArchive *resFile, short resID, const Rect &theRect)
|
bool LargeIconPlot (DrawSurface *surface, PortabilityLayer::IResourceArchive *resFile, short resID, const Rect &theRect)
|
||||||
{
|
{
|
||||||
Handle hdl = resFile->LoadResource('icl8', resID);
|
Handle hdl = resFile->LoadResource('icl8', resID);
|
||||||
if (hdl)
|
if (hdl)
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ static const char *gs_forbiddenNames[] =
|
|||||||
"LPT9",
|
"LPT9",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool IsCharForbidden(char c)
|
||||||
|
{
|
||||||
|
return (c < ' ' || c == '<' || c == '>' || c == ':' || c == '\"' || c == '/' || c == '\\' || c == '|' || c == '?' || c == '*' || c > '~' || c == '$' || c == '#');
|
||||||
|
}
|
||||||
|
|
||||||
namespace PortabilityLayer
|
namespace PortabilityLayer
|
||||||
{
|
{
|
||||||
GpArcResourceTypeTag GpArcResourceTypeTag::Encode(const ResTypeID &tag)
|
GpArcResourceTypeTag GpArcResourceTypeTag::Encode(const ResTypeID &tag)
|
||||||
@@ -42,7 +47,7 @@ namespace PortabilityLayer
|
|||||||
{
|
{
|
||||||
char c = chars[i];
|
char c = chars[i];
|
||||||
|
|
||||||
bool isForbidden = (c < ' ' || c == '<' || c == '>' || c == ':' || c == '\"' || c == '/' || c == '\\' || c == '|' || c == '?' || c == '*' || c > '~' || c == '$');
|
bool isForbidden = IsCharForbidden(c);
|
||||||
|
|
||||||
if (i == 3)
|
if (i == 3)
|
||||||
{
|
{
|
||||||
@@ -81,4 +86,57 @@ namespace PortabilityLayer
|
|||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GpArcResourceTypeTag::Load(const char *str)
|
||||||
|
{
|
||||||
|
size_t l = strlen(str);
|
||||||
|
if (l < sizeof(m_id))
|
||||||
|
{
|
||||||
|
memcpy(m_id, str, l);
|
||||||
|
m_id[l] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GpArcResourceTypeTag::Decode(ResTypeID &outTag)
|
||||||
|
{
|
||||||
|
char decodedChars[4];
|
||||||
|
size_t parseOffset = 0;
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
char parseChar = m_id[parseOffset];
|
||||||
|
if (parseChar == '\0')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (parseChar == '$')
|
||||||
|
{
|
||||||
|
char nibbles[2] = { m_id[parseOffset + 1], m_id[parseOffset + 2] };
|
||||||
|
parseOffset += 2;
|
||||||
|
|
||||||
|
int decodedNibbles[2];
|
||||||
|
|
||||||
|
for (int n = 0; n < 2; n++)
|
||||||
|
{
|
||||||
|
char nibble = nibbles[n];
|
||||||
|
if (nibble >= '0' && nibble <= '9')
|
||||||
|
decodedNibbles[n] = nibble - '0';
|
||||||
|
else if (nibble >= 'a' && nibble <= 'f')
|
||||||
|
decodedNibbles[n] = nibble - 'a' + 0xa;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
decodedChars[i] = (decodedNibbles[0] << 4) | (decodedNibbles[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
decodedChars[i] = parseChar;
|
||||||
|
|
||||||
|
parseOffset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
outTag = ResTypeID(decodedChars);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,8 @@ namespace PortabilityLayer
|
|||||||
char m_id[13];
|
char m_id[13];
|
||||||
|
|
||||||
static GpArcResourceTypeTag Encode(const ResTypeID &tag);
|
static GpArcResourceTypeTag Encode(const ResTypeID &tag);
|
||||||
|
|
||||||
|
bool Load(const char *str);
|
||||||
|
bool Decode(ResTypeID &outTag);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,17 +16,32 @@ namespace PortabilityLayer
|
|||||||
public:
|
public:
|
||||||
virtual bool FileExists(VirtualDirectory_t virtualDirectory, const char *path) = 0;
|
virtual bool FileExists(VirtualDirectory_t virtualDirectory, const char *path) = 0;
|
||||||
virtual bool FileLocked(VirtualDirectory_t virtualDirectory, const char *path, bool *exists) = 0;
|
virtual bool FileLocked(VirtualDirectory_t virtualDirectory, const char *path, bool *exists) = 0;
|
||||||
virtual GpIOStream *OpenFile(VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition) = 0;
|
virtual GpIOStream *OpenFileNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* subPaths, size_t numSubPaths, bool writeAccess, GpFileCreationDisposition_t createDisposition) = 0;
|
||||||
virtual bool DeleteFile(VirtualDirectory_t virtualDirectory, const char *path, bool &existed) = 0;
|
virtual bool DeleteFile(VirtualDirectory_t virtualDirectory, const char *path, bool &existed) = 0;
|
||||||
virtual HostDirectoryCursor *ScanDirectory(VirtualDirectory_t virtualDirectory) = 0;
|
virtual HostDirectoryCursor *ScanDirectoryNested(VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths) = 0;
|
||||||
|
HostDirectoryCursor *ScanDirectory(VirtualDirectory_t virtualDirectory);
|
||||||
|
|
||||||
virtual bool ValidateFilePath(const char *path, size_t pathLen) const = 0;
|
virtual bool ValidateFilePath(const char *path, size_t pathLen) const = 0;
|
||||||
virtual bool ValidateFilePathUnicodeChar(uint32_t ch) const = 0;
|
virtual bool ValidateFilePathUnicodeChar(uint32_t ch) const = 0;
|
||||||
|
|
||||||
|
virtual bool IsVirtualDirectoryLooseResources(VirtualDirectory_t virtualDir) const = 0;
|
||||||
|
|
||||||
static HostFileSystem *GetInstance();
|
static HostFileSystem *GetInstance();
|
||||||
static void SetInstance(HostFileSystem *instance);
|
static void SetInstance(HostFileSystem *instance);
|
||||||
|
|
||||||
|
GpIOStream *OpenFile(VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static HostFileSystem *ms_instance;
|
static HostFileSystem *ms_instance;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline GpIOStream *PortabilityLayer::HostFileSystem::OpenFile(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition)
|
||||||
|
{
|
||||||
|
return this->OpenFileNested(virtualDirectory, &path, 1, writeAccess, createDisposition);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PortabilityLayer::HostDirectoryCursor *PortabilityLayer::HostFileSystem::ScanDirectory(VirtualDirectory_t virtualDirectory)
|
||||||
|
{
|
||||||
|
return this->ScanDirectoryNested(virtualDirectory, nullptr, 0);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#ifndef __PL_HOST_SYSTEM_SERVICES_H__
|
|
||||||
#define __PL_HOST_SYSTEM_SERVICES_H__
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -34,5 +32,3 @@ namespace PortabilityLayer
|
|||||||
static HostSystemServices *ms_instance;
|
static HostSystemServices *ms_instance;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace PortabilityLayer
|
namespace PortabilityLayer
|
||||||
{
|
{
|
||||||
class ResourceArchive;
|
struct IResourceArchive;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DrawSurface;
|
struct DrawSurface;
|
||||||
@@ -52,7 +52,7 @@ private:
|
|||||||
~AnimationPackage();
|
~AnimationPackage();
|
||||||
|
|
||||||
THandle<BitmapImage> *m_images;
|
THandle<BitmapImage> *m_images;
|
||||||
PortabilityLayer::ResourceArchive *m_resArchive;
|
PortabilityLayer::IResourceArchive *m_resArchive;
|
||||||
size_t m_numImages;
|
size_t m_numImages;
|
||||||
|
|
||||||
uint32_t m_frameRateNumerator;
|
uint32_t m_frameRateNumerator;
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#include "ResourceManager.h"
|
#include "ResourceManager.h"
|
||||||
|
|
||||||
|
#include "BinarySearch.h"
|
||||||
#include "BMPFormat.h"
|
#include "BMPFormat.h"
|
||||||
#include "FileManager.h"
|
#include "FileManager.h"
|
||||||
#include "GPArchive.h"
|
#include "GPArchive.h"
|
||||||
|
#include "HostDirectoryCursor.h"
|
||||||
#include "HostFileSystem.h"
|
#include "HostFileSystem.h"
|
||||||
#include "HostMemoryBuffer.h"
|
#include "HostMemoryBuffer.h"
|
||||||
#include "GpIOStream.h"
|
#include "GpIOStream.h"
|
||||||
@@ -21,6 +23,7 @@
|
|||||||
#include "ZipFile.h"
|
#include "ZipFile.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace ResourceValidationRules
|
namespace ResourceValidationRules
|
||||||
{
|
{
|
||||||
@@ -97,7 +100,7 @@ namespace
|
|||||||
namespace PortabilityLayer
|
namespace PortabilityLayer
|
||||||
{
|
{
|
||||||
struct MMHandleBlock;
|
struct MMHandleBlock;
|
||||||
class ResourceArchive;
|
struct IResourceArchive;
|
||||||
|
|
||||||
class ResourceManagerImpl final : public ResourceManager
|
class ResourceManagerImpl final : public ResourceManager
|
||||||
{
|
{
|
||||||
@@ -108,9 +111,9 @@ namespace PortabilityLayer
|
|||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
|
|
||||||
THandle<void> GetAppResource(const ResTypeID &resTypeID, int16_t resID) const override;
|
THandle<void> GetAppResource(const ResTypeID &resTypeID, int16_t resID) const override;
|
||||||
ResourceArchive *GetAppResourceArchive() const override;
|
IResourceArchive *GetAppResourceArchive() const override;
|
||||||
|
|
||||||
ResourceArchive *LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const override;
|
IResourceArchive *LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const override;
|
||||||
PLError_t CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) override;
|
PLError_t CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) override;
|
||||||
|
|
||||||
void DissociateHandle(MMHandleBlock *hdl) const override;
|
void DissociateHandle(MMHandleBlock *hdl) const override;
|
||||||
@@ -119,9 +122,11 @@ namespace PortabilityLayer
|
|||||||
static ResourceManagerImpl *GetInstance();
|
static ResourceManagerImpl *GetInstance();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UnloadAndDestroyResourceFile(ResourceArchive *rf);
|
void UnloadAndDestroyResourceFile(IResourceArchive *rf);
|
||||||
|
|
||||||
ResourceArchive *m_appResArchive;
|
IResourceArchive *LoadResDirectory(VirtualDirectory_t virtualDir, const PLPasStr &filename) const;
|
||||||
|
|
||||||
|
IResourceArchive *m_appResArchive;
|
||||||
|
|
||||||
static ResourceManagerImpl ms_instance;
|
static ResourceManagerImpl ms_instance;
|
||||||
};
|
};
|
||||||
@@ -157,18 +162,36 @@ namespace PortabilityLayer
|
|||||||
return hdl->m_rmSelfRef;
|
return hdl->m_rmSelfRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceManagerImpl::UnloadAndDestroyResourceFile(ResourceArchive *rf)
|
void ResourceManagerImpl::UnloadAndDestroyResourceFile(IResourceArchive *rf)
|
||||||
{
|
{
|
||||||
rf->Destroy();
|
rf->Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IResourceArchive *ResourceManagerImpl::LoadResDirectory(VirtualDirectory_t virtualDir, const PLPasStr &filename) const
|
||||||
|
{
|
||||||
|
ResourceArchiveDirectory *archive = ResourceArchiveDirectory::Create(virtualDir, filename);
|
||||||
|
if (!archive)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (!archive->Init())
|
||||||
|
{
|
||||||
|
archive->Destroy();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return archive;
|
||||||
|
}
|
||||||
|
|
||||||
ResourceManagerImpl *ResourceManagerImpl::GetInstance()
|
ResourceManagerImpl *ResourceManagerImpl::GetInstance()
|
||||||
{
|
{
|
||||||
return &ms_instance;
|
return &ms_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceArchive *ResourceManagerImpl::LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const
|
IResourceArchive *ResourceManagerImpl::LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const
|
||||||
{
|
{
|
||||||
|
if (PortabilityLayer::HostFileSystem::GetInstance()->IsVirtualDirectoryLooseResources(virtualDir))
|
||||||
|
return LoadResDirectory(virtualDir, filename);
|
||||||
|
|
||||||
GpIOStream *fStream = nullptr;
|
GpIOStream *fStream = nullptr;
|
||||||
if (FileManager::GetInstance()->RawOpenFileResources(virtualDir, filename, EFilePermission_Read, true, GpFileCreationDispositions::kOpenExisting, fStream) != PLErrors::kNone)
|
if (FileManager::GetInstance()->RawOpenFileResources(virtualDir, filename, EFilePermission_Read, true, GpFileCreationDispositions::kOpenExisting, fStream) != PLErrors::kNone)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -180,7 +203,7 @@ namespace PortabilityLayer
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceArchive *archive = ResourceArchive::Create(proxy, fStream);
|
IResourceArchive *archive = ResourceArchiveZipFile::Create(proxy, fStream);
|
||||||
if (!archive)
|
if (!archive)
|
||||||
{
|
{
|
||||||
proxy->Destroy();
|
proxy->Destroy();
|
||||||
@@ -227,7 +250,7 @@ namespace PortabilityLayer
|
|||||||
return m_appResArchive->LoadResource(resType, resID);
|
return m_appResArchive->LoadResource(resType, resID);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceArchive *ResourceManagerImpl::GetAppResourceArchive() const
|
IResourceArchive *ResourceManagerImpl::GetAppResourceArchive() const
|
||||||
{
|
{
|
||||||
return m_appResArchive;
|
return m_appResArchive;
|
||||||
}
|
}
|
||||||
@@ -238,6 +261,31 @@ namespace PortabilityLayer
|
|||||||
|
|
||||||
// ===========================================================================================
|
// ===========================================================================================
|
||||||
|
|
||||||
|
const char *ResourceArchiveBase::GetFileExtensionForResType(const ResTypeID &resTypeID, int &outValidationRule)
|
||||||
|
{
|
||||||
|
const char *extension = ".bin";
|
||||||
|
outValidationRule = ResourceValidationRules::kNone;
|
||||||
|
|
||||||
|
if (resTypeID == ResTypeID('snd '))
|
||||||
|
{
|
||||||
|
extension = ".wav";
|
||||||
|
outValidationRule = ResourceValidationRules::kWAV;
|
||||||
|
}
|
||||||
|
else if (resTypeID == ResTypeID('Date') || resTypeID == ResTypeID('PICT'))
|
||||||
|
{
|
||||||
|
extension = kPICTExtension;
|
||||||
|
outValidationRule = ResourceValidationRules::kBMP;
|
||||||
|
}
|
||||||
|
else if (resTypeID == ResTypeID('STR#'))
|
||||||
|
extension = ".txt";
|
||||||
|
else if (resTypeID == ResTypeID('DITL') || resTypeID == ResTypeID('muvi'))
|
||||||
|
extension = ".json";
|
||||||
|
|
||||||
|
return extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===========================================================================================
|
||||||
|
|
||||||
ResourceArchiveRef::ResourceArchiveRef()
|
ResourceArchiveRef::ResourceArchiveRef()
|
||||||
: m_handle(nullptr)
|
: m_handle(nullptr)
|
||||||
, m_size(0)
|
, m_size(0)
|
||||||
@@ -245,7 +293,9 @@ namespace PortabilityLayer
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceArchive *ResourceArchive::Create(ZipFileProxy *zipFileProxy, GpIOStream *stream)
|
// ===========================================================================================
|
||||||
|
|
||||||
|
ResourceArchiveZipFile *ResourceArchiveZipFile::Create(ZipFileProxy *zipFileProxy, GpIOStream *stream)
|
||||||
{
|
{
|
||||||
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
||||||
|
|
||||||
@@ -262,39 +312,28 @@ namespace PortabilityLayer
|
|||||||
new (refs + i) ResourceArchiveRef();
|
new (refs + i) ResourceArchiveRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
void *storage = mm->Alloc(sizeof(ResourceArchive));
|
void *storage = mm->Alloc(sizeof(ResourceArchiveZipFile));
|
||||||
if (!storage)
|
if (!storage)
|
||||||
{
|
{
|
||||||
mm->Release(refs);
|
mm->Release(refs);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new (storage) ResourceArchive(zipFileProxy, stream, refs);
|
return new (storage) ResourceArchiveZipFile(zipFileProxy, stream, refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceArchive::Destroy()
|
void ResourceArchiveZipFile::Destroy()
|
||||||
{
|
{
|
||||||
this->~ResourceArchive();
|
this->~ResourceArchiveZipFile();
|
||||||
PortabilityLayer::MemoryManager::GetInstance()->Release(this);
|
PortabilityLayer::MemoryManager::GetInstance()->Release(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
THandle<void> ResourceArchive::LoadResource(const ResTypeID &resTypeID, int id)
|
THandle<void> ResourceArchiveZipFile::LoadResource(const ResTypeID &resTypeID, int id)
|
||||||
{
|
{
|
||||||
return GetResource(resTypeID, id, true);
|
return GetResource(resTypeID, id, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceArchive::GetResourceSize(const ResTypeID &resTypeID, int id, size_t &outSize) const
|
bool ResourceArchiveZipFile::HasAnyResourcesOfType(const ResTypeID &resTypeID) const
|
||||||
{
|
|
||||||
size_t index = 0;
|
|
||||||
int validationRule = 0;
|
|
||||||
if (!IndexResource(resTypeID, id, index, validationRule))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
outSize = m_zipFileProxy->GetFileSize(index);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ResourceArchive::HasAnyResourcesOfType(const ResTypeID &resTypeID) const
|
|
||||||
{
|
{
|
||||||
char resPrefix[6];
|
char resPrefix[6];
|
||||||
resTypeID.ExportAsChars(resPrefix);
|
resTypeID.ExportAsChars(resPrefix);
|
||||||
@@ -304,7 +343,7 @@ namespace PortabilityLayer
|
|||||||
return m_zipFileProxy->HasPrefix(resPrefix);
|
return m_zipFileProxy->HasPrefix(resPrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceArchive::FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const
|
bool ResourceArchiveZipFile::FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const
|
||||||
{
|
{
|
||||||
char resPrefix[6];
|
char resPrefix[6];
|
||||||
resTypeID.ExportAsChars(resPrefix);
|
resTypeID.ExportAsChars(resPrefix);
|
||||||
@@ -409,25 +448,9 @@ namespace PortabilityLayer
|
|||||||
return haveAny;
|
return haveAny;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceArchive::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 = ".bin";
|
const char *extension = GetFileExtensionForResType(resTypeID, outValidationRule);
|
||||||
outValidationRule = ResourceValidationRules::kNone;
|
|
||||||
|
|
||||||
if (resTypeID == ResTypeID('snd '))
|
|
||||||
{
|
|
||||||
extension = ".wav";
|
|
||||||
outValidationRule = ResourceValidationRules::kWAV;
|
|
||||||
}
|
|
||||||
else if (resTypeID == ResTypeID('Date') || resTypeID == ResTypeID('PICT'))
|
|
||||||
{
|
|
||||||
extension = kPICTExtension;
|
|
||||||
outValidationRule = ResourceValidationRules::kBMP;
|
|
||||||
}
|
|
||||||
else if (resTypeID == ResTypeID('STR#'))
|
|
||||||
extension = ".txt";
|
|
||||||
else if (resTypeID == ResTypeID('DITL') || resTypeID == ResTypeID('muvi'))
|
|
||||||
extension = ".json";
|
|
||||||
|
|
||||||
char resourceFile[64];
|
char resourceFile[64];
|
||||||
|
|
||||||
@@ -439,7 +462,7 @@ namespace PortabilityLayer
|
|||||||
return m_zipFileProxy->IndexFile(resourceFile, outIndex);
|
return m_zipFileProxy->IndexFile(resourceFile, outIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
THandle<void> ResourceArchive::GetResource(const ResTypeID &resTypeID, int id, bool load)
|
THandle<void> ResourceArchiveZipFile::GetResource(const ResTypeID &resTypeID, int id, bool load)
|
||||||
{
|
{
|
||||||
int validationRule = 0;
|
int validationRule = 0;
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
@@ -485,14 +508,14 @@ namespace PortabilityLayer
|
|||||||
return THandle<void>(handle);
|
return THandle<void>(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceArchive::ResourceArchive(ZipFileProxy *zipFileProxy, GpIOStream *stream, ResourceArchiveRef *resourceHandles)
|
ResourceArchiveZipFile::ResourceArchiveZipFile(ZipFileProxy *zipFileProxy, GpIOStream *stream, ResourceArchiveRef *resourceHandles)
|
||||||
: m_zipFileProxy(zipFileProxy)
|
: m_zipFileProxy(zipFileProxy)
|
||||||
, m_stream(stream)
|
, m_stream(stream)
|
||||||
, m_resourceHandles(resourceHandles)
|
, m_resourceHandles(resourceHandles)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceArchive::~ResourceArchive()
|
ResourceArchiveZipFile::~ResourceArchiveZipFile()
|
||||||
{
|
{
|
||||||
MemoryManager *mm = MemoryManager::GetInstance();
|
MemoryManager *mm = MemoryManager::GetInstance();
|
||||||
|
|
||||||
@@ -511,4 +534,333 @@ namespace PortabilityLayer
|
|||||||
m_zipFileProxy->Destroy();
|
m_zipFileProxy->Destroy();
|
||||||
m_stream->Close();
|
m_stream->Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========================================================================================
|
||||||
|
|
||||||
|
ResourceArchiveDirectory *ResourceArchiveDirectory::Create(VirtualDirectory_t directory, const PLPasStr &subdirectory)
|
||||||
|
{
|
||||||
|
void *storage = PortabilityLayer::MemoryManager::GetInstance()->Alloc(sizeof(ResourceArchiveDirectory));
|
||||||
|
if (!storage)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return new (storage) ResourceArchiveDirectory(directory, subdirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceArchiveDirectory::Destroy()
|
||||||
|
{
|
||||||
|
this->~ResourceArchiveDirectory();
|
||||||
|
PortabilityLayer::MemoryManager::GetInstance()->Release(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
THandle<void> ResourceArchiveDirectory::LoadResource(const ResTypeID &resTypeID, int id)
|
||||||
|
{
|
||||||
|
return GetResource(resTypeID, id, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceArchiveDirectory::HasAnyResourcesOfType(const ResTypeID &resTypeID) const
|
||||||
|
{
|
||||||
|
int16_t scratch;
|
||||||
|
return FindFirstResourceOfType(resTypeID, scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceArchiveDirectory::FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const
|
||||||
|
{
|
||||||
|
int32_t resID32 = resTypeID.ExportAsInt32();
|
||||||
|
|
||||||
|
const ResTypeEntry *firstTypeEntry = *m_resTypes;
|
||||||
|
const ResTypeEntry *lastTypeEntry = firstTypeEntry + m_numResourceTypes;
|
||||||
|
|
||||||
|
const ResTypeEntry *entry = BinarySearch(firstTypeEntry, lastTypeEntry, resID32, ResourceArchiveDirectory::ResTypeSearchPredicate);
|
||||||
|
|
||||||
|
if (entry == lastTypeEntry)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
outID = (*m_resIDs)[entry->m_firstRes];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceArchiveDirectory::Init()
|
||||||
|
{
|
||||||
|
PortabilityLayer::HostFileSystem *fs = PortabilityLayer::HostFileSystem::GetInstance();
|
||||||
|
|
||||||
|
const char *typePaths[1] = { this->m_subdirectory };
|
||||||
|
|
||||||
|
PortabilityLayer::HostDirectoryCursor *typeDirCursor = fs->ScanDirectoryNested(m_directory, typePaths, 1);
|
||||||
|
if (!typeDirCursor)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
||||||
|
|
||||||
|
m_resTypes = THandle<ResTypeEntry>(mm->AllocHandle(0));
|
||||||
|
if (!m_resTypes)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_resIDs = THandle<int16_t>(mm->AllocHandle(0));
|
||||||
|
if (!m_resIDs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
size_t resTypeCapacity = 0;
|
||||||
|
size_t resIDCapacity = 0;
|
||||||
|
|
||||||
|
const char *typeScanFilename = nullptr;
|
||||||
|
while (typeDirCursor->GetNext(typeScanFilename))
|
||||||
|
{
|
||||||
|
GpArcResourceTypeTag resourceTypeTag;
|
||||||
|
if (!resourceTypeTag.Load(typeScanFilename))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ResTypeID resTypeID;
|
||||||
|
if (!resourceTypeTag.Decode(resTypeID))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int32_t dirResType = resTypeID.ExportAsInt32();
|
||||||
|
|
||||||
|
ResTypeEntry rte;
|
||||||
|
rte.m_resTypeID = dirResType;
|
||||||
|
rte.m_firstRes = m_numResources;
|
||||||
|
rte.m_lastRes = m_numResources;
|
||||||
|
|
||||||
|
const char *idScanFilenames[2] = { this->m_subdirectory, typeScanFilename };
|
||||||
|
PortabilityLayer::HostDirectoryCursor *typeIDCursor = fs->ScanDirectoryNested(m_directory, idScanFilenames, 2);
|
||||||
|
if (!typeIDCursor)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char *idScanFilename = nullptr;
|
||||||
|
while (typeIDCursor->GetNext(idScanFilename))
|
||||||
|
{
|
||||||
|
int resID = 0;
|
||||||
|
bool isNegative = false;
|
||||||
|
|
||||||
|
for (size_t chi = 0; idScanFilename[chi] != '.' && idScanFilename[chi] != '\0'; chi++)
|
||||||
|
{
|
||||||
|
char ch = idScanFilename[chi];
|
||||||
|
if (ch == '-')
|
||||||
|
isNegative = true;
|
||||||
|
else if (ch >= '0' && ch <= '9')
|
||||||
|
{
|
||||||
|
resID *= 10;
|
||||||
|
int digit = ch - '0';
|
||||||
|
if (isNegative)
|
||||||
|
resID -= digit;
|
||||||
|
else
|
||||||
|
resID += digit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_numResources == resIDCapacity)
|
||||||
|
{
|
||||||
|
const size_t oldCapacity = resIDCapacity;
|
||||||
|
|
||||||
|
resIDCapacity *= 2;
|
||||||
|
if (resIDCapacity == 0)
|
||||||
|
resIDCapacity = 1;
|
||||||
|
|
||||||
|
if (!mm->ResizeHandle(m_resIDs.MMBlock(), sizeof(int16_t) * resIDCapacity))
|
||||||
|
{
|
||||||
|
typeIDCursor->Destroy();
|
||||||
|
typeDirCursor->Destroy();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(*m_resIDs)[m_numResources] = resID;
|
||||||
|
m_numResources++;
|
||||||
|
}
|
||||||
|
|
||||||
|
typeIDCursor->Destroy();
|
||||||
|
rte.m_lastRes = m_numResources;
|
||||||
|
|
||||||
|
if (m_numResourceTypes == resTypeCapacity)
|
||||||
|
{
|
||||||
|
const size_t oldCapacity = resTypeCapacity;
|
||||||
|
|
||||||
|
resTypeCapacity *= 2;
|
||||||
|
if (resTypeCapacity == 0)
|
||||||
|
resTypeCapacity = 1;
|
||||||
|
|
||||||
|
if (!mm->ResizeHandle(m_resTypes.MMBlock(), sizeof(ResTypeEntry) * resTypeCapacity))
|
||||||
|
{
|
||||||
|
typeDirCursor->Destroy();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(*m_resTypes)[m_numResourceTypes] = rte;
|
||||||
|
m_numResourceTypes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
mm->ResizeHandle(m_resTypes.MMBlock(), sizeof(ResTypeEntry) * m_numResourceTypes);
|
||||||
|
mm->ResizeHandle(m_resIDs.MMBlock(), sizeof(int16_t) * m_numResources);
|
||||||
|
|
||||||
|
ResTypeEntry *resTypes = *m_resTypes;
|
||||||
|
int16_t *resIDs = *m_resIDs;
|
||||||
|
|
||||||
|
std::sort(resTypes, resTypes + m_numResourceTypes, ResourceArchiveDirectory::ResTypeEntrySortPredicate);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < m_numResourceTypes; i++)
|
||||||
|
{
|
||||||
|
int16_t *resIDStart = resIDs + resTypes[i].m_firstRes;
|
||||||
|
int16_t *resIDEnd = resIDs + resTypes[i].m_lastRes;
|
||||||
|
|
||||||
|
std::sort(resIDStart, resIDEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_resourceHandles = static_cast<ResourceArchiveRef*>(mm->Alloc(sizeof(ResourceArchiveRef) * m_numResources));
|
||||||
|
if (!m_resourceHandles)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < m_numResources; i++)
|
||||||
|
new (m_resourceHandles + i) ResourceArchiveRef();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceArchiveDirectory::IndexResource(const ResTypeID &resTypeID, int id, size_t &outIndex) const
|
||||||
|
{
|
||||||
|
int32_t resID32 = resTypeID.ExportAsInt32();
|
||||||
|
|
||||||
|
const ResTypeEntry *firstTypeEntry = *m_resTypes;
|
||||||
|
const ResTypeEntry *lastTypeEntry = firstTypeEntry + m_numResourceTypes;
|
||||||
|
|
||||||
|
const ResTypeEntry *entry = BinarySearch(firstTypeEntry, lastTypeEntry, resID32, ResourceArchiveDirectory::ResTypeSearchPredicate);
|
||||||
|
|
||||||
|
if (entry == lastTypeEntry)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const int16_t *resIDs = *m_resIDs;
|
||||||
|
const int16_t *firstRes = resIDs + entry->m_firstRes;
|
||||||
|
const int16_t *lastRes = resIDs + entry->m_lastRes;
|
||||||
|
|
||||||
|
const int16_t *idLoc = BinarySearch(firstRes, lastRes, static_cast<int16_t>(id), ResourceArchiveDirectory::ResIDSearchPredicate);
|
||||||
|
if (idLoc == lastRes)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
outIndex = static_cast<size_t>(idLoc - resIDs);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
THandle<void> ResourceArchiveDirectory::GetResource(const ResTypeID &resTypeID, int id, bool load)
|
||||||
|
{
|
||||||
|
|
||||||
|
int validationRule = 0;
|
||||||
|
size_t index = 0;
|
||||||
|
if (!IndexResource(resTypeID, id, 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 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle->m_contents == nullptr && load)
|
||||||
|
{
|
||||||
|
int validationRule = 0;
|
||||||
|
const char *extension = GetFileExtensionForResType(resTypeID, validationRule);
|
||||||
|
|
||||||
|
GpArcResourceTypeTag resTypeTag = GpArcResourceTypeTag::Encode(resTypeID);
|
||||||
|
char fileName[32];
|
||||||
|
|
||||||
|
snprintf(fileName, sizeof(fileName) - 1, "%i%s", id, extension);
|
||||||
|
|
||||||
|
const char *paths[3] = { m_subdirectory, resTypeTag.m_id, fileName };
|
||||||
|
|
||||||
|
GpIOStream *ioStream = PortabilityLayer::HostFileSystem::GetInstance()->OpenFileNested(m_directory, paths, 3, false, GpFileCreationDispositions::kOpenExisting);
|
||||||
|
if (!ioStream)
|
||||||
|
return THandle<void>();
|
||||||
|
|
||||||
|
size_t size = ioStream->Size();
|
||||||
|
|
||||||
|
void *contents = MemoryManager::GetInstance()->Alloc(size);
|
||||||
|
handle->m_contents = contents;
|
||||||
|
handle->m_size = size;
|
||||||
|
ref->m_size = size;
|
||||||
|
|
||||||
|
bool readOK = (ioStream->Read(contents, size));
|
||||||
|
ioStream->Close();
|
||||||
|
|
||||||
|
if (!readOK || (validationRule != ResourceValidationRules::kNone && !ValidateResource(contents, ref->m_size, static_cast<ResourceValidationRule_t>(validationRule))))
|
||||||
|
{
|
||||||
|
MemoryManager::GetInstance()->Release(contents);
|
||||||
|
handle->m_contents = nullptr;
|
||||||
|
handle->m_size = 0;
|
||||||
|
ref->m_size = 0;
|
||||||
|
|
||||||
|
return THandle<void>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return THandle<void>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ResourceArchiveDirectory::ResTypeSearchPredicate(int32_t resTypeID, const ResTypeEntry &entry)
|
||||||
|
{
|
||||||
|
if (resTypeID < entry.m_resTypeID)
|
||||||
|
return -1;
|
||||||
|
if (resTypeID > entry.m_resTypeID)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ResourceArchiveDirectory::ResIDSearchPredicate(int16_t resTypeID, int16_t entry)
|
||||||
|
{
|
||||||
|
if (resTypeID < entry)
|
||||||
|
return -1;
|
||||||
|
if (resTypeID > entry)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceArchiveDirectory::ResTypeEntrySortPredicate(const ResTypeEntry &a, const ResTypeEntry &b)
|
||||||
|
{
|
||||||
|
return a.m_resTypeID < b.m_resTypeID;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceArchiveDirectory::ResourceArchiveDirectory(VirtualDirectory_t directory, const PLPasStr &subdirectory)
|
||||||
|
: m_directory(directory)
|
||||||
|
, m_numResourceTypes(0)
|
||||||
|
, m_resourceHandles(nullptr)
|
||||||
|
, m_numResources(0)
|
||||||
|
{
|
||||||
|
memcpy(m_subdirectory, subdirectory.UChars(), subdirectory.Length());
|
||||||
|
m_subdirectory[subdirectory.Length()] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceArchiveDirectory::~ResourceArchiveDirectory()
|
||||||
|
{
|
||||||
|
MemoryManager *mm = MemoryManager::GetInstance();
|
||||||
|
|
||||||
|
const size_t numHandles = m_numResources;
|
||||||
|
|
||||||
|
if (m_resourceHandles)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < numHandles; i++)
|
||||||
|
{
|
||||||
|
ResourceArchiveRef &ref = m_resourceHandles[numHandles - 1 - i];
|
||||||
|
if (ref.m_handle)
|
||||||
|
mm->ReleaseHandle(ref.m_handle);
|
||||||
|
|
||||||
|
ref.~ResourceArchiveRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mm->Release(m_resourceHandles);
|
||||||
|
|
||||||
|
m_resIDs.Dispose();
|
||||||
|
m_resTypes.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ namespace PortabilityLayer
|
|||||||
bool operator!=(const ResTypeID &other) const;
|
bool operator!=(const ResTypeID &other) const;
|
||||||
|
|
||||||
void ExportAsChars(char *chars) const;
|
void ExportAsChars(char *chars) const;
|
||||||
|
int32_t ExportAsInt32() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char m_id[4];
|
char m_id[4];
|
||||||
@@ -70,6 +71,11 @@ namespace PortabilityLayer
|
|||||||
{
|
{
|
||||||
memcpy(chars, m_id, 4);
|
memcpy(chars, m_id, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int32_t ResTypeID::ExportAsInt32() const
|
||||||
|
{
|
||||||
|
return ResTypeIDCodec::Decode(m_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "VirtualDirectory.h"
|
#include "VirtualDirectory.h"
|
||||||
|
#include "PascalStr.h"
|
||||||
#include "PLErrorCodes.h"
|
#include "PLErrorCodes.h"
|
||||||
#include "PLHandle.h"
|
#include "PLHandle.h"
|
||||||
|
|
||||||
@@ -25,21 +26,78 @@ namespace PortabilityLayer
|
|||||||
int16_t m_resID;
|
int16_t m_resID;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceArchive final
|
struct IResourceArchive
|
||||||
|
{
|
||||||
|
virtual void Destroy() = 0;
|
||||||
|
|
||||||
|
virtual THandle<void> LoadResource(const ResTypeID &resTypeID, int id) = 0;
|
||||||
|
|
||||||
|
virtual bool HasAnyResourcesOfType(const ResTypeID &resTypeID) const = 0;
|
||||||
|
virtual bool FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ResourceArchiveBase : public IResourceArchive
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static ResourceArchive *Create(ZipFileProxy *zipFileProxy, GpIOStream *stream);
|
static const char *GetFileExtensionForResType(const ResTypeID &resTypeID, int &outValidationRule);
|
||||||
void Destroy();
|
};
|
||||||
|
|
||||||
THandle<void> LoadResource(const ResTypeID &resTypeID, int id);
|
class ResourceArchiveDirectory final : public ResourceArchiveBase
|
||||||
bool GetResourceSize(const ResTypeID &resTypeID, int id, size_t &outSize) const;
|
{
|
||||||
|
public:
|
||||||
|
static ResourceArchiveDirectory *Create(VirtualDirectory_t directory, const PLPasStr &subdirectory);
|
||||||
|
void Destroy() override;
|
||||||
|
|
||||||
bool HasAnyResourcesOfType(const ResTypeID &resTypeID) const;
|
THandle<void> LoadResource(const ResTypeID &resTypeID, int id) override;
|
||||||
bool FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const;
|
|
||||||
|
bool HasAnyResourcesOfType(const ResTypeID &resTypeID) const override;
|
||||||
|
bool FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const override;
|
||||||
|
|
||||||
|
bool Init();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ResourceArchive(ZipFileProxy *zipFileProxy, GpIOStream *stream, ResourceArchiveRef *resourceHandles);
|
ResourceArchiveDirectory(VirtualDirectory_t directory, const PLPasStr &subdirectory);
|
||||||
~ResourceArchive();
|
~ResourceArchiveDirectory();
|
||||||
|
|
||||||
|
struct ResTypeEntry
|
||||||
|
{
|
||||||
|
int32_t m_resTypeID;
|
||||||
|
size_t m_firstRes;
|
||||||
|
size_t m_lastRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool IndexResource(const ResTypeID &resTypeID, int id, size_t &outIndex) const;
|
||||||
|
THandle<void> GetResource(const ResTypeID &resTypeID, int id, bool load);
|
||||||
|
|
||||||
|
static int ResTypeSearchPredicate(int32_t resTypeID, const ResTypeEntry &entry);
|
||||||
|
static int ResIDSearchPredicate(int16_t resTypeID, int16_t entry);
|
||||||
|
static bool ResTypeEntrySortPredicate(const ResTypeEntry &a, const ResTypeEntry &b);
|
||||||
|
|
||||||
|
VirtualDirectory_t m_directory;
|
||||||
|
char m_subdirectory[256];
|
||||||
|
|
||||||
|
THandle<ResTypeEntry> m_resTypes;
|
||||||
|
size_t m_numResourceTypes;
|
||||||
|
|
||||||
|
THandle<int16_t> m_resIDs;
|
||||||
|
ResourceArchiveRef *m_resourceHandles;
|
||||||
|
size_t m_numResources;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ResourceArchiveZipFile final : public ResourceArchiveBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static ResourceArchiveZipFile *Create(ZipFileProxy *zipFileProxy, GpIOStream *stream);
|
||||||
|
void Destroy() override;
|
||||||
|
|
||||||
|
THandle<void> LoadResource(const ResTypeID &resTypeID, int id) override;
|
||||||
|
|
||||||
|
bool HasAnyResourcesOfType(const ResTypeID &resTypeID) const override;
|
||||||
|
bool FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ResourceArchiveZipFile(ZipFileProxy *zipFileProxy, GpIOStream *stream, ResourceArchiveRef *resourceHandles);
|
||||||
|
~ResourceArchiveZipFile();
|
||||||
|
|
||||||
bool IndexResource(const ResTypeID &resTypeID, int id, size_t &outIndex, int &outValidationRule) const;
|
bool IndexResource(const ResTypeID &resTypeID, int id, size_t &outIndex, int &outValidationRule) const;
|
||||||
|
|
||||||
@@ -57,9 +115,9 @@ namespace PortabilityLayer
|
|||||||
virtual void Shutdown() = 0;
|
virtual void Shutdown() = 0;
|
||||||
|
|
||||||
virtual THandle<void> GetAppResource(const ResTypeID &resTypeID, int16_t resID) const = 0;
|
virtual THandle<void> GetAppResource(const ResTypeID &resTypeID, int16_t resID) const = 0;
|
||||||
virtual ResourceArchive *GetAppResourceArchive() const = 0;
|
virtual IResourceArchive *GetAppResourceArchive() const = 0;
|
||||||
|
|
||||||
virtual ResourceArchive *LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const = 0;
|
virtual IResourceArchive *LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const = 0;
|
||||||
virtual PLError_t CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) = 0;
|
virtual PLError_t CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) = 0;
|
||||||
|
|
||||||
virtual void DissociateHandle(MMHandleBlock *hdl) const = 0;
|
virtual void DissociateHandle(MMHandleBlock *hdl) const = 0;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace PortabilityLayer
|
|||||||
ScanlineMaskBuilder::~ScanlineMaskBuilder()
|
ScanlineMaskBuilder::~ScanlineMaskBuilder()
|
||||||
{
|
{
|
||||||
if (m_spans)
|
if (m_spans)
|
||||||
realloc(m_spans, 0);
|
(void)realloc(m_spans, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScanlineMaskBuilder::AppendSpan(size_t span)
|
bool ScanlineMaskBuilder::AppendSpan(size_t span)
|
||||||
|
|||||||
Reference in New Issue
Block a user