From 08220bd2a41c71f3f2e60d5dded226725683628f Mon Sep 17 00:00:00 2001 From: Aetias Date: Sat, 21 Oct 2023 12:54:05 +0200 Subject: [PATCH] Match autoload callback in ROM header --- asm/global.inc | 3 +-- asm/main.s | 10 +++++----- asm/ov01.s | 4 ++-- tools/lcf.py | 5 +++++ tools/rom/build.c | 41 ++++++++++++++++++++++++++++------------- tools/rom/ph.h | 1 + tools/rom/rom.h | 4 ++-- tools/rom/util.h | 26 ++++++++++++++++++++++++++ 8 files changed, 70 insertions(+), 24 deletions(-) diff --git a/asm/global.inc b/asm/global.inc index a3cf396c..285958c1 100644 --- a/asm/global.inc +++ b/asm/global.inc @@ -217,7 +217,6 @@ .extern data_02000934 .extern data_02000938 .extern data_02000a70 -.extern data_02000a74 .extern data_02000b30 .extern data_02000b34 .extern data_02000b38 @@ -251116,7 +251115,7 @@ .extern func_02000a40 .extern func_02000a50 .extern func_02000a6c -.extern func_02000a74 +.extern AutoloadDoneCallback .extern func_02000a78 .extern func_02000b60 .extern func_02000c30 diff --git a/asm/main.s b/asm/main.s index 019b0ab9..17b9effe 100644 --- a/asm/main.s +++ b/asm/main.s @@ -195,16 +195,16 @@ _02000a50: blt _02000a50 b _02000a0c _02000a6c: - b func_02000a74 + b AutoloadDoneCallback .align 2, 0 arm_func_end func_020009fc _02000a70: .word spAutoloadBlockInfosStart - .global func_02000a74 - arm_func_start func_02000a74 -func_02000a74: + .global AutoloadDoneCallback + arm_func_start AutoloadDoneCallback +AutoloadDoneCallback: bx lr - arm_func_end func_02000a74 + arm_func_end AutoloadDoneCallback .global func_02000a78 arm_func_start func_02000a78 diff --git a/asm/ov01.s b/asm/ov01.s index 7e40b4fa..c95e0d2d 100644 --- a/asm/ov01.s +++ b/asm/ov01.s @@ -5619,7 +5619,7 @@ _020f2b9e: bne _020f2b9e _020f2bb4: ldr r0, [sp, #0x14] - ldr r1, _020f2be8 ; =func_02000a74 + ldr r1, _020f2be8 ; =AutoloadDoneCallback ldr r2, [r0, #0x48] ldr r0, [r6, #0x28] sub r1, r1, r0 @@ -5642,7 +5642,7 @@ _020f2bd8: .word 0x027ffe00 _020f2bdc: .word data_ov01_020f890c _020f2be0: .word 0x00406000 _020f2be4: .word data_ov01_020f8908 -_020f2be8: .word func_02000a74 +_020f2be8: .word AutoloadDoneCallback _020f2bec: .word 0xe12fff1e .global func_ov01_020f2bf0 diff --git a/tools/lcf.py b/tools/lcf.py index 8008048c..6aaf6a50 100644 --- a/tools/lcf.py +++ b/tools/lcf.py @@ -225,6 +225,7 @@ with open(f'{BUILD}arm9_linker_script.lcf', 'w') as file: file.write(' DTCM : ORIGIN = 0x27e0000 >> arm9.bin\n') file.write(' AUTOLOADS : ORIGIN = 0 >> arm9.bin\n') file.write(' FOOTER : ORIGIN = 0 > arm9_footer.bin\n') + file.write(' METADATA : ORIGIN = 0 > arm9_metadata.bin\n') file.write('\n') file.write(' OV_TABLE : ORIGIN = 0 > arm9_ovt.bin\n') file.write('\n') @@ -279,6 +280,10 @@ with open(f'{BUILD}arm9_linker_script.lcf', 'w') as file: file.write(' WRITEW 0;\n') file.write(' } > FOOTER\n') file.write('\n') + file.write(' .metadata : {\n') + file.write(' WRITEW AutoloadDoneCallback;\n') + file.write(' } > METADATA\n') + file.write('\n') for ov in OVERLAYS: file.write(f' .{ov.name} : ' + '{\n') file.write(f' {ov.name}_start = .;\n') diff --git a/tools/rom/build.c b/tools/rom/build.c index 878157e6..8ec7f614 100644 --- a/tools/rom/build.c +++ b/tools/rom/build.c @@ -160,8 +160,8 @@ void InitHeader(Header *pHeader, const BuildInfo *info) { pHeader->bannerOffset = 0; // will be 256-aligned after file alloc table pHeader->secureAreaCrc = 0; // TODO: Calculate pHeader->secureAreaDelay = 0x0d7e; - pHeader->arm9AutoloadList = 0; // TODO: Get from linker (always 2000a74) - pHeader->arm7AutoloadList = 0x2380158; + pHeader->arm9AutoloadCallback = 0; // TODO: Get from linker (always 2000a74) + pHeader->arm7AutoloadCallback = 0x2380158; pHeader->secureAreaDisable = 0; pHeader->romSize = 0; // Will be set pHeader->headerSize = sizeof(Header); @@ -513,12 +513,22 @@ bool RewriteFat(FILE *fpRom, size_t fatStart, const FatEntry *entries, size_t nu fseek(fpRom, 0, SEEK_END); } -bool FinalizeHeader(FILE *fpRom, Header *pHeader, const char *arm7bios, uint32_t *secureArea) { +typedef struct { + uint32_t autoloadCallback; +} Arm9Metadata; + +bool FinalizeHeader(FILE *fpRom, Header *pHeader, const char *arm7bios) { Header header; memcpy(&header, pHeader, sizeof(header)); if (arm7bios != NULL) { - FILE *fp = fopen(arm7bios, "rb"); + FILE *fp = fopen(ARM9_PROGRAM_FILE, "rb"); + if (fp == NULL) FATAL("Failed to open ARM9 program '" ARM9_PROGRAM_FILE "'\n"); + uint32_t secureArea[0x1000]; + if (fread(secureArea, sizeof(secureArea), 1, fp) != 1) FATAL("Failed to read secure area\n"); + fclose(fp); + + fp = fopen(arm7bios, "rb"); if (fp == NULL) FATAL("Failed to open ARM7 BIOS '%s'\n", arm7bios); fseek(fp, 0x30, SEEK_SET); uint8_t encKey[sizeof(Blowfish)]; @@ -536,6 +546,13 @@ bool FinalizeHeader(FILE *fpRom, Header *pHeader, const char *arm7bios, uint32_t header.secureAreaCrc = Crc(secureArea, 0x4000); } + FILE *fp = fopen(ARM9_METADATA_FILE, "rb"); + if (fp == NULL) FATAL("Failed to open ARM9 metadata '" ARM9_METADATA_FILE "'\n"); + Arm9Metadata metadata; + if (fread(&metadata, sizeof(metadata), 1, fp) != 1) FATAL("Failed to read ARM9 metadata '" ARM9_METADATA_FILE "'\n"); + fclose(fp); + header.arm9AutoloadCallback = metadata.autoloadCallback; + header.headerCrc = Crc(&header, offsetof(Header, headerCrc)); size_t prevPos = ftell(fpRom); @@ -573,7 +590,7 @@ int main(int argc, const char **argv) { const char *baseDir = NULL; const char *buildDir = NULL; const char *romFile = NULL; - const char *arm7bios = NULL; + const char *arm7biosFile = NULL; Region region = 0; for (int i = 1; i < argc; ++i) { if (strcmp(argv[i], "-o") == 0) { @@ -599,7 +616,7 @@ int main(int argc, const char **argv) { fprintf(stderr, "Expected pathname after -7\n"); return 1; } - arm7bios = argv[i]; + arm7biosFile = argv[i]; } else if (strcmp(argv[i], "-r") == 0) { if (++i >= argc) { fprintf(stderr, "Expected region after -r\n"); @@ -755,6 +772,9 @@ int main(int argc, const char **argv) { return 1; } + char *arm7bios = NULL; + if (arm7biosFile != NULL && !AllocFullPath(arm7biosFile, &arm7bios)) return 1; + header.romSize = address; header.capacity = 15 - __builtin_clz(header.romSize); size_t romEnd = 1 << (17 + header.capacity); @@ -765,19 +785,14 @@ int main(int argc, const char **argv) { return 1; } - FILE *fp = fopen(ARM9_PROGRAM_FILE, "rb"); - if (fp == NULL) FATAL("Failed to open ARM9 program '" ARM9_PROGRAM_FILE "'\n"); - uint32_t secureArea[0x1000]; - if (fread(secureArea, sizeof(secureArea), 1, fp) != 1) FATAL("Failed to read secure area\n"); - fclose(fp); + if (!FinalizeHeader(fpRom, &header, arm7bios)) return false; + FreeFullPath(&arm7bios); if (chdir(rootDir) != 0) { fprintf(stderr, "Failed to leave build directory '%s'\n", buildDir); return 1; } - if (!FinalizeHeader(fpRom, &header, arm7bios, secureArea)) return false; - free(readBuffer); fclose(fpRom); } diff --git a/tools/rom/ph.h b/tools/rom/ph.h index aedb4e11..05d472a9 100644 --- a/tools/rom/ph.h +++ b/tools/rom/ph.h @@ -18,6 +18,7 @@ #define ARM9_PROGRAM_FILE "arm9.lz" #define ARM9_FOOTER_FILE "arm9_footer.bin" +#define ARM9_METADATA_FILE "arm9_metadata.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 38e96d96..f8423adf 100644 --- a/tools/rom/rom.h +++ b/tools/rom/rom.h @@ -40,8 +40,8 @@ typedef struct { /* 0068 */ uint32_t bannerOffset; /* 006c */ uint16_t secureAreaCrc; /* 006e */ uint16_t secureAreaDelay; - /* 0070 */ uint32_t arm9AutoloadList; - /* 0074 */ uint32_t arm7AutoloadList; + /* 0070 */ uint32_t arm9AutoloadCallback; + /* 0074 */ uint32_t arm7AutoloadCallback; /* 0078 */ uint64_t secureAreaDisable; /* 0080 */ uint32_t romSize; /* 0084 */ uint32_t headerSize; diff --git a/tools/rom/util.h b/tools/rom/util.h index 9164f2a6..e245b3b2 100644 --- a/tools/rom/util.h +++ b/tools/rom/util.h @@ -59,4 +59,30 @@ bool Utf8ToWchar(char *in, size_t inSize, wchar_t *out, size_t outSize) { #endif } +bool AllocFullPath(const char *path, char **pFullPath) { +#ifdef _WIN32 + if (path[0] == '/') { + // Remove drive letter, e.g. /c/Projects/ph/ -> /Projects/ph/ + const char *root = strchr(path + 1, '/'); + if (root - path == 2) path = root; + } + size_t size = GetFullPathNameA(path, 0, NULL, NULL); + char *fullPath = malloc(size); + size_t resultSize = GetFullPathNameA(path, size, fullPath, NULL); + if (resultSize == 0 || resultSize > size) FATAL("Failed to get full path for '%s'\n", path); + *pFullPath = fullPath; + return true; +#elif __linux__ + char *fullPath = realpath(path, NULL); + if (fullPath == NULL) FATAL("Failed to get full path for '%s'\n", path); + *pFullPath = fullPath; + return true; +#endif +} + +void FreeFullPath(char **pFullPath) { + free(*pFullPath); + *pFullPath = NULL; +} + #endif