Initial commit

This commit is contained in:
Gericom
2025-11-22 11:08:28 +01:00
commit 9cf3ffbfcf
358 changed files with 58350 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
#pragma once
#include "common.h"
#include "../LoaderPlatform.h"
#include "dspicoReadSectorsAsm.h"
#include "dspicoReadSdSectorDmaAsm.h"
#include "dspicoWriteSectorsAsm.h"
/// @brief Implementation of LoaderPlatform for the DS pico flashcard
class DSPicoLoaderPlatform : public LoaderPlatform
{
public:
const SdReadPatchCode* CreateSdReadPatchCode(
PatchCodeCollection& patchCodeCollection, PatchHeap& patchHeap) const override
{
return patchCodeCollection.GetOrAddSharedPatchCode([&]
{
return new DSPicoReadSdSectorsPatchCode(patchHeap,
patchCodeCollection.GetOrAddSharedPatchCode([&]
{
return new DSPicoReadSdSectorsDirectPatchCode(patchHeap);
}));
});
}
const SdReadDmaPatchCode* CreateSdReadDmaPatchCode(PatchCodeCollection& patchCodeCollection,
PatchHeap& patchHeap, const void* miiCardDmaCopy32Ptr) const override
{
auto pollSdDataReadyPatchCode = patchCodeCollection.GetOrAddSharedPatchCode([&]
{
return new DSPicoReadSdSectorDmaPollSdDataReadyPatchCode(patchHeap);
});
return patchCodeCollection.AddUniquePatchCode<DSPicoReadSdSectorDmaPatchCode>(
patchHeap, pollSdDataReadyPatchCode, miiCardDmaCopy32Ptr);
}
const SdWritePatchCode* CreateSdWritePatchCode(
PatchCodeCollection& patchCodeCollection, PatchHeap& patchHeap) const override
{
return patchCodeCollection.GetOrAddSharedPatchCode([&]
{
return new DSPicoWriteSdSectorsPatchCode(patchHeap);
});
}
bool HasDmaSdReads() const override { return true; }
};

View File

@@ -0,0 +1,56 @@
#pragma once
#include "sections.h"
#include "../SdReadDmaPatchCode.h"
DEFINE_SECTION_SYMBOLS(dspico_readsdsectordma);
DEFINE_SECTION_SYMBOLS(dspico_readsdsectordma_pollSdDataReady);
extern "C" void dspico_readSdSectorDma(u32 srcSector, u32 previousSrcSector, u32 dmaChannel, void* dst);
extern "C" void dspico_readSdSectorDma_pollSdDataReady();
extern "C" void dspico_finishReadSdSectorDma(void);
extern u32 dspico_readSdSectorDma_miiCardDmaCopy32Ptr;
extern u32 dspico_readSdSectorDma_pollSdDataReadyPtr;
class DSPicoReadSdSectorDmaPollSdDataReadyPatchCode : public PatchCode
{
public:
explicit DSPicoReadSdSectorDmaPollSdDataReadyPatchCode(PatchHeap& patchHeap)
: PatchCode(SECTION_START(dspico_readsdsectordma_pollSdDataReady), SECTION_SIZE(dspico_readsdsectordma_pollSdDataReady), patchHeap) { }
const void* GetPollSdDataReadyFunction() const
{
return GetAddressAtTarget((void*)dspico_readSdSectorDma_pollSdDataReady);
}
const SdReadDmaPatchCode::SdReadDmaFinishFunc GetSdReadDmaFinishFunction() const
{
return (const SdReadDmaPatchCode::SdReadDmaFinishFunc)GetAddressAtTarget((void*)dspico_finishReadSdSectorDma);
}
};
class DSPicoReadSdSectorDmaPatchCode : public SdReadDmaPatchCode
{
public:
DSPicoReadSdSectorDmaPatchCode(PatchHeap& patchHeap,
const DSPicoReadSdSectorDmaPollSdDataReadyPatchCode* pollSdDataReadyPatchCode, const void* miiCardDmaCopy32Ptr)
: SdReadDmaPatchCode(SECTION_START(dspico_readsdsectordma), SECTION_SIZE(dspico_readsdsectordma), patchHeap)
, _sdReadDmaFinishFunc(pollSdDataReadyPatchCode->GetSdReadDmaFinishFunction())
{
dspico_readSdSectorDma_miiCardDmaCopy32Ptr = (u32)miiCardDmaCopy32Ptr;
dspico_readSdSectorDma_pollSdDataReadyPtr = (u32)pollSdDataReadyPatchCode->GetPollSdDataReadyFunction();
}
const SdReadDmaFunc GetSdReadDmaFunction() const override
{
return (const SdReadDmaFunc)GetAddressAtTarget((void*)dspico_readSdSectorDma);
}
const SdReadDmaFinishFunc GetSdReadDmaFinishFunction() const override
{
return _sdReadDmaFinishFunc;
}
private:
const SdReadDmaFinishFunc _sdReadDmaFinishFunc;
};

