~ubuntu-branches/ubuntu/wily/mupen64plus/wily

« back to all changes in this revision

Viewing changes to glide64/rdp.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sven Eckelmann
  • Date: 2011-07-24 14:23:26 UTC
  • mfrom: (10.1.2 experimental)
  • Revision ID: james.westby@ubuntu.com-20110724142326-x9z5qu8j9jecrmod
Tags: 1.99.4+2
* Upload to unstable
* Remove overrides for lintian warning about change to native package
* Update Vcs-* fields to new anonscm.debian.org URLs in debian/control
* Fix spelling of "Flexible" in debian/control (Closes: #633693)
* Mark all targets in debian/rules as phony
* Add some information about the mupen64plus 2.0 vision in debian/NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
* Glide64 - Glide video plugin for Nintendo 64 emulators.
3
 
* Copyright (c) 2002  Dave2001
4
 
* Copyright (c) 2008  Günther <guenther.emu@freenet.de>
5
 
*
6
 
* This program is free software; you can redistribute it and/or modify
7
 
* it under the terms of the GNU General Public License as published by
8
 
* the Free Software Foundation; either version 2 of the License, or
9
 
* any later version.
10
 
*
11
 
* This program is distributed in the hope that it will be useful,
12
 
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
* GNU General Public License for more details.
15
 
*
16
 
* You should have received a copy of the GNU General Public
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
20
 
*/
21
 
 
22
 
//****************************************************************
23
 
//
24
 
// Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)
25
 
// Project started on December 29th, 2001
26
 
//
27
 
// To modify Glide64:
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.
30
 
//
31
 
// Official Glide64 development channel: #Glide64 on EFnet
32
 
//
33
 
// Original author: Dave2001 (Dave2999@hotmail.com)
34
 
// Other authors: Gonetz, Gugaman
35
 
//
36
 
//****************************************************************
37
 
 
38
 
#include "Gfx1.3.h"
39
 
#include "3dmath.h"
40
 
#include "Util.h"
41
 
#include "Debugger.h"
42
 
#include "Combine.h"
43
 
#include "Util.h"
44
 
#include "Ini.h"
45
 
#include "Tmem.h"
46
 
#include "TexCache.h"
47
 
#include "TexCache.h"
48
 
#include "TexBuffer.h"
49
 
#include "CRC.h"
50
 
 
51
 
#ifndef _WIN32
52
 
#include "messagebox.h"
53
 
#include <sys/time.h>
54
 
#endif // _WIN32
55
 
 
56
 
char out_buf[2048];
57
 
 
58
 
DWORD frame_count;  // frame counter
59
 
 
60
 
BOOL ucode_error_report = TRUE;
61
 
int wrong_tile = -1;
62
 
 
63
 
#if defined(NO_ASM)
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);
67
 
#else
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) : :);
70
 
#endif
71
 
 
72
 
// global strings
73
 
const char *ACmp[4] = { "NONE", "THRESHOLD", "UNKNOWN", "DITHER" };
74
 
 
75
 
const char *Mode0[16] = { "COMBINED",    "TEXEL0",
76
 
            "TEXEL1",     "PRIMITIVE",
77
 
            "SHADE",      "ENVIORNMENT",
78
 
            "1",        "NOISE",
79
 
            "0",        "0",
80
 
            "0",        "0",
81
 
            "0",        "0",
82
 
            "0",        "0" };
83
 
const char *Mode1[16] = { "COMBINED",    "TEXEL0",
84
 
            "TEXEL1",     "PRIMITIVE",
85
 
            "SHADE",      "ENVIORNMENT",
86
 
            "CENTER",     "K4",
87
 
            "0",        "0",
88
 
            "0",        "0",
89
 
            "0",        "0",
90
 
            "0",        "0" };
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",
98
 
            "PRIM_LODFRAC",   "K5",
99
 
            "0",        "0",
100
 
            "0",        "0",
101
 
            "0",        "0",
102
 
            "0",        "0",
103
 
            "0",        "0",
104
 
            "0",        "0",
105
 
            "0",        "0",
106
 
            "0",        "0" };
107
 
const char *Mode3[8] = { "COMBINED",    "TEXEL0",
108
 
            "TEXEL1",     "PRIMITIVE",
109
 
            "SHADE",      "ENVIORNMENT",
110
 
            "1",        "0" };
111
 
 
112
 
const char *Alpha0[8] = { "COMBINED",   "TEXEL0",
113
 
            "TEXEL1",     "PRIMITIVE",
114
 
            "SHADE",      "ENVIORNMENT",
115
 
            "1",        "0" };
116
 
const char *Alpha2[8] = { "LOD_FRACTION", "TEXEL0",
117
 
            "TEXEL1",     "PRIMITIVE",
118
 
            "SHADE",      "ENVIORNMENT",
119
 
            "PRIM_LODFRAC",   "0" };
120
 
 
121
 
//FIXME:unused?
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" };
126
 
 
127
 
const char *str_zs[2] = { "G_ZS_PIXEL", "G_ZS_PRIM" };
128
 
 
129
 
const char *str_yn[2] = { "NO", "YES" };
130
 
const char *str_offon[2] = { "OFF", "ON" };
131
 
 
132
 
const char *str_cull[4] = { "DISABLE", "FRONT", "BACK", "BOTH" };
133
 
 
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" };
138
 
 
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" };
141
 
 
142
 
const char *str_filter[3] = { "Point Sampled", "Average (box)", "Bilinear" };
143
 
 
144
 
const char *str_tlut[4]   = { "TT_NONE", "TT_UNKNOWN", "TT_RGBA_16", "TT_IA_16" };
145
 
 
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" };
149
 
 
150
 
 
151
 
// ZIGGY
152
 
// depth save/restore variables
153
 
// 0 : normal mode
154
 
// 1 : writing in normal depth buffer
155
 
// 2 : writing in alternate depth buffer
156
 
static int render_depth_mode;
157
 
 
158
 
// ** RDP graphics functions **
159
 
static void undef();
160
 
static void spnoop();
161
 
 
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();
198
 
 
199
 
static void rsp_reserved0();
200
 
static void rsp_reserved1();
201
 
static void rsp_reserved2();
202
 
static void rsp_reserved3();
203
 
 
204
 
static void ys_memrect();
205
 
 
206
 
BYTE microcode[4096];
207
 
DWORD uc_crc;
208
 
void microcheck ();
209
 
 
210
 
// ** UCODE FUNCTIONS **
211
 
#include "Ucode00.h"
212
 
#include "ucode01.h"
213
 
#include "ucode02.h"
214
 
#include "ucode03.h"
215
 
#include "ucode04.h"
216
 
#include "ucode05.h"
217
 
#include "ucode06.h"
218
 
#include "ucode07.h"
219
 
#include "ucode08.h"
220
 
#include "ucode.h"
221
 
 
222
 
static BOOL reset = 0;
223
 
static int old_ucode = -1;
224
 
 
225
 
// rdp_reset - resets the RDP_E
226
 
void rdp_reset ()
227
 
{
228
 
    reset = 1;
229
 
    
230
 
    rdp.model_i = 0;
231
 
    
232
 
    rdp.n_cached[0] = 0;
233
 
    rdp.n_cached[1] = 0;
234
 
    rdp.cur_cache[0] = NULL;
235
 
    rdp.cur_cache[1] = NULL;
236
 
  /*
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;
241
 
  */
242
 
    rdp.c_a0  = 0;
243
 
    rdp.c_b0  = 0;
244
 
    rdp.c_c0  = 0;
245
 
    rdp.c_d0  = 0;
246
 
    rdp.c_Aa0 = 0;
247
 
    rdp.c_Ab0 = 0;
248
 
    rdp.c_Ac0 = 0;
249
 
    rdp.c_Ad0 = 0;
250
 
    
251
 
    rdp.c_a1  = 0;
252
 
    rdp.c_b1  = 0;
253
 
    rdp.c_c1  = 0;
254
 
    rdp.c_d1  = 0;
255
 
    rdp.c_Aa1 = 0;
256
 
    rdp.c_Ab1 = 0;
257
 
    rdp.c_Ac1 = 0;
258
 
    rdp.c_Ad1 = 0;
259
 
    
260
 
    // Clear the palette CRC
261
 
    int i;
262
 
    for (i=0; i<16; i++)
263
 
        rdp.pal_8_crc[i] = 0;
264
 
    
265
 
    // Clear the palettes
266
 
    for (i=0; i<256; i++)
267
 
        rdp.pal_8[i] = 0;
268
 
    
269
 
    rdp.tlut_mode = 0;
270
 
    
271
 
    // Clear all segments ** VERY IMPORTANT FOR ZELDA **
272
 
    for (i=0; i<16; i++)
273
 
        rdp.segment[i] = 0;
274
 
    
275
 
    for (i=0; i<512; i++)
276
 
        rdp.addr[i] = 0;
277
 
    
278
 
    // set all vertex numbers
279
 
    for (i=0; i<MAX_VTX; i++)
280
 
        rdp.vtx[i].number = i;
281
 
 
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;
286
 
    rdp.num_lights = 0;
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;
289
 
    rdp.texrecting = 0;
290
 
    rdp.rm = 0;
291
 
    rdp.render_mode_changed = 0;
292
 
    rdp.othermode_h = 0;
293
 
    rdp.othermode_l = 0;
294
 
    
295
 
    rdp.tex_ctr = 0;
296
 
    
297
 
    rdp.tex = 0;
298
 
    
299
 
    rdp.cimg = 0;
300
 
    rdp.ocimg = 0;
301
 
    rdp.zimg = 0;
302
 
    rdp.ci_width = 0;
303
 
    rdp.cycle_mode = 2;
304
 
    
305
 
    rdp.allow_combine = 1;
306
 
    
307
 
  rdp.fog_coord_enabled = FALSE;
308
 
    rdp.skip_drawing = FALSE;
309
 
 
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;
317
 
    rdp.cur_tex_buf = 0;
318
 
  rdp.acc_tex_buf = 0;
319
 
    rdp.cur_image = 0;
320
 
    rdp.hires_tex = 0;
321
 
 
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; 
326
 
#ifdef _WIN32
327
 
    GetAsyncKeyState (VK_BACK);
328
 
    GetAsyncKeyState(0x42);
329
 
    GetAsyncKeyState(0x56);
330
 
    GetAsyncKeyState(0x43);
331
 
#endif // _WIN32
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;
341
 
}
342
 
 
343
 
# define PCEndian
344
 
# ifdef PCEndian
345
 
#  define ByteEndian(address)  (address^3)
346
 
#  define WordEndian(address)  (address^2)
347
 
# endif
348
 
# define _Read8Endian(array, address) (*((BYTE *)(array+ByteEndian(address))))
349
 
__inline static DWORD searchrdram(const char *ct)
350
 
{
351
 
    DWORD pos, pos2;
352
 
    const char *t;
353
 
    t = 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)
357
 
                break;
358
 
            else
359
 
                if (*(t + 1) == 0)
360
 
                    return pos;
361
 
        }
362
 
    }
363
 
    return 0;
364
 
}
365
 
 
366
 
void microcheck ()
367
 
{
368
 
    DWORD i;
369
 
    uc_crc = 0;
370
 
    
371
 
    // Check first 3k of ucode, because the last 1k sometimes contains trash
372
 
    for (i=0; i<3072>>2; i++)
373
 
    {
374
 
        uc_crc += ((DWORD*)microcode)[i];
375
 
    }
376
 
    
377
 
    FRDP_E ("crc: %08lx\n", uc_crc);
378
 
    
379
 
#ifdef LOG_UCODE
380
 
    std::ofstream ucf;
381
 
    ucf.open ("ucode.txt", ios::out | ios::binary);
382
 
    char d;
383
 
    for (i=0; i<0x400000; i++)
384
 
    {
385
 
        d = ((char*)gfx.RDRAM)[i^3];
386
 
        ucf.write (&d, 1);
387
 
    }
388
 
    ucf.close ();
389
 
#endif
390
 
    
391
 
    char str[9];
392
 
  sprintf (str, "%08lx", (unsigned long)uc_crc);
393
 
    
394
 
    INI_Open ();
395
 
    INI_FindSection ("UCODE");
396
 
    FRDP("ucode = %s\n", str);
397
 
    int uc = INI_ReadInt (str, -2, 0);
398
 
    
399
 
    if (uc == -2 && ucode_error_report)
400
 
    {
401
 
        INI_FindSection ("SETTINGS");
402
 
        settings.ucode = INI_ReadInt ("ucode", 0);
403
 
        INI_Close ();
404
 
        
405
 
        ReleaseGfx ();
406
 
        sprintf (out_buf, "Error: uCode crc not found in INI, using currently selected uCode\n\n%08lx", (unsigned long)uc_crc);
407
 
#ifdef _WIN32
408
 
        MessageBox (gfx.hWnd, out_buf, "Error", MB_OK|MB_ICONEXCLAMATION);
409
 
#else // _WIN32
410
 
       messagebox("Error", MB_OK|MB_ICONEXCLAMATION, "%s", out_buf);
411
 
#endif // _WIN32
412
 
        
413
 
        ucode_error_report = FALSE; // don't report any more ucode errors from this game
414
 
    }
415
 
    else if (uc == -1 && ucode_error_report)
416
 
    {
417
 
        INI_FindSection ("SETTINGS");
418
 
        settings.ucode = INI_ReadInt ("ucode", 0);
419
 
        INI_Close ();
420
 
        
421
 
        ReleaseGfx ();
422
 
        sprintf (out_buf, "Error: Unsupported uCode!\n\ncrc: %08lx", (unsigned long)uc_crc);
423
 
#ifdef _WIN32
424
 
        MessageBox (gfx.hWnd, out_buf, "Error", MB_OK|MB_ICONEXCLAMATION);
425
 
#else // _WIN32
426
 
       messagebox("Error", MB_OK|MB_ICONEXCLAMATION, "%s", out_buf);
427
 
#endif // _WIN32
428
 
        
429
 
        ucode_error_report = FALSE; // don't report any more ucode errors from this game
430
 
    }
431
 
    else
432
 
    {
433
 
        old_ucode = settings.ucode;
434
 
        settings.ucode = uc;
435
 
        FRDP("microcheck: old ucode: %d,  new ucode: %d\n", old_ucode, uc);
436
 
        //INI_FindSection ("SETTINGS");
437
 
        //INI_WriteInt ("ucode", uc);
438
 
        INI_Close ();
439
 
    }
440
 
}
441
 
 
442
 
#ifdef _WIN32
443
 
RECT prev_rect;
444
 
#endif // _WIN32
445
 
 
446
 
void drawNoFullscreenMessage()
447
 
{
448
 
    LOG ("drawNoFullscreenMessage ()\n");
449
 
#ifdef _WIN32
450
 
    SIZE str_size;
451
 
    RECT win_rect;
452
 
    HWND active_wnd = GetForegroundWindow ();
453
 
    
454
 
    GetClientRect (gfx.hWnd, &win_rect);
455
 
    if (win_rect.bottom != prev_rect.bottom ||
456
 
        win_rect.right != prev_rect.right ||
457
 
        rdp.window_changed)
458
 
    {
459
 
        rdp.window_changed = FALSE;
460
 
        
461
 
        prev_rect.bottom = win_rect.bottom;
462
 
        prev_rect.right = win_rect.right;
463
 
        
464
 
        HDC hdc = GetDC(gfx.hWnd);
465
 
        SetBkMode (hdc, TRANSPARENT);
466
 
        SetTextColor (hdc, RGB(255,255,255));
467
 
        
468
 
        FillRect (hdc, &win_rect, (HBRUSH)GetStockObject(DKGRAY_BRUSH));
469
 
        
470
 
        win_rect.bottom >>= 1;
471
 
        win_rect.right >>= 1;
472
 
        
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));
477
 
        
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));
482
 
        
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));
487
 
    }
