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