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