488
 
#endif // _WIN32
489
 
}
490
 
 
491
 
static WORD yuv_to_rgb(BYTE y, BYTE u, BYTE v)
492
 
{
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));
496
 
    r *= 0.125f;
497
 
    g *= 0.125f;
498
 
    b *= 0.125f;
499
 
    //clipping the result
500
 
    if (r > 32) r = 32;
501
 
    if (g > 32) g = 32;
502
 
    if (b > 32) b = 32;
503
 
    if (r < 0) r = 0;
504
 
    if (g < 0) g = 0;
505
 
    if (b < 0) b = 0;
506
 
    
507
 
    WORD c = (WORD)(((WORD)(r) << 11) |
508
 
              ((WORD)(g) << 6) |
509
 
              ((WORD)(b) << 1) | 1);
510
 
    return c;
511
 
}
512
 
 
513
 
static void DrawYUVImageToFrameBuffer()
514
 
{
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)
521
 
  {
522
 
    for (WORD x = 0; x < width; x+=16)
523
 
    {
524
 
       WORD *dst = cimg + x + y * rdp.ci_width;
525
 
       for (WORD h = 0; h < 16; h++)
526
 
       {
527
 
          for (WORD w = 0; w < 8; w++)
528
 
          {
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
531
 
            {
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);
538
 
            }
539
 
          }
540
 
          dst += rdp.ci_width - 16;
541
 
       }
542
 
       mb += 64;  //macro block is 768 bytes long, last 256 bytes are useless
543
 
    }
544
 
  }
545
 
}
546
 
 
547
 
static DWORD d_ul_x, d_ul_y, d_lr_x, d_lr_y;
548
 
 
549
 
typedef struct {
550
 
  int ul_x, ul_y, lr_x, lr_y;
551
 
} FB_PART;
552
 
 
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)
554
 
{
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);
558
 
  WORD c;
559
 
  for (int y=0; y < height; y++)
560
 
  {
561
 
    for (int x=0; x < width; x++)
562
 
    {
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;
565
 
    }
566
 
  }
567
 
 
568
 
  grLfbWriteRegion(GR_BUFFER_BACKBUFFER,
569
 
    scr_ul_x,
570
 
    scr_ul_y,
571
 
    GR_LFB_SRC_FMT_1555,
572
 
    width,
573
 
    height,
574
 
    FXTRUE,
575
 
    width<<1,
576
 
    dst);
577
 
  delete[] dst;
578
 
}
579
 
 
580
 
static void DrawFrameBufferToScreen()
581
 
{
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);
583
 
  if (!fullscreen)
584
 
    return;
585
 
  grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
586
 
    GR_COMBINE_FACTOR_ONE,
587
 
    GR_COMBINE_LOCAL_NONE,
588
 
    GR_COMBINE_OTHER_TEXTURE,
589
 
    FXFALSE);
590
 
  grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
591
 
    GR_COMBINE_FACTOR_ONE,
592
 
    GR_COMBINE_LOCAL_NONE,
593
 
    GR_COMBINE_OTHER_TEXTURE,
594
 
    FXFALSE);
595
 
  grConstantColorValue (0xFFFFFFFF);
596
 
  grAlphaBlendFunction( GR_BLEND_SRC_ALPHA, 
597
 
    GR_BLEND_ONE_MINUS_SRC_ALPHA, 
598
 
    GR_BLEND_ONE, 
599
 
    GR_BLEND_ZERO); 
600
 
  rdp.update |= UPDATE_COMBINE;
601
 
  
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;
609
 
 
610
 
  if (!settings.fb_optimize_write || ((src_width < 33) && (src_height < 33)))
611
 
  {
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);
618
 
    return;
619
 
  }
620
 
 
621
 
  FB_PART parts[8];
622
 
  int p;
623
 
  for (p = 0; p < 8; p++)
624
 
  {
625
 
    parts[p].lr_x = parts[p].lr_y = 0;
626
 
    parts[p].ul_x = parts[p].ul_y = 0xFFFF;
627
 
  }
628
 
 
629
 
  int num_of_parts = 0;
630
 
  int cur_part = 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++)
636
 
  {
637
 
    cur_part = 0;
638
 
    int w = 0;
639
 
    while (w < src_width)
640
 
    {
641
 
      while (w < src_width)
642
 
      {
643
 
        if (src[(w+h*rdp.ci_width)^1] == 0)
644
 
          w++;
645
 
        else
646
 
          break;
647
 
      }
648
 
      if (w == src_width)
649
 
        break;
650
 
      if (num_of_parts == 0) //first part
651
 
      {
652
 
        parts[0].ul_x = w;
653
 
        most_left = w;
654
 
        parts[0].ul_y = h;
655
 
        cur_part = 0;
656
 
      }
657
 
      else if (w < most_left - 2) //new part
658
 
      {
659
 
        parts[num_of_parts].ul_x = w;
660
 
        most_left = w;
661
 
        parts[num_of_parts].ul_y = h;
662
 
        cur_part = num_of_parts;
663
 
        num_of_parts++;
664
 
      }
665
 
      else if (w > most_right + 2) //new part
666
 
      {
667
 
        parts[num_of_parts].ul_x = w;
668
 
        most_right = w;
669
 
        parts[num_of_parts].ul_y = h;
670
 
        cur_part = num_of_parts;
671
 
        num_of_parts++;
672
 
      }
673
 
      else 
674
 
      {
675
 
        for (p = 0; p < num_of_parts; p++)
676
 
        {
677
 
          if ((w >  parts[p].ul_x - 2) && (w < parts[p].lr_x+2))
678
 
          {
679
 
            if (w < parts[p].ul_x) parts[p].ul_x = w;
680
 
            break;
681
 
          }
682
 
        }
683
 
        cur_part = p;
684
 
      }
685
 
      while (w < src_width)
686
 
      {
687
 
        if (src[(w+h*rdp.ci_width)^1] != 0)
688
 
          w++;
689
 
        else
690
 
          break;
691
 
      }
692
 
      if (num_of_parts == 0) //first part
693
 
      {
694
 
        parts[0].lr_x = w;
695
 
        most_right = w;
696
 
        num_of_parts++;
697
 
      }
698
 
      else 
699
 
      {
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;
703
 
      }
704
 
    }
705
 
  }
706
 
  /*
707
 
  for (p = 0; p < num_of_parts; p++)
708
 
  {
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);
710
 
  }
711
 
  */
712
 
  for (p = 0; p < num_of_parts; p++)
713
 
  {
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);
719
 
  }
720
 
  memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size);
721
 
}
722
 
 
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)
728
 
 
729
 
static void CopyFrameBuffer (GrBuffer_t buffer = GR_BUFFER_BACKBUFFER)
730
 
{
731
 
  if (!fullscreen)
732
 
    return;
733
 
  FRDP ("CopyFrameBuffer: %08lx... ", rdp.cimg);
734
 
  
735
 
  // don't bother to write the stuff in asm... the slow part is the read from video card,
736
 
  //   not the copy.
737
 
  
738
 
  int width = rdp.ci_width;//*gfx.VI_WIDTH_REG;
739
 
  int height;
740
 
  if (settings.fb_smart && !settings.PPL)
741
 
  {
742
 
    int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0;
743
 
    height = rdp.frame_buffers[ind].height;
744
 
  }
745
 
  else
746
 
  {
747
 
    height = rdp.ci_lower_bound;
748
 
    if (settings.PPL)
749
 
      height -= rdp.ci_upper_bound;
750
 
  }
751
 
  FRDP ("width: %d, height: %d...  ", width, height);
752
 
  
753
 
  if (rdp.scale_x < 1.1f)
754
 
  {
755
 
    WORD * ptr_src = new WORD[width*height];
756
 
    if (grLfbReadRegion(buffer,
757
 
      0,
758
 
      0,//rdp.ci_upper_bound,
759
 
      width,
760
 
      height,
761
 
      width<<1,
762
 
      ptr_src))
763
 
    {
764
 
      WORD *ptr_dst = (WORD*)(gfx.RDRAM+rdp.cimg);
765
 
      DWORD *ptr_dst32 = (DWORD*)(gfx.RDRAM+rdp.cimg);
766
 
      WORD c;
767
 
      
768
 
      for (int y=0; y<height; y++)
769
 
      {
770
 
        for (int x=0; x<width; x++)
771
 
        {
772
 
          c = ptr_src[x + y * width];
773
 
          if (settings.fb_read_alpha)
774
 
          {
775
 
            if (c > 0)
776
 
              c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;
777
 
          }
778
 
          else
779
 
          {
780
 
            c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;
781
 
          }
782
 
          if (rdp.ci_size == 2)
783
 
            ptr_dst[(x + y * width)^1] = c;
784
 
          else
785
 
            ptr_dst32[x + y * width] = RGBA16TO32(c);
786
 
        }
787
 
      }
788
 
      /*
789
 
      }
790
 
      else //8bit I or CI
791
 
      {
792
 
      BYTE *ptr_dst = (BYTE*)(gfx.RDRAM+rdp.cimg);
793
 
      WORD c;
794
 
      
795
 
        for (int y=0; y<height; y++)
796
 
        {
797
 
        for (int x=0; x<width; x++)
798
 
        {
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);
807
 
        }
808
 
        }
809
 
    }  */
810
 
      RDP ("ReadRegion.  Framebuffer copy complete.\n");
811
 
    }
812
 
    else
813
 
    {
814
 
      RDP ("Framebuffer copy failed.\n");
815
 
    }
816
 
    delete[] ptr_src;
817
 
  }
818
 
  else 
819
 
  {
820
 
    if (rdp.motionblur && settings.fb_hires)
821
 
    {
822
 
      return;
823
 
    }   
824
 
    else
825
 
    {
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);
828
 
      
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);
830
 
      GrLfbInfo_t info;
831
 
      info.size = sizeof(GrLfbInfo_t);
832
 
      
833
 
 
834
 
      // VP 888 disconnected for now
835
 
      if (1||rdp.ci_size <= 2) {
836
 
    if (grLfbLock (GR_LFB_READ_ONLY,
837
 
               buffer,
838
 
               GR_LFBWRITEMODE_565,
839
 
               GR_ORIGIN_UPPER_LEFT,
840
 
               FXFALSE,
841
 
               &info))
842
 
      {
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);
846
 
        WORD c;
847
 
        DWORD stride = info.strideInBytes>>1;
848
 
        
849
 
        BOOL read_alpha = settings.fb_read_alpha;
850
 
        if (settings.PM && rdp.frame_buffers[rdp.ci_count-1].status != ci_aux)
851
 
          read_alpha = FALSE;
852
 
        for (int y=0; y<height; y++)
853
 
          {
854
 
        for (int x=0; x<width; x++)
855
 
          {
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)
859
 
              c = 0;
860
 
            if (rdp.ci_size <= 2)
861
 
              ptr_dst[(x + y * width)^1] = c;
862
 
            else
863
 
              ptr_dst32[x + y * width] = RGBA16TO32(c);
864
 
          }
865
 
          }
866
 
        
867
 
        // Unlock the backbuffer
868
 
        grLfbUnlock (GR_LFB_READ_ONLY, buffer);
869
 
        RDP ("LfbLock.  Framebuffer copy complete.\n");
870
 
      }
871
 
      else
872
 
      {
873
 
        RDP ("Framebuffer copy failed.\n");
874
 
      }
875
 
    printf("erf\n");
876
 
      } else {
877
 
    printf("youhou\n");
878
 
    if (grLfbLock (GR_LFB_READ_ONLY,
879
 
               buffer,
880
 
               GR_LFBWRITEMODE_888,
881
 
               GR_ORIGIN_UPPER_LEFT,
882
 
               FXFALSE,
883
 
               &info))
884
 
      {
885
 
        DWORD *ptr_src = (DWORD*)info.lfbPtr;
886
 
        //FIXME: Why unused?
887
 
        //WORD *ptr_dst = (WORD*)(gfx.RDRAM+rdp.cimg);
888
 
        DWORD *ptr_dst32 = (DWORD*)(gfx.RDRAM+rdp.cimg);
889
 
        DWORD c;
890
 
        DWORD stride = info.strideInBytes>>1;
891
 
        
892
 
        BOOL read_alpha = settings.fb_read_alpha;
893
 
        if (settings.PM && rdp.frame_buffers[rdp.ci_count-1].status != ci_aux)
894
 
          read_alpha = FALSE;
895
 
        for (int y=0; y<height; y++)
896
 
          {
897
 
        for (int x=0; x<width; x++)
898
 
          {
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)
902
 
//            c = 0;
903
 
            ptr_dst32[x + y * width] = c;
904
 
          }
905
 
          }
906
 
        
907
 
        // Unlock the backbuffer
908
 
        grLfbUnlock (GR_LFB_READ_ONLY, buffer);
909
 
        RDP ("LfbLock.  Framebuffer copy complete.\n");
910
 
      }
911
 
      else
912
 
      {
913
 
        RDP ("Framebuffer copy failed.\n");
914
 
      }
915
 
      }
916
 
    }   
917
 
  }
918
 
}
919
 
 
920
 
/******************************************************************
921
 
Function: ProcessDList
922
 
Purpose:  This function is called when there is a Dlist to be
923
 
processed. (High level GFX list)
924
 
input:    none
925
 
output:   none
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;
934
 
BOOL CI_SET = TRUE;
935
 
 
936
 
EXPORT void CALL ProcessDList(void)
937
 
{
938
 
    no_dlist = FALSE;
939
 
  update_screen_count = 0;
940
 
    ChangeSize ();
941
 
    
942
 
#ifdef ALTTAB_FIX
943
 
    if (!hhkLowLevelKybd)
944
 
    {
945
 
        hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL, 
946
 
            LowLevelKeyboardProc, hInstance, 0);
947
 
    }
948
 
#endif
949
 
    
950
 
    LOG ("ProcessDList ()\n");
951
 
    
952
 
    if (!fullscreen)
953
 
  {
954
 
        drawNoFullscreenMessage();
955
 
    // Set an interrupt to allow the game to continue
956
 
    *gfx.MI_INTR_REG |= 0x20;
957
 
    gfx.CheckInterrupts();
958
 
  }
959
 
    
960
 
    if (reset)
961
 
    {
962
 
        reset = 0;
963
 
        
964
 
        memset (microcode, 0, 4096);
965
 
        if (settings.autodetect_ucode)
966
 
        {
967
 
            // Thanks to ZeZu for ucode autodetection!!!
968
 
            
969
 
            DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0);
970
 
            memcpy (microcode, gfx.RDRAM+startUcode, 4096);
971
 
            microcheck ();
972
 
            
973
 
        }
974
 
    }
975
 
  else if ( ((old_ucode == 6) && (settings.ucode == 1)) || settings.force_microcheck)
976
 
    {
977
 
        DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0);
978
 
        memcpy (microcode, gfx.RDRAM+startUcode, 4096);
979
 
        microcheck ();
980
 
    }
981
 
    
982
 
    if (exception) return;
983
 
    
984
 
    // Switch to fullscreen?
985
 
    if (to_fullscreen)
986
 
    {
987
 
        to_fullscreen = FALSE;
988
 
        
989
 
        if (!InitGfx (FALSE))
990
 
        {
991
 
            LOG ("FAILED!!!\n");
992
 
            return;
993
 
        }
994
 
        fullscreen = TRUE;
995
 
#ifdef _WIN32
996
 
        if (gfx.hStatusBar)
997
 
          ShowWindow( gfx.hStatusBar, SW_HIDE );
998
 
        ShowCursor( FALSE );
999
 
#endif // _WIN32
1000
 
    }
1001
 
    
1002
 
    // Clear out the RDP log
1003
 
#ifdef RDP_LOGGING
1004
 
    if (settings.logging && settings.log_clear)
1005
 
    {
1006
 
        CLOSE_RDP_LOG ();
1007
 
        OPEN_RDP_LOG ();
1008
 
    }
1009
 
#endif
1010
 
    
1011
 
#ifdef UNIMP_LOG
1012
 
    if (settings.log_unk && settings.unk_clear)
1013
 
    {
1014
 
        std::ofstream unimp;
1015
 
        unimp.open("unimp.txt");
1016
 
        unimp.close();
1017
 
    }
1018
 
#endif
1019
 
  
1020
 
  //* Set states *//
