Glide Plugin GLES2 port from mupen64plus-ae, but with special FrameSkip code
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glide64 / ucode05.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 int cur_mtx = 0;
41 int billboarding = 0;
42 int vtx_last = 0;
43 wxUint32 dma_offset_mtx = 0;
44 wxUint32 dma_offset_vtx = 0;
45
46 static void uc5_dma_offsets ()
47 {
48   dma_offset_mtx = rdp.cmd0 & 0x00FFFFFF;
49   dma_offset_vtx = rdp.cmd1 & 0x00FFFFFF;
50   vtx_last = 0;
51   FRDP("uc5:dma_offsets - mtx: %08lx, vtx: %08lx\n", dma_offset_mtx, dma_offset_vtx);
52 }
53
54 static void uc5_matrix ()
55 {
56   // Use segment offset to get the address
57   wxUint32 addr = dma_offset_mtx + (segoffset(rdp.cmd1) & BMASK);
58
59   wxUint8 n = (wxUint8)((rdp.cmd0 >> 16) & 0xF);
60   wxUint8 multiply;
61
62   if (n == 0) //DKR
63   {
64     n = (wxUint8)((rdp.cmd0 >> 22) & 0x3);
65     multiply = 0;
66   }
67   else //JF
68   {
69     multiply = (wxUint8)((rdp.cmd0 >> 23) & 0x1);
70   }
71
72   cur_mtx = n;
73
74   FRDP("uc5:matrix - #%d, addr: %08lx\n", n, addr);
75
76   if (multiply)
77   {
78     DECLAREALIGN16VAR(m[4][4]);
79     load_matrix(m, addr);
80     DECLAREALIGN16VAR(m_src[4][4]);
81     memcpy (m_src, rdp.dkrproj[0], 64);
82     MulMatrices(m, m_src, rdp.dkrproj[n]);
83   }
84   else
85   {
86     load_matrix(rdp.dkrproj[n], addr);
87   }
88   rdp.update |= UPDATE_MULT_MAT;
89
90 #ifdef EXTREME_LOGGING
91   FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[n][0][0], rdp.dkrproj[n][0][1], rdp.dkrproj[n][0][2], rdp.dkrproj[n][0][3]);
92   FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[n][1][0], rdp.dkrproj[n][1][1], rdp.dkrproj[n][1][2], rdp.dkrproj[n][1][3]);
93   FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[n][2][0], rdp.dkrproj[n][2][1], rdp.dkrproj[n][2][2], rdp.dkrproj[n][2][3]);
94   FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[n][3][0], rdp.dkrproj[n][3][1], rdp.dkrproj[n][3][2], rdp.dkrproj[n][3][3]);
95
96   for (int i=0; i<3; i++)
97   {
98     FRDP ("proj %d\n", i);
99     FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[i][0][0], rdp.dkrproj[i][0][1], rdp.dkrproj[i][0][2], rdp.dkrproj[i][0][3]);
100     FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[i][1][0], rdp.dkrproj[i][1][1], rdp.dkrproj[i][1][2], rdp.dkrproj[i][1][3]);
101     FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[i][2][0], rdp.dkrproj[i][2][1], rdp.dkrproj[i][2][2], rdp.dkrproj[i][2][3]);
102     FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[i][3][0], rdp.dkrproj[i][3][1], rdp.dkrproj[i][3][2], rdp.dkrproj[i][3][3]);
103   }
104 #endif
105 }
106
107 static void uc5_vertex ()
108 {
109 Check_FrameSkip;
110
111   wxUint32 addr = dma_offset_vtx + (segoffset(rdp.cmd1) & BMASK);
112
113   // | cccc cccc 1111 1??? 0000 0002 2222 2222 | cmd1 = address |
114   // c = vtx command
115   // 1 = method #1 of getting count
116   // 2 = method #2 of getting count
117   // ? = unknown, but used
118   // 0 = unused
119
120   int n = ((rdp.cmd0 >> 19) & 0x1F);// + 1;
121   if (settings.hacks&hack_Diddy)
122     n++;
123
124   if (rdp.cmd0 & 0x00010000)
125   {
126     if (billboarding)
127       vtx_last = 1;
128   }
129   else
130     vtx_last = 0;
131
132   int first = ((rdp.cmd0 >> 9) & 0x1F) + vtx_last;
133   FRDP ("uc5:vertex - addr: %08lx, first: %d, count: %d, matrix: %08lx\n", addr, first, n, cur_mtx);
134
135   int prj = cur_mtx;
136
137   int start = 0;
138   float x, y, z;
139   for (int i=first; i<first+n; i++)
140   {
141     start = (i-first) * 10;
142     VERTEX *v = &rdp.vtx[i];
143     x   = (float)((short*)gfx.RDRAM)[(((addr+start) >> 1) + 0)^1];
144     y   = (float)((short*)gfx.RDRAM)[(((addr+start) >> 1) + 1)^1];
145     z   = (float)((short*)gfx.RDRAM)[(((addr+start) >> 1) + 2)^1];
146
147     v->x = x*rdp.dkrproj[prj][0][0] + y*rdp.dkrproj[prj][1][0] + z*rdp.dkrproj[prj][2][0] + rdp.dkrproj[prj][3][0];
148     v->y = x*rdp.dkrproj[prj][0][1] + y*rdp.dkrproj[prj][1][1] + z*rdp.dkrproj[prj][2][1] + rdp.dkrproj[prj][3][1];
149     v->z = x*rdp.dkrproj[prj][0][2] + y*rdp.dkrproj[prj][1][2] + z*rdp.dkrproj[prj][2][2] + rdp.dkrproj[prj][3][2];
150     v->w = x*rdp.dkrproj[prj][0][3] + y*rdp.dkrproj[prj][1][3] + z*rdp.dkrproj[prj][2][3] + rdp.dkrproj[prj][3][3];
151
152     if (billboarding)
153     {
154       v->x += rdp.vtx[0].x;
155       v->y += rdp.vtx[0].y;
156       v->z += rdp.vtx[0].z;
157       v->w += rdp.vtx[0].w;
158     }
159
160     if (fabs(v->w) < 0.001) v->w = 0.001f;
161     v->oow = 1.0f / v->w;
162     v->x_w = v->x * v->oow;
163     v->y_w = v->y * v->oow;
164     v->z_w = v->z * v->oow;
165
166     v->uv_calculated = 0xFFFFFFFF;
167     v->screen_translated = 0;
168     v->shade_mod = 0;
169
170     v->scr_off = 0;
171     if (v->x < -v->w) v->scr_off |= 1;
172     if (v->x > v->w) v->scr_off |= 2;
173     if (v->y < -v->w) v->scr_off |= 4;
174     if (v->y > v->w) v->scr_off |= 8;
175     if (v->w < 0.1f) v->scr_off |= 16;
176     if (fabs(v->z_w) > 1.0) v->scr_off |= 32;
177
178     v->r = ((wxUint8*)gfx.RDRAM)[(addr+start + 6)^3];
179     v->g = ((wxUint8*)gfx.RDRAM)[(addr+start + 7)^3];
180     v->b = ((wxUint8*)gfx.RDRAM)[(addr+start + 8)^3];
181     v->a = ((wxUint8*)gfx.RDRAM)[(addr+start + 9)^3];
182     CalculateFog (v);
183
184 #ifdef EXTREME_LOGGING
185     FRDP ("v%d - x: %f, y: %f, z: %f, w: %f, z_w: %f, r=%d, g=%d, b=%d, a=%d\n", i, v->x, v->y, v->z, v->w, v->z_w, v->r, v->g, v->b, v->a);
186 #endif
187   }
188
189   vtx_last += n;
190 }
191
192 static void uc5_tridma ()
193 {
194 Check_FrameSkip;
195
196   vtx_last = 0;    // we've drawn something, so the vertex index needs resetting
197   if (rdp.skip_drawing)
198     return;
199
200   // | cccc cccc 2222 0000 1111 1111 1111 0000 | cmd1 = address |
201   // c = tridma command
202   // 1 = method #1 of getting count
203   // 2 = method #2 of getting count
204   // 0 = unused
205
206   wxUint32 addr = segoffset(rdp.cmd1) & BMASK;
207   int num = (rdp.cmd0 & 0xFFF0) >> 4;
208   //int num = ((rdp.cmd0 & 0x00F00000) >> 20) + 1;  // same thing!
209   FRDP("uc5:tridma #%d - addr: %08lx, count: %d\n", rdp.tri_n, addr, num);
210
211   int start, v0, v1, v2, flags;
212   for (int i=0; i<num; i++)
213   {
214     start = i << 4;
215     v0 = gfx.RDRAM[addr+start];
216     v1 = gfx.RDRAM[addr+start+1];
217     v2 = gfx.RDRAM[addr+start+2];
218
219     FRDP("tri #%d - %d, %d, %d\n", rdp.tri_n, v0, v1, v2);
220
221     VERTEX *v[3] = {
222       &rdp.vtx[v0],
223         &rdp.vtx[v1],
224         &rdp.vtx[v2]
225     };
226
227     flags = gfx.RDRAM[addr+start+3];
228
229     if (flags & 0x40) { // no cull
230       rdp.flags &= ~CULLMASK;
231       grCullMode (GR_CULL_DISABLE);
232     }
233     else {        // front cull
234       rdp.flags &= ~CULLMASK;
235       if (rdp.view_scale[0] < 0) {
236         rdp.flags |= CULL_BACK;   // agh, backwards culling
237         grCullMode (GR_CULL_POSITIVE);
238       }
239       else {
240         rdp.flags |= CULL_FRONT;
241         grCullMode (GR_CULL_NEGATIVE);
242       }
243     }
244     start += 4;
245
246     v[0]->ou = (float)((short*)gfx.RDRAM)[((addr+start) >> 1) + 5] / 32.0f;
247     v[0]->ov = (float)((short*)gfx.RDRAM)[((addr+start) >> 1) + 4] / 32.0f;
248     v[1]->ou = (float)((short*)gfx.RDRAM)[((addr+start) >> 1) + 3] / 32.0f;
249     v[1]->ov = (float)((short*)gfx.RDRAM)[((addr+start) >> 1) + 2] / 32.0f;
250     v[2]->ou = (float)((short*)gfx.RDRAM)[((addr+start) >> 1) + 1] / 32.0f;
251     v[2]->ov = (float)((short*)gfx.RDRAM)[((addr+start) >> 1) + 0] / 32.0f;
252
253     v[0]->uv_calculated = 0xFFFFFFFF;
254     v[1]->uv_calculated = 0xFFFFFFFF;
255     v[2]->uv_calculated = 0xFFFFFFFF;
256
257     if (cull_tri(v))
258       rdp.tri_n ++;
259     else
260     {
261       update ();
262
263       draw_tri (v);
264       rdp.tri_n ++;
265     }
266   }
267 }
268
269 static void uc5_dl_in_mem ()
270 {
271   wxUint32 addr = segoffset(rdp.cmd1) & BMASK;
272   int count = (rdp.cmd0 & 0x00FF0000) >> 16;
273   FRDP ("uc5:dl_in_mem - addr: %08lx, count: %d\n", addr, count);
274
275   if (rdp.pc_i >= 9) {
276     RDP_E ("** DL stack overflow **\n");
277     LRDP("** DL stack overflow **\n");
278     return;
279   }
280   rdp.pc_i ++;  // go to the next PC in the stack
281   rdp.pc[rdp.pc_i] = addr;  // jump to the address
282   rdp.dl_count = count + 1;
283 }
284
285 static void uc5_moveword()
286 {
287   LRDP("uc5:moveword ");
288
289   // Find which command this is (lowest byte of cmd0)
290   switch (rdp.cmd0 & 0xFF)
291   {
292   case 0x02:  // moveword matrix 2 billboard
293     billboarding = (rdp.cmd1 & 1);
294     FRDP ("matrix billboard - %s\n", str_offon[billboarding]);
295     break;
296
297   case 0x04:  // clip (verified same)
298     if (((rdp.cmd0>>8)&0xFFFF) == 0x04)
299     {
300       rdp.clip_ratio = sqrt((float)rdp.cmd1);
301       rdp.update |= UPDATE_VIEWPORT;
302     }
303     FRDP ("clip %08lx, %08lx\n", rdp.cmd0, rdp.cmd1);
304     break;
305
306   case 0x06:  // segment (verified same)
307     FRDP ("segment: %08lx -> seg%d\n", rdp.cmd1, (rdp.cmd0 >> 10) & 0x0F);
308     rdp.segment[(rdp.cmd0 >> 10) & 0x0F] = rdp.cmd1;
309     break;
310
311   case 0x08:
312     {
313       rdp.fog_multiplier = (short)(rdp.cmd1 >> 16);
314       rdp.fog_offset = (short)(rdp.cmd1 & 0x0000FFFF);
315       FRDP ("fog: multiplier: %f, offset: %f\n", rdp.fog_multiplier, rdp.fog_offset);
316       //          rdp.update |= UPDATE_FOG_ENABLED;
317     }
318     break;
319
320   case 0x0a:  // moveword matrix select
321     cur_mtx = (rdp.cmd1 >> 6) & 3;
322     FRDP ("matrix select - mtx: %d\n", cur_mtx);
323     break;
324
325   default:
326     FRDP ("(unknown) %02lx - IGNORED\n", rdp.cmd0&0xFF);
327   }
328 }
329
330 static void uc5_setgeometrymode()
331 {
332   FRDP("uc0:setgeometrymode %08lx\n", rdp.cmd1);
333
334   rdp.geom_mode |= rdp.cmd1;
335
336   if (rdp.cmd1 & 0x00000001)  // Z-Buffer enable
337   {
338     if (!(rdp.flags & ZBUF_ENABLED))
339     {
340       rdp.flags |= ZBUF_ENABLED;
341       rdp.update |= UPDATE_ZBUF_ENABLED;
342     }
343   }
344
345   //Added by Gonetz
346   if (rdp.cmd1 & 0x00010000)      // Fog enable
347   {
348     if (!(rdp.flags & FOG_ENABLED))
349     {
350       rdp.flags |= FOG_ENABLED;
351       rdp.update |= UPDATE_FOG_ENABLED;
352     }
353   }
354 }
355
356 static void uc5_cleargeometrymode()
357 {
358   FRDP("uc0:cleargeometrymode %08lx\n", rdp.cmd1);
359
360   rdp.geom_mode &= (~rdp.cmd1);
361
362   if (rdp.cmd1 & 0x00000001)  // Z-Buffer enable
363   {
364     if (rdp.flags & ZBUF_ENABLED)
365     {
366       rdp.flags ^= ZBUF_ENABLED;
367       rdp.update |= UPDATE_ZBUF_ENABLED;
368     }
369   }
370   //Added by Gonetz
371   if (rdp.cmd1 & 0x00010000)      // Fog enable
372   {
373     if (rdp.flags & FOG_ENABLED)
374     {
375       rdp.flags ^= FOG_ENABLED;
376       rdp.update |= UPDATE_FOG_ENABLED;
377     }
378   }
379 }