diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a86334..98f1bcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,12 @@ ## [Unreleased] ### Added +- DMA card read support for the DSTT platform - by @lifehackerhansol - DMA card read support for the M3DS platform - by @lifehackerhansol ### Fixed - DMA card read offsets for Pokemon Ranger (EU) - by @taxicat1 +- Split DSTT SD read to multiple patches to avoid running out of space - by @lifehackerhansol ## [v1.6.0] - 29 Mar 2026 diff --git a/README.md b/README.md index f5d5a5d..8766b2c 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Note that there can be some game compatibility differences between different pla | AKRPG | Acekard RPG SD card | ❌ | | DATEL | DATEL devices consisting of GAMES n' MUSIC and Action Replay DS(i) Media Edition | ❌ | | DSPICO | DSpico | ✅ | -| DSTT | DSTT, SuperCard DSONE SDHC, r4isdhc.com carts 2014+, r4i-sdhc.com carts, various derivatives | ❌ | +| DSTT | DSTT, SuperCard DSONE SDHC, r4isdhc.com carts 2014+, r4i-sdhc.com carts, various derivatives | ✅ | | EZP | EZ-Flash Parallel | ❌ | | G003 | M3i Zero (GMP-Z003) | ✅ | | ISNITRO | Supports the IS-NITRO-EMULATOR through agb semihosting. | ❌ | diff --git a/arm9/source/patches/platform/dstt/DsttLoaderPlatform.cpp b/arm9/source/patches/platform/dstt/DsttLoaderPlatform.cpp index 11bb198..7f833d2 100644 --- a/arm9/source/patches/platform/dstt/DsttLoaderPlatform.cpp +++ b/arm9/source/patches/platform/dstt/DsttLoaderPlatform.cpp @@ -190,7 +190,7 @@ bool DsttLoaderPlatform::InitializeSdCard(void) if (isSdhc) { sdHostSetRegister(DSTT_SD_HOST_REG_RESET | DSTT_SD_HOST_REG_CLEAN_ROM_MODE | DSTT_SD_HOST_REG_SDHC); - dstt_readSd_sdsc_shift = THUMB_MOVS_REG(THUMB_R7, THUMB_R0); + dstt_readSd_sdsc_shift = THUMB_MOVS_REG(THUMB_R6, THUMB_R0); dstt_writeSd_sdsc_shift = THUMB_NOP; } return true; diff --git a/arm9/source/patches/platform/dstt/DsttLoaderPlatform.h b/arm9/source/patches/platform/dstt/DsttLoaderPlatform.h index 3d0f7e3..a1b9af6 100644 --- a/arm9/source/patches/platform/dstt/DsttLoaderPlatform.h +++ b/arm9/source/patches/platform/dstt/DsttLoaderPlatform.h @@ -1,7 +1,10 @@ #pragma once #include "../LoaderPlatform.h" #include "DsttReadSdPatchCode.h" +#include "DsttReadSdDmaPatchCode.h" #include "DsttWriteSdPatchCode.h" +#include "DsttSdStopTransmissionPatchCode.h" +#include "DsttReadSdHelperPatchCode.h" /// @brief Implementation of LoaderPlatform for the DSTT flashcard class DsttLoaderPlatform : public LoaderPlatform @@ -15,11 +18,30 @@ public: return new DsttReadSdPatchCode(patchHeap, patchCodeCollection.GetOrAddSharedPatchCode([&] { - return new DsttReadSdStopTransmissionPatchCode(patchHeap); + return new DsttSdStopTransmissionPatchCode(patchHeap); + }), + patchCodeCollection.GetOrAddSharedPatchCode([&] + { + return new DsttReadSdHelperPatchCode(patchHeap); })); }); } + const IReadSectorsDmaPatchCode* CreateSdReadDmaPatchCode(PatchCodeCollection& patchCodeCollection, + PatchHeap& patchHeap, const void* miiCardDmaCopy32Ptr) const override + { + return patchCodeCollection.AddUniquePatchCode( + patchHeap, miiCardDmaCopy32Ptr, + patchCodeCollection.GetOrAddSharedPatchCode([&] + { + return new DsttSdStopTransmissionPatchCode(patchHeap); + }), + patchCodeCollection.GetOrAddSharedPatchCode([&] + { + return new DsttReadSdHelperPatchCode(patchHeap); + })); + } + const IWriteSectorsPatchCode* CreateSdWritePatchCode( PatchCodeCollection& patchCodeCollection, PatchHeap& patchHeap) const override { @@ -35,5 +57,7 @@ public: LoaderPlatformType GetPlatformType() const override { return LoaderPlatformType::Slot1; } + bool HasDmaSdReads() const override { return true; } + bool InitializeSdCard() override; }; diff --git a/arm9/source/patches/platform/dstt/DsttReadSdDmaPatchCode.h b/arm9/source/patches/platform/dstt/DsttReadSdDmaPatchCode.h new file mode 100644 index 0000000..7838737 --- /dev/null +++ b/arm9/source/patches/platform/dstt/DsttReadSdDmaPatchCode.h @@ -0,0 +1,44 @@ +#pragma once +#include "sections.h" +#include "patches/PatchCode.h" +#include "../IReadSectorsDmaPatchCode.h" +#include "DsttSdStopTransmissionPatchCode.h" +#include "DsttReadSdHelperPatchCode.h" + +DEFINE_SECTION_SYMBOLS(dstt_readsddma); + +extern "C" void dstt_readSdDma(u32 srcSector, u32 previousSrcSector, u32 dmaChannel, void* dst); + +extern u32 dstt_readSdDma_applySectorCommand_address; +extern u32 dstt_readSdDma_waitDataReady_address; +extern u32 dstt_readSdDma_stopTransmission_address; +extern u32 dstt_readSdDma_miiCardDmaCopy32Ptr; + +class DsttReadSdDmaPatchCode : public PatchCode, public IReadSectorsDmaPatchCode +{ +public: + DsttReadSdDmaPatchCode(PatchHeap& patchHeap, const void* miiCardDmaCopy32Ptr, + const DsttSdStopTransmissionPatchCode* dsttSdStopTransmissionPatchCode, + const DsttReadSdHelperPatchCode* dsttReadSdHelperPatchCode) + : PatchCode(SECTION_START(dstt_readsddma), SECTION_SIZE(dstt_readsddma), patchHeap) + { + dstt_readSdDma_miiCardDmaCopy32Ptr = (u32)miiCardDmaCopy32Ptr; + dstt_readSdDma_stopTransmission_address = (u32)dsttSdStopTransmissionPatchCode->GetStopTransmissionFunction(); + dstt_readSdDma_applySectorCommand_address = (u32)dsttReadSdHelperPatchCode->GetApplySectorCommandFunction(); + dstt_readSdDma_waitDataReady_address = (u32)dsttReadSdHelperPatchCode->GetWaitDataReadyFunction(); + _sdReadDmaFinishFunc = (ReadSectorsDmaFinishFunc)dsttSdStopTransmissionPatchCode->GetStopTransmissionFunction(); + } + + const ReadSectorsDmaFunc GetReadSectorsDmaFunction() const override + { + return (const ReadSectorsDmaFunc)GetAddressAtTarget((void*)dstt_readSdDma); + } + + const ReadSectorsDmaFinishFunc GetReadSectorsDmaFinishFunction() const override + { + return _sdReadDmaFinishFunc; + } + +private: + ReadSectorsDmaFinishFunc _sdReadDmaFinishFunc = 0; +}; diff --git a/arm9/source/patches/platform/dstt/DsttReadSdDmaPatchCode.s b/arm9/source/patches/platform/dstt/DsttReadSdDmaPatchCode.s new file mode 100644 index 0000000..a55d891 --- /dev/null +++ b/arm9/source/patches/platform/dstt/DsttReadSdDmaPatchCode.s @@ -0,0 +1,111 @@ +.cpu arm946e-s +.section "dstt_readsddma", "ax" +.syntax unified +.thumb + +// r0 = src sector +// r1 = previous src sector +// r2 = dma channel +// r3 = dst +.global dstt_readSdDma +.type dstt_readSdDma, %function +dstt_readSdDma: + push {r2-r7,lr} + + ldr r4, =0x040001A0 + + movs r3, #0x80 + strb r3, [r4,#1] + + adr r2, dstt_romSettings + // r2 - dstt_romSettings + // r3 - dstt_readSdDma_applySectorCommand_address + // r5 - dstt_readSdDma_stopTransmission_address + // r6 - dstt_readSdDma_waitDataReady_address + // r7 - dstt_readSdDma_miiCardDmaCopy32Ptr + ldmia r2, {r2, r3, r5, r6, r7} + + cmp r1, #0 + beq applySector + + subs r1, r0, r1 + cmp r1, #1 // if sequential + beq sector_loop_sequential + + blx r5 // dstt_readSdDma_stopTransmission_address + +applySector: + blx r3 // dstt_readSdDma_applySectorCommand_address + + b sector_loop + +sector_loop_sequential: + // set sd host mode DSTT_MODE_RECEIVE_DATA_BLOCK_STOP_CLOCK + // 51 00 00 00 00 00 07 00 + movs r1, #0x51 + str r1, [r4, #0x8] + movs r1, #7 + lsls r1, r1, #16 + str r1, [r4, #0xC] + +sector_loop: + str r2, [r4,#4] + + movs r1, #0x41 + lsls r1, r1, #20 // r1 = 0x04100000 + +cmd_wait_loop: + ldrb r3, [r4,#6] + lsrs r3, r3, #8 + bcc cmd_wait_loop + + ldr r3, [r1, #0x10] + blx r6 // dstt_readSdDma_waitDataReady_address + + // previous push had r2 = dma channel, r3 = dst at top of stack + // pop to the correct register for miiCardDmaCopy32 + pop {r0, r2} + adds r1, #0x10 // Source. r1 is 0x04100000 from the calling function + movs r3, #1 + lsls r3, r3, #9 // (1 << 9) = 512 = count + + blx r7 // dstt_readSdDma_miiCardDmaCopy32Ptr + +cmd81_poll_dma: + // read sd fifo + // 81 xx xx xx xx xx xx xx + // xx bytes are leftover from previous command + movs r1, #0x81 + strb r1, [r4,#0x8] + + movs r1, #0xC0 // select rom mode, with irq + strb r1, [r4,#0x1] + movs r1, #0xA1 + strb r1, [r4,#7] + + pop {r4-r7,pc} + +.balign 4 + +dstt_romSettings: + .word 0xA7180000 + +.global dstt_readSdDma_applySectorCommand_address +dstt_readSdDma_applySectorCommand_address: + .word 0 + +.global dstt_readSdDma_stopTransmission_address +dstt_readSdDma_stopTransmission_address: + .word 0 + +.global dstt_readSdDma_waitDataReady_address +dstt_readSdDma_waitDataReady_address: + .word 0 + +.global dstt_readSdDma_miiCardDmaCopy32Ptr +dstt_readSdDma_miiCardDmaCopy32Ptr: + .word 0 + +.pool + +.end diff --git a/arm9/source/patches/platform/dstt/DsttReadSdHelperPatchCode.h b/arm9/source/patches/platform/dstt/DsttReadSdHelperPatchCode.h new file mode 100644 index 0000000..47b3eda --- /dev/null +++ b/arm9/source/patches/platform/dstt/DsttReadSdHelperPatchCode.h @@ -0,0 +1,34 @@ +#pragma once +#include "sections.h" +#include "thumbInstructions.h" +#include "patches/PatchCode.h" + +DEFINE_SECTION_SYMBOLS(dstt_readsd_helper); + +extern "C" void dstt_readSd_applySectorCommand(void); +extern "C" void dstt_readSd_waitDataReady(void); +extern "C" void dstt_readSd_transferData(); + +extern u16 dstt_readSd_sdsc_shift; + +class DsttReadSdHelperPatchCode : public PatchCode +{ +public: + explicit DsttReadSdHelperPatchCode(PatchHeap& patchHeap) + : PatchCode(SECTION_START(dstt_readsd_helper), SECTION_SIZE(dstt_readsd_helper), patchHeap) { } + + const void* GetApplySectorCommandFunction() const + { + return GetAddressAtTarget((void*)dstt_readSd_applySectorCommand); + } + + const void* GetWaitDataReadyFunction() const + { + return GetAddressAtTarget((void*)dstt_readSd_waitDataReady); + } + + const void* GetTransferDataFunction() const + { + return GetAddressAtTarget((void*)dstt_readSd_transferData); + } +}; diff --git a/arm9/source/patches/platform/dstt/DsttReadSdHelperPatchCode.s b/arm9/source/patches/platform/dstt/DsttReadSdHelperPatchCode.s new file mode 100644 index 0000000..3d80e84 --- /dev/null +++ b/arm9/source/patches/platform/dstt/DsttReadSdHelperPatchCode.s @@ -0,0 +1,103 @@ +.cpu arm7tdmi +.section "dstt_readsd_helper", "ax" +.syntax unified +.thumb + +// r0 = src sector +.global dstt_readSd_applySectorCommand +.type dstt_readSd_applySectorCommand, %function +dstt_readSd_applySectorCommand: + push {r5-r6,lr} + +.global dstt_readSd_sdsc_shift +dstt_readSd_sdsc_shift: + lsls r6, r0, #9 + + // request sd read for sector 0xaabbccdd + // 54 aa bb cc dd 00 00 00 + movs r5, #0x54 + strb r5, [r4,#0x8] + lsrs r5, r6, #24 + strb r5, [r4,#0x9] + lsrs r5, r6, #16 + strb r5, [r4,#0xA] + lsrs r5, r6, #8 + strb r5, [r4,#0xB] + // make sure the last 3 bytes are zero + movs r5, #0xFF + ands r6, r5 + str r6, [r4,#0xC] // storing as little-endian puts the bottom 8 bits as first byte + + pop {r5-r6,pc} + +.balign 4 + +.global dstt_readSd_waitDataReady +.type dstt_readSd_waitDataReady, %function +dstt_readSd_waitDataReady: + push {r5-r7,lr} + + movs r6, #0x41 + lsls r6, r6, #20 // r6 = 0x04100000 + + // sd fifo full poll + // 80 xx xx xx xx xx xx xx + // xx bytes are leftover from previous command + movs r7, #0x80 + strb r7, [r4,#0x8] + + ldr r7, =0xA7180000 +cmd80_poll_loop: + str r7, [r4,#4] + +cmd80_wait_loop: + ldrb r5, [r4,#6] + lsrs r5, r5, #8 + bcc cmd80_wait_loop + ldr r5, [r6, #0x10] + cmp r5, #0 + bne cmd80_poll_loop + + pop {r5-r7,pc} + +.balign 4 + +// r1 = dst, will be incremented by 512 +.global dstt_readSd_transferData +.type dstt_readSd_transferData, %function +dstt_readSd_transferData: + push {r5-r7,lr} + + ldr r5, =0xA7180000 + + movs r6, #0x41 + lsls r6, r6, #20 // r6 = 0x04100000 + + // read sd fifo + // 81 xx xx xx xx xx xx xx + // xx bytes are leftover from previous command + movs r5, #0x81 + strb r5, [r4,#0x8] + movs r5, #0xA1 + strb r5, [r4,#7] + +cmd81_data_loop: + ldrb r5, [r4,#6] + lsrs r5, r5, #8 // check if data is ready + bcc cmd81_data_loop_check_transfer_end // if not skip reading + + ldr r5, [r6, #0x10] + stmia r1!, {r5} + +cmd81_data_loop_check_transfer_end: + ldrb r5, [r4,#7] + lsrs r5, r5, #8 // check if transfer is done + bcs cmd81_data_loop + + pop {r5-r7,pc} + +.balign 4 + +.pool + +.end diff --git a/arm9/source/patches/platform/dstt/DsttReadSdPatchCode.h b/arm9/source/patches/platform/dstt/DsttReadSdPatchCode.h index 498c55c..e9b9d9c 100644 --- a/arm9/source/patches/platform/dstt/DsttReadSdPatchCode.h +++ b/arm9/source/patches/platform/dstt/DsttReadSdPatchCode.h @@ -3,36 +3,30 @@ #include "thumbInstructions.h" #include "patches/PatchCode.h" #include "../IReadSectorsPatchCode.h" +#include "DsttSdStopTransmissionPatchCode.h" +#include "DsttReadSdHelperPatchCode.h" DEFINE_SECTION_SYMBOLS(dstt_readsd); -DEFINE_SECTION_SYMBOLS(dstt_readsd_stopTransmission); extern "C" void dstt_readSd(u32 srcSector, void* dst, u32 sectorCount); -extern "C" void dstt_stopTransmission(); +extern u32 dstt_readSd_applySectorCommand_address; +extern u32 dstt_waitDataReady_address; +extern u32 dstt_transferData_address; extern u32 dstt_stopTransmission_address; -extern u16 dstt_readSd_sdsc_shift; - -class DsttReadSdStopTransmissionPatchCode : public PatchCode -{ -public: - explicit DsttReadSdStopTransmissionPatchCode(PatchHeap& patchHeap) - : PatchCode(SECTION_START(dstt_readsd_stopTransmission), SECTION_SIZE(dstt_readsd_stopTransmission), patchHeap) { } - - const void* GetStopTransmissionFunction() const - { - return GetAddressAtTarget((void*)dstt_stopTransmission); - } -}; class DsttReadSdPatchCode : public PatchCode, public IReadSectorsPatchCode { public: explicit DsttReadSdPatchCode(PatchHeap& patchHeap, - const DsttReadSdStopTransmissionPatchCode* dsttReadSdStopTransmissionPatchCode) + const DsttSdStopTransmissionPatchCode* dsttSdStopTransmissionPatchCode, + const DsttReadSdHelperPatchCode* dsttReadSdHelperPatchCode) : PatchCode(SECTION_START(dstt_readsd), SECTION_SIZE(dstt_readsd), patchHeap) { - dstt_stopTransmission_address = (u32)dsttReadSdStopTransmissionPatchCode->GetStopTransmissionFunction(); + dstt_readSd_applySectorCommand_address = (u32)dsttReadSdHelperPatchCode->GetApplySectorCommandFunction(); + dstt_stopTransmission_address = (u32)dsttSdStopTransmissionPatchCode->GetStopTransmissionFunction(); + dstt_waitDataReady_address = (u32)dsttReadSdHelperPatchCode->GetWaitDataReadyFunction(); + dstt_transferData_address = (u32)dsttReadSdHelperPatchCode->GetTransferDataFunction(); } const ReadSectorsFunc GetReadSectorsFunction() const override diff --git a/arm9/source/patches/platform/dstt/DsttReadSdPatchCode.s b/arm9/source/patches/platform/dstt/DsttReadSdPatchCode.s index d61d3c6..74ee8aa 100644 --- a/arm9/source/patches/platform/dstt/DsttReadSdPatchCode.s +++ b/arm9/source/patches/platform/dstt/DsttReadSdPatchCode.s @@ -11,27 +11,11 @@ dstt_readSd: push {r4-r7,lr} -.global dstt_readSd_sdsc_shift -dstt_readSd_sdsc_shift: - lsls r7, r0, #9 + ldr r3, =0xA7180000 + ldr r4, =0x040001A0 - adr r0, dstt_stopTransmission_address - ldmia r0, {r0, r3, r4} - - // request sd read for sector 0xaabbccdd - // 54 aa bb cc dd 00 00 00 - movs r5, #0x54 - strb r5, [r4,#0x8] - lsrs r5, r7, #24 - strb r5, [r4,#0x9] - lsrs r5, r7, #16 - strb r5, [r4,#0xA] - lsrs r5, r7, #8 - strb r5, [r4,#0xB] - // make sure the last 3 bytes are zero - movs r5, #0xFF - ands r7, r5 - str r7, [r4,#0xC] // storing as little-endian puts the bottom 8 bits as first byte + ldr r7, dstt_readSd_applySectorCommand_address + bl blx_r7 movs r7, #0x80 strb r7, [r4,#1] @@ -48,42 +32,11 @@ cmd54_wait_loop: bcc cmd54_wait_loop ldr r5, [r6, #0x10] - // sd fifo full poll - // 80 xx xx xx xx xx xx xx - // xx bytes are leftover from previous command - strb r7, [r4,#0x8] + ldr r7, dstt_waitDataReady_address + bl blx_r7 -cmd80_poll_loop: - str r3, [r4,#4] - -cmd80_wait_loop: - ldrb r5, [r4,#6] - lsrs r5, r5, #8 - bcc cmd80_wait_loop - ldr r5, [r6, #0x10] - cmp r5, #0 - bne cmd80_poll_loop - - // read sd fifo - // 81 xx xx xx xx xx xx xx - // xx bytes are leftover from previous command - movs r5, #0x81 - strb r5, [r4,#0x8] - movs r5, #0xA1 - strb r5, [r4,#7] - -cmd81_data_loop: - ldrb r5, [r4,#6] - lsrs r5, r5, #8 // check if data is ready - bcc cmd81_data_loop_check_transfer_end // if not skip reading - - ldr r5, [r6, #0x10] - stmia r1!, {r5} - -cmd81_data_loop_check_transfer_end: - ldrb r5, [r4,#7] - lsrs r5, r5, #8 // check if transfer is done - bcs cmd81_data_loop + ldr r7, dstt_transferData_address + bl blx_r7 subs r2, #1 beq stop_transmission @@ -99,77 +52,31 @@ cmd81_data_loop_check_transfer_end: b sector_loop stop_transmission: - bx r0 + ldr r7, dstt_stopTransmission_address + bl blx_r7 + pop {r4-r7,pc} + +blx_r7: + bx r7 .balign 4 +.global dstt_readSd_applySectorCommand_address +dstt_readSd_applySectorCommand_address: + .word 0 + +.global dstt_waitDataReady_address +dstt_waitDataReady_address: + .word 0 + +.global dstt_transferData_address +dstt_transferData_address: + .word 0 + .global dstt_stopTransmission_address dstt_stopTransmission_address: .word 0 -settings: - .word 0xA7180000 - -regbase: - .word 0x040001A0 - .pool -.section "dstt_readsd_stopTransmission", "ax" -.thumb -.global dstt_stopTransmission -.type dstt_stopTransmission, %function -dstt_stopTransmission: - // send SD_CMD12_STOP_TRANSMISSION - - // set sd host mode DSTT_MODE_SDCMD_RESPONSE_32BIT, SD_CMD12_STOP_TRANSMISSION - // 51 00 00 00 00 0C 01 00 - movs r5, #0x51 - str r5, [r4,#0x8] - ldr r5,= 0x00010C00 - str r5, [r4,#0xC] - str r3, [r4,#4] - -cmd51_1_wait_loop: - ldrb r5, [r4,#6] - lsrs r5, r5, #8 - bcc cmd51_1_wait_loop - ldr r5, [r6, #0x10] - - // sd busy poll - // 50 xx xx xx xx xx xx xx - // xx bytes are leftover from previous command - movs r5, #0x50 - strb r5, [r4,#0x8] - -cmd50_poll_loop: - str r3, [r4,#4] - -cmd50_wait_loop: - ldrb r5, [r4,#6] - lsrs r5, r5, #8 - bcc cmd50_wait_loop - ldr r5, [r6, #0x10] - cmp r5, #0 - bne cmd50_poll_loop - - // read sd response - // 52 xx xx xx xx xx xx xx - // xx bytes are leftover from previous command - movs r5, #0x52 - strb r5, [r4,#0x8] - str r3, [r4,#4] - -cmd52_wait_loop: - ldrb r5, [r4,#6] - lsrs r5, r5, #8 - bcc cmd52_wait_loop - ldr r5, [r6, #0x10] - - pop {r4-r7,pc} - -.balign 4 - -.pool - -.end \ No newline at end of file +.end diff --git a/arm9/source/patches/platform/dstt/DsttSdStopTransmissionPatchCode.h b/arm9/source/patches/platform/dstt/DsttSdStopTransmissionPatchCode.h new file mode 100644 index 0000000..8b83131 --- /dev/null +++ b/arm9/source/patches/platform/dstt/DsttSdStopTransmissionPatchCode.h @@ -0,0 +1,20 @@ +#pragma once +#include "sections.h" +#include "thumbInstructions.h" +#include "patches/PatchCode.h" + +DEFINE_SECTION_SYMBOLS(dstt_sdstoptransmission); + +extern "C" void dstt_sdStopTransmission(); + +class DsttSdStopTransmissionPatchCode : public PatchCode +{ +public: + explicit DsttSdStopTransmissionPatchCode(PatchHeap& patchHeap) + : PatchCode(SECTION_START(dstt_sdstoptransmission), SECTION_SIZE(dstt_sdstoptransmission), patchHeap) { } + + const void* GetStopTransmissionFunction() const + { + return GetAddressAtTarget((void*)dstt_sdStopTransmission); + } +}; diff --git a/arm9/source/patches/platform/dstt/DsttSdStopTransmissionPatchCode.s b/arm9/source/patches/platform/dstt/DsttSdStopTransmissionPatchCode.s new file mode 100644 index 0000000..eb504bd --- /dev/null +++ b/arm9/source/patches/platform/dstt/DsttSdStopTransmissionPatchCode.s @@ -0,0 +1,73 @@ +.cpu arm7tdmi +.syntax unified +.thumb + +.section "dstt_sdstoptransmission", "ax" +.global dstt_sdStopTransmission +.type dstt_sdStopTransmission, %function +dstt_sdStopTransmission: + // send SD_CMD12_STOP_TRANSMISSION + push {r3-r6,lr} + + ldr r3, =0xA7180000 + ldr r4, =0x040001A0 + + // select rom mode, without irq + // the caller may not have ensured this is set + movs r6, #0x80 + strb r6, [r4,#1] + + // set sd host mode DSTT_MODE_SDCMD_RESPONSE_32BIT, SD_CMD12_STOP_TRANSMISSION + // 51 00 00 00 00 0C 01 00 + movs r5, #0x51 + str r5, [r4,#0x8] + ldr r5,= 0x00010C00 + str r5, [r4,#0xC] + str r3, [r4,#0x4] + + movs r6, #0x41 + lsls r6, r6, #20 // r6 = 0x04100000 + +cmd51_1_wait_loop: + ldrb r5, [r4,#6] + lsrs r5, r5, #8 + bcc cmd51_1_wait_loop + ldr r5, [r6, #0x10] + + // sd busy poll + // 50 xx xx xx xx xx xx xx + // xx bytes are leftover from previous command + movs r5, #0x50 + strb r5, [r4,#0x8] + +cmd50_poll_loop: + str r3, [r4,#4] + +cmd50_wait_loop: + ldrb r5, [r4,#6] + lsrs r5, r5, #8 + bcc cmd50_wait_loop + ldr r5, [r6, #0x10] + cmp r5, #0 + bne cmd50_poll_loop + + // read sd response + // 52 xx xx xx xx xx xx xx + // xx bytes are leftover from previous command + movs r5, #0x52 + strb r5, [r4,#0x8] + str r3, [r4,#4] + +cmd52_wait_loop: + ldrb r5, [r4,#6] + lsrs r5, r5, #8 + bcc cmd52_wait_loop + ldr r5, [r6, #0x10] + + pop {r3-r6,pc} + +.balign 4 + +.pool + +.end