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 1/5] 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"))); From ef386ac4c5ef40d88ad7064587aea22782288975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 18 Mar 2025 23:37:48 +0100 Subject: [PATCH 2/5] Add "GetFileInfoByHandle" function to (many) file systems --- Core/FileSystems/BlobFileSystem.cpp | 4 ++++ Core/FileSystems/BlobFileSystem.h | 1 + Core/FileSystems/DirectoryFileSystem.cpp | 10 ++++++++++ Core/FileSystems/DirectoryFileSystem.h | 2 ++ Core/FileSystems/FileSystem.h | 2 ++ Core/FileSystems/ISOFileSystem.cpp | 17 +++++++++++++++++ Core/FileSystems/ISOFileSystem.h | 4 ++++ Core/FileSystems/MetaFileSystem.cpp | 10 +++++++++- Core/FileSystems/MetaFileSystem.h | 5 +++-- Core/FileSystems/VirtualDiscFileSystem.cpp | 5 +++++ Core/FileSystems/VirtualDiscFileSystem.h | 1 + 11 files changed, 58 insertions(+), 3 deletions(-) diff --git a/Core/FileSystems/BlobFileSystem.cpp b/Core/FileSystems/BlobFileSystem.cpp index 5e18ad2911..0843ce440e 100644 --- a/Core/FileSystems/BlobFileSystem.cpp +++ b/Core/FileSystems/BlobFileSystem.cpp @@ -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(); diff --git a/Core/FileSystems/BlobFileSystem.h b/Core/FileSystems/BlobFileSystem.h index aa7dd076b7..256710d0e5 100644 --- a/Core/FileSystems/BlobFileSystem.h +++ b/Core/FileSystems/BlobFileSystem.h @@ -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; diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 3746f934e9..712627b6ca 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -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()) { diff --git a/Core/FileSystems/DirectoryFileSystem.h b/Core/FileSystems/DirectoryFileSystem.h index 556ba3c352..d3fb373781 100644 --- a/Core/FileSystems/DirectoryFileSystem.h +++ b/Core/FileSystems/DirectoryFileSystem.h @@ -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; diff --git a/Core/FileSystems/FileSystem.h b/Core/FileSystems/FileSystem.h index 10dcde76fb..18a267349b 100644 --- a/Core/FileSystems/FileSystem.h +++ b/Core/FileSystems/FileSystem.h @@ -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;} diff --git a/Core/FileSystems/ISOFileSystem.cpp b/Core/FileSystems/ISOFileSystem.cpp index 8ccd3e9091..48b3817f88 100644 --- a/Core/FileSystems/ISOFileSystem.cpp +++ b/Core/FileSystems/ISOFileSystem.cpp @@ -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 ISOFileSystem::GetDirListing(const std::string &path, bool *exists) { std::vector myVector; TreeEntry *entry = GetFromPath(path); diff --git a/Core/FileSystems/ISOFileSystem.h b/Core/FileSystems/ISOFileSystem.h index 8514ebdc5b..8afd29dffa 100644 --- a/Core/FileSystems/ISOFileSystem.h +++ b/Core/FileSystems/ISOFileSystem.h @@ -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); } diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 015e52197a..381cec9d83 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -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 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 guard(lock); + IFileSystem *sys = GetHandleOwner(handle); + if (sys) + return sys->GetFileInfoByHandle(handle); + return PSPFileInfo(); +} + std::vector MetaFileSystem::GetDirListing(const std::string &path, bool *exists) { std::lock_guard guard(lock); std::string of; diff --git a/Core/FileSystems/MetaFileSystem.h b/Core/FileSystems/MetaFileSystem.h index 41390e8ac2..4727804f5d 100644 --- a/Core/FileSystems/MetaFileSystem.h +++ b/Core/FileSystems/MetaFileSystem.h @@ -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); diff --git a/Core/FileSystems/VirtualDiscFileSystem.cpp b/Core/FileSystems/VirtualDiscFileSystem.cpp index ab95d4bb7c..af5a21e80c 100644 --- a/Core/FileSystems/VirtualDiscFileSystem.cpp +++ b/Core/FileSystems/VirtualDiscFileSystem.cpp @@ -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 diff --git a/Core/FileSystems/VirtualDiscFileSystem.h b/Core/FileSystems/VirtualDiscFileSystem.h index 74dad189f0..bfcbe3014d 100644 --- a/Core/FileSystems/VirtualDiscFileSystem.h +++ b/Core/FileSystems/VirtualDiscFileSystem.h @@ -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; From ef4e04c8a1228eebaa1e7fa6f2548337fbb5faa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 18 Mar 2025 23:39:07 +0100 Subject: [PATCH 3/5] Pass more filename information into elf loading. Allow dumping PRX into elf. --- Core/HLE/sceAtrac.cpp | 2 + Core/HLE/sceKernelModule.cpp | 74 ++++++++++++++++++++++-------------- Core/HLE/sceKernelModule.h | 3 +- Core/System.cpp | 7 +++- Core/System.h | 2 +- UI/ImDebugger/ImDebugger.cpp | 4 +- 6 files changed, 59 insertions(+), 33 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 0571a88587..5bd11e4a5d 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -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) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 0b8c732cf1..b27fd27da5 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1196,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()); @@ -1259,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; @@ -1329,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.iDumpFileTypes & (int)DumpFileType::EBOOT) { - // Copy the name to ensure it's null terminated. - char name[32]{}; - strncpy(name, head->modname, ARRAY_SIZE(head->modname)); - DumpFile(ptr, (u32)elfSize, name, DumpFileType::EBOOT); - } + // 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); } } @@ -1731,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) { @@ -1775,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; @@ -1894,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) { @@ -1947,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(); @@ -2104,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) { @@ -2525,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) { @@ -2540,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) { @@ -2604,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. diff --git a/Core/HLE/sceKernelModule.h b/Core/HLE/sceKernelModule.h index 14e0271158..bf9311995a 100644 --- a/Core/HLE/sceKernelModule.h +++ b/Core/HLE/sceKernelModule.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include #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(); diff --git a/Core/System.cpp b/Core/System.cpp index 4da70c0672..bd4b80222b 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -739,7 +739,10 @@ const char *DumpFileTypeToFileExtension(DumpFileType type) { } } -void DumpFile(const u8 *dataPtr, const u32 length, const char *name, DumpFileType type) { +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; @@ -768,7 +771,7 @@ void DumpFile(const u8 *dataPtr, const u32 length, const char *name, DumpFileTyp 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"); + 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; diff --git a/Core/System.h b/Core/System.h index 4c58e0ce80..a08309be54 100644 --- a/Core/System.h +++ b/Core/System.h @@ -113,4 +113,4 @@ inline CoreParameter &PSP_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); +void DumpFileIfEnabled(const u8 *dataPtr, const u32 length, const char *name, DumpFileType type); diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index fc051d7622..0d71fd29fd 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -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 &modules = __UtilityGetLoadedModules(); if (ImGui::BeginTable("modules", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersH)) { From c5ad1548bc9995ba0f5cf008fd4e5e4bddc100fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 19 Mar 2025 09:54:25 +0100 Subject: [PATCH 4/5] Add simple AT3 dumping (non-streaming only) --- Core/HLE/AtracCtx.cpp | 2 ++ Core/HLE/AtracCtx2.cpp | 12 ++++++++++-- UI/GameSettingsScreen.cpp | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Core/HLE/AtracCtx.cpp b/Core/HLE/AtracCtx.cpp index 856b3bd3d9..333cff0528 100644 --- a/Core/HLE/AtracCtx.cpp +++ b/Core/HLE/AtracCtx.cpp @@ -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. diff --git a/Core/HLE/AtracCtx2.cpp b/Core/HLE/AtracCtx2.cpp index 308edb0bc5..20436c3fc2 100644 --- a/Core/HLE/AtracCtx2.cpp +++ b/Core/HLE/AtracCtx2.cpp @@ -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" @@ -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; @@ -916,12 +924,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)++; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 3b548641c8..c2a97d526f 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1982,6 +1982,7 @@ void DeveloperToolsScreen::CreateViews() { 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"))); From da2b3fdd13edad2e561da9737d991d0e370ea86f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 19 Mar 2025 10:42:09 +0100 Subject: [PATCH 5/5] Warning fixes. Don't clamp readsize to reported file size. --- Core/HLE/AtracCtx.h | 2 +- Core/HLE/AtracCtx2.cpp | 6 ++---- Core/HLE/AtracCtx2.h | 2 +- Core/HLE/sceAtrac.h | 2 ++ Core/HW/Atrac3Standalone.cpp | 1 - 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Core/HLE/AtracCtx.h b/Core/HLE/AtracCtx.h index 0e5f2189b9..e776b15df7 100644 --- a/Core/HLE/AtracCtx.h +++ b/Core/HLE/AtracCtx.h @@ -258,7 +258,7 @@ public: u8 *BufferStart(); - AtracStatus BufferState() const { + AtracStatus BufferState() const override { return bufferState_; } diff --git a/Core/HLE/AtracCtx2.cpp b/Core/HLE/AtracCtx2.cpp index 20436c3fc2..6515186e40 100644 --- a/Core/HLE/AtracCtx2.cpp +++ b/Core/HLE/AtracCtx2.cpp @@ -131,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: @@ -838,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) { diff --git a/Core/HLE/AtracCtx2.h b/Core/HLE/AtracCtx2.h index e1a57cf9ce..7fd0e1eaf2 100644 --- a/Core/HLE/AtracCtx2.h +++ b/Core/HLE/AtracCtx2.h @@ -12,7 +12,7 @@ public: delete[] decodeTemp_; } - AtracStatus BufferState() const { + AtracStatus BufferState() const override { return context_->info.state; } diff --git a/Core/HLE/sceAtrac.h b/Core/HLE/sceAtrac.h index 2b0bed5035..7805e50de5 100644 --- a/Core/HLE/sceAtrac.h +++ b/Core/HLE/sceAtrac.h @@ -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. diff --git a/Core/HW/Atrac3Standalone.cpp b/Core/HW/Atrac3Standalone.cpp index 82a3f26cb8..b626326618 100644 --- a/Core/HW/Atrac3Standalone.cpp +++ b/Core/HW/Atrac3Standalone.cpp @@ -166,7 +166,6 @@ private: int channels_ = 0; int blockAlign_ = 0; - int srcPos_ = 0; float *buffers_[2]{}; bool codecOpen_ = false;