ALL: Huge upstream synch + PerRom DelaySI & CountPerOp parameters
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glide64 / Util.cpp
CommitLineData
98e75f2d 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
52VERTEX *vtx_list1[32]; // vertex indexing
53VERTEX *vtx_list2[32];
54
55//
56// util_init - initialize data for the functions in this file
57//
58
59void 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
68static wxUint32 u_cull_mode = 0;
69
70//software backface culling. Gonetz
71// mega modifications by Dave2001
72int 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
164void 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
283static int dzdx = 0;
284static int deltaZ = 0;
285VERTEX **org_vtx;
286
287void 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//*
668static 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//
680static 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
751static void render_tri (wxUint16 linew, int old_interpolate);
752
753void 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
824void 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//*
846static 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
883typedef struct {
884 float d; //*SEB* was doubles
885 float x;
886 float y;
887} LineEuqationType;
888
889static 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
894static 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
918static 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
960static 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
1035float 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
1050static 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/*
1080std::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{
1084va_list ap;
1085va_start(ap, fmt);
1086vsprintf(out_buf, fmt, ap);
1087LOGG(out_buf);
1088va_end(ap);
1089}
1090//*/
1091//#define LOGG(x)
1092//#define FRDP2(x)
1093
1094
1095void 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
1491static 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
1712void 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
1787void 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
1812typedef 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
1824void 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
2137void 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