diff --git a/README.md b/README.md index e84385b3..3004b49a 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Note that there can be some game compatibility differences between different pla | 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 | ❌ | -| EZP | EZ-Flash Parallel | ❌ | +| EZP | EZ-Flash Parallel | ✅ | | G003 | M3i Zero (GMP-Z003) | ✅ | | ISNITRO | Supports the IS-NITRO-EMULATOR through agb semihosting. | ❌ | | M3DS | M3 DS Real, M3i Zero, iTouchDS, r4rts.com, r4isdhc.com RTS (black) | ❌ | diff --git a/arm9/source/patches/platform/ezp/EzpLoaderPlatform.h b/arm9/source/patches/platform/ezp/EzpLoaderPlatform.h index 14ab7ce5..8f0f6fb6 100644 --- a/arm9/source/patches/platform/ezp/EzpLoaderPlatform.h +++ b/arm9/source/patches/platform/ezp/EzpLoaderPlatform.h @@ -1,6 +1,7 @@ #pragma once #include "../LoaderPlatform.h" #include "EzpReadSectorsPatchCode.h" +#include "EzpReadSectorsDmaPatchCode.h" #include "EzpReadSdDataPatchCode.h" #include "EzpWriteSectorsPatchCode.h" @@ -21,6 +22,13 @@ class EzpLoaderPlatform : public LoaderPlatform }); } + const IReadSectorsDmaPatchCode* CreateSdReadDmaPatchCode(PatchCodeCollection& patchCodeCollection, + PatchHeap& patchHeap, const void* miiCardDmaCopy32Ptr) const override + { + return patchCodeCollection.AddUniquePatchCode( + patchHeap, miiCardDmaCopy32Ptr); + } + const IWriteSectorsPatchCode* CreateSdWritePatchCode( PatchCodeCollection& patchCodeCollection, PatchHeap& patchHeap) const override { @@ -30,5 +38,7 @@ class EzpLoaderPlatform : public LoaderPlatform }); } + bool HasDmaSdReads() const override { return true; } + LoaderPlatformType GetPlatformType() const override { return LoaderPlatformType::Slot1; } }; diff --git a/arm9/source/patches/platform/ezp/EzpReadSectorsDmaPatchCode.h b/arm9/source/patches/platform/ezp/EzpReadSectorsDmaPatchCode.h new file mode 100644 index 00000000..31860e17 --- /dev/null +++ b/arm9/source/patches/platform/ezp/EzpReadSectorsDmaPatchCode.h @@ -0,0 +1,31 @@ +#pragma once +#include "sections.h" +#include "patches/PatchCode.h" +#include "../IReadSectorsDmaPatchCode.h" + +DEFINE_SECTION_SYMBOLS(ezp_readsectorsdma); + +extern "C" void ezp_readSectorsDma(u32 srcSector, u32 previousSrcSector, u32 dmaChannel, void* dst); +extern "C" void ezp_finishReadSectorsDma(void); + +extern u32 ezp_readSectorsDma_miiCardDmaCopy32Ptr; + +class EzpReadSectorsDmaPatchCode : public PatchCode, public IReadSectorsDmaPatchCode +{ +public: + explicit EzpReadSectorsDmaPatchCode(PatchHeap& patchHeap, const void* miiCardDmaCopy32Ptr) + : PatchCode(SECTION_START(ezp_readsectorsdma), SECTION_SIZE(ezp_readsectorsdma), patchHeap) + { + ezp_readSectorsDma_miiCardDmaCopy32Ptr = (u32)miiCardDmaCopy32Ptr; + } + + const ReadSectorsDmaFunc GetReadSectorsDmaFunction() const override + { + return (const ReadSectorsDmaFunc)GetAddressAtTarget((void*)ezp_readSectorsDma); + } + + const ReadSectorsDmaFinishFunc GetReadSectorsDmaFinishFunction() const override + { + return (const ReadSectorsDmaFinishFunc)GetAddressAtTarget((void*)ezp_finishReadSectorsDma); + } +}; diff --git a/arm9/source/patches/platform/ezp/EzpReadSectorsDmaPatchCode.s b/arm9/source/patches/platform/ezp/EzpReadSectorsDmaPatchCode.s new file mode 100644 index 00000000..63cc9d4e --- /dev/null +++ b/arm9/source/patches/platform/ezp/EzpReadSectorsDmaPatchCode.s @@ -0,0 +1,96 @@ +.cpu arm946e-s +.section "ezp_readsectorsdma", "ax" +.syntax unified +.thumb + +// r0 = src sector +// r1 = previous src sector +// r2 = dma channel +// r3 = dst +.global ezp_readSectorsDma +.type ezp_readSectorsDma, %function +ezp_readSectorsDma: + push {r4-r7,lr} + + ldr r4, =0x040001A0 + movs r7, #0x80 + strb r7, [r4,#0x1] + +sector_loop: + // request sd read for sector 0xaabbccdd + // for xx number of sectors (up to 4 sectors) + // TODO implement multiple sectors + // B9 00 00 xx aa bb cc dd + movs r7, #0xB9 + str r7, [r4,#0x8] + movs r7, #1 + strb r7, [r4,#0xB] + lsrs r7, r0, #24 + strb r7, [r4,#0xC] + lsrs r7, r0, #16 + strb r7, [r4,#0xD] + lsrs r7, r0, #8 + strb r7, [r4,#0xE] + strb r0, [r4,#0xF] + + ldr r1, =0x04100010 + +B9_poll_loop: + ldr r7, =0xA75860C8 + str r7, [r4,#0x4] + +B9_poll_transfer_loop: + ldrb r7, [r4,#0x6] + lsrs r7, r7, #8 + bcc B9_poll_check_transfer_end + ldr r5, [r1] + +B9_poll_check_transfer_end: + ldrb r7, [r4,#0x7] + lsrs r7, r7, #8 + bcs B9_poll_transfer_loop + + cmp r5, #0 + bne B9_poll_loop + + // Setup data read card command + movs r7, #0xBA + str r7, [r4,#0x8] + str r5, [r4,#0xC] // r5 is 0 here + +readDataWithDma: + movs r0, r2 // DMA channel + movs r2, r3 // Destination + movs r3, #1 + lsls r3, r3, #9 // (1 << 9) = 512 = count + + ldr r6, ezp_readSectorsDma_miiCardDmaCopy32Ptr + blx r6 + +BA_data_dma: + movs r7, #0xC0 // select rom mode, with irq + strb r7, [r4,#0x1] + ldr r7, =0xA15A6000 + str r7, [r4,#0x4] + + pop {r4-r7,pc} + +.balign 4 + +.global ezp_readSectorsDma_miiCardDmaCopy32Ptr +ezp_readSectorsDma_miiCardDmaCopy32Ptr: + .word 0 + +.pool + +.global ezp_finishReadSectorsDma +.type ezp_finishReadSectorsDma, %function +ezp_finishReadSectorsDma: + // No cleanup needed on this platform. + bx lr + +.balign 4 + +.pool + +.end