From f3df6b307f2eef0b8b58b2807d845e269b385d7b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 24 Dec 2015 10:40:25 -0800 Subject: [PATCH] Use a FileLoader for PBPs. Improves consistency, caching, etc. --- Core/ELF/PBPReader.cpp | 63 ++++++++++++++---------------------- Core/ELF/PBPReader.h | 10 +++--- Core/HLE/sceKernelModule.cpp | 7 ++-- Core/Loaders.cpp | 7 ++-- Core/PSPLoaders.cpp | 4 +-- UI/GameInfoCache.cpp | 13 +++++--- 6 files changed, 45 insertions(+), 59 deletions(-) diff --git a/Core/ELF/PBPReader.cpp b/Core/ELF/PBPReader.cpp index 9fed087f62..e14c1673b7 100644 --- a/Core/ELF/PBPReader.cpp +++ b/Core/ELF/PBPReader.cpp @@ -21,37 +21,32 @@ #include "Common/Log.h" #include "Common/FileUtil.h" +#include "Core/Loaders.h" #include "Core/ELF/PBPReader.h" -PBPReader::PBPReader(const char *filename) : header_(), isELF_(false) { - file_ = File::OpenCFile(filename, "rb"); - if (!file_) { - ERROR_LOG(LOADER, "Failed to open PBP file %s", filename); +PBPReader::PBPReader(FileLoader *fileLoader) : file_(nullptr), header_(), isELF_(false) { + if (!fileLoader->Exists()) { + ERROR_LOG(LOADER, "Failed to open PBP file %s", fileLoader->Path().c_str()); return; } - fseek(file_, 0, SEEK_END); - fileSize_ = ftell(file_); - fseek(file_, 0, SEEK_SET); - if (fread((char *)&header_, 1, sizeof(header_), file_) != sizeof(header_)) { - ERROR_LOG(LOADER, "PBP is too small to be valid: %s", filename); - fclose(file_); - file_ = nullptr; + fileSize_ = (size_t)fileLoader->FileSize(); + if (fileLoader->ReadAt(0, sizeof(header_), (u8 *)&header_) != sizeof(header_)) { + ERROR_LOG(LOADER, "PBP is too small to be valid: %s", fileLoader->Path().c_str()); return; } if (memcmp(header_.magic, "\0PBP", 4) != 0) { if (memcmp(header_.magic, "\nFLE", 4) != 0) { - DEBUG_LOG(LOADER, "%s: File actually an ELF, not a PBP", filename); + DEBUG_LOG(LOADER, "%s: File actually an ELF, not a PBP", fileLoader->Path().c_str()); isELF_ = true; } else { - ERROR_LOG(LOADER, "Magic number in %s indicated no PBP: %s", filename, header_.magic); + ERROR_LOG(LOADER, "Magic number in %s indicated no PBP: %s", fileLoader->Path().c_str(), header_.magic); } - fclose(file_); - file_ = nullptr; return; } DEBUG_LOG(LOADER, "Loading PBP, version = %08x", header_.version); + file_ = fileLoader; } bool PBPReader::GetSubFile(PBPSubFile file, std::vector *out) { @@ -62,20 +57,15 @@ bool PBPReader::GetSubFile(PBPSubFile file, std::vector *out) { const size_t expected = GetSubFileSize(file); const u32 off = header_.offsets[(int)file]; - if (fseek(file_, off, SEEK_SET) != 0) { - ERROR_LOG(LOADER, "PBP file offset invalid: %d", off); - return false; - } else { - out->resize(expected); - size_t bytes = fread((void *)out->data(), 1, expected, file_); - if (bytes != expected) { - ERROR_LOG(LOADER, "PBP file read truncated: %d -> %d", (int)expected, (int)bytes); - if (bytes < expected) { - out->resize(bytes); - } + out->resize(expected); + size_t bytes = file_->ReadAt(off, expected, (void *)out->data()); + if (bytes != expected) { + ERROR_LOG(LOADER, "PBP file read truncated: %d -> %d", (int)expected, (int)bytes); + if (bytes < expected) { + out->resize(bytes); } - return true; } + return true; } void PBPReader::GetSubFileAsString(PBPSubFile file, std::string *out) { @@ -88,21 +78,16 @@ void PBPReader::GetSubFileAsString(PBPSubFile file, std::string *out) { const u32 off = header_.offsets[(int)file]; out->resize(expected); - if (fseek(file_, off, SEEK_SET) != 0) { - ERROR_LOG(LOADER, "PBP file offset invalid: %d", off); - out->clear(); - } else { - size_t bytes = fread((void *)out->data(), 1, expected, file_); - if (bytes != expected) { - ERROR_LOG(LOADER, "PBP file read truncated: %d -> %d", (int)expected, (int)bytes); - if (bytes < expected) { - out->resize(bytes); - } + size_t bytes = file_->ReadAt(off, expected, (void *)out->data()); + if (bytes != expected) { + ERROR_LOG(LOADER, "PBP file read truncated: %d -> %d", (int)expected, (int)bytes); + if (bytes < expected) { + out->resize(bytes); } } } PBPReader::~PBPReader() { - if (file_) - fclose(file_); + // Does not take ownership. + file_ = nullptr; } diff --git a/Core/ELF/PBPReader.h b/Core/ELF/PBPReader.h index 2285af2ef0..de3d714cc3 100644 --- a/Core/ELF/PBPReader.h +++ b/Core/ELF/PBPReader.h @@ -37,13 +37,15 @@ struct PBPHeader { u32_le offsets[8]; }; +class FileLoader; + class PBPReader { public: - PBPReader(const char *filename); + PBPReader(FileLoader *fileLoader); ~PBPReader(); - bool IsValid() const { return file_ != 0; } - bool IsELF() const { return file_ == 0 && isELF_; } + bool IsValid() const { return file_ != nullptr; } + bool IsELF() const { return file_ == nullptr && isELF_; } bool GetSubFile(PBPSubFile file, std::vector *out); void GetSubFileAsString(PBPSubFile file, std::string *out); @@ -58,7 +60,7 @@ public: } private: - FILE *file_; + FileLoader *file_; size_t fileSize_; const PBPHeader header_; bool isELF_; diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 414d6109b7..a5fda0e8d6 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -29,6 +29,7 @@ #include "Core/HLE/ReplaceTables.h" #include "Core/Reporting.h" #include "Core/Host.h" +#include "Core/Loaders.h" #include "Core/MIPS/MIPS.h" #include "Core/MIPS/MIPSAnalyst.h" #include "Core/MIPS/MIPSCodeUtils.h" @@ -1368,11 +1369,11 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, bool fromT return module; } -static bool __KernelLoadPBP(const char *filename, std::string *error_string) +static bool __KernelLoadPBP(FileLoader *fileLoader, std::string *error_string) { - PBPReader pbp(filename); + PBPReader pbp(fileLoader); if (!pbp.IsValid()) { - ERROR_LOG(LOADER,"%s is not a valid homebrew PSP1.0 PBP",filename); + ERROR_LOG(LOADER, "%s is not a valid homebrew PSP1.0 PBP", fileLoader->Path().c_str()); *error_string = "Not a valid homebrew PBP"; return false; } diff --git a/Core/Loaders.cpp b/Core/Loaders.cpp index 517c76d75c..8544c92468 100644 --- a/Core/Loaders.cpp +++ b/Core/Loaders.cpp @@ -141,9 +141,7 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader) { 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. - // TODO: Change PBPReader to read FileLoader objects? - std::string filename = fileLoader->Path(); - PBPReader pbp(filename.c_str()); + PBPReader pbp(fileLoader); if (pbp.IsValid() && !pbp.IsELF()) { std::vector sfoData; if (pbp.GetSubFile(PBP_PARAM_SFO, &sfoData)) { @@ -166,11 +164,10 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader) { // 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(filename); + std::string path = File::GetDir(fileLoader->Path()); // 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; diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index 9460e17e98..2d2087aaa2 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -131,9 +131,7 @@ void InitMemoryForGamePBP(FileLoader *fileLoader) { return; } - // TODO: Change PBPReader to read FileLoader objects? - std::string filename = fileLoader->Path(); - PBPReader pbp(filename.c_str()); + PBPReader pbp(fileLoader); if (pbp.IsValid() && !pbp.IsELF()) { std::vector sfoData; if (pbp.GetSubFile(PBP_PARAM_SFO, &sfoData)) { diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 508dd8cc65..a823704fe1 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -322,16 +322,19 @@ public: case FILETYPE_PSP_PBP: case FILETYPE_PSP_PBP_DIRECTORY: { - std::string pbpFile = filename; - if (info_->fileType == FILETYPE_PSP_PBP_DIRECTORY) - pbpFile += "/EBOOT.PBP"; + FileLoader *pbpLoader = info_->GetFileLoader(); + std::unique_ptr altLoader; + if (info_->fileType == FILETYPE_PSP_PBP_DIRECTORY) { + pbpLoader = ConstructFileLoader(pbpLoader->Path() + "/EBOOT.PBP"); + altLoader.reset(pbpLoader); + } - PBPReader pbp(pbpFile.c_str()); + PBPReader pbp(pbpLoader); if (!pbp.IsValid()) { if (pbp.IsELF()) { goto handleELF; } - ERROR_LOG(LOADER, "invalid pbp %s\n", pbpFile.c_str()); + ERROR_LOG(LOADER, "invalid pbp %s\n", pbpLoader->Path().c_str()); return; }