1021
 
  if (settings.swapmode > 0)
1022
 
    SwapOK = TRUE;
1023
 
  rdp.updatescreen = 1;
1024
 
  
1025
 
    rdp.tri_n = 0;  // 0 triangles so far this frame
1026
 
    rdp.debug_n = 0;
1027
 
    
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
1035
 
    rdp.geom_mode = 0;
1036
 
  rdp.acmp = 0;
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;
1042
 
  rdp.zsrc = 0;
1043
 
    
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;
1050
 
    d_ul_x = 0xffff;
1051
 
    d_ul_y = 0xffff;
1052
 
    d_lr_x = 0;
1053
 
    d_lr_y = 0;
1054
 
    
1055
 
    //analize possible frame buffer usage
1056
 
    if (settings.fb_smart)
1057
 
        DetectFrameBufferUsage();
1058
 
  if (!settings.lego || rdp.num_of_ci > 1)
1059
 
    rdp.last_bg = 0;
1060
 
  //* End of set states *//
1061
 
  
1062
 
    
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);
1068
 
    
1069
 
    if (settings.tonic && dlist_length < 16)
1070
 
    {
1071
 
    rdp_fullsync();
1072
 
        FRDP_E("DLIST is too short!\n");
1073
 
        return;
1074
 
    }
1075
 
    
1076
 
    // Start executing at the start of the display list
1077
 
    rdp.pc_i = 0;
1078
 
    rdp.pc[rdp.pc_i] = dlist_start;
1079
 
    rdp.dl_count = -1;
1080
 
    rdp.halt = 0;
1081
 
  DWORD a;
1082
 
    
1083
 
    // catches exceptions so that it doesn't freeze
1084
 
#ifdef CATCH_EXCEPTIONS
1085
 
    try {
1086
 
#endif
1087
 
        
1088
 
        // MAIN PROCESSING LOOP
1089
 
        do {
1090
 
            
1091
 
            // Get the address of the next command
1092
 
            a = rdp.pc[rdp.pc_i] & BMASK;
1093
 
            
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
1098
 
            
1099
 
            // Output the address before the command
1100
 
#ifdef LOG_COMMANDS
1101
 
            FRDP ("%08lx (c0:%08lx, c1:%08lx): ", a, rdp.cmd0, rdp.cmd1);
1102
 
#else
1103
 
            FRDP ("%08lx: ", a);
1104
 
#endif
1105
 
            
1106
 
            // Go to the next instruction
1107
 
            rdp.pc[rdp.pc_i] = (a+8) & BMASK;
1108
 
            
1109
 
#ifdef PERFORMANCE
1110
 
            QueryPerformanceCounter ((LARGE_INTEGER*)&perf_cur);
1111
 
#endif
1112
 
            // Process this instruction
1113
 
            gfx_instruction[settings.ucode][rdp.cmd0>>24] ();
1114
 
            
1115
 
            // check DL counter
1116
 
            if (rdp.dl_count != -1)
1117
 
            {
1118
 
                rdp.dl_count --;
1119
 
                if (rdp.dl_count == 0)
1120
 
                {
1121
 
                    rdp.dl_count = -1;
1122
 
                    
1123
 
                    RDP ("End of DL\n");
1124
 
                    rdp.pc_i --;
1125
 
                }
1126
 
            }
1127
 
            
1128
 
#ifdef PERFORMANCE
1129
 
            QueryPerformanceCounter ((LARGE_INTEGER*)&perf_next);
1130
 
            __int64 t = perf_next-perf_cur;
1131
 
            sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, t);
1132
 
            rdp_log << out_buf;
1133
 
#endif
1134
 
            
1135
 
        } while (!rdp.halt);
1136
 
#ifdef CATCH_EXCEPTIONS
1137
 
    } catch (...) {
1138
 
        
1139
 
        if (fullscreen) ReleaseGfx ();
1140
 
# ifdef _WIN32
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)
1142
 
            exception = TRUE;
1143
 
# else // _WIN32
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)
1145
 
         exception = TRUE;
1146
 
# endif // _WIN32
1147
 
    }
1148
 
#endif
1149
 
    
1150
 
    if (settings.fb_smart)
1151
 
    {
1152
 
        rdp.scale_x = rdp.scale_x_bak;
1153
 
        rdp.scale_y = rdp.scale_y_bak;
1154
 
    }
1155
 
    if (settings.fb_read_always)
1156
 
    {
1157
 
    CopyFrameBuffer ();
1158
 
    }
1159
 
    if (rdp.yuv_image)
1160
 
    {
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; 
1167
 
    }
1168
 
    if (rdp.cur_image)
1169
 
    CloseTextureBuffer(rdp.read_whole_frame && (settings.PM || rdp.swap_ci_index >= 0));
1170
 
 
1171
 
  if (settings.TGR2 && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET)
1172
 
  {
1173
 
    newSwapBuffers ();
1174
 
    CI_SET = FALSE;
1175
 
  }
1176
 
    RDP("ProcessDList end\n");
1177
 
}
1178
 
 
1179
 
// undef - undefined instruction, always ignore
1180
 
static void undef()
1181
 
{
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();
1187
 
    rdp.halt = 1;
1188
 
  #endif    
1189
 
}
1190
 
 
1191
 
// spnoop - no operation, always ignore
1192
 
static void spnoop()
1193
 
{
1194
 
    RDP("spnoop\n");
1195
 
}
1196
 
 
1197
 
// noop - no operation, always ignore
1198
 
static void rdp_noop()
1199
 
{
1200
 
    RDP("noop\n");
1201
 
}
1202
 
 
1203
 
static void ys_memrect ()
1204
 
{
1205
 
    DWORD tile = (WORD)((rdp.cmd1 & 0x07000000) >> 24);
1206
 
    
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);
1211
 
    
1212
 
    rdp.pc[rdp.pc_i] += 16; // texrect is 196-bit
1213
 
    
1214
 
    if (lr_y > rdp.scissor_o.lr_y) lr_y = rdp.scissor_o.lr_y;
1215
 
    
1216
 
    FRDP ("memrect (%d, %d, %d, %d), ci_width: %d\n", ul_x, ul_y, lr_x, lr_y, rdp.ci_width);
1217
 
    
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;
1221
 
    
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);
1226
 
    }
1227
 
}
1228
 
 
1229
 
static void pm_palette_mod ()
1230
 
{
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++)
1241
 
  {
1242
 
    dst[i^1] = (rdp.pal_8[i]&1) ? prim16 : env16;
1243
 
  }
1244
 
  RDP("Texrect palette modification\n");
1245
 
}
1246
 
 
1247
 
static void rdp_texrect()
1248
 
{
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];
1252
 
 
1253
 
    if (settings.ASB) //modified Rice's hack for All-Star Baseball games
1254
 
    {
1255
 
        DWORD dwHalf1 = (((DWORD*)gfx.RDRAM)[(a>>2)+0]) >> 24;
1256
 
        if ((dwHalf1 != 0xF1)  && (dwHalf1 != 0xb3))
1257
 
        {
1258
 
            rdp.pc[rdp.pc_i] += 16; 
1259
 
        }
1260
 
        else
1261
 
        {
1262
 
            rdp.pc[rdp.pc_i] += 8;
1263
 
            rdp.cmd3 = rdp.cmd2;
1264
 
            rdp.cmd2 = 0;
1265
 
        }
1266
 
    }
1267
 
  else if (settings.yoshi && settings.ucode == 6)
1268
 
  {
1269
 
    ys_memrect();
1270
 
    return;
1271
 
  }
1272
 
    else
1273
 
    {
1274
 
        rdp.pc[rdp.pc_i] += 16; // texrect is 196-bit
1275
 
    }
1276
 
 
1277
 
  if (rdp.skip_drawing || (!settings.fb_smart && (rdp.cimg == rdp.zimg)))
1278
 
  {
1279
 
    if (settings.PM && rdp.ci_status == ci_useless)
1280
 
    {
1281
 
      pm_palette_mod ();
1282
 
    }
1283
 
    else
1284
 
    {
1285
 
        RDP("Texrect skipped\n");
1286
 
    }
1287
 
        return;
1288
 
    }
1289
 
 
1290
 
  if ((settings.ucode == 8) && rdp.cur_image && rdp.cur_image->format)
1291
 
    {
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");
1294
 
        rdp.tri_n += 2;
1295
 
        return;
1296
 
    }
1297
 
 
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)
1304
 
  {
1305
 
    lr_x++;
1306
 
    lr_y++;
1307
 
  }
1308
 
  if (ul_y == lr_y)
1309
 
  {
1310
 
    lr_y ++;
1311
 
  }
1312
 
 
1313
 
  //*   
1314
 
  if (rdp.hires_tex && settings.fb_optimize_texrect)
1315
 
    {
1316
 
       if (!rdp.hires_tex->drawn)
1317
 
       {
1318
 
            DRAWIMAGE d;
1319
 
            d.imageX    = 0;
1320
 
            d.imageW    = (WORD)rdp.hires_tex->width;
1321
 
      d.frameX  = ul_x;
1322
 
            d.frameW    = (WORD)(rdp.hires_tex->width);//(WORD)(ul_x + rdp.hires_tex->width);//lr_x;
1323
 
 
1324
 
            d.imageY    = 0;
1325
 
            d.imageH    = (WORD)rdp.hires_tex->height;
1326
 
      d.frameY  = ul_y;
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);
1329
 
            d.scaleX    = 1.0f;
1330
 
            d.scaleY    = 1.0f;
1331
 
      DrawHiresImage(&d, rdp.hires_tex->width == rdp.ci_width);
1332
 
            rdp.hires_tex->drawn = TRUE;
1333
 
       }
1334
 
       return;
1335
 
    }
1336
 
//*/
1337
 
    // framebuffer workaround for Zelda: MM LOT
1338
 
    if ((rdp.othermode_l & 0xFFFF0000) == 0x0f5a0000)
1339
 
        return;
1340
 
    
1341
 
    /*Gonetz*/
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)
1344
 
    {
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);
1346
 
        rdp.tri_n += 2;
1347
 
        return;
1348
 
    }
1349
 
//* 
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)
1352
 
    {
1353
 
        rdp.tri_n += 2;
1354
 
        return;
1355
 
    }
1356
 
//*/    
1357
 
  //*
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)))
1360
 
    {
1361
 
        if (settings.fb_smart)
1362
 
          if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self || !settings.fb_motionblur)
1363
 
          {
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");
1366
 
            rdp.tri_n += 2;
1367
 
            return;
1368
 
          }
1369
 
    }
1370
 
//*/    
1371
 
 
1372
 
    int i;
1373
 
    
1374
 
    DWORD tile = (WORD)((rdp.cmd1 & 0x07000000) >> 24);
1375
 
    
1376
 
    // update MUST be at the beginning, b/c of update_scissor
1377
 
    if (rdp.cycle_mode == 2)
1378
 
    {
1379
 
        rdp.tex = 1;
1380
 
        rdp.allow_combine = 0;
1381
 
        
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;
1388
 
    }
1389
 
 
1390
 
    rdp.texrecting = 1;
1391
 
    
1392
 
    DWORD prev_tile = rdp.cur_tile;
1393
 
    rdp.cur_tile = tile;
1394
 
    rdp.update |= UPDATE_COMBINE;
1395
 
    update ();
1396
 
    
1397
 
    rdp.texrecting = 0;
1398
 
    rdp.allow_combine = 1;
1399
 
 
1400
 
    if (!rdp.cur_cache[0]) 
1401
 
    {
1402
 
        rdp.cur_tile = prev_tile;
1403
 
        rdp.tri_n += 2;
1404
 
        return;
1405
 
    }
1406
 
    // ****
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;
1413
 
 
1414
 
    if (rdp.cycle_mode == 2) dsdx /= 4.0f;
1415
 
    
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;
1420
 
    
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);
1424
 
    
1425
 
    float off_size_x;
1426
 
    float off_size_y;
1427
 
 
1428
 
    if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip
1429
 
    {
1430
 
      off_size_x = (float)((lr_y - ul_y - 1) * dsdx);
1431
 
      off_size_y = (float)((lr_x - ul_x - 1) * dtdy);
1432
 
    }
1433
 
    else
1434
 
    {
1435
 
      off_size_x = (float)((lr_x - ul_x - 1) * dsdx);
1436
 
      off_size_y = (float)((lr_y - ul_y - 1) * dtdy);
1437
 
    }
1438
 
 
1439
 
    float lr_u0, lr_v0, ul_u0, ul_v0, lr_u1, lr_v1, ul_u1, ul_v1;
1440
 
    
1441
 
    if (rdp.cur_cache[0] && (rdp.tex & 1))
1442
 
    {
1443
 
        float sx=1, sy=1;
1444
 
        if (rdp.tiles[rdp.cur_tile].shift_s)
1445
 
        {
1446
 
            if (rdp.tiles[rdp.cur_tile].shift_s > 10)
1447
 
                sx = (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s));
1448
 
            else
1449
 
                sx = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile].shift_s);
1450
 
        }
1451
 
        if (rdp.tiles[rdp.cur_tile].shift_t)
1452
 
        {
1453
 
            if (rdp.tiles[rdp.cur_tile].shift_t > 10)
1454
 
                sy = (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t));
1455
 
            else
1456
 
                sy = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile].shift_t);
1457
 
        }
1458
 
    if (rdp.hires_tex && rdp.hires_tex->tile == 0)
1459
 
    {
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);
1463
 
        ul_u0 = off_x * sx;
1464
 
        ul_v0 = off_y * sy;
1465
 
        
1466
 
        lr_u0 = ul_u0 + off_size_x * sx;
1467
 
        lr_v0 = ul_v0 + off_size_y * sy;
1468
 
        
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);
1474
 
    }
1475
 
    else
1476
 
    {
1477
 
            ul_u0 = off_x * sx;
1478
 
        ul_v0 = off_y * sy;
1479
 
        
1480
 
        ul_u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;
1481
 
        ul_v0 -= rdp.tiles[rdp.cur_tile].f_ul_t;
1482
 
        
1483
 
        lr_u0 = ul_u0 + off_size_x * sx;
1484
 
        lr_v0 = ul_v0 + off_size_y * sy;
1485
 
        
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;
1490
 
        }
1491
 
    }
1492
 
    else
1493
 
    {
1494
 
        ul_u0 = ul_v0 = lr_u0 = lr_v0 = 0;
1495
 
    }
1496
 
    if (rdp.cur_cache[1] && (rdp.tex & 2))
1497
 
    {
1498
 
        float sx=1, sy=1;
1499
 
        
1500
 
        if (rdp.tiles[rdp.cur_tile+1].shift_s)
1501
 
        {
1502
 
            if (rdp.tiles[rdp.cur_tile+1].shift_s > 10)
1503
 
                sx = (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s));
1504
 
            else
1505
 
                sx = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile+1].shift_s);
1506
 
        }
1507
 
        if (rdp.tiles[rdp.cur_tile+1].shift_t)
1508
 
        {
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));
1511
 
            else
1512
 
                sy = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile+1].shift_t);
1513
 
        }
1514
 
        
1515
 
    if (rdp.hires_tex && rdp.hires_tex->tile == 1)
