2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002 Dave2001
4 * Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski
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
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.
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
21 //****************************************************************
23 // Glide64 - Glide Plugin for Nintendo 64 emulators
24 // Project started on December 29th, 2001
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
32 //****************************************************************
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.
38 //****************************************************************
49 #include "FBtoScreen.h"
50 #include "DepthBufferRender.h"
54 #elif defined(__MSC__)
56 #define PATH_MAX MAX_PATH
58 #include "osal_dynamiclib.h"
59 #ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
61 int ghq_dmptex_toggle_key = 0;
63 #if defined(__MINGW32__)
64 #define swprintf _snwprintf
65 #define vswprintf _vsnwprintf
68 #define G64_VERSION "G64 Mk2"
69 #define RELTIME "Date: " __DATE__// " Time: " __TIME__
81 std::ofstream rdp_log;
85 int elog_open = FALSE;
86 std::ofstream rdp_err;
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;
105 ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL;
106 ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath = NULL;
107 ptr_ConfigGetUserDataPath ConfigGetUserDataPath = NULL;
108 ptr_ConfigGetUserCachePath ConfigGetUserCachePath = NULL;
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;
124 GrContext_t gfx_context = 0;
125 int debugging = FALSE;
126 int exception = FALSE;
129 int ev_fullscreen = 0;
132 #define WINPROC_OVERRIDE
135 #ifdef WINPROC_OVERRIDE
136 LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
137 WNDPROC oldWndProc = NULL;
138 WNDPROC myWndProc = NULL;
142 HHOOK hhkLowLevelKybd = NULL;
143 LRESULT CALLBACK LowLevelKeyboardProc(int nCode,
144 WPARAM wParam, LPARAM lParam);
153 LARGE_INTEGER perf_freq;
154 LARGE_INTEGER fps_last;
155 LARGE_INTEGER fps_next;
157 wxUint32 fps_count = 0;
159 wxUint32 vi_count = 0;
164 float ntsc_percent = 0.0f;
165 float pal_percent = 0.0f;
170 // 60=0x0, 70=0x1, 72=0x2, 75=0x3, 80=0x4, 90=0x5, 100=0x6, 85=0x7, 120=0x8, none=0xff
173 //#include "ae_bridge.h"
174 #include "FrameSkipper.h"
175 FrameSkipper frameSkipper;
176 void vbo_resetcount();
179 unsigned long BMASK = 0x7FFFFF;
180 // Reality display processor structure
183 SETTINGS settings = { FALSE, 640, 480, GR_RESOLUTION_640x480, 0 };
185 HOTKEY_INFO hotkey_info;
187 VOODOO voodoo = {0, 0, 0, 0,
194 wxUint32 offset_font = 0;
195 wxUint32 offset_cursor = 0;
196 wxUint32 offset_textures = 0;
197 wxUint32 offset_texbuf1 = 0;
199 int capture_screen = 0;
200 char capture_path[256];
202 //SDL_sem *mutexProcessDList = SDL_CreateSemaphore(1);
204 // SOME FUNCTION DEFINITIONS
206 static void DrawFrameBuffer ();
209 void (*renderCallback)(int) = NULL;
210 static void (*l_DebugCallback)(void *, int, const char *) = NULL;
211 static void *l_DebugCallContext = NULL;
215 rdp.scale_1024 = settings.scr_res_x / 1024.0f;
216 rdp.scale_768 = settings.scr_res_y / 768.0f;
218 // float res_scl_x = (float)settings.res_x / 320.0f;
219 float res_scl_y = (float)settings.res_y / 240.0f;
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;
226 float fscale_x = (float)scale_x / 1024.0f;
227 float fscale_y = (float)scale_y / 2048.0f;
229 wxUint32 dwHStartReg = *gfx.VI_H_START_REG;
230 wxUint32 dwVStartReg = *gfx.VI_V_START_REG;
232 wxUint32 hstart = dwHStartReg >> 16;
233 wxUint32 hend = dwHStartReg & 0xFFFF;
235 // dunno... but sometimes this happens
236 if (hend == hstart) hend = (int)(*gfx.VI_WIDTH_REG / fscale_x);
238 wxUint32 vstart = dwVStartReg >> 16;
239 wxUint32 vend = dwVStartReg & 0xFFFF;
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;
246 sprintf (out_buf, "hstart: %d, hend: %d, vstart: %d, vend: %d\n", hstart, hend, vstart, vend);
248 sprintf (out_buf, "size: %d x %d\n", (int)rdp.vi_width, (int)rdp.vi_height);
252 rdp.scale_x = (float)settings.res_x / rdp.vi_width;
253 if (region > 0 && settings.pal230)
255 // odd... but pal games seem to want 230 as height...
256 rdp.scale_y = res_scl_y * (230.0f / rdp.vi_height) * aspect;
260 rdp.scale_y = (float)settings.res_y / rdp.vi_height * aspect;
262 // rdp.offset_x = settings.offset_x * res_scl_x;
263 // rdp.offset_y = settings.offset_y * res_scl_y;
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))
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;
275 rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
285 switch (settings.aspectmode)
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);
292 settings.res_x = settings.scr_res_x;
293 settings.res_y = (wxUint32)(settings.res_x / 4.0f * 3.0f);
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);
301 settings.res_x = settings.scr_res_x;
302 settings.res_y = (wxUint32)(settings.res_x / 16.0f * 9.0f);
305 default: //stretch or original
306 settings.res_x = settings.scr_res_x;
307 settings.res_y = settings.scr_res_y;
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
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;
321 // settings.res_x = settings.scr_res_x;
322 // settings.res_y = settings.scr_res_y;
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);
333 static wxConfigBase * OpenIni()
335 wxConfigBase * ini = wxConfigBase::Get(false);
338 if (iniName.IsEmpty())
339 iniName = pluginPath + wxT("/Glide64mk2.ini");
340 if (wxFileExists(iniName))
342 wxFileInputStream is(iniName);
343 wxFileConfig * fcfg = new wxFileConfig(is, wxConvISO8859_1);
344 wxConfigBase::Set(fcfg);
349 wxMessageBox(_T("Can not find ini file! Plugin will not run properly."), _T("File not found"), wxOK|wxICON_EXCLAMATION);
354 void WriteLog(m64p_msg_level level, const char *msg, ...)
359 vsnprintf(buf, 1023, msg, args);
364 l_DebugCallback(l_DebugCallContext, level, buf);
371 // LOG("ReadSettings\n");
374 ERRLOG("Could not open configuration!");
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");
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);
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);
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);
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);
407 settings.logging = (BOOL)Config_ReadInt ("logging", "Logging", 0);
408 settings.log_clear = (BOOL)Config_ReadInt ("log_clear", "", 0);
410 settings.run_in_window = (BOOL)Config_ReadInt ("run_in_window", "", 0);
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);
418 settings.autodetect_ucode = TRUE;
420 settings.wireframe = FALSE;
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;
432 #ifdef TEXTURE_FILTER
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]
437 // _("Smooth filtering 1"),
438 // _("Smooth filtering 2"),
439 // _("Smooth filtering 3"),
440 // _("Smooth filtering 4"),
441 // _("Sharp filtering 1"),
442 // _("Sharp filtering 2")
444 // settings.ghq_cmpr 0=S3TC and 1=FXT1
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]"
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);
474 void ReadSpecialSettings (const char * name)
477 // sprintf(buf, "ReadSpecialSettings. Name: %s\n", name);
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;
543 Ini * ini = Ini::OpenIni();
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)
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);
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;
593 // if (settings.custom_ini)
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));
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 );
607 frameSkipper.setSkips( FrameSkipper::MANUAL, settings.maxframeskip );
611 TODO-port: fix resolutions
613 if (ini->Read(_T("resolution"), &resolution))
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];
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;
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);
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;
653 settings.flame_corona = (settings.hacks & hack_Zelda) && !fb_depth_render_enabled;
656 //TODO-PORT: more ini stuff
657 void WriteSettings (bool saveEmulationSettings)
660 wxConfigBase * ini = OpenIni();
661 if (!ini || !ini->HasGroup(_T("/SETTINGS")))
663 ini->SetPath(_T("/SETTINGS"));
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);
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);
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_
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);
717 if (saveEmulationSettings)
721 wxString S = _T("/");
722 ini->SetPath(S+rdp.RomName);
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);
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);
745 ini->Write(_T("read_back_to_screen"), 0l);
748 wxFileOutputStream os(iniName);
749 ((wxFileConfig*)ini)->Save(os);
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;
760 int GetTexAddrUMA(int tmu, int texsize)
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];
767 int GetTexAddrNonUMA(int tmu, int texsize)
769 int addr = voodoo.tex_min_addr[tmu] + voodoo.tmem_ptr[tmu];
770 voodoo.tmem_ptr[tmu] += texsize;
773 GETTEXADDR GetTexAddr = GetTexAddrNonUMA;
775 // guLoadTextures - used to load the cursor and font textures
776 void guLoadTextures ()
778 if (grTextureBufferExt)
781 if (voodoo.max_tex_size <= 256)
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);
788 else if (settings.scr_res_x <= 1024)
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 );
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 );
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)
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;
823 offset_font += tbuf_size;
825 offset_texbuf1 = tbuf_size;
832 wxUint32 *data = (wxUint32*)font;
835 // ** Font texture **
836 wxUint8 *tex8 = (wxUint8*)malloc(256*64);
838 fontTex.smallLodLog2 = fontTex.largeLodLog2 = GR_LOD_LOG2_256;
839 fontTex.aspectRatioLog2 = GR_ASPECT_LOG2_4x1;
840 fontTex.format = GR_TEXFMT_ALPHA_8;
843 // Decompression: [1-bit inverse alpha --> 8-bit alpha]
845 for (i=0; i<0x200; i++)
847 // cur = ~*(data++), byteswapped
849 cur = _byteswap_ulong(~*(data++));
852 cur = ((cur&0xFF)<<24)|(((cur>>8)&0xFF)<<16)|(((cur>>16)&0xFF)<<8)|((cur>>24)&0xFF);
855 for (b=0x80000000; b!=0; b>>=1)
857 if (cur&b) *tex8 = 0xFF;
863 grTexDownloadMipMap (GR_TMU0,
864 voodoo.tex_min_addr[GR_TMU0] + offset_font,
865 GR_MIPMAPLEVELMASK_BOTH,
868 offset_cursor = offset_font + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &fontTex);
872 // ** Cursor texture **
874 data = (wxUint32*)cursor;
876 wxUint16 *tex16 = (wxUint16*)malloc(32*32*2);
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;
883 // Conversion: [16-bit 1555 (swapped) --> 16-bit 1555]
884 for (i=0; i<0x200; i++)
887 *(tex16++) = (wxUint16)(((cur&0x000000FF)<<8)|((cur&0x0000FF00)>>8));
888 *(tex16++) = (wxUint16)(((cur&0x00FF0000)>>8)|((cur&0xFF000000)>>24));
891 grTexDownloadMipMap (GR_TMU0,
892 voodoo.tex_min_addr[GR_TMU0] + offset_cursor,
893 GR_MIPMAPLEVELMASK_BOTH,
896 // Round to higher 16
897 offset_textures = ((offset_cursor + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &cursorTex))
899 free (cursorTex.data);
902 #ifdef TEXTURE_FILTER
903 void DisplayLoadProgress(const wchar_t *format, ...)
906 wchar_t wbuf[INFO_BUF];
910 va_start(args, format);
911 vswprintf(wbuf, INFO_BUF, format, args);
914 // XXX: convert to multibyte
915 wcstombs(buf, wbuf, INFO_BUF);
920 set_message_combiner ();
921 output (382, 380, 1, "LOADING TEXTURES. PLEASE WAIT...");
922 int len = min (strlen(buf)*8, 1024);
924 output (x, 360, 1, buf);
926 grColorMask (FXTRUE, FXTRUE);
927 grBufferClear (0, 0, 0xFFFF);
934 #ifdef TEXTURE_FILTER
935 wchar_t romname[256];
936 wchar_t foldername[PATH_MAX + 64];
937 wchar_t cachename[PATH_MAX + 64];
942 OPEN_RDP_LOG (); // doesn't matter if opens again; it will check for it
944 VLOG ("InitGfx ()\n");
952 // Select the Glide device
953 grSstSelect (settings.card_id);
955 // Is mirroring allowed?
956 const char *extensions = grGetString (GR_EXTENSION);
958 // Check which SST we are using and initialize stuff
959 // Hiroshi Morii <koolsmoky@users.sourceforge.net>
961 GR_SSTTYPE_VOODOO = 0,
962 GR_SSTTYPE_SST96 = 1,
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
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;
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;
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");
997 //TODO-PORT: fullscreen stuff
998 wxUint32 res_data = settings.res_data;
999 char strWrapperFullScreenResolutionExt[] = "grWrapperFullScreenResolutionExt";
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;
1010 res_data = settings.res_data;
1014 GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt =
1015 (GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress(strWrapperFullScreenResolutionExt);
1016 if (grWrapperFullScreenResolutionExt != NULL)
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];
1025 res_data = settings.res_data | 0x80000000;
1030 // Select the window
1032 if (fb_hwfbe_enabled)
1034 char strSstWinOpenExt[] ="grSstWinOpenExt";
1035 GRWINOPENEXT grSstWinOpenExt = (GRWINOPENEXT)grGetProcAddress(strSstWinOpenExt);
1036 if (grSstWinOpenExt)
1037 gfx_context = grSstWinOpenExt ((FxU32)NULL,
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
1047 gfx_context = grSstWinOpen ((FxU32)NULL,
1050 GR_COLORFORMAT_RGBA,
1051 GR_ORIGIN_UPPER_LEFT,
1052 2, // Double-buffering
1053 1); // 1 auxillary buffer
1057 ERRLOG("Error setting display mode");
1058 // grSstWinClose (gfx_context);
1064 to_fullscreen = FALSE;
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));
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);
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);
1089 if (strstr (extensions, "TEXMIRROR") && !(settings.hacks&hack_Zelda)) //zelda's trees suffer from hardware mirroring
1090 voodoo.sup_mirroring = 1;
1092 voodoo.sup_mirroring = 0;
1094 if (strstr (extensions, "TEXFMT")) //VSA100 texture format extension
1095 voodoo.sup_32bit_tex = TRUE;
1097 voodoo.sup_32bit_tex = FALSE;
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);
1103 if (fb_hwfbe_enabled)
1105 if (char * extstr = (char*)strstr(extensions, "TEXTUREBUFFER"))
1107 if (!strncmp(extstr, "TEXTUREBUFFER", 13))
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);
1118 settings.frame_buffer &= ~fb_hwfbe;
1121 grTextureBufferExt = 0;
1123 grStippleModeExt = (GRSTIPPLE)grStippleMode;
1124 grStipplePatternExt = (GRSTIPPLE)grStipplePattern;
1126 if (grStipplePatternExt)
1127 grStipplePatternExt(settings.stipple_pattern);
1129 // char strKeyPressedExt[] = "grKeyPressedExt";
1130 // grKeyPressed = (FxBool (FX_CALL *)(FxU32))grGetProcAddress (strKeyPressedExt);
1134 #ifdef SIMULATE_VOODOO1
1136 voodoo.sup_mirroring = 0;
1139 #ifdef SIMULATE_BANSHEE
1141 voodoo.sup_mirroring = 1;
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);
1152 grCullMode(GR_CULL_NEGATIVE);
1154 if (settings.fog) //"FOGCOORD" extension
1156 if (strstr (extensions, "FOGCOORD"))
1159 guFogGenerateLinear (fog_t, 0.0f, 255.0f);//(float)rdp.fog_multiplier + (float)rdp.fog_offset);//256.0f);
1161 for (int i = 63; i > 0; i--)
1163 if (fog_t[i] - fog_t[i-1] > 63)
1165 fog_t[i-1] = fog_t[i] - 63;
1169 // for (int f = 0; f < 64; f++)
1171 // FRDP("fog[%d]=%d->%f\n", f, fog_t[f], guFogTableIndexToW(f));
1174 grVertexLayout (GR_PARAM_FOG_EXT, offsetof(VERTEX,f), GR_PARAM_ENABLE);
1176 else //not supported
1177 settings.fog = FALSE;
1180 grDepthBufferMode (GR_DEPTHBUFFER_ZBUFFER);
1181 grDepthBufferFunction(GR_CMP_LESS);
1182 grDepthMask(FXTRUE);
1184 settings.res_x = settings.scr_res_x;
1185 settings.res_y = settings.scr_res_y;
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);
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;
1208 #ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
1209 if (!settings.ghq_use)
1211 settings.ghq_use = settings.ghq_fltr || settings.ghq_enht /*|| settings.ghq_cmpr*/ || settings.ghq_hirs;
1212 if (settings.ghq_use)
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;
1239 ghq_dmptex_toggle_key = 0;
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());
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
1249 settings.ghq_cache_size * 1024*1024, // cache texture to system memory
1252 romname, // name of ROM. must be no longer than 256 characters
1253 DisplayLoadProgress);
1256 if (settings.ghq_use && strstr (extensions, "TEXMIRROR"))
1257 voodoo.sup_mirroring = 1;
1265 VLOG("ReleaseGfx ()\n");
1267 // Restore gamma settings
1268 if (voodoo.gamma_correction)
1270 if (voodoo.gamma_table_r)
1271 grLoadGammaTable(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b);
1273 guGammaCorrectionRGB(1.3f, 1.3f, 1.3f); //1.3f is default 3dfx gamma for everything but desktop
1274 voodoo.gamma_correction = 0;
1278 grSstWinClose (gfx_context);
1284 rdp.window_changed = TRUE;
1287 // new API code begins here!
1293 EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front)
1295 VLOG("CALL ReadScreen2 ()\n");
1296 *width = settings.res_x;
1297 *height = settings.res_y;
1300 BYTE * line = (BYTE*)dest;
1303 for (wxUint32 y=0; y<settings.res_y; y++)
1305 for (wxUint32 x=0; x<settings.res_x; x++)
1312 // LOG ("ReadScreen. not in the fullscreen!\n");
1313 WARNLOG("[Glide64] Cannot save screenshot in windowed mode?\n");
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,
1327 // Copy the screen, let's hope this works.
1328 for (wxUint32 y=0; y<settings.res_y; y++)
1330 BYTE *ptr = (BYTE*) info.lfbPtr + (info.strideInBytes * y);
1331 for (wxUint32 x=0; x<settings.res_x; x++)
1333 line[x*3] = ptr[2]; // red
1334 line[x*3+1] = ptr[1]; // green
1335 line[x*3+2] = ptr[0]; // blue
1338 line += settings.res_x * 3;
1341 // Unlock the frontbuffer
1342 grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER);
1344 VLOG ("ReadScreen. Success.\n");
1348 EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
1349 void (*DebugCallback)(void *, int, const char *))
1351 VLOG("CALL PluginStartup ()\n");
1352 l_DebugCallback = DebugCallback;
1353 l_DebugCallContext = Context;
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)
1360 ERRLOG("Core emulator broken; no CoreAPIVersionFunc() function found.");
1361 return M64ERR_INCOMPATIBLE;
1363 int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion;
1364 (*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL);
1365 if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000))
1367 ERRLOG("Emulator core Config API incompatible with this plugin");
1368 return M64ERR_INCOMPATIBLE;
1370 if ((VidextAPIVersion & 0xffff0000) != (VIDEXT_API_VERSION & 0xffff0000))
1372 ERRLOG("Emulator core Video Extension API incompatible with this plugin");
1373 return M64ERR_INCOMPATIBLE;
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");
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");
1393 if (!ConfigOpenSection || !ConfigSetParameter || !ConfigGetParameter ||
1394 !ConfigSetDefaultInt || !ConfigSetDefaultFloat || !ConfigSetDefaultBool || !ConfigSetDefaultString ||
1395 !ConfigGetParamInt || !ConfigGetParamFloat || !ConfigGetParamBool || !ConfigGetParamString ||
1396 !ConfigGetSharedDataFilepath || !ConfigGetUserConfigPath || !ConfigGetUserDataPath || !ConfigGetUserCachePath)
1398 ERRLOG("Couldn't connect to Core configuration functions");
1399 return M64ERR_INCOMPATIBLE;
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");
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)
1418 ERRLOG("Couldn't connect to Core video functions");
1419 return M64ERR_INCOMPATIBLE;
1422 const char *configDir = ConfigGetSharedDataFilepath("Glide64mk2.ini");
1425 SetConfigDir(configDir);
1428 return M64ERR_SUCCESS;
1432 ERRLOG("Couldn't find Glide64mk2.ini");
1433 return M64ERR_FILES;
1437 EXPORT m64p_error CALL PluginShutdown(void)
1439 VLOG("CALL PluginShutdown ()\n");
1440 return M64ERR_SUCCESS;
1443 EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
1445 VLOG("CALL PluginGetVersion ()\n");
1446 /* set version info */
1447 if (PluginType != NULL)
1448 *PluginType = M64PLUGIN_GFX;
1450 if (PluginVersion != NULL)
1451 *PluginVersion = PLUGIN_VERSION;
1453 if (APIVersion != NULL)
1454 *APIVersion = VIDEO_PLUGIN_API_VERSION;
1456 if (PluginNamePtr != NULL)
1457 *PluginNamePtr = PLUGIN_NAME;
1459 if (Capabilities != NULL)
1464 return M64ERR_SUCCESS;
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
1472 *******************************************************************/
1473 EXPORT void CALL CaptureScreen ( char * Directory )
1476 strcpy (capture_path, Directory);
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.
1486 *******************************************************************/
1487 //#warning ChangeWindow unimplemented
1488 EXPORT void CALL ChangeWindow (void)
1490 VLOG ("ChangeWindow()\n");
1496 to_fullscreen = TRUE;
1497 ev_fullscreen = TRUE;
1500 ShowWindow( gfx.hStatusBar, SW_HIDE );
1501 ShowCursor( FALSE );
1506 ev_fullscreen = FALSE;
1511 ShowWindow( gfx.hStatusBar, SW_SHOW );
1512 SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
1518 // Go to fullscreen at next dlist
1519 // This is for compatibility with 1964, which reloads the plugin
1520 // when switching to fullscreen
1523 to_fullscreen = TRUE;
1526 ShowWindow( gfx.hStatusBar, SW_HIDE );
1527 ShowCursor( FALSE );
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);
1547 /******************************************************************
1549 Purpose: This function is called when the emulator is closing
1550 down allowing the dll to de-initialise.
1553 *******************************************************************/
1554 void CALL CloseDLL (void)
1556 VLOG ("CloseDLL ()\n");
1558 // re-set the old window proc
1559 #ifdef WINPROC_OVERRIDE
1560 SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
1564 if (hhkLowLevelKybd)
1566 UnhookWindowsHookEx(hhkLowLevelKybd);
1567 hhkLowLevelKybd = 0;
1573 #ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
1574 if (settings.ghq_use)
1577 settings.ghq_use = 0;
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;
1592 /******************************************************************
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
1598 *******************************************************************/
1599 void CALL DllTest ( HWND hParent )
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.
1610 *******************************************************************/
1611 void CALL DrawScreen (void)
1613 VLOG ("DrawScreen ()\n");
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)
1623 *******************************************************************/
1624 void CALL GetDllInfo ( PLUGIN_INFO * PluginInfo )
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
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
1639 BOOL WINAPI QueryPerformanceCounter(PLARGE_INTEGER counter)
1643 /* generic routine */
1644 gettimeofday( &tv, NULL );
1645 counter->QuadPart = (LONGLONG)tv.tv_usec + (LONGLONG)tv.tv_sec * 1000000;
1649 BOOL WINAPI QueryPerformanceFrequency(PLARGE_INTEGER frequency)
1651 frequency->s.LowPart= 1000000;
1652 frequency->s.HighPart= 0;
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
1664 Output: TRUE on success
1665 FALSE on failure to initialise
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 *******************************************************************/
1673 EXPORT int CALL InitiateGFX (GFX_INFO Gfx_Info)
1675 VLOG ("InitiateGFX (*)\n");
1678 // Assume scale of 1 for debug purposes
1682 memset (&settings, 0, sizeof(SETTINGS));
1684 char name[21] = "DEFAULT";
1685 ReadSpecialSettings (name);
1686 settings.res_data_org = settings.res_data;
1688 QueryPerformanceFrequency (&perf_freq);
1689 QueryPerformanceCounter (&fps_last);
1692 debug_init (); // Initialize debugger
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);
1710 if (fb_depth_render_enabled)
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);
1720 const char *extensions = grGetString (GR_EXTENSION);
1722 if (strstr (extensions, "EVOODOO"))
1725 voodoo.has_2mb_tex_boundary = 0;
1729 voodoo.has_2mb_tex_boundary = 1;
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
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.
1745 *******************************************************************/
1746 EXPORT void CALL MoveScreen (int xpos, int ypos)
1748 rdp.window_changed = TRUE;
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
1758 *******************************************************************/
1759 EXPORT void CALL ResizeVideoOutput(int Width, int Height)
1763 /******************************************************************
1765 Purpose: This function is called when a rom is closed.
1768 *******************************************************************/
1769 EXPORT void CALL RomClosed (void)
1771 VLOG ("RomClosed ()\n");
1772 printf("RomClosed ()\n");
1776 rdp.window_changed = TRUE;
1778 // if (fullscreen && evoodoo)//*SEB*
1782 static void CheckDRAMSize()
1787 test = gfx.RDRAM[0x007FFFFF] + 1;
1798 sprintf (out_buf, "Detected RDRAM size: %08lx\n", BMASK);
1803 /******************************************************************
1805 Purpose: This function is called when a rom is open. (from the
1809 *******************************************************************/
1810 EXPORT int CALL RomOpen (void)
1812 VLOG ("RomOpen ()\n");
1815 ucode_error_report = TRUE; // allowed to report ucode errors
1818 // Get the country code & translate to NTSC(0) or PAL(1)
1819 wxUint16 code = ((wxUint16*)gfx.HEADER)[0x1F^1];
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)
1828 frameSkipper.setTargetFPS(region == 1 ? 50 : 60);
1831 char name[21] = "DEFAULT";
1832 ReadSpecialSettings (name);
1834 // get the name of the ROM
1835 for (int i=0; i<20; i++)
1836 name[i] = gfx.HEADER[(32+i)^3];
1839 // remove all trailing spaces
1840 while (name[strlen(name)-1] == ' ')
1841 name[strlen(name)-1] = 0;
1843 strncpy(rdp.RomName, name, sizeof(name));
1844 ReadSpecialSettings (name);
1853 // ** EVOODOO EXTENSIONS **
1859 const char *extensions = grGetString (GR_EXTENSION);
1864 if (strstr (extensions, "EVOODOO"))
1873 if (strstr (extensions, "ROMNAME"))
1875 char strSetRomName[] = "grSetRomName";
1876 void (FX_CALL *grSetRomName)(char*);
1877 grSetRomName = (void (FX_CALL *)(char*))grGetProcAddress (strSetRomName);
1878 grSetRomName (name);
1884 EXPORT void CALL RomResumed(void)
1887 frameSkipper.start();
1891 /******************************************************************
1893 Purpose: Useally once Dlists are started being displayed, cfb is
1894 ignored. This function tells the dll to start displaying
1898 *******************************************************************/
1899 bool no_dlist = true;
1900 EXPORT void CALL ShowCFB (void)
1903 VLOG ("ShowCFB ()\n");
1906 EXPORT void CALL SetRenderingCallback(void (*callback)(int))
1908 VLOG("CALL SetRenderingCallback (*)\n");
1909 renderCallback = callback;
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)
1921 LRDP("Image height = 0 - skipping\n");
1926 fb_info.lr_x = VIwidth - 1;
1927 // fb_info.lr_x = (wxUint32)rdp.vi_width - 1;
1929 fb_info.lr_y = fb_info.height - 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;
1935 bool drawn = DrawFrameBufferToScreen(fb_info);
1936 if (settings.hacks&hack_Lego && drawn)
1938 rdp.updatescreen = 1;
1940 DrawFrameBufferToScreen(fb_info);
1946 void drawNoFullscreenMessage();
1948 void DrawFrameBuffer ()
1952 drawNoFullscreenMessage();
1959 grDepthMask (FXTRUE);
1960 grColorMask (FXTRUE, FXTRUE);
1961 grBufferClear (0, 0, 0xFFFF);
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
1974 *******************************************************************/
1975 wxUint32 update_screen_count = 0;
1976 EXPORT void CALL UpdateScreen (void)
1979 //printf("UpdateScreen()\n");
1980 frameSkipper.update();
1983 if (CheckKeyPressed(G64_VK_SPACE, 0x0001))
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);
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
1998 // vertical interrupt has occurred, increment counter
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)
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;
2018 wxUint32 limit = (settings.hacks&hack_Lego) ? 15 : 30;
2020 if (frameSkipper.willSkipNext())
2024 // if (!frameSkipper.hasSkipped())
2025 if (!frameSkipper.willSkipNext())
2027 if ((settings.frame_buffer&fb_cpu_write_hack) && (update_screen_count > limit) && (rdp.last_bg == 0))
2029 LRDP("DirectCPUWrite hack!\n");
2030 update_screen_count = 0;
2040 if( *gfx.VI_ORIGIN_REG > width )
2043 LRDP("ChangeSize done\n");
2045 if (!frameSkipper.willSkipNext())
2048 LRDP("DrawFrameBuffer done\n");
2049 rdp.updatescreen = 1;
2056 if (!frameSkipper.willSkipNext())
2058 if (settings.swapmode == 0)
2062 static void DrawWholeFrameBufferToScreen()
2064 static wxUint32 toScreenCI = 0;
2065 if (rdp.ci_width < 200)
2067 if (rdp.cimg == toScreenCI)
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)
2078 fb_info.lr_x = rdp.ci_width-1;
2080 fb_info.lr_y = rdp.ci_height-1;
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);
2087 static void GetGammaTable()
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)
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);
2102 wxUint32 curframe = 0;
2103 void newSwapBuffers()
2106 //frameSkipper.newFrame();
2107 //bool skipped = false;
2108 //printf("newSwapBuffers()\n");
2109 bool skipped = frameSkipper.willSkipNext();
2110 //bool skipped = frameSkipper.hasSkipped();
2112 if (!rdp.updatescreen) {
2115 if (settings.frame_buffer & fb_read_back_to_screen2)
2116 DrawWholeFrameBufferToScreen();
2117 frameSkipper.newFrame();
2123 rdp.updatescreen = 0;
2127 // Allow access to the whole screen
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);
2136 if ((settings.show_fps & 0xF) || settings.clock)
2137 set_message_combiner ();
2139 float y = (float)settings.res_y;
2140 if (settings.show_fps & 0x0F)
2142 if (settings.show_fps & 4)
2145 output (0, y, 0, "%d%% ", (int)pal_percent);
2147 output (0, y, 0, "%d%% ", (int)ntsc_percent);
2150 if (settings.show_fps & 2)
2152 output (0, y, 0, "VI/s: %.02f ", vi);
2155 if (settings.show_fps & 1)
2156 output (0, y, 0, "FPS: %.02f ", fps);
2162 if (settings.clock_24_hr)
2166 tm *cur_time = localtime (<ime);
2168 sprintf (out_buf, "%.2d:%.2d:%.2d", cur_time->tm_hour, cur_time->tm_min, cur_time->tm_sec);
2176 tm *cur_time = localtime (<ime);
2178 if (cur_time->tm_hour >= 12)
2180 strcpy (ampm, "PM");
2181 if (cur_time->tm_hour != 12)
2182 cur_time->tm_hour -= 12;
2184 if (cur_time->tm_hour == 0)
2185 cur_time->tm_hour = 12;
2187 if (cur_time->tm_hour >= 10)
2188 sprintf (out_buf, "%.5s %s", asctime(cur_time) + 11, ampm);
2190 sprintf (out_buf, " %.4s %s", asctime(cur_time) + 12, ampm);
2192 output ((float)(settings.res_x - 68), y, 0, out_buf, 0);
2195 if (CheckKeyPressed(G64_VK_BACK, 0x0001))
2197 hotkey_info.hk_filtering = 100;
2198 if (settings.filtering < 2)
2199 settings.filtering++;
2201 settings.filtering = 0;
2203 if ((abs((int)(frame_count - curframe)) > 3 ) && CheckKeyPressed(G64_VK_ALT, 0x8000)) //alt +
2205 if (CheckKeyPressed(G64_VK_B, 0x8000)) //b
2207 hotkey_info.hk_motionblur = 100;
2208 hotkey_info.hk_ref = 0;
2209 curframe = frame_count;
2210 settings.frame_buffer ^= fb_motionblur;
2212 else if (CheckKeyPressed(G64_VK_V, 0x8000)) //v
2214 hotkey_info.hk_ref = 100;
2215 hotkey_info.hk_motionblur = 0;
2216 curframe = frame_count;
2217 settings.frame_buffer ^= fb_ref;
2220 if (settings.buff_clear && (hotkey_info.hk_ref || hotkey_info.hk_motionblur || hotkey_info.hk_filtering))
2222 set_message_combiner ();
2226 if (hotkey_info.hk_ref)
2228 if (settings.frame_buffer & fb_ref)
2229 message = strcat(buf, "FB READ ALWAYS: ON");
2231 message = strcat(buf, "FB READ ALWAYS: OFF");
2232 hotkey_info.hk_ref--;
2234 if (hotkey_info.hk_motionblur)
2236 if (settings.frame_buffer & fb_motionblur)
2237 message = strcat(buf, " MOTION BLUR: ON");
2239 message = strcat(buf, " MOTION BLUR: OFF");
2240 hotkey_info.hk_motionblur--;
2242 if (hotkey_info.hk_filtering)
2244 switch (settings.filtering)
2247 message = strcat(buf, " FILTERING MODE: AUTOMATIC");
2250 message = strcat(buf, " FILTERING MODE: FORCE BILINEAR");
2253 message = strcat(buf, " FILTERING MODE: FORCE POINT-SAMPLED");
2256 hotkey_info.hk_filtering--;
2258 output (120.0f, (float)settings.res_y, 0, message, 0);
2265 // Make the directory if it doesn't exist
2266 if (!wxDirExists(capture_path))
2267 wxMkdir(capture_path);
2269 wxString romName = rdp.RomName;
2270 romName.Replace(wxT(" "), wxT("_"), true);
2271 romName.Replace(wxT(":"), wxT(";"), true);
2273 for (int i=1; ; i++)
2275 path = capture_path;
2276 path += wxT("Glide64mk2_");
2281 path << i << wxT(".") << ScreenShotFormats[settings.ssformat].extension;
2282 if (!wxFileName::FileExists(path))
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;
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,
2300 wxUint8 *ssimg = (wxUint8*)malloc(image_width * image_height * 3); // will be free in wxImage destructor
2302 wxUint32 offset_src = info.strideInBytes * offset_y;
2305 if (info.writeMode == GR_LFBWRITEMODE_8888)
2308 for (wxUint32 y = 0; y < image_height; y++)
2310 wxUint32 *ptr = (wxUint32*)((wxUint8*)info.lfbPtr + offset_src);
2312 for (wxUint32 x = 0; x < image_width; x++)
2315 ssimg[sspos++] = (wxUint8)((col >> 16) & 0xFF);
2316 ssimg[sspos++] = (wxUint8)((col >> 8) & 0xFF);
2317 ssimg[sspos++] = (wxUint8)(col & 0xFF);
2319 offset_src += info.strideInBytes;
2325 for (wxUint32 y = 0; y < image_height; y++)
2327 wxUint16 *ptr = (wxUint16*)((wxUint8*)info.lfbPtr + offset_src);
2329 for (wxUint32 x = 0; x < image_width; x++)
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);
2336 offset_src += info.strideInBytes;
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);
2348 // Capture the screen if debug capture is set
2349 if (_debugger.capture)
2351 // Allocate the screen
2352 _debugger.screen = new wxUint8 [(settings.res_x*settings.res_y) << 1];
2354 // Lock the backbuffer (already rendered)
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,
2364 wxUint32 offset_src=0, offset_dst=0;
2367 for (wxUint32 y=0; y<settings.res_y; y++)
2369 if (info.writeMode == GR_LFBWRITEMODE_8888)
2371 wxUint32 *src = (wxUint32*)((wxUint8*)info.lfbPtr + offset_src);
2372 wxUint16 *dst = (wxUint16*)(_debugger.screen + offset_dst);
2375 for (unsigned int x = 0; x < settings.res_x; 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;
2386 memcpy (_debugger.screen + offset_dst, (wxUint8*)info.lfbPtr + offset_src, settings.res_x << 1);
2388 offset_dst += settings.res_x << 1;
2389 offset_src += info.strideInBytes;
2392 // Unlock the backbuffer
2393 grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER);
2396 if (fullscreen && debugging)
2399 debug_cacheviewer ();
2406 if (settings.frame_buffer & fb_read_back_to_screen)
2407 DrawWholeFrameBufferToScreen();
2411 if (fb_hwfbe_enabled && !(settings.hacks&hack_RE2) && !evoodoo)
2412 grAuxBufferExt( GR_BUFFER_AUXBUFFER );
2421 grBufferSwap (settings.vsync);
2427 if (*gfx.VI_STATUS_REG&0x08) //gamma correction is used
2429 if (!voodoo.gamma_correction)
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;
2439 if (voodoo.gamma_correction)
2441 if (voodoo.gamma_table_r)
2442 grLoadGammaTable(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b);
2444 guGammaCorrectionRGB(1.3f, 1.3f, 1.3f); //1.3f is default 3dfx gamma for everything but desktop
2445 voodoo.gamma_correction = 0;
2450 if (_debugger.capture)
2458 if (debugging || settings.wireframe || settings.buff_clear || (settings.hacks&hack_PPL && settings.ucode == 6))
2460 if (settings.hacks&hack_RE2 && fb_depth_render_enabled)
2461 grDepthMask (FXFALSE);
2463 grDepthMask (FXTRUE);
2464 grBufferClear (0, 0, 0xFFFF);
2466 /* //let the game to clear the buffers
2469 grDepthMask (FXTRUE);
2470 grColorMask (FXFALSE, FXFALSE);
2471 grBufferClear (0, 0, 0xFFFF);
2472 grColorMask (FXTRUE, FXTRUE);
2480 if (settings.frame_buffer & fb_read_back_to_screen2)
2481 DrawWholeFrameBufferToScreen();
2485 frameSkipper.newFrame();
2488 // Open/close debugger?
2489 if (CheckKeyPressed(G64_VK_SCROLL, 0x0001))
2493 //if (settings.scr_res_x == 1024 && settings.scr_res_y == 768)
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);
2508 settings.res_x = settings.scr_res_x;
2509 settings.res_y = settings.scr_res_y;
2516 if (/*fullscreen && */debugging && CheckKeyPressed(G64_VK_INSERT, 0x0001))
2518 _debugger.capture = 1;
2525 /******************************************************************
2526 Function: ViStatusChanged
2527 Purpose: This function is called to notify the dll that the
2528 ViStatus registers value has been changed.
2531 *******************************************************************/
2532 EXPORT void CALL ViStatusChanged (void)
2536 /******************************************************************
2537 Function: ViWidthChanged
2538 Purpose: This function is called to notify the dll that the
2539 ViWidth registers value has been changed.
2542 *******************************************************************/
2543 EXPORT void CALL ViWidthChanged (void)
2547 #ifdef WINPROC_OVERRIDE
2548 LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2552 case WM_ACTIVATEAPP:
2553 if (wParam == TRUE && !fullscreen) rdp.window_changed = TRUE;
2556 if (!fullscreen) rdp.window_changed = TRUE;
2560 SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
2564 return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam);
2570 int CheckKeyPressed(int key, int mask)
2572 static Glide64Keys g64Keys;
2573 if (settings.use_hotkeys == 0)
2576 return (GetAsyncKeyState(g64Keys[key]) & mask);
2579 return grKeyPressed(g64Keys[key]);
2586 int k_ctl=0, k_alt=0, k_del=0;
2588 LRESULT CALLBACK LowLevelKeyboardProc(int nCode,
2589 WPARAM wParam, LPARAM lParam)
2591 if (!fullscreen) return CallNextHookEx(NULL, nCode, wParam, lParam);
2597 if (nCode == HC_ACTION)
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;
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;
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);
2633 return CallNextHookEx(NULL, nCode, wParam, lParam);
2638 // DllMain - called when the DLL is loaded, use this to get the DLL's instance
2641 class wxDLLApp : public wxApp
2644 virtual bool OnInit();
2647 IMPLEMENT_APP_NO_MAIN(wxDLLApp)
2649 bool wxDLLApp::OnInit()
2651 /* if (mutexProcessDList == NULL)
2652 mutexProcessDList = new wxMutex(wxMUTEX_DEFAULT);*/
2653 wxImage::AddHandler(new wxPNGHandler);
2654 wxImage::AddHandler(new wxJPEGHandler);
2659 int __attribute__ ((constructor)) DllLoad(void);
2660 int __attribute__ ((destructor)) DllUnload(void);
2663 // Called when the library is loaded and before dlopen() returns
2668 wxEntryStart(argc, argv);
2670 return wxTheApp->CallOnInit() ? TRUE : FALSE;
2674 // Called when the library is unloaded and before dlclose() returns
2684 extern "C" int WINAPI DllMain (HINSTANCE hinstDLL,
2688 sprintf (out_buf, "DllMain (%08lx - %d)\n", hinstDLL, fdwReason);
2691 if (fdwReason == DLL_PROCESS_ATTACH)
2693 wxSetInstance(hinstDLL);
2696 else if (fdwReason == DLL_PROCESS_DETACH)
2698 if (GFXWindow != NULL)
2699 GFXWindow->SetHWND(NULL);
2705 void CALL ReadScreen(void **dest, int *width, int *height)
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;
2715 for (wxUint32 y=0; y<settings.res_y; y++)
2717 for (wxUint32 x=0; x<settings.res_x; x++)
2724 LOG ("ReadScreen. not in the fullscreen!\n");
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,
2737 wxUint32 offset_src=info.strideInBytes*(settings.scr_res_y-1);
2741 if (info.writeMode == GR_LFBWRITEMODE_8888)
2744 for (wxUint32 y=0; y<settings.res_y; y++)
2746 wxUint32 *ptr = (wxUint32*)((wxUint8*)info.lfbPtr + offset_src);
2747 for (wxUint32 x=0; x<settings.res_x; x++)
2750 r = (wxUint8)((col >> 16) & 0xFF);
2751 g = (wxUint8)((col >> 8) & 0xFF);
2752 b = (wxUint8)(col & 0xFF);
2757 line += settings.res_x * 3;
2758 offset_src -= info.strideInBytes;
2764 for (wxUint32 y=0; y<settings.res_y; y++)
2766 wxUint16 *ptr = (wxUint16*)((wxUint8*)info.lfbPtr + offset_src);
2767 for (wxUint32 x=0; x<settings.res_x; x++)
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);
2777 line += settings.res_x * 3;
2778 offset_src -= info.strideInBytes;
2781 // Unlock the frontbuffer
2782 grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER);
2784 LOG ("ReadScreen. Success.\n");