Merge pull request #20129 from hrydgard/improved-file-dumping

Developer tools: Add settings for dumping decrypted ELFs and atrac files
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2025-03-19 11:15:21 +01:00
commit 978609adec
27 files changed
+254 -120

No files matched your search

+2 -1
View File
@@ -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),
+1 -1
View File
@@ -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
+7
View File
@@ -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,
+4
View File
@@ -101,6 +101,10 @@ PSPFileInfo BlobFileSystem::GetFileInfo(std::string filename) {
return info;
}
PSPFileInfo BlobFileSystem::GetFileInfoByHandle(u32 handle) {
return GetFileInfo("");
}
bool BlobFileSystem::OwnsHandle(u32 handle) {
auto entry = entries_.find(handle);
return entry != entries_.end();
+1
View File
@@ -43,6 +43,7 @@ public:
size_t WriteFile(u32 handle, const u8 *pointer, s64 size, int &usec) override;
size_t SeekFile(u32 handle, s32 position, FileMove type) override;
PSPFileInfo GetFileInfo(std::string filename) override;
PSPFileInfo GetFileInfoByHandle(u32 handle) override;
bool OwnsHandle(u32 handle) override;
int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override;
PSPDevType DevType(u32 handle) override;
+10
View File
@@ -727,6 +727,11 @@ PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) {
return ReplayApplyDiskFileInfo(x, CoreTiming::GetGlobalTimeUs());
}
PSPFileInfo DirectoryFileSystem::GetFileInfoByHandle(u32 handle) {
WARN_LOG(Log::FileSystem, "GetFileInfoByHandle not yet implemented for DirectoryFileSystem");
return PSPFileInfo();
}
#ifdef _WIN32
#define FILETIME_FROM_UNIX_EPOCH_US 11644473600000000ULL
@@ -1065,6 +1070,11 @@ PSPFileInfo VFSFileSystem::GetFileInfo(std::string filename) {
return x;
}
PSPFileInfo VFSFileSystem::GetFileInfoByHandle(u32 handle) {
return PSPFileInfo();
}
void VFSFileSystem::CloseFile(u32 handle) {
EntryMap::iterator iter = entries.find(handle);
if (iter != entries.end()) {
+2
View File
@@ -74,6 +74,7 @@ public:
size_t WriteFile(u32 handle, const u8 *pointer, s64 size, int &usec) override;
size_t SeekFile(u32 handle, s32 position, FileMove type) override;
PSPFileInfo GetFileInfo(std::string filename) override;
PSPFileInfo GetFileInfoByHandle(u32 handle) override;
bool OwnsHandle(u32 handle) override;
int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override;
PSPDevType DevType(u32 handle) override;
@@ -121,6 +122,7 @@ public:
size_t WriteFile(u32 handle, const u8 *pointer, s64 size, int &usec) override;
size_t SeekFile(u32 handle, s32 position, FileMove type) override;
PSPFileInfo GetFileInfo(std::string filename) override;
PSPFileInfo GetFileInfoByHandle(u32 handle) override;
bool OwnsHandle(u32 handle) override;
int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override;
PSPDevType DevType(u32 handle) override;
+2
View File
@@ -138,6 +138,7 @@ public:
virtual size_t WriteFile(u32 handle, const u8 *pointer, s64 size, int &usec) = 0;
virtual size_t SeekFile(u32 handle, s32 position, FileMove type) = 0;
virtual PSPFileInfo GetFileInfo(std::string filename) = 0;
virtual PSPFileInfo GetFileInfoByHandle(u32 handle) = 0; // Mainly used for debugging.
virtual bool OwnsHandle(u32 handle) = 0;
virtual bool MkDir(const std::string &dirname) = 0;
virtual bool RmDir(const std::string &dirname) = 0;
@@ -169,6 +170,7 @@ public:
size_t WriteFile(u32 handle, const u8 *pointer, s64 size, int &usec) override {return 0;}
size_t SeekFile(u32 handle, s32 position, FileMove type) override {return 0;}
PSPFileInfo GetFileInfo(std::string filename) override {PSPFileInfo f; return f;}
PSPFileInfo GetFileInfoByHandle(u32 handle) override {PSPFileInfo f; return f;}
bool OwnsHandle(u32 handle) override {return false;}
bool MkDir(const std::string &dirname) override {return false;}
bool RmDir(const std::string &dirname) override {return false;}
+17
View File
@@ -638,6 +638,23 @@ PSPFileInfo ISOFileSystem::GetFileInfo(std::string filename) {
return x;
}
PSPFileInfo ISOFileSystem::GetFileInfoByHandle(u32 handle) {
auto iter = entries.find(handle);
PSPFileInfo x;
if (iter != entries.end()) {
const TreeEntry *entry = iter->second.file;
x.name = entry->name;
// Strangely, it seems to be executable even for files.
x.access = 0555;
x.size = entry->size;
x.exists = true;
x.type = entry->isDirectory ? FILETYPE_DIRECTORY : FILETYPE_NORMAL;
x.isOnSectorSystem = true;
x.startSector = entry->startingPosition / 2048;
}
return x;
}
std::vector<PSPFileInfo> ISOFileSystem::GetDirListing(const std::string &path, bool *exists) {
std::vector<PSPFileInfo> myVector;
TreeEntry *entry = GetFromPath(path);
+4
View File
@@ -39,6 +39,7 @@ public:
size_t ReadFile(u32 handle, u8 *pointer, s64 size, int &usec) override;
size_t SeekFile(u32 handle, s32 position, FileMove type) override;
PSPFileInfo GetFileInfo(std::string filename) override;
PSPFileInfo GetFileInfoByHandle(u32 handle) override;
bool OwnsHandle(u32 handle) override;
int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override;
PSPDevType DevType(u32 handle) override;
@@ -136,6 +137,9 @@ public:
PSPFileInfo GetFileInfo(std::string filename) override {
return isoFileSystem_->GetFileInfo("");
}
PSPFileInfo GetFileInfoByHandle(u32 handle) override {
return isoFileSystem_->GetFileInfoByHandle(handle);
}
bool OwnsHandle(u32 handle) override {
return isoFileSystem_->OwnsHandle(handle);
}
+9 -1
View File
@@ -162,7 +162,7 @@ static bool RealPath(const std::string &currentDirectory, const std::string &inP
return true;
}
IFileSystem *MetaFileSystem::GetHandleOwner(u32 handle)
IFileSystem *MetaFileSystem::GetHandleOwner(u32 handle) const
{
std::lock_guard<std::recursive_mutex> guard(lock);
for (size_t i = 0; i < fileSystems.size(); i++)
@@ -368,6 +368,14 @@ PSPFileInfo MetaFileSystem::GetFileInfo(std::string filename)
}
}
PSPFileInfo MetaFileSystem::GetFileInfoByHandle(u32 handle) {
std::lock_guard<std::recursive_mutex> guard(lock);
IFileSystem *sys = GetHandleOwner(handle);
if (sys)
return sys->GetFileInfoByHandle(handle);
return PSPFileInfo();
}
std::vector<PSPFileInfo> MetaFileSystem::GetDirListing(const std::string &path, bool *exists) {
std::lock_guard<std::recursive_mutex> guard(lock);
std::string of;
+3 -2
View File
@@ -43,7 +43,7 @@ private:
currentDir_t currentDir;
std::string startingDirectory;
std::recursive_mutex lock; // must be recursive. TODO: fix that
mutable std::recursive_mutex lock; // must be recursive. TODO: fix that
// Assumes the lock is held
void Reset() {
@@ -73,7 +73,7 @@ public:
// The pointer returned from these are for temporary usage only. Do not store.
IFileSystem *GetSystem(const std::string &prefix);
IFileSystem *GetSystemFromFilename(const std::string &filename);
IFileSystem *GetHandleOwner(u32 handle);
IFileSystem *GetHandleOwner(u32 handle) const;
FileSystemFlags FlagsFromFilename(const std::string &filename) {
IFileSystem *sys = GetSystemFromFilename(filename);
return sys ? sys->Flags() : FileSystemFlags::NONE;
@@ -118,6 +118,7 @@ public:
size_t WriteFile(u32 handle, const u8 *pointer, s64 size, int &usec) override;
size_t SeekFile(u32 handle, s32 position, FileMove type) override;
PSPFileInfo GetFileInfo(std::string filename) override;
PSPFileInfo GetFileInfoByHandle(u32 handle) override;
bool OwnsHandle(u32 handle) override { return false; }
inline size_t GetSeekPos(u32 handle) {
return SeekFile(handle, 0, FILEMOVE_CURRENT);
@@ -641,6 +641,11 @@ PSPFileInfo VirtualDiscFileSystem::GetFileInfo(std::string filename) {
return x;
}
PSPFileInfo VirtualDiscFileSystem::GetFileInfoByHandle(u32 handle) {
WARN_LOG(Log::FileSystem, "GetFileInfoByHandle not yet implemented for VirtualDiscFileSystem");
return PSPFileInfo();
}
#ifdef _WIN32
#define FILETIME_FROM_UNIX_EPOCH_US 11644473600000000ULL
+1
View File
@@ -39,6 +39,7 @@ public:
size_t ReadFile(u32 handle, u8 *pointer, s64 size, int &usec) override;
void CloseFile(u32 handle) override;
PSPFileInfo GetFileInfo(std::string filename) override;
PSPFileInfo GetFileInfoByHandle(u32 handle) override;
bool OwnsHandle(u32 handle) override;
int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override;
PSPDevType DevType(u32 handle) override;
+2
View File
@@ -592,6 +592,8 @@ void AtracBase::CreateDecoder(int codecType, int bytesPerFrame, int channels) {
// First, init the standalone decoder.
if (codecType == PSP_MODE_AT_3) {
// TODO: This is maybe not entirely reliable? Mui Mui house in LocoRoco 2 fails. Although also fails
// when I override this, so maybe the issue is something different...
bool jointStereo = IsAtrac3StreamJointStereo(codecType, bytesPerFrame, channels);
// We don't pull this from the RIFF so that we can support OMA also.
+1 -1
View File
@@ -258,7 +258,7 @@ public:
u8 *BufferStart();
AtracStatus BufferState() const {
AtracStatus BufferState() const override {
return bufferState_;
}
+12 -6
View File
@@ -6,6 +6,7 @@
#include "Core/MemMapHelpers.h"
#include "Core/HLE/HLE.h"
#include "Core/HLE/FunctionWrappers.h"
#include "Core/System.h"
#include "Core/HLE/AtracCtx2.h"
#include "Core/HW/Atrac3Standalone.h"
@@ -130,7 +131,7 @@ int Atrac2::RemainingFrames() const {
// Handle the easy cases first.
switch (info.state) {
case 0:
case ATRAC_STATUS_UNINITIALIZED:
case ATRAC_STATUS_NO_DATA:
return 0;
case ATRAC_STATUS_ALL_DATA_LOADED:
@@ -807,6 +808,13 @@ int Atrac2::SetData(const Track &track, u32 bufferAddr, u32 readSize, u32 buffer
INFO_LOG(Log::ME, "Atrac2::SetData: outputChannels %d doesn't match track_.channels %d, decoder will expand.", outputChannels, track.channels);
}
if (readSize >= track.fileSize) {
INFO_LOG(Log::ME, "The full file was set directly - we can dump it.");
char filename[512];
snprintf(filename, sizeof(filename), "%s_%d%s", track.codecType == PSP_MODE_AT_3 ? "at3" : "at3plus", track.endSample, track.channels == 1 ? "_mono" : "");
DumpFileIfEnabled(Memory::GetPointer(bufferAddr), readSize, filename, DumpFileType::Atrac3);
}
CreateDecoder(track.codecType, track.bytesPerFrame, track.channels);
outputChannels_ = outputChannels;
@@ -830,9 +838,7 @@ int Atrac2::SetData(const Track &track, u32 bufferAddr, u32 readSize, u32 buffer
context_->codec.inBuf = bufferAddr;
if (readSize > track.fileSize) {
// This is seen in Tekken 6.
WARN_LOG(Log::ME, "readSize %d > track_.fileSize", readSize, track.fileSize);
readSize = track.fileSize;
INFO_LOG(Log::ME, "readSize (%d) > track_.fileSize (%d)", readSize, track.fileSize);
}
if (bufferSize >= track.fileSize) {
@@ -916,12 +922,12 @@ void Atrac2::WrapLastPacket() {
u32 Atrac2::SkipFrames(int *skipCount) {
SceAtracIdInfo &info = context_->info;
*skipCount = 0;
u32 temp;
u32 finishIgnored;
while (true) {
if (info.numSkipFrames == 0) {
return 0;
}
u32 retval = DecodeInternal(0, 0, &temp);
u32 retval = DecodeInternal(0, 0, &finishIgnored);
if (retval != 0) {
if (retval == SCE_ERROR_ATRAC_API_FAIL) {
(*skipCount)++;
+1 -1
View File
@@ -12,7 +12,7 @@ public:
delete[] decodeTemp_;
}
AtracStatus BufferState() const {
AtracStatus BufferState() const override {
return context_->info.state;
}
+2
View File
@@ -1075,6 +1075,8 @@ static int sceAtracSetAA3HalfwayBufferAndGetID(u32 buffer, u32 readSize, u32 buf
// These three are the external interface used by sceSas' AT3 integration.
// NOTE: There are special rules.
u32 AtracSasAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd) {
AtracBase *atrac = getAtrac(atracID);
if (!atrac)
+2
View File
@@ -34,6 +34,8 @@ constexpr u32 ATRAC3PLUS_MAX_SAMPLES = 0x800; // 2048
// The "state" member of SceAtracIdInfo.
enum AtracStatus : u8 {
ATRAC_STATUS_UNINITIALIZED = 0, // bad state
ATRAC_STATUS_NO_DATA = 1,
// The entire file is loaded into memory, no further file access needed.
+46 -103
View File
@@ -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.
@@ -1271,7 +1196,8 @@ static void parsePrxLibInfo(const u8* ptr, u32 headerSize) {
INFO_LOG(Log::sceModule, "~SCE module: Lib-PSP %s (SDK %s)", nameBuffer, versionBuffer);
}
static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAddress, bool fromTop, std::string *error_string, u32 *magic, u32 &error) {
// filename is only used for dumping/metadata.
static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAddress, bool fromTop, std::string *error_string, u32 *magic, std::string_view filename, u32 &error) {
PSPModule *module = new PSPModule();
kernelObjects.Create(module);
loadedModules.insert(module->GetUID());
@@ -1334,7 +1260,28 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
ret = head->psp_size - 0x150;
memcpy(newptr, in + 0x150, ret);
}
// decompress if required.
if (isGzip) {
auto temp = new u8[ret];
memcpy(temp, ptr, ret);
gzipDecompress((u8 *)ptr, maxElfSize, temp);
delete[] temp;
}
if (reportedModule) {
// Opportunity to dump the decrypted elf, even if we choose to fake it.
std::string elfFilename(filename);
if (elfFilename.empty()) {
// Use the name from the header.
elfFilename = head->modname;
}
DumpFileIfEnabled(ptr, head->psp_size, elfFilename.c_str(), DumpFileType::PRX);
if (isGzip) {
INFO_LOG(Log::sceModule, "gzip is enabled in 'reported' module");
}
// This should happen for all "kernel" modules.
*error_string = "Missing key";
delete [] newptr;
@@ -1404,22 +1351,11 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
// TODO: Is this right?
module->nm.bss_size = head->bss_size;
// decompress if required
if (isGzip)
{
auto temp = new u8[ret];
memcpy(temp, ptr, ret);
gzipDecompress((u8 *)ptr, maxElfSize, temp);
delete[] temp;
}
// If we've made it this far, it should be safe to dump.
if (g_Config.bDumpDecryptedEboot) {
// 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);
}
// Copy the name to ensure it's null terminated.
char name[32]{};
strncpy(name, head->modname, ARRAY_SIZE(head->modname));
DumpFileIfEnabled(ptr, (u32)elfSize, name, DumpFileType::EBOOT);
}
}
@@ -1806,14 +1742,15 @@ SceUID KernelLoadModule(const std::string &filename, std::string *error_string)
u32 error = SCE_KERNEL_ERROR_ILLEGAL_OBJECT;
u32 magic;
PSPModule *module = __KernelLoadELFFromPtr(&buffer[0], buffer.size(), 0, false, error_string, &magic, error);
PSPModule *module = __KernelLoadELFFromPtr(&buffer[0], buffer.size(), 0, false, error_string, &magic, filename, error);
if (module == nullptr)
return error;
return module->GetUID();
}
static PSPModule *__KernelLoadModule(u8 *fileptr, size_t fileSize, SceKernelLMOption *options, std::string *error_string) {
// filename is only used for dumping etc.
static PSPModule *__KernelLoadModule(u8 *fileptr, size_t fileSize, SceKernelLMOption *options, std::string_view filename, std::string *error_string) {
PSPModule *module = nullptr;
// Check for PBP
if (fileSize >= sizeof(PSP_Header) && memcmp(fileptr, "\0PBP", 4) == 0) {
@@ -1850,13 +1787,13 @@ static PSPModule *__KernelLoadModule(u8 *fileptr, size_t fileSize, SceKernelLMOp
}
u32 error;
module = __KernelLoadELFFromPtr(temp ? temp : fileptr + offsets[5], elfSize, PSP_GetDefaultLoadAddress(), false, error_string, &magic, error);
module = __KernelLoadELFFromPtr(temp ? temp : fileptr + offsets[5], elfSize, PSP_GetDefaultLoadAddress(), false, error_string, &magic, filename, error);
delete [] temp;
} else if (fileSize > sizeof(PSP_Header)) {
u32 error;
u32 magic = 0;
module = __KernelLoadELFFromPtr(fileptr, fileSize, PSP_GetDefaultLoadAddress(), false, error_string, &magic, error);
module = __KernelLoadELFFromPtr(fileptr, fileSize, PSP_GetDefaultLoadAddress(), false, error_string, &magic, filename, error);
} else {
*error_string = "ELF file truncated - can't load";
return nullptr;
@@ -1969,7 +1906,7 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str
}
size_t size = fileData.size();
PSPModule *module = __KernelLoadModule(fileData.data(), size, 0, error_string);
PSPModule *module = __KernelLoadModule(fileData.data(), size, 0, filename, error_string);
if (!module || module->isFake) {
if (module) {
@@ -2022,7 +1959,7 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str
return true;
}
bool __KernelLoadGEDump(const std::string &base_filename, std::string *error_string) {
bool __KernelLoadGEDump(std::string_view base_filename, std::string *error_string) {
__KernelLoadReset();
const u32 codeStartAddr = PSP_GetUserMemoryBase();
@@ -2179,7 +2116,7 @@ u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) {
u32 magic;
u32 error;
std::string error_string;
module = __KernelLoadELFFromPtr(fileData.data(), fileData.size(), 0, lmoption ? lmoption->position == PSP_SMEM_High : false, &error_string, &magic, error);
module = __KernelLoadELFFromPtr(fileData.data(), fileData.size(), 0, lmoption ? lmoption->position == PSP_SMEM_High : false, &error_string, &magic, name, error);
if (!module) {
if (magic == 0x46535000) {
@@ -2600,8 +2537,8 @@ u32 sceKernelFindModuleByName(const char *name)
return hleLogWarning(Log::sceModule, 0, "Module Not Found");
}
static u32 sceKernelLoadModuleByID(u32 id, u32 flags, u32 lmoptionPtr)
{
// The id in question here is a file handle.
static u32 sceKernelLoadModuleByID(u32 id, u32 flags, u32 lmoptionPtr) {
u32 error;
u32 handle = __IoGetFileHandleFromId(id, error);
if (handle == (u32)-1) {
@@ -2615,15 +2552,16 @@ static u32 sceKernelLoadModuleByID(u32 id, u32 flags, u32 lmoptionPtr)
lmoption = (SceKernelLMOption *)Memory::GetPointer(lmoptionPtr);
WARN_LOG_REPORT(Log::Loader, "sceKernelLoadModuleByID: unsupported options size=%08x, flags=%08x, pos=%d, access=%d, data=%d, text=%d", lmoption->size, lmoption->flags, lmoption->position, lmoption->access, lmoption->mpiddata, lmoption->mpidtext);
}
u32 pos = (u32) pspFileSystem.SeekFile(handle, 0, FILEMOVE_CURRENT);
u32 pos = (u32)pspFileSystem.SeekFile(handle, 0, FILEMOVE_CURRENT);
size_t size = pspFileSystem.SeekFile(handle, 0, FILEMOVE_END);
std::string error_string;
pspFileSystem.SeekFile(handle, pos, FILEMOVE_BEGIN);
PSPModule *module = nullptr;
u8 *temp = new u8[size - pos];
pspFileSystem.ReadFile(handle, temp, size - pos);
u32 magic;
module = __KernelLoadELFFromPtr(temp, size - pos, 0, lmoption ? lmoption->position == PSP_SMEM_High : false, &error_string, &magic, error);
module = __KernelLoadELFFromPtr(temp, size - pos, 0, lmoption ? lmoption->position == PSP_SMEM_High : false, &error_string, &magic, "", error);
delete [] temp;
if (!module) {
@@ -2679,7 +2617,12 @@ static SceUID sceKernelLoadModuleBufferUsbWlan(u32 size, u32 bufPtr, u32 flags,
PSPModule *module = nullptr;
u32 magic;
u32 error;
module = __KernelLoadELFFromPtr(Memory::GetPointer(bufPtr), size, 0, lmoption ? lmoption->position == PSP_SMEM_High : false, &error_string, &magic, error);
// For dumping only.
char fakeDebugFilename[512];
snprintf(fakeDebugFilename, sizeof(fakeDebugFilename), "moduleByPtr_%08x_%d", bufPtr, (int)size);
module = __KernelLoadELFFromPtr(Memory::GetPointer(bufPtr), size, 0, lmoption ? lmoption->position == PSP_SMEM_High : false, &error_string, &magic, fakeDebugFilename, error);
if (!module) {
// Some games try to load strange stuff as PARAM.SFO as modules and expect it to fail.
+2 -1
View File
@@ -18,6 +18,7 @@
#pragma once
#include <string>
#include <string_view>
#include <vector>
#include "Core/HLE/sceKernel.h"
@@ -42,7 +43,7 @@ void __KernelModuleShutdown();
u32 __KernelGetModuleGP(SceUID module);
bool KernelModuleIsKernelMode(SceUID module);
bool __KernelLoadGEDump(const std::string &base_filename, std::string *error_string);
bool __KernelLoadGEDump(std::string_view base_filename, std::string *error_string);
bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_string);
int __KernelGPUReplay();
void __KernelReturnFromModuleFunc();
-1
View File
@@ -166,7 +166,6 @@ private:
int channels_ = 0;
int blockAlign_ = 0;
int srcPos_ = 0;
float *buffers_[2]{};
bool codecOpen_ = false;
+106
View File
@@ -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,105 @@ 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 DumpFileIfEnabled(const u8 *dataPtr, const u32 length, const char *name, DumpFileType type) {
if (!(g_Config.iDumpFileTypes & (int)type)) {
return;
}
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);
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);
}
}
+4
View File
@@ -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 DumpFileIfEnabled(const u8 *dataPtr, const u32 length, const char *name, DumpFileType type);
+5 -1
View File
@@ -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,11 @@ 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")));
list->Add(new BitCheckBox(&g_Config.iDumpFileTypes, (int)DumpFileType::Atrac3, dev->T("Atrac3/3+")));
#if !PPSSPP_PLATFORM(ANDROID) && !PPSSPP_PLATFORM(IOS) && !PPSSPP_PLATFORM(SWITCH)
list->Add(new ItemHeader(dev->T("MIPSTracer")));
+3 -1
View File
@@ -1395,7 +1395,9 @@ static void DrawUtilityModules(ImConfig &cfg, ImControl &control) {
return;
}
ImGui::TextUnformatted("These are fake module representations loaded by sceUtilityLoadModule");
ImGui::TextUnformatted(
"These are fake module representations loaded by sceUtilityLoadModule\n"
"On a real PSP, these would be loaded from the BIOS.\n");
const std::map<int, u32> &modules = __UtilityGetLoadedModules();
if (ImGui::BeginTable("modules", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersH)) {