From 95fdba76bff03626b8a9fbc2ddac9658fa010fd9 Mon Sep 17 00:00:00 2001 From: Iliyas Jorio Date: Sat, 26 Dec 2020 17:02:46 +0100 Subject: [PATCH] Dump resources to files for debugging --- src/Files/Resources.cpp | 58 ++++++++++++++++++++++++++++++++++++----- src/Pomme.h | 5 ++++ src/PommeDebug.cpp | 7 ++--- 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/Files/Resources.cpp b/src/Files/Resources.cpp index 7b7fa1c..872eac3 100644 --- a/src/Files/Resources.cpp +++ b/src/Files/Resources.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "CompilerSupport/filesystem.h" #define LOG POMME_GENLOG(POMME_DEBUG_RESOURCES, "RSRC") @@ -20,6 +21,8 @@ static std::vector rezSearchStack; static int rezSearchStackIndex = 0; +static fs::path rezDumpHostDestinationPath = ""; + //----------------------------------------------------------------------------- // Internal @@ -48,24 +51,50 @@ static void PrintStack(const char* msg) { } LOG << "------------------------------------\n"; } +#endif -static void DumpResource(ResourceMetadata& meta) +static void DumpResource(const ResourceMetadata& meta) { + const FSSpec& spec = Pomme::Files::GetSpec(meta.forkRefNum); + Handle handle = NewHandle(meta.size); auto& fork = Pomme::Files::GetStream(meta.forkRefNum); fork.seekg(meta.dataOffset, std::ios::beg); fork.read(*handle, meta.size); + + fs::path outPath; + outPath = rezDumpHostDestinationPath; + outPath /= spec.cName; + outPath /= Pomme::FourCCString(meta.type, '_'); + fs::create_directories(outPath); + + std::stringstream ss; + ss << meta.id; + if (!meta.name.empty()) + { + ss << "-"; + for (auto c: meta.name) + ss << (char)(isalnum(c)? c: '_'); + } + outPath /= ss.str(); + outPath += "." + Pomme::FourCCString(meta.type, '_'); + + std::ofstream dump(outPath, std::ofstream::binary); + + // Add a 512-byte blank header to PICTs so tools such as ImageMagick or Preview.app will display them + if (meta.type == 'PICT') + { + for (int i = 0; i < 512; i++) + dump.put(0); + } - std::stringstream fn; - fn << "rezdump/" << meta.id << "_" << meta.name << "." << Pomme::FourCCString(meta.type, '_'); - std::ofstream dump(fn.str(), std::ofstream::binary); dump.write(*handle, meta.size); dump.close(); - std::cout << "wrote " << fn.str() << "\n"; + + std::cout << "wrote " << outPath << "\n"; DisposeHandle(handle); } -#endif //----------------------------------------------------------------------------- // Resource file management @@ -166,6 +195,10 @@ short FSpOpenResFile(const FSSpec* spec, char permission) resMetadata.size = size; resMetadata.name = name; GetCurRF().resourceMap[resType][resID] = resMetadata; + + // Dump resource to file (if user called Pomme_StartDumpingResource) + if (!rezDumpHostDestinationPath.empty()) + DumpResource(resMetadata); } } @@ -258,6 +291,7 @@ Handle GetResource(ResType theType, short theID) Handle handle = NewHandle(meta.size); forkStream.seekg(meta.dataOffset, std::ios::beg); forkStream.read(*handle, meta.size); + return handle; } @@ -302,3 +336,15 @@ long SizeResource(Handle theResource) { return GetResourceSizeOnDisk(theResource); } + +void Pomme_StartDumpingResources(const char* hostDestinationPath) +{ + if (hostDestinationPath) + { + rezDumpHostDestinationPath = hostDestinationPath; + } + else + { + rezDumpHostDestinationPath.clear(); + } +} \ No newline at end of file diff --git a/src/Pomme.h b/src/Pomme.h index 3205126..769e3ca 100644 --- a/src/Pomme.h +++ b/src/Pomme.h @@ -99,6 +99,11 @@ long GetResourceSizeOnDisk(Handle); long SizeResource(Handle); +// After calling this function, Pomme will dump all resources to separate files +// whenever a new resource fork is opened. +// Pass in NULL to stop dumping resources. +void Pomme_StartDumpingResources(const char* hostDestinationPath); + //----------------------------------------------------------------------------- // QuickDraw 2D: Shapes diff --git a/src/PommeDebug.cpp b/src/PommeDebug.cpp index 3ea46a4..9e12698 100644 --- a/src/PommeDebug.cpp +++ b/src/PommeDebug.cpp @@ -46,11 +46,12 @@ std::string Pomme::FourCCString(uint32_t t, char filler) #if !(TARGET_RT_BIGENDIAN) std::reverse(b, b + 4); #endif - // replace non-ascii with '?' + // Replace any non-alphanumeric character with the filler character. + // This ensures that the resulting string is suitable for use as a filename. for (int i = 0; i < 4; i++) { - char c = b[i]; - if (c < ' ' || c > '~') b[i] = filler; + if (!isalnum(b[i])) + b[i] = filler; } b[4] = '\0'; return b;