Path: blob/master/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/Util.cpp
2 views
/*1* Glide64 - Glide video plugin for Nintendo 64 emulators.2* Copyright (c) 2002 Dave20013* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA18*/1920//****************************************************************21//22// Glide64 - Glide Plugin for Nintendo 64 emulators23// Project started on December 29th, 200124//25// Authors:26// Dave2001, original author, founded the project in 2001, left it in 200227// Gugaman, joined the project in 2002, left it in 200228// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 200229// Hiroshi 'KoolSmoky' Morii, joined the project in 200730//31//****************************************************************32//33// To modify Glide64:34// * 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.35// * 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.36//37//****************************************************************3839#include <math.h>40#include "Gfx_1.3.h"41#include "Util.h"42#include "Combine.h"43#include "3dmath.h"44#include "Debugger.h"45#include "TexCache.h"46#include "DepthBufferRender.h"4748#define Vj rdp.vtxbuf2[j]49#define Vi rdp.vtxbuf2[i]5051VERTEX *vtx_list1[32]; // vertex indexing52VERTEX *vtx_list2[32];5354//55// util_init - initialize data for the functions in this file56//5758void util_init ()59{60for (int i=0; i<32; i++)61{62vtx_list1[i] = &rdp.vtx1[i];63vtx_list2[i] = &rdp.vtx2[i];64}65}6667static wxUint32 u_cull_mode = 0;6869//software backface culling. Gonetz70// mega modifications by Dave200171int cull_tri(VERTEX **v) // type changed to VERTEX** [Dave2001]72{73int i;7475if (v[0]->scr_off & v[1]->scr_off & v[2]->scr_off)76{77LRDP (" clipped\n");78return TRUE;79}8081// Triangle can't be culled, if it need clipping82int draw = FALSE;8384for (i=0; i<3; i++)85{86if (!v[i]->screen_translated)87{88v[i]->sx = rdp.view_trans[0] + v[i]->x_w * rdp.view_scale[0] + rdp.offset_x;89v[i]->sy = rdp.view_trans[1] + v[i]->y_w * rdp.view_scale[1] + rdp.offset_y;90v[i]->sz = rdp.view_trans[2] + v[i]->z_w * rdp.view_scale[2];91v[i]->screen_translated = 1;92}93if (v[i]->w < 0.01f) //need clip_z. can't be culled now94draw = 1;95}9697u_cull_mode = (rdp.flags & CULLMASK);98if (draw || u_cull_mode == 0 || u_cull_mode == CULLMASK) //no culling set99{100u_cull_mode >>= CULLSHIFT;101return FALSE;102}103104#define SW_CULLING105#ifdef SW_CULLING106#if 1 // H.Morii - faster float comparisons with zero area check added107108const float x1 = v[0]->sx - v[1]->sx;109const float y1 = v[0]->sy - v[1]->sy;110const float x2 = v[2]->sx - v[1]->sx;111const float y2 = v[2]->sy - v[1]->sy;112const float area = y1*x2 - x1*y2;113114const int iarea = *(int*)&area;115const unsigned int mode = (u_cull_mode << 19UL);116u_cull_mode >>= CULLSHIFT;117118if ((iarea & 0x7FFFFFFF) == 0)119{120LRDP (" zero area triangles\n");121return TRUE;122}123124if ((rdp.flags & CULLMASK) && ((int)(iarea ^ mode)) >= 0)125{126LRDP (" culled\n");127return TRUE;128}129#else130131float x1 = v[0]->sx - v[1]->sx;132float y1 = v[0]->sy - v[1]->sy;133float x2 = v[2]->sx - v[1]->sx;134float y2 = v[2]->sy - v[1]->sy;135136u_cull_mode >>= CULLSHIFT;137switch (u_cull_mode)138{139case 1: // cull front140// if ((x1*y2 - y1*x2) < 0.0f) //counter-clockwise, positive141if ((y1*x2-x1*y2) < 0.0f) //counter-clockwise, positive142{143LRDP (" culled!\n");144return TRUE;145}146return FALSE;147case 2: // cull back148// if ((x1*y2 - y1*x2) >= 0.0f) //clockwise, negative149if ((y1*x2-x1*y2) >= 0.0f) //clockwise, negative150{151LRDP (" culled!\n");152return TRUE;153}154return FALSE;155}156#endif157#endif158159return FALSE;160}161162163void apply_shade_mods (VERTEX *v)164{165float col[4];166wxUint32 mod;167memcpy (col, rdp.col, 16);168169if (rdp.cmb_flags)170{171if (v->shade_mod == 0)172v->color_backup = *(wxUint32*)(&(v->b));173else174*(wxUint32*)(&(v->b)) = v->color_backup;175mod = rdp.cmb_flags;176if (mod & CMB_SET)177{178if (col[0] > 1.0f) col[0] = 1.0f;179if (col[1] > 1.0f) col[1] = 1.0f;180if (col[2] > 1.0f) col[2] = 1.0f;181if (col[0] < 0.0f) col[0] = 0.0f;182if (col[1] < 0.0f) col[1] = 0.0f;183if (col[2] < 0.0f) col[2] = 0.0f;184v->r = (wxUint8)(255.0f * col[0]);185v->g = (wxUint8)(255.0f * col[1]);186v->b = (wxUint8)(255.0f * col[2]);187}188if (mod & CMB_A_SET)189{190if (col[3] > 1.0f) col[3] = 1.0f;191if (col[3] < 0.0f) col[3] = 0.0f;192v->a = (wxUint8)(255.0f * col[3]);193}194if (mod & CMB_SETSHADE_SHADEALPHA)195{196v->r = v->g = v->b = v->a;197}198if (mod & CMB_MULT_OWN_ALPHA)199{200float percent = v->a / 255.0f;201v->r = (wxUint8)(v->r * percent);202v->g = (wxUint8)(v->g * percent);203v->b = (wxUint8)(v->b * percent);204}205if (mod & CMB_MULT)206{207if (col[0] > 1.0f) col[0] = 1.0f;208if (col[1] > 1.0f) col[1] = 1.0f;209if (col[2] > 1.0f) col[2] = 1.0f;210if (col[0] < 0.0f) col[0] = 0.0f;211if (col[1] < 0.0f) col[1] = 0.0f;212if (col[2] < 0.0f) col[2] = 0.0f;213v->r = (wxUint8)(v->r * col[0]);214v->g = (wxUint8)(v->g * col[1]);215v->b = (wxUint8)(v->b * col[2]);216}217if (mod & CMB_A_MULT)218{219if (col[3] > 1.0f) col[3] = 1.0f;220if (col[3] < 0.0f) col[3] = 0.0f;221v->a = (wxUint8)(v->a * col[3]);222}223if (mod & CMB_SUB)224{225int r = v->r - (int)(255.0f * rdp.coladd[0]);226int g = v->g - (int)(255.0f * rdp.coladd[1]);227int b = v->b - (int)(255.0f * rdp.coladd[2]);228if (r < 0) r = 0;229if (g < 0) g = 0;230if (b < 0) b = 0;231v->r = (wxUint8)r;232v->g = (wxUint8)g;233v->b = (wxUint8)b;234}235if (mod & CMB_A_SUB)236{237int a = v->a - (int)(255.0f * rdp.coladd[3]);238if (a < 0) a = 0;239v->a = (wxUint8)a;240}241if (mod & CMB_ADD)242{243int r = v->r + (int)(255.0f * rdp.coladd[0]);244int g = v->g + (int)(255.0f * rdp.coladd[1]);245int b = v->b + (int)(255.0f * rdp.coladd[2]);246if (r > 255) r = 255;247if (g > 255) g = 255;248if (b > 255) b = 255;249v->r = (wxUint8)r;250v->g = (wxUint8)g;251v->b = (wxUint8)b;252}253if (mod & CMB_A_ADD)254{255int a = v->a + (int)(255.0f * rdp.coladd[3]);256if (a > 255) a = 255;257v->a = (wxUint8)a;258}259if (mod & CMB_COL_SUB_OWN)260{261int r = (wxUint8)(255.0f * rdp.coladd[0]) - v->r;262int g = (wxUint8)(255.0f * rdp.coladd[1]) - v->g;263int b = (wxUint8)(255.0f * rdp.coladd[2]) - v->b;264if (r < 0) r = 0;265if (g < 0) g = 0;266if (b < 0) b = 0;267v->r = (wxUint8)r;268v->g = (wxUint8)g;269v->b = (wxUint8)b;270}271v->shade_mod = cmb.shade_mod_hash;272}273if (rdp.cmb_flags_2 & CMB_INTER)274{275v->r = (wxUint8)(rdp.col_2[0] * rdp.shade_factor * 255.0f + v->r * (1.0f - rdp.shade_factor));276v->g = (wxUint8)(rdp.col_2[1] * rdp.shade_factor * 255.0f + v->g * (1.0f - rdp.shade_factor));277v->b = (wxUint8)(rdp.col_2[2] * rdp.shade_factor * 255.0f + v->b * (1.0f - rdp.shade_factor));278v->shade_mod = cmb.shade_mod_hash;279}280}281282static int dzdx = 0;283static int deltaZ = 0;284VERTEX **org_vtx;285286void draw_tri (VERTEX **vtx, wxUint16 linew)287{288deltaZ = dzdx = 0;289if (linew == 0 && (fb_depth_render_enabled || (rdp.rm & 0xC00) == 0xC00))290{291double X0 = vtx[0]->sx / rdp.scale_x;292double Y0 = vtx[0]->sy / rdp.scale_y;293double X1 = vtx[1]->sx / rdp.scale_x;294double Y1 = vtx[1]->sy / rdp.scale_y;295double X2 = vtx[2]->sx / rdp.scale_x;296double Y2 = vtx[2]->sy / rdp.scale_y;297double diffy_02 = Y0 - Y2;298double diffy_12 = Y1 - Y2;299double diffx_02 = X0 - X2;300double diffx_12 = X1 - X2;301302double denom = (diffx_02 * diffy_12 - diffx_12 * diffy_02);303if(denom*denom > 0.0)304{305double diffz_02 = vtx[0]->sz - vtx[2]->sz;306double diffz_12 = vtx[1]->sz - vtx[2]->sz;307double fdzdx = (diffz_02 * diffy_12 - diffz_12 * diffy_02) / denom;308if ((rdp.rm & 0xC00) == 0xC00) {309// Calculate deltaZ per polygon for Decal z-mode310double fdzdy = (diffz_02 * diffx_12 - diffz_12 * diffx_02) / denom;311double fdz = fabs(fdzdx) + fabs(fdzdy);312if ((settings.hacks & hack_Zelda) && (rdp.rm & 0x800))313fdz *= 4.0; // Decal mode in Zelda sometimes needs mutiplied deltaZ to work correct, e.g. roads314deltaZ = max(8, (int)fdz);315}316dzdx = (int)(fdzdx * 65536.0);317}318}319320org_vtx = vtx;321322for (int i=0; i<3; i++)323{324VERTEX *v = vtx[i];325326if (v->uv_calculated != rdp.tex_ctr)327{328#ifdef EXTREME_LOGGING329FRDP(" * CALCULATING VERTEX U/V: %d\n", v->number);330#endif331v->uv_calculated = rdp.tex_ctr;332333if (!(rdp.geom_mode & 0x00020000))334{335if (!(rdp.geom_mode & 0x00000200))336{337if (rdp.geom_mode & 0x00000004) // flat shading338{339int flag = min(2, (rdp.cmd1 >> 24) & 3);340v->a = vtx[flag]->a;341v->b = vtx[flag]->b;342v->g = vtx[flag]->g;343v->r = vtx[flag]->r;344#ifdef EXTREME_LOGGING345FRDP(" * Flat shaded, flag%d - r: %d, g: %d, b: %d, a: %d\n", flag, v->r, v->g, v->b, v->a);346#endif347}348else // prim color349{350#ifdef EXTREME_LOGGING351FRDP(" * Prim shaded %08lx\n", rdp.prim_color);352#endif353v->a = (wxUint8)(rdp.prim_color & 0xFF);354v->b = (wxUint8)((rdp.prim_color >> 8) & 0xFF);355v->g = (wxUint8)((rdp.prim_color >> 16) & 0xFF);356v->r = (wxUint8)((rdp.prim_color >> 24) & 0xFF);357}358}359}360361// Fix texture coordinates362if (!v->uv_scaled)363{364v->ou *= rdp.tiles[rdp.cur_tile].s_scale;365v->ov *= rdp.tiles[rdp.cur_tile].t_scale;366v->uv_scaled = 1;367if (!rdp.Persp_en)368{369// v->oow = v->w = 1.0f;370v->ou *= 0.5f;371v->ov *= 0.5f;372}373}374v->u1 = v->u0 = v->ou;375v->v1 = v->v0 = v->ov;376377if (rdp.tex >= 1 && rdp.cur_cache[0])378{379if (rdp.aTBuffTex[0])380{381v->u0 += rdp.aTBuffTex[0]->u_shift + rdp.aTBuffTex[0]->tile_uls;382v->v0 += rdp.aTBuffTex[0]->v_shift + rdp.aTBuffTex[0]->tile_ult;383}384385if (rdp.tiles[rdp.cur_tile].shift_s)386{387if (rdp.tiles[rdp.cur_tile].shift_s > 10)388v->u0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s));389else390v->u0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_s);391}392if (rdp.tiles[rdp.cur_tile].shift_t)393{394if (rdp.tiles[rdp.cur_tile].shift_t > 10)395v->v0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t));396else397v->v0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_t);398}399400if (rdp.aTBuffTex[0])401{402if (rdp.aTBuffTex[0]->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s)403v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;404if (rdp.aTBuffTex[0]->tile_ult != (int)rdp.tiles[rdp.cur_tile].f_ul_t || (settings.hacks&hack_Megaman))405v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t; //required for megaman (boss special attack)406v->u0 *= rdp.aTBuffTex[0]->u_scale;407v->v0 *= rdp.aTBuffTex[0]->v_scale;408#ifdef EXTREME_LOGGING409FRDP("tbuff_tex t0: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u0, v->v0);410#endif411}412else413{414v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;415v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t;416v->u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * v->u0;417v->v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * v->v0;418}419v->u0_w = v->u0 / v->w;420v->v0_w = v->v0 / v->w;421}422423if (rdp.tex >= 2 && rdp.cur_cache[1])424{425if (rdp.aTBuffTex[1])426{427v->u1 += rdp.aTBuffTex[1]->u_shift + rdp.aTBuffTex[1]->tile_uls;428v->v1 += rdp.aTBuffTex[1]->v_shift + rdp.aTBuffTex[1]->tile_ult;429}430if (rdp.tiles[rdp.cur_tile+1].shift_s)431{432if (rdp.tiles[rdp.cur_tile+1].shift_s > 10)433v->u1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s));434else435v->u1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_s);436}437if (rdp.tiles[rdp.cur_tile+1].shift_t)438{439if (rdp.tiles[rdp.cur_tile+1].shift_t > 10)440v->v1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t));441else442v->v1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_t);443}444445if (rdp.aTBuffTex[1])446{447if (rdp.aTBuffTex[1]->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s)448v->u1 -= rdp.tiles[rdp.cur_tile].f_ul_s;449v->u1 *= rdp.aTBuffTex[1]->u_scale;450v->v1 *= rdp.aTBuffTex[1]->v_scale;451#ifdef EXTREME_LOGGING452FRDP("tbuff_tex t1: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u1, v->v1);453#endif454}455else456{457v->u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s;458v->v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t;459v->u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * v->u1;460v->v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * v->v1;461}462463v->u1_w = v->u1 / v->w;464v->v1_w = v->v1 / v->w;465}466// 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);467}468#ifdef EXTREME_LOGGING469FRDP("draw_tri. v[%d] ou=%f, ov = %f\n", i, v->ou, v->ov);470#endif471if (v->shade_mod != cmb.shade_mod_hash)472apply_shade_mods (v);473} //for474475rdp.clip = 0;476477if ((vtx[0]->scr_off & 16) ||478(vtx[1]->scr_off & 16) ||479(vtx[2]->scr_off & 16))480rdp.clip |= CLIP_WMIN;481482vtx[0]->not_zclipped = vtx[1]->not_zclipped = vtx[2]->not_zclipped = 1;483484if (rdp.cur_cache[0] && (rdp.tex & 1) && (rdp.cur_cache[0]->splits > 1) && !rdp.aTBuffTex[0] && !rdp.clip)485{486int index,i,j, min_256,max_256, cur_256,left_256,right_256;487float percent;488489min_256 = min((int)vtx[0]->u0,(int)vtx[1]->u0); // bah, don't put two mins on one line490min_256 = min(min_256,(int)vtx[2]->u0) >> 8; // or it will be calculated twice491492max_256 = max((int)vtx[0]->u0,(int)vtx[1]->u0); // not like it makes much difference493max_256 = max(max_256,(int)vtx[2]->u0) >> 8; // anyway :P494495for (cur_256=min_256; cur_256<=max_256; cur_256++)496{497left_256 = cur_256 << 8;498right_256 = (cur_256+1) << 8;499500// Set vertex buffers501rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1502rdp.vtxbuf2 = rdp.vtx2;503rdp.vtx_buffer = 0;504rdp.n_global = 3;505index = 0;506507// ** Left plane **508for (i=0; i<3; i++)509{510j = i+1;511if (j == 3) j = 0;512513VERTEX *v1 = vtx[i];514VERTEX *v2 = vtx[j];515516if (v1->u0 >= left_256)517{518if (v2->u0 >= left_256) // Both are in, save the last one519{520rdp.vtxbuf[index] = *v2;521rdp.vtxbuf[index].u0 -= left_256;522rdp.vtxbuf[index++].v0 += cur_256 * rdp.cur_cache[0]->splitheight;523}524else // First is in, second is out, save intersection525{526percent = (left_256 - v1->u0) / (v2->u0 - v1->u0);527rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent;528rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent;529rdp.vtxbuf[index].z = v1->z + (v2->z - v1->z) * percent;530rdp.vtxbuf[index].w = v1->w + (v2->w - v1->w) * percent;531rdp.vtxbuf[index].f = v1->f + (v2->f - v1->f) * percent;532rdp.vtxbuf[index].u0 = 0.5f;533rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent +534cur_256 * rdp.cur_cache[0]->splitheight;535rdp.vtxbuf[index].u1 = v1->u1 + (v2->u1 - v1->u1) * percent;536rdp.vtxbuf[index].v1 = v1->v1 + (v2->v1 - v1->v1) * percent;537rdp.vtxbuf[index].b = (wxUint8)(v1->b + (v2->b - v1->b) * percent);538rdp.vtxbuf[index].g = (wxUint8)(v1->g + (v2->g - v1->g) * percent);539rdp.vtxbuf[index].r = (wxUint8)(v1->r + (v2->r - v1->r) * percent);540rdp.vtxbuf[index++].a = (wxUint8)(v1->a + (v2->a - v1->a) * percent);541}542}543else544{545//if (v2->u0 < left_256) // Both are out, save nothing546if (v2->u0 >= left_256) // First is out, second is in, save intersection & in point547{548percent = (left_256 - v2->u0) / (v1->u0 - v2->u0);549rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent;550rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent;551rdp.vtxbuf[index].z = v2->z + (v1->z - v2->z) * percent;552rdp.vtxbuf[index].w = v2->w + (v1->w - v2->w) * percent;553rdp.vtxbuf[index].f = v2->f + (v1->f - v2->f) * percent;554rdp.vtxbuf[index].u0 = 0.5f;555rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent +556cur_256 * rdp.cur_cache[0]->splitheight;557rdp.vtxbuf[index].u1 = v2->u1 + (v1->u1 - v2->u1) * percent;558rdp.vtxbuf[index].v1 = v2->v1 + (v1->v1 - v2->v1) * percent;559rdp.vtxbuf[index].b = (wxUint8)(v2->b + (v1->b - v2->b) * percent);560rdp.vtxbuf[index].g = (wxUint8)(v2->g + (v1->g - v2->g) * percent);561rdp.vtxbuf[index].r = (wxUint8)(v2->r + (v1->r - v2->r) * percent);562rdp.vtxbuf[index++].a = (wxUint8)(v2->a + (v1->a - v2->a) * percent);563564// Save the in point565rdp.vtxbuf[index] = *v2;566rdp.vtxbuf[index].u0 -= left_256;567rdp.vtxbuf[index++].v0 += cur_256 * rdp.cur_cache[0]->splitheight;568}569}570}571rdp.n_global = index;572573rdp.vtxbuf = rdp.vtx2; // now vtx1 holds the value, & vtx2 is the destination574rdp.vtxbuf2 = rdp.vtx1;575rdp.vtx_buffer ^= 1;576index = 0;577578for (i=0; i<rdp.n_global; i++)579{580j = i+1;581if (j == rdp.n_global) j = 0;582583VERTEX *v1 = &rdp.vtxbuf2[i];584VERTEX *v2 = &rdp.vtxbuf2[j];585586// ** Right plane **587if (v1->u0 <= right_256)588{589if (v2->u0 <= right_256) // Both are in, save the last one590{591rdp.vtxbuf[index] = *v2;592rdp.vtxbuf[index++].not_zclipped = 0;593}594else // First is in, second is out, save intersection595{596percent = (right_256 - v1->u0) / (v2->u0 - v1->u0);597rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent;598rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent;599rdp.vtxbuf[index].z = v1->z + (v2->z - v1->z) * percent;600rdp.vtxbuf[index].w = v1->w + (v2->w - v1->w) * percent;601rdp.vtxbuf[index].f = v1->f + (v2->f - v1->f) * percent;602rdp.vtxbuf[index].u0 = 255.5f;603rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent;604rdp.vtxbuf[index].u1 = v1->u1 + (v2->u1 - v1->u1) * percent;605rdp.vtxbuf[index].v1 = v1->v1 + (v2->v1 - v1->v1) * percent;606rdp.vtxbuf[index].b = (wxUint8)(v1->b + (v2->b - v1->b) * percent);607rdp.vtxbuf[index].g = (wxUint8)(v1->g + (v2->g - v1->g) * percent);608rdp.vtxbuf[index].r = (wxUint8)(v1->r + (v2->r - v1->r) * percent);609rdp.vtxbuf[index].a = (wxUint8)(v1->a + (v2->a - v1->a) * percent);610rdp.vtxbuf[index++].not_zclipped = 0;611}612}613else614{615//if (v2->u0 > 256.0f) // Both are out, save nothing616if (v2->u0 <= right_256) // First is out, second is in, save intersection & in point617{618percent = (right_256 - v2->u0) / (v1->u0 - v2->u0);619rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent;620rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent;621rdp.vtxbuf[index].z = v2->z + (v1->z - v2->z) * percent;622rdp.vtxbuf[index].w = v2->w + (v1->w - v2->w) * percent;623rdp.vtxbuf[index].f = v2->f + (v1->f - v2->f) * percent;624rdp.vtxbuf[index].u0 = 255.5f;625rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent;626rdp.vtxbuf[index].u1 = v2->u1 + (v1->u1 - v2->u1) * percent;627rdp.vtxbuf[index].v1 = v2->v1 + (v1->v1 - v2->v1) * percent;628rdp.vtxbuf[index].b = (wxUint8)(v2->b + (v1->b - v2->b) * percent);629rdp.vtxbuf[index].g = (wxUint8)(v2->g + (v1->g - v2->g) * percent);630rdp.vtxbuf[index].r = (wxUint8)(v2->r + (v1->r - v2->r) * percent);631rdp.vtxbuf[index].a = (wxUint8)(v2->a + (v1->a - v2->a) * percent);632rdp.vtxbuf[index++].not_zclipped = 0;633634// Save the in point635rdp.vtxbuf[index] = *v2;636rdp.vtxbuf[index++].not_zclipped = 0;637}638}639}640rdp.n_global = index;641642do_triangle_stuff (linew, TRUE);643}644}645else646{647// Set vertex buffers648rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1649rdp.vtxbuf2 = rdp.vtx2;650rdp.vtx_buffer = 0;651rdp.n_global = 3;652653rdp.vtxbuf[0] = *vtx[0];654rdp.vtxbuf[0].number = 1;655rdp.vtxbuf[1] = *vtx[1];656rdp.vtxbuf[1].number = 2;657rdp.vtxbuf[2] = *vtx[2];658rdp.vtxbuf[2].number = 4;659660do_triangle_stuff (linew, FALSE);661}662}663664#define interp2p(a, b, r) (a + (b - a) * r)665666//*667static void InterpolateColors(VERTEX & va, VERTEX & vb, VERTEX & res, float percent)668{669res.b = (wxUint8)interp2p(va.b, vb.b, percent);670res.g = (wxUint8)interp2p(va.g, vb.g, percent);;671res.r = (wxUint8)interp2p(va.r, vb.r, percent);;672res.a = (wxUint8)interp2p(va.a, vb.a, percent);;673res.f = interp2p(va.f, vb.f, percent);;674}675//*/676//677// clip_w - clips aint the z-axis678//679static void clip_w (int interpolate_colors)680{681int i,j,index,n=rdp.n_global;682float percent;683// Swap vertex buffers684VERTEX *tmp = rdp.vtxbuf2;685rdp.vtxbuf2 = rdp.vtxbuf;686rdp.vtxbuf = tmp;687rdp.vtx_buffer ^= 1;688index = 0;689690// Check the vertices for clipping691for (i=0; i<n; i++)692{693j = i+1;694if (j == 3) j = 0;695696if (Vi.w >= 0.01f)697{698if (Vj.w >= 0.01f) // Both are in, save the last one699{700rdp.vtxbuf[index] = Vj;701rdp.vtxbuf[index++].not_zclipped = 1;702}703else // First is in, second is out, save intersection704{705percent = (-Vi.w) / (Vj.w - Vi.w);706rdp.vtxbuf[index].not_zclipped = 0;707rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;708rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;709rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;710rdp.vtxbuf[index].w = 0.01f;711rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;712rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;713rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;714rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;715if (interpolate_colors)716InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);717else718rdp.vtxbuf[index++].number = Vi.number | Vj.number;719}720}721else722{723//if (Vj.w < 0.01f) // Both are out, save nothing724if (Vj.w >= 0.01f) // First is out, second is in, save intersection & in point725{726percent = (-Vj.w) / (Vi.w - Vj.w);727rdp.vtxbuf[index].not_zclipped = 0;728rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;729rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;730rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;731rdp.vtxbuf[index].w = 0.01f;732rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;733rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;734rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;735rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;736if (interpolate_colors)737InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);738else739rdp.vtxbuf[index++].number = Vi.number | Vj.number;740741// Save the in point742rdp.vtxbuf[index] = Vj;743rdp.vtxbuf[index++].not_zclipped = 1;744}745}746}747rdp.n_global = index;748}749750static void render_tri (wxUint16 linew, int old_interpolate);751752void do_triangle_stuff (wxUint16 linew, int old_interpolate) // what else?? do the triangle stuff :P (to keep from writing code twice)753{754int i;755756if (rdp.clip & CLIP_WMIN)757clip_w (old_interpolate);758759float maxZ = (rdp.zsrc != 1) ? rdp.view_trans[2] + rdp.view_scale[2] : rdp.prim_depth;760761wxUint8 no_clip = 2;762for (i=0; i<rdp.n_global; i++)763{764if (rdp.vtxbuf[i].not_zclipped)// && rdp.zsrc != 1)765{766#ifdef EXTREME_LOGGING767FRDP (" * NOT ZCLIPPPED: %d\n", rdp.vtxbuf[i].number);768#endif769rdp.vtxbuf[i].x = rdp.vtxbuf[i].sx;770rdp.vtxbuf[i].y = rdp.vtxbuf[i].sy;771rdp.vtxbuf[i].z = rdp.vtxbuf[i].sz;772rdp.vtxbuf[i].q = rdp.vtxbuf[i].oow;773rdp.vtxbuf[i].u0 = rdp.vtxbuf[i].u0_w;774rdp.vtxbuf[i].v0 = rdp.vtxbuf[i].v0_w;775rdp.vtxbuf[i].u1 = rdp.vtxbuf[i].u1_w;776rdp.vtxbuf[i].v1 = rdp.vtxbuf[i].v1_w;777}778else779{780#ifdef EXTREME_LOGGING781FRDP (" * ZCLIPPED: %d\n", rdp.vtxbuf[i].number);782#endif783rdp.vtxbuf[i].q = 1.0f / rdp.vtxbuf[i].w;784rdp.vtxbuf[i].x = rdp.view_trans[0] + rdp.vtxbuf[i].x * rdp.vtxbuf[i].q * rdp.view_scale[0] + rdp.offset_x;785rdp.vtxbuf[i].y = rdp.view_trans[1] + rdp.vtxbuf[i].y * rdp.vtxbuf[i].q * rdp.view_scale[1] + rdp.offset_y;786rdp.vtxbuf[i].z = rdp.view_trans[2] + rdp.vtxbuf[i].z * rdp.vtxbuf[i].q * rdp.view_scale[2];787if (rdp.tex >= 1)788{789rdp.vtxbuf[i].u0 *= rdp.vtxbuf[i].q;790rdp.vtxbuf[i].v0 *= rdp.vtxbuf[i].q;791}792if (rdp.tex >= 2)793{794rdp.vtxbuf[i].u1 *= rdp.vtxbuf[i].q;795rdp.vtxbuf[i].v1 *= rdp.vtxbuf[i].q;796}797}798799if (rdp.zsrc == 1)800rdp.vtxbuf[i].z = rdp.prim_depth;801802// Don't remove clipping, or it will freeze803if (rdp.vtxbuf[i].x > rdp.clip_max_x) rdp.clip |= CLIP_XMAX;804if (rdp.vtxbuf[i].x < rdp.clip_min_x) rdp.clip |= CLIP_XMIN;805if (rdp.vtxbuf[i].y > rdp.clip_max_y) rdp.clip |= CLIP_YMAX;806if (rdp.vtxbuf[i].y < rdp.clip_min_y) rdp.clip |= CLIP_YMIN;807if (rdp.vtxbuf[i].z > maxZ) rdp.clip |= CLIP_ZMAX;808if (rdp.vtxbuf[i].z < 0.0f) rdp.clip |= CLIP_ZMIN;809no_clip &= rdp.vtxbuf[i].screen_translated;810}811if (no_clip)812rdp.clip = 0;813else814{815if (!settings.clip_zmin)816rdp.clip &= ~CLIP_ZMIN;817if (!settings.clip_zmax)818rdp.clip &= ~CLIP_ZMAX;819}820render_tri (linew, old_interpolate);821}822823void do_triangle_stuff_2 (wxUint16 linew)824{825rdp.clip = 0;826827for (int i=0; i<rdp.n_global; i++)828{829// Don't remove clipping, or it will freeze830if (rdp.vtxbuf[i].x > rdp.clip_max_x) rdp.clip |= CLIP_XMAX;831if (rdp.vtxbuf[i].x < rdp.clip_min_x) rdp.clip |= CLIP_XMIN;832if (rdp.vtxbuf[i].y > rdp.clip_max_y) rdp.clip |= CLIP_YMAX;833if (rdp.vtxbuf[i].y < rdp.clip_min_y) rdp.clip |= CLIP_YMIN;834}835836render_tri (linew, TRUE);837}838839__inline wxUint8 real_to_char(double x)840{841return (wxUint8)(((int)floor(x+0.5))&0xFF);842}843844//*845static void InterpolateColors2(VERTEX & va, VERTEX & vb, VERTEX & res, float percent)846{847float w = 1.0f/(va.oow + (vb.oow-va.oow) * percent);848// res.oow = va.oow + (vb.oow-va.oow) * percent;849// res.q = res.oow;850float ba = va.b * va.oow;851float bb = vb.b * vb.oow;852res.b = real_to_char(interp2p(ba, bb, percent) * w);853float ga = va.g * va.oow;854float gb = vb.g * vb.oow;855res.g = real_to_char(interp2p(ga, gb, percent) * w);856float ra = va.r * va.oow;857float rb = vb.r * vb.oow;858res.r = real_to_char(interp2p(ra, rb, percent) * w);859float aa = va.a * va.oow;860float ab = vb.a * vb.oow;861res.a = real_to_char(interp2p(aa, ab, percent) * w);862float fa = va.f * va.oow;863float fb = vb.f * vb.oow;864res.f = interp2p(fa, fb, percent) * w;865/*866float u0a = va.u0_w * va.oow;867float u0b = vb.u0_w * vb.oow;868res.u0 = (u0a + (u0b - u0a) * percent) * w;869float v0a = va.v0_w * va.oow;870float v0b = vb.v0_w * vb.oow;871res.v0 = (v0a + (v0b - v0a) * percent) * w;872float u1a = va.u1_w * va.oow;873float u1b = vb.u1_w * vb.oow;874res.u1 = (u1a + (u1b - u1a) * percent) * w;875float v1a = va.v1_w * va.oow;876float v1b = vb.v1_w * vb.oow;877res.v1 = (v1a + (v1b - v1a) * percent) * w;878*/879}880//*/881882typedef struct {883double d;884double x;885double y;886} LineEuqationType;887888static double EvaLine(LineEuqationType &li, double x, double y)889{890return li.x*x+li.y*y+li.d;891}892893static void Create1LineEq(LineEuqationType &l, VERTEX &v1, VERTEX &v2, VERTEX &v3)894{895// Line between (x1,y1) to (x2,y2)896l.x = v2.sy-v1.sy;897l.y = v1.sx-v2.sx;898l.d = -(l.x*v2.sx+(l.y)*v2.sy);899if (EvaLine(l,v3.sx,v3.sy)*v3.oow < 0)900{901l.x = -l.x;902l.y = -l.y;903l.d = -l.d;904}905}906907908__inline double interp3p(float a, float b, float c, double r1, double r2)909{910return (a)+(((b)+((c)-(b))*(r2))-(a))*(r1);911}912/*913#define interp3p(a, b, c, r1, r2) \914(a+(((b)+((c)-(b))*(r2))-(a))*(r1))915*/916917static void InterpolateColors3(VERTEX &v1, VERTEX &v2, VERTEX &v3, VERTEX &out)918{919920LineEuqationType line;921Create1LineEq(line, v2, v3, v1);922923double aDot = (out.x*line.x + out.y*line.y);924double bDot = (v1.sx*line.x + v1.sy*line.y);925926double scale1 = ( - line.d - aDot) / ( bDot - aDot );927928double tx = out.x + scale1 * (v1.sx - out.x);929double ty = out.y + scale1 * (v1.sy - out.y);930931double s1 = 101.0, s2 = 101.0;932double den = tx - v1.sx;933if (fabs(den) > 1.0)934s1 = (out.x-v1.sx)/den;935if (s1 > 100.0f)936s1 = (out.y-v1.sy)/(ty-v1.sy);937938den = v3.sx - v2.sx;939if (fabs(den) > 1.0)940s2 = (tx-v2.sx)/den;941if (s2 > 100.0f)942s2 =(ty-v2.sy)/(v3.sy-v2.sy);943944double w = 1.0/interp3p(v1.oow,v2.oow,v3.oow,s1,s2);945946out.r = real_to_char(interp3p(v1.r*v1.oow,v2.r*v2.oow,v3.r*v3.oow,s1,s2)*w);947out.g = real_to_char(interp3p(v1.g*v1.oow,v2.g*v2.oow,v3.g*v3.oow,s1,s2)*w);948out.b = real_to_char(interp3p(v1.b*v1.oow,v2.b*v2.oow,v3.b*v3.oow,s1,s2)*w);949out.a = real_to_char(interp3p(v1.a*v1.oow,v2.a*v2.oow,v3.a*v3.oow,s1,s2)*w);950out.f = (float)(interp3p(v1.f*v1.oow,v2.f*v2.oow,v3.f*v3.oow,s1,s2)*w);951/*952out.u0 = interp3p(v1.u0_w*v1.oow,v2.u0_w*v2.oow,v3.u0_w*v3.oow,s1,s2)/oow;953out.v0 = interp3p(v1.v0_w*v1.oow,v2.v0_w*v2.oow,v3.v0_w*v3.oow,s1,s2)/oow;954out.u1 = interp3p(v1.u1_w*v1.oow,v2.u1_w*v2.oow,v3.u1_w*v3.oow,s1,s2)/oow;955out.v1 = interp3p(v1.v1_w*v1.oow,v2.v1_w*v2.oow,v3.v1_w*v3.oow,s1,s2)/oow;956*/957}958959static void CalculateLOD(VERTEX *v, int n)960{961//rdp.update |= UPDATE_TEXTURE;962/*963if (rdp.lod_calculated)964{965float detailmax;966if (dc0_detailmax < 0.5)967detailmax = rdp.lod_fraction;968else969detailmax = 1.0f - rdp.lod_fraction;970grTexDetailControl (GR_TMU0, dc0_lodbias, dc0_detailscale, detailmax);971if (num_tmu == 2)972grTexDetailControl (GR_TMU1, dc1_lodbias, dc1_detailscale, detailmax);973return;974}975*/976float deltaS, deltaT;977float deltaX, deltaY;978double deltaTexels, deltaPixels, lodFactor = 0;979double intptr;980float s_scale = rdp.tiles[rdp.cur_tile].width / 255.0f;981float t_scale = rdp.tiles[rdp.cur_tile].height / 255.0f;982if (settings.lodmode == 1)983{984deltaS = (v[1].u0/v[1].q - v[0].u0/v[0].q) * s_scale;985deltaT = (v[1].v0/v[1].q - v[0].v0/v[0].q) * t_scale;986deltaTexels = sqrt( deltaS * deltaS + deltaT * deltaT );987988deltaX = (v[1].x - v[0].x)/rdp.scale_x;989deltaY = (v[1].y - v[0].y)/rdp.scale_y;990deltaPixels = sqrt( deltaX * deltaX + deltaY * deltaY );991992lodFactor = deltaTexels / deltaPixels;993}994else995{996int i, j;997for (i = 0; i < n; i++)998{999j = (i < n-1) ? i + 1 : 0;10001001deltaS = (v[j].u0/v[j].q - v[i].u0/v[i].q) * s_scale;1002deltaT = (v[j].v0/v[j].q - v[i].v0/v[i].q) * t_scale;1003// deltaS = v[j].ou - v[i].ou;1004// deltaT = v[j].ov - v[i].ov;1005deltaTexels = sqrt( deltaS * deltaS + deltaT * deltaT );10061007deltaX = (v[j].x - v[i].x)/rdp.scale_x;1008deltaY = (v[j].y - v[i].y)/rdp.scale_y;1009deltaPixels = sqrt( deltaX * deltaX + deltaY * deltaY );10101011lodFactor += deltaTexels / deltaPixels;1012}1013// Divide by n (n edges) to find average1014lodFactor = lodFactor / n;1015}1016int ilod = (int)lodFactor;1017int lod_tile = min((int)(log10f((float)ilod)/log10f(2.0f)), rdp.cur_tile + rdp.mipmap_level);1018float lod_fraction = 1.0f;1019if (lod_tile < rdp.cur_tile + rdp.mipmap_level)1020{1021lod_fraction = max((float)modf(lodFactor / pow(2.,lod_tile),&intptr), rdp.prim_lodmin / 255.0f);1022}1023float detailmax;1024if (cmb.dc0_detailmax < 0.5f)1025detailmax = lod_fraction;1026else1027detailmax = 1.0f - lod_fraction;1028grTexDetailControl (GR_TMU0, cmb.dc0_lodbias, cmb.dc0_detailscale, detailmax);1029if (voodoo.num_tmu == 2)1030grTexDetailControl (GR_TMU1, cmb.dc1_lodbias, cmb.dc1_detailscale, detailmax);1031FRDP("CalculateLOD factor: %f, tile: %d, lod_fraction: %f\n", (float)lodFactor, lod_tile, lod_fraction);1032}10331034float ScaleZ(float z)1035{1036if (settings.n64_z_scale)1037{1038int iz = (int)(z*8.0f+0.5f);1039if (iz < 0) iz = 0;1040else if (iz >= 0x40000) iz = 0x40000 - 1;1041return (float)zLUT[iz];1042}1043if (z < 0.0f) return 0.0f;1044z *= 1.9f;1045if (z > 65534.0f) return 65534.0f;1046return z;1047}10481049static void DepthBuffer(VERTEX * vtx, int n)1050{1051if (fb_depth_render_enabled && !(settings.hacks&hack_RE2) && dzdx && (rdp.flags & ZBUF_UPDATE))1052{1053vertexi v[12];1054if (u_cull_mode == 1) //cull front1055{1056for(int i=0; i<n; i++)1057{1058v[i].x = (int)((vtx[n-i-1].x-rdp.offset_x) / rdp.scale_x * 65536.0);1059v[i].y = (int)((vtx[n-i-1].y-rdp.offset_y) / rdp.scale_y * 65536.0);1060v[i].z = (int)(vtx[n-i-1].z * 65536.0);1061}1062}1063else1064{1065for(int i=0; i<n; i++)1066{1067v[i].x = (int)((vtx[i].x-rdp.offset_x) / rdp.scale_x * 65536.0);1068v[i].y = (int)((vtx[i].y-rdp.offset_y) / rdp.scale_y * 65536.0);1069v[i].z = (int)(vtx[i].z * 65536.0);1070}1071}1072Rasterize(v, n, dzdx);1073}1074for(int i=0; i<n; i++)1075vtx[i].z = ScaleZ(vtx[i].z);1076}10771078/*1079std::ofstream loga;1080#define LOGG(x) loga.open("glide_log.txt",std::ios::app); loga << x; loga.flush(); loga.close();1081__inline void FRDP2(char *fmt, ...)1082{1083va_list ap;1084va_start(ap, fmt);1085vsprintf(out_buf, fmt, ap);1086LOGG(out_buf);1087va_end(ap);1088}1089//*/1090//#define LOGG(x)1091//#define FRDP2(x)109210931094void clip_tri(int interpolate_colors)1095{1096int i,j,index,n=rdp.n_global;1097float percent;10981099// Check which clipping is needed1100if (rdp.clip & CLIP_XMAX) // right of the screen1101{1102// Swap vertex buffers1103VERTEX *tmp = rdp.vtxbuf2;1104rdp.vtxbuf2 = rdp.vtxbuf;1105rdp.vtxbuf = tmp;1106rdp.vtx_buffer ^= 1;1107index = 0;11081109// Check the vertices for clipping1110for (i=0; i<n; i++)1111{1112j = i+1;1113if (j == n) j = 0;11141115if (Vi.x <= rdp.clip_max_x)1116{1117if (Vj.x <= rdp.clip_max_x) // Both are in, save the last one1118{1119rdp.vtxbuf[index++] = Vj;1120}1121else // First is in, second is out, save intersection1122{1123percent = (rdp.clip_max_x - Vi.x) / (Vj.x - Vi.x);1124rdp.vtxbuf[index].x = rdp.clip_max_x;1125rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;1126rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;1127rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;1128rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;1129rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;1130rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;1131rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;1132if (interpolate_colors)1133InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);1134else1135rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8;1136}1137}1138else1139{1140//if (Vj.x > rdp.clip_max_x) // Both are out, save nothing1141if (Vj.x <= rdp.clip_max_x) // First is out, second is in, save intersection & in point1142{1143percent = (rdp.clip_max_x - Vj.x) / (Vi.x - Vj.x);1144rdp.vtxbuf[index].x = rdp.clip_max_x;1145rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;1146rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;1147rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;1148rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;1149rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;1150rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;1151rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;1152if (interpolate_colors)1153InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);1154else1155rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8;11561157// Save the in point1158rdp.vtxbuf[index++] = Vj;1159}1160}1161}1162n = index;1163}1164if (rdp.clip & CLIP_XMIN) // left of the screen1165{1166// Swap vertex buffers1167VERTEX *tmp = rdp.vtxbuf2;1168rdp.vtxbuf2 = rdp.vtxbuf;1169rdp.vtxbuf = tmp;1170rdp.vtx_buffer ^= 1;1171index = 0;11721173// Check the vertices for clipping1174for (i=0; i<n; i++)1175{1176j = i+1;1177if (j == n) j = 0;11781179if (Vi.x >= rdp.clip_min_x)1180{1181if (Vj.x >= rdp.clip_min_x) // Both are in, save the last one1182{1183rdp.vtxbuf[index++] = Vj;1184}1185else // First is in, second is out, save intersection1186{1187percent = (rdp.clip_min_x - Vi.x) / (Vj.x - Vi.x);1188rdp.vtxbuf[index].x = rdp.clip_min_x;1189rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;1190rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;1191rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;1192rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;1193rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;1194rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;1195rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;1196if (interpolate_colors)1197InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);1198else1199rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8;1200}1201}1202else1203{1204//if (Vj.x < rdp.clip_min_x) // Both are out, save nothing1205if (Vj.x >= rdp.clip_min_x) // First is out, second is in, save intersection & in point1206{1207percent = (rdp.clip_min_x - Vj.x) / (Vi.x - Vj.x);1208rdp.vtxbuf[index].x = rdp.clip_min_x;1209rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;1210rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;1211rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;1212rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;1213rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;1214rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;1215rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;1216if (interpolate_colors)1217InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);1218else1219rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8;12201221// Save the in point1222rdp.vtxbuf[index++] = Vj;1223}1224}1225}1226n = index;1227}1228if (rdp.clip & CLIP_YMAX) // top of the screen1229{1230// Swap vertex buffers1231VERTEX *tmp = rdp.vtxbuf2;1232rdp.vtxbuf2 = rdp.vtxbuf;1233rdp.vtxbuf = tmp;1234rdp.vtx_buffer ^= 1;1235index = 0;12361237// Check the vertices for clipping1238for (i=0; i<n; i++)1239{1240j = i+1;1241if (j == n) j = 0;12421243if (Vi.y <= rdp.clip_max_y)1244{1245if (Vj.y <= rdp.clip_max_y) // Both are in, save the last one1246{1247rdp.vtxbuf[index++] = Vj;1248}1249else // First is in, second is out, save intersection1250{1251percent = (rdp.clip_max_y - Vi.y) / (Vj.y - Vi.y);1252rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;1253rdp.vtxbuf[index].y = rdp.clip_max_y;1254rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;1255rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;1256rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;1257rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;1258rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;1259rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;1260if (interpolate_colors)1261InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);1262else1263rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16;1264}1265}1266else1267{1268//if (Vj.y > rdp.clip_max_y) // Both are out, save nothing1269if (Vj.y <= rdp.clip_max_y) // First is out, second is in, save intersection & in point1270{1271percent = (rdp.clip_max_y - Vj.y) / (Vi.y - Vj.y);1272rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;1273rdp.vtxbuf[index].y = rdp.clip_max_y;1274rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;1275rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;1276rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;1277rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;1278rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;1279rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;1280if (interpolate_colors)1281InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);1282else1283rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16;12841285// Save the in point1286rdp.vtxbuf[index++] = Vj;1287}1288}1289}1290n = index;1291}1292if (rdp.clip & CLIP_YMIN) // bottom of the screen1293{1294// Swap vertex buffers1295VERTEX *tmp = rdp.vtxbuf2;1296rdp.vtxbuf2 = rdp.vtxbuf;1297rdp.vtxbuf = tmp;1298rdp.vtx_buffer ^= 1;1299index = 0;13001301// Check the vertices for clipping1302for (i=0; i<n; i++)1303{1304j = i+1;1305if (j == n) j = 0;13061307if (Vi.y >= rdp.clip_min_y)1308{1309if (Vj.y >= rdp.clip_min_y) // Both are in, save the last one1310{1311rdp.vtxbuf[index++] = Vj;1312}1313else // First is in, second is out, save intersection1314{1315percent = (rdp.clip_min_y - Vi.y) / (Vj.y - Vi.y);1316rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;1317rdp.vtxbuf[index].y = rdp.clip_min_y;1318rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;1319rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;1320rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;1321rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;1322rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;1323rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;1324if (interpolate_colors)1325InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);1326else1327rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16;1328}1329}1330else1331{1332//if (Vj.y < rdp.clip_min_y) // Both are out, save nothing1333if (Vj.y >= rdp.clip_min_y) // First is out, second is in, save intersection & in point1334{1335percent = (rdp.clip_min_y - Vj.y) / (Vi.y - Vj.y);1336rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;1337rdp.vtxbuf[index].y = rdp.clip_min_y;1338rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;1339rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;1340rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;1341rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;1342rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;1343rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;1344if (interpolate_colors)1345InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);1346else1347rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16;13481349// Save the in point1350rdp.vtxbuf[index++] = Vj;1351}1352}1353}1354n = index;1355}1356if (rdp.clip & CLIP_ZMAX) // far plane1357{1358// Swap vertex buffers1359VERTEX *tmp = rdp.vtxbuf2;1360rdp.vtxbuf2 = rdp.vtxbuf;1361rdp.vtxbuf = tmp;1362rdp.vtx_buffer ^= 1;1363index = 0;1364float maxZ = rdp.view_trans[2] + rdp.view_scale[2];13651366// Check the vertices for clipping1367for (i=0; i<n; i++)1368{1369j = i+1;1370if (j == n) j = 0;13711372if (Vi.z < maxZ)1373{1374if (Vj.z < maxZ) // Both are in, save the last one1375{1376rdp.vtxbuf[index++] = Vj;1377}1378else // First is in, second is out, save intersection1379{1380percent = (maxZ - Vi.z) / (Vj.z - Vi.z);1381rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;1382rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;1383rdp.vtxbuf[index].z = maxZ - 0.001f;1384rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;1385rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;1386rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;1387rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;1388rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;1389if (interpolate_colors)1390InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);1391else1392rdp.vtxbuf[index++].number = Vi.number | Vj.number;1393}1394}1395else1396{1397//if (Vj.z > maxZ) // Both are out, save nothing1398if (Vj.z < maxZ) // First is out, second is in, save intersection & in point1399{1400percent = (maxZ - Vj.z) / (Vi.z - Vj.z);1401rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;1402rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;1403rdp.vtxbuf[index].z = maxZ - 0.001f;;1404rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;1405rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;1406rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;1407rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;1408rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;1409if (interpolate_colors)1410InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);1411else1412rdp.vtxbuf[index++].number = Vi.number | Vj.number;14131414// Save the in point1415rdp.vtxbuf[index++] = Vj;1416}1417}1418}1419n = index;1420}1421/*1422if (rdp.clip & CLIP_ZMIN) // near Z1423{1424// Swap vertex buffers1425VERTEX *tmp = rdp.vtxbuf2;1426rdp.vtxbuf2 = rdp.vtxbuf;1427rdp.vtxbuf = tmp;1428rdp.vtx_buffer ^= 1;1429index = 0;14301431// Check the vertices for clipping1432for (i=0; i<n; i++)1433{1434j = i+1;1435if (j == n) j = 0;14361437if (Vi.z >= 0.0f)1438{1439if (Vj.z >= 0.0f) // Both are in, save the last one1440{1441rdp.vtxbuf[index++] = Vj;1442}1443else // First is in, second is out, save intersection1444{1445percent = (-Vi.z) / (Vj.z - Vi.z);1446rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;1447rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;1448rdp.vtxbuf[index].z = 0.0f;1449rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;1450rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;1451rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;1452rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;1453rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;1454if (interpolate_colors)1455InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);1456else1457rdp.vtxbuf[index++].number = Vi.number | Vj.number;1458}1459}1460else1461{1462//if (Vj.z < 0.0f) // Both are out, save nothing1463if (Vj.z >= 0.0f) // First is out, second is in, save intersection & in point1464{1465percent = (-Vj.z) / (Vi.z - Vj.z);1466rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;1467rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;1468rdp.vtxbuf[index].z = 0.0f;;1469rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;1470rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;1471rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;1472rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;1473rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;1474if (interpolate_colors)1475InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);1476else1477rdp.vtxbuf[index++].number = Vi.number | Vj.number;14781479// Save the in point1480rdp.vtxbuf[index++] = Vj;1481}1482}1483}1484n = index;1485}1486*/1487rdp.n_global = n;1488}14891490static void render_tri (wxUint16 linew, int old_interpolate)1491{1492if (rdp.clip)1493clip_tri(old_interpolate);1494int n = rdp.n_global;1495if (n < 3)1496{1497FRDP (" * render_tri: n < 3\n");1498return;1499}1500int i,j;1501//*1502if ((rdp.clip & CLIP_ZMIN) && (rdp.othermode_l & 0x00000030))1503{15041505int to_render = FALSE;1506for (i = 0; i < n; i++)1507{1508if (rdp.vtxbuf[i].z >= 0.0f)1509{1510to_render = TRUE;1511break;1512}1513}1514if (!to_render) //all z < 01515{1516FRDP (" * render_tri: all z < 0\n");1517return;1518}1519}1520//*/1521if (rdp.clip && !old_interpolate)1522{1523for (i = 0; i < n; i++)1524{1525float percent = 101.0f;1526VERTEX * v1 = 0, * v2 = 0;1527switch (rdp.vtxbuf[i].number&7)1528{1529case 1:1530case 2:1531case 4:1532continue;1533break;1534case 3:1535v1 = org_vtx[0];1536v2 = org_vtx[1];1537break;1538case 5:1539v1 = org_vtx[0];1540v2 = org_vtx[2];1541break;1542case 6:1543v1 = org_vtx[1];1544v2 = org_vtx[2];1545break;1546case 7:1547InterpolateColors3(*org_vtx[0], *org_vtx[1], *org_vtx[2], rdp.vtxbuf[i]);1548continue;1549break;1550}1551switch (rdp.vtxbuf[i].number&24)1552{1553case 8:1554percent = (rdp.vtxbuf[i].x-v1->sx)/(v2->sx-v1->sx);1555break;1556case 16:1557percent = (rdp.vtxbuf[i].y-v1->sy)/(v2->sy-v1->sy);1558break;1559default:1560{1561float d = (v2->sx-v1->sx);1562if (fabs(d) > 1.0)1563percent = (rdp.vtxbuf[i].x-v1->sx)/d;1564if (percent > 100.0f)1565percent = (rdp.vtxbuf[i].y-v1->sy)/(v2->sy-v1->sy);1566}1567}1568InterpolateColors2(*v1, *v2, rdp.vtxbuf[i], percent);1569}1570}1571/*1572if (rdp.clip)1573{1574LOGG("Colors before clipping:\n");1575unsigned int k;1576for(k=0; k<3; k++)1577{1578FRDP2("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);1579}1580FRDP("Got %d vertex after clipping\n", n);1581for(k=0; k<n; k++)1582{1583FRDP("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);1584}1585}1586*/15871588ConvertCoordsConvert (rdp.vtxbuf, n);1589if (rdp.fog_mode == RDP::fog_enabled)1590{1591for (i = 0; i < n; i++)1592{1593rdp.vtxbuf[i].f = 1.0f/max(4.0f, rdp.vtxbuf[i].f);1594}1595}1596else if (rdp.fog_mode == RDP::fog_blend)1597{1598float fog = 1.0f/max(1, rdp.fog_color&0xFF);1599for (i = 0; i < n; i++)1600{1601rdp.vtxbuf[i].f = fog;1602}1603}1604else if (rdp.fog_mode == RDP::fog_blend_inverse)1605{1606float fog = 1.0f/max(1, (~rdp.fog_color)&0xFF);1607for (i = 0; i < n; i++)1608{1609rdp.vtxbuf[i].f = fog;1610}1611}16121613if (settings.lodmode > 0 && rdp.cur_tile < rdp.mipmap_level)1614CalculateLOD(rdp.vtxbuf, n);16151616cmb.cmb_ext_use = cmb.tex_cmb_ext_use = 0;16171618/*1619if (rdp.tbuff_tex)1620{1621for (int k = 0; k < 3; k++)1622{1623FRDP("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);1624}1625}1626*/1627if (fullscreen)1628{1629if (settings.wireframe)1630{1631SetWireframeCol ();1632for (i=0; i<n; i++)1633{1634j = i+1;1635if (j == n) j = 0;1636grDrawLine (&rdp.vtxbuf[i], &rdp.vtxbuf[j]);1637}1638}1639else1640{16411642// VERTEX ** pv = rdp.vtx_buffer?(vtx_list2):(vtx_list1);1643// for (int k = 0; k < n; k ++)1644// 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]);1645// pv[k]->y = settings.res_y - pv[k]->y;16461647if (linew > 0)1648{1649VERTEX *V0 = &rdp.vtxbuf[0];1650VERTEX *V1 = &rdp.vtxbuf[1];1651if (fabs(V0->x - V1->x) < 0.01 && fabs(V0->y - V1->y) < 0.01)1652V1 = &rdp.vtxbuf[2];1653V0->z = ScaleZ(V0->z);1654V1->z = ScaleZ(V1->z);1655VERTEX v[4];1656v[0] = *V0;1657v[1] = *V0;1658v[2] = *V1;1659v[3] = *V1;1660float width = linew * 0.25f;1661if (fabs(V0->y - V1->y) < 0.0001)1662{1663v[0].x = v[1].x = V0->x;1664v[2].x = v[3].x = V1->x;16651666width *= rdp.scale_y;1667v[0].y = v[2].y = V0->y - width;1668v[1].y = v[3].y = V0->y + width;1669}1670else if (fabs(V0->x - V1->x) < 0.0001)1671{1672v[0].y = v[1].y = V0->y;1673v[2].y = v[3].y = V1->y;16741675width *= rdp.scale_x;1676v[0].x = v[2].x = V0->x - width;1677v[1].x = v[3].x = V0->x + width;1678}1679else1680{1681float dx = V1->x - V0->x;1682float dy = V1->y - V0->y;1683float len = sqrtf(dx*dx + dy*dy);1684float wx = dy * width * rdp.scale_x / len;1685float wy = dx * width * rdp.scale_y / len;1686v[0].x = V0->x + wx;1687v[0].y = V0->y - wy;1688v[1].x = V0->x - wx;1689v[1].y = V0->y + wy;1690v[2].x = V1->x + wx;1691v[2].y = V1->y - wy;1692v[3].x = V1->x - wx;1693v[3].y = V1->y + wy;1694}1695grDrawTriangle(&v[0], &v[1], &v[2]);1696grDrawTriangle(&v[1], &v[2], &v[3]);1697}1698else1699{1700DepthBuffer(rdp.vtxbuf, n);1701if ((rdp.rm & 0xC10) == 0xC10)1702grDepthBiasLevel (-deltaZ);1703grDrawVertexArray (GR_TRIANGLE_FAN, n, rdp.vtx_buffer?(&vtx_list2):(&vtx_list1));1704}1705}1706}17071708if (_debugger.capture) add_tri (rdp.vtxbuf, n, TRI_TRIANGLE);1709}17101711void add_tri (VERTEX *v, int n, int type)1712{1713//FRDP ("ENTER (%f, %f, %f), (%f, %f, %f), (%f, %f, %f)\n", v[0].x, v[0].y, v[0].w,1714// v[1].x, v[1].y, v[1].w, v[2].x, v[2].y, v[2].w);17151716// Debug capture1717if (_debugger.capture)1718{1719rdp.debug_n ++;17201721TRI_INFO *info = new TRI_INFO;1722info->nv = n;1723info->v = new VERTEX [n];1724memcpy (info->v, v, sizeof(VERTEX)*n);1725info->cycle_mode = rdp.cycle_mode;1726info->cycle1 = rdp.cycle1;1727info->cycle2 = rdp.cycle2;1728info->uncombined = rdp.uncombined;1729info->geom_mode = rdp.geom_mode;1730info->othermode_h = rdp.othermode_h;1731info->othermode_l = rdp.othermode_l;1732info->tri_n = rdp.tri_n;1733info->type = type;17341735for (int i=0; i<2; i++)1736{1737int j = rdp.cur_tile+i;1738if (i == 0)1739info->t[i].tmu = rdp.t0;1740else1741info->t[i].tmu = rdp.t1;1742info->t[i].cur_cache[0] = rdp.cur_cache_n[rdp.t0];1743info->t[i].cur_cache[1] = rdp.cur_cache_n[rdp.t1];1744info->t[i].format = rdp.tiles[j].format;1745info->t[i].size = rdp.tiles[j].size;1746info->t[i].width = rdp.tiles[j].width;1747info->t[i].height = rdp.tiles[j].height;1748info->t[i].line = rdp.tiles[j].line;1749info->t[i].palette = rdp.tiles[j].palette;1750info->t[i].clamp_s = rdp.tiles[j].clamp_s;1751info->t[i].clamp_t = rdp.tiles[j].clamp_t;1752info->t[i].mirror_s = rdp.tiles[j].mirror_s;1753info->t[i].mirror_t = rdp.tiles[j].mirror_t;1754info->t[i].shift_s = rdp.tiles[j].shift_s;1755info->t[i].shift_t = rdp.tiles[j].shift_t;1756info->t[i].mask_s = rdp.tiles[j].mask_s;1757info->t[i].mask_t = rdp.tiles[j].mask_t;1758info->t[i].ul_s = rdp.tiles[j].ul_s;1759info->t[i].ul_t = rdp.tiles[j].ul_t;1760info->t[i].lr_s = rdp.tiles[j].lr_s;1761info->t[i].lr_t = rdp.tiles[j].lr_t;1762info->t[i].t_ul_s = rdp.tiles[7].t_ul_s;1763info->t[i].t_ul_t = rdp.tiles[7].t_ul_t;1764info->t[i].t_lr_s = rdp.tiles[7].t_lr_s;1765info->t[i].t_lr_t = rdp.tiles[7].t_lr_t;1766info->t[i].scale_s = rdp.tiles[j].s_scale;1767info->t[i].scale_t = rdp.tiles[j].t_scale;1768}17691770info->fog_color = rdp.fog_color;1771info->fill_color = rdp.fill_color;1772info->prim_color = rdp.prim_color;1773info->blend_color = rdp.blend_color;1774info->env_color = rdp.env_color;1775info->prim_lodmin = rdp.prim_lodmin;1776info->prim_lodfrac = rdp.prim_lodfrac;17771778info->pNext = _debugger.tri_list;1779_debugger.tri_list = info;17801781if (_debugger.tri_last == NULL)1782_debugger.tri_last = _debugger.tri_list;1783}1784}17851786void update_scissor ()1787{1788if (rdp.update & UPDATE_SCISSOR)1789{1790rdp.update ^= UPDATE_SCISSOR;17911792// KILL the floating point error with 0.01f1793rdp.scissor.ul_x = (wxUint32)max(min((rdp.scissor_o.ul_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0);1794rdp.scissor.lr_x = (wxUint32)max(min((rdp.scissor_o.lr_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0);1795rdp.scissor.ul_y = (wxUint32)max(min((rdp.scissor_o.ul_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0);1796rdp.scissor.lr_y = (wxUint32)max(min((rdp.scissor_o.lr_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0);1797//grClipWindow specifies the hardware clipping window. Any pixels outside the clipping window are rejected.1798//Values are inclusive for minimum x and y values and exclusive for maximum x and y values.1799// 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);1800if (fullscreen)1801grClipWindow (rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);1802FRDP (" |- scissor - (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y,1803rdp.scissor.lr_x, rdp.scissor.lr_y);1804}1805}18061807//1808// update - update states if they need it1809//18101811typedef struct1812{1813unsigned int c2_m2b:2;1814unsigned int c1_m2b:2;1815unsigned int c2_m2a:2;1816unsigned int c1_m2a:2;1817unsigned int c2_m1b:2;1818unsigned int c1_m1b:2;1819unsigned int c2_m1a:2;1820unsigned int c1_m1a:2;1821} rdp_blender_setting;18221823void update ()1824{1825LRDP ("-+ update called\n");1826// Check for rendermode changes1827// Z buffer1828if (rdp.render_mode_changed & 0x00000C30)1829{1830FRDP (" |- render_mode_changed zbuf - decal: %s, update: %s, compare: %s\n",1831str_yn[(rdp.othermode_l & 0x00000400)?1:0],1832str_yn[(rdp.othermode_l&0x00000020)?1:0],1833str_yn[(rdp.othermode_l&0x00000010)?1:0]);18341835rdp.render_mode_changed &= ~0x00000C30;1836rdp.update |= UPDATE_ZBUF_ENABLED;18371838// Update?1839if ((rdp.othermode_l & 0x00000020))1840rdp.flags |= ZBUF_UPDATE;1841else1842rdp.flags &= ~ZBUF_UPDATE;18431844// Compare?1845if (rdp.othermode_l & 0x00000010)1846rdp.flags |= ZBUF_COMPARE;1847else1848rdp.flags &= ~ZBUF_COMPARE;1849}18501851// Alpha compare1852if (rdp.render_mode_changed & 0x00001000)1853{1854FRDP (" |- render_mode_changed alpha compare - on: %s\n",1855str_yn[(rdp.othermode_l&0x00001000)?1:0]);1856rdp.render_mode_changed &= ~0x00001000;1857rdp.update |= UPDATE_ALPHA_COMPARE;18581859if (rdp.othermode_l & 0x00001000)1860rdp.flags |= ALPHA_COMPARE;1861else1862rdp.flags &= ~ALPHA_COMPARE;1863}18641865if (rdp.render_mode_changed & 0x00002000) // alpha cvg sel1866{1867FRDP (" |- render_mode_changed alpha cvg sel - on: %s\n",1868str_yn[(rdp.othermode_l&0x00002000)?1:0]);1869rdp.render_mode_changed &= ~0x00002000;1870rdp.update |= UPDATE_COMBINE;1871rdp.update |= UPDATE_ALPHA_COMPARE;1872}18731874// Force blend1875if (rdp.render_mode_changed & 0xFFFF0000)1876{1877FRDP (" |- render_mode_changed force_blend - %08lx\n", rdp.othermode_l&0xFFFF0000);1878rdp.render_mode_changed &= 0x0000FFFF;18791880rdp.fbl_a0 = (wxUint8)((rdp.othermode_l>>30)&0x3);1881rdp.fbl_b0 = (wxUint8)((rdp.othermode_l>>26)&0x3);1882rdp.fbl_c0 = (wxUint8)((rdp.othermode_l>>22)&0x3);1883rdp.fbl_d0 = (wxUint8)((rdp.othermode_l>>18)&0x3);1884rdp.fbl_a1 = (wxUint8)((rdp.othermode_l>>28)&0x3);1885rdp.fbl_b1 = (wxUint8)((rdp.othermode_l>>24)&0x3);1886rdp.fbl_c1 = (wxUint8)((rdp.othermode_l>>20)&0x3);1887rdp.fbl_d1 = (wxUint8)((rdp.othermode_l>>16)&0x3);18881889rdp.update |= UPDATE_COMBINE;1890}18911892// Combine MUST go before texture1893if ((rdp.update & UPDATE_COMBINE) && rdp.allow_combine)1894{1895TBUFF_COLOR_IMAGE * aTBuff[2] = {0, 0};1896if (rdp.aTBuffTex[0])1897aTBuff[rdp.aTBuffTex[0]->tile] = rdp.aTBuffTex[0];1898if (rdp.aTBuffTex[1])1899aTBuff[rdp.aTBuffTex[1]->tile] = rdp.aTBuffTex[1];1900rdp.aTBuffTex[0] = aTBuff[0];1901rdp.aTBuffTex[1] = aTBuff[1];19021903LRDP (" |-+ update_combine\n");1904Combine ();1905}19061907if (rdp.update & UPDATE_TEXTURE) // note: UPDATE_TEXTURE and UPDATE_COMBINE are the same1908{1909rdp.tex_ctr ++;1910if (rdp.tex_ctr == 0xFFFFFFFF)1911rdp.tex_ctr = 0;19121913TexCache ();1914if (rdp.noise == RDP::noise_none)1915rdp.update ^= UPDATE_TEXTURE;1916}19171918if (fullscreen)1919{1920// Z buffer1921if (rdp.update & UPDATE_ZBUF_ENABLED)1922{1923// already logged above1924rdp.update ^= UPDATE_ZBUF_ENABLED;19251926if (((rdp.flags & ZBUF_ENABLED) || rdp.zsrc == 1) && rdp.cycle_mode < 2)1927{1928if (rdp.flags & ZBUF_COMPARE)1929{1930switch ((rdp.rm & 0xC00)>>10) {1931case 0:1932grDepthBiasLevel(0);1933grDepthBufferFunction (settings.zmode_compare_less ? GR_CMP_LESS : GR_CMP_LEQUAL);1934break;1935case 1:1936grDepthBiasLevel(-4);1937grDepthBufferFunction (settings.zmode_compare_less ? GR_CMP_LESS : GR_CMP_LEQUAL);1938break;1939case 2:1940grDepthBiasLevel(settings.ucode == 7 ? -4 : 0);1941grDepthBufferFunction (GR_CMP_LESS);1942break;1943case 3:1944// will be set dynamically per polygon1945//grDepthBiasLevel(-deltaZ);1946grDepthBufferFunction (GR_CMP_LEQUAL);1947break;1948}1949}1950else1951{1952grDepthBiasLevel(0);1953grDepthBufferFunction (GR_CMP_ALWAYS);1954}19551956if (rdp.flags & ZBUF_UPDATE)1957grDepthMask (FXTRUE);1958else1959grDepthMask (FXFALSE);1960}1961else1962{1963grDepthBiasLevel(0);1964grDepthBufferFunction (GR_CMP_ALWAYS);1965grDepthMask (FXFALSE);1966}1967}19681969// Alpha compare1970if (rdp.update & UPDATE_ALPHA_COMPARE)1971{1972// already logged above1973rdp.update ^= UPDATE_ALPHA_COMPARE;19741975// if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && !force_full_alpha)1976// if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && (rdp.blend_color&0xFF))1977if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && (!(rdp.othermode_l & 0x00004000) || (rdp.blend_color&0xFF)))1978{1979wxUint8 reference = (wxUint8)(rdp.blend_color&0xFF);1980grAlphaTestFunction (reference ? GR_CMP_GEQUAL : GR_CMP_GREATER);1981grAlphaTestReferenceValue (reference);1982FRDP (" |- alpha compare: blend: %02lx\n", reference);1983}1984else1985{1986if (rdp.flags & ALPHA_COMPARE)1987{1988if ((rdp.othermode_l & 0x5000) != 0x5000)1989{1990grAlphaTestFunction (GR_CMP_GEQUAL);1991grAlphaTestReferenceValue (0x20);//0xA0);1992LRDP (" |- alpha compare: 0x20\n");1993}1994else1995{1996grAlphaTestFunction (GR_CMP_GREATER);1997if (rdp.acmp == 3)1998{1999grAlphaTestReferenceValue ((wxUint8)(rdp.blend_color&0xFF));2000FRDP (" |- alpha compare: blend: %02lx\n", rdp.blend_color&0xFF);2001}2002else2003{2004grAlphaTestReferenceValue (0x00);2005LRDP (" |- alpha compare: 0x00\n");2006}2007}2008}2009else2010{2011grAlphaTestFunction (GR_CMP_ALWAYS);2012LRDP (" |- alpha compare: none\n");2013}2014}2015if (rdp.acmp == 3 && rdp.cycle_mode < 2)2016{2017if (grStippleModeExt != 0)2018{2019if (settings.old_style_adither || rdp.alpha_dither_mode != 3) {2020LRDP (" |- alpha compare: dither\n");2021grStippleModeExt(settings.stipple_mode);2022}2023else2024grStippleModeExt(GR_STIPPLE_DISABLE);2025}2026}2027else2028{2029if (grStippleModeExt)2030{2031//LRDP (" |- alpha compare: dither disabled\n");2032grStippleModeExt(GR_STIPPLE_DISABLE);2033}2034}2035}2036// Cull mode (leave this in for z-clipped triangles)2037if (rdp.update & UPDATE_CULL_MODE)2038{2039rdp.update ^= UPDATE_CULL_MODE;2040wxUint32 mode = (rdp.flags & CULLMASK) >> CULLSHIFT;2041FRDP (" |- cull_mode - mode: %s\n", str_cull[mode]);2042switch (mode)2043{2044case 0: // cull none2045case 3: // cull both2046grCullMode(GR_CULL_DISABLE);2047break;2048case 1: // cull front2049// grCullMode(GR_CULL_POSITIVE);2050grCullMode(GR_CULL_NEGATIVE);2051break;2052case 2: // cull back2053// grCullMode (GR_CULL_NEGATIVE);2054grCullMode (GR_CULL_POSITIVE);2055break;2056}2057}20582059//Added by Gonetz.2060if (settings.fog && (rdp.update & UPDATE_FOG_ENABLED))2061{2062rdp.update ^= UPDATE_FOG_ENABLED;20632064wxUint16 blender = (wxUint16)(rdp.othermode_l >> 16);2065if (rdp.flags & FOG_ENABLED)2066{2067rdp_blender_setting &bl = *(rdp_blender_setting*)(&(blender));2068if((rdp.fog_multiplier > 0) && (bl.c1_m1a==3 || bl.c1_m2a == 3 || bl.c2_m1a == 3 || bl.c2_m2a == 3))2069{2070grFogColorValue(rdp.fog_color);2071grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);2072rdp.fog_mode = RDP::fog_enabled;2073LRDP("fog enabled \n");2074}2075else2076{2077LRDP("fog disabled in blender\n");2078rdp.fog_mode = RDP::fog_disabled;2079grFogMode (GR_FOG_DISABLE);2080}2081}2082else if (blender == 0xc410 || blender == 0xc411 || blender == 0xf500)2083{2084grFogColorValue(rdp.fog_color);2085grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);2086rdp.fog_mode = RDP::fog_blend;2087LRDP("fog blend \n");2088}2089else if (blender == 0x04d1)2090{2091grFogColorValue(rdp.fog_color);2092grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);2093rdp.fog_mode = RDP::fog_blend_inverse;2094LRDP("fog blend \n");2095}2096else2097{2098LRDP("fog disabled\n");2099rdp.fog_mode = RDP::fog_disabled;2100grFogMode (GR_FOG_DISABLE);2101}2102}2103}21042105if (rdp.update & UPDATE_VIEWPORT)2106{2107rdp.update ^= UPDATE_VIEWPORT;2108if (fullscreen)2109{2110float scale_x = (float)fabs(rdp.view_scale[0]);2111float scale_y = (float)fabs(rdp.view_scale[1]);21122113rdp.clip_min_x = max((rdp.view_trans[0] - scale_x + rdp.offset_x) / rdp.clip_ratio, 0.0f);2114rdp.clip_min_y = max((rdp.view_trans[1] - scale_y + rdp.offset_y) / rdp.clip_ratio, 0.0f);2115rdp.clip_max_x = min((rdp.view_trans[0] + scale_x + rdp.offset_x) * rdp.clip_ratio, settings.res_x);2116rdp.clip_max_y = min((rdp.view_trans[1] + scale_y + rdp.offset_y) * rdp.clip_ratio, settings.res_y);21172118FRDP (" |- 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);2119if (!rdp.scissor_set)2120{2121rdp.scissor.ul_x = (wxUint32)rdp.clip_min_x;2122rdp.scissor.lr_x = (wxUint32)rdp.clip_max_x;2123rdp.scissor.ul_y = (wxUint32)rdp.clip_min_y;2124rdp.scissor.lr_y = (wxUint32)rdp.clip_max_y;2125grClipWindow (rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);2126}2127}2128}21292130if (rdp.update & UPDATE_SCISSOR)2131update_scissor ();21322133LRDP (" + update end\n");2134}21352136void set_message_combiner ()2137{2138grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,2139GR_COMBINE_FACTOR_ONE,2140GR_COMBINE_LOCAL_NONE,2141GR_COMBINE_OTHER_TEXTURE,2142FXFALSE);2143grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,2144GR_COMBINE_FACTOR_ONE,2145GR_COMBINE_LOCAL_NONE,2146GR_COMBINE_OTHER_TEXTURE,2147FXFALSE);2148if (settings.buff_clear && (settings.show_fps & 0x08))2149grAlphaBlendFunction (GR_BLEND_SRC_ALPHA,2150GR_BLEND_ONE_MINUS_SRC_ALPHA,2151GR_BLEND_ZERO,2152GR_BLEND_ZERO);2153else2154grAlphaBlendFunction (GR_BLEND_ONE,2155GR_BLEND_ZERO,2156GR_BLEND_ZERO,2157GR_BLEND_ZERO);2158grAlphaTestFunction (GR_CMP_ALWAYS);2159if (grStippleModeExt)2160{2161grStippleModeExt(GR_STIPPLE_DISABLE);2162}2163grTexFilterMode (0, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR);2164grTexCombine (GR_TMU1,2165GR_COMBINE_FUNCTION_NONE,2166GR_COMBINE_FACTOR_NONE,2167GR_COMBINE_FUNCTION_NONE,2168GR_COMBINE_FACTOR_NONE,2169FXFALSE, FXFALSE);2170grTexCombine (GR_TMU0,2171GR_COMBINE_FUNCTION_LOCAL,2172GR_COMBINE_FACTOR_NONE,2173GR_COMBINE_FUNCTION_LOCAL,2174GR_COMBINE_FACTOR_NONE,2175FXFALSE, FXFALSE);2176grTexSource(GR_TMU0,2177voodoo.tex_min_addr[GR_TMU0] + offset_font,2178GR_MIPMAPLEVELMASK_BOTH,2179&fontTex);2180grFogMode (GR_FOG_DISABLE);2181}2182218321842185