Path: blob/master/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/ucode00.h
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#define ucode_Fast3D 040#define ucode_F3DEX 141#define ucode_F3DEX2 242#define ucode_WaveRace 343#define ucode_StarWars 444#define ucode_DiddyKong 545#define ucode_S2DEX 646#define ucode_PerfectDark 747#define ucode_CBFD 848#define ucode_zSort 949#define ucode_Turbo3d 215051static void rsp_vertex(int v0, int n)52{53wxUint32 addr = segoffset(rdp.cmd1) & 0x00FFFFFF;54int i;55float x, y, z;5657rdp.v0 = v0; // Current vertex58rdp.vn = n; // Number to copy5960// This is special, not handled in update(), but here61// * Matrix Pre-multiplication idea by Gonetz ([email protected])62if (rdp.update & UPDATE_MULT_MAT)63{64rdp.update ^= UPDATE_MULT_MAT;65MulMatrices(rdp.model, rdp.proj, rdp.combined);66}67// *6869// This is special, not handled in update()70if (rdp.update & UPDATE_LIGHTS)71{72rdp.update ^= UPDATE_LIGHTS;7374// Calculate light vectors75for (wxUint32 l=0; l<rdp.num_lights; l++)76{77InverseTransformVector(&rdp.light[l].dir_x, rdp.light_vector[l], rdp.model);78NormalizeVector (rdp.light_vector[l]);79}80}8182FRDP ("rsp:vertex v0:%d, n:%d, from: %08lx\n", v0, n, addr);8384for (i=0; i < (n<<4); i+=16)85{86VERTEX *v = &rdp.vtx[v0 + (i>>4)];87x = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 0)^1];88y = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 1)^1];89z = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 2)^1];90v->flags = ((wxUint16*)gfx.RDRAM)[(((addr+i) >> 1) + 3)^1];91v->ou = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 4)^1];92v->ov = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 5)^1];93v->uv_scaled = 0;94v->a = ((wxUint8*)gfx.RDRAM)[(addr+i + 15)^3];9596v->x = x*rdp.combined[0][0] + y*rdp.combined[1][0] + z*rdp.combined[2][0] + rdp.combined[3][0];97v->y = x*rdp.combined[0][1] + y*rdp.combined[1][1] + z*rdp.combined[2][1] + rdp.combined[3][1];98v->z = x*rdp.combined[0][2] + y*rdp.combined[1][2] + z*rdp.combined[2][2] + rdp.combined[3][2];99v->w = x*rdp.combined[0][3] + y*rdp.combined[1][3] + z*rdp.combined[2][3] + rdp.combined[3][3];100101102if (fabs(v->w) < 0.001) v->w = 0.001f;103v->oow = 1.0f / v->w;104v->x_w = v->x * v->oow;105v->y_w = v->y * v->oow;106v->z_w = v->z * v->oow;107CalculateFog (v);108109v->uv_calculated = 0xFFFFFFFF;110v->screen_translated = 0;111v->shade_mod = 0;112113v->scr_off = 0;114if (v->x < -v->w) v->scr_off |= 1;115if (v->x > v->w) v->scr_off |= 2;116if (v->y < -v->w) v->scr_off |= 4;117if (v->y > v->w) v->scr_off |= 8;118if (v->w < 0.1f) v->scr_off |= 16;119// if (v->z_w > 1.0f) v->scr_off |= 32;120121if (rdp.geom_mode & 0x00020000)122{123v->vec[0] = ((char*)gfx.RDRAM)[(addr+i + 12)^3];124v->vec[1] = ((char*)gfx.RDRAM)[(addr+i + 13)^3];125v->vec[2] = ((char*)gfx.RDRAM)[(addr+i + 14)^3];126if (rdp.geom_mode & 0x40000)127{128if (rdp.geom_mode & 0x80000)129calc_linear (v);130else131calc_sphere (v);132}133NormalizeVector (v->vec);134135calc_light (v);136}137else138{139v->r = ((wxUint8*)gfx.RDRAM)[(addr+i + 12)^3];140v->g = ((wxUint8*)gfx.RDRAM)[(addr+i + 13)^3];141v->b = ((wxUint8*)gfx.RDRAM)[(addr+i + 14)^3];142}143#ifdef EXTREME_LOGGING144FRDP ("v%d - x: %f, y: %f, z: %f, w: %f, u: %f, v: %f, f: %f, z_w: %f, r=%d, g=%d, b=%d, a=%d\n", i>>4, v->x, v->y, v->z, v->w, v->ou*rdp.tiles[rdp.cur_tile].s_scale, v->ov*rdp.tiles[rdp.cur_tile].t_scale, v->f, v->z_w, v->r, v->g, v->b, v->a);145#endif146147}148}149150static void rsp_tri1(VERTEX **v, wxUint16 linew = 0)151{152if (cull_tri(v))153rdp.tri_n ++;154else155{156update ();157draw_tri (v, linew);158rdp.tri_n ++;159}160}161162static void rsp_tri2 (VERTEX **v)163{164int updated = 0;165166if (cull_tri(v))167rdp.tri_n ++;168else169{170updated = 1;171update ();172173draw_tri (v);174rdp.tri_n ++;175}176177if (cull_tri(v+3))178rdp.tri_n ++;179else180{181if (!updated)182update ();183184draw_tri (v+3);185rdp.tri_n ++;186}187}188189//190// uc0:vertex - loads vertices191//192static void uc0_vertex()193{194int v0 = (rdp.cmd0 >> 16) & 0xF; // Current vertex195int n = ((rdp.cmd0 >> 20) & 0xF) + 1; // Number of vertices to copy196rsp_vertex(v0, n);197}198199// ** Definitions **200201void modelview_load (float m[4][4])202{203memcpy (rdp.model, m, 64); // 4*4*4(float)204205rdp.update |= UPDATE_MULT_MAT | UPDATE_LIGHTS;206}207208void modelview_mul (float m[4][4])209{210DECLAREALIGN16VAR(m_src[4][4]);211memcpy (m_src, rdp.model, 64);212MulMatrices(m, m_src, rdp.model);213rdp.update |= UPDATE_MULT_MAT | UPDATE_LIGHTS;214}215216void modelview_push ()217{218if (rdp.model_i == rdp.model_stack_size)219{220RDP_E ("** Model matrix stack overflow ** too many pushes\n");221LRDP("** Model matrix stack overflow ** too many pushes\n");222return;223}224225memcpy (rdp.model_stack[rdp.model_i], rdp.model, 64);226rdp.model_i ++;227}228229void modelview_pop (int num = 1)230{231if (rdp.model_i > num - 1)232{233rdp.model_i -= num;234}235else236{237RDP_E ("** Model matrix stack error ** too many pops\n");238LRDP("** Model matrix stack error ** too many pops\n");239return;240}241memcpy (rdp.model, rdp.model_stack[rdp.model_i], 64);242rdp.update |= UPDATE_MULT_MAT | UPDATE_LIGHTS;243}244245void modelview_load_push (float m[4][4])246{247modelview_push ();248modelview_load (m);249}250251void modelview_mul_push (float m[4][4])252{253modelview_push ();254modelview_mul (m);255}256257void projection_load (float m[4][4])258{259memcpy (rdp.proj, m, 64); // 4*4*4(float)260261rdp.update |= UPDATE_MULT_MAT;262}263264void projection_mul (float m[4][4])265{266DECLAREALIGN16VAR(m_src[4][4]);267memcpy (m_src, rdp.proj, 64);268MulMatrices(m, m_src, rdp.proj);269rdp.update |= UPDATE_MULT_MAT;270}271272void load_matrix (float m[4][4], wxUint32 addr)273{274FRDP ("matrix - addr: %08lx\n", addr);275int x,y; // matrix index276addr >>= 1;277wxUint16 * src = (wxUint16*)gfx.RDRAM;278for (x=0; x<16; x+=4) { // Adding 4 instead of one, just to remove mult. later279for (y=0; y<4; y++) {280m[x>>2][y] = (float)(281(((wxInt32)src[(addr+x+y)^1]) << 16) |282src[(addr+x+y+16)^1]283) / 65536.0f;284}285}286}287288//289// uc0:matrix - performs matrix operations290//291static void uc0_matrix()292{293LRDP("uc0:matrix ");294295// Use segment offset to get the address296wxUint32 addr = segoffset(rdp.cmd1) & 0x00FFFFFF;297wxUint8 command = (wxUint8)((rdp.cmd0 >> 16) & 0xFF);298299DECLAREALIGN16VAR(m[4][4]);300load_matrix(m, addr);301302switch (command)303{304case 0: // modelview mul nopush305LRDP("modelview mul\n");306modelview_mul (m);307break;308309case 1: // projection mul nopush310case 5: // projection mul push, can't push projection311LRDP("projection mul\n");312projection_mul (m);313break;314315case 2: // modelview load nopush316LRDP("modelview load\n");317modelview_load (m);318break;319320case 3: // projection load nopush321case 7: // projection load push, can't push projection322LRDP("projection load\n");323projection_load (m);324325break;326327case 4: // modelview mul push328LRDP("modelview mul push\n");329modelview_mul_push (m);330break;331332case 6: // modelview load push333LRDP("modelview load push\n");334modelview_load_push (m);335break;336337default:338FRDP_E ("Unknown matrix command, %02lx", command);339FRDP ("Unknown matrix command, %02lx", command);340}341342#ifdef EXTREME_LOGGING343FRDP ("{%f,%f,%f,%f}\n", m[0][0], m[0][1], m[0][2], m[0][3]);344FRDP ("{%f,%f,%f,%f}\n", m[1][0], m[1][1], m[1][2], m[1][3]);345FRDP ("{%f,%f,%f,%f}\n", m[2][0], m[2][1], m[2][2], m[2][3]);346FRDP ("{%f,%f,%f,%f}\n", m[3][0], m[3][1], m[3][2], m[3][3]);347FRDP ("\nmodel\n{%f,%f,%f,%f}\n", rdp.model[0][0], rdp.model[0][1], rdp.model[0][2], rdp.model[0][3]);348FRDP ("{%f,%f,%f,%f}\n", rdp.model[1][0], rdp.model[1][1], rdp.model[1][2], rdp.model[1][3]);349FRDP ("{%f,%f,%f,%f}\n", rdp.model[2][0], rdp.model[2][1], rdp.model[2][2], rdp.model[2][3]);350FRDP ("{%f,%f,%f,%f}\n", rdp.model[3][0], rdp.model[3][1], rdp.model[3][2], rdp.model[3][3]);351FRDP ("\nproj\n{%f,%f,%f,%f}\n", rdp.proj[0][0], rdp.proj[0][1], rdp.proj[0][2], rdp.proj[0][3]);352FRDP ("{%f,%f,%f,%f}\n", rdp.proj[1][0], rdp.proj[1][1], rdp.proj[1][2], rdp.proj[1][3]);353FRDP ("{%f,%f,%f,%f}\n", rdp.proj[2][0], rdp.proj[2][1], rdp.proj[2][2], rdp.proj[2][3]);354FRDP ("{%f,%f,%f,%f}\n", rdp.proj[3][0], rdp.proj[3][1], rdp.proj[3][2], rdp.proj[3][3]);355#endif356}357358//359// uc0:movemem - loads a structure with data360//361static void uc0_movemem()362{363LRDP("uc0:movemem ");364365wxUint32 i,a;366367// Check the command368switch ((rdp.cmd0 >> 16) & 0xFF)369{370case 0x80:371{372a = (segoffset(rdp.cmd1) & 0xFFFFFF) >> 1;373374short scale_x = ((short*)gfx.RDRAM)[(a+0)^1] / 4;375short scale_y = ((short*)gfx.RDRAM)[(a+1)^1] / 4;376short scale_z = ((short*)gfx.RDRAM)[(a+2)^1];377short trans_x = ((short*)gfx.RDRAM)[(a+4)^1] / 4;378short trans_y = ((short*)gfx.RDRAM)[(a+5)^1] / 4;379short trans_z = ((short*)gfx.RDRAM)[(a+6)^1];380if (settings.correct_viewport)381{382scale_x = abs(scale_x);383scale_y = abs(scale_y);384}385rdp.view_scale[0] = scale_x * rdp.scale_x;386rdp.view_scale[1] = -scale_y * rdp.scale_y;387rdp.view_scale[2] = 32.0f * scale_z;388rdp.view_trans[0] = trans_x * rdp.scale_x;389rdp.view_trans[1] = trans_y * rdp.scale_y;390rdp.view_trans[2] = 32.0f * trans_z;391392// there are other values than x and y, but I don't know what they do393394rdp.update |= UPDATE_VIEWPORT;395396FRDP ("viewport scale(%d, %d, %d), trans(%d, %d, %d), from:%08lx\n", scale_x, scale_y, scale_z,397trans_x, trans_y, trans_z, rdp.cmd1);398}399break;400401case 0x82:402{403a = segoffset(rdp.cmd1) & 0x00ffffff;404char dir_x = ((char*)gfx.RDRAM)[(a+8)^3];405rdp.lookat[1][0] = (float)(dir_x) / 127.0f;406char dir_y = ((char*)gfx.RDRAM)[(a+9)^3];407rdp.lookat[1][1] = (float)(dir_y) / 127.0f;408char dir_z = ((char*)gfx.RDRAM)[(a+10)^3];409rdp.lookat[1][2] = (float)(dir_z) / 127.0f;410if (!dir_x && !dir_y)411rdp.use_lookat = FALSE;412else413rdp.use_lookat = TRUE;414FRDP("lookat_y (%f, %f, %f)\n", rdp.lookat[1][0], rdp.lookat[1][1], rdp.lookat[1][2]);415}416break;417418case 0x84:419a = segoffset(rdp.cmd1) & 0x00ffffff;420rdp.lookat[0][0] = (float)(((char*)gfx.RDRAM)[(a+8)^3]) / 127.0f;421rdp.lookat[0][1] = (float)(((char*)gfx.RDRAM)[(a+9)^3]) / 127.0f;422rdp.lookat[0][2] = (float)(((char*)gfx.RDRAM)[(a+10)^3]) / 127.0f;423rdp.use_lookat = TRUE;424FRDP("lookat_x (%f, %f, %f)\n", rdp.lookat[1][0], rdp.lookat[1][1], rdp.lookat[1][2]);425break;426427case 0x86:428case 0x88:429case 0x8a:430case 0x8c:431case 0x8e:432case 0x90:433case 0x92:434case 0x94:435// Get the light #436i = (((rdp.cmd0 >> 16) & 0xff) - 0x86) >> 1;437a = segoffset(rdp.cmd1) & 0x00ffffff;438439// Get the data440rdp.light[i].r = (float)(((wxUint8*)gfx.RDRAM)[(a+0)^3]) / 255.0f;441rdp.light[i].g = (float)(((wxUint8*)gfx.RDRAM)[(a+1)^3]) / 255.0f;442rdp.light[i].b = (float)(((wxUint8*)gfx.RDRAM)[(a+2)^3]) / 255.0f;443rdp.light[i].a = 1.0f;444// ** Thanks to Icepir8 for pointing this out **445// Lighting must be signed byte instead of byte446rdp.light[i].dir_x = (float)(((char*)gfx.RDRAM)[(a+8)^3]) / 127.0f;447rdp.light[i].dir_y = (float)(((char*)gfx.RDRAM)[(a+9)^3]) / 127.0f;448rdp.light[i].dir_z = (float)(((char*)gfx.RDRAM)[(a+10)^3]) / 127.0f;449// **450451//rdp.update |= UPDATE_LIGHTS;452453FRDP ("light: n: %d, r: %.3f, g: %.3f, b: %.3f, x: %.3f, y: %.3f, z: %.3f\n",454i, rdp.light[i].r, rdp.light[i].g, rdp.light[i].b,455rdp.light_vector[i][0], rdp.light_vector[i][1], rdp.light_vector[i][2]);456break;457458459case 0x9E: //gSPForceMatrix command. Modification of uc2_movemem:matrix. Gonetz.460{461// do not update the combined matrix!462rdp.update &= ~UPDATE_MULT_MAT;463464wxUint32 addr = segoffset(rdp.cmd1) & 0x00FFFFFF;465load_matrix(rdp.combined, addr);466467addr = rdp.pc[rdp.pc_i] & BMASK;468rdp.pc[rdp.pc_i] = (addr+24) & BMASK; //skip next 3 command, b/c they all are part of gSPForceMatrix469470#ifdef EXTREME_LOGGING471FRDP ("{%f,%f,%f,%f}\n", rdp.combined[0][0], rdp.combined[0][1], rdp.combined[0][2], rdp.combined[0][3]);472FRDP ("{%f,%f,%f,%f}\n", rdp.combined[1][0], rdp.combined[1][1], rdp.combined[1][2], rdp.combined[1][3]);473FRDP ("{%f,%f,%f,%f}\n", rdp.combined[2][0], rdp.combined[2][1], rdp.combined[2][2], rdp.combined[2][3]);474FRDP ("{%f,%f,%f,%f}\n", rdp.combined[3][0], rdp.combined[3][1], rdp.combined[3][2], rdp.combined[3][3]);475#endif476}477break;478479//next 3 command should never appear since they will be skipped in previous command480case 0x98:481RDP_E ("uc0:movemem matrix 0 - ERROR!\n");482LRDP("matrix 0 - IGNORED\n");483break;484485case 0x9A:486RDP_E ("uc0:movemem matrix 1 - ERROR!\n");487LRDP("matrix 1 - IGNORED\n");488break;489490case 0x9C:491RDP_E ("uc0:movemem matrix 2 - ERROR!\n");492LRDP("matrix 2 - IGNORED\n");493break;494495default:496FRDP_E ("uc0:movemem unknown (index: 0x%08lx)\n", (rdp.cmd0 >> 16) & 0xFF);497FRDP ("unknown (index: 0x%08lx)\n", (rdp.cmd0 >> 16) & 0xFF);498}499}500501//502// uc0:displaylist - makes a call to another section of code503//504static void uc0_displaylist()505{506wxUint32 addr = segoffset(rdp.cmd1) & 0x00FFFFFF;507508// This fixes partially Gauntlet: Legends509if (addr == rdp.pc[rdp.pc_i] - 8) { LRDP("display list not executed!\n"); return; }510511wxUint32 push = (rdp.cmd0 >> 16) & 0xFF; // push the old location?512513FRDP("uc0:displaylist: %08lx, push:%s", addr, push?"no":"yes");514FRDP(" (seg %d, offset %08lx)\n", (rdp.cmd1>>24)&0x0F, rdp.cmd1&0x00FFFFFF);515516switch (push)517{518case 0: // push519if (rdp.pc_i >= 9) {520RDP_E ("** DL stack overflow **");521LRDP("** DL stack overflow **\n");522return;523}524rdp.pc_i ++; // go to the next PC in the stack525rdp.pc[rdp.pc_i] = addr; // jump to the address526break;527528case 1: // no push529rdp.pc[rdp.pc_i] = addr; // just jump to the address530break;531532default:533RDP_E("Unknown displaylist operation\n");534LRDP("Unknown displaylist operation\n");535}536}537538//539// tri1 - renders a triangle540//541static void uc0_tri1()542{543FRDP("uc0:tri1 #%d - %d, %d, %d\n", rdp.tri_n,544((rdp.cmd1>>16) & 0xFF) / 10,545((rdp.cmd1>>8) & 0xFF) / 10,546(rdp.cmd1 & 0xFF) / 10);547548VERTEX *v[3] = {549&rdp.vtx[((rdp.cmd1 >> 16) & 0xFF) / 10],550&rdp.vtx[((rdp.cmd1 >> 8) & 0xFF) / 10],551&rdp.vtx[(rdp.cmd1 & 0xFF) / 10]552};553if (settings.hacks & hack_Makers)554{555rdp.force_wrap = FALSE;556for (int i = 0; i < 3; i++)557{558if (v[i]->ou < 0.0f || v[i]->ov < 0.0f)559{560rdp.force_wrap = TRUE;561break;562}563}564}565rsp_tri1(v);566}567568//569// uc0:enddl - ends a call made by uc0:displaylist570//571static void uc0_enddl()572{573LRDP("uc0:enddl\n");574575if (rdp.pc_i == 0)576{577LRDP("RDP end\n");578579// Halt execution here580rdp.halt = 1;581}582583rdp.pc_i --;584}585586static void uc0_culldl()587{588wxUint8 vStart = (wxUint8)((rdp.cmd0 & 0x00FFFFFF) / 40) & 0xF;589wxUint8 vEnd = (wxUint8)(rdp.cmd1 / 40) & 0x0F;590wxUint32 cond = 0;591VERTEX *v;592593FRDP("uc0:culldl start: %d, end: %d\n", vStart, vEnd);594595if (vEnd < vStart) return;596for (wxUint16 i=vStart; i<=vEnd; i++)597{598v = &rdp.vtx[i];599// Check if completely off the screen (quick frustrum clipping for 90 FOV)600if (v->x >= -v->w)601cond |= 0x01;602if (v->x <= v->w)603cond |= 0x02;604if (v->y >= -v->w)605cond |= 0x04;606if (v->y <= v->w)607cond |= 0x08;608if (v->w >= 0.1f)609cond |= 0x10;610611if (cond == 0x1F)612return;613}614615LRDP(" - "); // specify that the enddl is not a real command616uc0_enddl ();617}618619static void uc0_popmatrix()620{621LRDP("uc0:popmatrix\n");622623wxUint32 param = rdp.cmd1;624625switch (param)626{627case 0: // modelview628modelview_pop ();629break;630631case 1: // projection, can't632break;633634default:635FRDP_E ("Unknown uc0:popmatrix command: 0x%08lx\n", param);636FRDP ("Unknown uc0:popmatrix command: 0x%08lx\n", param);637}638}639640static void uc6_obj_sprite ();641642static void uc0_modifyvtx(wxUint8 where, wxUint16 vtx, wxUint32 val)643{644VERTEX *v = &rdp.vtx[vtx];645646switch (where)647{648case 0:649uc6_obj_sprite ();650break;651652case 0x10: // RGBA653v->r = (wxUint8)(val >> 24);654v->g = (wxUint8)((val >> 16) & 0xFF);655v->b = (wxUint8)((val >> 8) & 0xFF);656v->a = (wxUint8)(val & 0xFF);657v->shade_mod = 0;658659FRDP ("RGBA: %d, %d, %d, %d\n", v->r, v->g, v->b, v->a);660break;661662case 0x14: // ST663{664float scale = rdp.Persp_en ? 0.03125f : 0.015625f;665v->ou = (float)((short)(val>>16)) * scale;666v->ov = (float)((short)(val&0xFFFF)) * scale;667v->uv_calculated = 0xFFFFFFFF;668v->uv_scaled = 1;669}670FRDP ("u/v: (%04lx, %04lx), (%f, %f)\n", (short)(val>>16), (short)(val&0xFFFF),671v->ou, v->ov);672break;673674case 0x18: // XY screen675{676float scr_x = (float)((short)(val>>16)) / 4.0f;677float scr_y = (float)((short)(val&0xFFFF)) / 4.0f;678v->screen_translated = 2;679v->sx = scr_x * rdp.scale_x + rdp.offset_x;680v->sy = scr_y * rdp.scale_y + rdp.offset_y;681if (v->w < 0.01f)682{683v->w = 1.0f;684v->oow = 1.0f;685v->z_w = 1.0f;686}687v->sz = rdp.view_trans[2] + v->z_w * rdp.view_scale[2];688689v->scr_off = 0;690if (scr_x < 0) v->scr_off |= 1;691if (scr_x > rdp.vi_width) v->scr_off |= 2;692if (scr_y < 0) v->scr_off |= 4;693if (scr_y > rdp.vi_height) v->scr_off |= 8;694if (v->w < 0.1f) v->scr_off |= 16;695696FRDP ("x/y: (%f, %f)\n", scr_x, scr_y);697}698break;699700case 0x1C: // Z screen701{702float scr_z = (float)((short)(val>>16));703v->z_w = (scr_z - rdp.view_trans[2]) / rdp.view_scale[2];704v->z = v->z_w * v->w;705FRDP ("z: %f\n", scr_z);706}707break;708709default:710LRDP("UNKNOWN\n");711break;712}713}714715//716// uc0:moveword - moves a word to someplace, like the segment pointers717//718static void uc0_moveword()719{720LRDP("uc0:moveword ");721722// Find which command this is (lowest byte of cmd0)723switch (rdp.cmd0 & 0xFF)724{725case 0x00:726RDP_E ("uc0:moveword matrix - IGNORED\n");727LRDP("matrix - IGNORED\n");728break;729730case 0x02:731rdp.num_lights = ((rdp.cmd1 - 0x80000000) >> 5) - 1; // inverse of equation732if (rdp.num_lights > 8) rdp.num_lights = 0;733734rdp.update |= UPDATE_LIGHTS;735FRDP ("numlights: %d\n", rdp.num_lights);736break;737738case 0x04:739if (((rdp.cmd0>>8)&0xFFFF) == 0x04)740{741rdp.clip_ratio = sqrt((float)rdp.cmd1);742rdp.update |= UPDATE_VIEWPORT;743}744FRDP ("clip %08lx, %08lx\n", rdp.cmd0, rdp.cmd1);745break;746747case 0x06: // segment748FRDP ("segment: %08lx -> seg%d\n", rdp.cmd1, (rdp.cmd0 >> 10) & 0x0F);749if ((rdp.cmd1&BMASK)<BMASK)750rdp.segment[(rdp.cmd0 >> 10) & 0x0F] = rdp.cmd1;751break;752753case 0x08:754{755rdp.fog_multiplier = (short)(rdp.cmd1 >> 16);756rdp.fog_offset = (short)(rdp.cmd1 & 0x0000FFFF);757FRDP ("fog: multiplier: %f, offset: %f\n", rdp.fog_multiplier, rdp.fog_offset);758}759break;760761case 0x0a: // moveword LIGHTCOL762{763int n = (rdp.cmd0&0xE000) >> 13;764FRDP ("lightcol light:%d, %08lx\n", n, rdp.cmd1);765766rdp.light[n].r = (float)((rdp.cmd1 >> 24) & 0xFF) / 255.0f;767rdp.light[n].g = (float)((rdp.cmd1 >> 16) & 0xFF) / 255.0f;768rdp.light[n].b = (float)((rdp.cmd1 >> 8) & 0xFF) / 255.0f;769rdp.light[n].a = 255;770}771break;772773case 0x0c:774{775wxUint16 val = (wxUint16)((rdp.cmd0 >> 8) & 0xFFFF);776wxUint16 vtx = val / 40;777wxUint8 where = val%40;778uc0_modifyvtx(where, vtx, rdp.cmd1);779FRDP ("uc0:modifyvtx: vtx: %d, where: 0x%02lx, val: %08lx - ", vtx, where, rdp.cmd1);780}781break;782783case 0x0e:784LRDP("perspnorm - IGNORED\n");785break;786787default:788FRDP_E ("uc0:moveword unknown (index: 0x%08lx)\n", rdp.cmd0 & 0xFF);789FRDP ("unknown (index: 0x%08lx)\n", rdp.cmd0 & 0xFF);790}791}792793static void uc0_texture()794{795int tile = (rdp.cmd0 >> 8) & 0x07;796if (tile == 7 && (settings.hacks&hack_Supercross)) tile = 0; //fix for supercross 2000797rdp.mipmap_level = (rdp.cmd0 >> 11) & 0x07;798wxUint32 on = (rdp.cmd0 & 0xFF);799rdp.cur_tile = tile;800801if (on)802{803wxUint16 s = (wxUint16)((rdp.cmd1 >> 16) & 0xFFFF);804wxUint16 t = (wxUint16)(rdp.cmd1 & 0xFFFF);805806TILE *tmp_tile = &rdp.tiles[tile];807tmp_tile->on = 1;808tmp_tile->org_s_scale = s;809tmp_tile->org_t_scale = t;810tmp_tile->s_scale = (float)(s+1)/65536.0f;811tmp_tile->t_scale = (float)(t+1)/65536.0f;812tmp_tile->s_scale /= 32.0f;813tmp_tile->t_scale /= 32.0f;814815rdp.update |= UPDATE_TEXTURE;816817FRDP("uc0:texture: tile: %d, mipmap_lvl: %d, on: %d, s_scale: %f, t_scale: %f\n",818tile, rdp.mipmap_level, on, tmp_tile->s_scale, tmp_tile->t_scale);819}820else821{822LRDP("uc0:texture skipped b/c of off\n");823rdp.tiles[tile].on = 0;824}825}826827828static void uc0_setothermode_h()829{830LRDP("uc0:setothermode_h: ");831832int shift, len;833if ((settings.ucode == ucode_F3DEX2) || (settings.ucode == ucode_CBFD))834{835len = (rdp.cmd0 & 0xFF) + 1;836shift = 32 - ((rdp.cmd0 >> 8) & 0xFF) - len;837}838else839{840shift = (rdp.cmd0 >> 8) & 0xFF;841len = rdp.cmd0 & 0xFF;842}843844wxUint32 mask = 0;845int i = len;846for (; i; i--)847mask = (mask << 1) | 1;848mask <<= shift;849850rdp.cmd1 &= mask;851rdp.othermode_h &= ~mask;852rdp.othermode_h |= rdp.cmd1;853854if (mask & 0x00000030) // alpha dither mode855{856rdp.alpha_dither_mode = (rdp.othermode_h >> 4) & 0x3;857FRDP ("alpha dither mode: %s\n", str_dither[rdp.alpha_dither_mode]);858}859860if (mask & 0x000000C0) // rgb dither mode861{862wxUint32 dither_mode = (rdp.othermode_h >> 6) & 0x3;863FRDP ("rgb dither mode: %s\n", str_dither[dither_mode]);864}865866if (mask & 0x00003000) // filter mode867{868rdp.filter_mode = (int)((rdp.othermode_h & 0x00003000) >> 12);869rdp.update |= UPDATE_TEXTURE;870FRDP ("filter mode: %s\n", str_filter[rdp.filter_mode]);871}872873if (mask & 0x0000C000) // tlut mode874{875rdp.tlut_mode = (wxUint8)((rdp.othermode_h & 0x0000C000) >> 14);876FRDP ("tlut mode: %s\n", str_tlut[rdp.tlut_mode]);877}878879if (mask & 0x00300000) // cycle type880{881rdp.cycle_mode = (wxUint8)((rdp.othermode_h & 0x00300000) >> 20);882rdp.update |= UPDATE_ZBUF_ENABLED;883FRDP ("cycletype: %d\n", rdp.cycle_mode);884}885886if (mask & 0x00010000) // LOD enable887{888rdp.LOD_en = (rdp.othermode_h & 0x00010000) ? TRUE : FALSE;889FRDP ("LOD_en: %d\n", rdp.LOD_en);890}891892if (mask & 0x00080000) // Persp enable893{894if (rdp.persp_supported)895rdp.Persp_en = (rdp.othermode_h & 0x00080000) ? TRUE : FALSE;896FRDP ("Persp_en: %d\n", rdp.Persp_en);897}898899wxUint32 unk = mask & 0x0FFC60F0F;900if (unk) // unknown portions, LARGE901{902FRDP ("UNKNOWN PORTIONS: shift: %d, len: %d, unknowns: %08lx\n", shift, len, unk);903}904}905906static void uc0_setothermode_l()907{908LRDP("uc0:setothermode_l ");909910int shift, len;911if ((settings.ucode == ucode_F3DEX2) || (settings.ucode == ucode_CBFD))912{913len = (rdp.cmd0 & 0xFF) + 1;914shift = 32 - ((rdp.cmd0 >> 8) & 0xFF) - len;915if (shift < 0) shift = 0;916}917else918{919len = rdp.cmd0 & 0xFF;920shift = (rdp.cmd0 >> 8) & 0xFF;921}922923wxUint32 mask = 0;924int i = len;925for (; i; i--)926mask = (mask << 1) | 1;927mask <<= shift;928929rdp.cmd1 &= mask;930rdp.othermode_l &= ~mask;931rdp.othermode_l |= rdp.cmd1;932933if (mask & 0x00000003) // alpha compare934{935rdp.acmp = rdp.othermode_l & 0x00000003;936FRDP ("alpha compare %s\n", ACmp[rdp.acmp]);937rdp.update |= UPDATE_ALPHA_COMPARE;938}939940if (mask & 0x00000004) // z-src selection941{942rdp.zsrc = (rdp.othermode_l & 0x00000004) >> 2;943FRDP ("z-src sel: %s\n", str_zs[rdp.zsrc]);944FRDP ("z-src sel: %08lx\n", rdp.zsrc);945rdp.update |= UPDATE_ZBUF_ENABLED;946}947948if (mask & 0xFFFFFFF8) // rendermode / blender bits949{950rdp.update |= UPDATE_FOG_ENABLED; //if blender has no fog bits, fog must be set off951rdp.render_mode_changed |= rdp.rm ^ rdp.othermode_l;952rdp.rm = rdp.othermode_l;953if (settings.flame_corona && (rdp.rm == 0x00504341)) //hack for flame's corona954rdp.othermode_l |= /*0x00000020 |*/ 0x00000010;955FRDP ("rendermode: %08lx\n", rdp.othermode_l); // just output whole othermode_l956}957958// there is not one setothermode_l that's not handled :)959}960961static void uc0_setgeometrymode()962{963rdp.geom_mode |= rdp.cmd1;964FRDP("uc0:setgeometrymode %08lx; result: %08lx\n", rdp.cmd1, rdp.geom_mode);965966if (rdp.cmd1 & 0x00000001) // Z-Buffer enable967{968if (!(rdp.flags & ZBUF_ENABLED))969{970rdp.flags |= ZBUF_ENABLED;971rdp.update |= UPDATE_ZBUF_ENABLED;972}973}974if (rdp.cmd1 & 0x00001000) // Front culling975{976if (!(rdp.flags & CULL_FRONT))977{978rdp.flags |= CULL_FRONT;979rdp.update |= UPDATE_CULL_MODE;980}981}982if (rdp.cmd1 & 0x00002000) // Back culling983{984if (!(rdp.flags & CULL_BACK))985{986rdp.flags |= CULL_BACK;987rdp.update |= UPDATE_CULL_MODE;988}989}990991//Added by Gonetz992if (rdp.cmd1 & 0x00010000) // Fog enable993{994if (!(rdp.flags & FOG_ENABLED))995{996rdp.flags |= FOG_ENABLED;997rdp.update |= UPDATE_FOG_ENABLED;998}999}1000}10011002static void uc0_cleargeometrymode()1003{1004FRDP("uc0:cleargeometrymode %08lx\n", rdp.cmd1);10051006rdp.geom_mode &= (~rdp.cmd1);10071008if (rdp.cmd1 & 0x00000001) // Z-Buffer enable1009{1010if (rdp.flags & ZBUF_ENABLED)1011{1012rdp.flags ^= ZBUF_ENABLED;1013rdp.update |= UPDATE_ZBUF_ENABLED;1014}1015}1016if (rdp.cmd1 & 0x00001000) // Front culling1017{1018if (rdp.flags & CULL_FRONT)1019{1020rdp.flags ^= CULL_FRONT;1021rdp.update |= UPDATE_CULL_MODE;1022}1023}1024if (rdp.cmd1 & 0x00002000) // Back culling1025{1026if (rdp.flags & CULL_BACK)1027{1028rdp.flags ^= CULL_BACK;1029rdp.update |= UPDATE_CULL_MODE;1030}1031}10321033//Added by Gonetz1034if (rdp.cmd1 & 0x00010000) // Fog enable1035{1036if (rdp.flags & FOG_ENABLED)1037{1038rdp.flags ^= FOG_ENABLED;1039rdp.update |= UPDATE_FOG_ENABLED;1040}1041}1042}10431044static void uc0_line3d()1045{1046wxUint32 v0 = ((rdp.cmd1 >> 16) & 0xff) / 10;1047wxUint32 v1 = ((rdp.cmd1 >> 8) & 0xff) / 10;1048wxUint16 width = (wxUint16)(rdp.cmd1 & 0xFF) + 3;10491050VERTEX *v[3] = {1051&rdp.vtx[v1],1052&rdp.vtx[v0],1053&rdp.vtx[v0]1054};1055wxUint32 cull_mode = (rdp.flags & CULLMASK) >> CULLSHIFT;1056rdp.flags |= CULLMASK;1057rdp.update |= UPDATE_CULL_MODE;1058rsp_tri1(v, width);1059rdp.flags ^= CULLMASK;1060rdp.flags |= cull_mode << CULLSHIFT;1061rdp.update |= UPDATE_CULL_MODE;10621063FRDP("uc0:line3d v0:%d, v1:%d, width:%d\n", v0, v1, width);1064}10651066static void uc0_tri4 ()1067{1068// c0: 0000 0123, c1: 456789ab1069// becomes: 405 617 829 a3b10701071LRDP("uc0:tri4");1072FRDP(" #%d, #%d, #%d, #%d - %d, %d, %d - %d, %d, %d - %d, %d, %d - %d, %d, %d\n", rdp.tri_n, rdp.tri_n+1, rdp.tri_n+2, rdp.tri_n+3,1073(rdp.cmd1 >> 28) & 0xF,1074(rdp.cmd0 >> 12) & 0xF,1075(rdp.cmd1 >> 24) & 0xF,1076(rdp.cmd1 >> 20) & 0xF,1077(rdp.cmd0 >> 8) & 0xF,1078(rdp.cmd1 >> 16) & 0xF,1079(rdp.cmd1 >> 12) & 0xF,1080(rdp.cmd0 >> 4) & 0xF,1081(rdp.cmd1 >> 8) & 0xF,1082(rdp.cmd1 >> 4) & 0xF,1083(rdp.cmd0 >> 0) & 0xF,1084(rdp.cmd1 >> 0) & 0xF);10851086VERTEX *v[12] = {1087&rdp.vtx[(rdp.cmd1 >> 28) & 0xF],1088&rdp.vtx[(rdp.cmd0 >> 12) & 0xF],1089&rdp.vtx[(rdp.cmd1 >> 24) & 0xF],1090&rdp.vtx[(rdp.cmd1 >> 20) & 0xF],1091&rdp.vtx[(rdp.cmd0 >> 8) & 0xF],1092&rdp.vtx[(rdp.cmd1 >> 16) & 0xF],1093&rdp.vtx[(rdp.cmd1 >> 12) & 0xF],1094&rdp.vtx[(rdp.cmd0 >> 4) & 0xF],1095&rdp.vtx[(rdp.cmd1 >> 8) & 0xF],1096&rdp.vtx[(rdp.cmd1 >> 4) & 0xF],1097&rdp.vtx[(rdp.cmd0 >> 0) & 0xF],1098&rdp.vtx[(rdp.cmd1 >> 0) & 0xF],1099};11001101int updated = 0;11021103if (cull_tri(v))1104rdp.tri_n ++;1105else1106{1107updated = 1;1108update ();11091110draw_tri (v);1111rdp.tri_n ++;1112}11131114if (cull_tri(v+3))1115rdp.tri_n ++;1116else1117{1118if (!updated)1119{1120updated = 1;1121update ();1122}11231124draw_tri (v+3);1125rdp.tri_n ++;1126}11271128if (cull_tri(v+6))1129rdp.tri_n ++;1130else1131{1132if (!updated)1133{1134updated = 1;1135update ();1136}11371138draw_tri (v+6);1139rdp.tri_n ++;1140}11411142if (cull_tri(v+9))1143rdp.tri_n ++;1144else1145{1146if (!updated)1147{1148updated = 1;1149update ();1150}11511152draw_tri (v+9);1153rdp.tri_n ++;1154}1155}115611571158