Replace Tmem_nasm.asm with C++ code. Patch by pyro.
[Glide64.git] / Main.cpp
blobfc97f739f597694b5034dea96708606baa1a3333
1 /*
2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002 Dave2001
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 //****************************************************************
22 // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)
23 // Project started on December 29th, 2001
25 // To modify Glide64:
26 // * 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.
27 // * 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.
29 // Official Glide64 development channel: #Glide64 on EFnet
31 // Original author: Dave2001 (Dave2999@hotmail.com)
32 // Other authors: Gonetz, Gugaman
34 //****************************************************************
36 #include "Gfx1.3.h"
37 #include "Util.h"
38 #include "3dmath.h"
39 #include "Debugger.h"
40 #ifdef _WIN32
41 #include "resource.h"
42 #endif // _WIN32
44 #include "Combine.h"
46 #include "Ini.h"
48 #include "TexCache.h"
49 #include "CRC.h"
50 #include "DepthBufferRender.h"
52 #ifndef _WIN32
53 #include <string.h>
54 #include <stdlib.h>
55 #include "messagebox.h"
56 #include <sys/time.h>
57 #endif // _WIN32
59 #define G64_VERSION "0.9"
60 #define RELTIME "Date: " __DATE__ " Time: " __TIME__
62 #ifdef EXT_LOGGING
63 std::ofstream extlog;
64 #endif
66 #ifdef LOGGING
67 std::ofstream loga;
68 #endif
70 #ifdef RDP_LOGGING
71 BOOL log_open = FALSE;
72 std::ofstream rdp_log;
73 #endif
75 #ifdef RDP_ERROR_LOG
76 BOOL elog_open = FALSE;
77 std::ofstream rdp_err;
78 #endif
80 GFX_INFO gfx;
82 BOOL to_fullscreen = FALSE;
83 BOOL fullscreen = FALSE;
84 BOOL romopen = FALSE;
85 GrContext_t gfx_context = 0;
86 BOOL debugging = FALSE;
87 HINSTANCE hInstance = NULL;
88 BOOL exception = FALSE;
90 // ZIGGY temporary
91 #if defined(GCC) && defined(WIN32)
92 int dumping;
93 #endif
95 BOOL evoodoo = 0;
96 BOOL ev_fullscreen = 0;
98 long num_tmu;
99 long max_tex_size;
100 long sup_mirroring;
101 BOOL sup_32bit_tex = FALSE;
103 #ifdef _WIN32
104 #define WINPROC_OVERRIDE
105 #ifdef WINPROC_OVERRIDE
106 LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
107 WNDPROC oldWndProc = NULL;
108 WNDPROC myWndProc = NULL;
109 #endif
110 #endif // _WIN32
112 #ifdef ALTTAB_FIX
113 HHOOK hhkLowLevelKybd = NULL;
114 LRESULT CALLBACK LowLevelKeyboardProc(int nCode,
115 WPARAM wParam, LPARAM lParam);
116 #endif
118 #ifdef PERFORMANCE
119 __int64 perf_cur;
120 __int64 perf_next;
121 #endif
123 #ifdef FPS
124 LARGE_INTEGER perf_freq;
125 LARGE_INTEGER fps_last;
126 LARGE_INTEGER fps_next;
127 float fps = 0.0f;
128 DWORD fps_count = 0;
130 DWORD vi_count = 0;
131 float vi = 0.0f;
133 DWORD region = 0;
135 float ntsc_percent = 0.0f;
136 float pal_percent = 0.0f;
138 #endif
140 // Resolutions, MUST be in the correct order (SST1VID.H)
141 DWORD resolutions[0x18][2] = {
142 { 320, 200 },
143 { 320, 240 },
144 { 400, 256 },
145 { 512, 384 },
146 { 640, 200 },
147 { 640, 350 },
148 { 640, 400 },
149 { 640, 480 },
150 { 800, 600 },
151 { 960, 720 },
152 { 856, 480 },
153 { 512, 256 },
154 { 1024, 768 },
155 { 1280, 1024 },
156 { 1600, 1200 },
157 { 400, 300 },
159 // 0x10
160 { 1152, 864 },
161 { 1280, 960 },
162 { 1600, 1024 },
163 { 1792, 1344 },
164 { 1856, 1392 },
165 { 1920, 1440 },
166 { 2048, 1536 },
167 { 2048, 2048 }
170 // ref rate
171 // 60=0x0, 70=0x1, 72=0x2, 75=0x3, 80=0x4, 90=0x5, 100=0x6, 85=0x7, 120=0x8, none=0xff
173 unsigned long BMASK = 0x7FFFFF;
174 // Reality display processor structure
175 RDP rdp;
177 SETTINGS settings = { FALSE, 640, 480, GR_RESOLUTION_640x480, 0 };
179 HOTKEY_INFO hotkey_info;
181 GrTexInfo fontTex;
182 GrTexInfo cursorTex;
183 DWORD offset_font = 0;
184 DWORD offset_cursor = 0;
185 DWORD offset_textures = 0;
186 DWORD offset_texbuf1 = 0;
188 BOOL capture_screen = 0;
189 char capture_path[256];
191 void ChangeSize ()
193 float res_scl_x = (float)settings.res_x / 320.0f;
194 float res_scl_y = (float)settings.res_y / 240.0f;
196 DWORD scale_x = *gfx.VI_X_SCALE_REG & 0xFFF;
197 if (!scale_x) return;
198 DWORD scale_y = *gfx.VI_Y_SCALE_REG & 0xFFF;
199 if (!scale_y) return;
201 float fscale_x = (float)scale_x / 1024.0f;
202 float fscale_y = (float)scale_y / 1024.0f;
204 DWORD dwHStartReg = *gfx.VI_H_START_REG;
205 DWORD dwVStartReg = *gfx.VI_V_START_REG;
207 DWORD hstart = dwHStartReg >> 16;
208 DWORD hend = dwHStartReg & 0xFFFF;
210 // dunno... but sometimes this happens
211 if (hend == hstart) hend = (int)(*gfx.VI_WIDTH_REG / fscale_x);
213 DWORD vstart = dwVStartReg >> 16;
214 DWORD vend = dwVStartReg & 0xFFFF;
216 sprintf (out_buf, "hstart: %d, hend: %d, vstart: %d, vend: %d\n", hstart, hend, vstart, vend);
217 LOG (out_buf);
219 rdp.vi_width = (hend - hstart) * fscale_x;
220 rdp.vi_height = (vend - vstart)/2 * fscale_y;
222 sprintf (out_buf, "size: %d x %d\n", (int)rdp.vi_width, (int)rdp.vi_height);
223 LOG (out_buf);
225 if (region == 0)
227 if (*gfx.VI_WIDTH_REG == 0x500) // 1280x960 is different... needs height * 2
229 rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width);
230 rdp.scale_y = res_scl_y * (120.0f / rdp.vi_height);
232 else
234 rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width);
235 rdp.scale_y = res_scl_y * (240.0f / rdp.vi_height);
238 else
240 // odd... but pal games seem to want 230 as height...
241 if (*gfx.VI_WIDTH_REG == 0x500) // 1280x960 is different... needs height * 2
243 // NOT SURE ABOUT PAL HERE, DON'T HAVE PAL MEGAMAN TO TRY
244 rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width);
245 // VP changed to 120
246 rdp.scale_y = res_scl_y * (120.0f / rdp.vi_height);
247 //rdp.scale_y = res_scl_y * (115.0f / rdp.vi_height);
249 else
251 rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width);
252 // VP changed to 240
253 rdp.scale_y = res_scl_y * (240.0f / rdp.vi_height);
254 //rdp.scale_y = res_scl_y * (230.0f / rdp.vi_height);
258 rdp.offset_x = settings.offset_x * res_scl_x;
259 rdp.offset_y = settings.offset_y * res_scl_y;
260 if (settings.scale_x != 0)
261 rdp.scale_x *= (settings.scale_x / 100000.0f);
262 if (settings.scale_y != 0)
263 rdp.scale_y *= (settings.scale_y / 100000.0f);
265 rdp.scale_1024 = settings.scr_res_x / 1024.0f;
266 rdp.scale_768 = settings.scr_res_y / 768.0f;
268 rdp.scissor_o.ul_x = 0;
269 rdp.scissor_o.ul_y = 0;
270 rdp.scissor_o.lr_x = (DWORD)rdp.vi_width;
271 rdp.scissor_o.lr_y = (DWORD)rdp.vi_height;
273 rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
276 void ReadSettings ()
278 // LOG("ReadSettings\n");
279 INI_Open ();
280 INI_FindSection ("SETTINGS");
281 settings.card_id = (BYTE)INI_ReadInt ("card_id", 0);
283 settings.depth_bias = -INI_ReadInt ("depth_bias", 0);
284 settings.res_data = (DWORD) INI_ReadInt ("resolution", 7);
285 if (settings.res_data >= 24) settings.res_data = 12;
286 settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0];
287 settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1];
288 settings.autodetect_ucode = (BOOL)INI_ReadInt ("autodetect_ucode", 1);
289 settings.ucode = (DWORD)INI_ReadInt ("ucode", 2);
291 settings.wireframe = (BOOL)INI_ReadInt ("wireframe", 0);
292 settings.wfmode = (int)INI_ReadInt ("wfmode", 1);
293 settings.filtering = (BYTE)INI_ReadInt ("filtering", 1);
294 settings.fog = (BOOL)INI_ReadInt ("fog", 0);
295 settings.buff_clear = (BOOL)INI_ReadInt ("buff_clear", 1);
296 settings.vsync = (BOOL)INI_ReadInt ("vsync", 0);
297 settings.fast_crc = (BOOL)INI_ReadInt ("fast_crc", 0);
298 settings.swapmode = (BYTE)INI_ReadInt ("swapmode", 1);
299 settings.lodmode = (BYTE)INI_ReadInt ("lodmode", 0);
301 settings.logging = (BOOL)INI_ReadInt ("logging", 0);
302 settings.log_clear = (BOOL)INI_ReadInt ("log_clear", 0);
303 settings.run_in_window = (BOOL)INI_ReadInt ("run_in_window", 0);
304 settings.elogging = (BOOL)INI_ReadInt ("elogging", 0);
305 settings.filter_cache = (BOOL)INI_ReadInt ("filter_cache", 0);
306 settings.cpu_write_hack = (BOOL)INI_ReadInt ("detect_cpu_write", 0);
307 settings.unk_as_red = (BOOL)INI_ReadInt ("unk_as_red", 0);
308 settings.log_unk = (BOOL)INI_ReadInt ("log_unk", 0);
309 settings.unk_clear = (BOOL)INI_ReadInt ("unk_clear", 0);
311 settings.wrap_big_tex = (BOOL)INI_ReadInt ("wrap_big_tex", 0);
312 settings.flame_corona = (BOOL)INI_ReadInt ("flame_corona", 0);
313 // settings.RE2_native_video = (BOOL)INI_ReadInt ("RE2_native_video", 0);
315 settings.show_fps = (BYTE)INI_ReadInt ("show_fps", 0);
317 settings.clock = (BOOL)INI_ReadInt ("clock", 0);
318 settings.clock_24_hr = (BOOL)INI_ReadInt ("clock_24_hr", 0);
320 settings.fb_read_always = (BOOL)INI_ReadInt ("fb_read_always", 0);
321 settings.fb_read_alpha = (BOOL)INI_ReadInt ("fb_read_alpha", 0);
322 settings.fb_smart = (BOOL)INI_ReadInt ("fb_smart", 0);
323 settings.fb_motionblur = (BOOL)INI_ReadInt ("motionblur", 0);
324 settings.fb_hires = (BOOL)INI_ReadInt ("fb_hires", 0);
325 settings.fb_get_info = (BOOL)INI_ReadInt ("fb_get_info", 0);
326 settings.fb_depth_clear = (BOOL)INI_ReadInt ("fb_clear", 0);
327 settings.fb_depth_render = (BOOL)INI_ReadInt ("fb_render", 0);
328 if (settings.fb_depth_render)
329 settings.fb_depth_clear = TRUE;
331 settings.custom_ini = (BOOL)INI_ReadInt ("custom_ini", 0);
332 settings.hotkeys = (BOOL)INI_ReadInt ("hotkeys", 0);
334 #ifndef _WIN32
335 settings.full_res = (BOOL)INI_ReadInt ("full_res", 7);
336 settings.tex_filter = (BOOL)INI_ReadInt ("tex_filter", 0);
337 settings.noditheredalpha = (BOOL)INI_ReadInt ("noditheredalpha", 0);
338 settings.noglsl = (BOOL)INI_ReadInt ("noglsl", 0);
339 settings.FBO = (BOOL)INI_ReadInt ("fbo", 0);
340 settings.disable_auxbuf = (BOOL)INI_ReadInt ("disable_auxbuf", 0);
341 #endif
343 INI_Close ();
346 void ReadSpecialSettings (char name[21])
348 // char buf [256];
349 // sprintf(buf, "ReadSpecialSettings. Name: %s\n", name);
350 // LOG(buf);
351 settings.zelda = FALSE; //zeldas hacks
352 settings.bomberman64 = FALSE; //bomberman64 hacks
353 settings.diddy = FALSE; //diddy kong racing
354 settings.tonic = FALSE; //tonic trouble
355 settings.PPL = FALSE; //pokemon puzzle league requires many special fixes
356 settings.ASB = FALSE; //All-Star Baseball games
357 settings.doraemon2 = FALSE;//Doraemon 2
358 settings.invaders = FALSE; //Space Invaders
359 settings.BAR = FALSE; //Beetle Adventure Racing
360 settings.ISS64 = FALSE; //International Superstar Soccer 64
361 settings.RE2 = FALSE; //Resident Evil 2
362 settings.nitro = FALSE; //WCW Nitro
363 settings.chopper = FALSE; //Chopper Attack
364 settings.yoshi = FALSE; // Yoshi Story
365 settings.fzero = FALSE; // F-Zero
366 settings.PM = FALSE; //Paper Mario
367 settings.TGR = FALSE; //Top Gear Rally
368 settings.TGR2 = FALSE; //Top Gear Rally 2
369 settings.KI = FALSE; //Killer Instinct
370 settings.lego = FALSE; //LEGO Racers
372 //detect games which require special hacks
373 if (strstr(name, (const char *)"ZELDA") || strstr(name, (const char *)"MASK"))
374 settings.zelda = TRUE;
375 else if (strstr(name, (const char *)"ROADSTERS TROPHY"))
376 settings.zelda = TRUE;
377 else if (strstr(name, (const char *)"Diddy Kong Racing"))
378 settings.diddy = TRUE;
379 else if (strstr(name, (const char *)"BOMBERMAN64"))
380 settings.bomberman64 = TRUE;
381 else if (strstr(name, (const char *)"BAKU-BOMBERMAN"))
382 settings.bomberman64 = TRUE;
383 else if (strstr(name, (const char *)"Tonic Trouble"))
384 settings.tonic = TRUE;
385 else if (strstr(name, (const char *)"All") && strstr(name, (const char *)"Star") && strstr(name, (const char *)"Baseball"))
386 settings.ASB = TRUE;
387 else if (strstr(name, (const char *)"ÄÞ×´ÓÝ2 ˶ØɼÝÃÞÝ"))
388 settings.doraemon2 = TRUE;
389 else if (strstr(name, (const char *)"SPACE INVADERS"))
390 settings.invaders = TRUE;
391 else if (strstr(name, (const char *)"Beetle") || strstr(name, (const char *)"BEETLE") || strstr(name, (const char *)"HSV"))
392 settings.BAR = TRUE;
393 else if (strstr(name, (const char *)"I S S 64") || strstr(name, (const char *)"PERFECT STRIKER"))
394 settings.ISS64 = TRUE;
395 else if (strstr(name, (const char *)"NITRO64"))
396 settings.nitro = TRUE;
397 else if (strstr(name, (const char *)"CHOPPER_ATTACK"))
398 settings.chopper = TRUE;
399 else if (strstr(name, (const char *)"Resident Evil II") || strstr(name, (const char *)"BioHazard II"))
401 settings.RE2 = TRUE;
402 ZLUT_init();
404 else if (strstr(name, (const char *)"YOSHI STORY"))
405 settings.yoshi= TRUE;
406 else if (strstr(name, (const char *)"F-Zero X") || strstr(name, (const char *)"F-ZERO X"))
407 settings.fzero = TRUE;
408 else if (strstr(name, (const char *)"PAPER MARIO") || strstr(name, (const char *)"MARIO STORY"))
409 settings.PM = TRUE;
410 else if (strstr(name, (const char *)"TOP GEAR RALLY 2"))
411 settings.TGR2 = TRUE;
412 else if (strstr(name, (const char *)"TOP GEAR RALLY"))
413 settings.TGR = TRUE;
414 else if (strstr(name, (const char *)"Killer Instinct Gold") || strstr(name, (const char *)"KILLER INSTINCT GOLD"))
415 settings.KI = TRUE;
416 else if (strstr(name, (const char *)"LEGORacers"))
417 settings.lego = TRUE;
419 INI_Open ();
420 if (INI_FindSection (name,FALSE) == FALSE)
422 INI_Close ();
423 return;
426 int offset_x = INI_ReadInt ("offset_x", -1, 0);
427 int offset_y = INI_ReadInt ("offset_y", -1, 0);
428 int scale_x = INI_ReadInt ("scale_x", -1, 0);
429 int scale_y = INI_ReadInt ("scale_y", -1, 0);
430 int alt_tex_size = INI_ReadInt ("alt_tex_size", -1, 0);
431 int use_sts1_only = INI_ReadInt ("use_sts1_only", -1, 0);
432 int ppl = INI_ReadInt ("PPL", -1, 0);
433 // int texrect_zbuf = INI_ReadInt ("force_texrect_zbuf", -1, 0);
434 int optimize_texrect = INI_ReadInt ("optimize_texrect", -1, 0);
435 int optimize_write = INI_ReadInt ("optimize_write", -1, 0);
436 int ignore_aux_copy = INI_ReadInt ("ignore_aux_copy", -1, 0);
437 int ignore_previous = INI_ReadInt ("ignore_previous", -1, 0);
438 int hires_buf_clear = INI_ReadInt ("hires_buf_clear", -1, 0);
439 int wrap_big_tex = INI_ReadInt ("wrap_big_tex", -1, 0);
440 int tex_fix = INI_ReadInt ("fix_tex_coord", -1, 0);
441 int soft_depth_compare = INI_ReadInt ("soft_depth_compare", -1, 0);
442 int force_depth_compare = INI_ReadInt ("force_depth_compare", -1, 0);
443 int fillcolor_fix = INI_ReadInt ("fillcolor_fix", -1, 0);
444 int depth_bias = INI_ReadInt ("depth_bias", -1, 0);
445 int increase_texrect_edge = INI_ReadInt ("increase_texrect_edge", -1, 0);
446 int decrease_fillrect_edge = INI_ReadInt ("decrease_fillrect_edge", -1, 0);
447 int increase_primdepth = INI_ReadInt ("increase_primdepth", -1, 0);
448 int stipple_mode = INI_ReadInt ("stipple_mode", -1, 0);
449 int stipple_pattern = INI_ReadInt ("stipple_pattern", -1, 0);
450 int force_microcheck = INI_ReadInt ("force_microcheck", -1, 0);
451 int info_disable = INI_ReadInt ("fb_info_disable", -1, 0);
452 int hires_disable = INI_ReadInt ("fb_hires_disable", -1, 0);
454 if (offset_x != -1) settings.offset_x = offset_x;
455 if (offset_y != -1) settings.offset_y = offset_y;
456 if (scale_x != -1) settings.scale_x = scale_x;
457 if (scale_y != -1) settings.scale_y = scale_y;
458 if (alt_tex_size != -1) settings.alt_tex_size = alt_tex_size;
459 if (use_sts1_only != -1) settings.use_sts1_only = use_sts1_only;
460 if (ppl != -1) settings.PPL = ppl;
461 // if (texrect_zbuf != -1) settings.force_texrect_zbuf = texrect_zbuf;
462 if (optimize_texrect != -1) settings.fb_optimize_texrect = optimize_texrect;
463 if (optimize_write != -1) settings.fb_optimize_write = optimize_write;
464 if (ignore_aux_copy != -1) settings.fb_ignore_aux_copy = ignore_aux_copy;
465 if (hires_buf_clear != -1) settings.fb_hires_buf_clear = hires_buf_clear;
466 if (wrap_big_tex != -1) settings.wrap_big_tex = wrap_big_tex;
467 if (tex_fix != -1) settings.fix_tex_coord = tex_fix;
468 if (soft_depth_compare != -1) settings.soft_depth_compare = soft_depth_compare;
469 if (force_depth_compare != -1) settings.force_depth_compare = force_depth_compare;
470 if (fillcolor_fix != -1) settings.fillcolor_fix = fillcolor_fix;
471 if (depth_bias != -1) settings.depth_bias = -depth_bias;
472 if (increase_texrect_edge != -1) settings.increase_texrect_edge = increase_texrect_edge;
473 if (decrease_fillrect_edge != -1) settings.decrease_fillrect_edge = decrease_fillrect_edge;
474 if (increase_primdepth != -1) settings.increase_primdepth = increase_primdepth;
475 if (stipple_mode != -1) settings.stipple_mode = stipple_mode;
476 if (stipple_pattern != -1) settings.stipple_pattern = (DWORD)stipple_pattern;
477 if (force_microcheck != -1) settings.force_microcheck = force_microcheck;
478 if (ignore_previous != -1) settings.fb_ignore_previous = ignore_previous;
479 if (info_disable == 1) settings.fb_get_info = 0;
480 if (hires_disable == 1) settings.fb_hires = 0;
481 if (settings.lodmode == 0)
483 int lodmode = INI_ReadInt ("lodmode", -1, 0);
484 if (lodmode > 0)
485 settings.lodmode = lodmode;
488 if (settings.custom_ini)
490 int filtering = INI_ReadInt ("filtering", -1, 0);
491 int fog = INI_ReadInt ("fog", -1, 0);
492 int buff_clear = INI_ReadInt ("buff_clear", -1, 0);
493 int swapmode = INI_ReadInt ("swapmode", -1, 0);
494 int smart_read = INI_ReadInt ("fb_smart", -1, 0);
495 int read_alpha = INI_ReadInt ("fb_read_alpha", -1, 0);
496 int depth_clear = INI_ReadInt ("fb_clear", -1, 0);
497 //FIXME unused int depth_render = INI_ReadInt ("fb_render", -1, 0);
498 int resolution = (INT)INI_ReadInt ("resolution", -1, 0);
499 int cpu_write_hack = (INT)INI_ReadInt ("detect_cpu_write", -1, 0);
501 if (filtering != -1) settings.filtering = filtering;
502 if (fog != -1) settings.fog = fog;
503 if (buff_clear != -1) settings.buff_clear = buff_clear;
504 if (swapmode != -1) settings.swapmode= swapmode;
505 // settings.swapmode = 2;
506 if (smart_read != -1) settings.fb_smart = smart_read;
507 if (read_alpha != -1) settings.fb_read_alpha= read_alpha;
508 if (depth_clear != -1) settings.fb_depth_clear = depth_clear;
509 if (cpu_write_hack != -1) settings.cpu_write_hack = cpu_write_hack;
510 if (resolution != -1)
512 settings.res_data = (DWORD) resolution;
513 if (settings.res_data >= 0x18) settings.res_data = 12;
514 settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0];
515 settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1];
518 if (settings.fb_depth_render)
519 settings.fb_depth_clear = TRUE;
520 INI_Close ();
524 // WriteRegistry - writes the settings in the registry
527 void WriteSettings ()
529 INI_Open ();
530 INI_FindSection ("SETTINGS");
531 INI_WriteInt ("card_id", settings.card_id);
532 INI_WriteInt ("resolution", settings.res_data);
533 INI_WriteInt ("autodetect_ucode", settings.autodetect_ucode);
534 INI_WriteInt ("ucode", settings.ucode);
536 INI_WriteInt ("wireframe", settings.wireframe);
537 INI_WriteInt ("wfmode", settings.wfmode);
538 INI_WriteInt ("filtering", settings.filtering);
539 INI_WriteInt ("fog", settings.fog);
540 INI_WriteInt ("buff_clear", settings.buff_clear);
541 INI_WriteInt ("vsync", settings.vsync);
542 INI_WriteInt ("fast_crc", settings.fast_crc);
543 INI_WriteInt ("swapmode", settings.swapmode);
544 INI_WriteInt ("lodmode", settings.lodmode);
546 INI_WriteInt ("logging", settings.logging);
547 INI_WriteInt ("log_clear", settings.log_clear);
548 INI_WriteInt ("run_in_window", settings.run_in_window);
549 INI_WriteInt ("elogging", settings.elogging);
550 INI_WriteInt ("filter_cache", settings.filter_cache);
551 INI_WriteInt ("detect_cpu_write", settings.cpu_write_hack);
552 INI_WriteInt ("unk_as_red", settings.unk_as_red);
553 INI_WriteInt ("log_unk", settings.log_unk);
554 INI_WriteInt ("unk_clear", settings.unk_clear);
556 INI_WriteInt ("wrap_big_tex", settings.wrap_big_tex);
557 INI_WriteInt ("flame_corona", settings.flame_corona);
558 // INI_WriteInt ("RE2_native_video", settings.RE2_native_video);
561 INI_WriteInt ("show_fps", settings.show_fps);
563 INI_WriteInt ("clock", settings.clock);
564 INI_WriteInt ("clock_24_hr", settings.clock_24_hr);
566 INI_WriteInt ("fb_read_always", settings.fb_read_always);
567 INI_WriteInt ("fb_read_alpha", settings.fb_read_alpha);
568 INI_WriteInt ("fb_smart", settings.fb_smart);
569 INI_WriteInt ("motionblur", settings.fb_motionblur);
570 INI_WriteInt ("fb_hires", settings.fb_hires);
571 INI_WriteInt ("fb_get_info", settings.fb_get_info);
572 INI_WriteInt ("fb_clear", settings.fb_depth_clear);
573 INI_WriteInt ("fb_render", settings.fb_depth_render);
575 INI_WriteInt ("custom_ini", settings.custom_ini);
576 INI_WriteInt ("hotkeys", settings.hotkeys);
578 #ifndef _WIN32
579 INI_WriteInt ("full_res", settings.full_res);
580 INI_WriteInt ("tex_filter", settings.tex_filter);
581 INI_WriteInt ("noditheredalpha", settings.noditheredalpha);
582 INI_WriteInt ("noglsl", settings.noglsl);
583 INI_WriteInt ("fbo", settings.FBO);
584 #endif
586 INI_Close ();
589 #ifndef _WIN32
590 #include "font.h"
591 #include "cursor.h"
592 #endif // _WIN32
594 GRFRAMEBUFFERCOPYEXT grFramebufferCopyExt = NULL;
595 GRTEXBUFFEREXT grTextureBufferExt = NULL;
596 GRTEXBUFFEREXT grTextureAuxBufferExt = NULL;
597 GRAUXBUFFEREXT grAuxBufferExt = NULL;
598 GRSTIPPLE grStippleModeExt = NULL;
599 GRSTIPPLE grStipplePatternExt = NULL;
600 BOOL combineext = FALSE;
602 BOOL depthbuffersave = FALSE;
604 // guLoadTextures - used to load the cursor and font textures
605 void guLoadTextures ()
607 if (grTextureBufferExt)
609 int tbuf_size = 0;
610 if (max_tex_size <= 256)
612 grTextureBufferExt( GR_TMU1, grTexMinAddress(GR_TMU1), GR_LOD_LOG2_256, GR_LOD_LOG2_256,
613 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
614 tbuf_size = 8 * grTexCalcMemRequired(GR_LOD_LOG2_256, GR_LOD_LOG2_256,
615 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);
617 else if (settings.scr_res_x <= 1024)
619 grTextureBufferExt( GR_TMU1, grTexMinAddress(GR_TMU1), GR_LOD_LOG2_1024, GR_LOD_LOG2_1024,
620 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
621 tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_1024, GR_LOD_LOG2_1024,
622 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);
624 else
626 grTextureBufferExt( GR_TMU1, grTexMinAddress(GR_TMU1), GR_LOD_LOG2_2048, GR_LOD_LOG2_2048,
627 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
628 tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_2048, GR_LOD_LOG2_2048,
629 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);
632 //tbuf_size *= 2;
633 printf("tbuf_size %gMb\n", tbuf_size/1024.0f/1024);
634 rdp.texbufs[0].tmu = GR_TMU0;
635 rdp.texbufs[0].begin = grTexMinAddress(GR_TMU0);
636 rdp.texbufs[0].end = rdp.texbufs[0].begin+tbuf_size;
637 rdp.texbufs[0].count = 0;
638 rdp.texbufs[0].clear_allowed = TRUE;
639 if (num_tmu > 1)
641 rdp.texbufs[1].tmu = GR_TMU1;
642 rdp.texbufs[1].begin = grTexMinAddress(GR_TMU1);
643 rdp.texbufs[1].end = rdp.texbufs[1].begin+tbuf_size;
644 rdp.texbufs[1].count = 0;
645 rdp.texbufs[1].clear_allowed = TRUE;
646 offset_texbuf1 = tbuf_size;
648 offset_font = tbuf_size;
650 else
651 offset_font = 0;
653 #ifdef _WIN32
654 char path[256];
655 GetModuleFileName (hInstance, path, 256);
656 HMODULE hModule = GetModuleHandle (path);
658 HRSRC hrsrc = FindResource (hModule, MAKEINTRESOURCE(IDR_FONT), RT_RCDATA);
659 DWORD *data = (DWORD*)LoadResource (hModule, hrsrc);
660 DWORD cur;
661 #else
662 DWORD *data = (DWORD*)font;
663 DWORD cur;
664 #endif // _WIN32
666 // ** Font texture **
667 BYTE *tex8 = (BYTE*)malloc(256*64);
669 fontTex.smallLodLog2 = fontTex.largeLodLog2 = GR_LOD_LOG2_256;
670 fontTex.aspectRatioLog2 = GR_ASPECT_LOG2_4x1;
671 fontTex.format = GR_TEXFMT_ALPHA_8;
672 fontTex.data = tex8;
674 // Decompression: [1-bit inverse alpha --> 8-bit alpha]
675 DWORD i,b;
676 for (i=0; i<0x200; i++)
678 // cur = ~*(data++), byteswapped
679 #ifndef GCC
680 __asm {
681 mov eax, dword ptr [data]
682 mov ecx, dword ptr [eax]
683 add eax, 4
684 mov dword ptr [data], eax
685 not ecx
686 bswap ecx
687 mov dword ptr [cur],ecx
689 #else // _WIN32
690 asm volatile ("bswap %[cur]"
691 : [cur] "=g"(cur)
692 : "[cur]"(~*(data++))
694 #endif // _WIN32
696 for (b=0x80000000; b!=0; b>>=1)
698 if (cur&b) *tex8 = 0xFF;
699 else *tex8 = 0x00;
700 tex8 ++;
704 grTexDownloadMipMap (GR_TMU0,
705 grTexMinAddress(GR_TMU0) + offset_font,
706 GR_MIPMAPLEVELMASK_BOTH,
707 &fontTex);
709 offset_cursor = offset_font + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &fontTex);
711 free (fontTex.data);
713 // ** Cursor texture **
714 #ifdef _WIN32
715 hrsrc = FindResource (hModule, MAKEINTRESOURCE(IDR_CURSOR), RT_RCDATA);
716 data = (DWORD*)LoadResource (hModule, hrsrc);
717 #else // _WIN32
718 data = (DWORD*)cursor;
719 #endif // _WIN32
721 WORD *tex16 = (WORD*)malloc(32*32*2);
723 cursorTex.smallLodLog2 = cursorTex.largeLodLog2 = GR_LOD_LOG2_32;
724 cursorTex.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
725 cursorTex.format = GR_TEXFMT_ARGB_1555;
726 cursorTex.data = tex16;
728 // Conversion: [16-bit 1555 (swapped) --> 16-bit 1555]
729 for (i=0; i<0x200; i++)
731 cur = *(data++);
732 *(tex16++) = (WORD)(((cur&0x000000FF)<<8)|((cur&0x0000FF00)>>8));
733 *(tex16++) = (WORD)(((cur&0x00FF0000)>>8)|((cur&0xFF000000)>>24));
736 grTexDownloadMipMap (GR_TMU0,
737 grTexMinAddress(GR_TMU0) + offset_cursor,
738 GR_MIPMAPLEVELMASK_BOTH,
739 &cursorTex);
741 // Round to higher 16
742 offset_textures = ((offset_cursor + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &cursorTex))
743 & 0xFFFFFFF0) + 16;
744 free (cursorTex.data);
748 BOOL InitGfx (BOOL evoodoo_using_window)
750 if (fullscreen)
752 ReleaseGfx ();
755 OPEN_RDP_LOG (); // doesn't matter if opens again; it will check for it
756 OPEN_RDP_E_LOG ();
757 LOG ("InitGfx ()\n");
759 debugging = FALSE;
761 // Initialize Glide
762 grGlideInit ();
764 // Select the Glide device
765 grSstSelect (settings.card_id);
767 gfx_context = 0;
768 // Select the window
770 if (settings.fb_hires)
772 printf("fb_hires\n");
773 GRWINOPENEXT grSstWinOpenExt = (GRWINOPENEXT)grGetProcAddress("grSstWinOpenExt");
774 if (grSstWinOpenExt)
775 gfx_context = grSstWinOpenExt ((FxU32)gfx.hWnd,
776 settings.res_data | ((evoodoo_using_window)?0x80:0x00),
777 GR_REFRESH_60Hz,
778 GR_COLORFORMAT_RGBA,
779 GR_ORIGIN_UPPER_LEFT,
780 GR_PIXFMT_RGB_565,
781 2, // Double-buffering
782 1); // 1 auxillary buffer
784 if (!gfx_context)
785 gfx_context = grSstWinOpen ((FxU32)gfx.hWnd,
786 settings.res_data | ((evoodoo_using_window)?0x80:0x00),
787 GR_REFRESH_60Hz,
788 GR_COLORFORMAT_RGBA,
789 GR_ORIGIN_UPPER_LEFT,
790 2, // Double-buffering
791 1); // 1 auxillary buffer
793 if (!gfx_context)
795 #ifdef _WIN32
796 MessageBox (gfx.hWnd, "Error setting display mode", "Error", MB_OK|MB_ICONEXCLAMATION);
797 #else // _WIN32
798 messagebox("Error", MB_OK|MB_ICONEXCLAMATION, "Error setting display mode");
799 #endif // _WIN32
800 grSstWinClose (gfx_context);
801 grGlideShutdown ();
802 return FALSE;
805 // get the # of TMUs available
806 grGet (GR_NUM_TMU, 4, &num_tmu);
807 printf("num_tmu %ld\n", num_tmu);
808 // get maximal texture size
809 grGet (GR_MAX_TEXTURE_SIZE, 4, &max_tex_size);
810 //num_tmu = 1;
812 // Is mirroring allowed?
813 const char *extensions = grGetString (GR_EXTENSION);
815 printf("bebefore\n");
816 if (strstr (extensions, "TEXMIRROR"))
817 sup_mirroring = 1;
818 else
819 sup_mirroring = 0;
821 if (strstr (extensions, "TEXFMT")) //VSA100 texture format extension
822 sup_32bit_tex = TRUE;
823 else
824 sup_32bit_tex = FALSE;
826 printf("bebefore2\n");
827 if (settings.fb_hires)
829 if (char * extstr = strstr(extensions, "TEXTUREBUFFER"))
831 if (!strncmp(extstr, "TEXTUREBUFFER", 13))
833 grTextureBufferExt = (GRTEXBUFFEREXT) grGetProcAddress("grTextureBufferExt");
834 grTextureAuxBufferExt = (GRTEXBUFFEREXT) grGetProcAddress("grTextureAuxBufferExt");
835 grAuxBufferExt = (GRAUXBUFFEREXT) grGetProcAddress("grAuxBufferExt");
838 else
839 settings.fb_hires = 0;
841 else
842 grTextureBufferExt = 0;
844 grFramebufferCopyExt = (GRFRAMEBUFFERCOPYEXT) grGetProcAddress("grFramebufferCopyExt");
845 printf("before\n");
846 #ifdef _WIN32
847 HMODULE HGLIDE = GetModuleHandle("glide3x");
848 grStippleModeExt = (GRSTIPPLE) GetProcAddress(HGLIDE, "_grStippleMode@4");
849 grStipplePatternExt = (GRSTIPPLE) GetProcAddress(HGLIDE, "_grStipplePattern@4");
850 #else // _WIN32
851 grStippleModeExt = (GRSTIPPLE) grStippleMode;
852 grStipplePatternExt = (GRSTIPPLE) grStipplePattern;
853 #endif // _WIN32
854 printf("after\n");
855 if (grStipplePatternExt)
856 grStipplePatternExt(settings.stipple_pattern);
858 InitCombine();
860 #ifdef SIMULATE_VOODOO1
861 num_tmu = 1;
862 sup_mirroring = 0;
863 #endif
865 #ifdef SIMULATE_BANSHEE
866 num_tmu = 1;
867 sup_mirroring = 1;
868 #endif
870 fullscreen = TRUE;
872 if (evoodoo_using_window)
873 ev_fullscreen = FALSE;
874 else
875 ev_fullscreen = TRUE;
877 grCoordinateSpace (GR_WINDOW_COORDS);
878 grVertexLayout (GR_PARAM_XY, offsetof(VERTEX,x), GR_PARAM_ENABLE);
879 grVertexLayout (GR_PARAM_Q, offsetof(VERTEX,q), GR_PARAM_ENABLE);
880 grVertexLayout (GR_PARAM_Z, offsetof(VERTEX,z), GR_PARAM_ENABLE);
881 grVertexLayout (GR_PARAM_ST0, offsetof(VERTEX,coord[0]), GR_PARAM_ENABLE);
882 grVertexLayout (GR_PARAM_ST1, offsetof(VERTEX,coord[2]), GR_PARAM_ENABLE);
883 grVertexLayout (GR_PARAM_PARGB, offsetof(VERTEX,b), GR_PARAM_ENABLE);
885 grCullMode(GR_CULL_NEGATIVE);
887 if (settings.fog) //"FOGCOORD" extension
889 if (strstr (extensions, "FOGCOORD"))
891 GrFog_t fog_t[64];
892 guFogGenerateLinear (fog_t, 0.0f, 255.0f);//(float)rdp.fog_multiplier + (float)rdp.fog_offset);//256.0f);
894 for (int i = 63; i > 0; i--)
896 if (fog_t[i] - fog_t[i-1] > 63)
898 fog_t[i-1] = fog_t[i] - 63;
901 fog_t[0] = 0;
902 // for (int f = 0; f < 64; f++)
903 // {
904 // FRDP("fog[%d]=%d->%f\n", f, fog_t[f], guFogTableIndexToW(f));
905 // }
906 grFogTable (fog_t);
907 grVertexLayout (GR_PARAM_FOG_EXT, offsetof(VERTEX,f), GR_PARAM_ENABLE);
909 else //not supported
910 settings.fog = FALSE;
913 //grDepthBufferMode (GR_DEPTHBUFFER_WBUFFER);
914 grDepthBufferMode (GR_DEPTHBUFFER_ZBUFFER);
915 grDepthBufferFunction(GR_CMP_LESS);
916 grDepthMask(FXTRUE);
918 settings.res_x = settings.scr_res_x;
919 settings.res_y = settings.scr_res_y;
920 ChangeSize ();
922 guLoadTextures ();
923 grRenderBuffer(GR_BUFFER_BACKBUFFER);
925 rdp_reset ();
926 ClearCache ();
928 rdp.update |= UPDATE_SCISSOR;
930 return TRUE;
933 void ReleaseGfx ()
935 // Release graphics
936 grSstWinClose (gfx_context);
938 // Shutdown glide
939 grGlideShutdown();
941 fullscreen = FALSE;
942 rdp.window_changed = TRUE;
946 // DllMain - called when the DLL is loaded, use this to get the DLL's instance
949 #ifdef _WIN32
950 //#ifndef GCC
951 BOOL CALLBACK ConfigPageProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
952 BOOL CALLBACK DebugPageProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
953 BOOL CALLBACK StatisticsPageProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
955 extern "C" {
956 BOOL WINAPI DllMain (HINSTANCE hinstDLL,
957 DWORD fdwReason,
958 LPVOID lpReserved);
960 BOOL WINAPI DllMain (HINSTANCE hinstDLL,
961 DWORD fdwReason,
962 LPVOID lpReserved)
964 hInstance = hinstDLL;
966 sprintf (out_buf, "DllMain (%08lx - %d)\n", hinstDLL, fdwReason);
967 LOG (out_buf);
969 printf("DLLMain\n");
971 if (fdwReason == DLL_PROCESS_ATTACH)
973 memset(m_psp, 0, sizeof(m_psp));
974 memset(&m_PropSheet, 0, sizeof(m_PropSheet));
976 m_psp[0].dwSize = sizeof(PROPSHEETPAGE);
977 m_psp[0].dwFlags = PSP_USETITLE;
978 m_psp[0].hInstance = hInstance;
979 m_psp[0].pszTemplate = (LPCSTR)IDD_CONFIG;
980 m_psp[0].pszTitle = "Config";
981 m_psp[0].pfnDlgProc = (DLGPROC)ConfigPageProc;
983 m_psp[1].dwSize = sizeof(PROPSHEETPAGE);
984 m_psp[1].dwFlags = PSP_USETITLE;
985 m_psp[1].hInstance = hInstance;
986 m_psp[1].pszTemplate = (LPCSTR)IDD_STATISTICS;
987 m_psp[1].pszTitle = "On screen info";
988 m_psp[1].pfnDlgProc = (DLGPROC)StatisticsPageProc;
990 #ifndef _FINAL_RELEASE_
991 m_psp[2].dwSize = sizeof(PROPSHEETPAGE);
992 m_psp[2].dwFlags = PSP_USETITLE;
993 m_psp[2].hInstance = hInstance;
994 m_psp[2].pszTemplate = (LPCSTR)IDD_DEBUG;
995 m_psp[2].pszTitle = "Debug";
996 m_psp[2].pfnDlgProc = (DLGPROC)DebugPageProc;
998 m_PropSheet.nPages = 3;
999 #else
1000 m_PropSheet.nPages = 2;
1001 #endif
1003 m_PropSheet.dwSize = sizeof(PROPSHEETHEADER);
1004 m_PropSheet.dwFlags = PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW;
1005 // m_PropSheet.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK | PSH_NOAPPLYNOW;
1006 m_PropSheet.hInstance = hInstance;
1007 // m_PropSheet.hwndParent = hParent;
1008 m_PropSheet.pszCaption = (LPSTR) "Glide64 settings";
1009 m_PropSheet.nStartPage = 0;
1010 m_PropSheet.ppsp = (LPCPROPSHEETPAGE)m_psp;
1011 // m_PropSheet.pfnCallback = (PFNPROPSHEETCALLBACK) SheetProc;
1013 return TRUE;
1015 #endif // _WIN32
1017 void CALL ReadScreen(void **dest, long *width, long *height)
1019 *width = settings.res_x;
1020 *height = settings.res_y;
1021 BYTE * buff = new BYTE [settings.res_x * settings.res_y * 3];
1022 BYTE * line = buff;
1023 *dest = (void*)buff;
1025 if (!fullscreen)
1027 for (DWORD y=0; y<settings.res_y; y++)
1029 for (DWORD x=0; x<settings.res_x; x++)
1031 line[x*3] = 0x20;
1032 line[x*3+1] = 0x7f;
1033 line[x*3+2] = 0x40;
1036 LOG ("ReadScreen. not in the fullscreen!\n");
1037 return;
1040 GrLfbInfo_t info;
1041 info.size = sizeof(GrLfbInfo_t);
1042 #if 1
1043 printf("plop\n");
1044 if (grLfbLock (GR_LFB_READ_ONLY,
1045 GR_BUFFER_FRONTBUFFER,
1046 GR_LFBWRITEMODE_888,
1047 GR_ORIGIN_UPPER_LEFT,
1048 FXFALSE,
1049 &info))
1051 DWORD offset_src=info.strideInBytes*(settings.scr_res_y-1);
1053 // Copy the screen
1054 DWORD col;
1055 BYTE r, g, b;
1056 for (DWORD y=0; y<settings.res_y; y++)
1058 DWORD *ptr = (DWORD*)((BYTE*)info.lfbPtr + offset_src);
1059 for (DWORD x=0; x<settings.res_x; x++)
1061 col = *(ptr++);
1062 r = (col >> 16);
1063 g = (col >> 8) & 0xFF;
1064 b = col & 0xFF;
1065 line[x*3] = b;
1066 line[x*3+1] = g;
1067 line[x*3+2] = r;
1069 line += settings.res_x * 3;
1070 offset_src -= info.strideInBytes;
1073 // Unlock the frontbuffer
1074 grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER);
1076 #else
1077 if (grLfbLock (GR_LFB_READ_ONLY,
1078 GR_BUFFER_FRONTBUFFER,
1079 GR_LFBWRITEMODE_565,
1080 GR_ORIGIN_UPPER_LEFT,
1081 FXFALSE,
1082 &info))
1084 DWORD offset_src=info.strideInBytes*(settings.scr_res_y-1);
1086 // Copy the screen
1087 WORD col;
1088 BYTE r, g, b;
1089 for (DWORD y=0; y<settings.res_y; y++)
1091 WORD *ptr = (WORD*)((BYTE*)info.lfbPtr + offset_src);
1092 for (DWORD x=0; x<settings.res_x; x++)
1094 col = *(ptr++);
1095 r = (BYTE)((float)(col >> 11) / 31.0f * 255.0f);
1096 g = (BYTE)((float)((col >> 5) & 0x3F) / 63.0f * 255.0f);
1097 b = (BYTE)((float)(col & 0x1F) / 31.0f * 255.0f);
1098 line[x*3] = b;
1099 line[x*3+1] = g;
1100 line[x*3+2] = r;
1102 line += settings.res_x * 3;
1103 offset_src -= info.strideInBytes;
1106 // Unlock the frontbuffer
1107 grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER);
1109 #endif
1110 LOG ("ReadScreen. Success.\n");
1113 /******************************************************************
1114 Function: CaptureScreen
1115 Purpose: This function dumps the current frame to a file
1116 input: pointer to the directory to save the file to
1117 output: none
1118 *******************************************************************/
1119 EXPORT void CALL CaptureScreen ( char * Directory )
1121 capture_screen = 1;
1122 strcpy (capture_path, Directory);
1125 /******************************************************************
1126 Function: ChangeWindow
1127 Purpose: to change the window between fullscreen and window
1128 mode. If the window was in fullscreen this should
1129 change the screen to window mode and vice vesa.
1130 input: none
1131 output: none
1132 *******************************************************************/
1133 EXPORT void CALL ChangeWindow (void)
1135 LOG ("ChangeWindow()\n");
1137 if (evoodoo)
1139 if (!ev_fullscreen)
1141 to_fullscreen = TRUE;
1142 #ifdef _WIN32
1143 if (gfx.hStatusBar)
1144 ShowWindow( gfx.hStatusBar, SW_HIDE );
1145 ShowCursor( FALSE );
1146 #endif // _WIN32
1147 GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt =
1148 (GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress("grWrapperFullScreenResolutionExt");
1149 if (grWrapperFullScreenResolutionExt != NULL)
1151 settings.res_data_org = settings.res_data;
1152 settings.res_data = grWrapperFullScreenResolutionExt();
1153 settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0];
1154 settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1];
1157 else
1159 ReleaseGfx ();
1160 GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt =
1161 (GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress("grWrapperFullScreenResolutionExt");
1162 if (grWrapperFullScreenResolutionExt != NULL)
1164 settings.res_data = settings.res_data_org;
1165 settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0];
1166 settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1];
1168 InitGfx (TRUE);
1169 #ifdef _WN32
1170 ShowCursor( TRUE );
1171 if (gfx.hStatusBar)
1172 ShowWindow( gfx.hStatusBar, SW_SHOW );
1173 SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
1174 #endif // _WIN32
1177 else
1179 // Go to fullscreen at next dlist
1180 // This is for compatibility with 1964, which reloads the plugin
1181 // when switching to fullscreen
1182 if (!fullscreen)
1184 to_fullscreen = TRUE;
1185 #ifdef _WIN32
1186 if (gfx.hStatusBar)
1187 ShowWindow( gfx.hStatusBar, SW_HIDE );
1188 ShowCursor( FALSE );
1189 #endif // _WIN32
1191 else
1193 ReleaseGfx ();
1194 #ifdef _WIN32
1195 ShowCursor( TRUE );
1196 if (gfx.hStatusBar)
1197 ShowWindow( gfx.hStatusBar, SW_SHOW );
1198 // SetWindowLong fixes the following Windows XP Banshee issues:
1199 // 1964 crash error when loading another rom.
1200 // All N64 emu's minimize, restore crashes.
1201 SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
1202 #endif // _WIN32
1207 /******************************************************************
1208 Function: CloseDLL
1209 Purpose: This function is called when the emulator is closing
1210 down allowing the dll to de-initialise.
1211 input: none
1212 output: none
1213 *******************************************************************/
1214 EXPORT void CALL CloseDLL (void)
1216 LOG ("CloseDLL ()\n");
1218 // re-set the old window proc
1219 #ifdef WINPROC_OVERRIDE
1220 SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
1221 #endif
1223 #ifdef ALTTAB_FIX
1224 if (hhkLowLevelKybd)
1226 UnhookWindowsHookEx(hhkLowLevelKybd);
1227 hhkLowLevelKybd = 0;
1229 #endif
1231 //CLOSELOG ();
1233 if (fullscreen)
1234 ReleaseGfx ();
1235 ZLUT_release();
1236 ClearCache ();
1238 #ifdef _WIN32
1239 //taken from 1964 sources
1240 LRESULT APIENTRY About(HWND hDlg, unsigned message, WORD wParam, LONG lParam)
1242 switch(message)
1244 case WM_INITDIALOG: return(TRUE);
1246 case WM_COMMAND: if(wParam == IDOK || wParam == IDCANCEL){ EndDialog(hDlg, TRUE); return(TRUE); }break;
1249 return(FALSE);
1251 #endif // _WIN32
1252 /******************************************************************
1253 Function: DllAbout
1254 Purpose: This function is optional function that is provided
1255 to give further information about the DLL.
1256 input: a handle to the window that calls this function
1257 output: none
1258 *******************************************************************/
1259 EXPORT void CALL DllAbout ( HWND hParent )
1261 #ifdef _WIN32
1262 DialogBox(hInstance, "ABOUT", hParent, (DLGPROC) About);
1263 #else // _WIN32
1264 messagebox("Glide64 v"G64_VERSION, MB_OK,
1265 "Glide64 "G64_VERSION"\nRelease: " RELTIME "\n"
1266 "by Gonetz\nOriginal author: Dave2001\nOther developers: Gugaman\n\n"
1267 "Beta testers: Raziel64, Federelli, Flash\n\n"
1268 "Special thanks to:\n"
1269 "Niki, FiRES, Icepir8, Rice, ZeZu, Azimer, Hacktarux, Cyberman, LoneRaven, Falcon4ever,\n"
1270 "GokuSS4, _Demo_, Ogy, Quvack, Scorpiove, CpUMasteR, Doom, Lemmy, CyRUS64,\n"
1271 "McLeod, Linker, StrmnNrmn, Tekken, ExtendedPlay, Kool Smoky\n"
1272 "everyone at EmuXHaven, all my testers, anyone I've forgotten, and anyone else on\n"
1273 "the Emutalk message board who helped or brought encouragement\n\n"
1274 "Thanks to EmuXHaven for hosting my site:\nhttp://glide64.emuxhaven.net/\n\n"
1275 "Official development channel: #Glide64 on EFnet\nNO ROM REQUESTS / NO BETA REQUESTS");
1276 #endif // _WIN32
1279 /******************************************************************
1280 Function: DllTest
1281 Purpose: This function is optional function that is provided
1282 to allow the user to test the dll
1283 input: a handle to the window that calls this function
1284 output: none
1285 *******************************************************************/
1286 EXPORT void CALL DllTest ( HWND hParent )
1290 /******************************************************************
1291 Function: DrawScreen
1292 Purpose: This function is called when the emulator receives a
1293 WM_PAINT message. This allows the gfx to fit in when
1294 it is being used in the desktop.
1295 input: none
1296 output: none
1297 *******************************************************************/
1298 EXPORT void CALL DrawScreen (void)
1300 LOG ("DrawScreen ()\n");
1303 /******************************************************************
1304 Function: GetDllInfo
1305 Purpose: This function allows the emulator to gather information
1306 about the dll by filling in the PluginInfo structure.
1307 input: a pointer to a PLUGIN_INFO stucture that needs to be
1308 filled by the function. (see def above)
1309 output: none
1310 *******************************************************************/
1311 #ifdef WIN32
1312 # include <fcntl.h>
1313 # ifndef ATTACH_PARENT_PROCESS
1314 # define ATTACH_PARENT_PROCESS ((DWORD)-1)
1315 # endif
1317 typedef BOOL (WINAPI * AttachConsoleType)(DWORD);
1318 BOOL (WINAPI * AttachConsolePTR)(DWORD);
1319 #endif
1321 EXPORT void CALL GetDllInfo ( PLUGIN_INFO * PluginInfo )
1323 #ifdef WIN32x
1324 // ZIGGY code to attach to console and use it
1325 HANDLE libhnd;
1326 if ((libhnd = LoadLibrary("KERNEL32")) && (AttachConsolePTR = (AttachConsoleType)GetProcAddress((HINSTANCE__*)libhnd, "AttachConsole")) && AttachConsolePTR(ATTACH_PARENT_PROCESS))
1328 FILE * newstdout = freopen("CON", "w", stdout);
1329 FILE * newstderr = freopen("CON", "w", stderr);
1330 FILE * newstdin = freopen("CON", "r", stdin);
1331 } else {
1332 // AllocConsole();
1333 // FILE * newstdout = freopen("CON", "w", stdout);
1334 // FILE * newstderr = freopen("CON", "w", stderr);
1335 // FILE * newstdin = freopen("CON", "r", stdin);
1336 FILE * newstdout = freopen("stdout.txt", "w", stdout);
1337 _dup2(_fileno(stdout), _fileno(stderr));
1338 //FILE * newstderr = freopen("stderr.txt", "w", stderr);
1340 // _dup2(0, _fileno(stdout));
1341 // _dup2(1, _fileno(stdin));
1342 // _dup2(2, _fileno(stderr));
1343 #endif
1345 PluginInfo->Version = 0x0103; // Set to 0x0103
1346 PluginInfo->Type = PLUGIN_TYPE_GFX; // Set to PLUGIN_TYPE_GFX
1347 sprintf (PluginInfo->Name, "Glide64 "G64_VERSION); // Name of the DLL
1349 // If DLL supports memory these memory options then set them to TRUE or FALSE
1350 // if it does not support it
1351 PluginInfo->NormalMemory = TRUE; // a normal BYTE array
1352 PluginInfo->MemoryBswaped = TRUE; // a normal BYTE array where the memory has been pre
1353 // bswap on a dword (32 bits) boundry
1356 #ifndef _WIN32
1357 BOOL WINAPI QueryPerformanceCounter(PLARGE_INTEGER counter)
1359 struct timeval tv;
1361 /* generic routine */
1362 gettimeofday( &tv, NULL );
1363 counter->QuadPart = (LONGLONG)tv.tv_usec + (LONGLONG)tv.tv_sec * 1000000;
1364 return TRUE;
1367 BOOL WINAPI QueryPerformanceFrequency(PLARGE_INTEGER frequency)
1369 frequency->s.LowPart= 1000000;
1370 frequency->s.HighPart= 0;
1371 return TRUE;
1373 #endif
1375 /******************************************************************
1376 Function: InitiateGFX
1377 Purpose: This function is called when the DLL is started to give
1378 information from the emulator that the n64 graphics
1379 uses. This is not called from the emulation thread.
1380 Input: Gfx_Info is passed to this function which is defined
1381 above.
1382 Output: TRUE on success
1383 FALSE on failure to initialise
1385 ** note on interrupts **:
1386 To generate an interrupt set the appropriate bit in MI_INTR_REG
1387 and then call the function CheckInterrupts to tell the emulator
1388 that there is a waiting interrupt.
1389 *******************************************************************/
1391 EXPORT BOOL CALL InitiateGFX (GFX_INFO Gfx_Info)
1393 LOG ("InitiateGFX (*)\n");
1394 // Do *NOT* put this in rdp_reset or it could be set after the screen is initialized
1395 num_tmu = 2;
1397 // Assume scale of 1 for debug purposes
1398 rdp.scale_x = 1.0f;
1399 rdp.scale_y = 1.0f;
1401 memset (&settings, 0, sizeof(SETTINGS));
1402 ReadSettings ();
1404 #ifdef FPS
1405 QueryPerformanceFrequency (&perf_freq);
1406 QueryPerformanceCounter (&fps_last);
1407 #endif
1409 debug_init (); // Initialize debugger
1411 gfx = Gfx_Info;
1413 char name[21];
1414 // get the name of the ROM
1415 for (int i=0; i<20; i++)
1416 name[i] = gfx.HEADER[(32+i)^3];
1417 name[20] = 0;
1419 // remove all trailing spaces
1420 while (name[strlen(name)-1] == ' ')
1421 name[strlen(name)-1] = 0;
1423 ReadSpecialSettings (name);
1425 #ifdef WINPROC_OVERRIDE
1426 if (!oldWndProc)
1428 myWndProc = (WNDPROC)WndProc;
1429 oldWndProc = (WNDPROC)SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)myWndProc);
1431 #endif
1433 util_init ();
1434 math_init ();
1435 TexCacheInit ();
1436 CRC_BuildTable();
1437 CountCombine();
1438 if (settings.fb_depth_render)
1439 ZLUT_init();
1441 return TRUE;
1444 /******************************************************************
1445 Function: MoveScreen
1446 Purpose: This function is called in response to the emulator
1447 receiving a WM_MOVE passing the xpos and ypos passed
1448 from that message.
1449 input: xpos - the x-coordinate of the upper-left corner of the
1450 client area of the window.
1451 ypos - y-coordinate of the upper-left corner of the
1452 client area of the window.
1453 output: none
1454 *******************************************************************/
1455 EXPORT void CALL MoveScreen (int xpos, int ypos)
1457 LOG ("MoveScreen (" << xpos << ", " << ypos << ")\n");
1460 /******************************************************************
1461 Function: ProcessRDPList
1462 Purpose: This function is called when there is a Dlist to be
1463 processed. (Low level GFX list)
1464 input: none
1465 output: none
1466 *******************************************************************/
1467 #if 0
1468 EXPORT void CALL ProcessRDPList(void)
1470 if (settings.KI)
1472 *gfx.MI_INTR_REG |= 0x20;
1473 gfx.CheckInterrupts();
1475 LOG ("ProcessRDPList ()\n");
1476 printf("ProcessRPDList %x %x %x\n",
1477 *gfx.DPC_START_REG,
1478 *gfx.DPC_END_REG,
1479 *gfx.DPC_CURRENT_REG);
1480 //*gfx.DPC_STATUS_REG = 0xffffffff; // &= ~0x0002;
1482 //*gfx.DPC_START_REG = *gfx.DPC_END_REG;
1483 *gfx.DPC_CURRENT_REG = *gfx.DPC_END_REG;
1485 #endif
1487 /******************************************************************
1488 Function: RomClosed
1489 Purpose: This function is called when a rom is closed.
1490 input: none
1491 output: none
1492 *******************************************************************/
1493 EXPORT void CALL RomClosed (void)
1495 LOG ("RomClosed ()\n");
1497 CLOSE_RDP_LOG ();
1498 CLOSE_RDP_E_LOG ();
1499 rdp.window_changed = TRUE;
1500 romopen = FALSE;
1501 if (fullscreen && evoodoo)
1502 ReleaseGfx ();
1505 BOOL no_dlist = TRUE;
1507 /******************************************************************
1508 Function: RomOpen
1509 Purpose: This function is called when a rom is open. (from the
1510 emulation thread)
1511 input: none
1512 output: none
1513 *******************************************************************/
1514 EXPORT void CALL RomOpen (void)
1516 LOG ("RomOpen ()\n");
1517 no_dlist = TRUE;
1518 romopen = TRUE;
1519 ucode_error_report = TRUE; // allowed to report ucode errors
1521 // Get the country code & translate to NTSC(0) or PAL(1)
1522 WORD code = ((WORD*)gfx.HEADER)[0x1F^1];
1524 if (code == 0x4400) region = 1; // Germany (PAL)
1525 if (code == 0x4500) region = 0; // USA (NTSC)
1526 if (code == 0x4A00) region = 0; // Japan (NTSC)
1527 if (code == 0x5000) region = 1; // Europe (PAL)
1528 if (code == 0x5500) region = 0; // Australia (NTSC)
1530 char name[21] = "DEFAULT";
1531 ReadSpecialSettings (name);
1533 // get the name of the ROM
1534 for (int i=0; i<20; i++)
1535 name[i] = gfx.HEADER[(32+i)^3];
1536 name[20] = 0;
1538 // remove all trailing spaces
1539 while (name[strlen(name)-1] == ' ')
1540 name[strlen(name)-1] = 0;
1542 ReadSpecialSettings (name);
1545 printf("fb_clear %d fb_smart %d\n", settings.fb_depth_clear, settings.fb_smart);
1548 rdp_reset ();
1549 ClearCache ();
1551 /* JOSH FIXME: Needed in non-WIN32 case? */
1552 #ifndef GCC
1553 __try
1555 BYTE test = gfx.RDRAM[5000000];
1557 __except (EXCEPTION_EXECUTE_HANDLER)
1559 BMASK = WMASK;
1561 #endif // _WIN32
1563 OPEN_RDP_LOG ();
1564 OPEN_RDP_E_LOG ();
1566 // ** EVOODOO EXTENSIONS **
1567 if (!fullscreen)
1569 grGlideInit ();
1570 grSstSelect (0);
1572 const char *extensions = grGetString (GR_EXTENSION);
1573 printf("extensions '%s'\n", extensions);
1574 if (!fullscreen)
1576 grGlideShutdown ();
1578 if (strstr (extensions, "EVOODOO"))
1579 evoodoo = 1;
1580 else
1581 evoodoo = 0;
1583 if (evoodoo)
1584 InitGfx (TRUE);
1587 if (strstr (extensions, "ROMNAME"))
1589 void (__stdcall *grSetRomName)(char*);
1590 grSetRomName = (void (__stdcall *)(char*))grGetProcAddress ("grSetRomName");
1591 grSetRomName (name);
1593 // **
1596 /******************************************************************
1597 Function: ShowCFB
1598 Purpose: Useally once Dlists are started being displayed, cfb is
1599 ignored. This function tells the dll to start displaying
1600 them again.
1601 input: none
1602 output: none
1603 *******************************************************************/
1604 EXPORT void CALL ShowCFB (void)
1606 no_dlist = TRUE;
1607 LOG ("ShowCFB ()\n");
1611 void drawViRegBG();
1612 void drawNoFullscreenMessage();
1614 void DrawFrameBuffer ()
1616 if (!fullscreen)
1618 drawNoFullscreenMessage();
1620 if (to_fullscreen)
1622 to_fullscreen = FALSE;
1624 if (!InitGfx (FALSE))
1626 LOG ("FAILED!!!\n");
1627 return;
1629 fullscreen = TRUE;
1632 if (fullscreen)
1634 grDepthMask (FXTRUE);
1635 grColorMask (FXTRUE, FXTRUE);
1636 grBufferClear (0, 0, 0xFFFF);
1637 drawViRegBG();
1641 /******************************************************************
1642 Function: UpdateScreen
1643 Purpose: This function is called in response to a vsync of the
1644 screen were the VI bit in MI_INTR_REG has already been
1646 input: none
1647 output: none
1648 *******************************************************************/
1649 DWORD update_screen_count = 0;
1650 EXPORT void CALL UpdateScreen (void)
1652 #ifdef LOG_KEY
1653 if (GetAsyncKeyState (VK_SPACE) & 0x0001)
1655 LOG ("KEY!!!\n");
1657 #endif
1658 char out_buf[512];
1659 sprintf (out_buf, "UpdateScreen (). distance: %d\n", (int)(*gfx.VI_ORIGIN_REG) - (int)((*gfx.VI_WIDTH_REG) << 2));
1660 LOG (out_buf);
1661 // LOG ("UpdateScreen ()\n");
1663 DWORD width = (*gfx.VI_WIDTH_REG) << 1;
1664 if (fullscreen && (*gfx.VI_ORIGIN_REG > width))
1665 update_screen_count++;
1667 // vertical interrupt has occured, increment counter
1668 vi_count ++;
1670 #ifdef FPS
1671 // Check frames per second
1672 LARGE_INTEGER difference;
1673 QueryPerformanceCounter (&fps_next);
1674 difference.QuadPart = fps_next.QuadPart - fps_last.QuadPart;
1675 float diff_secs = (float)((double)difference.QuadPart / (double)perf_freq.QuadPart);
1676 if (diff_secs > 0.5f)
1678 fps = (float)fps_count / diff_secs;
1679 vi = (float)vi_count / diff_secs;
1680 ntsc_percent = vi / 0.6f;
1681 pal_percent = vi / 0.5f;
1682 fps_last = fps_next;
1683 fps_count = 0;
1684 vi_count = 0;
1686 #endif
1687 //*
1688 DWORD limit = settings.lego ? 15 : 50;
1689 if (settings.cpu_write_hack && (update_screen_count > limit) && (rdp.last_bg == 0))
1691 RDP("DirectCPUWrite hack!\n");
1692 update_screen_count = 0;
1693 no_dlist = TRUE;
1694 ClearCache ();
1695 UpdateScreen();
1696 return;
1698 //*/
1700 if( no_dlist )
1702 if( *gfx.VI_ORIGIN_REG > width )
1704 ChangeSize ();
1705 RDP("ChangeSize done\n");
1706 DrawFrameBuffer();
1707 RDP("DrawFrameBuffer done\n");
1708 rdp.updatescreen = 1;
1709 newSwapBuffers ();
1711 return;
1713 //*/
1714 if (settings.swapmode == 0)
1715 newSwapBuffers ();
1718 DWORD curframe = 0;
1719 void newSwapBuffers()
1721 if (rdp.updatescreen)
1723 rdp.updatescreen = 0;
1725 RDP ("swapped\n");
1727 // Allow access to the whole screen
1728 if (fullscreen)
1730 grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y);
1731 grDepthBufferFunction (GR_CMP_ALWAYS);
1732 grDepthMask (FXFALSE);
1734 grCullMode (GR_CULL_DISABLE);
1736 if ((settings.show_fps & 0xF) || settings.clock)
1737 set_message_combiner ();
1738 #ifdef FPS
1739 float y = (float)settings.res_y;
1740 if (settings.show_fps & 0x0F)
1742 if (settings.show_fps & 4)
1744 if (region) // PAL
1745 output (0, y, 0, "%d%% ", (int)pal_percent);
1746 else
1747 output (0, y, 0, "%d%% ", (int)ntsc_percent);
1748 y -= 16;
1750 if (settings.show_fps & 2)
1752 output (0, y, 0, "VI/s: %.02f ", vi);
1753 y -= 16;
1755 if (settings.show_fps & 1)
1756 output (0, y, 0, "FPS: %.02f ", fps);
1758 #endif
1760 if (settings.clock)
1762 if (settings.clock_24_hr)
1764 time_t ltime;
1765 time (&ltime);
1766 tm *cur_time = localtime (&ltime);
1768 sprintf (out_buf, "%.2d:%.2d:%.2d", cur_time->tm_hour, cur_time->tm_min, cur_time->tm_sec);
1770 else
1772 char ampm[] = "AM";
1773 time_t ltime;
1775 time (&ltime);
1776 tm *cur_time = localtime (&ltime);
1778 if (cur_time->tm_hour >= 12)
1780 strcpy (ampm, "PM");
1781 if (cur_time->tm_hour != 12)
1782 cur_time->tm_hour -= 12;
1784 if (cur_time->tm_hour == 0)
1785 cur_time->tm_hour = 12;
1787 if (cur_time->tm_hour >= 10)
1788 sprintf (out_buf, "%.5s %s", asctime(cur_time) + 11, ampm);
1789 else
1790 sprintf (out_buf, " %.4s %s", asctime(cur_time) + 12, ampm);
1792 output ((float)(settings.res_x - 68), y, 0, out_buf, 0);
1794 #ifdef _WIN32
1795 if (settings.hotkeys)
1797 if (GetAsyncKeyState (VK_BACK) & 0x0001)
1799 hotkey_info.filtering = 100;
1800 if (settings.filtering < 2)
1801 settings.filtering++;
1802 else
1803 settings.filtering = 0;
1805 if ((abs(frame_count - curframe) > 3 ) && (GetAsyncKeyState(VK_MENU) & 0x8000)) //alt +
1807 if (GetAsyncKeyState(0x42) & 0x8000) //b
1809 hotkey_info.fb_motionblur = 100;
1810 hotkey_info.fb_always = 0;
1811 curframe = frame_count;
1812 settings.fb_motionblur = !settings.fb_motionblur;
1814 else if (GetAsyncKeyState(0x56) & 0x8000) //v
1816 hotkey_info.fb_always = 100;
1817 hotkey_info.fb_motionblur = 0;
1818 curframe = frame_count;
1819 settings.fb_read_always = !settings.fb_read_always;
1821 if (GetAsyncKeyState(0x43) & 0x8000) //c
1823 hotkey_info.corona = 100;
1824 curframe = frame_count;
1825 settings.flame_corona = !settings.flame_corona;
1828 if (hotkey_info.fb_always || hotkey_info.fb_motionblur || hotkey_info.filtering || hotkey_info.corona)
1830 set_message_combiner ();
1831 int y = settings.res_y;
1832 char buf[64];
1833 char * message = 0;
1834 if (hotkey_info.fb_always)
1836 if (settings.fb_read_always)
1837 message = strcpy(buf, "FB READ ALWAYS: ON");
1838 else
1839 message = strcpy(buf, "FB READ ALWAYS: OFF");
1840 output ((float)(settings.res_x / 5), (float)y, 0, message, 0);
1841 hotkey_info.fb_always--;
1843 if (hotkey_info.fb_motionblur)
1845 if (settings.fb_motionblur)
1846 message = strcpy(buf, "MOTION BLUR: ON");
1847 else
1848 message = strcpy(buf, "MOTION BLUR: OFF");
1849 output ((float)(settings.res_x / 5), (float)y, 0, message, 0);
1850 hotkey_info.fb_motionblur--;
1852 if (hotkey_info.corona)
1854 if (settings.flame_corona)
1855 message = strcpy(buf, "CORONA FIX: ON");
1856 else
1857 message = strcpy(buf, "CORONA FIX: OFF");
1858 output ((float)(settings.res_x / 5 * 2), (float)y, 0, message, 0);
1859 hotkey_info.corona--;
1861 if (hotkey_info.filtering)
1863 switch (settings.filtering)
1865 case 0:
1866 message = strcpy(buf, "FILTERING MODE: AUTOMATIC");
1867 break;
1868 case 1:
1869 message = strcpy(buf, "FILTERING MODE: FORCE BILINEAR");
1870 break;
1871 case 2:
1872 message = strcpy(buf, "FILTERING MODE: FORCE POINT-SAMPLED");
1873 break;
1875 output ((float)(settings.res_x / 5 * 3), (float)y, 0, message, 0);
1876 hotkey_info.filtering--;
1880 #endif // _WIN32
1882 #ifdef _WIN32
1883 if (capture_screen)
1885 char path[256];
1886 FILE *file = NULL;
1888 // Make the directory if it doesn't exist
1889 _mkdir (capture_path);
1891 for (int i=0; ; i++)
1893 if (i < 10)
1894 sprintf (path, "%sss0%d.bmp", capture_path, i);
1895 else
1896 sprintf (path, "%sss%d.bmp", capture_path, i);
1897 if ((file = fopen(path,"rb")) == NULL)
1898 break;
1899 fclose (file);
1902 file = fopen (path, "wb");
1903 if (file == NULL) return;
1905 BITMAPFILEHEADER bmf;
1906 bmf.bfType = ((WORD)'M' << 8) | 'B';
1907 bmf.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
1908 settings.res_x * settings.res_y * 3;
1909 bmf.bfReserved1 = 0;
1910 bmf.bfReserved2 = 0;
1911 bmf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
1912 fwrite (&bmf, sizeof(BITMAPFILEHEADER), 1, file);
1914 BITMAPINFOHEADER bmi;
1915 bmi.biSize = sizeof(BITMAPINFOHEADER);
1916 bmi.biWidth = settings.res_x;
1917 bmi.biHeight = settings.res_y;
1918 bmi.biPlanes = 1;
1919 bmi.biBitCount = 24;
1920 bmi.biCompression = BI_RGB;
1921 bmi.biSizeImage = settings.res_x * settings.res_y * 3;
1922 bmi.biXPelsPerMeter = 0;
1923 bmi.biYPelsPerMeter = 0;
1924 bmi.biClrUsed = 0;
1925 bmi.biClrImportant = 0;
1926 fwrite (&bmi, sizeof(BITMAPINFOHEADER), 1, file);
1928 // Lock the backbuffer (already rendered)
1929 BYTE *line = new BYTE [settings.res_x * 3];
1931 GrLfbInfo_t info;
1932 info.size = sizeof(GrLfbInfo_t);
1933 #if 1
1934 if (grLfbLock (GR_LFB_READ_ONLY,
1935 GR_BUFFER_BACKBUFFER,
1936 GR_LFBWRITEMODE_888,
1937 GR_ORIGIN_UPPER_LEFT,
1938 FXFALSE,
1939 &info))
1941 DWORD offset_src=info.strideInBytes*(settings.scr_res_y-1);
1943 // Copy the screen
1944 DWORD col;
1945 BYTE r, g, b;
1946 for (DWORD y=0; y<settings.res_y; y++)
1948 DWORD *ptr = (DWORD*)((BYTE*)info.lfbPtr + offset_src);
1949 for (DWORD x=0; x<settings.res_x; x++)
1951 col = *(ptr++);
1952 r = (col >> 16);
1953 g = (col >> 8) & 0xFF;
1954 b = col & 0xFF;
1955 line[x*3] = b;
1956 line[x*3+1] = g;
1957 line[x*3+2] = r;
1959 fwrite (line, 1, settings.res_x*3, file);
1960 offset_src -= info.strideInBytes;
1963 // Unlock the backbuffer
1964 grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER);
1966 #else
1967 if (grLfbLock (GR_LFB_READ_ONLY,
1968 GR_BUFFER_BACKBUFFER,
1969 GR_LFBWRITEMODE_565,
1970 GR_ORIGIN_UPPER_LEFT,
1971 FXFALSE,
1972 &info))
1974 DWORD offset_src=info.strideInBytes*(settings.scr_res_y-1);
1976 // Copy the screen
1977 WORD col;
1978 BYTE r, g, b;
1979 for (DWORD y=0; y<settings.res_y; y++)
1981 WORD *ptr = (WORD*)((BYTE*)info.lfbPtr + offset_src);
1982 for (DWORD x=0; x<settings.res_x; x++)
1984 col = *(ptr++);
1985 r = (BYTE)((float)(col >> 11) / 31.0f * 255.0f);
1986 g = (BYTE)((float)((col >> 5) & 0x3F) / 63.0f * 255.0f);
1987 b = (BYTE)((float)(col & 0x1F) / 31.0f * 255.0f);
1988 line[x*3] = b;
1989 line[x*3+1] = g;
1990 line[x*3+2] = r;
1992 fwrite (line, 1, settings.res_x*3, file);
1993 offset_src -= info.strideInBytes;
1996 // Unlock the backbuffer
1997 grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER);
1999 #endif
2001 delete [] line;
2002 fclose (file);
2004 capture_screen = 0;
2006 #endif // _WIN32
2007 // Capture the screen if debug capture is set
2008 if (debug.capture)
2010 // Allocate the screen
2011 debug.screen = new BYTE [(settings.res_x*settings.res_y) << 1];
2013 // Lock the backbuffer (already rendered)
2014 GrLfbInfo_t info;
2015 info.size = sizeof(GrLfbInfo_t);
2016 while (!grLfbLock (GR_LFB_READ_ONLY,
2017 GR_BUFFER_BACKBUFFER,
2018 GR_LFBWRITEMODE_565,
2019 GR_ORIGIN_UPPER_LEFT,
2020 FXFALSE,
2021 &info));
2023 DWORD offset_src=0/*(settings.scr_res_y-settings.res_y)*info.strideInBytes*/, offset_dst=0;
2025 // Copy the screen
2026 for (DWORD y=0; y<settings.res_y; y++)
2028 memcpy (debug.screen + offset_dst, (BYTE*)info.lfbPtr + offset_src, settings.res_x << 1);
2029 offset_dst += settings.res_x << 1;
2030 offset_src += info.strideInBytes;
2033 // Unlock the backbuffer
2034 grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER);
2037 #ifdef _WIN32
2038 if (fullscreen && debugging)
2040 debug_keys ();
2041 debug_cacheviewer ();
2042 debug_mouse ();
2044 #endif // _WIN32
2046 if (fullscreen)
2048 LOG ("BUFFER SWAPPED\n");
2049 grBufferSwap (settings.vsync);
2050 fps_count ++;
2053 #ifdef _WIN32
2054 if (debug.capture)
2055 debug_capture ();
2056 #endif // _WIN32
2058 if (fullscreen && (debugging || settings.wireframe || settings.buff_clear))
2060 if (settings.RE2 && settings.fb_depth_render)
2061 grDepthMask (FXFALSE);
2062 else
2063 grDepthMask (FXTRUE);
2064 grBufferClear (0, 0, 0xFFFF);
2067 frame_count ++;
2068 #ifdef _WIN32
2069 // Open/close debugger?
2070 if (GetAsyncKeyState(VK_SCROLL) & 0x0001)
2072 if (!debugging)
2074 //if (settings.scr_res_x == 1024 && settings.scr_res_y == 768)
2076 debugging = 1;
2078 // Recalculate screen size, don't resize screen
2079 settings.res_x = (DWORD)(settings.scr_res_x * 0.625f);
2080 settings.res_y = (DWORD)(settings.scr_res_y * 0.625f);
2082 ChangeSize ();
2084 } else {
2085 debugging = 0;
2087 settings.res_x = settings.scr_res_x;
2088 settings.res_y = settings.scr_res_y;
2090 ChangeSize ();
2094 // Debug capture?
2095 if (/*fullscreen && */debugging && (GetAsyncKeyState(VK_INSERT) & 0x0001))
2097 debug.capture = 1;
2099 #endif // _WIN32
2103 /******************************************************************
2104 Function: ViStatusChanged
2105 Purpose: This function is called to notify the dll that the
2106 ViStatus registers value has been changed.
2107 input: none
2108 output: none
2109 *******************************************************************/
2110 EXPORT void CALL ViStatusChanged (void)
2114 /******************************************************************
2115 Function: ViWidthChanged
2116 Purpose: This function is called to notify the dll that the
2117 ViWidth registers value has been changed.
2118 input: none
2119 output: none
2120 *******************************************************************/
2121 EXPORT void CALL ViWidthChanged (void)
2125 #ifdef WINPROC_OVERRIDE
2126 LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2128 switch (msg)
2130 case WM_ACTIVATE:
2131 rdp.window_changed = TRUE;
2132 break;
2134 /* case WM_DESTROY:
2135 SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
2136 break;*/
2139 return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam);
2141 #endif
2143 BOOL k_ctl=0, k_alt=0, k_del=0;
2145 #ifdef ALTTAB_FIX
2146 LRESULT CALLBACK LowLevelKeyboardProc(int nCode,
2147 WPARAM wParam, LPARAM lParam) {
2148 if (!fullscreen) return CallNextHookEx(NULL, nCode, wParam, lParam);
2150 BOOL TabKey = FALSE;
2152 PKBDLLHOOKSTRUCT p;
2154 if (nCode == HC_ACTION)
2156 switch (wParam) {
2157 case WM_KEYUP: case WM_SYSKEYUP:
2158 p = (PKBDLLHOOKSTRUCT) lParam;
2159 if (p->vkCode == 162) k_ctl = 0;
2160 if (p->vkCode == 164) k_alt = 0;
2161 if (p->vkCode == 46) k_del = 0;
2162 goto do_it;
2164 case WM_KEYDOWN: case WM_SYSKEYDOWN:
2165 p = (PKBDLLHOOKSTRUCT) lParam;
2166 if (p->vkCode == 162) k_ctl = 1;
2167 if (p->vkCode == 164) k_alt = 1;
2168 if (p->vkCode == 46) k_del = 1;
2169 goto do_it;
2171 do_it:
2172 TabKey =
2173 ((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
2174 ((p->vkCode == VK_ESCAPE) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
2175 ((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) & 0x8000) != 0)) ||
2176 (k_ctl && k_alt && k_del);
2178 break;
2182 if (TabKey)
2184 k_ctl = 0;
2185 k_alt = 0;
2186 k_del = 0;
2187 ReleaseGfx ();
2190 return CallNextHookEx(NULL, nCode, wParam, lParam);
2192 #endif