From d866013b4e5e57f185c45ede44b38cb4d654fed4 Mon Sep 17 00:00:00 2001 From: ProjectRevoTPP Date: Mon, 20 Apr 2020 10:23:05 -0400 Subject: update mwasmarm patcher and decompile string_util.c (thanks Demki) --- tools/mwasmarm_patcher/mwasmarm_patcher.c | 84 ++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 24 deletions(-) (limited to 'tools/mwasmarm_patcher/mwasmarm_patcher.c') diff --git a/tools/mwasmarm_patcher/mwasmarm_patcher.c b/tools/mwasmarm_patcher/mwasmarm_patcher.c index cfea660c..2b887503 100644 --- a/tools/mwasmarm_patcher/mwasmarm_patcher.c +++ b/tools/mwasmarm_patcher/mwasmarm_patcher.c @@ -4,53 +4,78 @@ #include #include -// mwasmarm patcher v1.1 -// Patches the Metrowerk C compiler assembler to stop the line ending bug. +// mwasmarm patcher v1.2 +// Patches the Metrowerk C compiler assembler to stop the line ending bug and the 0x400 incbin bug. // Changelog: // v1.1: Added patch definitions and looped over them to find the matching // definition as well as the version. +// v1.2: Switched to array system for applying multiple patches for compiler +// versions and added 0x400 incbin fix for each version. + +struct PatchPair { + int offsetPatch; + int newByte; +}; struct PatchDef { char *version; char *sha1before; char *sha1after; - int offsetPatch; - int newByte; + struct PatchPair *patches; +}; + +// Patch definitions for each of the respective assembler versions. +struct PatchPair g12BasePatches[] = { + { 0x57614, 0x5 }, + { 0xD47, 0x8D }, + {0} +}; + +struct PatchPair g20BasePatches[] = { + { 0x57644, 0x5 }, + { 0xD47, 0x8D }, + {0} +}; + +struct PatchPair g20sp2p4Patches[] = { + { 0x57834, 0x5 }, + { 0xD47, 0x8D }, + {0} }; +// Table of definitions for each assembler version struct PatchDef gPatchDefs[] = { // mwasmarm 1.2/base definition { "mwasmarm 1.2/base", "87f942cc0a0e90e73550d8d6f3fffcdeb5f69fa5", - "2f1ccff22eaa443bb79235ca6477d3b86bdfd7e4", - 0x57614, - 0x5 + "3395ac5decf49135d892e93a3e6dd38676025983", + g12BasePatches }, // mwasmarm 2.0/base definition { "mwasmarm 2.0/base", "9d63877c776245129b4727b41d3e9e63cfc9cd28", - "f5dea73bf90791e104cb59458bebae8b08a55484", - 0x57644, - 0x5 + "ef75c3fb9f8d90cb4881386c41d8dc3ab4de7153", + g20BasePatches }, // mwasmarm 2.0/sp2p4 definition { "mwasmarm 2.0/sp2p4", "448cb0c7f1ace4393e9a9562f819f7a9f049be83", - "c82161527277b991a1b77e14617a93bcd19cf95c", - 0x57834, - 0x5 + "caa84dd90b1987ab7b42749bd5c9dcfdcfef59f3", + g20sp2p4Patches }, - { - } + {0} }; +// --------------------------------------------------------- +// Credit to ax6 for implementation of sha1 hash functions +// --------------------------------------------------------- + void sha1_process_block (const unsigned char * block, uint32_t * state); -// Credit to ax6 for implementation unsigned char * calculate_sha1 (const void * data, unsigned length) { uint32_t state[5] = {0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0}; const char * current; @@ -118,6 +143,10 @@ void sha1_process_block (const unsigned char * block, uint32_t * state) { state[4] += e; } +// --------------------------------------------------------- +// ax6 code end +// --------------------------------------------------------- + void fatal_printf(char *str, ...) { va_list args; va_start(args, str); @@ -146,21 +175,21 @@ int main(int argc, char *argv[]) { print_help(); return 1; } else { - // Open the file and sha1 read it. + // Open the file and read it's sha1 hash. FILE *f = fopen(argv[1], "rb+"); - if(f == NULL) { + if (f == NULL) { fatal_printf("ERROR: No file detected\n"); } int fsize = get_file_size(f); unsigned char *string = malloc(fsize + 1); - if(string == NULL) { + if (string == NULL) { fatal_printf("ERROR: Failed to allocate string variable\n"); } int readvar = fread(string, 1, fsize, f); // var to surpress warning // Check if sha1 matches either known assembler hashes. unsigned char *sha1 = calculate_sha1(string, fsize); - if(sha1 == NULL) { + if (sha1 == NULL) { fatal_printf("ERROR: Failed to retrieve sha1 hash\n"); } free(string); @@ -169,19 +198,26 @@ int main(int argc, char *argv[]) { for (int i=0; i < SHA_DIGEST_LENGTH; i++) { sprintf((unsigned char*)&(buf[i*2]), "%02x", sha1[i]); } + free(sha1); - for(int i = 0; gPatchDefs[i].sha1before != NULL; i++) { + // loop over each patch definition to attempt to locate a supported version and, if + // needed, apply the patch definitions. + for (int i = 0; gPatchDefs[i].sha1before != NULL; i++) { // check if already patched for the current loop. - if(!strcmp(buf, gPatchDefs[i].sha1after)) { + if (!strcmp(buf, gPatchDefs[i].sha1after)) { printf("Supported patched version detected (%s): no action needed\n", gPatchDefs[i].version); return 0; } else if(!strcmp(buf, gPatchDefs[i].sha1before)) { - fseek(f, gPatchDefs[i].offsetPatch, SEEK_SET); - fputc(gPatchDefs[i].newByte, f); + // we found an unpatched version: apply the patches. + for (int j = 0; gPatchDefs[i].patches[j].offsetPatch != 0; j++) { + fseek(f, gPatchDefs[i].patches[j].offsetPatch, SEEK_SET); + fputc(gPatchDefs[i].patches[j].newByte, f); + } printf("Supported unpatched version detected (%s): assembler patched\n", gPatchDefs[i].version); return 0; } } + // Unable to locate supported version, quitting fatal_printf("ERROR: Unsupported mwasmarm.exe version\n"); } return 0; -- cgit v1.2.3