Glide Plugin GLES2 port from mupen64plus-ae, but with special FrameSkip code
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glide64 / Util.cpp
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 #include <math.h>
41 #include "Gfx_1.3.h"
42 #include "Util.h"
43 #include "Combine.h"
44 #include "3dmath.h"
45 #include "Debugger.h"
46 #include "TexCache.h"
47 #include "DepthBufferRender.h"
48
49 #define Vj rdp.vtxbuf2[j]
50 #define Vi rdp.vtxbuf2[i]
51
52 VERTEX *vtx_list1[32];  // vertex indexing
53 VERTEX *vtx_list2[32];
54
55 //
56 // util_init - initialize data for the functions in this file
57 //
58
59 void util_init ()
60 {
61   for (int i=0; i<32; i++)
62   {
63     vtx_list1[i] = &rdp.vtx1[i];
64     vtx_list2[i] = &rdp.vtx2[i];
65   }
66 }
67
68 static wxUint32 u_cull_mode = 0;
69
70 //software backface culling. Gonetz
71 // mega modifications by Dave2001
72 int cull_tri(VERTEX **v) // type changed to VERTEX** [Dave2001]
73 {
74   int i;
75
76   if (v[0]->scr_off & v[1]->scr_off & v[2]->scr_off)
77   {
78     LRDP (" clipped\n");
79     return TRUE;
80   }
81
82   // Triangle can't be culled, if it need clipping
83   int draw = FALSE;
84
85   for (i=0; i<3; i++)
86   {
87     if (!v[i]->screen_translated)
88     {
89       v[i]->sx = rdp.view_trans[0] + v[i]->x_w * rdp.view_scale[0] + rdp.offset_x;
90       v[i]->sy = rdp.view_trans[1] + v[i]->y_w * rdp.view_scale[1] + rdp.offset_y;
91       v[i]->sz = rdp.view_trans[2] + v[i]->z_w * rdp.view_scale[2];
92       v[i]->screen_translated = 1;
93     }
94     if (v[i]->w < 0.01f) //need clip_z. can't be culled now
95       draw = 1;
96   }
97
98   u_cull_mode = (rdp.flags & CULLMASK);
99   if (draw || u_cull_mode == 0 || u_cull_mode == CULLMASK) //no culling set
100   {
101     u_cull_mode >>= CULLSHIFT;
102     return FALSE;
103   }
104
105 #define SW_CULLING
106 #ifdef SW_CULLING
107 #if 1 // H.Morii - faster float comparisons with zero area check added
108
109   const float x1 = v[0]->sx - v[1]->sx;
110   const float y1 = v[0]->sy - v[1]->sy;
111   const float x2 = v[2]->sx - v[1]->sx;
112   const float y2 = v[2]->sy - v[1]->sy;
113   const float area = y1*x2 - x1*y2;
114
115   const int iarea = *(int*)&area;
116   const unsigned int mode = (u_cull_mode << 19UL);
117   u_cull_mode >>= CULLSHIFT;
118
119   if ((iarea & 0x7FFFFFFF) == 0)
120   {
121           LRDP (" zero area triangles\n");
122       return TRUE;
123   }
124
125   if ((rdp.flags & CULLMASK) && ((int)(iarea ^ mode)) >= 0)
126   {
127           LRDP (" culled\n");
128       return TRUE;
129   }
130 #else
131
132   float x1 = v[0]->sx - v[1]->sx;
133   float y1 = v[0]->sy - v[1]->sy;
134   float x2 = v[2]->sx - v[1]->sx;
135   float y2 = v[2]->sy - v[1]->sy;
136
137   u_cull_mode >>= CULLSHIFT;
138   switch (u_cull_mode)
139   {
140   case 1: // cull front
141     //    if ((x1*y2 - y1*x2) < 0.0f) //counter-clockwise, positive
142     if ((y1*x2-x1*y2) < 0.0f) //counter-clockwise, positive
143     {
144       LRDP (" culled!\n");
145       return TRUE;
146     }
147     return FALSE;
148   case 2: // cull back
149     //    if ((x1*y2 - y1*x2) >= 0.0f) //clockwise, negative
150     if ((y1*x2-x1*y2) >= 0.0f) //clockwise, negative
151     {
152       LRDP (" culled!\n");
153       return TRUE;
154     }
155     return FALSE;
156   }
157 #endif
158 #endif
159
160   return FALSE;
161 }
162
163
164 void apply_shade_mods (VERTEX *v)
165 {
166   float col[4];
167   wxUint32 mod;
168   memcpy (col, rdp.col, 16);
169
170   if (rdp.cmb_flags)
171   {
172     if (v->shade_mod == 0)
173       v->color_backup = *(wxUint32*)(&(v->b));
174     else
175       *(wxUint32*)(&(v->b)) = v->color_backup;
176     mod = rdp.cmb_flags;
177     if (mod & CMB_SET)
178     {
179       if (col[0] > 1.0f) col[0] = 1.0f;
180       if (col[1] > 1.0f) col[1] = 1.0f;
181       if (col[2] > 1.0f) col[2] = 1.0f;
182       if (col[0] < 0.0f) col[0] = 0.0f;
183       if (col[1] < 0.0f) col[1] = 0.0f;
184       if (col[2] < 0.0f) col[2] = 0.0f;
185       v->r = (wxUint8)(255.0f * col[0]);
186       v->g = (wxUint8)(255.0f * col[1]);
187       v->b = (wxUint8)(255.0f * col[2]);
188     }
189     if (mod & CMB_A_SET)
190     {
191       if (col[3] > 1.0f) col[3] = 1.0f;
192       if (col[3] < 0.0f) col[3] = 0.0f;
193       v->a = (wxUint8)(255.0f * col[3]);
194     }
195     if (mod & CMB_SETSHADE_SHADEALPHA)
196     {
197       v->r = v->g = v->b = v->a;
198     }
199     if (mod & CMB_MULT_OWN_ALPHA)
200     {
201       float percent = v->a / 255.0f;
202       v->r = (wxUint8)(v->r * percent);
203       v->g = (wxUint8)(v->g * percent);
204       v->b = (wxUint8)(v->b * percent);
205     }
206     if (mod & CMB_MULT)
207     {
208       if (col[0] > 1.0f) col[0] = 1.0f;
209       if (col[1] > 1.0f) col[1] = 1.0f;
210       if (col[2] > 1.0f) col[2] = 1.0f;
211       if (col[0] < 0.0f) col[0] = 0.0f;
212       if (col[1] < 0.0f) col[1] = 0.0f;
213       if (col[2] < 0.0f) col[2] = 0.0f;
214       v->r = (wxUint8)(v->r * col[0]);
215       v->g = (wxUint8)(v->g * col[1]);
216       v->b = (wxUint8)(v->b * col[2]);
217     }
218     if (mod & CMB_A_MULT)
219     {
220       if (col[3] > 1.0f) col[3] = 1.0f;
221       if (col[3] < 0.0f) col[3] = 0.0f;
222       v->a = (wxUint8)(v->a * col[3]);
223     }
224     if (mod & CMB_SUB)
225     {
226       int r = v->r - (int)(255.0f * rdp.coladd[0]);
227       int g = v->g - (int)(255.0f * rdp.coladd[1]);
228       int b = v->b - (int)(255.0f * rdp.coladd[2]);
229       if (r < 0) r = 0;
230       if (g < 0) g = 0;
231       if (b < 0) b = 0;
232       v->r = (wxUint8)r;
233       v->g = (wxUint8)g;
234       v->b = (wxUint8)b;
235     }
236     if (mod & CMB_A_SUB)
237     {
238                     int a = v->a - (int)(255.0f * rdp.coladd[3]);
239         if (a < 0) a = 0;
240         v->a = (wxUint8)a;
241     }
242     if (mod & CMB_ADD)
243     {
244       int r = v->r + (int)(255.0f * rdp.coladd[0]);
245       int g = v->g + (int)(255.0f * rdp.coladd[1]);
246       int b = v->b + (int)(255.0f * rdp.coladd[2]);
247       if (r > 255) r = 255;
248       if (g > 255) g = 255;
249       if (b > 255) b = 255;
250       v->r = (wxUint8)r;
251       v->g = (wxUint8)g;
252       v->b = (wxUint8)b;
253     }
254     if (mod & CMB_A_ADD)
255     {
256                     int a = v->a + (int)(255.0f * rdp.coladd[3]);
257         if (a > 255) a = 255;
258         v->a = (wxUint8)a;
259     }
260     if (mod & CMB_COL_SUB_OWN)
261     {
262       int r = (wxUint8)(255.0f * rdp.coladd[0]) - v->r;
263       int g = (wxUint8)(255.0f * rdp.coladd[1]) - v->g;
264       int b = (wxUint8)(255.0f * rdp.coladd[2]) - v->b;
265       if (r < 0) r = 0;
266       if (g < 0) g = 0;
267       if (b < 0) b = 0;
268       v->r = (wxUint8)r;
269       v->g = (wxUint8)g;
270       v->b = (wxUint8)b;
271     }
272     v->shade_mod = cmb.shade_mod_hash;
273   }
274   if (rdp.cmb_flags_2 & CMB_INTER)
275   {
276     v->r = (wxUint8)(rdp.col_2[0] * rdp.shade_factor * 255.0f + v->r * (1.0f - rdp.shade_factor));
277     v->g = (wxUint8)(rdp.col_2[1] * rdp.shade_factor * 255.0f + v->g * (1.0f - rdp.shade_factor));
278     v->b = (wxUint8)(rdp.col_2[2] * rdp.shade_factor * 255.0f + v->b * (1.0f - rdp.shade_factor));
279     v->shade_mod = cmb.shade_mod_hash;
280   }
281 }
282
283 static int dzdx = 0;
284 static int deltaZ = 0;
285 VERTEX **org_vtx;
286
287 void draw_tri (VERTEX **vtx, wxUint16 linew)
288 {
289   deltaZ = dzdx = 0;
290   if (linew == 0 && (fb_depth_render_enabled || (rdp.rm & 0xC00) == 0xC00))
291   {
292     float X0 = vtx[0]->sx / rdp.scale_x;
293     float Y0 = vtx[0]->sy / rdp.scale_y;
294     float X1 = vtx[1]->sx / rdp.scale_x;
295     float Y1 = vtx[1]->sy / rdp.scale_y;
296     float X2 = vtx[2]->sx / rdp.scale_x;
297     float Y2 = vtx[2]->sy / rdp.scale_y;
298     float diffy_02 = Y0 - Y2;
299     float diffy_12 = Y1 - Y2;
300     float diffx_02 = X0 - X2;
301     float diffx_12 = X1 - X2;
302
303     float denom = (diffx_02 * diffy_12 - diffx_12 * diffy_02);
304     if(denom*denom > 0.0f)
305     {
306       float diffz_02 = vtx[0]->sz - vtx[2]->sz;
307       float diffz_12 = vtx[1]->sz - vtx[2]->sz;
308       float fdzdx = (diffz_02 * diffy_12 - diffz_12 * diffy_02) / denom;
309       if ((rdp.rm & 0xC00) == 0xC00) {
310         // Calculate deltaZ per polygon for Decal z-mode
311         float fdzdy = (diffz_02 * diffx_12 - diffz_12 * diffx_02) / denom;
312         float fdz = fabs(fdzdx) + fabs(fdzdy);
313         if ((settings.hacks & hack_Zelda) && (rdp.rm & 0x800))
314           fdz *= 4.0f;  // Decal mode in Zelda sometimes needs mutiplied deltaZ to work correct, e.g. roads
315         deltaZ = max(8, (int)fdz);
316       }
317       dzdx = (int)(fdzdx * 65536.0);
318     }
319   }
320
321   org_vtx = vtx;
322
323   for (int i=0; i<3; i++)
324   {
325     VERTEX *v = vtx[i];
326
327     if (v->uv_calculated != rdp.tex_ctr)
328     {
329 #ifdef EXTREME_LOGGING
330       FRDP(" * CALCULATING VERTEX U/V: %d\n", v->number);
331 #endif
332       v->uv_calculated = rdp.tex_ctr;
333
334       if (!(rdp.geom_mode & 0x00020000))
335       {
336         if (!(rdp.geom_mode & 0x00000200))
337         {
338           if (rdp.geom_mode & 0x00000004) // flat shading
339           {
340             int flag = min(2, (rdp.cmd1 >> 24) & 3);
341             v->a = vtx[flag]->a;
342             v->b = vtx[flag]->b;
343             v->g = vtx[flag]->g;
344             v->r = vtx[flag]->r;
345 #ifdef EXTREME_LOGGING
346             FRDP(" * Flat shaded, flag%d - r: %d, g: %d, b: %d, a: %d\n", flag, v->r, v->g, v->b, v->a);
347 #endif
348           }
349           else  // prim color
350           {
351 #ifdef EXTREME_LOGGING
352             FRDP(" * Prim shaded %08lx\n", rdp.prim_color);
353 #endif
354             v->a = (wxUint8)(rdp.prim_color & 0xFF);
355             v->b = (wxUint8)((rdp.prim_color >> 8) & 0xFF);
356             v->g = (wxUint8)((rdp.prim_color >> 16) & 0xFF);
357             v->r = (wxUint8)((rdp.prim_color >> 24) & 0xFF);
358           }
359         }
360       }
361
362       // Fix texture coordinates
363       if (!v->uv_scaled)
364       {
365         v->ou *= rdp.tiles[rdp.cur_tile].s_scale;
366         v->ov *= rdp.tiles[rdp.cur_tile].t_scale;
367         v->uv_scaled = 1;
368         if (!rdp.Persp_en)
369         {
370 //          v->oow = v->w = 1.0f;
371           v->ou *= 0.5f;
372           v->ov *= 0.5f;
373         }
374       }
375       v->u1 = v->u0 = v->ou;
376       v->v1 = v->v0 = v->ov;
377
378       if (rdp.tex >= 1 && rdp.cur_cache[0])
379       {
380         if (rdp.aTBuffTex[0])
381         {
382           v->u0 += rdp.aTBuffTex[0]->u_shift + rdp.aTBuffTex[0]->tile_uls;
383           v->v0 += rdp.aTBuffTex[0]->v_shift + rdp.aTBuffTex[0]->tile_ult;
384         }
385
386         if (rdp.tiles[rdp.cur_tile].shift_s)
387         {
388           if (rdp.tiles[rdp.cur_tile].shift_s > 10)
389             v->u0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s));
390           else
391             v->u0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_s);
392         }
393         if (rdp.tiles[rdp.cur_tile].shift_t)
394         {
395           if (rdp.tiles[rdp.cur_tile].shift_t > 10)
396             v->v0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t));
397           else
398             v->v0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_t);
399         }
400
401         if (rdp.aTBuffTex[0])
402         {
403           if (rdp.aTBuffTex[0]->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s)
404             v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;
405           if (rdp.aTBuffTex[0]->tile_ult != (int)rdp.tiles[rdp.cur_tile].f_ul_t || (settings.hacks&hack_Megaman))
406             v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t; //required for megaman (boss special attack)
407           v->u0 *= rdp.aTBuffTex[0]->u_scale;
408           v->v0 *= rdp.aTBuffTex[0]->v_scale;
409 #ifdef EXTREME_LOGGING
410           FRDP("tbuff_tex t0: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u0, v->v0);
411 #endif
412         }
413         else
414         {
415           v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;
416           v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t;
417           v->u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * v->u0;
418           v->v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * v->v0;
419         }
420         v->u0_w = v->u0 / v->w;
421         v->v0_w = v->v0 / v->w;
422       }
423
424       if (rdp.tex >= 2 && rdp.cur_cache[1])
425       {
426         if (rdp.aTBuffTex[1])
427         {
428           v->u1 += rdp.aTBuffTex[1]->u_shift + rdp.aTBuffTex[1]->tile_uls;
429           v->v1 += rdp.aTBuffTex[1]->v_shift + rdp.aTBuffTex[1]->tile_ult;
430         }
431         if (rdp.tiles[rdp.cur_tile+1].shift_s)
432         {
433           if (rdp.tiles[rdp.cur_tile+1].shift_s > 10)
434             v->u1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s));
435           else
436             v->u1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_s);
437         }
438         if (rdp.tiles[rdp.cur_tile+1].shift_t)
439         {
440           if (rdp.tiles[rdp.cur_tile+1].shift_t > 10)
441             v->v1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t));
442           else
443             v->v1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_t);
444         }
445
446         if (rdp.aTBuffTex[1])
447         {
448           if (rdp.aTBuffTex[1]->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s)
449             v->u1 -= rdp.tiles[rdp.cur_tile].f_ul_s;
450           v->u1 *= rdp.aTBuffTex[1]->u_scale;
451           v->v1 *= rdp.aTBuffTex[1]->v_scale;
452 #ifdef EXTREME_LOGGING
453           FRDP("tbuff_tex t1: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u1, v->v1);
454 #endif
455         }
456         else
457         {
458           v->u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s;
459           v->v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t;
460           v->u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * v->u1;
461           v->v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * v->v1;
462         }
463
464         v->u1_w = v->u1 / v->w;
465         v->v1_w = v->v1 / v->w;
466       }
467       //      FRDP(" * CALCULATING VERTEX U/V: %d  u0: %f, v0: %f, u1: %f, v1: %f\n", v->number, v->u0, v->v0, v->u1, v->v1);
468     }
469 #ifdef EXTREME_LOGGING
470             FRDP("draw_tri. v[%d] ou=%f, ov = %f\n", i, v->ou, v->ov);
471 #endif
472     if (v->shade_mod != cmb.shade_mod_hash)
473       apply_shade_mods (v);
474   } //for
475
476   rdp.clip = 0;
477
478   if ((vtx[0]->scr_off & 16) ||
479     (vtx[1]->scr_off & 16) ||
480     (vtx[2]->scr_off & 16))
481     rdp.clip |= CLIP_WMIN;
482
483   vtx[0]->not_zclipped = vtx[1]->not_zclipped = vtx[2]->not_zclipped = 1;
484
485   if (rdp.cur_cache[0] && (rdp.tex & 1) && (rdp.cur_cache[0]->splits > 1) && !rdp.aTBuffTex[0] && !rdp.clip)
486   {
487     int index,i,j, min_256,max_256, cur_256,left_256,right_256;
488     float percent;
489
490     min_256 = min((int)vtx[0]->u0,(int)vtx[1]->u0); // bah, don't put two mins on one line
491     min_256 = min(min_256,(int)vtx[2]->u0) >> 8;  // or it will be calculated twice
492
493     max_256 = max((int)vtx[0]->u0,(int)vtx[1]->u0); // not like it makes much difference
494     max_256 = max(max_256,(int)vtx[2]->u0) >> 8;  // anyway :P
495
496     for (cur_256=min_256; cur_256<=max_256; cur_256++)
497     {
498       left_256 = cur_256 << 8;
499       right_256 = (cur_256+1) << 8;
500
501       // Set vertex buffers
502       rdp.vtxbuf = rdp.vtx1;  // copy from v to rdp.vtx1
503       rdp.vtxbuf2 = rdp.vtx2;
504       rdp.vtx_buffer = 0;
505       rdp.n_global = 3;
506       index = 0;
507
508       // ** Left plane **
509       for (i=0; i<3; i++)
510       {
511         j = i+1;
512         if (j == 3) j = 0;
513
514         VERTEX *v1 = vtx[i];
515         VERTEX *v2 = vtx[j];
516
517         if (v1->u0 >= left_256)
518         {
519           if (v2->u0 >= left_256)   // Both are in, save the last one
520           {
521             rdp.vtxbuf[index] = *v2;
522             rdp.vtxbuf[index].u0 -= left_256;
523             rdp.vtxbuf[index++].v0 += cur_256 * rdp.cur_cache[0]->splitheight;
524           }
525           else      // First is in, second is out, save intersection
526           {
527             percent = (left_256 - v1->u0) / (v2->u0 - v1->u0);
528             rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent;
529             rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent;
530             rdp.vtxbuf[index].z = v1->z + (v2->z - v1->z) * percent;
531             rdp.vtxbuf[index].w = v1->w + (v2->w - v1->w) * percent;
532             rdp.vtxbuf[index].f = v1->f + (v2->f - v1->f) * percent;
533             rdp.vtxbuf[index].u0 = 0.5f;
534             rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent +
535               cur_256 * rdp.cur_cache[0]->splitheight;
536             rdp.vtxbuf[index].u1 = v1->u1 + (v2->u1 - v1->u1) * percent;
537             rdp.vtxbuf[index].v1 = v1->v1 + (v2->v1 - v1->v1) * percent;
538             rdp.vtxbuf[index].b = (wxUint8)(v1->b + (v2->b - v1->b) * percent);
539             rdp.vtxbuf[index].g = (wxUint8)(v1->g + (v2->g - v1->g) * percent);
540             rdp.vtxbuf[index].r = (wxUint8)(v1->r + (v2->r - v1->r) * percent);
541             rdp.vtxbuf[index++].a = (wxUint8)(v1->a + (v2->a - v1->a) * percent);
542           }
543         }
544         else
545         {
546           //if (v2->u0 < left_256)  // Both are out, save nothing
547           if (v2->u0 >= left_256) // First is out, second is in, save intersection & in point
548           {
549             percent = (left_256 - v2->u0) / (v1->u0 - v2->u0);
550             rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent;
551             rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent;
552             rdp.vtxbuf[index].z = v2->z + (v1->z - v2->z) * percent;
553             rdp.vtxbuf[index].w = v2->w + (v1->w - v2->w) * percent;
554             rdp.vtxbuf[index].f = v2->f + (v1->f - v2->f) * percent;
555             rdp.vtxbuf[index].u0 = 0.5f;
556             rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent +
557               cur_256 * rdp.cur_cache[0]->splitheight;
558             rdp.vtxbuf[index].u1 = v2->u1 + (v1->u1 - v2->u1) * percent;
559             rdp.vtxbuf[index].v1 = v2->v1 + (v1->v1 - v2->v1) * percent;
560             rdp.vtxbuf[index].b = (wxUint8)(v2->b + (v1->b - v2->b) * percent);
561             rdp.vtxbuf[index].g = (wxUint8)(v2->g + (v1->g - v2->g) * percent);
562             rdp.vtxbuf[index].r = (wxUint8)(v2->r + (v1->r - v2->r) * percent);
563             rdp.vtxbuf[index++].a = (wxUint8)(v2->a + (v1->a - v2->a) * percent);
564
565             // Save the in point
566             rdp.vtxbuf[index] = *v2;
567             rdp.vtxbuf[index].u0 -= left_256;
568             rdp.vtxbuf[index++].v0 += cur_256 * rdp.cur_cache[0]->splitheight;
569           }
570         }
571       }
572       rdp.n_global = index;
573
574       rdp.vtxbuf = rdp.vtx2;  // now vtx1 holds the value, & vtx2 is the destination
575       rdp.vtxbuf2 = rdp.vtx1;
576       rdp.vtx_buffer ^= 1;
577       index = 0;
578
579       for (i=0; i<rdp.n_global; i++)
580       {
581         j = i+1;
582         if (j == rdp.n_global) j = 0;
583
584         VERTEX *v1 = &rdp.vtxbuf2[i];
585         VERTEX *v2 = &rdp.vtxbuf2[j];
586
587         // ** Right plane **
588         if (v1->u0 <= right_256)
589         {
590           if (v2->u0 <= right_256)   // Both are in, save the last one
591           {
592             rdp.vtxbuf[index] = *v2;
593             rdp.vtxbuf[index++].not_zclipped = 0;
594           }
595           else      // First is in, second is out, save intersection
596           {
597             percent = (right_256 - v1->u0) / (v2->u0 - v1->u0);
598             rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent;
599             rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent;
600             rdp.vtxbuf[index].z = v1->z + (v2->z - v1->z) * percent;
601             rdp.vtxbuf[index].w = v1->w + (v2->w - v1->w) * percent;
602             rdp.vtxbuf[index].f = v1->f + (v2->f - v1->f) * percent;
603             rdp.vtxbuf[index].u0 = 255.5f;
604             rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent;
605             rdp.vtxbuf[index].u1 = v1->u1 + (v2->u1 - v1->u1) * percent;
606             rdp.vtxbuf[index].v1 = v1->v1 + (v2->v1 - v1->v1) * percent;
607             rdp.vtxbuf[index].b = (wxUint8)(v1->b + (v2->b - v1->b) * percent);
608             rdp.vtxbuf[index].g = (wxUint8)(v1->g + (v2->g - v1->g) * percent);
609             rdp.vtxbuf[index].r = (wxUint8)(v1->r + (v2->r - v1->r) * percent);
610             rdp.vtxbuf[index].a = (wxUint8)(v1->a + (v2->a - v1->a) * percent);
611             rdp.vtxbuf[index++].not_zclipped = 0;
612           }
613         }
614         else
615         {
616           //if (v2->u0 > 256.0f)  // Both are out, save nothing
617           if (v2->u0 <= right_256) // First is out, second is in, save intersection & in point
618           {
619             percent = (right_256 - v2->u0) / (v1->u0 - v2->u0);
620             rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent;
621             rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent;
622             rdp.vtxbuf[index].z = v2->z + (v1->z - v2->z) * percent;
623             rdp.vtxbuf[index].w = v2->w + (v1->w - v2->w) * percent;
624             rdp.vtxbuf[index].f = v2->f + (v1->f - v2->f) * percent;
625             rdp.vtxbuf[index].u0 = 255.5f;
626             rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent;
627             rdp.vtxbuf[index].u1 = v2->u1 + (v1->u1 - v2->u1) * percent;
628             rdp.vtxbuf[index].v1 = v2->v1 + (v1->v1 - v2->v1) * percent;
629             rdp.vtxbuf[index].b = (wxUint8)(v2->b + (v1->b - v2->b) * percent);
630             rdp.vtxbuf[index].g = (wxUint8)(v2->g + (v1->g - v2->g) * percent);
631             rdp.vtxbuf[index].r = (wxUint8)(v2->r + (v1->r - v2->r) * percent);
632             rdp.vtxbuf[index].a = (wxUint8)(v2->a + (v1->a - v2->a) * percent);
633             rdp.vtxbuf[index++].not_zclipped = 0;
634
635             // Save the in point
636             rdp.vtxbuf[index] = *v2;
637             rdp.vtxbuf[index++].not_zclipped = 0;
638           }
639         }
640       }
641       rdp.n_global = index;
642
643       do_triangle_stuff (linew, TRUE);
644     }
645   }
646   else
647   {
648     // Set vertex buffers
649     rdp.vtxbuf = rdp.vtx1;  // copy from v to rdp.vtx1
650     rdp.vtxbuf2 = rdp.vtx2;
651     rdp.vtx_buffer = 0;
652     rdp.n_global = 3;
653
654     rdp.vtxbuf[0] = *vtx[0];
655     rdp.vtxbuf[0].number = 1;
656     rdp.vtxbuf[1] = *vtx[1];
657     rdp.vtxbuf[1].number = 2;
658     rdp.vtxbuf[2] = *vtx[2];
659     rdp.vtxbuf[2].number = 4;
660
661     do_triangle_stuff (linew, FALSE);
662   }
663 }
664
665 #define interp2p(a, b, r)  (a + (b - a) * r)
666
667 //*
668 static void InterpolateColors(VERTEX & va, VERTEX & vb, VERTEX & res, float percent)
669 {
670   res.b = (wxUint8)interp2p(va.b, vb.b, percent);
671   res.g = (wxUint8)interp2p(va.g, vb.g, percent);;
672   res.r = (wxUint8)interp2p(va.r, vb.r, percent);;
673   res.a = (wxUint8)interp2p(va.a, vb.a, percent);;
674   res.f = interp2p(va.f, vb.f, percent);;
675 }
676 //*/
677 //
678 // clip_w - clips aint the z-axis
679 //
680 static void clip_w (int interpolate_colors)
681 {
682   int i,j,index,n=rdp.n_global;
683   float percent;
684   // Swap vertex buffers
685   VERTEX *tmp = rdp.vtxbuf2;
686   rdp.vtxbuf2 = rdp.vtxbuf;
687   rdp.vtxbuf = tmp;
688   rdp.vtx_buffer ^= 1;
689   index = 0;
690
691   // Check the vertices for clipping
692   for (i=0; i<n; i++)
693   {
694     j = i+1;
695     if (j == 3) j = 0;
696
697     if (Vi.w >= 0.01f)
698     {
699       if (Vj.w >= 0.01f)    // Both are in, save the last one
700       {
701         rdp.vtxbuf[index] = Vj;
702         rdp.vtxbuf[index++].not_zclipped = 1;
703       }
704       else      // First is in, second is out, save intersection
705       {
706         percent = (-Vi.w) / (Vj.w - Vi.w);
707         rdp.vtxbuf[index].not_zclipped = 0;
708         rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;
709         rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;
710         rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
711         rdp.vtxbuf[index].w = 0.01f;
712         rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
713         rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
714         rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
715         rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
716         if (interpolate_colors)
717           InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);
718         else
719           rdp.vtxbuf[index++].number = Vi.number | Vj.number;
720       }
721     }
722     else
723     {
724       //if (Vj.w < 0.01f) // Both are out, save nothing
725       if (Vj.w >= 0.01f)  // First is out, second is in, save intersection & in point
726       {
727         percent = (-Vj.w) / (Vi.w - Vj.w);
728         rdp.vtxbuf[index].not_zclipped = 0;
729         rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;
730         rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;
731         rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
732         rdp.vtxbuf[index].w = 0.01f;
733         rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
734         rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
735         rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
736         rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
737         if (interpolate_colors)
738           InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);
739         else
740           rdp.vtxbuf[index++].number = Vi.number | Vj.number;
741
742         // Save the in point
743         rdp.vtxbuf[index] = Vj;
744         rdp.vtxbuf[index++].not_zclipped = 1;
745       }
746     }
747   }
748   rdp.n_global = index;
749 }
750
751 static void render_tri (wxUint16 linew, int old_interpolate);
752
753 void do_triangle_stuff (wxUint16 linew, int old_interpolate) // what else?? do the triangle stuff :P (to keep from writing code twice)
754 {
755   int i;
756
757   if (rdp.clip & CLIP_WMIN)
758     clip_w (old_interpolate);
759
760   float maxZ = (rdp.zsrc != 1) ? rdp.view_trans[2] + rdp.view_scale[2] : rdp.prim_depth;
761
762   wxUint8 no_clip = 2;
763   for (i=0; i<rdp.n_global; i++)
764   {
765     if (rdp.vtxbuf[i].not_zclipped)// && rdp.zsrc != 1)
766     {
767 #ifdef EXTREME_LOGGING
768       FRDP (" * NOT ZCLIPPPED: %d\n", rdp.vtxbuf[i].number);
769 #endif
770       rdp.vtxbuf[i].x = rdp.vtxbuf[i].sx;
771       rdp.vtxbuf[i].y = rdp.vtxbuf[i].sy;
772       rdp.vtxbuf[i].z = rdp.vtxbuf[i].sz;
773       rdp.vtxbuf[i].q = rdp.vtxbuf[i].oow;
774       rdp.vtxbuf[i].u0 = rdp.vtxbuf[i].u0_w;
775       rdp.vtxbuf[i].v0 = rdp.vtxbuf[i].v0_w;
776       rdp.vtxbuf[i].u1 = rdp.vtxbuf[i].u1_w;
777       rdp.vtxbuf[i].v1 = rdp.vtxbuf[i].v1_w;
778     }
779     else
780     {
781 #ifdef EXTREME_LOGGING
782       FRDP (" * ZCLIPPED: %d\n", rdp.vtxbuf[i].number);
783 #endif
784       rdp.vtxbuf[i].q = 1.0f / rdp.vtxbuf[i].w;
785       rdp.vtxbuf[i].x = rdp.view_trans[0] + rdp.vtxbuf[i].x * rdp.vtxbuf[i].q * rdp.view_scale[0] + rdp.offset_x;
786       rdp.vtxbuf[i].y = rdp.view_trans[1] + rdp.vtxbuf[i].y * rdp.vtxbuf[i].q * rdp.view_scale[1] + rdp.offset_y;
787       rdp.vtxbuf[i].z = rdp.view_trans[2] + rdp.vtxbuf[i].z * rdp.vtxbuf[i].q * rdp.view_scale[2];
788       if (rdp.tex >= 1)
789       {
790         rdp.vtxbuf[i].u0 *= rdp.vtxbuf[i].q;
791         rdp.vtxbuf[i].v0 *= rdp.vtxbuf[i].q;
792       }
793       if (rdp.tex >= 2)
794       {
795         rdp.vtxbuf[i].u1 *= rdp.vtxbuf[i].q;
796         rdp.vtxbuf[i].v1 *= rdp.vtxbuf[i].q;
797       }
798     }
799
800     if (rdp.zsrc == 1)
801       rdp.vtxbuf[i].z = rdp.prim_depth;
802
803     // Don't remove clipping, or it will freeze
804     if (rdp.vtxbuf[i].x > rdp.clip_max_x) rdp.clip |= CLIP_XMAX;
805     if (rdp.vtxbuf[i].x < rdp.clip_min_x) rdp.clip |= CLIP_XMIN;
806     if (rdp.vtxbuf[i].y > rdp.clip_max_y) rdp.clip |= CLIP_YMAX;
807     if (rdp.vtxbuf[i].y < rdp.clip_min_y) rdp.clip |= CLIP_YMIN;
808     if (rdp.vtxbuf[i].z > maxZ)           rdp.clip |= CLIP_ZMAX;
809     if (rdp.vtxbuf[i].z < 0.0f)           rdp.clip |= CLIP_ZMIN;
810     no_clip &= rdp.vtxbuf[i].screen_translated;
811   }
812   if (no_clip)
813     rdp.clip = 0;
814   else
815   {
816     if (!settings.clip_zmin)
817       rdp.clip &= ~CLIP_ZMIN;
818     if (!settings.clip_zmax)
819       rdp.clip &= ~CLIP_ZMAX;
820   }
821   render_tri (linew, old_interpolate);
822 }
823
824 void do_triangle_stuff_2 (wxUint16 linew)
825 {
826   rdp.clip = 0;
827
828   for (int i=0; i<rdp.n_global; i++)
829   {
830     // Don't remove clipping, or it will freeze
831     if (rdp.vtxbuf[i].x > rdp.clip_max_x) rdp.clip |= CLIP_XMAX;
832     if (rdp.vtxbuf[i].x < rdp.clip_min_x) rdp.clip |= CLIP_XMIN;
833     if (rdp.vtxbuf[i].y > rdp.clip_max_y) rdp.clip |= CLIP_YMAX;
834     if (rdp.vtxbuf[i].y < rdp.clip_min_y) rdp.clip |= CLIP_YMIN;
835   }
836
837   render_tri (linew, TRUE);
838 }
839
840 __inline wxUint8 real_to_char(double x)
841 {
842   return (wxUint8)(((int)floor(x+0.5))&0xFF);
843 }
844
845 //*
846 static void InterpolateColors2(VERTEX & va, VERTEX & vb, VERTEX & res, float percent)
847 {
848   float w = 1.0f/(va.oow + (vb.oow-va.oow) * percent);
849   //   res.oow = va.oow + (vb.oow-va.oow) * percent;
850   //   res.q = res.oow;
851   float ba = va.b * va.oow;
852   float bb = vb.b * vb.oow;
853   res.b = real_to_char(interp2p(ba, bb, percent) * w);
854   float ga = va.g * va.oow;
855   float gb = vb.g * vb.oow;
856   res.g = real_to_char(interp2p(ga, gb, percent) * w);
857   float ra = va.r * va.oow;
858   float rb = vb.r * vb.oow;
859   res.r = real_to_char(interp2p(ra, rb, percent) * w);
860   float aa = va.a * va.oow;
861   float ab = vb.a * vb.oow;
862   res.a = real_to_char(interp2p(aa, ab, percent) * w);
863   float fa = va.f * va.oow;
864   float fb = vb.f * vb.oow;
865   res.f = interp2p(fa, fb, percent) * w;
866   /*
867   float u0a = va.u0_w * va.oow;
868   float u0b = vb.u0_w * vb.oow;
869   res.u0 = (u0a + (u0b - u0a) * percent) * w;
870   float v0a = va.v0_w * va.oow;
871   float v0b = vb.v0_w * vb.oow;
872   res.v0 = (v0a + (v0b - v0a) * percent) * w;
873   float u1a = va.u1_w * va.oow;
874   float u1b = vb.u1_w * vb.oow;
875   res.u1 = (u1a + (u1b - u1a) * percent) * w;
876   float v1a = va.v1_w * va.oow;
877   float v1b = vb.v1_w * vb.oow;
878   res.v1 = (v1a + (v1b - v1a) * percent) * w;
879   */
880 }
881 //*/
882
883 typedef struct {
884   float d;              //*SEB* was doubles
885   float x;
886   float y;
887 } LineEuqationType;
888
889 static float EvaLine(LineEuqationType &li, float x, float y)    //*SEB* all double before
890 {
891   return li.x*x+li.y*y+li.d;
892 }
893
894 static void Create1LineEq(LineEuqationType &l, VERTEX &v1, VERTEX &v2, VERTEX &v3)
895 {
896   // Line between (x1,y1) to (x2,y2)
897   l.x = v2.sy-v1.sy;
898   l.y = v1.sx-v2.sx;
899   l.d = -(l.x*v2.sx+(l.y)*v2.sy);
900   if (EvaLine(l,v3.sx,v3.sy)*v3.oow < 0)
901   {
902     l.x = -l.x;
903     l.y = -l.y;
904     l.d = -l.d;
905   }
906 }
907
908
909 __inline float interp3p(float a, float b, float c, float r1, float r2)  //*SEB* r1 and r2 and function was double
910 {
911   return (a)+(((b)+((c)-(b))*(r2))-(a))*(r1);
912 }
913 /*
914 #define interp3p(a, b, c, r1, r2) \
915   (a+(((b)+((c)-(b))*(r2))-(a))*(r1))
916 */
917
918 static void InterpolateColors3(VERTEX &v1, VERTEX &v2, VERTEX &v3, VERTEX &out) //*SEB* all double before
919 {
920
921   LineEuqationType line;
922   Create1LineEq(line, v2, v3, v1);
923
924   float aDot = (out.x*line.x + out.y*line.y);
925   float bDot = (v1.sx*line.x + v1.sy*line.y);
926
927   float scale1 = ( - line.d - aDot) / ( bDot - aDot );
928
929   float tx = out.x + scale1 * (v1.sx - out.x);
930   float ty = out.y + scale1 * (v1.sy - out.y);
931
932   float s1 = 101.0, s2 = 101.0;
933   float den = tx - v1.sx;
934   if (fabsf(den) > 1.0)
935     s1 = (out.x-v1.sx)/den;
936   if (s1 > 100.0f)
937     s1 = (out.y-v1.sy)/(ty-v1.sy);
938
939   den = v3.sx - v2.sx;
940   if (fabsf(den) > 1.0)
941     s2 = (tx-v2.sx)/den;
942   if (s2 > 100.0f)
943     s2 =(ty-v2.sy)/(v3.sy-v2.sy);
944
945   float w = 1.0/interp3p(v1.oow,v2.oow,v3.oow,s1,s2);
946
947   out.r = real_to_char(interp3p(v1.r*v1.oow,v2.r*v2.oow,v3.r*v3.oow,s1,s2)*w);
948   out.g = real_to_char(interp3p(v1.g*v1.oow,v2.g*v2.oow,v3.g*v3.oow,s1,s2)*w);
949   out.b = real_to_char(interp3p(v1.b*v1.oow,v2.b*v2.oow,v3.b*v3.oow,s1,s2)*w);
950   out.a = real_to_char(interp3p(v1.a*v1.oow,v2.a*v2.oow,v3.a*v3.oow,s1,s2)*w);
951   out.f = (float)(interp3p(v1.f*v1.oow,v2.f*v2.oow,v3.f*v3.oow,s1,s2)*w);
952   /*
953   out.u0 = interp3p(v1.u0_w*v1.oow,v2.u0_w*v2.oow,v3.u0_w*v3.oow,s1,s2)/oow;
954   out.v0 = interp3p(v1.v0_w*v1.oow,v2.v0_w*v2.oow,v3.v0_w*v3.oow,s1,s2)/oow;
955   out.u1 = interp3p(v1.u1_w*v1.oow,v2.u1_w*v2.oow,v3.u1_w*v3.oow,s1,s2)/oow;
956   out.v1 = interp3p(v1.v1_w*v1.oow,v2.v1_w*v2.oow,v3.v1_w*v3.oow,s1,s2)/oow;
957   */
958 }
959
960 static void CalculateLOD(VERTEX *v, int n)
961 {
962   //rdp.update |= UPDATE_TEXTURE;
963   /*
964   if (rdp.lod_calculated)
965   {
966   float detailmax;
967   if (dc0_detailmax < 0.5)
968   detailmax = rdp.lod_fraction;
969   else
970   detailmax = 1.0f - rdp.lod_fraction;
971   grTexDetailControl (GR_TMU0, dc0_lodbias, dc0_detailscale, detailmax);
972   if (num_tmu == 2)
973   grTexDetailControl (GR_TMU1, dc1_lodbias, dc1_detailscale, detailmax);
974   return;
975   }
976   */
977   float deltaS, deltaT;
978   float deltaX, deltaY;
979   float deltaTexels, deltaPixels, lodFactor = 0;        //*SEB* double before
980   float intptr;                                                                         //*SEB* double before
981   float s_scale = rdp.tiles[rdp.cur_tile].width / 255.0f;
982   float t_scale = rdp.tiles[rdp.cur_tile].height / 255.0f;
983   if (settings.lodmode == 1)
984   {
985     deltaS = (v[1].u0/v[1].q - v[0].u0/v[0].q) * s_scale;
986     deltaT = (v[1].v0/v[1].q - v[0].v0/v[0].q) * t_scale;
987     deltaTexels = sqrt( deltaS * deltaS + deltaT * deltaT );
988
989     deltaX = (v[1].x - v[0].x)/rdp.scale_x;
990     deltaY = (v[1].y - v[0].y)/rdp.scale_y;
991     deltaPixels = sqrt( deltaX * deltaX + deltaY * deltaY );
992
993     lodFactor = deltaTexels / deltaPixels;
994   }
995   else
996   {
997     int i, j;
998     for (i = 0; i < n; i++)
999     {
1000       j = (i < n-1) ? i + 1 : 0;
1001
1002       deltaS = (v[j].u0/v[j].q - v[i].u0/v[i].q) * s_scale;
1003       deltaT = (v[j].v0/v[j].q - v[i].v0/v[i].q) * t_scale;
1004       //    deltaS = v[j].ou - v[i].ou;
1005       //    deltaT = v[j].ov - v[i].ov;
1006       deltaTexels = sqrt( deltaS * deltaS + deltaT * deltaT );
1007
1008       deltaX = (v[j].x - v[i].x)/rdp.scale_x;
1009       deltaY = (v[j].y - v[i].y)/rdp.scale_y;
1010       deltaPixels = sqrt( deltaX * deltaX + deltaY * deltaY );
1011
1012       lodFactor += deltaTexels / deltaPixels;
1013     }
1014     // Divide by n (n edges) to find average
1015     lodFactor = lodFactor / n;
1016   }
1017   int ilod = (int)lodFactor;
1018   int lod_tile = min((int)(log10f((float)ilod)/log10f(2.0f)), rdp.cur_tile + rdp.mipmap_level);
1019   float lod_fraction = 1.0f;
1020   if (lod_tile < rdp.cur_tile + rdp.mipmap_level)
1021   {
1022         lod_fraction = max((float)modff(lodFactor / powf(2.,lod_tile),&intptr), (float)rdp.prim_lodmin / 255.0f);
1023   }
1024   float detailmax;
1025   if (cmb.dc0_detailmax < 0.5f)
1026     detailmax = lod_fraction;
1027   else
1028     detailmax = 1.0f - lod_fraction;
1029   grTexDetailControl (GR_TMU0, cmb.dc0_lodbias, cmb.dc0_detailscale, detailmax);
1030   if (voodoo.num_tmu == 2)
1031     grTexDetailControl (GR_TMU1, cmb.dc1_lodbias, cmb.dc1_detailscale, detailmax);
1032   FRDP("CalculateLOD factor: %f, tile: %d, lod_fraction: %f\n", (float)lodFactor, lod_tile, lod_fraction);
1033 }
1034
1035 float ScaleZ(float z)
1036 {
1037   if (settings.n64_z_scale)
1038   {
1039     int iz = (int)(z*8.0f+0.5f);
1040     if (iz < 0) iz = 0;
1041     else if (iz >= 0x40000) iz = 0x40000 - 1;
1042     return (float)zLUT[iz];
1043   }
1044   if (z  < 0.0f) return 0.0f;
1045   z *= 1.9f;
1046   if (z > 65534.0f) return 65534.0f;
1047   return z;
1048 }
1049
1050 static void DepthBuffer(VERTEX * vtx, int n)
1051 {
1052   if (fb_depth_render_enabled && !(settings.hacks&hack_RE2) && dzdx && (rdp.flags & ZBUF_UPDATE))
1053   {
1054     vertexi v[12];
1055     if (u_cull_mode == 1) //cull front
1056     {
1057       for(int i=0; i<n; i++)
1058       {
1059         v[i].x = (int)((vtx[n-i-1].x-rdp.offset_x) / rdp.scale_x * 65536.0);
1060         v[i].y = (int)((vtx[n-i-1].y-rdp.offset_y) / rdp.scale_y * 65536.0);
1061         v[i].z = (int)(vtx[n-i-1].z * 65536.0);
1062       }
1063     }
1064     else
1065     {
1066       for(int i=0; i<n; i++)
1067       {
1068         v[i].x = (int)((vtx[i].x-rdp.offset_x) / rdp.scale_x * 65536.0);
1069         v[i].y = (int)((vtx[i].y-rdp.offset_y) / rdp.scale_y * 65536.0);
1070         v[i].z = (int)(vtx[i].z * 65536.0);
1071       }
1072     }
1073     Rasterize(v, n, dzdx);
1074   }
1075   for(int i=0; i<n; i++)
1076     vtx[i].z = ScaleZ(vtx[i].z);
1077 }
1078
1079 /*
1080 std::ofstream loga;
1081 #define LOGG(x) loga.open("glide_log.txt",std::ios::app); loga << x; loga.flush(); loga.close();
1082 __inline void FRDP2(char *fmt, ...)
1083 {
1084 va_list ap;
1085 va_start(ap, fmt);
1086 vsprintf(out_buf, fmt, ap);
1087 LOGG(out_buf);
1088 va_end(ap);
1089 }
1090 //*/
1091 //#define LOGG(x)
1092 //#define FRDP2(x)
1093
1094
1095 void clip_tri(int interpolate_colors)
1096 {
1097   int i,j,index,n=rdp.n_global;
1098   float percent;
1099
1100   // Check which clipping is needed
1101   if (rdp.clip & CLIP_XMAX) // right of the screen
1102   {
1103     // Swap vertex buffers
1104     VERTEX *tmp = rdp.vtxbuf2;
1105     rdp.vtxbuf2 = rdp.vtxbuf;
1106     rdp.vtxbuf = tmp;
1107     rdp.vtx_buffer ^= 1;
1108     index = 0;
1109
1110     // Check the vertices for clipping
1111     for (i=0; i<n; i++)
1112     {
1113       j = i+1;
1114       if (j == n) j = 0;
1115
1116       if (Vi.x <= rdp.clip_max_x)
1117       {
1118         if (Vj.x <= rdp.clip_max_x)   // Both are in, save the last one
1119         {
1120           rdp.vtxbuf[index++] = Vj;
1121         }
1122         else      // First is in, second is out, save intersection
1123         {
1124           percent = (rdp.clip_max_x - Vi.x) / (Vj.x - Vi.x);
1125           rdp.vtxbuf[index].x = rdp.clip_max_x;
1126           rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;
1127           rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
1128           rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;
1129           rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
1130           rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
1131           rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
1132           rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
1133           if (interpolate_colors)
1134             InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);
1135           else
1136             rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8;
1137         }
1138       }
1139       else
1140       {
1141         //if (Vj.x > rdp.clip_max_x)  // Both are out, save nothing
1142         if (Vj.x <= rdp.clip_max_x) // First is out, second is in, save intersection & in point
1143         {
1144           percent = (rdp.clip_max_x - Vj.x) / (Vi.x - Vj.x);
1145           rdp.vtxbuf[index].x = rdp.clip_max_x;
1146           rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;
1147           rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
1148           rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;
1149           rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
1150           rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
1151           rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
1152           rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
1153           if (interpolate_colors)
1154             InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);
1155           else
1156             rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8;
1157
1158           // Save the in point
1159           rdp.vtxbuf[index++] = Vj;
1160         }
1161       }
1162     }
1163     n = index;
1164   }
1165   if (rdp.clip & CLIP_XMIN) // left of the screen
1166   {
1167     // Swap vertex buffers
1168     VERTEX *tmp = rdp.vtxbuf2;
1169     rdp.vtxbuf2 = rdp.vtxbuf;
1170     rdp.vtxbuf = tmp;
1171     rdp.vtx_buffer ^= 1;
1172     index = 0;
1173
1174     // Check the vertices for clipping
1175     for (i=0; i<n; i++)
1176     {
1177       j = i+1;
1178       if (j == n) j = 0;
1179
1180       if (Vi.x >= rdp.clip_min_x)
1181       {
1182         if (Vj.x >= rdp.clip_min_x)   // Both are in, save the last one
1183         {
1184           rdp.vtxbuf[index++] = Vj;
1185         }
1186         else      // First is in, second is out, save intersection
1187         {
1188           percent = (rdp.clip_min_x - Vi.x) / (Vj.x - Vi.x);
1189           rdp.vtxbuf[index].x = rdp.clip_min_x;
1190           rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;
1191           rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
1192           rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;
1193           rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
1194           rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
1195           rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
1196           rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
1197           if (interpolate_colors)
1198             InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);
1199           else
1200             rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8;
1201         }
1202       }
1203       else
1204       {
1205         //if (Vj.x < rdp.clip_min_x)  // Both are out, save nothing
1206         if (Vj.x >= rdp.clip_min_x) // First is out, second is in, save intersection & in point
1207         {
1208           percent = (rdp.clip_min_x - Vj.x) / (Vi.x - Vj.x);
1209           rdp.vtxbuf[index].x = rdp.clip_min_x;
1210           rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;
1211           rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
1212           rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;
1213           rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
1214           rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
1215           rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
1216           rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
1217           if (interpolate_colors)
1218             InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);
1219           else
1220             rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8;
1221
1222           // Save the in point
1223           rdp.vtxbuf[index++] = Vj;
1224         }
1225       }
1226     }
1227     n = index;
1228   }
1229   if (rdp.clip & CLIP_YMAX) // top of the screen
1230   {
1231     // Swap vertex buffers
1232     VERTEX *tmp = rdp.vtxbuf2;
1233     rdp.vtxbuf2 = rdp.vtxbuf;
1234     rdp.vtxbuf = tmp;
1235     rdp.vtx_buffer ^= 1;
1236     index = 0;
1237
1238     // Check the vertices for clipping
1239     for (i=0; i<n; i++)
1240     {
1241       j = i+1;
1242       if (j == n) j = 0;
1243
1244       if (Vi.y <= rdp.clip_max_y)
1245       {
1246         if (Vj.y <= rdp.clip_max_y)   // Both are in, save the last one
1247         {
1248           rdp.vtxbuf[index++] = Vj;
1249         }
1250         else      // First is in, second is out, save intersection
1251         {
1252           percent = (rdp.clip_max_y - Vi.y) / (Vj.y - Vi.y);
1253           rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;
1254           rdp.vtxbuf[index].y = rdp.clip_max_y;
1255           rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
1256           rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;
1257           rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
1258           rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
1259           rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
1260           rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
1261           if (interpolate_colors)
1262             InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);
1263           else
1264             rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16;
1265         }
1266       }
1267       else
1268       {
1269         //if (Vj.y > rdp.clip_max_y)  // Both are out, save nothing
1270         if (Vj.y <= rdp.clip_max_y) // First is out, second is in, save intersection & in point
1271         {
1272           percent = (rdp.clip_max_y - Vj.y) / (Vi.y - Vj.y);
1273           rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;
1274           rdp.vtxbuf[index].y = rdp.clip_max_y;
1275           rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
1276           rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;
1277           rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
1278           rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
1279           rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
1280           rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
1281           if (interpolate_colors)
1282             InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);
1283           else
1284             rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16;
1285
1286           // Save the in point
1287           rdp.vtxbuf[index++] = Vj;
1288         }
1289       }
1290     }
1291     n = index;
1292   }
1293   if (rdp.clip & CLIP_YMIN) // bottom of the screen
1294   {
1295     // Swap vertex buffers
1296     VERTEX *tmp = rdp.vtxbuf2;
1297     rdp.vtxbuf2 = rdp.vtxbuf;
1298     rdp.vtxbuf = tmp;
1299     rdp.vtx_buffer ^= 1;
1300     index = 0;
1301
1302     // Check the vertices for clipping
1303     for (i=0; i<n; i++)
1304     {
1305       j = i+1;
1306       if (j == n) j = 0;
1307
1308       if (Vi.y >= rdp.clip_min_y)
1309       {
1310         if (Vj.y >= rdp.clip_min_y)   // Both are in, save the last one
1311         {
1312           rdp.vtxbuf[index++] = Vj;
1313         }
1314         else      // First is in, second is out, save intersection
1315         {
1316           percent = (rdp.clip_min_y - Vi.y) / (Vj.y - Vi.y);
1317           rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;
1318           rdp.vtxbuf[index].y = rdp.clip_min_y;
1319           rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
1320           rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;
1321           rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
1322           rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
1323           rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
1324           rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
1325           if (interpolate_colors)
1326             InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);
1327           else
1328             rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16;
1329         }
1330       }
1331       else
1332       {
1333         //if (Vj.y < rdp.clip_min_y)  // Both are out, save nothing
1334         if (Vj.y >= rdp.clip_min_y) // First is out, second is in, save intersection & in point
1335         {
1336           percent = (rdp.clip_min_y - Vj.y) / (Vi.y - Vj.y);
1337           rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;
1338           rdp.vtxbuf[index].y = rdp.clip_min_y;
1339           rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
1340           rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;
1341           rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
1342           rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
1343           rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
1344           rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
1345           if (interpolate_colors)
1346             InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);
1347           else
1348             rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16;
1349
1350           // Save the in point
1351           rdp.vtxbuf[index++] = Vj;
1352         }
1353       }
1354     }
1355     n = index;
1356   }
1357   if (rdp.clip & CLIP_ZMAX) // far plane
1358   {
1359     // Swap vertex buffers
1360     VERTEX *tmp = rdp.vtxbuf2;
1361     rdp.vtxbuf2 = rdp.vtxbuf;
1362     rdp.vtxbuf = tmp;
1363     rdp.vtx_buffer ^= 1;
1364     index = 0;
1365     float maxZ = rdp.view_trans[2] + rdp.view_scale[2];
1366
1367     // Check the vertices for clipping
1368     for (i=0; i<n; i++)
1369     {
1370       j = i+1;
1371       if (j == n) j = 0;
1372
1373       if (Vi.z < maxZ)
1374       {
1375         if (Vj.z < maxZ)   // Both are in, save the last one
1376         {
1377           rdp.vtxbuf[index++] = Vj;
1378         }
1379         else      // First is in, second is out, save intersection
1380         {
1381           percent = (maxZ - Vi.z) / (Vj.z - Vi.z);
1382           rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;
1383           rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;
1384           rdp.vtxbuf[index].z = maxZ - 0.001f;
1385           rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;
1386           rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
1387           rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
1388           rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
1389           rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
1390           if (interpolate_colors)
1391             InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);
1392           else
1393             rdp.vtxbuf[index++].number = Vi.number | Vj.number;
1394         }
1395       }
1396       else
1397       {
1398         //if (Vj.z > maxZ)  // Both are out, save nothing
1399         if (Vj.z < maxZ) // First is out, second is in, save intersection & in point
1400         {
1401           percent = (maxZ - Vj.z) / (Vi.z - Vj.z);
1402           rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;
1403           rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;
1404           rdp.vtxbuf[index].z = maxZ - 0.001f;;
1405           rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;
1406           rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
1407           rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
1408           rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
1409           rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
1410           if (interpolate_colors)
1411             InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);
1412           else
1413             rdp.vtxbuf[index++].number = Vi.number | Vj.number;
1414
1415           // Save the in point
1416           rdp.vtxbuf[index++] = Vj;
1417         }
1418       }
1419     }
1420     n = index;
1421   }
1422 /*
1423   if (rdp.clip & CLIP_ZMIN) // near Z
1424   {
1425     // Swap vertex buffers
1426     VERTEX *tmp = rdp.vtxbuf2;
1427     rdp.vtxbuf2 = rdp.vtxbuf;
1428     rdp.vtxbuf = tmp;
1429     rdp.vtx_buffer ^= 1;
1430     index = 0;
1431
1432     // Check the vertices for clipping
1433     for (i=0; i<n; i++)
1434     {
1435       j = i+1;
1436       if (j == n) j = 0;
1437
1438       if (Vi.z >= 0.0f)
1439       {
1440         if (Vj.z >= 0.0f)   // Both are in, save the last one
1441         {
1442           rdp.vtxbuf[index++] = Vj;
1443         }
1444         else      // First is in, second is out, save intersection
1445         {
1446           percent = (-Vi.z) / (Vj.z - Vi.z);
1447           rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;
1448           rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;
1449           rdp.vtxbuf[index].z = 0.0f;
1450           rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;
1451           rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
1452           rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
1453           rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
1454           rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
1455           if (interpolate_colors)
1456             InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);
1457           else
1458             rdp.vtxbuf[index++].number = Vi.number | Vj.number;
1459         }
1460       }
1461       else
1462       {
1463         //if (Vj.z < 0.0f)  // Both are out, save nothing
1464         if (Vj.z >= 0.0f) // First is out, second is in, save intersection & in point
1465         {
1466           percent = (-Vj.z) / (Vi.z - Vj.z);
1467           rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;
1468           rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;
1469           rdp.vtxbuf[index].z = 0.0f;;
1470           rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;
1471           rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
1472           rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
1473           rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
1474           rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
1475           if (interpolate_colors)
1476             InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);
1477           else
1478             rdp.vtxbuf[index++].number = Vi.number | Vj.number;
1479
1480           // Save the in point
1481           rdp.vtxbuf[index++] = Vj;
1482         }
1483       }
1484     }
1485     n = index;
1486   }
1487 */
1488   rdp.n_global = n;
1489 }
1490
1491 static void render_tri (wxUint16 linew, int old_interpolate)
1492 {
1493   if (rdp.clip)
1494     clip_tri(old_interpolate);
1495   int n = rdp.n_global;
1496   if (n < 3)
1497   {
1498     FRDP (" * render_tri: n < 3\n");
1499     return;
1500   }
1501   int i,j;
1502   //*
1503   if ((rdp.clip & CLIP_ZMIN) && (rdp.othermode_l & 0x00000030))
1504   {
1505
1506     int to_render = FALSE;
1507     for (i = 0; i < n; i++)
1508     {
1509       if (rdp.vtxbuf[i].z >= 0.0f)
1510       {
1511         to_render = TRUE;
1512         break;
1513       }
1514     }
1515     if (!to_render) //all z < 0
1516     {
1517       FRDP (" * render_tri: all z < 0\n");
1518       return;
1519     }
1520   }
1521   //*/
1522   if (rdp.clip && !old_interpolate)
1523   {
1524     for (i = 0; i < n; i++)
1525     {
1526       float percent = 101.0f;
1527       VERTEX * v1 = 0,  * v2 = 0;
1528       switch (rdp.vtxbuf[i].number&7)
1529       {
1530       case 1:
1531       case 2:
1532       case 4:
1533         continue;
1534         break;
1535       case 3:
1536         v1 = org_vtx[0];
1537         v2 = org_vtx[1];
1538         break;
1539       case 5:
1540         v1 = org_vtx[0];
1541         v2 = org_vtx[2];
1542         break;
1543       case 6:
1544         v1 = org_vtx[1];
1545         v2 = org_vtx[2];
1546         break;
1547       case 7:
1548         InterpolateColors3(*org_vtx[0], *org_vtx[1], *org_vtx[2], rdp.vtxbuf[i]);
1549         continue;
1550         break;
1551       }
1552       switch (rdp.vtxbuf[i].number&24)
1553       {
1554       case 8:
1555         percent = (rdp.vtxbuf[i].x-v1->sx)/(v2->sx-v1->sx);
1556         break;
1557       case 16:
1558         percent = (rdp.vtxbuf[i].y-v1->sy)/(v2->sy-v1->sy);
1559         break;
1560       default:
1561         {
1562           float d = (v2->sx-v1->sx);
1563           if (fabs(d) > 1.0)
1564             percent = (rdp.vtxbuf[i].x-v1->sx)/d;
1565           if (percent > 100.0f)
1566             percent = (rdp.vtxbuf[i].y-v1->sy)/(v2->sy-v1->sy);
1567         }
1568       }
1569       InterpolateColors2(*v1, *v2, rdp.vtxbuf[i], percent);
1570     }
1571   }
1572   /*
1573   if (rdp.clip)
1574   {
1575   LOGG("Colors before clipping:\n");
1576   unsigned int k;
1577                 for(k=0; k<3; k++)
1578     {
1579                   FRDP2("V%d: r=%d, g=%d, b=%d, a=%d, f=%d\n", k, org_vtx[k]->r, org_vtx[k]->g, org_vtx[k]->b, org_vtx[k]->a, (short)org_vtx[k]->f);
1580       }
1581       FRDP("Got %d vertex after clipping\n", n);
1582       for(k=0; k<n; k++)
1583       {
1584       FRDP("V%d: r=%d, g=%d, b=%d, a=%d, f=%d\n", k, rdp.vtxbuf[k].r, rdp.vtxbuf[k].g, rdp.vtxbuf[k].b, rdp.vtxbuf[k].a, (short)rdp.vtxbuf[k].f);
1585       }
1586       }
1587   */
1588
1589   ConvertCoordsConvert (rdp.vtxbuf, n);
1590   if (rdp.fog_mode == RDP::fog_enabled)
1591   {
1592     for (i = 0; i < n; i++)
1593     {
1594       rdp.vtxbuf[i].f = 1.0f/max(4.0f, rdp.vtxbuf[i].f);
1595     }
1596   }
1597   else if (rdp.fog_mode == RDP::fog_blend)
1598   {
1599     float fog = 1.0f/max(1, rdp.fog_color&0xFF);
1600     for (i = 0; i < n; i++)
1601     {
1602       rdp.vtxbuf[i].f = fog;
1603     }
1604   }
1605   else if (rdp.fog_mode == RDP::fog_blend_inverse)
1606   {
1607     float fog = 1.0f/max(1, (~rdp.fog_color)&0xFF);
1608     for (i = 0; i < n; i++)
1609     {
1610       rdp.vtxbuf[i].f = fog;
1611     }
1612   }
1613
1614   if (settings.lodmode > 0 && rdp.cur_tile < rdp.mipmap_level)
1615     CalculateLOD(rdp.vtxbuf, n);
1616
1617   cmb.cmb_ext_use = cmb.tex_cmb_ext_use = 0;
1618
1619   /*
1620   if (rdp.tbuff_tex)
1621   {
1622   for (int k = 0; k < 3; k++)
1623   {
1624   FRDP("v%d %f->%f, width: %d. height: %d, tex_width: %d, tex_height: %d, lr_u: %f, lr_v: %f\n", k, vv0[k], pv[k]->v1, rdp.tbuff_tex->width, rdp.tbuff_tex->height, rdp.tbuff_tex->tex_width, rdp.tbuff_tex->tex_height, rdp.tbuff_tex->lr_u, rdp.tbuff_tex->lr_v);
1625   }
1626   }
1627   */
1628   if (fullscreen)
1629   {
1630     if (settings.wireframe)
1631     {
1632       SetWireframeCol ();
1633       for (i=0; i<n; i++)
1634       {
1635         j = i+1;
1636         if (j == n) j = 0;
1637         grDrawLine (&rdp.vtxbuf[i], &rdp.vtxbuf[j]);
1638       }
1639     }
1640     else
1641     {
1642
1643       //      VERTEX ** pv = rdp.vtx_buffer?(vtx_list2):(vtx_list1);
1644       //      for (int k = 0; k < n; k ++)
1645       //                        FRDP ("DRAW[%d]: v.x = %f, v.y = %f, v.z = %f, v.u = %f, v.v = %f\n", k, pv[k]->x, pv[k]->y, pv[k]->z, pv[k]->coord[rdp.t0<<1], pv[k]->coord[(rdp.t0<<1)+1]);
1646       //        pv[k]->y = settings.res_y - pv[k]->y;
1647
1648       if (linew > 0)
1649       {
1650         VERTEX *V0 = &rdp.vtxbuf[0];
1651         VERTEX *V1 = &rdp.vtxbuf[1];
1652         if (fabs(V0->x - V1->x) < 0.01 && fabs(V0->y - V1->y) < 0.01)
1653           V1 = &rdp.vtxbuf[2];
1654         V0->z = ScaleZ(V0->z);
1655         V1->z = ScaleZ(V1->z);
1656         VERTEX v[4];
1657         v[0] = *V0;
1658         v[1] = *V0;
1659         v[2] = *V1;
1660         v[3] = *V1;
1661         float width = linew * 0.25f;
1662         if (fabs(V0->y - V1->y) < 0.0001)
1663         {
1664           v[0].x = v[1].x = V0->x;
1665           v[2].x = v[3].x = V1->x;
1666
1667           width *= rdp.scale_y;
1668           v[0].y = v[2].y = V0->y - width;
1669           v[1].y = v[3].y = V0->y + width;
1670         }
1671         else if (fabs(V0->x - V1->x) < 0.0001)
1672         {
1673           v[0].y = v[1].y = V0->y;
1674           v[2].y = v[3].y = V1->y;
1675
1676           width *= rdp.scale_x;
1677           v[0].x = v[2].x = V0->x - width;
1678           v[1].x = v[3].x = V0->x + width;
1679         }
1680         else
1681         {
1682           float dx = V1->x - V0->x;
1683           float dy = V1->y - V0->y;
1684           float len = sqrtf(dx*dx + dy*dy);
1685           float wx = dy * width * rdp.scale_x / len;
1686           float wy = dx * width * rdp.scale_y / len;
1687           v[0].x = V0->x + wx;
1688           v[0].y = V0->y - wy;
1689           v[1].x = V0->x - wx;
1690           v[1].y = V0->y + wy;
1691           v[2].x = V1->x + wx;
1692           v[2].y = V1->y - wy;
1693           v[3].x = V1->x - wx;
1694           v[3].y = V1->y + wy;
1695         }
1696         grDrawTriangle(&v[0], &v[1], &v[2]);
1697         grDrawTriangle(&v[1], &v[2], &v[3]);
1698       }
1699       else
1700       {
1701         DepthBuffer(rdp.vtxbuf, n);
1702         if ((rdp.rm & 0xC10) == 0xC10)
1703           grDepthBiasLevel (-deltaZ);
1704         grDrawVertexArray (GR_TRIANGLE_FAN, n, rdp.vtx_buffer?(&vtx_list2):(&vtx_list1));
1705       }
1706     }
1707   }
1708
1709   if (_debugger.capture) add_tri (rdp.vtxbuf, n, TRI_TRIANGLE);
1710 }
1711
1712 void add_tri (VERTEX *v, int n, int type)
1713 {
1714   //FRDP ("ENTER (%f, %f, %f), (%f, %f, %f), (%f, %f, %f)\n", v[0].x, v[0].y, v[0].w,
1715   //  v[1].x, v[1].y, v[1].w, v[2].x, v[2].y, v[2].w);
1716
1717   // Debug capture
1718   if (_debugger.capture)
1719   {
1720     rdp.debug_n ++;
1721
1722     TRI_INFO *info = new TRI_INFO;
1723     info->nv = n;
1724     info->v = new VERTEX [n];
1725     memcpy (info->v, v, sizeof(VERTEX)*n);
1726     info->cycle_mode = rdp.cycle_mode;
1727     info->cycle1 = rdp.cycle1;
1728     info->cycle2 = rdp.cycle2;
1729     info->uncombined = rdp.uncombined;
1730     info->geom_mode = rdp.geom_mode;
1731     info->othermode_h = rdp.othermode_h;
1732     info->othermode_l = rdp.othermode_l;
1733     info->tri_n = rdp.tri_n;
1734     info->type = type;
1735
1736     for (int i=0; i<2; i++)
1737     {
1738       int j = rdp.cur_tile+i;
1739       if (i == 0)
1740         info->t[i].tmu = rdp.t0;
1741       else
1742         info->t[i].tmu = rdp.t1;
1743       info->t[i].cur_cache[0] = rdp.cur_cache_n[rdp.t0];
1744       info->t[i].cur_cache[1] = rdp.cur_cache_n[rdp.t1];
1745       info->t[i].format = rdp.tiles[j].format;
1746       info->t[i].size = rdp.tiles[j].size;
1747       info->t[i].width = rdp.tiles[j].width;
1748       info->t[i].height = rdp.tiles[j].height;
1749       info->t[i].line = rdp.tiles[j].line;
1750       info->t[i].palette = rdp.tiles[j].palette;
1751       info->t[i].clamp_s = rdp.tiles[j].clamp_s;
1752       info->t[i].clamp_t = rdp.tiles[j].clamp_t;
1753       info->t[i].mirror_s = rdp.tiles[j].mirror_s;
1754       info->t[i].mirror_t = rdp.tiles[j].mirror_t;
1755       info->t[i].shift_s = rdp.tiles[j].shift_s;
1756       info->t[i].shift_t = rdp.tiles[j].shift_t;
1757       info->t[i].mask_s = rdp.tiles[j].mask_s;
1758       info->t[i].mask_t = rdp.tiles[j].mask_t;
1759       info->t[i].ul_s = rdp.tiles[j].ul_s;
1760       info->t[i].ul_t = rdp.tiles[j].ul_t;
1761       info->t[i].lr_s = rdp.tiles[j].lr_s;
1762       info->t[i].lr_t = rdp.tiles[j].lr_t;
1763       info->t[i].t_ul_s = rdp.tiles[7].t_ul_s;
1764       info->t[i].t_ul_t = rdp.tiles[7].t_ul_t;
1765       info->t[i].t_lr_s = rdp.tiles[7].t_lr_s;
1766       info->t[i].t_lr_t = rdp.tiles[7].t_lr_t;
1767       info->t[i].scale_s = rdp.tiles[j].s_scale;
1768       info->t[i].scale_t = rdp.tiles[j].t_scale;
1769     }
1770
1771     info->fog_color = rdp.fog_color;
1772     info->fill_color = rdp.fill_color;
1773     info->prim_color = rdp.prim_color;
1774     info->blend_color = rdp.blend_color;
1775     info->env_color = rdp.env_color;
1776     info->prim_lodmin = rdp.prim_lodmin;
1777     info->prim_lodfrac = rdp.prim_lodfrac;
1778
1779     info->pNext = _debugger.tri_list;
1780     _debugger.tri_list = info;
1781
1782     if (_debugger.tri_last == NULL)
1783       _debugger.tri_last = _debugger.tri_list;
1784   }
1785 }
1786
1787 void update_scissor ()
1788 {
1789   if (rdp.update & UPDATE_SCISSOR)
1790   {
1791     rdp.update ^= UPDATE_SCISSOR;
1792
1793     // KILL the floating point error with 0.01f
1794     rdp.scissor.ul_x = (wxUint32)max(min((rdp.scissor_o.ul_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0);
1795     rdp.scissor.lr_x = (wxUint32)max(min((rdp.scissor_o.lr_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0);
1796     rdp.scissor.ul_y = (wxUint32)max(min((rdp.scissor_o.ul_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0);
1797     rdp.scissor.lr_y = (wxUint32)max(min((rdp.scissor_o.lr_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0);
1798     //grClipWindow specifies the hardware clipping window. Any pixels outside the clipping window are rejected.
1799     //Values are inclusive for minimum x and y values and exclusive for maximum x and y values.
1800 //    grClipWindow (rdp.scissor.ul_x?rdp.scissor.ul_x+1:0, rdp.scissor.ul_y?rdp.scissor.ul_y+1:0, rdp.scissor.lr_x, rdp.scissor.lr_y);
1801     if (fullscreen)
1802       grClipWindow (rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);
1803     FRDP (" |- scissor - (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y,
1804       rdp.scissor.lr_x, rdp.scissor.lr_y);
1805   }
1806 }
1807
1808 //
1809 // update - update states if they need it
1810 //
1811
1812 typedef struct
1813 {
1814   unsigned int  c2_m2b:2;
1815   unsigned int  c1_m2b:2;
1816   unsigned int  c2_m2a:2;
1817   unsigned int  c1_m2a:2;
1818   unsigned int  c2_m1b:2;
1819   unsigned int  c1_m1b:2;
1820   unsigned int  c2_m1a:2;
1821   unsigned int  c1_m1a:2;
1822 } rdp_blender_setting;
1823
1824 void update ()
1825 {
1826   LRDP ("-+ update called\n");
1827   // Check for rendermode changes
1828   // Z buffer
1829   if (rdp.render_mode_changed & 0x00000C30)
1830   {
1831     FRDP (" |- render_mode_changed zbuf - decal: %s, update: %s, compare: %s\n",
1832       str_yn[(rdp.othermode_l & 0x00000400)?1:0],
1833       str_yn[(rdp.othermode_l&0x00000020)?1:0],
1834       str_yn[(rdp.othermode_l&0x00000010)?1:0]);
1835
1836     rdp.render_mode_changed &= ~0x00000C30;
1837     rdp.update |= UPDATE_ZBUF_ENABLED;
1838
1839     // Update?
1840     if ((rdp.othermode_l & 0x00000020))
1841       rdp.flags |= ZBUF_UPDATE;
1842     else
1843       rdp.flags &= ~ZBUF_UPDATE;
1844
1845     // Compare?
1846     if (rdp.othermode_l & 0x00000010)
1847       rdp.flags |= ZBUF_COMPARE;
1848     else
1849       rdp.flags &= ~ZBUF_COMPARE;
1850   }
1851
1852   // Alpha compare
1853   if (rdp.render_mode_changed & 0x00001000)
1854   {
1855     FRDP (" |- render_mode_changed alpha compare - on: %s\n",
1856       str_yn[(rdp.othermode_l&0x00001000)?1:0]);
1857     rdp.render_mode_changed &= ~0x00001000;
1858     rdp.update |= UPDATE_ALPHA_COMPARE;
1859
1860     if (rdp.othermode_l & 0x00001000)
1861       rdp.flags |= ALPHA_COMPARE;
1862     else
1863       rdp.flags &= ~ALPHA_COMPARE;
1864   }
1865
1866   if (rdp.render_mode_changed & 0x00002000) // alpha cvg sel
1867   {
1868     FRDP (" |- render_mode_changed alpha cvg sel - on: %s\n",
1869       str_yn[(rdp.othermode_l&0x00002000)?1:0]);
1870     rdp.render_mode_changed &= ~0x00002000;
1871     rdp.update |= UPDATE_COMBINE;
1872     rdp.update |= UPDATE_ALPHA_COMPARE;
1873   }
1874
1875   // Force blend
1876   if (rdp.render_mode_changed & 0xFFFF0000)
1877   {
1878     FRDP (" |- render_mode_changed force_blend - %08lx\n", rdp.othermode_l&0xFFFF0000);
1879     rdp.render_mode_changed &= 0x0000FFFF;
1880
1881     rdp.fbl_a0 = (wxUint8)((rdp.othermode_l>>30)&0x3);
1882     rdp.fbl_b0 = (wxUint8)((rdp.othermode_l>>26)&0x3);
1883     rdp.fbl_c0 = (wxUint8)((rdp.othermode_l>>22)&0x3);
1884     rdp.fbl_d0 = (wxUint8)((rdp.othermode_l>>18)&0x3);
1885     rdp.fbl_a1 = (wxUint8)((rdp.othermode_l>>28)&0x3);
1886     rdp.fbl_b1 = (wxUint8)((rdp.othermode_l>>24)&0x3);
1887     rdp.fbl_c1 = (wxUint8)((rdp.othermode_l>>20)&0x3);
1888     rdp.fbl_d1 = (wxUint8)((rdp.othermode_l>>16)&0x3);
1889
1890     rdp.update |= UPDATE_COMBINE;
1891   }
1892
1893   // Combine MUST go before texture
1894   if ((rdp.update & UPDATE_COMBINE) && rdp.allow_combine)
1895   {
1896     TBUFF_COLOR_IMAGE * aTBuff[2] = {0, 0};
1897     if (rdp.aTBuffTex[0])
1898       aTBuff[rdp.aTBuffTex[0]->tile] = rdp.aTBuffTex[0];
1899     if (rdp.aTBuffTex[1])
1900       aTBuff[rdp.aTBuffTex[1]->tile] = rdp.aTBuffTex[1];
1901     rdp.aTBuffTex[0] = aTBuff[0];
1902     rdp.aTBuffTex[1] = aTBuff[1];
1903
1904     LRDP (" |-+ update_combine\n");
1905     Combine ();
1906   }
1907
1908   if (rdp.update & UPDATE_TEXTURE)  // note: UPDATE_TEXTURE and UPDATE_COMBINE are the same
1909   {
1910     rdp.tex_ctr ++;
1911     if (rdp.tex_ctr == 0xFFFFFFFF)
1912       rdp.tex_ctr = 0;
1913
1914     TexCache ();
1915         if (rdp.noise == RDP::noise_none)
1916       rdp.update ^= UPDATE_TEXTURE;
1917   }
1918
1919   if (fullscreen)
1920   {
1921     // Z buffer
1922     if (rdp.update & UPDATE_ZBUF_ENABLED)
1923     {
1924       // already logged above
1925       rdp.update ^= UPDATE_ZBUF_ENABLED;
1926
1927       if (((rdp.flags & ZBUF_ENABLED) || rdp.zsrc == 1) && rdp.cycle_mode < 2)
1928       {
1929         if (rdp.flags & ZBUF_COMPARE)
1930         {
1931           switch ((rdp.rm & 0xC00)>>10) {
1932             case 0:
1933               grDepthBiasLevel(0);
1934               grDepthBufferFunction (settings.zmode_compare_less ? GR_CMP_LESS : GR_CMP_LEQUAL);
1935               break;
1936             case 1:
1937               grDepthBiasLevel(-4);
1938               grDepthBufferFunction (settings.zmode_compare_less ? GR_CMP_LESS : GR_CMP_LEQUAL);
1939               break;
1940             case 2:
1941               grDepthBiasLevel(settings.ucode == 7 ? -4 : 0);
1942               grDepthBufferFunction (GR_CMP_LESS);
1943               break;
1944             case 3:
1945               // will be set dynamically per polygon
1946               //grDepthBiasLevel(-deltaZ);
1947               grDepthBufferFunction (GR_CMP_LEQUAL);
1948               break;
1949           }
1950         }
1951         else
1952         {
1953           grDepthBiasLevel(0);
1954           grDepthBufferFunction (GR_CMP_ALWAYS);
1955         }
1956
1957         if (rdp.flags & ZBUF_UPDATE)
1958           grDepthMask (FXTRUE);
1959         else
1960           grDepthMask (FXFALSE);
1961       }
1962       else
1963       {
1964         grDepthBiasLevel(0);
1965         grDepthBufferFunction (GR_CMP_ALWAYS);
1966         grDepthMask (FXFALSE);
1967       }
1968     }
1969
1970     // Alpha compare
1971     if (rdp.update & UPDATE_ALPHA_COMPARE)
1972     {
1973       // already logged above
1974       rdp.update ^= UPDATE_ALPHA_COMPARE;
1975
1976       //          if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && !force_full_alpha)
1977       //      if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && (rdp.blend_color&0xFF))
1978       if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && (!(rdp.othermode_l & 0x00004000) || (rdp.blend_color&0xFF)))
1979       {
1980         wxUint8 reference = (wxUint8)(rdp.blend_color&0xFF);
1981         grAlphaTestFunction (reference ? GR_CMP_GEQUAL : GR_CMP_GREATER);
1982         grAlphaTestReferenceValue (reference);
1983         FRDP (" |- alpha compare: blend: %02lx\n", reference);
1984       }
1985       else
1986       {
1987         if (rdp.flags & ALPHA_COMPARE)
1988         {
1989           if ((rdp.othermode_l & 0x5000) != 0x5000)
1990           {
1991             grAlphaTestFunction (GR_CMP_GEQUAL);
1992             grAlphaTestReferenceValue (0x20);//0xA0);
1993             LRDP (" |- alpha compare: 0x20\n");
1994           }
1995           else
1996           {
1997             grAlphaTestFunction (GR_CMP_GREATER);
1998             if (rdp.acmp == 3)
1999             {
2000               grAlphaTestReferenceValue ((wxUint8)(rdp.blend_color&0xFF));
2001               FRDP (" |- alpha compare: blend: %02lx\n", rdp.blend_color&0xFF);
2002             }
2003             else
2004             {
2005               grAlphaTestReferenceValue (0x00);
2006               LRDP (" |- alpha compare: 0x00\n");
2007             }
2008           }
2009         }
2010         else
2011         {
2012           grAlphaTestFunction (GR_CMP_ALWAYS);
2013           LRDP (" |- alpha compare: none\n");
2014         }
2015       }
2016       if (rdp.acmp == 3 && rdp.cycle_mode < 2)
2017       {
2018         if (grStippleModeExt != 0)
2019         {
2020           if (settings.old_style_adither || rdp.alpha_dither_mode != 3) {
2021             LRDP (" |- alpha compare: dither\n");
2022             grStippleModeExt(settings.stipple_mode);
2023           }
2024           else
2025             grStippleModeExt(GR_STIPPLE_DISABLE);
2026         }
2027       }
2028       else
2029       {
2030         if (grStippleModeExt)
2031         {
2032           //LRDP (" |- alpha compare: dither disabled\n");
2033           grStippleModeExt(GR_STIPPLE_DISABLE);
2034         }
2035       }
2036     }
2037     // Cull mode (leave this in for z-clipped triangles)
2038     if (rdp.update & UPDATE_CULL_MODE)
2039     {
2040       rdp.update ^= UPDATE_CULL_MODE;
2041       wxUint32 mode = (rdp.flags & CULLMASK) >> CULLSHIFT;
2042       FRDP (" |- cull_mode - mode: %s\n", str_cull[mode]);
2043       switch (mode)
2044       {
2045       case 0: // cull none
2046       case 3: // cull both
2047         grCullMode(GR_CULL_DISABLE);
2048         break;
2049       case 1: // cull front
2050         //        grCullMode(GR_CULL_POSITIVE);
2051         grCullMode(GR_CULL_NEGATIVE);
2052         break;
2053       case 2: // cull back
2054         //        grCullMode (GR_CULL_NEGATIVE);
2055         grCullMode (GR_CULL_POSITIVE);
2056         break;
2057       }
2058     }
2059
2060     //Added by Gonetz.
2061     if (settings.fog && (rdp.update & UPDATE_FOG_ENABLED))
2062     {
2063       rdp.update ^= UPDATE_FOG_ENABLED;
2064
2065       wxUint16 blender = (wxUint16)(rdp.othermode_l >> 16);
2066       if (rdp.flags & FOG_ENABLED)
2067       {
2068         rdp_blender_setting &bl = *(rdp_blender_setting*)(&(blender));
2069         if((rdp.fog_multiplier > 0) && (bl.c1_m1a==3 || bl.c1_m2a == 3 || bl.c2_m1a == 3 || bl.c2_m2a == 3))
2070         {
2071           grFogColorValue(rdp.fog_color);
2072           grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
2073           rdp.fog_mode = RDP::fog_enabled;
2074           LRDP("fog enabled \n");
2075         }
2076         else
2077         {
2078           LRDP("fog disabled in blender\n");
2079           rdp.fog_mode = RDP::fog_disabled;
2080           grFogMode (GR_FOG_DISABLE);
2081         }
2082       }
2083       else if (blender == 0xc410 || blender == 0xc411 || blender == 0xf500)
2084       {
2085         grFogColorValue(rdp.fog_color);
2086         grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
2087         rdp.fog_mode = RDP::fog_blend;
2088         LRDP("fog blend \n");
2089       }
2090       else if (blender == 0x04d1)
2091       {
2092         grFogColorValue(rdp.fog_color);
2093         grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
2094         rdp.fog_mode = RDP::fog_blend_inverse;
2095         LRDP("fog blend \n");
2096       }
2097       else
2098       {
2099         LRDP("fog disabled\n");
2100         rdp.fog_mode = RDP::fog_disabled;
2101         grFogMode (GR_FOG_DISABLE);
2102       }
2103     }
2104   }
2105
2106   if (rdp.update & UPDATE_VIEWPORT)
2107   {
2108     rdp.update ^= UPDATE_VIEWPORT;
2109     if (fullscreen)
2110     {
2111       float scale_x = (float)fabs(rdp.view_scale[0]);
2112       float scale_y = (float)fabs(rdp.view_scale[1]);
2113
2114       rdp.clip_min_x = max((rdp.view_trans[0] - scale_x + rdp.offset_x) / rdp.clip_ratio, 0.0f);
2115       rdp.clip_min_y = max((rdp.view_trans[1] - scale_y + rdp.offset_y) / rdp.clip_ratio, 0.0f);
2116       rdp.clip_max_x = min((rdp.view_trans[0] + scale_x + rdp.offset_x) * rdp.clip_ratio, settings.res_x);
2117       rdp.clip_max_y = min((rdp.view_trans[1] + scale_y + rdp.offset_y) * rdp.clip_ratio, settings.res_y);
2118
2119       FRDP (" |- viewport - (%d, %d, %d, %d)\n", (wxUint32)rdp.clip_min_x, (wxUint32)rdp.clip_min_y, (wxUint32)rdp.clip_max_x, (wxUint32)rdp.clip_max_y);
2120       if (!rdp.scissor_set)
2121       {
2122         rdp.scissor.ul_x = (wxUint32)rdp.clip_min_x;
2123         rdp.scissor.lr_x = (wxUint32)rdp.clip_max_x;
2124         rdp.scissor.ul_y = (wxUint32)rdp.clip_min_y;
2125         rdp.scissor.lr_y = (wxUint32)rdp.clip_max_y;
2126         grClipWindow (rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);
2127       }
2128     }
2129   }
2130
2131   if (rdp.update & UPDATE_SCISSOR)
2132     update_scissor ();
2133
2134   LRDP (" + update end\n");
2135 }
2136
2137 void set_message_combiner ()
2138 {
2139   grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
2140     GR_COMBINE_FACTOR_ONE,
2141     GR_COMBINE_LOCAL_NONE,
2142     GR_COMBINE_OTHER_TEXTURE,
2143     FXFALSE);
2144   grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
2145     GR_COMBINE_FACTOR_ONE,
2146     GR_COMBINE_LOCAL_NONE,
2147     GR_COMBINE_OTHER_TEXTURE,
2148     FXFALSE);
2149   if (settings.buff_clear && (settings.show_fps & 0x08))
2150     grAlphaBlendFunction (GR_BLEND_SRC_ALPHA,
2151     GR_BLEND_ONE_MINUS_SRC_ALPHA,
2152     GR_BLEND_ZERO,
2153     GR_BLEND_ZERO);
2154   else
2155     grAlphaBlendFunction (GR_BLEND_ONE,
2156     GR_BLEND_ZERO,
2157     GR_BLEND_ZERO,
2158     GR_BLEND_ZERO);
2159   grAlphaTestFunction (GR_CMP_ALWAYS);
2160   if (grStippleModeExt)
2161   {
2162     grStippleModeExt(GR_STIPPLE_DISABLE);
2163   }
2164   grTexFilterMode (0, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR);
2165   grTexCombine (GR_TMU1,
2166     GR_COMBINE_FUNCTION_NONE,
2167     GR_COMBINE_FACTOR_NONE,
2168     GR_COMBINE_FUNCTION_NONE,
2169     GR_COMBINE_FACTOR_NONE,
2170     FXFALSE, FXFALSE);
2171   grTexCombine (GR_TMU0,
2172     GR_COMBINE_FUNCTION_LOCAL,
2173     GR_COMBINE_FACTOR_NONE,
2174     GR_COMBINE_FUNCTION_LOCAL,
2175     GR_COMBINE_FACTOR_NONE,
2176     FXFALSE, FXFALSE);
2177   grTexSource(GR_TMU0,
2178     voodoo.tex_min_addr[GR_TMU0] + offset_font,
2179     GR_MIPMAPLEVELMASK_BOTH,
2180     &fontTex);
2181   grFogMode (GR_FOG_DISABLE);
2182 }
2183