Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/ucode00.h
2 views
1
/*
2
* Glide64 - Glide video plugin for Nintendo 64 emulators.
3
* Copyright (c) 2002 Dave2001
4
* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
*/
20
21
//****************************************************************
22
//
23
// Glide64 - Glide Plugin for Nintendo 64 emulators
24
// Project started on December 29th, 2001
25
//
26
// Authors:
27
// Dave2001, original author, founded the project in 2001, left it in 2002
28
// Gugaman, joined the project in 2002, left it in 2002
29
// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
30
// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
31
//
32
//****************************************************************
33
//
34
// To modify Glide64:
35
// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
36
// * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
37
//
38
//****************************************************************
39
40
#define ucode_Fast3D 0
41
#define ucode_F3DEX 1
42
#define ucode_F3DEX2 2
43
#define ucode_WaveRace 3
44
#define ucode_StarWars 4
45
#define ucode_DiddyKong 5
46
#define ucode_S2DEX 6
47
#define ucode_PerfectDark 7
48
#define ucode_CBFD 8
49
#define ucode_zSort 9
50
#define ucode_Turbo3d 21
51
52
static void rsp_vertex(int v0, int n)
53
{
54
wxUint32 addr = segoffset(rdp.cmd1) & 0x00FFFFFF;
55
int i;
56
float x, y, z;
57
58
rdp.v0 = v0; // Current vertex
59
rdp.vn = n; // Number to copy
60
61
// This is special, not handled in update(), but here
62
// * Matrix Pre-multiplication idea by Gonetz ([email protected])
63
if (rdp.update & UPDATE_MULT_MAT)
64
{
65
rdp.update ^= UPDATE_MULT_MAT;
66
MulMatrices(rdp.model, rdp.proj, rdp.combined);
67
}
68
// *
69
70
// This is special, not handled in update()
71
if (rdp.update & UPDATE_LIGHTS)
72
{
73
rdp.update ^= UPDATE_LIGHTS;
74
75
// Calculate light vectors
76
for (wxUint32 l=0; l<rdp.num_lights; l++)
77
{
78
InverseTransformVector(&rdp.light[l].dir_x, rdp.light_vector[l], rdp.model);
79
NormalizeVector (rdp.light_vector[l]);
80
}
81
}
82
83
FRDP ("rsp:vertex v0:%d, n:%d, from: %08lx\n", v0, n, addr);
84
85
for (i=0; i < (n<<4); i+=16)
86
{
87
VERTEX *v = &rdp.vtx[v0 + (i>>4)];
88
x = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 0)^1];
89
y = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 1)^1];
90
z = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 2)^1];
91
v->flags = ((wxUint16*)gfx.RDRAM)[(((addr+i) >> 1) + 3)^1];
92
v->ou = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 4)^1];
93
v->ov = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 5)^1];
94
v->uv_scaled = 0;
95
v->a = ((wxUint8*)gfx.RDRAM)[(addr+i + 15)^3];
96
97
v->x = x*rdp.combined[0][0] + y*rdp.combined[1][0] + z*rdp.combined[2][0] + rdp.combined[3][0];
98
v->y = x*rdp.combined[0][1] + y*rdp.combined[1][1] + z*rdp.combined[2][1] + rdp.combined[3][1];
99
v->z = x*rdp.combined[0][2] + y*rdp.combined[1][2] + z*rdp.combined[2][2] + rdp.combined[3][2];
100
v->w = x*rdp.combined[0][3] + y*rdp.combined[1][3] + z*rdp.combined[2][3] + rdp.combined[3][3];
101
102
103
if (fabs(v->w) < 0.001) v->w = 0.001f;
104
v->oow = 1.0f / v->w;
105
v->x_w = v->x * v->oow;
106
v->y_w = v->y * v->oow;
107
v->z_w = v->z * v->oow;
108
CalculateFog (v);
109
110
v->uv_calculated = 0xFFFFFFFF;
111
v->screen_translated = 0;
112
v->shade_mod = 0;
113
114
v->scr_off = 0;
115
if (v->x < -v->w) v->scr_off |= 1;
116
if (v->x > v->w) v->scr_off |= 2;
117
if (v->y < -v->w) v->scr_off |= 4;
118
if (v->y > v->w) v->scr_off |= 8;
119
if (v->w < 0.1f) v->scr_off |= 16;
120
// if (v->z_w > 1.0f) v->scr_off |= 32;
121
122
if (rdp.geom_mode & 0x00020000)
123
{
124
v->vec[0] = ((char*)gfx.RDRAM)[(addr+i + 12)^3];
125
v->vec[1] = ((char*)gfx.RDRAM)[(addr+i + 13)^3];
126
v->vec[2] = ((char*)gfx.RDRAM)[(addr+i + 14)^3];
127
if (rdp.geom_mode & 0x40000)
128
{
129
if (rdp.geom_mode & 0x80000)
130
calc_linear (v);
131
else
132
calc_sphere (v);
133
}
134
NormalizeVector (v->vec);
135
136
calc_light (v);
137
}
138
else
139
{
140
v->r = ((wxUint8*)gfx.RDRAM)[(addr+i + 12)^3];
141
v->g = ((wxUint8*)gfx.RDRAM)[(addr+i + 13)^3];
142
v->b = ((wxUint8*)gfx.RDRAM)[(addr+i + 14)^3];
143
}
144
#ifdef EXTREME_LOGGING
145
FRDP ("v%d - x: %f, y: %f, z: %f, w: %f, u: %f, v: %f, f: %f, z_w: %f, r=%d, g=%d, b=%d, a=%d\n", i>>4, v->x, v->y, v->z, v->w, v->ou*rdp.tiles[rdp.cur_tile].s_scale, v->ov*rdp.tiles[rdp.cur_tile].t_scale, v->f, v->z_w, v->r, v->g, v->b, v->a);
146
#endif
147
148
}
149
}
150
151
static void rsp_tri1(VERTEX **v, wxUint16 linew = 0)
152
{
153
if (cull_tri(v))
154
rdp.tri_n ++;
155
else
156
{
157
update ();
158
draw_tri (v, linew);
159
rdp.tri_n ++;
160
}
161
}
162
163
static void rsp_tri2 (VERTEX **v)
164
{
165
int updated = 0;
166
167
if (cull_tri(v))
168
rdp.tri_n ++;
169
else
170
{
171
updated = 1;
172
update ();
173
174
draw_tri (v);
175
rdp.tri_n ++;
176
}
177
178
if (cull_tri(v+3))
179
rdp.tri_n ++;
180
else
181
{
182
if (!updated)
183
update ();
184
185
draw_tri (v+3);
186
rdp.tri_n ++;
187
}
188
}
189
190
//
191
// uc0:vertex - loads vertices
192
//
193
static void uc0_vertex()
194
{
195
int v0 = (rdp.cmd0 >> 16) & 0xF; // Current vertex
196
int n = ((rdp.cmd0 >> 20) & 0xF) + 1; // Number of vertices to copy
197
rsp_vertex(v0, n);
198
}
199
200
// ** Definitions **
201
202
void modelview_load (float m[4][4])
203
{
204
memcpy (rdp.model, m, 64); // 4*4*4(float)
205
206
rdp.update |= UPDATE_MULT_MAT | UPDATE_LIGHTS;
207
}
208
209
void modelview_mul (float m[4][4])
210
{
211
DECLAREALIGN16VAR(m_src[4][4]);
212
memcpy (m_src, rdp.model, 64);
213
MulMatrices(m, m_src, rdp.model);
214
rdp.update |= UPDATE_MULT_MAT | UPDATE_LIGHTS;
215
}
216
217
void modelview_push ()
218
{
219
if (rdp.model_i == rdp.model_stack_size)
220
{
221
RDP_E ("** Model matrix stack overflow ** too many pushes\n");
222
LRDP("** Model matrix stack overflow ** too many pushes\n");
223
return;
224
}
225
226
memcpy (rdp.model_stack[rdp.model_i], rdp.model, 64);
227
rdp.model_i ++;
228
}
229
230
void modelview_pop (int num = 1)
231
{
232
if (rdp.model_i > num - 1)
233
{
234
rdp.model_i -= num;
235
}
236
else
237
{
238
RDP_E ("** Model matrix stack error ** too many pops\n");
239
LRDP("** Model matrix stack error ** too many pops\n");
240
return;
241
}
242
memcpy (rdp.model, rdp.model_stack[rdp.model_i], 64);
243
rdp.update |= UPDATE_MULT_MAT | UPDATE_LIGHTS;
244
}
245
246
void modelview_load_push (float m[4][4])
247
{
248
modelview_push ();
249
modelview_load (m);
250
}
251
252
void modelview_mul_push (float m[4][4])
253
{
254
modelview_push ();
255
modelview_mul (m);
256
}
257
258
void projection_load (float m[4][4])
259
{
260
memcpy (rdp.proj, m, 64); // 4*4*4(float)
261
262
rdp.update |= UPDATE_MULT_MAT;
263
}
264
265
void projection_mul (float m[4][4])
266
{
267
DECLAREALIGN16VAR(m_src[4][4]);
268
memcpy (m_src, rdp.proj, 64);
269
MulMatrices(m, m_src, rdp.proj);
270
rdp.update |= UPDATE_MULT_MAT;
271
}
272
273
void load_matrix (float m[4][4], wxUint32 addr)
274
{
275
FRDP ("matrix - addr: %08lx\n", addr);
276
int x,y; // matrix index
277
addr >>= 1;
278
wxUint16 * src = (wxUint16*)gfx.RDRAM;
279
for (x=0; x<16; x+=4) { // Adding 4 instead of one, just to remove mult. later
280
for (y=0; y<4; y++) {
281
m[x>>2][y] = (float)(
282
(((wxInt32)src[(addr+x+y)^1]) << 16) |
283
src[(addr+x+y+16)^1]
284
) / 65536.0f;
285
}
286
}
287
}
288
289
//
290
// uc0:matrix - performs matrix operations
291
//
292
static void uc0_matrix()
293
{
294
LRDP("uc0:matrix ");
295
296
// Use segment offset to get the address
297
wxUint32 addr = segoffset(rdp.cmd1) & 0x00FFFFFF;
298
wxUint8 command = (wxUint8)((rdp.cmd0 >> 16) & 0xFF);
299
300
DECLAREALIGN16VAR(m[4][4]);
301
load_matrix(m, addr);
302
303
switch (command)
304
{
305
case 0: // modelview mul nopush
306
LRDP("modelview mul\n");
307
modelview_mul (m);
308
break;
309
310
case 1: // projection mul nopush
311
case 5: // projection mul push, can't push projection
312
LRDP("projection mul\n");
313
projection_mul (m);
314
break;
315
316
case 2: // modelview load nopush
317
LRDP("modelview load\n");
318
modelview_load (m);
319
break;
320
321
case 3: // projection load nopush
322
case 7: // projection load push, can't push projection
323
LRDP("projection load\n");
324
projection_load (m);
325
326
break;
327
328
case 4: // modelview mul push
329
LRDP("modelview mul push\n");
330
modelview_mul_push (m);
331
break;
332
333
case 6: // modelview load push
334
LRDP("modelview load push\n");
335
modelview_load_push (m);
336
break;
337
338
default:
339
FRDP_E ("Unknown matrix command, %02lx", command);
340
FRDP ("Unknown matrix command, %02lx", command);
341
}
342
343
#ifdef EXTREME_LOGGING
344
FRDP ("{%f,%f,%f,%f}\n", m[0][0], m[0][1], m[0][2], m[0][3]);
345
FRDP ("{%f,%f,%f,%f}\n", m[1][0], m[1][1], m[1][2], m[1][3]);
346
FRDP ("{%f,%f,%f,%f}\n", m[2][0], m[2][1], m[2][2], m[2][3]);
347
FRDP ("{%f,%f,%f,%f}\n", m[3][0], m[3][1], m[3][2], m[3][3]);
348
FRDP ("\nmodel\n{%f,%f,%f,%f}\n", rdp.model[0][0], rdp.model[0][1], rdp.model[0][2], rdp.model[0][3]);
349
FRDP ("{%f,%f,%f,%f}\n", rdp.model[1][0], rdp.model[1][1], rdp.model[1][2], rdp.model[1][3]);
350
FRDP ("{%f,%f,%f,%f}\n", rdp.model[2][0], rdp.model[2][1], rdp.model[2][2], rdp.model[2][3]);
351
FRDP ("{%f,%f,%f,%f}\n", rdp.model[3][0], rdp.model[3][1], rdp.model[3][2], rdp.model[3][3]);
352
FRDP ("\nproj\n{%f,%f,%f,%f}\n", rdp.proj[0][0], rdp.proj[0][1], rdp.proj[0][2], rdp.proj[0][3]);
353
FRDP ("{%f,%f,%f,%f}\n", rdp.proj[1][0], rdp.proj[1][1], rdp.proj[1][2], rdp.proj[1][3]);
354
FRDP ("{%f,%f,%f,%f}\n", rdp.proj[2][0], rdp.proj[2][1], rdp.proj[2][2], rdp.proj[2][3]);
355
FRDP ("{%f,%f,%f,%f}\n", rdp.proj[3][0], rdp.proj[3][1], rdp.proj[3][2], rdp.proj[3][3]);
356
#endif
357
}
358
359
//
360
// uc0:movemem - loads a structure with data
361
//
362
static void uc0_movemem()
363
{
364
LRDP("uc0:movemem ");
365
366
wxUint32 i,a;
367
368
// Check the command
369
switch ((rdp.cmd0 >> 16) & 0xFF)
370
{
371
case 0x80:
372
{
373
a = (segoffset(rdp.cmd1) & 0xFFFFFF) >> 1;
374
375
short scale_x = ((short*)gfx.RDRAM)[(a+0)^1] / 4;
376
short scale_y = ((short*)gfx.RDRAM)[(a+1)^1] / 4;
377
short scale_z = ((short*)gfx.RDRAM)[(a+2)^1];
378
short trans_x = ((short*)gfx.RDRAM)[(a+4)^1] / 4;
379
short trans_y = ((short*)gfx.RDRAM)[(a+5)^1] / 4;
380
short trans_z = ((short*)gfx.RDRAM)[(a+6)^1];
381
if (settings.correct_viewport)
382
{
383
scale_x = abs(scale_x);
384
scale_y = abs(scale_y);
385
}
386
rdp.view_scale[0] = scale_x * rdp.scale_x;
387
rdp.view_scale[1] = -scale_y * rdp.scale_y;
388
rdp.view_scale[2] = 32.0f * scale_z;
389
rdp.view_trans[0] = trans_x * rdp.scale_x;
390
rdp.view_trans[1] = trans_y * rdp.scale_y;
391
rdp.view_trans[2] = 32.0f * trans_z;
392
393
// there are other values than x and y, but I don't know what they do
394
395
rdp.update |= UPDATE_VIEWPORT;
396
397
FRDP ("viewport scale(%d, %d, %d), trans(%d, %d, %d), from:%08lx\n", scale_x, scale_y, scale_z,
398
trans_x, trans_y, trans_z, rdp.cmd1);
399
}
400
break;
401
402
case 0x82:
403
{
404
a = segoffset(rdp.cmd1) & 0x00ffffff;
405
char dir_x = ((char*)gfx.RDRAM)[(a+8)^3];
406
rdp.lookat[1][0] = (float)(dir_x) / 127.0f;
407
char dir_y = ((char*)gfx.RDRAM)[(a+9)^3];
408
rdp.lookat[1][1] = (float)(dir_y) / 127.0f;
409
char dir_z = ((char*)gfx.RDRAM)[(a+10)^3];
410
rdp.lookat[1][2] = (float)(dir_z) / 127.0f;
411
if (!dir_x && !dir_y)
412
rdp.use_lookat = FALSE;
413
else
414
rdp.use_lookat = TRUE;
415
FRDP("lookat_y (%f, %f, %f)\n", rdp.lookat[1][0], rdp.lookat[1][1], rdp.lookat[1][2]);
416
}
417
break;
418
419
case 0x84:
420
a = segoffset(rdp.cmd1) & 0x00ffffff;
421
rdp.lookat[0][0] = (float)(((char*)gfx.RDRAM)[(a+8)^3]) / 127.0f;
422
rdp.lookat[0][1] = (float)(((char*)gfx.RDRAM)[(a+9)^3]) / 127.0f;
423
rdp.lookat[0][2] = (float)(((char*)gfx.RDRAM)[(a+10)^3]) / 127.0f;
424
rdp.use_lookat = TRUE;
425
FRDP("lookat_x (%f, %f, %f)\n", rdp.lookat[1][0], rdp.lookat[1][1], rdp.lookat[1][2]);
426
break;
427
428
case 0x86:
429
case 0x88:
430
case 0x8a:
431
case 0x8c:
432
case 0x8e:
433
case 0x90:
434
case 0x92:
435
case 0x94:
436
// Get the light #
437
i = (((rdp.cmd0 >> 16) & 0xff) - 0x86) >> 1;
438
a = segoffset(rdp.cmd1) & 0x00ffffff;
439
440
// Get the data
441
rdp.light[i].r = (float)(((wxUint8*)gfx.RDRAM)[(a+0)^3]) / 255.0f;
442
rdp.light[i].g = (float)(((wxUint8*)gfx.RDRAM)[(a+1)^3]) / 255.0f;
443
rdp.light[i].b = (float)(((wxUint8*)gfx.RDRAM)[(a+2)^3]) / 255.0f;
444
rdp.light[i].a = 1.0f;
445
// ** Thanks to Icepir8 for pointing this out **
446
// Lighting must be signed byte instead of byte
447
rdp.light[i].dir_x = (float)(((char*)gfx.RDRAM)[(a+8)^3]) / 127.0f;
448
rdp.light[i].dir_y = (float)(((char*)gfx.RDRAM)[(a+9)^3]) / 127.0f;
449
rdp.light[i].dir_z = (float)(((char*)gfx.RDRAM)[(a+10)^3]) / 127.0f;
450
// **
451
452
//rdp.update |= UPDATE_LIGHTS;
453
454
FRDP ("light: n: %d, r: %.3f, g: %.3f, b: %.3f, x: %.3f, y: %.3f, z: %.3f\n",
455
i, rdp.light[i].r, rdp.light[i].g, rdp.light[i].b,
456
rdp.light_vector[i][0], rdp.light_vector[i][1], rdp.light_vector[i][2]);
457
break;
458
459
460
case 0x9E: //gSPForceMatrix command. Modification of uc2_movemem:matrix. Gonetz.
461
{
462
// do not update the combined matrix!
463
rdp.update &= ~UPDATE_MULT_MAT;
464
465
wxUint32 addr = segoffset(rdp.cmd1) & 0x00FFFFFF;
466
load_matrix(rdp.combined, addr);
467
468
addr = rdp.pc[rdp.pc_i] & BMASK;
469
rdp.pc[rdp.pc_i] = (addr+24) & BMASK; //skip next 3 command, b/c they all are part of gSPForceMatrix
470
471
#ifdef EXTREME_LOGGING
472
FRDP ("{%f,%f,%f,%f}\n", rdp.combined[0][0], rdp.combined[0][1], rdp.combined[0][2], rdp.combined[0][3]);
473
FRDP ("{%f,%f,%f,%f}\n", rdp.combined[1][0], rdp.combined[1][1], rdp.combined[1][2], rdp.combined[1][3]);
474
FRDP ("{%f,%f,%f,%f}\n", rdp.combined[2][0], rdp.combined[2][1], rdp.combined[2][2], rdp.combined[2][3]);
475
FRDP ("{%f,%f,%f,%f}\n", rdp.combined[3][0], rdp.combined[3][1], rdp.combined[3][2], rdp.combined[3][3]);
476
#endif
477
}
478
break;
479
480
//next 3 command should never appear since they will be skipped in previous command
481
case 0x98:
482
RDP_E ("uc0:movemem matrix 0 - ERROR!\n");
483
LRDP("matrix 0 - IGNORED\n");
484
break;
485
486
case 0x9A:
487
RDP_E ("uc0:movemem matrix 1 - ERROR!\n");
488
LRDP("matrix 1 - IGNORED\n");
489
break;
490
491
case 0x9C:
492
RDP_E ("uc0:movemem matrix 2 - ERROR!\n");
493
LRDP("matrix 2 - IGNORED\n");
494
break;
495
496
default:
497
FRDP_E ("uc0:movemem unknown (index: 0x%08lx)\n", (rdp.cmd0 >> 16) & 0xFF);
498
FRDP ("unknown (index: 0x%08lx)\n", (rdp.cmd0 >> 16) & 0xFF);
499
}
500
}
501
502
//
503
// uc0:displaylist - makes a call to another section of code
504
//
505
static void uc0_displaylist()
506
{
507
wxUint32 addr = segoffset(rdp.cmd1) & 0x00FFFFFF;
508
509
// This fixes partially Gauntlet: Legends
510
if (addr == rdp.pc[rdp.pc_i] - 8) { LRDP("display list not executed!\n"); return; }
511
512
wxUint32 push = (rdp.cmd0 >> 16) & 0xFF; // push the old location?
513
514
FRDP("uc0:displaylist: %08lx, push:%s", addr, push?"no":"yes");
515
FRDP(" (seg %d, offset %08lx)\n", (rdp.cmd1>>24)&0x0F, rdp.cmd1&0x00FFFFFF);
516
517
switch (push)
518
{
519
case 0: // push
520
if (rdp.pc_i >= 9) {
521
RDP_E ("** DL stack overflow **");
522
LRDP("** DL stack overflow **\n");
523
return;
524
}
525
rdp.pc_i ++; // go to the next PC in the stack
526
rdp.pc[rdp.pc_i] = addr; // jump to the address
527
break;
528
529
case 1: // no push
530
rdp.pc[rdp.pc_i] = addr; // just jump to the address
531
break;
532
533
default:
534
RDP_E("Unknown displaylist operation\n");
535
LRDP("Unknown displaylist operation\n");
536
}
537
}
538
539
//
540
// tri1 - renders a triangle
541
//
542
static void uc0_tri1()
543
{
544
FRDP("uc0:tri1 #%d - %d, %d, %d\n", rdp.tri_n,
545
((rdp.cmd1>>16) & 0xFF) / 10,
546
((rdp.cmd1>>8) & 0xFF) / 10,
547
(rdp.cmd1 & 0xFF) / 10);
548
549
VERTEX *v[3] = {
550
&rdp.vtx[((rdp.cmd1 >> 16) & 0xFF) / 10],
551
&rdp.vtx[((rdp.cmd1 >> 8) & 0xFF) / 10],
552
&rdp.vtx[(rdp.cmd1 & 0xFF) / 10]
553
};
554
if (settings.hacks & hack_Makers)
555
{
556
rdp.force_wrap = FALSE;
557
for (int i = 0; i < 3; i++)
558
{
559
if (v[i]->ou < 0.0f || v[i]->ov < 0.0f)
560
{
561
rdp.force_wrap = TRUE;
562
break;
563
}
564
}
565
}
566
rsp_tri1(v);
567
}
568
569
//
570
// uc0:enddl - ends a call made by uc0:displaylist
571
//
572
static void uc0_enddl()
573
{
574
LRDP("uc0:enddl\n");
575
576
if (rdp.pc_i == 0)
577
{
578
LRDP("RDP end\n");
579
580
// Halt execution here
581
rdp.halt = 1;
582
}
583
584
rdp.pc_i --;
585
}
586
587
static void uc0_culldl()
588
{
589
wxUint8 vStart = (wxUint8)((rdp.cmd0 & 0x00FFFFFF) / 40) & 0xF;
590
wxUint8 vEnd = (wxUint8)(rdp.cmd1 / 40) & 0x0F;
591
wxUint32 cond = 0;
592
VERTEX *v;
593
594
FRDP("uc0:culldl start: %d, end: %d\n", vStart, vEnd);
595
596
if (vEnd < vStart) return;
597
for (wxUint16 i=vStart; i<=vEnd; i++)
598
{
599
v = &rdp.vtx[i];
600
// Check if completely off the screen (quick frustrum clipping for 90 FOV)
601
if (v->x >= -v->w)
602
cond |= 0x01;
603
if (v->x <= v->w)
604
cond |= 0x02;
605
if (v->y >= -v->w)
606
cond |= 0x04;
607
if (v->y <= v->w)
608
cond |= 0x08;
609
if (v->w >= 0.1f)
610
cond |= 0x10;
611
612
if (cond == 0x1F)
613
return;
614
}
615
616
LRDP(" - "); // specify that the enddl is not a real command
617
uc0_enddl ();
618
}
619
620
static void uc0_popmatrix()
621
{
622
LRDP("uc0:popmatrix\n");
623
624
wxUint32 param = rdp.cmd1;
625
626
switch (param)
627
{
628
case 0: // modelview
629
modelview_pop ();
630
break;
631
632
case 1: // projection, can't
633
break;
634
635
default:
636
FRDP_E ("Unknown uc0:popmatrix command: 0x%08lx\n", param);
637
FRDP ("Unknown uc0:popmatrix command: 0x%08lx\n", param);
638
}
639
}
640
641
static void uc6_obj_sprite ();
642
643
static void uc0_modifyvtx(wxUint8 where, wxUint16 vtx, wxUint32 val)
644
{
645
VERTEX *v = &rdp.vtx[vtx];
646
647
switch (where)
648
{
649
case 0:
650
uc6_obj_sprite ();
651
break;
652
653
case 0x10: // RGBA
654
v->r = (wxUint8)(val >> 24);
655
v->g = (wxUint8)((val >> 16) & 0xFF);
656
v->b = (wxUint8)((val >> 8) & 0xFF);
657
v->a = (wxUint8)(val & 0xFF);
658
v->shade_mod = 0;
659
660
FRDP ("RGBA: %d, %d, %d, %d\n", v->r, v->g, v->b, v->a);
661
break;
662
663
case 0x14: // ST
664
{
665
float scale = rdp.Persp_en ? 0.03125f : 0.015625f;
666
v->ou = (float)((short)(val>>16)) * scale;
667
v->ov = (float)((short)(val&0xFFFF)) * scale;
668
v->uv_calculated = 0xFFFFFFFF;
669
v->uv_scaled = 1;
670
}
671
FRDP ("u/v: (%04lx, %04lx), (%f, %f)\n", (short)(val>>16), (short)(val&0xFFFF),
672
v->ou, v->ov);
673
break;
674
675
case 0x18: // XY screen
676
{
677
float scr_x = (float)((short)(val>>16)) / 4.0f;
678
float scr_y = (float)((short)(val&0xFFFF)) / 4.0f;
679
v->screen_translated = 2;
680
v->sx = scr_x * rdp.scale_x + rdp.offset_x;
681
v->sy = scr_y * rdp.scale_y + rdp.offset_y;
682
if (v->w < 0.01f)
683
{
684
v->w = 1.0f;
685
v->oow = 1.0f;
686
v->z_w = 1.0f;
687
}
688
v->sz = rdp.view_trans[2] + v->z_w * rdp.view_scale[2];
689
690
v->scr_off = 0;
691
if (scr_x < 0) v->scr_off |= 1;
692
if (scr_x > rdp.vi_width) v->scr_off |= 2;
693
if (scr_y < 0) v->scr_off |= 4;
694
if (scr_y > rdp.vi_height) v->scr_off |= 8;
695
if (v->w < 0.1f) v->scr_off |= 16;
696
697
FRDP ("x/y: (%f, %f)\n", scr_x, scr_y);
698
}
699
break;
700
701
case 0x1C: // Z screen
702
{
703
float scr_z = (float)((short)(val>>16));
704
v->z_w = (scr_z - rdp.view_trans[2]) / rdp.view_scale[2];
705
v->z = v->z_w * v->w;
706
FRDP ("z: %f\n", scr_z);
707
}
708
break;
709
710
default:
711
LRDP("UNKNOWN\n");
712
break;
713
}
714
}
715
716
//
717
// uc0:moveword - moves a word to someplace, like the segment pointers
718
//
719
static void uc0_moveword()
720
{
721
LRDP("uc0:moveword ");
722
723
// Find which command this is (lowest byte of cmd0)
724
switch (rdp.cmd0 & 0xFF)
725
{
726
case 0x00:
727
RDP_E ("uc0:moveword matrix - IGNORED\n");
728
LRDP("matrix - IGNORED\n");
729
break;
730
731
case 0x02:
732
rdp.num_lights = ((rdp.cmd1 - 0x80000000) >> 5) - 1; // inverse of equation
733
if (rdp.num_lights > 8) rdp.num_lights = 0;
734
735
rdp.update |= UPDATE_LIGHTS;
736
FRDP ("numlights: %d\n", rdp.num_lights);
737
break;
738
739
case 0x04:
740
if (((rdp.cmd0>>8)&0xFFFF) == 0x04)
741
{
742
rdp.clip_ratio = sqrt((float)rdp.cmd1);
743
rdp.update |= UPDATE_VIEWPORT;
744
}
745
FRDP ("clip %08lx, %08lx\n", rdp.cmd0, rdp.cmd1);
746
break;
747
748
case 0x06: // segment
749
FRDP ("segment: %08lx -> seg%d\n", rdp.cmd1, (rdp.cmd0 >> 10) & 0x0F);
750
if ((rdp.cmd1&BMASK)<BMASK)
751
rdp.segment[(rdp.cmd0 >> 10) & 0x0F] = rdp.cmd1;
752
break;
753
754
case 0x08:
755
{
756
rdp.fog_multiplier = (short)(rdp.cmd1 >> 16);
757
rdp.fog_offset = (short)(rdp.cmd1 & 0x0000FFFF);
758
FRDP ("fog: multiplier: %f, offset: %f\n", rdp.fog_multiplier, rdp.fog_offset);
759
}
760
break;
761
762
case 0x0a: // moveword LIGHTCOL
763
{
764
int n = (rdp.cmd0&0xE000) >> 13;
765
FRDP ("lightcol light:%d, %08lx\n", n, rdp.cmd1);
766
767
rdp.light[n].r = (float)((rdp.cmd1 >> 24) & 0xFF) / 255.0f;
768
rdp.light[n].g = (float)((rdp.cmd1 >> 16) & 0xFF) / 255.0f;
769
rdp.light[n].b = (float)((rdp.cmd1 >> 8) & 0xFF) / 255.0f;
770
rdp.light[n].a = 255;
771
}
772
break;
773
774
case 0x0c:
775
{
776
wxUint16 val = (wxUint16)((rdp.cmd0 >> 8) & 0xFFFF);
777
wxUint16 vtx = val / 40;
778
wxUint8 where = val%40;
779
uc0_modifyvtx(where, vtx, rdp.cmd1);
780
FRDP ("uc0:modifyvtx: vtx: %d, where: 0x%02lx, val: %08lx - ", vtx, where, rdp.cmd1);
781
}
782
break;
783
784
case 0x0e:
785
LRDP("perspnorm - IGNORED\n");
786
break;
787
788
default:
789
FRDP_E ("uc0:moveword unknown (index: 0x%08lx)\n", rdp.cmd0 & 0xFF);
790
FRDP ("unknown (index: 0x%08lx)\n", rdp.cmd0 & 0xFF);
791
}
792
}
793
794
static void uc0_texture()
795
{
796
int tile = (rdp.cmd0 >> 8) & 0x07;
797
if (tile == 7 && (settings.hacks&hack_Supercross)) tile = 0; //fix for supercross 2000
798
rdp.mipmap_level = (rdp.cmd0 >> 11) & 0x07;
799
wxUint32 on = (rdp.cmd0 & 0xFF);
800
rdp.cur_tile = tile;
801
802
if (on)
803
{
804
wxUint16 s = (wxUint16)((rdp.cmd1 >> 16) & 0xFFFF);
805
wxUint16 t = (wxUint16)(rdp.cmd1 & 0xFFFF);
806
807
TILE *tmp_tile = &rdp.tiles[tile];
808
tmp_tile->on = 1;
809
tmp_tile->org_s_scale = s;
810
tmp_tile->org_t_scale = t;
811
tmp_tile->s_scale = (float)(s+1)/65536.0f;
812
tmp_tile->t_scale = (float)(t+1)/65536.0f;
813
tmp_tile->s_scale /= 32.0f;
814
tmp_tile->t_scale /= 32.0f;
815
816
rdp.update |= UPDATE_TEXTURE;
817
818
FRDP("uc0:texture: tile: %d, mipmap_lvl: %d, on: %d, s_scale: %f, t_scale: %f\n",
819
tile, rdp.mipmap_level, on, tmp_tile->s_scale, tmp_tile->t_scale);
820
}
821
else
822
{
823
LRDP("uc0:texture skipped b/c of off\n");
824
rdp.tiles[tile].on = 0;
825
}
826
}
827
828
829
static void uc0_setothermode_h()
830
{
831
LRDP("uc0:setothermode_h: ");
832
833
int shift, len;
834
if ((settings.ucode == ucode_F3DEX2) || (settings.ucode == ucode_CBFD))
835
{
836
len = (rdp.cmd0 & 0xFF) + 1;
837
shift = 32 - ((rdp.cmd0 >> 8) & 0xFF) - len;
838
}
839
else
840
{
841
shift = (rdp.cmd0 >> 8) & 0xFF;
842
len = rdp.cmd0 & 0xFF;
843
}
844
845
wxUint32 mask = 0;
846
int i = len;
847
for (; i; i--)
848
mask = (mask << 1) | 1;
849
mask <<= shift;
850
851
rdp.cmd1 &= mask;
852
rdp.othermode_h &= ~mask;
853
rdp.othermode_h |= rdp.cmd1;
854
855
if (mask & 0x00000030) // alpha dither mode
856
{
857
rdp.alpha_dither_mode = (rdp.othermode_h >> 4) & 0x3;
858
FRDP ("alpha dither mode: %s\n", str_dither[rdp.alpha_dither_mode]);
859
}
860
861
if (mask & 0x000000C0) // rgb dither mode
862
{
863
wxUint32 dither_mode = (rdp.othermode_h >> 6) & 0x3;
864
FRDP ("rgb dither mode: %s\n", str_dither[dither_mode]);
865
}
866
867
if (mask & 0x00003000) // filter mode
868
{
869
rdp.filter_mode = (int)((rdp.othermode_h & 0x00003000) >> 12);
870
rdp.update |= UPDATE_TEXTURE;
871
FRDP ("filter mode: %s\n", str_filter[rdp.filter_mode]);
872
}
873
874
if (mask & 0x0000C000) // tlut mode
875
{
876
rdp.tlut_mode = (wxUint8)((rdp.othermode_h & 0x0000C000) >> 14);
877
FRDP ("tlut mode: %s\n", str_tlut[rdp.tlut_mode]);
878
}
879
880
if (mask & 0x00300000) // cycle type
881
{
882
rdp.cycle_mode = (wxUint8)((rdp.othermode_h & 0x00300000) >> 20);
883
rdp.update |= UPDATE_ZBUF_ENABLED;
884
FRDP ("cycletype: %d\n", rdp.cycle_mode);
885
}
886
887
if (mask & 0x00010000) // LOD enable
888
{
889
rdp.LOD_en = (rdp.othermode_h & 0x00010000) ? TRUE : FALSE;
890
FRDP ("LOD_en: %d\n", rdp.LOD_en);
891
}
892
893
if (mask & 0x00080000) // Persp enable
894
{
895
if (rdp.persp_supported)
896
rdp.Persp_en = (rdp.othermode_h & 0x00080000) ? TRUE : FALSE;
897
FRDP ("Persp_en: %d\n", rdp.Persp_en);
898
}
899
900
wxUint32 unk = mask & 0x0FFC60F0F;
901
if (unk) // unknown portions, LARGE
902
{
903
FRDP ("UNKNOWN PORTIONS: shift: %d, len: %d, unknowns: %08lx\n", shift, len, unk);
904
}
905
}
906
907
static void uc0_setothermode_l()
908
{
909
LRDP("uc0:setothermode_l ");
910
911
int shift, len;
912
if ((settings.ucode == ucode_F3DEX2) || (settings.ucode == ucode_CBFD))
913
{
914
len = (rdp.cmd0 & 0xFF) + 1;
915
shift = 32 - ((rdp.cmd0 >> 8) & 0xFF) - len;
916
if (shift < 0) shift = 0;
917
}
918
else
919
{
920
len = rdp.cmd0 & 0xFF;
921
shift = (rdp.cmd0 >> 8) & 0xFF;
922
}
923
924
wxUint32 mask = 0;
925
int i = len;
926
for (; i; i--)
927
mask = (mask << 1) | 1;
928
mask <<= shift;
929
930
rdp.cmd1 &= mask;
931
rdp.othermode_l &= ~mask;
932
rdp.othermode_l |= rdp.cmd1;
933
934
if (mask & 0x00000003) // alpha compare
935
{
936
rdp.acmp = rdp.othermode_l & 0x00000003;
937
FRDP ("alpha compare %s\n", ACmp[rdp.acmp]);
938
rdp.update |= UPDATE_ALPHA_COMPARE;
939
}
940
941
if (mask & 0x00000004) // z-src selection
942
{
943
rdp.zsrc = (rdp.othermode_l & 0x00000004) >> 2;
944
FRDP ("z-src sel: %s\n", str_zs[rdp.zsrc]);
945
FRDP ("z-src sel: %08lx\n", rdp.zsrc);
946
rdp.update |= UPDATE_ZBUF_ENABLED;
947
}
948
949
if (mask & 0xFFFFFFF8) // rendermode / blender bits
950
{
951
rdp.update |= UPDATE_FOG_ENABLED; //if blender has no fog bits, fog must be set off
952
rdp.render_mode_changed |= rdp.rm ^ rdp.othermode_l;
953
rdp.rm = rdp.othermode_l;
954
if (settings.flame_corona && (rdp.rm == 0x00504341)) //hack for flame's corona
955
rdp.othermode_l |= /*0x00000020 |*/ 0x00000010;
956
FRDP ("rendermode: %08lx\n", rdp.othermode_l); // just output whole othermode_l
957
}
958
959
// there is not one setothermode_l that's not handled :)
960
}
961
962
static void uc0_setgeometrymode()
963
{
964
rdp.geom_mode |= rdp.cmd1;
965
FRDP("uc0:setgeometrymode %08lx; result: %08lx\n", rdp.cmd1, rdp.geom_mode);
966
967
if (rdp.cmd1 & 0x00000001) // Z-Buffer enable
968
{
969
if (!(rdp.flags & ZBUF_ENABLED))
970
{
971
rdp.flags |= ZBUF_ENABLED;
972
rdp.update |= UPDATE_ZBUF_ENABLED;
973
}
974
}
975
if (rdp.cmd1 & 0x00001000) // Front culling
976
{
977
if (!(rdp.flags & CULL_FRONT))
978
{
979
rdp.flags |= CULL_FRONT;
980
rdp.update |= UPDATE_CULL_MODE;
981
}
982
}
983
if (rdp.cmd1 & 0x00002000) // Back culling
984
{
985
if (!(rdp.flags & CULL_BACK))
986
{
987
rdp.flags |= CULL_BACK;
988
rdp.update |= UPDATE_CULL_MODE;
989
}
990
}
991
992
//Added by Gonetz
993
if (rdp.cmd1 & 0x00010000) // Fog enable
994
{
995
if (!(rdp.flags & FOG_ENABLED))
996
{
997
rdp.flags |= FOG_ENABLED;
998
rdp.update |= UPDATE_FOG_ENABLED;
999
}
1000
}
1001
}
1002
1003
static void uc0_cleargeometrymode()
1004
{
1005
FRDP("uc0:cleargeometrymode %08lx\n", rdp.cmd1);
1006
1007
rdp.geom_mode &= (~rdp.cmd1);
1008
1009
if (rdp.cmd1 & 0x00000001) // Z-Buffer enable
1010
{
1011
if (rdp.flags & ZBUF_ENABLED)
1012
{
1013
rdp.flags ^= ZBUF_ENABLED;
1014
rdp.update |= UPDATE_ZBUF_ENABLED;
1015
}
1016
}
1017
if (rdp.cmd1 & 0x00001000) // Front culling
1018
{
1019
if (rdp.flags & CULL_FRONT)
1020
{
1021
rdp.flags ^= CULL_FRONT;
1022
rdp.update |= UPDATE_CULL_MODE;
1023
}
1024
}
1025
if (rdp.cmd1 & 0x00002000) // Back culling
1026
{
1027
if (rdp.flags & CULL_BACK)
1028
{
1029
rdp.flags ^= CULL_BACK;
1030
rdp.update |= UPDATE_CULL_MODE;
1031
}
1032
}
1033
1034
//Added by Gonetz
1035
if (rdp.cmd1 & 0x00010000) // Fog enable
1036
{
1037
if (rdp.flags & FOG_ENABLED)
1038
{
1039
rdp.flags ^= FOG_ENABLED;
1040
rdp.update |= UPDATE_FOG_ENABLED;
1041
}
1042
}
1043
}
1044
1045
static void uc0_line3d()
1046
{
1047
wxUint32 v0 = ((rdp.cmd1 >> 16) & 0xff) / 10;
1048
wxUint32 v1 = ((rdp.cmd1 >> 8) & 0xff) / 10;
1049
wxUint16 width = (wxUint16)(rdp.cmd1 & 0xFF) + 3;
1050
1051
VERTEX *v[3] = {
1052
&rdp.vtx[v1],
1053
&rdp.vtx[v0],
1054
&rdp.vtx[v0]
1055
};
1056
wxUint32 cull_mode = (rdp.flags & CULLMASK) >> CULLSHIFT;
1057
rdp.flags |= CULLMASK;
1058
rdp.update |= UPDATE_CULL_MODE;
1059
rsp_tri1(v, width);
1060
rdp.flags ^= CULLMASK;
1061
rdp.flags |= cull_mode << CULLSHIFT;
1062
rdp.update |= UPDATE_CULL_MODE;
1063
1064
FRDP("uc0:line3d v0:%d, v1:%d, width:%d\n", v0, v1, width);
1065
}
1066
1067
static void uc0_tri4 ()
1068
{
1069
// c0: 0000 0123, c1: 456789ab
1070
// becomes: 405 617 829 a3b
1071
1072
LRDP("uc0:tri4");
1073
FRDP(" #%d, #%d, #%d, #%d - %d, %d, %d - %d, %d, %d - %d, %d, %d - %d, %d, %d\n", rdp.tri_n, rdp.tri_n+1, rdp.tri_n+2, rdp.tri_n+3,
1074
(rdp.cmd1 >> 28) & 0xF,
1075
(rdp.cmd0 >> 12) & 0xF,
1076
(rdp.cmd1 >> 24) & 0xF,
1077
(rdp.cmd1 >> 20) & 0xF,
1078
(rdp.cmd0 >> 8) & 0xF,
1079
(rdp.cmd1 >> 16) & 0xF,
1080
(rdp.cmd1 >> 12) & 0xF,
1081
(rdp.cmd0 >> 4) & 0xF,
1082
(rdp.cmd1 >> 8) & 0xF,
1083
(rdp.cmd1 >> 4) & 0xF,
1084
(rdp.cmd0 >> 0) & 0xF,
1085
(rdp.cmd1 >> 0) & 0xF);
1086
1087
VERTEX *v[12] = {
1088
&rdp.vtx[(rdp.cmd1 >> 28) & 0xF],
1089
&rdp.vtx[(rdp.cmd0 >> 12) & 0xF],
1090
&rdp.vtx[(rdp.cmd1 >> 24) & 0xF],
1091
&rdp.vtx[(rdp.cmd1 >> 20) & 0xF],
1092
&rdp.vtx[(rdp.cmd0 >> 8) & 0xF],
1093
&rdp.vtx[(rdp.cmd1 >> 16) & 0xF],
1094
&rdp.vtx[(rdp.cmd1 >> 12) & 0xF],
1095
&rdp.vtx[(rdp.cmd0 >> 4) & 0xF],
1096
&rdp.vtx[(rdp.cmd1 >> 8) & 0xF],
1097
&rdp.vtx[(rdp.cmd1 >> 4) & 0xF],
1098
&rdp.vtx[(rdp.cmd0 >> 0) & 0xF],
1099
&rdp.vtx[(rdp.cmd1 >> 0) & 0xF],
1100
};
1101
1102
int updated = 0;
1103
1104
if (cull_tri(v))
1105
rdp.tri_n ++;
1106
else
1107
{
1108
updated = 1;
1109
update ();
1110
1111
draw_tri (v);
1112
rdp.tri_n ++;
1113
}
1114
1115
if (cull_tri(v+3))
1116
rdp.tri_n ++;
1117
else
1118
{
1119
if (!updated)
1120
{
1121
updated = 1;
1122
update ();
1123
}
1124
1125
draw_tri (v+3);
1126
rdp.tri_n ++;
1127
}
1128
1129
if (cull_tri(v+6))
1130
rdp.tri_n ++;
1131
else
1132
{
1133
if (!updated)
1134
{
1135
updated = 1;
1136
update ();
1137
}
1138
1139
draw_tri (v+6);
1140
rdp.tri_n ++;
1141
}
1142
1143
if (cull_tri(v+9))
1144
rdp.tri_n ++;
1145
else
1146
{
1147
if (!updated)
1148
{
1149
updated = 1;
1150
update ();
1151
}
1152
1153
draw_tri (v+9);
1154
rdp.tri_n ++;
1155
}
1156
}
1157
1158