Glide Plugin GLES2 port from mupen64plus-ae, but with special FrameSkip code
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glide64 / ucode09.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 // December 2008 Created by Gonetz (Gonetz@ngs.ru)
41 //
42 //****************************************************************
43
44 void uc9_rpdcmd ();
45
46 typedef float M44[4][4];
47
48 struct ZSORTRDP {
49   float view_scale[2];
50   float view_trans[2];
51   float scale_x;
52   float scale_y;
53 } zSortRdp = {{0, 0}, {0, 0}, 0, 0};
54
55 //RSP command VRCPL
56 static int Calc_invw (int w) {
57         int count, neg;
58   union {
59         wxInt32           W;
60         wxUint32          UW;
61         wxInt16                 HW[2];
62         wxUint16                UHW[2];
63   } Result;
64         Result.W = w;
65         if (Result.UW == 0) {
66                 Result.UW = 0x7FFFFFFF;
67         } else {
68                 if (Result.W < 0) {
69                         neg = TRUE;
70                         if (Result.UHW[1] == 0xFFFF && Result.HW[0] < 0) {
71                                 Result.W = ~Result.W + 1;
72                         } else {
73                                 Result.W = ~Result.W;
74                         }
75                 } else {
76                         neg = FALSE;
77                 }
78                 for (count = 31; count > 0; count--) {
79                         if ((Result.W & (1 << count))) {
80                                 Result.W &= (0xFFC00000 >> (31 - count) );
81                                 count = 0;
82                         }
83                 }
84                 Result.W = 0x7FFFFFFF / Result.W;
85                 for (count = 31; count > 0; count--) {
86                         if ((Result.W & (1 << count))) {
87                                 Result.W &= (0xFFFF8000 >> (31 - count) );
88                                 count = 0;
89                         }
90                 }
91                 if (neg == TRUE) {
92                         Result.W = ~Result.W;
93                 }
94         }
95   return Result.W;
96 }
97
98 static void uc9_draw_object (wxUint8 * addr, wxUint32 type)
99 {
100 Check_FrameSkip;
101
102   wxUint32 textured, vnum, vsize;
103   switch (type) {
104     case 1: //sh tri
105       textured = 0;
106       vnum = 3;
107       vsize = 8;
108       break;
109     case 2: //tx tri
110       textured = 1;
111       vnum = 3;
112       vsize = 16;
113       break;
114     case 3: //sh quad
115       textured = 0;
116       vnum = 4;
117       vsize = 8;
118       break;
119     case 4: //tx quad
120       textured = 1;
121       vnum = 4;
122       vsize = 16;
123       break;
124     case 0: //null
125     default:
126       textured = vnum = vsize = 0;
127       break;
128   }
129   VERTEX vtx[4];
130   for (wxUint32 i = 0; i < vnum; i++)
131   {
132     VERTEX &v = vtx[i];
133     v.sx = zSortRdp.scale_x * ((short*)addr)[0^1];
134     v.sy = zSortRdp.scale_y * ((short*)addr)[1^1];
135     v.sz = 1.0f;
136     v.r = addr[4^3];
137     v.g = addr[5^3];
138     v.b = addr[6^3];
139     v.a = addr[7^3];
140     v.flags = 0;
141     v.uv_scaled = 0;
142     v.uv_calculated = 0xFFFFFFFF;
143     v.shade_mod = 0;
144     v.scr_off = 0;
145     v.screen_translated = 2;
146     if (textured)
147     {
148       v.ou = ((short*)addr)[4^1];
149       v.ov = ((short*)addr)[5^1];
150       v.w = Calc_invw(((int*)addr)[3]) / 31.0f;
151       v.oow = 1.0f / v.w;
152       FRDP ("v%d - sx: %f, sy: %f ou: %f, ov: %f, w: %f, r=%d, g=%d, b=%d, a=%d\n", i, v.sx/rdp.scale_x, v.sy/rdp.scale_y, v.ou*rdp.tiles[rdp.cur_tile].s_scale, v.ov*rdp.tiles[rdp.cur_tile].t_scale, v.w, v.r, v.g, v.b, v.a);
153     }
154     else
155     {
156       v.oow = v.w = 1.0f;
157       FRDP ("v%d - sx: %f, sy: %f r=%d, g=%d, b=%d, a=%d\n", i, v.sx/rdp.scale_x, v.sy/rdp.scale_y, v.r, v.g, v.b, v.a);
158     }
159     addr += vsize;
160   }
161   //*
162   VERTEX *pV[4] = {
163     &vtx[0],
164     &vtx[1],
165     &vtx[2],
166     &vtx[3]
167   };
168   if (vnum == 3)
169   {
170     FRDP("uc9:Tri #%d, #%d\n", rdp.tri_n, rdp.tri_n+1);
171     draw_tri (pV, 0);
172     rdp.tri_n ++;
173   }
174   else
175   {
176     FRDP("uc9:Quad #%d, #%d\n", rdp.tri_n, rdp.tri_n+1);
177     draw_tri (pV, 0);
178     draw_tri (pV+1, 0);
179     rdp.tri_n += 2;
180   }
181 }
182
183 static wxUint32 uc9_load_object (wxUint32 zHeader, wxUint32 * rdpcmds)
184 {
185   wxUint32 type = zHeader & 7;
186   wxUint8 * addr = gfx.RDRAM + (zHeader&0xFFFFFFF8);
187   switch (type) {
188     case 1: //sh tri
189     case 3: //sh quad
190       {
191         rdp.cmd1 = ((wxUint32*)addr)[1];
192         if (rdp.cmd1 != rdpcmds[0])
193         {
194           rdpcmds[0] = rdp.cmd1;
195           uc9_rpdcmd ();
196         }
197         update ();
198         uc9_draw_object(addr + 8, type);
199       }
200       break;
201     case 0: //null
202     case 2: //tx tri
203     case 4: //tx quad
204       {
205         rdp.cmd1 = ((wxUint32*)addr)[1];
206         if (rdp.cmd1 != rdpcmds[0])
207         {
208           rdpcmds[0] = rdp.cmd1;
209           uc9_rpdcmd ();
210         }
211         rdp.cmd1 = ((wxUint32*)addr)[2];
212         if (rdp.cmd1 != rdpcmds[1])
213         {
214           uc9_rpdcmd ();
215           rdpcmds[1] = rdp.cmd1;
216         }
217         rdp.cmd1 = ((wxUint32*)addr)[3];
218         if (rdp.cmd1 != rdpcmds[2])
219         {
220           uc9_rpdcmd ();
221           rdpcmds[2] = rdp.cmd1;
222         }
223         if (type)
224         {
225           update ();
226           uc9_draw_object(addr + 16, type);
227         }
228       }
229       break;
230   }
231   return segoffset(((wxUint32*)addr)[0]);
232 }
233
234 static void uc9_object ()
235 {
236   LRDP("uc9:object\n");
237   wxUint32 rdpcmds[3] = {0, 0, 0};
238   wxUint32 cmd1 = rdp.cmd1;
239   wxUint32 zHeader = segoffset(rdp.cmd0);
240   while (zHeader)
241     zHeader = uc9_load_object(zHeader, rdpcmds);
242   zHeader = segoffset(cmd1);
243   while (zHeader)
244     zHeader = uc9_load_object(zHeader, rdpcmds);
245 }
246
247 static void uc9_mix ()
248 {
249   LRDP("uc9:mix IGNORED\n");
250 }
251
252 static void uc9_fmlight ()
253 {
254   int mid = rdp.cmd0&0xFF;
255   rdp.num_lights = 1 + ((rdp.cmd1>>12)&0xFF);
256   wxUint32 a = -1024 + (rdp.cmd1&0xFFF);
257   FRDP ("uc9:fmlight matrix: %d, num: %d, dmem: %04lx\n", mid, rdp.num_lights, a);
258
259   M44 *m = NULL;
260   switch (mid) {
261   case 4:
262     m = (M44*)rdp.model;
263     break;
264   case 6:
265     m = (M44*)rdp.proj;
266     break;
267   case 8:
268     m = (M44*)rdp.combined;
269     break;
270   }
271
272   rdp.light[rdp.num_lights].r = (float)(((wxUint8*)gfx.DMEM)[(a+0)^3]) / 255.0f;
273   rdp.light[rdp.num_lights].g = (float)(((wxUint8*)gfx.DMEM)[(a+1)^3]) / 255.0f;
274   rdp.light[rdp.num_lights].b = (float)(((wxUint8*)gfx.DMEM)[(a+2)^3]) / 255.0f;
275   rdp.light[rdp.num_lights].a = 1.0f;
276   FRDP ("ambient light: r: %.3f, g: %.3f, b: %.3f\n", rdp.light[rdp.num_lights].r, rdp.light[rdp.num_lights].g, rdp.light[rdp.num_lights].b);
277   a += 8;
278   wxUint32 i;
279   for (i = 0; i < rdp.num_lights; i++)
280   {
281     rdp.light[i].r = (float)(((wxUint8*)gfx.DMEM)[(a+0)^3]) / 255.0f;
282     rdp.light[i].g = (float)(((wxUint8*)gfx.DMEM)[(a+1)^3]) / 255.0f;
283     rdp.light[i].b = (float)(((wxUint8*)gfx.DMEM)[(a+2)^3]) / 255.0f;
284     rdp.light[i].a = 1.0f;
285     rdp.light[i].dir_x = (float)(((char*)gfx.DMEM)[(a+8)^3]) / 127.0f;
286     rdp.light[i].dir_y = (float)(((char*)gfx.DMEM)[(a+9)^3]) / 127.0f;
287     rdp.light[i].dir_z = (float)(((char*)gfx.DMEM)[(a+10)^3]) / 127.0f;
288     FRDP ("light: n: %d, r: %.3f, g: %.3f, b: %.3f, x: %.3f, y: %.3f, z: %.3f\n",
289       i, rdp.light[i].r, rdp.light[i].g, rdp.light[i].b,
290       rdp.light[i].dir_x, rdp.light[i].dir_y, rdp.light[i].dir_z);
291 //    TransformVector(&rdp.light[i].dir_x, rdp.light_vector[i], *m);
292     InverseTransformVector(&rdp.light[i].dir_x, rdp.light_vector[i], *m);
293     NormalizeVector (rdp.light_vector[i]);
294     FRDP ("light vector: n: %d, x: %.3f, y: %.3f, z: %.3f\n",
295       i, rdp.light_vector[i][0], rdp.light_vector[i][1], rdp.light_vector[i][2]);
296     a += 24;
297   }
298   for (i = 0; i < 2; i++)
299   {
300     float dir_x = (float)(((char*)gfx.DMEM)[(a+8)^3]) / 127.0f;
301     float dir_y = (float)(((char*)gfx.DMEM)[(a+9)^3]) / 127.0f;
302     float dir_z = (float)(((char*)gfx.DMEM)[(a+10)^3]) / 127.0f;
303     if (sqrt(dir_x*dir_x + dir_y*dir_y + dir_z*dir_z) < 0.98)
304     {
305       rdp.use_lookat = FALSE;
306       return;
307     }
308     rdp.lookat[i][0] = dir_x;
309     rdp.lookat[i][1] = dir_y;
310     rdp.lookat[i][2] = dir_z;
311     a += 24;
312   }
313   rdp.use_lookat = TRUE;
314 }
315
316 static void uc9_light ()
317 {
318   wxUint32 csrs = -1024 + ((rdp.cmd0>>12)&0xFFF);
319   wxUint32 nsrs = -1024 + (rdp.cmd0&0xFFF);
320   wxUint32 num = 1 + ((rdp.cmd1>>24)&0xFF);
321   wxUint32 cdest = -1024 + ((rdp.cmd1>>12)&0xFFF);
322   wxUint32 tdest = -1024 + (rdp.cmd1&0xFFF);
323   int use_material = (csrs != 0x0ff0);
324   tdest >>= 1;
325   FRDP ("uc9:light n: %d, colsrs: %04lx, normales: %04lx, coldst: %04lx, texdst: %04lx\n", num, csrs, nsrs, cdest, tdest);
326   VERTEX v;
327   for (wxUint32 i = 0; i < num; i++)
328   {
329     v.vec[0] = ((char*)gfx.DMEM)[(nsrs++)^3];
330     v.vec[1] = ((char*)gfx.DMEM)[(nsrs++)^3];
331     v.vec[2] = ((char*)gfx.DMEM)[(nsrs++)^3];
332     calc_sphere (&v);
333 //    calc_linear (&v);
334     NormalizeVector (v.vec);
335     calc_light (&v);
336     v.a = 0xFF;
337     if (use_material)
338     {
339       v.r = (wxUint8)(((wxUint32)v.r * gfx.DMEM[(csrs++)^3])>>8);
340       v.g = (wxUint8)(((wxUint32)v.g * gfx.DMEM[(csrs++)^3])>>8);
341       v.b = (wxUint8)(((wxUint32)v.b * gfx.DMEM[(csrs++)^3])>>8);
342       v.a = gfx.DMEM[(csrs++)^3];
343     }
344     gfx.DMEM[(cdest++)^3] = v.r;
345     gfx.DMEM[(cdest++)^3] = v.g;
346     gfx.DMEM[(cdest++)^3] = v.b;
347     gfx.DMEM[(cdest++)^3] = v.a;
348     ((short*)gfx.DMEM)[(tdest++)^1] = (short)v.ou;
349     ((short*)gfx.DMEM)[(tdest++)^1] = (short)v.ov;
350   }
351 }
352
353 static void uc9_mtxtrnsp ()
354 {
355   LRDP("uc9:mtxtrnsp - ignored\n");
356   /*
357   LRDP("uc9:mtxtrnsp ");
358   M44 *s;
359   switch (rdp.cmd1&0xF) {
360   case 4:
361     s = (M44*)rdp.model;
362     LRDP("Model\n");
363     break;
364   case 6:
365     s = (M44*)rdp.proj;
366     LRDP("Proj\n");
367     break;
368   case 8:
369     s = (M44*)rdp.combined;
370     LRDP("Comb\n");
371     break;
372   }
373   float m = *s[1][0];
374   *s[1][0] = *s[0][1];
375   *s[0][1] = m;
376   m = *s[2][0];
377   *s[2][0] = *s[0][2];
378   *s[0][2] = m;
379   m = *s[2][1];
380   *s[2][1] = *s[1][2];
381   *s[1][2] = m;
382   */
383 }
384
385 static void uc9_mtxcat ()
386 {
387   LRDP("uc9:mtxcat ");
388   M44 *s = NULL;
389   M44 *t = NULL;
390   wxUint32 S = rdp.cmd0&0xF;
391   wxUint32 T = (rdp.cmd1>>16)&0xF;
392   wxUint32 D = rdp.cmd1&0xF;
393   switch (S) {
394   case 4:
395     s = (M44*)rdp.model;
396     LRDP("Model * ");
397     break;
398   case 6:
399     s = (M44*)rdp.proj;
400     LRDP("Proj * ");
401     break;
402   case 8:
403     s = (M44*)rdp.combined;
404     LRDP("Comb * ");
405     break;
406   }
407   switch (T) {
408   case 4:
409     t = (M44*)rdp.model;
410     LRDP("Model -> ");
411     break;
412   case 6:
413     t = (M44*)rdp.proj;
414     LRDP("Proj -> ");
415     break;
416   case 8:
417     LRDP("Comb -> ");
418     t = (M44*)rdp.combined;
419     break;
420   }
421   DECLAREALIGN16VAR(m[4][4]);
422   MulMatrices(*s, *t, m);
423
424   switch (D) {
425   case 4:
426     memcpy (rdp.model, m, 64);;
427     LRDP("Model\n");
428     break;
429   case 6:
430     memcpy (rdp.proj, m, 64);;
431     LRDP("Proj\n");
432     break;
433   case 8:
434     memcpy (rdp.combined, m, 64);;
435     LRDP("Comb\n");
436     break;
437   }
438 #ifdef EXTREME_LOGGING
439   FRDP ("\nmodel\n{%f,%f,%f,%f}\n", rdp.model[0][0], rdp.model[0][1], rdp.model[0][2], rdp.model[0][3]);
440   FRDP ("{%f,%f,%f,%f}\n", rdp.model[1][0], rdp.model[1][1], rdp.model[1][2], rdp.model[1][3]);
441   FRDP ("{%f,%f,%f,%f}\n", rdp.model[2][0], rdp.model[2][1], rdp.model[2][2], rdp.model[2][3]);
442   FRDP ("{%f,%f,%f,%f}\n", rdp.model[3][0], rdp.model[3][1], rdp.model[3][2], rdp.model[3][3]);
443   FRDP ("\nproj\n{%f,%f,%f,%f}\n", rdp.proj[0][0], rdp.proj[0][1], rdp.proj[0][2], rdp.proj[0][3]);
444   FRDP ("{%f,%f,%f,%f}\n", rdp.proj[1][0], rdp.proj[1][1], rdp.proj[1][2], rdp.proj[1][3]);
445   FRDP ("{%f,%f,%f,%f}\n", rdp.proj[2][0], rdp.proj[2][1], rdp.proj[2][2], rdp.proj[2][3]);
446   FRDP ("{%f,%f,%f,%f}\n", rdp.proj[3][0], rdp.proj[3][1], rdp.proj[3][2], rdp.proj[3][3]);
447   FRDP ("\ncombined\n{%f,%f,%f,%f}\n", rdp.combined[0][0], rdp.combined[0][1], rdp.combined[0][2], rdp.combined[0][3]);
448   FRDP ("{%f,%f,%f,%f}\n", rdp.combined[1][0], rdp.combined[1][1], rdp.combined[1][2], rdp.combined[1][3]);
449   FRDP ("{%f,%f,%f,%f}\n", rdp.combined[2][0], rdp.combined[2][1], rdp.combined[2][2], rdp.combined[2][3]);
450   FRDP ("{%f,%f,%f,%f}\n", rdp.combined[3][0], rdp.combined[3][1], rdp.combined[3][2], rdp.combined[3][3]);
451 #endif
452 }
453
454 typedef struct  {
455   short sy;
456   short sx;
457   int   invw;
458   short yi;
459   short xi;
460   short wi;
461   wxUint8 fog;
462   wxUint8 cc;
463 } zSortVDest;
464
465 static void uc9_mult_mpmtx ()
466 {
467   //int id = rdp.cmd0&0xFF;
468   int num = 1+ ((rdp.cmd1>>24)&0xFF);
469   int src = -1024 + ((rdp.cmd1>>12)&0xFFF);
470   int dst = -1024 + (rdp.cmd1&0xFFF);
471   FRDP ("uc9:mult_mpmtx from: %04lx  to: %04lx n: %d\n", src, dst, num);
472   short * saddr = (short*)(gfx.DMEM+src);
473   zSortVDest * daddr = (zSortVDest*)(gfx.DMEM+dst);
474   int idx = 0;
475   zSortVDest v;
476   memset(&v, 0, sizeof(zSortVDest));
477   //float scale_x = 4.0f/rdp.scale_x;
478   //float scale_y = 4.0f/rdp.scale_y;
479   for (int i = 0; i < num; i++)
480   {
481     short sx   = saddr[(idx++)^1];
482     short sy   = saddr[(idx++)^1];
483     short sz   = saddr[(idx++)^1];
484     float x = sx*rdp.combined[0][0] + sy*rdp.combined[1][0] + sz*rdp.combined[2][0] + rdp.combined[3][0];
485     float y = sx*rdp.combined[0][1] + sy*rdp.combined[1][1] + sz*rdp.combined[2][1] + rdp.combined[3][1];
486     float z = sx*rdp.combined[0][2] + sy*rdp.combined[1][2] + sz*rdp.combined[2][2] + rdp.combined[3][2];
487     float w = sx*rdp.combined[0][3] + sy*rdp.combined[1][3] + sz*rdp.combined[2][3] + rdp.combined[3][3];
488     v.sx = (short)(zSortRdp.view_trans[0] + x / w * zSortRdp.view_scale[0]);
489     v.sy = (short)(zSortRdp.view_trans[1] + y / w * zSortRdp.view_scale[1]);
490
491     v.xi = (short)x;
492     v.yi = (short)y;
493     v.wi = (short)w;
494     v.invw = Calc_invw((int)(w * 31.0));
495
496     if (w < 0.0f)
497       v.fog = 0;
498     else
499     {
500       int fog = (int)(z / w * rdp.fog_multiplier + rdp.fog_offset);
501       if (fog > 255)
502         fog = 255;
503       v.fog = (fog >= 0) ? (wxUint8)fog : 0;
504     }
505
506     v.cc = 0;
507     if (x < -w) v.cc |= 0x10;
508     if (x > w) v.cc |= 0x01;
509     if (y < -w) v.cc |= 0x20;
510     if (y > w) v.cc |= 0x02;
511     if (w < 0.1f) v.cc |= 0x04;
512
513     daddr[i] = v;
514     //memcpy(gfx.DMEM+dst+sizeof(zSortVDest)*i, &v, sizeof(zSortVDest));
515 //    FRDP("v%d x: %d, y: %d, z: %d -> sx: %d, sy: %d, w: %d, xi: %d, yi: %d, wi: %d, fog: %d\n", i, sx, sy, sz, v.sx, v.sy, v.invw, v.xi, v.yi, v.wi, v.fog);
516     FRDP("v%d x: %d, y: %d, z: %d -> sx: %04lx, sy: %04lx, invw: %08lx - %f, xi: %04lx, yi: %04lx, wi: %04lx, fog: %04lx\n", i, sx, sy, sz, v.sx, v.sy, v.invw, w, v.xi, v.yi, v.wi, v.fog);
517   }
518 }
519
520 static void uc9_link_subdl ()
521 {
522   LRDP("uc9:link_subdl IGNORED\n");
523 }
524
525 static void uc9_set_subdl ()
526 {
527   LRDP("uc9:set_subdl IGNORED\n");
528 }
529
530 static void uc9_wait_signal ()
531 {
532   LRDP("uc9:wait_signal IGNORED\n");
533 }
534
535 static void uc9_send_signal ()
536 {
537   LRDP("uc9:send_signal IGNORED\n");
538 }
539
540 void uc9_movemem ()
541 {
542   LRDP("uc9:movemem\n");
543   int idx = rdp.cmd0 & 0x0E;
544   int ofs = ((rdp.cmd0>>6)&0x1ff)<<3;
545   int len = (1 + ((rdp.cmd0>>15)&0x1ff))<<3;
546   FRDP ("uc9:movemem ofs: %d, len: %d. ", ofs, len);
547   int flag = rdp.cmd0 & 0x01;
548   wxUint32 addr = segoffset(rdp.cmd1);
549   switch (idx)
550   {
551
552   case 0: //save/load
553     if (flag == 0)
554     {
555       int dmem_addr = (idx<<3) + ofs;
556       FRDP ("Load to DMEM. %08lx -> %08lx\n", addr, dmem_addr);
557       memcpy(gfx.DMEM + dmem_addr, gfx.RDRAM + addr, len);
558     }
559     else
560     {
561       int dmem_addr = (idx<<3) + ofs;
562       FRDP ("Load from DMEM. %08lx -> %08lx\n", dmem_addr, addr);
563       memcpy(gfx.RDRAM + addr, gfx.DMEM + dmem_addr, len);
564     }
565     break;
566
567   case 4:  // model matrix
568   case 6:  // projection matrix
569   case 8:  // combined matrix
570     {
571       DECLAREALIGN16VAR(m[4][4]);
572       load_matrix(m, addr);
573       switch (idx)
574       {
575       case 4:  // model matrix
576         LRDP("Modelview load\n");
577         modelview_load (m);
578         break;
579       case 6:  // projection matrix
580         LRDP("Projection load\n");
581         projection_load (m);
582         break;
583       case 8:  // projection matrix
584         LRDP("Combined load\n");
585         rdp.update &= ~UPDATE_MULT_MAT;
586         memcpy (rdp.combined, m, 64);;
587         break;
588       }
589 #ifdef EXTREME_LOGGING
590   FRDP ("{%f,%f,%f,%f}\n", m[0][0], m[0][1], m[0][2], m[0][3]);
591   FRDP ("{%f,%f,%f,%f}\n", m[1][0], m[1][1], m[1][2], m[1][3]);
592   FRDP ("{%f,%f,%f,%f}\n", m[2][0], m[2][1], m[2][2], m[2][3]);
593   FRDP ("{%f,%f,%f,%f}\n", m[3][0], m[3][1], m[3][2], m[3][3]);
594   FRDP ("\nmodel\n{%f,%f,%f,%f}\n", rdp.model[0][0], rdp.model[0][1], rdp.model[0][2], rdp.model[0][3]);
595   FRDP ("{%f,%f,%f,%f}\n", rdp.model[1][0], rdp.model[1][1], rdp.model[1][2], rdp.model[1][3]);
596   FRDP ("{%f,%f,%f,%f}\n", rdp.model[2][0], rdp.model[2][1], rdp.model[2][2], rdp.model[2][3]);
597   FRDP ("{%f,%f,%f,%f}\n", rdp.model[3][0], rdp.model[3][1], rdp.model[3][2], rdp.model[3][3]);
598   FRDP ("\nproj\n{%f,%f,%f,%f}\n", rdp.proj[0][0], rdp.proj[0][1], rdp.proj[0][2], rdp.proj[0][3]);
599   FRDP ("{%f,%f,%f,%f}\n", rdp.proj[1][0], rdp.proj[1][1], rdp.proj[1][2], rdp.proj[1][3]);
600   FRDP ("{%f,%f,%f,%f}\n", rdp.proj[2][0], rdp.proj[2][1], rdp.proj[2][2], rdp.proj[2][3]);
601   FRDP ("{%f,%f,%f,%f}\n", rdp.proj[3][0], rdp.proj[3][1], rdp.proj[3][2], rdp.proj[3][3]);
602 #endif
603     }
604     break;
605
606   case 10:
607     LRDP("Othermode - IGNORED\n");
608     break;
609
610   case 12:   // VIEWPORT
611     {
612       wxUint32 a = addr >> 1;
613       short scale_x = ((short*)gfx.RDRAM)[(a+0)^1] >> 2;
614       short scale_y = ((short*)gfx.RDRAM)[(a+1)^1] >> 2;
615       short scale_z = ((short*)gfx.RDRAM)[(a+2)^1];
616       rdp.fog_multiplier = ((short*)gfx.RDRAM)[(a+3)^1];
617       short trans_x = ((short*)gfx.RDRAM)[(a+4)^1] >> 2;
618       short trans_y = ((short*)gfx.RDRAM)[(a+5)^1] >> 2;
619       short trans_z = ((short*)gfx.RDRAM)[(a+6)^1];
620       rdp.fog_offset = ((short*)gfx.RDRAM)[(a+7)^1];
621       rdp.view_scale[0] = scale_x * rdp.scale_x;
622       rdp.view_scale[1] = scale_y * rdp.scale_y;
623       rdp.view_scale[2] = 32.0f * scale_z;
624       rdp.view_trans[0] = trans_x * rdp.scale_x;
625       rdp.view_trans[1] = trans_y * rdp.scale_y;
626       rdp.view_trans[2] = 32.0f * trans_z;
627       zSortRdp.view_scale[0] = (float)(scale_x*4);
628       zSortRdp.view_scale[1] = (float)(scale_y*4);
629       zSortRdp.view_trans[0] = (float)(trans_x*4);
630       zSortRdp.view_trans[1] = (float)(trans_y*4);
631       zSortRdp.scale_x = rdp.scale_x / 4.0f;
632       zSortRdp.scale_y = rdp.scale_y / 4.0f;
633
634       rdp.update |= UPDATE_VIEWPORT;
635
636       rdp.mipmap_level = 0;
637       rdp.cur_tile = 0;
638       TILE *tmp_tile = &rdp.tiles[0];
639       tmp_tile->on = 1;
640       tmp_tile->org_s_scale = 0xFFFF;
641       tmp_tile->org_t_scale = 0xFFFF;
642       tmp_tile->s_scale = 0.031250f;
643       tmp_tile->t_scale = 0.031250f;
644
645       rdp.geom_mode |= 0x0200;
646
647       FRDP ("viewport scale(%d, %d, %d), trans(%d, %d, %d), from:%08lx\n", scale_x, scale_y, scale_z,
648         trans_x, trans_y, trans_z, a);
649       FRDP ("fog: multiplier: %f, offset: %f\n", rdp.fog_multiplier, rdp.fog_offset);
650     }
651     break;
652
653   default:
654     FRDP ("** UNKNOWN %d\n", idx);
655   }
656
657 }
658
659 static void uc9_setscissor()
660 {
661   rdp_setscissor();
662
663   if ((rdp.scissor_o.lr_x - rdp.scissor_o.ul_x) > (zSortRdp.view_scale[0] - zSortRdp.view_trans[0]))
664   {
665     float w = (rdp.scissor_o.lr_x - rdp.scissor_o.ul_x) / 2.0f;
666     float h = (rdp.scissor_o.lr_y - rdp.scissor_o.ul_y) / 2.0f;
667     rdp.view_scale[0] = w * rdp.scale_x;
668     rdp.view_scale[1] = h * rdp.scale_y;
669     rdp.view_trans[0] = w * rdp.scale_x;
670     rdp.view_trans[1] = h * rdp.scale_y;
671     zSortRdp.view_scale[0] = w * 4.0f;
672     zSortRdp.view_scale[1] = h * 4.0f;
673     zSortRdp.view_trans[0] = w * 4.0f;
674     zSortRdp.view_trans[1] = h * 4.0f;
675     zSortRdp.scale_x = rdp.scale_x / 4.0f;
676     zSortRdp.scale_y = rdp.scale_y / 4.0f;
677     rdp.update |= UPDATE_VIEWPORT;
678
679     rdp.mipmap_level = 0;
680     rdp.cur_tile = 0;
681     TILE *tmp_tile = &rdp.tiles[0];
682     tmp_tile->on = 1;
683     tmp_tile->org_s_scale = 0xFFFF;
684     tmp_tile->org_t_scale = 0xFFFF;
685     tmp_tile->s_scale = 0.031250f;
686     tmp_tile->t_scale = 0.031250f;
687
688     rdp.geom_mode |= 0x0200;
689   }
690 }