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