Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-glide64/src/Main.cpp
2 views
1
/*
2
* Glide64 - Glide video plugin for Nintendo 64 emulators.
3
* Copyright (c) 2002 Dave2001
4
*
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public
16
* Licence along with this program; if not, write to the Free
17
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
* Boston, MA 02110-1301, USA
19
*/
20
21
//****************************************************************
22
//
23
// Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)
24
// Project started on December 29th, 2001
25
//
26
// To modify Glide64:
27
// * 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.
28
// * 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.
29
//
30
// Official Glide64 development channel: #Glide64 on EFnet
31
//
32
// Original author: Dave2001 ([email protected])
33
// Other authors: Gonetz, Gugaman
34
//
35
//****************************************************************
36
37
#include "Util.h"
38
#include "3dmath.h"
39
#include "Debugger.h"
40
41
#include "Combine.h"
42
43
#include "Ini.h"
44
#include "Config.h"
45
46
#include "TexCache.h"
47
#include "CRC.h"
48
#include "DepthBufferRender.h"
49
50
#include <string.h>
51
#include <stdlib.h>
52
53
#ifndef _WIN32
54
#include <sys/time.h>
55
#endif
56
57
#include "osal_dynamiclib.h"
58
59
#define G64_VERSION "Mupen64Plus"
60
#define RELTIME "Date: " __DATE__ " Time: " __TIME__
61
62
#ifdef EXT_LOGGING
63
std::ofstream extlog;
64
#endif
65
66
#ifdef LOGGING
67
std::ofstream loga;
68
#endif
69
70
#ifdef RDP_LOGGING
71
BOOL log_open = FALSE;
72
std::ofstream rdp_log;
73
#endif
74
75
#ifdef RDP_ERROR_LOG
76
BOOL elog_open = FALSE;
77
std::ofstream rdp_err;
78
#endif
79
80
GFX_INFO gfx;
81
/* definitions of pointers to Core config functions */
82
ptr_ConfigOpenSection ConfigOpenSection = NULL;
83
ptr_ConfigSetParameter ConfigSetParameter = NULL;
84
ptr_ConfigGetParameter ConfigGetParameter = NULL;
85
ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL;
86
ptr_ConfigSetDefaultInt ConfigSetDefaultInt = NULL;
87
ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat = NULL;
88
ptr_ConfigSetDefaultBool ConfigSetDefaultBool = NULL;
89
ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL;
90
ptr_ConfigGetParamInt ConfigGetParamInt = NULL;
91
ptr_ConfigGetParamFloat ConfigGetParamFloat = NULL;
92
ptr_ConfigGetParamBool ConfigGetParamBool = NULL;
93
ptr_ConfigGetParamString ConfigGetParamString = NULL;
94
95
ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL;
96
ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath = NULL;
97
ptr_ConfigGetUserDataPath ConfigGetUserDataPath = NULL;
98
ptr_ConfigGetUserCachePath ConfigGetUserCachePath = NULL;
99
100
/* definitions of pointers to Core video extension functions */
101
ptr_VidExt_Init CoreVideo_Init = NULL;
102
ptr_VidExt_Quit CoreVideo_Quit = NULL;
103
ptr_VidExt_ListFullscreenModes CoreVideo_ListFullscreenModes = NULL;
104
ptr_VidExt_SetVideoMode CoreVideo_SetVideoMode = NULL;
105
ptr_VidExt_SetCaption CoreVideo_SetCaption = NULL;
106
ptr_VidExt_ToggleFullScreen CoreVideo_ToggleFullScreen = NULL;
107
ptr_VidExt_ResizeWindow CoreVideo_ResizeWindow = NULL;
108
ptr_VidExt_GL_GetProcAddress CoreVideo_GL_GetProcAddress = NULL;
109
ptr_VidExt_GL_SetAttribute CoreVideo_GL_SetAttribute = NULL;
110
ptr_VidExt_GL_SwapBuffers CoreVideo_GL_SwapBuffers = NULL;
111
112
BOOL to_fullscreen = FALSE;
113
BOOL fullscreen = FALSE;
114
BOOL romopen = FALSE;
115
GrContext_t gfx_context = 0;
116
BOOL debugging = FALSE;
117
HINSTANCE hInstance = NULL;
118
BOOL exception = FALSE;
119
120
BOOL evoodoo = 0;
121
BOOL ev_fullscreen = 0;
122
123
int num_tmu;
124
int max_tex_size;
125
long sup_mirroring;
126
BOOL sup_32bit_tex = FALSE;
127
128
#ifdef ALTTAB_FIX
129
HHOOK hhkLowLevelKybd = NULL;
130
LRESULT CALLBACK LowLevelKeyboardProc(int nCode,
131
WPARAM wParam, LPARAM lParam);
132
#endif
133
134
#ifdef PERFORMANCE
135
__int64 perf_cur;
136
__int64 perf_next;
137
#endif
138
139
#ifdef FPS
140
LARGE_INTEGER perf_freq;
141
LARGE_INTEGER fps_last;
142
LARGE_INTEGER fps_next;
143
float fps = 0.0f;
144
DWORD fps_count = 0;
145
146
DWORD vi_count = 0;
147
float vi = 0.0f;
148
149
DWORD region = 0;
150
151
float ntsc_percent = 0.0f;
152
float pal_percent = 0.0f;
153
154
#endif
155
156
// Resolutions, MUST be in the correct order (SST1VID.H)
157
DWORD resolutions[0x18][2] = {
158
{ 320, 200 },
159
{ 320, 240 },
160
{ 400, 256 },
161
{ 512, 384 },
162
{ 640, 200 },
163
{ 640, 350 },
164
{ 640, 400 },
165
{ 640, 480 },
166
{ 800, 600 },
167
{ 960, 720 },
168
{ 856, 480 },
169
{ 512, 256 },
170
{ 1024, 768 },
171
{ 1280, 1024 },
172
{ 1600, 1200 },
173
{ 400, 300 },
174
175
// 0x10
176
{ 1152, 864 },
177
{ 1280, 960 },
178
{ 1600, 1024 },
179
{ 1792, 1344 },
180
{ 1856, 1392 },
181
{ 1920, 1440 },
182
{ 2048, 1536 },
183
{ 2048, 2048 }
184
};
185
186
enum {
187
NONE,
188
ZELDA,
189
BOMBERMAN64,
190
DIDDY,
191
TONIC,
192
ASB,
193
DORAEMON2,
194
INVADERS,
195
BAR,
196
ISS64,
197
RE2,
198
NITRO,
199
CHOPPER,
200
YOSHI,
201
FZERO,
202
PM,
203
TGR,
204
TGR2,
205
KI,
206
LEGO
207
};
208
209
// ref rate
210
// 60=0x0, 70=0x1, 72=0x2, 75=0x3, 80=0x4, 90=0x5, 100=0x6, 85=0x7, 120=0x8, none=0xff
211
212
unsigned long BMASK = 0x7FFFFF;
213
// Reality display processor structure
214
RDP rdp;
215
216
SETTINGS settings = { FALSE, 640, 480, GR_RESOLUTION_640x480, 0 };
217
218
HOTKEY_INFO hotkey_info;
219
220
GrTexInfo fontTex;
221
GrTexInfo cursorTex;
222
DWORD offset_font = 0;
223
DWORD offset_cursor = 0;
224
DWORD offset_textures = 0;
225
DWORD offset_texbuf1 = 0;
226
227
BOOL capture_screen = 0;
228
char capture_path[256];
229
230
void (*renderCallback)(int) = NULL;
231
static void (*l_DebugCallback)(void *, int, const char *) = NULL;
232
static void *l_DebugCallContext = NULL;
233
234
235
void WriteLog(m64p_msg_level level, const char *msg, ...)
236
{
237
char buf[1024];
238
va_list args;
239
va_start(args, msg);
240
vsnprintf(buf, 1023, msg, args);
241
buf[1023]='\0';
242
va_end(args);
243
if (l_DebugCallback)
244
{
245
l_DebugCallback(l_DebugCallContext, level, buf);
246
}
247
}
248
249
void ChangeSize ()
250
{
251
float res_scl_x = (float)settings.res_x / 320.0f;
252
float res_scl_y = (float)settings.res_y / 240.0f;
253
254
DWORD scale_x = *gfx.VI_X_SCALE_REG & 0xFFF;
255
if (!scale_x) return;
256
DWORD scale_y = *gfx.VI_Y_SCALE_REG & 0xFFF;
257
if (!scale_y) return;
258
259
float fscale_x = (float)scale_x / 1024.0f;
260
float fscale_y = (float)scale_y / 1024.0f;
261
262
DWORD dwHStartReg = *gfx.VI_H_START_REG;
263
DWORD dwVStartReg = *gfx.VI_V_START_REG;
264
265
DWORD hstart = dwHStartReg >> 16;
266
DWORD hend = dwHStartReg & 0xFFFF;
267
268
// dunno... but sometimes this happens
269
if (hend == hstart) hend = (int)(*gfx.VI_WIDTH_REG / fscale_x);
270
271
DWORD vstart = dwVStartReg >> 16;
272
DWORD vend = dwVStartReg & 0xFFFF;
273
274
sprintf (out_buf, "hstart: %d, hend: %d, vstart: %d, vend: %d\n", hstart, hend, vstart, vend);
275
LOG (out_buf);
276
277
rdp.vi_width = (hend - hstart) * fscale_x;
278
rdp.vi_height = (vend - vstart)/2 * fscale_y;
279
280
sprintf (out_buf, "size: %d x %d\n", (int)rdp.vi_width, (int)rdp.vi_height);
281
LOG (out_buf);
282
283
if (region == 0)
284
{
285
if (*gfx.VI_WIDTH_REG == 0x500) // 1280x960 is different... needs height * 2
286
{
287
rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width);
288
rdp.scale_y = res_scl_y * (120.0f / rdp.vi_height);
289
}
290
else
291
{
292
rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width);
293
rdp.scale_y = res_scl_y * (240.0f / rdp.vi_height);
294
}
295
}
296
else
297
{
298
// odd... but pal games seem to want 230 as height...
299
if (*gfx.VI_WIDTH_REG == 0x500) // 1280x960 is different... needs height * 2
300
{
301
// NOT SURE ABOUT PAL HERE, DON'T HAVE PAL MEGAMAN TO TRY
302
rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width);
303
// VP changed to 120
304
rdp.scale_y = res_scl_y * (120.0f / rdp.vi_height);
305
//rdp.scale_y = res_scl_y * (115.0f / rdp.vi_height);
306
}
307
else
308
{
309
rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width);
310
// VP changed to 240
311
rdp.scale_y = res_scl_y * (240.0f / rdp.vi_height);
312
//rdp.scale_y = res_scl_y * (230.0f / rdp.vi_height);
313
}
314
}
315
316
rdp.offset_x = settings.offset_x * res_scl_x;
317
rdp.offset_y = settings.offset_y * res_scl_y;
318
if (settings.scale_x != 0)
319
rdp.scale_x *= (settings.scale_x / 100000.0f);
320
if (settings.scale_y != 0)
321
rdp.scale_y *= (settings.scale_y / 100000.0f);
322
323
rdp.scale_1024 = settings.scr_res_x / 1024.0f;
324
rdp.scale_768 = settings.scr_res_y / 768.0f;
325
326
rdp.scissor_o.ul_x = 0;
327
rdp.scissor_o.ul_y = 0;
328
rdp.scissor_o.lr_x = (DWORD)rdp.vi_width;
329
rdp.scissor_o.lr_y = (DWORD)rdp.vi_height;
330
331
rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
332
}
333
334
void ReadSettings ()
335
{
336
// LOG("ReadSettings\n");
337
if (!Config_Open())
338
{
339
WriteLog(M64MSG_ERROR, "Could not open configuration!");
340
return;
341
}
342
settings.card_id = (BYTE)Config_ReadInt ("card_id", "Card ID", 0, TRUE, FALSE);
343
344
settings.depth_bias = -Config_ReadInt ("depth_bias", "Depth bias level", 0, TRUE, FALSE);
345
PackedScreenResolution packedResolution = Config_ReadScreenSettings();
346
settings.res_data = (DWORD) packedResolution.resolution;
347
settings.scr_res_x = settings.res_x = packedResolution.width;
348
settings.scr_res_y = settings.res_y = packedResolution.height;
349
settings.autodetect_ucode = (BOOL)Config_ReadInt ("autodetect_ucode", "Auto-detect microcode", 1);
350
settings.ucode = (DWORD)Config_ReadInt ("ucode", "Force microcode", 2, TRUE, FALSE);
351
352
settings.wireframe = (BOOL)Config_ReadInt ("wireframe", "Wireframe display", 0);
353
settings.wfmode = (int)Config_ReadInt ("wfmode", "Wireframe mode: 0=Normal colors, 1=Vertex colors, 2=Red only", 1, TRUE, FALSE);
354
settings.filtering = (BYTE)Config_ReadInt ("filtering", "Filtering mode: 0=None, 1=Force bilinear, 2=Force point-sampled", 1, TRUE, FALSE);
355
settings.fog = (BOOL)Config_ReadInt ("fog", "Fog enabled", 1);
356
settings.buff_clear = (BOOL)Config_ReadInt ("buff_clear", "Buffer clear on every frame", 1);
357
settings.vsync = (BOOL)Config_ReadInt ("vsync", "Vertical sync", 0);
358
settings.fast_crc = (BOOL)Config_ReadInt ("fast_crc", "Fast CRC", 0);
359
settings.swapmode = (BYTE)Config_ReadInt ("swapmode", "Buffer swapping method: 0=Old, 1=New, 2=Hybrid", 1, TRUE, FALSE);
360
settings.lodmode = (BYTE)Config_ReadInt ("lodmode", "LOD calculation: 0=Off, 1=Fast, 2=Precise", 0, TRUE, FALSE);
361
362
settings.logging = (BOOL)Config_ReadInt ("logging", "Logging", 0);
363
settings.log_clear = (BOOL)Config_ReadInt ("log_clear", "", 0);
364
settings.elogging = (BOOL)Config_ReadInt ("elogging", "", 0);
365
settings.filter_cache = (BOOL)Config_ReadInt ("filter_cache", "Filter cache", 0);
366
settings.cpu_write_hack = (BOOL)Config_ReadInt ("detect_cpu_write", "Detect CPU writes", 0);
367
settings.unk_as_red = (BOOL)Config_ReadInt ("unk_as_red", "Display unknown combines as red", 0);
368
settings.log_unk = (BOOL)Config_ReadInt ("log_unk", "Log unknown combines", 0);
369
settings.unk_clear = (BOOL)Config_ReadInt ("unk_clear", "", 0);
370
371
settings.wrap_big_tex = (BOOL)Config_ReadInt ("wrap_big_tex", "Wrap textures too big for tmem", 0);
372
settings.flame_corona = (BOOL)Config_ReadInt ("flame_corona", "Zelda corona fix", 0);
373
// settings.RE2_native_video = (BOOL)INI_ReadInt ("RE2_native_video", 0);
374
375
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);
376
377
settings.clock = (BOOL)Config_ReadInt ("clock", "Clock enabled", 0);
378
settings.clock_24_hr = (BOOL)Config_ReadInt ("clock_24_hr", "Clock is 24-hour", 0);
379
380
settings.fb_read_always = (BOOL)Config_ReadInt ("fb_read_always", "Framebuffer read every frame", 0);
381
settings.fb_read_alpha = (BOOL)Config_ReadInt ("fb_read_alpha", "Framebuffer read alpha", 0);
382
settings.fb_smart = (BOOL)Config_ReadInt ("fb_smart", "Smart framebuffer", 0);
383
settings.fb_motionblur = (BOOL)Config_ReadInt ("motionblur", "Motion blur", 0);
384
settings.fb_hires = (BOOL)Config_ReadInt ("fb_hires", "Hi-res framebuffer", 1);
385
settings.fb_get_info = (BOOL)Config_ReadInt ("fb_get_info", "Get framebuffer info", 0);
386
settings.fb_depth_clear = (BOOL)Config_ReadInt ("fb_clear", "Clear framebuffer", 0);
387
settings.fb_depth_render = (BOOL)Config_ReadInt ("fb_render", "Depth buffer render", 0);
388
if (settings.fb_depth_render)
389
settings.fb_depth_clear = TRUE;
390
391
settings.custom_ini = (BOOL)Config_ReadInt ("custom_ini", "Use custom INI settings", 0);
392
settings.hotkeys = 0;
393
394
settings.full_res = 0;
395
settings.tex_filter = (DWORD)Config_ReadInt ("tex_filter", "Texture filter: 0=None, 1=Blur edges, 2=Super 2xSai, 3=Hq2x, 4=Hq4x", 0, TRUE, FALSE);
396
settings.noditheredalpha = (BOOL)Config_ReadInt ("noditheredalpha", "Disable dithered alpha", 1);
397
settings.noglsl = (BOOL)Config_ReadInt ("noglsl", "Disable GLSL combiners", 1);
398
settings.FBO = (BOOL)Config_ReadInt ("fbo", "Use framebuffer objects", 0);
399
settings.disable_auxbuf = (BOOL)Config_ReadInt ("disable_auxbuf", "Disable aux buffer", 0);
400
401
}
402
403
void ReadSpecialSettings (const char name[21])
404
{
405
// char buf [256];
406
// sprintf(buf, "ReadSpecialSettings. Name: %s\n", name);
407
// LOG(buf);
408
settings.zelda = FALSE; //zeldas hacks
409
settings.bomberman64 = FALSE; //bomberman64 hacks
410
settings.diddy = FALSE; //diddy kong racing
411
settings.tonic = FALSE; //tonic trouble
412
settings.PPL = FALSE; //pokemon puzzle league requires many special fixes
413
settings.ASB = FALSE; //All-Star Baseball games
414
settings.doraemon2 = FALSE;//Doraemon 2
415
settings.invaders = FALSE; //Space Invaders
416
settings.BAR = FALSE; //Beetle Adventure Racing
417
settings.ISS64 = FALSE; //International Superstar Soccer 64
418
settings.RE2 = FALSE; //Resident Evil 2
419
settings.nitro = FALSE; //WCW Nitro
420
settings.chopper = FALSE; //Chopper Attack
421
settings.yoshi = FALSE; // Yoshi Story
422
settings.fzero = FALSE; // F-Zero
423
settings.PM = FALSE; //Paper Mario
424
settings.TGR = FALSE; //Top Gear Rally
425
settings.TGR2 = FALSE; //Top Gear Rally 2
426
settings.KI = FALSE; //Killer Instinct
427
settings.lego = FALSE; //LEGO Racers
428
429
//detect games which require special hacks
430
if (strstr(name, (const char *)"ZELDA") || strstr(name, (const char *)"MASK"))
431
settings.zelda = TRUE;
432
else if (strstr(name, (const char *)"ROADSTERS TROPHY"))
433
settings.zelda = TRUE;
434
else if (strstr(name, (const char *)"Diddy Kong Racing"))
435
settings.diddy = TRUE;
436
else if (strstr(name, (const char *)"BOMBERMAN64"))
437
settings.bomberman64 = TRUE;
438
else if (strstr(name, (const char *)"BAKU-BOMBERMAN"))
439
settings.bomberman64 = TRUE;
440
else if (strstr(name, (const char *)"Tonic Trouble"))
441
settings.tonic = TRUE;
442
else if (strstr(name, (const char *)"All") && strstr(name, (const char *)"Star") && strstr(name, (const char *)"Baseball"))
443
settings.ASB = TRUE;
444
else if (strstr(name, (const char *)"\xbf\xef\xef\xbd\xbd\xbf\xb4\xd7\xbf\xef\xef\xbd\xbd\xbf\x20\x32\xb6\xcb\xbf\xef\xc9\xbd\xef\xbc\xbd\xbf\xbf\xef\xef\xbd\xbd\xbf\xbf\xef\x0a\xbd"))
445
settings.doraemon2 = TRUE;
446
else if (strstr(name, (const char *)"SPACE INVADERS"))
447
settings.invaders = TRUE;
448
else if (strstr(name, (const char *)"Beetle") || strstr(name, (const char *)"BEETLE") || strstr(name, (const char *)"HSV"))
449
settings.BAR = TRUE;
450
else if (strstr(name, (const char *)"I S S 64") || strstr(name, (const char *)"PERFECT STRIKER"))
451
settings.ISS64 = TRUE;
452
else if (strstr(name, (const char *)"NITRO64"))
453
settings.nitro = TRUE;
454
else if (strstr(name, (const char *)"CHOPPER_ATTACK"))
455
settings.chopper = TRUE;
456
else if (strstr(name, (const char *)"Resident Evil II") || strstr(name, (const char *)"BioHazard II"))
457
{
458
settings.RE2 = TRUE;
459
ZLUT_init();
460
}
461
else if (strstr(name, (const char *)"YOSHI STORY"))
462
settings.yoshi= TRUE;
463
else if (strstr(name, (const char *)"F-Zero X") || strstr(name, (const char *)"F-ZERO X"))
464
settings.fzero = TRUE;
465
else if (strstr(name, (const char *)"PAPER MARIO") || strstr(name, (const char *)"MARIO STORY"))
466
settings.PM = TRUE;
467
else if (strstr(name, (const char *)"TOP GEAR RALLY 2"))
468
settings.TGR2 = TRUE;
469
else if (strstr(name, (const char *)"TOP GEAR RALLY"))
470
settings.TGR = TRUE;
471
else if (strstr(name, (const char *)"Killer Instinct Gold") || strstr(name, (const char *)"KILLER INSTINCT GOLD"))
472
settings.KI = TRUE;
473
else if (strstr(name, (const char *)"LEGORacers"))
474
settings.lego = TRUE;
475
476
int EnableHacksForGame = (int)Config_ReadInt ("enable_hacks_for_game", "???", 0, TRUE, FALSE);
477
478
switch (EnableHacksForGame)
479
{
480
case ZELDA:
481
settings.zelda = TRUE;
482
break;
483
case BOMBERMAN64:
484
settings.bomberman64 = TRUE;
485
break;
486
case DIDDY:
487
settings.diddy = TRUE;
488
break;
489
case TONIC:
490
settings.tonic = TRUE;
491
break;
492
case ASB:
493
settings.ASB = TRUE;
494
break;
495
case DORAEMON2:
496
settings.doraemon2 = TRUE;
497
break;
498
case INVADERS:
499
settings.invaders = TRUE;
500
break;
501
case BAR:
502
settings.BAR = TRUE;
503
break;
504
case ISS64:
505
settings.ISS64 = TRUE;
506
break;
507
case RE2:
508
settings.RE2 = TRUE;
509
ZLUT_init();
510
break;
511
case NITRO:
512
settings.nitro = TRUE;
513
break;
514
case CHOPPER:
515
settings.chopper = TRUE;
516
break;
517
case YOSHI:
518
settings.yoshi= TRUE;
519
break;
520
case FZERO:
521
settings.fzero = TRUE;
522
break;
523
case PM:
524
settings.PM = TRUE;
525
break;
526
case TGR:
527
settings.TGR = TRUE;
528
break;
529
case TGR2:
530
settings.TGR2 = TRUE;
531
break;
532
case KI:
533
settings.KI = TRUE;
534
break;
535
case LEGO:
536
settings.lego = TRUE;
537
break;
538
}
539
540
541
settings.offset_x = (int)Config_ReadInt ("offset_x", "???", 0, TRUE, FALSE);
542
settings.offset_y = (int)Config_ReadInt ("offset_y", "???", 0, TRUE, FALSE);
543
settings.scale_x = (int)Config_ReadInt ("scale_x", "???", 100000, TRUE, FALSE);
544
settings.scale_y = (int)Config_ReadInt ("scale_y", "???", 100000, TRUE, FALSE);
545
settings.alt_tex_size = (BOOL)Config_ReadInt ("alt_tex_size", "???", 0);
546
settings.use_sts1_only = (BOOL)Config_ReadInt ("use_sts1_only", "???", 0);
547
settings.PPL = (BOOL)Config_ReadInt ("PPL", "???", 0);
548
settings.fb_optimize_texrect = (BOOL)Config_ReadInt ("fb_optimize_texrect", "???", 1);
549
settings.fb_optimize_write = (BOOL)Config_ReadInt ("fb_optimize_write", "???", 0);
550
settings.fb_ignore_aux_copy = (BOOL)Config_ReadInt ("fb_ignore_aux_copy", "???", 0);
551
settings.fb_hires_buf_clear = (BOOL)Config_ReadInt ("fb_hires_buf_clear", "???", 1);
552
settings.wrap_big_tex = (BOOL)Config_ReadInt ("wrap_big_tex", "???", 0);
553
settings.fix_tex_coord = (BOOL)Config_ReadInt ("fix_tex_coord", "???", 0);
554
settings.soft_depth_compare = (BOOL)Config_ReadInt ("soft_depth_compare", "???", 0);
555
settings.force_depth_compare = (BOOL)Config_ReadInt ("force_depth_compare", "???", 0);
556
settings.fillcolor_fix = (BOOL)Config_ReadInt ("fillcolor_fix", "???", 0);
557
settings.depth_bias = -(int)Config_ReadInt ("depth_bias", "???", 20, TRUE, FALSE);
558
settings.increase_texrect_edge = (BOOL)Config_ReadInt ("increase_texrect_edge", "???", 0);
559
settings.decrease_fillrect_edge = (BOOL)Config_ReadInt ("decrease_fillrect_edge", "???", 0);
560
settings.increase_primdepth = (BOOL)Config_ReadInt ("increase_primdepth", "???", 0);
561
settings.stipple_mode = (int)Config_ReadInt ("stipple_mode", "???", 1, TRUE, FALSE);
562
settings.stipple_pattern = (DWORD)Config_ReadInt ("stipple_pattern", "???", 1041204192, TRUE, FALSE);
563
settings.force_microcheck = (BOOL)Config_ReadInt ("force_microcheck", "???", 0);
564
settings.fb_ignore_previous = (BOOL)Config_ReadInt ("fb_ignore_previous", "???", 0);
565
settings.fb_get_info = (BOOL)Config_ReadInt ("fb_get_info", "???", 0);
566
settings.fb_hires = (BOOL)Config_ReadInt ("fb_hires", "???", 0);
567
568
settings.lodmode = (int)Config_ReadInt ("lodmode", "???", 0, TRUE, FALSE);
569
570
settings.filtering = (int)Config_ReadInt ("filtering", "???", 1, TRUE, FALSE);
571
settings.fog = (int)Config_ReadInt ("fog", "???", 1, TRUE, FALSE);
572
settings.buff_clear = (BOOL)Config_ReadInt ("buff_clear", "???", 1);
573
settings.swapmode = (int)Config_ReadInt ("swapmode", "???", 1, TRUE, FALSE);
574
settings.fb_smart = (BOOL)Config_ReadInt ("fb_smart", "???", 0);
575
settings.fb_read_alpha = (BOOL)Config_ReadInt ("fb_read_alpha", "???", 0);
576
settings.fb_depth_clear = (BOOL)Config_ReadInt ("fb_depth_clear", "???", 0);
577
settings.cpu_write_hack = (BOOL)Config_ReadInt ("cpu_write_hack", "???", 0);
578
579
if (settings.fb_depth_render)
580
settings.fb_depth_clear = TRUE;
581
INI_Close ();
582
}
583
584
#include "font.h"
585
#include "cursor.h"
586
587
GRFRAMEBUFFERCOPYEXT grFramebufferCopyExt = NULL;
588
GRTEXBUFFEREXT grTextureBufferExt = NULL;
589
GRTEXBUFFEREXT grTextureAuxBufferExt = NULL;
590
GRAUXBUFFEREXT grAuxBufferExt = NULL;
591
GRSTIPPLE grStippleModeExt = NULL;
592
GRSTIPPLE grStipplePatternExt = NULL;
593
BOOL combineext = FALSE;
594
595
BOOL depthbuffersave = FALSE;
596
597
// guLoadTextures - used to load the cursor and font textures
598
void guLoadTextures ()
599
{
600
if (grTextureBufferExt)
601
{
602
int tbuf_size = 0;
603
if (max_tex_size <= 256)
604
{
605
grTextureBufferExt( GR_TMU1, grTexMinAddress(GR_TMU1), GR_LOD_LOG2_256, GR_LOD_LOG2_256,
606
GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
607
tbuf_size = 8 * grTexCalcMemRequired(GR_LOD_LOG2_256, GR_LOD_LOG2_256,
608
GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);
609
}
610
else if (settings.scr_res_x <= 1024)
611
{
612
grTextureBufferExt( GR_TMU1, grTexMinAddress(GR_TMU1), GR_LOD_LOG2_1024, GR_LOD_LOG2_1024,
613
GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
614
tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_1024, GR_LOD_LOG2_1024,
615
GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);
616
}
617
else
618
{
619
grTextureBufferExt( GR_TMU1, grTexMinAddress(GR_TMU1), GR_LOD_LOG2_2048, GR_LOD_LOG2_2048,
620
GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
621
tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_2048, GR_LOD_LOG2_2048,
622
GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565);
623
}
624
625
//tbuf_size *= 2;
626
WriteLog(M64MSG_INFO, "tbuf_size %gMb\n", tbuf_size/1024.0f/1024);
627
rdp.texbufs[0].tmu = GR_TMU0;
628
rdp.texbufs[0].begin = grTexMinAddress(GR_TMU0);
629
rdp.texbufs[0].end = rdp.texbufs[0].begin+tbuf_size;
630
rdp.texbufs[0].count = 0;
631
rdp.texbufs[0].clear_allowed = TRUE;
632
if (num_tmu > 1)
633
{
634
rdp.texbufs[1].tmu = GR_TMU1;
635
rdp.texbufs[1].begin = grTexMinAddress(GR_TMU1);
636
rdp.texbufs[1].end = rdp.texbufs[1].begin+tbuf_size;
637
rdp.texbufs[1].count = 0;
638
rdp.texbufs[1].clear_allowed = TRUE;
639
offset_texbuf1 = tbuf_size;
640
}
641
offset_font = tbuf_size;
642
}
643
else
644
offset_font = 0;
645
646
DWORD *data = (DWORD*)font;
647
DWORD cur;
648
649
// ** Font texture **
650
BYTE *tex8 = (BYTE*)malloc(256*64);
651
652
fontTex.smallLodLog2 = fontTex.largeLodLog2 = GR_LOD_LOG2_256;
653
fontTex.aspectRatioLog2 = GR_ASPECT_LOG2_4x1;
654
fontTex.format = GR_TEXFMT_ALPHA_8;
655
fontTex.data = tex8;
656
657
// Decompression: [1-bit inverse alpha --> 8-bit alpha]
658
DWORD i,b;
659
for (i=0; i<0x200; i++)
660
{
661
// cur = ~*(data++), byteswapped
662
#if !defined(__GNUC__)
663
cur = _byteswap_ulong(~*(data++));
664
#else
665
cur = __builtin_bswap32(~*(data++));
666
#endif
667
668
for (b=0x80000000; b!=0; b>>=1)
669
{
670
if (cur&b) *tex8 = 0xFF;
671
else *tex8 = 0x00;
672
tex8 ++;
673
}
674
}
675
676
grTexDownloadMipMap (GR_TMU0,
677
grTexMinAddress(GR_TMU0) + offset_font,
678
GR_MIPMAPLEVELMASK_BOTH,
679
&fontTex);
680
681
offset_cursor = offset_font + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &fontTex);
682
683
free (fontTex.data);
684
685
// ** Cursor texture **
686
data = (DWORD*)cursor;
687
688
WORD *tex16 = (WORD*)malloc(32*32*2);
689
690
cursorTex.smallLodLog2 = cursorTex.largeLodLog2 = GR_LOD_LOG2_32;
691
cursorTex.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
692
cursorTex.format = GR_TEXFMT_ARGB_1555;
693
cursorTex.data = tex16;
694
695
// Conversion: [16-bit 1555 (swapped) --> 16-bit 1555]
696
for (i=0; i<0x200; i++)
697
{
698
cur = *(data++);
699
*(tex16++) = (WORD)(((cur&0x000000FF)<<8)|((cur&0x0000FF00)>>8));
700
*(tex16++) = (WORD)(((cur&0x00FF0000)>>8)|((cur&0xFF000000)>>24));
701
}
702
703
grTexDownloadMipMap (GR_TMU0,
704
grTexMinAddress(GR_TMU0) + offset_cursor,
705
GR_MIPMAPLEVELMASK_BOTH,
706
&cursorTex);
707
708
// Round to higher 16
709
offset_textures = ((offset_cursor + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &cursorTex))
710
& 0xFFFFFFF0) + 16;
711
free (cursorTex.data);
712
}
713
714
715
BOOL InitGfx (BOOL evoodoo_using_window)
716
{
717
if (fullscreen)
718
{
719
ReleaseGfx ();
720
}
721
722
OPEN_RDP_LOG (); // doesn't matter if opens again; it will check for it
723
OPEN_RDP_E_LOG ();
724
LOG ("InitGfx ()\n");
725
726
debugging = FALSE;
727
728
// Initialize Glide
729
grGlideInit ();
730
731
// Select the Glide device
732
grSstSelect (settings.card_id);
733
734
gfx_context = 0;
735
// Select the window
736
737
if (settings.fb_hires)
738
{
739
WriteLog(M64MSG_INFO, "fb_hires\n");
740
GRWINOPENEXT grSstWinOpenExt = (GRWINOPENEXT)grGetProcAddress("grSstWinOpenExt");
741
if (grSstWinOpenExt)
742
gfx_context = grSstWinOpenExt ((FxU32)NULL,
743
settings.res_data,
744
GR_REFRESH_60Hz,
745
GR_COLORFORMAT_RGBA,
746
GR_ORIGIN_UPPER_LEFT,
747
GR_PIXFMT_RGB_565,
748
2, // Double-buffering
749
1); // 1 auxillary buffer
750
}
751
if (!gfx_context)
752
gfx_context = grSstWinOpen ((FxU32)NULL,
753
settings.res_data,
754
GR_REFRESH_60Hz,
755
GR_COLORFORMAT_RGBA,
756
GR_ORIGIN_UPPER_LEFT,
757
2, // Double-buffering
758
1); // 1 auxillary buffer
759
760
if (!gfx_context)
761
{
762
WriteLog(M64MSG_ERROR, "Error setting display mode");
763
grSstWinClose (gfx_context);
764
grGlideShutdown ();
765
return FALSE;
766
}
767
768
// get the # of TMUs available
769
grGet (GR_NUM_TMU, 4, (FxI32 *) &num_tmu);
770
WriteLog(M64MSG_INFO, "num_tmu %d\n", num_tmu);
771
// get maximal texture size
772
grGet (GR_MAX_TEXTURE_SIZE, 4, (FxI32 *) &max_tex_size);
773
//num_tmu = 1;
774
775
// Is mirroring allowed?
776
const char *extensions = grGetString (GR_EXTENSION);
777
778
if (strstr (extensions, "TEXMIRROR"))
779
sup_mirroring = 1;
780
else
781
sup_mirroring = 0;
782
783
if (strstr (extensions, "TEXFMT")) //VSA100 texture format extension
784
sup_32bit_tex = TRUE;
785
else
786
sup_32bit_tex = FALSE;
787
788
if (settings.fb_hires)
789
{
790
const char * extstr = strstr(extensions, "TEXTUREBUFFER");
791
if (extstr)
792
{
793
if (!strncmp(extstr, "TEXTUREBUFFER", 13))
794
{
795
grTextureBufferExt = (GRTEXBUFFEREXT) grGetProcAddress("grTextureBufferExt");
796
grTextureAuxBufferExt = (GRTEXBUFFEREXT) grGetProcAddress("grTextureAuxBufferExt");
797
grAuxBufferExt = (GRAUXBUFFEREXT) grGetProcAddress("grAuxBufferExt");
798
}
799
}
800
else
801
settings.fb_hires = 0;
802
}
803
else
804
grTextureBufferExt = 0;
805
806
grFramebufferCopyExt = (GRFRAMEBUFFERCOPYEXT) grGetProcAddress("grFramebufferCopyExt");
807
grStippleModeExt = (GRSTIPPLE) grStippleMode;
808
grStipplePatternExt = (GRSTIPPLE) grStipplePattern;
809
if (grStipplePatternExt)
810
grStipplePatternExt(settings.stipple_pattern);
811
812
InitCombine();
813
814
#ifdef SIMULATE_VOODOO1
815
num_tmu = 1;
816
sup_mirroring = 0;
817
#endif
818
819
#ifdef SIMULATE_BANSHEE
820
num_tmu = 1;
821
sup_mirroring = 1;
822
#endif
823
824
fullscreen = TRUE;
825
826
if (evoodoo_using_window)
827
ev_fullscreen = FALSE;
828
else
829
ev_fullscreen = TRUE;
830
831
grCoordinateSpace (GR_WINDOW_COORDS);
832
grVertexLayout (GR_PARAM_XY, offsetof(VERTEX,x), GR_PARAM_ENABLE);
833
grVertexLayout (GR_PARAM_Q, offsetof(VERTEX,q), GR_PARAM_ENABLE);
834
grVertexLayout (GR_PARAM_Z, offsetof(VERTEX,z), GR_PARAM_ENABLE);
835
grVertexLayout (GR_PARAM_ST0, offsetof(VERTEX,coord[0]), GR_PARAM_ENABLE);
836
grVertexLayout (GR_PARAM_ST1, offsetof(VERTEX,coord[2]), GR_PARAM_ENABLE);
837
grVertexLayout (GR_PARAM_PARGB, offsetof(VERTEX,b), GR_PARAM_ENABLE);
838
839
grCullMode(GR_CULL_NEGATIVE);
840
841
if (settings.fog) //"FOGCOORD" extension
842
{
843
if (strstr (extensions, "FOGCOORD"))
844
{
845
GrFog_t fog_t[64];
846
guFogGenerateLinear (fog_t, 0.0f, 255.0f);//(float)rdp.fog_multiplier + (float)rdp.fog_offset);//256.0f);
847
848
for (int i = 63; i > 0; i--)
849
{
850
if (fog_t[i] - fog_t[i-1] > 63)
851
{
852
fog_t[i-1] = fog_t[i] - 63;
853
}
854
}
855
fog_t[0] = 0;
856
// for (int f = 0; f < 64; f++)
857
// {
858
// FRDP("fog[%d]=%d->%f\n", f, fog_t[f], guFogTableIndexToW(f));
859
// }
860
grFogTable (fog_t);
861
grVertexLayout (GR_PARAM_FOG_EXT, offsetof(VERTEX,f), GR_PARAM_ENABLE);
862
}
863
else //not supported
864
settings.fog = FALSE;
865
}
866
867
//grDepthBufferMode (GR_DEPTHBUFFER_WBUFFER);
868
grDepthBufferMode (GR_DEPTHBUFFER_ZBUFFER);
869
grDepthBufferFunction(GR_CMP_LESS);
870
grDepthMask(FXTRUE);
871
872
settings.res_x = settings.scr_res_x;
873
settings.res_y = settings.scr_res_y;
874
ChangeSize ();
875
876
guLoadTextures ();
877
grRenderBuffer(GR_BUFFER_BACKBUFFER);
878
879
rdp_reset ();
880
ClearCache ();
881
882
rdp.update |= UPDATE_SCISSOR;
883
884
return TRUE;
885
}
886
887
void ReleaseGfx ()
888
{
889
// Release graphics
890
grSstWinClose (gfx_context);
891
892
// Shutdown glide
893
grGlideShutdown();
894
895
fullscreen = FALSE;
896
rdp.window_changed = TRUE;
897
}
898
899
#ifdef __cplusplus
900
extern "C" {
901
#endif
902
903
EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front)
904
{
905
*width = settings.res_x;
906
*height = settings.res_y;
907
if (dest)
908
{
909
BYTE * line = (BYTE*)dest;
910
if (!fullscreen)
911
{
912
for (DWORD y=0; y<settings.res_y; y++)
913
{
914
for (DWORD x=0; x<settings.res_x; x++)
915
{
916
line[x*3] = 0x20;
917
line[x*3+1] = 0x7f;
918
line[x*3+2] = 0x40;
919
}
920
}
921
WriteLog(M64MSG_WARNING, "[Glide64] Cannot save screenshot in windowed mode?\n");
922
return;
923
}
924
925
GrLfbInfo_t info;
926
info.size = sizeof(GrLfbInfo_t);
927
if (grLfbLock(GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER, GR_LFBWRITEMODE_888, GR_ORIGIN_UPPER_LEFT, FXFALSE, &info))
928
{
929
// Copy the screen
930
for (DWORD y=0; y<settings.res_y; y++)
931
{
932
BYTE *ptr = (BYTE*) info.lfbPtr + (info.strideInBytes * y);
933
for (DWORD x=0; x<settings.res_x; x++)
934
{
935
line[x*4+2] = ptr[2]; // red
936
line[x*4+1] = ptr[1]; // green
937
line[x*4] = ptr[0]; // blue
938
ptr += 4;
939
}
940
line += settings.res_x * 4;
941
}
942
943
// Unlock the frontbuffer
944
grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER);
945
}
946
LOG ("ReadScreen. Success.\n");
947
}
948
}
949
950
EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
951
void (*DebugCallback)(void *, int, const char *))
952
{
953
l_DebugCallback = DebugCallback;
954
l_DebugCallContext = Context;
955
956
/* attach and call the CoreGetAPIVersions function, check Config and Video Extension API versions for compatibility */
957
ptr_CoreGetAPIVersions CoreAPIVersionFunc;
958
CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) osal_dynlib_getproc(CoreLibHandle, "CoreGetAPIVersions");
959
if (CoreAPIVersionFunc == NULL)
960
{
961
WriteLog(M64MSG_ERROR, "Core emulator broken; no CoreAPIVersionFunc() function found.");
962
return M64ERR_INCOMPATIBLE;
963
}
964
int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion;
965
(*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL);
966
if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000))
967
{
968
WriteLog(M64MSG_ERROR, "Emulator core Config API (v%i.%i.%i) incompatible with %s (v%i.%i.%i)",
969
VERSION_PRINTF_SPLIT(ConfigAPIVersion), PLUGIN_NAME, VERSION_PRINTF_SPLIT(CONFIG_API_VERSION));
970
return M64ERR_INCOMPATIBLE;
971
}
972
if ((VidextAPIVersion & 0xffff0000) != (VIDEXT_API_VERSION & 0xffff0000))
973
{
974
WriteLog(M64MSG_ERROR, "Emulator core Video Extension API (v%i.%i.%i) incompatible with %s (v%i.%i.%i)",
975
VERSION_PRINTF_SPLIT(VidextAPIVersion), PLUGIN_NAME, VERSION_PRINTF_SPLIT(VIDEXT_API_VERSION));
976
return M64ERR_INCOMPATIBLE;
977
}
978
979
/* Get the core config function pointers from the library handle */
980
ConfigOpenSection = (ptr_ConfigOpenSection) osal_dynlib_getproc(CoreLibHandle, "ConfigOpenSection");
981
ConfigSetParameter = (ptr_ConfigSetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigSetParameter");
982
ConfigGetParameter = (ptr_ConfigGetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParameter");
983
ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultInt");
984
ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultFloat");
985
ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultBool");
986
ConfigSetDefaultString = (ptr_ConfigSetDefaultString) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultString");
987
ConfigGetParamInt = (ptr_ConfigGetParamInt) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamInt");
988
ConfigGetParamFloat = (ptr_ConfigGetParamFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamFloat");
989
ConfigGetParamBool = (ptr_ConfigGetParamBool) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamBool");
990
ConfigGetParamString = (ptr_ConfigGetParamString) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamString");
991
992
ConfigGetSharedDataFilepath = (ptr_ConfigGetSharedDataFilepath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetSharedDataFilepath");
993
ConfigGetUserConfigPath = (ptr_ConfigGetUserConfigPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserConfigPath");
994
ConfigGetUserDataPath = (ptr_ConfigGetUserDataPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserDataPath");
995
ConfigGetUserCachePath = (ptr_ConfigGetUserCachePath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserCachePath");
996
997
if (!ConfigOpenSection || !ConfigSetParameter || !ConfigGetParameter ||
998
!ConfigSetDefaultInt || !ConfigSetDefaultFloat || !ConfigSetDefaultBool || !ConfigSetDefaultString ||
999
!ConfigGetParamInt || !ConfigGetParamFloat || !ConfigGetParamBool || !ConfigGetParamString ||
1000
!ConfigGetSharedDataFilepath || !ConfigGetUserConfigPath || !ConfigGetUserDataPath || !ConfigGetUserCachePath)
1001
{
1002
WriteLog(M64MSG_ERROR, "Couldn't connect to Core configuration functions");
1003
return M64ERR_INCOMPATIBLE;
1004
}
1005
1006
/* Get the core Video Extension function pointers from the library handle */
1007
CoreVideo_Init = (ptr_VidExt_Init) osal_dynlib_getproc(CoreLibHandle, "VidExt_Init");
1008
CoreVideo_Quit = (ptr_VidExt_Quit) osal_dynlib_getproc(CoreLibHandle, "VidExt_Quit");
1009
CoreVideo_ListFullscreenModes = (ptr_VidExt_ListFullscreenModes) osal_dynlib_getproc(CoreLibHandle, "VidExt_ListFullscreenModes");
1010
CoreVideo_SetVideoMode = (ptr_VidExt_SetVideoMode) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetVideoMode");
1011
CoreVideo_SetCaption = (ptr_VidExt_SetCaption) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetCaption");
1012
CoreVideo_ToggleFullScreen = (ptr_VidExt_ToggleFullScreen) osal_dynlib_getproc(CoreLibHandle, "VidExt_ToggleFullScreen");
1013
CoreVideo_ResizeWindow = (ptr_VidExt_ResizeWindow) osal_dynlib_getproc(CoreLibHandle, "VidExt_ResizeWindow");
1014
CoreVideo_GL_GetProcAddress = (ptr_VidExt_GL_GetProcAddress) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_GetProcAddress");
1015
CoreVideo_GL_SetAttribute = (ptr_VidExt_GL_SetAttribute) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SetAttribute");
1016
CoreVideo_GL_SwapBuffers = (ptr_VidExt_GL_SwapBuffers) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SwapBuffers");
1017
1018
if (!CoreVideo_Init || !CoreVideo_Quit || !CoreVideo_ListFullscreenModes || !CoreVideo_SetVideoMode ||
1019
!CoreVideo_SetCaption || !CoreVideo_ToggleFullScreen || !CoreVideo_GL_GetProcAddress ||
1020
!CoreVideo_GL_SetAttribute || !CoreVideo_GL_SwapBuffers || !CoreVideo_ResizeWindow)
1021
{
1022
WriteLog(M64MSG_ERROR, "Couldn't connect to Core video functions");
1023
return M64ERR_INCOMPATIBLE;
1024
}
1025
1026
const char *configDir = ConfigGetSharedDataFilepath("Glide64.ini");
1027
if (configDir)
1028
{
1029
SetConfigDir(configDir);
1030
ReadSettings();
1031
return M64ERR_SUCCESS;
1032
}
1033
else
1034
{
1035
WriteLog(M64MSG_ERROR, "Couldn't find Glide64.ini");
1036
return M64ERR_FILES;
1037
}
1038
}
1039
1040
EXPORT m64p_error CALL PluginShutdown(void)
1041
{
1042
return M64ERR_SUCCESS;
1043
}
1044
1045
EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
1046
{
1047
/* set version info */
1048
if (PluginType != NULL)
1049
*PluginType = M64PLUGIN_GFX;
1050
1051
if (PluginVersion != NULL)
1052
*PluginVersion = PLUGIN_VERSION;
1053
1054
if (APIVersion != NULL)
1055
*APIVersion = VIDEO_PLUGIN_API_VERSION;
1056
1057
if (PluginNamePtr != NULL)
1058
*PluginNamePtr = PLUGIN_NAME;
1059
1060
if (Capabilities != NULL)
1061
{
1062
*Capabilities = 0;
1063
}
1064
1065
return M64ERR_SUCCESS;
1066
}
1067
1068
/******************************************************************
1069
Function: CaptureScreen
1070
Purpose: This function dumps the current frame to a file
1071
input: pointer to the directory to save the file to
1072
output: none
1073
*******************************************************************/
1074
EXPORT void CALL CaptureScreen ( char * Directory )
1075
{
1076
capture_screen = 1;
1077
strcpy (capture_path, Directory);
1078
}
1079
1080
/******************************************************************
1081
Function: ChangeWindow
1082
Purpose: to change the window between fullscreen and window
1083
mode. If the window was in fullscreen this should
1084
change the screen to window mode and vice vesa.
1085
input: none
1086
output: none
1087
*******************************************************************/
1088
EXPORT void CALL ChangeWindow (void)
1089
{
1090
LOG ("ChangeWindow()\n");
1091
//TODO: do this better
1092
/*
1093
if (evoodoo)
1094
{
1095
if (!ev_fullscreen)
1096
{
1097
to_fullscreen = TRUE;
1098
GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt =
1099
(GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress("grWrapperFullScreenResolutionExt");
1100
if (grWrapperFullScreenResolutionExt != NULL)
1101
{
1102
settings.res_data_org = settings.res_data;
1103
settings.res_data = grWrapperFullScreenResolutionExt();
1104
settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0];
1105
settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1];
1106
}
1107
}
1108
else
1109
{
1110
ReleaseGfx ();
1111
GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt =
1112
(GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress("grWrapperFullScreenResolutionExt");
1113
if (grWrapperFullScreenResolutionExt != NULL)
1114
{
1115
settings.res_data = settings.res_data_org;
1116
settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0];
1117
settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1];
1118
}
1119
InitGfx(TRUE);
1120
}
1121
}
1122
else
1123
{
1124
// Go to fullscreen at next dlist
1125
// This is for compatibility with 1964, which reloads the plugin
1126
// when switching to fullscreen
1127
if (!fullscreen)
1128
{
1129
to_fullscreen = TRUE;
1130
}
1131
else
1132
{
1133
ReleaseGfx ();
1134
}
1135
}
1136
*/
1137
}
1138
1139
/******************************************************************
1140
Function: CloseDLL
1141
Purpose: This function is called when the emulator is closing
1142
down allowing the dll to de-initialise.
1143
input: none
1144
output: none
1145
*******************************************************************/
1146
EXPORT void CALL CloseDLL (void)
1147
{
1148
LOG ("CloseDLL ()\n");
1149
1150
// re-set the old window proc
1151
#ifdef WINPROC_OVERRIDE
1152
SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
1153
#endif
1154
1155
#ifdef ALTTAB_FIX
1156
if (hhkLowLevelKybd)
1157
{
1158
UnhookWindowsHookEx(hhkLowLevelKybd);
1159
hhkLowLevelKybd = 0;
1160
}
1161
#endif
1162
1163
//CLOSELOG ();
1164
1165
if (fullscreen)
1166
ReleaseGfx ();
1167
ZLUT_release();
1168
ClearCache ();
1169
}
1170
1171
#if 0
1172
/******************************************************************
1173
Function: DllAbout
1174
Purpose: This function is optional function that is provided
1175
to give further information about the DLL.
1176
input: a handle to the window that calls this function
1177
output: none
1178
*******************************************************************/
1179
EXPORT void CALL DllAbout ( HWND hParent )
1180
{
1181
messagebox("Glide64 v"G64_VERSION, MB_OK,
1182
"Glide64 "G64_VERSION"\nRelease: " RELTIME "\n"
1183
"by GuentherB, Richard42, Gonetz, Dave2001, Gugaman, and others\n\n"
1184
"Beta testers: Raziel64, Federelli, Flash\n\n"
1185
"Special thanks to:\n"
1186
"Niki, FiRES, Icepir8, Rice, ZeZu, Azimer, Hacktarux, Cyberman, LoneRaven, Falcon4ever,\n"
1187
"GokuSS4, _Demo_, Ogy, Quvack, Scorpiove, CpUMasteR, Doom, Lemmy, CyRUS64,\n"
1188
"McLeod, Linker, StrmnNrmn, Tekken, ExtendedPlay, Kool Smoky\n"
1189
"everyone at EmuXHaven, all my testers, anyone I've forgotten, and anyone else on\n"
1190
"the Emutalk message board who helped or brought encouragement\n\n"
1191
"Thanks to EmuXHaven for hosting my site:\nhttp://glide64.emuxhaven.net/\n\n"
1192
"Official development channel: #Glide64 on EFnet\nNO ROM REQUESTS / NO BETA REQUESTS");
1193
}
1194
#endif
1195
1196
/******************************************************************
1197
Function: DllTest
1198
Purpose: This function is optional function that is provided
1199
to allow the user to test the dll
1200
input: a handle to the window that calls this function
1201
output: none
1202
*******************************************************************/
1203
EXPORT void CALL DllTest ( HWND hParent )
1204
{
1205
}
1206
1207
/******************************************************************
1208
Function: DrawScreen
1209
Purpose: This function is called when the emulator receives a
1210
WM_PAINT message. This allows the gfx to fit in when
1211
it is being used in the desktop.
1212
input: none
1213
output: none
1214
*******************************************************************/
1215
EXPORT void CALL DrawScreen (void)
1216
{
1217
LOG ("DrawScreen ()\n");
1218
}
1219
1220
/******************************************************************
1221
Function: GetDllInfo
1222
Purpose: This function allows the emulator to gather information
1223
about the dll by filling in the PluginInfo structure.
1224
input: a pointer to a PLUGIN_INFO stucture that needs to be
1225
filled by the function. (see def above)
1226
output: none
1227
*******************************************************************/
1228
EXPORT void CALL GetDllInfo ( PLUGIN_INFO * PluginInfo )
1229
{
1230
PluginInfo->Version = 0x0103; // Set to 0x0103
1231
PluginInfo->Type = PLUGIN_TYPE_GFX; // Set to PLUGIN_TYPE_GFX
1232
sprintf (PluginInfo->Name, "Glide64 "G64_VERSION); // Name of the DLL
1233
1234
// If DLL supports memory these memory options then set them to TRUE or FALSE
1235
// if it does not support it
1236
PluginInfo->NormalMemory = TRUE; // a normal BYTE array
1237
PluginInfo->MemoryBswaped = TRUE; // a normal BYTE array where the memory has been pre
1238
// bswap on a dword (32 bits) boundry
1239
}
1240
1241
#ifndef WIN32
1242
BOOL WINAPI QueryPerformanceCounter(PLARGE_INTEGER counter)
1243
{
1244
struct timeval tv;
1245
1246
/* generic routine */
1247
gettimeofday( &tv, NULL );
1248
counter->QuadPart = (LONGLONG)tv.tv_usec + (LONGLONG)tv.tv_sec * 1000000;
1249
return TRUE;
1250
}
1251
1252
BOOL WINAPI QueryPerformanceFrequency(PLARGE_INTEGER frequency)
1253
{
1254
frequency->s.LowPart= 1000000;
1255
frequency->s.HighPart= 0;
1256
return TRUE;
1257
}
1258
#endif
1259
1260
/******************************************************************
1261
Function: InitiateGFX
1262
Purpose: This function is called when the DLL is started to give
1263
information from the emulator that the n64 graphics
1264
uses. This is not called from the emulation thread.
1265
Input: Gfx_Info is passed to this function which is defined
1266
above.
1267
Output: TRUE on success
1268
FALSE on failure to initialise
1269
1270
** note on interrupts **:
1271
To generate an interrupt set the appropriate bit in MI_INTR_REG
1272
and then call the function CheckInterrupts to tell the emulator
1273
that there is a waiting interrupt.
1274
*******************************************************************/
1275
1276
EXPORT BOOL CALL InitiateGFX (GFX_INFO Gfx_Info)
1277
{
1278
LOG ("InitiateGFX (*)\n");
1279
// Do *NOT* put this in rdp_reset or it could be set after the screen is initialized
1280
num_tmu = 2;
1281
1282
// Assume scale of 1 for debug purposes
1283
rdp.scale_x = 1.0f;
1284
rdp.scale_y = 1.0f;
1285
1286
memset (&settings, 0, sizeof(SETTINGS));
1287
ReadSettings ();
1288
1289
#ifdef FPS
1290
QueryPerformanceFrequency (&perf_freq);
1291
QueryPerformanceCounter (&fps_last);
1292
#endif
1293
1294
debug_init (); // Initialize debugger
1295
1296
gfx = Gfx_Info;
1297
/*
1298
char name[21];
1299
// get the name of the ROM
1300
for (int i=0; i<20; i++)
1301
name[i] = gfx.HEADER[(32+i)^3];
1302
name[20] = 0;
1303
1304
// remove all trailing spaces
1305
while (name[strlen(name)-1] == ' ')
1306
name[strlen(name)-1] = 0;
1307
1308
ReadSpecialSettings (name);
1309
*/
1310
#ifdef WINPROC_OVERRIDE
1311
if (!oldWndProc)
1312
{
1313
myWndProc = (WNDPROC)WndProc;
1314
oldWndProc = (WNDPROC)SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)myWndProc);
1315
}
1316
#endif
1317
1318
util_init ();
1319
math_init ();
1320
TexCacheInit ();
1321
CRC_BuildTable();
1322
CountCombine();
1323
if (settings.fb_depth_render)
1324
ZLUT_init();
1325
1326
return TRUE;
1327
}
1328
1329
/******************************************************************
1330
Function: MoveScreen
1331
Purpose: This function is called in response to the emulator
1332
receiving a WM_MOVE passing the xpos and ypos passed
1333
from that message.
1334
input: xpos - the x-coordinate of the upper-left corner of the
1335
client area of the window.
1336
ypos - y-coordinate of the upper-left corner of the
1337
client area of the window.
1338
output: none
1339
*******************************************************************/
1340
EXPORT void CALL MoveScreen (int xpos, int ypos)
1341
{
1342
LOG ("MoveScreen");
1343
}
1344
1345
/******************************************************************
1346
Function: ProcessRDPList
1347
Purpose: This function is called when there is a Dlist to be
1348
processed. (Low level GFX list)
1349
input: none
1350
output: none
1351
*******************************************************************/
1352
#if 0
1353
EXPORT void CALL ProcessRDPList(void)
1354
{
1355
if (settings.KI)
1356
{
1357
*gfx.MI_INTR_REG |= 0x20;
1358
gfx.CheckInterrupts();
1359
}
1360
LOG ("ProcessRDPList ()\n");
1361
printf("ProcessRPDList %x %x %x\n",
1362
*gfx.DPC_START_REG,
1363
*gfx.DPC_END_REG,
1364
*gfx.DPC_CURRENT_REG);
1365
//*gfx.DPC_STATUS_REG = 0xffffffff; // &= ~0x0002;
1366
1367
//*gfx.DPC_START_REG = *gfx.DPC_END_REG;
1368
*gfx.DPC_CURRENT_REG = *gfx.DPC_END_REG;
1369
}
1370
#endif
1371
1372
/******************************************************************
1373
Function: ResizeVideoOutput
1374
Purpose: This function is called to force us to resize our output OpenGL window.
1375
This is currently unsupported, and should never be called because we do
1376
not pass the RESIZABLE flag to VidExt_SetVideoMode when initializing.
1377
input: new width and height
1378
output: none
1379
*******************************************************************/
1380
EXPORT void CALL ResizeVideoOutput(int Width, int Height)
1381
{
1382
}
1383
1384
/******************************************************************
1385
Function: RomClosed
1386
Purpose: This function is called when a rom is closed.
1387
input: none
1388
output: none
1389
*******************************************************************/
1390
EXPORT void CALL RomClosed (void)
1391
{
1392
LOG ("RomClosed ()\n");
1393
1394
CLOSE_RDP_LOG ();
1395
CLOSE_RDP_E_LOG ();
1396
rdp.window_changed = TRUE;
1397
romopen = FALSE;
1398
if (fullscreen && evoodoo)
1399
ReleaseGfx ();
1400
CoreVideo_Quit();
1401
}
1402
1403
BOOL no_dlist = TRUE;
1404
1405
/******************************************************************
1406
Function: RomOpen
1407
Purpose: This function is called when a rom is open. (from the
1408
emulation thread)
1409
input: none
1410
output: none
1411
*******************************************************************/
1412
EXPORT int CALL RomOpen (void)
1413
{
1414
LOG ("RomOpen ()\n");
1415
if (CoreVideo_Init() != M64ERR_SUCCESS)
1416
{
1417
WriteLog(M64MSG_ERROR, "Could not initialize video!");
1418
return false;
1419
}
1420
1421
no_dlist = TRUE;
1422
romopen = TRUE;
1423
ucode_error_report = TRUE; // allowed to report ucode errors
1424
1425
// Get the country code & translate to NTSC(0) or PAL(1)
1426
WORD code = ((WORD*)gfx.HEADER)[0x1F^1];
1427
1428
if (code == 0x4400) region = 1; // Germany (PAL)
1429
if (code == 0x4500) region = 0; // USA (NTSC)
1430
if (code == 0x4A00) region = 0; // Japan (NTSC)
1431
if (code == 0x5000) region = 1; // Europe (PAL)
1432
if (code == 0x5500) region = 0; // Australia (NTSC)
1433
1434
char name[21] = "DEFAULT";
1435
ReadSpecialSettings (name);
1436
1437
// get the name of the ROM
1438
for (int i=0; i<20; i++)
1439
name[i] = gfx.HEADER[(32+i)^3];
1440
name[20] = 0;
1441
1442
// remove all trailing spaces
1443
while (name[strlen(name)-1] == ' ')
1444
name[strlen(name)-1] = 0;
1445
1446
ReadSpecialSettings (name);
1447
1448
1449
WriteLog(M64MSG_INFO, "fb_clear %d fb_smart %d\n", settings.fb_depth_clear, settings.fb_smart);
1450
1451
1452
rdp_reset ();
1453
ClearCache ();
1454
1455
OPEN_RDP_LOG ();
1456
OPEN_RDP_E_LOG ();
1457
1458
// ** EVOODOO EXTENSIONS **
1459
if (!fullscreen)
1460
{
1461
grGlideInit ();
1462
grSstSelect (0);
1463
}
1464
const char *extensions = grGetString (GR_EXTENSION);
1465
WriteLog(M64MSG_INFO, "extensions '%s'\n", extensions);
1466
if (!fullscreen)
1467
{
1468
grGlideShutdown ();
1469
1470
if (strstr (extensions, "EVOODOO"))
1471
evoodoo = 1;
1472
else
1473
evoodoo = 0;
1474
1475
if (evoodoo)
1476
InitGfx (TRUE);
1477
}
1478
1479
if (strstr (extensions, "ROMNAME"))
1480
{
1481
void (__stdcall *grSetRomName)(char*);
1482
grSetRomName = (void (__stdcall *)(char*))grGetProcAddress ("grSetRomName");
1483
grSetRomName (name);
1484
}
1485
// **
1486
return true;
1487
}
1488
1489
/******************************************************************
1490
Function: ShowCFB
1491
Purpose: Useally once Dlists are started being displayed, cfb is
1492
ignored. This function tells the dll to start displaying
1493
them again.
1494
input: none
1495
output: none
1496
*******************************************************************/
1497
EXPORT void CALL ShowCFB (void)
1498
{
1499
no_dlist = TRUE;
1500
LOG ("ShowCFB ()\n");
1501
}
1502
1503
EXPORT void CALL SetRenderingCallback(void (*callback)(int))
1504
{
1505
renderCallback = callback;
1506
}
1507
1508
/******************************************************************
1509
Function: UpdateScreen
1510
Purpose: This function is called in response to a vsync of the
1511
screen were the VI bit in MI_INTR_REG has already been
1512
set
1513
input: none
1514
output: none
1515
*******************************************************************/
1516
DWORD update_screen_count = 0;
1517
EXPORT void CALL UpdateScreen (void)
1518
{
1519
#ifdef LOG_KEY
1520
if (GetAsyncKeyState (VK_SPACE) & 0x0001)
1521
{
1522
LOG ("KEY!!!\n");
1523
}
1524
#endif
1525
char out_buf[512];
1526
sprintf (out_buf, "UpdateScreen (). distance: %d\n", (int)(*gfx.VI_ORIGIN_REG) - (int)((*gfx.VI_WIDTH_REG) << 2));
1527
LOG (out_buf);
1528
// LOG ("UpdateScreen ()\n");
1529
1530
DWORD width = (*gfx.VI_WIDTH_REG) << 1;
1531
if (fullscreen && (*gfx.VI_ORIGIN_REG > width))
1532
update_screen_count++;
1533
1534
// vertical interrupt has occured, increment counter
1535
vi_count ++;
1536
1537
#ifdef FPS
1538
// Check frames per second
1539
LARGE_INTEGER difference;
1540
QueryPerformanceCounter (&fps_next);
1541
difference.QuadPart = fps_next.QuadPart - fps_last.QuadPart;
1542
float diff_secs = (float)((double)difference.QuadPart / (double)perf_freq.QuadPart);
1543
if (diff_secs > 0.5f)
1544
{
1545
fps = (float)fps_count / diff_secs;
1546
vi = (float)vi_count / diff_secs;
1547
ntsc_percent = vi / 0.6f;
1548
pal_percent = vi / 0.5f;
1549
fps_last = fps_next;
1550
fps_count = 0;
1551
vi_count = 0;
1552
}
1553
#endif
1554
//*
1555
DWORD limit = settings.lego ? 15 : 50;
1556
if (settings.cpu_write_hack && (update_screen_count > limit) && (rdp.last_bg == 0))
1557
{
1558
RDP("DirectCPUWrite hack!\n");
1559
update_screen_count = 0;
1560
no_dlist = TRUE;
1561
ClearCache ();
1562
UpdateScreen();
1563
return;
1564
}
1565
//*/
1566
//*
1567
if( no_dlist )
1568
{
1569
if( *gfx.VI_ORIGIN_REG > width )
1570
{
1571
ChangeSize ();
1572
RDP("ChangeSize done\n");
1573
DrawFrameBuffer();
1574
RDP("DrawFrameBuffer done\n");
1575
rdp.updatescreen = 1;
1576
newSwapBuffers ();
1577
}
1578
return;
1579
}
1580
//*/
1581
if (settings.swapmode == 0)
1582
{
1583
newSwapBuffers ();
1584
}
1585
}
1586
1587
/******************************************************************
1588
Function: ViStatusChanged
1589
Purpose: This function is called to notify the dll that the
1590
ViStatus registers value has been changed.
1591
input: none
1592
output: none
1593
*******************************************************************/
1594
EXPORT void CALL ViStatusChanged (void)
1595
{
1596
}
1597
1598
/******************************************************************
1599
Function: ViWidthChanged
1600
Purpose: This function is called to notify the dll that the
1601
ViWidth registers value has been changed.
1602
input: none
1603
output: none
1604
*******************************************************************/
1605
EXPORT void CALL ViWidthChanged (void)
1606
{
1607
}
1608
1609
#ifdef __cplusplus
1610
}
1611
#endif
1612
1613
1614
1615
1616
void drawViRegBG();
1617
void drawNoFullscreenMessage();
1618
1619
void DrawFrameBuffer ()
1620
{
1621
if (!fullscreen)
1622
{
1623
drawNoFullscreenMessage();
1624
}
1625
if (to_fullscreen)
1626
{
1627
to_fullscreen = FALSE;
1628
1629
if (!InitGfx (FALSE))
1630
{
1631
LOG ("FAILED!!!\n");
1632
return;
1633
}
1634
fullscreen = TRUE;
1635
}
1636
1637
if (fullscreen)
1638
{
1639
grDepthMask (FXTRUE);
1640
grColorMask (FXTRUE, FXTRUE);
1641
grBufferClear (0, 0, 0xFFFF);
1642
drawViRegBG();
1643
}
1644
}
1645
1646
DWORD curframe = 0;
1647
void newSwapBuffers()
1648
{
1649
if (rdp.updatescreen)
1650
{
1651
rdp.updatescreen = 0;
1652
1653
RDP ("swapped\n");
1654
1655
// Allow access to the whole screen
1656
if (fullscreen)
1657
{
1658
grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y);
1659
grDepthBufferFunction (GR_CMP_ALWAYS);
1660
grDepthMask (FXFALSE);
1661
1662
grCullMode (GR_CULL_DISABLE);
1663
1664
if ((settings.show_fps & 0xF) || settings.clock)
1665
set_message_combiner ();
1666
#ifdef FPS
1667
float y = (float)settings.res_y;
1668
if (settings.show_fps & 0x0F)
1669
{
1670
if (settings.show_fps & 4)
1671
{
1672
if (region) // PAL
1673
output (0, y, 0, "%d%% ", (int)pal_percent);
1674
else
1675
output (0, y, 0, "%d%% ", (int)ntsc_percent);
1676
y -= 16;
1677
}
1678
if (settings.show_fps & 2)
1679
{
1680
output (0, y, 0, "VI/s: %.02f ", vi);
1681
y -= 16;
1682
}
1683
if (settings.show_fps & 1)
1684
output (0, y, 0, "FPS: %.02f ", fps);
1685
}
1686
#endif
1687
1688
if (settings.clock)
1689
{
1690
if (settings.clock_24_hr)
1691
{
1692
time_t ltime;
1693
time (&ltime);
1694
tm *cur_time = localtime (&ltime);
1695
1696
sprintf (out_buf, "%.2d:%.2d:%.2d", cur_time->tm_hour, cur_time->tm_min, cur_time->tm_sec);
1697
}
1698
else
1699
{
1700
char ampm[] = "AM";
1701
time_t ltime;
1702
1703
time (&ltime);
1704
tm *cur_time = localtime (&ltime);
1705
1706
if (cur_time->tm_hour >= 12)
1707
{
1708
strcpy (ampm, "PM");
1709
if (cur_time->tm_hour != 12)
1710
cur_time->tm_hour -= 12;
1711
}
1712
if (cur_time->tm_hour == 0)
1713
cur_time->tm_hour = 12;
1714
1715
if (cur_time->tm_hour >= 10)
1716
sprintf (out_buf, "%.5s %s", asctime(cur_time) + 11, ampm);
1717
else
1718
sprintf (out_buf, " %.4s %s", asctime(cur_time) + 12, ampm);
1719
}
1720
output ((float)(settings.res_x - 68), y, 0, out_buf, 0);
1721
}
1722
}
1723
1724
// Capture the screen if debug capture is set
1725
if (debug.capture)
1726
{
1727
// Allocate the screen
1728
debug.screen = new BYTE [(settings.res_x*settings.res_y) << 1];
1729
1730
// Lock the backbuffer (already rendered)
1731
GrLfbInfo_t info;
1732
info.size = sizeof(GrLfbInfo_t);
1733
while (!grLfbLock (GR_LFB_READ_ONLY,
1734
GR_BUFFER_BACKBUFFER,
1735
GR_LFBWRITEMODE_565,
1736
GR_ORIGIN_UPPER_LEFT,
1737
FXFALSE,
1738
&info));
1739
1740
DWORD offset_src=0/*(settings.scr_res_y-settings.res_y)*info.strideInBytes*/, offset_dst=0;
1741
1742
// Copy the screen
1743
for (DWORD y=0; y<settings.res_y; y++)
1744
{
1745
memcpy (debug.screen + offset_dst, (BYTE*)info.lfbPtr + offset_src, settings.res_x << 1);
1746
offset_dst += settings.res_x << 1;
1747
offset_src += info.strideInBytes;
1748
}
1749
1750
// Unlock the backbuffer
1751
grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER);
1752
}
1753
1754
if (fullscreen)
1755
{
1756
LOG ("BUFFER SWAPPED\n");
1757
grBufferSwap (settings.vsync);
1758
fps_count ++;
1759
}
1760
1761
if (fullscreen && (debugging || settings.wireframe || settings.buff_clear))
1762
{
1763
if (settings.RE2 && settings.fb_depth_render)
1764
grDepthMask (FXFALSE);
1765
else
1766
grDepthMask (FXTRUE);
1767
grBufferClear (0, 0, 0xFFFF);
1768
}
1769
1770
frame_count ++;
1771
}
1772
}
1773
1774
1775
#ifdef WINPROC_OVERRIDE
1776
LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1777
{
1778
switch (msg)
1779
{
1780
case WM_ACTIVATE:
1781
rdp.window_changed = TRUE;
1782
break;
1783
1784
/* case WM_DESTROY:
1785
SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
1786
break;*/
1787
}
1788
1789
return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam);
1790
}
1791
#endif
1792
1793
BOOL k_ctl=0, k_alt=0, k_del=0;
1794
1795
#ifdef ALTTAB_FIX
1796
LRESULT CALLBACK LowLevelKeyboardProc(int nCode,
1797
WPARAM wParam, LPARAM lParam) {
1798
if (!fullscreen) return CallNextHookEx(NULL, nCode, wParam, lParam);
1799
1800
BOOL TabKey = FALSE;
1801
1802
PKBDLLHOOKSTRUCT p;
1803
1804
if (nCode == HC_ACTION)
1805
{
1806
switch (wParam) {
1807
case WM_KEYUP: case WM_SYSKEYUP:
1808
p = (PKBDLLHOOKSTRUCT) lParam;
1809
if (p->vkCode == 162) k_ctl = 0;
1810
if (p->vkCode == 164) k_alt = 0;
1811
if (p->vkCode == 46) k_del = 0;
1812
goto do_it;
1813
1814
case WM_KEYDOWN: case WM_SYSKEYDOWN:
1815
p = (PKBDLLHOOKSTRUCT) lParam;
1816
if (p->vkCode == 162) k_ctl = 1;
1817
if (p->vkCode == 164) k_alt = 1;
1818
if (p->vkCode == 46) k_del = 1;
1819
goto do_it;
1820
1821
do_it:
1822
TabKey =
1823
((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
1824
((p->vkCode == VK_ESCAPE) && ((p->flags & LLKHF_ALTDOWN) != 0)) ||
1825
((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) & 0x8000) != 0)) ||
1826
(k_ctl && k_alt && k_del);
1827
1828
break;
1829
}
1830
}
1831
1832
if (TabKey)
1833
{
1834
k_ctl = 0;
1835
k_alt = 0;
1836
k_del = 0;
1837
ReleaseGfx ();
1838
}
1839
1840
return CallNextHookEx(NULL, nCode, wParam, lParam);
1841
}
1842
#endif
1843
1844
1845