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/GPU/Common/GPUDebugInterface.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/Log.h"
19
#include "Common/Math/expression_parser.h"
20
#include "Common/StringUtils.h"
21
#include "Core/Debugger/SymbolMap.h"
22
#include "GPU/Common/GPUDebugInterface.h"
23
#include "GPU/Debugger/Debugger.h"
24
#include "GPU/Debugger/GECommandTable.h"
25
#include "GPU/GPUState.h"
26
27
enum class GEReferenceIndex : uint32_t {
28
VADDR = 0x100,
29
IADDR,
30
OFFSET,
31
PC,
32
STALL,
33
BFLAG,
34
OP,
35
DATA,
36
CLUTADDR,
37
TRANSFERSRC,
38
TRANSFERDST,
39
PRIMCOUNT,
40
LASTPRIMCOUNT,
41
42
TEXADDR0,
43
TEXADDR1,
44
TEXADDR2,
45
TEXADDR3,
46
TEXADDR4,
47
TEXADDR5,
48
TEXADDR6,
49
TEXADDR7,
50
51
BONE_MATRIX = 0x200,
52
WORLD_MATRIX = 0x260,
53
VIEW_MATRIX = 0x26C,
54
PROJ_MATRIX = 0x278,
55
TGEN_MATRIX = 0x288,
56
MATRIX_END = 0x294,
57
58
FIELD_START = 0x1000,
59
FIELD_END = 0xFF000,
60
};
61
ENUM_CLASS_BITOPS(GEReferenceIndex);
62
63
struct ReferenceName {
64
GEReferenceIndex index;
65
const char *name;
66
};
67
68
static constexpr ReferenceName referenceNames[] = {
69
{ GEReferenceIndex::VADDR, "vaddr" },
70
{ GEReferenceIndex::IADDR, "iaddr" },
71
{ GEReferenceIndex::OFFSET, "offset" },
72
{ GEReferenceIndex::PC, "pc" },
73
{ GEReferenceIndex::STALL, "stall" },
74
{ GEReferenceIndex::BFLAG, "bflag" },
75
{ GEReferenceIndex::BFLAG, "boundflag" },
76
{ GEReferenceIndex::OP, "op" },
77
{ GEReferenceIndex::DATA, "data" },
78
{ GEReferenceIndex::CLUTADDR, "clutaddr" },
79
{ GEReferenceIndex::TRANSFERSRC, "transfersrc" },
80
{ GEReferenceIndex::TRANSFERDST, "transferdst" },
81
{ GEReferenceIndex::PRIMCOUNT, "primcount" },
82
{ GEReferenceIndex::LASTPRIMCOUNT, "lastprimcount" },
83
{ GEReferenceIndex::TEXADDR0, "texaddr0" },
84
{ GEReferenceIndex::TEXADDR1, "texaddr1" },
85
{ GEReferenceIndex::TEXADDR2, "texaddr2" },
86
{ GEReferenceIndex::TEXADDR3, "texaddr3" },
87
{ GEReferenceIndex::TEXADDR4, "texaddr4" },
88
{ GEReferenceIndex::TEXADDR5, "texaddr5" },
89
{ GEReferenceIndex::TEXADDR6, "texaddr6" },
90
{ GEReferenceIndex::TEXADDR7, "texaddr7" },
91
};
92
93
enum class GECmdField : uint8_t {
94
DATA, // Alias for the entire data.
95
LOW_FLAG,
96
LOW_U2,
97
LOW_U4,
98
LOW_U7,
99
LOW_U8,
100
LOW_U10,
101
LOW_U10_P1,
102
LOW_U11,
103
LOW_U16,
104
MID_U8,
105
MID_U10, // At 10, 10 bits.
106
MID_U10_P1, // At 10, 10 bits (add 1 to value.)
107
TOP_U8,
108
FLAG_AFTER_1, // At 1, 1 bit.
109
FLAG_AFTER_2, // At 2, 1 bit.
110
FLAG_AFTER_8, // At 8, 1 bit.
111
FLAG_AFTER_9, // At 9, 1 bit.
112
FLAG_AFTER_10, // At 10, 1 bit.
113
FLAG_AFTER_11, // At 11, 1 bit.
114
FLAG_AFTER_16, // At 16, 1 bit.
115
FLAG_AFTER_17, // At 17, 1 bit.
116
FLAG_AFTER_18, // At 18, 1 bit.
117
FLAG_AFTER_19, // At 19, 1 bit.
118
FLAG_AFTER_20, // At 20, 1 bit.
119
FLAG_AFTER_21, // At 21, 1 bit.
120
FLAG_AFTER_22, // At 22, 1 bit.
121
FLAG_AFTER_23, // At 23, 1 bit.
122
U2_AFTER_8, // At 8, 2 bits.
123
U3_AFTER_16, // At 16, 3 bits.
124
U12_AFTER_4, // At 4, 12 bits.
125
PRIM_TYPE, // At 16, 3 bits.
126
SIGNAL_TYPE, // At 16, 8 bits.
127
VTYPE_TC, // At 0, 2 bits.
128
VTYPE_COL, // At 2, 3 bits.
129
VTYPE_NRM, // At 5, 2 bits.
130
VTYPE_POS, // At 7, 2 bits.
131
VTYPE_WEIGHTTYPE, // At 9, 2 bits.
132
VTYPE_INDEX, // At 11, 2 bits.
133
VTYPE_WEIGHTCOUNT, // At 14, 3 bits.
134
VTYPE_MORPHCOUNT, // At 18, 3 bits.
135
PATCH_PRIM_TYPE, // At 0, 2 bits.
136
LIGHT_COMP, // At 0, 2 bits.
137
LIGHT_TYPE, // At 8, 2 bits.
138
LIGHT_TYPE_SPECULAR, // 1 if comp is 1 (but not 3.)
139
HIGH_ADDR, // At 16, 8 bits moved left to top 8 bits.
140
TEX_W, // At 0, 4 bits - 1 to this power.
141
TEX_H, // At 8, 4 bits - 1 to this power.
142
UVGEN_TYPE, // At 0, 2 bits.
143
UVGEN_PROJ, // At 8, 2 bits.
144
TEX_FORMAT, // At 0, 4 bits.
145
TEX_MINFILTER, // At 0, 3 bits.
146
TEX_MAGFILTER, // At 8, 1 bit.
147
TEX_LEVEL_MODE, // At 0, 2 bits.
148
LOW_U12_4_FLOAT, // At 0, 12.4 converted to float.
149
HIGH_S4_4_FLOAT, // At 16, s.3.4 converted to float.
150
TEX_FUNC, // At 0, 3 bits.
151
CLUT_BYTES, // At 0, 6 bits, multiplied by 8.
152
CLUT_FORMAT, // At 0, 2 bits.
153
CLUT_SHIFT, // At 2, 5 bits.
154
CLUT_OFFSET, // At 16, 5 bits, multiplied by 16.
155
COMPARE_FUNC2, // At 0, 2 bits.
156
COMPARE_FUNC3, // At 0, 3 bits.
157
STENCIL_OP_AT_0, // At 0, 3 bits.
158
STENCIL_OP_AT_8, // At 8, 3 bits.
159
STENCIL_OP_AT_16, // At 16, 3 bits.
160
BLEND_SRC, // At 0, 4 bits.
161
BLEND_DST, // At 4, 4 bits.
162
BLEND_EQUATION, // At 8, 3 bits.
163
LOGIC_OP, // At 0, 4 bits.
164
};
165
166
struct FieldName {
167
GECmdFormat fmt;
168
GECmdField field;
169
const char *name;
170
};
171
172
static constexpr FieldName fieldNames[] = {
173
{ GECmdFormat::PRIM, GECmdField::LOW_U16, "count" },
174
{ GECmdFormat::PRIM, GECmdField::PRIM_TYPE, "type" },
175
{ GECmdFormat::BEZIER, GECmdField::LOW_U8, "ucount" },
176
{ GECmdFormat::BEZIER, GECmdField::LOW_U8, "u" },
177
{ GECmdFormat::BEZIER, GECmdField::MID_U8, "vcount" },
178
{ GECmdFormat::BEZIER, GECmdField::MID_U8, "v" },
179
{ GECmdFormat::SPLINE, GECmdField::LOW_U8, "ucount" },
180
{ GECmdFormat::SPLINE, GECmdField::LOW_U8, "u" },
181
{ GECmdFormat::SPLINE, GECmdField::MID_U8, "vcount" },
182
{ GECmdFormat::SPLINE, GECmdField::MID_U8, "v" },
183
{ GECmdFormat::SPLINE, GECmdField::FLAG_AFTER_16, "ufirstopen" },
184
{ GECmdFormat::SPLINE, GECmdField::FLAG_AFTER_17, "ulastopen" },
185
{ GECmdFormat::SPLINE, GECmdField::FLAG_AFTER_18, "vfirstopen" },
186
{ GECmdFormat::SPLINE, GECmdField::FLAG_AFTER_19, "vlastopen" },
187
{ GECmdFormat::SIGNAL, GECmdField::LOW_U16, "data" },
188
{ GECmdFormat::SIGNAL, GECmdField::SIGNAL_TYPE, "type" },
189
{ GECmdFormat::VERTEX_TYPE, GECmdField::VTYPE_TC, "texcoord" },
190
{ GECmdFormat::VERTEX_TYPE, GECmdField::VTYPE_TC, "tc" },
191
{ GECmdFormat::VERTEX_TYPE, GECmdField::VTYPE_COL, "col" },
192
{ GECmdFormat::VERTEX_TYPE, GECmdField::VTYPE_COL, "color" },
193
{ GECmdFormat::VERTEX_TYPE, GECmdField::VTYPE_NRM, "normal" },
194
{ GECmdFormat::VERTEX_TYPE, GECmdField::VTYPE_POS, "pos" },
195
{ GECmdFormat::VERTEX_TYPE, GECmdField::VTYPE_POS, "position" },
196
{ GECmdFormat::VERTEX_TYPE, GECmdField::VTYPE_WEIGHTTYPE, "weighttype" },
197
{ GECmdFormat::VERTEX_TYPE, GECmdField::VTYPE_WEIGHTTYPE, "weight" },
198
{ GECmdFormat::VERTEX_TYPE, GECmdField::VTYPE_INDEX, "index" },
199
{ GECmdFormat::VERTEX_TYPE, GECmdField::VTYPE_WEIGHTCOUNT, "weightcount" },
200
{ GECmdFormat::VERTEX_TYPE, GECmdField::VTYPE_MORPHCOUNT, "morphcount" },
201
{ GECmdFormat::VERTEX_TYPE, GECmdField::FLAG_AFTER_23, "through" },
202
{ GECmdFormat::VERTEX_TYPE, GECmdField::FLAG_AFTER_23, "throughmode" },
203
{ GECmdFormat::X10_Y10, GECmdField::LOW_U10, "x" },
204
{ GECmdFormat::X10_Y10, GECmdField::MID_U10, "y" },
205
{ GECmdFormat::X10_Y10, GECmdField::LOW_U10_P1, "w" },
206
{ GECmdFormat::X10_Y10, GECmdField::MID_U10_P1, "h" },
207
{ GECmdFormat::FLAG, GECmdField::LOW_FLAG, "flag" },
208
{ GECmdFormat::BONE_NUM, GECmdField::LOW_U7, "num" },
209
{ GECmdFormat::MATRIX_NUM, GECmdField::LOW_U4, "num" },
210
{ GECmdFormat::FLOAT, GECmdField::DATA, "data" },
211
{ GECmdFormat::PATCH_DIVISION, GECmdField::LOW_U8, "u" },
212
{ GECmdFormat::PATCH_DIVISION, GECmdField::MID_U8, "v" },
213
{ GECmdFormat::PATCH_PRIM, GECmdField::PATCH_PRIM_TYPE, "type" },
214
{ GECmdFormat::SUBPIXEL_COORD, GECmdField::LOW_U4, "frac" },
215
{ GECmdFormat::SUBPIXEL_COORD, GECmdField::LOW_U4, "sub" },
216
{ GECmdFormat::SUBPIXEL_COORD, GECmdField::LOW_U4, "subpixels" },
217
{ GECmdFormat::SUBPIXEL_COORD, GECmdField::U12_AFTER_4, "int" },
218
{ GECmdFormat::SUBPIXEL_COORD, GECmdField::U12_AFTER_4, "integer" },
219
{ GECmdFormat::SUBPIXEL_COORD, GECmdField::LOW_U12_4_FLOAT, "pixels" },
220
{ GECmdFormat::MATERIAL_UPDATE, GECmdField::LOW_FLAG, "ambient" },
221
{ GECmdFormat::MATERIAL_UPDATE, GECmdField::FLAG_AFTER_1, "diffuse" },
222
{ GECmdFormat::MATERIAL_UPDATE, GECmdField::FLAG_AFTER_2, "specular" },
223
{ GECmdFormat::RGB, GECmdField::LOW_U8, "r" },
224
{ GECmdFormat::RGB, GECmdField::LOW_U8, "red" },
225
{ GECmdFormat::RGB, GECmdField::MID_U8, "g" },
226
{ GECmdFormat::RGB, GECmdField::MID_U8, "green" },
227
{ GECmdFormat::RGB, GECmdField::TOP_U8, "b" },
228
{ GECmdFormat::RGB, GECmdField::TOP_U8, "blue" },
229
{ GECmdFormat::LIGHT_TYPE, GECmdField::LIGHT_COMP, "computation" },
230
{ GECmdFormat::LIGHT_TYPE, GECmdField::LIGHT_TYPE, "type" },
231
{ GECmdFormat::LIGHT_TYPE, GECmdField::LIGHT_TYPE_SPECULAR, "specular" },
232
{ GECmdFormat::STRIDE, GECmdField::LOW_U11, "stride" },
233
{ GECmdFormat::STRIDE_HIGH_ADDR, GECmdField::HIGH_ADDR, "highaddr" },
234
{ GECmdFormat::HIGH_ADDR, GECmdField::HIGH_ADDR, "highaddr" },
235
{ GECmdFormat::HIGH_ADDR_ONLY, GECmdField::HIGH_ADDR, "highaddr" },
236
{ GECmdFormat::TEX_SIZE, GECmdField::TEX_W, "w" },
237
{ GECmdFormat::TEX_SIZE, GECmdField::TEX_W, "width" },
238
{ GECmdFormat::TEX_SIZE, GECmdField::TEX_H, "h" },
239
{ GECmdFormat::TEX_SIZE, GECmdField::TEX_H, "height" },
240
{ GECmdFormat::TEX_MAP_MODE, GECmdField::UVGEN_TYPE, "type" },
241
{ GECmdFormat::TEX_MAP_MODE, GECmdField::UVGEN_TYPE, "uv" },
242
{ GECmdFormat::TEX_MAP_MODE, GECmdField::UVGEN_PROJ, "proj" },
243
{ GECmdFormat::TEX_MAP_MODE, GECmdField::UVGEN_PROJ, "factor" },
244
{ GECmdFormat::TEX_LIGHT_SRC, GECmdField::LOW_U2, "u" },
245
{ GECmdFormat::TEX_LIGHT_SRC, GECmdField::U2_AFTER_8, "v" },
246
{ GECmdFormat::TEX_MODE, GECmdField::LOW_FLAG, "swizzle" },
247
{ GECmdFormat::TEX_MODE, GECmdField::FLAG_AFTER_8, "separateclut" },
248
{ GECmdFormat::TEX_MODE, GECmdField::FLAG_AFTER_8, "separate" },
249
{ GECmdFormat::TEX_MODE, GECmdField::U3_AFTER_16, "maxlevel" },
250
{ GECmdFormat::TEX_MODE, GECmdField::U3_AFTER_16, "level" },
251
{ GECmdFormat::TEX_FORMAT, GECmdField::TEX_FORMAT, "format" },
252
{ GECmdFormat::TEX_FORMAT, GECmdField::TEX_FORMAT, "fmt" },
253
{ GECmdFormat::TEX_FORMAT, GECmdField::FLAG_AFTER_2, "indexed" },
254
{ GECmdFormat::TEX_FILTER, GECmdField::TEX_MINFILTER, "min" },
255
{ GECmdFormat::TEX_FILTER, GECmdField::TEX_MINFILTER, "minify" },
256
{ GECmdFormat::TEX_FILTER, GECmdField::TEX_MAGFILTER, "mag" },
257
{ GECmdFormat::TEX_FILTER, GECmdField::TEX_MAGFILTER, "magnify" },
258
{ GECmdFormat::TEX_CLAMP, GECmdField::LOW_FLAG, "s" },
259
{ GECmdFormat::TEX_CLAMP, GECmdField::FLAG_AFTER_8, "t" },
260
{ GECmdFormat::TEX_LEVEL_MODE, GECmdField::TEX_LEVEL_MODE, "mode" },
261
{ GECmdFormat::TEX_LEVEL_MODE, GECmdField::HIGH_S4_4_FLOAT, "bias" },
262
{ GECmdFormat::TEX_FUNC, GECmdField::TEX_FUNC, "func" },
263
{ GECmdFormat::TEX_FUNC, GECmdField::TEX_FUNC, "function" },
264
{ GECmdFormat::TEX_FUNC, GECmdField::FLAG_AFTER_8, "alpha" },
265
{ GECmdFormat::TEX_FUNC, GECmdField::FLAG_AFTER_8, "a" },
266
{ GECmdFormat::TEX_FUNC, GECmdField::FLAG_AFTER_16, "double" },
267
{ GECmdFormat::TEX_FUNC, GECmdField::FLAG_AFTER_16, "doubling" },
268
{ GECmdFormat::CLUT_FORMAT, GECmdField::CLUT_FORMAT, "format" },
269
{ GECmdFormat::CLUT_FORMAT, GECmdField::CLUT_FORMAT, "fmt" },
270
{ GECmdFormat::CLUT_FORMAT, GECmdField::CLUT_SHIFT, "shift" },
271
{ GECmdFormat::CLUT_FORMAT, GECmdField::MID_U8, "mask" },
272
{ GECmdFormat::CLUT_FORMAT, GECmdField::CLUT_OFFSET, "offset" },
273
{ GECmdFormat::CLUT_FORMAT, GECmdField::CLUT_OFFSET, "base" },
274
{ GECmdFormat::CLEAR_MODE, GECmdField::LOW_FLAG, "on" },
275
{ GECmdFormat::CLEAR_MODE, GECmdField::LOW_FLAG, "enable" },
276
{ GECmdFormat::CLEAR_MODE, GECmdField::LOW_FLAG, "flag" },
277
{ GECmdFormat::CLEAR_MODE, GECmdField::FLAG_AFTER_8, "color" },
278
{ GECmdFormat::CLEAR_MODE, GECmdField::FLAG_AFTER_9, "alpha" },
279
{ GECmdFormat::CLEAR_MODE, GECmdField::FLAG_AFTER_9, "stencil" },
280
{ GECmdFormat::CLEAR_MODE, GECmdField::FLAG_AFTER_10, "depth" },
281
{ GECmdFormat::COLOR_TEST_FUNC, GECmdField::COMPARE_FUNC2, "func" },
282
{ GECmdFormat::ALPHA_TEST, GECmdField::COMPARE_FUNC3, "func" },
283
{ GECmdFormat::ALPHA_TEST, GECmdField::MID_U8, "ref" },
284
{ GECmdFormat::ALPHA_TEST, GECmdField::MID_U8, "reference" },
285
{ GECmdFormat::ALPHA_TEST, GECmdField::TOP_U8, "mask" },
286
{ GECmdFormat::STENCIL_OP, GECmdField::STENCIL_OP_AT_0, "sfail" },
287
{ GECmdFormat::STENCIL_OP, GECmdField::STENCIL_OP_AT_8, "zfail" },
288
{ GECmdFormat::STENCIL_OP, GECmdField::STENCIL_OP_AT_16, "zpass" },
289
{ GECmdFormat::STENCIL_OP, GECmdField::STENCIL_OP_AT_16, "pass" },
290
{ GECmdFormat::DEPTH_TEST_FUNC, GECmdField::COMPARE_FUNC3, "func" },
291
{ GECmdFormat::BLEND_MODE, GECmdField::BLEND_SRC, "src" },
292
{ GECmdFormat::BLEND_MODE, GECmdField::BLEND_SRC, "srcfactor" },
293
{ GECmdFormat::BLEND_MODE, GECmdField::BLEND_DST, "dst" },
294
{ GECmdFormat::BLEND_MODE, GECmdField::BLEND_DST, "dstfactor" },
295
{ GECmdFormat::BLEND_MODE, GECmdField::BLEND_DST, "dest" },
296
{ GECmdFormat::BLEND_MODE, GECmdField::BLEND_DST, "destfactor" },
297
{ GECmdFormat::BLEND_MODE, GECmdField::BLEND_EQUATION, "eq" },
298
{ GECmdFormat::BLEND_MODE, GECmdField::BLEND_EQUATION, "equation" },
299
{ GECmdFormat::BLEND_MODE, GECmdField::BLEND_EQUATION, "mode" },
300
{ GECmdFormat::LOGIC_OP, GECmdField::LOGIC_OP, "op" },
301
{ GECmdFormat::LOGIC_OP, GECmdField::LOGIC_OP, "mode" },
302
{ GECmdFormat::ALPHA_PRIM, GECmdField::LOW_U8, "alpha" },
303
{ GECmdFormat::ALPHA_PRIM, GECmdField::PRIM_TYPE, "type" },
304
{ GECmdFormat::ALPHA_PRIM, GECmdField::PRIM_TYPE, "prim" },
305
{ GECmdFormat::ALPHA_PRIM, GECmdField::FLAG_AFTER_11, "antialias" },
306
// TODO: Clip bits?
307
{ GECmdFormat::ALPHA_PRIM, GECmdField::FLAG_AFTER_18, "shading" },
308
{ GECmdFormat::ALPHA_PRIM, GECmdField::FLAG_AFTER_18, "gouraud" },
309
{ GECmdFormat::ALPHA_PRIM, GECmdField::FLAG_AFTER_19, "cull" },
310
{ GECmdFormat::ALPHA_PRIM, GECmdField::FLAG_AFTER_20, "cullccw" },
311
{ GECmdFormat::ALPHA_PRIM, GECmdField::FLAG_AFTER_21, "tex" },
312
{ GECmdFormat::ALPHA_PRIM, GECmdField::FLAG_AFTER_22, "fog" },
313
{ GECmdFormat::ALPHA_PRIM, GECmdField::FLAG_AFTER_23, "dither" },
314
};
315
316
struct GECmdConstant {
317
const char *name;
318
uint32_t value;
319
};
320
321
// TODO: It would be nice if these were somehow typed...
322
static constexpr GECmdConstant constantNames[] = {
323
{ "GE_PRIM_POINTS", GE_PRIM_POINTS },
324
{ "GE_PRIM_LINES", GE_PRIM_LINES },
325
{ "GE_PRIM_LINE_STRIP", GE_PRIM_LINE_STRIP },
326
{ "GE_PRIM_TRIANGLES", GE_PRIM_TRIANGLES },
327
{ "GE_PRIM_TRIANGLE_STRIP", GE_PRIM_TRIANGLE_STRIP },
328
{ "GE_PRIM_TRIANGLE_FAN", GE_PRIM_TRIANGLE_FAN },
329
{ "GE_PRIM_RECTANGLES", GE_PRIM_RECTANGLES },
330
{ "GE_PRIM_KEEP_PREVIOUS", GE_PRIM_KEEP_PREVIOUS },
331
{ "POINTS", GE_PRIM_POINTS },
332
{ "LINES", GE_PRIM_LINES },
333
{ "LINE_STRIP", GE_PRIM_LINE_STRIP },
334
{ "TRIANGLES", GE_PRIM_TRIANGLES },
335
{ "TRIANGLE_STRIP", GE_PRIM_TRIANGLE_STRIP },
336
{ "TRIANGLE_FAN", GE_PRIM_TRIANGLE_FAN },
337
{ "RECTANGLES", GE_PRIM_RECTANGLES },
338
{ "SPRITES", GE_PRIM_RECTANGLES },
339
{ "KEEP_PREVIOUS", GE_PRIM_KEEP_PREVIOUS },
340
{ "CONTINUE", GE_PRIM_KEEP_PREVIOUS },
341
{ "GE_PATCHPRIM_TRIANGLES", GE_PATCHPRIM_TRIANGLES, },
342
{ "GE_PATCHPRIM_LINES", GE_PATCHPRIM_LINES, },
343
{ "GE_PATCHPRIM_POINTS", GE_PATCHPRIM_POINTS, },
344
{ "GE_SIGNAL_NONE", PSP_GE_SIGNAL_NONE },
345
{ "GE_SIGNAL_HANDLER_SUSPEND", PSP_GE_SIGNAL_HANDLER_SUSPEND },
346
{ "GE_SIGNAL_HANDLER_CONTINUE", PSP_GE_SIGNAL_HANDLER_CONTINUE },
347
{ "GE_SIGNAL_HANDLER_PAUSE", PSP_GE_SIGNAL_HANDLER_PAUSE },
348
{ "GE_SIGNAL_SYNC", PSP_GE_SIGNAL_SYNC },
349
{ "GE_SIGNAL_JUMP", PSP_GE_SIGNAL_JUMP },
350
{ "GE_SIGNAL_CALL", PSP_GE_SIGNAL_CALL },
351
{ "GE_SIGNAL_RET", PSP_GE_SIGNAL_RET },
352
{ "GE_SIGNAL_RJUMP", PSP_GE_SIGNAL_RJUMP },
353
{ "GE_SIGNAL_RCALL", PSP_GE_SIGNAL_RCALL },
354
{ "GE_SIGNAL_OJUMP", PSP_GE_SIGNAL_OJUMP },
355
{ "GE_SIGNAL_OCALL", PSP_GE_SIGNAL_OCALL },
356
{ "GE_VTYPE_TC_NONE", GE_VTYPE_TC_NONE >> GE_VTYPE_TC_SHIFT },
357
{ "GE_VTYPE_TC_8BIT", GE_VTYPE_TC_8BIT >> GE_VTYPE_TC_SHIFT },
358
{ "GE_VTYPE_TC_16BIT", GE_VTYPE_TC_16BIT >> GE_VTYPE_TC_SHIFT },
359
{ "GE_VTYPE_TC_FLOAT", GE_VTYPE_TC_FLOAT >> GE_VTYPE_TC_SHIFT },
360
{ "GE_VTYPE_COL_NONE", GE_VTYPE_COL_NONE >> GE_VTYPE_COL_SHIFT },
361
{ "GE_VTYPE_COL_565", GE_VTYPE_COL_565 >> GE_VTYPE_COL_SHIFT },
362
{ "GE_VTYPE_COL_5650", GE_VTYPE_COL_565 >> GE_VTYPE_COL_SHIFT },
363
{ "GE_VTYPE_COL_5551", GE_VTYPE_COL_5551 >> GE_VTYPE_COL_SHIFT },
364
{ "GE_VTYPE_COL_4444", GE_VTYPE_COL_4444 >> GE_VTYPE_COL_SHIFT },
365
{ "GE_VTYPE_COL_8888", GE_VTYPE_COL_8888 >> GE_VTYPE_COL_SHIFT },
366
{ "GE_VTYPE_NRM_NONE", GE_VTYPE_NRM_NONE >> GE_VTYPE_NRM_SHIFT },
367
{ "GE_VTYPE_NRM_8BIT", GE_VTYPE_NRM_8BIT >> GE_VTYPE_NRM_SHIFT },
368
{ "GE_VTYPE_NRM_16BIT", GE_VTYPE_NRM_16BIT >> GE_VTYPE_NRM_SHIFT },
369
{ "GE_VTYPE_NRM_FLOAT", GE_VTYPE_NRM_FLOAT >> GE_VTYPE_NRM_SHIFT },
370
{ "GE_VTYPE_POS_8BIT", GE_VTYPE_POS_8BIT >> GE_VTYPE_POS_SHIFT },
371
{ "GE_VTYPE_POS_16BIT", GE_VTYPE_POS_16BIT >> GE_VTYPE_POS_SHIFT },
372
{ "GE_VTYPE_POS_FLOAT", GE_VTYPE_POS_FLOAT >> GE_VTYPE_POS_SHIFT },
373
{ "GE_VTYPE_WEIGHT_NONE", GE_VTYPE_WEIGHT_NONE >> GE_VTYPE_WEIGHT_SHIFT },
374
{ "GE_VTYPE_WEIGHT_8BIT", GE_VTYPE_WEIGHT_8BIT >> GE_VTYPE_WEIGHT_SHIFT },
375
{ "GE_VTYPE_WEIGHT_16BIT", GE_VTYPE_WEIGHT_16BIT >> GE_VTYPE_WEIGHT_SHIFT },
376
{ "GE_VTYPE_WEIGHT_FLOAT", GE_VTYPE_WEIGHT_FLOAT >> GE_VTYPE_WEIGHT_SHIFT },
377
{ "GE_VTYPE_IDX_NONE", GE_VTYPE_IDX_NONE >> GE_VTYPE_IDX_SHIFT },
378
{ "GE_VTYPE_IDX_8BIT", GE_VTYPE_IDX_8BIT >> GE_VTYPE_IDX_SHIFT },
379
{ "GE_VTYPE_IDX_16BIT", GE_VTYPE_IDX_16BIT >> GE_VTYPE_IDX_SHIFT },
380
{ "GE_VTYPE_IDX_32BIT", GE_VTYPE_IDX_32BIT >> GE_VTYPE_IDX_SHIFT },
381
{ "GE_LIGHTCOMP_ONLYDIFFUSE", GE_LIGHTCOMP_ONLYDIFFUSE },
382
{ "GE_LIGHTCOMP_BOTH", GE_LIGHTCOMP_BOTH },
383
{ "GE_LIGHTCOMP_ONLYPOWDIFFUSE", GE_LIGHTCOMP_ONLYPOWDIFFUSE },
384
{ "GE_LIGHTTYPE_DIRECTIONAL", GE_LIGHTTYPE_DIRECTIONAL },
385
{ "GE_LIGHTTYPE_POINT", GE_LIGHTTYPE_POINT },
386
{ "GE_LIGHTTYPE_SPOT", GE_LIGHTTYPE_SPOT },
387
{ "GE_TEXMAP_TEXTURE_COORDS", GE_TEXMAP_TEXTURE_COORDS },
388
{ "GE_TEXMAP_TEXTURE_MATRIX", GE_TEXMAP_TEXTURE_MATRIX },
389
{ "GE_TEXMAP_ENVIRONMENT_MAP", GE_TEXMAP_ENVIRONMENT_MAP },
390
{ "GE_PROJMAP_POSITION", GE_PROJMAP_POSITION },
391
{ "GE_PROJMAP_UV", GE_PROJMAP_UV },
392
{ "GE_PROJMAP_NORMALIZED_NORMAL", GE_PROJMAP_NORMALIZED_NORMAL },
393
{ "GE_PROJMAP_NORMAL", GE_PROJMAP_NORMAL },
394
{ "GE_TFMT_565", GE_TFMT_5650 },
395
{ "GE_TFMT_5650", GE_TFMT_5650 },
396
{ "GE_TFMT_5551", GE_TFMT_5551 },
397
{ "GE_TFMT_4444", GE_TFMT_4444 },
398
{ "GE_TFMT_8888", GE_TFMT_8888 },
399
{ "GE_TFMT_CLUT4", GE_TFMT_CLUT4 },
400
{ "GE_TFMT_CLUT8", GE_TFMT_CLUT8 },
401
{ "GE_TFMT_CLUT16", GE_TFMT_CLUT16 },
402
{ "GE_TFMT_CLUT32", GE_TFMT_CLUT32 },
403
{ "GE_TFMT_DXT1", GE_TFMT_DXT1 },
404
{ "GE_TFMT_DXT3", GE_TFMT_DXT3 },
405
{ "GE_TFMT_DXT5", GE_TFMT_DXT5 },
406
{ "GE_CMODE_16BIT_BGR5650", GE_CMODE_16BIT_BGR5650 },
407
{ "GE_CMODE_16BIT_ABGR5551", GE_CMODE_16BIT_ABGR5551 },
408
{ "GE_CMODE_16BIT_ABGR4444", GE_CMODE_16BIT_ABGR4444 },
409
{ "GE_CMODE_32BIT_ABGR8888", GE_CMODE_32BIT_ABGR8888 },
410
{ "GE_TFILT_NEAREST", GE_TFILT_NEAREST },
411
{ "GE_TFILT_LINEAR", GE_TFILT_LINEAR },
412
{ "GE_TFILT_NEAREST_MIPMAP_NEAREST", GE_TFILT_NEAREST_MIPMAP_NEAREST },
413
{ "GE_TFILT_LINEAR_MIPMAP_NEAREST", GE_TFILT_LINEAR_MIPMAP_NEAREST },
414
{ "GE_TFILT_NEAREST_MIPMAP_LINEAR", GE_TFILT_NEAREST_MIPMAP_LINEAR },
415
{ "GE_TFILT_LINEAR_MIPMAP_LINEAR", GE_TFILT_LINEAR_MIPMAP_LINEAR },
416
{ "NEAREST", GE_TFILT_NEAREST },
417
{ "LINEAR", GE_TFILT_LINEAR },
418
{ "GE_TEXLEVEL_MODE_AUTO", GE_TEXLEVEL_MODE_AUTO },
419
{ "GE_TEXLEVEL_MODE_CONST", GE_TEXLEVEL_MODE_CONST },
420
{ "GE_TEXLEVEL_MODE_SLOPE", GE_TEXLEVEL_MODE_SLOPE },
421
{ "GE_TEXFUNC_MODULATE", GE_TEXFUNC_MODULATE },
422
{ "GE_TEXFUNC_DECAL", GE_TEXFUNC_DECAL },
423
{ "GE_TEXFUNC_BLEND", GE_TEXFUNC_BLEND },
424
{ "GE_TEXFUNC_REPLACE", GE_TEXFUNC_REPLACE },
425
{ "GE_TEXFUNC_ADD", GE_TEXFUNC_ADD },
426
{ "GE_COMP_NEVER", GE_COMP_NEVER },
427
{ "GE_COMP_ALWAYS", GE_COMP_ALWAYS },
428
{ "GE_COMP_EQUAL", GE_COMP_EQUAL },
429
{ "GE_COMP_NOTEQUAL", GE_COMP_NOTEQUAL },
430
{ "GE_COMP_LESS", GE_COMP_LESS },
431
{ "GE_COMP_LEQUAL", GE_COMP_LEQUAL },
432
{ "GE_COMP_GREATER", GE_COMP_GREATER },
433
{ "GE_COMP_GEQUAL", GE_COMP_GEQUAL },
434
{ "NEVER", GE_COMP_NEVER },
435
{ "ALWAYS", GE_COMP_ALWAYS },
436
{ "EQUAL", GE_COMP_EQUAL },
437
{ "NOTEQUAL", GE_COMP_NOTEQUAL },
438
{ "LESS", GE_COMP_LESS },
439
{ "LEQUAL", GE_COMP_LEQUAL },
440
{ "LESSEQUAL", GE_COMP_LEQUAL },
441
{ "GREATER", GE_COMP_GREATER },
442
{ "GEQUAL", GE_COMP_GEQUAL },
443
{ "GREATEREQUAL", GE_COMP_GEQUAL },
444
{ "GE_STENCILOP_KEEP", GE_STENCILOP_KEEP },
445
{ "GE_STENCILOP_ZERO", GE_STENCILOP_ZERO },
446
{ "GE_STENCILOP_REPLACE", GE_STENCILOP_REPLACE },
447
{ "GE_STENCILOP_INVERT", GE_STENCILOP_INVERT },
448
{ "GE_STENCILOP_INCR", GE_STENCILOP_INCR },
449
{ "GE_STENCILOP_DECR", GE_STENCILOP_DECR },
450
{ "GE_BLENDMODE_MUL_AND_ADD", GE_BLENDMODE_MUL_AND_ADD },
451
{ "GE_BLENDMODE_MUL_AND_SUBTRACT", GE_BLENDMODE_MUL_AND_SUBTRACT },
452
{ "GE_BLENDMODE_MUL_AND_SUBTRACT_REVERSE", GE_BLENDMODE_MUL_AND_SUBTRACT_REVERSE },
453
{ "GE_BLENDMODE_MIN", GE_BLENDMODE_MIN },
454
{ "GE_BLENDMODE_MAX", GE_BLENDMODE_MAX },
455
{ "GE_BLENDMODE_ABSDIFF", GE_BLENDMODE_ABSDIFF },
456
{ "ADD", GE_BLENDMODE_MUL_AND_ADD },
457
{ "SUBTRACT", GE_BLENDMODE_MUL_AND_SUBTRACT },
458
{ "SUBTRACT_REVERSE", GE_BLENDMODE_MUL_AND_SUBTRACT_REVERSE },
459
{ "MIN", GE_BLENDMODE_MIN },
460
{ "MAX", GE_BLENDMODE_MAX },
461
{ "ABSDIFF", GE_BLENDMODE_ABSDIFF },
462
{ "GE_SRCBLEND_DSTCOLOR", GE_SRCBLEND_DSTCOLOR },
463
{ "GE_SRCBLEND_INVDSTCOLOR", GE_SRCBLEND_INVDSTCOLOR },
464
{ "GE_SRCBLEND_SRCALPHA", GE_SRCBLEND_SRCALPHA },
465
{ "GE_SRCBLEND_INVSRCALPHA", GE_SRCBLEND_INVSRCALPHA },
466
{ "GE_SRCBLEND_DSTALPHA", GE_SRCBLEND_DSTALPHA },
467
{ "GE_SRCBLEND_INVDSTALPHA", GE_SRCBLEND_INVDSTALPHA },
468
{ "GE_SRCBLEND_DOUBLESRCALPHA", GE_SRCBLEND_DOUBLESRCALPHA },
469
{ "GE_SRCBLEND_DOUBLEINVSRCALPHA", GE_SRCBLEND_DOUBLEINVSRCALPHA },
470
{ "GE_SRCBLEND_DOUBLEDSTALPHA", GE_SRCBLEND_DOUBLEDSTALPHA },
471
{ "GE_SRCBLEND_DOUBLEINVDSTALPHA", GE_SRCBLEND_DOUBLEINVDSTALPHA },
472
{ "GE_SRCBLEND_FIXA", GE_SRCBLEND_FIXA },
473
{ "GE_DSTBLEND_SRCCOLOR", GE_DSTBLEND_SRCCOLOR },
474
{ "GE_DSTBLEND_INVSRCCOLOR", GE_DSTBLEND_INVSRCCOLOR },
475
{ "GE_DSTBLEND_SRCALPHA", GE_DSTBLEND_SRCALPHA },
476
{ "GE_DSTBLEND_INVSRCALPHA", GE_DSTBLEND_INVSRCALPHA },
477
{ "GE_DSTBLEND_DSTALPHA", GE_DSTBLEND_DSTALPHA },
478
{ "GE_DSTBLEND_INVDSTALPHA", GE_DSTBLEND_INVDSTALPHA },
479
{ "GE_DSTBLEND_DOUBLESRCALPHA", GE_DSTBLEND_DOUBLESRCALPHA },
480
{ "GE_DSTBLEND_DOUBLEINVSRCALPHA", GE_DSTBLEND_DOUBLEINVSRCALPHA },
481
{ "GE_DSTBLEND_DOUBLEDSTALPHA", GE_DSTBLEND_DOUBLEDSTALPHA },
482
{ "GE_DSTBLEND_DOUBLEINVDSTALPHA", GE_DSTBLEND_DOUBLEINVDSTALPHA },
483
{ "GE_DSTBLEND_FIXB", GE_DSTBLEND_FIXB },
484
{ "SRCALPHA", GE_SRCBLEND_SRCALPHA },
485
{ "INVSRCALPHA", GE_SRCBLEND_INVSRCALPHA },
486
{ "INVERSESRCALPHA", GE_SRCBLEND_INVSRCALPHA },
487
{ "DSTALPHA", GE_DSTBLEND_DSTALPHA },
488
{ "INVDSTALPHA", GE_DSTBLEND_INVDSTALPHA },
489
{ "DOUBLESRCALPHA", GE_DSTBLEND_DOUBLESRCALPHA },
490
{ "DOUBLEINVSRCALPHA", GE_DSTBLEND_DOUBLEINVSRCALPHA },
491
{ "DOUBLEDSTALPHA", GE_DSTBLEND_DOUBLEDSTALPHA },
492
{ "DOUBLEINVDSTALPHA", GE_DSTBLEND_DOUBLEINVDSTALPHA },
493
{ "FIXED", GE_DSTBLEND_FIXB },
494
{ "GE_LOGIC_CLEAR", GE_LOGIC_CLEAR },
495
{ "GE_LOGIC_AND", GE_LOGIC_AND },
496
{ "GE_LOGIC_AND_REVERSE", GE_LOGIC_AND_REVERSE },
497
{ "GE_LOGIC_COPY", GE_LOGIC_COPY },
498
{ "GE_LOGIC_AND_INVERTED", GE_LOGIC_AND_INVERTED },
499
{ "GE_LOGIC_NOOP", GE_LOGIC_NOOP },
500
{ "GE_LOGIC_XOR", GE_LOGIC_XOR },
501
{ "GE_LOGIC_OR", GE_LOGIC_OR },
502
{ "GE_LOGIC_NOR", GE_LOGIC_NOR },
503
{ "GE_LOGIC_EQUIV", GE_LOGIC_EQUIV },
504
{ "GE_LOGIC_INVERTED", GE_LOGIC_INVERTED },
505
{ "GE_LOGIC_OR_REVERSE", GE_LOGIC_OR_REVERSE },
506
{ "GE_LOGIC_COPY_INVERTED", GE_LOGIC_COPY_INVERTED },
507
{ "GE_LOGIC_OR_INVERTED", GE_LOGIC_OR_INVERTED },
508
{ "GE_LOGIC_NAND", GE_LOGIC_NAND },
509
{ "GE_LOGIC_SET", GE_LOGIC_SET },
510
};
511
512
class GEExpressionFunctions : public IExpressionFunctions {
513
public:
514
GEExpressionFunctions(GPUDebugInterface *gpu) : gpu_(gpu) {}
515
516
bool parseReference(char *str, uint32_t &referenceIndex) override;
517
bool parseSymbol(char *str, uint32_t &symbolValue) override;
518
uint32_t getReferenceValue(uint32_t referenceIndex) override;
519
ExpressionType getReferenceType(uint32_t referenceIndex) override;
520
bool getMemoryValue(uint32_t address, int size, uint32_t &dest, std::string *error) override;
521
522
private:
523
bool parseFieldReference(const char *ref, const char *field, uint32_t &referenceIndex);
524
static uint32_t getFieldValue(GECmdFormat fmt, GECmdField field, uint32_t value);
525
static ExpressionType getFieldType(GECmdFormat fmt, GECmdField field);
526
527
GPUDebugInterface *gpu_;
528
};
529
530
bool GEExpressionFunctions::parseReference(char *str, uint32_t &referenceIndex) {
531
// TODO: Support formats and a form of fields (i.e. vtype.throughmode.)
532
// For now, let's just support the register bits directly.
533
GECmdInfo info;
534
if (GECmdInfoByName(str, info)) {
535
referenceIndex = info.reg;
536
return true;
537
}
538
539
char *dot = strchr(str, '.');
540
if (dot != nullptr) {
541
*dot = '\0';
542
bool success = parseFieldReference(str, dot + 1, referenceIndex);
543
*dot = '.';
544
if (success)
545
return true;
546
}
547
548
// Also allow non-register references.
549
for (const auto &entry : referenceNames) {
550
if (strcasecmp(str, entry.name) == 0) {
551
referenceIndex = (uint32_t)entry.index;
552
return true;
553
}
554
}
555
556
// And matrix data. Maybe should allow column/row specification.
557
int subindex = -1;
558
int len = -1;
559
560
if (sscanf(str, "bone%i%n", &subindex, &len) == 1) {
561
if (len == strlen(str) && subindex < 96) {
562
referenceIndex = (uint32_t)GEReferenceIndex::BONE_MATRIX + subindex;
563
return true;
564
}
565
}
566
if (sscanf(str, "world%i%n", &subindex, &len) == 1) {
567
if (len == strlen(str) && subindex < 12) {
568
referenceIndex = (uint32_t)GEReferenceIndex::WORLD_MATRIX + subindex;
569
return true;
570
}
571
}
572
if (sscanf(str, "view%i%n", &subindex, &len) == 1) {
573
if (len == strlen(str) && subindex < 12) {
574
referenceIndex = (uint32_t)GEReferenceIndex::VIEW_MATRIX + subindex;
575
return true;
576
}
577
}
578
if (sscanf(str, "proj%i%n", &subindex, &len) == 1) {
579
if (len == strlen(str) && subindex < 16) {
580
referenceIndex = (uint32_t)GEReferenceIndex::PROJ_MATRIX + subindex;
581
return true;
582
}
583
}
584
if (sscanf(str, "tgen%i%n", &subindex, &len) == 1 || sscanf(str, "texgen%i%n", &subindex, &len) == 1) {
585
if (len == strlen(str) && subindex < 12) {
586
referenceIndex = (uint32_t)GEReferenceIndex::TGEN_MATRIX + subindex;
587
return true;
588
}
589
}
590
591
return false;
592
}
593
594
bool GEExpressionFunctions::parseFieldReference(const char *ref, const char *field, uint32_t &referenceIndex) {
595
GECmdInfo info;
596
if (!GECmdInfoByName(ref, info)) {
597
return false;
598
}
599
600
for (const auto &entry : fieldNames) {
601
if (entry.fmt == info.fmt && strcasecmp(field, entry.name) == 0) {
602
referenceIndex = (info.reg << 12) | (uint32_t)entry.field;
603
return true;
604
}
605
}
606
607
return false;
608
}
609
610
bool GEExpressionFunctions::parseSymbol(char *str, uint32_t &symbolValue) {
611
// Mainly useful for checking memory addresses and constants.
612
613
for (const auto &entry : constantNames) {
614
if (strcasecmp(str, entry.name) == 0) {
615
symbolValue = entry.value;
616
return true;
617
}
618
}
619
620
return g_symbolMap->GetLabelValue(str, symbolValue);
621
}
622
623
uint32_t GEExpressionFunctions::getReferenceValue(uint32_t referenceIndex) {
624
GPUgstate state = gpu_->GetGState();
625
if (referenceIndex < 0x100) {
626
GECmdFormat fmt = GECmdInfoByCmd(GECommand(referenceIndex)).fmt;
627
uint32_t value = state.cmdmem[referenceIndex];
628
if (fmt == GECmdFormat::FLOAT)
629
return value << 8;
630
return value & 0x00FFFFFF;
631
}
632
633
if (referenceIndex >= (uint32_t)GEReferenceIndex::FIELD_START && referenceIndex <= (uint32_t)GEReferenceIndex::FIELD_END) {
634
uint32_t value = state.cmdmem[referenceIndex >> 12] & 0x00FFFFFF;
635
GECmdFormat fmt = GECmdInfoByCmd(GECommand(referenceIndex >> 12)).fmt;
636
return getFieldValue(fmt, GECmdField(referenceIndex & 0xFF), value);
637
}
638
639
// We return the matrix value as float bits, which gets interpreted correctly in the parser.
640
if (referenceIndex >= (uint32_t)GEReferenceIndex::BONE_MATRIX && referenceIndex < (uint32_t)GEReferenceIndex::MATRIX_END) {
641
float value;
642
if (referenceIndex >= (uint32_t)GEReferenceIndex::TGEN_MATRIX) {
643
value = state.tgenMatrix[referenceIndex - (uint32_t)GEReferenceIndex::TGEN_MATRIX];
644
} else if (referenceIndex >= (uint32_t)GEReferenceIndex::PROJ_MATRIX) {
645
value = state.projMatrix[referenceIndex - (uint32_t)GEReferenceIndex::PROJ_MATRIX];
646
} else if (referenceIndex >= (uint32_t)GEReferenceIndex::VIEW_MATRIX) {
647
value = state.viewMatrix[referenceIndex - (uint32_t)GEReferenceIndex::VIEW_MATRIX];
648
} else if (referenceIndex >= (uint32_t)GEReferenceIndex::WORLD_MATRIX) {
649
value = state.worldMatrix[referenceIndex - (uint32_t)GEReferenceIndex::WORLD_MATRIX];
650
} else {
651
value = state.boneMatrix[referenceIndex - (uint32_t)GEReferenceIndex::BONE_MATRIX];
652
}
653
654
uint32_t result;
655
memcpy(&result, &value, sizeof(result));
656
return result;
657
}
658
659
GEReferenceIndex ref = (GEReferenceIndex)referenceIndex;
660
DisplayList list;
661
switch (ref) {
662
case GEReferenceIndex::VADDR:
663
return gpu_->GetVertexAddress();
664
case GEReferenceIndex::IADDR:
665
return gpu_->GetIndexAddress();
666
case GEReferenceIndex::OFFSET:
667
// TODO: Should use an interface method, probably.
668
return gstate_c.offsetAddr;
669
case GEReferenceIndex::PC:
670
if (gpu_->GetCurrentDisplayList(list)) {
671
return list.pc;
672
}
673
return 0;
674
case GEReferenceIndex::STALL:
675
if (gpu_->GetCurrentDisplayList(list)) {
676
return list.stall;
677
}
678
return 0;
679
case GEReferenceIndex::BFLAG:
680
if (gpu_->GetCurrentDisplayList(list)) {
681
return list.bboxResult ? 1 : 0;
682
}
683
return 0;
684
case GEReferenceIndex::OP:
685
if (gpu_->GetCurrentDisplayList(list)) {
686
return Memory::Read_U32(list.pc);
687
}
688
return 0;
689
case GEReferenceIndex::DATA:
690
if (gpu_->GetCurrentDisplayList(list)) {
691
return Memory::Read_U32(list.pc) & 0x00FFFFFF;
692
}
693
return 0;
694
695
case GEReferenceIndex::CLUTADDR:
696
return state.getClutAddress();
697
698
case GEReferenceIndex::TRANSFERSRC:
699
return state.getTransferSrcAddress();
700
701
case GEReferenceIndex::TRANSFERDST:
702
return state.getTransferDstAddress();
703
704
case GEReferenceIndex::PRIMCOUNT:
705
return GPUDebug::PrimsThisFrame();
706
707
case GEReferenceIndex::LASTPRIMCOUNT:
708
return GPUDebug::PrimsLastFrame();
709
710
case GEReferenceIndex::TEXADDR0:
711
case GEReferenceIndex::TEXADDR1:
712
case GEReferenceIndex::TEXADDR2:
713
case GEReferenceIndex::TEXADDR3:
714
case GEReferenceIndex::TEXADDR4:
715
case GEReferenceIndex::TEXADDR5:
716
case GEReferenceIndex::TEXADDR6:
717
case GEReferenceIndex::TEXADDR7:
718
return state.getTextureAddress((int)ref - (int)GEReferenceIndex::TEXADDR0);
719
720
case GEReferenceIndex::BONE_MATRIX:
721
case GEReferenceIndex::WORLD_MATRIX:
722
case GEReferenceIndex::VIEW_MATRIX:
723
case GEReferenceIndex::PROJ_MATRIX:
724
case GEReferenceIndex::TGEN_MATRIX:
725
case GEReferenceIndex::MATRIX_END:
726
case GEReferenceIndex::FIELD_START:
727
case GEReferenceIndex::FIELD_END:
728
// Shouldn't have gotten here.
729
break;
730
}
731
732
_assert_msg_(false, "Invalid reference index");
733
return 0;
734
}
735
736
uint32_t GEExpressionFunctions::getFieldValue(GECmdFormat fmt, GECmdField field, uint32_t value) {
737
switch (field) {
738
case GECmdField::DATA:
739
return value;
740
case GECmdField::LOW_FLAG:
741
return value & 1;
742
case GECmdField::LOW_U2:
743
return value & 3;
744
case GECmdField::LOW_U4:
745
return value & 0xF;
746
case GECmdField::LOW_U7:
747
return value & 0x7F;
748
case GECmdField::LOW_U8:
749
return value & 0xFF;
750
case GECmdField::LOW_U10:
751
return value & 0x03FF;
752
case GECmdField::LOW_U10_P1:
753
return (value & 0x03FF) + 1;
754
case GECmdField::LOW_U11:
755
return value & 0x07FF;
756
case GECmdField::LOW_U16:
757
return value & 0xFFFF;
758
case GECmdField::MID_U8:
759
return (value >> 8) & 0xFF;
760
case GECmdField::MID_U10:
761
return (value >> 10) & 0x03FF;
762
case GECmdField::MID_U10_P1:
763
return ((value >> 10) & 0x03FF) + 1;
764
case GECmdField::TOP_U8:
765
return (value >> 16) & 0xFF;
766
case GECmdField::FLAG_AFTER_1:
767
return (value >> 1) & 1;
768
case GECmdField::FLAG_AFTER_2:
769
return (value >> 2) & 1;
770
case GECmdField::FLAG_AFTER_8:
771
return (value >> 8) & 1;
772
case GECmdField::FLAG_AFTER_9:
773
return (value >> 9) & 1;
774
case GECmdField::FLAG_AFTER_10:
775
return (value >> 10) & 1;
776
case GECmdField::FLAG_AFTER_11:
777
return (value >> 11) & 1;
778
case GECmdField::FLAG_AFTER_16:
779
return (value >> 16) & 1;
780
case GECmdField::FLAG_AFTER_17:
781
return (value >> 17) & 1;
782
case GECmdField::FLAG_AFTER_18:
783
return (value >> 18) & 1;
784
case GECmdField::FLAG_AFTER_19:
785
return (value >> 19) & 1;
786
case GECmdField::FLAG_AFTER_20:
787
return (value >> 20) & 1;
788
case GECmdField::FLAG_AFTER_21:
789
return (value >> 21) & 1;
790
case GECmdField::FLAG_AFTER_22:
791
return (value >> 22) & 1;
792
case GECmdField::FLAG_AFTER_23:
793
return (value >> 23) & 1;
794
case GECmdField::U2_AFTER_8:
795
return (value >> 8) & 3;
796
case GECmdField::U3_AFTER_16:
797
return (value >> 16) & 7;
798
case GECmdField::U12_AFTER_4:
799
return (value >> 4) & 0x0FFF;
800
801
// Below here are "typed" values, maybe they'll be exposed differently than integers someday.
802
803
case GECmdField::PRIM_TYPE:
804
return (value >> 16) & 7;
805
case GECmdField::SIGNAL_TYPE:
806
return (value >> 16) & 0xFF;
807
case GECmdField::VTYPE_TC:
808
return value & 3;
809
case GECmdField::VTYPE_COL:
810
return (value >> 2) & 7;
811
case GECmdField::VTYPE_NRM:
812
return (value >> 5) & 3;
813
case GECmdField::VTYPE_POS:
814
return (value >> 7) & 3;
815
case GECmdField::VTYPE_WEIGHTTYPE:
816
return (value >> 9) & 3;
817
case GECmdField::VTYPE_INDEX:
818
return (value >> 11) & 3;
819
case GECmdField::VTYPE_WEIGHTCOUNT:
820
return ((value >> 14) & 7) + 1;
821
case GECmdField::VTYPE_MORPHCOUNT:
822
return ((value >> 18) & 7) + 1;
823
case GECmdField::PATCH_PRIM_TYPE:
824
return value & 3;
825
case GECmdField::LIGHT_COMP:
826
return value & 3;
827
case GECmdField::LIGHT_TYPE:
828
return (value >> 8) & 3;
829
case GECmdField::LIGHT_TYPE_SPECULAR:
830
return (value & 3) == 1;
831
case GECmdField::HIGH_ADDR:
832
return (value << 8) & 0xFF000000;
833
case GECmdField::TEX_W:
834
return 1 << (value & 0xF);
835
case GECmdField::TEX_H:
836
return 1 << ((value >> 8) & 0xF);
837
case GECmdField::UVGEN_TYPE:
838
return value & 3;
839
case GECmdField::UVGEN_PROJ:
840
return (value >> 8) & 3;
841
case GECmdField::TEX_FORMAT:
842
return value & 0xF;
843
case GECmdField::TEX_MINFILTER:
844
return value & 7;
845
case GECmdField::TEX_MAGFILTER:
846
return (value >> 8) & 1;
847
case GECmdField::TEX_LEVEL_MODE:
848
return value & 3;
849
case GECmdField::LOW_U12_4_FLOAT:
850
{
851
float f = (value & 0xFFFF) / 16.0f;
852
uint32_t result;
853
memcpy(&result, &f, sizeof(result));
854
return result;
855
}
856
case GECmdField::HIGH_S4_4_FLOAT: // At 16, s.3.4 converted to float.
857
{
858
int value8 = (int)(s8)((value >> 16) & 0xFF);
859
float f = value8 / 16.0f;
860
uint32_t result;
861
memcpy(&result, &f, sizeof(result));
862
return result;
863
}
864
case GECmdField::TEX_FUNC:
865
return value & 7;
866
case GECmdField::CLUT_BYTES:
867
return (value & 0x3F) * 8;
868
case GECmdField::CLUT_FORMAT:
869
return value & 3;
870
case GECmdField::CLUT_SHIFT:
871
return (value >> 2) & 0x1F;
872
case GECmdField::CLUT_OFFSET:
873
return ((value >> 16) & 0x1F) << 4;
874
case GECmdField::COMPARE_FUNC2:
875
return value & 3;
876
case GECmdField::COMPARE_FUNC3:
877
return value & 7;
878
case GECmdField::STENCIL_OP_AT_0:
879
return value & 7;
880
case GECmdField::STENCIL_OP_AT_8:
881
return (value >> 8) & 7;
882
case GECmdField::STENCIL_OP_AT_16:
883
return (value >> 16) & 7;
884
case GECmdField::BLEND_SRC:
885
return value & 0xF;
886
case GECmdField::BLEND_DST:
887
return (value >> 4) & 0xF;
888
case GECmdField::BLEND_EQUATION:
889
return (value >> 8) & 7;
890
case GECmdField::LOGIC_OP:
891
return value & 0xF;
892
}
893
894
_assert_msg_(false, "Invalid field type");
895
return 0;
896
}
897
898
ExpressionType GEExpressionFunctions::getReferenceType(uint32_t referenceIndex) {
899
if (referenceIndex < 0x100) {
900
GECmdFormat fmt = GECmdInfoByCmd(GECommand(referenceIndex)).fmt;
901
if (fmt == GECmdFormat::FLOAT)
902
return EXPR_TYPE_FLOAT;
903
return EXPR_TYPE_UINT;
904
}
905
906
if (referenceIndex >= (uint32_t)GEReferenceIndex::FIELD_START && referenceIndex <= (uint32_t)GEReferenceIndex::FIELD_END) {
907
GECmdFormat fmt = GECmdInfoByCmd(GECommand(referenceIndex >> 12)).fmt;
908
return getFieldType(fmt, GECmdField(referenceIndex & 0xFF));
909
}
910
911
if (referenceIndex >= (uint32_t)GEReferenceIndex::BONE_MATRIX && referenceIndex < (uint32_t)GEReferenceIndex::MATRIX_END)
912
return EXPR_TYPE_FLOAT;
913
return EXPR_TYPE_UINT;
914
}
915
916
ExpressionType GEExpressionFunctions::getFieldType(GECmdFormat fmt, GECmdField field) {
917
switch (field) {
918
case GECmdField::LOW_U12_4_FLOAT:
919
case GECmdField::HIGH_S4_4_FLOAT:
920
return EXPR_TYPE_FLOAT;
921
922
default:
923
// Almost all of these are uint, so not listing each one.
924
break;
925
}
926
927
return EXPR_TYPE_UINT;
928
}
929
930
bool GEExpressionFunctions::getMemoryValue(uint32_t address, int size, uint32_t &dest, std::string *error) {
931
// We allow, but ignore, bad access.
932
// If we didn't, log/condition statements that reference registers couldn't be configured.
933
uint32_t valid = Memory::ValidSize(address, size);
934
uint8_t buf[4]{};
935
if (valid != 0)
936
memcpy(buf, Memory::GetPointerUnchecked(address), valid);
937
938
switch (size) {
939
case 1:
940
dest = buf[0];
941
return true;
942
case 2:
943
dest = (buf[1] << 8) | buf[0];
944
return true;
945
case 4:
946
dest = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
947
return true;
948
}
949
950
*error = StringFromFormat("Unexpected memory access size %d", size);
951
return false;
952
}
953
954
bool GPUDebugInitExpression(GPUDebugInterface *g, const char *str, PostfixExpression &exp) {
955
GEExpressionFunctions funcs(g);
956
return initPostfixExpression(str, &funcs, exp);
957
}
958
959
bool GPUDebugExecExpression(GPUDebugInterface *g, PostfixExpression &exp, uint32_t &result) {
960
GEExpressionFunctions funcs(g);
961
return parsePostfixExpression(exp, &funcs, result);
962
}
963
964
bool GPUDebugExecExpression(GPUDebugInterface *g, const char *str, uint32_t &result) {
965
GEExpressionFunctions funcs(g);
966
return parseExpression(str, &funcs, result);
967
}
968
969
void GPUDebugBuffer::Allocate(u32 stride, u32 height, GEBufferFormat fmt, bool flipped, bool reversed) {
970
GPUDebugBufferFormat actualFmt = GPUDebugBufferFormat(fmt);
971
if (reversed && actualFmt < GPU_DBG_FORMAT_8888) {
972
actualFmt |= GPU_DBG_FORMAT_REVERSE_FLAG;
973
}
974
Allocate(stride, height, actualFmt, flipped);
975
}
976
977
void GPUDebugBuffer::Allocate(u32 stride, u32 height, GPUDebugBufferFormat fmt, bool flipped) {
978
if (alloc_ && stride_ == stride && height_ == height && fmt_ == fmt) {
979
// Already allocated the right size.
980
flipped_ = flipped;
981
return;
982
}
983
984
Free();
985
alloc_ = true;
986
height_ = height;
987
stride_ = stride;
988
fmt_ = fmt;
989
flipped_ = flipped;
990
991
u32 pixelSize = PixelSize();
992
data_ = new u8[pixelSize * stride * height];
993
}
994
995
void GPUDebugBuffer::Free() {
996
if (alloc_ && data_ != NULL) {
997
delete [] data_;
998
}
999
data_ = NULL;
1000
}
1001
1002
void GPUDebugBuffer::ZeroBytes() {
1003
_dbg_assert_(data_);
1004
memset(data_, 0, PixelSize() * stride_ * height_);
1005
}
1006
1007
u32 GPUDebugBuffer::PixelSize() const {
1008
switch (fmt_) {
1009
case GPU_DBG_FORMAT_8888:
1010
case GPU_DBG_FORMAT_8888_BGRA:
1011
case GPU_DBG_FORMAT_FLOAT:
1012
case GPU_DBG_FORMAT_24BIT_8X:
1013
case GPU_DBG_FORMAT_24X_8BIT:
1014
case GPU_DBG_FORMAT_FLOAT_DIV_256:
1015
case GPU_DBG_FORMAT_24BIT_8X_DIV_256:
1016
return 4;
1017
1018
case GPU_DBG_FORMAT_888_RGB:
1019
return 3;
1020
1021
case GPU_DBG_FORMAT_8BIT:
1022
return 1;
1023
1024
default:
1025
return 2;
1026
}
1027
}
1028
1029
u32 GPUDebugBuffer::GetRawPixel(int x, int y) const {
1030
if (data_ == nullptr) {
1031
return 0;
1032
}
1033
1034
if (flipped_) {
1035
y = height_ - y - 1;
1036
}
1037
1038
u32 pixelSize = PixelSize();
1039
u32 byteOffset = pixelSize * (stride_ * y + x);
1040
const u8 *ptr = &data_[byteOffset];
1041
1042
switch (pixelSize) {
1043
case 4:
1044
return *(const u32 *)ptr;
1045
case 3:
1046
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
1047
case 2:
1048
return *(const u16 *)ptr;
1049
case 1:
1050
return *(const u8 *)ptr;
1051
default:
1052
return 0;
1053
}
1054
}
1055
1056
void GPUDebugBuffer::SetRawPixel(int x, int y, u32 c) {
1057
if (data_ == nullptr) {
1058
return;
1059
}
1060
1061
if (flipped_) {
1062
y = height_ - y - 1;
1063
}
1064
1065
u32 pixelSize = PixelSize();
1066
u32 byteOffset = pixelSize * (stride_ * y + x);
1067
u8 *ptr = &data_[byteOffset];
1068
1069
switch (pixelSize) {
1070
case 4:
1071
*(u32 *)ptr = c;
1072
break;
1073
case 3:
1074
ptr[0] = (c >> 0) & 0xFF;
1075
ptr[1] = (c >> 8) & 0xFF;
1076
ptr[2] = (c >> 16) & 0xFF;
1077
break;
1078
case 2:
1079
*(u16 *)ptr = (u16)c;
1080
break;
1081
case 1:
1082
*ptr = (u8)c;
1083
break;
1084
default:
1085
break;
1086
}
1087
}
1088
1089