Files
tyra-linux/engine/src/irx/irx_loader.cpp
T
2023-11-11 13:34:50 -03:00

206 lines
5.1 KiB
C++

/*
# _____ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2022, tyra - https://github.com/h4570/tyra
# Licensed under Apache License 2.0
# Wellington Carvalho <wellcoj@gmail.com>
*/
#include "irx/irx_loader.hpp"
#include "debug/debug.hpp"
#include <stdio.h>
#include <sys/stat.h>
#include <loadfile.h>
#include <kernel.h>
#include <sifrpc.h>
#include <sbv_patches.h>
#include <iopcontrol.h>
#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