#include #include #include #define RAM_START 0x08800000L #define RAM_TOP 0x0A000000L typedef unsigned long ULONG; typedef struct { ULONG signature; // \0PBP int version; // 0x00010000 int offsets[8]; } PBP_HEADER; typedef struct { ULONG magic; // \0PSF char rfu000[4]; int label_ptr; int data_ptr; int nsects; } PSF_HEADER; typedef struct { short label_off; char rfu001; char data_type; int datafield_used; int datafield_size; int data_off; } PSF_SECT; /*****************************************************************************/ /* Search for EBOOT, returns pointer to data found, or NULL if none. */ /* */ /* Params: */ /* ULONG *xistart : start address */ /* char **xoappname : returns pointer to malloc'd buffer containing */ /* eboot name */ /* char **xoapptype : returns pointer to malloc'd buffer containing */ /* eboot type */ /*****************************************************************************/ ULONG * searchForEboot(ULONG *xistart, char **xoappname, char **xoapptype) { int ldone = 0; ULONG *lptr; PSF_HEADER *lPsfHeader; ULONG *lfinaloffsaddr; int ii; *xoappname = NULL; *xoapptype = NULL; while (lptr < (ULONG*)RAM_TOP) { if (*lptr == 0x50425000L) // '\0PBP' : PBP magic num { /***********************************************************************/ /* Double-check that the final offset is within user RAM - this seems */ /* to eliminate most of the false positives */ /***********************************************************************/ lfinaloffsaddr = (lptr + (((PBP_HEADER*)lptr)->offsets[7] / 4)); if ((lfinaloffsaddr < (ULONG*)RAM_TOP) && (lfinaloffsaddr > (ULONG*)RAM_START)) { lPsfHeader = (PSF_HEADER*)(lptr + (((PBP_HEADER*)lptr)->offsets[0] / 4)); if (lPsfHeader->magic == 0x46535000L) // '\0PSF' : PSF magic num { char *lpsflabels = ((char*)lPsfHeader) + lPsfHeader->label_ptr; char *lpsfdata = ((char*)lPsfHeader) + lPsfHeader->data_ptr; PSF_SECT *lpsfsect; lpsfsect = (PSF_SECT*) (((char*)lPsfHeader) + sizeof(PSF_HEADER)); for (ii = 0; ii < lPsfHeader->nsects; ii++) { /*****************************************************************/ /* We're just looking for the EBOOT type param, and EBOOT title, */ /* which are string types. So we can ignore non-strings. */ /*****************************************************************/ if (lpsfsect[ii].data_type == 2) { char *llabel = lpsflabels + lpsfsect[ii].label_off; if (stricmp(llabel, "TITLE")==0) { *xoappname = (char*)malloc(lpsfsect[ii].datafield_size + 1); if (*xoappname) { strncpy(*xoappname, lpsfdata + lpsfsect[ii].data_off, lpsfsect[ii].datafield_size); (*xoappname)[lpsfsect[ii].datafield_size] = '\0'; } } else if (stricmp(llabel, "CATEGORY")==0) { *xoapptype = (char*)malloc(lpsfsect[ii].datafield_size + 1); if (*xoapptype) { strncpy(*xoapptype, lpsfdata + lpsfsect[ii].data_off, lpsfsect[ii].datafield_size); (*xoapptype)[lpsfsect[ii].datafield_size] = '\0'; } } } } return(lptr); } } } lptr++; } return(NULL); } /*****************************************************************************/ /* Search and dump the EBOOT.PBP */ /* */ /* Args: */ /* xifilename : filename to dump to */ /* xiwholeEboot : TRUE to dump the whole EBOOT, false to just dump the ELF*/ /*****************************************************************************/ ULONG *dumpGameshareEboot(const char *xifilename, int xiwholeEboot) { char *lstartaddr = (char*)RAM_START; char *lendaddr; char *lappname; char *lapptype; int ldone = 0; int loutfile; while (!ldone) { lstartaddr = (char*) searchForEboot((ULONG*)lstartaddr, &lappname, &lapptype); if (!lstartaddr) { ldone = 1; } else if (lapptype) { if (stricmp(lapptype, "WG")) { ldone = 1; } } } /***************************************************************************/ /* If we have a non-NULL pointer, then we found a gameshare eboot. */ /* Dump it now. */ /***************************************************************************/ if (lstartaddr) { lendaddr = lstartaddr + ((PBP_HEADER*)lstartaddr)->offsets[7]; if (!xiwholeEboot) { lstartaddr = lstartaddr + ((PBP_HEADER*)lstartaddr)->offsets[6]; } loutfile = sceIoOpen(xifilename, PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777); if (loutfile > 0) { sceIoWrite(loutfile, lstartaddr, (lendaddr - lstartaddr)); sceIoClose(loutfile); } } }