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 //****************************************************************
36 // January 2004 Created by Gonetz (Gonetz@ngs.ru)
37 //****************************************************************
39 DWORD uc8_normale_addr
= 0;
40 float uc8_coord_mod
[16];
42 static void uc8_vertex ()
44 if (rdp
.update
& UPDATE_MULT_MAT
)
46 rdp
.update
^= UPDATE_MULT_MAT
;
47 MulMatrices(rdp
.model
, rdp
.proj
, rdp
.combined
);
50 DWORD addr
= segoffset(rdp
.cmd1
);
54 rdp
.vn
= n
= (rdp
.cmd0
>> 12) & 0xFF;
55 rdp
.v0
= v0
= ((rdp
.cmd0
>> 1) & 0x7F) - n
;
57 FRDP ("uc8:vertex n: %d, v0: %d, from: %08lx\n", n
, v0
, addr
);
61 RDP_E ("** ERROR: uc2:vertex v0 < 0\n");
62 RDP ("** ERROR: uc2:vertex v0 < 0\n");
66 // This is special, not handled in update()
67 if (rdp
.update
& UPDATE_LIGHTS
)
69 rdp
.update
^= UPDATE_LIGHTS
;
71 // Calculate light vectors
72 for (DWORD l
=0; l
<rdp
.num_lights
; l
++)
74 InverseTransformVector(&rdp
.light
[l
].dir_x
, rdp
.light_vector
[l
], rdp
.model
);
75 NormalizeVector (rdp
.light_vector
[l
]);
76 #ifdef EXTREME_LOGGING
77 FRDP("light_vector[%d] x: %f, y: %f, z: %f\n", l
, rdp
.light_vector
[l
][0], rdp
.light_vector
[l
][1], rdp
.light_vector
[l
][2]);
82 for (i
=0; i
< (n
<<4); i
+=16)
84 VERTEX
*v
= &rdp
.vtx
[v0
+ (i
>>4)];
85 x
= (float)((short*)gfx
.RDRAM
)[(((addr
+i
) >> 1) + 0)^1];
86 y
= (float)((short*)gfx
.RDRAM
)[(((addr
+i
) >> 1) + 1)^1];
87 z
= (float)((short*)gfx
.RDRAM
)[(((addr
+i
) >> 1) + 2)^1];
88 v
->flags
= ((WORD
*)gfx
.RDRAM
)[(((addr
+i
) >> 1) + 3)^1];
89 v
->ou
= (float)((short*)gfx
.RDRAM
)[(((addr
+i
) >> 1) + 4)^1] * rdp
.tiles
[rdp
.cur_tile
].s_scale
;
90 v
->ov
= (float)((short*)gfx
.RDRAM
)[(((addr
+i
) >> 1) + 5)^1] * rdp
.tiles
[rdp
.cur_tile
].t_scale
;
91 v
->a
= ((BYTE
*)gfx
.RDRAM
)[(addr
+i
+ 15)^3];
93 #ifdef EXTREME_LOGGING
94 FRDP ("before v%d - x: %f, y: %f, z: %f\n", i
>>4, x
, y
, z
);
96 v
->x
= x
*rdp
.combined
[0][0] + y
*rdp
.combined
[1][0] + z
*rdp
.combined
[2][0] + rdp
.combined
[3][0];
97 v
->y
= x
*rdp
.combined
[0][1] + y
*rdp
.combined
[1][1] + z
*rdp
.combined
[2][1] + rdp
.combined
[3][1];
98 v
->z
= x
*rdp
.combined
[0][2] + y
*rdp
.combined
[1][2] + z
*rdp
.combined
[2][2] + rdp
.combined
[3][2];
99 v
->w
= x
*rdp
.combined
[0][3] + y
*rdp
.combined
[1][3] + z
*rdp
.combined
[2][3] + rdp
.combined
[3][3];
101 #ifdef EXTREME_LOGGING
102 FRDP ("v%d - x: %f, y: %f, z: %f, w: %f, u: %f, v: %f, flags: %d\n", i
>>4, v
->x
, v
->y
, v
->z
, v
->w
, v
->ou
, v
->ov
, v
->flags
);
105 v
->oow
= 1.0f
/ v
->w
;
106 v
->x_w
= v
->x
* v
->oow
;
107 v
->y_w
= v
->y
* v
->oow
;
108 v
->z_w
= v
->z
* v
->oow
;
110 v
->uv_calculated
= 0xFFFFFFFF;
111 v
->screen_translated
= 0;
112 v
->shade_mods_allowed
= 1;
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;
121 v
->r
= ((BYTE
*)gfx
.RDRAM
)[(addr
+i
+ 12)^3];
122 v
->g
= ((BYTE
*)gfx
.RDRAM
)[(addr
+i
+ 13)^3];
123 v
->b
= ((BYTE
*)gfx
.RDRAM
)[(addr
+i
+ 14)^3];
124 #ifdef EXTREME_LOGGING
125 FRDP ("r: %02lx, g: %02lx, b: %02lx, a: %02lx\n", v
->r
, v
->g
, v
->b
, v
->a
);
128 if ((rdp
.geom_mode
& 0x00020000))
130 DWORD shift
= v0
<< 1;
131 v
->vec
[0] = ((char*)gfx
.RDRAM
)[(uc8_normale_addr
+ (i
>>3) + shift
+ 0)^3];
132 v
->vec
[1] = ((char*)gfx
.RDRAM
)[(uc8_normale_addr
+ (i
>>3) + shift
+ 1)^3];
133 v
->vec
[2] = (char)(v
->flags
&0xff);
135 if (rdp
.geom_mode
& 0x80000)
138 #ifdef EXTREME_LOGGING
139 FRDP ("calc linear: v%d - u: %f, v: %f\n", i
>>4, v
->ou
, v
->ov
);
142 else if (rdp
.geom_mode
& 0x40000)
145 #ifdef EXTREME_LOGGING
146 FRDP ("calc sphere: v%d - u: %f, v: %f\n", i
>>4, v
->ou
, v
->ov
);
149 // FRDP("calc light. r: 0x%02lx, g: 0x%02lx, b: 0x%02lx, nx: %.3f, ny: %.3f, nz: %.3f\n", v->r, v->g, v->b, v->vec[0], v->vec[1], v->vec[2]);
150 FRDP("v[%d] calc light. r: 0x%02lx, g: 0x%02lx, b: 0x%02lx\n", i
>>4, v
->r
, v
->g
, v
->b
);
151 float color
[3] = {rdp
.light
[rdp
.num_lights
].r
, rdp
.light
[rdp
.num_lights
].g
, rdp
.light
[rdp
.num_lights
].b
};
152 FRDP("ambient light. r: %f, g: %f, b: %f\n", color
[0], color
[1], color
[2]);
153 float light_intensity
= 0.0f
;
155 if (rdp
.geom_mode
& 0x00400000)
157 NormalizeVector (v
->vec
);
158 for (l
= 0; l
< rdp
.num_lights
-1; l
++)
160 if (!rdp
.light
[l
].nonblack
)
162 light_intensity
= DotProduct (rdp
.light_vector
[l
], v
->vec
);
163 FRDP("light %d, intensity : %f\n", l
, light_intensity
);
164 if (light_intensity
< 0.0f
)
167 if (rdp
.light
[l
].ca
> 0.0f
)
169 float vx
= (v
->x
+ uc8_coord_mod
[8])*uc8_coord_mod
[12] - rdp
.light
[l
].x
;
170 float vy
= (v
->y
+ uc8_coord_mod
[9])*uc8_coord_mod
[13] - rdp
.light
[l
].y
;
171 float vz
= (v
->z
+ uc8_coord_mod
[10])*uc8_coord_mod
[14] - rdp
.light
[l
].z
;
172 float vw
= (v
->w
+ uc8_coord_mod
[11])*uc8_coord_mod
[15] - rdp
.light
[l
].w
;
173 float len
= (vx
*vx
+vy
*vy
+vz
*vz
+vw
*vw
)/65536.0f
;
174 float p_i
= rdp
.light
[l
].ca
/ len
;
175 if (p_i
> 1.0f
) p_i
= 1.0f
;
176 light_intensity
*= p_i
;
177 FRDP("light %d, len: %f, p_intensity : %f\n", l
, len
, p_i
);
180 color
[0] += rdp
.light
[l
].r
* light_intensity
;
181 color
[1] += rdp
.light
[l
].g
* light_intensity
;
182 color
[2] += rdp
.light
[l
].b
* light_intensity
;
183 FRDP("light %d r: %f, g: %f, b: %f\n", l
, color
[0], color
[1], color
[2]);
185 light_intensity
= DotProduct (rdp
.light_vector
[l
], v
->vec
);
186 FRDP("light %d, intensity : %f\n", l
, light_intensity
);
187 if (light_intensity
> 0.0f
)
189 color
[0] += rdp
.light
[l
].r
* light_intensity
;
190 color
[1] += rdp
.light
[l
].g
* light_intensity
;
191 color
[2] += rdp
.light
[l
].b
* light_intensity
;
193 FRDP("light %d r: %f, g: %f, b: %f\n", l
, color
[0], color
[1], color
[2]);
197 for (l
= 0; l
< rdp
.num_lights
; l
++)
199 if (rdp
.light
[l
].nonblack
&& rdp
.light
[l
].nonzero
)
201 float vx
= (v
->x
+ uc8_coord_mod
[8])*uc8_coord_mod
[12] - rdp
.light
[l
].x
;
202 float vy
= (v
->y
+ uc8_coord_mod
[9])*uc8_coord_mod
[13] - rdp
.light
[l
].y
;
203 float vz
= (v
->z
+ uc8_coord_mod
[10])*uc8_coord_mod
[14] - rdp
.light
[l
].z
;
204 float vw
= (v
->w
+ uc8_coord_mod
[11])*uc8_coord_mod
[15] - rdp
.light
[l
].w
;
205 float len
= (vx
*vx
+vy
*vy
+vz
*vz
+vw
*vw
)/65536.0f
;
206 light_intensity
= rdp
.light
[l
].ca
/ len
;
207 if (light_intensity
> 1.0f
) light_intensity
= 1.0f
;
208 FRDP("light %d, p_intensity : %f\n", l
, light_intensity
);
209 color
[0] += rdp
.light
[l
].r
* light_intensity
;
210 color
[1] += rdp
.light
[l
].g
* light_intensity
;
211 color
[2] += rdp
.light
[l
].b
* light_intensity
;
212 //FRDP("light %d r: %f, g: %f, b: %f\n", l, color[0], color[1], color[2]);
216 if (color
[0] > 1.0f
) color
[0] = 1.0f
;
217 if (color
[1] > 1.0f
) color
[1] = 1.0f
;
218 if (color
[2] > 1.0f
) color
[2] = 1.0f
;
219 v
->r
= (BYTE
)(((float)v
->r
)*color
[0]);
220 v
->g
= (BYTE
)(((float)v
->g
)*color
[1]);
221 v
->b
= (BYTE
)(((float)v
->b
)*color
[2]);
222 #ifdef EXTREME_LOGGING
223 FRDP("color after light: r: 0x%02lx, g: 0x%02lx, b: 0x%02lx\n", v
->r
, v
->g
, v
->b
);
229 static void uc8_moveword ()
231 BYTE index
= (BYTE
)((rdp
.cmd0
>> 16) & 0xFF);
232 WORD offset
= (WORD
)(rdp
.cmd0
& 0xFFFF);
233 DWORD data
= rdp
.cmd1
;
235 FRDP ("uc8:moveword ");
239 // NOTE: right now it's assuming that it sets the integer part first. This could
240 // be easily fixed, but only if i had something to test with.
243 rdp
.num_lights
= (data
/ 48);
244 rdp
.update
|= UPDATE_LIGHTS
;
245 FRDP ("numlights: %d\n", rdp
.num_lights
);
249 FRDP ("mw_clip %08lx, %08lx\n", rdp
.cmd0
, rdp
.cmd1
);
252 case 0x06: // moveword SEGMENT
254 FRDP ("SEGMENT %08lx -> seg%d\n", data
, offset
>> 2);
255 rdp
.segment
[(offset
>> 2) & 0xF] = data
;
261 rdp
.fog_multiplier
= (short)(rdp
.cmd1
>> 16);
262 rdp
.fog_offset
= (short)(rdp
.cmd1
& 0x0000FFFF);
263 FRDP ("fog: multiplier: %f, offset: %f\n", rdp
.fog_multiplier
, rdp
.fog_offset
);
268 RDP_E ("uc8:moveword forcemtx - IGNORED\n");
269 RDP ("forcemtx - IGNORED\n");
273 RDP ("perspnorm - IGNORED\n");
276 case 0x10: // moveword coord mod
278 BYTE n
= offset
>> 2;
280 FRDP ("coord mod:%d, %08lx\n", n
, data
);
283 DWORD idx
= (rdp
.cmd0
>>1)&3;
284 DWORD pos
= rdp
.cmd0
&0x30;
287 uc8_coord_mod
[0+idx
] = (short)(rdp
.cmd1
>>16);
288 uc8_coord_mod
[1+idx
] = (short)(rdp
.cmd1
&0xffff);
290 else if (pos
== 0x10)
292 uc8_coord_mod
[4+idx
] = (rdp
.cmd1
>>16)/65536.0f
;
293 uc8_coord_mod
[5+idx
] = (rdp
.cmd1
&0xffff)/65536.0f
;
294 uc8_coord_mod
[12+idx
] = uc8_coord_mod
[0+idx
] + uc8_coord_mod
[4+idx
];
295 uc8_coord_mod
[13+idx
] = uc8_coord_mod
[1+idx
] + uc8_coord_mod
[5+idx
];
298 else if (pos
== 0x20)
300 uc8_coord_mod
[8+idx
] = (short)(rdp
.cmd1
>>16);
301 uc8_coord_mod
[9+idx
] = (short)(rdp
.cmd1
&0xffff);
302 #ifdef EXTREME_LOGGING
305 for (int k
= 8; k
< 16; k
++)
307 FRDP("coord_mod[%d]=%f\n", k
, uc8_coord_mod
[k
]);
317 FRDP_E("uc8:moveword unknown (index: 0x%08lx, offset 0x%08lx)\n", index
, offset
);
318 FRDP ("unknown (index: 0x%08lx, offset 0x%08lx)\n", index
, offset
);
322 static void uc8_movemem ()
324 int idx
= rdp
.cmd0
& 0xFF;
325 DWORD addr
= segoffset(rdp
.cmd1
);
326 int ofs
= (rdp
.cmd0
>> 5) & 0x3FFF;
328 FRDP ("uc8:movemem ofs:%d ", ofs
);
335 short scale_x
= ((short*)gfx
.RDRAM
)[(a
+0)^1] >> 2;
336 short scale_y
= ((short*)gfx
.RDRAM
)[(a
+1)^1] >> 2;
337 short scale_z
= ((short*)gfx
.RDRAM
)[(a
+2)^1];
338 short trans_x
= ((short*)gfx
.RDRAM
)[(a
+4)^1] >> 2;
339 short trans_y
= ((short*)gfx
.RDRAM
)[(a
+5)^1] >> 2;
340 short trans_z
= ((short*)gfx
.RDRAM
)[(a
+6)^1];
341 rdp
.view_scale
[0] = scale_x
* rdp
.scale_x
;
342 rdp
.view_scale
[1] = -scale_y
* rdp
.scale_y
;
343 rdp
.view_scale
[2] = 32.0f
* scale_z
;
344 rdp
.view_trans
[0] = trans_x
* rdp
.scale_x
;
345 rdp
.view_trans
[1] = trans_y
* rdp
.scale_y
;
346 rdp
.view_trans
[2] = 32.0f
* trans_z
;
348 rdp
.update
|= UPDATE_VIEWPORT
;
350 FRDP ("viewport scale(%d, %d), trans(%d, %d), from:%08lx\n", scale_x
, scale_y
,
351 trans_x
, trans_y
, a
);
360 char dir_x
= ((char*)gfx
.RDRAM
)[(addr
+8)^3];
361 rdp
.lookat
[n
][0] = (float)(dir_x
) / 127.0f
;
362 char dir_y
= ((char*)gfx
.RDRAM
)[(addr
+9)^3];
363 rdp
.lookat
[n
][1] = (float)(dir_y
) / 127.0f
;
364 char dir_z
= ((char*)gfx
.RDRAM
)[(addr
+10)^3];
365 rdp
.lookat
[n
][2] = (float)(dir_z
) / 127.0f
;
366 rdp
.use_lookat
= TRUE
;
369 if (!dir_x
&& !dir_y
)
370 rdp
.use_lookat
= FALSE
;
372 FRDP("lookat_%d (%f, %f, %f)\n", n
, rdp
.lookat
[n
][0], rdp
.lookat
[n
][1], rdp
.lookat
[n
][2]);
376 BYTE col
= gfx
.RDRAM
[(addr
+0)^3];
377 rdp
.light
[n
].r
= (float)col
/ 255.0f
;
378 rdp
.light
[n
].nonblack
= col
;
379 col
= gfx
.RDRAM
[(addr
+1)^3];
380 rdp
.light
[n
].g
= (float)col
/ 255.0f
;
381 rdp
.light
[n
].nonblack
+= col
;
382 col
= gfx
.RDRAM
[(addr
+2)^3];
383 rdp
.light
[n
].b
= (float)col
/ 255.0f
;
384 rdp
.light
[n
].nonblack
+= col
;
385 rdp
.light
[n
].a
= 1.0f
;
386 rdp
.light
[n
].dir_x
= (float)(((char*)gfx
.RDRAM
)[(addr
+8)^3]) / 127.0f
;
387 rdp
.light
[n
].dir_y
= (float)(((char*)gfx
.RDRAM
)[(addr
+9)^3]) / 127.0f
;
388 rdp
.light
[n
].dir_z
= (float)(((char*)gfx
.RDRAM
)[(addr
+10)^3]) / 127.0f
;
392 //short pos = ((short*)gfx.RDRAM)[(a+16)^1];
393 rdp
.light
[n
].x
= (float)(((short*)gfx
.RDRAM
)[(a
+16)^1]);
394 rdp
.light
[n
].y
= (float)(((short*)gfx
.RDRAM
)[(a
+17)^1]);
395 rdp
.light
[n
].z
= (float)(((short*)gfx
.RDRAM
)[(a
+18)^1]);
396 rdp
.light
[n
].w
= (float)(((short*)gfx
.RDRAM
)[(a
+19)^1]);
397 rdp
.light
[n
].nonzero
= gfx
.RDRAM
[(addr
+12)^3];
398 rdp
.light
[n
].ca
= (float)rdp
.light
[n
].nonzero
/ 16.0f
;
399 // rdp.light[n].la = rdp.light[n].ca * 1.0f;
400 //#ifdef EXTREME_LOGGING
401 FRDP ("light: n: %d, pos: x: %f, y: %f, z: %f, w: %f, ca: %f\n",
402 n
, rdp
.light
[n
].x
, rdp
.light
[n
].y
, rdp
.light
[n
].z
, rdp
.light
[n
].w
, rdp
.light
[n
].ca
);
404 FRDP ("light: n: %d, r: %f, g: %f, b: %f. dir: x: %.3f, y: %.3f, z: %.3f\n",
405 n
, rdp
.light
[n
].r
, rdp
.light
[n
].g
, rdp
.light
[n
].b
,
406 rdp
.light
[n
].dir_x
, rdp
.light
[n
].dir_y
, rdp
.light
[n
].dir_z
);
407 #ifdef EXTREME_LOGGING
408 for (int t
=0; t
< 24; t
++)
410 FRDP ("light[%d] = 0x%04lx \n", t
, ((WORD
*)gfx
.RDRAM
)[(a
+t
)^1]);
418 uc8_normale_addr
= segoffset(rdp
.cmd1
);
419 FRDP ("Normale - addr: %08lx\n", uc8_normale_addr
);
420 #ifdef EXTREME_LOGGING
421 for (int i
= 0; i
< 32; i
++)
423 char x
= ((char*)gfx
.RDRAM
)[uc8_normale_addr
+ ((i
<<1) + 0)^3];
424 char y
= ((char*)gfx
.RDRAM
)[uc8_normale_addr
+ ((i
<<1) + 1)^3];
425 FRDP("#%d x = %d, y = %d\n", i
, x
, y
);
427 DWORD a
= uc8_normale_addr
>> 1;
428 for (i
= 0; i
< 32; i
++)
430 FRDP ("n[%d] = 0x%04lx \n", i
, ((WORD
*)gfx
.RDRAM
)[(a
+i
)^1]);
437 FRDP ("uc8:movemem unknown (%d)\n", idx
);
442 static void uc8_tri4() //by Gugaman Apr 19 2002
444 if (rdp
.skip_drawing
)
446 RDP("uc8:tri4. skipped\n");
450 FRDP("uc8:tri4 (#%d - #%d), %d-%d-%d, %d-%d-%d, %d-%d-%d, %d-%d-%d\n",
453 ((rdp
.cmd0
>> 23) & 0x1F),
454 ((rdp
.cmd0
>> 18) & 0x1F),
455 ((((rdp
.cmd0
>> 15) & 0x7) << 2) | ((rdp
.cmd1
>> 30) &0x3)),
456 ((rdp
.cmd0
>> 10) & 0x1F),
457 ((rdp
.cmd0
>> 5) & 0x1F),
458 ((rdp
.cmd0
>> 0) & 0x1F),
459 ((rdp
.cmd1
>> 25) & 0x1F),
460 ((rdp
.cmd1
>> 20) & 0x1F),
461 ((rdp
.cmd1
>> 15) & 0x1F),
462 ((rdp
.cmd1
>> 10) & 0x1F),
463 ((rdp
.cmd1
>> 5) & 0x1F),
464 ((rdp
.cmd1
>> 0) & 0x1F));
467 &rdp
.vtx
[(rdp
.cmd0
>> 23) & 0x1F],
468 &rdp
.vtx
[(rdp
.cmd0
>> 18) & 0x1F],
469 &rdp
.vtx
[((((rdp
.cmd0
>> 15) & 0x7) << 2) | ((rdp
.cmd1
>> 30) &0x3))],
470 &rdp
.vtx
[(rdp
.cmd0
>> 10) & 0x1F],
471 &rdp
.vtx
[(rdp
.cmd0
>> 5) & 0x1F],
472 &rdp
.vtx
[(rdp
.cmd0
>> 0) & 0x1F],
473 &rdp
.vtx
[(rdp
.cmd1
>> 25) & 0x1F],
474 &rdp
.vtx
[(rdp
.cmd1
>> 20) & 0x1F],
475 &rdp
.vtx
[(rdp
.cmd1
>> 15) & 0x1F],
476 &rdp
.vtx
[(rdp
.cmd1
>> 10) & 0x1F],
477 &rdp
.vtx
[(rdp
.cmd1
>> 5) & 0x1F],
478 &rdp
.vtx
[(rdp
.cmd1
>> 0) & 0x1F]