Path: blob/master/libmupen64plus/mupen64plus-video-glide64/src/rdp.cpp
2 views
/*1* Glide64 - Glide video plugin for Nintendo 64 emulators.2* Copyright (c) 2002 Dave20013* Copyright (c) 2008 Günther <[email protected]>4*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 Public16* Licence along with this program; if not, write to the Free17* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,18* Boston, MA 02110-1301, USA19*/2021//****************************************************************22//23// Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)24// Project started on December 29th, 200125//26// To modify Glide64:27// * 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.28// * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all.29//30// Official Glide64 development channel: #Glide64 on EFnet31//32// Original author: Dave2001 ([email protected])33// Other authors: Gonetz, Gugaman34//35//****************************************************************3637#define M64P_PLUGIN_PROTOTYPES 138#include "m64p_types.h"39#include "m64p_plugin.h"40#include "m64p_config.h"41#include "m64p_vidext.h"42#include "3dmath.h"43#include "Util.h"44#include "Debugger.h"45#include "Combine.h"46#include "Util.h"47#include "Ini.h"48#include "Config.h"49#include "Tmem.h"50#include "TexCache.h"51#include "TexCache.h"52#include "TexBuffer.h"53#include "CRC.h"54#include "rdp.h"5556#ifndef _WIN3257#include <sys/time.h>58#endif // _WIN325960char out_buf[2048];6162DWORD frame_count; // frame counter6364BOOL ucode_error_report = TRUE;65int wrong_tile = -1;6667int drawFlag = 1; // draw flag for rendering callback6869#if defined(__GNUC__)70#define bswap32(x) __builtin_bswap32(x)71#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))72#include <stdlib.h>73#define bswap32(x) _byteswap_ulong(x)74#else75static inline uint32_t bswap32(uint32_t val)76{77return (((val & 0xff000000) >> 24) |78((val & 0x00ff0000) >> 8) |79((val & 0x0000ff00) << 8) |80((val & 0x000000ff) << 24));81}82#endif8384// global strings85const char *ACmp[4] = { "NONE", "THRESHOLD", "UNKNOWN", "DITHER" };8687const char *Mode0[16] = { "COMBINED", "TEXEL0",88"TEXEL1", "PRIMITIVE",89"SHADE", "ENVIORNMENT",90"1", "NOISE",91"0", "0",92"0", "0",93"0", "0",94"0", "0" };95const char *Mode1[16] = { "COMBINED", "TEXEL0",96"TEXEL1", "PRIMITIVE",97"SHADE", "ENVIORNMENT",98"CENTER", "K4",99"0", "0",100"0", "0",101"0", "0",102"0", "0" };103const char *Mode2[32] = { "COMBINED", "TEXEL0",104"TEXEL1", "PRIMITIVE",105"SHADE", "ENVIORNMENT",106"SCALE", "COMBINED_ALPHA",107"T0_ALPHA", "T1_ALPHA",108"PRIM_ALPHA", "SHADE_ALPHA",109"ENV_ALPHA", "LOD_FRACTION",110"PRIM_LODFRAC", "K5",111"0", "0",112"0", "0",113"0", "0",114"0", "0",115"0", "0",116"0", "0",117"0", "0",118"0", "0" };119const char *Mode3[8] = { "COMBINED", "TEXEL0",120"TEXEL1", "PRIMITIVE",121"SHADE", "ENVIORNMENT",122"1", "0" };123124const char *Alpha0[8] = { "COMBINED", "TEXEL0",125"TEXEL1", "PRIMITIVE",126"SHADE", "ENVIORNMENT",127"1", "0" };128const char *Alpha2[8] = { "LOD_FRACTION", "TEXEL0",129"TEXEL1", "PRIMITIVE",130"SHADE", "ENVIORNMENT",131"PRIM_LODFRAC", "0" };132133//FIXME:unused?134//const char *FBLa[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG" };135//const char *FBLb[] = { "G_BL_A_IN", "G_BL_A_FOG", "G_BL_A_SHADE", "G_BL_0" };136//const char *FBLc[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG"};137//const char *FBLd[] = { "G_BL_1MA", "G_BL_A_MEM", "G_BL_1", "G_BL_0" };138139const char *str_zs[2] = { "G_ZS_PIXEL", "G_ZS_PRIM" };140141const char *str_yn[2] = { "NO", "YES" };142const char *str_offon[2] = { "OFF", "ON" };143144const char *str_cull[4] = { "DISABLE", "FRONT", "BACK", "BOTH" };145146// I=intensity probably147const char *str_format[8] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" };148const char *str_size[4] = { "4bit", "8bit", "16bit", "32bit" };149const char *str_cm[4] = { "WRAP/NO CLAMP", "MIRROR/NO CLAMP", "WRAP/CLAMP", "MIRROR/CLAMP" };150151//const char *str_lod[] = { "1", "2", "4", "8", "16", "32", "64", "128", "256" };152//const char *str_aspect[] = { "1x8", "1x4", "1x2", "1x1", "2x1", "4x1", "8x1" };153154const char *str_filter[3] = { "Point Sampled", "Average (box)", "Bilinear" };155156const char *str_tlut[4] = { "TT_NONE", "TT_UNKNOWN", "TT_RGBA_16", "TT_IA_16" };157158const char *CIStatus[10] = { "ci_main", "ci_zimg", "ci_unknown", "ci_useless",159"ci_old_copy", "ci_copy", "ci_copy_self",160"ci_zcopy", "ci_aux", "ci_aux_copy" };161162typedef struct163{164int ucode;165int crc;166} UcodeData;167168static UcodeData UcodeList[] =169{170{0, 0x006bd77f},171{2, 0x03044b84},172{2, 0x030f4b84},173{1, 0x05165579},174{1, 0x05777c62},175{1, 0x057e7c62},176{1, 0x07200895},177{2, 0x0bf36d36},178{-1, 0x0d7bbffb},179{5, 0x0d7cbffb},180{2, 0x0ff79527},181{-1, 0x0ff795bf},182{1, 0x1118b3e0},183{2, 0x168e9cd5},184{2, 0x1a1e18a0},185{2, 0x1a1e1920},186{2, 0x1a62dbaf},187{2, 0x1a62dc2f},188{1, 0x1de712ff},189{6, 0x1ea9e30f},190{2, 0x21f91834},191{2, 0x21f91874},192{2, 0x22099872},193{1, 0x24cd885b},194{1, 0x26a7879a},195{6, 0x299d5072},196{2, 0x2b291027},197{6, 0x2b5a89c2},198{1, 0x2c7975d6},199{2, 0x2f71d1d5},200{2, 0x2f7dd1d5},201{1, 0x327b933d},202{1, 0x339872a6},203{2, 0x377359b6},204{0, 0x3a1c2b34},205{0, 0x3a1cbac3},206{0, 0x3f7247fb},207{1, 0x3ff1a4ca},208{0, 0x4165e1fd},209{1, 0x4340ac9b},210{1, 0x440cfad6},211{7, 0x47d46e86},212{2, 0x485abff2},213{1, 0x4fe6df78},214{0, 0x5182f610},215{1, 0x5257cd2a},216{1, 0x5414030c},217{1, 0x5414030d},218{1, 0x559ff7d4},219{4, 0x5b5d36e3},220{3, 0x5b5d3763},221{0, 0x5d1d6f53},222{2, 0x5d3099f1},223{1, 0x5df1408c},224{1, 0x5ef4e34a},225{1, 0x6075e9eb},226{1, 0x60c1dcc4},227{2, 0x6124a508},228{2, 0x630a61fb},229{5, 0x63be08b1},230{5, 0x63be08b3},231{1, 0x64ed27e5},232{2, 0x65201989},233{2, 0x65201a09},234{1, 0x66c0b10a},235{2, 0x679e1205},236{6, 0x6bb745c9},237{2, 0x6d8f8f8a},238{0, 0x6e4d50af},239{1, 0x6eaa1da8},240{1, 0x72a4f34e},241{1, 0x73999a23},242{6, 0x74af0a74},243{2, 0x753be4a5},244{6, 0x794c3e28},245{1, 0x7df75834},246{1, 0x7f2d0a2e},247{1, 0x82f48073},248{1, 0x841ce10f},249{-1, 0x844b55b5},250{1, 0x863e1ca7},251{-1, 0x86b1593e},252{1, 0x8805ffea},253{1, 0x8d5735b2},254{1, 0x8d5735b3},255{-1, 0x8ec3e124},256{2, 0x93d11f7b},257{2, 0x93d11ffb},258{2, 0x93d1ff7b},259{2, 0x9551177b},260{2, 0x955117fb},261{2, 0x95cd0062},262{1, 0x97d1b58a},263{2, 0xa2d0f88e},264{1, 0xa346a5cc},265{2, 0xaa86cb1d},266{2, 0xaae4a5b9},267{2, 0xad0a6292},268{2, 0xad0a6312},269{0, 0xae08d5b9},270{1, 0xb1821ed3},271{1, 0xb4577b9c},272{0, 0xb54e7f93},273{2, 0xb62f900f},274{2, 0xba65ea1e},275{8, 0xba86cb1d},276{0, 0xbc03e969},277{2, 0xbc45382e},278{1, 0xbe78677c},279{1, 0xbed8b069},280{1, 0xc3704e41},281{1, 0xc46dbc3d},282{1, 0xc99a4c6c},283{2, 0xc901ce73},284{2, 0xc901cef3},285{2, 0xcb8c9b6c},286{1, 0xcee7920f},287{2, 0xcfa35a45},288{1, 0xd1663234},289{6, 0xd20dedbf},290{1, 0xd2a9f59c},291{1, 0xd41db5f7},292{0, 0xd5604971},293{1, 0xd57049a5},294{-1, 0xd5c4dc96},295{0, 0xd5d68b1f},296{1, 0xd802ec04},297{2, 0xda13ab96},298{2, 0xde7d67d4},299{2, 0xe1290fa2},300{0, 0xe41ec47e},301{2, 0xe65cb4ad},302{1, 0xe89c2b92},303{1, 0xe9231df2},304{1, 0xec040469},305{1, 0xee47381b},306{1, 0xef54ee35},307{-1, 0xf9893f70},308{1, 0xfb816260},309{-1, 0xff372492}310};311312// ZIGGY313// depth save/restore variables314// 0 : normal mode315// 1 : writing in normal depth buffer316// 2 : writing in alternate depth buffer317static int render_depth_mode;318319// ** RDP graphics functions **320static void undef();321static void spnoop();322323static void rdp_noop();324static void rdp_texrect();325//static void rdp_texrectflip();326static void rdp_loadsync();327static void rdp_pipesync();328static void rdp_tilesync();329static void rdp_fullsync();330static void rdp_setkeygb();331static void rdp_setkeyr();332static void rdp_setconvert();333static void rdp_setscissor();334static void rdp_setprimdepth();335static void rdp_setothermode();336static void rdp_loadtlut();337static void rdp_settilesize();338static void rdp_loadblock();339static void rdp_loadtile();340static void rdp_settile();341static void rdp_fillrect();342static void rdp_setfillcolor();343static void rdp_setfogcolor();344static void rdp_setblendcolor();345static void rdp_setprimcolor();346static void rdp_setenvcolor();347static void rdp_setcombine();348static void rdp_settextureimage();349static void rdp_setdepthimage();350static void rdp_setcolorimage();351static void rdp_trifill();352static void rdp_trishade();353static void rdp_tritxtr();354static void rdp_trishadetxtr();355static void rdp_trifillz();356static void rdp_trishadez();357static void rdp_tritxtrz();358static void rdp_trishadetxtrz();359360static void rsp_reserved0();361static void rsp_reserved1();362static void rsp_reserved2();363static void rsp_reserved3();364365static void ys_memrect();366367BYTE microcode[4096];368DWORD uc_crc;369void microcheck ();370371// ** UCODE FUNCTIONS **372#include "Ucode00.h"373#include "ucode01.h"374#include "ucode02.h"375#include "ucode03.h"376#include "ucode04.h"377#include "ucode05.h"378#include "ucode06.h"379#include "ucode07.h"380#include "ucode08.h"381#include "ucode.h"382383static BOOL reset = 0;384static int old_ucode = -1;385386// rdp_reset - resets the RDP_E387void rdp_reset ()388{389reset = 1;390391rdp.model_i = 0;392393rdp.n_cached[0] = 0;394rdp.n_cached[1] = 0;395rdp.cur_cache[0] = NULL;396rdp.cur_cache[1] = NULL;397/*398rdp.tmem_ptr[0] = offset_textures;399rdp.tmem_ptr[1] = offset_textures;400if (grTextureBufferExt)401rdp.tmem_ptr[1] = TEXMEM_2MB_EDGE * 2;402*/403rdp.c_a0 = 0;404rdp.c_b0 = 0;405rdp.c_c0 = 0;406rdp.c_d0 = 0;407rdp.c_Aa0 = 0;408rdp.c_Ab0 = 0;409rdp.c_Ac0 = 0;410rdp.c_Ad0 = 0;411412rdp.c_a1 = 0;413rdp.c_b1 = 0;414rdp.c_c1 = 0;415rdp.c_d1 = 0;416rdp.c_Aa1 = 0;417rdp.c_Ab1 = 0;418rdp.c_Ac1 = 0;419rdp.c_Ad1 = 0;420421// Clear the palette CRC422int i;423for (i=0; i<16; i++)424rdp.pal_8_crc[i] = 0;425426// Clear the palettes427for (i=0; i<256; i++)428rdp.pal_8[i] = 0;429430rdp.tlut_mode = 0;431432// Clear all segments ** VERY IMPORTANT FOR ZELDA **433for (i=0; i<16; i++)434rdp.segment[i] = 0;435436for (i=0; i<512; i++)437rdp.addr[i] = 0;438439// set all vertex numbers440for (i=0; i<MAX_VTX; i++)441rdp.vtx[i].number = i;442443rdp.scissor_o.ul_x = 0;444rdp.scissor_o.ul_y = 0;445rdp.scissor_o.lr_x = 320;446rdp.scissor_o.lr_y = 240;447rdp.num_lights = 0;448rdp.lookat[0][0] = rdp.lookat[1][1] = 1.0f;449rdp.lookat[0][1] = rdp.lookat[0][2] = rdp.lookat[1][0] = rdp.lookat[1][2] = 0.0f;450rdp.texrecting = 0;451rdp.rm = 0;452rdp.render_mode_changed = 0;453rdp.othermode_h = 0;454rdp.othermode_l = 0;455456rdp.tex_ctr = 0;457458rdp.tex = 0;459460rdp.cimg = 0;461rdp.ocimg = 0;462rdp.zimg = 0;463rdp.ci_width = 0;464rdp.cycle_mode = 2;465466rdp.allow_combine = 1;467468rdp.fog_coord_enabled = FALSE;469rdp.skip_drawing = FALSE;470471memset(rdp.frame_buffers, 0, sizeof(rdp.frame_buffers));472rdp.main_ci_index = 0;473rdp.maincimg[0].addr = rdp.maincimg[1].addr = rdp.last_drawn_ci_addr = 0x7FFFFFFF;474rdp.read_previous_ci = FALSE;475rdp.yuv_ul_x = rdp.yuv_ul_y = rdp.yuv_lr_x = rdp.yuv_lr_y = 0;476rdp.yuv_im_begin = 0x00FFFFFF;477rdp.yuv_image = FALSE;478rdp.cur_tex_buf = 0;479rdp.acc_tex_buf = 0;480rdp.cur_image = 0;481rdp.hires_tex = 0;482483hotkey_info.fb_always = 0;484hotkey_info.fb_motionblur = (settings.buff_clear == 0)?0:60;485hotkey_info.filtering = hotkey_info.fb_motionblur;486hotkey_info.corona = hotkey_info.fb_motionblur;487#ifdef _WIN32488GetAsyncKeyState (VK_BACK);489GetAsyncKeyState(0x42);490GetAsyncKeyState(0x56);491GetAsyncKeyState(0x43);492#endif // _WIN32493for (i = 0; i < num_tmu; i++)494rdp.texbufs[i].count = 0;495rdp.vi_org_reg = *gfx.VI_ORIGIN_REG;496rdp.view_scale[0] = 160.0f * rdp.scale_x;497rdp.view_scale[1] = -120.0f * rdp.scale_y;498rdp.view_trans[0] = 160.0f * rdp.scale_x;499rdp.view_trans[1] = 120.0f * rdp.scale_y;500rdp.view_scale[2] = 32.0f * 511.0f;501rdp.view_trans[2] = 32.0f * 511.0f;502}503504# define PCEndian505# ifdef PCEndian506# define ByteEndian(address) (address^3)507# define WordEndian(address) (address^2)508# endif509# define _Read8Endian(array, address) (*((BYTE *)(array+ByteEndian(address))))510__inline static DWORD searchrdram(const char *ct)511{512DWORD pos, pos2;513const char *t;514t = ct;515for (pos=0; pos<0x400000; pos++) {516for (pos2=pos, t=ct; *ct != 0; t++, pos2++) {517if (_Read8Endian(gfx.RDRAM, pos2) != *t)518break;519else520if (*(t + 1) == 0)521return pos;522}523}524return 0;525}526527int LookupUcode (int crc)528{529for (int i = 0; i < sizeof(UcodeList)/sizeof(UcodeData); i++)530{531if (crc == UcodeList[i].crc)532{533return UcodeList[i].ucode;534}535}536537return -2;538}539540void microcheck ()541{542DWORD i;543uc_crc = 0;544545// Check first 3k of ucode, because the last 1k sometimes contains trash546for (i=0; i<3072>>2; i++)547{548uc_crc += ((DWORD*)microcode)[i];549}550551FRDP_E ("crc: %08lx\n", uc_crc);552553#ifdef LOG_UCODE554std::ofstream ucf;555ucf.open ("ucode.txt", ios::out | ios::binary);556char d;557for (i=0; i<0x400000; i++)558{559d = ((char*)gfx.RDRAM)[i^3];560ucf.write (&d, 1);561}562ucf.close ();563#endif564565char str[9];566sprintf (str, "%08lx", (unsigned long)uc_crc);567568FRDP("ucode = %s\n", str);569int uc = LookupUcode(uc_crc);570WriteLog(M64MSG_INFO, "ucode = %d\n", uc);571if (uc == -2 && ucode_error_report)572{573Config_Open();574settings.ucode = Config_ReadInt ("ucode", "Force microcode", 0, FALSE, FALSE);575576ReleaseGfx ();577WriteLog(M64MSG_ERROR, "Error: uCode crc not found in INI, using currently selected uCode\n\n%08lx", (unsigned long)uc_crc);578579ucode_error_report = FALSE; // don't report any more ucode errors from this game580}581else if (uc == -1 && ucode_error_report)582{583Config_Open();584settings.ucode = Config_ReadInt ("ucode", "Force microcode", 0, FALSE, FALSE);585586ReleaseGfx ();587WriteLog(M64MSG_ERROR, "Error: Unsupported uCode!\n\ncrc: %08lx", (unsigned long)uc_crc);588589ucode_error_report = FALSE; // don't report any more ucode errors from this game590}591else592{593old_ucode = settings.ucode;594settings.ucode = uc;595FRDP("microcheck: old ucode: %d, new ucode: %d\n", old_ucode, uc);596}597}598599void drawNoFullscreenMessage()600{601LOG ("drawNoFullscreenMessage ()\n");602}603604static WORD yuv_to_rgb(BYTE y, BYTE u, BYTE v)605{606float r = y + (1.370705f * (v-128));607float g = y - (0.698001f * (v-128)) - (0.337633f * (u-128));608float b = y + (1.732446f * (u-128));609r *= 0.125f;610g *= 0.125f;611b *= 0.125f;612//clipping the result613if (r > 32) r = 32;614if (g > 32) g = 32;615if (b > 32) b = 32;616if (r < 0) r = 0;617if (g < 0) g = 0;618if (b < 0) b = 0;619620WORD c = (WORD)(((WORD)(r) << 11) |621((WORD)(g) << 6) |622((WORD)(b) << 1) | 1);623return c;624}625626static void DrawYUVImageToFrameBuffer()627{628WORD width = (WORD)(rdp.yuv_lr_x - rdp.yuv_ul_x);629WORD height = (WORD)(rdp.yuv_lr_y - rdp.yuv_ul_y);630DWORD * mb = (DWORD*)(gfx.RDRAM+rdp.yuv_im_begin); //pointer to the first macro block631WORD * cimg = (WORD*)(gfx.RDRAM+rdp.cimg);632//yuv macro block contains 16x16 texture. we need to put it in the proper place inside cimg633for (WORD y = 0; y < height; y+=16)634{635for (WORD x = 0; x < width; x+=16)636{637WORD *dst = cimg + x + y * rdp.ci_width;638for (WORD h = 0; h < 16; h++)639{640for (WORD w = 0; w < 8; w++)641{642DWORD t = *(mb++); //each DWORD contains 2 pixels643if ((x < rdp.ci_width) && (y < rdp.ci_height)) //clipping. texture image may be larger than color image644{645BYTE y0 = (BYTE)t&0xFF;646BYTE v = (BYTE)(t>>8)&0xFF;647BYTE y1 = (BYTE)(t>>16)&0xFF;648BYTE u = (BYTE)(t>>24)&0xFF;649*(dst++) = yuv_to_rgb(y0, u, v);650*(dst++) = yuv_to_rgb(y1, u, v);651}652}653dst += rdp.ci_width - 16;654}655mb += 64; //macro block is 768 bytes long, last 256 bytes are useless656}657}658}659660static DWORD d_ul_x, d_ul_y, d_lr_x, d_lr_y;661662typedef struct {663int ul_x, ul_y, lr_x, lr_y;664} FB_PART;665666static void DrawPart(int scr_ul_x, int scr_ul_y, int prt_ul_x, int prt_ul_y, int width, int height, float scale_x, float scale_y)667{668WORD * dst = new WORD[width*height];669DWORD shift = ((d_ul_y+prt_ul_y) * rdp.ci_width + d_ul_x + prt_ul_x) << 1;670WORD * src = (WORD*)(gfx.RDRAM+rdp.cimg+shift);671WORD c;672for (int y=0; y < height; y++)673{674for (int x=0; x < width; x++)675{676c = src[(int(x*scale_x)+int(y*scale_y)*rdp.ci_width)^1];677dst[x+y*width] = c?((c >> 1) | 0x8000):0;678}679}680681grLfbWriteRegion(GR_BUFFER_BACKBUFFER,682scr_ul_x,683scr_ul_y,684GR_LFB_SRC_FMT_1555,685width,686height,687FXTRUE,688width<<1,689dst);690delete[] dst;691}692693static void DrawFrameBufferToScreen()694{695FRDP("DrawFrameBufferToScreen. cimg: %08lx, ul_x: %d, uly: %d, lr_x: %d, lr_y: %d\n", rdp.cimg, d_ul_x, d_ul_y, d_lr_x, d_lr_y);696if (!fullscreen)697return;698grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,699GR_COMBINE_FACTOR_ONE,700GR_COMBINE_LOCAL_NONE,701GR_COMBINE_OTHER_TEXTURE,702FXFALSE);703grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,704GR_COMBINE_FACTOR_ONE,705GR_COMBINE_LOCAL_NONE,706GR_COMBINE_OTHER_TEXTURE,707FXFALSE);708grConstantColorValue (0xFFFFFFFF);709grAlphaBlendFunction( GR_BLEND_SRC_ALPHA,710GR_BLEND_ONE_MINUS_SRC_ALPHA,711GR_BLEND_ONE,712GR_BLEND_ZERO);713rdp.update |= UPDATE_COMBINE;714715float scale_x_dst = (float)settings.scr_res_x / rdp.vi_width;//(float)max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width);716float scale_y_dst = (float)settings.scr_res_y / rdp.vi_height;//(float)max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound);717float scale_x_src = (float)rdp.vi_width / (float)settings.scr_res_x;//(float)max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width);718float scale_y_src = (float)rdp.vi_height / (float)settings.scr_res_y;//(float)max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound);719int src_width = d_lr_x - d_ul_x + 1;720int src_height = d_lr_y - d_ul_y + 1;721int dst_width, dst_height, ul_x, ul_y;722723if (!settings.fb_optimize_write || ((src_width < 33) && (src_height < 33)))724{725dst_width = int(src_width*scale_x_dst);726dst_height = int(src_height*scale_y_dst);727ul_x = int(d_ul_x*scale_x_dst);728ul_y = int(d_ul_y*scale_y_dst);729DrawPart(ul_x, ul_y, 0, 0, dst_width, dst_height, scale_x_src, scale_y_src);730memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size);731return;732}733734FB_PART parts[8];735int p;736for (p = 0; p < 8; p++)737{738parts[p].lr_x = parts[p].lr_y = 0;739parts[p].ul_x = parts[p].ul_y = 0xFFFF;740}741742int num_of_parts = 0;743int cur_part = 0;744int most_left = d_ul_x;745int most_right = d_lr_x;746DWORD shift = (d_ul_y * rdp.ci_width + d_ul_x) << 1;747WORD * src = (WORD*)(gfx.RDRAM+rdp.cimg+shift);748for (int h = 0; h < src_height; h++)749{750cur_part = 0;751int w = 0;752while (w < src_width)753{754while (w < src_width)755{756if (src[(w+h*rdp.ci_width)^1] == 0)757w++;758else759break;760}761if (w == src_width)762break;763if (num_of_parts == 0) //first part764{765parts[0].ul_x = w;766most_left = w;767parts[0].ul_y = h;768cur_part = 0;769}770else if (w < most_left - 2) //new part771{772parts[num_of_parts].ul_x = w;773most_left = w;774parts[num_of_parts].ul_y = h;775cur_part = num_of_parts;776num_of_parts++;777}778else if (w > most_right + 2) //new part779{780parts[num_of_parts].ul_x = w;781most_right = w;782parts[num_of_parts].ul_y = h;783cur_part = num_of_parts;784num_of_parts++;785}786else787{788for (p = 0; p < num_of_parts; p++)789{790if ((w > parts[p].ul_x - 2) && (w < parts[p].lr_x+2))791{792if (w < parts[p].ul_x) parts[p].ul_x = w;793break;794}795}796cur_part = p;797}798while (w < src_width)799{800if (src[(w+h*rdp.ci_width)^1] != 0)801w++;802else803break;804}805if (num_of_parts == 0) //first part806{807parts[0].lr_x = w;808most_right = w;809num_of_parts++;810}811else812{813if (parts[cur_part].lr_x < w) parts[cur_part].lr_x = w;814if (most_right < w) most_right = w;815parts[cur_part].lr_y = h;816}817}818}819/*820for (p = 0; p < num_of_parts; p++)821{822FRDP("part#%d ul_x: %d, ul_y: %d, lr_x: %d, lr_y: %d\n", p, parts[p].ul_x, parts[p].ul_y, parts[p].lr_x, parts[p].lr_y);823}824*/825for (p = 0; p < num_of_parts; p++)826{827dst_width = int((parts[p].lr_x-parts[p].ul_x + 1)*scale_x_dst);828dst_height = int((parts[p].lr_y-parts[p].ul_y + 1)*scale_y_dst);829ul_x = int((d_ul_x+parts[p].ul_x)*scale_x_dst);830ul_y = int((d_ul_y+parts[p].ul_y)*scale_y_dst);831DrawPart(ul_x, ul_y, parts[p].ul_x, parts[p].ul_y, dst_width, dst_height, scale_x_src, scale_y_src);832}833memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size);834}835836#define RGBA16TO32(color) \837((color&1)?0xFF:0) | \838((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | \839((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | \840((DWORD)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8)841842static void CopyFrameBuffer (GrBuffer_t buffer = GR_BUFFER_BACKBUFFER)843{844if (!fullscreen)845return;846FRDP ("CopyFrameBuffer: %08lx... ", rdp.cimg);847848// don't bother to write the stuff in asm... the slow part is the read from video card,849// not the copy.850851int width = rdp.ci_width;//*gfx.VI_WIDTH_REG;852int height;853if (settings.fb_smart && !settings.PPL)854{855int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0;856height = rdp.frame_buffers[ind].height;857}858else859{860height = rdp.ci_lower_bound;861if (settings.PPL)862height -= rdp.ci_upper_bound;863}864FRDP ("width: %d, height: %d... ", width, height);865866if (rdp.scale_x < 1.1f)867{868WORD * ptr_src = new WORD[width*height];869if (grLfbReadRegion(buffer,8700,8710,//rdp.ci_upper_bound,872width,873height,874width<<1,875ptr_src))876{877WORD *ptr_dst = (WORD*)(gfx.RDRAM+rdp.cimg);878DWORD *ptr_dst32 = (DWORD*)(gfx.RDRAM+rdp.cimg);879WORD c;880881for (int y=0; y<height; y++)882{883for (int x=0; x<width; x++)884{885c = ptr_src[x + y * width];886if (settings.fb_read_alpha)887{888if (c > 0)889c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;890}891else892{893c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;894}895if (rdp.ci_size == 2)896ptr_dst[(x + y * width)^1] = c;897else898ptr_dst32[x + y * width] = RGBA16TO32(c);899}900}901/*902}903else //8bit I or CI904{905BYTE *ptr_dst = (BYTE*)(gfx.RDRAM+rdp.cimg);906WORD c;907908for (int y=0; y<height; y++)909{910for (int x=0; x<width; x++)911{912c = ptr_src[x + y * width];913BYTE b = (BYTE)((float)(c&0x1F)/31.0f*85.0f);914BYTE g = (BYTE)((float)((c>>5)&0x3F)/63.0f*85.0f);915BYTE r = (BYTE)((float)((c>>11)&0x1F)/31.0f*85.0f);916c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;917// FRDP("src: %08lx, dst: %d\n",c,(BYTE)(r+g+b));918ptr_dst[(x + y * width)^1] = (BYTE)(r+g+b);919// ptr_dst[(x + y * width)^1] = (BYTE)((c>>8)&0xFF);920}921}922} */923RDP ("ReadRegion. Framebuffer copy complete.\n");924}925else926{927RDP ("Framebuffer copy failed.\n");928}929delete[] ptr_src;930}931else932{933if (rdp.motionblur && settings.fb_hires)934{935return;936}937else938{939float scale_x = (float)settings.scr_res_x / rdp.vi_width;//(float)max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width);940float scale_y = (float)settings.scr_res_y / rdp.vi_height;//(float)max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound);941942FRDP("width: %d, height: %d, ul_y: %d, lr_y: %d, scale_x: %f, scale_y: %f, ci_width: %d, ci_height: %d\n",width, height, rdp.ci_upper_bound, rdp.ci_lower_bound, scale_x, scale_y, rdp.ci_width, rdp.ci_height);943GrLfbInfo_t info;944info.size = sizeof(GrLfbInfo_t);945946947// VP 888 disconnected for now948if (1||rdp.ci_size <= 2) {949if (grLfbLock (GR_LFB_READ_ONLY,950buffer,951GR_LFBWRITEMODE_565,952GR_ORIGIN_UPPER_LEFT,953FXFALSE,954&info))955{956WORD *ptr_src = (WORD*)info.lfbPtr;957WORD *ptr_dst = (WORD*)(gfx.RDRAM+rdp.cimg);958DWORD *ptr_dst32 = (DWORD*)(gfx.RDRAM+rdp.cimg);959WORD c;960DWORD stride = info.strideInBytes>>1;961962BOOL read_alpha = settings.fb_read_alpha;963if (settings.PM && rdp.frame_buffers[rdp.ci_count-1].status != ci_aux)964read_alpha = FALSE;965for (int y=0; y<height; y++)966{967for (int x=0; x<width; x++)968{969c = ptr_src[int(x*scale_x) + int(y * scale_y) * stride];970c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;971if (read_alpha && c == 1)972c = 0;973if (rdp.ci_size <= 2)974ptr_dst[(x + y * width)^1] = c;975else976ptr_dst32[x + y * width] = RGBA16TO32(c);977}978}979980// Unlock the backbuffer981grLfbUnlock (GR_LFB_READ_ONLY, buffer);982RDP ("LfbLock. Framebuffer copy complete.\n");983}984else985{986RDP ("Framebuffer copy failed.\n");987}988989} else {990991if (grLfbLock (GR_LFB_READ_ONLY,992buffer,993GR_LFBWRITEMODE_888,994GR_ORIGIN_UPPER_LEFT,995FXFALSE,996&info))997{998DWORD *ptr_src = (DWORD*)info.lfbPtr;999//FIXME: Why unused?1000//WORD *ptr_dst = (WORD*)(gfx.RDRAM+rdp.cimg);1001DWORD *ptr_dst32 = (DWORD*)(gfx.RDRAM+rdp.cimg);1002DWORD c;1003DWORD stride = info.strideInBytes>>1;10041005for (int y=0; y<height; y++)1006{1007for (int x=0; x<width; x++)1008{1009c = ptr_src[int(x*scale_x) + int(y * scale_y) * stride];1010ptr_dst32[x + y * width] = c;1011}1012}10131014// Unlock the backbuffer1015grLfbUnlock (GR_LFB_READ_ONLY, buffer);1016RDP ("LfbLock. Framebuffer copy complete.\n");1017}1018else1019{1020RDP ("Framebuffer copy failed.\n");1021}1022}1023}1024}1025}10261027/******************************************************************1028Function: ProcessDList1029Purpose: This function is called when there is a Dlist to be1030processed. (High level GFX list)1031input: none1032output: none1033*******************************************************************/1034void DetectFrameBufferUsage ();1035DWORD fbreads_front = 0;1036DWORD fbreads_back = 0;1037BOOL cpu_fb_read_called = FALSE;1038BOOL cpu_fb_write_called = FALSE;1039BOOL cpu_fb_write = FALSE;1040BOOL cpu_fb_ignore = FALSE;1041BOOL CI_SET = TRUE;10421043#ifdef __cplusplus1044extern "C" {1045#endif10461047EXPORT void CALL ProcessDList(void)1048{1049no_dlist = FALSE;1050update_screen_count = 0;1051ChangeSize ();10521053#ifdef ALTTAB_FIX1054if (!hhkLowLevelKybd)1055{1056hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL,1057LowLevelKeyboardProc, hInstance, 0);1058}1059#endif10601061LOG ("ProcessDList ()\n");10621063if (!fullscreen)1064{1065drawNoFullscreenMessage();1066// Set an interrupt to allow the game to continue1067*gfx.MI_INTR_REG |= 0x20;1068gfx.CheckInterrupts();1069}10701071if (reset)1072{1073reset = 0;10741075memset (microcode, 0, 4096);1076if (settings.autodetect_ucode)1077{1078// Thanks to ZeZu for ucode autodetection!!!10791080DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0);1081memcpy (microcode, gfx.RDRAM+startUcode, 4096);1082microcheck ();10831084}1085}1086else if ( ((old_ucode == 6) && (settings.ucode == 1)) || settings.force_microcheck)1087{1088DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0);1089memcpy (microcode, gfx.RDRAM+startUcode, 4096);1090microcheck ();1091}10921093if (exception) return;10941095// Switch to fullscreen?1096if (to_fullscreen)1097{1098to_fullscreen = FALSE;10991100if (!InitGfx (FALSE))1101{1102LOG ("FAILED!!!\n");1103return;1104}1105fullscreen = TRUE;1106}11071108// Clear out the RDP log1109#ifdef RDP_LOGGING1110if (settings.logging && settings.log_clear)1111{1112CLOSE_RDP_LOG ();1113OPEN_RDP_LOG ();1114}1115#endif11161117#ifdef UNIMP_LOG1118if (settings.log_unk && settings.unk_clear)1119{1120std::ofstream unimp;1121unimp.open("unimp.txt");1122unimp.close();1123}1124#endif11251126//* Set states *//1127if (settings.swapmode > 0)1128SwapOK = TRUE;1129rdp.updatescreen = 1;11301131rdp.tri_n = 0; // 0 triangles so far this frame1132rdp.debug_n = 0;11331134rdp.model_i = 0; // 0 matrices so far in stack1135//stack_size can be less then 32! Important for Silicon Vally. Thanks Orkin!1136rdp.model_stack_size = min(32, (*(DWORD*)(gfx.DMEM+0x0FE4))>>6);1137if (rdp.model_stack_size == 0)1138rdp.model_stack_size = 32;1139rdp.fb_drawn = rdp.fb_drawn_front = FALSE;1140rdp.update = 0x7FFFFFFF; // All but clear cache1141rdp.geom_mode = 0;1142rdp.acmp = 0;1143rdp.maincimg[1] = rdp.maincimg[0];1144rdp.skip_drawing = FALSE;1145rdp.s2dex_tex_loaded = FALSE;1146fbreads_front = fbreads_back = 0;1147rdp.fog_multiplier = rdp.fog_offset = 0;1148rdp.zsrc = 0;11491150if (cpu_fb_write == TRUE)1151DrawFrameBufferToScreen();1152cpu_fb_write = FALSE;1153cpu_fb_read_called = FALSE;1154cpu_fb_write_called = FALSE;1155cpu_fb_ignore = FALSE;1156d_ul_x = 0xffff;1157d_ul_y = 0xffff;1158d_lr_x = 0;1159d_lr_y = 0;11601161//analize possible frame buffer usage1162if (settings.fb_smart)1163DetectFrameBufferUsage();1164if (!settings.lego || rdp.num_of_ci > 1)1165rdp.last_bg = 0;1166//* End of set states *//116711681169// Get the start of the display list and the length of it1170DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0);1171DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4);1172FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_lenght: %d\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length);1173FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG);11741175if (settings.tonic && dlist_length < 16)1176{1177rdp_fullsync();1178FRDP_E("DLIST is too short!\n");1179return;1180}11811182// Start executing at the start of the display list1183rdp.pc_i = 0;1184rdp.pc[rdp.pc_i] = dlist_start;1185rdp.dl_count = -1;1186rdp.halt = 0;1187DWORD a;11881189// catches exceptions so that it doesn't freeze1190#ifdef CATCH_EXCEPTIONS1191try {1192#endif11931194// MAIN PROCESSING LOOP1195do {11961197// Get the address of the next command1198a = rdp.pc[rdp.pc_i] & BMASK;11991200// Load the next command and its input1201rdp.cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit1202rdp.cmd1 = ((DWORD*)gfx.RDRAM)[(a>>2)+1]; // /1203// cmd2 and cmd3 are filled only when needed, by the function that needs them12041205// Output the address before the command1206#ifdef LOG_COMMANDS1207FRDP ("%08lx (c0:%08lx, c1:%08lx): ", a, rdp.cmd0, rdp.cmd1);1208#else1209FRDP ("%08lx: ", a);1210#endif12111212// Go to the next instruction1213rdp.pc[rdp.pc_i] = (a+8) & BMASK;12141215#ifdef PERFORMANCE1216QueryPerformanceCounter ((LARGE_INTEGER*)&perf_cur);1217#endif1218// Process this instruction1219gfx_instruction[settings.ucode][rdp.cmd0>>24] ();12201221// check DL counter1222if (rdp.dl_count != -1)1223{1224rdp.dl_count --;1225if (rdp.dl_count == 0)1226{1227rdp.dl_count = -1;12281229RDP ("End of DL\n");1230rdp.pc_i --;1231}1232}12331234#ifdef PERFORMANCE1235QueryPerformanceCounter ((LARGE_INTEGER*)&perf_next);1236__int64 t = perf_next-perf_cur;1237sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, t);1238rdp_log << out_buf;1239#endif12401241} while (!rdp.halt);1242#ifdef CATCH_EXCEPTIONS1243} catch (...) {12441245if (fullscreen) ReleaseGfx ();1246WriteLog(M64MSG_ERROR, "The GFX plugin caused an exception and has been disabled.");1247exception = TRUE;1248}1249#endif12501251if (settings.fb_smart)1252{1253rdp.scale_x = rdp.scale_x_bak;1254rdp.scale_y = rdp.scale_y_bak;1255}1256if (settings.fb_read_always)1257{1258CopyFrameBuffer ();1259}1260if (rdp.yuv_image)1261{1262DrawYUVImageToFrameBuffer();1263rdp.yuv_image = FALSE;1264// FRDP("yuv image draw. ul_x: %f, ul_y: %f, lr_x: %f, lr_y: %f, begin: %08lx\n",1265// rdp.yuv_ul_x, rdp.yuv_ul_y, rdp.yuv_lr_x, rdp.yuv_lr_y, rdp.yuv_im_begin);1266rdp.yuv_ul_x = rdp.yuv_ul_y = rdp.yuv_lr_x = rdp.yuv_lr_y = 0;1267rdp.yuv_im_begin = 0x00FFFFFF;1268}1269if (rdp.cur_image)1270CloseTextureBuffer(rdp.read_whole_frame && (settings.PM || rdp.swap_ci_index >= 0));12711272if (settings.TGR2 && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET)1273{1274newSwapBuffers ();1275CI_SET = FALSE;1276}1277RDP("ProcessDList end\n");1278}12791280#ifdef __cplusplus1281}1282#endif12831284// undef - undefined instruction, always ignore1285static void undef()1286{1287FRDP_E("** undefined ** (%08lx)\n", rdp.cmd0);1288FRDP("** undefined ** (%08lx) - IGNORED\n", rdp.cmd0);1289#ifdef _FINAL_RELEASE_1290*gfx.MI_INTR_REG |= 0x20;1291gfx.CheckInterrupts();1292rdp.halt = 1;1293#endif1294}12951296// spnoop - no operation, always ignore1297static void spnoop()1298{1299RDP("spnoop\n");1300}13011302// noop - no operation, always ignore1303static void rdp_noop()1304{1305RDP("noop\n");1306}13071308static void ys_memrect ()1309{1310DWORD tile = (WORD)((rdp.cmd1 & 0x07000000) >> 24);13111312DWORD lr_x = (WORD)((rdp.cmd0 & 0x00FFF000) >> 14);1313DWORD lr_y = (WORD)((rdp.cmd0 & 0x00000FFF) >> 2);1314DWORD ul_x = (WORD)((rdp.cmd1 & 0x00FFF000) >> 14);1315DWORD ul_y = (WORD)((rdp.cmd1 & 0x00000FFF) >> 2);13161317rdp.pc[rdp.pc_i] += 16; // texrect is 196-bit13181319if (lr_y > rdp.scissor_o.lr_y) lr_y = rdp.scissor_o.lr_y;13201321FRDP ("memrect (%d, %d, %d, %d), ci_width: %d\n", ul_x, ul_y, lr_x, lr_y, rdp.ci_width);13221323DWORD y, width = lr_x - ul_x;1324DWORD texaddr = rdp.addr[rdp.tiles[tile].t_mem];1325DWORD tex_width = rdp.tiles[tile].line << 3;13261327for (y = ul_y; y < lr_y; y++) {1328BYTE *src = gfx.RDRAM + texaddr + (y - ul_y) * tex_width;1329BYTE *dst = gfx.RDRAM + rdp.cimg + ul_x + y * rdp.ci_width;1330memcpy (dst, src, width);1331}1332}13331334static void pm_palette_mod ()1335{1336BYTE envr = (BYTE)((float)((rdp.env_color >> 24)&0xFF)/255.0f*31.0f);1337BYTE envg = (BYTE)((float)((rdp.env_color >> 16)&0xFF)/255.0f*31.0f);1338BYTE envb = (BYTE)((float)((rdp.env_color >> 8)&0xFF)/255.0f*31.0f);1339WORD env16 = (WORD)((envr<<11)|(envg<<6)|(envb<<1)|1);1340BYTE prmr = (BYTE)((float)((rdp.prim_color >> 24)&0xFF)/255.0f*31.0f);1341BYTE prmg = (BYTE)((float)((rdp.prim_color >> 16)&0xFF)/255.0f*31.0f);1342BYTE prmb = (BYTE)((float)((rdp.prim_color >> 8)&0xFF)/255.0f*31.0f);1343WORD prim16 = (WORD)((prmr<<11)|(prmg<<6)|(prmb<<1)|1);1344WORD * dst = (WORD*)(gfx.RDRAM+rdp.cimg);1345for (int i = 0; i < 16; i++)1346{1347dst[i^1] = (rdp.pal_8[i]&1) ? prim16 : env16;1348}1349RDP("Texrect palette modification\n");1350}13511352static void rdp_texrect()1353{1354DWORD a = rdp.pc[rdp.pc_i];1355rdp.cmd2 = ((DWORD*)gfx.RDRAM)[(a>>2)+1];1356rdp.cmd3 = ((DWORD*)gfx.RDRAM)[(a>>2)+3];13571358if (settings.ASB) //modified Rice's hack for All-Star Baseball games1359{1360DWORD dwHalf1 = (((DWORD*)gfx.RDRAM)[(a>>2)+0]) >> 24;1361if ((dwHalf1 != 0xF1) && (dwHalf1 != 0xb3))1362{1363rdp.pc[rdp.pc_i] += 16;1364}1365else1366{1367rdp.pc[rdp.pc_i] += 8;1368rdp.cmd3 = rdp.cmd2;1369rdp.cmd2 = 0;1370}1371}1372else if (settings.yoshi && settings.ucode == 6)1373{1374ys_memrect();1375return;1376}1377else1378{1379rdp.pc[rdp.pc_i] += 16; // texrect is 196-bit1380}13811382if (rdp.skip_drawing || (!settings.fb_smart && (rdp.cimg == rdp.zimg)))1383{1384if (settings.PM && rdp.ci_status == ci_useless)1385{1386pm_palette_mod ();1387}1388else1389{1390RDP("Texrect skipped\n");1391}1392return;1393}13941395if ((settings.ucode == 8) && rdp.cur_image && rdp.cur_image->format)1396{1397//FRDP("Wrong Texrect. texaddr: %08lx, cimg: %08lx, cimg_end: %08lx\n", rdp.timg.addr, rdp.maincimg[1].addr, rdp.maincimg[1].addr+rdp.ci_width*rdp.ci_height*rdp.ci_size);1398RDP("Shadow texrect is skipped.\n");1399rdp.tri_n += 2;1400return;1401}14021403WORD ul_x = (WORD)((rdp.cmd1 & 0x00FFF000) >> 14);1404WORD ul_y = (WORD)((rdp.cmd1 & 0x00000FFF) >> 2);1405WORD lr_x = (WORD)((rdp.cmd0 & 0x00FFF000) >> 14);1406WORD lr_y = (WORD)((rdp.cmd0 & 0x00000FFF) >> 2);1407if (ul_x >= lr_x) return;1408if (rdp.cycle_mode > 1 || settings.increase_texrect_edge)1409{1410lr_x++;1411lr_y++;1412}1413if (ul_y == lr_y)1414{1415lr_y ++;1416}14171418//*1419if (rdp.hires_tex && settings.fb_optimize_texrect)1420{1421if (!rdp.hires_tex->drawn)1422{1423DRAWIMAGE d;1424d.imageX = 0;1425d.imageW = (WORD)rdp.hires_tex->width;1426d.frameX = ul_x;1427d.frameW = (WORD)(rdp.hires_tex->width);//(WORD)(ul_x + rdp.hires_tex->width);//lr_x;14281429d.imageY = 0;1430d.imageH = (WORD)rdp.hires_tex->height;1431d.frameY = ul_y;1432d.frameH = (WORD)(rdp.hires_tex->height);//(ul_y + rdp.hires_tex->height);1433FRDP("texrect. ul_x: %d, ul_y: %d, lr_x: %d, lr_y: %d, width: %d, height: %d\n", ul_x, ul_y, lr_x, lr_y, rdp.hires_tex->width, rdp.hires_tex->height);1434d.scaleX = 1.0f;1435d.scaleY = 1.0f;1436DrawHiresImage(&d, rdp.hires_tex->width == rdp.ci_width);1437rdp.hires_tex->drawn = TRUE;1438}1439return;1440}1441//*/1442// framebuffer workaround for Zelda: MM LOT1443if ((rdp.othermode_l & 0xFFFF0000) == 0x0f5a0000)1444return;14451446/*Gonetz*/1447//hack for Zelda MM. it removes black texrects which cover all geometry in "Link meets Zelda" cut scene1448if (settings.zelda && rdp.timg.addr >= rdp.cimg && rdp.timg.addr < rdp.ci_end)1449{1450FRDP("Wrong Texrect. texaddr: %08lx, cimg: %08lx, cimg_end: %08lx\n", rdp.cur_cache[0]->addr, rdp.cimg, rdp.cimg+rdp.ci_width*rdp.ci_height*2);1451rdp.tri_n += 2;1452return;1453}1454//*1455//hack for Banjo2. it removes black texrects under Banjo1456if (!settings.fb_hires && ((rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF)) == 0xFFFFFFFF && (rdp.othermode_l & 0xFFFF0000) == 0x00500000)1457{1458rdp.tri_n += 2;1459return;1460}1461//*/1462//*1463//remove motion blur in night vision1464if ((settings.ucode == 7) && (rdp.maincimg[1].addr != rdp.maincimg[0].addr) && (rdp.timg.addr >= rdp.maincimg[1].addr) && (rdp.timg.addr < (rdp.maincimg[1].addr+rdp.ci_width*rdp.ci_height*rdp.ci_size)))1465{1466if (settings.fb_smart)1467if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self || !settings.fb_motionblur)1468{1469// FRDP("Wrong Texrect. texaddr: %08lx, cimg: %08lx, cimg_end: %08lx\n", rdp.timg.addr, rdp.maincimg[1], rdp.maincimg[1]+rdp.ci_width*rdp.ci_height*rdp.ci_size);1470RDP("Wrong Texrect.\n");1471rdp.tri_n += 2;1472return;1473}1474}1475//*/14761477int i;14781479DWORD tile = (WORD)((rdp.cmd1 & 0x07000000) >> 24);14801481// update MUST be at the beginning, b/c of update_scissor1482if (rdp.cycle_mode == 2)1483{1484rdp.tex = 1;1485rdp.allow_combine = 0;14861487cmb.tmu1_func = cmb.tmu0_func = GR_COMBINE_FUNCTION_LOCAL;1488cmb.tmu1_fac = cmb.tmu0_fac = GR_COMBINE_FACTOR_NONE;1489cmb.tmu1_a_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_LOCAL;1490cmb.tmu1_a_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_NONE;1491cmb.tmu1_invert = cmb.tmu0_invert = FXFALSE;1492cmb.tmu1_a_invert = cmb.tmu0_a_invert = FXFALSE;1493}14941495rdp.texrecting = 1;14961497DWORD prev_tile = rdp.cur_tile;1498rdp.cur_tile = tile;1499rdp.update |= UPDATE_COMBINE;1500update ();15011502rdp.texrecting = 0;1503rdp.allow_combine = 1;15041505if (!rdp.cur_cache[0])1506{1507rdp.cur_tile = prev_tile;1508rdp.tri_n += 2;1509return;1510}1511// ****1512// ** Texrect offset by Gugaman **1513float off_x = (float)((short)((rdp.cmd2 & 0xFFFF0000) >> 16)) / 32.0f;1514if ((int(off_x) == 512) && (rdp.timg.width < 512)) off_x = 0.0f;1515float off_y = (float)((short)(rdp.cmd2 & 0x0000FFFF)) / 32.0f;1516float dsdx = (float)((short)((rdp.cmd3 & 0xFFFF0000) >> 16)) / 1024.0f;1517float dtdy = (float)((short)(rdp.cmd3 & 0x0000FFFF)) / 1024.0f;15181519if (rdp.cycle_mode == 2) dsdx /= 4.0f;15201521float s_ul_x = ul_x * rdp.scale_x + rdp.offset_x;1522float s_lr_x = lr_x * rdp.scale_x + rdp.offset_x;1523float s_ul_y = ul_y * rdp.scale_y + rdp.offset_y;1524float s_lr_y = lr_y * rdp.scale_y + rdp.offset_y;15251526FRDP("texrect (%d, %d, %d, %d), tile: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, tile, rdp.tri_n, rdp.tri_n+1);1527FRDP ("(%f, %f) -> (%f, %f), s: (%d, %d) -> (%d, %d)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y, rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);1528FRDP("\toff_x: %f, off_y: %f, dsdx: %f, dtdy: %f\n", off_x, off_y, dsdx, dtdy);15291530float off_size_x;1531float off_size_y;15321533if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip1534{1535off_size_x = (float)((lr_y - ul_y - 1) * dsdx);1536off_size_y = (float)((lr_x - ul_x - 1) * dtdy);1537}1538else1539{1540off_size_x = (float)((lr_x - ul_x - 1) * dsdx);1541off_size_y = (float)((lr_y - ul_y - 1) * dtdy);1542}15431544float lr_u0, lr_v0, ul_u0, ul_v0, lr_u1, lr_v1, ul_u1, ul_v1;15451546if (rdp.cur_cache[0] && (rdp.tex & 1))1547{1548float sx=1, sy=1;1549if (rdp.tiles[rdp.cur_tile].shift_s)1550{1551if (rdp.tiles[rdp.cur_tile].shift_s > 10)1552sx = (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s));1553else1554sx = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile].shift_s);1555}1556if (rdp.tiles[rdp.cur_tile].shift_t)1557{1558if (rdp.tiles[rdp.cur_tile].shift_t > 10)1559sy = (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t));1560else1561sy = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile].shift_t);1562}1563if (rdp.hires_tex && rdp.hires_tex->tile == 0)1564{1565off_x += rdp.hires_tex->u_shift;// + rdp.tiles[0].ul_s; //commented for Paper Mario motion blur1566off_y += rdp.hires_tex->v_shift;// + rdp.tiles[0].ul_t;1567FRDP("hires_tex ul_s: %d, ul_t: %d, off_x: %f, off_y: %f\n", rdp.tiles[0].ul_s, rdp.tiles[0].ul_t, off_x, off_y);1568ul_u0 = off_x * sx;1569ul_v0 = off_y * sy;15701571lr_u0 = ul_u0 + off_size_x * sx;1572lr_v0 = ul_v0 + off_size_y * sy;15731574ul_u0 *= rdp.hires_tex->u_scale;1575ul_v0 *= rdp.hires_tex->v_scale;1576lr_u0 *= rdp.hires_tex->u_scale;1577lr_v0 *= rdp.hires_tex->v_scale;1578FRDP("hires_tex ul_u0: %f, ul_v0: %f, lr_u0: %f, lr_v0: %f\n", ul_u0, ul_v0, lr_u0, lr_v0);1579}1580else1581{1582ul_u0 = off_x * sx;1583ul_v0 = off_y * sy;15841585ul_u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;1586ul_v0 -= rdp.tiles[rdp.cur_tile].f_ul_t;15871588lr_u0 = ul_u0 + off_size_x * sx;1589lr_v0 = ul_v0 + off_size_y * sy;15901591ul_u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * ul_u0;1592lr_u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * lr_u0;1593ul_v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * ul_v0;1594lr_v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * lr_v0;1595}1596}1597else1598{1599ul_u0 = ul_v0 = lr_u0 = lr_v0 = 0;1600}1601if (rdp.cur_cache[1] && (rdp.tex & 2))1602{1603float sx=1, sy=1;16041605if (rdp.tiles[rdp.cur_tile+1].shift_s)1606{1607if (rdp.tiles[rdp.cur_tile+1].shift_s > 10)1608sx = (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s));1609else1610sx = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile+1].shift_s);1611}1612if (rdp.tiles[rdp.cur_tile+1].shift_t)1613{1614if (rdp.tiles[rdp.cur_tile+1].shift_t > 10)1615sy = 1;//(float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t));1616else1617sy = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile+1].shift_t);1618}16191620if (rdp.hires_tex && rdp.hires_tex->tile == 1)1621{1622off_x += rdp.hires_tex->u_shift;// + rdp.tiles[0].ul_s; //commented for Paper Mario motion blur1623off_y += rdp.hires_tex->v_shift;// + rdp.tiles[0].ul_t;1624FRDP("hires_tex ul_s: %d, ul_t: %d, off_x: %f, off_y: %f\n", rdp.tiles[0].ul_s, rdp.tiles[0].ul_t, off_x, off_y);1625ul_u1 = off_x * sx;1626ul_v1 = off_y * sy;16271628lr_u1 = ul_u1 + off_size_x * sx;1629lr_v1 = ul_v1 + off_size_y * sy;16301631ul_u1 *= rdp.hires_tex->u_scale;1632ul_v1 *= rdp.hires_tex->v_scale;1633lr_u1 *= rdp.hires_tex->u_scale;1634lr_v1 *= rdp.hires_tex->v_scale;1635FRDP("hires_tex ul_u1: %f, ul_v1: %f, lr_u1: %f, lr_v1: %f\n", ul_u0, ul_v0, lr_u0, lr_v0);16361637}1638else1639{1640ul_u1 = off_x * sx;1641ul_v1 = off_y * sy;16421643ul_u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s;1644ul_v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t;16451646lr_u1 = ul_u1 + off_size_x * sx;1647lr_v1 = ul_v1 + off_size_y * sy;16481649ul_u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * ul_u1;1650lr_u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * lr_u1;1651ul_v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * ul_v1;1652lr_v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * lr_v1;1653}1654}1655else1656{1657ul_u1 = ul_v1 = lr_u1 = lr_v1 = 0;1658}1659rdp.cur_tile = prev_tile;16601661// ****16621663FRDP (" scissor: (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);16641665CCLIP2 (s_ul_x, s_lr_x, ul_u0, lr_u0, ul_u1, lr_u1, (float)rdp.scissor.ul_x, (float)rdp.scissor.lr_x);1666CCLIP2 (s_ul_y, s_lr_y, ul_v0, lr_v0, ul_v1, lr_v1, (float)rdp.scissor.ul_y, (float)rdp.scissor.lr_y);1667// CCLIP2 (s_lr_y, s_ul_y, lr_v0, ul_v0, lr_v1, ul_v1, (float)rdp.scissor.ul_y, (float)rdp.scissor.lr_y);16681669FRDP (" draw at: (%f, %f) -> (%f, %f)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y);16701671// DO NOT SET CLAMP MODE HERE16721673float Z = 1.0f;1674if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030)) // othermode check makes sure it1675// USES the z-buffer. Otherwise it returns bad (unset) values for lot and telescope1676//in zelda:mm.1677{1678FRDP ("prim_depth = %d\n", rdp.prim_depth);1679Z = rdp.prim_depth;1680if (settings.increase_primdepth)1681Z += 8.0f;1682Z = ScaleZ(Z);16831684grDepthBufferFunction (GR_CMP_LEQUAL);1685rdp.update |= UPDATE_ZBUF_ENABLED;1686}1687else1688{1689RDP ("no prim_depth used, using 1.0\n");1690}16911692VERTEX vstd[4] = {1693{ s_ul_x, s_ul_y, Z, 1.0f, ul_u0, ul_v0, ul_u1, ul_v1, { 0, 0, 0, 0}, 255 },1694{ s_lr_x, s_ul_y, Z, 1.0f, lr_u0, ul_v0, lr_u1, ul_v1, { 0, 0, 0, 0}, 255 },1695{ s_ul_x, s_lr_y, Z, 1.0f, ul_u0, lr_v0, ul_u1, lr_v1, { 0, 0, 0, 0}, 255 },1696{ s_lr_x, s_lr_y, Z, 1.0f, lr_u0, lr_v0, lr_u1, lr_v1, { 0, 0, 0, 0}, 255 } };16971698if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip1699{1700vstd[1].u0 = ul_u0;1701vstd[1].v0 = lr_v0;1702vstd[1].u1 = ul_u1;1703vstd[1].v1 = lr_v1;17041705vstd[2].u0 = lr_u0;1706vstd[2].v0 = ul_v0;1707vstd[2].u1 = lr_u1;1708vstd[2].v1 = ul_v1;1709}17101711VERTEX *vptr = vstd;1712int n_vertices = 4;17131714VERTEX *vnew = 0;1715// for (int j =0; j < 4; j++)1716// FRDP("v[%d] u0: %f, v0: %f, u1: %f, v1: %f\n", j, vstd[j].u0, vstd[j].v0, vstd[j].u1, vstd[j].v1);171717181719if (!rdp.hires_tex && rdp.cur_cache[0]->splits != 1)1720{1721// ** LARGE TEXTURE HANDLING **1722// *VERY* simple algebra for texrects1723float min_u, min_x, max_u, max_x;1724if (vstd[0].u0 < vstd[1].u0)1725{1726min_u = vstd[0].u0;1727min_x = vstd[0].x;1728max_u = vstd[1].u0;1729max_x = vstd[1].x;1730}1731else1732{1733min_u = vstd[1].u0;1734min_x = vstd[1].x;1735max_u = vstd[0].u0;1736max_x = vstd[0].x;1737}17381739int start_u_256, end_u_256;17401741if (settings.ucode == 7)1742{1743start_u_256 = 0;1744end_u_256 = (lr_x - ul_x - 1)>>8;1745}1746else1747{1748start_u_256 = (int)min_u >> 8;1749end_u_256 = (int)max_u >> 8;1750}1751//FRDP(" min_u: %f, max_u: %f start: %d, end: %d\n", min_u, max_u, start_u_256, end_u_256);17521753int splitheight = rdp.cur_cache[0]->splitheight;17541755int num_verts_line = 2 + ((end_u_256-start_u_256)<<1);1756vnew = new VERTEX [num_verts_line << 1];17571758n_vertices = num_verts_line << 1;1759vptr = vnew;17601761vnew[0] = vstd[0];1762vnew[0].u0 -= 256.0f * start_u_256;1763vnew[0].v0 += splitheight * start_u_256;1764vnew[0].u1 -= 256.0f * start_u_256;1765vnew[0].v1 += splitheight * start_u_256;1766vnew[1] = vstd[2];1767vnew[1].u0 -= 256.0f * start_u_256;1768vnew[1].v0 += splitheight * start_u_256;1769vnew[1].u1 -= 256.0f * start_u_256;1770vnew[1].v1 += splitheight * start_u_256;1771vnew[n_vertices-2] = vstd[1];1772vnew[n_vertices-2].u0 -= 256.0f * end_u_256;1773vnew[n_vertices-2].v0 += splitheight * end_u_256;1774vnew[n_vertices-2].u1 -= 256.0f * end_u_256;1775vnew[n_vertices-2].v1 += splitheight * end_u_256;1776vnew[n_vertices-1] = vstd[3];1777vnew[n_vertices-1].u0 -= 256.0f * end_u_256;1778vnew[n_vertices-1].v0 += splitheight * end_u_256;1779vnew[n_vertices-1].u1 -= 256.0f * end_u_256;1780vnew[n_vertices-1].v1 += splitheight * end_u_256;17811782// find the equation of the line of u,x1783float m = (max_x - min_x) / (max_u - min_u); // m = delta x / delta u1784float b = min_x - m * min_u; // b = y - m * x17851786for (i=start_u_256; i<end_u_256; i++)1787{1788// Find where x = current 256 multiple1789float x = m * ((i<<8)+256) + b;17901791int vn = 2 + ((i-start_u_256)<<2);1792vnew[vn] = vnew[0];1793vnew[vn].x = x;1794vnew[vn].u0 = 255.5f;1795vnew[vn].v0 += (float)splitheight * i;1796vnew[vn].u1 = 255.5f;1797vnew[vn].v1 += (float)splitheight * i;17981799vn ++;1800vnew[vn] = vnew[1];1801vnew[vn].x = x;1802vnew[vn].u0 = 255.5f;1803vnew[vn].v0 += (float)splitheight * i;1804vnew[vn].u1 = 255.5f;1805vnew[vn].v1 += (float)splitheight * i;18061807vn ++;1808vnew[vn] = vnew[vn-2];1809vnew[vn].u0 = 0.5f;1810vnew[vn].v0 += (float)splitheight;1811vnew[vn].u1 = 0.5f;1812vnew[vn].v1 += (float)splitheight;18131814vn ++;1815vnew[vn] = vnew[vn-2];1816vnew[vn].u0 = 0.5f;1817vnew[vn].v0 += (float)splitheight;1818vnew[vn].u1 = 0.5f;1819vnew[vn].v1 += (float)splitheight;1820}1821}18221823AllowShadeMods (vptr, n_vertices);1824for (i=0; i<n_vertices; i++)1825{1826VERTEX *z = &vptr[i];18271828z->u0 *= z->q;1829z->v0 *= z->q;1830z->u1 *= z->q;1831z->v1 *= z->q;18321833apply_shade_mods (z);1834}18351836if (fullscreen)1837{1838grFogMode (GR_FOG_DISABLE);18391840grClipWindow (0, 0, settings.res_x, settings.res_y);18411842grCullMode (GR_CULL_DISABLE);18431844if (rdp.cycle_mode == 2)1845{1846grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,1847GR_COMBINE_FACTOR_ONE,1848GR_COMBINE_LOCAL_NONE,1849GR_COMBINE_OTHER_TEXTURE,1850FXFALSE);1851grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,1852GR_COMBINE_FACTOR_ONE,1853GR_COMBINE_LOCAL_NONE,1854GR_COMBINE_OTHER_TEXTURE,1855FXFALSE);1856grAlphaBlendFunction (GR_BLEND_ONE,1857GR_BLEND_ZERO,1858GR_BLEND_ZERO,1859GR_BLEND_ZERO);1860if (rdp.othermode_l & 1)1861{1862grAlphaTestFunction (GR_CMP_GEQUAL);1863grAlphaTestReferenceValue (0x80);1864}1865else1866grAlphaTestFunction (GR_CMP_ALWAYS);18671868rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE;1869}18701871ConvertCoordsConvert (vptr, n_vertices);18721873if (settings.wireframe)1874{1875SetWireframeCol ();1876grDrawLine (&vstd[0], &vstd[2]);1877grDrawLine (&vstd[2], &vstd[1]);1878grDrawLine (&vstd[1], &vstd[0]);1879grDrawLine (&vstd[2], &vstd[3]);1880grDrawLine (&vstd[3], &vstd[1]);1881}1882else1883{1884grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, n_vertices, vptr, sizeof(VERTEX));1885}18861887if (debug.capture)1888{1889VERTEX vl[3];1890vl[0] = vstd[0];1891vl[1] = vstd[2];1892vl[2] = vstd[1];1893add_tri (vl, 3, TRI_TEXRECT);1894rdp.tri_n ++;1895vl[0] = vstd[2];1896vl[1] = vstd[3];1897vl[2] = vstd[1];1898add_tri (vl, 3, TRI_TEXRECT);1899rdp.tri_n ++;1900}1901else1902rdp.tri_n += 2;19031904if (settings.fog && (rdp.flags & FOG_ENABLED))1905{1906grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);1907}1908rdp.update |= UPDATE_CULL_MODE | UPDATE_VIEWPORT;1909}1910else1911{1912rdp.tri_n += 2;1913}19141915delete[] vnew;1916}19171918static void rdp_loadsync()1919{1920RDP("loadsync - ignored\n");1921}19221923static void rdp_pipesync()1924{1925RDP("pipesync - ignored\n");1926}19271928static void rdp_tilesync()1929{1930RDP("tilesync - ignored\n");1931}19321933static void rdp_fullsync()1934{1935// Set an interrupt to allow the game to continue1936*gfx.MI_INTR_REG |= 0x20;1937gfx.CheckInterrupts();1938RDP("fullsync\n");1939}19401941static void rdp_setkeygb()1942{1943RDP_E("setkeygb - IGNORED\n");1944RDP("setkeygb - IGNORED\n");1945}19461947static void rdp_setkeyr()1948{1949RDP_E("setkeyr - IGNORED\n");1950RDP("setkeyr - IGNORED\n");1951}19521953static void rdp_setconvert()1954{1955/*1956rdp.YUV_C0 = 1.1647f ;1957rdp.YUV_C1 = 0.79931f ;1958rdp.YUV_C2 = -0.1964f ;1959rdp.YUV_C3 = -0.40651f;1960rdp.YUV_C4 = 1.014f ;1961*/1962rdp.K5 = (BYTE)(rdp.cmd1&0x1FF);1963RDP_E("setconvert - IGNORED\n");1964RDP("setconvert - IGNORED\n");1965}19661967//1968// setscissor - sets the screen clipping rectangle1969//19701971static void rdp_setscissor()1972{1973// clipper resolution is 320x240, scale based on computer resolution1974rdp.scissor_o.ul_x = /*min(*/(DWORD)(((rdp.cmd0 & 0x00FFF000) >> 14))/*, 320)*/;1975rdp.scissor_o.ul_y = /*min(*/(DWORD)(((rdp.cmd0 & 0x00000FFF) >> 2))/*, 240)*/;1976rdp.scissor_o.lr_x = /*min(*/(DWORD)(((rdp.cmd1 & 0x00FFF000) >> 14))/*, 320)*/;1977rdp.scissor_o.lr_y = /*min(*/(DWORD)(((rdp.cmd1 & 0x00000FFF) >> 2))/*, 240)*/;19781979rdp.ci_upper_bound = rdp.scissor_o.ul_y;1980rdp.ci_lower_bound = rdp.scissor_o.lr_y;19811982FRDP("setscissor: (%d,%d) -> (%d,%d)\n", rdp.scissor_o.ul_x, rdp.scissor_o.ul_y,1983rdp.scissor_o.lr_x, rdp.scissor_o.lr_y);19841985rdp.update |= UPDATE_SCISSOR;1986}19871988static void rdp_setprimdepth()1989{1990rdp.prim_depth = (WORD)((rdp.cmd1 >> 16) & 0x7FFF);19911992FRDP("setprimdepth: %d\n", rdp.prim_depth);1993}19941995static void rdp_setothermode()1996{1997#define F3DEX2_SETOTHERMODE(cmd,sft,len,data) { \1998rdp.cmd0 = (cmd<<24) | ((32-(sft)-(len))<<8) | (((len)-1)); \1999rdp.cmd1 = data; \2000gfx_instruction[settings.ucode][cmd] (); \2001}2002#define SETOTHERMODE(cmd,sft,len,data) { \2003rdp.cmd0 = (cmd<<24) | ((sft)<<8) | (len); \2004rdp.cmd1 = data; \2005gfx_instruction[settings.ucode][cmd] (); \2006}20072008RDP("rdp_setothermode\n");20092010if ((settings.ucode == 2) || (settings.ucode == 8))2011{2012int cmd0 = rdp.cmd0;2013F3DEX2_SETOTHERMODE(0xE2, 0, 32, rdp.cmd1); // SETOTHERMODE_L2014F3DEX2_SETOTHERMODE(0xE3, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H2015}2016else2017{2018int cmd0 = rdp.cmd0;2019SETOTHERMODE(0xB9, 0, 32, rdp.cmd1); // SETOTHERMODE_L2020SETOTHERMODE(0xBA, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H2021}2022}20232024void load_palette (DWORD addr, WORD start, WORD count)2025{2026RDP ("Loading palette... ");2027WORD *dpal = rdp.pal_8 + start;2028WORD end = start+count;2029// WORD *spal = (WORD*)(gfx.RDRAM + (addr & BMASK));20302031for (WORD i=start; i<end; i++)2032{2033*(dpal++) = *(WORD *)(gfx.RDRAM + (addr^2));2034addr += 2;20352036#ifdef TLUT_LOGGING2037FRDP ("%d: %08lx\n", i, *(WORD *)(gfx.RDRAM + (addr^2)));2038#endif2039}2040start >>= 4;2041end = start + (count >> 4);2042for (WORD p = start; p < end; p++)2043{2044rdp.pal_8_crc[p] = CRC_Calculate( 0xFFFFFFFF, &rdp.pal_8[(p << 4)], 32 );2045}2046rdp.pal_256_crc = CRC_Calculate( 0xFFFFFFFF, rdp.pal_8_crc, 64 );2047RDP ("Done.\n");2048}20492050static void rdp_loadtlut()2051{2052DWORD tile = (rdp.cmd1 >> 24) & 0x07;2053WORD start = rdp.tiles[tile].t_mem - 256; // starting location in the palettes2054// WORD start = ((WORD)(rdp.cmd1 >> 2) & 0x3FF) + 1;2055WORD count = ((WORD)(rdp.cmd1 >> 14) & 0x3FF) + 1; // number to copy20562057if (rdp.timg.addr + (count<<1) > BMASK)2058count = (WORD)((BMASK - rdp.timg.addr) >> 1);20592060if (start+count > 256) count = 256-start;20612062FRDP("loadtlut: tile: %d, start: %d, count: %d, from: %08lx\n", tile, start, count,2063rdp.timg.addr);20642065load_palette (rdp.timg.addr, start, count);20662067rdp.timg.addr += count << 1;2068}20692070BOOL tile_set = 0;2071static void rdp_settilesize()2072{2073DWORD tile = (rdp.cmd1 >> 24) & 0x07;2074rdp.last_tile_size = tile;20752076rdp.tiles[tile].f_ul_s = (float)((rdp.cmd0 >> 12) & 0xFFF) / 4.0f;2077rdp.tiles[tile].f_ul_t = (float)(rdp.cmd0 & 0xFFF) / 4.0f;20782079int ul_s = (((WORD)(rdp.cmd0 >> 14)) & 0x03ff);2080int ul_t = (((WORD)(rdp.cmd0 >> 2 )) & 0x03ff);2081int lr_s = (((WORD)(rdp.cmd1 >> 14)) & 0x03ff);2082int lr_t = (((WORD)(rdp.cmd1 >> 2 )) & 0x03ff);20832084if (lr_s == 0 && ul_s == 0) //pokemon puzzle league set such tile size2085wrong_tile = tile;2086else if (wrong_tile == (int)tile)2087wrong_tile = -1;20882089if (settings.use_sts1_only)2090{2091// ** USE FIRST SETTILESIZE ONLY **2092// This option helps certain textures while using the 'Alternate texture size method',2093// but may break others. (should help more than break)20942095if (tile_set)2096{2097// coords in 10.2 format2098rdp.tiles[tile].ul_s = ul_s;2099rdp.tiles[tile].ul_t = ul_t;2100rdp.tiles[tile].lr_s = lr_s;2101rdp.tiles[tile].lr_t = lr_t;2102tile_set = 0;2103}2104}2105else2106{2107// coords in 10.2 format2108rdp.tiles[tile].ul_s = ul_s;2109rdp.tiles[tile].ul_t = ul_t;2110rdp.tiles[tile].lr_s = lr_s;2111rdp.tiles[tile].lr_t = lr_t;2112}21132114// handle wrapping2115if (rdp.tiles[tile].lr_s < rdp.tiles[tile].ul_s) rdp.tiles[tile].lr_s += 0x400;2116if (rdp.tiles[tile].lr_t < rdp.tiles[tile].ul_t) rdp.tiles[tile].lr_t += 0x400;21172118rdp.update |= UPDATE_TEXTURE;21192120rdp.first = 1;21212122if (tile == 0 && rdp.hires_tex)2123//if ((rdp.tiles[tile].size != 2) || ((rdp.timg.width == 1) && (rdp.hires_tex->width != (DWORD)(lr_s+1))))2124if (((rdp.tiles[tile].format == 0) && (rdp.tiles[tile].size != 2)) || ((rdp.timg.width == 1) && (rdp.hires_tex->width != (DWORD)(lr_s+1))))2125rdp.hires_tex = 0;2126if (rdp.hires_tex)2127{2128if (rdp.tiles[tile].format == 0 && rdp.hires_tex->format == 0)2129{2130if (tile == 1 && (DWORD)rdp.hires_tex->tmu != tile)2131SwapTextureBuffer();2132rdp.hires_tex->tile = tile;2133rdp.hires_tex->info.format = GR_TEXFMT_RGB_565;2134FRDP ("hires_tex: tile: %d\n", tile);2135}2136else if (tile == 0)2137{2138rdp.hires_tex->info.format = GR_TEXFMT_ALPHA_INTENSITY_88;2139}2140}2141FRDP ("settilesize: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d\n",2142tile, ul_s, ul_t, lr_s, lr_t);2143}21442145static void CopyswapBlock(int *pDst, unsigned int cnt, unsigned int SrcOffs)2146{2147// copy and byteswap a block of 8-byte dwords2148int rem = SrcOffs & 3;2149if (rem == 0)2150{2151int *pSrc = (int *) ((uintptr_t) gfx.RDRAM + SrcOffs);2152for (unsigned int x = 0; x < cnt; x++)2153{2154int s1 = bswap32(*pSrc++);2155int s2 = bswap32(*pSrc++);2156*pDst++ = s1;2157*pDst++ = s2;2158}2159}2160else2161{2162// set source pointer to 4-byte aligned RDRAM location before the start2163int *pSrc = (int *) ((uintptr_t) gfx.RDRAM + (SrcOffs & 0xfffffffc));2164// do the first partial 32-bit word2165int s0 = bswap32(*pSrc++);2166for (int x = 0; x < rem; x++)2167s0 >>= 8;2168for (int x = 4; x > rem; x--)2169{2170*((char *) pDst) = s0 & 0xff;2171pDst = (int *) ((char *) pDst + 1);2172s0 >>= 8;2173}2174// do one full 32-bit word2175s0 = bswap32(*pSrc++);2176*pDst++ = s0;2177// do 'cnt-1' 64-bit dwords2178for (unsigned int x = 0; x < cnt-1; x++)2179{2180int s1 = bswap32(*pSrc++);2181int s2 = bswap32(*pSrc++);2182*pDst++ = s1;2183*pDst++ = s2;2184}2185// do last partial 32-bit word2186s0 = bswap32(*pSrc++);2187for (; rem > 0; rem--)2188{2189*((char *) pDst) = s0 & 0xff;2190pDst = (int *) ((char *) pDst + 1);2191s0 >>= 8;2192}2193}2194}21952196static void WordswapBlock(int *pDst, unsigned int cnt, unsigned int TileSize)2197{2198// Since it's not loading 32-bit textures as the N64 would, 32-bit textures need to2199// be swapped by 64-bits, not 32.2200if (TileSize == 3)2201{2202// swapblock64 dst, cnt2203for (unsigned int x = 0; x < cnt / 2; x++, pDst += 4)2204{2205long long s1 = ((long long *) pDst)[0];2206long long s2 = ((long long *) pDst)[1];2207((long long *) pDst)[0] = s2;2208((long long *) pDst)[1] = s1;2209}2210}2211else2212{2213// swapblock32 dst, cnt2214for (unsigned int x = 0; x < cnt; x++, pDst += 2)2215{2216int s1 = pDst[0];2217int s2 = pDst[1];2218pDst[0] = s2;2219pDst[1] = s1;2220}2221}2222}22232224static void rdp_loadblock()2225{2226if (rdp.skip_drawing)2227{2228RDP("loadblock skipped\n");2229return;2230}2231DWORD tile = (DWORD)((rdp.cmd1 >> 24) & 0x07);2232DWORD dxt = (DWORD)(rdp.cmd1 & 0x0FFF);22332234rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr;22352236// ** DXT is used for swapping every other line2237/* double fdxt = (double)0x8000000F/(double)((DWORD)(2047/(dxt-1))); // F for error2238DWORD _dxt = (DWORD)fdxt;*/22392240// 0x00000800 -> 0x80000000 (so we can check the sign bit instead of the 11th bit)2241DWORD _dxt = dxt << 20;22422243DWORD addr = segoffset(rdp.timg.addr) & BMASK;22442245// lr_s specifies number of 64-bit words to copy2246// 10.2 format2247WORD ul_s = (WORD)(rdp.cmd0 >> 14) & 0x3FF;2248WORD ul_t = (WORD)(rdp.cmd0 >> 2) & 0x3FF;2249WORD lr_s = (WORD)(rdp.cmd1 >> 14) & 0x3FF;22502251rdp.tiles[tile].ul_s = ul_s;2252rdp.tiles[tile].ul_t = ul_t;2253rdp.tiles[tile].lr_s = lr_s;22542255rdp.timg.set_by = 0; // load block22562257// do a quick boundary check before copying to eliminate the possibility for exception2258if (ul_s >= 512) {2259lr_s = 1; // 1 so that it doesn't die on memcpy2260ul_s = 511;2261}2262if (ul_s+lr_s > 512)2263lr_s = 512-ul_s;22642265if (addr+(lr_s<<3) > BMASK+1)2266lr_s = (WORD)((BMASK-addr)>>3);22672268DWORD offs = rdp.timg.addr;2269DWORD cnt = lr_s+1;2270if (rdp.tiles[tile].size == 3)2271cnt <<= 1;2272//FIXME: unused? DWORD start_line = 0;22732274// if (lr_s > 0)2275rdp.timg.addr += cnt << 3;22762277int * pDst = (int *) ((uintptr_t)rdp.tmem+(rdp.tiles[tile].t_mem<<3));22782279// Load the block from RDRAM and byteswap it as it loads2280CopyswapBlock(pDst, cnt, offs);22812282// now do 32-bit or 64-bit word swapping on every other row of data2283int dxt_accum = 0;2284while (cnt > 0)2285{2286// skip over unswapped blocks2287do2288{2289pDst += 2;2290if (--cnt == 0)2291break;2292dxt_accum += _dxt;2293} while (!(dxt_accum & 0x80000000));2294// count number of blocks to swap2295if (cnt == 0) break;2296int swapcnt = 0;2297do2298{2299swapcnt++;2300if (--cnt == 0)2301break;2302dxt_accum += _dxt;2303} while (dxt_accum & 0x80000000);2304// do 32-bit or 64-bit swap operation on this block2305WordswapBlock(pDst, swapcnt, rdp.tiles[tile].size);2306pDst += swapcnt * 2;2307}23082309rdp.update |= UPDATE_TEXTURE;23102311FRDP ("loadblock: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, dxt: %08lx -> %08lx\n",2312tile, ul_s, ul_t, lr_s,2313dxt, _dxt);2314}23152316static void rdp_loadtile()2317{2318if (rdp.skip_drawing)2319return;2320rdp.timg.set_by = 1; // load tile23212322DWORD tile = (DWORD)((rdp.cmd1 >> 24) & 0x07);2323if (rdp.tiles[tile].format == 1)2324{2325rdp.yuv_image = TRUE;2326if (rdp.timg.addr < rdp.yuv_im_begin) rdp.yuv_im_begin = rdp.timg.addr;2327return;2328}23292330rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr;23312332WORD ul_s = (WORD)((rdp.cmd0 >> 14) & 0x03FF);2333WORD ul_t = (WORD)((rdp.cmd0 >> 2 ) & 0x03FF);2334WORD lr_s = (WORD)((rdp.cmd1 >> 14) & 0x03FF);2335WORD lr_t = (WORD)((rdp.cmd1 >> 2 ) & 0x03FF);23362337if (lr_s < ul_s || lr_t < ul_t) return;23382339if (wrong_tile >= 0) //there was a tile with zero length2340{2341rdp.tiles[wrong_tile].lr_s = lr_s;23422343if (rdp.tiles[tile].size > rdp.tiles[wrong_tile].size)2344rdp.tiles[wrong_tile].lr_s <<= (rdp.tiles[tile].size - rdp.tiles[wrong_tile].size);2345else if (rdp.tiles[tile].size < rdp.tiles[wrong_tile].size)2346rdp.tiles[wrong_tile].lr_s >>= (rdp.tiles[wrong_tile].size - rdp.tiles[tile].size);2347rdp.tiles[wrong_tile].lr_t = lr_t;2348// wrong_tile = -1;2349}23502351if (rdp.hires_tex)// && (rdp.tiles[tile].format == 0))2352{2353FRDP("loadtile: hires_tex ul_s: %d, ul_t:%d\n", ul_s, ul_t);2354rdp.hires_tex->tile_uls = ul_s;2355rdp.hires_tex->tile_ult = ul_t;2356}23572358if (settings.tonic && tile == 7)2359{2360rdp.tiles[0].ul_s = ul_s;2361rdp.tiles[0].ul_t = ul_t;2362rdp.tiles[0].lr_s = lr_s;2363rdp.tiles[0].lr_t = lr_t;2364}23652366DWORD height = lr_t - ul_t + 1; // get height2367DWORD width = lr_s - ul_s + 1;23682369DWORD wid_64 = rdp.tiles[tile].line;23702371// CHEAT: it's very unlikely that it loads more than 1 32-bit texture in one command,2372// so i don't bother to write in two different places at once. Just load once with2373// twice as much data.2374if (rdp.tiles[tile].size == 3)2375wid_64 <<= 1;23762377int line_n = rdp.timg.width;2378if (rdp.tiles[tile].size == 0)2379line_n >>= 1;2380else2381line_n <<= (rdp.tiles[tile].size-1);23822383int offs = ul_t * line_n;2384offs += ul_s << rdp.tiles[tile].size >> 1;2385offs += rdp.timg.addr;2386if ((unsigned int) offs >= BMASK)2387return;23882389// check if points to bad location2390DWORD size = width * height;2391if (rdp.tiles[tile].size == 0)2392size >>= 1;2393else2394size <<= (rdp.tiles[tile].size-1);23952396if (offs + line_n*height > BMASK)2397height = (BMASK - offs) / line_n;23982399int * pDst = (int *) ((uintptr_t)rdp.tmem+(rdp.tiles[tile].t_mem<<3));2400int * pEnd = (int *) ((uintptr_t)rdp.tmem+4096 - (wid_64<<3));24012402for (unsigned int y = 0; y < height; y++)2403{2404if (pDst > pEnd) break;2405CopyswapBlock(pDst, wid_64, offs);2406if (y & 1)2407{2408WordswapBlock(pDst, wid_64, rdp.tiles[tile].size);2409}2410pDst += wid_64 * 2;2411offs += line_n;2412}24132414FRDP("loadtile: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d\n", tile,2415ul_s, ul_t, lr_s, lr_t);2416}24172418static void rdp_settile()2419{2420tile_set = 1; // used to check if we only load the first settilesize24212422rdp.first = 0;24232424//rdp.cur_tile_n = (DWORD)((rdp.cmd1 >> 24) & 0x07);2425//rdp.cur_tile = &rdp.tiles[rdp.cur_tile_n];24262427rdp.last_tile = (DWORD)((rdp.cmd1 >> 24) & 0x07);2428TILE *tile = &rdp.tiles[rdp.last_tile];24292430tile->format = (BYTE)((rdp.cmd0 >> 21) & 0x07);2431tile->size = (BYTE)((rdp.cmd0 >> 19) & 0x03);2432tile->line = (WORD)((rdp.cmd0 >> 9) & 0x01FF);2433tile->t_mem = (WORD)(rdp.cmd0 & 0x1FF);2434tile->palette = (BYTE)((rdp.cmd1 >> 20) & 0x0F);2435tile->clamp_t = (BYTE)((rdp.cmd1 >> 19) & 0x01);2436tile->mirror_t = (BYTE)((rdp.cmd1 >> 18) & 0x01);2437tile->mask_t = (BYTE)((rdp.cmd1 >> 14) & 0x0F);2438tile->shift_t = (BYTE)((rdp.cmd1 >> 10) & 0x0F);2439tile->clamp_s = (BYTE)((rdp.cmd1 >> 9) & 0x01);2440tile->mirror_s = (BYTE)((rdp.cmd1 >> 8) & 0x01);2441tile->mask_s = (BYTE)((rdp.cmd1 >> 4) & 0x0F);2442tile->shift_s = (BYTE)(rdp.cmd1 & 0x0F);24432444rdp.update |= UPDATE_TEXTURE;24452446FRDP ("settile: tile: %d, format: %s, size: %s, line: %d, "2447"t_mem: %08lx, palette: %d, clamp_t/mirror_t: %s, mask_t: %d, "2448"shift_t: %d, clamp_s/mirror_s: %s, mask_s: %d, shift_s: %d\n",2449rdp.last_tile, str_format[tile->format], str_size[tile->size], tile->line,2450tile->t_mem, tile->palette, str_cm[(tile->clamp_t<<1)|tile->mirror_t], tile->mask_t,2451tile->shift_t, str_cm[(tile->clamp_s<<1)|tile->mirror_s], tile->mask_s, tile->shift_s);2452}24532454//2455// fillrect - fills a rectangle2456//24572458static void rdp_fillrect()2459{2460DWORD ul_x = ((rdp.cmd1 & 0x00FFF000) >> 14);2461DWORD ul_y = (rdp.cmd1 & 0x00000FFF) >> 2;2462DWORD lr_x = ((rdp.cmd0 & 0x00FFF000) >> 14) + 1;2463DWORD lr_y = ((rdp.cmd0 & 0x00000FFF) >> 2) + 1;2464if ((rdp.cimg == rdp.zimg) || (settings.fb_smart && rdp.frame_buffers[rdp.ci_count-1].status == ci_zimg))2465{2466RDP ("Fillrect - cleared the depth buffer\n");2467if (fullscreen)2468{24692470grDepthMask (FXTRUE);2471grColorMask (FXFALSE, FXFALSE);2472grBufferClear (0, 0, 0xFFFF);2473grColorMask (FXTRUE, FXTRUE);2474rdp.update |= UPDATE_ZBUF_ENABLED;2475if (settings.fb_depth_clear)2476{2477ul_x = min(max(ul_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x);2478lr_x = min(max(lr_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x);2479ul_y = min(max(ul_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y);2480lr_y = min(max(lr_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y);2481//FIXME:unused? DWORD zi_height = lr_y - ul_y - 1;2482// rdp.zi_nb_pixels = rdp.zi_width * zi_height;2483rdp.zi_lry = lr_y - 1;2484rdp.zi_lrx = lr_x - 1;2485// FRDP ("zi_width: %d, zi_height: %d\n", rdp.zi_width, zi_height);2486DWORD fillrect_width_in_dwords = (lr_x-ul_x) >> 1;2487DWORD zi_width_in_dwords = rdp.zi_width >> 1;2488ul_x >>= 1;2489DWORD * dst = (DWORD*)(gfx.RDRAM+rdp.cimg);2490dst += ul_y * zi_width_in_dwords;2491for (DWORD y = ul_y; y < lr_y; y++)2492{2493for (DWORD x = ul_x; x < fillrect_width_in_dwords; x++)2494{2495dst[x] = rdp.fill_color;2496}2497dst += zi_width_in_dwords;2498}2499}2500}2501return;2502}25032504if (rdp.skip_drawing)2505{2506RDP("Fillrect skipped\n");2507return;2508}25092510// Update scissor2511update_scissor ();25122513if ((ul_x > lr_x) || (ul_y > lr_y)) return;2514if (settings.bomberman64 && (lr_x == rdp.ci_width) && (rdp.cimg == rdp.ocimg)) //bomberman64 hack2515return;25162517if (rdp.cur_image && (rdp.cur_image->format != 0) && (rdp.cycle_mode == 3) && (rdp.cur_image->width == lr_x))2518{2519DWORD color = rdp.fill_color;2520color = ((color&1)?0xFF:0) |2521((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) |2522((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) |2523((DWORD)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8);2524grDepthMask (FXFALSE);2525grBufferClear (color, 0, 0xFFFF);2526grDepthMask (FXTRUE);2527rdp.update |= UPDATE_ZBUF_ENABLED;2528return;2529}25302531if (settings.decrease_fillrect_edge && rdp.cycle_mode == 0)2532{2533lr_x--; lr_y--;2534}2535FRDP("fillrect (%d,%d) -> (%d,%d), cycle mode: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, rdp.cycle_mode,2536rdp.tri_n, rdp.tri_n+1);25372538FRDP("scissor (%d,%d) -> (%d,%d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x,2539rdp.scissor.lr_y);25402541// KILL the floating point error with 0.01f2542DWORD s_ul_x = (DWORD)min(max(ul_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x);2543DWORD s_lr_x = (DWORD)min(max(lr_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x);2544DWORD s_ul_y = (DWORD)min(max(ul_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y);2545DWORD s_lr_y = (DWORD)min(max(lr_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y);25462547if (s_lr_x < 0.0f) s_lr_x = 0;2548if (s_lr_y < 0.0f) s_lr_y = 0;2549if (s_ul_x > (float)settings.res_x) s_ul_x = settings.res_x;2550if (s_ul_y > (float)settings.res_y) s_ul_y = settings.res_y;25512552FRDP (" - %d, %d, %d, %d\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y);25532554if (fullscreen)2555{2556grFogMode (GR_FOG_DISABLE);25572558grClipWindow (0, 0, settings.res_x, settings.res_y);25592560float Z = 1.0f;2561if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030))2562{2563Z = ScaleZ(rdp.prim_depth);2564grDepthBufferFunction (GR_CMP_LEQUAL);2565// grDepthMask (FXTRUE);2566FRDP ("prim_depth = %d\n", rdp.prim_depth);2567}2568else2569{2570grDepthBufferFunction (GR_CMP_ALWAYS);2571grDepthMask (FXFALSE);2572RDP ("no prim_depth used, using 1.0\n");2573}2574// Draw the rectangle2575VERTEX v[4] = {2576{ (float)s_ul_x, (float)s_ul_y, Z, 1.0f, 0,0,0,0, { 0,0,0,0 }, 0,0, 0,0,0,0 },2577{ (float)s_lr_x, (float)s_ul_y, Z, 1.0f, 0,0,0,0, { 0,0,0,0 }, 0,0, 0,0,0,0 },2578{ (float)s_ul_x, (float)s_lr_y, Z, 1.0f, 0,0,0,0, { 0,0,0,0 }, 0,0, 0,0,0,0 },2579{ (float)s_lr_x, (float)s_lr_y, Z, 1.0f, 0,0,0,0, { 0,0,0,0 }, 0,0, 0,0,0,0 } };25802581if (rdp.cycle_mode == 3)2582{2583DWORD color = (settings.fillcolor_fix) ? rdp.fill_color : (rdp.fill_color >> 16);25842585if (settings.PM && rdp.frame_buffers[rdp.ci_count-1].status == ci_aux)2586{2587//background of auxilary frame buffers must have zero alpha.2588//make it black, set 0 alpha to plack pixels on frame buffer read2589color = 0;2590}2591else2592{2593color = ((color&1)?0xFF:0) |2594((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) |2595((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) |2596((DWORD)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8);2597}2598grConstantColorValue (color);25992600grColorCombine (GR_COMBINE_FUNCTION_LOCAL,2601GR_COMBINE_FACTOR_NONE,2602GR_COMBINE_LOCAL_CONSTANT,2603GR_COMBINE_OTHER_NONE,2604FXFALSE);26052606grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,2607GR_COMBINE_FACTOR_NONE,2608GR_COMBINE_LOCAL_CONSTANT,2609GR_COMBINE_OTHER_NONE,2610FXFALSE);26112612grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);26132614rdp.update |= UPDATE_COMBINE;2615}2616else2617{2618Combine ();2619TexCache (); // (to update combiner)2620DWORD cmb_mode_c = (rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF);2621DWORD cmb_mode_a = (rdp.cycle1 & 0x0FFF0000) | ((rdp.cycle2 >> 16) & 0x00000FFF);2622if (cmb_mode_c == 0x9fff9fff || cmb_mode_a == 0x09ff09ff) //shade2623{2624AllowShadeMods (v, 4);2625for (int k = 0; k < 4; k++)2626apply_shade_mods (&v[k]);2627}2628}26292630grAlphaTestFunction (GR_CMP_ALWAYS);2631if (grStippleModeExt)2632grStippleModeExt(GR_STIPPLE_DISABLE);26332634grCullMode(GR_CULL_DISABLE);26352636if (settings.wireframe)2637{2638SetWireframeCol ();2639grDrawLine (&v[0], &v[2]);2640grDrawLine (&v[2], &v[1]);2641grDrawLine (&v[1], &v[0]);2642grDrawLine (&v[2], &v[3]);2643grDrawLine (&v[3], &v[1]);2644//grDrawLine (&v[1], &v[2]);2645}2646else2647{2648grDrawTriangle (&v[0], &v[2], &v[1]);2649grDrawTriangle (&v[2], &v[3], &v[1]);2650}26512652if (debug.capture)2653{2654VERTEX v1[3];2655v1[0] = v[0];2656v1[1] = v[2];2657v1[2] = v[1];2658add_tri (v1, 3, TRI_FILLRECT);2659rdp.tri_n ++;2660v1[0] = v[2];2661v1[1] = v[3];2662add_tri (v1, 3, TRI_FILLRECT);2663rdp.tri_n ++;2664}2665else2666rdp.tri_n += 2;26672668if (settings.fog && (rdp.flags & FOG_ENABLED))2669{2670grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);2671}26722673rdp.update |= UPDATE_CULL_MODE | UPDATE_ALPHA_COMPARE | UPDATE_ZBUF_ENABLED;2674}2675else2676{2677rdp.tri_n += 2;2678}2679}26802681//2682// setfillcolor - sets the filling color2683//26842685static void rdp_setfillcolor()2686{2687rdp.fill_color = rdp.cmd1;2688rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE;26892690FRDP("setfillcolor: %08lx\n", rdp.cmd1);2691}26922693static void rdp_setfogcolor()2694{2695rdp.fog_color = rdp.cmd1;2696rdp.update |= UPDATE_COMBINE | UPDATE_FOG_ENABLED;26972698FRDP("setfogcolor - %08lx\n", rdp.cmd1);2699}27002701static void rdp_setblendcolor()2702{2703rdp.blend_color = rdp.cmd1;2704rdp.update |= UPDATE_COMBINE;27052706FRDP("setblendcolor: %08lx\n", rdp.cmd1);2707}27082709static void rdp_setprimcolor()2710{2711rdp.prim_color = rdp.cmd1;2712rdp.prim_lodmin = (rdp.cmd0 >> 8) & 0xFF;2713rdp.prim_lodfrac = max(rdp.cmd0 & 0xFF, rdp.prim_lodmin);2714rdp.update |= UPDATE_COMBINE;27152716FRDP("setprimcolor: %08lx, lodmin: %d, lodfrac: %d\n", rdp.cmd1, rdp.prim_lodmin,2717rdp.prim_lodfrac);2718}27192720static void rdp_setenvcolor()2721{2722rdp.env_color = rdp.cmd1;2723rdp.update |= UPDATE_COMBINE;27242725FRDP("setenvcolor: %08lx\n", rdp.cmd1);2726}27272728static void rdp_setcombine()2729{2730rdp.c_a0 = (BYTE)((rdp.cmd0 >> 20) & 0xF);2731rdp.c_b0 = (BYTE)((rdp.cmd1 >> 28) & 0xF);2732rdp.c_c0 = (BYTE)((rdp.cmd0 >> 15) & 0x1F);2733rdp.c_d0 = (BYTE)((rdp.cmd1 >> 15) & 0x7);2734rdp.c_Aa0 = (BYTE)((rdp.cmd0 >> 12) & 0x7);2735rdp.c_Ab0 = (BYTE)((rdp.cmd1 >> 12) & 0x7);2736rdp.c_Ac0 = (BYTE)((rdp.cmd0 >> 9) & 0x7);2737rdp.c_Ad0 = (BYTE)((rdp.cmd1 >> 9) & 0x7);27382739rdp.c_a1 = (BYTE)((rdp.cmd0 >> 5) & 0xF);2740rdp.c_b1 = (BYTE)((rdp.cmd1 >> 24) & 0xF);2741rdp.c_c1 = (BYTE)((rdp.cmd0 >> 0) & 0x1F);2742rdp.c_d1 = (BYTE)((rdp.cmd1 >> 6) & 0x7);2743rdp.c_Aa1 = (BYTE)((rdp.cmd1 >> 21) & 0x7);2744rdp.c_Ab1 = (BYTE)((rdp.cmd1 >> 3) & 0x7);2745rdp.c_Ac1 = (BYTE)((rdp.cmd1 >> 18) & 0x7);2746rdp.c_Ad1 = (BYTE)((rdp.cmd1 >> 0) & 0x7);27472748rdp.cycle1 = (rdp.c_a0<<0) | (rdp.c_b0<<4) | (rdp.c_c0<<8) | (rdp.c_d0<<13)|2749(rdp.c_Aa0<<16)| (rdp.c_Ab0<<19)| (rdp.c_Ac0<<22)| (rdp.c_Ad0<<25);2750rdp.cycle2 = (rdp.c_a1<<0) | (rdp.c_b1<<4) | (rdp.c_c1<<8) | (rdp.c_d1<<13)|2751(rdp.c_Aa1<<16)| (rdp.c_Ab1<<19)| (rdp.c_Ac1<<22)| (rdp.c_Ad1<<25);27522753rdp.update |= UPDATE_COMBINE;27542755FRDP("setcombine\na0=%s b0=%s c0=%s d0=%s\nAa0=%s Ab0=%s Ac0=%s Ad0=%s\na1=%s b1=%s c1=%s d1=%s\nAa1=%s Ab1=%s Ac1=%s Ad1=%s\n",2756Mode0[rdp.c_a0], Mode1[rdp.c_b0], Mode2[rdp.c_c0], Mode3[rdp.c_d0],2757Alpha0[rdp.c_Aa0], Alpha1[rdp.c_Ab0], Alpha2[rdp.c_Ac0], Alpha3[rdp.c_Ad0],2758Mode0[rdp.c_a1], Mode1[rdp.c_b1], Mode2[rdp.c_c1], Mode3[rdp.c_d1],2759Alpha0[rdp.c_Aa1], Alpha1[rdp.c_Ab1], Alpha2[rdp.c_Ac1], Alpha3[rdp.c_Ad1]);2760}27612762//2763// settextureimage - sets the source for an image copy2764//27652766static void rdp_settextureimage()2767{2768static const char *format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" };2769static const char *size[] = { "4bit", "8bit", "16bit", "32bit" };27702771rdp.timg.format = (BYTE)((rdp.cmd0 >> 21) & 0x07);2772rdp.timg.size = (BYTE)((rdp.cmd0 >> 19) & 0x03);2773rdp.timg.width = (WORD)(1 + (rdp.cmd0 & 0x00000FFF));2774rdp.timg.addr = segoffset(rdp.cmd1);2775rdp.s2dex_tex_loaded = TRUE;2776rdp.update |= UPDATE_TEXTURE;27772778if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self && (rdp.timg.addr >= rdp.cimg) && (rdp.timg.addr < rdp.ci_end))2779{2780if (!rdp.fb_drawn)2781{2782if (!rdp.cur_image)2783CopyFrameBuffer();2784else if (rdp.frame_buffers[rdp.ci_count].status != ci_copy)2785CloseTextureBuffer(TRUE);2786rdp.fb_drawn = TRUE;2787}2788}27892790if (settings.fb_hires) //search this texture among drawn texture buffers2791{2792if (settings.zelda)2793{2794if (rdp.timg.size == 2)2795FindTextureBuffer(rdp.timg.addr, rdp.timg.width);2796}2797else2798FindTextureBuffer(rdp.timg.addr, rdp.timg.width);2799}28002801FRDP("settextureimage: format: %s, size: %s, width: %d, addr: %08lx\n",2802format[rdp.timg.format], size[rdp.timg.size],2803rdp.timg.width, rdp.timg.addr);2804}28052806static void rdp_setdepthimage()2807{2808rdp.zimg = segoffset(rdp.cmd1) & BMASK;2809rdp.zi_width = rdp.ci_width;2810FRDP("setdepthimage - %08lx\n", rdp.zimg);2811}281228132814BOOL SwapOK = TRUE;2815static void RestoreScale()2816{2817FRDP("Return to original scale: x = %f, y = %f\n", rdp.scale_x_bak, rdp.scale_y_bak);2818rdp.scale_x = rdp.scale_x_bak;2819rdp.scale_y = rdp.scale_y_bak;2820// update_scissor();2821rdp.view_scale[0] *= rdp.scale_x;2822rdp.view_scale[1] *= rdp.scale_y;2823rdp.view_trans[0] *= rdp.scale_x;2824rdp.view_trans[1] *= rdp.scale_y;2825rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;2826//*2827if (fullscreen)2828{2829grDepthMask (FXFALSE);2830grBufferClear (0, 0, 0xFFFF);2831grDepthMask (FXTRUE);2832}2833//*/2834}28352836static DWORD swapped_addr = 0;28372838static void rdp_setcolorimage()2839{2840render_depth_mode = 0;2841if (settings.fb_smart && (rdp.num_of_ci < NUMTEXBUF))2842{2843COLOR_IMAGE & cur_fb = rdp.frame_buffers[rdp.ci_count];2844COLOR_IMAGE & prev_fb = rdp.frame_buffers[rdp.ci_count-1];2845COLOR_IMAGE & next_fb = rdp.frame_buffers[rdp.ci_count+1];2846switch (cur_fb.status)2847{2848case ci_main:2849{28502851if (rdp.ci_count == 0)2852{2853if (rdp.ci_status == ci_aux) //for PPL2854{2855float sx = rdp.scale_x;2856float sy = rdp.scale_y;2857rdp.scale_x = 1.0f;2858rdp.scale_y = 1.0f;2859CopyFrameBuffer ();2860rdp.scale_x = sx;2861rdp.scale_y = sy;2862}2863if (!settings.fb_hires)2864{2865if ((rdp.num_of_ci > 1) &&2866(next_fb.status == ci_aux) &&2867(next_fb.width >= cur_fb.width))2868{2869rdp.scale_x = 1.0f;2870rdp.scale_y = 1.0f;2871}2872}2873else if (rdp.copy_ci_index && settings.PM) //tidal wave2874OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);2875}2876else if (!rdp.motionblur && settings.fb_hires && !SwapOK && (rdp.ci_count <= rdp.copy_ci_index))2877{2878if (next_fb.status == ci_aux_copy)2879OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);2880else2881OpenTextureBuffer(rdp.frame_buffers[rdp.copy_ci_index]);2882}2883else if (settings.fb_hires && rdp.read_whole_frame && prev_fb.status == ci_aux)2884{2885OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);2886}2887//else if (rdp.ci_status == ci_aux && !rdp.copy_ci_index)2888// CloseTextureBuffer();28892890rdp.skip_drawing = FALSE;2891}2892break;2893case ci_copy:2894{2895if (!rdp.motionblur || settings.fb_motionblur)2896{2897if (cur_fb.width == rdp.ci_width)2898{2899if (CopyTextureBuffer(prev_fb, cur_fb))2900// if (CloseTextureBuffer(TRUE))2901;2902else2903{2904if (!rdp.fb_drawn || prev_fb.status == ci_copy_self)2905{2906CopyFrameBuffer ();2907rdp.fb_drawn = TRUE;2908}2909memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);2910}2911}2912else2913{2914CloseTextureBuffer(TRUE);2915}2916}2917else2918{2919memset(gfx.RDRAM+cur_fb.addr, 0, cur_fb.width*cur_fb.height*rdp.ci_size);2920}2921rdp.skip_drawing = TRUE;2922}2923break;2924case ci_aux_copy:2925{2926rdp.skip_drawing = FALSE;2927if (CloseTextureBuffer(prev_fb.status != ci_aux_copy))2928;2929else if (!rdp.fb_drawn)2930{2931CopyFrameBuffer ();2932rdp.fb_drawn = TRUE;2933}2934if (settings.fb_hires)2935OpenTextureBuffer(cur_fb);2936}2937break;2938case ci_old_copy:2939{2940if (!rdp.motionblur || settings.fb_motionblur)2941{2942if (cur_fb.width == rdp.ci_width)2943{2944memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.maincimg[1].addr, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);2945}2946//rdp.skip_drawing = TRUE;2947}2948else2949{2950memset(gfx.RDRAM+cur_fb.addr, 0, (cur_fb.width*cur_fb.height)<<rdp.ci_size>>1);2951}2952}2953break;2954/*2955else if (rdp.frame_buffers[rdp.ci_count].status == ci_main_i)2956{2957// CopyFrameBuffer ();2958rdp.scale_x = rdp.scale_x_bak;2959rdp.scale_y = rdp.scale_y_bak;2960rdp.skip_drawing = FALSE;2961}2962*/2963case ci_aux:2964{2965if (!settings.fb_hires && cur_fb.format != 0)2966rdp.skip_drawing = TRUE;2967else2968{2969rdp.skip_drawing = FALSE;2970if (settings.fb_hires && OpenTextureBuffer(cur_fb))2971;2972else2973{2974if (cur_fb.format != 0)2975rdp.skip_drawing = TRUE;2976if (rdp.ci_count == 0)2977{2978// if (rdp.num_of_ci > 1)2979// {2980rdp.scale_x = 1.0f;2981rdp.scale_y = 1.0f;2982// }2983}2984else if (!settings.fb_hires && (prev_fb.status == ci_main) &&2985(prev_fb.width == cur_fb.width)) // for Pokemon Stadium2986CopyFrameBuffer ();2987}2988}2989cur_fb.status = ci_aux;2990}2991break;2992case ci_zimg:2993// ZIGGY2994// Zelda LoT effect save/restore depth buffer2995if (cur_fb.addr == rdp.zimg) {2996render_depth_mode = 1;2997} else {2998render_depth_mode = 2;2999}3000rdp.skip_drawing = TRUE;3001break;3002case ci_useless:3003//case ci_zcopy:3004rdp.skip_drawing = TRUE;3005break;3006case ci_copy_self:3007if (settings.fb_hires && (rdp.ci_count <= rdp.copy_ci_index) && (!SwapOK || settings.swapmode == 2))3008OpenTextureBuffer(cur_fb);3009rdp.skip_drawing = FALSE;3010/*3011if (settings.fb_hires)3012{3013if (SwapOK)3014{3015rdp.cimg = rdp.frame_buffers[rdp.ci_count].addr;3016rdp.maincimg[0].addr = rdp.cimg;3017newSwapBuffers();3018SwapOK = FALSE;3019OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count]);3020}3021}3022*/3023break;3024default:3025rdp.skip_drawing = FALSE;3026}30273028if ((rdp.ci_count > 0) && (prev_fb.status >= ci_aux)) //for Pokemon Stadium3029{3030if (!settings.fb_hires && prev_fb.format == 0)3031CopyFrameBuffer ();3032}3033if (!settings.fb_hires && cur_fb.status == ci_copy)3034{3035if (!rdp.motionblur && (rdp.num_of_ci > rdp.ci_count+1) && (next_fb.status != ci_aux))3036{3037RestoreScale();3038}3039}3040if (!settings.fb_hires && cur_fb.status == ci_aux)3041{3042if (cur_fb.format == 0)3043{3044if (settings.PPL && (rdp.scale_x < 1.1f)) //need to put current image back to frame buffer3045{3046int width = cur_fb.width;3047int height = cur_fb.height;3048WORD *ptr_dst = new WORD[width*height];3049WORD *ptr_src = (WORD*)(gfx.RDRAM+cur_fb.addr);3050WORD c;30513052for (int y=0; y<height; y++)3053{3054for (int x=0; x<width; x++)3055{3056c = ((ptr_src[(x + y * width)^1]) >> 1) | 0x8000;3057ptr_dst[x + y * width] = c;3058}3059}3060grLfbWriteRegion(GR_BUFFER_BACKBUFFER,30610,30620,3063GR_LFB_SRC_FMT_555,3064width,3065height,3066FXFALSE,3067width<<1,3068ptr_dst);3069delete[] ptr_dst;3070}3071/*3072else //just clear buffer3073{30743075grColorMask(FXTRUE, FXTRUE);3076grBufferClear (0, 0, 0xFFFF);3077}3078*/3079}3080}30813082if ((cur_fb.status == ci_main) && (rdp.ci_count > 0))3083{3084BOOL to_org_res = TRUE;3085for (int i = rdp.ci_count + 1; i < rdp.num_of_ci; i++)3086{3087if ((rdp.frame_buffers[i].status != ci_main) && (rdp.frame_buffers[i].status != ci_zimg) && (rdp.frame_buffers[i].status != ci_zcopy))3088{3089to_org_res = FALSE;3090break;3091}3092}3093if (to_org_res)3094{3095RDP("return to original scale\n");3096rdp.scale_x = rdp.scale_x_bak;3097rdp.scale_y = rdp.scale_y_bak;3098if (settings.fb_hires && !rdp.read_whole_frame)3099CloseTextureBuffer();3100}3101if (settings.fb_hires && !rdp.read_whole_frame && (prev_fb.status >= ci_aux) && (rdp.ci_count > rdp.copy_ci_index))3102CloseTextureBuffer();31033104}3105rdp.ci_status = cur_fb.status;3106rdp.ci_count++;3107}31083109rdp.ocimg = rdp.cimg;3110rdp.cimg = segoffset(rdp.cmd1) & BMASK;3111rdp.ci_width = (rdp.cmd0 & 0xFFF) + 1;3112if (settings.fb_smart)3113rdp.ci_height = rdp.frame_buffers[rdp.ci_count-1].height;3114else if (rdp.ci_width == 32)3115rdp.ci_height = 32;3116else3117rdp.ci_height = rdp.scissor_o.lr_y;3118if (rdp.zimg == rdp.cimg)3119{3120rdp.zi_width = rdp.ci_width;3121// int zi_height = min((int)rdp.zi_width*3/4, (int)rdp.vi_height);3122// rdp.zi_words = rdp.zi_width * zi_height;3123}3124DWORD format = (rdp.cmd0 >> 21) & 0x7;3125rdp.ci_size = (rdp.cmd0 >> 19) & 0x3;3126rdp.ci_end = rdp.cimg + ((rdp.ci_width*rdp.ci_height)<<(rdp.ci_size-1));3127FRDP("setcolorimage - %08lx, width: %d, height: %d, format: %d, size: %d\n", rdp.cmd1, rdp.ci_width, rdp.ci_height, format, rdp.ci_size);3128FRDP("cimg: %08lx, ocimg: %08lx, SwapOK: %d\n", rdp.cimg, rdp.ocimg, SwapOK);31293130if (format != 0 && !rdp.cur_image) //can't draw into non RGBA buffer3131{3132if (settings.fb_hires && rdp.ci_width <= 64)3133OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count - 1]);3134else if (format > 2)3135rdp.skip_drawing = TRUE;3136return;3137}3138else3139{3140if (!settings.fb_smart)3141rdp.skip_drawing = FALSE;3142}31433144CI_SET = TRUE;3145if (settings.swapmode > 0)3146{3147if (rdp.zimg == rdp.cimg)3148rdp.updatescreen = 1;31493150BOOL viSwapOK = ((settings.swapmode == 2) && (rdp.vi_org_reg == *gfx.VI_ORIGIN_REG)) ? FALSE : TRUE;3151if ((rdp.zimg != rdp.cimg) && (rdp.ocimg != rdp.cimg) && SwapOK && viSwapOK && !rdp.cur_image)3152{3153if (settings.fb_smart)3154rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index];3155else3156rdp.maincimg[0].addr = rdp.cimg;3157rdp.last_drawn_ci_addr = (settings.swapmode == 2) ? swapped_addr : rdp.maincimg[0].addr;3158swapped_addr = rdp.cimg;3159newSwapBuffers();3160rdp.vi_org_reg = *gfx.VI_ORIGIN_REG;3161SwapOK = FALSE;3162if (settings.fb_hires)3163{3164if (rdp.copy_ci_index && (rdp.frame_buffers[rdp.ci_count-1].status != ci_zimg))3165{3166int idx = (rdp.frame_buffers[rdp.ci_count].status == ci_aux_copy) ? rdp.main_ci_index : rdp.copy_ci_index;3167FRDP("attempt open tex buffer. status: %s, addr: %08lx\n", CIStatus[rdp.frame_buffers[idx].status], rdp.frame_buffers[idx].addr);3168OpenTextureBuffer(rdp.frame_buffers[idx]);3169if (rdp.frame_buffers[rdp.copy_ci_index].status == ci_main) //tidal wave3170rdp.copy_ci_index = 0;3171}3172else if (rdp.read_whole_frame && !rdp.cur_image)3173{3174OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);3175}3176}3177}3178}3179}31803181static void rdp_trifill()3182{3183RDP_E("trifill - IGNORED\n");3184RDP("trifill - IGNORED\n");3185}31863187static void rdp_trishade()3188{3189RDP_E("trishade - IGNORED\n");3190RDP("trishade - IGNORED\n");3191}31923193static void rdp_tritxtr()3194{3195RDP_E("tritxtr - IGNORED\n");3196RDP("tritxtr - IGNORED\n");3197}31983199static void rdp_trishadetxtr()3200{3201RDP_E("trishadetxtr - IGNORED\n");3202RDP("trishadetxtr - IGNORED\n");3203}32043205static void rdp_trifillz()3206{3207RDP_E("trifillz - IGNORED\n");3208RDP("trifillz - IGNORED\n");3209}32103211static void rdp_trishadez()3212{3213RDP_E("trishadez - IGNORED\n");3214RDP("trishadez - IGNORED\n");3215}32163217static void rdp_tritxtrz()3218{3219RDP_E("tritxtrz - IGNORED\n");3220RDP("tritxtrz - IGNORED\n");3221}32223223static void rdp_trishadetxtrz()3224{3225RDP_E("trishadetxtrz - IGNORED\n");3226RDP("trishadetxtrz - IGNORED\n");3227}32283229static void rsp_reserved0()3230{3231RDP_E("reserved0 - IGNORED\n");3232RDP("reserved0 - IGNORED\n");3233}32343235static void rsp_reserved1()3236{3237RDP("reserved1 - ignored\n");3238}32393240static void rsp_reserved2()3241{3242RDP("reserved2\n");3243}32443245static void rsp_reserved3()3246{3247RDP("reserved3 - ignored\n");3248}32493250void SetWireframeCol ()3251{3252if (!fullscreen) return;32533254switch (settings.wfmode)3255{3256//case 0: // normal colors, don't do anything3257case 1: // vertex colors3258grColorCombine (GR_COMBINE_FUNCTION_LOCAL,3259GR_COMBINE_FACTOR_NONE,3260GR_COMBINE_LOCAL_ITERATED,3261GR_COMBINE_OTHER_NONE,3262FXFALSE);3263grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,3264GR_COMBINE_FACTOR_NONE,3265GR_COMBINE_LOCAL_ITERATED,3266GR_COMBINE_OTHER_NONE,3267FXFALSE);3268grAlphaBlendFunction (GR_BLEND_ONE,3269GR_BLEND_ZERO,3270GR_BLEND_ZERO,3271GR_BLEND_ZERO);3272grTexCombine (GR_TMU0,3273GR_COMBINE_FUNCTION_ZERO,3274GR_COMBINE_FACTOR_NONE,3275GR_COMBINE_FUNCTION_ZERO,3276GR_COMBINE_FACTOR_NONE,3277FXFALSE, FXFALSE);3278grTexCombine (GR_TMU1,3279GR_COMBINE_FUNCTION_ZERO,3280GR_COMBINE_FACTOR_NONE,3281GR_COMBINE_FUNCTION_ZERO,3282GR_COMBINE_FACTOR_NONE,3283FXFALSE, FXFALSE);3284break;3285case 2: // red only3286grColorCombine (GR_COMBINE_FUNCTION_LOCAL,3287GR_COMBINE_FACTOR_NONE,3288GR_COMBINE_LOCAL_CONSTANT,3289GR_COMBINE_OTHER_NONE,3290FXFALSE);3291grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,3292GR_COMBINE_FACTOR_NONE,3293GR_COMBINE_LOCAL_CONSTANT,3294GR_COMBINE_OTHER_NONE,3295FXFALSE);3296grConstantColorValue (0xFF0000FF);3297grAlphaBlendFunction (GR_BLEND_ONE,3298GR_BLEND_ZERO,3299GR_BLEND_ZERO,3300GR_BLEND_ZERO);3301grTexCombine (GR_TMU0,3302GR_COMBINE_FUNCTION_ZERO,3303GR_COMBINE_FACTOR_NONE,3304GR_COMBINE_FUNCTION_ZERO,3305GR_COMBINE_FACTOR_NONE,3306FXFALSE, FXFALSE);3307grTexCombine (GR_TMU1,3308GR_COMBINE_FUNCTION_ZERO,3309GR_COMBINE_FACTOR_NONE,3310GR_COMBINE_FUNCTION_ZERO,3311GR_COMBINE_FACTOR_NONE,3312FXFALSE, FXFALSE);3313break;3314}33153316grAlphaTestFunction (GR_CMP_ALWAYS);3317grCullMode (GR_CULL_DISABLE);33183319//grDepthBufferFunction (GR_CMP_ALWAYS);3320//grDepthMask (FXFALSE);33213322rdp.update |= UPDATE_COMBINE | UPDATE_ALPHA_COMPARE;3323}33243325#ifdef __cplusplus3326extern "C" {3327#endif33283329/******************************************************************3330Function: FrameBufferRead3331Purpose: This function is called to notify the dll that the3332frame buffer memory is beening read at the given address.3333DLL should copy content from its render buffer to the frame buffer3334in N64 RDRAM3335DLL is responsible to maintain its own frame buffer memory addr list3336DLL should copy 4KB block content back to RDRAM frame buffer.3337Emulator should not call this function again if other memory3338is read within the same 4KB range3339input: addr rdram address3340val val3341size 1 = BYTE, 2 = WORD, 4 = DWORD3342output: none3343*******************************************************************/3344EXPORT void CALL FBRead(unsigned int addr)3345{3346LOG ("FBRead ()\n");33473348if (cpu_fb_ignore)3349return;3350if (cpu_fb_write_called)3351{3352cpu_fb_ignore = TRUE;3353cpu_fb_write = FALSE;3354return;3355}3356cpu_fb_read_called = TRUE;3357DWORD a = segoffset(addr);3358FRDP("FBRead. addr: %08lx\n", a);3359if (!rdp.fb_drawn && (a >= rdp.cimg) && (a < rdp.ci_end))3360{3361fbreads_back++;3362//if (fbreads_back > 2) //&& (rdp.ci_width <= 320))3363{3364CopyFrameBuffer ();3365rdp.fb_drawn = TRUE;3366}3367}3368if (!rdp.fb_drawn_front && (a >= rdp.maincimg[1].addr) && (a < rdp.maincimg[1].addr + rdp.ci_width*rdp.ci_height*2))3369{3370fbreads_front++;3371//if (fbreads_front > 2)//&& (rdp.ci_width <= 320))3372{3373DWORD cimg = rdp.cimg;3374rdp.cimg = rdp.maincimg[1].addr;3375if (settings.fb_smart)3376{3377rdp.ci_width = rdp.maincimg[1].width;3378rdp.ci_count = 0;3379DWORD h = rdp.frame_buffers[0].height;3380rdp.frame_buffers[0].height = rdp.maincimg[1].height;3381CopyFrameBuffer(GR_BUFFER_FRONTBUFFER);3382rdp.frame_buffers[0].height = h;3383}3384else3385{3386CopyFrameBuffer(GR_BUFFER_FRONTBUFFER);3387}3388rdp.cimg = cimg;3389rdp.fb_drawn_front = TRUE;3390}3391}3392}33933394#if 03395//TODO: remove3396/******************************************************************3397Function: FrameBufferWriteList3398Purpose: This function is called to notify the dll that the3399frame buffer has been modified by CPU at the given address.3400input: FrameBufferModifyEntry *plist3401size = size of the plist, max = 10243402output: none3403*******************************************************************/3404EXPORT void CALL FBWList(FrameBufferModifyEntry *plist, DWORD size)3405{3406LOG ("FBWList ()\n");3407FRDP("FBWList. size: %d\n", size);3408printf("FBWList. size: %d\n", size);3409}3410#endif34113412/******************************************************************3413Function: FrameBufferWrite3414Purpose: This function is called to notify the dll that the3415frame buffer has been modified by CPU at the given address.3416input: addr rdram address3417val val3418size 1 = BYTE, 2 = WORD, 4 = DWORD3419output: none3420*******************************************************************/3421EXPORT void CALL FBWrite(unsigned int addr, unsigned int size)3422{3423LOG ("FBWrite ()\n");3424if (cpu_fb_ignore)3425return;3426if (cpu_fb_read_called)3427{3428cpu_fb_ignore = TRUE;3429cpu_fb_write = FALSE;3430return;3431}3432cpu_fb_write_called = TRUE;3433DWORD a = segoffset(addr);3434FRDP("FBWrite. addr: %08lx\n", a);3435// ZIGGY : added a test on ci_width, otherwise we crash on zero division below3436if (!rdp.ci_width || a < rdp.cimg || a > rdp.ci_end)3437return;3438cpu_fb_write = TRUE;3439DWORD shift_l = (a-rdp.cimg) >> 1;3440DWORD shift_r = shift_l+2;34413442d_ul_x = min(d_ul_x, shift_l%rdp.ci_width);3443d_ul_y = min(d_ul_y, shift_l/rdp.ci_width);3444d_lr_x = max(d_lr_x, shift_r%rdp.ci_width);3445d_lr_y = max(d_lr_y, shift_r/rdp.ci_width);3446}344734483449/************************************************************************3450Function: FBGetFrameBufferInfo3451Purpose: This function is called by the emulator core to retrieve frame3452buffer information from the video plugin in order to be able3453to notify the video plugin about CPU frame buffer read/write3454operations34553456size:3457= 1 byte3458= 2 word (16 bit) <-- this is N64 default depth buffer format3459= 4 dword (32 bit)34603461when frame buffer information is not available yet, set all values3462in the FrameBufferInfo structure to 034633464input: FrameBufferInfo pinfo[6]3465pinfo is pointed to a FrameBufferInfo structure which to be3466filled in by this function3467output: Values are return in the FrameBufferInfo structure3468Plugin can return up to 6 frame buffer info3469************************************************************************/3470///*3471#if 03472//TODO: remove3473typedef struct3474{3475DWORD addr;3476DWORD size;3477DWORD width;3478DWORD height;3479} FrameBufferInfo;3480#endif34813482EXPORT void CALL FBGetFrameBufferInfo(void *p)3483{3484LOG ("FBGetFrameBufferInfo ()\n");3485FrameBufferInfo * pinfo = (FrameBufferInfo *)p;3486memset(pinfo,0,sizeof(FrameBufferInfo)*6);3487if (!settings.fb_get_info)3488return;3489RDP("FBGetFrameBufferInfo ()\n");3490//*3491if (settings.fb_smart)3492{3493pinfo[0].addr = rdp.maincimg[1].addr;3494pinfo[0].size = rdp.maincimg[1].size;3495pinfo[0].width = rdp.maincimg[1].width;3496pinfo[0].height = rdp.maincimg[1].height;3497int info_index = 1;3498for (int i = 0; i < rdp.num_of_ci && info_index < 6; i++)3499{3500COLOR_IMAGE & cur_fb = rdp.frame_buffers[i];3501if (cur_fb.status == ci_main || cur_fb.status == ci_copy_self ||3502cur_fb.status == ci_old_copy)3503{3504pinfo[info_index].addr = cur_fb.addr;3505pinfo[info_index].size = cur_fb.size;3506pinfo[info_index].width = cur_fb.width;3507pinfo[info_index].height = cur_fb.height;3508info_index++;3509}3510}3511}3512else3513{3514pinfo[0].addr = rdp.maincimg[0].addr;3515pinfo[0].size = rdp.ci_size;3516pinfo[0].width = rdp.ci_width;3517pinfo[0].height = rdp.ci_width*3/4;3518pinfo[1].addr = rdp.maincimg[1].addr;3519pinfo[1].size = rdp.ci_size;3520pinfo[1].width = rdp.ci_width;3521pinfo[1].height = rdp.ci_width*3/4;3522}3523//*/3524}3525#ifdef __cplusplus3526}3527#endif35283529//*/3530#include "UcodeFB.h"35313532void DetectFrameBufferUsage ()3533{3534RDP("DetectFrameBufferUsage\n");35353536DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0);3537#ifdef _WIN323538DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4);3539#endif // _WIN323540DWORD a;35413542BOOL tidal = FALSE;3543if (settings.PM && (rdp.copy_ci_index || rdp.frame_buffers[rdp.copy_ci_index].status == ci_copy_self))3544tidal = TRUE;3545DWORD ci = rdp.cimg, zi = rdp.zimg; // ci_width = rdp.ci_width;3546rdp.main_ci = rdp.main_ci_end = rdp.main_ci_bg = rdp.ci_count = 0;3547rdp.main_ci_index = rdp.copy_ci_index = 0;3548rdp.zimg_end = 0;3549rdp.tmpzimg = 0;3550rdp.motionblur = FALSE;3551rdp.main_ci_last_tex_addr = 0;3552BOOL previous_ci_was_read = rdp.read_previous_ci;3553rdp.read_previous_ci = FALSE;3554rdp.read_whole_frame = FALSE;3555rdp.swap_ci_index = rdp.black_ci_index = -1;3556SwapOK = TRUE;35573558// Start executing at the start of the display list3559rdp.pc_i = 0;3560rdp.pc[rdp.pc_i] = dlist_start;3561rdp.dl_count = -1;3562rdp.halt = 0;3563rdp.scale_x_bak = rdp.scale_x;3564rdp.scale_y_bak = rdp.scale_y;35653566// MAIN PROCESSING LOOP3567do {35683569// Get the address of the next command3570a = rdp.pc[rdp.pc_i] & BMASK;35713572// Load the next command and its input3573rdp.cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit3574rdp.cmd1 = ((DWORD*)gfx.RDRAM)[(a>>2)+1]; // /35753576// Output the address before the command35773578// Go to the next instruction3579rdp.pc[rdp.pc_i] = (a+8) & BMASK;35803581if ((intptr_t)(gfx_instruction_lite[settings.ucode][rdp.cmd0>>24]))3582gfx_instruction_lite[settings.ucode][rdp.cmd0>>24] ();35833584// check DL counter3585if (rdp.dl_count != -1)3586{3587rdp.dl_count --;3588if (rdp.dl_count == 0)3589{3590rdp.dl_count = -1;35913592RDP ("End of DL\n");3593rdp.pc_i --;3594}3595}35963597} while (!rdp.halt);3598SwapOK = TRUE;3599if (rdp.ci_count > NUMTEXBUF) //overflow3600{3601rdp.cimg = ci;3602rdp.zimg = zi;3603rdp.num_of_ci = rdp.ci_count;3604rdp.scale_x = rdp.scale_x_bak;3605rdp.scale_y = rdp.scale_y_bak;3606return;3607}36083609if (rdp.black_ci_index > 0 && rdp.black_ci_index < rdp.copy_ci_index)3610rdp.frame_buffers[rdp.black_ci_index].status = ci_main;36113612if (rdp.frame_buffers[rdp.ci_count-1].status == ci_unknown)3613{3614if (rdp.ci_count > 1)3615rdp.frame_buffers[rdp.ci_count-1].status = ci_aux;3616else3617rdp.frame_buffers[rdp.ci_count-1].status = ci_main;3618}36193620if ((rdp.frame_buffers[rdp.ci_count-1].status == ci_aux) &&3621(rdp.frame_buffers[rdp.main_ci_index].width < 320) &&3622(rdp.frame_buffers[rdp.ci_count-1].width > rdp.frame_buffers[rdp.main_ci_index].width))3623{3624for (int i = 0; i < rdp.ci_count; i++)3625{3626if (rdp.frame_buffers[i].status == ci_main)3627rdp.frame_buffers[i].status = ci_aux;3628else if (rdp.frame_buffers[i].addr == rdp.frame_buffers[rdp.ci_count-1].addr)3629rdp.frame_buffers[i].status = ci_main;3630// FRDP("rdp.frame_buffers[%d].status = %d\n", i, rdp.frame_buffers[i].status);3631}3632rdp.main_ci_index = rdp.ci_count-1;3633}36343635BOOL all_zimg = TRUE;3636int i;3637for (i = 0; i < rdp.ci_count; i++)3638{3639if (rdp.frame_buffers[i].status != ci_zimg)3640{3641all_zimg = FALSE;3642break;3643}3644}3645if (all_zimg)3646{3647for (i = 0; i < rdp.ci_count; i++)3648rdp.frame_buffers[i].status = ci_main;3649}36503651RDP("detect fb final results: \n");3652for (i = 0; i < rdp.ci_count; i++)3653{3654FRDP("rdp.frame_buffers[%d].status = %s, addr: %08lx, height: %d\n", i, CIStatus[rdp.frame_buffers[i].status], rdp.frame_buffers[i].addr, rdp.frame_buffers[i].height);3655}36563657rdp.cimg = ci;3658rdp.zimg = zi;3659rdp.num_of_ci = rdp.ci_count;3660if (rdp.read_previous_ci && previous_ci_was_read)3661if (!settings.fb_hires || !rdp.copy_ci_index)3662rdp.motionblur = TRUE;3663if (rdp.motionblur || settings.fb_hires || (rdp.frame_buffers[rdp.copy_ci_index].status == ci_aux_copy))3664{3665rdp.scale_x = rdp.scale_x_bak;3666rdp.scale_y = rdp.scale_y_bak;3667}36683669if ((rdp.read_previous_ci || previous_ci_was_read) && !rdp.copy_ci_index)3670rdp.read_whole_frame = TRUE;3671if (rdp.read_whole_frame)3672{3673if (settings.fb_hires && !settings.fb_ignore_previous)3674{3675if (rdp.swap_ci_index < 0)3676{3677rdp.texbufs[0].clear_allowed = TRUE;3678OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);3679}3680}3681else3682{3683if (rdp.motionblur)3684{3685if (settings.fb_motionblur)3686CopyFrameBuffer();3687else3688memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size);3689}3690else //if (ci_width == rdp.frame_buffers[rdp.main_ci_index].width)3691{3692if (rdp.maincimg[0].height > 65) //for 10803693{3694rdp.cimg = rdp.maincimg[0].addr;3695rdp.ci_width = rdp.maincimg[0].width;3696rdp.ci_count = 0;3697DWORD h = rdp.frame_buffers[0].height;3698rdp.frame_buffers[0].height = rdp.maincimg[0].height;3699CopyFrameBuffer();3700rdp.frame_buffers[0].height = h;3701}3702else //conker3703{3704CopyFrameBuffer();3705}3706}3707}3708}37093710if (settings.fb_hires)3711{3712for (i = 0; i < num_tmu; i++)3713{3714rdp.texbufs[i].clear_allowed = TRUE;3715for (int j = 0; j < 256; j++)3716{3717rdp.texbufs[i].images[j].drawn = FALSE;3718rdp.texbufs[i].images[j].clear = TRUE;3719}3720}3721if (tidal)3722{3723//RDP("Tidal wave!\n");3724rdp.copy_ci_index = rdp.main_ci_index;3725}3726}3727rdp.ci_count = 0;3728if (settings.fb_ignore_previous)3729rdp.read_whole_frame = FALSE;3730else3731rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index];3732// rdp.scale_x = rdp.scale_x_bak;3733// rdp.scale_y = rdp.scale_y_bak;3734RDP("DetectFrameBufferUsage End\n");3735}37363737373837393740#ifdef __cplusplus3741extern "C" {3742#endif37433744/******************************************************************3745Function: ProcessRDPList3746Purpose: This function is called when there is a Dlist to be3747processed. (Low level GFX list)3748input: none3749output: none3750*******************************************************************/3751EXPORT void CALL ProcessRDPList(void)3752{3753if (settings.KI)3754{3755*gfx.MI_INTR_REG |= 0x20;3756gfx.CheckInterrupts();3757}3758LOG ("ProcessRDPList ()\n");37593760no_dlist = FALSE;3761update_screen_count = 0;3762ChangeSize ();37633764#ifdef ALTTAB_FIX3765if (!hhkLowLevelKybd)3766{3767hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL,3768LowLevelKeyboardProc, hInstance, 0);3769}3770#endif37713772LOG ("ProcessDList ()\n");37733774if (!fullscreen)3775{3776drawNoFullscreenMessage();3777// Set an interrupt to allow the game to continue3778*gfx.MI_INTR_REG |= 0x20;3779gfx.CheckInterrupts();3780}37813782if (reset)3783{3784reset = 0;37853786memset (microcode, 0, 4096);3787if (settings.autodetect_ucode)3788{3789// Thanks to ZeZu for ucode autodetection!!!37903791DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0);3792memcpy (microcode, gfx.RDRAM+startUcode, 4096);3793microcheck ();37943795}3796}3797else if ( ((old_ucode == 6) && (settings.ucode == 1)) || settings.force_microcheck)3798{3799DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0);3800memcpy (microcode, gfx.RDRAM+startUcode, 4096);3801microcheck ();3802}38033804if (exception) return;38053806// Switch to fullscreen?3807if (to_fullscreen)3808{3809to_fullscreen = FALSE;38103811if (!InitGfx (FALSE))3812{3813LOG ("FAILED!!!\n");3814return;3815}3816fullscreen = TRUE;3817}38183819// Clear out the RDP log3820#ifdef RDP_LOGGING3821if (settings.logging && settings.log_clear)3822{3823CLOSE_RDP_LOG ();3824OPEN_RDP_LOG ();3825}3826#endif38273828#ifdef UNIMP_LOG3829if (settings.log_unk && settings.unk_clear)3830{3831std::ofstream unimp;3832unimp.open("unimp.txt");3833unimp.close();3834}3835#endif38363837//* Set states *//3838if (settings.swapmode > 0)3839SwapOK = TRUE;3840rdp.updatescreen = 1;38413842rdp.tri_n = 0; // 0 triangles so far this frame3843rdp.debug_n = 0;38443845rdp.model_i = 0; // 0 matrices so far in stack3846//stack_size can be less then 32! Important for Silicon Vally. Thanks Orkin!3847rdp.model_stack_size = min(32, (*(DWORD*)(gfx.DMEM+0x0FE4))>>6);3848if (rdp.model_stack_size == 0)3849rdp.model_stack_size = 32;3850rdp.fb_drawn = rdp.fb_drawn_front = FALSE;3851rdp.update = 0x7FFFFFFF; // All but clear cache3852rdp.geom_mode = 0;3853rdp.acmp = 0;3854rdp.maincimg[1] = rdp.maincimg[0];3855rdp.skip_drawing = FALSE;3856rdp.s2dex_tex_loaded = FALSE;3857fbreads_front = fbreads_back = 0;3858rdp.fog_multiplier = rdp.fog_offset = 0;3859rdp.zsrc = 0;38603861if (cpu_fb_write == TRUE)3862DrawFrameBufferToScreen();3863cpu_fb_write = FALSE;3864cpu_fb_read_called = FALSE;3865cpu_fb_write_called = FALSE;3866cpu_fb_ignore = FALSE;3867d_ul_x = 0xffff;3868d_ul_y = 0xffff;3869d_lr_x = 0;3870d_lr_y = 0;38713872//analize possible frame buffer usage3873if (settings.fb_smart)3874DetectFrameBufferUsage();3875if (!settings.lego || rdp.num_of_ci > 1)3876rdp.last_bg = 0;3877//* End of set states *//387838793880// Get the start of the display list and the length of it3881// DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0);3882// DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4);3883DWORD dlist_start = *gfx.DPC_CURRENT_REG;3884DWORD dlist_length = *gfx.DPC_END_REG - *gfx.DPC_CURRENT_REG;3885FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_lenght: %d\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length);3886FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG);38873888if (settings.tonic && dlist_length < 16)3889{3890rdp_fullsync();3891FRDP_E("DLIST is too short!\n");3892return;3893}38943895// Start executing at the start of the display list3896rdp.pc_i = 0;3897rdp.pc[rdp.pc_i] = dlist_start;3898rdp.dl_count = -1;3899rdp.halt = 0;3900DWORD a;39013902// catches exceptions so that it doesn't freeze3903#ifdef CATCH_EXCEPTIONS3904try {3905#endif39063907// MAIN PROCESSING LOOP3908do {39093910// Get the address of the next command3911a = rdp.pc[rdp.pc_i] & BMASK;39123913// Load the next command and its input3914rdp.cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit3915rdp.cmd1 = ((DWORD*)gfx.RDRAM)[(a>>2)+1]; // /3916// cmd2 and cmd3 are filled only when needed, by the function that needs them39173918// Output the address before the command3919#ifdef LOG_COMMANDS3920FRDP ("%08lx (c0:%08lx, c1:%08lx): ", a, rdp.cmd0, rdp.cmd1);3921#else3922FRDP ("%08lx: ", a);3923#endif39243925// Go to the next instruction3926rdp.pc[rdp.pc_i] = (a+8) & BMASK;39273928#ifdef PERFORMANCE3929QueryPerformanceCounter ((LARGE_INTEGER*)&perf_cur);3930#endif3931// Process this instruction3932gfx_instruction[settings.ucode][((rdp.cmd0>>24)&0x3f) + 0x100-0x40] ();39333934// check DL counter3935if (rdp.dl_count != -1)3936{3937rdp.dl_count --;3938if (rdp.dl_count == 0)3939{3940rdp.dl_count = -1;39413942RDP ("End of DL\n");3943rdp.pc_i --;3944}3945}39463947#ifdef PERFORMANCE3948QueryPerformanceCounter ((LARGE_INTEGER*)&perf_next);3949__int64 t = perf_next-perf_cur;3950sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, t);3951rdp_log << out_buf;3952#endif39533954} while (0);3955#ifdef CATCH_EXCEPTIONS3956} catch (...) {39573958if (fullscreen) ReleaseGfx ();3959WriteLog(M64MSG_ERROR, "The GFX plugin caused an exception and has been disabled.");3960exception = TRUE;3961}3962#endif39633964if (settings.fb_smart)3965{3966rdp.scale_x = rdp.scale_x_bak;3967rdp.scale_y = rdp.scale_y_bak;3968}3969if (settings.fb_read_always)3970{3971CopyFrameBuffer ();3972}3973if (rdp.yuv_image)3974{3975DrawYUVImageToFrameBuffer();3976rdp.yuv_image = FALSE;3977// FRDP("yuv image draw. ul_x: %f, ul_y: %f, lr_x: %f, lr_y: %f, begin: %08lx\n",3978// rdp.yuv_ul_x, rdp.yuv_ul_y, rdp.yuv_lr_x, rdp.yuv_lr_y, rdp.yuv_im_begin);3979rdp.yuv_ul_x = rdp.yuv_ul_y = rdp.yuv_lr_x = rdp.yuv_lr_y = 0;3980rdp.yuv_im_begin = 0x00FFFFFF;3981}3982if (rdp.cur_image)3983CloseTextureBuffer(rdp.read_whole_frame && (settings.PM || rdp.swap_ci_index >= 0));39843985if (settings.TGR2 && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET)3986{3987newSwapBuffers ();3988CI_SET = FALSE;3989}3990RDP("ProcessDList end\n");3991399239933994399539963997WriteLog(M64MSG_VERBOSE, "ProcessRPDList %x %x %x\n",3998*gfx.DPC_START_REG,3999*gfx.DPC_END_REG,4000*gfx.DPC_CURRENT_REG);4001//*gfx.DPC_STATUS_REG = 0xffffffff; // &= ~0x0002;40024003*gfx.DPC_START_REG = *gfx.DPC_END_REG;4004*gfx.DPC_CURRENT_REG = *gfx.DPC_END_REG;4005}40064007#ifdef __cplusplus4008}4009#endif401040114012401340144015// Local Variables: ***4016// tab-width:4 ***4017// c-file-offset:4 ***4018// End: ***4019402040214022