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