Files
pico-loader/arm7/source/fat/dldi.cpp
2025-11-23 17:14:17 +01:00

98 lines
2.8 KiB
C++

#include "common.h"
#include <string.h>
#include "ipc.h"
#include "ipcCommands.h"
#include "loader/DldiDriver.h"
static u8 sDldiBuffer[16 * 1024] alignas(32);
static DldiDriver sDldiDriver = DldiDriver((dldi_header_t*)sDldiBuffer);
[[gnu::target("thumb")]]
static bool readSectorsWithPatchCode(u32 sector, u32 count, void* buffer)
{
typedef void (*patch_code_read_sd_sectors_t)(u32 srcSector, void* dst, u32 sectorCount);
(*(patch_code_read_sd_sectors_t*)0x037F8000)(sector, buffer, count);
return true;
}
[[gnu::target("thumb")]]
static bool writeSectorsWithPatchCode(u32 sector, u32 count, const void* buffer)
{
typedef void (*patch_code_write_sd_sectors_t)(u32 dstSector, const void* src, u32 sectorCount);
(*(patch_code_write_sd_sectors_t*)0x037F8004)(sector, buffer, count);
return true;
}
bool dldi_init()
{
auto driver = (const dldi_header_t*)gLoaderHeader.dldiDriver;
if (!driver || driver->dldiMagic != DLDI_MAGIC || driver->driverMagic == DLDI_DRIVER_MAGIC_NONE)
{
LOG_DEBUG("No dldi driver found\n");
// Need to initialize before getting the patch code
sendToArm9(IPC_COMMAND_ARM9_INITIALIZE_SD_CARD);
if (!receiveFromArm9())
{
LOG_ERROR("Sd card initialization failed\n");
return false;
}
// Try to get the patch code
sendToArm9(IPC_COMMAND_ARM9_GET_SD_FUNCTIONS);
if (!receiveFromArm9())
{
LOG_ERROR("Getting patch code failed\n");
return false;
}
LOG_DEBUG("Using patch code sd read/write\n");
((dldi_header_t*)sDldiBuffer)->readSectorsFuncAddress = (u32)readSectorsWithPatchCode;
((dldi_header_t*)sDldiBuffer)->writeSectorsFuncAddress = (u32)writeSectorsWithPatchCode;
}
else
{
u32 driverSize = 1 << driver->driverSize;
if (driverSize > sizeof(sDldiBuffer))
{
LOG_ERROR("Not enough space for dldi driver of size %d\n", driverSize);
return false;
}
memcpy(sDldiBuffer, driver, driverSize);
sDldiDriver.Relocate();
sDldiDriver.PrepareForUse();
if (!sDldiDriver.Startup())
{
LOG_ERROR("DLDI startup failed\n");
return false;
}
sendToArm9(IPC_COMMAND_ARM9_INITIALIZE_SD_CARD);
if (!receiveFromArm9())
{
LOG_ERROR("Sd card initialization failed\n");
return false;
}
}
return true;
}
extern "C" bool dldi_readSectors(void* buffer, u32 sector, u32 count)
{
return sDldiDriver.ReadSectors(sector, count, buffer);
}
extern "C" bool dldi_writeSectors(const void* buffer, u32 sector, u32 count)
{
return sDldiDriver.WriteSectors(sector, count, buffer);
}
bool dldi_patchTo(dldi_header_t* stub)
{
return sDldiDriver.PatchTo(stub);
}