Path: blob/master/libmupen64plus/mupen64plus-video-glide64/src/Util.cpp
2 views
/*1* Glide64 - Glide video plugin for Nintendo 64 emulators.2* Copyright (c) 2002 Dave20013*4* This program is free software; you can redistribute it and/or modify5* it under the terms of the GNU General Public License as published by6* the Free Software Foundation; either version 2 of the License, or7* any later version.8*9* This program is distributed in the hope that it will be useful,10* but WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12* GNU General Public License for more details.13*14* You should have received a copy of the GNU General Public15* License along with this program; if not, write to the Free16* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,17* Boston, MA 02110-1301, USA18*/1920//****************************************************************21//22// Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)23// Project started on December 29th, 200124//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.28//29// Official Glide64 development channel: #Glide64 on EFnet30//31// Original author: Dave2001 ([email protected])32// Other authors: Gonetz, Gugaman33//34//****************************************************************3536#define M64P_PLUGIN_PROTOTYPES 137#include "m64p_types.h"38#include "m64p_plugin.h"39#include "m64p_config.h"40#include "m64p_vidext.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#ifndef _WIN3249#include <string.h>50#include <stdlib.h>51#endif // _WIN325253#define max(a,b) ((a) > (b) ? (a) : (b))54#define min(a,b) ((a) < (b) ? (a) : (b))5556#define Vj rdp.vtxbuf2[j]57#define Vi rdp.vtxbuf2[i]5859VERTEX *vtx_list1[32]; // vertex indexing60VERTEX *vtx_list2[32];6162//63// util_init - initialize data for the functions in this file64//6566void util_init ()67{68for (int i=0; i<32; i++)69{70vtx_list1[i] = &rdp.vtx1[i];71vtx_list2[i] = &rdp.vtx2[i];72}73}7475//software backface culling. Gonetz76// mega modifications by Dave200177BOOL cull_tri(VERTEX **v) // type changed to VERTEX** [Dave2001]78{79int i;8081if (v[0]->scr_off & v[1]->scr_off & v[2]->scr_off)82{83RDP (" clipped\n");84return TRUE;85}8687// Triangle can't be culled, if it need clipping88BOOL draw = FALSE;8990//fix for sun in zeldas91BOOL fix_i_uv = FALSE;92if (settings.zelda && rdp.rm == 0x0c184241 && rdp.tiles[rdp.cur_tile].format == 4)93fix_i_uv = TRUE;9495for (i=0; i<3; i++)96{97if (!v[i]->screen_translated)98{99v[i]->sx = rdp.view_trans[0] + v[i]->x_w * rdp.view_scale[0];100v[i]->sy = rdp.view_trans[1] + v[i]->y_w * rdp.view_scale[1];101v[i]->sz = rdp.view_trans[2] + v[i]->z_w * rdp.view_scale[2];102if ((fix_i_uv) && (v[i]->uv_fixed == 0))103{104v[i]->uv_fixed = 1;105v[i]->ou *= 0.5f;106v[i]->ov *= 0.5f;107}108v[i]->screen_translated = 1;109}110if (v[i]->w < 0.01f) //need clip_z. can't be culled now111draw = 1;112}113114if (settings.fix_tex_coord)115fix_tex_coord (v);116if (draw) return FALSE; // z-clipping, can't be culled by software117118#define SW_CULLING119#ifdef SW_CULLING120//now we need to check, if triangle's vertices are in clockwise order121// Use precalculated x/z and y/z coordinates.122float x1 = v[0]->sx - v[1]->sx;123float y1 = v[0]->sy - v[1]->sy;124float x2 = v[2]->sx - v[1]->sx;125float y2 = v[2]->sy - v[1]->sy;126127DWORD mode = (rdp.flags & CULLMASK) >> CULLSHIFT;128switch (mode)129{130case 1: // cull front131// if ((x1*y2 - y1*x2) < 0.0f) //counter-clockwise, positive132if ((y1*x2-x1*y2) < 0.0f) //counter-clockwise, positive133{134RDP (" culled!\n");135return TRUE;136}137return FALSE;138case 2: // cull back139// if ((x1*y2 - y1*x2) >= 0.0f) //clockwise, negative140if ((y1*x2-x1*y2) >= 0.0f) //clockwise, negative141{142RDP (" culled!\n");143return TRUE;144}145return FALSE;146}147#endif148149return FALSE;150}151152153void apply_shade_mods (VERTEX *v)154{155float col[4];156DWORD cmb;157memcpy (col, rdp.col, 16);158159if (rdp.cmb_flags)160{161cmb = rdp.cmb_flags;162if (cmb & CMB_SET)163{164if (col[0] > 1.0f) col[0] = 1.0f;165if (col[1] > 1.0f) col[1] = 1.0f;166if (col[2] > 1.0f) col[2] = 1.0f;167if (col[0] < 0.0f) col[0] = 0.0f;168if (col[1] < 0.0f) col[1] = 0.0f;169if (col[2] < 0.0f) col[2] = 0.0f;170v->r = (BYTE)(255.0f * col[0]);171v->g = (BYTE)(255.0f * col[1]);172v->b = (BYTE)(255.0f * col[2]);173}174if (cmb & CMB_A_SET)175{176if (col[3] > 1.0f) col[3] = 1.0f;177if (col[3] < 0.0f) col[3] = 0.0f;178v->a = (BYTE)(255.0f * col[3]);179}180if (cmb & CMB_SETSHADE_SHADEALPHA)181{182v->r = v->g = v->b = v->a;183}184if (cmb & CMB_SUB)185{186int r = v->r - (int)(255.0f * rdp.coladd[0]);187int g = v->g - (int)(255.0f * rdp.coladd[1]);188int b = v->b - (int)(255.0f * rdp.coladd[2]);189if (r < 0) r = 0;190if (g < 0) g = 0;191if (b < 0) b = 0;192v->r = (BYTE)r;193v->g = (BYTE)g;194v->b = (BYTE)b;195}196if (cmb & CMB_A_SUB)197{198int a = v->a - (int)(255.0f * rdp.coladd[3]);199if (a < 0) a = 0;200v->a = (BYTE)a;201}202203if (cmb & CMB_ADD)204{205int r = v->r + (int)(255.0f * rdp.coladd[0]);206int g = v->g + (int)(255.0f * rdp.coladd[1]);207int b = v->b + (int)(255.0f * rdp.coladd[2]);208if (r > 255) r = 255;209if (g > 255) g = 255;210if (b > 255) b = 255;211v->r = (BYTE)r;212v->g = (BYTE)g;213v->b = (BYTE)b;214}215if (cmb & CMB_A_ADD)216{217int a = v->a + (int)(255.0f * rdp.coladd[3]);218if (a > 255) a = 255;219v->a = (BYTE)a;220}221if (cmb & CMB_COL_SUB_OWN)222{223int r = (BYTE)(255.0f * rdp.coladd[0]) - v->r;224int g = (BYTE)(255.0f * rdp.coladd[1]) - v->g;225int b = (BYTE)(255.0f * rdp.coladd[2]) - v->b;226if (r < 0) r = 0;227if (g < 0) g = 0;228if (b < 0) b = 0;229v->r = (BYTE)r;230v->g = (BYTE)g;231v->b = (BYTE)b;232}233if (cmb & CMB_MULT)234{235if (col[0] > 1.0f) col[0] = 1.0f;236if (col[1] > 1.0f) col[1] = 1.0f;237if (col[2] > 1.0f) col[2] = 1.0f;238if (col[0] < 0.0f) col[0] = 0.0f;239if (col[1] < 0.0f) col[1] = 0.0f;240if (col[2] < 0.0f) col[2] = 0.0f;241v->r = (BYTE)(v->r * col[0]);242v->g = (BYTE)(v->g * col[1]);243v->b = (BYTE)(v->b * col[2]);244}245if (cmb & CMB_A_MULT)246{247if (col[3] > 1.0f) col[3] = 1.0f;248if (col[3] < 0.0f) col[3] = 0.0f;249v->a = (BYTE)(v->a * col[3]);250}251if (cmb & CMB_MULT_OWN_ALPHA)252{253float percent = v->a / 255.0f;254v->r = (BYTE)(v->r * percent);255v->g = (BYTE)(v->g * percent);256v->b = (BYTE)(v->b * percent);257}258v->shade_mods_allowed = 0;259}260cmb = rdp.cmb_flags_2;261if (cmb & CMB_INTER)262{263v->r = (BYTE)(rdp.col_2[0] * rdp.shade_factor * 255.0f + v->r * (1.0f - rdp.shade_factor));264v->g = (BYTE)(rdp.col_2[1] * rdp.shade_factor * 255.0f + v->g * (1.0f - rdp.shade_factor));265v->b = (BYTE)(rdp.col_2[2] * rdp.shade_factor * 255.0f + v->b * (1.0f - rdp.shade_factor));266v->shade_mods_allowed = 0;267}268}269270271static long dzdx = 0;272273void DrawTri (VERTEX **vtx, WORD linew)274{275if (settings.fb_depth_render && linew == 0)276{277float X0 = vtx[0]->sx / rdp.scale_x;278float Y0 = vtx[0]->sy / rdp.scale_y;279float X1 = vtx[1]->sx / rdp.scale_x;280float Y1 = vtx[1]->sy / rdp.scale_y;281float X2 = vtx[2]->sx / rdp.scale_x;282float Y2 = vtx[2]->sy / rdp.scale_y;283float diff12 = Y1 - Y2;284float diff02 = Y0 - Y2;285286287double denom = ((X0 - X2) * diff12 -288(X1 - X2) * diff02);289if(denom*denom > 0.0)290{291dzdx = (long)(((vtx[0]->sz - vtx[2]->sz) * diff12 -292(vtx[1]->sz - vtx[2]->sz) * diff02) / denom * 65536.0);293}294else295dzdx = 0;296}297else298dzdx = 0;299300for (int i=0; i<3; i++)301{302VERTEX *v = vtx[i];303304if (v->uv_calculated != rdp.tex_ctr)305{306#ifdef EXTREME_LOGGING307FRDP(" * CALCULATING VERTEX U/V: %d\n", v->number);308#endif309v->uv_calculated = rdp.tex_ctr;310311if (!(rdp.geom_mode & 0x00020000))312{313if (!(rdp.geom_mode & 0x00000200))314{315if (rdp.geom_mode & 0x00000004) // flat shading316{317#ifdef EXTREME_LOGGING318RDP(" * Flat shaded\n");319#endif320v->a = vtx[0]->a;321v->b = vtx[0]->b;322v->g = vtx[0]->g;323v->r = vtx[0]->r;324}325else // prim color326{327#ifdef EXTREME_LOGGING328FRDP(" * Prim shaded %08lx\n", rdp.prim_color);329#endif330v->a = (BYTE)(rdp.prim_color & 0xFF);331v->b = (BYTE)((rdp.prim_color >> 8) & 0xFF);332v->g = (BYTE)((rdp.prim_color >> 16) & 0xFF);333v->r = (BYTE)((rdp.prim_color >> 24) & 0xFF);334}335}336}337338// Fix texture coordinates339v->u1 = v->u0 = v->ou;340v->v1 = v->v0 = v->ov;341342if (rdp.tex >= 1 && rdp.cur_cache[0])343{344if (rdp.hires_tex && rdp.hires_tex->tile == 0)345{346v->u0 += rdp.hires_tex->u_shift + rdp.hires_tex->tile_uls;347v->v0 += rdp.hires_tex->v_shift + rdp.hires_tex->tile_ult;348}349350if (rdp.tiles[rdp.cur_tile].shift_s)351{352if (rdp.tiles[rdp.cur_tile].shift_s > 10)353v->u0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s));354else355v->u0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_s);356}357if (rdp.tiles[rdp.cur_tile].shift_t)358{359if (rdp.tiles[rdp.cur_tile].shift_t > 10)360v->v0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t));361else362v->v0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_t);363}364365if (rdp.hires_tex && rdp.hires_tex->tile == 0)366{367if (rdp.hires_tex->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s)368v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;369v->u0 *= rdp.hires_tex->u_scale;370v->v0 *= rdp.hires_tex->u_scale;371v->u0 -= 0.45f;372v->v0 -= 0.45f;373FRDP("hires_tex t0: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u0, v->v0);374}375else376{377v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;378v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t;379v->u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * v->u0;380v->v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * v->v0;381}382v->u0_w = v->u0 / v->w;383v->v0_w = v->v0 / v->w;384}385386if (rdp.tex >= 2 && rdp.cur_cache[1])387{388if (rdp.hires_tex && rdp.hires_tex->tile == 1)389{390v->u1 += rdp.hires_tex->u_shift + rdp.hires_tex->tile_uls;391v->v1 += rdp.hires_tex->v_shift + rdp.hires_tex->tile_ult;392}393if (rdp.tiles[rdp.cur_tile+1].shift_s)394{395if (rdp.tiles[rdp.cur_tile+1].shift_s > 10)396v->u1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s));397else398v->u1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_s);399}400if (rdp.tiles[rdp.cur_tile+1].shift_t)401{402if (rdp.tiles[rdp.cur_tile+1].shift_t > 10)403v->v1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t));404else405v->v1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_t);406}407408if (rdp.hires_tex && rdp.hires_tex->tile == 1)409{410if (rdp.hires_tex->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s)411v->u1 -= rdp.tiles[rdp.cur_tile].f_ul_s;412v->u1 *= rdp.hires_tex->u_scale;413v->v1 *= rdp.hires_tex->u_scale;414v->u1 -= 0.45f;415v->v1 -= 0.45f;416FRDP("hires_tex t1: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u0, v->v0);417}418else419{420v->u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s;421v->v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t;422v->u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * v->u1;423v->v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * v->v1;424}425426v->u1_w = v->u1 / v->w;427v->v1_w = v->v1 / v->w;428}429// 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);430}431if (v->shade_mods_allowed)432apply_shade_mods (v);433} //for434435rdp.clip = 0;436437if ((vtx[0]->scr_off & 16) ||438(vtx[1]->scr_off & 16) ||439(vtx[2]->scr_off & 16))440rdp.clip |= CLIP_ZMIN;441442vtx[0]->not_zclipped = vtx[1]->not_zclipped = vtx[2]->not_zclipped = 1;443444if (rdp.cur_cache[0] && (rdp.tex & 1) && (rdp.cur_cache[0]->splits > 1) && !rdp.hires_tex && !rdp.clip)445{446int index,i,j, min_256,max_256, cur_256,left_256,right_256;447float percent;448449min_256 = min((int)vtx[0]->u0,(int)vtx[1]->u0); // bah, don't put two mins on one line450min_256 = min(min_256,(int)vtx[2]->u0) >> 8; // or it will be calculated twice451452max_256 = max((int)vtx[0]->u0,(int)vtx[1]->u0); // not like it makes much difference453max_256 = max(max_256,(int)vtx[2]->u0) >> 8; // anyway :P454455for (cur_256=min_256; cur_256<=max_256; cur_256++)456{457left_256 = cur_256 << 8;458right_256 = (cur_256+1) << 8;459460// Set vertex buffers461rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1462rdp.vtxbuf2 = rdp.vtx2;463rdp.vtx_buffer = 0;464rdp.n_global = 3;465index = 0;466467// ** Left plane **468for (i=0; i<3; i++)469{470j = i+1;471if (j == 3) j = 0;472473VERTEX *v1 = vtx[i];474VERTEX *v2 = vtx[j];475476if (v1->u0 >= left_256)477{478if (v2->u0 >= left_256) // Both are in, save the last one479{480rdp.vtxbuf[index] = *v2;481rdp.vtxbuf[index].u0 -= left_256;482rdp.vtxbuf[index++].v0 += rdp.cur_cache[0]->c_scl_y * (cur_256 * rdp.cur_cache[0]->splitheight);483}484else // First is in, second is out, save intersection485{486percent = (left_256 - v1->u0) / (v2->u0 - v1->u0);487rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent;488rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent;489rdp.vtxbuf[index].z = v1->z + (v2->z - v1->z) * percent;490rdp.vtxbuf[index].w = v1->w + (v2->w - v1->w) * percent;491rdp.vtxbuf[index].f = v1->f + (v2->f - v1->f) * percent;492rdp.vtxbuf[index].u0 = 0.5f;493rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent +494rdp.cur_cache[0]->c_scl_y * cur_256 * rdp.cur_cache[0]->splitheight;495rdp.vtxbuf[index].u1 = v1->u1 + (v2->u1 - v1->u1) * percent;496rdp.vtxbuf[index].v1 = v1->v1 + (v2->v1 - v1->v1) * percent;497rdp.vtxbuf[index].b = (BYTE)(v1->b + (v2->b - v1->b) * percent);498rdp.vtxbuf[index].g = (BYTE)(v1->g + (v2->g - v1->g) * percent);499rdp.vtxbuf[index].r = (BYTE)(v1->r + (v2->r - v1->r) * percent);500rdp.vtxbuf[index++].a = (BYTE)(v1->a + (v2->a - v1->a) * percent);501}502}503else504{505//if (v2->u0 < left_256) // Both are out, save nothing506if (v2->u0 >= left_256) // First is out, second is in, save intersection & in point507{508percent = (left_256 - v2->u0) / (v1->u0 - v2->u0);509rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent;510rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent;511rdp.vtxbuf[index].z = v2->z + (v1->z - v2->z) * percent;512rdp.vtxbuf[index].w = v2->w + (v1->w - v2->w) * percent;513rdp.vtxbuf[index].f = v2->f + (v1->f - v2->f) * percent;514rdp.vtxbuf[index].u0 = 0.5f;515rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent +516rdp.cur_cache[0]->c_scl_y * cur_256 * rdp.cur_cache[0]->splitheight;517rdp.vtxbuf[index].u1 = v2->u1 + (v1->u1 - v2->u1) * percent;518rdp.vtxbuf[index].v1 = v2->v1 + (v1->v1 - v2->v1) * percent;519rdp.vtxbuf[index].b = (BYTE)(v2->b + (v1->b - v2->b) * percent);520rdp.vtxbuf[index].g = (BYTE)(v2->g + (v1->g - v2->g) * percent);521rdp.vtxbuf[index].r = (BYTE)(v2->r + (v1->r - v2->r) * percent);522rdp.vtxbuf[index++].a = (BYTE)(v2->a + (v1->a - v2->a) * percent);523524// Save the in point525rdp.vtxbuf[index] = *v2;526rdp.vtxbuf[index].u0 -= left_256;527rdp.vtxbuf[index++].v0 += rdp.cur_cache[0]->c_scl_y * (cur_256 * rdp.cur_cache[0]->splitheight);528}529}530}531rdp.n_global = index;532533rdp.vtxbuf = rdp.vtx2; // now vtx1 holds the value, & vtx2 is the destination534rdp.vtxbuf2 = rdp.vtx1;535rdp.vtx_buffer ^= 1;536index = 0;537538for (i=0; i<rdp.n_global; i++)539{540j = i+1;541if (j == rdp.n_global) j = 0;542543VERTEX *v1 = &rdp.vtxbuf2[i];544VERTEX *v2 = &rdp.vtxbuf2[j];545546// ** Right plane **547if (v1->u0 <= 256.0f)548{549if (v2->u0 <= 256.0f) // Both are in, save the last one550{551rdp.vtxbuf[index] = *v2;552rdp.vtxbuf[index++].not_zclipped = 0;553}554else // First is in, second is out, save intersection555{556percent = (right_256 - v1->u0) / (v2->u0 - v1->u0);557rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent;558rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent;559rdp.vtxbuf[index].z = v1->z + (v2->z - v1->z) * percent;560rdp.vtxbuf[index].w = v1->w + (v2->w - v1->w) * percent;561rdp.vtxbuf[index].f = v1->f + (v2->f - v1->f) * percent;562rdp.vtxbuf[index].u0 = 255.5f;563rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent;564rdp.vtxbuf[index].u1 = v1->u1 + (v2->u1 - v1->u1) * percent;565rdp.vtxbuf[index].v1 = v1->v1 + (v2->v1 - v1->v1) * percent;566rdp.vtxbuf[index].b = (BYTE)(v1->b + (v2->b - v1->b) * percent);567rdp.vtxbuf[index].g = (BYTE)(v1->g + (v2->g - v1->g) * percent);568rdp.vtxbuf[index].r = (BYTE)(v1->r + (v2->r - v1->r) * percent);569rdp.vtxbuf[index].a = (BYTE)(v1->a + (v2->a - v1->a) * percent);570rdp.vtxbuf[index++].not_zclipped = 0;571}572}573else574{575//if (v2->u0 > 256.0f) // Both are out, save nothing576if (v2->u0 <= 256.0f) // First is out, second is in, save intersection & in point577{578percent = (right_256 - v2->u0) / (v1->u0 - v2->u0);579rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent;580rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent;581rdp.vtxbuf[index].z = v2->z + (v1->z - v2->z) * percent;582rdp.vtxbuf[index].w = v2->w + (v1->w - v2->w) * percent;583rdp.vtxbuf[index].f = v2->f + (v1->f - v2->f) * percent;584rdp.vtxbuf[index].u0 = 255.5f;585rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent;586rdp.vtxbuf[index].u1 = v2->u1 + (v1->u1 - v2->u1) * percent;587rdp.vtxbuf[index].v1 = v2->v1 + (v1->v1 - v2->v1) * percent;588rdp.vtxbuf[index].b = (BYTE)(v2->b + (v1->b - v2->b) * percent);589rdp.vtxbuf[index].g = (BYTE)(v2->g + (v1->g - v2->g) * percent);590rdp.vtxbuf[index].r = (BYTE)(v2->r + (v1->r - v2->r) * percent);591rdp.vtxbuf[index].a = (BYTE)(v2->a + (v1->a - v2->a) * percent);592rdp.vtxbuf[index++].not_zclipped = 0;593594// Save the in point595rdp.vtxbuf[index] = *v2;596rdp.vtxbuf[index++].not_zclipped = 0;597}598}599}600rdp.n_global = index;601602do_triangle_stuff (linew);603}604}605else606{607// Set vertex buffers608rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1609rdp.vtxbuf2 = rdp.vtx2;610rdp.vtx_buffer = 0;611rdp.n_global = 3;612613rdp.vtxbuf[0] = *vtx[0];614rdp.vtxbuf[1] = *vtx[1];615rdp.vtxbuf[2] = *vtx[2];616617do_triangle_stuff (linew);618}619}620621void do_triangle_stuff (WORD linew) // what else?? do the triangle stuff :P (to keep from writing code twice)622{623int i;624625// if (rdp.zsrc != 1)626clip_z ();627628for (i=0; i<rdp.n_global; i++)629{630if (rdp.vtxbuf[i].not_zclipped)// && rdp.zsrc != 1)631{632#ifdef EXTREME_LOGGING633FRDP (" * NOT ZCLIPPPED: %d\n", rdp.vtxbuf[i].number);634#endif635rdp.vtxbuf[i].x = rdp.vtxbuf[i].sx;636rdp.vtxbuf[i].y = rdp.vtxbuf[i].sy;637rdp.vtxbuf[i].z = rdp.vtxbuf[i].sz;638rdp.vtxbuf[i].q = rdp.vtxbuf[i].oow;639rdp.vtxbuf[i].u0 = rdp.vtxbuf[i].u0_w;640rdp.vtxbuf[i].v0 = rdp.vtxbuf[i].v0_w;641rdp.vtxbuf[i].u1 = rdp.vtxbuf[i].u1_w;642rdp.vtxbuf[i].v1 = rdp.vtxbuf[i].v1_w;643}644else645{646#ifdef EXTREME_LOGGING647FRDP (" * ZCLIPPED: %d\n", rdp.vtxbuf[i].number);648#endif649rdp.vtxbuf[i].q = 1.0f / rdp.vtxbuf[i].w;650rdp.vtxbuf[i].x = rdp.view_trans[0] + rdp.vtxbuf[i].x * rdp.vtxbuf[i].q * rdp.view_scale[0];651rdp.vtxbuf[i].y = rdp.view_trans[1] + rdp.vtxbuf[i].y * rdp.vtxbuf[i].q * rdp.view_scale[1];652rdp.vtxbuf[i].z = rdp.view_trans[2] + rdp.vtxbuf[i].z * rdp.vtxbuf[i].q * rdp.view_scale[2];653if (rdp.tex >= 1)654{655rdp.vtxbuf[i].u0 *= rdp.vtxbuf[i].q;656rdp.vtxbuf[i].v0 *= rdp.vtxbuf[i].q;657}658if (rdp.tex >= 2)659{660rdp.vtxbuf[i].u1 *= rdp.vtxbuf[i].q;661rdp.vtxbuf[i].v1 *= rdp.vtxbuf[i].q;662}663}664665if (rdp.zsrc == 1)666rdp.vtxbuf[i].z = rdp.prim_depth;667668// Don't remove clipping, or it will freeze669if (rdp.vtxbuf[i].x > rdp.scissor.lr_x) rdp.clip |= CLIP_XMAX;670if (rdp.vtxbuf[i].x < rdp.scissor.ul_x) rdp.clip |= CLIP_XMIN;671if (rdp.vtxbuf[i].y > rdp.scissor.lr_y) rdp.clip |= CLIP_YMAX;672if (rdp.vtxbuf[i].y < rdp.scissor.ul_y) rdp.clip |= CLIP_YMIN;673}674675clip_tri (linew);676}677678void do_triangle_stuff_2 (WORD linew)679{680rdp.clip = 0;681682for (int i=0; i<rdp.n_global; i++)683{684// Don't remove clipping, or it will freeze685if (rdp.vtxbuf[i].x > rdp.scissor.lr_x) rdp.clip |= CLIP_XMAX;686if (rdp.vtxbuf[i].x < rdp.scissor.ul_x) rdp.clip |= CLIP_XMIN;687if (rdp.vtxbuf[i].y > rdp.scissor.lr_y) rdp.clip |= CLIP_YMAX;688if (rdp.vtxbuf[i].y < rdp.scissor.ul_y) rdp.clip |= CLIP_YMIN;689}690691clip_tri (linew);692}693694//695// clip_z - clips along the z-axis, also copies the vertex buffer for clip_tri696// * ALWAYS * processes it, even if it does not need z-clipping. It needs697// to copy the buffer anyway.698//699700void clip_z ()701{702int i,j,index,n=rdp.n_global;703float percent;704705if (rdp.clip & CLIP_ZMIN)706{707// Swap vertex buffers708VERTEX *tmp = rdp.vtxbuf2;709rdp.vtxbuf2 = rdp.vtxbuf;710rdp.vtxbuf = tmp;711rdp.vtx_buffer ^= 1;712index = 0;713714// Check the vertices for clipping715for (i=0; i<n; i++)716{717j = i+1;718if (j == n) j = 0;719720if (Vi.w >= 0.01f)721{722if (Vj.w >= 0.01f) // Both are in, save the last one723{724rdp.vtxbuf[index] = Vj;725rdp.vtxbuf[index++].not_zclipped = 1;726}727else // First is in, second is out, save intersection728{729percent = (-Vi.w) / (Vj.w - Vi.w);730rdp.vtxbuf[index].not_zclipped = 0;731rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;732rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;733rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;734rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;735rdp.vtxbuf[index].w = 0.01f;736rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;737rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;738rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;739rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;740rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);741rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);742rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);743rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);744}745}746else747{748//if (Vj.w < 0.01f) // Both are out, save nothing749if (Vj.w >= 0.01f) // First is out, second is in, save intersection & in point750{751percent = (-Vj.w) / (Vi.w - Vj.w);752rdp.vtxbuf[index].not_zclipped = 0;753rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;754rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;755rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;756rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;757rdp.vtxbuf[index].w = 0.01f;758rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;759rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;760rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;761rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;762rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);763rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);764rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);765rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);766767// Save the in point768rdp.vtxbuf[index] = Vj;769rdp.vtxbuf[index++].not_zclipped = 1;770}771}772}773rdp.n_global = index;774}775}776777static void CalculateLOD(VERTEX **v, int n)778{779//rdp.update |= UPDATE_TEXTURE;780/*781if (rdp.lod_calculated)782{783float detailmax;784if (dc0_detailmax < 0.5)785detailmax = rdp.lod_fraction;786else787detailmax = 1.0f - rdp.lod_fraction;788grTexDetailControl (GR_TMU0, dc0_lodbias, dc0_detailscale, detailmax);789if (num_tmu == 2)790grTexDetailControl (GR_TMU1, dc1_lodbias, dc1_detailscale, detailmax);791return;792}793*/794float deltaS, deltaT;795float deltaX, deltaY;796double deltaTexels, deltaPixels, lodFactor = 0;797double intptr;798float s_scale = rdp.tiles[rdp.cur_tile].width / 255.0f;799float t_scale = rdp.tiles[rdp.cur_tile].height / 255.0f;800if (settings.lodmode == 1)801{802deltaS = (v[1]->u0/v[1]->q - v[0]->u0/v[0]->q) * s_scale;803deltaT = (v[1]->v0/v[1]->q - v[0]->v0/v[0]->q) * t_scale;804deltaTexels = sqrt( deltaS * deltaS + deltaT * deltaT );805806deltaX = (v[1]->x - v[0]->x)/rdp.scale_x;807deltaY = (v[1]->y - v[0]->y)/rdp.scale_y;808deltaPixels = sqrt( deltaX * deltaX + deltaY * deltaY );809810lodFactor = deltaTexels / deltaPixels;811}812else813{814int i, j;815for (i = 0; i < n; i++)816{817j = (i < n-1) ? i + 1 : 0;818819deltaS = (v[j]->u0/v[j]->q - v[i]->u0/v[i]->q) * s_scale;820deltaT = (v[j]->v0/v[j]->q - v[i]->v0/v[i]->q) * t_scale;821// deltaS = v[j]->ou - v[i]->ou;822// deltaT = v[j]->ov - v[i]->ov;823deltaTexels = sqrt( deltaS * deltaS + deltaT * deltaT );824825deltaX = (v[j]->x - v[i]->x)/rdp.scale_x;826deltaY = (v[j]->y - v[i]->y)/rdp.scale_y;827deltaPixels = sqrt( deltaX * deltaX + deltaY * deltaY );828829lodFactor += deltaTexels / deltaPixels;830}831// Divide by n (n edges) to find average832lodFactor = lodFactor / n;833}834long ilod = (long)lodFactor;835int lod_tile = min((int)(log((double)ilod)/log(2.0)), rdp.cur_tile + rdp.mipmap_level);836float lod_fraction = 1.0f;837if (lod_tile < rdp.cur_tile + rdp.mipmap_level)838{839lod_fraction = max((float)modf(lodFactor / pow(2.0f,lod_tile),&intptr), rdp.prim_lodmin / 255.0f);840}841float detailmax;842if (cmb.dc0_detailmax < 0.5f)843detailmax = lod_fraction;844else845detailmax = 1.0f - lod_fraction;846grTexDetailControl (GR_TMU0, cmb.dc0_lodbias, cmb.dc0_detailscale, detailmax);847if (num_tmu == 2)848grTexDetailControl (GR_TMU1, cmb.dc1_lodbias, cmb.dc1_detailscale, detailmax);849FRDP("CalculateLOD factor: %f, tile: %d, lod_fraction: %f\n", (float)lodFactor, lod_tile, lod_fraction);850}851852static void DepthBuffer(VERTEX ** vtx, int n)853{854if (settings.RE2)855{856for(int i=0; i<n; i++)857{858int fz = (int)(vtx[i]->z*8.0f+0.5f);859if (fz < 0) fz = 0;860else if (fz >= 0x40000) fz = 0x40000 - 1;861vtx[i]->z = (float)zLUT[fz];862}863return;864}865if (settings.fb_depth_render && dzdx && (rdp.flags & ZBUF_UPDATE))866{867vertexi v[12];868869for(int i=0; i<n; i++)870{871v[i].x = (long)(vtx[i]->x / rdp.scale_x * 65536.0);872v[i].y = (long)(vtx[i]->y / rdp.scale_y * 65536.0);873v[i].z = (long)(vtx[i]->z * 65536.0);874}875Rasterize(v, n, dzdx);876}877for(int i=0; i<n; i++)878vtx[i]->z = ScaleZ(vtx[i]->z);879}880881void clip_tri (WORD linew)882{883int i,j,index,n=rdp.n_global;884float percent;885886// rdp.vtxbuf and rdp.vtxbuf2 were set by clip_z887888// Check which clipping is needed889if (rdp.clip & CLIP_XMAX) // right of the screen890{891// Swap vertex buffers892VERTEX *tmp = rdp.vtxbuf2;893rdp.vtxbuf2 = rdp.vtxbuf;894rdp.vtxbuf = tmp;895rdp.vtx_buffer ^= 1;896index = 0;897898// Check the vertices for clipping899for (i=0; i<n; i++)900{901j = i+1;902if (j == n) j = 0;903904if (Vi.x <= rdp.scissor.lr_x)905{906if (Vj.x <= rdp.scissor.lr_x) // Both are in, save the last one907{908rdp.vtxbuf[index++] = Vj;909}910else // First is in, second is out, save intersection911{912percent = (rdp.scissor.lr_x - Vi.x) / (Vj.x - Vi.x);913rdp.vtxbuf[index].x = (float)rdp.scissor.lr_x + 0.001f;914rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;915rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;916rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;917rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;918rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;919rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;920rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;921rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;922rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);923rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);924rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);925rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);926}927}928else929{930//if (Vj.x > rdp.scissor.lr_x) // Both are out, save nothing931if (Vj.x <= rdp.scissor.lr_x) // First is out, second is in, save intersection & in point932{933percent = (rdp.scissor.lr_x - Vj.x) / (Vi.x - Vj.x);934rdp.vtxbuf[index].x = (float)rdp.scissor.lr_x + 0.001f;935rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;936rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;937rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;938rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;939rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;940rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;941rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;942rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;943rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);944rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);945rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);946rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);947948// Save the in point949rdp.vtxbuf[index++] = Vj;950}951}952}953n = index;954}955if (rdp.clip & CLIP_XMIN) // left of the screen956{957// Swap vertex buffers958VERTEX *tmp = rdp.vtxbuf2;959rdp.vtxbuf2 = rdp.vtxbuf;960rdp.vtxbuf = tmp;961rdp.vtx_buffer ^= 1;962index = 0;963964// Check the vertices for clipping965for (i=0; i<n; i++)966{967j = i+1;968if (j == n) j = 0;969970if (Vi.x >= rdp.scissor.ul_x)971{972if (Vj.x >= rdp.scissor.ul_x) // Both are in, save the last one973{974rdp.vtxbuf[index++] = Vj;975}976else // First is in, second is out, save intersection977{978percent = (rdp.scissor.ul_x - Vi.x) / (Vj.x - Vi.x);979rdp.vtxbuf[index].x = (float)rdp.scissor.ul_x + 0.001f;980rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent;981rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;982rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;983rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;984rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;985rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;986rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;987rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;988rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);989rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);990rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);991rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);992}993}994else995{996//if (Vj.x < rdp.scissor.ul_x) // Both are out, save nothing997if (Vj.x >= rdp.scissor.ul_x) // First is out, second is in, save intersection & in point998{999percent = (rdp.scissor.ul_x - Vj.x) / (Vi.x - Vj.x);1000rdp.vtxbuf[index].x = (float)rdp.scissor.ul_x + 0.001f;1001rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent;1002rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;1003rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;1004rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;1005rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;1006rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;1007rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;1008rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;1009rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);1010rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);1011rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);1012rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);10131014// Save the in point1015rdp.vtxbuf[index++] = Vj;1016}1017}1018}1019n = index;1020}1021if (rdp.clip & CLIP_YMAX) // top of the screen1022{1023// Swap vertex buffers1024VERTEX *tmp = rdp.vtxbuf2;1025rdp.vtxbuf2 = rdp.vtxbuf;1026rdp.vtxbuf = tmp;1027rdp.vtx_buffer ^= 1;1028index = 0;10291030// Check the vertices for clipping1031for (i=0; i<n; i++)1032{1033j = i+1;1034if (j == n) j = 0;10351036if (Vi.y <= rdp.scissor.lr_y)1037{1038if (Vj.y <= rdp.scissor.lr_y) // Both are in, save the last one1039{1040rdp.vtxbuf[index++] = Vj;1041}1042else // First is in, second is out, save intersection1043{1044percent = (rdp.scissor.lr_y - Vi.y) / (Vj.y - Vi.y);1045rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;1046rdp.vtxbuf[index].y = (float)rdp.scissor.lr_y + 0.001f;1047rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;1048rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;1049rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;1050rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;1051rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;1052rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;1053rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;1054rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);1055rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);1056rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);1057rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);1058}1059}1060else1061{1062//if (Vj.y > rdp.scissor.lr_y) // Both are out, save nothing1063if (Vj.y <= rdp.scissor.lr_y) // First is out, second is in, save intersection & in point1064{1065percent = (rdp.scissor.lr_y - Vj.y) / (Vi.y - Vj.y);1066rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;1067rdp.vtxbuf[index].y = (float)rdp.scissor.lr_y + 0.001f;1068rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;1069rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;1070rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;1071rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;1072rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;1073rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;1074rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;1075rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);1076rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);1077rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);1078rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);10791080// Save the in point1081rdp.vtxbuf[index++] = Vj;1082}1083}1084}1085n = index;1086}1087if (rdp.clip & CLIP_YMIN) // bottom of the screen1088{1089// Swap vertex buffers1090VERTEX *tmp = rdp.vtxbuf2;1091rdp.vtxbuf2 = rdp.vtxbuf;1092rdp.vtxbuf = tmp;1093rdp.vtx_buffer ^= 1;1094index = 0;10951096// Check the vertices for clipping1097for (i=0; i<n; i++)1098{1099j = i+1;1100if (j == n) j = 0;11011102if (Vi.y >= rdp.scissor.ul_y)1103{1104if (Vj.y >= rdp.scissor.ul_y) // Both are in, save the last one1105{1106rdp.vtxbuf[index++] = Vj;1107}1108else // First is in, second is out, save intersection1109{1110percent = (rdp.scissor.ul_y - Vi.y) / (Vj.y - Vi.y);1111rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;1112rdp.vtxbuf[index].y = (float)rdp.scissor.ul_y + 0.001f;1113rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent;1114rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent;1115rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent;1116rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent;1117rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent;1118rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent;1119rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent;1120rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent);1121rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent);1122rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent);1123rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent);1124}1125}1126else1127{1128//if (Vj.y < rdp.scissor.ul_y) // Both are out, save nothing1129if (Vj.y >= rdp.scissor.ul_y) // First is out, second is in, save intersection & in point1130{1131percent = (rdp.scissor.ul_y - Vj.y) / (Vi.y - Vj.y);1132rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;1133rdp.vtxbuf[index].y = (float)rdp.scissor.ul_y + 0.001f;1134rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent;1135rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent;1136rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent;1137rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent;1138rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent;1139rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent;1140rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent;1141rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent);1142rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent);1143rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent);1144rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent);11451146// Save the in point1147rdp.vtxbuf[index++] = Vj;1148}1149}1150}1151n = index;1152}11531154if (n < 3)1155{1156FRDP (" * clip_tri: n < 3\n");1157return;1158}1159ConvertCoordsConvert (rdp.vtxbuf, n);1160if (rdp.fog_coord_enabled)1161{1162for (i = 0; i < n; i++)1163{1164rdp.vtxbuf[i].f = 1.0f/max(16.0f,rdp.vtxbuf[i].f);1165}1166}11671168if (settings.lodmode > 0 && rdp.cur_tile < rdp.mipmap_level)1169CalculateLOD(rdp.vtx_buffer?(vtx_list2):(vtx_list1), n);11701171cmb.cmb_ext_use = cmb.tex_cmb_ext_use = 0;11721173/*1174if (rdp.hires_tex)1175{1176for (int k = 0; k < 3; k++)1177{1178FRDP("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);1179}1180}1181*/1182if (fullscreen)1183{1184if (settings.wireframe)1185{1186SetWireframeCol ();1187for (i=0; i<n; i++)1188{1189j = i+1;1190if (j == n) j = 0;1191grDrawLine (&rdp.vtxbuf[i], &rdp.vtxbuf[j]);1192}1193}1194else1195{11961197// VERTEX ** pv = rdp.vtx_buffer?(vtx_list2):(vtx_list1);1198// for (int k = 0; k < n; k ++)1199// 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]);1200// pv[k]->y = settings.res_y - pv[k]->y;12011202if (linew > 0)1203{1204if (linew == 1)1205{1206for (i=0; i<n; i++)1207{1208rdp.vtxbuf[i].z = ScaleZ(rdp.vtxbuf[i].z);1209j = i+1;1210if (j == n) j = 0;1211grDrawLine (&rdp.vtxbuf[i], &rdp.vtxbuf[j]);1212}1213}1214else if (n == 3)1215{1216rdp.vtxbuf[0].z = ScaleZ(rdp.vtxbuf[0].z);1217rdp.vtxbuf[1].z = ScaleZ(rdp.vtxbuf[1].z);1218VERTEX v[4];1219v[0] = rdp.vtxbuf[0];1220v[1] = rdp.vtxbuf[0];1221v[2] = rdp.vtxbuf[1];1222v[3] = rdp.vtxbuf[1];1223float width = (linew-1)*0.25f;1224if(rdp.vtxbuf[0].y == rdp.vtxbuf[1].y )1225{1226v[0].x = v[1].x = rdp.vtxbuf[0].x;1227v[2].x = v[3].x = rdp.vtxbuf[1].x;12281229v[0].y = v[2].y = rdp.vtxbuf[0].y-width*rdp.scale_y+1;1230v[1].y = v[3].y = rdp.vtxbuf[0].y+width*rdp.scale_y;1231}1232else1233{1234v[0].y = v[1].y = rdp.vtxbuf[0].y;1235v[2].y = v[3].y = rdp.vtxbuf[1].y;12361237v[0].x = v[2].x = rdp.vtxbuf[0].x-width*rdp.scale_x+1;1238v[1].x = v[3].x = rdp.vtxbuf[0].x+width*rdp.scale_x;1239}1240grDrawTriangle(&v[0], &v[1], &v[2]);1241grDrawTriangle(&v[1], &v[2], &v[3]);1242}1243}1244else1245{1246if (settings.ucode == 5)1247for (i=0; i<n; i++)1248if (rdp.vtxbuf[i].z < -1000.0f) return;//rdp.vtxbuf[i].z = 0.0f;1249DepthBuffer(rdp.vtx_buffer?(vtx_list2):(vtx_list1), n);1250grDrawVertexArray (GR_TRIANGLE_FAN, n, rdp.vtx_buffer?(&vtx_list2):(&vtx_list1));1251}1252//grDrawVertexArrayContiguous (GR_TRIANGLE_FAN, n, rdp.vtxbuf, sizeof(VERTEX));1253}1254}12551256if (debug.capture) add_tri (rdp.vtxbuf, n, TRI_TRIANGLE);1257}12581259void add_tri (VERTEX *v, int n, int type)1260{1261//FRDP ("ENTER (%f, %f, %f), (%f, %f, %f), (%f, %f, %f)\n", v[0].x, v[0].y, v[0].w,1262// v[1].x, v[1].y, v[1].w, v[2].x, v[2].y, v[2].w);12631264// Debug capture1265if (debug.capture)1266{1267rdp.debug_n ++;12681269TRI_INFO *info = new TRI_INFO;1270info->nv = n;1271info->v = new VERTEX [n];1272memcpy (info->v, v, sizeof(VERTEX)*n);1273info->cycle_mode = rdp.cycle_mode;1274info->cycle1 = rdp.cycle1;1275info->cycle2 = rdp.cycle2;1276info->uncombined = rdp.uncombined;1277info->geom_mode = rdp.geom_mode;1278info->othermode_h = rdp.othermode_h;1279info->othermode_l = rdp.othermode_l;1280info->tri_n = rdp.tri_n;1281info->type = type;12821283for (int i=0; i<2; i++)1284{1285int j = rdp.cur_tile+i;1286if (i == 0)1287info->t[i].tmu = rdp.t0;1288else1289info->t[i].tmu = rdp.t1;1290info->t[i].cur_cache[0] = rdp.cur_cache_n[rdp.t0];1291info->t[i].cur_cache[1] = rdp.cur_cache_n[rdp.t1];1292info->t[i].format = rdp.tiles[j].format;1293info->t[i].size = rdp.tiles[j].size;1294info->t[i].width = rdp.tiles[j].width;1295info->t[i].height = rdp.tiles[j].height;1296info->t[i].line = rdp.tiles[j].line;1297info->t[i].palette = rdp.tiles[j].palette;1298info->t[i].clamp_s = rdp.tiles[j].clamp_s;1299info->t[i].clamp_t = rdp.tiles[j].clamp_t;1300info->t[i].mirror_s = rdp.tiles[j].mirror_s;1301info->t[i].mirror_t = rdp.tiles[j].mirror_t;1302info->t[i].shift_s = rdp.tiles[j].shift_s;1303info->t[i].shift_t = rdp.tiles[j].shift_t;1304info->t[i].mask_s = rdp.tiles[j].mask_s;1305info->t[i].mask_t = rdp.tiles[j].mask_t;1306info->t[i].ul_s = rdp.tiles[j].ul_s;1307info->t[i].ul_t = rdp.tiles[j].ul_t;1308info->t[i].lr_s = rdp.tiles[j].lr_s;1309info->t[i].lr_t = rdp.tiles[j].lr_t;1310info->t[i].t_ul_s = rdp.tiles[7].t_ul_s;1311info->t[i].t_ul_t = rdp.tiles[7].t_ul_t;1312info->t[i].t_lr_s = rdp.tiles[7].t_lr_s;1313info->t[i].t_lr_t = rdp.tiles[7].t_lr_t;1314info->t[i].scale_s = rdp.tiles[j].s_scale;1315info->t[i].scale_t = rdp.tiles[j].t_scale;1316}13171318info->fog_color = rdp.fog_color;1319info->fill_color = rdp.fill_color;1320info->prim_color = rdp.prim_color;1321info->blend_color = rdp.blend_color;1322info->env_color = rdp.env_color;1323info->prim_lodmin = rdp.prim_lodmin;1324info->prim_lodfrac = rdp.prim_lodfrac;13251326info->pNext = debug.tri_list;1327debug.tri_list = info;13281329if (debug.tri_last == NULL)1330debug.tri_last = debug.tri_list;1331}1332}13331334void update_scissor ()1335{1336if (rdp.update & UPDATE_SCISSOR)1337{1338rdp.update ^= UPDATE_SCISSOR;13391340// KILL the floating point error with 0.01f1341rdp.scissor.ul_x = (DWORD) max(min((rdp.scissor_o.ul_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0);1342rdp.scissor.lr_x = (DWORD) max(min((rdp.scissor_o.lr_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0);1343rdp.scissor.ul_y = (DWORD) max(min((rdp.scissor_o.ul_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0);1344rdp.scissor.lr_y = (DWORD) max(min((rdp.scissor_o.lr_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0);1345FRDP (" |- scissor - (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y,1346rdp.scissor.lr_x, rdp.scissor.lr_y);1347}1348}13491350//1351// update - update states if they need it1352//13531354typedef struct1355{1356unsigned int c2_m2b:2;1357unsigned int c1_m2b:2;1358unsigned int c2_m2a:2;1359unsigned int c1_m2a:2;1360unsigned int c2_m1b:2;1361unsigned int c1_m1b:2;1362unsigned int c2_m1a:2;1363unsigned int c1_m1a:2;1364} rdp_blender_setting;13651366void update ()1367{1368RDP ("-+ update called\n");1369// Check for rendermode changes1370// Z buffer1371if (rdp.render_mode_changed & 0x00000C30)1372{1373FRDP (" |- render_mode_changed zbuf - decal: %s, update: %s, compare: %s\n",1374str_yn[(rdp.othermode_l&0x00000C00) == 0x00000C00],1375str_yn[(rdp.othermode_l&0x00000020)?1:0],1376str_yn[(rdp.othermode_l&0x00000010)?1:0]);13771378rdp.render_mode_changed &= ~0x00000C30;1379rdp.update |= UPDATE_ZBUF_ENABLED;13801381// Decal?1382// if ((rdp.othermode_l & 0x00000C00) == 0x00000C00)1383if (rdp.othermode_l & 0x00000800)1384rdp.flags |= ZBUF_DECAL;1385else1386rdp.flags &= ~ZBUF_DECAL;13871388// Update?1389if ((rdp.othermode_l & 0x00000020))1390rdp.flags |= ZBUF_UPDATE;1391else1392rdp.flags &= ~ZBUF_UPDATE;13931394// Compare?1395if (rdp.othermode_l & 0x00000010)1396rdp.flags |= ZBUF_COMPARE;1397else1398rdp.flags &= ~ZBUF_COMPARE;1399}14001401// Alpha compare1402if (rdp.render_mode_changed & 0x00001000)1403{1404FRDP (" |- render_mode_changed alpha compare - on: %s\n",1405str_yn[(rdp.othermode_l&0x00001000)?1:0]);1406rdp.render_mode_changed &= ~0x00001000;1407rdp.update |= UPDATE_ALPHA_COMPARE;14081409if (rdp.othermode_l & 0x00001000)1410rdp.flags |= ALPHA_COMPARE;1411else1412rdp.flags &= ~ALPHA_COMPARE;1413}14141415if (rdp.render_mode_changed & 0x00002000) // alpha cvg sel1416{1417FRDP (" |- render_mode_changed alpha cvg sel - on: %s\n",1418str_yn[(rdp.othermode_l&0x00002000)?1:0]);1419rdp.render_mode_changed &= ~0x00002000;1420rdp.update |= UPDATE_COMBINE;1421}14221423// Force blend1424if (rdp.render_mode_changed & 0xFFFF0000)1425{1426FRDP (" |- render_mode_changed force_blend - %08lx\n", rdp.othermode_l&0xFFFF0000);1427rdp.render_mode_changed &= 0x0000FFFF;14281429rdp.fbl_a0 = (BYTE)((rdp.othermode_l>>30)&0x3);1430rdp.fbl_b0 = (BYTE)((rdp.othermode_l>>26)&0x3);1431rdp.fbl_c0 = (BYTE)((rdp.othermode_l>>22)&0x3);1432rdp.fbl_d0 = (BYTE)((rdp.othermode_l>>18)&0x3);1433rdp.fbl_a1 = (BYTE)((rdp.othermode_l>>28)&0x3);1434rdp.fbl_b1 = (BYTE)((rdp.othermode_l>>24)&0x3);1435rdp.fbl_c1 = (BYTE)((rdp.othermode_l>>20)&0x3);1436rdp.fbl_d1 = (BYTE)((rdp.othermode_l>>16)&0x3);14371438rdp.update |= UPDATE_COMBINE;1439}14401441//if (fullscreen)1442//{1443// Combine MUST go before texture1444if ((rdp.update & UPDATE_COMBINE) && rdp.allow_combine)1445{1446RDP (" |-+ update_combine\n");1447Combine ();1448}14491450if (rdp.update & UPDATE_TEXTURE) // note: UPDATE_TEXTURE and UPDATE_COMBINE are the same1451{1452rdp.tex_ctr ++;1453if (rdp.tex_ctr == 0xFFFFFFFF)1454rdp.tex_ctr = 0;14551456TexCache ();1457if (rdp.noise == noise_none)1458rdp.update ^= UPDATE_TEXTURE;1459}14601461if (fullscreen)1462{1463// Z buffer1464if (rdp.update & UPDATE_ZBUF_ENABLED)1465{1466// already logged above1467rdp.update ^= UPDATE_ZBUF_ENABLED;14681469if (rdp.flags & ZBUF_DECAL)1470{1471if ((rdp.othermode_l & 0x00000C00) == 0x00000C00)1472{1473grDepthBiasLevel (settings.depth_bias);//(-32);1474FRDP("depth bias: %d\n", settings.depth_bias);1475}1476else1477{1478// VP changed that to -1 (was -4)1479grDepthBiasLevel (-4);//-16);1480RDP("depth bias: -4");1481}1482}1483else1484{1485grDepthBiasLevel (0);1486}14871488if ((rdp.flags & ZBUF_ENABLED) || (settings.force_depth_compare && rdp.zsrc == 1))1489{1490if ((rdp.flags & ZBUF_COMPARE))1491{1492if (settings.soft_depth_compare)1493{1494grDepthBufferFunction (GR_CMP_LEQUAL);1495}1496else1497{1498grDepthBufferFunction (GR_CMP_LESS);1499}1500}1501else1502{1503grDepthBufferFunction (GR_CMP_ALWAYS);1504}15051506if ((rdp.flags & ZBUF_UPDATE)1507// || (rdp.flags & ZBUF_DECAL) // FOR DEBUGGING ONLY1508)1509{1510grDepthMask (FXTRUE);1511}1512else1513{1514grDepthMask (FXFALSE);1515}1516}1517else1518{1519grDepthBufferFunction (GR_CMP_ALWAYS);1520grDepthMask (FXFALSE);1521}1522}1523// Alpha compare1524if (rdp.update & UPDATE_ALPHA_COMPARE)1525{1526// already logged above1527rdp.update ^= UPDATE_ALPHA_COMPARE;15281529// if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && !force_full_alpha)1530// if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && (rdp.blend_color&0xFF))1531if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && (!(rdp.othermode_l & 0x00004000) || (rdp.blend_color&0xFF)))1532{1533BYTE reference = (BYTE)(rdp.blend_color&0xFF);1534if (reference)1535grAlphaTestFunction (GR_CMP_GEQUAL);1536else1537grAlphaTestFunction (GR_CMP_GREATER);1538grAlphaTestReferenceValue (reference);1539FRDP (" |- alpha compare: blend: %02lx\n", reference);1540}1541else1542{1543if (rdp.flags & ALPHA_COMPARE)1544{1545if ((rdp.othermode_l & 0x5000) != 0x5000)1546{1547grAlphaTestFunction (GR_CMP_GEQUAL);1548grAlphaTestReferenceValue (0x20);//0xA0);1549RDP (" |- alpha compare: 0x20\n");1550}1551else1552{1553grAlphaTestFunction (GR_CMP_GREATER);1554if (rdp.acmp == 3)1555{1556grAlphaTestReferenceValue ((BYTE)(rdp.blend_color&0xFF));1557FRDP (" |- alpha compare: blend: %02lx\n", rdp.blend_color&0xFF);1558}1559else1560{1561grAlphaTestReferenceValue (0x00);1562RDP (" |- alpha compare: 0x00\n");1563}1564}1565}1566else1567{1568grAlphaTestFunction (GR_CMP_ALWAYS);1569RDP (" |- alpha compare: none\n");1570}1571}1572if (rdp.acmp == 3)1573{1574if (grStippleModeExt)1575{1576RDP (" |- alpha compare: dither\n");1577grStippleModeExt(settings.stipple_mode);1578// grStippleModeExt(GR_STIPPLE_PATTERN);1579}1580}1581else1582{1583if (grStippleModeExt)1584{1585//RDP (" |- alpha compare: dither disabled\n");1586grStippleModeExt(GR_STIPPLE_DISABLE);1587}1588}1589}1590// Cull mode (leave this in for z-clipped triangles)1591if (rdp.update & UPDATE_CULL_MODE)1592{1593rdp.update ^= UPDATE_CULL_MODE;1594DWORD mode = (rdp.flags & CULLMASK) >> CULLSHIFT;1595FRDP (" |- cull_mode - mode: %s\n", str_cull[mode]);1596switch (mode)1597{1598case 0: // cull none1599case 3: // cull both1600grCullMode(GR_CULL_DISABLE);1601break;1602case 1: // cull front1603// grCullMode(GR_CULL_POSITIVE);1604grCullMode(GR_CULL_NEGATIVE);1605break;1606case 2: // cull back1607// grCullMode (GR_CULL_NEGATIVE);1608grCullMode (GR_CULL_POSITIVE);1609break;1610}1611}16121613//Added by Gonetz.1614if (settings.fog && (rdp.update & UPDATE_FOG_ENABLED))1615{1616rdp.update ^= UPDATE_FOG_ENABLED;16171618if (rdp.flags & FOG_ENABLED)1619{1620typedef union { WORD *w; rdp_blender_setting *b; } BLEND;1621WORD blword = (WORD) (rdp.othermode_l >> 16);1622BLEND bl;1623bl.w = &blword;1624if((rdp.fog_multiplier > 0) && (bl.b->c1_m1a==3 || bl.b->c1_m2a == 3 || bl.b->c2_m1a == 3 || bl.b->c2_m2a == 3))1625{1626grFogColorValue(rdp.fog_color);1627grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);1628rdp.fog_coord_enabled = TRUE;1629RDP("fog enabled \n");1630}1631else1632{1633RDP("fog disabled in blender\n");1634rdp.fog_coord_enabled = FALSE;1635grFogMode (GR_FOG_DISABLE);1636}1637}1638else1639{1640RDP("fog disabled\n");1641rdp.fog_coord_enabled = FALSE;1642grFogMode (GR_FOG_DISABLE);1643}1644}1645}16461647if (rdp.update & UPDATE_VIEWPORT)1648{1649rdp.update ^= UPDATE_VIEWPORT;1650if (fullscreen)1651{1652if (settings.RE2)1653{1654grClipWindow (0, 0, settings.res_x-1, settings.res_y-1);1655}1656else1657{1658float scale_x = (float)fabs(rdp.view_scale[0]);1659float scale_y = (float)fabs(rdp.view_scale[1]);1660//printf("scale_y %g\n", scale_y);16611662DWORD min_x = (DWORD) max(rdp.view_trans[0] - scale_x, 0);1663DWORD min_y = (DWORD) max(rdp.view_trans[1] - scale_y, 0);1664DWORD max_x = (DWORD) min(rdp.view_trans[0] + scale_x + 1, settings.res_x);1665DWORD max_y = (DWORD) min(rdp.view_trans[1] + scale_y + 1, settings.res_y);16661667FRDP (" |- viewport - (%d, %d, %d, %d)\n", min_x, min_y, max_x, max_y);1668grClipWindow (min_x, min_y, max_x, max_y);1669//printf("viewport %d %d %d %d\n", min_x, min_y, max_x, max_y);1670}1671}1672}16731674if (rdp.update & UPDATE_SCISSOR)1675update_scissor ();16761677RDP (" + update end\n");1678}16791680void set_message_combiner ()1681{1682grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,1683GR_COMBINE_FACTOR_ONE,1684GR_COMBINE_LOCAL_NONE,1685GR_COMBINE_OTHER_TEXTURE,1686FXFALSE);1687grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,1688GR_COMBINE_FACTOR_ONE,1689GR_COMBINE_LOCAL_NONE,1690GR_COMBINE_OTHER_TEXTURE,1691FXFALSE);1692if (settings.buff_clear && (settings.show_fps & 0x08))1693grAlphaBlendFunction (GR_BLEND_SRC_ALPHA,1694GR_BLEND_ONE_MINUS_SRC_ALPHA,1695GR_BLEND_ZERO,1696GR_BLEND_ZERO);1697else1698grAlphaBlendFunction (GR_BLEND_ONE,1699GR_BLEND_ZERO,1700GR_BLEND_ZERO,1701GR_BLEND_ZERO);1702grAlphaTestFunction (GR_CMP_ALWAYS);1703if (grStippleModeExt)1704{1705grStippleModeExt(GR_STIPPLE_DISABLE);1706}1707grTexCombine (GR_TMU1,1708GR_COMBINE_FUNCTION_NONE,1709GR_COMBINE_FACTOR_NONE,1710GR_COMBINE_FUNCTION_NONE,1711GR_COMBINE_FACTOR_NONE,1712FXFALSE, FXFALSE);1713grTexCombine (GR_TMU0,1714GR_COMBINE_FUNCTION_LOCAL,1715GR_COMBINE_FACTOR_NONE,1716GR_COMBINE_FUNCTION_LOCAL,1717GR_COMBINE_FACTOR_NONE,1718FXFALSE, FXFALSE);1719grTexSource(GR_TMU0,1720grTexMinAddress(GR_TMU0) + offset_font,1721GR_MIPMAPLEVELMASK_BOTH,1722&fontTex);1723grFogMode (GR_FOG_DISABLE);1724}17251726/*17271 bit: common17282 bit: I textures, V-Rally 9917293 bit: South Park, Polaris17304 bit: Mace17315 bit: CyberTiger17326 bit: Yoshi Story1733*/1734void fix_tex_coord (VERTEX **v)1735{1736BOOL fix = FALSE;1737if (settings.fix_tex_coord & 449)1738{1739// if ( (rdp.tiles[rdp.last_tile_size].format == 2) ||1740// ( (rdp.tiles[rdp.last_tile_size].size != 2)) )1741if (rdp.tiles[rdp.last_tile_size].size != 2)1742{1743if (settings.fix_tex_coord & 128)1744{1745if (v[0]->sz != v[1]->sz || v[0]->sz != v[2]->sz)1746return;1747}17481749if (settings.fix_tex_coord & 256) //dr.mario1750{1751if ((rdp.tiles[rdp.last_tile_size].format == 2) && (rdp.tiles[rdp.last_tile_size].size == 0))1752return;1753}17541755// int lu = (rdp.tiles[rdp.last_tile_size].ul_s)<<1;1756int ru = (rdp.tiles[rdp.last_tile_size].lr_s+1)<<1;1757int rv = (rdp.tiles[rdp.last_tile_size].lr_t+1)<<1;1758int diff = (settings.fix_tex_coord & 64) ? 5 : 3;17591760for (int t = 0; t < 3; t++)1761{1762if (v[t]->uv_fixed == 0) //&& (((short)v[t]->ou > 0) || ((short)v[t]->ov > 0)))1763{1764if ( (abs((short)v[t]->ou - ru) < diff) || (abs((short)v[t]->ov - rv) < diff) )1765// if ( ((short)v[t]->ou == lu) || (abs((short)v[t]->ou - ru) < 3) )1766{1767fix = TRUE;1768break;1769}1770}1771else1772{1773fix = TRUE;1774break;1775}1776}1777if (fix)1778{1779for (int t = 0; t < 3; t++)1780{1781if (v[t]->uv_fixed == 0)1782{1783v[t]->uv_fixed = 1;1784FRDP("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);1785v[t]->ou *= 0.5f;1786v[t]->ov *= 0.5f;1787}1788}1789return;1790}1791}1792}1793if (settings.fix_tex_coord & 2)1794{1795if (rdp.tiles[rdp.last_tile_size].format == 4)1796{1797for (int t = 0; t < 3; t++)1798{1799if (v[t]->uv_fixed == 0)1800{1801v[t]->uv_fixed = 1;1802v[t]->ou *= 0.5f;1803v[t]->ov *= 0.5f;1804}1805}1806return;1807}1808}1809if (settings.fix_tex_coord & 4)1810{1811TILE & last_tile = rdp.tiles[rdp.last_tile_size];1812if ((last_tile.format == 2) &&1813(last_tile.size == 0) &&1814(last_tile.line%2 == 0) &&1815(last_tile.lr_s >= last_tile.lr_t))1816{1817int ru = (rdp.tiles[rdp.last_tile_size].lr_s+1);1818int rv = (rdp.tiles[rdp.last_tile_size].lr_t+1);1819int t;1820for (t = 0; t < 3; t++)1821{1822if (v[t]->uv_fixed == 0)1823{1824if ( (abs((short)v[t]->ou - ru) < 3) || (abs((short)v[t]->ov - rv) < 3) )1825return;1826}1827}1828for (t = 0; t < 3; t++)1829{1830if (v[t]->uv_fixed == 0)1831{1832v[t]->uv_fixed = 1;1833v[t]->ou *= 0.5f;1834v[t]->ov *= 0.5f;1835}1836}1837return;1838}1839}1840if (settings.fix_tex_coord & 8)1841{1842if (rdp.tiles[rdp.last_tile_size].format == 3 && rdp.tiles[rdp.last_tile_size].size == 1)1843{1844short width = (rdp.tiles[rdp.last_tile_size].ul_s<<1)+1 ;1845for (int t = 0; t < 3; t++)1846{1847if (v[t]->uv_fixed == 0)1848{1849if (short(v[t]->ou) == width)1850{1851fix = TRUE;1852break;1853}1854}1855else1856{1857fix = TRUE;1858break;1859}1860}1861if (fix)1862{1863RDP("texcoord fixed!\n");1864for (int t = 0; t < 3; t++)1865{1866if (v[t]->uv_fixed == 0)1867{1868v[t]->uv_fixed = 1;1869v[t]->ou *= 0.5f;1870v[t]->ov *= 0.5f;1871}1872}1873return;1874}1875}1876}1877if (settings.fix_tex_coord & 16)1878{1879if ((rdp.tiles[rdp.last_tile_size].format == 2) && (rdp.tiles[rdp.last_tile_size].size == 0))1880{1881short width = rdp.tiles[rdp.last_tile_size].lr_s + 1;1882short height = rdp.tiles[rdp.last_tile_size].lr_t + 1;1883for (int t = 0; t < 3; t++)1884{1885if (v[t]->uv_fixed == 0)1886{1887if ((short(v[t]->ou) > width) || (short(v[t]->ov) > height))1888{1889fix = TRUE;1890break;1891}1892}1893else1894{1895fix = TRUE;1896break;1897}1898}1899if (fix)1900{1901for (int t = 0; t < 3; t++)1902{1903if (v[t]->uv_fixed == 0)1904{1905v[t]->uv_fixed = 1;1906v[t]->ou *= 0.5f;1907v[t]->ov *= 0.5f;1908}1909}1910RDP("texcoord fixed!\n");1911return;1912}1913}1914}1915if (settings.fix_tex_coord & 32)1916{1917if (!rdp.vtx[rdp.v0].uv_fixed &&1918(rdp.tiles[rdp.last_tile_size].format == 2) &&1919(rdp.tiles[rdp.last_tile_size].size == 1) &&1920(rdp.tiles[rdp.last_tile_size].lr_s >= 31) &&1921(rdp.tiles[rdp.last_tile_size].lr_t >= 31))1922{1923int ru = (rdp.tiles[rdp.last_tile_size].lr_s+1)<<1;1924int rv = (rdp.tiles[rdp.last_tile_size].lr_t+1)<<1;1925int top = rdp.v0 + rdp.vn;1926for (int t = rdp.v0; t < top; t++)1927{1928if ( (abs((short)rdp.vtx[t].ou - ru) < 2) || (abs((short)rdp.vtx[t].ov - rv) < 2) )1929{1930fix = TRUE;1931break;1932}1933}1934if (fix)1935{1936for (int t = rdp.v0; t < top; t++)1937{1938rdp.vtx[t].uv_fixed = 1;1939rdp.vtx[t].ou *= 0.5f;1940rdp.vtx[t].ov *= 0.5f;1941}1942RDP("texcoord fixed!\n");1943return;1944}1945}1946}1947}1948194919501951