1516
 
    {
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);
1520
 
            ul_u1 = off_x * sx;
1521
 
        ul_v1 = off_y * sy;
1522
 
        
1523
 
        lr_u1 = ul_u1 + off_size_x * sx;
1524
 
        lr_v1 = ul_v1 + off_size_y * sy;
1525
 
        
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);
1531
 
        
1532
 
    }
1533
 
    else
1534
 
    {
1535
 
        ul_u1 = off_x * sx;
1536
 
        ul_v1 = off_y * sy;
1537
 
        
1538
 
        ul_u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s;
1539
 
        ul_v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t;
1540
 
        
1541
 
        lr_u1 = ul_u1 + off_size_x * sx;
1542
 
        lr_v1 = ul_v1 + off_size_y * sy;
1543
 
        
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;
1548
 
    }
1549
 
  }
1550
 
    else
1551
 
    {
1552
 
        ul_u1 = ul_v1 = lr_u1 = lr_v1 = 0;
1553
 
    }
1554
 
    rdp.cur_tile = prev_tile;
1555
 
 
1556
 
    // ****
1557
 
    
1558
 
    FRDP ("  scissor: (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);
1559
 
    
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);
1563
 
    
1564
 
    FRDP ("  draw at: (%f, %f) -> (%f, %f)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y);
1565
 
    
1566
 
    // DO NOT SET CLAMP MODE HERE
1567
 
    
1568
 
    float Z = 1.0f;
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
1571
 
        //in zelda:mm.
1572
 
    {
1573
 
            FRDP ("prim_depth = %d\n", rdp.prim_depth);
1574
 
        Z = rdp.prim_depth;
1575
 
    if (settings.increase_primdepth)
1576
 
          Z += 8.0f;
1577
 
    Z = ScaleZ(Z);
1578
 
 
1579
 
            grDepthBufferFunction (GR_CMP_LEQUAL);
1580
 
            rdp.update |= UPDATE_ZBUF_ENABLED;
1581
 
        }
1582
 
    else
1583
 
    {
1584
 
        RDP ("no prim_depth used, using 1.0\n");
1585
 
    }
1586
 
    
1587
 
    VERTEX vstd[4] = {
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 } };
1592
 
        
1593
 
        if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip
1594
 
        {
1595
 
            vstd[1].u0 = ul_u0;
1596
 
            vstd[1].v0 = lr_v0;
1597
 
            vstd[1].u1 = ul_u1;
1598
 
            vstd[1].v1 = lr_v1;
1599
 
            
1600
 
            vstd[2].u0 = lr_u0;
1601
 
            vstd[2].v0 = ul_v0;
1602
 
            vstd[2].u1 = lr_u1;
1603
 
            vstd[2].v1 = ul_v1;
1604
 
        }
1605
 
 
1606
 
        VERTEX *vptr = vstd;
1607
 
        int n_vertices = 4;
1608
 
        
1609
 
    VERTEX *vnew = 0;
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);
1612
 
 
1613
 
 
1614
 
        if (!rdp.hires_tex && rdp.cur_cache[0]->splits != 1)
1615
 
        {
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)
1620
 
            {
1621
 
                min_u = vstd[0].u0;
1622
 
                min_x = vstd[0].x;
1623
 
                max_u = vstd[1].u0;
1624
 
                max_x = vstd[1].x;
1625
 
            }
1626
 
            else
1627
 
            {
1628
 
                min_u = vstd[1].u0;
1629
 
                min_x = vstd[1].x;
1630
 
                max_u = vstd[0].u0;
1631
 
                max_x = vstd[0].x;
1632
 
            }
1633
 
            
1634
 
            int start_u_256, end_u_256;
1635
 
        
1636
 
            if (settings.ucode == 7)
1637
 
            {
1638
 
              start_u_256 = 0;
1639
 
              end_u_256 = (lr_x - ul_x - 1)>>8;
1640
 
            }
1641
 
            else
1642
 
            {
1643
 
              start_u_256 = (int)min_u >> 8;
1644
 
              end_u_256 = (int)max_u >> 8;
1645
 
            }
1646
 
            //FRDP(" min_u: %f, max_u: %f start: %d, end: %d\n", min_u, max_u, start_u_256, end_u_256);
1647
 
 
1648
 
            int splitheight = rdp.cur_cache[0]->splitheight;
1649
 
            
1650
 
            int num_verts_line = 2 + ((end_u_256-start_u_256)<<1);
1651
 
            vnew = new VERTEX [num_verts_line << 1];
1652
 
            
1653
 
            n_vertices = num_verts_line << 1;
1654
 
            vptr = vnew;
1655
 
            
1656
 
            vnew[0] = vstd[0];
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;
1661
 
            vnew[1] = vstd[2];
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;
1676
 
            
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
1680
 
            
1681
 
            for (i=start_u_256; i<end_u_256; i++)
1682
 
            {
1683
 
                // Find where x = current 256 multiple
1684
 
                float x = m * ((i<<8)+256) + b;
1685
 
                
1686
 
                int vn = 2 + ((i-start_u_256)<<2);
1687
 
                vnew[vn] = vnew[0];
1688
 
                vnew[vn].x = x;
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;
1693
 
                
1694
 
                vn ++;
1695
 
                vnew[vn] = vnew[1];
1696
 
                vnew[vn].x = x;
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;
1701
 
                
1702
 
                vn ++;
1703
 
                vnew[vn] = vnew[vn-2];
1704
 
                vnew[vn].u0 = 0.5f;
1705
 
                vnew[vn].v0 += (float)splitheight;
1706
 
        vnew[vn].u1 = 0.5f;
1707
 
        vnew[vn].v1 += (float)splitheight;
1708
 
                
1709
 
                vn ++;
1710
 
                vnew[vn] = vnew[vn-2];
1711
 
                vnew[vn].u0 = 0.5f;
1712
 
                vnew[vn].v0 += (float)splitheight;
1713
 
        vnew[vn].u1 = 0.5f;
1714
 
        vnew[vn].v1 += (float)splitheight;
1715
 
            }
1716
 
        }
1717
 
        
1718
 
    AllowShadeMods (vptr, n_vertices);
1719
 
        for (i=0; i<n_vertices; i++)
1720
 
        {
1721
 
            VERTEX *z = &vptr[i];
1722
 
            
1723
 
            z->u0 *= z->q;
1724
 
            z->v0 *= z->q;
1725
 
            z->u1 *= z->q;
1726
 
            z->v1 *= z->q;
1727
 
            
1728
 
            apply_shade_mods (z);
1729
 
        }
1730
 
                               
1731
 
        if (fullscreen)
1732
 
        {
1733
 
            grFogMode (GR_FOG_DISABLE);
1734
 
            
1735
 
            grClipWindow (0, 0, settings.res_x, settings.res_y);
1736
 
            
1737
 
            grCullMode (GR_CULL_DISABLE);
1738
 
            
1739
 
            if (rdp.cycle_mode == 2)
1740
 
            {
1741
 
                grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
1742
 
                    GR_COMBINE_FACTOR_ONE,
1743
 
                    GR_COMBINE_LOCAL_NONE,
1744
 
                    GR_COMBINE_OTHER_TEXTURE,
1745
 
                    FXFALSE);
1746
 
                grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
1747
 
                    GR_COMBINE_FACTOR_ONE,
1748
 
                    GR_COMBINE_LOCAL_NONE,
1749
 
                    GR_COMBINE_OTHER_TEXTURE,
1750
 
                    FXFALSE);
1751
 
                grAlphaBlendFunction (GR_BLEND_ONE,
1752
 
                    GR_BLEND_ZERO,
1753
 
                    GR_BLEND_ZERO,
1754
 
                    GR_BLEND_ZERO);
1755
 
                if (rdp.othermode_l & 1)
1756
 
                {
1757
 
                    grAlphaTestFunction (GR_CMP_GEQUAL);
1758
 
                    grAlphaTestReferenceValue (0x80);
1759
 
                }
1760
 
                else
1761
 
                    grAlphaTestFunction (GR_CMP_ALWAYS);
1762
 
                
1763
 
                rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE;
1764
 
            }
1765
 
            
1766
 
            ConvertCoordsConvert (vptr, n_vertices);
1767
 
            
1768
 
            if (settings.wireframe)
1769
 
            {
1770
 
                SetWireframeCol ();
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]);
1776
 
            }
1777
 
            else
1778
 
            {
1779
 
                grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, n_vertices, vptr, sizeof(VERTEX));
1780
 
            }
1781
 
            
1782
 
            if (debug.capture)
1783
 
            {
1784
 
                VERTEX vl[3];
1785
 
                vl[0] = vstd[0];
1786
 
                vl[1] = vstd[2];
1787
 
                vl[2] = vstd[1];
1788
 
                add_tri (vl, 3, TRI_TEXRECT);
1789
 
                rdp.tri_n ++;
1790
 
                vl[0] = vstd[2];
1791
 
                vl[1] = vstd[3];
1792
 
                vl[2] = vstd[1];
1793
 
                add_tri (vl, 3, TRI_TEXRECT);
1794
 
                rdp.tri_n ++;
1795
 
            }
1796
 
            else
1797
 
                rdp.tri_n += 2;
1798
 
            
1799
 
      if (settings.fog && (rdp.flags & FOG_ENABLED))
1800
 
      {
1801
 
        grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
1802
 
      }
1803
 
            rdp.update |= UPDATE_CULL_MODE | UPDATE_VIEWPORT;
1804
 
        }
1805
 
        else
1806
 
        {
1807
 
            rdp.tri_n += 2;
1808
 
        }
1809
 
        
1810
 
    delete[] vnew;
1811
 
}
1812
 
 
1813
 
static void rdp_loadsync()
1814
 
{
1815
 
    RDP("loadsync - ignored\n");
1816
 
}
1817
 
 
1818
 
static void rdp_pipesync()
1819
 
{
1820
 
    RDP("pipesync - ignored\n");
1821
 
}
1822
 
 
1823
 
static void rdp_tilesync()
1824
 
{
1825
 
    RDP("tilesync - ignored\n");
1826
 
}
1827
 
 
1828
 
static void rdp_fullsync()
1829
 
{
1830
 
  // Set an interrupt to allow the game to continue
1831
 
  *gfx.MI_INTR_REG |= 0x20;
1832
 
  gfx.CheckInterrupts();
1833
 
  RDP("fullsync\n");
1834
 
}
1835
 
 
1836
 
static void rdp_setkeygb()
1837
 
{
1838
 
    RDP_E("setkeygb - IGNORED\n");
1839
 
    RDP("setkeygb - IGNORED\n");
1840
 
}
1841
 
 
1842
 
static void rdp_setkeyr()
1843
 
{
1844
 
    RDP_E("setkeyr - IGNORED\n");
1845
 
    RDP("setkeyr - IGNORED\n");
1846
 
}
1847
 
 
1848
 
static void rdp_setconvert()
1849
 
{
1850
 
    /*
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   ;
1856
 
    */
1857
 
    rdp.K5 = (BYTE)(rdp.cmd1&0x1FF);
1858
 
    RDP_E("setconvert - IGNORED\n");
1859
 
    RDP("setconvert - IGNORED\n");
1860
 
}
1861
 
 
1862
 
//
1863
 
// setscissor - sets the screen clipping rectangle
1864
 
//
1865
 
 
1866
 
static void rdp_setscissor()
1867
 
{
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)*/;
1873
 
    
1874
 
    rdp.ci_upper_bound = rdp.scissor_o.ul_y;
1875
 
    rdp.ci_lower_bound = rdp.scissor_o.lr_y;
1876
 
    
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);
1879
 
    
1880
 
    rdp.update |= UPDATE_SCISSOR;
1881
 
}
1882
 
 
1883
 
static void rdp_setprimdepth()
1884
 
{
1885
 
    rdp.prim_depth = (WORD)((rdp.cmd1 >> 16) & 0x7FFF);
1886
 
    
1887
 
    FRDP("setprimdepth: %d\n", rdp.prim_depth);
1888
 
}
1889
 
 
1890
 
static void rdp_setothermode()
1891
 
{
1892
 
#define F3DEX2_SETOTHERMODE(cmd,sft,len,data) { \
1893
 
    rdp.cmd0 = (cmd<<24) | ((32-(sft)-(len))<<8) | (((len)-1)); \
1894
 
    rdp.cmd1 = data; \
1895
 
    gfx_instruction[settings.ucode][cmd] (); \
1896
 
}
1897
 
#define SETOTHERMODE(cmd,sft,len,data) { \
1898
 
    rdp.cmd0 = (cmd<<24) | ((sft)<<8) | (len); \
1899
 
    rdp.cmd1 = data; \
1900
 
    gfx_instruction[settings.ucode][cmd] (); \
1901
 
}
1902
 
    
1903
 
    RDP("rdp_setothermode\n");
1904
 
    
1905
 
    if ((settings.ucode == 2) || (settings.ucode == 8))
1906
 
    {
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
1910
 
    }
1911
 
    else
1912
 
    {
1913
 
        int cmd0 = rdp.cmd0;
1914
 
        SETOTHERMODE(0xB9, 0, 32, rdp.cmd1);            // SETOTHERMODE_L
1915
 
        SETOTHERMODE(0xBA, 0, 32, cmd0 & 0x00FFFFFF);       // SETOTHERMODE_H
1916
 
    }
1917
 
}
1918
 
 
1919
 
void load_palette (DWORD addr, WORD start, WORD count)
1920
 
{
1921
 
    RDP ("Loading palette... ");
1922
 
    WORD *dpal = rdp.pal_8 + start;
1923
 
    WORD end = start+count;
1924
 
    //  WORD *spal = (WORD*)(gfx.RDRAM + (addr & BMASK));
1925
 
    
1926
 
    for (WORD i=start; i<end; i++)
1927
 
    {
1928
 
        *(dpal++) = *(WORD *)(gfx.RDRAM + (addr^2));
1929
 
        addr += 2;
1930
 
        
1931
 
#ifdef TLUT_LOGGING
1932
 
        FRDP ("%d: %08lx\n", i, *(WORD *)(gfx.RDRAM + (addr^2)));
1933
 
#endif
1934
 
    }
1935
 
    start >>= 4;
1936
 
    end = start + (count >> 4);
1937
 
    for (WORD p = start; p < end; p++)
1938
 
    {
1939
 
      rdp.pal_8_crc[p] = CRC_Calculate( 0xFFFFFFFF, &rdp.pal_8[(p << 4)], 32 );
1940
 
    }
1941
 
    rdp.pal_256_crc = CRC_Calculate( 0xFFFFFFFF, rdp.pal_8_crc, 64 );
1942
 
    RDP ("Done.\n");
1943
 
}
1944
 
 
1945
 
static void rdp_loadtlut()
1946
 
{
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
1951
 
    
1952
 
    if (rdp.timg.addr + (count<<1) > BMASK)
1953
 
        count = (WORD)((BMASK - rdp.timg.addr) >> 1);
1954
 
    
1955
 
    if (start+count > 256) count = 256-start;
1956
 
    
1957
 
    FRDP("loadtlut: tile: %d, start: %d, count: %d, from: %08lx\n", tile, start, count,
1958
 
        rdp.timg.addr);
1959
 
    
1960
 
    load_palette (rdp.timg.addr, start, count);
1961
 
    
1962
 
    rdp.timg.addr += count << 1;
1963
 
}
1964
 
 
1965
 
BOOL tile_set = 0;
1966
 
static void rdp_settilesize()
1967
 
{
1968
 
    DWORD tile = (rdp.cmd1 >> 24) & 0x07;
1969
 
    rdp.last_tile_size = tile;
1970
 
    
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;
1973
 
    
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);
1978
 
    
1979
 
    if (lr_s == 0 && ul_s == 0)  //pokemon puzzle league set such tile size
