diff --git a/Core/HLE/HLETables.cpp b/Core/HLE/HLETables.cpp index 5fe9411f67..c0877ea20e 100644 --- a/Core/HLE/HLETables.cpp +++ b/Core/HLE/HLETables.cpp @@ -97,7 +97,7 @@ const HLEFunction FakeSysCalls[] = { {NID_EXTENDRETURN, __KernelReturnFromExtendStack, "__KernelReturnFromExtendStack", 'x', ""}, {NID_MODULERETURN, __KernelReturnFromModuleFunc, "__KernelReturnFromModuleFunc", 'x', ""}, {NID_IDLE, __KernelIdle, "_sceKernelIdle", 'x', ""}, - {NID_GPUREPLAY, __KernelGPUReplay, "__KernelGPUReplay", 'x', ""}, + {NID_GPUREPLAY, &WrapI_V<__KernelGPUReplay>, "__KernelGPUReplay", 'x', ""}, {NID_HLECALLRETURN, HLEReturnFromMipsCall, "HLEReturnFromMipsCall", 'x', ""}, }; diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 40fb6a26df..dd510c79fb 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1984,21 +1984,26 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str bool __KernelLoadGEDump(const std::string &base_filename, std::string *error_string) { __KernelLoadReset(); - mipsr4k.pc = PSP_GetUserMemoryBase(); + constexpr u32 codeStart = PSP_GetUserMemoryBase(); + mipsr4k.pc = codeStart; const static u32_le runDumpCode[] = { // 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. + // Call the actual render. Jump here to start over. MIPS_MAKE_SYSCALL("FakeSysCalls", "__KernelGPUReplay"), + MIPS_MAKE_NOP(), + // Re-run immediately if requested by the return value from __KernelGPUReplay + MIPS_MAKE_BNEZ(codeStart + 4 * 4, codeStart + 8, MIPS_REG_V0), + MIPS_MAKE_NOP(), // Make sure we don't get out of sync. MIPS_MAKE_LUI(MIPS_REG_A0, 0), MIPS_MAKE_SYSCALL("sceGe_user", "sceGeDrawSync"), // Wait for the next vblank to render again. - MIPS_MAKE_J(mipsr4k.pc + 8), + MIPS_MAKE_J(codeStart + 8), MIPS_MAKE_SYSCALL("sceDisplay", "sceDisplayWaitVblankStart"), - // This never gets reached, just here to be safe. + // This never gets reached, just here to be "safe". MIPS_MAKE_BREAK(0), }; @@ -2021,13 +2026,13 @@ bool __KernelLoadGEDump(const std::string &base_filename, std::string *error_str return true; } -void __KernelGPUReplay() { +int __KernelGPUReplay() { // 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(Log::G3D, "Failed to load dump filename"); Core_Stop(); - return; + return 0; } std::string filename(filenamep, currentMIPS->r[MIPS_REG_S0]); @@ -2042,6 +2047,7 @@ void __KernelGPUReplay() { System_SendDebugScreenshot(std::string((const char *)&topaddr[0], linesize * 272), 272); Core_Stop(); } + return 0; } int sceKernelLoadExec(const char *filename, u32 paramPtr) diff --git a/Core/HLE/sceKernelModule.h b/Core/HLE/sceKernelModule.h index a227153477..4e76a3f008 100644 --- a/Core/HLE/sceKernelModule.h +++ b/Core/HLE/sceKernelModule.h @@ -43,7 +43,7 @@ u32 __KernelGetModuleGP(SceUID module); bool KernelModuleIsKernelMode(SceUID module); bool __KernelLoadGEDump(const std::string &base_filename, std::string *error_string); bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_string); -void __KernelGPUReplay(); +int __KernelGPUReplay(); void __KernelReturnFromModuleFunc(); SceUID KernelLoadModule(const std::string &filename, std::string *error_string); int KernelStartModule(SceUID moduleId, u32 argsize, u32 argAddr, u32 returnValueAddr, SceKernelSMOption *smoption, bool *needsWait); diff --git a/Core/MIPS/MIPSCodeUtils.h b/Core/MIPS/MIPSCodeUtils.h index 17789f72c7..9665f49886 100644 --- a/Core/MIPS/MIPSCodeUtils.h +++ b/Core/MIPS/MIPSCodeUtils.h @@ -29,6 +29,7 @@ #define MIPS_MAKE_JAL(addr) (0x0C000000 | ((addr)>>2)) #define MIPS_MAKE_JR_RA() (0x03e00008) #define MIPS_MAKE_NOP() (0) +#define MIPS_MAKE_BNEZ(pc, addr, rs) (0x14000000 | (rs << 21) | (((int)(addr - (pc + 4)) >> 2) & 0xFFFF)) #define MIPS_MAKE_ADDIU(dreg, sreg, immval) ((9 << 26) | ((dreg) << 16) | ((sreg) << 21) | (immval)) #define MIPS_MAKE_LUI(reg, immval) (0x3c000000 | ((reg) << 16) | (immval))