2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002 Dave2001
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
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 //****************************************************************
22 // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)
23 // Project started on December 29th, 2001
26 // * 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.
27 // * 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 // Official Glide64 development channel: #Glide64 on EFnet
31 // Original author: Dave2001 (Dave2999@hotmail.com)
32 // Other authors: Gonetz, Gugaman
34 //****************************************************************
39 #define __int32 int32_t
42 static void uc0_enddl();
47 // matrix functions ***** SWITCH TO POINTERS LATER ******
50 void modelview_load (float m
[4][4])
52 memcpy (rdp
.model
, m
, 64); // 4*4*4(float)
54 rdp
.update
|= UPDATE_MULT_MAT
| UPDATE_LIGHTS
;
57 void modelview_mul (float m
[4][4])
59 __declspec( align(16) ) float m_src
[4][4];
60 memcpy (m_src
, rdp
.model
, 64);
61 MulMatrices(m
, m_src
, rdp
.model
);
62 rdp
.update
|= UPDATE_MULT_MAT
| UPDATE_LIGHTS
;
65 void modelview_push ()
67 if (rdp
.model_i
== rdp
.model_stack_size
)
69 RDP_E ("** Model matrix stack overflow ** too many pushes\n");
70 RDP ("** Model matrix stack overflow ** too many pushes\n");
74 memcpy (rdp
.model_stack
[rdp
.model_i
], rdp
.model
, 64);
78 void modelview_pop (int num
= 1)
80 if (rdp
.model_i
> num
- 1)
86 RDP_E ("** Model matrix stack error ** too many pops\n");
87 RDP ("** Model matrix stack error ** too many pops\n");
90 memcpy (rdp
.model
, rdp
.model_stack
[rdp
.model_i
], 64);
91 rdp
.update
|= UPDATE_MULT_MAT
| UPDATE_LIGHTS
;
94 void modelview_load_push (float m
[4][4])
100 void modelview_mul_push (float m
[4][4])
106 void projection_load (float m
[4][4])
108 memcpy (rdp
.proj
, m
, 64); // 4*4*4(float)
110 rdp
.update
|= UPDATE_MULT_MAT
;
113 void projection_mul (float m
[4][4])
115 __declspec( align(16) ) float m_src
[4][4];
116 memcpy (m_src
, rdp
.proj
, 64);
117 MulMatrices(m
, m_src
, rdp
.proj
);
118 rdp
.update
|= UPDATE_MULT_MAT
;
122 // uc0:matrix - performs matrix operations
125 static void uc0_matrix()
129 // Use segment offset to get the address
130 DWORD addr
= segoffset(rdp
.cmd1
) & 0x00FFFFFF;
131 BYTE command
= (BYTE
)((rdp
.cmd0
>> 16) & 0xFF);
133 __declspec( align(16) ) float m
[4][4];
134 int x
,y
; // matrix index
138 for (x
=0; x
<16; x
+=4) { // Adding 4 instead of one, just to remove mult. later
139 for (y
=0; y
<4; y
++) {
140 m
[x
>>2][y
] = (float)(
141 (((__int32
)((WORD
*)gfx
.RDRAM
)[(addr
+x
+y
)^1]) << 16) |
142 ((WORD
*)gfx
.RDRAM
)[(addr
+x
+y
+16)^1]
149 case 0: // modelview mul nopush
150 RDP ("modelview mul\n");
154 case 1: // projection mul nopush
155 case 5: // projection mul push, can't push projection
156 RDP ("projection mul\n");
160 case 2: // modelview load nopush
161 RDP ("modelview load\n");
165 case 3: // projection load nopush
166 case 7: // projection load push, can't push projection
167 RDP ("projection load\n");
172 case 4: // modelview mul push
173 RDP ("modelview mul push\n");
174 modelview_mul_push (m
);
177 case 6: // modelview load push
178 RDP ("modelview load push\n");
179 modelview_load_push (m
);
183 FRDP_E ("Unknown matrix command, %02lx", command
);
184 FRDP ("Unknown matrix command, %02lx", command
);
187 #ifdef EXTREME_LOGGING
188 FRDP ("{%f,%f,%f,%f}\n", m
[0][0], m
[0][1], m
[0][2], m
[0][3]);
189 FRDP ("{%f,%f,%f,%f}\n", m
[1][0], m
[1][1], m
[1][2], m
[1][3]);
190 FRDP ("{%f,%f,%f,%f}\n", m
[2][0], m
[2][1], m
[2][2], m
[2][3]);
191 FRDP ("{%f,%f,%f,%f}\n", m
[3][0], m
[3][1], m
[3][2], m
[3][3]);
192 FRDP ("\nmodel\n{%f,%f,%f,%f}\n", rdp
.model
[0][0], rdp
.model
[0][1], rdp
.model
[0][2], rdp
.model
[0][3]);
193 FRDP ("{%f,%f,%f,%f}\n", rdp
.model
[1][0], rdp
.model
[1][1], rdp
.model
[1][2], rdp
.model
[1][3]);
194 FRDP ("{%f,%f,%f,%f}\n", rdp
.model
[2][0], rdp
.model
[2][1], rdp
.model
[2][2], rdp
.model
[2][3]);
195 FRDP ("{%f,%f,%f,%f}\n", rdp
.model
[3][0], rdp
.model
[3][1], rdp
.model
[3][2], rdp
.model
[3][3]);
196 FRDP ("\nproj\n{%f,%f,%f,%f}\n", rdp
.proj
[0][0], rdp
.proj
[0][1], rdp
.proj
[0][2], rdp
.proj
[0][3]);
197 FRDP ("{%f,%f,%f,%f}\n", rdp
.proj
[1][0], rdp
.proj
[1][1], rdp
.proj
[1][2], rdp
.proj
[1][3]);
198 FRDP ("{%f,%f,%f,%f}\n", rdp
.proj
[2][0], rdp
.proj
[2][1], rdp
.proj
[2][2], rdp
.proj
[2][3]);
199 FRDP ("{%f,%f,%f,%f}\n", rdp
.proj
[3][0], rdp
.proj
[3][1], rdp
.proj
[3][2], rdp
.proj
[3][3]);
204 // uc0:movemem - loads a structure with data
207 static void uc0_movemem()
214 switch ((rdp
.cmd0
>> 16) & 0xFF)
218 a
= (segoffset(rdp
.cmd1
) & 0xFFFFFF) >> 1;
220 short scale_x
= ((short*)gfx
.RDRAM
)[(a
+0)^1] / 4;
221 short scale_y
= ((short*)gfx
.RDRAM
)[(a
+1)^1] / 4;
222 short scale_z
= ((short*)gfx
.RDRAM
)[(a
+2)^1];
223 short trans_x
= ((short*)gfx
.RDRAM
)[(a
+4)^1] / 4;
224 short trans_y
= ((short*)gfx
.RDRAM
)[(a
+5)^1] / 4;
225 short trans_z
= ((short*)gfx
.RDRAM
)[(a
+6)^1];
226 rdp
.view_scale
[0] = scale_x
* rdp
.scale_x
;
227 rdp
.view_scale
[1] = -scale_y
* rdp
.scale_y
;
228 rdp
.view_scale
[2] = 32.0f
* scale_z
;
229 rdp
.view_trans
[0] = trans_x
* rdp
.scale_x
+ rdp
.offset_x
;
230 rdp
.view_trans
[1] = trans_y
* rdp
.scale_y
+ rdp
.offset_y
;
231 rdp
.view_trans
[2] = 32.0f
* trans_z
;
233 // there are other values than x and y, but I don't know what they do
235 rdp
.update
|= UPDATE_VIEWPORT
;
237 FRDP ("viewport scale(%d, %d, %d), trans(%d, %d, %d), from:%08lx\n", scale_x
, scale_y
, scale_z
,
238 trans_x
, trans_y
, trans_z
, rdp
.cmd1
);
244 a
= segoffset(rdp
.cmd1
) & 0x00ffffff;
245 char dir_x
= ((char*)gfx
.RDRAM
)[(a
+8)^3];
246 rdp
.lookat
[1][0] = (float)(dir_x
) / 127.0f
;
247 char dir_y
= ((char*)gfx
.RDRAM
)[(a
+9)^3];
248 rdp
.lookat
[1][1] = (float)(dir_y
) / 127.0f
;
249 char dir_z
= ((char*)gfx
.RDRAM
)[(a
+10)^3];
250 rdp
.lookat
[1][2] = (float)(dir_z
) / 127.0f
;
251 if (!dir_x
&& !dir_y
)
252 rdp
.use_lookat
= FALSE
;
254 rdp
.use_lookat
= TRUE
;
255 FRDP("lookat_y (%f, %f, %f)\n", rdp
.lookat
[1][0], rdp
.lookat
[1][1], rdp
.lookat
[1][2]);
260 a
= segoffset(rdp
.cmd1
) & 0x00ffffff;
261 rdp
.lookat
[0][0] = (float)(((char*)gfx
.RDRAM
)[(a
+8)^3]) / 127.0f
;
262 rdp
.lookat
[0][1] = (float)(((char*)gfx
.RDRAM
)[(a
+9)^3]) / 127.0f
;
263 rdp
.lookat
[0][2] = (float)(((char*)gfx
.RDRAM
)[(a
+10)^3]) / 127.0f
;
264 rdp
.use_lookat
= TRUE
;
265 FRDP("lookat_x (%f, %f, %f)\n", rdp
.lookat
[1][0], rdp
.lookat
[1][1], rdp
.lookat
[1][2]);
277 i
= (((rdp
.cmd0
>> 16) & 0xff) - 0x86) >> 1;
278 a
= segoffset(rdp
.cmd1
) & 0x00ffffff;
281 rdp
.light
[i
].r
= (float)(((BYTE
*)gfx
.RDRAM
)[(a
+0)^3]) / 255.0f
;
282 rdp
.light
[i
].g
= (float)(((BYTE
*)gfx
.RDRAM
)[(a
+1)^3]) / 255.0f
;
283 rdp
.light
[i
].b
= (float)(((BYTE
*)gfx
.RDRAM
)[(a
+2)^3]) / 255.0f
;
284 rdp
.light
[i
].a
= 1.0f
;
285 // ** Thanks to Icepir8 for pointing this out **
286 // Lighting must be signed byte instead of byte
287 rdp
.light
[i
].dir_x
= (float)(((char*)gfx
.RDRAM
)[(a
+8)^3]) / 127.0f
;
288 rdp
.light
[i
].dir_y
= (float)(((char*)gfx
.RDRAM
)[(a
+9)^3]) / 127.0f
;
289 rdp
.light
[i
].dir_z
= (float)(((char*)gfx
.RDRAM
)[(a
+10)^3]) / 127.0f
;
292 //rdp.update |= UPDATE_LIGHTS;
294 FRDP ("light: n: %d, r: %.3f, g: %.3f, b: %.3f, x: %.3f, y: %.3f, z: %.3f\n",
295 i
, rdp
.light
[i
].r
, rdp
.light
[i
].g
, rdp
.light
[i
].b
,
296 rdp
.light_vector
[i
][0], rdp
.light_vector
[i
][1], rdp
.light_vector
[i
][2]);
300 case 0x9E: //gSPForceMatrix command. Modification of uc2_movemem:matrix. Gonetz.
302 // do not update the combined matrix!
303 rdp
.update
&= ~UPDATE_MULT_MAT
;
306 DWORD addr
= segoffset(rdp
.cmd1
) & 0x00FFFFFF;
307 FRDP ("matrix addr: %08lx\n", addr
);
310 DWORD a
= rdp
.pc
[rdp
.pc_i
] & BMASK
;
311 rdp
.pc
[rdp
.pc_i
] = (a
+24) & BMASK
; //skip next 3 command, b/c they all are part of gSPForceMatrix
313 for (x
=0; x
<16; x
+=4) { // Adding 4 instead of one, just to remove mult. later
315 for (y
=0; y
<4; y
++) {
316 rdp
.combined
[x
>>2][y
] = (float)(
317 (((__int32
)((WORD
*)gfx
.RDRAM
)[(addr
+x
+y
)^1]) << 16) |
318 ((WORD
*)gfx
.RDRAM
)[(addr
+x
+y
+16)^1]
323 #ifdef EXTREME_LOGGING
324 FRDP ("{%f,%f,%f,%f}\n", rdp
.combined
[0][0], rdp
.combined
[0][1], rdp
.combined
[0][2], rdp
.combined
[0][3]);
325 FRDP ("{%f,%f,%f,%f}\n", rdp
.combined
[1][0], rdp
.combined
[1][1], rdp
.combined
[1][2], rdp
.combined
[1][3]);
326 FRDP ("{%f,%f,%f,%f}\n", rdp
.combined
[2][0], rdp
.combined
[2][1], rdp
.combined
[2][2], rdp
.combined
[2][3]);
327 FRDP ("{%f,%f,%f,%f}\n", rdp
.combined
[3][0], rdp
.combined
[3][1], rdp
.combined
[3][2], rdp
.combined
[3][3]);
332 //next 3 command should never appear since they will be skipped in previous command
334 RDP_E ("uc0:movemem matrix 0 - ERROR!\n");
335 RDP ("matrix 0 - IGNORED\n");
339 RDP_E ("uc0:movemem matrix 1 - ERROR!\n");
340 RDP ("matrix 1 - IGNORED\n");
344 RDP_E ("uc0:movemem matrix 2 - ERROR!\n");
345 RDP ("matrix 2 - IGNORED\n");
349 FRDP_E ("uc0:movemem unknown (index: 0x%08lx)\n", (rdp
.cmd0
>> 16) & 0xFF);
350 FRDP ("unknown (index: 0x%08lx)\n", (rdp
.cmd0
>> 16) & 0xFF);
355 // uc0:vertex - loads vertices
358 static void uc0_vertex()
360 DWORD addr
= segoffset(rdp
.cmd1
) & 0x00FFFFFF;
364 rdp
.v0
= v0
= (rdp
.cmd0
>> 16) & 0xF; // Current vertex
365 rdp
.vn
= n
= ((rdp
.cmd0
>> 20) & 0xF) + 1; // Number of vertices to copy
367 FRDP("uc0:vertex: v0: %d, n: %d\n", v0
, n
);
369 // This is special, not handled in update(), but here
370 // * Matrix Pre-multiplication idea by Gonetz (Gonetz@ngs.ru)
371 if (rdp
.update
& UPDATE_MULT_MAT
)
373 rdp
.update
^= UPDATE_MULT_MAT
;
374 MulMatrices(rdp
.model
, rdp
.proj
, rdp
.combined
);
378 // This is special, not handled in update()
379 if (rdp
.update
& UPDATE_LIGHTS
)
381 rdp
.update
^= UPDATE_LIGHTS
;
383 // Calculate light vectors
384 for (DWORD l
=0; l
<rdp
.num_lights
; l
++)
386 InverseTransformVector(&rdp
.light
[l
].dir_x
, rdp
.light_vector
[l
], rdp
.model
);
387 NormalizeVector (rdp
.light_vector
[l
]);
391 for (i
=0; i
< (n
<<4); i
+=16)
393 VERTEX
*v
= &rdp
.vtx
[v0
+ (i
>>4)];
394 x
= (float)((short*)gfx
.RDRAM
)[(((addr
+i
) >> 1) + 0)^1];
395 y
= (float)((short*)gfx
.RDRAM
)[(((addr
+i
) >> 1) + 1)^1];
396 z
= (float)((short*)gfx
.RDRAM
)[(((addr
+i
) >> 1) + 2)^1];
397 v
->flags
= ((WORD
*)gfx
.RDRAM
)[(((addr
+i
) >> 1) + 3)^1];
398 v
->ou
= (float)((short*)gfx
.RDRAM
)[(((addr
+i
) >> 1) + 4)^1] * rdp
.tiles
[rdp
.cur_tile
].s_scale
;
399 v
->ov
= (float)((short*)gfx
.RDRAM
)[(((addr
+i
) >> 1) + 5)^1] * rdp
.tiles
[rdp
.cur_tile
].t_scale
;
400 v
->a
= ((BYTE
*)gfx
.RDRAM
)[(addr
+i
+ 15)^3];
402 v
->x
= x
*rdp
.combined
[0][0] + y
*rdp
.combined
[1][0] + z
*rdp
.combined
[2][0] + rdp
.combined
[3][0];
403 v
->y
= x
*rdp
.combined
[0][1] + y
*rdp
.combined
[1][1] + z
*rdp
.combined
[2][1] + rdp
.combined
[3][1];
404 v
->z
= x
*rdp
.combined
[0][2] + y
*rdp
.combined
[1][2] + z
*rdp
.combined
[2][2] + rdp
.combined
[3][2];
405 v
->w
= x
*rdp
.combined
[0][3] + y
*rdp
.combined
[1][3] + z
*rdp
.combined
[2][3] + rdp
.combined
[3][3];
407 #ifdef EXTREME_LOGGING
408 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
);
411 v
->oow
= 1.0f
/ v
->w
;
412 v
->x_w
= v
->x
* v
->oow
;
413 v
->y_w
= v
->y
* v
->oow
;
414 v
->z_w
= v
->z
* v
->oow
;
417 v
->uv_calculated
= 0xFFFFFFFF;
418 v
->screen_translated
= 0;
419 v
->shade_mods_allowed
= 1;
422 if (v
->x
< -v
->w
) v
->scr_off
|= 1;
423 if (v
->x
> v
->w
) v
->scr_off
|= 2;
424 if (v
->y
< -v
->w
) v
->scr_off
|= 4;
425 if (v
->y
> v
->w
) v
->scr_off
|= 8;
426 if (v
->w
< 0.1f
) v
->scr_off
|= 16;
428 if (rdp
.geom_mode
& 0x00020000)
430 v
->vec
[0] = ((char*)gfx
.RDRAM
)[(addr
+i
+ 12)^3];
431 v
->vec
[1] = ((char*)gfx
.RDRAM
)[(addr
+i
+ 13)^3];
432 v
->vec
[2] = ((char*)gfx
.RDRAM
)[(addr
+i
+ 14)^3];
433 if (rdp
.geom_mode
& 0x80000) calc_linear (v
);
434 else if (rdp
.geom_mode
& 0x40000) calc_sphere (v
);
435 NormalizeVector (v
->vec
);
441 v
->r
= ((BYTE
*)gfx
.RDRAM
)[(addr
+i
+ 12)^3];
442 v
->g
= ((BYTE
*)gfx
.RDRAM
)[(addr
+i
+ 13)^3];
443 v
->b
= ((BYTE
*)gfx
.RDRAM
)[(addr
+i
+ 14)^3];
449 // uc0:displaylist - makes a call to another section of code
452 static void uc0_displaylist()
454 DWORD addr
= segoffset(rdp
.cmd1
) & 0x00FFFFFF;
456 // This fixes partially Gauntlet: Legends
457 if (addr
== rdp
.pc
[rdp
.pc_i
] - 8) { RDP ("display list not executed!\n"); return; }
459 DWORD push
= (rdp
.cmd0
>> 16) & 0xFF; // push the old location?
461 FRDP("uc0:displaylist: %08lx, push:%s", addr
, push
?"no":"yes");
462 FRDP(" (seg %d, offset %08lx)\n", (rdp
.cmd1
>>24)&0x0F, rdp
.cmd1
&0x00FFFFFF);
468 RDP_E ("** DL stack overflow **");
469 RDP ("** DL stack overflow **\n");
472 rdp
.pc_i
++; // go to the next PC in the stack
473 rdp
.pc
[rdp
.pc_i
] = addr
; // jump to the address
477 rdp
.pc
[rdp
.pc_i
] = addr
; // just jump to the address
481 RDP_E("Unknown displaylist operation\n");
482 RDP ("Unknown displaylist operation\n");
487 // tri1 - renders a triangle
490 static void uc0_tri1()
492 FRDP("uc0:tri1 #%d - %d, %d, %d\n", rdp
.tri_n
,
493 ((rdp
.cmd1
>>16) & 0xFF) / 10,
494 ((rdp
.cmd1
>>8) & 0xFF) / 10,
495 (rdp
.cmd1
& 0xFF) / 10);
498 &rdp
.vtx
[((rdp
.cmd1
>> 16) & 0xFF) / 10],
499 &rdp
.vtx
[((rdp
.cmd1
>> 8) & 0xFF) / 10],
500 &rdp
.vtx
[(rdp
.cmd1
& 0xFF) / 10]
512 static void uc0_culldl()
514 BYTE vStart
= (BYTE
)((rdp
.cmd0
& 0x00FFFFFF) / 40) & 0xF;
515 BYTE vEnd
= (BYTE
)(rdp
.cmd1
/ 40) & 0x0F;
519 FRDP("uc0:culldl start: %d, end: %d\n", vStart
, vEnd
);
521 if (vEnd
< vStart
) return;
522 for (WORD i
=vStart
; i
<=vEnd
; i
++)
525 // Check if completely off the screen (quick frustrum clipping for 90 FOV)
541 RDP (" - "); // specify that the enddl is not a real command
545 static void uc0_popmatrix()
547 RDP("uc0:popmatrix\n");
549 DWORD param
= rdp
.cmd1
;
557 case 1: // projection, can't
561 FRDP_E ("Unknown uc0:popmatrix command: 0x%08lx\n", param
);
562 FRDP ("Unknown uc0:popmatrix command: 0x%08lx\n", param
);
566 void uc6_obj_sprite ();
568 static void uc0_modifyvtx(BYTE where
, WORD vtx
, DWORD val
)
570 VERTEX
*v
= &rdp
.vtx
[vtx
];
579 v
->r
= (BYTE
)(val
>> 24);
580 v
->g
= (BYTE
)((val
>> 16) & 0xFF);
581 v
->b
= (BYTE
)((val
>> 8) & 0xFF);
582 v
->a
= (BYTE
)(val
& 0xFF);
583 v
->shade_mods_allowed
= 1;
585 FRDP ("RGBA: %d, %d, %d, %d\n", v
->r
, v
->g
, v
->b
, v
->a
);
589 v
->ou
= (float)((short)(val
>>16)) / 32.0f
;
590 v
->ov
= (float)((short)(val
&0xFFFF)) / 32.0f
;
591 v
->uv_calculated
= 0xFFFFFFFF;
594 FRDP ("u/v: (%04lx, %04lx), (%f, %f)\n", (short)(val
>>16), (short)(val
&0xFFFF),
598 case 0x18: // XY screen
600 float scr_x
= (float)((short)(val
>>16)) / 4.0f
;
601 float scr_y
= (float)((short)(val
&0xFFFF)) / 4.0f
;
602 v
->screen_translated
= 1;
603 v
->sx
= scr_x
* rdp
.scale_x
;
604 v
->sy
= scr_y
* rdp
.scale_y
;
611 v
->sz
= rdp
.view_trans
[2] + v
->z_w
* rdp
.view_scale
[2];
614 if (scr_x
< 0) v
->scr_off
|= 1;
615 if (scr_x
> rdp
.vi_width
) v
->scr_off
|= 2;
616 if (scr_y
< 0) v
->scr_off
|= 4;
617 if (scr_y
> rdp
.vi_height
) v
->scr_off
|= 8;
618 if (v
->w
< 0.1f
) v
->scr_off
|= 16;
620 FRDP ("x/y: (%f, %f)\n", scr_x
, scr_y
);
624 case 0x1C: // Z screen
626 float scr_z
= (float)((short)(val
>>16));
627 v
->z_w
= (scr_z
- rdp
.view_trans
[2]) / rdp
.view_scale
[2];
628 v
->z
= v
->z_w
* v
->w
;
629 FRDP ("z: %f\n", scr_z
);
640 // uc0:moveword - moves a word to someplace, like the segment pointers
643 static void uc0_moveword()
645 RDP("uc0:moveword ");
647 // Find which command this is (lowest byte of cmd0)
648 switch (rdp
.cmd0
& 0xFF)
651 RDP_E ("uc0:moveword matrix - IGNORED\n");
652 RDP ("matrix - IGNORED\n");
656 rdp
.num_lights
= ((rdp
.cmd1
- 0x80000000) >> 5) - 1; // inverse of equation
657 if (rdp
.num_lights
> 8) rdp
.num_lights
= 0;
659 rdp
.update
|= UPDATE_LIGHTS
;
660 FRDP ("numlights: %d\n", rdp
.num_lights
);
664 FRDP ("clip %08lx, %08lx\n", rdp
.cmd0
, rdp
.cmd1
);
667 case 0x06: // segment
668 FRDP ("segment: %08lx -> seg%d\n", rdp
.cmd1
, (rdp
.cmd0
>> 10) & 0x0F);
669 if ((rdp
.cmd1
&BMASK
)<BMASK
)
670 rdp
.segment
[(rdp
.cmd0
>> 10) & 0x0F] = rdp
.cmd1
;
675 rdp
.fog_multiplier
= (short)(rdp
.cmd1
>> 16);
676 rdp
.fog_offset
= (short)(rdp
.cmd1
& 0x0000FFFF);
677 FRDP ("fog: multiplier: %f, offset: %f\n", rdp
.fog_multiplier
, rdp
.fog_offset
);
681 case 0x0a: // moveword LIGHTCOL
683 int n
= (rdp
.cmd0
&0xE000) >> 13;
684 FRDP ("lightcol light:%d, %08lx\n", n
, rdp
.cmd1
);
686 rdp
.light
[n
].r
= (float)((rdp
.cmd1
>> 24) & 0xFF) / 255.0f
;
687 rdp
.light
[n
].g
= (float)((rdp
.cmd1
>> 16) & 0xFF) / 255.0f
;
688 rdp
.light
[n
].b
= (float)((rdp
.cmd1
>> 8) & 0xFF) / 255.0f
;
689 rdp
.light
[n
].a
= 255;
695 WORD val
= (WORD
)((rdp
.cmd0
>> 8) & 0xFFFF);
698 uc0_modifyvtx(where
, vtx
, rdp
.cmd1
);
699 FRDP ("uc0:modifyvtx: vtx: %d, where: 0x%02lx, val: %08lx - ", vtx
, where
, rdp
.cmd1
);
704 RDP ("perspnorm - IGNORED\n");
708 FRDP_E ("uc0:moveword unknown (index: 0x%08lx)\n", rdp
.cmd0
& 0xFF);
709 FRDP ("unknown (index: 0x%08lx)\n", rdp
.cmd0
& 0xFF);
713 static void uc0_texture()
715 int tile
= (rdp
.cmd0
>> 8) & 0x07;
716 rdp
.mipmap_level
= (rdp
.cmd0
>> 11) & 0x07;
717 DWORD on
= (rdp
.cmd0
& 0xFF);
723 WORD s
= (WORD
)((rdp
.cmd1
>> 16) & 0xFFFF);
724 WORD t
= (WORD
)(rdp
.cmd1
& 0xFFFF);
726 TILE
*tmp_tile
= &rdp
.tiles
[tile
];
727 tmp_tile
->on
= (BYTE
)on
;
728 tmp_tile
->org_s_scale
= s
;
729 tmp_tile
->org_t_scale
= t
;
730 tmp_tile
->s_scale
= (float)(s
+1)/65536.0f
;
731 tmp_tile
->t_scale
= (float)(t
+1)/65536.0f
;
732 tmp_tile
->s_scale
/= 32.0f
;
733 tmp_tile
->t_scale
/= 32.0f
;
735 rdp
.update
|= UPDATE_TEXTURE
;
737 FRDP("uc0:texture: tile: %d, mipmap_lvl: %d, on: %d, s_scale: %f, t_scale: %f\n",
738 tile
, rdp
.mipmap_level
, on
, tmp_tile
->s_scale
, tmp_tile
->t_scale
);
742 RDP("uc0:texture skipped b/c of off\n");
747 static void uc0_setothermode_h()
749 RDP ("uc0:setothermode_h: ");
752 if ((settings
.ucode
== 2) || (settings
.ucode
== 8))
754 len
= (rdp
.cmd0
& 0xFF) + 1;
755 shift
= 32 - ((rdp
.cmd0
>> 8) & 0xFF) - len
;
759 shift
= (rdp
.cmd0
>> 8) & 0xFF;
760 len
= rdp
.cmd0
& 0xFF;
766 mask
= (mask
<< 1) | 1;
770 rdp
.othermode_h
&= ~mask
;
771 rdp
.othermode_h
|= rdp
.cmd1
;
773 if (mask
& 0x00003000) // filter mode
775 rdp
.filter_mode
= (int)((rdp
.othermode_h
& 0x00003000) >> 12);
776 rdp
.update
|= UPDATE_TEXTURE
;
777 FRDP ("filter mode: %s\n", str_filter
[rdp
.filter_mode
]);
780 if (mask
& 0x0000C000) // tlut mode
782 rdp
.tlut_mode
= (BYTE
)((rdp
.othermode_h
& 0x0000C000) >> 14);
783 FRDP ("tlut mode: %s\n", str_tlut
[rdp
.tlut_mode
]);
786 if (mask
& 0x00300000) // cycle type
788 rdp
.cycle_mode
= (BYTE
)((rdp
.othermode_h
& 0x00300000) >> 20);
789 FRDP ("cycletype: %d\n", rdp
.cycle_mode
);
792 if (mask
& 0x00010000) // LOD enable
794 rdp
.LOD_en
= (rdp
.othermode_h
& 0x00010000) ? TRUE
: FALSE
;
795 FRDP ("LOD_en: %d\n", rdp
.LOD_en
);
798 DWORD unk
= mask
& 0xFFCF0FFF;
799 if (unk
) // unknown portions, LARGE
801 FRDP ("UNKNOWN PORTIONS: shift: %d, len: %d, unknowns: %08lx\n", shift
, len
, unk
);
805 static void uc0_setothermode_l()
807 RDP("uc0:setothermode_l ");
810 if ((settings
.ucode
== 2) || (settings
.ucode
== 8))
812 len
= (rdp
.cmd0
& 0xFF) + 1;
813 shift
= 32 - ((rdp
.cmd0
>> 8) & 0xFF) - len
;
817 len
= rdp
.cmd0
& 0xFF;
818 shift
= (rdp
.cmd0
>> 8) & 0xFF;
824 mask
= (mask
<< 1) | 1;
828 rdp
.othermode_l
&= ~mask
;
829 rdp
.othermode_l
|= rdp
.cmd1
;
831 if (mask
& 0x00000003) // alpha compare
833 rdp
.acmp
= rdp
.othermode_l
& 0x00000003;
834 FRDP ("alpha compare %s\n", ACmp
[rdp
.acmp
]);
835 rdp
.update
|= UPDATE_ALPHA_COMPARE
;
838 if (mask
& 0x00000004) // z-src selection
840 rdp
.zsrc
= (rdp
.othermode_l
& 0x00000004) >> 2;
841 FRDP ("z-src sel: %s\n", str_zs
[rdp
.zsrc
]);
842 FRDP ("z-src sel: %08lx\n", rdp
.zsrc
);
845 if (mask
& 0xFFFFFFF8) // rendermode / blender bits
847 rdp
.update
|= UPDATE_FOG_ENABLED
; //if blender has no fog bits, fog must be set off
848 rdp
.render_mode_changed
|= rdp
.rm
^ rdp
.othermode_l
;
849 rdp
.rm
= rdp
.othermode_l
;
850 if (settings
.flame_corona
&& (rdp
.rm
== 0x00504341)) //hack for flame's corona
851 rdp
.othermode_l
|= /*0x00000020 |*/ 0x00000010;
852 FRDP ("rendermode: %08lx\n", rdp
.othermode_l
); // just output whole othermode_l
855 // there is not one setothermode_l that's not handled :)
859 // uc0:enddl - ends a call made by uc0:displaylist
862 static void uc0_enddl()
870 // Halt execution here
877 static void uc0_setgeometrymode()
879 FRDP("uc0:setgeometrymode %08lx\n", rdp
.cmd1
);
881 rdp
.geom_mode
|= rdp
.cmd1
;
883 if (rdp
.cmd1
& 0x00000001) // Z-Buffer enable
885 if (!(rdp
.flags
& ZBUF_ENABLED
))
887 rdp
.flags
|= ZBUF_ENABLED
;
888 rdp
.update
|= UPDATE_ZBUF_ENABLED
;
891 if (rdp
.cmd1
& 0x00001000) // Front culling
893 if (!(rdp
.flags
& CULL_FRONT
))
895 rdp
.flags
|= CULL_FRONT
;
896 rdp
.update
|= UPDATE_CULL_MODE
;
899 if (rdp
.cmd1
& 0x00002000) // Back culling
901 if (!(rdp
.flags
& CULL_BACK
))
903 rdp
.flags
|= CULL_BACK
;
904 rdp
.update
|= UPDATE_CULL_MODE
;
909 if (rdp
.cmd1
& 0x00010000) // Fog enable
911 if (!(rdp
.flags
& FOG_ENABLED
))
913 rdp
.flags
|= FOG_ENABLED
;
914 rdp
.update
|= UPDATE_FOG_ENABLED
;
919 static void uc0_cleargeometrymode()
921 FRDP("uc0:cleargeometrymode %08lx\n", rdp
.cmd1
);
923 rdp
.geom_mode
&= (~rdp
.cmd1
);
925 if (rdp
.cmd1
& 0x00000001) // Z-Buffer enable
927 if (rdp
.flags
& ZBUF_ENABLED
)
929 rdp
.flags
^= ZBUF_ENABLED
;
930 rdp
.update
|= UPDATE_ZBUF_ENABLED
;
933 if (rdp
.cmd1
& 0x00001000) // Front culling
935 if (rdp
.flags
& CULL_FRONT
)
937 rdp
.flags
^= CULL_FRONT
;
938 rdp
.update
|= UPDATE_CULL_MODE
;
941 if (rdp
.cmd1
& 0x00002000) // Back culling
943 if (rdp
.flags
& CULL_BACK
)
945 rdp
.flags
^= CULL_BACK
;
946 rdp
.update
|= UPDATE_CULL_MODE
;
951 if (rdp
.cmd1
& 0x00010000) // Fog enable
953 if (rdp
.flags
& FOG_ENABLED
)
955 rdp
.flags
^= FOG_ENABLED
;
956 rdp
.update
|= UPDATE_FOG_ENABLED
;
961 static void uc0_quad3d()
963 // Actually line3d, not supported I think
965 int v0
= ((rdp
.cmd1
>> 16) & 0xff) / 10;
966 int v1
= ((rdp
.cmd1
>> 8) & 0xff) / 10;
967 int f
= (rdp
.cmd1
>> 24) & 0xff;
969 FRDP("uc0:line3d v0:%d, v1:%d, f:%02lx - IGNORED\n", v0
, v1
, f
);
972 static void uc0_rdphalf_1()
974 RDP_E("uc0:rdphalf_1 - IGNORED\n");
975 RDP ("uc0:rdphalf_1 - IGNORED\n");
978 static void uc0_rdphalf_2()
980 RDP_E("uc0:rdphalf_2 - IGNORED\n");
981 RDP ("uc0:rdphalf_2 - IGNORED\n");
984 static void uc0_rdphalf_cont()
986 RDP_E("uc0:rdphalf_cont - IGNORED\n");
987 RDP ("uc0:rdphalf_cont - IGNORED\n");
990 static void uc0_tri4 ()
992 // c0: 0000 0123, c1: 456789ab
993 // becomes: 405 617 829 a3b
996 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,
997 (rdp
.cmd1
>> 28) & 0xF,
998 (rdp
.cmd0
>> 12) & 0xF,
999 (rdp
.cmd1
>> 24) & 0xF,
1000 (rdp
.cmd1
>> 20) & 0xF,
1001 (rdp
.cmd0
>> 8) & 0xF,
1002 (rdp
.cmd1
>> 16) & 0xF,
1003 (rdp
.cmd1
>> 12) & 0xF,
1004 (rdp
.cmd0
>> 4) & 0xF,
1005 (rdp
.cmd1
>> 8) & 0xF,
1006 (rdp
.cmd1
>> 4) & 0xF,
1007 (rdp
.cmd0
>> 0) & 0xF,
1008 (rdp
.cmd1
>> 0) & 0xF);
1011 &rdp
.vtx
[(rdp
.cmd1
>> 28) & 0xF],
1012 &rdp
.vtx
[(rdp
.cmd0
>> 12) & 0xF],
1013 &rdp
.vtx
[(rdp
.cmd1
>> 24) & 0xF],
1014 &rdp
.vtx
[(rdp
.cmd1
>> 20) & 0xF],
1015 &rdp
.vtx
[(rdp
.cmd0
>> 8) & 0xF],
1016 &rdp
.vtx
[(rdp
.cmd1
>> 16) & 0xF],
1017 &rdp
.vtx
[(rdp
.cmd1
>> 12) & 0xF],
1018 &rdp
.vtx
[(rdp
.cmd0
>> 4) & 0xF],
1019 &rdp
.vtx
[(rdp
.cmd1
>> 8) & 0xF],
1020 &rdp
.vtx
[(rdp
.cmd1
>> 4) & 0xF],
1021 &rdp
.vtx
[(rdp
.cmd0
>> 0) & 0xF],
1022 &rdp
.vtx
[(rdp
.cmd1
>> 0) & 0xF],