Path: blob/master/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/rdp.cpp
2 views
/*1* Glide64 - Glide video plugin for Nintendo 64 emulators.2* Copyright (c) 2002 Dave20013* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA18*/1920//****************************************************************21//22// Glide64 - Glide Plugin for Nintendo 64 emulators23// Project started on December 29th, 200124//25// Authors:26// Dave2001, original author, founded the project in 2001, left it in 200227// Gugaman, joined the project in 2002, left it in 200228// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 200229// Hiroshi 'KoolSmoky' Morii, joined the project in 200730//31//****************************************************************32//33// To modify Glide64:34// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.35// * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all.36//37//****************************************************************3839#include <math.h>40#include "Gfx_1.3.h"41#include "m64p.h"42#include "Config.h"43#include "3dmath.h"44#include "Util.h"45#include "Debugger.h"46#include "Combine.h"47#include "TexCache.h"48#include "TexBuffer.h"49#include "FBtoScreen.h"50#include "CRC.h"5152/*53const int NumOfFormats = 3;54SCREEN_SHOT_FORMAT ScreenShotFormats[NumOfFormats] = { {wxT("BMP"), wxT("bmp"), wxBITMAP_TYPE_BMP}, {wxT("PNG"), wxT("png"), wxBITMAP_TYPE_PNG}, {wxT("JPEG"), wxT("jpeg"), wxBITMAP_TYPE_JPEG} };55*/56const char *ACmp[] = { "NONE", "THRESHOLD", "UNKNOWN", "DITHER" };5758const char *Mode0[] = { "COMBINED", "TEXEL0",59"TEXEL1", "PRIMITIVE",60"SHADE", "ENVIORNMENT",61"1", "NOISE",62"0", "0",63"0", "0",64"0", "0",65"0", "0" };6667const char *Mode1[] = { "COMBINED", "TEXEL0",68"TEXEL1", "PRIMITIVE",69"SHADE", "ENVIORNMENT",70"CENTER", "K4",71"0", "0",72"0", "0",73"0", "0",74"0", "0" };7576const char *Mode2[] = { "COMBINED", "TEXEL0",77"TEXEL1", "PRIMITIVE",78"SHADE", "ENVIORNMENT",79"SCALE", "COMBINED_ALPHA",80"T0_ALPHA", "T1_ALPHA",81"PRIM_ALPHA", "SHADE_ALPHA",82"ENV_ALPHA", "LOD_FRACTION",83"PRIM_LODFRAC", "K5",84"0", "0",85"0", "0",86"0", "0",87"0", "0",88"0", "0",89"0", "0",90"0", "0",91"0", "0" };9293const char *Mode3[] = { "COMBINED", "TEXEL0",94"TEXEL1", "PRIMITIVE",95"SHADE", "ENVIORNMENT",96"1", "0" };9798const char *Alpha0[] = { "COMBINED", "TEXEL0",99"TEXEL1", "PRIMITIVE",100"SHADE", "ENVIORNMENT",101"1", "0" };102103#define Alpha1 Alpha0104const char *Alpha2[] = { "LOD_FRACTION", "TEXEL0",105"TEXEL1", "PRIMITIVE",106"SHADE", "ENVIORNMENT",107"PRIM_LODFRAC", "0" };108#define Alpha3 Alpha0109110const char *FBLa[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG" };111const char *FBLb[] = { "G_BL_A_IN", "G_BL_A_FOG", "G_BL_A_SHADE", "G_BL_0" };112const char *FBLc[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG"};113const char *FBLd[] = { "G_BL_1MA", "G_BL_A_MEM", "G_BL_1", "G_BL_0" };114115const char *str_zs[] = { "G_ZS_PIXEL", "G_ZS_PRIM" };116117const char *str_yn[] = { "NO", "YES" };118const char *str_offon[] = { "OFF", "ON" };119120const char *str_cull[] = { "DISABLE", "FRONT", "BACK", "BOTH" };121122// I=intensity probably123const char *str_format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" };124const char *str_size[] = { "4bit", "8bit", "16bit", "32bit" };125const char *str_cm[] = { "WRAP/NO CLAMP", "MIRROR/NO CLAMP", "WRAP/CLAMP", "MIRROR/CLAMP" };126const char *str_lod[] = { "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "2048" };127const char *str_aspect[] = { "1x8", "1x4", "1x2", "1x1", "2x1", "4x1", "8x1" };128129const char *str_filter[] = { "Point Sampled", "Average (box)", "Bilinear" };130131const char *str_tlut[] = { "TT_NONE", "TT_UNKNOWN", "TT_RGBA_16", "TT_IA_16" };132133const char *str_dither[] = { "Pattern", "~Pattern", "Noise", "None" };134135const char *CIStatus[] = { "ci_main", "ci_zimg", "ci_unknown", "ci_useless",136"ci_old_copy", "ci_copy", "ci_copy_self",137"ci_zcopy", "ci_aux", "ci_aux_copy" };138139typedef struct140{141int ucode;142int crc;143} UcodeData;144145static UcodeData UcodeList[] =146{147{0, 0x006bd77f},148{2, 0x03044b84},149{2, 0x030f4b84},150{1, 0x05165579},151{1, 0x05777c62},152{1, 0x057e7c62},153{0, 0x07200895},154{9, 0x0bf36d36},155{-1, 0x0d7bbffb},156{5, 0x0d7cbffb},157{2, 0x0ff79527},158{-1, 0x0ff795bf},159{1, 0x1118b3e0},160{1, 0x1517a281},161{2, 0x168e9cd5},162{2, 0x1a1e18a0},163{2, 0x1a1e1920},164{2, 0x1a62dbaf},165{2, 0x1a62dc2f},166{1, 0x1de712ff},167{6, 0x1ea9e30f},168{21, 0x1f120bbb},169{2, 0x21f91834},170{2, 0x21f91874},171{2, 0x22099872},172{1, 0x24cd885b},173{1, 0x26a7879a},174{6, 0x299d5072},175{2, 0x2b291027},176{6, 0x2b5a89c2},177{1, 0x2c7975d6},178{1, 0x2d3fe3f1},179{2, 0x2f71d1d5},180{2, 0x2f7dd1d5},181{1, 0x327b933d},182{1, 0x339872a6},183{2, 0x377359b6},184{0, 0x3a1c2b34},185{0, 0x3a1cbac3},186{0, 0x3f7247fb},187{1, 0x3ff1a4ca},188{0, 0x4165e1fd},189{1, 0x4340ac9b},190{1, 0x440cfad6},191{7, 0x47d46e86},192{2, 0x485abff2},193{1, 0x4fe6df78},194{0, 0x5182f610},195{1, 0x5257cd2a},196{1, 0x5414030c},197{1, 0x5414030d},198{1, 0x559ff7d4},199{4, 0x5b5d36e3},200{3, 0x5b5d3763},201{0, 0x5d1d6f53},202{2, 0x5d3099f1},203{1, 0x5df1408c},204{1, 0x5ef4e34a},205{1, 0x6075e9eb},206{1, 0x60c1dcc4},207{2, 0x6124a508},208{2, 0x630a61fb},209{5, 0x63be08b1},210{5, 0x63be08b3},211{1, 0x64ed27e5},212{2, 0x65201989},213{2, 0x65201a09},214{1, 0x66c0b10a},215{2, 0x679e1205},216{6, 0x6bb745c9},217{2, 0x6d8f8f8a},218{0, 0x6e4d50af},219{1, 0x6eaa1da8},220{1, 0x72a4f34e},221{1, 0x73999a23},222{6, 0x74af0a74},223{2, 0x753be4a5},224{6, 0x794c3e28},225{1, 0x7df75834},226{1, 0x7f2d0a2e},227{1, 0x82f48073},228{1, 0x832fcb99},229{1, 0x841ce10f},230{-1, 0x844b55b5},231{1, 0x863e1ca7},232{-1, 0x86b1593e},233{1, 0x8805ffea},234{1, 0x8d5735b2},235{1, 0x8d5735b3},236{-1, 0x8ec3e124},237{2, 0x93d11f7b},238{2, 0x93d11ffb},239{2, 0x93d1ff7b},240{2, 0x9551177b},241{2, 0x955117fb},242{2, 0x95cd0062},243{1, 0x97d1b58a},244{2, 0xa2d0f88e},245{1, 0xa346a5cc},246{2, 0xaa86cb1d},247{2, 0xaae4a5b9},248{2, 0xad0a6292},249{2, 0xad0a6312},250{0, 0xae08d5b9},251{1, 0xb1821ed3},252{1, 0xb4577b9c},253{0, 0xb54e7f93},254{2, 0xb62f900f},255{2, 0xba65ea1e},256{8, 0xba86cb1d},257{0, 0xbc03e969},258{2, 0xbc45382e},259{1, 0xbe78677c},260{1, 0xbed8b069},261{1, 0xc3704e41},262{1, 0xc46dbc3d},263{1, 0xc99a4c6c},264{2, 0xc901ce73},265{2, 0xc901cef3},266{2, 0xcb8c9b6c},267{1, 0xcee7920f},268{2, 0xcfa35a45},269{1, 0xd1663234},270{6, 0xd20dedbf},271{1, 0xd2a9f59c},272{1, 0xd41db5f7},273{0, 0xd5604971},274{1, 0xd57049a5},275{-1, 0xd5c4dc96},276{0, 0xd5d68b1f},277{0, 0xd67c2f8b},278{1, 0xd802ec04},279{2, 0xda13ab96},280{2, 0xde7d67d4},281{2, 0xe1290fa2},282{0, 0xe41ec47e},283{2, 0xe65cb4ad},284{1, 0xe89c2b92},285{1, 0xe9231df2},286{1, 0xec040469},287{1, 0xee47381b},288{1, 0xef54ee35},289{21, 0xf9893f70},290{1, 0xfb816260},291{21, 0xff372492}292};293294//static variables295296char out_buf[2048];297298wxUint32 frame_count; // frame counter299300int ucode_error_report = TRUE;301int wrong_tile = -1;302303// ** RDP graphics functions **304static void undef();305static void spnoop();306307static void rdp_noop();308static void rdp_texrect();309//static void rdp_texrectflip();310static void rdp_loadsync();311static void rdp_pipesync();312static void rdp_tilesync();313static void rdp_fullsync();314static void rdp_setkeygb();315static void rdp_setkeyr();316static void rdp_setconvert();317static void rdp_setscissor();318static void rdp_setprimdepth();319static void rdp_setothermode();320static void rdp_loadtlut();321static void rdp_settilesize();322static void rdp_loadblock();323static void rdp_loadtile();324static void rdp_settile();325static void rdp_fillrect();326static void rdp_setfillcolor();327static void rdp_setfogcolor();328static void rdp_setblendcolor();329static void rdp_setprimcolor();330static void rdp_setenvcolor();331static void rdp_setcombine();332static void rdp_settextureimage();333static void rdp_setdepthimage();334static void rdp_setcolorimage();335static void rdp_trifill();336static void rdp_trishade();337static void rdp_tritxtr();338static void rdp_trishadetxtr();339static void rdp_trifillz();340static void rdp_trishadez();341static void rdp_tritxtrz();342static void rdp_trishadetxtrz();343static void rdphalf_1();344static void rdphalf_2();345static void rdphalf_cont();346347static void rsp_reserved0();348static void rsp_reserved1();349static void rsp_reserved2();350static void rsp_reserved3();351352static void ys_memrect();353354wxUint8 microcode[4096];355wxUint32 uc_crc;356void microcheck ();357358// ** UCODE FUNCTIONS **359#include "ucode00.h"360#include "ucode01.h"361#include "ucode02.h"362#include "ucode03.h"363#include "ucode04.h"364#include "ucode05.h"365#include "ucode06.h"366#include "ucode07.h"367#include "ucode08.h"368#include "ucode09.h"369#include "ucode.h"370#include "ucode09rdp.h"371#include "turbo3D.h"372373static int reset = 0;374static int old_ucode = -1;375376void RDP::Reset()377{378memset(this, 0, sizeof(RDP_Base));379// set all vertex numbers380for (int i=0; i<MAX_VTX; i++)381vtx[i].number = i;382383scissor_o.ul_x = 0;384scissor_o.ul_y = 0;385scissor_o.lr_x = 320;386scissor_o.lr_y = 240;387388vi_org_reg = *gfx.VI_ORIGIN_REG;389view_scale[2] = 32.0f * 511.0f;390view_trans[2] = 32.0f * 511.0f;391clip_ratio = 1.0f;392393lookat[0][0] = lookat[1][1] = 1.0f;394395cycle_mode = 2;396allow_combine = 1;397rdp.update = UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE;398fog_mode = RDP::fog_enabled;399maincimg[0].addr = maincimg[1].addr = last_drawn_ci_addr = 0x7FFFFFFF;400401hotkey_info.hk_ref = 90;402hotkey_info.hk_motionblur = (settings.buff_clear == 0)?0:90;403hotkey_info.hk_filtering = hotkey_info.hk_motionblur;404405CheckKeyPressed(G64_VK_BACK, 1); //BACK406CheckKeyPressed(G64_VK_B, 1);407CheckKeyPressed(G64_VK_V, 1);408}409410RDP::RDP()411{412vtx1 = new VERTEX[256];413memset(vtx1, 0, sizeof(VERTEX)*256);414vtx2 = new VERTEX[256];415memset(vtx2, 0, sizeof(VERTEX)*256);416vtxbuf = vtxbuf2 = 0;417vtx_buffer = n_global = 0;418419for (int i = 0; i < MAX_TMU; i++)420{421cache[i] = new CACHE_LUT[MAX_CACHE];422cur_cache[i] = 0;423cur_cache_n[i] = 0;424};425426vtx = new VERTEX[MAX_VTX];427memset(vtx, 0, sizeof(VERTEX)*MAX_VTX);428v0 = vn = 0;429430frame_buffers = new COLOR_IMAGE[NUMTEXBUF+2];431}432433RDP::~RDP()434{435delete[] vtx1;436delete[] vtx2;437for (int i = 0; i < MAX_TMU; i++)438delete[] cache[i];439440delete[] vtx;441delete[] frame_buffers;442}443444void rdp_reset ()445{446reset = 1;447rdp.Reset();448}449450int LookupUcode (int crc)451{452for (int i = 0; i < sizeof(UcodeList)/sizeof(UcodeData); i++)453{454if (crc == UcodeList[i].crc)455{456return UcodeList[i].ucode;457}458}459460return -2;461}462463void microcheck ()464{465wxUint32 i;466uc_crc = 0;467468// Check first 3k of ucode, because the last 1k sometimes contains trash469for (i=0; i<3072>>2; i++)470{471uc_crc += ((wxUint32*)microcode)[i];472}473474FRDP_E ("crc: %08lx\n", uc_crc);475476#ifdef LOG_UCODE477std::ofstream ucf;478ucf.open ("ucode.txt", std::ios::out | std::ios::binary);479char d;480for (i=0; i<0x400000; i++)481{482d = ((char*)gfx.RDRAM)[i^3];483ucf.write (&d, 1);484}485ucf.close ();486#endif487488FRDP("ucode = %08lx\n", uc_crc);489490int uc = LookupUcode(uc_crc);491492if (uc == -2 && ucode_error_report)493{494settings.ucode = Config_ReadInt("ucode", "Force microcode", 0, TRUE, FALSE);495496ReleaseGfx ();497ERRLOG("Error: uCode crc not found in INI, using currently selected uCode\n\n%08lx", (unsigned long)uc_crc);498499ucode_error_report = FALSE; // don't report any more ucode errors from this game500}501else if (uc == -1 && ucode_error_report)502{503settings.ucode = 2; //ini->Read(_T("/SETTINGS/ucode"), 0);504505ReleaseGfx ();506ERRLOG("Error: Unsupported uCode!\n\ncrc: %08lx", (unsigned long)uc_crc);507508ucode_error_report = FALSE; // don't report any more ucode errors from this game509}510else511{512old_ucode = settings.ucode;513settings.ucode = uc;514FRDP("microcheck: old ucode: %d, new ucode: %d\n", old_ucode, uc);515if (uc_crc == 0x8d5735b2 || uc_crc == 0xb1821ed3 || uc_crc == 0x1118b3e0) //F3DLP.Rej ucode. perspective texture correction is not implemented516{517rdp.Persp_en = 1;518rdp.persp_supported = FALSE;519}520else if (settings.texture_correction)521rdp.persp_supported = TRUE;522}523}524525#ifdef __WINDOWS__526static void GetClientSize(int * width, int * height)527{528#ifdef __WINDOWS__529RECT win_rect;530GetClientRect (gfx.hWnd, &win_rect);531*width = win_rect.right;532*height = win_rect.bottom;533#else534GFXWindow->GetClientSize(width, height);535#endif536}537#endif538539void drawNoFullscreenMessage()540{541//need to find, how to do it on non-windows OS542//the code below will compile on any OS543//but it works only on windows, because544//I don't know, how to initialize GFXWindow on other OS545#ifdef __WINDOWS__546LOG ("drawNoFullscreenMessage ()\n");547if (rdp.window_changed)548{549rdp.window_changed = FALSE;550int width, height;551GetClientSize(&width, &height);552553wxClientDC dc(GFXWindow);554dc.SetBrush(*wxMEDIUM_GREY_BRUSH);555dc.SetTextForeground(*wxWHITE);556dc.SetBackgroundMode(wxTRANSPARENT);557dc.DrawRectangle(0, 0, width, height);558559wxCoord w, h;560wxString text = wxT("Glide64mk2");561dc.GetTextExtent(text, &w, &h);562wxCoord x = (width - w)/2;563wxCoord y = height/2 - h*4;564dc.DrawText(text, x, y);565566text = wxT("Gfx cannot be drawn in windowed mode");567dc.GetTextExtent(text, &w, &h);568x = (width - w)/2;569y = height/2 - h;570dc.DrawText(text, x, y);571572text = wxT("Press Alt+Enter to switch to fullscreen");573dc.GetTextExtent(text, &w, &h);574x = (width - w)/2;575y = (height - h)/2 + h*2;576dc.DrawText(text, x, y);577}578#endif579}580581static wxUint32 d_ul_x, d_ul_y, d_lr_x, d_lr_y;582583static void DrawPartFrameBufferToScreen()584{585FB_TO_SCREEN_INFO fb_info;586fb_info.addr = rdp.cimg;587fb_info.size = rdp.ci_size;588fb_info.width = rdp.ci_width;589fb_info.height = rdp.ci_height;590fb_info.ul_x = d_ul_x;591fb_info.lr_x = d_lr_x;592fb_info.ul_y = d_ul_y;593fb_info.lr_y = d_lr_y;594fb_info.opaque = 0;595DrawFrameBufferToScreen(fb_info);596memset(gfx.RDRAM+rdp.cimg, 0, (rdp.ci_width*rdp.ci_height)<<rdp.ci_size>>1);597}598599#define RGBA16TO32(color) \600((color&1)?0xFF:0) | \601((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | \602((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | \603((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8)604605static void CopyFrameBuffer (GrBuffer_t buffer = GR_BUFFER_BACKBUFFER)606{607if (!fullscreen)608return;609FRDP ("CopyFrameBuffer: %08lx... ", rdp.cimg);610611// don't bother to write the stuff in asm... the slow part is the read from video card,612// not the copy.613614wxUint32 width = rdp.ci_width;//*gfx.VI_WIDTH_REG;615wxUint32 height;616if (fb_emulation_enabled && !(settings.hacks&hack_PPL))617{618int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0;619height = rdp.frame_buffers[ind].height;620}621else622{623height = rdp.ci_lower_bound;624if (settings.hacks&hack_PPL)625height -= rdp.ci_upper_bound;626}627FRDP ("width: %d, height: %d... ", width, height);628629if (rdp.scale_x < 1.1f)630{631wxUint16 * ptr_src = new wxUint16[width*height];632if (grLfbReadRegion(buffer,633(wxUint32)rdp.offset_x,634(wxUint32)rdp.offset_y,//rdp.ci_upper_bound,635width,636height,637width<<1,638ptr_src))639{640wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg);641wxUint32 *ptr_dst32 = (wxUint32*)(gfx.RDRAM+rdp.cimg);642wxUint16 c;643644for (wxUint32 y=0; y<height; y++)645{646for (wxUint32 x=0; x<width; x++)647{648c = ptr_src[x + y * width];649if (settings.frame_buffer&fb_read_alpha)650{651if (c > 0)652c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;653}654else655{656c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;657}658if (rdp.ci_size == 2)659ptr_dst[(x + y * width)^1] = c;660else661ptr_dst32[x + y * width] = RGBA16TO32(c);662}663}664LRDP("ReadRegion. Framebuffer copy complete.\n");665}666else667{668LRDP("Framebuffer copy failed.\n");669}670delete[] ptr_src;671}672else673{674if (rdp.motionblur && fb_hwfbe_enabled)675{676return;677}678else679{680float scale_x = (settings.scr_res_x - rdp.offset_x*2.0f) / max(width, rdp.vi_width);681float scale_y = (settings.scr_res_y - rdp.offset_y*2.0f) / max(height, rdp.vi_height);682683FRDP("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);684GrLfbInfo_t info;685info.size = sizeof(GrLfbInfo_t);686687if (grLfbLock (GR_LFB_READ_ONLY,688buffer,689GR_LFBWRITEMODE_565,690GR_ORIGIN_UPPER_LEFT,691FXFALSE,692&info))693{694wxUint16 *ptr_src = (wxUint16*)info.lfbPtr;695wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg);696wxUint32 *ptr_dst32 = (wxUint32*)(gfx.RDRAM+rdp.cimg);697wxUint16 c;698wxUint32 stride = info.strideInBytes>>1;699700int read_alpha = settings.frame_buffer & fb_read_alpha;701if ((settings.hacks&hack_PMario) && rdp.frame_buffers[rdp.ci_count-1].status != ci_aux)702read_alpha = FALSE;703int x_start = 0, y_start = 0, x_end = width, y_end = height;704if (settings.hacks&hack_BAR)705{706x_start = 80, y_start = 24, x_end = 240, y_end = 86;707}708for (int y=y_start; y<y_end; y++)709{710for (int x=x_start; x<x_end; x++)711{712c = ptr_src[int(x*scale_x + rdp.offset_x) + int(y * scale_y + rdp.offset_y) * stride];713c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;714if (read_alpha && c == 1)715c = 0;716if (rdp.ci_size <= 2)717ptr_dst[(x + y * width)^1] = c;718else719ptr_dst32[x + y * width] = RGBA16TO32(c);720}721}722723// Unlock the backbuffer724grLfbUnlock (GR_LFB_READ_ONLY, buffer);725LRDP("LfbLock. Framebuffer copy complete.\n");726}727else728{729LRDP("Framebuffer copy failed.\n");730}731}732}733}734735void GoToFullScreen()736{737//if (!InitGfx ())738{739LOG ("FAILED!!!\n");740return;741}742}743744class SoftLocker745{746public:747// lock the mutex in the ctor748SoftLocker(SDL_sem *mutex)749: _isOk(false), _mutex(mutex)750{ _isOk = ( SDL_SemTryWait(_mutex) == 0 ); }751752// returns true if mutex was successfully locked in ctor753bool IsOk() const754{ return _isOk; }755756// unlock the mutex in dtor757~SoftLocker()758{ if ( IsOk() ) SDL_SemPost(_mutex); }759760private:761bool _isOk;762SDL_sem *_mutex;763};764765766/******************************************************************767Function: ProcessDList768Purpose: This function is called when there is a Dlist to be769processed. (High level GFX list)770input: none771output: none772*******************************************************************/773void DetectFrameBufferUsage ();774wxUint32 fbreads_front = 0;775wxUint32 fbreads_back = 0;776int cpu_fb_read_called = FALSE;777int cpu_fb_write_called = FALSE;778int cpu_fb_write = FALSE;779int cpu_fb_ignore = FALSE;780int CI_SET = TRUE;781wxUint32 ucode5_texshiftaddr = 0;782wxUint32 ucode5_texshiftcount = 0;783wxUint16 ucode5_texshift = 0;784int depth_buffer_fog;785786#ifdef __cplusplus787extern "C" {788#endif789790791EXPORT void CALL ProcessDList(void)792{793SoftLocker lock(mutexProcessDList);794if (!lock.IsOk()) //mutex is busy795{796if (!fullscreen)797drawNoFullscreenMessage();798// Set an interrupt to allow the game to continue799*gfx.MI_INTR_REG |= 0x20;800gfx.CheckInterrupts();801return;802}803804no_dlist = false;805update_screen_count = 0;806ChangeSize ();807808#ifdef ALTTAB_FIX809if (!hhkLowLevelKybd)810{811hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL,812LowLevelKeyboardProc, NULL, 0);813}814#endif815816VLOG ("ProcessDList ()\n");817818if (!fullscreen)819{820drawNoFullscreenMessage();821// Set an interrupt to allow the game to continue822*gfx.MI_INTR_REG |= 0x20;823gfx.CheckInterrupts();824}825826if (reset)827{828reset = 0;829if (settings.autodetect_ucode)830{831// Thanks to ZeZu for ucode autodetection!!!832wxUint32 startUcode = *(wxUint32*)(gfx.DMEM+0xFD0);833memcpy (microcode, gfx.RDRAM+startUcode, 4096);834microcheck ();835}836else837memset (microcode, 0, 4096);838}839else if ( ((old_ucode == ucode_S2DEX) && (settings.ucode == ucode_F3DEX)) || settings.force_microcheck)840{841wxUint32 startUcode = *(wxUint32*)(gfx.DMEM+0xFD0);842memcpy (microcode, gfx.RDRAM+startUcode, 4096);843microcheck ();844}845846if (exception)847return;848849// Switch to fullscreen?850if (to_fullscreen)851GoToFullScreen();852853if (!fullscreen && !settings.run_in_window)854return;855856// Clear out the RDP log857#ifdef RDP_LOGGING858if (settings.logging && settings.log_clear)859{860CLOSE_RDP_LOG ();861OPEN_RDP_LOG ();862}863#endif864865#ifdef UNIMP_LOG866if (settings.log_unk && settings.unk_clear)867{868std::ofstream unimp;869unimp.open("unimp.txt");870unimp.close();871}872#endif873874//* Set states *//875if (settings.swapmode > 0)876SwapOK = TRUE;877rdp.updatescreen = 1;878879rdp.tri_n = 0; // 0 triangles so far this frame880rdp.debug_n = 0;881882rdp.model_i = 0; // 0 matrices so far in stack883//stack_size can be less then 32! Important for Silicon Vally. Thanks Orkin!884rdp.model_stack_size = min(32, (*(wxUint32*)(gfx.DMEM+0x0FE4))>>6);885if (rdp.model_stack_size == 0)886rdp.model_stack_size = 32;887rdp.Persp_en = TRUE;888rdp.fb_drawn = rdp.fb_drawn_front = FALSE;889rdp.update = 0x7FFFFFFF; // All but clear cache890rdp.geom_mode = 0;891rdp.acmp = 0;892rdp.maincimg[1] = rdp.maincimg[0];893rdp.skip_drawing = FALSE;894rdp.s2dex_tex_loaded = FALSE;895rdp.bg_image_height = 0xFFFF;896fbreads_front = fbreads_back = 0;897rdp.fog_multiplier = rdp.fog_offset = 0;898rdp.zsrc = 0;899if (rdp.vi_org_reg != *gfx.VI_ORIGIN_REG)900rdp.tlut_mode = 0; //is it correct?901rdp.scissor_set = FALSE;902ucode5_texshiftaddr = ucode5_texshiftcount = 0;903cpu_fb_write = FALSE;904cpu_fb_read_called = FALSE;905cpu_fb_write_called = FALSE;906cpu_fb_ignore = FALSE;907d_ul_x = 0xffff;908d_ul_y = 0xffff;909d_lr_x = 0;910d_lr_y = 0;911depth_buffer_fog = TRUE;912913//analize possible frame buffer usage914if (fb_emulation_enabled)915DetectFrameBufferUsage();916if (!(settings.hacks&hack_Lego) || rdp.num_of_ci > 1)917rdp.last_bg = 0;918//* End of set states *//919920// Get the start of the display list and the length of it921wxUint32 dlist_start = *(wxUint32*)(gfx.DMEM+0xFF0);922wxUint32 dlist_length = *(wxUint32*)(gfx.DMEM+0xFF4);923FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_length: %d, x_scale: %f, y_scale: %f\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length, (*gfx.VI_X_SCALE_REG & 0xFFF)/1024.0f, (*gfx.VI_Y_SCALE_REG & 0xFFF)/1024.0f);924FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG);925926if (cpu_fb_write == TRUE)927DrawPartFrameBufferToScreen();928if ((settings.hacks&hack_Tonic) && dlist_length < 16)929{930rdp_fullsync();931FRDP_E("DLIST is too short!\n");932return;933}934935// Start executing at the start of the display list936rdp.pc_i = 0;937rdp.pc[rdp.pc_i] = dlist_start;938rdp.dl_count = -1;939rdp.halt = 0;940wxUint32 a;941942// catches exceptions so that it doesn't freeze943#ifdef CATCH_EXCEPTIONS944try {945#endif946if (settings.ucode == ucode_Turbo3d)947{948Turbo3D();949}950else951{952// MAIN PROCESSING LOOP953do {954955// Get the address of the next command956a = rdp.pc[rdp.pc_i] & BMASK;957958// Load the next command and its input959rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit960rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // /961// cmd2 and cmd3 are filled only when needed, by the function that needs them962963// Output the address before the command964#ifdef LOG_COMMANDS965FRDP ("%08lx (c0:%08lx, c1:%08lx): ", a, rdp.cmd0, rdp.cmd1);966#else967FRDP ("%08lx: ", a);968#endif969970// Go to the next instruction971rdp.pc[rdp.pc_i] = (a+8) & BMASK;972973#ifdef PERFORMANCE974perf_cur = wxDateTime::UNow();975#endif976// Process this instruction977gfx_instruction[settings.ucode][rdp.cmd0>>24] ();978979// check DL counter980if (rdp.dl_count != -1)981{982rdp.dl_count --;983if (rdp.dl_count == 0)984{985rdp.dl_count = -1;986987LRDP("End of DL\n");988rdp.pc_i --;989}990}991992#ifdef PERFORMANCE993perf_next = wxDateTime::UNow();994sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, (perf_next-perf_cur).Format(_T("%l")).mb_str());995rdp_log << out_buf;996#endif997998} while (!rdp.halt);999}1000#ifdef CATCH_EXCEPTIONS1001} catch (...) {10021003if (fullscreen)1004{1005ReleaseGfx ();1006rdp_reset ();1007#ifdef TEXTURE_FILTER1008if (settings.ghq_use)1009{1010ext_ghq_shutdown();1011settings.ghq_use = 0;1012}1013#endif1014}1015ERRLOG("The GFX plugin caused an exception and has been disabled.");1016exception = TRUE;1017return;1018}1019#endif10201021if (fb_emulation_enabled)1022{1023rdp.scale_x = rdp.scale_x_bak;1024rdp.scale_y = rdp.scale_y_bak;1025}1026if (settings.frame_buffer & fb_ref)1027CopyFrameBuffer ();1028if (rdp.cur_image)1029CloseTextureBuffer(rdp.read_whole_frame && ((settings.hacks&hack_PMario) || rdp.swap_ci_index >= 0));10301031if ((settings.hacks&hack_TGR2) && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET)1032{1033newSwapBuffers ();1034CI_SET = FALSE;1035}1036LRDP("ProcessDList end\n");1037}10381039#ifdef __cplusplus1040}1041#endif10421043// undef - undefined instruction, always ignore1044static void undef()1045{1046FRDP_E("** undefined ** (%08lx)\n", rdp.cmd0);1047FRDP("** undefined ** (%08lx) - IGNORED\n", rdp.cmd0);1048#ifdef _ENDUSER_RELEASE_1049*gfx.MI_INTR_REG |= 0x20;1050gfx.CheckInterrupts();1051rdp.halt = 1;1052#endif1053}10541055// spnoop - no operation, always ignore1056static void spnoop()1057{1058LRDP("spnoop\n");1059}10601061// noop - no operation, always ignore1062static void rdp_noop()1063{1064LRDP("noop\n");1065}10661067static void ys_memrect ()1068{1069wxUint32 tile = (wxUint16)((rdp.cmd1 & 0x07000000) >> 24);10701071wxUint32 lr_x = (wxUint16)((rdp.cmd0 & 0x00FFF000) >> 14);1072wxUint32 lr_y = (wxUint16)((rdp.cmd0 & 0x00000FFF) >> 2);1073wxUint32 ul_x = (wxUint16)((rdp.cmd1 & 0x00FFF000) >> 14);1074wxUint32 ul_y = (wxUint16)((rdp.cmd1 & 0x00000FFF) >> 2);10751076if (lr_y > rdp.scissor_o.lr_y)1077lr_y = rdp.scissor_o.lr_y;1078wxUint32 off_x = ((rdp.cmd2 & 0xFFFF0000) >> 16) >> 5;1079wxUint32 off_y = (rdp.cmd2 & 0x0000FFFF) >> 5;10801081FRDP ("memrect (%d, %d, %d, %d), ci_width: %d", ul_x, ul_y, lr_x, lr_y, rdp.ci_width);1082if (off_x > 0)1083FRDP (" off_x: %d", off_x);1084if (off_y > 0)1085FRDP (" off_y: %d", off_y);1086LRDP("\n");10871088wxUint32 y, width = lr_x - ul_x;1089wxUint32 tex_width = rdp.tiles[tile].line << 3;1090wxUint8 * texaddr = gfx.RDRAM + rdp.addr[rdp.tiles[tile].t_mem] + tex_width*off_y + off_x;1091wxUint8 * fbaddr = gfx.RDRAM + rdp.cimg + ul_x;10921093for (y = ul_y; y < lr_y; y++) {1094wxUint8 *src = texaddr + (y - ul_y) * tex_width;1095wxUint8 *dst = fbaddr + y * rdp.ci_width;1096memcpy (dst, src, width);1097}1098}10991100static void pm_palette_mod ()1101{1102wxUint8 envr = (wxUint8)((float)((rdp.env_color >> 24)&0xFF)/255.0f*31.0f);1103wxUint8 envg = (wxUint8)((float)((rdp.env_color >> 16)&0xFF)/255.0f*31.0f);1104wxUint8 envb = (wxUint8)((float)((rdp.env_color >> 8)&0xFF)/255.0f*31.0f);1105wxUint16 env16 = (wxUint16)((envr<<11)|(envg<<6)|(envb<<1)|1);1106wxUint8 prmr = (wxUint8)((float)((rdp.prim_color >> 24)&0xFF)/255.0f*31.0f);1107wxUint8 prmg = (wxUint8)((float)((rdp.prim_color >> 16)&0xFF)/255.0f*31.0f);1108wxUint8 prmb = (wxUint8)((float)((rdp.prim_color >> 8)&0xFF)/255.0f*31.0f);1109wxUint16 prim16 = (wxUint16)((prmr<<11)|(prmg<<6)|(prmb<<1)|1);1110wxUint16 * dst = (wxUint16*)(gfx.RDRAM+rdp.cimg);1111for (int i = 0; i < 16; i++)1112{1113dst[i^1] = (rdp.pal_8[i]&1) ? prim16 : env16;1114}1115LRDP("Texrect palette modification\n");1116}11171118static void pd_zcopy ()1119{1120wxUint16 ul_x = (wxUint16)((rdp.cmd1 & 0x00FFF000) >> 14);1121wxUint16 lr_x = (wxUint16)((rdp.cmd0 & 0x00FFF000) >> 14) + 1;1122wxUint16 ul_u = (wxUint16)((rdp.cmd2 & 0xFFFF0000) >> 21) + 1;1123wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg);1124wxUint16 width = lr_x - ul_x;1125wxUint16 * ptr_src = ((wxUint16*)rdp.tmem)+ul_u;1126wxUint16 c;1127for (wxUint16 x=0; x<width; x++)1128{1129c = ptr_src[x];1130c = ((c<<8)&0xFF00) | (c >> 8);1131ptr_dst[(ul_x+x)^1] = c;1132// FRDP("dst[%d]=%04lx \n", (x + ul_x)^1, c);1133}1134}11351136static void DrawDepthBufferFog()1137{1138if (rdp.zi_width < 200)1139return;1140FB_TO_SCREEN_INFO fb_info;1141fb_info.addr = rdp.zimg;1142fb_info.size = 2;1143fb_info.width = rdp.zi_width;1144fb_info.height = rdp.ci_height;1145fb_info.ul_x = rdp.scissor_o.ul_x;1146fb_info.lr_x = rdp.scissor_o.lr_x;1147fb_info.ul_y = rdp.scissor_o.ul_y;1148fb_info.lr_y = rdp.scissor_o.lr_y;1149fb_info.opaque = 0;1150DrawDepthBufferToScreen(fb_info);1151}11521153static void rdp_texrect()1154{1155if (!rdp.LLE)1156{1157wxUint32 a = rdp.pc[rdp.pc_i];1158wxUint8 cmdHalf1 = gfx.RDRAM[a+3];1159wxUint8 cmdHalf2 = gfx.RDRAM[a+11];1160a >>= 2;1161if ((cmdHalf1 == 0xE1 && cmdHalf2 == 0xF1) || (cmdHalf1 == 0xB4 && cmdHalf2 == 0xB3) || (cmdHalf1 == 0xB3 && cmdHalf2 == 0xB2))1162{1163//gSPTextureRectangle1164rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a+1];1165rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a+3];1166rdp.pc[rdp.pc_i] += 16;1167}1168else1169{1170//gDPTextureRectangle1171if (settings.hacks&hack_ASB)1172rdp.cmd2 = 0;1173else1174rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a+0];1175rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a+1];1176rdp.pc[rdp.pc_i] += 8;1177}1178}1179if ((settings.hacks&hack_Yoshi) && settings.ucode == ucode_S2DEX)1180{1181ys_memrect();1182return;1183}11841185if (rdp.skip_drawing || (!fb_emulation_enabled && (rdp.cimg == rdp.zimg)))1186{1187if ((settings.hacks&hack_PMario) && rdp.ci_status == ci_useless)1188{1189pm_palette_mod ();1190}1191else1192{1193LRDP("Texrect skipped\n");1194}1195return;1196}11971198if ((settings.ucode == ucode_CBFD) && rdp.cur_image && rdp.cur_image->format)1199{1200//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);1201LRDP("Shadow texrect is skipped.\n");1202rdp.tri_n += 2;1203return;1204}12051206if ((settings.ucode == ucode_PerfectDark) && (rdp.frame_buffers[rdp.ci_count-1].status == ci_zcopy))1207{1208pd_zcopy ();1209LRDP("Depth buffer copied.\n");1210rdp.tri_n += 2;1211return;1212}12131214if ((rdp.othermode_l >> 16) == 0x3c18 && rdp.cycle1 == 0x03ffffff && rdp.cycle2 == 0x01ff1fff) //depth image based fog1215{1216if (!depth_buffer_fog)1217return;1218if (settings.fog)1219DrawDepthBufferFog();1220depth_buffer_fog = FALSE;1221return;1222}12231224// FRDP ("rdp.cycle1 %08lx, rdp.cycle2 %08lx\n", rdp.cycle1, rdp.cycle2);12251226float ul_x, ul_y, lr_x, lr_y;1227if (rdp.cycle_mode == 2)1228{1229ul_x = max(0.0f, (short)((rdp.cmd1 & 0x00FFF000) >> 14));1230ul_y = max(0.0f, (short)((rdp.cmd1 & 0x00000FFF) >> 2));1231lr_x = max(0.0f, (short)((rdp.cmd0 & 0x00FFF000) >> 14));1232lr_y = max(0.0f, (short)((rdp.cmd0 & 0x00000FFF) >> 2));1233}1234else1235{1236ul_x = max(0.0f, ((short)((rdp.cmd1 & 0x00FFF000) >> 12)) / 4.0f);1237ul_y = max(0.0f, ((short)(rdp.cmd1 & 0x00000FFF)) / 4.0f);1238lr_x = max(0.0f, ((short)((rdp.cmd0 & 0x00FFF000) >> 12)) / 4.0f);1239lr_y = max(0.0f, ((short)(rdp.cmd0 & 0x00000FFF)) / 4.0f);1240}12411242if (ul_x >= lr_x)1243{1244FRDP("Wrong Texrect: ul_x: %f, lr_x: %f\n", ul_x, lr_x);1245return;1246}12471248if (rdp.cycle_mode > 1)1249{1250lr_x += 1.0f;1251lr_y += 1.0f;1252} else if (lr_y - ul_y < 1.0f)1253lr_y = ceil(lr_y);12541255if (settings.increase_texrect_edge)1256{1257if (floor(lr_x) != lr_x)1258lr_x = ceil(lr_x);1259if (floor(lr_y) != lr_y)1260lr_y = ceil(lr_y);1261}12621263//*1264if (rdp.tbuff_tex && (settings.frame_buffer & fb_optimize_texrect))1265{1266LRDP("Attempt to optimize texrect\n");1267if (!rdp.tbuff_tex->drawn)1268{1269DRAWIMAGE d;1270d.imageX = 0;1271d.imageW = (wxUint16)rdp.tbuff_tex->width;1272d.frameX = (wxUint16)ul_x;1273d.frameW = (wxUint16)(rdp.tbuff_tex->width);12741275d.imageY = 0;1276d.imageH = (wxUint16)rdp.tbuff_tex->height;1277d.frameY = (wxUint16)ul_y;1278d.frameH = (wxUint16)(rdp.tbuff_tex->height);1279FRDP("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.tbuff_tex->width, rdp.tbuff_tex->height);1280d.scaleX = 1.0f;1281d.scaleY = 1.0f;1282DrawHiresImage(d, rdp.tbuff_tex->width == rdp.ci_width);1283rdp.tbuff_tex->drawn = TRUE;1284}1285return;1286}1287//*/1288// framebuffer workaround for Zelda: MM LOT1289if ((rdp.othermode_l & 0xFFFF0000) == 0x0f5a0000)1290return;12911292/*Gonetz*/1293//hack for Zelda MM. it removes black texrects which cover all geometry in "Link meets Zelda" cut scene1294if ((settings.hacks&hack_Zelda) && rdp.timg.addr >= rdp.cimg && rdp.timg.addr < rdp.ci_end)1295{1296FRDP("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);1297rdp.tri_n += 2;1298return;1299}1300//*1301//hack for Banjo2. it removes black texrects under Banjo1302if (!fb_hwfbe_enabled && ((rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF)) == 0xFFFFFFFF && (rdp.othermode_l & 0xFFFF0000) == 0x00500000)1303{1304rdp.tri_n += 2;1305return;1306}1307//*/1308//*1309//remove motion blur in night vision1310if ((settings.ucode == ucode_PerfectDark) && (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)))1311{1312if (fb_emulation_enabled)1313if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self)1314{1315//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);1316LRDP("Wrong Texrect.\n");1317rdp.tri_n += 2;1318return;1319}1320}1321//*/13221323int i;13241325wxUint32 tile = (wxUint16)((rdp.cmd1 & 0x07000000) >> 24);13261327rdp.texrecting = 1;13281329wxUint32 prev_tile = rdp.cur_tile;1330rdp.cur_tile = tile;13311332const float Z = set_sprite_combine_mode ();13331334rdp.texrecting = 0;13351336if (!rdp.cur_cache[0])1337{1338rdp.cur_tile = prev_tile;1339rdp.tri_n += 2;1340return;1341}1342// ****1343// ** Texrect offset by Gugaman **1344//1345//integer representation of texture coordinate.1346//needed to detect and avoid overflow after shifting1347wxInt32 off_x_i = (rdp.cmd2 >> 16) & 0xFFFF;1348wxInt32 off_y_i = rdp.cmd2 & 0xFFFF;1349float dsdx = (float)((short)((rdp.cmd3 & 0xFFFF0000) >> 16)) / 1024.0f;1350float dtdy = (float)((short)(rdp.cmd3 & 0x0000FFFF)) / 1024.0f;1351if (off_x_i & 0x8000) //check for sign bit1352off_x_i |= ~0xffff; //make it negative1353//the same as for off_x_i1354if (off_y_i & 0x8000)1355off_y_i |= ~0xffff;13561357if (rdp.cycle_mode == 2)1358dsdx /= 4.0f;13591360float s_ul_x = ul_x * rdp.scale_x + rdp.offset_x;1361float s_lr_x = lr_x * rdp.scale_x + rdp.offset_x;1362float s_ul_y = ul_y * rdp.scale_y + rdp.offset_y;1363float s_lr_y = lr_y * rdp.scale_y + rdp.offset_y;13641365FRDP("texrect (%.2f, %.2f, %.2f, %.2f), tile: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, tile, rdp.tri_n, rdp.tri_n+1);1366FRDP ("(%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);1367FRDP("\toff_x: %f, off_y: %f, dsdx: %f, dtdy: %f\n", off_x_i/32.0f, off_y_i/32.0f, dsdx, dtdy);13681369float off_size_x;1370float off_size_y;13711372if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip1373{1374#ifdef TEXTURE_FILTER1375if (rdp.cur_cache[0]->is_hires_tex)1376{1377off_size_x = (float)((lr_y - ul_y) * dsdx);1378off_size_y = (float)((lr_x - ul_x) * dtdy);1379}1380else1381#endif1382{1383off_size_x = (lr_y - ul_y - 1) * dsdx;1384off_size_y = (lr_x - ul_x - 1) * dtdy;1385}1386}1387else1388{1389#ifdef TEXTURE_FILTER1390if (rdp.cur_cache[0]->is_hires_tex)1391{1392off_size_x = (float)((lr_x - ul_x) * dsdx);1393off_size_y = (float)((lr_y - ul_y) * dtdy);1394}1395else1396#endif1397{1398off_size_x = (lr_x - ul_x - 1) * dsdx;1399off_size_y = (lr_y - ul_y - 1) * dtdy;1400}1401}14021403struct {1404float ul_u, ul_v, lr_u, lr_v;1405} texUV[2]; //struct for texture coordinates1406//angrylion's macro, helps to cut overflowed values.1407#define SIGN16(x) (((x) & 0x8000) ? ((x) | ~0xffff) : ((x) & 0xffff))14081409//calculate texture coordinates1410for (int i = 0; i < 2; i++)1411{1412if (rdp.cur_cache[i] && (rdp.tex & (i+1)))1413{1414float sx = 1, sy = 1;1415int x_i = off_x_i, y_i = off_y_i;1416TILE & tile = rdp.tiles[rdp.cur_tile + i];1417//shifting1418if (tile.shift_s)1419{1420if (tile.shift_s > 10)1421{1422wxUint8 iShift = (16 - tile.shift_s);1423x_i <<= iShift;1424sx = (float)(1 << iShift);1425}1426else1427{1428wxUint8 iShift = tile.shift_s;1429x_i >>= iShift;1430sx = 1.0f/(float)(1 << iShift);1431}1432}1433if (tile.shift_t)1434{1435if (tile.shift_t > 10)1436{1437wxUint8 iShift = (16 - tile.shift_t);1438y_i <<= iShift;1439sy = (float)(1 << iShift);1440}1441else1442{1443wxUint8 iShift = tile.shift_t;1444y_i >>= iShift;1445sy = 1.0f/(float)(1 << iShift);1446}1447}14481449if (rdp.aTBuffTex[i]) //hwfbe texture1450{1451float t0_off_x;1452float t0_off_y;1453if (off_x_i + off_y_i == 0)1454{1455t0_off_x = tile.ul_s;1456t0_off_y = tile.ul_t;1457}1458else1459{1460t0_off_x = off_x_i/32.0f;1461t0_off_y = off_y_i/32.0f;1462}1463t0_off_x += rdp.aTBuffTex[i]->u_shift;// + tile.ul_s; //commented for Paper Mario motion blur1464t0_off_y += rdp.aTBuffTex[i]->v_shift;// + tile.ul_t;1465texUV[i].ul_u = t0_off_x * sx;1466texUV[i].ul_v = t0_off_y * sy;14671468texUV[i].lr_u = texUV[i].ul_u + off_size_x * sx;1469texUV[i].lr_v = texUV[i].ul_v + off_size_y * sy;14701471texUV[i].ul_u *= rdp.aTBuffTex[i]->u_scale;1472texUV[i].ul_v *= rdp.aTBuffTex[i]->v_scale;1473texUV[i].lr_u *= rdp.aTBuffTex[i]->u_scale;1474texUV[i].lr_v *= rdp.aTBuffTex[i]->v_scale;1475FRDP("tbuff_tex[%d] ul_u: %f, ul_v: %f, lr_u: %f, lr_v: %f\n",1476i, texUV[i].ul_u, texUV[i].ul_v, texUV[i].lr_u, texUV[i].lr_v);1477}1478else //common case1479{1480//kill 10.5 format overflow by SIGN16 macro1481texUV[i].ul_u = SIGN16(x_i) / 32.0f;1482texUV[i].ul_v = SIGN16(y_i) / 32.0f;14831484texUV[i].ul_u -= tile.f_ul_s;1485texUV[i].ul_v -= tile.f_ul_t;14861487texUV[i].lr_u = texUV[i].ul_u + off_size_x * sx;1488texUV[i].lr_v = texUV[i].ul_v + off_size_y * sy;14891490texUV[i].ul_u = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_x * texUV[i].ul_u;1491texUV[i].lr_u = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_x * texUV[i].lr_u;1492texUV[i].ul_v = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_y * texUV[i].ul_v;1493texUV[i].lr_v = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_y * texUV[i].lr_v;1494}1495}1496else1497{1498texUV[i].ul_u = texUV[i].ul_v = texUV[i].lr_u = texUV[i].lr_v = 0;1499}1500}1501rdp.cur_tile = prev_tile;15021503// ****15041505FRDP (" scissor: (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);15061507CCLIP2 (s_ul_x, s_lr_x, texUV[0].ul_u, texUV[0].lr_u, texUV[1].ul_u, texUV[1].lr_u, (float)rdp.scissor.ul_x, (float)rdp.scissor.lr_x);1508CCLIP2 (s_ul_y, s_lr_y, texUV[0].ul_v, texUV[0].lr_v, texUV[1].ul_v, texUV[1].lr_v, (float)rdp.scissor.ul_y, (float)rdp.scissor.lr_y);15091510FRDP (" draw at: (%f, %f) -> (%f, %f)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y);15111512VERTEX vstd[4] = {1513{ s_ul_x, s_ul_y, Z, 1.0f, texUV[0].ul_u, texUV[0].ul_v, texUV[1].ul_u, texUV[1].ul_v, {0, 0, 0, 0}, 255 },1514{ s_lr_x, s_ul_y, Z, 1.0f, texUV[0].lr_u, texUV[0].ul_v, texUV[1].lr_u, texUV[1].ul_v, {0, 0, 0, 0}, 255 },1515{ s_ul_x, s_lr_y, Z, 1.0f, texUV[0].ul_u, texUV[0].lr_v, texUV[1].ul_u, texUV[1].lr_v, {0, 0, 0, 0}, 255 },1516{ s_lr_x, s_lr_y, Z, 1.0f, texUV[0].lr_u, texUV[0].lr_v, texUV[1].lr_u, texUV[1].lr_v, {0, 0, 0, 0}, 255 } };15171518if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip1519{1520vstd[1].u0 = texUV[0].ul_u;1521vstd[1].v0 = texUV[0].lr_v;1522vstd[1].u1 = texUV[1].ul_u;1523vstd[1].v1 = texUV[1].lr_v;15241525vstd[2].u0 = texUV[0].lr_u;1526vstd[2].v0 = texUV[0].ul_v;1527vstd[2].u1 = texUV[1].lr_u;1528vstd[2].v1 = texUV[1].ul_v;1529}15301531VERTEX *vptr = vstd;1532int n_vertices = 4;15331534VERTEX *vnew = 0;1535// for (int j =0; j < 4; j++)1536// 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);153715381539if (!rdp.aTBuffTex[0] && rdp.cur_cache[0]->splits != 1)1540{1541// ** LARGE TEXTURE HANDLING **1542// *VERY* simple algebra for texrects1543float min_u, min_x, max_u, max_x;1544if (vstd[0].u0 < vstd[1].u0)1545{1546min_u = vstd[0].u0;1547min_x = vstd[0].x;1548max_u = vstd[1].u0;1549max_x = vstd[1].x;1550}1551else1552{1553min_u = vstd[1].u0;1554min_x = vstd[1].x;1555max_u = vstd[0].u0;1556max_x = vstd[0].x;1557}15581559int start_u_256, end_u_256;1560start_u_256 = (int)min_u >> 8;1561end_u_256 = (int)max_u >> 8;1562//FRDP(" min_u: %f, max_u: %f start: %d, end: %d\n", min_u, max_u, start_u_256, end_u_256);15631564int splitheight = rdp.cur_cache[0]->splitheight;15651566int num_verts_line = 2 + ((end_u_256-start_u_256)<<1);1567n_vertices = num_verts_line << 1;1568vnew = new VERTEX [n_vertices];1569vptr = vnew;15701571vnew[0] = vstd[0];1572vnew[0].u0 -= 256.0f * start_u_256;1573vnew[0].v0 += splitheight * start_u_256;1574vnew[0].u1 -= 256.0f * start_u_256;1575vnew[0].v1 += splitheight * start_u_256;1576vnew[1] = vstd[2];1577vnew[1].u0 -= 256.0f * start_u_256;1578vnew[1].v0 += splitheight * start_u_256;1579vnew[1].u1 -= 256.0f * start_u_256;1580vnew[1].v1 += splitheight * start_u_256;1581vnew[n_vertices-2] = vstd[1];1582vnew[n_vertices-2].u0 -= 256.0f * end_u_256;1583vnew[n_vertices-2].v0 += splitheight * end_u_256;1584vnew[n_vertices-2].u1 -= 256.0f * end_u_256;1585vnew[n_vertices-2].v1 += splitheight * end_u_256;1586vnew[n_vertices-1] = vstd[3];1587vnew[n_vertices-1].u0 -= 256.0f * end_u_256;1588vnew[n_vertices-1].v0 += splitheight * end_u_256;1589vnew[n_vertices-1].u1 -= 256.0f * end_u_256;1590vnew[n_vertices-1].v1 += splitheight * end_u_256;15911592// find the equation of the line of u,x1593float m = (max_x - min_x) / (max_u - min_u); // m = delta x / delta u1594float b = min_x - m * min_u; // b = y - m * x15951596for (i=start_u_256; i<end_u_256; i++)1597{1598// Find where x = current 256 multiple1599float x = m * ((i<<8)+256) + b;16001601int vn = 2 + ((i-start_u_256)<<2);1602vnew[vn] = vstd[0];1603vnew[vn].x = x;1604vnew[vn].u0 = 255.5f;1605vnew[vn].v0 += (float)splitheight * i;1606vnew[vn].u1 = 255.5f;1607vnew[vn].v1 += (float)splitheight * i;16081609vn ++;1610vnew[vn] = vstd[2];1611vnew[vn].x = x;1612vnew[vn].u0 = 255.5f;1613vnew[vn].v0 += (float)splitheight * i;1614vnew[vn].u1 = 255.5f;1615vnew[vn].v1 += (float)splitheight * i;16161617vn ++;1618vnew[vn] = vnew[vn-2];1619vnew[vn].u0 = 0.5f;1620vnew[vn].v0 += (float)splitheight;1621vnew[vn].u1 = 0.5f;1622vnew[vn].v1 += (float)splitheight;16231624vn ++;1625vnew[vn] = vnew[vn-2];1626vnew[vn].u0 = 0.5f;1627vnew[vn].v0 += (float)splitheight;1628vnew[vn].u1 = 0.5f;1629vnew[vn].v1 += (float)splitheight;1630}1631//*1632if (n_vertices > 12)1633{1634float texbound = (float)(splitheight << 1);1635for (int k = 0; k < n_vertices; k ++)1636{1637if (vnew[k].v0 > texbound)1638vnew[k].v0 = (float)fmod(vnew[k].v0, texbound);1639}1640}1641//*/1642}16431644AllowShadeMods (vptr, n_vertices);1645for (i=0; i<n_vertices; i++)1646{1647apply_shade_mods (&vptr[i]);1648}16491650if (fullscreen)1651{1652if (rdp.fog_mode >= RDP::fog_blend)1653{1654float fog;1655if (rdp.fog_mode == RDP::fog_blend)1656fog = 1.0f/max(1, rdp.fog_color&0xFF);1657else1658fog = 1.0f/max(1, (~rdp.fog_color)&0xFF);1659for (i = 0; i < n_vertices; i++)1660{1661vptr[i].f = fog;1662}1663grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);1664}16651666ConvertCoordsConvert (vptr, n_vertices);16671668if (settings.wireframe)1669{1670SetWireframeCol ();1671grDrawLine (&vstd[0], &vstd[2]);1672grDrawLine (&vstd[2], &vstd[1]);1673grDrawLine (&vstd[1], &vstd[0]);1674grDrawLine (&vstd[2], &vstd[3]);1675grDrawLine (&vstd[3], &vstd[1]);1676}1677else1678{1679grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, n_vertices, vptr, sizeof(VERTEX));1680}16811682if (_debugger.capture)1683{1684VERTEX vl[3];1685vl[0] = vstd[0];1686vl[1] = vstd[2];1687vl[2] = vstd[1];1688add_tri (vl, 3, TRI_TEXRECT);1689rdp.tri_n ++;1690vl[0] = vstd[2];1691vl[1] = vstd[3];1692vl[2] = vstd[1];1693add_tri (vl, 3, TRI_TEXRECT);1694rdp.tri_n ++;1695}1696else1697rdp.tri_n += 2;1698}1699else1700{1701rdp.tri_n += 2;1702}17031704delete[] vnew;1705}17061707static void rdp_loadsync()1708{1709LRDP("loadsync - ignored\n");1710}17111712static void rdp_pipesync()1713{1714LRDP("pipesync - ignored\n");1715}17161717static void rdp_tilesync()1718{1719LRDP("tilesync - ignored\n");1720}17211722static void rdp_fullsync()1723{1724// Set an interrupt to allow the game to continue1725*gfx.MI_INTR_REG |= 0x20;1726gfx.CheckInterrupts();1727LRDP("fullsync\n");1728}17291730static void rdp_setkeygb()1731{1732wxUint32 sB = rdp.cmd1&0xFF;1733wxUint32 cB = (rdp.cmd1>>8)&0xFF;1734wxUint32 sG = (rdp.cmd1>>16)&0xFF;1735wxUint32 cG = (rdp.cmd1>>24)&0xFF;1736rdp.SCALE = (rdp.SCALE&0xFF0000FF) | (sG<<16) | (sB<<8);1737rdp.CENTER = (rdp.CENTER&0xFF0000FF) | (cG<<16) | (cB<<8);1738FRDP("setkeygb. cG=%02lx, sG=%02lx, cB=%02lx, sB=%02lx\n", cG, sG, cB, sB);1739}17401741static void rdp_setkeyr()1742{1743wxUint32 sR = rdp.cmd1&0xFF;1744wxUint32 cR = (rdp.cmd1>>8)&0xFF;1745rdp.SCALE = (rdp.SCALE&0x00FFFFFF) | (sR<<24);1746rdp.CENTER = (rdp.CENTER&0x00FFFFFF) | (cR<<24);1747FRDP("setkeyr. cR=%02lx, sR=%02lx\n", cR, sR);1748}17491750static void rdp_setconvert()1751{1752/*1753rdp.YUV_C0 = 1.1647f ;1754rdp.YUV_C1 = 0.79931f ;1755rdp.YUV_C2 = -0.1964f ;1756rdp.YUV_C3 = -0.40651f;1757rdp.YUV_C4 = 1.014f ;1758*/1759rdp.K4 = (wxUint8)(rdp.cmd1>>9)&0x1FF;1760rdp.K5 = (wxUint8)(rdp.cmd1&0x1FF);1761// RDP_E("setconvert - IGNORED\n");1762FRDP("setconvert. K4=%02lx K5=%02lx\n", rdp.K4, rdp.K5);1763}17641765//1766// setscissor - sets the screen clipping rectangle1767//17681769static void rdp_setscissor()1770{1771// clipper resolution is 320x240, scale based on computer resolution1772rdp.scissor_o.ul_x = /*min(*/(wxUint32)(((rdp.cmd0 & 0x00FFF000) >> 14))/*, 320)*/;1773rdp.scissor_o.ul_y = /*min(*/(wxUint32)(((rdp.cmd0 & 0x00000FFF) >> 2))/*, 240)*/;1774rdp.scissor_o.lr_x = /*min(*/(wxUint32)(((rdp.cmd1 & 0x00FFF000) >> 14))/*, 320)*/;1775rdp.scissor_o.lr_y = /*min(*/(wxUint32)(((rdp.cmd1 & 0x00000FFF) >> 2))/*, 240)*/;17761777rdp.ci_upper_bound = rdp.scissor_o.ul_y;1778rdp.ci_lower_bound = rdp.scissor_o.lr_y;1779rdp.scissor_set = TRUE;17801781FRDP("setscissor: (%d,%d) -> (%d,%d)\n", rdp.scissor_o.ul_x, rdp.scissor_o.ul_y,1782rdp.scissor_o.lr_x, rdp.scissor_o.lr_y);17831784rdp.update |= UPDATE_SCISSOR;17851786if (rdp.view_scale[0] == 0) //viewport is not set?1787{1788rdp.view_scale[0] = (rdp.scissor_o.lr_x>>1)*rdp.scale_x;1789rdp.view_scale[1] = (rdp.scissor_o.lr_y>>1)*-rdp.scale_y;1790rdp.view_trans[0] = rdp.view_scale[0];1791rdp.view_trans[1] = -rdp.view_scale[1];1792rdp.update |= UPDATE_VIEWPORT;1793}1794}17951796static void rdp_setprimdepth()1797{1798rdp.prim_depth = (wxUint16)((rdp.cmd1 >> 16) & 0x7FFF);1799rdp.prim_dz = (wxUint16)(rdp.cmd1 & 0x7FFF);18001801FRDP("setprimdepth: %d\n", rdp.prim_depth);1802}18031804static void rdp_setothermode()1805{1806#define F3DEX2_SETOTHERMODE(cmd,sft,len,data) { \1807rdp.cmd0 = (cmd<<24) | ((32-(sft)-(len))<<8) | (((len)-1)); \1808rdp.cmd1 = data; \1809gfx_instruction[settings.ucode][cmd] (); \1810}1811#define SETOTHERMODE(cmd,sft,len,data) { \1812rdp.cmd0 = (cmd<<24) | ((sft)<<8) | (len); \1813rdp.cmd1 = data; \1814gfx_instruction[settings.ucode][cmd] (); \1815}18161817LRDP("rdp_setothermode\n");18181819if ((settings.ucode == ucode_F3DEX2) || (settings.ucode == ucode_CBFD))1820{1821int cmd0 = rdp.cmd0;1822F3DEX2_SETOTHERMODE(0xE2, 0, 32, rdp.cmd1); // SETOTHERMODE_L1823F3DEX2_SETOTHERMODE(0xE3, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H1824}1825else1826{1827int cmd0 = rdp.cmd0;1828SETOTHERMODE(0xB9, 0, 32, rdp.cmd1); // SETOTHERMODE_L1829SETOTHERMODE(0xBA, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H1830}1831}18321833void load_palette (wxUint32 addr, wxUint16 start, wxUint16 count)1834{1835LRDP("Loading palette... ");1836wxUint16 *dpal = rdp.pal_8 + start;1837wxUint16 end = start+count;1838#ifdef TEXTURE_FILTER1839wxUint16 *spal = (wxUint16*)(gfx.RDRAM + (addr & BMASK));1840#endif18411842for (wxUint16 i=start; i<end; i++)1843{1844*(dpal++) = *(wxUint16 *)(gfx.RDRAM + (addr^2));1845addr += 2;18461847#ifdef TLUT_LOGGING1848FRDP ("%d: %08lx\n", i, *(wxUint16 *)(gfx.RDRAM + (addr^2)));1849#endif1850}1851#ifdef TEXTURE_FILTER1852if (settings.ghq_hirs)1853memcpy((wxUint8*)(rdp.pal_8_rice+start), spal, count<<1);1854#endif1855start >>= 4;1856end = start + (count >> 4);1857if (end == start) // it can be if count < 161858end = start + 1;1859for (wxUint16 p = start; p < end; p++)1860{1861rdp.pal_8_crc[p] = CRC32( 0xFFFFFFFF, &rdp.pal_8[(p << 4)], 32 );1862}1863rdp.pal_256_crc = CRC32( 0xFFFFFFFF, rdp.pal_8_crc, 64 );1864LRDP("Done.\n");1865}18661867static void rdp_loadtlut()1868{1869wxUint32 tile = (rdp.cmd1 >> 24) & 0x07;1870wxUint16 start = rdp.tiles[tile].t_mem - 256; // starting location in the palettes1871// wxUint16 start = ((wxUint16)(rdp.cmd1 >> 2) & 0x3FF) + 1;1872wxUint16 count = ((wxUint16)(rdp.cmd1 >> 14) & 0x3FF) + 1; // number to copy18731874if (rdp.timg.addr + (count<<1) > BMASK)1875count = (wxUint16)((BMASK - rdp.timg.addr) >> 1);18761877if (start+count > 256) count = 256-start;18781879FRDP("loadtlut: tile: %d, start: %d, count: %d, from: %08lx\n", tile, start, count,1880rdp.timg.addr);18811882load_palette (rdp.timg.addr, start, count);18831884rdp.timg.addr += count << 1;18851886if (rdp.tbuff_tex) //paranoid check.1887{1888//the buffer is definitely wrong, as there must be no CI frame buffers1889//find and remove it1890for (int i = 0; i < voodoo.num_tmu; i++)1891{1892for (int j = 0; j < rdp.texbufs[i].count; j++)1893{1894if (&(rdp.texbufs[i].images[j]) == rdp.tbuff_tex)1895{1896rdp.texbufs[i].count--;1897if (j < rdp.texbufs[i].count)1898memcpy(&(rdp.texbufs[i].images[j]), &(rdp.texbufs[i].images[j+1]), sizeof(TBUFF_COLOR_IMAGE)*(rdp.texbufs[i].count-j));1899return;1900}1901}1902}1903}1904}19051906int tile_set = 0;1907static void rdp_settilesize()1908{1909wxUint32 tile = (rdp.cmd1 >> 24) & 0x07;1910rdp.last_tile_size = tile;19111912rdp.tiles[tile].f_ul_s = (float)((rdp.cmd0 >> 12) & 0xFFF) / 4.0f;1913rdp.tiles[tile].f_ul_t = (float)(rdp.cmd0 & 0xFFF) / 4.0f;19141915int ul_s = (((wxUint16)(rdp.cmd0 >> 14)) & 0x03ff);1916int ul_t = (((wxUint16)(rdp.cmd0 >> 2 )) & 0x03ff);1917int lr_s = (((wxUint16)(rdp.cmd1 >> 14)) & 0x03ff);1918int lr_t = (((wxUint16)(rdp.cmd1 >> 2 )) & 0x03ff);19191920if (lr_s == 0 && ul_s == 0) //pokemon puzzle league set such tile size1921wrong_tile = tile;1922else if (wrong_tile == (int)tile)1923wrong_tile = -1;19241925if (settings.use_sts1_only)1926{1927// ** USE FIRST SETTILESIZE ONLY **1928// This option helps certain textures while using the 'Alternate texture size method',1929// but may break others. (should help more than break)19301931if (tile_set)1932{1933// coords in 10.2 format1934rdp.tiles[tile].ul_s = ul_s;1935rdp.tiles[tile].ul_t = ul_t;1936rdp.tiles[tile].lr_s = lr_s;1937rdp.tiles[tile].lr_t = lr_t;1938tile_set = 0;1939}1940}1941else1942{1943// coords in 10.2 format1944rdp.tiles[tile].ul_s = ul_s;1945rdp.tiles[tile].ul_t = ul_t;1946rdp.tiles[tile].lr_s = lr_s;1947rdp.tiles[tile].lr_t = lr_t;1948}19491950// handle wrapping1951if (rdp.tiles[tile].lr_s < rdp.tiles[tile].ul_s) rdp.tiles[tile].lr_s += 0x400;1952if (rdp.tiles[tile].lr_t < rdp.tiles[tile].ul_t) rdp.tiles[tile].lr_t += 0x400;19531954rdp.update |= UPDATE_TEXTURE;19551956rdp.first = 1;19571958FRDP ("settilesize: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d, f_ul_s: %f, f_ul_t: %f\n",1959tile, ul_s, ul_t, lr_s, lr_t, rdp.tiles[tile].f_ul_s, rdp.tiles[tile].f_ul_t);1960}19611962void setTBufTex(wxUint16 t_mem, wxUint32 cnt)1963{1964FRDP("setTBufTex t_mem=%d, cnt=%d\n", t_mem, cnt);1965TBUFF_COLOR_IMAGE * pTbufTex = rdp.tbuff_tex;1966for (int i = 0; i < 2; i++)1967{1968LRDP("Before: ");1969if (rdp.aTBuffTex[i]) {1970FRDP("rdp.aTBuffTex[%d]: tmu=%d t_mem=%d tile=%d\n", i, rdp.aTBuffTex[i]->tmu, rdp.aTBuffTex[i]->t_mem, rdp.aTBuffTex[i]->tile);1971} else {1972FRDP("rdp.aTBuffTex[%d]=0\n", i);1973}1974if ((rdp.aTBuffTex[i] == 0 && rdp.aTBuffTex[i^1] != pTbufTex) || (rdp.aTBuffTex[i] && rdp.aTBuffTex[i]->t_mem >= t_mem && rdp.aTBuffTex[i]->t_mem < t_mem + cnt))1975{1976if (pTbufTex)1977{1978rdp.aTBuffTex[i] = pTbufTex;1979rdp.aTBuffTex[i]->t_mem = t_mem;1980pTbufTex = 0;1981FRDP("rdp.aTBuffTex[%d] tmu=%d t_mem=%d\n", i, rdp.aTBuffTex[i]->tmu, rdp.aTBuffTex[i]->t_mem);1982}1983else1984{1985rdp.aTBuffTex[i] = 0;1986FRDP("rdp.aTBuffTex[%d]=0\n", i);1987}1988}1989}1990}19911992static inline void loadBlock(uint32_t *src, uint32_t *dst, uint32_t off, int dxt, int cnt)1993{1994uint32_t *v5;1995int v6;1996uint32_t *v7;1997uint32_t v8;1998int v9;1999uint32_t v10;2000uint32_t *v11;2001uint32_t v12;2002uint32_t v13;2003uint32_t v14;2004int v15;2005int v16;2006uint32_t *v17;2007int v18;2008uint32_t v19;2009uint32_t v20;2010int i;20112012v5 = dst;2013v6 = cnt;2014if ( cnt )2015{2016v7 = (uint32_t *)((char *)src + (off & 0xFFFFFFFC));2017v8 = off & 3;2018if ( !(off & 3) )2019goto LABEL_23;2020v9 = 4 - v8;2021v10 = *v7;2022v11 = v7 + 1;2023do2024{2025v10 = __ROL__(v10, 8);2026--v8;2027}2028while ( v8 );2029do2030{2031v10 = __ROL__(v10, 8);2032*(uint8_t *)v5 = v10;2033v5 = (uint32_t *)((char *)v5 + 1);2034--v9;2035}2036while ( v9 );2037v12 = *v11;2038v7 = v11 + 1;2039*v5 = bswap32(v12);2040++v5;2041v6 = cnt - 1;2042if ( cnt != 1 )2043{2044LABEL_23:2045do2046{2047*v5 = bswap32(*v7);2048v5[1] = bswap32(v7[1]);2049v7 += 2;2050v5 += 2;2051--v6;2052}2053while ( v6 );2054}2055v13 = off & 3;2056if ( off & 3 )2057{2058v14 = *(uint32_t *)((char *)src + ((8 * cnt + off) & 0xFFFFFFFC));2059do2060{2061v14 = __ROL__(v14, 8);2062*(uint8_t *)v5 = v14;2063v5 = (uint32_t *)((char *)v5 + 1);2064--v13;2065}2066while ( v13 );2067}2068}2069v15 = cnt;2070v16 = 0;2071v17 = dst;2072v18 = 0;2073dxt_test:2074while ( 1 )2075{2076v17 += 2;2077--v15;2078if ( !v15 )2079break;2080v16 += dxt;2081if ( v16 < 0 )2082{2083while ( 1 )2084{2085++v18;2086--v15;2087if ( !v15 )2088goto end_dxt_test;2089v16 += dxt;2090if ( v16 >= 0 )2091{2092for ( i = v15; v18; --v18 )2093{2094v19 = *v17;2095*v17 = v17[1];2096v17[1] = v19;2097v17 += 2;2098}2099v15 = i;2100goto dxt_test;2101}2102}2103}2104}2105end_dxt_test:2106while ( v18 )2107{2108v20 = *v17;2109*v17 = v17[1];2110v17[1] = v20;2111v17 += 2;2112--v18;2113}2114}21152116void LoadBlock32b(wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 lr_s, wxUint32 dxt);2117static void rdp_loadblock()2118{2119if (rdp.skip_drawing)2120{2121LRDP("loadblock skipped\n");2122return;2123}2124wxUint32 tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07);2125wxUint32 dxt = (wxUint32)(rdp.cmd1 & 0x0FFF);2126wxUint16 lr_s = (wxUint16)(rdp.cmd1 >> 14) & 0x3FF;2127if (ucode5_texshiftaddr)2128{2129if (ucode5_texshift % ((lr_s+1)<<3))2130{2131rdp.timg.addr -= ucode5_texshift;2132ucode5_texshiftaddr = 0;2133ucode5_texshift = 0;2134ucode5_texshiftcount = 0;2135}2136else2137ucode5_texshiftcount++;2138}21392140rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr;21412142// ** DXT is used for swapping every other line2143/* double fdxt = (double)0x8000000F/(double)((wxUint32)(2047/(dxt-1))); // F for error2144wxUint32 _dxt = (wxUint32)fdxt;*/21452146// 0x00000800 -> 0x80000000 (so we can check the sign bit instead of the 11th bit)2147wxUint32 _dxt = dxt << 20;21482149wxUint32 addr = segoffset(rdp.timg.addr) & BMASK;21502151// lr_s specifies number of 64-bit words to copy2152// 10.2 format2153wxUint16 ul_s = (wxUint16)(rdp.cmd0 >> 14) & 0x3FF;2154wxUint16 ul_t = (wxUint16)(rdp.cmd0 >> 2) & 0x3FF;21552156rdp.tiles[tile].ul_s = ul_s;2157rdp.tiles[tile].ul_t = ul_t;2158rdp.tiles[tile].lr_s = lr_s;21592160rdp.timg.set_by = 0; // load block21612162#ifdef TEXTURE_FILTER2163LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[tile].t_mem];2164info.tile_width = lr_s;2165info.dxt = dxt;2166#endif21672168// do a quick boundary check before copying to eliminate the possibility for exception2169if (ul_s >= 512) {2170lr_s = 1; // 1 so that it doesn't die on memcpy2171ul_s = 511;2172}2173if (ul_s+lr_s > 512)2174lr_s = 512-ul_s;21752176if (addr+(lr_s<<3) > BMASK+1)2177lr_s = (wxUint16)((BMASK-addr)>>3);21782179//angrylion's advice to use ul_s in texture image offset and cnt calculations.2180//Helps to fix Vigilante 8 jpeg backgrounds and logos2181wxUint32 off = rdp.timg.addr + (ul_s << rdp.tiles[tile].size >> 1);2182unsigned char *dst = ((unsigned char *)rdp.tmem) + (rdp.tiles[tile].t_mem<<3);2183wxUint32 cnt = lr_s-ul_s+1;2184if (rdp.tiles[tile].size == 3)2185cnt <<= 1;21862187if (((rdp.tiles[tile].t_mem + cnt) << 3) > sizeof(rdp.tmem)) {2188WriteLog(M64MSG_INFO, "rdp_loadblock wanted to write %u bytes after the end of tmem", ((rdp.tiles[tile].t_mem + cnt) << 3) - sizeof(rdp.tmem));2189cnt = (sizeof(rdp.tmem) >> 3) - (rdp.tiles[tile].t_mem);2190}21912192if (rdp.timg.size == 3)2193LoadBlock32b(tile, ul_s, ul_t, lr_s, dxt);2194else2195loadBlock((uint32_t *)gfx.RDRAM, (uint32_t *)dst, off, _dxt, cnt);21962197rdp.timg.addr += cnt << 3;2198rdp.tiles[tile].lr_t = ul_t + ((dxt*cnt)>>11);21992200rdp.update |= UPDATE_TEXTURE;22012202FRDP ("loadblock: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, dxt: %08lx -> %08lx\n",2203tile, ul_s, ul_t, lr_s,2204dxt, _dxt);22052206if (fb_hwfbe_enabled)2207setTBufTex(rdp.tiles[tile].t_mem, cnt);2208}220922102211static inline void loadTile(uint32_t *src, uint32_t *dst, int width, int height, int line, int off, uint32_t *end)2212{2213uint32_t *v7;2214int v8;2215uint32_t *v9;2216int v10;2217int v11;2218int v12;2219uint32_t *v13;2220int v14;2221int v15;2222uint32_t v16;2223uint32_t *v17;2224uint32_t v18;2225int v19;2226uint32_t v20;2227int v21;2228uint32_t v22;2229int v23;2230uint32_t *v24;2231int v25;2232int v26;2233uint32_t *v27;2234int v28;2235int v29;2236int v30;2237uint32_t *v31;22382239v7 = dst;2240v8 = width;2241v9 = src;2242v10 = off;2243v11 = 0;2244v12 = height;2245do2246{2247if ( end < v7 )2248break;2249v31 = v7;2250v30 = v8;2251v29 = v12;2252v28 = v11;2253v27 = v9;2254v26 = v10;2255if ( v8 )2256{2257v25 = v8;2258v24 = v9;2259v23 = v10;2260v13 = (uint32_t *)((char *)v9 + (v10 & 0xFFFFFFFC));2261v14 = v10 & 3;2262if ( !(v10 & 3) )2263goto LABEL_20;2264v15 = 4 - v14;2265v16 = *v13;2266v17 = v13 + 1;2267do2268{2269v16 = __ROL__(v16, 8);2270--v14;2271}2272while ( v14 );2273do2274{2275v16 = __ROL__(v16, 8);2276*(uint8_t *)v7 = v16;2277v7 = (uint32_t *)((char *)v7 + 1);2278--v15;2279}2280while ( v15 );2281v18 = *v17;2282v13 = v17 + 1;2283*v7 = bswap32(v18);2284++v7;2285--v8;2286if ( v8 )2287{2288LABEL_20:2289do2290{2291*v7 = bswap32(*v13);2292v7[1] = bswap32(v13[1]);2293v13 += 2;2294v7 += 2;2295--v8;2296}2297while ( v8 );2298}2299v19 = v23 & 3;2300if ( v23 & 3 )2301{2302v20 = *(uint32_t *)((char *)v24 + ((8 * v25 + v23) & 0xFFFFFFFC));2303do2304{2305v20 = __ROL__(v20, 8);2306*(uint8_t *)v7 = v20;2307v7 = (uint32_t *)((char *)v7 + 1);2308--v19;2309}2310while ( v19 );2311}2312}2313v9 = v27;2314v21 = v29;2315v8 = v30;2316v11 = v28 ^ 1;2317if ( v28 == 1 )2318{2319v7 = v31;2320if ( v30 )2321{2322do2323{2324v22 = *v7;2325*v7 = v7[1];2326v7[1] = v22;2327v7 += 2;2328--v8;2329}2330while ( v8 );2331}2332v21 = v29;2333v8 = v30;2334}2335v10 = line + v26;2336v12 = v21 - 1;2337}2338while ( v12 );2339}23402341void LoadTile32b (wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 width, wxUint32 height);2342static void rdp_loadtile()2343{2344if (rdp.skip_drawing)2345{2346LRDP("loadtile skipped\n");2347return;2348}2349rdp.timg.set_by = 1; // load tile23502351wxUint32 tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07);23522353rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr;23542355wxUint16 ul_s = (wxUint16)((rdp.cmd0 >> 14) & 0x03FF);2356wxUint16 ul_t = (wxUint16)((rdp.cmd0 >> 2 ) & 0x03FF);2357wxUint16 lr_s = (wxUint16)((rdp.cmd1 >> 14) & 0x03FF);2358wxUint16 lr_t = (wxUint16)((rdp.cmd1 >> 2 ) & 0x03FF);23592360if (lr_s < ul_s || lr_t < ul_t) return;23612362if (wrong_tile >= 0) //there was a tile with zero length2363{2364rdp.tiles[wrong_tile].lr_s = lr_s;23652366if (rdp.tiles[tile].size > rdp.tiles[wrong_tile].size)2367rdp.tiles[wrong_tile].lr_s <<= (rdp.tiles[tile].size - rdp.tiles[wrong_tile].size);2368else if (rdp.tiles[tile].size < rdp.tiles[wrong_tile].size)2369rdp.tiles[wrong_tile].lr_s >>= (rdp.tiles[wrong_tile].size - rdp.tiles[tile].size);2370rdp.tiles[wrong_tile].lr_t = lr_t;2371rdp.tiles[wrong_tile].mask_s = rdp.tiles[wrong_tile].mask_t = 0;2372// wrong_tile = -1;2373}23742375if (rdp.tbuff_tex)// && (rdp.tiles[tile].format == 0))2376{2377FRDP("loadtile: tbuff_tex ul_s: %d, ul_t:%d\n", ul_s, ul_t);2378rdp.tbuff_tex->tile_uls = ul_s;2379rdp.tbuff_tex->tile_ult = ul_t;2380}23812382if ((settings.hacks&hack_Tonic) && tile == 7)2383{2384rdp.tiles[0].ul_s = ul_s;2385rdp.tiles[0].ul_t = ul_t;2386rdp.tiles[0].lr_s = lr_s;2387rdp.tiles[0].lr_t = lr_t;2388}23892390wxUint32 height = lr_t - ul_t + 1; // get height2391wxUint32 width = lr_s - ul_s + 1;23922393#ifdef TEXTURE_FILTER2394LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[tile].t_mem];2395info.tile_ul_s = ul_s;2396info.tile_ul_t = ul_t;2397info.tile_width = (rdp.tiles[tile].mask_s ? min((wxUint16)width, 1<<rdp.tiles[tile].mask_s) : (wxUint16)width);2398info.tile_height = (rdp.tiles[tile].mask_t ? min((wxUint16)height, 1<<rdp.tiles[tile].mask_t) : (wxUint16)height);2399if (settings.hacks&hack_MK64) {2400if (info.tile_width%2)2401info.tile_width--;2402if (info.tile_height%2)2403info.tile_height--;2404}2405info.tex_width = rdp.timg.width;2406info.tex_size = rdp.timg.size;2407#endif24082409int line_n = rdp.timg.width << rdp.tiles[tile].size >> 1;2410wxUint32 offs = ul_t * line_n;2411offs += ul_s << rdp.tiles[tile].size >> 1;2412offs += rdp.timg.addr;2413if (offs >= BMASK)2414return;24152416if (rdp.timg.size == 3)2417{2418LoadTile32b(tile, ul_s, ul_t, width, height);2419}2420else2421{2422// check if points to bad location2423if (offs + line_n*height > BMASK)2424height = (BMASK - offs) / line_n;2425if (height == 0)2426return;24272428wxUint32 wid_64 = rdp.tiles[tile].line;2429unsigned char *dst = ((unsigned char *)rdp.tmem) + (rdp.tiles[tile].t_mem<<3);2430unsigned char *end = ((unsigned char *)rdp.tmem) + 4096 - (wid_64<<3);2431loadTile((uint32_t *)gfx.RDRAM, (uint32_t *)dst, wid_64, height, line_n, offs, (uint32_t *)end);2432}2433FRDP("loadtile: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d\n", tile,2434ul_s, ul_t, lr_s, lr_t);24352436if (fb_hwfbe_enabled)2437setTBufTex(rdp.tiles[tile].t_mem, rdp.tiles[tile].line*height);2438}24392440static void rdp_settile()2441{2442tile_set = 1; // used to check if we only load the first settilesize24432444rdp.first = 0;24452446rdp.last_tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07);2447TILE *tile = &rdp.tiles[rdp.last_tile];24482449tile->format = (wxUint8)((rdp.cmd0 >> 21) & 0x07);2450tile->size = (wxUint8)((rdp.cmd0 >> 19) & 0x03);2451tile->line = (wxUint16)((rdp.cmd0 >> 9) & 0x01FF);2452tile->t_mem = (wxUint16)(rdp.cmd0 & 0x1FF);2453tile->palette = (wxUint8)((rdp.cmd1 >> 20) & 0x0F);2454tile->clamp_t = (wxUint8)((rdp.cmd1 >> 19) & 0x01);2455tile->mirror_t = (wxUint8)((rdp.cmd1 >> 18) & 0x01);2456tile->mask_t = (wxUint8)((rdp.cmd1 >> 14) & 0x0F);2457tile->shift_t = (wxUint8)((rdp.cmd1 >> 10) & 0x0F);2458tile->clamp_s = (wxUint8)((rdp.cmd1 >> 9) & 0x01);2459tile->mirror_s = (wxUint8)((rdp.cmd1 >> 8) & 0x01);2460tile->mask_s = (wxUint8)((rdp.cmd1 >> 4) & 0x0F);2461tile->shift_s = (wxUint8)(rdp.cmd1 & 0x0F);24622463rdp.update |= UPDATE_TEXTURE;24642465FRDP ("settile: tile: %d, format: %s, size: %s, line: %d, "2466"t_mem: %08lx, palette: %d, clamp_t/mirror_t: %s, mask_t: %d, "2467"shift_t: %d, clamp_s/mirror_s: %s, mask_s: %d, shift_s: %d\n",2468rdp.last_tile, str_format[tile->format], str_size[tile->size], tile->line,2469tile->t_mem, tile->palette, str_cm[(tile->clamp_t<<1)|tile->mirror_t], tile->mask_t,2470tile->shift_t, str_cm[(tile->clamp_s<<1)|tile->mirror_s], tile->mask_s, tile->shift_s);24712472if (fb_hwfbe_enabled && rdp.last_tile < rdp.cur_tile + 2)2473{2474for (int i = 0; i < 2; i++)2475{2476if (rdp.aTBuffTex[i])2477{2478if (rdp.aTBuffTex[i]->t_mem == tile->t_mem)2479{2480if (rdp.aTBuffTex[i]->size == tile->size)2481{2482rdp.aTBuffTex[i]->tile = rdp.last_tile;2483rdp.aTBuffTex[i]->info.format = tile->format == 0 ? GR_TEXFMT_RGB_565 : GR_TEXFMT_ALPHA_INTENSITY_88;2484FRDP("rdp.aTBuffTex[%d] tile=%d, format=%s\n", i, rdp.last_tile, tile->format == 0 ? "RGB565" : "Alpha88");2485}2486else2487rdp.aTBuffTex[i] = 0;2488break;2489}2490else if (rdp.aTBuffTex[i]->tile == rdp.last_tile) //wrong! t_mem must be the same2491rdp.aTBuffTex[i] = 0;2492}2493}2494}2495}24962497//2498// fillrect - fills a rectangle2499//25002501static void rdp_fillrect()2502{2503wxUint32 ul_x = ((rdp.cmd1 & 0x00FFF000) >> 14);2504wxUint32 ul_y = (rdp.cmd1 & 0x00000FFF) >> 2;2505wxUint32 lr_x = ((rdp.cmd0 & 0x00FFF000) >> 14) + 1;2506wxUint32 lr_y = ((rdp.cmd0 & 0x00000FFF) >> 2) + 1;2507if ((ul_x > lr_x) || (ul_y > lr_y))2508{2509LRDP("Fillrect. Wrong coordinates. Skipped\n");2510return;2511}2512int pd_multiplayer = (settings.ucode == ucode_PerfectDark) && (rdp.cycle_mode == 3) && (rdp.fill_color == 0xFFFCFFFC);2513if ((rdp.cimg == rdp.zimg) || (fb_emulation_enabled && rdp.frame_buffers[rdp.ci_count-1].status == ci_zimg) || pd_multiplayer)2514{2515LRDP("Fillrect - cleared the depth buffer\n");2516if (fullscreen)2517{2518if (!(settings.hacks&hack_Hyperbike) || rdp.ci_width > 64) //do not clear main depth buffer for aux depth buffers2519{2520update_scissor ();2521grDepthMask (FXTRUE);2522grColorMask (FXFALSE, FXFALSE);2523grBufferClear (0, 0, rdp.fill_color ? rdp.fill_color&0xFFFF : 0xFFFF);2524grColorMask (FXTRUE, FXTRUE);2525rdp.update |= UPDATE_ZBUF_ENABLED;2526}2527//if (settings.frame_buffer&fb_depth_clear)2528{2529ul_x = min(max(ul_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x);2530lr_x = min(max(lr_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x);2531ul_y = min(max(ul_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y);2532lr_y = min(max(lr_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y);2533wxUint32 zi_width_in_dwords = rdp.ci_width >> 1;2534ul_x >>= 1;2535lr_x >>= 1;2536wxUint32 * dst = (wxUint32*)(gfx.RDRAM+rdp.cimg);2537dst += ul_y * zi_width_in_dwords;2538for (wxUint32 y = ul_y; y < lr_y; y++)2539{2540for (wxUint32 x = ul_x; x < lr_x; x++)2541{2542dst[x] = rdp.fill_color;2543}2544dst += zi_width_in_dwords;2545}2546}2547}2548return;2549}25502551if (rdp.skip_drawing)2552{2553LRDP("Fillrect skipped\n");2554return;2555}25562557if (rdp.cur_image && (rdp.cur_image->format != 0) && (rdp.cycle_mode == 3) && (rdp.cur_image->width == lr_x - ul_x) && (rdp.cur_image->height == lr_y - ul_y))2558{2559wxUint32 color = rdp.fill_color;2560if (rdp.ci_size < 3)2561{2562color = ((color&1)?0xFF:0) |2563((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) |2564((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) |2565((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8);2566}2567grDepthMask (FXFALSE);2568grBufferClear (color, 0, 0xFFFF);2569grDepthMask (FXTRUE);2570rdp.update |= UPDATE_ZBUF_ENABLED;2571LRDP("Fillrect - cleared the texture buffer\n");2572return;2573}25742575// Update scissor2576if (fullscreen)2577update_scissor ();25782579if (settings.decrease_fillrect_edge && rdp.cycle_mode == 0)2580{2581lr_x--; lr_y--;2582}2583FRDP("fillrect (%d,%d) -> (%d,%d), cycle mode: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, rdp.cycle_mode,2584rdp.tri_n, rdp.tri_n+1);25852586FRDP("scissor (%d,%d) -> (%d,%d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x,2587rdp.scissor.lr_y);25882589// KILL the floating point error with 0.01f2590wxInt32 s_ul_x = (wxUint32)min(max(ul_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x);2591wxInt32 s_lr_x = (wxUint32)min(max(lr_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x);2592wxInt32 s_ul_y = (wxUint32)min(max(ul_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y);2593wxInt32 s_lr_y = (wxUint32)min(max(lr_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y);25942595if (s_lr_x < 0) s_lr_x = 0;2596if (s_lr_y < 0) s_lr_y = 0;2597if ((wxUint32)s_ul_x > settings.res_x) s_ul_x = settings.res_x;2598if ((wxUint32)s_ul_y > settings.res_y) s_ul_y = settings.res_y;25992600FRDP (" - %d, %d, %d, %d\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y);26012602if (fullscreen)2603{2604grFogMode (GR_FOG_DISABLE);26052606const float Z = (rdp.cycle_mode == 3) ? 0.0f : set_sprite_combine_mode();26072608// Draw the rectangle2609VERTEX v[4] = {2610{ (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},2611{ (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},2612{ (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},2613{ (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} };26142615if (rdp.cycle_mode == 3)2616{2617wxUint32 color = rdp.fill_color;26182619if ((settings.hacks&hack_PMario) && rdp.frame_buffers[rdp.ci_count-1].status == ci_aux)2620{2621//background of auxiliary frame buffers must have zero alpha.2622//make it black, set 0 alpha to plack pixels on frame buffer read2623color = 0;2624}2625else if (rdp.ci_size < 3)2626{2627color = ((color&1)?0xFF:0) |2628((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) |2629((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) |2630((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8);2631}26322633grConstantColorValue (color);26342635grColorCombine (GR_COMBINE_FUNCTION_LOCAL,2636GR_COMBINE_FACTOR_NONE,2637GR_COMBINE_LOCAL_CONSTANT,2638GR_COMBINE_OTHER_NONE,2639FXFALSE);26402641grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,2642GR_COMBINE_FACTOR_NONE,2643GR_COMBINE_LOCAL_CONSTANT,2644GR_COMBINE_OTHER_NONE,2645FXFALSE);26462647grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);26482649grAlphaTestFunction (GR_CMP_ALWAYS);2650if (grStippleModeExt)2651grStippleModeExt(GR_STIPPLE_DISABLE);26522653grCullMode(GR_CULL_DISABLE);2654grFogMode (GR_FOG_DISABLE);2655grDepthBufferFunction (GR_CMP_ALWAYS);2656grDepthMask (FXFALSE);26572658rdp.update |= UPDATE_COMBINE | UPDATE_CULL_MODE | UPDATE_FOG_ENABLED | UPDATE_ZBUF_ENABLED;2659}2660else2661{2662wxUint32 cmb_mode_c = (rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF);2663wxUint32 cmb_mode_a = (rdp.cycle1 & 0x0FFF0000) | ((rdp.cycle2 >> 16) & 0x00000FFF);2664if (cmb_mode_c == 0x9fff9fff || cmb_mode_a == 0x09ff09ff) //shade2665{2666AllowShadeMods (v, 4);2667for (int k = 0; k < 4; k++)2668apply_shade_mods (&v[k]);2669}2670if ((rdp.othermode_l & 0x4000) && ((rdp.othermode_l >> 16) == 0x0550)) //special blender mode for Bomberman642671{2672grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,2673GR_COMBINE_FACTOR_NONE,2674GR_COMBINE_LOCAL_CONSTANT,2675GR_COMBINE_OTHER_NONE,2676FXFALSE);2677grConstantColorValue((cmb.ccolor&0xFFFFFF00)|(rdp.fog_color&0xFF));2678rdp.update |= UPDATE_COMBINE;2679}2680}26812682if (settings.wireframe)2683{2684SetWireframeCol ();2685grDrawLine (&v[0], &v[2]);2686grDrawLine (&v[2], &v[1]);2687grDrawLine (&v[1], &v[0]);2688grDrawLine (&v[2], &v[3]);2689grDrawLine (&v[3], &v[1]);2690//grDrawLine (&v[1], &v[2]);2691}2692else2693{2694grDrawTriangle (&v[0], &v[2], &v[1]);2695grDrawTriangle (&v[2], &v[3], &v[1]);2696}26972698if (_debugger.capture)2699{2700VERTEX v1[3];2701v1[0] = v[0];2702v1[1] = v[2];2703v1[2] = v[1];2704add_tri (v1, 3, TRI_FILLRECT);2705rdp.tri_n ++;2706v1[0] = v[2];2707v1[1] = v[3];2708add_tri (v1, 3, TRI_FILLRECT);2709rdp.tri_n ++;2710}2711else2712rdp.tri_n += 2;2713}2714else2715{2716rdp.tri_n += 2;2717}2718}27192720//2721// setfillcolor - sets the filling color2722//27232724static void rdp_setfillcolor()2725{2726rdp.fill_color = rdp.cmd1;2727rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE;27282729FRDP("setfillcolor: %08lx\n", rdp.cmd1);2730}27312732static void rdp_setfogcolor()2733{2734rdp.fog_color = rdp.cmd1;2735rdp.update |= UPDATE_COMBINE | UPDATE_FOG_ENABLED;27362737FRDP("setfogcolor - %08lx\n", rdp.cmd1);2738}27392740static void rdp_setblendcolor()2741{2742rdp.blend_color = rdp.cmd1;2743rdp.update |= UPDATE_COMBINE;27442745FRDP("setblendcolor: %08lx\n", rdp.cmd1);2746}27472748static void rdp_setprimcolor()2749{2750rdp.prim_color = rdp.cmd1;2751rdp.prim_lodmin = (rdp.cmd0 >> 8) & 0xFF;2752rdp.prim_lodfrac = max(rdp.cmd0 & 0xFF, rdp.prim_lodmin);2753rdp.update |= UPDATE_COMBINE;27542755FRDP("setprimcolor: %08lx, lodmin: %d, lodfrac: %d\n", rdp.cmd1, rdp.prim_lodmin,2756rdp.prim_lodfrac);2757}27582759static void rdp_setenvcolor()2760{2761rdp.env_color = rdp.cmd1;2762rdp.update |= UPDATE_COMBINE;27632764FRDP("setenvcolor: %08lx\n", rdp.cmd1);2765}27662767static void rdp_setcombine()2768{2769rdp.c_a0 = (wxUint8)((rdp.cmd0 >> 20) & 0xF);2770rdp.c_b0 = (wxUint8)((rdp.cmd1 >> 28) & 0xF);2771rdp.c_c0 = (wxUint8)((rdp.cmd0 >> 15) & 0x1F);2772rdp.c_d0 = (wxUint8)((rdp.cmd1 >> 15) & 0x7);2773rdp.c_Aa0 = (wxUint8)((rdp.cmd0 >> 12) & 0x7);2774rdp.c_Ab0 = (wxUint8)((rdp.cmd1 >> 12) & 0x7);2775rdp.c_Ac0 = (wxUint8)((rdp.cmd0 >> 9) & 0x7);2776rdp.c_Ad0 = (wxUint8)((rdp.cmd1 >> 9) & 0x7);27772778rdp.c_a1 = (wxUint8)((rdp.cmd0 >> 5) & 0xF);2779rdp.c_b1 = (wxUint8)((rdp.cmd1 >> 24) & 0xF);2780rdp.c_c1 = (wxUint8)((rdp.cmd0 >> 0) & 0x1F);2781rdp.c_d1 = (wxUint8)((rdp.cmd1 >> 6) & 0x7);2782rdp.c_Aa1 = (wxUint8)((rdp.cmd1 >> 21) & 0x7);2783rdp.c_Ab1 = (wxUint8)((rdp.cmd1 >> 3) & 0x7);2784rdp.c_Ac1 = (wxUint8)((rdp.cmd1 >> 18) & 0x7);2785rdp.c_Ad1 = (wxUint8)((rdp.cmd1 >> 0) & 0x7);27862787rdp.cycle1 = (rdp.c_a0<<0) | (rdp.c_b0<<4) | (rdp.c_c0<<8) | (rdp.c_d0<<13)|2788(rdp.c_Aa0<<16)| (rdp.c_Ab0<<19)| (rdp.c_Ac0<<22)| (rdp.c_Ad0<<25);2789rdp.cycle2 = (rdp.c_a1<<0) | (rdp.c_b1<<4) | (rdp.c_c1<<8) | (rdp.c_d1<<13)|2790(rdp.c_Aa1<<16)| (rdp.c_Ab1<<19)| (rdp.c_Ac1<<22)| (rdp.c_Ad1<<25);27912792rdp.update |= UPDATE_COMBINE;27932794FRDP("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",2795Mode0[rdp.c_a0], Mode1[rdp.c_b0], Mode2[rdp.c_c0], Mode3[rdp.c_d0],2796Alpha0[rdp.c_Aa0], Alpha1[rdp.c_Ab0], Alpha2[rdp.c_Ac0], Alpha3[rdp.c_Ad0],2797Mode0[rdp.c_a1], Mode1[rdp.c_b1], Mode2[rdp.c_c1], Mode3[rdp.c_d1],2798Alpha0[rdp.c_Aa1], Alpha1[rdp.c_Ab1], Alpha2[rdp.c_Ac1], Alpha3[rdp.c_Ad1]);2799}28002801//2802// settextureimage - sets the source for an image copy2803//28042805static void rdp_settextureimage()2806{2807static const char *format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" };2808static const char *size[] = { "4bit", "8bit", "16bit", "32bit" };28092810rdp.timg.format = (wxUint8)((rdp.cmd0 >> 21) & 0x07);2811rdp.timg.size = (wxUint8)((rdp.cmd0 >> 19) & 0x03);2812rdp.timg.width = (wxUint16)(1 + (rdp.cmd0 & 0x00000FFF));2813rdp.timg.addr = segoffset(rdp.cmd1);2814if (ucode5_texshiftaddr)2815{2816if (rdp.timg.format == 0)2817{2818wxUint16 * t = (wxUint16*)(gfx.RDRAM+ucode5_texshiftaddr);2819ucode5_texshift = t[ucode5_texshiftcount^1];2820rdp.timg.addr += ucode5_texshift;2821}2822else2823{2824ucode5_texshiftaddr = 0;2825ucode5_texshift = 0;2826ucode5_texshiftcount = 0;2827}2828}2829rdp.s2dex_tex_loaded = TRUE;2830rdp.update |= UPDATE_TEXTURE;28312832if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self && (rdp.timg.addr >= rdp.cimg) && (rdp.timg.addr < rdp.ci_end))2833{2834if (!rdp.fb_drawn)2835{2836if (!rdp.cur_image)2837CopyFrameBuffer();2838else2839CloseTextureBuffer(TRUE);2840rdp.fb_drawn = TRUE;2841}2842}28432844if (fb_hwfbe_enabled) //search this texture among drawn texture buffers2845FindTextureBuffer(rdp.timg.addr, rdp.timg.width);28462847FRDP("settextureimage: format: %s, size: %s, width: %d, addr: %08lx\n",2848format[rdp.timg.format], size[rdp.timg.size],2849rdp.timg.width, rdp.timg.addr);2850}28512852static void rdp_setdepthimage()2853{2854rdp.zimg = segoffset(rdp.cmd1) & BMASK;2855rdp.zi_width = rdp.ci_width;2856FRDP("setdepthimage - %08lx\n", rdp.zimg);2857}28582859int SwapOK = TRUE;2860static void RestoreScale()2861{2862FRDP("Return to original scale: x = %f, y = %f\n", rdp.scale_x_bak, rdp.scale_y_bak);2863rdp.scale_x = rdp.scale_x_bak;2864rdp.scale_y = rdp.scale_y_bak;2865// update_scissor();2866rdp.view_scale[0] *= rdp.scale_x;2867rdp.view_scale[1] *= rdp.scale_y;2868rdp.view_trans[0] *= rdp.scale_x;2869rdp.view_trans[1] *= rdp.scale_y;2870rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;2871//*2872if (fullscreen)2873{2874grDepthMask (FXFALSE);2875grBufferClear (0, 0, 0xFFFF);2876grDepthMask (FXTRUE);2877}2878//*/2879}28802881static wxUint32 swapped_addr = 0;28822883static void rdp_setcolorimage()2884{2885if (fb_emulation_enabled && (rdp.num_of_ci < NUMTEXBUF))2886{2887COLOR_IMAGE & cur_fb = rdp.frame_buffers[rdp.ci_count];2888COLOR_IMAGE & prev_fb = rdp.frame_buffers[rdp.ci_count?rdp.ci_count-1:0];2889COLOR_IMAGE & next_fb = rdp.frame_buffers[rdp.ci_count+1];2890switch (cur_fb.status)2891{2892case ci_main:2893{28942895if (rdp.ci_count == 0)2896{2897if ((rdp.ci_status == ci_aux)) //for PPL2898{2899float sx = rdp.scale_x;2900float sy = rdp.scale_y;2901rdp.scale_x = 1.0f;2902rdp.scale_y = 1.0f;2903CopyFrameBuffer ();2904rdp.scale_x = sx;2905rdp.scale_y = sy;2906}2907if (!fb_hwfbe_enabled)2908{2909if ((rdp.num_of_ci > 1) &&2910(next_fb.status == ci_aux) &&2911(next_fb.width >= cur_fb.width))2912{2913rdp.scale_x = 1.0f;2914rdp.scale_y = 1.0f;2915}2916}2917else if (rdp.copy_ci_index && (settings.hacks&hack_PMario)) //tidal wave2918OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);2919}2920else if (!rdp.motionblur && fb_hwfbe_enabled && !SwapOK && (rdp.ci_count <= rdp.copy_ci_index))2921{2922if (next_fb.status == ci_aux_copy)2923OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);2924else2925OpenTextureBuffer(rdp.frame_buffers[rdp.copy_ci_index]);2926}2927else if (fb_hwfbe_enabled && prev_fb.status == ci_aux)2928{2929if (rdp.motionblur)2930{2931rdp.cur_image = &(rdp.texbufs[rdp.cur_tex_buf].images[0]);2932grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );2933grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2,2934rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH );2935}2936else if (rdp.read_whole_frame)2937{2938OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);2939}2940}2941//else if (rdp.ci_status == ci_aux && !rdp.copy_ci_index)2942// CloseTextureBuffer();29432944rdp.skip_drawing = FALSE;2945}2946break;2947case ci_copy:2948{2949if (!rdp.motionblur || (settings.frame_buffer&fb_motionblur))2950{2951if (cur_fb.width == rdp.ci_width)2952{2953if (CopyTextureBuffer(prev_fb, cur_fb))2954{2955// if (CloseTextureBuffer(TRUE))2956//*2957if ((settings.hacks&hack_Zelda) && (rdp.frame_buffers[rdp.ci_count+2].status == ci_aux) && !rdp.fb_drawn) //hack for photo camera in Zelda MM2958{2959CopyFrameBuffer (GR_BUFFER_TEXTUREBUFFER_EXT);2960rdp.fb_drawn = TRUE;2961memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);2962}2963//*/2964}2965else2966{2967if (!rdp.fb_drawn || prev_fb.status == ci_copy_self)2968{2969CopyFrameBuffer ();2970rdp.fb_drawn = TRUE;2971}2972memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);2973}2974}2975else2976{2977CloseTextureBuffer(TRUE);2978}2979}2980else2981{2982memset(gfx.RDRAM+cur_fb.addr, 0, cur_fb.width*cur_fb.height*rdp.ci_size);2983}2984rdp.skip_drawing = TRUE;2985}2986break;2987case ci_aux_copy:2988{2989rdp.skip_drawing = FALSE;2990if (CloseTextureBuffer(prev_fb.status != ci_aux_copy))2991;2992else if (!rdp.fb_drawn)2993{2994CopyFrameBuffer ();2995rdp.fb_drawn = TRUE;2996}2997if (fb_hwfbe_enabled)2998OpenTextureBuffer(cur_fb);2999}3000break;3001case ci_old_copy:3002{3003if (!rdp.motionblur || (settings.frame_buffer&fb_motionblur))3004{3005if (cur_fb.width == rdp.ci_width)3006{3007memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.maincimg[1].addr, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);3008}3009//rdp.skip_drawing = TRUE;3010}3011else3012{3013memset(gfx.RDRAM+cur_fb.addr, 0, (cur_fb.width*cur_fb.height)<<rdp.ci_size>>1);3014}3015}3016break;3017/*3018else if (rdp.frame_buffers[rdp.ci_count].status == ci_main_i)3019{3020// CopyFrameBuffer ();3021rdp.scale_x = rdp.scale_x_bak;3022rdp.scale_y = rdp.scale_y_bak;3023rdp.skip_drawing = FALSE;3024}3025*/3026case ci_aux:3027{3028if (!fb_hwfbe_enabled && cur_fb.format != 0)3029rdp.skip_drawing = TRUE;3030else3031{3032rdp.skip_drawing = FALSE;3033if (fb_hwfbe_enabled && OpenTextureBuffer(cur_fb))3034;3035else3036{3037if (cur_fb.format != 0)3038rdp.skip_drawing = TRUE;3039if (rdp.ci_count == 0)3040{3041// if (rdp.num_of_ci > 1)3042// {3043rdp.scale_x = 1.0f;3044rdp.scale_y = 1.0f;3045// }3046}3047else if (!fb_hwfbe_enabled && (prev_fb.status == ci_main) &&3048(prev_fb.width == cur_fb.width)) // for Pokemon Stadium3049CopyFrameBuffer ();3050}3051}3052cur_fb.status = ci_aux;3053}3054break;3055case ci_zimg:3056if (settings.ucode != ucode_PerfectDark)3057{3058if (fb_hwfbe_enabled && !rdp.copy_ci_index && (rdp.copy_zi_index || (settings.hacks&hack_BAR)))3059{3060GrLOD_t LOD = GR_LOD_LOG2_1024;3061if (settings.scr_res_x > 1024)3062LOD = GR_LOD_LOG2_2048;3063grTextureAuxBufferExt( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, LOD, LOD,3064GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );3065grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT );3066LRDP("rdp_setcolorimage - set texture depth buffer to TMU0\n");3067}3068}3069rdp.skip_drawing = TRUE;3070break;3071case ci_zcopy:3072if (settings.ucode != ucode_PerfectDark)3073{3074if (fb_hwfbe_enabled && !rdp.copy_ci_index && rdp.copy_zi_index == rdp.ci_count)3075{3076CopyDepthBuffer();3077}3078rdp.skip_drawing = TRUE;3079}3080break;3081case ci_useless:3082rdp.skip_drawing = TRUE;3083break;3084case ci_copy_self:3085if (fb_hwfbe_enabled && (rdp.ci_count <= rdp.copy_ci_index) && (!SwapOK || settings.swapmode == 2))3086OpenTextureBuffer(cur_fb);3087rdp.skip_drawing = FALSE;3088break;3089default:3090rdp.skip_drawing = FALSE;3091}30923093if ((rdp.ci_count > 0) && (prev_fb.status >= ci_aux)) //for Pokemon Stadium3094{3095if (!fb_hwfbe_enabled && prev_fb.format == 0)3096CopyFrameBuffer ();3097else if ((settings.hacks&hack_Knockout) && prev_fb.width < 100)3098CopyFrameBuffer (GR_BUFFER_TEXTUREBUFFER_EXT);3099}3100if (!fb_hwfbe_enabled && cur_fb.status == ci_copy)3101{3102if (!rdp.motionblur && (rdp.num_of_ci > rdp.ci_count+1) && (next_fb.status != ci_aux))3103{3104RestoreScale();3105}3106}3107if (!fb_hwfbe_enabled && cur_fb.status == ci_aux)3108{3109if (cur_fb.format == 0)3110{3111if ((settings.hacks&hack_PPL) && (rdp.scale_x < 1.1f)) //need to put current image back to frame buffer3112{3113int width = cur_fb.width;3114int height = cur_fb.height;3115wxUint16 *ptr_dst = new wxUint16[width*height];3116wxUint16 *ptr_src = (wxUint16*)(gfx.RDRAM+cur_fb.addr);3117wxUint16 c;31183119for (int y=0; y<height; y++)3120{3121for (int x=0; x<width; x++)3122{3123c = ((ptr_src[(x + y * width)^1]) >> 1) | 0x8000;3124ptr_dst[x + y * width] = c;3125}3126}3127grLfbWriteRegion(GR_BUFFER_BACKBUFFER,3128(wxUint32)rdp.offset_x,3129(wxUint32)rdp.offset_y,3130GR_LFB_SRC_FMT_555,3131width,3132height,3133FXFALSE,3134width<<1,3135ptr_dst);3136delete[] ptr_dst;3137}3138/*3139else //just clear buffer3140{31413142grColorMask(FXTRUE, FXTRUE);3143grBufferClear (0, 0, 0xFFFF);3144}3145*/3146}3147}31483149if ((cur_fb.status == ci_main) && (rdp.ci_count > 0))3150{3151int to_org_res = TRUE;3152for (int i = rdp.ci_count + 1; i < rdp.num_of_ci; i++)3153{3154if ((rdp.frame_buffers[i].status != ci_main) && (rdp.frame_buffers[i].status != ci_zimg) && (rdp.frame_buffers[i].status != ci_zcopy))3155{3156to_org_res = FALSE;3157break;3158}3159}3160if (to_org_res)3161{3162LRDP("return to original scale\n");3163rdp.scale_x = rdp.scale_x_bak;3164rdp.scale_y = rdp.scale_y_bak;3165if (fb_hwfbe_enabled && !rdp.read_whole_frame)3166CloseTextureBuffer();3167}3168if (fb_hwfbe_enabled && !rdp.read_whole_frame && (prev_fb.status >= ci_aux) && (rdp.ci_count > rdp.copy_ci_index))3169CloseTextureBuffer();31703171}3172rdp.ci_status = cur_fb.status;3173rdp.ci_count++;3174}31753176rdp.ocimg = rdp.cimg;3177rdp.cimg = segoffset(rdp.cmd1) & BMASK;3178rdp.ci_width = (rdp.cmd0 & 0xFFF) + 1;3179if (fb_emulation_enabled)3180rdp.ci_height = rdp.frame_buffers[rdp.ci_count-1].height;3181else if (rdp.ci_width == 32)3182rdp.ci_height = 32;3183else3184rdp.ci_height = rdp.scissor_o.lr_y;3185if (rdp.zimg == rdp.cimg)3186{3187rdp.zi_width = rdp.ci_width;3188// int zi_height = min((int)rdp.zi_width*3/4, (int)rdp.vi_height);3189// rdp.zi_words = rdp.zi_width * zi_height;3190}3191wxUint32 format = (rdp.cmd0 >> 21) & 0x7;3192rdp.ci_size = (rdp.cmd0 >> 19) & 0x3;3193rdp.ci_end = rdp.cimg + ((rdp.ci_width*rdp.ci_height)<<(rdp.ci_size-1));3194FRDP("setcolorimage - %08lx, width: %d, height: %d, format: %d, size: %d\n", rdp.cmd1, rdp.ci_width, rdp.ci_height, format, rdp.ci_size);3195FRDP("cimg: %08lx, ocimg: %08lx, SwapOK: %d\n", rdp.cimg, rdp.ocimg, SwapOK);31963197if (format != 0) //can't draw into non RGBA buffer3198{3199if (!rdp.cur_image)3200{3201if (fb_hwfbe_enabled && rdp.ci_width <= 64)3202OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count - 1]);3203else if (format > 2)3204rdp.skip_drawing = TRUE;3205return;3206}3207}3208else3209{3210if (!fb_emulation_enabled)3211rdp.skip_drawing = FALSE;3212}32133214CI_SET = TRUE;3215if (settings.swapmode > 0)3216{3217if (rdp.zimg == rdp.cimg)3218rdp.updatescreen = 1;32193220int viSwapOK = ((settings.swapmode == 2) && (rdp.vi_org_reg == *gfx.VI_ORIGIN_REG)) ? FALSE : TRUE;3221if ((rdp.zimg != rdp.cimg) && (rdp.ocimg != rdp.cimg) && SwapOK && viSwapOK && !rdp.cur_image)3222{3223if (fb_emulation_enabled)3224rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index];3225else3226rdp.maincimg[0].addr = rdp.cimg;3227rdp.last_drawn_ci_addr = (settings.swapmode == 2) ? swapped_addr : rdp.maincimg[0].addr;3228swapped_addr = rdp.cimg;3229newSwapBuffers();3230rdp.vi_org_reg = *gfx.VI_ORIGIN_REG;3231SwapOK = FALSE;3232if (fb_hwfbe_enabled)3233{3234if (rdp.copy_ci_index && (rdp.frame_buffers[rdp.ci_count-1].status != ci_zimg))3235{3236int idx = (rdp.frame_buffers[rdp.ci_count].status == ci_aux_copy) ? rdp.main_ci_index : rdp.copy_ci_index;3237FRDP("attempt open tex buffer. status: %s, addr: %08lx\n", CIStatus[rdp.frame_buffers[idx].status], rdp.frame_buffers[idx].addr);3238OpenTextureBuffer(rdp.frame_buffers[idx]);3239if (rdp.frame_buffers[rdp.copy_ci_index].status == ci_main) //tidal wave3240rdp.copy_ci_index = 0;3241}3242else if (rdp.read_whole_frame && !rdp.cur_image)3243{3244OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);3245}3246}3247}3248}3249}32503251static void rsp_reserved0()3252{3253if (settings.ucode == ucode_DiddyKong)3254{3255ucode5_texshiftaddr = segoffset(rdp.cmd1);3256ucode5_texshiftcount = 0;3257FRDP("uc5_texshift. addr: %08lx\n", ucode5_texshiftaddr);3258}3259else3260{3261RDP_E("reserved0 - IGNORED\n");3262LRDP("reserved0 - IGNORED\n");3263}3264}32653266static void rsp_reserved1()3267{3268LRDP("reserved1 - ignored\n");3269}32703271static void rsp_reserved2()3272{3273LRDP("reserved2\n");3274}32753276static void rsp_reserved3()3277{3278LRDP("reserved3 - ignored\n");3279}32803281void SetWireframeCol ()3282{3283if (!fullscreen) return;32843285switch (settings.wfmode)3286{3287//case 0: // normal colors, don't do anything3288case 1: // vertex colors3289grColorCombine (GR_COMBINE_FUNCTION_LOCAL,3290GR_COMBINE_FACTOR_NONE,3291GR_COMBINE_LOCAL_ITERATED,3292GR_COMBINE_OTHER_NONE,3293FXFALSE);3294grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,3295GR_COMBINE_FACTOR_NONE,3296GR_COMBINE_LOCAL_ITERATED,3297GR_COMBINE_OTHER_NONE,3298FXFALSE);3299grAlphaBlendFunction (GR_BLEND_ONE,3300GR_BLEND_ZERO,3301GR_BLEND_ZERO,3302GR_BLEND_ZERO);3303grTexCombine (GR_TMU0,3304GR_COMBINE_FUNCTION_ZERO,3305GR_COMBINE_FACTOR_NONE,3306GR_COMBINE_FUNCTION_ZERO,3307GR_COMBINE_FACTOR_NONE,3308FXFALSE, FXFALSE);3309grTexCombine (GR_TMU1,3310GR_COMBINE_FUNCTION_ZERO,3311GR_COMBINE_FACTOR_NONE,3312GR_COMBINE_FUNCTION_ZERO,3313GR_COMBINE_FACTOR_NONE,3314FXFALSE, FXFALSE);3315break;3316case 2: // red only3317grColorCombine (GR_COMBINE_FUNCTION_LOCAL,3318GR_COMBINE_FACTOR_NONE,3319GR_COMBINE_LOCAL_CONSTANT,3320GR_COMBINE_OTHER_NONE,3321FXFALSE);3322grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,3323GR_COMBINE_FACTOR_NONE,3324GR_COMBINE_LOCAL_CONSTANT,3325GR_COMBINE_OTHER_NONE,3326FXFALSE);3327grConstantColorValue (0xFF0000FF);3328grAlphaBlendFunction (GR_BLEND_ONE,3329GR_BLEND_ZERO,3330GR_BLEND_ZERO,3331GR_BLEND_ZERO);3332grTexCombine (GR_TMU0,3333GR_COMBINE_FUNCTION_ZERO,3334GR_COMBINE_FACTOR_NONE,3335GR_COMBINE_FUNCTION_ZERO,3336GR_COMBINE_FACTOR_NONE,3337FXFALSE, FXFALSE);3338grTexCombine (GR_TMU1,3339GR_COMBINE_FUNCTION_ZERO,3340GR_COMBINE_FACTOR_NONE,3341GR_COMBINE_FUNCTION_ZERO,3342GR_COMBINE_FACTOR_NONE,3343FXFALSE, FXFALSE);3344break;3345}33463347grAlphaTestFunction (GR_CMP_ALWAYS);3348grCullMode (GR_CULL_DISABLE);33493350rdp.update |= UPDATE_COMBINE | UPDATE_ALPHA_COMPARE;3351}33523353/******************************************************************3354Function: FrameBufferRead3355Purpose: This function is called to notify the dll that the3356frame buffer memory is beening read at the given address.3357DLL should copy content from its render buffer to the frame buffer3358in N64 RDRAM3359DLL is responsible to maintain its own frame buffer memory addr list3360DLL should copy 4KB block content back to RDRAM frame buffer.3361Emulator should not call this function again if other memory3362is read within the same 4KB range3363input: addr rdram address3364val val3365size 1 = wxUint8, 2 = wxUint16, 4 = wxUint323366output: none3367*******************************************************************/33683369#ifdef __cplusplus3370extern "C" {3371#endif33723373EXPORT void CALL FBRead(wxUint32 addr)3374{3375LOG ("FBRead ()\n");33763377if (cpu_fb_ignore)3378return;3379if (cpu_fb_write_called)3380{3381cpu_fb_ignore = TRUE;3382cpu_fb_write = FALSE;3383return;3384}3385cpu_fb_read_called = TRUE;3386wxUint32 a = segoffset(addr);3387FRDP("FBRead. addr: %08lx\n", a);3388if (!rdp.fb_drawn && (a >= rdp.cimg) && (a < rdp.ci_end))3389{3390fbreads_back++;3391//if (fbreads_back > 2) //&& (rdp.ci_width <= 320))3392{3393CopyFrameBuffer ();3394rdp.fb_drawn = TRUE;3395}3396}3397if (!rdp.fb_drawn_front && (a >= rdp.maincimg[1].addr) && (a < rdp.maincimg[1].addr + rdp.ci_width*rdp.ci_height*2))3398{3399fbreads_front++;3400//if (fbreads_front > 2)//&& (rdp.ci_width <= 320))3401{3402wxUint32 cimg = rdp.cimg;3403rdp.cimg = rdp.maincimg[1].addr;3404if (fb_emulation_enabled)3405{3406rdp.ci_width = rdp.maincimg[1].width;3407rdp.ci_count = 0;3408wxUint32 h = rdp.frame_buffers[0].height;3409rdp.frame_buffers[0].height = rdp.maincimg[1].height;3410CopyFrameBuffer(GR_BUFFER_FRONTBUFFER);3411rdp.frame_buffers[0].height = h;3412}3413else3414{3415CopyFrameBuffer(GR_BUFFER_FRONTBUFFER);3416}3417rdp.cimg = cimg;3418rdp.fb_drawn_front = TRUE;3419}3420}3421}34223423#if 03424/******************************************************************3425Function: FrameBufferWriteList3426Purpose: This function is called to notify the dll that the3427frame buffer has been modified by CPU at the given address.3428input: FrameBufferModifyEntry *plist3429size = size of the plist, max = 10243430output: none3431*******************************************************************/3432EXPORT void CALL FBWList(FrameBufferModifyEntry *plist, wxUint32 size)3433{3434LOG ("FBWList ()\n");3435FRDP("FBWList. size: %d\n", size);3436}3437#endif34383439/******************************************************************3440Function: FrameBufferWrite3441Purpose: This function is called to notify the dll that the3442frame buffer has been modified by CPU at the given address.3443input: addr rdram address3444val val3445size 1 = wxUint8, 2 = wxUint16, 4 = wxUint323446output: none3447*******************************************************************/3448EXPORT void CALL FBWrite(wxUint32 addr, wxUint32 size)3449{3450LOG ("FBWrite ()\n");3451if (cpu_fb_ignore)3452return;3453if (cpu_fb_read_called)3454{3455cpu_fb_ignore = TRUE;3456cpu_fb_write = FALSE;3457return;3458}3459cpu_fb_write_called = TRUE;3460wxUint32 a = segoffset(addr);3461FRDP("FBWrite. addr: %08lx\n", a);3462if (a < rdp.cimg || a > rdp.ci_end)3463return;3464cpu_fb_write = TRUE;3465wxUint32 shift_l = (a-rdp.cimg) >> 1;3466wxUint32 shift_r = shift_l+2;34673468d_ul_x = min(d_ul_x, shift_l%rdp.ci_width);3469d_ul_y = min(d_ul_y, shift_l/rdp.ci_width);3470d_lr_x = max(d_lr_x, shift_r%rdp.ci_width);3471d_lr_y = max(d_lr_y, shift_r/rdp.ci_width);3472}347334743475/************************************************************************3476Function: FBGetFrameBufferInfo3477Purpose: This function is called by the emulator core to retrieve frame3478buffer information from the video plugin in order to be able3479to notify the video plugin about CPU frame buffer read/write3480operations34813482size:3483= 1 byte3484= 2 word (16 bit) <-- this is N64 default depth buffer format3485= 4 dword (32 bit)34863487when frame buffer information is not available yet, set all values3488in the FrameBufferInfo structure to 034893490input: FrameBufferInfo pinfo[6]3491pinfo is pointed to a FrameBufferInfo structure which to be3492filled in by this function3493output: Values are return in the FrameBufferInfo structure3494Plugin can return up to 6 frame buffer info3495************************************************************************/3496///*3497#if 03498typedef struct3499{3500wxUint32 addr;3501wxUint32 size;3502wxUint32 width;3503wxUint32 height;3504} FrameBufferInfo;3505#endif3506EXPORT void CALL FBGetFrameBufferInfo(void *p)3507{3508VLOG ("FBGetFrameBufferInfo ()\n");3509FrameBufferInfo * pinfo = (FrameBufferInfo *)p;3510memset(pinfo,0,sizeof(FrameBufferInfo)*6);3511if (!(settings.frame_buffer&fb_get_info))3512return;3513LRDP("FBGetFrameBufferInfo ()\n");3514//*3515if (fb_emulation_enabled)3516{3517pinfo[0].addr = rdp.maincimg[1].addr;3518pinfo[0].size = rdp.maincimg[1].size;3519pinfo[0].width = rdp.maincimg[1].width;3520pinfo[0].height = rdp.maincimg[1].height;3521int info_index = 1;3522for (int i = 0; i < rdp.num_of_ci && info_index < 6; i++)3523{3524COLOR_IMAGE & cur_fb = rdp.frame_buffers[i];3525if (cur_fb.status == ci_main || cur_fb.status == ci_copy_self ||3526cur_fb.status == ci_old_copy)3527{3528pinfo[info_index].addr = cur_fb.addr;3529pinfo[info_index].size = cur_fb.size;3530pinfo[info_index].width = cur_fb.width;3531pinfo[info_index].height = cur_fb.height;3532info_index++;3533}3534}3535}3536else3537{3538pinfo[0].addr = rdp.maincimg[0].addr;3539pinfo[0].size = rdp.ci_size;3540pinfo[0].width = rdp.ci_width;3541pinfo[0].height = rdp.ci_width*3/4;3542pinfo[1].addr = rdp.maincimg[1].addr;3543pinfo[1].size = rdp.ci_size;3544pinfo[1].width = rdp.ci_width;3545pinfo[1].height = rdp.ci_width*3/4;3546}3547//*/3548}3549#ifdef __cplusplus3550}3551#endif3552//*/3553#include "ucodeFB.h"35543555void DetectFrameBufferUsage ()3556{3557LRDP("DetectFrameBufferUsage\n");35583559wxUint32 dlist_start = *(wxUint32*)(gfx.DMEM+0xFF0);3560wxUint32 a;35613562int tidal = FALSE;3563if ((settings.hacks&hack_PMario) && (rdp.copy_ci_index || rdp.frame_buffers[rdp.copy_ci_index].status == ci_copy_self))3564tidal = TRUE;3565wxUint32 ci = rdp.cimg, zi = rdp.zimg;3566wxUint32 ci_height = rdp.frame_buffers[(rdp.ci_count > 0)?rdp.ci_count-1:0].height;3567rdp.main_ci = rdp.main_ci_end = rdp.main_ci_bg = rdp.ci_count = 0;3568rdp.main_ci_index = rdp.copy_ci_index = rdp.copy_zi_index = 0;3569rdp.zimg_end = 0;3570rdp.tmpzimg = 0;3571rdp.motionblur = FALSE;3572rdp.main_ci_last_tex_addr = 0;3573int previous_ci_was_read = rdp.read_previous_ci;3574rdp.read_previous_ci = FALSE;3575rdp.read_whole_frame = FALSE;3576rdp.swap_ci_index = rdp.black_ci_index = -1;3577SwapOK = TRUE;35783579// Start executing at the start of the display list3580rdp.pc_i = 0;3581rdp.pc[rdp.pc_i] = dlist_start;3582rdp.dl_count = -1;3583rdp.halt = 0;3584rdp.scale_x_bak = rdp.scale_x;3585rdp.scale_y_bak = rdp.scale_y;35863587// MAIN PROCESSING LOOP3588do {35893590// Get the address of the next command3591a = rdp.pc[rdp.pc_i] & BMASK;35923593// Load the next command and its input3594rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit3595rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // /35963597// Output the address before the command35983599// Go to the next instruction3600rdp.pc[rdp.pc_i] = (a+8) & BMASK;36013602if (wxPtrToUInt(reinterpret_cast<void*>(gfx_instruction_lite[settings.ucode][rdp.cmd0>>24])))3603gfx_instruction_lite[settings.ucode][rdp.cmd0>>24] ();36043605// check DL counter3606if (rdp.dl_count != -1)3607{3608rdp.dl_count --;3609if (rdp.dl_count == 0)3610{3611rdp.dl_count = -1;36123613LRDP("End of DL\n");3614rdp.pc_i --;3615}3616}36173618} while (!rdp.halt);3619SwapOK = TRUE;3620if (rdp.ci_count > NUMTEXBUF) //overflow3621{3622rdp.cimg = ci;3623rdp.zimg = zi;3624rdp.num_of_ci = rdp.ci_count;3625rdp.scale_x = rdp.scale_x_bak;3626rdp.scale_y = rdp.scale_y_bak;3627return;3628}36293630if (rdp.black_ci_index > 0 && rdp.black_ci_index < rdp.copy_ci_index)3631rdp.frame_buffers[rdp.black_ci_index].status = ci_main;36323633if (rdp.frame_buffers[rdp.ci_count-1].status == ci_unknown)3634{3635if (rdp.ci_count > 1)3636rdp.frame_buffers[rdp.ci_count-1].status = ci_aux;3637else3638rdp.frame_buffers[rdp.ci_count-1].status = ci_main;3639}36403641if ((rdp.frame_buffers[rdp.ci_count-1].status == ci_aux) &&3642(rdp.frame_buffers[rdp.main_ci_index].width < 320) &&3643(rdp.frame_buffers[rdp.ci_count-1].width > rdp.frame_buffers[rdp.main_ci_index].width))3644{3645for (int i = 0; i < rdp.ci_count; i++)3646{3647if (rdp.frame_buffers[i].status == ci_main)3648rdp.frame_buffers[i].status = ci_aux;3649else if (rdp.frame_buffers[i].addr == rdp.frame_buffers[rdp.ci_count-1].addr)3650rdp.frame_buffers[i].status = ci_main;3651// FRDP("rdp.frame_buffers[%d].status = %d\n", i, rdp.frame_buffers[i].status);3652}3653rdp.main_ci_index = rdp.ci_count-1;3654}36553656int all_zimg = TRUE;3657int i;3658for (i = 0; i < rdp.ci_count; i++)3659{3660if (rdp.frame_buffers[i].status != ci_zimg)3661{3662all_zimg = FALSE;3663break;3664}3665}3666if (all_zimg)3667{3668for (i = 0; i < rdp.ci_count; i++)3669rdp.frame_buffers[i].status = ci_main;3670}36713672LRDP("detect fb final results: \n");3673for (i = 0; i < rdp.ci_count; i++)3674{3675FRDP("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);3676}36773678rdp.cimg = ci;3679rdp.zimg = zi;3680rdp.num_of_ci = rdp.ci_count;3681if (rdp.read_previous_ci && previous_ci_was_read)3682{3683if (!fb_hwfbe_enabled || !rdp.copy_ci_index)3684rdp.motionblur = TRUE;3685}3686if (rdp.motionblur || fb_hwfbe_enabled || (rdp.frame_buffers[rdp.copy_ci_index].status == ci_aux_copy))3687{3688rdp.scale_x = rdp.scale_x_bak;3689rdp.scale_y = rdp.scale_y_bak;3690}36913692if ((rdp.read_previous_ci || previous_ci_was_read) && !rdp.copy_ci_index)3693rdp.read_whole_frame = TRUE;3694if (rdp.read_whole_frame)3695{3696if (fb_hwfbe_enabled)3697{3698if (rdp.read_previous_ci && !previous_ci_was_read && (settings.swapmode != 2) && (settings.ucode != ucode_PerfectDark))3699{3700int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0;3701wxUint32 height = rdp.frame_buffers[ind].height;3702rdp.frame_buffers[ind].height = ci_height;3703CopyFrameBuffer();3704rdp.frame_buffers[ind].height = height;3705}3706if (rdp.swap_ci_index < 0)3707{3708rdp.texbufs[0].clear_allowed = rdp.texbufs[1].clear_allowed = TRUE;3709OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);3710}3711}3712else3713{3714if (rdp.motionblur)3715{3716if (settings.frame_buffer&fb_motionblur)3717CopyFrameBuffer();3718else3719memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size);3720}3721else //if (ci_width == rdp.frame_buffers[rdp.main_ci_index].width)3722{3723if (rdp.maincimg[0].height > 65) //for 10803724{3725rdp.cimg = rdp.maincimg[0].addr;3726rdp.ci_width = rdp.maincimg[0].width;3727rdp.ci_count = 0;3728wxUint32 h = rdp.frame_buffers[0].height;3729rdp.frame_buffers[0].height = rdp.maincimg[0].height;3730CopyFrameBuffer();3731rdp.frame_buffers[0].height = h;3732}3733else //conker3734{3735CopyFrameBuffer();3736}3737}3738}3739}37403741if (fb_hwfbe_enabled)3742{3743for (i = 0; i < voodoo.num_tmu; i++)3744{3745rdp.texbufs[i].clear_allowed = TRUE;3746for (int j = 0; j < 256; j++)3747{3748rdp.texbufs[i].images[j].drawn = FALSE;3749rdp.texbufs[i].images[j].clear = TRUE;3750}3751}3752if (tidal)3753{3754//LRDP("Tidal wave!\n");3755rdp.copy_ci_index = rdp.main_ci_index;3756}3757}3758rdp.ci_count = 0;3759if (settings.hacks&hack_Banjo2)3760rdp.cur_tex_buf = 0;3761rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index];3762// rdp.scale_x = rdp.scale_x_bak;3763// rdp.scale_y = rdp.scale_y_bak;3764LRDP("DetectFrameBufferUsage End\n");3765}37663767/*******************************************3768* ProcessRDPList *3769*******************************************3770* based on sources of ziggy's z64 *3771*******************************************/37723773static wxUint32 rdp_cmd_ptr = 0;3774static wxUint32 rdp_cmd_cur = 0;3775static wxUint32 rdp_cmd_data[0x1000];37763777void lle_triangle(wxUint32 w1, wxUint32 w2, int shade, int texture, int zbuffer,3778wxUint32 * rdp_cmd)3779{3780rdp.cur_tile = (w1 >> 16) & 0x7;3781int j;3782int xleft, xright, xleft_inc, xright_inc;3783int r, g, b, a, z, s, t, w;3784int drdx = 0, dgdx = 0, dbdx = 0, dadx = 0, dzdx = 0, dsdx = 0, dtdx = 0, dwdx = 0;3785int drde = 0, dgde = 0, dbde = 0, dade = 0, dzde = 0, dsde = 0, dtde = 0, dwde = 0;3786int flip = (w1 & 0x800000) ? 1 : 0;37873788wxInt32 yl, ym, yh;3789wxInt32 xl, xm, xh;3790wxInt32 dxldy, dxhdy, dxmdy;3791wxUint32 w3, w4, w5, w6, w7, w8;37923793wxUint32 * shade_base = rdp_cmd + 8;3794wxUint32 * texture_base = rdp_cmd + 8;3795wxUint32 * zbuffer_base = rdp_cmd + 8;37963797if (shade)3798{3799texture_base += 16;3800zbuffer_base += 16;3801}3802if (texture)3803{3804zbuffer_base += 16;3805}38063807w3 = rdp_cmd[2];3808w4 = rdp_cmd[3];3809w5 = rdp_cmd[4];3810w6 = rdp_cmd[5];3811w7 = rdp_cmd[6];3812w8 = rdp_cmd[7];38133814yl = (w1 & 0x3fff);3815ym = ((w2 >> 16) & 0x3fff);3816yh = ((w2 >> 0) & 0x3fff);3817xl = (wxInt32)(w3);3818xh = (wxInt32)(w5);3819xm = (wxInt32)(w7);3820dxldy = (wxInt32)(w4);3821dxhdy = (wxInt32)(w6);3822dxmdy = (wxInt32)(w8);38233824if (yl & (0x800<<2)) yl |= 0xfffff000<<2;3825if (ym & (0x800<<2)) ym |= 0xfffff000<<2;3826if (yh & (0x800<<2)) yh |= 0xfffff000<<2;38273828yh &= ~3;38293830r = 0xff; g = 0xff; b = 0xff; a = 0xff; z = 0xffff0000; s = 0; t = 0; w = 0x30000;38313832if (shade)3833{3834r = (shade_base[0] & 0xffff0000) | ((shade_base[+4 ] >> 16) & 0x0000ffff);3835g = ((shade_base[0 ] << 16) & 0xffff0000) | (shade_base[4 ] & 0x0000ffff);3836b = (shade_base[1 ] & 0xffff0000) | ((shade_base[5 ] >> 16) & 0x0000ffff);3837a = ((shade_base[1 ] << 16) & 0xffff0000) | (shade_base[5 ] & 0x0000ffff);3838drdx = (shade_base[2 ] & 0xffff0000) | ((shade_base[6 ] >> 16) & 0x0000ffff);3839dgdx = ((shade_base[2 ] << 16) & 0xffff0000) | (shade_base[6 ] & 0x0000ffff);3840dbdx = (shade_base[3 ] & 0xffff0000) | ((shade_base[7 ] >> 16) & 0x0000ffff);3841dadx = ((shade_base[3 ] << 16) & 0xffff0000) | (shade_base[7 ] & 0x0000ffff);3842drde = (shade_base[8 ] & 0xffff0000) | ((shade_base[12] >> 16) & 0x0000ffff);3843dgde = ((shade_base[8 ] << 16) & 0xffff0000) | (shade_base[12] & 0x0000ffff);3844dbde = (shade_base[9 ] & 0xffff0000) | ((shade_base[13] >> 16) & 0x0000ffff);3845dade = ((shade_base[9 ] << 16) & 0xffff0000) | (shade_base[13] & 0x0000ffff);3846}3847if (texture)3848{3849s = (texture_base[0 ] & 0xffff0000) | ((texture_base[4 ] >> 16) & 0x0000ffff);3850t = ((texture_base[0 ] << 16) & 0xffff0000) | (texture_base[4 ] & 0x0000ffff);3851w = (texture_base[1 ] & 0xffff0000) | ((texture_base[5 ] >> 16) & 0x0000ffff);3852// w = abs(w);3853dsdx = (texture_base[2 ] & 0xffff0000) | ((texture_base[6 ] >> 16) & 0x0000ffff);3854dtdx = ((texture_base[2 ] << 16) & 0xffff0000) | (texture_base[6 ] & 0x0000ffff);3855dwdx = (texture_base[3 ] & 0xffff0000) | ((texture_base[7 ] >> 16) & 0x0000ffff);3856dsde = (texture_base[8 ] & 0xffff0000) | ((texture_base[12] >> 16) & 0x0000ffff);3857dtde = ((texture_base[8 ] << 16) & 0xffff0000) | (texture_base[12] & 0x0000ffff);3858dwde = (texture_base[9 ] & 0xffff0000) | ((texture_base[13] >> 16) & 0x0000ffff);3859}3860if (zbuffer)3861{3862z = zbuffer_base[0];3863dzdx = zbuffer_base[1];3864dzde = zbuffer_base[2];3865}38663867xh <<= 2; xm <<= 2; xl <<= 2;3868r <<= 2; g <<= 2; b <<= 2; a <<= 2;3869dsde >>= 2; dtde >>= 2; dsdx >>= 2; dtdx >>= 2;3870dzdx >>= 2; dzde >>= 2;3871dwdx >>= 2; dwde >>= 2;38723873#define XSCALE(x) (float(x)/(1<<18))3874#define YSCALE(y) (float(y)/(1<<2))3875#define ZSCALE(z) ((rdp.zsrc == 1)? float(rdp.prim_depth) : float(wxUint32(z))/0xffff0000)3876//#define WSCALE(w) (rdp.Persp_en? (float(wxUint32(w) + 0x10000)/0xffff0000) : 1.0f)3877//#define WSCALE(w) (rdp.Persp_en? 4294901760.0/(w + 65536) : 1.0f)3878#define WSCALE(w) (rdp.Persp_en? 65536.0f/float((w+ 0xffff)>>16) : 1.0f)3879#define CSCALE(c) (((c)>0x3ff0000? 0x3ff0000:((c)<0? 0 : (c)))>>18)3880#define _PERSP(w) ( w )3881#define PERSP(s, w) ( ((int64_t)(s) << 20) / (_PERSP(w)? _PERSP(w):1) )3882#define SSCALE(s, _w) (rdp.Persp_en? float(PERSP(s, _w))/(1 << 10) : float(s)/(1<<21))3883#define TSCALE(s, w) (rdp.Persp_en? float(PERSP(s, w))/(1 << 10) : float(s)/(1<<21))38843885int nbVtxs = 0;3886VERTEX vtxbuf[12];3887VERTEX * vtx = &vtxbuf[nbVtxs++];38883889xleft = xm;3890xright = xh;3891xleft_inc = dxmdy;3892xright_inc = dxhdy;38933894while (yh<ym &&3895!((!flip && xleft < xright+0x10000) ||3896(flip && xleft > xright-0x10000))) {3897xleft += xleft_inc;3898xright += xright_inc;3899s += dsde; t += dtde; w += dwde;3900r += drde; g += dgde; b += dbde; a += dade;3901z += dzde;3902yh++;3903}39043905j = ym-yh;3906if (j > 0)3907{3908int dx = (xleft-xright)>>16;3909if ((!flip && xleft < xright) ||3910(flip/* && xleft > xright*/))3911{3912if (shade) {3913vtx->r = CSCALE(r+drdx*dx);3914vtx->g = CSCALE(g+dgdx*dx);3915vtx->b = CSCALE(b+dbdx*dx);3916vtx->a = CSCALE(a+dadx*dx);3917}3918if (texture) {3919vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx);3920vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx);3921}3922vtx->x = XSCALE(xleft);3923vtx->y = YSCALE(yh);3924vtx->z = ZSCALE(z+dzdx*dx);3925vtx->w = WSCALE(w+dwdx*dx);3926vtx = &vtxbuf[nbVtxs++];3927}3928if ((!flip/* && xleft < xright*/) ||3929(flip && xleft > xright))3930{3931if (shade) {3932vtx->r = CSCALE(r);3933vtx->g = CSCALE(g);3934vtx->b = CSCALE(b);3935vtx->a = CSCALE(a);3936}3937if (texture) {3938vtx->ou = SSCALE(s, w);3939vtx->ov = TSCALE(t, w);3940}3941vtx->x = XSCALE(xright);3942vtx->y = YSCALE(yh);3943vtx->z = ZSCALE(z);3944vtx->w = WSCALE(w);3945vtx = &vtxbuf[nbVtxs++];3946}3947xleft += xleft_inc*j; xright += xright_inc*j;3948s += dsde*j; t += dtde*j;3949if (w + dwde*j) w += dwde*j;3950else w += dwde*(j-1);3951r += drde*j; g += dgde*j; b += dbde*j; a += dade*j;3952z += dzde*j;3953// render ...3954}39553956if (xl != xh)3957xleft = xl;39583959//if (yl-ym > 0)3960{3961int dx = (xleft-xright)>>16;3962if ((!flip && xleft <= xright) ||3963(flip/* && xleft >= xright*/))3964{3965if (shade) {3966vtx->r = CSCALE(r+drdx*dx);3967vtx->g = CSCALE(g+dgdx*dx);3968vtx->b = CSCALE(b+dbdx*dx);3969vtx->a = CSCALE(a+dadx*dx);3970}3971if (texture) {3972vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx);3973vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx);3974}3975vtx->x = XSCALE(xleft);3976vtx->y = YSCALE(ym);3977vtx->z = ZSCALE(z+dzdx*dx);3978vtx->w = WSCALE(w+dwdx*dx);3979vtx = &vtxbuf[nbVtxs++];3980}3981if ((!flip/* && xleft <= xright*/) ||3982(flip && xleft >= xright))3983{3984if (shade) {3985vtx->r = CSCALE(r);3986vtx->g = CSCALE(g);3987vtx->b = CSCALE(b);3988vtx->a = CSCALE(a);3989}3990if (texture) {3991vtx->ou = SSCALE(s, w);3992vtx->ov = TSCALE(t, w);3993}3994vtx->x = XSCALE(xright);3995vtx->y = YSCALE(ym);3996vtx->z = ZSCALE(z);3997vtx->w = WSCALE(w);3998vtx = &vtxbuf[nbVtxs++];3999}4000}4001xleft_inc = dxldy;4002xright_inc = dxhdy;40034004j = yl-ym;4005//j--; // ?4006xleft += xleft_inc*j; xright += xright_inc*j;4007s += dsde*j; t += dtde*j; w += dwde*j;4008r += drde*j; g += dgde*j; b += dbde*j; a += dade*j;4009z += dzde*j;40104011while (yl>ym &&4012!((!flip && xleft < xright+0x10000) ||4013(flip && xleft > xright-0x10000))) {4014xleft -= xleft_inc; xright -= xright_inc;4015s -= dsde; t -= dtde; w -= dwde;4016r -= drde; g -= dgde; b -= dbde; a -= dade;4017z -= dzde;4018j--;4019yl--;4020}40214022// render ...4023if (j >= 0) {4024int dx = (xleft-xright)>>16;4025if ((!flip && xleft <= xright) ||4026(flip/* && xleft >= xright*/))4027{4028if (shade) {4029vtx->r = CSCALE(r+drdx*dx);4030vtx->g = CSCALE(g+dgdx*dx);4031vtx->b = CSCALE(b+dbdx*dx);4032vtx->a = CSCALE(a+dadx*dx);4033}4034if (texture) {4035vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx);4036vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx);4037}4038vtx->x = XSCALE(xleft);4039vtx->y = YSCALE(yl);4040vtx->z = ZSCALE(z+dzdx*dx);4041vtx->w = WSCALE(w+dwdx*dx);4042vtx = &vtxbuf[nbVtxs++];4043}4044if ((!flip/* && xleft <= xright*/) ||4045(flip && xleft >= xright))4046{4047if (shade) {4048vtx->r = CSCALE(r);4049vtx->g = CSCALE(g);4050vtx->b = CSCALE(b);4051vtx->a = CSCALE(a);4052}4053if (texture) {4054vtx->ou = SSCALE(s, w);4055vtx->ov = TSCALE(t, w);4056}4057vtx->x = XSCALE(xright);4058vtx->y = YSCALE(yl);4059vtx->z = ZSCALE(z);4060vtx->w = WSCALE(w);4061vtx = &vtxbuf[nbVtxs++];4062}4063}40644065if (fullscreen)4066{4067update ();4068for (int k = 0; k < nbVtxs-1; k++)4069{4070VERTEX * v = &vtxbuf[k];4071v->x = v->x * rdp.scale_x + rdp.offset_x;4072v->y = v->y * rdp.scale_y + rdp.offset_y;4073// v->z = 1.0f;///v->w;4074v->q = 1.0f/v->w;4075v->u1 = v->u0 = v->ou;4076v->v1 = v->v0 = v->ov;4077if (rdp.tex >= 1 && rdp.cur_cache[0])4078{4079if (rdp.tiles[rdp.cur_tile].shift_s)4080{4081if (rdp.tiles[rdp.cur_tile].shift_s > 10)4082v->u0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s));4083else4084v->u0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_s);4085}4086if (rdp.tiles[rdp.cur_tile].shift_t)4087{4088if (rdp.tiles[rdp.cur_tile].shift_t > 10)4089v->v0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t));4090else4091v->v0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_t);4092}40934094v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;4095v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t;4096v->u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * v->u0;4097v->v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * v->v0;4098v->u0 /= v->w;4099v->v0 /= v->w;4100}41014102if (rdp.tex >= 2 && rdp.cur_cache[1])4103{4104if (rdp.tiles[rdp.cur_tile+1].shift_s)4105{4106if (rdp.tiles[rdp.cur_tile+1].shift_s > 10)4107v->u1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s));4108else4109v->u1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_s);4110}4111if (rdp.tiles[rdp.cur_tile+1].shift_t)4112{4113if (rdp.tiles[rdp.cur_tile+1].shift_t > 10)4114v->v1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t));4115else4116v->v1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_t);4117}41184119v->u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s;4120v->v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t;4121v->u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * v->u1;4122v->v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * v->v1;4123v->u1 /= v->w;4124v->v1 /= v->w;4125}4126apply_shade_mods (v);4127}4128ConvertCoordsConvert (vtxbuf, nbVtxs);4129grCullMode (GR_CULL_DISABLE);4130grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, nbVtxs-1, vtxbuf, sizeof(VERTEX));4131if (_debugger.capture)4132{4133VERTEX vl[3];4134vl[0] = vtxbuf[0];4135vl[1] = vtxbuf[2];4136vl[2] = vtxbuf[1];4137add_tri (vl, 3, TRI_TRIANGLE);4138rdp.tri_n++;4139if (nbVtxs > 4)4140{4141vl[0] = vtxbuf[2];4142vl[1] = vtxbuf[3];4143vl[2] = vtxbuf[1];4144add_tri (vl, 3, TRI_TRIANGLE);4145rdp.tri_n++;4146}4147}4148}4149}41504151static void rdp_triangle(int shade, int texture, int zbuffer)4152{4153lle_triangle(rdp.cmd0, rdp.cmd1, shade, texture, zbuffer, rdp_cmd_data + rdp_cmd_cur);4154}41554156static void rdp_trifill()4157{4158rdp_triangle(0, 0, 0);4159LRDP("trifill\n");4160}41614162static void rdp_trishade()4163{4164rdp_triangle(1, 0, 0);4165LRDP("trishade\n");4166}41674168static void rdp_tritxtr()4169{4170rdp_triangle(0, 1, 0);4171LRDP("tritxtr\n");4172}41734174static void rdp_trishadetxtr()4175{4176rdp_triangle(1, 1, 0);4177LRDP("trishadetxtr\n");4178}41794180static void rdp_trifillz()4181{4182rdp_triangle(0, 0, 1);4183LRDP("trifillz\n");4184}41854186static void rdp_trishadez()4187{4188rdp_triangle(1, 0, 1);4189LRDP("trishadez\n");4190}41914192static void rdp_tritxtrz()4193{4194rdp_triangle(0, 1, 1);4195LRDP("tritxtrz\n");4196}41974198static void rdp_trishadetxtrz()4199{4200rdp_triangle(1, 1, 1);4201LRDP("trishadetxtrz\n");4202}420342044205static rdp_instr rdp_command_table[64] =4206{4207/* 0x00 */4208spnoop, undef, undef, undef,4209undef, undef, undef, undef,4210rdp_trifill, rdp_trifillz, rdp_tritxtr, rdp_tritxtrz,4211rdp_trishade, rdp_trishadez, rdp_trishadetxtr, rdp_trishadetxtrz,4212/* 0x10 */4213undef, undef, undef, undef,4214undef, undef, undef, undef,4215undef, undef, undef, undef,4216undef, undef, undef, undef,4217/* 0x20 */4218undef, undef, undef, undef,4219rdp_texrect, rdp_texrect, rdp_loadsync, rdp_pipesync,4220rdp_tilesync, rdp_fullsync, rdp_setkeygb, rdp_setkeyr,4221rdp_setconvert, rdp_setscissor, rdp_setprimdepth, rdp_setothermode,4222/* 0x30 */4223rdp_loadtlut, undef, rdp_settilesize, rdp_loadblock,4224rdp_loadtile, rdp_settile, rdp_fillrect, rdp_setfillcolor,4225rdp_setfogcolor, rdp_setblendcolor, rdp_setprimcolor, rdp_setenvcolor,4226rdp_setcombine, rdp_settextureimage, rdp_setdepthimage, rdp_setcolorimage4227};42284229static const wxUint32 rdp_command_length[64] =4230{42318, // 0x00, No Op42328, // 0x01, ???42338, // 0x02, ???42348, // 0x03, ???42358, // 0x04, ???42368, // 0x05, ???42378, // 0x06, ???42388, // 0x07, ???423932, // 0x08, Non-Shaded Triangle424032+16, // 0x09, Non-Shaded, Z-Buffered Triangle424132+64, // 0x0a, Textured Triangle424232+64+16, // 0x0b, Textured, Z-Buffered Triangle424332+64, // 0x0c, Shaded Triangle424432+64+16, // 0x0d, Shaded, Z-Buffered Triangle424532+64+64, // 0x0e, Shaded+Textured Triangle424632+64+64+16,// 0x0f, Shaded+Textured, Z-Buffered Triangle42478, // 0x10, ???42488, // 0x11, ???42498, // 0x12, ???42508, // 0x13, ???42518, // 0x14, ???42528, // 0x15, ???42538, // 0x16, ???42548, // 0x17, ???42558, // 0x18, ???42568, // 0x19, ???42578, // 0x1a, ???42588, // 0x1b, ???42598, // 0x1c, ???42608, // 0x1d, ???42618, // 0x1e, ???42628, // 0x1f, ???42638, // 0x20, ???42648, // 0x21, ???42658, // 0x22, ???42668, // 0x23, ???426716, // 0x24, Texture_Rectangle426816, // 0x25, Texture_Rectangle_Flip42698, // 0x26, Sync_Load42708, // 0x27, Sync_Pipe42718, // 0x28, Sync_Tile42728, // 0x29, Sync_Full42738, // 0x2a, Set_Key_GB42748, // 0x2b, Set_Key_R42758, // 0x2c, Set_Convert42768, // 0x2d, Set_Scissor42778, // 0x2e, Set_Prim_Depth42788, // 0x2f, Set_Other_Modes42798, // 0x30, Load_TLUT42808, // 0x31, ???42818, // 0x32, Set_Tile_Size42828, // 0x33, Load_Block42838, // 0x34, Load_Tile42848, // 0x35, Set_Tile42858, // 0x36, Fill_Rectangle42868, // 0x37, Set_Fill_Color42878, // 0x38, Set_Fog_Color42888, // 0x39, Set_Blend_Color42898, // 0x3a, Set_Prim_Color42908, // 0x3b, Set_Env_Color42918, // 0x3c, Set_Combine42928, // 0x3d, Set_Texture_Image42938, // 0x3e, Set_Mask_Image42948 // 0x3f, Set_Color_Image4295};42964297#define rdram ((wxUint32*)gfx.RDRAM)4298#define rsp_dmem ((wxUint32*)gfx.DMEM)42994300#define dp_start (*(wxUint32*)gfx.DPC_START_REG)4301#define dp_end (*(wxUint32*)gfx.DPC_END_REG)4302#define dp_current (*(wxUint32*)gfx.DPC_CURRENT_REG)4303#define dp_status (*(wxUint32*)gfx.DPC_STATUS_REG)43044305inline wxUint32 READ_RDP_DATA(wxUint32 address)4306{4307if (dp_status & 0x1) // XBUS_DMEM_DMA enabled4308return rsp_dmem[(address & 0xfff)>>2];4309else4310return rdram[address>>2];4311}43124313static void rdphalf_1()4314{4315wxUint32 cmd = rdp.cmd1 >> 24;4316if (cmd >= 0xc8 && cmd <=0xcf) //triangle command4317{4318LRDP("rdphalf_1 - lle triangle\n");4319rdp_cmd_ptr = 0;4320rdp_cmd_cur = 0;4321wxUint32 a;43224323do4324{4325rdp_cmd_data[rdp_cmd_ptr++] = rdp.cmd1;4326// check DL counter4327if (rdp.dl_count != -1)4328{4329rdp.dl_count --;4330if (rdp.dl_count == 0)4331{4332rdp.dl_count = -1;43334334LRDP("End of DL\n");4335rdp.pc_i --;4336}4337}43384339// Get the address of the next command4340a = rdp.pc[rdp.pc_i] & BMASK;43414342// Load the next command and its input4343rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit4344rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // /43454346// Go to the next instruction4347rdp.pc[rdp.pc_i] = (a+8) & BMASK;43484349}while ((rdp.cmd0 >> 24) != 0xb3);4350rdp_cmd_data[rdp_cmd_ptr++] = rdp.cmd1;4351cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f;4352rdp.cmd0 = rdp_cmd_data[rdp_cmd_cur+0];4353rdp.cmd1 = rdp_cmd_data[rdp_cmd_cur+1];4354/*4355wxUint32 cmd3 = ((wxUint32*)gfx.RDRAM)[(a>>2)+2];4356if ((cmd3>>24) == 0xb4)4357rglSingleTriangle = TRUE;4358else4359rglSingleTriangle = FALSE;4360*/4361rdp_command_table[cmd]();4362}4363else4364{4365LRDP("rdphalf_1 - IGNORED\n");4366}4367}43684369static void rdphalf_2()4370{4371RDP_E("rdphalf_2 - IGNORED\n");4372LRDP("rdphalf_2 - IGNORED\n");4373}43744375static void rdphalf_cont()4376{4377RDP_E("rdphalf_cont - IGNORED\n");4378LRDP("rdphalf_cont - IGNORED\n");4379}43804381/******************************************************************4382Function: ProcessRDPList4383Purpose: This function is called when there is a Dlist to be4384processed. (Low level GFX list)4385input: none4386output: none4387*******************************************************************/4388#ifdef __cplusplus4389extern "C" {4390#endif4391EXPORT void CALL ProcessRDPList(void)4392{4393LOG ("ProcessRDPList ()\n");4394LRDP("ProcessRDPList ()\n");43954396SoftLocker lock(mutexProcessDList);4397if (!lock.IsOk()) //mutex is busy4398{4399if (!fullscreen)4400drawNoFullscreenMessage();4401// Set an interrupt to allow the game to continue4402*gfx.MI_INTR_REG |= 0x20;4403gfx.CheckInterrupts();4404return;4405}44064407wxUint32 i;4408wxUint32 cmd, length, cmd_length;4409rdp_cmd_ptr = 0;4410rdp_cmd_cur = 0;44114412if (dp_end <= dp_current) return;4413length = dp_end - dp_current;44144415// load command data4416for (i=0; i < length; i += 4)4417{4418rdp_cmd_data[rdp_cmd_ptr++] = READ_RDP_DATA(dp_current + i);4419if (rdp_cmd_ptr >= 0x1000)4420{4421FRDP("rdp_process_list: rdp_cmd_ptr overflow %x %x --> %x\n", length, dp_current, dp_end);4422}4423}44244425dp_current = dp_end;44264427cmd = (rdp_cmd_data[0] >> 24) & 0x3f;4428cmd_length = (rdp_cmd_ptr + 1) * 4;44294430// check if more data is needed4431if (cmd_length < rdp_command_length[cmd])4432return;4433rdp.LLE = TRUE;4434while (rdp_cmd_cur < rdp_cmd_ptr)4435{4436cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f;44374438if (((rdp_cmd_ptr-rdp_cmd_cur) * 4) < rdp_command_length[cmd])4439return;44404441// execute the command4442rdp.cmd0 = rdp_cmd_data[rdp_cmd_cur+0];4443rdp.cmd1 = rdp_cmd_data[rdp_cmd_cur+1];4444rdp.cmd2 = rdp_cmd_data[rdp_cmd_cur+2];4445rdp.cmd3 = rdp_cmd_data[rdp_cmd_cur+3];4446rdp_command_table[cmd]();44474448rdp_cmd_cur += rdp_command_length[cmd] / 4;4449};4450rdp.LLE = FALSE;44514452dp_start = dp_end;44534454dp_status &= ~0x0002;44554456//}4457}44584459#ifdef __cplusplus4460}4461#endif4462446344644465