diff --git a/build/tools/patchtmpjump/Makefile b/build/tools/patchtmpjump/Makefile new file mode 100644 index 00000000..04a268f7 --- /dev/null +++ b/build/tools/patchtmpjump/Makefile @@ -0,0 +1,46 @@ +#! make -f +#--------------------------------------------------------------------------- +# Project: TwlSDK - tools - patchtmpjump +# File: Makefile +# +# Copyright 2009 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#--------------------------------------------------------------------------- + +TWLSDK_PLATFORM = NITRO +TARGET_PLATFORM = NITRO + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +TARGETS = patchtmpjump.exe + +SOURCES = patchtmpjump.c +OBJECTS = patchtmpjump.o + +#INSTALL_DIR = $(TWL_INSTALL_TOOLSDIR)/bin +#INSTALL_TARGETS = $(TARGETS) + +LDIRT_CLEAN = $(OBJECTS) $(TARGETS) + +include $(TWLSDK_ROOT)/build/buildtools/modulerules.x86 + + +#---------------------------------------------------------------------------- +# build +#---------------------------------------------------------------------------- +do-build: $(TARGETS) + +$(TARGETS): $(OBJECTS) + $(CC_X86) $+ -o $@ + +patchtmpjump.o: patchtmpjump.c +# diff --git a/build/tools/patchtmpjump/patchtmpjump.c b/build/tools/patchtmpjump/patchtmpjump.c new file mode 100644 index 00000000..da7acf76 --- /dev/null +++ b/build/tools/patchtmpjump/patchtmpjump.c @@ -0,0 +1,405 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - tools - patchtmpjump + File: patchtmpjump.c + + Copyright 2009 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include // free() +#include +#include // stat() + +//#define ENABLE_DEBUG +#ifdef ENABLE_DEBUG +#define DEBUG_PRINT fprintf +#else +#define DEBUG_PRINT(...) +#endif +#define errorf(...) do { fprintf(stderr, "Error: "); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); } while(0) + +#define warningf(...) do { fprintf(stderr, "Warning: "); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); } while(0) + +#define SDK_NITROCODE_LE 0x2106c0de +#define SDK_NITROCODE_BE 0xdec00621 + +#define SURFFIX_TMPJUMP ".ntrtmpjump.srl" +#define NOP_CODE 0xE1A00000 + +typedef unsigned char u8; +typedef unsigned short int u16; +typedef unsigned long int u32; +typedef signed char s8; +typedef signed short int s16; +typedef signed long int s32; + +typedef struct ROM_Header +{ + // 0x000- + u8 header[32]; // システム予約 + + // 0x020- + // ARM9 + u32 main_rom_offset; // 転送元 ROM オフセット + u32 main_entry_address; // 実行開始アドレス(未実装) + u32 main_ram_address; // 転送先 RAM アドレス + u32 main_size; // 転送サイズ + + // ARM7 + u32 sub_rom_offset; // 転送元 ROM オフセット + u32 sub_entry_address; // 実行開始アドレス(未実装) + u32 sub_ram_address; // 転送先 RAM アドレス + u32 sub_size; // 転送サイズ + +} +ROM_Header; + +u32 SearchSdkVersion( void *filebuffer ); +s32 PatchForPMSleep( void *buffer, u32 version ); +int WriteFile(const char *filename, char *buffer, int size); +int ReadFile(const char *filename, void *filebuffer); + +// SDKバージョン検出用マジックコード +static const u32 sdk_ver_magic_code[] = { + SDK_NITROCODE_BE, + SDK_NITROCODE_LE, +}; + +// SDKバージョンリスト +static const u32 sdk_ver_list[] = { + 0x02004ee8, + 0x030028a0, + 0x03017530, + 0x03027531, + 0x04007530, + 0x04017531, + 0x04027530, +}; +static const u32 sdk_ver_mask = 0xFFFF0000; + +// 対象コード +static const u32 target_idx_400 = 3; +static const u32 target_code_400[] = { + // if (PMi_TriggerBL & PM_TRIGGER_CARD) + 0xE3100008, // TST Rx, #0x8 + 0x0A000001, // BEQ xxxx + // OS_EnableIrqMask(OS_IE_CARD_IREQ) + 0xE3A00601, // MOV Rx, #0x100000 + 0xEBFFD650, // BL EnableIrqMask <- target + // if (PMi_TriggerBL & PM_TRIGGER_CARTRIDGE) + 0xE59F00C8, // LDR Rx, [PC, #xxx] + 0xE1D000B0, // LDRH Rx, [Rx] + 0xE3100010, // TST R0, #0x10 + 0x0A000001, // BEQ xxxx + // OS_EnableIrqMask(OS_IE_CARTRIDGE) + 0xE3A00A02, // MOV Rx, #0x2000 + 0xEBFFD64A, // BL EnableIrqMask + // OS_RestoreInterrupts(prepIntrMode) + 0xE1A00004, // MOV Rx, Rx + 0xEBFFE377, // BL OS_RestoreInterrupts + // OS_EnableIrq() + 0, +}; +static const u32 target_mask_400[] = { + // if (PMi_TriggerBL & PM_TRIGGER_CARD) + 0xFEF0FFFF, // TST Rx, #0x8 + 0xFF000000, // BEQ xxxx + // OS_EnableIrqMask(OS_IE_CARD_IREQ) + 0xFFFF0FFF, // MOV Rx, #0x100000 + 0xFF000000, // BL EnableIrqMask <- target + // if (PMi_TriggerBL & PM_TRIGGER_CARTRIDGE) + 0xFFFF0000, // LDR Rx, [PC, #xxx] + 0xFFF00000, // LDRH Rx, [Rx] + 0xFEF0FFFF, // TST Rx, #0x10 + 0xFF000000, // BEQ xxxx + // OS_EnableIrqMask(OS_IE_CARTRIDGE) + 0xFFFF0FFF, // MOV Rx, #0x2000 + 0xFF000000, // BL EnableIrqMask + // OS_RestoreInterrupts(prepIntrMode) + 0xFFFF0000, // MOV Rx, Rx + 0xFF000000, // BL OS_RestoreInterrupts + 0, +}; + +// 対象コードリスト +static const u32 * const target_code_list[] = { + target_code_400, // 0x02004ee8 + target_code_400, // 0x030028a0 + target_code_400, // 0x03017530 + target_code_400, // 0x03027531 + target_code_400, // 0x04007530 + target_code_400, // 0x04017531 + target_code_400, // 0x04027530 +}; + +static const u32 * const target_mask_list[] = { + target_mask_400, // 0x02004ee8 + target_mask_400, // 0x030028a0 + target_mask_400, // 0x03017530 + target_mask_400, // 0x03027531 + target_mask_400, // 0x04007530 + target_mask_400, // 0x04017531 + target_mask_400, // 0x04027530 +}; + +static const u32 * const target_idx_list[] = { + &target_idx_400, // 0x02004ee8 + &target_idx_400, // 0x030028a0 + &target_idx_400, // 0x03017530 + &target_idx_400, // 0x03027531 + &target_idx_400, // 0x04007530 + &target_idx_400, // 0x04017531 + &target_idx_400, // 0x04027530 +}; + + + + +/*---------------------------------------------------------------------------* + Name: main + + Description: patch NitroSDK ROM for tmp jump + + Arguments: file name of binary + + Returns: 0 if success + *---------------------------------------------------------------------------*/ +int main(int argc, char *argv[]) +{ + int i; + int fsize; + char *buffer; + char *fname; + char outputname[FILENAME_MAX]; + u32 version; + + if (argc > 1) + { + for (i = 1; i < argc; i++) + { + // Read entire file image + fname = argv[i]; + + fsize = ReadFile(fname, &buffer); + if (fsize < 0) + { + return 1; + } + + // Search SDK version + version = SearchSdkVersion(buffer); + DEBUG_PRINT(stdout, "SDK version %08X\n", (int)version); + + // Patch ARM7 component + if ( PatchForPMSleep(buffer, version) ) + { + return 1; + } + + // Output patched binaries + sprintf(outputname, "%s%s", fname, SURFFIX_TMPJUMP); + if (fsize != WriteFile(outputname, buffer, fsize)) + { + return 1; + } + + free(buffer); + } + } + else + { + fprintf(stderr, + "Usage: patchtmpjump [ROM IMAGE...]\n\n" + "Patch NITRO ROM for tmp jump\n"); + } + return 0; +} + +/*---------------------------------------------------------------------------* + * search SDK version + *---------------------------------------------------------------------------*/ +u32 SearchSdkVersion( void *buffer ) +{ + ROM_Header* h = buffer; + const u32 *magic = sdk_ver_magic_code; + + int offset = h->main_entry_address - h->main_ram_address; + int size = h->main_size - offset; + u32 *cur = (void*)((u8*)buffer + h->main_rom_offset + offset); + u32 *end = (void*)((u8*)cur + size); + + while( cur < end ) + { + if( cur[0] == magic[0] && cur[1] == magic[1] ) + { + return cur[-1]; + } + cur++; + } + return 0; +} + +/*---------------------------------------------------------------------------* + * patch PMi_DoSleep + *---------------------------------------------------------------------------*/ +s32 PatchForPMSleep( void *buffer, u32 version ) +{ + ROM_Header* h = buffer; + int size = h->sub_size; + u32 *cur = (void*)((u8*)buffer + h->sub_rom_offset); + u32 *end = (void*)((u8*)cur + size); + u32 count = 0; + int i; + + for ( i=0; i