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/GeDisasm.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 <cstdio>
19
#include "Core/MemMap.h"
20
#include "GPU/ge_constants.h"
21
#include "GPU/GPU.h"
22
#include "GPU/GPUInterface.h"
23
#include "GPU/GPUState.h"
24
#include "GPU/GeDisasm.h"
25
26
void GeDescribeVertexType(u32 op, char *buffer, int len) {
27
bool through = (op & GE_VTYPE_THROUGH_MASK) == GE_VTYPE_THROUGH;
28
int tc = (op & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT;
29
int col = (op & GE_VTYPE_COL_MASK) >> GE_VTYPE_COL_SHIFT;
30
int nrm = (op & GE_VTYPE_NRM_MASK) >> GE_VTYPE_NRM_SHIFT;
31
int pos = (op & GE_VTYPE_POS_MASK) >> GE_VTYPE_POS_SHIFT;
32
int weight = (op & GE_VTYPE_WEIGHT_MASK) >> GE_VTYPE_WEIGHT_SHIFT;
33
int weightCount = ((op & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT) + 1;
34
int morphCount = (op & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT;
35
int idx = (op & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT;
36
37
static const char * const colorNames[] = {
38
NULL,
39
"unsupported1",
40
"unsupported2",
41
"unsupported3",
42
"BGR 565",
43
"ABGR 1555",
44
"ABGR 4444",
45
"ABGR 8888",
46
};
47
static const char * const typeNames[] = {
48
NULL,
49
"u8",
50
"u16",
51
"float",
52
};
53
static const char * const typeNamesI[] = {
54
NULL,
55
"u8",
56
"u16",
57
"u32",
58
};
59
static const char * const typeNamesS[] = {
60
NULL,
61
"s8",
62
"s16",
63
"float",
64
};
65
66
char *w = buffer, *end = buffer + len;
67
if (through)
68
w += snprintf(w, end - w, "through, ");
69
if (typeNames[tc] && w < end)
70
w += snprintf(w, end - w, "%s texcoords, ", typeNames[tc]);
71
if (colorNames[col] && w < end)
72
w += snprintf(w, end - w, "%s colors, ", colorNames[col]);
73
if (typeNames[nrm] && w < end)
74
w += snprintf(w, end - w, "%s normals, ", typeNamesS[nrm]);
75
if (typeNames[pos] && w < end)
76
w += snprintf(w, end - w, "%s positions, ", typeNamesS[pos]);
77
if (typeNames[weight] && w < end)
78
w += snprintf(w, end - w, "%s weights (%d), ", typeNames[weight], weightCount);
79
else if (weightCount > 1 && w < end)
80
w += snprintf(w, end - w, "unknown weights (%d), ", weightCount);
81
if (morphCount > 0 && w < end)
82
w += snprintf(w, end - w, "%d morphs, ", morphCount);
83
if (typeNamesI[idx] && w < end)
84
w += snprintf(w, end - w, "%s indexes, ", typeNamesI[idx]);
85
86
if (w < buffer + 2)
87
snprintf(buffer, len, "none");
88
// Otherwise, get rid of the pesky trailing comma.
89
else if (w < end)
90
w[-2] = '\0';
91
}
92
93
void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer, int bufsize) {
94
u32 cmd = op >> 24;
95
u32 data = op & 0xFFFFFF;
96
97
static const char * const primTypes[8] = {
98
"POINTS",
99
"LINES",
100
"LINE_STRIP",
101
"TRIANGLES",
102
"TRIANGLE_STRIP",
103
"TRIANGLE_FAN",
104
"RECTANGLES",
105
"CONTINUE_PREVIOUS",
106
};
107
108
// Handle control and drawing commands here directly. The others we delegate.
109
switch (cmd)
110
{
111
case GE_CMD_NOP:
112
if (data != 0)
113
snprintf(buffer, bufsize, "NOP: data= %06x", data);
114
else
115
snprintf(buffer, bufsize, "NOP");
116
break;
117
118
// Pretty sure this is some sort of NOP to eat some pipelining issue,
119
// often seen after CALL instructions.
120
case GE_CMD_NOP_FF:
121
if (data != 0)
122
snprintf(buffer, bufsize, "NOP_FF: data= %06x", data);
123
else
124
snprintf(buffer, bufsize, "NOP_FF");
125
break;
126
127
case GE_CMD_BASE:
128
if ((data & 0x000F0000) == data)
129
snprintf(buffer, bufsize, "BASE: high=%02x", data >> 16);
130
else
131
snprintf(buffer, bufsize, "BASE: high=%02x (extra %06x)", data >> 16, data & ~0x000F0000);
132
break;
133
134
case GE_CMD_VADDR:
135
snprintf(buffer, bufsize, "VADDR: %06x => %08x", data, gstate_c.getRelativeAddress(data));
136
break;
137
138
case GE_CMD_IADDR:
139
snprintf(buffer, bufsize, "IADDR: %06x => %08x", data, gstate_c.getRelativeAddress(data));
140
break;
141
142
case GE_CMD_PRIM:
143
{
144
u32 count = data & 0xFFFF;
145
u32 type = (data >> 16) & 7;
146
if (gstate.vertType & GE_VTYPE_IDX_MASK)
147
snprintf(buffer, bufsize, "DRAW PRIM %s: count= %i vaddr= %08x, iaddr= %08x", type < 7 ? primTypes[type] : "INVALID", count, gstate_c.vertexAddr, gstate_c.indexAddr);
148
else
149
snprintf(buffer, bufsize, "DRAW PRIM %s: count= %i vaddr= %08x", type < 7 ? primTypes[type] : "INVALID", count, gstate_c.vertexAddr);
150
}
151
break;
152
153
case GE_CMD_BEZIER:
154
{
155
int bz_ucount = data & 0xFF;
156
int bz_vcount = (data >> 8) & 0xFF;
157
if (data & 0xFF0000)
158
snprintf(buffer, bufsize, "DRAW BEZIER: %i x %i (extra %x)", bz_ucount, bz_vcount, data >> 16);
159
else
160
snprintf(buffer, bufsize, "DRAW BEZIER: %i x %i", bz_ucount, bz_vcount);
161
}
162
break;
163
164
case GE_CMD_SPLINE:
165
{
166
int sp_ucount = data & 0xFF;
167
int sp_vcount = (data >> 8) & 0xFF;
168
int sp_utype = (data >> 16) & 0x3;
169
int sp_vtype = (data >> 18) & 0x3;
170
if (data & 0xF00000)
171
snprintf(buffer, bufsize, "DRAW SPLINE: %i x %i (type %ix%i, extra %x)", sp_ucount, sp_vcount, sp_utype, sp_vtype, data >> 20);
172
else
173
snprintf(buffer, bufsize, "DRAW SPLINE: %i x %i (type %ix%i)", sp_ucount, sp_vcount, sp_utype, sp_vtype);
174
}
175
break;
176
177
case GE_CMD_JUMP:
178
{
179
u32 target = gstate_c.getRelativeAddress(op & 0x00FFFFFC);
180
snprintf(buffer, bufsize, "JUMP: %08x to %08x (%06x)", pc, target, data);
181
}
182
break;
183
184
case GE_CMD_CALL:
185
{
186
u32 retval = pc + 4;
187
u32 target = gstate_c.getRelativeAddress(op & 0x00FFFFFC);
188
snprintf(buffer, bufsize, "CALL: %08x to %08x (%06x), ret=%08x", pc, target, data, retval);
189
}
190
break;
191
192
case GE_CMD_RET:
193
if (data)
194
snprintf(buffer, bufsize, "RET: data= %06x", data);
195
else
196
snprintf(buffer, bufsize, "RET");
197
break;
198
199
case GE_CMD_SIGNAL:
200
snprintf(buffer, bufsize, "SIGNAL %06x", data);
201
break;
202
203
case GE_CMD_FINISH:
204
snprintf(buffer, bufsize, "FINISH %06x", data);
205
break;
206
207
case GE_CMD_END:
208
switch (prev >> 24)
209
{
210
case GE_CMD_SIGNAL:
211
{
212
snprintf(buffer, bufsize, "END - ");
213
// TODO: see http://code.google.com/p/jpcsp/source/detail?r=2935#
214
int behaviour = (prev >> 16) & 0xFF;
215
int signal = prev & 0xFFFF;
216
int enddata = data & 0xFFFFFF;
217
// We should probably defer to sceGe here, no sense in implementing this stuff in every GPU
218
u32 target = (((signal << 16) | (enddata & 0xFFFF)) & 0xFFFFFFFC);
219
switch (behaviour) {
220
case PSP_GE_SIGNAL_HANDLER_SUSPEND:
221
snprintf(buffer, bufsize, "Signal with wait. signal/end: %04x %04x", signal, enddata);
222
break;
223
case PSP_GE_SIGNAL_HANDLER_CONTINUE:
224
snprintf(buffer, bufsize, "Signal without wait. signal/end: %04x %04x", signal, enddata);
225
break;
226
case PSP_GE_SIGNAL_HANDLER_PAUSE:
227
snprintf(buffer, bufsize, "Signal with pause. signal/end: %04x %04x", signal, enddata);
228
break;
229
case PSP_GE_SIGNAL_SYNC:
230
snprintf(buffer, bufsize, "Signal with sync. signal/end: %04x %04x", signal, enddata);
231
break;
232
case PSP_GE_SIGNAL_JUMP:
233
snprintf(buffer, bufsize, "Signal with jump. signal/end: %04x %04x, target: %08x", signal, enddata, target);
234
break;
235
case PSP_GE_SIGNAL_CALL:
236
snprintf(buffer, bufsize, "Signal with call. signal/end: %04x %04x, target: %08x", signal, enddata, target);
237
break;
238
case PSP_GE_SIGNAL_RET:
239
snprintf(buffer, bufsize, "Signal with return. signal/end: %04x %04x", signal, enddata);
240
break;
241
case PSP_GE_SIGNAL_RJUMP:
242
target += pc;
243
snprintf(buffer, bufsize, "Signal with jump (relative.) signal/end: %04x %04x, target: %08x", signal, enddata, target);
244
break;
245
case PSP_GE_SIGNAL_RCALL:
246
target += pc;
247
snprintf(buffer, bufsize, "Signal with call (relative.) signal/end: %04x %04x, target: %08x", signal, enddata, target);
248
break;
249
case PSP_GE_SIGNAL_OJUMP:
250
target = gstate_c.getRelativeAddress(target);
251
snprintf(buffer, bufsize, "Signal with jump (offset.) signal/end: %04x %04x, target: %08x", signal, enddata, target);
252
break;
253
case PSP_GE_SIGNAL_OCALL:
254
target = gstate_c.getRelativeAddress(target);
255
snprintf(buffer, bufsize, "Signal with call (offset.) signal/end: %04x %04x, target: %08x", signal, enddata, target);
256
break;
257
default:
258
snprintf(buffer, bufsize, "UNKNOWN Signal UNIMPLEMENTED %i! signal/end: %04x %04x", behaviour, signal, enddata);
259
break;
260
}
261
}
262
break;
263
case GE_CMD_FINISH:
264
if (data)
265
snprintf(buffer, bufsize, "END: data= %06x", data);
266
else
267
snprintf(buffer, bufsize, "END");
268
break;
269
default:
270
snprintf(buffer, bufsize, "END: %06x, not finished (%08x)", data, prev);
271
break;
272
}
273
break;
274
275
case GE_CMD_BJUMP:
276
{
277
u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0x0FFFFFFF;
278
snprintf(buffer, bufsize, "BBOX_JUMP: target= %08x", target);
279
}
280
break;
281
282
case GE_CMD_BOUNDINGBOX:
283
snprintf(buffer, bufsize, "BBOX_TEST: %06x", data);
284
break;
285
286
case GE_CMD_ORIGIN:
287
if (data)
288
snprintf(buffer, bufsize, "ORIGIN offset=%08x (extra %06x)", pc, data);
289
else
290
snprintf(buffer, bufsize, "ORIGIN offset=%08x", pc);
291
break;
292
293
case GE_CMD_VERTEXTYPE:
294
{
295
int len = snprintf(buffer, bufsize, "SetVertexType: ");
296
GeDescribeVertexType(op, buffer + len, bufsize - len);
297
}
298
break;
299
300
case GE_CMD_OFFSETADDR:
301
snprintf(buffer, bufsize, "OffsetAddr: %06x (offset=%08x)", data, data << 8);
302
break;
303
304
case GE_CMD_REGION1:
305
{
306
int x1 = data & 0x3ff;
307
int y1 = (data >> 10) & 0x3ff;
308
if (data & 0xF00000)
309
snprintf(buffer, bufsize, "Region Rate: %d %d (extra %x)", x1, y1, data >> 20);
310
else
311
snprintf(buffer, bufsize, "Region Rate: %d %d", x1, y1);
312
}
313
break;
314
315
case GE_CMD_REGION2:
316
{
317
int x2 = data & 0x3ff;
318
int y2 = (data >> 10) & 0x3ff;
319
if (data & 0xF00000)
320
snprintf(buffer, bufsize, "Region BR: %d %d (extra %x)", x2, y2, data >> 20);
321
else
322
snprintf(buffer, bufsize, "Region BR: %d %d", x2, y2);
323
}
324
break;
325
326
case GE_CMD_DEPTHCLAMPENABLE:
327
snprintf(buffer, bufsize, "Depth clamp enable: %i", data);
328
break;
329
330
case GE_CMD_CULLFACEENABLE:
331
snprintf(buffer, bufsize, "CullFace enable: %i", data);
332
break;
333
334
case GE_CMD_TEXTUREMAPENABLE:
335
snprintf(buffer, bufsize, "Texture map enable: %i", data);
336
break;
337
338
case GE_CMD_LIGHTINGENABLE:
339
snprintf(buffer, bufsize, "Lighting enable: %i", data);
340
break;
341
342
case GE_CMD_FOGENABLE:
343
snprintf(buffer, bufsize, "Fog enable: %i", data);
344
break;
345
346
case GE_CMD_DITHERENABLE:
347
snprintf(buffer, bufsize, "Dither enable: %i", data);
348
break;
349
350
case GE_CMD_OFFSETX:
351
if (data & ~0xFFFF)
352
snprintf(buffer, bufsize, "Offset X: %04x / %d with sub %d (extra %02x)", data & 0xFFFF, data >> 4, data & 0xF, data >> 16);
353
else
354
snprintf(buffer, bufsize, "Offset X: %04x / %d with sub %d", data & 0xFFFF, data >> 4, data & 0xF);
355
break;
356
357
case GE_CMD_OFFSETY:
358
if (data & ~0xFFFF)
359
snprintf(buffer, bufsize, "Offset Y: %04x / %d with sub %d (extra %02x)", data & 0xFFFF, data >> 4, data & 0xF, data >> 16);
360
else
361
snprintf(buffer, bufsize, "Offset Y: %04x / %d with sub %d", data & 0xFFFF, data >> 4, data & 0xF);
362
break;
363
364
case GE_CMD_TEXSCALEU:
365
snprintf(buffer, bufsize, "Texture U scale: %f", getFloat24(data));
366
break;
367
368
case GE_CMD_TEXSCALEV:
369
snprintf(buffer, bufsize, "Texture V scale: %f", getFloat24(data));
370
break;
371
372
case GE_CMD_TEXOFFSETU:
373
snprintf(buffer, bufsize, "Texture U offset: %f", getFloat24(data));
374
break;
375
376
case GE_CMD_TEXOFFSETV:
377
snprintf(buffer, bufsize, "Texture V offset: %f", getFloat24(data));
378
break;
379
380
case GE_CMD_SCISSOR1:
381
{
382
int x1 = data & 0x3ff;
383
int y1 = (data >> 10) & 0x3ff;
384
if (data & 0xF00000)
385
snprintf(buffer, bufsize, "Scissor TL: %i, %i (extra %x)", x1, y1, data >> 20);
386
else
387
snprintf(buffer, bufsize, "Scissor TL: %i, %i", x1, y1);
388
}
389
break;
390
case GE_CMD_SCISSOR2:
391
{
392
int x2 = data & 0x3ff;
393
int y2 = (data >> 10) & 0x3ff;
394
if (data & 0xF00000)
395
snprintf(buffer, bufsize, "Scissor BR: %i, %i (extra %x)", x2, y2, data >> 20);
396
else
397
snprintf(buffer, bufsize, "Scissor BR: %i, %i", x2, y2);
398
}
399
break;
400
401
case GE_CMD_MINZ:
402
if (data & 0xFF0000)
403
snprintf(buffer, bufsize, "MinZ: 0x%04x / %f (extra %02x)", data & 0xFFFF, (float)(data & 0xFFFF) / 65535.0f, data >> 16);
404
else
405
snprintf(buffer, bufsize, "MinZ: 0x%04x / %f", data, (float)data / 65535.0f);
406
break;
407
408
case GE_CMD_MAXZ:
409
if (data & 0xFF0000)
410
snprintf(buffer, bufsize, "MaxZ: 0x%04x / %f (extra %02x)", data & 0xFFFF, (float)(data & 0xFFFF) / 65535.0f, data >> 16);
411
else
412
snprintf(buffer, bufsize, "MaxZ: 0x%04x / %f", data, (float)data / 65535.0f);
413
break;
414
415
case GE_CMD_FRAMEBUFPTR:
416
{
417
snprintf(buffer, bufsize, "Framebuf ptr: 0x04%06x", data);
418
}
419
break;
420
421
case GE_CMD_FRAMEBUFWIDTH:
422
if (data & ~0x07FC)
423
snprintf(buffer, bufsize, "Framebuf stride: 0x%x (extra %06x)", data & 0x07FC, data & ~0x07FC);
424
else
425
snprintf(buffer, bufsize, "Framebuf stride: %04x", data);
426
break;
427
428
case GE_CMD_FRAMEBUFPIXFORMAT:
429
if (data <= 3)
430
snprintf(buffer, bufsize, "Framebuf PixelFormat: %s", GeBufferFormatToString((GEBufferFormat)data));
431
else
432
snprintf(buffer, bufsize, "Framebuf PixelFormat: invalid %x", data);
433
break;
434
435
case GE_CMD_TEXADDR0:
436
case GE_CMD_TEXADDR1:
437
case GE_CMD_TEXADDR2:
438
case GE_CMD_TEXADDR3:
439
case GE_CMD_TEXADDR4:
440
case GE_CMD_TEXADDR5:
441
case GE_CMD_TEXADDR6:
442
case GE_CMD_TEXADDR7:
443
snprintf(buffer, bufsize, "Texture address %d: low=%06x", cmd - GE_CMD_TEXADDR0, data);
444
break;
445
446
case GE_CMD_TEXBUFWIDTH0:
447
case GE_CMD_TEXBUFWIDTH1:
448
case GE_CMD_TEXBUFWIDTH2:
449
case GE_CMD_TEXBUFWIDTH3:
450
case GE_CMD_TEXBUFWIDTH4:
451
case GE_CMD_TEXBUFWIDTH5:
452
case GE_CMD_TEXBUFWIDTH6:
453
case GE_CMD_TEXBUFWIDTH7:
454
snprintf(buffer, bufsize, "Texture stride %d: 0x%04x, address high=%02x", cmd - GE_CMD_TEXBUFWIDTH0, data & 0xFFFF, data >> 16);
455
break;
456
457
case GE_CMD_CLUTADDR:
458
snprintf(buffer, bufsize, "CLUT addr: low=%06x", data);
459
break;
460
461
case GE_CMD_CLUTADDRUPPER:
462
if ((data & 0x000F0000) == data)
463
snprintf(buffer, bufsize, "CLUT addr: high=%02x", data >> 16);
464
else
465
snprintf(buffer, bufsize, "CLUT addr: high=%02x (extra %06x)", data >> 16, data & ~0x000F0000);
466
break;
467
468
case GE_CMD_LOADCLUT:
469
if ((data & 0xFFFFC0) != 0)
470
snprintf(buffer, bufsize, "Clut load: %08x, %d bytes (extra %06x)", gstate.getClutAddress(), (data & 0x3F) << 5, data & 0xFFFFC0);
471
else
472
snprintf(buffer, bufsize, "Clut load: %08x, %d bytes", gstate.getClutAddress(), (data & 0x3F) << 5);
473
break;
474
475
case GE_CMD_TEXMAPMODE:
476
{
477
static const char * const uvgen[] = {
478
"texcoords",
479
"texgen matrix",
480
"env map",
481
"invalid"
482
};
483
static const char * const uvproj[] = {
484
"pos",
485
"uv",
486
"normalized normal",
487
"normal",
488
};
489
if ((data & 0x000303) == data)
490
snprintf(buffer, bufsize, "Tex map mode: uvgen=%s, uvproj=%s", uvgen[data & 3], uvproj[(data >> 8) & 3]);
491
else
492
snprintf(buffer, bufsize, "Tex map mode: uvgen=%s, uvproj=%s (extra %06x)", uvgen[data & 3], uvproj[(data >> 8) & 3], data & ~0x000303);
493
}
494
break;
495
496
case GE_CMD_TEXSHADELS:
497
if ((data & 0x000303) == data)
498
snprintf(buffer, bufsize, "Tex shade light sources: %d, %d", data & 3, (data >> 8) & 3);
499
else
500
snprintf(buffer, bufsize, "Tex shade light sources: %d, %d (extra %06x)", data & 3, (data >> 8) & 3, data & ~0x000303);
501
break;
502
503
case GE_CMD_CLUTFORMAT:
504
{
505
const char *clutformats[] = {
506
"BGR 5650",
507
"ABGR 1555",
508
"ABGR 4444",
509
"ABGR 8888",
510
};
511
snprintf(buffer, bufsize, "Clut format: %06x (%s)", data, clutformats[data & 3]);
512
}
513
break;
514
515
case GE_CMD_TRANSFERSRC:
516
{
517
if (data & 0xF)
518
snprintf(buffer, bufsize, "Block transfer src: low=%06x (extra: %x)", data & ~0xF, data & 0xF);
519
else
520
snprintf(buffer, bufsize, "Block transfer src: low=%06x", data);
521
// Nothing to do, the next one prints
522
}
523
break;
524
525
case GE_CMD_TRANSFERSRCW:
526
{
527
u32 xferSrc = (gstate.transfersrc & 0x00FFFFFF) | ((data & 0xFF0000) << 8);
528
u32 xferSrcW = (data & 0x400) != 0 ? 0x400 : (data & 0x3FF);
529
u32 validMask = (data & 0x400) != 0 ? 0xFF0400 : 0xFF03FF;
530
if (data & ~validMask)
531
snprintf(buffer, bufsize, "Block transfer src: high=%02x, w=%d (addr %08x, extra %x)", data >> 16, xferSrcW, xferSrc, data & ~validMask);
532
else
533
snprintf(buffer, bufsize, "Block transfer src: high=%02x, w=%d (addr %08x)", data >> 16, xferSrcW, xferSrc);
534
break;
535
}
536
537
case GE_CMD_TRANSFERDST:
538
{
539
// Nothing to do, the next one prints
540
if (data & 0xF)
541
snprintf(buffer, bufsize, "Block transfer dst: low=%06x (extra: %x)", data & ~0xF, data & 0xF);
542
else
543
snprintf(buffer, bufsize, "Block transfer dst: low=%06x", data);
544
}
545
break;
546
547
case GE_CMD_TRANSFERDSTW:
548
{
549
u32 xferDst = (gstate.transferdst & 0x00FFFFFF) | ((data & 0xFF0000) << 8);
550
u32 xferDstW = (data & 0x400) != 0 ? 0x400 : (data & 0x3FF);
551
u32 validMask = (data & 0x400) != 0 ? 0xFF0400 : 0xFF03FF;
552
if (data & ~validMask)
553
snprintf(buffer, bufsize, "Block transfer dst: high=%02x, w=%d (addr %08x, extra %x)", data >> 16, xferDstW, xferDst, data & ~validMask);
554
else
555
snprintf(buffer, bufsize, "Block transfer dst: high=%02x, w=%d (addr %08x)", data >> 16, xferDstW, xferDst);
556
break;
557
}
558
559
case GE_CMD_TRANSFERSRCPOS:
560
{
561
u32 x = (data & 1023);
562
u32 y = ((data>>10) & 1023);
563
if (data & 0xF00000)
564
snprintf(buffer, bufsize, "Block transfer src rect TL: %i, %i (extra %x)", x, y, data >> 20);
565
else
566
snprintf(buffer, bufsize, "Block transfer src rect TL: %i, %i", x, y);
567
break;
568
}
569
570
case GE_CMD_TRANSFERDSTPOS:
571
{
572
u32 x = (data & 1023);
573
u32 y = ((data>>10) & 1023);
574
if (data & 0xF00000)
575
snprintf(buffer, bufsize, "Block transfer dst rect TL: %d, %d (extra %x)", x, y, data >> 20);
576
else
577
snprintf(buffer, bufsize, "Block transfer dst rect TL: %d, %d", x, y);
578
break;
579
}
580
581
case GE_CMD_TRANSFERSIZE:
582
{
583
u32 w = (data & 1023)+1;
584
u32 h = ((data>>10) & 1023)+1;
585
if (data & 0xF00000)
586
snprintf(buffer, bufsize, "Block transfer rect size: %i x %i (extra %x)", w, h, data >> 20);
587
else
588
snprintf(buffer, bufsize, "Block transfer rect size: %i x %i", w, h);
589
break;
590
}
591
592
case GE_CMD_TRANSFERSTART:
593
if (data & ~1)
594
snprintf(buffer, bufsize, "Block transfer start: bpp=%d (extra %x)", (data & 1) ? 4 : 2, data & ~1);
595
else
596
snprintf(buffer, bufsize, "Block transfer start: bpp=%d", (data & 1) ? 4 : 2);
597
break;
598
599
case GE_CMD_TEXSIZE0:
600
case GE_CMD_TEXSIZE1:
601
case GE_CMD_TEXSIZE2:
602
case GE_CMD_TEXSIZE3:
603
case GE_CMD_TEXSIZE4:
604
case GE_CMD_TEXSIZE5:
605
case GE_CMD_TEXSIZE6:
606
case GE_CMD_TEXSIZE7:
607
{
608
int w = 1 << (data & 0xf);
609
int h = 1 << ((data>>8) & 0xf);
610
if ((data & ~0x0F0F) == 0 && w <= 512 && h <= 512)
611
snprintf(buffer, bufsize, "Texture size %d: %dx%d", cmd - GE_CMD_TEXSIZE0, w, h);
612
else
613
snprintf(buffer, bufsize, "Texture size %d: %dx%d (extra %06x)", cmd - GE_CMD_TEXSIZE0, w, h, data);
614
}
615
break;
616
617
case GE_CMD_ZBUFPTR:
618
{
619
snprintf(buffer, bufsize, "Zbuf ptr: %06x", data);
620
}
621
break;
622
623
case GE_CMD_ZBUFWIDTH:
624
if (data & ~0x07FC)
625
snprintf(buffer, bufsize, "Zbuf stride: 0x%x (extra %06x)", data & 0x07FC, data & ~0x07FC);
626
else
627
snprintf(buffer, bufsize, "Zbuf stride: %04x", data);
628
break;
629
630
case GE_CMD_AMBIENTCOLOR:
631
snprintf(buffer, bufsize, "Ambient color: %06x", data);
632
break;
633
634
case GE_CMD_AMBIENTALPHA:
635
if (data & ~0xFF)
636
snprintf(buffer, bufsize, "Ambient alpha: %02x (extra %04x)", data & 0xFF, data >> 8);
637
else
638
snprintf(buffer, bufsize, "Ambient alpha: %02x", data);
639
break;
640
641
case GE_CMD_MATERIALAMBIENT:
642
snprintf(buffer, bufsize, "Material ambient color: %06x", data);
643
break;
644
645
case GE_CMD_MATERIALDIFFUSE:
646
snprintf(buffer, bufsize, "Material diffuse color: %06x", data);
647
break;
648
649
case GE_CMD_MATERIALEMISSIVE:
650
snprintf(buffer, bufsize, "Material emissive color: %06x", data);
651
break;
652
653
case GE_CMD_MATERIALSPECULAR:
654
snprintf(buffer, bufsize, "Material specular color: %06x", data);
655
break;
656
657
case GE_CMD_MATERIALALPHA:
658
if (data & ~0xFF)
659
snprintf(buffer, bufsize, "Material alpha: %02x (extra %04x)", data & 0xFF, data >> 8);
660
else
661
snprintf(buffer, bufsize, "Material alpha: %02x", data);
662
break;
663
664
case GE_CMD_MATERIALSPECULARCOEF:
665
snprintf(buffer, bufsize, "Material specular coef: %f", getFloat24(data));
666
break;
667
668
case GE_CMD_SHADEMODE:
669
if (data & ~1)
670
snprintf(buffer, bufsize, "Shade: %d (%s, extra %x)", data & 1, (data & 1) ? "gouraud" : "flat", data & ~1);
671
else
672
snprintf(buffer, bufsize, "Shade: %d (%s)", data & 1, (data & 1) ? "gouraud" : "flat");
673
break;
674
675
case GE_CMD_LIGHTMODE:
676
if (data & ~1)
677
snprintf(buffer, bufsize, "Lightmode: %d (%s, extra %x)", data & 1, (data & 1) ? "separate spec" : "single color", data & ~1);
678
else
679
snprintf(buffer, bufsize, "Lightmode: %d (%s)", data & 1, (data & 1) ? "separate spec" : "single color");
680
break;
681
682
case GE_CMD_LIGHTTYPE0:
683
case GE_CMD_LIGHTTYPE1:
684
case GE_CMD_LIGHTTYPE2:
685
case GE_CMD_LIGHTTYPE3:
686
{
687
static const char *lightComputations[] = {
688
"diffuse",
689
"diffuse + spec",
690
"pow(diffuse)",
691
"unknown (diffuse?)",
692
};
693
static const char *lightTypes[] = {
694
"directional",
695
"point",
696
"spot",
697
"unknown (directional?)",
698
};
699
const int comp = (data & 0x0003) >> 0;
700
const int type = (data & 0x0300) >> 8;
701
702
if (data & ~0x0303)
703
snprintf(buffer, bufsize, "Light %d type: %s, comp: %s (extra %06x)", cmd - GE_CMD_LIGHTTYPE0, lightTypes[type], lightComputations[comp], data & ~0x0303);
704
else
705
snprintf(buffer, bufsize, "Light %d type: %s, comp: %s", cmd - GE_CMD_LIGHTTYPE0, lightTypes[type], lightComputations[comp]);
706
}
707
break;
708
709
case GE_CMD_LX0:case GE_CMD_LY0:case GE_CMD_LZ0:
710
case GE_CMD_LX1:case GE_CMD_LY1:case GE_CMD_LZ1:
711
case GE_CMD_LX2:case GE_CMD_LY2:case GE_CMD_LZ2:
712
case GE_CMD_LX3:case GE_CMD_LY3:case GE_CMD_LZ3:
713
{
714
int n = cmd - GE_CMD_LX0;
715
int l = n / 3;
716
int c = n % 3;
717
float val = getFloat24(data);
718
snprintf(buffer, bufsize, "Light %i %c pos: %f", l, c+'X', val);
719
}
720
break;
721
722
case GE_CMD_LDX0:case GE_CMD_LDY0:case GE_CMD_LDZ0:
723
case GE_CMD_LDX1:case GE_CMD_LDY1:case GE_CMD_LDZ1:
724
case GE_CMD_LDX2:case GE_CMD_LDY2:case GE_CMD_LDZ2:
725
case GE_CMD_LDX3:case GE_CMD_LDY3:case GE_CMD_LDZ3:
726
{
727
int n = cmd - GE_CMD_LDX0;
728
int l = n / 3;
729
int c = n % 3;
730
float val = getFloat24(data);
731
snprintf(buffer, bufsize, "Light %i %c dir: %f", l, c+'X', val);
732
}
733
break;
734
735
case GE_CMD_LKA0:case GE_CMD_LKB0:case GE_CMD_LKC0:
736
case GE_CMD_LKA1:case GE_CMD_LKB1:case GE_CMD_LKC1:
737
case GE_CMD_LKA2:case GE_CMD_LKB2:case GE_CMD_LKC2:
738
case GE_CMD_LKA3:case GE_CMD_LKB3:case GE_CMD_LKC3:
739
{
740
int n = cmd - GE_CMD_LKA0;
741
int l = n / 3;
742
int c = n % 3;
743
float val = getFloat24(data);
744
snprintf(buffer, bufsize, "Light %i %c att: %f", l, c+'X', val);
745
}
746
break;
747
748
case GE_CMD_LKS0:
749
case GE_CMD_LKS1:
750
case GE_CMD_LKS2:
751
case GE_CMD_LKS3:
752
snprintf(buffer, bufsize, "Light %d spot exponent: %f", cmd - GE_CMD_LKS0, getFloat24(data));
753
break;
754
755
case GE_CMD_LKO0:
756
case GE_CMD_LKO1:
757
case GE_CMD_LKO2:
758
case GE_CMD_LKO3:
759
snprintf(buffer, bufsize, "Light %d spot cutoff: %f", cmd - GE_CMD_LKO0, getFloat24(data));
760
break;
761
762
case GE_CMD_LAC0:case GE_CMD_LAC1:case GE_CMD_LAC2:case GE_CMD_LAC3:
763
case GE_CMD_LDC0:case GE_CMD_LDC1:case GE_CMD_LDC2:case GE_CMD_LDC3:
764
case GE_CMD_LSC0:case GE_CMD_LSC1:case GE_CMD_LSC2:case GE_CMD_LSC3:
765
{
766
float r = (float)(data & 0xff)/255.0f;
767
float g = (float)((data>>8) & 0xff)/255.0f;
768
float b = (float)(data>>16)/255.0f;
769
770
static const char * const lightColorTypes[] = {
771
"ambient",
772
"diffuse",
773
"specular",
774
};
775
776
int l = (cmd - GE_CMD_LAC0) / 3;
777
int t = (cmd - GE_CMD_LAC0) % 3;
778
snprintf(buffer, bufsize, "Light %d %s color: %f %f %f", l, lightColorTypes[t], r, g, b);
779
}
780
break;
781
782
case GE_CMD_VIEWPORTXSCALE:
783
snprintf(buffer, bufsize, "Viewport X scale: %f", getFloat24(data));
784
break;
785
case GE_CMD_VIEWPORTYSCALE:
786
snprintf(buffer, bufsize, "Viewport Y scale: %f", getFloat24(data));
787
break;
788
case GE_CMD_VIEWPORTZSCALE:
789
snprintf(buffer, bufsize, "Viewport Z scale: %f", getFloat24(data));
790
break;
791
case GE_CMD_VIEWPORTXCENTER:
792
snprintf(buffer, bufsize, "Viewport X center: %f", getFloat24(data));
793
break;
794
case GE_CMD_VIEWPORTYCENTER:
795
snprintf(buffer, bufsize, "Viewport Y center: %f", getFloat24(data));
796
break;
797
case GE_CMD_VIEWPORTZCENTER:
798
snprintf(buffer, bufsize, "Viewport Z center: %f", getFloat24(data));
799
break;
800
801
case GE_CMD_LIGHTENABLE0:
802
case GE_CMD_LIGHTENABLE1:
803
case GE_CMD_LIGHTENABLE2:
804
case GE_CMD_LIGHTENABLE3:
805
snprintf(buffer, bufsize, "Light %i enable: %d", cmd-GE_CMD_LIGHTENABLE0, data);
806
break;
807
808
case GE_CMD_CULL:
809
if (data & ~1)
810
snprintf(buffer, bufsize, "Cull: %s (extra %06x)", (data & 1) ? "back (CCW)" : "front (CW)", data & ~1);
811
else
812
snprintf(buffer, bufsize, "Cull: %s", (data & 1) ? "back (CCW)" : "front (CW)");
813
break;
814
815
case GE_CMD_PATCHDIVISION:
816
{
817
int patch_div_s = data & 0x7F;
818
int patch_div_t = (data >> 8) & 0x7F;
819
if (data & 0xFF8080)
820
snprintf(buffer, bufsize, "Patch subdivision: %d x %d (extra %x)", patch_div_s, patch_div_t, data & 0xFF8080);
821
else
822
snprintf(buffer, bufsize, "Patch subdivision: %d x %d", patch_div_s, patch_div_t);
823
}
824
break;
825
826
case GE_CMD_PATCHPRIMITIVE:
827
{
828
static const char *patchPrims[] = {
829
"triangles",
830
"lines",
831
"points",
832
"unknown/points",
833
};
834
if (data & ~3)
835
snprintf(buffer, bufsize, "Patch Primitive: %s (extra %06x)", patchPrims[data & 3], data & ~3);
836
else
837
snprintf(buffer, bufsize, "Patch Primitive: %s", patchPrims[data & 3]);
838
}
839
break;
840
841
case GE_CMD_PATCHFACING:
842
if (data & ~1)
843
snprintf(buffer, bufsize, "Patch Facing: %s (extra %06x)", (data & 1) ? "reversed normals" : "standard normals", data & ~1);
844
else
845
snprintf(buffer, bufsize, "Patch Facing: %s", (data & 1) ? "reversed normals" : "standard normals");
846
break;
847
848
case GE_CMD_REVERSENORMAL:
849
if (data & ~1)
850
snprintf(buffer, bufsize, "Reverse normal: %s (extra %06x)", (data & 1) ? "reversed" : "standard", data & ~1);
851
else
852
snprintf(buffer, bufsize, "Reverse normal: %s", (data & 1) ? "reversed" : "standard");
853
break;
854
855
case GE_CMD_MATERIALUPDATE:
856
{
857
static const char *materialTypes[] = {
858
"none",
859
"ambient",
860
"diffuse",
861
"ambient, diffuse",
862
"specular",
863
"ambient, specular",
864
"diffuse, specular",
865
"ambient, diffuse, specular",
866
};
867
if (data & ~7)
868
snprintf(buffer, bufsize, "Material update: %s (extra %06x)", materialTypes[data & 7], data & ~7);
869
else
870
snprintf(buffer, bufsize, "Material update: %s", materialTypes[data & 7]);
871
}
872
break;
873
874
875
//////////////////////////////////////////////////////////////////
876
// CLEARING
877
//////////////////////////////////////////////////////////////////
878
case GE_CMD_CLEARMODE:
879
{
880
const char *clearModes[] = {
881
"on",
882
"on, color",
883
"on, alpha/stencil",
884
"on, color, alpha/stencil",
885
"on, depth",
886
"on, color, depth",
887
"on, alpha/stencil, depth",
888
"on, color, alpha/stencil, depth",
889
};
890
891
const char *mode;
892
if (data & 1)
893
mode = clearModes[(data >> 8) & 7];
894
else
895
mode = "off";
896
if (data & ~0x0701)
897
snprintf(buffer, bufsize, "Clear mode: %s (extra %06x)", mode, data & ~0x0701);
898
else
899
snprintf(buffer, bufsize, "Clear mode: %s", mode);
900
}
901
break;
902
903
904
//////////////////////////////////////////////////////////////////
905
// ALPHA BLENDING
906
//////////////////////////////////////////////////////////////////
907
case GE_CMD_ALPHABLENDENABLE:
908
snprintf(buffer, bufsize, "Alpha blend enable: %d", data);
909
break;
910
911
case GE_CMD_BLENDMODE:
912
{
913
const char *blendModes[] = {
914
"add",
915
"subtract",
916
"reverse subtract",
917
"min",
918
"max",
919
"abs subtract",
920
"unsupported1",
921
"unsupported2",
922
};
923
const char *blendFactorsA[16] = {
924
"dst",
925
"1.0 - dst",
926
"src.a",
927
"1.0 - src.a",
928
"dst.a",
929
"1.0 - dst.a",
930
"2.0 * src.a",
931
"1.0 - 2.0 * src.a",
932
"2.0 * dst.a",
933
"1.0 - 2.0 * dst.a",
934
"fixed",
935
"fixed2",
936
"fixed3",
937
"fixed4",
938
"fixed5",
939
};
940
const char *blendFactorsB[16] = {
941
"src",
942
"1.0 - src",
943
"src.a",
944
"1.0 - src.a",
945
"dst.a",
946
"1.0 - dst.a",
947
"2.0 * src.a",
948
"1.0 - 2.0 * src.a",
949
"2.0 * dst.a",
950
"1.0 - 2.0 * dst.a",
951
"fixed",
952
"fixed2",
953
"fixed3",
954
"fixed4",
955
"fixed5",
956
};
957
958
const char *blendFactorA = blendFactorsA[(data >> 0) & 0xF];
959
const char *blendFactorB = blendFactorsB[(data >> 4) & 0xF];
960
const char *blendMode = blendModes[(data >> 8) & 0x7];
961
962
if (data & ~0xFF0007FF)
963
snprintf(buffer, bufsize, "Blend mode: %s %s, %s (extra: %06x)", blendMode, blendFactorA, blendFactorB, data & ~0xFF0007FF);
964
else
965
snprintf(buffer, bufsize, "Blend mode: %s %s, %s", blendMode, blendFactorA, blendFactorB);
966
}
967
break;
968
969
case GE_CMD_BLENDFIXEDA:
970
snprintf(buffer, bufsize, "Blend fix A: %06x", data);
971
break;
972
973
case GE_CMD_BLENDFIXEDB:
974
snprintf(buffer, bufsize, "Blend fix B: %06x", data);
975
break;
976
977
case GE_CMD_ALPHATESTENABLE:
978
snprintf(buffer, bufsize, "Alpha test enable: %d", data);
979
break;
980
981
case GE_CMD_ALPHATEST:
982
{
983
const char *alphaTestFuncs[] = { " NEVER ", " ALWAYS ", " == ", " != ", " < ", " <= ", " > ", " >= " };
984
if (data & ~0xFFFF07)
985
snprintf(buffer, bufsize, "Alpha test: (src.a & %02x)%s%02x (extra %06x)", (data >> 16) & 0xFF, alphaTestFuncs[data & 7], (data >> 8) & 0xFF, data & ~0xFFFF07);
986
else
987
snprintf(buffer, bufsize, "Alpha test: (src.a & %02x)%s%02x", (data >> 16) & 0xFF, alphaTestFuncs[data & 7], (data >> 8) & 0xFF);
988
}
989
break;
990
991
case GE_CMD_ANTIALIASENABLE:
992
snprintf(buffer, bufsize, "Antialias enable: %d", data);
993
break;
994
995
case GE_CMD_PATCHCULLENABLE:
996
snprintf(buffer, bufsize, "Patch cull enable: %d", data);
997
break;
998
999
case GE_CMD_COLORTESTENABLE:
1000
snprintf(buffer, bufsize, "Color test enable: %d", data);
1001
break;
1002
1003
case GE_CMD_LOGICOPENABLE:
1004
snprintf(buffer, bufsize, "Logic op enable: %d", data);
1005
break;
1006
1007
case GE_CMD_TEXFUNC:
1008
{
1009
const char * const texfuncs[] = {
1010
"modulate",
1011
"decal",
1012
"blend",
1013
"replace",
1014
"add",
1015
"add2",
1016
"add3",
1017
"add4",
1018
};
1019
if (data & ~0x10107)
1020
snprintf(buffer, bufsize, "TexFunc %d %s %s%s (extra %x)", data & 7, data & 0x100 ? "RGBA" : "RGB", texfuncs[data & 7], data & 0x10000 ? ", color double" : "", data & ~0x10107);
1021
else
1022
snprintf(buffer, bufsize, "TexFunc %d %s %s%s", data & 7, data & 0x100 ? "RGBA" : "RGB", texfuncs[data & 7], data & 0x10000 ? ", color double" : "");
1023
}
1024
break;
1025
1026
case GE_CMD_TEXFILTER:
1027
{
1028
static const char * const textureFilters[] = {
1029
"nearest",
1030
"linear",
1031
"nearest, invalid",
1032
"linear, invalid",
1033
"nearest, mipmap nearest",
1034
"linear, mipmap nearest",
1035
"nearest, mipmap linear",
1036
"linear, mipmap linear",
1037
};
1038
int min = data & 7;
1039
int mag = (data >> 8) & 1;
1040
if (data & ~0x107)
1041
snprintf(buffer, bufsize, "TexFilter min: %s, mag: %s (extra %x)", textureFilters[min], textureFilters[mag], data & ~0x107);
1042
else
1043
snprintf(buffer, bufsize, "TexFilter min: %s, mag: %s", textureFilters[min], textureFilters[mag]);
1044
}
1045
break;
1046
1047
case GE_CMD_TEXENVCOLOR:
1048
snprintf(buffer, bufsize, "TexEnvColor %06x", data);
1049
break;
1050
1051
case GE_CMD_TEXMODE:
1052
if (data & ~0x070101)
1053
snprintf(buffer, bufsize, "TexMode %s, %d levels, %s (extra %06x)", (data & 1) ? "swizzle" : "no swizzle", (data >> 16) & 7, (data >> 8) & 1 ? "separate cluts" : "shared clut", data & ~0x070101);
1054
else
1055
snprintf(buffer, bufsize, "TexMode %s, %d levels, %s", (data & 1) ? "swizzle" : "no swizzle", (data >> 16) & 7, (data >> 8) & 1 ? "separate cluts" : "shared clut");
1056
break;
1057
1058
case GE_CMD_TEXFORMAT:
1059
{
1060
static const char * const texformats[] = {
1061
"5650",
1062
"5551",
1063
"4444",
1064
"8888",
1065
"CLUT4",
1066
"CLUT8",
1067
"CLUT16",
1068
"CLUT32",
1069
"DXT1",
1070
"DXT3",
1071
"DXT5",
1072
"unsupported1",
1073
"unsupported2",
1074
"unsupported3",
1075
"unsupported4",
1076
"unsupported5",
1077
};
1078
if (data & ~0xF)
1079
snprintf(buffer, bufsize, "TexFormat %s (extra %06x)", texformats[data & 0xF], data & ~0xF);
1080
else
1081
snprintf(buffer, bufsize, "TexFormat %s", texformats[data & 0xF]);
1082
}
1083
break;
1084
1085
case GE_CMD_TEXFLUSH:
1086
if (data)
1087
snprintf(buffer, bufsize, "TexFlush: %x", data);
1088
else
1089
snprintf(buffer, bufsize, "TexFlush");
1090
break;
1091
1092
case GE_CMD_TEXSYNC:
1093
if (data)
1094
snprintf(buffer, bufsize, "TexSync: %x", data);
1095
else
1096
snprintf(buffer, bufsize, "TexSync");
1097
break;
1098
1099
case GE_CMD_TEXWRAP:
1100
if (data & ~0x0101)
1101
snprintf(buffer, bufsize, "TexWrap %s s, %s t (extra %x)", data & 1 ? "clamp" : "wrap", data & 0x100 ? "clamp" : "wrap", data & ~0x0101);
1102
else
1103
snprintf(buffer, bufsize, "TexWrap %s s, %s t", data & 1 ? "clamp" : "wrap", data & 0x100 ? "clamp" : "wrap");
1104
break;
1105
1106
case GE_CMD_TEXLEVEL:
1107
{
1108
static const char * const mipLevelModes[] = {
1109
"auto + bias",
1110
"bias",
1111
"slope + bias",
1112
"invalid + bias",
1113
};
1114
const int biasFixed = (s8)(data >> 16);
1115
const float bias = (float)biasFixed / 16.0f;
1116
if (data & ~0xFF0003)
1117
snprintf(buffer, bufsize, "TexLevel mode: %s Offset: %f / %d (extra %x)", mipLevelModes[data & 3], bias, biasFixed, data & ~0xFF0003);
1118
else
1119
snprintf(buffer, bufsize, "TexLevel mode: %s Offset: %f / %d", mipLevelModes[data & 3], bias, biasFixed);
1120
}
1121
break;
1122
1123
case GE_CMD_FOG1:
1124
snprintf(buffer, bufsize, "Fog end %f", getFloat24(data));
1125
break;
1126
1127
case GE_CMD_FOG2:
1128
snprintf(buffer, bufsize, "Fog slope %f", getFloat24(data));
1129
break;
1130
1131
case GE_CMD_FOGCOLOR:
1132
snprintf(buffer, bufsize, "FogColor %06x", data);
1133
break;
1134
1135
case GE_CMD_TEXLODSLOPE:
1136
snprintf(buffer, bufsize, "TexLodSlope %f", getFloat24(data));
1137
break;
1138
1139
//////////////////////////////////////////////////////////////////
1140
// Z/STENCIL TESTING
1141
//////////////////////////////////////////////////////////////////
1142
1143
case GE_CMD_ZTESTENABLE:
1144
if (data & ~1)
1145
snprintf(buffer, bufsize, "Z test enable: %d (extra %x)", data & 1, data);
1146
else
1147
snprintf(buffer, bufsize, "Z test enable: %d", data & 1);
1148
break;
1149
1150
case GE_CMD_STENCILOP:
1151
{
1152
static const char * const stencilOps[] = { "KEEP", "ZERO", "REPLACE", "INVERT", "INCREMENT", "DECREMENT", "unsupported1", "unsupported2" };
1153
snprintf(buffer, bufsize, "Stencil op: fail=%s, pass/depthfail=%s, pass=%s", stencilOps[data & 7], stencilOps[(data >> 8) & 7], stencilOps[(data >> 16) & 7]);
1154
}
1155
break;
1156
1157
case GE_CMD_STENCILTEST:
1158
{
1159
static const char * const zTestFuncs[] = { " NEVER ", " ALWAYS ", " == ", " != ", " < ", " <= ", " > ", " >= " };
1160
if (data & ~0xFFFF07)
1161
snprintf(buffer, bufsize, "Stencil test: %02x%s(dst.a & %02x) (extra %06x)", (data >> 8) & 0xFF, zTestFuncs[data & 7], (data >> 16) & 0xFF, data & ~0xFFFF07);
1162
else
1163
snprintf(buffer, bufsize, "Stencil test: %02x%s(dst.a & %02x)", (data >> 8) & 0xFF, zTestFuncs[data & 7], (data >> 16) & 0xFF);
1164
}
1165
break;
1166
1167
case GE_CMD_STENCILTESTENABLE:
1168
snprintf(buffer, bufsize, "Stencil test enable: %d", data);
1169
break;
1170
1171
case GE_CMD_ZTEST:
1172
{
1173
static const char * const zTestFuncs[] = { "NEVER", "ALWAYS", "==", "!=", "<", "<=", ">", ">=" };
1174
if (data & ~7)
1175
snprintf(buffer, bufsize, "Z test mode: %s (extra %06x)", zTestFuncs[data & 7], data & ~7);
1176
else
1177
snprintf(buffer, bufsize, "Z test mode: %s", zTestFuncs[data & 7]);
1178
}
1179
break;
1180
1181
case GE_CMD_MORPHWEIGHT0:
1182
case GE_CMD_MORPHWEIGHT1:
1183
case GE_CMD_MORPHWEIGHT2:
1184
case GE_CMD_MORPHWEIGHT3:
1185
case GE_CMD_MORPHWEIGHT4:
1186
case GE_CMD_MORPHWEIGHT5:
1187
case GE_CMD_MORPHWEIGHT6:
1188
case GE_CMD_MORPHWEIGHT7:
1189
{
1190
int index = cmd - GE_CMD_MORPHWEIGHT0;
1191
float weight = getFloat24(data);
1192
snprintf(buffer, bufsize, "MorphWeight %i = %f", index, weight);
1193
}
1194
break;
1195
1196
case GE_CMD_DITH0:
1197
case GE_CMD_DITH1:
1198
case GE_CMD_DITH2:
1199
case GE_CMD_DITH3:
1200
snprintf(buffer, bufsize, "DitherMatrix %i = %06x",cmd-GE_CMD_DITH0,data);
1201
break;
1202
1203
case GE_CMD_LOGICOP:
1204
{
1205
const char * const logicOps[] = {
1206
"clear",
1207
"and",
1208
"reverse and",
1209
"copy",
1210
"inverted and",
1211
"noop",
1212
"xor",
1213
"or",
1214
"negated or",
1215
"equivalence",
1216
"inverted",
1217
"reverse or",
1218
"inverted copy",
1219
"inverted or",
1220
"negated and",
1221
"set",
1222
};
1223
if (data & ~0xF)
1224
snprintf(buffer, bufsize, "LogicOp: %s (%06x)", logicOps[data & 0xF], data & ~0xF);
1225
else
1226
snprintf(buffer, bufsize, "LogicOp: %s", logicOps[data & 0xF]);
1227
}
1228
break;
1229
1230
case GE_CMD_ZWRITEDISABLE:
1231
if (data & ~1)
1232
snprintf(buffer, bufsize, "ZMask: %s (extra %06x)", data & 1 ? "disable write" : "allow write", data & ~1);
1233
else
1234
snprintf(buffer, bufsize, "ZMask: %s", data & 1 ? "disable write" : "allow write");
1235
break;
1236
1237
case GE_CMD_COLORTEST:
1238
{
1239
const char *colorTests[] = {" NEVER ", " ALWAYS ", " == ", " != "};
1240
if (data & ~3)
1241
snprintf(buffer, bufsize, "ColorTest: (src.rgb & cmask)%s(dst.rgb & cmask) (extra %06x)", colorTests[data & 3], data & ~3);
1242
else
1243
snprintf(buffer, bufsize, "ColorTest: (src.rgb & cmask)%s(dst.rgb & cmask)", colorTests[data & 3]);
1244
}
1245
break;
1246
1247
case GE_CMD_COLORREF:
1248
snprintf(buffer, bufsize, "ColorRef: %06x", data);
1249
break;
1250
1251
case GE_CMD_COLORTESTMASK:
1252
snprintf(buffer, bufsize, "ColorTestMask: %06x", data);
1253
break;
1254
1255
case GE_CMD_MASKRGB:
1256
snprintf(buffer, bufsize, "MaskRGB: %06x (bits not to write)", data);
1257
break;
1258
1259
case GE_CMD_MASKALPHA:
1260
if (data & ~0xFF)
1261
snprintf(buffer, bufsize, "MaskAlpha: %02x (bits not to write) (extra %04x)", data & 0xFF, data >> 8);
1262
else
1263
snprintf(buffer, bufsize, "MaskAlpha: %02x (bits not to write)", data & 0xFF);
1264
break;
1265
1266
case GE_CMD_WORLDMATRIXNUMBER:
1267
if (data & ~0xF)
1268
snprintf(buffer, bufsize, "World # %d (extra %x)", data & 0xF, data & ~0xF);
1269
else
1270
snprintf(buffer, bufsize, "World # %d", data & 0xF);
1271
break;
1272
1273
case GE_CMD_WORLDMATRIXDATA:
1274
snprintf(buffer, bufsize, "World data # %f", getFloat24(data));
1275
break;
1276
1277
case GE_CMD_VIEWMATRIXNUMBER:
1278
if (data & ~0xF)
1279
snprintf(buffer, bufsize, "VIEW # %d (extra %x)", data & 0xF, data & ~0xF);
1280
else
1281
snprintf(buffer, bufsize, "VIEW # %d", data & 0xF);
1282
break;
1283
1284
case GE_CMD_VIEWMATRIXDATA:
1285
snprintf(buffer, bufsize, "VIEW data # %f", getFloat24(data));
1286
break;
1287
1288
case GE_CMD_PROJMATRIXNUMBER:
1289
if (data & ~0xF)
1290
snprintf(buffer, bufsize, "PROJECTION # %d (extra %x)", data & 0xF, data & ~0xF);
1291
else
1292
snprintf(buffer, bufsize, "PROJECTION # %d", data & 0xF);
1293
break;
1294
1295
case GE_CMD_PROJMATRIXDATA:
1296
snprintf(buffer, bufsize, "PROJECTION matrix data # %f", getFloat24(data));
1297
break;
1298
1299
case GE_CMD_TGENMATRIXNUMBER:
1300
if (data & ~0xF)
1301
snprintf(buffer, bufsize, "TGEN # %d (extra %x)", data & 0xF, data & ~0xF);
1302
else
1303
snprintf(buffer, bufsize, "TGEN # %d", data & 0xF);
1304
break;
1305
1306
case GE_CMD_TGENMATRIXDATA:
1307
snprintf(buffer, bufsize, "TGEN data # %f", getFloat24(data));
1308
break;
1309
1310
case GE_CMD_BONEMATRIXNUMBER:
1311
if (data & ~0x7F)
1312
snprintf(buffer, bufsize, "BONE #%d (extra %x)", data & 0x7F, data & ~0x7F);
1313
else
1314
snprintf(buffer, bufsize, "BONE #%d", data & 0x7F);
1315
break;
1316
1317
case GE_CMD_BONEMATRIXDATA:
1318
snprintf(buffer, bufsize, "BONE data # %f", getFloat24(data));
1319
break;
1320
1321
case GE_CMD_VSCX:
1322
if (data & ~0xFFFF)
1323
snprintf(buffer, bufsize, "Vertex screen X: %04x / %d with sub %d (extra %02x)", data & 0xFFFF, data >> 4, data & 0xF, data >> 16);
1324
else
1325
snprintf(buffer, bufsize, "Vertex screen X: %04x / %d with sub %d", data & 0xFFFF, data >> 4, data & 0xF);
1326
break;
1327
1328
case GE_CMD_VSCY:
1329
if (data & ~0xFFFF)
1330
snprintf(buffer, bufsize, "Vertex screen Y: %04x / %d with sub %d (extra %02x)", data & 0xFFFF, data >> 4, data & 0xF, data >> 16);
1331
else
1332
snprintf(buffer, bufsize, "Vertex screen Y: %04x / %d with sub %d", data & 0xFFFF, data >> 4, data & 0xF);
1333
break;
1334
1335
case GE_CMD_VSCZ:
1336
if (data & ~0xFFFF)
1337
snprintf(buffer, bufsize, "Vertex Z: %04x (extra %02x)", data & 0xFFFF, data >> 16);
1338
else
1339
snprintf(buffer, bufsize, "Vertex Z: %04x", data & 0xFFFF);
1340
break;
1341
1342
case GE_CMD_VTCS:
1343
snprintf(buffer, bufsize, "Vertex tex S: %f", getFloat24(data));
1344
break;
1345
1346
case GE_CMD_VTCT:
1347
snprintf(buffer, bufsize, "Vertex tex T: %f", getFloat24(data));
1348
break;
1349
1350
case GE_CMD_VTCQ:
1351
snprintf(buffer, bufsize, "Vertex tex Q: %f", getFloat24(data));
1352
break;
1353
1354
case GE_CMD_VCV:
1355
snprintf(buffer, bufsize, "Vertex color: %06x", data);
1356
break;
1357
1358
case GE_CMD_VAP:
1359
{
1360
bool antialias = (data & GE_IMM_ANTIALIAS) != 0;
1361
int clip = (data & GE_IMM_CLIPMASK) >> 12;
1362
bool shading = (data & GE_IMM_SHADING) != 0;
1363
bool cullEnable = (data & GE_IMM_CULLENABLE) != 0;
1364
int cullMode = (data & GE_IMM_CULLFACE) != 0 ? 1 : 0;
1365
bool texturing = (data & GE_IMM_TEXTURE) != 0;
1366
bool dither = (data & GE_IMM_DITHER) != 0;
1367
char *p = buffer;
1368
p += snprintf(p, bufsize - (p - buffer), "Vertex draw: alpha=%02x, prim=%s", data & 0xFF, primTypes[(data >> 8) & 7]);
1369
if (antialias)
1370
p += snprintf(p, bufsize - (p - buffer), ", antialias");
1371
if (clip != 0)
1372
p += snprintf(p, bufsize - (p - buffer), ", clip=%02x", clip);
1373
if (shading)
1374
p += snprintf(p, bufsize - (p - buffer), ", shading");
1375
if (cullEnable)
1376
p += snprintf(p, bufsize - (p - buffer), ", cull=%s", cullMode == 1 ? "back (CCW)" : "front (CW)");
1377
if (texturing)
1378
p += snprintf(p, bufsize - (p - buffer), ", texturing");
1379
if (dither)
1380
p += snprintf(p, bufsize - (p - buffer), ", dither");
1381
}
1382
break;
1383
1384
case GE_CMD_VFC:
1385
if (data & ~0xFF)
1386
snprintf(buffer, bufsize, "Vertex fog: %02x / %f (extra %04x)", data & 0xFF, (data & 0xFF) / 255.0f, data >> 8);
1387
else
1388
snprintf(buffer, bufsize, "Vertex fog: %02x / %f", data & 0xFF, (data & 0xFF) / 255.0f);
1389
break;
1390
1391
case GE_CMD_VSCV:
1392
snprintf(buffer, bufsize, "Vertex secondary color: %06x", data);
1393
break;
1394
1395
default:
1396
snprintf(buffer, bufsize, "Unknown: %08x", op);
1397
break;
1398
}
1399
}
1400
1401
1402