diff --git a/Core/FileSystems/BlobFileSystem.h b/Core/FileSystems/BlobFileSystem.h index c26f596dee..573fdacdd7 100644 --- a/Core/FileSystems/BlobFileSystem.h +++ b/Core/FileSystems/BlobFileSystem.h @@ -18,6 +18,8 @@ #pragma once // This is used for opening a debug file as a blob, and mounting it. +// Importantly, uses a fileLoader for all access, so http:// URLs are supported. +// As of writing, only used by GE dump replay. #include #include diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 575f9c0a83..f3d0005558 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1639,18 +1639,27 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str return true; } -bool __KernelLoadGEDump(std::string *error_string) { +bool __KernelLoadGEDump(const std::string &base_filename, std::string *error_string) { __KernelLoadReset(); mipsr4k.pc = PSP_GetUserMemoryBase(); const static u32_le runDumpCode[] = { - MIPS_MAKE_LUI(MIPS_REG_RA, mipsr4k.pc >> 16), + // Save the filename. + MIPS_MAKE_ORI(MIPS_REG_S0, MIPS_REG_A0, 0), + MIPS_MAKE_ORI(MIPS_REG_S1, MIPS_REG_A1, 0), + // Call the actual render. MIPS_MAKE_SYSCALL("FakeSysCalls", "__KernelGPUReplay"), + // Make sure we don't get out of sync. MIPS_MAKE_LUI(MIPS_REG_A0, 0), MIPS_MAKE_SYSCALL("sceGe_user", "sceGeDrawSync"), + // Set the return address after the entry which saved the filename. + MIPS_MAKE_LUI(MIPS_REG_RA, mipsr4k.pc >> 16), + MIPS_MAKE_ADDIU(MIPS_REG_RA, MIPS_REG_RA, 8), + // Wait for the next vblank to render again. MIPS_MAKE_JR_RA(), MIPS_MAKE_SYSCALL("sceDisplay", "sceDisplayWaitVblankStart"), + // This never gets reached, just here to be safe. MIPS_MAKE_BREAK(0), }; @@ -1666,7 +1675,7 @@ bool __KernelLoadGEDump(std::string *error_string) { module->nm.entry_addr = mipsr4k.pc; module->nm.gp_value = -1; - SceUID threadID = __KernelSetupRootThread(module->GetUID(), 0, nullptr, 0x20, 0x1000, 0); + SceUID threadID = __KernelSetupRootThread(module->GetUID(), (int)base_filename.size(), base_filename.data(), 0x20, 0x1000, 0); __KernelSetThreadRA(threadID, NID_MODULERETURN); __KernelStartIdleThreads(module->GetUID()); @@ -1674,7 +1683,16 @@ bool __KernelLoadGEDump(std::string *error_string) { } void __KernelGPUReplay() { - if (!GPURecord::RunMountedReplay()) { + // Special ABI: s0 and s1 are the "args". Not null terminated. + const char *filenamep = Memory::GetCharPointer(currentMIPS->r[MIPS_REG_S1]); + if (!filenamep) { + ERROR_LOG(SYSTEM, "Failed to load dump filename"); + Core_Stop(); + return; + } + + std::string filename(filenamep, currentMIPS->r[MIPS_REG_S0]); + if (!GPURecord::RunMountedReplay(filename)) { Core_Stop(); } } diff --git a/Core/HLE/sceKernelModule.h b/Core/HLE/sceKernelModule.h index 1c58a02548..232c71d23f 100644 --- a/Core/HLE/sceKernelModule.h +++ b/Core/HLE/sceKernelModule.h @@ -39,7 +39,7 @@ void __KernelModuleDoState(PointerWrap &p); void __KernelModuleShutdown(); u32 __KernelGetModuleGP(SceUID module); -bool __KernelLoadGEDump(std::string *error_string); +bool __KernelLoadGEDump(const std::string &base_filename, std::string *error_string); bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_string); void __KernelGPUReplay(); void __KernelReturnFromModuleFunc(); diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index 193fe52b72..3dd9b76492 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -361,6 +361,6 @@ bool Load_PSP_GE_Dump(FileLoader *fileLoader, std::string *error_string) { BlobFileSystem *umd = new BlobFileSystem(&pspFileSystem, fileLoader, "data.ppdmp"); pspFileSystem.Mount("disc0:", umd); - __KernelLoadGEDump(error_string); + __KernelLoadGEDump("disc0:/data.ppdmp", error_string); return true; } diff --git a/GPU/Debugger/Record.cpp b/GPU/Debugger/Record.cpp index 7360b017cb..5e4d250a07 100644 --- a/GPU/Debugger/Record.cpp +++ b/GPU/Debugger/Record.cpp @@ -991,10 +991,10 @@ static bool ReadCompressed(u32 fp, void *dest, size_t sz) { return real_size == sz; } -bool RunMountedReplay() { +bool RunMountedReplay(const std::string &filename) { _assert_msg_(SYSTEM, !active && !nextFrame, "Cannot run replay while recording."); - u32 fp = pspFileSystem.OpenFile("disc0:/data.ppdmp", FILEACCESS_READ); + u32 fp = pspFileSystem.OpenFile(filename, FILEACCESS_READ); u8 header[8]{}; int version = 0; pspFileSystem.ReadFile(fp, header, sizeof(header)); diff --git a/GPU/Debugger/Record.h b/GPU/Debugger/Record.h index f3ba37a605..3cfc995a80 100644 --- a/GPU/Debugger/Record.h +++ b/GPU/Debugger/Record.h @@ -17,6 +17,7 @@ #pragma once +#include #include "Common/CommonTypes.h" namespace GPURecord { @@ -30,6 +31,6 @@ void NotifyMemset(u32 dest, int v, u32 sz); void NotifyUpload(u32 dest, u32 sz); void NotifyFrame(); -bool RunMountedReplay(); +bool RunMountedReplay(const std::string &filename); };