From c4241e283a4bec147b1399dbd66058fae9a9fb7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 18 Mar 2025 19:24:45 +0100 Subject: [PATCH] Prepare to generalize file dumping --- Core/Config.cpp | 3 +- Core/Config.h | 2 +- Core/ConfigValues.h | 7 +++ Core/HLE/sceKernelModule.cpp | 79 +-------------------------- Core/System.cpp | 103 +++++++++++++++++++++++++++++++++++ Core/System.h | 4 ++ UI/GameSettingsScreen.cpp | 5 +- 7 files changed, 123 insertions(+), 80 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 5c33f4cca7..d5d73a3b5e 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -329,7 +329,8 @@ static const ConfigSetting generalSettings[] = { ConfigSetting("PauseExitsEmulator", &g_Config.bPauseExitsEmulator, false, CfgFlag::DONT_SAVE), ConfigSetting("PauseMenuExitsEmulator", &g_Config.bPauseMenuExitsEmulator, false, CfgFlag::DONT_SAVE), - ConfigSetting("DumpDecryptedEboots", &g_Config.bDumpDecryptedEboot, false, CfgFlag::PER_GAME), + ConfigSetting("DumpFileTypes", &g_Config.iDumpFileTypes, 0, CfgFlag::PER_GAME), + ConfigSetting("FullscreenOnDoubleclick", &g_Config.bFullscreenOnDoubleclick, true, CfgFlag::DONT_SAVE), ConfigSetting("ShowMenuBar", &g_Config.bShowMenuBar, true, CfgFlag::DEFAULT), diff --git a/Core/Config.h b/Core/Config.h index 844c124d20..8e26bb3fae 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -86,7 +86,7 @@ public: bool bDumpAudio; bool bSaveLoadResetsAVdumping; bool bEnableLogging; - bool bDumpDecryptedEboot; + int iDumpFileTypes; // DumpFileType bitflag enum bool bFullscreenOnDoubleclick; // These four are Win UI only diff --git a/Core/ConfigValues.h b/Core/ConfigValues.h index 5d6a410ad1..065ad069f1 100644 --- a/Core/ConfigValues.h +++ b/Core/ConfigValues.h @@ -165,6 +165,13 @@ enum class ShowStatusFlags { BATTERY_PERCENT = 1 << 3, }; +enum class DumpFileType { + EBOOT = (1 << 0), + PRX = (1 << 1), + Atrac3 = (1 << 2), +}; +ENUM_CLASS_BITOPS(DumpFileType); + // for iTiltInputType enum TiltTypes { TILT_NULL = 0, diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index a5bc0afc58..0b8c732cf1 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -915,81 +915,6 @@ void PSPModule::Cleanup() { } } -static void SaveDecryptedEbootToStorageMedia(const u8 *decryptedEbootDataPtr, const u32 length, const char *name) { - if (!decryptedEbootDataPtr) { - ERROR_LOG(Log::sceModule, "Error saving decrypted EBOOT.BIN: invalid pointer"); - return; - } - - if (length == 0) { - ERROR_LOG(Log::sceModule, "Error saving decrypted EBOOT.BIN: invalid length"); - return; - } - - const std::string filenameToDumpTo = StringFromFormat("%s_%s.BIN", g_paramSFO.GetDiscID().c_str(), name); - const Path dumpDirectory = GetSysDirectory(DIRECTORY_DUMP); - const Path fullPath = dumpDirectory / filenameToDumpTo; - - auto s = GetI18NCategory(I18NCat::SYSTEM); - - // If the file already exists, don't dump it again. - if (File::Exists(fullPath)) { - INFO_LOG(Log::sceModule, "Decrypted EBOOT.BIN already exists for this game, skipping dump."); - - char *path = new char[strlen(fullPath.c_str()) + 1]; - strcpy(path, fullPath.c_str()); - - g_OSD.Show(OSDType::MESSAGE_INFO, s->T("Dump Decrypted Eboot"), fullPath.ToVisualString(), 5.0f, "decr"); - if (System_GetPropertyBool(SYSPROP_CAN_SHOW_FILE)) { - g_OSD.SetClickCallback("decr", [](bool clicked, void *userdata) { - char *path = (char *)userdata; - if (clicked) { - System_ShowFileInFolder(Path(path)); - } else { - delete[] path; - } - }, path); - } - return; - } - - // Make sure the dump directory exists before continuing. - if (!File::Exists(dumpDirectory)) { - if (!File::CreateDir(dumpDirectory)) { - ERROR_LOG(Log::sceModule, "Unable to create directory for EBOOT dumping, aborting."); - return; - } - } - - FILE *decryptedEbootFile = File::OpenCFile(fullPath, "wb"); - if (!decryptedEbootFile) { - ERROR_LOG(Log::sceModule, "Unable to write decrypted EBOOT."); - return; - } - - const size_t lengthToWrite = length; - - fwrite(decryptedEbootDataPtr, sizeof(u8), lengthToWrite, decryptedEbootFile); - fclose(decryptedEbootFile); - INFO_LOG(Log::sceModule, "Successfully wrote decrypted EBOOT to %s", fullPath.c_str()); - - char *path = new char[strlen(fullPath.c_str()) + 1]; - strcpy(path, fullPath.c_str()); - - // Re-suing the translation string here. - g_OSD.Show(OSDType::MESSAGE_SUCCESS, s->T("Dump Decrypted Eboot"), fullPath.ToVisualString(), 5.0f, "decr"); - if (System_GetPropertyBool(SYSPROP_CAN_SHOW_FILE)) { - g_OSD.SetClickCallback("decr", [](bool clicked, void *userdata) { - char *path = (char *)userdata; - if (clicked) { - System_ShowFileInFolder(Path(path)); - } else { - delete[] path; - } - }, path); - } -} - static bool IsHLEVersionedModule(const char *name) { // TODO: Only some of these are currently known to be versioned. // Potentially only sceMpeg_library matters. @@ -1414,11 +1339,11 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load } // If we've made it this far, it should be safe to dump. - if (g_Config.bDumpDecryptedEboot) { + if (g_Config.iDumpFileTypes & (int)DumpFileType::EBOOT) { // Copy the name to ensure it's null terminated. char name[32]{}; strncpy(name, head->modname, ARRAY_SIZE(head->modname)); - SaveDecryptedEbootToStorageMedia(ptr, (u32)elfSize, name); + DumpFile(ptr, (u32)elfSize, name, DumpFileType::EBOOT); } } } diff --git a/Core/System.cpp b/Core/System.cpp index dceaf3323d..4da70c0672 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -33,6 +33,8 @@ #include "Common/System/System.h" #include "Common/System/Request.h" +#include "Common/System/OSD.h" +#include "Common/Data/Text/I18n.h" #include "Common/File/Path.h" #include "Common/File/FileUtil.h" #include "Common/File/DirListing.h" @@ -61,6 +63,8 @@ #include "Core/PSPLoaders.h" #include "Core/ELF/ParamSFO.h" #include "Core/SaveState.h" +#include "Common/File/FileUtil.h" +#include "Common/StringUtils.h" #include "Common/ExceptionHandlerSetup.h" #include "GPU/GPUCommon.h" #include "GPU/Debugger/Playback.h" @@ -716,3 +720,102 @@ const char *CoreStateToString(CoreState state) { default: return "N/A"; } } + +const char *DumpFileTypeToString(DumpFileType type) { + switch (type) { + case DumpFileType::EBOOT: return "EBOOT"; + case DumpFileType::PRX: return "PRX"; + case DumpFileType::Atrac3: return "AT3"; + default: return "N/A"; + } +} + +const char *DumpFileTypeToFileExtension(DumpFileType type) { + switch (type) { + case DumpFileType::EBOOT: return ".BIN"; + case DumpFileType::PRX: return ".prx"; + case DumpFileType::Atrac3: return ".at3"; + default: return "N/A"; + } +} + +void DumpFile(const u8 *dataPtr, const u32 length, const char *name, DumpFileType type) { + if (!dataPtr) { + ERROR_LOG(Log::System, "Error dumping %s: invalid pointer", DumpFileTypeToString(DumpFileType::EBOOT)); + return; + } + if (length == 0) { + ERROR_LOG(Log::System, "Error dumping %s: invalid length", DumpFileTypeToString(DumpFileType::EBOOT)); + return; + } + + const char *extension = DumpFileTypeToFileExtension(type); + const std::string filenameToDumpTo = StringFromFormat("%s_%s%s", g_paramSFO.GetDiscID().c_str(), name, extension); + const Path dumpDirectory = GetSysDirectory(DIRECTORY_DUMP); + const Path fullPath = dumpDirectory / filenameToDumpTo; + + auto s = GetI18NCategory(I18NCat::SYSTEM); + + std::string_view titleStr = "Dump Decrypted Eboot"; + if (type != DumpFileType::EBOOT) { + titleStr = s->T(DumpFileTypeToString(type)); + } + + // If the file already exists, don't dump it again. + if (File::Exists(fullPath)) { + INFO_LOG(Log::sceModule, "%s already exists for this game, skipping dump.", filenameToDumpTo.c_str()); + + char *path = new char[strlen(fullPath.c_str()) + 1]; + strcpy(path, fullPath.c_str()); + + g_OSD.Show(OSDType::MESSAGE_INFO, titleStr, fullPath.ToVisualString(), 5.0f, "file_dumped"); + if (System_GetPropertyBool(SYSPROP_CAN_SHOW_FILE)) { + g_OSD.SetClickCallback("file_dumped", [](bool clicked, void *userdata) { + char *path = (char *)userdata; + if (clicked) { + System_ShowFileInFolder(Path(path)); + } else { + delete[] path; + } + }, path); + } + return; + } + + // Make sure the dump directory exists before continuing. + if (!File::Exists(dumpDirectory)) { + if (!File::CreateDir(dumpDirectory)) { + ERROR_LOG(Log::sceModule, "Unable to create directory for EBOOT dumping, aborting."); + return; + } + } + + FILE *file = File::OpenCFile(fullPath, "wb"); + if (!file) { + ERROR_LOG(Log::sceModule, "Unable to write decrypted EBOOT."); + return; + } + + const size_t lengthToWrite = length; + + fwrite(dataPtr, sizeof(u8), lengthToWrite, file); + fclose(file); + + INFO_LOG(Log::sceModule, "Successfully wrote %s to %s", DumpFileTypeToString(type), fullPath.c_str()); + + char *path = new char[strlen(fullPath.c_str()) + 1]; + strcpy(path, fullPath.c_str()); + + // Re-suing the translation string here. + g_OSD.Show(OSDType::MESSAGE_SUCCESS, titleStr, fullPath.ToVisualString(), 5.0f, "decr"); + if (System_GetPropertyBool(SYSPROP_CAN_SHOW_FILE)) { + g_OSD.SetClickCallback("decr", [](bool clicked, void *userdata) { + char *path = (char *)userdata; + if (clicked) { + System_ShowFileInFolder(Path(path)); + } else { + delete[] path; + } + }, path); + } +} diff --git a/Core/System.h b/Core/System.h index 4b584223cd..4c58e0ce80 100644 --- a/Core/System.h +++ b/Core/System.h @@ -20,6 +20,7 @@ #include "Common/CommonTypes.h" #include "Common/File/Path.h" #include "Core/CoreParameter.h" +#include "Core/ConfigValues.h" class MetaFileSystem; class ParamSFOData; @@ -110,3 +111,6 @@ inline CoreParameter &PSP_CoreParameter() { extern CoreParameter g_CoreParameter; return g_CoreParameter; } + +// Centralized place for dumping useful files, also takes care of checking for dupes and creating a clickable UI popup. +void DumpFile(const u8 *dataPtr, const u32 length, const char *name, DumpFileType type); diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 9b5dfc0f27..3b548641c8 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1894,7 +1894,6 @@ void DeveloperToolsScreen::CreateViews() { list->Add(new Choice(dev->T("JIT debug tools")))->OnClick.Handle(this, &DeveloperToolsScreen::OnJitDebugTools); list->Add(new CheckBox(&g_Config.bShowDeveloperMenu, dev->T("Show Developer Menu"))); - list->Add(new CheckBox(&g_Config.bDumpDecryptedEboot, dev->T("Dump Decrypted Eboot", "Dump Decrypted EBOOT.BIN (If Encrypted) When Booting Game"))); #if !PPSSPP_PLATFORM(UWP) Choice *cpuTests = new Choice(dev->T("Run CPU Tests")); @@ -1980,6 +1979,10 @@ void DeveloperToolsScreen::CreateViews() { auto displayRefreshRate = list->Add(new PopupSliderChoice(&g_Config.iDisplayRefreshRate, 60, 1000, 60, dev->T("Display refresh rate"), 1, screenManager())); displayRefreshRate->SetFormat(si->T("%d Hz")); + list->Add(new ItemHeader("Dump file types")); + list->Add(new BitCheckBox(&g_Config.iDumpFileTypes, (int)DumpFileType::EBOOT, dev->T("Dump Decrypted Eboot", "Dump Decrypted EBOOT.BIN (If Encrypted) When Booting Game"))); + list->Add(new BitCheckBox(&g_Config.iDumpFileTypes, (int)DumpFileType::PRX, dev->T("PRX"))); + #if !PPSSPP_PLATFORM(ANDROID) && !PPSSPP_PLATFORM(IOS) && !PPSSPP_PLATFORM(SWITCH) list->Add(new ItemHeader(dev->T("MIPSTracer")));