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,64 @@
#pragma once
#include "common.h"
#include "../acekard-common/IoRPGLoaderPlatform.h"
#include "r4idsnReadSdAsm.h"
#include "r4idsnSdReadSectorAsm.h"
#include "r4idsnWriteSdAsm.h"
/// @brief Implementation of LoaderPlatform for the r4idsn.com flashcard.
class R4iDSNLoaderPlatform : public IoRPGLoaderPlatform
{
private:
enum
{
IORPG_CMD_SDIO_BYTE = 0xAB
};
public:
R4iDSNLoaderPlatform() : IoRPGLoaderPlatform(IORPG_CMD_SDIO_BYTE) { }
const SdReadPatchCode* CreateSdReadPatchCode(
PatchCodeCollection& patchCodeCollection, PatchHeap& patchHeap) const override
{
return patchCodeCollection.GetOrAddSharedPatchCode([&]
{
auto* waitForStatePatchCode = patchCodeCollection.GetOrAddSharedPatchCode([&]
{
return new ioRPGSDWaitForStatePatchCode(patchHeap);
});
return new R4iDSNReadSdPatchCode(patchHeap,
patchCodeCollection.GetOrAddSharedPatchCode([&]
{
return new ioRPGSendSDIOCommandPatchCode(patchHeap);
}),
patchCodeCollection.GetOrAddSharedPatchCode([&]
{
return new R4iDSNSDReadSectorPatchCode(patchHeap, waitForStatePatchCode);
}),
waitForStatePatchCode);
});
}
const SdWritePatchCode* CreateSdWritePatchCode(
PatchCodeCollection& patchCodeCollection, PatchHeap& patchHeap) const override
{
return patchCodeCollection.GetOrAddSharedPatchCode([&]
{
return new R4iDSNWriteSdPatchCode(patchHeap,
patchCodeCollection.GetOrAddSharedPatchCode([&]
{
return new ioRPGSendSDIOCommandPatchCode(patchHeap);
}),
patchCodeCollection.GetOrAddSharedPatchCode([&]
{
return new ioRPGSDWaitForStatePatchCode(patchHeap);
}));
});
}
void PatchSdscShift(void) const override
{
r4idsn_readSd_sdsc_shift = THUMB_MOVS_REG(THUMB_R4, THUMB_R0);
r4idsn_writeSd_sdsc_shift = THUMB_MOVS_REG(THUMB_R7, THUMB_R0);
}
};

View File

@@ -0,0 +1,36 @@
#pragma once
#include "sections.h"
#include "thumbInstructions.h"
#include "r4idsnSdReadSectorAsm.h"
#include "../SdReadPatchCode.h"
#include "../acekard-common/iorpgSendSdioCommandAsm.h"
#include "../acekard-common/iorpgSdWaitForStateAsm.h"
DEFINE_SECTION_SYMBOLS(r4idsn_readsd);
extern "C" void r4idsn_readSd(u32 srcSector, void* dst, u32 sectorCount);
extern u32 r4idsn_readSd_sendSdioCommand_address;
extern u32 r4idsn_readSd_sdReadSector_address;
extern u32 r4idsn_readSd_sdWaitForState_address;
extern u16 r4idsn_readSd_sdsc_shift;
class R4iDSNReadSdPatchCode : public SdReadPatchCode
{
public:
explicit R4iDSNReadSdPatchCode(PatchHeap& patchHeap,
const ioRPGSendSDIOCommandPatchCode* iorpgSendSdioCommandPatchCode,
const R4iDSNSDReadSectorPatchCode* r4idsnSdReadSectorPatchCode,
const ioRPGSDWaitForStatePatchCode* iorpgSdWaitForStatePatchCode)
: SdReadPatchCode(SECTION_START(r4idsn_readsd), SECTION_SIZE(r4idsn_readsd), patchHeap)
{
r4idsn_readSd_sendSdioCommand_address = (u32)iorpgSendSdioCommandPatchCode->GetSendSdioCommandFunction();
r4idsn_readSd_sdReadSector_address = (u32)r4idsnSdReadSectorPatchCode->GetSDReadSectorFunction();
r4idsn_readSd_sdWaitForState_address = (u32)iorpgSdWaitForStatePatchCode->GetSDWaitForStateFunction();
}
const SdReadFunc GetSdReadFunction() const override
{
return (const SdReadFunc)GetAddressAtTarget((void*)r4idsn_readSd);
}
};

