2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002 Dave2001
4 * Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski
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
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.
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
21 //****************************************************************
23 // Glide64 - Glide Plugin for Nintendo 64 emulators
24 // Project started on December 29th, 2001
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
32 //****************************************************************
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.
38 //****************************************************************
50 #include "TexBuffer.h"
51 #include "FBtoScreen.h"
55 #include "FrameSkipper.h"
56 extern FrameSkipper frameSkipper;
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} };
72 const char *ACmp[] = { "NONE", "THRESHOLD", "UNKNOWN", "DITHER" };
74 const char *Mode0[] = { "COMBINED", "TEXEL0",
75 "TEXEL1", "PRIMITIVE",
76 "SHADE", "ENVIORNMENT",
83 const char *Mode1[] = { "COMBINED", "TEXEL0",
84 "TEXEL1", "PRIMITIVE",
85 "SHADE", "ENVIORNMENT",
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",
109 const char *Mode3[] = { "COMBINED", "TEXEL0",
110 "TEXEL1", "PRIMITIVE",
111 "SHADE", "ENVIORNMENT",
114 const char *Alpha0[] = { "COMBINED", "TEXEL0",
115 "TEXEL1", "PRIMITIVE",
116 "SHADE", "ENVIORNMENT",
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
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" };
131 const char *str_zs[] = { "G_ZS_PIXEL", "G_ZS_PRIM" };
133 const char *str_yn[] = { "NO", "YES" };
134 const char *str_offon[] = { "OFF", "ON" };
136 const char *str_cull[] = { "DISABLE", "FRONT", "BACK", "BOTH" };
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" };
145 const char *str_filter[] = { "Point Sampled", "Average (box)", "Bilinear" };
147 const char *str_tlut[] = { "TT_NONE", "TT_UNKNOWN", "TT_RGBA_16", "TT_IA_16" };
149 const char *str_dither[] = { "Pattern", "~Pattern", "Noise", "None" };
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" };
159 wxUint32 frame_count; // frame counter
161 int ucode_error_report = TRUE;
164 // ** RDP graphics functions **
166 static void spnoop();
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();
208 static void rsp_reserved0();
209 static void rsp_reserved1();
210 static void rsp_reserved2();
211 static void rsp_reserved3();
213 static void ys_memrect();
215 wxUint8 microcode[4096];
220 #define Check_FrameSkip if (frameSkipper.willSkipNext()) return
222 #define Check_FrameSkip {}
225 // ** UCODE FUNCTIONS **
237 #include "ucode09rdp.h"
240 static int reset = 0;
241 static int old_ucode = -1;
245 memset(this, 0, sizeof(RDP_Base));
246 // set all vertex numbers
247 for (int i=0; i<MAX_VTX; i++)
252 scissor_o.lr_x = 320;
253 scissor_o.lr_y = 240;
255 vi_org_reg = *gfx.VI_ORIGIN_REG;
256 view_scale[2] = 32.0f * 511.0f;
257 view_trans[2] = 32.0f * 511.0f;
260 lookat[0][0] = lookat[1][1] = 1.0f;
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;
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;
272 CheckKeyPressed(G64_VK_BACK, 1); //BACK
273 CheckKeyPressed(G64_VK_B, 1);
274 CheckKeyPressed(G64_VK_V, 1);
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;
286 for (int i = 0; i < MAX_TMU; i++)
288 cache[i] = new CACHE_LUT[MAX_CACHE];
293 vtx = new VERTEX[MAX_VTX];
294 memset(vtx, 0, sizeof(VERTEX)*MAX_VTX);
297 frame_buffers = new COLOR_IMAGE[NUMTEXBUF+2];
304 for (int i = 0; i < MAX_TMU; i++)
308 delete[] frame_buffers;
322 // Check first 3k of ucode, because the last 1k sometimes contains trash
323 for (i=0; i<3072>>2; i++)
325 uc_crc += ((wxUint32*)microcode)[i];
328 FRDP_E ("crc: %08lx\n", uc_crc);
332 ucf.open ("ucode.txt", std::ios::out | std::ios::binary);
334 for (i=0; i<0x400000; i++)
336 d = ((char*)gfx.RDRAM)[i^3];
342 FRDP("ucode = %08lx\n", uc_crc);
344 Ini * ini = Ini::OpenIni();
345 ini->SetPath("UCODE");
347 sprintf (str, "%08lx", (unsigned long)uc_crc);
348 int uc = ini->Read(str, -2);
350 if (uc == -2 && ucode_error_report)
352 settings.ucode = Config_ReadInt("ucode", "Force microcode", 0, TRUE, FALSE);
355 ERRLOG("Error: uCode crc not found in INI, using currently selected uCode\n\n%08lx", (unsigned long)uc_crc);
357 ucode_error_report = FALSE; // don't report any more ucode errors from this game
359 else if (uc == -1 && ucode_error_report)
361 settings.ucode = ini->Read(_T("/SETTINGS/ucode"), 0);
364 ERRLOG("Error: Unsupported uCode!\n\ncrc: %08lx", (unsigned long)uc_crc);
366 ucode_error_report = FALSE; // don't report any more ucode errors from this game
370 old_ucode = settings.ucode;
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
376 rdp.persp_supported = FALSE;
378 else if (settings.texture_correction)
379 rdp.persp_supported = TRUE;
384 static void GetClientSize(int * width, int * height)
388 GetClientRect (gfx.hWnd, &win_rect);
389 *width = win_rect.right;
390 *height = win_rect.bottom;
392 GFXWindow->GetClientSize(width, height);
397 void drawNoFullscreenMessage()
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
404 LOG ("drawNoFullscreenMessage ()\n");
405 if (rdp.window_changed)
407 rdp.window_changed = FALSE;
409 GetClientSize(&width, &height);
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);
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);
424 text = wxT("Gfx cannot be drawn in windowed mode");
425 dc.GetTextExtent(text, &w, &h);
428 dc.DrawText(text, x, y);
430 text = wxT("Press Alt+Enter to switch to fullscreen");
431 dc.GetTextExtent(text, &w, &h);
433 y = (height - h)/2 + h*2;
434 dc.DrawText(text, x, y);
439 static wxUint32 d_ul_x, d_ul_y, d_lr_x, d_lr_y;
441 static void DrawPartFrameBufferToScreen()
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;
453 DrawFrameBufferToScreen(fb_info);
454 memset(gfx.RDRAM+rdp.cimg, 0, (rdp.ci_width*rdp.ci_height)<<rdp.ci_size>>1);
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)
463 static void CopyFrameBuffer (GrBuffer_t buffer = GR_BUFFER_BACKBUFFER)
467 FRDP ("CopyFrameBuffer: %08lx... ", rdp.cimg);
469 // don't bother to write the stuff in asm... the slow part is the read from video card,
472 wxUint32 width = rdp.ci_width;//*gfx.VI_WIDTH_REG;
474 if (fb_emulation_enabled && !(settings.hacks&hack_PPL))
476 int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0;
477 height = rdp.frame_buffers[ind].height;
481 height = rdp.ci_lower_bound;
482 if (settings.hacks&hack_PPL)
483 height -= rdp.ci_upper_bound;
485 FRDP ("width: %d, height: %d... ", width, height);
486 //printf("CopyFrameBuffer width: %d, height: %d... ", width, height);
488 if (rdp.scale_x < 1.1f)
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,
499 wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg);
500 wxUint32 *ptr_dst32 = (wxUint32*)(gfx.RDRAM+rdp.cimg);
503 for (wxUint32 y=0; y<height; y++)
505 for (wxUint32 x=0; x<width; x++)
507 c = ptr_src[x + y * width];
508 if (settings.frame_buffer&fb_read_alpha)
511 c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;
515 c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;
517 if (rdp.ci_size == 2)
518 ptr_dst[(x + y * width)^1] = c;
520 ptr_dst32[x + y * width] = RGBA16TO32(c);
523 LRDP("ReadRegion. Framebuffer copy complete.\n");
527 LRDP("Framebuffer copy failed.\n");
533 if (rdp.motionblur && fb_hwfbe_enabled)
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);
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);
545 info.size = sizeof(GrLfbInfo_t);
547 if (grLfbLock (GR_LFB_READ_ONLY,
550 GR_ORIGIN_UPPER_LEFT,
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);
558 wxUint32 stride = info.strideInBytes>>1;
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)
563 int x_start = 0, y_start = 0, x_end = width, y_end = height;
564 if (settings.hacks&hack_BAR)
566 x_start = 80, y_start = 24, x_end = 240, y_end = 86;
568 for (int y=y_start; y<y_end; y++)
570 for (int x=x_start; x<x_end; x++)
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)
576 if (rdp.ci_size <= 2)
577 ptr_dst[(x + y * width)^1] = c;
579 ptr_dst32[x + y * width] = RGBA16TO32(c);
583 // Unlock the backbuffer
584 grLfbUnlock (GR_LFB_READ_ONLY, buffer);
585 LRDP("LfbLock. Framebuffer copy complete.\n");
589 LRDP("Framebuffer copy failed.\n");
595 void GoToFullScreen()
607 // lock the mutex in the ctor
608 SoftLocker(SDL_sem *mutex)
609 : _isOk(false), _mutex(mutex)
610 { _isOk = ( SDL_SemTryWait(_mutex) == 0 ); }
612 // returns true if mutex was successfully locked in ctor
616 // unlock the mutex in dtor
618 { if ( IsOk() ) SDL_SemPost(_mutex); }
626 /******************************************************************
627 Function: ProcessDList
628 Purpose: This function is called when there is a Dlist to be
629 processed. (High level GFX list)
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;
641 wxUint32 ucode5_texshiftaddr = 0;
642 wxUint32 ucode5_texshiftcount = 0;
643 wxUint16 ucode5_texshift = 0;
644 int depth_buffer_fog;
651 EXPORT void CALL ProcessDList(void)
653 // SoftLocker lock(mutexProcessDList);
655 //printf("ProcessDList()\n");
656 // frameSkipper.newFrame();
658 // if (frameSkipper.willSkipNext())
660 if (/*!lock.IsOk()*/0) //mutex is busy
663 // printf("Frameskip, reason=%s\n", (lock.IsOk())?"lock":"frameskip");
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;
678 update_screen_count = 0;
682 if (!hhkLowLevelKybd)
684 hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL,
685 LowLevelKeyboardProc, NULL, 0);
689 VLOG ("ProcessDList ()\n");
693 drawNoFullscreenMessage();
694 // Set an interrupt to allow the game to continue
695 *gfx.MI_INTR_REG |= 0x20;
696 gfx.CheckInterrupts();
702 if (settings.autodetect_ucode)
704 // Thanks to ZeZu for ucode autodetection!!!
705 wxUint32 startUcode = *(wxUint32*)(gfx.DMEM+0xFD0);
706 memcpy (microcode, gfx.RDRAM+startUcode, 4096);
710 memset (microcode, 0, 4096);
712 else if ( ((old_ucode == ucode_S2DEX) && (settings.ucode == ucode_F3DEX)) || settings.force_microcheck)
714 wxUint32 startUcode = *(wxUint32*)(gfx.DMEM+0xFD0);
715 memcpy (microcode, gfx.RDRAM+startUcode, 4096);
722 // Switch to fullscreen?
726 if (!fullscreen && !settings.run_in_window)
729 // Clear out the RDP log
731 if (settings.logging && settings.log_clear)
739 if (settings.log_unk && settings.unk_clear)
742 unimp.open("unimp.txt");
748 if (settings.swapmode > 0)
750 rdp.updatescreen = 1;
752 rdp.tri_n = 0; // 0 triangles so far this frame
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;
761 rdp.fb_drawn = rdp.fb_drawn_front = FALSE;
762 rdp.update = 0x7FFFFFFF; // All but clear cache
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;
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;
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)
791 //* End of set states *//
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);
799 if (cpu_fb_write == TRUE)
800 DrawPartFrameBufferToScreen();
801 if ((settings.hacks&hack_Tonic) && dlist_length < 16)
804 FRDP_E("DLIST is too short!\n");
808 // Start executing at the start of the display list
810 rdp.pc[rdp.pc_i] = dlist_start;
816 // catches exceptions so that it doesn't freeze
817 #ifdef CATCH_EXCEPTIONS
820 if (settings.ucode == ucode_Turbo3d)
826 // MAIN PROCESSING LOOP
829 // Get the address of the next command
830 a = rdp.pc[rdp.pc_i] & BMASK;
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
837 // Output the address before the command
839 FRDP ("%08lx (c0:%08lx, c1:%08lx): ", a, rdp.cmd0, rdp.cmd1);
844 // Go to the next instruction
845 rdp.pc[rdp.pc_i] = (a+8) & BMASK;
848 perf_cur = ticksGetTicks();
850 // Process this instruction
851 gfx_instruction[settings.ucode][rdp.cmd0>>24] ();
854 if (rdp.dl_count != -1)
857 if (rdp.dl_count == 0)
867 perf_next = ticksGetTicks();
868 sprintf (out_buf, "perf %08x: %lli\n", a-8, (perf_next-perf_cur));
878 #ifdef CATCH_EXCEPTIONS
885 #ifdef TEXTURE_FILTER
886 if (settings.ghq_use)
889 settings.ghq_use = 0;
893 ERRLOG("The GFX plugin caused an exception and has been disabled.");
899 if (fb_emulation_enabled)
901 rdp.scale_x = rdp.scale_x_bak;
902 rdp.scale_y = rdp.scale_y_bak;
905 if (!frameSkipper.willSkipNext())
907 if (settings.frame_buffer & fb_ref)
910 CloseTextureBuffer(rdp.read_whole_frame && ((settings.hacks&hack_PMario) || rdp.swap_ci_index >= 0));
912 if ((settings.hacks&hack_TGR2) && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET)
917 LRDP("ProcessDList end\n");
924 // undef - undefined instruction, always ignore
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();
936 // spnoop - no operation, always ignore
942 // noop - no operation, always ignore
943 static void rdp_noop()
948 static void ys_memrect ()
950 wxUint32 tile = (wxUint16)((rdp.cmd1 & 0x07000000) >> 24);
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);
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;
962 FRDP ("memrect (%d, %d, %d, %d), ci_width: %d", ul_x, ul_y, lr_x, lr_y, rdp.ci_width);
964 FRDP (" off_x: %d", off_x);
966 FRDP (" off_y: %d", off_y);
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;
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);
981 static void pm_palette_mod ()
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++)
994 dst[i^1] = (rdp.pal_8[i]&1) ? prim16 : env16;
996 LRDP("Texrect palette modification\n");
999 static void pd_zcopy ()
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;
1008 for (wxUint16 x=0; x<width; 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);
1017 static void DrawDepthBufferFog()
1019 if (rdp.zi_width < 200)
1021 FB_TO_SCREEN_INFO fb_info;
1022 fb_info.addr = rdp.zimg;
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;
1031 DrawDepthBufferToScreen(fb_info);
1034 static void rdp_texrect()
1038 wxUint32 a = rdp.pc[rdp.pc_i];
1039 wxUint8 cmdHalf1 = gfx.RDRAM[a+3];
1040 wxUint8 cmdHalf2 = gfx.RDRAM[a+11];
1042 if ((cmdHalf1 == 0xE1 && cmdHalf2 == 0xF1) || (cmdHalf1 == 0xB4 && cmdHalf2 == 0xB3) || (cmdHalf1 == 0xB3 && cmdHalf2 == 0xB2))
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;
1051 //gDPTextureRectangle
1052 if (settings.hacks&hack_ASB)
1055 rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a+0];
1056 rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a+1];
1057 rdp.pc[rdp.pc_i] += 8;
1060 if ((settings.hacks&hack_Yoshi) && settings.ucode == ucode_S2DEX)
1066 if (rdp.skip_drawing || (!fb_emulation_enabled && (rdp.cimg == rdp.zimg)))
1068 if ((settings.hacks&hack_PMario) && rdp.ci_status == ci_useless)
1074 LRDP("Texrect skipped\n");
1079 if ((settings.ucode == ucode_CBFD) && rdp.cur_image && rdp.cur_image->format)
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");
1087 if ((settings.ucode == ucode_PerfectDark) && (rdp.frame_buffers[rdp.ci_count-1].status == ci_zcopy))
1090 LRDP("Depth buffer copied.\n");
1095 if ((rdp.othermode_l >> 16) == 0x3c18 && rdp.cycle1 == 0x03ffffff && rdp.cycle2 == 0x01ff1fff) //depth image based fog
1097 if (!depth_buffer_fog)
1100 DrawDepthBufferFog();
1101 depth_buffer_fog = FALSE;
1105 // FRDP ("rdp.cycle1 %08lx, rdp.cycle2 %08lx\n", rdp.cycle1, rdp.cycle2);
1107 float ul_x, ul_y, lr_x, lr_y;
1108 if (rdp.cycle_mode == 2)
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));
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);
1125 FRDP("Wrong Texrect: ul_x: %f, lr_x: %f\n", ul_x, lr_x);
1129 if (rdp.cycle_mode > 1)
1133 } else if (lr_y - ul_y < 1.0f)
1136 if (settings.increase_texrect_edge)
1138 if (floor(lr_x) != lr_x)
1140 if (floor(lr_y) != lr_y)
1145 if (rdp.tbuff_tex && (settings.frame_buffer & fb_optimize_texrect))
1147 LRDP("Attempt to optimize texrect\n");
1148 if (!rdp.tbuff_tex->drawn)
1152 d.imageW = (wxUint16)rdp.tbuff_tex->width;
1153 d.frameX = (wxUint16)ul_x;
1154 d.frameW = (wxUint16)(rdp.tbuff_tex->width);
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);
1163 DrawHiresImage(d, rdp.tbuff_tex->width == rdp.ci_width);
1164 rdp.tbuff_tex->drawn = TRUE;
1169 // framebuffer workaround for Zelda: MM LOT
1170 if ((rdp.othermode_l & 0xFFFF0000) == 0x0f5a0000)
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)
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);
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)
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)))
1193 if (fb_emulation_enabled)
1194 if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self)
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");
1206 wxUint32 tile = (wxUint16)((rdp.cmd1 & 0x07000000) >> 24);
1210 wxUint32 prev_tile = rdp.cur_tile;
1211 rdp.cur_tile = tile;
1213 const float Z = set_sprite_combine_mode ();
1217 if (!rdp.cur_cache[0])
1219 rdp.cur_tile = prev_tile;
1224 // ** Texrect offset by Gugaman **
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)
1238 if (rdp.cycle_mode == 2)
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;
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);
1253 if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip
1255 #ifdef TEXTURE_FILTER
1256 if (rdp.cur_cache[0]->is_hires_tex)
1258 off_size_x = (float)((lr_y - ul_y) * dsdx);
1259 off_size_y = (float)((lr_x - ul_x) * dtdy);
1264 off_size_x = (lr_y - ul_y - 1) * dsdx;
1265 off_size_y = (lr_x - ul_x - 1) * dtdy;
1270 #ifdef TEXTURE_FILTER
1271 if (rdp.cur_cache[0]->is_hires_tex)
1273 off_size_x = (float)((lr_x - ul_x) * dsdx);
1274 off_size_y = (float)((lr_y - ul_y) * dtdy);
1279 off_size_x = (lr_x - ul_x - 1) * dsdx;
1280 off_size_y = (lr_y - ul_y - 1) * dtdy;
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))
1290 //calculate texture coordinates
1291 for (int i = 0; i < 2; i++)
1293 if (rdp.cur_cache[i] && (rdp.tex & (i+1)))
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];
1301 if (tile.shift_s > 10)
1303 wxUint8 iShift = (16 - tile.shift_s);
1305 sx = (float)(1 << iShift);
1309 wxUint8 iShift = tile.shift_s;
1311 sx = 1.0f/(float)(1 << iShift);
1316 if (tile.shift_t > 10)
1318 wxUint8 iShift = (16 - tile.shift_t);
1320 sy = (float)(1 << iShift);
1324 wxUint8 iShift = tile.shift_t;
1326 sy = 1.0f/(float)(1 << iShift);
1330 if (rdp.aTBuffTex[i]) //hwfbe texture
1334 if (off_x_i + off_y_i == 0)
1336 t0_off_x = tile.ul_s;
1337 t0_off_y = tile.ul_t;
1341 t0_off_x = off_x_i/32.0f;
1342 t0_off_y = off_y_i/32.0f;
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;
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;
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);
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;
1365 texUV[i].ul_u -= tile.f_ul_s;
1366 texUV[i].ul_v -= tile.f_ul_t;
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;
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;
1379 texUV[i].ul_u = texUV[i].ul_v = texUV[i].lr_u = texUV[i].lr_v = 0;
1382 rdp.cur_tile = prev_tile;
1386 FRDP (" scissor: (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);
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);
1391 FRDP (" draw at: (%f, %f) -> (%f, %f)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y);
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 } };
1399 if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip
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;
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;
1412 VERTEX *vptr = vstd;
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);
1420 if (!rdp.aTBuffTex[0] && rdp.cur_cache[0]->splits != 1)
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)
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);
1445 int splitheight = rdp.cur_cache[0]->splitheight;
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];
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;
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;
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
1477 for (i=start_u_256; i<end_u_256; i++)
1479 // Find where x = current 256 multiple
1480 float x = m * ((i<<8)+256) + b;
1482 int vn = 2 + ((i-start_u_256)<<2);
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;
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;
1499 vnew[vn] = vnew[vn-2];
1501 vnew[vn].v0 += (float)splitheight;
1503 vnew[vn].v1 += (float)splitheight;
1506 vnew[vn] = vnew[vn-2];
1508 vnew[vn].v0 += (float)splitheight;
1510 vnew[vn].v1 += (float)splitheight;
1513 if (n_vertices > 12)
1515 float texbound = (float)(splitheight << 1);
1516 for (int k = 0; k < n_vertices; k ++)
1518 if (vnew[k].v0 > texbound)
1519 vnew[k].v0 = (float)fmod(vnew[k].v0, texbound);
1525 AllowShadeMods (vptr, n_vertices);
1526 for (i=0; i<n_vertices; i++)
1528 apply_shade_mods (&vptr[i]);
1533 if (rdp.fog_mode >= RDP::fog_blend)
1536 if (rdp.fog_mode == RDP::fog_blend)
1537 fog = 1.0f/max(1, rdp.fog_color&0xFF);
1539 fog = 1.0f/max(1, (~rdp.fog_color)&0xFF);
1540 for (i = 0; i < n_vertices; i++)
1544 grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
1547 ConvertCoordsConvert (vptr, n_vertices);
1549 if (settings.wireframe)
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]);
1560 grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, n_vertices, vptr, sizeof(VERTEX));
1563 if (_debugger.capture)
1569 add_tri (vl, 3, TRI_TEXRECT);
1574 add_tri (vl, 3, TRI_TEXRECT);
1588 static void rdp_loadsync()
1590 LRDP("loadsync - ignored\n");
1593 static void rdp_pipesync()
1595 LRDP("pipesync - ignored\n");
1598 static void rdp_tilesync()
1600 LRDP("tilesync - ignored\n");
1603 static void rdp_fullsync()
1605 // Set an interrupt to allow the game to continue
1606 *gfx.MI_INTR_REG |= 0x20;
1607 gfx.CheckInterrupts();
1611 static void rdp_setkeygb()
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);
1622 static void rdp_setkeyr()
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);
1631 static void rdp_setconvert()
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 ;
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);
1647 // setscissor - sets the screen clipping rectangle
1650 static void rdp_setscissor()
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)*/;
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;
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);
1665 rdp.update |= UPDATE_SCISSOR;
1667 if (rdp.view_scale[0] == 0) //viewport is not set?
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;
1677 static void rdp_setprimdepth()
1679 rdp.prim_depth = (wxUint16)((rdp.cmd1 >> 16) & 0x7FFF);
1680 rdp.prim_dz = (wxUint16)(rdp.cmd1 & 0x7FFF);
1682 FRDP("setprimdepth: %d\n", rdp.prim_depth);
1685 static void rdp_setothermode()
1687 #define F3DEX2_SETOTHERMODE(cmd,sft,len,data) { \
1688 rdp.cmd0 = (cmd<<24) | ((32-(sft)-(len))<<8) | (((len)-1)); \
1690 gfx_instruction[settings.ucode][cmd] (); \
1692 #define SETOTHERMODE(cmd,sft,len,data) { \
1693 rdp.cmd0 = (cmd<<24) | ((sft)<<8) | (len); \
1695 gfx_instruction[settings.ucode][cmd] (); \
1698 LRDP("rdp_setothermode\n");
1700 if ((settings.ucode == ucode_F3DEX2) || (settings.ucode == ucode_CBFD))
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
1708 int cmd0 = rdp.cmd0;
1709 SETOTHERMODE(0xB9, 0, 32, rdp.cmd1); // SETOTHERMODE_L
1710 SETOTHERMODE(0xBA, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H
1714 void load_palette (wxUint32 addr, wxUint16 start, wxUint16 count)
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));
1723 for (wxUint16 i=start; i<end; i++)
1725 *(dpal++) = *(wxUint16 *)(gfx.RDRAM + (addr^2));
1729 FRDP ("%d: %08lx\n", i, *(wxUint16 *)(gfx.RDRAM + (addr^2)));
1732 #ifdef TEXTURE_FILTER
1733 if (settings.ghq_hirs)
1734 memcpy((wxUint8*)(rdp.pal_8_rice+start), spal, count<<1);
1737 end = start + (count >> 4);
1738 if (end == start) // it can be if count < 16
1740 for (wxUint16 p = start; p < end; p++)
1742 rdp.pal_8_crc[p] = CRC32( 0xFFFFFFFF, &rdp.pal_8[(p << 4)], 32 );
1744 rdp.pal_256_crc = CRC32( 0xFFFFFFFF, rdp.pal_8_crc, 64 );
1748 static void rdp_loadtlut()
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
1755 if (rdp.timg.addr + (count<<1) > BMASK)
1756 count = (wxUint16)((BMASK - rdp.timg.addr) >> 1);
1758 if (start+count > 256) count = 256-start;
1760 FRDP("loadtlut: tile: %d, start: %d, count: %d, from: %08lx\n", tile, start, count,
1763 load_palette (rdp.timg.addr, start, count);
1765 rdp.timg.addr += count << 1;
1767 if (rdp.tbuff_tex) //paranoid check.
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++)
1773 for (int j = 0; j < rdp.texbufs[i].count; j++)
1775 if (&(rdp.texbufs[i].images[j]) == rdp.tbuff_tex)
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));
1788 static void rdp_settilesize()
1790 wxUint32 tile = (rdp.cmd1 >> 24) & 0x07;
1791 rdp.last_tile_size = tile;
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;
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);
1801 if (lr_s == 0 && ul_s == 0) //pokemon puzzle league set such tile size
1803 else if (wrong_tile == (int)tile)
1806 if (settings.use_sts1_only)
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)
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;
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;
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;
1835 rdp.update |= UPDATE_TEXTURE;
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);
1843 void setTBufTex(wxUint16 t_mem, wxUint32 cnt)
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++)
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);
1853 FRDP("rdp.aTBuffTex[%d]=0\n", i);
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))
1859 rdp.aTBuffTex[i] = pTbufTex;
1860 rdp.aTBuffTex[i]->t_mem = t_mem;
1862 FRDP("rdp.aTBuffTex[%d] tmu=%d t_mem=%d\n", i, rdp.aTBuffTex[i]->tmu, rdp.aTBuffTex[i]->t_mem);
1866 rdp.aTBuffTex[i] = 0;
1867 FRDP("rdp.aTBuffTex[%d]=0\n", i);
1873 static inline void loadBlock(uint32_t *src, uint32_t *dst, uint32_t off, int dxt, int cnt)
1897 v7 = (uint32_t *)((char *)src + (off & 0xFFFFFFFC));
1906 v10 = __ROL__(v10, 8);
1912 v10 = __ROL__(v10, 8);
1913 *(uint8_t *)v5 = v10;
1914 v5 = (uint32_t *)((char *)v5 + 1);
1929 v5[1] = bswap32(v7[1]);
1939 v14 = *(uint32_t *)((char *)src + ((8 * cnt + off) & 0xFFFFFFFC));
1942 v14 = __ROL__(v14, 8);
1943 *(uint8_t *)v5 = v14;
1944 v5 = (uint32_t *)((char *)v5 + 1);
1973 for ( i = v15; v18; --v18 )
1997 void LoadBlock32b(wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 lr_s, wxUint32 dxt);
1998 static void rdp_loadblock()
2000 if (rdp.skip_drawing)
2002 LRDP("loadblock skipped\n");
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)
2010 if (ucode5_texshift % ((lr_s+1)<<3))
2012 rdp.timg.addr -= ucode5_texshift;
2013 ucode5_texshiftaddr = 0;
2014 ucode5_texshift = 0;
2015 ucode5_texshiftcount = 0;
2018 ucode5_texshiftcount++;
2021 rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr;
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;*/
2027 // 0x00000800 -> 0x80000000 (so we can check the sign bit instead of the 11th bit)
2028 wxUint32 _dxt = dxt << 20;
2030 wxUint32 addr = segoffset(rdp.timg.addr) & BMASK;
2032 // lr_s specifies number of 64-bit words to copy
2034 wxUint16 ul_s = (wxUint16)(rdp.cmd0 >> 14) & 0x3FF;
2035 wxUint16 ul_t = (wxUint16)(rdp.cmd0 >> 2) & 0x3FF;
2037 rdp.tiles[tile].ul_s = ul_s;
2038 rdp.tiles[tile].ul_t = ul_t;
2039 rdp.tiles[tile].lr_s = lr_s;
2041 rdp.timg.set_by = 0; // load block
2043 #ifdef TEXTURE_FILTER
2044 LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[tile].t_mem];
2045 info.tile_width = lr_s;
2049 // do a quick boundary check before copying to eliminate the possibility for exception
2051 lr_s = 1; // 1 so that it doesn't die on memcpy
2054 if (ul_s+lr_s > 512)
2057 if (addr+(lr_s<<3) > BMASK+1)
2058 lr_s = (wxUint16)((BMASK-addr)>>3);
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)
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);
2073 if (rdp.timg.size == 3)
2074 LoadBlock32b(tile, ul_s, ul_t, lr_s, dxt);
2076 loadBlock((uint32_t *)gfx.RDRAM, (uint32_t *)dst, off, _dxt, cnt);
2078 rdp.timg.addr += cnt << 3;
2079 rdp.tiles[tile].lr_t = ul_t + ((dxt*cnt)>>11);
2081 rdp.update |= UPDATE_TEXTURE;
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,
2087 if (fb_hwfbe_enabled)
2088 setTBufTex(rdp.tiles[tile].t_mem, cnt);
2092 static inline void loadTile(uint32_t *src, uint32_t *dst, int width, int height, int line, int off, uint32_t *end)
2141 v13 = (uint32_t *)((char *)v9 + (v10 & 0xFFFFFFFC));
2150 v16 = __ROL__(v16, 8);
2156 v16 = __ROL__(v16, 8);
2157 *(uint8_t *)v7 = v16;
2158 v7 = (uint32_t *)((char *)v7 + 1);
2172 *v7 = bswap32(*v13);
2173 v7[1] = bswap32(v13[1]);
2183 v20 = *(uint32_t *)((char *)v24 + ((8 * v25 + v23) & 0xFFFFFFFC));
2186 v20 = __ROL__(v20, 8);
2187 *(uint8_t *)v7 = v20;
2188 v7 = (uint32_t *)((char *)v7 + 1);
2222 void LoadTile32b (wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 width, wxUint32 height);
2223 static void rdp_loadtile()
2225 if (rdp.skip_drawing)
2227 LRDP("loadtile skipped\n");
2230 rdp.timg.set_by = 1; // load tile
2232 wxUint32 tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07);
2234 rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr;
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);
2241 if (lr_s < ul_s || lr_t < ul_t) return;
2243 if (wrong_tile >= 0) //there was a tile with zero length
2245 rdp.tiles[wrong_tile].lr_s = lr_s;
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;
2256 if (rdp.tbuff_tex)// && (rdp.tiles[tile].format == 0))
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;
2263 if ((settings.hacks&hack_Tonic) && tile == 7)
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;
2271 wxUint32 height = lr_t - ul_t + 1; // get height
2272 wxUint32 width = lr_s - ul_s + 1;
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)
2283 if (info.tile_height%2)
2286 info.tex_width = rdp.timg.width;
2287 info.tex_size = rdp.timg.size;
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;
2297 if (rdp.timg.size == 3)
2299 LoadTile32b(tile, ul_s, ul_t, width, height);
2303 // check if points to bad location
2304 if (offs + line_n*height > BMASK)
2305 height = (BMASK - offs) / line_n;
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);
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);
2317 if (fb_hwfbe_enabled)
2318 setTBufTex(rdp.tiles[tile].t_mem, rdp.tiles[tile].line*height);
2321 static void rdp_settile()
2323 tile_set = 1; // used to check if we only load the first settilesize
2327 rdp.last_tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07);
2328 TILE *tile = &rdp.tiles[rdp.last_tile];
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);
2344 rdp.update |= UPDATE_TEXTURE;
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);
2353 if (fb_hwfbe_enabled && rdp.last_tile < rdp.cur_tile + 2)
2355 for (int i = 0; i < 2; i++)
2357 if (rdp.aTBuffTex[i])
2359 if (rdp.aTBuffTex[i]->t_mem == tile->t_mem)
2361 if (rdp.aTBuffTex[i]->size == tile->size)
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");
2368 rdp.aTBuffTex[i] = 0;
2371 else if (rdp.aTBuffTex[i]->tile == rdp.last_tile) //wrong! t_mem must be the same
2372 rdp.aTBuffTex[i] = 0;
2379 // fillrect - fills a rectangle
2382 static void rdp_fillrect()
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))
2390 LRDP("Fillrect. Wrong coordinates. Skipped\n");
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)
2396 LRDP("Fillrect - cleared the depth buffer\n");
2399 if (!(settings.hacks&hack_Hyperbike) || rdp.ci_width > 64) //do not clear main depth buffer for aux depth buffers
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;
2408 //if (settings.frame_buffer&fb_depth_clear)
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;
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++)
2421 for (wxUint32 x = ul_x; x < lr_x; x++)
2423 dst[x] = rdp.fill_color;
2425 dst += zi_width_in_dwords;
2432 if (rdp.skip_drawing)
2434 LRDP("Fillrect skipped\n");
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))
2440 wxUint32 color = rdp.fill_color;
2441 if (rdp.ci_size < 3)
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);
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");
2460 if (settings.decrease_fillrect_edge && rdp.cycle_mode == 0)
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);
2467 FRDP("scissor (%d,%d) -> (%d,%d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x,
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);
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;
2481 FRDP (" - %d, %d, %d, %d\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y);
2485 grFogMode (GR_FOG_DISABLE);
2487 const float Z = (rdp.cycle_mode == 3) ? 0.0f : set_sprite_combine_mode();
2489 // Draw the rectangle
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} };
2496 if (rdp.cycle_mode == 3)
2498 wxUint32 color = rdp.fill_color;
2500 if ((settings.hacks&hack_PMario) && rdp.frame_buffers[rdp.ci_count-1].status == ci_aux)
2502 //background of auxiliary frame buffers must have zero alpha.
2503 //make it black, set 0 alpha to plack pixels on frame buffer read
2506 else if (rdp.ci_size < 3)
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);
2514 grConstantColorValue (color);
2516 grColorCombine (GR_COMBINE_FUNCTION_LOCAL,
2517 GR_COMBINE_FACTOR_NONE,
2518 GR_COMBINE_LOCAL_CONSTANT,
2519 GR_COMBINE_OTHER_NONE,
2522 grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
2523 GR_COMBINE_FACTOR_NONE,
2524 GR_COMBINE_LOCAL_CONSTANT,
2525 GR_COMBINE_OTHER_NONE,
2528 grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);
2530 grAlphaTestFunction (GR_CMP_ALWAYS);
2531 if (grStippleModeExt)
2532 grStippleModeExt(GR_STIPPLE_DISABLE);
2534 grCullMode(GR_CULL_DISABLE);
2535 grFogMode (GR_FOG_DISABLE);
2536 grDepthBufferFunction (GR_CMP_ALWAYS);
2537 grDepthMask (FXFALSE);
2539 rdp.update |= UPDATE_COMBINE | UPDATE_CULL_MODE | UPDATE_FOG_ENABLED | UPDATE_ZBUF_ENABLED;
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
2547 AllowShadeMods (v, 4);
2548 for (int k = 0; k < 4; k++)
2549 apply_shade_mods (&v[k]);
2551 if ((rdp.othermode_l & 0x4000) && ((rdp.othermode_l >> 16) == 0x0550)) //special blender mode for Bomberman64
2553 grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
2554 GR_COMBINE_FACTOR_NONE,
2555 GR_COMBINE_LOCAL_CONSTANT,
2556 GR_COMBINE_OTHER_NONE,
2558 grConstantColorValue((cmb.ccolor&0xFFFFFF00)|(rdp.fog_color&0xFF));
2559 rdp.update |= UPDATE_COMBINE;
2563 if (settings.wireframe)
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]);
2575 grDrawTriangle (&v[0], &v[2], &v[1]);
2576 grDrawTriangle (&v[2], &v[3], &v[1]);
2579 if (_debugger.capture)
2585 add_tri (v1, 3, TRI_FILLRECT);
2589 add_tri (v1, 3, TRI_FILLRECT);
2602 // setfillcolor - sets the filling color
2605 static void rdp_setfillcolor()
2607 rdp.fill_color = rdp.cmd1;
2608 rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE;
2610 FRDP("setfillcolor: %08lx\n", rdp.cmd1);
2613 static void rdp_setfogcolor()
2615 rdp.fog_color = rdp.cmd1;
2616 rdp.update |= UPDATE_COMBINE | UPDATE_FOG_ENABLED;
2618 FRDP("setfogcolor - %08lx\n", rdp.cmd1);
2621 static void rdp_setblendcolor()
2623 rdp.blend_color = rdp.cmd1;
2624 rdp.update |= UPDATE_COMBINE;
2626 FRDP("setblendcolor: %08lx\n", rdp.cmd1);
2629 static void rdp_setprimcolor()
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;
2636 FRDP("setprimcolor: %08lx, lodmin: %d, lodfrac: %d\n", rdp.cmd1, rdp.prim_lodmin,
2640 static void rdp_setenvcolor()
2642 rdp.env_color = rdp.cmd1;
2643 rdp.update |= UPDATE_COMBINE;
2645 FRDP("setenvcolor: %08lx\n", rdp.cmd1);
2648 static void rdp_setcombine()
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);
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);
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);
2673 rdp.update |= UPDATE_COMBINE;
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]);
2683 // settextureimage - sets the source for an image copy
2686 static void rdp_settextureimage()
2688 static const char *format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" };
2689 static const char *size[] = { "4bit", "8bit", "16bit", "32bit" };
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)
2697 if (rdp.timg.format == 0)
2699 wxUint16 * t = (wxUint16*)(gfx.RDRAM+ucode5_texshiftaddr);
2700 ucode5_texshift = t[ucode5_texshiftcount^1];
2701 rdp.timg.addr += ucode5_texshift;
2705 ucode5_texshiftaddr = 0;
2706 ucode5_texshift = 0;
2707 ucode5_texshiftcount = 0;
2710 rdp.s2dex_tex_loaded = TRUE;
2711 rdp.update |= UPDATE_TEXTURE;
2713 if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self && (rdp.timg.addr >= rdp.cimg) && (rdp.timg.addr < rdp.ci_end))
2720 CloseTextureBuffer(TRUE);
2721 rdp.fb_drawn = TRUE;
2725 if (fb_hwfbe_enabled) //search this texture among drawn texture buffers
2726 FindTextureBuffer(rdp.timg.addr, rdp.timg.width);
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);
2733 static void rdp_setdepthimage()
2735 rdp.zimg = segoffset(rdp.cmd1) & BMASK;
2736 rdp.zi_width = rdp.ci_width;
2737 FRDP("setdepthimage - %08lx\n", rdp.zimg);
2741 static void RestoreScale()
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;
2755 grDepthMask (FXFALSE);
2756 grBufferClear (0, 0, 0xFFFF);
2757 grDepthMask (FXTRUE);
2762 static wxUint32 swapped_addr = 0;
2764 static void rdp_setcolorimage()
2766 //unsigned int ticks = ticksGetTicks();
2767 //bool showdeb = false;
2768 if (fb_emulation_enabled && (rdp.num_of_ci < NUMTEXBUF))
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)
2780 if (rdp.ci_count == 0)
2782 if ((rdp.ci_status == ci_aux)) //for PPL
2784 float sx = rdp.scale_x;
2785 float sy = rdp.scale_y;
2792 if (!fb_hwfbe_enabled)
2794 if ((rdp.num_of_ci > 1) &&
2795 (next_fb.status == ci_aux) &&
2796 (next_fb.width >= cur_fb.width))
2802 else if (rdp.copy_ci_index && (settings.hacks&hack_PMario)) //tidal wave
2803 OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
2805 else if (!rdp.motionblur && fb_hwfbe_enabled && !SwapOK && (rdp.ci_count <= rdp.copy_ci_index))
2807 if (next_fb.status == ci_aux_copy)
2808 OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
2810 OpenTextureBuffer(rdp.frame_buffers[rdp.copy_ci_index]);
2812 else if (fb_hwfbe_enabled && prev_fb.status == ci_aux)
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 );
2821 else if (rdp.read_whole_frame)
2823 OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
2826 //else if (rdp.ci_status == ci_aux && !rdp.copy_ci_index)
2827 // CloseTextureBuffer();
2829 rdp.skip_drawing = FALSE;
2834 if (!rdp.motionblur || (settings.frame_buffer&fb_motionblur))
2836 if (cur_fb.width == rdp.ci_width)
2838 if (CopyTextureBuffer(prev_fb, cur_fb))
2840 // if (CloseTextureBuffer(TRUE))
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
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);
2852 if (!rdp.fb_drawn || prev_fb.status == ci_copy_self)
2855 rdp.fb_drawn = TRUE;
2857 memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);
2862 CloseTextureBuffer(TRUE);
2867 memset(gfx.RDRAM+cur_fb.addr, 0, cur_fb.width*cur_fb.height*rdp.ci_size);
2869 rdp.skip_drawing = TRUE;
2874 rdp.skip_drawing = FALSE;
2875 if (CloseTextureBuffer(prev_fb.status != ci_aux_copy))
2877 else if (!rdp.fb_drawn)
2880 rdp.fb_drawn = TRUE;
2882 if (fb_hwfbe_enabled)
2883 OpenTextureBuffer(cur_fb);
2888 if (!rdp.motionblur || (settings.frame_buffer&fb_motionblur))
2890 if (cur_fb.width == rdp.ci_width)
2892 memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.maincimg[1].addr, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);
2894 //rdp.skip_drawing = TRUE;
2898 memset(gfx.RDRAM+cur_fb.addr, 0, (cur_fb.width*cur_fb.height)<<rdp.ci_size>>1);
2903 else if (rdp.frame_buffers[rdp.ci_count].status == ci_main_i)
2905 // CopyFrameBuffer ();
2906 rdp.scale_x = rdp.scale_x_bak;
2907 rdp.scale_y = rdp.scale_y_bak;
2908 rdp.skip_drawing = FALSE;
2913 //unsigned int tticks = ticksGetTicks();
2914 if (!fb_hwfbe_enabled && cur_fb.format != 0)
2915 rdp.skip_drawing = TRUE;
2918 rdp.skip_drawing = FALSE;
2919 if (fb_hwfbe_enabled && OpenTextureBuffer(cur_fb))
2923 if (cur_fb.format != 0)
2924 rdp.skip_drawing = TRUE;
2925 if (rdp.ci_count == 0)
2927 // if (rdp.num_of_ci > 1)
2933 else if (!fb_hwfbe_enabled && (prev_fb.status == ci_main) &&
2934 (prev_fb.width == cur_fb.width)) // for Pokemon Stadium
2938 cur_fb.status = ci_aux;
2939 //tticks = ticksGetTicks() - ticks;
2940 //printf("intermediary: %u ms\n", tticks);
2944 if (settings.ucode != ucode_PerfectDark)
2946 if (fb_hwfbe_enabled && !rdp.copy_ci_index && (rdp.copy_zi_index || (settings.hacks&hack_BAR)))
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");
2957 rdp.skip_drawing = TRUE;
2960 if (settings.ucode != ucode_PerfectDark)
2962 if (fb_hwfbe_enabled && !rdp.copy_ci_index && rdp.copy_zi_index == rdp.ci_count)
2966 rdp.skip_drawing = TRUE;
2970 rdp.skip_drawing = TRUE;
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;
2978 rdp.skip_drawing = FALSE;
2981 if ((rdp.ci_count > 0) && (prev_fb.status >= ci_aux)) //for Pokemon Stadium
2983 if (!fb_hwfbe_enabled && prev_fb.format == 0)
2985 else if ((settings.hacks&hack_Knockout) && prev_fb.width < 100)
2986 CopyFrameBuffer (GR_BUFFER_TEXTUREBUFFER_EXT);
2988 if (!fb_hwfbe_enabled && cur_fb.status == ci_copy)
2990 if (!rdp.motionblur && (rdp.num_of_ci > rdp.ci_count+1) && (next_fb.status != ci_aux))
2995 if (!fb_hwfbe_enabled && cur_fb.status == ci_aux)
2997 if (cur_fb.format == 0)
2999 if ((settings.hacks&hack_PPL) && (rdp.scale_x < 1.1f)) //need to put current image back to frame buffer
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);
3007 for (int y=0; y<height; y++)
3009 for (int x=0; x<width; x++)
3011 c = ((ptr_src[(x + y * width)^1]) >> 1) | 0x8000;
3012 ptr_dst[x + y * width] = c;
3015 grLfbWriteRegion(GR_BUFFER_BACKBUFFER,
3016 (wxUint32)rdp.offset_x,
3017 (wxUint32)rdp.offset_y,
3027 else //just clear buffer
3030 grColorMask(FXTRUE, FXTRUE);
3031 grBufferClear (0, 0, 0xFFFF);
3037 if ((cur_fb.status == ci_main) && (rdp.ci_count > 0))
3039 int to_org_res = TRUE;
3040 for (int i = rdp.ci_count + 1; i < rdp.num_of_ci; i++)
3042 if ((rdp.frame_buffers[i].status != ci_main) && (rdp.frame_buffers[i].status != ci_zimg) && (rdp.frame_buffers[i].status != ci_zcopy))
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();
3056 if (fb_hwfbe_enabled && !rdp.read_whole_frame && (prev_fb.status >= ci_aux) && (rdp.ci_count > rdp.copy_ci_index))
3057 CloseTextureBuffer();
3060 rdp.ci_status = cur_fb.status;
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)
3072 rdp.ci_height = rdp.scissor_o.lr_y;
3073 if (rdp.zimg == rdp.cimg)
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;
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);
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);
3088 if (format != 0) //can't draw into non RGBA buffer
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;
3101 if (!fb_emulation_enabled)
3102 rdp.skip_drawing = FALSE;
3106 if (settings.swapmode > 0)
3108 if (rdp.zimg == rdp.cimg)
3109 rdp.updatescreen = 1;
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)
3114 if (fb_emulation_enabled)
3115 rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index];
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;
3121 rdp.vi_org_reg = *gfx.VI_ORIGIN_REG;
3123 if (fb_hwfbe_enabled)
3125 if (rdp.copy_ci_index && (rdp.frame_buffers[rdp.ci_count-1].status != ci_zimg))
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;
3133 else if (rdp.read_whole_frame && !rdp.cur_image)
3135 OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
3140 //ticks = ticksGetTicks() - ticks;
3141 //if (showdeb) printf("time = %u\n", ticks);
3144 static void rsp_reserved0()
3146 if (settings.ucode == ucode_DiddyKong)
3148 ucode5_texshiftaddr = segoffset(rdp.cmd1);
3149 ucode5_texshiftcount = 0;
3150 FRDP("uc5_texshift. addr: %08lx\n", ucode5_texshiftaddr);
3154 RDP_E("reserved0 - IGNORED\n");
3155 LRDP("reserved0 - IGNORED\n");
3159 static void rsp_reserved1()
3161 LRDP("reserved1 - ignored\n");
3164 static void rsp_reserved2()
3166 LRDP("reserved2\n");
3169 static void rsp_reserved3()
3171 LRDP("reserved3 - ignored\n");
3174 void SetWireframeCol ()
3176 if (!fullscreen) return;
3178 switch (settings.wfmode)
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,
3187 grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
3188 GR_COMBINE_FACTOR_NONE,
3189 GR_COMBINE_LOCAL_ITERATED,
3190 GR_COMBINE_OTHER_NONE,
3192 grAlphaBlendFunction (GR_BLEND_ONE,
3196 grTexCombine (GR_TMU0,
3197 GR_COMBINE_FUNCTION_ZERO,
3198 GR_COMBINE_FACTOR_NONE,
3199 GR_COMBINE_FUNCTION_ZERO,
3200 GR_COMBINE_FACTOR_NONE,
3202 grTexCombine (GR_TMU1,
3203 GR_COMBINE_FUNCTION_ZERO,
3204 GR_COMBINE_FACTOR_NONE,
3205 GR_COMBINE_FUNCTION_ZERO,
3206 GR_COMBINE_FACTOR_NONE,
3210 grColorCombine (GR_COMBINE_FUNCTION_LOCAL,
3211 GR_COMBINE_FACTOR_NONE,
3212 GR_COMBINE_LOCAL_CONSTANT,
3213 GR_COMBINE_OTHER_NONE,
3215 grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
3216 GR_COMBINE_FACTOR_NONE,
3217 GR_COMBINE_LOCAL_CONSTANT,
3218 GR_COMBINE_OTHER_NONE,
3220 grConstantColorValue (0xFF0000FF);
3221 grAlphaBlendFunction (GR_BLEND_ONE,
3225 grTexCombine (GR_TMU0,
3226 GR_COMBINE_FUNCTION_ZERO,
3227 GR_COMBINE_FACTOR_NONE,
3228 GR_COMBINE_FUNCTION_ZERO,
3229 GR_COMBINE_FACTOR_NONE,
3231 grTexCombine (GR_TMU1,
3232 GR_COMBINE_FUNCTION_ZERO,
3233 GR_COMBINE_FACTOR_NONE,
3234 GR_COMBINE_FUNCTION_ZERO,
3235 GR_COMBINE_FACTOR_NONE,
3240 grAlphaTestFunction (GR_CMP_ALWAYS);
3241 grCullMode (GR_CULL_DISABLE);
3243 rdp.update |= UPDATE_COMBINE | UPDATE_ALPHA_COMPARE;
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
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
3258 size 1 = wxUint8, 2 = wxUint16, 4 = wxUint32
3260 *******************************************************************/
3266 EXPORT void CALL FBRead(wxUint32 addr)
3268 LOG ("FBRead ()\n");
3272 if (cpu_fb_write_called)
3274 cpu_fb_ignore = TRUE;
3275 cpu_fb_write = FALSE;
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))
3284 //if (fbreads_back > 2) //&& (rdp.ci_width <= 320))
3287 rdp.fb_drawn = TRUE;
3290 if (!rdp.fb_drawn_front && (a >= rdp.maincimg[1].addr) && (a < rdp.maincimg[1].addr + rdp.ci_width*rdp.ci_height*2))
3293 //if (fbreads_front > 2)//&& (rdp.ci_width <= 320))
3295 wxUint32 cimg = rdp.cimg;
3296 rdp.cimg = rdp.maincimg[1].addr;
3297 if (fb_emulation_enabled)
3299 rdp.ci_width = rdp.maincimg[1].width;
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;
3308 CopyFrameBuffer(GR_BUFFER_FRONTBUFFER);
3311 rdp.fb_drawn_front = TRUE;
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
3324 *******************************************************************/
3325 EXPORT void CALL FBWList(FrameBufferModifyEntry *plist, wxUint32 size)
3327 LOG ("FBWList ()\n");
3328 FRDP("FBWList. size: %d\n", size);
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
3338 size 1 = wxUint8, 2 = wxUint16, 4 = wxUint32
3340 *******************************************************************/
3341 EXPORT void CALL FBWrite(wxUint32 addr, wxUint32 size)
3343 LOG ("FBWrite ()\n");
3346 if (cpu_fb_read_called)
3348 cpu_fb_ignore = TRUE;
3349 cpu_fb_write = FALSE;
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)
3357 cpu_fb_write = TRUE;
3358 wxUint32 shift_l = (a-rdp.cimg) >> 1;
3359 wxUint32 shift_r = shift_l+2;
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);
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
3377 = 2 word (16 bit) <-- this is N64 default depth buffer format
3380 when frame buffer information is not available yet, set all values
3381 in the FrameBufferInfo structure to 0
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 ************************************************************************/
3399 EXPORT void CALL FBGetFrameBufferInfo(void *p)
3401 VLOG ("FBGetFrameBufferInfo ()\n");
3402 FrameBufferInfo * pinfo = (FrameBufferInfo *)p;
3403 memset(pinfo,0,sizeof(FrameBufferInfo)*6);
3404 if (!(settings.frame_buffer&fb_get_info))
3406 LRDP("FBGetFrameBufferInfo ()\n");
3408 if (fb_emulation_enabled)
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;
3415 for (int i = 0; i < rdp.num_of_ci && info_index < 6; i++)
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)
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;
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;
3446 #include "ucodeFB.h"
3448 void DetectFrameBufferUsage ()
3450 LRDP("DetectFrameBufferUsage\n");
3452 wxUint32 dlist_start = *(wxUint32*)(gfx.DMEM+0xFF0);
3456 if ((settings.hacks&hack_PMario) && (rdp.copy_ci_index || rdp.frame_buffers[rdp.copy_ci_index].status == ci_copy_self))
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;
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;
3472 // Start executing at the start of the display list
3474 rdp.pc[rdp.pc_i] = dlist_start;
3477 rdp.scale_x_bak = rdp.scale_x;
3478 rdp.scale_y_bak = rdp.scale_y;
3480 // MAIN PROCESSING LOOP
3483 // Get the address of the next command
3484 a = rdp.pc[rdp.pc_i] & BMASK;
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]; // /
3490 // Output the address before the command
3492 // Go to the next instruction
3493 rdp.pc[rdp.pc_i] = (a+8) & BMASK;
3495 if (wxPtrToUInt(reinterpret_cast<void*>(gfx_instruction_lite[settings.ucode][rdp.cmd0>>24])))
3496 gfx_instruction_lite[settings.ucode][rdp.cmd0>>24] ();
3499 if (rdp.dl_count != -1)
3502 if (rdp.dl_count == 0)
3506 LRDP("End of DL\n");
3511 } while (!rdp.halt);
3513 if (rdp.ci_count > NUMTEXBUF) //overflow
3517 rdp.num_of_ci = rdp.ci_count;
3518 rdp.scale_x = rdp.scale_x_bak;
3519 rdp.scale_y = rdp.scale_y_bak;
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;
3526 if (rdp.frame_buffers[rdp.ci_count-1].status == ci_unknown)
3528 if (rdp.ci_count > 1)
3529 rdp.frame_buffers[rdp.ci_count-1].status = ci_aux;
3531 rdp.frame_buffers[rdp.ci_count-1].status = ci_main;
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))
3538 for (int i = 0; i < rdp.ci_count; i++)
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);
3546 rdp.main_ci_index = rdp.ci_count-1;
3549 int all_zimg = TRUE;
3551 for (i = 0; i < rdp.ci_count; i++)
3553 if (rdp.frame_buffers[i].status != ci_zimg)
3561 for (i = 0; i < rdp.ci_count; i++)
3562 rdp.frame_buffers[i].status = ci_main;
3565 LRDP("detect fb final results: \n");
3566 for (i = 0; i < rdp.ci_count; i++)
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);
3573 rdp.num_of_ci = rdp.ci_count;
3574 if (rdp.read_previous_ci && previous_ci_was_read)
3576 if (!fb_hwfbe_enabled || !rdp.copy_ci_index)
3577 rdp.motionblur = TRUE;
3579 if (rdp.motionblur || fb_hwfbe_enabled || (rdp.frame_buffers[rdp.copy_ci_index].status == ci_aux_copy))
3581 rdp.scale_x = rdp.scale_x_bak;
3582 rdp.scale_y = rdp.scale_y_bak;
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)
3589 if (fb_hwfbe_enabled)
3591 if (rdp.read_previous_ci && !previous_ci_was_read && (settings.swapmode != 2) && (settings.ucode != ucode_PerfectDark))
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;
3597 rdp.frame_buffers[ind].height = height;
3599 if (rdp.swap_ci_index < 0)
3601 rdp.texbufs[0].clear_allowed = rdp.texbufs[1].clear_allowed = TRUE;
3602 OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
3609 if (settings.frame_buffer&fb_motionblur)
3612 memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size);
3614 else //if (ci_width == rdp.frame_buffers[rdp.main_ci_index].width)
3616 if (rdp.maincimg[0].height > 65) //for 1080
3618 rdp.cimg = rdp.maincimg[0].addr;
3619 rdp.ci_width = rdp.maincimg[0].width;
3621 wxUint32 h = rdp.frame_buffers[0].height;
3622 rdp.frame_buffers[0].height = rdp.maincimg[0].height;
3624 rdp.frame_buffers[0].height = h;
3634 if (fb_hwfbe_enabled)
3636 for (i = 0; i < voodoo.num_tmu; i++)
3638 rdp.texbufs[i].clear_allowed = TRUE;
3639 for (int j = 0; j < 256; j++)
3641 rdp.texbufs[i].images[j].drawn = FALSE;
3642 rdp.texbufs[i].images[j].clear = TRUE;
3647 //LRDP("Tidal wave!\n");
3648 rdp.copy_ci_index = rdp.main_ci_index;
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");
3660 /*******************************************
3662 *******************************************
3663 * based on sources of ziggy's z64 *
3664 *******************************************/
3666 static wxUint32 rdp_cmd_ptr = 0;
3667 static wxUint32 rdp_cmd_cur = 0;
3668 static wxUint32 rdp_cmd_data[0x1000];
3670 void lle_triangle(wxUint32 w1, wxUint32 w2, int shade, int texture, int zbuffer,
3673 rdp.cur_tile = (w1 >> 16) & 0x7;
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;
3683 wxInt32 dxldy, dxhdy, dxmdy;
3684 wxUint32 w3, w4, w5, w6, w7, w8;
3686 wxUint32 * shade_base = rdp_cmd + 8;
3687 wxUint32 * texture_base = rdp_cmd + 8;
3688 wxUint32 * zbuffer_base = rdp_cmd + 8;
3708 ym = ((w2 >> 16) & 0x3fff);
3709 yh = ((w2 >> 0) & 0x3fff);
3713 dxldy = (wxInt32)(w4);
3714 dxhdy = (wxInt32)(w6);
3715 dxmdy = (wxInt32)(w8);
3717 if (yl & (0x800<<2)) yl |= 0xfffff000<<2;
3718 if (ym & (0x800<<2)) ym |= 0xfffff000<<2;
3719 if (yh & (0x800<<2)) yh |= 0xfffff000<<2;
3723 r = 0xff; g = 0xff; b = 0xff; a = 0xff; z = 0xffff0000; s = 0; t = 0; w = 0x30000;
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);
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);
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);
3755 z = zbuffer_base[0];
3756 dzdx = zbuffer_base[1];
3757 dzde = zbuffer_base[2];
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;
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))
3780 VERTEX * vtx = &vtxbuf[nbVtxs++];
3788 !((!flip && xleft < xright+0x10000) ||
3789 (flip && xleft > xright-0x10000))) {
3791 xright += xright_inc;
3792 s += dsde; t += dtde; w += dwde;
3793 r += drde; g += dgde; b += dbde; a += dade;
3801 int dx = (xleft-xright)>>16;
3802 if ((!flip && xleft < xright) ||
3803 (flip/* && xleft > xright*/))
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);
3812 vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx);
3813 vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx);
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++];
3821 if ((!flip/* && xleft < xright*/) ||
3822 (flip && xleft > xright))
3831 vtx->ou = SSCALE(s, w);
3832 vtx->ov = TSCALE(t, w);
3834 vtx->x = XSCALE(xright);
3835 vtx->y = YSCALE(yh);
3838 vtx = &vtxbuf[nbVtxs++];
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;
3854 int dx = (xleft-xright)>>16;
3855 if ((!flip && xleft <= xright) ||
3856 (flip/* && xleft >= xright*/))
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);
3865 vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx);
3866 vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx);
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++];
3874 if ((!flip/* && xleft <= xright*/) ||
3875 (flip && xleft >= xright))
3884 vtx->ou = SSCALE(s, w);
3885 vtx->ov = TSCALE(t, w);
3887 vtx->x = XSCALE(xright);
3888 vtx->y = YSCALE(ym);
3891 vtx = &vtxbuf[nbVtxs++];
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;
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;
3917 int dx = (xleft-xright)>>16;
3918 if ((!flip && xleft <= xright) ||
3919 (flip/* && xleft >= xright*/))
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);
3928 vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx);
3929 vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx);
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++];
3937 if ((!flip/* && xleft <= xright*/) ||
3938 (flip && xleft >= xright))
3947 vtx->ou = SSCALE(s, w);
3948 vtx->ov = TSCALE(t, w);
3950 vtx->x = XSCALE(xright);
3951 vtx->y = YSCALE(yl);
3954 vtx = &vtxbuf[nbVtxs++];
3961 for (int k = 0; k < nbVtxs-1; k++)
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;
3968 v->u1 = v->u0 = v->ou;
3969 v->v1 = v->v0 = v->ov;
3970 if (rdp.tex >= 1 && rdp.cur_cache[0])
3972 if (rdp.tiles[rdp.cur_tile].shift_s)
3974 if (rdp.tiles[rdp.cur_tile].shift_s > 10)
3975 v->u0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s));
3977 v->u0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_s);
3979 if (rdp.tiles[rdp.cur_tile].shift_t)
3981 if (rdp.tiles[rdp.cur_tile].shift_t > 10)
3982 v->v0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t));
3984 v->v0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_t);
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;
3995 if (rdp.tex >= 2 && rdp.cur_cache[1])
3997 if (rdp.tiles[rdp.cur_tile+1].shift_s)
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));
4002 v->u1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_s);
4004 if (rdp.tiles[rdp.cur_tile+1].shift_t)
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));
4009 v->v1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_t);
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;
4019 apply_shade_mods (v);
4021 ConvertCoordsConvert (vtxbuf, nbVtxs);
4022 grCullMode (GR_CULL_DISABLE);
4023 grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, nbVtxs-1, vtxbuf, sizeof(VERTEX));
4024 if (_debugger.capture)
4030 add_tri (vl, 3, TRI_TRIANGLE);
4037 add_tri (vl, 3, TRI_TRIANGLE);
4044 static void rdp_triangle(int shade, int texture, int zbuffer)
4046 lle_triangle(rdp.cmd0, rdp.cmd1, shade, texture, zbuffer, rdp_cmd_data + rdp_cmd_cur);
4049 static void rdp_trifill()
4051 rdp_triangle(0, 0, 0);
4055 static void rdp_trishade()
4057 rdp_triangle(1, 0, 0);
4061 static void rdp_tritxtr()
4063 rdp_triangle(0, 1, 0);
4067 static void rdp_trishadetxtr()
4069 rdp_triangle(1, 1, 0);
4070 LRDP("trishadetxtr\n");
4073 static void rdp_trifillz()
4075 rdp_triangle(0, 0, 1);
4079 static void rdp_trishadez()
4081 rdp_triangle(1, 0, 1);
4082 LRDP("trishadez\n");
4085 static void rdp_tritxtrz()
4087 rdp_triangle(0, 1, 1);
4091 static void rdp_trishadetxtrz()
4093 rdp_triangle(1, 1, 1);
4094 LRDP("trishadetxtrz\n");
4098 static rdp_instr rdp_command_table[64] =
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,
4106 undef, undef, undef, undef,
4107 undef, undef, undef, undef,
4108 undef, undef, undef, undef,
4109 undef, undef, undef, undef,
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,
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
4122 static const wxUint32 rdp_command_length[64] =
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
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
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
4190 #define rdram ((wxUint32*)gfx.RDRAM)
4191 #define rsp_dmem ((wxUint32*)gfx.DMEM)
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)
4198 inline wxUint32 READ_RDP_DATA(wxUint32 address)
4200 if (dp_status & 0x1) // XBUS_DMEM_DMA enabled
4201 return rsp_dmem[(address & 0xfff)>>2];
4203 return rdram[address>>2];
4206 static void rdphalf_1()
4208 wxUint32 cmd = rdp.cmd1 >> 24;
4209 if (cmd >= 0xc8 && cmd <=0xcf) //triangle command
4211 LRDP("rdphalf_1 - lle triangle\n");
4218 rdp_cmd_data[rdp_cmd_ptr++] = rdp.cmd1;
4220 if (rdp.dl_count != -1)
4223 if (rdp.dl_count == 0)
4227 LRDP("End of DL\n");
4232 // Get the address of the next command
4233 a = rdp.pc[rdp.pc_i] & BMASK;
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]; // /
4239 // Go to the next instruction
4240 rdp.pc[rdp.pc_i] = (a+8) & BMASK;
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];
4248 wxUint32 cmd3 = ((wxUint32*)gfx.RDRAM)[(a>>2)+2];
4249 if ((cmd3>>24) == 0xb4)
4250 rglSingleTriangle = TRUE;
4252 rglSingleTriangle = FALSE;
4254 rdp_command_table[cmd]();
4258 LRDP("rdphalf_1 - IGNORED\n");
4262 static void rdphalf_2()
4264 RDP_E("rdphalf_2 - IGNORED\n");
4265 LRDP("rdphalf_2 - IGNORED\n");
4268 static void rdphalf_cont()
4270 RDP_E("rdphalf_cont - IGNORED\n");
4271 LRDP("rdphalf_cont - IGNORED\n");
4274 /******************************************************************
4275 Function: ProcessRDPList
4276 Purpose: This function is called when there is a Dlist to be
4277 processed. (Low level GFX list)
4280 *******************************************************************/
4284 EXPORT void CALL ProcessRDPList(void)
4286 LOG ("ProcessRDPList ()\n");
4287 LRDP("ProcessRDPList ()\n");
4289 // SoftLocker lock(mutexProcessDList);
4290 if (/*!lock.IsOk()*/0) //mutex is busy
4293 drawNoFullscreenMessage();
4294 // Set an interrupt to allow the game to continue
4295 *gfx.MI_INTR_REG |= 0x20;
4296 gfx.CheckInterrupts();
4301 wxUint32 cmd, length, cmd_length;
4305 if (dp_end <= dp_current) return;
4306 length = dp_end - dp_current;
4308 // load command data
4309 for (i=0; i < length; i += 4)
4311 rdp_cmd_data[rdp_cmd_ptr++] = READ_RDP_DATA(dp_current + i);
4312 if (rdp_cmd_ptr >= 0x1000)
4314 FRDP("rdp_process_list: rdp_cmd_ptr overflow %x %x --> %x\n", length, dp_current, dp_end);
4318 dp_current = dp_end;
4320 cmd = (rdp_cmd_data[0] >> 24) & 0x3f;
4321 cmd_length = (rdp_cmd_ptr + 1) * 4;
4323 // check if more data is needed
4324 if (cmd_length < rdp_command_length[cmd])
4327 while (rdp_cmd_cur < rdp_cmd_ptr)
4329 cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f;
4331 if (((rdp_cmd_ptr-rdp_cmd_cur) * 4) < rdp_command_length[cmd])
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]();
4341 rdp_cmd_cur += rdp_command_length[cmd] / 4;
4347 dp_status &= ~0x0002;