mirror of
https://github.com/ApacheThunder/SCKILL.git
synced 2025-06-19 03:25:32 -04:00
Add waitstate patching from ArcheyChen loader, SRAM patch not working
This commit is contained in:
parent
d2c9722f25
commit
15e8930321
191
SCFW_Kernel_GBA/source/EepromSave.c
Normal file
191
SCFW_Kernel_GBA/source/EepromSave.c
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
#include "find.h"
|
||||||
|
#include "Save.h"
|
||||||
|
#include "EepromSave.h"
|
||||||
|
|
||||||
|
extern u32 romSize;
|
||||||
|
|
||||||
|
//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;
|
||||||
|
}
|
7
SCFW_Kernel_GBA/source/EepromSave.h
Normal file
7
SCFW_Kernel_GBA/source/EepromSave.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Save.h"
|
||||||
|
|
||||||
|
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);
|
358
SCFW_Kernel_GBA/source/FlashSave.c
Normal file
358
SCFW_Kernel_GBA/source/FlashSave.c
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
#include "find.h"
|
||||||
|
#include "Save.h"
|
||||||
|
#include "FlashSave.h"
|
||||||
|
|
||||||
|
extern u32 romSize;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
9
SCFW_Kernel_GBA/source/FlashSave.h
Normal file
9
SCFW_Kernel_GBA/source/FlashSave.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Save.h"
|
||||||
|
|
||||||
|
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);
|
86
SCFW_Kernel_GBA/source/Save.c
Normal file
86
SCFW_Kernel_GBA/source/Save.c
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include <gba.h>
|
||||||
|
#include "EepromSave.h"
|
||||||
|
#include "FlashSave.h"
|
||||||
|
#include "Save.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
u32 romSize;
|
||||||
|
|
||||||
|
#define SAVE_TYPE_COUNT 25
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void twoByteCpy(u16 *dst, const u16 *src, u32 size){
|
||||||
|
size >>= 1;
|
||||||
|
while(size--){
|
||||||
|
*dst = *src;
|
||||||
|
dst++;
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
}
|
63
SCFW_Kernel_GBA/source/Save.h
Normal file
63
SCFW_Kernel_GBA/source/Save.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// #ifdef __cplusplus
|
||||||
|
// extern "C" {
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern u32 romSize;
|
||||||
|
const struct save_type* save_findTag();
|
||||||
|
|
||||||
|
void twoByteCpy(u16 *dst, const u16 *src, u32 size);
|
||||||
|
// #ifdef __cplusplus
|
||||||
|
// }
|
||||||
|
// #endif
|
487
SCFW_Kernel_GBA/source/WhiteScreenPatch.c
Normal file
487
SCFW_Kernel_GBA/source/WhiteScreenPatch.c
Normal file
@ -0,0 +1,487 @@
|
|||||||
|
#include "gba.h"
|
||||||
|
#include "Save.h"
|
||||||
|
extern u32 romSize;
|
||||||
|
extern bool savingAllowed;
|
||||||
|
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 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void 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;
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
}
|
5
SCFW_Kernel_GBA/source/WhiteScreenPatch.h
Normal file
5
SCFW_Kernel_GBA/source/WhiteScreenPatch.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void patchGeneralWhiteScreen();
|
||||||
|
|
||||||
|
void patchSpecificGame();
|
20
SCFW_Kernel_GBA/source/find.h
Normal file
20
SCFW_Kernel_GBA/source/find.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef FIND_H
|
||||||
|
#define FIND_H
|
||||||
|
|
||||||
|
#include <gba.h>
|
||||||
|
|
||||||
|
// #ifdef __cplusplus
|
||||||
|
// extern "C" {
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// COMMON
|
||||||
|
//u8* memsearch(const u8* start, u32 dataSize, const u8* find, u32 findSize);
|
||||||
|
u32* memsearch32(const u32* start, u32 dataSize, const u32* find, u32 findSize, bool forward);
|
||||||
|
u16* memsearch16(const u16* start, u32 dataSize, const u16* find, u32 findSize, bool forward);
|
||||||
|
u8* memsearch8(const u8* start, u32 dataSize, const u8* find, u32 findSize, bool forward);
|
||||||
|
|
||||||
|
// #ifdef __cplusplus
|
||||||
|
// }
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
#endif // FIND_H
|
130
SCFW_Kernel_GBA/source/find_common.c
Normal file
130
SCFW_Kernel_GBA/source/find_common.c
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
//#include <string.h> // memcmp
|
||||||
|
#include <stddef.h> // NULL
|
||||||
|
#include <gba.h>
|
||||||
|
//#include <limits.h>
|
||||||
|
|
||||||
|
// (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Boyer-Moore Horspool algorithm
|
||||||
|
*/
|
||||||
|
/*u8* memsearch(const u8* start, u32 dataSize, const u8* find, u32 findSize) {
|
||||||
|
u32 dataLen = dataSize/sizeof(u8);
|
||||||
|
u32 findLen = findSize/sizeof(u8);
|
||||||
|
|
||||||
|
u32 table[TABLE_SIZE];
|
||||||
|
|
||||||
|
// Preprocessing
|
||||||
|
for (u32 i = 0; i < TABLE_SIZE; ++i) {
|
||||||
|
table[i] = findLen;
|
||||||
|
}
|
||||||
|
for (u32 i = 0; i < findLen - 1; ++i) {
|
||||||
|
table[find[i]] = findLen - i - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Searching
|
||||||
|
u32 j = 0;
|
||||||
|
while (j <= dataLen - findLen) {
|
||||||
|
u8 c = start[j + findLen - 1];
|
||||||
|
if (find[findLen - 1] == c && memcmp(find, start + j, findLen - 1) == 0) {
|
||||||
|
return (u8*)start + j;
|
||||||
|
}
|
||||||
|
j += table[c];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quick Search algorithm
|
||||||
|
*/
|
||||||
|
/*u8* memsearch(const u8* start, u32 dataSize, const u8* find, u32 findSize) {
|
||||||
|
u32 dataLen = dataSize/sizeof(u8);
|
||||||
|
u32 findLen = findSize/sizeof(u8);
|
||||||
|
|
||||||
|
u32 table[TABLE_SIZE];
|
||||||
|
|
||||||
|
// Preprocessing
|
||||||
|
for (u32 i = 0; i < TABLE_SIZE; ++i) {
|
||||||
|
table[i] = findLen + 1;
|
||||||
|
}
|
||||||
|
for (u32 i = 0; i < findLen; ++i) {
|
||||||
|
table[find[i]] = findLen - i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Searching
|
||||||
|
u32 j = 0;
|
||||||
|
while (j <= dataLen - findLen) {
|
||||||
|
if (memcmp(find, start + j, findLen) == 0) {
|
||||||
|
return (u8*)start + j;
|
||||||
|
}
|
||||||
|
j += table[start[j + findLen]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}*/
|
@ -7,6 +7,9 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#include "Save.h"
|
||||||
|
#include "WhiteScreenPatch.h"
|
||||||
|
|
||||||
char *stpcpy(char*, char*);
|
char *stpcpy(char*, char*);
|
||||||
|
|
||||||
void tryAgain() {
|
void tryAgain() {
|
||||||
@ -76,6 +79,7 @@ void sc_mode(u32 mode)
|
|||||||
EWRAM_DATA u8 filebuf[0x4000];
|
EWRAM_DATA u8 filebuf[0x4000];
|
||||||
|
|
||||||
u32 pressed;
|
u32 pressed;
|
||||||
|
bool savingAllowed;
|
||||||
|
|
||||||
void setLastPlayed(char *path) {
|
void setLastPlayed(char *path) {
|
||||||
/*
|
/*
|
||||||
@ -146,6 +150,22 @@ void selectFile(char *path) {
|
|||||||
fclose(lastSaved);
|
fclose(lastSaved);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iprintf("Applying patches...\n");
|
||||||
|
sc_mode(SC_RAM_RW);
|
||||||
|
patchGeneralWhiteScreen();
|
||||||
|
patchSpecificGame();
|
||||||
|
|
||||||
|
printf("White Screen patch done!\nNow patching Save\n");
|
||||||
|
|
||||||
|
const struct save_type* saveType = savingAllowed ? save_findTag() : NULL;
|
||||||
|
if (saveType != NULL && saveType->patchFunc != NULL){
|
||||||
|
bool done = saveType->patchFunc(saveType);
|
||||||
|
if(!done)
|
||||||
|
printf("Save Type Patch Error\n");
|
||||||
|
}else{
|
||||||
|
printf("No need to patch\n");
|
||||||
|
}
|
||||||
|
|
||||||
iprintf("Let's go.\n");
|
iprintf("Let's go.\n");
|
||||||
setLastPlayed(path);
|
setLastPlayed(path);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user