View File

@@ -0,0 +1,69 @@
.cpu arm7tdmi
.syntax unified
.section "r4idsn_readsd", "ax"
.thumb
// r0 = src sector
// r1 = dst
// r2 = sector count
.global r4idsn_readSd
.type r4idsn_readSd, %function
r4idsn_readSd:
push {r4,lr}
ldr r4, =0x040001A0
movs r3, #0x80
strb r3, [r4,#1]
.global r4idsn_readSd_sdsc_shift
r4idsn_readSd_sdsc_shift:
lsls r4, r0, #9
push {r0-r1}
ldr r0, =0x120004AB
movs r1, r4
ldr r3, r4idsn_readSd_sendSdioCommand_address
bl blx_r3
// Wait for SD state
movs r0, #4
movs r1, #7
ldr r3, r4idsn_readSd_sdWaitForState_address
bl blx_r3
pop {r0-r1}
// Read sectors. Parameters identical to readSd
ldr r3, r4idsn_readSd_sdReadSector_address
bl blx_r3
// Send CMD12 == STOP_TRANSMISSION
push {r0-r1}
ldr r0, =0x0C0001AB
movs r1, #0
ldr r3, r4idsn_readSd_sendSdioCommand_address
bl blx_r3
pop {r0-r1,r4,pc}
blx_r3:
bx r3
.balign 4
.global r4idsn_readSd_sendSdioCommand_address
r4idsn_readSd_sendSdioCommand_address:
.word 0
.global r4idsn_readSd_sdReadSector_address
r4idsn_readSd_sdReadSector_address:
.word 0
.global r4idsn_readSd_sdWaitForState_address
r4idsn_readSd_sdWaitForState_address:
.word 0
.pool
.end

View File

@@ -0,0 +1,26 @@
#pragma once
#include "sections.h"
#include "thumbInstructions.h"
#include "../acekard-common/iorpgSdWaitForStateAsm.h"
DEFINE_SECTION_SYMBOLS(r4idsn_sdreadsector);
extern "C" void r4idsn_sdReadSector(u32 srcSector, void* dst, u32 sectorCount);
extern u32 r4idsn_sdReadSector_sdWaitForState_address;
class R4iDSNSDReadSectorPatchCode : public PatchCode
{
public:
explicit R4iDSNSDReadSectorPatchCode(PatchHeap& patchHeap,
const ioRPGSDWaitForStatePatchCode* iorpgSdWaitForStatePatchCode)
: PatchCode(SECTION_START(r4idsn_sdreadsector), SECTION_SIZE(r4idsn_sdreadsector), patchHeap)
{
r4idsn_sdReadSector_sdWaitForState_address = (u32)iorpgSdWaitForStatePatchCode->GetSDWaitForStateFunction();
}
const void* GetSDReadSectorFunction() const
{
return GetAddressAtTarget((void*)r4idsn_sdReadSector);
}
};

View File

@@ -0,0 +1,67 @@
.cpu arm7tdmi
.syntax unified
.section "r4idsn_sdreadsector", "ax"
.thumb
// r0 = src sector
// r1 = dst
// r2 = sector count
.global r4idsn_sdReadSector
.type r4idsn_sdReadSector, %function
r4idsn_sdReadSector:
push {r4-r5,lr}
ldr r4, =0x040001A0
ldr r5, =0x04100010
sector_loop:
// NOW we can start reading things
movs r3, #0xB7
str r3, [r4,#0x8]
// The full CMD is B7 00 00 00 00 13 00 00
// If we use 0x1300 and str, then it goes into the expected place
movs r3, #0x13
lsls r3, r3, #8
str r3, [r4,#0xC]
ldr r3, =0xA1406004
str r3, [r4,#4]
r4idsn_sdReadSector_read_loop:
ldrb r3, [r4,#6]
lsrs r3, r3, #8 // check if data is ready
bcc r4idsn_sdReadSector_read_loop_check_transfer_end // if not skip reading
ldr r3, [r5]
stmia r1!, {r3}
r4idsn_sdReadSector_read_loop_check_transfer_end:
ldrb r3, [r4,#7]
lsrs r3, r3, #8 // check if transfer is done
bcs r4idsn_sdReadSector_read_loop
// Wait for SD state
push {r0-r1}
movs r0, #4
movs r1, #7
ldr r3, r4idsn_sdReadSector_sdWaitForState_address
bl blx_r3
pop {r0-r1}
subs r2, #1
bne sector_loop
pop {r4-r5,pc}
blx_r3:
bx r3
.balign 4
.global r4idsn_sdReadSector_sdWaitForState_address
r4idsn_sdReadSector_sdWaitForState_address:
.word 0
.pool
.end

View File

@@ -0,0 +1,32 @@
#pragma once
#include "sections.h"
#include "thumbInstructions.h"
#include "../SdWritePatchCode.h"
#include "../acekard-common/iorpgSendSdioCommandAsm.h"
#include "../acekard-common/iorpgSdWaitForStateAsm.h"
DEFINE_SECTION_SYMBOLS(r4idsn_writesd);
extern "C" void r4idsn_writeSd(u32 srcSector, void* dst, u32 sectorCount);
extern u32 r4idsn_writeSd_sendSdioCommand_address;
extern u32 r4idsn_writeSd_sdWaitForState_address;
extern u16 r4idsn_writeSd_sdsc_shift;
class R4iDSNWriteSdPatchCode : public SdWritePatchCode
{
public:
explicit R4iDSNWriteSdPatchCode(PatchHeap& patchHeap,
const ioRPGSendSDIOCommandPatchCode* iorpgSendSdioCommandPatchCode,
const ioRPGSDWaitForStatePatchCode* iorpgSdWaitForStatePatchCode)
: SdWritePatchCode(SECTION_START(r4idsn_writesd), SECTION_SIZE(r4idsn_writesd), patchHeap)
{
r4idsn_writeSd_sendSdioCommand_address = (u32)iorpgSendSdioCommandPatchCode->GetSendSdioCommandFunction();
r4idsn_writeSd_sdWaitForState_address = (u32)iorpgSdWaitForStatePatchCode->GetSDWaitForStateFunction();
}
const SdWriteFunc GetSdWriteFunction() const override
{
return (const SdWriteFunc)GetAddressAtTarget((void*)r4idsn_writeSd);
}
};

View File

@@ -0,0 +1,81 @@
.cpu arm7tdmi
.syntax unified
.section "r4idsn_writesd", "ax"
.thumb
// r0 = dst sector
// r1 = src
// r2 = sector count
.global r4idsn_writeSd
.type r4idsn_writeSd, %function
r4idsn_writeSd:
push {r4-r7,lr}
ldr r4, =0x040001A0
movs r3, #0x80
strb r3, [r4,#1]
sector_loop:
.global r4idsn_writeSd_sdsc_shift
r4idsn_writeSd_sdsc_shift:
lsls r7, r0, #9
push {r0-r1}
// SDIO cmd
ldr r0, =0x180005AB
// param
movs r1, r7
ldr r6, r4idsn_writeSd_sendSdioCommand_address
bl blx_r6
pop {r0-r1}
// NOW we can start writing things
movs r7, #1
lsls r7, r7, #9
r4idsn_writeSd_block_write_loop:
// start copy to MCCMD1
ldmia r1!, {r5, r6}
str r5, [r4, #0x8]
str r6, [r4, #0xc]
ldr r3, =0xA0406000
str r3, [r4,#4]
r4idsn_writeSd_block_write_wait_busy:
ldr r3, [r4,#4]
cmp r3, #0
blt r4idsn_writeSd_block_write_wait_busy
subs r7, r7, #8
bne r4idsn_writeSd_block_write_loop
push {r0-r1}
// Wait for SD state
movs r0, #4
movs r1, #0
ldr r6, r4idsn_writeSd_sdWaitForState_address
bl blx_r6
pop {r0-r1}
adds r0, #1
subs r2, #1
bne sector_loop
pop {r4-r7,pc}
blx_r6:
bx r6
.balign 4
.global r4idsn_writeSd_sendSdioCommand_address
r4idsn_writeSd_sendSdioCommand_address:
.word 0
.global r4idsn_writeSd_sdWaitForState_address
r4idsn_writeSd_sdWaitForState_address:
.word 0
.pool
.end