mirror of
https://github.com/wiiu-env/haxchi.git
synced 2024-11-16 13:19:16 +01:00
bfa52229b6
-sorting game list before displaying it -better stack positions for kirby mass attack, super mario 64 ds, kirby canvas curse, zelda phantom hourglass, spirit tracks and pokemon ranger shadows of almia -added support for pokemon ranger, animal crossing wild world, pokemon mystery dungeon explorers of sky and pokemon ranger guardian signs
276 lines
8.5 KiB
ArmAsm
276 lines
8.5 KiB
ArmAsm
.include "coreinit.s"
|
|
.include "defines.s"
|
|
|
|
; more useful definitions
|
|
HBL_LOADER_ADR equ (0x01800000)
|
|
SELECTOR_ADDRESS equ (0x01808000)
|
|
CFW_BOOTER_ADR equ (0x0180C000)
|
|
|
|
NERD_THREAD0OBJECT equ (HAX_TARGET_ADDRESS - 0x1000)
|
|
NERD_THREAD2OBJECT equ (HAX_TARGET_ADDRESS - 0x2000)
|
|
|
|
.macro set_sp,v
|
|
.word LWZ_R0R1x14_LWZ_R30R1x8_R31R1xC_MTLR_R0_ADDI_R1x10_BLR
|
|
.word 0xDEADBABE ; r30
|
|
.word v ; r31
|
|
.word 0xDEAD0001 ; garbage
|
|
.word MR_R11R31_LMW_R26R1x8_LWZ_R0x24_MTLR_R0_ADDI_R1x20_CLRLWI_R3R11x18_BLR
|
|
.word 0xDEADBABE ; r26
|
|
.word 0xDEADBABE ; r27
|
|
.word 0xDEADBABE ; r28
|
|
.word 0xDEADBABE ; r29
|
|
.word 0xDEADBABE ; r30
|
|
.word 0xDEADBABE ; r31
|
|
.word 0xDEAD0001 ; garbage
|
|
.word LWZ_R0R11x4_R31R11xM4_MTLR_R0_MR_R1R11_BLR
|
|
.endmacro
|
|
|
|
.macro call_func,f,arg1,arg2,arg3,arg4
|
|
.word LMW_R21R1xC_LWZ_R0R1x3C_MTLR_R0_ADDI_R1_x38_BLR
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEADBABE ; r21
|
|
.word 0xDEADBABE ; r22
|
|
.word 0xDEADBABE ; r23
|
|
.word 0xDEADBABE ; r24
|
|
.word 0xDEADBABE ; r25
|
|
.word 0xDEADBABE ; r26
|
|
.word f ; r27 (ctr)
|
|
.word arg4 ; r28 (r6)
|
|
.word arg3 ; r29 (r5)
|
|
.word arg2 ; r30 (r4)
|
|
.word arg1 - 2 ; r31 (r3 - 2)
|
|
; sp is here when LMW_R26R1x18 happens
|
|
.word 0xDEAD0004 ; garbage
|
|
.word MTCTR_R27_ADDI_R31x2_MR_R3R31_R4R30_R5R29_R6R28_BCTRL_LMW_R26R1x18_MTLR_R1x34_ADDI_R1x30_BLR
|
|
.word 0xDEAD0008 ; garbage
|
|
.word 0xDEAD000C ; garbage
|
|
.word 0xDEAD0010 ; garbage
|
|
.word 0xDEAD0014 ; garbage
|
|
.word 0xDEADBABE ; r26
|
|
.word 0xDEADBABE ; r27
|
|
.word 0xDEADBABE ; r28
|
|
.word 0xDEADBABE ; r29
|
|
.word 0xDEADBABE ; r30
|
|
.word 0xDEADBABE ; r31
|
|
; final sp is here
|
|
.word 0xDEADBABE ; garbage
|
|
.endmacro
|
|
|
|
.macro call_func_6args,f,arg1,arg2,arg3,arg4,arg5,arg6
|
|
.word LMW_R21R1xC_LWZ_R0R1x3C_MTLR_R0_ADDI_R1_x38_BLR
|
|
.word 0xDEAD0001 ; garbage
|
|
.word arg6 ; r21 (r8)
|
|
.word 0xDEADBABE ; r22
|
|
.word 0xDEADBABE ; r23
|
|
.word arg1 ; r24 (r3)
|
|
.word arg2 ; r25 (r4)
|
|
.word 0xDEADBABE ; r26
|
|
.word arg3 ; r27 (r5)
|
|
.word arg4 ; r28 (r6)
|
|
.word arg5 ; r29 (r7)
|
|
.word LMW_R21R1xC_LWZ_R0R1x3C_MTLR_R0_ADDI_R1_x38_BLR ; r30 (ctr)
|
|
.word 0xDEADBABE ; r31
|
|
; sp is here when LMW_R26R1x18 happens
|
|
.word 0xDEAD0004 ; garbage
|
|
.word MTCTR_R30_MR_R8R21_R7R29_R6R28_R5R27_R4R25_R3R24_BCTRL
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEADBABE ; r21
|
|
.word 0xDEADBABE ; r22
|
|
.word 0xDEADBABE ; r23
|
|
.word 0xDEADBABE ; r24
|
|
.word 0xDEADBABE ; r25
|
|
.word 0xDEADBABE ; r26
|
|
.word f ; r27 (ctr)
|
|
.word arg4 ; r28 (r6)
|
|
.word arg3 ; r29 (r5)
|
|
.word arg2 ; r30 (r4)
|
|
.word arg1 - 2 ; r31 (r3 - 2)
|
|
; sp is here when LMW_R26R1x18 happens
|
|
.word 0xDEAD0004 ; garbage
|
|
.word MTCTR_R27_ADDI_R31x2_MR_R3R31_R4R30_R5R29_R6R28_BCTRL_LMW_R26R1x18_MTLR_R1x34_ADDI_R1x30_BLR
|
|
.word 0xDEAD0008 ; garbage
|
|
.word 0xDEAD000C ; garbage
|
|
.word 0xDEAD0010 ; garbage
|
|
.word 0xDEAD0014 ; garbage
|
|
.word 0xDEADBABE ; r26
|
|
.word 0xDEADBABE ; r27
|
|
.word 0xDEADBABE ; r28
|
|
.word 0xDEADBABE ; r29
|
|
.word 0xDEADBABE ; r30
|
|
.word 0xDEADBABE ; r31
|
|
; final sp is here
|
|
.word 0xDEADBABE ; garbage
|
|
.endmacro
|
|
|
|
|
|
; hacked from arm7 ram offset (unsafe, game stack pointer)
|
|
.create "haxchi_rop_hook.bin", HAX_TARGET_ADDRESS
|
|
.arm.big
|
|
|
|
rop_hook_start:
|
|
;call_func BCTRL, 0x0, 0x0, 0x0, 0x0 ; infinite loop
|
|
;call_func OSFATAL, 0x1007E7A8, 0, 0, 0
|
|
; move stack pointer to safe area
|
|
set_sp (rop_start - 4)
|
|
.Close
|
|
|
|
|
|
; original game arm9 ram offset (safe, normally arm9 code)
|
|
.create "haxchi_rop.bin", ARM9_ROM_LOCATION
|
|
.arm.big
|
|
|
|
rop_start:
|
|
; do hachihachi cleanups so we can use everything safely
|
|
call_func HACHI_APPLICATION_SHUTDOWNANDDESTROY, HACHI_APPLICATION_PTR, 0, 0, 0
|
|
call_func NERD_FASTWIIU_SHUTDOWN, 0, 0, 0, 0
|
|
call_func CORE_SHUTDOWN, 0, 0, 0, 0
|
|
|
|
; set up hbl_loader in core 0
|
|
call_func_6args NERD_CREATETHREAD, NERD_THREAD0OBJECT, LWZ_R0xAFC_MTLR_R0_ADDI_R1xAF8_BLR, 0x1007E7A8, thread0_param, 0x0, 0x0
|
|
|
|
; the code below prepares the stack for the thread in core 0
|
|
|
|
; load memcpy jump into r3
|
|
.word LWZ_R3_8_R1_LWZ_R0x14_MTLR_R0_ADDI_R1x10_BLR
|
|
.word MEMCPY ; r3
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEAD0001 ; garbage
|
|
; more r3 into r12 for our memcpy jump at the end of this
|
|
.word MR_R12_R3_CMPLW_R12_R0_LI_R3_0_BEQ_ADDI_R3_R12x10_LWZ_R0_R1x14_MTLR_R0_ADDI_R1x10_BLR
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEAD0001 ; garbage
|
|
; prepare r31 to be a valid value for the next call
|
|
.word LWZ_R0R1x14_LWZ_R30R1x8_R31R1xC_MTLR_R0_ADDI_R1x10_BLR
|
|
.word 0xDEADBABE ; r30
|
|
.word (core0rop_end - core0rop) ; r31 (has to be the same as r5 in the next call)
|
|
.word 0xDEAD0001 ; garbage
|
|
; get r5 ready for the length we want to copy
|
|
.word LWZ_R5_R1x8_CMPLW_R5_R31_BNE_MR_R3_R5_LWZ_R0_R1x1C_LWZ_R30_R1x10_MTLR_R0_LWZ_R31_R1x14_ADDI_R1x18_BLR
|
|
.word (core0rop_end - core0rop) ; r5
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEAD0001 ; r30
|
|
.word 0xDEAD0001 ; r31
|
|
.word 0xDEAD0001 ; garbage
|
|
; get r4 ready for the data we want to copy
|
|
.word LWZ_R4_R1xC_STW_R12_R1x8_LWZ_R3_R1x8_LWZ_R0_R1x1C_MTLR_R0_ADDI_R1x18_BLR
|
|
.word 0xDEAD0001 ; garbage
|
|
.word core0rop ; r4
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEAD0001 ; garbage
|
|
; prepare r31 to be a valid value for the next call
|
|
.word LWZ_R0R1x14_LWZ_R30R1x8_R31R1xC_MTLR_R0_ADDI_R1x10_BLR
|
|
.word 0xDEADBABE ; r30
|
|
.word (HAX_TARGET_ADDRESS-0x3000) ; r31 (has to be valid here)
|
|
.word 0xDEAD0001 ; garbage
|
|
; loads the required value for the addition onto r3 later on
|
|
.word LWZ_R7_R1x10_LWZ_R8_R1x14_STW_R7_R31x0_STW_R8_R31x0_LWZ_R0_R1x2C_LWZ_R31_R0x24_MTLR_R0_LWZ_R30_R0x20_ADDI_R1x28_BLR
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEAD0001 ; garbage
|
|
.word (0x00800000 - 0x30 + 0xAFC) ; r7
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEAD0001 ; r30
|
|
.word 0xDEAD0001 ; r31
|
|
.word 0xDEAD0001 ; garbage
|
|
; loads pointer to new thread sp into r3
|
|
.word LWZ_R3_8_R1_LWZ_R0x14_MTLR_R0_ADDI_R1x10_BLR
|
|
.word (NERD_THREAD0OBJECT+4) ; r3
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEAD0001 ; garbage
|
|
; r3 contains new thread sp end after this load
|
|
.word LWZ_R3_4_R3_LWZ_R0xC_MTLR_R0_ADDI_R1x8_BLR
|
|
.word 0xDEAD0001 ; garbage
|
|
; r3 contains code injection thread sp after this add
|
|
.word LWZ_R0_R1x1C_LWZ_R30_R1x10_MTLR_R0_LWZ_R31_R1x14_ADDI_R1x18_ADD_R3_R7_BLR
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEAD0001 ; r30
|
|
.word 0xDEAD0001 ; r31
|
|
.word 0xDEAD0001 ; garbage
|
|
; jump to previously prepared r12 for memcpy
|
|
.word MTCTR_R12_BCTRL_LI_R3_0_LWZ_R0_R1x14_LWZ_R31_R1xC_MTLR_R0_ADDI_R1x10_BLR
|
|
.word 0xDEAD0001 ; garbage
|
|
.word 0xDEAD0001 ; r31
|
|
.word 0xDEAD0001 ; garbage
|
|
|
|
; thread stack is prepared after this point
|
|
|
|
; wait for hbl_loader to do its job
|
|
call_func NERD_STARTTHREAD, NERD_THREAD0OBJECT, 0x0, 0x0, 0x0
|
|
call_func NERD_JOINTHREAD, NERD_THREAD0OBJECT, 0x0, 0x0, 0x0
|
|
|
|
; prepare system for foreground release
|
|
call_func OSSAVESDONE_READYTORELEASE, 0, 0, 0, 0
|
|
|
|
; instruct all 3 cores to release foreground to prepare mii studio app launch
|
|
call_func_6args NERD_CREATETHREAD, NERD_THREAD0OBJECT, OSRELEASEFOREGROUND, 0, thread0_param, 0x0, 0x0
|
|
call_func NERD_STARTTHREAD, NERD_THREAD0OBJECT, 0x0, 0x0, 0x0
|
|
|
|
call_func_6args NERD_CREATETHREAD, NERD_THREAD2OBJECT, OSRELEASEFOREGROUND, 0, thread2_param, 0x0, 0x0
|
|
call_func NERD_STARTTHREAD, NERD_THREAD2OBJECT, 0x0, 0x0, 0x0
|
|
|
|
; we are the main thread in core 1 so we call this direct
|
|
call_func OSRELEASEFOREGROUND, 0, 0, 0, 0
|
|
|
|
; launch mii studio app
|
|
.word _START_EXIT
|
|
|
|
core0rop:
|
|
; switch codegen to RW
|
|
call_func OSCODEGEN_SWITCHSECMODE, 0x0, 0x0, 0x0, 0x0
|
|
|
|
; memcpy code
|
|
call_func MEMCPY, HBL_LOADER_ADR, hbl_loader, hbl_loader_end - hbl_loader, 0x0
|
|
call_func MEMCPY, SELECTOR_ADDRESS, code, code_end - code, 0x0
|
|
call_func MEMCPY, CFW_BOOTER_ADR, cfw_booter, cfw_booter_end - cfw_booter, 0x0
|
|
call_func DC_FLUSHRANGE, HBL_LOADER_ADR, 0xE000, 0x0, 0x0
|
|
|
|
; switch codegen to RX
|
|
call_func OSCODEGEN_SWITCHSECMODE, 0x1, 0x0, 0x0, 0x0
|
|
call_func IC_INVALIDATERANGE, HBL_LOADER_ADR, 0xE000, 0x0, 0x0
|
|
|
|
; execute option_select in codegen
|
|
.word SELECTOR_ADDRESS
|
|
core0rop_end:
|
|
|
|
; core 0 thread params
|
|
output0_string:
|
|
.ascii "hax0thread"
|
|
.byte 0x00
|
|
.align 0x4
|
|
|
|
thread0_param:
|
|
.word output0_string
|
|
.word 0x00800000 ; stack size
|
|
.word 0x00000010 ; thread prio
|
|
.halfword 0x0001 ; thread affinity (core0)
|
|
|
|
; core 2 thread params
|
|
output2_string:
|
|
.ascii "hax2thread"
|
|
.byte 0x00
|
|
.align 0x4
|
|
|
|
thread2_param:
|
|
.word output2_string
|
|
.word 0x00800000 ; stack size
|
|
.word 0x00000010 ; thread prio
|
|
.halfword 0x0004 ; thread affinity (core2)
|
|
|
|
code:
|
|
.incbin "code550.bin"
|
|
code_end:
|
|
|
|
hbl_loader:
|
|
.incbin "hbl_loader.bin"
|
|
hbl_loader_end:
|
|
|
|
cfw_booter:
|
|
.incbin "cfw_booter.bin"
|
|
cfw_booter_end:
|
|
|
|
.Close
|