Glide Plugin GLES2 port from mupen64plus-ae, but with special FrameSkip code
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glide64 / ucode08.h
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 // January 2004 Created by Gonetz (Gonetz@ngs.ru)
41 //
42 //****************************************************************
43
44 wxUint32 uc8_normale_addr = 0;
45 float uc8_coord_mod[16];
46
47 static void uc8_vertex ()
48 {
49 Check_FrameSkip;
50
51         if (rdp.update & UPDATE_MULT_MAT)
52         {
53                 rdp.update ^= UPDATE_MULT_MAT;
54         MulMatrices(rdp.model, rdp.proj, rdp.combined);
55         }
56
57         wxUint32 addr = segoffset(rdp.cmd1);
58         int v0, i, n;
59         float x, y, z;
60
61         rdp.vn = n = (rdp.cmd0 >> 12) & 0xFF;
62         rdp.v0 = v0 = ((rdp.cmd0 >> 1) & 0x7F) - n;
63
64         FRDP ("uc8:vertex n: %d, v0: %d, from: %08lx\n", n, v0, addr);
65
66         if (v0 < 0)
67         {
68                 RDP_E ("** ERROR: uc2:vertex v0 < 0\n");
69                 LRDP("** ERROR: uc2:vertex v0 < 0\n");
70                 return;
71         }
72         //*
73         // This is special, not handled in update()
74         if (rdp.update & UPDATE_LIGHTS)
75         {
76                 rdp.update ^= UPDATE_LIGHTS;
77
78                 // Calculate light vectors
79                 for (wxUint32 l=0; l<rdp.num_lights; l++)
80                 {
81                         InverseTransformVector(&rdp.light[l].dir_x, rdp.light_vector[l], rdp.model);
82                         NormalizeVector (rdp.light_vector[l]);
83 #ifdef EXTREME_LOGGING
84                         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]);
85 #endif
86                 }
87         }
88         //*/
89     #ifdef __ARM_NEON__
90     float32x4_t comb0, comb1, comb2, comb3;
91     float32x4_t v_xyzw;
92     comb0 = vld1q_f32(rdp.combined[0]);
93     comb1 = vld1q_f32(rdp.combined[1]);
94     comb2 = vld1q_f32(rdp.combined[2]);
95     comb3 = vld1q_f32(rdp.combined[3]);
96         
97         float32x4_t uc8_8_11, uc8_12_15;
98         uc8_8_11 = vld1q_f32(uc8_coord_mod+8);
99         uc8_12_15 = vld1q_f32(uc8_coord_mod+12);
100         float32x4_t unite={1.0f, 1.0f, 1.0f, 1.0f};
101         
102         float32x4_t rdplight[12], rdpcolor[12];
103         for (i=0; i<rdp.num_lights; i++) {
104                 rdplight[i] = vld1q_f32(&rdp.light[i].x);
105                 rdpcolor[i] = vld1q_f32(&rdp.light[i].r);
106         }
107         
108     #endif
109         for (i=0; i < (n<<4); i+=16)
110         {
111                 VERTEX *v = &rdp.vtx[v0 + (i>>4)];
112                 x   = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 0)^1];
113                 y   = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 1)^1];
114                 z   = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 2)^1];
115                 v->flags  = ((wxUint16*)gfx.RDRAM)[(((addr+i) >> 1) + 3)^1];
116                 v->ou   = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 4)^1];
117                 v->ov   = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 5)^1];
118         v->uv_scaled = 0;
119                 v->a    = ((wxUint8*)gfx.RDRAM)[(addr+i + 15)^3];
120
121 #ifdef EXTREME_LOGGING
122                 FRDP ("before v%d - x: %f, y: %f, z: %f\n", i>>4, x, y, z);
123 #endif
124                 #ifdef __ARM_NEON__
125                 v_xyzw = x*comb0+y*comb1+z*comb2+comb3;
126                 //vst1q_f32((float*)v, v_xyzw);
127                 #else
128                 v->x = x*rdp.combined[0][0] + y*rdp.combined[1][0] + z*rdp.combined[2][0] + rdp.combined[3][0];
129                 v->y = x*rdp.combined[0][1] + y*rdp.combined[1][1] + z*rdp.combined[2][1] + rdp.combined[3][1];
130                 v->z = x*rdp.combined[0][2] + y*rdp.combined[1][2] + z*rdp.combined[2][2] + rdp.combined[3][2];
131                 v->w = x*rdp.combined[0][3] + y*rdp.combined[1][3] + z*rdp.combined[2][3] + rdp.combined[3][3];
132                 #endif
133
134 #ifdef EXTREME_LOGGING
135                 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);
136 #endif
137                 v->uv_calculated = 0xFFFFFFFF;
138                 v->screen_translated = 0;
139                 v->shade_mod = 0;
140                 #ifdef __ARM_NEON__
141                 v->x=v_xyzw[0];
142                 v->y=v_xyzw[1];
143                 v->z=v_xyzw[2];
144                 v->w=v_xyzw[3];
145                 #endif
146
147                 ///*
148                 v->r = ((wxUint8*)gfx.RDRAM)[(addr+i + 12)^3];
149                 v->g = ((wxUint8*)gfx.RDRAM)[(addr+i + 13)^3];
150                 v->b = ((wxUint8*)gfx.RDRAM)[(addr+i + 14)^3];
151
152         if (fabs(v->w) < 0.001) v->w = 0.001f;
153                 v->oow = 1.0f / v->w;
154                 #ifdef __ARM_NEON__
155                 v_xyzw *= v->oow;
156                 v->x_w=v_xyzw[0];
157                 v->y_w=v_xyzw[1];
158                 v->z_w=v_xyzw[2];
159                 #else
160                 v->x_w = v->x * v->oow;
161                 v->y_w = v->y * v->oow;
162                 v->z_w = v->z * v->oow;
163                 #endif
164
165                 v->scr_off = 0;
166                 if (v->x < -v->w) v->scr_off |= 1;
167                 if (v->x > v->w) v->scr_off |= 2;
168                 if (v->y < -v->w) v->scr_off |= 4;
169                 if (v->y > v->w) v->scr_off |= 8;
170                 if (v->w < 0.1f) v->scr_off |= 16;
171 #ifdef EXTREME_LOGGING
172                 FRDP ("r: %02lx, g: %02lx, b: %02lx, a: %02lx\n", v->r, v->g, v->b, v->a);
173 #endif
174
175                 if ((rdp.geom_mode & 0x00020000))
176                 {
177                         wxUint32 shift = v0 << 1;
178                         v->vec[0] = ((char*)gfx.RDRAM)[(uc8_normale_addr + (i>>3) + shift + 0)^3];
179                         v->vec[1] = ((char*)gfx.RDRAM)[(uc8_normale_addr + (i>>3) + shift + 1)^3];
180                         v->vec[2] = (char)(v->flags&0xff);
181
182                         if (rdp.geom_mode & 0x80000)
183                         {
184                                 calc_linear (v);
185 #ifdef EXTREME_LOGGING
186                                 FRDP ("calc linear: v%d - u: %f, v: %f\n", i>>4, v->ou, v->ov);
187 #endif
188                         }
189                         else if (rdp.geom_mode & 0x40000)
190                         {
191                                 calc_sphere (v);
192 #ifdef EXTREME_LOGGING
193                                 FRDP ("calc sphere: v%d - u: %f, v: %f\n", i>>4, v->ou, v->ov);
194 #endif
195                         }
196                         //     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]);
197                         FRDP("v[%d] calc light. r: 0x%02lx, g: 0x%02lx, b: 0x%02lx\n", i>>4, v->r, v->g, v->b);
198                         #ifdef __ARM_NEON__
199                         float32x4_t color = {rdp.light[rdp.num_lights].r, rdp.light[rdp.num_lights].g, rdp.light[rdp.num_lights].b, 1.0f};
200                         #else
201                         float color[3] = {rdp.light[rdp.num_lights].r, rdp.light[rdp.num_lights].g, rdp.light[rdp.num_lights].b};
202                         #endif
203                         FRDP("ambient light. r: %f, g: %f, b: %f\n", color[0], color[1], color[2]);
204                         float light_intensity = 0.0f;
205                         wxUint32 l;
206                         if (rdp.geom_mode & 0x00400000)
207                         {
208                                 NormalizeVector (v->vec);
209                                 for (l = 0; l < rdp.num_lights-1; l++)
210         {
211           if (!rdp.light[l].nonblack)
212             continue;
213           light_intensity = DotProduct (rdp.light_vector[l], v->vec);
214           FRDP("light %d, intensity : %f\n", l, light_intensity);
215           if (light_intensity < 0.0f)
216             continue;
217           //*
218           if (rdp.light[l].ca > 0.0f)
219           {
220                         #ifdef __ARM_NEON__
221                         float32x4_t vxyzw = (v_xyzw + uc8_8_11)*uc8_12_15 - rdplight[l];
222                         vxyzw = vxyzw*vxyzw;
223                         float invlen = 65536.0f/(vxyzw[0]+vxyzw[1]+vxyzw[2]+vxyzw[3]);
224             float p_i = rdp.light[l].ca * invlen;
225                         #else
226             float vx = (v->x + uc8_coord_mod[8])*uc8_coord_mod[12] - rdp.light[l].x;
227             float vy = (v->y + uc8_coord_mod[9])*uc8_coord_mod[13] - rdp.light[l].y;
228             float vz = (v->z + uc8_coord_mod[10])*uc8_coord_mod[14] - rdp.light[l].z;
229             float vw = (v->w + uc8_coord_mod[11])*uc8_coord_mod[15] - rdp.light[l].w;
230             float len = (vx*vx+vy*vy+vz*vz+vw*vw)/65536.0f;
231             float p_i = rdp.light[l].ca / len;
232                         #endif
233             if (p_i > 1.0f) p_i = 1.0f;
234             light_intensity *= p_i;
235                         #if __ARM_NEON__
236             FRDP("light %d, 1/len: %f, p_intensity : %f\n", l, invlen, p_i);
237                         #else
238             FRDP("light %d, len: %f, p_intensity : %f\n", l, len, p_i);
239                         #endif
240           }
241           //*/
242                   #ifdef __ARM_NEON__
243                   color += rdpcolor[l] * light_intensity;
244                   #else
245           color[0] += rdp.light[l].r * light_intensity;
246           color[1] += rdp.light[l].g * light_intensity;
247           color[2] += rdp.light[l].b * light_intensity;
248                   #endif
249           FRDP("light %d r: %f, g: %f, b: %f\n", l, color[0], color[1], color[2]);
250         }
251         light_intensity = DotProduct (rdp.light_vector[l], v->vec);
252         FRDP("light %d, intensity : %f\n", l, light_intensity);
253         if (light_intensity > 0.0f)
254         {
255                   #ifdef __ARM_NEON__
256                   color += rdpcolor[l] * light_intensity;
257                   #else
258           color[0] += rdp.light[l].r * light_intensity;
259           color[1] += rdp.light[l].g * light_intensity;
260           color[2] += rdp.light[l].b * light_intensity;
261                   #endif
262         }
263         FRDP("light %d r: %f, g: %f, b: %f\n", l, color[0], color[1], color[2]);
264       }
265                         else
266                         {
267                                 for (l = 0; l < rdp.num_lights; l++)
268                                 {
269                                         if (rdp.light[l].nonblack && rdp.light[l].nonzero)
270                                         {
271                                                 #ifdef __ARM_NEON__
272                                                 float32x4_t vxyzw = (v_xyzw + uc8_8_11)*uc8_12_15 - rdplight[l];
273                                                 vxyzw = vxyzw*vxyzw;
274                                                 float invlen = 65536.0f/(vxyzw[0]+vxyzw[1]+vxyzw[2]+vxyzw[3]);
275                                                 light_intensity = rdp.light[l].ca * invlen;
276                                                 #else
277                                                 float vx = (v->x + uc8_coord_mod[8])*uc8_coord_mod[12] - rdp.light[l].x;
278                                                 float vy = (v->y + uc8_coord_mod[9])*uc8_coord_mod[13] - rdp.light[l].y;
279                                                 float vz = (v->z + uc8_coord_mod[10])*uc8_coord_mod[14] - rdp.light[l].z;
280                                                 float vw = (v->w + uc8_coord_mod[11])*uc8_coord_mod[15] - rdp.light[l].w;
281                                                 float len = (vx*vx+vy*vy+vz*vz+vw*vw)/65536.0f;
282                                                 light_intensity = rdp.light[l].ca / len;
283                                                 #endif
284                                                 if (light_intensity > 1.0f) light_intensity = 1.0f;
285                                                 FRDP("light %d, p_intensity : %f\n", l, light_intensity);
286                                             #ifdef __ARM_NEON__
287                                                 color += rdpcolor[l] * light_intensity;
288                                                 #else
289                                                 color[0] += rdp.light[l].r * light_intensity;
290                                                 color[1] += rdp.light[l].g * light_intensity;
291                                                 color[2] += rdp.light[l].b * light_intensity;
292                                                 #endif
293                                                 //FRDP("light %d r: %f, g: %f, b: %f\n", l, color[0], color[1], color[2]);
294                                         }
295                                 }
296                         }
297                         #ifdef __ARM_NEON__
298                         color = vminq_f32(color, unite);
299                         #else
300                         if (color[0] > 1.0f) color[0] = 1.0f;
301                         if (color[1] > 1.0f) color[1] = 1.0f;
302                         if (color[2] > 1.0f) color[2] = 1.0f;
303                         #endif
304                         v->r = (wxUint8)(((float)v->r)*color[0]);
305                         v->g = (wxUint8)(((float)v->g)*color[1]);
306                         v->b = (wxUint8)(((float)v->b)*color[2]);
307 #ifdef EXTREME_LOGGING
308                 FRDP("color after light: r: 0x%02lx, g: 0x%02lx, b: 0x%02lx\n", v->r, v->g, v->b);
309 #endif
310                 }
311   }
312 }
313
314 static void uc8_moveword ()
315 {
316         wxUint8 index = (wxUint8)((rdp.cmd0 >> 16) & 0xFF);
317         wxUint16 offset = (wxUint16)(rdp.cmd0 & 0xFFFF);
318         wxUint32 data = rdp.cmd1;
319
320         FRDP ("uc8:moveword ");
321
322         switch (index)
323         {
324                 // NOTE: right now it's assuming that it sets the integer part first.  This could
325                 //  be easily fixed, but only if i had something to test with.
326
327         case 0x02:
328                 rdp.num_lights = (data / 48);
329                 rdp.update |= UPDATE_LIGHTS;
330                 FRDP ("numlights: %d\n", rdp.num_lights);
331                 break;
332
333         case 0x04:
334     if (offset == 0x04)
335     {
336       rdp.clip_ratio = sqrt((float)rdp.cmd1);
337       rdp.update |= UPDATE_VIEWPORT;
338     }
339                 FRDP ("mw_clip %08lx, %08lx\n", rdp.cmd0, rdp.cmd1);
340                 break;
341
342         case 0x06:  // moveword SEGMENT
343                 {
344                         FRDP ("SEGMENT %08lx -> seg%d\n", data, offset >> 2);
345                         rdp.segment[(offset >> 2) & 0xF] = data;
346                 }
347                 break;
348
349         case 0x08:
350                 {
351                         rdp.fog_multiplier = (short)(rdp.cmd1 >> 16);
352                         rdp.fog_offset = (short)(rdp.cmd1 & 0x0000FFFF);
353                         FRDP ("fog: multiplier: %f, offset: %f\n", rdp.fog_multiplier, rdp.fog_offset);
354                 }
355                 break;
356
357         case 0x0c:
358                 RDP_E ("uc8:moveword forcemtx - IGNORED\n");
359                 LRDP("forcemtx - IGNORED\n");
360                 break;
361
362         case 0x0e:
363                 LRDP("perspnorm - IGNORED\n");
364                 break;
365
366         case 0x10:  // moveword coord mod
367                 {
368                         wxUint8 n = offset >> 2;
369
370                         FRDP ("coord mod:%d, %08lx\n", n, data);
371                         if (rdp.cmd0&8)
372                                 return;
373                         wxUint32 idx = (rdp.cmd0>>1)&3;
374                         wxUint32 pos = rdp.cmd0&0x30;
375                         if (pos == 0)
376                         {
377                                 uc8_coord_mod[0+idx] = (short)(rdp.cmd1>>16);
378                                 uc8_coord_mod[1+idx] = (short)(rdp.cmd1&0xffff);
379                         }
380                         else if (pos == 0x10)
381                         {
382                                 uc8_coord_mod[4+idx] = (rdp.cmd1>>16)/65536.0f;
383                                 uc8_coord_mod[5+idx] = (rdp.cmd1&0xffff)/65536.0f;
384                                 uc8_coord_mod[12+idx] = uc8_coord_mod[0+idx] + uc8_coord_mod[4+idx];
385                                 uc8_coord_mod[13+idx] = uc8_coord_mod[1+idx] + uc8_coord_mod[5+idx];
386
387                         }
388                         else if (pos == 0x20)
389                         {
390                                 uc8_coord_mod[8+idx] = (short)(rdp.cmd1>>16);
391                                 uc8_coord_mod[9+idx] = (short)(rdp.cmd1&0xffff);
392 #ifdef EXTREME_LOGGING
393                                 if (idx)
394                                 {
395                                         for (int k = 8; k < 16; k++)
396                                         {
397                                                 FRDP("coord_mod[%d]=%f\n", k, uc8_coord_mod[k]);
398                                         }
399                                 }
400 #endif
401                         }
402
403                 }
404                 break;
405
406         default:
407                 FRDP_E("uc8:moveword unknown (index: 0x%08lx, offset 0x%08lx)\n", index, offset);
408                 FRDP ("unknown (index: 0x%08lx, offset 0x%08lx)\n", index, offset);
409   }
410 }
411
412 static void uc8_movemem ()
413 {
414         int idx = rdp.cmd0 & 0xFF;
415         wxUint32 addr = segoffset(rdp.cmd1);
416         int ofs = (rdp.cmd0 >> 5) & 0x3FFF;
417
418         FRDP ("uc8:movemem ofs:%d ", ofs);
419
420         switch (idx)
421         {
422         case 8:   // VIEWPORT
423                 {
424                         wxUint32 a = addr >> 1;
425                         short scale_x = ((short*)gfx.RDRAM)[(a+0)^1] >> 2;
426                         short scale_y = ((short*)gfx.RDRAM)[(a+1)^1] >> 2;
427                         short scale_z = ((short*)gfx.RDRAM)[(a+2)^1];
428                         short trans_x = ((short*)gfx.RDRAM)[(a+4)^1] >> 2;
429                         short trans_y = ((short*)gfx.RDRAM)[(a+5)^1] >> 2;
430                         short trans_z = ((short*)gfx.RDRAM)[(a+6)^1];
431                         rdp.view_scale[0] = scale_x * rdp.scale_x;
432                         rdp.view_scale[1] = -scale_y * rdp.scale_y;
433                         rdp.view_scale[2] = 32.0f * scale_z;
434                         rdp.view_trans[0] = trans_x * rdp.scale_x;
435                         rdp.view_trans[1] = trans_y * rdp.scale_y;
436                         rdp.view_trans[2] = 32.0f * trans_z;
437
438                         rdp.update |= UPDATE_VIEWPORT;
439
440                         FRDP ("viewport scale(%d, %d), trans(%d, %d), from:%08lx\n", scale_x, scale_y,
441                                 trans_x, trans_y, a);
442                 }
443                 break;
444
445         case 10:  // LIGHT
446                 {
447                         int n = (ofs / 48);
448             if (n < 2)
449             {
450               char dir_x = ((char*)gfx.RDRAM)[(addr+8)^3];
451               rdp.lookat[n][0] = (float)(dir_x) / 127.0f;
452               char dir_y = ((char*)gfx.RDRAM)[(addr+9)^3];
453               rdp.lookat[n][1] = (float)(dir_y) / 127.0f;
454               char dir_z = ((char*)gfx.RDRAM)[(addr+10)^3];
455               rdp.lookat[n][2] = (float)(dir_z) / 127.0f;
456               rdp.use_lookat = TRUE;
457               if (n == 1)
458               {
459                  if (!dir_x && !dir_y)
460                    rdp.use_lookat = FALSE;
461               }
462               FRDP("lookat_%d (%f, %f, %f)\n", n, rdp.lookat[n][0], rdp.lookat[n][1], rdp.lookat[n][2]);
463               return;
464             }
465             n -= 2;
466                         wxUint8 col = gfx.RDRAM[(addr+0)^3];
467                         rdp.light[n].r = (float)col / 255.0f;
468                         rdp.light[n].nonblack = col;
469                         col = gfx.RDRAM[(addr+1)^3];
470                         rdp.light[n].g = (float)col / 255.0f;
471                         rdp.light[n].nonblack += col;
472                         col = gfx.RDRAM[(addr+2)^3];
473                         rdp.light[n].b = (float)col / 255.0f;
474                         rdp.light[n].nonblack += col;
475                         rdp.light[n].a = 1.0f;
476                         rdp.light[n].dir_x = (float)(((char*)gfx.RDRAM)[(addr+8)^3]) / 127.0f;
477                         rdp.light[n].dir_y = (float)(((char*)gfx.RDRAM)[(addr+9)^3]) / 127.0f;
478                         rdp.light[n].dir_z = (float)(((char*)gfx.RDRAM)[(addr+10)^3]) / 127.0f;
479                         // **
480                         wxUint32 a = addr >> 1;
481                         rdp.light[n].x = (float)(((short*)gfx.RDRAM)[(a+16)^1]);
482                         rdp.light[n].y = (float)(((short*)gfx.RDRAM)[(a+17)^1]);
483                         rdp.light[n].z = (float)(((short*)gfx.RDRAM)[(a+18)^1]);
484                         rdp.light[n].w = (float)(((short*)gfx.RDRAM)[(a+19)^1]);
485                         rdp.light[n].nonzero = gfx.RDRAM[(addr+12)^3];
486                         rdp.light[n].ca = (float)rdp.light[n].nonzero / 16.0f;
487                         //rdp.light[n].la = rdp.light[n].ca * 1.0f;
488 #ifdef EXTREME_LOGGING
489                         FRDP ("light: n: %d, pos: x: %f, y: %f, z: %f, w: %f, ca: %f\n",
490                                 n, rdp.light[n].x, rdp.light[n].y, rdp.light[n].z, rdp.light[n].w, rdp.light[n].ca);
491 #endif
492                         FRDP ("light: n: %d, r: %f, g: %f, b: %f. dir: x: %.3f, y: %.3f, z: %.3f\n",
493                                 n, rdp.light[n].r, rdp.light[n].g, rdp.light[n].b,
494                                 rdp.light[n].dir_x, rdp.light[n].dir_y, rdp.light[n].dir_z);
495 #ifdef EXTREME_LOGGING
496                         for (int t=0; t < 24; t++)
497                         {
498                                 FRDP ("light[%d] = 0x%04lx \n", t, ((wxUint16*)gfx.RDRAM)[(a+t)^1]);
499                         }
500 #endif
501                 }
502                 break;
503
504         case 14: //Normales
505                 {
506                         uc8_normale_addr = segoffset(rdp.cmd1);
507                         FRDP ("Normale - addr: %08lx\n", uc8_normale_addr);
508 #ifdef EXTREME_LOGGING
509       int i;
510                         for (i = 0; i < 32; i++)
511                         {
512                                 char x = ((char*)gfx.RDRAM)[uc8_normale_addr + ((i<<1) + 0)^3];
513                                 char y = ((char*)gfx.RDRAM)[uc8_normale_addr + ((i<<1) + 1)^3];
514                                 FRDP("#%d x = %d, y = %d\n", i, x, y);
515                         }
516                         wxUint32 a = uc8_normale_addr >> 1;
517                         for (i = 0; i < 32; i++)
518                         {
519                                 FRDP ("n[%d] = 0x%04lx \n", i, ((wxUint16*)gfx.RDRAM)[(a+i)^1]);
520                         }
521 #endif
522                 }
523                 break;
524
525         default:
526                 FRDP ("uc8:movemem unknown (%d)\n", idx);
527         }
528 }
529
530
531 static void uc8_tri4() //by Gugaman Apr 19 2002
532 {
533 Check_FrameSkip;
534
535     if (rdp.skip_drawing)
536     {
537                 LRDP("uc8:tri4. skipped\n");
538                 return;
539     }
540
541         FRDP("uc8:tri4 (#%d - #%d), %d-%d-%d, %d-%d-%d, %d-%d-%d, %d-%d-%d\n",
542                 rdp.tri_n,
543                 rdp.tri_n+3,
544                 ((rdp.cmd0 >> 23) & 0x1F),
545                 ((rdp.cmd0 >> 18) & 0x1F),
546                 ((((rdp.cmd0 >> 15) & 0x7) << 2) | ((rdp.cmd1 >> 30) &0x3)),
547                 ((rdp.cmd0 >> 10) & 0x1F),
548                 ((rdp.cmd0 >> 5) & 0x1F),
549                 ((rdp.cmd0 >> 0) & 0x1F),
550                 ((rdp.cmd1 >> 25) & 0x1F),
551                 ((rdp.cmd1 >> 20) & 0x1F),
552                 ((rdp.cmd1 >> 15) & 0x1F),
553                 ((rdp.cmd1 >> 10) & 0x1F),
554                 ((rdp.cmd1 >> 5) & 0x1F),
555                 ((rdp.cmd1 >> 0) & 0x1F));
556
557         VERTEX *v[12] = {
558                 &rdp.vtx[(rdp.cmd0 >> 23) & 0x1F],
559                         &rdp.vtx[(rdp.cmd0 >> 18) & 0x1F],
560                         &rdp.vtx[((((rdp.cmd0 >> 15) & 0x7) << 2) | ((rdp.cmd1 >> 30) &0x3))],
561                         &rdp.vtx[(rdp.cmd0 >> 10) & 0x1F],
562                         &rdp.vtx[(rdp.cmd0 >> 5) & 0x1F],
563                         &rdp.vtx[(rdp.cmd0 >> 0) & 0x1F],
564                         &rdp.vtx[(rdp.cmd1 >> 25) & 0x1F],
565                         &rdp.vtx[(rdp.cmd1 >> 20) & 0x1F],
566                         &rdp.vtx[(rdp.cmd1 >> 15) & 0x1F],
567                         &rdp.vtx[(rdp.cmd1 >> 10) & 0x1F],
568                         &rdp.vtx[(rdp.cmd1 >> 5) & 0x1F],
569                         &rdp.vtx[(rdp.cmd1 >> 0) & 0x1F]
570         };
571
572         int updated = 0;
573
574         if (cull_tri(v))
575                 rdp.tri_n ++;
576         else
577         {
578                 updated = 1;
579                 update ();
580
581                 draw_tri (v);
582                 rdp.tri_n ++;
583         }
584
585         if (cull_tri(v+3))
586                 rdp.tri_n ++;
587         else
588         {
589                 if (!updated)
590                 {
591                         updated = 1;
592                         update ();
593                 }
594
595                 draw_tri (v+3);
596                 rdp.tri_n ++;
597         }
598
599         if (cull_tri(v+6))
600                 rdp.tri_n ++;
601         else
602         {
603                 if (!updated)
604                 {
605                         updated = 1;
606                         update ();
607                 }
608
609                 draw_tri (v+6);
610                 rdp.tri_n ++;
611         }
612
613         if (cull_tri(v+9))
614                 rdp.tri_n ++;
615         else
616         {
617                 if (!updated)
618                 {
619                         updated = 1;
620                         update ();
621                 }
622
623                 draw_tri (v+9);
624                 rdp.tri_n ++;
625         }
626 }