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