Use a more foolproof texture breaking method.

This commit is contained in:
Unknown W. Brackets 2013-10-12 04:45:10 -07:00
parent 3ac5198b89
commit 2584d0e67f
4 changed files with 73 additions and 10 deletions

View File

@ -19,6 +19,7 @@
#include <set>
#include "base/mutex.h"
#include "GPU/Debugger/Breakpoints.h"
#include "GPU/GPUState.h"
namespace GPUBreakpoints {
@ -35,8 +36,77 @@ static std::vector<bool> breakCmdsTemp;
static std::set<u32> breakPCsTemp;
static std::set<u32> 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<bool> 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) {

View File

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

View File

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

View File

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