From 939b26475de3f452478429246d7ca3c4c7addf17 Mon Sep 17 00:00:00 2001 From: LunaMoo Date: Fri, 26 May 2017 23:15:04 +0200 Subject: [PATCH] Fix a bunch of emu features for Homebrew by better identification. --- Core/ELF/ParamSFO.cpp | 59 ++++++++++++++++++++------------ Core/ELF/ParamSFO.h | 1 + Core/PSPLoaders.cpp | 11 ++++++ Core/System.cpp | 5 +-- Core/TextureReplacer.cpp | 5 ++- GPU/Common/FramebufferCommon.cpp | 5 ++- GPU/GLES/GPU_GLES.cpp | 5 ++- UI/GameInfoCache.cpp | 17 +++++++-- UI/GameInfoCache.h | 2 +- UI/GameScreen.cpp | 2 ++ UI/GameSettingsScreen.cpp | 3 ++ UI/NativeApp.cpp | 2 +- UI/PauseScreen.cpp | 6 ++++ 13 files changed, 91 insertions(+), 32 deletions(-) diff --git a/Core/ELF/ParamSFO.cpp b/Core/ELF/ParamSFO.cpp index 7d9387a97d..7db7ca0e2d 100644 --- a/Core/ELF/ParamSFO.cpp +++ b/Core/ELF/ParamSFO.cpp @@ -20,7 +20,9 @@ #include "Common/CommonTypes.h" #include "Common/Log.h" +#include "Common/StringUtils.h" #include "Core/ELF/ParamSFO.h" +#include "Core/Core.h" struct Header { @@ -40,42 +42,36 @@ struct IndexTable u32 data_table_offset; /* Offset of the param_data from start of data_table */ }; -void ParamSFOData::SetValue(std::string key, unsigned int value, int max_size) -{ +void ParamSFOData::SetValue(std::string key, unsigned int value, int max_size) { values[key].type = VT_INT; values[key].i_value = value; values[key].max_size = max_size; } -void ParamSFOData::SetValue(std::string key, std::string value, int max_size) -{ +void ParamSFOData::SetValue(std::string key, std::string value, int max_size) { values[key].type = VT_UTF8; values[key].s_value = value; values[key].max_size = max_size; } -void ParamSFOData::SetValue(std::string key, const u8* value, unsigned int size, int max_size) -{ +void ParamSFOData::SetValue(std::string key, const u8* value, unsigned int size, int max_size) { values[key].type = VT_UTF8_SPE; values[key].SetData(value,size); values[key].max_size = max_size; } -int ParamSFOData::GetValueInt(std::string key) -{ +int ParamSFOData::GetValueInt(std::string key) { std::map::iterator it = values.find(key); if(it == values.end() || it->second.type != VT_INT) return 0; return it->second.i_value; } -std::string ParamSFOData::GetValueString(std::string key) -{ +std::string ParamSFOData::GetValueString(std::string key) { std::map::iterator it = values.find(key); if(it == values.end() || (it->second.type != VT_UTF8)) return ""; return it->second.s_value; } -u8* ParamSFOData::GetValueData(std::string key, unsigned int *size) -{ +u8* ParamSFOData::GetValueData(std::string key, unsigned int *size) { std::map::iterator it = values.find(key); if(it == values.end() || (it->second.type != VT_UTF8_SPE)) return 0; @@ -95,8 +91,7 @@ std::vector ParamSFOData::GetKeys() { } // I'm so sorry Ced but this is highly endian unsafe :( -bool ParamSFOData::ReadSFO(const u8 *paramsfo, size_t size) -{ +bool ParamSFOData::ReadSFO(const u8 *paramsfo, size_t size) { if (size < sizeof(Header)) return false; const Header *header = (const Header *)paramsfo; @@ -145,8 +140,7 @@ bool ParamSFOData::ReadSFO(const u8 *paramsfo, size_t size) return true; } -int ParamSFOData::GetDataOffset(const u8 *paramsfo, std::string dataName) -{ +int ParamSFOData::GetDataOffset(const u8 *paramsfo, std::string dataName) { const Header *header = (const Header *)paramsfo; if (header->magic != 0x46535000) return -1; @@ -170,8 +164,7 @@ int ParamSFOData::GetDataOffset(const u8 *paramsfo, std::string dataName) return -1; } -bool ParamSFOData::WriteSFO(u8 **paramsfo, size_t *size) -{ +bool ParamSFOData::WriteSFO(u8 **paramsfo, size_t *size) { size_t total_size = 0; size_t key_size = 0; size_t data_size = 0; @@ -256,13 +249,11 @@ bool ParamSFOData::WriteSFO(u8 **paramsfo, size_t *size) return true; } -void ParamSFOData::Clear() -{ +void ParamSFOData::Clear() { values.clear(); } -void ParamSFOData::ValueData::SetData(const u8* data, int size) -{ +void ParamSFOData::ValueData::SetData(const u8* data, int size) { if(u_value) { delete[] u_value; @@ -276,3 +267,27 @@ void ParamSFOData::ValueData::SetData(const u8* data, int size) u_size = size; } +std::string ParamSFOData::GenerateFakeID(std::string filename) { + // Generates fake gameID for homebrew based on it's folder name. + // Should probably not be a part of ParamSFO, but it'll be called in same places. + std::string file = PSP_CoreParameter().fileToStart; + if (filename != "") + file = filename; + + std::size_t lslash = file.find_last_of("/"); + file = file.substr(lslash + 1); + + int sumOfAllLetters = 0; + for (char &c : file) { + sumOfAllLetters += c; + c = toupper(c); + } + + if (file.size() < 4) { + file += "HOME"; + } + file = file.substr(0, 4); + + std::string fakeID = file + StringFromFormat("%05i", sumOfAllLetters); + return fakeID; +} diff --git a/Core/ELF/ParamSFO.h b/Core/ELF/ParamSFO.h index 956ebbab14..ead49feff8 100644 --- a/Core/ELF/ParamSFO.h +++ b/Core/ELF/ParamSFO.h @@ -35,6 +35,7 @@ public: u8* GetValueData(std::string key, unsigned int *size); std::vector GetKeys(); + std::string GenerateFakeID(std::string filename = ""); bool ReadSFO(const u8 *paramsfo, size_t size); bool WriteSFO(u8 **paramsfo, size_t *size); diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index 0a7fd9b16c..096ada69b7 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -322,5 +322,16 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) { pspFileSystem.Mount("umd0:", fs); std::string finalName = ms_path + file + extension; + + std::string homebrewName = PSP_CoreParameter().fileToStart; + std::size_t lslash = homebrewName.find_last_of("/"); + homebrewName = homebrewName.substr(lslash +1); + std::string madeUpID = g_paramSFO.GenerateFakeID(); + + char title[1024]; + sprintf(title, "%s : %s", madeUpID.c_str(), homebrewName.c_str()); + INFO_LOG(LOADER, "%s", title); + host->SetWindowTitle(title); + return __KernelLoadExec(finalName.c_str(), 0, error_string); } diff --git a/Core/System.cpp b/Core/System.cpp index bca2a58ea8..89a5151edc 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -243,9 +243,10 @@ void CPU_Init() { // 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); + if (discID.empty()) { + discID = g_paramSFO.GenerateFakeID(); } + coreParameter.compat.Load(discID); Memory::Init(); mipsr4k.Reset(); diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index ed9b2c10fb..2889d9b9d7 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -48,8 +48,11 @@ void TextureReplacer::Init() { void TextureReplacer::NotifyConfigChanged() { gameID_ = g_paramSFO.GetValueString("DISC_ID"); + if (gameID_.empty()) { + gameID_ = g_paramSFO.GenerateFakeID(); + } - enabled_ = !gameID_.empty() && (g_Config.bReplaceTextures || g_Config.bSaveNewTextures); + enabled_ = g_Config.bReplaceTextures || g_Config.bSaveNewTextures; if (enabled_) { basePath_ = GetSysDirectory(DIRECTORY_TEXTURES) + gameID_ + "/"; diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 70b3e7ab09..91e1675ee9 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -133,7 +133,10 @@ FramebufferManagerCommon::~FramebufferManagerCommon() { } void FramebufferManagerCommon::Init() { - const std::string gameId = g_paramSFO.GetValueString("DISC_ID"); + std::string gameId = g_paramSFO.GetValueString("DISC_ID"); + if (gameId.empty()) { + gameId = g_paramSFO.GenerateFakeID(); + } BeginFrame(); } diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index b56c3789c6..1f40a0299b 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -169,9 +169,12 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) // Load shader cache. std::string discID = g_paramSFO.GetValueString("DISC_ID"); + if (discID.empty()) { + discID = g_paramSFO.GenerateFakeID(); + } if (discID.size()) { File::CreateFullPath(GetSysDirectory(DIRECTORY_APP_CACHE)); - shaderCachePath_ = GetSysDirectory(DIRECTORY_APP_CACHE) + "/" + g_paramSFO.GetValueString("DISC_ID") + ".glshadercache"; + shaderCachePath_ = GetSysDirectory(DIRECTORY_APP_CACHE) + "/" + discID + ".glshadercache"; shaderManagerGL_->LoadAndPrecompile(shaderCachePath_); } diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index af3672a3a8..ec8f803060 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -262,7 +262,7 @@ bool GameInfo::DeleteAllSaveData() { void GameInfo::ParseParamSFO() { title = paramSFO.GetValueString("TITLE"); id = paramSFO.GetValueString("DISC_ID"); - id_version = paramSFO.GetValueString("DISC_ID") + "_" + paramSFO.GetValueString("DISC_VERSION"); + id_version = id + "_" + paramSFO.GetValueString("DISC_VERSION"); disc_total = paramSFO.GetValueInt("DISC_TOTAL"); disc_number = paramSFO.GetValueInt("DISC_NUMBER"); // region = paramSFO.GetValueInt("REGION"); // Always seems to be 32768? @@ -405,6 +405,15 @@ public: std::lock_guard lock(info_->lock); info_->paramSFO.ReadSFO(sfoData); info_->ParseParamSFO(); + + // Assuming PSP_PBP_DIRECTORY without ID or with disc_total < 1 in GAME dir must be homebrew + if ((info_->id.empty() || info_->disc_total < 1) + && gamePath_.find("/PSP/GAME/") != std::string::npos + && info_->fileType == IdentifiedFileType::PSP_PBP_DIRECTORY) { + info_->id = g_paramSFO.GenerateFakeID(gamePath_); + info_->id_version = info_->id + "_1.00"; + info_->region = GAMEREGION_MAX + 1; // Homebrew + } } // Then, ICON0.PNG. @@ -444,8 +453,10 @@ handleELF: // An elf on its own has no usable information, no icons, no nothing. { std::lock_guard lock(info_->lock); - info_->id = "ELF000000"; - info_->id_version = "ELF000000_1.00"; + info_->id = g_paramSFO.GenerateFakeID(gamePath_); + info_->id_version = info_->id + "_1.00"; + info_->region = GAMEREGION_MAX + 1; // Homebrew + info_->paramSFOLoaded = true; } diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index 14e290a040..f664a1d621 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -1,4 +1,4 @@ -// Copyright (c) 2013- PPSSPP Project. +// Copyright (c) 2013- PPSSPP Project. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index 37729c24ed..e0e73c76fe 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -236,6 +236,8 @@ void GameScreen::update() { "Asia" }; tvRegion_->SetText(ga->T(regionNames[info->region])); + } else if (info->region > GAMEREGION_MAX){ + tvRegion_->SetText(ga->T("Homebrew")); } if (!info->id.empty()) { diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 15902fe0b9..a2fd7f7ebe 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1331,6 +1331,9 @@ UI::EventReturn DeveloperToolsScreen::OnLoadLanguageIni(UI::EventParams &e) { UI::EventReturn DeveloperToolsScreen::OnOpenTexturesIniFile(UI::EventParams &e) { std::string gameID = g_paramSFO.GetValueString("DISC_ID"); + if (gameID.empty()) { + gameID = g_paramSFO.GenerateFakeID(); + } std::string texturesDirectory = GetSysDirectory(DIRECTORY_TEXTURES) + gameID + "/"; bool enabled_ = !gameID.empty(); if (enabled_) { diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 6eaee626bf..429ee2cd3e 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -715,7 +715,7 @@ void TakeScreenshot() { std::string gameId = g_paramSFO.GetValueString("DISC_ID"); if (gameId.empty()) { - gameId = "MENU"; + gameId = g_paramSFO.GenerateFakeID(); } char filename[2048]; diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index f0630fb3df..ff2e5035c3 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -321,6 +321,9 @@ void GamePauseScreen::CreateViews() { continueChoice->OnClick.Handle(this, &UIScreen::OnBack); std::string gameId = g_paramSFO.GetValueString("DISC_ID"); + if (gameId.empty()) { + gameId = g_paramSFO.GenerateFakeID(); + } if (g_Config.hasGameConfig(gameId)) { rightColumnItems->Add(new Choice(pa->T("Game Settings")))->OnClick.Handle(this, &GamePauseScreen::OnGameSettings); rightColumnItems->Add(new Choice(pa->T("Delete Game Config")))->OnClick.Handle(this, &GamePauseScreen::OnDeleteConfig); @@ -422,6 +425,9 @@ void GamePauseScreen::CallbackDeleteConfig(bool yes) UI::EventReturn GamePauseScreen::OnCreateConfig(UI::EventParams &e) { std::string gameId = g_paramSFO.GetValueString("DISC_ID"); + if (gameId.empty()) { + gameId = g_paramSFO.GenerateFakeID(); + } g_Config.createGameConfig(gameId); g_Config.changeGameSpecific(gameId); g_Config.saveGameConfig(gameId);