From 2584d0e67fa7e1101abe7bd9f60347b49eebfc02 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 12 Oct 2013 04:45:10 -0700 Subject: [PATCH] Use a more foolproof texture breaking method. --- GPU/Debugger/Breakpoints.cpp | 70 +++++++++++++++++++++++++++++++ GPU/Debugger/Breakpoints.h | 2 + Windows/GEDebugger/GEDebugger.cpp | 9 +--- Windows/GEDebugger/GEDebugger.h | 2 - 4 files changed, 73 insertions(+), 10 deletions(-) diff --git a/GPU/Debugger/Breakpoints.cpp b/GPU/Debugger/Breakpoints.cpp index 0a8d371834..a4123f87c0 100644 --- a/GPU/Debugger/Breakpoints.cpp +++ b/GPU/Debugger/Breakpoints.cpp @@ -19,6 +19,7 @@ #include #include "base/mutex.h" #include "GPU/Debugger/Breakpoints.h" +#include "GPU/GPUState.h" namespace GPUBreakpoints { @@ -35,8 +36,77 @@ static std::vector breakCmdsTemp; static std::set breakPCsTemp; static std::set breakTexturesTemp; +// These are commands we run before breaking on a texture. +// They are commands that affect the decoding of the texture. +const static u8 textureRelatedCmds[] = { + GE_CMD_TEXADDR0, GE_CMD_TEXADDR1, GE_CMD_TEXADDR2, GE_CMD_TEXADDR3, GE_CMD_TEXADDR4, GE_CMD_TEXADDR5, GE_CMD_TEXADDR6, GE_CMD_TEXADDR7, + GE_CMD_TEXBUFWIDTH0, GE_CMD_TEXBUFWIDTH1, GE_CMD_TEXBUFWIDTH2, GE_CMD_TEXBUFWIDTH3, GE_CMD_TEXBUFWIDTH4, GE_CMD_TEXBUFWIDTH5, GE_CMD_TEXBUFWIDTH6, GE_CMD_TEXBUFWIDTH7, + GE_CMD_TEXSIZE0, GE_CMD_TEXSIZE1, GE_CMD_TEXSIZE2, GE_CMD_TEXSIZE3, GE_CMD_TEXSIZE4, GE_CMD_TEXSIZE5, GE_CMD_TEXSIZE6, GE_CMD_TEXSIZE7, + + GE_CMD_CLUTADDR, GE_CMD_CLUTADDRUPPER, GE_CMD_LOADCLUT, GE_CMD_CLUTFORMAT, + GE_CMD_TEXFORMAT, GE_CMD_TEXMODE, GE_CMD_TEXTUREMAPENABLE, + + // Sometimes found between clut/texture params. + GE_CMD_TEXFLUSH, GE_CMD_TEXSYNC, +}; +static std::vector nonTextureCmds; + void Init() { ClearAllBreakpoints(); + + nonTextureCmds.clear(); + nonTextureCmds.resize(256, true); + for (size_t i = 0; i < ARRAY_SIZE(textureRelatedCmds); ++i) { + nonTextureCmds[textureRelatedCmds[i]] = false; + } +} + +void AddNonTextureTempBreakpoints() { + for (int i = 0; i < 256; ++i) { + if (nonTextureCmds[i]) { + AddCmdBreakpoint(i, true); + } + } +} + +u32 GetAdjustedTextureAddress(u32 op) { + const u8 cmd = op >> 24; + bool interesting = (cmd >= GE_CMD_TEXADDR0 && cmd <= GE_CMD_TEXADDR7); + interesting = interesting || (cmd >= GE_CMD_TEXBUFWIDTH0 && cmd <= GE_CMD_TEXBUFWIDTH7); + + if (!interesting) { + return (u32)-1; + } + + int level = cmd <= GE_CMD_TEXADDR7 ? cmd - GE_CMD_TEXADDR0 : cmd - GE_CMD_TEXBUFWIDTH0; + u32 addr; + + // Okay, so would this op modify the low or high part? + if (cmd <= GE_CMD_TEXADDR7) { + addr = (op & 0xFFFFF0) | ((gstate.texbufwidth[level] << 8) & 0x0F000000); + } else { + addr = (gstate.texaddr[level] & 0xFFFFF0) | ((op << 8) & 0x0F000000); + } + + return addr; +} + +bool IsTextureCmdBreakpoint(u32 op) { + u32 addr = GetAdjustedTextureAddress(op); + return addr != (u32)-1 && IsTextureBreakpoint(addr); +} + +bool IsBreakpoint(u32 pc, u32 op) { + if (IsAddressBreakpoint(pc) || IsOpBreakpoint(op)) { + return true; + } + + if (breakTexturesCount != 0 && IsTextureCmdBreakpoint(op)) { + // Break on the next non-texture. + AddNonTextureTempBreakpoints(); + } + + return false; } bool IsAddressBreakpoint(u32 addr, bool &temp) { diff --git a/GPU/Debugger/Breakpoints.h b/GPU/Debugger/Breakpoints.h index cf16bc8b11..166b7a8168 100644 --- a/GPU/Debugger/Breakpoints.h +++ b/GPU/Debugger/Breakpoints.h @@ -22,6 +22,8 @@ namespace GPUBreakpoints { void Init(); + bool IsBreakpoint(u32 pc, u32 op); + bool IsAddressBreakpoint(u32 addr, bool &temp); bool IsAddressBreakpoint(u32 addr); bool IsCmdBreakpoint(u8 cmd, bool &temp); diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index c06d0d7354..f025e49a4f 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -113,16 +113,9 @@ bool CGEDebugger::IsTextureBreak(u32 op) { breakNext = BREAK_NEXT_NONTEX; } - if (IsTextureBreakpoint(state.getTextureAddress(level)) && breakNext == BREAK_NONE) { - breakNext = BREAK_NEXT_NONTEX; - } return false; } -bool CGEDebugger::IsOpOrTextureBreakPoint(u32 op) { - return IsOpBreakpoint(op) || IsTextureBreak(op); -} - static void SetPauseAction(PauseAction act, bool waitComplete = true) { { lock_guard guard(pauseLock); @@ -561,7 +554,7 @@ void WindowsHost::GPUNotifyCommand(u32 pc) { u32 op = Memory::ReadUnchecked_U32(pc); u8 cmd = op >> 24; - if (breakNext == BREAK_NEXT_OP || CGEDebugger::IsOpOrTextureBreakPoint(op) || IsAddressBreakpoint(pc)) { + if (breakNext == BREAK_NEXT_OP || CGEDebugger::IsTextureBreak(op) || IsBreakpoint(pc, op)) { PauseWithMessage(WM_GEDBG_BREAK_CMD, (WPARAM) pc); } } diff --git a/Windows/GEDebugger/GEDebugger.h b/Windows/GEDebugger/GEDebugger.h index 5d86f48845..f90443d449 100644 --- a/Windows/GEDebugger/GEDebugger.h +++ b/Windows/GEDebugger/GEDebugger.h @@ -57,8 +57,6 @@ public: static void Init(); static bool IsTextureBreak(u32 op); - // Separate so the UI can just show op break points separately. - static bool IsOpOrTextureBreakPoint(u32 op); protected: BOOL DlgProc(UINT message, WPARAM wParam, LPARAM lParam);