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