220 lines
5.6 KiB
C
220 lines
5.6 KiB
C
//typedef unsigned char u8;
|
|
//typedef unsigned short u16;
|
|
//typedef unsigned int u32;
|
|
|
|
typedef void *pointer;
|
|
|
|
#define NULL 0
|
|
|
|
typedef struct _smod_mod_info {
|
|
//struct _smod_mod_info *next;
|
|
pointer next;
|
|
/** A pointer to the name in IOP RAM, this must be smem_read(). */
|
|
//char *name;
|
|
pointer name;
|
|
u16 version;
|
|
/** For MODLOAD shipped with games. The old MODLOAD module from boot ROMs do not use a flags field. */
|
|
u16 newflags;
|
|
u16 id;
|
|
u16 unused;
|
|
/** _start */
|
|
u32 entry;
|
|
u32 gp;
|
|
u32 text_start;
|
|
u32 text_size;
|
|
u32 data_size;
|
|
u32 bss_size;
|
|
u32 unused1;
|
|
u32 unused2;
|
|
} smod_mod_info_t;
|
|
|
|
typedef struct _slib_imp_list {
|
|
u8 magic;
|
|
//struct _slib_imp_list *next;
|
|
pointer next;
|
|
u16 version;
|
|
u16 flags;
|
|
u8 name[8];
|
|
//void *imports[0];
|
|
pointer imports[0];
|
|
} slib_imp_list_t;
|
|
|
|
typedef struct _slib_exp_lib {
|
|
//struct _slib_exp_lib *prev;
|
|
pointer prev;
|
|
//struct _slib_imp_list *caller;
|
|
pointer caller;
|
|
u16 version;
|
|
u16 flags;
|
|
u8 name[8];
|
|
//void *exports[0];
|
|
pointer exports[0];
|
|
} slib_exp_lib_t;
|
|
|
|
typedef struct _slib_exp_lib_list {
|
|
//struct _slib_exp_lib *tail;
|
|
pointer tail;
|
|
//struct _slib_exp_lib *head;
|
|
pointer head;
|
|
} slib_exp_lib_list_t;
|
|
|
|
#define SMEM_BUF_SIZE 0x300 //Must be large enough to accommodate all operations.
|
|
|
|
struct smem_buf {
|
|
union {
|
|
u8 bytes[SMEM_BUF_SIZE / sizeof(u8)];
|
|
u32 words[SMEM_BUF_SIZE / sizeof(u32)];
|
|
smod_mod_info_t mod_info;
|
|
slib_exp_lib_t exp_lib;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
size_t strlen(const char *str) {
|
|
const char *s;
|
|
for (s = str; *s; ++s);
|
|
return (s - str);
|
|
}
|
|
|
|
int memcmp(const char *cs_in, const char *ct_in, size_t n) {
|
|
size_t i;
|
|
const unsigned char * cs = (const unsigned char*) cs_in;
|
|
const unsigned char * ct = (const unsigned char*) ct_in;
|
|
|
|
for (i = 0; i < n; i++, cs++, ct++)
|
|
{
|
|
if (*cs < *ct)
|
|
{
|
|
return -1;
|
|
}
|
|
else if (*cs > *ct)
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
slib_exp_lib_list_t _slib_cur_exp_lib_list;
|
|
|
|
struct smem_buf smem_buf;
|
|
|
|
typedef unsigned int SifRpcReceiveData_t;
|
|
|
|
size_t SifRpcGetOtherData(void *a, pointer x, void *dest, size_t s, int z) {
|
|
memcpy(dest, x, s);
|
|
return s;
|
|
}
|
|
|
|
slib_exp_lib_list_t *slib_exp_lib_list(void) {
|
|
SifRpcReceiveData_t RData;
|
|
slib_exp_lib_t *core_exps;
|
|
slib_exp_lib_list_t *exp_lib_list = NULL;
|
|
u32 i, addr, core_end, NextMod, *exp_func;
|
|
void *pGetLoadcoreInternalData;
|
|
smod_mod_info_t *ModInfo;
|
|
|
|
/* Read the start of the global module table - this is where we will search. */
|
|
if(SifRpcGetOtherData(&RData, (void*)0x800, &smem_buf, sizeof(smod_mod_info_t), 0)>=0){
|
|
/* The first entry points to LOADCORE's module info. We then use the
|
|
module info to determine the end of LOADCORE's .text segment (just
|
|
past the export library we're trying to find. */
|
|
NextMod = *smem_buf.words;
|
|
if(SifRpcGetOtherData(&RData, (void*)NextMod, &smem_buf, sizeof(smod_mod_info_t), 0)>=0){
|
|
ModInfo = &smem_buf.mod_info;
|
|
core_end = ModInfo->text_start+ModInfo->text_size;
|
|
|
|
/* Back up so we position ourselves infront of where the export
|
|
library will be. */
|
|
if(SifRpcGetOtherData(&RData, (void*)(core_end - 512), &smem_buf, 512, 0)>=0){
|
|
/* Search for LOADCORE's export library. */
|
|
for (i = 0; i < 512; i += 4) {
|
|
/* SYSMEM's export library sits at 0x830, so it should appear in
|
|
LOADCORE's prev pointer. */
|
|
if (smem_buf.words[i / sizeof(u32)] == 0x830) {
|
|
if (!memcmp(smem_buf.bytes + i + 12, "loadcore", 8))
|
|
//if(*(unsigned int *)(smem_buf.bytes + i + 12) == 0x64616f6c) // 6c 6f 61 64 == load
|
|
break;
|
|
}
|
|
}
|
|
if (i >= 512)
|
|
return NULL;
|
|
|
|
/* Get to the start of the export table, and find the address of the
|
|
routine that will get us the export library list info. */
|
|
core_exps = (slib_exp_lib_t *)(smem_buf.bytes + i);
|
|
pGetLoadcoreInternalData = core_exps->exports[3];
|
|
|
|
if(SifRpcGetOtherData(&RData, pGetLoadcoreInternalData, &smem_buf, 8, 0)>=0){
|
|
exp_func = smem_buf.words;
|
|
|
|
/* Parse the two instructions that hold the address of the table. */
|
|
if ((exp_func[0] & 0xffff0000) != 0x3c020000) /* lui v0, XXXX */
|
|
return NULL;
|
|
if ((exp_func[1] & 0xffff0000) != 0x24420000) /* addiu v0, v0, XXXX */
|
|
return NULL;
|
|
|
|
addr = ((exp_func[0] & 0xffff) << 16) | (exp_func[1] & 0xffff);
|
|
|
|
if(SifRpcGetOtherData(&RData, (void*)addr, &smem_buf, 8, 0)>=0){
|
|
_slib_cur_exp_lib_list.tail = (slib_exp_lib_t *)(smem_buf.words[0]);
|
|
_slib_cur_exp_lib_list.head = (slib_exp_lib_t *)(smem_buf.words[1]);
|
|
exp_lib_list = &_slib_cur_exp_lib_list;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return exp_lib_list;
|
|
}
|
|
|
|
#define EXP_LIB_MAX SMEM_BUF_SIZE /* We can even handle CDVDMAN's bloat! */
|
|
|
|
int slib_get_exp_lib(const char *name, slib_exp_lib_t *library)
|
|
{
|
|
SifRpcReceiveData_t RData;
|
|
slib_exp_lib_list_t *exp_lib_list = &_slib_cur_exp_lib_list;
|
|
slib_exp_lib_t *exp_lib = &smem_buf.exp_lib;
|
|
void *cur_lib;
|
|
int len = strlen(name), count = 0;
|
|
|
|
if (!exp_lib_list->head && !(exp_lib_list = slib_exp_lib_list()))
|
|
return 0;
|
|
|
|
/* Read the tail export library to initiate the search. */
|
|
cur_lib = exp_lib_list->tail;
|
|
|
|
while (cur_lib) {
|
|
if(SifRpcGetOtherData(&RData, cur_lib, exp_lib, EXP_LIB_MAX, 0)>=0){
|
|
if (!memcmp(exp_lib->name, name, len)) {
|
|
while (exp_lib->exports[count] != 0)
|
|
count++;
|
|
|
|
if (library)
|
|
memcpy(library, exp_lib, sizeof(slib_exp_lib_t) + count * 4);
|
|
|
|
return count;
|
|
}
|
|
|
|
cur_lib = exp_lib->prev;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void *resolve(char *name, int export) {
|
|
slib_exp_lib_t *modload_lib = (void *)0x100;
|
|
|
|
memset(&_slib_cur_exp_lib_list, 0, sizeof(slib_exp_lib_list_t));
|
|
|
|
if (!slib_get_exp_lib(name, modload_lib)) {
|
|
return NULL;
|
|
}
|
|
|
|
return modload_lib->exports[export];
|
|
}
|