void __UmdReplace(std::string filepath) { // Only get system from disc0 seems have been enough. IFileSystem* currentUMD = pspFileSystem.GetSystem("disc0:"); if (!currentUMD) return; IFileSystem* umd2; FileInfo info; if (!getFileInfo(filepath.c_str(), &info)) // This shouldn't happen, but for safety. return; if (info.isDirectory) { umd2 = new VirtualDiscFileSystem(&pspFileSystem, filepath); } else { auto bd = constructBlockDevice(filepath.c_str()); if (!bd) return; umd2 = new ISOFileSystem(&pspFileSystem, bd); pspFileSystem.Remount(currentUMD, umd2); } delete currentUMD; // TODO Is this always correct if UMD was not activated? u32 notifyArg = PSP_UMD_PRESENT | PSP_UMD_READABLE | PSP_UMD_CHANGED; if (driveCBId != -1) __KernelNotifyCallback(driveCBId, notifyArg); }
bool Load_PSP_ELF_PBP(const char *filename, std::string *error_string) { // This is really just for headless, might need tweaking later. if (!PSP_CoreParameter().mountIso.empty()) { auto bd = constructBlockDevice(PSP_CoreParameter().mountIso.c_str()); if (bd != NULL) { ISOFileSystem *umd2 = new ISOFileSystem(&pspFileSystem, bd); pspFileSystem.Mount("umd1:", umd2); pspFileSystem.Mount("disc0:", umd2); pspFileSystem.Mount("umd:", umd2); } } std::string full_path = filename; std::string path, file, extension; SplitPath(ReplaceAll(full_path, "\\", "/"), &path, &file, &extension); #ifdef _WIN32 path = ReplaceAll(path, "/", "\\"); #endif DirectoryFileSystem *fs = new DirectoryFileSystem(&pspFileSystem, path); pspFileSystem.Mount("umd0:", fs); std::string finalName = "umd0:/" + file + extension; return __KernelLoadExec(finalName.c_str(), 0, error_string); }
ProcessResult process(const char *iso, const char *output) { BlockDevice *blockDevice = constructBlockDevice(iso); if (!blockDevice) return RESULT_INPUT_READ_FAIL; std::ofstream out; out.open(output); if (!out) { delete blockDevice; return RESULT_OUTPUT_WRITE_FAIL; } VolDescriptor desc; blockDevice->ReadBlock(16, (u8*)&desc); if (memcmp(desc.cd001, "CD001", 5)) { fprintf(stderr, "ERROR: Block 16 does not start with CD001.\n"); delete blockDevice; return RESULT_INPUT_PARSE_FAIL; } u32 rootSector = desc.root.firstDataSectorLE; u32 rootSize = desc.root.dataLengthLE; descend(blockDevice, rootSector, rootSize, out, ""); delete blockDevice; return RESULT_SUCCESS; }
// We gather the game info before actually loading/booting the ISO // to determine if the emulator should enable extra memory and // double-sized texture coordinates. void InitMemoryForGameISO(std::string fileToStart) { IFileSystem* umd2; // check if it's a disc directory FileInfo info; if (!getFileInfo(fileToStart.c_str(), &info)) return; if (info.isDirectory) { umd2 = new VirtualDiscFileSystem(&pspFileSystem, fileToStart); } else { auto bd = constructBlockDevice(fileToStart.c_str()); // Can't init anything without a block device... if (!bd) return; umd2 = new ISOFileSystem(&pspFileSystem, bd); } // Parse PARAM.SFO //pspFileSystem.Mount("host0:",umd2); pspFileSystem.Mount("umd0:", umd2); pspFileSystem.Mount("umd1:", umd2); pspFileSystem.Mount("disc0:", umd2); pspFileSystem.Mount("umd:", umd2); std::string gameID; std::string sfoPath("disc0:/PSP_GAME/PARAM.SFO"); PSPFileInfo fileInfo = pspFileSystem.GetFileInfo(sfoPath.c_str()); if (fileInfo.exists) { u8 *paramsfo = new u8[(size_t)fileInfo.size]; u32 fd = pspFileSystem.OpenFile(sfoPath, FILEACCESS_READ); pspFileSystem.ReadFile(fd, paramsfo, fileInfo.size); pspFileSystem.CloseFile(fd); if (g_paramSFO.ReadSFO(paramsfo, (size_t)fileInfo.size)) { gameID = g_paramSFO.GetValueString("DISC_ID"); for (size_t i = 0; i < ARRAY_SIZE(g_HDRemasters); i++) { if(g_HDRemasters[i].gameID == gameID) { g_RemasterMode = true; Memory::g_MemorySize = g_HDRemasters[i].MemorySize; if(g_HDRemasters[i].DoubleTextureCoordinates) g_DoubleTextureCoordinates = true; break; } } DEBUG_LOG(LOADER, "HDRemaster mode is %s", g_RemasterMode? "true": "false"); } delete [] paramsfo; } }
bool Load_PSP_ISO(const char *filename, std::string *error_string) { ISOFileSystem *umd2 = new ISOFileSystem(&pspFileSystem, constructBlockDevice(filename)); // Parse PARAM.SFO //pspFileSystem.Mount("host0:",umd2); pspFileSystem.Mount("umd0:", umd2); pspFileSystem.Mount("umd1:", umd2); pspFileSystem.Mount("disc0:", umd2); pspFileSystem.Mount("umd:", umd2); std::string sfoPath("disc0:/PSP_GAME/PARAM.SFO"); PSPFileInfo fileInfo = pspFileSystem.GetFileInfo(sfoPath.c_str()); if (fileInfo.exists) { u8 *paramsfo = new u8[(size_t)fileInfo.size]; u32 fd = pspFileSystem.OpenFile(sfoPath, FILEACCESS_READ); pspFileSystem.ReadFile(fd, paramsfo, fileInfo.size); pspFileSystem.CloseFile(fd); if (g_paramSFO.ReadSFO(paramsfo, (size_t)fileInfo.size)) { char title[1024]; sprintf(title, "%s : %s", g_paramSFO.GetValueString("DISC_ID").c_str(), g_paramSFO.GetValueString("TITLE").c_str()); INFO_LOG(LOADER, "%s", title); host->SetWindowTitle(title); } delete [] paramsfo; } std::string bootpath("disc0:/PSP_GAME/SYSDIR/EBOOT.BIN"); // bypass patchers if (pspFileSystem.GetFileInfo("disc0:/PSP_GAME/SYSDIR/EBOOT.OLD").exists) { bootpath = "disc0:/PSP_GAME/SYSDIR/EBOOT.OLD"; } bool hasEncrypted = false; u32 fd; if ((fd = pspFileSystem.OpenFile(bootpath, FILEACCESS_READ)) != 0) { u8 head[4]; pspFileSystem.ReadFile(fd, head, 4); if (memcmp(head, "~PSP", 4) == 0 || memcmp(head, "\x7F""ELF", 4) == 0) { hasEncrypted = true; } pspFileSystem.CloseFile(fd); } if (!hasEncrypted) { // try unencrypted BOOT.BIN bootpath = "disc0:/PSP_GAME/SYSDIR/BOOT.BIN"; } INFO_LOG(LOADER,"Loading %s...", bootpath.c_str()); return __KernelLoadExec(bootpath.c_str(), 0, error_string); }
bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) { // This is really just for headless, might need tweaking later. if (PSP_CoreParameter().mountIsoLoader != nullptr) { auto bd = constructBlockDevice(PSP_CoreParameter().mountIsoLoader); if (bd != NULL) { ISOFileSystem *umd2 = new ISOFileSystem(&pspFileSystem, bd); pspFileSystem.Mount("umd1:", umd2); pspFileSystem.Mount("disc0:", umd2); pspFileSystem.Mount("umd:", umd2); } } std::string full_path = fileLoader->Path(); std::string path, file, extension; SplitPath(ReplaceAll(full_path, "\\", "/"), &path, &file, &extension); #ifdef _WIN32 path = ReplaceAll(path, "/", "\\"); #endif if (!PSP_CoreParameter().mountRoot.empty()) { // We don't want to worry about .. and cwd and such. const std::string rootNorm = NormalizePath(PSP_CoreParameter().mountRoot + "/"); const std::string pathNorm = NormalizePath(path + "/"); // If root is not a subpath of path, we can't boot the game. if (!startsWith(pathNorm, rootNorm)) { *error_string = "Cannot boot ELF located outside mountRoot."; return false; } const std::string filepath = ReplaceAll(pathNorm.substr(rootNorm.size()), "\\", "/"); file = filepath + "/" + file; path = rootNorm + "/"; pspFileSystem.SetStartingDirectory(filepath); } DirectoryFileSystem *fs = new DirectoryFileSystem(&pspFileSystem, path); pspFileSystem.Mount("umd0:", fs); std::string finalName = "umd0:/" + file + extension; return __KernelLoadExec(finalName.c_str(), 0, error_string); }
void __UmdReplace(std::string filepath) { // TODO: This should really go through Loaders, no? What if it's an invalid file? // Only get system from disc0 seems have been enough. IFileSystem* currentUMD = pspFileSystem.GetSystem("disc0:"); IFileSystem* currentISOBlock = pspFileSystem.GetSystem("umd0:"); if (!currentUMD) return; FileLoader *loadedFile = ConstructFileLoader(filepath); IFileSystem* umd2; if (!loadedFile->Exists()) { delete loadedFile; return; } UpdateLoadedFile(loadedFile); if (loadedFile->IsDirectory()) { umd2 = new VirtualDiscFileSystem(&pspFileSystem, filepath); } else { auto bd = constructBlockDevice(loadedFile); if (!bd) return; umd2 = new ISOFileSystem(&pspFileSystem, bd); pspFileSystem.Remount(currentUMD, umd2); if (currentUMD != currentISOBlock) { // We mounted an ISO block system separately. IFileSystem *iso = new ISOBlockSystem(static_cast<ISOFileSystem *>(umd2)); pspFileSystem.Remount(currentISOBlock, iso); delete currentISOBlock; } } delete currentUMD; // TODO Is this always correct if UMD was not activated? u32 notifyArg = PSP_UMD_PRESENT | PSP_UMD_READABLE | PSP_UMD_CHANGED; if (driveCBId != -1) __KernelNotifyCallback(driveCBId, notifyArg); }
static int CalculateCRCThread() { setCurrentThreadName("ReportCRC"); // TODO: Use the blockDevice from pspFileSystem? FileLoader *fileLoader = ConstructFileLoader(crcFilename); BlockDevice *blockDevice = constructBlockDevice(fileLoader); u32 crc = 0; if (blockDevice) { crc = blockDevice->CalculateCRC(); } delete blockDevice; delete fileLoader; lock_guard guard(crcLock); crcResults[crcFilename] = crc; crcCond.notify_one(); return 0; }
virtual void run() { delete info_->fileLoader; info_->fileLoader = ConstructFileLoader(gamePath_); if (!info_->fileLoader->Exists()) return; std::string filename = gamePath_; info_->path = gamePath_; info_->fileType = Identify_File(info_->fileLoader); // Fallback title info_->title = getFilename(info_->path); switch (info_->fileType) { case FILETYPE_PSP_PBP: case FILETYPE_PSP_PBP_DIRECTORY: { std::string pbpFile = filename; if (info_->fileType == FILETYPE_PSP_PBP_DIRECTORY) pbpFile += "/EBOOT.PBP"; PBPReader pbp(pbpFile.c_str()); if (!pbp.IsValid()) { if (pbp.IsELF()) { goto handleELF; } ERROR_LOG(LOADER, "invalid pbp %s\n", pbpFile.c_str()); return; } // First, PARAM.SFO. size_t sfoSize; u8 *sfoData = pbp.GetSubFile(PBP_PARAM_SFO, &sfoSize); { lock_guard lock(info_->lock); info_->paramSFO.ReadSFO(sfoData, sfoSize); info_->ParseParamSFO(); } delete [] sfoData; // Then, ICON0.PNG. { lock_guard lock(info_->lock); if (pbp.GetSubFileSize(PBP_ICON0_PNG) > 0) { pbp.GetSubFileAsString(PBP_ICON0_PNG, &info_->iconTextureData); } else { // Read standard icon size_t sz; DEBUG_LOG(LOADER, "Loading unknown.png because a PBP was missing an icon"); uint8_t *contents = VFSReadFile("unknown.png", &sz); if (contents) { lock_guard lock(info_->lock); info_->iconTextureData = std::string((const char *)contents, sz); } delete [] contents; } info_->iconDataLoaded = true; } if (info_->wantFlags & GAMEINFO_WANTBG) { if (pbp.GetSubFileSize(PBP_PIC0_PNG) > 0) { lock_guard lock(info_->lock); pbp.GetSubFileAsString(PBP_PIC0_PNG, &info_->pic0TextureData); info_->pic0DataLoaded = true; } if (pbp.GetSubFileSize(PBP_PIC1_PNG) > 0) { lock_guard lock(info_->lock); pbp.GetSubFileAsString(PBP_PIC1_PNG, &info_->pic1TextureData); info_->pic1DataLoaded = true; } } if (info_->wantFlags & GAMEINFO_WANTSND) { if (pbp.GetSubFileSize(PBP_SND0_AT3) > 0) { lock_guard lock(info_->lock); pbp.GetSubFileAsString(PBP_SND0_AT3, &info_->sndFileData); info_->sndDataLoaded = true; } } } break; case FILETYPE_PSP_ELF: handleELF: // An elf on its own has no usable information, no icons, no nothing. info_->title = getFilename(filename); info_->id = "ELF000000"; info_->id_version = "ELF000000_1.00"; info_->paramSFOLoaded = true; { // Read standard icon size_t sz; uint8_t *contents = VFSReadFile("unknown.png", &sz); DEBUG_LOG(LOADER, "Loading unknown.png because there was an ELF"); if (contents) { lock_guard lock(info_->lock); info_->iconTextureData = std::string((const char *)contents, sz); info_->iconDataLoaded = true; } delete [] contents; } break; case FILETYPE_PSP_DISC_DIRECTORY: { info_->fileType = FILETYPE_PSP_ISO; SequentialHandleAllocator handles; VirtualDiscFileSystem umd(&handles, gamePath_.c_str()); // Alright, let's fetch the PARAM.SFO. std::string paramSFOcontents; if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, 0)) { lock_guard lock(info_->lock); info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size()); info_->ParseParamSFO(); } ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock); info_->iconDataLoaded = true; if (info_->wantFlags & GAMEINFO_WANTBG) { ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock); info_->pic0DataLoaded = true; ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); info_->pic1DataLoaded = true; } if (info_->wantFlags & GAMEINFO_WANTSND) { ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, &info_->lock); info_->pic1DataLoaded = true; } break; } case FILETYPE_PSP_ISO: case FILETYPE_PSP_ISO_NP: { info_->fileType = FILETYPE_PSP_ISO; SequentialHandleAllocator handles; // Let's assume it's an ISO. // TODO: This will currently read in the whole directory tree. Not really necessary for just a // few files. BlockDevice *bd = constructBlockDevice(info_->fileLoader); if (!bd) return; // nothing to do here.. ISOFileSystem umd(&handles, bd, "/PSP_GAME"); // Alright, let's fetch the PARAM.SFO. std::string paramSFOcontents; if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, 0)) { lock_guard lock(info_->lock); info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size()); info_->ParseParamSFO(); if (info_->wantFlags & GAMEINFO_WANTBG) { ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock); info_->pic0DataLoaded = true; ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); info_->pic1DataLoaded = true; } if (info_->wantFlags & GAMEINFO_WANTSND) { ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, &info_->lock); info_->pic1DataLoaded = true; } } // Fall back to unknown icon if ISO is broken/is a homebrew ISO, override is allowed though if (!ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock)) { size_t sz; uint8_t *contents = VFSReadFile("unknown.png", &sz); DEBUG_LOG(LOADER, "Loading unknown.png because no icon was found"); if (contents) { lock_guard lock(info_->lock); info_->iconTextureData = std::string((const char *)contents, sz); } delete [] contents; } info_->iconDataLoaded = true; break; } case FILETYPE_ARCHIVE_ZIP: info_->paramSFOLoaded = true; { // Read standard icon size_t sz; uint8_t *contents = VFSReadFile("zip.png", &sz); if (contents) { lock_guard lock(info_->lock); info_->iconTextureData = std::string((const char *)contents, sz); info_->iconDataLoaded = true; } delete [] contents; } break; case FILETYPE_ARCHIVE_RAR: info_->paramSFOLoaded = true; { // Read standard icon size_t sz; uint8_t *contents = VFSReadFile("rargray.png", &sz); if (contents) { lock_guard lock(info_->lock); info_->iconTextureData = std::string((const char *)contents, sz); info_->iconDataLoaded = true; } delete [] contents; } break; case FILETYPE_ARCHIVE_7Z: info_->paramSFOLoaded = true; { // Read standard icon size_t sz; uint8_t *contents = VFSReadFile("7z.png", &sz); if (contents) { lock_guard lock(info_->lock); info_->iconTextureData = std::string((const char *)contents, sz); info_->iconDataLoaded = true; } delete[] contents; } break; case FILETYPE_NORMAL_DIRECTORY: default: info_->paramSFOLoaded = true; break; } if (info_->wantFlags & GAMEINFO_WANTSIZE) { info_->gameSize = info_->GetGameSizeInBytes(); info_->saveDataSize = info_->GetSaveDataSizeInBytes(); info_->installDataSize = info_->GetInstallDataSizeInBytes(); } }
// This may run off-main-thread and we thus can't use the global // pspFileSystem (well, we could with synchronization but there might not // even be a game running). GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, bool wantBG) { auto iter = info_.find(gamePath); if (iter != info_.end()) { GameInfo *info = iter->second; if (!info->wantBG && wantBG) { // Need to start over. delete info; goto again; } if (info->iconTextureData.size()) { info->iconTexture = new Texture(); // TODO: We could actually do the PNG decoding as well on the async thread. // We'd have to split up Texture->LoadPNG though, creating some intermediate Image class maybe. if (info->iconTexture->LoadPNG((const u8 *)info->iconTextureData.data(), info->iconTextureData.size(), false)) { info->timeIconWasLoaded = time_now_d(); } info->iconTextureData.clear(); } if (info->pic0TextureData.size()) { info->pic0Texture = new Texture(); if (info->pic0Texture->LoadPNG((const u8 *)info->pic0TextureData.data(), info->pic0TextureData.size(), false)) { info->timePic0WasLoaded = time_now_d(); } info->pic0TextureData.clear(); } if (info->pic1TextureData.size()) { info->pic1Texture = new Texture(); if (info->pic1Texture->LoadPNG((const u8 *)info->pic1TextureData.data(), info->pic1TextureData.size(), false)) { info->timePic1WasLoaded = time_now_d(); } info->pic1TextureData.clear(); } iter->second->lastAccessedTime = time_now_d(); return iter->second; } again: // return info; // TODO: Everything below here should be asynchronous and run on a thread, // filling in the info as it goes. // A game can be either an UMD or a directory under ms0:/PSP/GAME . if (startsWith(gamePath, "ms0:/PSP/GAME")) { return 0; // TODO: The case of these extensions is not perfect. } else if (endsWith(gamePath, ".PBP") || endsWith(gamePath, ".elf")) { return 0; } else { SequentialHandleAllocator handles; // Let's assume it's an ISO. // TODO: This will currently read in the whole directory tree. Not really necessary for just a // few files. BlockDevice *bd = constructBlockDevice(gamePath.c_str()); if (!bd) return 0; // nothing to do here.. ISOFileSystem umd(&handles, bd, "/PSP_GAME"); GameInfo *info = new GameInfo(); info->wantBG = wantBG; // Alright, let's fetch the PARAM.SFO. std::string paramSFOcontents; if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents)) { lock_guard lock(info->lock); info->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size()); info->title = info->paramSFO.GetValueString("TITLE"); } ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info->iconTextureData); if (wantBG) { { lock_guard lock(info->lock); ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info->pic0TextureData); } { lock_guard lock(info->lock); ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info->pic1TextureData); } } info_[gamePath] = info; return info; } return 0; }
// We gather the game info before actually loading/booting the ISO // to determine if the emulator should enable extra memory and // double-sized texture coordinates. void InitMemoryForGameISO(FileLoader *fileLoader) { IFileSystem* umd2; if (!fileLoader->Exists()) { return; } bool actualIso = false; if (fileLoader->IsDirectory()) { umd2 = new VirtualDiscFileSystem(&pspFileSystem, fileLoader->Path()); } else { auto bd = constructBlockDevice(fileLoader); // Can't init anything without a block device... if (!bd) return; #ifdef _M_X64 if (g_Config.bCacheFullIsoInRam) { // The constructor destroys the original block device object after reading it. bd = new RAMBlockDevice(bd); } #endif umd2 = new ISOFileSystem(&pspFileSystem, bd); actualIso = true; } // Parse PARAM.SFO //pspFileSystem.Mount("host0:",umd2); IFileSystem *entireIso = 0; if (actualIso) { entireIso = new ISOBlockSystem(static_cast<ISOFileSystem *>(umd2)); } else { entireIso = umd2; } pspFileSystem.Mount("umd0:", entireIso); pspFileSystem.Mount("umd1:", entireIso); pspFileSystem.Mount("disc0:", umd2); pspFileSystem.Mount("umd:", entireIso); std::string gameID; std::string sfoPath("disc0:/PSP_GAME/PARAM.SFO"); PSPFileInfo fileInfo = pspFileSystem.GetFileInfo(sfoPath.c_str()); if (fileInfo.exists) { std::vector<u8> paramsfo; pspFileSystem.ReadEntireFile(sfoPath, paramsfo); if (g_paramSFO.ReadSFO(paramsfo)) { gameID = g_paramSFO.GetValueString("DISC_ID"); for (size_t i = 0; i < ARRAY_SIZE(g_HDRemasters); i++) { if(g_HDRemasters[i].gameID == gameID) { g_RemasterMode = true; Memory::g_MemorySize = g_HDRemasters[i].MemorySize; if(g_HDRemasters[i].DoubleTextureCoordinates) g_DoubleTextureCoordinates = true; break; } } DEBUG_LOG(LOADER, "HDRemaster mode is %s", g_RemasterMode? "true": "false"); } } }
virtual void run() { if (!info_->LoadFromPath(gamePath_)) return; std::string filename = gamePath_; { lock_guard lock(info_->lock); info_->fileType = Identify_File(info_->GetFileLoader()); } switch (info_->fileType) { case FILETYPE_PSP_PBP: case FILETYPE_PSP_PBP_DIRECTORY: { FileLoader *pbpLoader = info_->GetFileLoader(); std::unique_ptr<FileLoader> altLoader; if (info_->fileType == FILETYPE_PSP_PBP_DIRECTORY) { pbpLoader = ConstructFileLoader(pbpLoader->Path() + "/EBOOT.PBP"); altLoader.reset(pbpLoader); } PBPReader pbp(pbpLoader); if (!pbp.IsValid()) { if (pbp.IsELF()) { goto handleELF; } ERROR_LOG(LOADER, "invalid pbp %s\n", pbpLoader->Path().c_str()); return; } // First, PARAM.SFO. std::vector<u8> sfoData; if (pbp.GetSubFile(PBP_PARAM_SFO, &sfoData)) { lock_guard lock(info_->lock); info_->paramSFO.ReadSFO(sfoData); info_->ParseParamSFO(); } // Then, ICON0.PNG. if (pbp.GetSubFileSize(PBP_ICON0_PNG) > 0) { lock_guard lock(info_->lock); pbp.GetSubFileAsString(PBP_ICON0_PNG, &info_->iconTextureData); } else { // Read standard icon DEBUG_LOG(LOADER, "Loading unknown.png because a PBP was missing an icon"); ReadVFSToString("unknown.png", &info_->iconTextureData, &info_->lock); } info_->iconDataLoaded = true; if (info_->wantFlags & GAMEINFO_WANTBG) { if (pbp.GetSubFileSize(PBP_PIC0_PNG) > 0) { lock_guard lock(info_->lock); pbp.GetSubFileAsString(PBP_PIC0_PNG, &info_->pic0TextureData); info_->pic0DataLoaded = true; } if (pbp.GetSubFileSize(PBP_PIC1_PNG) > 0) { lock_guard lock(info_->lock); pbp.GetSubFileAsString(PBP_PIC1_PNG, &info_->pic1TextureData); info_->pic1DataLoaded = true; } } if (info_->wantFlags & GAMEINFO_WANTSND) { if (pbp.GetSubFileSize(PBP_SND0_AT3) > 0) { lock_guard lock(info_->lock); pbp.GetSubFileAsString(PBP_SND0_AT3, &info_->sndFileData); info_->sndDataLoaded = true; } } } break; case FILETYPE_PSP_ELF: handleELF: // An elf on its own has no usable information, no icons, no nothing. { lock_guard lock(info_->lock); info_->id = "ELF000000"; info_->id_version = "ELF000000_1.00"; info_->paramSFOLoaded = true; } // Read standard icon DEBUG_LOG(LOADER, "Loading unknown.png because there was an ELF"); ReadVFSToString("unknown.png", &info_->iconTextureData, &info_->lock); info_->iconDataLoaded = true; break; case FILETYPE_PSP_SAVEDATA_DIRECTORY: { SequentialHandleAllocator handles; VirtualDiscFileSystem umd(&handles, gamePath_.c_str()); // Alright, let's fetch the PARAM.SFO. std::string paramSFOcontents; if (ReadFileToString(&umd, "/PARAM.SFO", ¶mSFOcontents, 0)) { lock_guard lock(info_->lock); info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size()); info_->ParseParamSFO(); } ReadFileToString(&umd, "/ICON0.PNG", &info_->iconTextureData, &info_->lock); info_->iconDataLoaded = true; if (info_->wantFlags & GAMEINFO_WANTBG) { ReadFileToString(&umd, "/PIC1.PNG", &info_->pic1TextureData, &info_->lock); info_->pic1DataLoaded = true; } break; } case FILETYPE_PPSSPP_SAVESTATE: { info_->SetTitle(SaveState::GetTitle(gamePath_)); lock_guard guard(info_->lock); // Let's use the screenshot as an icon, too. std::string screenshotPath = ReplaceAll(gamePath_, ".ppst", ".jpg"); if (File::Exists(screenshotPath)) { if (readFileToString(false, screenshotPath.c_str(), info_->iconTextureData)) { info_->iconDataLoaded = true; } } break; } case FILETYPE_PSP_DISC_DIRECTORY: { info_->fileType = FILETYPE_PSP_ISO; SequentialHandleAllocator handles; VirtualDiscFileSystem umd(&handles, gamePath_.c_str()); // Alright, let's fetch the PARAM.SFO. std::string paramSFOcontents; if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, 0)) { lock_guard lock(info_->lock); info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size()); info_->ParseParamSFO(); } ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock); info_->iconDataLoaded = true; if (info_->wantFlags & GAMEINFO_WANTBG) { ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock); info_->pic0DataLoaded = true; ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); info_->pic1DataLoaded = true; } if (info_->wantFlags & GAMEINFO_WANTSND) { ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, &info_->lock); info_->pic1DataLoaded = true; } break; } case FILETYPE_PSP_ISO: case FILETYPE_PSP_ISO_NP: { info_->fileType = FILETYPE_PSP_ISO; SequentialHandleAllocator handles; // Let's assume it's an ISO. // TODO: This will currently read in the whole directory tree. Not really necessary for just a // few files. BlockDevice *bd = constructBlockDevice(info_->GetFileLoader()); if (!bd) return; // nothing to do here.. ISOFileSystem umd(&handles, bd, "/PSP_GAME"); // Alright, let's fetch the PARAM.SFO. std::string paramSFOcontents; if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, nullptr)) { lock_guard lock(info_->lock); info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size()); info_->ParseParamSFO(); if (info_->wantFlags & GAMEINFO_WANTBG) { ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock); info_->pic0DataLoaded = true; ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); info_->pic1DataLoaded = true; } if (info_->wantFlags & GAMEINFO_WANTSND) { ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, &info_->lock); info_->pic1DataLoaded = true; } } // Fall back to unknown icon if ISO is broken/is a homebrew ISO, override is allowed though if (!ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock)) { DEBUG_LOG(LOADER, "Loading unknown.png because no icon was found"); ReadVFSToString("unknown.png", &info_->iconTextureData, &info_->lock); } info_->iconDataLoaded = true; break; } case FILETYPE_ARCHIVE_ZIP: info_->paramSFOLoaded = true; { ReadVFSToString("zip.png", &info_->iconTextureData, &info_->lock); info_->iconDataLoaded = true; } break; case FILETYPE_ARCHIVE_RAR: info_->paramSFOLoaded = true; { ReadVFSToString("rargray.png", &info_->iconTextureData, &info_->lock); info_->iconDataLoaded = true; } break; case FILETYPE_ARCHIVE_7Z: info_->paramSFOLoaded = true; { ReadVFSToString("7z.png", &info_->iconTextureData, &info_->lock); info_->iconDataLoaded = true; } break; case FILETYPE_NORMAL_DIRECTORY: default: info_->paramSFOLoaded = true; break; } info_->hasConfig = g_Config.hasGameConfig(info_->id); if (info_->wantFlags & GAMEINFO_WANTSIZE) { lock_guard lock(info_->lock); info_->gameSize = info_->GetGameSizeInBytes(); info_->saveDataSize = info_->GetSaveDataSizeInBytes(); info_->installDataSize = info_->GetInstallDataSizeInBytes(); } info_->pending = false; info_->DisposeFileLoader(); }
virtual void run() { getFileInfo(gamePath_.c_str(), &info_->fileInfo); if (!info_->fileInfo.exists) return; std::string filename = gamePath_; info_->fileType = Identify_File(filename); switch (info_->fileType) { case FILETYPE_PSP_PBP: case FILETYPE_PSP_PBP_DIRECTORY: { std::string pbpFile = filename; if (info_->fileType == FILETYPE_PSP_PBP_DIRECTORY) pbpFile += "/EBOOT.PBP"; PBPReader pbp(pbpFile.c_str()); if (!pbp.IsValid()) return; // First, PARAM.SFO. size_t sfoSize; u8 *sfoData = pbp.GetSubFile(PBP_PARAM_SFO, &sfoSize); { lock_guard lock(info_->lock); info_->paramSFO.ReadSFO(sfoData, sfoSize); info_->title = info_->paramSFO.GetValueString("TITLE"); info_->id = info_->paramSFO.GetValueString("DISC_ID"); info_->id_version = info_->paramSFO.GetValueString("DISC_ID") + "_" + info_->paramSFO.GetValueString("DISC_VERSION"); info_->paramSFOLoaded = true; } delete [] sfoData; // Then, ICON0.PNG. { lock_guard lock(info_->lock); if (pbp.GetSubFileSize(PBP_ICON0_PNG) > 0) { pbp.GetSubFileAsString(PBP_ICON0_PNG, &info_->iconTextureData); } else { // Read standard icon size_t sz; INFO_LOG(HLE, "Loading unknown.png because a PBP was missing an icon"); uint8_t *contents = VFSReadFile("unknown.png", &sz); if (contents) { lock_guard lock(info_->lock); info_->iconTextureData = std::string((const char *)contents, sz); } delete [] contents; } } if (info_->wantBG) { if (pbp.GetSubFileSize(PBP_PIC1_PNG) > 0) { lock_guard lock(info_->lock); pbp.GetSubFileAsString(PBP_PIC1_PNG, &info_->pic1TextureData); } } } break; case FILETYPE_PSP_ELF: // An elf on its own has no usable information, no icons, no nothing. info_->title = getFilename(filename); info_->id = "ELF000000"; info_->id_version = "ELF000000_1.00"; info_->paramSFOLoaded = true; { // Read standard icon size_t sz; uint8_t *contents = VFSReadFile("unknown.png", &sz); INFO_LOG(HLE, "Loading unknown.png because there was an ELF"); if (contents) { lock_guard lock(info_->lock); info_->iconTextureData = std::string((const char *)contents, sz); } delete [] contents; } break; case FILETYPE_PSP_DISC_DIRECTORY: { info_->fileType = FILETYPE_PSP_ISO; SequentialHandleAllocator handles; VirtualDiscFileSystem umd(&handles,gamePath_.c_str()); // Alright, let's fetch the PARAM.SFO. std::string paramSFOcontents; if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, 0)) { lock_guard lock(info_->lock); info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size()); info_->title = info_->paramSFO.GetValueString("TITLE"); info_->id = info_->paramSFO.GetValueString("DISC_ID"); info_->id_version = info_->paramSFO.GetValueString("DISC_ID") + "_" + info_->paramSFO.GetValueString("DISC_VERSION"); info_->paramSFOLoaded = true; } ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock); if (info_->wantBG) { ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock); } ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); break; } case FILETYPE_PSP_ISO: case FILETYPE_PSP_ISO_NP: { info_->fileType = FILETYPE_PSP_ISO; SequentialHandleAllocator handles; // Let's assume it's an ISO. // TODO: This will currently read in the whole directory tree. Not really necessary for just a // few files. BlockDevice *bd = constructBlockDevice(gamePath_.c_str()); if (!bd) return; // nothing to do here.. ISOFileSystem umd(&handles, bd, "/PSP_GAME"); // Alright, let's fetch the PARAM.SFO. std::string paramSFOcontents; if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, 0)) { lock_guard lock(info_->lock); info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size()); info_->title = info_->paramSFO.GetValueString("TITLE"); info_->id = info_->paramSFO.GetValueString("DISC_ID"); info_->id_version = info_->paramSFO.GetValueString("DISC_ID") + "_" + info_->paramSFO.GetValueString("DISC_VERSION"); info_->paramSFOLoaded = true; } else { // Fall back to the filename for title if ISO is broken info_->title = gamePath_; } ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock); if (info_->wantBG) { ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock); } ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); break; } case FILETYPE_NORMAL_DIRECTORY: info_->title = gamePath_; break; default: { std::string fn, ext; SplitPath(gamePath_, 0, &fn, &ext); info_->title = fn + "." + ext; } break; } // probably only want these when we ask for the background image... // should maybe flip the flag to "onlyIcon" if (info_->wantBG) { info_->gameSize = info_->GetGameSizeInBytes(); info_->saveDataSize = info_->GetSaveDataSizeInBytes(); } }