mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 09:39:33 +01:00
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:
27 files changed
+254
-120
No files matched your search
+2
-1
@@ -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
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ static bool RealPath(const std::string ¤tDirectory, 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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -258,7 +258,7 @@ public:
|
||||
|
||||
u8 *BufferStart();
|
||||
|
||||
AtracStatus BufferState() const {
|
||||
AtracStatus BufferState() const override {
|
||||
return bufferState_;
|
||||
}
|
||||
|
||||
|
||||
+12
-6
@@ -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)++;
|
||||
|
||||
@@ -12,7 +12,7 @@ public:
|
||||
delete[] decodeTemp_;
|
||||
}
|
||||
|
||||
AtracStatus BufferState() const {
|
||||
AtracStatus BufferState() const override {
|
||||
return context_->info.state;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -166,7 +166,6 @@ private:
|
||||
int channels_ = 0;
|
||||
int blockAlign_ = 0;
|
||||
|
||||
int srcPos_ = 0;
|
||||
float *buffers_[2]{};
|
||||
|
||||
bool codecOpen_ = false;
|
||||
|
||||
+106
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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")));
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
Reference in new issue
Block a user