From 82beb726fcfb28955943c9498c2f263f9590837d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Jun 2017 14:46:36 -0700 Subject: [PATCH] GE Debugger: Record init state and display buf. Some things are now visible, but still drawing wrong... --- Core/HLE/sceDisplay.cpp | 42 +++++++++++++++++-------------- Core/HLE/sceDisplay.h | 7 ++++-- Core/HLE/sceIo.cpp | 4 ++- GPU/Debugger/Record.cpp | 55 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 22 deletions(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 19ccacf1f3..9f271ee2de 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -825,13 +825,29 @@ static u32 sceDisplaySetMode(int displayMode, int displayWidth, int displayHeigh return DisplayWaitForVblanks("display mode", 1); } -// Some games (GTA) never call this during gameplay, so bad place to put a framerate counter. -static u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync) { +void __DisplaySetFramebuf(u32 topaddr, int linesize, int pixelFormat, int sync) { FrameBufferState fbstate = {0}; fbstate.topaddr = topaddr; - fbstate.fmt = (GEBufferFormat)pixelformat; + fbstate.fmt = (GEBufferFormat)pixelFormat; fbstate.stride = linesize; + if (sync == PSP_DISPLAY_SETBUF_IMMEDIATE) { + // Write immediately to the current framebuffer parameters + framebuf = fbstate; + gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.stride, framebuf.fmt); + } else { + // Delay the write until vblank + latchedFramebuf = fbstate; + framebufIsLatched = true; + + // If we update the format or stride, this affects the current framebuf immediately. + framebuf.fmt = latchedFramebuf.fmt; + framebuf.stride = latchedFramebuf.stride; + } +} + +// Some games (GTA) never call this during gameplay, so bad place to put a framerate counter. +u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync) { if (sync != PSP_DISPLAY_SETBUF_IMMEDIATE && sync != PSP_DISPLAY_SETBUF_NEXTFRAME) { return hleLogError(SCEDISPLAY, SCE_KERNEL_ERROR_INVALID_MODE, "invalid sync mode"); } @@ -849,7 +865,7 @@ static u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int } if (sync == PSP_DISPLAY_SETBUF_IMMEDIATE) { - if (fbstate.fmt != latchedFramebuf.fmt || fbstate.stride != latchedFramebuf.stride) { + if ((GEBufferFormat)pixelformat != latchedFramebuf.fmt || linesize != latchedFramebuf.stride) { return hleReportError(SCEDISPLAY, SCE_KERNEL_ERROR_INVALID_MODE, "must change latched framebuf first"); } } @@ -882,19 +898,7 @@ static u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int lastFlipCycles = CoreTiming::GetTicks(); } - if (sync == PSP_DISPLAY_SETBUF_IMMEDIATE) { - // Write immediately to the current framebuffer parameters - framebuf = fbstate; - gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.stride, framebuf.fmt); - } else { - // Delay the write until vblank - latchedFramebuf = fbstate; - framebufIsLatched = true; - - // If we update the format or stride, this affects the current framebuf immediately. - framebuf.fmt = latchedFramebuf.fmt; - framebuf.stride = latchedFramebuf.stride; - } + __DisplaySetFramebuf(topaddr, linesize, pixelformat, sync); if (delayCycles > 0) { // Okay, the game is going at too high a frame rate. God of War and Fat Princess both do this. @@ -910,10 +914,10 @@ static u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int } } -bool __DisplayGetFramebuf(u8 **topaddr, u32 *linesize, u32 *pixelFormat, int latchedMode) { +bool __DisplayGetFramebuf(PSPPointer *topaddr, u32 *linesize, u32 *pixelFormat, int latchedMode) { const FrameBufferState &fbState = latchedMode == PSP_DISPLAY_SETBUF_NEXTFRAME ? latchedFramebuf : framebuf; if (topaddr != nullptr) - *topaddr = Memory::GetPointer(fbState.topaddr); + (*topaddr).ptr = fbState.topaddr; if (linesize != nullptr) *linesize = fbState.stride; if (pixelFormat != nullptr) diff --git a/Core/HLE/sceDisplay.h b/Core/HLE/sceDisplay.h index caaeafa72d..db6cbcd1e1 100644 --- a/Core/HLE/sceDisplay.h +++ b/Core/HLE/sceDisplay.h @@ -17,6 +17,8 @@ #pragma once +#include "Core/MemMap.h" + void __DisplayInit(); void __DisplayDoState(PointerWrap &p); void __DisplayShutdown(); @@ -27,7 +29,8 @@ void Register_sceDisplay(); bool __DisplayFrameDone(); // Get information about the current framebuffer. -bool __DisplayGetFramebuf(u8 **topaddr, u32 *linesize, u32 *pixelFormat, int mode); +bool __DisplayGetFramebuf(PSPPointer *topaddr, u32 *linesize, u32 *pixelFormat, int mode); +void __DisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync); typedef void (*VblankCallback)(); // Listen for vblank events. Only register during init. @@ -44,4 +47,4 @@ int __DisplayGetFlipCount(); // Call this when resuming to avoid a small speedup burst void __DisplaySetWasPaused(); -void Register_sceDisplay_driver(); \ No newline at end of file +void Register_sceDisplay_driver(); diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 26f83d1ac7..ead6f487a5 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -1825,7 +1825,8 @@ static u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 o return 0; case 0x20: // EMULATOR_DEVCTL__EMIT_SCREENSHOT - u8 *topaddr; + { + PSPPointer topaddr; u32 linesize, pixelFormat; __DisplayGetFramebuf(&topaddr, &linesize, &pixelFormat, 0); @@ -1833,6 +1834,7 @@ static u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 o host->SendDebugScreenshot(topaddr, linesize, 272); return 0; } + } ERROR_LOG(SCEIO, "sceIoDevCtl: UNKNOWN PARAMETERS"); diff --git a/GPU/Debugger/Record.cpp b/GPU/Debugger/Record.cpp index 915c81c988..8584fff906 100644 --- a/GPU/Debugger/Record.cpp +++ b/GPU/Debugger/Record.cpp @@ -47,6 +47,7 @@ static bool active = false; static bool nextFrame = false; enum class CommandType : u8 { + INIT = 0, REGISTERS = 1, VERTICES = 2, INDICES = 3, @@ -55,6 +56,7 @@ enum class CommandType : u8 { MEMSET = 6, MEMCPYDEST = 7, MEMCPYDATA = 8, + DISPLAY = 9, TEXTURE0 = 0x10, TEXTURE1 = 0x11, @@ -115,8 +117,35 @@ static std::string GenRecordingFilename() { return StringFromFormat("%s_%04d.ppdmp", prefix.c_str(), 9999); } +static void EmitDisplayBuf() { + struct DisplayBufData { + PSPPointer topaddr; + u32 linesize, pixelFormat; + }; + + DisplayBufData disp{}; + __DisplayGetFramebuf(&disp.topaddr, &disp.linesize, &disp.pixelFormat, 0); + + u32 ptr = (u32)pushbuf.size(); + u32 sz = (u32)sizeof(disp); + pushbuf.resize(pushbuf.size() + sz); + memcpy(pushbuf.data() + ptr, &disp, sz); + + commands.push_back({CommandType::DISPLAY, sz, ptr}); +} + +static void BeginRecording() { + u32 ptr = (u32)pushbuf.size(); + u32 sz = 512 * 4; + pushbuf.resize(pushbuf.size() + sz); + gstate.Save((u32_le *)(pushbuf.data() + ptr)); + + commands.push_back({CommandType::INIT, sz, ptr}); +} + static void WriteRecording() { FlushRegisters(); + EmitDisplayBuf(); const std::string filename = GenRecordingFilename(); FILE *fp = File::OpenCFile(filename, "wb"); @@ -443,6 +472,7 @@ void NotifyFrame() { active = true; nextFrame = false; lastTextures.clear(); + BeginRecording(); } } @@ -481,6 +511,11 @@ static void FreePSPPointer(u32 &p) { } } +static void ExecuteInit(u32 ptr, u32 sz) { + gstate.Restore((u32_le *)(pushbuf.data() + ptr)); + gpu->ReapplyGfxState(); +} + static void ExecuteRegisters(u32 ptr, u32 sz) { ExecuteSubmitCmds(pushbuf.data() + ptr, sz); } @@ -578,6 +613,18 @@ static void ExecuteTexture(int level, u32 ptr, u32 sz) { execListQueue.push_back(((GE_CMD_TEXADDR0 + level) << 24) | (pspPointer & 0x00FFFFFF)); } +static void ExecuteDisplay(u32 ptr, u32 sz) { + struct DisplayBufData { + PSPPointer topaddr; + u32 linesize, pixelFormat; + }; + + DisplayBufData *disp = (DisplayBufData *)(pushbuf.data() + ptr); + + __DisplaySetFramebuf(disp->topaddr.ptr, disp->linesize, disp->pixelFormat, 1); + __DisplaySetFramebuf(disp->topaddr.ptr, disp->linesize, disp->pixelFormat, 0); +} + static void ExecuteFree() { FreePSPPointer(execIndPtr); FreePSPPointer(execVertPtr); @@ -594,6 +641,10 @@ static bool ExecuteCommands() { for (size_t i = 0; i < commands.size(); ++i) { const Command &cmd = commands[i]; switch (cmd.type) { + case CommandType::INIT: + ExecuteInit(cmd.ptr, cmd.sz); + break; + case CommandType::REGISTERS: ExecuteRegisters(cmd.ptr, cmd.sz); break; @@ -637,6 +688,10 @@ static bool ExecuteCommands() { ExecuteTexture((int)cmd.type - (int)CommandType::TEXTURE0, cmd.ptr, cmd.sz); break; + case CommandType::DISPLAY: + ExecuteDisplay(cmd.ptr, cmd.sz); + break; + default: ERROR_LOG(SYSTEM, "Unsupported GE dump command: %d", cmd.type); return false;