1980
 
        wrong_tile = tile;
1981
 
    else if (wrong_tile == (int)tile)
1982
 
        wrong_tile = -1;
1983
 
    
1984
 
    if (settings.use_sts1_only)
1985
 
    {
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)
1989
 
        
1990
 
        if (tile_set)
1991
 
        {
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;
1997
 
            tile_set = 0;
1998
 
        }
1999
 
    }
2000
 
    else
2001
 
    {
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;
2007
 
    }
2008
 
    
2009
 
    // handle wrapping
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;
2012
 
 
2013
 
    rdp.update |= UPDATE_TEXTURE;
2014
 
    
2015
 
    rdp.first = 1;
2016
 
    
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))))
2020
 
        rdp.hires_tex = 0;
2021
 
    if (rdp.hires_tex)
2022
 
    {
2023
 
      if (rdp.tiles[tile].format == 0 && rdp.hires_tex->format == 0)
2024
 
      {
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);
2030
 
      }
2031
 
      else if (tile == 0)
2032
 
      {
2033
 
        rdp.hires_tex->info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
2034
 
      }
2035
 
    }
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);
2038
 
}
2039
 
 
2040
 
static void CopyswapBlock(int *pDst, unsigned int cnt, unsigned int SrcOffs)
2041
 
{
2042
 
    // copy and byteswap a block of 8-byte dwords
2043
 
    int rem = SrcOffs & 3;
2044
 
    if (rem == 0)
2045
 
    {
2046
 
        int *pSrc = (int *) ((uintptr_t) gfx.RDRAM + SrcOffs);
2047
 
        for (unsigned int x = 0; x < cnt; x++)
2048
 
        {
2049
 
            int s1 = *pSrc++;
2050
 
            int s2 = *pSrc++;
2051
 
            BYTESWAP2(s1, s2)
2052
 
            *pDst++ = s1;
2053
 
            *pDst++ = s2;
2054
 
        }
2055
 
    }
2056
 
    else
2057
 
    {
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
2061
 
        int s0 = *pSrc++;
2062
 
        BYTESWAP1(s0)
2063
 
        for (int x = 0; x < rem; x++)
2064
 
            s0 >>= 8;
2065
 
        for (int x = 4; x > rem; x--)
2066
 
        {
2067
 
            *((char *) pDst) = s0 & 0xff;
2068
 
            pDst = (int *) ((char *) pDst + 1);
2069
 
            s0 >>= 8;
2070
 
        }
2071
 
        // do one full 32-bit word
2072
 
        s0 = *pSrc++;
2073
 
        BYTESWAP1(s0)
2074
 
        *pDst++ = s0;
2075
 
        // do 'cnt-1' 64-bit dwords
2076
 
        for (unsigned int x = 0; x < cnt-1; x++)
2077
 
        {
2078
 
            int s1 = *pSrc++;
2079
 
            int s2 = *pSrc++;
2080
 
            BYTESWAP2(s1, s2)
2081
 
            *pDst++ = s1;
2082
 
            *pDst++ = s2;
2083
 
        }
2084
 
        // do last partial 32-bit word
2085
 
        s0 = *pSrc++;
2086
 
        BYTESWAP1(s0)
2087
 
        for (; rem > 0; rem--)
2088
 
        {
2089
 
            *((char *) pDst) = s0 & 0xff;
2090
 
            pDst = (int *) ((char *) pDst + 1);
2091
 
            s0 >>= 8;
2092
 
        }
2093
 
    }
2094
 
}
2095
 
 
2096
 
static void WordswapBlock(int *pDst, unsigned int cnt, unsigned int TileSize)
2097
 
{
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.
2100
 
    if (TileSize == 3)
2101
 
    {
2102
 
        // swapblock64 dst, cnt
2103
 
        for (unsigned int x = 0; x < cnt / 2; x++, pDst += 4)
2104
 
        {
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;
2109
 
        }
2110
 
    }
2111
 
    else
2112
 
    {
2113
 
        // swapblock32 dst, cnt
2114
 
        for (unsigned int x = 0; x < cnt; x++, pDst += 2)
2115
 
        {
2116
 
            int s1 = pDst[0];
2117
 
            int s2 = pDst[1];
2118
 
            pDst[0] = s2;
2119
 
            pDst[1] = s1;
2120
 
        }
2121
 
    }
2122
 
}
2123
 
 
2124
 
static void rdp_loadblock()
2125
 
{
2126
 
    if (rdp.skip_drawing)
2127
 
    {
2128
 
       RDP("loadblock skipped\n");
2129
 
        return;
2130
 
    }
2131
 
    DWORD tile = (DWORD)((rdp.cmd1 >> 24) & 0x07);
2132
 
    DWORD dxt = (DWORD)(rdp.cmd1 & 0x0FFF);
2133
 
    
2134
 
    rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr;
2135
 
    
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;*/
2139
 
    
2140
 
    // 0x00000800 -> 0x80000000 (so we can check the sign bit instead of the 11th bit)
2141
 
    DWORD _dxt = dxt << 20;
2142
 
    
2143
 
    DWORD addr = segoffset(rdp.timg.addr) & BMASK;
2144
 
    
2145
 
    // lr_s specifies number of 64-bit words to copy
2146
 
    // 10.2 format
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;
2150
 
    
2151
 
    rdp.tiles[tile].ul_s = ul_s;
2152
 
    rdp.tiles[tile].ul_t = ul_t;
2153
 
    rdp.tiles[tile].lr_s = lr_s;
2154
 
    
2155
 
    rdp.timg.set_by = 0;  // load block
2156
 
 
2157
 
    // do a quick boundary check before copying to eliminate the possibility for exception
2158
 
    if (ul_s >= 512) {
2159
 
        lr_s = 1;   // 1 so that it doesn't die on memcpy
2160
 
        ul_s = 511;
2161
 
    }
2162
 
    if (ul_s+lr_s > 512)
2163
 
        lr_s = 512-ul_s;
2164
 
    
2165
 
    if (addr+(lr_s<<3) > BMASK+1)
2166
 
        lr_s = (WORD)((BMASK-addr)>>3);
2167
 
    
2168
 
    DWORD offs = rdp.timg.addr;
2169
 
    DWORD cnt = lr_s+1;
2170
 
    if (rdp.tiles[tile].size == 3)
2171
 
        cnt <<= 1;
2172
 
  //FIXME: unused? DWORD start_line = 0;
2173
 
 
2174
 
  //    if (lr_s > 0)
2175
 
    rdp.timg.addr += cnt << 3;
2176
 
 
2177
 
    int * pDst = (int *) ((uintptr_t)rdp.tmem+(rdp.tiles[tile].t_mem<<3));
2178
 
 
2179
 
    // Load the block from RDRAM and byteswap it as it loads
2180
 
    CopyswapBlock(pDst, cnt, offs);
2181
 
 
2182
 
    // now do 32-bit or 64-bit word swapping on every other row of data
2183
 
    int dxt_accum = 0;
2184
 
    while (cnt > 0)
2185
 
    {
2186
 
        // skip over unswapped blocks
2187
 
        do
2188
 
        {
2189
 
            pDst += 2;
2190
 
            if (--cnt == 0)
2191
 
                break;
2192
 
            dxt_accum += _dxt;
2193
 
        } while (!(dxt_accum & 0x80000000));
2194
 
        // count number of blocks to swap
2195
 
        if (cnt == 0) break;
2196
 
        int swapcnt = 0;
2197
 
        do
2198
 
        {
2199
 
            swapcnt++;
2200
 
            if (--cnt == 0)
2201
 
                break;
2202
 
            dxt_accum += _dxt;
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;
2207
 
    }
2208
 
   
2209
 
    rdp.update |= UPDATE_TEXTURE;
2210
 
    
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,
2213
 
        dxt, _dxt);
2214
 
}
2215
 
 
2216
 
static void rdp_loadtile()
2217
 
{
2218
 
    if (rdp.skip_drawing)
2219
 
        return;
2220
 
    rdp.timg.set_by = 1;  // load tile
2221
 
    
2222
 
    DWORD tile = (DWORD)((rdp.cmd1 >> 24) & 0x07);
2223
 
    if (rdp.tiles[tile].format == 1)
2224
 
    {
2225
 
        rdp.yuv_image = TRUE;
2226
 
        if (rdp.timg.addr < rdp.yuv_im_begin) rdp.yuv_im_begin = rdp.timg.addr;
2227
 
        return;
2228
 
    }
2229
 
    
2230
 
    rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr;
2231
 
    
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);
2236
 
    
2237
 
    if (lr_s < ul_s || lr_t < ul_t) return;
2238
 
    
2239
 
    if (wrong_tile >= 0)  //there was a tile with zero length
2240
 
    {
2241
 
        rdp.tiles[wrong_tile].lr_s = lr_s;
2242
 
        
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;
2248
 
        //     wrong_tile = -1;
2249
 
    }
2250
 
    
2251
 
  if (rdp.hires_tex)// && (rdp.tiles[tile].format == 0))
2252
 
  {
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;
2256
 
    }
2257
 
 
2258
 
    if (settings.tonic && tile == 7)
2259
 
    {
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;
2264
 
    }
2265
 
 
2266
 
    DWORD height = lr_t - ul_t + 1;   // get height
2267
 
    DWORD width = lr_s - ul_s + 1;
2268
 
    
2269
 
    DWORD wid_64 = rdp.tiles[tile].line;
2270
 
 
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)
2275
 
        wid_64 <<= 1;
2276
 
    
2277
 
    int line_n = rdp.timg.width;
2278
 
    if (rdp.tiles[tile].size == 0)
2279
 
        line_n >>= 1;
2280
 
    else
2281
 
        line_n <<= (rdp.tiles[tile].size-1);
2282
 
    
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)
2287
 
    return;
2288
 
    
2289
 
    // check if points to bad location
2290
 
  DWORD size = width * height;
2291
 
    if (rdp.tiles[tile].size == 0)
2292
 
        size >>= 1;
2293
 
    else
2294
 
        size <<= (rdp.tiles[tile].size-1);
2295
 
    
2296
 
  if (offs + line_n*height > BMASK)
2297
 
    height = (BMASK - offs) / line_n;
2298
 
    
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));
2301
 
 
2302
 
    for (unsigned int y = 0; y < height; y++)
2303
 
    {
2304
 
        if (pDst > pEnd) break;
2305
 
        CopyswapBlock(pDst, wid_64, offs);
2306
 
        if (y & 1)
2307
 
        {
2308
 
            WordswapBlock(pDst, wid_64, rdp.tiles[tile].size);
2309
 
        }
2310
 
        pDst += wid_64 * 2;
2311
 
        offs += line_n;
2312
 
    }
2313
 
    
2314
 
    FRDP("loadtile: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d\n", tile,
2315
 
        ul_s, ul_t, lr_s, lr_t);
2316
 
}
2317
 
 
2318
 
static void rdp_settile()
2319
 
{
2320
 
    tile_set = 1; // used to check if we only load the first settilesize
2321
 
    
2322
 
    rdp.first = 0;
2323
 
    
2324
 
    //rdp.cur_tile_n = (DWORD)((rdp.cmd1 >> 24) & 0x07);
2325
 
    //rdp.cur_tile = &rdp.tiles[rdp.cur_tile_n];
2326
 
    
2327
 
    rdp.last_tile = (DWORD)((rdp.cmd1 >> 24) & 0x07);
2328
 
    TILE *tile = &rdp.tiles[rdp.last_tile];
2329
 
    
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);
2343
 
    
2344
 
    rdp.update |= UPDATE_TEXTURE;
2345
 
    
2346
 
    FRDP ("settile: tile: %d, format: %s, size: %s, line: %d, "
2347
 
        "t_mem: %08lx, palette: %d, clamp_t/mirror_t: %s, mask_t: %d, "
2348
 
        "shift_t: %d, clamp_s/mirror_s: %s, mask_s: %d, shift_s: %d\n",
2349
 
        rdp.last_tile, str_format[tile->format], str_size[tile->size], tile->line,
2350
 
        tile->t_mem, tile->palette, str_cm[(tile->clamp_t<<1)|tile->mirror_t], tile->mask_t,
2351
 
        tile->shift_t, str_cm[(tile->clamp_s<<1)|tile->mirror_s], tile->mask_s, tile->shift_s);
2352
 
}
2353
 
 
2354
 
//
2355
 
// fillrect - fills a rectangle
2356
 
//
2357
 
 
2358
 
static void rdp_fillrect()
2359
 
{
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))
2365
 
    {
2366
 
        RDP ("Fillrect - cleared the depth buffer\n");
2367
 
        if (fullscreen)
2368
 
        {
2369
 
            
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)
2376
 
            {
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;
2388
 
        ul_x >>= 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++)
2392
 
        {
2393
 
          for (DWORD x = ul_x; x < fillrect_width_in_dwords; x++)
2394
 
          {
2395
 
            dst[x] = rdp.fill_color;
2396
 
          } 
2397
 
          dst += zi_width_in_dwords;
2398
 
        }
2399
 
            }
2400
 
        }
2401
 
        return;
2402
 
    }
2403
 
    
2404
 
    if (rdp.skip_drawing)
2405
 
    {
2406
 
        RDP("Fillrect skipped\n");
2407
 
        return;
2408
 
    }
2409
 
    
2410
 
    // Update scissor
2411
 
    update_scissor ();
2412
 
    
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
2415
 
        return;
2416
 
 
2417
 
  if (rdp.cur_image && (rdp.cur_image->format != 0) && (rdp.cycle_mode == 3) && (rdp.cur_image->width == lr_x))
2418
 
  {
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;
2428
 
        return;
2429
 
    }
2430
 
    
2431
 
  if (settings.decrease_fillrect_edge && rdp.cycle_mode == 0)
2432
 
    {
2433
 
        lr_x--; lr_y--;
2434
 
    }
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);
2437
 
    
2438
 
    FRDP("scissor (%d,%d) -> (%d,%d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x,
2439
 
        rdp.scissor.lr_y);
2440
 
    
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);
2446
 
    
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;
2451
 
    
2452
 
    FRDP (" - %d, %d, %d, %d\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y);
2453
 
    
2454
 
    if (fullscreen)
2455
 
    {
2456
 
        grFogMode (GR_FOG_DISABLE);
2457
 
        
2458
 
        grClipWindow (0, 0, settings.res_x, settings.res_y);
2459
 
        
2460
 
    float Z = 1.0f;
2461
 
    if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030))
2462
 
    {
2463
 
            Z = ScaleZ(rdp.prim_depth);
2464
 
        grDepthBufferFunction (GR_CMP_LEQUAL);
2465
 
        //          grDepthMask (FXTRUE);
2466
 
        FRDP ("prim_depth = %d\n", rdp.prim_depth);
2467
 
    }
2468
 
    else
2469
 
    {
2470
 
      grDepthBufferFunction (GR_CMP_ALWAYS);
2471
 
      grDepthMask (FXFALSE);
2472
 
            RDP ("no prim_depth used, using 1.0\n");
2473
 
    }
2474
 
        // Draw the rectangle
2475
 
        VERTEX v[4] = {
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 } };
2480
 
            
2481
 
            if (rdp.cycle_mode == 3)
2482
 
            {
2483
 
        DWORD color = (settings.fillcolor_fix) ? rdp.fill_color : (rdp.fill_color >> 16);
2484
 
 
2485
 
        if (settings.PM && rdp.frame_buffers[rdp.ci_count-1].status == ci_aux)
2486
 
        {
2487
 
          //background of auxilary frame buffers must have zero alpha. 
2488
 
          //make it black, set 0 alpha to plack pixels on frame buffer read
2489
 
          color = 0;
2490
 
        }
2491
 
        else
2492
 
        {
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);
2497
 
        }
