Copyright 2009, Ifcaro
Licenced under Academic Free License version 3.0
Review OpenUsbLd README & LICENSE files for further details.
*/
#ifdef __DECI2_DEBUG
#include <iopcontrol_special.h>
#endif
#include "include/opl.h"
#include "include/gui.h"
#include "include/ethsupport.h"
#include "include/hddsupport.h"
#include "include/util.h"
#include "include/pad.h"
#include "include/system.h"
#include "include/ioman.h"
#include "include/ioprp.h"
#include "include/bdmsupport.h"
#include "include/OSDHistory.h"
#include "include/renderman.h"
#include "include/extern_irx.h"
#include "../ee_core/include/modules.h"
#include "../ee_core/include/coreconfig.h"
#include <osd_config.h>
#include "include/pggsm.h"
#include "include/cheatman.h"
#include "include/xparam.h"
#ifdef PADEMU
#include <libds34bt.h>
#include <libds34usb.h>
#endif
#define NEWLIB_PORT_AWARE
#include <fileXio_rpc.h>
typedef struct
{
char VMC_filename[1024];
int VMC_size_mb;
int VMC_blocksize;
int VMC_thread_priority;
int VMC_card_slot;
} createVMCparam_t;
extern unsigned char eecore_elf[];
extern unsigned int size_eecore_elf;
extern unsigned char IOPRP_img[];
extern unsigned int size_IOPRP_img;
extern unsigned char eesync_irx[];
extern unsigned int size_eesync_irx;
#define MAX_MODULES 64
static void *g_sysLoadedModBuffer[MAX_MODULES];
static s32 sysLoadModuleLock = -1;
#define ELF_MAGIC 0x464c457f
#define ELF_PT_LOAD 1
typedef struct
{
u8 ident[16];
u16 type;
u16 machine;
u32 version;
u32 entry;
u32 phoff;
u32 shoff;
u32 flags;
u16 ehsize;
u16 phentsize;
u16 phnum;
u16 shentsize;
u16 shnum;
u16 shstrndx;
} elf_header_t;
typedef struct
{
u32 type;
u32 offset;
void *vaddr;
u32 paddr;
u32 filesz;
u32 memsz;
u32 flags;
u32 align;
} elf_pheader_t;
void guiWarning(const char *text, int count);
void guiEnd();
void menuEnd();
void lngEnd();
void thmEnd();
void rmEnd();
static void poweroffHandler(void *arg);
int sysLoadModuleBuffer(void *buffer, int size, int argc, char *argv)
{
int i, id, ret, index = 0;
WaitSema(sysLoadModuleLock);
for (i = 0; i < MAX_MODULES; i++) {
if (g_sysLoadedModBuffer[i] == NULL) {
index = i;
break;
}
}
if (i == MAX_MODULES) {
LOG("WARNING: REACHED MODULES LIMIT (%d)\n", MAX_MODULES);
ret = -1;
goto exit;
}
for (i = 0; i < MAX_MODULES; i++) {
if (g_sysLoadedModBuffer[i] == buffer) {
LOG("MODULE ALREADY LOADED (%d)\n", i);
ret = 0;
goto exit;
}
}
id = SifExecModuleBuffer(buffer, size, argc, argv, &ret);
LOG("\t-- ID=%d, ret=%d\n", id, ret);
if ((id < 0) || (ret)) {
ret = -2;
goto exit;
}
g_sysLoadedModBuffer[index] = buffer;
ret = 0;
exit:
SignalSema(sysLoadModuleLock);
return ret;
}
#define OPL_SIF_CMD_BUFF_SIZE 1
static SifCmdHandlerData_t OplSifCmdbuffer[OPL_SIF_CMD_BUFF_SIZE];
static unsigned char dev9Initialized = 0, dev9Loaded = 0, dev9InitCount = 0;
void sysInitDev9(void)
{
int ret;
if (!dev9Initialized) {
LOG("[DEV9]:\n");
ret = sysLoadModuleBuffer(&ps2dev9_irx, size_ps2dev9_irx, 0, NULL);
dev9Loaded = (ret == 0);
dev9Initialized = 1;
}
dev9InitCount++;
}
void sysShutdownDev9(void)
{
if (dev9InitCount > 0) {
--dev9InitCount;
if (dev9InitCount == 0) {
if (dev9Loaded) {
while (fileXioDevctl("dev9x:", DDIOC_OFF, NULL, 0, NULL, 0) < 0) {
};
}
}
}
}
void sysReset(int modload_mask)
{
#ifdef PADEMU
ds34usb_reset();
ds34bt_reset();
#endif
fileXioExit();
SifExitIopHeap();
SifLoadFileExit();
SifExitRpc();
SifInitRpc(0);
#ifdef _DTL_T10000
while (!SifIopReset("rom0:UDNL", 0))
;
#else
#ifdef __DECI2_DEBUG
while (!SifIopRebootBuffer(&deci2_img, size_deci2_img))
;
#else
while (!SifIopReset("", 0))
;
#endif
#endif
dev9Initialized = 0;
while (!SifIopSync())
;
SifInitRpc(0);
SifSetCmdBuffer(OplSifCmdbuffer, OPL_SIF_CMD_BUFF_SIZE);
sceCdInit(SCECdINoD);
SifLoadFileInit();
SifInitIopHeap();
sbv_patch_enable_lmb();
sbv_patch_disable_prefix_check();
if (sysLoadModuleLock < 0) {
sysLoadModuleLock = sbCreateSemaphore();
}
memset((void *)&g_sysLoadedModBuffer[0], 0, MAX_MODULES * 4);
LOG("[IOMANX]:\n");
sysLoadModuleBuffer(&iomanx_irx, size_iomanx_irx, 0, NULL);
LOG("[FILEXIO]:\n");
sysLoadModuleBuffer(&filexio_irx, size_filexio_irx, 0, NULL);
LOG("[SIO2MAN]:\n");
sysLoadModuleBuffer(&sio2man_irx, size_sio2man_irx, 0, NULL);
if (modload_mask & SYS_LOAD_MC_MODULES) {
LOG("[MCMAN]:\n");
sysLoadModuleBuffer(&mcman_irx, size_mcman_irx, 0, NULL);
LOG("[MCSERV]:\n");
sysLoadModuleBuffer(&mcserv_irx, size_mcserv_irx, 0, NULL);
}
LOG("[PADMAN]:\n");
sysLoadModuleBuffer(&padman_irx, size_padman_irx, 0, NULL);
LOG("[POWEROFF]:\n");
sysLoadModuleBuffer(&poweroff_irx, size_poweroff_irx, 0, NULL);
if (modload_mask & SYS_LOAD_USB_MODULES) {
bdmLoadModules();
}
if (modload_mask & SYS_LOAD_ISOFS_MODULE) {
LOG("[ISOFS]:\n");
sysLoadModuleBuffer(&isofs_irx, size_isofs_irx, 0, NULL);
}
LOG("[GENVMC]:\n");
sysLoadModuleBuffer(&genvmc_irx, size_genvmc_irx, 0, NULL);
LOG("[LIBSD]:\n");
sysLoadModuleBuffer(&libsd_irx, size_libsd_irx, 0, NULL);
LOG("[AUDSRV]:\n");
sysLoadModuleBuffer(&audsrv_irx, size_audsrv_irx, 0, NULL);
#ifdef PADEMU
int ds3pads = 1;
ds34usb_deinit();
ds34bt_deinit();
if (modload_mask & SYS_LOAD_USB_MODULES) {
LOG("[DS34_USB]:\n");
sysLoadModuleBuffer(&ds34usb_irx, size_ds34usb_irx, 4, (char *)&ds3pads);
LOG("[DS34_BT]:\n");
sysLoadModuleBuffer(&ds34bt_irx, size_ds34bt_irx, 4, (char *)&ds3pads);
ds34usb_init();
ds34bt_init();
}
#endif
fileXioInit();
poweroffInit();
poweroffSetCallback(&poweroffHandler, NULL);
}
static void poweroffHandler(void *arg)
{
sysPowerOff();
}
void sysPowerOff(void)
{
deinit(NO_EXCEPTION, IO_MODE_SELECTED_NONE);
poweroffShutdown();
}
static unsigned int crctab[0x400];
unsigned int USBA_crc32(const char *string)
{
int crc, table, count, byte;
for (table = 0; table < 256; table++) {
crc = table << 24;
for (count = 8; count > 0; count--) {
if (crc < 0)
crc = crc << 1;
else
crc = (crc << 1) ^ 0x04C11DB7;
}
crctab[255 - table] = crc;
}
do {
byte = string[count++];
crc = crctab[byte ^ ((crc >> 24) & 0xFF)] ^ ((crc << 8) & 0xFFFFFF00);
} while ((string[count - 1] != 0) && (count <= 32));
return crc;
}
int sysGetDiscID(char *hexDiscID)
{
u8 key[16];
if (sceCdStatus() == SCECdErOPENS)
return -1;
while (sceCdGetDiskType() == SCECdDETCT) {
;
}
if (sceCdGetDiskType() == SCECdNODISC)
return -1;
sceCdDiskReady(0);
LOG("SYSTEM Disc drive is ready\n");
int cdmode = sceCdGetDiskType();
if (cdmode == SCECdNODISC)
return -1;
if ((cdmode != SCECdPS2DVD) && (cdmode != SCECdPS2CD) && (cdmode != SCECdPS2CDDA)) {
sceCdStop();
sceCdSync(0);
LOG("SYSTEM Disc stopped, Disc is not ps2 disc!\n");
return -2;
}
LOG("SYSTEM Disc standby\n");
sceCdStandby();
sceCdSync(0);
LOG("SYSTEM Disc read key\n");
if (sceCdReadKey(0, 0, 0x4b, key) == 0) {
LOG("SYSTEM Cannot read CD/DVD key.\n");
sceCdStop();
sceCdSync(0);
LOG("SYSTEM Disc stopped\n");
return -3;
}
sceCdStop();
snprintf(hexDiscID, 15, "%02X %02X %02X %02X %02X", key[10], key[11], key[12], key[13], key[14]);
LOG("SYSTEM PS2 Disc ID = %s\n", hexDiscID);
sceCdSync(0);
LOG("SYSTEM Disc stopped\n");
return 1;
}
void sysExecExit(void)
{
deinit(NO_EXCEPTION, IO_MODE_SELECTED_ALL);
exit(0);
}
#define CORE_IRX_USB 0x01
#define CORE_IRX_ETH 0x02
#define CORE_IRX_SMB 0x04
#define CORE_IRX_HDD 0x08
#define CORE_IRX_VMC 0x10
#define CORE_IRX_DEBUG 0x20
#define CORE_IRX_DECI2 0x40
#define CORE_IRX_ILINK 0x80
#define CORE_IRX_MX4SIO 0x100
typedef struct
{
char *game;
char *mode;
void *module;
int *module_size;
} patchlist_t;
static const patchlist_t iop_patch_list[] = {
{"SLUS_205.61", "", &iremsndpatch_irx, &size_iremsndpatch_irx},
{"SLES_513.01", "", &iremsndpatch_irx, &size_iremsndpatch_irx},
{"SLPS_251.13", "", &iremsndpatch_irx, &size_iremsndpatch_irx},
{"SLES_535.08", "", &apemodpatch_irx, &size_apemodpatch_irx},
{"SLUS_204.13", "", &f2techioppatch_irx, &size_f2techioppatch_irx},
{"SLES_504.46", "", &f2techioppatch_irx, &size_f2techioppatch_irx},
{"SLES_506.08", "", &f2techioppatch_irx, &size_f2techioppatch_irx},
{NULL, NULL, NULL, NULL},
};
static unsigned int addIopPatch(const char *mode_str, const char *startup, irxptr_t *tab)
{
const patchlist_t *p;
int i;
for (i = 0; iop_patch_list[i].game != NULL; i++) {
p = &iop_patch_list[i];
if (!strcmp(p->game, startup) && (p->mode[0] == '\0' || !strcmp(p->mode, startup))) {
tab->info = (*(p->module_size)) | SET_OPL_MOD_ID(OPL_MODULE_ID_IOP_PATCH);
tab->ptr = (void *)p->module;
return 1;
}
}
return 0;
}
typedef struct
{
char *game;
void *addr;
} modStorageSetting_t;
static const modStorageSetting_t mod_storage_location_list[] = {
{"SLUS_209.77", (void *)0x01fc7000},
{"SLPM_656.32", (void *)0x01fc7000},
{NULL, NULL},
};
static void *GetModStorageLocation(const char *startup, unsigned compatFlags)
{
const modStorageSetting_t *p;
int i;
for (i = 0; mod_storage_location_list[i].game != NULL; i++) {
p = &mod_storage_location_list[i];
if (!strcmp(p->game, startup)) {
return p->addr;
}
}
return ((void *)OPL_MOD_STORAGE);
}
static unsigned int sendIrxKernelRAM(const char *startup, const char *mode_str, unsigned int modules, void *ModuleStorage, int size_cdvdman_irx, void **cdvdman_irx, int size_mcemu_irx, void **mcemu_irx)
{
irxtab_t *irxtable;
irxptr_t *irxptr_tab;
void *irxptr, *ioprp_image;
int i, modcount;
unsigned int curIrxSize, size_ioprp_image, total_size;
if (!strcmp(mode_str, "BDM_USB_MODE"))
modules |= CORE_IRX_USB;
else if (!strcmp(mode_str, "BDM_ILK_MODE"))
modules |= CORE_IRX_ILINK;
else if (!strcmp(mode_str, "BDM_M4S_MODE"))
modules |= CORE_IRX_MX4SIO;
else if (!strcmp(mode_str, "BDM_ATA_MODE"))
modules |= CORE_IRX_HDD;
else if (!strcmp(mode_str, "ETH_MODE"))
modules |= CORE_IRX_ETH | CORE_IRX_SMB;
else
modules |= CORE_IRX_HDD;
irxtable = (irxtab_t *)ModuleStorage;
irxptr_tab = (irxptr_t *)((unsigned char *)irxtable + sizeof(irxtab_t));
size_ioprp_image = size_IOPRP_img + size_cdvdman_irx + size_cdvdfsv_irx + size_eesync_irx + 256;
LOG("IOPRP image size calculated: %d\n", size_ioprp_image);
ioprp_image = malloc(size_ioprp_image);
size_ioprp_image = patch_IOPRP_image(ioprp_image, cdvdman_irx, size_cdvdman_irx);
LOG("IOPRP image size actual: %d\n", size_ioprp_image);
modcount = 0;
irxptr_tab[modcount].info = size_udnl_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_UDNL);
irxptr_tab[modcount++].ptr = (void *)&udnl_irx;
irxptr_tab[modcount].info = size_ioprp_image | SET_OPL_MOD_ID(OPL_MODULE_ID_IOPRP);
irxptr_tab[modcount++].ptr = ioprp_image;
irxptr_tab[modcount].info = size_imgdrv_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_IMGDRV);
irxptr_tab[modcount++].ptr = (void *)&imgdrv_irx;
irxptr_tab[modcount].info = size_resetspu_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_RESETSPU);
irxptr_tab[modcount++].ptr = (void *)&resetspu_irx;
#ifdef PADEMU
#define PADEMU_ARG || gEnablePadEmu
#else
#define PADEMU_ARG
#endif
if (modules & (CORE_IRX_MX4SIO | CORE_IRX_VMC) PADEMU_ARG) {
irxptr_tab[modcount].info = size_sio2man_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_SIO2MAN);
irxptr_tab[modcount++].ptr = (void *)&sio2man_irx;
}
if ((modules & CORE_IRX_USB) PADEMU_ARG) {
irxptr_tab[modcount].info = size_usbd_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_USBD);
irxptr_tab[modcount++].ptr = (void *)&usbd_irx;
}
if (modules & CORE_IRX_USB) {
irxptr_tab[modcount].info = size_usbmass_bd_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_USBMASSBD);
irxptr_tab[modcount++].ptr = (void *)&usbmass_bd_irx;
}
if (modules & CORE_IRX_ILINK) {
irxptr_tab[modcount].info = size_iLinkman_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_ILINK);
irxptr_tab[modcount++].ptr = (void *)&iLinkman_irx;
irxptr_tab[modcount].info = size_IEEE1394_bd_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_ILINKBD);
irxptr_tab[modcount++].ptr = (void *)&IEEE1394_bd_irx;
}
if (modules & CORE_IRX_MX4SIO) {
irxptr_tab[modcount].info = size_mx4sio_bd_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_MX4SIOBD);
irxptr_tab[modcount++].ptr = (void *)&mx4sio_bd_irx;
}
if (modules & CORE_IRX_ETH) {
irxptr_tab[modcount].info = size_smap_ingame_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_SMAP);
irxptr_tab[modcount++].ptr = (void *)&smap_ingame_irx;
irxptr_tab[modcount].info = size_ingame_smstcpip_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_SMSTCPIP);
irxptr_tab[modcount++].ptr = (void *)&ingame_smstcpip_irx;
}
if (modules & CORE_IRX_SMB) {
irxptr_tab[modcount].info = size_smbinit_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_SMBINIT);
irxptr_tab[modcount++].ptr = (void *)&smbinit_irx;
}
if (modules & CORE_IRX_VMC) {
irxptr_tab[modcount].info = size_mcemu_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_MCEMU);
irxptr_tab[modcount++].ptr = (void *)mcemu_irx;
}
#ifdef PADEMU
if (gEnablePadEmu) {
if (gPadEmuSettings & 0xFF) {
irxptr_tab[modcount].info = size_bt_pademu_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_PADEMU);
irxptr_tab[modcount++].ptr = (void *)&bt_pademu_irx;
} else {
irxptr_tab[modcount].info = size_usb_pademu_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_PADEMU);
irxptr_tab[modcount++].ptr = (void *)&usb_pademu_irx;
}
}
#endif
#ifdef __INGAME_DEBUG
#ifdef __DECI2_DEBUG
if (modules & CORE_IRX_DECI2) {
irxptr_tab[modcount].info = size_drvtif_ingame_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_DRVTIF);
irxptr_tab[modcount++].ptr = (void *)&drvtif_ingame_irx;
irxptr_tab[modcount].info = size_tifinet_ingame_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_TIFINET);
irxptr_tab[modcount++].ptr = (void *)&tifinet_ingame_irx;
}
#elif defined(TTY_UDP)
if (modules & CORE_IRX_DEBUG) {
irxptr_tab[modcount].info = size_udptty_ingame_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_UDPTTY);
irxptr_tab[modcount++].ptr = (void *)&udptty_ingame_irx;
irxptr_tab[modcount].info = size_ioptrap_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_IOPTRAP);
irxptr_tab[modcount++].ptr = (void *)&ioptrap_irx;
}
#elif defined(TTY_PPC_UART)
if (modules & CORE_IRX_DEBUG) {
irxptr_tab[modcount].info = size_ppctty_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_PPCTTY);
irxptr_tab[modcount++].ptr = (void *)&ppctty_irx;
irxptr_tab[modcount].info = size_ioptrap_irx | SET_OPL_MOD_ID(OPL_MODULE_ID_IOPTRAP);
irxptr_tab[modcount++].ptr = (void *)&ioptrap_irx;
}
#endif
#endif
modcount += addIopPatch(mode_str, startup, &irxptr_tab[modcount]);
irxtable->modules = irxptr_tab;
irxtable->count = modcount;
#ifdef __DECI2_DEBUG
irxptr = (void *)0x00033000;
LOG("SYSTEM DECI2 UDNL address start: %p end: %p\n", irxptr, (void *)((u8 *)irxptr + GET_OPL_MOD_SIZE(irxptr_tab[0].info)));
DI();
ee_kmode_enter();
memcpy((void *)(0x80000000 | (unsigned int)irxptr), irxptr_tab[0].ptr, GET_OPL_MOD_SIZE(irxptr_tab[0].info));
ee_kmode_exit();
EI();
irxptr_tab[0].ptr = irxptr;
#endif
total_size = (sizeof(irxtab_t) + sizeof(irxptr_t) * modcount + 0xF) & ~0xF;
irxptr = (void *)((((unsigned int)irxptr_tab + sizeof(irxptr_t) * modcount) + 0xF) & ~0xF);
#ifdef __DECI2_DEBUG
for (i = 1; i < modcount; i++) {
#else
for (i = 0; i < modcount; i++) {
#endif
curIrxSize = GET_OPL_MOD_SIZE(irxptr_tab[i].info);
if (curIrxSize > 0) {
LOG("SYSTEM IRX %u address start: %p end: %p\n", GET_OPL_MOD_ID(irxptr_tab[i].info), irxptr, (void *)((u8 *)irxptr + curIrxSize));
memcpy(irxptr, irxptr_tab[i].ptr, curIrxSize);
irxptr_tab[i].ptr = irxptr;
irxptr = (void *)((u8 *)irxptr + ((curIrxSize + 0xF) & ~0xF));
total_size += ((curIrxSize + 0xF) & ~0xF);
} else {
irxptr_tab[i].ptr = NULL;
}
}
free(ioprp_image);
LOG("SYSTEM IRX STORAGE %p - %p\n", ModuleStorage, (u8 *)ModuleStorage + total_size);
return total_size;
}
#ifdef __DECI2_DEBUG
Look for the start of the EE DECI2 manager initialization function.
The stock EE kernel has no reset function, but the EE kernel is most likely already primed to self-destruct and in need of a good reset.
What happens is that the OSD initializes the EE DECI2 TTY protocol at startup, but the EE DECI2 manager is never aware that the OSDSYS ever loads other programs.
As a result, the EE kernel crashes immediately when the EE TTY gets used (when the IOP side of DECI2 comes up), when it invokes whatever that exists at the OSD's old ETTY handler's location. :(
Must be run in kernel mode.
*/
static int ResetDECI2(void)
{
int result;
unsigned int i, *ptr;
void (*pDeci2ManagerInit)(void);
static const unsigned int Deci2ManagerInitPattern[] = {
0x3c02bf80,
0x3c04bfc0,
0x34423800,
0x34840102
};
result = -1;
ptr = (void *)0x80000000;
for (i = 0; i < 0x20000 / 4; i++) {
if (ptr[i + 0] == Deci2ManagerInitPattern[0] &&
ptr[i + 1] == Deci2ManagerInitPattern[1] &&
ptr[i + 2] == Deci2ManagerInitPattern[2] &&
ptr[i + 3] == Deci2ManagerInitPattern[3]) {
pDeci2ManagerInit = (void *)&ptr[i - 14];
pDeci2ManagerInit();
result = 0;
break;
}
}
return result;
}
int sysInitDECI2(void)
{
int result;
DI();
ee_kmode_enter();
result = ResetDECI2();
ee_kmode_exit();
EI();
return result;
}
#endif
* Patches the kernel to use the EELOAD module at the specified location.
* Must be run in kernel mode.
*/
static void *initLoadExecPS2(void *new_eeload)
{
void *result;
static const unsigned int initEELOADCopyPattern[] = {
0x8FA30010,
0x0240302D,
0x8FA50014,
0x8C67000C,
0x18E00009,
};
u32 *p;
result = NULL;
for (p = (u32 *)0x80001000; p < (u32 *)0x80030000; p++) {
if (memcmp(p, &initEELOADCopyPattern, sizeof(initEELOADCopyPattern)) == 0) {
p[1] = 0x3C120000 | (u16)((u32)new_eeload >> 16);
p[2] = 0x36520000 | (u16)((u32)new_eeload & 0xFFFF);
p[3] = 0x24070000;
result = (void *)p;
break;
}
}
return result;
}
* Pathces the kernel to begin erasure of memory from the specified address.
* Must be run in kernel mode.
*/
static void *initInitializeUserMemory(void *start)
{
u32 *p;
void *result;
result = NULL;
for (p = (unsigned int *)0x80001000; p < (unsigned int *)0x80030000; p++) {
* Search for function call and where $a0 is set.
* lui $a0, 0x0008
* jal InitializeUserMemory
* ori $a0, $a0, 0x2000
*/
if (p[0] == 0x3c040008 && (p[1] & 0xfc000000) == 0x0c000000 && p[2] == 0x34842000) {
p[0] = 0x3c040000 | ((unsigned int)start >> 16);
p[2] = 0x34840000 | ((unsigned int)start & 0xffff);
result = (void *)p;
break;
}
}
return result;
}
static int initKernel(void *eeload, void *modStorageEnd, void **eeloadCopy, void **initUserMemory)
{
DI();
ee_kmode_enter();
#ifdef __DECI2_DEBUG
ResetDECI2();
#endif
*eeloadCopy = initLoadExecPS2(eeload);
*initUserMemory = initInitializeUserMemory(modStorageEnd);
ee_kmode_exit();
EI();
return ((*eeloadCopy != NULL && *initUserMemory != NULL) ? 0 : -1);
}
#ifdef __DEBUG
void sysPrintEECoreConfig(struct EECoreConfig_t *config)
{
LOG("EECoreConfig Values = 0x%08X\n", (u32)config);
LOG("Game Mode Desc = %s\n", config->GameModeDesc);
LOG("EnableDebug = %d\n", config->EnableDebug);
LOG("Exit Path = (%s)\n", config->ExitPath);
LOG("HDD Spindown = %d\n", config->HDDSpindown);
LOG("IP=%s NM=%s GW=%s mode: %d\n", config->g_ps2_ip, config->g_ps2_netmask, config->g_ps2_gateway, config->g_ps2_ETHOpMode);
LOG("PS2RD Cheat Engine = %s\n", config->gCheatList == NULL ? "Disabled" : "Enabled");
LOG("EnforceLanguage = %s\n", config->enforceLanguage == 0 ? "Disabled" : "Enabled");
LOG("GSM = %s\n", config->EnableGSMOp == 0 ? "Disabled" : "Enabled");
LOG("PADEMU = %s\n", config->EnablePadEmuOp == 0 ? "Disabled" : "Enabled");
LOG("enforceLanguage = %s\n", config->enforceLanguage == 0 ? "Disabled" : "Enabled");
LOG("eeloadCopy = 0x%08X\n", config->eeloadCopy);
LOG("initUserMemory = 0x%08X\n", config->initUserMemory);
LOG("ModStorageStart = 0x%08X\n", config->ModStorageStart);
LOG("ModStorageEnd = 0x%08X\n", config->ModStorageEnd);
LOG("GameID = %s\n", config->GameID);
LOG("Compat Mask = 0x%02x\n", config->_CompatMask);
}
#endif
void sysLaunchLoaderElf(const char *filename, const char *mode_str, int size_cdvdman_irx, void **cdvdman_irx, int size_mcemu_irx, void **mcemu_irx, int EnablePS2Logo, unsigned int compatflags)
{
unsigned int modules, ModuleStorageSize;
void *ModuleStorage, *ModuleStorageEnd;
u8 local_ip_address[4], local_netmask[4], local_gateway[4];
u8 *boot_elf = NULL;
elf_header_t *eh;
elf_pheader_t *eph;
void *pdata;
int argc, i;
char ElfPath[32];
char *argv[4];
void *eeloadCopy, *initUserMemory;
struct GsmConfig_t gsm_config;
ethGetNetConfig(local_ip_address, local_netmask, local_gateway);
#if (!defined(__DEBUG) && !defined(_DTL_T10000))
AddHistoryRecordUsingFullPath(filename);
#endif
if (gExitPath[0] == '\0')
strncpy(gExitPath, "Browser", sizeof(gExitPath));
LOG("[CLEAREFFECTS]:\n");
sysLoadModuleBuffer(&cleareffects_irx, size_cleareffects_irx, 0, NULL);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#pragma GCC diagnostic ignored "-Wstringop-overflow"
memset((void *)0x00084000, 0, 0x00100000 - 0x00084000);
#pragma GCC diagnostic pop
modules = 0;
ModuleStorage = GetModStorageLocation(filename, compatflags);
#ifdef __DECI2_DEBUG
modules |= CORE_IRX_DECI2 | CORE_IRX_ETH;
#elif defined(__INGAME_DEBUG)
modules |= CORE_IRX_DEBUG;
#ifdef TTY_UDP
modules |= CORE_IRX_ETH;
#endif
#endif
modules |= CORE_IRX_VMC;
LOG("SYSTEM LaunchLoaderElf loading modules\n");
ModuleStorageSize = (sendIrxKernelRAM(filename, mode_str, modules, ModuleStorage, size_cdvdman_irx, cdvdman_irx, size_mcemu_irx, mcemu_irx) + 0x3F) & ~0x3F;
ModuleStorageEnd = (void *)((u8 *)ModuleStorage + ModuleStorageSize);
boot_elf = (u8 *)&eecore_elf;
eh = (elf_header_t *)boot_elf;
eph = (elf_pheader_t *)(boot_elf + eh->phoff);
ApplyDeckardXParam(filename);
if (initKernel((void *)eh->entry, ModuleStorageEnd, &eeloadCopy, &initUserMemory) != 0) {
LOG("Error - kernel is unsupported.\n");
asm volatile("break\n");
}
ConfigParam PARAM;
GetOsdConfigParam(&PARAM);
if (gOSDLanguageEnable) {
if (gOSDLanguageValue >= LANGUAGE_JAPANESE && gOSDLanguageValue <= LANGUAGE_PORTUGUESE) {
PARAM.language = gOSDLanguageValue;
LOG("System Language enforced to %d\n", gOSDLanguageValue);
}
if (gOSDTVAspectRatio >= TV_SCREEN_43 && gOSDTVAspectRatio <= TV_SCREEN_169) {
PARAM.screenType = gOSDTVAspectRatio;
LOG("System screenType enforced to %d\n", gOSDTVAspectRatio);
}
if (gOSDVideOutput == VIDEO_OUTPUT_RGB || gOSDVideOutput == VIDEO_OUTPUT_COMPONENT) {
PARAM.videoOutput = gOSDVideOutput;
LOG("System video output enforced to %d\n", gOSDVideOutput);
}
}
struct EECoreConfig_t *config = NULL;
u32 *core_ptr = (u32 *)&eecore_elf;
for (i = 0; i < size_eecore_elf / 4; i++) {
if (core_ptr[0] == EE_CORE_MAGIC_0 && core_ptr[1] == EE_CORE_MAGIC_1) {
config = (struct EECoreConfig_t *)core_ptr;
break;
}
core_ptr++;
}
if (config == NULL) {
LOG("Error - EE core config MAGIC not found!\n");
asm volatile("break\n");
}
memset(config, 0, sizeof(struct EECoreConfig_t));
config->magic[0] = EE_CORE_MAGIC_0;
config->magic[1] = EE_CORE_MAGIC_1;
strncpy(config->ExitPath, gExitPath, CORE_EXIT_PATH_MAX_LEN);
strncpy(config->GameModeDesc, mode_str, CORE_GAME_MODE_DESC_MAX_LEN);
config->EnableDebug = gEnableDebug;
config->HDDSpindown = gHDDSpindown;
config->g_ps2_ETHOpMode = gETHOpMode;
if (GetCheatsEnabled()) {
set_cheats_list();
config->gCheatList = GetCheatsList();
} else
config->gCheatList = NULL;
sprintf(config->g_ps2_ip, "%u.%u.%u.%u", local_ip_address[0], local_ip_address[1], local_ip_address[2], local_ip_address[3]);
sprintf(config->g_ps2_netmask, "%u.%u.%u.%u", local_netmask[0], local_netmask[1], local_netmask[2], local_netmask[3]);
sprintf(config->g_ps2_gateway, "%u.%u.%u.%u", local_gateway[0], local_gateway[1], local_gateway[2], local_gateway[3]);
config->EnableGSMOp = GetGSMEnabled();
if (config->EnableGSMOp) {
PrepareGSM(NULL, &gsm_config);
config->GsmConfig.interlace = gsm_config.interlace;
config->GsmConfig.mode = gsm_config.mode;
config->GsmConfig.ffmd = gsm_config.ffmd;
config->GsmConfig.display = gsm_config.display;
config->GsmConfig.syncv = gsm_config.syncv;
config->GsmConfig.smode2 = gsm_config.smode2;
config->GsmConfig.dx_offset = gsm_config.dx_offset;
config->GsmConfig.dy_offset = gsm_config.dy_offset;
config->GsmConfig.k576P_fix = gsm_config.k576P_fix;
config->GsmConfig.kGsDxDyOffsetSupported = gsm_config.kGsDxDyOffsetSupported;
config->GsmConfig.FIELD_fix = gsm_config.FIELD_fix;
}
#ifdef PADEMU
config->EnablePadEmuOp = gEnablePadEmu;
config->PadEmuSettings = (unsigned int)(gPadEmuSettings >> 8);
config->PadMacroSettings = (unsigned int)(gPadMacroSettings);
#endif
config->CustomOSDConfigParam.spdifMode = PARAM.spdifMode;
config->CustomOSDConfigParam.screenType = PARAM.screenType;
config->CustomOSDConfigParam.videoOutput = PARAM.videoOutput;
config->CustomOSDConfigParam.japLanguage = PARAM.japLanguage;
config->CustomOSDConfigParam.ps1drvConfig = PARAM.ps1drvConfig;
config->CustomOSDConfigParam.version = PARAM.version;
config->CustomOSDConfigParam.language = PARAM.language;
config->CustomOSDConfigParam.timezoneOffset = PARAM.timezoneOffset;
config->enforceLanguage = gOSDLanguageEnable;
config->eeloadCopy = eeloadCopy;
config->initUserMemory = initUserMemory;
config->ModStorageStart = ModuleStorage;
config->ModStorageEnd = ModuleStorageEnd;
strncpy(config->GameID, filename, CORE_GAME_ID_MAX_LEN);
config->_CompatMask = compatflags;
#ifdef __DEBUG
sysPrintEECoreConfig(config);
#endif
FlushCache(0);
FlushCache(2);
for (i = 0; i < eh->phnum; i++) {
if (eph[i].type != ELF_PT_LOAD)
continue;
pdata = (void *)((u8 *)boot_elf + eph[i].offset);
memcpy(eph[i].vaddr, pdata, eph[i].filesz);
LOG("EECORE PH COPY: %d 0x%08X 0x%08X 0x%08X\n", i, (u32)eph[i].vaddr, (u32)pdata, eph[i].filesz);
if (eph[i].memsz > eph[i].filesz) {
LOG("EECORE PH CLEAR: %d 0x%08X 0x%08X\n", i, (u32)((u32)eph[i].vaddr + eph[i].filesz), eph[i].memsz - eph[i].filesz);
memset(eph[i].vaddr + eph[i].filesz, 0, eph[i].memsz - eph[i].filesz);
}
}
argc = 0;
if (EnablePS2Logo) {
int fd = 0;
if ((fd = open("rom0:PS2LOGO", O_RDONLY)) >= 0) {
close(fd);
argv[argc] = "rom0:PS2LOGO";
argc++;
}
}
snprintf(ElfPath, sizeof(ElfPath), "cdrom0:\\%s;1", filename);
argv[argc] = ElfPath;
argc++;
#ifdef __DEBUG
LOG("Starting ee_core with following argv arguments:\n");
for (i = 0; i < argc; i++) {
LOG("[%d] %s\n", i, argv[i]);
}
#endif
LOG("Leaving OPL GUI, starting eecore = 0x%08X \n", (u32)eh->entry);
fileXioExit();
SifExitRpc();
FlushCache(0);
FlushCache(2);
ExecPS2((void *)eh->entry, NULL, argc, argv);
}
int sysCheckMC(void)
{
DIR *mc0_root_dir = opendir("mc0:/");
if (mc0_root_dir != NULL) {
closedir(mc0_root_dir);
return 0;
}
DIR *mc1_root_dir = opendir("mc1:/");
if (mc1_root_dir != NULL) {
closedir(mc1_root_dir);
return 1;
}
return -11;
}
int sysCheckVMC(const char *prefix, const char *sep, char *name, int createSize, vmc_superblock_t *vmc_superblock)
{
int size = -1;
char path[256];
snprintf(path, sizeof(path), "%sVMC%s%s.bin", prefix, sep, name);
if (createSize == -1)
unlink(path);
else {
int fd = open(path, O_RDONLY, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
if (fd >= 0) {
size = lseek(fd, 0, SEEK_END);
if (vmc_superblock) {
memset(vmc_superblock, 0, sizeof(vmc_superblock_t));
lseek(fd, 0, SEEK_SET);
read(fd, (void *)vmc_superblock, sizeof(vmc_superblock_t));
LOG("SYSTEM File size : 0x%X\n", size);
LOG("SYSTEM Magic : %s\n", vmc_superblock->magic);
LOG("SYSTEM Card type : %d\n", vmc_superblock->mc_type);
LOG("SYSTEM Flags : 0x%X\n", (vmc_superblock->mc_flag & 0xFF) | 0x100);
LOG("SYSTEM Page_size : 0x%X\n", vmc_superblock->page_size);
LOG("SYSTEM Block_size : 0x%X\n", vmc_superblock->pages_per_block);
LOG("SYSTEM Card_size : 0x%X\n", vmc_superblock->pages_per_cluster * vmc_superblock->clusters_per_card);
if (!strncmp(vmc_superblock->magic, "Sony PS2 Memory Card Format", 27) && vmc_superblock->mc_type == 0x2 && size == vmc_superblock->pages_per_cluster * vmc_superblock->clusters_per_card * vmc_superblock->page_size) {
LOG("SYSTEM VMC file structure valid: %s\n", path);
} else
size = 0;
}
if (size % 1048576)
size = 0;
else
size /= 1048576;
close(fd);
if (createSize && (createSize != size))
unlink(path);
}
if (createSize && (createSize != size)) {
createVMCparam_t createParam;
strcpy(createParam.VMC_filename, path);
createParam.VMC_size_mb = createSize;
createParam.VMC_blocksize = 16;
createParam.VMC_thread_priority = 0x0f;
createParam.VMC_card_slot = -1;
fileXioDevctl("genvmc:", 0xC0DE0001, (void *)&createParam, sizeof(createParam), NULL, 0);
}
}
return size;
}