|
|
|
@@ -16,14 +16,18 @@
|
|
|
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
|
|
|
|
|
|
#include "Common/CommonTypes.h"
|
|
|
|
|
#include "Common/StringUtils.h"
|
|
|
|
|
#include "Core/System.h"
|
|
|
|
|
#include "Windows/resource.h"
|
|
|
|
|
#include "Windows/InputBox.h"
|
|
|
|
|
#include "Windows/GEDebugger/GEDebugger.h"
|
|
|
|
|
#include "Windows/GEDebugger/TabVertices.h"
|
|
|
|
|
#include "Windows/W32Util/ContextMenu.h"
|
|
|
|
|
#include "GPU/Common/VertexDecoderCommon.h"
|
|
|
|
|
#include "GPU/GPUState.h"
|
|
|
|
|
#include "GPU/GeDisasm.h"
|
|
|
|
|
#include "GPU/Common/GPUDebugInterface.h"
|
|
|
|
|
#include "GPU/Debugger/Breakpoints.h"
|
|
|
|
|
|
|
|
|
|
static const GenericListViewColumn vertexListCols[] = {
|
|
|
|
|
{ L"X", 0.1f },
|
|
|
|
@@ -55,7 +59,8 @@ enum VertexListCols {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const GenericListViewColumn matrixListCols[] = {
|
|
|
|
|
{ L"Name", 0.24f },
|
|
|
|
|
{ L"", 0.03f },
|
|
|
|
|
{ L"Name", 0.21f },
|
|
|
|
|
{ L"0", 0.19f },
|
|
|
|
|
{ L"1", 0.19f },
|
|
|
|
|
{ L"2", 0.19f },
|
|
|
|
@@ -67,6 +72,7 @@ GenericListViewDef matrixListDef = {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum MatrixListCols {
|
|
|
|
|
MATRIXLIST_COL_BREAKPOINT,
|
|
|
|
|
MATRIXLIST_COL_NAME,
|
|
|
|
|
MATRIXLIST_COL_0,
|
|
|
|
|
MATRIXLIST_COL_1,
|
|
|
|
@@ -360,81 +366,118 @@ BOOL TabVertices::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
|
|
|
|
|
|
|
|
|
CtrlMatrixList::CtrlMatrixList(HWND hwnd)
|
|
|
|
|
: GenericListControl(hwnd, matrixListDef) {
|
|
|
|
|
SetIconList(12, 12, { (HICON)LoadIcon(GetModuleHandle(nullptr), (LPCWSTR)IDI_BREAKPOINT_SMALL) });
|
|
|
|
|
Update();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CtrlMatrixList::GetValue(int row, int col, float &val) {
|
|
|
|
|
if (!gpuDebug || row < 0 || row >= MATRIXLIST_ROW_COUNT || col < 0 || col >= MATRIXLIST_COL_COUNT)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (col < MATRIXLIST_COL_0)
|
|
|
|
|
col = MATRIXLIST_COL_0;
|
|
|
|
|
|
|
|
|
|
auto state = gpuDebug->GetGState();
|
|
|
|
|
if (row >= MATRIXLIST_ROW_BONE_0_0) {
|
|
|
|
|
int b = (row - MATRIXLIST_ROW_BONE_0_0) / 3;
|
|
|
|
|
int r = (row - MATRIXLIST_ROW_BONE_0_0) % 3;
|
|
|
|
|
int offset = b * 12 + r + (col - MATRIXLIST_COL_0) * 3;
|
|
|
|
|
|
|
|
|
|
val = state.boneMatrix[offset];
|
|
|
|
|
return true;
|
|
|
|
|
} else if (row >= MATRIXLIST_ROW_TGEN_0) {
|
|
|
|
|
int r = row - MATRIXLIST_ROW_TGEN_0;
|
|
|
|
|
int offset = r + (col - MATRIXLIST_COL_0) * 3;
|
|
|
|
|
|
|
|
|
|
val = state.tgenMatrix[offset];
|
|
|
|
|
return true;
|
|
|
|
|
} else if (row >= MATRIXLIST_ROW_PROJ_0) {
|
|
|
|
|
int r = row - MATRIXLIST_ROW_PROJ_0;
|
|
|
|
|
int offset = r + (col - MATRIXLIST_COL_0) * 4;
|
|
|
|
|
|
|
|
|
|
val = state.projMatrix[offset];
|
|
|
|
|
return true;
|
|
|
|
|
} else if (row >= MATRIXLIST_ROW_VIEW_0) {
|
|
|
|
|
int r = row - MATRIXLIST_ROW_VIEW_0;
|
|
|
|
|
int offset = r + (col - MATRIXLIST_COL_0) * 3;
|
|
|
|
|
|
|
|
|
|
val = state.viewMatrix[offset];
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int r = row - MATRIXLIST_ROW_WORLD_0;
|
|
|
|
|
int offset = r + (col - MATRIXLIST_COL_0) * 3;
|
|
|
|
|
|
|
|
|
|
val = state.worldMatrix[offset];
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CtrlMatrixList::GetColumnText(wchar_t *dest, int row, int col) {
|
|
|
|
|
if (!gpuDebug || row < 0 || row >= MATRIXLIST_ROW_COUNT || col < 0 || col >= MATRIXLIST_COL_COUNT) {
|
|
|
|
|
if (col == MATRIXLIST_COL_BREAKPOINT) {
|
|
|
|
|
wcscpy(dest, L" ");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float val;
|
|
|
|
|
if (!GetValue(row, col, val)) {
|
|
|
|
|
wcscpy(dest, L"Invalid");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto state = gpuDebug->GetGState();
|
|
|
|
|
|
|
|
|
|
if (row >= MATRIXLIST_ROW_BONE_0_0) {
|
|
|
|
|
int b = (row - MATRIXLIST_ROW_BONE_0_0) / 3;
|
|
|
|
|
int r = (row - MATRIXLIST_ROW_BONE_0_0) % 3;
|
|
|
|
|
int offset = b * 12 + r + (col - 1) * 3;
|
|
|
|
|
|
|
|
|
|
switch (col) {
|
|
|
|
|
case MATRIXLIST_COL_NAME:
|
|
|
|
|
swprintf(dest, 255, L"Bone #%d row %d", b, r);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
swprintf(dest, 255, L"%f", state.boneMatrix[offset]);
|
|
|
|
|
swprintf(dest, 255, L"%f", val);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else if (row >= MATRIXLIST_ROW_TGEN_0) {
|
|
|
|
|
int r = row - MATRIXLIST_ROW_TGEN_0;
|
|
|
|
|
int offset = r + (col - 1) * 4;
|
|
|
|
|
|
|
|
|
|
switch (col) {
|
|
|
|
|
case MATRIXLIST_COL_NAME:
|
|
|
|
|
swprintf(dest, 255, L"Texgen %d", r);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
swprintf(dest, 255, L"%f", state.tgenMatrix[offset]);
|
|
|
|
|
swprintf(dest, 255, L"%f", val);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else if (row >= MATRIXLIST_ROW_PROJ_0) {
|
|
|
|
|
int r = row - MATRIXLIST_ROW_PROJ_0;
|
|
|
|
|
int offset = r + (col - 1) * 4;
|
|
|
|
|
|
|
|
|
|
switch (col) {
|
|
|
|
|
case MATRIXLIST_COL_NAME:
|
|
|
|
|
swprintf(dest, 255, L"Proj %d", r);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
swprintf(dest, 255, L"%f", state.projMatrix[offset]);
|
|
|
|
|
swprintf(dest, 255, L"%f", val);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else if (row >= MATRIXLIST_ROW_VIEW_0) {
|
|
|
|
|
int r = row - MATRIXLIST_ROW_VIEW_0;
|
|
|
|
|
int offset = r + (col - 1) * 3;
|
|
|
|
|
|
|
|
|
|
switch (col) {
|
|
|
|
|
case MATRIXLIST_COL_NAME:
|
|
|
|
|
swprintf(dest, 255, L"View %d", r);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
swprintf(dest, 255, L"%f", state.viewMatrix[offset]);
|
|
|
|
|
swprintf(dest, 255, L"%f", val);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
int r = row - MATRIXLIST_ROW_WORLD_0;
|
|
|
|
|
int offset = r + (col - 1) * 3;
|
|
|
|
|
|
|
|
|
|
switch (col) {
|
|
|
|
|
case MATRIXLIST_COL_NAME:
|
|
|
|
|
swprintf(dest, 255, L"World %d", r);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
swprintf(dest, 255, L"%f", state.worldMatrix[offset]);
|
|
|
|
|
swprintf(dest, 255, L"%f", val);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -448,6 +491,127 @@ int CtrlMatrixList::GetRowCount() {
|
|
|
|
|
return MATRIXLIST_ROW_COUNT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct MatrixCmdPair {
|
|
|
|
|
MatrixListRows row;
|
|
|
|
|
GECommand numCmd;
|
|
|
|
|
GECommand cmd;
|
|
|
|
|
};
|
|
|
|
|
static constexpr MatrixCmdPair matrixCmds[] = {
|
|
|
|
|
{ MATRIXLIST_ROW_WORLD_0, GE_CMD_WORLDMATRIXNUMBER, GE_CMD_WORLDMATRIXDATA },
|
|
|
|
|
{ MATRIXLIST_ROW_VIEW_0, GE_CMD_VIEWMATRIXNUMBER, GE_CMD_VIEWMATRIXDATA },
|
|
|
|
|
{ MATRIXLIST_ROW_PROJ_0, GE_CMD_PROJMATRIXNUMBER, GE_CMD_PROJMATRIXDATA },
|
|
|
|
|
{ MATRIXLIST_ROW_TGEN_0, GE_CMD_TGENMATRIXNUMBER, GE_CMD_TGENMATRIXDATA },
|
|
|
|
|
{ MATRIXLIST_ROW_BONE_0_0, GE_CMD_BONEMATRIXNUMBER, GE_CMD_BONEMATRIXDATA },
|
|
|
|
|
{ MATRIXLIST_ROW_COUNT, GE_CMD_NOP },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void CtrlMatrixList::ToggleBreakpoint(int row) {
|
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(matrixCmds) - 1; ++i) {
|
|
|
|
|
if (row < matrixCmds[i].row || row >= matrixCmds[i + 1].row)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// Okay, this command is in range. Toggle the actual breakpoint.
|
|
|
|
|
auto &info = matrixCmds[i];
|
|
|
|
|
bool state = !GPUBreakpoints::IsCmdBreakpoint(info.cmd);
|
|
|
|
|
if (state)
|
|
|
|
|
GPUBreakpoints::AddCmdBreakpoint(info.cmd);
|
|
|
|
|
else
|
|
|
|
|
GPUBreakpoints::RemoveCmdBreakpoint(info.cmd);
|
|
|
|
|
|
|
|
|
|
for (int r = matrixCmds[i].row; r < matrixCmds[i + 1].row; ++r) {
|
|
|
|
|
SetItemState(r, state ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CtrlMatrixList::OnDoubleClick(int row, int column) {
|
|
|
|
|
if (row >= GetRowCount())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (column == MATRIXLIST_COL_BREAKPOINT) {
|
|
|
|
|
ToggleBreakpoint(row);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float val;
|
|
|
|
|
if (!GetValue(row, column, val))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
std::string strvalue = StringFromFormat("%f", val);
|
|
|
|
|
bool res = InputBox_GetString(GetModuleHandle(NULL), GetHandle(), L"Column value", strvalue, strvalue);
|
|
|
|
|
if (!res)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (sscanf(strvalue.c_str(), "%f", &val) == 1) {
|
|
|
|
|
auto prevState = gpuDebug->GetGState();
|
|
|
|
|
auto setCmdValue = [&](u32 op) {
|
|
|
|
|
SendMessage(GetParent(GetParent(GetHandle())), WM_GEDBG_SETCMDWPARAM, op, NULL);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
union {
|
|
|
|
|
float f;
|
|
|
|
|
u32 u;
|
|
|
|
|
} temp = { val };
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(matrixCmds) - 1; ++i) {
|
|
|
|
|
if (row < matrixCmds[i].row || row >= matrixCmds[i + 1].row)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// Everything is 3 except the projection matrix, which is 4.
|
|
|
|
|
int sz = matrixCmds[i + 1].row - matrixCmds[i].row == 4 ? 4 : 3;
|
|
|
|
|
// Always zero except for bones.
|
|
|
|
|
int b = (row - matrixCmds[i].row) / sz;
|
|
|
|
|
int r = (row - matrixCmds[i].row) % sz;
|
|
|
|
|
int c = column >= MATRIXLIST_COL_0 ? column - MATRIXLIST_COL_0 : 0;
|
|
|
|
|
|
|
|
|
|
// Okay, now set the number, then data.
|
|
|
|
|
int n = b * 12 + r + c * sz;
|
|
|
|
|
setCmdValue((matrixCmds[i].numCmd << 24) | n);
|
|
|
|
|
setCmdValue((matrixCmds[i].cmd << 24) | (temp.u >> 8));
|
|
|
|
|
|
|
|
|
|
// Done, revert the number.
|
|
|
|
|
setCmdValue(prevState.cmdmem[matrixCmds[i].numCmd]);
|
|
|
|
|
Update();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CtrlMatrixList::OnRightClick(int row, int column, const POINT &point) {
|
|
|
|
|
if (row >= GetRowCount())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
POINT screenPt(point);
|
|
|
|
|
ClientToScreen(GetHandle(), &screenPt);
|
|
|
|
|
|
|
|
|
|
HMENU subMenu = GetContextMenu(ContextMenuID::GEDBG_MATRIX);
|
|
|
|
|
SetMenuDefaultItem(subMenu, ID_REGLIST_CHANGE, FALSE);
|
|
|
|
|
|
|
|
|
|
switch (TriggerContextMenu(ContextMenuID::GEDBG_MATRIX, GetHandle(), ContextPoint::FromClient(point))) {
|
|
|
|
|
case ID_DISASM_TOGGLEBREAKPOINT:
|
|
|
|
|
ToggleBreakpoint(row);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_DISASM_COPYINSTRUCTIONDISASM:
|
|
|
|
|
{
|
|
|
|
|
float val;
|
|
|
|
|
if (GetValue(row, column, val)) {
|
|
|
|
|
wchar_t dest[512];
|
|
|
|
|
swprintf(dest, 511, L"%f", val);
|
|
|
|
|
W32Util::CopyTextToClipboard(GetHandle(), dest);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case ID_GEDBG_COPYALL:
|
|
|
|
|
CopyRows(0, GetRowCount());
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_REGLIST_CHANGE:
|
|
|
|
|
OnDoubleClick(row, MATRIXLIST_COL_0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TabMatrices::TabMatrices(HINSTANCE _hInstance, HWND _hParent)
|
|
|
|
|
: Dialog((LPCSTR)IDD_GEDBG_TAB_MATRICES, _hInstance, _hParent) {
|
|
|
|
|
values = new CtrlMatrixList(GetDlgItem(m_hDlg, IDC_GEDBG_MATRICES));
|
|
|
|
|