GE Debugger: Record init state and display buf.

Some things are now visible, but still drawing wrong...
This commit is contained in:
Unknown W. Brackets 2017-06-03 14:46:36 -07:00
parent 21153c899b
commit 82beb726fc
4 changed files with 86 additions and 22 deletions

View File

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

View File

@ -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<u8> *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();
void Register_sceDisplay_driver();

View File

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

View File

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