diff --git a/arm9/include/dsCard.h b/arm9/include/dsCard.h index aef5f63..fe3c689 100644 --- a/arm9/include/dsCard.h +++ b/arm9/include/dsCard.h @@ -38,18 +38,19 @@ typedef bool BOOL ; //--------------------------------------------------- //DS 卡 基本操作 //Arm9 方面基本操作容许ARM7访问slot1 - void Enable_Arm7DS(void); + // void Enable_Arm7DS(void); //Arm9 方面基本操作容许ARM9访问slot1 - void Enable_Arm9DS(void); + // void Enable_Arm9DS(void); //下面是访问震动卡的函数 #define FlashBase 0x08000000 -#define PSRAMBase_S98 0x08800000 +#define PSRAMBase_S98 0x08800000 // EZ Flash Omega PSRAM location while in Kernal mode. (only writable in Kernal mode) #define FlashBase_S98 0x09000000 -#define _Ez5PsRAM 0x08000000 -#define SAVE_sram_base 0x0E000000 +#define SRAM_ADDR 0x0A000000 +#define SRAM_ADDR_OMEGA 0x0E000000 +#define RTC_ENABLE ((vu16*)0x080000C8) void OpenNorWrite(); void CloseNorWrite(); void SetRompage(u16 page); @@ -58,9 +59,13 @@ typedef bool BOOL ; void Set_AUTO_save(u16 mode); u16 Read_S71NOR_ID(); // For Reading EZFlash Omega ID u16 Read_S98NOR_ID(); // For Reading EZFlash Omega ID - void SetPSRampage(u16 page); // EZFlash Omega uses this instead of regular SetRamPage + void SetPSRampage(u16 page); // EZFlash Omega uses this to change what 8MB of 32MB PSRAM is accessible at 0x08800000 void Set_RTC_status(u16 status); // EZFlash Omega RTC thingy u16 Read_SET_info(u32 offset); + void rtc_toggle(bool enable); + void SetbufferControl(u16 control); + void Omega_Bank_Switching(u8 bank); + void Omega_InitFatBuffer(BYTE saveMODE); void OpenRamWrite(); void CloseRamWrite(); void SetSerialMode(); @@ -68,13 +73,12 @@ typedef bool BOOL ; void chip_reset(); void Block_EraseIntel(u32 blockAdd); void Block_Erase(u32 blockAdd); - // void ReadNorFlash(u8* pBuf,u32 address,u16 len); + // void ReadNorFlash(u8* pBuf,u32 address,u16 len); // Not used anywhere right now. Disabled out for now. void WriteNorFlashINTEL(u32 address,u8 *buffer,u32 size); void WriteNorFlash(u32 address,u8 *buffer,u32 size); void WriteSram(uint32 address, u8* data , uint32 size ); void ReadSram(uint32 address, u8* data , uint32 size ); void SetShake(u16 data); - void Omega_Bank_Switching(u8 bank); #ifdef __cplusplus } #endif diff --git a/arm9/include/dsCard.itcm.cpp b/arm9/include/dsCard.itcm.cpp index 942cb23..2fd0609 100644 --- a/arm9/include/dsCard.itcm.cpp +++ b/arm9/include/dsCard.itcm.cpp @@ -10,7 +10,7 @@ #include "dscard.h" #include "string.h" #include "io_sc_common.h" - +#include "tonccpy.h" #ifdef __cplusplus extern "C" { @@ -133,6 +133,43 @@ void Set_RTC_status(u16 status) { *(u16*)0x9fc0000 = 0x1500; } +void rtc_toggle(bool enable) { + if (enable) { *RTC_ENABLE = 1; } else { *RTC_ENABLE = 0; } +} + +void Omega_Bank_Switching(u8 bank) { + *((vu8*)(SRAM_ADDR_OMEGA+0x5555)) = 0xAA; + *((vu8*)(SRAM_ADDR_OMEGA+0x2AAA)) = 0x55; + *((vu8*)(SRAM_ADDR_OMEGA+0x5555)) = 0xB0; + *((vu8*)SRAM_ADDR_OMEGA) = bank; +} + +void SetbufferControl(u16 control) { + *(u16*)0x9fe0000 = 0xd200; + *(u16*)0x8000000 = 0x1500; + *(u16*)0x8020000 = 0xd200; + *(u16*)0x8040000 = 0x1500; + *(u16*)0x9420000 = control; //A1 + *(u16*)0x9fc0000 = 0x1500; +} + +static u32 FAT_table_buffer[0x400/4]; + +void Omega_InitFatBuffer(BYTE saveMODE) { + toncset((void*)FAT_table_buffer, 0, (0x400/4)); + FAT_table_buffer[2] = 0xFFFFFFFF; + // FAT_table_buffer[0x1F0/4] = 0; //size + FAT_table_buffer[0x1F4/4] = 0x2; // 0x1 == rom copy to psram // 0x2 == copy mode + // FAT_table_buffer[0x1F8/4] = 0; // secort of cluster + // FAT_table_buffer[0x1FC/4] = (0x31<<24) | 0x20000; // save mode and save file size + FAT_table_buffer[0x1FC/4] = (saveMODE<<24) | 0x10000; // save mode and save file size + SetbufferControl(1); + // tonccpy((void*)0x9E00000, FAT_table_buffer, 0x400); + // dmaCopy(FAT_table_buffer, (void*)0x9E00000, 0x400); + tonccpy((void*)0x9E00000, FAT_table_buffer, 0x400); + SetbufferControl(3); + SetbufferControl(0); +} void SetRampage(u16 page) { *(vu16*)0x9fe0000 = 0xd200; @@ -188,15 +225,14 @@ u32 ReadNorFlashID() { fwrite((void*)(FlashBase+0x2002), 2, 1, testFile); fclose(testFile); }*/ - - + if ((id1 != 0x227E) || (id2 != 0x227E)) { if (checkForSuperCard()) { ID = 0x227E2202; return 0x227E0000; } // Check For EZ Flash Omega - SetRompage(0x8002); + SetRompage(0x8000); id1 = Read_S98NOR_ID(); if ((id1 == 0x223D)) { ID = 0x227EEA00; @@ -507,7 +543,7 @@ void WriteNorFlashINTEL(u32 address,u8 *buffer,u32 size) { v1 = *((vu16*)(FlashBase+mapaddress+(loopwrite>>1))); v2 = *((vu16*)(FlashBase+mapaddress+(loopwrite>>1)+0x2000)); if((v1==0x90) || (v2==0x90)) { // error response, hopefully this never actually happens? - WriteSram(0xA000000,(u8 *)buf,0x8000); + WriteSram(SRAM_ADDR,(u8 *)buf,0x8000); while(1); break; } @@ -571,21 +607,14 @@ void WriteNorFlash(u32 address,u8 *buffer,u32 size) { } } -void Omega_Bank_Switching(u8 bank) { - *((vu8 *)(SAVE_sram_base+0x5555)) = 0xAA ; - *((vu8 *)(SAVE_sram_base+0x2AAA)) = 0x55 ; - *((vu8 *)(SAVE_sram_base+0x5555)) = 0xB0 ; - *((vu8 *)(SAVE_sram_base+0x0000)) = bank ; -} - -void WriteSram(uint32 address, u8* data , uint32 size ) { - uint32 i ; - for(i=0;i +#include // NULL +//#include // memcmp +//#include + +// (memcmp is slower) +//#define memcmp __builtin_memcmp + +//#define TABLE_SIZE (UCHAR_MAX + 1) // 256 + +/* +* Look for @find and return the position of it. +* Brute Force algorithm +*/ +u32* memsearch32(const u32* start, u32 dataSize, const u32* find, u32 findSize, bool forward) { + u32 dataLen = dataSize/sizeof(u32); + u32 findLen = findSize/sizeof(u32); + + const u32* end = forward ? (start + dataLen) : (start - dataLen); + for (u32* addr = (u32*)start; addr != end; forward ? ++addr : --addr) { + bool found = true; + for (u32 j = 0; j < findLen; ++j) { + if (addr[j] != find[j]) { + found = false; + break; + } + } + if (found) { + return (u32*)addr; + } + } + return NULL; +} +u16* memsearch16(const u16* start, u32 dataSize, const u16* find, u32 findSize, bool forward) { + u32 dataLen = dataSize/sizeof(u16); + u32 findLen = findSize/sizeof(u16); + + const u16* end = forward ? (start + dataLen) : (start - dataLen); + for (u16* addr = (u16*)start; addr != end; forward ? ++addr : --addr) { + bool found = true; + for (u32 j = 0; j < findLen; ++j) { + if (addr[j] != find[j]) { + found = false; + break; + } + } + if (found) { + return (u16*)addr; + } + } + return NULL; +} +u8* memsearch8(const u8* start, u32 dataSize, const u8* find, u32 findSize, bool forward) { + u32 dataLen = dataSize/sizeof(u8); + u32 findLen = findSize/sizeof(u8); + + const u8* end = forward ? (start + dataLen) : (start - dataLen); + for (u8* addr = (u8*)start; addr != end; forward ? ++addr : --addr) { + bool found = true; + for (u32 j = 0; j < findLen; ++j) { + if (addr[j] != find[j]) { + found = false; + break; + } + } + if (found) { + return (u8*)addr; + } + } + return NULL; +} + diff --git a/arm9/include/find.h b/arm9/include/find.h new file mode 100644 index 0000000..da6ba7a --- /dev/null +++ b/arm9/include/find.h @@ -0,0 +1,21 @@ +#ifndef FIND_H +#define FIND_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// COMMON +//u8* memsearch(const u8* start, u32 dataSize, const u8* find, u32 findSize); +extern u32* memsearch32(const u32* start, u32 dataSize, const u32* find, u32 findSize, bool forward); +extern u16* memsearch16(const u16* start, u32 dataSize, const u16* find, u32 findSize, bool forward); +extern u8* memsearch8(const u8* start, u32 dataSize, const u8* find, u32 findSize, bool forward); + +#ifdef __cplusplus +} +#endif + +#endif // FIND_H + diff --git a/arm9/include/io_sc_common.c b/arm9/include/io_sc_common.c index b453d4f..d448af3 100644 --- a/arm9/include/io_sc_common.c +++ b/arm9/include/io_sc_common.c @@ -29,6 +29,10 @@ #include "io_sc_common.h" +#ifndef NULL + #define NULL 0 +#endif + /*----------------------------------------------------------------- _SC_changeMode (was SC_Unlock) Added by MightyMax @@ -52,3 +56,58 @@ void _SC_changeMode16(u16 mode) { *unlockAddress = mode; } +void twoByteCpy(u16 *dst, const u16 *src, u32 size) { + if (size == 0 || dst == NULL || src == NULL)return; + + u32 count; + u16 *dst16; // hword destination + u8 *src8; // byte source + + // Ideal case: copy by 4x words. Leaves tail for later. + if (((u32)src|(u32)dst) %4 == 0 && size >= 4) { + u32 *src32= (u32*)src, *dst32= (u32*)dst; + + count = size/4; + u32 tmp = count&3; + count /= 4; + + // Duff's Device, good friend! + switch(tmp) { + do { *dst32++ = *src32++; + case 3: *dst32++ = *src32++; + case 2: *dst32++ = *src32++; + case 1: *dst32++ = *src32++; + case 0: ; } while (count--); + } + + // Check for tail + size &= 3; + if (size == 0)return; + + src8 = (u8*)src32; + dst16 = (u16*)dst32; + } else { + // Unaligned + + u32 dstOfs = (u32)dst&1; + src8 = (u8*)src; + dst16 = (u16*)(dst-dstOfs); + + // Head: 1 byte. + if (dstOfs != 0) { + *dst16 = (*dst16 & 0xFF) | *src8++<<8; + dst16++; + if (--size == 0)return; + } + } + + // Unaligned main: copy by 2x byte. + count = size/2; + while (count--) { + *dst16++ = src8[0] | src8[1]<<8; + src8 += 2; + } + + // Tail: 1 byte. + if (size & 1)*dst16 = (*dst16 &~ 0xFF) | *src8; +} \ No newline at end of file diff --git a/arm9/include/io_sc_common.h b/arm9/include/io_sc_common.h index 534e979..c8e85cf 100644 --- a/arm9/include/io_sc_common.h +++ b/arm9/include/io_sc_common.h @@ -48,6 +48,7 @@ extern "C" { extern void _SC_changeMode(u8 mode); extern void _SC_changeMode16(u16 mode); +extern void twoByteCpy(u16 *dst, const u16 *src, u32 size); #ifdef __cplusplus } diff --git a/arm9/include/sc_patches.c b/arm9/include/sc_patches.c new file mode 100644 index 0000000..724ae11 --- /dev/null +++ b/arm9/include/sc_patches.c @@ -0,0 +1,348 @@ +#include + +#include "io_sc_common.h" + +u32 prefetchPatch[8] = { + 0xE59F000C, // LDR R0, =0x4000204 + 0xE59F100C, // LDR R1, =0x4000 + 0xE4A01000, // STRT R1, [R0] + 0xE59F0008, // LDR R0, =0x80000C0 (this changes, depending on the ROM) + 0xE1A0F000, // MOV PC, R0 + 0x04000204, + 0x00004000, + 0x080000C0 +}; + +static const u8 sDbzLoGUPatch1[0x24] = { + 0x0A, 0x1C, 0x40, 0x0B, 0xE0, 0x21, 0x09, 0x05, 0x41, 0x18, 0x07, 0x31, 0x00, 0x23, 0x08, 0x78, + 0x10, 0x70, 0x01, 0x33, 0x01, 0x32, 0x01, 0x39, 0x07, 0x2B, 0xF8, 0xD9, 0x00, 0x20, 0x70, 0xBC, + 0x02, 0xBC, 0x08, 0x47 +}; + +static const u8 sDbzLoGUPatch2[0x28] = { + 0x70, 0xB5, 0x00, 0x04, 0x0A, 0x1C, 0x40, 0x0B, 0xE0, 0x21, 0x09, 0x05, 0x41, 0x18, 0x07, 0x31, + 0x00, 0x23, 0x10, 0x78, 0x08, 0x70, 0x01, 0x33, 0x01, 0x32, 0x01, 0x39, 0x07, 0x2B, 0xF8, 0xD9, + 0x00, 0x20, 0x70, 0xBC, 0x02, 0xBC, 0x08, 0x47 +}; + +static const u8 wwTwistedPatch[0xF0] = { + 0x1F, 0x24, 0x1F, 0xB4, 0x33, 0x48, 0x01, 0x21, 0x01, 0x60, 0x33, 0x48, 0x01, 0x21, 0x01, 0x60, + 0x32, 0x49, 0x0A, 0x68, 0x10, 0x23, 0x1A, 0x40, 0x1E, 0xD1, 0x30, 0x49, 0x0A, 0x68, 0x02, 0x23, + 0x1A, 0x40, 0x0D, 0xD0, 0x2E, 0x48, 0x01, 0x68, 0x01, 0x22, 0x91, 0x42, 0x02, 0xDB, 0x09, 0x19, + 0x01, 0x60, 0x38, 0xE0, 0x2A, 0x48, 0x01, 0x22, 0x02, 0x60, 0x12, 0x19, 0x02, 0x60, 0x32, 0xE0, + 0x27, 0x48, 0x01, 0x68, 0x01, 0x22, 0x91, 0x42, 0x00, 0xDB, 0x01, 0xE0, 0x02, 0x60, 0x11, 0x1C, + 0x24, 0x4B, 0xC9, 0x18, 0x01, 0x60, 0x26, 0xE0, 0x20, 0x49, 0x0A, 0x68, 0x20, 0x23, 0x1A, 0x40, + 0x1E, 0xD1, 0x1E, 0x49, 0x0A, 0x68, 0x02, 0x23, 0x1A, 0x40, 0x0D, 0xD0, 0x1C, 0x48, 0x01, 0x68, + 0x1D, 0x4A, 0x91, 0x42, 0x02, 0xDC, 0x09, 0x1B, 0x01, 0x60, 0x14, 0xE0, 0x18, 0x48, 0x1A, 0x4A, + 0x02, 0x60, 0x12, 0x1B, 0x02, 0x60, 0x0E, 0xE0, 0x15, 0x48, 0x01, 0x68, 0x16, 0x4A, 0x91, 0x42, + 0x00, 0xDC, 0x01, 0xE0, 0x02, 0x60, 0x11, 0x1C, 0x12, 0x4B, 0xC9, 0x1A, 0x01, 0x60, 0x02, 0xE0, + 0x0F, 0x48, 0x01, 0x21, 0x01, 0x60, 0x1F, 0xBC, 0x0C, 0x48, 0x00, 0x88, 0x0F, 0x4A, 0x10, 0x47, + 0x00, 0x7F, 0x00, 0x03, 0xA0, 0x7F, 0x00, 0x03, 0x30, 0x01, 0x00, 0x04, 0x4B, 0x13, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x03, 0x98, 0x0F, 0x00, 0x03, 0x30, 0x01, 0x00, 0x04, + 0x30, 0x10, 0x00, 0x03, 0x20, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x4B, 0x13, 0x00, 0x08 +}; + +static const u8 yoshiTopsyTurvyPatch[0x18C] = { + 0x0C, 0x20, 0x9F, 0xE5, 0x80, 0x30, 0xA0, 0xE3, 0x00, 0x30, 0xE2, 0xE4, 0x04, 0x30, 0x9F, 0xE5, + 0x13, 0xFF, 0x2F, 0xE1, 0xE0, 0x7F, 0x00, 0x03, 0x69, 0x51, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xB5, 0x01, 0x4F, 0x00, 0x00, 0x09, 0xE0, 0xE0, 0x7F, 0x00, 0x03, 0x02, 0x49, 0x09, 0x88, + 0x01, 0x23, 0x08, 0x40, 0x70, 0x47, 0x00, 0x00, 0x30, 0x01, 0x00, 0x04, 0x3D, 0x78, 0x7F, 0x1C, + 0x80, 0x26, 0x35, 0x42, 0x24, 0xD0, 0x33, 0x48, 0x00, 0x21, 0x00, 0x88, 0x88, 0x42, 0x04, 0xD1, + 0x31, 0x49, 0x20, 0x20, 0x00, 0x02, 0x02, 0x30, 0x08, 0x80, 0x30, 0x48, 0x03, 0x21, 0x00, 0x88, + 0x88, 0x42, 0x04, 0xD1, 0x2E, 0x49, 0x20, 0x20, 0x00, 0x02, 0x02, 0x30, 0x08, 0x80, 0x02, 0x20, + 0x00, 0x02, 0x00, 0x30, 0xFF, 0xF7, 0xDA, 0xFF, 0x02, 0xD1, 0x2A, 0x49, 0x00, 0x20, 0x08, 0x80, + 0x01, 0x20, 0xFF, 0x30, 0xFF, 0xF7, 0xD2, 0xFF, 0x02, 0xD1, 0x27, 0x49, 0x03, 0x20, 0x08, 0x80, + 0x76, 0x08, 0x35, 0x42, 0x02, 0xD0, 0x25, 0x49, 0x63, 0x20, 0x08, 0x70, 0x76, 0x08, 0x35, 0x42, + 0x04, 0xD0, 0x23, 0x49, 0x27, 0x20, 0x00, 0x02, 0x0F, 0x30, 0x08, 0x80, 0x76, 0x08, 0x35, 0x42, + 0x02, 0xD0, 0x20, 0x49, 0x03, 0x20, 0x08, 0x80, 0x76, 0x08, 0x35, 0x42, 0x22, 0xD0, 0x1E, 0x49, + 0xAA, 0x20, 0x00, 0x02, 0xAA, 0x30, 0x08, 0x80, 0x1C, 0x49, 0xAA, 0x20, 0x00, 0x02, 0xAA, 0x30, + 0x08, 0x80, 0x1B, 0x49, 0xAA, 0x20, 0x00, 0x02, 0xAA, 0x30, 0x08, 0x80, 0x19, 0x49, 0xAA, 0x20, + 0x00, 0x02, 0xAA, 0x30, 0x08, 0x80, 0x18, 0x49, 0xAA, 0x20, 0x00, 0x02, 0xAA, 0x30, 0x08, 0x80, + 0x16, 0x49, 0xAA, 0x20, 0x00, 0x02, 0xAA, 0x30, 0x08, 0x80, 0x15, 0x49, 0xAA, 0x20, 0x00, 0x02, + 0xAA, 0x30, 0x08, 0x80, 0x76, 0x08, 0x35, 0x42, 0x02, 0xD0, 0x12, 0x49, 0x0A, 0x20, 0x08, 0x80, + 0x00, 0x00, 0x21, 0xE0, 0xE0, 0x1D, 0x00, 0x03, 0xE0, 0x1D, 0x00, 0x03, 0xE0, 0x1D, 0x00, 0x03, + 0xE0, 0x1D, 0x00, 0x03, 0xE0, 0x1D, 0x00, 0x03, 0xE0, 0x1D, 0x00, 0x03, 0xD8, 0x03, 0x00, 0x03, + 0xF8, 0x03, 0x00, 0x03, 0x00, 0x05, 0x00, 0x03, 0xDA, 0x03, 0x00, 0x03, 0xDC, 0x03, 0x00, 0x03, + 0xDE, 0x03, 0x00, 0x03, 0xE0, 0x03, 0x00, 0x03, 0xE2, 0x03, 0x00, 0x03, 0xE4, 0x03, 0x00, 0x03, + 0xE6, 0x03, 0x00, 0x03, 0x48, 0x29, 0x00, 0x02, 0xFF, 0xBD, 0x00, 0x00, 0x00, 0xB5, 0x03, 0x48, + 0xFE, 0x46, 0x00, 0x47, 0x01, 0xBC, 0x86, 0x46, 0x01, 0xBC, 0x01, 0xE0, 0x01, 0x9C, 0x7B, 0x08, + 0x02, 0x48, 0x00, 0x88, 0xC0, 0x43, 0x80, 0x05, 0x81, 0x0D, 0x01, 0xE0, 0x30, 0x01, 0x00, 0x04, + 0x03, 0xB4, 0x01, 0x48, 0x01, 0x90, 0x01, 0xBD, 0x18, 0x1A, 0x00, 0x08 +}; + +void patchGeneralWhiteScreen(u32 romSize) { + u32 entryPoint = *(u32*)0x08000000; + entryPoint -= 0xEA000000; + entryPoint += 2; + prefetchPatch[7] = 0x08000000+(entryPoint*4); + + u32 patchOffset = 0x01FFFFDC; + + vu32 *patchAddr = (vu32*)(0x08000000+patchOffset); + for(int i=0;i<8;i++)patchAddr[i] = prefetchPatch[i]; + + + u32 branchCode = 0xEA000000+(patchOffset/sizeof(u32))-2; + *(vu32*)0x08000000 = branchCode; + + u32 searchRange = 0x08000000+romSize; + if (romSize > 0x01FFFFDC) searchRange = 0x09FFFFDC; + + // General fix for white screen crash + // Patch out wait states + for (u32 addr = 0x080000C0; addr < searchRange; addr+=4) { + if (*(u32*)addr == 0x04000204 && + (*(u8*)(addr-1) == 0x00 || *(u8*)(addr-1) == 0x03 || *(u8*)(addr-1) == 0x04 || *(u8*)(addr+7) == 0x04 + || *(u8*)(addr-1) == 0x08 || *(u8*)(addr-1) == 0x09 + || *(u8*)(addr-1) == 0x47 || *(u8*)(addr-1) == 0x81 || *(u8*)(addr-1) == 0x85 + || *(u8*)(addr-1) == 0xE0 || *(u8*)(addr-1) == 0xE7 || *(u16*)(addr-2) == 0xFFFE)) + { + *(vu32*)addr = 0; + } + } + + // Also check at 0x410 + if (*(u32*)0x08000410 == 0x04000204)*(vu32*)0x08000410 = 0; +} + +bool patchSpecificGame() { + u32 nop = 0xE1A00000; + + u32 gameCode = *(u32*)(0x080000AC); + + if (gameCode == 0x50584C42) { + //Astreix & Obelix XXL (Europe) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0x50118) == 0x4014)*(u16*)(0x08000000 + 0x50118) = 0x4000; + } else if (gameCode == 0x454D4441) { + //Doom (USA) + //Fix black screen crash + if (*(u16*)(0x08000000 + 0x51C) == 0x45B6)*(u16*)(0x08000000 + 0x51C) = 0x4002; + } else if (gameCode == 0x45443941 || gameCode == 0x50443941) { + //Doom II (USA/Europe) + //Fix black screen crash + if (*(u16*)(0x08000000 + 0x2856) == 0x5281)*(u16*)(0x08000000 + 0x2856) = 0x46C0; + } else if (gameCode == 0x45474C41) { + //Dragon Ball Z - The Legacy of Goku (USA) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0x96E8) == 0x80A8) *(u16*)(0x08000000 + 0x96E8) = 0x46C0; + + //Fix "game cannot be played on hardware found" error + if (*(u16*)(0x08000000 + 0x356) == 0x7002)*(u16*)(0x08000000 + 0x356) = 0; + if (*(u16*)(0x08000000 + 0x35E) == 0x7043)*(u16*)(0x08000000 + 0x35E) = 0; + if (*(u16*)(0x08000000 + 0x37E) == 0x7001)*(u16*)(0x08000000 + 0x37E) = 0; + if (*(u16*)(0x08000000 + 0x382) == 0x7041)*(u16*)(0x08000000 + 0x382) = 0; + + if (*(u16*)(0x08000000 + 0xE27E) == 0xB0A2) { + *(u16*)(0x08000000 + 0xE27E) = 0x400; + for (int i = 0; i < (int)sizeof(sDbzLoGUPatch1); i += 2)*(u16*)(0x08000000 + 0xE280 + i) = *(u16*)&sDbzLoGUPatch1[i]; + for (int i = 0; i < (int)sizeof(sDbzLoGUPatch2); i += 2)*(u16*)(0x08000000 + 0xE32C + i) = *(u16*)&sDbzLoGUPatch2[i]; + } + } else if (gameCode == 0x50474C41) { + //Dragon Ball Z - The Legacy of Goku (Europe) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0x9948) == 0x80B0)*(u16*)(0x08000000 + 0x9948) = 0x46C0; + + //Fix "game cannot be played on hardware found" error + if (*(u16*)(0x08000000 + 0x33C) == 0x7119)*(u16*)(0x08000000 + 0x33C) = 0x46C0; + if (*(u16*)(0x08000000 + 0x340) == 0x7159)*(u16*)(0x08000000 + 0x340) = 0x46C0; + if (*(u16*)(0x08000000 + 0x356) == 0x705A)*(u16*)(0x08000000 + 0x356) = 0x46C0; + if (*(u16*)(0x08000000 + 0x35A) == 0x7002)*(u16*)(0x08000000 + 0x35A) = 0x46C0; + if (*(u16*)(0x08000000 + 0x35E) == 0x7042)*(u16*)(0x08000000 + 0x35E) = 0x46C0; + if (*(u16*)(0x08000000 + 0x384) == 0x7001)*(u16*)(0x08000000 + 0x384) = 0x46C0; + if (*(u16*)(0x08000000 + 0x388) == 0x7041)*(u16*)(0x08000000 + 0x388) = 0x46C0; + if (*(u16*)(0x08000000 + 0x494C) == 0x7002)*(u16*)(0x08000000 + 0x494C) = 0x46C0; + if (*(u16*)(0x08000000 + 0x4950) == 0x7042)*(u16*)(0x08000000 + 0x4950) = 0x46C0; + if (*(u16*)(0x08000000 + 0x4978) == 0x7001)*(u16*)(0x08000000 + 0x4978) = 0x46C0; + if (*(u16*)(0x08000000 + 0x497C) == 0x7041)*(u16*)(0x08000000 + 0x497C) = 0x46C0; + if (*(u16*)(0x08000000 + 0x988E) == 0x7028)*(u16*)(0x08000000 + 0x988E) = 0x46C0; + if (*(u16*)(0x08000000 + 0x9992) == 0x7068)*(u16*)(0x08000000 + 0x9992) = 0x46C0; + } else if (gameCode == 0x45464C41) { + //Dragon Ball Z - The Legacy of Goku II (USA) + *((u32*)0x080000E0) = nop; +//tonccpy((u16*)0x080000E0, &nop, sizeof(u32)); // Fix white screen crash + + //Fix "game will not run on the hardware found" error + if (*(u16*)(0x08000000 + 0x3B8E9E) == 0x1102)*(u16*)(0x08000000 + 0x3B8E9E) = 0x1001; + if (*(u16*)(0x08000000 + 0x3B8EAE) == 0x0003)*(u16*)(0x08000000 + 0x3B8EAE) = 0; + } else if (gameCode == 0x4A464C41) { + //Dragon Ball Z - The Legacy of Goku II International (Japan) + *((u32*)0x080000E0) = nop; +//tonccpy((u16*)0x080000E0, &nop, sizeof(u32)); // Fix white screen crash + + //Fix "game will not run on the hardware found" error + if (*(u16*)(0x08000000 + 0x3FC8F6) == 0x1102)*(u16*)(0x08000000 + 0x3FC8F6) = 0x1001; + if (*(u16*)(0x08000000 + 0x3FC906) == 0x0003)*(u16*)(0x08000000 + 0x3FC906) = 0; + } else if (gameCode == 0x50464C41) { + //Dragon Ball Z - The Legacy of Goku II (Europe) + *((u32*)0x080000E0) = nop; +//tonccpy((u16*)0x080000E0, &nop, sizeof(u32)); // Fix white screen crash + + //Fix "game will not run on the hardware found" error + if (*(u16*)(0x08000000 + 0x6F42B2) == 0x1102)*(u16*)(0x08000000 + 0x6F42B2) = 0x1001; + if (*(u16*)(0x08000000 + 0x6F42C2) == 0x0003)*(u16*)(0x08000000 + 0x6F42C2) = 0; + } else if (gameCode == 0x45464C42) { + //2 Games in 1 - Dragon Ball Z - The Legacy of Goku I & II (USA) + *((u32*)0x080000E0) = nop; +//tonccpy((u16*)0x080000E0, &nop, sizeof(u32)); // Fix white screen crash + + if (*(u16*)(0x08000000 + 0x49840) == 0x80A8)*(u16*)(0x08000000 + 0x49840) = 0x46C0; + + // tonccpy((u16*)0x088000E0, &nop, sizeof(u32)); + *((u32*)0x080000E0) = nop; + + //LoG1: Fix "game cannot be played on hardware found" error + if (*(u16*)(0x08000000 + 0x40356) == 0x7002)*(u16*)(0x08000000 + 0x40356) = 0; + if (*(u16*)(0x08000000 + 0x4035E) == 0x7043)*(u16*)(0x08000000 + 0x4035E) = 0; + if (*(u16*)(0x08000000 + 0x4037E) == 0x7001)*(u16*)(0x08000000 + 0x4037E) = 0; + if (*(u16*)(0x08000000 + 0x40382) == 0x7041)*(u16*)(0x08000000 + 0x40382) = 0; + + //Do we need this? + /*if (*(u16*)(0x08000000 + 0x4E316) == 0xB0A2) { + *(u16*)(0x08000000 + 0x4E316) = 0x400; + for (int i = 0; i < sizeof(sDbzLoGUPatch1); i += 2)*(u16*)(0x08000000 + 0x4E318 + i) = *(u16*)&sDbzLoGUPatch1[i]; + for (int i = 0; i < sizeof(sDbzLoGUPatch2); i += 2)*(u16*)(0x08000000 + 0x????? + i) = *(u16*)&sDbzLoGUPatch2[i]; + }*/ + + //LoG2: Fix "game will not run on the hardware found" error + if (*(u16*)(0x08000000 + 0xBB9016) == 0x1102)*(u16*)(0x08000000 + 0xBB9016) = 0x1001; + if (*(u16*)(0x08000000 + 0xBB9026) == 0x0003)*(u16*)(0x08000000 + 0xBB9026) = 0; + } else if (gameCode == 0x45424442) { + //Dragon Ball Z - Taiketsu (USA) + //Fix "game cannot be played on this hardware" error + if (*(u16*)(0x08000000 + 0x2BD54) == 0x7818)*(u16*)(0x08000000 + 0x2BD54) = 0x2000; + if (*(u16*)(0x08000000 + 0x2BD60) == 0x7810)*(u16*)(0x08000000 + 0x2BD60) = 0x2000; + if (*(u16*)(0x08000000 + 0x2BD80) == 0x703A)*(u16*)(0x08000000 + 0x2BD80) = 0x1C00; + if (*(u16*)(0x08000000 + 0x2BD82) == 0x7839)*(u16*)(0x08000000 + 0x2BD82) = 0x2100; + if (*(u16*)(0x08000000 + 0x2BD8C) == 0x7030)*(u16*)(0x08000000 + 0x2BD8C) = 0x1C00; + if (*(u16*)(0x08000000 + 0x2BD8E) == 0x7830)*(u16*)(0x08000000 + 0x2BD8E) = 0x2000; + if (*(u16*)(0x08000000 + 0x2BDAC) == 0x7008)*(u16*)(0x08000000 + 0x2BDAC) = 0x1C00; + if (*(u16*)(0x08000000 + 0x2BDB2) == 0x7008)*(u16*)(0x08000000 + 0x2BDB2) = 0x1C00; + } else if (gameCode == 0x50424442) { + //Dragon Ball Z - Taiketsu (Europe) + //Fix "game cannot be played on this hardware" error + if (*(u16*)(0x08000000 + 0x3FE08) == 0x7818)*(u16*)(0x08000000 + 0x3FE08) = 0x2000; + if (*(u16*)(0x08000000 + 0x3FE14) == 0x7810)*(u16*)(0x08000000 + 0x3FE14) = 0x2000; + if (*(u16*)(0x08000000 + 0x3FE34) == 0x703A)*(u16*)(0x08000000 + 0x3FE34) = 0x1C00; + if (*(u16*)(0x08000000 + 0x3FE36) == 0x7839)*(u16*)(0x08000000 + 0x3FE36) = 0x2100; + if (*(u16*)(0x08000000 + 0x3FE40) == 0x7030)*(u16*)(0x08000000 + 0x3FE40) = 0x1C00; + if (*(u16*)(0x08000000 + 0x3FE42) == 0x7830)*(u16*)(0x08000000 + 0x3FE42) = 0x2000; + if (*(u16*)(0x08000000 + 0x3FE58) == 0x7008)*(u16*)(0x08000000 + 0x3FE58) = 0x1C00; + if (*(u16*)(0x08000000 + 0x3FE66) == 0x7008)*(u16*)(0x08000000 + 0x3FE66) = 0x1C00; + } else if (gameCode == 0x45334742) { + //Dragon Ball Z - Buu's Fury (USA) + *((u32*)0x080000E0) = nop; + //tonccpy((u16*)0x080000E0, &nop, sizeof(u32)); // Fix white screen crash + + //Fix "game will not run on this hardware" error + if (*(u16*)(0x08000000 + 0x8B66) == 0x7032)*(u16*)(0x08000000 + 0x8B66) = 0; + if (*(u16*)(0x08000000 + 0x8B6A) == 0x7072)*(u16*)(0x08000000 + 0x8B6A) = 0; + if (*(u16*)(0x08000000 + 0x8B86) == 0x7008)*(u16*)(0x08000000 + 0x8B86) = 0; + if (*(u16*)(0x08000000 + 0x8B8C) == 0x7031)*(u16*)(0x08000000 + 0x8B8C) = 0; + if (*(u16*)(0x08000000 + 0x8B90) == 0x7071)*(u16*)(0x08000000 + 0x8B90) = 0; + } else if (gameCode == 0x45345442) { + //Dragon Ball GT - Transformation (USA) + *((u32*)0x080000E0) = nop; + //tonccpy((u16*)0x080000E0, &nop, sizeof(u32)); // Fix white screen crash + } else if (gameCode == 0x45465542) { + //2 Games in 1 - Dragon Ball Z - Buu's Fury & Dragon Ball GT - Transformation (USA) + *((u32*)0x080000E0) = nop; + //tonccpy((u16*)0x080000E0, &nop, sizeof(u32)); // Fix white screen crash + *((u32*)0x080300E0) = nop; + *((u32*)0x088000E0) = nop; + // tonccpy((u16*)0x080300E0, &nop, sizeof(u32)); + // tonccpy((u16*)0x088000E0, &nop, sizeof(u32)); + + //DBZ BF: Fix "game will not run on this hardware" error + if (*(u16*)(0x08000000 + 0x38B66) == 0x7032)*(u16*)(0x08000000 + 0x38B66) = 0; + if (*(u16*)(0x08000000 + 0x38B6A) == 0x7072)*(u16*)(0x08000000 + 0x38B6A) = 0; + if (*(u16*)(0x08000000 + 0x38B86) == 0x7008)*(u16*)(0x08000000 + 0x38B86) = 0; + if (*(u16*)(0x08000000 + 0x38B8C) == 0x7031)*(u16*)(0x08000000 + 0x38B8C) = 0; + if (*(u16*)(0x08000000 + 0x38B90) == 0x7071)*(u16*)(0x08000000 + 0x38B90) = 0; + } else if (gameCode == 0x45564442) { + //Dragon Ball - Advanced Adventure (USA) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0x10C240) == 0x8008)*(u16*)(0x08000000 + 0x10C240) = 0x46C0; + } else if (gameCode == 0x50564442) { + //Dragon Ball - Advanced Adventure (Europe) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0x10CE3C) == 0x8008)*(u16*)(0x08000000 + 0x10CE3C) = 0x46C0; + } else if (gameCode == 0x4A564442) { + //Dragon Ball - Advanced Adventure (Japan) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0x10B078) == 0x8008)*(u16*)(0x08000000 + 0x10B078) = 0x46C0; + } else if (gameCode == 0x454B3842) { + //Kirby and the Amazing Mirror (USA) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0x1515A4) == 0x8008)*(u16*)(0x08000000 + 0x1515A4) = 0x46C0; + } else if (gameCode == 0x504B3842) { + //Kirby and the Amazing Mirror (Europe) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0x151EE0) == 0x8008)*(u16*)(0x08000000 + 0x151EE0) = 0x46C0; + } else if (gameCode == 0x4A4B3842) { + //Hoshi no Kirby - Kagami no Daimeikyuu (Japan) (V1.1) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0x151564) == 0x8008)*(u16*)(0x08000000 + 0x151564) = 0x46C0; + } else if (gameCode == 0x45533342) { + //Sonic Advance 3 (USA) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0xBB67C) == 0x8008)*(u16*)(0x08000000 + 0xBB67C) = 0x46C0; + } else if (gameCode == 0x50533342) { + //Sonic Advance 3 (Europe) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0xBBA04) == 0x8008)*(u16*)(0x08000000 + 0xBBA04) = 0x46C0; + } else if (gameCode == 0x4A533342) { + //Sonic Advance 3 (Japan) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0xBB9F8) == 0x8008)*(u16*)(0x08000000 + 0xBB9F8) = 0x46C0; + } else if (gameCode == 0x45593241) { + //Top Gun - Combat Zones (USA) + //Fix softlock when attempting to save (original cartridge does not have a save chip) + if (*(u16*)(0x08000000 + 0x88816) == 0x3501)*(u16*)(0x08000000 + 0x88816) = 0x3401; + + // savingAllowed = false; + return false; + } else if (gameCode == 0x45415741 || gameCode == 0x4A415741) { + //Wario Land 4/Advance (USA/Europe/Japan) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0x726) == 0x8008)*(u16*)(0x08000000 + 0x726) = 0x46C0; + } else if (gameCode == 0x43415741) { + //Wario Land Advance (iQue) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0xE92) == 0x8008)*(u16*)(0x08000000 + 0xE92) = 0x46C0; + } else if (gameCode == 0x45575A52) { + //WarioWare: Twisted! (USA) + //Patch out tilt controls + if (*(u16*)(0x08000000 + 0x1348) == 0x8800)*(u16*)(0x08000000 + 0x1348) = 0x4700; + + if (*(u16*)(0x08000000 + 0x1376) == 0x0400 && *(u16*)(0x08000000 + 0x1374) == 0x0130) { + *(u16*)(0x08000000 + 0x1376) = 0x08E9; + *(u16*)(0x08000000 + 0x1374) = 0x3C6D; + + // tonccpy((u8*)0x08E93C6C, &wwTwistedPatch, 0xF0); + twoByteCpy((u16*)0x08E93C6C,(const u16*)wwTwistedPatch,0xF0); + } + } else if (gameCode == 0x4547594B) { + //Yoshi Topsy-Turvy (USA) + //Fix white screen crash + if (*(u16*)(0x08000000 + 0x16E4) == 0x8008)*(u16*)(0x08000000 + 0x16E4) = 0x46C0; + + //Patch out tilt controls + if (*(u16*)(0x08000000 + 0x1F2) == 0x0802 && *(u16*)(0x08000000 + 0x1F0) == 0x5169) { + *(u16*)(0x08000000 + 0x1F2) = 0x087B; + *(u16*)(0x08000000 + 0x1F0) = 0x9BE0; + + // tonccpy((u8*)0x087B9BE0, &yoshiTopsyTurvyPatch, 0x18C); + twoByteCpy((u16*)0x087B9BE0,(const u16*)yoshiTopsyTurvyPatch,0x18C); + } + + if (*(u16*)(0x08000000 + 0x1A0E) == 0x4808)*(u16*)(0x08000000 + 0x1A0E) = 0xB401; + if (*(u16*)(0x08000000 + 0x1A10) == 0x8800)*(u16*)(0x08000000 + 0x1A10) = 0x4800; + if (*(u16*)(0x08000000 + 0x1A12) == 0x43C0)*(u16*)(0x08000000 + 0x1A12) = 0x4700; + if (*(u16*)(0x08000000 + 0x1A14) == 0x0580)*(u16*)(0x08000000 + 0x1A14) = 0x9D3D; + if (*(u16*)(0x08000000 + 0x1A16) == 0x0D81)*(u16*)(0x08000000 + 0x1A16) = 0x087B; + } + return true; +} + diff --git a/arm9/include/sc_patches.h b/arm9/include/sc_patches.h new file mode 100644 index 0000000..5d0c999 --- /dev/null +++ b/arm9/include/sc_patches.h @@ -0,0 +1,67 @@ +#ifndef SC_PATCHES_H +#define SC_PATCHES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void patchGeneralWhiteScreen(u32 romSize); +bool patchSpecificGame(); + +enum SaveType { + SAVE_TYPE_NONE = 0, + + SAVE_TYPE_EEPROM = (1 << 14), + SAVE_TYPE_EEPROM_V111, + SAVE_TYPE_EEPROM_V120, + SAVE_TYPE_EEPROM_V121, + SAVE_TYPE_EEPROM_V122, + SAVE_TYPE_EEPROM_V124, + SAVE_TYPE_EEPROM_V125, + SAVE_TYPE_EEPROM_V126, + + SAVE_TYPE_FLASH = (2 << 14), + SAVE_TYPE_FLASH512 = SAVE_TYPE_FLASH | (0 << 13), + SAVE_TYPE_FLASH_V120, + SAVE_TYPE_FLASH_V121, + SAVE_TYPE_FLASH_V123, + SAVE_TYPE_FLASH_V124, + SAVE_TYPE_FLASH_V125, + SAVE_TYPE_FLASH_V126, + SAVE_TYPE_FLASH512_V130, + SAVE_TYPE_FLASH512_V131, + SAVE_TYPE_FLASH512_V133, + + SAVE_TYPE_FLASH1M = SAVE_TYPE_FLASH | (1 << 13), + SAVE_TYPE_FLASH1M_V102, + SAVE_TYPE_FLASH1M_V103, + + SAVE_TYPE_SRAM = (3 << 14), + SAVE_TYPE_SRAM_F_V100, + SAVE_TYPE_SRAM_F_V102, + SAVE_TYPE_SRAM_F_V103, + SAVE_TYPE_SRAM_V110, + SAVE_TYPE_SRAM_V111, + SAVE_TYPE_SRAM_V112, + SAVE_TYPE_SRAM_V113, + + SAVE_TYPE_TYPE_MASK = (3 << 14) +}; + +struct save_type { + char tag[16]; + u16 tagLength; + u16 type; + u32 size; + bool (*patchFunc)(const struct save_type* type); +}; + +const struct save_type* save_findTag(); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/arm9/include/sc_sram.c b/arm9/include/sc_sram.c new file mode 100644 index 0000000..3a98685 --- /dev/null +++ b/arm9/include/sc_sram.c @@ -0,0 +1,601 @@ +#include +#include "find.h" +#include "sc_patches.h" + +#include "io_sc_common.h" + +#define SAVE_TYPE_COUNT 25 + +u32 romSize; + +// SRAM Patches + +static const u8 flash1M_V102_find1[48] = { + 0xaa,0x21,0x19,0x70,0x05,0x4a,0x55,0x21,0x11,0x70,0xb0,0x21,0x19,0x70,0xe0,0x21, + 0x09,0x05,0x08,0x70,0x70,0x47,0x55,0x55,0x00,0x0e,0xaa,0x2a,0x00,0x0e,0x30,0xb5, + 0x91,0xb0,0x68,0x46,0x00,0xf0,0xf3,0xf8,0x6d,0x46,0x01,0x35,0x06,0x4a,0xaa,0x20 +}; +static const u8 flash1M_V102_replace1[136] = { + 0x80,0x21,0x09,0x02,0x09,0x22,0x12,0x06,0x9f,0x44,0x11,0x80,0x03,0x49,0xc3,0x02, + 0xc9,0x18,0x11,0x80,0x70,0x47,0xfe,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x30,0xb5, + 0x91,0xb0,0x68,0x46,0x00,0xf0,0xf3,0xf8,0x6d,0x46,0x01,0x35,0x06,0x4a,0xaa,0x20, + 0x00,0x00,0x05,0x49,0x55,0x20,0x00,0x00,0x90,0x20,0x00,0x00,0x10,0xa9,0x03,0x4a, + 0x10,0x1c,0x08,0xe0,0x00,0x00,0x55,0x55,0x00,0x0e,0xaa,0x2a,0x00,0x0e,0x20,0x4e, + 0x00,0x00,0x08,0x88,0x01,0x38,0x08,0x80,0x08,0x88,0x00,0x28,0xf9,0xd1,0x0c,0x48, + 0x13,0x20,0x13,0x20,0x00,0x06,0x04,0x0c,0xe0,0x20,0x00,0x05,0x62,0x20,0x62,0x20, + 0x00,0x06,0x00,0x0e,0x04,0x43,0x07,0x49,0xaa,0x20,0x00,0x00,0x07,0x4a,0x55,0x20, + 0x00,0x00,0xf0,0x20,0x00,0x00,0x00,0x00 +}; +static const u8 flash1M_V102_find2[24] = { + 0x14,0x49,0xaa,0x24,0x0c,0x70,0x13,0x4b,0x55,0x22,0x1a,0x70,0x80,0x20,0x08,0x70, + 0x0c,0x70,0x1a,0x70,0x10,0x20,0x08,0x70 +}; +static const u8 flash1M_V102_replace2[24] = { + 0x0e,0x21,0x09,0x06,0xff,0x24,0x80,0x22,0x13,0x4b,0x52,0x02,0x01,0x3a,0x8c,0x54, + 0xfc,0xd1,0x00,0x00,0x00,0x00,0x00,0x00 +}; +static const u8 flash1M_V102_find3[22] = { + 0xaa,0x25,0x0d,0x70,0x13,0x4b,0x55,0x22,0x1a,0x70,0x80,0x20,0x08,0x70,0x0d,0x70, + 0x1a,0x70,0x30,0x20,0x20,0x70 +}; +static const u8 flash1M_V102_replace3[22] = { + 0xff,0x25,0x08,0x22,0x00,0x00,0x52,0x02,0x01,0x3a,0xa5,0x54,0xfc,0xd1,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00 +}; +static const u8 flash1M_V102_find4[12] = { + 0x22,0x70,0x09,0x4b,0x55,0x22,0x1a,0x70,0xa0,0x22,0x22,0x70 +}; +static const u8 flash1M_V102_replace4[12] = { + 0x00,0x00,0x09,0x4b,0x55,0x22,0x00,0x00,0xa0,0x22,0x00,0x00 +}; + + +static const u8 flash1M_V103_find1[98] = { + 0x05,0x4b,0xaa,0x21,0x19,0x70,0x05,0x4a,0x55,0x21,0x11,0x70,0xb0,0x21,0x19,0x70, + 0xe0,0x21,0x09,0x05,0x08,0x70,0x70,0x47,0x55,0x55,0x00,0x0e,0xaa,0x2a,0x00,0x0e, + 0x30,0xb5,0x91,0xb0,0x68,0x46,0x00,0xf0,0xf3,0xf8,0x6d,0x46,0x01,0x35,0x06,0x4a, + 0xaa,0x20,0x10,0x70,0x05,0x49,0x55,0x20,0x08,0x70,0x90,0x20,0x10,0x70,0x10,0xa9, + 0x03,0x4a,0x10,0x1c,0x08,0xe0,0x00,0x00,0x55,0x55,0x00,0x0e,0xaa,0x2a,0x00,0x0e, + 0x20,0x4e,0x00,0x00,0x08,0x88,0x01,0x38,0x08,0x80,0x08,0x88,0x00,0x28,0xf9,0xd1, + 0x0c,0x48 +}; +static const u8 flash1M_V103_replace1[138] = { + 0x05,0x4b,0x80,0x21,0x09,0x02,0x09,0x22,0x12,0x06,0x9f,0x44,0x11,0x80,0x03,0x49, + 0xc3,0x02,0xc9,0x18,0x11,0x80,0x70,0x47,0xfe,0xff,0xff,0x01,0x00,0x00,0x00,0x00, + 0x30,0xb5,0x91,0xb0,0x68,0x46,0x00,0xf0,0xf3,0xf8,0x6d,0x46,0x01,0x35,0x06,0x4a, + 0xaa,0x20,0x00,0x00,0x05,0x49,0x55,0x20,0x00,0x00,0x90,0x20,0x00,0x00,0x10,0xa9, + 0x03,0x4a,0x10,0x1c,0x08,0xe0,0x00,0x00,0x55,0x55,0x00,0x0e,0xaa,0x2a,0x00,0x0e, + 0x20,0x4e,0x00,0x00,0x08,0x88,0x01,0x38,0x08,0x80,0x08,0x88,0x00,0x28,0xf9,0xd1, + 0x0c,0x48,0x13,0x20,0x13,0x20,0x00,0x06,0x04,0x0c,0xe0,0x20,0x00,0x05,0x62,0x20, + 0x62,0x20,0x00,0x06,0x00,0x0e,0x04,0x43,0x07,0x49,0xaa,0x20,0x00,0x00,0x07,0x4a, + 0x55,0x20,0x00,0x00,0xf0,0x20,0x00,0x00,0x00,0x00 +}; +static const u8 flash1M_V103_find2[24] = { + 0x14,0x49,0xaa,0x24,0x0c,0x70,0x13,0x4b,0x55,0x22,0x1a,0x70,0x80,0x20,0x08,0x70, + 0x0c,0x70,0x1a,0x70,0x10,0x20,0x08,0x70 +}; +static const u8 flash1M_V103_replace2[24] = { + 0x0e,0x21,0x09,0x06,0xff,0x24,0x80,0x22,0x13,0x4b,0x52,0x02,0x01,0x3a,0x8c,0x54, + 0xfc,0xd1,0x00,0x00,0x00,0x00,0x00,0x00 +}; +static const u8 flash1M_V103_find3[22] = { + 0xaa,0x25,0x0d,0x70,0x14,0x4b,0x55,0x22,0x1a,0x70,0x80,0x20,0x08,0x70,0x0d,0x70, + 0x1a,0x70,0x30,0x20,0x20,0x70 +}; +static const u8 flash1M_V103_replace3[22] = { + 0xff,0x25,0x08,0x22,0x00,0x00,0x52,0x02,0x01,0x3a,0xa5,0x54,0xfc,0xd1,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00 +}; +static const u8 flash1M_V103_find4[12] = { + 0x10,0x70,0x0b,0x49,0x55,0x20,0x08,0x70,0xa0,0x20,0x10,0x70 +}; +static const u8 flash1M_V103_replace4[12] = { + 0x00,0x00,0x0b,0x49,0x55,0x20,0x00,0x00,0xa0,0x20,0x00,0x00 +}; +static const u8 flash1M_V103_find5[12] = { + 0x22,0x70,0x09,0x4b,0x55,0x22,0x1a,0x70,0xa0,0x22,0x22,0x70 +}; +static const u8 flash1M_V103_replace5[12] = { + 0x00,0x00,0x09,0x4b,0x55,0x22,0x00,0x00,0xa0,0x22,0x00,0x00 +}; + + +// FLASH512_V130, V131, and V133 have all the same patches. +// Patches are from gbatemp thread, but gbata doesn't actually support V133. +static const u8 flash512_V13X_find1[38] = { + 0xf0,0xb5,0xa0,0xb0,0x0d,0x1c,0x16,0x1c,0x1f,0x1c,0x03,0x04,0x1c,0x0c,0x0f,0x4a, + 0x10,0x88,0x0f,0x49,0x08,0x40,0x03,0x21,0x08,0x43,0x10,0x80,0x0d,0x48,0x00,0x68, + 0x01,0x68,0x80,0x20,0x80,0x02 +}; +static const u8 flash512_V13X_replace1[38] = { + 0x70,0xb5,0xa0,0xb0,0x00,0x03,0x40,0x18,0xe0,0x21,0x09,0x05,0x09,0x18,0x08,0x78, + 0x10,0x70,0x01,0x3b,0x01,0x32,0x01,0x31,0x00,0x2b,0xf8,0xd1,0x00,0x20,0x20,0xb0, + 0x70,0xbc,0x02,0xbc,0x08,0x47 +}; +static const u8 flash512_V13X_find2[8] = { + 0xff,0xf7,0x88,0xfd,0x00,0x04,0x03,0x0c +}; +static const u8 flash512_V13X_replace2[8] = { + 0x1b,0x23,0x1b,0x02,0x32,0x20,0x03,0x43 +}; +static const u8 flash512_V13X_find3[8] = { + 0x70,0xb5,0x90,0xb0,0x15,0x4d,0x29,0x88 +}; +static const u8 flash512_V13X_find4[8] = { + 0x70,0xb5,0x46,0x46,0x40,0xb4,0x90,0xb0 +}; +static const u8 flash512_V13X_replace3_4[8] = { + 0x00,0xb5,0x00,0x20,0x02,0xbc,0x08,0x47 +}; +static const u8 flash512_V13X_find5[24] = { + 0xf0,0xb5,0x90,0xb0,0x0f,0x1c,0x00,0x04,0x04,0x0c,0x03,0x48,0x00,0x68,0x40,0x89, + 0x84,0x42,0x05,0xd3,0x01,0x48,0x41,0xe0 +}; +static const u8 flash512_V13X_replace5[42] = { + 0x7c,0xb5,0x90,0xb0,0x00,0x03,0x0a,0x1c,0xe0,0x21,0x09,0x05,0x09,0x18,0x01,0x23, + 0x1b,0x03,0x10,0x78,0x08,0x70,0x01,0x3b,0x01,0x32,0x01,0x31,0x00,0x2b,0xf8,0xd1, + 0x00,0x20,0x10,0xb0,0x7c,0xbc,0x02,0xbc,0x08,0x47 +}; + + +// Encompasses FLASH_V120 and V121. +static const u8 flash_V12X_find1[12] = { + 0x90,0xb5,0x93,0xb0,0x6f,0x46,0x39,0x1d,0x08,0x1c,0x00,0xf0 +}; +static const u8 flash_V12X_replace1[14] = { + 0x00,0xb5,0x3d,0x20,0x00,0x02,0x1f,0x21,0x08,0x43,0x02,0xbc,0x08,0x47 +}; +static const u8 flash_V12X_find2[35] = { + 0x80,0xb5,0x94,0xb0,0x6f,0x46,0x39,0x1c,0x08,0x80,0x38,0x1c,0x01,0x88,0x0f,0x29, + 0x04,0xd9,0x01,0x48,0x56,0xe0,0x00,0x00,0xff,0x80,0x00,0x00,0x23,0x48,0x23,0x49, + 0x0a,0x88,0x23 +}; +static const u8 flash_V12X_replace2[36] = { + 0x7c,0xb5,0x00,0x07,0x00,0x0c,0xe0,0x21,0x09,0x05,0x09,0x18,0x01,0x23,0x1b,0x03, + 0xff,0x20,0x08,0x70,0x01,0x3b,0x01,0x31,0x00,0x2b,0xfa,0xd1,0x00,0x20,0x7c,0xbc, + 0x02,0xbc,0x08,0x47 +}; +static const u8 flash_V12X_find3[42] = { + 0x80,0xb5,0x94,0xb0,0x6f,0x46,0x79,0x60,0x39,0x1c,0x08,0x80,0x38,0x1c,0x01,0x88, + 0x0f,0x29,0x03,0xd9,0x00,0x48,0x73,0xe0,0xff,0x80,0x00,0x00,0x38,0x1c,0x01,0x88, + 0x08,0x1c,0xff,0xf7,0x21,0xfe,0x39,0x1c,0x0c,0x31 +}; +static const u8 flash_V12X_replace3[42] = { + 0x7c,0xb5,0x90,0xb0,0x00,0x03,0x0a,0x1c,0xe0,0x21,0x09,0x05,0x09,0x18,0x01,0x23, + 0x1b,0x03,0x10,0x78,0x08,0x70,0x01,0x3b,0x01,0x32,0x01,0x31,0x00,0x2b,0xf8,0xd1, + 0x00,0x20,0x10,0xb0,0x7c,0xbc,0x08,0xbc,0x08,0x47 +}; + +// Encompasses FLASH_V123, V124, V125, and V126. +// FIXME for FLASH_V125 and FLASH_V126: Medabots/Metarot and Super Monkey Ball Jr. (U) don't patch 1:1 with gbata. +static const u8 flash_V12Y_find1[8] = { + 0xff,0xf7,0xaa,0xff,0x00,0x04,0x03,0x0c +}; +static const u8 flash_V12Y_replace1[8] = { + 0x1b,0x23,0x1b,0x02,0x32,0x20,0x03,0x43 +}; +static const u8 flash_V12Y_find2[6] = { + 0x70,0xb5,0x90,0xb0,0x15,0x4d +}; +static const u8 flash_V12Y_replace2[4] = { + 0x00,0x20,0x70,0x47/*,0x15,0x4d*/ +}; +// Patch 3 differs from GBATemp tutorial. +// The added bytes at the end have significance. +static const u8 flash_V12Y_find3[9] = { + 0x70,0xb5,0x46,0x46,0x40,0xb4,0x90,0xb0,0x00 +}; +static const u8 flash_V12Y_replace3[4] = { + 0x00,0x20,0x70,0x47/*,0x40,0xb4,0x90,0xb0,0x00*/ +}; +static const u8 flash_V12Y_find4[38] = { + 0xf0,0xb5,0x90,0xb0,0x0f,0x1c,0x00,0x04,0x04,0x0c,0x0f,0x2c,0x04,0xd9,0x01,0x48, + 0x40,0xe0,0x00,0x00,0xff,0x80,0x00,0x00,0x20,0x1c,0xff,0xf7,0xd7,0xfe,0x00,0x04, + 0x05,0x0c,0x00,0x2d,0x35,0xd1 +}; +static const u8 flash_V12Y_replace4[38] = { + 0x70,0xb5,0x00,0x03,0x0a,0x1c,0xe0,0x21,0x09,0x05,0x41,0x18,0x01,0x23,0x1b,0x03, + 0x10,0x78,0x08,0x70,0x01,0x3b,0x01,0x32,0x01,0x31,0x00,0x2b,0xf8,0xd1,0x00,0x20, + 0x70,0xbc,0x02,0xbc,0x08,0x47 +}; + + +bool flash_patchV120(const struct save_type* type) { + u8* func1 = memsearch8((u8*)0x08000000, romSize, flash_V12X_find1, sizeof(flash_V12X_find1), true); + if (!func1) + return false; + twoByteCpy((u16*)func1, (const u16*)flash_V12X_replace1, sizeof(flash_V12X_replace1)); + + u8* func2 = memsearch8((u8*)0x08000000, romSize, flash_V12X_find2, sizeof(flash_V12X_find2), true); + if (!func2) + return false; + twoByteCpy((u16*)func2, (const u16*)flash_V12X_replace2, sizeof(flash_V12X_replace2)); + + u8* func3 = memsearch8((u8*)0x08000000, romSize, flash_V12X_find3, sizeof(flash_V12X_find3), true); + if (!func3) + return false; + twoByteCpy((u16*)func3, (const u16*)flash_V12X_replace3, sizeof(flash_V12X_replace3)); + + return true; +} + +bool flash_patchV123(const struct save_type* type) { + u8* func1 = memsearch8((u8*)0x08000000, romSize, flash_V12Y_find1, sizeof(flash_V12Y_find1), true); + if (!func1) + return false; + twoByteCpy((u16*)func1, (const u16*)flash_V12Y_replace1, sizeof(flash_V12Y_replace1)); + + u8* func2 = memsearch8((u8*)0x08000000, romSize, flash_V12Y_find2, sizeof(flash_V12Y_find2), true); + if (!func2) + return false; + twoByteCpy((u16*)func2, (const u16*)flash_V12Y_replace2, sizeof(flash_V12Y_replace2)); + + u8* func3 = memsearch8((u8*)0x08000000, romSize, flash_V12Y_find3, sizeof(flash_V12Y_find3), true); + if (!func3) + return false; + twoByteCpy((u16*)func3, (const u16*)flash_V12Y_replace3, sizeof(flash_V12Y_replace3)); + + u8* func4 = memsearch8((u8*)0x08000000, romSize, flash_V12Y_find4, sizeof(flash_V12Y_find4), true); + if (!func4) + return false; + twoByteCpy((u16*)func4, (const u16*)flash_V12Y_replace4, sizeof(flash_V12Y_replace4)); + + return true; +} + +/*bool flash_patchV126(const struct save_type* type) +{ +}*/ + +bool flash_patch512V130(const struct save_type* type) { + u32* romPos = (u32*)0x08000000; + u32 curRomSize = romSize; + u32 startSig[4] = {0}; + startSig[0] = *(u32*)0x08000000; + startSig[1] = *(u32*)0x08000004; + startSig[2] = *(u32*)0x08000008; + startSig[3] = *(u32*)0x0800000C; + + for (int i = 0; i < 2; i++) { + + if (i != 0) { + while (romPos < romPos+romSize) { + // Look for another ROM in 2 in 1 game packs + romPos += 0x100000; + curRomSize -= 0x100000; + if (curRomSize <= 0) break; + if (romPos[0] == startSig[0] + && romPos[1] == startSig[1] + && romPos[2] == startSig[2] + && romPos[3] == startSig[3]) { + break; + } + } + + if (romPos >= romPos+romSize) break; + } + + u8* func1 = memsearch8((u8*)romPos, curRomSize, flash512_V13X_find1, sizeof(flash512_V13X_find1), true); + if (!func1) + return false; + twoByteCpy((u16*)func1, (const u16*)flash512_V13X_replace1, sizeof(flash512_V13X_replace1)); + + u8* func2 = memsearch8((u8*)romPos, curRomSize, flash512_V13X_find2, sizeof(flash512_V13X_find2), true); + if (!func2) + return false; + twoByteCpy((u16*)func2, (const u16*)flash512_V13X_replace2, sizeof(flash512_V13X_replace2)); + + u8* func3 = memsearch8((u8*)romPos, curRomSize, flash512_V13X_find3, sizeof(flash512_V13X_find3), true); + if (!func3) + return false; + twoByteCpy((u16*)func3, (const u16*)flash512_V13X_replace3_4, sizeof(flash512_V13X_replace3_4)); + + u8* func4 = memsearch8((u8*)romPos, curRomSize, flash512_V13X_find4, sizeof(flash512_V13X_find4), true); + if (!func4) + return false; + twoByteCpy((u16*)func4, (const u16*)flash512_V13X_replace3_4, sizeof(flash512_V13X_replace3_4)); + + u8* func5 = memsearch8((u8*)romPos, curRomSize, flash512_V13X_find5, sizeof(flash512_V13X_find5), true); + if (!func5) + return false; + twoByteCpy((u16*)func5, (const u16*)flash512_V13X_replace5, sizeof(flash512_V13X_replace5)); + + } + + return true; +} + +bool flash_patch1MV102(const struct save_type* type) { + u8* func1 = memsearch8((u8*)0x08000000, romSize, flash1M_V102_find1, sizeof(flash1M_V102_find1), true); + if (!func1) + return false; + twoByteCpy((u16*)func1, (const u16*)flash1M_V102_replace1, sizeof(flash1M_V102_replace1)); + + u8* func2 = memsearch8((u8*)0x08000000, romSize, flash1M_V102_find2, sizeof(flash1M_V102_find2), true); + if (!func2) + return false; + twoByteCpy((u16*)func2, (const u16*)flash1M_V102_replace2, sizeof(flash1M_V102_replace2)); + + u8* func3 = memsearch8((u8*)0x08000000, romSize, flash1M_V102_find3, sizeof(flash1M_V102_find3), true); + if (!func3) + return false; + twoByteCpy((u16*)func3, (const u16*)flash1M_V102_replace3, sizeof(flash1M_V102_replace3)); + + u8* func4 = memsearch8((u8*)0x08000000, romSize, flash1M_V102_find4, sizeof(flash1M_V102_find4), true); + if (!func4) + return false; + twoByteCpy((u16*)func4, (const u16*)flash1M_V102_replace4, sizeof(flash1M_V102_replace4)); + + return true; +} + +bool flash_patch1MV103(const struct save_type* type) { + u8* func1 = memsearch8((u8*)0x08000000, romSize, flash1M_V103_find1, sizeof(flash1M_V103_find1), true); + if (!func1) + return false; + twoByteCpy((u16*)func1, (const u16*)flash1M_V103_replace1, sizeof(flash1M_V103_replace1)); + + u8* func2 = memsearch8((u8*)0x08000000, romSize, flash1M_V103_find2, sizeof(flash1M_V103_find2), true); + if (!func2) + return false; + twoByteCpy((u16*)func2, (const u16*)flash1M_V103_replace2, sizeof(flash1M_V103_replace2)); + + u8* func3 = memsearch8((u8*)0x08000000, romSize, flash1M_V103_find3, sizeof(flash1M_V103_find3), true); + if (!func3) + return false; + twoByteCpy((u16*)func3, (const u16*)flash1M_V103_replace3, sizeof(flash1M_V103_replace3)); + + u8* func4 = memsearch8((u8*)0x08000000, romSize, flash1M_V103_find4, sizeof(flash1M_V103_find4), true); + if (!func4) + return false; + twoByteCpy((u16*)func4, (const u16*)flash1M_V103_replace4, sizeof(flash1M_V103_replace4)); + + u8* func5 = memsearch8((u8*)0x08000000, romSize, flash1M_V103_find5, sizeof(flash1M_V103_find5), true); + if (!func5) + return false; + twoByteCpy((u16*)func5, (const u16*)flash1M_V103_replace5, sizeof(flash1M_V103_replace5)); + + return true; +} + +//todo: Moero!! Jaleco Collection (Japan) reports EEPROM_V124, but the signatures below don't work! + +static const u8 sReadEepromDwordV111Sig[0x10] = { 0xB0, 0xB5, 0xAA, 0xB0, 0x6F, 0x46, 0x79, 0x60, 0x39, 0x1C, 0x08, 0x80, 0x38, 0x1C, 0x01, 0x88 }; + +static const u8 sReadEepromDwordV120Sig[0x10] = { 0x70, 0xB5, 0xA2, 0xB0, 0x0D, 0x1C, 0x00, 0x04, 0x03, 0x0C, 0x03, 0x48, 0x00, 0x68, 0x80, 0x88 }; + +static const u8 sProgramEepromDwordV111Sig[0x10] = { 0x80, 0xB5, 0xAA, 0xB0, 0x6F, 0x46, 0x79, 0x60, 0x39, 0x1C, 0x08, 0x80, 0x38, 0x1C, 0x01, 0x88 }; + +//changed in EEPROM_V124 +static const u8 sProgramEepromDwordV120Sig[0x10] = { 0x30, 0xB5, 0xA9, 0xB0, 0x0D, 0x1C, 0x00, 0x04, 0x04, 0x0C, 0x03, 0x48, 0x00, 0x68, 0x80, 0x88 }; + +//changed in EEPROM_V126 +static const u8 sProgramEepromDwordV124Sig[0x10] = { 0xF0, 0xB5, 0xAC, 0xB0, 0x0D, 0x1C, 0x00, 0x04, 0x01, 0x0C, 0x12, 0x06, 0x17, 0x0E, 0x03, 0x48 }; + +static const u8 sProgramEepromDwordV126Sig[0x10] = { 0xF0, 0xB5, 0x47, 0x46, 0x80, 0xB4, 0xAC, 0xB0, 0x0E, 0x1C, 0x00, 0x04, 0x05, 0x0C, 0x12, 0x06 }; + +//not in EEPROM_V111 +//could be used to identify the eeprom size, but not strictly needed +/*static u16 identifyEeprom(u16 kbitSize) +{ + return 0; +}*/ + +const u8 patch_eeprom_1[] = { + 0x00,0x04, // LSL R0, R0, #0x10 + 0x0a,0x1c, // ADD R2, R1, #0 + 0x40,0x0b, // LSR R0, R0, #0xD + 0xe0,0x21,0x09,0x05, // MOVL R1, 0xE000000 + 0x41,0x18, // ADD R1, R0, R1 + 0x07,0x31, // ADD R1, #7 + 0x00,0x23, // MOV R3, #0 + //l1: + 0x08,0x78, // LDRB R0, [R1] + 0x10,0x70, // STRB R0, [R2] + 0x01,0x33, // ADD R3, #1 + 0x01,0x32, // ADD R2, #1 + 0x01,0x39, // SUB R1, #1 + 0x07,0x2b, // CMP R3, #7 + 0xf8,0xd9, // BLS l1 + 0x00,0x20, // MOV R0, #0 + 0x70,0x47 // BX LR +}; + +const u8 patch_eeprom_2[] = { + 0x00,0x04, // LSL R0, R0, #0x10 + 0x0a,0x1c, // ADD R2, R1, #0 + 0x40,0x0b, // LSR R0, R0, #0xD + 0xe0,0x21,0x09,0x05, // MOVL R1, 0xE000000 + 0x41,0x18, // ADD R1, R0, R1 + 0x07,0x31, // ADD R1, #7 + 0x00,0x23, // MOV R3, #0 + //l1: + 0x10,0x78, // LDRB R0, [R2] + 0x08,0x70, // STRB R0, [R1] + 0x01,0x33, // ADD R3, #1 + 0x01,0x32, // ADD R2, #1 + 0x01,0x39, // SUB R1, #1 + 0x07,0x2b, // CMP R3, #7 + 0xf8,0xd9, // BLS l1 + 0x00,0x20, // MOV R0, #0 + 0x70,0x47 // BX LR +}; + +bool eeprom_patchV111(const struct save_type* type) { + u8* readFunc = memsearch8((u8*)0x08000000, romSize, sReadEepromDwordV111Sig, 0x10, true); + if (!readFunc) + return false; + twoByteCpy((u16*)readFunc, (const u16*)patch_eeprom_1, sizeof(patch_eeprom_1)); + + u8* progFunc = memsearch8((u8*)0x08000000, romSize, sProgramEepromDwordV111Sig, 0x10, true); + if (!progFunc) + return false; + twoByteCpy((u16*)progFunc, (const u16*)patch_eeprom_2, sizeof(patch_eeprom_2)); + return true; +} + +bool eeprom_patchV120(const struct save_type* type) { + u32* romPos = (u32*)0x08000000; + u32 curRomSize = romSize; + u32 startSig[4] = {0}; + startSig[0] = *(u32*)0x08000000; + startSig[1] = *(u32*)0x08000004; + startSig[2] = *(u32*)0x08000008; + startSig[3] = *(u32*)0x0800000C; + + for (int i = 0; i < 3; i++) { + + if (i != 0) { + while (romPos < romPos+romSize) { + // Look for another ROM in 2-3 in 1 game packs + romPos += 0x100000; + curRomSize -= 0x100000; + if (curRomSize <= 0) break; + if (romPos[0] == startSig[0] + && romPos[1] == startSig[1] + && romPos[2] == startSig[2] + && romPos[3] == startSig[3]) { + break; + } + } + + if (romPos >= romPos+romSize) break; + } + + u8* readFunc = memsearch8((u8*)romPos, curRomSize, sReadEepromDwordV120Sig, 0x10, true); + if (!readFunc) + return false; + twoByteCpy((u16*)readFunc, (const u16*)patch_eeprom_1, sizeof(patch_eeprom_1)); + + u8* progFunc = memsearch8((u8*)romPos, curRomSize, sProgramEepromDwordV120Sig, 0x10, true); + if (!progFunc) + return false; + twoByteCpy((u16*)progFunc, (const u16*)patch_eeprom_2, sizeof(patch_eeprom_2)); + + } + + return true; +} + +bool eeprom_patchV124(const struct save_type* type) { + u32* romPos = (u32*)0x08000000; + u32 curRomSize = romSize; + u32 startSig[4] = {0}; + startSig[0] = *(u32*)0x08000000; + startSig[1] = *(u32*)0x08000004; + startSig[2] = *(u32*)0x08000008; + startSig[3] = *(u32*)0x0800000C; + + for (int i = 0; i < 2; i++) { + + if (i != 0) { + while (romPos < romPos+romSize) { + // Look for another ROM in 2 in 1 game packs + romPos += 0x100000; + curRomSize -= 0x100000; + if (curRomSize <= 0) break; + if (romPos[0] == startSig[0] + && romPos[1] == startSig[1] + && romPos[2] == startSig[2] + && romPos[3] == startSig[3]) { + break; + } + } + + if (romPos >= romPos+romSize) break; + } + + u8* readFunc = memsearch8((u8*)romPos, curRomSize, sReadEepromDwordV120Sig, 0x10, true); + if (!readFunc) + return false; + twoByteCpy((u16*)readFunc, (const u16*)patch_eeprom_1, sizeof(patch_eeprom_1)); + + u8* progFunc = memsearch8((u8*)romPos, curRomSize, sProgramEepromDwordV124Sig, 0x10, true); + if (!progFunc) + return false; + twoByteCpy((u16*)progFunc, (const u16*)patch_eeprom_2, sizeof(patch_eeprom_2)); + + } + + return true; +} + +bool eeprom_patchV126(const struct save_type* type) { + u8* readFunc = memsearch8((u8*)0x08000000, romSize, sReadEepromDwordV120Sig, 0x10, true); + if (!readFunc) + return false; + twoByteCpy((u16*)readFunc, (const u16*)patch_eeprom_1, sizeof(patch_eeprom_1)); + + u8* progFunc = memsearch8((u8*)0x08000000, romSize, sProgramEepromDwordV126Sig, 0x10, true); + if (!progFunc) + return false; + twoByteCpy((u16*)progFunc, (const u16*)patch_eeprom_2, sizeof(patch_eeprom_2)); + return true; +} + + +static const struct save_type sSaveTypes[SAVE_TYPE_COUNT] = { + {"EEPROM_V111", 12, SAVE_TYPE_EEPROM_V111, 512, eeprom_patchV111}, + {"EEPROM_V120", 12, SAVE_TYPE_EEPROM_V120, 8 * 1024, eeprom_patchV120}, + {"EEPROM_V121", 12, SAVE_TYPE_EEPROM_V121, 8 * 1024, eeprom_patchV120}, + {"EEPROM_V122", 12, SAVE_TYPE_EEPROM_V122, 8 * 1024, eeprom_patchV120}, + {"EEPROM_V124", 12, SAVE_TYPE_EEPROM_V124, 8 * 1024, eeprom_patchV124}, + {"EEPROM_V125", 12, SAVE_TYPE_EEPROM_V125, 8 * 1024, eeprom_patchV124}, + {"EEPROM_V126", 12, SAVE_TYPE_EEPROM_V126, 8 * 1024, eeprom_patchV126}, + + {"FLASH_V120", 11, SAVE_TYPE_FLASH_V120, 64 * 1024, flash_patchV120}, + {"FLASH_V121", 11, SAVE_TYPE_FLASH_V121, 64 * 1024, flash_patchV120}, + {"FLASH_V123", 11, SAVE_TYPE_FLASH_V123, 64 * 1024, flash_patchV123}, + {"FLASH_V124", 11, SAVE_TYPE_FLASH_V124, 64 * 1024, flash_patchV123}, + {"FLASH_V125", 11, SAVE_TYPE_FLASH_V125, 64 * 1024, flash_patchV123}, + {"FLASH_V126", 11, SAVE_TYPE_FLASH_V126, 64 * 1024, /*flash_patchV126*/ flash_patchV123}, + {"FLASH512_V130", 14, SAVE_TYPE_FLASH512_V130, 64 * 1024, flash_patch512V130}, + {"FLASH512_V131", 14, SAVE_TYPE_FLASH512_V131, 64 * 1024, flash_patch512V130}, + {"FLASH512_V133", 14, SAVE_TYPE_FLASH512_V133, 64 * 1024, flash_patch512V130}, + {"FLASH1M_V102", 13, SAVE_TYPE_FLASH1M_V102, 128 * 1024, flash_patch1MV102}, + {"FLASH1M_V103", 13, SAVE_TYPE_FLASH1M_V103, 128 * 1024, flash_patch1MV103}, + + //sram does not require patching + {"SRAM_F_V100", 12, SAVE_TYPE_SRAM_F_V100, 32 * 1024, NULL}, + {"SRAM_F_V102", 12, SAVE_TYPE_SRAM_F_V102, 32 * 1024, NULL}, + {"SRAM_F_V103", 12, SAVE_TYPE_SRAM_F_V103, 32 * 1024, NULL}, + + {"SRAM_V110", 10, SAVE_TYPE_SRAM_V110, 32 * 1024, NULL}, + {"SRAM_V111", 10, SAVE_TYPE_SRAM_V111, 32 * 1024, NULL}, + {"SRAM_V112", 10, SAVE_TYPE_SRAM_V112, 32 * 1024, NULL}, + {"SRAM_V113", 10, SAVE_TYPE_SRAM_V113, 32 * 1024, NULL}, +}; + +const struct save_type* save_findTag() { + u32 curAddr = 0x080000C0; + char saveTag[16]; + while (curAddr < 0x08000000+romSize) { + u32 fst = *(u32*)curAddr; + // tonccpy(&saveTag, (u8*)curAddr, 16); + ((u32*)saveTag)[0] = ((u32*)curAddr)[0]; + ((u32*)saveTag)[1] = ((u32*)curAddr)[1]; + ((u32*)saveTag)[2] = ((u32*)curAddr)[2]; + ((u32*)saveTag)[3] = ((u32*)curAddr)[3]; + enum SaveType type = SAVE_TYPE_NONE; + if (fst == 0x53414C46 && (saveTag[5] == '_' || saveTag[5] == '5' || saveTag[5] == '1')) { + //FLAS + type = SAVE_TYPE_FLASH; + } else if (fst == 0x4D415253) { + //SRAM + type = SAVE_TYPE_SRAM; + } else if (fst == 0x52504545 && saveTag[6] == '_') { + //EEPR + type = SAVE_TYPE_EEPROM; + } + + if (type != SAVE_TYPE_NONE) { + for (int i = 0; i < SAVE_TYPE_COUNT; i++) { + if (strncmp(saveTag, sSaveTypes[i].tag, sSaveTypes[i].tagLength) != 0)continue; + return &sSaveTypes[i]; + } + } + curAddr += 4; + } + return NULL; +} + diff --git a/arm9/include/sc_sram.h b/arm9/include/sc_sram.h new file mode 100644 index 0000000..3226450 --- /dev/null +++ b/arm9/include/sc_sram.h @@ -0,0 +1,31 @@ +#ifndef SC_SRAM_H +#define SC_SRAM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern u32 romSize; + +bool flash_patchV120(const struct save_type* type); +bool flash_patchV123(const struct save_type* type); +bool flash_patchV126(const struct save_type* type); +bool flash_patch512V130(const struct save_type* type); +bool flash_patch1MV102(const struct save_type* type); +bool flash_patch1MV103(const struct save_type* type); + +bool eeprom_patchV111(const struct save_type* type); +bool eeprom_patchV120(const struct save_type* type); +bool eeprom_patchV124(const struct save_type* type); +bool eeprom_patchV126(const struct save_type* type); + +const struct save_type* save_findTag(); + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/arm9/include/tonccpy.c b/arm9/include/tonccpy.c new file mode 100644 index 0000000..a51437e --- /dev/null +++ b/arm9/include/tonccpy.c @@ -0,0 +1,136 @@ +#include "tonccpy.h" +//# tonccpy.c + +//! VRAM-safe cpy. +/*! This version mimics memcpy in functionality, with + the benefit of working for VRAM as well. It is also + slightly faster than the original memcpy, but faster + implementations can be made. + \param dst Destination pointer. + \param src Source pointer. + \param size Fill-length in bytes. + \note The pointers and size need not be word-aligned. +*/ +void tonccpy(void *dst, const void *src, uint size) +{ + if(size==0 || dst==0 || src==0) + return; + + uint count; + u16 *dst16; // hword destination + u8 *src8; // byte source + + // Ideal case: copy by 4x words. Leaves tail for later. + if( ((u32)src|(u32)dst)%4==0 && size>=4) + { + u32 *src32= (u32*)src, *dst32= (u32*)dst; + + count= size/4; + uint tmp= count&3; + count /= 4; + + // Duff's Device, good friend! + switch(tmp) { + do { *dst32++ = *src32++; + case 3: *dst32++ = *src32++; + case 2: *dst32++ = *src32++; + case 1: *dst32++ = *src32++; + case 0: ; } while(count--); + } + + // Check for tail + size &= 3; + if(size == 0) + return; + + src8= (u8*)src32; + dst16= (u16*)dst32; + } + else // Unaligned. + { + uint dstOfs= (u32)dst&1; + src8= (u8*)src; + dst16= (u16*)(dst-dstOfs); + + // Head: 1 byte. + if(dstOfs != 0) + { + *dst16= (*dst16 & 0xFF) | *src8++<<8; + dst16++; + if(--size==0) + return; + } + } + + // Unaligned main: copy by 2x byte. + count= size/2; + while(count--) + { + *dst16++ = src8[0] | src8[1]<<8; + src8 += 2; + } + + // Tail: 1 byte. + if(size&1) + *dst16= (*dst16 &~ 0xFF) | *src8; +} +//# toncset.c + +//! VRAM-safe memset, internal routine. +/*! This version mimics memset in functionality, with + the benefit of working for VRAM as well. It is also + slightly faster than the original memset. + \param dst Destination pointer. + \param fill Word to fill with. + \param size Fill-length in bytes. + \note The \a dst pointer and \a size need not be + word-aligned. In the case of unaligned fills, \a fill + will be masked off to match the situation. +*/ +void __toncset(void *dst, u32 fill, uint size) +{ + if(size==0 || dst==0) + return; + + uint left= (u32)dst&3; + u32 *dst32= (u32*)(dst-left); + u32 count, mask; + + // Unaligned head. + if(left != 0) + { + // Adjust for very small stint. + if(left+size<4) + { + mask= BIT_MASK(size*8)<<(left*8); + *dst32= (*dst32 &~ mask) | (fill & mask); + return; + } + + mask= BIT_MASK(left*8); + *dst32= (*dst32 & mask) | (fill&~mask); + dst32++; + size -= 4-left; + } + + // Main stint. + count= size/4; + uint tmp= count&3; + count /= 4; + + switch(tmp) { + do { *dst32++ = fill; + case 3: *dst32++ = fill; + case 2: *dst32++ = fill; + case 1: *dst32++ = fill; + case 0: ; } while(count--); + } + + // Tail + size &= 3; + if(size) + { + mask= BIT_MASK(size*8); + *dst32= (*dst32 &~ mask) | (fill & mask); + } +} diff --git a/arm9/include/tonccpy.h b/arm9/include/tonccpy.h new file mode 100644 index 0000000..dd4267d --- /dev/null +++ b/arm9/include/tonccpy.h @@ -0,0 +1,43 @@ +//# Stuff you may not have yet. + +#ifndef TONCCPY_H +#define TONCCPY_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef unsigned int uint; +#define BIT_MASK(len) ( (1<<(len))-1 ) +static inline u32 quad8(u16 x) { x |= x<<8; return x | x<<16; } + + +//# Declarations and inlines. + +void tonccpy(void *dst, const void *src, uint size); + +void __toncset(void *dst, u32 fill, uint size); +static inline void toncset(void *dst, u8 src, uint size); +static inline void toncset16(void *dst, u16 src, uint size); +static inline void toncset32(void *dst, u32 src, uint size); + + +//! VRAM-safe memset, byte version. Size in bytes. +static inline void toncset(void *dst, u8 src, uint size) +{ __toncset(dst, quad8(src), size); } + +//! VRAM-safe memset, halfword version. Size in hwords. +static inline void toncset16(void *dst, u16 src, uint size) +{ __toncset(dst, src|src<<16, size*2); } + +//! VRAM-safe memset, word version. Size in words. +static inline void toncset32(void *dst, u32 src, uint size) +{ __toncset(dst, src, size*4); } + +#ifdef __cplusplus +} +#endif +#endif diff --git a/arm9/source/ctrl_tbl.cpp b/arm9/source/ctrl_tbl.cpp index af99d46..99c4d2a 100644 --- a/arm9/source/ctrl_tbl.cpp +++ b/arm9/source/ctrl_tbl.cpp @@ -12,9 +12,6 @@ struct ctrl_tbl ctrl; -#define SRAM_ADDR 0x0A000000 - - extern int carttype; #ifdef __cplusplus @@ -23,6 +20,8 @@ extern "C" { extern void _RamPG(void); extern void _RamSave(int bnk); +extern bool isOmega; +extern bool isSuperCard; #ifdef __cplusplus } @@ -35,14 +34,20 @@ void ctrl_get() { memset((u8*)&ctrl, 0, sizeof(struct ctrl_tbl)); - if(carttype != 5) { + if(carttype != 5 && !isSuperCard && !isOmega) { _RamPG(); ReadSram(SRAM_ADDR, (u8*)&ctrl, sizeof(struct ctrl_tbl)); _RamSave(0); return; } - sprintf(expfile, "%s/EXP128K.dat", ini.sign_dir); + if (isSuperCard) { + sprintf(expfile, "%s/SUPERCRD.dat", ini.sign_dir); + } else if (isOmega) { + sprintf(expfile, "%s/OMEGA.dat", ini.sign_dir); + } else { + sprintf(expfile, "%s/EXP128K.dat", ini.sign_dir); + } exp = fopen(expfile, "rb"); if(exp != NULL) { fread(&ctrl, 1, sizeof(struct ctrl_tbl), exp); @@ -53,15 +58,21 @@ void ctrl_get() { void ctrl_set() { FILE *exp; char expfile[64]; - - if(carttype != 5) { + + if(carttype != 5 && !isSuperCard && !isOmega) { _RamPG(); WriteSram(SRAM_ADDR, (u8*)&ctrl, sizeof(struct ctrl_tbl)); _RamSave(0); return; } - - sprintf(expfile, "%s/EXP128K.dat", ini.sign_dir); + + if (isSuperCard) { + sprintf(expfile, "%s/SUPERCRD.dat", ini.sign_dir); + } else if (isOmega) { + sprintf(expfile, "%s/OMEGA.dat", ini.sign_dir); + } else { + sprintf(expfile, "%s/EXP128K.dat", ini.sign_dir); + } exp = fopen(expfile, "wb"); if(exp != NULL) { fwrite(&ctrl, 1, sizeof(struct ctrl_tbl), exp); diff --git a/arm9/source/gba_patch.cpp b/arm9/source/gba_patch.cpp index 9b8bd92..7e1ccb2 100644 --- a/arm9/source/gba_patch.cpp +++ b/arm9/source/gba_patch.cpp @@ -780,108 +780,13 @@ void gba_check_int(char *name) { } } -u32 gba_check_Ram1(u8 *buf, u32 bufsize, u32 size, u32 ofs) { - u32 i, ii; - u32 *pbuf; - u32 oldtype; - - -// if(SaveType != 0) -// return(SaveSize); - if(PatchVer == PATCH_VER)return(SaveSize); - - pbuf = (u32*)buf; - if(PatchCnt > 1) { oldtype = PatchType[PatchCnt-1]/0x10; } else { oldtype = 0; } - - i = ofs; - for(ii = 0; ii < bufsize / 4; ii++) { - ii = _type_chk(pbuf, ii, i); - if(SaveType == 8)break; - - if(oldtype == 0 || oldtype == 2) { - ii = _eeprom_chk(pbuf, ii, i, size); - if(oldtype == 0) - oldtype = PatchType[PatchCnt-1]/0x10; - } - - if(oldtype == 0 || oldtype == 3) { - ii = _flash512_chk(pbuf, ii, i); - if(oldtype == 0) - oldtype = PatchType[PatchCnt-1]/0x10; - } - - if(oldtype == 0 || oldtype == 4) { - ii = _flash_chk(pbuf, ii, i); - if(oldtype == 0) - oldtype = PatchType[PatchCnt-1]/0x10; - } - - if(oldtype == 0 || oldtype == 5) { - ii = _flash1M_chk(pbuf, ii, i); - if(oldtype == 0) - oldtype = PatchType[PatchCnt-1]/0x10; - } - - if(oldtype == 0 || oldtype == 8) { - ii = _fmini_chk(pbuf, ii, i); - if(oldtype == 0) - oldtype = PatchType[PatchCnt-1]/0x10; - } - } - return(SaveSize); -} - - -static void _ReadPSram(uint32 address, u8* data , uint32 size ) { +static void _ReadPSram(uint32 address, u8* data, uint32 size) { u32 i; u16* pData = (u16*)data; u16* sData = (u16*)address; - for(i = 0; i < size / 2; i++)pData[i] = sData[i]; } -void gba_check_Ram2(u32 exp, u8 *buf, u32 bufsize, u32 size) { - u32 i, ii; - u32 *pbuf; - // int cnt; - - switch (SaveType) { - case 0: // UNKNOWN Famicom Mini - if(PatchCnt > 2 && PatchType[1] == 0x81 && PatchType[2] == 0x84) { - SaveType = 8; - PatchCnt = 3; - strcpy((char*)SaveVer, "FaMini"); - } - break; - case 8: - PatchType[PatchCnt] = 0x86; // Patch - PatchAddr[PatchCnt] = 0x100000 - 0x800; - PatchCnt++; - break; - } - - if(SaveType < 2 || PatchCnt <= 1 || SaveType == PatchType[1]/0x10)return; - - pbuf = (u32*)buf; - PatchCnt = 1; - for(i = 0; i < size; i += bufsize, exp += bufsize) { - _ReadPSram(exp, buf, bufsize+0x400); -// dmaCopy((void *)exp, buf, bufsize); -// dmaCopyWords(3, buf, (void *)exp, 0x100000); - // cnt = PatchCnt; - for(ii = 0; ii < bufsize / 4; ii++) { - switch (SaveType) { - case 2: ii = _eeprom_chk(pbuf, ii, i, size); break; - case 3: ii = _flash512_chk(pbuf, ii, i); break; - case 4: ii = _flash_chk(pbuf, ii, i); break; - case 5: ii = _flash1M_chk(pbuf, ii, i); break; - } - } -// if(PatchCnt > 1 && cnt == PatchCnt) -// break; - } -} - u32 gba_check(FILE *gbaFile, u32 size, u8 *buf, u32 bufsize) { u32 i, ii; u32 *pbuf; @@ -1706,7 +1611,6 @@ static void _patch_write(char *name) { fwrite(buf, 1, 256, sign); fclose(sign); - } void gba_patch_Ram(u32 exp, char *name, int cart) { @@ -1728,21 +1632,32 @@ void gba_patch_Ram(u32 exp, char *name, int cart) { fmini = 124; + u8 _OmegaPage = 0; + for(i = 1; i < PatchCnt; i++) { - - buf = (u8*)(exp + PatchAddr[i]); - - + // EZ Flash Omega and it's silly mapping schemes.... :P if (isOmega) { - if ((exp + PatchAddr[i]) > 0x09000000 && (exp + PatchAddr[i]) < 0x09800000) { + if ((exp + PatchAddr[i]) >= 0x08800000 && (exp + PatchAddr[i]) < 0x09000000) { + SetPSRampage(0); + _OmegaPage = 0; + } else if ((exp + PatchAddr[i]) >= 0x09000000 && (exp + PatchAddr[i]) < 0x09800000) { SetPSRampage(0x1000); - } else if ((exp + PatchAddr[i]) > 0x0A000000 && (exp + PatchAddr[i]) < 0x0A800000) { + _OmegaPage = 0x01; + } else if ((exp + PatchAddr[i]) >= 0x09800000 && (exp + PatchAddr[i]) < 0x0A000000) { SetPSRampage(0x2000); - } else if ((exp + PatchAddr[i]) > 0x0B000000 && (exp + PatchAddr[i]) < 0x0B800000) { + _OmegaPage = 0x02; + } else if ((exp + PatchAddr[i]) >= 0x0A000000 && (exp + PatchAddr[i]) < 0x0A800000) { SetPSRampage(0x3000); + _OmegaPage = 0x03; } } + + if (isOmega) { + buf = (u8*)((exp + PatchAddr[i]) - (_OmegaPage * 0x00800000)); + } else { + buf = (u8*)(exp + PatchAddr[i]); + } switch(SaveType) { case 2: // EEPROM @@ -1796,8 +1711,7 @@ void gba_patch_Ram(u32 exp, char *name, int cart) { case 5: // FLASH1M_V if(PatchType[i] == 0x51) { for(j = i + 1; j < PatchCnt; j++) { -// if(PatchType[j] == 0x56) -// savel = PatchAddr[j]; +// if(PatchType[j] == 0x56)savel = PatchAddr[j]; if(PatchType[j] == 0x58)break; } if (j < PatchCnt)V102 = false; @@ -1957,6 +1871,115 @@ void gba_patch_Ram(u32 exp, char *name, int cart) { if (isOmega)SetPSRampage(0); } +u32 gba_check_Ram1(u8 *buf, u32 bufsize, u32 size, u32 ofs) { + u32 i, ii; + u32 *pbuf; + u32 oldtype; + + +// if(SaveType != 0)return(SaveSize); + if(PatchVer == PATCH_VER)return(SaveSize); + + pbuf = (u32*)buf; + if(PatchCnt > 1) { oldtype = PatchType[PatchCnt-1]/0x10; } else { oldtype = 0; } + + i = ofs; + for(ii = 0; ii < bufsize / 4; ii++) { + ii = _type_chk(pbuf, ii, i); + if(SaveType == 8)break; + + if(oldtype == 0 || oldtype == 2) { + ii = _eeprom_chk(pbuf, ii, i, size); + if(oldtype == 0)oldtype = PatchType[PatchCnt-1]/0x10; + } + + if(oldtype == 0 || oldtype == 3) { + ii = _flash512_chk(pbuf, ii, i); + if(oldtype == 0)oldtype = PatchType[PatchCnt-1]/0x10; + } + + if(oldtype == 0 || oldtype == 4) { + ii = _flash_chk(pbuf, ii, i); + if(oldtype == 0)oldtype = PatchType[PatchCnt-1]/0x10; + } + + if(oldtype == 0 || oldtype == 5) { + ii = _flash1M_chk(pbuf, ii, i); + if(oldtype == 0)oldtype = PatchType[PatchCnt-1]/0x10; + } + + if(oldtype == 0 || oldtype == 8) { + ii = _fmini_chk(pbuf, ii, i); + if(oldtype == 0)oldtype = PatchType[PatchCnt-1]/0x10; + } + } + return(SaveSize); +} + +void gba_check_Ram2(u32 exp, u8 *buf, u32 bufsize, u32 size) { + u32 i, ii; + u32 *pbuf; + // int cnt; + + switch (SaveType) { + case 0: // UNKNOWN Famicom Mini + if(PatchCnt > 2 && PatchType[1] == 0x81 && PatchType[2] == 0x84) { + SaveType = 8; + PatchCnt = 3; + strcpy((char*)SaveVer, "FaMini"); + } + break; + case 8: + PatchType[PatchCnt] = 0x86; // Patch + PatchAddr[PatchCnt] = 0x100000 - 0x800; + PatchCnt++; + break; + } + + if(SaveType < 2 || PatchCnt <= 1 || SaveType == PatchType[1]/0x10)return; + + pbuf = (u32*)buf; + PatchCnt = 1; + + u16 OmegaPage = 0; + + for(i = 0; i < size; i += bufsize, exp += bufsize) { + if (isOmega) { + if (exp >= 0x09000000) { + OmegaPage += 0x1000; + SetPSRampage(OmegaPage); + exp = PSRAMBase_S98; + } + /*if (exp >= 0x08800000 && exp < 0x09000000) { + SetPSRampage(0); + } else if (exp >= 0x09000000 && exp < 0x09800000) { + SetPSRampage(0x1000); + } else if (exp >= 0x0A000000 && exp < 0x0A800000) { + SetPSRampage(0x2000); + } else if (exp >= 0x0B000000 && exp < 0x0B800000) { + SetPSRampage(0x3000); + }*/ + } + // u32 currentAddress = exp; + // if (isOmega && currentAddress >= 0x08800000 && _OmegaPage != 0)currentAddress = (currentAddress - (_OmegaPage * 0x00800000)); + _ReadPSram(exp, buf, bufsize+0x400); +// dmaCopy((void *)exp, buf, bufsize); +// dmaCopyWords(3, buf, (void *)exp, 0x100000); + // cnt = PatchCnt; + for(ii = 0; ii < bufsize / 4; ii++) { + switch (SaveType) { + case 2: ii = _eeprom_chk(pbuf, ii, i, size); break; + case 3: ii = _flash512_chk(pbuf, ii, i); break; + case 4: ii = _flash_chk(pbuf, ii, i); break; + case 5: ii = _flash1M_chk(pbuf, ii, i); break; + } + } +// if(PatchCnt > 1 && cnt == PatchCnt) +// break; + if (isOmega)SetPSRampage(0); + } +} + void gba_patch(u8 *buf, u32 add, u32 bufsize, int GBAmode, char *name) { int i, j; diff --git a/arm9/source/gba_patch.h b/arm9/source/gba_patch.h index 77e8861..5c16397 100644 --- a/arm9/source/gba_patch.h +++ b/arm9/source/gba_patch.h @@ -3,12 +3,13 @@ extern "C" { #endif extern void gba_check_int(char *name); -extern u32 gba_check_Ram1(u8 *buf, u32 bufsize, u32 size, u32 ofs); -extern void gba_check_Ram2(u32 exp, u8 *buf, u32 bufsize, u32 size); -extern u32 gba_check(FILE *gbaFile, u32 size, u8 *buf, u32 bufsize); extern void gba_patch_Ram(u32 exp, char *name, int cart); +extern u32 gba_check(FILE *gbaFile, u32 size, u8 *buf, u32 bufsize); +extern u32 gba_check_Ram1(u8 *buf, u32 bufsize, u32 size, u32 ofs); +extern void gba_check_Ram2(u32 exp, u8 *buf, u32 bufsize, u32 size); extern void gba_patch(u8 *buf, u32 add, u32 bufsize, int GBAmode, char *name); #ifdef __cplusplus } #endif + diff --git a/arm9/source/gbaldr.itcm.cpp b/arm9/source/gbaldr.itcm.cpp index 34a36d6..f424262 100644 --- a/arm9/source/gbaldr.itcm.cpp +++ b/arm9/source/gbaldr.itcm.cpp @@ -25,6 +25,8 @@ //#include #include "dsCard.h" +#include "sc_patches.h" +#include "sc_sram.h" //#include //basic print funcionality @@ -34,7 +36,6 @@ #define SRAM_PAGE_SIZE 0x1000 // SRAM Page Size #define MAX_SRAM 0x80000 // 4MBit/512KByte total SRAM -#define SRAM_ADDR 0x0A000000 #define USE_SRAM 0x20000 // 128KByte #define USE_SRAM_PG 48 // 0x0A030000-0A031FFF #define USE_SRAM_PG_EZ4 11 // 0x0A008000-0A00FFFF @@ -45,7 +46,6 @@ #define USE_SRAM_NOR 16 // 0x0A010000-0A02FFFF -#define USE_SRAM_PSR_Omega 160 #define USE_SRAM_PSR 50 // 0x0A032000-0A051FFF #define USE_SRAM_PSR_EZ4 16 // 0x0A010000-0A02FFFF #define USE_SRAM_PSR_EWN 8 // 0x0A000000-0A01FFFF @@ -60,6 +60,8 @@ extern "C" { #endif +extern void turn_off(int cmd); +extern void dsp_bar(int mod, int per); extern char curpath[]; extern int sortfile[]; @@ -404,13 +406,22 @@ void _RamPG() { SetM3Ram(USE_SRAM_PG_M3); return; } - SetRampage(USE_SRAM_PG); + if (isOmega) { + // Omega_Bank_Switching(0); + // SetRampage(0x20); + SetRampage(0x40); + // SetRampage(USE_SRAM_PG); + + } else { + SetRampage(USE_SRAM_PG); + } + // SetRampage(USE_SRAM_PG); return; } void _RamSave(int bnk) { if (isSuperCard)return; - if (isOmega)return; + // if (isOmega)return; switch (carttype) { case 3: SetRampage(USE_SRAM_PSR_EZ4 + bnk * 16); @@ -427,11 +438,17 @@ void _RamSave(int bnk) { if(GBAmode == 0) { if (isOmega) { - SetRampage(bnk * 16); + SetRampage(bnk * 0x10); + /*switch (bnk) { + case 0: SetRampage(0); break; + case 1: SetRampage(0x10); break; + default: return; + }*/ } else { SetRampage(USE_SRAM_PSR + bnk * 16); } - } else { + } else { + if (isOmega)return; SetRampage(USE_SRAM_NOR + bnk * 16); } return; @@ -484,9 +501,9 @@ int checkFlashID() { SetSDControl(0); Set_RTC_status(1); gl_ingame_RTC_open_status = Read_SET_info(13); - if( (gl_ingame_RTC_open_status != 0x0) && (gl_ingame_RTC_open_status != 0x1))gl_ingame_RTC_open_status = 0x1; - Omega_Bank_Switching(0); - Set_AUTO_save(0); + if ((gl_ingame_RTC_open_status != 0x0) && (gl_ingame_RTC_open_status != 0x1))gl_ingame_RTC_open_status = 0x1; + // Set_AUTO_save(0); + // Omega_Bank_Switching(0); return carttype; case 0x227E0000: // SuperCard carttype = 6; @@ -641,13 +658,12 @@ bool checkBackup() { void writeSramToFile(char *savename) { - FILE *saver; + FILE *saver; u32 len; if(savename[0] == 0) return; -// if((GBAmode == 0) && (checkBackup() == false)) -// return; +// if((GBAmode == 0) && (checkBackup() == false))return; // getSaveFilename(filename, tbuf); sprintf(tbuf, "%s/%s", ini.save_dir, savename); @@ -656,16 +672,17 @@ void writeSramToFile(char *savename) { // OpenNorWrite(); _RamSave(0); - - ReadSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); + + if (isOmega) { ReadSram(SRAM_ADDR_OMEGA, rwbuf, USE_SRAM / 2); } else { ReadSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); } + if(saver != NULL) { len = USE_SRAM / 2; if(len > savesize)len = savesize; fwrite(rwbuf, 1, len, saver); } - if(savesize > USE_SRAM / 2) { + if((savesize > (USE_SRAM / 2)) && !isSuperCard) { _RamSave(1); - ReadSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); + if (isOmega) { ReadSram(SRAM_ADDR_OMEGA, rwbuf, USE_SRAM / 2); } else { ReadSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); } if(saver != NULL)fwrite(rwbuf, 1, USE_SRAM / 2, saver); } fclose(saver); @@ -688,32 +705,63 @@ void SRAMdump(int cmd) { mx = 8; switch (carttype) { + case 1: + if (isOmega)mx = 2; + break; case 4: mx = 4; break; case 5: mx = 2; break; - case 6: mx = 16; break; - } + case 6: + if (isSuperCard) { mx = 1; } else { mx = 16; } + break; + } sprintf(name, "%s/SRAM.BIN", ini.save_dir); + if(cmd == 0) { + dsp_bar(4, -1); dmp = fopen(name, "wb"); for(i = 0; i < mx; i++) { - if(carttype == 6) { + if(carttype == 6 && !isSuperCard) { SetM3Ram(i); - } else { - if((carttype >= 4) && !isSuperCard) { + } else if (!isSuperCard) { + if((carttype >= 4)) { SetEWINRam(8 + i); } else { - if (isOmega && (i > 4))Omega_Bank_Switching(0x01); + // if (isOmega && (i > 4))Omega_Bank_Switching(1); SetRampage(i * 16); } } - ReadSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); + + if (isOmega) { ReadSram(SRAM_ADDR_OMEGA, rwbuf, USE_SRAM / 2); } else { ReadSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); } + if(dmp != NULL)fwrite(rwbuf, 1, USE_SRAM / 2, dmp); + + if (i == 0) { + dsp_bar(4, 0); + } else { + switch (mx) { + case 2: + if (i == 1) { dsp_bar(4, 50); } else if (i == 2) { dsp_bar(4, 100); } + break; + case 4: + if (i == 1) { dsp_bar(4, 25); } else if (i == 2) { dsp_bar(4, 50); } else if (i == 3) { dsp_bar(4, 75); } else if (i == 4) { dsp_bar(4, 100); } + break; + case 8: + if (i == 2) { dsp_bar(4, 25); } else if (i == 4) { dsp_bar(4, 50); } else if (i == 6) { dsp_bar(4, 75); } else if (i == 8) { dsp_bar(4, 100); } + break; + case 16: + if (i == 4) { dsp_bar(4, 25); } else if (i == 8) { dsp_bar(4, 50); } else if (i == 12) { dsp_bar(6, 75); } else if (i == 16) { dsp_bar(8, 100); } + break; + } + } } } else { + dsp_bar(5, -1); dmp = fopen(name, "rb"); if((carttype < 4) && !isSuperCard && !isOmega && !is3in1Plus)OpenNorWrite(); + if (isOmega)Omega_Bank_Switching(0); + for(i = 0; i < mx; i++) { memset(rwbuf, 0, USE_SRAM / 2); if(dmp != NULL) @@ -724,18 +772,36 @@ void SRAMdump(int cmd) { if((carttype >= 4) && !isSuperCard) { SetEWINRam(8 + i); } else { - if (isOmega && (i > 4))Omega_Bank_Switching(0x01); + // if (isOmega && (i > 4))Omega_Bank_Switching(1); SetRampage(i * 16); } } - WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); + if (isOmega) { WriteSram(SRAM_ADDR_OMEGA, rwbuf, USE_SRAM / 2); } else { WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); } + if (i == 0) { + dsp_bar(5, 0); + } else { + switch (mx) { + case 2: + if (i == 1) { dsp_bar(5, 50); } else if (i == 2) { dsp_bar(5, 100); } + break; + case 4: + if (i == 1) { dsp_bar(5, 25); } else if (i == 2) { dsp_bar(5, 50); } else if (i == 3) { dsp_bar(5, 75); } else if (i == 4) { dsp_bar(5, 100); } + break; + case 8: + if (i == 2) { dsp_bar(5, 25); } else if (i == 4) { dsp_bar(5, 50); } else if (i == 6) { dsp_bar(5, 75); } else if (i == 8) { dsp_bar(5, 100); } + break; + case 16: + if (i == 4) { dsp_bar(5, 25); } else if (i == 8) { dsp_bar(5, 50); } else if (i == 12) { dsp_bar(5, 75); } else if (i == 16) { dsp_bar(5, 100); } + break; + } + } } - if((carttype < 4) && !isSuperCard && !isOmega && !is3in1Plus)CloseNorWrite(); } fclose(dmp); - if (isOmega)Omega_Bank_Switching(0); + // if (isOmega)Omega_Bank_Switching(0); _RamSave(0); + dsp_bar(-1, 100); } void blankSRAM(char *savename) { @@ -745,11 +811,16 @@ void blankSRAM(char *savename) { if((carttype < 4) && !isSuperCard && !isOmega && !is3in1Plus)OpenNorWrite(); _RamSave(0); - WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); + + if (isOmega)Omega_Bank_Switching(0); + + if (isOmega) { WriteSram(SRAM_ADDR_OMEGA, rwbuf, USE_SRAM / 2); } else { WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); } // if(carttype != 5) { - _RamSave(1); - WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); + if (!isSuperCard) { + _RamSave(1); + if (isOmega) { WriteSram(SRAM_ADDR_OMEGA, rwbuf, USE_SRAM / 2); } else { WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); } + } // } ctrl.save_siz[GBAmode] = savesize; @@ -776,7 +847,6 @@ void writeSramFromFile(char *savename) { return; } - if((carttype < 4) && !isSuperCard && !isOmega && !is3in1Plus)OpenNorWrite(); ctrl.save_siz[GBAmode] = savesize; @@ -791,14 +861,17 @@ void writeSramFromFile(char *savename) { memset(rwbuf, 0xFF, USE_SRAM / 2); fread(rwbuf, 1, USE_SRAM / 2, saver); - WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); + + if (isOmega)Omega_Bank_Switching(0); + + if (isOmega) { WriteSram(SRAM_ADDR_OMEGA, rwbuf, USE_SRAM / 2); } else { WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); } // if(carttype != 5) { - if(savesize > USE_SRAM / 2) { + if((savesize > (USE_SRAM / 2)) && !isSuperCard) { _RamSave(1); memset(rwbuf, 0xFF, USE_SRAM / 2); fread(rwbuf, 1, USE_SRAM / 2, saver); - WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); + if (isOmega) { WriteSram(SRAM_ADDR_OMEGA, rwbuf, USE_SRAM / 2); } else { WriteSram(SRAM_ADDR, rwbuf, USE_SRAM / 2); } _RamSave(0); } // } @@ -809,7 +882,7 @@ void writeSramFromFile(char *savename) { } -void _ReadPSram(uint32 address, u8* data , uint32 size) { +/*void _ReadPSram(uint32 address, u8* data , uint32 size) { u32 i; u16* pData = (u16*)data; u16* sData = (u16*)address; @@ -817,7 +890,7 @@ void _ReadPSram(uint32 address, u8* data , uint32 size) { for(i = 0; i < size / 2; i++)pData[i] = sData[i]; } -/*void _WritePSram(uint32 address, u8* data , uint32 size) { +void _WritePSram(uint32 address, u8* data , uint32 size) { u32 i; u16* sData = (u16*)data; u16* pData = (u16*)address; @@ -826,10 +899,6 @@ void _ReadPSram(uint32 address, u8* data , uint32 size) { }*/ -extern void turn_off(int cmd); -extern void dsp_bar(int mod, int per); - - int writeFileToNor(int sel) { FILE *gbaFile; char savName[512]; @@ -912,9 +981,14 @@ int writeFileToNor(int sel) { CloseNorWrite(); + dsp_bar(5, -1); // getSaveFilename(sel, savName); if(cmd >= 0) { writeSramFromFile(savName); } else { blankSRAM(savName); } + dsp_bar(5, 100); + + for (int i = 0; i < 30; i++)swiWaitForVBlank(); + dsp_bar(-1, 100); // SetRampage(USE_SRAM_NOR); return(0); @@ -934,7 +1008,7 @@ int writeFileToRam(int sel) { if (carttype >= 3) { fsz = MAX_NOR; } else if (isOmega) { fsz = MAX_NOR; } else { fsz = MAX_PSRAM; } - if (carttype >= 4) { exp = 0x08000000; } else if (isOmega) { exp = 0x08800000; } else { exp = 0x08060000; } + if (carttype >= 4) { exp = FlashBase; } else if (isOmega) { exp = PSRAMBase_S98; } else { exp = 0x08060000; } exps = exp; @@ -949,7 +1023,7 @@ int writeFileToRam(int sel) { sprintf(tbuf, "%s%s", curpath, fs[sel].filename); gbaFile = fopen(tbuf, "rb"); - if(gbaFile == NULL) return(0); + if (gbaFile == NULL)return 0; strcpy(savName, fs[sel].filename); cmd = save_sel(0, savName); @@ -977,18 +1051,18 @@ int writeFileToRam(int sel) { if(siz == 0 && gba)header_rep(rwbuf); - savesize = gba_check_Ram1(rwbuf, 0x100000, fs[sel].filesize, siz); - + if (!isOmega)savesize = gba_check_Ram1(rwbuf, 0x100000, fs[sel].filesize, siz); + + // EZ Flash Omega and it's silly mapping schemes.... :P if (isOmega) { if (exp >= 0x09000000) { PSRamPage += 0x1000; SetPSRampage(PSRamPage); - exp = 0x08800000; + exp = PSRAMBase_S98; } } // _WritePSram(exp, rwbuf, 0x100000); - dmaCopy((void*)rwbuf, (void*)exp, 0x100000); // dmaCopyWords(3, rwbuf, (void *)exp, 0x100000); } @@ -998,9 +1072,32 @@ int writeFileToRam(int sel) { if (isOmega)SetPSRampage(0); dsp_bar(2, 100); - gba_check_Ram2(exps, rwbuf, 0x100000, fs[sel].filesize); - gba_patch_Ram(exps, fs[sel].filename, carttype); - + + bool allowPatches = true; + + if (isSuperCard) { + dsp_bar(-1, 100); + dsp_bar(3, -1); + dsp_bar(3, 25); + patchGeneralWhiteScreen(fs[sel].filesize); + allowPatches = patchSpecificGame(); + dsp_bar(3, 50); + romSize = fs[sel].filesize; + const struct save_type* saveType = allowPatches ? save_findTag() : NULL; + dsp_bar(3, 75); + if (saveType != NULL && saveType->patchFunc != NULL)saveType->patchFunc(saveType); + dsp_bar(3, 100); + for (int I = 0; I < 50; I++)swiWaitForVBlank(); + dsp_bar(-1, 100); + } else { + gba_check_Ram2(exps, rwbuf, 0x100000, fs[sel].filesize); + dsp_bar(-1, 100); + } + + dsp_bar(5, -1); + + if (!isSuperCard)gba_patch_Ram(exps, fs[sel].filename, carttype); + fclose(gbaFile); @@ -1010,10 +1107,11 @@ int writeFileToRam(int sel) { // } // getSaveFilename(sel, savName); + + dsp_bar(5, 50); + if(cmd >= 0) { writeSramFromFile(savName); } else { blankSRAM(savName); } - - dsp_bar(-1, 100); - + if((carttype < 4) && !isSuperCard && !isOmega)CloseNorWrite(); _RamSave(0); @@ -1022,19 +1120,24 @@ int writeFileToRam(int sel) { if(carttype == 6) { Close_M3(); } else { Close_EWIN(); } } + dsp_bar(5, 100); + + for (int i = 0; i < 30; i++)swiWaitForVBlank(); + + dsp_bar(-1, 100); + if (isSuperCard)return 0; if (isOmega) { Set_RTC_status(gl_ingame_RTC_open_status); + rtc_toggle(true); + // Omega_InitFatBuffer(0x10); SetRompage(0x200); return 0; } - if(carttype == 3) { - SetRompage(0x300); - } else if(carttype <= 2) { - SetRompage(384); - } + if (carttype == 3) { SetRompage(0x300); } else if (carttype <= 2) { SetRompage(384); } + return 0; } diff --git a/arm9/source/main.c b/arm9/source/main.c index 883bc89..b00af7b 100644 --- a/arm9/source/main.c +++ b/arm9/source/main.c @@ -882,9 +882,19 @@ int gba_sel() { if(GBAmode == 1) { if(checkSRAM(filename)) { // if(cnf_inp(3, 4) & KEY_A) - if(save_sel(0, filename) >= 0)writeSramFromFile(filename); + if(save_sel(0, filename) >= 0) { + dsp_bar(5, -1); + swiWaitForVBlank(); + dsp_bar(5, 50); + writeSramFromFile(filename); + dsp_bar(5, 100); + for (int I = 0; I < 50; I++)swiWaitForVBlank(); + dsp_bar(-1, 100); + } _gba_sel_dsp(sel, yc, 0); - } else err_cnf(4, 5); + } else { + err_cnf(4, 5); + } } else { if(cnf_inp(5, 6) & KEY_A) { SRAMdump(1); @@ -930,7 +940,15 @@ int gba_sel() { if(ky & KEY_B) { if(checkSRAM(filename)) { // if(cnf_inp(1, 2) & KEY_A) { - if(save_sel(1, filename) >= 0)writeSramToFile(filename); + if(save_sel(1, filename) >= 0) { + dsp_bar(4, -1); + swiWaitForVBlank(); + dsp_bar(4, 50); + writeSramToFile(filename); + dsp_bar(4, 100); + for (int I = 0; I < 50; I++)swiWaitForVBlank(); + dsp_bar(-1, 100); + } _gba_sel_dsp(sel, yc, 0); } else { err_cnf(4, 5); @@ -1096,7 +1114,15 @@ inp_key(); GBAmode = 0; if(checkSRAM(filename) && checkBackup()) { + dsp_bar(4, -1); + dsp_bar(4, 0); + for (int I = 0; I < 30; I++)swiWaitForVBlank(); if(save_sel(1, filename) >= 0)writeSramToFile(filename); + dsp_bar(4, 50); + for (int I = 0; I < 30; I++)swiWaitForVBlank(); + dsp_bar(4, 100); + for (int I = 0; I < 30; I++)swiWaitForVBlank(); + dsp_bar(-1, 100); } getGBAmode(); diff --git a/arm9/source/message.cpp b/arm9/source/message.cpp index 7705341..3f88b1a 100644 --- a/arm9/source/message.cpp +++ b/arm9/source/message.cpp @@ -5,7 +5,7 @@ char *errmsg[16]; char *cnfmsg[11]; -char *barmsg[4]; +char *barmsg[6]; char *cmd_m[4]; char *t_msg[22]; char *savmsg[6]; @@ -78,18 +78,22 @@ static const char *cnfmsg_e[11] = { }; -static const char *barmsg_j[4] = { +static const char *barmsg_j[6] = { " NOR傪徚嫀拞... ", // 0 " NOR偵僐僺乕拞... ", // 1 " RAM偵儘乕僪拞... ", // 2 - " ROM傪夝愅拞... " // 3 + " ROM傪夝愅拞... ", // 3 + " SRAM偺撉傒庢傝 ", // 4 + " SRAM傊偺彂偒崬傒 " // 5 }; -static const char *barmsg_e[4] = { +static const char *barmsg_e[6] = { " Erasing NOR... ", // 0 " Copying to NOR... ", // 1 " Loading to RAM... ", // 2 - " Analyzing ROM... " // 3 + " Analyzing ROM... ", // 3 + " Reading SRAM... ", // 4 + " Writing SRAM... " // 5 }; @@ -187,7 +191,7 @@ void setLangMsg() { if(UserLang != 0) { for(i = 0; i < 16; i++)errmsg[i] = (char*)errmsg_e[i]; for(i = 0; i < 11; i++)cnfmsg[i] = (char*)cnfmsg_e[i]; - for(i = 0; i < 4; i++)barmsg[i] = (char*)barmsg_e[i]; + for(i = 0; i < 6; i++)barmsg[i] = (char*)barmsg_e[i]; for(i = 0; i < 4; i++)cmd_m[i] = (char*)cmd_m_e[i]; for(i = 0; i < 22; i++)t_msg[i] = (char*)t_msg_e[i]; for(i = 0; i < 6; i++)savmsg[i] = (char*)savmsg_e[i]; @@ -196,7 +200,7 @@ void setLangMsg() { for(i = 0; i < 16; i++)errmsg[i] = (char*)errmsg_j[i]; for(i = 0; i < 11; i++)cnfmsg[i] = (char*)cnfmsg_j[i]; - for(i = 0; i < 4; i++)barmsg[i] = (char*)barmsg_j[i]; + for(i = 0; i < 6; i++)barmsg[i] = (char*)barmsg_j[i]; for(i = 0; i < 4; i++)cmd_m[i] = (char*)cmd_m_j[i]; for(i = 0; i < 22; i++)t_msg[i] = (char*)t_msg_j[i]; for(i = 0; i < 6; i++)savmsg[i] = (char*)savmsg_j[i];