From e5eade0d238daee09dfb2c20eb5d1a37cfd5a517 Mon Sep 17 00:00:00 2001 From: Gericom Date: Thu, 6 Feb 2020 13:04:22 +0100 Subject: [PATCH] Improved protected bios reading; fixes #90 Fixes Wakeboarding Unleashed featuring Shaun Murray and the Super Mario Advance Mario Bros minigame --- arm9/source/bios.s | 14 +++++++++++--- arm9/source/bios.vram.cpp | 7 ++++--- arm9/source/bios_patches.s | 12 +++++++++++- arm9/source/dtcm_data.s | 15 ++++++++++++--- arm9/source/emu/handle_address_read.s | 14 ++++++-------- arm9/source/emu/irq.s | 10 ++++++++++ arm9/source/patchUtil.h | 3 +++ arm9/source/patchUtil.vram.cpp | 7 +++++++ 8 files changed, 64 insertions(+), 18 deletions(-) create mode 100644 arm9/source/patchUtil.h create mode 100644 arm9/source/patchUtil.vram.cpp diff --git a/arm9/source/bios.s b/arm9/source/bios.s index 9d3cbb6..aefb622 100644 --- a/arm9/source/bios.s +++ b/arm9/source/bios.s @@ -5,8 +5,16 @@ gGbaBios: .global bios_swiVeneer bios_swiVeneer: - ldr pc,= (gGbaBios + 0x140) + b swiPatch -.pool +.space 0x4000 - (. - gGbaBios) -.space 0x4000 - (. - gGbaBios) \ No newline at end of file +swiPatch: + push {r0,r1} + ldr r0,= gBiosOp + ldr r1,= 0xE3A02004 + str r1, [r0] + pop {r0, r1} + b (gGbaBios + 0x140) + +.pool \ No newline at end of file diff --git a/arm9/source/bios.vram.cpp b/arm9/source/bios.vram.cpp index 89b4a3c..94777cf 100644 --- a/arm9/source/bios.vram.cpp +++ b/arm9/source/bios.vram.cpp @@ -1,10 +1,12 @@ #include "vram.h" #include "sd_access.h" #include "fat/ff.h" +#include "patchUtil.h" #include "bios.h" extern "C" void bios_cpuset_cache_patch(); extern "C" void bios_cpufastset_cache_patch(); +extern "C" void bios_softResetPatch(); /** * \brief Relocates the gba bios so it can be executed from vram @@ -89,9 +91,8 @@ static void applyRelocation() */ static void applyPatches() { - //Make bios jump to 02040000 - //todo: check if this is even needed anymore, it may be handled by prefetch abort just fine - //gGbaBios[0xCC >> 2] = 0xE3A0E781; + //patch for having the right protected op at boot + gGbaBios[0xDC >> 2] = pcu_makeArmBranch((u32)&gGbaBios[0xDC >> 2], (u32)&bios_softResetPatch); //fix post boot redirect //todo: maybe I should correctly implement that register instead diff --git a/arm9/source/bios_patches.s b/arm9/source/bios_patches.s index 5131ddd..671bee7 100644 --- a/arm9/source/bios_patches.s +++ b/arm9/source/bios_patches.s @@ -91,4 +91,14 @@ bios_cpufastset_cache_patch: //don't use the armv5 interworking! ldr r4,= (gGbaBios + 0xBC8) bx r4 -#endif \ No newline at end of file +#endif + +.global bios_softResetPatch +bios_softResetPatch: + //set the right protected bios opcode + ldr r0,= gBiosOp + ldr r1,= 0xE129F000 + str r1, [r0] + mov r0, #0 + mov r1, #0 + bx lr \ No newline at end of file diff --git a/arm9/source/dtcm_data.s b/arm9/source/dtcm_data.s index 5343c4b..6263dad 100644 --- a/arm9/source/dtcm_data.s +++ b/arm9/source/dtcm_data.s @@ -1,4 +1,4 @@ -.section .dtcm2 +.section ".dtcm2","ax" .altmacro #include "consts.s" @@ -309,6 +309,15 @@ timer_shadow_regs_dtcm: .short 0 //reload value .endr +//the current bios opcode that is returned if you do a protected read +//[00DCh+8] = 0xE129F000, after startup and softreset //before this address 0x27C is read +//[0134h+8] = 0xE25EF004, during irq execution +//[013Ch+8] = 0xE55EC002, after irq execution +//[0188h+8] = 0xE3A02004, after swi execution; reads between 0x1C8 and 0x274 +.global gBiosOp +gBiosOp: +.word 0xE3A02004 + //for some reason the file is ignored without this nop here -nop -nop \ No newline at end of file +@ nop +@ nop \ No newline at end of file diff --git a/arm9/source/emu/handle_address_read.s b/arm9/source/emu/handle_address_read.s index c6e152e..47ffe70 100644 --- a/arm9/source/emu/handle_address_read.s +++ b/arm9/source/emu/handle_address_read.s @@ -2,11 +2,6 @@ #include "consts.s" -//bios_op = 0xE129F000 //[00DCh+8] after startup and softreset //before this address 0x27C is read -//bios_op = 0xE25EF004 //[0134h+8] during irq execution -//bios_op = 0xE55EC002 //[013Ch+8] after irq execution -bios_op = 0xE3A02004 //[0188h+8] after swi execution; reads between 0x1C8 and 0x274 - .global read_address_from_handler_32bit read_address_from_handler_32bit: cmp r9, #0x10000000 @@ -54,8 +49,9 @@ read_address_from_handler_bios_32: cmp r10, #0x4000 ldrlt r10, [r9] //if the opcode is in the bios, read the data bxlt lr - ldr r10,= bios_op + ldr r10,= gBiosOp and r11, r9, #3 + ldr r10, [r10] mov r11, r11, lsl #3 mov r10, r10, ror r11 bx lr @@ -208,7 +204,8 @@ read_address_from_handler_bios_16: sub r10, #8 cmp r10, #0x4000 ldrlth r10, [r9] //if the opcode is in the bios, read the data - ldrge r10,= (bios_op & 0xFFFF) + ldrge r10,= gBiosOp + ldrgeh r10, [r10] tst r9, #1 movne r10, r10, ror #8 bx lr @@ -368,8 +365,9 @@ read_address_from_handler_bios_8: cmp r10, #0x4000 ldrltb r10, [r9] //if the opcode is in the bios, read the data bxlt lr - ldr r10,= bios_op + ldr r10,= gBiosOp and r11, r9, #3 + ldr r10, [r10] mov r11, r11, lsl #3 mov r10, r10, ror r11 and r10, r10, #0xFF diff --git a/arm9/source/emu/irq.s b/arm9/source/emu/irq.s index 967786e..b4fb5eb 100644 --- a/arm9/source/emu/irq.s +++ b/arm9/source/emu/irq.s @@ -214,6 +214,11 @@ irq_cont_handle_gba: bic r2, #(1 << 16) ldr r1,= pu_data_permissions str r2, [r12, #0x210] + + ldr r0,= gBiosOp + ldr r2,= 0xE25EF004 + str r2, [r0] + mcr p15, 0, r1, c5, c0, 2 ADR LR, loc_138 @@ -227,6 +232,11 @@ loc_138: ldr r2,= pu_data_permissions orr r1, #(1 << 16) str r1, [r12, #0x210] + + ldr r0,= gBiosOp + ldr r1,= 0xE55EC002 + str r1, [r0] + mcr p15, 0, r2, c5, c0, 2 LDMFD SP!, {R0-R3,R12,LR} diff --git a/arm9/source/patchUtil.h b/arm9/source/patchUtil.h new file mode 100644 index 0000000..fccb49a --- /dev/null +++ b/arm9/source/patchUtil.h @@ -0,0 +1,3 @@ +#pragma once + +u32 pcu_makeArmBranch(u32 instAddr, u32 target); \ No newline at end of file diff --git a/arm9/source/patchUtil.vram.cpp b/arm9/source/patchUtil.vram.cpp new file mode 100644 index 0000000..c501198 --- /dev/null +++ b/arm9/source/patchUtil.vram.cpp @@ -0,0 +1,7 @@ +#include "vram.h" +#include "patchUtil.h" + +u32 pcu_makeArmBranch(u32 instAddr, u32 target) +{ + return 0xEA000000 | (((target >> 2) - (instAddr >> 2) - 2) & 0xFFFFFF); +} \ No newline at end of file