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