I have tried using just the plain PSAR file and the PSAR packed into an updater EBOOT and this hasn't fixed the issue all official updater EBOOTs appear to extract alright. I have also tried extracting the PSAR with the original 5.00 3000 PSAR dumper and it correctly dumped the files and I have not modified libpsardumper or pspdecrypt. I have also left the PSAR buffer size at 9400000 which is the same as the original PSAR decrypter but I have tried a number of different buffer sizes, although I cannot read the whole file at once due to a lack of available RAM so I cannot increase the buffer to the full PSAR size. Lastly I have also tried disabling that particular check and using a 'less' modified version of the PSAR dumper which decrypts all the files with no success.
Assume the paramaters passed are DumpPSAR(MODE_ENCRYPT, "ms0:/360.PSAR", "ms0:/TM/360M33", "3.60", NULL);
Code: Select all
void DumpPSAR(int extractmode, char *filepath, char *outdir, char *requiredver, char *requiredfiles[])
{
char message[256];
int s, res;
u8 pbp_header[0x28];
SceUID fd;
int error = 0;
int psar_pos = 0, psar_offs;
int table_mode;
if (sceKernelDevkitVersion() < 0x02070110){
vlfGuiMessageDialog("PSAR Extraction requires a 2.71 or higher kernel. If you are in a Custom Firmware please re-execute this application on a higher kernel.", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
sceKernelVolatileMemLock(0, (void *)&g_dataOut2, &s);
SetStatus(0, 0, 240, 120, VLF_ALIGNMENT_CENTER, "Loading PSAR...");
if (ReadFile(filepath, 0, pbp_header, sizeof(pbp_header)) != sizeof(pbp_header)){
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog(strcat("Unable to read ", strdup(filepath)), VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
if(memcmp(pbp_header, "PSAR", 4) == 0){psar_offs = 0;}
else{psar_offs = *(u32 *)&pbp_header[0x24];}
fd = sceIoOpen(filepath, PSP_O_RDONLY, 0);
int cbFile = sceIoLseek32(fd, 0, PSP_SEEK_END) - psar_offs;
sceIoLseek32(fd, psar_offs, PSP_SEEK_SET);
SetStatus(0, 1, 240, 160, VLF_ALIGNMENT_CENTER, "Buffering PSAR data...");
if (sceIoRead(fd, g_dataPSAR, PSAR_BUFFER_SIZE) <= 0){
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog("Error reading file", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
if (memcmp(g_dataPSAR, "PSAR", 4) != 0){
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog("Invalid PSAR file", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
res = pspPSARInit(g_dataPSAR, g_dataOut, g_dataOut2);
if (res < 0){
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog("pspPSARInit failed", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
char *ver = GetVersion((char *)g_dataOut+0x10);
if(requiredver != NULL){
if(strcmp(ver, requiredver) != 0){
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog("Wrong EBOOT.PBP version", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
}
if (memcmp(ver, "3.8", 3) == 0 || memcmp(ver, "3.9", 3) == 0){table_mode = 1;}
else if (memcmp(ver, "4.0", 3) == 0){table_mode = 2;}
else if (memcmp(ver, "5.0", 3) == 0){table_mode = 3;}
else{table_mode = 0;}
SetStatus(0, 0, 240, 120, VLF_ALIGNMENT_CENTER, "Table Mode: %d", table_mode);
while (1){
char name[128];
int cbExpanded;
int pos;
int signcheck;
int i = 0, filerequired = 1;
int res = pspPSARGetNextFile(g_dataPSAR, cbFile, g_dataOut, g_dataOut2, name, &cbExpanded, &pos, &signcheck);
if (res < 0){
if (error){
sprintf(message, "PSAR decode error at 0x%08X", pos);
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog(message, VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
int dpos = pos-psar_pos;
psar_pos = pos;
error = 1;
memmove(g_dataPSAR, g_dataPSAR+dpos, PSAR_BUFFER_SIZE-dpos);
SetStatus(0, 1, 240, 160, VLF_ALIGNMENT_CENTER, "Buffering PSAR data...");
if (sceIoRead(fd, g_dataPSAR+(PSAR_BUFFER_SIZE-dpos), dpos) <= 0){
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog("Unable to read file", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
pspPSARSetBufferPosition(psar_pos);
continue;
}
else if (res == 0){ /* no more files */
break;
}
if (is5Dnum(name)){
if (strcmp(name, "00001") != 0 && strcmp(name, "00002") != 0 && strcmp(name, "00003") != 0){
int found = 0;
if (_1gtable_size > 0){found = FindTablePath(_1g_table, _1gtable_size, name, name);}
if (!found && _2gtable_size > 0){found = FindTablePath(_2g_table, _2gtable_size, name, name);}
if (!found && _3gtable_size > 0){found = FindTablePath(_3g_table, _3gtable_size, name, name);}
if (!found){
SetStatus(0, 0, 240, 120, VLF_ALIGNMENT_CENTER, "Warning: cannot find path of %s", name);
error = 0;
continue;
}
}
}
else if (!strncmp(name, "com:", 4) && comtable_size > 0){
if (!FindTablePath(com_table, comtable_size, name+4, name)){
SetStatus(0, 0, 240, 120, VLF_ALIGNMENT_CENTER, "Warning: cannot find path of %s", name);
error = 0;
continue;
}
}
else if (!strncmp(name, "01g:", 4) && _1gtable_size > 0){
if (!FindTablePath(_1g_table, _1gtable_size, name+4, name)){
sprintf(message, "Cannot find path of %s", name);
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog(message, VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
}
else if (!strncmp(name, "02g:", 4) && _2gtable_size > 0){
if (!FindTablePath(_2g_table, _2gtable_size, name+4, name)){
sprintf(message, "Cannot find path of %s", name);
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog(message, VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
}
if(requiredfiles == NULL){filerequired = 1;}
else{
filerequired = 0;
i = 0;
while(i != -1){
if(strcmp(name, requiredfiles[i]) == 0){filerequired = 1;i = -2;}
i++;
if(strcmp(requiredfiles[i], "0") == 0){i = -1;}
}
}
if(filerequired == 1){SetStatus(0, 0, 240, 120, VLF_ALIGNMENT_CENTER, "%s", name);}
char* szFileBase = strrchr(name, '/');
if (szFileBase != NULL)
szFileBase++; // after slash
else
szFileBase = "err.err";
if (cbExpanded > 0){
char szDataPath[128];
if (!strncmp(name, "flash0:/", 8)){sprintf(szDataPath, "%s/%s", outdir, name+8);}
else if (!strncmp(name, "flash1:/", 8)){sprintf(szDataPath, "%s/%s", outdir, name+8);}
else if (!strcmp(name, "com:00000")){
comtable_size = pspDecryptTable(g_dataOut2, g_dataOut, cbExpanded, table_mode);
if (comtable_size <= 0){
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog("Cannot decrypt common table", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
if (comtable_size > sizeof(com_table)){
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog("COM table buffer is too small", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
memcpy(com_table, g_dataOut2, comtable_size);
continue;
}
else if (!strcmp(name, "01g:00000") || !strcmp(name, "00001")){
_1gtable_size = pspDecryptTable(g_dataOut2, g_dataOut, cbExpanded, table_mode);
if (_1gtable_size <= 0){
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog("Cannot decrypt 1g table", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
if (_1gtable_size > sizeof(_1g_table)){
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog("1g table buffer is too small", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
memcpy(_1g_table, g_dataOut2, _1gtable_size);
continue;
}
else if (!strcmp(name, "02g:00000") || !strcmp(name, "00002")){
_2gtable_size = pspDecryptTable(g_dataOut2, g_dataOut, cbExpanded, table_mode);
if (_2gtable_size <= 0){
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog("Cannot decrypt 2g table", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
if (_2gtable_size > sizeof(_2g_table)){
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog("2g table buffer is too small", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
memcpy(_2g_table, g_dataOut2, _2gtable_size);
continue;
}
else if (!strcmp(name, "00003")){
_3gtable_size = pspDecryptTable(g_dataOut2, g_dataOut, cbExpanded, table_mode);
if (_3gtable_size <= 0){
// We don't have yet the keys for table of 3000, they are only in mesg_led03g.prx
SetStatus(0, 0, 240, 120, VLF_ALIGNMENT_CENTER, "Cannot decrypt 3g table");
error = 0;
continue;
}
if (_3gtable_size > sizeof(_3g_table)){
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog("3g table buffer is too small", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
memcpy(_3g_table, g_dataOut2, _3gtable_size);
continue;
}
else{continue;}
if (signcheck && extractmode == MODE_ENCRYPT_SIGCHECK && (strcmp(name, "flash0:/kd/loadexec.prx") != 0) && (strcmp(name, "flash0:/kd/loadexec_01g.prx") != 0) && (strcmp(name, "flash0:/kd/loadexec_02g.prx") != 0)){
pspSignCheck(g_dataOut2);
}
if ((extractmode != MODE_DECRYPT) || (memcmp(g_dataOut2, "~PSP", 4) != 0)){
if (WriteFile(szDataPath, g_dataOut2, cbExpanded) != cbExpanded){
sprintf(message, "Cannot write %s", szDataPath);
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog(message, VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
break;
}
}
if ((memcmp(g_dataOut2, "~PSP", 4) == 0) && (extractmode == MODE_DECRYPT)){
int cbDecrypted = pspDecryptPRX(g_dataOut2, g_dataOut, cbExpanded);
// output goes back to main buffer
// trashed 'g_dataOut2'
if (cbDecrypted > 0){
u8* pbToSave = g_dataOut;
int cbToSave = cbDecrypted;
if ((g_dataOut[0] == 0x1F && g_dataOut[1] == 0x8B) || memcmp(g_dataOut, "2RLZ", 4) == 0 || memcmp(g_dataOut, "KL4E", 4) == 0){
int cbExp = pspDecompress(g_dataOut, g_dataOut2, sizeof(g_dataOut));
if (cbExp > 0){
pbToSave = g_dataOut2;
cbToSave = cbExp;
}
else{
SetStatus(0, 0, 240, 120, VLF_ALIGNMENT_CENTER, "Decompress error 0x%08X\n\nFile will be written compressed", cbExp);
}
}
if (WriteFile(szDataPath, pbToSave, cbToSave) != cbToSave){
sprintf(message, "Cannot write %s", szDataPath);
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog(message, VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
}
else
{
sceKernelVolatileMemUnlock(0);vlfGuiMessageDialog("Unable to decrypt file", VLF_MD_TYPE_ERROR|VLF_MD_BUTTONS_NONE);OnBackToMainMenu(0);return;
}
}
}
error = 0;
scePowerTick(0);
}
sceIoClose(fd);
scePowerTick(0);
SetStatus(1, 0, 240, 120, VLF_ALIGNMENT_CENTER, "PSAR file has been extracted to %s", outdir);
return 0;
}
Code: Select all
int WriteFile(char *file, void *buf, int size)
{
SceUID fd;
int i;
int pathlen = 0;
char filepath[128];
for(i=1; i<(strlen(file)); i++){
if(strncmp(file+i-1, "/", 1) == 0){
pathlen=i-1;
strncpy(filepath, file, pathlen);
filepath[pathlen] = 0;
sceIoMkdir(filepath, 0777);
}
}
fd = sceIoOpen(file, PSP_O_WRONLY|PSP_O_CREAT|PSP_O_TRUNC, 0777);
if(fd < 0){return fd;}
int written = sceIoWrite(fd, buf, size);
sceIoClose(fd);
return written;
}