Use a FileLoader for PBPs.

Improves consistency, caching, etc.
This commit is contained in:
Unknown W. Brackets 2015-12-24 10:40:25 -08:00
parent a53f0360f3
commit f3df6b307f
6 changed files with 45 additions and 59 deletions

View File

@ -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<u8> *out) {
@ -62,20 +57,15 @@ bool PBPReader::GetSubFile(PBPSubFile file, std::vector<u8> *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;
}

View File

@ -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<u8> *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_;

View File

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

View File

@ -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<u8> 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;

View File

@ -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<u8> sfoData;
if (pbp.GetSubFile(PBP_PARAM_SFO, &sfoData)) {

View File

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