2
* Glide64 - Glide video plugin for Nintendo 64 emulators.
3
* Copyright (c) 2002 Dave2001
4
* Copyright (c) 2008 Günther <guenther.emu@freenet.de>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public
17
* Licence along with this program; if not, write to the Free
18
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19
* Boston, MA 02110-1301, USA
22
//****************************************************************
24
// Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)
25
// Project started on December 29th, 2001
28
// * 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.
29
// * 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.
31
// Official Glide64 development channel: #Glide64 on EFnet
33
// Original author: Dave2001 (Dave2999@hotmail.com)
34
// Other authors: Gonetz, Gugaman
36
//****************************************************************
48
#include "TexBuffer.h"
52
#include "messagebox.h"
58
DWORD frame_count; // frame counter
60
BOOL ucode_error_report = TRUE;
64
#define BYTESWAP1(s1) s1 = ((s1 & 0xff) << 24) | ((s1 & 0xff00) << 8) | ((s1 & 0xff0000) >> 8) | ((s1 & 0xff000000) >> 24);
65
#define BYTESWAP2(s1,s2) s1 = ((s1 & 0xff) << 24) | ((s1 & 0xff00) << 8) | ((s1 & 0xff0000) >> 8) | ((s1 & 0xff000000) >> 24); \
66
s2 = ((s2 & 0xff) << 24) | ((s2 & 0xff00) << 8) | ((s2 & 0xff0000) >> 8) | ((s2 & 0xff000000) >> 24);
68
#define BYTESWAP1(s1) asm volatile (" bswap %0; " : "+r" (s1) : :);
69
#define BYTESWAP2(s1,s2) asm volatile (" bswap %0; bswap %1; " : "+r" (s1), "+r" (s2) : :);
73
const char *ACmp[4] = { "NONE", "THRESHOLD", "UNKNOWN", "DITHER" };
75
const char *Mode0[16] = { "COMBINED", "TEXEL0",
76
"TEXEL1", "PRIMITIVE",
77
"SHADE", "ENVIORNMENT",
83
const char *Mode1[16] = { "COMBINED", "TEXEL0",
84
"TEXEL1", "PRIMITIVE",
85
"SHADE", "ENVIORNMENT",
91
const char *Mode2[32] = { "COMBINED", "TEXEL0",
92
"TEXEL1", "PRIMITIVE",
93
"SHADE", "ENVIORNMENT",
94
"SCALE", "COMBINED_ALPHA",
95
"T0_ALPHA", "T1_ALPHA",
96
"PRIM_ALPHA", "SHADE_ALPHA",
97
"ENV_ALPHA", "LOD_FRACTION",
107
const char *Mode3[8] = { "COMBINED", "TEXEL0",
108
"TEXEL1", "PRIMITIVE",
109
"SHADE", "ENVIORNMENT",
112
const char *Alpha0[8] = { "COMBINED", "TEXEL0",
113
"TEXEL1", "PRIMITIVE",
114
"SHADE", "ENVIORNMENT",
116
const char *Alpha2[8] = { "LOD_FRACTION", "TEXEL0",
117
"TEXEL1", "PRIMITIVE",
118
"SHADE", "ENVIORNMENT",
119
"PRIM_LODFRAC", "0" };
122
//const char *FBLa[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG" };
123
//const char *FBLb[] = { "G_BL_A_IN", "G_BL_A_FOG", "G_BL_A_SHADE", "G_BL_0" };
124
//const char *FBLc[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG"};
125
//const char *FBLd[] = { "G_BL_1MA", "G_BL_A_MEM", "G_BL_1", "G_BL_0" };
127
const char *str_zs[2] = { "G_ZS_PIXEL", "G_ZS_PRIM" };
129
const char *str_yn[2] = { "NO", "YES" };
130
const char *str_offon[2] = { "OFF", "ON" };
132
const char *str_cull[4] = { "DISABLE", "FRONT", "BACK", "BOTH" };
134
// I=intensity probably
135
const char *str_format[8] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" };
136
const char *str_size[4] = { "4bit", "8bit", "16bit", "32bit" };
137
const char *str_cm[4] = { "WRAP/NO CLAMP", "MIRROR/NO CLAMP", "WRAP/CLAMP", "MIRROR/CLAMP" };
139
//const char *str_lod[] = { "1", "2", "4", "8", "16", "32", "64", "128", "256" };
140
//const char *str_aspect[] = { "1x8", "1x4", "1x2", "1x1", "2x1", "4x1", "8x1" };
142
const char *str_filter[3] = { "Point Sampled", "Average (box)", "Bilinear" };
144
const char *str_tlut[4] = { "TT_NONE", "TT_UNKNOWN", "TT_RGBA_16", "TT_IA_16" };
146
const char *CIStatus[10] = { "ci_main", "ci_zimg", "ci_unknown", "ci_useless",
147
"ci_old_copy", "ci_copy", "ci_copy_self",
148
"ci_zcopy", "ci_aux", "ci_aux_copy" };
152
// depth save/restore variables
154
// 1 : writing in normal depth buffer
155
// 2 : writing in alternate depth buffer
156
static int render_depth_mode;
158
// ** RDP graphics functions **
160
static void spnoop();
162
static void rdp_noop();
163
static void rdp_texrect();
164
//static void rdp_texrectflip();
165
static void rdp_loadsync();
166
static void rdp_pipesync();
167
static void rdp_tilesync();
168
static void rdp_fullsync();
169
static void rdp_setkeygb();
170
static void rdp_setkeyr();
171
static void rdp_setconvert();
172
static void rdp_setscissor();
173
static void rdp_setprimdepth();
174
static void rdp_setothermode();
175
static void rdp_loadtlut();
176
static void rdp_settilesize();
177
static void rdp_loadblock();
178
static void rdp_loadtile();
179
static void rdp_settile();
180
static void rdp_fillrect();
181
static void rdp_setfillcolor();
182
static void rdp_setfogcolor();
183
static void rdp_setblendcolor();
184
static void rdp_setprimcolor();
185
static void rdp_setenvcolor();
186
static void rdp_setcombine();
187
static void rdp_settextureimage();
188
static void rdp_setdepthimage();
189
static void rdp_setcolorimage();
190
static void rdp_trifill();
191
static void rdp_trishade();
192
static void rdp_tritxtr();
193
static void rdp_trishadetxtr();
194
static void rdp_trifillz();
195
static void rdp_trishadez();
196
static void rdp_tritxtrz();
197
static void rdp_trishadetxtrz();
199
static void rsp_reserved0();
200
static void rsp_reserved1();
201
static void rsp_reserved2();
202
static void rsp_reserved3();
204
static void ys_memrect();
206
BYTE microcode[4096];
210
// ** UCODE FUNCTIONS **
222
static BOOL reset = 0;
223
static int old_ucode = -1;
225
// rdp_reset - resets the RDP_E
234
rdp.cur_cache[0] = NULL;
235
rdp.cur_cache[1] = NULL;
237
rdp.tmem_ptr[0] = offset_textures;
238
rdp.tmem_ptr[1] = offset_textures;
239
if (grTextureBufferExt)
240
rdp.tmem_ptr[1] = TEXMEM_2MB_EDGE * 2;
260
// Clear the palette CRC
263
rdp.pal_8_crc[i] = 0;
265
// Clear the palettes
266
for (i=0; i<256; i++)
271
// Clear all segments ** VERY IMPORTANT FOR ZELDA **
275
for (i=0; i<512; i++)
278
// set all vertex numbers
279
for (i=0; i<MAX_VTX; i++)
280
rdp.vtx[i].number = i;
282
rdp.scissor_o.ul_x = 0;
283
rdp.scissor_o.ul_y = 0;
284
rdp.scissor_o.lr_x = 320;
285
rdp.scissor_o.lr_y = 240;
287
rdp.lookat[0][0] = rdp.lookat[1][1] = 1.0f;
288
rdp.lookat[0][1] = rdp.lookat[0][2] = rdp.lookat[1][0] = rdp.lookat[1][2] = 0.0f;
291
rdp.render_mode_changed = 0;
305
rdp.allow_combine = 1;
307
rdp.fog_coord_enabled = FALSE;
308
rdp.skip_drawing = FALSE;
310
memset(rdp.frame_buffers, 0, sizeof(rdp.frame_buffers));
311
rdp.main_ci_index = 0;
312
rdp.maincimg[0].addr = rdp.maincimg[1].addr = rdp.last_drawn_ci_addr = 0x7FFFFFFF;
313
rdp.read_previous_ci = FALSE;
314
rdp.yuv_ul_x = rdp.yuv_ul_y = rdp.yuv_lr_x = rdp.yuv_lr_y = 0;
315
rdp.yuv_im_begin = 0x00FFFFFF;
316
rdp.yuv_image = FALSE;
322
hotkey_info.fb_always = 0;
323
hotkey_info.fb_motionblur = (settings.buff_clear == 0)?0:60;
324
hotkey_info.filtering = hotkey_info.fb_motionblur;
325
hotkey_info.corona = hotkey_info.fb_motionblur;
327
GetAsyncKeyState (VK_BACK);
328
GetAsyncKeyState(0x42);
329
GetAsyncKeyState(0x56);
330
GetAsyncKeyState(0x43);
332
for (i = 0; i < num_tmu; i++)
333
rdp.texbufs[i].count = 0;
334
rdp.vi_org_reg = *gfx.VI_ORIGIN_REG;
335
rdp.view_scale[0] = 160.0f * rdp.scale_x;
336
rdp.view_scale[1] = -120.0f * rdp.scale_y;
337
rdp.view_trans[0] = 160.0f * rdp.scale_x;
338
rdp.view_trans[1] = 120.0f * rdp.scale_y;
339
rdp.view_scale[2] = 32.0f * 511.0f;
340
rdp.view_trans[2] = 32.0f * 511.0f;
345
# define ByteEndian(address) (address^3)
346
# define WordEndian(address) (address^2)
348
# define _Read8Endian(array, address) (*((BYTE *)(array+ByteEndian(address))))
349
__inline static DWORD searchrdram(const char *ct)
354
for (pos=0; pos<0x400000; pos++) {
355
for (pos2=pos, t=ct; *ct != 0; t++, pos2++) {
356
if (_Read8Endian(gfx.RDRAM, pos2) != *t)
371
// Check first 3k of ucode, because the last 1k sometimes contains trash
372
for (i=0; i<3072>>2; i++)
374
uc_crc += ((DWORD*)microcode)[i];
377
FRDP_E ("crc: %08lx\n", uc_crc);
381
ucf.open ("ucode.txt", ios::out | ios::binary);
383
for (i=0; i<0x400000; i++)
385
d = ((char*)gfx.RDRAM)[i^3];
392
sprintf (str, "%08lx", (unsigned long)uc_crc);
395
INI_FindSection ("UCODE");
396
FRDP("ucode = %s\n", str);
397
int uc = INI_ReadInt (str, -2, 0);
399
if (uc == -2 && ucode_error_report)
401
INI_FindSection ("SETTINGS");
402
settings.ucode = INI_ReadInt ("ucode", 0);
406
sprintf (out_buf, "Error: uCode crc not found in INI, using currently selected uCode\n\n%08lx", (unsigned long)uc_crc);
408
MessageBox (gfx.hWnd, out_buf, "Error", MB_OK|MB_ICONEXCLAMATION);
410
messagebox("Error", MB_OK|MB_ICONEXCLAMATION, "%s", out_buf);
413
ucode_error_report = FALSE; // don't report any more ucode errors from this game
415
else if (uc == -1 && ucode_error_report)
417
INI_FindSection ("SETTINGS");
418
settings.ucode = INI_ReadInt ("ucode", 0);
422
sprintf (out_buf, "Error: Unsupported uCode!\n\ncrc: %08lx", (unsigned long)uc_crc);
424
MessageBox (gfx.hWnd, out_buf, "Error", MB_OK|MB_ICONEXCLAMATION);
426
messagebox("Error", MB_OK|MB_ICONEXCLAMATION, "%s", out_buf);
429
ucode_error_report = FALSE; // don't report any more ucode errors from this game
433
old_ucode = settings.ucode;
435
FRDP("microcheck: old ucode: %d, new ucode: %d\n", old_ucode, uc);
436
//INI_FindSection ("SETTINGS");
437
//INI_WriteInt ("ucode", uc);
446
void drawNoFullscreenMessage()
448
LOG ("drawNoFullscreenMessage ()\n");
452
HWND active_wnd = GetForegroundWindow ();
454
GetClientRect (gfx.hWnd, &win_rect);
455
if (win_rect.bottom != prev_rect.bottom ||
456
win_rect.right != prev_rect.right ||
459
rdp.window_changed = FALSE;
461
prev_rect.bottom = win_rect.bottom;
462
prev_rect.right = win_rect.right;
464
HDC hdc = GetDC(gfx.hWnd);
465
SetBkMode (hdc, TRANSPARENT);
466
SetTextColor (hdc, RGB(255,255,255));
468
FillRect (hdc, &win_rect, (HBRUSH)GetStockObject(DKGRAY_BRUSH));
470
win_rect.bottom >>= 1;
471
win_rect.right >>= 1;
473
sprintf (out_buf, "Glide64");
474
GetTextExtentPoint32 (hdc, out_buf, strlen(out_buf), &str_size);
475
TextOut (hdc, win_rect.right - (str_size.cx>>1),
476
win_rect.bottom - str_size.cy - 32, out_buf, strlen(out_buf));
478
sprintf (out_buf, "Gfx cannot be drawn in windowed mode");
479
GetTextExtentPoint32 (hdc, out_buf, strlen(out_buf), &str_size);
480
TextOut (hdc, win_rect.right - (str_size.cx>>1),
481
win_rect.bottom - str_size.cy - 2, out_buf, strlen(out_buf));
483
sprintf (out_buf, "Press Alt+Enter to switch to fullscreen");
484
GetTextExtentPoint32 (hdc, out_buf, strlen(out_buf), &str_size);
485
TextOut (hdc, win_rect.right - (str_size.cx>>1),
486
win_rect.bottom + 2, out_buf, strlen(out_buf));
491
static WORD yuv_to_rgb(BYTE y, BYTE u, BYTE v)
493
float r = y + (1.370705f * (v-128));
494
float g = y - (0.698001f * (v-128)) - (0.337633f * (u-128));
495
float b = y + (1.732446f * (u-128));
499
//clipping the result
507
WORD c = (WORD)(((WORD)(r) << 11) |
509
((WORD)(b) << 1) | 1);
513
static void DrawYUVImageToFrameBuffer()
515
WORD width = (WORD)(rdp.yuv_lr_x - rdp.yuv_ul_x);
516
WORD height = (WORD)(rdp.yuv_lr_y - rdp.yuv_ul_y);
517
DWORD * mb = (DWORD*)(gfx.RDRAM+rdp.yuv_im_begin); //pointer to the first macro block
518
WORD * cimg = (WORD*)(gfx.RDRAM+rdp.cimg);
519
//yuv macro block contains 16x16 texture. we need to put it in the proper place inside cimg
520
for (WORD y = 0; y < height; y+=16)
522
for (WORD x = 0; x < width; x+=16)
524
WORD *dst = cimg + x + y * rdp.ci_width;
525
for (WORD h = 0; h < 16; h++)
527
for (WORD w = 0; w < 8; w++)
529
DWORD t = *(mb++); //each DWORD contains 2 pixels
530
if ((x < rdp.ci_width) && (y < rdp.ci_height)) //clipping. texture image may be larger than color image
532
BYTE y0 = (BYTE)t&0xFF;
533
BYTE v = (BYTE)(t>>8)&0xFF;
534
BYTE y1 = (BYTE)(t>>16)&0xFF;
535
BYTE u = (BYTE)(t>>24)&0xFF;
536
*(dst++) = yuv_to_rgb(y0, u, v);
537
*(dst++) = yuv_to_rgb(y1, u, v);
540
dst += rdp.ci_width - 16;
542
mb += 64; //macro block is 768 bytes long, last 256 bytes are useless
547
static DWORD d_ul_x, d_ul_y, d_lr_x, d_lr_y;
550
int ul_x, ul_y, lr_x, lr_y;
553
static void DrawPart(int scr_ul_x, int scr_ul_y, int prt_ul_x, int prt_ul_y, int width, int height, float scale_x, float scale_y)
555
WORD * dst = new WORD[width*height];
556
DWORD shift = ((d_ul_y+prt_ul_y) * rdp.ci_width + d_ul_x + prt_ul_x) << 1;
557
WORD * src = (WORD*)(gfx.RDRAM+rdp.cimg+shift);
559
for (int y=0; y < height; y++)
561
for (int x=0; x < width; x++)
563
c = src[(int(x*scale_x)+int(y*scale_y)*rdp.ci_width)^1];
564
dst[x+y*width] = c?((c >> 1) | 0x8000):0;
568
grLfbWriteRegion(GR_BUFFER_BACKBUFFER,
580
static void DrawFrameBufferToScreen()
582
FRDP("DrawFrameBufferToScreen. cimg: %08lx, ul_x: %d, uly: %d, lr_x: %d, lr_y: %d\n", rdp.cimg, d_ul_x, d_ul_y, d_lr_x, d_lr_y);
585
grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
586
GR_COMBINE_FACTOR_ONE,
587
GR_COMBINE_LOCAL_NONE,
588
GR_COMBINE_OTHER_TEXTURE,
590
grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
591
GR_COMBINE_FACTOR_ONE,
592
GR_COMBINE_LOCAL_NONE,
593
GR_COMBINE_OTHER_TEXTURE,
595
grConstantColorValue (0xFFFFFFFF);
596
grAlphaBlendFunction( GR_BLEND_SRC_ALPHA,
597
GR_BLEND_ONE_MINUS_SRC_ALPHA,
600
rdp.update |= UPDATE_COMBINE;
602
float scale_x_dst = (float)settings.scr_res_x / rdp.vi_width;//(float)max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width);
603
float scale_y_dst = (float)settings.scr_res_y / rdp.vi_height;//(float)max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound);
604
float scale_x_src = (float)rdp.vi_width / (float)settings.scr_res_x;//(float)max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width);
605
float scale_y_src = (float)rdp.vi_height / (float)settings.scr_res_y;//(float)max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound);
606
int src_width = d_lr_x - d_ul_x + 1;
607
int src_height = d_lr_y - d_ul_y + 1;
608
int dst_width, dst_height, ul_x, ul_y;
610
if (!settings.fb_optimize_write || ((src_width < 33) && (src_height < 33)))
612
dst_width = int(src_width*scale_x_dst);
613
dst_height = int(src_height*scale_y_dst);
614
ul_x = int(d_ul_x*scale_x_dst);
615
ul_y = int(d_ul_y*scale_y_dst);
616
DrawPart(ul_x, ul_y, 0, 0, dst_width, dst_height, scale_x_src, scale_y_src);
617
memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size);
623
for (p = 0; p < 8; p++)
625
parts[p].lr_x = parts[p].lr_y = 0;
626
parts[p].ul_x = parts[p].ul_y = 0xFFFF;
629
int num_of_parts = 0;
631
int most_left = d_ul_x;
632
int most_right = d_lr_x;
633
DWORD shift = (d_ul_y * rdp.ci_width + d_ul_x) << 1;
634
WORD * src = (WORD*)(gfx.RDRAM+rdp.cimg+shift);
635
for (int h = 0; h < src_height; h++)
639
while (w < src_width)
641
while (w < src_width)
643
if (src[(w+h*rdp.ci_width)^1] == 0)
650
if (num_of_parts == 0) //first part
657
else if (w < most_left - 2) //new part
659
parts[num_of_parts].ul_x = w;
661
parts[num_of_parts].ul_y = h;
662
cur_part = num_of_parts;
665
else if (w > most_right + 2) //new part
667
parts[num_of_parts].ul_x = w;
669
parts[num_of_parts].ul_y = h;
670
cur_part = num_of_parts;
675
for (p = 0; p < num_of_parts; p++)
677
if ((w > parts[p].ul_x - 2) && (w < parts[p].lr_x+2))
679
if (w < parts[p].ul_x) parts[p].ul_x = w;
685
while (w < src_width)
687
if (src[(w+h*rdp.ci_width)^1] != 0)
692
if (num_of_parts == 0) //first part
700
if (parts[cur_part].lr_x < w) parts[cur_part].lr_x = w;
701
if (most_right < w) most_right = w;
702
parts[cur_part].lr_y = h;
707
for (p = 0; p < num_of_parts; p++)
709
FRDP("part#%d ul_x: %d, ul_y: %d, lr_x: %d, lr_y: %d\n", p, parts[p].ul_x, parts[p].ul_y, parts[p].lr_x, parts[p].lr_y);
712
for (p = 0; p < num_of_parts; p++)
714
dst_width = int((parts[p].lr_x-parts[p].ul_x + 1)*scale_x_dst);
715
dst_height = int((parts[p].lr_y-parts[p].ul_y + 1)*scale_y_dst);
716
ul_x = int((d_ul_x+parts[p].ul_x)*scale_x_dst);
717
ul_y = int((d_ul_y+parts[p].ul_y)*scale_y_dst);
718
DrawPart(ul_x, ul_y, parts[p].ul_x, parts[p].ul_y, dst_width, dst_height, scale_x_src, scale_y_src);
720
memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size);
723
#define RGBA16TO32(color) \
724
((color&1)?0xFF:0) | \
725
((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | \
726
((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | \
727
((DWORD)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8)
729
static void CopyFrameBuffer (GrBuffer_t buffer = GR_BUFFER_BACKBUFFER)
733
FRDP ("CopyFrameBuffer: %08lx... ", rdp.cimg);
735
// don't bother to write the stuff in asm... the slow part is the read from video card,
738
int width = rdp.ci_width;//*gfx.VI_WIDTH_REG;
740
if (settings.fb_smart && !settings.PPL)
742
int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0;
743
height = rdp.frame_buffers[ind].height;
747
height = rdp.ci_lower_bound;
749
height -= rdp.ci_upper_bound;
751
FRDP ("width: %d, height: %d... ", width, height);
753
if (rdp.scale_x < 1.1f)
755
WORD * ptr_src = new WORD[width*height];
756
if (grLfbReadRegion(buffer,
758
0,//rdp.ci_upper_bound,
764
WORD *ptr_dst = (WORD*)(gfx.RDRAM+rdp.cimg);
765
DWORD *ptr_dst32 = (DWORD*)(gfx.RDRAM+rdp.cimg);
768
for (int y=0; y<height; y++)
770
for (int x=0; x<width; x++)
772
c = ptr_src[x + y * width];
773
if (settings.fb_read_alpha)
776
c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;
780
c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;
782
if (rdp.ci_size == 2)
783
ptr_dst[(x + y * width)^1] = c;
785
ptr_dst32[x + y * width] = RGBA16TO32(c);
792
BYTE *ptr_dst = (BYTE*)(gfx.RDRAM+rdp.cimg);
795
for (int y=0; y<height; y++)
797
for (int x=0; x<width; x++)
799
c = ptr_src[x + y * width];
800
BYTE b = (BYTE)((float)(c&0x1F)/31.0f*85.0f);
801
BYTE g = (BYTE)((float)((c>>5)&0x3F)/63.0f*85.0f);
802
BYTE r = (BYTE)((float)((c>>11)&0x1F)/31.0f*85.0f);
803
c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;
804
// FRDP("src: %08lx, dst: %d\n",c,(BYTE)(r+g+b));
805
ptr_dst[(x + y * width)^1] = (BYTE)(r+g+b);
806
// ptr_dst[(x + y * width)^1] = (BYTE)((c>>8)&0xFF);
810
RDP ("ReadRegion. Framebuffer copy complete.\n");
814
RDP ("Framebuffer copy failed.\n");
820
if (rdp.motionblur && settings.fb_hires)
826
float scale_x = (float)settings.scr_res_x / rdp.vi_width;//(float)max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width);
827
float scale_y = (float)settings.scr_res_y / rdp.vi_height;//(float)max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound);
829
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);
831
info.size = sizeof(GrLfbInfo_t);
834
// VP 888 disconnected for now
835
if (1||rdp.ci_size <= 2) {
836
if (grLfbLock (GR_LFB_READ_ONLY,
839
GR_ORIGIN_UPPER_LEFT,
843
WORD *ptr_src = (WORD*)info.lfbPtr;
844
WORD *ptr_dst = (WORD*)(gfx.RDRAM+rdp.cimg);
845
DWORD *ptr_dst32 = (DWORD*)(gfx.RDRAM+rdp.cimg);
847
DWORD stride = info.strideInBytes>>1;
849
BOOL read_alpha = settings.fb_read_alpha;
850
if (settings.PM && rdp.frame_buffers[rdp.ci_count-1].status != ci_aux)
852
for (int y=0; y<height; y++)
854
for (int x=0; x<width; x++)
856
c = ptr_src[int(x*scale_x) + int(y * scale_y) * stride];
857
c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;
858
if (read_alpha && c == 1)
860
if (rdp.ci_size <= 2)
861
ptr_dst[(x + y * width)^1] = c;
863
ptr_dst32[x + y * width] = RGBA16TO32(c);
867
// Unlock the backbuffer
868
grLfbUnlock (GR_LFB_READ_ONLY, buffer);
869
RDP ("LfbLock. Framebuffer copy complete.\n");
873
RDP ("Framebuffer copy failed.\n");
878
if (grLfbLock (GR_LFB_READ_ONLY,
881
GR_ORIGIN_UPPER_LEFT,
885
DWORD *ptr_src = (DWORD*)info.lfbPtr;
887
//WORD *ptr_dst = (WORD*)(gfx.RDRAM+rdp.cimg);
888
DWORD *ptr_dst32 = (DWORD*)(gfx.RDRAM+rdp.cimg);
890
DWORD stride = info.strideInBytes>>1;
892
BOOL read_alpha = settings.fb_read_alpha;
893
if (settings.PM && rdp.frame_buffers[rdp.ci_count-1].status != ci_aux)
895
for (int y=0; y<height; y++)
897
for (int x=0; x<width; x++)
899
c = ptr_src[int(x*scale_x) + int(y * scale_y) * stride];
900
// c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;
901
// if (read_alpha && c == 1)
903
ptr_dst32[x + y * width] = c;
907
// Unlock the backbuffer
908
grLfbUnlock (GR_LFB_READ_ONLY, buffer);
909
RDP ("LfbLock. Framebuffer copy complete.\n");
913
RDP ("Framebuffer copy failed.\n");
920
/******************************************************************
921
Function: ProcessDList
922
Purpose: This function is called when there is a Dlist to be
923
processed. (High level GFX list)
926
*******************************************************************/
927
void DetectFrameBufferUsage ();
928
DWORD fbreads_front = 0;
929
DWORD fbreads_back = 0;
930
BOOL cpu_fb_read_called = FALSE;
931
BOOL cpu_fb_write_called = FALSE;
932
BOOL cpu_fb_write = FALSE;
933
BOOL cpu_fb_ignore = FALSE;
936
EXPORT void CALL ProcessDList(void)
939
update_screen_count = 0;
943
if (!hhkLowLevelKybd)
945
hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL,
946
LowLevelKeyboardProc, hInstance, 0);
950
LOG ("ProcessDList ()\n");
954
drawNoFullscreenMessage();
955
// Set an interrupt to allow the game to continue
956
*gfx.MI_INTR_REG |= 0x20;
957
gfx.CheckInterrupts();
964
memset (microcode, 0, 4096);
965
if (settings.autodetect_ucode)
967
// Thanks to ZeZu for ucode autodetection!!!
969
DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0);
970
memcpy (microcode, gfx.RDRAM+startUcode, 4096);
975
else if ( ((old_ucode == 6) && (settings.ucode == 1)) || settings.force_microcheck)
977
DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0);
978
memcpy (microcode, gfx.RDRAM+startUcode, 4096);
982
if (exception) return;
984
// Switch to fullscreen?
987
to_fullscreen = FALSE;
989
if (!InitGfx (FALSE))
997
ShowWindow( gfx.hStatusBar, SW_HIDE );
1002
// Clear out the RDP log
1004
if (settings.logging && settings.log_clear)
1012
if (settings.log_unk && settings.unk_clear)
1014
std::ofstream unimp;
1015
unimp.open("unimp.txt");
1021
if (settings.swapmode > 0)
1023
rdp.updatescreen = 1;
1025
rdp.tri_n = 0; // 0 triangles so far this frame
1028
rdp.model_i = 0; // 0 matrices so far in stack
1029
//stack_size can be less then 32! Important for Silicon Vally. Thanks Orkin!
1030
rdp.model_stack_size = min(32, (*(DWORD*)(gfx.DMEM+0x0FE4))>>6);
1031
if (rdp.model_stack_size == 0)
1032
rdp.model_stack_size = 32;
1033
rdp.fb_drawn = rdp.fb_drawn_front = FALSE;
1034
rdp.update = 0x7FFFFFFF; // All but clear cache
1037
rdp.maincimg[1] = rdp.maincimg[0];
1038
rdp.skip_drawing = FALSE;
1039
rdp.s2dex_tex_loaded = FALSE;
1040
fbreads_front = fbreads_back = 0;
1041
rdp.fog_multiplier = rdp.fog_offset = 0;
1044
if (cpu_fb_write == TRUE)
1045
DrawFrameBufferToScreen();
1046
cpu_fb_write = FALSE;
1047
cpu_fb_read_called = FALSE;
1048
cpu_fb_write_called = FALSE;
1049
cpu_fb_ignore = FALSE;
1055
//analize possible frame buffer usage
1056
if (settings.fb_smart)
1057
DetectFrameBufferUsage();
1058
if (!settings.lego || rdp.num_of_ci > 1)
1060
//* End of set states *//
1063
// Get the start of the display list and the length of it
1064
DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0);
1065
DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4);
1066
FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_lenght: %d\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length);
1067
FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG);
1069
if (settings.tonic && dlist_length < 16)
1072
FRDP_E("DLIST is too short!\n");
1076
// Start executing at the start of the display list
1078
rdp.pc[rdp.pc_i] = dlist_start;
1083
// catches exceptions so that it doesn't freeze
1084
#ifdef CATCH_EXCEPTIONS
1088
// MAIN PROCESSING LOOP
1091
// Get the address of the next command
1092
a = rdp.pc[rdp.pc_i] & BMASK;
1094
// Load the next command and its input
1095
rdp.cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit
1096
rdp.cmd1 = ((DWORD*)gfx.RDRAM)[(a>>2)+1]; // /
1097
// cmd2 and cmd3 are filled only when needed, by the function that needs them
1099
// Output the address before the command
1101
FRDP ("%08lx (c0:%08lx, c1:%08lx): ", a, rdp.cmd0, rdp.cmd1);
1103
FRDP ("%08lx: ", a);
1106
// Go to the next instruction
1107
rdp.pc[rdp.pc_i] = (a+8) & BMASK;
1110
QueryPerformanceCounter ((LARGE_INTEGER*)&perf_cur);
1112
// Process this instruction
1113
gfx_instruction[settings.ucode][rdp.cmd0>>24] ();
1116
if (rdp.dl_count != -1)
1119
if (rdp.dl_count == 0)
1123
RDP ("End of DL\n");
1129
QueryPerformanceCounter ((LARGE_INTEGER*)&perf_next);
1130
__int64 t = perf_next-perf_cur;
1131
sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, t);
1135
} while (!rdp.halt);
1136
#ifdef CATCH_EXCEPTIONS
1139
if (fullscreen) ReleaseGfx ();
1141
if (MessageBox (gfx.hWnd, "The GFX plugin caused an exception and has been disabled.\nWould you like to turn it back on and attempt to continue?", "Glide64 Exception", MB_YESNO|MB_ICONEXCLAMATION) == IDNO)
1144
if (messagebox("Glide64 Exception", MB_YESNO|MB_ICONEXCLAMATION, "The GFX plugin caused an exception and has been disabled.\nWould you like to turn it back on and attempt to continue?") == 2)
1150
if (settings.fb_smart)
1152
rdp.scale_x = rdp.scale_x_bak;
1153
rdp.scale_y = rdp.scale_y_bak;
1155
if (settings.fb_read_always)
1161
DrawYUVImageToFrameBuffer();
1162
rdp.yuv_image = FALSE;
1163
// FRDP("yuv image draw. ul_x: %f, ul_y: %f, lr_x: %f, lr_y: %f, begin: %08lx\n",
1164
// rdp.yuv_ul_x, rdp.yuv_ul_y, rdp.yuv_lr_x, rdp.yuv_lr_y, rdp.yuv_im_begin);
1165
rdp.yuv_ul_x = rdp.yuv_ul_y = rdp.yuv_lr_x = rdp.yuv_lr_y = 0;
1166
rdp.yuv_im_begin = 0x00FFFFFF;
1169
CloseTextureBuffer(rdp.read_whole_frame && (settings.PM || rdp.swap_ci_index >= 0));
1171
if (settings.TGR2 && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET)
1176
RDP("ProcessDList end\n");
1179
// undef - undefined instruction, always ignore
1182
FRDP_E("** undefined ** (%08lx)\n", rdp.cmd0);
1183
FRDP("** undefined ** (%08lx) - IGNORED\n", rdp.cmd0);
1184
#ifdef _FINAL_RELEASE_
1185
*gfx.MI_INTR_REG |= 0x20;
1186
gfx.CheckInterrupts();
1191
// spnoop - no operation, always ignore
1192
static void spnoop()
1197
// noop - no operation, always ignore
1198
static void rdp_noop()
1203
static void ys_memrect ()
1205
DWORD tile = (WORD)((rdp.cmd1 & 0x07000000) >> 24);
1207
DWORD lr_x = (WORD)((rdp.cmd0 & 0x00FFF000) >> 14);
1208
DWORD lr_y = (WORD)((rdp.cmd0 & 0x00000FFF) >> 2);
1209
DWORD ul_x = (WORD)((rdp.cmd1 & 0x00FFF000) >> 14);
1210
DWORD ul_y = (WORD)((rdp.cmd1 & 0x00000FFF) >> 2);
1212
rdp.pc[rdp.pc_i] += 16; // texrect is 196-bit
1214
if (lr_y > rdp.scissor_o.lr_y) lr_y = rdp.scissor_o.lr_y;
1216
FRDP ("memrect (%d, %d, %d, %d), ci_width: %d\n", ul_x, ul_y, lr_x, lr_y, rdp.ci_width);
1218
DWORD y, width = lr_x - ul_x;
1219
DWORD texaddr = rdp.addr[rdp.tiles[tile].t_mem];
1220
DWORD tex_width = rdp.tiles[tile].line << 3;
1222
for (y = ul_y; y < lr_y; y++) {
1223
BYTE *src = gfx.RDRAM + texaddr + (y - ul_y) * tex_width;
1224
BYTE *dst = gfx.RDRAM + rdp.cimg + ul_x + y * rdp.ci_width;
1225
memcpy (dst, src, width);
1229
static void pm_palette_mod ()
1231
BYTE envr = (BYTE)((float)((rdp.env_color >> 24)&0xFF)/255.0f*31.0f);
1232
BYTE envg = (BYTE)((float)((rdp.env_color >> 16)&0xFF)/255.0f*31.0f);
1233
BYTE envb = (BYTE)((float)((rdp.env_color >> 8)&0xFF)/255.0f*31.0f);
1234
WORD env16 = (WORD)((envr<<11)|(envg<<6)|(envb<<1)|1);
1235
BYTE prmr = (BYTE)((float)((rdp.prim_color >> 24)&0xFF)/255.0f*31.0f);
1236
BYTE prmg = (BYTE)((float)((rdp.prim_color >> 16)&0xFF)/255.0f*31.0f);
1237
BYTE prmb = (BYTE)((float)((rdp.prim_color >> 8)&0xFF)/255.0f*31.0f);
1238
WORD prim16 = (WORD)((prmr<<11)|(prmg<<6)|(prmb<<1)|1);
1239
WORD * dst = (WORD*)(gfx.RDRAM+rdp.cimg);
1240
for (int i = 0; i < 16; i++)
1242
dst[i^1] = (rdp.pal_8[i]&1) ? prim16 : env16;
1244
RDP("Texrect palette modification\n");
1247
static void rdp_texrect()
1249
DWORD a = rdp.pc[rdp.pc_i];
1250
rdp.cmd2 = ((DWORD*)gfx.RDRAM)[(a>>2)+1];
1251
rdp.cmd3 = ((DWORD*)gfx.RDRAM)[(a>>2)+3];
1253
if (settings.ASB) //modified Rice's hack for All-Star Baseball games
1255
DWORD dwHalf1 = (((DWORD*)gfx.RDRAM)[(a>>2)+0]) >> 24;
1256
if ((dwHalf1 != 0xF1) && (dwHalf1 != 0xb3))
1258
rdp.pc[rdp.pc_i] += 16;
1262
rdp.pc[rdp.pc_i] += 8;
1263
rdp.cmd3 = rdp.cmd2;
1267
else if (settings.yoshi && settings.ucode == 6)
1274
rdp.pc[rdp.pc_i] += 16; // texrect is 196-bit
1277
if (rdp.skip_drawing || (!settings.fb_smart && (rdp.cimg == rdp.zimg)))
1279
if (settings.PM && rdp.ci_status == ci_useless)
1285
RDP("Texrect skipped\n");
1290
if ((settings.ucode == 8) && rdp.cur_image && rdp.cur_image->format)
1292
//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);
1293
RDP("Shadow texrect is skipped.\n");
1298
WORD ul_x = (WORD)((rdp.cmd1 & 0x00FFF000) >> 14);
1299
WORD ul_y = (WORD)((rdp.cmd1 & 0x00000FFF) >> 2);
1300
WORD lr_x = (WORD)((rdp.cmd0 & 0x00FFF000) >> 14);
1301
WORD lr_y = (WORD)((rdp.cmd0 & 0x00000FFF) >> 2);
1302
if (ul_x >= lr_x) return;
1303
if (rdp.cycle_mode > 1 || settings.increase_texrect_edge)
1314
if (rdp.hires_tex && settings.fb_optimize_texrect)
1316
if (!rdp.hires_tex->drawn)
1320
d.imageW = (WORD)rdp.hires_tex->width;
1322
d.frameW = (WORD)(rdp.hires_tex->width);//(WORD)(ul_x + rdp.hires_tex->width);//lr_x;
1325
d.imageH = (WORD)rdp.hires_tex->height;
1327
d.frameH = (WORD)(rdp.hires_tex->height);//(ul_y + rdp.hires_tex->height);
1328
FRDP("texrect. ul_x: %d, ul_y: %d, lr_x: %d, lr_y: %d, width: %d, height: %d\n", ul_x, ul_y, lr_x, lr_y, rdp.hires_tex->width, rdp.hires_tex->height);
1331
DrawHiresImage(&d, rdp.hires_tex->width == rdp.ci_width);
1332
rdp.hires_tex->drawn = TRUE;
1337
// framebuffer workaround for Zelda: MM LOT
1338
if ((rdp.othermode_l & 0xFFFF0000) == 0x0f5a0000)
1342
//hack for Zelda MM. it removes black texrects which cover all geometry in "Link meets Zelda" cut scene
1343
if (settings.zelda && rdp.timg.addr >= rdp.cimg && rdp.timg.addr < rdp.ci_end)
1345
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);
1350
//hack for Banjo2. it removes black texrects under Banjo
1351
if (!settings.fb_hires && ((rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF)) == 0xFFFFFFFF && (rdp.othermode_l & 0xFFFF0000) == 0x00500000)
1358
//remove motion blur in night vision
1359
if ((settings.ucode == 7) && (rdp.maincimg[1].addr != rdp.maincimg[0].addr) && (rdp.timg.addr >= rdp.maincimg[1].addr) && (rdp.timg.addr < (rdp.maincimg[1].addr+rdp.ci_width*rdp.ci_height*rdp.ci_size)))
1361
if (settings.fb_smart)
1362
if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self || !settings.fb_motionblur)
1364
// 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);
1365
RDP("Wrong Texrect.\n");
1374
DWORD tile = (WORD)((rdp.cmd1 & 0x07000000) >> 24);
1376
// update MUST be at the beginning, b/c of update_scissor
1377
if (rdp.cycle_mode == 2)
1380
rdp.allow_combine = 0;
1382
cmb.tmu1_func = cmb.tmu0_func = GR_COMBINE_FUNCTION_LOCAL;
1383
cmb.tmu1_fac = cmb.tmu0_fac = GR_COMBINE_FACTOR_NONE;
1384
cmb.tmu1_a_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_LOCAL;
1385
cmb.tmu1_a_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_NONE;
1386
cmb.tmu1_invert = cmb.tmu0_invert = FXFALSE;
1387
cmb.tmu1_a_invert = cmb.tmu0_a_invert = FXFALSE;
1392
DWORD prev_tile = rdp.cur_tile;
1393
rdp.cur_tile = tile;
1394
rdp.update |= UPDATE_COMBINE;
1398
rdp.allow_combine = 1;
1400
if (!rdp.cur_cache[0])
1402
rdp.cur_tile = prev_tile;
1407
// ** Texrect offset by Gugaman **
1408
float off_x = (float)((short)((rdp.cmd2 & 0xFFFF0000) >> 16)) / 32.0f;
1409
if ((int(off_x) == 512) && (rdp.timg.width < 512)) off_x = 0.0f;
1410
float off_y = (float)((short)(rdp.cmd2 & 0x0000FFFF)) / 32.0f;
1411
float dsdx = (float)((short)((rdp.cmd3 & 0xFFFF0000) >> 16)) / 1024.0f;
1412
float dtdy = (float)((short)(rdp.cmd3 & 0x0000FFFF)) / 1024.0f;
1414
if (rdp.cycle_mode == 2) dsdx /= 4.0f;
1416
float s_ul_x = ul_x * rdp.scale_x + rdp.offset_x;
1417
float s_lr_x = lr_x * rdp.scale_x + rdp.offset_x;
1418
float s_ul_y = ul_y * rdp.scale_y + rdp.offset_y;
1419
float s_lr_y = lr_y * rdp.scale_y + rdp.offset_y;
1421
FRDP("texrect (%d, %d, %d, %d), tile: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, tile, rdp.tri_n, rdp.tri_n+1);
1422
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);
1423
FRDP("\toff_x: %f, off_y: %f, dsdx: %f, dtdy: %f\n", off_x, off_y, dsdx, dtdy);
1428
if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip
1430
off_size_x = (float)((lr_y - ul_y - 1) * dsdx);
1431
off_size_y = (float)((lr_x - ul_x - 1) * dtdy);
1435
off_size_x = (float)((lr_x - ul_x - 1) * dsdx);
1436
off_size_y = (float)((lr_y - ul_y - 1) * dtdy);
1439
float lr_u0, lr_v0, ul_u0, ul_v0, lr_u1, lr_v1, ul_u1, ul_v1;
1441
if (rdp.cur_cache[0] && (rdp.tex & 1))
1444
if (rdp.tiles[rdp.cur_tile].shift_s)
1446
if (rdp.tiles[rdp.cur_tile].shift_s > 10)
1447
sx = (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s));
1449
sx = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile].shift_s);
1451
if (rdp.tiles[rdp.cur_tile].shift_t)
1453
if (rdp.tiles[rdp.cur_tile].shift_t > 10)
1454
sy = (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t));
1456
sy = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile].shift_t);
1458
if (rdp.hires_tex && rdp.hires_tex->tile == 0)
1460
off_x += rdp.hires_tex->u_shift;// + rdp.tiles[0].ul_s; //commented for Paper Mario motion blur
1461
off_y += rdp.hires_tex->v_shift;// + rdp.tiles[0].ul_t;
1462
FRDP("hires_tex ul_s: %d, ul_t: %d, off_x: %f, off_y: %f\n", rdp.tiles[0].ul_s, rdp.tiles[0].ul_t, off_x, off_y);
1466
lr_u0 = ul_u0 + off_size_x * sx;
1467
lr_v0 = ul_v0 + off_size_y * sy;
1469
ul_u0 *= rdp.hires_tex->u_scale;
1470
ul_v0 *= rdp.hires_tex->v_scale;
1471
lr_u0 *= rdp.hires_tex->u_scale;
1472
lr_v0 *= rdp.hires_tex->v_scale;
1473
FRDP("hires_tex ul_u0: %f, ul_v0: %f, lr_u0: %f, lr_v0: %f\n", ul_u0, ul_v0, lr_u0, lr_v0);
1480
ul_u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;
1481
ul_v0 -= rdp.tiles[rdp.cur_tile].f_ul_t;
1483
lr_u0 = ul_u0 + off_size_x * sx;
1484
lr_v0 = ul_v0 + off_size_y * sy;
1486
ul_u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * ul_u0;
1487
lr_u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * lr_u0;
1488
ul_v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * ul_v0;
1489
lr_v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * lr_v0;
1494
ul_u0 = ul_v0 = lr_u0 = lr_v0 = 0;
1496
if (rdp.cur_cache[1] && (rdp.tex & 2))
1500
if (rdp.tiles[rdp.cur_tile+1].shift_s)
1502
if (rdp.tiles[rdp.cur_tile+1].shift_s > 10)
1503
sx = (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s));
1505
sx = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile+1].shift_s);
1507
if (rdp.tiles[rdp.cur_tile+1].shift_t)
1509
if (rdp.tiles[rdp.cur_tile+1].shift_t > 10)
1510
sy = 1;//(float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t));
1512
sy = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile+1].shift_t);
1515
if (rdp.hires_tex && rdp.hires_tex->tile == 1)
1517
off_x += rdp.hires_tex->u_shift;// + rdp.tiles[0].ul_s; //commented for Paper Mario motion blur
1518
off_y += rdp.hires_tex->v_shift;// + rdp.tiles[0].ul_t;
1519
FRDP("hires_tex ul_s: %d, ul_t: %d, off_x: %f, off_y: %f\n", rdp.tiles[0].ul_s, rdp.tiles[0].ul_t, off_x, off_y);
1523
lr_u1 = ul_u1 + off_size_x * sx;
1524
lr_v1 = ul_v1 + off_size_y * sy;
1526
ul_u1 *= rdp.hires_tex->u_scale;
1527
ul_v1 *= rdp.hires_tex->v_scale;
1528
lr_u1 *= rdp.hires_tex->u_scale;
1529
lr_v1 *= rdp.hires_tex->v_scale;
1530
FRDP("hires_tex ul_u1: %f, ul_v1: %f, lr_u1: %f, lr_v1: %f\n", ul_u0, ul_v0, lr_u0, lr_v0);
1538
ul_u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s;
1539
ul_v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t;
1541
lr_u1 = ul_u1 + off_size_x * sx;
1542
lr_v1 = ul_v1 + off_size_y * sy;
1544
ul_u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * ul_u1;
1545
lr_u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * lr_u1;
1546
ul_v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * ul_v1;
1547
lr_v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * lr_v1;
1552
ul_u1 = ul_v1 = lr_u1 = lr_v1 = 0;
1554
rdp.cur_tile = prev_tile;
1558
FRDP (" scissor: (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);
1560
CCLIP2 (s_ul_x, s_lr_x, ul_u0, lr_u0, ul_u1, lr_u1, (float)rdp.scissor.ul_x, (float)rdp.scissor.lr_x);
1561
CCLIP2 (s_ul_y, s_lr_y, ul_v0, lr_v0, ul_v1, lr_v1, (float)rdp.scissor.ul_y, (float)rdp.scissor.lr_y);
1562
// CCLIP2 (s_lr_y, s_ul_y, lr_v0, ul_v0, lr_v1, ul_v1, (float)rdp.scissor.ul_y, (float)rdp.scissor.lr_y);
1564
FRDP (" draw at: (%f, %f) -> (%f, %f)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y);
1566
// DO NOT SET CLAMP MODE HERE
1569
if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030)) // othermode check makes sure it
1570
// USES the z-buffer. Otherwise it returns bad (unset) values for lot and telescope
1573
FRDP ("prim_depth = %d\n", rdp.prim_depth);
1575
if (settings.increase_primdepth)
1579
grDepthBufferFunction (GR_CMP_LEQUAL);
1580
rdp.update |= UPDATE_ZBUF_ENABLED;
1584
RDP ("no prim_depth used, using 1.0\n");
1588
{ s_ul_x, s_ul_y, Z, 1.0f, ul_u0, ul_v0, ul_u1, ul_v1, { 0, 0, 0, 0}, 255 },
1589
{ s_lr_x, s_ul_y, Z, 1.0f, lr_u0, ul_v0, lr_u1, ul_v1, { 0, 0, 0, 0}, 255 },
1590
{ s_ul_x, s_lr_y, Z, 1.0f, ul_u0, lr_v0, ul_u1, lr_v1, { 0, 0, 0, 0}, 255 },
1591
{ s_lr_x, s_lr_y, Z, 1.0f, lr_u0, lr_v0, lr_u1, lr_v1, { 0, 0, 0, 0}, 255 } };
1593
if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip
1606
VERTEX *vptr = vstd;
1610
// for (int j =0; j < 4; j++)
1611
// 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);
1614
if (!rdp.hires_tex && rdp.cur_cache[0]->splits != 1)
1616
// ** LARGE TEXTURE HANDLING **
1617
// *VERY* simple algebra for texrects
1618
float min_u, min_x, max_u, max_x;
1619
if (vstd[0].u0 < vstd[1].u0)
1634
int start_u_256, end_u_256;
1636
if (settings.ucode == 7)
1639
end_u_256 = (lr_x - ul_x - 1)>>8;
1643
start_u_256 = (int)min_u >> 8;
1644
end_u_256 = (int)max_u >> 8;
1646
//FRDP(" min_u: %f, max_u: %f start: %d, end: %d\n", min_u, max_u, start_u_256, end_u_256);
1648
int splitheight = rdp.cur_cache[0]->splitheight;
1650
int num_verts_line = 2 + ((end_u_256-start_u_256)<<1);
1651
vnew = new VERTEX [num_verts_line << 1];
1653
n_vertices = num_verts_line << 1;
1657
vnew[0].u0 -= 256.0f * start_u_256;
1658
vnew[0].v0 += splitheight * start_u_256;
1659
vnew[0].u1 -= 256.0f * start_u_256;
1660
vnew[0].v1 += splitheight * start_u_256;
1662
vnew[1].u0 -= 256.0f * start_u_256;
1663
vnew[1].v0 += splitheight * start_u_256;
1664
vnew[1].u1 -= 256.0f * start_u_256;
1665
vnew[1].v1 += splitheight * start_u_256;
1666
vnew[n_vertices-2] = vstd[1];
1667
vnew[n_vertices-2].u0 -= 256.0f * end_u_256;
1668
vnew[n_vertices-2].v0 += splitheight * end_u_256;
1669
vnew[n_vertices-2].u1 -= 256.0f * end_u_256;
1670
vnew[n_vertices-2].v1 += splitheight * end_u_256;
1671
vnew[n_vertices-1] = vstd[3];
1672
vnew[n_vertices-1].u0 -= 256.0f * end_u_256;
1673
vnew[n_vertices-1].v0 += splitheight * end_u_256;
1674
vnew[n_vertices-1].u1 -= 256.0f * end_u_256;
1675
vnew[n_vertices-1].v1 += splitheight * end_u_256;
1677
// find the equation of the line of u,x
1678
float m = (max_x - min_x) / (max_u - min_u); // m = delta x / delta u
1679
float b = min_x - m * min_u; // b = y - m * x
1681
for (i=start_u_256; i<end_u_256; i++)
1683
// Find where x = current 256 multiple
1684
float x = m * ((i<<8)+256) + b;
1686
int vn = 2 + ((i-start_u_256)<<2);
1689
vnew[vn].u0 = 255.5f;
1690
vnew[vn].v0 += (float)splitheight * i;
1691
vnew[vn].u1 = 255.5f;
1692
vnew[vn].v1 += (float)splitheight * i;
1697
vnew[vn].u0 = 255.5f;
1698
vnew[vn].v0 += (float)splitheight * i;
1699
vnew[vn].u1 = 255.5f;
1700
vnew[vn].v1 += (float)splitheight * i;
1703
vnew[vn] = vnew[vn-2];
1705
vnew[vn].v0 += (float)splitheight;
1707
vnew[vn].v1 += (float)splitheight;
1710
vnew[vn] = vnew[vn-2];
1712
vnew[vn].v0 += (float)splitheight;
1714
vnew[vn].v1 += (float)splitheight;
1718
AllowShadeMods (vptr, n_vertices);
1719
for (i=0; i<n_vertices; i++)
1721
VERTEX *z = &vptr[i];
1728
apply_shade_mods (z);
1733
grFogMode (GR_FOG_DISABLE);
1735
grClipWindow (0, 0, settings.res_x, settings.res_y);
1737
grCullMode (GR_CULL_DISABLE);
1739
if (rdp.cycle_mode == 2)
1741
grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
1742
GR_COMBINE_FACTOR_ONE,
1743
GR_COMBINE_LOCAL_NONE,
1744
GR_COMBINE_OTHER_TEXTURE,
1746
grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
1747
GR_COMBINE_FACTOR_ONE,
1748
GR_COMBINE_LOCAL_NONE,
1749
GR_COMBINE_OTHER_TEXTURE,
1751
grAlphaBlendFunction (GR_BLEND_ONE,
1755
if (rdp.othermode_l & 1)
1757
grAlphaTestFunction (GR_CMP_GEQUAL);
1758
grAlphaTestReferenceValue (0x80);
1761
grAlphaTestFunction (GR_CMP_ALWAYS);
1763
rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE;
1766
ConvertCoordsConvert (vptr, n_vertices);
1768
if (settings.wireframe)
1771
grDrawLine (&vstd[0], &vstd[2]);
1772
grDrawLine (&vstd[2], &vstd[1]);
1773
grDrawLine (&vstd[1], &vstd[0]);
1774
grDrawLine (&vstd[2], &vstd[3]);
1775
grDrawLine (&vstd[3], &vstd[1]);
1779
grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, n_vertices, vptr, sizeof(VERTEX));
1788
add_tri (vl, 3, TRI_TEXRECT);
1793
add_tri (vl, 3, TRI_TEXRECT);
1799
if (settings.fog && (rdp.flags & FOG_ENABLED))
1801
grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
1803
rdp.update |= UPDATE_CULL_MODE | UPDATE_VIEWPORT;
1813
static void rdp_loadsync()
1815
RDP("loadsync - ignored\n");
1818
static void rdp_pipesync()
1820
RDP("pipesync - ignored\n");
1823
static void rdp_tilesync()
1825
RDP("tilesync - ignored\n");
1828
static void rdp_fullsync()
1830
// Set an interrupt to allow the game to continue
1831
*gfx.MI_INTR_REG |= 0x20;
1832
gfx.CheckInterrupts();
1836
static void rdp_setkeygb()
1838
RDP_E("setkeygb - IGNORED\n");
1839
RDP("setkeygb - IGNORED\n");
1842
static void rdp_setkeyr()
1844
RDP_E("setkeyr - IGNORED\n");
1845
RDP("setkeyr - IGNORED\n");
1848
static void rdp_setconvert()
1851
rdp.YUV_C0 = 1.1647f ;
1852
rdp.YUV_C1 = 0.79931f ;
1853
rdp.YUV_C2 = -0.1964f ;
1854
rdp.YUV_C3 = -0.40651f;
1855
rdp.YUV_C4 = 1.014f ;
1857
rdp.K5 = (BYTE)(rdp.cmd1&0x1FF);
1858
RDP_E("setconvert - IGNORED\n");
1859
RDP("setconvert - IGNORED\n");
1863
// setscissor - sets the screen clipping rectangle
1866
static void rdp_setscissor()
1868
// clipper resolution is 320x240, scale based on computer resolution
1869
rdp.scissor_o.ul_x = /*min(*/(DWORD)(((rdp.cmd0 & 0x00FFF000) >> 14))/*, 320)*/;
1870
rdp.scissor_o.ul_y = /*min(*/(DWORD)(((rdp.cmd0 & 0x00000FFF) >> 2))/*, 240)*/;
1871
rdp.scissor_o.lr_x = /*min(*/(DWORD)(((rdp.cmd1 & 0x00FFF000) >> 14))/*, 320)*/;
1872
rdp.scissor_o.lr_y = /*min(*/(DWORD)(((rdp.cmd1 & 0x00000FFF) >> 2))/*, 240)*/;
1874
rdp.ci_upper_bound = rdp.scissor_o.ul_y;
1875
rdp.ci_lower_bound = rdp.scissor_o.lr_y;
1877
FRDP("setscissor: (%d,%d) -> (%d,%d)\n", rdp.scissor_o.ul_x, rdp.scissor_o.ul_y,
1878
rdp.scissor_o.lr_x, rdp.scissor_o.lr_y);
1880
rdp.update |= UPDATE_SCISSOR;
1883
static void rdp_setprimdepth()
1885
rdp.prim_depth = (WORD)((rdp.cmd1 >> 16) & 0x7FFF);
1887
FRDP("setprimdepth: %d\n", rdp.prim_depth);
1890
static void rdp_setothermode()
1892
#define F3DEX2_SETOTHERMODE(cmd,sft,len,data) { \
1893
rdp.cmd0 = (cmd<<24) | ((32-(sft)-(len))<<8) | (((len)-1)); \
1895
gfx_instruction[settings.ucode][cmd] (); \
1897
#define SETOTHERMODE(cmd,sft,len,data) { \
1898
rdp.cmd0 = (cmd<<24) | ((sft)<<8) | (len); \
1900
gfx_instruction[settings.ucode][cmd] (); \
1903
RDP("rdp_setothermode\n");
1905
if ((settings.ucode == 2) || (settings.ucode == 8))
1907
int cmd0 = rdp.cmd0;
1908
F3DEX2_SETOTHERMODE(0xE2, 0, 32, rdp.cmd1); // SETOTHERMODE_L
1909
F3DEX2_SETOTHERMODE(0xE3, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H
1913
int cmd0 = rdp.cmd0;
1914
SETOTHERMODE(0xB9, 0, 32, rdp.cmd1); // SETOTHERMODE_L
1915
SETOTHERMODE(0xBA, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H
1919
void load_palette (DWORD addr, WORD start, WORD count)
1921
RDP ("Loading palette... ");
1922
WORD *dpal = rdp.pal_8 + start;
1923
WORD end = start+count;
1924
// WORD *spal = (WORD*)(gfx.RDRAM + (addr & BMASK));
1926
for (WORD i=start; i<end; i++)
1928
*(dpal++) = *(WORD *)(gfx.RDRAM + (addr^2));
1932
FRDP ("%d: %08lx\n", i, *(WORD *)(gfx.RDRAM + (addr^2)));
1936
end = start + (count >> 4);
1937
for (WORD p = start; p < end; p++)
1939
rdp.pal_8_crc[p] = CRC_Calculate( 0xFFFFFFFF, &rdp.pal_8[(p << 4)], 32 );
1941
rdp.pal_256_crc = CRC_Calculate( 0xFFFFFFFF, rdp.pal_8_crc, 64 );
1945
static void rdp_loadtlut()
1947
DWORD tile = (rdp.cmd1 >> 24) & 0x07;
1948
WORD start = rdp.tiles[tile].t_mem - 256; // starting location in the palettes
1949
// WORD start = ((WORD)(rdp.cmd1 >> 2) & 0x3FF) + 1;
1950
WORD count = ((WORD)(rdp.cmd1 >> 14) & 0x3FF) + 1; // number to copy
1952
if (rdp.timg.addr + (count<<1) > BMASK)
1953
count = (WORD)((BMASK - rdp.timg.addr) >> 1);
1955
if (start+count > 256) count = 256-start;
1957
FRDP("loadtlut: tile: %d, start: %d, count: %d, from: %08lx\n", tile, start, count,
1960
load_palette (rdp.timg.addr, start, count);
1962
rdp.timg.addr += count << 1;
1966
static void rdp_settilesize()
1968
DWORD tile = (rdp.cmd1 >> 24) & 0x07;
1969
rdp.last_tile_size = tile;
1971
rdp.tiles[tile].f_ul_s = (float)((rdp.cmd0 >> 12) & 0xFFF) / 4.0f;
1972
rdp.tiles[tile].f_ul_t = (float)(rdp.cmd0 & 0xFFF) / 4.0f;
1974
int ul_s = (((WORD)(rdp.cmd0 >> 14)) & 0x03ff);
1975
int ul_t = (((WORD)(rdp.cmd0 >> 2 )) & 0x03ff);
1976
int lr_s = (((WORD)(rdp.cmd1 >> 14)) & 0x03ff);
1977
int lr_t = (((WORD)(rdp.cmd1 >> 2 )) & 0x03ff);
1979
if (lr_s == 0 && ul_s == 0) //pokemon puzzle league set such tile size
1981
else if (wrong_tile == (int)tile)
1984
if (settings.use_sts1_only)
1986
// ** USE FIRST SETTILESIZE ONLY **
1987
// This option helps certain textures while using the 'Alternate texture size method',
1988
// but may break others. (should help more than break)
1992
// coords in 10.2 format
1993
rdp.tiles[tile].ul_s = ul_s;
1994
rdp.tiles[tile].ul_t = ul_t;
1995
rdp.tiles[tile].lr_s = lr_s;
1996
rdp.tiles[tile].lr_t = lr_t;
2002
// coords in 10.2 format
2003
rdp.tiles[tile].ul_s = ul_s;
2004
rdp.tiles[tile].ul_t = ul_t;
2005
rdp.tiles[tile].lr_s = lr_s;
2006
rdp.tiles[tile].lr_t = lr_t;
2010
if (rdp.tiles[tile].lr_s < rdp.tiles[tile].ul_s) rdp.tiles[tile].lr_s += 0x400;
2011
if (rdp.tiles[tile].lr_t < rdp.tiles[tile].ul_t) rdp.tiles[tile].lr_t += 0x400;
2013
rdp.update |= UPDATE_TEXTURE;
2017
if (tile == 0 && rdp.hires_tex)
2018
//if ((rdp.tiles[tile].size != 2) || ((rdp.timg.width == 1) && (rdp.hires_tex->width != (DWORD)(lr_s+1))))
2019
if (((rdp.tiles[tile].format == 0) && (rdp.tiles[tile].size != 2)) || ((rdp.timg.width == 1) && (rdp.hires_tex->width != (DWORD)(lr_s+1))))
2023
if (rdp.tiles[tile].format == 0 && rdp.hires_tex->format == 0)
2025
if (tile == 1 && (DWORD)rdp.hires_tex->tmu != tile)
2026
SwapTextureBuffer();
2027
rdp.hires_tex->tile = tile;
2028
rdp.hires_tex->info.format = GR_TEXFMT_RGB_565;
2029
FRDP ("hires_tex: tile: %d\n", tile);
2033
rdp.hires_tex->info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
2036
FRDP ("settilesize: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d\n",
2037
tile, ul_s, ul_t, lr_s, lr_t);
2040
static void CopyswapBlock(int *pDst, unsigned int cnt, unsigned int SrcOffs)
2042
// copy and byteswap a block of 8-byte dwords
2043
int rem = SrcOffs & 3;
2046
int *pSrc = (int *) ((uintptr_t) gfx.RDRAM + SrcOffs);
2047
for (unsigned int x = 0; x < cnt; x++)
2058
// set source pointer to 4-byte aligned RDRAM location before the start
2059
int *pSrc = (int *) ((uintptr_t) gfx.RDRAM + (SrcOffs & 0xfffffffc));
2060
// do the first partial 32-bit word
2063
for (int x = 0; x < rem; x++)
2065
for (int x = 4; x > rem; x--)
2067
*((char *) pDst) = s0 & 0xff;
2068
pDst = (int *) ((char *) pDst + 1);
2071
// do one full 32-bit word
2075
// do 'cnt-1' 64-bit dwords
2076
for (unsigned int x = 0; x < cnt-1; x++)
2084
// do last partial 32-bit word
2087
for (; rem > 0; rem--)
2089
*((char *) pDst) = s0 & 0xff;
2090
pDst = (int *) ((char *) pDst + 1);
2096
static void WordswapBlock(int *pDst, unsigned int cnt, unsigned int TileSize)
2098
// Since it's not loading 32-bit textures as the N64 would, 32-bit textures need to
2099
// be swapped by 64-bits, not 32.
2102
// swapblock64 dst, cnt
2103
for (unsigned int x = 0; x < cnt / 2; x++, pDst += 4)
2105
long long s1 = ((long long *) pDst)[0];
2106
long long s2 = ((long long *) pDst)[1];
2107
((long long *) pDst)[0] = s2;
2108
((long long *) pDst)[1] = s1;
2113
// swapblock32 dst, cnt
2114
for (unsigned int x = 0; x < cnt; x++, pDst += 2)
2124
static void rdp_loadblock()
2126
if (rdp.skip_drawing)
2128
RDP("loadblock skipped\n");
2131
DWORD tile = (DWORD)((rdp.cmd1 >> 24) & 0x07);
2132
DWORD dxt = (DWORD)(rdp.cmd1 & 0x0FFF);
2134
rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr;
2136
// ** DXT is used for swapping every other line
2137
/* double fdxt = (double)0x8000000F/(double)((DWORD)(2047/(dxt-1))); // F for error
2138
DWORD _dxt = (DWORD)fdxt;*/
2140
// 0x00000800 -> 0x80000000 (so we can check the sign bit instead of the 11th bit)
2141
DWORD _dxt = dxt << 20;
2143
DWORD addr = segoffset(rdp.timg.addr) & BMASK;
2145
// lr_s specifies number of 64-bit words to copy
2147
WORD ul_s = (WORD)(rdp.cmd0 >> 14) & 0x3FF;
2148
WORD ul_t = (WORD)(rdp.cmd0 >> 2) & 0x3FF;
2149
WORD lr_s = (WORD)(rdp.cmd1 >> 14) & 0x3FF;
2151
rdp.tiles[tile].ul_s = ul_s;
2152
rdp.tiles[tile].ul_t = ul_t;
2153
rdp.tiles[tile].lr_s = lr_s;
2155
rdp.timg.set_by = 0; // load block
2157
// do a quick boundary check before copying to eliminate the possibility for exception
2159
lr_s = 1; // 1 so that it doesn't die on memcpy
2162
if (ul_s+lr_s > 512)
2165
if (addr+(lr_s<<3) > BMASK+1)
2166
lr_s = (WORD)((BMASK-addr)>>3);
2168
DWORD offs = rdp.timg.addr;
2170
if (rdp.tiles[tile].size == 3)
2172
//FIXME: unused? DWORD start_line = 0;
2175
rdp.timg.addr += cnt << 3;
2177
int * pDst = (int *) ((uintptr_t)rdp.tmem+(rdp.tiles[tile].t_mem<<3));
2179
// Load the block from RDRAM and byteswap it as it loads
2180
CopyswapBlock(pDst, cnt, offs);
2182
// now do 32-bit or 64-bit word swapping on every other row of data
2186
// skip over unswapped blocks
2193
} while (!(dxt_accum & 0x80000000));
2194
// count number of blocks to swap
2195
if (cnt == 0) break;
2203
} while (dxt_accum & 0x80000000);
2204
// do 32-bit or 64-bit swap operation on this block
2205
WordswapBlock(pDst, swapcnt, rdp.tiles[tile].size);
2206
pDst += swapcnt * 2;
2209
rdp.update |= UPDATE_TEXTURE;
2211
FRDP ("loadblock: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, dxt: %08lx -> %08lx\n",
2212
tile, ul_s, ul_t, lr_s,
2216
static void rdp_loadtile()
2218
if (rdp.skip_drawing)
2220
rdp.timg.set_by = 1; // load tile
2222
DWORD tile = (DWORD)((rdp.cmd1 >> 24) & 0x07);
2223
if (rdp.tiles[tile].format == 1)
2225
rdp.yuv_image = TRUE;
2226
if (rdp.timg.addr < rdp.yuv_im_begin) rdp.yuv_im_begin = rdp.timg.addr;
2230
rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr;
2232
WORD ul_s = (WORD)((rdp.cmd0 >> 14) & 0x03FF);
2233
WORD ul_t = (WORD)((rdp.cmd0 >> 2 ) & 0x03FF);
2234
WORD lr_s = (WORD)((rdp.cmd1 >> 14) & 0x03FF);
2235
WORD lr_t = (WORD)((rdp.cmd1 >> 2 ) & 0x03FF);
2237
if (lr_s < ul_s || lr_t < ul_t) return;
2239
if (wrong_tile >= 0) //there was a tile with zero length
2241
rdp.tiles[wrong_tile].lr_s = lr_s;
2243
if (rdp.tiles[tile].size > rdp.tiles[wrong_tile].size)
2244
rdp.tiles[wrong_tile].lr_s <<= (rdp.tiles[tile].size - rdp.tiles[wrong_tile].size);
2245
else if (rdp.tiles[tile].size < rdp.tiles[wrong_tile].size)
2246
rdp.tiles[wrong_tile].lr_s >>= (rdp.tiles[wrong_tile].size - rdp.tiles[tile].size);
2247
rdp.tiles[wrong_tile].lr_t = lr_t;
2251
if (rdp.hires_tex)// && (rdp.tiles[tile].format == 0))
2253
FRDP("loadtile: hires_tex ul_s: %d, ul_t:%d\n", ul_s, ul_t);
2254
rdp.hires_tex->tile_uls = ul_s;
2255
rdp.hires_tex->tile_ult = ul_t;
2258
if (settings.tonic && tile == 7)
2260
rdp.tiles[0].ul_s = ul_s;
2261
rdp.tiles[0].ul_t = ul_t;
2262
rdp.tiles[0].lr_s = lr_s;
2263
rdp.tiles[0].lr_t = lr_t;
2266
DWORD height = lr_t - ul_t + 1; // get height
2267
DWORD width = lr_s - ul_s + 1;
2269
DWORD wid_64 = rdp.tiles[tile].line;
2271
// CHEAT: it's very unlikely that it loads more than 1 32-bit texture in one command,
2272
// so i don't bother to write in two different places at once. Just load once with
2273
// twice as much data.
2274
if (rdp.tiles[tile].size == 3)
2277
int line_n = rdp.timg.width;
2278
if (rdp.tiles[tile].size == 0)
2281
line_n <<= (rdp.tiles[tile].size-1);
2283
int offs = ul_t * line_n;
2284
offs += ul_s << rdp.tiles[tile].size >> 1;
2285
offs += rdp.timg.addr;
2286
if ((unsigned int) offs >= BMASK)
2289
// check if points to bad location
2290
DWORD size = width * height;
2291
if (rdp.tiles[tile].size == 0)
2294
size <<= (rdp.tiles[tile].size-1);
2296
if (offs + line_n*height > BMASK)
2297
height = (BMASK - offs) / line_n;
2299
int * pDst = (int *) ((uintptr_t)rdp.tmem+(rdp.tiles[tile].t_mem<<3));
2300
int * pEnd = (int *) ((uintptr_t)rdp.tmem+4096 - (wid_64<<3));
2302
for (unsigned int y = 0; y < height; y++)
2304
if (pDst > pEnd) break;
2305
CopyswapBlock(pDst, wid_64, offs);
2308
WordswapBlock(pDst, wid_64, rdp.tiles[tile].size);
2314
FRDP("loadtile: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d\n", tile,
2315
ul_s, ul_t, lr_s, lr_t);
2318
static void rdp_settile()
2320
tile_set = 1; // used to check if we only load the first settilesize
2324
//rdp.cur_tile_n = (DWORD)((rdp.cmd1 >> 24) & 0x07);
2325
//rdp.cur_tile = &rdp.tiles[rdp.cur_tile_n];
2327
rdp.last_tile = (DWORD)((rdp.cmd1 >> 24) & 0x07);
2328
TILE *tile = &rdp.tiles[rdp.last_tile];
2330
tile->format = (BYTE)((rdp.cmd0 >> 21) & 0x07);
2331
tile->size = (BYTE)((rdp.cmd0 >> 19) & 0x03);
2332
tile->line = (WORD)((rdp.cmd0 >> 9) & 0x01FF);
2333
tile->t_mem = (WORD)(rdp.cmd0 & 0x1FF);
2334
tile->palette = (BYTE)((rdp.cmd1 >> 20) & 0x0F);
2335
tile->clamp_t = (BYTE)((rdp.cmd1 >> 19) & 0x01);
2336
tile->mirror_t = (BYTE)((rdp.cmd1 >> 18) & 0x01);
2337
tile->mask_t = (BYTE)((rdp.cmd1 >> 14) & 0x0F);
2338
tile->shift_t = (BYTE)((rdp.cmd1 >> 10) & 0x0F);
2339
tile->clamp_s = (BYTE)((rdp.cmd1 >> 9) & 0x01);
2340
tile->mirror_s = (BYTE)((rdp.cmd1 >> 8) & 0x01);
2341
tile->mask_s = (BYTE)((rdp.cmd1 >> 4) & 0x0F);
2342
tile->shift_s = (BYTE)(rdp.cmd1 & 0x0F);
2344
rdp.update |= UPDATE_TEXTURE;
2346
FRDP ("settile: tile: %d, format: %s, size: %s, line: %d, "
2347
"t_mem: %08lx, palette: %d, clamp_t/mirror_t: %s, mask_t: %d, "
2348
"shift_t: %d, clamp_s/mirror_s: %s, mask_s: %d, shift_s: %d\n",
2349
rdp.last_tile, str_format[tile->format], str_size[tile->size], tile->line,
2350
tile->t_mem, tile->palette, str_cm[(tile->clamp_t<<1)|tile->mirror_t], tile->mask_t,
2351
tile->shift_t, str_cm[(tile->clamp_s<<1)|tile->mirror_s], tile->mask_s, tile->shift_s);
2355
// fillrect - fills a rectangle
2358
static void rdp_fillrect()
2360
DWORD ul_x = ((rdp.cmd1 & 0x00FFF000) >> 14);
2361
DWORD ul_y = (rdp.cmd1 & 0x00000FFF) >> 2;
2362
DWORD lr_x = ((rdp.cmd0 & 0x00FFF000) >> 14) + 1;
2363
DWORD lr_y = ((rdp.cmd0 & 0x00000FFF) >> 2) + 1;
2364
if ((rdp.cimg == rdp.zimg) || (settings.fb_smart && rdp.frame_buffers[rdp.ci_count-1].status == ci_zimg))
2366
RDP ("Fillrect - cleared the depth buffer\n");
2370
grDepthMask (FXTRUE);
2371
grColorMask (FXFALSE, FXFALSE);
2372
grBufferClear (0, 0, 0xFFFF);
2373
grColorMask (FXTRUE, FXTRUE);
2374
rdp.update |= UPDATE_ZBUF_ENABLED;
2375
if (settings.fb_depth_clear)
2377
ul_x = min(max(ul_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x);
2378
lr_x = min(max(lr_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x);
2379
ul_y = min(max(ul_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y);
2380
lr_y = min(max(lr_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y);
2381
//FIXME:unused? DWORD zi_height = lr_y - ul_y - 1;
2382
// rdp.zi_nb_pixels = rdp.zi_width * zi_height;
2383
rdp.zi_lry = lr_y - 1;
2384
rdp.zi_lrx = lr_x - 1;
2385
// FRDP ("zi_width: %d, zi_height: %d\n", rdp.zi_width, zi_height);
2386
DWORD fillrect_width_in_dwords = (lr_x-ul_x) >> 1;
2387
DWORD zi_width_in_dwords = rdp.zi_width >> 1;
2389
DWORD * dst = (DWORD*)(gfx.RDRAM+rdp.cimg);
2390
dst += ul_y * zi_width_in_dwords;
2391
for (DWORD y = ul_y; y < lr_y; y++)
2393
for (DWORD x = ul_x; x < fillrect_width_in_dwords; x++)
2395
dst[x] = rdp.fill_color;
2397
dst += zi_width_in_dwords;
2404
if (rdp.skip_drawing)
2406
RDP("Fillrect skipped\n");
2413
if ((ul_x > lr_x) || (ul_y > lr_y)) return;
2414
if (settings.bomberman64 && (lr_x == rdp.ci_width) && (rdp.cimg == rdp.ocimg)) //bomberman64 hack
2417
if (rdp.cur_image && (rdp.cur_image->format != 0) && (rdp.cycle_mode == 3) && (rdp.cur_image->width == lr_x))
2419
DWORD color = rdp.fill_color;
2420
color = ((color&1)?0xFF:0) |
2421
((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) |
2422
((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) |
2423
((DWORD)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8);
2424
grDepthMask (FXFALSE);
2425
grBufferClear (color, 0, 0xFFFF);
2426
grDepthMask (FXTRUE);
2427
rdp.update |= UPDATE_ZBUF_ENABLED;
2431
if (settings.decrease_fillrect_edge && rdp.cycle_mode == 0)
2435
FRDP("fillrect (%d,%d) -> (%d,%d), cycle mode: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, rdp.cycle_mode,
2436
rdp.tri_n, rdp.tri_n+1);
2438
FRDP("scissor (%d,%d) -> (%d,%d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x,
2441
// KILL the floating point error with 0.01f
2442
DWORD s_ul_x = (DWORD)min(max(ul_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x);
2443
DWORD s_lr_x = (DWORD)min(max(lr_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x);
2444
DWORD s_ul_y = (DWORD)min(max(ul_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y);
2445
DWORD s_lr_y = (DWORD)min(max(lr_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y);
2447
if (s_lr_x < 0.0f) s_lr_x = 0;
2448
if (s_lr_y < 0.0f) s_lr_y = 0;
2449
if (s_ul_x > (float)settings.res_x) s_ul_x = settings.res_x;
2450
if (s_ul_y > (float)settings.res_y) s_ul_y = settings.res_y;
2452
FRDP (" - %d, %d, %d, %d\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y);
2456
grFogMode (GR_FOG_DISABLE);
2458
grClipWindow (0, 0, settings.res_x, settings.res_y);
2461
if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030))
2463
Z = ScaleZ(rdp.prim_depth);
2464
grDepthBufferFunction (GR_CMP_LEQUAL);
2465
// grDepthMask (FXTRUE);
2466
FRDP ("prim_depth = %d\n", rdp.prim_depth);
2470
grDepthBufferFunction (GR_CMP_ALWAYS);
2471
grDepthMask (FXFALSE);
2472
RDP ("no prim_depth used, using 1.0\n");
2474
// Draw the rectangle
2476
{ (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 },
2477
{ (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 },
2478
{ (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 },
2479
{ (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 } };
2481
if (rdp.cycle_mode == 3)
2483
DWORD color = (settings.fillcolor_fix) ? rdp.fill_color : (rdp.fill_color >> 16);
2485
if (settings.PM && rdp.frame_buffers[rdp.ci_count-1].status == ci_aux)
2487
//background of auxilary frame buffers must have zero alpha.
2488
//make it black, set 0 alpha to plack pixels on frame buffer read
2493
color = ((color&1)?0xFF:0) |
2494
((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) |
2495
((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) |
2496
((DWORD)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8);
2498
grConstantColorValue (color);
2500
grColorCombine (GR_COMBINE_FUNCTION_LOCAL,
2501
GR_COMBINE_FACTOR_NONE,
2502
GR_COMBINE_LOCAL_CONSTANT,
2503
GR_COMBINE_OTHER_NONE,
2506
grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
2507
GR_COMBINE_FACTOR_NONE,
2508
GR_COMBINE_LOCAL_CONSTANT,
2509
GR_COMBINE_OTHER_NONE,
2512
grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);
2514
rdp.update |= UPDATE_COMBINE;
2519
TexCache (); // (to update combiner)
2520
DWORD cmb_mode_c = (rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF);
2521
DWORD cmb_mode_a = (rdp.cycle1 & 0x0FFF0000) | ((rdp.cycle2 >> 16) & 0x00000FFF);
2522
if (cmb_mode_c == 0x9fff9fff || cmb_mode_a == 0x09ff09ff) //shade
2524
AllowShadeMods (v, 4);
2525
for (int k = 0; k < 4; k++)
2526
apply_shade_mods (&v[k]);
2530
grAlphaTestFunction (GR_CMP_ALWAYS);
2531
if (grStippleModeExt)
2532
grStippleModeExt(GR_STIPPLE_DISABLE);
2534
grCullMode(GR_CULL_DISABLE);
2536
if (settings.wireframe)
2539
grDrawLine (&v[0], &v[2]);
2540
grDrawLine (&v[2], &v[1]);
2541
grDrawLine (&v[1], &v[0]);
2542
grDrawLine (&v[2], &v[3]);
2543
grDrawLine (&v[3], &v[1]);
2544
//grDrawLine (&v[1], &v[2]);
2548
grDrawTriangle (&v[0], &v[2], &v[1]);
2549
grDrawTriangle (&v[2], &v[3], &v[1]);
2558
add_tri (v1, 3, TRI_FILLRECT);
2562
add_tri (v1, 3, TRI_FILLRECT);
2568
if (settings.fog && (rdp.flags & FOG_ENABLED))
2570
grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
2573
rdp.update |= UPDATE_CULL_MODE | UPDATE_ALPHA_COMPARE | UPDATE_ZBUF_ENABLED;
2582
// setfillcolor - sets the filling color
2585
static void rdp_setfillcolor()
2587
rdp.fill_color = rdp.cmd1;
2588
rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE;
2590
FRDP("setfillcolor: %08lx\n", rdp.cmd1);
2593
static void rdp_setfogcolor()
2595
rdp.fog_color = rdp.cmd1;
2596
rdp.update |= UPDATE_COMBINE | UPDATE_FOG_ENABLED;
2598
FRDP("setfogcolor - %08lx\n", rdp.cmd1);
2601
static void rdp_setblendcolor()
2603
rdp.blend_color = rdp.cmd1;
2604
rdp.update |= UPDATE_COMBINE;
2606
FRDP("setblendcolor: %08lx\n", rdp.cmd1);
2609
static void rdp_setprimcolor()
2611
rdp.prim_color = rdp.cmd1;
2612
rdp.prim_lodmin = (rdp.cmd0 >> 8) & 0xFF;
2613
rdp.prim_lodfrac = max(rdp.cmd0 & 0xFF, rdp.prim_lodmin);
2614
rdp.update |= UPDATE_COMBINE;
2616
FRDP("setprimcolor: %08lx, lodmin: %d, lodfrac: %d\n", rdp.cmd1, rdp.prim_lodmin,
2620
static void rdp_setenvcolor()
2622
rdp.env_color = rdp.cmd1;
2623
rdp.update |= UPDATE_COMBINE;
2625
FRDP("setenvcolor: %08lx\n", rdp.cmd1);
2628
static void rdp_setcombine()
2630
rdp.c_a0 = (BYTE)((rdp.cmd0 >> 20) & 0xF);
2631
rdp.c_b0 = (BYTE)((rdp.cmd1 >> 28) & 0xF);
2632
rdp.c_c0 = (BYTE)((rdp.cmd0 >> 15) & 0x1F);
2633
rdp.c_d0 = (BYTE)((rdp.cmd1 >> 15) & 0x7);
2634
rdp.c_Aa0 = (BYTE)((rdp.cmd0 >> 12) & 0x7);
2635
rdp.c_Ab0 = (BYTE)((rdp.cmd1 >> 12) & 0x7);
2636
rdp.c_Ac0 = (BYTE)((rdp.cmd0 >> 9) & 0x7);
2637
rdp.c_Ad0 = (BYTE)((rdp.cmd1 >> 9) & 0x7);
2639
rdp.c_a1 = (BYTE)((rdp.cmd0 >> 5) & 0xF);
2640
rdp.c_b1 = (BYTE)((rdp.cmd1 >> 24) & 0xF);
2641
rdp.c_c1 = (BYTE)((rdp.cmd0 >> 0) & 0x1F);
2642
rdp.c_d1 = (BYTE)((rdp.cmd1 >> 6) & 0x7);
2643
rdp.c_Aa1 = (BYTE)((rdp.cmd1 >> 21) & 0x7);
2644
rdp.c_Ab1 = (BYTE)((rdp.cmd1 >> 3) & 0x7);
2645
rdp.c_Ac1 = (BYTE)((rdp.cmd1 >> 18) & 0x7);
2646
rdp.c_Ad1 = (BYTE)((rdp.cmd1 >> 0) & 0x7);
2648
rdp.cycle1 = (rdp.c_a0<<0) | (rdp.c_b0<<4) | (rdp.c_c0<<8) | (rdp.c_d0<<13)|
2649
(rdp.c_Aa0<<16)| (rdp.c_Ab0<<19)| (rdp.c_Ac0<<22)| (rdp.c_Ad0<<25);
2650
rdp.cycle2 = (rdp.c_a1<<0) | (rdp.c_b1<<4) | (rdp.c_c1<<8) | (rdp.c_d1<<13)|
2651
(rdp.c_Aa1<<16)| (rdp.c_Ab1<<19)| (rdp.c_Ac1<<22)| (rdp.c_Ad1<<25);
2653
rdp.update |= UPDATE_COMBINE;
2655
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",
2656
Mode0[rdp.c_a0], Mode1[rdp.c_b0], Mode2[rdp.c_c0], Mode3[rdp.c_d0],
2657
Alpha0[rdp.c_Aa0], Alpha1[rdp.c_Ab0], Alpha2[rdp.c_Ac0], Alpha3[rdp.c_Ad0],
2658
Mode0[rdp.c_a1], Mode1[rdp.c_b1], Mode2[rdp.c_c1], Mode3[rdp.c_d1],
2659
Alpha0[rdp.c_Aa1], Alpha1[rdp.c_Ab1], Alpha2[rdp.c_Ac1], Alpha3[rdp.c_Ad1]);
2663
// settextureimage - sets the source for an image copy
2666
static void rdp_settextureimage()
2668
static const char *format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" };
2669
static const char *size[] = { "4bit", "8bit", "16bit", "32bit" };
2671
rdp.timg.format = (BYTE)((rdp.cmd0 >> 21) & 0x07);
2672
rdp.timg.size = (BYTE)((rdp.cmd0 >> 19) & 0x03);
2673
rdp.timg.width = (WORD)(1 + (rdp.cmd0 & 0x00000FFF));
2674
rdp.timg.addr = segoffset(rdp.cmd1);
2675
rdp.s2dex_tex_loaded = TRUE;
2676
rdp.update |= UPDATE_TEXTURE;
2678
if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self && (rdp.timg.addr >= rdp.cimg) && (rdp.timg.addr < rdp.ci_end))
2684
else if (rdp.frame_buffers[rdp.ci_count].status != ci_copy)
2685
CloseTextureBuffer(TRUE);
2686
rdp.fb_drawn = TRUE;
2690
if (settings.fb_hires) //search this texture among drawn texture buffers
2694
if (rdp.timg.size == 2)
2695
FindTextureBuffer(rdp.timg.addr, rdp.timg.width);
2698
FindTextureBuffer(rdp.timg.addr, rdp.timg.width);
2701
FRDP("settextureimage: format: %s, size: %s, width: %d, addr: %08lx\n",
2702
format[rdp.timg.format], size[rdp.timg.size],
2703
rdp.timg.width, rdp.timg.addr);
2706
static void rdp_setdepthimage()
2708
rdp.zimg = segoffset(rdp.cmd1) & BMASK;
2709
rdp.zi_width = rdp.ci_width;
2710
FRDP("setdepthimage - %08lx\n", rdp.zimg);
2715
static void RestoreScale()
2717
FRDP("Return to original scale: x = %f, y = %f\n", rdp.scale_x_bak, rdp.scale_y_bak);
2718
rdp.scale_x = rdp.scale_x_bak;
2719
rdp.scale_y = rdp.scale_y_bak;
2720
// update_scissor();
2721
rdp.view_scale[0] *= rdp.scale_x;
2722
rdp.view_scale[1] *= rdp.scale_y;
2723
rdp.view_trans[0] *= rdp.scale_x;
2724
rdp.view_trans[1] *= rdp.scale_y;
2725
rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
2729
grDepthMask (FXFALSE);
2730
grBufferClear (0, 0, 0xFFFF);
2731
grDepthMask (FXTRUE);
2736
static DWORD swapped_addr = 0;
2738
static void rdp_setcolorimage()
2740
render_depth_mode = 0;
2741
if (settings.fb_smart && (rdp.num_of_ci < NUMTEXBUF))
2743
COLOR_IMAGE & cur_fb = rdp.frame_buffers[rdp.ci_count];
2744
COLOR_IMAGE & prev_fb = rdp.frame_buffers[rdp.ci_count-1];
2745
COLOR_IMAGE & next_fb = rdp.frame_buffers[rdp.ci_count+1];
2746
switch (cur_fb.status)
2751
if (rdp.ci_count == 0)
2753
if ((rdp.ci_status == ci_aux)) //for PPL
2755
float sx = rdp.scale_x;
2756
float sy = rdp.scale_y;
2763
if (!settings.fb_hires)
2765
if ((rdp.num_of_ci > 1) &&
2766
(next_fb.status == ci_aux) &&
2767
(next_fb.width >= cur_fb.width))
2773
else if (rdp.copy_ci_index && settings.PM) //tidal wave
2774
OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
2776
else if (!rdp.motionblur && settings.fb_hires && !SwapOK && (rdp.ci_count <= rdp.copy_ci_index))
2778
if (next_fb.status == ci_aux_copy)
2779
OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
2781
OpenTextureBuffer(rdp.frame_buffers[rdp.copy_ci_index]);
2783
else if (settings.fb_hires && rdp.read_whole_frame && prev_fb.status == ci_aux)
2785
OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
2787
//else if (rdp.ci_status == ci_aux && !rdp.copy_ci_index)
2788
// CloseTextureBuffer();
2790
rdp.skip_drawing = FALSE;
2795
if (!rdp.motionblur || settings.fb_motionblur)
2797
if (cur_fb.width == rdp.ci_width)
2799
if (CopyTextureBuffer(prev_fb, cur_fb))
2800
// if (CloseTextureBuffer(TRUE))
2804
if (!rdp.fb_drawn || prev_fb.status == ci_copy_self)
2807
rdp.fb_drawn = TRUE;
2809
memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);
2814
CloseTextureBuffer(TRUE);
2819
memset(gfx.RDRAM+cur_fb.addr, 0, cur_fb.width*cur_fb.height*rdp.ci_size);
2821
rdp.skip_drawing = TRUE;
2826
rdp.skip_drawing = FALSE;
2827
if (CloseTextureBuffer(prev_fb.status != ci_aux_copy))
2829
else if (!rdp.fb_drawn)
2832
rdp.fb_drawn = TRUE;
2834
if (settings.fb_hires)
2835
OpenTextureBuffer(cur_fb);
2840
if (!rdp.motionblur || settings.fb_motionblur)
2842
if (cur_fb.width == rdp.ci_width)
2844
memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.maincimg[1].addr, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);
2846
//rdp.skip_drawing = TRUE;
2850
memset(gfx.RDRAM+cur_fb.addr, 0, (cur_fb.width*cur_fb.height)<<rdp.ci_size>>1);
2855
else if (rdp.frame_buffers[rdp.ci_count].status == ci_main_i)
2857
// CopyFrameBuffer ();
2858
rdp.scale_x = rdp.scale_x_bak;
2859
rdp.scale_y = rdp.scale_y_bak;
2860
rdp.skip_drawing = FALSE;
2865
if (!settings.fb_hires && cur_fb.format != 0)
2866
rdp.skip_drawing = TRUE;
2869
rdp.skip_drawing = FALSE;
2870
if (settings.fb_hires && OpenTextureBuffer(cur_fb))
2874
if (cur_fb.format != 0)
2875
rdp.skip_drawing = TRUE;
2876
if (rdp.ci_count == 0)
2878
// if (rdp.num_of_ci > 1)
2884
else if (!settings.fb_hires && (prev_fb.status == ci_main) &&
2885
(prev_fb.width == cur_fb.width)) // for Pokemon Stadium
2889
cur_fb.status = ci_aux;
2894
// Zelda LoT effect save/restore depth buffer
2895
if (cur_fb.addr == rdp.zimg) {
2896
render_depth_mode = 1;
2898
render_depth_mode = 2;
2900
rdp.skip_drawing = TRUE;
2904
rdp.skip_drawing = TRUE;
2907
if (settings.fb_hires && (rdp.ci_count <= rdp.copy_ci_index) && (!SwapOK || settings.swapmode == 2))
2908
OpenTextureBuffer(cur_fb);
2909
rdp.skip_drawing = FALSE;
2911
if (settings.fb_hires)
2915
rdp.cimg = rdp.frame_buffers[rdp.ci_count].addr;
2916
rdp.maincimg[0].addr = rdp.cimg;
2919
OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count]);
2925
rdp.skip_drawing = FALSE;
2928
if ((rdp.ci_count > 0) && (prev_fb.status >= ci_aux)) //for Pokemon Stadium
2930
if (!settings.fb_hires && prev_fb.format == 0)
2933
if (!settings.fb_hires && cur_fb.status == ci_copy)
2935
if (!rdp.motionblur && (rdp.num_of_ci > rdp.ci_count+1) && (next_fb.status != ci_aux))
2940
if (!settings.fb_hires && cur_fb.status == ci_aux)
2942
if (cur_fb.format == 0)
2944
if (settings.PPL && (rdp.scale_x < 1.1f)) //need to put current image back to frame buffer
2946
int width = cur_fb.width;
2947
int height = cur_fb.height;
2948
WORD *ptr_dst = new WORD[width*height];
2949
WORD *ptr_src = (WORD*)(gfx.RDRAM+cur_fb.addr);
2952
for (int y=0; y<height; y++)
2954
for (int x=0; x<width; x++)
2956
c = ((ptr_src[(x + y * width)^1]) >> 1) | 0x8000;
2957
ptr_dst[x + y * width] = c;
2960
grLfbWriteRegion(GR_BUFFER_BACKBUFFER,
2972
else //just clear buffer
2975
grColorMask(FXTRUE, FXTRUE);
2976
grBufferClear (0, 0, 0xFFFF);
2982
if ((cur_fb.status == ci_main) && (rdp.ci_count > 0))
2984
BOOL to_org_res = TRUE;
2985
for (int i = rdp.ci_count + 1; i < rdp.num_of_ci; i++)
2987
if ((rdp.frame_buffers[i].status != ci_main) && (rdp.frame_buffers[i].status != ci_zimg) && (rdp.frame_buffers[i].status != ci_zcopy))
2995
RDP("return to original scale\n");
2996
rdp.scale_x = rdp.scale_x_bak;
2997
rdp.scale_y = rdp.scale_y_bak;
2998
if (settings.fb_hires && !rdp.read_whole_frame)
2999
CloseTextureBuffer();
3001
if (settings.fb_hires && !rdp.read_whole_frame && (prev_fb.status >= ci_aux) && (rdp.ci_count > rdp.copy_ci_index))
3002
CloseTextureBuffer();
3005
rdp.ci_status = cur_fb.status;
3009
rdp.ocimg = rdp.cimg;
3010
rdp.cimg = segoffset(rdp.cmd1) & BMASK;
3011
rdp.ci_width = (rdp.cmd0 & 0xFFF) + 1;
3012
if (settings.fb_smart)
3013
rdp.ci_height = rdp.frame_buffers[rdp.ci_count-1].height;
3014
else if (rdp.ci_width == 32)
3017
rdp.ci_height = rdp.scissor_o.lr_y;
3018
if (rdp.zimg == rdp.cimg)
3020
rdp.zi_width = rdp.ci_width;
3021
// int zi_height = min((int)rdp.zi_width*3/4, (int)rdp.vi_height);
3022
// rdp.zi_words = rdp.zi_width * zi_height;
3024
DWORD format = (rdp.cmd0 >> 21) & 0x7;
3025
rdp.ci_size = (rdp.cmd0 >> 19) & 0x3;
3026
rdp.ci_end = rdp.cimg + ((rdp.ci_width*rdp.ci_height)<<(rdp.ci_size-1));
3027
FRDP("setcolorimage - %08lx, width: %d, height: %d, format: %d, size: %d\n", rdp.cmd1, rdp.ci_width, rdp.ci_height, format, rdp.ci_size);
3028
FRDP("cimg: %08lx, ocimg: %08lx, SwapOK: %d\n", rdp.cimg, rdp.ocimg, SwapOK);
3030
if (format != 0 && !rdp.cur_image) //can't draw into non RGBA buffer
3032
if (settings.fb_hires && rdp.ci_width <= 64)
3033
OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count - 1]);
3034
else if (format > 2)
3035
rdp.skip_drawing = TRUE;
3040
if (!settings.fb_smart)
3041
rdp.skip_drawing = FALSE;
3045
if (settings.swapmode > 0)
3047
if (rdp.zimg == rdp.cimg)
3048
rdp.updatescreen = 1;
3050
BOOL viSwapOK = ((settings.swapmode == 2) && (rdp.vi_org_reg == *gfx.VI_ORIGIN_REG)) ? FALSE : TRUE;
3051
if ((rdp.zimg != rdp.cimg) && (rdp.ocimg != rdp.cimg) && SwapOK && viSwapOK && !rdp.cur_image)
3053
if (settings.fb_smart)
3054
rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index];
3056
rdp.maincimg[0].addr = rdp.cimg;
3057
rdp.last_drawn_ci_addr = (settings.swapmode == 2) ? swapped_addr : rdp.maincimg[0].addr;
3058
swapped_addr = rdp.cimg;
3060
rdp.vi_org_reg = *gfx.VI_ORIGIN_REG;
3062
if (settings.fb_hires)
3064
if (rdp.copy_ci_index && (rdp.frame_buffers[rdp.ci_count-1].status != ci_zimg))
3066
int idx = (rdp.frame_buffers[rdp.ci_count].status == ci_aux_copy) ? rdp.main_ci_index : rdp.copy_ci_index;
3067
FRDP("attempt open tex buffer. status: %s, addr: %08lx\n", CIStatus[rdp.frame_buffers[idx].status], rdp.frame_buffers[idx].addr);
3068
OpenTextureBuffer(rdp.frame_buffers[idx]);
3069
if (rdp.frame_buffers[rdp.copy_ci_index].status == ci_main) //tidal wave
3070
rdp.copy_ci_index = 0;
3072
else if (rdp.read_whole_frame && !rdp.cur_image)
3074
OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
3081
static void rdp_trifill()
3083
RDP_E("trifill - IGNORED\n");
3084
RDP("trifill - IGNORED\n");
3087
static void rdp_trishade()
3089
RDP_E("trishade - IGNORED\n");
3090
RDP("trishade - IGNORED\n");
3093
static void rdp_tritxtr()
3095
RDP_E("tritxtr - IGNORED\n");
3096
RDP("tritxtr - IGNORED\n");
3099
static void rdp_trishadetxtr()
3101
RDP_E("trishadetxtr - IGNORED\n");
3102
RDP("trishadetxtr - IGNORED\n");
3105
static void rdp_trifillz()
3107
RDP_E("trifillz - IGNORED\n");
3108
RDP("trifillz - IGNORED\n");
3111
static void rdp_trishadez()
3113
RDP_E("trishadez - IGNORED\n");
3114
RDP("trishadez - IGNORED\n");
3117
static void rdp_tritxtrz()
3119
RDP_E("tritxtrz - IGNORED\n");
3120
RDP("tritxtrz - IGNORED\n");
3123
static void rdp_trishadetxtrz()
3125
RDP_E("trishadetxtrz - IGNORED\n");
3126
RDP("trishadetxtrz - IGNORED\n");
3129
static void rsp_reserved0()
3131
RDP_E("reserved0 - IGNORED\n");
3132
RDP("reserved0 - IGNORED\n");
3135
static void rsp_reserved1()
3137
RDP("reserved1 - ignored\n");
3140
static void rsp_reserved2()
3145
static void rsp_reserved3()
3147
RDP("reserved3 - ignored\n");
3150
void SetWireframeCol ()
3152
if (!fullscreen) return;
3154
switch (settings.wfmode)
3156
//case 0: // normal colors, don't do anything
3157
case 1: // vertex colors
3158
grColorCombine (GR_COMBINE_FUNCTION_LOCAL,
3159
GR_COMBINE_FACTOR_NONE,
3160
GR_COMBINE_LOCAL_ITERATED,
3161
GR_COMBINE_OTHER_NONE,
3163
grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
3164
GR_COMBINE_FACTOR_NONE,
3165
GR_COMBINE_LOCAL_ITERATED,
3166
GR_COMBINE_OTHER_NONE,
3168
grAlphaBlendFunction (GR_BLEND_ONE,
3172
grTexCombine (GR_TMU0,
3173
GR_COMBINE_FUNCTION_ZERO,
3174
GR_COMBINE_FACTOR_NONE,
3175
GR_COMBINE_FUNCTION_ZERO,
3176
GR_COMBINE_FACTOR_NONE,
3178
grTexCombine (GR_TMU1,
3179
GR_COMBINE_FUNCTION_ZERO,
3180
GR_COMBINE_FACTOR_NONE,
3181
GR_COMBINE_FUNCTION_ZERO,
3182
GR_COMBINE_FACTOR_NONE,
3186
grColorCombine (GR_COMBINE_FUNCTION_LOCAL,
3187
GR_COMBINE_FACTOR_NONE,
3188
GR_COMBINE_LOCAL_CONSTANT,
3189
GR_COMBINE_OTHER_NONE,
3191
grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
3192
GR_COMBINE_FACTOR_NONE,
3193
GR_COMBINE_LOCAL_CONSTANT,
3194
GR_COMBINE_OTHER_NONE,
3196
grConstantColorValue (0xFF0000FF);
3197
grAlphaBlendFunction (GR_BLEND_ONE,
3201
grTexCombine (GR_TMU0,
3202
GR_COMBINE_FUNCTION_ZERO,
3203
GR_COMBINE_FACTOR_NONE,
3204
GR_COMBINE_FUNCTION_ZERO,
3205
GR_COMBINE_FACTOR_NONE,
3207
grTexCombine (GR_TMU1,
3208
GR_COMBINE_FUNCTION_ZERO,
3209
GR_COMBINE_FACTOR_NONE,
3210
GR_COMBINE_FUNCTION_ZERO,
3211
GR_COMBINE_FACTOR_NONE,
3216
grAlphaTestFunction (GR_CMP_ALWAYS);
3217
grCullMode (GR_CULL_DISABLE);
3219
//grDepthBufferFunction (GR_CMP_ALWAYS);
3220
//grDepthMask (FXFALSE);
3222
rdp.update |= UPDATE_COMBINE | UPDATE_ALPHA_COMPARE;
3225
/******************************************************************
3226
Function: FrameBufferRead
3227
Purpose: This function is called to notify the dll that the
3228
frame buffer memory is beening read at the given address.
3229
DLL should copy content from its render buffer to the frame buffer
3231
DLL is responsible to maintain its own frame buffer memory addr list
3232
DLL should copy 4KB block content back to RDRAM frame buffer.
3233
Emulator should not call this function again if other memory
3234
is read within the same 4KB range
3235
input: addr rdram address
3237
size 1 = BYTE, 2 = WORD, 4 = DWORD
3239
*******************************************************************/
3240
EXPORT void CALL FBRead(DWORD addr)
3243
LOG ("FBRead ()\n");
3247
if (cpu_fb_write_called)
3249
cpu_fb_ignore = TRUE;
3250
cpu_fb_write = FALSE;
3253
cpu_fb_read_called = TRUE;
3254
DWORD a = segoffset(addr);
3255
FRDP("FBRead. addr: %08lx\n", a);
3256
if (!rdp.fb_drawn && (a >= rdp.cimg) && (a < rdp.ci_end))
3259
//if (fbreads_back > 2) //&& (rdp.ci_width <= 320))
3262
rdp.fb_drawn = TRUE;
3265
if (!rdp.fb_drawn_front && (a >= rdp.maincimg[1].addr) && (a < rdp.maincimg[1].addr + rdp.ci_width*rdp.ci_height*2))
3268
//if (fbreads_front > 2)//&& (rdp.ci_width <= 320))
3270
DWORD cimg = rdp.cimg;
3271
rdp.cimg = rdp.maincimg[1].addr;
3272
if (settings.fb_smart)
3274
rdp.ci_width = rdp.maincimg[1].width;
3276
DWORD h = rdp.frame_buffers[0].height;
3277
rdp.frame_buffers[0].height = rdp.maincimg[1].height;
3278
CopyFrameBuffer(GR_BUFFER_FRONTBUFFER);
3279
rdp.frame_buffers[0].height = h;
3283
CopyFrameBuffer(GR_BUFFER_FRONTBUFFER);
3286
rdp.fb_drawn_front = TRUE;
3291
/******************************************************************
3292
Function: FrameBufferWriteList
3293
Purpose: This function is called to notify the dll that the
3294
frame buffer has been modified by CPU at the given address.
3295
input: FrameBufferModifyEntry *plist
3296
size = size of the plist, max = 1024
3298
*******************************************************************/
3299
EXPORT void CALL FBWList(FrameBufferModifyEntry *plist, DWORD size)
3301
LOG ("FBWList ()\n");
3302
FRDP("FBWList. size: %d\n", size);
3303
printf("FBWList. size: %d\n", size);
3307
/******************************************************************
3308
Function: FrameBufferWrite
3309
Purpose: This function is called to notify the dll that the
3310
frame buffer has been modified by CPU at the given address.
3311
input: addr rdram address
3313
size 1 = BYTE, 2 = WORD, 4 = DWORD
3315
*******************************************************************/
3316
EXPORT void CALL FBWrite(DWORD addr, DWORD size)
3318
LOG ("FBWrite ()\n");
3321
if (cpu_fb_read_called)
3323
cpu_fb_ignore = TRUE;
3324
cpu_fb_write = FALSE;
3327
cpu_fb_write_called = TRUE;
3328
DWORD a = segoffset(addr);
3329
FRDP("FBWrite. addr: %08lx\n", a);
3330
// ZIGGY : added a test on ci_width, otherwise we crash on zero division below
3331
if (!rdp.ci_width || a < rdp.cimg || a > rdp.ci_end)
3333
cpu_fb_write = TRUE;
3334
DWORD shift_l = (a-rdp.cimg) >> 1;
3335
DWORD shift_r = shift_l+2;
3337
d_ul_x = min(d_ul_x, shift_l%rdp.ci_width);
3338
d_ul_y = min(d_ul_y, shift_l/rdp.ci_width);
3339
d_lr_x = max(d_lr_x, shift_r%rdp.ci_width);
3340
d_lr_y = max(d_lr_y, shift_r/rdp.ci_width);
3344
/************************************************************************
3345
Function: FBGetFrameBufferInfo
3346
Purpose: This function is called by the emulator core to retrieve frame
3347
buffer information from the video plugin in order to be able
3348
to notify the video plugin about CPU frame buffer read/write
3353
= 2 word (16 bit) <-- this is N64 default depth buffer format
3356
when frame buffer information is not available yet, set all values
3357
in the FrameBufferInfo structure to 0
3359
input: FrameBufferInfo pinfo[6]
3360
pinfo is pointed to a FrameBufferInfo structure which to be
3361
filled in by this function
3362
output: Values are return in the FrameBufferInfo structure
3363
Plugin can return up to 6 frame buffer info
3364
************************************************************************/
3373
EXPORT void CALL FBGetFrameBufferInfo(void *p)
3375
LOG ("FBGetFrameBufferInfo ()\n");
3376
FrameBufferInfo * pinfo = (FrameBufferInfo *)p;
3377
memset(pinfo,0,sizeof(FrameBufferInfo)*6);
3378
if (!settings.fb_get_info)
3380
RDP("FBGetFrameBufferInfo ()\n");
3382
if (settings.fb_smart)
3384
pinfo[0].addr = rdp.maincimg[1].addr;
3385
pinfo[0].size = rdp.maincimg[1].size;
3386
pinfo[0].width = rdp.maincimg[1].width;
3387
pinfo[0].height = rdp.maincimg[1].height;
3389
for (int i = 0; i < rdp.num_of_ci && info_index < 6; i++)
3391
COLOR_IMAGE & cur_fb = rdp.frame_buffers[i];
3392
if (cur_fb.status == ci_main || cur_fb.status == ci_copy_self ||
3393
cur_fb.status == ci_old_copy)
3395
pinfo[info_index].addr = cur_fb.addr;
3396
pinfo[info_index].size = cur_fb.size;
3397
pinfo[info_index].width = cur_fb.width;
3398
pinfo[info_index].height = cur_fb.height;
3405
pinfo[0].addr = rdp.maincimg[0].addr;
3406
pinfo[0].size = rdp.ci_size;
3407
pinfo[0].width = rdp.ci_width;
3408
pinfo[0].height = rdp.ci_width*3/4;
3409
pinfo[1].addr = rdp.maincimg[1].addr;
3410
pinfo[1].size = rdp.ci_size;
3411
pinfo[1].width = rdp.ci_width;
3412
pinfo[1].height = rdp.ci_width*3/4;
3417
#include "UcodeFB.h"
3419
void DetectFrameBufferUsage ()
3421
RDP("DetectFrameBufferUsage\n");
3423
DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0);
3425
DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4);
3430
if (settings.PM && (rdp.copy_ci_index || rdp.frame_buffers[rdp.copy_ci_index].status == ci_copy_self))
3432
DWORD ci = rdp.cimg, zi = rdp.zimg; // ci_width = rdp.ci_width;
3433
rdp.main_ci = rdp.main_ci_end = rdp.main_ci_bg = rdp.ci_count = 0;
3434
rdp.main_ci_index = rdp.copy_ci_index = 0;
3437
rdp.motionblur = FALSE;
3438
rdp.main_ci_last_tex_addr = 0;
3439
BOOL previous_ci_was_read = rdp.read_previous_ci;
3440
rdp.read_previous_ci = FALSE;
3441
rdp.read_whole_frame = FALSE;
3442
rdp.swap_ci_index = rdp.black_ci_index = -1;
3445
// Start executing at the start of the display list
3447
rdp.pc[rdp.pc_i] = dlist_start;
3450
rdp.scale_x_bak = rdp.scale_x;
3451
rdp.scale_y_bak = rdp.scale_y;
3453
// MAIN PROCESSING LOOP
3456
// Get the address of the next command
3457
a = rdp.pc[rdp.pc_i] & BMASK;
3459
// Load the next command and its input
3460
rdp.cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit
3461
rdp.cmd1 = ((DWORD*)gfx.RDRAM)[(a>>2)+1]; // /
3463
// Output the address before the command
3465
// Go to the next instruction
3466
rdp.pc[rdp.pc_i] = (a+8) & BMASK;
3468
if ((intptr_t)(gfx_instruction_lite[settings.ucode][rdp.cmd0>>24]))
3469
gfx_instruction_lite[settings.ucode][rdp.cmd0>>24] ();
3472
if (rdp.dl_count != -1)
3475
if (rdp.dl_count == 0)
3479
RDP ("End of DL\n");
3484
} while (!rdp.halt);
3486
if (rdp.ci_count > NUMTEXBUF) //overflow
3490
rdp.num_of_ci = rdp.ci_count;
3491
rdp.scale_x = rdp.scale_x_bak;
3492
rdp.scale_y = rdp.scale_y_bak;
3496
if (rdp.black_ci_index > 0 && rdp.black_ci_index < rdp.copy_ci_index)
3497
rdp.frame_buffers[rdp.black_ci_index].status = ci_main;
3499
if (rdp.frame_buffers[rdp.ci_count-1].status == ci_unknown)
3501
if (rdp.ci_count > 1)
3502
rdp.frame_buffers[rdp.ci_count-1].status = ci_aux;
3504
rdp.frame_buffers[rdp.ci_count-1].status = ci_main;
3507
if ((rdp.frame_buffers[rdp.ci_count-1].status == ci_aux) &&
3508
(rdp.frame_buffers[rdp.main_ci_index].width < 320) &&
3509
(rdp.frame_buffers[rdp.ci_count-1].width > rdp.frame_buffers[rdp.main_ci_index].width))
3511
for (int i = 0; i < rdp.ci_count; i++)
3513
if (rdp.frame_buffers[i].status == ci_main)
3514
rdp.frame_buffers[i].status = ci_aux;
3515
else if (rdp.frame_buffers[i].addr == rdp.frame_buffers[rdp.ci_count-1].addr)
3516
rdp.frame_buffers[i].status = ci_main;
3517
// FRDP("rdp.frame_buffers[%d].status = %d\n", i, rdp.frame_buffers[i].status);
3519
rdp.main_ci_index = rdp.ci_count-1;
3522
BOOL all_zimg = TRUE;
3524
for (i = 0; i < rdp.ci_count; i++)
3526
if (rdp.frame_buffers[i].status != ci_zimg)
3534
for (i = 0; i < rdp.ci_count; i++)
3535
rdp.frame_buffers[i].status = ci_main;
3538
RDP("detect fb final results: \n");
3539
for (i = 0; i < rdp.ci_count; i++)
3541
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);
3546
rdp.num_of_ci = rdp.ci_count;
3547
if (rdp.read_previous_ci && previous_ci_was_read)
3548
if (!settings.fb_hires || !rdp.copy_ci_index)
3549
rdp.motionblur = TRUE;
3550
if (rdp.motionblur || settings.fb_hires || (rdp.frame_buffers[rdp.copy_ci_index].status == ci_aux_copy))
3552
rdp.scale_x = rdp.scale_x_bak;
3553
rdp.scale_y = rdp.scale_y_bak;
3556
if ((rdp.read_previous_ci || previous_ci_was_read) && !rdp.copy_ci_index)
3557
rdp.read_whole_frame = TRUE;
3558
if (rdp.read_whole_frame)
3560
if (settings.fb_hires && !settings.fb_ignore_previous)
3562
if (rdp.swap_ci_index < 0)
3564
rdp.texbufs[0].clear_allowed = rdp.texbufs[0].clear_allowed = TRUE;
3565
OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
3572
if (settings.fb_motionblur)
3575
memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size);
3577
else //if (ci_width == rdp.frame_buffers[rdp.main_ci_index].width)
3579
if (rdp.maincimg[0].height > 65) //for 1080
3581
rdp.cimg = rdp.maincimg[0].addr;
3582
rdp.ci_width = rdp.maincimg[0].width;
3584
DWORD h = rdp.frame_buffers[0].height;
3585
rdp.frame_buffers[0].height = rdp.maincimg[0].height;
3587
rdp.frame_buffers[0].height = h;
3597
if (settings.fb_hires)
3599
for (i = 0; i < num_tmu; i++)
3601
rdp.texbufs[i].clear_allowed = TRUE;
3602
for (int j = 0; j < 256; j++)
3604
rdp.texbufs[i].images[j].drawn = FALSE;
3605
rdp.texbufs[i].images[j].clear = TRUE;
3610
//RDP("Tidal wave!\n");
3611
rdp.copy_ci_index = rdp.main_ci_index;
3615
if (settings.fb_ignore_previous)
3616
rdp.read_whole_frame = FALSE;
3618
rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index];
3619
// rdp.scale_x = rdp.scale_x_bak;
3620
// rdp.scale_y = rdp.scale_y_bak;
3621
RDP("DetectFrameBufferUsage End\n");
3628
/******************************************************************
3629
Function: ProcessRDPList
3630
Purpose: This function is called when there is a Dlist to be
3631
processed. (Low level GFX list)
3634
*******************************************************************/
3635
EXPORT void CALL ProcessRDPList(void)
3639
*gfx.MI_INTR_REG |= 0x20;
3640
gfx.CheckInterrupts();
3642
LOG ("ProcessRDPList ()\n");
3645
update_screen_count = 0;
3649
if (!hhkLowLevelKybd)
3651
hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL,
3652
LowLevelKeyboardProc, hInstance, 0);
3656
LOG ("ProcessDList ()\n");
3660
drawNoFullscreenMessage();
3661
// Set an interrupt to allow the game to continue
3662
*gfx.MI_INTR_REG |= 0x20;
3663
gfx.CheckInterrupts();
3670
memset (microcode, 0, 4096);
3671
if (settings.autodetect_ucode)
3673
// Thanks to ZeZu for ucode autodetection!!!
3675
DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0);
3676
memcpy (microcode, gfx.RDRAM+startUcode, 4096);
3681
else if ( ((old_ucode == 6) && (settings.ucode == 1)) || settings.force_microcheck)
3683
DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0);
3684
memcpy (microcode, gfx.RDRAM+startUcode, 4096);
3688
if (exception) return;
3690
// Switch to fullscreen?
3693
to_fullscreen = FALSE;
3695
if (!InitGfx (FALSE))
3697
LOG ("FAILED!!!\n");
3703
ShowWindow( gfx.hStatusBar, SW_HIDE );
3704
ShowCursor( FALSE );
3708
// Clear out the RDP log
3710
if (settings.logging && settings.log_clear)
3718
if (settings.log_unk && settings.unk_clear)
3720
std::ofstream unimp;
3721
unimp.open("unimp.txt");
3727
if (settings.swapmode > 0)
3729
rdp.updatescreen = 1;
3731
rdp.tri_n = 0; // 0 triangles so far this frame
3734
rdp.model_i = 0; // 0 matrices so far in stack
3735
//stack_size can be less then 32! Important for Silicon Vally. Thanks Orkin!
3736
rdp.model_stack_size = min(32, (*(DWORD*)(gfx.DMEM+0x0FE4))>>6);
3737
if (rdp.model_stack_size == 0)
3738
rdp.model_stack_size = 32;
3739
rdp.fb_drawn = rdp.fb_drawn_front = FALSE;
3740
rdp.update = 0x7FFFFFFF; // All but clear cache
3743
rdp.maincimg[1] = rdp.maincimg[0];
3744
rdp.skip_drawing = FALSE;
3745
rdp.s2dex_tex_loaded = FALSE;
3746
fbreads_front = fbreads_back = 0;
3747
rdp.fog_multiplier = rdp.fog_offset = 0;
3750
if (cpu_fb_write == TRUE)
3751
DrawFrameBufferToScreen();
3752
cpu_fb_write = FALSE;
3753
cpu_fb_read_called = FALSE;
3754
cpu_fb_write_called = FALSE;
3755
cpu_fb_ignore = FALSE;
3761
//analize possible frame buffer usage
3762
if (settings.fb_smart)
3763
DetectFrameBufferUsage();
3764
if (!settings.lego || rdp.num_of_ci > 1)
3766
//* End of set states *//
3769
// Get the start of the display list and the length of it
3770
// DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0);
3771
// DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4);
3772
DWORD dlist_start = *gfx.DPC_CURRENT_REG;
3773
DWORD dlist_length = *gfx.DPC_END_REG - *gfx.DPC_CURRENT_REG;
3774
FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_lenght: %d\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length);
3775
FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG);
3777
if (settings.tonic && dlist_length < 16)
3780
FRDP_E("DLIST is too short!\n");
3784
// Start executing at the start of the display list
3786
rdp.pc[rdp.pc_i] = dlist_start;
3791
// catches exceptions so that it doesn't freeze
3792
#ifdef CATCH_EXCEPTIONS
3796
// MAIN PROCESSING LOOP
3799
// Get the address of the next command
3800
a = rdp.pc[rdp.pc_i] & BMASK;
3802
// Load the next command and its input
3803
rdp.cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit
3804
rdp.cmd1 = ((DWORD*)gfx.RDRAM)[(a>>2)+1]; // /
3805
// cmd2 and cmd3 are filled only when needed, by the function that needs them
3807
// Output the address before the command
3809
FRDP ("%08lx (c0:%08lx, c1:%08lx): ", a, rdp.cmd0, rdp.cmd1);
3811
FRDP ("%08lx: ", a);
3814
// Go to the next instruction
3815
rdp.pc[rdp.pc_i] = (a+8) & BMASK;
3818
QueryPerformanceCounter ((LARGE_INTEGER*)&perf_cur);
3820
// Process this instruction
3821
gfx_instruction[settings.ucode][((rdp.cmd0>>24)&0x3f) + 0x100-0x40] ();
3824
if (rdp.dl_count != -1)
3827
if (rdp.dl_count == 0)
3831
RDP ("End of DL\n");
3837
QueryPerformanceCounter ((LARGE_INTEGER*)&perf_next);
3838
__int64 t = perf_next-perf_cur;
3839
sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, t);
3844
#ifdef CATCH_EXCEPTIONS
3847
if (fullscreen) ReleaseGfx ();
3849
if (MessageBox (gfx.hWnd, "The GFX plugin caused an exception and has been disabled.\nWould you like to turn it back on and attempt to continue?", "Glide64 Exception", MB_YESNO|MB_ICONEXCLAMATION) == IDNO)
3852
if (messagebox("Glide64 Exception", MB_YESNO|MB_ICONEXCLAMATION, "The GFX plugin caused an exception and has been disabled.\nWould you like to turn it back on and attempt to continue?") == 2)
3858
if (settings.fb_smart)
3860
rdp.scale_x = rdp.scale_x_bak;
3861
rdp.scale_y = rdp.scale_y_bak;
3863
if (settings.fb_read_always)
3869
DrawYUVImageToFrameBuffer();
3870
rdp.yuv_image = FALSE;
3871
// FRDP("yuv image draw. ul_x: %f, ul_y: %f, lr_x: %f, lr_y: %f, begin: %08lx\n",
3872
// rdp.yuv_ul_x, rdp.yuv_ul_y, rdp.yuv_lr_x, rdp.yuv_lr_y, rdp.yuv_im_begin);
3873
rdp.yuv_ul_x = rdp.yuv_ul_y = rdp.yuv_lr_x = rdp.yuv_lr_y = 0;
3874
rdp.yuv_im_begin = 0x00FFFFFF;
3877
CloseTextureBuffer(rdp.read_whole_frame && (settings.PM || rdp.swap_ci_index >= 0));
3879
if (settings.TGR2 && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET)
3884
RDP("ProcessDList end\n");
3891
printf("ProcessRPDList %x %x %x\n",
3894
*gfx.DPC_CURRENT_REG);
3895
//*gfx.DPC_STATUS_REG = 0xffffffff; // &= ~0x0002;
3897
*gfx.DPC_START_REG = *gfx.DPC_END_REG;
3898
*gfx.DPC_CURRENT_REG = *gfx.DPC_END_REG;
3906
// Local Variables: ***
3908
// c-file-offset:4 ***