| 1 | /* |
| 2 | * Glide64 - Glide video plugin for Nintendo 64 emulators. |
| 3 | * Copyright (c) 2002 Dave2001 |
| 4 | * Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; either version 2 of the License, or |
| 9 | * any later version. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU General Public License |
| 17 | * along with this program; if not, write to the Free Software |
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ |
| 20 | |
| 21 | //**************************************************************** |
| 22 | // |
| 23 | // Glide64 - Glide Plugin for Nintendo 64 emulators |
| 24 | // Project started on December 29th, 2001 |
| 25 | // |
| 26 | // Authors: |
| 27 | // Dave2001, original author, founded the project in 2001, left it in 2002 |
| 28 | // Gugaman, joined the project in 2002, left it in 2002 |
| 29 | // Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002 |
| 30 | // Hiroshi 'KoolSmoky' Morii, joined the project in 2007 |
| 31 | // |
| 32 | //**************************************************************** |
| 33 | // |
| 34 | // To modify Glide64: |
| 35 | // * 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. |
| 36 | // * 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. |
| 37 | // |
| 38 | //**************************************************************** |
| 39 | |
| 40 | #include <math.h> |
| 41 | #include "Gfx_1.3.h" |
| 42 | #include "m64p.h" |
| 43 | #include "Ini.h" |
| 44 | #include "Config.h" |
| 45 | #include "3dmath.h" |
| 46 | #include "Util.h" |
| 47 | #include "Debugger.h" |
| 48 | #include "Combine.h" |
| 49 | #include "TexCache.h" |
| 50 | #include "TexBuffer.h" |
| 51 | #include "FBtoScreen.h" |
| 52 | #include "CRC.h" |
| 53 | |
| 54 | #ifdef PAULSCODE |
| 55 | #include "FrameSkipper.h" |
| 56 | extern FrameSkipper frameSkipper; |
| 57 | #endif |
| 58 | |
| 59 | #ifdef PERFORMANCE |
| 60 | #include "ticks.h" |
| 61 | #endif |
| 62 | |
| 63 | #ifdef __ARM_NEON__ |
| 64 | #include "arm_neon.h" |
| 65 | //#include "ticks.h" |
| 66 | #endif |
| 67 | |
| 68 | /* |
| 69 | const int NumOfFormats = 3; |
| 70 | SCREEN_SHOT_FORMAT ScreenShotFormats[NumOfFormats] = { {wxT("BMP"), wxT("bmp"), wxBITMAP_TYPE_BMP}, {wxT("PNG"), wxT("png"), wxBITMAP_TYPE_PNG}, {wxT("JPEG"), wxT("jpeg"), wxBITMAP_TYPE_JPEG} }; |
| 71 | */ |
| 72 | const char *ACmp[] = { "NONE", "THRESHOLD", "UNKNOWN", "DITHER" }; |
| 73 | |
| 74 | const char *Mode0[] = { "COMBINED", "TEXEL0", |
| 75 | "TEXEL1", "PRIMITIVE", |
| 76 | "SHADE", "ENVIORNMENT", |
| 77 | "1", "NOISE", |
| 78 | "0", "0", |
| 79 | "0", "0", |
| 80 | "0", "0", |
| 81 | "0", "0" }; |
| 82 | |
| 83 | const char *Mode1[] = { "COMBINED", "TEXEL0", |
| 84 | "TEXEL1", "PRIMITIVE", |
| 85 | "SHADE", "ENVIORNMENT", |
| 86 | "CENTER", "K4", |
| 87 | "0", "0", |
| 88 | "0", "0", |
| 89 | "0", "0", |
| 90 | "0", "0" }; |
| 91 | |
| 92 | const char *Mode2[] = { "COMBINED", "TEXEL0", |
| 93 | "TEXEL1", "PRIMITIVE", |
| 94 | "SHADE", "ENVIORNMENT", |
| 95 | "SCALE", "COMBINED_ALPHA", |
| 96 | "T0_ALPHA", "T1_ALPHA", |
| 97 | "PRIM_ALPHA", "SHADE_ALPHA", |
| 98 | "ENV_ALPHA", "LOD_FRACTION", |
| 99 | "PRIM_LODFRAC", "K5", |
| 100 | "0", "0", |
| 101 | "0", "0", |
| 102 | "0", "0", |
| 103 | "0", "0", |
| 104 | "0", "0", |
| 105 | "0", "0", |
| 106 | "0", "0", |
| 107 | "0", "0" }; |
| 108 | |
| 109 | const char *Mode3[] = { "COMBINED", "TEXEL0", |
| 110 | "TEXEL1", "PRIMITIVE", |
| 111 | "SHADE", "ENVIORNMENT", |
| 112 | "1", "0" }; |
| 113 | |
| 114 | const char *Alpha0[] = { "COMBINED", "TEXEL0", |
| 115 | "TEXEL1", "PRIMITIVE", |
| 116 | "SHADE", "ENVIORNMENT", |
| 117 | "1", "0" }; |
| 118 | |
| 119 | #define Alpha1 Alpha0 |
| 120 | const char *Alpha2[] = { "LOD_FRACTION", "TEXEL0", |
| 121 | "TEXEL1", "PRIMITIVE", |
| 122 | "SHADE", "ENVIORNMENT", |
| 123 | "PRIM_LODFRAC", "0" }; |
| 124 | #define Alpha3 Alpha0 |
| 125 | |
| 126 | const char *FBLa[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG" }; |
| 127 | const char *FBLb[] = { "G_BL_A_IN", "G_BL_A_FOG", "G_BL_A_SHADE", "G_BL_0" }; |
| 128 | const char *FBLc[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG"}; |
| 129 | const char *FBLd[] = { "G_BL_1MA", "G_BL_A_MEM", "G_BL_1", "G_BL_0" }; |
| 130 | |
| 131 | const char *str_zs[] = { "G_ZS_PIXEL", "G_ZS_PRIM" }; |
| 132 | |
| 133 | const char *str_yn[] = { "NO", "YES" }; |
| 134 | const char *str_offon[] = { "OFF", "ON" }; |
| 135 | |
| 136 | const char *str_cull[] = { "DISABLE", "FRONT", "BACK", "BOTH" }; |
| 137 | |
| 138 | // I=intensity probably |
| 139 | const char *str_format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" }; |
| 140 | const char *str_size[] = { "4bit", "8bit", "16bit", "32bit" }; |
| 141 | const char *str_cm[] = { "WRAP/NO CLAMP", "MIRROR/NO CLAMP", "WRAP/CLAMP", "MIRROR/CLAMP" }; |
| 142 | const char *str_lod[] = { "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "2048" }; |
| 143 | const char *str_aspect[] = { "1x8", "1x4", "1x2", "1x1", "2x1", "4x1", "8x1" }; |
| 144 | |
| 145 | const char *str_filter[] = { "Point Sampled", "Average (box)", "Bilinear" }; |
| 146 | |
| 147 | const char *str_tlut[] = { "TT_NONE", "TT_UNKNOWN", "TT_RGBA_16", "TT_IA_16" }; |
| 148 | |
| 149 | const char *str_dither[] = { "Pattern", "~Pattern", "Noise", "None" }; |
| 150 | |
| 151 | const char *CIStatus[] = { "ci_main", "ci_zimg", "ci_unknown", "ci_useless", |
| 152 | "ci_old_copy", "ci_copy", "ci_copy_self", |
| 153 | "ci_zcopy", "ci_aux", "ci_aux_copy" }; |
| 154 | |
| 155 | //static variables |
| 156 | |
| 157 | char out_buf[2048]; |
| 158 | |
| 159 | wxUint32 frame_count; // frame counter |
| 160 | |
| 161 | int ucode_error_report = TRUE; |
| 162 | int wrong_tile = -1; |
| 163 | |
| 164 | // ** RDP graphics functions ** |
| 165 | static void undef(); |
| 166 | static void spnoop(); |
| 167 | |
| 168 | static void rdp_noop(); |
| 169 | static void rdp_texrect(); |
| 170 | //static void rdp_texrectflip(); |
| 171 | static void rdp_loadsync(); |
| 172 | static void rdp_pipesync(); |
| 173 | static void rdp_tilesync(); |
| 174 | static void rdp_fullsync(); |
| 175 | static void rdp_setkeygb(); |
| 176 | static void rdp_setkeyr(); |
| 177 | static void rdp_setconvert(); |
| 178 | static void rdp_setscissor(); |
| 179 | static void rdp_setprimdepth(); |
| 180 | static void rdp_setothermode(); |
| 181 | static void rdp_loadtlut(); |
| 182 | static void rdp_settilesize(); |
| 183 | static void rdp_loadblock(); |
| 184 | static void rdp_loadtile(); |
| 185 | static void rdp_settile(); |
| 186 | static void rdp_fillrect(); |
| 187 | static void rdp_setfillcolor(); |
| 188 | static void rdp_setfogcolor(); |
| 189 | static void rdp_setblendcolor(); |
| 190 | static void rdp_setprimcolor(); |
| 191 | static void rdp_setenvcolor(); |
| 192 | static void rdp_setcombine(); |
| 193 | static void rdp_settextureimage(); |
| 194 | static void rdp_setdepthimage(); |
| 195 | static void rdp_setcolorimage(); |
| 196 | static void rdp_trifill(); |
| 197 | static void rdp_trishade(); |
| 198 | static void rdp_tritxtr(); |
| 199 | static void rdp_trishadetxtr(); |
| 200 | static void rdp_trifillz(); |
| 201 | static void rdp_trishadez(); |
| 202 | static void rdp_tritxtrz(); |
| 203 | static void rdp_trishadetxtrz(); |
| 204 | static void rdphalf_1(); |
| 205 | static void rdphalf_2(); |
| 206 | static void rdphalf_cont(); |
| 207 | |
| 208 | static void rsp_reserved0(); |
| 209 | static void rsp_reserved1(); |
| 210 | static void rsp_reserved2(); |
| 211 | static void rsp_reserved3(); |
| 212 | |
| 213 | static void ys_memrect(); |
| 214 | |
| 215 | wxUint8 microcode[4096]; |
| 216 | wxUint32 uc_crc; |
| 217 | void microcheck (); |
| 218 | |
| 219 | #ifdef PAULSCODE |
| 220 | #define Check_FrameSkip if (frameSkipper.willSkipNext()) return |
| 221 | #else |
| 222 | #define Check_FrameSkip {} |
| 223 | #endif |
| 224 | |
| 225 | // ** UCODE FUNCTIONS ** |
| 226 | #include "ucode00.h" |
| 227 | #include "ucode01.h" |
| 228 | #include "ucode02.h" |
| 229 | #include "ucode03.h" |
| 230 | #include "ucode04.h" |
| 231 | #include "ucode05.h" |
| 232 | #include "ucode06.h" |
| 233 | #include "ucode07.h" |
| 234 | #include "ucode08.h" |
| 235 | #include "ucode09.h" |
| 236 | #include "ucode.h" |
| 237 | #include "ucode09rdp.h" |
| 238 | #include "turbo3D.h" |
| 239 | |
| 240 | static int reset = 0; |
| 241 | static int old_ucode = -1; |
| 242 | |
| 243 | void RDP::Reset() |
| 244 | { |
| 245 | memset(this, 0, sizeof(RDP_Base)); |
| 246 | // set all vertex numbers |
| 247 | for (int i=0; i<MAX_VTX; i++) |
| 248 | vtx[i].number = i; |
| 249 | |
| 250 | scissor_o.ul_x = 0; |
| 251 | scissor_o.ul_y = 0; |
| 252 | scissor_o.lr_x = 320; |
| 253 | scissor_o.lr_y = 240; |
| 254 | |
| 255 | vi_org_reg = *gfx.VI_ORIGIN_REG; |
| 256 | view_scale[2] = 32.0f * 511.0f; |
| 257 | view_trans[2] = 32.0f * 511.0f; |
| 258 | clip_ratio = 1.0f; |
| 259 | |
| 260 | lookat[0][0] = lookat[1][1] = 1.0f; |
| 261 | |
| 262 | cycle_mode = 2; |
| 263 | allow_combine = 1; |
| 264 | rdp.update = UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE; |
| 265 | fog_mode = RDP::fog_enabled; |
| 266 | maincimg[0].addr = maincimg[1].addr = last_drawn_ci_addr = 0x7FFFFFFF; |
| 267 | |
| 268 | hotkey_info.hk_ref = 90; |
| 269 | hotkey_info.hk_motionblur = (settings.buff_clear == 0)?0:90; |
| 270 | hotkey_info.hk_filtering = hotkey_info.hk_motionblur; |
| 271 | |
| 272 | CheckKeyPressed(G64_VK_BACK, 1); //BACK |
| 273 | CheckKeyPressed(G64_VK_B, 1); |
| 274 | CheckKeyPressed(G64_VK_V, 1); |
| 275 | } |
| 276 | |
| 277 | RDP::RDP() |
| 278 | { |
| 279 | vtx1 = new VERTEX[256]; |
| 280 | memset(vtx1, 0, sizeof(VERTEX)*256); |
| 281 | vtx2 = new VERTEX[256]; |
| 282 | memset(vtx2, 0, sizeof(VERTEX)*256); |
| 283 | vtxbuf = vtxbuf2 = 0; |
| 284 | vtx_buffer = n_global = 0; |
| 285 | |
| 286 | for (int i = 0; i < MAX_TMU; i++) |
| 287 | { |
| 288 | cache[i] = new CACHE_LUT[MAX_CACHE]; |
| 289 | cur_cache[i] = 0; |
| 290 | cur_cache_n[i] = 0; |
| 291 | }; |
| 292 | |
| 293 | vtx = new VERTEX[MAX_VTX]; |
| 294 | memset(vtx, 0, sizeof(VERTEX)*MAX_VTX); |
| 295 | v0 = vn = 0; |
| 296 | |
| 297 | frame_buffers = new COLOR_IMAGE[NUMTEXBUF+2]; |
| 298 | } |
| 299 | |
| 300 | RDP::~RDP() |
| 301 | { |
| 302 | delete[] vtx1; |
| 303 | delete[] vtx2; |
| 304 | for (int i = 0; i < MAX_TMU; i++) |
| 305 | delete[] cache[i]; |
| 306 | |
| 307 | delete[] vtx; |
| 308 | delete[] frame_buffers; |
| 309 | } |
| 310 | |
| 311 | void rdp_reset () |
| 312 | { |
| 313 | reset = 1; |
| 314 | rdp.Reset(); |
| 315 | } |
| 316 | |
| 317 | void microcheck () |
| 318 | { |
| 319 | wxUint32 i; |
| 320 | uc_crc = 0; |
| 321 | |
| 322 | // Check first 3k of ucode, because the last 1k sometimes contains trash |
| 323 | for (i=0; i<3072>>2; i++) |
| 324 | { |
| 325 | uc_crc += ((wxUint32*)microcode)[i]; |
| 326 | } |
| 327 | |
| 328 | FRDP_E ("crc: %08lx\n", uc_crc); |
| 329 | |
| 330 | #ifdef LOG_UCODE |
| 331 | std::ofstream ucf; |
| 332 | ucf.open ("ucode.txt", std::ios::out | std::ios::binary); |
| 333 | char d; |
| 334 | for (i=0; i<0x400000; i++) |
| 335 | { |
| 336 | d = ((char*)gfx.RDRAM)[i^3]; |
| 337 | ucf.write (&d, 1); |
| 338 | } |
| 339 | ucf.close (); |
| 340 | #endif |
| 341 | |
| 342 | FRDP("ucode = %08lx\n", uc_crc); |
| 343 | |
| 344 | Ini * ini = Ini::OpenIni(); |
| 345 | ini->SetPath("UCODE"); |
| 346 | char str[9]; |
| 347 | sprintf (str, "%08lx", (unsigned long)uc_crc); |
| 348 | int uc = ini->Read(str, -2); |
| 349 | |
| 350 | if (uc == -2 && ucode_error_report) |
| 351 | { |
| 352 | settings.ucode = Config_ReadInt("ucode", "Force microcode", 0, TRUE, FALSE); |
| 353 | |
| 354 | ReleaseGfx (); |
| 355 | ERRLOG("Error: uCode crc not found in INI, using currently selected uCode\n\n%08lx", (unsigned long)uc_crc); |
| 356 | |
| 357 | ucode_error_report = FALSE; // don't report any more ucode errors from this game |
| 358 | } |
| 359 | else if (uc == -1 && ucode_error_report) |
| 360 | { |
| 361 | settings.ucode = ini->Read(_T("/SETTINGS/ucode"), 0); |
| 362 | |
| 363 | ReleaseGfx (); |
| 364 | ERRLOG("Error: Unsupported uCode!\n\ncrc: %08lx", (unsigned long)uc_crc); |
| 365 | |
| 366 | ucode_error_report = FALSE; // don't report any more ucode errors from this game |
| 367 | } |
| 368 | else |
| 369 | { |
| 370 | old_ucode = settings.ucode; |
| 371 | settings.ucode = uc; |
| 372 | FRDP("microcheck: old ucode: %d, new ucode: %d\n", old_ucode, uc); |
| 373 | if (uc_crc == 0x8d5735b2 || uc_crc == 0xb1821ed3 || uc_crc == 0x1118b3e0) //F3DLP.Rej ucode. perspective texture correction is not implemented |
| 374 | { |
| 375 | rdp.Persp_en = 1; |
| 376 | rdp.persp_supported = FALSE; |
| 377 | } |
| 378 | else if (settings.texture_correction) |
| 379 | rdp.persp_supported = TRUE; |
| 380 | } |
| 381 | } |
| 382 | |
| 383 | #ifdef __WINDOWS__ |
| 384 | static void GetClientSize(int * width, int * height) |
| 385 | { |
| 386 | #ifdef __WINDOWS__ |
| 387 | RECT win_rect; |
| 388 | GetClientRect (gfx.hWnd, &win_rect); |
| 389 | *width = win_rect.right; |
| 390 | *height = win_rect.bottom; |
| 391 | #else |
| 392 | GFXWindow->GetClientSize(width, height); |
| 393 | #endif |
| 394 | } |
| 395 | #endif |
| 396 | |
| 397 | void drawNoFullscreenMessage() |
| 398 | { |
| 399 | //need to find, how to do it on non-windows OS |
| 400 | //the code below will compile on any OS |
| 401 | //but it works only on windows, because |
| 402 | //I don't know, how to initialize GFXWindow on other OS |
| 403 | #ifdef __WINDOWS__ |
| 404 | LOG ("drawNoFullscreenMessage ()\n"); |
| 405 | if (rdp.window_changed) |
| 406 | { |
| 407 | rdp.window_changed = FALSE; |
| 408 | int width, height; |
| 409 | GetClientSize(&width, &height); |
| 410 | |
| 411 | wxClientDC dc(GFXWindow); |
| 412 | dc.SetBrush(*wxMEDIUM_GREY_BRUSH); |
| 413 | dc.SetTextForeground(*wxWHITE); |
| 414 | dc.SetBackgroundMode(wxTRANSPARENT); |
| 415 | dc.DrawRectangle(0, 0, width, height); |
| 416 | |
| 417 | wxCoord w, h; |
| 418 | wxString text = wxT("Glide64mk2"); |
| 419 | dc.GetTextExtent(text, &w, &h); |
| 420 | wxCoord x = (width - w)/2; |
| 421 | wxCoord y = height/2 - h*4; |
| 422 | dc.DrawText(text, x, y); |
| 423 | |
| 424 | text = wxT("Gfx cannot be drawn in windowed mode"); |
| 425 | dc.GetTextExtent(text, &w, &h); |
| 426 | x = (width - w)/2; |
| 427 | y = height/2 - h; |
| 428 | dc.DrawText(text, x, y); |
| 429 | |
| 430 | text = wxT("Press Alt+Enter to switch to fullscreen"); |
| 431 | dc.GetTextExtent(text, &w, &h); |
| 432 | x = (width - w)/2; |
| 433 | y = (height - h)/2 + h*2; |
| 434 | dc.DrawText(text, x, y); |
| 435 | } |
| 436 | #endif |
| 437 | } |
| 438 | |
| 439 | static wxUint32 d_ul_x, d_ul_y, d_lr_x, d_lr_y; |
| 440 | |
| 441 | static void DrawPartFrameBufferToScreen() |
| 442 | { |
| 443 | FB_TO_SCREEN_INFO fb_info; |
| 444 | fb_info.addr = rdp.cimg; |
| 445 | fb_info.size = rdp.ci_size; |
| 446 | fb_info.width = rdp.ci_width; |
| 447 | fb_info.height = rdp.ci_height; |
| 448 | fb_info.ul_x = d_ul_x; |
| 449 | fb_info.lr_x = d_lr_x; |
| 450 | fb_info.ul_y = d_ul_y; |
| 451 | fb_info.lr_y = d_lr_y; |
| 452 | fb_info.opaque = 0; |
| 453 | DrawFrameBufferToScreen(fb_info); |
| 454 | memset(gfx.RDRAM+rdp.cimg, 0, (rdp.ci_width*rdp.ci_height)<<rdp.ci_size>>1); |
| 455 | } |
| 456 | |
| 457 | #define RGBA16TO32(color) \ |
| 458 | ((color&1)?0xFF:0) | \ |
| 459 | ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | \ |
| 460 | ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | \ |
| 461 | ((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8) |
| 462 | |
| 463 | static void CopyFrameBuffer (GrBuffer_t buffer = GR_BUFFER_BACKBUFFER) |
| 464 | { |
| 465 | if (!fullscreen) |
| 466 | return; |
| 467 | FRDP ("CopyFrameBuffer: %08lx... ", rdp.cimg); |
| 468 | |
| 469 | // don't bother to write the stuff in asm... the slow part is the read from video card, |
| 470 | // not the copy. |
| 471 | |
| 472 | wxUint32 width = rdp.ci_width;//*gfx.VI_WIDTH_REG; |
| 473 | wxUint32 height; |
| 474 | if (fb_emulation_enabled && !(settings.hacks&hack_PPL)) |
| 475 | { |
| 476 | int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0; |
| 477 | height = rdp.frame_buffers[ind].height; |
| 478 | } |
| 479 | else |
| 480 | { |
| 481 | height = rdp.ci_lower_bound; |
| 482 | if (settings.hacks&hack_PPL) |
| 483 | height -= rdp.ci_upper_bound; |
| 484 | } |
| 485 | FRDP ("width: %d, height: %d... ", width, height); |
| 486 | //printf("CopyFrameBuffer width: %d, height: %d... ", width, height); |
| 487 | |
| 488 | if (rdp.scale_x < 1.1f) |
| 489 | { |
| 490 | wxUint16 * ptr_src = new wxUint16[width*height]; |
| 491 | if (grLfbReadRegion(buffer, |
| 492 | (wxUint32)rdp.offset_x, |
| 493 | (wxUint32)rdp.offset_y,//rdp.ci_upper_bound, |
| 494 | width, |
| 495 | height, |
| 496 | width<<1, |
| 497 | ptr_src)) |
| 498 | { |
| 499 | wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg); |
| 500 | wxUint32 *ptr_dst32 = (wxUint32*)(gfx.RDRAM+rdp.cimg); |
| 501 | wxUint16 c; |
| 502 | |
| 503 | for (wxUint32 y=0; y<height; y++) |
| 504 | { |
| 505 | for (wxUint32 x=0; x<width; x++) |
| 506 | { |
| 507 | c = ptr_src[x + y * width]; |
| 508 | if (settings.frame_buffer&fb_read_alpha) |
| 509 | { |
| 510 | if (c > 0) |
| 511 | c = (c&0xFFC0) | ((c&0x001F) << 1) | 1; |
| 512 | } |
| 513 | else |
| 514 | { |
| 515 | c = (c&0xFFC0) | ((c&0x001F) << 1) | 1; |
| 516 | } |
| 517 | if (rdp.ci_size == 2) |
| 518 | ptr_dst[(x + y * width)^1] = c; |
| 519 | else |
| 520 | ptr_dst32[x + y * width] = RGBA16TO32(c); |
| 521 | } |
| 522 | } |
| 523 | LRDP("ReadRegion. Framebuffer copy complete.\n"); |
| 524 | } |
| 525 | else |
| 526 | { |
| 527 | LRDP("Framebuffer copy failed.\n"); |
| 528 | } |
| 529 | delete[] ptr_src; |
| 530 | } |
| 531 | else |
| 532 | { |
| 533 | if (rdp.motionblur && fb_hwfbe_enabled) |
| 534 | { |
| 535 | return; |
| 536 | } |
| 537 | else |
| 538 | { |
| 539 | float scale_x = (settings.scr_res_x - rdp.offset_x*2.0f) / max(width, rdp.vi_width); |
| 540 | float scale_y = (settings.scr_res_y - rdp.offset_y*2.0f) / max(height, rdp.vi_height); |
| 541 | |
| 542 | 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); |
| 543 | //printf("CopyFrameBuffer width: %d, height: %d, ul_y: %d, lr_y: %d, scale_x: %f, scale_y: %f, ci_width: %d, ci_height: %d\n",width, height, rdp.ci_upper_bound, rdp.ci_lower_bound, scale_x, scale_y, rdp.ci_width, rdp.ci_height); |
| 544 | GrLfbInfo_t info; |
| 545 | info.size = sizeof(GrLfbInfo_t); |
| 546 | |
| 547 | if (grLfbLock (GR_LFB_READ_ONLY, |
| 548 | buffer, |
| 549 | GR_LFBWRITEMODE_565, |
| 550 | GR_ORIGIN_UPPER_LEFT, |
| 551 | FXFALSE, |
| 552 | &info)) |
| 553 | { |
| 554 | wxUint16 *ptr_src = (wxUint16*)info.lfbPtr; |
| 555 | wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg); |
| 556 | wxUint32 *ptr_dst32 = (wxUint32*)(gfx.RDRAM+rdp.cimg); |
| 557 | wxUint16 c; |
| 558 | wxUint32 stride = info.strideInBytes>>1; |
| 559 | |
| 560 | int read_alpha = settings.frame_buffer & fb_read_alpha; |
| 561 | if ((settings.hacks&hack_PMario) && rdp.frame_buffers[rdp.ci_count-1].status != ci_aux) |
| 562 | read_alpha = FALSE; |
| 563 | int x_start = 0, y_start = 0, x_end = width, y_end = height; |
| 564 | if (settings.hacks&hack_BAR) |
| 565 | { |
| 566 | x_start = 80, y_start = 24, x_end = 240, y_end = 86; |
| 567 | } |
| 568 | for (int y=y_start; y<y_end; y++) |
| 569 | { |
| 570 | for (int x=x_start; x<x_end; x++) |
| 571 | { |
| 572 | c = ptr_src[int(x*scale_x + rdp.offset_x) + int(y * scale_y + rdp.offset_y) * stride]; |
| 573 | c = (c&0xFFC0) | ((c&0x001F) << 1) | 1; |
| 574 | if (read_alpha && c == 1) |
| 575 | c = 0; |
| 576 | if (rdp.ci_size <= 2) |
| 577 | ptr_dst[(x + y * width)^1] = c; |
| 578 | else |
| 579 | ptr_dst32[x + y * width] = RGBA16TO32(c); |
| 580 | } |
| 581 | } |
| 582 | |
| 583 | // Unlock the backbuffer |
| 584 | grLfbUnlock (GR_LFB_READ_ONLY, buffer); |
| 585 | LRDP("LfbLock. Framebuffer copy complete.\n"); |
| 586 | } |
| 587 | else |
| 588 | { |
| 589 | LRDP("Framebuffer copy failed.\n"); |
| 590 | } |
| 591 | } |
| 592 | } |
| 593 | } |
| 594 | |
| 595 | void GoToFullScreen() |
| 596 | { |
| 597 | //if (!InitGfx ()) |
| 598 | { |
| 599 | LOG ("FAILED!!!\n"); |
| 600 | return; |
| 601 | } |
| 602 | } |
| 603 | |
| 604 | class SoftLocker |
| 605 | { |
| 606 | public: |
| 607 | // lock the mutex in the ctor |
| 608 | SoftLocker(SDL_sem *mutex) |
| 609 | : _isOk(false), _mutex(mutex) |
| 610 | { _isOk = ( SDL_SemTryWait(_mutex) == 0 ); } |
| 611 | |
| 612 | // returns true if mutex was successfully locked in ctor |
| 613 | bool IsOk() const |
| 614 | { return _isOk; } |
| 615 | |
| 616 | // unlock the mutex in dtor |
| 617 | ~SoftLocker() |
| 618 | { if ( IsOk() ) SDL_SemPost(_mutex); } |
| 619 | |
| 620 | private: |
| 621 | bool _isOk; |
| 622 | SDL_sem *_mutex; |
| 623 | }; |
| 624 | |
| 625 | |
| 626 | /****************************************************************** |
| 627 | Function: ProcessDList |
| 628 | Purpose: This function is called when there is a Dlist to be |
| 629 | processed. (High level GFX list) |
| 630 | input: none |
| 631 | output: none |
| 632 | *******************************************************************/ |
| 633 | void DetectFrameBufferUsage (); |
| 634 | wxUint32 fbreads_front = 0; |
| 635 | wxUint32 fbreads_back = 0; |
| 636 | int cpu_fb_read_called = FALSE; |
| 637 | int cpu_fb_write_called = FALSE; |
| 638 | int cpu_fb_write = FALSE; |
| 639 | int cpu_fb_ignore = FALSE; |
| 640 | int CI_SET = TRUE; |
| 641 | wxUint32 ucode5_texshiftaddr = 0; |
| 642 | wxUint32 ucode5_texshiftcount = 0; |
| 643 | wxUint16 ucode5_texshift = 0; |
| 644 | int depth_buffer_fog; |
| 645 | |
| 646 | #ifdef __cplusplus |
| 647 | extern "C" { |
| 648 | #endif |
| 649 | |
| 650 | |
| 651 | EXPORT void CALL ProcessDList(void) |
| 652 | { |
| 653 | // SoftLocker lock(mutexProcessDList); |
| 654 | #ifdef PAULSCODE |
| 655 | //printf("ProcessDList()\n"); |
| 656 | // frameSkipper.newFrame(); |
| 657 | if (0) |
| 658 | // if (frameSkipper.willSkipNext()) |
| 659 | #else |
| 660 | if (/*!lock.IsOk()*/0) //mutex is busy |
| 661 | #endif |
| 662 | { |
| 663 | // printf("Frameskip, reason=%s\n", (lock.IsOk())?"lock":"frameskip"); |
| 664 | /* if (!fullscreen) |
| 665 | drawNoFullscreenMessage();*/ |
| 666 | // Set an interrupt to allow the game to continue |
| 667 | *(gfx.MI_INTR_REG) |= 0x20; |
| 668 | gfx.CheckInterrupts(); |
| 669 | *(gfx.MI_INTR_REG) |= 0x01; |
| 670 | gfx.CheckInterrupts(); |
| 671 | // rdp.updatescreen = 1; |
| 672 | // no_dlist = true; |
| 673 | // rdp_fullsync(); |
| 674 | return; |
| 675 | } |
| 676 | |
| 677 | no_dlist = false; |
| 678 | update_screen_count = 0; |
| 679 | ChangeSize (); |
| 680 | |
| 681 | #ifdef ALTTAB_FIX |
| 682 | if (!hhkLowLevelKybd) |
| 683 | { |
| 684 | hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL, |
| 685 | LowLevelKeyboardProc, NULL, 0); |
| 686 | } |
| 687 | #endif |
| 688 | |
| 689 | VLOG ("ProcessDList ()\n"); |
| 690 | /* |
| 691 | if (!fullscreen) |
| 692 | { |
| 693 | drawNoFullscreenMessage(); |
| 694 | // Set an interrupt to allow the game to continue |
| 695 | *gfx.MI_INTR_REG |= 0x20; |
| 696 | gfx.CheckInterrupts(); |
| 697 | } |
| 698 | */ |
| 699 | if (reset) |
| 700 | { |
| 701 | reset = 0; |
| 702 | if (settings.autodetect_ucode) |
| 703 | { |
| 704 | // Thanks to ZeZu for ucode autodetection!!! |
| 705 | wxUint32 startUcode = *(wxUint32*)(gfx.DMEM+0xFD0); |
| 706 | memcpy (microcode, gfx.RDRAM+startUcode, 4096); |
| 707 | microcheck (); |
| 708 | } |
| 709 | else |
| 710 | memset (microcode, 0, 4096); |
| 711 | } |
| 712 | else if ( ((old_ucode == ucode_S2DEX) && (settings.ucode == ucode_F3DEX)) || settings.force_microcheck) |
| 713 | { |
| 714 | wxUint32 startUcode = *(wxUint32*)(gfx.DMEM+0xFD0); |
| 715 | memcpy (microcode, gfx.RDRAM+startUcode, 4096); |
| 716 | microcheck (); |
| 717 | } |
| 718 | |
| 719 | if (exception) |
| 720 | return; |
| 721 | |
| 722 | // Switch to fullscreen? |
| 723 | if (to_fullscreen) |
| 724 | GoToFullScreen(); |
| 725 | |
| 726 | if (!fullscreen && !settings.run_in_window) |
| 727 | return; |
| 728 | |
| 729 | // Clear out the RDP log |
| 730 | #ifdef RDP_LOGGING |
| 731 | if (settings.logging && settings.log_clear) |
| 732 | { |
| 733 | CLOSE_RDP_LOG (); |
| 734 | OPEN_RDP_LOG (); |
| 735 | } |
| 736 | #endif |
| 737 | |
| 738 | #ifdef UNIMP_LOG |
| 739 | if (settings.log_unk && settings.unk_clear) |
| 740 | { |
| 741 | std::ofstream unimp; |
| 742 | unimp.open("unimp.txt"); |
| 743 | unimp.close(); |
| 744 | } |
| 745 | #endif |
| 746 | |
| 747 | //* Set states *// |
| 748 | if (settings.swapmode > 0) |
| 749 | SwapOK = TRUE; |
| 750 | rdp.updatescreen = 1; |
| 751 | |
| 752 | rdp.tri_n = 0; // 0 triangles so far this frame |
| 753 | rdp.debug_n = 0; |
| 754 | |
| 755 | rdp.model_i = 0; // 0 matrices so far in stack |
| 756 | //stack_size can be less then 32! Important for Silicon Vally. Thanks Orkin! |
| 757 | rdp.model_stack_size = min(32, (*(wxUint32*)(gfx.DMEM+0x0FE4))>>6); |
| 758 | if (rdp.model_stack_size == 0) |
| 759 | rdp.model_stack_size = 32; |
| 760 | rdp.Persp_en = TRUE; |
| 761 | rdp.fb_drawn = rdp.fb_drawn_front = FALSE; |
| 762 | rdp.update = 0x7FFFFFFF; // All but clear cache |
| 763 | rdp.geom_mode = 0; |
| 764 | rdp.acmp = 0; |
| 765 | rdp.maincimg[1] = rdp.maincimg[0]; |
| 766 | rdp.skip_drawing = FALSE; |
| 767 | rdp.s2dex_tex_loaded = FALSE; |
| 768 | rdp.bg_image_height = 0xFFFF; |
| 769 | fbreads_front = fbreads_back = 0; |
| 770 | rdp.fog_multiplier = rdp.fog_offset = 0; |
| 771 | rdp.zsrc = 0; |
| 772 | if (rdp.vi_org_reg != *gfx.VI_ORIGIN_REG) |
| 773 | rdp.tlut_mode = 0; //is it correct? |
| 774 | rdp.scissor_set = FALSE; |
| 775 | ucode5_texshiftaddr = ucode5_texshiftcount = 0; |
| 776 | cpu_fb_write = FALSE; |
| 777 | cpu_fb_read_called = FALSE; |
| 778 | cpu_fb_write_called = FALSE; |
| 779 | cpu_fb_ignore = FALSE; |
| 780 | d_ul_x = 0xffff; |
| 781 | d_ul_y = 0xffff; |
| 782 | d_lr_x = 0; |
| 783 | d_lr_y = 0; |
| 784 | depth_buffer_fog = TRUE; |
| 785 | //printf("ProcessDList\n"); |
| 786 | //analize possible frame buffer usage |
| 787 | if (fb_emulation_enabled) |
| 788 | DetectFrameBufferUsage(); |
| 789 | if (!(settings.hacks&hack_Lego) || rdp.num_of_ci > 1) |
| 790 | rdp.last_bg = 0; |
| 791 | //* End of set states *// |
| 792 | |
| 793 | // Get the start of the display list and the length of it |
| 794 | wxUint32 dlist_start = *(wxUint32*)(gfx.DMEM+0xFF0); |
| 795 | wxUint32 dlist_length = *(wxUint32*)(gfx.DMEM+0xFF4); |
| 796 | FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_length: %d, x_scale: %f, y_scale: %f\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length, (*gfx.VI_X_SCALE_REG & 0xFFF)/1024.0f, (*gfx.VI_Y_SCALE_REG & 0xFFF)/1024.0f); |
| 797 | FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG); |
| 798 | |
| 799 | if (cpu_fb_write == TRUE) |
| 800 | DrawPartFrameBufferToScreen(); |
| 801 | if ((settings.hacks&hack_Tonic) && dlist_length < 16) |
| 802 | { |
| 803 | rdp_fullsync(); |
| 804 | FRDP_E("DLIST is too short!\n"); |
| 805 | return; |
| 806 | } |
| 807 | |
| 808 | // Start executing at the start of the display list |
| 809 | rdp.pc_i = 0; |
| 810 | rdp.pc[rdp.pc_i] = dlist_start; |
| 811 | rdp.dl_count = -1; |
| 812 | rdp.halt = 0; |
| 813 | wxUint32 a; |
| 814 | |
| 815 | |
| 816 | // catches exceptions so that it doesn't freeze |
| 817 | #ifdef CATCH_EXCEPTIONS |
| 818 | try { |
| 819 | #endif |
| 820 | if (settings.ucode == ucode_Turbo3d) |
| 821 | { |
| 822 | Turbo3D(); |
| 823 | } |
| 824 | else |
| 825 | { |
| 826 | // MAIN PROCESSING LOOP |
| 827 | do { |
| 828 | |
| 829 | // Get the address of the next command |
| 830 | a = rdp.pc[rdp.pc_i] & BMASK; |
| 831 | |
| 832 | // Load the next command and its input |
| 833 | rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit |
| 834 | rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // / |
| 835 | // cmd2 and cmd3 are filled only when needed, by the function that needs them |
| 836 | |
| 837 | // Output the address before the command |
| 838 | #ifdef LOG_COMMANDS |
| 839 | FRDP ("%08lx (c0:%08lx, c1:%08lx): ", a, rdp.cmd0, rdp.cmd1); |
| 840 | #else |
| 841 | FRDP ("%08lx: ", a); |
| 842 | #endif |
| 843 | |
| 844 | // Go to the next instruction |
| 845 | rdp.pc[rdp.pc_i] = (a+8) & BMASK; |
| 846 | |
| 847 | #ifdef PERFORMANCE |
| 848 | perf_cur = ticksGetTicks(); |
| 849 | #endif |
| 850 | // Process this instruction |
| 851 | gfx_instruction[settings.ucode][rdp.cmd0>>24] (); |
| 852 | |
| 853 | // check DL counter |
| 854 | if (rdp.dl_count != -1) |
| 855 | { |
| 856 | rdp.dl_count --; |
| 857 | if (rdp.dl_count == 0) |
| 858 | { |
| 859 | rdp.dl_count = -1; |
| 860 | |
| 861 | LRDP("End of DL\n"); |
| 862 | rdp.pc_i --; |
| 863 | } |
| 864 | } |
| 865 | |
| 866 | #ifdef PERFORMANCE |
| 867 | perf_next = ticksGetTicks(); |
| 868 | sprintf (out_buf, "perf %08x: %lli\n", a-8, (perf_next-perf_cur)); |
| 869 | #ifdef RDP_LOGGING |
| 870 | rdp_log << out_buf; |
| 871 | #else |
| 872 | printf(out_buf); |
| 873 | #endif |
| 874 | #endif |
| 875 | |
| 876 | } while (!rdp.halt); |
| 877 | } |
| 878 | #ifdef CATCH_EXCEPTIONS |
| 879 | } catch (...) { |
| 880 | |
| 881 | if (fullscreen) |
| 882 | { |
| 883 | ReleaseGfx (); |
| 884 | rdp_reset (); |
| 885 | #ifdef TEXTURE_FILTER |
| 886 | if (settings.ghq_use) |
| 887 | { |
| 888 | ext_ghq_shutdown(); |
| 889 | settings.ghq_use = 0; |
| 890 | } |
| 891 | #endif |
| 892 | } |
| 893 | ERRLOG("The GFX plugin caused an exception and has been disabled."); |
| 894 | exception = TRUE; |
| 895 | return; |
| 896 | } |
| 897 | #endif |
| 898 | |
| 899 | if (fb_emulation_enabled) |
| 900 | { |
| 901 | rdp.scale_x = rdp.scale_x_bak; |
| 902 | rdp.scale_y = rdp.scale_y_bak; |
| 903 | } |
| 904 | #ifdef PAULSCODE |
| 905 | if (!frameSkipper.willSkipNext()) |
| 906 | #endif |
| 907 | if (settings.frame_buffer & fb_ref) |
| 908 | CopyFrameBuffer (); |
| 909 | if (rdp.cur_image) |
| 910 | CloseTextureBuffer(rdp.read_whole_frame && ((settings.hacks&hack_PMario) || rdp.swap_ci_index >= 0)); |
| 911 | |
| 912 | if ((settings.hacks&hack_TGR2) && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET) |
| 913 | { |
| 914 | newSwapBuffers (); |
| 915 | CI_SET = FALSE; |
| 916 | } |
| 917 | LRDP("ProcessDList end\n"); |
| 918 | } |
| 919 | |
| 920 | #ifdef __cplusplus |
| 921 | } |
| 922 | #endif |
| 923 | |
| 924 | // undef - undefined instruction, always ignore |
| 925 | static void undef() |
| 926 | { |
| 927 | FRDP_E("** undefined ** (%08lx)\n", rdp.cmd0); |
| 928 | FRDP("** undefined ** (%08lx) - IGNORED\n", rdp.cmd0); |
| 929 | #ifdef _ENDUSER_RELEASE_ |
| 930 | *gfx.MI_INTR_REG |= 0x20; |
| 931 | gfx.CheckInterrupts(); |
| 932 | rdp.halt = 1; |
| 933 | #endif |
| 934 | } |
| 935 | |
| 936 | // spnoop - no operation, always ignore |
| 937 | static void spnoop() |
| 938 | { |
| 939 | LRDP("spnoop\n"); |
| 940 | } |
| 941 | |
| 942 | // noop - no operation, always ignore |
| 943 | static void rdp_noop() |
| 944 | { |
| 945 | LRDP("noop\n"); |
| 946 | } |
| 947 | |
| 948 | static void ys_memrect () |
| 949 | { |
| 950 | wxUint32 tile = (wxUint16)((rdp.cmd1 & 0x07000000) >> 24); |
| 951 | |
| 952 | wxUint32 lr_x = (wxUint16)((rdp.cmd0 & 0x00FFF000) >> 14); |
| 953 | wxUint32 lr_y = (wxUint16)((rdp.cmd0 & 0x00000FFF) >> 2); |
| 954 | wxUint32 ul_x = (wxUint16)((rdp.cmd1 & 0x00FFF000) >> 14); |
| 955 | wxUint32 ul_y = (wxUint16)((rdp.cmd1 & 0x00000FFF) >> 2); |
| 956 | |
| 957 | if (lr_y > rdp.scissor_o.lr_y) |
| 958 | lr_y = rdp.scissor_o.lr_y; |
| 959 | wxUint32 off_x = ((rdp.cmd2 & 0xFFFF0000) >> 16) >> 5; |
| 960 | wxUint32 off_y = (rdp.cmd2 & 0x0000FFFF) >> 5; |
| 961 | |
| 962 | FRDP ("memrect (%d, %d, %d, %d), ci_width: %d", ul_x, ul_y, lr_x, lr_y, rdp.ci_width); |
| 963 | if (off_x > 0) |
| 964 | FRDP (" off_x: %d", off_x); |
| 965 | if (off_y > 0) |
| 966 | FRDP (" off_y: %d", off_y); |
| 967 | LRDP("\n"); |
| 968 | |
| 969 | wxUint32 y, width = lr_x - ul_x; |
| 970 | wxUint32 tex_width = rdp.tiles[tile].line << 3; |
| 971 | wxUint8 * texaddr = gfx.RDRAM + rdp.addr[rdp.tiles[tile].t_mem] + tex_width*off_y + off_x; |
| 972 | wxUint8 * fbaddr = gfx.RDRAM + rdp.cimg + ul_x; |
| 973 | |
| 974 | for (y = ul_y; y < lr_y; y++) { |
| 975 | wxUint8 *src = texaddr + (y - ul_y) * tex_width; |
| 976 | wxUint8 *dst = fbaddr + y * rdp.ci_width; |
| 977 | memcpy (dst, src, width); |
| 978 | } |
| 979 | } |
| 980 | |
| 981 | static void pm_palette_mod () |
| 982 | { |
| 983 | wxUint8 envr = (wxUint8)((float)((rdp.env_color >> 24)&0xFF)/255.0f*31.0f); |
| 984 | wxUint8 envg = (wxUint8)((float)((rdp.env_color >> 16)&0xFF)/255.0f*31.0f); |
| 985 | wxUint8 envb = (wxUint8)((float)((rdp.env_color >> 8)&0xFF)/255.0f*31.0f); |
| 986 | wxUint16 env16 = (wxUint16)((envr<<11)|(envg<<6)|(envb<<1)|1); |
| 987 | wxUint8 prmr = (wxUint8)((float)((rdp.prim_color >> 24)&0xFF)/255.0f*31.0f); |
| 988 | wxUint8 prmg = (wxUint8)((float)((rdp.prim_color >> 16)&0xFF)/255.0f*31.0f); |
| 989 | wxUint8 prmb = (wxUint8)((float)((rdp.prim_color >> 8)&0xFF)/255.0f*31.0f); |
| 990 | wxUint16 prim16 = (wxUint16)((prmr<<11)|(prmg<<6)|(prmb<<1)|1); |
| 991 | wxUint16 * dst = (wxUint16*)(gfx.RDRAM+rdp.cimg); |
| 992 | for (int i = 0; i < 16; i++) |
| 993 | { |
| 994 | dst[i^1] = (rdp.pal_8[i]&1) ? prim16 : env16; |
| 995 | } |
| 996 | LRDP("Texrect palette modification\n"); |
| 997 | } |
| 998 | |
| 999 | static void pd_zcopy () |
| 1000 | { |
| 1001 | wxUint16 ul_x = (wxUint16)((rdp.cmd1 & 0x00FFF000) >> 14); |
| 1002 | wxUint16 lr_x = (wxUint16)((rdp.cmd0 & 0x00FFF000) >> 14) + 1; |
| 1003 | wxUint16 ul_u = (wxUint16)((rdp.cmd2 & 0xFFFF0000) >> 21) + 1; |
| 1004 | wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg); |
| 1005 | wxUint16 width = lr_x - ul_x; |
| 1006 | wxUint16 * ptr_src = ((wxUint16*)rdp.tmem)+ul_u; |
| 1007 | wxUint16 c; |
| 1008 | for (wxUint16 x=0; x<width; x++) |
| 1009 | { |
| 1010 | c = ptr_src[x]; |
| 1011 | c = ((c<<8)&0xFF00) | (c >> 8); |
| 1012 | ptr_dst[(ul_x+x)^1] = c; |
| 1013 | // FRDP("dst[%d]=%04lx \n", (x + ul_x)^1, c); |
| 1014 | } |
| 1015 | } |
| 1016 | |
| 1017 | static void DrawDepthBufferFog() |
| 1018 | { |
| 1019 | if (rdp.zi_width < 200) |
| 1020 | return; |
| 1021 | FB_TO_SCREEN_INFO fb_info; |
| 1022 | fb_info.addr = rdp.zimg; |
| 1023 | fb_info.size = 2; |
| 1024 | fb_info.width = rdp.zi_width; |
| 1025 | fb_info.height = rdp.ci_height; |
| 1026 | fb_info.ul_x = rdp.scissor_o.ul_x; |
| 1027 | fb_info.lr_x = rdp.scissor_o.lr_x; |
| 1028 | fb_info.ul_y = rdp.scissor_o.ul_y; |
| 1029 | fb_info.lr_y = rdp.scissor_o.lr_y; |
| 1030 | fb_info.opaque = 0; |
| 1031 | DrawDepthBufferToScreen(fb_info); |
| 1032 | } |
| 1033 | |
| 1034 | static void rdp_texrect() |
| 1035 | { |
| 1036 | if (!rdp.LLE) |
| 1037 | { |
| 1038 | wxUint32 a = rdp.pc[rdp.pc_i]; |
| 1039 | wxUint8 cmdHalf1 = gfx.RDRAM[a+3]; |
| 1040 | wxUint8 cmdHalf2 = gfx.RDRAM[a+11]; |
| 1041 | a >>= 2; |
| 1042 | if ((cmdHalf1 == 0xE1 && cmdHalf2 == 0xF1) || (cmdHalf1 == 0xB4 && cmdHalf2 == 0xB3) || (cmdHalf1 == 0xB3 && cmdHalf2 == 0xB2)) |
| 1043 | { |
| 1044 | //gSPTextureRectangle |
| 1045 | rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a+1]; |
| 1046 | rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a+3]; |
| 1047 | rdp.pc[rdp.pc_i] += 16; |
| 1048 | } |
| 1049 | else |
| 1050 | { |
| 1051 | //gDPTextureRectangle |
| 1052 | if (settings.hacks&hack_ASB) |
| 1053 | rdp.cmd2 = 0; |
| 1054 | else |
| 1055 | rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a+0]; |
| 1056 | rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a+1]; |
| 1057 | rdp.pc[rdp.pc_i] += 8; |
| 1058 | } |
| 1059 | } |
| 1060 | if ((settings.hacks&hack_Yoshi) && settings.ucode == ucode_S2DEX) |
| 1061 | { |
| 1062 | ys_memrect(); |
| 1063 | return; |
| 1064 | } |
| 1065 | |
| 1066 | if (rdp.skip_drawing || (!fb_emulation_enabled && (rdp.cimg == rdp.zimg))) |
| 1067 | { |
| 1068 | if ((settings.hacks&hack_PMario) && rdp.ci_status == ci_useless) |
| 1069 | { |
| 1070 | pm_palette_mod (); |
| 1071 | } |
| 1072 | else |
| 1073 | { |
| 1074 | LRDP("Texrect skipped\n"); |
| 1075 | } |
| 1076 | return; |
| 1077 | } |
| 1078 | |
| 1079 | if ((settings.ucode == ucode_CBFD) && rdp.cur_image && rdp.cur_image->format) |
| 1080 | { |
| 1081 | //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); |
| 1082 | LRDP("Shadow texrect is skipped.\n"); |
| 1083 | rdp.tri_n += 2; |
| 1084 | return; |
| 1085 | } |
| 1086 | |
| 1087 | if ((settings.ucode == ucode_PerfectDark) && (rdp.frame_buffers[rdp.ci_count-1].status == ci_zcopy)) |
| 1088 | { |
| 1089 | pd_zcopy (); |
| 1090 | LRDP("Depth buffer copied.\n"); |
| 1091 | rdp.tri_n += 2; |
| 1092 | return; |
| 1093 | } |
| 1094 | |
| 1095 | if ((rdp.othermode_l >> 16) == 0x3c18 && rdp.cycle1 == 0x03ffffff && rdp.cycle2 == 0x01ff1fff) //depth image based fog |
| 1096 | { |
| 1097 | if (!depth_buffer_fog) |
| 1098 | return; |
| 1099 | if (settings.fog) |
| 1100 | DrawDepthBufferFog(); |
| 1101 | depth_buffer_fog = FALSE; |
| 1102 | return; |
| 1103 | } |
| 1104 | |
| 1105 | // FRDP ("rdp.cycle1 %08lx, rdp.cycle2 %08lx\n", rdp.cycle1, rdp.cycle2); |
| 1106 | |
| 1107 | float ul_x, ul_y, lr_x, lr_y; |
| 1108 | if (rdp.cycle_mode == 2) |
| 1109 | { |
| 1110 | ul_x = max(0.0f, (short)((rdp.cmd1 & 0x00FFF000) >> 14)); |
| 1111 | ul_y = max(0.0f, (short)((rdp.cmd1 & 0x00000FFF) >> 2)); |
| 1112 | lr_x = max(0.0f, (short)((rdp.cmd0 & 0x00FFF000) >> 14)); |
| 1113 | lr_y = max(0.0f, (short)((rdp.cmd0 & 0x00000FFF) >> 2)); |
| 1114 | } |
| 1115 | else |
| 1116 | { |
| 1117 | ul_x = max(0.0f, ((short)((rdp.cmd1 & 0x00FFF000) >> 12)) / 4.0f); |
| 1118 | ul_y = max(0.0f, ((short)(rdp.cmd1 & 0x00000FFF)) / 4.0f); |
| 1119 | lr_x = max(0.0f, ((short)((rdp.cmd0 & 0x00FFF000) >> 12)) / 4.0f); |
| 1120 | lr_y = max(0.0f, ((short)(rdp.cmd0 & 0x00000FFF)) / 4.0f); |
| 1121 | } |
| 1122 | |
| 1123 | if (ul_x >= lr_x) |
| 1124 | { |
| 1125 | FRDP("Wrong Texrect: ul_x: %f, lr_x: %f\n", ul_x, lr_x); |
| 1126 | return; |
| 1127 | } |
| 1128 | |
| 1129 | if (rdp.cycle_mode > 1) |
| 1130 | { |
| 1131 | lr_x += 1.0f; |
| 1132 | lr_y += 1.0f; |
| 1133 | } else if (lr_y - ul_y < 1.0f) |
| 1134 | lr_y = ceil(lr_y); |
| 1135 | |
| 1136 | if (settings.increase_texrect_edge) |
| 1137 | { |
| 1138 | if (floor(lr_x) != lr_x) |
| 1139 | lr_x = ceil(lr_x); |
| 1140 | if (floor(lr_y) != lr_y) |
| 1141 | lr_y = ceil(lr_y); |
| 1142 | } |
| 1143 | |
| 1144 | //* |
| 1145 | if (rdp.tbuff_tex && (settings.frame_buffer & fb_optimize_texrect)) |
| 1146 | { |
| 1147 | LRDP("Attempt to optimize texrect\n"); |
| 1148 | if (!rdp.tbuff_tex->drawn) |
| 1149 | { |
| 1150 | DRAWIMAGE d; |
| 1151 | d.imageX = 0; |
| 1152 | d.imageW = (wxUint16)rdp.tbuff_tex->width; |
| 1153 | d.frameX = (wxUint16)ul_x; |
| 1154 | d.frameW = (wxUint16)(rdp.tbuff_tex->width); |
| 1155 | |
| 1156 | d.imageY = 0; |
| 1157 | d.imageH = (wxUint16)rdp.tbuff_tex->height; |
| 1158 | d.frameY = (wxUint16)ul_y; |
| 1159 | d.frameH = (wxUint16)(rdp.tbuff_tex->height); |
| 1160 | FRDP("texrect. ul_x: %d, ul_y: %d, lr_x: %d, lr_y: %d, width: %d, height: %d\n", ul_x, ul_y, lr_x, lr_y, rdp.tbuff_tex->width, rdp.tbuff_tex->height); |
| 1161 | d.scaleX = 1.0f; |
| 1162 | d.scaleY = 1.0f; |
| 1163 | DrawHiresImage(d, rdp.tbuff_tex->width == rdp.ci_width); |
| 1164 | rdp.tbuff_tex->drawn = TRUE; |
| 1165 | } |
| 1166 | return; |
| 1167 | } |
| 1168 | //*/ |
| 1169 | // framebuffer workaround for Zelda: MM LOT |
| 1170 | if ((rdp.othermode_l & 0xFFFF0000) == 0x0f5a0000) |
| 1171 | return; |
| 1172 | |
| 1173 | /*Gonetz*/ |
| 1174 | //hack for Zelda MM. it removes black texrects which cover all geometry in "Link meets Zelda" cut scene |
| 1175 | if ((settings.hacks&hack_Zelda) && rdp.timg.addr >= rdp.cimg && rdp.timg.addr < rdp.ci_end) |
| 1176 | { |
| 1177 | 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); |
| 1178 | rdp.tri_n += 2; |
| 1179 | return; |
| 1180 | } |
| 1181 | //* |
| 1182 | //hack for Banjo2. it removes black texrects under Banjo |
| 1183 | if (!fb_hwfbe_enabled && ((rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF)) == 0xFFFFFFFF && (rdp.othermode_l & 0xFFFF0000) == 0x00500000) |
| 1184 | { |
| 1185 | rdp.tri_n += 2; |
| 1186 | return; |
| 1187 | } |
| 1188 | //*/ |
| 1189 | //* |
| 1190 | //remove motion blur in night vision |
| 1191 | if ((settings.ucode == ucode_PerfectDark) && (rdp.maincimg[1].addr != rdp.maincimg[0].addr) && (rdp.timg.addr >= rdp.maincimg[1].addr) && (rdp.timg.addr < (rdp.maincimg[1].addr+rdp.ci_width*rdp.ci_height*rdp.ci_size))) |
| 1192 | { |
| 1193 | if (fb_emulation_enabled) |
| 1194 | if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self) |
| 1195 | { |
| 1196 | //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); |
| 1197 | LRDP("Wrong Texrect.\n"); |
| 1198 | rdp.tri_n += 2; |
| 1199 | return; |
| 1200 | } |
| 1201 | } |
| 1202 | //*/ |
| 1203 | |
| 1204 | int i; |
| 1205 | |
| 1206 | wxUint32 tile = (wxUint16)((rdp.cmd1 & 0x07000000) >> 24); |
| 1207 | |
| 1208 | rdp.texrecting = 1; |
| 1209 | |
| 1210 | wxUint32 prev_tile = rdp.cur_tile; |
| 1211 | rdp.cur_tile = tile; |
| 1212 | |
| 1213 | const float Z = set_sprite_combine_mode (); |
| 1214 | |
| 1215 | rdp.texrecting = 0; |
| 1216 | |
| 1217 | if (!rdp.cur_cache[0]) |
| 1218 | { |
| 1219 | rdp.cur_tile = prev_tile; |
| 1220 | rdp.tri_n += 2; |
| 1221 | return; |
| 1222 | } |
| 1223 | // **** |
| 1224 | // ** Texrect offset by Gugaman ** |
| 1225 | // |
| 1226 | //integer representation of texture coordinate. |
| 1227 | //needed to detect and avoid overflow after shifting |
| 1228 | wxInt32 off_x_i = (rdp.cmd2 >> 16) & 0xFFFF; |
| 1229 | wxInt32 off_y_i = rdp.cmd2 & 0xFFFF; |
| 1230 | float dsdx = (float)((short)((rdp.cmd3 & 0xFFFF0000) >> 16)) / 1024.0f; |
| 1231 | float dtdy = (float)((short)(rdp.cmd3 & 0x0000FFFF)) / 1024.0f; |
| 1232 | if (off_x_i & 0x8000) //check for sign bit |
| 1233 | off_x_i |= ~0xffff; //make it negative |
| 1234 | //the same as for off_x_i |
| 1235 | if (off_y_i & 0x8000) |
| 1236 | off_y_i |= ~0xffff; |
| 1237 | |
| 1238 | if (rdp.cycle_mode == 2) |
| 1239 | dsdx /= 4.0f; |
| 1240 | |
| 1241 | float s_ul_x = ul_x * rdp.scale_x + rdp.offset_x; |
| 1242 | float s_lr_x = lr_x * rdp.scale_x + rdp.offset_x; |
| 1243 | float s_ul_y = ul_y * rdp.scale_y + rdp.offset_y; |
| 1244 | float s_lr_y = lr_y * rdp.scale_y + rdp.offset_y; |
| 1245 | |
| 1246 | FRDP("texrect (%.2f, %.2f, %.2f, %.2f), tile: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, tile, rdp.tri_n, rdp.tri_n+1); |
| 1247 | 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); |
| 1248 | FRDP("\toff_x: %f, off_y: %f, dsdx: %f, dtdy: %f\n", off_x_i/32.0f, off_y_i/32.0f, dsdx, dtdy); |
| 1249 | |
| 1250 | float off_size_x; |
| 1251 | float off_size_y; |
| 1252 | |
| 1253 | if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip |
| 1254 | { |
| 1255 | #ifdef TEXTURE_FILTER |
| 1256 | if (rdp.cur_cache[0]->is_hires_tex) |
| 1257 | { |
| 1258 | off_size_x = (float)((lr_y - ul_y) * dsdx); |
| 1259 | off_size_y = (float)((lr_x - ul_x) * dtdy); |
| 1260 | } |
| 1261 | else |
| 1262 | #endif |
| 1263 | { |
| 1264 | off_size_x = (lr_y - ul_y - 1) * dsdx; |
| 1265 | off_size_y = (lr_x - ul_x - 1) * dtdy; |
| 1266 | } |
| 1267 | } |
| 1268 | else |
| 1269 | { |
| 1270 | #ifdef TEXTURE_FILTER |
| 1271 | if (rdp.cur_cache[0]->is_hires_tex) |
| 1272 | { |
| 1273 | off_size_x = (float)((lr_x - ul_x) * dsdx); |
| 1274 | off_size_y = (float)((lr_y - ul_y) * dtdy); |
| 1275 | } |
| 1276 | else |
| 1277 | #endif |
| 1278 | { |
| 1279 | off_size_x = (lr_x - ul_x - 1) * dsdx; |
| 1280 | off_size_y = (lr_y - ul_y - 1) * dtdy; |
| 1281 | } |
| 1282 | } |
| 1283 | |
| 1284 | struct { |
| 1285 | float ul_u, ul_v, lr_u, lr_v; |
| 1286 | } texUV[2]; //struct for texture coordinates |
| 1287 | //angrylion's macro, helps to cut overflowed values. |
| 1288 | #define SIGN16(x) (((x) & 0x8000) ? ((x) | ~0xffff) : ((x) & 0xffff)) |
| 1289 | |
| 1290 | //calculate texture coordinates |
| 1291 | for (int i = 0; i < 2; i++) |
| 1292 | { |
| 1293 | if (rdp.cur_cache[i] && (rdp.tex & (i+1))) |
| 1294 | { |
| 1295 | float sx = 1, sy = 1; |
| 1296 | int x_i = off_x_i, y_i = off_y_i; |
| 1297 | TILE & tile = rdp.tiles[rdp.cur_tile + i]; |
| 1298 | //shifting |
| 1299 | if (tile.shift_s) |
| 1300 | { |
| 1301 | if (tile.shift_s > 10) |
| 1302 | { |
| 1303 | wxUint8 iShift = (16 - tile.shift_s); |
| 1304 | x_i <<= iShift; |
| 1305 | sx = (float)(1 << iShift); |
| 1306 | } |
| 1307 | else |
| 1308 | { |
| 1309 | wxUint8 iShift = tile.shift_s; |
| 1310 | x_i >>= iShift; |
| 1311 | sx = 1.0f/(float)(1 << iShift); |
| 1312 | } |
| 1313 | } |
| 1314 | if (tile.shift_t) |
| 1315 | { |
| 1316 | if (tile.shift_t > 10) |
| 1317 | { |
| 1318 | wxUint8 iShift = (16 - tile.shift_t); |
| 1319 | y_i <<= iShift; |
| 1320 | sy = (float)(1 << iShift); |
| 1321 | } |
| 1322 | else |
| 1323 | { |
| 1324 | wxUint8 iShift = tile.shift_t; |
| 1325 | y_i >>= iShift; |
| 1326 | sy = 1.0f/(float)(1 << iShift); |
| 1327 | } |
| 1328 | } |
| 1329 | |
| 1330 | if (rdp.aTBuffTex[i]) //hwfbe texture |
| 1331 | { |
| 1332 | float t0_off_x; |
| 1333 | float t0_off_y; |
| 1334 | if (off_x_i + off_y_i == 0) |
| 1335 | { |
| 1336 | t0_off_x = tile.ul_s; |
| 1337 | t0_off_y = tile.ul_t; |
| 1338 | } |
| 1339 | else |
| 1340 | { |
| 1341 | t0_off_x = off_x_i/32.0f; |
| 1342 | t0_off_y = off_y_i/32.0f; |
| 1343 | } |
| 1344 | t0_off_x += rdp.aTBuffTex[i]->u_shift;// + tile.ul_s; //commented for Paper Mario motion blur |
| 1345 | t0_off_y += rdp.aTBuffTex[i]->v_shift;// + tile.ul_t; |
| 1346 | texUV[i].ul_u = t0_off_x * sx; |
| 1347 | texUV[i].ul_v = t0_off_y * sy; |
| 1348 | |
| 1349 | texUV[i].lr_u = texUV[i].ul_u + off_size_x * sx; |
| 1350 | texUV[i].lr_v = texUV[i].ul_v + off_size_y * sy; |
| 1351 | |
| 1352 | texUV[i].ul_u *= rdp.aTBuffTex[i]->u_scale; |
| 1353 | texUV[i].ul_v *= rdp.aTBuffTex[i]->v_scale; |
| 1354 | texUV[i].lr_u *= rdp.aTBuffTex[i]->u_scale; |
| 1355 | texUV[i].lr_v *= rdp.aTBuffTex[i]->v_scale; |
| 1356 | FRDP("tbuff_tex[%d] ul_u: %f, ul_v: %f, lr_u: %f, lr_v: %f\n", |
| 1357 | i, texUV[i].ul_u, texUV[i].ul_v, texUV[i].lr_u, texUV[i].lr_v); |
| 1358 | } |
| 1359 | else //common case |
| 1360 | { |
| 1361 | //kill 10.5 format overflow by SIGN16 macro |
| 1362 | texUV[i].ul_u = SIGN16(x_i) / 32.0f; |
| 1363 | texUV[i].ul_v = SIGN16(y_i) / 32.0f; |
| 1364 | |
| 1365 | texUV[i].ul_u -= tile.f_ul_s; |
| 1366 | texUV[i].ul_v -= tile.f_ul_t; |
| 1367 | |
| 1368 | texUV[i].lr_u = texUV[i].ul_u + off_size_x * sx; |
| 1369 | texUV[i].lr_v = texUV[i].ul_v + off_size_y * sy; |
| 1370 | |
| 1371 | texUV[i].ul_u = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_x * texUV[i].ul_u; |
| 1372 | texUV[i].lr_u = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_x * texUV[i].lr_u; |
| 1373 | texUV[i].ul_v = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_y * texUV[i].ul_v; |
| 1374 | texUV[i].lr_v = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_y * texUV[i].lr_v; |
| 1375 | } |
| 1376 | } |
| 1377 | else |
| 1378 | { |
| 1379 | texUV[i].ul_u = texUV[i].ul_v = texUV[i].lr_u = texUV[i].lr_v = 0; |
| 1380 | } |
| 1381 | } |
| 1382 | rdp.cur_tile = prev_tile; |
| 1383 | |
| 1384 | // **** |
| 1385 | |
| 1386 | FRDP (" scissor: (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y); |
| 1387 | |
| 1388 | CCLIP2 (s_ul_x, s_lr_x, texUV[0].ul_u, texUV[0].lr_u, texUV[1].ul_u, texUV[1].lr_u, (float)rdp.scissor.ul_x, (float)rdp.scissor.lr_x); |
| 1389 | CCLIP2 (s_ul_y, s_lr_y, texUV[0].ul_v, texUV[0].lr_v, texUV[1].ul_v, texUV[1].lr_v, (float)rdp.scissor.ul_y, (float)rdp.scissor.lr_y); |
| 1390 | |
| 1391 | FRDP (" draw at: (%f, %f) -> (%f, %f)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y); |
| 1392 | |
| 1393 | VERTEX vstd[4] = { |
| 1394 | { s_ul_x, s_ul_y, Z, 1.0f, texUV[0].ul_u, texUV[0].ul_v, texUV[1].ul_u, texUV[1].ul_v, {0, 0, 0, 0}, 255 }, |
| 1395 | { s_lr_x, s_ul_y, Z, 1.0f, texUV[0].lr_u, texUV[0].ul_v, texUV[1].lr_u, texUV[1].ul_v, {0, 0, 0, 0}, 255 }, |
| 1396 | { s_ul_x, s_lr_y, Z, 1.0f, texUV[0].ul_u, texUV[0].lr_v, texUV[1].ul_u, texUV[1].lr_v, {0, 0, 0, 0}, 255 }, |
| 1397 | { s_lr_x, s_lr_y, Z, 1.0f, texUV[0].lr_u, texUV[0].lr_v, texUV[1].lr_u, texUV[1].lr_v, {0, 0, 0, 0}, 255 } }; |
| 1398 | |
| 1399 | if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip |
| 1400 | { |
| 1401 | vstd[1].u0 = texUV[0].ul_u; |
| 1402 | vstd[1].v0 = texUV[0].lr_v; |
| 1403 | vstd[1].u1 = texUV[1].ul_u; |
| 1404 | vstd[1].v1 = texUV[1].lr_v; |
| 1405 | |
| 1406 | vstd[2].u0 = texUV[0].lr_u; |
| 1407 | vstd[2].v0 = texUV[0].ul_v; |
| 1408 | vstd[2].u1 = texUV[1].lr_u; |
| 1409 | vstd[2].v1 = texUV[1].ul_v; |
| 1410 | } |
| 1411 | |
| 1412 | VERTEX *vptr = vstd; |
| 1413 | int n_vertices = 4; |
| 1414 | |
| 1415 | VERTEX *vnew = 0; |
| 1416 | // for (int j =0; j < 4; j++) |
| 1417 | // 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); |
| 1418 | |
| 1419 | |
| 1420 | if (!rdp.aTBuffTex[0] && rdp.cur_cache[0]->splits != 1) |
| 1421 | { |
| 1422 | // ** LARGE TEXTURE HANDLING ** |
| 1423 | // *VERY* simple algebra for texrects |
| 1424 | float min_u, min_x, max_u, max_x; |
| 1425 | if (vstd[0].u0 < vstd[1].u0) |
| 1426 | { |
| 1427 | min_u = vstd[0].u0; |
| 1428 | min_x = vstd[0].x; |
| 1429 | max_u = vstd[1].u0; |
| 1430 | max_x = vstd[1].x; |
| 1431 | } |
| 1432 | else |
| 1433 | { |
| 1434 | min_u = vstd[1].u0; |
| 1435 | min_x = vstd[1].x; |
| 1436 | max_u = vstd[0].u0; |
| 1437 | max_x = vstd[0].x; |
| 1438 | } |
| 1439 | |
| 1440 | int start_u_256, end_u_256; |
| 1441 | start_u_256 = (int)min_u >> 8; |
| 1442 | end_u_256 = (int)max_u >> 8; |
| 1443 | //FRDP(" min_u: %f, max_u: %f start: %d, end: %d\n", min_u, max_u, start_u_256, end_u_256); |
| 1444 | |
| 1445 | int splitheight = rdp.cur_cache[0]->splitheight; |
| 1446 | |
| 1447 | int num_verts_line = 2 + ((end_u_256-start_u_256)<<1); |
| 1448 | n_vertices = num_verts_line << 1; |
| 1449 | vnew = new VERTEX [n_vertices]; |
| 1450 | vptr = vnew; |
| 1451 | |
| 1452 | vnew[0] = vstd[0]; |
| 1453 | vnew[0].u0 -= 256.0f * start_u_256; |
| 1454 | vnew[0].v0 += splitheight * start_u_256; |
| 1455 | vnew[0].u1 -= 256.0f * start_u_256; |
| 1456 | vnew[0].v1 += splitheight * start_u_256; |
| 1457 | vnew[1] = vstd[2]; |
| 1458 | vnew[1].u0 -= 256.0f * start_u_256; |
| 1459 | vnew[1].v0 += splitheight * start_u_256; |
| 1460 | vnew[1].u1 -= 256.0f * start_u_256; |
| 1461 | vnew[1].v1 += splitheight * start_u_256; |
| 1462 | vnew[n_vertices-2] = vstd[1]; |
| 1463 | vnew[n_vertices-2].u0 -= 256.0f * end_u_256; |
| 1464 | vnew[n_vertices-2].v0 += splitheight * end_u_256; |
| 1465 | vnew[n_vertices-2].u1 -= 256.0f * end_u_256; |
| 1466 | vnew[n_vertices-2].v1 += splitheight * end_u_256; |
| 1467 | vnew[n_vertices-1] = vstd[3]; |
| 1468 | vnew[n_vertices-1].u0 -= 256.0f * end_u_256; |
| 1469 | vnew[n_vertices-1].v0 += splitheight * end_u_256; |
| 1470 | vnew[n_vertices-1].u1 -= 256.0f * end_u_256; |
| 1471 | vnew[n_vertices-1].v1 += splitheight * end_u_256; |
| 1472 | |
| 1473 | // find the equation of the line of u,x |
| 1474 | float m = (max_x - min_x) / (max_u - min_u); // m = delta x / delta u |
| 1475 | float b = min_x - m * min_u; // b = y - m * x |
| 1476 | |
| 1477 | for (i=start_u_256; i<end_u_256; i++) |
| 1478 | { |
| 1479 | // Find where x = current 256 multiple |
| 1480 | float x = m * ((i<<8)+256) + b; |
| 1481 | |
| 1482 | int vn = 2 + ((i-start_u_256)<<2); |
| 1483 | vnew[vn] = vstd[0]; |
| 1484 | vnew[vn].x = x; |
| 1485 | vnew[vn].u0 = 255.5f; |
| 1486 | vnew[vn].v0 += (float)splitheight * i; |
| 1487 | vnew[vn].u1 = 255.5f; |
| 1488 | vnew[vn].v1 += (float)splitheight * i; |
| 1489 | |
| 1490 | vn ++; |
| 1491 | vnew[vn] = vstd[2]; |
| 1492 | vnew[vn].x = x; |
| 1493 | vnew[vn].u0 = 255.5f; |
| 1494 | vnew[vn].v0 += (float)splitheight * i; |
| 1495 | vnew[vn].u1 = 255.5f; |
| 1496 | vnew[vn].v1 += (float)splitheight * i; |
| 1497 | |
| 1498 | vn ++; |
| 1499 | vnew[vn] = vnew[vn-2]; |
| 1500 | vnew[vn].u0 = 0.5f; |
| 1501 | vnew[vn].v0 += (float)splitheight; |
| 1502 | vnew[vn].u1 = 0.5f; |
| 1503 | vnew[vn].v1 += (float)splitheight; |
| 1504 | |
| 1505 | vn ++; |
| 1506 | vnew[vn] = vnew[vn-2]; |
| 1507 | vnew[vn].u0 = 0.5f; |
| 1508 | vnew[vn].v0 += (float)splitheight; |
| 1509 | vnew[vn].u1 = 0.5f; |
| 1510 | vnew[vn].v1 += (float)splitheight; |
| 1511 | } |
| 1512 | //* |
| 1513 | if (n_vertices > 12) |
| 1514 | { |
| 1515 | float texbound = (float)(splitheight << 1); |
| 1516 | for (int k = 0; k < n_vertices; k ++) |
| 1517 | { |
| 1518 | if (vnew[k].v0 > texbound) |
| 1519 | vnew[k].v0 = (float)fmod(vnew[k].v0, texbound); |
| 1520 | } |
| 1521 | } |
| 1522 | //*/ |
| 1523 | } |
| 1524 | |
| 1525 | AllowShadeMods (vptr, n_vertices); |
| 1526 | for (i=0; i<n_vertices; i++) |
| 1527 | { |
| 1528 | apply_shade_mods (&vptr[i]); |
| 1529 | } |
| 1530 | |
| 1531 | if (fullscreen) |
| 1532 | { |
| 1533 | if (rdp.fog_mode >= RDP::fog_blend) |
| 1534 | { |
| 1535 | float fog; |
| 1536 | if (rdp.fog_mode == RDP::fog_blend) |
| 1537 | fog = 1.0f/max(1, rdp.fog_color&0xFF); |
| 1538 | else |
| 1539 | fog = 1.0f/max(1, (~rdp.fog_color)&0xFF); |
| 1540 | for (i = 0; i < n_vertices; i++) |
| 1541 | { |
| 1542 | vptr[i].f = fog; |
| 1543 | } |
| 1544 | grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); |
| 1545 | } |
| 1546 | |
| 1547 | ConvertCoordsConvert (vptr, n_vertices); |
| 1548 | |
| 1549 | if (settings.wireframe) |
| 1550 | { |
| 1551 | SetWireframeCol (); |
| 1552 | grDrawLine (&vstd[0], &vstd[2]); |
| 1553 | grDrawLine (&vstd[2], &vstd[1]); |
| 1554 | grDrawLine (&vstd[1], &vstd[0]); |
| 1555 | grDrawLine (&vstd[2], &vstd[3]); |
| 1556 | grDrawLine (&vstd[3], &vstd[1]); |
| 1557 | } |
| 1558 | else |
| 1559 | { |
| 1560 | grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, n_vertices, vptr, sizeof(VERTEX)); |
| 1561 | } |
| 1562 | |
| 1563 | if (_debugger.capture) |
| 1564 | { |
| 1565 | VERTEX vl[3]; |
| 1566 | vl[0] = vstd[0]; |
| 1567 | vl[1] = vstd[2]; |
| 1568 | vl[2] = vstd[1]; |
| 1569 | add_tri (vl, 3, TRI_TEXRECT); |
| 1570 | rdp.tri_n ++; |
| 1571 | vl[0] = vstd[2]; |
| 1572 | vl[1] = vstd[3]; |
| 1573 | vl[2] = vstd[1]; |
| 1574 | add_tri (vl, 3, TRI_TEXRECT); |
| 1575 | rdp.tri_n ++; |
| 1576 | } |
| 1577 | else |
| 1578 | rdp.tri_n += 2; |
| 1579 | } |
| 1580 | else |
| 1581 | { |
| 1582 | rdp.tri_n += 2; |
| 1583 | } |
| 1584 | |
| 1585 | delete[] vnew; |
| 1586 | } |
| 1587 | |
| 1588 | static void rdp_loadsync() |
| 1589 | { |
| 1590 | LRDP("loadsync - ignored\n"); |
| 1591 | } |
| 1592 | |
| 1593 | static void rdp_pipesync() |
| 1594 | { |
| 1595 | LRDP("pipesync - ignored\n"); |
| 1596 | } |
| 1597 | |
| 1598 | static void rdp_tilesync() |
| 1599 | { |
| 1600 | LRDP("tilesync - ignored\n"); |
| 1601 | } |
| 1602 | |
| 1603 | static void rdp_fullsync() |
| 1604 | { |
| 1605 | // Set an interrupt to allow the game to continue |
| 1606 | *gfx.MI_INTR_REG |= 0x20; |
| 1607 | gfx.CheckInterrupts(); |
| 1608 | LRDP("fullsync\n"); |
| 1609 | } |
| 1610 | |
| 1611 | static void rdp_setkeygb() |
| 1612 | { |
| 1613 | wxUint32 sB = rdp.cmd1&0xFF; |
| 1614 | wxUint32 cB = (rdp.cmd1>>8)&0xFF; |
| 1615 | wxUint32 sG = (rdp.cmd1>>16)&0xFF; |
| 1616 | wxUint32 cG = (rdp.cmd1>>24)&0xFF; |
| 1617 | rdp.SCALE = (rdp.SCALE&0xFF0000FF) | (sG<<16) | (sB<<8); |
| 1618 | rdp.CENTER = (rdp.CENTER&0xFF0000FF) | (cG<<16) | (cB<<8); |
| 1619 | FRDP("setkeygb. cG=%02lx, sG=%02lx, cB=%02lx, sB=%02lx\n", cG, sG, cB, sB); |
| 1620 | } |
| 1621 | |
| 1622 | static void rdp_setkeyr() |
| 1623 | { |
| 1624 | wxUint32 sR = rdp.cmd1&0xFF; |
| 1625 | wxUint32 cR = (rdp.cmd1>>8)&0xFF; |
| 1626 | rdp.SCALE = (rdp.SCALE&0x00FFFFFF) | (sR<<24); |
| 1627 | rdp.CENTER = (rdp.CENTER&0x00FFFFFF) | (cR<<24); |
| 1628 | FRDP("setkeyr. cR=%02lx, sR=%02lx\n", cR, sR); |
| 1629 | } |
| 1630 | |
| 1631 | static void rdp_setconvert() |
| 1632 | { |
| 1633 | /* |
| 1634 | rdp.YUV_C0 = 1.1647f ; |
| 1635 | rdp.YUV_C1 = 0.79931f ; |
| 1636 | rdp.YUV_C2 = -0.1964f ; |
| 1637 | rdp.YUV_C3 = -0.40651f; |
| 1638 | rdp.YUV_C4 = 1.014f ; |
| 1639 | */ |
| 1640 | rdp.K4 = (wxUint8)(rdp.cmd1>>9)&0x1FF; |
| 1641 | rdp.K5 = (wxUint8)(rdp.cmd1&0x1FF); |
| 1642 | // RDP_E("setconvert - IGNORED\n"); |
| 1643 | FRDP("setconvert. K4=%02lx K5=%02lx\n", rdp.K4, rdp.K5); |
| 1644 | } |
| 1645 | |
| 1646 | // |
| 1647 | // setscissor - sets the screen clipping rectangle |
| 1648 | // |
| 1649 | |
| 1650 | static void rdp_setscissor() |
| 1651 | { |
| 1652 | // clipper resolution is 320x240, scale based on computer resolution |
| 1653 | rdp.scissor_o.ul_x = /*min(*/(wxUint32)(((rdp.cmd0 & 0x00FFF000) >> 14))/*, 320)*/; |
| 1654 | rdp.scissor_o.ul_y = /*min(*/(wxUint32)(((rdp.cmd0 & 0x00000FFF) >> 2))/*, 240)*/; |
| 1655 | rdp.scissor_o.lr_x = /*min(*/(wxUint32)(((rdp.cmd1 & 0x00FFF000) >> 14))/*, 320)*/; |
| 1656 | rdp.scissor_o.lr_y = /*min(*/(wxUint32)(((rdp.cmd1 & 0x00000FFF) >> 2))/*, 240)*/; |
| 1657 | |
| 1658 | rdp.ci_upper_bound = rdp.scissor_o.ul_y; |
| 1659 | rdp.ci_lower_bound = rdp.scissor_o.lr_y; |
| 1660 | rdp.scissor_set = TRUE; |
| 1661 | |
| 1662 | FRDP("setscissor: (%d,%d) -> (%d,%d)\n", rdp.scissor_o.ul_x, rdp.scissor_o.ul_y, |
| 1663 | rdp.scissor_o.lr_x, rdp.scissor_o.lr_y); |
| 1664 | |
| 1665 | rdp.update |= UPDATE_SCISSOR; |
| 1666 | |
| 1667 | if (rdp.view_scale[0] == 0) //viewport is not set? |
| 1668 | { |
| 1669 | rdp.view_scale[0] = (rdp.scissor_o.lr_x>>1)*rdp.scale_x; |
| 1670 | rdp.view_scale[1] = (rdp.scissor_o.lr_y>>1)*-rdp.scale_y; |
| 1671 | rdp.view_trans[0] = rdp.view_scale[0]; |
| 1672 | rdp.view_trans[1] = -rdp.view_scale[1]; |
| 1673 | rdp.update |= UPDATE_VIEWPORT; |
| 1674 | } |
| 1675 | } |
| 1676 | |
| 1677 | static void rdp_setprimdepth() |
| 1678 | { |
| 1679 | rdp.prim_depth = (wxUint16)((rdp.cmd1 >> 16) & 0x7FFF); |
| 1680 | rdp.prim_dz = (wxUint16)(rdp.cmd1 & 0x7FFF); |
| 1681 | |
| 1682 | FRDP("setprimdepth: %d\n", rdp.prim_depth); |
| 1683 | } |
| 1684 | |
| 1685 | static void rdp_setothermode() |
| 1686 | { |
| 1687 | #define F3DEX2_SETOTHERMODE(cmd,sft,len,data) { \ |
| 1688 | rdp.cmd0 = (cmd<<24) | ((32-(sft)-(len))<<8) | (((len)-1)); \ |
| 1689 | rdp.cmd1 = data; \ |
| 1690 | gfx_instruction[settings.ucode][cmd] (); \ |
| 1691 | } |
| 1692 | #define SETOTHERMODE(cmd,sft,len,data) { \ |
| 1693 | rdp.cmd0 = (cmd<<24) | ((sft)<<8) | (len); \ |
| 1694 | rdp.cmd1 = data; \ |
| 1695 | gfx_instruction[settings.ucode][cmd] (); \ |
| 1696 | } |
| 1697 | |
| 1698 | LRDP("rdp_setothermode\n"); |
| 1699 | |
| 1700 | if ((settings.ucode == ucode_F3DEX2) || (settings.ucode == ucode_CBFD)) |
| 1701 | { |
| 1702 | int cmd0 = rdp.cmd0; |
| 1703 | F3DEX2_SETOTHERMODE(0xE2, 0, 32, rdp.cmd1); // SETOTHERMODE_L |
| 1704 | F3DEX2_SETOTHERMODE(0xE3, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H |
| 1705 | } |
| 1706 | else |
| 1707 | { |
| 1708 | int cmd0 = rdp.cmd0; |
| 1709 | SETOTHERMODE(0xB9, 0, 32, rdp.cmd1); // SETOTHERMODE_L |
| 1710 | SETOTHERMODE(0xBA, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H |
| 1711 | } |
| 1712 | } |
| 1713 | |
| 1714 | void load_palette (wxUint32 addr, wxUint16 start, wxUint16 count) |
| 1715 | { |
| 1716 | LRDP("Loading palette... "); |
| 1717 | wxUint16 *dpal = rdp.pal_8 + start; |
| 1718 | wxUint16 end = start+count; |
| 1719 | #ifdef TEXTURE_FILTER |
| 1720 | wxUint16 *spal = (wxUint16*)(gfx.RDRAM + (addr & BMASK)); |
| 1721 | #endif |
| 1722 | |
| 1723 | for (wxUint16 i=start; i<end; i++) |
| 1724 | { |
| 1725 | *(dpal++) = *(wxUint16 *)(gfx.RDRAM + (addr^2)); |
| 1726 | addr += 2; |
| 1727 | |
| 1728 | #ifdef TLUT_LOGGING |
| 1729 | FRDP ("%d: %08lx\n", i, *(wxUint16 *)(gfx.RDRAM + (addr^2))); |
| 1730 | #endif |
| 1731 | } |
| 1732 | #ifdef TEXTURE_FILTER |
| 1733 | if (settings.ghq_hirs) |
| 1734 | memcpy((wxUint8*)(rdp.pal_8_rice+start), spal, count<<1); |
| 1735 | #endif |
| 1736 | start >>= 4; |
| 1737 | end = start + (count >> 4); |
| 1738 | if (end == start) // it can be if count < 16 |
| 1739 | end = start + 1; |
| 1740 | for (wxUint16 p = start; p < end; p++) |
| 1741 | { |
| 1742 | rdp.pal_8_crc[p] = CRC32( 0xFFFFFFFF, &rdp.pal_8[(p << 4)], 32 ); |
| 1743 | } |
| 1744 | rdp.pal_256_crc = CRC32( 0xFFFFFFFF, rdp.pal_8_crc, 64 ); |
| 1745 | LRDP("Done.\n"); |
| 1746 | } |
| 1747 | |
| 1748 | static void rdp_loadtlut() |
| 1749 | { |
| 1750 | wxUint32 tile = (rdp.cmd1 >> 24) & 0x07; |
| 1751 | wxUint16 start = rdp.tiles[tile].t_mem - 256; // starting location in the palettes |
| 1752 | // wxUint16 start = ((wxUint16)(rdp.cmd1 >> 2) & 0x3FF) + 1; |
| 1753 | wxUint16 count = ((wxUint16)(rdp.cmd1 >> 14) & 0x3FF) + 1; // number to copy |
| 1754 | |
| 1755 | if (rdp.timg.addr + (count<<1) > BMASK) |
| 1756 | count = (wxUint16)((BMASK - rdp.timg.addr) >> 1); |
| 1757 | |
| 1758 | if (start+count > 256) count = 256-start; |
| 1759 | |
| 1760 | FRDP("loadtlut: tile: %d, start: %d, count: %d, from: %08lx\n", tile, start, count, |
| 1761 | rdp.timg.addr); |
| 1762 | |
| 1763 | load_palette (rdp.timg.addr, start, count); |
| 1764 | |
| 1765 | rdp.timg.addr += count << 1; |
| 1766 | |
| 1767 | if (rdp.tbuff_tex) //paranoid check. |
| 1768 | { |
| 1769 | //the buffer is definitely wrong, as there must be no CI frame buffers |
| 1770 | //find and remove it |
| 1771 | for (int i = 0; i < voodoo.num_tmu; i++) |
| 1772 | { |
| 1773 | for (int j = 0; j < rdp.texbufs[i].count; j++) |
| 1774 | { |
| 1775 | if (&(rdp.texbufs[i].images[j]) == rdp.tbuff_tex) |
| 1776 | { |
| 1777 | rdp.texbufs[i].count--; |
| 1778 | if (j < rdp.texbufs[i].count) |
| 1779 | memcpy(&(rdp.texbufs[i].images[j]), &(rdp.texbufs[i].images[j+1]), sizeof(TBUFF_COLOR_IMAGE)*(rdp.texbufs[i].count-j)); |
| 1780 | return; |
| 1781 | } |
| 1782 | } |
| 1783 | } |
| 1784 | } |
| 1785 | } |
| 1786 | |
| 1787 | int tile_set = 0; |
| 1788 | static void rdp_settilesize() |
| 1789 | { |
| 1790 | wxUint32 tile = (rdp.cmd1 >> 24) & 0x07; |
| 1791 | rdp.last_tile_size = tile; |
| 1792 | |
| 1793 | rdp.tiles[tile].f_ul_s = (float)((rdp.cmd0 >> 12) & 0xFFF) / 4.0f; |
| 1794 | rdp.tiles[tile].f_ul_t = (float)(rdp.cmd0 & 0xFFF) / 4.0f; |
| 1795 | |
| 1796 | int ul_s = (((wxUint16)(rdp.cmd0 >> 14)) & 0x03ff); |
| 1797 | int ul_t = (((wxUint16)(rdp.cmd0 >> 2 )) & 0x03ff); |
| 1798 | int lr_s = (((wxUint16)(rdp.cmd1 >> 14)) & 0x03ff); |
| 1799 | int lr_t = (((wxUint16)(rdp.cmd1 >> 2 )) & 0x03ff); |
| 1800 | |
| 1801 | if (lr_s == 0 && ul_s == 0) //pokemon puzzle league set such tile size |
| 1802 | wrong_tile = tile; |
| 1803 | else if (wrong_tile == (int)tile) |
| 1804 | wrong_tile = -1; |
| 1805 | |
| 1806 | if (settings.use_sts1_only) |
| 1807 | { |
| 1808 | // ** USE FIRST SETTILESIZE ONLY ** |
| 1809 | // This option helps certain textures while using the 'Alternate texture size method', |
| 1810 | // but may break others. (should help more than break) |
| 1811 | |
| 1812 | if (tile_set) |
| 1813 | { |
| 1814 | // coords in 10.2 format |
| 1815 | rdp.tiles[tile].ul_s = ul_s; |
| 1816 | rdp.tiles[tile].ul_t = ul_t; |
| 1817 | rdp.tiles[tile].lr_s = lr_s; |
| 1818 | rdp.tiles[tile].lr_t = lr_t; |
| 1819 | tile_set = 0; |
| 1820 | } |
| 1821 | } |
| 1822 | else |
| 1823 | { |
| 1824 | // coords in 10.2 format |
| 1825 | rdp.tiles[tile].ul_s = ul_s; |
| 1826 | rdp.tiles[tile].ul_t = ul_t; |
| 1827 | rdp.tiles[tile].lr_s = lr_s; |
| 1828 | rdp.tiles[tile].lr_t = lr_t; |
| 1829 | } |
| 1830 | |
| 1831 | // handle wrapping |
| 1832 | if (rdp.tiles[tile].lr_s < rdp.tiles[tile].ul_s) rdp.tiles[tile].lr_s += 0x400; |
| 1833 | if (rdp.tiles[tile].lr_t < rdp.tiles[tile].ul_t) rdp.tiles[tile].lr_t += 0x400; |
| 1834 | |
| 1835 | rdp.update |= UPDATE_TEXTURE; |
| 1836 | |
| 1837 | rdp.first = 1; |
| 1838 | |
| 1839 | FRDP ("settilesize: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d, f_ul_s: %f, f_ul_t: %f\n", |
| 1840 | tile, ul_s, ul_t, lr_s, lr_t, rdp.tiles[tile].f_ul_s, rdp.tiles[tile].f_ul_t); |
| 1841 | } |
| 1842 | |
| 1843 | void setTBufTex(wxUint16 t_mem, wxUint32 cnt) |
| 1844 | { |
| 1845 | FRDP("setTBufTex t_mem=%d, cnt=%d\n", t_mem, cnt); |
| 1846 | TBUFF_COLOR_IMAGE * pTbufTex = rdp.tbuff_tex; |
| 1847 | for (int i = 0; i < 2; i++) |
| 1848 | { |
| 1849 | LRDP("Before: "); |
| 1850 | if (rdp.aTBuffTex[i]) { |
| 1851 | FRDP("rdp.aTBuffTex[%d]: tmu=%d t_mem=%d tile=%d\n", i, rdp.aTBuffTex[i]->tmu, rdp.aTBuffTex[i]->t_mem, rdp.aTBuffTex[i]->tile); |
| 1852 | } else { |
| 1853 | FRDP("rdp.aTBuffTex[%d]=0\n", i); |
| 1854 | } |
| 1855 | if ((rdp.aTBuffTex[i] == 0 && rdp.aTBuffTex[i^1] != pTbufTex) || (rdp.aTBuffTex[i] && rdp.aTBuffTex[i]->t_mem >= t_mem && rdp.aTBuffTex[i]->t_mem < t_mem + cnt)) |
| 1856 | { |
| 1857 | if (pTbufTex) |
| 1858 | { |
| 1859 | rdp.aTBuffTex[i] = pTbufTex; |
| 1860 | rdp.aTBuffTex[i]->t_mem = t_mem; |
| 1861 | pTbufTex = 0; |
| 1862 | FRDP("rdp.aTBuffTex[%d] tmu=%d t_mem=%d\n", i, rdp.aTBuffTex[i]->tmu, rdp.aTBuffTex[i]->t_mem); |
| 1863 | } |
| 1864 | else |
| 1865 | { |
| 1866 | rdp.aTBuffTex[i] = 0; |
| 1867 | FRDP("rdp.aTBuffTex[%d]=0\n", i); |
| 1868 | } |
| 1869 | } |
| 1870 | } |
| 1871 | } |
| 1872 | |
| 1873 | static inline void loadBlock(uint32_t *src, uint32_t *dst, uint32_t off, int dxt, int cnt) |
| 1874 | { |
| 1875 | uint32_t *v5; |
| 1876 | int v6; |
| 1877 | uint32_t *v7; |
| 1878 | uint32_t v8; |
| 1879 | int v9; |
| 1880 | uint32_t v10; |
| 1881 | uint32_t *v11; |
| 1882 | uint32_t v12; |
| 1883 | uint32_t v13; |
| 1884 | uint32_t v14; |
| 1885 | int v15; |
| 1886 | int v16; |
| 1887 | uint32_t *v17; |
| 1888 | int v18; |
| 1889 | uint32_t v19; |
| 1890 | uint32_t v20; |
| 1891 | int i; |
| 1892 | |
| 1893 | v5 = dst; |
| 1894 | v6 = cnt; |
| 1895 | if ( cnt ) |
| 1896 | { |
| 1897 | v7 = (uint32_t *)((char *)src + (off & 0xFFFFFFFC)); |
| 1898 | v8 = off & 3; |
| 1899 | if ( !(off & 3) ) |
| 1900 | goto LABEL_23; |
| 1901 | v9 = 4 - v8; |
| 1902 | v10 = *v7; |
| 1903 | v11 = v7 + 1; |
| 1904 | do |
| 1905 | { |
| 1906 | v10 = __ROL__(v10, 8); |
| 1907 | --v8; |
| 1908 | } |
| 1909 | while ( v8 ); |
| 1910 | do |
| 1911 | { |
| 1912 | v10 = __ROL__(v10, 8); |
| 1913 | *(uint8_t *)v5 = v10; |
| 1914 | v5 = (uint32_t *)((char *)v5 + 1); |
| 1915 | --v9; |
| 1916 | } |
| 1917 | while ( v9 ); |
| 1918 | v12 = *v11; |
| 1919 | v7 = v11 + 1; |
| 1920 | *v5 = bswap32(v12); |
| 1921 | ++v5; |
| 1922 | v6 = cnt - 1; |
| 1923 | if ( cnt != 1 ) |
| 1924 | { |
| 1925 | LABEL_23: |
| 1926 | do |
| 1927 | { |
| 1928 | *v5 = bswap32(*v7); |
| 1929 | v5[1] = bswap32(v7[1]); |
| 1930 | v7 += 2; |
| 1931 | v5 += 2; |
| 1932 | --v6; |
| 1933 | } |
| 1934 | while ( v6 ); |
| 1935 | } |
| 1936 | v13 = off & 3; |
| 1937 | if ( off & 3 ) |
| 1938 | { |
| 1939 | v14 = *(uint32_t *)((char *)src + ((8 * cnt + off) & 0xFFFFFFFC)); |
| 1940 | do |
| 1941 | { |
| 1942 | v14 = __ROL__(v14, 8); |
| 1943 | *(uint8_t *)v5 = v14; |
| 1944 | v5 = (uint32_t *)((char *)v5 + 1); |
| 1945 | --v13; |
| 1946 | } |
| 1947 | while ( v13 ); |
| 1948 | } |
| 1949 | } |
| 1950 | v15 = cnt; |
| 1951 | v16 = 0; |
| 1952 | v17 = dst; |
| 1953 | v18 = 0; |
| 1954 | dxt_test: |
| 1955 | while ( 1 ) |
| 1956 | { |
| 1957 | v17 += 2; |
| 1958 | --v15; |
| 1959 | if ( !v15 ) |
| 1960 | break; |
| 1961 | v16 += dxt; |
| 1962 | if ( v16 < 0 ) |
| 1963 | { |
| 1964 | while ( 1 ) |
| 1965 | { |
| 1966 | ++v18; |
| 1967 | --v15; |
| 1968 | if ( !v15 ) |
| 1969 | goto end_dxt_test; |
| 1970 | v16 += dxt; |
| 1971 | if ( v16 >= 0 ) |
| 1972 | { |
| 1973 | for ( i = v15; v18; --v18 ) |
| 1974 | { |
| 1975 | v19 = *v17; |
| 1976 | *v17 = v17[1]; |
| 1977 | v17[1] = v19; |
| 1978 | v17 += 2; |
| 1979 | } |
| 1980 | v15 = i; |
| 1981 | goto dxt_test; |
| 1982 | } |
| 1983 | } |
| 1984 | } |
| 1985 | } |
| 1986 | end_dxt_test: |
| 1987 | while ( v18 ) |
| 1988 | { |
| 1989 | v20 = *v17; |
| 1990 | *v17 = v17[1]; |
| 1991 | v17[1] = v20; |
| 1992 | v17 += 2; |
| 1993 | --v18; |
| 1994 | } |
| 1995 | } |
| 1996 | |
| 1997 | void LoadBlock32b(wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 lr_s, wxUint32 dxt); |
| 1998 | static void rdp_loadblock() |
| 1999 | { |
| 2000 | if (rdp.skip_drawing) |
| 2001 | { |
| 2002 | LRDP("loadblock skipped\n"); |
| 2003 | return; |
| 2004 | } |
| 2005 | wxUint32 tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07); |
| 2006 | wxUint32 dxt = (wxUint32)(rdp.cmd1 & 0x0FFF); |
| 2007 | wxUint16 lr_s = (wxUint16)(rdp.cmd1 >> 14) & 0x3FF; |
| 2008 | if (ucode5_texshiftaddr) |
| 2009 | { |
| 2010 | if (ucode5_texshift % ((lr_s+1)<<3)) |
| 2011 | { |
| 2012 | rdp.timg.addr -= ucode5_texshift; |
| 2013 | ucode5_texshiftaddr = 0; |
| 2014 | ucode5_texshift = 0; |
| 2015 | ucode5_texshiftcount = 0; |
| 2016 | } |
| 2017 | else |
| 2018 | ucode5_texshiftcount++; |
| 2019 | } |
| 2020 | |
| 2021 | rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr; |
| 2022 | |
| 2023 | // ** DXT is used for swapping every other line |
| 2024 | /* double fdxt = (double)0x8000000F/(double)((wxUint32)(2047/(dxt-1))); // F for error |
| 2025 | wxUint32 _dxt = (wxUint32)fdxt;*/ |
| 2026 | |
| 2027 | // 0x00000800 -> 0x80000000 (so we can check the sign bit instead of the 11th bit) |
| 2028 | wxUint32 _dxt = dxt << 20; |
| 2029 | |
| 2030 | wxUint32 addr = segoffset(rdp.timg.addr) & BMASK; |
| 2031 | |
| 2032 | // lr_s specifies number of 64-bit words to copy |
| 2033 | // 10.2 format |
| 2034 | wxUint16 ul_s = (wxUint16)(rdp.cmd0 >> 14) & 0x3FF; |
| 2035 | wxUint16 ul_t = (wxUint16)(rdp.cmd0 >> 2) & 0x3FF; |
| 2036 | |
| 2037 | rdp.tiles[tile].ul_s = ul_s; |
| 2038 | rdp.tiles[tile].ul_t = ul_t; |
| 2039 | rdp.tiles[tile].lr_s = lr_s; |
| 2040 | |
| 2041 | rdp.timg.set_by = 0; // load block |
| 2042 | |
| 2043 | #ifdef TEXTURE_FILTER |
| 2044 | LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[tile].t_mem]; |
| 2045 | info.tile_width = lr_s; |
| 2046 | info.dxt = dxt; |
| 2047 | #endif |
| 2048 | |
| 2049 | // do a quick boundary check before copying to eliminate the possibility for exception |
| 2050 | if (ul_s >= 512) { |
| 2051 | lr_s = 1; // 1 so that it doesn't die on memcpy |
| 2052 | ul_s = 511; |
| 2053 | } |
| 2054 | if (ul_s+lr_s > 512) |
| 2055 | lr_s = 512-ul_s; |
| 2056 | |
| 2057 | if (addr+(lr_s<<3) > BMASK+1) |
| 2058 | lr_s = (wxUint16)((BMASK-addr)>>3); |
| 2059 | |
| 2060 | //angrylion's advice to use ul_s in texture image offset and cnt calculations. |
| 2061 | //Helps to fix Vigilante 8 jpeg backgrounds and logos |
| 2062 | wxUint32 off = rdp.timg.addr + (ul_s << rdp.tiles[tile].size >> 1); |
| 2063 | unsigned char *dst = ((unsigned char *)rdp.tmem) + (rdp.tiles[tile].t_mem<<3); |
| 2064 | wxUint32 cnt = lr_s-ul_s+1; |
| 2065 | if (rdp.tiles[tile].size == 3) |
| 2066 | cnt <<= 1; |
| 2067 | |
| 2068 | if (((rdp.tiles[tile].t_mem + cnt) << 3) > sizeof(rdp.tmem)) { |
| 2069 | WriteLog(M64MSG_INFO, "rdp_loadblock wanted to write %u bytes after the end of tmem", ((rdp.tiles[tile].t_mem + cnt) << 3) - sizeof(rdp.tmem)); |
| 2070 | cnt = (sizeof(rdp.tmem) >> 3) - (rdp.tiles[tile].t_mem); |
| 2071 | } |
| 2072 | |
| 2073 | if (rdp.timg.size == 3) |
| 2074 | LoadBlock32b(tile, ul_s, ul_t, lr_s, dxt); |
| 2075 | else |
| 2076 | loadBlock((uint32_t *)gfx.RDRAM, (uint32_t *)dst, off, _dxt, cnt); |
| 2077 | |
| 2078 | rdp.timg.addr += cnt << 3; |
| 2079 | rdp.tiles[tile].lr_t = ul_t + ((dxt*cnt)>>11); |
| 2080 | |
| 2081 | rdp.update |= UPDATE_TEXTURE; |
| 2082 | |
| 2083 | FRDP ("loadblock: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, dxt: %08lx -> %08lx\n", |
| 2084 | tile, ul_s, ul_t, lr_s, |
| 2085 | dxt, _dxt); |
| 2086 | |
| 2087 | if (fb_hwfbe_enabled) |
| 2088 | setTBufTex(rdp.tiles[tile].t_mem, cnt); |
| 2089 | } |
| 2090 | |
| 2091 | |
| 2092 | static inline void loadTile(uint32_t *src, uint32_t *dst, int width, int height, int line, int off, uint32_t *end) |
| 2093 | { |
| 2094 | uint32_t *v7; |
| 2095 | int v8; |
| 2096 | uint32_t *v9; |
| 2097 | int v10; |
| 2098 | int v11; |
| 2099 | int v12; |
| 2100 | uint32_t *v13; |
| 2101 | int v14; |
| 2102 | int v15; |
| 2103 | uint32_t v16; |
| 2104 | uint32_t *v17; |
| 2105 | uint32_t v18; |
| 2106 | int v19; |
| 2107 | uint32_t v20; |
| 2108 | int v21; |
| 2109 | uint32_t v22; |
| 2110 | int v23; |
| 2111 | uint32_t *v24; |
| 2112 | int v25; |
| 2113 | int v26; |
| 2114 | uint32_t *v27; |
| 2115 | int v28; |
| 2116 | int v29; |
| 2117 | int v30; |
| 2118 | uint32_t *v31; |
| 2119 | |
| 2120 | v7 = dst; |
| 2121 | v8 = width; |
| 2122 | v9 = src; |
| 2123 | v10 = off; |
| 2124 | v11 = 0; |
| 2125 | v12 = height; |
| 2126 | do |
| 2127 | { |
| 2128 | if ( end < v7 ) |
| 2129 | break; |
| 2130 | v31 = v7; |
| 2131 | v30 = v8; |
| 2132 | v29 = v12; |
| 2133 | v28 = v11; |
| 2134 | v27 = v9; |
| 2135 | v26 = v10; |
| 2136 | if ( v8 ) |
| 2137 | { |
| 2138 | v25 = v8; |
| 2139 | v24 = v9; |
| 2140 | v23 = v10; |
| 2141 | v13 = (uint32_t *)((char *)v9 + (v10 & 0xFFFFFFFC)); |
| 2142 | v14 = v10 & 3; |
| 2143 | if ( !(v10 & 3) ) |
| 2144 | goto LABEL_20; |
| 2145 | v15 = 4 - v14; |
| 2146 | v16 = *v13; |
| 2147 | v17 = v13 + 1; |
| 2148 | do |
| 2149 | { |
| 2150 | v16 = __ROL__(v16, 8); |
| 2151 | --v14; |
| 2152 | } |
| 2153 | while ( v14 ); |
| 2154 | do |
| 2155 | { |
| 2156 | v16 = __ROL__(v16, 8); |
| 2157 | *(uint8_t *)v7 = v16; |
| 2158 | v7 = (uint32_t *)((char *)v7 + 1); |
| 2159 | --v15; |
| 2160 | } |
| 2161 | while ( v15 ); |
| 2162 | v18 = *v17; |
| 2163 | v13 = v17 + 1; |
| 2164 | *v7 = bswap32(v18); |
| 2165 | ++v7; |
| 2166 | --v8; |
| 2167 | if ( v8 ) |
| 2168 | { |
| 2169 | LABEL_20: |
| 2170 | do |
| 2171 | { |
| 2172 | *v7 = bswap32(*v13); |
| 2173 | v7[1] = bswap32(v13[1]); |
| 2174 | v13 += 2; |
| 2175 | v7 += 2; |
| 2176 | --v8; |
| 2177 | } |
| 2178 | while ( v8 ); |
| 2179 | } |
| 2180 | v19 = v23 & 3; |
| 2181 | if ( v23 & 3 ) |
| 2182 | { |
| 2183 | v20 = *(uint32_t *)((char *)v24 + ((8 * v25 + v23) & 0xFFFFFFFC)); |
| 2184 | do |
| 2185 | { |
| 2186 | v20 = __ROL__(v20, 8); |
| 2187 | *(uint8_t *)v7 = v20; |
| 2188 | v7 = (uint32_t *)((char *)v7 + 1); |
| 2189 | --v19; |
| 2190 | } |
| 2191 | while ( v19 ); |
| 2192 | } |
| 2193 | } |
| 2194 | v9 = v27; |
| 2195 | v21 = v29; |
| 2196 | v8 = v30; |
| 2197 | v11 = v28 ^ 1; |
| 2198 | if ( v28 == 1 ) |
| 2199 | { |
| 2200 | v7 = v31; |
| 2201 | if ( v30 ) |
| 2202 | { |
| 2203 | do |
| 2204 | { |
| 2205 | v22 = *v7; |
| 2206 | *v7 = v7[1]; |
| 2207 | v7[1] = v22; |
| 2208 | v7 += 2; |
| 2209 | --v8; |
| 2210 | } |
| 2211 | while ( v8 ); |
| 2212 | } |
| 2213 | v21 = v29; |
| 2214 | v8 = v30; |
| 2215 | } |
| 2216 | v10 = line + v26; |
| 2217 | v12 = v21 - 1; |
| 2218 | } |
| 2219 | while ( v12 ); |
| 2220 | } |
| 2221 | |
| 2222 | void LoadTile32b (wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 width, wxUint32 height); |
| 2223 | static void rdp_loadtile() |
| 2224 | { |
| 2225 | if (rdp.skip_drawing) |
| 2226 | { |
| 2227 | LRDP("loadtile skipped\n"); |
| 2228 | return; |
| 2229 | } |
| 2230 | rdp.timg.set_by = 1; // load tile |
| 2231 | |
| 2232 | wxUint32 tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07); |
| 2233 | |
| 2234 | rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr; |
| 2235 | |
| 2236 | wxUint16 ul_s = (wxUint16)((rdp.cmd0 >> 14) & 0x03FF); |
| 2237 | wxUint16 ul_t = (wxUint16)((rdp.cmd0 >> 2 ) & 0x03FF); |
| 2238 | wxUint16 lr_s = (wxUint16)((rdp.cmd1 >> 14) & 0x03FF); |
| 2239 | wxUint16 lr_t = (wxUint16)((rdp.cmd1 >> 2 ) & 0x03FF); |
| 2240 | |
| 2241 | if (lr_s < ul_s || lr_t < ul_t) return; |
| 2242 | |
| 2243 | if (wrong_tile >= 0) //there was a tile with zero length |
| 2244 | { |
| 2245 | rdp.tiles[wrong_tile].lr_s = lr_s; |
| 2246 | |
| 2247 | if (rdp.tiles[tile].size > rdp.tiles[wrong_tile].size) |
| 2248 | rdp.tiles[wrong_tile].lr_s <<= (rdp.tiles[tile].size - rdp.tiles[wrong_tile].size); |
| 2249 | else if (rdp.tiles[tile].size < rdp.tiles[wrong_tile].size) |
| 2250 | rdp.tiles[wrong_tile].lr_s >>= (rdp.tiles[wrong_tile].size - rdp.tiles[tile].size); |
| 2251 | rdp.tiles[wrong_tile].lr_t = lr_t; |
| 2252 | rdp.tiles[wrong_tile].mask_s = rdp.tiles[wrong_tile].mask_t = 0; |
| 2253 | // wrong_tile = -1; |
| 2254 | } |
| 2255 | |
| 2256 | if (rdp.tbuff_tex)// && (rdp.tiles[tile].format == 0)) |
| 2257 | { |
| 2258 | FRDP("loadtile: tbuff_tex ul_s: %d, ul_t:%d\n", ul_s, ul_t); |
| 2259 | rdp.tbuff_tex->tile_uls = ul_s; |
| 2260 | rdp.tbuff_tex->tile_ult = ul_t; |
| 2261 | } |
| 2262 | |
| 2263 | if ((settings.hacks&hack_Tonic) && tile == 7) |
| 2264 | { |
| 2265 | rdp.tiles[0].ul_s = ul_s; |
| 2266 | rdp.tiles[0].ul_t = ul_t; |
| 2267 | rdp.tiles[0].lr_s = lr_s; |
| 2268 | rdp.tiles[0].lr_t = lr_t; |
| 2269 | } |
| 2270 | |
| 2271 | wxUint32 height = lr_t - ul_t + 1; // get height |
| 2272 | wxUint32 width = lr_s - ul_s + 1; |
| 2273 | |
| 2274 | #ifdef TEXTURE_FILTER |
| 2275 | LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[tile].t_mem]; |
| 2276 | info.tile_ul_s = ul_s; |
| 2277 | info.tile_ul_t = ul_t; |
| 2278 | info.tile_width = (rdp.tiles[tile].mask_s ? min((wxUint16)width, 1<<rdp.tiles[tile].mask_s) : (wxUint16)width); |
| 2279 | info.tile_height = (rdp.tiles[tile].mask_t ? min((wxUint16)height, 1<<rdp.tiles[tile].mask_t) : (wxUint16)height); |
| 2280 | if (settings.hacks&hack_MK64) { |
| 2281 | if (info.tile_width%2) |
| 2282 | info.tile_width--; |
| 2283 | if (info.tile_height%2) |
| 2284 | info.tile_height--; |
| 2285 | } |
| 2286 | info.tex_width = rdp.timg.width; |
| 2287 | info.tex_size = rdp.timg.size; |
| 2288 | #endif |
| 2289 | |
| 2290 | int line_n = rdp.timg.width << rdp.tiles[tile].size >> 1; |
| 2291 | wxUint32 offs = ul_t * line_n; |
| 2292 | offs += ul_s << rdp.tiles[tile].size >> 1; |
| 2293 | offs += rdp.timg.addr; |
| 2294 | if (offs >= BMASK) |
| 2295 | return; |
| 2296 | |
| 2297 | if (rdp.timg.size == 3) |
| 2298 | { |
| 2299 | LoadTile32b(tile, ul_s, ul_t, width, height); |
| 2300 | } |
| 2301 | else |
| 2302 | { |
| 2303 | // check if points to bad location |
| 2304 | if (offs + line_n*height > BMASK) |
| 2305 | height = (BMASK - offs) / line_n; |
| 2306 | if (height == 0) |
| 2307 | return; |
| 2308 | |
| 2309 | wxUint32 wid_64 = rdp.tiles[tile].line; |
| 2310 | unsigned char *dst = ((unsigned char *)rdp.tmem) + (rdp.tiles[tile].t_mem<<3); |
| 2311 | unsigned char *end = ((unsigned char *)rdp.tmem) + 4096 - (wid_64<<3); |
| 2312 | loadTile((uint32_t *)gfx.RDRAM, (uint32_t *)dst, wid_64, height, line_n, offs, (uint32_t *)end); |
| 2313 | } |
| 2314 | FRDP("loadtile: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d\n", tile, |
| 2315 | ul_s, ul_t, lr_s, lr_t); |
| 2316 | |
| 2317 | if (fb_hwfbe_enabled) |
| 2318 | setTBufTex(rdp.tiles[tile].t_mem, rdp.tiles[tile].line*height); |
| 2319 | } |
| 2320 | |
| 2321 | static void rdp_settile() |
| 2322 | { |
| 2323 | tile_set = 1; // used to check if we only load the first settilesize |
| 2324 | |
| 2325 | rdp.first = 0; |
| 2326 | |
| 2327 | rdp.last_tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07); |
| 2328 | TILE *tile = &rdp.tiles[rdp.last_tile]; |
| 2329 | |
| 2330 | tile->format = (wxUint8)((rdp.cmd0 >> 21) & 0x07); |
| 2331 | tile->size = (wxUint8)((rdp.cmd0 >> 19) & 0x03); |
| 2332 | tile->line = (wxUint16)((rdp.cmd0 >> 9) & 0x01FF); |
| 2333 | tile->t_mem = (wxUint16)(rdp.cmd0 & 0x1FF); |
| 2334 | tile->palette = (wxUint8)((rdp.cmd1 >> 20) & 0x0F); |
| 2335 | tile->clamp_t = (wxUint8)((rdp.cmd1 >> 19) & 0x01); |
| 2336 | tile->mirror_t = (wxUint8)((rdp.cmd1 >> 18) & 0x01); |
| 2337 | tile->mask_t = (wxUint8)((rdp.cmd1 >> 14) & 0x0F); |
| 2338 | tile->shift_t = (wxUint8)((rdp.cmd1 >> 10) & 0x0F); |
| 2339 | tile->clamp_s = (wxUint8)((rdp.cmd1 >> 9) & 0x01); |
| 2340 | tile->mirror_s = (wxUint8)((rdp.cmd1 >> 8) & 0x01); |
| 2341 | tile->mask_s = (wxUint8)((rdp.cmd1 >> 4) & 0x0F); |
| 2342 | tile->shift_s = (wxUint8)(rdp.cmd1 & 0x0F); |
| 2343 | |
| 2344 | rdp.update |= UPDATE_TEXTURE; |
| 2345 | |
| 2346 | FRDP ("settile: tile: %d, format: %s, size: %s, line: %d, " |
| 2347 | "t_mem: %08lx, palette: %d, clamp_t/mirror_t: %s, mask_t: %d, " |
| 2348 | "shift_t: %d, clamp_s/mirror_s: %s, mask_s: %d, shift_s: %d\n", |
| 2349 | rdp.last_tile, str_format[tile->format], str_size[tile->size], tile->line, |
| 2350 | tile->t_mem, tile->palette, str_cm[(tile->clamp_t<<1)|tile->mirror_t], tile->mask_t, |
| 2351 | tile->shift_t, str_cm[(tile->clamp_s<<1)|tile->mirror_s], tile->mask_s, tile->shift_s); |
| 2352 | |
| 2353 | if (fb_hwfbe_enabled && rdp.last_tile < rdp.cur_tile + 2) |
| 2354 | { |
| 2355 | for (int i = 0; i < 2; i++) |
| 2356 | { |
| 2357 | if (rdp.aTBuffTex[i]) |
| 2358 | { |
| 2359 | if (rdp.aTBuffTex[i]->t_mem == tile->t_mem) |
| 2360 | { |
| 2361 | if (rdp.aTBuffTex[i]->size == tile->size) |
| 2362 | { |
| 2363 | rdp.aTBuffTex[i]->tile = rdp.last_tile; |
| 2364 | rdp.aTBuffTex[i]->info.format = tile->format == 0 ? GR_TEXFMT_RGB_565 : GR_TEXFMT_ALPHA_INTENSITY_88; |
| 2365 | FRDP("rdp.aTBuffTex[%d] tile=%d, format=%s\n", i, rdp.last_tile, tile->format == 0 ? "RGB565" : "Alpha88"); |
| 2366 | } |
| 2367 | else |
| 2368 | rdp.aTBuffTex[i] = 0; |
| 2369 | break; |
| 2370 | } |
| 2371 | else if (rdp.aTBuffTex[i]->tile == rdp.last_tile) //wrong! t_mem must be the same |
| 2372 | rdp.aTBuffTex[i] = 0; |
| 2373 | } |
| 2374 | } |
| 2375 | } |
| 2376 | } |
| 2377 | |
| 2378 | // |
| 2379 | // fillrect - fills a rectangle |
| 2380 | // |
| 2381 | |
| 2382 | static void rdp_fillrect() |
| 2383 | { |
| 2384 | wxUint32 ul_x = ((rdp.cmd1 & 0x00FFF000) >> 14); |
| 2385 | wxUint32 ul_y = (rdp.cmd1 & 0x00000FFF) >> 2; |
| 2386 | wxUint32 lr_x = ((rdp.cmd0 & 0x00FFF000) >> 14) + 1; |
| 2387 | wxUint32 lr_y = ((rdp.cmd0 & 0x00000FFF) >> 2) + 1; |
| 2388 | if ((ul_x > lr_x) || (ul_y > lr_y)) |
| 2389 | { |
| 2390 | LRDP("Fillrect. Wrong coordinates. Skipped\n"); |
| 2391 | return; |
| 2392 | } |
| 2393 | int pd_multiplayer = (settings.ucode == ucode_PerfectDark) && (rdp.cycle_mode == 3) && (rdp.fill_color == 0xFFFCFFFC); |
| 2394 | if ((rdp.cimg == rdp.zimg) || (fb_emulation_enabled && rdp.frame_buffers[rdp.ci_count-1].status == ci_zimg) || pd_multiplayer) |
| 2395 | { |
| 2396 | LRDP("Fillrect - cleared the depth buffer\n"); |
| 2397 | if (fullscreen) |
| 2398 | { |
| 2399 | if (!(settings.hacks&hack_Hyperbike) || rdp.ci_width > 64) //do not clear main depth buffer for aux depth buffers |
| 2400 | { |
| 2401 | update_scissor (); |
| 2402 | grDepthMask (FXTRUE); |
| 2403 | grColorMask (FXFALSE, FXFALSE); |
| 2404 | grBufferClear (0, 0, rdp.fill_color ? rdp.fill_color&0xFFFF : 0xFFFF); |
| 2405 | grColorMask (FXTRUE, FXTRUE); |
| 2406 | rdp.update |= UPDATE_ZBUF_ENABLED; |
| 2407 | } |
| 2408 | //if (settings.frame_buffer&fb_depth_clear) |
| 2409 | { |
| 2410 | ul_x = min(max(ul_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x); |
| 2411 | lr_x = min(max(lr_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x); |
| 2412 | ul_y = min(max(ul_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y); |
| 2413 | lr_y = min(max(lr_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y); |
| 2414 | wxUint32 zi_width_in_dwords = rdp.ci_width >> 1; |
| 2415 | ul_x >>= 1; |
| 2416 | lr_x >>= 1; |
| 2417 | wxUint32 * dst = (wxUint32*)(gfx.RDRAM+rdp.cimg); |
| 2418 | dst += ul_y * zi_width_in_dwords; |
| 2419 | for (wxUint32 y = ul_y; y < lr_y; y++) |
| 2420 | { |
| 2421 | for (wxUint32 x = ul_x; x < lr_x; x++) |
| 2422 | { |
| 2423 | dst[x] = rdp.fill_color; |
| 2424 | } |
| 2425 | dst += zi_width_in_dwords; |
| 2426 | } |
| 2427 | } |
| 2428 | } |
| 2429 | return; |
| 2430 | } |
| 2431 | |
| 2432 | if (rdp.skip_drawing) |
| 2433 | { |
| 2434 | LRDP("Fillrect skipped\n"); |
| 2435 | return; |
| 2436 | } |
| 2437 | |
| 2438 | if (rdp.cur_image && (rdp.cur_image->format != 0) && (rdp.cycle_mode == 3) && (rdp.cur_image->width == lr_x - ul_x) && (rdp.cur_image->height == lr_y - ul_y)) |
| 2439 | { |
| 2440 | wxUint32 color = rdp.fill_color; |
| 2441 | if (rdp.ci_size < 3) |
| 2442 | { |
| 2443 | color = ((color&1)?0xFF:0) | |
| 2444 | ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | |
| 2445 | ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | |
| 2446 | ((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8); |
| 2447 | } |
| 2448 | grDepthMask (FXFALSE); |
| 2449 | grBufferClear (color, 0, 0xFFFF); |
| 2450 | grDepthMask (FXTRUE); |
| 2451 | rdp.update |= UPDATE_ZBUF_ENABLED; |
| 2452 | LRDP("Fillrect - cleared the texture buffer\n"); |
| 2453 | return; |
| 2454 | } |
| 2455 | |
| 2456 | // Update scissor |
| 2457 | if (fullscreen) |
| 2458 | update_scissor (); |
| 2459 | |
| 2460 | if (settings.decrease_fillrect_edge && rdp.cycle_mode == 0) |
| 2461 | { |
| 2462 | lr_x--; lr_y--; |
| 2463 | } |
| 2464 | FRDP("fillrect (%d,%d) -> (%d,%d), cycle mode: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, rdp.cycle_mode, |
| 2465 | rdp.tri_n, rdp.tri_n+1); |
| 2466 | |
| 2467 | FRDP("scissor (%d,%d) -> (%d,%d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, |
| 2468 | rdp.scissor.lr_y); |
| 2469 | |
| 2470 | // KILL the floating point error with 0.01f |
| 2471 | wxInt32 s_ul_x = (wxUint32)min(max(ul_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x); |
| 2472 | wxInt32 s_lr_x = (wxUint32)min(max(lr_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x); |
| 2473 | wxInt32 s_ul_y = (wxUint32)min(max(ul_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y); |
| 2474 | wxInt32 s_lr_y = (wxUint32)min(max(lr_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y); |
| 2475 | |
| 2476 | if (s_lr_x < 0) s_lr_x = 0; |
| 2477 | if (s_lr_y < 0) s_lr_y = 0; |
| 2478 | if ((wxUint32)s_ul_x > settings.res_x) s_ul_x = settings.res_x; |
| 2479 | if ((wxUint32)s_ul_y > settings.res_y) s_ul_y = settings.res_y; |
| 2480 | |
| 2481 | FRDP (" - %d, %d, %d, %d\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y); |
| 2482 | |
| 2483 | if (fullscreen) |
| 2484 | { |
| 2485 | grFogMode (GR_FOG_DISABLE); |
| 2486 | |
| 2487 | const float Z = (rdp.cycle_mode == 3) ? 0.0f : set_sprite_combine_mode(); |
| 2488 | |
| 2489 | // Draw the rectangle |
| 2490 | VERTEX v[4] = { |
| 2491 | { (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}, |
| 2492 | { (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}, |
| 2493 | { (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}, |
| 2494 | { (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} }; |
| 2495 | |
| 2496 | if (rdp.cycle_mode == 3) |
| 2497 | { |
| 2498 | wxUint32 color = rdp.fill_color; |
| 2499 | |
| 2500 | if ((settings.hacks&hack_PMario) && rdp.frame_buffers[rdp.ci_count-1].status == ci_aux) |
| 2501 | { |
| 2502 | //background of auxiliary frame buffers must have zero alpha. |
| 2503 | //make it black, set 0 alpha to plack pixels on frame buffer read |
| 2504 | color = 0; |
| 2505 | } |
| 2506 | else if (rdp.ci_size < 3) |
| 2507 | { |
| 2508 | color = ((color&1)?0xFF:0) | |
| 2509 | ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | |
| 2510 | ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | |
| 2511 | ((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8); |
| 2512 | } |
| 2513 | |
| 2514 | grConstantColorValue (color); |
| 2515 | |
| 2516 | grColorCombine (GR_COMBINE_FUNCTION_LOCAL, |
| 2517 | GR_COMBINE_FACTOR_NONE, |
| 2518 | GR_COMBINE_LOCAL_CONSTANT, |
| 2519 | GR_COMBINE_OTHER_NONE, |
| 2520 | FXFALSE); |
| 2521 | |
| 2522 | grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, |
| 2523 | GR_COMBINE_FACTOR_NONE, |
| 2524 | GR_COMBINE_LOCAL_CONSTANT, |
| 2525 | GR_COMBINE_OTHER_NONE, |
| 2526 | FXFALSE); |
| 2527 | |
| 2528 | grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO); |
| 2529 | |
| 2530 | grAlphaTestFunction (GR_CMP_ALWAYS); |
| 2531 | if (grStippleModeExt) |
| 2532 | grStippleModeExt(GR_STIPPLE_DISABLE); |
| 2533 | |
| 2534 | grCullMode(GR_CULL_DISABLE); |
| 2535 | grFogMode (GR_FOG_DISABLE); |
| 2536 | grDepthBufferFunction (GR_CMP_ALWAYS); |
| 2537 | grDepthMask (FXFALSE); |
| 2538 | |
| 2539 | rdp.update |= UPDATE_COMBINE | UPDATE_CULL_MODE | UPDATE_FOG_ENABLED | UPDATE_ZBUF_ENABLED; |
| 2540 | } |
| 2541 | else |
| 2542 | { |
| 2543 | wxUint32 cmb_mode_c = (rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF); |
| 2544 | wxUint32 cmb_mode_a = (rdp.cycle1 & 0x0FFF0000) | ((rdp.cycle2 >> 16) & 0x00000FFF); |
| 2545 | if (cmb_mode_c == 0x9fff9fff || cmb_mode_a == 0x09ff09ff) //shade |
| 2546 | { |
| 2547 | AllowShadeMods (v, 4); |
| 2548 | for (int k = 0; k < 4; k++) |
| 2549 | apply_shade_mods (&v[k]); |
| 2550 | } |
| 2551 | if ((rdp.othermode_l & 0x4000) && ((rdp.othermode_l >> 16) == 0x0550)) //special blender mode for Bomberman64 |
| 2552 | { |
| 2553 | grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, |
| 2554 | GR_COMBINE_FACTOR_NONE, |
| 2555 | GR_COMBINE_LOCAL_CONSTANT, |
| 2556 | GR_COMBINE_OTHER_NONE, |
| 2557 | FXFALSE); |
| 2558 | grConstantColorValue((cmb.ccolor&0xFFFFFF00)|(rdp.fog_color&0xFF)); |
| 2559 | rdp.update |= UPDATE_COMBINE; |
| 2560 | } |
| 2561 | } |
| 2562 | |
| 2563 | if (settings.wireframe) |
| 2564 | { |
| 2565 | SetWireframeCol (); |
| 2566 | grDrawLine (&v[0], &v[2]); |
| 2567 | grDrawLine (&v[2], &v[1]); |
| 2568 | grDrawLine (&v[1], &v[0]); |
| 2569 | grDrawLine (&v[2], &v[3]); |
| 2570 | grDrawLine (&v[3], &v[1]); |
| 2571 | //grDrawLine (&v[1], &v[2]); |
| 2572 | } |
| 2573 | else |
| 2574 | { |
| 2575 | grDrawTriangle (&v[0], &v[2], &v[1]); |
| 2576 | grDrawTriangle (&v[2], &v[3], &v[1]); |
| 2577 | } |
| 2578 | |
| 2579 | if (_debugger.capture) |
| 2580 | { |
| 2581 | VERTEX v1[3]; |
| 2582 | v1[0] = v[0]; |
| 2583 | v1[1] = v[2]; |
| 2584 | v1[2] = v[1]; |
| 2585 | add_tri (v1, 3, TRI_FILLRECT); |
| 2586 | rdp.tri_n ++; |
| 2587 | v1[0] = v[2]; |
| 2588 | v1[1] = v[3]; |
| 2589 | add_tri (v1, 3, TRI_FILLRECT); |
| 2590 | rdp.tri_n ++; |
| 2591 | } |
| 2592 | else |
| 2593 | rdp.tri_n += 2; |
| 2594 | } |
| 2595 | else |
| 2596 | { |
| 2597 | rdp.tri_n += 2; |
| 2598 | } |
| 2599 | } |
| 2600 | |
| 2601 | // |
| 2602 | // setfillcolor - sets the filling color |
| 2603 | // |
| 2604 | |
| 2605 | static void rdp_setfillcolor() |
| 2606 | { |
| 2607 | rdp.fill_color = rdp.cmd1; |
| 2608 | rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE; |
| 2609 | |
| 2610 | FRDP("setfillcolor: %08lx\n", rdp.cmd1); |
| 2611 | } |
| 2612 | |
| 2613 | static void rdp_setfogcolor() |
| 2614 | { |
| 2615 | rdp.fog_color = rdp.cmd1; |
| 2616 | rdp.update |= UPDATE_COMBINE | UPDATE_FOG_ENABLED; |
| 2617 | |
| 2618 | FRDP("setfogcolor - %08lx\n", rdp.cmd1); |
| 2619 | } |
| 2620 | |
| 2621 | static void rdp_setblendcolor() |
| 2622 | { |
| 2623 | rdp.blend_color = rdp.cmd1; |
| 2624 | rdp.update |= UPDATE_COMBINE; |
| 2625 | |
| 2626 | FRDP("setblendcolor: %08lx\n", rdp.cmd1); |
| 2627 | } |
| 2628 | |
| 2629 | static void rdp_setprimcolor() |
| 2630 | { |
| 2631 | rdp.prim_color = rdp.cmd1; |
| 2632 | rdp.prim_lodmin = (rdp.cmd0 >> 8) & 0xFF; |
| 2633 | rdp.prim_lodfrac = max(rdp.cmd0 & 0xFF, rdp.prim_lodmin); |
| 2634 | rdp.update |= UPDATE_COMBINE; |
| 2635 | |
| 2636 | FRDP("setprimcolor: %08lx, lodmin: %d, lodfrac: %d\n", rdp.cmd1, rdp.prim_lodmin, |
| 2637 | rdp.prim_lodfrac); |
| 2638 | } |
| 2639 | |
| 2640 | static void rdp_setenvcolor() |
| 2641 | { |
| 2642 | rdp.env_color = rdp.cmd1; |
| 2643 | rdp.update |= UPDATE_COMBINE; |
| 2644 | |
| 2645 | FRDP("setenvcolor: %08lx\n", rdp.cmd1); |
| 2646 | } |
| 2647 | |
| 2648 | static void rdp_setcombine() |
| 2649 | { |
| 2650 | rdp.c_a0 = (wxUint8)((rdp.cmd0 >> 20) & 0xF); |
| 2651 | rdp.c_b0 = (wxUint8)((rdp.cmd1 >> 28) & 0xF); |
| 2652 | rdp.c_c0 = (wxUint8)((rdp.cmd0 >> 15) & 0x1F); |
| 2653 | rdp.c_d0 = (wxUint8)((rdp.cmd1 >> 15) & 0x7); |
| 2654 | rdp.c_Aa0 = (wxUint8)((rdp.cmd0 >> 12) & 0x7); |
| 2655 | rdp.c_Ab0 = (wxUint8)((rdp.cmd1 >> 12) & 0x7); |
| 2656 | rdp.c_Ac0 = (wxUint8)((rdp.cmd0 >> 9) & 0x7); |
| 2657 | rdp.c_Ad0 = (wxUint8)((rdp.cmd1 >> 9) & 0x7); |
| 2658 | |
| 2659 | rdp.c_a1 = (wxUint8)((rdp.cmd0 >> 5) & 0xF); |
| 2660 | rdp.c_b1 = (wxUint8)((rdp.cmd1 >> 24) & 0xF); |
| 2661 | rdp.c_c1 = (wxUint8)((rdp.cmd0 >> 0) & 0x1F); |
| 2662 | rdp.c_d1 = (wxUint8)((rdp.cmd1 >> 6) & 0x7); |
| 2663 | rdp.c_Aa1 = (wxUint8)((rdp.cmd1 >> 21) & 0x7); |
| 2664 | rdp.c_Ab1 = (wxUint8)((rdp.cmd1 >> 3) & 0x7); |
| 2665 | rdp.c_Ac1 = (wxUint8)((rdp.cmd1 >> 18) & 0x7); |
| 2666 | rdp.c_Ad1 = (wxUint8)((rdp.cmd1 >> 0) & 0x7); |
| 2667 | |
| 2668 | rdp.cycle1 = (rdp.c_a0<<0) | (rdp.c_b0<<4) | (rdp.c_c0<<8) | (rdp.c_d0<<13)| |
| 2669 | (rdp.c_Aa0<<16)| (rdp.c_Ab0<<19)| (rdp.c_Ac0<<22)| (rdp.c_Ad0<<25); |
| 2670 | rdp.cycle2 = (rdp.c_a1<<0) | (rdp.c_b1<<4) | (rdp.c_c1<<8) | (rdp.c_d1<<13)| |
| 2671 | (rdp.c_Aa1<<16)| (rdp.c_Ab1<<19)| (rdp.c_Ac1<<22)| (rdp.c_Ad1<<25); |
| 2672 | |
| 2673 | rdp.update |= UPDATE_COMBINE; |
| 2674 | |
| 2675 | 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", |
| 2676 | Mode0[rdp.c_a0], Mode1[rdp.c_b0], Mode2[rdp.c_c0], Mode3[rdp.c_d0], |
| 2677 | Alpha0[rdp.c_Aa0], Alpha1[rdp.c_Ab0], Alpha2[rdp.c_Ac0], Alpha3[rdp.c_Ad0], |
| 2678 | Mode0[rdp.c_a1], Mode1[rdp.c_b1], Mode2[rdp.c_c1], Mode3[rdp.c_d1], |
| 2679 | Alpha0[rdp.c_Aa1], Alpha1[rdp.c_Ab1], Alpha2[rdp.c_Ac1], Alpha3[rdp.c_Ad1]); |
| 2680 | } |
| 2681 | |
| 2682 | // |
| 2683 | // settextureimage - sets the source for an image copy |
| 2684 | // |
| 2685 | |
| 2686 | static void rdp_settextureimage() |
| 2687 | { |
| 2688 | static const char *format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" }; |
| 2689 | static const char *size[] = { "4bit", "8bit", "16bit", "32bit" }; |
| 2690 | |
| 2691 | rdp.timg.format = (wxUint8)((rdp.cmd0 >> 21) & 0x07); |
| 2692 | rdp.timg.size = (wxUint8)((rdp.cmd0 >> 19) & 0x03); |
| 2693 | rdp.timg.width = (wxUint16)(1 + (rdp.cmd0 & 0x00000FFF)); |
| 2694 | rdp.timg.addr = segoffset(rdp.cmd1); |
| 2695 | if (ucode5_texshiftaddr) |
| 2696 | { |
| 2697 | if (rdp.timg.format == 0) |
| 2698 | { |
| 2699 | wxUint16 * t = (wxUint16*)(gfx.RDRAM+ucode5_texshiftaddr); |
| 2700 | ucode5_texshift = t[ucode5_texshiftcount^1]; |
| 2701 | rdp.timg.addr += ucode5_texshift; |
| 2702 | } |
| 2703 | else |
| 2704 | { |
| 2705 | ucode5_texshiftaddr = 0; |
| 2706 | ucode5_texshift = 0; |
| 2707 | ucode5_texshiftcount = 0; |
| 2708 | } |
| 2709 | } |
| 2710 | rdp.s2dex_tex_loaded = TRUE; |
| 2711 | rdp.update |= UPDATE_TEXTURE; |
| 2712 | |
| 2713 | if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self && (rdp.timg.addr >= rdp.cimg) && (rdp.timg.addr < rdp.ci_end)) |
| 2714 | { |
| 2715 | if (!rdp.fb_drawn) |
| 2716 | { |
| 2717 | if (!rdp.cur_image) |
| 2718 | CopyFrameBuffer(); |
| 2719 | else |
| 2720 | CloseTextureBuffer(TRUE); |
| 2721 | rdp.fb_drawn = TRUE; |
| 2722 | } |
| 2723 | } |
| 2724 | |
| 2725 | if (fb_hwfbe_enabled) //search this texture among drawn texture buffers |
| 2726 | FindTextureBuffer(rdp.timg.addr, rdp.timg.width); |
| 2727 | |
| 2728 | FRDP("settextureimage: format: %s, size: %s, width: %d, addr: %08lx\n", |
| 2729 | format[rdp.timg.format], size[rdp.timg.size], |
| 2730 | rdp.timg.width, rdp.timg.addr); |
| 2731 | } |
| 2732 | |
| 2733 | static void rdp_setdepthimage() |
| 2734 | { |
| 2735 | rdp.zimg = segoffset(rdp.cmd1) & BMASK; |
| 2736 | rdp.zi_width = rdp.ci_width; |
| 2737 | FRDP("setdepthimage - %08lx\n", rdp.zimg); |
| 2738 | } |
| 2739 | |
| 2740 | int SwapOK = TRUE; |
| 2741 | static void RestoreScale() |
| 2742 | { |
| 2743 | FRDP("Return to original scale: x = %f, y = %f\n", rdp.scale_x_bak, rdp.scale_y_bak); |
| 2744 | rdp.scale_x = rdp.scale_x_bak; |
| 2745 | rdp.scale_y = rdp.scale_y_bak; |
| 2746 | // update_scissor(); |
| 2747 | rdp.view_scale[0] *= rdp.scale_x; |
| 2748 | rdp.view_scale[1] *= rdp.scale_y; |
| 2749 | rdp.view_trans[0] *= rdp.scale_x; |
| 2750 | rdp.view_trans[1] *= rdp.scale_y; |
| 2751 | rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR; |
| 2752 | //* |
| 2753 | if (fullscreen) |
| 2754 | { |
| 2755 | grDepthMask (FXFALSE); |
| 2756 | grBufferClear (0, 0, 0xFFFF); |
| 2757 | grDepthMask (FXTRUE); |
| 2758 | } |
| 2759 | //*/ |
| 2760 | } |
| 2761 | |
| 2762 | static wxUint32 swapped_addr = 0; |
| 2763 | |
| 2764 | static void rdp_setcolorimage() |
| 2765 | { |
| 2766 | //unsigned int ticks = ticksGetTicks(); |
| 2767 | //bool showdeb = false; |
| 2768 | if (fb_emulation_enabled && (rdp.num_of_ci < NUMTEXBUF)) |
| 2769 | { |
| 2770 | COLOR_IMAGE & cur_fb = rdp.frame_buffers[rdp.ci_count]; |
| 2771 | COLOR_IMAGE & prev_fb = rdp.frame_buffers[rdp.ci_count?rdp.ci_count-1:0]; |
| 2772 | COLOR_IMAGE & next_fb = rdp.frame_buffers[rdp.ci_count+1]; |
| 2773 | //if (cur_fb.status==ci_aux) showdeb = true; |
| 2774 | //if (showdeb) printf("rp_setcolorimage, status=%i\n", cur_fb.status); |
| 2775 | switch (cur_fb.status) |
| 2776 | { |
| 2777 | case ci_main: |
| 2778 | { |
| 2779 | |
| 2780 | if (rdp.ci_count == 0) |
| 2781 | { |
| 2782 | if ((rdp.ci_status == ci_aux)) //for PPL |
| 2783 | { |
| 2784 | float sx = rdp.scale_x; |
| 2785 | float sy = rdp.scale_y; |
| 2786 | rdp.scale_x = 1.0f; |
| 2787 | rdp.scale_y = 1.0f; |
| 2788 | CopyFrameBuffer (); |
| 2789 | rdp.scale_x = sx; |
| 2790 | rdp.scale_y = sy; |
| 2791 | } |
| 2792 | if (!fb_hwfbe_enabled) |
| 2793 | { |
| 2794 | if ((rdp.num_of_ci > 1) && |
| 2795 | (next_fb.status == ci_aux) && |
| 2796 | (next_fb.width >= cur_fb.width)) |
| 2797 | { |
| 2798 | rdp.scale_x = 1.0f; |
| 2799 | rdp.scale_y = 1.0f; |
| 2800 | } |
| 2801 | } |
| 2802 | else if (rdp.copy_ci_index && (settings.hacks&hack_PMario)) //tidal wave |
| 2803 | OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); |
| 2804 | } |
| 2805 | else if (!rdp.motionblur && fb_hwfbe_enabled && !SwapOK && (rdp.ci_count <= rdp.copy_ci_index)) |
| 2806 | { |
| 2807 | if (next_fb.status == ci_aux_copy) |
| 2808 | OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); |
| 2809 | else |
| 2810 | OpenTextureBuffer(rdp.frame_buffers[rdp.copy_ci_index]); |
| 2811 | } |
| 2812 | else if (fb_hwfbe_enabled && prev_fb.status == ci_aux) |
| 2813 | { |
| 2814 | if (rdp.motionblur) |
| 2815 | { |
| 2816 | rdp.cur_image = &(rdp.texbufs[rdp.cur_tex_buf].images[0]); |
| 2817 | grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT ); |
| 2818 | grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2, |
| 2819 | rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH ); |
| 2820 | } |
| 2821 | else if (rdp.read_whole_frame) |
| 2822 | { |
| 2823 | OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); |
| 2824 | } |
| 2825 | } |
| 2826 | //else if (rdp.ci_status == ci_aux && !rdp.copy_ci_index) |
| 2827 | // CloseTextureBuffer(); |
| 2828 | |
| 2829 | rdp.skip_drawing = FALSE; |
| 2830 | } |
| 2831 | break; |
| 2832 | case ci_copy: |
| 2833 | { |
| 2834 | if (!rdp.motionblur || (settings.frame_buffer&fb_motionblur)) |
| 2835 | { |
| 2836 | if (cur_fb.width == rdp.ci_width) |
| 2837 | { |
| 2838 | if (CopyTextureBuffer(prev_fb, cur_fb)) |
| 2839 | { |
| 2840 | // if (CloseTextureBuffer(TRUE)) |
| 2841 | //* |
| 2842 | if ((settings.hacks&hack_Zelda) && (rdp.frame_buffers[rdp.ci_count+2].status == ci_aux) && !rdp.fb_drawn) //hack for photo camera in Zelda MM |
| 2843 | { |
| 2844 | CopyFrameBuffer (GR_BUFFER_TEXTUREBUFFER_EXT); |
| 2845 | rdp.fb_drawn = TRUE; |
| 2846 | memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1); |
| 2847 | } |
| 2848 | //*/ |
| 2849 | } |
| 2850 | else |
| 2851 | { |
| 2852 | if (!rdp.fb_drawn || prev_fb.status == ci_copy_self) |
| 2853 | { |
| 2854 | CopyFrameBuffer (); |
| 2855 | rdp.fb_drawn = TRUE; |
| 2856 | } |
| 2857 | memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1); |
| 2858 | } |
| 2859 | } |
| 2860 | else |
| 2861 | { |
| 2862 | CloseTextureBuffer(TRUE); |
| 2863 | } |
| 2864 | } |
| 2865 | else |
| 2866 | { |
| 2867 | memset(gfx.RDRAM+cur_fb.addr, 0, cur_fb.width*cur_fb.height*rdp.ci_size); |
| 2868 | } |
| 2869 | rdp.skip_drawing = TRUE; |
| 2870 | } |
| 2871 | break; |
| 2872 | case ci_aux_copy: |
| 2873 | { |
| 2874 | rdp.skip_drawing = FALSE; |
| 2875 | if (CloseTextureBuffer(prev_fb.status != ci_aux_copy)) |
| 2876 | ; |
| 2877 | else if (!rdp.fb_drawn) |
| 2878 | { |
| 2879 | CopyFrameBuffer (); |
| 2880 | rdp.fb_drawn = TRUE; |
| 2881 | } |
| 2882 | if (fb_hwfbe_enabled) |
| 2883 | OpenTextureBuffer(cur_fb); |
| 2884 | } |
| 2885 | break; |
| 2886 | case ci_old_copy: |
| 2887 | { |
| 2888 | if (!rdp.motionblur || (settings.frame_buffer&fb_motionblur)) |
| 2889 | { |
| 2890 | if (cur_fb.width == rdp.ci_width) |
| 2891 | { |
| 2892 | memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.maincimg[1].addr, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1); |
| 2893 | } |
| 2894 | //rdp.skip_drawing = TRUE; |
| 2895 | } |
| 2896 | else |
| 2897 | { |
| 2898 | memset(gfx.RDRAM+cur_fb.addr, 0, (cur_fb.width*cur_fb.height)<<rdp.ci_size>>1); |
| 2899 | } |
| 2900 | } |
| 2901 | break; |
| 2902 | /* |
| 2903 | else if (rdp.frame_buffers[rdp.ci_count].status == ci_main_i) |
| 2904 | { |
| 2905 | // CopyFrameBuffer (); |
| 2906 | rdp.scale_x = rdp.scale_x_bak; |
| 2907 | rdp.scale_y = rdp.scale_y_bak; |
| 2908 | rdp.skip_drawing = FALSE; |
| 2909 | } |
| 2910 | */ |
| 2911 | case ci_aux: |
| 2912 | { |
| 2913 | //unsigned int tticks = ticksGetTicks(); |
| 2914 | if (!fb_hwfbe_enabled && cur_fb.format != 0) |
| 2915 | rdp.skip_drawing = TRUE; |
| 2916 | else |
| 2917 | { |
| 2918 | rdp.skip_drawing = FALSE; |
| 2919 | if (fb_hwfbe_enabled && OpenTextureBuffer(cur_fb)) |
| 2920 | ; |
| 2921 | else |
| 2922 | { |
| 2923 | if (cur_fb.format != 0) |
| 2924 | rdp.skip_drawing = TRUE; |
| 2925 | if (rdp.ci_count == 0) |
| 2926 | { |
| 2927 | // if (rdp.num_of_ci > 1) |
| 2928 | // { |
| 2929 | rdp.scale_x = 1.0f; |
| 2930 | rdp.scale_y = 1.0f; |
| 2931 | // } |
| 2932 | } |
| 2933 | else if (!fb_hwfbe_enabled && (prev_fb.status == ci_main) && |
| 2934 | (prev_fb.width == cur_fb.width)) // for Pokemon Stadium |
| 2935 | CopyFrameBuffer (); |
| 2936 | } |
| 2937 | } |
| 2938 | cur_fb.status = ci_aux; |
| 2939 | //tticks = ticksGetTicks() - ticks; |
| 2940 | //printf("intermediary: %u ms\n", tticks); |
| 2941 | } |
| 2942 | break; |
| 2943 | case ci_zimg: |
| 2944 | if (settings.ucode != ucode_PerfectDark) |
| 2945 | { |
| 2946 | if (fb_hwfbe_enabled && !rdp.copy_ci_index && (rdp.copy_zi_index || (settings.hacks&hack_BAR))) |
| 2947 | { |
| 2948 | GrLOD_t LOD = GR_LOD_LOG2_1024; |
| 2949 | if (settings.scr_res_x > 1024) |
| 2950 | LOD = GR_LOD_LOG2_2048; |
| 2951 | grTextureAuxBufferExt( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, LOD, LOD, |
| 2952 | GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH ); |
| 2953 | grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT ); |
| 2954 | LRDP("rdp_setcolorimage - set texture depth buffer to TMU0\n"); |
| 2955 | } |
| 2956 | } |
| 2957 | rdp.skip_drawing = TRUE; |
| 2958 | break; |
| 2959 | case ci_zcopy: |
| 2960 | if (settings.ucode != ucode_PerfectDark) |
| 2961 | { |
| 2962 | if (fb_hwfbe_enabled && !rdp.copy_ci_index && rdp.copy_zi_index == rdp.ci_count) |
| 2963 | { |
| 2964 | CopyDepthBuffer(); |
| 2965 | } |
| 2966 | rdp.skip_drawing = TRUE; |
| 2967 | } |
| 2968 | break; |
| 2969 | case ci_useless: |
| 2970 | rdp.skip_drawing = TRUE; |
| 2971 | break; |
| 2972 | case ci_copy_self: |
| 2973 | if (fb_hwfbe_enabled && (rdp.ci_count <= rdp.copy_ci_index) && (!SwapOK || settings.swapmode == 2)) |
| 2974 | OpenTextureBuffer(cur_fb); |
| 2975 | rdp.skip_drawing = FALSE; |
| 2976 | break; |
| 2977 | default: |
| 2978 | rdp.skip_drawing = FALSE; |
| 2979 | } |
| 2980 | |
| 2981 | if ((rdp.ci_count > 0) && (prev_fb.status >= ci_aux)) //for Pokemon Stadium |
| 2982 | { |
| 2983 | if (!fb_hwfbe_enabled && prev_fb.format == 0) |
| 2984 | CopyFrameBuffer (); |
| 2985 | else if ((settings.hacks&hack_Knockout) && prev_fb.width < 100) |
| 2986 | CopyFrameBuffer (GR_BUFFER_TEXTUREBUFFER_EXT); |
| 2987 | } |
| 2988 | if (!fb_hwfbe_enabled && cur_fb.status == ci_copy) |
| 2989 | { |
| 2990 | if (!rdp.motionblur && (rdp.num_of_ci > rdp.ci_count+1) && (next_fb.status != ci_aux)) |
| 2991 | { |
| 2992 | RestoreScale(); |
| 2993 | } |
| 2994 | } |
| 2995 | if (!fb_hwfbe_enabled && cur_fb.status == ci_aux) |
| 2996 | { |
| 2997 | if (cur_fb.format == 0) |
| 2998 | { |
| 2999 | if ((settings.hacks&hack_PPL) && (rdp.scale_x < 1.1f)) //need to put current image back to frame buffer |
| 3000 | { |
| 3001 | int width = cur_fb.width; |
| 3002 | int height = cur_fb.height; |
| 3003 | wxUint16 *ptr_dst = new wxUint16[width*height]; |
| 3004 | wxUint16 *ptr_src = (wxUint16*)(gfx.RDRAM+cur_fb.addr); |
| 3005 | wxUint16 c; |
| 3006 | |
| 3007 | for (int y=0; y<height; y++) |
| 3008 | { |
| 3009 | for (int x=0; x<width; x++) |
| 3010 | { |
| 3011 | c = ((ptr_src[(x + y * width)^1]) >> 1) | 0x8000; |
| 3012 | ptr_dst[x + y * width] = c; |
| 3013 | } |
| 3014 | } |
| 3015 | grLfbWriteRegion(GR_BUFFER_BACKBUFFER, |
| 3016 | (wxUint32)rdp.offset_x, |
| 3017 | (wxUint32)rdp.offset_y, |
| 3018 | GR_LFB_SRC_FMT_555, |
| 3019 | width, |
| 3020 | height, |
| 3021 | FXFALSE, |
| 3022 | width<<1, |
| 3023 | ptr_dst); |
| 3024 | delete[] ptr_dst; |
| 3025 | } |
| 3026 | /* |
| 3027 | else //just clear buffer |
| 3028 | { |
| 3029 | |
| 3030 | grColorMask(FXTRUE, FXTRUE); |
| 3031 | grBufferClear (0, 0, 0xFFFF); |
| 3032 | } |
| 3033 | */ |
| 3034 | } |
| 3035 | } |
| 3036 | |
| 3037 | if ((cur_fb.status == ci_main) && (rdp.ci_count > 0)) |
| 3038 | { |
| 3039 | int to_org_res = TRUE; |
| 3040 | for (int i = rdp.ci_count + 1; i < rdp.num_of_ci; i++) |
| 3041 | { |
| 3042 | if ((rdp.frame_buffers[i].status != ci_main) && (rdp.frame_buffers[i].status != ci_zimg) && (rdp.frame_buffers[i].status != ci_zcopy)) |
| 3043 | { |
| 3044 | to_org_res = FALSE; |
| 3045 | break; |
| 3046 | } |
| 3047 | } |
| 3048 | if (to_org_res) |
| 3049 | { |
| 3050 | LRDP("return to original scale\n"); |
| 3051 | rdp.scale_x = rdp.scale_x_bak; |
| 3052 | rdp.scale_y = rdp.scale_y_bak; |
| 3053 | if (fb_hwfbe_enabled && !rdp.read_whole_frame) |
| 3054 | CloseTextureBuffer(); |
| 3055 | } |
| 3056 | if (fb_hwfbe_enabled && !rdp.read_whole_frame && (prev_fb.status >= ci_aux) && (rdp.ci_count > rdp.copy_ci_index)) |
| 3057 | CloseTextureBuffer(); |
| 3058 | |
| 3059 | } |
| 3060 | rdp.ci_status = cur_fb.status; |
| 3061 | rdp.ci_count++; |
| 3062 | } |
| 3063 | |
| 3064 | rdp.ocimg = rdp.cimg; |
| 3065 | rdp.cimg = segoffset(rdp.cmd1) & BMASK; |
| 3066 | rdp.ci_width = (rdp.cmd0 & 0xFFF) + 1; |
| 3067 | if (fb_emulation_enabled) |
| 3068 | rdp.ci_height = rdp.frame_buffers[rdp.ci_count-1].height; |
| 3069 | else if (rdp.ci_width == 32) |
| 3070 | rdp.ci_height = 32; |
| 3071 | else |
| 3072 | rdp.ci_height = rdp.scissor_o.lr_y; |
| 3073 | if (rdp.zimg == rdp.cimg) |
| 3074 | { |
| 3075 | rdp.zi_width = rdp.ci_width; |
| 3076 | // int zi_height = min((int)rdp.zi_width*3/4, (int)rdp.vi_height); |
| 3077 | // rdp.zi_words = rdp.zi_width * zi_height; |
| 3078 | } |
| 3079 | wxUint32 format = (rdp.cmd0 >> 21) & 0x7; |
| 3080 | rdp.ci_size = (rdp.cmd0 >> 19) & 0x3; |
| 3081 | rdp.ci_end = rdp.cimg + ((rdp.ci_width*rdp.ci_height)<<(rdp.ci_size-1)); |
| 3082 | FRDP("setcolorimage - %08lx, width: %d, height: %d, format: %d, size: %d\n", rdp.cmd1, rdp.ci_width, rdp.ci_height, format, rdp.ci_size); |
| 3083 | FRDP("cimg: %08lx, ocimg: %08lx, SwapOK: %d\n", rdp.cimg, rdp.ocimg, SwapOK); |
| 3084 | |
| 3085 | //if (showdeb) printf("setcolorimage - %08x, width: %d, height: %d, format: %d, size: %d\n", rdp.cmd1, rdp.ci_width, rdp.ci_height, format, rdp.ci_size); |
| 3086 | //if (showdeb) printf("cimg: %08x, ocimg: %08x, SwapOK: %d\n", rdp.cimg, rdp.ocimg, SwapOK); |
| 3087 | |
| 3088 | if (format != 0) //can't draw into non RGBA buffer |
| 3089 | { |
| 3090 | if (!rdp.cur_image) |
| 3091 | { |
| 3092 | if (fb_hwfbe_enabled && rdp.ci_width <= 64) |
| 3093 | OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count - 1]); |
| 3094 | else if (format > 2) |
| 3095 | rdp.skip_drawing = TRUE; |
| 3096 | return; |
| 3097 | } |
| 3098 | } |
| 3099 | else |
| 3100 | { |
| 3101 | if (!fb_emulation_enabled) |
| 3102 | rdp.skip_drawing = FALSE; |
| 3103 | } |
| 3104 | |
| 3105 | CI_SET = TRUE; |
| 3106 | if (settings.swapmode > 0) |
| 3107 | { |
| 3108 | if (rdp.zimg == rdp.cimg) |
| 3109 | rdp.updatescreen = 1; |
| 3110 | |
| 3111 | int viSwapOK = ((settings.swapmode == 2) && (rdp.vi_org_reg == *gfx.VI_ORIGIN_REG)) ? FALSE : TRUE; |
| 3112 | if ((rdp.zimg != rdp.cimg) && (rdp.ocimg != rdp.cimg) && SwapOK && viSwapOK && !rdp.cur_image) |
| 3113 | { |
| 3114 | if (fb_emulation_enabled) |
| 3115 | rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index]; |
| 3116 | else |
| 3117 | rdp.maincimg[0].addr = rdp.cimg; |
| 3118 | rdp.last_drawn_ci_addr = (settings.swapmode == 2) ? swapped_addr : rdp.maincimg[0].addr; |
| 3119 | swapped_addr = rdp.cimg; |
| 3120 | newSwapBuffers(); |
| 3121 | rdp.vi_org_reg = *gfx.VI_ORIGIN_REG; |
| 3122 | SwapOK = FALSE; |
| 3123 | if (fb_hwfbe_enabled) |
| 3124 | { |
| 3125 | if (rdp.copy_ci_index && (rdp.frame_buffers[rdp.ci_count-1].status != ci_zimg)) |
| 3126 | { |
| 3127 | int idx = (rdp.frame_buffers[rdp.ci_count].status == ci_aux_copy) ? rdp.main_ci_index : rdp.copy_ci_index; |
| 3128 | FRDP("attempt open tex buffer. status: %s, addr: %08lx\n", CIStatus[rdp.frame_buffers[idx].status], rdp.frame_buffers[idx].addr); |
| 3129 | OpenTextureBuffer(rdp.frame_buffers[idx]); |
| 3130 | if (rdp.frame_buffers[rdp.copy_ci_index].status == ci_main) //tidal wave |
| 3131 | rdp.copy_ci_index = 0; |
| 3132 | } |
| 3133 | else if (rdp.read_whole_frame && !rdp.cur_image) |
| 3134 | { |
| 3135 | OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); |
| 3136 | } |
| 3137 | } |
| 3138 | } |
| 3139 | } |
| 3140 | //ticks = ticksGetTicks() - ticks; |
| 3141 | //if (showdeb) printf("time = %u\n", ticks); |
| 3142 | } |
| 3143 | |
| 3144 | static void rsp_reserved0() |
| 3145 | { |
| 3146 | if (settings.ucode == ucode_DiddyKong) |
| 3147 | { |
| 3148 | ucode5_texshiftaddr = segoffset(rdp.cmd1); |
| 3149 | ucode5_texshiftcount = 0; |
| 3150 | FRDP("uc5_texshift. addr: %08lx\n", ucode5_texshiftaddr); |
| 3151 | } |
| 3152 | else |
| 3153 | { |
| 3154 | RDP_E("reserved0 - IGNORED\n"); |
| 3155 | LRDP("reserved0 - IGNORED\n"); |
| 3156 | } |
| 3157 | } |
| 3158 | |
| 3159 | static void rsp_reserved1() |
| 3160 | { |
| 3161 | LRDP("reserved1 - ignored\n"); |
| 3162 | } |
| 3163 | |
| 3164 | static void rsp_reserved2() |
| 3165 | { |
| 3166 | LRDP("reserved2\n"); |
| 3167 | } |
| 3168 | |
| 3169 | static void rsp_reserved3() |
| 3170 | { |
| 3171 | LRDP("reserved3 - ignored\n"); |
| 3172 | } |
| 3173 | |
| 3174 | void SetWireframeCol () |
| 3175 | { |
| 3176 | if (!fullscreen) return; |
| 3177 | |
| 3178 | switch (settings.wfmode) |
| 3179 | { |
| 3180 | //case 0: // normal colors, don't do anything |
| 3181 | case 1: // vertex colors |
| 3182 | grColorCombine (GR_COMBINE_FUNCTION_LOCAL, |
| 3183 | GR_COMBINE_FACTOR_NONE, |
| 3184 | GR_COMBINE_LOCAL_ITERATED, |
| 3185 | GR_COMBINE_OTHER_NONE, |
| 3186 | FXFALSE); |
| 3187 | grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, |
| 3188 | GR_COMBINE_FACTOR_NONE, |
| 3189 | GR_COMBINE_LOCAL_ITERATED, |
| 3190 | GR_COMBINE_OTHER_NONE, |
| 3191 | FXFALSE); |
| 3192 | grAlphaBlendFunction (GR_BLEND_ONE, |
| 3193 | GR_BLEND_ZERO, |
| 3194 | GR_BLEND_ZERO, |
| 3195 | GR_BLEND_ZERO); |
| 3196 | grTexCombine (GR_TMU0, |
| 3197 | GR_COMBINE_FUNCTION_ZERO, |
| 3198 | GR_COMBINE_FACTOR_NONE, |
| 3199 | GR_COMBINE_FUNCTION_ZERO, |
| 3200 | GR_COMBINE_FACTOR_NONE, |
| 3201 | FXFALSE, FXFALSE); |
| 3202 | grTexCombine (GR_TMU1, |
| 3203 | GR_COMBINE_FUNCTION_ZERO, |
| 3204 | GR_COMBINE_FACTOR_NONE, |
| 3205 | GR_COMBINE_FUNCTION_ZERO, |
| 3206 | GR_COMBINE_FACTOR_NONE, |
| 3207 | FXFALSE, FXFALSE); |
| 3208 | break; |
| 3209 | case 2: // red only |
| 3210 | grColorCombine (GR_COMBINE_FUNCTION_LOCAL, |
| 3211 | GR_COMBINE_FACTOR_NONE, |
| 3212 | GR_COMBINE_LOCAL_CONSTANT, |
| 3213 | GR_COMBINE_OTHER_NONE, |
| 3214 | FXFALSE); |
| 3215 | grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, |
| 3216 | GR_COMBINE_FACTOR_NONE, |
| 3217 | GR_COMBINE_LOCAL_CONSTANT, |
| 3218 | GR_COMBINE_OTHER_NONE, |
| 3219 | FXFALSE); |
| 3220 | grConstantColorValue (0xFF0000FF); |
| 3221 | grAlphaBlendFunction (GR_BLEND_ONE, |
| 3222 | GR_BLEND_ZERO, |
| 3223 | GR_BLEND_ZERO, |
| 3224 | GR_BLEND_ZERO); |
| 3225 | grTexCombine (GR_TMU0, |
| 3226 | GR_COMBINE_FUNCTION_ZERO, |
| 3227 | GR_COMBINE_FACTOR_NONE, |
| 3228 | GR_COMBINE_FUNCTION_ZERO, |
| 3229 | GR_COMBINE_FACTOR_NONE, |
| 3230 | FXFALSE, FXFALSE); |
| 3231 | grTexCombine (GR_TMU1, |
| 3232 | GR_COMBINE_FUNCTION_ZERO, |
| 3233 | GR_COMBINE_FACTOR_NONE, |
| 3234 | GR_COMBINE_FUNCTION_ZERO, |
| 3235 | GR_COMBINE_FACTOR_NONE, |
| 3236 | FXFALSE, FXFALSE); |
| 3237 | break; |
| 3238 | } |
| 3239 | |
| 3240 | grAlphaTestFunction (GR_CMP_ALWAYS); |
| 3241 | grCullMode (GR_CULL_DISABLE); |
| 3242 | |
| 3243 | rdp.update |= UPDATE_COMBINE | UPDATE_ALPHA_COMPARE; |
| 3244 | } |
| 3245 | |
| 3246 | /****************************************************************** |
| 3247 | Function: FrameBufferRead |
| 3248 | Purpose: This function is called to notify the dll that the |
| 3249 | frame buffer memory is beening read at the given address. |
| 3250 | DLL should copy content from its render buffer to the frame buffer |
| 3251 | in N64 RDRAM |
| 3252 | DLL is responsible to maintain its own frame buffer memory addr list |
| 3253 | DLL should copy 4KB block content back to RDRAM frame buffer. |
| 3254 | Emulator should not call this function again if other memory |
| 3255 | is read within the same 4KB range |
| 3256 | input: addr rdram address |
| 3257 | val val |
| 3258 | size 1 = wxUint8, 2 = wxUint16, 4 = wxUint32 |
| 3259 | output: none |
| 3260 | *******************************************************************/ |
| 3261 | |
| 3262 | #ifdef __cplusplus |
| 3263 | extern "C" { |
| 3264 | #endif |
| 3265 | |
| 3266 | EXPORT void CALL FBRead(wxUint32 addr) |
| 3267 | { |
| 3268 | LOG ("FBRead ()\n"); |
| 3269 | |
| 3270 | if (cpu_fb_ignore) |
| 3271 | return; |
| 3272 | if (cpu_fb_write_called) |
| 3273 | { |
| 3274 | cpu_fb_ignore = TRUE; |
| 3275 | cpu_fb_write = FALSE; |
| 3276 | return; |
| 3277 | } |
| 3278 | cpu_fb_read_called = TRUE; |
| 3279 | wxUint32 a = segoffset(addr); |
| 3280 | FRDP("FBRead. addr: %08lx\n", a); |
| 3281 | if (!rdp.fb_drawn && (a >= rdp.cimg) && (a < rdp.ci_end)) |
| 3282 | { |
| 3283 | fbreads_back++; |
| 3284 | //if (fbreads_back > 2) //&& (rdp.ci_width <= 320)) |
| 3285 | { |
| 3286 | CopyFrameBuffer (); |
| 3287 | rdp.fb_drawn = TRUE; |
| 3288 | } |
| 3289 | } |
| 3290 | if (!rdp.fb_drawn_front && (a >= rdp.maincimg[1].addr) && (a < rdp.maincimg[1].addr + rdp.ci_width*rdp.ci_height*2)) |
| 3291 | { |
| 3292 | fbreads_front++; |
| 3293 | //if (fbreads_front > 2)//&& (rdp.ci_width <= 320)) |
| 3294 | { |
| 3295 | wxUint32 cimg = rdp.cimg; |
| 3296 | rdp.cimg = rdp.maincimg[1].addr; |
| 3297 | if (fb_emulation_enabled) |
| 3298 | { |
| 3299 | rdp.ci_width = rdp.maincimg[1].width; |
| 3300 | rdp.ci_count = 0; |
| 3301 | wxUint32 h = rdp.frame_buffers[0].height; |
| 3302 | rdp.frame_buffers[0].height = rdp.maincimg[1].height; |
| 3303 | CopyFrameBuffer(GR_BUFFER_FRONTBUFFER); |
| 3304 | rdp.frame_buffers[0].height = h; |
| 3305 | } |
| 3306 | else |
| 3307 | { |
| 3308 | CopyFrameBuffer(GR_BUFFER_FRONTBUFFER); |
| 3309 | } |
| 3310 | rdp.cimg = cimg; |
| 3311 | rdp.fb_drawn_front = TRUE; |
| 3312 | } |
| 3313 | } |
| 3314 | } |
| 3315 | |
| 3316 | #if 0 |
| 3317 | /****************************************************************** |
| 3318 | Function: FrameBufferWriteList |
| 3319 | Purpose: This function is called to notify the dll that the |
| 3320 | frame buffer has been modified by CPU at the given address. |
| 3321 | input: FrameBufferModifyEntry *plist |
| 3322 | size = size of the plist, max = 1024 |
| 3323 | output: none |
| 3324 | *******************************************************************/ |
| 3325 | EXPORT void CALL FBWList(FrameBufferModifyEntry *plist, wxUint32 size) |
| 3326 | { |
| 3327 | LOG ("FBWList ()\n"); |
| 3328 | FRDP("FBWList. size: %d\n", size); |
| 3329 | } |
| 3330 | #endif |
| 3331 | |
| 3332 | /****************************************************************** |
| 3333 | Function: FrameBufferWrite |
| 3334 | Purpose: This function is called to notify the dll that the |
| 3335 | frame buffer has been modified by CPU at the given address. |
| 3336 | input: addr rdram address |
| 3337 | val val |
| 3338 | size 1 = wxUint8, 2 = wxUint16, 4 = wxUint32 |
| 3339 | output: none |
| 3340 | *******************************************************************/ |
| 3341 | EXPORT void CALL FBWrite(wxUint32 addr, wxUint32 size) |
| 3342 | { |
| 3343 | LOG ("FBWrite ()\n"); |
| 3344 | if (cpu_fb_ignore) |
| 3345 | return; |
| 3346 | if (cpu_fb_read_called) |
| 3347 | { |
| 3348 | cpu_fb_ignore = TRUE; |
| 3349 | cpu_fb_write = FALSE; |
| 3350 | return; |
| 3351 | } |
| 3352 | cpu_fb_write_called = TRUE; |
| 3353 | wxUint32 a = segoffset(addr); |
| 3354 | FRDP("FBWrite. addr: %08lx\n", a); |
| 3355 | if (a < rdp.cimg || a > rdp.ci_end) |
| 3356 | return; |
| 3357 | cpu_fb_write = TRUE; |
| 3358 | wxUint32 shift_l = (a-rdp.cimg) >> 1; |
| 3359 | wxUint32 shift_r = shift_l+2; |
| 3360 | |
| 3361 | d_ul_x = min(d_ul_x, shift_l%rdp.ci_width); |
| 3362 | d_ul_y = min(d_ul_y, shift_l/rdp.ci_width); |
| 3363 | d_lr_x = max(d_lr_x, shift_r%rdp.ci_width); |
| 3364 | d_lr_y = max(d_lr_y, shift_r/rdp.ci_width); |
| 3365 | } |
| 3366 | |
| 3367 | |
| 3368 | /************************************************************************ |
| 3369 | Function: FBGetFrameBufferInfo |
| 3370 | Purpose: This function is called by the emulator core to retrieve frame |
| 3371 | buffer information from the video plugin in order to be able |
| 3372 | to notify the video plugin about CPU frame buffer read/write |
| 3373 | operations |
| 3374 | |
| 3375 | size: |
| 3376 | = 1 byte |
| 3377 | = 2 word (16 bit) <-- this is N64 default depth buffer format |
| 3378 | = 4 dword (32 bit) |
| 3379 | |
| 3380 | when frame buffer information is not available yet, set all values |
| 3381 | in the FrameBufferInfo structure to 0 |
| 3382 | |
| 3383 | input: FrameBufferInfo pinfo[6] |
| 3384 | pinfo is pointed to a FrameBufferInfo structure which to be |
| 3385 | filled in by this function |
| 3386 | output: Values are return in the FrameBufferInfo structure |
| 3387 | Plugin can return up to 6 frame buffer info |
| 3388 | ************************************************************************/ |
| 3389 | ///* |
| 3390 | #if 0 |
| 3391 | typedef struct |
| 3392 | { |
| 3393 | wxUint32 addr; |
| 3394 | wxUint32 size; |
| 3395 | wxUint32 width; |
| 3396 | wxUint32 height; |
| 3397 | } FrameBufferInfo; |
| 3398 | #endif |
| 3399 | EXPORT void CALL FBGetFrameBufferInfo(void *p) |
| 3400 | { |
| 3401 | VLOG ("FBGetFrameBufferInfo ()\n"); |
| 3402 | FrameBufferInfo * pinfo = (FrameBufferInfo *)p; |
| 3403 | memset(pinfo,0,sizeof(FrameBufferInfo)*6); |
| 3404 | if (!(settings.frame_buffer&fb_get_info)) |
| 3405 | return; |
| 3406 | LRDP("FBGetFrameBufferInfo ()\n"); |
| 3407 | //* |
| 3408 | if (fb_emulation_enabled) |
| 3409 | { |
| 3410 | pinfo[0].addr = rdp.maincimg[1].addr; |
| 3411 | pinfo[0].size = rdp.maincimg[1].size; |
| 3412 | pinfo[0].width = rdp.maincimg[1].width; |
| 3413 | pinfo[0].height = rdp.maincimg[1].height; |
| 3414 | int info_index = 1; |
| 3415 | for (int i = 0; i < rdp.num_of_ci && info_index < 6; i++) |
| 3416 | { |
| 3417 | COLOR_IMAGE & cur_fb = rdp.frame_buffers[i]; |
| 3418 | if (cur_fb.status == ci_main || cur_fb.status == ci_copy_self || |
| 3419 | cur_fb.status == ci_old_copy) |
| 3420 | { |
| 3421 | pinfo[info_index].addr = cur_fb.addr; |
| 3422 | pinfo[info_index].size = cur_fb.size; |
| 3423 | pinfo[info_index].width = cur_fb.width; |
| 3424 | pinfo[info_index].height = cur_fb.height; |
| 3425 | info_index++; |
| 3426 | } |
| 3427 | } |
| 3428 | } |
| 3429 | else |
| 3430 | { |
| 3431 | pinfo[0].addr = rdp.maincimg[0].addr; |
| 3432 | pinfo[0].size = rdp.ci_size; |
| 3433 | pinfo[0].width = rdp.ci_width; |
| 3434 | pinfo[0].height = rdp.ci_width*3/4; |
| 3435 | pinfo[1].addr = rdp.maincimg[1].addr; |
| 3436 | pinfo[1].size = rdp.ci_size; |
| 3437 | pinfo[1].width = rdp.ci_width; |
| 3438 | pinfo[1].height = rdp.ci_width*3/4; |
| 3439 | } |
| 3440 | //*/ |
| 3441 | } |
| 3442 | #ifdef __cplusplus |
| 3443 | } |
| 3444 | #endif |
| 3445 | //*/ |
| 3446 | #include "ucodeFB.h" |
| 3447 | |
| 3448 | void DetectFrameBufferUsage () |
| 3449 | { |
| 3450 | LRDP("DetectFrameBufferUsage\n"); |
| 3451 | |
| 3452 | wxUint32 dlist_start = *(wxUint32*)(gfx.DMEM+0xFF0); |
| 3453 | wxUint32 a; |
| 3454 | |
| 3455 | int tidal = FALSE; |
| 3456 | if ((settings.hacks&hack_PMario) && (rdp.copy_ci_index || rdp.frame_buffers[rdp.copy_ci_index].status == ci_copy_self)) |
| 3457 | tidal = TRUE; |
| 3458 | wxUint32 ci = rdp.cimg, zi = rdp.zimg; |
| 3459 | wxUint32 ci_height = rdp.frame_buffers[(rdp.ci_count > 0)?rdp.ci_count-1:0].height; |
| 3460 | rdp.main_ci = rdp.main_ci_end = rdp.main_ci_bg = rdp.ci_count = 0; |
| 3461 | rdp.main_ci_index = rdp.copy_ci_index = rdp.copy_zi_index = 0; |
| 3462 | rdp.zimg_end = 0; |
| 3463 | rdp.tmpzimg = 0; |
| 3464 | rdp.motionblur = FALSE; |
| 3465 | rdp.main_ci_last_tex_addr = 0; |
| 3466 | int previous_ci_was_read = rdp.read_previous_ci; |
| 3467 | rdp.read_previous_ci = FALSE; |
| 3468 | rdp.read_whole_frame = FALSE; |
| 3469 | rdp.swap_ci_index = rdp.black_ci_index = -1; |
| 3470 | SwapOK = TRUE; |
| 3471 | |
| 3472 | // Start executing at the start of the display list |
| 3473 | rdp.pc_i = 0; |
| 3474 | rdp.pc[rdp.pc_i] = dlist_start; |
| 3475 | rdp.dl_count = -1; |
| 3476 | rdp.halt = 0; |
| 3477 | rdp.scale_x_bak = rdp.scale_x; |
| 3478 | rdp.scale_y_bak = rdp.scale_y; |
| 3479 | |
| 3480 | // MAIN PROCESSING LOOP |
| 3481 | do { |
| 3482 | |
| 3483 | // Get the address of the next command |
| 3484 | a = rdp.pc[rdp.pc_i] & BMASK; |
| 3485 | |
| 3486 | // Load the next command and its input |
| 3487 | rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit |
| 3488 | rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // / |
| 3489 | |
| 3490 | // Output the address before the command |
| 3491 | |
| 3492 | // Go to the next instruction |
| 3493 | rdp.pc[rdp.pc_i] = (a+8) & BMASK; |
| 3494 | |
| 3495 | if (wxPtrToUInt(reinterpret_cast<void*>(gfx_instruction_lite[settings.ucode][rdp.cmd0>>24]))) |
| 3496 | gfx_instruction_lite[settings.ucode][rdp.cmd0>>24] (); |
| 3497 | |
| 3498 | // check DL counter |
| 3499 | if (rdp.dl_count != -1) |
| 3500 | { |
| 3501 | rdp.dl_count --; |
| 3502 | if (rdp.dl_count == 0) |
| 3503 | { |
| 3504 | rdp.dl_count = -1; |
| 3505 | |
| 3506 | LRDP("End of DL\n"); |
| 3507 | rdp.pc_i --; |
| 3508 | } |
| 3509 | } |
| 3510 | |
| 3511 | } while (!rdp.halt); |
| 3512 | SwapOK = TRUE; |
| 3513 | if (rdp.ci_count > NUMTEXBUF) //overflow |
| 3514 | { |
| 3515 | rdp.cimg = ci; |
| 3516 | rdp.zimg = zi; |
| 3517 | rdp.num_of_ci = rdp.ci_count; |
| 3518 | rdp.scale_x = rdp.scale_x_bak; |
| 3519 | rdp.scale_y = rdp.scale_y_bak; |
| 3520 | return; |
| 3521 | } |
| 3522 | |
| 3523 | if (rdp.black_ci_index > 0 && rdp.black_ci_index < rdp.copy_ci_index) |
| 3524 | rdp.frame_buffers[rdp.black_ci_index].status = ci_main; |
| 3525 | |
| 3526 | if (rdp.frame_buffers[rdp.ci_count-1].status == ci_unknown) |
| 3527 | { |
| 3528 | if (rdp.ci_count > 1) |
| 3529 | rdp.frame_buffers[rdp.ci_count-1].status = ci_aux; |
| 3530 | else |
| 3531 | rdp.frame_buffers[rdp.ci_count-1].status = ci_main; |
| 3532 | } |
| 3533 | |
| 3534 | if ((rdp.frame_buffers[rdp.ci_count-1].status == ci_aux) && |
| 3535 | (rdp.frame_buffers[rdp.main_ci_index].width < 320) && |
| 3536 | (rdp.frame_buffers[rdp.ci_count-1].width > rdp.frame_buffers[rdp.main_ci_index].width)) |
| 3537 | { |
| 3538 | for (int i = 0; i < rdp.ci_count; i++) |
| 3539 | { |
| 3540 | if (rdp.frame_buffers[i].status == ci_main) |
| 3541 | rdp.frame_buffers[i].status = ci_aux; |
| 3542 | else if (rdp.frame_buffers[i].addr == rdp.frame_buffers[rdp.ci_count-1].addr) |
| 3543 | rdp.frame_buffers[i].status = ci_main; |
| 3544 | // FRDP("rdp.frame_buffers[%d].status = %d\n", i, rdp.frame_buffers[i].status); |
| 3545 | } |
| 3546 | rdp.main_ci_index = rdp.ci_count-1; |
| 3547 | } |
| 3548 | |
| 3549 | int all_zimg = TRUE; |
| 3550 | int i; |
| 3551 | for (i = 0; i < rdp.ci_count; i++) |
| 3552 | { |
| 3553 | if (rdp.frame_buffers[i].status != ci_zimg) |
| 3554 | { |
| 3555 | all_zimg = FALSE; |
| 3556 | break; |
| 3557 | } |
| 3558 | } |
| 3559 | if (all_zimg) |
| 3560 | { |
| 3561 | for (i = 0; i < rdp.ci_count; i++) |
| 3562 | rdp.frame_buffers[i].status = ci_main; |
| 3563 | } |
| 3564 | |
| 3565 | LRDP("detect fb final results: \n"); |
| 3566 | for (i = 0; i < rdp.ci_count; i++) |
| 3567 | { |
| 3568 | 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); |
| 3569 | } |
| 3570 | |
| 3571 | rdp.cimg = ci; |
| 3572 | rdp.zimg = zi; |
| 3573 | rdp.num_of_ci = rdp.ci_count; |
| 3574 | if (rdp.read_previous_ci && previous_ci_was_read) |
| 3575 | { |
| 3576 | if (!fb_hwfbe_enabled || !rdp.copy_ci_index) |
| 3577 | rdp.motionblur = TRUE; |
| 3578 | } |
| 3579 | if (rdp.motionblur || fb_hwfbe_enabled || (rdp.frame_buffers[rdp.copy_ci_index].status == ci_aux_copy)) |
| 3580 | { |
| 3581 | rdp.scale_x = rdp.scale_x_bak; |
| 3582 | rdp.scale_y = rdp.scale_y_bak; |
| 3583 | } |
| 3584 | |
| 3585 | if ((rdp.read_previous_ci || previous_ci_was_read) && !rdp.copy_ci_index) |
| 3586 | rdp.read_whole_frame = TRUE; |
| 3587 | if (rdp.read_whole_frame) |
| 3588 | { |
| 3589 | if (fb_hwfbe_enabled) |
| 3590 | { |
| 3591 | if (rdp.read_previous_ci && !previous_ci_was_read && (settings.swapmode != 2) && (settings.ucode != ucode_PerfectDark)) |
| 3592 | { |
| 3593 | int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0; |
| 3594 | wxUint32 height = rdp.frame_buffers[ind].height; |
| 3595 | rdp.frame_buffers[ind].height = ci_height; |
| 3596 | CopyFrameBuffer(); |
| 3597 | rdp.frame_buffers[ind].height = height; |
| 3598 | } |
| 3599 | if (rdp.swap_ci_index < 0) |
| 3600 | { |
| 3601 | rdp.texbufs[0].clear_allowed = rdp.texbufs[1].clear_allowed = TRUE; |
| 3602 | OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); |
| 3603 | } |
| 3604 | } |
| 3605 | else |
| 3606 | { |
| 3607 | if (rdp.motionblur) |
| 3608 | { |
| 3609 | if (settings.frame_buffer&fb_motionblur) |
| 3610 | CopyFrameBuffer(); |
| 3611 | else |
| 3612 | memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size); |
| 3613 | } |
| 3614 | else //if (ci_width == rdp.frame_buffers[rdp.main_ci_index].width) |
| 3615 | { |
| 3616 | if (rdp.maincimg[0].height > 65) //for 1080 |
| 3617 | { |
| 3618 | rdp.cimg = rdp.maincimg[0].addr; |
| 3619 | rdp.ci_width = rdp.maincimg[0].width; |
| 3620 | rdp.ci_count = 0; |
| 3621 | wxUint32 h = rdp.frame_buffers[0].height; |
| 3622 | rdp.frame_buffers[0].height = rdp.maincimg[0].height; |
| 3623 | CopyFrameBuffer(); |
| 3624 | rdp.frame_buffers[0].height = h; |
| 3625 | } |
| 3626 | else //conker |
| 3627 | { |
| 3628 | CopyFrameBuffer(); |
| 3629 | } |
| 3630 | } |
| 3631 | } |
| 3632 | } |
| 3633 | |
| 3634 | if (fb_hwfbe_enabled) |
| 3635 | { |
| 3636 | for (i = 0; i < voodoo.num_tmu; i++) |
| 3637 | { |
| 3638 | rdp.texbufs[i].clear_allowed = TRUE; |
| 3639 | for (int j = 0; j < 256; j++) |
| 3640 | { |
| 3641 | rdp.texbufs[i].images[j].drawn = FALSE; |
| 3642 | rdp.texbufs[i].images[j].clear = TRUE; |
| 3643 | } |
| 3644 | } |
| 3645 | if (tidal) |
| 3646 | { |
| 3647 | //LRDP("Tidal wave!\n"); |
| 3648 | rdp.copy_ci_index = rdp.main_ci_index; |
| 3649 | } |
| 3650 | } |
| 3651 | rdp.ci_count = 0; |
| 3652 | if (settings.hacks&hack_Banjo2) |
| 3653 | rdp.cur_tex_buf = 0; |
| 3654 | rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index]; |
| 3655 | // rdp.scale_x = rdp.scale_x_bak; |
| 3656 | // rdp.scale_y = rdp.scale_y_bak; |
| 3657 | LRDP("DetectFrameBufferUsage End\n"); |
| 3658 | } |
| 3659 | |
| 3660 | /******************************************* |
| 3661 | * ProcessRDPList * |
| 3662 | ******************************************* |
| 3663 | * based on sources of ziggy's z64 * |
| 3664 | *******************************************/ |
| 3665 | |
| 3666 | static wxUint32 rdp_cmd_ptr = 0; |
| 3667 | static wxUint32 rdp_cmd_cur = 0; |
| 3668 | static wxUint32 rdp_cmd_data[0x1000]; |
| 3669 | |
| 3670 | void lle_triangle(wxUint32 w1, wxUint32 w2, int shade, int texture, int zbuffer, |
| 3671 | wxUint32 * rdp_cmd) |
| 3672 | { |
| 3673 | rdp.cur_tile = (w1 >> 16) & 0x7; |
| 3674 | int j; |
| 3675 | int xleft, xright, xleft_inc, xright_inc; |
| 3676 | int r, g, b, a, z, s, t, w; |
| 3677 | int drdx = 0, dgdx = 0, dbdx = 0, dadx = 0, dzdx = 0, dsdx = 0, dtdx = 0, dwdx = 0; |
| 3678 | int drde = 0, dgde = 0, dbde = 0, dade = 0, dzde = 0, dsde = 0, dtde = 0, dwde = 0; |
| 3679 | int flip = (w1 & 0x800000) ? 1 : 0; |
| 3680 | |
| 3681 | wxInt32 yl, ym, yh; |
| 3682 | wxInt32 xl, xm, xh; |
| 3683 | wxInt32 dxldy, dxhdy, dxmdy; |
| 3684 | wxUint32 w3, w4, w5, w6, w7, w8; |
| 3685 | |
| 3686 | wxUint32 * shade_base = rdp_cmd + 8; |
| 3687 | wxUint32 * texture_base = rdp_cmd + 8; |
| 3688 | wxUint32 * zbuffer_base = rdp_cmd + 8; |
| 3689 | |
| 3690 | if (shade) |
| 3691 | { |
| 3692 | texture_base += 16; |
| 3693 | zbuffer_base += 16; |
| 3694 | } |
| 3695 | if (texture) |
| 3696 | { |
| 3697 | zbuffer_base += 16; |
| 3698 | } |
| 3699 | |
| 3700 | w3 = rdp_cmd[2]; |
| 3701 | w4 = rdp_cmd[3]; |
| 3702 | w5 = rdp_cmd[4]; |
| 3703 | w6 = rdp_cmd[5]; |
| 3704 | w7 = rdp_cmd[6]; |
| 3705 | w8 = rdp_cmd[7]; |
| 3706 | |
| 3707 | yl = (w1 & 0x3fff); |
| 3708 | ym = ((w2 >> 16) & 0x3fff); |
| 3709 | yh = ((w2 >> 0) & 0x3fff); |
| 3710 | xl = (wxInt32)(w3); |
| 3711 | xh = (wxInt32)(w5); |
| 3712 | xm = (wxInt32)(w7); |
| 3713 | dxldy = (wxInt32)(w4); |
| 3714 | dxhdy = (wxInt32)(w6); |
| 3715 | dxmdy = (wxInt32)(w8); |
| 3716 | |
| 3717 | if (yl & (0x800<<2)) yl |= 0xfffff000<<2; |
| 3718 | if (ym & (0x800<<2)) ym |= 0xfffff000<<2; |
| 3719 | if (yh & (0x800<<2)) yh |= 0xfffff000<<2; |
| 3720 | |
| 3721 | yh &= ~3; |
| 3722 | |
| 3723 | r = 0xff; g = 0xff; b = 0xff; a = 0xff; z = 0xffff0000; s = 0; t = 0; w = 0x30000; |
| 3724 | |
| 3725 | if (shade) |
| 3726 | { |
| 3727 | r = (shade_base[0] & 0xffff0000) | ((shade_base[+4 ] >> 16) & 0x0000ffff); |
| 3728 | g = ((shade_base[0 ] << 16) & 0xffff0000) | (shade_base[4 ] & 0x0000ffff); |
| 3729 | b = (shade_base[1 ] & 0xffff0000) | ((shade_base[5 ] >> 16) & 0x0000ffff); |
| 3730 | a = ((shade_base[1 ] << 16) & 0xffff0000) | (shade_base[5 ] & 0x0000ffff); |
| 3731 | drdx = (shade_base[2 ] & 0xffff0000) | ((shade_base[6 ] >> 16) & 0x0000ffff); |
| 3732 | dgdx = ((shade_base[2 ] << 16) & 0xffff0000) | (shade_base[6 ] & 0x0000ffff); |
| 3733 | dbdx = (shade_base[3 ] & 0xffff0000) | ((shade_base[7 ] >> 16) & 0x0000ffff); |
| 3734 | dadx = ((shade_base[3 ] << 16) & 0xffff0000) | (shade_base[7 ] & 0x0000ffff); |
| 3735 | drde = (shade_base[8 ] & 0xffff0000) | ((shade_base[12] >> 16) & 0x0000ffff); |
| 3736 | dgde = ((shade_base[8 ] << 16) & 0xffff0000) | (shade_base[12] & 0x0000ffff); |
| 3737 | dbde = (shade_base[9 ] & 0xffff0000) | ((shade_base[13] >> 16) & 0x0000ffff); |
| 3738 | dade = ((shade_base[9 ] << 16) & 0xffff0000) | (shade_base[13] & 0x0000ffff); |
| 3739 | } |
| 3740 | if (texture) |
| 3741 | { |
| 3742 | s = (texture_base[0 ] & 0xffff0000) | ((texture_base[4 ] >> 16) & 0x0000ffff); |
| 3743 | t = ((texture_base[0 ] << 16) & 0xffff0000) | (texture_base[4 ] & 0x0000ffff); |
| 3744 | w = (texture_base[1 ] & 0xffff0000) | ((texture_base[5 ] >> 16) & 0x0000ffff); |
| 3745 | // w = abs(w); |
| 3746 | dsdx = (texture_base[2 ] & 0xffff0000) | ((texture_base[6 ] >> 16) & 0x0000ffff); |
| 3747 | dtdx = ((texture_base[2 ] << 16) & 0xffff0000) | (texture_base[6 ] & 0x0000ffff); |
| 3748 | dwdx = (texture_base[3 ] & 0xffff0000) | ((texture_base[7 ] >> 16) & 0x0000ffff); |
| 3749 | dsde = (texture_base[8 ] & 0xffff0000) | ((texture_base[12] >> 16) & 0x0000ffff); |
| 3750 | dtde = ((texture_base[8 ] << 16) & 0xffff0000) | (texture_base[12] & 0x0000ffff); |
| 3751 | dwde = (texture_base[9 ] & 0xffff0000) | ((texture_base[13] >> 16) & 0x0000ffff); |
| 3752 | } |
| 3753 | if (zbuffer) |
| 3754 | { |
| 3755 | z = zbuffer_base[0]; |
| 3756 | dzdx = zbuffer_base[1]; |
| 3757 | dzde = zbuffer_base[2]; |
| 3758 | } |
| 3759 | |
| 3760 | xh <<= 2; xm <<= 2; xl <<= 2; |
| 3761 | r <<= 2; g <<= 2; b <<= 2; a <<= 2; |
| 3762 | dsde >>= 2; dtde >>= 2; dsdx >>= 2; dtdx >>= 2; |
| 3763 | dzdx >>= 2; dzde >>= 2; |
| 3764 | dwdx >>= 2; dwde >>= 2; |
| 3765 | |
| 3766 | #define XSCALE(x) (float(x)/(1<<18)) |
| 3767 | #define YSCALE(y) (float(y)/(1<<2)) |
| 3768 | #define ZSCALE(z) ((rdp.zsrc == 1)? float(rdp.prim_depth) : float(wxUint32(z))/0xffff0000) |
| 3769 | //#define WSCALE(w) (rdp.Persp_en? (float(wxUint32(w) + 0x10000)/0xffff0000) : 1.0f) |
| 3770 | //#define WSCALE(w) (rdp.Persp_en? 4294901760.0/(w + 65536) : 1.0f) |
| 3771 | #define WSCALE(w) (rdp.Persp_en? 65536.0f/float((w+ 0xffff)>>16) : 1.0f) |
| 3772 | #define CSCALE(c) (((c)>0x3ff0000? 0x3ff0000:((c)<0? 0 : (c)))>>18) |
| 3773 | #define _PERSP(w) ( w ) |
| 3774 | #define PERSP(s, w) ( ((int64_t)(s) << 20) / (_PERSP(w)? _PERSP(w):1) ) |
| 3775 | #define SSCALE(s, _w) (rdp.Persp_en? float(PERSP(s, _w))/(1 << 10) : float(s)/(1<<21)) |
| 3776 | #define TSCALE(s, w) (rdp.Persp_en? float(PERSP(s, w))/(1 << 10) : float(s)/(1<<21)) |
| 3777 | |
| 3778 | int nbVtxs = 0; |
| 3779 | VERTEX vtxbuf[12]; |
| 3780 | VERTEX * vtx = &vtxbuf[nbVtxs++]; |
| 3781 | |
| 3782 | xleft = xm; |
| 3783 | xright = xh; |
| 3784 | xleft_inc = dxmdy; |
| 3785 | xright_inc = dxhdy; |
| 3786 | |
| 3787 | while (yh<ym && |
| 3788 | !((!flip && xleft < xright+0x10000) || |
| 3789 | (flip && xleft > xright-0x10000))) { |
| 3790 | xleft += xleft_inc; |
| 3791 | xright += xright_inc; |
| 3792 | s += dsde; t += dtde; w += dwde; |
| 3793 | r += drde; g += dgde; b += dbde; a += dade; |
| 3794 | z += dzde; |
| 3795 | yh++; |
| 3796 | } |
| 3797 | |
| 3798 | j = ym-yh; |
| 3799 | if (j > 0) |
| 3800 | { |
| 3801 | int dx = (xleft-xright)>>16; |
| 3802 | if ((!flip && xleft < xright) || |
| 3803 | (flip/* && xleft > xright*/)) |
| 3804 | { |
| 3805 | if (shade) { |
| 3806 | vtx->r = CSCALE(r+drdx*dx); |
| 3807 | vtx->g = CSCALE(g+dgdx*dx); |
| 3808 | vtx->b = CSCALE(b+dbdx*dx); |
| 3809 | vtx->a = CSCALE(a+dadx*dx); |
| 3810 | } |
| 3811 | if (texture) { |
| 3812 | vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx); |
| 3813 | vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx); |
| 3814 | } |
| 3815 | vtx->x = XSCALE(xleft); |
| 3816 | vtx->y = YSCALE(yh); |
| 3817 | vtx->z = ZSCALE(z+dzdx*dx); |
| 3818 | vtx->w = WSCALE(w+dwdx*dx); |
| 3819 | vtx = &vtxbuf[nbVtxs++]; |
| 3820 | } |
| 3821 | if ((!flip/* && xleft < xright*/) || |
| 3822 | (flip && xleft > xright)) |
| 3823 | { |
| 3824 | if (shade) { |
| 3825 | vtx->r = CSCALE(r); |
| 3826 | vtx->g = CSCALE(g); |
| 3827 | vtx->b = CSCALE(b); |
| 3828 | vtx->a = CSCALE(a); |
| 3829 | } |
| 3830 | if (texture) { |
| 3831 | vtx->ou = SSCALE(s, w); |
| 3832 | vtx->ov = TSCALE(t, w); |
| 3833 | } |
| 3834 | vtx->x = XSCALE(xright); |
| 3835 | vtx->y = YSCALE(yh); |
| 3836 | vtx->z = ZSCALE(z); |
| 3837 | vtx->w = WSCALE(w); |
| 3838 | vtx = &vtxbuf[nbVtxs++]; |
| 3839 | } |
| 3840 | xleft += xleft_inc*j; xright += xright_inc*j; |
| 3841 | s += dsde*j; t += dtde*j; |
| 3842 | if (w + dwde*j) w += dwde*j; |
| 3843 | else w += dwde*(j-1); |
| 3844 | r += drde*j; g += dgde*j; b += dbde*j; a += dade*j; |
| 3845 | z += dzde*j; |
| 3846 | // render ... |
| 3847 | } |
| 3848 | |
| 3849 | if (xl != xh) |
| 3850 | xleft = xl; |
| 3851 | |
| 3852 | //if (yl-ym > 0) |
| 3853 | { |
| 3854 | int dx = (xleft-xright)>>16; |
| 3855 | if ((!flip && xleft <= xright) || |
| 3856 | (flip/* && xleft >= xright*/)) |
| 3857 | { |
| 3858 | if (shade) { |
| 3859 | vtx->r = CSCALE(r+drdx*dx); |
| 3860 | vtx->g = CSCALE(g+dgdx*dx); |
| 3861 | vtx->b = CSCALE(b+dbdx*dx); |
| 3862 | vtx->a = CSCALE(a+dadx*dx); |
| 3863 | } |
| 3864 | if (texture) { |
| 3865 | vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx); |
| 3866 | vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx); |
| 3867 | } |
| 3868 | vtx->x = XSCALE(xleft); |
| 3869 | vtx->y = YSCALE(ym); |
| 3870 | vtx->z = ZSCALE(z+dzdx*dx); |
| 3871 | vtx->w = WSCALE(w+dwdx*dx); |
| 3872 | vtx = &vtxbuf[nbVtxs++]; |
| 3873 | } |
| 3874 | if ((!flip/* && xleft <= xright*/) || |
| 3875 | (flip && xleft >= xright)) |
| 3876 | { |
| 3877 | if (shade) { |
| 3878 | vtx->r = CSCALE(r); |
| 3879 | vtx->g = CSCALE(g); |
| 3880 | vtx->b = CSCALE(b); |
| 3881 | vtx->a = CSCALE(a); |
| 3882 | } |
| 3883 | if (texture) { |
| 3884 | vtx->ou = SSCALE(s, w); |
| 3885 | vtx->ov = TSCALE(t, w); |
| 3886 | } |
| 3887 | vtx->x = XSCALE(xright); |
| 3888 | vtx->y = YSCALE(ym); |
| 3889 | vtx->z = ZSCALE(z); |
| 3890 | vtx->w = WSCALE(w); |
| 3891 | vtx = &vtxbuf[nbVtxs++]; |
| 3892 | } |
| 3893 | } |
| 3894 | xleft_inc = dxldy; |
| 3895 | xright_inc = dxhdy; |
| 3896 | |
| 3897 | j = yl-ym; |
| 3898 | //j--; // ? |
| 3899 | xleft += xleft_inc*j; xright += xright_inc*j; |
| 3900 | s += dsde*j; t += dtde*j; w += dwde*j; |
| 3901 | r += drde*j; g += dgde*j; b += dbde*j; a += dade*j; |
| 3902 | z += dzde*j; |
| 3903 | |
| 3904 | while (yl>ym && |
| 3905 | !((!flip && xleft < xright+0x10000) || |
| 3906 | (flip && xleft > xright-0x10000))) { |
| 3907 | xleft -= xleft_inc; xright -= xright_inc; |
| 3908 | s -= dsde; t -= dtde; w -= dwde; |
| 3909 | r -= drde; g -= dgde; b -= dbde; a -= dade; |
| 3910 | z -= dzde; |
| 3911 | j--; |
| 3912 | yl--; |
| 3913 | } |
| 3914 | |
| 3915 | // render ... |
| 3916 | if (j >= 0) { |
| 3917 | int dx = (xleft-xright)>>16; |
| 3918 | if ((!flip && xleft <= xright) || |
| 3919 | (flip/* && xleft >= xright*/)) |
| 3920 | { |
| 3921 | if (shade) { |
| 3922 | vtx->r = CSCALE(r+drdx*dx); |
| 3923 | vtx->g = CSCALE(g+dgdx*dx); |
| 3924 | vtx->b = CSCALE(b+dbdx*dx); |
| 3925 | vtx->a = CSCALE(a+dadx*dx); |
| 3926 | } |
| 3927 | if (texture) { |
| 3928 | vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx); |
| 3929 | vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx); |
| 3930 | } |
| 3931 | vtx->x = XSCALE(xleft); |
| 3932 | vtx->y = YSCALE(yl); |
| 3933 | vtx->z = ZSCALE(z+dzdx*dx); |
| 3934 | vtx->w = WSCALE(w+dwdx*dx); |
| 3935 | vtx = &vtxbuf[nbVtxs++]; |
| 3936 | } |
| 3937 | if ((!flip/* && xleft <= xright*/) || |
| 3938 | (flip && xleft >= xright)) |
| 3939 | { |
| 3940 | if (shade) { |
| 3941 | vtx->r = CSCALE(r); |
| 3942 | vtx->g = CSCALE(g); |
| 3943 | vtx->b = CSCALE(b); |
| 3944 | vtx->a = CSCALE(a); |
| 3945 | } |
| 3946 | if (texture) { |
| 3947 | vtx->ou = SSCALE(s, w); |
| 3948 | vtx->ov = TSCALE(t, w); |
| 3949 | } |
| 3950 | vtx->x = XSCALE(xright); |
| 3951 | vtx->y = YSCALE(yl); |
| 3952 | vtx->z = ZSCALE(z); |
| 3953 | vtx->w = WSCALE(w); |
| 3954 | vtx = &vtxbuf[nbVtxs++]; |
| 3955 | } |
| 3956 | } |
| 3957 | |
| 3958 | if (fullscreen) |
| 3959 | { |
| 3960 | update (); |
| 3961 | for (int k = 0; k < nbVtxs-1; k++) |
| 3962 | { |
| 3963 | VERTEX * v = &vtxbuf[k]; |
| 3964 | v->x = v->x * rdp.scale_x + rdp.offset_x; |
| 3965 | v->y = v->y * rdp.scale_y + rdp.offset_y; |
| 3966 | // v->z = 1.0f;///v->w; |
| 3967 | v->q = 1.0f/v->w; |
| 3968 | v->u1 = v->u0 = v->ou; |
| 3969 | v->v1 = v->v0 = v->ov; |
| 3970 | if (rdp.tex >= 1 && rdp.cur_cache[0]) |
| 3971 | { |
| 3972 | if (rdp.tiles[rdp.cur_tile].shift_s) |
| 3973 | { |
| 3974 | if (rdp.tiles[rdp.cur_tile].shift_s > 10) |
| 3975 | v->u0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s)); |
| 3976 | else |
| 3977 | v->u0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_s); |
| 3978 | } |
| 3979 | if (rdp.tiles[rdp.cur_tile].shift_t) |
| 3980 | { |
| 3981 | if (rdp.tiles[rdp.cur_tile].shift_t > 10) |
| 3982 | v->v0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t)); |
| 3983 | else |
| 3984 | v->v0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_t); |
| 3985 | } |
| 3986 | |
| 3987 | v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s; |
| 3988 | v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t; |
| 3989 | v->u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * v->u0; |
| 3990 | v->v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * v->v0; |
| 3991 | v->u0 /= v->w; |
| 3992 | v->v0 /= v->w; |
| 3993 | } |
| 3994 | |
| 3995 | if (rdp.tex >= 2 && rdp.cur_cache[1]) |
| 3996 | { |
| 3997 | if (rdp.tiles[rdp.cur_tile+1].shift_s) |
| 3998 | { |
| 3999 | if (rdp.tiles[rdp.cur_tile+1].shift_s > 10) |
| 4000 | v->u1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s)); |
| 4001 | else |
| 4002 | v->u1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_s); |
| 4003 | } |
| 4004 | if (rdp.tiles[rdp.cur_tile+1].shift_t) |
| 4005 | { |
| 4006 | if (rdp.tiles[rdp.cur_tile+1].shift_t > 10) |
| 4007 | v->v1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t)); |
| 4008 | else |
| 4009 | v->v1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_t); |
| 4010 | } |
| 4011 | |
| 4012 | v->u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s; |
| 4013 | v->v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t; |
| 4014 | v->u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * v->u1; |
| 4015 | v->v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * v->v1; |
| 4016 | v->u1 /= v->w; |
| 4017 | v->v1 /= v->w; |
| 4018 | } |
| 4019 | apply_shade_mods (v); |
| 4020 | } |
| 4021 | ConvertCoordsConvert (vtxbuf, nbVtxs); |
| 4022 | grCullMode (GR_CULL_DISABLE); |
| 4023 | grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, nbVtxs-1, vtxbuf, sizeof(VERTEX)); |
| 4024 | if (_debugger.capture) |
| 4025 | { |
| 4026 | VERTEX vl[3]; |
| 4027 | vl[0] = vtxbuf[0]; |
| 4028 | vl[1] = vtxbuf[2]; |
| 4029 | vl[2] = vtxbuf[1]; |
| 4030 | add_tri (vl, 3, TRI_TRIANGLE); |
| 4031 | rdp.tri_n++; |
| 4032 | if (nbVtxs > 4) |
| 4033 | { |
| 4034 | vl[0] = vtxbuf[2]; |
| 4035 | vl[1] = vtxbuf[3]; |
| 4036 | vl[2] = vtxbuf[1]; |
| 4037 | add_tri (vl, 3, TRI_TRIANGLE); |
| 4038 | rdp.tri_n++; |
| 4039 | } |
| 4040 | } |
| 4041 | } |
| 4042 | } |
| 4043 | |
| 4044 | static void rdp_triangle(int shade, int texture, int zbuffer) |
| 4045 | { |
| 4046 | lle_triangle(rdp.cmd0, rdp.cmd1, shade, texture, zbuffer, rdp_cmd_data + rdp_cmd_cur); |
| 4047 | } |
| 4048 | |
| 4049 | static void rdp_trifill() |
| 4050 | { |
| 4051 | rdp_triangle(0, 0, 0); |
| 4052 | LRDP("trifill\n"); |
| 4053 | } |
| 4054 | |
| 4055 | static void rdp_trishade() |
| 4056 | { |
| 4057 | rdp_triangle(1, 0, 0); |
| 4058 | LRDP("trishade\n"); |
| 4059 | } |
| 4060 | |
| 4061 | static void rdp_tritxtr() |
| 4062 | { |
| 4063 | rdp_triangle(0, 1, 0); |
| 4064 | LRDP("tritxtr\n"); |
| 4065 | } |
| 4066 | |
| 4067 | static void rdp_trishadetxtr() |
| 4068 | { |
| 4069 | rdp_triangle(1, 1, 0); |
| 4070 | LRDP("trishadetxtr\n"); |
| 4071 | } |
| 4072 | |
| 4073 | static void rdp_trifillz() |
| 4074 | { |
| 4075 | rdp_triangle(0, 0, 1); |
| 4076 | LRDP("trifillz\n"); |
| 4077 | } |
| 4078 | |
| 4079 | static void rdp_trishadez() |
| 4080 | { |
| 4081 | rdp_triangle(1, 0, 1); |
| 4082 | LRDP("trishadez\n"); |
| 4083 | } |
| 4084 | |
| 4085 | static void rdp_tritxtrz() |
| 4086 | { |
| 4087 | rdp_triangle(0, 1, 1); |
| 4088 | LRDP("tritxtrz\n"); |
| 4089 | } |
| 4090 | |
| 4091 | static void rdp_trishadetxtrz() |
| 4092 | { |
| 4093 | rdp_triangle(1, 1, 1); |
| 4094 | LRDP("trishadetxtrz\n"); |
| 4095 | } |
| 4096 | |
| 4097 | |
| 4098 | static rdp_instr rdp_command_table[64] = |
| 4099 | { |
| 4100 | /* 0x00 */ |
| 4101 | spnoop, undef, undef, undef, |
| 4102 | undef, undef, undef, undef, |
| 4103 | rdp_trifill, rdp_trifillz, rdp_tritxtr, rdp_tritxtrz, |
| 4104 | rdp_trishade, rdp_trishadez, rdp_trishadetxtr, rdp_trishadetxtrz, |
| 4105 | /* 0x10 */ |
| 4106 | undef, undef, undef, undef, |
| 4107 | undef, undef, undef, undef, |
| 4108 | undef, undef, undef, undef, |
| 4109 | undef, undef, undef, undef, |
| 4110 | /* 0x20 */ |
| 4111 | undef, undef, undef, undef, |
| 4112 | rdp_texrect, rdp_texrect, rdp_loadsync, rdp_pipesync, |
| 4113 | rdp_tilesync, rdp_fullsync, rdp_setkeygb, rdp_setkeyr, |
| 4114 | rdp_setconvert, rdp_setscissor, rdp_setprimdepth, rdp_setothermode, |
| 4115 | /* 0x30 */ |
| 4116 | rdp_loadtlut, undef, rdp_settilesize, rdp_loadblock, |
| 4117 | rdp_loadtile, rdp_settile, rdp_fillrect, rdp_setfillcolor, |
| 4118 | rdp_setfogcolor, rdp_setblendcolor, rdp_setprimcolor, rdp_setenvcolor, |
| 4119 | rdp_setcombine, rdp_settextureimage, rdp_setdepthimage, rdp_setcolorimage |
| 4120 | }; |
| 4121 | |
| 4122 | static const wxUint32 rdp_command_length[64] = |
| 4123 | { |
| 4124 | 8, // 0x00, No Op |
| 4125 | 8, // 0x01, ??? |
| 4126 | 8, // 0x02, ??? |
| 4127 | 8, // 0x03, ??? |
| 4128 | 8, // 0x04, ??? |
| 4129 | 8, // 0x05, ??? |
| 4130 | 8, // 0x06, ??? |
| 4131 | 8, // 0x07, ??? |
| 4132 | 32, // 0x08, Non-Shaded Triangle |
| 4133 | 32+16, // 0x09, Non-Shaded, Z-Buffered Triangle |
| 4134 | 32+64, // 0x0a, Textured Triangle |
| 4135 | 32+64+16, // 0x0b, Textured, Z-Buffered Triangle |
| 4136 | 32+64, // 0x0c, Shaded Triangle |
| 4137 | 32+64+16, // 0x0d, Shaded, Z-Buffered Triangle |
| 4138 | 32+64+64, // 0x0e, Shaded+Textured Triangle |
| 4139 | 32+64+64+16,// 0x0f, Shaded+Textured, Z-Buffered Triangle |
| 4140 | 8, // 0x10, ??? |
| 4141 | 8, // 0x11, ??? |
| 4142 | 8, // 0x12, ??? |
| 4143 | 8, // 0x13, ??? |
| 4144 | 8, // 0x14, ??? |
| 4145 | 8, // 0x15, ??? |
| 4146 | 8, // 0x16, ??? |
| 4147 | 8, // 0x17, ??? |
| 4148 | 8, // 0x18, ??? |
| 4149 | 8, // 0x19, ??? |
| 4150 | 8, // 0x1a, ??? |
| 4151 | 8, // 0x1b, ??? |
| 4152 | 8, // 0x1c, ??? |
| 4153 | 8, // 0x1d, ??? |
| 4154 | 8, // 0x1e, ??? |
| 4155 | 8, // 0x1f, ??? |
| 4156 | 8, // 0x20, ??? |
| 4157 | 8, // 0x21, ??? |
| 4158 | 8, // 0x22, ??? |
| 4159 | 8, // 0x23, ??? |
| 4160 | 16, // 0x24, Texture_Rectangle |
| 4161 | 16, // 0x25, Texture_Rectangle_Flip |
| 4162 | 8, // 0x26, Sync_Load |
| 4163 | 8, // 0x27, Sync_Pipe |
| 4164 | 8, // 0x28, Sync_Tile |
| 4165 | 8, // 0x29, Sync_Full |
| 4166 | 8, // 0x2a, Set_Key_GB |
| 4167 | 8, // 0x2b, Set_Key_R |
| 4168 | 8, // 0x2c, Set_Convert |
| 4169 | 8, // 0x2d, Set_Scissor |
| 4170 | 8, // 0x2e, Set_Prim_Depth |
| 4171 | 8, // 0x2f, Set_Other_Modes |
| 4172 | 8, // 0x30, Load_TLUT |
| 4173 | 8, // 0x31, ??? |
| 4174 | 8, // 0x32, Set_Tile_Size |
| 4175 | 8, // 0x33, Load_Block |
| 4176 | 8, // 0x34, Load_Tile |
| 4177 | 8, // 0x35, Set_Tile |
| 4178 | 8, // 0x36, Fill_Rectangle |
| 4179 | 8, // 0x37, Set_Fill_Color |
| 4180 | 8, // 0x38, Set_Fog_Color |
| 4181 | 8, // 0x39, Set_Blend_Color |
| 4182 | 8, // 0x3a, Set_Prim_Color |
| 4183 | 8, // 0x3b, Set_Env_Color |
| 4184 | 8, // 0x3c, Set_Combine |
| 4185 | 8, // 0x3d, Set_Texture_Image |
| 4186 | 8, // 0x3e, Set_Mask_Image |
| 4187 | 8 // 0x3f, Set_Color_Image |
| 4188 | }; |
| 4189 | |
| 4190 | #define rdram ((wxUint32*)gfx.RDRAM) |
| 4191 | #define rsp_dmem ((wxUint32*)gfx.DMEM) |
| 4192 | |
| 4193 | #define dp_start (*(wxUint32*)gfx.DPC_START_REG) |
| 4194 | #define dp_end (*(wxUint32*)gfx.DPC_END_REG) |
| 4195 | #define dp_current (*(wxUint32*)gfx.DPC_CURRENT_REG) |
| 4196 | #define dp_status (*(wxUint32*)gfx.DPC_STATUS_REG) |
| 4197 | |
| 4198 | inline wxUint32 READ_RDP_DATA(wxUint32 address) |
| 4199 | { |
| 4200 | if (dp_status & 0x1) // XBUS_DMEM_DMA enabled |
| 4201 | return rsp_dmem[(address & 0xfff)>>2]; |
| 4202 | else |
| 4203 | return rdram[address>>2]; |
| 4204 | } |
| 4205 | |
| 4206 | static void rdphalf_1() |
| 4207 | { |
| 4208 | wxUint32 cmd = rdp.cmd1 >> 24; |
| 4209 | if (cmd >= 0xc8 && cmd <=0xcf) //triangle command |
| 4210 | { |
| 4211 | LRDP("rdphalf_1 - lle triangle\n"); |
| 4212 | rdp_cmd_ptr = 0; |
| 4213 | rdp_cmd_cur = 0; |
| 4214 | wxUint32 a; |
| 4215 | |
| 4216 | do |
| 4217 | { |
| 4218 | rdp_cmd_data[rdp_cmd_ptr++] = rdp.cmd1; |
| 4219 | // check DL counter |
| 4220 | if (rdp.dl_count != -1) |
| 4221 | { |
| 4222 | rdp.dl_count --; |
| 4223 | if (rdp.dl_count == 0) |
| 4224 | { |
| 4225 | rdp.dl_count = -1; |
| 4226 | |
| 4227 | LRDP("End of DL\n"); |
| 4228 | rdp.pc_i --; |
| 4229 | } |
| 4230 | } |
| 4231 | |
| 4232 | // Get the address of the next command |
| 4233 | a = rdp.pc[rdp.pc_i] & BMASK; |
| 4234 | |
| 4235 | // Load the next command and its input |
| 4236 | rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit |
| 4237 | rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // / |
| 4238 | |
| 4239 | // Go to the next instruction |
| 4240 | rdp.pc[rdp.pc_i] = (a+8) & BMASK; |
| 4241 | |
| 4242 | }while ((rdp.cmd0 >> 24) != 0xb3); |
| 4243 | rdp_cmd_data[rdp_cmd_ptr++] = rdp.cmd1; |
| 4244 | cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f; |
| 4245 | rdp.cmd0 = rdp_cmd_data[rdp_cmd_cur+0]; |
| 4246 | rdp.cmd1 = rdp_cmd_data[rdp_cmd_cur+1]; |
| 4247 | /* |
| 4248 | wxUint32 cmd3 = ((wxUint32*)gfx.RDRAM)[(a>>2)+2]; |
| 4249 | if ((cmd3>>24) == 0xb4) |
| 4250 | rglSingleTriangle = TRUE; |
| 4251 | else |
| 4252 | rglSingleTriangle = FALSE; |
| 4253 | */ |
| 4254 | rdp_command_table[cmd](); |
| 4255 | } |
| 4256 | else |
| 4257 | { |
| 4258 | LRDP("rdphalf_1 - IGNORED\n"); |
| 4259 | } |
| 4260 | } |
| 4261 | |
| 4262 | static void rdphalf_2() |
| 4263 | { |
| 4264 | RDP_E("rdphalf_2 - IGNORED\n"); |
| 4265 | LRDP("rdphalf_2 - IGNORED\n"); |
| 4266 | } |
| 4267 | |
| 4268 | static void rdphalf_cont() |
| 4269 | { |
| 4270 | RDP_E("rdphalf_cont - IGNORED\n"); |
| 4271 | LRDP("rdphalf_cont - IGNORED\n"); |
| 4272 | } |
| 4273 | |
| 4274 | /****************************************************************** |
| 4275 | Function: ProcessRDPList |
| 4276 | Purpose: This function is called when there is a Dlist to be |
| 4277 | processed. (Low level GFX list) |
| 4278 | input: none |
| 4279 | output: none |
| 4280 | *******************************************************************/ |
| 4281 | #ifdef __cplusplus |
| 4282 | extern "C" { |
| 4283 | #endif |
| 4284 | EXPORT void CALL ProcessRDPList(void) |
| 4285 | { |
| 4286 | LOG ("ProcessRDPList ()\n"); |
| 4287 | LRDP("ProcessRDPList ()\n"); |
| 4288 | |
| 4289 | // SoftLocker lock(mutexProcessDList); |
| 4290 | if (/*!lock.IsOk()*/0) //mutex is busy |
| 4291 | { |
| 4292 | if (!fullscreen) |
| 4293 | drawNoFullscreenMessage(); |
| 4294 | // Set an interrupt to allow the game to continue |
| 4295 | *gfx.MI_INTR_REG |= 0x20; |
| 4296 | gfx.CheckInterrupts(); |
| 4297 | return; |
| 4298 | } |
| 4299 | |
| 4300 | wxUint32 i; |
| 4301 | wxUint32 cmd, length, cmd_length; |
| 4302 | rdp_cmd_ptr = 0; |
| 4303 | rdp_cmd_cur = 0; |
| 4304 | |
| 4305 | if (dp_end <= dp_current) return; |
| 4306 | length = dp_end - dp_current; |
| 4307 | |
| 4308 | // load command data |
| 4309 | for (i=0; i < length; i += 4) |
| 4310 | { |
| 4311 | rdp_cmd_data[rdp_cmd_ptr++] = READ_RDP_DATA(dp_current + i); |
| 4312 | if (rdp_cmd_ptr >= 0x1000) |
| 4313 | { |
| 4314 | FRDP("rdp_process_list: rdp_cmd_ptr overflow %x %x --> %x\n", length, dp_current, dp_end); |
| 4315 | } |
| 4316 | } |
| 4317 | |
| 4318 | dp_current = dp_end; |
| 4319 | |
| 4320 | cmd = (rdp_cmd_data[0] >> 24) & 0x3f; |
| 4321 | cmd_length = (rdp_cmd_ptr + 1) * 4; |
| 4322 | |
| 4323 | // check if more data is needed |
| 4324 | if (cmd_length < rdp_command_length[cmd]) |
| 4325 | return; |
| 4326 | rdp.LLE = TRUE; |
| 4327 | while (rdp_cmd_cur < rdp_cmd_ptr) |
| 4328 | { |
| 4329 | cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f; |
| 4330 | |
| 4331 | if (((rdp_cmd_ptr-rdp_cmd_cur) * 4) < rdp_command_length[cmd]) |
| 4332 | return; |
| 4333 | |
| 4334 | // execute the command |
| 4335 | rdp.cmd0 = rdp_cmd_data[rdp_cmd_cur+0]; |
| 4336 | rdp.cmd1 = rdp_cmd_data[rdp_cmd_cur+1]; |
| 4337 | rdp.cmd2 = rdp_cmd_data[rdp_cmd_cur+2]; |
| 4338 | rdp.cmd3 = rdp_cmd_data[rdp_cmd_cur+3]; |
| 4339 | rdp_command_table[cmd](); |
| 4340 | |
| 4341 | rdp_cmd_cur += rdp_command_length[cmd] / 4; |
| 4342 | }; |
| 4343 | rdp.LLE = FALSE; |
| 4344 | |
| 4345 | dp_start = dp_end; |
| 4346 | |
| 4347 | dp_status &= ~0x0002; |
| 4348 | |
| 4349 | //} |
| 4350 | } |
| 4351 | |
| 4352 | #ifdef __cplusplus |
| 4353 | } |
| 4354 | #endif |
| 4355 | |