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
61 #include "osal_dynamiclib.h"
62 #ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
64 int ghq_dmptex_toggle_key = 0;
66 #if defined(__MINGW32__)
67 #define swprintf _snwprintf
68 #define vswprintf _vsnwprintf
71 #define G64_VERSION "G64 Mk2"
72 #define RELTIME "Date: " __DATE__// " Time: " __TIME__
84 std::ofstream rdp_log;
88 int elog_open = FALSE;
89 std::ofstream rdp_err;
94 /* definitions of pointers to Core config functions */
95 ptr_ConfigOpenSection ConfigOpenSection = NULL;
96 ptr_ConfigSetParameter ConfigSetParameter = NULL;
97 ptr_ConfigGetParameter ConfigGetParameter = NULL;
98 ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL;
99 ptr_ConfigSetDefaultInt ConfigSetDefaultInt = NULL;
100 ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat = NULL;
101 ptr_ConfigSetDefaultBool ConfigSetDefaultBool = NULL;
102 ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL;
103 ptr_ConfigGetParamInt ConfigGetParamInt = NULL;
104 ptr_ConfigGetParamFloat ConfigGetParamFloat = NULL;
105 ptr_ConfigGetParamBool ConfigGetParamBool = NULL;
106 ptr_ConfigGetParamString ConfigGetParamString = NULL;
108 ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL;
109 ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath = NULL;
110 ptr_ConfigGetUserDataPath ConfigGetUserDataPath = NULL;
111 ptr_ConfigGetUserCachePath ConfigGetUserCachePath = NULL;
113 /* definitions of pointers to Core video extension functions */
114 ptr_VidExt_Init CoreVideo_Init = NULL;
115 ptr_VidExt_Quit CoreVideo_Quit = NULL;
116 ptr_VidExt_ListFullscreenModes CoreVideo_ListFullscreenModes = NULL;
117 ptr_VidExt_SetVideoMode CoreVideo_SetVideoMode = NULL;
118 ptr_VidExt_SetCaption CoreVideo_SetCaption = NULL;
119 ptr_VidExt_ToggleFullScreen CoreVideo_ToggleFullScreen = NULL;
120 ptr_VidExt_ResizeWindow CoreVideo_ResizeWindow = NULL;
121 ptr_VidExt_GL_GetProcAddress CoreVideo_GL_GetProcAddress = NULL;
122 ptr_VidExt_GL_SetAttribute CoreVideo_GL_SetAttribute = NULL;
123 ptr_VidExt_GL_SwapBuffers CoreVideo_GL_SwapBuffers = NULL;
124 int to_fullscreen = FALSE;
125 int fullscreen = FALSE;
127 GrContext_t gfx_context = 0;
128 int debugging = FALSE;
129 int exception = FALSE;
132 int ev_fullscreen = 0;
135 #define WINPROC_OVERRIDE
138 #ifdef WINPROC_OVERRIDE
139 LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
140 WNDPROC oldWndProc = NULL;
141 WNDPROC myWndProc = NULL;
145 HHOOK hhkLowLevelKybd = NULL;
146 LRESULT CALLBACK LowLevelKeyboardProc(int nCode,
147 WPARAM wParam, LPARAM lParam);
156 LARGE_INTEGER perf_freq;
157 LARGE_INTEGER fps_last;
158 LARGE_INTEGER fps_next;
160 wxUint32 fps_count = 0;
162 wxUint32 vi_count = 0;
167 float ntsc_percent = 0.0f;
168 float pal_percent = 0.0f;
173 // 60=0x0, 70=0x1, 72=0x2, 75=0x3, 80=0x4, 90=0x5, 100=0x6, 85=0x7, 120=0x8, none=0xff
176 //#include "ae_bridge.h"
177 #include "FrameSkipper.h"
178 FrameSkipper frameSkipper;
179 void vbo_resetcount();
182 unsigned long BMASK = 0x7FFFFF;
183 // Reality display processor structure
186 SETTINGS settings = { FALSE, 640, 480, GR_RESOLUTION_640x480, 0 };
188 HOTKEY_INFO hotkey_info;
190 VOODOO voodoo = {0, 0, 0, 0,
197 wxUint32 offset_font = 0;
198 wxUint32 offset_cursor = 0;
199 wxUint32 offset_textures = 0;
200 wxUint32 offset_texbuf1 = 0;
202 int capture_screen = 0;
203 char capture_path[256];
205 //SDL_sem *mutexProcessDList = SDL_CreateSemaphore(1);
207 // SOME FUNCTION DEFINITIONS
209 static void DrawFrameBuffer ();
212 void (*renderCallback)(int) = NULL;
213 static void (*l_DebugCallback)(void *, int, const char *) = NULL;
214 static void *l_DebugCallContext = NULL;
218 rdp.scale_1024 = settings.scr_res_x / 1024.0f;
219 rdp.scale_768 = settings.scr_res_y / 768.0f;
221 // float res_scl_x = (float)settings.res_x / 320.0f;
222 float res_scl_y = (float)settings.res_y / 240.0f;
224 wxUint32 scale_x = *gfx.VI_X_SCALE_REG & 0xFFF;
225 if (!scale_x) return;
226 wxUint32 scale_y = *gfx.VI_Y_SCALE_REG & 0xFFF;
227 if (!scale_y) return;
229 float fscale_x = (float)scale_x / 1024.0f;
230 float fscale_y = (float)scale_y / 2048.0f;
232 wxUint32 dwHStartReg = *gfx.VI_H_START_REG;
233 wxUint32 dwVStartReg = *gfx.VI_V_START_REG;
235 wxUint32 hstart = dwHStartReg >> 16;
236 wxUint32 hend = dwHStartReg & 0xFFFF;
238 // dunno... but sometimes this happens
239 if (hend == hstart) hend = (int)(*gfx.VI_WIDTH_REG / fscale_x);
241 wxUint32 vstart = dwVStartReg >> 16;
242 wxUint32 vend = dwVStartReg & 0xFFFF;
244 rdp.vi_width = (hend - hstart) * fscale_x;
245 rdp.vi_height = (vend - vstart) * fscale_y * 1.0126582f;
246 float aspect = (settings.adjust_aspect && (fscale_y > fscale_x) && (rdp.vi_width > rdp.vi_height)) ? fscale_x/fscale_y : 1.0f;
249 sprintf (out_buf, "hstart: %d, hend: %d, vstart: %d, vend: %d\n", hstart, hend, vstart, vend);
251 sprintf (out_buf, "size: %d x %d\n", (int)rdp.vi_width, (int)rdp.vi_height);
255 rdp.scale_x = (float)settings.res_x / rdp.vi_width;
256 if (region > 0 && settings.pal230)
258 // odd... but pal games seem to want 230 as height...
259 rdp.scale_y = res_scl_y * (230.0f / rdp.vi_height) * aspect;
263 rdp.scale_y = (float)settings.res_y / rdp.vi_height * aspect;
265 // rdp.offset_x = settings.offset_x * res_scl_x;
266 // rdp.offset_y = settings.offset_y * res_scl_y;
269 rdp.offset_y = ((float)settings.res_y - rdp.vi_height * rdp.scale_y) * 0.5f;
270 if (((wxUint32)rdp.vi_width <= (*gfx.VI_WIDTH_REG)/2) && (rdp.vi_width > rdp.vi_height))
273 rdp.scissor_o.ul_x = 0;
274 rdp.scissor_o.ul_y = 0;
275 rdp.scissor_o.lr_x = (wxUint32)rdp.vi_width;
276 rdp.scissor_o.lr_y = (wxUint32)rdp.vi_height;
278 rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
288 switch (settings.aspectmode)
291 if (settings.scr_res_x >= settings.scr_res_y * 4.0f / 3.0f) {
292 settings.res_y = settings.scr_res_y;
293 settings.res_x = (wxUint32)(settings.res_y * 4.0f / 3.0f);
295 settings.res_x = settings.scr_res_x;
296 settings.res_y = (wxUint32)(settings.res_x / 4.0f * 3.0f);
300 if (settings.scr_res_x >= settings.scr_res_y * 16.0f / 9.0f) {
301 settings.res_y = settings.scr_res_y;
302 settings.res_x = (wxUint32)(settings.res_y * 16.0f / 9.0f);
304 settings.res_x = settings.scr_res_x;
305 settings.res_y = (wxUint32)(settings.res_x / 16.0f * 9.0f);
308 default: //stretch or original
309 settings.res_x = settings.scr_res_x;
310 settings.res_y = settings.scr_res_y;
313 rdp.offset_x = (settings.scr_res_x - settings.res_x) / 2.0f;
314 float offset_y = (settings.scr_res_y - settings.res_y) / 2.0f;
315 settings.res_x += (wxUint32)rdp.offset_x;
316 settings.res_y += (wxUint32)offset_y;
317 rdp.offset_y += offset_y;
318 if (settings.aspectmode == 3) // original
320 rdp.scale_x = rdp.scale_y = 1.0f;
321 rdp.offset_x = (settings.scr_res_x - rdp.vi_width) / 2.0f;
322 rdp.offset_y = (settings.scr_res_y - rdp.vi_height) / 2.0f;
324 // settings.res_x = settings.scr_res_x;
325 // settings.res_y = settings.scr_res_y;
330 char strConfigWrapperExt[] = "grConfigWrapperExt";
331 GRCONFIGWRAPPEREXT grConfigWrapperExt = (GRCONFIGWRAPPEREXT)grGetProcAddress(strConfigWrapperExt);
332 if (grConfigWrapperExt)
333 grConfigWrapperExt(settings.wrpResolution, settings.wrpVRAM * 1024 * 1024, settings.wrpFBO, settings.wrpAnisotropic);
336 static wxConfigBase * OpenIni()
338 wxConfigBase * ini = wxConfigBase::Get(false);
341 if (iniName.IsEmpty())
342 iniName = pluginPath + wxT("/Glide64mk2.ini");
343 if (wxFileExists(iniName))
345 wxFileInputStream is(iniName);
346 wxFileConfig * fcfg = new wxFileConfig(is, wxConvISO8859_1);
347 wxConfigBase::Set(fcfg);
352 wxMessageBox(_T("Can not find ini file! Plugin will not run properly."), _T("File not found"), wxOK|wxICON_EXCLAMATION);
357 void WriteLog(m64p_msg_level level, const char *msg, ...)
362 vsnprintf(buf, 1023, msg, args);
367 l_DebugCallback(l_DebugCallContext, level, buf);
374 // LOG("ReadSettings\n");
377 ERRLOG("Could not open configuration!");
381 settings.card_id = (BYTE)Config_ReadInt ("card_id", "Card ID", 0, TRUE, FALSE);
382 //settings.lang_id not needed
383 // depth_bias = -Config_ReadInt ("depth_bias", "Depth bias level", 0, TRUE, FALSE);
384 settings.res_data = 0;
385 settings.scr_res_x = settings.res_x = Config_ReadScreenInt("ScreenWidth");
386 settings.scr_res_y = settings.res_y = Config_ReadScreenInt("ScreenHeight");
388 settings.vsync = (BOOL)Config_ReadInt ("vsync", "Vertical sync", 0);
389 settings.ssformat = (BOOL)Config_ReadInt("ssformat", "TODO:ssformat", 0);
390 //settings.fast_crc = (BOOL)Config_ReadInt ("fast_crc", "Fast CRC", 0);
392 settings.show_fps = (BYTE)Config_ReadInt ("show_fps", "Display performance stats (add together desired flags): 1=FPS counter, 2=VI/s counter, 4=% speed, 8=FPS transparent", 0, TRUE, FALSE);
393 settings.clock = (BOOL)Config_ReadInt ("clock", "Clock enabled", 0);
394 settings.clock_24_hr = (BOOL)Config_ReadInt ("clock_24_hr", "Clock is 24-hour", 0);
395 // settings.advanced_options only good for GUI config
396 // settings.texenh_options = only good for GUI config
397 //settings.use_hotkeys = ini->Read(_T("hotkeys"), 1l);
399 settings.wrpResolution = (BYTE)Config_ReadInt ("wrpResolution", "Wrapper resolution", 0, TRUE, FALSE);
400 settings.wrpVRAM = (BYTE)Config_ReadInt ("wrpVRAM", "Wrapper VRAM", 0, TRUE, FALSE);
401 settings.wrpFBO = (BOOL)Config_ReadInt ("wrpFBO", "Wrapper FBO", 1, TRUE, TRUE);
402 settings.wrpAnisotropic = (BOOL)Config_ReadInt ("wrpAnisotropic", "Wrapper Anisotropic Filtering", 0, TRUE, TRUE);
404 #ifndef _ENDUSER_RELEASE_
405 settings.autodetect_ucode = (BOOL)Config_ReadInt ("autodetect_ucode", "Auto-detect microcode", 1);
406 settings.ucode = (wxUint32)Config_ReadInt ("ucode", "Force microcode", 2, TRUE, FALSE);
407 settings.wireframe = (BOOL)Config_ReadInt ("wireframe", "Wireframe display", 0);
408 settings.wfmode = (int)Config_ReadInt ("wfmode", "Wireframe mode: 0=Normal colors, 1=Vertex colors, 2=Red only", 1, TRUE, FALSE);
410 settings.logging = (BOOL)Config_ReadInt ("logging", "Logging", 0);
411 settings.log_clear = (BOOL)Config_ReadInt ("log_clear", "", 0);
413 settings.run_in_window = (BOOL)Config_ReadInt ("run_in_window", "", 0);
415 settings.elogging = (BOOL)Config_ReadInt ("elogging", "", 0);
416 settings.filter_cache = (BOOL)Config_ReadInt ("filter_cache", "Filter cache", 0);
417 settings.unk_as_red = (BOOL)Config_ReadInt ("unk_as_red", "Display unknown combines as red", 0);
418 settings.log_unk = (BOOL)Config_ReadInt ("log_unk", "Log unknown combines", 0);
419 settings.unk_clear = (BOOL)Config_ReadInt ("unk_clear", "", 0);
421 settings.autodetect_ucode = TRUE;
423 settings.wireframe = FALSE;
425 settings.logging = FALSE;
426 settings.log_clear = FALSE;
427 settings.run_in_window = FALSE;
428 settings.elogging = FALSE;
429 settings.filter_cache = FALSE;
430 settings.unk_as_red = FALSE;
431 settings.log_unk = FALSE;
432 settings.unk_clear = FALSE;
435 #ifdef TEXTURE_FILTER
437 // settings.ghq_fltr range is 0 through 6
438 // Filters:\nApply a filter to either smooth or sharpen textures.\nThere are 4 different smoothing filters and 2 different sharpening filters.\nThe higher the number, the stronger the effect,\ni.e. \"Smoothing filter 4\" will have a much more noticeable effect than \"Smoothing filter 1\".\nBe aware that performance may have an impact depending on the game and/or the PC.\n[Recommended: your preference]
440 // _("Smooth filtering 1"),
441 // _("Smooth filtering 2"),
442 // _("Smooth filtering 3"),
443 // _("Smooth filtering 4"),
444 // _("Sharp filtering 1"),
445 // _("Sharp filtering 2")
447 // settings.ghq_cmpr 0=S3TC and 1=FXT1
449 //settings.ghq_ent is ___
450 // "Texture enhancement:\n7 different filters are selectable here, each one with a distinctive look.\nBe aware of possible performance impacts.\n\nIMPORTANT: 'Store' mode - saves textures in cache 'as is'. It can improve performance in games, which load many textures.\nDisable 'Ignore backgrounds' option for better result.\n\n[Recommended: your preference]"
454 settings.ghq_fltr = Config_ReadInt ("ghq_fltr", "Texture Enhancement: Smooth/Sharpen Filters", 0, TRUE, FALSE);
455 settings.ghq_cmpr = Config_ReadInt ("ghq_cmpr", "Texture Compression: 0 for S3TC, 1 for FXT1", 0, TRUE, FALSE);
456 settings.ghq_enht = Config_ReadInt ("ghq_enht", "Texture Enhancement: More filters", 0, TRUE, FALSE);
457 settings.ghq_hirs = Config_ReadInt ("ghq_hirs", "Hi-res texture pack format (0 for none, 1 for Rice)", 0, TRUE, FALSE);
458 settings.ghq_enht_cmpr = Config_ReadInt ("ghq_enht_cmpr", "Compress texture cache with S3TC or FXT1", 0, TRUE, TRUE);
459 settings.ghq_enht_tile = Config_ReadInt ("ghq_enht_tile", "Tile textures (saves memory but could cause issues)", 0, TRUE, FALSE);
460 settings.ghq_enht_f16bpp = Config_ReadInt ("ghq_enht_f16bpp", "Force 16bpp textures (saves ram but lower quality)", 0, TRUE, TRUE);
461 settings.ghq_enht_gz = Config_ReadInt ("ghq_enht_gz", "Compress texture cache", 1, TRUE, TRUE);
462 settings.ghq_enht_nobg = Config_ReadInt ("ghq_enht_nobg", "Don't enhance textures for backgrounds", 0, TRUE, TRUE);
463 settings.ghq_hirs_cmpr = Config_ReadInt ("ghq_hirs_cmpr", "Enable S3TC and FXT1 compression", 0, TRUE, TRUE);
464 settings.ghq_hirs_tile = Config_ReadInt ("ghq_hirs_tile", "Tile hi-res textures (saves memory but could cause issues)", 0, TRUE, TRUE);
465 settings.ghq_hirs_f16bpp = Config_ReadInt ("ghq_hirs_f16bpp", "Force 16bpp hi-res textures (saves ram but lower quality)", 0, TRUE, TRUE);
466 settings.ghq_hirs_gz = Config_ReadInt ("ghq_hirs_gz", "Compress hi-res texture cache", 1, TRUE, TRUE);
467 settings.ghq_hirs_altcrc = Config_ReadInt ("ghq_hirs_altcrc", "Alternative CRC calculation -- emulates Rice bug", 1, TRUE, TRUE);
468 settings.ghq_cache_save = Config_ReadInt ("ghq_cache_save", "Save tex cache to disk", 1, TRUE, TRUE);
469 settings.ghq_cache_size = Config_ReadInt ("ghq_cache_size", "Texture Cache Size (MB)", 128, TRUE, FALSE);
470 settings.ghq_hirs_let_texartists_fly = Config_ReadInt ("ghq_hirs_let_texartists_fly", "Use full alpha channel -- could cause issues for some tex packs", 0, TRUE, TRUE);
471 settings.ghq_hirs_dump = Config_ReadInt ("ghq_hirs_dump", "Dump textures", 0, FALSE, TRUE);
477 void ReadSpecialSettings (const char * name)
480 // sprintf(buf, "ReadSpecialSettings. Name: %s\n", name);
484 //detect games which require special hacks
485 if (strstr(name, (const char *)"ZELDA") || strstr(name, (const char *)"MASK"))
486 settings.hacks |= hack_Zelda;
487 else if (strstr(name, (const char *)"ROADSTERS TROPHY"))
488 settings.hacks |= hack_Zelda;
489 else if (strstr(name, (const char *)"Diddy Kong Racing"))
490 settings.hacks |= hack_Diddy;
491 else if (strstr(name, (const char *)"Tonic Trouble"))
492 settings.hacks |= hack_Tonic;
493 else if (strstr(name, (const char *)"All") && strstr(name, (const char *)"Star") && strstr(name, (const char *)"Baseball"))
494 settings.hacks |= hack_ASB;
495 else if (strstr(name, (const char *)"Beetle") || strstr(name, (const char *)"BEETLE") || strstr(name, (const char *)"HSV"))
496 settings.hacks |= hack_BAR;
497 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"))
498 settings.hacks |= hack_ISS64;
499 else if (strstr(name, (const char *)"MARIOKART64"))
500 settings.hacks |= hack_MK64;
501 else if (strstr(name, (const char *)"NITRO64"))
502 settings.hacks |= hack_WCWnitro;
503 else if (strstr(name, (const char *)"CHOPPER_ATTACK") || strstr(name, (const char *)"WILD CHOPPERS"))
504 settings.hacks |= hack_Chopper;
505 else if (strstr(name, (const char *)"Resident Evil II") || strstr(name, (const char *)"BioHazard II"))
506 settings.hacks |= hack_RE2;
507 else if (strstr(name, (const char *)"YOSHI STORY"))
508 settings.hacks |= hack_Yoshi;
509 else if (strstr(name, (const char *)"F-Zero X") || strstr(name, (const char *)"F-ZERO X"))
510 settings.hacks |= hack_Fzero;
511 else if (strstr(name, (const char *)"PAPER MARIO") || strstr(name, (const char *)"MARIO STORY"))
512 settings.hacks |= hack_PMario;
513 else if (strstr(name, (const char *)"TOP GEAR RALLY 2"))
514 settings.hacks |= hack_TGR2;
515 else if (strstr(name, (const char *)"TOP GEAR RALLY"))
516 settings.hacks |= hack_TGR;
517 else if (strstr(name, (const char *)"Top Gear Hyper Bike"))
518 settings.hacks |= hack_Hyperbike;
519 else if (strstr(name, (const char *)"Killer Instinct Gold") || strstr(name, (const char *)"KILLER INSTINCT GOLD"))
520 settings.hacks |= hack_KI;
521 else if (strstr(name, (const char *)"Knockout Kings 2000"))
522 settings.hacks |= hack_Knockout;
523 else if (strstr(name, (const char *)"LEGORacers"))
524 settings.hacks |= hack_Lego;
525 else if (strstr(name, (const char *)"OgreBattle64"))
526 settings.hacks |= hack_Ogre64;
527 else if (strstr(name, (const char *)"Pilot Wings64"))
528 settings.hacks |= hack_Pilotwings;
529 else if (strstr(name, (const char *)"Supercross"))
530 settings.hacks |= hack_Supercross;
531 else if (strstr(name, (const char *)"STARCRAFT 64"))
532 settings.hacks |= hack_Starcraft;
533 else if (strstr(name, (const char *)"BANJO KAZOOIE 2") || strstr(name, (const char *)"BANJO TOOIE"))
534 settings.hacks |= hack_Banjo2;
535 else if (strstr(name, (const char *)"FIFA: RTWC 98") || strstr(name, (const char *)"RoadToWorldCup98"))
536 settings.hacks |= hack_Fifa98;
537 else if (strstr(name, (const char *)"Mega Man 64") || strstr(name, (const char *)"RockMan Dash"))
538 settings.hacks |= hack_Megaman;
539 else if (strstr(name, (const char *)"MISCHIEF MAKERS") || strstr(name, (const char *)"TROUBLE MAKERS"))
540 settings.hacks |= hack_Makers;
541 else if (strstr(name, (const char *)"GOLDENEYE"))
542 settings.hacks |= hack_GoldenEye;
543 else if (strstr(name, (const char *)"PUZZLE LEAGUE"))
544 settings.hacks |= hack_PPL;
546 Ini * ini = Ini::OpenIni();
551 ini->Read(_T("alt_tex_size"), &(settings.alt_tex_size));
552 ini->Read(_T("use_sts1_only"), &(settings.use_sts1_only));
553 ini->Read(_T("force_calc_sphere"), &(settings.force_calc_sphere));
554 ini->Read(_T("correct_viewport"), &(settings.correct_viewport));
555 ini->Read(_T("increase_texrect_edge"), &(settings.increase_texrect_edge));
556 ini->Read(_T("decrease_fillrect_edge"), &(settings.decrease_fillrect_edge));
557 if (ini->Read(_T("texture_correction"), -1) == 0) settings.texture_correction = 0;
558 else settings.texture_correction = 1;
559 if (ini->Read(_T("pal230"), -1) == 1) settings.pal230 = 1;
560 else settings.pal230 = 0;
561 ini->Read(_T("stipple_mode"), &(settings.stipple_mode));
562 int stipple_pattern = ini->Read(_T("stipple_pattern"), -1);
563 if (stipple_pattern > 0) settings.stipple_pattern = (wxUint32)stipple_pattern;
564 ini->Read(_T("force_microcheck"), &(settings.force_microcheck));
565 ini->Read(_T("force_quad3d"), &(settings.force_quad3d));
566 ini->Read(_T("clip_zmin"), &(settings.clip_zmin));
567 ini->Read(_T("clip_zmax"), &(settings.clip_zmax));
568 ini->Read(_T("fast_crc"), &(settings.fast_crc));
569 ini->Read(_T("adjust_aspect"), &(settings.adjust_aspect), 1);
570 ini->Read(_T("zmode_compare_less"), &(settings.zmode_compare_less));
571 ini->Read(_T("old_style_adither"), &(settings.old_style_adither));
572 ini->Read(_T("n64_z_scale"), &(settings.n64_z_scale));
573 if (settings.n64_z_scale)
577 int optimize_texrect = ini->Read(_T("optimize_texrect"), -1);
578 int ignore_aux_copy = ini->Read(_T("ignore_aux_copy"), -1);
579 int hires_buf_clear = ini->Read(_T("hires_buf_clear"), -1);
580 int read_alpha = ini->Read(_T("fb_read_alpha"), -1);
581 int useless_is_useless = ini->Read(_T("useless_is_useless"), -1);
582 int fb_crc_mode = ini->Read(_T("fb_crc_mode"), -1);
584 if (optimize_texrect > 0) settings.frame_buffer |= fb_optimize_texrect;
585 else if (optimize_texrect == 0) settings.frame_buffer &= ~fb_optimize_texrect;
586 if (ignore_aux_copy > 0) settings.frame_buffer |= fb_ignore_aux_copy;
587 else if (ignore_aux_copy == 0) settings.frame_buffer &= ~fb_ignore_aux_copy;
588 if (hires_buf_clear > 0) settings.frame_buffer |= fb_hwfbe_buf_clear;
589 else if (hires_buf_clear == 0) settings.frame_buffer &= ~fb_hwfbe_buf_clear;
590 if (read_alpha > 0) settings.frame_buffer |= fb_read_alpha;
591 else if (read_alpha == 0) settings.frame_buffer &= ~fb_read_alpha;
592 if (useless_is_useless > 0) settings.frame_buffer |= fb_useless_is_useless;
593 else settings.frame_buffer &= ~fb_useless_is_useless;
594 if (fb_crc_mode >= 0) settings.fb_crc_mode = (SETTINGS::FBCRCMODE)fb_crc_mode;
596 // if (settings.custom_ini)
598 ini->Read(_T("filtering"), &(settings.filtering));
599 ini->Read(_T("fog"), &(settings.fog));
600 ini->Read(_T("buff_clear"), &(settings.buff_clear));
601 ini->Read(_T("swapmode"), &(settings.swapmode));
602 ini->Read(_T("aspect"), &(settings.aspectmode));
603 ini->Read(_T("lodmode"), &(settings.lodmode));
605 ini->Read(_T("autoframeskip"), &(settings.autoframeskip));
606 ini->Read(_T("maxframeskip"), &(settings.maxframeskip));
607 if( settings.autoframeskip == 1 )
608 frameSkipper.setSkips( FrameSkipper::AUTO, settings.maxframeskip );
610 frameSkipper.setSkips( FrameSkipper::MANUAL, settings.maxframeskip );
614 TODO-port: fix resolutions
616 if (ini->Read(_T("resolution"), &resolution))
618 settings.res_data = (wxUint32)resolution;
619 if (settings.res_data >= 0x18) settings.res_data = 12;
620 settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0];
621 settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1];
625 PackedScreenResolution tmpRes = Config_ReadScreenSettings();
626 settings.res_data = tmpRes.resolution;
627 settings.scr_res_x = settings.res_x = tmpRes.width;
628 settings.scr_res_y = settings.res_y = tmpRes.height;
631 int smart_read = ini->Read(_T("fb_smart"), -1);
632 int hires = ini->Read(_T("fb_hires"), -1);
633 int read_always = ini->Read(_T("fb_read_always"), -1);
634 int read_back_to_screen = ini->Read(_T("read_back_to_screen"), -1);
635 int cpu_write_hack = ini->Read(_T("detect_cpu_write"), -1);
636 int get_fbinfo = ini->Read(_T("fb_get_info"), -1);
637 int depth_render = ini->Read(_T("fb_render"), -1);
639 if (smart_read > 0) settings.frame_buffer |= fb_emulation;
640 else if (smart_read == 0) settings.frame_buffer &= ~fb_emulation;
641 if (hires > 0) settings.frame_buffer |= fb_hwfbe;
642 else if (hires == 0) settings.frame_buffer &= ~fb_hwfbe;
643 if (read_always > 0) settings.frame_buffer |= fb_ref;
644 else if (read_always == 0) settings.frame_buffer &= ~fb_ref;
645 if (read_back_to_screen == 1) settings.frame_buffer |= fb_read_back_to_screen;
646 else if (read_back_to_screen == 2) settings.frame_buffer |= fb_read_back_to_screen2;
647 else if (read_back_to_screen == 0) settings.frame_buffer &= ~(fb_read_back_to_screen|fb_read_back_to_screen2);
648 if (cpu_write_hack > 0) settings.frame_buffer |= fb_cpu_write_hack;
649 else if (cpu_write_hack == 0) settings.frame_buffer &= ~fb_cpu_write_hack;
650 if (get_fbinfo > 0) settings.frame_buffer |= fb_get_info;
651 else if (get_fbinfo == 0) settings.frame_buffer &= ~fb_get_info;
652 if (depth_render > 0) settings.frame_buffer |= fb_depth_render;
653 else if (depth_render == 0) settings.frame_buffer &= ~fb_depth_render;
654 settings.frame_buffer |= fb_motionblur;
656 settings.flame_corona = (settings.hacks & hack_Zelda) && !fb_depth_render_enabled;
659 //TODO-PORT: more ini stuff
660 void WriteSettings (bool saveEmulationSettings)
663 wxConfigBase * ini = OpenIni();
664 if (!ini || !ini->HasGroup(_T("/SETTINGS")))
666 ini->SetPath(_T("/SETTINGS"));
668 ini->Write(_T("card_id"), settings.card_id);
669 ini->Write(_T("lang_id"), settings.lang_id);
670 ini->Write(_T("resolution"), (int)settings.res_data);
671 ini->Write(_T("ssformat"), settings.ssformat);
672 ini->Write(_T("vsync"), settings.vsync);
673 ini->Write(_T("show_fps"), settings.show_fps);
674 ini->Write(_T("clock"), settings.clock);
675 ini->Write(_T("clock_24_hr"), settings.clock_24_hr);
676 ini->Write(_T("advanced_options"), settings.advanced_options);
677 ini->Write(_T("texenh_options"), settings.texenh_options);
679 ini->Write(_T("wrpResolution"), settings.wrpResolution);
680 ini->Write(_T("wrpVRAM"), settings.wrpVRAM);
681 ini->Write(_T("wrpFBO"), settings.wrpFBO);
682 ini->Write(_T("wrpAnisotropic"), settings.wrpAnisotropic);
684 #ifndef _ENDUSER_RELEASE_
685 ini->Write(_T("autodetect_ucode"), settings.autodetect_ucode);
686 ini->Write(_T("ucode"), (int)settings.ucode);
687 ini->Write(_T("wireframe"), settings.wireframe);
688 ini->Write(_T("wfmode"), settings.wfmode);
689 ini->Write(_T("logging"), settings.logging);
690 ini->Write(_T("log_clear"), settings.log_clear);
691 ini->Write(_T("run_in_window"), settings.run_in_window);
692 ini->Write(_T("elogging"), settings.elogging);
693 ini->Write(_T("filter_cache"), settings.filter_cache);
694 ini->Write(_T("unk_as_red"), settings.unk_as_red);
695 ini->Write(_T("log_unk"), settings.log_unk);
696 ini->Write(_T("unk_clear"), settings.unk_clear);
697 #endif //_ENDUSER_RELEASE_
699 #ifdef TEXTURE_FILTER
700 ini->Write(_T("ghq_fltr"), settings.ghq_fltr);
701 ini->Write(_T("ghq_cmpr"), settings.ghq_cmpr);
702 ini->Write(_T("ghq_enht"), settings.ghq_enht);
703 ini->Write(_T("ghq_hirs"), settings.ghq_hirs);
704 ini->Write(_T("ghq_enht_cmpr"), settings.ghq_enht_cmpr);
705 ini->Write(_T("ghq_enht_tile"), settings.ghq_enht_tile);
706 ini->Write(_T("ghq_enht_f16bpp"), settings.ghq_enht_f16bpp);
707 ini->Write(_T("ghq_enht_gz"), settings.ghq_enht_gz);
708 ini->Write(_T("ghq_enht_nobg"), settings.ghq_enht_nobg);
709 ini->Write(_T("ghq_hirs_cmpr"), settings.ghq_hirs_cmpr);
710 ini->Write(_T("ghq_hirs_tile"), settings.ghq_hirs_tile);
711 ini->Write(_T("ghq_hirs_f16bpp"), settings.ghq_hirs_f16bpp);
712 ini->Write(_T("ghq_hirs_gz"), settings.ghq_hirs_gz);
713 ini->Write(_T("ghq_hirs_altcrc"), settings.ghq_hirs_altcrc);
714 ini->Write(_T("ghq_cache_save"), settings.ghq_cache_save);
715 ini->Write(_T("ghq_cache_size"), settings.ghq_cache_size);
716 ini->Write(_T("ghq_hirs_let_texartists_fly"), settings.ghq_hirs_let_texartists_fly);
717 ini->Write(_T("ghq_hirs_dump"), settings.ghq_hirs_dump);
720 if (saveEmulationSettings)
724 wxString S = _T("/");
725 ini->SetPath(S+rdp.RomName);
728 ini->SetPath(_T("/DEFAULT"));
729 ini->Write(_T("filtering"), settings.filtering);
730 ini->Write(_T("fog"), settings.fog);
731 ini->Write(_T("buff_clear"), settings.buff_clear);
732 ini->Write(_T("swapmode"), settings.swapmode);
733 ini->Write(_T("lodmode"), settings.lodmode);
734 ini->Write(_T("aspect"), settings.aspectmode);
736 ini->Write(_T("fb_read_always"), settings.frame_buffer&fb_ref ? 1 : 0l);
737 ini->Write(_T("fb_smart"), settings.frame_buffer & fb_emulation ? 1 : 0l);
738 // ini->Write("motionblur", settings.frame_buffer & fb_motionblur ? 1 : 0);
739 ini->Write(_T("fb_hires"), settings.frame_buffer & fb_hwfbe ? 1 : 0l);
740 ini->Write(_T("fb_get_info"), settings.frame_buffer & fb_get_info ? 1 : 0l);
741 ini->Write(_T("fb_render"), settings.frame_buffer & fb_depth_render ? 1 : 0l);
742 ini->Write(_T("detect_cpu_write"), settings.frame_buffer & fb_cpu_write_hack ? 1 : 0l);
743 if (settings.frame_buffer & fb_read_back_to_screen)
744 ini->Write(_T("read_back_to_screen"), 1);
745 else if (settings.frame_buffer & fb_read_back_to_screen2)
746 ini->Write(_T("read_back_to_screen"), 2);
748 ini->Write(_T("read_back_to_screen"), 0l);
751 wxFileOutputStream os(iniName);
752 ((wxFileConfig*)ini)->Save(os);
756 GRTEXBUFFEREXT grTextureBufferExt = NULL;
757 GRTEXBUFFEREXT grTextureAuxBufferExt = NULL;
758 GRAUXBUFFEREXT grAuxBufferExt = NULL;
759 GRSTIPPLE grStippleModeExt = NULL;
760 GRSTIPPLE grStipplePatternExt = NULL;
761 FxBool (FX_CALL *grKeyPressed)(FxU32) = NULL;
763 int GetTexAddrUMA(int tmu, int texsize)
765 int addr = voodoo.tex_min_addr[0] + voodoo.tmem_ptr[0];
766 voodoo.tmem_ptr[0] += texsize;
767 voodoo.tmem_ptr[1] = voodoo.tmem_ptr[0];
770 int GetTexAddrNonUMA(int tmu, int texsize)
772 int addr = voodoo.tex_min_addr[tmu] + voodoo.tmem_ptr[tmu];
773 voodoo.tmem_ptr[tmu] += texsize;
776 GETTEXADDR GetTexAddr = GetTexAddrNonUMA;
778 // guLoadTextures - used to load the cursor and font textures
779 void guLoadTextures ()
781 if (grTextureBufferExt)
784 if (voodoo.max_tex_size <= 256)
786 grTextureBufferExt( GR_TMU1, voodoo.tex_min_addr[GR_TMU1], GR_LOD_LOG2_256, GR_LOD_LOG2_256,
787 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
788 tbuf_size = 8 * grTexCalcMemRequired(GR_LOD_LOG2_256, GR_LOD_LOG2_256,
789 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);
791 else if (settings.scr_res_x <= 1024)
793 grTextureBufferExt( GR_TMU0, voodoo.tex_min_addr[GR_TMU0], GR_LOD_LOG2_1024, GR_LOD_LOG2_1024,
794 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
795 tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_1024, GR_LOD_LOG2_1024,
796 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);
797 grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
798 grBufferClear (0, 0, 0xFFFF);
799 grRenderBuffer( GR_BUFFER_BACKBUFFER );
803 grTextureBufferExt( GR_TMU0, voodoo.tex_min_addr[GR_TMU0], GR_LOD_LOG2_2048, GR_LOD_LOG2_2048,
804 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
805 tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_2048, GR_LOD_LOG2_2048,
806 GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);
807 grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
808 grBufferClear (0, 0, 0xFFFF);
809 grRenderBuffer( GR_BUFFER_BACKBUFFER );
812 rdp.texbufs[0].tmu = GR_TMU0;
813 rdp.texbufs[0].begin = voodoo.tex_min_addr[GR_TMU0];
814 rdp.texbufs[0].end = rdp.texbufs[0].begin+tbuf_size;
815 rdp.texbufs[0].count = 0;
816 rdp.texbufs[0].clear_allowed = TRUE;
817 offset_font = tbuf_size;
818 if (voodoo.num_tmu > 1)
820 rdp.texbufs[1].tmu = GR_TMU1;
821 rdp.texbufs[1].begin = voodoo.tex_UMA ? rdp.texbufs[0].end : voodoo.tex_min_addr[GR_TMU1];
822 rdp.texbufs[1].end = rdp.texbufs[1].begin+tbuf_size;
823 rdp.texbufs[1].count = 0;
824 rdp.texbufs[1].clear_allowed = TRUE;
826 offset_font += tbuf_size;
828 offset_texbuf1 = tbuf_size;
835 wxUint32 *data = (wxUint32*)font;
838 // ** Font texture **
839 wxUint8 *tex8 = (wxUint8*)malloc(256*64);
841 fontTex.smallLodLog2 = fontTex.largeLodLog2 = GR_LOD_LOG2_256;
842 fontTex.aspectRatioLog2 = GR_ASPECT_LOG2_4x1;
843 fontTex.format = GR_TEXFMT_ALPHA_8;
846 // Decompression: [1-bit inverse alpha --> 8-bit alpha]
848 for (i=0; i<0x200; i++)
850 // cur = ~*(data++), byteswapped
852 cur = _byteswap_ulong(~*(data++));
855 cur = ((cur&0xFF)<<24)|(((cur>>8)&0xFF)<<16)|(((cur>>16)&0xFF)<<8)|((cur>>24)&0xFF);
858 for (b=0x80000000; b!=0; b>>=1)
860 if (cur&b) *tex8 = 0xFF;
866 grTexDownloadMipMap (GR_TMU0,
867 voodoo.tex_min_addr[GR_TMU0] + offset_font,
868 GR_MIPMAPLEVELMASK_BOTH,
871 offset_cursor = offset_font + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &fontTex);
875 // ** Cursor texture **
877 data = (wxUint32*)cursor;
879 wxUint16 *tex16 = (wxUint16*)malloc(32*32*2);
881 cursorTex.smallLodLog2 = cursorTex.largeLodLog2 = GR_LOD_LOG2_32;
882 cursorTex.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
883 cursorTex.format = GR_TEXFMT_ARGB_1555;
884 cursorTex.data = tex16;
886 // Conversion: [16-bit 1555 (swapped) --> 16-bit 1555]
887 for (i=0; i<0x200; i++)
890 *(tex16++) = (wxUint16)(((cur&0x000000FF)<<8)|((cur&0x0000FF00)>>8));
891 *(tex16++) = (wxUint16)(((cur&0x00FF0000)>>8)|((cur&0xFF000000)>>24));
894 grTexDownloadMipMap (GR_TMU0,
895 voodoo.tex_min_addr[GR_TMU0] + offset_cursor,
896 GR_MIPMAPLEVELMASK_BOTH,
899 // Round to higher 16
900 offset_textures = ((offset_cursor + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &cursorTex))
902 free (cursorTex.data);
905 #ifdef TEXTURE_FILTER
906 void DisplayLoadProgress(const wchar_t *format, ...)
909 wchar_t wbuf[INFO_BUF];
913 va_start(args, format);
914 vswprintf(wbuf, INFO_BUF, format, args);
917 // XXX: convert to multibyte
918 wcstombs(buf, wbuf, INFO_BUF);
923 set_message_combiner ();
924 output (382, 380, 1, "LOADING TEXTURES. PLEASE WAIT...");
925 int len = min (strlen(buf)*8, 1024);
927 output (x, 360, 1, buf);
929 grColorMask (FXTRUE, FXTRUE);
930 grBufferClear (0, 0, 0xFFFF);
937 #ifdef TEXTURE_FILTER
938 wchar_t romname[256];
939 wchar_t foldername[PATH_MAX + 64];
940 wchar_t cachename[PATH_MAX + 64];
945 OPEN_RDP_LOG (); // doesn't matter if opens again; it will check for it
947 VLOG ("InitGfx ()\n");
955 // Select the Glide device
956 grSstSelect (settings.card_id);
958 // Is mirroring allowed?
959 const char *extensions = grGetString (GR_EXTENSION);
961 // Check which SST we are using and initialize stuff
962 // Hiroshi Morii <koolsmoky@users.sourceforge.net>
964 GR_SSTTYPE_VOODOO = 0,
965 GR_SSTTYPE_SST96 = 1,
967 GR_SSTTYPE_Voodoo2 = 3,
968 GR_SSTTYPE_Banshee = 4,
969 GR_SSTTYPE_Voodoo3 = 5,
970 GR_SSTTYPE_Voodoo4 = 6,
971 GR_SSTTYPE_Voodoo5 = 7
973 const char *hardware = grGetString(GR_HARDWARE);
974 unsigned int SST_type = GR_SSTTYPE_VOODOO;
975 if (strstr(hardware, "Rush")) {
976 SST_type = GR_SSTTYPE_SST96;
977 } else if (strstr(hardware, "Voodoo2")) {
978 SST_type = GR_SSTTYPE_Voodoo2;
979 } else if (strstr(hardware, "Voodoo Banshee")) {
980 SST_type = GR_SSTTYPE_Banshee;
981 } else if (strstr(hardware, "Voodoo3")) {
982 SST_type = GR_SSTTYPE_Voodoo3;
983 } else if (strstr(hardware, "Voodoo4")) {
984 SST_type = GR_SSTTYPE_Voodoo4;
985 } else if (strstr(hardware, "Voodoo5")) {
986 SST_type = GR_SSTTYPE_Voodoo5;
988 // 2Mb Texture boundary
989 voodoo.has_2mb_tex_boundary = (SST_type < GR_SSTTYPE_Banshee) && !evoodoo;
990 // use UMA if available
991 voodoo.tex_UMA = FALSE;
993 if (strstr(extensions, " TEXUMA ")) {
994 // we get better texture cache hits with UMA on
995 grEnable(GR_TEXTURE_UMA_EXT);
996 voodoo.tex_UMA = TRUE;
997 LOG ("Using TEXUMA extension.\n");
1000 //TODO-PORT: fullscreen stuff
1001 wxUint32 res_data = settings.res_data;
1002 char strWrapperFullScreenResolutionExt[] = "grWrapperFullScreenResolutionExt";
1005 GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt =
1006 (GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress(strWrapperFullScreenResolutionExt);
1007 if (grWrapperFullScreenResolutionExt) {
1008 wxUint32 _width, _height = 0;
1009 settings.res_data = grWrapperFullScreenResolutionExt(&_width, &_height);
1010 settings.scr_res_x = settings.res_x = _width;
1011 settings.scr_res_y = settings.res_y = _height;
1013 res_data = settings.res_data;
1017 GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt =
1018 (GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress(strWrapperFullScreenResolutionExt);
1019 if (grWrapperFullScreenResolutionExt != NULL)
1022 TODO-port: fix resolutions
1023 settings.res_data = settings.res_data_org;
1024 settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0];
1025 settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1];
1028 res_data = settings.res_data | 0x80000000;
1033 // Select the window
1035 if (fb_hwfbe_enabled)
1037 char strSstWinOpenExt[] ="grSstWinOpenExt";
1038 GRWINOPENEXT grSstWinOpenExt = (GRWINOPENEXT)grGetProcAddress(strSstWinOpenExt);
1039 if (grSstWinOpenExt)
1040 gfx_context = grSstWinOpenExt ((FxU32)NULL,
1043 GR_COLORFORMAT_RGBA,
1044 GR_ORIGIN_UPPER_LEFT,
1045 fb_emulation_enabled?GR_PIXFMT_RGB_565:GR_PIXFMT_ARGB_8888, //32b color is not compatible with fb emulation
1046 2, // Double-buffering
1047 1); // 1 auxillary buffer
1050 gfx_context = grSstWinOpen ((FxU32)NULL,
1053 GR_COLORFORMAT_RGBA,
1054 GR_ORIGIN_UPPER_LEFT,
1055 2, // Double-buffering
1056 1); // 1 auxillary buffer
1060 ERRLOG("Error setting display mode");
1061 // grSstWinClose (gfx_context);
1067 to_fullscreen = FALSE;
1070 // get the # of TMUs available
1071 grGet (GR_NUM_TMU, 4, (FxI32*)&voodoo.num_tmu);
1072 // get maximal texture size
1073 grGet (GR_MAX_TEXTURE_SIZE, 4, (FxI32*)&voodoo.max_tex_size);
1074 voodoo.sup_large_tex = (voodoo.max_tex_size > 256 && !(settings.hacks & hack_PPL));
1079 GetTexAddr = GetTexAddrUMA;
1080 voodoo.tex_min_addr[0] = voodoo.tex_min_addr[1] = grTexMinAddress(GR_TMU0);
1081 voodoo.tex_max_addr[0] = voodoo.tex_max_addr[1] = grTexMaxAddress(GR_TMU0);
1085 GetTexAddr = GetTexAddrNonUMA;
1086 voodoo.tex_min_addr[0] = grTexMinAddress(GR_TMU0);
1087 voodoo.tex_min_addr[1] = grTexMinAddress(GR_TMU1);
1088 voodoo.tex_max_addr[0] = grTexMaxAddress(GR_TMU0);
1089 voodoo.tex_max_addr[1] = grTexMaxAddress(GR_TMU1);
1092 if (strstr (extensions, "TEXMIRROR") && !(settings.hacks&hack_Zelda)) //zelda's trees suffer from hardware mirroring
1093 voodoo.sup_mirroring = 1;
1095 voodoo.sup_mirroring = 0;
1097 if (strstr (extensions, "TEXFMT")) //VSA100 texture format extension
1098 voodoo.sup_32bit_tex = TRUE;
1100 voodoo.sup_32bit_tex = FALSE;
1102 voodoo.gamma_correction = 0;
1103 if (strstr(extensions, "GETGAMMA"))
1104 grGet(GR_GAMMA_TABLE_ENTRIES, sizeof(voodoo.gamma_table_size), &voodoo.gamma_table_size);
1106 if (fb_hwfbe_enabled)
1108 if (char * extstr = (char*)strstr(extensions, "TEXTUREBUFFER"))
1110 if (!strncmp(extstr, "TEXTUREBUFFER", 13))
1112 char strTextureBufferExt[] = "grTextureBufferExt";
1113 grTextureBufferExt = (GRTEXBUFFEREXT) grGetProcAddress(strTextureBufferExt);
1114 char strTextureAuxBufferExt[] = "grTextureAuxBufferExt";
1115 grTextureAuxBufferExt = (GRTEXBUFFEREXT) grGetProcAddress(strTextureAuxBufferExt);
1116 char strAuxBufferExt[] = "grAuxBufferExt";
1117 grAuxBufferExt = (GRAUXBUFFEREXT) grGetProcAddress(strAuxBufferExt);
1121 settings.frame_buffer &= ~fb_hwfbe;
1124 grTextureBufferExt = 0;
1126 grStippleModeExt = (GRSTIPPLE)grStippleMode;
1127 grStipplePatternExt = (GRSTIPPLE)grStipplePattern;
1129 if (grStipplePatternExt)
1130 grStipplePatternExt(settings.stipple_pattern);
1132 // char strKeyPressedExt[] = "grKeyPressedExt";
1133 // grKeyPressed = (FxBool (FX_CALL *)(FxU32))grGetProcAddress (strKeyPressedExt);
1137 #ifdef SIMULATE_VOODOO1
1139 voodoo.sup_mirroring = 0;
1142 #ifdef SIMULATE_BANSHEE
1144 voodoo.sup_mirroring = 1;
1147 grCoordinateSpace (GR_WINDOW_COORDS);
1148 grVertexLayout (GR_PARAM_XY, offsetof(VERTEX,x), GR_PARAM_ENABLE);
1149 grVertexLayout (GR_PARAM_Q, offsetof(VERTEX,q), GR_PARAM_ENABLE);
1150 grVertexLayout (GR_PARAM_Z, offsetof(VERTEX,z), GR_PARAM_ENABLE);
1151 grVertexLayout (GR_PARAM_ST0, offsetof(VERTEX,coord[0]), GR_PARAM_ENABLE);
1152 grVertexLayout (GR_PARAM_ST1, offsetof(VERTEX,coord[2]), GR_PARAM_ENABLE);
1153 grVertexLayout (GR_PARAM_PARGB, offsetof(VERTEX,b), GR_PARAM_ENABLE);
1155 grCullMode(GR_CULL_NEGATIVE);
1157 if (settings.fog) //"FOGCOORD" extension
1159 if (strstr (extensions, "FOGCOORD"))
1162 guFogGenerateLinear (fog_t, 0.0f, 255.0f);//(float)rdp.fog_multiplier + (float)rdp.fog_offset);//256.0f);
1164 for (int i = 63; i > 0; i--)
1166 if (fog_t[i] - fog_t[i-1] > 63)
1168 fog_t[i-1] = fog_t[i] - 63;
1172 // for (int f = 0; f < 64; f++)
1174 // FRDP("fog[%d]=%d->%f\n", f, fog_t[f], guFogTableIndexToW(f));
1177 grVertexLayout (GR_PARAM_FOG_EXT, offsetof(VERTEX,f), GR_PARAM_ENABLE);
1179 else //not supported
1180 settings.fog = FALSE;
1183 grDepthBufferMode (GR_DEPTHBUFFER_ZBUFFER);
1184 grDepthBufferFunction(GR_CMP_LESS);
1185 grDepthMask(FXTRUE);
1187 settings.res_x = settings.scr_res_x;
1188 settings.res_y = settings.scr_res_y;
1194 grCullMode (GR_CULL_DISABLE);
1195 grDepthBufferMode (GR_DEPTHBUFFER_ZBUFFER);
1196 grDepthBufferFunction (GR_CMP_ALWAYS);
1197 grRenderBuffer(GR_BUFFER_BACKBUFFER);
1198 grColorMask (FXTRUE, FXTRUE);
1199 grDepthMask (FXTRUE);
1200 grBufferClear (0, 0, 0xFFFF);
1202 grBufferClear (0, 0, 0xFFFF);
1203 grDepthMask (FXFALSE);
1204 grTexFilterMode (0, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR);
1205 grTexFilterMode (1, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR);
1206 grTexClampMode (0, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP);
1207 grTexClampMode (1, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP);
1208 grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y);
1209 rdp.update |= UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE;
1211 #ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
1212 if (!settings.ghq_use)
1214 settings.ghq_use = settings.ghq_fltr || settings.ghq_enht /*|| settings.ghq_cmpr*/ || settings.ghq_hirs;
1215 if (settings.ghq_use)
1218 int options = texfltr[settings.ghq_fltr]|texenht[settings.ghq_enht]|texcmpr[settings.ghq_cmpr]|texhirs[settings.ghq_hirs];
1219 if (settings.ghq_enht_cmpr)
1220 options |= COMPRESS_TEX;
1221 if (settings.ghq_hirs_cmpr)
1222 options |= COMPRESS_HIRESTEX;
1223 // if (settings.ghq_enht_tile)
1224 // options |= TILE_TEX;
1225 if (settings.ghq_hirs_tile)
1226 options |= TILE_HIRESTEX;
1227 if (settings.ghq_enht_f16bpp)
1228 options |= FORCE16BPP_TEX;
1229 if (settings.ghq_hirs_f16bpp)
1230 options |= FORCE16BPP_HIRESTEX;
1231 if (settings.ghq_enht_gz)
1232 options |= GZ_TEXCACHE;
1233 if (settings.ghq_hirs_gz)
1234 options |= GZ_HIRESTEXCACHE;
1235 if (settings.ghq_cache_save)
1236 options |= (DUMP_TEXCACHE|DUMP_HIRESTEXCACHE);
1237 if (settings.ghq_hirs_let_texartists_fly)
1238 options |= LET_TEXARTISTS_FLY;
1239 if (settings.ghq_hirs_dump)
1240 options |= DUMP_TEX;
1242 ghq_dmptex_toggle_key = 0;
1244 swprintf(romname, sizeof(romname) / sizeof(*romname), L"%hs", rdp.RomName);
1245 swprintf(foldername, sizeof(foldername) / sizeof(*foldername), L"%hs", ConfigGetUserDataPath());
1246 swprintf(cachename, sizeof(cachename) / sizeof(*cachename), L"%hs", ConfigGetUserCachePath());
1248 settings.ghq_use = (int)ext_ghq_init(voodoo.max_tex_size, // max texture width supported by hardware
1249 voodoo.max_tex_size, // max texture height supported by hardware
1250 voodoo.sup_32bit_tex?32:16, // max texture bpp supported by hardware
1252 settings.ghq_cache_size * 1024*1024, // cache texture to system memory
1255 romname, // name of ROM. must be no longer than 256 characters
1256 DisplayLoadProgress);
1259 if (settings.ghq_use && strstr (extensions, "TEXMIRROR"))
1260 voodoo.sup_mirroring = 1;
1268 VLOG("ReleaseGfx ()\n");
1270 // Restore gamma settings
1271 if (voodoo.gamma_correction)
1273 if (voodoo.gamma_table_r)
1274 grLoadGammaTable(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b);
1276 guGammaCorrectionRGB(1.3f, 1.3f, 1.3f); //1.3f is default 3dfx gamma for everything but desktop
1277 voodoo.gamma_correction = 0;
1281 grSstWinClose (gfx_context);
1287 rdp.window_changed = TRUE;
1290 // new API code begins here!
1296 EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front)
1298 VLOG("CALL ReadScreen2 ()\n");
1299 *width = settings.res_x;
1300 *height = settings.res_y;
1303 BYTE * line = (BYTE*)dest;
1306 for (wxUint32 y=0; y<settings.res_y; y++)
1308 for (wxUint32 x=0; x<settings.res_x; x++)
1315 // LOG ("ReadScreen. not in the fullscreen!\n");
1316 WARNLOG("[Glide64] Cannot save screenshot in windowed mode?\n");
1322 info.size = sizeof(GrLfbInfo_t);
1323 if (grLfbLock (GR_LFB_READ_ONLY,
1324 GR_BUFFER_FRONTBUFFER,
1325 GR_LFBWRITEMODE_888,
1326 GR_ORIGIN_UPPER_LEFT,
1330 // Copy the screen, let's hope this works.
1331 for (wxUint32 y=0; y<settings.res_y; y++)
1333 BYTE *ptr = (BYTE*) info.lfbPtr + (info.strideInBytes * y);
1334 for (wxUint32 x=0; x<settings.res_x; x++)
1336 line[x*3] = ptr[2]; // red
1337 line[x*3+1] = ptr[1]; // green
1338 line[x*3+2] = ptr[0]; // blue
1341 line += settings.res_x * 3;
1344 // Unlock the frontbuffer
1345 grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER);
1347 VLOG ("ReadScreen. Success.\n");
1351 EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
1352 void (*DebugCallback)(void *, int, const char *))
1354 VLOG("CALL PluginStartup ()\n");
1355 l_DebugCallback = DebugCallback;
1356 l_DebugCallContext = Context;
1358 /* attach and call the CoreGetAPIVersions function, check Config and Video Extension API versions for compatibility */
1359 ptr_CoreGetAPIVersions CoreAPIVersionFunc;
1360 CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) osal_dynlib_getproc(CoreLibHandle, "CoreGetAPIVersions");
1361 if (CoreAPIVersionFunc == NULL)
1363 ERRLOG("Core emulator broken; no CoreAPIVersionFunc() function found.");
1364 return M64ERR_INCOMPATIBLE;
1366 int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion;
1367 (*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL);
1368 if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000))
1370 ERRLOG("Emulator core Config API incompatible with this plugin");
1371 return M64ERR_INCOMPATIBLE;
1373 if ((VidextAPIVersion & 0xffff0000) != (VIDEXT_API_VERSION & 0xffff0000))
1375 ERRLOG("Emulator core Video Extension API incompatible with this plugin");
1376 return M64ERR_INCOMPATIBLE;
1379 ConfigOpenSection = (ptr_ConfigOpenSection) osal_dynlib_getproc(CoreLibHandle, "ConfigOpenSection");
1380 ConfigSetParameter = (ptr_ConfigSetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigSetParameter");
1381 ConfigGetParameter = (ptr_ConfigGetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParameter");
1382 ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultInt");
1383 ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultFloat");
1384 ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultBool");
1385 ConfigSetDefaultString = (ptr_ConfigSetDefaultString) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultString");
1386 ConfigGetParamInt = (ptr_ConfigGetParamInt) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamInt");
1387 ConfigGetParamFloat = (ptr_ConfigGetParamFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamFloat");
1388 ConfigGetParamBool = (ptr_ConfigGetParamBool) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamBool");
1389 ConfigGetParamString = (ptr_ConfigGetParamString) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamString");
1391 ConfigGetSharedDataFilepath = (ptr_ConfigGetSharedDataFilepath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetSharedDataFilepath");
1392 ConfigGetUserConfigPath = (ptr_ConfigGetUserConfigPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserConfigPath");
1393 ConfigGetUserDataPath = (ptr_ConfigGetUserDataPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserDataPath");
1394 ConfigGetUserCachePath = (ptr_ConfigGetUserCachePath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserCachePath");
1396 if (!ConfigOpenSection || !ConfigSetParameter || !ConfigGetParameter ||
1397 !ConfigSetDefaultInt || !ConfigSetDefaultFloat || !ConfigSetDefaultBool || !ConfigSetDefaultString ||
1398 !ConfigGetParamInt || !ConfigGetParamFloat || !ConfigGetParamBool || !ConfigGetParamString ||
1399 !ConfigGetSharedDataFilepath || !ConfigGetUserConfigPath || !ConfigGetUserDataPath || !ConfigGetUserCachePath)
1401 ERRLOG("Couldn't connect to Core configuration functions");
1402 return M64ERR_INCOMPATIBLE;
1405 /* Get the core Video Extension function pointers from the library handle */
1406 CoreVideo_Init = (ptr_VidExt_Init) osal_dynlib_getproc(CoreLibHandle, "VidExt_Init");
1407 CoreVideo_Quit = (ptr_VidExt_Quit) osal_dynlib_getproc(CoreLibHandle, "VidExt_Quit");
1408 CoreVideo_ListFullscreenModes = (ptr_VidExt_ListFullscreenModes) osal_dynlib_getproc(CoreLibHandle, "VidExt_ListFullscreenModes");
1409 CoreVideo_SetVideoMode = (ptr_VidExt_SetVideoMode) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetVideoMode");
1410 CoreVideo_SetCaption = (ptr_VidExt_SetCaption) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetCaption");
1411 CoreVideo_ToggleFullScreen = (ptr_VidExt_ToggleFullScreen) osal_dynlib_getproc(CoreLibHandle, "VidExt_ToggleFullScreen");
1412 CoreVideo_ResizeWindow = (ptr_VidExt_ResizeWindow) osal_dynlib_getproc(CoreLibHandle, "VidExt_ResizeWindow");
1413 CoreVideo_GL_GetProcAddress = (ptr_VidExt_GL_GetProcAddress) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_GetProcAddress");
1414 CoreVideo_GL_SetAttribute = (ptr_VidExt_GL_SetAttribute) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SetAttribute");
1415 CoreVideo_GL_SwapBuffers = (ptr_VidExt_GL_SwapBuffers) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SwapBuffers");
1417 if (!CoreVideo_Init || !CoreVideo_Quit || !CoreVideo_ListFullscreenModes || !CoreVideo_SetVideoMode ||
1418 !CoreVideo_SetCaption || !CoreVideo_ToggleFullScreen || !CoreVideo_ResizeWindow || !CoreVideo_GL_GetProcAddress ||
1419 !CoreVideo_GL_SetAttribute || !CoreVideo_GL_SwapBuffers)
1421 ERRLOG("Couldn't connect to Core video functions");
1422 return M64ERR_INCOMPATIBLE;
1425 const char *configDir = ConfigGetSharedDataFilepath("Glide64mk2.ini");
1428 SetConfigDir(configDir);
1430 return M64ERR_SUCCESS;
1434 ERRLOG("Couldn't find Glide64mk2.ini");
1435 return M64ERR_FILES;
1439 EXPORT m64p_error CALL PluginShutdown(void)
1441 VLOG("CALL PluginShutdown ()\n");
1442 return M64ERR_SUCCESS;
1445 EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
1447 VLOG("CALL PluginGetVersion ()\n");
1448 /* set version info */
1449 if (PluginType != NULL)
1450 *PluginType = M64PLUGIN_GFX;
1452 if (PluginVersion != NULL)
1453 *PluginVersion = PLUGIN_VERSION;
1455 if (APIVersion != NULL)
1456 *APIVersion = VIDEO_PLUGIN_API_VERSION;
1458 if (PluginNamePtr != NULL)
1459 *PluginNamePtr = PLUGIN_NAME;
1461 if (Capabilities != NULL)
1466 return M64ERR_SUCCESS;
1469 /******************************************************************
1470 Function: CaptureScreen
1471 Purpose: This function dumps the current frame to a file
1472 input: pointer to the directory to save the file to
1474 *******************************************************************/
1475 EXPORT void CALL CaptureScreen ( char * Directory )
1478 strcpy (capture_path, Directory);
1481 /******************************************************************
1482 Function: ChangeWindow
1483 Purpose: to change the window between fullscreen and window
1484 mode. If the window was in fullscreen this should
1485 change the screen to window mode and vice vesa.
1488 *******************************************************************/
1489 //#warning ChangeWindow unimplemented
1490 EXPORT void CALL ChangeWindow (void)
1492 VLOG ("ChangeWindow()\n");
1498 to_fullscreen = TRUE;
1499 ev_fullscreen = TRUE;
1502 ShowWindow( gfx.hStatusBar, SW_HIDE );
1503 ShowCursor( FALSE );
1508 ev_fullscreen = FALSE;
1513 ShowWindow( gfx.hStatusBar, SW_SHOW );
1514 SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
1520 // Go to fullscreen at next dlist
1521 // This is for compatibility with 1964, which reloads the plugin
1522 // when switching to fullscreen
1525 to_fullscreen = TRUE;
1528 ShowWindow( gfx.hStatusBar, SW_HIDE );
1529 ShowCursor( FALSE );
1538 ShowWindow( gfx.hStatusBar, SW_SHOW );
1539 // SetWindowLong fixes the following Windows XP Banshee issues:
1540 // 1964 crash error when loading another rom.
1541 // All N64 emu's minimize, restore crashes.
1542 SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
1549 /******************************************************************
1551 Purpose: This function is called when the emulator is closing
1552 down allowing the dll to de-initialise.
1555 *******************************************************************/
1556 void CALL CloseDLL (void)
1558 VLOG ("CloseDLL ()\n");
1560 // re-set the old window proc
1561 #ifdef WINPROC_OVERRIDE
1562 SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
1566 if (hhkLowLevelKybd)
1568 UnhookWindowsHookEx(hhkLowLevelKybd);
1569 hhkLowLevelKybd = 0;
1575 #ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
1576 if (settings.ghq_use)
1579 settings.ghq_use = 0;
1586 delete[] voodoo.gamma_table_r;
1587 voodoo.gamma_table_r = 0;
1588 delete[] voodoo.gamma_table_g;
1589 voodoo.gamma_table_g = 0;
1590 delete[] voodoo.gamma_table_b;
1591 voodoo.gamma_table_b = 0;
1594 /******************************************************************
1596 Purpose: This function is optional function that is provided
1597 to allow the user to test the dll
1598 input: a handle to the window that calls this function
1600 *******************************************************************/
1601 void CALL DllTest ( HWND hParent )
1605 /******************************************************************
1606 Function: DrawScreen
1607 Purpose: This function is called when the emulator receives a
1608 WM_PAINT message. This allows the gfx to fit in when
1609 it is being used in the desktop.
1612 *******************************************************************/
1613 void CALL DrawScreen (void)
1615 VLOG ("DrawScreen ()\n");
1618 /******************************************************************
1619 Function: GetDllInfo
1620 Purpose: This function allows the emulator to gather information
1621 about the dll by filling in the PluginInfo structure.
1622 input: a pointer to a PLUGIN_INFO stucture that needs to be
1623 filled by the function. (see def above)
1625 *******************************************************************/
1626 void CALL GetDllInfo ( PLUGIN_INFO * PluginInfo )
1628 VLOG ("GetDllInfo ()\n");
1629 PluginInfo->Version = 0x0103; // Set to 0x0103
1630 PluginInfo->Type = PLUGIN_TYPE_GFX; // Set to PLUGIN_TYPE_GFX
1631 sprintf (PluginInfo->Name, "Glide64mk2 " G64_VERSION RELTIME); // Name of the DLL
1633 // If DLL supports memory these memory options then set them to TRUE or FALSE
1634 // if it does not support it
1635 PluginInfo->NormalMemory = TRUE; // a normal wxUint8 array
1636 PluginInfo->MemoryBswaped = TRUE; // a normal wxUint8 array where the memory has been pre
1637 // bswap on a dword (32 bits) boundry
1641 BOOL WINAPI QueryPerformanceCounter(PLARGE_INTEGER counter)
1645 /* generic routine */
1646 gettimeofday( &tv, NULL );
1647 counter->QuadPart = (LONGLONG)tv.tv_usec + (LONGLONG)tv.tv_sec * 1000000;
1651 BOOL WINAPI QueryPerformanceFrequency(PLARGE_INTEGER frequency)
1653 frequency->s.LowPart= 1000000;
1654 frequency->s.HighPart= 0;
1659 /******************************************************************
1660 Function: InitiateGFX
1661 Purpose: This function is called when the DLL is started to give
1662 information from the emulator that the n64 graphics
1663 uses. This is not called from the emulation thread.
1664 Input: Gfx_Info is passed to this function which is defined
1666 Output: TRUE on success
1667 FALSE on failure to initialise
1669 ** note on interrupts **:
1670 To generate an interrupt set the appropriate bit in MI_INTR_REG
1671 and then call the function CheckInterrupts to tell the emulator
1672 that there is a waiting interrupt.
1673 *******************************************************************/
1675 EXPORT int CALL InitiateGFX (GFX_INFO Gfx_Info)
1677 VLOG ("InitiateGFX (*)\n");
1680 // Assume scale of 1 for debug purposes
1684 memset (&settings, 0, sizeof(SETTINGS));
1686 char name[21] = "DEFAULT";
1687 ReadSpecialSettings (name);
1688 settings.res_data_org = settings.res_data;
1690 QueryPerformanceFrequency (&perf_freq);
1691 QueryPerformanceCounter (&fps_last);
1694 debug_init (); // Initialize debugger
1698 #ifdef WINPROC_OVERRIDE
1699 // [H.Morii] inject our own winproc so that "alt-enter to fullscreen"
1700 // message is shown when the emulator window is activated.
1701 WNDPROC curWndProc = (WNDPROC)GetWindowLong(gfx.hWnd, GWL_WNDPROC);
1702 if (curWndProc && curWndProc != (WNDPROC)WndProc) {
1703 oldWndProc = (WNDPROC)SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)WndProc);
1712 if (fb_depth_render_enabled)
1715 char strConfigWrapperExt[] = "grConfigWrapperExt";
1716 GRCONFIGWRAPPEREXT grConfigWrapperExt = (GRCONFIGWRAPPEREXT)grGetProcAddress(strConfigWrapperExt);
1717 if (grConfigWrapperExt)
1718 grConfigWrapperExt(settings.wrpResolution, settings.wrpVRAM * 1024 * 1024, settings.wrpFBO, settings.wrpAnisotropic);
1722 const char *extensions = grGetString (GR_EXTENSION);
1724 if (strstr (extensions, "EVOODOO"))
1727 voodoo.has_2mb_tex_boundary = 0;
1731 voodoo.has_2mb_tex_boundary = 1;
1737 /******************************************************************
1738 Function: MoveScreen
1739 Purpose: This function is called in response to the emulator
1740 receiving a WM_MOVE passing the xpos and ypos passed
1742 input: xpos - the x-coordinate of the upper-left corner of the
1743 client area of the window.
1744 ypos - y-coordinate of the upper-left corner of the
1745 client area of the window.
1747 *******************************************************************/
1748 EXPORT void CALL MoveScreen (int xpos, int ypos)
1750 rdp.window_changed = TRUE;
1753 /******************************************************************
1754 Function: ResizeVideoOutput
1755 Purpose: This function is called to force us to resize our output OpenGL window.
1756 This is currently unsupported, and should never be called because we do
1757 not pass the RESIZABLE flag to VidExt_SetVideoMode when initializing.
1758 input: new width and height
1760 *******************************************************************/
1761 EXPORT void CALL ResizeVideoOutput(int Width, int Height)
1765 /******************************************************************
1767 Purpose: This function is called when a rom is closed.
1770 *******************************************************************/
1771 EXPORT void CALL RomClosed (void)
1773 VLOG ("RomClosed ()\n");
1774 printf("RomClosed ()\n");
1778 rdp.window_changed = TRUE;
1780 // if (fullscreen && evoodoo)//*SEB*
1784 static void CheckDRAMSize()
1789 test = gfx.RDRAM[0x007FFFFF] + 1;
1800 sprintf (out_buf, "Detected RDRAM size: %08lx\n", BMASK);
1805 /******************************************************************
1807 Purpose: This function is called when a rom is open. (from the
1811 *******************************************************************/
1812 EXPORT int CALL RomOpen (void)
1814 VLOG ("RomOpen ()\n");
1817 ucode_error_report = TRUE; // allowed to report ucode errors
1820 // Get the country code & translate to NTSC(0) or PAL(1)
1821 wxUint16 code = ((wxUint16*)gfx.HEADER)[0x1F^1];
1823 if (code == 0x4400) region = 1; // Germany (PAL)
1824 if (code == 0x4500) region = 0; // USA (NTSC)
1825 if (code == 0x4A00) region = 0; // Japan (NTSC)
1826 if (code == 0x5000) region = 1; // Europe (PAL)
1827 if (code == 0x5500) region = 0; // Australia (NTSC)
1830 frameSkipper.setTargetFPS(region == 1 ? 50 : 60);
1833 char name[21] = "DEFAULT";
1834 ReadSpecialSettings (name);
1836 // get the name of the ROM
1837 for (int i=0; i<20; i++)
1838 name[i] = gfx.HEADER[(32+i)^3];
1841 // remove all trailing spaces
1842 while (name[strlen(name)-1] == ' ')
1843 name[strlen(name)-1] = 0;
1845 strncpy(rdp.RomName, name, sizeof(name));
1846 ReadSpecialSettings (name);
1855 // ** EVOODOO EXTENSIONS **
1861 const char *extensions = grGetString (GR_EXTENSION);
1866 if (strstr (extensions, "EVOODOO"))
1875 if (strstr (extensions, "ROMNAME"))
1877 char strSetRomName[] = "grSetRomName";
1878 void (FX_CALL *grSetRomName)(char*);
1879 grSetRomName = (void (FX_CALL *)(char*))grGetProcAddress (strSetRomName);
1880 grSetRomName (name);
1886 EXPORT void CALL RomResumed(void)
1889 frameSkipper.start();
1893 /******************************************************************
1895 Purpose: Useally once Dlists are started being displayed, cfb is
1896 ignored. This function tells the dll to start displaying
1900 *******************************************************************/
1901 bool no_dlist = true;
1902 EXPORT void CALL ShowCFB (void)
1905 VLOG ("ShowCFB ()\n");
1908 EXPORT void CALL SetRenderingCallback(void (*callback)(int))
1910 VLOG("CALL SetRenderingCallback (*)\n");
1911 renderCallback = callback;
1916 LRDP("drawViRegBG\n");
1917 const wxUint32 VIwidth = *gfx.VI_WIDTH_REG;
1918 FB_TO_SCREEN_INFO fb_info;
1919 fb_info.width = VIwidth;
1920 fb_info.height = (wxUint32)rdp.vi_height;
1921 if (fb_info.height == 0)
1923 LRDP("Image height = 0 - skipping\n");
1928 fb_info.lr_x = VIwidth - 1;
1929 // fb_info.lr_x = (wxUint32)rdp.vi_width - 1;
1931 fb_info.lr_y = fb_info.height - 1;
1933 fb_info.addr = *gfx.VI_ORIGIN_REG;
1934 fb_info.size = *gfx.VI_STATUS_REG & 3;
1935 rdp.last_bg = fb_info.addr;
1937 bool drawn = DrawFrameBufferToScreen(fb_info);
1938 if (settings.hacks&hack_Lego && drawn)
1940 rdp.updatescreen = 1;
1942 DrawFrameBufferToScreen(fb_info);
1948 void drawNoFullscreenMessage();
1950 void DrawFrameBuffer ()
1954 drawNoFullscreenMessage();
1961 grDepthMask (FXTRUE);
1962 grColorMask (FXTRUE, FXTRUE);
1963 grBufferClear (0, 0, 0xFFFF);
1969 /******************************************************************
1970 Function: UpdateScreen
1971 Purpose: This function is called in response to a vsync of the
1972 screen were the VI bit in MI_INTR_REG has already been
1976 *******************************************************************/
1977 wxUint32 update_screen_count = 0;
1978 EXPORT void CALL UpdateScreen (void)
1981 //printf("UpdateScreen()\n");
1982 frameSkipper.update();
1985 if (CheckKeyPressed(G64_VK_SPACE, 0x0001))
1991 sprintf (out_buf, "UpdateScreen (). Origin: %08x, Old origin: %08x, width: %d\n", *gfx.VI_ORIGIN_REG, rdp.vi_org_reg, *gfx.VI_WIDTH_REG);
1995 wxUint32 width = (*gfx.VI_WIDTH_REG) << 1;
1996 if (fullscreen && (*gfx.VI_ORIGIN_REG > width))
1997 update_screen_count++;
1998 //TODO-PORT: wx times
2000 // vertical interrupt has occurred, increment counter
2003 // Check frames per second
2004 LARGE_INTEGER difference;
2005 QueryPerformanceCounter (&fps_next);
2006 difference.QuadPart = fps_next.QuadPart - fps_last.QuadPart;
2007 float diff_secs = (float)((double)difference.QuadPart / (double)perf_freq.QuadPart);
2008 if (diff_secs > 0.5f)
2010 fps = (float)(fps_count / diff_secs);
2011 vi = (float)(vi_count / diff_secs);
2012 ntsc_percent = vi / 0.6f;
2013 pal_percent = vi / 0.5f;
2014 fps_last = fps_next;
2020 wxUint32 limit = (settings.hacks&hack_Lego) ? 15 : 30;
2022 if (frameSkipper.willSkipNext())
2026 // if (!frameSkipper.hasSkipped())
2027 if (!frameSkipper.willSkipNext())
2029 if ((settings.frame_buffer&fb_cpu_write_hack) && (update_screen_count > limit) && (rdp.last_bg == 0))
2031 LRDP("DirectCPUWrite hack!\n");
2032 update_screen_count = 0;
2042 if( *gfx.VI_ORIGIN_REG > width )
2045 LRDP("ChangeSize done\n");
2047 if (!frameSkipper.willSkipNext())
2050 LRDP("DrawFrameBuffer done\n");
2051 rdp.updatescreen = 1;
2058 if (!frameSkipper.willSkipNext())
2060 if (settings.swapmode == 0)
2064 static void DrawWholeFrameBufferToScreen()
2066 static wxUint32 toScreenCI = 0;
2067 if (rdp.ci_width < 200)
2069 if (rdp.cimg == toScreenCI)
2071 toScreenCI = rdp.cimg;
2072 FB_TO_SCREEN_INFO fb_info;
2073 fb_info.addr = rdp.cimg;
2074 fb_info.size = rdp.ci_size;
2075 fb_info.width = rdp.ci_width;
2076 fb_info.height = rdp.ci_height;
2077 if (fb_info.height == 0)
2080 fb_info.lr_x = rdp.ci_width-1;
2082 fb_info.lr_y = rdp.ci_height-1;
2084 DrawFrameBufferToScreen(fb_info);
2085 if (!(settings.frame_buffer & fb_ref))
2086 memset(gfx.RDRAM+rdp.cimg, 0, (rdp.ci_width*rdp.ci_height)<<rdp.ci_size>>1);
2089 static void GetGammaTable()
2091 char strGetGammaTableExt[] = "grGetGammaTableExt";
2092 void (FX_CALL *grGetGammaTableExt)(FxU32, FxU32*, FxU32*, FxU32*) =
2093 (void (FX_CALL *)(FxU32, FxU32*, FxU32*, FxU32*))grGetProcAddress(strGetGammaTableExt);
2094 if (grGetGammaTableExt)
2096 voodoo.gamma_table_r = new FxU32[voodoo.gamma_table_size];
2097 voodoo.gamma_table_g = new FxU32[voodoo.gamma_table_size];
2098 voodoo.gamma_table_b = new FxU32[voodoo.gamma_table_size];
2099 grGetGammaTableExt(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b);
2104 wxUint32 curframe = 0;
2105 void newSwapBuffers()
2108 //frameSkipper.newFrame();
2109 //bool skipped = false;
2110 //printf("newSwapBuffers()\n");
2111 bool skipped = frameSkipper.willSkipNext();
2112 //bool skipped = frameSkipper.hasSkipped();
2114 if (!rdp.updatescreen) {
2117 if (settings.frame_buffer & fb_read_back_to_screen2)
2118 DrawWholeFrameBufferToScreen();
2119 frameSkipper.newFrame();
2125 rdp.updatescreen = 0;
2129 // Allow access to the whole screen
2132 rdp.update |= UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE;
2133 grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y);
2134 grDepthBufferFunction (GR_CMP_ALWAYS);
2135 grDepthMask (FXFALSE);
2136 grCullMode (GR_CULL_DISABLE);
2138 if ((settings.show_fps & 0xF) || settings.clock)
2139 set_message_combiner ();
2141 float y = (float)settings.res_y;
2142 if (settings.show_fps & 0x0F)
2144 if (settings.show_fps & 4)
2147 output (0, y, 0, "%d%% ", (int)pal_percent);
2149 output (0, y, 0, "%d%% ", (int)ntsc_percent);
2152 if (settings.show_fps & 2)
2154 output (0, y, 0, "VI/s: %.02f ", vi);
2157 if (settings.show_fps & 1)
2158 output (0, y, 0, "FPS: %.02f ", fps);
2164 if (settings.clock_24_hr)
2168 tm *cur_time = localtime (<ime);
2170 sprintf (out_buf, "%.2d:%.2d:%.2d", cur_time->tm_hour, cur_time->tm_min, cur_time->tm_sec);
2178 tm *cur_time = localtime (<ime);
2180 if (cur_time->tm_hour >= 12)
2182 strcpy (ampm, "PM");
2183 if (cur_time->tm_hour != 12)
2184 cur_time->tm_hour -= 12;
2186 if (cur_time->tm_hour == 0)
2187 cur_time->tm_hour = 12;
2189 if (cur_time->tm_hour >= 10)
2190 sprintf (out_buf, "%.5s %s", asctime(cur_time) + 11, ampm);
2192 sprintf (out_buf, " %.4s %s", asctime(cur_time) + 12, ampm);
2194 output ((float)(settings.res_x - 68), y, 0, out_buf, 0);
2197 if (CheckKeyPressed(G64_VK_BACK, 0x0001))
2199 hotkey_info.hk_filtering = 100;
2200 if (settings.filtering < 2)
2201 settings.filtering++;
2203 settings.filtering = 0;
2205 if ((abs((int)(frame_count - curframe)) > 3 ) && CheckKeyPressed(G64_VK_ALT, 0x8000)) //alt +
2207 if (CheckKeyPressed(G64_VK_B, 0x8000)) //b
2209 hotkey_info.hk_motionblur = 100;
2210 hotkey_info.hk_ref = 0;
2211 curframe = frame_count;
2212 settings.frame_buffer ^= fb_motionblur;
2214 else if (CheckKeyPressed(G64_VK_V, 0x8000)) //v
2216 hotkey_info.hk_ref = 100;
2217 hotkey_info.hk_motionblur = 0;
2218 curframe = frame_count;
2219 settings.frame_buffer ^= fb_ref;
2222 if (settings.buff_clear && (hotkey_info.hk_ref || hotkey_info.hk_motionblur || hotkey_info.hk_filtering))
2224 set_message_combiner ();
2228 if (hotkey_info.hk_ref)
2230 if (settings.frame_buffer & fb_ref)
2231 message = strcat(buf, "FB READ ALWAYS: ON");
2233 message = strcat(buf, "FB READ ALWAYS: OFF");
2234 hotkey_info.hk_ref--;
2236 if (hotkey_info.hk_motionblur)
2238 if (settings.frame_buffer & fb_motionblur)
2239 message = strcat(buf, " MOTION BLUR: ON");
2241 message = strcat(buf, " MOTION BLUR: OFF");
2242 hotkey_info.hk_motionblur--;
2244 if (hotkey_info.hk_filtering)
2246 switch (settings.filtering)
2249 message = strcat(buf, " FILTERING MODE: AUTOMATIC");
2252 message = strcat(buf, " FILTERING MODE: FORCE BILINEAR");
2255 message = strcat(buf, " FILTERING MODE: FORCE POINT-SAMPLED");
2258 hotkey_info.hk_filtering--;
2260 output (120.0f, (float)settings.res_y, 0, message, 0);
2267 // Make the directory if it doesn't exist
2268 if (!wxDirExists(capture_path))
2269 wxMkdir(capture_path);
2271 wxString romName = rdp.RomName;
2272 romName.Replace(wxT(" "), wxT("_"), true);
2273 romName.Replace(wxT(":"), wxT(";"), true);
2275 for (int i=1; ; i++)
2277 path = capture_path;
2278 path += wxT("Glide64mk2_");
2283 path << i << wxT(".") << ScreenShotFormats[settings.ssformat].extension;
2284 if (!wxFileName::FileExists(path))
2288 const wxUint32 offset_x = (wxUint32)rdp.offset_x;
2289 const wxUint32 offset_y = (wxUint32)rdp.offset_y;
2290 const wxUint32 image_width = settings.scr_res_x - offset_x*2;
2291 const wxUint32 image_height = settings.scr_res_y - offset_y*2;
2294 info.size = sizeof(GrLfbInfo_t);
2295 if (grLfbLock (GR_LFB_READ_ONLY,
2296 GR_BUFFER_BACKBUFFER,
2297 GR_LFBWRITEMODE_565,
2298 GR_ORIGIN_UPPER_LEFT,
2302 wxUint8 *ssimg = (wxUint8*)malloc(image_width * image_height * 3); // will be free in wxImage destructor
2304 wxUint32 offset_src = info.strideInBytes * offset_y;
2307 if (info.writeMode == GR_LFBWRITEMODE_8888)
2310 for (wxUint32 y = 0; y < image_height; y++)
2312 wxUint32 *ptr = (wxUint32*)((wxUint8*)info.lfbPtr + offset_src);
2314 for (wxUint32 x = 0; x < image_width; x++)
2317 ssimg[sspos++] = (wxUint8)((col >> 16) & 0xFF);
2318 ssimg[sspos++] = (wxUint8)((col >> 8) & 0xFF);
2319 ssimg[sspos++] = (wxUint8)(col & 0xFF);
2321 offset_src += info.strideInBytes;
2327 for (wxUint32 y = 0; y < image_height; y++)
2329 wxUint16 *ptr = (wxUint16*)((wxUint8*)info.lfbPtr + offset_src);
2331 for (wxUint32 x = 0; x < image_width; x++)
2334 ssimg[sspos++] = (wxUint8)((float)(col >> 11) / 31.0f * 255.0f);
2335 ssimg[sspos++] = (wxUint8)((float)((col >> 5) & 0x3F) / 63.0f * 255.0f);
2336 ssimg[sspos++] = (wxUint8)((float)(col & 0x1F) / 31.0f * 255.0f);
2338 offset_src += info.strideInBytes;
2341 // Unlock the backbuffer
2342 grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER);
2343 wxImage screenshot(image_width, image_height, ssimg);
2344 screenshot.SaveFile(path, ScreenShotFormats[settings.ssformat].type);
2350 // Capture the screen if debug capture is set
2351 if (_debugger.capture)
2353 // Allocate the screen
2354 _debugger.screen = new wxUint8 [(settings.res_x*settings.res_y) << 1];
2356 // Lock the backbuffer (already rendered)
2358 info.size = sizeof(GrLfbInfo_t);
2359 while (!grLfbLock (GR_LFB_READ_ONLY,
2360 GR_BUFFER_BACKBUFFER,
2361 GR_LFBWRITEMODE_565,
2362 GR_ORIGIN_UPPER_LEFT,
2366 wxUint32 offset_src=0, offset_dst=0;
2369 for (wxUint32 y=0; y<settings.res_y; y++)
2371 if (info.writeMode == GR_LFBWRITEMODE_8888)
2373 wxUint32 *src = (wxUint32*)((wxUint8*)info.lfbPtr + offset_src);
2374 wxUint16 *dst = (wxUint16*)(_debugger.screen + offset_dst);
2377 for (unsigned int x = 0; x < settings.res_x; x++)
2380 r = (wxUint8)((col >> 19) & 0x1F);
2381 g = (wxUint8)((col >> 10) & 0x3F);
2382 b = (wxUint8)((col >> 3) & 0x1F);
2383 dst[x] = (r<<11)|(g<<5)|b;
2388 memcpy (_debugger.screen + offset_dst, (wxUint8*)info.lfbPtr + offset_src, settings.res_x << 1);
2390 offset_dst += settings.res_x << 1;
2391 offset_src += info.strideInBytes;
2394 // Unlock the backbuffer
2395 grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER);
2398 if (fullscreen && debugging)
2401 debug_cacheviewer ();
2408 if (settings.frame_buffer & fb_read_back_to_screen)
2409 DrawWholeFrameBufferToScreen();
2413 if (fb_hwfbe_enabled && !(settings.hacks&hack_RE2) && !evoodoo)
2414 grAuxBufferExt( GR_BUFFER_AUXBUFFER );
2423 grBufferSwap (settings.vsync);
2429 if (*gfx.VI_STATUS_REG&0x08) //gamma correction is used
2431 if (!voodoo.gamma_correction)
2433 if (voodoo.gamma_table_size && !voodoo.gamma_table_r)
2434 GetGammaTable(); //save initial gamma tables
2435 guGammaCorrectionRGB(2.0f, 2.0f, 2.0f); //with gamma=2.0 gamma table is the same, as in N64
2436 voodoo.gamma_correction = 1;
2441 if (voodoo.gamma_correction)
2443 if (voodoo.gamma_table_r)
2444 grLoadGammaTable(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b);
2446 guGammaCorrectionRGB(1.3f, 1.3f, 1.3f); //1.3f is default 3dfx gamma for everything but desktop
2447 voodoo.gamma_correction = 0;
2452 if (_debugger.capture)
2460 if (debugging || settings.wireframe || settings.buff_clear || (settings.hacks&hack_PPL && settings.ucode == 6))
2462 if (settings.hacks&hack_RE2 && fb_depth_render_enabled)
2463 grDepthMask (FXFALSE);
2465 grDepthMask (FXTRUE);
2466 grBufferClear (0, 0, 0xFFFF);
2468 /* //let the game to clear the buffers
2471 grDepthMask (FXTRUE);
2472 grColorMask (FXFALSE, FXFALSE);
2473 grBufferClear (0, 0, 0xFFFF);
2474 grColorMask (FXTRUE, FXTRUE);
2482 if (settings.frame_buffer & fb_read_back_to_screen2)
2483 DrawWholeFrameBufferToScreen();
2487 frameSkipper.newFrame();
2490 // Open/close debugger?
2491 if (CheckKeyPressed(G64_VK_SCROLL, 0x0001))
2495 //if (settings.scr_res_x == 1024 && settings.scr_res_y == 768)
2499 // Recalculate screen size, don't resize screen
2500 settings.res_x = (wxUint32)(settings.scr_res_x * 0.625f);
2501 settings.res_y = (wxUint32)(settings.scr_res_y * 0.625f);
2510 settings.res_x = settings.scr_res_x;
2511 settings.res_y = settings.scr_res_y;
2518 if (/*fullscreen && */debugging && CheckKeyPressed(G64_VK_INSERT, 0x0001))
2520 _debugger.capture = 1;
2527 /******************************************************************
2528 Function: ViStatusChanged
2529 Purpose: This function is called to notify the dll that the
2530 ViStatus registers value has been changed.
2533 *******************************************************************/
2534 EXPORT void CALL ViStatusChanged (void)
2538 /******************************************************************
2539 Function: ViWidthChanged
2540 Purpose: This function is called to notify the dll that the
2541 ViWidth registers value has been changed.
2544 *******************************************************************/
2545 EXPORT void CALL ViWidthChanged (void)
2549 #ifdef WINPROC_OVERRIDE
2550 LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2554 case WM_ACTIVATEAPP:
2555 if (wParam == TRUE && !fullscreen) rdp.window_changed = TRUE;
2558 if (!fullscreen) rdp.window_changed = TRUE;
2562 SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
2566 return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam);
2572 int CheckKeyPressed(int key, int mask)
2574 static Glide64Keys g64Keys;
2575 if (settings.use_hotkeys == 0)
2578 return (GetAsyncKeyState(g64Keys[key]) & mask);
2581 return grKeyPressed(g64Keys[key]);
2588 int k_ctl=0, k_alt=0, k_del=0;
2590 LRESULT CALLBACK LowLevelKeyboardProc(int nCode,
2591 WPARAM wParam, LPARAM lParam)
2593 if (!fullscreen) return CallNextHookEx(NULL, nCode, wParam, lParam);
2599 if (nCode == HC_ACTION)
2602 case WM_KEYUP: case WM_SYSKEYUP:
2603 p = (PKBDLLHOOKSTRUCT) lParam;
2604 if (p->vkCode == 162) k_ctl = 0;
2605 if (p->vkCode == 164) k_alt = 0;
2606 if (p->vkCode == 46) k_del = 0;
2609 case WM_KEYDOWN: case WM_SYSKEYDOWN:
2610 p = (PKBDLLHOOKSTRUCT) lParam;
2611 if (p->vkCode == 162) k_ctl = 1;
2612 if (p->vkCode == 164) k_alt = 1;
2613 if (p->vkCode == 46) k_del = 1;
2618 ((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
2619 ((p->vkCode == VK_ESCAPE) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
2620 ((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) & 0x8000) != 0)) ||
2621 (k_ctl && k_alt && k_del);
2635 return CallNextHookEx(NULL, nCode, wParam, lParam);
2640 // DllMain - called when the DLL is loaded, use this to get the DLL's instance
2643 class wxDLLApp : public wxApp
2646 virtual bool OnInit();
2649 IMPLEMENT_APP_NO_MAIN(wxDLLApp)
2651 bool wxDLLApp::OnInit()
2653 /* if (mutexProcessDList == NULL)
2654 mutexProcessDList = new wxMutex(wxMUTEX_DEFAULT);*/
2655 wxImage::AddHandler(new wxPNGHandler);
2656 wxImage::AddHandler(new wxJPEGHandler);
2661 int __attribute__ ((constructor)) DllLoad(void);
2662 int __attribute__ ((destructor)) DllUnload(void);
2665 // Called when the library is loaded and before dlopen() returns
2670 wxEntryStart(argc, argv);
2672 return wxTheApp->CallOnInit() ? TRUE : FALSE;
2676 // Called when the library is unloaded and before dlclose() returns
2686 extern "C" int WINAPI DllMain (HINSTANCE hinstDLL,
2690 sprintf (out_buf, "DllMain (%08lx - %d)\n", hinstDLL, fdwReason);
2693 if (fdwReason == DLL_PROCESS_ATTACH)
2695 wxSetInstance(hinstDLL);
2698 else if (fdwReason == DLL_PROCESS_DETACH)
2700 if (GFXWindow != NULL)
2701 GFXWindow->SetHWND(NULL);
2707 void CALL ReadScreen(void **dest, int *width, int *height)
2709 *width = settings.res_x;
2710 *height = settings.res_y;
2711 wxUint8 * buff = (wxUint8*)malloc(settings.res_x * settings.res_y * 3);
2712 wxUint8 * line = buff;
2713 *dest = (void*)buff;
2717 for (wxUint32 y=0; y<settings.res_y; y++)
2719 for (wxUint32 x=0; x<settings.res_x; x++)
2726 LOG ("ReadScreen. not in the fullscreen!\n");
2731 info.size = sizeof(GrLfbInfo_t);
2732 if (grLfbLock (GR_LFB_READ_ONLY,
2733 GR_BUFFER_FRONTBUFFER,
2734 GR_LFBWRITEMODE_565,
2735 GR_ORIGIN_UPPER_LEFT,
2739 wxUint32 offset_src=info.strideInBytes*(settings.scr_res_y-1);
2743 if (info.writeMode == GR_LFBWRITEMODE_8888)
2746 for (wxUint32 y=0; y<settings.res_y; y++)
2748 wxUint32 *ptr = (wxUint32*)((wxUint8*)info.lfbPtr + offset_src);
2749 for (wxUint32 x=0; x<settings.res_x; x++)
2752 r = (wxUint8)((col >> 16) & 0xFF);
2753 g = (wxUint8)((col >> 8) & 0xFF);
2754 b = (wxUint8)(col & 0xFF);
2759 line += settings.res_x * 3;
2760 offset_src -= info.strideInBytes;
2766 for (wxUint32 y=0; y<settings.res_y; y++)
2768 wxUint16 *ptr = (wxUint16*)((wxUint8*)info.lfbPtr + offset_src);
2769 for (wxUint32 x=0; x<settings.res_x; x++)
2772 r = (wxUint8)((float)(col >> 11) / 31.0f * 255.0f);
2773 g = (wxUint8)((float)((col >> 5) & 0x3F) / 63.0f * 255.0f);
2774 b = (wxUint8)((float)(col & 0x1F) / 31.0f * 255.0f);
2779 line += settings.res_x * 3;
2780 offset_src -= info.strideInBytes;
2783 // Unlock the frontbuffer
2784 grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER);
2786 LOG ("ReadScreen. Success.\n");