diff --git a/include/arm9/arm7_stub.h b/include/arm9/arm7_stub.h index 5628660..91b5e22 100644 --- a/include/arm9/arm7_stub.h +++ b/include/arm9/arm7_stub.h @@ -5,4 +5,5 @@ extern const u32 _arm7_stub_start[]; +extern const u32 _arm7_stub_swi[]; extern const u32 _arm7_stub_end[]; diff --git a/include/arm9/hardware/lgy.h b/include/arm9/hardware/lgy.h index f7c9c7c..749fb6a 100644 --- a/include/arm9/hardware/lgy.h +++ b/include/arm9/hardware/lgy.h @@ -2,5 +2,5 @@ -void LGY_prepareLegacyMode(void); +void LGY_prepareLegacyMode(bool gbaBios); void LGY_backupGbaSave(void); diff --git a/include/ipc_handler.h b/include/ipc_handler.h index 8d6ca0e..c4c4c96 100644 --- a/include/ipc_handler.h +++ b/include/ipc_handler.h @@ -33,7 +33,7 @@ typedef enum { - IPC_CMD9_PREPARE_AGB = MAKE_CMD(0, 0, 0, 0), + IPC_CMD9_PREPARE_AGB = MAKE_CMD(0, 0, 0, 1), IPC_CMD9_PREPARE_POWER = MAKE_CMD(1, 0, 0, 0) } IpcCmd9; diff --git a/source/arm11/hardware/lgy.c b/source/arm11/hardware/lgy.c index 9c7ecd6..8aadfa5 100644 --- a/source/arm11/hardware/lgy.c +++ b/source/arm11/hardware/lgy.c @@ -34,7 +34,8 @@ static void lgySleepIrqHandler(u32 intSource) void LGY_prepareLegacyMode(void) { - PXI_sendCmd(IPC_CMD9_PREPARE_AGB, NULL, 0); + const u32 cmdBuf = false; + PXI_sendCmd(IPC_CMD9_PREPARE_AGB, &cmdBuf, 1); LGYFB_init(); diff --git a/source/arm9/arm7_stub.s b/source/arm9/arm7_stub.s index 5471e1b..4645e3d 100644 --- a/source/arm9/arm7_stub.s +++ b/source/arm9/arm7_stub.s @@ -3,56 +3,51 @@ .fpu softvfp .global _arm7_stub_start +.global _arm7_stub_swi .global _arm7_stub_end .type _arm7_stub_start %function -.type gbaReset %function -.type waitCycles %function .align 2 +@ Must be located at 0x3007E00. _arm7_stub_start: mov r0, #0xD3 + adr r1, _arm7_stub_start + 0x200 @ 0x3008000 msr CPSR_cxsf, r0 - ldr sp, =0x03008000 mov r0, #0xD2 + mov sp, r1 msr CPSR_cxsf, r0 - ldr sp, =0x03007FA0 mov r0, #0xDF + sub sp, r1, #0x60 @ 0x3007FA0 msr CPSR_cxsf, r0 - ldr sp, =0x03007F80 - mov r3, #0x04700000 - mov r0, #1 - str r0, [r3] @ Disable BIOS overlay. - mov r0, #0x100 - bl waitCycles - ldr r0, =0x1999E8 - bl waitCycles + mov r3, #0x4700000 + adr r2, _arm7_stub_16 + 1 + sub sp, r1, #0x80 @ 0x3007F80 + bx r2 - ldr r3, =0x04000006 @ REG_VCOUNT +.thumb +_arm7_stub_16: + mov r0, #1 + str r0, [r3] @ Disable BIOS overlay. + @ The original ARM7 stub waits 256 cycles here (for the BIOS overlay disable?). + @ The original ARM7 stub waits 1677800 cycles (100 ms) here. + + lsl r3, r0, #26 @ 0x4000000 wait_vcount_160_lp: - ldrb r0, [r3] - cmp r0, #160 @ Wait for REG_VCOUNT = 160. + ldrb r0, [r3, #6] @ REG_VCOUNT + cmp r0, #160 @ Wait for REG_VCOUNT == 160. bne wait_vcount_160_lp + mov r4, r3 @ Needed for function call 0xBC below. mov r0, #0xFF - bl gbaReset +_arm7_stub_swi: + swi 0x10 @ RegisterRamReset + @swi 0x26 @ HardReset (BIOS animation) + mov r0, #0xBC mov r2, #0 - mov r4, #0x04000000 - mov lr, #0xBC - bx lr + bx r0 .pool - -gbaReset: - swi 0x10000 @ RegisterRamReset - @swi 0x260000 @ HardReset - bx lr - - -waitCycles: - subs r0, r0, #4 - bcs waitCycles - bx lr - +.align 2 _arm7_stub_end: diff --git a/source/arm9/hardware/lgy.c b/source/arm9/hardware/lgy.c index 69ff7bc..d00bb2d 100644 --- a/source/arm9/hardware/lgy.c +++ b/source/arm9/hardware/lgy.c @@ -22,8 +22,12 @@ #define REGs_LGY_GBA_SAVE_TIMING ((vu32*)(LGY_REGS_BASE + 0x120)) -#define MAX_ROM_SIZE (1024u * 1024u * 32u) -#define MAX_SAVE_SIZE (1024u * 128u) +#define MAX_ROM_SIZE (1024u * 1024u * 32u) +#define MAX_SAVE_SIZE (1024u * 128u) +#define ARM7_STUB_LOC (0x3007E00u) +#define ARM7_STUB_LOC9 (0x80BFE00u) +#define ROM_LOC (0x20000000u) +#define SAVE_LOC (0x08080000u) static FATFS g_sd = {0}; @@ -32,16 +36,17 @@ static u32 g_saveHash[8] = {0}; -void LGY_prepareLegacyMode(void) +void LGY_prepareLegacyMode(bool gbaBios) { REG_LGY_MODE = 2; // GBA mode // BIOS overlay REGs_LGY_A7_VECTOR[0] = 0xE51FF004; //ldr pc, [pc, #-4] - REGs_LGY_A7_VECTOR[1] = 0x03007E00; - // GBA address: 0x03007E00 - NDMA_copy((u32*)0x080BFE00, _arm7_stub_start, (u32)_arm7_stub_end - (u32)_arm7_stub_start); - //iomemcpy((u32*)0x080BFE00, _arm7_stub_start, (u32)_arm7_stub_end - (u32)_arm7_stub_start); + REGs_LGY_A7_VECTOR[1] = ARM7_STUB_LOC; + NDMA_copy((u32*)ARM7_STUB_LOC9, _arm7_stub_start, (u32)_arm7_stub_end - (u32)_arm7_stub_start); + //iomemcpy((u32*)ARM7_STUB_LOC9, _arm7_stub_start, (u32)_arm7_stub_end - (u32)_arm7_stub_start); + // Patch swi 0x10 (RegisterRamReset) to swi 0x26 (HardReset). + if(gbaBios) *((u8*)(ARM7_STUB_LOC9 + ((u32)_arm7_stub_swi - (u32)_arm7_stub_start))) = 0x26; REG_LGY_GBA_SAVE_TYPE = 0xE; static const u32 saveStuff[4] = {0x27C886, 0x8CE35, 0x184, 0x31170}; @@ -55,7 +60,7 @@ void LGY_prepareLegacyMode(void) { if((romSize = f_size(&f)) > MAX_ROM_SIZE) panic(); - u8 *ptr = (u8*)0x20000000u; + u8 *ptr = (u8*)ROM_LOC; UINT read; FRESULT res; while((res = f_read(&f, ptr, 0x100000u, &read)) == FR_OK && read == 0x100000u) @@ -70,17 +75,17 @@ void LGY_prepareLegacyMode(void) if(f_open(&f, "sdmc:/rom.sav", FA_OPEN_EXISTING | FA_READ) == FR_OK) { UINT read; - if(f_read(&f, (void*)0x08080000, MAX_SAVE_SIZE, &read) != FR_OK) panic(); + if(f_read(&f, (void*)SAVE_LOC, MAX_SAVE_SIZE, &read) != FR_OK) panic(); f_close(&f); - sha((u32*)0x08080000, g_saveSize, g_saveHash, SHA_INPUT_BIG | SHA_MODE_256, SHA_OUTPUT_BIG); + sha((u32*)SAVE_LOC, g_saveSize, g_saveHash, SHA_INPUT_BIG | SHA_MODE_256, SHA_OUTPUT_BIG); } - else NDMA_fill((u32*)0x08080000, 0xFFFFFFFFu, g_saveSize); + else NDMA_fill((u32*)SAVE_LOC, 0xFFFFFFFFu, g_saveSize); } // Pad ROM area with "open bus" value. if(romSize < MAX_ROM_SIZE) - NDMA_fill((u32*)(0x20000000 + romSize), 0xFFFFFFFFu, MAX_ROM_SIZE - romSize); + NDMA_fill((u32*)(ROM_LOC + romSize), 0xFFFFFFFFu, MAX_ROM_SIZE - romSize); } void LGY_backupGbaSave(void) @@ -91,14 +96,14 @@ void LGY_backupGbaSave(void) REG_LGY_GBA_SAVE_MAP = 1; u32 newHash[8]; - sha((u32*)0x08080000, g_saveSize, newHash, SHA_INPUT_BIG | SHA_MODE_256, SHA_OUTPUT_BIG); + sha((u32*)SAVE_LOC, g_saveSize, newHash, SHA_INPUT_BIG | SHA_MODE_256, SHA_OUTPUT_BIG); if(memcmp(g_saveHash, newHash, 32) != 0) // Backup save if it changed. { FIL f; if(f_open(&f, "sdmc:/rom.sav", FA_OPEN_ALWAYS | FA_WRITE) == FR_OK) { UINT written; - if(f_write(&f, (void*)0x08080000, g_saveSize, &written) != FR_OK) panic(); + if(f_write(&f, (void*)SAVE_LOC, g_saveSize, &written) != FR_OK) panic(); f_close(&f); } } diff --git a/source/arm9/ipc_handler.c b/source/arm9/ipc_handler.c index 8f92343..fc09303 100644 --- a/source/arm9/ipc_handler.c +++ b/source/arm9/ipc_handler.c @@ -36,7 +36,7 @@ u32 IPC_handleCmd(u8 cmdId, u32 inBufs, u32 outBufs, const u32 *const buf) switch(cmdId) { case IPC_CMD_ID_MASK(IPC_CMD9_PREPARE_AGB): - LGY_prepareLegacyMode(); + LGY_prepareLegacyMode(*buf); break; case IPC_CMD_ID_MASK(IPC_CMD9_PREPARE_POWER): LGY_backupGbaSave();