View File

@@ -0,0 +1,135 @@
.cpu arm946e-s
.section "dspico_readsdsectordma", "ax"
.syntax unified
.thumb
// r0 = src sector
// r1 = previous src sector
// r2 = dma channel
// r3 = dst
.global dspico_readSdSectorDma
.type dspico_readSdSectorDma, %function
dspico_readSdSectorDma:
push {r2,r3,r4,r5,r6,r7,lr}
adr r5, readRequestSettings
// readRequestSettings, regBase, cardDataRegAddress, miiCardDmaCopy32Ptr, pollSdDataReadyPtr
ldmia r5, {r2,r4,r5,r6,r7}
movs r3, #0x80
strb r3, [r4, #0x9] // select rom mode, without irq
cmp r1, #0 // if first sector
beq 1f // first sector, skip poll
blx r7 // pollSdDataReady
1:
subs r1, r0, r1
cmp r1, #1 // if sequential
beq readDataWithDma
// card_romSetCmd(0xE300000000000000ull | sector);
movs r3, #0xE3
str r3, [r4, #0x10] // E3 00 00 00
movs r3, r0
rors r3, r4 // ror 24
str r3, [r4, #0x14] // AA XX CC XX
strb r0, [r4, #0x17] // AA XX CC DD
lsrs r3, r0, #16
strb r3, [r4, #0x15]
// card_romStartXfer
str r2, [r4, #0xC] // REG_MCCNT1 = MCCNT1_ENABLE | settings;
blx r7 // pollSdDataReady
readDataWithDma:
pop {r0,r2} // dma channel, dst
movs r1, r5 // src = 0x04100010
movs r3, #1
lsls r3, r3, #9 // (1 << 9) = 512 = count
blx r6
3:
ldrb r0, [r4, #0xF]
lsrs r0, r0, #8
bcs 3b
// r0 is zero here
str r0, [r4, #0x14] // 00 00 00 00
movs r0, #0xE5
str r0, [r4, #0x10] // E5 00 00 00
ldr r0,= 0xA1444000
movs r1, #0xC0
strb r1, [r4, #0x9] // select rom mode, with irq
str r0, [r4, #0xC] // REG_MCCNT1 = MCCNT1_ENABLE | settings;
pop {r4,r5,r6,r7,pc} // popping pc is safe for armv4t when not switching mode
.balign 4
readRequestSettings:
.word 0xA0406000
regBase:
.word 0x04000198
cardDataRegAddress:
.word 0x04100010
.global dspico_readSdSectorDma_miiCardDmaCopy32Ptr
dspico_readSdSectorDma_miiCardDmaCopy32Ptr:
.word 0
.global dspico_readSdSectorDma_pollSdDataReadyPtr
dspico_readSdSectorDma_pollSdDataReadyPtr:
.word 0
.pool
.section "dspico_readsdsectordma_pollSdDataReady", "ax"
.thumb
.global dspico_readSdSectorDma_pollSdDataReady
.type dspico_readSdSectorDma_pollSdDataReady, %function
dspico_readSdSectorDma_pollSdDataReady:
ldrb r3, [r4, #0xF]
lsrs r3, r3, #8
bcs dspico_readSdSectorDma_pollSdDataReady
// r3 is zero here
// card_romSetCmd(0xE400000000000000ull);
str r3, [r4, #0x14] // 00 00 00 00
movs r3, #0xE4
str r3, [r4, #0x10] // E4 00 00 00
// card_romStartXfer
ldr r3,= 0xA7446000
str r3, [r4, #0xC] // REG_MCCNT1 = MCCNT1_ENABLE | settings;
1:
ldrb r3, [r4, #0xE]
lsrs r3, r3, #8
bcc 1b
ldr r3, [r5] // [0x04100010]
cmp r3, #0
beq dspico_readSdSectorDma_pollSdDataReady
bx lr
.global dspico_finishReadSdSectorDma
.type dspico_finishReadSdSectorDma, %function
dspico_finishReadSdSectorDma:
push {r4,r5,lr}
ldr r4,= 0x04000198
ldr r5,= 0x04100010
movs r3, #0x80
strb r3, [r4, #0x9] // select rom mode, without irq
bl dspico_readSdSectorDma_pollSdDataReady
pop {r4,r5,pc}
.balign 4
.pool
.end

View File

@@ -0,0 +1,38 @@
#pragma once
#include "sections.h"
#include "../SdReadPatchCode.h"
DEFINE_SECTION_SYMBOLS(dspico_readsdsectors);
DEFINE_SECTION_SYMBOLS(dspico_readsdsectors_readdirect);
extern "C" void dspico_readSdSectors(u32 srcSector, void* dst, u32 sectorCount);
extern "C" void dspico_readSdSectorsDirect();
extern u32 dspico_readsdsectors_readDirectAddress;
class DSPicoReadSdSectorsDirectPatchCode : public PatchCode
{
public:
explicit DSPicoReadSdSectorsDirectPatchCode(PatchHeap& patchHeap)
: PatchCode(SECTION_START(dspico_readsdsectors_readdirect), SECTION_SIZE(dspico_readsdsectors_readdirect), patchHeap) { }
const void* GetReadSdSectorsDirectFunction() const
{
return GetAddressAtTarget((void*)dspico_readSdSectorsDirect);
}
};
class DSPicoReadSdSectorsPatchCode : public SdReadPatchCode
{
public:
DSPicoReadSdSectorsPatchCode(PatchHeap& patchHeap, const DSPicoReadSdSectorsDirectPatchCode* readSdSectorsDirectPatchCode)
: SdReadPatchCode(SECTION_START(dspico_readsdsectors), SECTION_SIZE(dspico_readsdsectors), patchHeap)
{
dspico_readsdsectors_readDirectAddress = (u32)readSdSectorsDirectPatchCode->GetReadSdSectorsDirectFunction();
}
const SdReadFunc GetSdReadFunction() const override
{
return (const SdReadFunc)GetAddressAtTarget((void*)dspico_readSdSectors);
}
};

View File

@@ -0,0 +1,129 @@
.cpu arm7tdmi
.section "dspico_readsdsectors", "ax"
.syntax unified
.thumb
// r0 = src sector
// r1 = dst
// r2 = sector count
.global dspico_readSdSectors
.type dspico_readSdSectors, %function
dspico_readSdSectors:
push {r0,r1,r2,r4-r7,lr}
pop {r4,r5,r6}
1:
// card_romSetCmd(0xE300000000000000ull | sector);
adr r2, read_request_settings
ldmia r2, {r1,r2}
movs r0, #0xE3
str r0, [r2, #0x10] // E3 00 00 00
movs r0, r4
rors r0, r2 // ror 24
str r0, [r2, #0x14] // AA XX CC XX
strb r4, [r2, #0x17] // AA XX CC DD
lsrs r0, r4, #16
strb r0, [r2, #0x15]
// card_romStartXfer
movs r0, #0x80
strb r0, [r2, #0x9]
str r1, [r2, #0xC] // REG_MCCNT1 = MCCNT1_ENABLE | settings;
ldr r3, dspico_readsdsectors_readDirectAddress
bl blx_r3
pop {r4-r7,pc} // popping pc is safe for armv4t when not switching mode
blx_r3:
bx r3
.balign 4
read_request_settings:
.word 0xA0406000
reg_base:
.word 0x04000198
.global dspico_readsdsectors_readDirectAddress
dspico_readsdsectors_readDirectAddress:
.word 0
.pool
.section "dspico_readsdsectors_readdirect", "ax"
.thumb
.global dspico_readSdSectorsDirect
.type dspico_readSdSectorsDirect, %function
dspico_readSdSectorsDirect:
push {r4,r6,r7,lr}
b poll_read_done
1:
movs r0, #0xE5
str r0, [r2, #0x10] // E5 00 00 00
movs r0, #0
str r0, [r2, #0x14] // 00 00 00 00
ldr r0,= 0xA1444000
// card_romStartXfer
3:
ldrb r4, [r2, #0xF]
lsrs r4, r4, #8
bcs 3b
str r0, [r2, #0xC] // REG_MCCNT1 = MCCNT1_ENABLE | settings;
movs r0, #128
ldr r4,= 0x04100000
2:
ldrb r3, [r2, #0xE]
lsrs r3, r3, #8
bcc 2b
ldr r3, [r4, #0x10]
stmia r5!, {r3}
subs r0, #1
bne 2b
subs r6, #1 // count -= len
// card_romWaitBusy
poll_read_done:
3:
ldrb r1, [r2, #0xF]
lsrs r1, r1, #8
bcs 3b
// card_romSetCmd(0xE400000000000000ull);
movs r1, #0xE4
str r1, [r2, #0x10] // E4 00 00 00
movs r1, #0
str r1, [r2, #0x14] // 00 00 00 00
// card_romStartXfer
ldr r1,= 0xA7446000
str r1, [r2, #0xC] // REG_MCCNT1 = MCCNT1_ENABLE | settings;
4:
ldrb r1, [r2, #0xE]
lsrs r1, r1, #8
bcc 4b
movs r1, #0x41
lsls r1, r1, #20 // 0x04100000
ldr r1, [r1, #0x10]
cmp r1, #0
beq poll_read_done
cmp r6, #0
bne 1b
pop {r4,r6,r7,pc}
.balign 4
.pool
.end

View File

@@ -0,0 +1,19 @@
#pragma once
#include "sections.h"
#include "../SdWritePatchCode.h"
DEFINE_SECTION_SYMBOLS(dspico_writesdsectors);
extern "C" void dspico_writeSdSectors(u32 dstSector, const void* src, u32 sectorCount);
class DSPicoWriteSdSectorsPatchCode : public SdWritePatchCode
{
public:
explicit DSPicoWriteSdSectorsPatchCode(PatchHeap& patchHeap)
: SdWritePatchCode(SECTION_START(dspico_writesdsectors), SECTION_SIZE(dspico_writesdsectors), patchHeap) { }
const SdWriteFunc GetSdWriteFunction() const override
{
return (const SdWriteFunc)GetAddressAtTarget((void*)dspico_writeSdSectors);
}
};

View File

@@ -0,0 +1,91 @@
.cpu arm7tdmi
.section "dspico_writesdsectors", "ax"
.syntax unified
.thumb
// r0 = dst sector
// r1 = src
// r2 = sector count
.global dspico_writeSdSectors
.type dspico_writeSdSectors, %function
dspico_writeSdSectors:
push {r0,r1,r2,r4-r7,lr}
pop {r4,r5,r6}
1:
// card_romSetCmd(0xF6E10D9B00000000ull | sector);
adr r2, write_cmd_rev
ldmia r2, {r0,r1,r2,r3}
str r0, [r2, #0x10] // F6 E1 0D 9B
movs r0, r4
rors r0, r2 // ror 24
str r0, [r2, #0x14] // AA XX CC XX
strb r4, [r2, #0x17] // AA XX CC DD
lsrs r0, r4, #16
strb r0, [r2, #0x15]
// card_romStartXfer
movs r0, #0x80
strb r0, [r2, #0x9]
str r1, [r2, #0xC] // REG_MCCNT1 = MCCNT1_ENABLE | settings;
movs r1, #0x41
lsls r1, r1, #20 // 0x04100000
2:
ldrb r7, [r2, #0xE]
lsrs r7, r7, #8
bcc 2b
ldmia r5!, {r7}
str r7, [r1, #0x10]
subs r0, #1
bne 2b
// card_romWaitBusy
poll_write_done:
3:
ldrb r7, [r2, #0xF]
lsrs r7, r7, #8
bcs 3b
// card_romSetCmd(0xE400000000000000ull);
movs r7, #0xE4
str r7, [r2, #0x10] // E4 00 00 00
movs r7, #0
str r7, [r2, #0x14] // 00 00 00 00
// card_romStartXfer
str r3, [r2, #0xC] // REG_MCCNT1 = MCCNT1_ENABLE | settings;
4:
ldrb r7, [r2, #0xE]
lsrs r7, r7, #8
bcc 4b
ldr r7, [r1, #0x10]
cmp r7, #0
beq poll_write_done
adds r4, #1
subs r6, #1
bne 1b
pop {r4-r7,pc} // popping pc is safe for armv4t when not switching mode
.balign 4
write_cmd_rev:
.word 0x9B0DE1F6
write_cmd_settings:
.word 0xE1486000
reg_base:
.word 0x04000198
write_poll_settings:
.word 0xA7446000
.pool
.end