CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Windows/GEDebugger/TabState.cpp
Views: 1401
1
// Copyright (c) 2012- PPSSPP Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18
#include "Common/CommonWindows.h"
19
#include <commctrl.h>
20
#include <array>
21
#include "Common/CommonFuncs.h"
22
#include "Common/CommonTypes.h"
23
#include "Common/Data/Encoding/Utf8.h"
24
#include "Common/Data/Text/Parsers.h"
25
#include "Common/Log.h"
26
#include "Common/StringUtils.h"
27
#include "Windows/resource.h"
28
#include "Windows/InputBox.h"
29
#include "Windows/GEDebugger/GEDebugger.h"
30
#include "Windows/GEDebugger/TabState.h"
31
#include "Windows/W32Util/ContextMenu.h"
32
#include "GPU/GPUState.h"
33
#include "GPU/GeDisasm.h"
34
#include "GPU/Common/GPUDebugInterface.h"
35
#include "GPU/Debugger/Breakpoints.h"
36
#include "GPU/Debugger/Stepping.h"
37
38
using namespace GPUBreakpoints;
39
40
// First column is the breakpoint icon.
41
static const GenericListViewColumn stateValuesCols[] = {
42
{ L"", 0.03f },
43
{ L"Name", 0.40f },
44
{ L"Value", 0.57f },
45
};
46
47
GenericListViewDef stateValuesListDef = {
48
stateValuesCols,
49
ARRAY_SIZE(stateValuesCols),
50
nullptr,
51
false,
52
};
53
54
enum StateValuesCols {
55
STATEVALUES_COL_BREAKPOINT,
56
STATEVALUES_COL_NAME,
57
STATEVALUES_COL_VALUE,
58
};
59
60
enum CmdFormatType {
61
CMD_FMT_HEX = 0,
62
CMD_FMT_NUM,
63
CMD_FMT_FLOAT24,
64
CMD_FMT_PTRWIDTH,
65
CMD_FMT_XY,
66
CMD_FMT_XYXY,
67
CMD_FMT_XYZ,
68
CMD_FMT_XYPLUS1,
69
CMD_FMT_TEXSIZE,
70
CMD_FMT_F16_XY,
71
CMD_FMT_VERTEXTYPE,
72
CMD_FMT_TEXFMT,
73
CMD_FMT_CLUTFMT,
74
CMD_FMT_COLORTEST,
75
CMD_FMT_ALPHATEST,
76
CMD_FMT_STENCILTEST,
77
CMD_FMT_ZTEST,
78
CMD_FMT_OFFSETADDR,
79
CMD_FMT_VADDR,
80
CMD_FMT_IADDR,
81
CMD_FMT_MATERIALUPDATE,
82
CMD_FMT_STENCILOP,
83
CMD_FMT_BLENDMODE,
84
CMD_FMT_FLAG,
85
CMD_FMT_CLEARMODE,
86
CMD_FMT_TEXFUNC,
87
CMD_FMT_TEXMODE,
88
CMD_FMT_LOGICOP,
89
CMD_FMT_TEXWRAP,
90
CMD_FMT_TEXLEVEL,
91
CMD_FMT_TEXFILTER,
92
CMD_FMT_TEXMAPMODE,
93
CMD_FMT_TEXSHADELS,
94
CMD_FMT_SHADEMODEL,
95
CMD_FMT_LIGHTMODE,
96
CMD_FMT_LIGHTTYPE,
97
CMD_FMT_CULL,
98
CMD_FMT_PATCHPRIMITIVE,
99
};
100
101
struct TabStateRow {
102
const TCHAR *title;
103
u8 cmd;
104
CmdFormatType fmt;
105
u8 enableCmd;
106
u8 otherCmd;
107
u8 otherCmd2;
108
};
109
110
static const TabStateRow stateFlagsRows[] = {
111
{ L"Lighting enable", GE_CMD_LIGHTINGENABLE, CMD_FMT_FLAG },
112
{ L"Light 0 enable", GE_CMD_LIGHTENABLE0, CMD_FMT_FLAG },
113
{ L"Light 1 enable", GE_CMD_LIGHTENABLE1, CMD_FMT_FLAG },
114
{ L"Light 2 enable", GE_CMD_LIGHTENABLE2, CMD_FMT_FLAG },
115
{ L"Light 3 enable", GE_CMD_LIGHTENABLE3, CMD_FMT_FLAG },
116
{ L"Depth clamp enable", GE_CMD_DEPTHCLAMPENABLE, CMD_FMT_FLAG },
117
{ L"Cullface enable", GE_CMD_CULLFACEENABLE, CMD_FMT_FLAG },
118
{ L"Texture map enable", GE_CMD_TEXTUREMAPENABLE, CMD_FMT_FLAG },
119
{ L"Fog enable", GE_CMD_FOGENABLE, CMD_FMT_FLAG },
120
{ L"Dither enable", GE_CMD_DITHERENABLE, CMD_FMT_FLAG },
121
{ L"Alpha blend enable", GE_CMD_ALPHABLENDENABLE, CMD_FMT_FLAG },
122
{ L"Alpha test enable", GE_CMD_ALPHATESTENABLE, CMD_FMT_FLAG },
123
{ L"Depth test enable", GE_CMD_ZTESTENABLE, CMD_FMT_FLAG },
124
{ L"Stencil test enable", GE_CMD_STENCILTESTENABLE, CMD_FMT_FLAG },
125
{ L"Antialias enable", GE_CMD_ANTIALIASENABLE, CMD_FMT_FLAG },
126
{ L"Patch cull enable", GE_CMD_PATCHCULLENABLE, CMD_FMT_FLAG },
127
{ L"Color test enable", GE_CMD_COLORTESTENABLE, CMD_FMT_FLAG },
128
{ L"Logic op enable", GE_CMD_LOGICOPENABLE, CMD_FMT_FLAG },
129
{ L"Depth write disable", GE_CMD_ZWRITEDISABLE, CMD_FMT_FLAG },
130
};
131
132
static const TabStateRow stateLightingRows[] = {
133
{ L"Ambient color", GE_CMD_AMBIENTCOLOR, CMD_FMT_HEX },
134
{ L"Ambient alpha", GE_CMD_AMBIENTALPHA, CMD_FMT_HEX },
135
{ L"Material update", GE_CMD_MATERIALUPDATE, CMD_FMT_MATERIALUPDATE },
136
{ L"Material emissive", GE_CMD_MATERIALEMISSIVE, CMD_FMT_HEX },
137
{ L"Material ambient", GE_CMD_MATERIALAMBIENT, CMD_FMT_HEX },
138
{ L"Material diffuse", GE_CMD_MATERIALDIFFUSE, CMD_FMT_HEX },
139
{ L"Material alpha", GE_CMD_MATERIALALPHA, CMD_FMT_HEX },
140
{ L"Material specular", GE_CMD_MATERIALSPECULAR, CMD_FMT_HEX },
141
{ L"Mat. specular coef", GE_CMD_MATERIALSPECULARCOEF, CMD_FMT_FLOAT24 },
142
{ L"Reverse normals", GE_CMD_REVERSENORMAL, CMD_FMT_FLAG },
143
{ L"Shade model", GE_CMD_SHADEMODE, CMD_FMT_SHADEMODEL },
144
{ L"Light mode", GE_CMD_LIGHTMODE, CMD_FMT_LIGHTMODE, GE_CMD_LIGHTINGENABLE },
145
{ L"Light type 0", GE_CMD_LIGHTTYPE0, CMD_FMT_LIGHTTYPE, GE_CMD_LIGHTENABLE0 },
146
{ L"Light type 1", GE_CMD_LIGHTTYPE1, CMD_FMT_LIGHTTYPE, GE_CMD_LIGHTENABLE1 },
147
{ L"Light type 2", GE_CMD_LIGHTTYPE2, CMD_FMT_LIGHTTYPE, GE_CMD_LIGHTENABLE2 },
148
{ L"Light type 3", GE_CMD_LIGHTTYPE3, CMD_FMT_LIGHTTYPE, GE_CMD_LIGHTENABLE3 },
149
{ L"Light pos 0", GE_CMD_LX0, CMD_FMT_XYZ, GE_CMD_LIGHTENABLE0, GE_CMD_LY0, GE_CMD_LZ0 },
150
{ L"Light pos 1", GE_CMD_LX1, CMD_FMT_XYZ, GE_CMD_LIGHTENABLE1, GE_CMD_LY1, GE_CMD_LZ1 },
151
{ L"Light pos 2", GE_CMD_LX2, CMD_FMT_XYZ, GE_CMD_LIGHTENABLE2, GE_CMD_LY2, GE_CMD_LZ2 },
152
{ L"Light pos 3", GE_CMD_LX3, CMD_FMT_XYZ, GE_CMD_LIGHTENABLE3, GE_CMD_LY3, GE_CMD_LZ3 },
153
{ L"Light dir 0", GE_CMD_LDX0, CMD_FMT_XYZ, GE_CMD_LIGHTENABLE0, GE_CMD_LDY0, GE_CMD_LDZ0 },
154
{ L"Light dir 1", GE_CMD_LDX1, CMD_FMT_XYZ, GE_CMD_LIGHTENABLE1, GE_CMD_LDY1, GE_CMD_LDZ1 },
155
{ L"Light dir 2", GE_CMD_LDX2, CMD_FMT_XYZ, GE_CMD_LIGHTENABLE2, GE_CMD_LDY2, GE_CMD_LDZ2 },
156
{ L"Light dir 3", GE_CMD_LDX3, CMD_FMT_XYZ, GE_CMD_LIGHTENABLE3, GE_CMD_LDY3, GE_CMD_LDZ3 },
157
{ L"Light att 0", GE_CMD_LKA0, CMD_FMT_XYZ, GE_CMD_LIGHTENABLE0, GE_CMD_LKB0, GE_CMD_LKC0 },
158
{ L"Light att 1", GE_CMD_LKA1, CMD_FMT_XYZ, GE_CMD_LIGHTENABLE1, GE_CMD_LKB1, GE_CMD_LKC1 },
159
{ L"Light att 2", GE_CMD_LKA2, CMD_FMT_XYZ, GE_CMD_LIGHTENABLE2, GE_CMD_LKB2, GE_CMD_LKC2 },
160
{ L"Light att 3", GE_CMD_LKA3, CMD_FMT_XYZ, GE_CMD_LIGHTENABLE3, GE_CMD_LKB3, GE_CMD_LKC3 },
161
{ L"Lightspot coef 0", GE_CMD_LKS0, CMD_FMT_FLOAT24, GE_CMD_LIGHTENABLE0 },
162
{ L"Lightspot coef 1", GE_CMD_LKS1, CMD_FMT_FLOAT24, GE_CMD_LIGHTENABLE1 },
163
{ L"Lightspot coef 2", GE_CMD_LKS2, CMD_FMT_FLOAT24, GE_CMD_LIGHTENABLE2 },
164
{ L"Lightspot coef 3", GE_CMD_LKS3, CMD_FMT_FLOAT24, GE_CMD_LIGHTENABLE3 },
165
{ L"Light angle 0", GE_CMD_LKO0, CMD_FMT_FLOAT24, GE_CMD_LIGHTENABLE0 },
166
{ L"Light angle 1", GE_CMD_LKO1, CMD_FMT_FLOAT24, GE_CMD_LIGHTENABLE1 },
167
{ L"Light angle 2", GE_CMD_LKO2, CMD_FMT_FLOAT24, GE_CMD_LIGHTENABLE2 },
168
{ L"Light angle 3", GE_CMD_LKO3, CMD_FMT_FLOAT24, GE_CMD_LIGHTENABLE3 },
169
{ L"Light ambient 0", GE_CMD_LAC0, CMD_FMT_HEX, GE_CMD_LIGHTENABLE0 },
170
{ L"Light diffuse 0", GE_CMD_LDC0, CMD_FMT_HEX, GE_CMD_LIGHTENABLE0 },
171
{ L"Light specular 0", GE_CMD_LSC0, CMD_FMT_HEX, GE_CMD_LIGHTENABLE0 },
172
{ L"Light ambient 1", GE_CMD_LAC1, CMD_FMT_HEX, GE_CMD_LIGHTENABLE1 },
173
{ L"Light diffuse 1", GE_CMD_LDC1, CMD_FMT_HEX, GE_CMD_LIGHTENABLE1 },
174
{ L"Light specular 1", GE_CMD_LSC1, CMD_FMT_HEX, GE_CMD_LIGHTENABLE1 },
175
{ L"Light ambient 2", GE_CMD_LAC2, CMD_FMT_HEX, GE_CMD_LIGHTENABLE2 },
176
{ L"Light diffuse 2", GE_CMD_LDC2, CMD_FMT_HEX, GE_CMD_LIGHTENABLE2 },
177
{ L"Light specular 2", GE_CMD_LSC2, CMD_FMT_HEX, GE_CMD_LIGHTENABLE2 },
178
{ L"Light ambient 3", GE_CMD_LAC3, CMD_FMT_HEX, GE_CMD_LIGHTENABLE3 },
179
{ L"Light diffuse 3", GE_CMD_LDC3, CMD_FMT_HEX, GE_CMD_LIGHTENABLE3 },
180
{ L"Light specular 3", GE_CMD_LSC3, CMD_FMT_HEX, GE_CMD_LIGHTENABLE3 },
181
};
182
183
static const TabStateRow stateTextureRows[] = {
184
{ L"Texture L0 addr", GE_CMD_TEXADDR0, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH0 },
185
{ L"Texture L0 size", GE_CMD_TEXSIZE0, CMD_FMT_TEXSIZE, GE_CMD_TEXTUREMAPENABLE },
186
{ L"Tex format", GE_CMD_TEXFORMAT, CMD_FMT_TEXFMT, GE_CMD_TEXTUREMAPENABLE },
187
{ L"Tex CLUT", GE_CMD_CLUTADDR, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_CLUTADDRUPPER },
188
{ L"Tex CLUT format", GE_CMD_CLUTFORMAT, CMD_FMT_CLUTFMT, GE_CMD_TEXTUREMAPENABLE },
189
190
{ L"Tex U scale", GE_CMD_TEXSCALEU, CMD_FMT_FLOAT24, GE_CMD_TEXTUREMAPENABLE },
191
{ L"Tex V scale", GE_CMD_TEXSCALEV, CMD_FMT_FLOAT24, GE_CMD_TEXTUREMAPENABLE },
192
{ L"Tex U offset", GE_CMD_TEXOFFSETU, CMD_FMT_FLOAT24, GE_CMD_TEXTUREMAPENABLE },
193
{ L"Tex V offset", GE_CMD_TEXOFFSETV, CMD_FMT_FLOAT24, GE_CMD_TEXTUREMAPENABLE },
194
{ L"Tex mapping mode", GE_CMD_TEXMAPMODE, CMD_FMT_TEXMAPMODE, GE_CMD_TEXTUREMAPENABLE },
195
{ L"Tex shade srcs", GE_CMD_TEXSHADELS, CMD_FMT_TEXSHADELS, GE_CMD_TEXTUREMAPENABLE },
196
{ L"Tex func", GE_CMD_TEXFUNC, CMD_FMT_TEXFUNC, GE_CMD_TEXTUREMAPENABLE },
197
{ L"Tex env color", GE_CMD_TEXENVCOLOR, CMD_FMT_HEX, GE_CMD_TEXTUREMAPENABLE },
198
{ L"Tex mode", GE_CMD_TEXMODE, CMD_FMT_TEXMODE, GE_CMD_TEXTUREMAPENABLE },
199
{ L"Tex filtering", GE_CMD_TEXFILTER, CMD_FMT_TEXFILTER, GE_CMD_TEXTUREMAPENABLE },
200
{ L"Tex wrapping", GE_CMD_TEXWRAP, CMD_FMT_TEXWRAP, GE_CMD_TEXTUREMAPENABLE },
201
{ L"Tex level/bias", GE_CMD_TEXLEVEL, CMD_FMT_TEXLEVEL, GE_CMD_TEXTUREMAPENABLE },
202
{ L"Tex lod slope", GE_CMD_TEXLODSLOPE, CMD_FMT_FLOAT24, GE_CMD_TEXTUREMAPENABLE },
203
{ L"Texture L1 addr", GE_CMD_TEXADDR1, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH1 },
204
{ L"Texture L2 addr", GE_CMD_TEXADDR2, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH2 },
205
{ L"Texture L3 addr", GE_CMD_TEXADDR3, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH3 },
206
{ L"Texture L4 addr", GE_CMD_TEXADDR4, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH4 },
207
{ L"Texture L5 addr", GE_CMD_TEXADDR5, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH5 },
208
{ L"Texture L6 addr", GE_CMD_TEXADDR6, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH6 },
209
{ L"Texture L7 addr", GE_CMD_TEXADDR7, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH7 },
210
{ L"Texture L1 size", GE_CMD_TEXSIZE1, CMD_FMT_TEXSIZE, GE_CMD_TEXTUREMAPENABLE },
211
{ L"Texture L2 size", GE_CMD_TEXSIZE2, CMD_FMT_TEXSIZE, GE_CMD_TEXTUREMAPENABLE },
212
{ L"Texture L3 size", GE_CMD_TEXSIZE3, CMD_FMT_TEXSIZE, GE_CMD_TEXTUREMAPENABLE },
213
{ L"Texture L4 size", GE_CMD_TEXSIZE4, CMD_FMT_TEXSIZE, GE_CMD_TEXTUREMAPENABLE },
214
{ L"Texture L5 size", GE_CMD_TEXSIZE5, CMD_FMT_TEXSIZE, GE_CMD_TEXTUREMAPENABLE },
215
{ L"Texture L6 size", GE_CMD_TEXSIZE6, CMD_FMT_TEXSIZE, GE_CMD_TEXTUREMAPENABLE },
216
{ L"Texture L7 size", GE_CMD_TEXSIZE7, CMD_FMT_TEXSIZE, GE_CMD_TEXTUREMAPENABLE },
217
};
218
219
static const TabStateRow stateSettingsRows[] = {
220
{ L"Framebuffer", GE_CMD_FRAMEBUFPTR, CMD_FMT_PTRWIDTH, 0, GE_CMD_FRAMEBUFWIDTH },
221
{ L"Framebuffer format", GE_CMD_FRAMEBUFPIXFORMAT, CMD_FMT_TEXFMT },
222
{ L"Depthbuffer", GE_CMD_ZBUFPTR, CMD_FMT_PTRWIDTH, 0, GE_CMD_ZBUFWIDTH },
223
{ L"Viewport Scale", GE_CMD_VIEWPORTXSCALE, CMD_FMT_XYZ, 0, GE_CMD_VIEWPORTYSCALE, GE_CMD_VIEWPORTZSCALE },
224
{ L"Viewport Offset", GE_CMD_VIEWPORTXCENTER, CMD_FMT_XYZ, 0, GE_CMD_VIEWPORTYCENTER, GE_CMD_VIEWPORTZCENTER },
225
{ L"Scissor", GE_CMD_SCISSOR1, CMD_FMT_XYXY, 0, GE_CMD_SCISSOR2 },
226
{ L"Region", GE_CMD_REGION1, CMD_FMT_XYXY, 0, GE_CMD_REGION2 },
227
{ L"Color test", GE_CMD_COLORTEST, CMD_FMT_COLORTEST, GE_CMD_COLORTESTENABLE, GE_CMD_COLORREF, GE_CMD_COLORTESTMASK },
228
{ L"Alpha test", GE_CMD_ALPHATEST, CMD_FMT_ALPHATEST, GE_CMD_ALPHATESTENABLE },
229
{ L"Clear mode", GE_CMD_CLEARMODE, CMD_FMT_CLEARMODE },
230
{ L"Stencil test", GE_CMD_STENCILTEST, CMD_FMT_STENCILTEST, GE_CMD_STENCILTESTENABLE },
231
{ L"Stencil test op", GE_CMD_STENCILOP, CMD_FMT_STENCILOP, GE_CMD_STENCILTESTENABLE },
232
{ L"Depth test", GE_CMD_ZTEST, CMD_FMT_ZTEST, GE_CMD_ZTESTENABLE },
233
{ L"RGB mask", GE_CMD_MASKRGB, CMD_FMT_HEX },
234
{ L"Stencil/alpha mask", GE_CMD_MASKALPHA, CMD_FMT_HEX },
235
{ L"Transfer src", GE_CMD_TRANSFERSRC, CMD_FMT_PTRWIDTH, 0, GE_CMD_TRANSFERSRCW },
236
{ L"Transfer src pos", GE_CMD_TRANSFERSRCPOS, CMD_FMT_XY },
237
{ L"Transfer dst", GE_CMD_TRANSFERDST, CMD_FMT_PTRWIDTH, 0, GE_CMD_TRANSFERDSTW },
238
{ L"Transfer dst pos", GE_CMD_TRANSFERDSTPOS, CMD_FMT_XY },
239
{ L"Transfer size", GE_CMD_TRANSFERSIZE, CMD_FMT_XYPLUS1 },
240
{ L"Vertex type", GE_CMD_VERTEXTYPE, CMD_FMT_VERTEXTYPE },
241
{ L"Offset addr", GE_CMD_OFFSETADDR, CMD_FMT_OFFSETADDR },
242
{ L"Vertex addr", GE_CMD_VADDR, CMD_FMT_VADDR },
243
{ L"Index addr", GE_CMD_IADDR, CMD_FMT_IADDR },
244
{ L"Min Z", GE_CMD_MINZ, CMD_FMT_HEX },
245
{ L"Max Z", GE_CMD_MAXZ, CMD_FMT_HEX },
246
{ L"Offset", GE_CMD_OFFSETX, CMD_FMT_F16_XY, 0, GE_CMD_OFFSETY },
247
{ L"Cull mode", GE_CMD_CULL, CMD_FMT_CULL, GE_CMD_CULLFACEENABLE },
248
{ L"Alpha blend mode", GE_CMD_BLENDMODE, CMD_FMT_BLENDMODE, GE_CMD_ALPHABLENDENABLE },
249
{ L"Blend color A", GE_CMD_BLENDFIXEDA, CMD_FMT_HEX, GE_CMD_ALPHABLENDENABLE },
250
{ L"Blend color B", GE_CMD_BLENDFIXEDB, CMD_FMT_HEX, GE_CMD_ALPHABLENDENABLE },
251
{ L"Logic Op", GE_CMD_LOGICOP, CMD_FMT_LOGICOP, GE_CMD_LOGICOPENABLE },
252
{ L"Fog 1", GE_CMD_FOG1, CMD_FMT_FLOAT24, GE_CMD_FOGENABLE },
253
{ L"Fog 2", GE_CMD_FOG2, CMD_FMT_FLOAT24, GE_CMD_FOGENABLE },
254
{ L"Fog color", GE_CMD_FOGCOLOR, CMD_FMT_HEX, GE_CMD_FOGENABLE },
255
{ L"Morph Weight 0", GE_CMD_MORPHWEIGHT0, CMD_FMT_FLOAT24 },
256
{ L"Morph Weight 1", GE_CMD_MORPHWEIGHT1, CMD_FMT_FLOAT24 },
257
{ L"Morph Weight 2", GE_CMD_MORPHWEIGHT2, CMD_FMT_FLOAT24 },
258
{ L"Morph Weight 3", GE_CMD_MORPHWEIGHT3, CMD_FMT_FLOAT24 },
259
{ L"Morph Weight 4", GE_CMD_MORPHWEIGHT4, CMD_FMT_FLOAT24 },
260
{ L"Morph Weight 5", GE_CMD_MORPHWEIGHT5, CMD_FMT_FLOAT24 },
261
{ L"Morph Weight 6", GE_CMD_MORPHWEIGHT6, CMD_FMT_FLOAT24 },
262
{ L"Morph Weight 7", GE_CMD_MORPHWEIGHT7, CMD_FMT_FLOAT24 },
263
// TODO: Format?
264
{ L"Patch division", GE_CMD_PATCHDIVISION, CMD_FMT_HEX },
265
{ L"Patch primitive", GE_CMD_PATCHPRIMITIVE, CMD_FMT_PATCHPRIMITIVE },
266
// TODO: Format?
267
{ L"Patch facing", GE_CMD_PATCHFACING, CMD_FMT_HEX, GE_CMD_PATCHCULLENABLE },
268
{ L"Dither 0", GE_CMD_DITH0, CMD_FMT_HEX, GE_CMD_DITHERENABLE },
269
{ L"Dither 1", GE_CMD_DITH1, CMD_FMT_HEX, GE_CMD_DITHERENABLE },
270
{ L"Dither 2", GE_CMD_DITH2, CMD_FMT_HEX, GE_CMD_DITHERENABLE },
271
{ L"Dither 3", GE_CMD_DITH3, CMD_FMT_HEX, GE_CMD_DITHERENABLE },
272
{ L"Imm vertex XY", GE_CMD_VSCX, CMD_FMT_F16_XY, 0, GE_CMD_VSCY },
273
{ L"Imm vertex Z", GE_CMD_VSCZ, CMD_FMT_HEX },
274
{ L"Imm vertex tex STQ", GE_CMD_VTCS, CMD_FMT_XYZ, 0, GE_CMD_VTCT, GE_CMD_VTCQ },
275
{ L"Imm vertex color0", GE_CMD_VCV, CMD_FMT_HEX },
276
{ L"Imm vertex color1", GE_CMD_VSCV, CMD_FMT_HEX },
277
{ L"Imm vertex fog", GE_CMD_VFC, CMD_FMT_HEX },
278
// TODO: Format?
279
{ L"Imm vertex prim", GE_CMD_VAP, CMD_FMT_HEX },
280
};
281
282
// TODO: Commands not present in the above lists (some because they don't have meaningful values...):
283
// GE_CMD_PRIM, GE_CMD_BEZIER, GE_CMD_SPLINE, GE_CMD_BOUNDINGBOX,
284
// GE_CMD_JUMP, GE_CMD_BJUMP, GE_CMD_CALL, GE_CMD_RET, GE_CMD_END, GE_CMD_SIGNAL, GE_CMD_FINISH,
285
// GE_CMD_BONEMATRIXNUMBER, GE_CMD_BONEMATRIXDATA, GE_CMD_WORLDMATRIXNUMBER, GE_CMD_WORLDMATRIXDATA,
286
// GE_CMD_VIEWMATRIXNUMBER, GE_CMD_VIEWMATRIXDATA, GE_CMD_PROJMATRIXNUMBER, GE_CMD_PROJMATRIXDATA,
287
// GE_CMD_TGENMATRIXNUMBER, GE_CMD_TGENMATRIXDATA,
288
// GE_CMD_LOADCLUT, GE_CMD_TEXFLUSH, GE_CMD_TEXSYNC,
289
// GE_CMD_TRANSFERSTART,
290
// GE_CMD_UNKNOWN_*
291
292
static std::vector<TabStateRow> watchList;
293
294
static void ToggleWatchList(const TabStateRow &info) {
295
for (size_t i = 0; i < watchList.size(); ++i) {
296
if (watchList[i].cmd == info.cmd) {
297
watchList.erase(watchList.begin() + i);
298
return;
299
}
300
}
301
302
watchList.push_back(info);
303
}
304
305
static bool ToggleBreakpoint(const TabStateRow &info) {
306
if (IsCmdBreakpoint(info.cmd)) {
307
RemoveCmdBreakpoint(info.cmd);
308
if (info.otherCmd)
309
RemoveCmdBreakpoint(info.otherCmd);
310
if (info.otherCmd2)
311
RemoveCmdBreakpoint(info.otherCmd2);
312
return false;
313
}
314
315
AddCmdBreakpoint(info.cmd);
316
if (info.otherCmd)
317
AddCmdBreakpoint(info.otherCmd);
318
if (info.otherCmd2)
319
AddCmdBreakpoint(info.otherCmd2);
320
return true;
321
}
322
323
bool PromptStateValue(const TabStateRow &info, HWND hparent, const wchar_t *title, u32 &value) {
324
if (info.fmt == CMD_FMT_FLOAT24 || info.fmt == CMD_FMT_XYZ) {
325
union {
326
u32 u;
327
float f;
328
} temp = { value << 8 };
329
330
std::string strvalue = StringFromFormat("%f", temp.f);
331
bool res = InputBox_GetString(GetModuleHandle(NULL), hparent, title, strvalue, strvalue);
332
if (!res)
333
return false;
334
335
// Okay, the result could be a simple float, hex (0x...), or invalid.
336
if (sscanf(strvalue.c_str(), "0x%08x", &value) == 1)
337
return true;
338
if (sscanf(strvalue.c_str(), "%f", &temp.f) == 1) {
339
value = temp.u >> 8;
340
return true;
341
}
342
return false;
343
}
344
return InputBox_GetHex(GetModuleHandle(NULL), hparent, title, value, value);
345
}
346
347
CtrlStateValues::CtrlStateValues(const TabStateRow *rows, int rowCount, HWND hwnd)
348
: GenericListControl(hwnd, stateValuesListDef),
349
rows_(rows), rowCount_(rowCount) {
350
SetIconList(12, 12, { (HICON)LoadIcon(GetModuleHandle(nullptr), (LPCWSTR)IDI_BREAKPOINT_SMALL) });
351
Update();
352
}
353
354
void FormatStateRow(wchar_t *dest, const TabStateRow &info, u32 value, bool enabled, u32 otherValue, u32 otherValue2) {
355
switch (info.fmt) {
356
case CMD_FMT_HEX:
357
swprintf(dest, 255, L"%06x", value);
358
break;
359
360
case CMD_FMT_NUM:
361
swprintf(dest, 255, L"%d", value);
362
break;
363
364
case CMD_FMT_FLOAT24:
365
swprintf(dest, 255, L"%f", getFloat24(value));
366
break;
367
368
case CMD_FMT_PTRWIDTH:
369
value |= (otherValue & 0x00FF0000) << 8;
370
otherValue &= 0xFFFF;
371
swprintf(dest, 255, L"%08x, w=%d", value, otherValue);
372
break;
373
374
case CMD_FMT_XY:
375
{
376
int x = value & 0x3FF;
377
int y = value >> 10;
378
swprintf(dest, 255, L"%d,%d", x, y);
379
}
380
break;
381
382
case CMD_FMT_XYPLUS1:
383
{
384
int x = value & 0x3FF;
385
int y = value >> 10;
386
swprintf(dest, 255, L"%d,%d", x + 1, y + 1);
387
}
388
break;
389
390
case CMD_FMT_XYXY:
391
{
392
int x1 = value & 0x3FF;
393
int y1 = value >> 10;
394
int x2 = otherValue & 0x3FF;
395
int y2 = otherValue >> 10;
396
swprintf(dest, 255, L"%d,%d - %d,%d", x1, y1, x2, y2);
397
}
398
break;
399
400
case CMD_FMT_XYZ:
401
{
402
float x = getFloat24(value);
403
float y = getFloat24(otherValue);
404
float z = getFloat24(otherValue2);
405
swprintf(dest, 255, L"%f, %f, %f", x, y, z);
406
}
407
break;
408
409
case CMD_FMT_TEXSIZE:
410
{
411
int w = 1 << (value & 0x1f);
412
int h = 1 << ((value >> 8) & 0x1f);
413
swprintf(dest, 255, L"%dx%d", w, h);
414
}
415
break;
416
417
case CMD_FMT_F16_XY:
418
{
419
float x = (float)value / 16.0f;
420
float y = (float)otherValue / 16.0f;
421
swprintf(dest, 255, L"%fx%f", x, y);
422
}
423
break;
424
425
case CMD_FMT_VERTEXTYPE:
426
{
427
char buffer[256];
428
GeDescribeVertexType(value, buffer);
429
swprintf(dest, 255, L"%S", buffer);
430
}
431
break;
432
433
case CMD_FMT_TEXFMT:
434
{
435
static const char *texformats[] = {
436
"5650",
437
"5551",
438
"4444",
439
"8888",
440
"CLUT4",
441
"CLUT8",
442
"CLUT16",
443
"CLUT32",
444
"DXT1",
445
"DXT3",
446
"DXT5",
447
};
448
if (value < (u32)ARRAY_SIZE(texformats)) {
449
swprintf(dest, 255, L"%S", texformats[value]);
450
}
451
else if ((value & 0xF) < (u32)ARRAY_SIZE(texformats)) {
452
swprintf(dest, 255, L"%S (extra bits %06x)", texformats[value & 0xF], value & ~0xF);
453
}
454
else {
455
swprintf(dest, 255, L"%06x", value);
456
}
457
}
458
break;
459
460
case CMD_FMT_CLUTFMT:
461
{
462
const char *clutformats[] = {
463
"BGR 5650",
464
"ABGR 1555",
465
"ABGR 4444",
466
"ABGR 8888",
467
};
468
const u8 palette = (value >> 0) & 3;
469
const u8 shift = (value >> 2) & 0x3F;
470
const u8 mask = (value >> 8) & 0xFF;
471
const u8 offset = (value >> 16) & 0xFF;
472
if (offset < 0x20 && shift < 0x20) {
473
if (offset == 0 && shift == 0) {
474
swprintf(dest, 255, L"%S ind & %02x", clutformats[palette], mask);
475
} else {
476
swprintf(dest, 255, L"%S (ind >> %d) & %02x, offset +%d", clutformats[palette], shift, mask, offset);
477
}
478
} else {
479
swprintf(dest, 255, L"%06x", value);
480
}
481
}
482
break;
483
484
case CMD_FMT_COLORTEST:
485
{
486
static const char *colorTests[] = {"NEVER", "ALWAYS", " == ", " != "};
487
const u32 mask = otherValue2;
488
const u32 ref = otherValue;
489
if (value < (u32)ARRAY_SIZE(colorTests)) {
490
swprintf(dest, 255, L"pass if (c & %06x) %S (%06x & %06x)", mask, colorTests[value], ref, mask);
491
} else {
492
swprintf(dest, 255, L"%06x, ref=%06x, maks=%06x", value, ref, mask);
493
}
494
}
495
break;
496
497
case CMD_FMT_ALPHATEST:
498
case CMD_FMT_STENCILTEST:
499
{
500
static const char *alphaTestFuncs[] = { "NEVER", "ALWAYS", "==", "!=", "<", "<=", ">", ">=" };
501
const u8 mask = (value >> 16) & 0xff;
502
const u8 ref = (value >> 8) & 0xff;
503
const u8 func = (value >> 0) & 0xff;
504
if (func < (u8)ARRAY_SIZE(alphaTestFuncs)) {
505
if (info.fmt == CMD_FMT_ALPHATEST) {
506
swprintf(dest, 255, L"pass if (a & %02x) %S (%02x & %02x)", mask, alphaTestFuncs[func], ref, mask);
507
} else if (info.fmt == CMD_FMT_STENCILTEST) {
508
// Stencil test is the other way around.
509
swprintf(dest, 255, L"pass if (%02x & %02x) %S (a & %02x)", ref, mask, alphaTestFuncs[func], mask);
510
}
511
} else {
512
swprintf(dest, 255, L"%06x", value);
513
}
514
}
515
break;
516
517
case CMD_FMT_ZTEST:
518
{
519
static const char *zTestFuncs[] = { "NEVER", "ALWAYS", "==", "!=", "<", "<=", ">", ">=" };
520
if (value < (u32)ARRAY_SIZE(zTestFuncs)) {
521
swprintf(dest, 255, L"pass if src %S dst", zTestFuncs[value]);
522
} else {
523
swprintf(dest, 255, L"%06x", value);
524
}
525
}
526
break;
527
528
case CMD_FMT_OFFSETADDR:
529
swprintf(dest, 255, L"%08x", gpuDebug->GetRelativeAddress(0));
530
break;
531
532
case CMD_FMT_VADDR:
533
swprintf(dest, 255, L"%08x", gpuDebug->GetVertexAddress());
534
break;
535
536
case CMD_FMT_IADDR:
537
swprintf(dest, 255, L"%08x", gpuDebug->GetIndexAddress());
538
break;
539
540
case CMD_FMT_MATERIALUPDATE:
541
{
542
static const char *materialTypes[] = {
543
"none",
544
"ambient",
545
"diffuse",
546
"ambient, diffuse",
547
"specular",
548
"ambient, specular",
549
"diffuse, specular",
550
"ambient, diffuse, specular",
551
};
552
if (value < (u32)ARRAY_SIZE(materialTypes)) {
553
swprintf(dest, 255, L"%S", materialTypes[value]);
554
} else {
555
swprintf(dest, 255, L"%06x", value);
556
}
557
}
558
break;
559
560
case CMD_FMT_SHADEMODEL:
561
if (value == 0) {
562
swprintf(dest, 255, L"flat");
563
} else if (value == 1) {
564
swprintf(dest, 255, L"gouraud");
565
} else {
566
swprintf(dest, 255, L"%06x", value);
567
}
568
break;
569
570
case CMD_FMT_STENCILOP:
571
{
572
static const char *stencilOps[] = { "KEEP", "ZERO", "REPLACE", "INVERT", "INCREMENT", "DECREMENT" };
573
const u8 sfail = (value >> 0) & 0xFF;
574
const u8 zfail = (value >> 8) & 0xFF;
575
const u8 pass = (value >> 16) & 0xFF;
576
const u8 totalValid = (u8)ARRAY_SIZE(stencilOps);
577
if (sfail < totalValid && zfail < totalValid && pass < totalValid) {
578
swprintf(dest, 255, L"fail=%S, pass/depthfail=%S, pass=%S", stencilOps[sfail], stencilOps[zfail], stencilOps[pass]);
579
} else {
580
swprintf(dest, 255, L"%06x", value);
581
}
582
}
583
break;
584
585
case CMD_FMT_BLENDMODE:
586
{
587
const char *blendModes[] = {
588
"add",
589
"subtract",
590
"reverse subtract",
591
"min",
592
"max",
593
"abs subtract",
594
};
595
const char *blendFactorsA[] = {
596
"dst",
597
"1.0 - dst",
598
"src.a",
599
"1.0 - src.a",
600
"dst.a",
601
"1.0 - dst.a",
602
"2.0 * src.a",
603
"1.0 - 2.0 * src.a",
604
"2.0 * dst.a",
605
"1.0 - 2.0 * dst.a",
606
"fixed",
607
};
608
const char *blendFactorsB[] = {
609
"src",
610
"1.0 - src",
611
"src.a",
612
"1.0 - src.a",
613
"dst.a",
614
"1.0 - dst.a",
615
"2.0 * src.a",
616
"1.0 - 2.0 * src.a",
617
"2.0 * dst.a",
618
"1.0 - 2.0 * dst.a",
619
"fixed",
620
};
621
const u8 blendFactorA = (value >> 0) & 0xF;
622
const u8 blendFactorB = (value >> 4) & 0xF;
623
const u32 blendMode = (value >> 8);
624
625
if (blendFactorA < (u8)ARRAY_SIZE(blendFactorsA) && blendFactorB < (u8)ARRAY_SIZE(blendFactorsB) && blendMode < (u32)ARRAY_SIZE(blendModes)) {
626
swprintf(dest, 255, L"%S: %S, %S", blendModes[blendMode], blendFactorsA[blendFactorA], blendFactorsB[blendFactorB]);
627
} else {
628
swprintf(dest, 255, L"%06x", value);
629
}
630
}
631
break;
632
633
case CMD_FMT_CLEARMODE:
634
if (value == 0) {
635
swprintf(dest, 255, L"%d", value);
636
} else if ((value & ~(GE_CLEARMODE_ALL | 1)) == 0) {
637
const char *clearmodes[] = {
638
"1, write disabled",
639
"1, write color",
640
"1, write alpha/stencil",
641
"1, write color, alpha/stencil",
642
"1, write depth",
643
"1, write color, depth",
644
"1, write alpha/stencil, depth",
645
"1, write color, alpha/stencil, depth",
646
};
647
swprintf(dest, 255, L"%S", clearmodes[value >> 8]);
648
} else {
649
swprintf(dest, 255, L"%06x", value);
650
}
651
break;
652
653
case CMD_FMT_TEXFUNC:
654
{
655
const char *texfuncs[] = {
656
"modulate",
657
"decal",
658
"blend",
659
"replace",
660
"add",
661
};
662
const u8 func = (value >> 0) & 0xFF;
663
const u8 rgba = (value >> 8) & 0xFF;
664
const u8 colorDouble = (value >> 16) & 0xFF;
665
666
if (rgba <= 1 && colorDouble <= 1 && func < (u8)ARRAY_SIZE(texfuncs)) {
667
swprintf(dest, 255, L"%S, %S%S", texfuncs[func], rgba ? "RGBA" : "RGB", colorDouble ? ", color doubling" : "");
668
} else {
669
swprintf(dest, 255, L"%06x", value);
670
}
671
}
672
break;
673
674
case CMD_FMT_TEXMODE:
675
{
676
const u8 swizzle = (value >> 0) & 0xFF;
677
const u8 clutLevels = (value >> 8) & 0xFF;
678
const u8 maxLevel = (value >> 16) & 0xFF;
679
680
if (swizzle <= 1 && clutLevels <= 1 && maxLevel <= 7) {
681
swprintf(dest, 255, L"%S%d levels%S", swizzle ? "swizzled, " : "", maxLevel + 1, clutLevels ? ", CLUT per level" : "");
682
} else {
683
swprintf(dest, 255, L"%06x", value);
684
}
685
}
686
break;
687
688
case CMD_FMT_LOGICOP:
689
{
690
const char *logicOps[] = {
691
"clear",
692
"and",
693
"reverse and",
694
"copy",
695
"inverted and",
696
"noop",
697
"xor",
698
"or",
699
"negated or",
700
"equivalence",
701
"inverted",
702
"reverse or",
703
"inverted copy",
704
"inverted or",
705
"negated and",
706
"set",
707
};
708
709
if (value < ARRAY_SIZE(logicOps)) {
710
swprintf(dest, 255, L"%S", logicOps[value]);
711
} else {
712
swprintf(dest, 255, L"%06x", value);
713
}
714
}
715
break;
716
717
case CMD_FMT_TEXWRAP:
718
{
719
if ((value & ~0x0101) == 0) {
720
const bool clampS = (value & 0x0001) != 0;
721
const bool clampT = (value & 0x0100) != 0;
722
swprintf(dest, 255, L"%S s, %S t", clampS ? "clamp" : "wrap", clampT ? "clamp" : "wrap");
723
} else {
724
swprintf(dest, 255, L"%06x", value);
725
}
726
}
727
break;
728
729
case CMD_FMT_TEXLEVEL:
730
{
731
static constexpr std::array<const char*, 3> mipLevelModes = {
732
"auto + bias",
733
"bias",
734
"slope + bias",
735
};
736
const int mipLevel = value & 0xFFFF;
737
const int biasFixed = (s8)(value >> 16);
738
const float bias = (float)biasFixed / 16.0f;
739
740
if (mipLevel == 0 || mipLevel == 1 || mipLevel == 2) {
741
swprintf(dest, 255, L"%S: %f", mipLevelModes[mipLevel], bias);
742
} else {
743
swprintf(dest, 255, L"%06x", value);
744
}
745
}
746
break;
747
748
case CMD_FMT_TEXFILTER:
749
{
750
const char *textureFilters[] = {
751
"nearest",
752
"linear",
753
NULL,
754
NULL,
755
"nearest, mipmap nearest",
756
"linear, mipmap nearest",
757
"nearest, mipmap linear",
758
"linear, mipmap linear",
759
};
760
if ((value & ~0x0107) == 0 && textureFilters[value & 7] != NULL) {
761
const int min = (value & 0x0007) >> 0;
762
const int mag = (value & 0x0100) >> 8;
763
swprintf(dest, 255, L"min: %S, mag: %S", textureFilters[min], textureFilters[mag]);
764
} else {
765
swprintf(dest, 255, L"%06x", value);
766
}
767
}
768
break;
769
770
case CMD_FMT_TEXMAPMODE:
771
{
772
static constexpr std::array<const char*, 4> uvGenModes = {
773
"tex coords",
774
"tex matrix",
775
"tex env map",
776
"unknown (tex coords?)",
777
};
778
static constexpr std::array<const char*, 4> uvProjModes = {
779
"pos",
780
"uv",
781
"normalized normal",
782
"normal",
783
};
784
if ((value & ~0x0303) == 0) {
785
const int uvGen = (value & 0x0003) >> 0;
786
const int uvProj = (value & 0x0300) >> 8;
787
swprintf(dest, 255, L"gen: %S, proj: %S", uvGenModes[uvGen], uvProjModes[uvProj]);
788
} else {
789
swprintf(dest, 255, L"%06x", value);
790
}
791
}
792
break;
793
794
case CMD_FMT_TEXSHADELS:
795
if ((value & ~0x0303) == 0) {
796
const int sLight = (value & 0x0003) >> 0;
797
const int tLight = (value & 0x0300) >> 8;
798
swprintf(dest, 255, L"s: %d, t: %d", sLight, tLight);
799
} else {
800
swprintf(dest, 255, L"%06x", value);
801
}
802
break;
803
804
case CMD_FMT_LIGHTMODE:
805
if (value == 0) {
806
swprintf(dest, 255, L"mixed color");
807
} else if (value == 1) {
808
swprintf(dest, 255, L"separate specular");
809
} else {
810
swprintf(dest, 255, L"%06x", value);
811
}
812
break;
813
814
case CMD_FMT_LIGHTTYPE:
815
{
816
static constexpr std::array<const char*, 4> lightComputations = {
817
"diffuse",
818
"diffuse + spec",
819
"pow(diffuse)",
820
"unknown (diffuse?)",
821
};
822
static constexpr std::array<const char*, 4> lightTypes = {
823
"directional",
824
"point",
825
"spot",
826
"unknown (directional?)",
827
};
828
if ((value & ~0x0303) == 0) {
829
const int comp = (value & 0x0003) >> 0;
830
const int type = (value & 0x0300) >> 8;
831
swprintf(dest, 255, L"type: %S, comp: %S", lightTypes[type], lightComputations[comp]);
832
} else {
833
swprintf(dest, 255, L"%06x", value);
834
}
835
}
836
break;
837
838
case CMD_FMT_CULL:
839
if (value == 0) {
840
swprintf(dest, 255, L"front (CW)");
841
} else if (value == 1) {
842
swprintf(dest, 255, L"back (CCW)");
843
} else {
844
swprintf(dest, 255, L"%06x", value);
845
}
846
break;
847
848
case CMD_FMT_PATCHPRIMITIVE:
849
{
850
const char *patchPrims[] = {
851
"triangles",
852
"lines",
853
"points",
854
};
855
if (value < (u32)ARRAY_SIZE(patchPrims)) {
856
swprintf(dest, 255, L"%S", patchPrims[value]);
857
} else {
858
swprintf(dest, 255, L"%06x", value);
859
}
860
}
861
break;
862
863
case CMD_FMT_FLAG:
864
if ((value & ~1) == 0) {
865
swprintf(dest, 255, L"%d", value);
866
} else {
867
swprintf(dest, 255, L"%06x", value);
868
}
869
break;
870
871
default:
872
swprintf(dest, 255, L"BAD FORMAT %06x", value);
873
}
874
875
// TODO: Turn row grey or some such?
876
if (!enabled) {
877
wcscat(dest, L" (disabled)");
878
}
879
}
880
881
void CtrlStateValues::GetColumnText(wchar_t *dest, int row, int col) {
882
if (row < 0 || row >= rowCount_) {
883
return;
884
}
885
886
switch (col) {
887
case STATEVALUES_COL_BREAKPOINT:
888
wcscpy(dest, L" ");
889
break;
890
891
case STATEVALUES_COL_NAME:
892
wcscpy(dest, rows_[row].title);
893
break;
894
895
case STATEVALUES_COL_VALUE:
896
{
897
if (gpuDebug == NULL) {
898
wcscpy(dest, L"N/A");
899
break;
900
}
901
902
const auto info = rows_[row];
903
const auto state = gpuDebug->GetGState();
904
const bool enabled = info.enableCmd == 0 || (state.cmdmem[info.enableCmd] & 1) == 1;
905
const u32 value = state.cmdmem[info.cmd] & 0xFFFFFF;
906
const u32 otherValue = state.cmdmem[info.otherCmd] & 0xFFFFFF;
907
const u32 otherValue2 = state.cmdmem[info.otherCmd2] & 0xFFFFFF;
908
909
FormatStateRow(dest, info, value, enabled, otherValue, otherValue2);
910
break;
911
}
912
}
913
}
914
915
void CtrlStateValues::OnDoubleClick(int row, int column) {
916
if (gpuDebug == nullptr || row >= rowCount_) {
917
return;
918
}
919
920
const auto info = rows_[row];
921
922
if (column == STATEVALUES_COL_BREAKPOINT) {
923
bool proceed = true;
924
if (GetCmdBreakpointCond(info.cmd, nullptr)) {
925
int ret = MessageBox(GetHandle(), L"This breakpoint has a custom condition.\nDo you want to remove it?", L"Confirmation", MB_YESNO);
926
proceed = ret == IDYES;
927
}
928
if (proceed)
929
SetItemState(row, ToggleBreakpoint(info) ? 1 : 0);
930
return;
931
}
932
933
switch (info.fmt) {
934
case CMD_FMT_FLAG:
935
{
936
const auto state = gpuDebug->GetGState();
937
u32 newValue = state.cmdmem[info.cmd] ^ 1;
938
SetCmdValue(newValue);
939
}
940
break;
941
942
default:
943
{
944
wchar_t title[1024];
945
const auto state = gpuDebug->GetGState();
946
947
u32 newValue = state.cmdmem[info.cmd] & 0x00FFFFFF;
948
swprintf(title, 1023, L"New value for %s", info.title);
949
if (PromptStateValue(info, GetHandle(), title, newValue)) {
950
newValue |= state.cmdmem[info.cmd] & 0xFF000000;
951
SetCmdValue(newValue);
952
953
if (info.otherCmd) {
954
newValue = state.cmdmem[info.otherCmd] & 0x00FFFFFF;
955
swprintf(title, 1023, L"New value for %s (secondary)", info.title);
956
if (PromptStateValue(info, GetHandle(), title, newValue)) {
957
newValue |= state.cmdmem[info.otherCmd] & 0xFF000000;
958
SetCmdValue(newValue);
959
960
if (info.otherCmd2) {
961
newValue = state.cmdmem[info.otherCmd2] & 0x00FFFFFF;
962
swprintf(title, 1023, L"New value for %s (tertiary)", info.title);
963
if (PromptStateValue(info, GetHandle(), title, newValue)) {
964
newValue |= state.cmdmem[info.otherCmd2] & 0xFF000000;
965
SetCmdValue(newValue);
966
}
967
}
968
}
969
}
970
}
971
}
972
break;
973
}
974
}
975
976
void CtrlStateValues::OnRightClick(int row, int column, const POINT &point) {
977
if (gpuDebug == nullptr) {
978
return;
979
}
980
981
const auto info = rows_[row];
982
const auto state = gpuDebug->GetGState();
983
984
POINT screenPt(point);
985
ClientToScreen(GetHandle(), &screenPt);
986
987
HMENU subMenu = GetContextMenu(ContextMenuID::GEDBG_STATE);
988
SetMenuDefaultItem(subMenu, ID_REGLIST_CHANGE, FALSE);
989
EnableMenuItem(subMenu, ID_GEDBG_SETCOND, GPUBreakpoints::IsCmdBreakpoint(info.cmd) ? MF_ENABLED : MF_GRAYED);
990
991
// Ehh, kinda ugly.
992
if (!watchList.empty() && rows_ == &watchList[0]) {
993
ModifyMenu(subMenu, ID_GEDBG_WATCH, MF_BYCOMMAND | MF_STRING, ID_GEDBG_WATCH, L"Remove Watch");
994
} else {
995
ModifyMenu(subMenu, ID_GEDBG_WATCH, MF_BYCOMMAND | MF_STRING, ID_GEDBG_WATCH, L"Add Watch");
996
}
997
if (info.fmt == CMD_FMT_FLAG) {
998
ModifyMenu(subMenu, ID_REGLIST_CHANGE, MF_BYCOMMAND | MF_STRING, ID_REGLIST_CHANGE, L"Toggle Flag");
999
} else {
1000
ModifyMenu(subMenu, ID_REGLIST_CHANGE, MF_BYCOMMAND | MF_STRING, ID_REGLIST_CHANGE, L"Change...");
1001
}
1002
1003
switch (TriggerContextMenu(ContextMenuID::GEDBG_STATE, GetHandle(), ContextPoint::FromClient(point)))
1004
{
1005
case ID_DISASM_TOGGLEBREAKPOINT: {
1006
bool proceed = true;
1007
if (GetCmdBreakpointCond(info.cmd, nullptr)) {
1008
int ret = MessageBox(GetHandle(), L"This breakpoint has a custom condition.\nDo you want to remove it?", L"Confirmation", MB_YESNO);
1009
proceed = ret == IDYES;
1010
}
1011
if (proceed)
1012
SetItemState(row, ToggleBreakpoint(info) ? 1 : 0);
1013
break;
1014
}
1015
1016
case ID_GEDBG_SETCOND:
1017
PromptBreakpointCond(info);
1018
break;
1019
1020
case ID_DISASM_COPYINSTRUCTIONHEX: {
1021
char temp[16];
1022
snprintf(temp, sizeof(temp), "%08x", gstate.cmdmem[info.cmd] & 0x00FFFFFF);
1023
W32Util::CopyTextToClipboard(GetHandle(), temp);
1024
break;
1025
}
1026
1027
case ID_DISASM_COPYINSTRUCTIONDISASM: {
1028
const bool enabled = info.enableCmd == 0 || (state.cmdmem[info.enableCmd] & 1) == 1;
1029
const u32 value = state.cmdmem[info.cmd] & 0xFFFFFF;
1030
const u32 otherValue = state.cmdmem[info.otherCmd] & 0xFFFFFF;
1031
const u32 otherValue2 = state.cmdmem[info.otherCmd2] & 0xFFFFFF;
1032
1033
wchar_t dest[512];
1034
FormatStateRow(dest, info, value, enabled, otherValue, otherValue2);
1035
W32Util::CopyTextToClipboard(GetHandle(), dest);
1036
break;
1037
}
1038
1039
case ID_GEDBG_COPYALL:
1040
CopyRows(0, GetRowCount());
1041
break;
1042
1043
case ID_REGLIST_CHANGE:
1044
OnDoubleClick(row, STATEVALUES_COL_VALUE);
1045
break;
1046
1047
case ID_GEDBG_WATCH:
1048
ToggleWatchList(info);
1049
SendMessage(GetParent(GetParent(GetHandle())), WM_GEDBG_UPDATE_WATCH, 0, 0);
1050
break;
1051
}
1052
}
1053
1054
bool CtrlStateValues::OnRowPrePaint(int row, LPNMLVCUSTOMDRAW msg) {
1055
if (gpuDebug && RowValuesChanged(row)) {
1056
msg->clrText = RGB(255, 0, 0);
1057
return true;
1058
}
1059
return false;
1060
}
1061
1062
void CtrlStateValues::SetCmdValue(u32 op) {
1063
SendMessage(GetParent(GetParent(GetHandle())), WM_GEDBG_SETCMDWPARAM, op, NULL);
1064
Update();
1065
}
1066
1067
bool CtrlStateValues::RowValuesChanged(int row) {
1068
_assert_(gpuDebug != nullptr && row >= 0 && row < rowCount_);
1069
1070
const auto info = rows_[row];
1071
const auto state = gpuDebug->GetGState();
1072
const auto lastState = GPUStepping::LastState();
1073
1074
if (state.cmdmem[info.cmd] != lastState.cmdmem[info.cmd])
1075
return true;
1076
if (info.otherCmd && state.cmdmem[info.otherCmd] != lastState.cmdmem[info.otherCmd])
1077
return true;
1078
if (info.otherCmd2 && state.cmdmem[info.otherCmd2] != lastState.cmdmem[info.otherCmd2])
1079
return true;
1080
1081
return false;
1082
}
1083
1084
void CtrlStateValues::PromptBreakpointCond(const TabStateRow &info) {
1085
std::string expression;
1086
GPUBreakpoints::GetCmdBreakpointCond(info.cmd, &expression);
1087
if (!InputBox_GetString(GetModuleHandle(NULL), GetHandle(), L"Expression", expression, expression))
1088
return;
1089
1090
std::string error;
1091
if (!GPUBreakpoints::SetCmdBreakpointCond(info.cmd, expression, &error)) {
1092
MessageBox(GetHandle(), ConvertUTF8ToWString(error).c_str(), L"Invalid expression", MB_OK | MB_ICONEXCLAMATION);
1093
} else {
1094
if (info.otherCmd)
1095
GPUBreakpoints::SetCmdBreakpointCond(info.otherCmd, expression, &error);
1096
if (info.otherCmd2)
1097
GPUBreakpoints::SetCmdBreakpointCond(info.otherCmd2, expression, &error);
1098
}
1099
1100
}
1101
1102
TabStateValues::TabStateValues(const TabStateRow *rows, int rowCount, LPCSTR dialogID, HINSTANCE _hInstance, HWND _hParent)
1103
: Dialog(dialogID, _hInstance, _hParent) {
1104
values = new CtrlStateValues(rows, rowCount, GetDlgItem(m_hDlg, IDC_GEDBG_VALUES));
1105
}
1106
1107
TabStateValues::~TabStateValues() {
1108
delete values;
1109
}
1110
1111
void TabStateValues::UpdateSize(WORD width, WORD height) {
1112
struct Position {
1113
int x,y;
1114
int w,h;
1115
};
1116
1117
Position position;
1118
static const int borderMargin = 5;
1119
1120
position.x = borderMargin;
1121
position.y = borderMargin;
1122
position.w = width - 2 * borderMargin;
1123
position.h = height - 2 * borderMargin;
1124
1125
HWND handle = GetDlgItem(m_hDlg,IDC_GEDBG_VALUES);
1126
MoveWindow(handle, position.x, position.y, position.w, position.h, TRUE);
1127
}
1128
1129
BOOL TabStateValues::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
1130
switch (message) {
1131
case WM_INITDIALOG:
1132
return TRUE;
1133
1134
case WM_SIZE:
1135
UpdateSize(LOWORD(lParam), HIWORD(lParam));
1136
return TRUE;
1137
1138
case WM_NOTIFY:
1139
switch (wParam)
1140
{
1141
case IDC_GEDBG_VALUES:
1142
SetWindowLongPtr(m_hDlg, DWLP_MSGRESULT, values->HandleNotify(lParam));
1143
return TRUE;
1144
}
1145
break;
1146
}
1147
1148
return FALSE;
1149
}
1150
1151
TabStateFlags::TabStateFlags(HINSTANCE _hInstance, HWND _hParent)
1152
: TabStateValues(stateFlagsRows, ARRAY_SIZE(stateFlagsRows), (LPCSTR)IDD_GEDBG_TAB_VALUES, _hInstance, _hParent) {
1153
}
1154
1155
TabStateLighting::TabStateLighting(HINSTANCE _hInstance, HWND _hParent)
1156
: TabStateValues(stateLightingRows, ARRAY_SIZE(stateLightingRows), (LPCSTR)IDD_GEDBG_TAB_VALUES, _hInstance, _hParent) {
1157
}
1158
1159
TabStateSettings::TabStateSettings(HINSTANCE _hInstance, HWND _hParent)
1160
: TabStateValues(stateSettingsRows, ARRAY_SIZE(stateSettingsRows), (LPCSTR)IDD_GEDBG_TAB_VALUES, _hInstance, _hParent) {
1161
}
1162
1163
TabStateTexture::TabStateTexture(HINSTANCE _hInstance, HWND _hParent)
1164
: TabStateValues(stateTextureRows, ARRAY_SIZE(stateTextureRows), (LPCSTR)IDD_GEDBG_TAB_VALUES, _hInstance, _hParent) {
1165
}
1166
1167
TabStateWatch::TabStateWatch(HINSTANCE _hInstance, HWND _hParent)
1168
: TabStateValues(nullptr, 0, (LPCSTR)IDD_GEDBG_TAB_VALUES, _hInstance, _hParent) {
1169
}
1170
1171
void TabStateWatch::Update() {
1172
if (watchList.empty()) {
1173
values->UpdateRows(nullptr, 0);
1174
} else {
1175
values->UpdateRows(&watchList[0], (int)watchList.size());
1176
}
1177
TabStateValues::Update();
1178
}
1179
1180