Add facility for __KernelGPUReplay to request to be called again

This commit is contained in:
Henrik Rydgård 2024-12-06 13:57:49 +01:00
parent b010f1bd48
commit ccd5bcaa45
4 changed files with 15 additions and 8 deletions

View file

@ -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', ""},
};

View file

@ -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)

View file

@ -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);

View file

@ -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))