mirror of
https://github.com/LumaTeam/Luma3DS.git
synced 2026-02-22 09:54:38 +00:00
194 lines
5.2 KiB
ArmAsm
194 lines
5.2 KiB
ArmAsm
.section .emunand_patch, "aw", %progbits
|
|
.arm
|
|
.align 4
|
|
|
|
@ Code originally by Normmatt
|
|
|
|
.global emunandPatch
|
|
emunandPatch:
|
|
@ Original code that still needs to be executed
|
|
mov r4, r0
|
|
mov r5, r1
|
|
mov r7, r2
|
|
mov r6, r3
|
|
@ End
|
|
|
|
@ If we're already trying to access the SD, return
|
|
ldr r2, [r0, #4]
|
|
ldr r1, emunandPatchSdmmcStructPtr
|
|
cmp r2, r1
|
|
beq out
|
|
|
|
str r1, [r0, #4] @ Set object to be SD
|
|
ldr r2, [r0, #8] @ Get sector to read
|
|
cmp r2, #0 @ For GW compatibility, see if we're trying to read the ncsd header (sector 0)
|
|
|
|
ldr r3, emunandPatchNandOffset
|
|
add r2, r3 @ Add the offset to the NAND in the SD
|
|
|
|
ldreq r3, emunandPatchNcsdHeaderOffset
|
|
addeq r2, r3 @ If we're reading the ncsd header, add the offset of that sector
|
|
|
|
str r2, [r0, #8] @ Store sector to read
|
|
|
|
out:
|
|
@ Restore registers.
|
|
mov r1, r5
|
|
mov r2, r7
|
|
mov r3, r6
|
|
|
|
@ Return 4 bytes behind where we got called,
|
|
@ due to the offset of this function being stored there
|
|
mov r0, lr
|
|
add r0, #4
|
|
bx r0
|
|
|
|
.pool
|
|
|
|
_emunandPatchEnd:
|
|
|
|
.global emunandProtoPatch
|
|
emunandProtoPatch:
|
|
@ Save registers
|
|
push {r0-r3}
|
|
|
|
@ If we're already trying to access the SD, return
|
|
ldr r2, [r0, #4]
|
|
ldr r1, emunandPatchSdmmcStructPtr
|
|
cmp r2, r1
|
|
beq _out
|
|
|
|
ldrb r2, [r1, #0xc] @ Get sdmc->m_isInitialised
|
|
cmp r2, #0 @ Is initialised?
|
|
beq _pastSdmc @ if not, use "NAND" object, patched elsewhere to access SD
|
|
str r1, [r0, #4] @ Set object to be SD
|
|
_pastSdmc:
|
|
ldr r2, [r0, #8] @ Get sector to read
|
|
cmp r2, #0 @ For GW compatibility, see if we're trying to read the ncsd header (sector 0)
|
|
|
|
ldr r3, emunandPatchNandOffset
|
|
add r2, r3 @ Add the offset to the NAND in the SD
|
|
|
|
ldreq r3, emunandPatchNcsdHeaderOffset
|
|
addeq r2, r3 @ If we're reading the ncsd header, add the offset of that sector
|
|
|
|
str r2, [r0, #8] @ Store sector to read
|
|
|
|
_out:
|
|
@ Restore registers
|
|
pop {r0-r3}
|
|
@ Execute original code that got patched.
|
|
cmp r1, #3
|
|
mov r12, r2
|
|
add r0, r0, #4
|
|
movne r1, #0
|
|
moveq r1, #1
|
|
@ r2 about to be overwritten, so it's free to use here.
|
|
@ Save off our return address and restore lr.
|
|
mov r2, lr
|
|
pop {lr}
|
|
@ r2+0 is return address (patched movne r1, #0)
|
|
@ r2+4 is moveq r1, #1
|
|
@ r2+8 is the following instruction (mov r2, r3)
|
|
add r2, #8
|
|
bx r2
|
|
|
|
.global emunandProtoCidPatch
|
|
emunandProtoCidPatch:
|
|
@ If we're already trying to access the SD, return
|
|
ldr r4, emunandPatchSdmmcStructPtr
|
|
cmp r0, r4
|
|
beq _cid_return
|
|
|
|
@ Trying to access nand, so copy the NAND cid into r1
|
|
adr r4, emunandPatchNandCid
|
|
ldr r2, [r4, #0]
|
|
ldr r3, [r4, #4]
|
|
ldr r5, [r4, #8]
|
|
ldr r6, [r4, #0xc]
|
|
str r2, [r1, #0]
|
|
str r3, [r1, #4]
|
|
str r5, [r1, #8]
|
|
str r6, [r1, #0xc]
|
|
@ And return from whence we came
|
|
mov r0, #0
|
|
pop {r4-r6, pc}
|
|
|
|
_cid_return:
|
|
@ Execute original code that got patched.
|
|
mov r4, r0
|
|
ldr r0, [r0]
|
|
mov r5, r1
|
|
@ lr+0 is return address (patched mov r5, r1)
|
|
@ lr+4 is following instruction (ldr r1, [r0,#8])
|
|
add lr, #4
|
|
bx lr
|
|
|
|
.global emunandProtoPatch238
|
|
emunandProtoPatch238:
|
|
@ Save registers
|
|
push {r0-r3}
|
|
|
|
@ If we're already trying to access the SD, return
|
|
ldr r2, [r4, #4]
|
|
ldr r1, emunandPatchSdmmcStructPtr
|
|
cmp r2, r1
|
|
beq _out238
|
|
|
|
ldr r2, [r1, #0x24] @ Get sdmc->m_someObjInitedLater
|
|
cmp r2, #0 @ Is initialised?
|
|
beq _pastSdmc238 @ if not, use "NAND" object, patched elsewhere to access SD
|
|
str r1, [r4, #4] @ Set object to be SD
|
|
_pastSdmc238:
|
|
|
|
ldr r2, [r4, #8] @ Get sector to read
|
|
cmp r2, #0 @ For GW compatibility, see if we're trying to read the ncsd header (sector 0)
|
|
|
|
ldr r3, emunandPatchNandOffset
|
|
add r2, r3 @ Add the offset to the NAND in the SD
|
|
|
|
ldreq r3, emunandPatchNcsdHeaderOffset
|
|
addeq r2, r3 @ If we're reading the ncsd header, add the offset of that sector
|
|
|
|
str r2, [r4, #8] @ Store sector to read
|
|
|
|
_out238:
|
|
@ Restore registers
|
|
pop {r0-r3}
|
|
@ Execute original code that got patched.
|
|
cmp r0, #3
|
|
movne r0, #0
|
|
moveq r0, #1
|
|
@ r1 about to be overwritten, so it's free to use here.
|
|
@ Save off our return address.
|
|
mov r1, lr
|
|
@ r1+0 is return address (patched moveq r1, #1)
|
|
@ r1+4 is tst r0, #0xff or sub sp, sp, #0xc
|
|
add r1, #4
|
|
bx r1
|
|
|
|
.pool
|
|
|
|
.global emunandPatchSdmmcStructPtr
|
|
.global emunandPatchNandOffset
|
|
.global emunandPatchNcsdHeaderOffset
|
|
.global emunandPatchNandCid
|
|
|
|
_emunandPatchBssStart:
|
|
emunandPatchSdmmcStructPtr: .word 0 @ Pointer to sdmmc struct
|
|
emunandPatchNandOffset: .word 0 @ For rednand this should be 1
|
|
emunandPatchNcsdHeaderOffset: .word 0 @ Depends on nand manufacturer + emunand type (GW/RED)
|
|
emunandPatchNandCid: @ Store emmc cid here, to override "sdmc's" when trying to read emmc's
|
|
.word 0,0,0,0
|
|
_emunandPatchBssEnd:
|
|
|
|
.pool
|
|
.balign 4
|
|
|
|
.global emunandPatchSize
|
|
emunandPatchSize:
|
|
.word _emunandPatchEnd - emunandPatch
|
|
|
|
.global emunandPatchBssSize
|
|
emunandPatchBssSize:
|
|
.word _emunandPatchBssEnd - _emunandPatchBssStart |