bool SavedataParam::Load(SceUtilitySavedataParam *param, int saveId) { if (!param) { return false; } u8 *data_ = (u8*)Memory::GetPointer(param->dataBuf); std::string dirPath = GetSaveFilePath(param, saveId); if (saveId >= 0 && saveNameListDataCount > 0) // if user selection, use it { if (saveDataList[saveId].size == 0) // don't read no existing file { return false; } } std::string filePath = dirPath+"/"+GetFileName(param); s64 readSize; INFO_LOG(HLE,"Loading file with size %u in %s",param->dataBufSize,filePath.c_str()); if (!ReadPSPFile(filePath, data_, param->dataBufSize, &readSize)) { ERROR_LOG(HLE,"Error reading file %s",filePath.c_str()); return false; } param->dataSize = (SceSize)readSize; // copy back save name in request strncpy(param->saveName,GetSaveDirName(param, saveId).c_str(),20); ParamSFOData sfoFile; std::string sfopath = dirPath+"/"+sfoName; PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath); if(sfoInfo.exists) // Read sfo { u8 *sfoData = new u8[(size_t)sfoInfo.size]; size_t sfoSize = (size_t)sfoInfo.size; if(ReadPSPFile(sfopath,sfoData,sfoSize, NULL)) { sfoFile.ReadSFO(sfoData,sfoSize); // copy back info in request strncpy(param->sfoParam.title,sfoFile.GetValueString("TITLE").c_str(),128); strncpy(param->sfoParam.savedataTitle,sfoFile.GetValueString("SAVEDATA_TITLE").c_str(),128); strncpy(param->sfoParam.detail,sfoFile.GetValueString("SAVEDATA_DETAIL").c_str(),1024); param->sfoParam.parentalLevel = sfoFile.GetValueInt("PARENTAL_LEVEL"); } delete[] sfoData; } // Don't know what it is, but PSP always respond this and this unlock some game param->bind = 1021; return true; }
void SavedataParam::LoadSFO(SceUtilitySavedataParam *param, const std::string dirPath) { ParamSFOData sfoFile; std::string sfopath = dirPath+"/" + SFO_FILENAME; PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath); if (sfoInfo.exists) { // Read sfo std::vector<u8> sfoData; if (pspFileSystem.ReadEntireFile(sfopath, sfoData) >= 0) { sfoFile.ReadSFO(sfoData); // copy back info in request strncpy(param->sfoParam.title,sfoFile.GetValueString("TITLE").c_str(),128); strncpy(param->sfoParam.savedataTitle,sfoFile.GetValueString("SAVEDATA_TITLE").c_str(),128); strncpy(param->sfoParam.detail,sfoFile.GetValueString("SAVEDATA_DETAIL").c_str(),1024); param->sfoParam.parentalLevel = sfoFile.GetValueInt("PARENTAL_LEVEL"); } } }
void SavedataParam::LoadSFO(SceUtilitySavedataParam *param, const std::string dirPath) { ParamSFOData sfoFile; std::string sfopath = dirPath+"/" + SFO_FILENAME; PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath); if(sfoInfo.exists) { // Read sfo u8 *sfoData = new u8[(size_t)sfoInfo.size]; size_t sfoSize = (size_t)sfoInfo.size; if(ReadPSPFile(sfopath,&sfoData,sfoSize, NULL)) { sfoFile.ReadSFO(sfoData,sfoSize); // copy back info in request strncpy(param->sfoParam.title,sfoFile.GetValueString("TITLE").c_str(),128); strncpy(param->sfoParam.savedataTitle,sfoFile.GetValueString("SAVEDATA_TITLE").c_str(),128); strncpy(param->sfoParam.detail,sfoFile.GetValueString("SAVEDATA_DETAIL").c_str(),1024); param->sfoParam.parentalLevel = sfoFile.GetValueInt("PARENTAL_LEVEL"); } delete[] sfoData; } }
// TODO : improve, look in the file more IdentifiedFileType Identify_File(FileLoader *fileLoader) { if (fileLoader == nullptr) { ERROR_LOG(LOADER, "Invalid fileLoader"); return FILETYPE_ERROR; } if (fileLoader->Path().size() == 0) { ERROR_LOG(LOADER, "Invalid filename %s", fileLoader->Path().c_str()); return FILETYPE_ERROR; } if (!fileLoader->Exists()) { return FILETYPE_ERROR; } std::string extension = fileLoader->Extension(); if (!strcasecmp(extension.c_str(), ".iso")) { // may be a psx iso, they have 2352 byte sectors. You never know what some people try to open if ((fileLoader->FileSize() % 2352) == 0) { unsigned char sync[12]; fileLoader->ReadAt(0, 12, sync); // each sector in a mode2 image starts with these 12 bytes if (memcmp(sync,"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00",12) == 0) { return FILETYPE_ISO_MODE2; } // maybe it also just happened to have that size, } return FILETYPE_PSP_ISO; } else if (!strcasecmp(extension.c_str(),".cso")) { return FILETYPE_PSP_ISO; } else if (!strcasecmp(extension.c_str(),".ppst")) { return FILETYPE_PPSSPP_SAVESTATE; } // First, check if it's a directory with an EBOOT.PBP in it. if (fileLoader->IsDirectory()) { std::string filename = fileLoader->Path(); if (filename.size() > 4) { // Check for existence of EBOOT.PBP, as required for "Directory games". if (File::Exists((filename + "/EBOOT.PBP").c_str())) { return FILETYPE_PSP_PBP_DIRECTORY; } // check if it's a disc directory if (File::Exists((filename + "/PSP_GAME").c_str())) { return FILETYPE_PSP_DISC_DIRECTORY; } // Not that, okay, let's guess it's a savedata directory if it has a param.sfo... if (File::Exists((filename + "/PARAM.SFO").c_str())) { return FILETYPE_PSP_SAVEDATA_DIRECTORY; } } return FILETYPE_NORMAL_DIRECTORY; } u32_le id; size_t readSize = fileLoader->ReadAt(0, 4, 1, &id); if (readSize != 1) { return FILETYPE_ERROR; } u32 psar_offset = 0, psar_id = 0; u32 _id = id; switch (_id) { case 'PBP\x00': fileLoader->ReadAt(0x24, 4, 1, &psar_offset); fileLoader->ReadAt(psar_offset, 4, 1, &psar_id); break; case '!raR': return FILETYPE_ARCHIVE_RAR; case '\x04\x03KP': case '\x06\x05KP': case '\x08\x07KP': return FILETYPE_ARCHIVE_ZIP; } if (id == 'FLE\x7F') { std::string filename = fileLoader->Path(); // There are a few elfs misnamed as pbp (like Trig Wars), accept that. if (!strcasecmp(extension.c_str(), ".plf") || strstr(filename.c_str(),"BOOT.BIN") || !strcasecmp(extension.c_str(), ".elf") || !strcasecmp(extension.c_str(), ".prx") || !strcasecmp(extension.c_str(), ".pbp")) { return FILETYPE_PSP_ELF; } return FILETYPE_UNKNOWN_ELF; } else if (id == 'PBP\x00') { // Do this PS1 eboot check FIRST before checking other eboot types. // It seems like some are malformed and slip through the PSAR check below. PBPReader pbp(fileLoader); if (pbp.IsValid() && !pbp.IsELF()) { std::vector<u8> sfoData; if (pbp.GetSubFile(PBP_PARAM_SFO, &sfoData)) { ParamSFOData paramSFO; paramSFO.ReadSFO(sfoData); // PS1 Eboots are supposed to use "ME" as their PARAM SFO category. // If they don't, and they're still malformed (e.g. PSISOIMG0000 isn't found), there's nothing we can do. if (paramSFO.GetValueString("CATEGORY") == "ME") return FILETYPE_PSP_PS1_PBP; } } if (psar_id == 'MUPN') { return FILETYPE_PSP_ISO_NP; } // PS1 PSAR begins with "PSISOIMG0000" if (psar_id == 'SISP') { return FILETYPE_PSP_PS1_PBP; } // Let's check if we got pointed to a PBP within such a directory. // If so we just move up and return the directory itself as the game. std::string path = File::GetDir(fileLoader->Path()); // If loading from memstick... size_t pos = path.find("/PSP/GAME/"); if (pos != std::string::npos) { return FILETYPE_PSP_PBP_DIRECTORY; } return FILETYPE_PSP_PBP; } else if (!strcasecmp(extension.c_str(),".pbp")) { ERROR_LOG(LOADER, "A PBP with the wrong magic number?"); return FILETYPE_PSP_PBP; } else if (!strcasecmp(extension.c_str(),".bin")) { return FILETYPE_UNKNOWN_BIN; } else if (!strcasecmp(extension.c_str(),".zip")) { return FILETYPE_ARCHIVE_ZIP; } else if (!strcasecmp(extension.c_str(),".rar")) { return FILETYPE_ARCHIVE_RAR; } else if (!strcasecmp(extension.c_str(),".r00")) { return FILETYPE_ARCHIVE_RAR; } else if (!strcasecmp(extension.c_str(),".r01")) { return FILETYPE_ARCHIVE_RAR; } else if (!extension.empty() && !strcasecmp(extension.substr(1).c_str(), ".7z")) { return FILETYPE_ARCHIVE_7Z; } return FILETYPE_UNKNOWN; }
void CPU_Init() { coreState = CORE_POWERUP; currentMIPS = &mipsr4k; g_symbolMap = new SymbolMap(); // Default memory settings // Seems to be the safest place currently.. Memory::g_MemorySize = Memory::RAM_NORMAL_SIZE; // 32 MB of ram by default g_RemasterMode = false; g_DoubleTextureCoordinates = false; Memory::g_PSPModel = g_Config.iPSPModel; std::string filename = coreParameter.fileToStart; loadedFile = ResolveFileLoaderTarget(ConstructFileLoader(filename)); #ifdef _M_X64 if (g_Config.bCacheFullIsoInRam) { loadedFile = new RamCachingFileLoader(loadedFile); } #endif IdentifiedFileType type = Identify_File(loadedFile); // TODO: Put this somewhere better? if (coreParameter.mountIso != "") { coreParameter.mountIsoLoader = ConstructFileLoader(coreParameter.mountIso); } MIPSAnalyst::Reset(); Replacement_Init(); switch (type) { case FILETYPE_PSP_ISO: case FILETYPE_PSP_ISO_NP: case FILETYPE_PSP_DISC_DIRECTORY: InitMemoryForGameISO(loadedFile); break; case FILETYPE_PSP_PBP: InitMemoryForGamePBP(loadedFile); break; case FILETYPE_PSP_PBP_DIRECTORY: // This is normal for homebrew. // ERROR_LOG(LOADER, "PBP directory resolution failed."); break; default: break; } // Here we have read the PARAM.SFO, let's see if we need any compatibility overrides. // Homebrew usually has an empty discID, and even if they do have a disc id, it's not // likely to collide with any commercial ones. std::string discID = g_paramSFO.GetValueString("DISC_ID"); if (!discID.empty()) { coreParameter.compat.Load(discID); } Memory::Init(); mipsr4k.Reset(); host->AttemptLoadSymbolMap(); if (coreParameter.enableSound) { Audio_Init(); } CoreTiming::Init(); // Init all the HLE modules HLEInit(); // TODO: Check Game INI here for settings, patches and cheats, and modify coreParameter accordingly // Why did we check for CORE_POWERDOWN here? if (!LoadFile(&loadedFile, &coreParameter.errorString)) { CPU_Shutdown(); coreParameter.fileToStart = ""; CPU_SetState(CPU_THREAD_NOT_RUNNING); return; } if (coreParameter.updateRecent) { g_Config.AddRecent(filename); } coreState = coreParameter.startPaused ? CORE_STEPPING : CORE_RUNNING; }
bool SavedataParam::Load(SceUtilitySavedataParam *param, int saveId) { if (!param) { return false; } u8 *data_ = (u8*)Memory::GetPointer(param->dataBuf); std::string dirPath = GetSaveFilePath(param, saveId); if (saveId >= 0 && saveNameListDataCount > 0) // if user selection, use it { if (saveDataList[saveId].size == 0) // don't read no existing file { return false; } } std::string filePath = dirPath+"/"+GetFileName(param); s64 readSize; INFO_LOG(HLE,"Loading file with size %u in %s",param->dataBufSize,filePath.c_str()); u8* saveData = 0; int saveSize = -1; if (!ReadPSPFile(filePath, &saveData, saveSize, &readSize)) { ERROR_LOG(HLE,"Error reading file %s",filePath.c_str()); return false; } saveSize = (int)readSize; // copy back save name in request strncpy(param->saveName,GetSaveDirName(param, saveId).c_str(),20); ParamSFOData sfoFile; std::string sfopath = dirPath+"/"+sfoName; PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath); if(sfoInfo.exists) // Read sfo { u8 *sfoData = new u8[(size_t)sfoInfo.size]; size_t sfoSize = (size_t)sfoInfo.size; if(ReadPSPFile(sfopath,&sfoData,sfoSize, NULL)) { sfoFile.ReadSFO(sfoData,sfoSize); // copy back info in request strncpy(param->sfoParam.title,sfoFile.GetValueString("TITLE").c_str(),128); strncpy(param->sfoParam.savedataTitle,sfoFile.GetValueString("SAVEDATA_TITLE").c_str(),128); strncpy(param->sfoParam.detail,sfoFile.GetValueString("SAVEDATA_DETAIL").c_str(),1024); param->sfoParam.parentalLevel = sfoFile.GetValueInt("PARENTAL_LEVEL"); } delete[] sfoData; } // Don't know what it is, but PSP always respond this and this unlock some game param->bind = 1021; bool isCrypted = IsSaveEncrypted(param,saveId); bool saveDone = false; if(isCrypted)// Try to decrypt { int align_len = align16(saveSize); u8* data_base = new u8[align_len]; u8* cryptKey = new u8[0x10]; memset(cryptKey,0,0x10); if(param->key[0] != 0) { memcpy(cryptKey, param->key, 0x10); } memset(data_base + saveSize, 0, align_len - saveSize); memcpy(data_base, saveData, saveSize); int decryptMode = 1; if(param->key[0] != 0) { decryptMode = (GetSDKMainVersion(sceKernelGetCompiledSdkVersion()) >= 4 ? 5 : 3); } if(DecryptSave(decryptMode, data_base, &saveSize, &align_len, ((param->key[0] != 0)?cryptKey:0)) == 0) { memcpy(data_, data_base, saveSize); saveDone = true; } delete[] data_base; delete[] cryptKey; } if(!saveDone) // not crypted or decrypt fail { memcpy(data_, saveData, saveSize); } param->dataSize = (SceSize)saveSize; delete[] saveData; return true; }
// TODO : improve, look in the file more IdentifiedFileType Identify_File(std::string &filename) { if (filename.size() == 0) { ERROR_LOG(LOADER, "invalid filename %s", filename.c_str()); return FILETYPE_ERROR; } FileInfo info; if (!getFileInfo(filename.c_str(), &info)) { return FILETYPE_ERROR; } std::string extension = filename.size() >= 5 ? filename.substr(filename.size() - 4) : ""; if (!strcasecmp(extension.c_str(),".iso")) { // may be a psx iso, they have 2352 byte sectors. You never know what some people try to open if ((info.size % 2352) == 0) { FILE *f = File::OpenCFile(filename.c_str(), "rb"); if (!f) { // File does not exists return FILETYPE_ERROR; } unsigned char sync[12]; fread(sync,1,12,f); fclose(f); // each sector in a mode2 image starts with these 12 bytes if (memcmp(sync,"\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00",12) == 0) { return FILETYPE_ISO_MODE2; } // maybe it also just happened to have that size, } return FILETYPE_PSP_ISO; } else if (!strcasecmp(extension.c_str(),".cso")) { return FILETYPE_PSP_ISO; } // First, check if it's a directory with an EBOOT.PBP in it. if (info.isDirectory) { if (filename.size() > 4) { FileInfo ebootInfo; // Check for existence of EBOOT.PBP, as required for "Directory games". if (getFileInfo((filename + "/EBOOT.PBP").c_str(), &ebootInfo)) { if (ebootInfo.exists) { return FILETYPE_PSP_PBP_DIRECTORY; } } // check if it's a disc directory if (getFileInfo((filename + "/PSP_GAME").c_str(), &ebootInfo)) { if (ebootInfo.exists) { return FILETYPE_PSP_DISC_DIRECTORY; } } } return FILETYPE_NORMAL_DIRECTORY; } FILE *f = File::OpenCFile(filename.c_str(), "rb"); if (!f) { // File does not exists return FILETYPE_ERROR; } u32_le id; size_t readSize = fread(&id, 4, 1, f); if (readSize != 1) { fclose(f); return FILETYPE_ERROR; } u32 psar_offset = 0, psar_id = 0; u32 _id = id; switch (_id) { case 'PBP\x00': fseek(f, 0x24, SEEK_SET); fread(&psar_offset, 4, 1, f); fseek(f, psar_offset, SEEK_SET); fread(&psar_id, 4, 1, f); break; case '!raR': return FILETYPE_ARCHIVE_RAR; case '\x04\x03KP': case '\x06\x05KP': case '\x08\x07KP': return FILETYPE_ARCHIVE_ZIP; } fclose(f); if (id == 'FLE\x7F') { // There are a few elfs misnamed as pbp (like Trig Wars), accept that. if (!strcasecmp(extension.c_str(), ".plf") || strstr(filename.c_str(),"BOOT.BIN") || !strcasecmp(extension.c_str(), ".elf") || !strcasecmp(extension.c_str(), ".prx") || !strcasecmp(extension.c_str(), ".pbp")) { return FILETYPE_PSP_ELF; } return FILETYPE_UNKNOWN_ELF; } else if (id == 'PBP\x00') { // Do this PS1 eboot check FIRST before checking other eboot types. // It seems like some are malformed and slip through the PSAR check below. PBPReader pbp(filename.c_str()); if (pbp.IsValid()) { if (!pbp.IsELF()) { size_t sfoSize; u8 *sfoData = pbp.GetSubFile(PBP_PARAM_SFO, &sfoSize); { recursive_mutex _lock; lock_guard lock(_lock); ParamSFOData paramSFO; paramSFO.ReadSFO(sfoData, sfoSize); // PS1 Eboots are supposed to use "ME" as their PARAM SFO category. // If they don't, and they're still malformed (e.g. PSISOIMG0000 isn't found), there's nothing we can do. if (paramSFO.GetValueString("CATEGORY") == "ME") return FILETYPE_PSP_PS1_PBP; } delete[] sfoData; } } if (psar_id == 'MUPN') { return FILETYPE_PSP_ISO_NP; } // PS1 PSAR begins with "PSISOIMG0000" if (psar_id == 'SISP') { return FILETYPE_PSP_PS1_PBP; } // Let's check if we got pointed to a PBP within such a directory. // If so we just move up and return the directory itself as the game. std::string path = getDir(filename); // If loading from memstick... size_t pos = path.find("/PSP/GAME/"); if (pos != std::string::npos) { filename = path; return FILETYPE_PSP_PBP_DIRECTORY; } return FILETYPE_PSP_PBP; } else if (!strcasecmp(extension.c_str(),".pbp")) { ERROR_LOG(LOADER, "A PBP with the wrong magic number?"); return FILETYPE_PSP_PBP; } else if (!strcasecmp(extension.c_str(),".bin")) { return FILETYPE_UNKNOWN_BIN; } else if (!strcasecmp(extension.c_str(),".zip")) { return FILETYPE_ARCHIVE_ZIP; } else if (!strcasecmp(extension.c_str(),".rar")) { return FILETYPE_ARCHIVE_RAR; } else if (!strcasecmp(extension.c_str(),".r00")) { return FILETYPE_ARCHIVE_RAR; } else if (!strcasecmp(extension.c_str(),".r01")) { return FILETYPE_ARCHIVE_RAR; } return FILETYPE_UNKNOWN; }