diff --git a/MiniRez/MiniRez.cpp b/MiniRez/MiniRez.cpp index 55409e1..bf6f219 100644 --- a/MiniRez/MiniRez.cpp +++ b/MiniRez/MiniRez.cpp @@ -1,538 +1,538 @@ -#include -#include -#include -#include - -#include "BytePack.h" -#include "CFileStream.h" -#include "IOStream.h" - -#include "MacBinary2.h" -#include "MacFileMem.h" - -// Very simplified resource compiler - -using namespace PortabilityLayer; - -struct SimpleResource -{ - char m_type[4]; - int m_resourceID; - std::string m_name; - std::vector m_resourceData; - size_t m_offsetInResData; - uint8_t m_attributes; -}; - -struct ResCatalogData -{ -}; - -bool IsWhitespace(char c) -{ - return c <= ' '; -} - -void AppendUInt16(std::vector &vec, uint16_t value) -{ - uint8_t encoded[2]; - BytePack::BigUInt16(encoded, value); - vec.push_back(encoded[0]); - vec.push_back(encoded[1]); -} - -void AppendInt16(std::vector &vec, int16_t value) -{ - AppendUInt16(vec, static_cast(value)); -} - -void AppendUInt32(std::vector &vec, uint32_t value) -{ - uint8_t encoded[4]; - BytePack::BigUInt32(encoded, value); - vec.push_back(encoded[0]); - vec.push_back(encoded[1]); - vec.push_back(encoded[2]); - vec.push_back(encoded[3]); -} - -uint32_t TypeToU32(const char *resType) -{ - uint32_t v = 0; - for (int i = 0; i < 4; i++) - v |= static_cast(resType[i]) << (24 - i * 8); - - return v; -} - -bool FindNextNonWhitespace(CFileStream &fs, char &nextChar) -{ - for (;;) - { - char c; - if (!fs.Read(&c, 1)) - return false; - - if (!IsWhitespace(c)) - { - nextChar = c; - return true; - } - } -} - -std::string HandleEscapes(const std::string &str) -{ - const size_t len = str.size(); - - std::string processed; - - for (size_t i = 0; i < len; i++) - { - const char c = str[i]; - - if (c == '\\' && len - i >= 5 && str[i + 1] == '0' && str[i + 2] == 'x') - { - const char highNibbleChar = str[i + 3]; - const char lowNibbleChar = str[i + 4]; - - int highNibble = highNibbleChar - '0'; - int lowNibble = lowNibbleChar - '0'; - - const char reconstructed = (highNibble << 4) | lowNibble; - processed.append(&reconstructed, 1); - - i += 4; - } - else - processed.append(&c, 1); - } - - return processed; -} - -void DefError() -{ - fprintf(stderr, "Malformed def"); - exit(-1); -} - -int main(int argc, const char **argv) -{ - if (argc != 3) - { - fprintf(stderr, "Usage: MiniRez "); - return -1; - } - - FILE *f = nullptr; - if (fopen_s(&f, argv[1], "rb")) - { - fprintf(stderr, "Failed to open input file"); - return -1; - } - - CFileStream fs(f, true, false, true); - - int defsParsed = 0; - - std::vector resources; - - for (;;) - { - printf("%i defs parsed...\n", defsParsed); - defsParsed++; - UFilePos_t defStartOffset = fs.Tell(); - - char nextChar = 0; - if (!FindNextNonWhitespace(fs, nextChar)) - break; - - if (IsWhitespace(nextChar)) - continue; - - if (nextChar == 'd') - { - char nextChars[3]; - if (fs.Read(nextChars, 3) != 3 || nextChars[0] != 'a' || nextChars[1] != 't' || nextChars[2] != 'a') - { - fprintf(stderr, "Unknown token"); - return -1; - } - - if (!FindNextNonWhitespace(fs, nextChar) || nextChar != '\'') - DefError(); - - char resType[5]; - if (!fs.Read(resType, 5) || resType[4] != '\'') - DefError(); - - if (!FindNextNonWhitespace(fs, nextChar) || nextChar != '(') - DefError(); - - int resID = 0; - bool hasProperty = false; - bool isNegative = false; - for (;;) - { - if (!fs.Read(&nextChar, 1)) - DefError(); - - if (nextChar == ')') - break; - else if (nextChar == ',') - { - hasProperty = true; - break; - } - else if (nextChar == '-') - isNegative = true; - else if (nextChar >= '0' && nextChar <= '9') - resID = resID * 10 + (nextChar - '0'); - else - DefError(); - } - - std::string resName; - std::string propName; - std::vector resData; - - if (hasProperty) - { - char singleCharStr[2]; - singleCharStr[1] = '\0'; - - if (!FindNextNonWhitespace(fs, singleCharStr[0])) - DefError(); - - - if (singleCharStr[0] == '\"') - { - hasProperty = false; - - for (;;) - { - if (!fs.Read(singleCharStr, 1)) - DefError(); - - if (singleCharStr[0] == '"') - break; - - resName += singleCharStr; - } - - if (!FindNextNonWhitespace(fs, nextChar)) - DefError(); - - if (nextChar == ')') - { - } - else if (nextChar == ',') - { - hasProperty = true; - if (!FindNextNonWhitespace(fs, singleCharStr[0])) - DefError(); - } - else - DefError(); - } - - if (hasProperty) - { - propName = singleCharStr; - - for (;;) - { - if (!fs.Read(singleCharStr, 1)) - DefError(); - - if (singleCharStr[0] == ')') - break; - - propName += singleCharStr; - } - } - } - - if (!FindNextNonWhitespace(fs, nextChar) || nextChar != '{') - DefError(); - - // Data item parse loop - for (;;) - { - if (!FindNextNonWhitespace(fs, nextChar)) - DefError(); - - if (nextChar == '$') - { - // Res data bytes - uint8_t b = 0; - bool highNibble = true; - - if (!fs.Read(&nextChar, 1) || nextChar != '\"') - DefError(); - - for (;;) - { - if (!fs.Read(&nextChar, 1)) - DefError(); - - uint8_t fragment = 0; - - if (nextChar == '\"') - break; - else if (nextChar >= '0' && nextChar <= '9') - fragment = nextChar - '0'; - else if (nextChar >= 'a' && nextChar <= 'f') - fragment = nextChar - 'a' + 0xa; - else if (nextChar >= 'A' && nextChar <= 'F') - fragment = nextChar - 'A' + 0xa; - else if (nextChar == ' ') - { - continue; - } - else - DefError(); - - if (highNibble) - { - b = fragment << 4; - highNibble = false; - } - else - { - resData.push_back(b | fragment); - highNibble = true; - } - } - - continue; - } - else if (nextChar == '}') - break; - else if (nextChar == '/') - { - if (!fs.Read(&nextChar, 1)) - DefError(); - - if (nextChar == '/') - { - for (;;) - { - if (!fs.Read(&nextChar, 1)) - DefError(); - - if (nextChar == '\r' || nextChar == '\n') - break; - } - } - else if (nextChar == '*') - { - char prevChar = nextChar; - - for (;;) - { - if (!fs.Read(&nextChar, 1)) - DefError(); - - if (nextChar == '/' && prevChar == '*') - break; - - prevChar = nextChar; - } - } - else - DefError(); - } - else - DefError(); - } - - if (!FindNextNonWhitespace(fs, nextChar) || nextChar != ';') - DefError(); - - SimpleResource *res = new SimpleResource(); - res->m_name = HandleEscapes(resName); - res->m_resourceID = resID; - memcpy(res->m_type, resType, 4); - res->m_resourceData.swap(resData); - res->m_attributes = 0; - - if (propName == "purgeable") - res->m_attributes |= (1 << 5); - - - resources.push_back(res); - } - else - { - fprintf(stderr, "Unknown token"); - return -1; - } - } - - std::vector resourceForkData; - - for (size_t i = 0; i < 16; i++) - resourceForkData.push_back(0); - - size_t resForkDataStart = resourceForkData.size(); - - std::vector uniqueResTypes; - std::vector resTypeCounts; - std::vector uniqueResNames; - - printf("Re-emitting defs...\n"); - for (size_t i = 0; i < resources.size(); i++) - { - SimpleResource *res = resources[i]; - - res->m_offsetInResData = resourceForkData.size() - resForkDataStart; - - uint8_t packedLen[4]; - BytePack::BigUInt32(packedLen, static_cast(res->m_resourceData.size())); - - for (int j = 0; j < 4; j++) - resourceForkData.push_back(packedLen[j]); - - for (size_t j = 0; j < res->m_resourceData.size(); j++) - resourceForkData.push_back(res->m_resourceData[j]); - - uint32_t resTypeCode = TypeToU32(res->m_type); - std::vector::iterator uniqueResTypeIndex = std::find(uniqueResTypes.begin(), uniqueResTypes.end(), resTypeCode); - - if (uniqueResTypeIndex == uniqueResTypes.end()) - { - uniqueResTypes.push_back(resTypeCode); - resTypeCounts.push_back(1); - } - else - resTypeCounts[uniqueResTypeIndex - uniqueResTypes.begin()]++; - - if (!res->m_name.empty()) - { - if (std::find(uniqueResNames.begin(), uniqueResNames.end(), res->m_name) == uniqueResNames.end()) - uniqueResNames.push_back(res->m_name); - } +#include +#include +#include +#include + +#include "BytePack.h" +#include "CFileStream.h" +#include "IOStream.h" + +#include "MacBinary2.h" +#include "MacFileMem.h" + +// Very simplified resource compiler + +using namespace PortabilityLayer; + +struct SimpleResource +{ + char m_type[4]; + int m_resourceID; + std::string m_name; + std::vector m_resourceData; + size_t m_offsetInResData; + uint8_t m_attributes; +}; + +struct ResCatalogData +{ +}; + +bool IsWhitespace(char c) +{ + return c <= ' '; +} + +void AppendUInt16(std::vector &vec, uint16_t value) +{ + uint8_t encoded[2]; + BytePack::BigUInt16(encoded, value); + vec.push_back(encoded[0]); + vec.push_back(encoded[1]); +} + +void AppendInt16(std::vector &vec, int16_t value) +{ + AppendUInt16(vec, static_cast(value)); +} + +void AppendUInt32(std::vector &vec, uint32_t value) +{ + uint8_t encoded[4]; + BytePack::BigUInt32(encoded, value); + vec.push_back(encoded[0]); + vec.push_back(encoded[1]); + vec.push_back(encoded[2]); + vec.push_back(encoded[3]); +} + +uint32_t TypeToU32(const char *resType) +{ + uint32_t v = 0; + for (int i = 0; i < 4; i++) + v |= static_cast(resType[i]) << (24 - i * 8); + + return v; +} + +bool FindNextNonWhitespace(CFileStream &fs, char &nextChar) +{ + for (;;) + { + char c; + if (!fs.Read(&c, 1)) + return false; + + if (!IsWhitespace(c)) + { + nextChar = c; + return true; + } + } +} + +std::string HandleEscapes(const std::string &str) +{ + const size_t len = str.size(); + + std::string processed; + + for (size_t i = 0; i < len; i++) + { + const char c = str[i]; + + if (c == '\\' && len - i >= 5 && str[i + 1] == '0' && str[i + 2] == 'x') + { + const char highNibbleChar = str[i + 3]; + const char lowNibbleChar = str[i + 4]; + + int highNibble = highNibbleChar - '0'; + int lowNibble = lowNibbleChar - '0'; + + const char reconstructed = (highNibble << 4) | lowNibble; + processed.append(&reconstructed, 1); + + i += 4; + } + else + processed.append(&c, 1); } - printf("Re-emit OK\n"); - - const size_t resDataSize = resourceForkData.size() - resForkDataStart; - const size_t resMapPos = resourceForkData.size(); - - // Reserved space for resource header copy (16), handle to next res map (4), file ref number (2) - for (size_t j = 0; j < 22; j++) - resourceForkData.push_back(0); - - uint16_t resForkAttributes = 0; // We don't use any of these - - const size_t typeListEntrySize = 8; - const size_t refListEntrySize = 12; - - const size_t resourceTypeListStartLoc = 28; - const size_t resourceTypeListSize = 2 + uniqueResTypes.size() * typeListEntrySize; - const size_t resourceRefListStartLoc = resourceTypeListStartLoc + resourceTypeListSize; - const size_t resourceNameListStartLoc = resourceRefListStartLoc + resources.size() * refListEntrySize; - - AppendUInt16(resourceForkData, resForkAttributes); - AppendUInt16(resourceForkData, static_cast(resourceTypeListStartLoc)); - AppendUInt16(resourceForkData, static_cast(resourceNameListStartLoc)); - AppendUInt16(resourceForkData, static_cast(uniqueResTypes.size() - 1)); - - std::vector refListStartForType; - refListStartForType.resize(resTypeCounts.size()); + return processed; +} + +void DefError() +{ + fprintf(stderr, "Malformed def"); + exit(-1); +} + +int main(int argc, const char **argv) +{ + if (argc != 3) + { + fprintf(stderr, "Usage: MiniRez "); + return -1; + } + + FILE *f = nullptr; + if (fopen_s(&f, argv[1], "rb")) + { + fprintf(stderr, "Failed to open input file"); + return -1; + } + + CFileStream fs(f, true, false, true); + + int defsParsed = 0; + + std::vector resources; + + for (;;) + { + printf("%i defs parsed...\n", defsParsed); + defsParsed++; + UFilePos_t defStartOffset = fs.Tell(); + + char nextChar = 0; + if (!FindNextNonWhitespace(fs, nextChar)) + break; + + if (IsWhitespace(nextChar)) + continue; + + if (nextChar == 'd') + { + char nextChars[3]; + if (fs.Read(nextChars, 3) != 3 || nextChars[0] != 'a' || nextChars[1] != 't' || nextChars[2] != 'a') + { + fprintf(stderr, "Unknown token"); + return -1; + } + + if (!FindNextNonWhitespace(fs, nextChar) || nextChar != '\'') + DefError(); + + char resType[5]; + if (!fs.Read(resType, 5) || resType[4] != '\'') + DefError(); + + if (!FindNextNonWhitespace(fs, nextChar) || nextChar != '(') + DefError(); + + int resID = 0; + bool hasProperty = false; + bool isNegative = false; + for (;;) + { + if (!fs.Read(&nextChar, 1)) + DefError(); + + if (nextChar == ')') + break; + else if (nextChar == ',') + { + hasProperty = true; + break; + } + else if (nextChar == '-') + isNegative = true; + else if (nextChar >= '0' && nextChar <= '9') + resID = resID * 10 + (nextChar - '0'); + else + DefError(); + } + + std::string resName; + std::string propName; + std::vector resData; + + if (hasProperty) + { + char singleCharStr[2]; + singleCharStr[1] = '\0'; + + if (!FindNextNonWhitespace(fs, singleCharStr[0])) + DefError(); + + + if (singleCharStr[0] == '\"') + { + hasProperty = false; + + for (;;) + { + if (!fs.Read(singleCharStr, 1)) + DefError(); + + if (singleCharStr[0] == '"') + break; + + resName += singleCharStr; + } + + if (!FindNextNonWhitespace(fs, nextChar)) + DefError(); + + if (nextChar == ')') + { + } + else if (nextChar == ',') + { + hasProperty = true; + if (!FindNextNonWhitespace(fs, singleCharStr[0])) + DefError(); + } + else + DefError(); + } + + if (hasProperty) + { + propName = singleCharStr; + + for (;;) + { + if (!fs.Read(singleCharStr, 1)) + DefError(); + + if (singleCharStr[0] == ')') + break; + + propName += singleCharStr; + } + } + } + + if (!FindNextNonWhitespace(fs, nextChar) || nextChar != '{') + DefError(); + + // Data item parse loop + for (;;) + { + if (!FindNextNonWhitespace(fs, nextChar)) + DefError(); + + if (nextChar == '$') + { + // Res data bytes + uint8_t b = 0; + bool highNibble = true; + + if (!fs.Read(&nextChar, 1) || nextChar != '\"') + DefError(); + + for (;;) + { + if (!fs.Read(&nextChar, 1)) + DefError(); + + uint8_t fragment = 0; + + if (nextChar == '\"') + break; + else if (nextChar >= '0' && nextChar <= '9') + fragment = nextChar - '0'; + else if (nextChar >= 'a' && nextChar <= 'f') + fragment = nextChar - 'a' + 0xa; + else if (nextChar >= 'A' && nextChar <= 'F') + fragment = nextChar - 'A' + 0xa; + else if (nextChar == ' ') + { + continue; + } + else + DefError(); + + if (highNibble) + { + b = fragment << 4; + highNibble = false; + } + else + { + resData.push_back(b | fragment); + highNibble = true; + } + } + + continue; + } + else if (nextChar == '}') + break; + else if (nextChar == '/') + { + if (!fs.Read(&nextChar, 1)) + DefError(); + + if (nextChar == '/') + { + for (;;) + { + if (!fs.Read(&nextChar, 1)) + DefError(); + + if (nextChar == '\r' || nextChar == '\n') + break; + } + } + else if (nextChar == '*') + { + char prevChar = nextChar; + + for (;;) + { + if (!fs.Read(&nextChar, 1)) + DefError(); + + if (nextChar == '/' && prevChar == '*') + break; + + prevChar = nextChar; + } + } + else + DefError(); + } + else + DefError(); + } + + if (!FindNextNonWhitespace(fs, nextChar) || nextChar != ';') + DefError(); + + SimpleResource *res = new SimpleResource(); + res->m_name = HandleEscapes(resName); + res->m_resourceID = resID; + memcpy(res->m_type, resType, 4); + res->m_resourceData.swap(resData); + res->m_attributes = 0; + + if (propName == "purgeable") + res->m_attributes |= (1 << 5); + + + resources.push_back(res); + } + else + { + fprintf(stderr, "Unknown token"); + return -1; + } + } + + std::vector resourceForkData; + + for (size_t i = 0; i < 16; i++) + resourceForkData.push_back(0); + + size_t resForkDataStart = resourceForkData.size(); + + std::vector uniqueResTypes; + std::vector resTypeCounts; + std::vector uniqueResNames; + + printf("Re-emitting defs...\n"); + for (size_t i = 0; i < resources.size(); i++) + { + SimpleResource *res = resources[i]; + + res->m_offsetInResData = resourceForkData.size() - resForkDataStart; + + uint8_t packedLen[4]; + BytePack::BigUInt32(packedLen, static_cast(res->m_resourceData.size())); + + for (int j = 0; j < 4; j++) + resourceForkData.push_back(packedLen[j]); + + for (size_t j = 0; j < res->m_resourceData.size(); j++) + resourceForkData.push_back(res->m_resourceData[j]); + + uint32_t resTypeCode = TypeToU32(res->m_type); + std::vector::iterator uniqueResTypeIndex = std::find(uniqueResTypes.begin(), uniqueResTypes.end(), resTypeCode); + + if (uniqueResTypeIndex == uniqueResTypes.end()) + { + uniqueResTypes.push_back(resTypeCode); + resTypeCounts.push_back(1); + } + else + resTypeCounts[uniqueResTypeIndex - uniqueResTypes.begin()]++; + + if (!res->m_name.empty()) + { + if (std::find(uniqueResNames.begin(), uniqueResNames.end(), res->m_name) == uniqueResNames.end()) + uniqueResNames.push_back(res->m_name); + } + } + + printf("Re-emit OK\n"); + + const size_t resDataSize = resourceForkData.size() - resForkDataStart; + const size_t resMapPos = resourceForkData.size(); + + // Reserved space for resource header copy (16), handle to next res map (4), file ref number (2) + for (size_t j = 0; j < 22; j++) + resourceForkData.push_back(0); + + uint16_t resForkAttributes = 0; // We don't use any of these + + const size_t typeListEntrySize = 8; + const size_t refListEntrySize = 12; + + const size_t resourceTypeListStartLoc = 28; + const size_t resourceTypeListSize = 2 + uniqueResTypes.size() * typeListEntrySize; + const size_t resourceRefListStartLoc = resourceTypeListStartLoc + resourceTypeListSize; + const size_t resourceNameListStartLoc = resourceRefListStartLoc + resources.size() * refListEntrySize; + + AppendUInt16(resourceForkData, resForkAttributes); + AppendUInt16(resourceForkData, static_cast(resourceTypeListStartLoc)); + AppendUInt16(resourceForkData, static_cast(resourceNameListStartLoc)); + AppendUInt16(resourceForkData, static_cast(uniqueResTypes.size() - 1)); + + std::vector refListStartForType; + refListStartForType.resize(resTypeCounts.size()); if (resTypeCounts.size() > 0) - { - refListStartForType[0] = 0; - for (size_t i = 1; i < refListStartForType.size(); i++) + { + refListStartForType[0] = 0; + for (size_t i = 1; i < refListStartForType.size(); i++) refListStartForType[i] = refListStartForType[i - 1] + resTypeCounts[i - 1]; - } - - std::vector nameListStarts; - nameListStarts.resize(uniqueResNames.size()); + } + + std::vector nameListStarts; + nameListStarts.resize(uniqueResNames.size()); if (nameListStarts.size() > 0) - { - nameListStarts[0] = 0; - for (size_t i = 1; i < nameListStarts.size(); i++) + { + nameListStarts[0] = 0; + for (size_t i = 1; i < nameListStarts.size(); i++) nameListStarts[i] = nameListStarts[i - 1] + uniqueResNames[i - 1].size() + 1; - } - - // Write resource type list - for (size_t i = 0; i < uniqueResTypes.size(); i++) - { - AppendUInt32(resourceForkData, uniqueResTypes[i]); - AppendUInt16(resourceForkData, resTypeCounts[i] - 1); - AppendUInt16(resourceForkData, static_cast(refListStartForType[i] * refListEntrySize + resourceTypeListSize)); - } - - // Write reference lists - for (size_t ti = 0; ti < uniqueResTypes.size(); ti++) - { - uint32_t resType = uniqueResTypes[ti]; - - for (size_t i = 0; i < resources.size(); i++) - { - const SimpleResource *res = resources[i]; - if (TypeToU32(res->m_type) != resType) - continue; - - AppendInt16(resourceForkData, res->m_resourceID); - if (res->m_name.empty()) - AppendInt16(resourceForkData, -1); - else - { - const std::vector::iterator nameIt = std::find(uniqueResNames.begin(), uniqueResNames.end(), res->m_name); - const size_t nameIndex = nameIt - uniqueResNames.begin(); - - AppendUInt16(resourceForkData, static_cast(nameListStarts[nameIndex])); - } - - resourceForkData.push_back(res->m_attributes); - - const size_t resDataStart = res->m_offsetInResData; - - resourceForkData.push_back((resDataStart >> 16) & 0xff); - resourceForkData.push_back((resDataStart >> 8) & 0xff); - resourceForkData.push_back((resDataStart >> 0) & 0xff); - - for (int j = 0; j < 4; j++) - resourceForkData.push_back(0); // Reserved - } - } - - // Write name lists - for (size_t ni = 0; ni < uniqueResNames.size(); ni++) - { - const std::string &name = uniqueResNames[ni]; - const size_t nameLen = name.size(); - - resourceForkData.push_back(static_cast(nameLen)); - - for (size_t i = 0; i < nameLen; i++) - resourceForkData.push_back(name[i]); - } - - const size_t resMapSize = resourceForkData.size() - resMapPos; - - BytePack::BigUInt32(&resourceForkData[0], static_cast(resForkDataStart)); - BytePack::BigUInt32(&resourceForkData[4], static_cast(resMapPos)); - BytePack::BigUInt32(&resourceForkData[8], static_cast(resDataSize)); + } + + // Write resource type list + for (size_t i = 0; i < uniqueResTypes.size(); i++) + { + AppendUInt32(resourceForkData, uniqueResTypes[i]); + AppendUInt16(resourceForkData, resTypeCounts[i] - 1); + AppendUInt16(resourceForkData, static_cast(refListStartForType[i] * refListEntrySize + resourceTypeListSize)); + } + + // Write reference lists + for (size_t ti = 0; ti < uniqueResTypes.size(); ti++) + { + uint32_t resType = uniqueResTypes[ti]; + + for (size_t i = 0; i < resources.size(); i++) + { + const SimpleResource *res = resources[i]; + if (TypeToU32(res->m_type) != resType) + continue; + + AppendInt16(resourceForkData, res->m_resourceID); + if (res->m_name.empty()) + AppendInt16(resourceForkData, -1); + else + { + const std::vector::iterator nameIt = std::find(uniqueResNames.begin(), uniqueResNames.end(), res->m_name); + const size_t nameIndex = nameIt - uniqueResNames.begin(); + + AppendUInt16(resourceForkData, static_cast(nameListStarts[nameIndex])); + } + + resourceForkData.push_back(res->m_attributes); + + const size_t resDataStart = res->m_offsetInResData; + + resourceForkData.push_back((resDataStart >> 16) & 0xff); + resourceForkData.push_back((resDataStart >> 8) & 0xff); + resourceForkData.push_back((resDataStart >> 0) & 0xff); + + for (int j = 0; j < 4; j++) + resourceForkData.push_back(0); // Reserved + } + } + + // Write name lists + for (size_t ni = 0; ni < uniqueResNames.size(); ni++) + { + const std::string &name = uniqueResNames[ni]; + const size_t nameLen = name.size(); + + resourceForkData.push_back(static_cast(nameLen)); + + for (size_t i = 0; i < nameLen; i++) + resourceForkData.push_back(name[i]); + } + + const size_t resMapSize = resourceForkData.size() - resMapPos; + + BytePack::BigUInt32(&resourceForkData[0], static_cast(resForkDataStart)); + BytePack::BigUInt32(&resourceForkData[4], static_cast(resMapPos)); + BytePack::BigUInt32(&resourceForkData[8], static_cast(resDataSize)); BytePack::BigUInt32(&resourceForkData[12], static_cast(resMapSize)); - printf("Writing to %s...", argv[2]); - - FILE *outF = nullptr; - if (fopen_s(&outF, argv[2], "wb")) - { - fprintf(stderr, "Failed to open output file"); - return -1; - } - - fwrite(&resourceForkData[0], 1, resourceForkData.size(), outF); - fclose(outF); - - return 0; -} + printf("Writing to %s...", argv[2]); + + FILE *outF = nullptr; + if (fopen_s(&outF, argv[2], "wb")) + { + fprintf(stderr, "Failed to open output file"); + return -1; + } + + fwrite(&resourceForkData[0], 1, resourceForkData.size(), outF); + fclose(outF); + + return 0; +}