diff --git a/BizHawk.MultiClient/output/dll/mupen64plus-video-glide64.dll b/BizHawk.MultiClient/output/dll/mupen64plus-video-glide64.dll index a78e6cb555..b1ad1499bd 100644 Binary files a/BizHawk.MultiClient/output/dll/mupen64plus-video-glide64.dll and b/BizHawk.MultiClient/output/dll/mupen64plus-video-glide64.dll differ diff --git a/libmupen64plus/mupen64plus-video-glide64/src/rdp.cpp b/libmupen64plus/mupen64plus-video-glide64/src/rdp.cpp index 335cd1acf3..45a2cd8562 100644 --- a/libmupen64plus/mupen64plus-video-glide64/src/rdp.cpp +++ b/libmupen64plus/mupen64plus-video-glide64/src/rdp.cpp @@ -1,3860 +1,4020 @@ -/* -* Glide64 - Glide video plugin for Nintendo 64 emulators. -* Copyright (c) 2002 Dave2001 -* Copyright (c) 2008 Günther -* -* 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 -* Licence along with this program; if not, write to the Free -* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -* Boston, MA 02110-1301, USA -*/ - -//**************************************************************** -// -// Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) -// Project started on December 29th, 2001 -// -// 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. -// -// Official Glide64 development channel: #Glide64 on EFnet -// -// Original author: Dave2001 (Dave2999@hotmail.com) -// Other authors: Gonetz, Gugaman -// -//**************************************************************** - -#define M64P_PLUGIN_PROTOTYPES 1 -#include "m64p_types.h" -#include "m64p_plugin.h" -#include "m64p_config.h" -#include "m64p_vidext.h" -#include "3dmath.h" -#include "Util.h" -#include "Debugger.h" -#include "Combine.h" -#include "Util.h" -#include "Ini.h" -#include "Config.h" -#include "Tmem.h" -#include "TexCache.h" -#include "TexCache.h" -#include "TexBuffer.h" -#include "CRC.h" -#include "rdp.h" - -#ifndef _WIN32 -#include -#endif // _WIN32 - -char out_buf[2048]; - -DWORD frame_count; // frame counter - -BOOL ucode_error_report = TRUE; -int wrong_tile = -1; - -int drawFlag = 1; // draw flag for rendering callback - -#if defined(__GNUC__) - #define bswap32(x) __builtin_bswap32(x) -#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) - #include - #define bswap32(x) _byteswap_ulong(x) -#else -static inline uint32_t bswap32(uint32_t val) -{ - return (((val & 0xff000000) >> 24) | - ((val & 0x00ff0000) >> 8) | - ((val & 0x0000ff00) << 8) | - ((val & 0x000000ff) << 24)); -} -#endif - -// global strings -const char *ACmp[4] = { "NONE", "THRESHOLD", "UNKNOWN", "DITHER" }; - -const char *Mode0[16] = { "COMBINED", "TEXEL0", - "TEXEL1", "PRIMITIVE", - "SHADE", "ENVIORNMENT", - "1", "NOISE", - "0", "0", - "0", "0", - "0", "0", - "0", "0" }; -const char *Mode1[16] = { "COMBINED", "TEXEL0", - "TEXEL1", "PRIMITIVE", - "SHADE", "ENVIORNMENT", - "CENTER", "K4", - "0", "0", - "0", "0", - "0", "0", - "0", "0" }; -const char *Mode2[32] = { "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[8] = { "COMBINED", "TEXEL0", - "TEXEL1", "PRIMITIVE", - "SHADE", "ENVIORNMENT", - "1", "0" }; - -const char *Alpha0[8] = { "COMBINED", "TEXEL0", - "TEXEL1", "PRIMITIVE", - "SHADE", "ENVIORNMENT", - "1", "0" }; -const char *Alpha2[8] = { "LOD_FRACTION", "TEXEL0", - "TEXEL1", "PRIMITIVE", - "SHADE", "ENVIORNMENT", - "PRIM_LODFRAC", "0" }; - -//FIXME:unused? -//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[2] = { "G_ZS_PIXEL", "G_ZS_PRIM" }; - -const char *str_yn[2] = { "NO", "YES" }; -const char *str_offon[2] = { "OFF", "ON" }; - -const char *str_cull[4] = { "DISABLE", "FRONT", "BACK", "BOTH" }; - -// I=intensity probably -const char *str_format[8] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" }; -const char *str_size[4] = { "4bit", "8bit", "16bit", "32bit" }; -const char *str_cm[4] = { "WRAP/NO CLAMP", "MIRROR/NO CLAMP", "WRAP/CLAMP", "MIRROR/CLAMP" }; - -//const char *str_lod[] = { "1", "2", "4", "8", "16", "32", "64", "128", "256" }; -//const char *str_aspect[] = { "1x8", "1x4", "1x2", "1x1", "2x1", "4x1", "8x1" }; - -const char *str_filter[3] = { "Point Sampled", "Average (box)", "Bilinear" }; - -const char *str_tlut[4] = { "TT_NONE", "TT_UNKNOWN", "TT_RGBA_16", "TT_IA_16" }; - -const char *CIStatus[10] = { "ci_main", "ci_zimg", "ci_unknown", "ci_useless", - "ci_old_copy", "ci_copy", "ci_copy_self", - "ci_zcopy", "ci_aux", "ci_aux_copy" }; - - -// ZIGGY -// depth save/restore variables -// 0 : normal mode -// 1 : writing in normal depth buffer -// 2 : writing in alternate depth buffer -static int render_depth_mode; - -// ** 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 rsp_reserved0(); -static void rsp_reserved1(); -static void rsp_reserved2(); -static void rsp_reserved3(); - -static void ys_memrect(); - -BYTE microcode[4096]; -DWORD uc_crc; -void microcheck (); - -// ** 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 "ucode.h" - -static BOOL reset = 0; -static int old_ucode = -1; - -// rdp_reset - resets the RDP_E -void rdp_reset () -{ - reset = 1; - - rdp.model_i = 0; - - rdp.n_cached[0] = 0; - rdp.n_cached[1] = 0; - rdp.cur_cache[0] = NULL; - rdp.cur_cache[1] = NULL; - /* - rdp.tmem_ptr[0] = offset_textures; - rdp.tmem_ptr[1] = offset_textures; - if (grTextureBufferExt) - rdp.tmem_ptr[1] = TEXMEM_2MB_EDGE * 2; - */ - rdp.c_a0 = 0; - rdp.c_b0 = 0; - rdp.c_c0 = 0; - rdp.c_d0 = 0; - rdp.c_Aa0 = 0; - rdp.c_Ab0 = 0; - rdp.c_Ac0 = 0; - rdp.c_Ad0 = 0; - - rdp.c_a1 = 0; - rdp.c_b1 = 0; - rdp.c_c1 = 0; - rdp.c_d1 = 0; - rdp.c_Aa1 = 0; - rdp.c_Ab1 = 0; - rdp.c_Ac1 = 0; - rdp.c_Ad1 = 0; - - // Clear the palette CRC - int i; - for (i=0; i<16; i++) - rdp.pal_8_crc[i] = 0; - - // Clear the palettes - for (i=0; i<256; i++) - rdp.pal_8[i] = 0; - - rdp.tlut_mode = 0; - - // Clear all segments ** VERY IMPORTANT FOR ZELDA ** - for (i=0; i<16; i++) - rdp.segment[i] = 0; - - for (i=0; i<512; i++) - rdp.addr[i] = 0; - - // set all vertex numbers - for (i=0; i>2; i++) - { - uc_crc += ((DWORD*)microcode)[i]; - } - - FRDP_E ("crc: %08lx\n", uc_crc); - -#ifdef LOG_UCODE - std::ofstream ucf; - ucf.open ("ucode.txt", ios::out | ios::binary); - char d; - for (i=0; i<0x400000; i++) - { - d = ((char*)gfx.RDRAM)[i^3]; - ucf.write (&d, 1); - } - ucf.close (); -#endif - - char str[9]; - sprintf (str, "%08lx", (unsigned long)uc_crc); - - INI_Open (); - INI_FindSection ("UCODE"); - FRDP("ucode = %s\n", str); - int uc = INI_ReadInt (str, -2, 0); - WriteLog(M64MSG_INFO, "ucode = %d\n", uc); - if (uc == -2 && ucode_error_report) - { - Config_Open(); - settings.ucode = Config_ReadInt ("ucode", "Force microcode", 0, FALSE, FALSE); - - ReleaseGfx (); - WriteLog(M64MSG_ERROR, "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) - { - Config_Open(); - settings.ucode = Config_ReadInt ("ucode", "Force microcode", 0, FALSE, FALSE); - - ReleaseGfx (); - WriteLog(M64MSG_ERROR, "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); - } -} - -void drawNoFullscreenMessage() -{ - LOG ("drawNoFullscreenMessage ()\n"); -} - -static WORD yuv_to_rgb(BYTE y, BYTE u, BYTE v) -{ - float r = y + (1.370705f * (v-128)); - float g = y - (0.698001f * (v-128)) - (0.337633f * (u-128)); - float b = y + (1.732446f * (u-128)); - r *= 0.125f; - g *= 0.125f; - b *= 0.125f; - //clipping the result - if (r > 32) r = 32; - if (g > 32) g = 32; - if (b > 32) b = 32; - if (r < 0) r = 0; - if (g < 0) g = 0; - if (b < 0) b = 0; - - WORD c = (WORD)(((WORD)(r) << 11) | - ((WORD)(g) << 6) | - ((WORD)(b) << 1) | 1); - return c; -} - -static void DrawYUVImageToFrameBuffer() -{ - WORD width = (WORD)(rdp.yuv_lr_x - rdp.yuv_ul_x); - WORD height = (WORD)(rdp.yuv_lr_y - rdp.yuv_ul_y); - DWORD * mb = (DWORD*)(gfx.RDRAM+rdp.yuv_im_begin); //pointer to the first macro block - WORD * cimg = (WORD*)(gfx.RDRAM+rdp.cimg); - //yuv macro block contains 16x16 texture. we need to put it in the proper place inside cimg - for (WORD y = 0; y < height; y+=16) - { - for (WORD x = 0; x < width; x+=16) - { - WORD *dst = cimg + x + y * rdp.ci_width; - for (WORD h = 0; h < 16; h++) - { - for (WORD w = 0; w < 8; w++) - { - DWORD t = *(mb++); //each DWORD contains 2 pixels - if ((x < rdp.ci_width) && (y < rdp.ci_height)) //clipping. texture image may be larger than color image - { - BYTE y0 = (BYTE)t&0xFF; - BYTE v = (BYTE)(t>>8)&0xFF; - BYTE y1 = (BYTE)(t>>16)&0xFF; - BYTE u = (BYTE)(t>>24)&0xFF; - *(dst++) = yuv_to_rgb(y0, u, v); - *(dst++) = yuv_to_rgb(y1, u, v); - } - } - dst += rdp.ci_width - 16; - } - mb += 64; //macro block is 768 bytes long, last 256 bytes are useless - } - } -} - -static DWORD d_ul_x, d_ul_y, d_lr_x, d_lr_y; - -typedef struct { - int ul_x, ul_y, lr_x, lr_y; -} FB_PART; - -static void DrawPart(int scr_ul_x, int scr_ul_y, int prt_ul_x, int prt_ul_y, int width, int height, float scale_x, float scale_y) -{ - WORD * dst = new WORD[width*height]; - DWORD shift = ((d_ul_y+prt_ul_y) * rdp.ci_width + d_ul_x + prt_ul_x) << 1; - WORD * src = (WORD*)(gfx.RDRAM+rdp.cimg+shift); - WORD c; - for (int y=0; y < height; y++) - { - for (int x=0; x < width; x++) - { - c = src[(int(x*scale_x)+int(y*scale_y)*rdp.ci_width)^1]; - dst[x+y*width] = c?((c >> 1) | 0x8000):0; - } - } - - grLfbWriteRegion(GR_BUFFER_BACKBUFFER, - scr_ul_x, - scr_ul_y, - GR_LFB_SRC_FMT_1555, - width, - height, - FXTRUE, - width<<1, - dst); - delete[] dst; -} - -static void DrawFrameBufferToScreen() -{ - FRDP("DrawFrameBufferToScreen. cimg: %08lx, ul_x: %d, uly: %d, lr_x: %d, lr_y: %d\n", rdp.cimg, d_ul_x, d_ul_y, d_lr_x, d_lr_y); - if (!fullscreen) - return; - grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, - GR_COMBINE_FACTOR_ONE, - GR_COMBINE_LOCAL_NONE, - GR_COMBINE_OTHER_TEXTURE, - FXFALSE); - grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, - GR_COMBINE_FACTOR_ONE, - GR_COMBINE_LOCAL_NONE, - GR_COMBINE_OTHER_TEXTURE, - FXFALSE); - grConstantColorValue (0xFFFFFFFF); - grAlphaBlendFunction( GR_BLEND_SRC_ALPHA, - GR_BLEND_ONE_MINUS_SRC_ALPHA, - GR_BLEND_ONE, - GR_BLEND_ZERO); - rdp.update |= UPDATE_COMBINE; - - float scale_x_dst = (float)settings.scr_res_x / rdp.vi_width;//(float)max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width); - float scale_y_dst = (float)settings.scr_res_y / rdp.vi_height;//(float)max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound); - float scale_x_src = (float)rdp.vi_width / (float)settings.scr_res_x;//(float)max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width); - float scale_y_src = (float)rdp.vi_height / (float)settings.scr_res_y;//(float)max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound); - int src_width = d_lr_x - d_ul_x + 1; - int src_height = d_lr_y - d_ul_y + 1; - int dst_width, dst_height, ul_x, ul_y; - - if (!settings.fb_optimize_write || ((src_width < 33) && (src_height < 33))) - { - dst_width = int(src_width*scale_x_dst); - dst_height = int(src_height*scale_y_dst); - ul_x = int(d_ul_x*scale_x_dst); - ul_y = int(d_ul_y*scale_y_dst); - DrawPart(ul_x, ul_y, 0, 0, dst_width, dst_height, scale_x_src, scale_y_src); - memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size); - return; - } - - FB_PART parts[8]; - int p; - for (p = 0; p < 8; p++) - { - parts[p].lr_x = parts[p].lr_y = 0; - parts[p].ul_x = parts[p].ul_y = 0xFFFF; - } - - int num_of_parts = 0; - int cur_part = 0; - int most_left = d_ul_x; - int most_right = d_lr_x; - DWORD shift = (d_ul_y * rdp.ci_width + d_ul_x) << 1; - WORD * src = (WORD*)(gfx.RDRAM+rdp.cimg+shift); - for (int h = 0; h < src_height; h++) - { - cur_part = 0; - int w = 0; - while (w < src_width) - { - while (w < src_width) - { - if (src[(w+h*rdp.ci_width)^1] == 0) - w++; - else - break; - } - if (w == src_width) - break; - if (num_of_parts == 0) //first part - { - parts[0].ul_x = w; - most_left = w; - parts[0].ul_y = h; - cur_part = 0; - } - else if (w < most_left - 2) //new part - { - parts[num_of_parts].ul_x = w; - most_left = w; - parts[num_of_parts].ul_y = h; - cur_part = num_of_parts; - num_of_parts++; - } - else if (w > most_right + 2) //new part - { - parts[num_of_parts].ul_x = w; - most_right = w; - parts[num_of_parts].ul_y = h; - cur_part = num_of_parts; - num_of_parts++; - } - else - { - for (p = 0; p < num_of_parts; p++) - { - if ((w > parts[p].ul_x - 2) && (w < parts[p].lr_x+2)) - { - if (w < parts[p].ul_x) parts[p].ul_x = w; - break; - } - } - cur_part = p; - } - while (w < src_width) - { - if (src[(w+h*rdp.ci_width)^1] != 0) - w++; - else - break; - } - if (num_of_parts == 0) //first part - { - parts[0].lr_x = w; - most_right = w; - num_of_parts++; - } - else - { - if (parts[cur_part].lr_x < w) parts[cur_part].lr_x = w; - if (most_right < w) most_right = w; - parts[cur_part].lr_y = h; - } - } - } - /* - for (p = 0; p < num_of_parts; p++) - { - FRDP("part#%d ul_x: %d, ul_y: %d, lr_x: %d, lr_y: %d\n", p, parts[p].ul_x, parts[p].ul_y, parts[p].lr_x, parts[p].lr_y); - } - */ - for (p = 0; p < num_of_parts; p++) - { - dst_width = int((parts[p].lr_x-parts[p].ul_x + 1)*scale_x_dst); - dst_height = int((parts[p].lr_y-parts[p].ul_y + 1)*scale_y_dst); - ul_x = int((d_ul_x+parts[p].ul_x)*scale_x_dst); - ul_y = int((d_ul_y+parts[p].ul_y)*scale_y_dst); - DrawPart(ul_x, ul_y, parts[p].ul_x, parts[p].ul_y, dst_width, dst_height, scale_x_src, scale_y_src); - } - memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size); -} - -#define RGBA16TO32(color) \ - ((color&1)?0xFF:0) | \ - ((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | \ - ((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | \ -((DWORD)((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. - - int width = rdp.ci_width;//*gfx.VI_WIDTH_REG; - int height; - if (settings.fb_smart && !settings.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.PPL) - height -= rdp.ci_upper_bound; - } - FRDP ("width: %d, height: %d... ", width, height); - - if (rdp.scale_x < 1.1f) - { - WORD * ptr_src = new WORD[width*height]; - if (grLfbReadRegion(buffer, - 0, - 0,//rdp.ci_upper_bound, - width, - height, - width<<1, - ptr_src)) - { - WORD *ptr_dst = (WORD*)(gfx.RDRAM+rdp.cimg); - DWORD *ptr_dst32 = (DWORD*)(gfx.RDRAM+rdp.cimg); - WORD c; - - for (int y=0; y 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); - } - } - /* - } - else //8bit I or CI - { - BYTE *ptr_dst = (BYTE*)(gfx.RDRAM+rdp.cimg); - WORD c; - - for (int y=0; y>5)&0x3F)/63.0f*85.0f); - BYTE r = (BYTE)((float)((c>>11)&0x1F)/31.0f*85.0f); - c = (c&0xFFC0) | ((c&0x001F) << 1) | 1; - // FRDP("src: %08lx, dst: %d\n",c,(BYTE)(r+g+b)); - ptr_dst[(x + y * width)^1] = (BYTE)(r+g+b); - // ptr_dst[(x + y * width)^1] = (BYTE)((c>>8)&0xFF); - } - } - } */ - RDP ("ReadRegion. Framebuffer copy complete.\n"); - } - else - { - RDP ("Framebuffer copy failed.\n"); - } - delete[] ptr_src; - } - else - { - if (rdp.motionblur && settings.fb_hires) - { - return; - } - else - { - float scale_x = (float)settings.scr_res_x / rdp.vi_width;//(float)max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width); - float scale_y = (float)settings.scr_res_y / rdp.vi_height;//(float)max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound); - - 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); - GrLfbInfo_t info; - info.size = sizeof(GrLfbInfo_t); - - - // VP 888 disconnected for now - if (1||rdp.ci_size <= 2) { - if (grLfbLock (GR_LFB_READ_ONLY, - buffer, - GR_LFBWRITEMODE_565, - GR_ORIGIN_UPPER_LEFT, - FXFALSE, - &info)) - { - WORD *ptr_src = (WORD*)info.lfbPtr; - WORD *ptr_dst = (WORD*)(gfx.RDRAM+rdp.cimg); - DWORD *ptr_dst32 = (DWORD*)(gfx.RDRAM+rdp.cimg); - WORD c; - DWORD stride = info.strideInBytes>>1; - - BOOL read_alpha = settings.fb_read_alpha; - if (settings.PM && rdp.frame_buffers[rdp.ci_count-1].status != ci_aux) - read_alpha = FALSE; - for (int y=0; y>1; - - for (int y=0; y 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, (*(DWORD*)(gfx.DMEM+0x0FE4))>>6); - if (rdp.model_stack_size == 0) - rdp.model_stack_size = 32; - 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; - fbreads_front = fbreads_back = 0; - rdp.fog_multiplier = rdp.fog_offset = 0; - rdp.zsrc = 0; - - if (cpu_fb_write == TRUE) - DrawFrameBufferToScreen(); - 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; - - //analize possible frame buffer usage - if (settings.fb_smart) - DetectFrameBufferUsage(); - if (!settings.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 - DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0); - DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4); - FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_lenght: %d\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length); - FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG); - - if (settings.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; - DWORD a; - - // catches exceptions so that it doesn't freeze -#ifdef CATCH_EXCEPTIONS - try { -#endif - - // 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 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit - rdp.cmd1 = ((DWORD*)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 - QueryPerformanceCounter ((LARGE_INTEGER*)&perf_cur); -#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; - - RDP ("End of DL\n"); - rdp.pc_i --; - } - } - -#ifdef PERFORMANCE - QueryPerformanceCounter ((LARGE_INTEGER*)&perf_next); - __int64 t = perf_next-perf_cur; - sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, t); - rdp_log << out_buf; -#endif - - } while (!rdp.halt); -#ifdef CATCH_EXCEPTIONS - } catch (...) { - - if (fullscreen) ReleaseGfx (); - WriteLog(M64MSG_ERROR, "The GFX plugin caused an exception and has been disabled."); - exception = TRUE; - } -#endif - - if (settings.fb_smart) - { - rdp.scale_x = rdp.scale_x_bak; - rdp.scale_y = rdp.scale_y_bak; - } - if (settings.fb_read_always) - { - CopyFrameBuffer (); - } - if (rdp.yuv_image) - { - DrawYUVImageToFrameBuffer(); - rdp.yuv_image = FALSE; -// FRDP("yuv image draw. ul_x: %f, ul_y: %f, lr_x: %f, lr_y: %f, begin: %08lx\n", -// rdp.yuv_ul_x, rdp.yuv_ul_y, rdp.yuv_lr_x, rdp.yuv_lr_y, rdp.yuv_im_begin); - rdp.yuv_ul_x = rdp.yuv_ul_y = rdp.yuv_lr_x = rdp.yuv_lr_y = 0; - rdp.yuv_im_begin = 0x00FFFFFF; - } - if (rdp.cur_image) - CloseTextureBuffer(rdp.read_whole_frame && (settings.PM || rdp.swap_ci_index >= 0)); - - if (settings.TGR2 && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET) - { - newSwapBuffers (); - CI_SET = FALSE; - } - RDP("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 _FINAL_RELEASE_ - *gfx.MI_INTR_REG |= 0x20; - gfx.CheckInterrupts(); - rdp.halt = 1; - #endif -} - -// spnoop - no operation, always ignore -static void spnoop() -{ - RDP("spnoop\n"); -} - -// noop - no operation, always ignore -static void rdp_noop() -{ - RDP("noop\n"); -} - -static void ys_memrect () -{ - DWORD tile = (WORD)((rdp.cmd1 & 0x07000000) >> 24); - - DWORD lr_x = (WORD)((rdp.cmd0 & 0x00FFF000) >> 14); - DWORD lr_y = (WORD)((rdp.cmd0 & 0x00000FFF) >> 2); - DWORD ul_x = (WORD)((rdp.cmd1 & 0x00FFF000) >> 14); - DWORD ul_y = (WORD)((rdp.cmd1 & 0x00000FFF) >> 2); - - rdp.pc[rdp.pc_i] += 16; // texrect is 196-bit - - if (lr_y > rdp.scissor_o.lr_y) lr_y = rdp.scissor_o.lr_y; - - FRDP ("memrect (%d, %d, %d, %d), ci_width: %d\n", ul_x, ul_y, lr_x, lr_y, rdp.ci_width); - - DWORD y, width = lr_x - ul_x; - DWORD texaddr = rdp.addr[rdp.tiles[tile].t_mem]; - DWORD tex_width = rdp.tiles[tile].line << 3; - - for (y = ul_y; y < lr_y; y++) { - BYTE *src = gfx.RDRAM + texaddr + (y - ul_y) * tex_width; - BYTE *dst = gfx.RDRAM + rdp.cimg + ul_x + y * rdp.ci_width; - memcpy (dst, src, width); - } -} - -static void pm_palette_mod () -{ - BYTE envr = (BYTE)((float)((rdp.env_color >> 24)&0xFF)/255.0f*31.0f); - BYTE envg = (BYTE)((float)((rdp.env_color >> 16)&0xFF)/255.0f*31.0f); - BYTE envb = (BYTE)((float)((rdp.env_color >> 8)&0xFF)/255.0f*31.0f); - WORD env16 = (WORD)((envr<<11)|(envg<<6)|(envb<<1)|1); - BYTE prmr = (BYTE)((float)((rdp.prim_color >> 24)&0xFF)/255.0f*31.0f); - BYTE prmg = (BYTE)((float)((rdp.prim_color >> 16)&0xFF)/255.0f*31.0f); - BYTE prmb = (BYTE)((float)((rdp.prim_color >> 8)&0xFF)/255.0f*31.0f); - WORD prim16 = (WORD)((prmr<<11)|(prmg<<6)|(prmb<<1)|1); - WORD * dst = (WORD*)(gfx.RDRAM+rdp.cimg); - for (int i = 0; i < 16; i++) - { - dst[i^1] = (rdp.pal_8[i]&1) ? prim16 : env16; - } - RDP("Texrect palette modification\n"); -} - -static void rdp_texrect() -{ - DWORD a = rdp.pc[rdp.pc_i]; - rdp.cmd2 = ((DWORD*)gfx.RDRAM)[(a>>2)+1]; - rdp.cmd3 = ((DWORD*)gfx.RDRAM)[(a>>2)+3]; - - if (settings.ASB) //modified Rice's hack for All-Star Baseball games - { - DWORD dwHalf1 = (((DWORD*)gfx.RDRAM)[(a>>2)+0]) >> 24; - if ((dwHalf1 != 0xF1) && (dwHalf1 != 0xb3)) - { - rdp.pc[rdp.pc_i] += 16; - } - else - { - rdp.pc[rdp.pc_i] += 8; - rdp.cmd3 = rdp.cmd2; - rdp.cmd2 = 0; - } - } - else if (settings.yoshi && settings.ucode == 6) - { - ys_memrect(); - return; - } - else - { - rdp.pc[rdp.pc_i] += 16; // texrect is 196-bit - } - - if (rdp.skip_drawing || (!settings.fb_smart && (rdp.cimg == rdp.zimg))) - { - if (settings.PM && rdp.ci_status == ci_useless) - { - pm_palette_mod (); - } - else - { - RDP("Texrect skipped\n"); - } - return; - } - - if ((settings.ucode == 8) && 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); - RDP("Shadow texrect is skipped.\n"); - rdp.tri_n += 2; - return; - } - - WORD ul_x = (WORD)((rdp.cmd1 & 0x00FFF000) >> 14); - WORD ul_y = (WORD)((rdp.cmd1 & 0x00000FFF) >> 2); - WORD lr_x = (WORD)((rdp.cmd0 & 0x00FFF000) >> 14); - WORD lr_y = (WORD)((rdp.cmd0 & 0x00000FFF) >> 2); - if (ul_x >= lr_x) return; - if (rdp.cycle_mode > 1 || settings.increase_texrect_edge) - { - lr_x++; - lr_y++; - } - if (ul_y == lr_y) - { - lr_y ++; - } - - //* - if (rdp.hires_tex && settings.fb_optimize_texrect) - { - if (!rdp.hires_tex->drawn) - { - DRAWIMAGE d; - d.imageX = 0; - d.imageW = (WORD)rdp.hires_tex->width; - d.frameX = ul_x; - d.frameW = (WORD)(rdp.hires_tex->width);//(WORD)(ul_x + rdp.hires_tex->width);//lr_x; - - d.imageY = 0; - d.imageH = (WORD)rdp.hires_tex->height; - d.frameY = ul_y; - d.frameH = (WORD)(rdp.hires_tex->height);//(ul_y + rdp.hires_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.hires_tex->width, rdp.hires_tex->height); - d.scaleX = 1.0f; - d.scaleY = 1.0f; - DrawHiresImage(&d, rdp.hires_tex->width == rdp.ci_width); - rdp.hires_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.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 (!settings.fb_hires && ((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 == 7) && (rdp.maincimg[1].addr != rdp.maincimg[0].addr) && (rdp.timg.addr >= rdp.maincimg[1].addr) && (rdp.timg.addr < (rdp.maincimg[1].addr+rdp.ci_width*rdp.ci_height*rdp.ci_size))) - { - if (settings.fb_smart) - if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self || !settings.fb_motionblur) - { - // 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); - RDP("Wrong Texrect.\n"); - rdp.tri_n += 2; - return; - } - } -//*/ - - int i; - - DWORD tile = (WORD)((rdp.cmd1 & 0x07000000) >> 24); - - // update MUST be at the beginning, b/c of update_scissor - if (rdp.cycle_mode == 2) - { - rdp.tex = 1; - rdp.allow_combine = 0; - - cmb.tmu1_func = cmb.tmu0_func = GR_COMBINE_FUNCTION_LOCAL; - cmb.tmu1_fac = cmb.tmu0_fac = GR_COMBINE_FACTOR_NONE; - cmb.tmu1_a_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_LOCAL; - cmb.tmu1_a_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_NONE; - cmb.tmu1_invert = cmb.tmu0_invert = FXFALSE; - cmb.tmu1_a_invert = cmb.tmu0_a_invert = FXFALSE; - } - - rdp.texrecting = 1; - - DWORD prev_tile = rdp.cur_tile; - rdp.cur_tile = tile; - rdp.update |= UPDATE_COMBINE; - update (); - - rdp.texrecting = 0; - rdp.allow_combine = 1; - - if (!rdp.cur_cache[0]) - { - rdp.cur_tile = prev_tile; - rdp.tri_n += 2; - return; - } - // **** - // ** Texrect offset by Gugaman ** - float off_x = (float)((short)((rdp.cmd2 & 0xFFFF0000) >> 16)) / 32.0f; - if ((int(off_x) == 512) && (rdp.timg.width < 512)) off_x = 0.0f; - float off_y = (float)((short)(rdp.cmd2 & 0x0000FFFF)) / 32.0f; - float dsdx = (float)((short)((rdp.cmd3 & 0xFFFF0000) >> 16)) / 1024.0f; - float dtdy = (float)((short)(rdp.cmd3 & 0x0000FFFF)) / 1024.0f; - - 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 (%d, %d, %d, %d), tile: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, tile, rdp.tri_n, rdp.tri_n+1); - 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, off_y, dsdx, dtdy); - - float off_size_x; - float off_size_y; - - if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip - { - off_size_x = (float)((lr_y - ul_y - 1) * dsdx); - off_size_y = (float)((lr_x - ul_x - 1) * dtdy); - } - else - { - off_size_x = (float)((lr_x - ul_x - 1) * dsdx); - off_size_y = (float)((lr_y - ul_y - 1) * dtdy); - } - - float lr_u0, lr_v0, ul_u0, ul_v0, lr_u1, lr_v1, ul_u1, ul_v1; - - if (rdp.cur_cache[0] && (rdp.tex & 1)) - { - float sx=1, sy=1; - if (rdp.tiles[rdp.cur_tile].shift_s) - { - if (rdp.tiles[rdp.cur_tile].shift_s > 10) - sx = (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s)); - else - sx = (float)1.0f/(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) - sy = (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t)); - else - sy = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile].shift_t); - } - if (rdp.hires_tex && rdp.hires_tex->tile == 0) - { - off_x += rdp.hires_tex->u_shift;// + rdp.tiles[0].ul_s; //commented for Paper Mario motion blur - off_y += rdp.hires_tex->v_shift;// + rdp.tiles[0].ul_t; - FRDP("hires_tex ul_s: %d, ul_t: %d, off_x: %f, off_y: %f\n", rdp.tiles[0].ul_s, rdp.tiles[0].ul_t, off_x, off_y); - ul_u0 = off_x * sx; - ul_v0 = off_y * sy; - - lr_u0 = ul_u0 + off_size_x * sx; - lr_v0 = ul_v0 + off_size_y * sy; - - ul_u0 *= rdp.hires_tex->u_scale; - ul_v0 *= rdp.hires_tex->v_scale; - lr_u0 *= rdp.hires_tex->u_scale; - lr_v0 *= rdp.hires_tex->v_scale; - FRDP("hires_tex ul_u0: %f, ul_v0: %f, lr_u0: %f, lr_v0: %f\n", ul_u0, ul_v0, lr_u0, lr_v0); - } - else - { - ul_u0 = off_x * sx; - ul_v0 = off_y * sy; - - ul_u0 -= rdp.tiles[rdp.cur_tile].f_ul_s; - ul_v0 -= rdp.tiles[rdp.cur_tile].f_ul_t; - - lr_u0 = ul_u0 + off_size_x * sx; - lr_v0 = ul_v0 + off_size_y * sy; - - ul_u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * ul_u0; - lr_u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * lr_u0; - ul_v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * ul_v0; - lr_v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * lr_v0; - } - } - else - { - ul_u0 = ul_v0 = lr_u0 = lr_v0 = 0; - } - if (rdp.cur_cache[1] && (rdp.tex & 2)) - { - float sx=1, sy=1; - - if (rdp.tiles[rdp.cur_tile+1].shift_s) - { - if (rdp.tiles[rdp.cur_tile+1].shift_s > 10) - sx = (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s)); - else - sx = (float)1.0f/(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) - sy = 1;//(float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t)); - else - sy = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile+1].shift_t); - } - - if (rdp.hires_tex && rdp.hires_tex->tile == 1) - { - off_x += rdp.hires_tex->u_shift;// + rdp.tiles[0].ul_s; //commented for Paper Mario motion blur - off_y += rdp.hires_tex->v_shift;// + rdp.tiles[0].ul_t; - FRDP("hires_tex ul_s: %d, ul_t: %d, off_x: %f, off_y: %f\n", rdp.tiles[0].ul_s, rdp.tiles[0].ul_t, off_x, off_y); - ul_u1 = off_x * sx; - ul_v1 = off_y * sy; - - lr_u1 = ul_u1 + off_size_x * sx; - lr_v1 = ul_v1 + off_size_y * sy; - - ul_u1 *= rdp.hires_tex->u_scale; - ul_v1 *= rdp.hires_tex->v_scale; - lr_u1 *= rdp.hires_tex->u_scale; - lr_v1 *= rdp.hires_tex->v_scale; - FRDP("hires_tex ul_u1: %f, ul_v1: %f, lr_u1: %f, lr_v1: %f\n", ul_u0, ul_v0, lr_u0, lr_v0); - - } - else - { - ul_u1 = off_x * sx; - ul_v1 = off_y * sy; - - ul_u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s; - ul_v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t; - - lr_u1 = ul_u1 + off_size_x * sx; - lr_v1 = ul_v1 + off_size_y * sy; - - ul_u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * ul_u1; - lr_u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * lr_u1; - ul_v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * ul_v1; - lr_v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * lr_v1; - } - } - else - { - ul_u1 = ul_v1 = lr_u1 = lr_v1 = 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, ul_u0, lr_u0, ul_u1, lr_u1, (float)rdp.scissor.ul_x, (float)rdp.scissor.lr_x); - CCLIP2 (s_ul_y, s_lr_y, ul_v0, lr_v0, ul_v1, lr_v1, (float)rdp.scissor.ul_y, (float)rdp.scissor.lr_y); -// CCLIP2 (s_lr_y, s_ul_y, lr_v0, ul_v0, lr_v1, ul_v1, (float)rdp.scissor.ul_y, (float)rdp.scissor.lr_y); - - FRDP (" draw at: (%f, %f) -> (%f, %f)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y); - - // DO NOT SET CLAMP MODE HERE - - float Z = 1.0f; - if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030)) // othermode check makes sure it - // USES the z-buffer. Otherwise it returns bad (unset) values for lot and telescope - //in zelda:mm. - { - FRDP ("prim_depth = %d\n", rdp.prim_depth); - Z = rdp.prim_depth; - if (settings.increase_primdepth) - Z += 8.0f; - Z = ScaleZ(Z); - - grDepthBufferFunction (GR_CMP_LEQUAL); - rdp.update |= UPDATE_ZBUF_ENABLED; - } - else - { - RDP ("no prim_depth used, using 1.0\n"); - } - - VERTEX vstd[4] = { - { s_ul_x, s_ul_y, Z, 1.0f, ul_u0, ul_v0, ul_u1, ul_v1, { 0, 0, 0, 0}, 255 }, - { s_lr_x, s_ul_y, Z, 1.0f, lr_u0, ul_v0, lr_u1, ul_v1, { 0, 0, 0, 0}, 255 }, - { s_ul_x, s_lr_y, Z, 1.0f, ul_u0, lr_v0, ul_u1, lr_v1, { 0, 0, 0, 0}, 255 }, - { s_lr_x, s_lr_y, Z, 1.0f, lr_u0, lr_v0, lr_u1, lr_v1, { 0, 0, 0, 0}, 255 } }; - - if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip - { - vstd[1].u0 = ul_u0; - vstd[1].v0 = lr_v0; - vstd[1].u1 = ul_u1; - vstd[1].v1 = lr_v1; - - vstd[2].u0 = lr_u0; - vstd[2].v0 = ul_v0; - vstd[2].u1 = lr_u1; - vstd[2].v1 = ul_v1; - } - - 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.hires_tex && 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; - - if (settings.ucode == 7) - { - start_u_256 = 0; - end_u_256 = (lr_x - ul_x - 1)>>8; - } - else - { - 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); - vnew = new VERTEX [num_verts_line << 1]; - - n_vertices = num_verts_line << 1; - 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; iu0 *= z->q; - z->v0 *= z->q; - z->u1 *= z->q; - z->v1 *= z->q; - - apply_shade_mods (z); - } - - if (fullscreen) - { - grFogMode (GR_FOG_DISABLE); - - grClipWindow (0, 0, settings.res_x, settings.res_y); - - grCullMode (GR_CULL_DISABLE); - - if (rdp.cycle_mode == 2) - { - grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, - GR_COMBINE_FACTOR_ONE, - GR_COMBINE_LOCAL_NONE, - GR_COMBINE_OTHER_TEXTURE, - FXFALSE); - grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, - GR_COMBINE_FACTOR_ONE, - GR_COMBINE_LOCAL_NONE, - GR_COMBINE_OTHER_TEXTURE, - FXFALSE); - grAlphaBlendFunction (GR_BLEND_ONE, - GR_BLEND_ZERO, - GR_BLEND_ZERO, - GR_BLEND_ZERO); - if (rdp.othermode_l & 1) - { - grAlphaTestFunction (GR_CMP_GEQUAL); - grAlphaTestReferenceValue (0x80); - } - else - grAlphaTestFunction (GR_CMP_ALWAYS); - - rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE; - } - - 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 (debug.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; - - if (settings.fog && (rdp.flags & FOG_ENABLED)) - { - grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); - } - rdp.update |= UPDATE_CULL_MODE | UPDATE_VIEWPORT; - } - else - { - rdp.tri_n += 2; - } - - delete[] vnew; -} - -static void rdp_loadsync() -{ - RDP("loadsync - ignored\n"); -} - -static void rdp_pipesync() -{ - RDP("pipesync - ignored\n"); -} - -static void rdp_tilesync() -{ - RDP("tilesync - ignored\n"); -} - -static void rdp_fullsync() -{ - // Set an interrupt to allow the game to continue - *gfx.MI_INTR_REG |= 0x20; - gfx.CheckInterrupts(); - RDP("fullsync\n"); -} - -static void rdp_setkeygb() -{ - RDP_E("setkeygb - IGNORED\n"); - RDP("setkeygb - IGNORED\n"); -} - -static void rdp_setkeyr() -{ - RDP_E("setkeyr - IGNORED\n"); - RDP("setkeyr - IGNORED\n"); -} - -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.K5 = (BYTE)(rdp.cmd1&0x1FF); - RDP_E("setconvert - IGNORED\n"); - RDP("setconvert - IGNORED\n"); -} - -// -// 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(*/(DWORD)(((rdp.cmd0 & 0x00FFF000) >> 14))/*, 320)*/; - rdp.scissor_o.ul_y = /*min(*/(DWORD)(((rdp.cmd0 & 0x00000FFF) >> 2))/*, 240)*/; - rdp.scissor_o.lr_x = /*min(*/(DWORD)(((rdp.cmd1 & 0x00FFF000) >> 14))/*, 320)*/; - rdp.scissor_o.lr_y = /*min(*/(DWORD)(((rdp.cmd1 & 0x00000FFF) >> 2))/*, 240)*/; - - rdp.ci_upper_bound = rdp.scissor_o.ul_y; - rdp.ci_lower_bound = rdp.scissor_o.lr_y; - - 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; -} - -static void rdp_setprimdepth() -{ - rdp.prim_depth = (WORD)((rdp.cmd1 >> 16) & 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] (); \ -} - - RDP("rdp_setothermode\n"); - - if ((settings.ucode == 2) || (settings.ucode == 8)) - { - 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 (DWORD addr, WORD start, WORD count) -{ - RDP ("Loading palette... "); - WORD *dpal = rdp.pal_8 + start; - WORD end = start+count; - // WORD *spal = (WORD*)(gfx.RDRAM + (addr & BMASK)); - - for (WORD i=start; i>= 4; - end = start + (count >> 4); - for (WORD p = start; p < end; p++) - { - rdp.pal_8_crc[p] = CRC_Calculate( 0xFFFFFFFF, &rdp.pal_8[(p << 4)], 32 ); - } - rdp.pal_256_crc = CRC_Calculate( 0xFFFFFFFF, rdp.pal_8_crc, 64 ); - RDP ("Done.\n"); -} - -static void rdp_loadtlut() -{ - DWORD tile = (rdp.cmd1 >> 24) & 0x07; - WORD start = rdp.tiles[tile].t_mem - 256; // starting location in the palettes - // WORD start = ((WORD)(rdp.cmd1 >> 2) & 0x3FF) + 1; - WORD count = ((WORD)(rdp.cmd1 >> 14) & 0x3FF) + 1; // number to copy - - if (rdp.timg.addr + (count<<1) > BMASK) - count = (WORD)((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; -} - -BOOL tile_set = 0; -static void rdp_settilesize() -{ - DWORD 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 = (((WORD)(rdp.cmd0 >> 14)) & 0x03ff); - int ul_t = (((WORD)(rdp.cmd0 >> 2 )) & 0x03ff); - int lr_s = (((WORD)(rdp.cmd1 >> 14)) & 0x03ff); - int lr_t = (((WORD)(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; - - if (tile == 0 && rdp.hires_tex) - //if ((rdp.tiles[tile].size != 2) || ((rdp.timg.width == 1) && (rdp.hires_tex->width != (DWORD)(lr_s+1)))) - if (((rdp.tiles[tile].format == 0) && (rdp.tiles[tile].size != 2)) || ((rdp.timg.width == 1) && (rdp.hires_tex->width != (DWORD)(lr_s+1)))) - rdp.hires_tex = 0; - if (rdp.hires_tex) - { - if (rdp.tiles[tile].format == 0 && rdp.hires_tex->format == 0) - { - if (tile == 1 && (DWORD)rdp.hires_tex->tmu != tile) - SwapTextureBuffer(); - rdp.hires_tex->tile = tile; - rdp.hires_tex->info.format = GR_TEXFMT_RGB_565; - FRDP ("hires_tex: tile: %d\n", tile); - } - else if (tile == 0) - { - rdp.hires_tex->info.format = GR_TEXFMT_ALPHA_INTENSITY_88; - } - } - FRDP ("settilesize: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d\n", - tile, ul_s, ul_t, lr_s, lr_t); -} - -static void CopyswapBlock(int *pDst, unsigned int cnt, unsigned int SrcOffs) -{ - // copy and byteswap a block of 8-byte dwords - int rem = SrcOffs & 3; - if (rem == 0) - { - int *pSrc = (int *) ((uintptr_t) gfx.RDRAM + SrcOffs); - for (unsigned int x = 0; x < cnt; x++) - { - int s1 = bswap32(*pSrc++); - int s2 = bswap32(*pSrc++); - *pDst++ = s1; - *pDst++ = s2; - } - } - else - { - // set source pointer to 4-byte aligned RDRAM location before the start - int *pSrc = (int *) ((uintptr_t) gfx.RDRAM + (SrcOffs & 0xfffffffc)); - // do the first partial 32-bit word - int s0 = bswap32(*pSrc++); - for (int x = 0; x < rem; x++) - s0 >>= 8; - for (int x = 4; x > rem; x--) - { - *((char *) pDst) = s0 & 0xff; - pDst = (int *) ((char *) pDst + 1); - s0 >>= 8; - } - // do one full 32-bit word - s0 = bswap32(*pSrc++); - *pDst++ = s0; - // do 'cnt-1' 64-bit dwords - for (unsigned int x = 0; x < cnt-1; x++) - { - int s1 = bswap32(*pSrc++); - int s2 = bswap32(*pSrc++); - *pDst++ = s1; - *pDst++ = s2; - } - // do last partial 32-bit word - s0 = bswap32(*pSrc++); - for (; rem > 0; rem--) - { - *((char *) pDst) = s0 & 0xff; - pDst = (int *) ((char *) pDst + 1); - s0 >>= 8; - } - } -} - -static void WordswapBlock(int *pDst, unsigned int cnt, unsigned int TileSize) -{ - // Since it's not loading 32-bit textures as the N64 would, 32-bit textures need to - // be swapped by 64-bits, not 32. - if (TileSize == 3) - { - // swapblock64 dst, cnt - for (unsigned int x = 0; x < cnt / 2; x++, pDst += 4) - { - long long s1 = ((long long *) pDst)[0]; - long long s2 = ((long long *) pDst)[1]; - ((long long *) pDst)[0] = s2; - ((long long *) pDst)[1] = s1; - } - } - else - { - // swapblock32 dst, cnt - for (unsigned int x = 0; x < cnt; x++, pDst += 2) - { - int s1 = pDst[0]; - int s2 = pDst[1]; - pDst[0] = s2; - pDst[1] = s1; - } - } -} - -static void rdp_loadblock() -{ - if (rdp.skip_drawing) - { - RDP("loadblock skipped\n"); - return; - } - DWORD tile = (DWORD)((rdp.cmd1 >> 24) & 0x07); - DWORD dxt = (DWORD)(rdp.cmd1 & 0x0FFF); - - rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr; - - // ** DXT is used for swapping every other line - /* double fdxt = (double)0x8000000F/(double)((DWORD)(2047/(dxt-1))); // F for error - DWORD _dxt = (DWORD)fdxt;*/ - - // 0x00000800 -> 0x80000000 (so we can check the sign bit instead of the 11th bit) - DWORD _dxt = dxt << 20; - - DWORD addr = segoffset(rdp.timg.addr) & BMASK; - - // lr_s specifies number of 64-bit words to copy - // 10.2 format - WORD ul_s = (WORD)(rdp.cmd0 >> 14) & 0x3FF; - WORD ul_t = (WORD)(rdp.cmd0 >> 2) & 0x3FF; - WORD lr_s = (WORD)(rdp.cmd1 >> 14) & 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 - - // 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 = (WORD)((BMASK-addr)>>3); - - DWORD offs = rdp.timg.addr; - DWORD cnt = lr_s+1; - if (rdp.tiles[tile].size == 3) - cnt <<= 1; - //FIXME: unused? DWORD start_line = 0; - - // if (lr_s > 0) - rdp.timg.addr += cnt << 3; - - int * pDst = (int *) ((uintptr_t)rdp.tmem+(rdp.tiles[tile].t_mem<<3)); - - // Load the block from RDRAM and byteswap it as it loads - CopyswapBlock(pDst, cnt, offs); - - // now do 32-bit or 64-bit word swapping on every other row of data - int dxt_accum = 0; - while (cnt > 0) - { - // skip over unswapped blocks - do - { - pDst += 2; - if (--cnt == 0) - break; - dxt_accum += _dxt; - } while (!(dxt_accum & 0x80000000)); - // count number of blocks to swap - if (cnt == 0) break; - int swapcnt = 0; - do - { - swapcnt++; - if (--cnt == 0) - break; - dxt_accum += _dxt; - } while (dxt_accum & 0x80000000); - // do 32-bit or 64-bit swap operation on this block - WordswapBlock(pDst, swapcnt, rdp.tiles[tile].size); - pDst += swapcnt * 2; - } - - 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); -} - -static void rdp_loadtile() -{ - if (rdp.skip_drawing) - return; - rdp.timg.set_by = 1; // load tile - - DWORD tile = (DWORD)((rdp.cmd1 >> 24) & 0x07); - if (rdp.tiles[tile].format == 1) - { - rdp.yuv_image = TRUE; - if (rdp.timg.addr < rdp.yuv_im_begin) rdp.yuv_im_begin = rdp.timg.addr; - return; - } - - rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr; - - WORD ul_s = (WORD)((rdp.cmd0 >> 14) & 0x03FF); - WORD ul_t = (WORD)((rdp.cmd0 >> 2 ) & 0x03FF); - WORD lr_s = (WORD)((rdp.cmd1 >> 14) & 0x03FF); - WORD lr_t = (WORD)((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; - // wrong_tile = -1; - } - - if (rdp.hires_tex)// && (rdp.tiles[tile].format == 0)) - { - FRDP("loadtile: hires_tex ul_s: %d, ul_t:%d\n", ul_s, ul_t); - rdp.hires_tex->tile_uls = ul_s; - rdp.hires_tex->tile_ult = ul_t; - } - - if (settings.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; - } - - DWORD height = lr_t - ul_t + 1; // get height - DWORD width = lr_s - ul_s + 1; - - DWORD wid_64 = rdp.tiles[tile].line; - - // CHEAT: it's very unlikely that it loads more than 1 32-bit texture in one command, - // so i don't bother to write in two different places at once. Just load once with - // twice as much data. - if (rdp.tiles[tile].size == 3) - wid_64 <<= 1; - - int line_n = rdp.timg.width; - if (rdp.tiles[tile].size == 0) - line_n >>= 1; - else - line_n <<= (rdp.tiles[tile].size-1); - - int offs = ul_t * line_n; - offs += ul_s << rdp.tiles[tile].size >> 1; - offs += rdp.timg.addr; - if ((unsigned int) offs >= BMASK) - return; - - // check if points to bad location - DWORD size = width * height; - if (rdp.tiles[tile].size == 0) - size >>= 1; - else - size <<= (rdp.tiles[tile].size-1); - - if (offs + line_n*height > BMASK) - height = (BMASK - offs) / line_n; - - int * pDst = (int *) ((uintptr_t)rdp.tmem+(rdp.tiles[tile].t_mem<<3)); - int * pEnd = (int *) ((uintptr_t)rdp.tmem+4096 - (wid_64<<3)); - - for (unsigned int y = 0; y < height; y++) - { - if (pDst > pEnd) break; - CopyswapBlock(pDst, wid_64, offs); - if (y & 1) - { - WordswapBlock(pDst, wid_64, rdp.tiles[tile].size); - } - pDst += wid_64 * 2; - offs += line_n; - } - - 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); -} - -static void rdp_settile() -{ - tile_set = 1; // used to check if we only load the first settilesize - - rdp.first = 0; - - //rdp.cur_tile_n = (DWORD)((rdp.cmd1 >> 24) & 0x07); - //rdp.cur_tile = &rdp.tiles[rdp.cur_tile_n]; - - rdp.last_tile = (DWORD)((rdp.cmd1 >> 24) & 0x07); - TILE *tile = &rdp.tiles[rdp.last_tile]; - - tile->format = (BYTE)((rdp.cmd0 >> 21) & 0x07); - tile->size = (BYTE)((rdp.cmd0 >> 19) & 0x03); - tile->line = (WORD)((rdp.cmd0 >> 9) & 0x01FF); - tile->t_mem = (WORD)(rdp.cmd0 & 0x1FF); - tile->palette = (BYTE)((rdp.cmd1 >> 20) & 0x0F); - tile->clamp_t = (BYTE)((rdp.cmd1 >> 19) & 0x01); - tile->mirror_t = (BYTE)((rdp.cmd1 >> 18) & 0x01); - tile->mask_t = (BYTE)((rdp.cmd1 >> 14) & 0x0F); - tile->shift_t = (BYTE)((rdp.cmd1 >> 10) & 0x0F); - tile->clamp_s = (BYTE)((rdp.cmd1 >> 9) & 0x01); - tile->mirror_s = (BYTE)((rdp.cmd1 >> 8) & 0x01); - tile->mask_s = (BYTE)((rdp.cmd1 >> 4) & 0x0F); - tile->shift_s = (BYTE)(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); -} - -// -// fillrect - fills a rectangle -// - -static void rdp_fillrect() -{ - DWORD ul_x = ((rdp.cmd1 & 0x00FFF000) >> 14); - DWORD ul_y = (rdp.cmd1 & 0x00000FFF) >> 2; - DWORD lr_x = ((rdp.cmd0 & 0x00FFF000) >> 14) + 1; - DWORD lr_y = ((rdp.cmd0 & 0x00000FFF) >> 2) + 1; - if ((rdp.cimg == rdp.zimg) || (settings.fb_smart && rdp.frame_buffers[rdp.ci_count-1].status == ci_zimg)) - { - RDP ("Fillrect - cleared the depth buffer\n"); - if (fullscreen) - { - - grDepthMask (FXTRUE); - grColorMask (FXFALSE, FXFALSE); - grBufferClear (0, 0, 0xFFFF); - grColorMask (FXTRUE, FXTRUE); - rdp.update |= UPDATE_ZBUF_ENABLED; - if (settings.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); - //FIXME:unused? DWORD zi_height = lr_y - ul_y - 1; - // rdp.zi_nb_pixels = rdp.zi_width * zi_height; - rdp.zi_lry = lr_y - 1; - rdp.zi_lrx = lr_x - 1; - // FRDP ("zi_width: %d, zi_height: %d\n", rdp.zi_width, zi_height); - DWORD fillrect_width_in_dwords = (lr_x-ul_x) >> 1; - DWORD zi_width_in_dwords = rdp.zi_width >> 1; - ul_x >>= 1; - DWORD * dst = (DWORD*)(gfx.RDRAM+rdp.cimg); - dst += ul_y * zi_width_in_dwords; - for (DWORD y = ul_y; y < lr_y; y++) - { - for (DWORD x = ul_x; x < fillrect_width_in_dwords; x++) - { - dst[x] = rdp.fill_color; - } - dst += zi_width_in_dwords; - } - } - } - return; - } - - if (rdp.skip_drawing) - { - RDP("Fillrect skipped\n"); - return; - } - - // Update scissor - update_scissor (); - - if ((ul_x > lr_x) || (ul_y > lr_y)) return; - if (settings.bomberman64 && (lr_x == rdp.ci_width) && (rdp.cimg == rdp.ocimg)) //bomberman64 hack - return; - - if (rdp.cur_image && (rdp.cur_image->format != 0) && (rdp.cycle_mode == 3) && (rdp.cur_image->width == lr_x)) - { - DWORD color = rdp.fill_color; - color = ((color&1)?0xFF:0) | - ((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | - ((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | - ((DWORD)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8); - grDepthMask (FXFALSE); - grBufferClear (color, 0, 0xFFFF); - grDepthMask (FXTRUE); - rdp.update |= UPDATE_ZBUF_ENABLED; - return; - } - - 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 - DWORD s_ul_x = (DWORD)min(max(ul_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x); - DWORD s_lr_x = (DWORD)min(max(lr_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x); - DWORD s_ul_y = (DWORD)min(max(ul_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y); - DWORD s_lr_y = (DWORD)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.0f) s_lr_x = 0; - if (s_lr_y < 0.0f) s_lr_y = 0; - if (s_ul_x > (float)settings.res_x) s_ul_x = settings.res_x; - if (s_ul_y > (float)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); - - grClipWindow (0, 0, settings.res_x, settings.res_y); - - float Z = 1.0f; - if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030)) - { - Z = ScaleZ(rdp.prim_depth); - grDepthBufferFunction (GR_CMP_LEQUAL); - // grDepthMask (FXTRUE); - FRDP ("prim_depth = %d\n", rdp.prim_depth); - } - else - { - grDepthBufferFunction (GR_CMP_ALWAYS); - grDepthMask (FXFALSE); - RDP ("no prim_depth used, using 1.0\n"); - } - // 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) - { - DWORD color = (settings.fillcolor_fix) ? rdp.fill_color : (rdp.fill_color >> 16); - - if (settings.PM && rdp.frame_buffers[rdp.ci_count-1].status == ci_aux) - { - //background of auxilary frame buffers must have zero alpha. - //make it black, set 0 alpha to plack pixels on frame buffer read - color = 0; - } - else - { - color = ((color&1)?0xFF:0) | - ((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | - ((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | - ((DWORD)((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); - - rdp.update |= UPDATE_COMBINE; - } - else - { - Combine (); - TexCache (); // (to update combiner) - DWORD cmb_mode_c = (rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF); - DWORD 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]); - } - } - - grAlphaTestFunction (GR_CMP_ALWAYS); - if (grStippleModeExt) - grStippleModeExt(GR_STIPPLE_DISABLE); - - grCullMode(GR_CULL_DISABLE); - - 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 (debug.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; - - if (settings.fog && (rdp.flags & FOG_ENABLED)) - { - grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); - } - - rdp.update |= UPDATE_CULL_MODE | UPDATE_ALPHA_COMPARE | UPDATE_ZBUF_ENABLED; - } - 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 = (BYTE)((rdp.cmd0 >> 20) & 0xF); - rdp.c_b0 = (BYTE)((rdp.cmd1 >> 28) & 0xF); - rdp.c_c0 = (BYTE)((rdp.cmd0 >> 15) & 0x1F); - rdp.c_d0 = (BYTE)((rdp.cmd1 >> 15) & 0x7); - rdp.c_Aa0 = (BYTE)((rdp.cmd0 >> 12) & 0x7); - rdp.c_Ab0 = (BYTE)((rdp.cmd1 >> 12) & 0x7); - rdp.c_Ac0 = (BYTE)((rdp.cmd0 >> 9) & 0x7); - rdp.c_Ad0 = (BYTE)((rdp.cmd1 >> 9) & 0x7); - - rdp.c_a1 = (BYTE)((rdp.cmd0 >> 5) & 0xF); - rdp.c_b1 = (BYTE)((rdp.cmd1 >> 24) & 0xF); - rdp.c_c1 = (BYTE)((rdp.cmd0 >> 0) & 0x1F); - rdp.c_d1 = (BYTE)((rdp.cmd1 >> 6) & 0x7); - rdp.c_Aa1 = (BYTE)((rdp.cmd1 >> 21) & 0x7); - rdp.c_Ab1 = (BYTE)((rdp.cmd1 >> 3) & 0x7); - rdp.c_Ac1 = (BYTE)((rdp.cmd1 >> 18) & 0x7); - rdp.c_Ad1 = (BYTE)((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 = (BYTE)((rdp.cmd0 >> 21) & 0x07); - rdp.timg.size = (BYTE)((rdp.cmd0 >> 19) & 0x03); - rdp.timg.width = (WORD)(1 + (rdp.cmd0 & 0x00000FFF)); - rdp.timg.addr = segoffset(rdp.cmd1); - 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 if (rdp.frame_buffers[rdp.ci_count].status != ci_copy) - CloseTextureBuffer(TRUE); - rdp.fb_drawn = TRUE; - } - } - - if (settings.fb_hires) //search this texture among drawn texture buffers - { - if (settings.zelda) - { - if (rdp.timg.size == 2) - FindTextureBuffer(rdp.timg.addr, rdp.timg.width); - } - else - 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); -} - - -BOOL 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 DWORD swapped_addr = 0; - -static void rdp_setcolorimage() -{ - render_depth_mode = 0; - if (settings.fb_smart && (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-1]; - COLOR_IMAGE & next_fb = rdp.frame_buffers[rdp.ci_count+1]; - 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 (!settings.fb_hires) - { - 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.PM) //tidal wave - OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); - } - else if (!rdp.motionblur && settings.fb_hires && !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 (settings.fb_hires && rdp.read_whole_frame && prev_fb.status == ci_aux) - { - 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.fb_motionblur) - { - if (cur_fb.width == rdp.ci_width) - { - if (CopyTextureBuffer(prev_fb, cur_fb)) - // if (CloseTextureBuffer(TRUE)) - ; - 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)<>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 (settings.fb_hires) - OpenTextureBuffer(cur_fb); - } - break; - case ci_old_copy: - { - if (!rdp.motionblur || settings.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)<>1); - } - //rdp.skip_drawing = TRUE; - } - else - { - memset(gfx.RDRAM+cur_fb.addr, 0, (cur_fb.width*cur_fb.height)<>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: - { - if (!settings.fb_hires && cur_fb.format != 0) - rdp.skip_drawing = TRUE; - else - { - rdp.skip_drawing = FALSE; - if (settings.fb_hires && 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 (!settings.fb_hires && (prev_fb.status == ci_main) && - (prev_fb.width == cur_fb.width)) // for Pokemon Stadium - CopyFrameBuffer (); - } - } - cur_fb.status = ci_aux; - } - break; - case ci_zimg: - // ZIGGY - // Zelda LoT effect save/restore depth buffer - if (cur_fb.addr == rdp.zimg) { - render_depth_mode = 1; - } else { - render_depth_mode = 2; - } - rdp.skip_drawing = TRUE; - break; - case ci_useless: - //case ci_zcopy: - rdp.skip_drawing = TRUE; - break; - case ci_copy_self: - if (settings.fb_hires && (rdp.ci_count <= rdp.copy_ci_index) && (!SwapOK || settings.swapmode == 2)) - OpenTextureBuffer(cur_fb); - rdp.skip_drawing = FALSE; - /* - if (settings.fb_hires) - { - if (SwapOK) - { - rdp.cimg = rdp.frame_buffers[rdp.ci_count].addr; - rdp.maincimg[0].addr = rdp.cimg; - newSwapBuffers(); - SwapOK = FALSE; - OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count]); - } - } - */ - break; - default: - rdp.skip_drawing = FALSE; - } - - if ((rdp.ci_count > 0) && (prev_fb.status >= ci_aux)) //for Pokemon Stadium - { - if (!settings.fb_hires && prev_fb.format == 0) - CopyFrameBuffer (); - } - if (!settings.fb_hires && cur_fb.status == ci_copy) - { - if (!rdp.motionblur && (rdp.num_of_ci > rdp.ci_count+1) && (next_fb.status != ci_aux)) - { - RestoreScale(); - } - } - if (!settings.fb_hires && cur_fb.status == ci_aux) - { - if (cur_fb.format == 0) - { - if (settings.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; - WORD *ptr_dst = new WORD[width*height]; - WORD *ptr_src = (WORD*)(gfx.RDRAM+cur_fb.addr); - WORD c; - - for (int y=0; y> 1) | 0x8000; - ptr_dst[x + y * width] = c; - } - } - grLfbWriteRegion(GR_BUFFER_BACKBUFFER, - 0, - 0, - 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)) - { - BOOL 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) - { - RDP("return to original scale\n"); - rdp.scale_x = rdp.scale_x_bak; - rdp.scale_y = rdp.scale_y_bak; - if (settings.fb_hires && !rdp.read_whole_frame) - CloseTextureBuffer(); - } - if (settings.fb_hires && !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 (settings.fb_smart) - 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; - } - DWORD 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 (format != 0 && !rdp.cur_image) //can't draw into non RGBA buffer - { - if (settings.fb_hires && rdp.ci_width <= 64) - OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count - 1]); - else if (format > 2) - rdp.skip_drawing = TRUE; - return; - } - else - { - if (!settings.fb_smart) - rdp.skip_drawing = FALSE; - } - - CI_SET = TRUE; - if (settings.swapmode > 0) - { - if (rdp.zimg == rdp.cimg) - rdp.updatescreen = 1; - - BOOL 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 (settings.fb_smart) - 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 (settings.fb_hires) - { - 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]); - } - } - } - } -} - -static void rdp_trifill() -{ - RDP_E("trifill - IGNORED\n"); - RDP("trifill - IGNORED\n"); -} - -static void rdp_trishade() -{ - RDP_E("trishade - IGNORED\n"); - RDP("trishade - IGNORED\n"); -} - -static void rdp_tritxtr() -{ - RDP_E("tritxtr - IGNORED\n"); - RDP("tritxtr - IGNORED\n"); -} - -static void rdp_trishadetxtr() -{ - RDP_E("trishadetxtr - IGNORED\n"); - RDP("trishadetxtr - IGNORED\n"); -} - -static void rdp_trifillz() -{ - RDP_E("trifillz - IGNORED\n"); - RDP("trifillz - IGNORED\n"); -} - -static void rdp_trishadez() -{ - RDP_E("trishadez - IGNORED\n"); - RDP("trishadez - IGNORED\n"); -} - -static void rdp_tritxtrz() -{ - RDP_E("tritxtrz - IGNORED\n"); - RDP("tritxtrz - IGNORED\n"); -} - -static void rdp_trishadetxtrz() -{ - RDP_E("trishadetxtrz - IGNORED\n"); - RDP("trishadetxtrz - IGNORED\n"); -} - -static void rsp_reserved0() -{ - RDP_E("reserved0 - IGNORED\n"); - RDP("reserved0 - IGNORED\n"); -} - -static void rsp_reserved1() -{ - RDP("reserved1 - ignored\n"); -} - -static void rsp_reserved2() -{ - RDP("reserved2\n"); -} - -static void rsp_reserved3() -{ - RDP("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); - - //grDepthBufferFunction (GR_CMP_ALWAYS); - //grDepthMask (FXFALSE); - - rdp.update |= UPDATE_COMBINE | UPDATE_ALPHA_COMPARE; -} - -#ifdef __cplusplus -extern "C" { -#endif - -/****************************************************************** -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 = BYTE, 2 = WORD, 4 = DWORD -output: none -*******************************************************************/ -EXPORT void CALL FBRead(unsigned int 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; - DWORD 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)) - { - DWORD cimg = rdp.cimg; - rdp.cimg = rdp.maincimg[1].addr; - if (settings.fb_smart) - { - rdp.ci_width = rdp.maincimg[1].width; - rdp.ci_count = 0; - DWORD 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 -//TODO: remove -/****************************************************************** -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, DWORD size) -{ - LOG ("FBWList ()\n"); - FRDP("FBWList. size: %d\n", size); - printf("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 = BYTE, 2 = WORD, 4 = DWORD -output: none -*******************************************************************/ -EXPORT void CALL FBWrite(unsigned int addr, unsigned int 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; - DWORD a = segoffset(addr); - FRDP("FBWrite. addr: %08lx\n", a); - // ZIGGY : added a test on ci_width, otherwise we crash on zero division below - if (!rdp.ci_width || a < rdp.cimg || a > rdp.ci_end) - return; - cpu_fb_write = TRUE; - DWORD shift_l = (a-rdp.cimg) >> 1; - DWORD 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 -//TODO: remove -typedef struct -{ - DWORD addr; - DWORD size; - DWORD width; - DWORD height; -} FrameBufferInfo; -#endif - -EXPORT void CALL FBGetFrameBufferInfo(void *p) -{ - LOG ("FBGetFrameBufferInfo ()\n"); - FrameBufferInfo * pinfo = (FrameBufferInfo *)p; - memset(pinfo,0,sizeof(FrameBufferInfo)*6); - if (!settings.fb_get_info) - return; - RDP("FBGetFrameBufferInfo ()\n"); - //* - if (settings.fb_smart) - { - 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 () -{ - RDP("DetectFrameBufferUsage\n"); - - DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0); -#ifdef _WIN32 - DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4); -#endif // _WIN32 - DWORD a; - - BOOL tidal = FALSE; - if (settings.PM && (rdp.copy_ci_index || rdp.frame_buffers[rdp.copy_ci_index].status == ci_copy_self)) - tidal = TRUE; - DWORD ci = rdp.cimg, zi = rdp.zimg; // ci_width = rdp.ci_width; - rdp.main_ci = rdp.main_ci_end = rdp.main_ci_bg = rdp.ci_count = 0; - rdp.main_ci_index = rdp.copy_ci_index = 0; - rdp.zimg_end = 0; - rdp.tmpzimg = 0; - rdp.motionblur = FALSE; - rdp.main_ci_last_tex_addr = 0; - BOOL 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 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit - rdp.cmd1 = ((DWORD*)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 ((intptr_t)(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; - - RDP ("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; - } - - BOOL 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; - } - - RDP("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 (!settings.fb_hires || !rdp.copy_ci_index) - rdp.motionblur = TRUE; - if (rdp.motionblur || settings.fb_hires || (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 (settings.fb_hires && !settings.fb_ignore_previous) - { - if (rdp.swap_ci_index < 0) - { - rdp.texbufs[0].clear_allowed = TRUE; - OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); - } - } - else - { - if (rdp.motionblur) - { - if (settings.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; - DWORD 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 (settings.fb_hires) - { - for (i = 0; i < 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) - { - //RDP("Tidal wave!\n"); - rdp.copy_ci_index = rdp.main_ci_index; - } - } - rdp.ci_count = 0; - if (settings.fb_ignore_previous) - rdp.read_whole_frame = FALSE; - else - rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index]; - // rdp.scale_x = rdp.scale_x_bak; - // rdp.scale_y = rdp.scale_y_bak; - RDP("DetectFrameBufferUsage End\n"); -} - - - - -#ifdef __cplusplus -extern "C" { -#endif - -/****************************************************************** -Function: ProcessRDPList -Purpose: This function is called when there is a Dlist to be -processed. (Low level GFX list) -input: none -output: none -*******************************************************************/ -EXPORT void CALL ProcessRDPList(void) -{ - if (settings.KI) - { - *gfx.MI_INTR_REG |= 0x20; - gfx.CheckInterrupts(); - } - LOG ("ProcessRDPList ()\n"); - - no_dlist = FALSE; - update_screen_count = 0; - ChangeSize (); - -#ifdef ALTTAB_FIX - if (!hhkLowLevelKybd) - { - hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL, - LowLevelKeyboardProc, hInstance, 0); - } -#endif - - LOG ("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; - - memset (microcode, 0, 4096); - if (settings.autodetect_ucode) - { - // Thanks to ZeZu for ucode autodetection!!! - - DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0); - memcpy (microcode, gfx.RDRAM+startUcode, 4096); - microcheck (); - - } - } - else if ( ((old_ucode == 6) && (settings.ucode == 1)) || settings.force_microcheck) - { - DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0); - memcpy (microcode, gfx.RDRAM+startUcode, 4096); - microcheck (); - } - - if (exception) return; - - // Switch to fullscreen? - if (to_fullscreen) - { - to_fullscreen = FALSE; - - if (!InitGfx (FALSE)) - { - LOG ("FAILED!!!\n"); - return; - } - fullscreen = TRUE; - } - - // 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, (*(DWORD*)(gfx.DMEM+0x0FE4))>>6); - if (rdp.model_stack_size == 0) - rdp.model_stack_size = 32; - 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; - fbreads_front = fbreads_back = 0; - rdp.fog_multiplier = rdp.fog_offset = 0; - rdp.zsrc = 0; - - if (cpu_fb_write == TRUE) - DrawFrameBufferToScreen(); - 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; - - //analize possible frame buffer usage - if (settings.fb_smart) - DetectFrameBufferUsage(); - if (!settings.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 -// DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0); -// DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4); - DWORD dlist_start = *gfx.DPC_CURRENT_REG; - DWORD dlist_length = *gfx.DPC_END_REG - *gfx.DPC_CURRENT_REG; - FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_lenght: %d\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length); - FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG); - - if (settings.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; - DWORD a; - - // catches exceptions so that it doesn't freeze -#ifdef CATCH_EXCEPTIONS - try { -#endif - - // 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 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit - rdp.cmd1 = ((DWORD*)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 - QueryPerformanceCounter ((LARGE_INTEGER*)&perf_cur); -#endif - // Process this instruction - gfx_instruction[settings.ucode][((rdp.cmd0>>24)&0x3f) + 0x100-0x40] (); - - // check DL counter - if (rdp.dl_count != -1) - { - rdp.dl_count --; - if (rdp.dl_count == 0) - { - rdp.dl_count = -1; - - RDP ("End of DL\n"); - rdp.pc_i --; - } - } - -#ifdef PERFORMANCE - QueryPerformanceCounter ((LARGE_INTEGER*)&perf_next); - __int64 t = perf_next-perf_cur; - sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, t); - rdp_log << out_buf; -#endif - - } while (0); -#ifdef CATCH_EXCEPTIONS - } catch (...) { - - if (fullscreen) ReleaseGfx (); - WriteLog(M64MSG_ERROR, "The GFX plugin caused an exception and has been disabled."); - exception = TRUE; - } -#endif - - if (settings.fb_smart) - { - rdp.scale_x = rdp.scale_x_bak; - rdp.scale_y = rdp.scale_y_bak; - } - if (settings.fb_read_always) - { - CopyFrameBuffer (); - } - if (rdp.yuv_image) - { - DrawYUVImageToFrameBuffer(); - rdp.yuv_image = FALSE; -// FRDP("yuv image draw. ul_x: %f, ul_y: %f, lr_x: %f, lr_y: %f, begin: %08lx\n", -// rdp.yuv_ul_x, rdp.yuv_ul_y, rdp.yuv_lr_x, rdp.yuv_lr_y, rdp.yuv_im_begin); - rdp.yuv_ul_x = rdp.yuv_ul_y = rdp.yuv_lr_x = rdp.yuv_lr_y = 0; - rdp.yuv_im_begin = 0x00FFFFFF; - } - if (rdp.cur_image) - CloseTextureBuffer(rdp.read_whole_frame && (settings.PM || rdp.swap_ci_index >= 0)); - - if (settings.TGR2 && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET) - { - newSwapBuffers (); - CI_SET = FALSE; - } - RDP("ProcessDList end\n"); - - - - - - - WriteLog(M64MSG_VERBOSE, "ProcessRPDList %x %x %x\n", - *gfx.DPC_START_REG, - *gfx.DPC_END_REG, - *gfx.DPC_CURRENT_REG); - //*gfx.DPC_STATUS_REG = 0xffffffff; // &= ~0x0002; - - *gfx.DPC_START_REG = *gfx.DPC_END_REG; - *gfx.DPC_CURRENT_REG = *gfx.DPC_END_REG; -} - -#ifdef __cplusplus -} -#endif - - - - - -// Local Variables: *** -// tab-width:4 *** -// c-file-offset:4 *** -// End: *** - +/* +* Glide64 - Glide video plugin for Nintendo 64 emulators. +* Copyright (c) 2002 Dave2001 +* Copyright (c) 2008 Günther +* +* 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 +* Licence along with this program; if not, write to the Free +* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301, USA +*/ + +//**************************************************************** +// +// Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) +// Project started on December 29th, 2001 +// +// 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. +// +// Official Glide64 development channel: #Glide64 on EFnet +// +// Original author: Dave2001 (Dave2999@hotmail.com) +// Other authors: Gonetz, Gugaman +// +//**************************************************************** + +#define M64P_PLUGIN_PROTOTYPES 1 +#include "m64p_types.h" +#include "m64p_plugin.h" +#include "m64p_config.h" +#include "m64p_vidext.h" +#include "3dmath.h" +#include "Util.h" +#include "Debugger.h" +#include "Combine.h" +#include "Util.h" +#include "Ini.h" +#include "Config.h" +#include "Tmem.h" +#include "TexCache.h" +#include "TexCache.h" +#include "TexBuffer.h" +#include "CRC.h" +#include "rdp.h" + +#ifndef _WIN32 +#include +#endif // _WIN32 + +char out_buf[2048]; + +DWORD frame_count; // frame counter + +BOOL ucode_error_report = TRUE; +int wrong_tile = -1; + +int drawFlag = 1; // draw flag for rendering callback + +#if defined(__GNUC__) + #define bswap32(x) __builtin_bswap32(x) +#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) + #include + #define bswap32(x) _byteswap_ulong(x) +#else +static inline uint32_t bswap32(uint32_t val) +{ + return (((val & 0xff000000) >> 24) | + ((val & 0x00ff0000) >> 8) | + ((val & 0x0000ff00) << 8) | + ((val & 0x000000ff) << 24)); +} +#endif + +// global strings +const char *ACmp[4] = { "NONE", "THRESHOLD", "UNKNOWN", "DITHER" }; + +const char *Mode0[16] = { "COMBINED", "TEXEL0", + "TEXEL1", "PRIMITIVE", + "SHADE", "ENVIORNMENT", + "1", "NOISE", + "0", "0", + "0", "0", + "0", "0", + "0", "0" }; +const char *Mode1[16] = { "COMBINED", "TEXEL0", + "TEXEL1", "PRIMITIVE", + "SHADE", "ENVIORNMENT", + "CENTER", "K4", + "0", "0", + "0", "0", + "0", "0", + "0", "0" }; +const char *Mode2[32] = { "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[8] = { "COMBINED", "TEXEL0", + "TEXEL1", "PRIMITIVE", + "SHADE", "ENVIORNMENT", + "1", "0" }; + +const char *Alpha0[8] = { "COMBINED", "TEXEL0", + "TEXEL1", "PRIMITIVE", + "SHADE", "ENVIORNMENT", + "1", "0" }; +const char *Alpha2[8] = { "LOD_FRACTION", "TEXEL0", + "TEXEL1", "PRIMITIVE", + "SHADE", "ENVIORNMENT", + "PRIM_LODFRAC", "0" }; + +//FIXME:unused? +//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[2] = { "G_ZS_PIXEL", "G_ZS_PRIM" }; + +const char *str_yn[2] = { "NO", "YES" }; +const char *str_offon[2] = { "OFF", "ON" }; + +const char *str_cull[4] = { "DISABLE", "FRONT", "BACK", "BOTH" }; + +// I=intensity probably +const char *str_format[8] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" }; +const char *str_size[4] = { "4bit", "8bit", "16bit", "32bit" }; +const char *str_cm[4] = { "WRAP/NO CLAMP", "MIRROR/NO CLAMP", "WRAP/CLAMP", "MIRROR/CLAMP" }; + +//const char *str_lod[] = { "1", "2", "4", "8", "16", "32", "64", "128", "256" }; +//const char *str_aspect[] = { "1x8", "1x4", "1x2", "1x1", "2x1", "4x1", "8x1" }; + +const char *str_filter[3] = { "Point Sampled", "Average (box)", "Bilinear" }; + +const char *str_tlut[4] = { "TT_NONE", "TT_UNKNOWN", "TT_RGBA_16", "TT_IA_16" }; + +const char *CIStatus[10] = { "ci_main", "ci_zimg", "ci_unknown", "ci_useless", + "ci_old_copy", "ci_copy", "ci_copy_self", + "ci_zcopy", "ci_aux", "ci_aux_copy" }; + +typedef struct +{ + int ucode; + int crc; +} UcodeData; + +static UcodeData UcodeList[] = +{ + {0, 0x006bd77f}, + {2, 0x03044b84}, + {2, 0x030f4b84}, + {1, 0x05165579}, + {1, 0x05777c62}, + {1, 0x057e7c62}, + {1, 0x07200895}, + {2, 0x0bf36d36}, + {-1, 0x0d7bbffb}, + {5, 0x0d7cbffb}, + {2, 0x0ff79527}, + {-1, 0x0ff795bf}, + {1, 0x1118b3e0}, + {2, 0x168e9cd5}, + {2, 0x1a1e18a0}, + {2, 0x1a1e1920}, + {2, 0x1a62dbaf}, + {2, 0x1a62dc2f}, + {1, 0x1de712ff}, + {6, 0x1ea9e30f}, + {2, 0x21f91834}, + {2, 0x21f91874}, + {2, 0x22099872}, + {1, 0x24cd885b}, + {1, 0x26a7879a}, + {6, 0x299d5072}, + {2, 0x2b291027}, + {6, 0x2b5a89c2}, + {1, 0x2c7975d6}, + {2, 0x2f71d1d5}, + {2, 0x2f7dd1d5}, + {1, 0x327b933d}, + {1, 0x339872a6}, + {2, 0x377359b6}, + {0, 0x3a1c2b34}, + {0, 0x3a1cbac3}, + {0, 0x3f7247fb}, + {1, 0x3ff1a4ca}, + {0, 0x4165e1fd}, + {1, 0x4340ac9b}, + {1, 0x440cfad6}, + {7, 0x47d46e86}, + {2, 0x485abff2}, + {1, 0x4fe6df78}, + {0, 0x5182f610}, + {1, 0x5257cd2a}, + {1, 0x5414030c}, + {1, 0x5414030d}, + {1, 0x559ff7d4}, + {4, 0x5b5d36e3}, + {3, 0x5b5d3763}, + {0, 0x5d1d6f53}, + {2, 0x5d3099f1}, + {1, 0x5df1408c}, + {1, 0x5ef4e34a}, + {1, 0x6075e9eb}, + {1, 0x60c1dcc4}, + {2, 0x6124a508}, + {2, 0x630a61fb}, + {5, 0x63be08b1}, + {5, 0x63be08b3}, + {1, 0x64ed27e5}, + {2, 0x65201989}, + {2, 0x65201a09}, + {1, 0x66c0b10a}, + {2, 0x679e1205}, + {6, 0x6bb745c9}, + {2, 0x6d8f8f8a}, + {0, 0x6e4d50af}, + {1, 0x6eaa1da8}, + {1, 0x72a4f34e}, + {1, 0x73999a23}, + {6, 0x74af0a74}, + {2, 0x753be4a5}, + {6, 0x794c3e28}, + {1, 0x7df75834}, + {1, 0x7f2d0a2e}, + {1, 0x82f48073}, + {1, 0x841ce10f}, + {-1, 0x844b55b5}, + {1, 0x863e1ca7}, + {-1, 0x86b1593e}, + {1, 0x8805ffea}, + {1, 0x8d5735b2}, + {1, 0x8d5735b3}, + {-1, 0x8ec3e124}, + {2, 0x93d11f7b}, + {2, 0x93d11ffb}, + {2, 0x93d1ff7b}, + {2, 0x9551177b}, + {2, 0x955117fb}, + {2, 0x95cd0062}, + {1, 0x97d1b58a}, + {2, 0xa2d0f88e}, + {1, 0xa346a5cc}, + {2, 0xaa86cb1d}, + {2, 0xaae4a5b9}, + {2, 0xad0a6292}, + {2, 0xad0a6312}, + {0, 0xae08d5b9}, + {1, 0xb1821ed3}, + {1, 0xb4577b9c}, + {0, 0xb54e7f93}, + {2, 0xb62f900f}, + {2, 0xba65ea1e}, + {8, 0xba86cb1d}, + {0, 0xbc03e969}, + {2, 0xbc45382e}, + {1, 0xbe78677c}, + {1, 0xbed8b069}, + {1, 0xc3704e41}, + {1, 0xc46dbc3d}, + {1, 0xc99a4c6c}, + {2, 0xc901ce73}, + {2, 0xc901cef3}, + {2, 0xcb8c9b6c}, + {1, 0xcee7920f}, + {2, 0xcfa35a45}, + {1, 0xd1663234}, + {6, 0xd20dedbf}, + {1, 0xd2a9f59c}, + {1, 0xd41db5f7}, + {0, 0xd5604971}, + {1, 0xd57049a5}, + {-1, 0xd5c4dc96}, + {0, 0xd5d68b1f}, + {1, 0xd802ec04}, + {2, 0xda13ab96}, + {2, 0xde7d67d4}, + {2, 0xe1290fa2}, + {0, 0xe41ec47e}, + {2, 0xe65cb4ad}, + {1, 0xe89c2b92}, + {1, 0xe9231df2}, + {1, 0xec040469}, + {1, 0xee47381b}, + {1, 0xef54ee35}, + {-1, 0xf9893f70}, + {1, 0xfb816260}, + {-1, 0xff372492} +}; + +// ZIGGY +// depth save/restore variables +// 0 : normal mode +// 1 : writing in normal depth buffer +// 2 : writing in alternate depth buffer +static int render_depth_mode; + +// ** 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 rsp_reserved0(); +static void rsp_reserved1(); +static void rsp_reserved2(); +static void rsp_reserved3(); + +static void ys_memrect(); + +BYTE microcode[4096]; +DWORD uc_crc; +void microcheck (); + +// ** 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 "ucode.h" + +static BOOL reset = 0; +static int old_ucode = -1; + +// rdp_reset - resets the RDP_E +void rdp_reset () +{ + reset = 1; + + rdp.model_i = 0; + + rdp.n_cached[0] = 0; + rdp.n_cached[1] = 0; + rdp.cur_cache[0] = NULL; + rdp.cur_cache[1] = NULL; + /* + rdp.tmem_ptr[0] = offset_textures; + rdp.tmem_ptr[1] = offset_textures; + if (grTextureBufferExt) + rdp.tmem_ptr[1] = TEXMEM_2MB_EDGE * 2; + */ + rdp.c_a0 = 0; + rdp.c_b0 = 0; + rdp.c_c0 = 0; + rdp.c_d0 = 0; + rdp.c_Aa0 = 0; + rdp.c_Ab0 = 0; + rdp.c_Ac0 = 0; + rdp.c_Ad0 = 0; + + rdp.c_a1 = 0; + rdp.c_b1 = 0; + rdp.c_c1 = 0; + rdp.c_d1 = 0; + rdp.c_Aa1 = 0; + rdp.c_Ab1 = 0; + rdp.c_Ac1 = 0; + rdp.c_Ad1 = 0; + + // Clear the palette CRC + int i; + for (i=0; i<16; i++) + rdp.pal_8_crc[i] = 0; + + // Clear the palettes + for (i=0; i<256; i++) + rdp.pal_8[i] = 0; + + rdp.tlut_mode = 0; + + // Clear all segments ** VERY IMPORTANT FOR ZELDA ** + for (i=0; i<16; i++) + rdp.segment[i] = 0; + + for (i=0; i<512; i++) + rdp.addr[i] = 0; + + // set all vertex numbers + for (i=0; i>2; i++) + { + uc_crc += ((DWORD*)microcode)[i]; + } + + FRDP_E ("crc: %08lx\n", uc_crc); + +#ifdef LOG_UCODE + std::ofstream ucf; + ucf.open ("ucode.txt", ios::out | ios::binary); + char d; + for (i=0; i<0x400000; i++) + { + d = ((char*)gfx.RDRAM)[i^3]; + ucf.write (&d, 1); + } + ucf.close (); +#endif + + char str[9]; + sprintf (str, "%08lx", (unsigned long)uc_crc); + + FRDP("ucode = %s\n", str); + int uc = LookupUcode(uc_crc); + WriteLog(M64MSG_INFO, "ucode = %d\n", uc); + if (uc == -2 && ucode_error_report) + { + Config_Open(); + settings.ucode = Config_ReadInt ("ucode", "Force microcode", 0, FALSE, FALSE); + + ReleaseGfx (); + WriteLog(M64MSG_ERROR, "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) + { + Config_Open(); + settings.ucode = Config_ReadInt ("ucode", "Force microcode", 0, FALSE, FALSE); + + ReleaseGfx (); + WriteLog(M64MSG_ERROR, "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); + } +} + +void drawNoFullscreenMessage() +{ + LOG ("drawNoFullscreenMessage ()\n"); +} + +static WORD yuv_to_rgb(BYTE y, BYTE u, BYTE v) +{ + float r = y + (1.370705f * (v-128)); + float g = y - (0.698001f * (v-128)) - (0.337633f * (u-128)); + float b = y + (1.732446f * (u-128)); + r *= 0.125f; + g *= 0.125f; + b *= 0.125f; + //clipping the result + if (r > 32) r = 32; + if (g > 32) g = 32; + if (b > 32) b = 32; + if (r < 0) r = 0; + if (g < 0) g = 0; + if (b < 0) b = 0; + + WORD c = (WORD)(((WORD)(r) << 11) | + ((WORD)(g) << 6) | + ((WORD)(b) << 1) | 1); + return c; +} + +static void DrawYUVImageToFrameBuffer() +{ + WORD width = (WORD)(rdp.yuv_lr_x - rdp.yuv_ul_x); + WORD height = (WORD)(rdp.yuv_lr_y - rdp.yuv_ul_y); + DWORD * mb = (DWORD*)(gfx.RDRAM+rdp.yuv_im_begin); //pointer to the first macro block + WORD * cimg = (WORD*)(gfx.RDRAM+rdp.cimg); + //yuv macro block contains 16x16 texture. we need to put it in the proper place inside cimg + for (WORD y = 0; y < height; y+=16) + { + for (WORD x = 0; x < width; x+=16) + { + WORD *dst = cimg + x + y * rdp.ci_width; + for (WORD h = 0; h < 16; h++) + { + for (WORD w = 0; w < 8; w++) + { + DWORD t = *(mb++); //each DWORD contains 2 pixels + if ((x < rdp.ci_width) && (y < rdp.ci_height)) //clipping. texture image may be larger than color image + { + BYTE y0 = (BYTE)t&0xFF; + BYTE v = (BYTE)(t>>8)&0xFF; + BYTE y1 = (BYTE)(t>>16)&0xFF; + BYTE u = (BYTE)(t>>24)&0xFF; + *(dst++) = yuv_to_rgb(y0, u, v); + *(dst++) = yuv_to_rgb(y1, u, v); + } + } + dst += rdp.ci_width - 16; + } + mb += 64; //macro block is 768 bytes long, last 256 bytes are useless + } + } +} + +static DWORD d_ul_x, d_ul_y, d_lr_x, d_lr_y; + +typedef struct { + int ul_x, ul_y, lr_x, lr_y; +} FB_PART; + +static void DrawPart(int scr_ul_x, int scr_ul_y, int prt_ul_x, int prt_ul_y, int width, int height, float scale_x, float scale_y) +{ + WORD * dst = new WORD[width*height]; + DWORD shift = ((d_ul_y+prt_ul_y) * rdp.ci_width + d_ul_x + prt_ul_x) << 1; + WORD * src = (WORD*)(gfx.RDRAM+rdp.cimg+shift); + WORD c; + for (int y=0; y < height; y++) + { + for (int x=0; x < width; x++) + { + c = src[(int(x*scale_x)+int(y*scale_y)*rdp.ci_width)^1]; + dst[x+y*width] = c?((c >> 1) | 0x8000):0; + } + } + + grLfbWriteRegion(GR_BUFFER_BACKBUFFER, + scr_ul_x, + scr_ul_y, + GR_LFB_SRC_FMT_1555, + width, + height, + FXTRUE, + width<<1, + dst); + delete[] dst; +} + +static void DrawFrameBufferToScreen() +{ + FRDP("DrawFrameBufferToScreen. cimg: %08lx, ul_x: %d, uly: %d, lr_x: %d, lr_y: %d\n", rdp.cimg, d_ul_x, d_ul_y, d_lr_x, d_lr_y); + if (!fullscreen) + return; + grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_NONE, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_NONE, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + grConstantColorValue (0xFFFFFFFF); + grAlphaBlendFunction( GR_BLEND_SRC_ALPHA, + GR_BLEND_ONE_MINUS_SRC_ALPHA, + GR_BLEND_ONE, + GR_BLEND_ZERO); + rdp.update |= UPDATE_COMBINE; + + float scale_x_dst = (float)settings.scr_res_x / rdp.vi_width;//(float)max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width); + float scale_y_dst = (float)settings.scr_res_y / rdp.vi_height;//(float)max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound); + float scale_x_src = (float)rdp.vi_width / (float)settings.scr_res_x;//(float)max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width); + float scale_y_src = (float)rdp.vi_height / (float)settings.scr_res_y;//(float)max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound); + int src_width = d_lr_x - d_ul_x + 1; + int src_height = d_lr_y - d_ul_y + 1; + int dst_width, dst_height, ul_x, ul_y; + + if (!settings.fb_optimize_write || ((src_width < 33) && (src_height < 33))) + { + dst_width = int(src_width*scale_x_dst); + dst_height = int(src_height*scale_y_dst); + ul_x = int(d_ul_x*scale_x_dst); + ul_y = int(d_ul_y*scale_y_dst); + DrawPart(ul_x, ul_y, 0, 0, dst_width, dst_height, scale_x_src, scale_y_src); + memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size); + return; + } + + FB_PART parts[8]; + int p; + for (p = 0; p < 8; p++) + { + parts[p].lr_x = parts[p].lr_y = 0; + parts[p].ul_x = parts[p].ul_y = 0xFFFF; + } + + int num_of_parts = 0; + int cur_part = 0; + int most_left = d_ul_x; + int most_right = d_lr_x; + DWORD shift = (d_ul_y * rdp.ci_width + d_ul_x) << 1; + WORD * src = (WORD*)(gfx.RDRAM+rdp.cimg+shift); + for (int h = 0; h < src_height; h++) + { + cur_part = 0; + int w = 0; + while (w < src_width) + { + while (w < src_width) + { + if (src[(w+h*rdp.ci_width)^1] == 0) + w++; + else + break; + } + if (w == src_width) + break; + if (num_of_parts == 0) //first part + { + parts[0].ul_x = w; + most_left = w; + parts[0].ul_y = h; + cur_part = 0; + } + else if (w < most_left - 2) //new part + { + parts[num_of_parts].ul_x = w; + most_left = w; + parts[num_of_parts].ul_y = h; + cur_part = num_of_parts; + num_of_parts++; + } + else if (w > most_right + 2) //new part + { + parts[num_of_parts].ul_x = w; + most_right = w; + parts[num_of_parts].ul_y = h; + cur_part = num_of_parts; + num_of_parts++; + } + else + { + for (p = 0; p < num_of_parts; p++) + { + if ((w > parts[p].ul_x - 2) && (w < parts[p].lr_x+2)) + { + if (w < parts[p].ul_x) parts[p].ul_x = w; + break; + } + } + cur_part = p; + } + while (w < src_width) + { + if (src[(w+h*rdp.ci_width)^1] != 0) + w++; + else + break; + } + if (num_of_parts == 0) //first part + { + parts[0].lr_x = w; + most_right = w; + num_of_parts++; + } + else + { + if (parts[cur_part].lr_x < w) parts[cur_part].lr_x = w; + if (most_right < w) most_right = w; + parts[cur_part].lr_y = h; + } + } + } + /* + for (p = 0; p < num_of_parts; p++) + { + FRDP("part#%d ul_x: %d, ul_y: %d, lr_x: %d, lr_y: %d\n", p, parts[p].ul_x, parts[p].ul_y, parts[p].lr_x, parts[p].lr_y); + } + */ + for (p = 0; p < num_of_parts; p++) + { + dst_width = int((parts[p].lr_x-parts[p].ul_x + 1)*scale_x_dst); + dst_height = int((parts[p].lr_y-parts[p].ul_y + 1)*scale_y_dst); + ul_x = int((d_ul_x+parts[p].ul_x)*scale_x_dst); + ul_y = int((d_ul_y+parts[p].ul_y)*scale_y_dst); + DrawPart(ul_x, ul_y, parts[p].ul_x, parts[p].ul_y, dst_width, dst_height, scale_x_src, scale_y_src); + } + memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size); +} + +#define RGBA16TO32(color) \ + ((color&1)?0xFF:0) | \ + ((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | \ + ((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | \ +((DWORD)((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. + + int width = rdp.ci_width;//*gfx.VI_WIDTH_REG; + int height; + if (settings.fb_smart && !settings.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.PPL) + height -= rdp.ci_upper_bound; + } + FRDP ("width: %d, height: %d... ", width, height); + + if (rdp.scale_x < 1.1f) + { + WORD * ptr_src = new WORD[width*height]; + if (grLfbReadRegion(buffer, + 0, + 0,//rdp.ci_upper_bound, + width, + height, + width<<1, + ptr_src)) + { + WORD *ptr_dst = (WORD*)(gfx.RDRAM+rdp.cimg); + DWORD *ptr_dst32 = (DWORD*)(gfx.RDRAM+rdp.cimg); + WORD c; + + for (int y=0; y 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); + } + } + /* + } + else //8bit I or CI + { + BYTE *ptr_dst = (BYTE*)(gfx.RDRAM+rdp.cimg); + WORD c; + + for (int y=0; y>5)&0x3F)/63.0f*85.0f); + BYTE r = (BYTE)((float)((c>>11)&0x1F)/31.0f*85.0f); + c = (c&0xFFC0) | ((c&0x001F) << 1) | 1; + // FRDP("src: %08lx, dst: %d\n",c,(BYTE)(r+g+b)); + ptr_dst[(x + y * width)^1] = (BYTE)(r+g+b); + // ptr_dst[(x + y * width)^1] = (BYTE)((c>>8)&0xFF); + } + } + } */ + RDP ("ReadRegion. Framebuffer copy complete.\n"); + } + else + { + RDP ("Framebuffer copy failed.\n"); + } + delete[] ptr_src; + } + else + { + if (rdp.motionblur && settings.fb_hires) + { + return; + } + else + { + float scale_x = (float)settings.scr_res_x / rdp.vi_width;//(float)max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width); + float scale_y = (float)settings.scr_res_y / rdp.vi_height;//(float)max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound); + + 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); + GrLfbInfo_t info; + info.size = sizeof(GrLfbInfo_t); + + + // VP 888 disconnected for now + if (1||rdp.ci_size <= 2) { + if (grLfbLock (GR_LFB_READ_ONLY, + buffer, + GR_LFBWRITEMODE_565, + GR_ORIGIN_UPPER_LEFT, + FXFALSE, + &info)) + { + WORD *ptr_src = (WORD*)info.lfbPtr; + WORD *ptr_dst = (WORD*)(gfx.RDRAM+rdp.cimg); + DWORD *ptr_dst32 = (DWORD*)(gfx.RDRAM+rdp.cimg); + WORD c; + DWORD stride = info.strideInBytes>>1; + + BOOL read_alpha = settings.fb_read_alpha; + if (settings.PM && rdp.frame_buffers[rdp.ci_count-1].status != ci_aux) + read_alpha = FALSE; + for (int y=0; y>1; + + for (int y=0; y 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, (*(DWORD*)(gfx.DMEM+0x0FE4))>>6); + if (rdp.model_stack_size == 0) + rdp.model_stack_size = 32; + 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; + fbreads_front = fbreads_back = 0; + rdp.fog_multiplier = rdp.fog_offset = 0; + rdp.zsrc = 0; + + if (cpu_fb_write == TRUE) + DrawFrameBufferToScreen(); + 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; + + //analize possible frame buffer usage + if (settings.fb_smart) + DetectFrameBufferUsage(); + if (!settings.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 + DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0); + DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4); + FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_lenght: %d\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length); + FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG); + + if (settings.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; + DWORD a; + + // catches exceptions so that it doesn't freeze +#ifdef CATCH_EXCEPTIONS + try { +#endif + + // 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 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit + rdp.cmd1 = ((DWORD*)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 + QueryPerformanceCounter ((LARGE_INTEGER*)&perf_cur); +#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; + + RDP ("End of DL\n"); + rdp.pc_i --; + } + } + +#ifdef PERFORMANCE + QueryPerformanceCounter ((LARGE_INTEGER*)&perf_next); + __int64 t = perf_next-perf_cur; + sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, t); + rdp_log << out_buf; +#endif + + } while (!rdp.halt); +#ifdef CATCH_EXCEPTIONS + } catch (...) { + + if (fullscreen) ReleaseGfx (); + WriteLog(M64MSG_ERROR, "The GFX plugin caused an exception and has been disabled."); + exception = TRUE; + } +#endif + + if (settings.fb_smart) + { + rdp.scale_x = rdp.scale_x_bak; + rdp.scale_y = rdp.scale_y_bak; + } + if (settings.fb_read_always) + { + CopyFrameBuffer (); + } + if (rdp.yuv_image) + { + DrawYUVImageToFrameBuffer(); + rdp.yuv_image = FALSE; +// FRDP("yuv image draw. ul_x: %f, ul_y: %f, lr_x: %f, lr_y: %f, begin: %08lx\n", +// rdp.yuv_ul_x, rdp.yuv_ul_y, rdp.yuv_lr_x, rdp.yuv_lr_y, rdp.yuv_im_begin); + rdp.yuv_ul_x = rdp.yuv_ul_y = rdp.yuv_lr_x = rdp.yuv_lr_y = 0; + rdp.yuv_im_begin = 0x00FFFFFF; + } + if (rdp.cur_image) + CloseTextureBuffer(rdp.read_whole_frame && (settings.PM || rdp.swap_ci_index >= 0)); + + if (settings.TGR2 && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET) + { + newSwapBuffers (); + CI_SET = FALSE; + } + RDP("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 _FINAL_RELEASE_ + *gfx.MI_INTR_REG |= 0x20; + gfx.CheckInterrupts(); + rdp.halt = 1; + #endif +} + +// spnoop - no operation, always ignore +static void spnoop() +{ + RDP("spnoop\n"); +} + +// noop - no operation, always ignore +static void rdp_noop() +{ + RDP("noop\n"); +} + +static void ys_memrect () +{ + DWORD tile = (WORD)((rdp.cmd1 & 0x07000000) >> 24); + + DWORD lr_x = (WORD)((rdp.cmd0 & 0x00FFF000) >> 14); + DWORD lr_y = (WORD)((rdp.cmd0 & 0x00000FFF) >> 2); + DWORD ul_x = (WORD)((rdp.cmd1 & 0x00FFF000) >> 14); + DWORD ul_y = (WORD)((rdp.cmd1 & 0x00000FFF) >> 2); + + rdp.pc[rdp.pc_i] += 16; // texrect is 196-bit + + if (lr_y > rdp.scissor_o.lr_y) lr_y = rdp.scissor_o.lr_y; + + FRDP ("memrect (%d, %d, %d, %d), ci_width: %d\n", ul_x, ul_y, lr_x, lr_y, rdp.ci_width); + + DWORD y, width = lr_x - ul_x; + DWORD texaddr = rdp.addr[rdp.tiles[tile].t_mem]; + DWORD tex_width = rdp.tiles[tile].line << 3; + + for (y = ul_y; y < lr_y; y++) { + BYTE *src = gfx.RDRAM + texaddr + (y - ul_y) * tex_width; + BYTE *dst = gfx.RDRAM + rdp.cimg + ul_x + y * rdp.ci_width; + memcpy (dst, src, width); + } +} + +static void pm_palette_mod () +{ + BYTE envr = (BYTE)((float)((rdp.env_color >> 24)&0xFF)/255.0f*31.0f); + BYTE envg = (BYTE)((float)((rdp.env_color >> 16)&0xFF)/255.0f*31.0f); + BYTE envb = (BYTE)((float)((rdp.env_color >> 8)&0xFF)/255.0f*31.0f); + WORD env16 = (WORD)((envr<<11)|(envg<<6)|(envb<<1)|1); + BYTE prmr = (BYTE)((float)((rdp.prim_color >> 24)&0xFF)/255.0f*31.0f); + BYTE prmg = (BYTE)((float)((rdp.prim_color >> 16)&0xFF)/255.0f*31.0f); + BYTE prmb = (BYTE)((float)((rdp.prim_color >> 8)&0xFF)/255.0f*31.0f); + WORD prim16 = (WORD)((prmr<<11)|(prmg<<6)|(prmb<<1)|1); + WORD * dst = (WORD*)(gfx.RDRAM+rdp.cimg); + for (int i = 0; i < 16; i++) + { + dst[i^1] = (rdp.pal_8[i]&1) ? prim16 : env16; + } + RDP("Texrect palette modification\n"); +} + +static void rdp_texrect() +{ + DWORD a = rdp.pc[rdp.pc_i]; + rdp.cmd2 = ((DWORD*)gfx.RDRAM)[(a>>2)+1]; + rdp.cmd3 = ((DWORD*)gfx.RDRAM)[(a>>2)+3]; + + if (settings.ASB) //modified Rice's hack for All-Star Baseball games + { + DWORD dwHalf1 = (((DWORD*)gfx.RDRAM)[(a>>2)+0]) >> 24; + if ((dwHalf1 != 0xF1) && (dwHalf1 != 0xb3)) + { + rdp.pc[rdp.pc_i] += 16; + } + else + { + rdp.pc[rdp.pc_i] += 8; + rdp.cmd3 = rdp.cmd2; + rdp.cmd2 = 0; + } + } + else if (settings.yoshi && settings.ucode == 6) + { + ys_memrect(); + return; + } + else + { + rdp.pc[rdp.pc_i] += 16; // texrect is 196-bit + } + + if (rdp.skip_drawing || (!settings.fb_smart && (rdp.cimg == rdp.zimg))) + { + if (settings.PM && rdp.ci_status == ci_useless) + { + pm_palette_mod (); + } + else + { + RDP("Texrect skipped\n"); + } + return; + } + + if ((settings.ucode == 8) && 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); + RDP("Shadow texrect is skipped.\n"); + rdp.tri_n += 2; + return; + } + + WORD ul_x = (WORD)((rdp.cmd1 & 0x00FFF000) >> 14); + WORD ul_y = (WORD)((rdp.cmd1 & 0x00000FFF) >> 2); + WORD lr_x = (WORD)((rdp.cmd0 & 0x00FFF000) >> 14); + WORD lr_y = (WORD)((rdp.cmd0 & 0x00000FFF) >> 2); + if (ul_x >= lr_x) return; + if (rdp.cycle_mode > 1 || settings.increase_texrect_edge) + { + lr_x++; + lr_y++; + } + if (ul_y == lr_y) + { + lr_y ++; + } + + //* + if (rdp.hires_tex && settings.fb_optimize_texrect) + { + if (!rdp.hires_tex->drawn) + { + DRAWIMAGE d; + d.imageX = 0; + d.imageW = (WORD)rdp.hires_tex->width; + d.frameX = ul_x; + d.frameW = (WORD)(rdp.hires_tex->width);//(WORD)(ul_x + rdp.hires_tex->width);//lr_x; + + d.imageY = 0; + d.imageH = (WORD)rdp.hires_tex->height; + d.frameY = ul_y; + d.frameH = (WORD)(rdp.hires_tex->height);//(ul_y + rdp.hires_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.hires_tex->width, rdp.hires_tex->height); + d.scaleX = 1.0f; + d.scaleY = 1.0f; + DrawHiresImage(&d, rdp.hires_tex->width == rdp.ci_width); + rdp.hires_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.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 (!settings.fb_hires && ((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 == 7) && (rdp.maincimg[1].addr != rdp.maincimg[0].addr) && (rdp.timg.addr >= rdp.maincimg[1].addr) && (rdp.timg.addr < (rdp.maincimg[1].addr+rdp.ci_width*rdp.ci_height*rdp.ci_size))) + { + if (settings.fb_smart) + if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self || !settings.fb_motionblur) + { + // 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); + RDP("Wrong Texrect.\n"); + rdp.tri_n += 2; + return; + } + } +//*/ + + int i; + + DWORD tile = (WORD)((rdp.cmd1 & 0x07000000) >> 24); + + // update MUST be at the beginning, b/c of update_scissor + if (rdp.cycle_mode == 2) + { + rdp.tex = 1; + rdp.allow_combine = 0; + + cmb.tmu1_func = cmb.tmu0_func = GR_COMBINE_FUNCTION_LOCAL; + cmb.tmu1_fac = cmb.tmu0_fac = GR_COMBINE_FACTOR_NONE; + cmb.tmu1_a_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_LOCAL; + cmb.tmu1_a_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_NONE; + cmb.tmu1_invert = cmb.tmu0_invert = FXFALSE; + cmb.tmu1_a_invert = cmb.tmu0_a_invert = FXFALSE; + } + + rdp.texrecting = 1; + + DWORD prev_tile = rdp.cur_tile; + rdp.cur_tile = tile; + rdp.update |= UPDATE_COMBINE; + update (); + + rdp.texrecting = 0; + rdp.allow_combine = 1; + + if (!rdp.cur_cache[0]) + { + rdp.cur_tile = prev_tile; + rdp.tri_n += 2; + return; + } + // **** + // ** Texrect offset by Gugaman ** + float off_x = (float)((short)((rdp.cmd2 & 0xFFFF0000) >> 16)) / 32.0f; + if ((int(off_x) == 512) && (rdp.timg.width < 512)) off_x = 0.0f; + float off_y = (float)((short)(rdp.cmd2 & 0x0000FFFF)) / 32.0f; + float dsdx = (float)((short)((rdp.cmd3 & 0xFFFF0000) >> 16)) / 1024.0f; + float dtdy = (float)((short)(rdp.cmd3 & 0x0000FFFF)) / 1024.0f; + + 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 (%d, %d, %d, %d), tile: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, tile, rdp.tri_n, rdp.tri_n+1); + 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, off_y, dsdx, dtdy); + + float off_size_x; + float off_size_y; + + if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip + { + off_size_x = (float)((lr_y - ul_y - 1) * dsdx); + off_size_y = (float)((lr_x - ul_x - 1) * dtdy); + } + else + { + off_size_x = (float)((lr_x - ul_x - 1) * dsdx); + off_size_y = (float)((lr_y - ul_y - 1) * dtdy); + } + + float lr_u0, lr_v0, ul_u0, ul_v0, lr_u1, lr_v1, ul_u1, ul_v1; + + if (rdp.cur_cache[0] && (rdp.tex & 1)) + { + float sx=1, sy=1; + if (rdp.tiles[rdp.cur_tile].shift_s) + { + if (rdp.tiles[rdp.cur_tile].shift_s > 10) + sx = (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s)); + else + sx = (float)1.0f/(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) + sy = (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t)); + else + sy = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile].shift_t); + } + if (rdp.hires_tex && rdp.hires_tex->tile == 0) + { + off_x += rdp.hires_tex->u_shift;// + rdp.tiles[0].ul_s; //commented for Paper Mario motion blur + off_y += rdp.hires_tex->v_shift;// + rdp.tiles[0].ul_t; + FRDP("hires_tex ul_s: %d, ul_t: %d, off_x: %f, off_y: %f\n", rdp.tiles[0].ul_s, rdp.tiles[0].ul_t, off_x, off_y); + ul_u0 = off_x * sx; + ul_v0 = off_y * sy; + + lr_u0 = ul_u0 + off_size_x * sx; + lr_v0 = ul_v0 + off_size_y * sy; + + ul_u0 *= rdp.hires_tex->u_scale; + ul_v0 *= rdp.hires_tex->v_scale; + lr_u0 *= rdp.hires_tex->u_scale; + lr_v0 *= rdp.hires_tex->v_scale; + FRDP("hires_tex ul_u0: %f, ul_v0: %f, lr_u0: %f, lr_v0: %f\n", ul_u0, ul_v0, lr_u0, lr_v0); + } + else + { + ul_u0 = off_x * sx; + ul_v0 = off_y * sy; + + ul_u0 -= rdp.tiles[rdp.cur_tile].f_ul_s; + ul_v0 -= rdp.tiles[rdp.cur_tile].f_ul_t; + + lr_u0 = ul_u0 + off_size_x * sx; + lr_v0 = ul_v0 + off_size_y * sy; + + ul_u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * ul_u0; + lr_u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * lr_u0; + ul_v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * ul_v0; + lr_v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * lr_v0; + } + } + else + { + ul_u0 = ul_v0 = lr_u0 = lr_v0 = 0; + } + if (rdp.cur_cache[1] && (rdp.tex & 2)) + { + float sx=1, sy=1; + + if (rdp.tiles[rdp.cur_tile+1].shift_s) + { + if (rdp.tiles[rdp.cur_tile+1].shift_s > 10) + sx = (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s)); + else + sx = (float)1.0f/(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) + sy = 1;//(float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t)); + else + sy = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile+1].shift_t); + } + + if (rdp.hires_tex && rdp.hires_tex->tile == 1) + { + off_x += rdp.hires_tex->u_shift;// + rdp.tiles[0].ul_s; //commented for Paper Mario motion blur + off_y += rdp.hires_tex->v_shift;// + rdp.tiles[0].ul_t; + FRDP("hires_tex ul_s: %d, ul_t: %d, off_x: %f, off_y: %f\n", rdp.tiles[0].ul_s, rdp.tiles[0].ul_t, off_x, off_y); + ul_u1 = off_x * sx; + ul_v1 = off_y * sy; + + lr_u1 = ul_u1 + off_size_x * sx; + lr_v1 = ul_v1 + off_size_y * sy; + + ul_u1 *= rdp.hires_tex->u_scale; + ul_v1 *= rdp.hires_tex->v_scale; + lr_u1 *= rdp.hires_tex->u_scale; + lr_v1 *= rdp.hires_tex->v_scale; + FRDP("hires_tex ul_u1: %f, ul_v1: %f, lr_u1: %f, lr_v1: %f\n", ul_u0, ul_v0, lr_u0, lr_v0); + + } + else + { + ul_u1 = off_x * sx; + ul_v1 = off_y * sy; + + ul_u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s; + ul_v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t; + + lr_u1 = ul_u1 + off_size_x * sx; + lr_v1 = ul_v1 + off_size_y * sy; + + ul_u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * ul_u1; + lr_u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * lr_u1; + ul_v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * ul_v1; + lr_v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * lr_v1; + } + } + else + { + ul_u1 = ul_v1 = lr_u1 = lr_v1 = 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, ul_u0, lr_u0, ul_u1, lr_u1, (float)rdp.scissor.ul_x, (float)rdp.scissor.lr_x); + CCLIP2 (s_ul_y, s_lr_y, ul_v0, lr_v0, ul_v1, lr_v1, (float)rdp.scissor.ul_y, (float)rdp.scissor.lr_y); +// CCLIP2 (s_lr_y, s_ul_y, lr_v0, ul_v0, lr_v1, ul_v1, (float)rdp.scissor.ul_y, (float)rdp.scissor.lr_y); + + FRDP (" draw at: (%f, %f) -> (%f, %f)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y); + + // DO NOT SET CLAMP MODE HERE + + float Z = 1.0f; + if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030)) // othermode check makes sure it + // USES the z-buffer. Otherwise it returns bad (unset) values for lot and telescope + //in zelda:mm. + { + FRDP ("prim_depth = %d\n", rdp.prim_depth); + Z = rdp.prim_depth; + if (settings.increase_primdepth) + Z += 8.0f; + Z = ScaleZ(Z); + + grDepthBufferFunction (GR_CMP_LEQUAL); + rdp.update |= UPDATE_ZBUF_ENABLED; + } + else + { + RDP ("no prim_depth used, using 1.0\n"); + } + + VERTEX vstd[4] = { + { s_ul_x, s_ul_y, Z, 1.0f, ul_u0, ul_v0, ul_u1, ul_v1, { 0, 0, 0, 0}, 255 }, + { s_lr_x, s_ul_y, Z, 1.0f, lr_u0, ul_v0, lr_u1, ul_v1, { 0, 0, 0, 0}, 255 }, + { s_ul_x, s_lr_y, Z, 1.0f, ul_u0, lr_v0, ul_u1, lr_v1, { 0, 0, 0, 0}, 255 }, + { s_lr_x, s_lr_y, Z, 1.0f, lr_u0, lr_v0, lr_u1, lr_v1, { 0, 0, 0, 0}, 255 } }; + + if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip + { + vstd[1].u0 = ul_u0; + vstd[1].v0 = lr_v0; + vstd[1].u1 = ul_u1; + vstd[1].v1 = lr_v1; + + vstd[2].u0 = lr_u0; + vstd[2].v0 = ul_v0; + vstd[2].u1 = lr_u1; + vstd[2].v1 = ul_v1; + } + + 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.hires_tex && 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; + + if (settings.ucode == 7) + { + start_u_256 = 0; + end_u_256 = (lr_x - ul_x - 1)>>8; + } + else + { + 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); + vnew = new VERTEX [num_verts_line << 1]; + + n_vertices = num_verts_line << 1; + 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; iu0 *= z->q; + z->v0 *= z->q; + z->u1 *= z->q; + z->v1 *= z->q; + + apply_shade_mods (z); + } + + if (fullscreen) + { + grFogMode (GR_FOG_DISABLE); + + grClipWindow (0, 0, settings.res_x, settings.res_y); + + grCullMode (GR_CULL_DISABLE); + + if (rdp.cycle_mode == 2) + { + grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_NONE, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_NONE, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + grAlphaBlendFunction (GR_BLEND_ONE, + GR_BLEND_ZERO, + GR_BLEND_ZERO, + GR_BLEND_ZERO); + if (rdp.othermode_l & 1) + { + grAlphaTestFunction (GR_CMP_GEQUAL); + grAlphaTestReferenceValue (0x80); + } + else + grAlphaTestFunction (GR_CMP_ALWAYS); + + rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE; + } + + 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 (debug.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; + + if (settings.fog && (rdp.flags & FOG_ENABLED)) + { + grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); + } + rdp.update |= UPDATE_CULL_MODE | UPDATE_VIEWPORT; + } + else + { + rdp.tri_n += 2; + } + + delete[] vnew; +} + +static void rdp_loadsync() +{ + RDP("loadsync - ignored\n"); +} + +static void rdp_pipesync() +{ + RDP("pipesync - ignored\n"); +} + +static void rdp_tilesync() +{ + RDP("tilesync - ignored\n"); +} + +static void rdp_fullsync() +{ + // Set an interrupt to allow the game to continue + *gfx.MI_INTR_REG |= 0x20; + gfx.CheckInterrupts(); + RDP("fullsync\n"); +} + +static void rdp_setkeygb() +{ + RDP_E("setkeygb - IGNORED\n"); + RDP("setkeygb - IGNORED\n"); +} + +static void rdp_setkeyr() +{ + RDP_E("setkeyr - IGNORED\n"); + RDP("setkeyr - IGNORED\n"); +} + +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.K5 = (BYTE)(rdp.cmd1&0x1FF); + RDP_E("setconvert - IGNORED\n"); + RDP("setconvert - IGNORED\n"); +} + +// +// 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(*/(DWORD)(((rdp.cmd0 & 0x00FFF000) >> 14))/*, 320)*/; + rdp.scissor_o.ul_y = /*min(*/(DWORD)(((rdp.cmd0 & 0x00000FFF) >> 2))/*, 240)*/; + rdp.scissor_o.lr_x = /*min(*/(DWORD)(((rdp.cmd1 & 0x00FFF000) >> 14))/*, 320)*/; + rdp.scissor_o.lr_y = /*min(*/(DWORD)(((rdp.cmd1 & 0x00000FFF) >> 2))/*, 240)*/; + + rdp.ci_upper_bound = rdp.scissor_o.ul_y; + rdp.ci_lower_bound = rdp.scissor_o.lr_y; + + 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; +} + +static void rdp_setprimdepth() +{ + rdp.prim_depth = (WORD)((rdp.cmd1 >> 16) & 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] (); \ +} + + RDP("rdp_setothermode\n"); + + if ((settings.ucode == 2) || (settings.ucode == 8)) + { + 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 (DWORD addr, WORD start, WORD count) +{ + RDP ("Loading palette... "); + WORD *dpal = rdp.pal_8 + start; + WORD end = start+count; + // WORD *spal = (WORD*)(gfx.RDRAM + (addr & BMASK)); + + for (WORD i=start; i>= 4; + end = start + (count >> 4); + for (WORD p = start; p < end; p++) + { + rdp.pal_8_crc[p] = CRC_Calculate( 0xFFFFFFFF, &rdp.pal_8[(p << 4)], 32 ); + } + rdp.pal_256_crc = CRC_Calculate( 0xFFFFFFFF, rdp.pal_8_crc, 64 ); + RDP ("Done.\n"); +} + +static void rdp_loadtlut() +{ + DWORD tile = (rdp.cmd1 >> 24) & 0x07; + WORD start = rdp.tiles[tile].t_mem - 256; // starting location in the palettes + // WORD start = ((WORD)(rdp.cmd1 >> 2) & 0x3FF) + 1; + WORD count = ((WORD)(rdp.cmd1 >> 14) & 0x3FF) + 1; // number to copy + + if (rdp.timg.addr + (count<<1) > BMASK) + count = (WORD)((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; +} + +BOOL tile_set = 0; +static void rdp_settilesize() +{ + DWORD 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 = (((WORD)(rdp.cmd0 >> 14)) & 0x03ff); + int ul_t = (((WORD)(rdp.cmd0 >> 2 )) & 0x03ff); + int lr_s = (((WORD)(rdp.cmd1 >> 14)) & 0x03ff); + int lr_t = (((WORD)(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; + + if (tile == 0 && rdp.hires_tex) + //if ((rdp.tiles[tile].size != 2) || ((rdp.timg.width == 1) && (rdp.hires_tex->width != (DWORD)(lr_s+1)))) + if (((rdp.tiles[tile].format == 0) && (rdp.tiles[tile].size != 2)) || ((rdp.timg.width == 1) && (rdp.hires_tex->width != (DWORD)(lr_s+1)))) + rdp.hires_tex = 0; + if (rdp.hires_tex) + { + if (rdp.tiles[tile].format == 0 && rdp.hires_tex->format == 0) + { + if (tile == 1 && (DWORD)rdp.hires_tex->tmu != tile) + SwapTextureBuffer(); + rdp.hires_tex->tile = tile; + rdp.hires_tex->info.format = GR_TEXFMT_RGB_565; + FRDP ("hires_tex: tile: %d\n", tile); + } + else if (tile == 0) + { + rdp.hires_tex->info.format = GR_TEXFMT_ALPHA_INTENSITY_88; + } + } + FRDP ("settilesize: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d\n", + tile, ul_s, ul_t, lr_s, lr_t); +} + +static void CopyswapBlock(int *pDst, unsigned int cnt, unsigned int SrcOffs) +{ + // copy and byteswap a block of 8-byte dwords + int rem = SrcOffs & 3; + if (rem == 0) + { + int *pSrc = (int *) ((uintptr_t) gfx.RDRAM + SrcOffs); + for (unsigned int x = 0; x < cnt; x++) + { + int s1 = bswap32(*pSrc++); + int s2 = bswap32(*pSrc++); + *pDst++ = s1; + *pDst++ = s2; + } + } + else + { + // set source pointer to 4-byte aligned RDRAM location before the start + int *pSrc = (int *) ((uintptr_t) gfx.RDRAM + (SrcOffs & 0xfffffffc)); + // do the first partial 32-bit word + int s0 = bswap32(*pSrc++); + for (int x = 0; x < rem; x++) + s0 >>= 8; + for (int x = 4; x > rem; x--) + { + *((char *) pDst) = s0 & 0xff; + pDst = (int *) ((char *) pDst + 1); + s0 >>= 8; + } + // do one full 32-bit word + s0 = bswap32(*pSrc++); + *pDst++ = s0; + // do 'cnt-1' 64-bit dwords + for (unsigned int x = 0; x < cnt-1; x++) + { + int s1 = bswap32(*pSrc++); + int s2 = bswap32(*pSrc++); + *pDst++ = s1; + *pDst++ = s2; + } + // do last partial 32-bit word + s0 = bswap32(*pSrc++); + for (; rem > 0; rem--) + { + *((char *) pDst) = s0 & 0xff; + pDst = (int *) ((char *) pDst + 1); + s0 >>= 8; + } + } +} + +static void WordswapBlock(int *pDst, unsigned int cnt, unsigned int TileSize) +{ + // Since it's not loading 32-bit textures as the N64 would, 32-bit textures need to + // be swapped by 64-bits, not 32. + if (TileSize == 3) + { + // swapblock64 dst, cnt + for (unsigned int x = 0; x < cnt / 2; x++, pDst += 4) + { + long long s1 = ((long long *) pDst)[0]; + long long s2 = ((long long *) pDst)[1]; + ((long long *) pDst)[0] = s2; + ((long long *) pDst)[1] = s1; + } + } + else + { + // swapblock32 dst, cnt + for (unsigned int x = 0; x < cnt; x++, pDst += 2) + { + int s1 = pDst[0]; + int s2 = pDst[1]; + pDst[0] = s2; + pDst[1] = s1; + } + } +} + +static void rdp_loadblock() +{ + if (rdp.skip_drawing) + { + RDP("loadblock skipped\n"); + return; + } + DWORD tile = (DWORD)((rdp.cmd1 >> 24) & 0x07); + DWORD dxt = (DWORD)(rdp.cmd1 & 0x0FFF); + + rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr; + + // ** DXT is used for swapping every other line + /* double fdxt = (double)0x8000000F/(double)((DWORD)(2047/(dxt-1))); // F for error + DWORD _dxt = (DWORD)fdxt;*/ + + // 0x00000800 -> 0x80000000 (so we can check the sign bit instead of the 11th bit) + DWORD _dxt = dxt << 20; + + DWORD addr = segoffset(rdp.timg.addr) & BMASK; + + // lr_s specifies number of 64-bit words to copy + // 10.2 format + WORD ul_s = (WORD)(rdp.cmd0 >> 14) & 0x3FF; + WORD ul_t = (WORD)(rdp.cmd0 >> 2) & 0x3FF; + WORD lr_s = (WORD)(rdp.cmd1 >> 14) & 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 + + // 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 = (WORD)((BMASK-addr)>>3); + + DWORD offs = rdp.timg.addr; + DWORD cnt = lr_s+1; + if (rdp.tiles[tile].size == 3) + cnt <<= 1; + //FIXME: unused? DWORD start_line = 0; + + // if (lr_s > 0) + rdp.timg.addr += cnt << 3; + + int * pDst = (int *) ((uintptr_t)rdp.tmem+(rdp.tiles[tile].t_mem<<3)); + + // Load the block from RDRAM and byteswap it as it loads + CopyswapBlock(pDst, cnt, offs); + + // now do 32-bit or 64-bit word swapping on every other row of data + int dxt_accum = 0; + while (cnt > 0) + { + // skip over unswapped blocks + do + { + pDst += 2; + if (--cnt == 0) + break; + dxt_accum += _dxt; + } while (!(dxt_accum & 0x80000000)); + // count number of blocks to swap + if (cnt == 0) break; + int swapcnt = 0; + do + { + swapcnt++; + if (--cnt == 0) + break; + dxt_accum += _dxt; + } while (dxt_accum & 0x80000000); + // do 32-bit or 64-bit swap operation on this block + WordswapBlock(pDst, swapcnt, rdp.tiles[tile].size); + pDst += swapcnt * 2; + } + + 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); +} + +static void rdp_loadtile() +{ + if (rdp.skip_drawing) + return; + rdp.timg.set_by = 1; // load tile + + DWORD tile = (DWORD)((rdp.cmd1 >> 24) & 0x07); + if (rdp.tiles[tile].format == 1) + { + rdp.yuv_image = TRUE; + if (rdp.timg.addr < rdp.yuv_im_begin) rdp.yuv_im_begin = rdp.timg.addr; + return; + } + + rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr; + + WORD ul_s = (WORD)((rdp.cmd0 >> 14) & 0x03FF); + WORD ul_t = (WORD)((rdp.cmd0 >> 2 ) & 0x03FF); + WORD lr_s = (WORD)((rdp.cmd1 >> 14) & 0x03FF); + WORD lr_t = (WORD)((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; + // wrong_tile = -1; + } + + if (rdp.hires_tex)// && (rdp.tiles[tile].format == 0)) + { + FRDP("loadtile: hires_tex ul_s: %d, ul_t:%d\n", ul_s, ul_t); + rdp.hires_tex->tile_uls = ul_s; + rdp.hires_tex->tile_ult = ul_t; + } + + if (settings.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; + } + + DWORD height = lr_t - ul_t + 1; // get height + DWORD width = lr_s - ul_s + 1; + + DWORD wid_64 = rdp.tiles[tile].line; + + // CHEAT: it's very unlikely that it loads more than 1 32-bit texture in one command, + // so i don't bother to write in two different places at once. Just load once with + // twice as much data. + if (rdp.tiles[tile].size == 3) + wid_64 <<= 1; + + int line_n = rdp.timg.width; + if (rdp.tiles[tile].size == 0) + line_n >>= 1; + else + line_n <<= (rdp.tiles[tile].size-1); + + int offs = ul_t * line_n; + offs += ul_s << rdp.tiles[tile].size >> 1; + offs += rdp.timg.addr; + if ((unsigned int) offs >= BMASK) + return; + + // check if points to bad location + DWORD size = width * height; + if (rdp.tiles[tile].size == 0) + size >>= 1; + else + size <<= (rdp.tiles[tile].size-1); + + if (offs + line_n*height > BMASK) + height = (BMASK - offs) / line_n; + + int * pDst = (int *) ((uintptr_t)rdp.tmem+(rdp.tiles[tile].t_mem<<3)); + int * pEnd = (int *) ((uintptr_t)rdp.tmem+4096 - (wid_64<<3)); + + for (unsigned int y = 0; y < height; y++) + { + if (pDst > pEnd) break; + CopyswapBlock(pDst, wid_64, offs); + if (y & 1) + { + WordswapBlock(pDst, wid_64, rdp.tiles[tile].size); + } + pDst += wid_64 * 2; + offs += line_n; + } + + 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); +} + +static void rdp_settile() +{ + tile_set = 1; // used to check if we only load the first settilesize + + rdp.first = 0; + + //rdp.cur_tile_n = (DWORD)((rdp.cmd1 >> 24) & 0x07); + //rdp.cur_tile = &rdp.tiles[rdp.cur_tile_n]; + + rdp.last_tile = (DWORD)((rdp.cmd1 >> 24) & 0x07); + TILE *tile = &rdp.tiles[rdp.last_tile]; + + tile->format = (BYTE)((rdp.cmd0 >> 21) & 0x07); + tile->size = (BYTE)((rdp.cmd0 >> 19) & 0x03); + tile->line = (WORD)((rdp.cmd0 >> 9) & 0x01FF); + tile->t_mem = (WORD)(rdp.cmd0 & 0x1FF); + tile->palette = (BYTE)((rdp.cmd1 >> 20) & 0x0F); + tile->clamp_t = (BYTE)((rdp.cmd1 >> 19) & 0x01); + tile->mirror_t = (BYTE)((rdp.cmd1 >> 18) & 0x01); + tile->mask_t = (BYTE)((rdp.cmd1 >> 14) & 0x0F); + tile->shift_t = (BYTE)((rdp.cmd1 >> 10) & 0x0F); + tile->clamp_s = (BYTE)((rdp.cmd1 >> 9) & 0x01); + tile->mirror_s = (BYTE)((rdp.cmd1 >> 8) & 0x01); + tile->mask_s = (BYTE)((rdp.cmd1 >> 4) & 0x0F); + tile->shift_s = (BYTE)(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); +} + +// +// fillrect - fills a rectangle +// + +static void rdp_fillrect() +{ + DWORD ul_x = ((rdp.cmd1 & 0x00FFF000) >> 14); + DWORD ul_y = (rdp.cmd1 & 0x00000FFF) >> 2; + DWORD lr_x = ((rdp.cmd0 & 0x00FFF000) >> 14) + 1; + DWORD lr_y = ((rdp.cmd0 & 0x00000FFF) >> 2) + 1; + if ((rdp.cimg == rdp.zimg) || (settings.fb_smart && rdp.frame_buffers[rdp.ci_count-1].status == ci_zimg)) + { + RDP ("Fillrect - cleared the depth buffer\n"); + if (fullscreen) + { + + grDepthMask (FXTRUE); + grColorMask (FXFALSE, FXFALSE); + grBufferClear (0, 0, 0xFFFF); + grColorMask (FXTRUE, FXTRUE); + rdp.update |= UPDATE_ZBUF_ENABLED; + if (settings.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); + //FIXME:unused? DWORD zi_height = lr_y - ul_y - 1; + // rdp.zi_nb_pixels = rdp.zi_width * zi_height; + rdp.zi_lry = lr_y - 1; + rdp.zi_lrx = lr_x - 1; + // FRDP ("zi_width: %d, zi_height: %d\n", rdp.zi_width, zi_height); + DWORD fillrect_width_in_dwords = (lr_x-ul_x) >> 1; + DWORD zi_width_in_dwords = rdp.zi_width >> 1; + ul_x >>= 1; + DWORD * dst = (DWORD*)(gfx.RDRAM+rdp.cimg); + dst += ul_y * zi_width_in_dwords; + for (DWORD y = ul_y; y < lr_y; y++) + { + for (DWORD x = ul_x; x < fillrect_width_in_dwords; x++) + { + dst[x] = rdp.fill_color; + } + dst += zi_width_in_dwords; + } + } + } + return; + } + + if (rdp.skip_drawing) + { + RDP("Fillrect skipped\n"); + return; + } + + // Update scissor + update_scissor (); + + if ((ul_x > lr_x) || (ul_y > lr_y)) return; + if (settings.bomberman64 && (lr_x == rdp.ci_width) && (rdp.cimg == rdp.ocimg)) //bomberman64 hack + return; + + if (rdp.cur_image && (rdp.cur_image->format != 0) && (rdp.cycle_mode == 3) && (rdp.cur_image->width == lr_x)) + { + DWORD color = rdp.fill_color; + color = ((color&1)?0xFF:0) | + ((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | + ((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | + ((DWORD)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8); + grDepthMask (FXFALSE); + grBufferClear (color, 0, 0xFFFF); + grDepthMask (FXTRUE); + rdp.update |= UPDATE_ZBUF_ENABLED; + return; + } + + 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 + DWORD s_ul_x = (DWORD)min(max(ul_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x); + DWORD s_lr_x = (DWORD)min(max(lr_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x); + DWORD s_ul_y = (DWORD)min(max(ul_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y); + DWORD s_lr_y = (DWORD)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.0f) s_lr_x = 0; + if (s_lr_y < 0.0f) s_lr_y = 0; + if (s_ul_x > (float)settings.res_x) s_ul_x = settings.res_x; + if (s_ul_y > (float)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); + + grClipWindow (0, 0, settings.res_x, settings.res_y); + + float Z = 1.0f; + if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030)) + { + Z = ScaleZ(rdp.prim_depth); + grDepthBufferFunction (GR_CMP_LEQUAL); + // grDepthMask (FXTRUE); + FRDP ("prim_depth = %d\n", rdp.prim_depth); + } + else + { + grDepthBufferFunction (GR_CMP_ALWAYS); + grDepthMask (FXFALSE); + RDP ("no prim_depth used, using 1.0\n"); + } + // 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) + { + DWORD color = (settings.fillcolor_fix) ? rdp.fill_color : (rdp.fill_color >> 16); + + if (settings.PM && rdp.frame_buffers[rdp.ci_count-1].status == ci_aux) + { + //background of auxilary frame buffers must have zero alpha. + //make it black, set 0 alpha to plack pixels on frame buffer read + color = 0; + } + else + { + color = ((color&1)?0xFF:0) | + ((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | + ((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | + ((DWORD)((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); + + rdp.update |= UPDATE_COMBINE; + } + else + { + Combine (); + TexCache (); // (to update combiner) + DWORD cmb_mode_c = (rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF); + DWORD 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]); + } + } + + grAlphaTestFunction (GR_CMP_ALWAYS); + if (grStippleModeExt) + grStippleModeExt(GR_STIPPLE_DISABLE); + + grCullMode(GR_CULL_DISABLE); + + 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 (debug.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; + + if (settings.fog && (rdp.flags & FOG_ENABLED)) + { + grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); + } + + rdp.update |= UPDATE_CULL_MODE | UPDATE_ALPHA_COMPARE | UPDATE_ZBUF_ENABLED; + } + 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 = (BYTE)((rdp.cmd0 >> 20) & 0xF); + rdp.c_b0 = (BYTE)((rdp.cmd1 >> 28) & 0xF); + rdp.c_c0 = (BYTE)((rdp.cmd0 >> 15) & 0x1F); + rdp.c_d0 = (BYTE)((rdp.cmd1 >> 15) & 0x7); + rdp.c_Aa0 = (BYTE)((rdp.cmd0 >> 12) & 0x7); + rdp.c_Ab0 = (BYTE)((rdp.cmd1 >> 12) & 0x7); + rdp.c_Ac0 = (BYTE)((rdp.cmd0 >> 9) & 0x7); + rdp.c_Ad0 = (BYTE)((rdp.cmd1 >> 9) & 0x7); + + rdp.c_a1 = (BYTE)((rdp.cmd0 >> 5) & 0xF); + rdp.c_b1 = (BYTE)((rdp.cmd1 >> 24) & 0xF); + rdp.c_c1 = (BYTE)((rdp.cmd0 >> 0) & 0x1F); + rdp.c_d1 = (BYTE)((rdp.cmd1 >> 6) & 0x7); + rdp.c_Aa1 = (BYTE)((rdp.cmd1 >> 21) & 0x7); + rdp.c_Ab1 = (BYTE)((rdp.cmd1 >> 3) & 0x7); + rdp.c_Ac1 = (BYTE)((rdp.cmd1 >> 18) & 0x7); + rdp.c_Ad1 = (BYTE)((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 = (BYTE)((rdp.cmd0 >> 21) & 0x07); + rdp.timg.size = (BYTE)((rdp.cmd0 >> 19) & 0x03); + rdp.timg.width = (WORD)(1 + (rdp.cmd0 & 0x00000FFF)); + rdp.timg.addr = segoffset(rdp.cmd1); + 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 if (rdp.frame_buffers[rdp.ci_count].status != ci_copy) + CloseTextureBuffer(TRUE); + rdp.fb_drawn = TRUE; + } + } + + if (settings.fb_hires) //search this texture among drawn texture buffers + { + if (settings.zelda) + { + if (rdp.timg.size == 2) + FindTextureBuffer(rdp.timg.addr, rdp.timg.width); + } + else + 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); +} + + +BOOL 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 DWORD swapped_addr = 0; + +static void rdp_setcolorimage() +{ + render_depth_mode = 0; + if (settings.fb_smart && (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-1]; + COLOR_IMAGE & next_fb = rdp.frame_buffers[rdp.ci_count+1]; + 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 (!settings.fb_hires) + { + 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.PM) //tidal wave + OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); + } + else if (!rdp.motionblur && settings.fb_hires && !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 (settings.fb_hires && rdp.read_whole_frame && prev_fb.status == ci_aux) + { + 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.fb_motionblur) + { + if (cur_fb.width == rdp.ci_width) + { + if (CopyTextureBuffer(prev_fb, cur_fb)) + // if (CloseTextureBuffer(TRUE)) + ; + 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)<>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 (settings.fb_hires) + OpenTextureBuffer(cur_fb); + } + break; + case ci_old_copy: + { + if (!rdp.motionblur || settings.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)<>1); + } + //rdp.skip_drawing = TRUE; + } + else + { + memset(gfx.RDRAM+cur_fb.addr, 0, (cur_fb.width*cur_fb.height)<>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: + { + if (!settings.fb_hires && cur_fb.format != 0) + rdp.skip_drawing = TRUE; + else + { + rdp.skip_drawing = FALSE; + if (settings.fb_hires && 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 (!settings.fb_hires && (prev_fb.status == ci_main) && + (prev_fb.width == cur_fb.width)) // for Pokemon Stadium + CopyFrameBuffer (); + } + } + cur_fb.status = ci_aux; + } + break; + case ci_zimg: + // ZIGGY + // Zelda LoT effect save/restore depth buffer + if (cur_fb.addr == rdp.zimg) { + render_depth_mode = 1; + } else { + render_depth_mode = 2; + } + rdp.skip_drawing = TRUE; + break; + case ci_useless: + //case ci_zcopy: + rdp.skip_drawing = TRUE; + break; + case ci_copy_self: + if (settings.fb_hires && (rdp.ci_count <= rdp.copy_ci_index) && (!SwapOK || settings.swapmode == 2)) + OpenTextureBuffer(cur_fb); + rdp.skip_drawing = FALSE; + /* + if (settings.fb_hires) + { + if (SwapOK) + { + rdp.cimg = rdp.frame_buffers[rdp.ci_count].addr; + rdp.maincimg[0].addr = rdp.cimg; + newSwapBuffers(); + SwapOK = FALSE; + OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count]); + } + } + */ + break; + default: + rdp.skip_drawing = FALSE; + } + + if ((rdp.ci_count > 0) && (prev_fb.status >= ci_aux)) //for Pokemon Stadium + { + if (!settings.fb_hires && prev_fb.format == 0) + CopyFrameBuffer (); + } + if (!settings.fb_hires && cur_fb.status == ci_copy) + { + if (!rdp.motionblur && (rdp.num_of_ci > rdp.ci_count+1) && (next_fb.status != ci_aux)) + { + RestoreScale(); + } + } + if (!settings.fb_hires && cur_fb.status == ci_aux) + { + if (cur_fb.format == 0) + { + if (settings.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; + WORD *ptr_dst = new WORD[width*height]; + WORD *ptr_src = (WORD*)(gfx.RDRAM+cur_fb.addr); + WORD c; + + for (int y=0; y> 1) | 0x8000; + ptr_dst[x + y * width] = c; + } + } + grLfbWriteRegion(GR_BUFFER_BACKBUFFER, + 0, + 0, + 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)) + { + BOOL 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) + { + RDP("return to original scale\n"); + rdp.scale_x = rdp.scale_x_bak; + rdp.scale_y = rdp.scale_y_bak; + if (settings.fb_hires && !rdp.read_whole_frame) + CloseTextureBuffer(); + } + if (settings.fb_hires && !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 (settings.fb_smart) + 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; + } + DWORD 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 (format != 0 && !rdp.cur_image) //can't draw into non RGBA buffer + { + if (settings.fb_hires && rdp.ci_width <= 64) + OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count - 1]); + else if (format > 2) + rdp.skip_drawing = TRUE; + return; + } + else + { + if (!settings.fb_smart) + rdp.skip_drawing = FALSE; + } + + CI_SET = TRUE; + if (settings.swapmode > 0) + { + if (rdp.zimg == rdp.cimg) + rdp.updatescreen = 1; + + BOOL 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 (settings.fb_smart) + 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 (settings.fb_hires) + { + 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]); + } + } + } + } +} + +static void rdp_trifill() +{ + RDP_E("trifill - IGNORED\n"); + RDP("trifill - IGNORED\n"); +} + +static void rdp_trishade() +{ + RDP_E("trishade - IGNORED\n"); + RDP("trishade - IGNORED\n"); +} + +static void rdp_tritxtr() +{ + RDP_E("tritxtr - IGNORED\n"); + RDP("tritxtr - IGNORED\n"); +} + +static void rdp_trishadetxtr() +{ + RDP_E("trishadetxtr - IGNORED\n"); + RDP("trishadetxtr - IGNORED\n"); +} + +static void rdp_trifillz() +{ + RDP_E("trifillz - IGNORED\n"); + RDP("trifillz - IGNORED\n"); +} + +static void rdp_trishadez() +{ + RDP_E("trishadez - IGNORED\n"); + RDP("trishadez - IGNORED\n"); +} + +static void rdp_tritxtrz() +{ + RDP_E("tritxtrz - IGNORED\n"); + RDP("tritxtrz - IGNORED\n"); +} + +static void rdp_trishadetxtrz() +{ + RDP_E("trishadetxtrz - IGNORED\n"); + RDP("trishadetxtrz - IGNORED\n"); +} + +static void rsp_reserved0() +{ + RDP_E("reserved0 - IGNORED\n"); + RDP("reserved0 - IGNORED\n"); +} + +static void rsp_reserved1() +{ + RDP("reserved1 - ignored\n"); +} + +static void rsp_reserved2() +{ + RDP("reserved2\n"); +} + +static void rsp_reserved3() +{ + RDP("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); + + //grDepthBufferFunction (GR_CMP_ALWAYS); + //grDepthMask (FXFALSE); + + rdp.update |= UPDATE_COMBINE | UPDATE_ALPHA_COMPARE; +} + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************** +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 = BYTE, 2 = WORD, 4 = DWORD +output: none +*******************************************************************/ +EXPORT void CALL FBRead(unsigned int 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; + DWORD 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)) + { + DWORD cimg = rdp.cimg; + rdp.cimg = rdp.maincimg[1].addr; + if (settings.fb_smart) + { + rdp.ci_width = rdp.maincimg[1].width; + rdp.ci_count = 0; + DWORD 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 +//TODO: remove +/****************************************************************** +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, DWORD size) +{ + LOG ("FBWList ()\n"); + FRDP("FBWList. size: %d\n", size); + printf("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 = BYTE, 2 = WORD, 4 = DWORD +output: none +*******************************************************************/ +EXPORT void CALL FBWrite(unsigned int addr, unsigned int 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; + DWORD a = segoffset(addr); + FRDP("FBWrite. addr: %08lx\n", a); + // ZIGGY : added a test on ci_width, otherwise we crash on zero division below + if (!rdp.ci_width || a < rdp.cimg || a > rdp.ci_end) + return; + cpu_fb_write = TRUE; + DWORD shift_l = (a-rdp.cimg) >> 1; + DWORD 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 +//TODO: remove +typedef struct +{ + DWORD addr; + DWORD size; + DWORD width; + DWORD height; +} FrameBufferInfo; +#endif + +EXPORT void CALL FBGetFrameBufferInfo(void *p) +{ + LOG ("FBGetFrameBufferInfo ()\n"); + FrameBufferInfo * pinfo = (FrameBufferInfo *)p; + memset(pinfo,0,sizeof(FrameBufferInfo)*6); + if (!settings.fb_get_info) + return; + RDP("FBGetFrameBufferInfo ()\n"); + //* + if (settings.fb_smart) + { + 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 () +{ + RDP("DetectFrameBufferUsage\n"); + + DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0); +#ifdef _WIN32 + DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4); +#endif // _WIN32 + DWORD a; + + BOOL tidal = FALSE; + if (settings.PM && (rdp.copy_ci_index || rdp.frame_buffers[rdp.copy_ci_index].status == ci_copy_self)) + tidal = TRUE; + DWORD ci = rdp.cimg, zi = rdp.zimg; // ci_width = rdp.ci_width; + rdp.main_ci = rdp.main_ci_end = rdp.main_ci_bg = rdp.ci_count = 0; + rdp.main_ci_index = rdp.copy_ci_index = 0; + rdp.zimg_end = 0; + rdp.tmpzimg = 0; + rdp.motionblur = FALSE; + rdp.main_ci_last_tex_addr = 0; + BOOL 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 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit + rdp.cmd1 = ((DWORD*)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 ((intptr_t)(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; + + RDP ("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; + } + + BOOL 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; + } + + RDP("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 (!settings.fb_hires || !rdp.copy_ci_index) + rdp.motionblur = TRUE; + if (rdp.motionblur || settings.fb_hires || (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 (settings.fb_hires && !settings.fb_ignore_previous) + { + if (rdp.swap_ci_index < 0) + { + rdp.texbufs[0].clear_allowed = TRUE; + OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); + } + } + else + { + if (rdp.motionblur) + { + if (settings.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; + DWORD 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 (settings.fb_hires) + { + for (i = 0; i < 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) + { + //RDP("Tidal wave!\n"); + rdp.copy_ci_index = rdp.main_ci_index; + } + } + rdp.ci_count = 0; + if (settings.fb_ignore_previous) + rdp.read_whole_frame = FALSE; + else + rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index]; + // rdp.scale_x = rdp.scale_x_bak; + // rdp.scale_y = rdp.scale_y_bak; + RDP("DetectFrameBufferUsage End\n"); +} + + + + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************** +Function: ProcessRDPList +Purpose: This function is called when there is a Dlist to be +processed. (Low level GFX list) +input: none +output: none +*******************************************************************/ +EXPORT void CALL ProcessRDPList(void) +{ + if (settings.KI) + { + *gfx.MI_INTR_REG |= 0x20; + gfx.CheckInterrupts(); + } + LOG ("ProcessRDPList ()\n"); + + no_dlist = FALSE; + update_screen_count = 0; + ChangeSize (); + +#ifdef ALTTAB_FIX + if (!hhkLowLevelKybd) + { + hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL, + LowLevelKeyboardProc, hInstance, 0); + } +#endif + + LOG ("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; + + memset (microcode, 0, 4096); + if (settings.autodetect_ucode) + { + // Thanks to ZeZu for ucode autodetection!!! + + DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0); + memcpy (microcode, gfx.RDRAM+startUcode, 4096); + microcheck (); + + } + } + else if ( ((old_ucode == 6) && (settings.ucode == 1)) || settings.force_microcheck) + { + DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0); + memcpy (microcode, gfx.RDRAM+startUcode, 4096); + microcheck (); + } + + if (exception) return; + + // Switch to fullscreen? + if (to_fullscreen) + { + to_fullscreen = FALSE; + + if (!InitGfx (FALSE)) + { + LOG ("FAILED!!!\n"); + return; + } + fullscreen = TRUE; + } + + // 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, (*(DWORD*)(gfx.DMEM+0x0FE4))>>6); + if (rdp.model_stack_size == 0) + rdp.model_stack_size = 32; + 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; + fbreads_front = fbreads_back = 0; + rdp.fog_multiplier = rdp.fog_offset = 0; + rdp.zsrc = 0; + + if (cpu_fb_write == TRUE) + DrawFrameBufferToScreen(); + 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; + + //analize possible frame buffer usage + if (settings.fb_smart) + DetectFrameBufferUsage(); + if (!settings.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 +// DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0); +// DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4); + DWORD dlist_start = *gfx.DPC_CURRENT_REG; + DWORD dlist_length = *gfx.DPC_END_REG - *gfx.DPC_CURRENT_REG; + FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_lenght: %d\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length); + FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG); + + if (settings.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; + DWORD a; + + // catches exceptions so that it doesn't freeze +#ifdef CATCH_EXCEPTIONS + try { +#endif + + // 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 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit + rdp.cmd1 = ((DWORD*)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 + QueryPerformanceCounter ((LARGE_INTEGER*)&perf_cur); +#endif + // Process this instruction + gfx_instruction[settings.ucode][((rdp.cmd0>>24)&0x3f) + 0x100-0x40] (); + + // check DL counter + if (rdp.dl_count != -1) + { + rdp.dl_count --; + if (rdp.dl_count == 0) + { + rdp.dl_count = -1; + + RDP ("End of DL\n"); + rdp.pc_i --; + } + } + +#ifdef PERFORMANCE + QueryPerformanceCounter ((LARGE_INTEGER*)&perf_next); + __int64 t = perf_next-perf_cur; + sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, t); + rdp_log << out_buf; +#endif + + } while (0); +#ifdef CATCH_EXCEPTIONS + } catch (...) { + + if (fullscreen) ReleaseGfx (); + WriteLog(M64MSG_ERROR, "The GFX plugin caused an exception and has been disabled."); + exception = TRUE; + } +#endif + + if (settings.fb_smart) + { + rdp.scale_x = rdp.scale_x_bak; + rdp.scale_y = rdp.scale_y_bak; + } + if (settings.fb_read_always) + { + CopyFrameBuffer (); + } + if (rdp.yuv_image) + { + DrawYUVImageToFrameBuffer(); + rdp.yuv_image = FALSE; +// FRDP("yuv image draw. ul_x: %f, ul_y: %f, lr_x: %f, lr_y: %f, begin: %08lx\n", +// rdp.yuv_ul_x, rdp.yuv_ul_y, rdp.yuv_lr_x, rdp.yuv_lr_y, rdp.yuv_im_begin); + rdp.yuv_ul_x = rdp.yuv_ul_y = rdp.yuv_lr_x = rdp.yuv_lr_y = 0; + rdp.yuv_im_begin = 0x00FFFFFF; + } + if (rdp.cur_image) + CloseTextureBuffer(rdp.read_whole_frame && (settings.PM || rdp.swap_ci_index >= 0)); + + if (settings.TGR2 && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET) + { + newSwapBuffers (); + CI_SET = FALSE; + } + RDP("ProcessDList end\n"); + + + + + + + WriteLog(M64MSG_VERBOSE, "ProcessRPDList %x %x %x\n", + *gfx.DPC_START_REG, + *gfx.DPC_END_REG, + *gfx.DPC_CURRENT_REG); + //*gfx.DPC_STATUS_REG = 0xffffffff; // &= ~0x0002; + + *gfx.DPC_START_REG = *gfx.DPC_END_REG; + *gfx.DPC_CURRENT_REG = *gfx.DPC_END_REG; +} + +#ifdef __cplusplus +} +#endif + + + + + +// Local Variables: *** +// tab-width:4 *** +// c-file-offset:4 *** +// End: *** +