Replace Tmem_nasm.asm with C++ code. Patch by pyro.
[Glide64.git] / Util.cpp
blobd57847cfccfc9647c339d9f9c3dd82a0b79dcb6e
1 /*
2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002 Dave2001
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 //****************************************************************
22 // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)
23 // Project started on December 29th, 2001
25 // To modify Glide64:
26 // * 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.
27 // * 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.
29 // Official Glide64 development channel: #Glide64 on EFnet
31 // Original author: Dave2001 (Dave2999@hotmail.com)
32 // Other authors: Gonetz, Gugaman
34 //****************************************************************
36 #include "Gfx1.3.h"
37 #include "Util.h"
38 #include "Combine.h"
39 #include "3dmath.h"
40 #include "Debugger.h"
41 #include "TexCache.h"
42 #include "DepthBufferRender.h"
44 #ifndef _WIN32
45 #include <string.h>
46 #include <stdlib.h>
47 #endif // _WIN32
49 #define Vj rdp.vtxbuf2[j]
50 #define Vi rdp.vtxbuf2[i]
52 VERTEX *vtx_list1[32]; // vertex indexing
53 VERTEX *vtx_list2[32];
56 // util_init - initialize data for the functions in this file
59 void util_init ()
61 for (int i=0; i<32; i++)
63 vtx_list1[i] = &rdp.vtx1[i];
64 vtx_list2[i] = &rdp.vtx2[i];
68 //software backface culling. Gonetz
69 // mega modifications by Dave2001
70 BOOL cull_tri(VERTEX **v) // type changed to VERTEX** [Dave2001]
72 int i;
74 if (v[0]->scr_off & v[1]->scr_off & v[2]->scr_off)
76 RDP (" clipped\n");
77 return TRUE;
80 // Triangle can't be culled, if it need clipping
81 BOOL draw = FALSE;
83 //fix for sun in zeldas
84 BOOL fix_i_uv = FALSE;
85 if (settings.zelda && rdp.rm == 0x0c184241 && rdp.tiles[rdp.cur_tile].format == 4)
86 fix_i_uv = TRUE;
88 for (i=0; i<3; i++)
90 if (!v[i]->screen_translated)
92 v[i]->sx = rdp.view_trans[0] + v[i]->x_w * rdp.view_scale[0];
93 v[i]->sy = rdp.view_trans[1] + v[i]->y_w * rdp.view_scale[1];
94 v[i]->sz = rdp.view_trans[2] + v[i]->z_w * rdp.view_scale[2];
95 if ((fix_i_uv) && (v[i]->uv_fixed == 0))
97 v[i]->uv_fixed = 1;
98 v[i]->ou *= 0.5f;
99 v[i]->ov *= 0.5f;
101 v[i]->screen_translated = 1;
103 if (v[i]->w < 0.01f) //need clip_z. can't be culled now
104 draw = 1;
107 if (settings.fix_tex_coord)
108 fix_tex_coord (v);
109 if (draw) return FALSE; // z-clipping, can't be culled by software
111 #define SW_CULLING
112 #ifdef SW_CULLING
113 //now we need to check, if triangle's vertices are in clockwise order
114 // Use precalculated x/z and y/z coordinates.
115 float x1 = v[0]->sx - v[1]->sx;
116 float y1 = v[0]->sy - v[1]->sy;
117 float x2 = v[2]->sx - v[1]->sx;
118 float y2 = v[2]->sy - v[1]->sy;
120 DWORD mode = (rdp.flags & CULLMASK) >> CULLSHIFT;
121 switch (mode)
123 case 1: // cull front
124 // if ((x1*y2 - y1*x2) < 0.0f) //counter-clockwise, positive
125 if ((y1*x2-x1*y2) < 0.0f) //counter-clockwise, positive
127 RDP (" culled!\n");
128 return TRUE;
130 return FALSE;
131 case 2: // cull back
132 // if ((x1*y2 - y1*x2) >= 0.0f) //clockwise, negative
133 if ((y1*x2-x1*y2) >= 0.0f) //clockwise, negative
135 RDP (" culled!\n");
136 return TRUE;
138 return FALSE;
140 #endif
142 return FALSE;
146 void apply_shade_mods (VERTEX *v)
148 float col[4];
149 DWORD cmb;
150 memcpy (col, rdp.col, 16);
152 if (rdp.cmb_flags)
154 cmb = rdp.cmb_flags;
155 if (cmb & CMB_SET)
157 if (col[0] > 1.0f) col[0] = 1.0f;
158 if (col[1] > 1.0f) col[1] = 1.0f;
159 if (col[2] > 1.0f) col[2] = 1.0f;
160 if (col[0] < 0.0f) col[0] = 0.0f;
161 if (col[1] < 0.0f) col[1] = 0.0f;
162 if (col[2] < 0.0f) col[2] = 0.0f;
163 v->r = (BYTE)(255.0f * col[0]);
164 v->g = (BYTE)(255.0f * col[1]);
165 v->b = (BYTE)(255.0f * col[2]);
167 if (cmb & CMB_A_SET)
169 if (col[3] > 1.0f) col[3] = 1.0f;
170 if (col[3] < 0.0f) col[3] = 0.0f;
171 v->a = (BYTE)(255.0f * col[3]);
173 if (cmb & CMB_SETSHADE_SHADEALPHA)
175 v->r = v->g = v->b = v->a;
177 if (cmb & CMB_SUB)
179 int r = v->r - (int)(255.0f * rdp.coladd[0]);
180 int g = v->g - (int)(255.0f * rdp.coladd[1]);
181 int b = v->b - (int)(255.0f * rdp.coladd[2]);
182 if (r < 0) r = 0;
183 if (g < 0) g = 0;
184 if (b < 0) b = 0;
185 v->r = (BYTE)r;
186 v->g = (BYTE)g;
187 v->b = (BYTE)b;
189 if (cmb & CMB_A_SUB)
191 int a = v->a - (int)(255.0f * rdp.coladd[3]);
192 if (a < 0) a = 0;
193 v->a = (BYTE)a;
196 if (cmb & CMB_ADD)
198 int r = v->r + (int)(255.0f * rdp.coladd[0]);
199 int g = v->g + (int)(255.0f * rdp.coladd[1]);
200 int b = v->b + (int)(255.0f * rdp.coladd[2]);
201 if (r > 255) r = 255;
202 if (g > 255) g = 255;
203 if (b > 255) b = 255;
204 v->r = (BYTE)r;
205 v->g = (BYTE)g;
206 v->b = (BYTE)b;
208 if (cmb & CMB_A_ADD)
210 int a = v->a + (int)(255.0f * rdp.coladd[3]);
211 if (a > 255) a = 255;
212 v->a = (BYTE)a;
214 if (cmb & CMB_COL_SUB_OWN)
216 int r = (BYTE)(255.0f * rdp.coladd[0]) - v->r;
217 int g = (BYTE)(255.0f * rdp.coladd[1]) - v->g;
218 int b = (BYTE)(255.0f * rdp.coladd[2]) - v->b;
219 if (r < 0) r = 0;
220 if (g < 0) g = 0;
221 if (b < 0) b = 0;
222 v->r = (BYTE)r;
223 v->g = (BYTE)g;
224 v->b = (BYTE)b;
226 if (cmb & CMB_MULT)
228 if (col[0] > 1.0f) col[0] = 1.0f;
229 if (col[1] > 1.0f) col[1] = 1.0f;
230 if (col[2] > 1.0f) col[2] = 1.0f;
231 if (col[0] < 0.0f) col[0] = 0.0f;
232 if (col[1] < 0.0f) col[1] = 0.0f;
233 if (col[2] < 0.0f) col[2] = 0.0f;
234 v->r = (BYTE)(v->r * col[0]);
235 v->g = (BYTE)(v->g * col[1]);
236 v->b = (BYTE)(v->b * col[2]);
238 if (cmb & CMB_A_MULT)
240 if (col[3] > 1.0f) col[3] = 1.0f;
241 if (col[3] < 0.0f) col[3] = 0.0f;
242 v->a = (BYTE)(v->a * col[3]);
244 if (cmb & CMB_MULT_OWN_ALPHA)
246 float percent = v->a / 255.0f;
247 v->r = (BYTE)(v->r * percent);
248 v->g = (BYTE)(v->g * percent);
249 v->b = (BYTE)(v->b * percent);
251 v->shade_mods_allowed = 0;
253 cmb = rdp.cmb_flags_2;
254 if (cmb & CMB_INTER)
256 v->r = (BYTE)(rdp.col_2[0] * rdp.shade_factor * 255.0f + v->r * (1.0f - rdp.shade_factor));
257 v->g = (BYTE)(rdp.col_2[1] * rdp.shade_factor * 255.0f + v->g * (1.0f - rdp.shade_factor));
258 v->b = (BYTE)(rdp.col_2[2] * rdp.shade_factor * 255.0f + v->b * (1.0f - rdp.shade_factor));
259 v->shade_mods_allowed = 0;
264 static long dzdx = 0;
266 void DrawTri (VERTEX **vtx, WORD linew)
268 if (settings.fb_depth_render && linew == 0)
270 float X0 = vtx[0]->sx / rdp.scale_x;
271 float Y0 = vtx[0]->sy / rdp.scale_y;
272 float X1 = vtx[1]->sx / rdp.scale_x;
273 float Y1 = vtx[1]->sy / rdp.scale_y;
274 float X2 = vtx[2]->sx / rdp.scale_x;
275 float Y2 = vtx[2]->sy / rdp.scale_y;
276 float diff12 = Y1 - Y2;
277 float diff02 = Y0 - Y2;
280 double denom = ((X0 - X2) * diff12 -
281 (X1 - X2) * diff02);
282 if(denom*denom > 0.0)
284 dzdx = (long)(((vtx[0]->sz - vtx[2]->sz) * diff12 -
285 (vtx[1]->sz - vtx[2]->sz) * diff02) / denom * 65536.0);
287 else
288 dzdx = 0;
290 else
291 dzdx = 0;
293 for (int i=0; i<3; i++)
295 VERTEX *v = vtx[i];
297 if (v->uv_calculated != rdp.tex_ctr)
299 #ifdef EXTREME_LOGGING
300 FRDP(" * CALCULATING VERTEX U/V: %d\n", v->number);
301 #endif
302 v->uv_calculated = rdp.tex_ctr;
304 if (!(rdp.geom_mode & 0x00020000))
306 if (!(rdp.geom_mode & 0x00000200))
308 if (rdp.geom_mode & 0x00000004) // flat shading
310 #ifdef EXTREME_LOGGING
311 RDP(" * Flat shaded\n");
312 #endif
313 v->a = vtx[0]->a;
314 v->b = vtx[0]->b;
315 v->g = vtx[0]->g;
316 v->r = vtx[0]->r;
318 else // prim color
320 #ifdef EXTREME_LOGGING
321 FRDP(" * Prim shaded %08lx\n", rdp.prim_color);
322 #endif
323 v->a = (BYTE)(rdp.prim_color & 0xFF);
324 v->b = (BYTE)((rdp.prim_color >> 8) & 0xFF);
325 v->g = (BYTE)((rdp.prim_color >> 16) & 0xFF);
326 v->r = (BYTE)((rdp.prim_color >> 24) & 0xFF);
331 // Fix texture coordinates
332 v->u1 = v->u0 = v->ou;
333 v->v1 = v->v0 = v->ov;
335 if (rdp.tex >= 1 && rdp.cur_cache[0])
337 if (rdp.hires_tex && rdp.hires_tex->tile == 0)
339 v->u0 += rdp.hires_tex->u_shift + rdp.hires_tex->tile_uls;
340 v->v0 += rdp.hires_tex->v_shift + rdp.hires_tex->tile_ult;
343 if (rdp.tiles[rdp.cur_tile].shift_s)
345 if (rdp.tiles[rdp.cur_tile].shift_s > 10)
346 v->u0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s));
347 else
348 v->u0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_s);
350 if (rdp.tiles[rdp.cur_tile].shift_t)
352 if (rdp.tiles[rdp.cur_tile].shift_t > 10)
353 v->v0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t));
354 else
355 v->v0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_t);
358 if (rdp.hires_tex && rdp.hires_tex->tile == 0)
360 if (rdp.hires_tex->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s)
361 v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;
362 v->u0 *= rdp.hires_tex->u_scale;
363 v->v0 *= rdp.hires_tex->u_scale;
364 v->u0 -= 0.45f;
365 v->v0 -= 0.45f;
366 FRDP("hires_tex t0: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u0, v->v0);
368 else
370 v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;
371 v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t;
372 v->u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * v->u0;
373 v->v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * v->v0;
375 v->u0_w = v->u0 / v->w;
376 v->v0_w = v->v0 / v->w;
379 if (rdp.tex >= 2 && rdp.cur_cache[1])
381 if (rdp.hires_tex && rdp.hires_tex->tile == 1)
383 v->u1 += rdp.hires_tex->u_shift + rdp.hires_tex->tile_uls;
384 v->v1 += rdp.hires_tex->v_shift + rdp.hires_tex->tile_ult;
386 if (rdp.tiles[rdp.cur_tile+1].shift_s)
388 if (rdp.tiles[rdp.cur_tile+1].shift_s > 10)
389 v->u1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s));
390 else
391 v->u1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_s);
393 if (rdp.tiles[rdp.cur_tile+1].shift_t)
395 if (rdp.tiles[rdp.cur_tile+1].shift_t > 10)
396 v->v1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t));
397 else
398 v->v1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_t);
401 if (rdp.hires_tex && rdp.hires_tex->tile == 1)
403 if (rdp.hires_tex->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s)
404 v->u1 -= rdp.tiles[rdp.cur_tile].f_ul_s;
405 v->u1 *= rdp.hires_tex->u_scale;
406 v->v1 *= rdp.hires_tex->u_scale;
407 v->u1 -= 0.45f;
408 v->v1 -= 0.45f;
409 FRDP("hires_tex t1: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u0, v->v0);
411 else
413 v->u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s;
414 v->v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t;
415 v->u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * v->u1;
416 v->v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * v->v1;
419 v->u1_w = v->u1 / v->w;
420 v->v1_w = v->v1 / v->w;
422 // 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);
424 if (v->shade_mods_allowed)
425 apply_shade_mods (v);
426 } //for
428 rdp.clip = 0;
430 if ((vtx[0]->scr_off & 16) ||
431 (vtx[1]->scr_off & 16) ||
432 (vtx[2]->scr_off & 16))
433 rdp.clip |= CLIP_ZMIN;
435 vtx[0]->not_zclipped = vtx[1]->not_zclipped = vtx[2]->not_zclipped = 1;
437 if (rdp.cur_cache[0] && (rdp.tex & 1) && (rdp.cur_cache[0]->splits > 1) && !rdp.hires_tex && !rdp.clip)
439 int index,i,j, min_256,max_256, cur_256,left_256,right_256;
440 float percent;
442 min_256 = min((int)vtx[0]->u0,(int)vtx[1]->u0); // bah, don't put two mins on one line
443 min_256 = min(min_256,(int)vtx[2]->u0) >> 8; // or it will be calculated twice
445 max_256 = max((int)vtx[0]->u0,(int)vtx[1]->u0); // not like it makes much difference
446 max_256 = max(max_256,(int)vtx[2]->u0) >> 8; // anyway :P
448 for (cur_256=min_256; cur_256<=max_256; cur_256++)
450 left_256 = cur_256 << 8;
451 right_256 = (cur_256+1) << 8;
453 // Set vertex buffers
454 rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1
455 rdp.vtxbuf2 = rdp.vtx2;
456 rdp.vtx_buffer = 0;
457 rdp.n_global = 3;
458 index = 0;
460 // ** Left plane **
461 for (i=0; i<3; i++)
463 j = i+1;
464 if (j == 3) j = 0;
466 VERTEX *v1 = vtx[i];
467 VERTEX *v2 = vtx[j];
469 if (v1->u0 >= left_256)
471 if (v2->u0 >= left_256) // Both are in, save the last one
473 rdp.vtxbuf[index] = *v2;
474 rdp.vtxbuf[index].u0 -= left_256;
475 rdp.vtxbuf[index++].v0 += rdp.cur_cache[0]->c_scl_y * (cur_256 * rdp.cur_cache[0]->splitheight);
477 else // First is in, second is out, save intersection
479 percent = (left_256 - v1->u0) / (v2->u0 - v1->u0);
480 rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent;
481 rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent;
482 rdp.vtxbuf[index].z = v1->z + (v2->z - v1->z) * percent;
483 rdp.vtxbuf[index].w = v1->w + (v2->w - v1->w) * percent;
484 rdp.vtxbuf[index].f = v1->f + (v2->f - v1->f) * percent;
485 rdp.vtxbuf[index].u0 = 0.5f;
486 rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent +
487 rdp.cur_cache[0]->c_scl_y * cur_256 * rdp.cur_cache[0]->splitheight;
488 rdp.vtxbuf[index].u1 = v1->u1 + (v2->u1 - v1->u1) * percent;
489 rdp.vtxbuf[index].v1 = v1->v1 + (v2->v1 - v1->v1) * percent;
490 rdp.vtxbuf[index].b = (BYTE)(v1->b + (v2->b - v1->b) * percent);
491 rdp.vtxbuf[index].g = (BYTE)(v1->g + (v2->g - v1->g) * percent);
492 rdp.vtxbuf[index].r = (BYTE)(v1->r + (v2->r - v1->r) * percent);
493 rdp.vtxbuf[index++].a = (BYTE)(v1->a + (v2->a - v1->a) * percent);
496 else
498 //if (v2->u0 < left_256) // Both are out, save nothing
499 if (v2->u0 >= left_256) // First is out, second is in, save intersection & in point
501 percent = (left_256 - v2->u0) / (v1->u0 - v2->u0);
502 rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent;
503 rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent;
504 rdp.vtxbuf[index].z = v2->z + (v1->z - v2->z) * percent;
505 rdp.vtxbuf[index].w = v2->w + (v1->w - v2->w) * percent;
506 rdp.vtxbuf[index].f = v2->f + (v1->f - v2->f) * percent;
507 rdp.vtxbuf[index].u0 = 0.5f;
508 rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent +
509 rdp.cur_cache[0]->c_scl_y * cur_256 * rdp.cur_cache[0]->splitheight;
510 rdp.vtxbuf[index].u1 = v2->u1 + (v1->u1 - v2->u1) * percent;
511 rdp.vtxbuf[index].v1 = v2->v1 + (v1->v1 - v2->v1) * percent;
512 rdp.vtxbuf[index].b = (BYTE)(v2->b + (v1->b - v2->b) * percent);
513 rdp.vtxbuf[index].g = (BYTE)(v2->g + (v1->g - v2->g) * percent);
514 rdp.vtxbuf[index].r = (BYTE)(v2->r + (v1->r - v2->r) * percent);
515 rdp.vtxbuf[index++].a = (BYTE)(v2->a + (v1->a - v2->a) * percent);
517 // Save the in point
518 rdp.vtxbuf[index] = *v2;
519 rdp.vtxbuf[index].u0 -= left_256;
520 rdp.vtxbuf[index++].v0 += rdp.cur_cache[0]->c_scl_y * (cur_256 * rdp.cur_cache[0]->splitheight);
524 rdp.n_global = index;
526 rdp.vtxbuf = rdp.vtx2; // now vtx1 holds the value, & vtx2 is the destination
527 rdp.vtxbuf2 = rdp.vtx1;
528 rdp.vtx_buffer ^= 1;
529 index = 0;
531 for (i=0; i<rdp.n_global; i++)
533 j = i+1;
534 if (j == rdp.n_global) j = 0;
536 VERTEX *v1 = &rdp.vtxbuf2[i];
537 VERTEX *v2 = &rdp.vtxbuf2[j];
539 // ** Right plane **
540 if (v1->u0 <= 256.0f)
542 if (v2->u0 <= 256.0f) // Both are in, save the last one
544 rdp.vtxbuf[index] = *v2;
545 rdp.vtxbuf[index++].not_zclipped = 0;
547 else // First is in, second is out, save intersection
549 percent = (right_256 - v1->u0) / (v2->u0 - v1->u0);
550 rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent;
551 rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent;
552 rdp.vtxbuf[index].z = v1->z + (v2->z - v1->z) * percent;
553 rdp.vtxbuf[index].w = v1->w + (v2->w - v1->w) * percent;
554 rdp.vtxbuf[index].f = v1->f + (v2->f - v1->f) * percent;
555 rdp.vtxbuf[index].u0 = 255.5f;
556 rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent;
557 rdp.vtxbuf[index].u1 = v1->u1 + (v2->u1 - v1->u1) * percent;
558 rdp.vtxbuf[index].v1 = v1->v1 + (v2->v1 - v1->v1) * percent;
559 rdp.vtxbuf[index].b = (BYTE)(v1->b + (v2->b - v1->b) * percent);
560 rdp.vtxbuf[index].g = (BYTE)(v1->g + (v2->g - v1->g) * percent);
561 rdp.vtxbuf[index].r = (BYTE)(v1->r + (v2->r - v1->r) * percent);
562 rdp.vtxbuf[index].a = (BYTE)(v1->a + (v2->a - v1->a) * percent);
563 rdp.vtxbuf[index++].not_zclipped = 0;
566 else
568 //if (v2->u0 > 256.0f) // Both are out, save nothing
569 if (v2->u0 <= 256.0f) // First is out, second is in, save intersection & in point
571 percent = (right_256 - v2->u0) / (v1->u0 - v2->u0);
572 rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent;
573 rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent;
574 rdp.vtxbuf[index].z = v2->z + (v1->z - v2->z) * percent;
575 rdp.vtxbuf[index].w = v2->w + (v1->w - v2->w) * percent;
576 rdp.vtxbuf[index].f = v2->f + (v1->f - v2->f) * percent;
577 rdp.vtxbuf[index].u0 = 255.5f;
578 rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent;
579 rdp.vtxbuf[index].u1 = v2->u1 + (v1->u1 - v2->u1) * percent;
580 rdp.vtxbuf[index].v1 = v2->v1 + (v1->v1 - v2->v1) * percent;
581 rdp.vtxbuf[index].b = (BYTE)(v2->b + (v1->b - v2->b) * percent);
582 rdp.vtxbuf[index].g = (BYTE)(v2->g + (v1->g - v2->g) * percent);
583 rdp.vtxbuf[index].r = (BYTE)(v2->r + (v1->r - v2->r) * percent);
584 rdp.vtxbuf[index].a = (BYTE)(v2->a + (v1->a - v2->a) * percent);
585 rdp.vtxbuf[index++].not_zclipped = 0;
587 // Save the in point
588 rdp.vtxbuf[index] = *v2;
589 rdp.vtxbuf[index++].not_zclipped = 0;
593 rdp.n_global = index;
595 do_triangle_stuff (linew);
598 else
600 // Set vertex buffers
601 rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1
602 rdp.vtxbuf2 = rdp.vtx2;
603 rdp.vtx_buffer = 0;
604 rdp.n_global = 3;
606 rdp.vtxbuf[0] = *vtx[0];
607 rdp.vtxbuf[1] = *vtx[1];
608 rdp.vtxbuf[2] = *vtx[2];
610 do_triangle_stuff (linew);
614 void do_triangle_stuff (WORD linew) // what else?? do the triangle stuff :P (to keep from writing code twice)
616 int i;
618 // if (rdp.zsrc != 1)
619 clip_z ();
621 for (i=0; i<rdp.n_global; i++)
623 if (rdp.vtxbuf[i].not_zclipped)// && rdp.zsrc != 1)
625 #ifdef EXTREME_LOGGING
626 FRDP (" * NOT ZCLIPPPED: %d\n", rdp.vtxbuf[i].number);
627 #endif
628 rdp.vtxbuf[i].x = rdp.vtxbuf[i].sx;
629 rdp.vtxbuf[i].y = rdp.vtxbuf[i].sy;
630 rdp.vtxbuf[i].z = rdp.vtxbuf[i].sz;
631 rdp.vtxbuf[i].q = rdp.vtxbuf[i].oow;
632 rdp.vtxbuf[i].u0 = rdp.vtxbuf[i].u0_w;
633 rdp.vtxbuf[i].v0 = rdp.vtxbuf[i].v0_w;
634 rdp.vtxbuf[i].u1 = rdp.vtxbuf[i].u1_w;
635 rdp.vtxbuf[i].v1 = rdp.vtxbuf[i].v1_w;
637 else
639 #ifdef EXTREME_LOGGING
640 FRDP (" * ZCLIPPED: %d\n", rdp.vtxbuf[i].number);
641 #endif
642 rdp.vtxbuf[i].q = 1.0f / rdp.vtxbuf[i].w;
643 rdp.vtxbuf[i].x = rdp.view_trans[0] + rdp.vtxbuf[i].x * rdp.vtxbuf[i].q * rdp.view_scale[0];
644 rdp.vtxbuf[i].y = rdp.view_trans[1] + rdp.vtxbuf[i].y * rdp.vtxbuf[i].q * rdp.view_scale[1];
645 rdp.vtxbuf[i].z = rdp.view_trans[2] + rdp.vtxbuf[i].z * rdp.vtxbuf[i].q * rdp.view_scale[2];
646 if (rdp.tex >= 1)
648 rdp.vtxbuf[i].u0 *= rdp.vtxbuf[i].q;
649 rdp.vtxbuf[i].v0 *= rdp.vtxbuf[i].q;
651 if (rdp.tex >= 2)
653 rdp.vtxbuf[i].u1 *= rdp.vtxbuf[i].q;
654 rdp.vtxbuf[i].v1 *= rdp.vtxbuf[i].q;
658 if (rdp.zsrc == 1)
659 rdp.vtxbuf[i].z = rdp.prim_depth;
661 // Don't remove clipping, or it will freeze
662 if (rdp.vtxbuf[i].x > rdp.scissor.lr_x) rdp.clip |= CLIP_XMAX;
663 if (rdp.vtxbuf[i].x < rdp.scissor.ul_x) rdp.clip |= CLIP_XMIN;
664 if (rdp.vtxbuf[i].y > rdp.scissor.lr_y) rdp.clip |= CLIP_YMAX;
665 if (rdp.vtxbuf[i].y < rdp.scissor.ul_y) rdp.clip |= CLIP_YMIN;
668 clip_tri (linew);
671 void do_triangle_stuff_2 (WORD linew)
673 rdp.clip = 0;
675 for (int i=0; i<rdp.n_global; i++)
677 // Don't remove clipping, or it will freeze
678 if (rdp.vtxbuf[i].x > rdp.scissor.lr_x) rdp.clip |= CLIP_XMAX;
679 if (rdp.vtxbuf[i].x < rdp.scissor.ul_x) rdp.clip |= CLIP_XMIN;
680 if (rdp.vtxbuf[i].y > rdp.scissor.lr_y) rdp.clip |= CLIP_YMAX;
681 if (rdp.vtxbuf[i].y < rdp.scissor.ul_y) rdp.clip |= CLIP_YMIN;
684 clip_tri (linew);
688 // clip_z - clips along the z-axis, also copies the vertex buffer for clip_tri
689 // * ALWAYS * processes it, even if it does not need z-clipping. It needs
690 // to copy the buffer anyway.
693 void clip_z ()
695 int i,j,index,n=rdp.n_global;
696 float percent;
698 if (rdp.clip & CLIP_ZMIN)
700 // Swap vertex buffers
701 VERTEX *tmp = rdp.vtxbuf2;
702 rdp.vtxbuf2 = rdp.vtxbuf;
703 rdp.vtxbuf = tmp;
704 rdp.vtx_buffer ^= 1;
705 index = 0;
707 // Check the vertices for clipping
708 for (i=0; i<n; i++)
710 j = i+1;
711 if (j == n) j = 0;
713 if (Vi.w >= 0.01f)
715 if (Vj.w >= 0.01f) // Both are in, save the last one
717 rdp.vtxbuf[index] = Vj;
718 rdp.vtxbuf[index++].not_zclipped = 1;
720 else // First is in, second is out, save intersection
722 percent = (-Vi.w) / (Vj.w - Vi.w);
723 rdp.vtxbuf[index].not_zclipped = 0;
724 rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;
725 rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;
726 rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
727 rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;
728 rdp.vtxbuf[index].w = 0.01f;
729 rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
730 rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
731 rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
732 rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
733 rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);
734 rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);
735 rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);
736 rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);
739 else
741 //if (Vj.w < 0.01f) // Both are out, save nothing
742 if (Vj.w >= 0.01f) // First is out, second is in, save intersection & in point
744 percent = (-Vj.w) / (Vi.w - Vj.w);
745 rdp.vtxbuf[index].not_zclipped = 0;
746 rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;
747 rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;
748 rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
749 rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;
750 rdp.vtxbuf[index].w = 0.01f;
751 rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
752 rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
753 rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
754 rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
755 rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);
756 rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);
757 rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);
758 rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);
760 // Save the in point
761 rdp.vtxbuf[index] = Vj;
762 rdp.vtxbuf[index++].not_zclipped = 1;
766 rdp.n_global = index;
770 static void CalculateLOD(VERTEX **v, int n)
772 //rdp.update |= UPDATE_TEXTURE;
774 if (rdp.lod_calculated)
776 float detailmax;
777 if (dc0_detailmax < 0.5)
778 detailmax = rdp.lod_fraction;
779 else
780 detailmax = 1.0f - rdp.lod_fraction;
781 grTexDetailControl (GR_TMU0, dc0_lodbias, dc0_detailscale, detailmax);
782 if (num_tmu == 2)
783 grTexDetailControl (GR_TMU1, dc1_lodbias, dc1_detailscale, detailmax);
784 return;
787 float deltaS, deltaT;
788 float deltaX, deltaY;
789 double deltaTexels, deltaPixels, lodFactor = 0;
790 double intptr;
791 float s_scale = rdp.tiles[rdp.cur_tile].width / 255.0f;
792 float t_scale = rdp.tiles[rdp.cur_tile].height / 255.0f;
793 if (settings.lodmode == 1)
795 deltaS = (v[1]->u0/v[1]->q - v[0]->u0/v[0]->q) * s_scale;
796 deltaT = (v[1]->v0/v[1]->q - v[0]->v0/v[0]->q) * t_scale;
797 deltaTexels = sqrt( deltaS * deltaS + deltaT * deltaT );
799 deltaX = (v[1]->x - v[0]->x)/rdp.scale_x;
800 deltaY = (v[1]->y - v[0]->y)/rdp.scale_y;
801 deltaPixels = sqrt( deltaX * deltaX + deltaY * deltaY );
803 lodFactor = deltaTexels / deltaPixels;
805 else
807 int i, j;
808 for (i = 0; i < n; i++)
810 j = (i < n-1) ? i + 1 : 0;
812 deltaS = (v[j]->u0/v[j]->q - v[i]->u0/v[i]->q) * s_scale;
813 deltaT = (v[j]->v0/v[j]->q - v[i]->v0/v[i]->q) * t_scale;
814 // deltaS = v[j]->ou - v[i]->ou;
815 // deltaT = v[j]->ov - v[i]->ov;
816 deltaTexels = sqrt( deltaS * deltaS + deltaT * deltaT );
818 deltaX = (v[j]->x - v[i]->x)/rdp.scale_x;
819 deltaY = (v[j]->y - v[i]->y)/rdp.scale_y;
820 deltaPixels = sqrt( deltaX * deltaX + deltaY * deltaY );
822 lodFactor += deltaTexels / deltaPixels;
824 // Divide by n (n edges) to find average
825 lodFactor = lodFactor / n;
827 long ilod = (long)lodFactor;
828 int lod_tile = min((int)(log(ilod)/log(2)), rdp.cur_tile + rdp.mipmap_level);
829 float lod_fraction = 1.0f;
830 if (lod_tile < rdp.cur_tile + rdp.mipmap_level)
832 lod_fraction = max((float)modf(lodFactor / pow(2,lod_tile),&intptr), rdp.prim_lodmin / 255.0f);
834 float detailmax;
835 if (cmb.dc0_detailmax < 0.5f)
836 detailmax = lod_fraction;
837 else
838 detailmax = 1.0f - lod_fraction;
839 grTexDetailControl (GR_TMU0, cmb.dc0_lodbias, cmb.dc0_detailscale, detailmax);
840 if (num_tmu == 2)
841 grTexDetailControl (GR_TMU1, cmb.dc1_lodbias, cmb.dc1_detailscale, detailmax);
842 FRDP("CalculateLOD factor: %f, tile: %d, lod_fraction: %f\n", (float)lodFactor, lod_tile, lod_fraction);
845 static void DepthBuffer(VERTEX ** vtx, int n)
847 if (settings.RE2)
849 for(int i=0; i<n; i++)
851 int fz = (int)(vtx[i]->z*8.0f+0.5f);
852 if (fz < 0) fz = 0;
853 else if (fz >= 0x40000) fz = 0x40000 - 1;
854 vtx[i]->z = (float)zLUT[fz];
856 return;
858 if (settings.fb_depth_render && dzdx && (rdp.flags & ZBUF_UPDATE))
860 vertexi v[12];
862 for(int i=0; i<n; i++)
864 v[i].x = (long)(vtx[i]->x / rdp.scale_x * 65536.0);
865 v[i].y = (long)(vtx[i]->y / rdp.scale_y * 65536.0);
866 v[i].z = (long)(vtx[i]->z * 65536.0);
868 Rasterize(v, n, dzdx);
870 for(int i=0; i<n; i++)
871 vtx[i]->z = ScaleZ(vtx[i]->z);
874 void clip_tri (WORD linew)
876 int i,j,index,n=rdp.n_global;
877 float percent;
879 // rdp.vtxbuf and rdp.vtxbuf2 were set by clip_z
881 // Check which clipping is needed
882 if (rdp.clip & CLIP_XMAX) // right of the screen
884 // Swap vertex buffers
885 VERTEX *tmp = rdp.vtxbuf2;
886 rdp.vtxbuf2 = rdp.vtxbuf;
887 rdp.vtxbuf = tmp;
888 rdp.vtx_buffer ^= 1;
889 index = 0;
891 // Check the vertices for clipping
892 for (i=0; i<n; i++)
894 j = i+1;
895 if (j == n) j = 0;
897 if (Vi.x <= rdp.scissor.lr_x)
899 if (Vj.x <= rdp.scissor.lr_x) // Both are in, save the last one
901 rdp.vtxbuf[index++] = Vj;
903 else // First is in, second is out, save intersection
905 percent = (rdp.scissor.lr_x - Vi.x) / (Vj.x - Vi.x);
906 rdp.vtxbuf[index].x = (float)rdp.scissor.lr_x + 0.001f;
907 rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;
908 rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
909 rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;
910 rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;
911 rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
912 rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
913 rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
914 rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
915 rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);
916 rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);
917 rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);
918 rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);
921 else
923 //if (Vj.x > rdp.scissor.lr_x) // Both are out, save nothing
924 if (Vj.x <= rdp.scissor.lr_x) // First is out, second is in, save intersection & in point
926 percent = (rdp.scissor.lr_x - Vj.x) / (Vi.x - Vj.x);
927 rdp.vtxbuf[index].x = (float)rdp.scissor.lr_x + 0.001f;
928 rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;
929 rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
930 rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;
931 rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;
932 rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
933 rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
934 rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
935 rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
936 rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);
937 rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);
938 rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);
939 rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);
941 // Save the in point
942 rdp.vtxbuf[index++] = Vj;
946 n = index;
948 if (rdp.clip & CLIP_XMIN) // left of the screen
950 // Swap vertex buffers
951 VERTEX *tmp = rdp.vtxbuf2;
952 rdp.vtxbuf2 = rdp.vtxbuf;
953 rdp.vtxbuf = tmp;
954 rdp.vtx_buffer ^= 1;
955 index = 0;
957 // Check the vertices for clipping
958 for (i=0; i<n; i++)
960 j = i+1;
961 if (j == n) j = 0;
963 if (Vi.x >= rdp.scissor.ul_x)
965 if (Vj.x >= rdp.scissor.ul_x) // Both are in, save the last one
967 rdp.vtxbuf[index++] = Vj;
969 else // First is in, second is out, save intersection
971 percent = (rdp.scissor.ul_x - Vi.x) / (Vj.x - Vi.x);
972 rdp.vtxbuf[index].x = (float)rdp.scissor.ul_x + 0.001f;
973 rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;
974 rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
975 rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;
976 rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;
977 rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
978 rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
979 rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
980 rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
981 rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);
982 rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);
983 rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);
984 rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);
987 else
989 //if (Vj.x < rdp.scissor.ul_x) // Both are out, save nothing
990 if (Vj.x >= rdp.scissor.ul_x) // First is out, second is in, save intersection & in point
992 percent = (rdp.scissor.ul_x - Vj.x) / (Vi.x - Vj.x);
993 rdp.vtxbuf[index].x = (float)rdp.scissor.ul_x + 0.001f;
994 rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;
995 rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
996 rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;
997 rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;
998 rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
999 rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
1000 rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
1001 rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
1002 rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);
1003 rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);
1004 rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);
1005 rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);
1007 // Save the in point
1008 rdp.vtxbuf[index++] = Vj;
1012 n = index;
1014 if (rdp.clip & CLIP_YMAX) // top of the screen
1016 // Swap vertex buffers
1017 VERTEX *tmp = rdp.vtxbuf2;
1018 rdp.vtxbuf2 = rdp.vtxbuf;
1019 rdp.vtxbuf = tmp;
1020 rdp.vtx_buffer ^= 1;
1021 index = 0;
1023 // Check the vertices for clipping
1024 for (i=0; i<n; i++)
1026 j = i+1;
1027 if (j == n) j = 0;
1029 if (Vi.y <= rdp.scissor.lr_y)
1031 if (Vj.y <= rdp.scissor.lr_y) // Both are in, save the last one
1033 rdp.vtxbuf[index++] = Vj;
1035 else // First is in, second is out, save intersection
1037 percent = (rdp.scissor.lr_y - Vi.y) / (Vj.y - Vi.y);
1038 rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;
1039 rdp.vtxbuf[index].y = (float)rdp.scissor.lr_y + 0.001f;
1040 rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
1041 rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;
1042 rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;
1043 rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
1044 rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
1045 rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
1046 rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
1047 rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);
1048 rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);
1049 rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);
1050 rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);
1053 else
1055 //if (Vj.y > rdp.scissor.lr_y) // Both are out, save nothing
1056 if (Vj.y <= rdp.scissor.lr_y) // First is out, second is in, save intersection & in point
1058 percent = (rdp.scissor.lr_y - Vj.y) / (Vi.y - Vj.y);
1059 rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;
1060 rdp.vtxbuf[index].y = (float)rdp.scissor.lr_y + 0.001f;
1061 rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
1062 rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;
1063 rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;
1064 rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
1065 rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
1066 rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
1067 rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
1068 rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);
1069 rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);
1070 rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);
1071 rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);
1073 // Save the in point
1074 rdp.vtxbuf[index++] = Vj;
1078 n = index;
1080 if (rdp.clip & CLIP_YMIN) // bottom of the screen
1082 // Swap vertex buffers
1083 VERTEX *tmp = rdp.vtxbuf2;
1084 rdp.vtxbuf2 = rdp.vtxbuf;
1085 rdp.vtxbuf = tmp;
1086 rdp.vtx_buffer ^= 1;
1087 index = 0;
1089 // Check the vertices for clipping
1090 for (i=0; i<n; i++)
1092 j = i+1;
1093 if (j == n) j = 0;
1095 if (Vi.y >= rdp.scissor.ul_y)
1097 if (Vj.y >= rdp.scissor.ul_y) // Both are in, save the last one
1099 rdp.vtxbuf[index++] = Vj;
1101 else // First is in, second is out, save intersection
1103 percent = (rdp.scissor.ul_y - Vi.y) / (Vj.y - Vi.y);
1104 rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;
1105 rdp.vtxbuf[index].y = (float)rdp.scissor.ul_y + 0.001f;
1106 rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;
1107 rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;
1108 rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;
1109 rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;
1110 rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;
1111 rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;
1112 rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;
1113 rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);
1114 rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);
1115 rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);
1116 rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);
1119 else
1121 //if (Vj.y < rdp.scissor.ul_y) // Both are out, save nothing
1122 if (Vj.y >= rdp.scissor.ul_y) // First is out, second is in, save intersection & in point
1124 percent = (rdp.scissor.ul_y - Vj.y) / (Vi.y - Vj.y);
1125 rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;
1126 rdp.vtxbuf[index].y = (float)rdp.scissor.ul_y + 0.001f;
1127 rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;
1128 rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;
1129 rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;
1130 rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;
1131 rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;
1132 rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;
1133 rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;
1134 rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);
1135 rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);
1136 rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);
1137 rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);
1139 // Save the in point
1140 rdp.vtxbuf[index++] = Vj;
1144 n = index;
1147 if (n < 3)
1149 FRDP (" * clip_tri: n < 3\n");
1150 return;
1152 ConvertCoordsConvert (rdp.vtxbuf, n);
1153 if (rdp.fog_coord_enabled)
1155 for (i = 0; i < n; i++)
1157 rdp.vtxbuf[i].f = 1.0f/max(16.0f,rdp.vtxbuf[i].f);
1161 if (settings.lodmode > 0 && rdp.cur_tile < rdp.mipmap_level)
1162 CalculateLOD(rdp.vtx_buffer?(vtx_list2):(vtx_list1), n);
1164 cmb.cmb_ext_use = cmb.tex_cmb_ext_use = 0;
1167 if (rdp.hires_tex)
1169 for (int k = 0; k < 3; k++)
1171 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.hires_tex->width, rdp.hires_tex->height, rdp.hires_tex->tex_width, rdp.hires_tex->tex_height, rdp.hires_tex->lr_u, rdp.hires_tex->lr_v);
1175 if (fullscreen)
1177 if (settings.wireframe)
1179 SetWireframeCol ();
1180 for (i=0; i<n; i++)
1182 j = i+1;
1183 if (j == n) j = 0;
1184 grDrawLine (&rdp.vtxbuf[i], &rdp.vtxbuf[j]);
1187 else
1190 // VERTEX ** pv = rdp.vtx_buffer?(vtx_list2):(vtx_list1);
1191 // for (int k = 0; k < n; k ++)
1192 // 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]);
1193 // pv[k]->y = settings.res_y - pv[k]->y;
1195 if (linew > 0)
1197 if (linew == 1)
1199 for (i=0; i<n; i++)
1201 rdp.vtxbuf[i].z = ScaleZ(rdp.vtxbuf[i].z);
1202 j = i+1;
1203 if (j == n) j = 0;
1204 grDrawLine (&rdp.vtxbuf[i], &rdp.vtxbuf[j]);
1207 else if (n == 3)
1209 rdp.vtxbuf[0].z = ScaleZ(rdp.vtxbuf[0].z);
1210 rdp.vtxbuf[1].z = ScaleZ(rdp.vtxbuf[1].z);
1211 VERTEX v[4];
1212 v[0] = rdp.vtxbuf[0];
1213 v[1] = rdp.vtxbuf[0];
1214 v[2] = rdp.vtxbuf[1];
1215 v[3] = rdp.vtxbuf[1];
1216 float width = (linew-1)*0.25f;
1217 if(rdp.vtxbuf[0].y == rdp.vtxbuf[1].y )
1219 v[0].x = v[1].x = rdp.vtxbuf[0].x;
1220 v[2].x = v[3].x = rdp.vtxbuf[1].x;
1222 v[0].y = v[2].y = rdp.vtxbuf[0].y-width*rdp.scale_y+1;
1223 v[1].y = v[3].y = rdp.vtxbuf[0].y+width*rdp.scale_y;
1225 else
1227 v[0].y = v[1].y = rdp.vtxbuf[0].y;
1228 v[2].y = v[3].y = rdp.vtxbuf[1].y;
1230 v[0].x = v[2].x = rdp.vtxbuf[0].x-width*rdp.scale_x+1;
1231 v[1].x = v[3].x = rdp.vtxbuf[0].x+width*rdp.scale_x;
1233 grDrawTriangle(&v[0], &v[1], &v[2]);
1234 grDrawTriangle(&v[1], &v[2], &v[3]);
1237 else
1239 if (settings.ucode == 5)
1240 for (i=0; i<n; i++)
1241 if (rdp.vtxbuf[i].z < -1000.0f) return;//rdp.vtxbuf[i].z = 0.0f;
1242 DepthBuffer(rdp.vtx_buffer?(vtx_list2):(vtx_list1), n);
1243 grDrawVertexArray (GR_TRIANGLE_FAN, n, rdp.vtx_buffer?(&vtx_list2):(&vtx_list1));
1245 //grDrawVertexArrayContiguous (GR_TRIANGLE_FAN, n, rdp.vtxbuf, sizeof(VERTEX));
1249 if (debug.capture) add_tri (rdp.vtxbuf, n, TRI_TRIANGLE);
1252 void add_tri (VERTEX *v, int n, int type)
1254 //FRDP ("ENTER (%f, %f, %f), (%f, %f, %f), (%f, %f, %f)\n", v[0].x, v[0].y, v[0].w,
1255 // v[1].x, v[1].y, v[1].w, v[2].x, v[2].y, v[2].w);
1257 // Debug capture
1258 if (debug.capture)
1260 rdp.debug_n ++;
1262 TRI_INFO *info = new TRI_INFO;
1263 info->nv = n;
1264 info->v = new VERTEX [n];
1265 memcpy (info->v, v, sizeof(VERTEX)*n);
1266 info->cycle_mode = rdp.cycle_mode;
1267 info->cycle1 = rdp.cycle1;
1268 info->cycle2 = rdp.cycle2;
1269 info->uncombined = rdp.uncombined;
1270 info->geom_mode = rdp.geom_mode;
1271 info->othermode_h = rdp.othermode_h;
1272 info->othermode_l = rdp.othermode_l;
1273 info->tri_n = rdp.tri_n;
1274 info->type = type;
1276 for (int i=0; i<2; i++)
1278 int j = rdp.cur_tile+i;
1279 if (i == 0)
1280 info->t[i].tmu = rdp.t0;
1281 else
1282 info->t[i].tmu = rdp.t1;
1283 info->t[i].cur_cache[0] = rdp.cur_cache_n[rdp.t0];
1284 info->t[i].cur_cache[1] = rdp.cur_cache_n[rdp.t1];
1285 info->t[i].format = rdp.tiles[j].format;
1286 info->t[i].size = rdp.tiles[j].size;
1287 info->t[i].width = rdp.tiles[j].width;
1288 info->t[i].height = rdp.tiles[j].height;
1289 info->t[i].line = rdp.tiles[j].line;
1290 info->t[i].palette = rdp.tiles[j].palette;
1291 info->t[i].clamp_s = rdp.tiles[j].clamp_s;
1292 info->t[i].clamp_t = rdp.tiles[j].clamp_t;
1293 info->t[i].mirror_s = rdp.tiles[j].mirror_s;
1294 info->t[i].mirror_t = rdp.tiles[j].mirror_t;
1295 info->t[i].shift_s = rdp.tiles[j].shift_s;
1296 info->t[i].shift_t = rdp.tiles[j].shift_t;
1297 info->t[i].mask_s = rdp.tiles[j].mask_s;
1298 info->t[i].mask_t = rdp.tiles[j].mask_t;
1299 info->t[i].ul_s = rdp.tiles[j].ul_s;
1300 info->t[i].ul_t = rdp.tiles[j].ul_t;
1301 info->t[i].lr_s = rdp.tiles[j].lr_s;
1302 info->t[i].lr_t = rdp.tiles[j].lr_t;
1303 info->t[i].t_ul_s = rdp.tiles[7].t_ul_s;
1304 info->t[i].t_ul_t = rdp.tiles[7].t_ul_t;
1305 info->t[i].t_lr_s = rdp.tiles[7].t_lr_s;
1306 info->t[i].t_lr_t = rdp.tiles[7].t_lr_t;
1307 info->t[i].scale_s = rdp.tiles[j].s_scale;
1308 info->t[i].scale_t = rdp.tiles[j].t_scale;
1311 info->fog_color = rdp.fog_color;
1312 info->fill_color = rdp.fill_color;
1313 info->prim_color = rdp.prim_color;
1314 info->blend_color = rdp.blend_color;
1315 info->env_color = rdp.env_color;
1316 info->prim_lodmin = rdp.prim_lodmin;
1317 info->prim_lodfrac = rdp.prim_lodfrac;
1319 info->pNext = debug.tri_list;
1320 debug.tri_list = info;
1322 if (debug.tri_last == NULL)
1323 debug.tri_last = debug.tri_list;
1327 void update_scissor ()
1329 if (rdp.update & UPDATE_SCISSOR)
1331 rdp.update ^= UPDATE_SCISSOR;
1333 // KILL the floating point error with 0.01f
1334 rdp.scissor.ul_x = (DWORD) max(min((rdp.scissor_o.ul_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0);
1335 rdp.scissor.lr_x = (DWORD) max(min((rdp.scissor_o.lr_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0);
1336 rdp.scissor.ul_y = (DWORD) max(min((rdp.scissor_o.ul_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0);
1337 rdp.scissor.lr_y = (DWORD) max(min((rdp.scissor_o.lr_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0);
1338 FRDP (" |- scissor - (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y,
1339 rdp.scissor.lr_x, rdp.scissor.lr_y);
1344 // update - update states if they need it
1347 typedef struct
1349 unsigned int c2_m2b:2;
1350 unsigned int c1_m2b:2;
1351 unsigned int c2_m2a:2;
1352 unsigned int c1_m2a:2;
1353 unsigned int c2_m1b:2;
1354 unsigned int c1_m1b:2;
1355 unsigned int c2_m1a:2;
1356 unsigned int c1_m1a:2;
1357 } rdp_blender_setting;
1359 void update ()
1361 RDP ("-+ update called\n");
1362 // Check for rendermode changes
1363 // Z buffer
1364 if (rdp.render_mode_changed & 0x00000C30)
1366 FRDP (" |- render_mode_changed zbuf - decal: %s, update: %s, compare: %s\n",
1367 str_yn[(rdp.othermode_l&0x00000C00) == 0x00000C00],
1368 str_yn[(rdp.othermode_l&0x00000020)?1:0],
1369 str_yn[(rdp.othermode_l&0x00000010)?1:0]);
1371 rdp.render_mode_changed &= ~0x00000C30;
1372 rdp.update |= UPDATE_ZBUF_ENABLED;
1374 // Decal?
1375 // if ((rdp.othermode_l & 0x00000C00) == 0x00000C00)
1376 if (rdp.othermode_l & 0x00000800)
1377 rdp.flags |= ZBUF_DECAL;
1378 else
1379 rdp.flags &= ~ZBUF_DECAL;
1381 // Update?
1382 if ((rdp.othermode_l & 0x00000020))
1383 rdp.flags |= ZBUF_UPDATE;
1384 else
1385 rdp.flags &= ~ZBUF_UPDATE;
1387 // Compare?
1388 if (rdp.othermode_l & 0x00000010)
1389 rdp.flags |= ZBUF_COMPARE;
1390 else
1391 rdp.flags &= ~ZBUF_COMPARE;
1394 // Alpha compare
1395 if (rdp.render_mode_changed & 0x00001000)
1397 FRDP (" |- render_mode_changed alpha compare - on: %s\n",
1398 str_yn[(rdp.othermode_l&0x00001000)?1:0]);
1399 rdp.render_mode_changed &= ~0x00001000;
1400 rdp.update |= UPDATE_ALPHA_COMPARE;
1402 if (rdp.othermode_l & 0x00001000)
1403 rdp.flags |= ALPHA_COMPARE;
1404 else
1405 rdp.flags &= ~ALPHA_COMPARE;
1408 if (rdp.render_mode_changed & 0x00002000) // alpha cvg sel
1410 FRDP (" |- render_mode_changed alpha cvg sel - on: %s\n",
1411 str_yn[(rdp.othermode_l&0x00002000)?1:0]);
1412 rdp.render_mode_changed &= ~0x00002000;
1413 rdp.update |= UPDATE_COMBINE;
1416 // Force blend
1417 if (rdp.render_mode_changed & 0xFFFF0000)
1419 FRDP (" |- render_mode_changed force_blend - %08lx\n", rdp.othermode_l&0xFFFF0000);
1420 rdp.render_mode_changed &= 0x0000FFFF;
1422 rdp.fbl_a0 = (BYTE)((rdp.othermode_l>>30)&0x3);
1423 rdp.fbl_b0 = (BYTE)((rdp.othermode_l>>26)&0x3);
1424 rdp.fbl_c0 = (BYTE)((rdp.othermode_l>>22)&0x3);
1425 rdp.fbl_d0 = (BYTE)((rdp.othermode_l>>18)&0x3);
1426 rdp.fbl_a1 = (BYTE)((rdp.othermode_l>>28)&0x3);
1427 rdp.fbl_b1 = (BYTE)((rdp.othermode_l>>24)&0x3);
1428 rdp.fbl_c1 = (BYTE)((rdp.othermode_l>>20)&0x3);
1429 rdp.fbl_d1 = (BYTE)((rdp.othermode_l>>16)&0x3);
1431 rdp.update |= UPDATE_COMBINE;
1434 //if (fullscreen)
1436 // Combine MUST go before texture
1437 if ((rdp.update & UPDATE_COMBINE) && rdp.allow_combine)
1439 RDP (" |-+ update_combine\n");
1440 Combine ();
1443 if (rdp.update & UPDATE_TEXTURE) // note: UPDATE_TEXTURE and UPDATE_COMBINE are the same
1445 rdp.tex_ctr ++;
1446 if (rdp.tex_ctr == 0xFFFFFFFF)
1447 rdp.tex_ctr = 0;
1449 TexCache ();
1450 if (rdp.noise == noise_none)
1451 rdp.update ^= UPDATE_TEXTURE;
1454 if (fullscreen)
1456 // Z buffer
1457 if (rdp.update & UPDATE_ZBUF_ENABLED)
1459 // already logged above
1460 rdp.update ^= UPDATE_ZBUF_ENABLED;
1462 if (rdp.flags & ZBUF_DECAL)
1464 if ((rdp.othermode_l & 0x00000C00) == 0x00000C00)
1466 grDepthBiasLevel (settings.depth_bias);//(-32);
1467 FRDP("depth bias: %d\n", settings.depth_bias);
1469 else
1471 // VP changed that to -1 (was -4)
1472 grDepthBiasLevel (-4);//-16);
1473 RDP("depth bias: -4");
1476 else
1478 grDepthBiasLevel (0);
1481 if ((rdp.flags & ZBUF_ENABLED) || (settings.force_depth_compare && rdp.zsrc == 1))
1483 if ((rdp.flags & ZBUF_COMPARE))
1485 if (settings.soft_depth_compare)
1487 grDepthBufferFunction (GR_CMP_LEQUAL);
1489 else
1491 grDepthBufferFunction (GR_CMP_LESS);
1494 else
1496 grDepthBufferFunction (GR_CMP_ALWAYS);
1499 if ((rdp.flags & ZBUF_UPDATE)
1500 // || (rdp.flags & ZBUF_DECAL) // FOR DEBUGGING ONLY
1503 grDepthMask (FXTRUE);
1505 else
1507 grDepthMask (FXFALSE);
1510 else
1512 grDepthBufferFunction (GR_CMP_ALWAYS);
1513 grDepthMask (FXFALSE);
1516 // Alpha compare
1517 if (rdp.update & UPDATE_ALPHA_COMPARE)
1519 // already logged above
1520 rdp.update ^= UPDATE_ALPHA_COMPARE;
1522 // if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && !force_full_alpha)
1523 // if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && (rdp.blend_color&0xFF))
1524 if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && (!(rdp.othermode_l & 0x00004000) || (rdp.blend_color&0xFF)))
1526 BYTE reference = (BYTE)(rdp.blend_color&0xFF);
1527 if (reference)
1528 grAlphaTestFunction (GR_CMP_GEQUAL);
1529 else
1530 grAlphaTestFunction (GR_CMP_GREATER);
1531 grAlphaTestReferenceValue (reference);
1532 FRDP (" |- alpha compare: blend: %02lx\n", reference);
1534 else
1536 if (rdp.flags & ALPHA_COMPARE)
1538 if ((rdp.othermode_l & 0x5000) != 0x5000)
1540 grAlphaTestFunction (GR_CMP_GEQUAL);
1541 grAlphaTestReferenceValue (0x20);//0xA0);
1542 RDP (" |- alpha compare: 0x20\n");
1544 else
1546 grAlphaTestFunction (GR_CMP_GREATER);
1547 if (rdp.acmp == 3)
1549 grAlphaTestReferenceValue ((BYTE)(rdp.blend_color&0xFF));
1550 FRDP (" |- alpha compare: blend: %02lx\n", rdp.blend_color&0xFF);
1552 else
1554 grAlphaTestReferenceValue (0x00);
1555 RDP (" |- alpha compare: 0x00\n");
1559 else
1561 grAlphaTestFunction (GR_CMP_ALWAYS);
1562 RDP (" |- alpha compare: none\n");
1565 if (rdp.acmp == 3)
1567 if (grStippleModeExt)
1569 RDP (" |- alpha compare: dither\n");
1570 grStippleModeExt(settings.stipple_mode);
1571 // grStippleModeExt(GR_STIPPLE_PATTERN);
1574 else
1576 if (grStippleModeExt)
1578 //RDP (" |- alpha compare: dither disabled\n");
1579 grStippleModeExt(GR_STIPPLE_DISABLE);
1583 // Cull mode (leave this in for z-clipped triangles)
1584 if (rdp.update & UPDATE_CULL_MODE)
1586 rdp.update ^= UPDATE_CULL_MODE;
1587 DWORD mode = (rdp.flags & CULLMASK) >> CULLSHIFT;
1588 FRDP (" |- cull_mode - mode: %s\n", str_cull[mode]);
1589 switch (mode)
1591 case 0: // cull none
1592 case 3: // cull both
1593 grCullMode(GR_CULL_DISABLE);
1594 break;
1595 case 1: // cull front
1596 // grCullMode(GR_CULL_POSITIVE);
1597 grCullMode(GR_CULL_NEGATIVE);
1598 break;
1599 case 2: // cull back
1600 // grCullMode (GR_CULL_NEGATIVE);
1601 grCullMode (GR_CULL_POSITIVE);
1602 break;
1606 //Added by Gonetz.
1607 if (settings.fog && (rdp.update & UPDATE_FOG_ENABLED))
1609 rdp.update ^= UPDATE_FOG_ENABLED;
1611 if (rdp.flags & FOG_ENABLED)
1613 typedef union { WORD *w; rdp_blender_setting *b; } BLEND;
1614 WORD blword = (WORD) (rdp.othermode_l >> 16);
1615 BLEND bl;
1616 bl.w = &blword;
1617 if((rdp.fog_multiplier > 0) && (bl.b->c1_m1a==3 || bl.b->c1_m2a == 3 || bl.b->c2_m1a == 3 || bl.b->c2_m2a == 3))
1619 grFogColorValue(rdp.fog_color);
1620 grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
1621 rdp.fog_coord_enabled = TRUE;
1622 RDP("fog enabled \n");
1624 else
1626 RDP("fog disabled in blender\n");
1627 rdp.fog_coord_enabled = FALSE;
1628 grFogMode (GR_FOG_DISABLE);
1631 else
1633 RDP("fog disabled\n");
1634 rdp.fog_coord_enabled = FALSE;
1635 grFogMode (GR_FOG_DISABLE);
1640 if (rdp.update & UPDATE_VIEWPORT)
1642 rdp.update ^= UPDATE_VIEWPORT;
1643 if (fullscreen)
1645 if (settings.RE2)
1647 grClipWindow (0, 0, settings.res_x-1, settings.res_y-1);
1649 else
1651 float scale_x = (float)fabs(rdp.view_scale[0]);
1652 float scale_y = (float)fabs(rdp.view_scale[1]);
1653 //printf("scale_y %g\n", scale_y);
1655 DWORD min_x = (DWORD) max(rdp.view_trans[0] - scale_x, 0);
1656 DWORD min_y = (DWORD) max(rdp.view_trans[1] - scale_y, 0);
1657 DWORD max_x = (DWORD) min(rdp.view_trans[0] + scale_x + 1, settings.res_x);
1658 DWORD max_y = (DWORD) min(rdp.view_trans[1] + scale_y + 1, settings.res_y);
1660 FRDP (" |- viewport - (%d, %d, %d, %d)\n", min_x, min_y, max_x, max_y);
1661 grClipWindow (min_x, min_y, max_x, max_y);
1662 //printf("viewport %d %d %d %d\n", min_x, min_y, max_x, max_y);
1667 if (rdp.update & UPDATE_SCISSOR)
1668 update_scissor ();
1670 RDP (" + update end\n");
1673 void set_message_combiner ()
1675 grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
1676 GR_COMBINE_FACTOR_ONE,
1677 GR_COMBINE_LOCAL_NONE,
1678 GR_COMBINE_OTHER_TEXTURE,
1679 FXFALSE);
1680 grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
1681 GR_COMBINE_FACTOR_ONE,
1682 GR_COMBINE_LOCAL_NONE,
1683 GR_COMBINE_OTHER_TEXTURE,
1684 FXFALSE);
1685 if (settings.buff_clear && (settings.show_fps & 0x08))
1686 grAlphaBlendFunction (GR_BLEND_SRC_ALPHA,
1687 GR_BLEND_ONE_MINUS_SRC_ALPHA,
1688 GR_BLEND_ZERO,
1689 GR_BLEND_ZERO);
1690 else
1691 grAlphaBlendFunction (GR_BLEND_ONE,
1692 GR_BLEND_ZERO,
1693 GR_BLEND_ZERO,
1694 GR_BLEND_ZERO);
1695 grAlphaTestFunction (GR_CMP_ALWAYS);
1696 if (grStippleModeExt)
1698 grStippleModeExt(GR_STIPPLE_DISABLE);
1700 grTexCombine (GR_TMU1,
1701 GR_COMBINE_FUNCTION_NONE,
1702 GR_COMBINE_FACTOR_NONE,
1703 GR_COMBINE_FUNCTION_NONE,
1704 GR_COMBINE_FACTOR_NONE,
1705 FXFALSE, FXFALSE);
1706 grTexCombine (GR_TMU0,
1707 GR_COMBINE_FUNCTION_LOCAL,
1708 GR_COMBINE_FACTOR_NONE,
1709 GR_COMBINE_FUNCTION_LOCAL,
1710 GR_COMBINE_FACTOR_NONE,
1711 FXFALSE, FXFALSE);
1712 grTexSource(GR_TMU0,
1713 grTexMinAddress(GR_TMU0) + offset_font,
1714 GR_MIPMAPLEVELMASK_BOTH,
1715 &fontTex);
1716 grFogMode (GR_FOG_DISABLE);
1720 1 bit: common
1721 2 bit: I textures, V-Rally 99
1722 3 bit: South Park, Polaris
1723 4 bit: Mace
1724 5 bit: CyberTiger
1725 6 bit: Yoshi Story
1727 void fix_tex_coord (VERTEX **v)
1729 BOOL fix = FALSE;
1730 if (settings.fix_tex_coord & 449)
1732 // if ( (rdp.tiles[rdp.last_tile_size].format == 2) ||
1733 // ( (rdp.tiles[rdp.last_tile_size].size != 2)) )
1734 if (rdp.tiles[rdp.last_tile_size].size != 2)
1736 if (settings.fix_tex_coord & 128)
1738 if (v[0]->sz != v[1]->sz || v[0]->sz != v[2]->sz)
1739 return;
1742 if (settings.fix_tex_coord & 256) //dr.mario
1744 if ((rdp.tiles[rdp.last_tile_size].format == 2) && (rdp.tiles[rdp.last_tile_size].size == 0))
1745 return;
1748 // int lu = (rdp.tiles[rdp.last_tile_size].ul_s)<<1;
1749 int ru = (rdp.tiles[rdp.last_tile_size].lr_s+1)<<1;
1750 int rv = (rdp.tiles[rdp.last_tile_size].lr_t+1)<<1;
1751 int diff = (settings.fix_tex_coord & 64) ? 5 : 3;
1753 for (int t = 0; t < 3; t++)
1755 if ((v[t]->uv_fixed == 0)) //&& (((short)v[t]->ou > 0) || ((short)v[t]->ov > 0)))
1757 if ( (abs((short)v[t]->ou - ru) < diff) || (abs((short)v[t]->ov - rv) < diff) )
1758 // if ( ((short)v[t]->ou == lu) || (abs((short)v[t]->ou - ru) < 3) )
1760 fix = TRUE;
1761 break;
1764 else
1766 fix = TRUE;
1767 break;
1770 if (fix)
1772 for (int t = 0; t < 3; t++)
1774 if (v[t]->uv_fixed == 0)
1776 v[t]->uv_fixed = 1;
1777 FRDP("v[%d] uv_fixed (%f, %f)->(%f,%f)\n",t, v[t]->ou, v[t]->ov, v[t]->ou*0.5f, v[t]->ov*0.5f);
1778 v[t]->ou *= 0.5f;
1779 v[t]->ov *= 0.5f;
1782 return;
1786 if (settings.fix_tex_coord & 2)
1788 if (rdp.tiles[rdp.last_tile_size].format == 4)
1790 for (int t = 0; t < 3; t++)
1792 if (v[t]->uv_fixed == 0)
1794 v[t]->uv_fixed = 1;
1795 v[t]->ou *= 0.5f;
1796 v[t]->ov *= 0.5f;
1799 return;
1802 if (settings.fix_tex_coord & 4)
1804 TILE & last_tile = rdp.tiles[rdp.last_tile_size];
1805 if ((last_tile.format == 2) &&
1806 (last_tile.size == 0) &&
1807 (last_tile.line%2 == 0) &&
1808 (last_tile.lr_s >= last_tile.lr_t))
1810 int ru = (rdp.tiles[rdp.last_tile_size].lr_s+1);
1811 int rv = (rdp.tiles[rdp.last_tile_size].lr_t+1);
1812 int t;
1813 for (t = 0; t < 3; t++)
1815 if (v[t]->uv_fixed == 0)
1817 if ( (abs((short)v[t]->ou - ru) < 3) || (abs((short)v[t]->ov - rv) < 3) )
1818 return;
1821 for (t = 0; t < 3; t++)
1823 if (v[t]->uv_fixed == 0)
1825 v[t]->uv_fixed = 1;
1826 v[t]->ou *= 0.5f;
1827 v[t]->ov *= 0.5f;
1830 return;
1833 if (settings.fix_tex_coord & 8)
1835 if (rdp.tiles[rdp.last_tile_size].format == 3 && rdp.tiles[rdp.last_tile_size].size == 1)
1837 short width = (rdp.tiles[rdp.last_tile_size].ul_s<<1)+1 ;
1838 for (int t = 0; t < 3; t++)
1840 if (v[t]->uv_fixed == 0)
1842 if (short(v[t]->ou) == width)
1844 fix = TRUE;
1845 break;
1848 else
1850 fix = TRUE;
1851 break;
1854 if (fix)
1856 RDP("texcoord fixed!\n");
1857 for (int t = 0; t < 3; t++)
1859 if (v[t]->uv_fixed == 0)
1861 v[t]->uv_fixed = 1;
1862 v[t]->ou *= 0.5f;
1863 v[t]->ov *= 0.5f;
1866 return;
1870 if (settings.fix_tex_coord & 16)
1872 if ((rdp.tiles[rdp.last_tile_size].format == 2) && (rdp.tiles[rdp.last_tile_size].size == 0))
1874 short width = rdp.tiles[rdp.last_tile_size].lr_s + 1;
1875 short height = rdp.tiles[rdp.last_tile_size].lr_t + 1;
1876 for (int t = 0; t < 3; t++)
1878 if (v[t]->uv_fixed == 0)
1880 if ((short(v[t]->ou) > width) || (short(v[t]->ov) > height))
1882 fix = TRUE;
1883 break;
1886 else
1888 fix = TRUE;
1889 break;
1892 if (fix)
1894 for (int t = 0; t < 3; t++)
1896 if (v[t]->uv_fixed == 0)
1898 v[t]->uv_fixed = 1;
1899 v[t]->ou *= 0.5f;
1900 v[t]->ov *= 0.5f;
1903 RDP("texcoord fixed!\n");
1904 return;
1908 if (settings.fix_tex_coord & 32)
1910 if (!rdp.vtx[rdp.v0].uv_fixed &&
1911 (rdp.tiles[rdp.last_tile_size].format == 2) &&
1912 (rdp.tiles[rdp.last_tile_size].size == 1) &&
1913 (rdp.tiles[rdp.last_tile_size].lr_s >= 31) &&
1914 (rdp.tiles[rdp.last_tile_size].lr_t >= 31))
1916 int ru = (rdp.tiles[rdp.last_tile_size].lr_s+1)<<1;
1917 int rv = (rdp.tiles[rdp.last_tile_size].lr_t+1)<<1;
1918 int top = rdp.v0 + rdp.vn;
1919 for (int t = rdp.v0; t < top; t++)
1921 if ( (abs((short)rdp.vtx[t].ou - ru) < 2) || (abs((short)rdp.vtx[t].ov - rv) < 2) )
1923 fix = TRUE;
1924 break;
1927 if (fix)
1929 for (int t = rdp.v0; t < top; t++)
1931 rdp.vtx[t].uv_fixed = 1;
1932 rdp.vtx[t].ou *= 0.5f;
1933 rdp.vtx[t].ov *= 0.5f;
1935 RDP("texcoord fixed!\n");
1936 return;