--- /dev/null
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002 Dave2001
+* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * 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.
+// * 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.
+//
+//****************************************************************
+
+#include <math.h>
+#include "Gfx_1.3.h"
+#include "m64p.h"
+#include "Ini.h"
+#include "Config.h"
+#include "3dmath.h"
+#include "Util.h"
+#include "Debugger.h"
+#include "Combine.h"
+#include "TexCache.h"
+#include "TexBuffer.h"
+#include "FBtoScreen.h"
+#include "CRC.h"
+
+#ifdef PAULSCODE
+#include "FrameSkipper.h"
+extern FrameSkipper frameSkipper;
+#endif
+
+#ifdef PERFORMANCE
+#include "ticks.h"
+#endif
+
+#ifdef __ARM_NEON__
+#include "arm_neon.h"
+//#include "ticks.h"
+#endif
+
+/*
+const int NumOfFormats = 3;
+SCREEN_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} };
+*/
+const char *ACmp[] = { "NONE", "THRESHOLD", "UNKNOWN", "DITHER" };
+
+const char *Mode0[] = { "COMBINED", "TEXEL0",
+ "TEXEL1", "PRIMITIVE",
+ "SHADE", "ENVIORNMENT",
+ "1", "NOISE",
+ "0", "0",
+ "0", "0",
+ "0", "0",
+ "0", "0" };
+
+const char *Mode1[] = { "COMBINED", "TEXEL0",
+ "TEXEL1", "PRIMITIVE",
+ "SHADE", "ENVIORNMENT",
+ "CENTER", "K4",
+ "0", "0",
+ "0", "0",
+ "0", "0",
+ "0", "0" };
+
+const char *Mode2[] = { "COMBINED", "TEXEL0",
+ "TEXEL1", "PRIMITIVE",
+ "SHADE", "ENVIORNMENT",
+ "SCALE", "COMBINED_ALPHA",
+ "T0_ALPHA", "T1_ALPHA",
+ "PRIM_ALPHA", "SHADE_ALPHA",
+ "ENV_ALPHA", "LOD_FRACTION",
+ "PRIM_LODFRAC", "K5",
+ "0", "0",
+ "0", "0",
+ "0", "0",
+ "0", "0",
+ "0", "0",
+ "0", "0",
+ "0", "0",
+ "0", "0" };
+
+const char *Mode3[] = { "COMBINED", "TEXEL0",
+ "TEXEL1", "PRIMITIVE",
+ "SHADE", "ENVIORNMENT",
+ "1", "0" };
+
+const char *Alpha0[] = { "COMBINED", "TEXEL0",
+ "TEXEL1", "PRIMITIVE",
+ "SHADE", "ENVIORNMENT",
+ "1", "0" };
+
+#define Alpha1 Alpha0
+const char *Alpha2[] = { "LOD_FRACTION", "TEXEL0",
+ "TEXEL1", "PRIMITIVE",
+ "SHADE", "ENVIORNMENT",
+ "PRIM_LODFRAC", "0" };
+#define Alpha3 Alpha0
+
+const char *FBLa[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG" };
+const char *FBLb[] = { "G_BL_A_IN", "G_BL_A_FOG", "G_BL_A_SHADE", "G_BL_0" };
+const char *FBLc[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG"};
+const char *FBLd[] = { "G_BL_1MA", "G_BL_A_MEM", "G_BL_1", "G_BL_0" };
+
+const char *str_zs[] = { "G_ZS_PIXEL", "G_ZS_PRIM" };
+
+const char *str_yn[] = { "NO", "YES" };
+const char *str_offon[] = { "OFF", "ON" };
+
+const char *str_cull[] = { "DISABLE", "FRONT", "BACK", "BOTH" };
+
+// I=intensity probably
+const char *str_format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" };
+const char *str_size[] = { "4bit", "8bit", "16bit", "32bit" };
+const char *str_cm[] = { "WRAP/NO CLAMP", "MIRROR/NO CLAMP", "WRAP/CLAMP", "MIRROR/CLAMP" };
+const char *str_lod[] = { "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "2048" };
+const char *str_aspect[] = { "1x8", "1x4", "1x2", "1x1", "2x1", "4x1", "8x1" };
+
+const char *str_filter[] = { "Point Sampled", "Average (box)", "Bilinear" };
+
+const char *str_tlut[] = { "TT_NONE", "TT_UNKNOWN", "TT_RGBA_16", "TT_IA_16" };
+
+const char *str_dither[] = { "Pattern", "~Pattern", "Noise", "None" };
+
+const char *CIStatus[] = { "ci_main", "ci_zimg", "ci_unknown", "ci_useless",
+ "ci_old_copy", "ci_copy", "ci_copy_self",
+ "ci_zcopy", "ci_aux", "ci_aux_copy" };
+
+//static variables
+
+char out_buf[2048];
+
+wxUint32 frame_count; // frame counter
+
+int ucode_error_report = TRUE;
+int wrong_tile = -1;
+
+// ** RDP graphics functions **
+static void undef();
+static void spnoop();
+
+static void rdp_noop();
+static void rdp_texrect();
+//static void rdp_texrectflip();
+static void rdp_loadsync();
+static void rdp_pipesync();
+static void rdp_tilesync();
+static void rdp_fullsync();
+static void rdp_setkeygb();
+static void rdp_setkeyr();
+static void rdp_setconvert();
+static void rdp_setscissor();
+static void rdp_setprimdepth();
+static void rdp_setothermode();
+static void rdp_loadtlut();
+static void rdp_settilesize();
+static void rdp_loadblock();
+static void rdp_loadtile();
+static void rdp_settile();
+static void rdp_fillrect();
+static void rdp_setfillcolor();
+static void rdp_setfogcolor();
+static void rdp_setblendcolor();
+static void rdp_setprimcolor();
+static void rdp_setenvcolor();
+static void rdp_setcombine();
+static void rdp_settextureimage();
+static void rdp_setdepthimage();
+static void rdp_setcolorimage();
+static void rdp_trifill();
+static void rdp_trishade();
+static void rdp_tritxtr();
+static void rdp_trishadetxtr();
+static void rdp_trifillz();
+static void rdp_trishadez();
+static void rdp_tritxtrz();
+static void rdp_trishadetxtrz();
+static void rdphalf_1();
+static void rdphalf_2();
+static void rdphalf_cont();
+
+static void rsp_reserved0();
+static void rsp_reserved1();
+static void rsp_reserved2();
+static void rsp_reserved3();
+
+static void ys_memrect();
+
+wxUint8 microcode[4096];
+wxUint32 uc_crc;
+void microcheck ();
+
+#ifdef PAULSCODE
+#define Check_FrameSkip if (frameSkipper.willSkipNext()) return
+#else
+#define Check_FrameSkip {}
+#endif
+
+// ** UCODE FUNCTIONS **
+#include "ucode00.h"
+#include "ucode01.h"
+#include "ucode02.h"
+#include "ucode03.h"
+#include "ucode04.h"
+#include "ucode05.h"
+#include "ucode06.h"
+#include "ucode07.h"
+#include "ucode08.h"
+#include "ucode09.h"
+#include "ucode.h"
+#include "ucode09rdp.h"
+#include "turbo3D.h"
+
+static int reset = 0;
+static int old_ucode = -1;
+
+void RDP::Reset()
+{
+ memset(this, 0, sizeof(RDP_Base));
+ // set all vertex numbers
+ for (int i=0; i<MAX_VTX; i++)
+ vtx[i].number = i;
+
+ scissor_o.ul_x = 0;
+ scissor_o.ul_y = 0;
+ scissor_o.lr_x = 320;
+ scissor_o.lr_y = 240;
+
+ vi_org_reg = *gfx.VI_ORIGIN_REG;
+ view_scale[2] = 32.0f * 511.0f;
+ view_trans[2] = 32.0f * 511.0f;
+ clip_ratio = 1.0f;
+
+ lookat[0][0] = lookat[1][1] = 1.0f;
+
+ cycle_mode = 2;
+ allow_combine = 1;
+ rdp.update = UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE;
+ fog_mode = RDP::fog_enabled;
+ maincimg[0].addr = maincimg[1].addr = last_drawn_ci_addr = 0x7FFFFFFF;
+
+ hotkey_info.hk_ref = 90;
+ hotkey_info.hk_motionblur = (settings.buff_clear == 0)?0:90;
+ hotkey_info.hk_filtering = hotkey_info.hk_motionblur;
+
+ CheckKeyPressed(G64_VK_BACK, 1); //BACK
+ CheckKeyPressed(G64_VK_B, 1);
+ CheckKeyPressed(G64_VK_V, 1);
+}
+
+RDP::RDP()
+{
+ vtx1 = new VERTEX[256];
+ memset(vtx1, 0, sizeof(VERTEX)*256);
+ vtx2 = new VERTEX[256];
+ memset(vtx2, 0, sizeof(VERTEX)*256);
+ vtxbuf = vtxbuf2 = 0;
+ vtx_buffer = n_global = 0;
+
+ for (int i = 0; i < MAX_TMU; i++)
+ {
+ cache[i] = new CACHE_LUT[MAX_CACHE];
+ cur_cache[i] = 0;
+ cur_cache_n[i] = 0;
+ };
+
+ vtx = new VERTEX[MAX_VTX];
+ memset(vtx, 0, sizeof(VERTEX)*MAX_VTX);
+ v0 = vn = 0;
+
+ frame_buffers = new COLOR_IMAGE[NUMTEXBUF+2];
+}
+
+RDP::~RDP()
+{
+ delete[] vtx1;
+ delete[] vtx2;
+ for (int i = 0; i < MAX_TMU; i++)
+ delete[] cache[i];
+
+ delete[] vtx;
+ delete[] frame_buffers;
+}
+
+void rdp_reset ()
+{
+ reset = 1;
+ rdp.Reset();
+}
+
+void microcheck ()
+{
+ wxUint32 i;
+ uc_crc = 0;
+
+ // Check first 3k of ucode, because the last 1k sometimes contains trash
+ for (i=0; i<3072>>2; i++)
+ {
+ uc_crc += ((wxUint32*)microcode)[i];
+ }
+
+ FRDP_E ("crc: %08lx\n", uc_crc);
+
+#ifdef LOG_UCODE
+ std::ofstream ucf;
+ ucf.open ("ucode.txt", std::ios::out | std::ios::binary);
+ char d;
+ for (i=0; i<0x400000; i++)
+ {
+ d = ((char*)gfx.RDRAM)[i^3];
+ ucf.write (&d, 1);
+ }
+ ucf.close ();
+#endif
+
+ FRDP("ucode = %08lx\n", uc_crc);
+
+ Ini * ini = Ini::OpenIni();
+ ini->SetPath("UCODE");
+ char str[9];
+ sprintf (str, "%08lx", (unsigned long)uc_crc);
+ int uc = ini->Read(str, -2);
+
+ if (uc == -2 && ucode_error_report)
+ {
+ settings.ucode = Config_ReadInt("ucode", "Force microcode", 0, TRUE, FALSE);
+
+ ReleaseGfx ();
+ ERRLOG("Error: uCode crc not found in INI, using currently selected uCode\n\n%08lx", (unsigned long)uc_crc);
+
+ ucode_error_report = FALSE; // don't report any more ucode errors from this game
+ }
+ else if (uc == -1 && ucode_error_report)
+ {
+ settings.ucode = ini->Read(_T("/SETTINGS/ucode"), 0);
+
+ ReleaseGfx ();
+ ERRLOG("Error: Unsupported uCode!\n\ncrc: %08lx", (unsigned long)uc_crc);
+
+ ucode_error_report = FALSE; // don't report any more ucode errors from this game
+ }
+ else
+ {
+ old_ucode = settings.ucode;
+ settings.ucode = uc;
+ FRDP("microcheck: old ucode: %d, new ucode: %d\n", old_ucode, uc);
+ if (uc_crc == 0x8d5735b2 || uc_crc == 0xb1821ed3 || uc_crc == 0x1118b3e0) //F3DLP.Rej ucode. perspective texture correction is not implemented
+ {
+ rdp.Persp_en = 1;
+ rdp.persp_supported = FALSE;
+ }
+ else if (settings.texture_correction)
+ rdp.persp_supported = TRUE;
+ }
+}
+
+#ifdef __WINDOWS__
+static void GetClientSize(int * width, int * height)
+{
+#ifdef __WINDOWS__
+ RECT win_rect;
+ GetClientRect (gfx.hWnd, &win_rect);
+ *width = win_rect.right;
+ *height = win_rect.bottom;
+#else
+ GFXWindow->GetClientSize(width, height);
+#endif
+}
+#endif
+
+void drawNoFullscreenMessage()
+{
+//need to find, how to do it on non-windows OS
+//the code below will compile on any OS
+//but it works only on windows, because
+//I don't know, how to initialize GFXWindow on other OS
+#ifdef __WINDOWS__
+ LOG ("drawNoFullscreenMessage ()\n");
+ if (rdp.window_changed)
+ {
+ rdp.window_changed = FALSE;
+ int width, height;
+ GetClientSize(&width, &height);
+
+ wxClientDC dc(GFXWindow);
+ dc.SetBrush(*wxMEDIUM_GREY_BRUSH);
+ dc.SetTextForeground(*wxWHITE);
+ dc.SetBackgroundMode(wxTRANSPARENT);
+ dc.DrawRectangle(0, 0, width, height);
+
+ wxCoord w, h;
+ wxString text = wxT("Glide64mk2");
+ dc.GetTextExtent(text, &w, &h);
+ wxCoord x = (width - w)/2;
+ wxCoord y = height/2 - h*4;
+ dc.DrawText(text, x, y);
+
+ text = wxT("Gfx cannot be drawn in windowed mode");
+ dc.GetTextExtent(text, &w, &h);
+ x = (width - w)/2;
+ y = height/2 - h;
+ dc.DrawText(text, x, y);
+
+ text = wxT("Press Alt+Enter to switch to fullscreen");
+ dc.GetTextExtent(text, &w, &h);
+ x = (width - w)/2;
+ y = (height - h)/2 + h*2;
+ dc.DrawText(text, x, y);
+ }
+#endif
+}
+
+static wxUint32 d_ul_x, d_ul_y, d_lr_x, d_lr_y;
+
+static void DrawPartFrameBufferToScreen()
+{
+ FB_TO_SCREEN_INFO fb_info;
+ fb_info.addr = rdp.cimg;
+ fb_info.size = rdp.ci_size;
+ fb_info.width = rdp.ci_width;
+ fb_info.height = rdp.ci_height;
+ fb_info.ul_x = d_ul_x;
+ fb_info.lr_x = d_lr_x;
+ fb_info.ul_y = d_ul_y;
+ fb_info.lr_y = d_lr_y;
+ fb_info.opaque = 0;
+ DrawFrameBufferToScreen(fb_info);
+ memset(gfx.RDRAM+rdp.cimg, 0, (rdp.ci_width*rdp.ci_height)<<rdp.ci_size>>1);
+}
+
+#define RGBA16TO32(color) \
+ ((color&1)?0xFF:0) | \
+ ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | \
+ ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | \
+ ((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8)
+
+static void CopyFrameBuffer (GrBuffer_t buffer = GR_BUFFER_BACKBUFFER)
+{
+ if (!fullscreen)
+ return;
+ FRDP ("CopyFrameBuffer: %08lx... ", rdp.cimg);
+
+ // don't bother to write the stuff in asm... the slow part is the read from video card,
+ // not the copy.
+
+ wxUint32 width = rdp.ci_width;//*gfx.VI_WIDTH_REG;
+ wxUint32 height;
+ if (fb_emulation_enabled && !(settings.hacks&hack_PPL))
+ {
+ int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0;
+ height = rdp.frame_buffers[ind].height;
+ }
+ else
+ {
+ height = rdp.ci_lower_bound;
+ if (settings.hacks&hack_PPL)
+ height -= rdp.ci_upper_bound;
+ }
+ FRDP ("width: %d, height: %d... ", width, height);
+//printf("CopyFrameBuffer width: %d, height: %d... ", width, height);
+
+ if (rdp.scale_x < 1.1f)
+ {
+ wxUint16 * ptr_src = new wxUint16[width*height];
+ if (grLfbReadRegion(buffer,
+ (wxUint32)rdp.offset_x,
+ (wxUint32)rdp.offset_y,//rdp.ci_upper_bound,
+ width,
+ height,
+ width<<1,
+ ptr_src))
+ {
+ wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg);
+ wxUint32 *ptr_dst32 = (wxUint32*)(gfx.RDRAM+rdp.cimg);
+ wxUint16 c;
+
+ for (wxUint32 y=0; y<height; y++)
+ {
+ for (wxUint32 x=0; x<width; x++)
+ {
+ c = ptr_src[x + y * width];
+ if (settings.frame_buffer&fb_read_alpha)
+ {
+ if (c > 0)
+ c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;
+ }
+ else
+ {
+ c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;
+ }
+ if (rdp.ci_size == 2)
+ ptr_dst[(x + y * width)^1] = c;
+ else
+ ptr_dst32[x + y * width] = RGBA16TO32(c);
+ }
+ }
+ LRDP("ReadRegion. Framebuffer copy complete.\n");
+ }
+ else
+ {
+ LRDP("Framebuffer copy failed.\n");
+ }
+ delete[] ptr_src;
+ }
+ else
+ {
+ if (rdp.motionblur && fb_hwfbe_enabled)
+ {
+ return;
+ }
+ else
+ {
+ float scale_x = (settings.scr_res_x - rdp.offset_x*2.0f) / max(width, rdp.vi_width);
+ float scale_y = (settings.scr_res_y - rdp.offset_y*2.0f) / max(height, rdp.vi_height);
+
+ FRDP("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);
+//printf("CopyFrameBuffer 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);
+ GrLfbInfo_t info;
+ info.size = sizeof(GrLfbInfo_t);
+
+ if (grLfbLock (GR_LFB_READ_ONLY,
+ buffer,
+ GR_LFBWRITEMODE_565,
+ GR_ORIGIN_UPPER_LEFT,
+ FXFALSE,
+ &info))
+ {
+ wxUint16 *ptr_src = (wxUint16*)info.lfbPtr;
+ wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg);
+ wxUint32 *ptr_dst32 = (wxUint32*)(gfx.RDRAM+rdp.cimg);
+ wxUint16 c;
+ wxUint32 stride = info.strideInBytes>>1;
+
+ int read_alpha = settings.frame_buffer & fb_read_alpha;
+ if ((settings.hacks&hack_PMario) && rdp.frame_buffers[rdp.ci_count-1].status != ci_aux)
+ read_alpha = FALSE;
+ int x_start = 0, y_start = 0, x_end = width, y_end = height;
+ if (settings.hacks&hack_BAR)
+ {
+ x_start = 80, y_start = 24, x_end = 240, y_end = 86;
+ }
+ for (int y=y_start; y<y_end; y++)
+ {
+ for (int x=x_start; x<x_end; x++)
+ {
+ c = ptr_src[int(x*scale_x + rdp.offset_x) + int(y * scale_y + rdp.offset_y) * stride];
+ c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;
+ if (read_alpha && c == 1)
+ c = 0;
+ if (rdp.ci_size <= 2)
+ ptr_dst[(x + y * width)^1] = c;
+ else
+ ptr_dst32[x + y * width] = RGBA16TO32(c);
+ }
+ }
+
+ // Unlock the backbuffer
+ grLfbUnlock (GR_LFB_READ_ONLY, buffer);
+ LRDP("LfbLock. Framebuffer copy complete.\n");
+ }
+ else
+ {
+ LRDP("Framebuffer copy failed.\n");
+ }
+ }
+ }
+}
+
+void GoToFullScreen()
+{
+ //if (!InitGfx ())
+ {
+ LOG ("FAILED!!!\n");
+ return;
+ }
+}
+
+class SoftLocker
+{
+public:
+ // lock the mutex in the ctor
+ SoftLocker(SDL_sem *mutex)
+ : _isOk(false), _mutex(mutex)
+ { _isOk = ( SDL_SemTryWait(_mutex) == 0 ); }
+
+ // returns true if mutex was successfully locked in ctor
+ bool IsOk() const
+ { return _isOk; }
+
+ // unlock the mutex in dtor
+ ~SoftLocker()
+ { if ( IsOk() ) SDL_SemPost(_mutex); }
+
+private:
+ bool _isOk;
+ SDL_sem *_mutex;
+};
+
+
+/******************************************************************
+Function: ProcessDList
+Purpose: This function is called when there is a Dlist to be
+processed. (High level GFX list)
+input: none
+output: none
+*******************************************************************/
+void DetectFrameBufferUsage ();
+wxUint32 fbreads_front = 0;
+wxUint32 fbreads_back = 0;
+int cpu_fb_read_called = FALSE;
+int cpu_fb_write_called = FALSE;
+int cpu_fb_write = FALSE;
+int cpu_fb_ignore = FALSE;
+int CI_SET = TRUE;
+wxUint32 ucode5_texshiftaddr = 0;
+wxUint32 ucode5_texshiftcount = 0;
+wxUint16 ucode5_texshift = 0;
+int depth_buffer_fog;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+EXPORT void CALL ProcessDList(void)
+{
+// SoftLocker lock(mutexProcessDList);
+#ifdef PAULSCODE
+//printf("ProcessDList()\n");
+// frameSkipper.newFrame();
+ if (0)
+// if (frameSkipper.willSkipNext())
+#else
+ if (/*!lock.IsOk()*/0) //mutex is busy
+#endif
+ {
+// printf("Frameskip, reason=%s\n", (lock.IsOk())?"lock":"frameskip");
+ /* if (!fullscreen)
+ drawNoFullscreenMessage();*/
+ // Set an interrupt to allow the game to continue
+ *(gfx.MI_INTR_REG) |= 0x20;
+ gfx.CheckInterrupts();
+ *(gfx.MI_INTR_REG) |= 0x01;
+ gfx.CheckInterrupts();
+// rdp.updatescreen = 1;
+// no_dlist = true;
+// rdp_fullsync();
+ return;
+ }
+
+ no_dlist = false;
+ update_screen_count = 0;
+ ChangeSize ();
+
+#ifdef ALTTAB_FIX
+ if (!hhkLowLevelKybd)
+ {
+ hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL,
+ LowLevelKeyboardProc, NULL, 0);
+ }
+#endif
+
+ VLOG ("ProcessDList ()\n");
+/*
+ if (!fullscreen)
+ {
+ drawNoFullscreenMessage();
+ // Set an interrupt to allow the game to continue
+ *gfx.MI_INTR_REG |= 0x20;
+ gfx.CheckInterrupts();
+ }
+*/
+ if (reset)
+ {
+ reset = 0;
+ if (settings.autodetect_ucode)
+ {
+ // Thanks to ZeZu for ucode autodetection!!!
+ wxUint32 startUcode = *(wxUint32*)(gfx.DMEM+0xFD0);
+ memcpy (microcode, gfx.RDRAM+startUcode, 4096);
+ microcheck ();
+ }
+ else
+ memset (microcode, 0, 4096);
+ }
+ else if ( ((old_ucode == ucode_S2DEX) && (settings.ucode == ucode_F3DEX)) || settings.force_microcheck)
+ {
+ wxUint32 startUcode = *(wxUint32*)(gfx.DMEM+0xFD0);
+ memcpy (microcode, gfx.RDRAM+startUcode, 4096);
+ microcheck ();
+ }
+
+ if (exception)
+ return;
+
+ // Switch to fullscreen?
+ if (to_fullscreen)
+ GoToFullScreen();
+
+ if (!fullscreen && !settings.run_in_window)
+ return;
+
+ // Clear out the RDP log
+#ifdef RDP_LOGGING
+ if (settings.logging && settings.log_clear)
+ {
+ CLOSE_RDP_LOG ();
+ OPEN_RDP_LOG ();
+ }
+#endif
+
+#ifdef UNIMP_LOG
+ if (settings.log_unk && settings.unk_clear)
+ {
+ std::ofstream unimp;
+ unimp.open("unimp.txt");
+ unimp.close();
+ }
+#endif
+
+ //* Set states *//
+ if (settings.swapmode > 0)
+ SwapOK = TRUE;
+ rdp.updatescreen = 1;
+
+ rdp.tri_n = 0; // 0 triangles so far this frame
+ rdp.debug_n = 0;
+
+ rdp.model_i = 0; // 0 matrices so far in stack
+ //stack_size can be less then 32! Important for Silicon Vally. Thanks Orkin!
+ rdp.model_stack_size = min(32, (*(wxUint32*)(gfx.DMEM+0x0FE4))>>6);
+ if (rdp.model_stack_size == 0)
+ rdp.model_stack_size = 32;
+ rdp.Persp_en = TRUE;
+ rdp.fb_drawn = rdp.fb_drawn_front = FALSE;
+ rdp.update = 0x7FFFFFFF; // All but clear cache
+ rdp.geom_mode = 0;
+ rdp.acmp = 0;
+ rdp.maincimg[1] = rdp.maincimg[0];
+ rdp.skip_drawing = FALSE;
+ rdp.s2dex_tex_loaded = FALSE;
+ rdp.bg_image_height = 0xFFFF;
+ fbreads_front = fbreads_back = 0;
+ rdp.fog_multiplier = rdp.fog_offset = 0;
+ rdp.zsrc = 0;
+ if (rdp.vi_org_reg != *gfx.VI_ORIGIN_REG)
+ rdp.tlut_mode = 0; //is it correct?
+ rdp.scissor_set = FALSE;
+ ucode5_texshiftaddr = ucode5_texshiftcount = 0;
+ cpu_fb_write = FALSE;
+ cpu_fb_read_called = FALSE;
+ cpu_fb_write_called = FALSE;
+ cpu_fb_ignore = FALSE;
+ d_ul_x = 0xffff;
+ d_ul_y = 0xffff;
+ d_lr_x = 0;
+ d_lr_y = 0;
+ depth_buffer_fog = TRUE;
+//printf("ProcessDList\n");
+ //analize possible frame buffer usage
+ if (fb_emulation_enabled)
+ DetectFrameBufferUsage();
+ if (!(settings.hacks&hack_Lego) || rdp.num_of_ci > 1)
+ rdp.last_bg = 0;
+ //* End of set states *//
+
+ // Get the start of the display list and the length of it
+ wxUint32 dlist_start = *(wxUint32*)(gfx.DMEM+0xFF0);
+ wxUint32 dlist_length = *(wxUint32*)(gfx.DMEM+0xFF4);
+ FRDP("--- 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);
+ FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG);
+
+ if (cpu_fb_write == TRUE)
+ DrawPartFrameBufferToScreen();
+ if ((settings.hacks&hack_Tonic) && dlist_length < 16)
+ {
+ rdp_fullsync();
+ FRDP_E("DLIST is too short!\n");
+ return;
+ }
+
+ // Start executing at the start of the display list
+ rdp.pc_i = 0;
+ rdp.pc[rdp.pc_i] = dlist_start;
+ rdp.dl_count = -1;
+ rdp.halt = 0;
+ wxUint32 a;
+
+
+ // catches exceptions so that it doesn't freeze
+#ifdef CATCH_EXCEPTIONS
+ try {
+#endif
+ if (settings.ucode == ucode_Turbo3d)
+ {
+ Turbo3D();
+ }
+ else
+ {
+ // MAIN PROCESSING LOOP
+ do {
+
+ // Get the address of the next command
+ a = rdp.pc[rdp.pc_i] & BMASK;
+
+ // Load the next command and its input
+ rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit
+ rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // /
+ // cmd2 and cmd3 are filled only when needed, by the function that needs them
+
+ // Output the address before the command
+#ifdef LOG_COMMANDS
+ FRDP ("%08lx (c0:%08lx, c1:%08lx): ", a, rdp.cmd0, rdp.cmd1);
+#else
+ FRDP ("%08lx: ", a);
+#endif
+
+ // Go to the next instruction
+ rdp.pc[rdp.pc_i] = (a+8) & BMASK;
+
+#ifdef PERFORMANCE
+ perf_cur = ticksGetTicks();
+#endif
+ // Process this instruction
+ gfx_instruction[settings.ucode][rdp.cmd0>>24] ();
+
+ // check DL counter
+ if (rdp.dl_count != -1)
+ {
+ rdp.dl_count --;
+ if (rdp.dl_count == 0)
+ {
+ rdp.dl_count = -1;
+
+ LRDP("End of DL\n");
+ rdp.pc_i --;
+ }
+ }
+
+#ifdef PERFORMANCE
+ perf_next = ticksGetTicks();
+ sprintf (out_buf, "perf %08x: %lli\n", a-8, (perf_next-perf_cur));
+#ifdef RDP_LOGGING
+ rdp_log << out_buf;
+#else
+ printf(out_buf);
+#endif
+#endif
+
+ } while (!rdp.halt);
+ }
+#ifdef CATCH_EXCEPTIONS
+ } catch (...) {
+
+ if (fullscreen)
+ {
+ ReleaseGfx ();
+ rdp_reset ();
+#ifdef TEXTURE_FILTER
+ if (settings.ghq_use)
+ {
+ ext_ghq_shutdown();
+ settings.ghq_use = 0;
+ }
+#endif
+ }
+ ERRLOG("The GFX plugin caused an exception and has been disabled.");
+ exception = TRUE;
+ return;
+ }
+#endif
+
+ if (fb_emulation_enabled)
+ {
+ rdp.scale_x = rdp.scale_x_bak;
+ rdp.scale_y = rdp.scale_y_bak;
+ }
+#ifdef PAULSCODE
+ if (!frameSkipper.willSkipNext())
+#endif
+ if (settings.frame_buffer & fb_ref)
+ CopyFrameBuffer ();
+ if (rdp.cur_image)
+ CloseTextureBuffer(rdp.read_whole_frame && ((settings.hacks&hack_PMario) || rdp.swap_ci_index >= 0));
+
+ if ((settings.hacks&hack_TGR2) && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET)
+ {
+ newSwapBuffers ();
+ CI_SET = FALSE;
+ }
+ LRDP("ProcessDList end\n");
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+// undef - undefined instruction, always ignore
+static void undef()
+{
+ FRDP_E("** undefined ** (%08lx)\n", rdp.cmd0);
+ FRDP("** undefined ** (%08lx) - IGNORED\n", rdp.cmd0);
+#ifdef _ENDUSER_RELEASE_
+ *gfx.MI_INTR_REG |= 0x20;
+ gfx.CheckInterrupts();
+ rdp.halt = 1;
+#endif
+}
+
+// spnoop - no operation, always ignore
+static void spnoop()
+{
+ LRDP("spnoop\n");
+}
+
+// noop - no operation, always ignore
+static void rdp_noop()
+{
+ LRDP("noop\n");
+}
+
+static void ys_memrect ()
+{
+ wxUint32 tile = (wxUint16)((rdp.cmd1 & 0x07000000) >> 24);
+
+ wxUint32 lr_x = (wxUint16)((rdp.cmd0 & 0x00FFF000) >> 14);
+ wxUint32 lr_y = (wxUint16)((rdp.cmd0 & 0x00000FFF) >> 2);
+ wxUint32 ul_x = (wxUint16)((rdp.cmd1 & 0x00FFF000) >> 14);
+ wxUint32 ul_y = (wxUint16)((rdp.cmd1 & 0x00000FFF) >> 2);
+
+ if (lr_y > rdp.scissor_o.lr_y)
+ lr_y = rdp.scissor_o.lr_y;
+ wxUint32 off_x = ((rdp.cmd2 & 0xFFFF0000) >> 16) >> 5;
+ wxUint32 off_y = (rdp.cmd2 & 0x0000FFFF) >> 5;
+
+ FRDP ("memrect (%d, %d, %d, %d), ci_width: %d", ul_x, ul_y, lr_x, lr_y, rdp.ci_width);
+ if (off_x > 0)
+ FRDP (" off_x: %d", off_x);
+ if (off_y > 0)
+ FRDP (" off_y: %d", off_y);
+ LRDP("\n");
+
+ wxUint32 y, width = lr_x - ul_x;
+ wxUint32 tex_width = rdp.tiles[tile].line << 3;
+ wxUint8 * texaddr = gfx.RDRAM + rdp.addr[rdp.tiles[tile].t_mem] + tex_width*off_y + off_x;
+ wxUint8 * fbaddr = gfx.RDRAM + rdp.cimg + ul_x;
+
+ for (y = ul_y; y < lr_y; y++) {
+ wxUint8 *src = texaddr + (y - ul_y) * tex_width;
+ wxUint8 *dst = fbaddr + y * rdp.ci_width;
+ memcpy (dst, src, width);
+ }
+}
+
+static void pm_palette_mod ()
+{
+ wxUint8 envr = (wxUint8)((float)((rdp.env_color >> 24)&0xFF)/255.0f*31.0f);
+ wxUint8 envg = (wxUint8)((float)((rdp.env_color >> 16)&0xFF)/255.0f*31.0f);
+ wxUint8 envb = (wxUint8)((float)((rdp.env_color >> 8)&0xFF)/255.0f*31.0f);
+ wxUint16 env16 = (wxUint16)((envr<<11)|(envg<<6)|(envb<<1)|1);
+ wxUint8 prmr = (wxUint8)((float)((rdp.prim_color >> 24)&0xFF)/255.0f*31.0f);
+ wxUint8 prmg = (wxUint8)((float)((rdp.prim_color >> 16)&0xFF)/255.0f*31.0f);
+ wxUint8 prmb = (wxUint8)((float)((rdp.prim_color >> 8)&0xFF)/255.0f*31.0f);
+ wxUint16 prim16 = (wxUint16)((prmr<<11)|(prmg<<6)|(prmb<<1)|1);
+ wxUint16 * dst = (wxUint16*)(gfx.RDRAM+rdp.cimg);
+ for (int i = 0; i < 16; i++)
+ {
+ dst[i^1] = (rdp.pal_8[i]&1) ? prim16 : env16;
+ }
+ LRDP("Texrect palette modification\n");
+}
+
+static void pd_zcopy ()
+{
+ wxUint16 ul_x = (wxUint16)((rdp.cmd1 & 0x00FFF000) >> 14);
+ wxUint16 lr_x = (wxUint16)((rdp.cmd0 & 0x00FFF000) >> 14) + 1;
+ wxUint16 ul_u = (wxUint16)((rdp.cmd2 & 0xFFFF0000) >> 21) + 1;
+ wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg);
+ wxUint16 width = lr_x - ul_x;
+ wxUint16 * ptr_src = ((wxUint16*)rdp.tmem)+ul_u;
+ wxUint16 c;
+ for (wxUint16 x=0; x<width; x++)
+ {
+ c = ptr_src[x];
+ c = ((c<<8)&0xFF00) | (c >> 8);
+ ptr_dst[(ul_x+x)^1] = c;
+ // FRDP("dst[%d]=%04lx \n", (x + ul_x)^1, c);
+ }
+}
+
+static void DrawDepthBufferFog()
+{
+ if (rdp.zi_width < 200)
+ return;
+ FB_TO_SCREEN_INFO fb_info;
+ fb_info.addr = rdp.zimg;
+ fb_info.size = 2;
+ fb_info.width = rdp.zi_width;
+ fb_info.height = rdp.ci_height;
+ fb_info.ul_x = rdp.scissor_o.ul_x;
+ fb_info.lr_x = rdp.scissor_o.lr_x;
+ fb_info.ul_y = rdp.scissor_o.ul_y;
+ fb_info.lr_y = rdp.scissor_o.lr_y;
+ fb_info.opaque = 0;
+ DrawDepthBufferToScreen(fb_info);
+}
+
+static void rdp_texrect()
+{
+ if (!rdp.LLE)
+ {
+ wxUint32 a = rdp.pc[rdp.pc_i];
+ wxUint8 cmdHalf1 = gfx.RDRAM[a+3];
+ wxUint8 cmdHalf2 = gfx.RDRAM[a+11];
+ a >>= 2;
+ if ((cmdHalf1 == 0xE1 && cmdHalf2 == 0xF1) || (cmdHalf1 == 0xB4 && cmdHalf2 == 0xB3) || (cmdHalf1 == 0xB3 && cmdHalf2 == 0xB2))
+ {
+ //gSPTextureRectangle
+ rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a+1];
+ rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a+3];
+ rdp.pc[rdp.pc_i] += 16;
+ }
+ else
+ {
+ //gDPTextureRectangle
+ if (settings.hacks&hack_ASB)
+ rdp.cmd2 = 0;
+ else
+ rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a+0];
+ rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a+1];
+ rdp.pc[rdp.pc_i] += 8;
+ }
+ }
+ if ((settings.hacks&hack_Yoshi) && settings.ucode == ucode_S2DEX)
+ {
+ ys_memrect();
+ return;
+ }
+
+ if (rdp.skip_drawing || (!fb_emulation_enabled && (rdp.cimg == rdp.zimg)))
+ {
+ if ((settings.hacks&hack_PMario) && rdp.ci_status == ci_useless)
+ {
+ pm_palette_mod ();
+ }
+ else
+ {
+ LRDP("Texrect skipped\n");
+ }
+ return;
+ }
+
+ if ((settings.ucode == ucode_CBFD) && rdp.cur_image && rdp.cur_image->format)
+ {
+ //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);
+ LRDP("Shadow texrect is skipped.\n");
+ rdp.tri_n += 2;
+ return;
+ }
+
+ if ((settings.ucode == ucode_PerfectDark) && (rdp.frame_buffers[rdp.ci_count-1].status == ci_zcopy))
+ {
+ pd_zcopy ();
+ LRDP("Depth buffer copied.\n");
+ rdp.tri_n += 2;
+ return;
+ }
+
+ if ((rdp.othermode_l >> 16) == 0x3c18 && rdp.cycle1 == 0x03ffffff && rdp.cycle2 == 0x01ff1fff) //depth image based fog
+ {
+ if (!depth_buffer_fog)
+ return;
+ if (settings.fog)
+ DrawDepthBufferFog();
+ depth_buffer_fog = FALSE;
+ return;
+ }
+
+ // FRDP ("rdp.cycle1 %08lx, rdp.cycle2 %08lx\n", rdp.cycle1, rdp.cycle2);
+
+ float ul_x, ul_y, lr_x, lr_y;
+ if (rdp.cycle_mode == 2)
+ {
+ ul_x = max(0.0f, (short)((rdp.cmd1 & 0x00FFF000) >> 14));
+ ul_y = max(0.0f, (short)((rdp.cmd1 & 0x00000FFF) >> 2));
+ lr_x = max(0.0f, (short)((rdp.cmd0 & 0x00FFF000) >> 14));
+ lr_y = max(0.0f, (short)((rdp.cmd0 & 0x00000FFF) >> 2));
+ }
+ else
+ {
+ ul_x = max(0.0f, ((short)((rdp.cmd1 & 0x00FFF000) >> 12)) / 4.0f);
+ ul_y = max(0.0f, ((short)(rdp.cmd1 & 0x00000FFF)) / 4.0f);
+ lr_x = max(0.0f, ((short)((rdp.cmd0 & 0x00FFF000) >> 12)) / 4.0f);
+ lr_y = max(0.0f, ((short)(rdp.cmd0 & 0x00000FFF)) / 4.0f);
+ }
+
+ if (ul_x >= lr_x)
+ {
+ FRDP("Wrong Texrect: ul_x: %f, lr_x: %f\n", ul_x, lr_x);
+ return;
+ }
+
+ if (rdp.cycle_mode > 1)
+ {
+ lr_x += 1.0f;
+ lr_y += 1.0f;
+ } else if (lr_y - ul_y < 1.0f)
+ lr_y = ceil(lr_y);
+
+ if (settings.increase_texrect_edge)
+ {
+ if (floor(lr_x) != lr_x)
+ lr_x = ceil(lr_x);
+ if (floor(lr_y) != lr_y)
+ lr_y = ceil(lr_y);
+ }
+
+ //*
+ if (rdp.tbuff_tex && (settings.frame_buffer & fb_optimize_texrect))
+ {
+ LRDP("Attempt to optimize texrect\n");
+ if (!rdp.tbuff_tex->drawn)
+ {
+ DRAWIMAGE d;
+ d.imageX = 0;
+ d.imageW = (wxUint16)rdp.tbuff_tex->width;
+ d.frameX = (wxUint16)ul_x;
+ d.frameW = (wxUint16)(rdp.tbuff_tex->width);
+
+ d.imageY = 0;
+ d.imageH = (wxUint16)rdp.tbuff_tex->height;
+ d.frameY = (wxUint16)ul_y;
+ d.frameH = (wxUint16)(rdp.tbuff_tex->height);
+ FRDP("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);
+ d.scaleX = 1.0f;
+ d.scaleY = 1.0f;
+ DrawHiresImage(d, rdp.tbuff_tex->width == rdp.ci_width);
+ rdp.tbuff_tex->drawn = TRUE;
+ }
+ return;
+ }
+ //*/
+ // framebuffer workaround for Zelda: MM LOT
+ if ((rdp.othermode_l & 0xFFFF0000) == 0x0f5a0000)
+ return;
+
+ /*Gonetz*/
+ //hack for Zelda MM. it removes black texrects which cover all geometry in "Link meets Zelda" cut scene
+ if ((settings.hacks&hack_Zelda) && rdp.timg.addr >= rdp.cimg && rdp.timg.addr < rdp.ci_end)
+ {
+ FRDP("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);
+ rdp.tri_n += 2;
+ return;
+ }
+ //*
+ //hack for Banjo2. it removes black texrects under Banjo
+ if (!fb_hwfbe_enabled && ((rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF)) == 0xFFFFFFFF && (rdp.othermode_l & 0xFFFF0000) == 0x00500000)
+ {
+ rdp.tri_n += 2;
+ return;
+ }
+ //*/
+ //*
+ //remove motion blur in night vision
+ if ((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)))
+ {
+ if (fb_emulation_enabled)
+ if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self)
+ {
+ //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);
+ LRDP("Wrong Texrect.\n");
+ rdp.tri_n += 2;
+ return;
+ }
+ }
+ //*/
+
+ int i;
+
+ wxUint32 tile = (wxUint16)((rdp.cmd1 & 0x07000000) >> 24);
+
+ rdp.texrecting = 1;
+
+ wxUint32 prev_tile = rdp.cur_tile;
+ rdp.cur_tile = tile;
+
+ const float Z = set_sprite_combine_mode ();
+
+ rdp.texrecting = 0;
+
+ if (!rdp.cur_cache[0])
+ {
+ rdp.cur_tile = prev_tile;
+ rdp.tri_n += 2;
+ return;
+ }
+ // ****
+ // ** Texrect offset by Gugaman **
+ //
+ //integer representation of texture coordinate.
+ //needed to detect and avoid overflow after shifting
+ wxInt32 off_x_i = (rdp.cmd2 >> 16) & 0xFFFF;
+ wxInt32 off_y_i = rdp.cmd2 & 0xFFFF;
+ float dsdx = (float)((short)((rdp.cmd3 & 0xFFFF0000) >> 16)) / 1024.0f;
+ float dtdy = (float)((short)(rdp.cmd3 & 0x0000FFFF)) / 1024.0f;
+ if (off_x_i & 0x8000) //check for sign bit
+ off_x_i |= ~0xffff; //make it negative
+ //the same as for off_x_i
+ if (off_y_i & 0x8000)
+ off_y_i |= ~0xffff;
+
+ if (rdp.cycle_mode == 2)
+ dsdx /= 4.0f;
+
+ float s_ul_x = ul_x * rdp.scale_x + rdp.offset_x;
+ float s_lr_x = lr_x * rdp.scale_x + rdp.offset_x;
+ float s_ul_y = ul_y * rdp.scale_y + rdp.offset_y;
+ float s_lr_y = lr_y * rdp.scale_y + rdp.offset_y;
+
+ FRDP("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);
+ FRDP ("(%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);
+ FRDP("\toff_x: %f, off_y: %f, dsdx: %f, dtdy: %f\n", off_x_i/32.0f, off_y_i/32.0f, dsdx, dtdy);
+
+ float off_size_x;
+ float off_size_y;
+
+ if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip
+ {
+#ifdef TEXTURE_FILTER
+ if (rdp.cur_cache[0]->is_hires_tex)
+ {
+ off_size_x = (float)((lr_y - ul_y) * dsdx);
+ off_size_y = (float)((lr_x - ul_x) * dtdy);
+ }
+ else
+#endif
+ {
+ off_size_x = (lr_y - ul_y - 1) * dsdx;
+ off_size_y = (lr_x - ul_x - 1) * dtdy;
+ }
+ }
+ else
+ {
+#ifdef TEXTURE_FILTER
+ if (rdp.cur_cache[0]->is_hires_tex)
+ {
+ off_size_x = (float)((lr_x - ul_x) * dsdx);
+ off_size_y = (float)((lr_y - ul_y) * dtdy);
+ }
+ else
+#endif
+ {
+ off_size_x = (lr_x - ul_x - 1) * dsdx;
+ off_size_y = (lr_y - ul_y - 1) * dtdy;
+ }
+ }
+
+ struct {
+ float ul_u, ul_v, lr_u, lr_v;
+ } texUV[2]; //struct for texture coordinates
+ //angrylion's macro, helps to cut overflowed values.
+ #define SIGN16(x) (((x) & 0x8000) ? ((x) | ~0xffff) : ((x) & 0xffff))
+
+ //calculate texture coordinates
+ for (int i = 0; i < 2; i++)
+ {
+ if (rdp.cur_cache[i] && (rdp.tex & (i+1)))
+ {
+ float sx = 1, sy = 1;
+ int x_i = off_x_i, y_i = off_y_i;
+ TILE & tile = rdp.tiles[rdp.cur_tile + i];
+ //shifting
+ if (tile.shift_s)
+ {
+ if (tile.shift_s > 10)
+ {
+ wxUint8 iShift = (16 - tile.shift_s);
+ x_i <<= iShift;
+ sx = (float)(1 << iShift);
+ }
+ else
+ {
+ wxUint8 iShift = tile.shift_s;
+ x_i >>= iShift;
+ sx = 1.0f/(float)(1 << iShift);
+ }
+ }
+ if (tile.shift_t)
+ {
+ if (tile.shift_t > 10)
+ {
+ wxUint8 iShift = (16 - tile.shift_t);
+ y_i <<= iShift;
+ sy = (float)(1 << iShift);
+ }
+ else
+ {
+ wxUint8 iShift = tile.shift_t;
+ y_i >>= iShift;
+ sy = 1.0f/(float)(1 << iShift);
+ }
+ }
+
+ if (rdp.aTBuffTex[i]) //hwfbe texture
+ {
+ float t0_off_x;
+ float t0_off_y;
+ if (off_x_i + off_y_i == 0)
+ {
+ t0_off_x = tile.ul_s;
+ t0_off_y = tile.ul_t;
+ }
+ else
+ {
+ t0_off_x = off_x_i/32.0f;
+ t0_off_y = off_y_i/32.0f;
+ }
+ t0_off_x += rdp.aTBuffTex[i]->u_shift;// + tile.ul_s; //commented for Paper Mario motion blur
+ t0_off_y += rdp.aTBuffTex[i]->v_shift;// + tile.ul_t;
+ texUV[i].ul_u = t0_off_x * sx;
+ texUV[i].ul_v = t0_off_y * sy;
+
+ texUV[i].lr_u = texUV[i].ul_u + off_size_x * sx;
+ texUV[i].lr_v = texUV[i].ul_v + off_size_y * sy;
+
+ texUV[i].ul_u *= rdp.aTBuffTex[i]->u_scale;
+ texUV[i].ul_v *= rdp.aTBuffTex[i]->v_scale;
+ texUV[i].lr_u *= rdp.aTBuffTex[i]->u_scale;
+ texUV[i].lr_v *= rdp.aTBuffTex[i]->v_scale;
+ FRDP("tbuff_tex[%d] ul_u: %f, ul_v: %f, lr_u: %f, lr_v: %f\n",
+ i, texUV[i].ul_u, texUV[i].ul_v, texUV[i].lr_u, texUV[i].lr_v);
+ }
+ else //common case
+ {
+ //kill 10.5 format overflow by SIGN16 macro
+ texUV[i].ul_u = SIGN16(x_i) / 32.0f;
+ texUV[i].ul_v = SIGN16(y_i) / 32.0f;
+
+ texUV[i].ul_u -= tile.f_ul_s;
+ texUV[i].ul_v -= tile.f_ul_t;
+
+ texUV[i].lr_u = texUV[i].ul_u + off_size_x * sx;
+ texUV[i].lr_v = texUV[i].ul_v + off_size_y * sy;
+
+ texUV[i].ul_u = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_x * texUV[i].ul_u;
+ texUV[i].lr_u = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_x * texUV[i].lr_u;
+ texUV[i].ul_v = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_y * texUV[i].ul_v;
+ texUV[i].lr_v = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_y * texUV[i].lr_v;
+ }
+ }
+ else
+ {
+ texUV[i].ul_u = texUV[i].ul_v = texUV[i].lr_u = texUV[i].lr_v = 0;
+ }
+ }
+ rdp.cur_tile = prev_tile;
+
+ // ****
+
+ FRDP (" scissor: (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);
+
+ CCLIP2 (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);
+ CCLIP2 (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);
+
+ FRDP (" draw at: (%f, %f) -> (%f, %f)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y);
+
+ VERTEX vstd[4] = {
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 } };
+
+ if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip
+ {
+ vstd[1].u0 = texUV[0].ul_u;
+ vstd[1].v0 = texUV[0].lr_v;
+ vstd[1].u1 = texUV[1].ul_u;
+ vstd[1].v1 = texUV[1].lr_v;
+
+ vstd[2].u0 = texUV[0].lr_u;
+ vstd[2].v0 = texUV[0].ul_v;
+ vstd[2].u1 = texUV[1].lr_u;
+ vstd[2].v1 = texUV[1].ul_v;
+ }
+
+ VERTEX *vptr = vstd;
+ int n_vertices = 4;
+
+ VERTEX *vnew = 0;
+ // for (int j =0; j < 4; j++)
+ // 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);
+
+
+ if (!rdp.aTBuffTex[0] && rdp.cur_cache[0]->splits != 1)
+ {
+ // ** LARGE TEXTURE HANDLING **
+ // *VERY* simple algebra for texrects
+ float min_u, min_x, max_u, max_x;
+ if (vstd[0].u0 < vstd[1].u0)
+ {
+ min_u = vstd[0].u0;
+ min_x = vstd[0].x;
+ max_u = vstd[1].u0;
+ max_x = vstd[1].x;
+ }
+ else
+ {
+ min_u = vstd[1].u0;
+ min_x = vstd[1].x;
+ max_u = vstd[0].u0;
+ max_x = vstd[0].x;
+ }
+
+ int start_u_256, end_u_256;
+ start_u_256 = (int)min_u >> 8;
+ end_u_256 = (int)max_u >> 8;
+ //FRDP(" min_u: %f, max_u: %f start: %d, end: %d\n", min_u, max_u, start_u_256, end_u_256);
+
+ int splitheight = rdp.cur_cache[0]->splitheight;
+
+ int num_verts_line = 2 + ((end_u_256-start_u_256)<<1);
+ n_vertices = num_verts_line << 1;
+ vnew = new VERTEX [n_vertices];
+ vptr = vnew;
+
+ vnew[0] = vstd[0];
+ vnew[0].u0 -= 256.0f * start_u_256;
+ vnew[0].v0 += splitheight * start_u_256;
+ vnew[0].u1 -= 256.0f * start_u_256;
+ vnew[0].v1 += splitheight * start_u_256;
+ vnew[1] = vstd[2];
+ vnew[1].u0 -= 256.0f * start_u_256;
+ vnew[1].v0 += splitheight * start_u_256;
+ vnew[1].u1 -= 256.0f * start_u_256;
+ vnew[1].v1 += splitheight * start_u_256;
+ vnew[n_vertices-2] = vstd[1];
+ vnew[n_vertices-2].u0 -= 256.0f * end_u_256;
+ vnew[n_vertices-2].v0 += splitheight * end_u_256;
+ vnew[n_vertices-2].u1 -= 256.0f * end_u_256;
+ vnew[n_vertices-2].v1 += splitheight * end_u_256;
+ vnew[n_vertices-1] = vstd[3];
+ vnew[n_vertices-1].u0 -= 256.0f * end_u_256;
+ vnew[n_vertices-1].v0 += splitheight * end_u_256;
+ vnew[n_vertices-1].u1 -= 256.0f * end_u_256;
+ vnew[n_vertices-1].v1 += splitheight * end_u_256;
+
+ // find the equation of the line of u,x
+ float m = (max_x - min_x) / (max_u - min_u); // m = delta x / delta u
+ float b = min_x - m * min_u; // b = y - m * x
+
+ for (i=start_u_256; i<end_u_256; i++)
+ {
+ // Find where x = current 256 multiple
+ float x = m * ((i<<8)+256) + b;
+
+ int vn = 2 + ((i-start_u_256)<<2);
+ vnew[vn] = vstd[0];
+ vnew[vn].x = x;
+ vnew[vn].u0 = 255.5f;
+ vnew[vn].v0 += (float)splitheight * i;
+ vnew[vn].u1 = 255.5f;
+ vnew[vn].v1 += (float)splitheight * i;
+
+ vn ++;
+ vnew[vn] = vstd[2];
+ vnew[vn].x = x;
+ vnew[vn].u0 = 255.5f;
+ vnew[vn].v0 += (float)splitheight * i;
+ vnew[vn].u1 = 255.5f;
+ vnew[vn].v1 += (float)splitheight * i;
+
+ vn ++;
+ vnew[vn] = vnew[vn-2];
+ vnew[vn].u0 = 0.5f;
+ vnew[vn].v0 += (float)splitheight;
+ vnew[vn].u1 = 0.5f;
+ vnew[vn].v1 += (float)splitheight;
+
+ vn ++;
+ vnew[vn] = vnew[vn-2];
+ vnew[vn].u0 = 0.5f;
+ vnew[vn].v0 += (float)splitheight;
+ vnew[vn].u1 = 0.5f;
+ vnew[vn].v1 += (float)splitheight;
+ }
+ //*
+ if (n_vertices > 12)
+ {
+ float texbound = (float)(splitheight << 1);
+ for (int k = 0; k < n_vertices; k ++)
+ {
+ if (vnew[k].v0 > texbound)
+ vnew[k].v0 = (float)fmod(vnew[k].v0, texbound);
+ }
+ }
+ //*/
+ }
+
+ AllowShadeMods (vptr, n_vertices);
+ for (i=0; i<n_vertices; i++)
+ {
+ apply_shade_mods (&vptr[i]);
+ }
+
+ if (fullscreen)
+ {
+ if (rdp.fog_mode >= RDP::fog_blend)
+ {
+ float fog;
+ if (rdp.fog_mode == RDP::fog_blend)
+ fog = 1.0f/max(1, rdp.fog_color&0xFF);
+ else
+ fog = 1.0f/max(1, (~rdp.fog_color)&0xFF);
+ for (i = 0; i < n_vertices; i++)
+ {
+ vptr[i].f = fog;
+ }
+ grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
+ }
+
+ ConvertCoordsConvert (vptr, n_vertices);
+
+ if (settings.wireframe)
+ {
+ SetWireframeCol ();
+ grDrawLine (&vstd[0], &vstd[2]);
+ grDrawLine (&vstd[2], &vstd[1]);
+ grDrawLine (&vstd[1], &vstd[0]);
+ grDrawLine (&vstd[2], &vstd[3]);
+ grDrawLine (&vstd[3], &vstd[1]);
+ }
+ else
+ {
+ grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, n_vertices, vptr, sizeof(VERTEX));
+ }
+
+ if (_debugger.capture)
+ {
+ VERTEX vl[3];
+ vl[0] = vstd[0];
+ vl[1] = vstd[2];
+ vl[2] = vstd[1];
+ add_tri (vl, 3, TRI_TEXRECT);
+ rdp.tri_n ++;
+ vl[0] = vstd[2];
+ vl[1] = vstd[3];
+ vl[2] = vstd[1];
+ add_tri (vl, 3, TRI_TEXRECT);
+ rdp.tri_n ++;
+ }
+ else
+ rdp.tri_n += 2;
+ }
+ else
+ {
+ rdp.tri_n += 2;
+ }
+
+ delete[] vnew;
+}
+
+static void rdp_loadsync()
+{
+ LRDP("loadsync - ignored\n");
+}
+
+static void rdp_pipesync()
+{
+ LRDP("pipesync - ignored\n");
+}
+
+static void rdp_tilesync()
+{
+ LRDP("tilesync - ignored\n");
+}
+
+static void rdp_fullsync()
+{
+ // Set an interrupt to allow the game to continue
+ *gfx.MI_INTR_REG |= 0x20;
+ gfx.CheckInterrupts();
+ LRDP("fullsync\n");
+}
+
+static void rdp_setkeygb()
+{
+ wxUint32 sB = rdp.cmd1&0xFF;
+ wxUint32 cB = (rdp.cmd1>>8)&0xFF;
+ wxUint32 sG = (rdp.cmd1>>16)&0xFF;
+ wxUint32 cG = (rdp.cmd1>>24)&0xFF;
+ rdp.SCALE = (rdp.SCALE&0xFF0000FF) | (sG<<16) | (sB<<8);
+ rdp.CENTER = (rdp.CENTER&0xFF0000FF) | (cG<<16) | (cB<<8);
+ FRDP("setkeygb. cG=%02lx, sG=%02lx, cB=%02lx, sB=%02lx\n", cG, sG, cB, sB);
+}
+
+static void rdp_setkeyr()
+{
+ wxUint32 sR = rdp.cmd1&0xFF;
+ wxUint32 cR = (rdp.cmd1>>8)&0xFF;
+ rdp.SCALE = (rdp.SCALE&0x00FFFFFF) | (sR<<24);
+ rdp.CENTER = (rdp.CENTER&0x00FFFFFF) | (cR<<24);
+ FRDP("setkeyr. cR=%02lx, sR=%02lx\n", cR, sR);
+}
+
+static void rdp_setconvert()
+{
+ /*
+ rdp.YUV_C0 = 1.1647f ;
+ rdp.YUV_C1 = 0.79931f ;
+ rdp.YUV_C2 = -0.1964f ;
+ rdp.YUV_C3 = -0.40651f;
+ rdp.YUV_C4 = 1.014f ;
+ */
+ rdp.K4 = (wxUint8)(rdp.cmd1>>9)&0x1FF;
+ rdp.K5 = (wxUint8)(rdp.cmd1&0x1FF);
+ // RDP_E("setconvert - IGNORED\n");
+ FRDP("setconvert. K4=%02lx K5=%02lx\n", rdp.K4, rdp.K5);
+}
+
+//
+// setscissor - sets the screen clipping rectangle
+//
+
+static void rdp_setscissor()
+{
+ // clipper resolution is 320x240, scale based on computer resolution
+ rdp.scissor_o.ul_x = /*min(*/(wxUint32)(((rdp.cmd0 & 0x00FFF000) >> 14))/*, 320)*/;
+ rdp.scissor_o.ul_y = /*min(*/(wxUint32)(((rdp.cmd0 & 0x00000FFF) >> 2))/*, 240)*/;
+ rdp.scissor_o.lr_x = /*min(*/(wxUint32)(((rdp.cmd1 & 0x00FFF000) >> 14))/*, 320)*/;
+ rdp.scissor_o.lr_y = /*min(*/(wxUint32)(((rdp.cmd1 & 0x00000FFF) >> 2))/*, 240)*/;
+
+ rdp.ci_upper_bound = rdp.scissor_o.ul_y;
+ rdp.ci_lower_bound = rdp.scissor_o.lr_y;
+ rdp.scissor_set = TRUE;
+
+ FRDP("setscissor: (%d,%d) -> (%d,%d)\n", rdp.scissor_o.ul_x, rdp.scissor_o.ul_y,
+ rdp.scissor_o.lr_x, rdp.scissor_o.lr_y);
+
+ rdp.update |= UPDATE_SCISSOR;
+
+ if (rdp.view_scale[0] == 0) //viewport is not set?
+ {
+ rdp.view_scale[0] = (rdp.scissor_o.lr_x>>1)*rdp.scale_x;
+ rdp.view_scale[1] = (rdp.scissor_o.lr_y>>1)*-rdp.scale_y;
+ rdp.view_trans[0] = rdp.view_scale[0];
+ rdp.view_trans[1] = -rdp.view_scale[1];
+ rdp.update |= UPDATE_VIEWPORT;
+ }
+}
+
+static void rdp_setprimdepth()
+{
+ rdp.prim_depth = (wxUint16)((rdp.cmd1 >> 16) & 0x7FFF);
+ rdp.prim_dz = (wxUint16)(rdp.cmd1 & 0x7FFF);
+
+ FRDP("setprimdepth: %d\n", rdp.prim_depth);
+}
+
+static void rdp_setothermode()
+{
+#define F3DEX2_SETOTHERMODE(cmd,sft,len,data) { \
+ rdp.cmd0 = (cmd<<24) | ((32-(sft)-(len))<<8) | (((len)-1)); \
+ rdp.cmd1 = data; \
+ gfx_instruction[settings.ucode][cmd] (); \
+}
+#define SETOTHERMODE(cmd,sft,len,data) { \
+ rdp.cmd0 = (cmd<<24) | ((sft)<<8) | (len); \
+ rdp.cmd1 = data; \
+ gfx_instruction[settings.ucode][cmd] (); \
+}
+
+ LRDP("rdp_setothermode\n");
+
+ if ((settings.ucode == ucode_F3DEX2) || (settings.ucode == ucode_CBFD))
+ {
+ int cmd0 = rdp.cmd0;
+ F3DEX2_SETOTHERMODE(0xE2, 0, 32, rdp.cmd1); // SETOTHERMODE_L
+ F3DEX2_SETOTHERMODE(0xE3, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H
+ }
+ else
+ {
+ int cmd0 = rdp.cmd0;
+ SETOTHERMODE(0xB9, 0, 32, rdp.cmd1); // SETOTHERMODE_L
+ SETOTHERMODE(0xBA, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H
+ }
+}
+
+void load_palette (wxUint32 addr, wxUint16 start, wxUint16 count)
+{
+ LRDP("Loading palette... ");
+ wxUint16 *dpal = rdp.pal_8 + start;
+ wxUint16 end = start+count;
+#ifdef TEXTURE_FILTER
+ wxUint16 *spal = (wxUint16*)(gfx.RDRAM + (addr & BMASK));
+#endif
+
+ for (wxUint16 i=start; i<end; i++)
+ {
+ *(dpal++) = *(wxUint16 *)(gfx.RDRAM + (addr^2));
+ addr += 2;
+
+#ifdef TLUT_LOGGING
+ FRDP ("%d: %08lx\n", i, *(wxUint16 *)(gfx.RDRAM + (addr^2)));
+#endif
+ }
+#ifdef TEXTURE_FILTER
+ if (settings.ghq_hirs)
+ memcpy((wxUint8*)(rdp.pal_8_rice+start), spal, count<<1);
+#endif
+ start >>= 4;
+ end = start + (count >> 4);
+ if (end == start) // it can be if count < 16
+ end = start + 1;
+ for (wxUint16 p = start; p < end; p++)
+ {
+ rdp.pal_8_crc[p] = CRC32( 0xFFFFFFFF, &rdp.pal_8[(p << 4)], 32 );
+ }
+ rdp.pal_256_crc = CRC32( 0xFFFFFFFF, rdp.pal_8_crc, 64 );
+ LRDP("Done.\n");
+}
+
+static void rdp_loadtlut()
+{
+ wxUint32 tile = (rdp.cmd1 >> 24) & 0x07;
+ wxUint16 start = rdp.tiles[tile].t_mem - 256; // starting location in the palettes
+ // wxUint16 start = ((wxUint16)(rdp.cmd1 >> 2) & 0x3FF) + 1;
+ wxUint16 count = ((wxUint16)(rdp.cmd1 >> 14) & 0x3FF) + 1; // number to copy
+
+ if (rdp.timg.addr + (count<<1) > BMASK)
+ count = (wxUint16)((BMASK - rdp.timg.addr) >> 1);
+
+ if (start+count > 256) count = 256-start;
+
+ FRDP("loadtlut: tile: %d, start: %d, count: %d, from: %08lx\n", tile, start, count,
+ rdp.timg.addr);
+
+ load_palette (rdp.timg.addr, start, count);
+
+ rdp.timg.addr += count << 1;
+
+ if (rdp.tbuff_tex) //paranoid check.
+ {
+ //the buffer is definitely wrong, as there must be no CI frame buffers
+ //find and remove it
+ for (int i = 0; i < voodoo.num_tmu; i++)
+ {
+ for (int j = 0; j < rdp.texbufs[i].count; j++)
+ {
+ if (&(rdp.texbufs[i].images[j]) == rdp.tbuff_tex)
+ {
+ rdp.texbufs[i].count--;
+ if (j < rdp.texbufs[i].count)
+ memcpy(&(rdp.texbufs[i].images[j]), &(rdp.texbufs[i].images[j+1]), sizeof(TBUFF_COLOR_IMAGE)*(rdp.texbufs[i].count-j));
+ return;
+ }
+ }
+ }
+ }
+}
+
+int tile_set = 0;
+static void rdp_settilesize()
+{
+ wxUint32 tile = (rdp.cmd1 >> 24) & 0x07;
+ rdp.last_tile_size = tile;
+
+ rdp.tiles[tile].f_ul_s = (float)((rdp.cmd0 >> 12) & 0xFFF) / 4.0f;
+ rdp.tiles[tile].f_ul_t = (float)(rdp.cmd0 & 0xFFF) / 4.0f;
+
+ int ul_s = (((wxUint16)(rdp.cmd0 >> 14)) & 0x03ff);
+ int ul_t = (((wxUint16)(rdp.cmd0 >> 2 )) & 0x03ff);
+ int lr_s = (((wxUint16)(rdp.cmd1 >> 14)) & 0x03ff);
+ int lr_t = (((wxUint16)(rdp.cmd1 >> 2 )) & 0x03ff);
+
+ if (lr_s == 0 && ul_s == 0) //pokemon puzzle league set such tile size
+ wrong_tile = tile;
+ else if (wrong_tile == (int)tile)
+ wrong_tile = -1;
+
+ if (settings.use_sts1_only)
+ {
+ // ** USE FIRST SETTILESIZE ONLY **
+ // This option helps certain textures while using the 'Alternate texture size method',
+ // but may break others. (should help more than break)
+
+ if (tile_set)
+ {
+ // coords in 10.2 format
+ rdp.tiles[tile].ul_s = ul_s;
+ rdp.tiles[tile].ul_t = ul_t;
+ rdp.tiles[tile].lr_s = lr_s;
+ rdp.tiles[tile].lr_t = lr_t;
+ tile_set = 0;
+ }
+ }
+ else
+ {
+ // coords in 10.2 format
+ rdp.tiles[tile].ul_s = ul_s;
+ rdp.tiles[tile].ul_t = ul_t;
+ rdp.tiles[tile].lr_s = lr_s;
+ rdp.tiles[tile].lr_t = lr_t;
+ }
+
+ // handle wrapping
+ if (rdp.tiles[tile].lr_s < rdp.tiles[tile].ul_s) rdp.tiles[tile].lr_s += 0x400;
+ if (rdp.tiles[tile].lr_t < rdp.tiles[tile].ul_t) rdp.tiles[tile].lr_t += 0x400;
+
+ rdp.update |= UPDATE_TEXTURE;
+
+ rdp.first = 1;
+
+ FRDP ("settilesize: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d, f_ul_s: %f, f_ul_t: %f\n",
+ tile, ul_s, ul_t, lr_s, lr_t, rdp.tiles[tile].f_ul_s, rdp.tiles[tile].f_ul_t);
+}
+
+void setTBufTex(wxUint16 t_mem, wxUint32 cnt)
+{
+ FRDP("setTBufTex t_mem=%d, cnt=%d\n", t_mem, cnt);
+ TBUFF_COLOR_IMAGE * pTbufTex = rdp.tbuff_tex;
+ for (int i = 0; i < 2; i++)
+ {
+ LRDP("Before: ");
+ if (rdp.aTBuffTex[i]) {
+ FRDP("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);
+ } else {
+ FRDP("rdp.aTBuffTex[%d]=0\n", i);
+ }
+ if ((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))
+ {
+ if (pTbufTex)
+ {
+ rdp.aTBuffTex[i] = pTbufTex;
+ rdp.aTBuffTex[i]->t_mem = t_mem;
+ pTbufTex = 0;
+ FRDP("rdp.aTBuffTex[%d] tmu=%d t_mem=%d\n", i, rdp.aTBuffTex[i]->tmu, rdp.aTBuffTex[i]->t_mem);
+ }
+ else
+ {
+ rdp.aTBuffTex[i] = 0;
+ FRDP("rdp.aTBuffTex[%d]=0\n", i);
+ }
+ }
+ }
+}
+
+static inline void loadBlock(uint32_t *src, uint32_t *dst, uint32_t off, int dxt, int cnt)
+{
+ uint32_t *v5;
+ int v6;
+ uint32_t *v7;
+ uint32_t v8;
+ int v9;
+ uint32_t v10;
+ uint32_t *v11;
+ uint32_t v12;
+ uint32_t v13;
+ uint32_t v14;
+ int v15;
+ int v16;
+ uint32_t *v17;
+ int v18;
+ uint32_t v19;
+ uint32_t v20;
+ int i;
+
+ v5 = dst;
+ v6 = cnt;
+ if ( cnt )
+ {
+ v7 = (uint32_t *)((char *)src + (off & 0xFFFFFFFC));
+ v8 = off & 3;
+ if ( !(off & 3) )
+ goto LABEL_23;
+ v9 = 4 - v8;
+ v10 = *v7;
+ v11 = v7 + 1;
+ do
+ {
+ v10 = __ROL__(v10, 8);
+ --v8;
+ }
+ while ( v8 );
+ do
+ {
+ v10 = __ROL__(v10, 8);
+ *(uint8_t *)v5 = v10;
+ v5 = (uint32_t *)((char *)v5 + 1);
+ --v9;
+ }
+ while ( v9 );
+ v12 = *v11;
+ v7 = v11 + 1;
+ *v5 = bswap32(v12);
+ ++v5;
+ v6 = cnt - 1;
+ if ( cnt != 1 )
+ {
+LABEL_23:
+ do
+ {
+ *v5 = bswap32(*v7);
+ v5[1] = bswap32(v7[1]);
+ v7 += 2;
+ v5 += 2;
+ --v6;
+ }
+ while ( v6 );
+ }
+ v13 = off & 3;
+ if ( off & 3 )
+ {
+ v14 = *(uint32_t *)((char *)src + ((8 * cnt + off) & 0xFFFFFFFC));
+ do
+ {
+ v14 = __ROL__(v14, 8);
+ *(uint8_t *)v5 = v14;
+ v5 = (uint32_t *)((char *)v5 + 1);
+ --v13;
+ }
+ while ( v13 );
+ }
+ }
+ v15 = cnt;
+ v16 = 0;
+ v17 = dst;
+ v18 = 0;
+dxt_test:
+ while ( 1 )
+ {
+ v17 += 2;
+ --v15;
+ if ( !v15 )
+ break;
+ v16 += dxt;
+ if ( v16 < 0 )
+ {
+ while ( 1 )
+ {
+ ++v18;
+ --v15;
+ if ( !v15 )
+ goto end_dxt_test;
+ v16 += dxt;
+ if ( v16 >= 0 )
+ {
+ for ( i = v15; v18; --v18 )
+ {
+ v19 = *v17;
+ *v17 = v17[1];
+ v17[1] = v19;
+ v17 += 2;
+ }
+ v15 = i;
+ goto dxt_test;
+ }
+ }
+ }
+ }
+end_dxt_test:
+ while ( v18 )
+ {
+ v20 = *v17;
+ *v17 = v17[1];
+ v17[1] = v20;
+ v17 += 2;
+ --v18;
+ }
+}
+
+void LoadBlock32b(wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 lr_s, wxUint32 dxt);
+static void rdp_loadblock()
+{
+ if (rdp.skip_drawing)
+ {
+ LRDP("loadblock skipped\n");
+ return;
+ }
+ wxUint32 tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07);
+ wxUint32 dxt = (wxUint32)(rdp.cmd1 & 0x0FFF);
+ wxUint16 lr_s = (wxUint16)(rdp.cmd1 >> 14) & 0x3FF;
+ if (ucode5_texshiftaddr)
+ {
+ if (ucode5_texshift % ((lr_s+1)<<3))
+ {
+ rdp.timg.addr -= ucode5_texshift;
+ ucode5_texshiftaddr = 0;
+ ucode5_texshift = 0;
+ ucode5_texshiftcount = 0;
+ }
+ else
+ ucode5_texshiftcount++;
+ }
+
+ rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr;
+
+ // ** DXT is used for swapping every other line
+ /* double fdxt = (double)0x8000000F/(double)((wxUint32)(2047/(dxt-1))); // F for error
+ wxUint32 _dxt = (wxUint32)fdxt;*/
+
+ // 0x00000800 -> 0x80000000 (so we can check the sign bit instead of the 11th bit)
+ wxUint32 _dxt = dxt << 20;
+
+ wxUint32 addr = segoffset(rdp.timg.addr) & BMASK;
+
+ // lr_s specifies number of 64-bit words to copy
+ // 10.2 format
+ wxUint16 ul_s = (wxUint16)(rdp.cmd0 >> 14) & 0x3FF;
+ wxUint16 ul_t = (wxUint16)(rdp.cmd0 >> 2) & 0x3FF;
+
+ rdp.tiles[tile].ul_s = ul_s;
+ rdp.tiles[tile].ul_t = ul_t;
+ rdp.tiles[tile].lr_s = lr_s;
+
+ rdp.timg.set_by = 0; // load block
+
+#ifdef TEXTURE_FILTER
+ LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[tile].t_mem];
+ info.tile_width = lr_s;
+ info.dxt = dxt;
+#endif
+
+ // do a quick boundary check before copying to eliminate the possibility for exception
+ if (ul_s >= 512) {
+ lr_s = 1; // 1 so that it doesn't die on memcpy
+ ul_s = 511;
+ }
+ if (ul_s+lr_s > 512)
+ lr_s = 512-ul_s;
+
+ if (addr+(lr_s<<3) > BMASK+1)
+ lr_s = (wxUint16)((BMASK-addr)>>3);
+
+ //angrylion's advice to use ul_s in texture image offset and cnt calculations.
+ //Helps to fix Vigilante 8 jpeg backgrounds and logos
+ wxUint32 off = rdp.timg.addr + (ul_s << rdp.tiles[tile].size >> 1);
+ unsigned char *dst = ((unsigned char *)rdp.tmem) + (rdp.tiles[tile].t_mem<<3);
+ wxUint32 cnt = lr_s-ul_s+1;
+ if (rdp.tiles[tile].size == 3)
+ cnt <<= 1;
+
+ if (((rdp.tiles[tile].t_mem + cnt) << 3) > sizeof(rdp.tmem)) {
+ WriteLog(M64MSG_INFO, "rdp_loadblock wanted to write %u bytes after the end of tmem", ((rdp.tiles[tile].t_mem + cnt) << 3) - sizeof(rdp.tmem));
+ cnt = (sizeof(rdp.tmem) >> 3) - (rdp.tiles[tile].t_mem);
+ }
+
+ if (rdp.timg.size == 3)
+ LoadBlock32b(tile, ul_s, ul_t, lr_s, dxt);
+ else
+ loadBlock((uint32_t *)gfx.RDRAM, (uint32_t *)dst, off, _dxt, cnt);
+
+ rdp.timg.addr += cnt << 3;
+ rdp.tiles[tile].lr_t = ul_t + ((dxt*cnt)>>11);
+
+ rdp.update |= UPDATE_TEXTURE;
+
+ FRDP ("loadblock: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, dxt: %08lx -> %08lx\n",
+ tile, ul_s, ul_t, lr_s,
+ dxt, _dxt);
+
+ if (fb_hwfbe_enabled)
+ setTBufTex(rdp.tiles[tile].t_mem, cnt);
+}
+
+
+static inline void loadTile(uint32_t *src, uint32_t *dst, int width, int height, int line, int off, uint32_t *end)
+{
+ uint32_t *v7;
+ int v8;
+ uint32_t *v9;
+ int v10;
+ int v11;
+ int v12;
+ uint32_t *v13;
+ int v14;
+ int v15;
+ uint32_t v16;
+ uint32_t *v17;
+ uint32_t v18;
+ int v19;
+ uint32_t v20;
+ int v21;
+ uint32_t v22;
+ int v23;
+ uint32_t *v24;
+ int v25;
+ int v26;
+ uint32_t *v27;
+ int v28;
+ int v29;
+ int v30;
+ uint32_t *v31;
+
+ v7 = dst;
+ v8 = width;
+ v9 = src;
+ v10 = off;
+ v11 = 0;
+ v12 = height;
+ do
+ {
+ if ( end < v7 )
+ break;
+ v31 = v7;
+ v30 = v8;
+ v29 = v12;
+ v28 = v11;
+ v27 = v9;
+ v26 = v10;
+ if ( v8 )
+ {
+ v25 = v8;
+ v24 = v9;
+ v23 = v10;
+ v13 = (uint32_t *)((char *)v9 + (v10 & 0xFFFFFFFC));
+ v14 = v10 & 3;
+ if ( !(v10 & 3) )
+ goto LABEL_20;
+ v15 = 4 - v14;
+ v16 = *v13;
+ v17 = v13 + 1;
+ do
+ {
+ v16 = __ROL__(v16, 8);
+ --v14;
+ }
+ while ( v14 );
+ do
+ {
+ v16 = __ROL__(v16, 8);
+ *(uint8_t *)v7 = v16;
+ v7 = (uint32_t *)((char *)v7 + 1);
+ --v15;
+ }
+ while ( v15 );
+ v18 = *v17;
+ v13 = v17 + 1;
+ *v7 = bswap32(v18);
+ ++v7;
+ --v8;
+ if ( v8 )
+ {
+LABEL_20:
+ do
+ {
+ *v7 = bswap32(*v13);
+ v7[1] = bswap32(v13[1]);
+ v13 += 2;
+ v7 += 2;
+ --v8;
+ }
+ while ( v8 );
+ }
+ v19 = v23 & 3;
+ if ( v23 & 3 )
+ {
+ v20 = *(uint32_t *)((char *)v24 + ((8 * v25 + v23) & 0xFFFFFFFC));
+ do
+ {
+ v20 = __ROL__(v20, 8);
+ *(uint8_t *)v7 = v20;
+ v7 = (uint32_t *)((char *)v7 + 1);
+ --v19;
+ }
+ while ( v19 );
+ }
+ }
+ v9 = v27;
+ v21 = v29;
+ v8 = v30;
+ v11 = v28 ^ 1;
+ if ( v28 == 1 )
+ {
+ v7 = v31;
+ if ( v30 )
+ {
+ do
+ {
+ v22 = *v7;
+ *v7 = v7[1];
+ v7[1] = v22;
+ v7 += 2;
+ --v8;
+ }
+ while ( v8 );
+ }
+ v21 = v29;
+ v8 = v30;
+ }
+ v10 = line + v26;
+ v12 = v21 - 1;
+ }
+ while ( v12 );
+}
+
+void LoadTile32b (wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 width, wxUint32 height);
+static void rdp_loadtile()
+{
+ if (rdp.skip_drawing)
+ {
+ LRDP("loadtile skipped\n");
+ return;
+ }
+ rdp.timg.set_by = 1; // load tile
+
+ wxUint32 tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07);
+
+ rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr;
+
+ wxUint16 ul_s = (wxUint16)((rdp.cmd0 >> 14) & 0x03FF);
+ wxUint16 ul_t = (wxUint16)((rdp.cmd0 >> 2 ) & 0x03FF);
+ wxUint16 lr_s = (wxUint16)((rdp.cmd1 >> 14) & 0x03FF);
+ wxUint16 lr_t = (wxUint16)((rdp.cmd1 >> 2 ) & 0x03FF);
+
+ if (lr_s < ul_s || lr_t < ul_t) return;
+
+ if (wrong_tile >= 0) //there was a tile with zero length
+ {
+ rdp.tiles[wrong_tile].lr_s = lr_s;
+
+ if (rdp.tiles[tile].size > rdp.tiles[wrong_tile].size)
+ rdp.tiles[wrong_tile].lr_s <<= (rdp.tiles[tile].size - rdp.tiles[wrong_tile].size);
+ else if (rdp.tiles[tile].size < rdp.tiles[wrong_tile].size)
+ rdp.tiles[wrong_tile].lr_s >>= (rdp.tiles[wrong_tile].size - rdp.tiles[tile].size);
+ rdp.tiles[wrong_tile].lr_t = lr_t;
+ rdp.tiles[wrong_tile].mask_s = rdp.tiles[wrong_tile].mask_t = 0;
+ // wrong_tile = -1;
+ }
+
+ if (rdp.tbuff_tex)// && (rdp.tiles[tile].format == 0))
+ {
+ FRDP("loadtile: tbuff_tex ul_s: %d, ul_t:%d\n", ul_s, ul_t);
+ rdp.tbuff_tex->tile_uls = ul_s;
+ rdp.tbuff_tex->tile_ult = ul_t;
+ }
+
+ if ((settings.hacks&hack_Tonic) && tile == 7)
+ {
+ rdp.tiles[0].ul_s = ul_s;
+ rdp.tiles[0].ul_t = ul_t;
+ rdp.tiles[0].lr_s = lr_s;
+ rdp.tiles[0].lr_t = lr_t;
+ }
+
+ wxUint32 height = lr_t - ul_t + 1; // get height
+ wxUint32 width = lr_s - ul_s + 1;
+
+#ifdef TEXTURE_FILTER
+ LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[tile].t_mem];
+ info.tile_ul_s = ul_s;
+ info.tile_ul_t = ul_t;
+ info.tile_width = (rdp.tiles[tile].mask_s ? min((wxUint16)width, 1<<rdp.tiles[tile].mask_s) : (wxUint16)width);
+ info.tile_height = (rdp.tiles[tile].mask_t ? min((wxUint16)height, 1<<rdp.tiles[tile].mask_t) : (wxUint16)height);
+ if (settings.hacks&hack_MK64) {
+ if (info.tile_width%2)
+ info.tile_width--;
+ if (info.tile_height%2)
+ info.tile_height--;
+ }
+ info.tex_width = rdp.timg.width;
+ info.tex_size = rdp.timg.size;
+#endif
+
+ int line_n = rdp.timg.width << rdp.tiles[tile].size >> 1;
+ wxUint32 offs = ul_t * line_n;
+ offs += ul_s << rdp.tiles[tile].size >> 1;
+ offs += rdp.timg.addr;
+ if (offs >= BMASK)
+ return;
+
+ if (rdp.timg.size == 3)
+ {
+ LoadTile32b(tile, ul_s, ul_t, width, height);
+ }
+ else
+ {
+ // check if points to bad location
+ if (offs + line_n*height > BMASK)
+ height = (BMASK - offs) / line_n;
+ if (height == 0)
+ return;
+
+ wxUint32 wid_64 = rdp.tiles[tile].line;
+ unsigned char *dst = ((unsigned char *)rdp.tmem) + (rdp.tiles[tile].t_mem<<3);
+ unsigned char *end = ((unsigned char *)rdp.tmem) + 4096 - (wid_64<<3);
+ loadTile((uint32_t *)gfx.RDRAM, (uint32_t *)dst, wid_64, height, line_n, offs, (uint32_t *)end);
+ }
+ FRDP("loadtile: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d\n", tile,
+ ul_s, ul_t, lr_s, lr_t);
+
+ if (fb_hwfbe_enabled)
+ setTBufTex(rdp.tiles[tile].t_mem, rdp.tiles[tile].line*height);
+}
+
+static void rdp_settile()
+{
+ tile_set = 1; // used to check if we only load the first settilesize
+
+ rdp.first = 0;
+
+ rdp.last_tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07);
+ TILE *tile = &rdp.tiles[rdp.last_tile];
+
+ tile->format = (wxUint8)((rdp.cmd0 >> 21) & 0x07);
+ tile->size = (wxUint8)((rdp.cmd0 >> 19) & 0x03);
+ tile->line = (wxUint16)((rdp.cmd0 >> 9) & 0x01FF);
+ tile->t_mem = (wxUint16)(rdp.cmd0 & 0x1FF);
+ tile->palette = (wxUint8)((rdp.cmd1 >> 20) & 0x0F);
+ tile->clamp_t = (wxUint8)((rdp.cmd1 >> 19) & 0x01);
+ tile->mirror_t = (wxUint8)((rdp.cmd1 >> 18) & 0x01);
+ tile->mask_t = (wxUint8)((rdp.cmd1 >> 14) & 0x0F);
+ tile->shift_t = (wxUint8)((rdp.cmd1 >> 10) & 0x0F);
+ tile->clamp_s = (wxUint8)((rdp.cmd1 >> 9) & 0x01);
+ tile->mirror_s = (wxUint8)((rdp.cmd1 >> 8) & 0x01);
+ tile->mask_s = (wxUint8)((rdp.cmd1 >> 4) & 0x0F);
+ tile->shift_s = (wxUint8)(rdp.cmd1 & 0x0F);
+
+ rdp.update |= UPDATE_TEXTURE;
+
+ FRDP ("settile: tile: %d, format: %s, size: %s, line: %d, "
+ "t_mem: %08lx, palette: %d, clamp_t/mirror_t: %s, mask_t: %d, "
+ "shift_t: %d, clamp_s/mirror_s: %s, mask_s: %d, shift_s: %d\n",
+ rdp.last_tile, str_format[tile->format], str_size[tile->size], tile->line,
+ tile->t_mem, tile->palette, str_cm[(tile->clamp_t<<1)|tile->mirror_t], tile->mask_t,
+ tile->shift_t, str_cm[(tile->clamp_s<<1)|tile->mirror_s], tile->mask_s, tile->shift_s);
+
+ if (fb_hwfbe_enabled && rdp.last_tile < rdp.cur_tile + 2)
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ if (rdp.aTBuffTex[i])
+ {
+ if (rdp.aTBuffTex[i]->t_mem == tile->t_mem)
+ {
+ if (rdp.aTBuffTex[i]->size == tile->size)
+ {
+ rdp.aTBuffTex[i]->tile = rdp.last_tile;
+ rdp.aTBuffTex[i]->info.format = tile->format == 0 ? GR_TEXFMT_RGB_565 : GR_TEXFMT_ALPHA_INTENSITY_88;
+ FRDP("rdp.aTBuffTex[%d] tile=%d, format=%s\n", i, rdp.last_tile, tile->format == 0 ? "RGB565" : "Alpha88");
+ }
+ else
+ rdp.aTBuffTex[i] = 0;
+ break;
+ }
+ else if (rdp.aTBuffTex[i]->tile == rdp.last_tile) //wrong! t_mem must be the same
+ rdp.aTBuffTex[i] = 0;
+ }
+ }
+ }
+}
+
+//
+// fillrect - fills a rectangle
+//
+
+static void rdp_fillrect()
+{
+ wxUint32 ul_x = ((rdp.cmd1 & 0x00FFF000) >> 14);
+ wxUint32 ul_y = (rdp.cmd1 & 0x00000FFF) >> 2;
+ wxUint32 lr_x = ((rdp.cmd0 & 0x00FFF000) >> 14) + 1;
+ wxUint32 lr_y = ((rdp.cmd0 & 0x00000FFF) >> 2) + 1;
+ if ((ul_x > lr_x) || (ul_y > lr_y))
+ {
+ LRDP("Fillrect. Wrong coordinates. Skipped\n");
+ return;
+ }
+ int pd_multiplayer = (settings.ucode == ucode_PerfectDark) && (rdp.cycle_mode == 3) && (rdp.fill_color == 0xFFFCFFFC);
+ if ((rdp.cimg == rdp.zimg) || (fb_emulation_enabled && rdp.frame_buffers[rdp.ci_count-1].status == ci_zimg) || pd_multiplayer)
+ {
+ LRDP("Fillrect - cleared the depth buffer\n");
+ if (fullscreen)
+ {
+ if (!(settings.hacks&hack_Hyperbike) || rdp.ci_width > 64) //do not clear main depth buffer for aux depth buffers
+ {
+ update_scissor ();
+ grDepthMask (FXTRUE);
+ grColorMask (FXFALSE, FXFALSE);
+ grBufferClear (0, 0, rdp.fill_color ? rdp.fill_color&0xFFFF : 0xFFFF);
+ grColorMask (FXTRUE, FXTRUE);
+ rdp.update |= UPDATE_ZBUF_ENABLED;
+ }
+ //if (settings.frame_buffer&fb_depth_clear)
+ {
+ ul_x = min(max(ul_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x);
+ lr_x = min(max(lr_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x);
+ ul_y = min(max(ul_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y);
+ lr_y = min(max(lr_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y);
+ wxUint32 zi_width_in_dwords = rdp.ci_width >> 1;
+ ul_x >>= 1;
+ lr_x >>= 1;
+ wxUint32 * dst = (wxUint32*)(gfx.RDRAM+rdp.cimg);
+ dst += ul_y * zi_width_in_dwords;
+ for (wxUint32 y = ul_y; y < lr_y; y++)
+ {
+ for (wxUint32 x = ul_x; x < lr_x; x++)
+ {
+ dst[x] = rdp.fill_color;
+ }
+ dst += zi_width_in_dwords;
+ }
+ }
+ }
+ return;
+ }
+
+ if (rdp.skip_drawing)
+ {
+ LRDP("Fillrect skipped\n");
+ return;
+ }
+
+ if (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))
+ {
+ wxUint32 color = rdp.fill_color;
+ if (rdp.ci_size < 3)
+ {
+ color = ((color&1)?0xFF:0) |
+ ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) |
+ ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) |
+ ((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8);
+ }
+ grDepthMask (FXFALSE);
+ grBufferClear (color, 0, 0xFFFF);
+ grDepthMask (FXTRUE);
+ rdp.update |= UPDATE_ZBUF_ENABLED;
+ LRDP("Fillrect - cleared the texture buffer\n");
+ return;
+ }
+
+ // Update scissor
+ if (fullscreen)
+ update_scissor ();
+
+ if (settings.decrease_fillrect_edge && rdp.cycle_mode == 0)
+ {
+ lr_x--; lr_y--;
+ }
+ FRDP("fillrect (%d,%d) -> (%d,%d), cycle mode: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, rdp.cycle_mode,
+ rdp.tri_n, rdp.tri_n+1);
+
+ FRDP("scissor (%d,%d) -> (%d,%d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x,
+ rdp.scissor.lr_y);
+
+ // KILL the floating point error with 0.01f
+ wxInt32 s_ul_x = (wxUint32)min(max(ul_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x);
+ wxInt32 s_lr_x = (wxUint32)min(max(lr_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x);
+ wxInt32 s_ul_y = (wxUint32)min(max(ul_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y);
+ wxInt32 s_lr_y = (wxUint32)min(max(lr_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y);
+
+ if (s_lr_x < 0) s_lr_x = 0;
+ if (s_lr_y < 0) s_lr_y = 0;
+ if ((wxUint32)s_ul_x > settings.res_x) s_ul_x = settings.res_x;
+ if ((wxUint32)s_ul_y > settings.res_y) s_ul_y = settings.res_y;
+
+ FRDP (" - %d, %d, %d, %d\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y);
+
+ if (fullscreen)
+ {
+ grFogMode (GR_FOG_DISABLE);
+
+ const float Z = (rdp.cycle_mode == 3) ? 0.0f : set_sprite_combine_mode();
+
+ // Draw the rectangle
+ VERTEX v[4] = {
+ { (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},
+ { (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},
+ { (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},
+ { (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} };
+
+ if (rdp.cycle_mode == 3)
+ {
+ wxUint32 color = rdp.fill_color;
+
+ if ((settings.hacks&hack_PMario) && rdp.frame_buffers[rdp.ci_count-1].status == ci_aux)
+ {
+ //background of auxiliary frame buffers must have zero alpha.
+ //make it black, set 0 alpha to plack pixels on frame buffer read
+ color = 0;
+ }
+ else if (rdp.ci_size < 3)
+ {
+ color = ((color&1)?0xFF:0) |
+ ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) |
+ ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) |
+ ((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8);
+ }
+
+ grConstantColorValue (color);
+
+ grColorCombine (GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_LOCAL_CONSTANT,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+ grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_LOCAL_CONSTANT,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+ grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);
+
+ grAlphaTestFunction (GR_CMP_ALWAYS);
+ if (grStippleModeExt)
+ grStippleModeExt(GR_STIPPLE_DISABLE);
+
+ grCullMode(GR_CULL_DISABLE);
+ grFogMode (GR_FOG_DISABLE);
+ grDepthBufferFunction (GR_CMP_ALWAYS);
+ grDepthMask (FXFALSE);
+
+ rdp.update |= UPDATE_COMBINE | UPDATE_CULL_MODE | UPDATE_FOG_ENABLED | UPDATE_ZBUF_ENABLED;
+ }
+ else
+ {
+ wxUint32 cmb_mode_c = (rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF);
+ wxUint32 cmb_mode_a = (rdp.cycle1 & 0x0FFF0000) | ((rdp.cycle2 >> 16) & 0x00000FFF);
+ if (cmb_mode_c == 0x9fff9fff || cmb_mode_a == 0x09ff09ff) //shade
+ {
+ AllowShadeMods (v, 4);
+ for (int k = 0; k < 4; k++)
+ apply_shade_mods (&v[k]);
+ }
+ if ((rdp.othermode_l & 0x4000) && ((rdp.othermode_l >> 16) == 0x0550)) //special blender mode for Bomberman64
+ {
+ grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_LOCAL_CONSTANT,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+ grConstantColorValue((cmb.ccolor&0xFFFFFF00)|(rdp.fog_color&0xFF));
+ rdp.update |= UPDATE_COMBINE;
+ }
+ }
+
+ if (settings.wireframe)
+ {
+ SetWireframeCol ();
+ grDrawLine (&v[0], &v[2]);
+ grDrawLine (&v[2], &v[1]);
+ grDrawLine (&v[1], &v[0]);
+ grDrawLine (&v[2], &v[3]);
+ grDrawLine (&v[3], &v[1]);
+ //grDrawLine (&v[1], &v[2]);
+ }
+ else
+ {
+ grDrawTriangle (&v[0], &v[2], &v[1]);
+ grDrawTriangle (&v[2], &v[3], &v[1]);
+ }
+
+ if (_debugger.capture)
+ {
+ VERTEX v1[3];
+ v1[0] = v[0];
+ v1[1] = v[2];
+ v1[2] = v[1];
+ add_tri (v1, 3, TRI_FILLRECT);
+ rdp.tri_n ++;
+ v1[0] = v[2];
+ v1[1] = v[3];
+ add_tri (v1, 3, TRI_FILLRECT);
+ rdp.tri_n ++;
+ }
+ else
+ rdp.tri_n += 2;
+ }
+ else
+ {
+ rdp.tri_n += 2;
+ }
+}
+
+//
+// setfillcolor - sets the filling color
+//
+
+static void rdp_setfillcolor()
+{
+ rdp.fill_color = rdp.cmd1;
+ rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE;
+
+ FRDP("setfillcolor: %08lx\n", rdp.cmd1);
+}
+
+static void rdp_setfogcolor()
+{
+ rdp.fog_color = rdp.cmd1;
+ rdp.update |= UPDATE_COMBINE | UPDATE_FOG_ENABLED;
+
+ FRDP("setfogcolor - %08lx\n", rdp.cmd1);
+}
+
+static void rdp_setblendcolor()
+{
+ rdp.blend_color = rdp.cmd1;
+ rdp.update |= UPDATE_COMBINE;
+
+ FRDP("setblendcolor: %08lx\n", rdp.cmd1);
+}
+
+static void rdp_setprimcolor()
+{
+ rdp.prim_color = rdp.cmd1;
+ rdp.prim_lodmin = (rdp.cmd0 >> 8) & 0xFF;
+ rdp.prim_lodfrac = max(rdp.cmd0 & 0xFF, rdp.prim_lodmin);
+ rdp.update |= UPDATE_COMBINE;
+
+ FRDP("setprimcolor: %08lx, lodmin: %d, lodfrac: %d\n", rdp.cmd1, rdp.prim_lodmin,
+ rdp.prim_lodfrac);
+}
+
+static void rdp_setenvcolor()
+{
+ rdp.env_color = rdp.cmd1;
+ rdp.update |= UPDATE_COMBINE;
+
+ FRDP("setenvcolor: %08lx\n", rdp.cmd1);
+}
+
+static void rdp_setcombine()
+{
+ rdp.c_a0 = (wxUint8)((rdp.cmd0 >> 20) & 0xF);
+ rdp.c_b0 = (wxUint8)((rdp.cmd1 >> 28) & 0xF);
+ rdp.c_c0 = (wxUint8)((rdp.cmd0 >> 15) & 0x1F);
+ rdp.c_d0 = (wxUint8)((rdp.cmd1 >> 15) & 0x7);
+ rdp.c_Aa0 = (wxUint8)((rdp.cmd0 >> 12) & 0x7);
+ rdp.c_Ab0 = (wxUint8)((rdp.cmd1 >> 12) & 0x7);
+ rdp.c_Ac0 = (wxUint8)((rdp.cmd0 >> 9) & 0x7);
+ rdp.c_Ad0 = (wxUint8)((rdp.cmd1 >> 9) & 0x7);
+
+ rdp.c_a1 = (wxUint8)((rdp.cmd0 >> 5) & 0xF);
+ rdp.c_b1 = (wxUint8)((rdp.cmd1 >> 24) & 0xF);
+ rdp.c_c1 = (wxUint8)((rdp.cmd0 >> 0) & 0x1F);
+ rdp.c_d1 = (wxUint8)((rdp.cmd1 >> 6) & 0x7);
+ rdp.c_Aa1 = (wxUint8)((rdp.cmd1 >> 21) & 0x7);
+ rdp.c_Ab1 = (wxUint8)((rdp.cmd1 >> 3) & 0x7);
+ rdp.c_Ac1 = (wxUint8)((rdp.cmd1 >> 18) & 0x7);
+ rdp.c_Ad1 = (wxUint8)((rdp.cmd1 >> 0) & 0x7);
+
+ rdp.cycle1 = (rdp.c_a0<<0) | (rdp.c_b0<<4) | (rdp.c_c0<<8) | (rdp.c_d0<<13)|
+ (rdp.c_Aa0<<16)| (rdp.c_Ab0<<19)| (rdp.c_Ac0<<22)| (rdp.c_Ad0<<25);
+ rdp.cycle2 = (rdp.c_a1<<0) | (rdp.c_b1<<4) | (rdp.c_c1<<8) | (rdp.c_d1<<13)|
+ (rdp.c_Aa1<<16)| (rdp.c_Ab1<<19)| (rdp.c_Ac1<<22)| (rdp.c_Ad1<<25);
+
+ rdp.update |= UPDATE_COMBINE;
+
+ FRDP("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",
+ Mode0[rdp.c_a0], Mode1[rdp.c_b0], Mode2[rdp.c_c0], Mode3[rdp.c_d0],
+ Alpha0[rdp.c_Aa0], Alpha1[rdp.c_Ab0], Alpha2[rdp.c_Ac0], Alpha3[rdp.c_Ad0],
+ Mode0[rdp.c_a1], Mode1[rdp.c_b1], Mode2[rdp.c_c1], Mode3[rdp.c_d1],
+ Alpha0[rdp.c_Aa1], Alpha1[rdp.c_Ab1], Alpha2[rdp.c_Ac1], Alpha3[rdp.c_Ad1]);
+}
+
+//
+// settextureimage - sets the source for an image copy
+//
+
+static void rdp_settextureimage()
+{
+ static const char *format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" };
+ static const char *size[] = { "4bit", "8bit", "16bit", "32bit" };
+
+ rdp.timg.format = (wxUint8)((rdp.cmd0 >> 21) & 0x07);
+ rdp.timg.size = (wxUint8)((rdp.cmd0 >> 19) & 0x03);
+ rdp.timg.width = (wxUint16)(1 + (rdp.cmd0 & 0x00000FFF));
+ rdp.timg.addr = segoffset(rdp.cmd1);
+ if (ucode5_texshiftaddr)
+ {
+ if (rdp.timg.format == 0)
+ {
+ wxUint16 * t = (wxUint16*)(gfx.RDRAM+ucode5_texshiftaddr);
+ ucode5_texshift = t[ucode5_texshiftcount^1];
+ rdp.timg.addr += ucode5_texshift;
+ }
+ else
+ {
+ ucode5_texshiftaddr = 0;
+ ucode5_texshift = 0;
+ ucode5_texshiftcount = 0;
+ }
+ }
+ rdp.s2dex_tex_loaded = TRUE;
+ rdp.update |= UPDATE_TEXTURE;
+
+ if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self && (rdp.timg.addr >= rdp.cimg) && (rdp.timg.addr < rdp.ci_end))
+ {
+ if (!rdp.fb_drawn)
+ {
+ if (!rdp.cur_image)
+ CopyFrameBuffer();
+ else
+ CloseTextureBuffer(TRUE);
+ rdp.fb_drawn = TRUE;
+ }
+ }
+
+ if (fb_hwfbe_enabled) //search this texture among drawn texture buffers
+ FindTextureBuffer(rdp.timg.addr, rdp.timg.width);
+
+ FRDP("settextureimage: format: %s, size: %s, width: %d, addr: %08lx\n",
+ format[rdp.timg.format], size[rdp.timg.size],
+ rdp.timg.width, rdp.timg.addr);
+}
+
+static void rdp_setdepthimage()
+{
+ rdp.zimg = segoffset(rdp.cmd1) & BMASK;
+ rdp.zi_width = rdp.ci_width;
+ FRDP("setdepthimage - %08lx\n", rdp.zimg);
+}
+
+int SwapOK = TRUE;
+static void RestoreScale()
+{
+ FRDP("Return to original scale: x = %f, y = %f\n", rdp.scale_x_bak, rdp.scale_y_bak);
+ rdp.scale_x = rdp.scale_x_bak;
+ rdp.scale_y = rdp.scale_y_bak;
+ // update_scissor();
+ rdp.view_scale[0] *= rdp.scale_x;
+ rdp.view_scale[1] *= rdp.scale_y;
+ rdp.view_trans[0] *= rdp.scale_x;
+ rdp.view_trans[1] *= rdp.scale_y;
+ rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
+ //*
+ if (fullscreen)
+ {
+ grDepthMask (FXFALSE);
+ grBufferClear (0, 0, 0xFFFF);
+ grDepthMask (FXTRUE);
+ }
+ //*/
+}
+
+static wxUint32 swapped_addr = 0;
+
+static void rdp_setcolorimage()
+{
+//unsigned int ticks = ticksGetTicks();
+//bool showdeb = false;
+ if (fb_emulation_enabled && (rdp.num_of_ci < NUMTEXBUF))
+ {
+ COLOR_IMAGE & cur_fb = rdp.frame_buffers[rdp.ci_count];
+ COLOR_IMAGE & prev_fb = rdp.frame_buffers[rdp.ci_count?rdp.ci_count-1:0];
+ COLOR_IMAGE & next_fb = rdp.frame_buffers[rdp.ci_count+1];
+//if (cur_fb.status==ci_aux) showdeb = true;
+//if (showdeb) printf("rp_setcolorimage, status=%i\n", cur_fb.status);
+ switch (cur_fb.status)
+ {
+ case ci_main:
+ {
+
+ if (rdp.ci_count == 0)
+ {
+ if ((rdp.ci_status == ci_aux)) //for PPL
+ {
+ float sx = rdp.scale_x;
+ float sy = rdp.scale_y;
+ rdp.scale_x = 1.0f;
+ rdp.scale_y = 1.0f;
+ CopyFrameBuffer ();
+ rdp.scale_x = sx;
+ rdp.scale_y = sy;
+ }
+ if (!fb_hwfbe_enabled)
+ {
+ if ((rdp.num_of_ci > 1) &&
+ (next_fb.status == ci_aux) &&
+ (next_fb.width >= cur_fb.width))
+ {
+ rdp.scale_x = 1.0f;
+ rdp.scale_y = 1.0f;
+ }
+ }
+ else if (rdp.copy_ci_index && (settings.hacks&hack_PMario)) //tidal wave
+ OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
+ }
+ else if (!rdp.motionblur && fb_hwfbe_enabled && !SwapOK && (rdp.ci_count <= rdp.copy_ci_index))
+ {
+ if (next_fb.status == ci_aux_copy)
+ OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
+ else
+ OpenTextureBuffer(rdp.frame_buffers[rdp.copy_ci_index]);
+ }
+ else if (fb_hwfbe_enabled && prev_fb.status == ci_aux)
+ {
+ if (rdp.motionblur)
+ {
+ rdp.cur_image = &(rdp.texbufs[rdp.cur_tex_buf].images[0]);
+ grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
+ grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2,
+ rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH );
+ }
+ else if (rdp.read_whole_frame)
+ {
+ OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
+ }
+ }
+ //else if (rdp.ci_status == ci_aux && !rdp.copy_ci_index)
+ // CloseTextureBuffer();
+
+ rdp.skip_drawing = FALSE;
+ }
+ break;
+ case ci_copy:
+ {
+ if (!rdp.motionblur || (settings.frame_buffer&fb_motionblur))
+ {
+ if (cur_fb.width == rdp.ci_width)
+ {
+ if (CopyTextureBuffer(prev_fb, cur_fb))
+ {
+ // if (CloseTextureBuffer(TRUE))
+ //*
+ if ((settings.hacks&hack_Zelda) && (rdp.frame_buffers[rdp.ci_count+2].status == ci_aux) && !rdp.fb_drawn) //hack for photo camera in Zelda MM
+ {
+ CopyFrameBuffer (GR_BUFFER_TEXTUREBUFFER_EXT);
+ rdp.fb_drawn = TRUE;
+ memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);
+ }
+ //*/
+ }
+ else
+ {
+ if (!rdp.fb_drawn || prev_fb.status == ci_copy_self)
+ {
+ CopyFrameBuffer ();
+ rdp.fb_drawn = TRUE;
+ }
+ memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);
+ }
+ }
+ else
+ {
+ CloseTextureBuffer(TRUE);
+ }
+ }
+ else
+ {
+ memset(gfx.RDRAM+cur_fb.addr, 0, cur_fb.width*cur_fb.height*rdp.ci_size);
+ }
+ rdp.skip_drawing = TRUE;
+ }
+ break;
+ case ci_aux_copy:
+ {
+ rdp.skip_drawing = FALSE;
+ if (CloseTextureBuffer(prev_fb.status != ci_aux_copy))
+ ;
+ else if (!rdp.fb_drawn)
+ {
+ CopyFrameBuffer ();
+ rdp.fb_drawn = TRUE;
+ }
+ if (fb_hwfbe_enabled)
+ OpenTextureBuffer(cur_fb);
+ }
+ break;
+ case ci_old_copy:
+ {
+ if (!rdp.motionblur || (settings.frame_buffer&fb_motionblur))
+ {
+ if (cur_fb.width == rdp.ci_width)
+ {
+ memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.maincimg[1].addr, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);
+ }
+ //rdp.skip_drawing = TRUE;
+ }
+ else
+ {
+ memset(gfx.RDRAM+cur_fb.addr, 0, (cur_fb.width*cur_fb.height)<<rdp.ci_size>>1);
+ }
+ }
+ break;
+ /*
+ else if (rdp.frame_buffers[rdp.ci_count].status == ci_main_i)
+ {
+ // CopyFrameBuffer ();
+ rdp.scale_x = rdp.scale_x_bak;
+ rdp.scale_y = rdp.scale_y_bak;
+ rdp.skip_drawing = FALSE;
+ }
+ */
+ case ci_aux:
+ {
+//unsigned int tticks = ticksGetTicks();
+ if (!fb_hwfbe_enabled && cur_fb.format != 0)
+ rdp.skip_drawing = TRUE;
+ else
+ {
+ rdp.skip_drawing = FALSE;
+ if (fb_hwfbe_enabled && OpenTextureBuffer(cur_fb))
+ ;
+ else
+ {
+ if (cur_fb.format != 0)
+ rdp.skip_drawing = TRUE;
+ if (rdp.ci_count == 0)
+ {
+ // if (rdp.num_of_ci > 1)
+ // {
+ rdp.scale_x = 1.0f;
+ rdp.scale_y = 1.0f;
+ // }
+ }
+ else if (!fb_hwfbe_enabled && (prev_fb.status == ci_main) &&
+ (prev_fb.width == cur_fb.width)) // for Pokemon Stadium
+ CopyFrameBuffer ();
+ }
+ }
+ cur_fb.status = ci_aux;
+//tticks = ticksGetTicks() - ticks;
+//printf("intermediary: %u ms\n", tticks);
+ }
+ break;
+ case ci_zimg:
+ if (settings.ucode != ucode_PerfectDark)
+ {
+ if (fb_hwfbe_enabled && !rdp.copy_ci_index && (rdp.copy_zi_index || (settings.hacks&hack_BAR)))
+ {
+ GrLOD_t LOD = GR_LOD_LOG2_1024;
+ if (settings.scr_res_x > 1024)
+ LOD = GR_LOD_LOG2_2048;
+ grTextureAuxBufferExt( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, LOD, LOD,
+ GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
+ grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT );
+ LRDP("rdp_setcolorimage - set texture depth buffer to TMU0\n");
+ }
+ }
+ rdp.skip_drawing = TRUE;
+ break;
+ case ci_zcopy:
+ if (settings.ucode != ucode_PerfectDark)
+ {
+ if (fb_hwfbe_enabled && !rdp.copy_ci_index && rdp.copy_zi_index == rdp.ci_count)
+ {
+ CopyDepthBuffer();
+ }
+ rdp.skip_drawing = TRUE;
+ }
+ break;
+ case ci_useless:
+ rdp.skip_drawing = TRUE;
+ break;
+ case ci_copy_self:
+ if (fb_hwfbe_enabled && (rdp.ci_count <= rdp.copy_ci_index) && (!SwapOK || settings.swapmode == 2))
+ OpenTextureBuffer(cur_fb);
+ rdp.skip_drawing = FALSE;
+ break;
+ default:
+ rdp.skip_drawing = FALSE;
+ }
+
+ if ((rdp.ci_count > 0) && (prev_fb.status >= ci_aux)) //for Pokemon Stadium
+ {
+ if (!fb_hwfbe_enabled && prev_fb.format == 0)
+ CopyFrameBuffer ();
+ else if ((settings.hacks&hack_Knockout) && prev_fb.width < 100)
+ CopyFrameBuffer (GR_BUFFER_TEXTUREBUFFER_EXT);
+ }
+ if (!fb_hwfbe_enabled && cur_fb.status == ci_copy)
+ {
+ if (!rdp.motionblur && (rdp.num_of_ci > rdp.ci_count+1) && (next_fb.status != ci_aux))
+ {
+ RestoreScale();
+ }
+ }
+ if (!fb_hwfbe_enabled && cur_fb.status == ci_aux)
+ {
+ if (cur_fb.format == 0)
+ {
+ if ((settings.hacks&hack_PPL) && (rdp.scale_x < 1.1f)) //need to put current image back to frame buffer
+ {
+ int width = cur_fb.width;
+ int height = cur_fb.height;
+ wxUint16 *ptr_dst = new wxUint16[width*height];
+ wxUint16 *ptr_src = (wxUint16*)(gfx.RDRAM+cur_fb.addr);
+ wxUint16 c;
+
+ for (int y=0; y<height; y++)
+ {
+ for (int x=0; x<width; x++)
+ {
+ c = ((ptr_src[(x + y * width)^1]) >> 1) | 0x8000;
+ ptr_dst[x + y * width] = c;
+ }
+ }
+ grLfbWriteRegion(GR_BUFFER_BACKBUFFER,
+ (wxUint32)rdp.offset_x,
+ (wxUint32)rdp.offset_y,
+ GR_LFB_SRC_FMT_555,
+ width,
+ height,
+ FXFALSE,
+ width<<1,
+ ptr_dst);
+ delete[] ptr_dst;
+ }
+ /*
+ else //just clear buffer
+ {
+
+ grColorMask(FXTRUE, FXTRUE);
+ grBufferClear (0, 0, 0xFFFF);
+ }
+ */
+ }
+ }
+
+ if ((cur_fb.status == ci_main) && (rdp.ci_count > 0))
+ {
+ int to_org_res = TRUE;
+ for (int i = rdp.ci_count + 1; i < rdp.num_of_ci; i++)
+ {
+ if ((rdp.frame_buffers[i].status != ci_main) && (rdp.frame_buffers[i].status != ci_zimg) && (rdp.frame_buffers[i].status != ci_zcopy))
+ {
+ to_org_res = FALSE;
+ break;
+ }
+ }
+ if (to_org_res)
+ {
+ LRDP("return to original scale\n");
+ rdp.scale_x = rdp.scale_x_bak;
+ rdp.scale_y = rdp.scale_y_bak;
+ if (fb_hwfbe_enabled && !rdp.read_whole_frame)
+ CloseTextureBuffer();
+ }
+ if (fb_hwfbe_enabled && !rdp.read_whole_frame && (prev_fb.status >= ci_aux) && (rdp.ci_count > rdp.copy_ci_index))
+ CloseTextureBuffer();
+
+ }
+ rdp.ci_status = cur_fb.status;
+ rdp.ci_count++;
+ }
+
+ rdp.ocimg = rdp.cimg;
+ rdp.cimg = segoffset(rdp.cmd1) & BMASK;
+ rdp.ci_width = (rdp.cmd0 & 0xFFF) + 1;
+ if (fb_emulation_enabled)
+ rdp.ci_height = rdp.frame_buffers[rdp.ci_count-1].height;
+ else if (rdp.ci_width == 32)
+ rdp.ci_height = 32;
+ else
+ rdp.ci_height = rdp.scissor_o.lr_y;
+ if (rdp.zimg == rdp.cimg)
+ {
+ rdp.zi_width = rdp.ci_width;
+ // int zi_height = min((int)rdp.zi_width*3/4, (int)rdp.vi_height);
+ // rdp.zi_words = rdp.zi_width * zi_height;
+ }
+ wxUint32 format = (rdp.cmd0 >> 21) & 0x7;
+ rdp.ci_size = (rdp.cmd0 >> 19) & 0x3;
+ rdp.ci_end = rdp.cimg + ((rdp.ci_width*rdp.ci_height)<<(rdp.ci_size-1));
+ FRDP("setcolorimage - %08lx, width: %d, height: %d, format: %d, size: %d\n", rdp.cmd1, rdp.ci_width, rdp.ci_height, format, rdp.ci_size);
+ FRDP("cimg: %08lx, ocimg: %08lx, SwapOK: %d\n", rdp.cimg, rdp.ocimg, SwapOK);
+
+//if (showdeb) printf("setcolorimage - %08x, width: %d, height: %d, format: %d, size: %d\n", rdp.cmd1, rdp.ci_width, rdp.ci_height, format, rdp.ci_size);
+//if (showdeb) printf("cimg: %08x, ocimg: %08x, SwapOK: %d\n", rdp.cimg, rdp.ocimg, SwapOK);
+
+ if (format != 0) //can't draw into non RGBA buffer
+ {
+ if (!rdp.cur_image)
+ {
+ if (fb_hwfbe_enabled && rdp.ci_width <= 64)
+ OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count - 1]);
+ else if (format > 2)
+ rdp.skip_drawing = TRUE;
+ return;
+ }
+ }
+ else
+ {
+ if (!fb_emulation_enabled)
+ rdp.skip_drawing = FALSE;
+ }
+
+ CI_SET = TRUE;
+ if (settings.swapmode > 0)
+ {
+ if (rdp.zimg == rdp.cimg)
+ rdp.updatescreen = 1;
+
+ int viSwapOK = ((settings.swapmode == 2) && (rdp.vi_org_reg == *gfx.VI_ORIGIN_REG)) ? FALSE : TRUE;
+ if ((rdp.zimg != rdp.cimg) && (rdp.ocimg != rdp.cimg) && SwapOK && viSwapOK && !rdp.cur_image)
+ {
+ if (fb_emulation_enabled)
+ rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index];
+ else
+ rdp.maincimg[0].addr = rdp.cimg;
+ rdp.last_drawn_ci_addr = (settings.swapmode == 2) ? swapped_addr : rdp.maincimg[0].addr;
+ swapped_addr = rdp.cimg;
+ newSwapBuffers();
+ rdp.vi_org_reg = *gfx.VI_ORIGIN_REG;
+ SwapOK = FALSE;
+ if (fb_hwfbe_enabled)
+ {
+ if (rdp.copy_ci_index && (rdp.frame_buffers[rdp.ci_count-1].status != ci_zimg))
+ {
+ int idx = (rdp.frame_buffers[rdp.ci_count].status == ci_aux_copy) ? rdp.main_ci_index : rdp.copy_ci_index;
+ FRDP("attempt open tex buffer. status: %s, addr: %08lx\n", CIStatus[rdp.frame_buffers[idx].status], rdp.frame_buffers[idx].addr);
+ OpenTextureBuffer(rdp.frame_buffers[idx]);
+ if (rdp.frame_buffers[rdp.copy_ci_index].status == ci_main) //tidal wave
+ rdp.copy_ci_index = 0;
+ }
+ else if (rdp.read_whole_frame && !rdp.cur_image)
+ {
+ OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
+ }
+ }
+ }
+ }
+//ticks = ticksGetTicks() - ticks;
+//if (showdeb) printf("time = %u\n", ticks);
+}
+
+static void rsp_reserved0()
+{
+ if (settings.ucode == ucode_DiddyKong)
+ {
+ ucode5_texshiftaddr = segoffset(rdp.cmd1);
+ ucode5_texshiftcount = 0;
+ FRDP("uc5_texshift. addr: %08lx\n", ucode5_texshiftaddr);
+ }
+ else
+ {
+ RDP_E("reserved0 - IGNORED\n");
+ LRDP("reserved0 - IGNORED\n");
+ }
+}
+
+static void rsp_reserved1()
+{
+ LRDP("reserved1 - ignored\n");
+}
+
+static void rsp_reserved2()
+{
+ LRDP("reserved2\n");
+}
+
+static void rsp_reserved3()
+{
+ LRDP("reserved3 - ignored\n");
+}
+
+void SetWireframeCol ()
+{
+ if (!fullscreen) return;
+
+ switch (settings.wfmode)
+ {
+ //case 0: // normal colors, don't do anything
+ case 1: // vertex colors
+ grColorCombine (GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_LOCAL_ITERATED,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+ grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_LOCAL_ITERATED,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+ grAlphaBlendFunction (GR_BLEND_ONE,
+ GR_BLEND_ZERO,
+ GR_BLEND_ZERO,
+ GR_BLEND_ZERO);
+ grTexCombine (GR_TMU0,
+ GR_COMBINE_FUNCTION_ZERO,
+ GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_ZERO,
+ GR_COMBINE_FACTOR_NONE,
+ FXFALSE, FXFALSE);
+ grTexCombine (GR_TMU1,
+ GR_COMBINE_FUNCTION_ZERO,
+ GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_ZERO,
+ GR_COMBINE_FACTOR_NONE,
+ FXFALSE, FXFALSE);
+ break;
+ case 2: // red only
+ grColorCombine (GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_LOCAL_CONSTANT,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+ grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_LOCAL_CONSTANT,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+ grConstantColorValue (0xFF0000FF);
+ grAlphaBlendFunction (GR_BLEND_ONE,
+ GR_BLEND_ZERO,
+ GR_BLEND_ZERO,
+ GR_BLEND_ZERO);
+ grTexCombine (GR_TMU0,
+ GR_COMBINE_FUNCTION_ZERO,
+ GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_ZERO,
+ GR_COMBINE_FACTOR_NONE,
+ FXFALSE, FXFALSE);
+ grTexCombine (GR_TMU1,
+ GR_COMBINE_FUNCTION_ZERO,
+ GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_ZERO,
+ GR_COMBINE_FACTOR_NONE,
+ FXFALSE, FXFALSE);
+ break;
+ }
+
+ grAlphaTestFunction (GR_CMP_ALWAYS);
+ grCullMode (GR_CULL_DISABLE);
+
+ rdp.update |= UPDATE_COMBINE | UPDATE_ALPHA_COMPARE;
+}
+
+/******************************************************************
+Function: FrameBufferRead
+Purpose: This function is called to notify the dll that the
+frame buffer memory is beening read at the given address.
+DLL should copy content from its render buffer to the frame buffer
+in N64 RDRAM
+DLL is responsible to maintain its own frame buffer memory addr list
+DLL should copy 4KB block content back to RDRAM frame buffer.
+Emulator should not call this function again if other memory
+is read within the same 4KB range
+input: addr rdram address
+val val
+size 1 = wxUint8, 2 = wxUint16, 4 = wxUint32
+output: none
+*******************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EXPORT void CALL FBRead(wxUint32 addr)
+{
+ LOG ("FBRead ()\n");
+
+ if (cpu_fb_ignore)
+ return;
+ if (cpu_fb_write_called)
+ {
+ cpu_fb_ignore = TRUE;
+ cpu_fb_write = FALSE;
+ return;
+ }
+ cpu_fb_read_called = TRUE;
+ wxUint32 a = segoffset(addr);
+ FRDP("FBRead. addr: %08lx\n", a);
+ if (!rdp.fb_drawn && (a >= rdp.cimg) && (a < rdp.ci_end))
+ {
+ fbreads_back++;
+ //if (fbreads_back > 2) //&& (rdp.ci_width <= 320))
+ {
+ CopyFrameBuffer ();
+ rdp.fb_drawn = TRUE;
+ }
+ }
+ if (!rdp.fb_drawn_front && (a >= rdp.maincimg[1].addr) && (a < rdp.maincimg[1].addr + rdp.ci_width*rdp.ci_height*2))
+ {
+ fbreads_front++;
+ //if (fbreads_front > 2)//&& (rdp.ci_width <= 320))
+ {
+ wxUint32 cimg = rdp.cimg;
+ rdp.cimg = rdp.maincimg[1].addr;
+ if (fb_emulation_enabled)
+ {
+ rdp.ci_width = rdp.maincimg[1].width;
+ rdp.ci_count = 0;
+ wxUint32 h = rdp.frame_buffers[0].height;
+ rdp.frame_buffers[0].height = rdp.maincimg[1].height;
+ CopyFrameBuffer(GR_BUFFER_FRONTBUFFER);
+ rdp.frame_buffers[0].height = h;
+ }
+ else
+ {
+ CopyFrameBuffer(GR_BUFFER_FRONTBUFFER);
+ }
+ rdp.cimg = cimg;
+ rdp.fb_drawn_front = TRUE;
+ }
+ }
+}
+
+#if 0
+/******************************************************************
+Function: FrameBufferWriteList
+Purpose: This function is called to notify the dll that the
+frame buffer has been modified by CPU at the given address.
+input: FrameBufferModifyEntry *plist
+size = size of the plist, max = 1024
+output: none
+*******************************************************************/
+EXPORT void CALL FBWList(FrameBufferModifyEntry *plist, wxUint32 size)
+{
+ LOG ("FBWList ()\n");
+ FRDP("FBWList. size: %d\n", size);
+}
+#endif
+
+/******************************************************************
+Function: FrameBufferWrite
+Purpose: This function is called to notify the dll that the
+frame buffer has been modified by CPU at the given address.
+input: addr rdram address
+val val
+size 1 = wxUint8, 2 = wxUint16, 4 = wxUint32
+output: none
+*******************************************************************/
+EXPORT void CALL FBWrite(wxUint32 addr, wxUint32 size)
+{
+ LOG ("FBWrite ()\n");
+ if (cpu_fb_ignore)
+ return;
+ if (cpu_fb_read_called)
+ {
+ cpu_fb_ignore = TRUE;
+ cpu_fb_write = FALSE;
+ return;
+ }
+ cpu_fb_write_called = TRUE;
+ wxUint32 a = segoffset(addr);
+ FRDP("FBWrite. addr: %08lx\n", a);
+ if (a < rdp.cimg || a > rdp.ci_end)
+ return;
+ cpu_fb_write = TRUE;
+ wxUint32 shift_l = (a-rdp.cimg) >> 1;
+ wxUint32 shift_r = shift_l+2;
+
+ d_ul_x = min(d_ul_x, shift_l%rdp.ci_width);
+ d_ul_y = min(d_ul_y, shift_l/rdp.ci_width);
+ d_lr_x = max(d_lr_x, shift_r%rdp.ci_width);
+ d_lr_y = max(d_lr_y, shift_r/rdp.ci_width);
+}
+
+
+/************************************************************************
+Function: FBGetFrameBufferInfo
+Purpose: This function is called by the emulator core to retrieve frame
+buffer information from the video plugin in order to be able
+to notify the video plugin about CPU frame buffer read/write
+operations
+
+size:
+= 1 byte
+= 2 word (16 bit) <-- this is N64 default depth buffer format
+= 4 dword (32 bit)
+
+when frame buffer information is not available yet, set all values
+in the FrameBufferInfo structure to 0
+
+input: FrameBufferInfo pinfo[6]
+pinfo is pointed to a FrameBufferInfo structure which to be
+filled in by this function
+output: Values are return in the FrameBufferInfo structure
+Plugin can return up to 6 frame buffer info
+************************************************************************/
+///*
+#if 0
+typedef struct
+{
+ wxUint32 addr;
+ wxUint32 size;
+ wxUint32 width;
+ wxUint32 height;
+} FrameBufferInfo;
+#endif
+EXPORT void CALL FBGetFrameBufferInfo(void *p)
+{
+ VLOG ("FBGetFrameBufferInfo ()\n");
+ FrameBufferInfo * pinfo = (FrameBufferInfo *)p;
+ memset(pinfo,0,sizeof(FrameBufferInfo)*6);
+ if (!(settings.frame_buffer&fb_get_info))
+ return;
+ LRDP("FBGetFrameBufferInfo ()\n");
+ //*
+ if (fb_emulation_enabled)
+ {
+ pinfo[0].addr = rdp.maincimg[1].addr;
+ pinfo[0].size = rdp.maincimg[1].size;
+ pinfo[0].width = rdp.maincimg[1].width;
+ pinfo[0].height = rdp.maincimg[1].height;
+ int info_index = 1;
+ for (int i = 0; i < rdp.num_of_ci && info_index < 6; i++)
+ {
+ COLOR_IMAGE & cur_fb = rdp.frame_buffers[i];
+ if (cur_fb.status == ci_main || cur_fb.status == ci_copy_self ||
+ cur_fb.status == ci_old_copy)
+ {
+ pinfo[info_index].addr = cur_fb.addr;
+ pinfo[info_index].size = cur_fb.size;
+ pinfo[info_index].width = cur_fb.width;
+ pinfo[info_index].height = cur_fb.height;
+ info_index++;
+ }
+ }
+ }
+ else
+ {
+ pinfo[0].addr = rdp.maincimg[0].addr;
+ pinfo[0].size = rdp.ci_size;
+ pinfo[0].width = rdp.ci_width;
+ pinfo[0].height = rdp.ci_width*3/4;
+ pinfo[1].addr = rdp.maincimg[1].addr;
+ pinfo[1].size = rdp.ci_size;
+ pinfo[1].width = rdp.ci_width;
+ pinfo[1].height = rdp.ci_width*3/4;
+ }
+ //*/
+}
+#ifdef __cplusplus
+}
+#endif
+//*/
+#include "ucodeFB.h"
+
+void DetectFrameBufferUsage ()
+{
+ LRDP("DetectFrameBufferUsage\n");
+
+ wxUint32 dlist_start = *(wxUint32*)(gfx.DMEM+0xFF0);
+ wxUint32 a;
+
+ int tidal = FALSE;
+ if ((settings.hacks&hack_PMario) && (rdp.copy_ci_index || rdp.frame_buffers[rdp.copy_ci_index].status == ci_copy_self))
+ tidal = TRUE;
+ wxUint32 ci = rdp.cimg, zi = rdp.zimg;
+ wxUint32 ci_height = rdp.frame_buffers[(rdp.ci_count > 0)?rdp.ci_count-1:0].height;
+ rdp.main_ci = rdp.main_ci_end = rdp.main_ci_bg = rdp.ci_count = 0;
+ rdp.main_ci_index = rdp.copy_ci_index = rdp.copy_zi_index = 0;
+ rdp.zimg_end = 0;
+ rdp.tmpzimg = 0;
+ rdp.motionblur = FALSE;
+ rdp.main_ci_last_tex_addr = 0;
+ int previous_ci_was_read = rdp.read_previous_ci;
+ rdp.read_previous_ci = FALSE;
+ rdp.read_whole_frame = FALSE;
+ rdp.swap_ci_index = rdp.black_ci_index = -1;
+ SwapOK = TRUE;
+
+ // Start executing at the start of the display list
+ rdp.pc_i = 0;
+ rdp.pc[rdp.pc_i] = dlist_start;
+ rdp.dl_count = -1;
+ rdp.halt = 0;
+ rdp.scale_x_bak = rdp.scale_x;
+ rdp.scale_y_bak = rdp.scale_y;
+
+ // MAIN PROCESSING LOOP
+ do {
+
+ // Get the address of the next command
+ a = rdp.pc[rdp.pc_i] & BMASK;
+
+ // Load the next command and its input
+ rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit
+ rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // /
+
+ // Output the address before the command
+
+ // Go to the next instruction
+ rdp.pc[rdp.pc_i] = (a+8) & BMASK;
+
+ if (wxPtrToUInt(reinterpret_cast<void*>(gfx_instruction_lite[settings.ucode][rdp.cmd0>>24])))
+ gfx_instruction_lite[settings.ucode][rdp.cmd0>>24] ();
+
+ // check DL counter
+ if (rdp.dl_count != -1)
+ {
+ rdp.dl_count --;
+ if (rdp.dl_count == 0)
+ {
+ rdp.dl_count = -1;
+
+ LRDP("End of DL\n");
+ rdp.pc_i --;
+ }
+ }
+
+ } while (!rdp.halt);
+ SwapOK = TRUE;
+ if (rdp.ci_count > NUMTEXBUF) //overflow
+ {
+ rdp.cimg = ci;
+ rdp.zimg = zi;
+ rdp.num_of_ci = rdp.ci_count;
+ rdp.scale_x = rdp.scale_x_bak;
+ rdp.scale_y = rdp.scale_y_bak;
+ return;
+ }
+
+ if (rdp.black_ci_index > 0 && rdp.black_ci_index < rdp.copy_ci_index)
+ rdp.frame_buffers[rdp.black_ci_index].status = ci_main;
+
+ if (rdp.frame_buffers[rdp.ci_count-1].status == ci_unknown)
+ {
+ if (rdp.ci_count > 1)
+ rdp.frame_buffers[rdp.ci_count-1].status = ci_aux;
+ else
+ rdp.frame_buffers[rdp.ci_count-1].status = ci_main;
+ }
+
+ if ((rdp.frame_buffers[rdp.ci_count-1].status == ci_aux) &&
+ (rdp.frame_buffers[rdp.main_ci_index].width < 320) &&
+ (rdp.frame_buffers[rdp.ci_count-1].width > rdp.frame_buffers[rdp.main_ci_index].width))
+ {
+ for (int i = 0; i < rdp.ci_count; i++)
+ {
+ if (rdp.frame_buffers[i].status == ci_main)
+ rdp.frame_buffers[i].status = ci_aux;
+ else if (rdp.frame_buffers[i].addr == rdp.frame_buffers[rdp.ci_count-1].addr)
+ rdp.frame_buffers[i].status = ci_main;
+ // FRDP("rdp.frame_buffers[%d].status = %d\n", i, rdp.frame_buffers[i].status);
+ }
+ rdp.main_ci_index = rdp.ci_count-1;
+ }
+
+ int all_zimg = TRUE;
+ int i;
+ for (i = 0; i < rdp.ci_count; i++)
+ {
+ if (rdp.frame_buffers[i].status != ci_zimg)
+ {
+ all_zimg = FALSE;
+ break;
+ }
+ }
+ if (all_zimg)
+ {
+ for (i = 0; i < rdp.ci_count; i++)
+ rdp.frame_buffers[i].status = ci_main;
+ }
+
+ LRDP("detect fb final results: \n");
+ for (i = 0; i < rdp.ci_count; i++)
+ {
+ FRDP("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);
+ }
+
+ rdp.cimg = ci;
+ rdp.zimg = zi;
+ rdp.num_of_ci = rdp.ci_count;
+ if (rdp.read_previous_ci && previous_ci_was_read)
+ {
+ if (!fb_hwfbe_enabled || !rdp.copy_ci_index)
+ rdp.motionblur = TRUE;
+ }
+ if (rdp.motionblur || fb_hwfbe_enabled || (rdp.frame_buffers[rdp.copy_ci_index].status == ci_aux_copy))
+ {
+ rdp.scale_x = rdp.scale_x_bak;
+ rdp.scale_y = rdp.scale_y_bak;
+ }
+
+ if ((rdp.read_previous_ci || previous_ci_was_read) && !rdp.copy_ci_index)
+ rdp.read_whole_frame = TRUE;
+ if (rdp.read_whole_frame)
+ {
+ if (fb_hwfbe_enabled)
+ {
+ if (rdp.read_previous_ci && !previous_ci_was_read && (settings.swapmode != 2) && (settings.ucode != ucode_PerfectDark))
+ {
+ int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0;
+ wxUint32 height = rdp.frame_buffers[ind].height;
+ rdp.frame_buffers[ind].height = ci_height;
+ CopyFrameBuffer();
+ rdp.frame_buffers[ind].height = height;
+ }
+ if (rdp.swap_ci_index < 0)
+ {
+ rdp.texbufs[0].clear_allowed = rdp.texbufs[1].clear_allowed = TRUE;
+ OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
+ }
+ }
+ else
+ {
+ if (rdp.motionblur)
+ {
+ if (settings.frame_buffer&fb_motionblur)
+ CopyFrameBuffer();
+ else
+ memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size);
+ }
+ else //if (ci_width == rdp.frame_buffers[rdp.main_ci_index].width)
+ {
+ if (rdp.maincimg[0].height > 65) //for 1080
+ {
+ rdp.cimg = rdp.maincimg[0].addr;
+ rdp.ci_width = rdp.maincimg[0].width;
+ rdp.ci_count = 0;
+ wxUint32 h = rdp.frame_buffers[0].height;
+ rdp.frame_buffers[0].height = rdp.maincimg[0].height;
+ CopyFrameBuffer();
+ rdp.frame_buffers[0].height = h;
+ }
+ else //conker
+ {
+ CopyFrameBuffer();
+ }
+ }
+ }
+ }
+
+ if (fb_hwfbe_enabled)
+ {
+ for (i = 0; i < voodoo.num_tmu; i++)
+ {
+ rdp.texbufs[i].clear_allowed = TRUE;
+ for (int j = 0; j < 256; j++)
+ {
+ rdp.texbufs[i].images[j].drawn = FALSE;
+ rdp.texbufs[i].images[j].clear = TRUE;
+ }
+ }
+ if (tidal)
+ {
+ //LRDP("Tidal wave!\n");
+ rdp.copy_ci_index = rdp.main_ci_index;
+ }
+ }
+ rdp.ci_count = 0;
+ if (settings.hacks&hack_Banjo2)
+ rdp.cur_tex_buf = 0;
+ rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index];
+ // rdp.scale_x = rdp.scale_x_bak;
+ // rdp.scale_y = rdp.scale_y_bak;
+ LRDP("DetectFrameBufferUsage End\n");
+}
+
+/*******************************************
+ * ProcessRDPList *
+ *******************************************
+ * based on sources of ziggy's z64 *
+ *******************************************/
+
+static wxUint32 rdp_cmd_ptr = 0;
+static wxUint32 rdp_cmd_cur = 0;
+static wxUint32 rdp_cmd_data[0x1000];
+
+void lle_triangle(wxUint32 w1, wxUint32 w2, int shade, int texture, int zbuffer,
+ wxUint32 * rdp_cmd)
+{
+ rdp.cur_tile = (w1 >> 16) & 0x7;
+ int j;
+ int xleft, xright, xleft_inc, xright_inc;
+ int r, g, b, a, z, s, t, w;
+ int drdx = 0, dgdx = 0, dbdx = 0, dadx = 0, dzdx = 0, dsdx = 0, dtdx = 0, dwdx = 0;
+ int drde = 0, dgde = 0, dbde = 0, dade = 0, dzde = 0, dsde = 0, dtde = 0, dwde = 0;
+ int flip = (w1 & 0x800000) ? 1 : 0;
+
+ wxInt32 yl, ym, yh;
+ wxInt32 xl, xm, xh;
+ wxInt32 dxldy, dxhdy, dxmdy;
+ wxUint32 w3, w4, w5, w6, w7, w8;
+
+ wxUint32 * shade_base = rdp_cmd + 8;
+ wxUint32 * texture_base = rdp_cmd + 8;
+ wxUint32 * zbuffer_base = rdp_cmd + 8;
+
+ if (shade)
+ {
+ texture_base += 16;
+ zbuffer_base += 16;
+ }
+ if (texture)
+ {
+ zbuffer_base += 16;
+ }
+
+ w3 = rdp_cmd[2];
+ w4 = rdp_cmd[3];
+ w5 = rdp_cmd[4];
+ w6 = rdp_cmd[5];
+ w7 = rdp_cmd[6];
+ w8 = rdp_cmd[7];
+
+ yl = (w1 & 0x3fff);
+ ym = ((w2 >> 16) & 0x3fff);
+ yh = ((w2 >> 0) & 0x3fff);
+ xl = (wxInt32)(w3);
+ xh = (wxInt32)(w5);
+ xm = (wxInt32)(w7);
+ dxldy = (wxInt32)(w4);
+ dxhdy = (wxInt32)(w6);
+ dxmdy = (wxInt32)(w8);
+
+ if (yl & (0x800<<2)) yl |= 0xfffff000<<2;
+ if (ym & (0x800<<2)) ym |= 0xfffff000<<2;
+ if (yh & (0x800<<2)) yh |= 0xfffff000<<2;
+
+ yh &= ~3;
+
+ r = 0xff; g = 0xff; b = 0xff; a = 0xff; z = 0xffff0000; s = 0; t = 0; w = 0x30000;
+
+ if (shade)
+ {
+ r = (shade_base[0] & 0xffff0000) | ((shade_base[+4 ] >> 16) & 0x0000ffff);
+ g = ((shade_base[0 ] << 16) & 0xffff0000) | (shade_base[4 ] & 0x0000ffff);
+ b = (shade_base[1 ] & 0xffff0000) | ((shade_base[5 ] >> 16) & 0x0000ffff);
+ a = ((shade_base[1 ] << 16) & 0xffff0000) | (shade_base[5 ] & 0x0000ffff);
+ drdx = (shade_base[2 ] & 0xffff0000) | ((shade_base[6 ] >> 16) & 0x0000ffff);
+ dgdx = ((shade_base[2 ] << 16) & 0xffff0000) | (shade_base[6 ] & 0x0000ffff);
+ dbdx = (shade_base[3 ] & 0xffff0000) | ((shade_base[7 ] >> 16) & 0x0000ffff);
+ dadx = ((shade_base[3 ] << 16) & 0xffff0000) | (shade_base[7 ] & 0x0000ffff);
+ drde = (shade_base[8 ] & 0xffff0000) | ((shade_base[12] >> 16) & 0x0000ffff);
+ dgde = ((shade_base[8 ] << 16) & 0xffff0000) | (shade_base[12] & 0x0000ffff);
+ dbde = (shade_base[9 ] & 0xffff0000) | ((shade_base[13] >> 16) & 0x0000ffff);
+ dade = ((shade_base[9 ] << 16) & 0xffff0000) | (shade_base[13] & 0x0000ffff);
+ }
+ if (texture)
+ {
+ s = (texture_base[0 ] & 0xffff0000) | ((texture_base[4 ] >> 16) & 0x0000ffff);
+ t = ((texture_base[0 ] << 16) & 0xffff0000) | (texture_base[4 ] & 0x0000ffff);
+ w = (texture_base[1 ] & 0xffff0000) | ((texture_base[5 ] >> 16) & 0x0000ffff);
+ // w = abs(w);
+ dsdx = (texture_base[2 ] & 0xffff0000) | ((texture_base[6 ] >> 16) & 0x0000ffff);
+ dtdx = ((texture_base[2 ] << 16) & 0xffff0000) | (texture_base[6 ] & 0x0000ffff);
+ dwdx = (texture_base[3 ] & 0xffff0000) | ((texture_base[7 ] >> 16) & 0x0000ffff);
+ dsde = (texture_base[8 ] & 0xffff0000) | ((texture_base[12] >> 16) & 0x0000ffff);
+ dtde = ((texture_base[8 ] << 16) & 0xffff0000) | (texture_base[12] & 0x0000ffff);
+ dwde = (texture_base[9 ] & 0xffff0000) | ((texture_base[13] >> 16) & 0x0000ffff);
+ }
+ if (zbuffer)
+ {
+ z = zbuffer_base[0];
+ dzdx = zbuffer_base[1];
+ dzde = zbuffer_base[2];
+ }
+
+ xh <<= 2; xm <<= 2; xl <<= 2;
+ r <<= 2; g <<= 2; b <<= 2; a <<= 2;
+ dsde >>= 2; dtde >>= 2; dsdx >>= 2; dtdx >>= 2;
+ dzdx >>= 2; dzde >>= 2;
+ dwdx >>= 2; dwde >>= 2;
+
+#define XSCALE(x) (float(x)/(1<<18))
+#define YSCALE(y) (float(y)/(1<<2))
+#define ZSCALE(z) ((rdp.zsrc == 1)? float(rdp.prim_depth) : float(wxUint32(z))/0xffff0000)
+ //#define WSCALE(w) (rdp.Persp_en? (float(wxUint32(w) + 0x10000)/0xffff0000) : 1.0f)
+ //#define WSCALE(w) (rdp.Persp_en? 4294901760.0/(w + 65536) : 1.0f)
+#define WSCALE(w) (rdp.Persp_en? 65536.0f/float((w+ 0xffff)>>16) : 1.0f)
+#define CSCALE(c) (((c)>0x3ff0000? 0x3ff0000:((c)<0? 0 : (c)))>>18)
+#define _PERSP(w) ( w )
+#define PERSP(s, w) ( ((int64_t)(s) << 20) / (_PERSP(w)? _PERSP(w):1) )
+#define SSCALE(s, _w) (rdp.Persp_en? float(PERSP(s, _w))/(1 << 10) : float(s)/(1<<21))
+#define TSCALE(s, w) (rdp.Persp_en? float(PERSP(s, w))/(1 << 10) : float(s)/(1<<21))
+
+ int nbVtxs = 0;
+ VERTEX vtxbuf[12];
+ VERTEX * vtx = &vtxbuf[nbVtxs++];
+
+ xleft = xm;
+ xright = xh;
+ xleft_inc = dxmdy;
+ xright_inc = dxhdy;
+
+ while (yh<ym &&
+ !((!flip && xleft < xright+0x10000) ||
+ (flip && xleft > xright-0x10000))) {
+ xleft += xleft_inc;
+ xright += xright_inc;
+ s += dsde; t += dtde; w += dwde;
+ r += drde; g += dgde; b += dbde; a += dade;
+ z += dzde;
+ yh++;
+ }
+
+ j = ym-yh;
+ if (j > 0)
+ {
+ int dx = (xleft-xright)>>16;
+ if ((!flip && xleft < xright) ||
+ (flip/* && xleft > xright*/))
+ {
+ if (shade) {
+ vtx->r = CSCALE(r+drdx*dx);
+ vtx->g = CSCALE(g+dgdx*dx);
+ vtx->b = CSCALE(b+dbdx*dx);
+ vtx->a = CSCALE(a+dadx*dx);
+ }
+ if (texture) {
+ vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx);
+ vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx);
+ }
+ vtx->x = XSCALE(xleft);
+ vtx->y = YSCALE(yh);
+ vtx->z = ZSCALE(z+dzdx*dx);
+ vtx->w = WSCALE(w+dwdx*dx);
+ vtx = &vtxbuf[nbVtxs++];
+ }
+ if ((!flip/* && xleft < xright*/) ||
+ (flip && xleft > xright))
+ {
+ if (shade) {
+ vtx->r = CSCALE(r);
+ vtx->g = CSCALE(g);
+ vtx->b = CSCALE(b);
+ vtx->a = CSCALE(a);
+ }
+ if (texture) {
+ vtx->ou = SSCALE(s, w);
+ vtx->ov = TSCALE(t, w);
+ }
+ vtx->x = XSCALE(xright);
+ vtx->y = YSCALE(yh);
+ vtx->z = ZSCALE(z);
+ vtx->w = WSCALE(w);
+ vtx = &vtxbuf[nbVtxs++];
+ }
+ xleft += xleft_inc*j; xright += xright_inc*j;
+ s += dsde*j; t += dtde*j;
+ if (w + dwde*j) w += dwde*j;
+ else w += dwde*(j-1);
+ r += drde*j; g += dgde*j; b += dbde*j; a += dade*j;
+ z += dzde*j;
+ // render ...
+ }
+
+ if (xl != xh)
+ xleft = xl;
+
+ //if (yl-ym > 0)
+ {
+ int dx = (xleft-xright)>>16;
+ if ((!flip && xleft <= xright) ||
+ (flip/* && xleft >= xright*/))
+ {
+ if (shade) {
+ vtx->r = CSCALE(r+drdx*dx);
+ vtx->g = CSCALE(g+dgdx*dx);
+ vtx->b = CSCALE(b+dbdx*dx);
+ vtx->a = CSCALE(a+dadx*dx);
+ }
+ if (texture) {
+ vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx);
+ vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx);
+ }
+ vtx->x = XSCALE(xleft);
+ vtx->y = YSCALE(ym);
+ vtx->z = ZSCALE(z+dzdx*dx);
+ vtx->w = WSCALE(w+dwdx*dx);
+ vtx = &vtxbuf[nbVtxs++];
+ }
+ if ((!flip/* && xleft <= xright*/) ||
+ (flip && xleft >= xright))
+ {
+ if (shade) {
+ vtx->r = CSCALE(r);
+ vtx->g = CSCALE(g);
+ vtx->b = CSCALE(b);
+ vtx->a = CSCALE(a);
+ }
+ if (texture) {
+ vtx->ou = SSCALE(s, w);
+ vtx->ov = TSCALE(t, w);
+ }
+ vtx->x = XSCALE(xright);
+ vtx->y = YSCALE(ym);
+ vtx->z = ZSCALE(z);
+ vtx->w = WSCALE(w);
+ vtx = &vtxbuf[nbVtxs++];
+ }
+ }
+ xleft_inc = dxldy;
+ xright_inc = dxhdy;
+
+ j = yl-ym;
+ //j--; // ?
+ xleft += xleft_inc*j; xright += xright_inc*j;
+ s += dsde*j; t += dtde*j; w += dwde*j;
+ r += drde*j; g += dgde*j; b += dbde*j; a += dade*j;
+ z += dzde*j;
+
+ while (yl>ym &&
+ !((!flip && xleft < xright+0x10000) ||
+ (flip && xleft > xright-0x10000))) {
+ xleft -= xleft_inc; xright -= xright_inc;
+ s -= dsde; t -= dtde; w -= dwde;
+ r -= drde; g -= dgde; b -= dbde; a -= dade;
+ z -= dzde;
+ j--;
+ yl--;
+ }
+
+ // render ...
+ if (j >= 0) {
+ int dx = (xleft-xright)>>16;
+ if ((!flip && xleft <= xright) ||
+ (flip/* && xleft >= xright*/))
+ {
+ if (shade) {
+ vtx->r = CSCALE(r+drdx*dx);
+ vtx->g = CSCALE(g+dgdx*dx);
+ vtx->b = CSCALE(b+dbdx*dx);
+ vtx->a = CSCALE(a+dadx*dx);
+ }
+ if (texture) {
+ vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx);
+ vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx);
+ }
+ vtx->x = XSCALE(xleft);
+ vtx->y = YSCALE(yl);
+ vtx->z = ZSCALE(z+dzdx*dx);
+ vtx->w = WSCALE(w+dwdx*dx);
+ vtx = &vtxbuf[nbVtxs++];
+ }
+ if ((!flip/* && xleft <= xright*/) ||
+ (flip && xleft >= xright))
+ {
+ if (shade) {
+ vtx->r = CSCALE(r);
+ vtx->g = CSCALE(g);
+ vtx->b = CSCALE(b);
+ vtx->a = CSCALE(a);
+ }
+ if (texture) {
+ vtx->ou = SSCALE(s, w);
+ vtx->ov = TSCALE(t, w);
+ }
+ vtx->x = XSCALE(xright);
+ vtx->y = YSCALE(yl);
+ vtx->z = ZSCALE(z);
+ vtx->w = WSCALE(w);
+ vtx = &vtxbuf[nbVtxs++];
+ }
+ }
+
+ if (fullscreen)
+ {
+ update ();
+ for (int k = 0; k < nbVtxs-1; k++)
+ {
+ VERTEX * v = &vtxbuf[k];
+ v->x = v->x * rdp.scale_x + rdp.offset_x;
+ v->y = v->y * rdp.scale_y + rdp.offset_y;
+ // v->z = 1.0f;///v->w;
+ v->q = 1.0f/v->w;
+ v->u1 = v->u0 = v->ou;
+ v->v1 = v->v0 = v->ov;
+ if (rdp.tex >= 1 && rdp.cur_cache[0])
+ {
+ if (rdp.tiles[rdp.cur_tile].shift_s)
+ {
+ if (rdp.tiles[rdp.cur_tile].shift_s > 10)
+ v->u0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s));
+ else
+ v->u0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_s);
+ }
+ if (rdp.tiles[rdp.cur_tile].shift_t)
+ {
+ if (rdp.tiles[rdp.cur_tile].shift_t > 10)
+ v->v0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t));
+ else
+ v->v0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_t);
+ }
+
+ v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;
+ v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t;
+ v->u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * v->u0;
+ v->v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * v->v0;
+ v->u0 /= v->w;
+ v->v0 /= v->w;
+ }
+
+ if (rdp.tex >= 2 && rdp.cur_cache[1])
+ {
+ if (rdp.tiles[rdp.cur_tile+1].shift_s)
+ {
+ if (rdp.tiles[rdp.cur_tile+1].shift_s > 10)
+ v->u1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s));
+ else
+ v->u1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_s);
+ }
+ if (rdp.tiles[rdp.cur_tile+1].shift_t)
+ {
+ if (rdp.tiles[rdp.cur_tile+1].shift_t > 10)
+ v->v1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t));
+ else
+ v->v1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_t);
+ }
+
+ v->u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s;
+ v->v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t;
+ v->u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * v->u1;
+ v->v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * v->v1;
+ v->u1 /= v->w;
+ v->v1 /= v->w;
+ }
+ apply_shade_mods (v);
+ }
+ ConvertCoordsConvert (vtxbuf, nbVtxs);
+ grCullMode (GR_CULL_DISABLE);
+ grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, nbVtxs-1, vtxbuf, sizeof(VERTEX));
+ if (_debugger.capture)
+ {
+ VERTEX vl[3];
+ vl[0] = vtxbuf[0];
+ vl[1] = vtxbuf[2];
+ vl[2] = vtxbuf[1];
+ add_tri (vl, 3, TRI_TRIANGLE);
+ rdp.tri_n++;
+ if (nbVtxs > 4)
+ {
+ vl[0] = vtxbuf[2];
+ vl[1] = vtxbuf[3];
+ vl[2] = vtxbuf[1];
+ add_tri (vl, 3, TRI_TRIANGLE);
+ rdp.tri_n++;
+ }
+ }
+ }
+}
+
+static void rdp_triangle(int shade, int texture, int zbuffer)
+{
+ lle_triangle(rdp.cmd0, rdp.cmd1, shade, texture, zbuffer, rdp_cmd_data + rdp_cmd_cur);
+}
+
+static void rdp_trifill()
+{
+ rdp_triangle(0, 0, 0);
+ LRDP("trifill\n");
+}
+
+static void rdp_trishade()
+{
+ rdp_triangle(1, 0, 0);
+ LRDP("trishade\n");
+}
+
+static void rdp_tritxtr()
+{
+ rdp_triangle(0, 1, 0);
+ LRDP("tritxtr\n");
+}
+
+static void rdp_trishadetxtr()
+{
+ rdp_triangle(1, 1, 0);
+ LRDP("trishadetxtr\n");
+}
+
+static void rdp_trifillz()
+{
+ rdp_triangle(0, 0, 1);
+ LRDP("trifillz\n");
+}
+
+static void rdp_trishadez()
+{
+ rdp_triangle(1, 0, 1);
+ LRDP("trishadez\n");
+}
+
+static void rdp_tritxtrz()
+{
+ rdp_triangle(0, 1, 1);
+ LRDP("tritxtrz\n");
+}
+
+static void rdp_trishadetxtrz()
+{
+ rdp_triangle(1, 1, 1);
+ LRDP("trishadetxtrz\n");
+}
+
+
+static rdp_instr rdp_command_table[64] =
+{
+ /* 0x00 */
+ spnoop, undef, undef, undef,
+ undef, undef, undef, undef,
+ rdp_trifill, rdp_trifillz, rdp_tritxtr, rdp_tritxtrz,
+ rdp_trishade, rdp_trishadez, rdp_trishadetxtr, rdp_trishadetxtrz,
+ /* 0x10 */
+ undef, undef, undef, undef,
+ undef, undef, undef, undef,
+ undef, undef, undef, undef,
+ undef, undef, undef, undef,
+ /* 0x20 */
+ undef, undef, undef, undef,
+ rdp_texrect, rdp_texrect, rdp_loadsync, rdp_pipesync,
+ rdp_tilesync, rdp_fullsync, rdp_setkeygb, rdp_setkeyr,
+ rdp_setconvert, rdp_setscissor, rdp_setprimdepth, rdp_setothermode,
+ /* 0x30 */
+ rdp_loadtlut, undef, rdp_settilesize, rdp_loadblock,
+ rdp_loadtile, rdp_settile, rdp_fillrect, rdp_setfillcolor,
+ rdp_setfogcolor, rdp_setblendcolor, rdp_setprimcolor, rdp_setenvcolor,
+ rdp_setcombine, rdp_settextureimage, rdp_setdepthimage, rdp_setcolorimage
+};
+
+static const wxUint32 rdp_command_length[64] =
+{
+ 8, // 0x00, No Op
+ 8, // 0x01, ???
+ 8, // 0x02, ???
+ 8, // 0x03, ???
+ 8, // 0x04, ???
+ 8, // 0x05, ???
+ 8, // 0x06, ???
+ 8, // 0x07, ???
+ 32, // 0x08, Non-Shaded Triangle
+ 32+16, // 0x09, Non-Shaded, Z-Buffered Triangle
+ 32+64, // 0x0a, Textured Triangle
+ 32+64+16, // 0x0b, Textured, Z-Buffered Triangle
+ 32+64, // 0x0c, Shaded Triangle
+ 32+64+16, // 0x0d, Shaded, Z-Buffered Triangle
+ 32+64+64, // 0x0e, Shaded+Textured Triangle
+ 32+64+64+16,// 0x0f, Shaded+Textured, Z-Buffered Triangle
+ 8, // 0x10, ???
+ 8, // 0x11, ???
+ 8, // 0x12, ???
+ 8, // 0x13, ???
+ 8, // 0x14, ???
+ 8, // 0x15, ???
+ 8, // 0x16, ???
+ 8, // 0x17, ???
+ 8, // 0x18, ???
+ 8, // 0x19, ???
+ 8, // 0x1a, ???
+ 8, // 0x1b, ???
+ 8, // 0x1c, ???
+ 8, // 0x1d, ???
+ 8, // 0x1e, ???
+ 8, // 0x1f, ???
+ 8, // 0x20, ???
+ 8, // 0x21, ???
+ 8, // 0x22, ???
+ 8, // 0x23, ???
+ 16, // 0x24, Texture_Rectangle
+ 16, // 0x25, Texture_Rectangle_Flip
+ 8, // 0x26, Sync_Load
+ 8, // 0x27, Sync_Pipe
+ 8, // 0x28, Sync_Tile
+ 8, // 0x29, Sync_Full
+ 8, // 0x2a, Set_Key_GB
+ 8, // 0x2b, Set_Key_R
+ 8, // 0x2c, Set_Convert
+ 8, // 0x2d, Set_Scissor
+ 8, // 0x2e, Set_Prim_Depth
+ 8, // 0x2f, Set_Other_Modes
+ 8, // 0x30, Load_TLUT
+ 8, // 0x31, ???
+ 8, // 0x32, Set_Tile_Size
+ 8, // 0x33, Load_Block
+ 8, // 0x34, Load_Tile
+ 8, // 0x35, Set_Tile
+ 8, // 0x36, Fill_Rectangle
+ 8, // 0x37, Set_Fill_Color
+ 8, // 0x38, Set_Fog_Color
+ 8, // 0x39, Set_Blend_Color
+ 8, // 0x3a, Set_Prim_Color
+ 8, // 0x3b, Set_Env_Color
+ 8, // 0x3c, Set_Combine
+ 8, // 0x3d, Set_Texture_Image
+ 8, // 0x3e, Set_Mask_Image
+ 8 // 0x3f, Set_Color_Image
+};
+
+#define rdram ((wxUint32*)gfx.RDRAM)
+#define rsp_dmem ((wxUint32*)gfx.DMEM)
+
+#define dp_start (*(wxUint32*)gfx.DPC_START_REG)
+#define dp_end (*(wxUint32*)gfx.DPC_END_REG)
+#define dp_current (*(wxUint32*)gfx.DPC_CURRENT_REG)
+#define dp_status (*(wxUint32*)gfx.DPC_STATUS_REG)
+
+inline wxUint32 READ_RDP_DATA(wxUint32 address)
+{
+ if (dp_status & 0x1) // XBUS_DMEM_DMA enabled
+ return rsp_dmem[(address & 0xfff)>>2];
+ else
+ return rdram[address>>2];
+}
+
+static void rdphalf_1()
+{
+ wxUint32 cmd = rdp.cmd1 >> 24;
+ if (cmd >= 0xc8 && cmd <=0xcf) //triangle command
+ {
+ LRDP("rdphalf_1 - lle triangle\n");
+ rdp_cmd_ptr = 0;
+ rdp_cmd_cur = 0;
+ wxUint32 a;
+
+ do
+ {
+ rdp_cmd_data[rdp_cmd_ptr++] = rdp.cmd1;
+ // check DL counter
+ if (rdp.dl_count != -1)
+ {
+ rdp.dl_count --;
+ if (rdp.dl_count == 0)
+ {
+ rdp.dl_count = -1;
+
+ LRDP("End of DL\n");
+ rdp.pc_i --;
+ }
+ }
+
+ // Get the address of the next command
+ a = rdp.pc[rdp.pc_i] & BMASK;
+
+ // Load the next command and its input
+ rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit
+ rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // /
+
+ // Go to the next instruction
+ rdp.pc[rdp.pc_i] = (a+8) & BMASK;
+
+ }while ((rdp.cmd0 >> 24) != 0xb3);
+ rdp_cmd_data[rdp_cmd_ptr++] = rdp.cmd1;
+ cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f;
+ rdp.cmd0 = rdp_cmd_data[rdp_cmd_cur+0];
+ rdp.cmd1 = rdp_cmd_data[rdp_cmd_cur+1];
+ /*
+ wxUint32 cmd3 = ((wxUint32*)gfx.RDRAM)[(a>>2)+2];
+ if ((cmd3>>24) == 0xb4)
+ rglSingleTriangle = TRUE;
+ else
+ rglSingleTriangle = FALSE;
+ */
+ rdp_command_table[cmd]();
+ }
+ else
+ {
+ LRDP("rdphalf_1 - IGNORED\n");
+ }
+}
+
+static void rdphalf_2()
+{
+ RDP_E("rdphalf_2 - IGNORED\n");
+ LRDP("rdphalf_2 - IGNORED\n");
+}
+
+static void rdphalf_cont()
+{
+ RDP_E("rdphalf_cont - IGNORED\n");
+ LRDP("rdphalf_cont - IGNORED\n");
+}
+
+/******************************************************************
+Function: ProcessRDPList
+Purpose: This function is called when there is a Dlist to be
+processed. (Low level GFX list)
+input: none
+output: none
+*******************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+EXPORT void CALL ProcessRDPList(void)
+{
+ LOG ("ProcessRDPList ()\n");
+ LRDP("ProcessRDPList ()\n");
+
+ // SoftLocker lock(mutexProcessDList);
+ if (/*!lock.IsOk()*/0) //mutex is busy
+ {
+ if (!fullscreen)
+ drawNoFullscreenMessage();
+ // Set an interrupt to allow the game to continue
+ *gfx.MI_INTR_REG |= 0x20;
+ gfx.CheckInterrupts();
+ return;
+ }
+
+ wxUint32 i;
+ wxUint32 cmd, length, cmd_length;
+ rdp_cmd_ptr = 0;
+ rdp_cmd_cur = 0;
+
+ if (dp_end <= dp_current) return;
+ length = dp_end - dp_current;
+
+ // load command data
+ for (i=0; i < length; i += 4)
+ {
+ rdp_cmd_data[rdp_cmd_ptr++] = READ_RDP_DATA(dp_current + i);
+ if (rdp_cmd_ptr >= 0x1000)
+ {
+ FRDP("rdp_process_list: rdp_cmd_ptr overflow %x %x --> %x\n", length, dp_current, dp_end);
+ }
+ }
+
+ dp_current = dp_end;
+
+ cmd = (rdp_cmd_data[0] >> 24) & 0x3f;
+ cmd_length = (rdp_cmd_ptr + 1) * 4;
+
+ // check if more data is needed
+ if (cmd_length < rdp_command_length[cmd])
+ return;
+ rdp.LLE = TRUE;
+ while (rdp_cmd_cur < rdp_cmd_ptr)
+ {
+ cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f;
+
+ if (((rdp_cmd_ptr-rdp_cmd_cur) * 4) < rdp_command_length[cmd])
+ return;
+
+ // execute the command
+ rdp.cmd0 = rdp_cmd_data[rdp_cmd_cur+0];
+ rdp.cmd1 = rdp_cmd_data[rdp_cmd_cur+1];
+ rdp.cmd2 = rdp_cmd_data[rdp_cmd_cur+2];
+ rdp.cmd3 = rdp_cmd_data[rdp_cmd_cur+3];
+ rdp_command_table[cmd]();
+
+ rdp_cmd_cur += rdp_command_length[cmd] / 4;
+ };
+ rdp.LLE = FALSE;
+
+ dp_start = dp_end;
+
+ dp_status &= ~0x0002;
+
+ //}
+}
+
+#ifdef __cplusplus
+}
+#endif
+