Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use MEMSIZE SFO param to detect 64MB homebrew #8296

Merged
merged 8 commits into from
Dec 24, 2015
70 changes: 26 additions & 44 deletions Core/ELF/PBPReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,64 +21,51 @@

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

u8 *PBPReader::GetSubFile(PBPSubFile file, size_t *outSize) {
bool PBPReader::GetSubFile(PBPSubFile file, std::vector<u8> *out) {
if (!file_) {
*outSize = 0;
return new u8[0];
return false;
}

const size_t expected = GetSubFileSize(file);
const u32 off = header_.offsets[(int)file];

*outSize = expected;
if (fseek(file_, off, SEEK_SET) != 0) {
ERROR_LOG(LOADER, "PBP file offset invalid: %d", off);
*outSize = 0;
return new u8[0];
} else {
u8 *buffer = new u8[expected];
size_t bytes = fread(buffer, 1, expected, file_);
if (bytes != expected) {
ERROR_LOG(LOADER, "PBP file read truncated: %d -> %d", (int)expected, (int)bytes);
if (bytes < expected) {
*outSize = bytes;
}
out->resize(expected);
size_t bytes = file_->ReadAt(off, expected, &(*out)[0]);
if (bytes != expected) {
ERROR_LOG(LOADER, "PBP file read truncated: %d -> %d", (int)expected, (int)bytes);
if (bytes < expected) {
out->resize(bytes);
}
return buffer;
}
return true;
}

void PBPReader::GetSubFileAsString(PBPSubFile file, std::string *out) {
Expand All @@ -91,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;
}
13 changes: 7 additions & 6 deletions Core/ELF/PBPReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,17 @@ 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_; }

// Delete the returned buffer with delete [].
u8 *GetSubFile(PBPSubFile file, size_t *outSize);
bool GetSubFile(PBPSubFile file, std::vector<u8> *out);
void GetSubFileAsString(PBPSubFile file, std::string *out);

size_t GetSubFileSize(PBPSubFile file) {
Expand All @@ -59,7 +60,7 @@ class PBPReader {
}

private:
FILE *file_;
FileLoader *file_;
size_t fileSize_;
const PBPHeader header_;
bool isELF_;
Expand Down
8 changes: 8 additions & 0 deletions Core/ELF/ParamSFO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ u8* ParamSFOData::GetValueData(std::string key, unsigned int *size)
return it->second.u_value;
}

std::vector<std::string> ParamSFOData::GetKeys() {
std::vector<std::string> result;
for (const auto &pair : values) {
result.push_back(pair.first);
}
return result;
}

// I'm so sorry Ced but this is highly endian unsafe :(
bool ParamSFOData::ReadSFO(const u8 *paramsfo, size_t size)
{
Expand Down
2 changes: 2 additions & 0 deletions Core/ELF/ParamSFO.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class ParamSFOData
std::string GetValueString(std::string key);
u8* GetValueData(std::string key, unsigned int *size);

std::vector<std::string> GetKeys();

bool ReadSFO(const u8 *paramsfo, size_t size);
bool WriteSFO(u8 **paramsfo, size_t *size);

Expand Down
17 changes: 9 additions & 8 deletions Core/HLE/sceKernelModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1368,26 +1369,26 @@ 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;
}

size_t elfSize;
u8 *elfData = pbp.GetSubFile(PBP_EXECUTABLE_PSP, &elfSize);
std::vector<u8> elfData;
if (!pbp.GetSubFile(PBP_EXECUTABLE_PSP, &elfData)) {
return false;
}
u32 magic;
u32 error;
Module *module = __KernelLoadELFFromPtr(elfData, PSP_GetDefaultLoadAddress(), false, error_string, &magic, error);
Module *module = __KernelLoadELFFromPtr(&elfData[0], PSP_GetDefaultLoadAddress(), false, error_string, &magic, error);
if (!module) {
delete [] elfData;
return false;
}
mipsr4k.pc = module->nm.entry_addr;
delete [] elfData;
return true;
}

Expand Down
31 changes: 11 additions & 20 deletions Core/Loaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,24 +141,16 @@ 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());
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;
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;
}
}

Expand All @@ -172,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;
Expand Down
16 changes: 14 additions & 2 deletions Core/MemMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,15 +340,16 @@ void Init()

void DoState(PointerWrap &p)
{
auto s = p.Section("Memory", 1, 2);
auto s = p.Section("Memory", 1, 3);
if (!s)
return;

if (s < 2) {
if (!g_RemasterMode)
g_MemorySize = RAM_NORMAL_SIZE;
g_PSPModel = PSP_MODEL_FAT;
} else {
} else if (s == 2) {
// In version 2, we determine memory size based on PSP model.
u32 oldMemorySize = g_MemorySize;
p.Do(g_PSPModel);
p.DoMarker("PSPModel");
Expand All @@ -359,6 +360,17 @@ void DoState(PointerWrap &p)
Init();
}
}
} else {
// In version 3, we started just saving the memory size directly.
// It's no longer based strictly on the PSP model.
u32 oldMemorySize = g_MemorySize;
p.Do(g_PSPModel);
p.DoMarker("PSPModel");
p.Do(g_MemorySize);
if (oldMemorySize != g_MemorySize) {
Shutdown();
Init();
}
}

p.DoArray(GetPointer(PSP_GetKernelMemoryBase()), g_MemorySize);
Expand Down
Loading