2498
 
                grConstantColorValue (color);
2499
 
                
2500
 
                grColorCombine (GR_COMBINE_FUNCTION_LOCAL,
2501
 
                    GR_COMBINE_FACTOR_NONE,
2502
 
                    GR_COMBINE_LOCAL_CONSTANT,
2503
 
                    GR_COMBINE_OTHER_NONE,
2504
 
                    FXFALSE);
2505
 
                
2506
 
                grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
2507
 
                    GR_COMBINE_FACTOR_NONE,
2508
 
                    GR_COMBINE_LOCAL_CONSTANT,
2509
 
                    GR_COMBINE_OTHER_NONE,
2510
 
                    FXFALSE);
2511
 
                
2512
 
                grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO);
2513
 
                
2514
 
                rdp.update |= UPDATE_COMBINE;
2515
 
            }
2516
 
            else
2517
 
            {
2518
 
                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
2523
 
        {
2524
 
          AllowShadeMods (v, 4);
2525
 
          for (int k = 0; k < 4; k++)
2526
 
            apply_shade_mods (&v[k]);
2527
 
            }
2528
 
            }
2529
 
            
2530
 
            grAlphaTestFunction (GR_CMP_ALWAYS);
2531
 
      if (grStippleModeExt)
2532
 
        grStippleModeExt(GR_STIPPLE_DISABLE);
2533
 
            
2534
 
            grCullMode(GR_CULL_DISABLE);
2535
 
            
2536
 
            if (settings.wireframe)
2537
 
            {
2538
 
                SetWireframeCol ();
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]);
2545
 
            }
2546
 
            else
2547
 
            {
2548
 
                grDrawTriangle (&v[0], &v[2], &v[1]);
2549
 
                grDrawTriangle (&v[2], &v[3], &v[1]);
2550
 
            }
2551
 
            
2552
 
            if (debug.capture)
2553
 
            {
2554
 
                VERTEX v1[3];
2555
 
                v1[0] = v[0];
2556
 
                v1[1] = v[2];
2557
 
                v1[2] = v[1];
2558
 
                add_tri (v1, 3, TRI_FILLRECT);
2559
 
                rdp.tri_n ++;
2560
 
                v1[0] = v[2];
2561
 
                v1[1] = v[3];
2562
 
                add_tri (v1, 3, TRI_FILLRECT);
2563
 
                rdp.tri_n ++;
2564
 
            }
2565
 
            else
2566
 
                rdp.tri_n += 2;
2567
 
            
2568
 
      if (settings.fog && (rdp.flags & FOG_ENABLED)) 
2569
 
      {
2570
 
        grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
2571
 
      }
2572
 
            
2573
 
            rdp.update |= UPDATE_CULL_MODE | UPDATE_ALPHA_COMPARE | UPDATE_ZBUF_ENABLED;
2574
 
  }
2575
 
  else
2576
 
  {
2577
 
      rdp.tri_n += 2;
2578
 
  }
2579
 
}
2580
 
 
2581
 
//
2582
 
// setfillcolor - sets the filling color
2583
 
//
2584
 
 
2585
 
static void rdp_setfillcolor()
2586
 
{
2587
 
  rdp.fill_color = rdp.cmd1;
2588
 
    rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE;
2589
 
    
2590
 
    FRDP("setfillcolor: %08lx\n", rdp.cmd1);
2591
 
}
2592
 
 
2593
 
static void rdp_setfogcolor()
2594
 
{
2595
 
  rdp.fog_color = rdp.cmd1;
2596
 
    rdp.update |= UPDATE_COMBINE | UPDATE_FOG_ENABLED;
2597
 
    
2598
 
    FRDP("setfogcolor - %08lx\n", rdp.cmd1);
2599
 
}
2600
 
 
2601
 
static void rdp_setblendcolor()
2602
 
{
2603
 
  rdp.blend_color = rdp.cmd1;
2604
 
    rdp.update |= UPDATE_COMBINE;
2605
 
    
2606
 
    FRDP("setblendcolor: %08lx\n", rdp.cmd1);
2607
 
}
2608
 
 
2609
 
static void rdp_setprimcolor()
2610
 
{
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;
2615
 
    
2616
 
    FRDP("setprimcolor: %08lx, lodmin: %d, lodfrac: %d\n", rdp.cmd1, rdp.prim_lodmin,
2617
 
        rdp.prim_lodfrac);
2618
 
}
2619
 
 
2620
 
static void rdp_setenvcolor()
2621
 
{
2622
 
  rdp.env_color = rdp.cmd1;
2623
 
    rdp.update |= UPDATE_COMBINE;
2624
 
    
2625
 
    FRDP("setenvcolor: %08lx\n", rdp.cmd1);
2626
 
}
2627
 
 
2628
 
static void rdp_setcombine()
2629
 
{
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);
2638
 
    
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);
2647
 
    
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);
2652
 
    
2653
 
    rdp.update |= UPDATE_COMBINE;
2654
 
    
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]);
2660
 
}
2661
 
 
2662
 
//
2663
 
// settextureimage - sets the source for an image copy
2664
 
//
2665
 
 
2666
 
static void rdp_settextureimage()
2667
 
{
2668
 
    static const char *format[]   = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" };
2669
 
    static const char *size[]     = { "4bit", "8bit", "16bit", "32bit" };
2670
 
    
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;
2677
 
    
2678
 
  if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self && (rdp.timg.addr >= rdp.cimg) && (rdp.timg.addr < rdp.ci_end)) 
2679
 
        {
2680
 
            if (!rdp.fb_drawn)
2681
 
            {
2682
 
            if (!rdp.cur_image)
2683
 
          CopyFrameBuffer();
2684
 
        else if (rdp.frame_buffers[rdp.ci_count].status != ci_copy)
2685
 
          CloseTextureBuffer(TRUE);
2686
 
                rdp.fb_drawn = TRUE;
2687
 
            }
2688
 
    }
2689
 
    
2690
 
    if (settings.fb_hires) //search this texture among drawn texture buffers
2691
 
    {
2692
 
      if (settings.zelda)
2693
 
      {
2694
 
         if (rdp.timg.size == 2) 
2695
 
           FindTextureBuffer(rdp.timg.addr, rdp.timg.width);
2696
 
      }
2697
 
      else
2698
 
           FindTextureBuffer(rdp.timg.addr, rdp.timg.width);
2699
 
    }
2700
 
 
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);
2704
 
}
2705
 
 
2706
 
static void rdp_setdepthimage()
2707
 
{
2708
 
    rdp.zimg = segoffset(rdp.cmd1) & BMASK;
2709
 
  rdp.zi_width = rdp.ci_width;
2710
 
    FRDP("setdepthimage - %08lx\n", rdp.zimg);
2711
 
}
2712
 
 
2713
 
 
2714
 
BOOL SwapOK = TRUE;
2715
 
static void RestoreScale()
2716
 
{
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;
2726
 
  //*
2727
 
  if (fullscreen)
2728
 
  {
2729
 
    grDepthMask (FXFALSE);
2730
 
    grBufferClear (0, 0, 0xFFFF);
2731
 
    grDepthMask (FXTRUE);
2732
 
  }
2733
 
  //*/
2734
 
}
2735
 
 
2736
 
static DWORD swapped_addr = 0;
2737
 
 
2738
 
static void rdp_setcolorimage()
2739
 
{
2740
 
  render_depth_mode = 0;
2741
 
  if (settings.fb_smart && (rdp.num_of_ci < NUMTEXBUF))
2742
 
    {
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)
2747
 
        {
2748
 
        case ci_main:
2749
 
            {
2750
 
 
2751
 
                if (rdp.ci_count == 0)
2752
 
                {
2753
 
                    if ((rdp.ci_status == ci_aux)) //for PPL
2754
 
                    {
2755
 
                        float sx = rdp.scale_x;
2756
 
                        float sy = rdp.scale_y;
2757
 
                        rdp.scale_x = 1.0f;
2758
 
                        rdp.scale_y = 1.0f;
2759
 
                CopyFrameBuffer ();
2760
 
                        rdp.scale_x = sx;
2761
 
                        rdp.scale_y = sy;
2762
 
                    }
2763
 
                    if (!settings.fb_hires)
2764
 
                    {
2765
 
                        if ((rdp.num_of_ci > 1) && 
2766
 
                  (next_fb.status == ci_aux) && 
2767
 
                  (next_fb.width >= cur_fb.width))
2768
 
                        {
2769
 
                            rdp.scale_x = 1.0f;
2770
 
                            rdp.scale_y = 1.0f;
2771
 
                        }
2772
 
                    }
2773
 
              else if (rdp.copy_ci_index && settings.PM) //tidal wave
2774
 
                OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
2775
 
                }
2776
 
                else if (!rdp.motionblur && settings.fb_hires && !SwapOK && (rdp.ci_count <= rdp.copy_ci_index))
2777
 
        {
2778
 
          if (next_fb.status == ci_aux_copy)
2779
 
            OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
2780
 
          else
2781
 
                  OpenTextureBuffer(rdp.frame_buffers[rdp.copy_ci_index]);
2782
 
        }
2783
 
        else if (settings.fb_hires && rdp.read_whole_frame && prev_fb.status == ci_aux)
2784
 
        {
2785
 
          OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
2786
 
        }
2787
 
                //else if (rdp.ci_status == ci_aux && !rdp.copy_ci_index)
2788
 
                //  CloseTextureBuffer();
2789
 
 
2790
 
                rdp.skip_drawing = FALSE;
2791
 
            }
2792
 
            break;
2793
 
        case ci_copy:
2794
 
            {
2795
 
                if (!rdp.motionblur || settings.fb_motionblur)
2796
 
                {
2797
 
          if (cur_fb.width == rdp.ci_width)
2798
 
          {
2799
 
            if (CopyTextureBuffer(prev_fb, cur_fb))
2800
 
              //                      if (CloseTextureBuffer(TRUE))
2801
 
                      ;
2802
 
            else 
2803
 
                    {
2804
 
              if (!rdp.fb_drawn || prev_fb.status == ci_copy_self)
2805
 
                        {
2806
 
                CopyFrameBuffer ();
2807
 
                            rdp.fb_drawn = TRUE;
2808
 
                        }
2809
 
              memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);
2810
 
                    }
2811
 
          }
2812
 
          else
2813
 
                    {
2814
 
            CloseTextureBuffer(TRUE);
2815
 
          }
2816
 
        }
2817
 
        else
2818
 
        {
2819
 
          memset(gfx.RDRAM+cur_fb.addr, 0, cur_fb.width*cur_fb.height*rdp.ci_size);
2820
 
        }
2821
 
        rdp.skip_drawing = TRUE;
2822
 
      }
2823
 
      break;
2824
 
    case ci_aux_copy:
2825
 
      {
2826
 
                    rdp.skip_drawing = FALSE;
2827
 
        if (CloseTextureBuffer(prev_fb.status != ci_aux_copy))
2828
 
          ;
2829
 
        else if (!rdp.fb_drawn)
2830
 
        {
2831
 
          CopyFrameBuffer ();
2832
 
          rdp.fb_drawn = TRUE;
2833
 
                    }
2834
 
        if (settings.fb_hires) 
2835
 
          OpenTextureBuffer(cur_fb);
2836
 
            }
2837
 
            break;
2838
 
        case ci_old_copy:
2839
 
            {
2840
 
                if (!rdp.motionblur || settings.fb_motionblur)
2841
 
                {
2842
 
          if (cur_fb.width == rdp.ci_width)
2843
 
                    {
2844
 
            memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.maincimg[1].addr, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);
2845
 
                    }
2846
 
                    //rdp.skip_drawing = TRUE;
2847
 
                }
2848
 
                else
2849
 
                {
2850
 
          memset(gfx.RDRAM+cur_fb.addr, 0, (cur_fb.width*cur_fb.height)<<rdp.ci_size>>1);
2851
 
                }
2852
 
            }
2853
 
            break;
2854
 
            /*
2855
 
            else if (rdp.frame_buffers[rdp.ci_count].status == ci_main_i)
2856
 
            {
2857
 
      //       CopyFrameBuffer ();
2858
 
            rdp.scale_x = rdp.scale_x_bak;
2859
 
            rdp.scale_y = rdp.scale_y_bak;
2860
 
            rdp.skip_drawing = FALSE;
2861
 
            }
2862
 
            */
2863
 
        case ci_aux:
2864
 
            {
2865
 
        if (!settings.fb_hires && cur_fb.format != 0)
2866
 
                    rdp.skip_drawing = TRUE;
2867
 
                else
2868
 
                {
2869
 
                    rdp.skip_drawing = FALSE;
2870
 
          if (settings.fb_hires && OpenTextureBuffer(cur_fb))
2871
 
                      ;
2872
 
                    else
2873
 
                    {
2874
 
                        if (cur_fb.format != 0)
2875
 
                  rdp.skip_drawing = TRUE;
2876
 
                        if (rdp.ci_count == 0) 
2877
 
                        {
2878
 
                            //           if (rdp.num_of_ci > 1)
2879
 
                            //           {
2880
 
                            rdp.scale_x = 1.0f;
2881
 
                            rdp.scale_y = 1.0f;
2882
 
                            //           }
2883
 
                        }
2884
 
                else if (!settings.fb_hires && (prev_fb.status == ci_main) && 
2885
 
                  (prev_fb.width == cur_fb.width)) // for Pokemon Stadium
2886
 
                  CopyFrameBuffer ();
2887
 
                    }
2888
 
                }
2889
 
        cur_fb.status = ci_aux;
2890
 
            }
2891
 
            break;
2892
 
        case ci_zimg:
2893
 
          // ZIGGY
2894
 
          // Zelda LoT effect save/restore depth buffer
2895
 
          if (cur_fb.addr == rdp.zimg) {
2896
 
            render_depth_mode = 1;
2897
 
          } else {
2898
 
            render_depth_mode = 2;
2899
 
          }
2900
 
          rdp.skip_drawing = TRUE;
2901
 
          break;
2902
 
        case ci_useless:
2903
 
            //case ci_zcopy:
2904
 
            rdp.skip_drawing = TRUE;
2905
 
            break;
2906
 
        case ci_copy_self:
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;
2910
 
            /*
2911
 
            if (settings.fb_hires)
2912
 
            {
2913
 
              if (SwapOK)
2914
 
              {
2915
 
                rdp.cimg = rdp.frame_buffers[rdp.ci_count].addr;
2916
 
      rdp.maincimg[0].addr = rdp.cimg;
2917
 
                newSwapBuffers();
2918
 
                SwapOK = FALSE;
2919
 
                OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count]);
2920
 
              }
2921
 
            }
2922
 
            */
2923
 
            break;
2924
 
        default:
2925
 
            rdp.skip_drawing = FALSE;
2926
 
        }
2927
 
        
2928
 
    if ((rdp.ci_count > 0) && (prev_fb.status >= ci_aux)) //for Pokemon Stadium
2929
 
        {
2930
 
      if (!settings.fb_hires && prev_fb.format == 0)
2931
 
        CopyFrameBuffer ();
2932
 
        }
2933
 
    if (!settings.fb_hires && cur_fb.status == ci_copy)
2934
 
        {
2935
 
      if (!rdp.motionblur && (rdp.num_of_ci > rdp.ci_count+1) && (next_fb.status != ci_aux))
2936
 
            {
2937
 
        RestoreScale();
2938
 
            }
2939
 
        }
2940
 
    if (!settings.fb_hires && cur_fb.status == ci_aux)
