From: root Date: Thu, 2 Jun 2016 18:20:47 +0000 (-0400) Subject: Loader now uses externalized patches. X-Git-Tag: stable-1~10 X-Git-Url: https://chaos.moe/g/?a=commitdiff_plain;h=a467d9fbd12d1e30dbaed6d9765c7dce1d4b8282;p=corbenik%2Fcorbenik.git Loader now uses externalized patches. Aside from a few ones that involve complicated steps, of course. It's STILL smaller than Nintendo's loader, incidentally! (A few things need tweaking - namely, it is very slow to boot. I expect I need some kind of patch cache generated prior to boot. I also need to turn off the altmenu patch.) --- diff --git a/external/loader/source/interp.c b/external/loader/source/interp.c index d09955e..92440af 100644 --- a/external/loader/source/interp.c +++ b/external/loader/source/interp.c @@ -1,8 +1,6 @@ // 'Tis not ready for the world at large yet. // I don't want to delete it since I'm working on it though, // so it's temporarliy #if'd 0. -#if 0 - #define LOADER 1 #include <3ds.h> @@ -19,9 +17,13 @@ #include "config.h" #include "../../../source/patch_format.h" -#include "patch/patch.h" +// Because I want to avoid malloc. +// Patches must be smaller than this (including header!) +#define MAX_PATCHSIZE 512 // Yes, we're including a C file. Problem? #include "../../../source/interp.c" +#if 0 + #endif diff --git a/external/loader/source/interp.h b/external/loader/source/interp.h new file mode 100644 index 0000000..06849dd --- /dev/null +++ b/external/loader/source/interp.h @@ -0,0 +1,6 @@ +#ifndef __INTERP_H +#define __INTERP_H + +int execb(char* filename, uint64_t tid, uint8_t* search_mem, uint32_t search_len); + +#endif diff --git a/external/loader/source/logger.c b/external/loader/source/logger.c index 4aa090a..9f71e53 100644 --- a/external/loader/source/logger.c +++ b/external/loader/source/logger.c @@ -11,8 +11,6 @@ #include "config.h" #include "../../../source/patch_format.h" -#include "patch/patch.h" - Handle log_file_hdl; int logger_is_initd = 0; @@ -51,7 +49,7 @@ void logstr(const char* str) { return; // Write data. - FSFILE_Write(log_file_hdl, &wrote, size, str, len, 0); + FSFILE_Write(log_file_hdl, &wrote, size, str, len, FS_WRITE_FLUSH); } void logu64(u64 progId) { diff --git a/external/loader/source/memory.c b/external/loader/source/memory.c index 40a9ddd..b131616 100644 --- a/external/loader/source/memory.c +++ b/external/loader/source/memory.c @@ -10,8 +10,6 @@ #include "config.h" #include "../../../source/patch_format.h" -#include "patch/patch.h" - int memcmp(const void* buf1, const void* buf2, u32 size) { diff --git a/external/loader/source/patch/block_cart_update.c b/external/loader/source/patch/block_cart_update.c deleted file mode 100644 index 362a7d2..0000000 --- a/external/loader/source/patch/block_cart_update.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "patch.h" - -/* - find 4, 0x0C, 0x18, 0xE1, 0xD8 - set 4, 0x0B, 0x18, 0x21, 0xC8 - - find 4, 0x0C, 0x18, 0xE1, 0xD8 - set 4, 0x0B, 0x18, 0x21, 0xC8 -*/ - -void -disable_cart_updates(u64 progId, u8* code, u32 size) -{ - static const u8 stopCartUpdatesPattern[] = { 0x0C, 0x18, 0xE1, 0xD8 }; - static const u8 stopCartUpdatesPatch[] = { 0x0B, 0x18, 0x21, 0xC8 }; - - // Disable updates from foreign carts (makes carts region-free) - patchMemory(code, size, stopCartUpdatesPattern, - sizeof(stopCartUpdatesPattern), 0, stopCartUpdatesPatch, - sizeof(stopCartUpdatesPatch), 2); - - logstr(" disable_cart_updates\n"); -} diff --git a/external/loader/source/patch/block_eshop_update.c b/external/loader/source/patch/block_eshop_update.c deleted file mode 100644 index b2894f6..0000000 --- a/external/loader/source/patch/block_eshop_update.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "patch.h" - -/* - find 4, 0x30, 0xB5, 0xF1, 0xB0 - set 6, 0x00, 0x20, 0x08, 0x60, 0x70, 0x47 - */ - -void -disable_eshop_updates(u64 progId, u8* code, u32 size) -{ - static const u8 skipEshopUpdateCheckPattern[] = { 0x30, 0xB5, 0xF1, 0xB0 }; - static const u8 skipEshopUpdateCheckPatch[] = { 0x00, 0x20, 0x08, - 0x60, 0x70, 0x47 }; - - // Skip update checks to access the EShop - patchMemory(code, size, skipEshopUpdateCheckPattern, - sizeof(skipEshopUpdateCheckPattern), 0, - skipEshopUpdateCheckPatch, sizeof(skipEshopUpdateCheckPatch), - 1); - - logstr(" disable_eshop_updates\n"); -} diff --git a/external/loader/source/patch/block_nim_update.c b/external/loader/source/patch/block_nim_update.c deleted file mode 100644 index 1e049a0..0000000 --- a/external/loader/source/patch/block_nim_update.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "patch.h" - -/* - find 4, 0x25, 0x79, 0x0B, 0x99 - set 2, 0xE3, 0xA0 - */ - -void -disable_nim_updates(u64 progId, u8* code, u32 size) -{ - static const u8 blockAutoUpdatesPattern[] = { 0x25, 0x79, 0x0B, 0x99 }; - static const u8 blockAutoUpdatesPatch[] = { 0xE3, 0xA0 }; - - // Block silent auto-updates - patchMemory(code, size, blockAutoUpdatesPattern, - sizeof(blockAutoUpdatesPattern), 0, blockAutoUpdatesPatch, - sizeof(blockAutoUpdatesPatch), 1); - - logstr(" disable_nim_updates\n"); -} diff --git a/external/loader/source/patch/errdisp.c b/external/loader/source/patch/errdisp.c deleted file mode 100644 index 8446b8f..0000000 --- a/external/loader/source/patch/errdisp.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "patch.h" - -/* - find 8, 0x14, 0x00, 0xD0, 0xE5, 0xDB, 0x9A, 0x9F, 0xED - set 4, 0x00, 0x00, 0xA0, 0xE3 - - find 8, 0x14, 0x00, 0xD0, 0xE5, 0x01, 0x00, 0x10, 0xE3 - set 4, 0x00, 0x00, 0xA0, 0xE3 - find 8, 0x14, 0x00, 0xD0, 0xE5, 0x01, 0x00, 0x10, 0xE3 - set 4, 0x00, 0x00, 0xA0, 0xE3 - find 8, 0x14, 0x00, 0xD0, 0xE5, 0x01, 0x00, 0x10, 0xE3 - set 4, 0x00, 0x00, 0xA0, 0xE3 - */ - -void errdisp_devpatch(u64 progId, u8* code, u32 size) { - static const u8 unitinfoCheckPattern1[] = {0x14, 0x00, 0xD0, 0xE5, 0xDB, 0x9A, 0x9F, 0xED}; - static const u8 unitinfoCheckPattern2[] = {0x14, 0x00, 0xD0, 0xE5, 0x01, 0x00, 0x10, 0xE3} ; - static const u8 unitinfoCheckPatch[] = {0x00, 0x00, 0xA0, 0xE3} ; - - patchMemory(code, size, - unitinfoCheckPattern1, - sizeof(unitinfoCheckPattern1), 0, - unitinfoCheckPatch, - sizeof(unitinfoCheckPatch), 1 - ); - - patchMemory(code, size, - unitinfoCheckPattern2, - sizeof(unitinfoCheckPattern2), 0, - unitinfoCheckPatch, - sizeof(unitinfoCheckPatch), 3 - ); -} diff --git a/external/loader/source/patch/friends_ver.c b/external/loader/source/patch/friends_ver.c deleted file mode 100644 index f24c228..0000000 --- a/external/loader/source/patch/friends_ver.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "patch.h" - -/* - find 8, 0xE0, 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x01, 0x01 - fwd 9 - set 1, 0x06 - */ - -void -fake_friends_version(u64 progId, u8* code, u32 size) -{ - static const u8 fpdVerPattern[] = { 0xE0, 0x1E, 0xFF, 0x2F, - 0xE1, 0x01, 0x01, 0x01 }; - static const u8 fpdVerPatch = 0x06; // Latest version. - - // Allow online access to work with old friends modules - patchMemory(code, size, fpdVerPattern, sizeof(fpdVerPattern), 9, - &fpdVerPatch, sizeof(fpdVerPatch), 1); - - logstr(" fake_friends_version\n"); -} diff --git a/external/loader/source/patch/mset_str.c b/external/loader/source/patch/mset_str.c deleted file mode 100644 index 1569199..0000000 --- a/external/loader/source/patch/mset_str.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "patch.h" - -/* - find 8, u"Ver." - set 8, u".hax" - */ - -void -settings_string(u64 progId, u8* code, u32 size) -{ - static const u16 verPattern[] = u"Ver."; - static const u16 verPatch[] = u".hax"; - - // Patch Ver. string - patchMemory(code, size, verPattern, sizeof(verPattern) - sizeof(u16), 0, - verPatch, sizeof(verPatch) - sizeof(u16), 1); - - logstr(" settings_string\n"); -} diff --git a/external/loader/source/patch/patch.h b/external/loader/source/patch/patch.h deleted file mode 100644 index e9bc4c4..0000000 --- a/external/loader/source/patch/patch.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __PATCH_PATCH_H -#define __PATCH_PATCH_H - -#include <3ds.h> -#include "../patcher.h" -#include "../memory.h" -#include "../logger.h" - -#ifndef PATH_MAX -#define PATH_MAX 255 -#define _MAX_LFN 255 -#endif -#include "../config.h" -#include "../../../../source/patch_format.h" - -void disable_cart_updates(u64 progId, u8* code, u32 size); -void disable_eshop_updates(u64 progId, u8* code, u32 size); -void disable_nim_updates(u64 progId, u8* code, u32 size); -void fake_friends_version(u64 progId, u8* code, u32 size); -void settings_string(u64 progId, u8* code, u32 size); -void region_patch(u64 progId, u8* code, u32 size); -void ro_sigpatch(u64 progId, u8* code, u32 size); -void secureinfo_sigpatch(u64 progId, u8* code, u32 size); -void errdisp_devpatch(u64 progId, u8* code, u32 size); - -#endif diff --git a/external/loader/source/patch/regionfree.c b/external/loader/source/patch/regionfree.c deleted file mode 100644 index f8e677e..0000000 --- a/external/loader/source/patch/regionfree.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "patch.h" - -/* - find 8, 0x00, 0x00, 0x55, 0xE3, 0x01, 0x10, 0xA0, 0xE3 - back 16 - set 8, 0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 - */ - -void -region_patch(u64 progId, u8* code, u32 size) -{ - static const u8 regionFreePattern[] = { 0x00, 0x00, 0x55, 0xE3, - 0x01, 0x10, 0xA0, 0xE3 }; - static const u8 regionFreePatch[] = { 0x01, 0x00, 0xA0, 0xE3, - 0x1E, 0xFF, 0x2F, 0xE1 }; - - // Patch SMDH region checks - patchMemory(code, size, regionFreePattern, sizeof(regionFreePattern), -16, - regionFreePatch, sizeof(regionFreePatch), 1); - - logstr(" region_patch\n"); -} diff --git a/external/loader/source/patch/ro_sigs.c b/external/loader/source/patch/ro_sigs.c deleted file mode 100644 index b44d821..0000000 --- a/external/loader/source/patch/ro_sigs.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "patch.h" - -/* - find 8, 0x30, 0x40, 0x2D, 0xE9, 0x02, 0x50, 0xA0, 0xE1 - set 8, 0x00, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 - - find 8, 0x30, 0x40, 0x2D, 0xE9, 0x24, 0xD0, 0x4D, 0xE2 - set 8, 0x00, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 - - find 8, 0xF8, 0x4F, 0x2D, 0xE9, 0x01, 0x70, 0xA0, 0xE1 - set 8, 0x00, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 - */ - -void -ro_sigpatch(u64 progId, u8* code, u32 size) -{ - static const u8 sigCheckPattern[] = { 0x30, 0x40, 0x2D, 0xE9, - 0x02, 0x50, 0xA0, 0xE1 }; - static const u8 sha256ChecksPattern1[] = { 0x30, 0x40, 0x2D, 0xE9, - 0x24, 0xD0, 0x4D, 0xE2 }; - static const u8 sha256ChecksPattern2[] = { 0xF8, 0x4F, 0x2D, 0xE9, - 0x01, 0x70, 0xA0, 0xE1 }; - - // mov r0, #0; bx lr - equivalent to 'return 0;' - static const u8 stub[] = { 0x00, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 }; - - // Disable CRR0 signature (RSA2048 with SHA256) check - patchMemory(code, size, sigCheckPattern, sizeof(sigCheckPattern), 0, stub, - sizeof(stub), 1); - - // Disable CRO0/CRR0 SHA256 hash checks (section hashes, and hash table) - patchMemory(code, size, sha256ChecksPattern1, sizeof(sha256ChecksPattern1), - 0, stub, sizeof(stub), 1); - - patchMemory(code, size, sha256ChecksPattern2, sizeof(sha256ChecksPattern2), - 0, stub, sizeof(stub), 1); - - logstr(" ro_sigpatch\n"); -} diff --git a/external/loader/source/patch/secinfo_sigs.c b/external/loader/source/patch/secinfo_sigs.c deleted file mode 100644 index 525b386..0000000 --- a/external/loader/source/patch/secinfo_sigs.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "patch.h" - -/* - find 5, 0x06, 0x46, 0x10, 0x48, 0xFC - set 2, 0x00, 0x26 - */ - -void -secureinfo_sigpatch(u64 progId, u8* code, u32 size) -{ - static const u8 secureinfoSigCheckPattern[] = { 0x06, 0x46, 0x10, 0x48, - 0xFC }; - static const u8 secureinfoSigCheckPatch[] = { 0x00, 0x26 }; - - // Disable SecureInfo signature check - patchMemory(code, size, secureinfoSigCheckPattern, - sizeof(secureinfoSigCheckPattern), 0, secureinfoSigCheckPatch, - sizeof(secureinfoSigCheckPatch), 1); - - logstr(" secureinfo_sigpatch\n"); -} diff --git a/external/loader/source/patcher.c b/external/loader/source/patcher.c index 121f55c..ca98da6 100644 --- a/external/loader/source/patcher.c +++ b/external/loader/source/patcher.c @@ -4,15 +4,14 @@ #include "internal.h" #include "memory.h" #include "logger.h" +#include "../../../source/patch_format.h" +#include "interp.h" #ifndef PATH_MAX #define PATH_MAX 255 #define _MAX_LFN 255 #endif #include "config.h" -#include "../../../source/patch_format.h" - -#include "patch/patch.h" int fileOpen(Handle* file, FS_ArchiveID id, const char* path, int flags) @@ -57,8 +56,7 @@ load_config() FSFILE_Close(file); // Read to memory. - if (config.magic[0] != 'O' || config.magic[1] != 'V' || - config.magic[2] != 'A' || config.magic[3] != 'N') { + if (memcmp(config.magic, "OVAN", 4)) { // Incorrect magic. // Failed to read. return; @@ -355,69 +353,21 @@ patch_ro(u64 progId, u8* ro, u32 size, u32 orig_size) void patch_text(u64 progId, u8* text, u32 size, u32 orig_size) { - switch (progId) { - case 0x0004003000008F02LL: // USA Menu - case 0x0004003000008202LL: // EUR Menu - case 0x0004003000009802LL: // JPN Menu - case 0x000400300000A102LL: // CHN Menu - case 0x000400300000A902LL: // KOR Menu - case 0x000400300000B102LL: // TWN Menu - { - region_patch(progId, text, orig_size); - break; - } - - case 0x0004013000002C02LL: // NIM - { - disable_nim_updates(progId, text, orig_size); - disable_eshop_updates(progId, text, orig_size); - break; - } - - case 0x0004013000003202LL: // FRIENDS - { - fake_friends_version(progId, text, orig_size); - break; - } - - case 0x0004001000021000LL: // USA MSET - case 0x0004001000020000LL: // JPN MSET - case 0x0004001000022000LL: // EUR MSET - case 0x0004001000026000LL: // CHN MSET - case 0x0004001000027000LL: // KOR MSET - case 0x0004001000028000LL: // TWN MSET - { - settings_string(progId, text, size); - break; - } - case 0x0004013000008002LL: // NS - { - disable_cart_updates(progId, text, orig_size); - adjust_cpu_settings(progId, text, orig_size); - break; - } - - case 0x0004013000001702LL: // CFG - { - secureinfo_sigpatch(progId, text, orig_size); - break; - } - case 0x0004013000003702LL: // RO - { - ro_sigpatch(progId, text, orig_size); - break; - } - case 0x0004003000008A02LL: // ErrDisp - { - errdisp_devpatch(progId, text, orig_size); - break; - } - default: // Anything else. - { - language_emu(progId, text, orig_size); - break; - } - } + if (progId == 0x0004013000008002LL) + adjust_cpu_settings(progId, text, orig_size); + + execb(PATH_PATCHES "/block_nim_update.vco", progId, text, orig_size); + execb(PATH_PATCHES "/block_eshop_update.vco", progId, text, orig_size); + execb(PATH_PATCHES "/block_cart_update.vco", progId, text, orig_size); + execb(PATH_PATCHES "/errdisp.vco", progId, text, orig_size); + execb(PATH_PATCHES "/friends_ver.vco", progId, text, orig_size); + execb(PATH_PATCHES "/mset_str.vco", progId, text, orig_size); + execb(PATH_PATCHES "/ns_force_menu.vco", progId, text, orig_size); + execb(PATH_PATCHES "/regionfree.vco", progId, text, orig_size); + execb(PATH_PATCHES "/secinfo_sigs.vco", progId, text, orig_size); + execb(PATH_PATCHES "/ro_sigs.vco", progId, text, orig_size); + + language_emu(progId, text, orig_size); } // Gets how many bytes .text must be extended by for patches to fit. diff --git a/host/bytecode_asm.py b/host/bytecode_asm.py index 30aed0e..993ee46 100755 --- a/host/bytecode_asm.py +++ b/host/bytecode_asm.py @@ -204,8 +204,6 @@ with open(in_file, "r") as ins: offsets += [size] size += len(bytes) - print(offsets) - ins.seek(0) for line in ins: @@ -226,7 +224,11 @@ with open(in_file, "r") as ins: data += struct.pack('I', size) if title: for f in title: - data += bytearray.fromhex(f) + tid = bytearray.fromhex(f) # Endianness. + print([tid]) + tid.reverse() + print([tid]) + data += tid if deps: for f in deps: data += pad_zero_r(bytearray.fromhex(f), 8) diff --git a/source/interp.c b/source/interp.c index ad82970..70e183a 100644 --- a/source/interp.c +++ b/source/interp.c @@ -21,8 +21,10 @@ #define OP_TITLE 0x0A #ifdef LOADER - #define fprintf(a...) - #define abort(a...) + #define log(a) logstr(a) + #define abort(a) { logstr(a) ; svcBreak(USERBREAK_ASSERT) ; } +#else + #define log(a) fprintf(stderr, a) #endif struct mode { @@ -119,7 +121,7 @@ int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug) { switch(*code) { case OP_NOP: if (debug) - fprintf(stderr, "nop\n"); + log("nop\n"); code++; test_was_false = 0; break; @@ -129,7 +131,7 @@ int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug) { code += 2; #else if (debug) - fprintf(stderr, "rel\n"); + log("rel\n"); code++; if (!test_was_false) current_mode = &modes[*code]; @@ -141,15 +143,13 @@ int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug) { break; case OP_FIND: // Find pattern. if (debug) - fprintf(stderr, "find\n"); + log("find\n"); code += 2; if (!test_was_false) { offset = (uint32_t)memfind(current_mode->memory+offset, current_mode->size - offset, code, *(code-1)); if ((uint8_t*)offset == NULL) { // Error. Abort. abort("Find opcode failed.\n"); - } else if (debug) { - fprintf(stderr, "Match @ %x\n", offset); } offset = offset - (uint32_t)current_mode->memory; } else { @@ -159,7 +159,7 @@ int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug) { break; case OP_BACK: if (debug) - fprintf(stderr, "back\n"); + log("back\n"); code++; if (!test_was_false) { if (offset < *code) { @@ -174,7 +174,7 @@ int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug) { break; case OP_FWD: if (debug) - fprintf(stderr, "fwd\n"); + log("fwd\n"); code++; if (!test_was_false) { offset += *code; @@ -189,7 +189,7 @@ int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug) { break; case OP_SET: // Set data. if (debug) - fprintf(stderr, "set\n"); + log("set\n"); code += 2; if (!test_was_false) memcpy(current_mode->memory+offset, code, *(code-1)); @@ -200,24 +200,22 @@ int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug) { break; case OP_TEST: // Test data. if (debug) - fprintf(stderr, "test\n"); + log("test\n"); code += 2; if(memcmp(current_mode->memory+offset, code, *(code-1))) { test_was_false = 1; if (debug) - fprintf(stderr, "false\n"); + log("false\n"); } else if (debug) { - fprintf(stderr, "true\n"); + log("true\n"); } code += *(code-1); break; case OP_JMP: // Jump to offset. if (debug) - fprintf(stderr, "jmp\n"); + log("jmp\n"); code++; if (!test_was_false) { - if (debug) - fprintf(stderr, "jmp to %hu,%hu\n", code[0], code[1]); code = bytecode + code[1] + ( code[0] * 0x100 ); } else { code += 2; @@ -226,7 +224,7 @@ int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug) { break; case OP_REWIND: if (debug) - fprintf(stderr, "rewind\n"); + log("rewind\n"); code++; if (!test_was_false) offset = 0; @@ -235,7 +233,7 @@ int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug) { break; case OP_AND: if (debug) - fprintf(stderr, "and\n"); + log("and\n"); code += 2; if (!test_was_false) { for(i=0; i < *(code-1); i++) { @@ -249,9 +247,10 @@ int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug) { break; case OP_TITLE: if (debug) - fprintf(stderr, "title\n"); + log("title\n"); // FIXME - NYI default: +#ifndef LOADER // Panic; not proper opcode. fprintf(stderr, "Invalid opcode. State:\n" " Relative: %u\n" @@ -268,6 +267,7 @@ int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug) { code - bytecode, code, *code); +#endif abort("Halting startup.\n"); break; } @@ -281,24 +281,97 @@ int execb(char* filename, uint64_t tid, uint8_t* search_mem, uint32_t search_len #else int execb(char* filename) { #endif - uint8_t* patch_mem; uint32_t patch_len; struct system_patch* patch; #ifdef LOADER - // Loader can use actual allocation functions, so this isn't as much of an issue + log(" check "); + log(filename); + log("\n"); + + uint8_t patch_dat2[MAX_PATCHSIZE]; + uint8_t *patch_dat = patch_dat2; + + patch = (struct system_patch*)patch_dat; + + Handle file; + u32 total; + + // Open file. + if (!R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, filename, FS_OPEN_READ))) { + // Failed to open. + return 1; + } + + u64 file_size; + + if (!R_SUCCEEDED(FSFILE_GetSize(file, &file_size))) { + FSFILE_Close(file); // Read to memory. + + return 1; + } + + if (file_size > MAX_PATCHSIZE) { + log(" too large (please report)\n"); + + FSFILE_Close(file); // Read to memory. + + return 1; + } + + // Read file. + if (!R_SUCCEEDED(FSFILE_Read(file, &total, 0, patch_dat, file_size))) { + FSFILE_Close(file); // Read to memory. + + // Failed to read. + return 1; + } + + FSFILE_Close(file); // Done reading in. // Set memory. modes[18].memory = search_mem; modes[18].size = search_len; - // Load patch. We need memory, so... - // svcControlMemory(&tmp, __loader_prog_heap, 0x0, __ctru_heap_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); - // Check magic. + if (memcmp(patch->magic, "AIDA", 4)) { + log(" magic wrong\n"); + + return 1; // Incorrect patch magic. + } // Check TID supported. + if (patch->titles == 0) { + return 0; // Not an error - this patch isn't meant for us. + } + + log(" checking tid\n"); + + uint8_t* title_buf = patch_dat + sizeof(struct system_patch); + + int apply = 0; + for(uint32_t i=0; i < patch->titles; i++, title_buf += 8) { + if(!memcmp(title_buf, (uint8_t*)&tid, 8)) { + // Applicable patch found. + log(" applicable\n"); + apply = 1; + break; + } + } + + if (!apply) { + // Not meant for us. Not an error, though. + return 0; + } + + // Patch is relevant to us, so we'll apply it. + + log(" exec\n"); + + uint8_t* patch_mem = (uint8_t*)patch + sizeof(struct system_patch) + (patch->depends * 8) + (patch->titles * 8); + patch_len = patch->size; #else + uint8_t* patch_mem; // Read patch to scrap memory. FILE* f = fopen(filename, "r"); @@ -325,5 +398,5 @@ int execb(char* filename) { patch_mem = (uint8_t*)patch + sizeof(struct system_patch) + (patch->depends * 8) + (patch->titles * 8); patch_len = patch->size; #endif - return exec_bytecode(patch_mem, patch_len, 0); + return exec_bytecode(patch_mem, patch_len, 1); }