Add support for Slot 2 flashcarts using Compact Flash (#84)

- Supercard CF (SUPERCARDCF)
- GBA Media Player CF (MPCF)
- M3 Adapter CF (M3CF)
- Max Media Dock CF (MMCF)
This commit is contained in:
Edoardo Lolletti
2026-01-10 23:00:39 +01:00
committed by GitHub
parent eac8f7e734
commit 6a97b677a7
22 changed files with 945 additions and 3 deletions

View File

@@ -0,0 +1,86 @@
#pragma once
#include "common.h"
#include "sections.h"
#include "patches/PatchCode.h"
#include "thumbInstructions.h"
#include "../IReadSectorsPatchCode.h"
#include "../IWriteSectorsPatchCode.h"
#include "CompactFlashRegisters.h"
#include "ICompactFlashLockUnlockPatchCode.h"
DEFINE_SECTION_SYMBOLS(cf_perform_transfer);
DEFINE_SECTION_SYMBOLS(cf_read_write_functions);
extern "C" bool cf_performTransferSectors(u32 numSectors, u32 sector, u8 command, void* srcAddr, void* dstAddr);
extern "C" bool cf_readSectors(u32 sector, void* buffer, u32 numSectors);
extern "C" bool cf_writeSectors(u32 sector, void* buffer, u32 numSectors);
extern vu16* cf_performTransferSectors_reg_sector_count;
extern u32 cf_performTransferSectors_waitCardAvailableForCommands;
extern u32 cf_performTransferSectors_waitNextBlockReady;
extern vu16* cf_performTransfer_reg_data;
extern u32 cf_performTransfer_performTransferSectors;
extern u32 cf_performTransfer_lockUnlockCard;
extern u16 cf_performTransfer_unlock_label[2];
extern u16 cf_performTransfer_lock_label[2];
class CompactFlashTransferSectorPatchCode : public PatchCode
{
public:
CompactFlashTransferSectorPatchCode(PatchHeap& patchHeap,
const cf_registers_t& registers,
const CompactFlashStatusFunctionsPatchCode* compactFlashStatusFunctionsPatchCode)
: PatchCode(SECTION_START(cf_perform_transfer), SECTION_SIZE(cf_perform_transfer), patchHeap)
{
cf_performTransferSectors_reg_sector_count = registers.sectorCount;
cf_performTransferSectors_waitCardAvailableForCommands = (u32)compactFlashStatusFunctionsPatchCode->GetWaitCardAvailableForCommandsFunction();
cf_performTransferSectors_waitNextBlockReady = (u32)compactFlashStatusFunctionsPatchCode->GetWaitNextBlockReadyFunction();
}
const void* GetPerformTransferSectorsFunction() const
{
return GetAddressAtTarget((void*)cf_performTransferSectors);
}
};
class CompactFlashReadWriteSectorPatchCode : public PatchCode, public IReadSectorsPatchCode, public IWriteSectorsPatchCode
{
public:
CompactFlashReadWriteSectorPatchCode(PatchHeap& patchHeap,
const cf_registers_t& registers,
const CompactFlashTransferSectorPatchCode* compactFlashTransferSectorPatchCode,
const ICompactFlashLockUnlockPatchCode* lockUnlockCard)
: PatchCode(SECTION_START(cf_read_write_functions), SECTION_SIZE(cf_read_write_functions), patchHeap)
{
cf_performTransfer_reg_data = registers.data;
cf_performTransfer_performTransferSectors = (u32)compactFlashTransferSectorPatchCode->GetPerformTransferSectorsFunction();
if (lockUnlockCard)
{
cf_performTransfer_lockUnlockCard = (u32)lockUnlockCard->GetLockUnlockFunction();
}
else
{
// what is getting replaced is a `bl`, taking 4 bytes
const u16 noLockingOpcode = THUMB_MOV_HIREG(THUMB_HI_R8, THUMB_HI_R8);
cf_performTransfer_unlock_label[0] = noLockingOpcode;
cf_performTransfer_unlock_label[1] = noLockingOpcode;
cf_performTransfer_lock_label[0] = noLockingOpcode;
cf_performTransfer_lock_label[1] = noLockingOpcode;
}
}
const ReadSectorsFunc GetReadSectorsFunction() const override
{
return (const ReadSectorsFunc)GetAddressAtTarget((void*)cf_readSectors);
}
const WriteSectorsFunc GetWriteSectorFunction() const override
{
return (const WriteSectorsFunc)GetAddressAtTarget((void*)cf_writeSectors);
}
};