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