diff --git a/arm9/source/patches/platform/datel/DatelLoaderPlatform.h b/arm9/source/patches/platform/datel/DatelLoaderPlatform.h index b98577a..8bd4dc6 100644 --- a/arm9/source/patches/platform/datel/DatelLoaderPlatform.h +++ b/arm9/source/patches/platform/datel/DatelLoaderPlatform.h @@ -15,9 +15,13 @@ public: { return new DatelReadSpiBytePatchCode(patchHeap); }); + auto cycleSpi = patchCodeCollection.GetOrAddSharedPatchCode([&] + { + return new DatelCycleSpiPatchCode(patchHeap); + }); auto sendSdio = patchCodeCollection.GetOrAddSharedPatchCode([&] { - return new DatelSendSdioCommandPatchCode(patchHeap, spi); + return new DatelSendSdioCommandPatchCode(patchHeap, spi, cycleSpi); }); return patchCodeCollection.GetOrAddSharedPatchCode([&] { @@ -32,9 +36,13 @@ public: { return new DatelReadSpiBytePatchCode(patchHeap); }); + auto cycleSpi = patchCodeCollection.GetOrAddSharedPatchCode([&] + { + return new DatelCycleSpiPatchCode(patchHeap); + }); auto sendSdio = patchCodeCollection.GetOrAddSharedPatchCode([&] { - return new DatelSendSdioCommandPatchCode(patchHeap, spi); + return new DatelSendSdioCommandPatchCode(patchHeap, spi, cycleSpi); }); return patchCodeCollection.GetOrAddSharedPatchCode([&] { diff --git a/arm9/source/patches/platform/datel/DatelSendSdioCommandPatchCode.h b/arm9/source/patches/platform/datel/DatelSendSdioCommandPatchCode.h index 86a4f32..c9967ae 100644 --- a/arm9/source/patches/platform/datel/DatelSendSdioCommandPatchCode.h +++ b/arm9/source/patches/platform/datel/DatelSendSdioCommandPatchCode.h @@ -3,6 +3,7 @@ #include "patches/PatchCode.h" DEFINE_SECTION_SYMBOLS(datel_read_spi); +DEFINE_SECTION_SYMBOLS(datel_cycle_spi); DEFINE_SECTION_SYMBOLS(datel_spi_send); extern "C" u8 datel_readSpiByte(); @@ -11,11 +12,14 @@ extern "C" u16 datel_readSpiShort(); extern "C" u8 datel_readSpiByteTimeout(); extern "C" bool datel_waitSpiByteTimeout(); +extern "C" void datel_cycleSpi(); + extern "C" u8 datel_spiSendSDIOCommandR0(u32 arg, u8 cmd); extern "C" u8 datel_spiSendSDIOCommand(u32 arg, u8 cmd, int extraBytes); -extern u32 datel_spiSendSDIOCommandR0_ReadWriteSpiByte; +extern u32 datel_spiSendSDIOCommandR0_CycleSpi; extern u32 datel_spiSendSDIOCommandR0_ReadSpiByteTimeout; +extern u32 datel_spiSendSDIOCommandR0_ReadWriteSpiByte; class DatelReadSpiBytePatchCode : public PatchCode { @@ -49,14 +53,29 @@ public: } }; +class DatelCycleSpiPatchCode : public PatchCode +{ +public: + explicit DatelCycleSpiPatchCode(PatchHeap& patchHeap) + : PatchCode(SECTION_START(datel_cycle_spi), SECTION_SIZE(datel_cycle_spi), patchHeap) { } + + const void* GetCycleSpiFunction() const + { + return GetAddressAtTarget((void*)datel_cycleSpi); + } +}; + class DatelSendSdioCommandPatchCode : public PatchCode { public: - DatelSendSdioCommandPatchCode(PatchHeap& patchHeap, const DatelReadSpiBytePatchCode* datelReadSpiBytePatchCode) + DatelSendSdioCommandPatchCode(PatchHeap& patchHeap, + const DatelReadSpiBytePatchCode* datelReadSpiBytePatchCode, + const DatelCycleSpiPatchCode* datelCycleSpiPatchCode) : PatchCode(SECTION_START(datel_spi_send), SECTION_SIZE(datel_spi_send), patchHeap) { - datel_spiSendSDIOCommandR0_ReadWriteSpiByte = (u32)datelReadSpiBytePatchCode->GetReadWriteSpiByteFunction(); + datel_spiSendSDIOCommandR0_CycleSpi = (u32)datelCycleSpiPatchCode->GetCycleSpiFunction(); datel_spiSendSDIOCommandR0_ReadSpiByteTimeout = (u32)datelReadSpiBytePatchCode->GetReadSpiByteTimeoutFunction(); + datel_spiSendSDIOCommandR0_ReadWriteSpiByte = (u32)datelReadSpiBytePatchCode->GetReadWriteSpiByteFunction(); } const void* GetSpiSendSDIOCommandR0Function() const diff --git a/arm9/source/patches/platform/datel/DatelSendSdioCommandPatchCode.s b/arm9/source/patches/platform/datel/DatelSendSdioCommandPatchCode.s index 1eced1c..290baee 100644 --- a/arm9/source/patches/platform/datel/DatelSendSdioCommandPatchCode.s +++ b/arm9/source/patches/platform/datel/DatelSendSdioCommandPatchCode.s @@ -10,7 +10,7 @@ BEGIN_ASM_FUNC datel_readSpiByte movs r0, 0xFF @u8 datel_readWriteSpiByte(u8); BEGIN_ASM_FUNC datel_readWriteSpiByte - push {r1-r3, lr} + push {r1-r3} ldr r3, =REG_MCCNT0 @ Wait if there's a transfer in progress (can happen if the random byte sent by the cycle spi function is still on its way) 1: @@ -27,7 +27,8 @@ BEGIN_ASM_FUNC datel_readWriteSpiByte @uppper half always 0 ldrh r0, [r3, #2] cmp r0, #0 - pop {r1-r3, pc} + pop {r1-r3} + mov pc,lr @u16 datel_readWriteSpiShort(); BEGIN_ASM_FUNC datel_readSpiShort @@ -53,12 +54,13 @@ BEGIN_ASM_FUNC datel_readSpiByteTimeout subs r4, r4, #1 bne 1b 1: - pop {r1-r4, pc} + pop {r1-r4,pc} @bool datel_waitSpiByteTimeout(); BEGIN_ASM_FUNC datel_waitSpiByteTimeout - push {r1-r4, lr} - @ use a timeout of 0x1000 instead of 0xFFFF, easier to setup + push {r1-r4} + push {lr} + @ use a timeout of 0x10000 instead of 0xFFFF, easier to setup @ ldr r2, =DATEL_SD_WRITE_TIMEOUT_LEN movs r2, #1 lsls r2, #16 @@ -69,15 +71,19 @@ BEGIN_ASM_FUNC datel_waitSpiByteTimeout bne 1b movs r0, #0 - pop {r1-r4, pc} + b end 1: movs r0, #1 - pop {r1-r4, pc} +end: + pop {r1} + mov lr,r1 + pop {r1-r4} + mov pc,lr -.section "datel_spi_send", "ax" +.section "datel_cycle_spi", "ax" @void datel_cycleSpi(); -datel_cycleSpi: +BEGIN_ASM_FUNC datel_cycleSpi push {r0-r5, lr} adr r0, datel_cycleSpi_data ldm r0!, {r1,r3,r4} @@ -106,7 +112,14 @@ datel_sendNtrCommandF2: beq datel_sendNtrCommandF2 pop {r0-r5, pc} +.balign 4 +.pool +datel_cycleSpi_data: + .word REG_MCCNT0 + .word 0x00FFA040 @ MCCNT0_MODE_SPI | MCCNT0_SPI_HOLD_CS | MCCNT0_ENABLE in lower 16 bit, 0xFF in upper 16 + .word 0xA07F6000 @ MCCNT1_RESET_OFF | MCCNT1_CMD_SCRAMBLE | MCCNT1_READ_DATA_DESCRAMBLE | MCCNT1_CLOCK_SCRAMBLER | MCCNT1_LATENCY2(0x3F) +.section "datel_spi_send", "ax" @ NOTE!!!: This function needs to set r0 last with mov or something similar so that it updates the zero flags @u8 datel_spiSendSDIOCommandR0(u32 arg, u8 cmd); BEGIN_ASM_FUNC datel_spiSendSDIOCommandR0 @@ -115,12 +128,14 @@ BEGIN_ASM_FUNC datel_spiSendSDIOCommandR0 BEGIN_ASM_FUNC datel_spiSendSDIOCommand push {r0-r7, lr} - bl datel_cycleSpi + ldr r3, datel_spiSendSDIOCommandR0_CycleSpi + @ branch to datel_cycleSpi + bl datel_spiSendSDIOCommandR0_InterworkR3 - adr r4, datel_spiSendSDIOCommandR0_ReadSpiByteTimeout + adr r3, datel_spiSendSDIOCommandR0_ReadSpiByteTimeout @ r3 contains ReadSpiByteTimeout @ r7 contains ReadWriteSpiByte - ldm r4!, {r3,r7} + ldm r3, {r3,r7} @ we use the cmd and arg directly from the stack @ r0 is on top, r1 is right below, we read the command id as the last byte pushed of r1, @@ -157,7 +172,9 @@ BEGIN_ASM_FUNC datel_spiSendSDIOCommand bcc datel_spiSendSDIOCommandR0_Interwork movs r0, r6 pop {r1} - pop {r1-r7, pc} + pop {r1-r7} + pop {r2} + mov pc,r2 datel_spiSendSDIOCommandR0_Interwork: bx r7 @@ -165,10 +182,9 @@ datel_spiSendSDIOCommandR0_InterworkR3: bx r3 .balign 4 .pool -datel_cycleSpi_data: - .word REG_MCCNT0 - .word 0x00FFA040 @ MCCNT0_MODE_SPI | MCCNT0_SPI_HOLD_CS | MCCNT0_ENABLE in lower 16 bit, 0xFF in upper 16 - .word 0xA07F6000 @ MCCNT1_RESET_OFF | MCCNT1_CMD_SCRAMBLE | MCCNT1_READ_DATA_DESCRAMBLE | MCCNT1_CLOCK_SCRAMBLER | MCCNT1_LATENCY2(0x3F) +.global datel_spiSendSDIOCommandR0_CycleSpi +datel_spiSendSDIOCommandR0_CycleSpi: + .word 0 .global datel_spiSendSDIOCommandR0_ReadSpiByteTimeout datel_spiSendSDIOCommandR0_ReadSpiByteTimeout: .word 0 diff --git a/arm9/source/patches/platform/datel/DatelWriteSdPatchCode.s b/arm9/source/patches/platform/datel/DatelWriteSdPatchCode.s index 9db6db4..008f1d9 100644 --- a/arm9/source/patches/platform/datel/DatelWriteSdPatchCode.s +++ b/arm9/source/patches/platform/datel/DatelWriteSdPatchCode.s @@ -29,7 +29,10 @@ datel_writeSectorSdhcLabel: movs r1, DATEL_SDIO_CMD25_WRITE_MULTIPLE_BLOCK movs r2, #1 ldr r7, datel_SDWriteMultipleSector_SpiSendSDIOCommand - bl datel_SDWriteMultipleSector_Interwork + + @ call datel_readSpiByte + mov lr,pc + mov pc,r7 bne CMD25_not_ok @ r6 contains datel_SDWriteMultipleSector_WaitSpiByteTimeout @@ -49,11 +52,15 @@ write_next_sector: @ Send start token movs r0, DATEL_SPI_MULTI_BLOCK_WRITE_TOKEN - bl datel_SDWriteMultipleSector_InterworkR1 @ call datel_readWriteSpiByte + @ call datel_readWriteSpiByte + mov lr,pc + mov pc,r1 write_next_byte: ldrb r0, [r4, r5] - bl datel_SDWriteMultipleSector_InterworkR1 @ call datel_readWriteSpiByte + @ call datel_readWriteSpiByte + mov lr,pc + mov pc,r1 adds r5, #1 @ Shifting left by 0x17 will set the Zero flag if the number that was shifted is a multiple @@ -61,11 +68,17 @@ write_next_byte: lsls r0, r5, #0x17 bne write_next_byte - @ write dummy crc - bl datel_SDWriteMultipleSector_Interwork @ call datel_readSpiByte - bl datel_SDWriteMultipleSector_Interwork @ call datel_readSpiByte + @ write dummy crc (ignore result) + @ call datel_readSpiByte + mov lr,pc + mov pc,r7 + @ call datel_readSpiByte + mov lr,pc + mov pc,r7 - bl datel_SDWriteMultipleSector_Interwork @ call datel_readSpiByte + @ call datel_readSpiByte + mov lr,pc + mov pc,r7 @ we check if the lower nibble is equal to DATEL_SD_WRITE_OK subs r0, DATEL_SD_WRITE_OK @@ -73,7 +86,9 @@ write_next_byte: bne write_command_failed @ Wait for card to write data - bl datel_SDWriteMultipleSector_InterworkR6 @ call datel_waitSpiByteTimeout + @ call datel_waitSpiByteTimeout + mov lr,pc + mov pc,r6 beq sector_write_timeout_expired @ r3 holds the total number of bytes to write @@ -82,13 +97,21 @@ write_next_byte: @ send stop token movs r0, DATEL_SPI_END_MULTI_BLOCK_WRITE - bl datel_SDWriteMultipleSector_InterworkR1 @ call datel_readWriteSpiByte + + @ call datel_readWriteSpiByte + mov lr,pc + mov pc,r1 @ send 1 byte clock - bl datel_SDWriteMultipleSector_Interwork @ call datel_readSpiByte - - bl datel_SDWriteMultipleSector_InterworkR6 @ call datel_waitSpiByteTimeout + + @ call datel_readSpiByte + mov lr,pc + mov pc,r7 + @ call datel_waitSpiByteTimeout + mov lr,pc + mov pc,r6 + @ pop {r1-r7, pc} CMD25_not_ok: @@ -97,12 +120,6 @@ sector_write_timeout_expired: @ movs r0, #0 pop {r1-r7, pc} -datel_SDWriteMultipleSector_Interwork: - bx r7 -datel_SDWriteMultipleSector_InterworkR6: - bx r6 -datel_SDWriteMultipleSector_InterworkR1: - bx r1 .balign 4 .pool