#include "common.h" #include #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); }