2941
 
        {
2942
 
      if (cur_fb.format == 0)
2943
 
            {
2944
 
                if (settings.PPL && (rdp.scale_x < 1.1f))  //need to put current image back to frame buffer
2945
 
                {
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);
2950
 
                    WORD c;
2951
 
                    
2952
 
                    for (int y=0; y<height; y++)
2953
 
                    {
2954
 
                        for (int x=0; x<width; x++)
2955
 
                        {
2956
 
                            c = ((ptr_src[(x + y * width)^1]) >> 1) | 0x8000;
2957
 
                            ptr_dst[x + y * width] = c;
2958
 
                        }
2959
 
                    }
2960
 
                    grLfbWriteRegion(GR_BUFFER_BACKBUFFER,
2961
 
                        0,
2962
 
                        0,
2963
 
                        GR_LFB_SRC_FMT_555,
2964
 
                        width,
2965
 
                        height,
2966
 
                        FXFALSE,
2967
 
                        width<<1,
2968
 
                        ptr_dst);
2969
 
                    delete[] ptr_dst;
2970
 
                }
2971
 
                /*
2972
 
                else  //just clear buffer
2973
 
                {
2974
 
                
2975
 
                  grColorMask(FXTRUE, FXTRUE);
2976
 
                  grBufferClear (0, 0, 0xFFFF);
2977
 
                  }
2978
 
                */
2979
 
            }
2980
 
        }
2981
 
        
2982
 
    if ((cur_fb.status == ci_main) && (rdp.ci_count > 0))
2983
 
        {
2984
 
            BOOL to_org_res = TRUE;
2985
 
            for (int i = rdp.ci_count + 1; i < rdp.num_of_ci; i++)
2986
 
            {
2987
 
        if ((rdp.frame_buffers[i].status != ci_main) && (rdp.frame_buffers[i].status != ci_zimg) && (rdp.frame_buffers[i].status != ci_zcopy))
2988
 
                {
2989
 
                    to_org_res = FALSE;
2990
 
                    break;
2991
 
                }
2992
 
            }
2993
 
            if (to_org_res)
2994
 
            {
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();
3000
 
            }
3001
 
      if (settings.fb_hires && !rdp.read_whole_frame && (prev_fb.status >= ci_aux) && (rdp.ci_count > rdp.copy_ci_index))
3002
 
                  CloseTextureBuffer();
3003
 
 
3004
 
        }
3005
 
    rdp.ci_status = cur_fb.status;
3006
 
        rdp.ci_count++;
3007
 
  }
3008
 
  
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)
3015
 
    rdp.ci_height = 32;
3016
 
  else
3017
 
    rdp.ci_height = rdp.scissor_o.lr_y;
3018
 
  if (rdp.zimg == rdp.cimg) 
3019
 
  {
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;
3023
 
  }
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);
3029
 
 
3030
 
  if (format != 0 && !rdp.cur_image) //can't draw into non RGBA buffer
3031
 
  {
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;
3036
 
      return;
3037
 
  }
3038
 
  else
3039
 
  {
3040
 
      if (!settings.fb_smart)
3041
 
          rdp.skip_drawing = FALSE;
3042
 
  }
3043
 
 
3044
 
  CI_SET = TRUE;
3045
 
  if (settings.swapmode > 0)
3046
 
  {
3047
 
      if (rdp.zimg == rdp.cimg)
3048
 
          rdp.updatescreen = 1;
3049
 
      
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)
3052
 
      {
3053
 
          if (settings.fb_smart)
3054
 
        rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index];
3055
 
          else
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;
3059
 
          newSwapBuffers();
3060
 
      rdp.vi_org_reg = *gfx.VI_ORIGIN_REG;
3061
 
          SwapOK = FALSE;
3062
 
      if (settings.fb_hires)
3063
 
          {
3064
 
        if (rdp.copy_ci_index && (rdp.frame_buffers[rdp.ci_count-1].status != ci_zimg))
3065
 
        {
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;
3071
 
          }
3072
 
        else if (rdp.read_whole_frame && !rdp.cur_image)
3073
 
        {
3074
 
          OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
3075
 
            }
3076
 
      } 
3077
 
      }
3078
 
  }
3079
 
}
3080
 
 
3081
 
static void rdp_trifill()
3082
 
{
3083
 
    RDP_E("trifill - IGNORED\n");
3084
 
    RDP("trifill - IGNORED\n");
3085
 
}
3086
 
 
3087
 
static void rdp_trishade()
3088
 
{
3089
 
    RDP_E("trishade - IGNORED\n");
3090
 
    RDP("trishade - IGNORED\n");
3091
 
}
3092
 
 
3093
 
static void rdp_tritxtr()
3094
 
{
3095
 
    RDP_E("tritxtr - IGNORED\n");
3096
 
    RDP("tritxtr - IGNORED\n");
3097
 
}
3098
 
 
3099
 
static void rdp_trishadetxtr()
3100
 
{
3101
 
    RDP_E("trishadetxtr - IGNORED\n");
3102
 
    RDP("trishadetxtr - IGNORED\n");
3103
 
}
3104
 
 
3105
 
static void rdp_trifillz()
3106
 
{
3107
 
    RDP_E("trifillz - IGNORED\n");
3108
 
    RDP("trifillz - IGNORED\n");
3109
 
}
3110
 
 
3111
 
static void rdp_trishadez()
3112
 
{
3113
 
    RDP_E("trishadez - IGNORED\n");
3114
 
    RDP("trishadez - IGNORED\n");
3115
 
}
3116
 
 
3117
 
static void rdp_tritxtrz()
3118
 
{
3119
 
    RDP_E("tritxtrz - IGNORED\n");
3120
 
    RDP("tritxtrz - IGNORED\n");
3121
 
}
3122
 
 
3123
 
static void rdp_trishadetxtrz()
3124
 
{
3125
 
    RDP_E("trishadetxtrz - IGNORED\n");
3126
 
    RDP("trishadetxtrz - IGNORED\n");
3127
 
}
3128
 
 
3129
 
static void rsp_reserved0()
3130
 
{
3131
 
    RDP_E("reserved0 - IGNORED\n");
3132
 
    RDP("reserved0 - IGNORED\n");
3133
 
}
3134
 
 
3135
 
static void rsp_reserved1()
3136
 
{
3137
 
    RDP("reserved1 - ignored\n");
3138
 
}
3139
 
 
3140
 
static void rsp_reserved2()
3141
 
{
3142
 
    RDP("reserved2\n");
3143
 
}
3144
 
 
3145
 
static void rsp_reserved3()
3146
 
{
3147
 
    RDP("reserved3 - ignored\n");
3148
 
}
3149
 
 
3150
 
void SetWireframeCol ()
3151
 
{
3152
 
    if (!fullscreen) return;
3153
 
    
3154
 
    switch (settings.wfmode)
3155
 
    {
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,
3162
 
            FXFALSE);
3163
 
        grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
3164
 
            GR_COMBINE_FACTOR_NONE,
3165
 
            GR_COMBINE_LOCAL_ITERATED,
3166
 
            GR_COMBINE_OTHER_NONE,
3167
 
            FXFALSE);
3168
 
        grAlphaBlendFunction (GR_BLEND_ONE,
3169
 
            GR_BLEND_ZERO,
3170
 
            GR_BLEND_ZERO,
3171
 
            GR_BLEND_ZERO);
3172
 
        grTexCombine (GR_TMU0,
3173
 
            GR_COMBINE_FUNCTION_ZERO,
3174
 
            GR_COMBINE_FACTOR_NONE,
3175
 
            GR_COMBINE_FUNCTION_ZERO,
3176
 
            GR_COMBINE_FACTOR_NONE,
3177
 
            FXFALSE, FXFALSE);
3178
 
        grTexCombine (GR_TMU1,
3179
 
            GR_COMBINE_FUNCTION_ZERO,
3180
 
            GR_COMBINE_FACTOR_NONE,
3181
 
            GR_COMBINE_FUNCTION_ZERO,
3182
 
            GR_COMBINE_FACTOR_NONE,
3183
 
            FXFALSE, FXFALSE);
3184
 
        break;
3185
 
    case 2: // red only
3186
 
        grColorCombine (GR_COMBINE_FUNCTION_LOCAL,
3187
 
            GR_COMBINE_FACTOR_NONE,
3188
 
            GR_COMBINE_LOCAL_CONSTANT,
3189
 
            GR_COMBINE_OTHER_NONE,
3190
 
            FXFALSE);
3191
 
        grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
3192
 
            GR_COMBINE_FACTOR_NONE,
3193
 
            GR_COMBINE_LOCAL_CONSTANT,
3194
 
            GR_COMBINE_OTHER_NONE,
3195
 
            FXFALSE);
3196
 
    grConstantColorValue (0xFF0000FF);
3197
 
        grAlphaBlendFunction (GR_BLEND_ONE,
3198
 
            GR_BLEND_ZERO,
3199
 
            GR_BLEND_ZERO,
3200
 
            GR_BLEND_ZERO);
3201
 
        grTexCombine (GR_TMU0,
3202
 
            GR_COMBINE_FUNCTION_ZERO,
3203
 
            GR_COMBINE_FACTOR_NONE,
3204
 
            GR_COMBINE_FUNCTION_ZERO,
3205
 
            GR_COMBINE_FACTOR_NONE,
3206
 
            FXFALSE, FXFALSE);
3207
 
        grTexCombine (GR_TMU1,
3208
 
            GR_COMBINE_FUNCTION_ZERO,
3209
 
            GR_COMBINE_FACTOR_NONE,
3210
 
            GR_COMBINE_FUNCTION_ZERO,
3211
 
            GR_COMBINE_FACTOR_NONE,
3212
 
            FXFALSE, FXFALSE);
3213
 
        break;
3214
 
    }
3215
 
    
3216
 
    grAlphaTestFunction (GR_CMP_ALWAYS);
3217
 
    grCullMode (GR_CULL_DISABLE);
3218
 
    
3219
 
    //grDepthBufferFunction (GR_CMP_ALWAYS);
3220
 
    //grDepthMask (FXFALSE);
3221
 
    
3222
 
    rdp.update |= UPDATE_COMBINE | UPDATE_ALPHA_COMPARE;
3223
 
}
3224
 
 
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
3230
 
in N64 RDRAM
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
3236
 
val         val
3237
 
size        1 = BYTE, 2 = WORD, 4 = DWORD
3238
 
output:   none
3239
 
*******************************************************************/ 
3240
 
EXPORT void CALL FBRead(DWORD addr)
3241
 
{
3242
 
  printf("FBRead\n");
3243
 
    LOG ("FBRead ()\n");
3244
 
    
3245
 
  if (cpu_fb_ignore)
3246
 
    return;
3247
 
  if (cpu_fb_write_called)
3248
 
  {
3249
 
    cpu_fb_ignore = TRUE;
3250
 
    cpu_fb_write = FALSE;
3251
 
    return;
3252
 
  }
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))
3257
 
    {
3258
 
    fbreads_back++;
3259
 
    //if (fbreads_back > 2) //&& (rdp.ci_width <= 320))
3260
 
    {
3261
 
      CopyFrameBuffer ();
3262
 
            rdp.fb_drawn = TRUE;
3263
 
    }
3264
 
  }
3265
 
  if (!rdp.fb_drawn_front && (a >= rdp.maincimg[1].addr) && (a < rdp.maincimg[1].addr + rdp.ci_width*rdp.ci_height*2))
3266
 
  {
3267
 
    fbreads_front++;
3268
 
    //if (fbreads_front > 2)//&& (rdp.ci_width <= 320))
3269
 
    {
3270
 
            DWORD cimg = rdp.cimg;
3271
 
        rdp.cimg = rdp.maincimg[1].addr;
3272
 
        if (settings.fb_smart)
3273
 
        {
3274
 
          rdp.ci_width = rdp.maincimg[1].width;
3275
 
          rdp.ci_count = 0;
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;
3280
 
        }
3281
 
        else
3282
 
        {
3283
 
          CopyFrameBuffer(GR_BUFFER_FRONTBUFFER);
3284
 
        }
3285
 
        rdp.cimg = cimg;
3286
 
        rdp.fb_drawn_front = TRUE;
3287
 
        }
3288
 
    }
3289
 
}
3290
 
 
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
3297
 
output:   none
3298
 
*******************************************************************/ 
3299
 
EXPORT void CALL FBWList(FrameBufferModifyEntry *plist, DWORD size)
3300
 
{
3301
 
    LOG ("FBWList ()\n");
3302
 
    FRDP("FBWList. size: %d\n", size);
3303
 
    printf("FBWList. size: %d\n", size);
3304
 
}
3305
 
 
3306
 
 
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
3312
 
val         val
3313
 
size        1 = BYTE, 2 = WORD, 4 = DWORD
3314
 
output:   none
3315
 
*******************************************************************/ 
3316
 
EXPORT void CALL FBWrite(DWORD addr, DWORD size)
3317
 
{
3318
 
    LOG ("FBWrite ()\n");
3319
 
  if (cpu_fb_ignore)
3320
 
    return;
3321
 
  if (cpu_fb_read_called)
3322
 
  {
3323
 
    cpu_fb_ignore = TRUE;
3324
 
    cpu_fb_write = FALSE;
3325
 
    return;
3326
 
  }
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)
3332
 
      return;
3333
 
    cpu_fb_write = TRUE;
3334
 
    DWORD shift_l = (a-rdp.cimg) >> 1;
3335
 
    DWORD shift_r = shift_l+2;
3336
 
 
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);
3341
 
}
3342
 
 
3343
 
 
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
3349
 
          operations
3350
 
 
3351
 
          size:
3352
 
            = 1     byte
3353
 
            = 2     word (16 bit) <-- this is N64 default depth buffer format
3354
 
            = 4     dword (32 bit)
3355
 
 
3356
 
          when frame buffer information is not available yet, set all values
3357
 
          in the FrameBufferInfo structure to 0
3358
 
 
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
 
************************************************************************/
3365
 
///*
3366
 
typedef struct
3367
 
{
3368
 
    DWORD addr;
3369
 
    DWORD size;
3370
 
    DWORD width;
3371
 
    DWORD height;
3372
 
} FrameBufferInfo;
3373
 
EXPORT void CALL FBGetFrameBufferInfo(void *p)
3374
 
{
3375
 
  LOG ("FBGetFrameBufferInfo ()\n");
3376
 
    FrameBufferInfo * pinfo = (FrameBufferInfo *)p;
3377
 
        memset(pinfo,0,sizeof(FrameBufferInfo)*6);
3378
 
  if (!settings.fb_get_info)
3379
 
    return;
3380
 
  RDP("FBGetFrameBufferInfo ()\n");
3381
 
  //*
3382
 
    if (settings.fb_smart)
3383
 
    {
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;
3388
 
    int info_index = 1;
3389
 
    for (int i = 0; i < rdp.num_of_ci && info_index < 6; i++)
3390
 
      {
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)
3394
 
         {
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;
3399
 
            info_index++;
3400
 
         }
3401
 
      }
3402
 
  }
3403
 
  else
3404
 
      {
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;
3413
 
    }
3414
 
//*/
3415
 
}
3416
 
//*/
3417
 
#include "UcodeFB.h"
3418
 
 
3419
 
void DetectFrameBufferUsage ()
3420
 
{
3421
 
    RDP("DetectFrameBufferUsage\n");
3422
 
    
3423
 
    DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0);
3424
 
#ifdef _WIN32
3425
 
    DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4);
3426
 
#endif // _WIN32
3427
 
    DWORD a;
3428
 
    
3429
 
  BOOL tidal = FALSE;
3430
 
  if (settings.PM && (rdp.copy_ci_index || rdp.frame_buffers[rdp.copy_ci_index].status == ci_copy_self))
3431
 
    tidal = TRUE;
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;
3435
 
    rdp.zimg_end = 0;
3436
 
    rdp.tmpzimg = 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;
3443
 
  SwapOK = TRUE;
3444
 
 
3445
 
    // Start executing at the start of the display list
3446
 
    rdp.pc_i = 0;
