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