GLIDE: Update from upstream
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glide64 / Main.cpp
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 "Gfx_1.3.h"
41 #include "Ini.h"
42 #include "Config.h"
43 #include "Util.h"
44 #include "3dmath.h"
45 #include "Debugger.h"
46 #include "Combine.h"
47 #include "TexCache.h"
48 #include "CRC.h"
49 #include "FBtoScreen.h"
50 #include "DepthBufferRender.h"
51
52 #if defined(__GNUC__)
53 #include <sys/time.h>
54 #elif defined(__MSC__)
55 #include <time.h>
56 #define PATH_MAX MAX_PATH
57 #endif
58 #ifndef PATH_MAX
59   #define PATH_MAX 4096
60 #endif
61 #include "osal_dynamiclib.h"
62 #ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
63 #include <stdarg.h>
64 int  ghq_dmptex_toggle_key = 0;
65 #endif
66 #if defined(__MINGW32__)
67 #define swprintf _snwprintf
68 #define vswprintf _vsnwprintf
69 #endif
70
71 #define G64_VERSION "G64 Mk2"
72 #define RELTIME "Date: " __DATE__// " Time: " __TIME__
73
74 #ifdef EXT_LOGGING
75 std::ofstream extlog;
76 #endif
77
78 #ifdef LOGGING
79 std::ofstream loga;
80 #endif
81
82 #ifdef RDP_LOGGING
83 int log_open = FALSE;
84 std::ofstream rdp_log;
85 #endif
86
87 #ifdef RDP_ERROR_LOG
88 int elog_open = FALSE;
89 std::ofstream rdp_err;
90 #endif
91
92 GFX_INFO gfx;
93
94 /* definitions of pointers to Core config functions */
95 ptr_ConfigOpenSection      ConfigOpenSection = NULL;
96 ptr_ConfigSetParameter     ConfigSetParameter = NULL;
97 ptr_ConfigGetParameter     ConfigGetParameter = NULL;
98 ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL;
99 ptr_ConfigSetDefaultInt    ConfigSetDefaultInt = NULL;
100 ptr_ConfigSetDefaultFloat  ConfigSetDefaultFloat = NULL;
101 ptr_ConfigSetDefaultBool   ConfigSetDefaultBool = NULL;
102 ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL;
103 ptr_ConfigGetParamInt      ConfigGetParamInt = NULL;
104 ptr_ConfigGetParamFloat    ConfigGetParamFloat = NULL;
105 ptr_ConfigGetParamBool     ConfigGetParamBool = NULL;
106 ptr_ConfigGetParamString   ConfigGetParamString = NULL;
107
108 ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL;
109 ptr_ConfigGetUserConfigPath     ConfigGetUserConfigPath = NULL;
110 ptr_ConfigGetUserDataPath       ConfigGetUserDataPath = NULL;
111 ptr_ConfigGetUserCachePath      ConfigGetUserCachePath = NULL;
112
113 /* definitions of pointers to Core video extension functions */
114 ptr_VidExt_Init                  CoreVideo_Init = NULL;
115 ptr_VidExt_Quit                  CoreVideo_Quit = NULL;
116 ptr_VidExt_ListFullscreenModes   CoreVideo_ListFullscreenModes = NULL;
117 ptr_VidExt_SetVideoMode          CoreVideo_SetVideoMode = NULL;
118 ptr_VidExt_SetCaption            CoreVideo_SetCaption = NULL;
119 ptr_VidExt_ToggleFullScreen      CoreVideo_ToggleFullScreen = NULL;
120 ptr_VidExt_ResizeWindow          CoreVideo_ResizeWindow = NULL;
121 ptr_VidExt_GL_GetProcAddress     CoreVideo_GL_GetProcAddress = NULL;
122 ptr_VidExt_GL_SetAttribute       CoreVideo_GL_SetAttribute = NULL;
123 ptr_VidExt_GL_SwapBuffers        CoreVideo_GL_SwapBuffers = NULL;
124 int to_fullscreen = FALSE;
125 int fullscreen = FALSE;
126 int romopen = FALSE;
127 GrContext_t gfx_context = 0;
128 int debugging = FALSE;
129 int exception = FALSE;
130
131 int evoodoo = 0;
132 int ev_fullscreen = 0;
133
134 #ifdef __WINDOWS__
135 #define WINPROC_OVERRIDE
136 #endif
137
138 #ifdef WINPROC_OVERRIDE
139 LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
140 WNDPROC oldWndProc = NULL;
141 WNDPROC myWndProc = NULL;
142 #endif
143
144 #ifdef ALTTAB_FIX
145 HHOOK hhkLowLevelKybd = NULL;
146 LRESULT CALLBACK LowLevelKeyboardProc(int nCode,
147                                       WPARAM wParam, LPARAM lParam);
148 #endif
149
150 #ifdef PERFORMANCE
151 int64 perf_cur;
152 int64 perf_next;
153 #endif
154
155 #ifdef FPS
156 LARGE_INTEGER perf_freq;
157 LARGE_INTEGER fps_last;
158 LARGE_INTEGER fps_next;
159 float      fps = 0.0f;
160 wxUint32   fps_count = 0;
161
162 wxUint32   vi_count = 0;
163 float      vi = 0.0f;
164
165 wxUint32   region = 0;
166
167 float      ntsc_percent = 0.0f;
168 float      pal_percent = 0.0f;
169
170 #endif
171
172 // ref rate
173 // 60=0x0, 70=0x1, 72=0x2, 75=0x3, 80=0x4, 90=0x5, 100=0x6, 85=0x7, 120=0x8, none=0xff
174
175 #ifdef PAULSCODE
176 //#include "ae_bridge.h"
177 #include "FrameSkipper.h"
178 FrameSkipper frameSkipper;
179 void vbo_resetcount();
180 #endif
181
182 unsigned long BMASK = 0x7FFFFF;
183 // Reality display processor structure
184 RDP rdp;
185
186 SETTINGS settings = { FALSE, 640, 480, GR_RESOLUTION_640x480, 0 };
187
188 HOTKEY_INFO hotkey_info;
189
190 VOODOO voodoo = {0, 0, 0, 0,
191                  0, 0, 0, 0,
192                  0, 0, 0, 0
193                 };
194
195 GrTexInfo fontTex;
196 GrTexInfo cursorTex;
197 wxUint32   offset_font = 0;
198 wxUint32   offset_cursor = 0;
199 wxUint32   offset_textures = 0;
200 wxUint32   offset_texbuf1 = 0;
201
202 int    capture_screen = 0;
203 char    capture_path[256];
204
205 //SDL_sem *mutexProcessDList = SDL_CreateSemaphore(1);
206
207 // SOME FUNCTION DEFINITIONS 
208
209 static void DrawFrameBuffer ();
210
211
212 void (*renderCallback)(int) = NULL;
213 static void (*l_DebugCallback)(void *, int, const char *) = NULL;
214 static void *l_DebugCallContext = NULL;
215
216 void _ChangeSize ()
217 {
218   rdp.scale_1024 = settings.scr_res_x / 1024.0f;
219   rdp.scale_768 = settings.scr_res_y / 768.0f;
220
221 //  float res_scl_x = (float)settings.res_x / 320.0f;
222   float res_scl_y = (float)settings.res_y / 240.0f;
223
224   wxUint32 scale_x = *gfx.VI_X_SCALE_REG & 0xFFF;
225   if (!scale_x) return;
226   wxUint32 scale_y = *gfx.VI_Y_SCALE_REG & 0xFFF;
227   if (!scale_y) return;
228
229   float fscale_x = (float)scale_x / 1024.0f;
230   float fscale_y = (float)scale_y / 2048.0f;
231
232   wxUint32 dwHStartReg = *gfx.VI_H_START_REG;
233   wxUint32 dwVStartReg = *gfx.VI_V_START_REG;
234
235   wxUint32 hstart = dwHStartReg >> 16;
236   wxUint32 hend = dwHStartReg & 0xFFFF;
237
238   // dunno... but sometimes this happens
239   if (hend == hstart) hend = (int)(*gfx.VI_WIDTH_REG / fscale_x);
240
241   wxUint32 vstart = dwVStartReg >> 16;
242   wxUint32 vend = dwVStartReg & 0xFFFF;
243
244   rdp.vi_width = (hend - hstart) * fscale_x;
245   rdp.vi_height = (vend - vstart) * fscale_y * 1.0126582f;
246   float aspect = (settings.adjust_aspect && (fscale_y > fscale_x) && (rdp.vi_width > rdp.vi_height)) ? fscale_x/fscale_y : 1.0f;
247
248 #ifdef LOGGING
249   sprintf (out_buf, "hstart: %d, hend: %d, vstart: %d, vend: %d\n", hstart, hend, vstart, vend);
250   LOG (out_buf);
251   sprintf (out_buf, "size: %d x %d\n", (int)rdp.vi_width, (int)rdp.vi_height);
252   LOG (out_buf);
253 #endif
254
255   rdp.scale_x = (float)settings.res_x / rdp.vi_width;
256   if (region > 0 && settings.pal230)
257   {
258     // odd... but pal games seem to want 230 as height...
259     rdp.scale_y = res_scl_y * (230.0f / rdp.vi_height)  * aspect;
260   }
261   else
262   {
263     rdp.scale_y = (float)settings.res_y / rdp.vi_height * aspect;
264   }
265   //  rdp.offset_x = settings.offset_x * res_scl_x;
266   //  rdp.offset_y = settings.offset_y * res_scl_y;
267   //rdp.offset_x = 0;
268   //  rdp.offset_y = 0;
269   rdp.offset_y = ((float)settings.res_y - rdp.vi_height * rdp.scale_y) * 0.5f;
270   if (((wxUint32)rdp.vi_width <= (*gfx.VI_WIDTH_REG)/2) && (rdp.vi_width > rdp.vi_height))
271     rdp.scale_y *= 0.5f;
272
273   rdp.scissor_o.ul_x = 0;
274   rdp.scissor_o.ul_y = 0;
275   rdp.scissor_o.lr_x = (wxUint32)rdp.vi_width;
276   rdp.scissor_o.lr_y = (wxUint32)rdp.vi_height;
277
278   rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
279 }
280
281 void ChangeSize ()
282 {
283   if (debugging)
284   {
285     _ChangeSize ();
286     return;
287   }
288   switch (settings.aspectmode)
289   {
290   case 0: //4:3
291     if (settings.scr_res_x >= settings.scr_res_y * 4.0f / 3.0f) {
292       settings.res_y = settings.scr_res_y;
293       settings.res_x = (wxUint32)(settings.res_y * 4.0f / 3.0f);
294     } else {
295       settings.res_x = settings.scr_res_x;
296       settings.res_y = (wxUint32)(settings.res_x / 4.0f * 3.0f);
297     }
298     break;
299   case 1: //16:9
300     if (settings.scr_res_x >= settings.scr_res_y * 16.0f / 9.0f) {
301       settings.res_y = settings.scr_res_y;
302       settings.res_x = (wxUint32)(settings.res_y * 16.0f / 9.0f);
303     } else {
304       settings.res_x = settings.scr_res_x;
305       settings.res_y = (wxUint32)(settings.res_x / 16.0f * 9.0f);
306     }
307     break;
308   default: //stretch or original
309     settings.res_x = settings.scr_res_x;
310     settings.res_y = settings.scr_res_y;
311   }
312   _ChangeSize ();
313   rdp.offset_x = (settings.scr_res_x - settings.res_x) / 2.0f;
314   float offset_y = (settings.scr_res_y - settings.res_y) / 2.0f;
315   settings.res_x += (wxUint32)rdp.offset_x;
316   settings.res_y += (wxUint32)offset_y;
317   rdp.offset_y += offset_y;
318   if (settings.aspectmode == 3) // original
319   {
320           rdp.scale_x = rdp.scale_y = 1.0f;
321           rdp.offset_x = (settings.scr_res_x - rdp.vi_width) / 2.0f;
322           rdp.offset_y = (settings.scr_res_y - rdp.vi_height) / 2.0f;
323   }
324   //    settings.res_x = settings.scr_res_x;
325   //    settings.res_y = settings.scr_res_y;
326 }
327
328 void ConfigWrapper()
329 {
330   char strConfigWrapperExt[] = "grConfigWrapperExt";
331   GRCONFIGWRAPPEREXT grConfigWrapperExt = (GRCONFIGWRAPPEREXT)grGetProcAddress(strConfigWrapperExt);
332   if (grConfigWrapperExt)
333     grConfigWrapperExt(settings.wrpResolution, settings.wrpVRAM * 1024 * 1024, settings.wrpFBO, settings.wrpAnisotropic);
334 }
335 /*
336 static wxConfigBase * OpenIni()
337 {
338   wxConfigBase * ini = wxConfigBase::Get(false);
339   if (!ini)
340   {
341     if (iniName.IsEmpty())
342       iniName = pluginPath + wxT("/Glide64mk2.ini");
343     if (wxFileExists(iniName))
344     {
345       wxFileInputStream is(iniName);
346       wxFileConfig * fcfg = new wxFileConfig(is, wxConvISO8859_1);
347       wxConfigBase::Set(fcfg);
348       ini = fcfg;
349     }
350   }
351   if (!ini)
352     wxMessageBox(_T("Can not find ini file! Plugin will not run properly."), _T("File not found"), wxOK|wxICON_EXCLAMATION);
353   return ini;
354 }
355 */
356 #ifndef OLDAPI
357 void WriteLog(m64p_msg_level level, const char *msg, ...)
358 {
359   char buf[1024];
360   va_list args;
361   va_start(args, msg);
362   vsnprintf(buf, 1023, msg, args);
363   buf[1023]='\0';
364   va_end(args);
365   if (l_DebugCallback)
366   {
367     l_DebugCallback(l_DebugCallContext, level, buf);
368   }
369 }
370 #endif
371
372 void ReadSettings ()
373 {
374   //  LOG("ReadSettings\n");
375   if (!Config_Open())
376   {
377     ERRLOG("Could not open configuration!");
378     return;
379   }
380
381   settings.card_id = (BYTE)Config_ReadInt ("card_id", "Card ID", 0, TRUE, FALSE);
382   //settings.lang_id not needed
383   // depth_bias = -Config_ReadInt ("depth_bias", "Depth bias level", 0, TRUE, FALSE);
384   settings.res_data = 0;
385   settings.scr_res_x = settings.res_x = Config_ReadScreenInt("ScreenWidth");
386   settings.scr_res_y = settings.res_y = Config_ReadScreenInt("ScreenHeight");
387
388   settings.vsync = (BOOL)Config_ReadInt ("vsync", "Vertical sync", 0);
389   settings.ssformat = (BOOL)Config_ReadInt("ssformat", "TODO:ssformat", 0);
390   //settings.fast_crc = (BOOL)Config_ReadInt ("fast_crc", "Fast CRC", 0);
391
392   settings.show_fps = (BYTE)Config_ReadInt ("show_fps", "Display performance stats (add together desired flags): 1=FPS counter, 2=VI/s counter, 4=% speed, 8=FPS transparent", 0, TRUE, FALSE);
393   settings.clock = (BOOL)Config_ReadInt ("clock", "Clock enabled", 0);
394   settings.clock_24_hr = (BOOL)Config_ReadInt ("clock_24_hr", "Clock is 24-hour", 0);
395   // settings.advanced_options only good for GUI config
396   // settings.texenh_options = only good for GUI config
397   //settings.use_hotkeys = ini->Read(_T("hotkeys"), 1l);
398
399   settings.wrpResolution = (BYTE)Config_ReadInt ("wrpResolution", "Wrapper resolution", 0, TRUE, FALSE);
400   settings.wrpVRAM = (BYTE)Config_ReadInt ("wrpVRAM", "Wrapper VRAM", 0, TRUE, FALSE);
401   settings.wrpFBO = (BOOL)Config_ReadInt ("wrpFBO", "Wrapper FBO", 1, TRUE, TRUE);
402   settings.wrpAnisotropic = (BOOL)Config_ReadInt ("wrpAnisotropic", "Wrapper Anisotropic Filtering", 0, TRUE, TRUE);
403
404 #ifndef _ENDUSER_RELEASE_
405   settings.autodetect_ucode = (BOOL)Config_ReadInt ("autodetect_ucode", "Auto-detect microcode", 1);
406   settings.ucode = (wxUint32)Config_ReadInt ("ucode", "Force microcode", 2, TRUE, FALSE);
407   settings.wireframe = (BOOL)Config_ReadInt ("wireframe", "Wireframe display", 0);
408   settings.wfmode = (int)Config_ReadInt ("wfmode", "Wireframe mode: 0=Normal colors, 1=Vertex colors, 2=Red only", 1, TRUE, FALSE);
409
410   settings.logging = (BOOL)Config_ReadInt ("logging", "Logging", 0);
411   settings.log_clear = (BOOL)Config_ReadInt ("log_clear", "", 0);
412
413   settings.run_in_window = (BOOL)Config_ReadInt ("run_in_window", "", 0);
414
415   settings.elogging = (BOOL)Config_ReadInt ("elogging", "", 0);
416   settings.filter_cache = (BOOL)Config_ReadInt ("filter_cache", "Filter cache", 0);
417   settings.unk_as_red = (BOOL)Config_ReadInt ("unk_as_red", "Display unknown combines as red", 0);
418   settings.log_unk = (BOOL)Config_ReadInt ("log_unk", "Log unknown combines", 0);
419   settings.unk_clear = (BOOL)Config_ReadInt ("unk_clear", "", 0);
420 #else
421   settings.autodetect_ucode = TRUE;
422   settings.ucode = 2;
423   settings.wireframe = FALSE;
424   settings.wfmode = 0;
425   settings.logging = FALSE;
426   settings.log_clear = FALSE;
427   settings.run_in_window = FALSE;
428   settings.elogging = FALSE;
429   settings.filter_cache = FALSE;
430   settings.unk_as_red = FALSE;
431   settings.log_unk = FALSE;
432   settings.unk_clear = FALSE;
433 #endif
434
435 #ifdef TEXTURE_FILTER
436   
437   // settings.ghq_fltr range is 0 through 6
438   // Filters:\nApply a filter to either smooth or sharpen textures.\nThere are 4 different smoothing filters and 2 different sharpening filters.\nThe higher the number, the stronger the effect,\ni.e. \"Smoothing filter 4\" will have a much more noticeable effect than \"Smoothing filter 1\".\nBe aware that performance may have an impact depending on the game and/or the PC.\n[Recommended: your preference]
439   // _("None"),
440   // _("Smooth filtering 1"),
441   // _("Smooth filtering 2"),
442   // _("Smooth filtering 3"),
443   // _("Smooth filtering 4"),
444   // _("Sharp filtering 1"),
445   // _("Sharp filtering 2")
446
447 // settings.ghq_cmpr 0=S3TC and 1=FXT1
448
449 //settings.ghq_ent is ___
450 // "Texture enhancement:\n7 different filters are selectable here, each one with a distinctive look.\nBe aware of possible performance impacts.\n\nIMPORTANT: 'Store' mode - saves textures in cache 'as is'. It can improve performance in games, which load many textures.\nDisable 'Ignore backgrounds' option for better result.\n\n[Recommended: your preference]"
451
452
453
454   settings.ghq_fltr = Config_ReadInt ("ghq_fltr", "Texture Enhancement: Smooth/Sharpen Filters", 0, TRUE, FALSE);
455   settings.ghq_cmpr = Config_ReadInt ("ghq_cmpr", "Texture Compression: 0 for S3TC, 1 for FXT1", 0, TRUE, FALSE);
456   settings.ghq_enht = Config_ReadInt ("ghq_enht", "Texture Enhancement: More filters", 0, TRUE, FALSE);
457   settings.ghq_hirs = Config_ReadInt ("ghq_hirs", "Hi-res texture pack format (0 for none, 1 for Rice)", 0, TRUE, FALSE);
458   settings.ghq_enht_cmpr  = Config_ReadInt ("ghq_enht_cmpr", "Compress texture cache with S3TC or FXT1", 0, TRUE, TRUE);
459   settings.ghq_enht_tile = Config_ReadInt ("ghq_enht_tile", "Tile textures (saves memory but could cause issues)", 0, TRUE, FALSE);
460   settings.ghq_enht_f16bpp = Config_ReadInt ("ghq_enht_f16bpp", "Force 16bpp textures (saves ram but lower quality)", 0, TRUE, TRUE);
461   settings.ghq_enht_gz  = Config_ReadInt ("ghq_enht_gz", "Compress texture cache", 1, TRUE, TRUE);
462   settings.ghq_enht_nobg  = Config_ReadInt ("ghq_enht_nobg", "Don't enhance textures for backgrounds", 0, TRUE, TRUE);
463   settings.ghq_hirs_cmpr  = Config_ReadInt ("ghq_hirs_cmpr", "Enable S3TC and FXT1 compression", 0, TRUE, TRUE);
464   settings.ghq_hirs_tile = Config_ReadInt ("ghq_hirs_tile", "Tile hi-res textures (saves memory but could cause issues)", 0, TRUE, TRUE);
465   settings.ghq_hirs_f16bpp = Config_ReadInt ("ghq_hirs_f16bpp", "Force 16bpp hi-res textures (saves ram but lower quality)", 0, TRUE, TRUE);
466   settings.ghq_hirs_gz  = Config_ReadInt ("ghq_hirs_gz", "Compress hi-res texture cache", 1, TRUE, TRUE);
467   settings.ghq_hirs_altcrc = Config_ReadInt ("ghq_hirs_altcrc", "Alternative CRC calculation -- emulates Rice bug", 1, TRUE, TRUE);
468   settings.ghq_cache_save = Config_ReadInt ("ghq_cache_save", "Save tex cache to disk", 1, TRUE, TRUE);
469   settings.ghq_cache_size = Config_ReadInt ("ghq_cache_size", "Texture Cache Size (MB)", 128, TRUE, FALSE);
470   settings.ghq_hirs_let_texartists_fly = Config_ReadInt ("ghq_hirs_let_texartists_fly", "Use full alpha channel -- could cause issues for some tex packs", 0, TRUE, TRUE);
471   settings.ghq_hirs_dump = Config_ReadInt ("ghq_hirs_dump", "Dump textures", 0, FALSE, TRUE);
472 #endif
473
474   settings.special_alt_tex_size = Config_ReadInt("alt_tex_size", "Alternate texture size method: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
475   settings.special_use_sts1_only = Config_ReadInt("use_sts1_only", "Use first SETTILESIZE only: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
476   settings.special_force_calc_sphere = Config_ReadInt("force_calc_sphere", "Use spheric mapping only: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
477   settings.special_correct_viewport = Config_ReadInt("correct_viewport", "Force positive viewport: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
478   settings.special_increase_texrect_edge = Config_ReadInt("increase_texrect_edge", "Force texrect size to integral value: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
479   settings.special_decrease_fillrect_edge = Config_ReadInt("decrease_fillrect_edge", "Reduce fillrect size by 1: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
480   settings.special_texture_correction = Config_ReadInt("texture_correction", "Enable perspective texture correction emulation: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
481   settings.special_pal230 = Config_ReadInt("pal230", "Set special scale for PAL games: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
482   settings.special_stipple_mode = Config_ReadInt("stipple_mode", "3DFX Dithered alpha emulation mode: -1=Game default, >=0=dithered alpha emulation mode", -1, TRUE, FALSE);
483   settings.special_stipple_pattern = Config_ReadInt("stipple_pattern", "3DFX Dithered alpha pattern: -1=Game default, >=0=pattern used for dithered alpha emulation", -1, TRUE, FALSE);
484   settings.special_force_microcheck = Config_ReadInt("force_microcheck", "Check microcode each frame: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
485   settings.special_force_quad3d = Config_ReadInt("force_quad3d", "Force 0xb5 command to be quad, not line 3D: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
486   settings.special_clip_zmin = Config_ReadInt("clip_zmin", "Enable near z clipping: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
487   settings.special_clip_zmax = Config_ReadInt("clip_zmax", "Enable far plane clipping: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
488   settings.special_fast_crc = Config_ReadInt("fast_crc", "Use fast CRC algorithm: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
489   settings.special_adjust_aspect = Config_ReadInt("adjust_aspect", "Adjust screen aspect for wide screen mode: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
490   settings.special_zmode_compare_less = Config_ReadInt("zmode_compare_less", "Force strict check in Depth buffer test: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
491   settings.special_old_style_adither = Config_ReadInt("old_style_adither", "Apply alpha dither regardless of alpha_dither_mode: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
492   settings.special_n64_z_scale = Config_ReadInt("n64_z_scale", "Scale vertex z value before writing to depth buffer: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
493   settings.special_optimize_texrect = Config_ReadInt("optimize_texrect", "Fast texrect rendering with hwfbe: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
494   settings.special_ignore_aux_copy = Config_ReadInt("ignore_aux_copy", "Do not copy auxiliary frame buffers: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
495   settings.special_hires_buf_clear = Config_ReadInt("hires_buf_clear", "Clear auxiliary texture frame buffers: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
496   settings.special_fb_read_alpha = Config_ReadInt("fb_read_alpha", "Read alpha from framebuffer: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
497   settings.special_useless_is_useless = Config_ReadInt("useless_is_useless", "Handle unchanged fb: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
498   settings.special_fb_crc_mode = Config_ReadInt("fb_crc_mode", "Set frambuffer CRC mode: -1=Game default, 0=disable CRC, 1=fast CRC, 2=safe CRC", -1, TRUE, FALSE);
499   settings.special_filtering = Config_ReadInt("filtering", "Filtering mode: -1=Game default, 0=automatic, 1=force bilinear, 2=force point sampled", -1, TRUE, FALSE);
500   settings.special_fog = Config_ReadInt("fog", "Fog: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
501   settings.special_buff_clear = Config_ReadInt("buff_clear", "Buffer clear on every frame: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
502   settings.special_swapmode = Config_ReadInt("swapmode", "Buffer swapping method: -1=Game default, 0=swap buffers when vertical interrupt has occurred, 1=swap buffers when set of conditions is satisfied. Prevents flicker on some games, 2=mix of first two methods", -1, TRUE, FALSE);
503   settings.special_aspect = Config_ReadInt("aspect", "Aspect ratio: -1=Game default, 0=Force 4:3, 1=Force 16:9, 2=Stretch, 3=Original", -1, TRUE, FALSE);
504   settings.special_lodmode = Config_ReadInt("lodmode", "LOD calculation: -1=Game default, 0=disable. 1=fast, 2=precise", -1, TRUE, FALSE);
505   settings.special_fb_smart = Config_ReadInt("fb_smart", "Smart framebuffer: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
506   settings.special_fb_hires = Config_ReadInt("fb_hires", "Hardware frame buffer emulation: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
507   settings.special_fb_read_always = Config_ReadInt("fb_read_always", "Read framebuffer every frame (may be slow use only for effects that need it e.g. Banjo Kazooie, DK64 transitions): -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
508   settings.special_read_back_to_screen = Config_ReadInt("read_back_to_screen", "Render N64 frame buffer as texture: -1=Game default, 0=disable, 1=mode1, 2=mode2", -1, TRUE, FALSE);
509   settings.special_detect_cpu_write = Config_ReadInt("detect_cpu_write", "Show images written directly by CPU: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
510   settings.special_fb_get_info = Config_ReadInt("fb_get_info", "Get frame buffer info: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
511   settings.special_fb_render = Config_ReadInt("fb_render", "Enable software depth render: -1=Game default, 0=disable. 1=enable", -1, TRUE, FALSE);
512
513   //TODO-PORT: remove?
514   ConfigWrapper();
515 }
516
517 void ReadSpecialSettings (const char * name)
518 {
519   //  char buf [256];
520   //  sprintf(buf, "ReadSpecialSettings. Name: %s\n", name);
521   //  LOG(buf);
522   settings.hacks = 0;
523
524   //detect games which require special hacks
525   if (strstr(name, (const char *)"ZELDA") || strstr(name, (const char *)"MASK"))
526     settings.hacks |= hack_Zelda;
527   else if (strstr(name, (const char *)"ROADSTERS TROPHY"))
528     settings.hacks |= hack_Zelda;
529   else if (strstr(name, (const char *)"Diddy Kong Racing"))
530     settings.hacks |= hack_Diddy;
531   else if (strstr(name, (const char *)"Tonic Trouble"))
532     settings.hacks |= hack_Tonic;
533   else if (strstr(name, (const char *)"All") && strstr(name, (const char *)"Star") && strstr(name, (const char *)"Baseball"))
534     settings.hacks |= hack_ASB;
535   else if (strstr(name, (const char *)"Beetle") || strstr(name, (const char *)"BEETLE") || strstr(name, (const char *)"HSV"))
536     settings.hacks |= hack_BAR;
537   else if (strstr(name, (const char *)"I S S 64") || strstr(name, (const char *)"J WORLD SOCCER3") || strstr(name, (const char *)"PERFECT STRIKER") || strstr(name, (const char *)"RONALDINHO SOCCER"))
538     settings.hacks |= hack_ISS64;
539   else if (strstr(name, (const char *)"MARIOKART64"))
540     settings.hacks |= hack_MK64;
541   else if (strstr(name, (const char *)"NITRO64"))
542     settings.hacks |= hack_WCWnitro;
543   else if (strstr(name, (const char *)"CHOPPER_ATTACK") || strstr(name, (const char *)"WILD CHOPPERS"))
544     settings.hacks |= hack_Chopper;
545   else if (strstr(name, (const char *)"Resident Evil II") || strstr(name, (const char *)"BioHazard II"))
546     settings.hacks |= hack_RE2;
547   else if (strstr(name, (const char *)"YOSHI STORY"))
548     settings.hacks |= hack_Yoshi;
549   else if (strstr(name, (const char *)"F-Zero X") || strstr(name, (const char *)"F-ZERO X"))
550     settings.hacks |= hack_Fzero;
551   else if (strstr(name, (const char *)"PAPER MARIO") || strstr(name, (const char *)"MARIO STORY"))
552     settings.hacks |= hack_PMario;
553   else if (strstr(name, (const char *)"TOP GEAR RALLY 2"))
554     settings.hacks |= hack_TGR2;
555   else if (strstr(name, (const char *)"TOP GEAR RALLY"))
556     settings.hacks |= hack_TGR;
557   else if (strstr(name, (const char *)"Top Gear Hyper Bike"))
558     settings.hacks |= hack_Hyperbike;
559   else if (strstr(name, (const char *)"Killer Instinct Gold") || strstr(name, (const char *)"KILLER INSTINCT GOLD"))
560     settings.hacks |= hack_KI;
561   else if (strstr(name, (const char *)"Knockout Kings 2000"))
562     settings.hacks |= hack_Knockout;
563   else if (strstr(name, (const char *)"LEGORacers"))
564     settings.hacks |= hack_Lego;
565   else if (strstr(name, (const char *)"OgreBattle64"))
566     settings.hacks |= hack_Ogre64;
567   else if (strstr(name, (const char *)"Pilot Wings64"))
568     settings.hacks |= hack_Pilotwings;
569   else if (strstr(name, (const char *)"Supercross"))
570     settings.hacks |= hack_Supercross;
571   else if (strstr(name, (const char *)"STARCRAFT 64"))
572     settings.hacks |= hack_Starcraft;
573   else if (strstr(name, (const char *)"BANJO KAZOOIE 2") || strstr(name, (const char *)"BANJO TOOIE"))
574     settings.hacks |= hack_Banjo2;
575   else if (strstr(name, (const char *)"FIFA: RTWC 98") || strstr(name, (const char *)"RoadToWorldCup98"))
576     settings.hacks |= hack_Fifa98;
577   else if (strstr(name, (const char *)"Mega Man 64") || strstr(name, (const char *)"RockMan Dash"))
578     settings.hacks |= hack_Megaman;
579   else if (strstr(name, (const char *)"MISCHIEF MAKERS") || strstr(name, (const char *)"TROUBLE MAKERS"))
580     settings.hacks |= hack_Makers;
581   else if (strstr(name, (const char *)"GOLDENEYE"))
582     settings.hacks |= hack_GoldenEye;
583   else if (strstr(name, (const char *)"PUZZLE LEAGUE"))
584     settings.hacks |= hack_PPL;
585
586   Ini * ini = Ini::OpenIni();
587   if (!ini)
588     return;
589   ini->SetPath(name);
590
591   ini->Read(_T("alt_tex_size"), &(settings.alt_tex_size));
592   if (settings.special_alt_tex_size >= 0)
593     settings.alt_tex_size = settings.special_alt_tex_size;
594
595   ini->Read(_T("use_sts1_only"), &(settings.use_sts1_only));
596   if (settings.special_use_sts1_only >= 0)
597     settings.use_sts1_only = settings.special_use_sts1_only;
598
599   ini->Read(_T("force_calc_sphere"), &(settings.force_calc_sphere));
600   if (settings.special_force_calc_sphere >= 0)
601     settings.force_calc_sphere = settings.special_force_calc_sphere;
602
603   ini->Read(_T("correct_viewport"), &(settings.correct_viewport));
604   if (settings.special_correct_viewport >= 0)
605     settings.correct_viewport = settings.special_correct_viewport;
606
607   ini->Read(_T("increase_texrect_edge"), &(settings.increase_texrect_edge));
608   if (settings.special_increase_texrect_edge >= 0)
609     settings.increase_texrect_edge = settings.special_increase_texrect_edge;
610
611   ini->Read(_T("decrease_fillrect_edge"), &(settings.decrease_fillrect_edge));
612   if (settings.special_decrease_fillrect_edge >= 0)
613     settings.decrease_fillrect_edge = settings.special_decrease_fillrect_edge;
614
615   if (ini->Read(_T("texture_correction"), -1) == 0) settings.texture_correction = 0;
616   else settings.texture_correction = 1;
617   if (settings.special_texture_correction >= 0)
618     settings.texture_correction = settings.special_texture_correction;
619
620   if (ini->Read(_T("pal230"), -1) == 1) settings.pal230 = 1;
621   else settings.pal230 = 0;
622   if (settings.special_pal230 >= 0)
623     settings.pal230 = settings.special_pal230;
624
625   ini->Read(_T("stipple_mode"), &(settings.stipple_mode));
626   if (settings.special_stipple_mode >= 0)
627     settings.stipple_mode = settings.special_stipple_mode;
628
629   int stipple_pattern = ini->Read(_T("stipple_pattern"), -1);
630   if (stipple_pattern > 0) settings.stipple_pattern = (wxUint32)stipple_pattern;
631   if (settings.special_stipple_pattern >= 0)
632     stipple_pattern = settings.special_stipple_pattern;
633
634   ini->Read(_T("force_microcheck"), &(settings.force_microcheck));
635   if (settings.special_force_microcheck >= 0)
636     settings.force_microcheck = settings.special_force_microcheck;
637
638   ini->Read(_T("force_quad3d"), &(settings.force_quad3d));
639   if (settings.special_force_quad3d >= 0)
640     settings.force_quad3d = settings.special_force_quad3d;
641
642   ini->Read(_T("clip_zmin"), &(settings.clip_zmin));
643   if (settings.special_clip_zmin >= 0)
644     settings.clip_zmin = settings.special_clip_zmin;
645
646   ini->Read(_T("clip_zmax"), &(settings.clip_zmax));
647   if (settings.special_clip_zmax >= 0)
648     settings.clip_zmax = settings.special_clip_zmax;
649
650   ini->Read(_T("fast_crc"), &(settings.fast_crc));
651   if (settings.special_fast_crc >= 0)
652     settings.fast_crc = settings.special_fast_crc;
653
654   ini->Read(_T("adjust_aspect"), &(settings.adjust_aspect), 1);
655   if (settings.special_adjust_aspect >= 0)
656     settings.adjust_aspect = settings.special_adjust_aspect;
657
658   ini->Read(_T("zmode_compare_less"), &(settings.zmode_compare_less));
659   if (settings.special_zmode_compare_less >= 0)
660     settings.zmode_compare_less = settings.special_zmode_compare_less;
661
662   ini->Read(_T("old_style_adither"), &(settings.old_style_adither));
663   if (settings.special_old_style_adither >= 0)
664     settings.old_style_adither = settings.special_old_style_adither;
665
666   ini->Read(_T("n64_z_scale"), &(settings.n64_z_scale));
667   if (settings.special_n64_z_scale >= 0)
668     settings.n64_z_scale = settings.special_n64_z_scale;
669
670   if (settings.n64_z_scale)
671     ZLUT_init();
672
673   //frame buffer
674   int optimize_texrect = ini->Read(_T("optimize_texrect"), -1);
675   if (settings.special_optimize_texrect >= 0)
676     optimize_texrect = settings.special_optimize_texrect;
677
678   int ignore_aux_copy = ini->Read(_T("ignore_aux_copy"), -1);
679   if (settings.special_ignore_aux_copy >= 0)
680     ignore_aux_copy = settings.special_ignore_aux_copy;
681
682   int hires_buf_clear = ini->Read(_T("hires_buf_clear"), -1);
683   if (settings.special_hires_buf_clear >= 0)
684     hires_buf_clear = settings.special_hires_buf_clear;
685
686   int read_alpha = ini->Read(_T("fb_read_alpha"), -1);
687   if (settings.special_fb_read_alpha >= 0)
688     read_alpha = settings.special_fb_read_alpha;
689
690   int useless_is_useless = ini->Read(_T("useless_is_useless"), -1);
691   if (settings.special_useless_is_useless >= 0)
692     useless_is_useless = settings.special_useless_is_useless;
693
694   int fb_crc_mode = ini->Read(_T("fb_crc_mode"), -1);
695   if (settings.special_fb_crc_mode >= 0)
696     fb_crc_mode = settings.special_fb_crc_mode;
697
698
699   if (optimize_texrect > 0) settings.frame_buffer |= fb_optimize_texrect;
700   else if (optimize_texrect == 0) settings.frame_buffer &= ~fb_optimize_texrect;
701   if (ignore_aux_copy > 0) settings.frame_buffer |= fb_ignore_aux_copy;
702   else if (ignore_aux_copy == 0) settings.frame_buffer &= ~fb_ignore_aux_copy;
703   if (hires_buf_clear > 0) settings.frame_buffer |= fb_hwfbe_buf_clear;
704   else if (hires_buf_clear == 0) settings.frame_buffer &= ~fb_hwfbe_buf_clear;
705   if (read_alpha > 0) settings.frame_buffer |= fb_read_alpha;
706   else if (read_alpha == 0) settings.frame_buffer &= ~fb_read_alpha;
707   if (useless_is_useless > 0) settings.frame_buffer |= fb_useless_is_useless;
708   else settings.frame_buffer &= ~fb_useless_is_useless;
709   if (fb_crc_mode >= 0) settings.fb_crc_mode = (SETTINGS::FBCRCMODE)fb_crc_mode;
710
711   //  if (settings.custom_ini)
712   {
713     ini->Read(_T("filtering"), &(settings.filtering));
714     ini->Read(_T("fog"), &(settings.fog));
715     ini->Read(_T("buff_clear"), &(settings.buff_clear));
716     ini->Read(_T("swapmode"), &(settings.swapmode));
717     int tmp_aspect = ini->Read(_T("aspect"), -1);
718     if (tmp_aspect != 0) settings.aspectmode = tmp_aspect;
719     ini->Read(_T("lodmode"), &(settings.lodmode));
720 #ifdef PAULSCODE
721     ini->Read(_T("autoframeskip"), &(settings.autoframeskip));
722     ini->Read(_T("maxframeskip"), &(settings.maxframeskip));
723     if( settings.autoframeskip == 1 )
724       frameSkipper.setSkips( FrameSkipper::AUTO, settings.maxframeskip );
725     else
726       frameSkipper.setSkips( FrameSkipper::MANUAL, settings.maxframeskip );
727 #endif
728
729     /*
730     TODO-port: fix resolutions
731     int resolution;
732     if (ini->Read(_T("resolution"), &resolution))
733     {
734       settings.res_data = (wxUint32)resolution;
735       if (settings.res_data >= 0x18) settings.res_data = 12;
736       settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0];
737       settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1];
738     }
739     */
740         
741         PackedScreenResolution tmpRes = Config_ReadScreenSettings();
742         settings.res_data = tmpRes.resolution;
743         settings.scr_res_x = settings.res_x = tmpRes.width;
744         settings.scr_res_y = settings.res_y = tmpRes.height;
745
746     //frame buffer
747     int smart_read = ini->Read(_T("fb_smart"), -1);
748     if (settings.special_fb_smart >= 0)
749       smart_read = settings.special_fb_smart;
750
751     int hires = ini->Read(_T("fb_hires"), -1);
752     if (settings.special_fb_hires >= 0)
753       hires = settings.special_fb_hires;
754
755     int read_always = ini->Read(_T("fb_read_always"), -1);
756     if (settings.special_fb_read_always >= 0)
757       read_always = settings.special_fb_read_always;
758
759     int read_back_to_screen = ini->Read(_T("read_back_to_screen"), -1);
760     if (settings.special_read_back_to_screen >= 0)
761       read_back_to_screen = settings.special_read_back_to_screen;
762
763     int cpu_write_hack = ini->Read(_T("detect_cpu_write"), -1);
764     if (settings.special_detect_cpu_write >= 0)
765       cpu_write_hack = settings.special_detect_cpu_write;
766
767     int get_fbinfo = ini->Read(_T("fb_get_info"), -1);
768     if (settings.special_fb_get_info >= 0)
769       get_fbinfo = settings.special_fb_get_info;
770
771     int depth_render = ini->Read(_T("fb_render"), -1);
772     if (settings.special_fb_render >= 0)
773       depth_render = settings.special_fb_render;
774
775     if (smart_read > 0) settings.frame_buffer |= fb_emulation;
776     else if (smart_read == 0) settings.frame_buffer &= ~fb_emulation;
777     if (hires > 0) settings.frame_buffer |= fb_hwfbe;
778     else if (hires == 0) settings.frame_buffer &= ~fb_hwfbe;
779     if (read_always > 0) settings.frame_buffer |= fb_ref;
780     else if (read_always == 0) settings.frame_buffer &= ~fb_ref;
781     if (read_back_to_screen == 1) settings.frame_buffer |= fb_read_back_to_screen;
782     else if (read_back_to_screen == 2) settings.frame_buffer |= fb_read_back_to_screen2;
783     else if (read_back_to_screen == 0) settings.frame_buffer &= ~(fb_read_back_to_screen|fb_read_back_to_screen2);
784     if (cpu_write_hack > 0) settings.frame_buffer |= fb_cpu_write_hack;
785     else if (cpu_write_hack == 0) settings.frame_buffer &= ~fb_cpu_write_hack;
786     if (get_fbinfo > 0) settings.frame_buffer |= fb_get_info;
787     else if (get_fbinfo == 0) settings.frame_buffer &= ~fb_get_info;
788     if (depth_render > 0) settings.frame_buffer |= fb_depth_render;
789     else if (depth_render == 0) settings.frame_buffer &= ~fb_depth_render;
790     settings.frame_buffer |= fb_motionblur;
791   }
792   settings.flame_corona = (settings.hacks & hack_Zelda) && !fb_depth_render_enabled;
793 }
794
795 //TODO-PORT: more ini stuff
796 void WriteSettings (bool saveEmulationSettings)
797 {
798 /*
799   wxConfigBase * ini = OpenIni();
800   if (!ini || !ini->HasGroup(_T("/SETTINGS")))
801     return;
802   ini->SetPath(_T("/SETTINGS"));
803
804   ini->Write(_T("card_id"), settings.card_id);
805   ini->Write(_T("lang_id"), settings.lang_id);
806   ini->Write(_T("resolution"), (int)settings.res_data);
807   ini->Write(_T("ssformat"), settings.ssformat);
808   ini->Write(_T("vsync"), settings.vsync);
809   ini->Write(_T("show_fps"), settings.show_fps);
810   ini->Write(_T("clock"), settings.clock);
811   ini->Write(_T("clock_24_hr"), settings.clock_24_hr);
812   ini->Write(_T("advanced_options"), settings.advanced_options);
813   ini->Write(_T("texenh_options"), settings.texenh_options);
814
815   ini->Write(_T("wrpResolution"), settings.wrpResolution);
816   ini->Write(_T("wrpVRAM"), settings.wrpVRAM);
817   ini->Write(_T("wrpFBO"), settings.wrpFBO);
818   ini->Write(_T("wrpAnisotropic"), settings.wrpAnisotropic);
819
820 #ifndef _ENDUSER_RELEASE_
821   ini->Write(_T("autodetect_ucode"), settings.autodetect_ucode);
822   ini->Write(_T("ucode"), (int)settings.ucode);
823   ini->Write(_T("wireframe"), settings.wireframe);
824   ini->Write(_T("wfmode"), settings.wfmode);
825   ini->Write(_T("logging"), settings.logging);
826   ini->Write(_T("log_clear"), settings.log_clear);
827   ini->Write(_T("run_in_window"), settings.run_in_window);
828   ini->Write(_T("elogging"), settings.elogging);
829   ini->Write(_T("filter_cache"), settings.filter_cache);
830   ini->Write(_T("unk_as_red"), settings.unk_as_red);
831   ini->Write(_T("log_unk"), settings.log_unk);
832   ini->Write(_T("unk_clear"), settings.unk_clear);
833 #endif //_ENDUSER_RELEASE_
834
835 #ifdef TEXTURE_FILTER
836   ini->Write(_T("ghq_fltr"), settings.ghq_fltr);
837   ini->Write(_T("ghq_cmpr"), settings.ghq_cmpr);
838   ini->Write(_T("ghq_enht"), settings.ghq_enht);
839   ini->Write(_T("ghq_hirs"), settings.ghq_hirs);
840   ini->Write(_T("ghq_enht_cmpr"), settings.ghq_enht_cmpr);
841   ini->Write(_T("ghq_enht_tile"), settings.ghq_enht_tile);
842   ini->Write(_T("ghq_enht_f16bpp"), settings.ghq_enht_f16bpp);
843   ini->Write(_T("ghq_enht_gz"), settings.ghq_enht_gz);
844   ini->Write(_T("ghq_enht_nobg"), settings.ghq_enht_nobg);
845   ini->Write(_T("ghq_hirs_cmpr"), settings.ghq_hirs_cmpr);
846   ini->Write(_T("ghq_hirs_tile"), settings.ghq_hirs_tile);
847   ini->Write(_T("ghq_hirs_f16bpp"), settings.ghq_hirs_f16bpp);
848   ini->Write(_T("ghq_hirs_gz"), settings.ghq_hirs_gz);
849   ini->Write(_T("ghq_hirs_altcrc"), settings.ghq_hirs_altcrc);
850   ini->Write(_T("ghq_cache_save"), settings.ghq_cache_save);
851   ini->Write(_T("ghq_cache_size"), settings.ghq_cache_size);
852   ini->Write(_T("ghq_hirs_let_texartists_fly"), settings.ghq_hirs_let_texartists_fly);
853   ini->Write(_T("ghq_hirs_dump"), settings.ghq_hirs_dump);
854 #endif
855
856   if (saveEmulationSettings)
857   {
858     if (romopen)
859     {
860       wxString S = _T("/");
861       ini->SetPath(S+rdp.RomName);
862     }
863     else
864       ini->SetPath(_T("/DEFAULT"));
865     ini->Write(_T("filtering"), settings.filtering);
866     ini->Write(_T("fog"), settings.fog);
867     ini->Write(_T("buff_clear"), settings.buff_clear);
868     ini->Write(_T("swapmode"), settings.swapmode);
869     ini->Write(_T("lodmode"), settings.lodmode);
870     ini->Write(_T("aspect"), settings.aspectmode);
871
872     ini->Write(_T("fb_read_always"), settings.frame_buffer&fb_ref ? 1 : 0l);
873     ini->Write(_T("fb_smart"), settings.frame_buffer & fb_emulation ? 1 : 0l);
874     //    ini->Write("motionblur", settings.frame_buffer & fb_motionblur ? 1 : 0);
875     ini->Write(_T("fb_hires"), settings.frame_buffer & fb_hwfbe ? 1 : 0l);
876     ini->Write(_T("fb_get_info"), settings.frame_buffer & fb_get_info ? 1 : 0l);
877     ini->Write(_T("fb_render"), settings.frame_buffer & fb_depth_render ? 1 : 0l);
878     ini->Write(_T("detect_cpu_write"), settings.frame_buffer & fb_cpu_write_hack ? 1 : 0l);
879     if (settings.frame_buffer & fb_read_back_to_screen)
880       ini->Write(_T("read_back_to_screen"), 1);
881     else if (settings.frame_buffer & fb_read_back_to_screen2)
882       ini->Write(_T("read_back_to_screen"), 2);
883     else
884       ini->Write(_T("read_back_to_screen"), 0l);
885   }
886
887   wxFileOutputStream os(iniName);
888   ((wxFileConfig*)ini)->Save(os);
889 */
890 }
891
892 GRTEXBUFFEREXT   grTextureBufferExt = NULL;
893 GRTEXBUFFEREXT   grTextureAuxBufferExt = NULL;
894 GRAUXBUFFEREXT   grAuxBufferExt = NULL;
895 GRSTIPPLE grStippleModeExt = NULL;
896 GRSTIPPLE grStipplePatternExt = NULL;
897 FxBool (FX_CALL *grKeyPressed)(FxU32) = NULL;
898
899 int GetTexAddrUMA(int tmu, int texsize)
900 {
901   int addr = voodoo.tex_min_addr[0] + voodoo.tmem_ptr[0];
902   voodoo.tmem_ptr[0] += texsize;
903   voodoo.tmem_ptr[1] = voodoo.tmem_ptr[0];
904   return addr;
905 }
906 int GetTexAddrNonUMA(int tmu, int texsize)
907 {
908   int addr = voodoo.tex_min_addr[tmu] + voodoo.tmem_ptr[tmu];
909   voodoo.tmem_ptr[tmu] += texsize;
910   return addr;
911 }
912 GETTEXADDR GetTexAddr = GetTexAddrNonUMA;
913
914 // guLoadTextures - used to load the cursor and font textures
915 void guLoadTextures ()
916 {
917   if (grTextureBufferExt)
918   {
919     int tbuf_size = 0;
920     if (voodoo.max_tex_size <= 256)
921     {
922       grTextureBufferExt(  GR_TMU1, voodoo.tex_min_addr[GR_TMU1], GR_LOD_LOG2_256, GR_LOD_LOG2_256,
923         GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
924       tbuf_size = 8 * grTexCalcMemRequired(GR_LOD_LOG2_256, GR_LOD_LOG2_256,
925         GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);
926     }
927     else if (settings.scr_res_x <= 1024)
928     {
929       grTextureBufferExt(  GR_TMU0, voodoo.tex_min_addr[GR_TMU0], GR_LOD_LOG2_1024, GR_LOD_LOG2_1024,
930         GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
931       tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_1024, GR_LOD_LOG2_1024,
932         GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);
933       grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
934       grBufferClear (0, 0, 0xFFFF);
935       grRenderBuffer( GR_BUFFER_BACKBUFFER );
936     }
937     else
938     {
939       grTextureBufferExt(  GR_TMU0, voodoo.tex_min_addr[GR_TMU0], GR_LOD_LOG2_2048, GR_LOD_LOG2_2048,
940         GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
941       tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_2048, GR_LOD_LOG2_2048,
942         GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);
943       grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
944       grBufferClear (0, 0, 0xFFFF);
945       grRenderBuffer( GR_BUFFER_BACKBUFFER );
946     }
947
948     rdp.texbufs[0].tmu = GR_TMU0;
949     rdp.texbufs[0].begin = voodoo.tex_min_addr[GR_TMU0];
950     rdp.texbufs[0].end = rdp.texbufs[0].begin+tbuf_size;
951     rdp.texbufs[0].count = 0;
952     rdp.texbufs[0].clear_allowed = TRUE;
953     offset_font = tbuf_size;
954     if (voodoo.num_tmu > 1)
955     {
956       rdp.texbufs[1].tmu = GR_TMU1;
957       rdp.texbufs[1].begin = voodoo.tex_UMA ? rdp.texbufs[0].end : voodoo.tex_min_addr[GR_TMU1];
958       rdp.texbufs[1].end = rdp.texbufs[1].begin+tbuf_size;
959       rdp.texbufs[1].count = 0;
960       rdp.texbufs[1].clear_allowed = TRUE;
961       if (voodoo.tex_UMA)
962         offset_font += tbuf_size;
963       else
964         offset_texbuf1 = tbuf_size;
965     }
966   }
967   else
968     offset_font = 0;
969
970 #include "font.h"
971   wxUint32 *data = (wxUint32*)font;
972   wxUint32 cur;
973
974   // ** Font texture **
975   wxUint8 *tex8 = (wxUint8*)malloc(256*64);
976
977   fontTex.smallLodLog2 = fontTex.largeLodLog2 = GR_LOD_LOG2_256;
978   fontTex.aspectRatioLog2 = GR_ASPECT_LOG2_4x1;
979   fontTex.format = GR_TEXFMT_ALPHA_8;
980   fontTex.data = tex8;
981
982   // Decompression: [1-bit inverse alpha --> 8-bit alpha]
983   wxUint32 i,b;
984   for (i=0; i<0x200; i++)
985   {
986     // cur = ~*(data++), byteswapped
987 #ifdef __VISUALC__
988     cur = _byteswap_ulong(~*(data++));
989 #else
990     cur = ~*(data++);
991     cur = ((cur&0xFF)<<24)|(((cur>>8)&0xFF)<<16)|(((cur>>16)&0xFF)<<8)|((cur>>24)&0xFF);
992 #endif
993
994     for (b=0x80000000; b!=0; b>>=1)
995     {
996       if (cur&b) *tex8 = 0xFF;
997       else *tex8 = 0x00;
998       tex8 ++;
999     }
1000   }
1001
1002   grTexDownloadMipMap (GR_TMU0,
1003     voodoo.tex_min_addr[GR_TMU0] + offset_font,
1004     GR_MIPMAPLEVELMASK_BOTH,
1005     &fontTex);
1006
1007   offset_cursor = offset_font + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &fontTex);
1008
1009   free (fontTex.data);
1010
1011   // ** Cursor texture **
1012 #include "cursor.h"
1013   data = (wxUint32*)cursor;
1014
1015   wxUint16 *tex16 = (wxUint16*)malloc(32*32*2);
1016
1017   cursorTex.smallLodLog2 = cursorTex.largeLodLog2 = GR_LOD_LOG2_32;
1018   cursorTex.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
1019   cursorTex.format = GR_TEXFMT_ARGB_1555;
1020   cursorTex.data = tex16;
1021
1022   // Conversion: [16-bit 1555 (swapped) --> 16-bit 1555]
1023   for (i=0; i<0x200; i++)
1024   {
1025     cur = *(data++);
1026     *(tex16++) = (wxUint16)(((cur&0x000000FF)<<8)|((cur&0x0000FF00)>>8));
1027     *(tex16++) = (wxUint16)(((cur&0x00FF0000)>>8)|((cur&0xFF000000)>>24));
1028   }
1029
1030   grTexDownloadMipMap (GR_TMU0,
1031     voodoo.tex_min_addr[GR_TMU0] + offset_cursor,
1032     GR_MIPMAPLEVELMASK_BOTH,
1033     &cursorTex);
1034
1035   // Round to higher 16
1036   offset_textures = ((offset_cursor + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &cursorTex))
1037     & 0xFFFFFFF0) + 16;
1038   free (cursorTex.data);
1039 }
1040
1041 #ifdef TEXTURE_FILTER
1042 void DisplayLoadProgress(const wchar_t *format, ...)
1043 {
1044   va_list args;
1045   wchar_t wbuf[INFO_BUF];
1046   char buf[INFO_BUF];
1047
1048   // process input
1049   va_start(args, format);
1050   vswprintf(wbuf, INFO_BUF, format, args);
1051   va_end(args);
1052
1053   // XXX: convert to multibyte
1054   wcstombs(buf, wbuf, INFO_BUF);
1055
1056   if (fullscreen)
1057   {
1058     float x;
1059     set_message_combiner ();
1060     output (382, 380, 1, "LOADING TEXTURES. PLEASE WAIT...");
1061     int len = min (strlen(buf)*8, 1024);
1062     x = (1024-len)/2.0f;
1063     output (x, 360, 1, buf);
1064     grBufferSwap (0);
1065     grColorMask (FXTRUE, FXTRUE);
1066     grBufferClear (0, 0, 0xFFFF);
1067   }
1068 }
1069 #endif
1070
1071 int InitGfx ()
1072 {
1073 #ifdef TEXTURE_FILTER
1074   wchar_t romname[256];
1075   wchar_t foldername[PATH_MAX + 64];
1076   wchar_t cachename[PATH_MAX + 64];
1077 #endif
1078   if (fullscreen)
1079     ReleaseGfx ();
1080
1081   OPEN_RDP_LOG ();  // doesn't matter if opens again; it will check for it
1082   OPEN_RDP_E_LOG ();
1083   VLOG ("InitGfx ()\n");
1084
1085   debugging = FALSE;
1086   rdp_reset ();
1087
1088   // Initialize Glide
1089   grGlideInit ();
1090
1091   // Select the Glide device
1092   grSstSelect (settings.card_id);
1093
1094   // Is mirroring allowed?
1095   const char *extensions = grGetString (GR_EXTENSION);
1096
1097   // Check which SST we are using and initialize stuff
1098   // Hiroshi Morii <koolsmoky@users.sourceforge.net>
1099   enum {
1100     GR_SSTTYPE_VOODOO  = 0,
1101     GR_SSTTYPE_SST96   = 1,
1102     GR_SSTTYPE_AT3D    = 2,
1103     GR_SSTTYPE_Voodoo2 = 3,
1104     GR_SSTTYPE_Banshee = 4,
1105     GR_SSTTYPE_Voodoo3 = 5,
1106     GR_SSTTYPE_Voodoo4 = 6,
1107     GR_SSTTYPE_Voodoo5 = 7
1108   };
1109   const char *hardware = grGetString(GR_HARDWARE);
1110   unsigned int SST_type = GR_SSTTYPE_VOODOO;
1111   if (strstr(hardware, "Rush")) {
1112     SST_type = GR_SSTTYPE_SST96;
1113   } else if (strstr(hardware, "Voodoo2")) {
1114     SST_type = GR_SSTTYPE_Voodoo2;
1115   } else if (strstr(hardware, "Voodoo Banshee")) {
1116     SST_type = GR_SSTTYPE_Banshee;
1117   } else if (strstr(hardware, "Voodoo3")) {
1118     SST_type = GR_SSTTYPE_Voodoo3;
1119   } else if (strstr(hardware, "Voodoo4")) {
1120     SST_type = GR_SSTTYPE_Voodoo4;
1121   } else if (strstr(hardware, "Voodoo5")) {
1122     SST_type = GR_SSTTYPE_Voodoo5;
1123   }
1124   // 2Mb Texture boundary
1125   voodoo.has_2mb_tex_boundary = (SST_type < GR_SSTTYPE_Banshee) && !evoodoo;
1126   // use UMA if available
1127   voodoo.tex_UMA = FALSE;
1128   //*
1129   if (strstr(extensions, " TEXUMA ")) {
1130     // we get better texture cache hits with UMA on
1131     grEnable(GR_TEXTURE_UMA_EXT);
1132     voodoo.tex_UMA = TRUE;
1133     LOG ("Using TEXUMA extension.\n");
1134   }
1135   //*/
1136 //TODO-PORT: fullscreen stuff
1137   wxUint32 res_data = settings.res_data;
1138   char strWrapperFullScreenResolutionExt[] = "grWrapperFullScreenResolutionExt";
1139   if (ev_fullscreen)
1140   {
1141       GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt =
1142         (GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress(strWrapperFullScreenResolutionExt);
1143       if (grWrapperFullScreenResolutionExt) {
1144         wxUint32 _width, _height = 0;
1145         settings.res_data = grWrapperFullScreenResolutionExt(&_width, &_height);
1146         settings.scr_res_x = settings.res_x = _width;
1147         settings.scr_res_y = settings.res_y = _height;
1148       }
1149       res_data = settings.res_data;
1150   }
1151   else if (evoodoo)
1152   {
1153       GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt =
1154         (GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress(strWrapperFullScreenResolutionExt);
1155       if (grWrapperFullScreenResolutionExt != NULL)
1156       {
1157 /*
1158         TODO-port: fix resolutions
1159         settings.res_data = settings.res_data_org;
1160         settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0];
1161         settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1];
1162 */
1163       }
1164       res_data = settings.res_data | 0x80000000;
1165   }
1166
1167   gfx_context = 0;
1168
1169   // Select the window
1170
1171   if (fb_hwfbe_enabled)
1172   {
1173     char strSstWinOpenExt[] ="grSstWinOpenExt";
1174     GRWINOPENEXT grSstWinOpenExt = (GRWINOPENEXT)grGetProcAddress(strSstWinOpenExt);
1175     if (grSstWinOpenExt)
1176       gfx_context = grSstWinOpenExt ((FxU32)NULL,
1177       res_data,
1178       GR_REFRESH_60Hz,
1179       GR_COLORFORMAT_RGBA,
1180       GR_ORIGIN_UPPER_LEFT,
1181       fb_emulation_enabled?GR_PIXFMT_RGB_565:GR_PIXFMT_ARGB_8888, //32b color is not compatible with fb emulation
1182       2,    // Double-buffering
1183       1);   // 1 auxillary buffer
1184   }
1185   if (!gfx_context)
1186     gfx_context = grSstWinOpen ((FxU32)NULL,
1187     res_data,
1188     GR_REFRESH_60Hz,
1189     GR_COLORFORMAT_RGBA,
1190     GR_ORIGIN_UPPER_LEFT,
1191     2,    // Double-buffering
1192     1);   // 1 auxillary buffer
1193
1194   if (!gfx_context)
1195   {
1196     ERRLOG("Error setting display mode");
1197     //    grSstWinClose (gfx_context);
1198     grGlideShutdown ();
1199     return FALSE;
1200   }
1201
1202   fullscreen = TRUE;
1203   to_fullscreen = FALSE;
1204
1205
1206   // get the # of TMUs available
1207   grGet (GR_NUM_TMU, 4, (FxI32*)&voodoo.num_tmu);
1208   // get maximal texture size
1209   grGet (GR_MAX_TEXTURE_SIZE, 4, (FxI32*)&voodoo.max_tex_size);
1210   voodoo.sup_large_tex = (voodoo.max_tex_size > 256 && !(settings.hacks & hack_PPL));
1211
1212   //num_tmu = 1;
1213   if (voodoo.tex_UMA)
1214   {
1215     GetTexAddr = GetTexAddrUMA;
1216     voodoo.tex_min_addr[0] = voodoo.tex_min_addr[1] = grTexMinAddress(GR_TMU0);
1217     voodoo.tex_max_addr[0] = voodoo.tex_max_addr[1] = grTexMaxAddress(GR_TMU0);
1218   }
1219   else
1220   {
1221     GetTexAddr = GetTexAddrNonUMA;
1222     voodoo.tex_min_addr[0] = grTexMinAddress(GR_TMU0);
1223     voodoo.tex_min_addr[1] = grTexMinAddress(GR_TMU1);
1224     voodoo.tex_max_addr[0] = grTexMaxAddress(GR_TMU0);
1225     voodoo.tex_max_addr[1] = grTexMaxAddress(GR_TMU1);
1226   }
1227
1228   if (strstr (extensions, "TEXMIRROR") && !(settings.hacks&hack_Zelda)) //zelda's trees suffer from hardware mirroring
1229     voodoo.sup_mirroring = 1;
1230   else
1231     voodoo.sup_mirroring = 0;
1232
1233   if (strstr (extensions, "TEXFMT"))  //VSA100 texture format extension
1234     voodoo.sup_32bit_tex = TRUE;
1235   else
1236     voodoo.sup_32bit_tex = FALSE;
1237
1238   voodoo.gamma_correction = 0;
1239   if (strstr(extensions, "GETGAMMA"))
1240     grGet(GR_GAMMA_TABLE_ENTRIES, sizeof(voodoo.gamma_table_size), &voodoo.gamma_table_size);
1241
1242   if (fb_hwfbe_enabled)
1243   {
1244     if (char * extstr = (char*)strstr(extensions, "TEXTUREBUFFER"))
1245     {
1246       if (!strncmp(extstr, "TEXTUREBUFFER", 13))
1247       {
1248         char strTextureBufferExt[] = "grTextureBufferExt";
1249         grTextureBufferExt = (GRTEXBUFFEREXT) grGetProcAddress(strTextureBufferExt);
1250         char strTextureAuxBufferExt[] = "grTextureAuxBufferExt";
1251         grTextureAuxBufferExt = (GRTEXBUFFEREXT) grGetProcAddress(strTextureAuxBufferExt);
1252         char strAuxBufferExt[] = "grAuxBufferExt";
1253         grAuxBufferExt = (GRAUXBUFFEREXT) grGetProcAddress(strAuxBufferExt);
1254       }
1255     }
1256     else
1257       settings.frame_buffer &= ~fb_hwfbe;
1258   }
1259   else
1260     grTextureBufferExt = 0;
1261
1262   grStippleModeExt = (GRSTIPPLE)grStippleMode;
1263   grStipplePatternExt = (GRSTIPPLE)grStipplePattern;
1264
1265   if (grStipplePatternExt)
1266     grStipplePatternExt(settings.stipple_pattern);
1267
1268 //  char strKeyPressedExt[] = "grKeyPressedExt";
1269 //  grKeyPressed = (FxBool (FX_CALL *)(FxU32))grGetProcAddress (strKeyPressedExt);
1270
1271   InitCombine();
1272
1273 #ifdef SIMULATE_VOODOO1
1274   voodoo.num_tmu = 1;
1275   voodoo.sup_mirroring = 0;
1276 #endif
1277
1278 #ifdef SIMULATE_BANSHEE
1279   voodoo.num_tmu = 1;
1280   voodoo.sup_mirroring = 1;
1281 #endif
1282
1283   grCoordinateSpace (GR_WINDOW_COORDS);
1284   grVertexLayout (GR_PARAM_XY, offsetof(VERTEX,x), GR_PARAM_ENABLE);
1285   grVertexLayout (GR_PARAM_Q, offsetof(VERTEX,q), GR_PARAM_ENABLE);
1286   grVertexLayout (GR_PARAM_Z, offsetof(VERTEX,z), GR_PARAM_ENABLE);
1287   grVertexLayout (GR_PARAM_ST0, offsetof(VERTEX,coord[0]), GR_PARAM_ENABLE);
1288   grVertexLayout (GR_PARAM_ST1, offsetof(VERTEX,coord[2]), GR_PARAM_ENABLE);
1289   grVertexLayout (GR_PARAM_PARGB, offsetof(VERTEX,b), GR_PARAM_ENABLE);
1290
1291   grCullMode(GR_CULL_NEGATIVE);
1292
1293   if (settings.fog) //"FOGCOORD" extension
1294   {
1295     if (strstr (extensions, "FOGCOORD"))
1296     {
1297       GrFog_t fog_t[64];
1298       guFogGenerateLinear (fog_t, 0.0f, 255.0f);//(float)rdp.fog_multiplier + (float)rdp.fog_offset);//256.0f);
1299
1300       for (int i = 63; i > 0; i--)
1301       {
1302         if (fog_t[i] - fog_t[i-1] > 63)
1303         {
1304           fog_t[i-1] = fog_t[i] - 63;
1305         }
1306       }
1307       fog_t[0] = 0;
1308       //      for (int f = 0; f < 64; f++)
1309       //      {
1310       //        FRDP("fog[%d]=%d->%f\n", f, fog_t[f], guFogTableIndexToW(f));
1311       //      }
1312       grFogTable (fog_t);
1313       grVertexLayout (GR_PARAM_FOG_EXT, offsetof(VERTEX,f), GR_PARAM_ENABLE);
1314     }
1315     else //not supported
1316       settings.fog = FALSE;
1317   }
1318
1319   grDepthBufferMode (GR_DEPTHBUFFER_ZBUFFER);
1320   grDepthBufferFunction(GR_CMP_LESS);
1321   grDepthMask(FXTRUE);
1322
1323   settings.res_x = settings.scr_res_x;
1324   settings.res_y = settings.scr_res_y;
1325   ChangeSize ();
1326
1327   guLoadTextures ();
1328   ClearCache ();
1329
1330   grCullMode (GR_CULL_DISABLE);
1331   grDepthBufferMode (GR_DEPTHBUFFER_ZBUFFER);
1332   grDepthBufferFunction (GR_CMP_ALWAYS);
1333   grRenderBuffer(GR_BUFFER_BACKBUFFER);
1334   grColorMask (FXTRUE, FXTRUE);
1335   grDepthMask (FXTRUE);
1336   grBufferClear (0, 0, 0xFFFF);
1337   grBufferSwap (0);
1338   grBufferClear (0, 0, 0xFFFF);
1339   grDepthMask (FXFALSE);
1340   grTexFilterMode (0, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR);
1341   grTexFilterMode (1, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR);
1342   grTexClampMode (0, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP);
1343   grTexClampMode (1, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP);
1344   grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y);
1345   rdp.update |= UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE;
1346
1347 #ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
1348   if (!settings.ghq_use)
1349   {
1350     settings.ghq_use = settings.ghq_fltr || settings.ghq_enht /*|| settings.ghq_cmpr*/ || settings.ghq_hirs;
1351     if (settings.ghq_use)
1352     {
1353       /* Plugin path */
1354       int options = texfltr[settings.ghq_fltr]|texenht[settings.ghq_enht]|texcmpr[settings.ghq_cmpr]|texhirs[settings.ghq_hirs];
1355       if (settings.ghq_enht_cmpr)
1356         options |= COMPRESS_TEX;
1357       if (settings.ghq_hirs_cmpr)
1358         options |= COMPRESS_HIRESTEX;
1359       //      if (settings.ghq_enht_tile)
1360       //        options |= TILE_TEX;
1361       if (settings.ghq_hirs_tile)
1362         options |= TILE_HIRESTEX;
1363       if (settings.ghq_enht_f16bpp)
1364         options |= FORCE16BPP_TEX;
1365       if (settings.ghq_hirs_f16bpp)
1366         options |= FORCE16BPP_HIRESTEX;
1367       if (settings.ghq_enht_gz)
1368         options |= GZ_TEXCACHE;
1369       if (settings.ghq_hirs_gz)
1370         options |= GZ_HIRESTEXCACHE;
1371       if (settings.ghq_cache_save)
1372         options |= (DUMP_TEXCACHE|DUMP_HIRESTEXCACHE);
1373       if (settings.ghq_hirs_let_texartists_fly)
1374         options |= LET_TEXARTISTS_FLY;
1375       if (settings.ghq_hirs_dump)
1376         options |= DUMP_TEX;
1377
1378       ghq_dmptex_toggle_key = 0;
1379
1380       swprintf(romname, sizeof(romname) / sizeof(*romname), L"%hs", rdp.RomName);
1381       swprintf(foldername, sizeof(foldername) / sizeof(*foldername), L"%hs", ConfigGetUserDataPath());
1382       swprintf(cachename, sizeof(cachename) / sizeof(*cachename), L"%hs", ConfigGetUserCachePath());
1383
1384       settings.ghq_use = (int)ext_ghq_init(voodoo.max_tex_size, // max texture width supported by hardware
1385         voodoo.max_tex_size, // max texture height supported by hardware
1386         voodoo.sup_32bit_tex?32:16, // max texture bpp supported by hardware
1387         options,
1388         settings.ghq_cache_size * 1024*1024, // cache texture to system memory
1389         foldername,
1390         cachename,
1391         romname, // name of ROM. must be no longer than 256 characters
1392         DisplayLoadProgress);
1393     }
1394   }
1395   if (settings.ghq_use && strstr (extensions, "TEXMIRROR"))
1396     voodoo.sup_mirroring = 1;
1397 #endif
1398
1399   return TRUE;
1400 }
1401
1402 void ReleaseGfx ()
1403 {
1404   VLOG("ReleaseGfx ()\n");
1405
1406   // Restore gamma settings
1407   if (voodoo.gamma_correction)
1408   {
1409     if (voodoo.gamma_table_r)
1410       grLoadGammaTable(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b);
1411     else
1412       guGammaCorrectionRGB(1.3f, 1.3f, 1.3f); //1.3f is default 3dfx gamma for everything but desktop
1413     voodoo.gamma_correction = 0;
1414   }
1415
1416   // Release graphics
1417   grSstWinClose (gfx_context);
1418
1419   // Shutdown glide
1420   grGlideShutdown();
1421
1422   fullscreen = FALSE;
1423   rdp.window_changed = TRUE;
1424 }
1425
1426 // new API code begins here!
1427
1428 #ifdef __cplusplus
1429 extern "C" {
1430 #endif
1431
1432 EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front)
1433 {
1434   VLOG("CALL ReadScreen2 ()\n");
1435   *width = settings.res_x;
1436   *height = settings.res_y;
1437   if (dest)
1438   {
1439     BYTE * line = (BYTE*)dest;
1440     if (!fullscreen)
1441     {
1442       for (wxUint32 y=0; y<settings.res_y; y++)
1443       {
1444         for (wxUint32 x=0; x<settings.res_x; x++)
1445         {
1446           line[x*3] = 0x20;
1447           line[x*3+1] = 0x7f;
1448           line[x*3+2] = 0x40;
1449         }
1450       }
1451       // LOG ("ReadScreen. not in the fullscreen!\n");
1452       WARNLOG("[Glide64] Cannot save screenshot in windowed mode?\n");
1453
1454       return;
1455     }
1456
1457   GrLfbInfo_t info;
1458   info.size = sizeof(GrLfbInfo_t);
1459   if (grLfbLock (GR_LFB_READ_ONLY,
1460     GR_BUFFER_FRONTBUFFER,
1461     GR_LFBWRITEMODE_888,
1462     GR_ORIGIN_UPPER_LEFT,
1463     FXFALSE,
1464     &info))
1465   {
1466     // Copy the screen, let's hope this works.
1467       for (wxUint32 y=0; y<settings.res_y; y++)
1468       {
1469         BYTE *ptr = (BYTE*) info.lfbPtr + (info.strideInBytes * y);
1470         for (wxUint32 x=0; x<settings.res_x; x++)
1471         {
1472           line[x*3]   = ptr[2];  // red
1473           line[x*3+1] = ptr[1];  // green
1474           line[x*3+2] = ptr[0];  // blue
1475           ptr += 4;
1476         }
1477         line += settings.res_x * 3;
1478       }
1479
1480       // Unlock the frontbuffer
1481       grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER);
1482     }
1483     VLOG ("ReadScreen. Success.\n");
1484   }
1485 }
1486
1487 EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
1488                                    void (*DebugCallback)(void *, int, const char *))
1489 {
1490   VLOG("CALL PluginStartup ()\n");
1491     l_DebugCallback = DebugCallback;
1492     l_DebugCallContext = Context;
1493
1494     /* attach and call the CoreGetAPIVersions function, check Config and Video Extension API versions for compatibility */
1495     ptr_CoreGetAPIVersions CoreAPIVersionFunc;
1496     CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) osal_dynlib_getproc(CoreLibHandle, "CoreGetAPIVersions");
1497     if (CoreAPIVersionFunc == NULL)
1498     {
1499         ERRLOG("Core emulator broken; no CoreAPIVersionFunc() function found.");
1500         return M64ERR_INCOMPATIBLE;
1501     }
1502     int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion;
1503     (*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL);
1504     if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000))
1505     {
1506         ERRLOG("Emulator core Config API incompatible with this plugin");
1507         return M64ERR_INCOMPATIBLE;
1508     }
1509     if ((VidextAPIVersion & 0xffff0000) != (VIDEXT_API_VERSION & 0xffff0000))
1510     {
1511         ERRLOG("Emulator core Video Extension API incompatible with this plugin");
1512         return M64ERR_INCOMPATIBLE;
1513     }
1514
1515     ConfigOpenSection = (ptr_ConfigOpenSection) osal_dynlib_getproc(CoreLibHandle, "ConfigOpenSection");
1516     ConfigSetParameter = (ptr_ConfigSetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigSetParameter");
1517     ConfigGetParameter = (ptr_ConfigGetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParameter");
1518     ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultInt");
1519     ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultFloat");
1520     ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultBool");
1521     ConfigSetDefaultString = (ptr_ConfigSetDefaultString) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultString");
1522     ConfigGetParamInt = (ptr_ConfigGetParamInt) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamInt");
1523     ConfigGetParamFloat = (ptr_ConfigGetParamFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamFloat");
1524     ConfigGetParamBool = (ptr_ConfigGetParamBool) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamBool");
1525     ConfigGetParamString = (ptr_ConfigGetParamString) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamString");
1526
1527     ConfigGetSharedDataFilepath = (ptr_ConfigGetSharedDataFilepath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetSharedDataFilepath");
1528     ConfigGetUserConfigPath = (ptr_ConfigGetUserConfigPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserConfigPath");
1529     ConfigGetUserDataPath = (ptr_ConfigGetUserDataPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserDataPath");
1530     ConfigGetUserCachePath = (ptr_ConfigGetUserCachePath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserCachePath");
1531
1532     if (!ConfigOpenSection   || !ConfigSetParameter    || !ConfigGetParameter ||
1533         !ConfigSetDefaultInt || !ConfigSetDefaultFloat || !ConfigSetDefaultBool || !ConfigSetDefaultString ||
1534         !ConfigGetParamInt   || !ConfigGetParamFloat   || !ConfigGetParamBool   || !ConfigGetParamString ||
1535         !ConfigGetSharedDataFilepath || !ConfigGetUserConfigPath || !ConfigGetUserDataPath || !ConfigGetUserCachePath)
1536     {
1537         ERRLOG("Couldn't connect to Core configuration functions");
1538         return M64ERR_INCOMPATIBLE;
1539     }
1540
1541     /* Get the core Video Extension function pointers from the library handle */
1542     CoreVideo_Init = (ptr_VidExt_Init) osal_dynlib_getproc(CoreLibHandle, "VidExt_Init");
1543     CoreVideo_Quit = (ptr_VidExt_Quit) osal_dynlib_getproc(CoreLibHandle, "VidExt_Quit");
1544     CoreVideo_ListFullscreenModes = (ptr_VidExt_ListFullscreenModes) osal_dynlib_getproc(CoreLibHandle, "VidExt_ListFullscreenModes");
1545     CoreVideo_SetVideoMode = (ptr_VidExt_SetVideoMode) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetVideoMode");
1546     CoreVideo_SetCaption = (ptr_VidExt_SetCaption) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetCaption");
1547     CoreVideo_ToggleFullScreen = (ptr_VidExt_ToggleFullScreen) osal_dynlib_getproc(CoreLibHandle, "VidExt_ToggleFullScreen");
1548     CoreVideo_ResizeWindow = (ptr_VidExt_ResizeWindow) osal_dynlib_getproc(CoreLibHandle, "VidExt_ResizeWindow");
1549     CoreVideo_GL_GetProcAddress = (ptr_VidExt_GL_GetProcAddress) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_GetProcAddress");
1550     CoreVideo_GL_SetAttribute = (ptr_VidExt_GL_SetAttribute) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SetAttribute");
1551     CoreVideo_GL_SwapBuffers = (ptr_VidExt_GL_SwapBuffers) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SwapBuffers");
1552
1553     if (!CoreVideo_Init || !CoreVideo_Quit || !CoreVideo_ListFullscreenModes || !CoreVideo_SetVideoMode ||
1554         !CoreVideo_SetCaption || !CoreVideo_ToggleFullScreen || !CoreVideo_ResizeWindow || !CoreVideo_GL_GetProcAddress ||
1555         !CoreVideo_GL_SetAttribute || !CoreVideo_GL_SwapBuffers)
1556     {
1557         ERRLOG("Couldn't connect to Core video functions");
1558         return M64ERR_INCOMPATIBLE;
1559     }
1560
1561     const char *configDir = ConfigGetSharedDataFilepath("Glide64mk2.ini");
1562     if (configDir)
1563     {
1564         SetConfigDir(configDir);
1565         ReadSettings();
1566                 return M64ERR_SUCCESS;
1567     }
1568     else
1569     {
1570         ERRLOG("Couldn't find Glide64mk2.ini");
1571         return M64ERR_FILES;
1572     }
1573 }
1574
1575 EXPORT m64p_error CALL PluginShutdown(void)
1576 {
1577   VLOG("CALL PluginShutdown ()\n");
1578     return M64ERR_SUCCESS;
1579 }
1580
1581 EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
1582 {
1583   VLOG("CALL PluginGetVersion ()\n");
1584     /* set version info */
1585     if (PluginType != NULL)
1586         *PluginType = M64PLUGIN_GFX;
1587
1588     if (PluginVersion != NULL)
1589         *PluginVersion = PLUGIN_VERSION;
1590
1591     if (APIVersion != NULL)
1592         *APIVersion = VIDEO_PLUGIN_API_VERSION;
1593
1594     if (PluginNamePtr != NULL)
1595         *PluginNamePtr = PLUGIN_NAME;
1596
1597     if (Capabilities != NULL)
1598     {
1599         *Capabilities = 0;
1600     }
1601
1602     return M64ERR_SUCCESS;
1603 }
1604
1605 /******************************************************************
1606 Function: CaptureScreen
1607 Purpose:  This function dumps the current frame to a file
1608 input:    pointer to the directory to save the file to
1609 output:   none
1610 *******************************************************************/
1611 EXPORT void CALL CaptureScreen ( char * Directory )
1612 {
1613   capture_screen = 1;
1614   strcpy (capture_path, Directory);
1615 }
1616
1617 /******************************************************************
1618 Function: ChangeWindow
1619 Purpose:  to change the window between fullscreen and window
1620 mode. If the window was in fullscreen this should
1621 change the screen to window mode and vice vesa.
1622 input:    none
1623 output:   none
1624 *******************************************************************/
1625 //#warning ChangeWindow unimplemented
1626 EXPORT void CALL ChangeWindow (void)
1627 {
1628   VLOG ("ChangeWindow()\n");
1629   #ifdef OLDAPI
1630   if (evoodoo)
1631   {
1632     if (!ev_fullscreen)
1633     {
1634       to_fullscreen = TRUE;
1635       ev_fullscreen = TRUE;
1636 #ifdef __WINDOWS__
1637       if (gfx.hStatusBar)
1638         ShowWindow( gfx.hStatusBar, SW_HIDE );
1639       ShowCursor( FALSE );
1640 #endif
1641     }
1642     else
1643     {
1644       ev_fullscreen = FALSE;
1645       InitGfx ();
1646 #ifdef __WINDOWS__
1647       ShowCursor( TRUE );
1648       if (gfx.hStatusBar)
1649         ShowWindow( gfx.hStatusBar, SW_SHOW );
1650       SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
1651 #endif
1652     }
1653   }
1654   else
1655   {
1656     // Go to fullscreen at next dlist
1657     // This is for compatibility with 1964, which reloads the plugin
1658     //  when switching to fullscreen
1659     if (!fullscreen)
1660     {
1661       to_fullscreen = TRUE;
1662 #ifdef __WINDOWS__
1663       if (gfx.hStatusBar)
1664         ShowWindow( gfx.hStatusBar, SW_HIDE );
1665       ShowCursor( FALSE );
1666 #endif
1667     }
1668     else
1669     {
1670       ReleaseGfx ();
1671 #ifdef __WINDOWS__
1672       ShowCursor( TRUE );
1673       if (gfx.hStatusBar)
1674         ShowWindow( gfx.hStatusBar, SW_SHOW );
1675       // SetWindowLong fixes the following Windows XP Banshee issues:
1676       // 1964 crash error when loading another rom.
1677       // All N64 emu's minimize, restore crashes.
1678       SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
1679 #endif
1680     }
1681   }
1682 #endif
1683 }
1684
1685 /******************************************************************
1686 Function: CloseDLL
1687 Purpose:  This function is called when the emulator is closing
1688 down allowing the dll to de-initialise.
1689 input:    none
1690 output:   none
1691 *******************************************************************/
1692 void CALL CloseDLL (void)
1693 {
1694   VLOG ("CloseDLL ()\n");
1695
1696   // re-set the old window proc
1697 #ifdef WINPROC_OVERRIDE
1698   SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
1699 #endif
1700
1701 #ifdef ALTTAB_FIX
1702   if (hhkLowLevelKybd)
1703   {
1704     UnhookWindowsHookEx(hhkLowLevelKybd);
1705     hhkLowLevelKybd = 0;
1706   }
1707 #endif
1708
1709   //CLOSELOG ();
1710
1711 #ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
1712   if (settings.ghq_use)
1713   {
1714     ext_ghq_shutdown();
1715     settings.ghq_use = 0;
1716   }
1717 #endif
1718   if (fullscreen)
1719     ReleaseGfx ();
1720   ZLUT_release();
1721   ClearCache ();
1722   delete[] voodoo.gamma_table_r;
1723   voodoo.gamma_table_r = 0;
1724   delete[] voodoo.gamma_table_g;
1725   voodoo.gamma_table_g = 0;
1726   delete[] voodoo.gamma_table_b;
1727   voodoo.gamma_table_b = 0;
1728 }
1729
1730 /******************************************************************
1731 Function: DllTest
1732 Purpose:  This function is optional function that is provided
1733 to allow the user to test the dll
1734 input:    a handle to the window that calls this function
1735 output:   none
1736 *******************************************************************/
1737 void CALL DllTest ( HWND hParent )
1738 {
1739 }
1740
1741 /******************************************************************
1742 Function: DrawScreen
1743 Purpose:  This function is called when the emulator receives a
1744 WM_PAINT message. This allows the gfx to fit in when
1745 it is being used in the desktop.
1746 input:    none
1747 output:   none
1748 *******************************************************************/
1749 void CALL DrawScreen (void)
1750 {
1751   VLOG ("DrawScreen ()\n");
1752 }
1753
1754 /******************************************************************
1755 Function: GetDllInfo
1756 Purpose:  This function allows the emulator to gather information
1757 about the dll by filling in the PluginInfo structure.
1758 input:    a pointer to a PLUGIN_INFO stucture that needs to be
1759 filled by the function. (see def above)
1760 output:   none
1761 *******************************************************************/
1762 void CALL GetDllInfo ( PLUGIN_INFO * PluginInfo )
1763 {
1764   VLOG ("GetDllInfo ()\n");
1765   PluginInfo->Version = 0x0103;     // Set to 0x0103
1766   PluginInfo->Type  = PLUGIN_TYPE_GFX;  // Set to PLUGIN_TYPE_GFX
1767   sprintf (PluginInfo->Name, "Glide64mk2 " G64_VERSION RELTIME);  // Name of the DLL
1768
1769   // If DLL supports memory these memory options then set them to TRUE or FALSE
1770   //  if it does not support it
1771   PluginInfo->NormalMemory = TRUE;  // a normal wxUint8 array
1772   PluginInfo->MemoryBswaped = TRUE; // a normal wxUint8 array where the memory has been pre
1773   // bswap on a dword (32 bits) boundry
1774 }
1775
1776 #ifndef WIN32
1777 BOOL WINAPI QueryPerformanceCounter(PLARGE_INTEGER counter)
1778 {
1779    struct timeval tv;
1780
1781    /* generic routine */
1782    gettimeofday( &tv, NULL );
1783    counter->QuadPart = (LONGLONG)tv.tv_usec + (LONGLONG)tv.tv_sec * 1000000;
1784    return TRUE;
1785 }
1786
1787 BOOL WINAPI QueryPerformanceFrequency(PLARGE_INTEGER frequency)
1788 {
1789    frequency->s.LowPart= 1000000;
1790    frequency->s.HighPart= 0;
1791    return TRUE;
1792 }
1793 #endif
1794
1795 /******************************************************************
1796 Function: InitiateGFX
1797 Purpose:  This function is called when the DLL is started to give
1798 information from the emulator that the n64 graphics
1799 uses. This is not called from the emulation thread.
1800 Input:    Gfx_Info is passed to this function which is defined
1801 above.
1802 Output:   TRUE on success
1803 FALSE on failure to initialise
1804
1805 ** note on interrupts **:
1806 To generate an interrupt set the appropriate bit in MI_INTR_REG
1807 and then call the function CheckInterrupts to tell the emulator
1808 that there is a waiting interrupt.
1809 *******************************************************************/
1810
1811 EXPORT int CALL InitiateGFX (GFX_INFO Gfx_Info)
1812 {
1813   VLOG ("InitiateGFX (*)\n");
1814   voodoo.num_tmu = 2;
1815
1816   // Assume scale of 1 for debug purposes
1817   rdp.scale_x = 1.0f;
1818   rdp.scale_y = 1.0f;
1819
1820   memset (&settings, 0, sizeof(SETTINGS));
1821   ReadSettings ();
1822   char name[21] = "DEFAULT";
1823   ReadSpecialSettings (name);
1824   settings.res_data_org = settings.res_data;
1825 #ifdef FPS
1826   QueryPerformanceFrequency (&perf_freq);
1827   QueryPerformanceCounter (&fps_last);
1828 #endif
1829
1830   debug_init ();    // Initialize debugger
1831
1832   gfx = Gfx_Info;
1833
1834 #ifdef WINPROC_OVERRIDE
1835   // [H.Morii] inject our own winproc so that "alt-enter to fullscreen"
1836   // message is shown when the emulator window is activated.
1837   WNDPROC curWndProc = (WNDPROC)GetWindowLong(gfx.hWnd, GWL_WNDPROC);
1838   if (curWndProc && curWndProc != (WNDPROC)WndProc) {
1839     oldWndProc = (WNDPROC)SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)WndProc);
1840   }
1841 #endif
1842
1843   util_init ();
1844   math_init ();
1845   TexCacheInit ();
1846   CRC_BuildTable();
1847   CountCombine();
1848   if (fb_depth_render_enabled)
1849     ZLUT_init();
1850
1851   char strConfigWrapperExt[] = "grConfigWrapperExt";
1852   GRCONFIGWRAPPEREXT grConfigWrapperExt = (GRCONFIGWRAPPEREXT)grGetProcAddress(strConfigWrapperExt);
1853   if (grConfigWrapperExt)
1854     grConfigWrapperExt(settings.wrpResolution, settings.wrpVRAM * 1024 * 1024, settings.wrpFBO, settings.wrpAnisotropic);
1855
1856   grGlideInit ();
1857   grSstSelect (0);
1858   const char *extensions = grGetString (GR_EXTENSION);
1859   grGlideShutdown ();
1860   if (strstr (extensions, "EVOODOO"))
1861   {
1862     evoodoo = 1;
1863     voodoo.has_2mb_tex_boundary = 0;
1864   }
1865   else {
1866     evoodoo = 0;
1867     voodoo.has_2mb_tex_boundary = 1;
1868   }
1869
1870   return TRUE;
1871 }
1872
1873 /******************************************************************
1874 Function: MoveScreen
1875 Purpose:  This function is called in response to the emulator
1876 receiving a WM_MOVE passing the xpos and ypos passed
1877 from that message.
1878 input:    xpos - the x-coordinate of the upper-left corner of the
1879 client area of the window.
1880 ypos - y-coordinate of the upper-left corner of the
1881 client area of the window.
1882 output:   none
1883 *******************************************************************/
1884 EXPORT void CALL MoveScreen (int xpos, int ypos)
1885 {
1886   rdp.window_changed = TRUE;
1887 }
1888
1889 /******************************************************************
1890 Function: ResizeVideoOutput
1891 Purpose:  This function is called to force us to resize our output OpenGL window.
1892           This is currently unsupported, and should never be called because we do
1893           not pass the RESIZABLE flag to VidExt_SetVideoMode when initializing.
1894 input:    new width and height
1895 output:   none
1896 *******************************************************************/
1897 EXPORT void CALL ResizeVideoOutput(int Width, int Height)
1898 {
1899 }
1900
1901 /******************************************************************
1902 Function: RomClosed
1903 Purpose:  This function is called when a rom is closed.
1904 input:    none
1905 output:   none
1906 *******************************************************************/
1907 EXPORT void CALL RomClosed (void)
1908 {
1909   VLOG ("RomClosed ()\n");
1910 printf("RomClosed ()\n");
1911
1912   CLOSE_RDP_LOG ();
1913   CLOSE_RDP_E_LOG ();
1914   rdp.window_changed = TRUE;
1915   romopen = FALSE;
1916 //  if (fullscreen && evoodoo)//*SEB*
1917     ReleaseGfx ();
1918 }
1919
1920 static void CheckDRAMSize()
1921 {
1922   wxUint32 test;
1923   GLIDE64_TRY
1924   {
1925     test = gfx.RDRAM[0x007FFFFF] + 1;
1926   }
1927   GLIDE64_CATCH
1928   {
1929     test = 0;
1930   }
1931   if (test)
1932     BMASK = 0x7FFFFF;
1933   else
1934     BMASK = WMASK;
1935 #ifdef LOGGING
1936   sprintf (out_buf, "Detected RDRAM size: %08lx\n", BMASK);
1937   LOG (out_buf);
1938 #endif
1939 }
1940
1941 /******************************************************************
1942 Function: RomOpen
1943 Purpose:  This function is called when a rom is open. (from the
1944 emulation thread)
1945 input:    none
1946 output:   none
1947 *******************************************************************/
1948 EXPORT int CALL RomOpen (void)
1949 {
1950   VLOG ("RomOpen ()\n");
1951   no_dlist = true;
1952   romopen = TRUE;
1953   ucode_error_report = TRUE;    // allowed to report ucode errors
1954   rdp_reset ();
1955
1956   // Get the country code & translate to NTSC(0) or PAL(1)
1957   wxUint16 code = ((wxUint16*)gfx.HEADER)[0x1F^1];
1958
1959   if (code == 0x4400) region = 1; // Germany (PAL)
1960   if (code == 0x4500) region = 0; // USA (NTSC)
1961   if (code == 0x4A00) region = 0; // Japan (NTSC)
1962   if (code == 0x5000) region = 1; // Europe (PAL)
1963   if (code == 0x5500) region = 0; // Australia (NTSC)
1964
1965 #ifdef PAULSCODE
1966   frameSkipper.setTargetFPS(region == 1 ? 50 : 60);
1967 #endif
1968
1969   char name[21] = "DEFAULT";
1970   ReadSpecialSettings (name);
1971
1972   // get the name of the ROM
1973   for (int i=0; i<20; i++)
1974     name[i] = gfx.HEADER[(32+i)^3];
1975   name[20] = 0;
1976
1977   // remove all trailing spaces
1978   while (name[strlen(name)-1] == ' ')
1979     name[strlen(name)-1] = 0;
1980
1981   strncpy(rdp.RomName, name, sizeof(name));
1982   ReadSpecialSettings (name);
1983   ClearCache ();
1984
1985   CheckDRAMSize();
1986
1987   OPEN_RDP_LOG ();
1988   OPEN_RDP_E_LOG ();
1989
1990
1991   // ** EVOODOO EXTENSIONS **
1992   if (!fullscreen)
1993   {
1994     grGlideInit ();
1995     grSstSelect (0);
1996   }
1997   const char *extensions = grGetString (GR_EXTENSION);
1998   if (!fullscreen)
1999   {
2000     grGlideShutdown ();
2001
2002     if (strstr (extensions, "EVOODOO"))
2003       evoodoo = 1;
2004     else
2005       evoodoo = 0;
2006
2007     if (evoodoo)
2008       InitGfx ();
2009   }
2010
2011   if (strstr (extensions, "ROMNAME"))
2012   {
2013     char strSetRomName[] = "grSetRomName";
2014     void (FX_CALL *grSetRomName)(char*);
2015     grSetRomName = (void (FX_CALL *)(char*))grGetProcAddress (strSetRomName);
2016     grSetRomName (name);
2017   }
2018   // **
2019   return true;
2020 }
2021
2022 EXPORT void CALL RomResumed(void)
2023 {
2024 #ifdef PAULSCODE
2025   frameSkipper.start();
2026 #endif
2027 }
2028
2029 /******************************************************************
2030 Function: ShowCFB
2031 Purpose:  Useally once Dlists are started being displayed, cfb is
2032 ignored. This function tells the dll to start displaying
2033 them again.
2034 input:    none
2035 output:   none
2036 *******************************************************************/
2037 bool no_dlist = true;
2038 EXPORT void CALL ShowCFB (void)
2039 {
2040   no_dlist = true;
2041   VLOG ("ShowCFB ()\n");
2042 }
2043
2044 EXPORT void CALL SetRenderingCallback(void (*callback)(int))
2045 {
2046   VLOG("CALL SetRenderingCallback (*)\n");
2047     renderCallback = callback;
2048 }
2049
2050 void drawViRegBG()
2051 {
2052   LRDP("drawViRegBG\n");
2053   const wxUint32 VIwidth = *gfx.VI_WIDTH_REG;
2054   FB_TO_SCREEN_INFO fb_info;
2055   fb_info.width  = VIwidth;
2056   fb_info.height = (wxUint32)rdp.vi_height;
2057   if (fb_info.height == 0)
2058   {
2059     LRDP("Image height = 0 - skipping\n");
2060     return;
2061   }
2062   fb_info.ul_x = 0;
2063
2064   fb_info.lr_x = VIwidth - 1;
2065   //  fb_info.lr_x = (wxUint32)rdp.vi_width - 1;
2066   fb_info.ul_y = 0;
2067   fb_info.lr_y = fb_info.height - 1;
2068   fb_info.opaque = 1;
2069   fb_info.addr = *gfx.VI_ORIGIN_REG;
2070   fb_info.size = *gfx.VI_STATUS_REG & 3;
2071   rdp.last_bg = fb_info.addr;
2072
2073   bool drawn = DrawFrameBufferToScreen(fb_info);
2074   if (settings.hacks&hack_Lego && drawn)
2075   {
2076     rdp.updatescreen = 1;
2077     newSwapBuffers ();
2078     DrawFrameBufferToScreen(fb_info);
2079   }
2080 }
2081
2082 }
2083
2084 void drawNoFullscreenMessage();
2085
2086 void DrawFrameBuffer ()
2087 {
2088   if (!fullscreen)
2089   {
2090     drawNoFullscreenMessage();
2091   }
2092   if (to_fullscreen)
2093     GoToFullScreen();
2094
2095   if (fullscreen)
2096   {
2097     grDepthMask (FXTRUE);
2098     grColorMask (FXTRUE, FXTRUE);
2099     grBufferClear (0, 0, 0xFFFF);
2100     drawViRegBG();
2101   }
2102 }
2103
2104 extern "C" {
2105 /******************************************************************
2106 Function: UpdateScreen
2107 Purpose:  This function is called in response to a vsync of the
2108 screen were the VI bit in MI_INTR_REG has already been
2109 set
2110 input:    none
2111 output:   none
2112 *******************************************************************/
2113 wxUint32 update_screen_count = 0;
2114 EXPORT void CALL UpdateScreen (void)
2115 {
2116 #ifdef PAULSCODE
2117 //printf("UpdateScreen()\n");
2118   frameSkipper.update();
2119 #endif
2120 #ifdef LOG_KEY
2121   if (CheckKeyPressed(G64_VK_SPACE, 0x0001))
2122   {
2123     LOG ("KEY!!!\n");
2124   }
2125 #endif
2126   char out_buf[128];
2127   sprintf (out_buf, "UpdateScreen (). Origin: %08x, Old origin: %08x, width: %d\n", *gfx.VI_ORIGIN_REG, rdp.vi_org_reg, *gfx.VI_WIDTH_REG);
2128   VLOG (out_buf);
2129   LRDP(out_buf);
2130
2131   wxUint32 width = (*gfx.VI_WIDTH_REG) << 1;
2132   if (fullscreen && (*gfx.VI_ORIGIN_REG  > width))
2133     update_screen_count++;
2134 //TODO-PORT: wx times
2135 #ifdef FPS
2136   // vertical interrupt has occurred, increment counter
2137   vi_count ++;
2138
2139   // Check frames per second
2140   LARGE_INTEGER difference;
2141   QueryPerformanceCounter (&fps_next);
2142   difference.QuadPart = fps_next.QuadPart - fps_last.QuadPart;
2143   float diff_secs = (float)((double)difference.QuadPart / (double)perf_freq.QuadPart);
2144   if (diff_secs > 0.5f)
2145   {
2146     fps = (float)(fps_count / diff_secs);
2147     vi = (float)(vi_count / diff_secs);
2148     ntsc_percent = vi / 0.6f;
2149     pal_percent = vi / 0.5f;
2150     fps_last = fps_next;
2151     fps_count = 0;
2152     vi_count = 0;
2153   }
2154 #endif
2155   //*
2156   wxUint32 limit = (settings.hacks&hack_Lego) ? 15 : 30;
2157 #ifdef PAULSCODE0
2158   if (frameSkipper.willSkipNext())
2159         return;
2160 #endif
2161 #ifdef PAULSCODE
2162 //  if (!frameSkipper.hasSkipped())
2163   if (!frameSkipper.willSkipNext())
2164 #endif
2165   if ((settings.frame_buffer&fb_cpu_write_hack) && (update_screen_count > limit) && (rdp.last_bg == 0))
2166   {
2167     LRDP("DirectCPUWrite hack!\n");
2168     update_screen_count = 0;
2169     no_dlist = true;
2170     ClearCache ();
2171     UpdateScreen();
2172     return;
2173   }
2174   //*/
2175   //*
2176   if( no_dlist )
2177   {
2178     if( *gfx.VI_ORIGIN_REG  > width )
2179     {
2180       ChangeSize ();
2181       LRDP("ChangeSize done\n");
2182 #ifdef PAULSCODE
2183           if (!frameSkipper.willSkipNext())
2184 #endif
2185       DrawFrameBuffer();
2186       LRDP("DrawFrameBuffer done\n");
2187       rdp.updatescreen = 1;
2188       newSwapBuffers ();
2189     }
2190     return;
2191   }
2192   //*/
2193 #ifdef PAULSCODE0
2194   if (!frameSkipper.willSkipNext())
2195 #endif
2196   if (settings.swapmode == 0)
2197     newSwapBuffers ();
2198 }
2199
2200 static void DrawWholeFrameBufferToScreen()
2201 {
2202   static wxUint32 toScreenCI = 0;
2203   if (rdp.ci_width < 200)
2204     return;
2205   if (rdp.cimg == toScreenCI)
2206     return;
2207   toScreenCI = rdp.cimg;
2208   FB_TO_SCREEN_INFO fb_info;
2209   fb_info.addr   = rdp.cimg;
2210   fb_info.size   = rdp.ci_size;
2211   fb_info.width  = rdp.ci_width;
2212   fb_info.height = rdp.ci_height;
2213   if (fb_info.height == 0)
2214     return;
2215   fb_info.ul_x = 0;
2216   fb_info.lr_x = rdp.ci_width-1;
2217   fb_info.ul_y = 0;
2218   fb_info.lr_y = rdp.ci_height-1;
2219   fb_info.opaque = 0;
2220   DrawFrameBufferToScreen(fb_info);
2221   if (!(settings.frame_buffer & fb_ref))
2222     memset(gfx.RDRAM+rdp.cimg, 0, (rdp.ci_width*rdp.ci_height)<<rdp.ci_size>>1);
2223 }
2224
2225 static void GetGammaTable()
2226 {
2227   char strGetGammaTableExt[] = "grGetGammaTableExt";
2228   void (FX_CALL *grGetGammaTableExt)(FxU32, FxU32*, FxU32*, FxU32*) =
2229     (void (FX_CALL *)(FxU32, FxU32*, FxU32*, FxU32*))grGetProcAddress(strGetGammaTableExt);
2230   if (grGetGammaTableExt)
2231   {
2232     voodoo.gamma_table_r = new FxU32[voodoo.gamma_table_size];
2233     voodoo.gamma_table_g = new FxU32[voodoo.gamma_table_size];
2234     voodoo.gamma_table_b = new FxU32[voodoo.gamma_table_size];
2235     grGetGammaTableExt(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b);
2236   }
2237 }
2238
2239 }
2240 wxUint32 curframe = 0;
2241 void newSwapBuffers()
2242 {
2243 #ifdef PAULSCODE
2244 //frameSkipper.newFrame();
2245 //bool skipped = false;
2246 //printf("newSwapBuffers()\n");
2247 bool skipped = frameSkipper.willSkipNext();
2248 //bool skipped = frameSkipper.hasSkipped();
2249 #endif
2250   if (!rdp.updatescreen) {
2251 #ifdef PAULSCODE0
2252     if (skipped) {
2253       if (settings.frame_buffer & fb_read_back_to_screen2)
2254         DrawWholeFrameBufferToScreen();
2255       frameSkipper.newFrame();
2256     }
2257 #endif
2258     return;
2259   }
2260
2261   rdp.updatescreen = 0;
2262
2263   LRDP("swapped\n");
2264
2265   // Allow access to the whole screen
2266   if (fullscreen)
2267   {
2268     rdp.update |= UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE;
2269     grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y);
2270     grDepthBufferFunction (GR_CMP_ALWAYS);
2271     grDepthMask (FXFALSE);
2272     grCullMode (GR_CULL_DISABLE);
2273
2274     if ((settings.show_fps & 0xF) || settings.clock)
2275       set_message_combiner ();
2276 #ifdef FPS
2277     float y = (float)settings.res_y;
2278     if (settings.show_fps & 0x0F)
2279     {
2280       if (settings.show_fps & 4)
2281       {
2282         if (region)   // PAL
2283           output (0, y, 0, "%d%% ", (int)pal_percent);
2284         else
2285           output (0, y, 0, "%d%% ", (int)ntsc_percent);
2286         y -= 16;
2287       }
2288       if (settings.show_fps & 2)
2289       {
2290         output (0, y, 0, "VI/s: %.02f ", vi);
2291         y -= 16;
2292       }
2293       if (settings.show_fps & 1)
2294         output (0, y, 0, "FPS: %.02f ", fps);
2295     }
2296 #endif
2297
2298     if (settings.clock)
2299     {
2300       if (settings.clock_24_hr)
2301       {
2302           time_t ltime;
2303           time (&ltime);
2304           tm *cur_time = localtime (&ltime);
2305
2306           sprintf (out_buf, "%.2d:%.2d:%.2d", cur_time->tm_hour, cur_time->tm_min, cur_time->tm_sec);
2307       }
2308       else
2309       {
2310           char ampm[] = "AM";
2311           time_t ltime;
2312
2313           time (&ltime);
2314           tm *cur_time = localtime (&ltime);
2315
2316           if (cur_time->tm_hour >= 12)
2317           {
2318             strcpy (ampm, "PM");
2319             if (cur_time->tm_hour != 12)
2320               cur_time->tm_hour -= 12;
2321           }
2322           if (cur_time->tm_hour == 0)
2323             cur_time->tm_hour = 12;
2324
2325           if (cur_time->tm_hour >= 10)
2326             sprintf (out_buf, "%.5s %s", asctime(cur_time) + 11, ampm);
2327           else
2328             sprintf (out_buf, " %.4s %s", asctime(cur_time) + 12, ampm);
2329         }
2330         output ((float)(settings.res_x - 68), y, 0, out_buf, 0);
2331       }
2332     //hotkeys
2333     if (CheckKeyPressed(G64_VK_BACK, 0x0001))
2334     {
2335       hotkey_info.hk_filtering = 100;
2336       if (settings.filtering < 2)
2337         settings.filtering++;
2338       else
2339         settings.filtering = 0;
2340     }
2341     if ((abs((int)(frame_count - curframe)) > 3 ) && CheckKeyPressed(G64_VK_ALT, 0x8000))  //alt +
2342     {
2343       if (CheckKeyPressed(G64_VK_B, 0x8000))  //b
2344       {
2345         hotkey_info.hk_motionblur = 100;
2346         hotkey_info.hk_ref = 0;
2347         curframe = frame_count;
2348         settings.frame_buffer ^= fb_motionblur;
2349       }
2350       else if (CheckKeyPressed(G64_VK_V, 0x8000))  //v
2351       {
2352         hotkey_info.hk_ref = 100;
2353         hotkey_info.hk_motionblur = 0;
2354         curframe = frame_count;
2355         settings.frame_buffer ^= fb_ref;
2356       }
2357     }
2358     if (settings.buff_clear && (hotkey_info.hk_ref || hotkey_info.hk_motionblur || hotkey_info.hk_filtering))
2359     {
2360       set_message_combiner ();
2361       char buf[256];
2362       buf[0] = 0;
2363       char * message = 0;
2364       if (hotkey_info.hk_ref)
2365       {
2366         if (settings.frame_buffer & fb_ref)
2367           message = strcat(buf, "FB READ ALWAYS: ON");
2368         else
2369           message = strcat(buf, "FB READ ALWAYS: OFF");
2370         hotkey_info.hk_ref--;
2371       }
2372       if (hotkey_info.hk_motionblur)
2373       {
2374         if (settings.frame_buffer & fb_motionblur)
2375           message = strcat(buf, "  MOTION BLUR: ON");
2376         else
2377           message = strcat(buf, "  MOTION BLUR: OFF");
2378         hotkey_info.hk_motionblur--;
2379       }
2380       if (hotkey_info.hk_filtering)
2381       {
2382         switch (settings.filtering)
2383         {
2384         case 0:
2385           message = strcat(buf, "  FILTERING MODE: AUTOMATIC");
2386           break;
2387         case 1:
2388           message = strcat(buf, "  FILTERING MODE: FORCE BILINEAR");
2389           break;
2390         case 2:
2391           message = strcat(buf, "  FILTERING MODE: FORCE POINT-SAMPLED");
2392           break;
2393         }
2394         hotkey_info.hk_filtering--;
2395       }
2396       output (120.0f, (float)settings.res_y, 0, message, 0);
2397     }
2398   }
2399     #ifdef OLDAPI
2400   if (capture_screen)
2401   {
2402     //char path[256];
2403     // Make the directory if it doesn't exist
2404     if (!wxDirExists(capture_path))
2405       wxMkdir(capture_path);
2406     wxString path;
2407     wxString romName = rdp.RomName;
2408     romName.Replace(wxT(" "), wxT("_"), true);
2409     romName.Replace(wxT(":"), wxT(";"), true);
2410
2411     for (int i=1; ; i++)
2412     {
2413       path = capture_path;
2414       path += wxT("Glide64mk2_");
2415       path += romName;
2416       path += wxT("_");
2417       if (i < 10)
2418         path += wxT("0");
2419       path << i << wxT(".") << ScreenShotFormats[settings.ssformat].extension;
2420       if (!wxFileName::FileExists(path))
2421         break;
2422     }
2423
2424     const wxUint32 offset_x = (wxUint32)rdp.offset_x;
2425     const wxUint32 offset_y = (wxUint32)rdp.offset_y;
2426     const wxUint32 image_width = settings.scr_res_x - offset_x*2;
2427     const wxUint32 image_height = settings.scr_res_y - offset_y*2;
2428
2429     GrLfbInfo_t info;
2430     info.size = sizeof(GrLfbInfo_t);
2431     if (grLfbLock (GR_LFB_READ_ONLY,
2432       GR_BUFFER_BACKBUFFER,
2433       GR_LFBWRITEMODE_565,
2434       GR_ORIGIN_UPPER_LEFT,
2435       FXFALSE,
2436       &info))
2437     {
2438       wxUint8 *ssimg = (wxUint8*)malloc(image_width * image_height * 3); // will be free in wxImage destructor
2439       int sspos = 0;
2440       wxUint32 offset_src = info.strideInBytes * offset_y;
2441
2442       // Copy the screen
2443       if (info.writeMode == GR_LFBWRITEMODE_8888)
2444       {
2445         wxUint32 col;
2446         for (wxUint32 y = 0; y < image_height; y++)
2447         {
2448           wxUint32 *ptr = (wxUint32*)((wxUint8*)info.lfbPtr + offset_src);
2449           ptr += offset_x;
2450           for (wxUint32 x = 0; x < image_width; x++)
2451           {
2452             col = *(ptr++);
2453             ssimg[sspos++] = (wxUint8)((col >> 16) & 0xFF);
2454             ssimg[sspos++] = (wxUint8)((col >> 8) & 0xFF);
2455             ssimg[sspos++] = (wxUint8)(col & 0xFF);
2456           }
2457           offset_src += info.strideInBytes;
2458         }
2459       }
2460       else
2461       {
2462         wxUint16 col;
2463         for (wxUint32 y = 0; y < image_height; y++)
2464         {
2465           wxUint16 *ptr = (wxUint16*)((wxUint8*)info.lfbPtr + offset_src);
2466           ptr += offset_x;
2467           for (wxUint32 x = 0; x < image_width; x++)
2468           {
2469             col = *(ptr++);
2470             ssimg[sspos++] = (wxUint8)((float)(col >> 11) / 31.0f * 255.0f);
2471             ssimg[sspos++] = (wxUint8)((float)((col >> 5) & 0x3F) / 63.0f * 255.0f);
2472             ssimg[sspos++] = (wxUint8)((float)(col & 0x1F) / 31.0f * 255.0f);
2473           }
2474           offset_src += info.strideInBytes;
2475         }
2476       }
2477       // Unlock the backbuffer
2478       grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER);
2479       wxImage screenshot(image_width, image_height, ssimg);
2480       screenshot.SaveFile(path, ScreenShotFormats[settings.ssformat].type);
2481       capture_screen = 0;
2482     }
2483   }
2484     #endif
2485
2486   // Capture the screen if debug capture is set
2487   if (_debugger.capture)
2488   {
2489     // Allocate the screen
2490     _debugger.screen = new wxUint8 [(settings.res_x*settings.res_y) << 1];
2491
2492     // Lock the backbuffer (already rendered)
2493     GrLfbInfo_t info;
2494     info.size = sizeof(GrLfbInfo_t);
2495     while (!grLfbLock (GR_LFB_READ_ONLY,
2496       GR_BUFFER_BACKBUFFER,
2497       GR_LFBWRITEMODE_565,
2498       GR_ORIGIN_UPPER_LEFT,
2499       FXFALSE,
2500       &info));
2501
2502     wxUint32 offset_src=0, offset_dst=0;
2503
2504     // Copy the screen
2505     for (wxUint32 y=0; y<settings.res_y; y++)
2506     {
2507       if (info.writeMode == GR_LFBWRITEMODE_8888)
2508       {
2509         wxUint32 *src = (wxUint32*)((wxUint8*)info.lfbPtr + offset_src);
2510         wxUint16 *dst = (wxUint16*)(_debugger.screen + offset_dst);
2511         wxUint8 r, g, b;
2512         wxUint32 col;
2513         for (unsigned int x = 0; x < settings.res_x; x++)
2514         {
2515           col = src[x];
2516           r = (wxUint8)((col >> 19) & 0x1F);
2517           g = (wxUint8)((col >> 10) & 0x3F);
2518           b = (wxUint8)((col >> 3)  & 0x1F);
2519           dst[x] = (r<<11)|(g<<5)|b;
2520         }
2521       }
2522       else
2523       {
2524         memcpy (_debugger.screen + offset_dst, (wxUint8*)info.lfbPtr + offset_src, settings.res_x << 1);
2525       }
2526       offset_dst += settings.res_x << 1;
2527       offset_src += info.strideInBytes;
2528     }
2529
2530     // Unlock the backbuffer
2531     grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER);
2532   }
2533
2534   if (fullscreen && debugging)
2535   {
2536     debug_keys ();
2537     debug_cacheviewer ();
2538     debug_mouse ();
2539   }
2540
2541 #ifdef PAULSCODE
2542   if (!skipped)
2543 #endif
2544   if (settings.frame_buffer & fb_read_back_to_screen)
2545     DrawWholeFrameBufferToScreen();
2546
2547   if (fullscreen)
2548   {
2549     if (fb_hwfbe_enabled && !(settings.hacks&hack_RE2) && !evoodoo)
2550       grAuxBufferExt( GR_BUFFER_AUXBUFFER );
2551 #ifdef PAULSCODE
2552         if (skipped)
2553         {
2554                 vbo_resetcount();
2555         } 
2556         else
2557 #endif
2558         {
2559                 grBufferSwap (settings.vsync);
2560                 fps_count ++;
2561         }
2562 #ifdef PAULSCODE
2563     if (!skipped)
2564 #endif
2565     if (*gfx.VI_STATUS_REG&0x08) //gamma correction is used
2566     {
2567       if (!voodoo.gamma_correction)
2568       {
2569         if (voodoo.gamma_table_size && !voodoo.gamma_table_r)
2570           GetGammaTable(); //save initial gamma tables
2571         guGammaCorrectionRGB(2.0f, 2.0f, 2.0f); //with gamma=2.0 gamma table is the same, as in N64
2572         voodoo.gamma_correction = 1;
2573       }
2574     }
2575     else
2576     {
2577       if (voodoo.gamma_correction)
2578       {
2579         if (voodoo.gamma_table_r)
2580           grLoadGammaTable(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b);
2581         else
2582           guGammaCorrectionRGB(1.3f, 1.3f, 1.3f); //1.3f is default 3dfx gamma for everything but desktop
2583         voodoo.gamma_correction = 0;
2584       }
2585     }
2586   }
2587
2588   if (_debugger.capture)
2589     debug_capture ();
2590
2591   if (fullscreen)
2592   {
2593 #ifdef PAULSCODE0
2594     if (!skipped)
2595 #endif
2596     if  (debugging || settings.wireframe || settings.buff_clear || (settings.hacks&hack_PPL && settings.ucode == 6))
2597     {
2598       if (settings.hacks&hack_RE2 && fb_depth_render_enabled)
2599         grDepthMask (FXFALSE);
2600       else
2601         grDepthMask (FXTRUE);
2602       grBufferClear (0, 0, 0xFFFF);
2603     }
2604     /* //let the game to clear the buffers
2605     else
2606     {
2607     grDepthMask (FXTRUE);
2608     grColorMask (FXFALSE, FXFALSE);
2609     grBufferClear (0, 0, 0xFFFF);
2610     grColorMask (FXTRUE, FXTRUE);
2611     }
2612     */
2613   }
2614
2615 #ifdef PAULSCODE
2616   if (!skipped)
2617 #endif
2618   if (settings.frame_buffer & fb_read_back_to_screen2)
2619     DrawWholeFrameBufferToScreen();
2620
2621   frame_count ++;
2622 #ifdef PAULSCODE
2623         frameSkipper.newFrame();
2624 #endif
2625
2626   // Open/close debugger?
2627   if (CheckKeyPressed(G64_VK_SCROLL, 0x0001))
2628   {
2629     if (!debugging)
2630     {
2631       //if (settings.scr_res_x == 1024 && settings.scr_res_y == 768)
2632       {
2633         debugging = 1;
2634
2635         // Recalculate screen size, don't resize screen
2636         settings.res_x = (wxUint32)(settings.scr_res_x * 0.625f);
2637         settings.res_y = (wxUint32)(settings.scr_res_y * 0.625f);
2638
2639         ChangeSize ();
2640       }
2641     } 
2642     else
2643     {
2644       debugging = 0;
2645
2646       settings.res_x = settings.scr_res_x;
2647       settings.res_y = settings.scr_res_y;
2648
2649       ChangeSize ();
2650     }
2651   }
2652
2653   // Debug capture?
2654   if (/*fullscreen && */debugging && CheckKeyPressed(G64_VK_INSERT, 0x0001))
2655   {
2656     _debugger.capture = 1;
2657   }
2658 }
2659
2660 extern "C"
2661 {
2662
2663 /******************************************************************
2664 Function: ViStatusChanged
2665 Purpose:  This function is called to notify the dll that the
2666 ViStatus registers value has been changed.
2667 input:    none
2668 output:   none
2669 *******************************************************************/
2670 EXPORT void CALL ViStatusChanged (void)
2671 {
2672 }
2673
2674 /******************************************************************
2675 Function: ViWidthChanged
2676 Purpose:  This function is called to notify the dll that the
2677 ViWidth registers value has been changed.
2678 input:    none
2679 output:   none
2680 *******************************************************************/
2681 EXPORT void CALL ViWidthChanged (void)
2682 {
2683 }
2684
2685 #ifdef WINPROC_OVERRIDE
2686 LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2687 {
2688   switch (msg)
2689   {
2690   case WM_ACTIVATEAPP:
2691     if (wParam == TRUE && !fullscreen) rdp.window_changed = TRUE;
2692     break;
2693   case WM_PAINT:
2694     if (!fullscreen) rdp.window_changed = TRUE;
2695     break;
2696
2697     /*    case WM_DESTROY:
2698     SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
2699     break;*/
2700   }
2701
2702   return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam);
2703 }
2704 #endif
2705
2706 }
2707
2708 int CheckKeyPressed(int key, int mask)
2709 {
2710 static Glide64Keys g64Keys;
2711   if (settings.use_hotkeys == 0)
2712     return 0;
2713 #ifdef __WINDOWS__
2714   return (GetAsyncKeyState(g64Keys[key]) & mask);
2715 #else
2716   if (grKeyPressed)
2717     return grKeyPressed(g64Keys[key]);
2718 #endif
2719   return 0;
2720 }
2721
2722
2723 #ifdef ALTTAB_FIX
2724 int k_ctl=0, k_alt=0, k_del=0;
2725
2726 LRESULT CALLBACK LowLevelKeyboardProc(int nCode,
2727                                       WPARAM wParam, LPARAM lParam)
2728 {
2729   if (!fullscreen) return CallNextHookEx(NULL, nCode, wParam, lParam);
2730
2731   int TabKey = FALSE;
2732
2733   PKBDLLHOOKSTRUCT p;
2734
2735   if (nCode == HC_ACTION)
2736   {
2737     switch (wParam) {
2738 case WM_KEYUP:    case WM_SYSKEYUP:
2739   p = (PKBDLLHOOKSTRUCT) lParam;
2740   if (p->vkCode == 162) k_ctl = 0;
2741   if (p->vkCode == 164) k_alt = 0;
2742   if (p->vkCode == 46) k_del = 0;
2743   goto do_it;
2744
2745 case WM_KEYDOWN:  case WM_SYSKEYDOWN:
2746   p = (PKBDLLHOOKSTRUCT) lParam;
2747   if (p->vkCode == 162) k_ctl = 1;
2748   if (p->vkCode == 164) k_alt = 1;
2749   if (p->vkCode == 46) k_del = 1;
2750   goto do_it;
2751
2752 do_it:
2753   TabKey =
2754     ((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
2755     ((p->vkCode == VK_ESCAPE) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
2756     ((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) & 0x8000) != 0)) ||
2757     (k_ctl && k_alt && k_del);
2758
2759   break;
2760     }
2761   }
2762
2763   if (TabKey)
2764   {
2765     k_ctl = 0;
2766     k_alt = 0;
2767     k_del = 0;
2768     ReleaseGfx ();
2769   }
2770
2771   return CallNextHookEx(NULL, nCode, wParam, lParam);
2772 }
2773 #endif
2774
2775 //
2776 // DllMain - called when the DLL is loaded, use this to get the DLL's instance
2777 //
2778 #ifdef OLDAPI
2779 class wxDLLApp : public wxApp
2780 {
2781 public:
2782   virtual bool OnInit();
2783 };
2784
2785 IMPLEMENT_APP_NO_MAIN(wxDLLApp)
2786
2787 bool wxDLLApp::OnInit()
2788 {
2789 /*  if (mutexProcessDList == NULL)
2790     mutexProcessDList = new wxMutex(wxMUTEX_DEFAULT);*/
2791   wxImage::AddHandler(new wxPNGHandler);
2792   wxImage::AddHandler(new wxJPEGHandler);
2793   return true;
2794 }
2795
2796 #ifndef __WINDOWS__
2797 int __attribute__ ((constructor)) DllLoad(void);
2798 int __attribute__ ((destructor)) DllUnload(void);
2799 #endif
2800
2801 // Called when the library is loaded and before dlopen() returns
2802 int DllLoad(void)
2803 {
2804     int argc = 0;
2805     char **argv = NULL;
2806     wxEntryStart(argc, argv);
2807     if (wxTheApp)
2808       return wxTheApp->CallOnInit() ? TRUE : FALSE;
2809     return 0;
2810 }
2811
2812 // Called when the library is unloaded and before dlclose() returns
2813 int DllUnload(void)
2814 {
2815     if ( wxTheApp )
2816       wxTheApp->OnExit();
2817     wxEntryCleanup();
2818     return TRUE;
2819 }
2820
2821 #ifdef __WINDOWS__
2822 extern "C" int WINAPI DllMain (HINSTANCE hinstDLL,
2823                      wxUint32 fdwReason,
2824                      LPVOID lpReserved)
2825 {
2826   sprintf (out_buf, "DllMain (%08lx - %d)\n", hinstDLL, fdwReason);
2827   LOG (out_buf);
2828
2829   if (fdwReason == DLL_PROCESS_ATTACH)
2830   {
2831     wxSetInstance(hinstDLL);
2832     return DllLoad();
2833   }
2834   else if (fdwReason == DLL_PROCESS_DETACH)
2835   {
2836     if (GFXWindow != NULL)
2837       GFXWindow->SetHWND(NULL);
2838     return DllUnload();
2839   }
2840   return TRUE;
2841 }
2842
2843 void CALL ReadScreen(void **dest, int *width, int *height)
2844 {
2845   *width = settings.res_x;
2846   *height = settings.res_y;
2847   wxUint8 * buff = (wxUint8*)malloc(settings.res_x * settings.res_y * 3);
2848   wxUint8 * line = buff;
2849   *dest = (void*)buff;
2850
2851   if (!fullscreen)
2852   {
2853     for (wxUint32 y=0; y<settings.res_y; y++)
2854     {
2855       for (wxUint32 x=0; x<settings.res_x; x++)
2856       {
2857         line[x*3] = 0x20;
2858         line[x*3+1] = 0x7f;
2859         line[x*3+2] = 0x40;
2860       }
2861     }
2862     LOG ("ReadScreen. not in the fullscreen!\n");
2863     return;
2864   }
2865
2866   GrLfbInfo_t info;
2867   info.size = sizeof(GrLfbInfo_t);
2868   if (grLfbLock (GR_LFB_READ_ONLY,
2869     GR_BUFFER_FRONTBUFFER,
2870     GR_LFBWRITEMODE_565,
2871     GR_ORIGIN_UPPER_LEFT,
2872     FXFALSE,
2873     &info))
2874   {
2875     wxUint32 offset_src=info.strideInBytes*(settings.scr_res_y-1);
2876
2877     // Copy the screen
2878     wxUint8 r, g, b;
2879     if (info.writeMode == GR_LFBWRITEMODE_8888)
2880     {
2881       wxUint32 col;
2882       for (wxUint32 y=0; y<settings.res_y; y++)
2883       {
2884         wxUint32 *ptr = (wxUint32*)((wxUint8*)info.lfbPtr + offset_src);
2885         for (wxUint32 x=0; x<settings.res_x; x++)
2886         {
2887           col = *(ptr++);
2888           r = (wxUint8)((col >> 16) & 0xFF);
2889           g = (wxUint8)((col >> 8) & 0xFF);
2890           b = (wxUint8)(col & 0xFF);
2891           line[x*3] = b;
2892           line[x*3+1] = g;
2893           line[x*3+2] = r;
2894         }
2895         line += settings.res_x * 3;
2896         offset_src -= info.strideInBytes;
2897       }
2898     }
2899     else
2900     {
2901       wxUint16 col;
2902       for (wxUint32 y=0; y<settings.res_y; y++)
2903       {
2904         wxUint16 *ptr = (wxUint16*)((wxUint8*)info.lfbPtr + offset_src);
2905         for (wxUint32 x=0; x<settings.res_x; x++)
2906         {
2907           col = *(ptr++);
2908           r = (wxUint8)((float)(col >> 11) / 31.0f * 255.0f);
2909           g = (wxUint8)((float)((col >> 5) & 0x3F) / 63.0f * 255.0f);
2910           b = (wxUint8)((float)(col & 0x1F) / 31.0f * 255.0f);
2911           line[x*3] = b;
2912           line[x*3+1] = g;
2913           line[x*3+2] = r;
2914         }
2915         line += settings.res_x * 3;
2916         offset_src -= info.strideInBytes;
2917       }
2918     }
2919     // Unlock the frontbuffer
2920     grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER);
2921   }
2922   LOG ("ReadScreen. Success.\n");
2923 }
2924 #endif
2925 #endif