/* # _____ ____ ___ # | \/ ____| |___| # | | | \ | | #----------------------------------------------------------------------- # Copyright 2022, tyra - https://github.com/h4570/tyra # Licensed under Apache License 2.0 # Wellington Carvalho */ #include "irx/irx_loader.hpp" #include "debug/debug.hpp" #include #include #include #include #include #include #include #include "file/file_utils.hpp" // external IRX modules #define EXTERN_IRX(_irx) \ extern u8 _irx[]; \ extern int size_##_irx EXTERN_IRX(sio2man_irx); EXTERN_IRX(padman_irx); EXTERN_IRX(audsrv_irx); EXTERN_IRX(libsd_irx); EXTERN_IRX(fileXio_irx); EXTERN_IRX(iomanX_irx); EXTERN_IRX(bdm_irx); EXTERN_IRX(bdmfs_fatfs_irx); EXTERN_IRX(usbd_irx); EXTERN_IRX(usbmass_bd_irx); namespace Tyra { bool IrxLoader::isLoaded = false; IrxLoader::IrxLoader() { SifInitRpc(0); while (!SifIopReset("", 0)) { }; while (!SifIopSync()) { }; SifInitRpc(0); this->applyRpcPatches(); } IrxLoader::~IrxLoader() {} void IrxLoader::loadAll(const bool& withUsb, const bool& isLoggingToFile) { if (isLoaded) { TYRA_LOG("IRX modules already loaded!"); return; } loadIO(!isLoggingToFile); loadSio2man(!isLoggingToFile); loadPadman(!isLoggingToFile); loadLibsd(!isLoggingToFile); if (withUsb) { loadUsbModules(!isLoggingToFile); } loadAudsrv(true); isLoaded = true; } /** * @brief Apply the SBV LMB patch to allow modules to be loaded from a buffer in * EE RAM. * */ int IrxLoader::applyRpcPatches() { int ret; ret = sbv_patch_enable_lmb(); TYRA_ASSERT(ret >= 0, "Failed to load Applying SBV Patches sbv_patch_enable_lmb"); ret = sbv_patch_disable_prefix_check(); TYRA_ASSERT( ret >= 0, "Failed to load Applying SBV Patches sbv_patch_disable_prefix_check"); ret = sbv_patch_fileio(); TYRA_ASSERT(ret >= 0, "Failed to load Applying SBV Patches sbv_patch_fileio"); return ret; } void IrxLoader::loadLibsd(const bool& verbose) { if (verbose) TYRA_LOG("IRX: Loading libsd..."); int ret; SifExecModuleBuffer(&libsd_irx, size_libsd_irx, 0, nullptr, &ret); TYRA_ASSERT(ret >= 0, "Failed to load module: libsd_irx"); if (verbose) TYRA_LOG("IRX: Libsd loaded!"); } void IrxLoader::loadIO(const bool& verbose) { int ret; if (verbose) TYRA_LOG("IRX: Loading iomanX..."); SifExecModuleBuffer(&iomanX_irx, size_iomanX_irx, 0, nullptr, &ret); TYRA_ASSERT(ret >= 0, "Failed to load module: iomanX_irx"); if (verbose) TYRA_LOG("IRX: iomanX loaded!"); if (verbose) TYRA_LOG("IRX: Loading fileXio..."); SifExecModuleBuffer(&fileXio_irx, size_fileXio_irx, 0, nullptr, &ret); TYRA_ASSERT(ret >= 0, "Failed to load module: fileXio_irx"); if (verbose) TYRA_LOG("IRX: fileXio_irx loaded!"); } void IrxLoader::loadUsbModules(const bool& verbose) { if (verbose) TYRA_LOG("IRX: Loading usb modules..."); int ret; SifExecModuleBuffer(&usbd_irx, size_usbd_irx, 0, nullptr, &ret); TYRA_ASSERT(ret >= 0, "Failed to load module: usbd_irx"); SifExecModuleBuffer(&bdm_irx, size_bdm_irx, 0, nullptr, &ret); TYRA_ASSERT(ret >= 0, "Failed to load module: bdm_irx"); SifExecModuleBuffer(&bdmfs_fatfs_irx, size_bdmfs_fatfs_irx, 0, nullptr, &ret); TYRA_ASSERT(ret >= 0, "Failed to load module: bdmfs_fatfs"); SifExecModuleBuffer(&usbmass_bd_irx, size_usbmass_bd_irx, 0, nullptr, &ret); TYRA_ASSERT(ret >= 0, "Failed to load module: usbmass"); waitUntilUsbDeviceIsReady(); if (verbose) TYRA_LOG("IRX: Usb modules loaded!"); } void IrxLoader::loadAudsrv(const bool& verbose) { if (verbose) TYRA_LOG("IRX: Loading audsrv..."); int ret; SifExecModuleBuffer(&audsrv_irx, size_audsrv_irx, 0, nullptr, &ret); TYRA_ASSERT(ret >= 0, "Failed to load module: audsrv_irx"); if (verbose) TYRA_LOG("IRX: Audsrv loaded!"); } void IrxLoader::loadSio2man(const bool& verbose) { if (verbose) TYRA_LOG("IRX: Loading sio2man..."); int ret; SifExecModuleBuffer(&sio2man_irx, size_sio2man_irx, 0, nullptr, &ret); TYRA_ASSERT(ret >= 0, "Failed to load module: sio2man_irx"); if (verbose) TYRA_LOG("IRX: Sio2man loaded!"); } void IrxLoader::loadPadman(const bool& verbose) { if (verbose) TYRA_LOG("IRX: Loading padman..."); int ret; SifExecModuleBuffer(&padman_irx, size_padman_irx, 0, nullptr, &ret); TYRA_ASSERT(ret >= 0, "Failed to load module: padman_irx"); if (verbose) TYRA_LOG("IRX: Padman loaded!"); } void IrxLoader::delay(int count) { int i; int ret; for (i = 0; i < count; i++) { ret = 0x01000000; while (ret--) asm("nop\nnop\nnop\nnop"); } } void IrxLoader::waitUntilUsbDeviceIsReady() { struct stat buffer; int ret = -1; int retries = 50; delay(5); // some delay is required by usb mass storage driver while (ret != 0 && retries > 0) { ret = stat("mass:/", &buffer); /* Wait until the device is ready */ nopdelay(); retries--; } } } // namespace Tyra