3447
 
    rdp.pc[rdp.pc_i] = dlist_start;
3448
 
    rdp.dl_count = -1;
3449
 
    rdp.halt = 0;
3450
 
    rdp.scale_x_bak = rdp.scale_x;
3451
 
    rdp.scale_y_bak = rdp.scale_y;
3452
 
    
3453
 
    // MAIN PROCESSING LOOP
3454
 
    do {
3455
 
        
3456
 
        // Get the address of the next command
3457
 
        a = rdp.pc[rdp.pc_i] & BMASK;
3458
 
        
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]; // /
3462
 
        
3463
 
        // Output the address before the command
3464
 
        
3465
 
        // Go to the next instruction
3466
 
        rdp.pc[rdp.pc_i] = (a+8) & BMASK;
3467
 
        
3468
 
        if ((intptr_t)(gfx_instruction_lite[settings.ucode][rdp.cmd0>>24]))
3469
 
            gfx_instruction_lite[settings.ucode][rdp.cmd0>>24] ();
3470
 
        
3471
 
        // check DL counter
3472
 
        if (rdp.dl_count != -1)
3473
 
        {
3474
 
            rdp.dl_count --;
3475
 
            if (rdp.dl_count == 0)
3476
 
            {
3477
 
                rdp.dl_count = -1;
3478
 
                
3479
 
                RDP ("End of DL\n");
3480
 
                rdp.pc_i --;
3481
 
            }
3482
 
        }
3483
 
        
3484
 
    } while (!rdp.halt);
3485
 
  SwapOK = TRUE;
3486
 
  if (rdp.ci_count > NUMTEXBUF) //overflow
3487
 
  {
3488
 
    rdp.cimg = ci; 
3489
 
    rdp.zimg = zi;
3490
 
    rdp.num_of_ci = rdp.ci_count;
3491
 
    rdp.scale_x = rdp.scale_x_bak;
3492
 
    rdp.scale_y = rdp.scale_y_bak;
3493
 
    return;
3494
 
  }
3495
 
    
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;
3498
 
    
3499
 
    if (rdp.frame_buffers[rdp.ci_count-1].status == ci_unknown)
3500
 
    {
3501
 
        if (rdp.ci_count > 1)
3502
 
            rdp.frame_buffers[rdp.ci_count-1].status = ci_aux;
3503
 
        else
3504
 
            rdp.frame_buffers[rdp.ci_count-1].status = ci_main;
3505
 
    }
3506
 
    
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))
3510
 
    {
3511
 
        for (int i = 0; i < rdp.ci_count; i++)
3512
 
        {
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);
3518
 
        }
3519
 
        rdp.main_ci_index = rdp.ci_count-1;
3520
 
    }
3521
 
    
3522
 
    BOOL all_zimg = TRUE;
3523
 
        int i;
3524
 
    for (i = 0; i < rdp.ci_count; i++)
3525
 
    {
3526
 
        if (rdp.frame_buffers[i].status != ci_zimg)
3527
 
        {
3528
 
          all_zimg = FALSE;
3529
 
          break;
3530
 
        }
3531
 
    }
3532
 
    if (all_zimg)
3533
 
    {
3534
 
      for (i = 0; i < rdp.ci_count; i++)
3535
 
        rdp.frame_buffers[i].status = ci_main;
3536
 
    }
3537
 
 
3538
 
    RDP("detect fb final results: \n");
3539
 
    for (i = 0; i < rdp.ci_count; i++)
3540
 
    {
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);
3542
 
    }
3543
 
    
3544
 
    rdp.cimg = ci; 
3545
 
    rdp.zimg = zi;
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))
3551
 
    {
3552
 
        rdp.scale_x = rdp.scale_x_bak;
3553
 
        rdp.scale_y = rdp.scale_y_bak;
3554
 
    }
3555
 
 
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)
3559
 
    {
3560
 
      if (settings.fb_hires && !settings.fb_ignore_previous)
3561
 
      {
3562
 
        if (rdp.swap_ci_index < 0)
3563
 
        {
3564
 
          rdp.texbufs[0].clear_allowed = rdp.texbufs[0].clear_allowed = TRUE;
3565
 
          OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
3566
 
        }
3567
 
      }
3568
 
      else
3569
 
    {
3570
 
      if (rdp.motionblur)
3571
 
      {
3572
 
        if (settings.fb_motionblur)
3573
 
            CopyFrameBuffer();
3574
 
        else
3575
 
          memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size);
3576
 
      }
3577
 
        else //if (ci_width == rdp.frame_buffers[rdp.main_ci_index].width)
3578
 
        {
3579
 
          if (rdp.maincimg[0].height > 65) //for 1080
3580
 
          {
3581
 
            rdp.cimg = rdp.maincimg[0].addr;
3582
 
            rdp.ci_width = rdp.maincimg[0].width;
3583
 
            rdp.ci_count = 0;
3584
 
            DWORD h = rdp.frame_buffers[0].height;
3585
 
            rdp.frame_buffers[0].height = rdp.maincimg[0].height;
3586
 
            CopyFrameBuffer();
3587
 
            rdp.frame_buffers[0].height = h;
3588
 
          }
3589
 
          else //conker
3590
 
          {
3591
 
            CopyFrameBuffer();
3592
 
          }
3593
 
        }   
3594
 
      }
3595
 
    }
3596
 
 
3597
 
    if (settings.fb_hires)
3598
 
    {
3599
 
      for (i = 0; i < num_tmu; i++)
3600
 
      {
3601
 
        rdp.texbufs[i].clear_allowed = TRUE;
3602
 
        for (int j = 0; j < 256; j++)
3603
 
        {
3604
 
          rdp.texbufs[i].images[j].drawn = FALSE;
3605
 
          rdp.texbufs[i].images[j].clear = TRUE;
3606
 
        }
3607
 
      }
3608
 
      if (tidal)
3609
 
      {
3610
 
        //RDP("Tidal wave!\n");
3611
 
        rdp.copy_ci_index = rdp.main_ci_index;
3612
 
      }
3613
 
    }
3614
 
    rdp.ci_count = 0;
3615
 
    if (settings.fb_ignore_previous)
3616
 
      rdp.read_whole_frame = FALSE;
3617
 
    else
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");
3622
 
}
3623
 
 
3624
 
 
3625
 
 
3626
 
 
3627
 
 
3628
 
/******************************************************************
3629
 
Function: ProcessRDPList
3630
 
Purpose:  This function is called when there is a Dlist to be
3631
 
processed. (Low level GFX list)
3632
 
input:    none
3633
 
output:   none
3634
 
*******************************************************************/ 
3635
 
EXPORT void CALL ProcessRDPList(void)
3636
 
{
3637
 
  if (settings.KI)
3638
 
  {
3639
 
    *gfx.MI_INTR_REG |= 0x20;
3640
 
    gfx.CheckInterrupts();
3641
 
  }
3642
 
  LOG ("ProcessRDPList ()\n");
3643
 
 
3644
 
  no_dlist = FALSE;
3645
 
  update_screen_count = 0;
3646
 
  ChangeSize ();
3647
 
    
3648
 
#ifdef ALTTAB_FIX
3649
 
    if (!hhkLowLevelKybd)
3650
 
    {
3651
 
        hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL, 
3652
 
            LowLevelKeyboardProc, hInstance, 0);
3653
 
    }
3654
 
#endif
3655
 
    
3656
 
    LOG ("ProcessDList ()\n");
3657
 
    
3658
 
    if (!fullscreen)
3659
 
  {
3660
 
        drawNoFullscreenMessage();
3661
 
    // Set an interrupt to allow the game to continue
3662
 
    *gfx.MI_INTR_REG |= 0x20;
3663
 
    gfx.CheckInterrupts();
3664
 
  }
3665
 
    
3666
 
    if (reset)
3667
 
    {
3668
 
        reset = 0;
3669
 
        
3670
 
        memset (microcode, 0, 4096);
3671
 
        if (settings.autodetect_ucode)
3672
 
        {
3673
 
            // Thanks to ZeZu for ucode autodetection!!!
3674
 
            
3675
 
            DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0);
3676
 
            memcpy (microcode, gfx.RDRAM+startUcode, 4096);
3677
 
            microcheck ();
3678
 
            
3679
 
        }
3680
 
    }
3681
 
  else if ( ((old_ucode == 6) && (settings.ucode == 1)) || settings.force_microcheck)
3682
 
    {
3683
 
        DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0);
3684
 
        memcpy (microcode, gfx.RDRAM+startUcode, 4096);
3685
 
        microcheck ();
3686
 
    }
3687
 
    
3688
 
    if (exception) return;
3689
 
    
3690
 
    // Switch to fullscreen?
3691
 
    if (to_fullscreen)
3692
 
    {
3693
 
        to_fullscreen = FALSE;
3694
 
        
3695
 
        if (!InitGfx (FALSE))
3696
 
        {
3697
 
            LOG ("FAILED!!!\n");
3698
 
            return;
3699
 
        }
3700
 
        fullscreen = TRUE;
3701
 
#ifdef _WIN32
3702
 
        if (gfx.hStatusBar)
3703
 
          ShowWindow( gfx.hStatusBar, SW_HIDE );
3704
 
        ShowCursor( FALSE );
3705
 
#endif // _WIN32
3706
 
    }
3707
 
    
3708
 
    // Clear out the RDP log
3709
 
#ifdef RDP_LOGGING
3710
 
    if (settings.logging && settings.log_clear)
3711
 
    {
3712
 
        CLOSE_RDP_LOG ();
3713
 
        OPEN_RDP_LOG ();
3714
 
    }
3715
 
#endif
3716
 
    
3717
 
#ifdef UNIMP_LOG
3718
 
    if (settings.log_unk && settings.unk_clear)
3719
 
    {
3720
 
        std::ofstream unimp;
3721
 
        unimp.open("unimp.txt");
3722
 
        unimp.close();
3723
 
    }
3724
 
#endif
3725
 
  
3726
 
  //* Set states *//
3727
 
  if (settings.swapmode > 0)
3728
 
    SwapOK = TRUE;
3729
 
  rdp.updatescreen = 1;
3730
 
  
3731
 
    rdp.tri_n = 0;  // 0 triangles so far this frame
3732
 
    rdp.debug_n = 0;
3733
 
    
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
3741
 
    rdp.geom_mode = 0;
3742
 
  rdp.acmp = 0;
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;
3748
 
  rdp.zsrc = 0;
3749
 
    
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;
3756
 
    d_ul_x = 0xffff;
3757
 
    d_ul_y = 0xffff;
3758
 
    d_lr_x = 0;
3759
 
    d_lr_y = 0;
3760
 
    
3761
 
    //analize possible frame buffer usage
3762
 
    if (settings.fb_smart)
3763
 
        DetectFrameBufferUsage();
3764
 
  if (!settings.lego || rdp.num_of_ci > 1)
3765
 
    rdp.last_bg = 0;
3766
 
  //* End of set states *//
3767
 
  
3768
 
    
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);
3776
 
    
3777
 
    if (settings.tonic && dlist_length < 16)
3778
 
    {
3779
 
    rdp_fullsync();
3780
 
        FRDP_E("DLIST is too short!\n");
3781
 
        return;
3782
 
    }
3783
 
    
3784
 
    // Start executing at the start of the display list
3785
 
    rdp.pc_i = 0;
3786
 
    rdp.pc[rdp.pc_i] = dlist_start;
3787
 
    rdp.dl_count = -1;
3788
 
    rdp.halt = 0;
3789
 
  DWORD a;
3790
 
    
3791
 
    // catches exceptions so that it doesn't freeze
3792
 
#ifdef CATCH_EXCEPTIONS
3793
 
    try {
3794
 
#endif
3795
 
        
3796
 
        // MAIN PROCESSING LOOP
3797
 
        do {
3798
 
            
3799
 
            // Get the address of the next command
3800
 
            a = rdp.pc[rdp.pc_i] & BMASK;
3801
 
            
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
3806
 
            
3807
 
            // Output the address before the command
3808
 
#ifdef LOG_COMMANDS
3809
 
            FRDP ("%08lx (c0:%08lx, c1:%08lx): ", a, rdp.cmd0, rdp.cmd1);
3810
 
#else
3811
 
            FRDP ("%08lx: ", a);
3812
 
#endif
3813
 
            
3814
 
            // Go to the next instruction
3815
 
            rdp.pc[rdp.pc_i] = (a+8) & BMASK;
3816
 
            
3817
 
#ifdef PERFORMANCE
3818
 
            QueryPerformanceCounter ((LARGE_INTEGER*)&perf_cur);
3819
 
#endif
3820
 
            // Process this instruction
3821
 
            gfx_instruction[settings.ucode][((rdp.cmd0>>24)&0x3f) + 0x100-0x40] ();
3822
 
            
3823
 
            // check DL counter
3824
 
            if (rdp.dl_count != -1)
3825
 
            {
3826
 
                rdp.dl_count --;
3827
 
                if (rdp.dl_count == 0)
3828
 
                {
3829
 
                    rdp.dl_count = -1;
3830
 
                    
3831
 
                    RDP ("End of DL\n");
3832
 
                    rdp.pc_i --;
3833
 
                }
3834
 
            }
3835
 
            
3836
 
#ifdef PERFORMANCE
3837
 
            QueryPerformanceCounter ((LARGE_INTEGER*)&perf_next);
3838
 
            __int64 t = perf_next-perf_cur;
3839
 
            sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, t);
3840
 
            rdp_log << out_buf;
3841
 
#endif
3842
 
            
3843
 
        } while (0);
3844
 
#ifdef CATCH_EXCEPTIONS
3845
 
    } catch (...) {
3846
 
        
3847
 
        if (fullscreen) ReleaseGfx ();
3848
 
# ifdef _WIN32
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)
3850
 
            exception = TRUE;
3851
 
# else // _WIN32
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)
3853
 
         exception = TRUE;
3854
 
# endif // _WIN32
3855
 
    }
3856
 
#endif
3857
 
    
3858
 
    if (settings.fb_smart)
3859
 
    {
3860
 
        rdp.scale_x = rdp.scale_x_bak;
3861
 
        rdp.scale_y = rdp.scale_y_bak;
3862
 
    }
3863
 
    if (settings.fb_read_always)
3864
 
    {
3865
 
    CopyFrameBuffer ();
3866
 
    }
3867
 
    if (rdp.yuv_image)
3868
 
    {
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; 
3875
 
    }
3876
 
    if (rdp.cur_image)
3877
 
    CloseTextureBuffer(rdp.read_whole_frame && (settings.PM || rdp.swap_ci_index >= 0));
3878
 
 
3879
 
  if (settings.TGR2 && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET)
3880
 
  {
3881
 
    newSwapBuffers ();
3882
 
    CI_SET = FALSE;
3883
 
  }
3884
 
    RDP("ProcessDList end\n");
3885
 
 
3886
 
 
3887
 
 
3888
 
 
3889
 
 
3890
 
  
3891
 
  printf("ProcessRPDList %x %x %x\n",
3892
 
         *gfx.DPC_START_REG,
3893
 
         *gfx.DPC_END_REG,
3894
 
         *gfx.DPC_CURRENT_REG);
3895
 
  //*gfx.DPC_STATUS_REG = 0xffffffff; // &= ~0x0002;
3896
 
 
3897
 
  *gfx.DPC_START_REG = *gfx.DPC_END_REG;
3898
 
  *gfx.DPC_CURRENT_REG = *gfx.DPC_END_REG;
3899
 
}
3900
 
 
3901
 
 
3902
 
 
3903
 
 
3904
 
 
3905
 
 
3906
 
//  Local Variables: ***
3907
 
//  tab-width:4 ***
3908
 
//  c-file-offset:4 ***
3909
 
//  End: ***
3910