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;
}