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