From 3b81b5158ddcc8ee5f11ed39868431a311c831a4 Mon Sep 17 00:00:00 2001 From: Aetias Date: Sun, 15 Oct 2023 11:37:48 +0200 Subject: [PATCH] Make buildrom run without errors --- tools/rom/build.c | 54 ++++++++++++++++++++++++++++++----------------- tools/rom/files.h | 21 ++++++++++++++---- tools/rom/ph.h | 2 +- tools/rom/rom.h | 4 ++-- tools/rom/util.h | 12 +++++------ 5 files changed, 61 insertions(+), 32 deletions(-) diff --git a/tools/rom/build.c b/tools/rom/build.c index db6008eb..4bf7e410 100644 --- a/tools/rom/build.c +++ b/tools/rom/build.c @@ -146,6 +146,7 @@ bool Align(size_t alignment, FILE *fpRom, size_t *pAddress) { if (fputc(0xff, fpRom) == -1) FATAL("Failed to pad output ROM at address 0x%x\n", address); address += 1; } + *pAddress = address; return true; } @@ -160,9 +161,10 @@ bool WriteArm9Overlays(FILE *fpRom, size_t *pAddress, size_t *pNumOverlays, FatE sprintf(fileName, "ov%02d.lz", ovNum); if (!Align(256, fpRom, &address)) return false; size_t startOffset = address; - if (!AppendFile(fpRom, fileName, &address, NULL)) return false; + if (!AppendFile(fpRom, fileName, &address, NULL)) break; entries[ovNum].startOffset = startOffset; entries[ovNum].endOffset = address; + ovNum += 1; } if (chdir("..") != 0) FATAL("Failed to leave overlays directory '" OVERLAYS_SUBDIR "'\n"); @@ -243,6 +245,8 @@ bool WriteFntSubtable(FileTree *tree, FntContext *pContext) { ctx.subtable[ctx.subtableSize] = 0; // End of subtable ctx.subtableSize += 1; + ctx.nextFileId += numFiles; + // Recurse child directories for (size_t i = 0; i < tree->numChildren; ++i) { FileTree *child = &tree->children[i]; @@ -257,13 +261,14 @@ bool WriteFntSubtable(FileTree *tree, FntContext *pContext) { mainEntry.parentId = ctx.parentId; if (!GrowFntTable(&ctx, ctx.tableSize + 1)) return false; memcpy(&ctx.table[ctx.tableSize], &mainEntry, sizeof(mainEntry)); + ctx.tableSize += 1; - ctx.nextFileId += numFiles; uint16_t oldParentId = ctx.parentId; ctx.parentId = subdirId; char name[128]; strncpy(name, entry->name, entry->length); + name[entry->length] = '\0'; if (!WriteFntSubtable(child, &ctx)) return false; ctx.parentId = oldParentId; @@ -289,7 +294,7 @@ bool WriteFnt(FILE *fpRom, size_t *pAddress, FileTree *pRoot, size_t firstFileId FntContext ctx; ctx.table = malloc(INITIAL_TABLE_SIZE * sizeof(FntEntry)); if (ctx.table == NULL) FATAL("Failed to allocate FNT table\n"); - ctx.tableSize = 0; + ctx.tableSize = 1; ctx.tableMax = INITIAL_TABLE_SIZE; ctx.nextFileId = firstFileId; @@ -300,10 +305,9 @@ bool WriteFnt(FILE *fpRom, size_t *pAddress, FileTree *pRoot, size_t firstFileId ctx.subtableSize = 0; ctx.subtableMax = INITIAL_SUBTABLE_SIZE; - FntEntry rootEntry; - rootEntry.subtableOffset = 0; // will add main table length later - rootEntry.firstFile = firstFileId; - rootEntry.parentId = 0; // will be set to number of directories later + ctx.table[0].subtableOffset = 0; // will add main table length later + ctx.table[0].firstFile = firstFileId; + ctx.table[0].parentId = 0; // will be set to number of directories later size_t tableStart = address; if (!WriteFntSubtable(pRoot, &ctx)) return false; @@ -341,6 +345,7 @@ bool AppendAssets(FILE *fpRom, size_t *pAddress, const FileTree *tree, FatContex if (!entry->isSubdir) continue; char name[128]; strncpy(name, entry->name, entry->length); + name[entry->length] = '\0'; if (chdir(name) != 0) FATAL("Failed to enter assets directory '%s'\n", name); if (!AppendAssets(fpRom, &address, child, &ctx)) return false; if (chdir("..") != 0) FATAL("Failed to leave assets directory '%s'\n", name); @@ -354,6 +359,7 @@ bool AppendAssets(FILE *fpRom, size_t *pAddress, const FileTree *tree, FatContex if (entry->isSubdir) continue; char name[128]; strncpy(name, entry->name, entry->length); + name[entry->length] = '\0'; if (!Align(256, fpRom, &address)) return false; size_t startOffset = address; if (!AppendFile(fpRom, name, &address, NULL)) return false; @@ -400,11 +406,11 @@ void PrintUsage(const char *program) { printf( "buildrom " VERSION "\n" "\n" - "Usage: %s -a ASSETSDIR -b BUILDDIR -r REGION -o OUTFILE\n" - " -a ASSETSDIR\tAssets directory generated by extractrom\n" - " -b BUILDDIR \tBuild directory generated by Makefile\n" - " -r REGION \tJ = Japan, E = USA, P = Europe\n" - " -o OUTFILE \tOutput ROM file\n", + "Usage: %s -a BASEDIR -b BUILDDIR -r REGION -o OUTFILE\n" + " -a BASEDIR \tBase directory generated by extractrom\n" + " -b BUILDDIR\tBuild directory generated by Makefile\n" + " -r REGION \tJ = Japan, E = USA, P = Europe\n" + " -o OUTFILE \tOutput ROM file\n", program ); } @@ -415,7 +421,7 @@ int main(int argc, const char **argv) { PrintUsage(program); return 0; } - const char *assetsDir = NULL; + const char *baseDir = NULL; const char *buildDir = NULL; const char *romFile = NULL; Region region = 0; @@ -431,7 +437,7 @@ int main(int argc, const char **argv) { fprintf(stderr, "Expected pathname after -a\n"); return 1; } - assetsDir = argv[i]; + baseDir = argv[i]; } else if (strcmp(argv[i], "-b") == 0) { if (++i >= argc) { fprintf(stderr, "Expected pathname after -b\n"); @@ -453,9 +459,9 @@ int main(int argc, const char **argv) { return 1; } } - if (assetsDir == NULL) { + if (baseDir == NULL) { PrintUsage(program); - fprintf(stderr, "Please provide an assets directory, see usage above\n"); + fprintf(stderr, "Please provide a base directory, see usage above\n"); return 1; } if (buildDir == NULL) { @@ -530,8 +536,8 @@ int main(int argc, const char **argv) { return 1; } - if (chdir(assetsDir) != 0) { - fprintf(stderr, "Failed to enter assets directory '%s'\n", assetsDir); + if (chdir(baseDir) != 0) { + fprintf(stderr, "Failed to enter base directory '%s'\n", baseDir); return 1; } @@ -539,6 +545,11 @@ int main(int argc, const char **argv) { header.arm7.offset = address; if (!AppendFile(fpRom, ARM7_PROGRAM_FILE, &address, &header.arm7.size)) return 1; + if (chdir(ASSETS_SUBDIR) != 0) { + fprintf(stderr, "Failed to enter assets directory '" ASSETS_SUBDIR "'\n"); + return 1; + } + FileTree root; if (!MakeFileTree(&root)) return false; if (!SortFileTree(&root)) return false; @@ -556,8 +567,13 @@ int main(int argc, const char **argv) { if (!FreeFileTree(&root)) return false; + if (chdir("..") != 0) { + fprintf(stderr, "Failed to leave assets directory '" ASSETS_SUBDIR "'\n"); + return 1; + } + if (chdir(rootDir) != 0) { - fprintf(stderr, "Failed to leave assets directory '%s'\n", assetsDir); + fprintf(stderr, "Failed to leave base directory '%s'\n", baseDir); return 1; } diff --git a/tools/rom/files.h b/tools/rom/files.h index 4f53dbce..2dd5ca34 100644 --- a/tools/rom/files.h +++ b/tools/rom/files.h @@ -21,6 +21,8 @@ bool IterFiles(bool (*callback)(const char *name, bool isDir, void*), void *user if (hFind == INVALID_HANDLE_VALUE) FATAL("Failed to open directory to iterate files\n"); do { const char *name = findData.cFileName; + if (strcmp(name, ".") == 0) continue; + if (strcmp(name, "..") == 0) continue; bool isDir = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; if (!callback(name, isDir, userData)) return false; } while (FindNextFileA(hFind, &findData)); @@ -40,7 +42,7 @@ bool IterFiles(bool (*callback)(const char *name, bool isDir, void*), void *user bool _GrowFileTreeChildren(FileTree *pTree, size_t minChildren) { FileTree tree; memcpy(&tree, pTree, sizeof(tree)); - if (tree.numChildren >= minChildren) return true; + if (tree.maxChildren >= minChildren) return true; size_t newSize = tree.maxChildren; if (newSize == 0) newSize = minChildren; @@ -77,6 +79,7 @@ bool _FileTreeFileCallback(const char *name, bool isDir, void *userData) { FileTree child; if (!MakeFileTree(&child)) return false; child.entry = entry; + if (!_GrowFileTreeChildren(pTree, pTree->numChildren + 1)) return false; memcpy(&pTree->children[pTree->numChildren], &child, sizeof(child)); pTree->numChildren += 1; @@ -98,12 +101,14 @@ bool _FileTreeFileCallback(const char *name, bool isDir, void *userData) { memcpy(&pTree->children[pTree->numChildren], &child, sizeof(child)); pTree->numChildren += 1; } + return true; } bool MakeFileTree(FileTree *pTree) { FileTree tree; - tree.maxChildren = 0; + tree.children = NULL; tree.numChildren = 0; + tree.maxChildren = 0; if (!_GrowFileTreeChildren(&tree, 64)) return false; tree.entry = NULL; @@ -126,6 +131,7 @@ bool FreeFileTree(FileTree *pTree) { free(pTree->entry); pTree->entry = NULL; } + return true; } int CompareFileTree(const void *a, const void *b) { @@ -134,14 +140,21 @@ int CompareFileTree(const void *a, const void *b) { size_t lenA = treeA->entry->length; size_t lenB = treeB->entry->length; size_t minSize = (lenA < lenB) ? lenA : lenB; - int cmp = strncmp(treeA->entry->name, treeB->entry->name, minSize); - if (cmp != 0) return cmp; + + const char *nameA = treeA->entry->name; + const char *nameB = treeB->entry->name; + for (size_t i = 0; i < minSize; ++i) { + const char chA = tolower(nameA[i]); + const char chB = tolower(nameB[i]); + if (chA != chB) return chA - chB; + } if (lenA < lenB) return -1; if (lenA > lenB) return 1; return 0; } bool SortFileTree(FileTree *pTree) { + if (pTree->numChildren <= 1) return true; FileTree tree; memcpy(&tree, pTree, sizeof(tree)); diff --git a/tools/rom/ph.h b/tools/rom/ph.h index 31dc32af..aedb4e11 100644 --- a/tools/rom/ph.h +++ b/tools/rom/ph.h @@ -17,7 +17,7 @@ #define ASSETS_SUBDIR "assets" #define ARM9_PROGRAM_FILE "arm9.lz" -#define ARM9_FOOTER_FILE "footer.bin" +#define ARM9_FOOTER_FILE "arm9_footer.bin" #define ARM9_OVERLAY_TABLE_FILE "arm9_ovt.bin" #define OVERLAYS_SUBDIR "overlays" diff --git a/tools/rom/rom.h b/tools/rom/rom.h index cbeaddef..2ea778d9 100644 --- a/tools/rom/rom.h +++ b/tools/rom/rom.h @@ -47,8 +47,8 @@ typedef struct { /* 0084 */ uint32_t headerSize; /* 0088 */ uint32_t autoloadParamsOffset; /* 008c */ uint8_t reserved1[0x8]; - /* 0094 */ uint32_t romEnd; - /* 0096 */ uint32_t rwEnd; + /* 0094 */ uint16_t romEnd; + /* 0096 */ uint16_t rwEnd; /* 0098 */ uint8_t reserved2[0x18]; /* 00b0 */ uint8_t reserved3[0x10]; /* 00c0 */ uint8_t logo[0x9c]; diff --git a/tools/rom/util.h b/tools/rom/util.h index 0ef47173..884b9970 100644 --- a/tools/rom/util.h +++ b/tools/rom/util.h @@ -7,12 +7,12 @@ #define FATAL(...) do { fprintf(stderr, __VA_ARGS__); return false; } while (0) -#define WRITE16(buf,val) do { ((char*) buf)[0] = (val) & 0xFF; ((char*) buf)[1] = ((val) >> 8) & 0xFF; } while (0) -#define WRITE24(buf,val) do { ((char*) buf)[0] = (val) & 0xFF; ((char*) buf)[1] = ((val) >> 8) & 0xFF; ((char*) buf)[2] = ((val) >> 16) & 0xFF; } while (0) -#define WRITE32(buf,val) do { ((char*) buf)[0] = (val) & 0xFF; ((char*) buf)[1] = ((val) >> 8) & 0xFF; ((char*) buf)[2] = ((val) >> 16) & 0xFF; ((char*) buf)[3] = ((val) >> 24) & 0xFF; } while (0) -#define READ16(buf) (((char*) buf)[0] | (((char*) buf)[1] << 8)) -#define READ24(buf) (((char*) buf)[0] | (((char*) buf)[1] << 8) | (((char*) buf)[2] << 16)) -#define READ32(buf) (((char*) buf)[0] | (((char*) buf)[1] << 8) | (((char*) buf)[2] << 16) | (((char*) buf)[3] << 24)) +#define WRITE16(buf,val) do { ((uint8_t*) buf)[0] = (val) & 0xFF; ((uint8_t*) buf)[1] = ((val) >> 8) & 0xFF; } while (0) +#define WRITE24(buf,val) do { ((uint8_t*) buf)[0] = (val) & 0xFF; ((uint8_t*) buf)[1] = ((val) >> 8) & 0xFF; ((uint8_t*) buf)[2] = ((val) >> 16) & 0xFF; } while (0) +#define WRITE32(buf,val) do { ((uint8_t*) buf)[0] = (val) & 0xFF; ((uint8_t*) buf)[1] = ((val) >> 8) & 0xFF; ((uint8_t*) buf)[2] = ((val) >> 16) & 0xFF; ((uint8_t*) buf)[3] = ((val) >> 24) & 0xFF; } while (0) +#define READ16(buf) (((uint8_t*) buf)[0] | (((uint8_t*) buf)[1] << 8)) +#define READ24(buf) (((uint8_t*) buf)[0] | (((uint8_t*) buf)[1] << 8) | (((uint8_t*) buf)[2] << 16)) +#define READ32(buf) (((uint8_t*) buf)[0] | (((uint8_t*) buf)[1] << 8) | (((uint8_t*) buf)[2] << 16) | (((uint8_t*) buf)[3] << 24)) #ifdef _WIN32 # include