Mercurial > vba-linux
comparison src/win32/VBA.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // VBA.cpp : Defines the class behaviors for the application. | |
2 // | |
3 #include "stdafx.h" | |
4 #include <mmsystem.h> | |
5 #include <cassert> | |
6 | |
7 #include "resource.h" | |
8 #include "VBA.h" | |
9 #include "AVIWrite.h" | |
10 #include "Input.h" | |
11 #include "IUpdate.h" | |
12 #include "LangSelect.h" | |
13 #include "MainWnd.h" | |
14 #include "Reg.h" | |
15 #include "WavWriter.h" | |
16 #include "WinResUtil.h" | |
17 #include "WinMiscUtil.h" | |
18 #include "ramwatch.h" | |
19 | |
20 #include "../gba/GBA.h" | |
21 #include "../gba/GBAGlobals.h" | |
22 #include "../gba/agbprint.h" | |
23 #include "../gb/GB.h" | |
24 #include "../gb/gbGlobals.h" | |
25 #include "../gb/gbPrinter.h" | |
26 #include "../common/CheatSearch.h" | |
27 #include "../gba/RTC.h" | |
28 #include "../gba/GBASound.h" | |
29 #include "../common/Util.h" | |
30 #include "../common/Text.h" | |
31 #include "../common/movie.h" | |
32 #include "../common/nesvideos-piece.h" | |
33 #include "../common/vbalua.h" | |
34 #include "../filters/filters.h" | |
35 #include "../version.h" | |
36 | |
37 extern IDisplay *newGDIDisplay(); | |
38 extern IDisplay *newDirectDrawDisplay(); | |
39 extern IDisplay *newDirect3DDisplay(); | |
40 extern IDisplay *newOpenGLDisplay(); | |
41 | |
42 extern Input *newDirectInput(); | |
43 | |
44 extern void remoteStubSignal(int, int); | |
45 extern void remoteOutput(char *, u32); | |
46 extern void remoteStubMain(); | |
47 extern void remoteSetProtocol(int); | |
48 extern void remoteCleanUp(); | |
49 extern int remoteSocket; | |
50 | |
51 void winlog(const char *msg, ...); | |
52 | |
53 bool debugger = false; | |
54 | |
55 char movieFileToPlay[1024]; | |
56 bool playMovieFile = false; | |
57 bool playMovieFileReadOnly = false; | |
58 char wavFileToOutput [1024]; | |
59 bool outputWavFile = false; | |
60 bool outputAVIFile = false; | |
61 bool flagHideMenu = false; | |
62 int quitAfterTime = -1; | |
63 int pauseAfterTime = -1; | |
64 | |
65 void winSignal(int, int); | |
66 void winOutput(char *, u32); | |
67 | |
68 void (*dbgSignal)(int, int) = winSignal; | |
69 void (*dbgOutput)(char *, u32) = winOutput; | |
70 | |
71 #ifdef MMX | |
72 extern "C" bool cpu_mmx; | |
73 #endif | |
74 | |
75 // nowhere good to put them to | |
76 | |
77 void DrawTextMessages(u8 *dest, int pitch, int left, int bottom) | |
78 { | |
79 for (int slot = 0; slot < SCREEN_MESSAGE_SLOTS; slot++) | |
80 { | |
81 if (theApp.screenMessage[slot]) | |
82 { | |
83 if ((theApp.screenMessageDuration[slot] < 0 || | |
84 (int)(GetTickCount() - theApp.screenMessageTime[slot]) < theApp.screenMessageDuration[slot]) && | |
85 (!theApp.disableStatusMessage || slot == 1 || slot == 2)) | |
86 { | |
87 drawText(dest, | |
88 pitch, | |
89 left, | |
90 bottom - 10 * (slot + 1), | |
91 theApp.screenMessageBuffer[slot], | |
92 theApp.screenMessageColorBuffer[slot]); | |
93 } | |
94 else | |
95 { | |
96 theApp.screenMessage[slot] = false; | |
97 } | |
98 } | |
99 } | |
100 } | |
101 | |
102 // draw Lua graphics in game screen | |
103 void DrawLuaGui() | |
104 { | |
105 int copyX = 240, copyY = 160; | |
106 int screenX = 240, screenY = 160; | |
107 int copyOffsetX = 0, copyOffsetY = 0; | |
108 if (systemCartridgeType == 1) | |
109 { | |
110 if (gbBorderOn) | |
111 { | |
112 copyX = 256, copyY = 224; | |
113 screenX = 256, screenY = 224; | |
114 } | |
115 else | |
116 { | |
117 copyX = 160, copyY = 144; | |
118 screenX = 160, screenY = 144; | |
119 } | |
120 } | |
121 int pitch = copyX * (systemColorDepth / 8) + (systemColorDepth == 24 ? 0 : 4); | |
122 | |
123 ++copyOffsetY; // don't know why it's needed | |
124 | |
125 VBALuaGui(&pix[copyOffsetY * pitch + copyOffsetX * (systemColorDepth / 8)], copyX, screenX, screenY); | |
126 VBALuaClearGui(); | |
127 } | |
128 | |
129 void directXMessage(const char *msg) | |
130 { | |
131 systemMessage( | |
132 IDS_DIRECTX_7_REQUIRED, | |
133 "DirectX 7.0 or greater is required to run.\nDownload at http://www.microsoft.com/directx.\n\nError found at: %s", | |
134 msg); | |
135 } | |
136 | |
137 void winlog(const char *msg, ...) | |
138 { | |
139 CString buffer; | |
140 va_list valist; | |
141 | |
142 va_start(valist, msg); | |
143 buffer.FormatV(msg, valist); | |
144 | |
145 FILE *winout = fopen("vba-trace.log", "w"); | |
146 | |
147 fputs(buffer, winout); | |
148 | |
149 fclose(winout); | |
150 | |
151 va_end(valist); | |
152 } | |
153 | |
154 // code from SDL_main.c for Windows | |
155 /* Parse a command line buffer into arguments */ | |
156 | |
157 static int parseCommandLine(char *cmdline, char * *argv) | |
158 { | |
159 char *bufp; | |
160 int argc; | |
161 | |
162 argc = 0; | |
163 for (bufp = cmdline; *bufp; ) | |
164 { | |
165 /* Skip leading whitespace */ | |
166 while (isspace(*bufp)) | |
167 { | |
168 ++bufp; | |
169 } | |
170 /* Skip over argument */ | |
171 if (*bufp == '"') | |
172 { | |
173 ++bufp; | |
174 if (*bufp) | |
175 { | |
176 if (argv) | |
177 { | |
178 argv[argc] = bufp; | |
179 } | |
180 ++argc; | |
181 } | |
182 /* Skip over word */ | |
183 while (*bufp && (*bufp != '"')) | |
184 { | |
185 ++bufp; | |
186 } | |
187 } | |
188 else | |
189 { | |
190 if (*bufp) | |
191 { | |
192 if (argv) | |
193 { | |
194 argv[argc] = bufp; | |
195 } | |
196 ++argc; | |
197 } | |
198 /* Skip over word */ | |
199 while (*bufp && !isspace(*bufp)) | |
200 { | |
201 ++bufp; | |
202 } | |
203 } | |
204 if (*bufp) | |
205 { | |
206 if (argv) | |
207 { | |
208 *bufp = '\0'; | |
209 } | |
210 ++bufp; | |
211 } | |
212 } | |
213 if (argv) | |
214 { | |
215 argv[argc] = NULL; | |
216 } | |
217 return(argc); | |
218 } | |
219 | |
220 static void debugSystemScreenMessage1(const char *msg) | |
221 { | |
222 systemScreenMessage(msg, 3); | |
223 } | |
224 | |
225 static void debugSystemScreenMessage2(const char *msg) | |
226 { | |
227 systemScreenMessage(msg, 4); | |
228 } | |
229 | |
230 static void winSignal(int, int) | |
231 {} | |
232 | |
233 #define CPUReadByteQuick(addr) \ | |
234 map[(addr) >> 24].address[(addr) & map[(addr) >> 24].mask] | |
235 | |
236 static void winOutput(char *s, u32 addr) | |
237 { | |
238 if (s) | |
239 { | |
240 log(s); | |
241 } | |
242 else | |
243 { | |
244 CString str; | |
245 char c; | |
246 | |
247 c = CPUReadByteQuick(addr); | |
248 addr++; | |
249 while (c) | |
250 { | |
251 str += c; | |
252 c = CPUReadByteQuick(addr); | |
253 addr++; | |
254 } | |
255 log(str); | |
256 } | |
257 } | |
258 | |
259 typedef BOOL (WINAPI * GETMENUBARINFO)(HWND, LONG, LONG, PMENUBARINFO); | |
260 | |
261 static int winGetMenuBarHeight() | |
262 { | |
263 HINSTANCE hinstDll = /**/ ::LoadLibrary("USER32.DLL"); | |
264 | |
265 if (hinstDll) | |
266 { | |
267 GETMENUBARINFO func = (GETMENUBARINFO)GetProcAddress(hinstDll, "GetMenuBarInfo"); | |
268 | |
269 if (func) | |
270 { | |
271 MENUBARINFO info; | |
272 info.cbSize = sizeof(info); | |
273 | |
274 func(AfxGetMainWnd()->GetSafeHwnd(), OBJID_MENU, 0, &info); | |
275 | |
276 /**/ ::FreeLibrary(hinstDll); | |
277 | |
278 return info.rcBar.bottom - info.rcBar.top + 1; | |
279 } | |
280 } | |
281 | |
282 return GetSystemMetrics(SM_CYMENU); | |
283 } | |
284 | |
285 ///////////////////////////////////////////////////////////////////////////// | |
286 // VBA | |
287 | |
288 BEGIN_MESSAGE_MAP(VBA, CWinApp) | |
289 //{{AFX_MSG_MAP(VBA) | |
290 // NOTE - the ClassWizard will add and remove mapping macros here. | |
291 // DO NOT EDIT what you see in these blocks of generated code! | |
292 //}}AFX_MSG_MAP | |
293 END_MESSAGE_MAP() | |
294 | |
295 ///////////////////////////////////////////////////////////////////////////// | |
296 // The one and only VBA object | |
297 | |
298 VBA theApp; | |
299 | |
300 ///////////////////////////////////////////////////////////////////////////// | |
301 // VBA construction | |
302 | |
303 VBA::VBA() : emulator(::theEmulator) | |
304 { | |
305 // important | |
306 { | |
307 #ifdef MULTITHREAD_STDLOCALE_WORKAROUND | |
308 // Note: there's a known threading bug regarding std::locale with MSVC according to | |
309 // http://connect.microsoft.com/VisualStudio/feedback/details/492128/std-locale-constructor-modifies-global-locale-via-setlocale | |
310 int iPreviousFlag = ::_configthreadlocale(_ENABLE_PER_THREAD_LOCALE); | |
311 #endif | |
312 using std::locale; | |
313 locale::global(locale(locale::classic(), "", locale::collate | locale::ctype)); | |
314 | |
315 #ifdef MULTITHREAD_STDLOCALE_WORKAROUND | |
316 if (iPreviousFlag > 0 ) | |
317 ::_configthreadlocale(iPreviousFlag); | |
318 #endif | |
319 } | |
320 | |
321 mode320Available = false; | |
322 mode640Available = false; | |
323 mode800Available = false; | |
324 windowPositionX = 0; | |
325 windowPositionY = 0; | |
326 filterFunction = NULL; | |
327 ifbFunction = NULL; | |
328 ifbType = 0; | |
329 filterType = 0; | |
330 filterWidth = 0; | |
331 filterHeight = 0; | |
332 fsWidth = 0; | |
333 fsHeight = 0; | |
334 fsColorDepth = 0; | |
335 fsForceChange = false; | |
336 surfaceSizeX = 0; | |
337 surfaceSizeY = 0; | |
338 sizeX = 0; | |
339 sizeY = 0; | |
340 videoOption = 0; | |
341 fullScreenStretch = false; | |
342 disableStatusMessage = false; | |
343 showSpeed = 1; | |
344 showSpeedTransparent = true; | |
345 showRenderedFrames = 0; | |
346 for (int j = 0; j < SCREEN_MESSAGE_SLOTS; j++) | |
347 { | |
348 screenMessage[j] = false; | |
349 screenMessageTime[j] = 0; | |
350 screenMessageDuration[j] = 0; | |
351 } | |
352 menuToggle = true; | |
353 display = NULL; | |
354 menu = NULL; | |
355 popup = NULL; | |
356 soundInitialized = false; | |
357 useBiosFile = false; | |
358 skipBiosFile = false; | |
359 active = true; | |
360 paused = false; | |
361 recentFreeze = false; | |
362 autoSaveLoadCheatList = false; | |
363 pauseDuringCheatSearch = false; | |
364 modelessCheatDialogIsOpen = false; | |
365 // winout = NULL; | |
366 // removeIntros = false; | |
367 autoIPS = true; | |
368 winGbBorderOn = 0; | |
369 hideMovieBorder = false; | |
370 winFlashSize = 0x10000; | |
371 winRtcEnable = false; | |
372 winSaveType = 0; | |
373 rewindMemory = NULL; | |
374 frameSearchMemory = NULL; | |
375 rewindPos = 0; | |
376 rewindTopPos = 0; | |
377 rewindCounter = 0; | |
378 rewindCount = 0; | |
379 rewindSaveNeeded = false; | |
380 rewindTimer = 0; | |
381 captureFormat = 0; | |
382 tripleBuffering = true; | |
383 autoHideMenu = false; | |
384 throttle = 100; | |
385 throttleLastTime = 0; | |
386 /// autoFrameSkipLastTime = 0; | |
387 /// autoFrameSkip = false; | |
388 vsync = false; | |
389 changingVideoSize = false; | |
390 pVideoDriverGUID = NULL; | |
391 renderMethod = DIRECT_DRAW; | |
392 iconic = false; | |
393 ddrawEmulationOnly = false; | |
394 ddrawUsingEmulationOnly = false; | |
395 ddrawDebug = false; | |
396 ddrawUseVideoMemory = false; | |
397 d3dFilter = 0; | |
398 glFilter = 0; | |
399 glType = 0; | |
400 regEnabled = false; | |
401 pauseWhenInactive = true; | |
402 muteWhenInactive = true; | |
403 enableBackgroundInput = false; | |
404 alwaysOnTop = false; | |
405 filenamePreference = true; | |
406 frameCounter = false; | |
407 lagCounter = false; | |
408 extraCounter = false; | |
409 inputDisplay = false; | |
410 speedupToggle = false; | |
411 useOldSync = false; | |
412 allowLeftRight = false; | |
413 autofireAccountForLag = false; | |
414 nextframeAccountForLag = false; | |
415 muteFrameAdvance = false; | |
416 muteWhenInactive = false; | |
417 winMuteForNow = false; | |
418 winGbPrinterEnabled = false; | |
419 threadPriority = 2; | |
420 disableMMX = false; | |
421 languageOption = 0; | |
422 languageModule = NULL; | |
423 languageName = ""; | |
424 renderedFrames = 0; | |
425 input = NULL; | |
426 joypadDefault = 0; | |
427 autoFire = 0; | |
428 autoFire2 = 0; | |
429 autoHold = 0; | |
430 autoFireToggle = false; | |
431 winPauseNextFrame = false; | |
432 soundRecording = false; | |
433 soundRecorder = NULL; | |
434 sound = NULL; | |
435 aviRecording = false; | |
436 aviRecorder = NULL; | |
437 painting = false; | |
438 mouseCounter = 0; | |
439 movieReadOnly = true; | |
440 movieOnEndPause = false; | |
441 movieOnEndBehavior = 0; | |
442 wasPaused = false; | |
443 fsMaxScale = 0; | |
444 romSize = 0; | |
445 autoLoadMostRecent = false; | |
446 loadMakesRecent = false; | |
447 loadMakesCurrent = false; | |
448 saveMakesCurrent = false; | |
449 currentSlot = 0; | |
450 showSlotTime = false; | |
451 frameSearchLoadValid = false; | |
452 frameSearching = false; | |
453 frameSearchSkipping = false; | |
454 nvVideoLog = false; | |
455 nvAudioLog = false; | |
456 LoggingEnabled = 0; | |
457 /// FPS = 60; | |
458 | |
459 updateCount = 0; | |
460 | |
461 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; | |
462 | |
463 ZeroMemory(&emulator, sizeof(emulator)); | |
464 | |
465 hAccel = NULL; | |
466 | |
467 for (int i = 0; i < 24; ) | |
468 { | |
469 systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10); | |
470 systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10); | |
471 systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10); | |
472 systemGbPalette[i++] = 0; | |
473 } | |
474 | |
475 VBAMovieInit(); | |
476 | |
477 TIMECAPS tc; | |
478 if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) == TIMERR_NOERROR) | |
479 { | |
480 wmTimerRes = min(max(tc.wPeriodMin, 1), tc.wPeriodMax); | |
481 timeBeginPeriod(wmTimerRes); | |
482 } | |
483 else | |
484 { | |
485 wmTimerRes = 5; | |
486 timeBeginPeriod(wmTimerRes); | |
487 } | |
488 } | |
489 | |
490 VBA::~VBA() | |
491 { | |
492 if (VBAMovieActive()) | |
493 VBAMovieStop(true); | |
494 | |
495 saveSettings(); | |
496 | |
497 InterframeCleanup(); | |
498 | |
499 if (aviRecorder) | |
500 { | |
501 delete aviRecorder; | |
502 aviRecorder = NULL; | |
503 aviRecording = false; | |
504 } | |
505 | |
506 if (soundRecorder) | |
507 { | |
508 delete soundRecorder; | |
509 soundRecorder = NULL; | |
510 } | |
511 soundRecording = false; | |
512 soundPause(); | |
513 soundShutdown(); | |
514 | |
515 ((MainWnd *)(m_pMainWnd))->winFileClose(); | |
516 | |
517 if (input) | |
518 delete input; | |
519 | |
520 shutdownDisplay(); | |
521 | |
522 if (rewindMemory) | |
523 free(rewindMemory); | |
524 | |
525 if (frameSearchMemory) | |
526 free(frameSearchMemory); | |
527 | |
528 timeEndPeriod(wmTimerRes); | |
529 } | |
530 | |
531 ///////////////////////////////////////////////////////////////////////////// | |
532 // VBA initialization | |
533 | |
534 #include <afxdisp.h> | |
535 | |
536 BOOL VBA::InitInstance() | |
537 { | |
538 AfxEnableControlContainer(); | |
539 // Standard initialization | |
540 // If you are not using these features and wish to reduce the size | |
541 // of your final executable, you should remove from the following | |
542 // the specific initialization routines you do not need. | |
543 | |
544 //#ifdef _AFXDLL | |
545 // Enable3dControls(); // Call this when using MFC in a shared DLL | |
546 //#else | |
547 // Enable3dControlsStatic(); // Call this when linking to MFC statically | |
548 //#endif | |
549 | |
550 SetRegistryKey(_T("VBA")); | |
551 | |
552 remoteSetProtocol(0); | |
553 | |
554 systemVerbose = GetPrivateProfileInt("config", "verbose", 0, "VBA.ini"); | |
555 systemDebug = GetPrivateProfileInt("config", "debug", 0, "VBA.ini"); | |
556 ddrawDebug = GetPrivateProfileInt("config", "ddrawDebug", 0, "VBA.ini") ? true : false; | |
557 | |
558 wndClass = AfxRegisterWndClass(0, LoadCursor(IDC_ARROW), (HBRUSH)GetStockObject(BLACK_BRUSH), LoadIcon(IDI_ICON)); | |
559 | |
560 char winBuffer[2048]; | |
561 GetModuleFileName(NULL, winBuffer, 2048); | |
562 char *p = strrchr(winBuffer, '\\'); | |
563 if (p) | |
564 *p = 0; | |
565 exeDir = winBuffer; | |
566 | |
567 regInit(winBuffer); | |
568 | |
569 loadSettings(); | |
570 theApp.LuaFastForward = -1; | |
571 if (!initInput()) | |
572 return FALSE; | |
573 | |
574 if (!initDisplay()) | |
575 { | |
576 if (videoOption >= VIDEO_320x240) | |
577 { | |
578 regSetDwordValue("video", VIDEO_1X); | |
579 if (pVideoDriverGUID) | |
580 regSetDwordValue("defaultVideoDriver", TRUE); | |
581 } | |
582 return FALSE; | |
583 } | |
584 | |
585 hAccel = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR)); | |
586 | |
587 winAccelMgr.Connect((MainWnd *)m_pMainWnd); | |
588 | |
589 extern void winAccelAddCommandsFromMenu(CAcceleratorManager & mgr, CMenu * pMenu, const CString &parentStr); | |
590 extern void winAccelAddCommandsFromTable(CAcceleratorManager & mgr); | |
591 | |
592 winAccelAddCommandsFromMenu(winAccelMgr, &m_menu, CString()); | |
593 winAccelAddCommandsFromTable(winAccelMgr); | |
594 | |
595 winAccelMgr.CreateDefaultTable(); | |
596 winAccelMgr.Load(); | |
597 winAccelMgr.UpdateWndTable(); | |
598 winAccelMgr.UpdateMenu(menu); | |
599 | |
600 if (m_lpCmdLine[0]) | |
601 { | |
602 int argc = parseCommandLine(m_lpCmdLine, NULL); | |
603 char * *argv = (char * *)malloc((argc + 1) * sizeof(char *)); | |
604 parseCommandLine(m_lpCmdLine, argv); | |
605 | |
606 bool gotFlag = false, enoughArgs = false; | |
607 for (int i = 0; i < argc; i++) | |
608 { | |
609 if (argv[i][0] == '-' || gotFlag) | |
610 { | |
611 if (!gotFlag) | |
612 loadSettings(); | |
613 gotFlag = true; | |
614 if (_stricmp(argv[i], "-rom") == 0) | |
615 { | |
616 if (i + 1 >= argc || argv[i + 1][0] == '-') | |
617 goto invalidArgument; | |
618 romFilename = argv[++i]; | |
619 winCorrectPath(romFilename); | |
620 gameFilename = romFilename; | |
621 } | |
622 else if (_stricmp(argv[i], "-bios") == 0) | |
623 { | |
624 if (i + 1 >= argc || argv[i + 1][0] == '-') | |
625 goto invalidArgument; | |
626 biosFileName = argv[++i]; | |
627 winCorrectPath(biosFileName); | |
628 | |
629 //systemLoadBIOS(); | |
630 } | |
631 else if (_stricmp(argv[i], "-frameskip") == 0) | |
632 { | |
633 if (i + 1 >= argc || argv[i + 1][0] == '-') | |
634 goto invalidArgument; | |
635 frameSkip = atoi(argv[++i]); | |
636 if (frameSkip < 0) | |
637 frameSkip = 0; | |
638 if (frameSkip > 9) | |
639 frameSkip = 9; | |
640 gbFrameSkip = frameSkip; | |
641 } | |
642 else if (_stricmp(argv[i], "-throttle") == 0) | |
643 { | |
644 if (i + 1 >= argc || argv[i + 1][0] == '-') | |
645 goto invalidArgument; | |
646 throttle = atoi(argv[++i]); | |
647 if (throttle < 5) | |
648 throttle = 5; | |
649 if (throttle > 1000) | |
650 throttle = 1000; | |
651 } | |
652 else if (_stricmp(argv[i], "-throttleKeepPitch") == 0) | |
653 { | |
654 if (i + 1 >= argc || argv[i + 1][0] == '-') | |
655 goto invalidArgument; | |
656 accuratePitchThrottle = atoi(argv[++i]) != 0; | |
657 } | |
658 else if (_stricmp(argv[i], "-synchronize") == 0) | |
659 { | |
660 if (i + 1 >= argc || argv[i + 1][0] == '-') | |
661 goto invalidArgument; | |
662 synchronize = atoi(argv[++i]) != 0; | |
663 } | |
664 else if (_stricmp(argv[i], "-hideborder") == 0) | |
665 { | |
666 if (i + 1 >= argc || argv[i + 1][0] == '-') | |
667 goto invalidArgument; | |
668 hideMovieBorder = atoi(argv[++i]) != 0; | |
669 } | |
670 else if (_stricmp(argv[i], "-play") == 0) | |
671 { | |
672 playMovieFile = true; | |
673 if (i + 1 >= argc || argv[i + 1][0] == '-') | |
674 goto invalidArgument; | |
675 strcpy(movieFileToPlay, argv[++i]); | |
676 winCorrectPath(movieFileToPlay); | |
677 if (i + 1 >= argc || argv[i + 1][0] == '-') { --i; goto invalidArgument; } | |
678 playMovieFileReadOnly = atoi(argv[++i]) != 0; | |
679 } | |
680 else if (_stricmp(argv[i], "-videoLog") == 0) | |
681 { | |
682 nvVideoLog = true; | |
683 nvAudioLog = true; | |
684 LoggingEnabled = 2; | |
685 if (i + 1 >= argc || argv[i + 1][0] == '-') {} | |
686 else | |
687 NESVideoSetVideoCmd(argv[++i]); | |
688 } | |
689 else if (_stricmp(argv[i], "-logDebug") == 0) | |
690 { | |
691 NESVideoEnableDebugging(debugSystemScreenMessage1, debugSystemScreenMessage2); | |
692 } | |
693 else if (_stricmp(argv[i], "-logToFile") == 0) | |
694 { | |
695 NESVideoSetFileFuncs(fopen, fclose); | |
696 } | |
697 else if (_stricmp(argv[i], "-outputWAV") == 0) | |
698 { | |
699 outputWavFile = true; | |
700 if (i + 1 >= argc || argv[i + 1][0] == '-') | |
701 goto invalidArgument; | |
702 strcpy(wavFileToOutput, argv[++i]); | |
703 } | |
704 else if (_stricmp(argv[i], "-outputAVI") == 0) | |
705 { | |
706 outputAVIFile = true; | |
707 } | |
708 else if (_stricmp(argv[i], "-quitAfter") == 0) | |
709 { | |
710 if (i + 1 >= argc || argv[i + 1][0] == '-') | |
711 goto invalidArgument; | |
712 quitAfterTime = atoi(argv[++i]); | |
713 } | |
714 else if (_stricmp(argv[i], "-pauseAt") == 0) | |
715 { | |
716 if (i + 1 >= argc || argv[i + 1][0] == '-') | |
717 goto invalidArgument; | |
718 pauseAfterTime = atoi(argv[++i]); | |
719 } | |
720 else if (_stricmp(argv[i], "-videoScale") == 0) | |
721 { | |
722 if (i + 1 >= argc || argv[i + 1][0] == '-') | |
723 goto invalidArgument; | |
724 int size = atoi(argv[++i]); | |
725 if (size < 1) | |
726 size = 1; | |
727 if (size > 4) | |
728 size = 4; | |
729 switch (size) | |
730 { | |
731 case 1: | |
732 videoOption = VIDEO_1X; break; | |
733 case 2: | |
734 videoOption = VIDEO_2X; break; | |
735 case 3: | |
736 videoOption = VIDEO_3X; break; | |
737 case 4: | |
738 videoOption = VIDEO_4X; break; | |
739 } | |
740 } | |
741 else if (_stricmp(argv[i], "-hideMenu") == 0) | |
742 { | |
743 flagHideMenu = true; | |
744 } | |
745 else | |
746 { | |
747 enoughArgs = true; | |
748 invalidArgument: | |
749 char str [2048]; // the string is larger than 1024 bytes | |
750 strcpy(str, ""); | |
751 if (_stricmp(argv[i], "-h") != 0) | |
752 if (enoughArgs) | |
753 sprintf(str, "Invalid commandline argument %d: %s\n", i, argv[i]); | |
754 else | |
755 sprintf(str, "Not enough arguments for arg %d: %s\n", i, argv[i]); | |
756 strcat(str, "Valid commands:\n" | |
757 "-h \t\t\t displays this help\n" | |
758 "-rom filename \t\t opens the given ROM\n" | |
759 "-bios filename \t\t use the given GBA BIOS\n" | |
760 "-play filename val \t\t plays the given VBM movie (val: 1 = read-only, 0 = editable)\n" | |
761 "-outputWAV filename \t outputs WAV audio to the given file\n" | |
762 "-outputAVI \t\t outputs an AVI (you are prompted for location and codec)\n" | |
763 "-frameskip val \t\t sets the frameskip amount to the given value\n" | |
764 "-synchronize val \t\t limits running speed to sound playing speed, (0 = off, 1 = on)\n" | |
765 "-throttle val \t\t sets the throttle speed to the given percentage\n" | |
766 "-hideborder val \t\t hides SGB border, if any (0 = show, 1 = hide)\n" | |
767 "-throttleKeepPitch val \t if throttle and synch, don't change sound freq (0 = off, 1 = on)\n" | |
768 "-quitAfter val \t\t close program when frame counter == val\n" | |
769 "-pauseAt val \t\t pause (movie) once when frame counter == val\n" | |
770 "-videoScale val \t\t sets the video size (val = 1 for 1X, 2 for 2X, 3 for 3X, or 4 for 4X)\n" | |
771 "-hideMenu \t\t hides the menu until program exit\n" | |
772 "\n" | |
773 "-videoLog args \t does (nesvideos) video+audio logging with the given arguments\n" | |
774 "-logToFile \t tells logging to use fopen/fclose of args, if logging is enabled\n" | |
775 "-logDebug \t tells logging to output debug info to screen, if logging is enabled\n" | |
776 ); | |
777 theApp.winCheckFullscreen(); | |
778 AfxGetApp()->m_pMainWnd->MessageBox(str, "Commandline Help", MB_OK | MB_ICONINFORMATION); | |
779 exit(0); | |
780 } | |
781 } | |
782 else | |
783 { | |
784 // assume anything else is a ROM, for backward compatibility | |
785 romFilename = argv[i++]; | |
786 gameFilename = romFilename; | |
787 loadSettings(); | |
788 } | |
789 } | |
790 | |
791 /* | |
792 int index = filename.ReverseFind('.'); | |
793 | |
794 if (index != -1) | |
795 filename = filename.Left(index); | |
796 */ | |
797 if (romFilename.GetLength() > 0) | |
798 { | |
799 ((MainWnd *)theApp.m_pMainWnd)->winFileRun(); | |
800 } | |
801 free(argv); | |
802 } | |
803 | |
804 return TRUE; | |
805 } | |
806 | |
807 void VBA::adjustDestRect() | |
808 { | |
809 POINT point; | |
810 | |
811 point.x = 0; | |
812 point.y = 0; | |
813 | |
814 m_pMainWnd->ClientToScreen(&point); | |
815 dest.top = point.y; | |
816 dest.left = point.x; | |
817 | |
818 point.x = surfaceSizeX; | |
819 point.y = surfaceSizeY; | |
820 | |
821 m_pMainWnd->ClientToScreen(&point); | |
822 dest.bottom = point.y; | |
823 dest.right = point.x; | |
824 | |
825 if (videoOption > VIDEO_4X) | |
826 { | |
827 int menuSkip = 0; | |
828 if (menuToggle) | |
829 { | |
830 menuSkip = winGetMenuBarHeight(); | |
831 } | |
832 | |
833 if (fullScreenStretch) | |
834 { | |
835 dest.top = menuSkip; | |
836 dest.left = 0; | |
837 dest.right = fsWidth; | |
838 dest.bottom = fsHeight; | |
839 } | |
840 else | |
841 { | |
842 int top = (fsHeight - surfaceSizeY) / 2; | |
843 int left = (fsWidth - surfaceSizeX) / 2; | |
844 dest.top += top - menuSkip * 2; | |
845 dest.bottom += top; | |
846 dest.left += left; | |
847 dest.right += left; | |
848 } | |
849 } | |
850 } | |
851 | |
852 void VBA::updateIFB() | |
853 { | |
854 if (systemColorDepth == 16) | |
855 { | |
856 switch (ifbType) | |
857 { | |
858 case 0: | |
859 default: | |
860 ifbFunction = NULL; | |
861 break; | |
862 case 1: | |
863 ifbFunction = MotionBlurIB; | |
864 break; | |
865 case 2: | |
866 ifbFunction = SmartIB; | |
867 break; | |
868 } | |
869 } | |
870 else if (systemColorDepth == 32) | |
871 { | |
872 switch (ifbType) | |
873 { | |
874 case 0: | |
875 default: | |
876 ifbFunction = NULL; | |
877 break; | |
878 case 1: | |
879 ifbFunction = MotionBlurIB32; | |
880 break; | |
881 case 2: | |
882 ifbFunction = SmartIB32; | |
883 break; | |
884 } | |
885 } | |
886 else | |
887 ifbFunction = NULL; | |
888 } | |
889 | |
890 void VBA::updateFilter() | |
891 { | |
892 filterWidth = sizeX; | |
893 filterHeight = sizeY; | |
894 | |
895 if (systemColorDepth == 16 && (videoOption > VIDEO_1X && | |
896 videoOption != VIDEO_320x240)) | |
897 { | |
898 switch (filterType) | |
899 { | |
900 default: | |
901 case 0: | |
902 filterFunction = NULL; | |
903 break; | |
904 case 1: | |
905 filterFunction = ScanlinesTV; | |
906 break; | |
907 case 2: | |
908 filterFunction = _2xSaI; | |
909 break; | |
910 case 3: | |
911 filterFunction = Super2xSaI; | |
912 break; | |
913 case 4: | |
914 filterFunction = SuperEagle; | |
915 break; | |
916 case 5: | |
917 filterFunction = Pixelate2x16; | |
918 break; | |
919 case 6: | |
920 filterFunction = MotionBlur; | |
921 break; | |
922 case 7: | |
923 filterFunction = AdMame2x; | |
924 break; | |
925 case 8: | |
926 filterFunction = Simple2x16; | |
927 break; | |
928 case 9: | |
929 filterFunction = Bilinear; | |
930 break; | |
931 case 10: | |
932 filterFunction = BilinearPlus; | |
933 break; | |
934 case 11: | |
935 filterFunction = Scanlines; | |
936 break; | |
937 case 12: | |
938 filterFunction = hq2xS; | |
939 break; | |
940 case 13: | |
941 filterFunction = hq2x; | |
942 break; | |
943 case 14: | |
944 filterFunction = lq2x; | |
945 break; | |
946 case 15: | |
947 filterFunction = hq3xS; | |
948 break; | |
949 case 16: | |
950 filterFunction = hq3x; | |
951 break; | |
952 case 17: | |
953 filterFunction = Simple3x16; | |
954 break; | |
955 case 18: | |
956 filterFunction = Simple4x16; | |
957 break; | |
958 case 19: | |
959 filterFunction = Pixelate3x16; | |
960 break; | |
961 case 20: | |
962 filterFunction = Pixelate4x16; | |
963 break; | |
964 } | |
965 switch (filterType) | |
966 { | |
967 case 0: // normal -> 1x texture | |
968 rect.right = sizeX; | |
969 rect.bottom = sizeY; | |
970 break; | |
971 default: // other -> 2x texture | |
972 rect.right = sizeX * 2; | |
973 rect.bottom = sizeY * 2; | |
974 memset(delta, 255, sizeof(delta)); | |
975 break; | |
976 case 15: // hq3x -> 3x texture | |
977 case 16: | |
978 case 17: | |
979 case 19: | |
980 rect.right = sizeX * 3; | |
981 rect.bottom = sizeY * 3; | |
982 memset(delta, 255, sizeof(delta)); | |
983 break; | |
984 case 18: // Simple4x -> 4x texture | |
985 case 20: | |
986 rect.right = sizeX * 4; | |
987 rect.bottom = sizeY * 4; | |
988 memset(delta, 255, sizeof(delta)); | |
989 break; | |
990 } | |
991 } | |
992 else | |
993 { | |
994 if (systemColorDepth == 32 && videoOption > VIDEO_1X && | |
995 videoOption != VIDEO_320x240) | |
996 { | |
997 switch (filterType) | |
998 { | |
999 default: | |
1000 case 0: | |
1001 filterFunction = NULL; | |
1002 break; | |
1003 case 1: | |
1004 filterFunction = ScanlinesTV32; | |
1005 break; | |
1006 case 2: | |
1007 filterFunction = _2xSaI32; | |
1008 break; | |
1009 case 3: | |
1010 filterFunction = Super2xSaI32; | |
1011 break; | |
1012 case 4: | |
1013 filterFunction = SuperEagle32; | |
1014 break; | |
1015 case 5: | |
1016 filterFunction = Pixelate2x32; | |
1017 break; | |
1018 case 6: | |
1019 filterFunction = MotionBlur32; | |
1020 break; | |
1021 case 7: | |
1022 filterFunction = AdMame2x32; | |
1023 break; | |
1024 case 8: | |
1025 filterFunction = Simple2x32; | |
1026 break; | |
1027 case 9: | |
1028 filterFunction = Bilinear32; | |
1029 break; | |
1030 case 10: | |
1031 filterFunction = BilinearPlus32; | |
1032 break; | |
1033 case 11: | |
1034 filterFunction = Scanlines32; | |
1035 break; | |
1036 case 12: | |
1037 filterFunction = hq2xS32; | |
1038 break; | |
1039 case 13: | |
1040 filterFunction = hq2x32; | |
1041 break; | |
1042 case 14: | |
1043 filterFunction = lq2x32; | |
1044 break; | |
1045 case 15: | |
1046 filterFunction = hq3xS32; | |
1047 break; | |
1048 case 16: | |
1049 filterFunction = hq3x32; | |
1050 break; | |
1051 case 17: | |
1052 filterFunction = Simple3x32; | |
1053 break; | |
1054 case 18: | |
1055 filterFunction = Simple4x32; | |
1056 break; | |
1057 case 19: | |
1058 filterFunction = Pixelate3x32; | |
1059 break; | |
1060 case 20: | |
1061 filterFunction = Pixelate4x32; | |
1062 break; | |
1063 } | |
1064 switch (filterType) | |
1065 { | |
1066 case 0: // normal -> 1x texture | |
1067 rect.right = sizeX; | |
1068 rect.bottom = sizeY; | |
1069 break; | |
1070 default: // other -> 2x texture | |
1071 rect.right = sizeX * 2; | |
1072 rect.bottom = sizeY * 2; | |
1073 memset(delta, 255, sizeof(delta)); | |
1074 break; | |
1075 case 15: // hq3x -> 3x texture | |
1076 case 16: | |
1077 case 17: | |
1078 case 19: | |
1079 rect.right = sizeX * 3; | |
1080 rect.bottom = sizeY * 3; | |
1081 memset(delta, 255, sizeof(delta)); | |
1082 break; | |
1083 case 18: // Simple4x -> 4x texture | |
1084 case 20: | |
1085 rect.right = sizeX * 4; | |
1086 rect.bottom = sizeY * 4; | |
1087 memset(delta, 255, sizeof(delta)); | |
1088 break; | |
1089 } | |
1090 } | |
1091 else | |
1092 filterFunction = NULL; | |
1093 } | |
1094 | |
1095 if (display) | |
1096 display->changeRenderSize(rect.right, rect.bottom); | |
1097 } | |
1098 | |
1099 void VBA::recreateMenuBar() | |
1100 { | |
1101 m_menu.Detach(); | |
1102 m_menu.Attach(winResLoadMenu(MAKEINTRESOURCE(IDR_MENU))); | |
1103 | |
1104 if (m_pMainWnd && menuToggle) // assuming that whether the menu has been set is always kept tracked | |
1105 { | |
1106 m_pMainWnd->SetMenu(&m_menu); | |
1107 } | |
1108 | |
1109 if (menu != NULL) | |
1110 { | |
1111 DestroyMenu(menu); | |
1112 } | |
1113 | |
1114 menu = m_menu.GetSafeHmenu(); | |
1115 } | |
1116 | |
1117 void VBA::updateMenuBar() | |
1118 { | |
1119 if (flagHideMenu) | |
1120 return; | |
1121 | |
1122 recreateMenuBar(); | |
1123 | |
1124 if (popup != NULL) | |
1125 { | |
1126 // force popup recreation if language changed | |
1127 DestroyMenu(popup); | |
1128 popup = NULL; | |
1129 } | |
1130 } | |
1131 | |
1132 void VBA::saveRewindStateIfNecessary() | |
1133 { | |
1134 if (rewindSaveNeeded && rewindMemory && emulator.emuWriteMemState) | |
1135 { | |
1136 rewindCount++; | |
1137 if (rewindCount > rewindSlots) | |
1138 rewindCount = rewindSlots; | |
1139 assert(rewindPos >= 0 && rewindPos < rewindSlots); | |
1140 if (emulator.emuWriteMemState(&rewindMemory[rewindPos * REWIND_SIZE], REWIND_SIZE)) | |
1141 { | |
1142 rewindPos = ++rewindPos % rewindSlots; | |
1143 assert(rewindPos >= 0 && rewindPos < rewindSlots); | |
1144 if (rewindCount == rewindSlots) | |
1145 rewindTopPos = ++rewindTopPos % rewindSlots; | |
1146 } | |
1147 } | |
1148 | |
1149 // also update/cache some frame search stuff | |
1150 if (frameSearching) | |
1151 { | |
1152 extern SMovie Movie; | |
1153 int curFrame = (Movie.state == MOVIE_STATE_NONE) ? systemCounters.frameCount : Movie.currentFrame; | |
1154 int endFrame = theApp.frameSearchStart + theApp.frameSearchLength; | |
1155 frameSearchSkipping = (curFrame < endFrame); | |
1156 frameSearchFirstStep = false; | |
1157 | |
1158 if (curFrame == endFrame) | |
1159 { | |
1160 // cache intermediate state to speed up searching forward | |
1161 emulator.emuWriteMemState(&frameSearchMemory[REWIND_SIZE * 1], REWIND_SIZE); | |
1162 } | |
1163 | |
1164 if (curFrame == endFrame + 1) | |
1165 { | |
1166 emulator.emuWriteMemState(&frameSearchMemory[REWIND_SIZE * 2], REWIND_SIZE); | |
1167 frameSearchLoadValid = true; | |
1168 } | |
1169 } | |
1170 else | |
1171 { | |
1172 frameSearchFirstStep = false; | |
1173 | |
1174 assert(!frameSearchSkipping); | |
1175 // just in case | |
1176 frameSearchSkipping = false; | |
1177 } | |
1178 } | |
1179 | |
1180 BOOL VBA::OnIdle(LONG lCount) | |
1181 { | |
1182 if (emulating && debugger) | |
1183 { | |
1184 MSG msg; | |
1185 remoteStubMain(); | |
1186 if (debugger) | |
1187 return TRUE; // continue loop | |
1188 return !::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE); | |
1189 } | |
1190 else if (emulating && active && !paused) | |
1191 { | |
1192 /// for(int i = 0; i < 2; i++) | |
1193 { | |
1194 emulator.emuMain(emulator.emuCount); | |
1195 | |
1196 // save the state for rewinding, if necessary | |
1197 saveRewindStateIfNecessary(); | |
1198 | |
1199 rewindSaveNeeded = false; | |
1200 } | |
1201 | |
1202 if (mouseCounter) | |
1203 { | |
1204 if (--mouseCounter == 0) | |
1205 { | |
1206 SetCursor(NULL); | |
1207 } | |
1208 } | |
1209 return TRUE; | |
1210 } | |
1211 else if (emulating) // this fixes display if resetting while paused | |
1212 { | |
1213 // VBAUpdateButtonPressDisplay(); | |
1214 VBAUpdateFrameCountDisplay(); | |
1215 systemRefreshScreen(); | |
1216 } | |
1217 | |
1218 return FALSE; | |
1219 | |
1220 // return CWinApp::OnIdle(lCount); | |
1221 } | |
1222 | |
1223 void VBA::addRecentFile(const CString &file) | |
1224 { | |
1225 // Do not change recent list if frozen | |
1226 if (recentFreeze) | |
1227 return; | |
1228 int i = 0; | |
1229 for (i = 0; i < 10; ++i) | |
1230 { | |
1231 if (recentFiles[i].GetLength() == 0) | |
1232 break; | |
1233 | |
1234 if (recentFiles[i].Compare(file) == 0) | |
1235 { | |
1236 if (i == 0) | |
1237 return; | |
1238 CString p = recentFiles[i]; | |
1239 for (int j = i; j > 0; --j) | |
1240 { | |
1241 recentFiles[j] = recentFiles[j - 1]; | |
1242 } | |
1243 recentFiles[0] = p; | |
1244 return; | |
1245 } | |
1246 } | |
1247 int num = 0; | |
1248 for (i = 0; i < 10; ++i) | |
1249 { | |
1250 if (recentFiles[i].GetLength() != 0) | |
1251 ++num; | |
1252 } | |
1253 if (num == 10) | |
1254 { | |
1255 --num; | |
1256 } | |
1257 | |
1258 for (i = num; i >= 1; --i) | |
1259 { | |
1260 recentFiles[i] = recentFiles[i - 1]; | |
1261 } | |
1262 recentFiles[0] = file; | |
1263 } | |
1264 | |
1265 void VBA::updateFrameSkip() | |
1266 { | |
1267 switch (systemCartridgeType) | |
1268 { | |
1269 case 0: | |
1270 systemFrameSkip = frameSkip; | |
1271 break; | |
1272 case 1: | |
1273 systemFrameSkip = gbFrameSkip; | |
1274 break; | |
1275 } | |
1276 } | |
1277 | |
1278 void VBA::updateVideoSize(UINT id) | |
1279 { | |
1280 int value = 0; | |
1281 bool forceUpdate = false; | |
1282 | |
1283 switch (id) | |
1284 { | |
1285 case ID_OPTIONS_VIDEO_X1: | |
1286 value = VIDEO_1X; | |
1287 forceUpdate = true; | |
1288 break; | |
1289 case ID_OPTIONS_VIDEO_X2: | |
1290 value = VIDEO_2X; | |
1291 forceUpdate = true; | |
1292 break; | |
1293 case ID_OPTIONS_VIDEO_X3: | |
1294 value = VIDEO_3X; | |
1295 forceUpdate = true; | |
1296 break; | |
1297 case ID_OPTIONS_VIDEO_X4: | |
1298 value = VIDEO_4X; | |
1299 forceUpdate = true; | |
1300 break; | |
1301 case ID_OPTIONS_VIDEO_FULLSCREEN320X240: | |
1302 value = VIDEO_320x240; | |
1303 fsWidth = 320; | |
1304 fsHeight = 240; | |
1305 fsColorDepth = 16; | |
1306 break; | |
1307 case ID_OPTIONS_VIDEO_FULLSCREEN640X480: | |
1308 value = VIDEO_640x480; | |
1309 fsWidth = 640; | |
1310 fsHeight = 480; | |
1311 fsColorDepth = 16; | |
1312 break; | |
1313 case ID_OPTIONS_VIDEO_FULLSCREEN800X600: | |
1314 value = VIDEO_800x600; | |
1315 fsWidth = 800; | |
1316 fsHeight = 600; | |
1317 fsColorDepth = 16; | |
1318 break; | |
1319 case ID_OPTIONS_VIDEO_FULLSCREEN: | |
1320 value = VIDEO_OTHER; | |
1321 forceUpdate = true; | |
1322 break; | |
1323 } | |
1324 | |
1325 if (videoOption != value || forceUpdate) | |
1326 updateWindowSize(value); | |
1327 } | |
1328 | |
1329 void VBA::updateWindowSize(int value) | |
1330 { | |
1331 regSetDwordValue("video", value); | |
1332 | |
1333 if (value == VIDEO_OTHER) | |
1334 { | |
1335 regSetDwordValue("fsWidth", fsWidth); | |
1336 regSetDwordValue("fsHeight", fsHeight); | |
1337 regSetDwordValue("fsColorDepth", fsColorDepth); | |
1338 } | |
1339 | |
1340 if (display && | |
1341 (((value >= VIDEO_320x240 || videoOption >= VIDEO_320x240) && videoOption != value) || | |
1342 fsForceChange)) | |
1343 { | |
1344 fsForceChange = false; | |
1345 videoOption = value; | |
1346 initDisplay(); | |
1347 } | |
1348 | |
1349 videoOption = value; | |
1350 | |
1351 if (systemCartridgeType == 1) | |
1352 { | |
1353 if (gbBorderOn) | |
1354 { | |
1355 sizeX = 256; | |
1356 sizeY = 224; | |
1357 gbBorderLineSkip = 256; | |
1358 gbBorderColumnSkip = 48; | |
1359 gbBorderRowSkip = 40; | |
1360 } | |
1361 else | |
1362 { | |
1363 sizeX = 160; | |
1364 sizeY = 144; | |
1365 gbBorderLineSkip = 160; | |
1366 gbBorderColumnSkip = 0; | |
1367 gbBorderRowSkip = 0; | |
1368 } | |
1369 } | |
1370 else | |
1371 { | |
1372 sizeX = 240; | |
1373 sizeY = 160; | |
1374 } | |
1375 | |
1376 switch (videoOption) | |
1377 { | |
1378 case VIDEO_1X: | |
1379 surfaceSizeX = sizeX; | |
1380 surfaceSizeY = sizeY; | |
1381 break; | |
1382 case VIDEO_2X: | |
1383 surfaceSizeX = sizeX * 2; | |
1384 surfaceSizeY = sizeY * 2; | |
1385 break; | |
1386 case VIDEO_3X: | |
1387 surfaceSizeX = sizeX * 3; | |
1388 surfaceSizeY = sizeY * 3; | |
1389 break; | |
1390 case VIDEO_4X: | |
1391 surfaceSizeX = sizeX * 4; | |
1392 surfaceSizeY = sizeY * 4; | |
1393 break; | |
1394 case VIDEO_320x240: | |
1395 case VIDEO_640x480: | |
1396 case VIDEO_800x600: | |
1397 case VIDEO_OTHER: | |
1398 // Need to fix this code later. For now, Fullscreen takes the whole screen. | |
1399 if (fullScreenStretch) | |
1400 { | |
1401 surfaceSizeX = fsWidth; | |
1402 surfaceSizeY = fsHeight; | |
1403 } | |
1404 else | |
1405 { | |
1406 double scaleX = (double)fsWidth / (double)sizeX; | |
1407 double scaleY = (double)fsHeight / (double)sizeY; | |
1408 double scaleMin = scaleX < scaleY ? scaleX : scaleY; | |
1409 if (fsMaxScale) | |
1410 scaleMin = scaleMin > fsMaxScale ? fsMaxScale : scaleMin; | |
1411 surfaceSizeX = (int)(scaleMin * sizeX); | |
1412 surfaceSizeY = (int)(scaleMin * sizeY); | |
1413 } | |
1414 break; | |
1415 } | |
1416 | |
1417 rect.left = 0; | |
1418 rect.top = 0; | |
1419 rect.right = sizeX; | |
1420 rect.bottom = sizeY; | |
1421 | |
1422 int winSizeX = 0; | |
1423 int winSizeY = 0; | |
1424 int x = 0; | |
1425 int y = 0; | |
1426 | |
1427 DWORD style = WS_POPUP | WS_VISIBLE; | |
1428 DWORD styleEx = alwaysOnTop ? WS_EX_TOPMOST : 0; | |
1429 | |
1430 if (videoOption <= VIDEO_4X) | |
1431 { | |
1432 style |= WS_OVERLAPPEDWINDOW; | |
1433 | |
1434 dest.left = 0; | |
1435 dest.top = 0; | |
1436 dest.right = surfaceSizeX; | |
1437 dest.bottom = surfaceSizeY; | |
1438 | |
1439 x = windowPositionX; | |
1440 y = windowPositionY; | |
1441 } | |
1442 else | |
1443 { | |
1444 dest.left = 0; | |
1445 dest.top = 0; | |
1446 dest.right = fsWidth; | |
1447 dest.bottom = fsHeight; | |
1448 } | |
1449 | |
1450 AdjustWindowRectEx(&dest, style, flagHideMenu ? FALSE : TRUE, styleEx); | |
1451 winSizeX = dest.right - dest.left; | |
1452 winSizeY = dest.bottom - dest.top; | |
1453 | |
1454 if (m_pMainWnd == NULL) | |
1455 { | |
1456 // Create a new window | |
1457 m_pMainWnd = new MainWnd; | |
1458 m_pMainWnd->CreateEx(styleEx, | |
1459 theApp.wndClass, | |
1460 VBA_NAME_AND_VERSION, | |
1461 style, | |
1462 x, y, winSizeX, winSizeY, | |
1463 NULL, | |
1464 0); | |
1465 | |
1466 if (!(HWND)*m_pMainWnd) | |
1467 { | |
1468 winlog("Error creating Window %08x\n", GetLastError()); | |
1469 AfxPostQuitMessage(0); | |
1470 return; | |
1471 } | |
1472 } | |
1473 else | |
1474 { | |
1475 m_pMainWnd->SetWindowPos(0, //HWND_TOPMOST, | |
1476 x, | |
1477 y, | |
1478 winSizeX, | |
1479 winSizeY, | |
1480 SWP_NOMOVE | SWP_SHOWWINDOW); | |
1481 } | |
1482 | |
1483 updateMenuBar(); // add menubar first of all, or winGetMenuBarHeight() will get random height. | |
1484 winAccelMgr.UpdateMenu(menu); | |
1485 adjustDestRect(); | |
1486 | |
1487 updateIFB(); | |
1488 updateFilter(); | |
1489 | |
1490 m_pMainWnd->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN); | |
1491 } | |
1492 | |
1493 bool VBA::initDisplay() | |
1494 { | |
1495 if (display) | |
1496 { | |
1497 changingVideoSize = true; | |
1498 shutdownDisplay(); | |
1499 if (input) | |
1500 { | |
1501 delete input; | |
1502 input = NULL; | |
1503 } | |
1504 CWnd *pWnd = m_pMainWnd; | |
1505 | |
1506 m_pMainWnd = NULL; | |
1507 pWnd->DragAcceptFiles(FALSE); | |
1508 pWnd->DestroyWindow(); | |
1509 delete pWnd; | |
1510 | |
1511 display = NULL; | |
1512 } | |
1513 | |
1514 if (display == NULL) | |
1515 { | |
1516 updateWindowSize(videoOption); | |
1517 | |
1518 switch (renderMethod) | |
1519 { | |
1520 case GDI: | |
1521 display = newGDIDisplay(); | |
1522 break; | |
1523 case DIRECT_DRAW: | |
1524 display = newDirectDrawDisplay(); | |
1525 break; | |
1526 case DIRECT_3D: | |
1527 display = newDirect3DDisplay(); | |
1528 break; | |
1529 case OPENGL: | |
1530 display = newOpenGLDisplay(); | |
1531 break; | |
1532 } | |
1533 | |
1534 if (display->initialize()) | |
1535 { | |
1536 if (input == NULL) | |
1537 { | |
1538 if (!initInput()) | |
1539 { | |
1540 changingVideoSize = false; | |
1541 AfxPostQuitMessage(0); | |
1542 return false; | |
1543 } | |
1544 } | |
1545 | |
1546 input->checkKeys(); | |
1547 | |
1548 changingVideoSize = false; | |
1549 } | |
1550 else | |
1551 { | |
1552 if (videoOption == VIDEO_320x240 || | |
1553 videoOption == VIDEO_640x480 || | |
1554 videoOption == VIDEO_800x600 || | |
1555 videoOption == VIDEO_OTHER) | |
1556 { | |
1557 regSetDwordValue("video", VIDEO_1X); | |
1558 if (pVideoDriverGUID) | |
1559 regSetDwordValue("defaultVideoDriver", TRUE); | |
1560 } | |
1561 changingVideoSize = false; | |
1562 return false; | |
1563 } | |
1564 } | |
1565 changingVideoSize = false; | |
1566 return true; | |
1567 } | |
1568 | |
1569 bool VBA::updateRenderMethod(bool force) | |
1570 { | |
1571 bool res = true; | |
1572 if (force || (display && display->getType() != renderMethod)) | |
1573 { | |
1574 res = initDisplay(); | |
1575 | |
1576 while (!res && renderMethod > 0) | |
1577 { | |
1578 if (renderMethod == OPENGL) | |
1579 renderMethod = DIRECT_3D; | |
1580 else if (renderMethod == DIRECT_3D) | |
1581 renderMethod = DIRECT_DRAW; | |
1582 else if (renderMethod == DIRECT_DRAW) | |
1583 renderMethod = GDI; | |
1584 | |
1585 res = initDisplay(); | |
1586 } | |
1587 } | |
1588 | |
1589 updateIFB(); | |
1590 updateFilter(); | |
1591 | |
1592 m_pMainWnd->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN); | |
1593 | |
1594 regSetDwordValue("renderMethod", renderMethod); | |
1595 | |
1596 return res; | |
1597 } | |
1598 | |
1599 void VBA::winCheckFullscreen() | |
1600 { | |
1601 if (videoOption > VIDEO_4X && tripleBuffering) | |
1602 { | |
1603 if (display) | |
1604 display->checkFullScreen(); | |
1605 } | |
1606 } | |
1607 | |
1608 void VBA::shutdownDisplay() | |
1609 { | |
1610 if (display != NULL) | |
1611 { | |
1612 display->cleanup(); | |
1613 delete display; | |
1614 display = NULL; | |
1615 } | |
1616 } | |
1617 | |
1618 void VBA::updatePriority() | |
1619 { | |
1620 switch (threadPriority) | |
1621 { | |
1622 case 0: | |
1623 SetThreadPriority(THREAD_PRIORITY_HIGHEST); | |
1624 break; | |
1625 case 1: | |
1626 SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL); | |
1627 break; | |
1628 case 3: | |
1629 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); | |
1630 break; | |
1631 default: | |
1632 SetThreadPriority(THREAD_PRIORITY_NORMAL); | |
1633 } | |
1634 } | |
1635 | |
1636 #ifdef MMX | |
1637 bool VBA::detectMMX() | |
1638 { | |
1639 bool support = false; | |
1640 char brand[13]; | |
1641 | |
1642 // check for Intel chip | |
1643 __try { | |
1644 __asm { | |
1645 mov eax, 0; | |
1646 cpuid; | |
1647 mov [dword ptr brand + 0], ebx; | |
1648 mov [dword ptr brand + 4], edx; | |
1649 mov [dword ptr brand + 8], ecx; | |
1650 } | |
1651 } | |
1652 __except(EXCEPTION_EXECUTE_HANDLER) { | |
1653 if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION) | |
1654 { | |
1655 return false; | |
1656 } | |
1657 return false; | |
1658 } | |
1659 // Check for Intel or AMD CPUs | |
1660 if (strncmp(brand, "GenuineIntel", 12)) | |
1661 { | |
1662 if (strncmp(brand, "AuthenticAMD", 12)) | |
1663 { | |
1664 return false; | |
1665 } | |
1666 } | |
1667 | |
1668 __asm { | |
1669 mov eax, 1; | |
1670 cpuid; | |
1671 test edx, 00800000h; | |
1672 jz NotFound; | |
1673 mov [support], 1; | |
1674 NotFound: | |
1675 } | |
1676 return support; | |
1677 } | |
1678 | |
1679 #endif | |
1680 | |
1681 void VBA::winSetLanguageOption(int option, bool force) | |
1682 { | |
1683 if (((option == languageOption) && option != 2) && !force) | |
1684 return; | |
1685 switch (option) | |
1686 { | |
1687 case 0: | |
1688 { | |
1689 char lbuffer[10]; | |
1690 | |
1691 if (GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SABBREVLANGNAME, | |
1692 lbuffer, 10)) | |
1693 { | |
1694 HINSTANCE l = winLoadLanguage(lbuffer); | |
1695 if (l == NULL) | |
1696 { | |
1697 LCID locIdBase = MAKELCID(MAKELANGID(PRIMARYLANGID(GetSystemDefaultLangID()), SUBLANG_NEUTRAL), SORT_DEFAULT); | |
1698 if (GetLocaleInfo(locIdBase, LOCALE_SABBREVLANGNAME, | |
1699 lbuffer, 10)) | |
1700 { | |
1701 l = winLoadLanguage(lbuffer); | |
1702 if (l == NULL) | |
1703 { | |
1704 systemMessage(IDS_FAILED_TO_LOAD_LIBRARY, | |
1705 "Failed to load library %s", | |
1706 lbuffer); | |
1707 return; | |
1708 } | |
1709 } | |
1710 } | |
1711 AfxSetResourceHandle(l); | |
1712 if (languageModule != NULL) | |
1713 /**/ ::FreeLibrary(languageModule); | |
1714 languageModule = l; | |
1715 } | |
1716 else | |
1717 { | |
1718 systemMessage(IDS_FAILED_TO_GET_LOCINFO, | |
1719 "Failed to get locale information"); | |
1720 return; | |
1721 } | |
1722 break; | |
1723 } | |
1724 case 1: | |
1725 if (languageModule != NULL) | |
1726 /**/ ::FreeLibrary(languageModule); | |
1727 languageModule = NULL; | |
1728 AfxSetResourceHandle(AfxGetInstanceHandle()); | |
1729 break; | |
1730 case 2: | |
1731 { | |
1732 if (!force) | |
1733 { | |
1734 LangSelect dlg; | |
1735 if (dlg.DoModal()) | |
1736 { | |
1737 HINSTANCE l = winLoadLanguage(languageName); | |
1738 if (l == NULL) | |
1739 { | |
1740 systemMessage(IDS_FAILED_TO_LOAD_LIBRARY, | |
1741 "Failed to load library %s", | |
1742 languageName); | |
1743 return; | |
1744 } | |
1745 AfxSetResourceHandle(l); | |
1746 if (languageModule != NULL) | |
1747 /**/ ::FreeLibrary(languageModule); | |
1748 languageModule = l; | |
1749 } | |
1750 } | |
1751 else | |
1752 { | |
1753 if (languageName.IsEmpty()) | |
1754 return; | |
1755 HINSTANCE l = winLoadLanguage(languageName); | |
1756 if (l == NULL) | |
1757 { | |
1758 systemMessage(IDS_FAILED_TO_LOAD_LIBRARY, | |
1759 "Failed to load library %s", | |
1760 languageName); | |
1761 return; | |
1762 } | |
1763 AfxSetResourceHandle(l); | |
1764 if (languageModule != NULL) | |
1765 FreeLibrary(languageModule); | |
1766 languageModule = l; | |
1767 } | |
1768 break; | |
1769 } | |
1770 } | |
1771 languageOption = option; | |
1772 updateMenuBar(); | |
1773 theApp.winAccelMgr.UpdateMenu(theApp.menu); | |
1774 } | |
1775 | |
1776 HINSTANCE VBA::winLoadLanguage(const char *name) | |
1777 { | |
1778 CString buffer; | |
1779 | |
1780 buffer.Format("vba_%s.dll", name); | |
1781 | |
1782 HINSTANCE l = /**/ ::LoadLibrary(buffer); | |
1783 | |
1784 if (l == NULL) | |
1785 { | |
1786 if (strlen(name) == 3) | |
1787 { | |
1788 char buffer2[3]; | |
1789 buffer2[0] = name[0]; | |
1790 buffer2[1] = name[1]; | |
1791 buffer2[2] = 0; | |
1792 buffer.Format("vba_%s.dll", buffer2); | |
1793 | |
1794 return /**/ ::LoadLibrary(buffer); | |
1795 } | |
1796 } | |
1797 return l; | |
1798 } | |
1799 | |
1800 bool VBA::initInput() | |
1801 { | |
1802 if (input) | |
1803 delete input; | |
1804 input = newDirectInput(); | |
1805 if (input->initialize()) | |
1806 { | |
1807 input->loadSettings(); | |
1808 input->checkKeys(); | |
1809 return true; | |
1810 } | |
1811 delete input; | |
1812 return false; | |
1813 } | |
1814 | |
1815 void VBA::winAddUpdateListener(IUpdateListener *l) | |
1816 { | |
1817 updateList.AddTail(l); | |
1818 updateCount++; | |
1819 } | |
1820 | |
1821 void VBA::winRemoveUpdateListener(IUpdateListener *l) | |
1822 { | |
1823 POSITION pos = updateList.Find(l); | |
1824 if (pos) | |
1825 { | |
1826 updateList.RemoveAt(pos); | |
1827 updateCount--; | |
1828 if (updateCount < 0) | |
1829 updateCount = 0; | |
1830 } | |
1831 } | |
1832 | |
1833 void VBA::loadSettings() | |
1834 { | |
1835 CString buffer; | |
1836 // video | |
1837 bool defaultVideoDriver = regQueryDwordValue("defaultVideoDriver", true) ? true : false; | |
1838 if (!regQueryBinaryValue("videoDriverGUID", (char *)&videoDriverGUID, sizeof(GUID))) | |
1839 { | |
1840 defaultVideoDriver = TRUE; | |
1841 } | |
1842 if (defaultVideoDriver) | |
1843 pVideoDriverGUID = NULL; | |
1844 else | |
1845 pVideoDriverGUID = &videoDriverGUID; | |
1846 | |
1847 videoOption = regQueryDwordValue("video", 0); | |
1848 if (videoOption < 0 || videoOption > VIDEO_OTHER) | |
1849 videoOption = 0; | |
1850 switch (videoOption) | |
1851 { | |
1852 case VIDEO_320x240: | |
1853 fsWidth = 320; | |
1854 fsHeight = 240; | |
1855 fsColorDepth = 16; | |
1856 break; | |
1857 case VIDEO_640x480: | |
1858 fsWidth = 640; | |
1859 fsHeight = 480; | |
1860 fsColorDepth = 16; | |
1861 break; | |
1862 case VIDEO_800x600: | |
1863 fsWidth = 800; | |
1864 fsHeight = 600; | |
1865 fsColorDepth = 16; | |
1866 break; | |
1867 } | |
1868 if (videoOption == VIDEO_OTHER) | |
1869 { | |
1870 if (fsWidth < 0 || fsWidth > 4095 || fsHeight < 0 || fsHeight > 4095) | |
1871 videoOption = 0; | |
1872 if (fsColorDepth != 16 && fsColorDepth != 24 && fsColorDepth != 32) | |
1873 videoOption = 0; | |
1874 } | |
1875 | |
1876 fsWidth = regQueryDwordValue("fsWidth", 0); | |
1877 fsHeight = regQueryDwordValue("fsHeight", 0); | |
1878 fsColorDepth = regQueryDwordValue("fsColorDepth", 0); | |
1879 fsMaxScale = regQueryDwordValue("fsMaxScale", 0); | |
1880 fullScreenStretch = regQueryDwordValue("stretch", 0) ? true : false; | |
1881 | |
1882 renderMethod = (DISPLAY_TYPE)regQueryDwordValue("renderMethod", DIRECT_DRAW); | |
1883 if (renderMethod < GDI || renderMethod > OPENGL) | |
1884 renderMethod = DIRECT_DRAW; | |
1885 | |
1886 ddrawEmulationOnly = regQueryDwordValue("ddrawEmulationOnly", false) ? true : false; | |
1887 ddrawUseVideoMemory = regQueryDwordValue("ddrawUseVideoMemory", false) ? true : false; | |
1888 tripleBuffering = regQueryDwordValue("tripleBuffering", true) ? true : false; | |
1889 vsync = regQueryDwordValue("vsync", false) ? true : false; | |
1890 | |
1891 d3dFilter = regQueryDwordValue("d3dFilter", 0); | |
1892 if (d3dFilter < 0 || d3dFilter > 1) | |
1893 d3dFilter = 0; | |
1894 glFilter = regQueryDwordValue("glFilter", 0); | |
1895 if (glFilter < 0 || glFilter > 1) | |
1896 glFilter = 0; | |
1897 glType = regQueryDwordValue("glType", 0); | |
1898 if (glType < 0 || glType > 1) | |
1899 glType = 0; | |
1900 | |
1901 // pixel filter & ifb | |
1902 filterType = regQueryDwordValue("filter", 0); | |
1903 if (filterType < 0 || filterType > 20) | |
1904 filterType = 0; | |
1905 disableMMX = regQueryDwordValue("disableMMX", 0) ? true : false; | |
1906 ifbType = regQueryDwordValue("ifbType", 0); | |
1907 if (ifbType < 0 || ifbType > 2) | |
1908 ifbType = 0; | |
1909 | |
1910 // frame skipping | |
1911 frameSkip = regQueryDwordValue("frameSkip", /*2*/ 0); | |
1912 if (frameSkip < 0 || frameSkip > 9) | |
1913 frameSkip = 1; | |
1914 gbFrameSkip = regQueryDwordValue("gbFrameSkip", 0); | |
1915 if (gbFrameSkip < 0 || gbFrameSkip > 9) | |
1916 gbFrameSkip = 0; | |
1917 /// autoFrameSkip = regQueryDwordValue("autoFrameSkip", FALSE) ? TRUE : FALSE; | |
1918 | |
1919 // input | |
1920 joypadDefault = regQueryDwordValue("joypadDefault", 0); | |
1921 if (joypadDefault < 0 || joypadDefault > 3) | |
1922 joypadDefault = 0; | |
1923 allowLeftRight = regQueryDwordValue("allowLeftRight", false) ? true : false; | |
1924 autofireAccountForLag = regQueryDwordValue("autofireAccountForLag", false) ? true : false; | |
1925 nextframeAccountForLag = regQueryDwordValue("nextframeAccountForLag", false) ? true : false; | |
1926 theApp.AsscWithSaveState = regQueryDwordValue("AsscWithSaveState", false) ? true : false; | |
1927 | |
1928 // speed | |
1929 throttle = regQueryDwordValue("throttle", 0); | |
1930 if (throttle < 5 || throttle > 1000) | |
1931 throttle = 100; | |
1932 | |
1933 synchronize = regQueryDwordValue("synchronize", 1) ? true : false; | |
1934 accuratePitchThrottle = regQueryDwordValue("accuratePitchThrottle", FALSE) ? TRUE : FALSE; | |
1935 | |
1936 // sound | |
1937 int resChannels = regQueryDwordValue("soundEnable", 0x30f); | |
1938 soundEnableChannels(resChannels); | |
1939 soundDisableChannels(~resChannels); | |
1940 soundOffFlag = (regQueryDwordValue("soundOff", 0)) ? true : false; | |
1941 soundQuality = regQueryDwordValue("soundQuality", 2); | |
1942 soundEcho = regQueryDwordValue("soundEcho", 0) ? true : false; | |
1943 soundLowPass = regQueryDwordValue("soundLowPass", 0) ? true : false; | |
1944 soundReverse = regQueryDwordValue("soundReverse", 0) ? true : false; | |
1945 soundVolume = regQueryDwordValue("soundVolume", 0); | |
1946 if (soundVolume < 0 || soundVolume > 5) | |
1947 soundVolume = 0; | |
1948 muteFrameAdvance = regQueryDwordValue("muteFrameAdvance", 0) ? TRUE : FALSE; | |
1949 muteWhenInactive = regQueryDwordValue("muteWhenInactive", 0) ? TRUE : FALSE; | |
1950 | |
1951 // emulation | |
1952 memLagEnabled = regQueryDwordValue("memLagEnabled", false) ? true : false; | |
1953 memLagTempEnabled = memLagEnabled; | |
1954 gbNullInputHackEnabled = regQueryDwordValue("gbNullInputHackEnabled", false) ? true : false; | |
1955 gbNullInputHackTempEnabled = gbNullInputHackEnabled; | |
1956 useOldSync = regQueryDwordValue("useOldSync", 0) ? TRUE : FALSE; | |
1957 useOldFrameTiming = regQueryDwordValue("useOldGBTiming", false) ? true : false; | |
1958 | |
1959 useBiosFile = regQueryDwordValue("useBios", 0) ? true : false; | |
1960 skipBiosFile = regQueryDwordValue("skipBios", 0) ? true : false; | |
1961 buffer = regQueryStringValue("biosFile", ""); | |
1962 if (!buffer.IsEmpty()) | |
1963 { | |
1964 biosFileName = buffer; | |
1965 } | |
1966 // removeIntros = regQueryDwordValue("removeIntros", false) ? true : false; | |
1967 | |
1968 autoIPS = regQueryDwordValue("autoIPS", true) ? true : false; | |
1969 | |
1970 agbPrintEnable(regQueryDwordValue("agbPrint", 0) ? true : false); | |
1971 winRtcEnable = regQueryDwordValue("rtcEnabled", 0) ? true : false; | |
1972 rtcEnable(winRtcEnable); | |
1973 | |
1974 winSaveType = regQueryDwordValue("saveType", 0); | |
1975 if (winSaveType < 0 || winSaveType > 5) | |
1976 winSaveType = 0; | |
1977 cpuEnhancedDetection = regQueryDwordValue("enhancedDetection", 1) ? true : false; | |
1978 winFlashSize = regQueryDwordValue("flashSize", 0x10000); | |
1979 if (winFlashSize != 0x10000 && winFlashSize != 0x20000) | |
1980 winFlashSize = 0x10000; | |
1981 | |
1982 cpuDisableSfx = regQueryDwordValue("disableSfx", 0) ? true : false; | |
1983 | |
1984 // GBx | |
1985 winGbPrinterEnabled = regQueryDwordValue("gbPrinter", false) ? true : false; | |
1986 if (winGbPrinterEnabled) | |
1987 gbSerialFunction = gbPrinterSend; | |
1988 else | |
1989 gbSerialFunction = NULL; | |
1990 gbEmulatorType = regQueryDwordValue("emulatorType", 0); | |
1991 if (gbEmulatorType < 0 || gbEmulatorType > 5) | |
1992 gbEmulatorType = 1; | |
1993 winGbBorderOn = regQueryDwordValue("borderOn", 0); | |
1994 gbBorderAutomatic = regQueryDwordValue("borderAutomatic", 0); | |
1995 | |
1996 gbColorOption = regQueryDwordValue("colorOption", 0); | |
1997 gbPaletteOption = regQueryDwordValue("gbPaletteOption", 0); | |
1998 if (gbPaletteOption < 0) | |
1999 gbPaletteOption = 0; | |
2000 if (gbPaletteOption > 2) | |
2001 gbPaletteOption = 2; | |
2002 regQueryBinaryValue("gbPalette", (char *)systemGbPalette, 24 * sizeof(u16)); | |
2003 | |
2004 // head-up display | |
2005 showSpeed = regQueryDwordValue("showSpeed", 1); | |
2006 if (showSpeed < 0 || showSpeed > 2) | |
2007 showSpeed = 1; | |
2008 showSpeedTransparent = regQueryDwordValue("showSpeedTransparent", TRUE) ? TRUE : FALSE; | |
2009 outlinedText = regQueryDwordValue("outlinedText", TRUE) != 0; | |
2010 transparentText = regQueryDwordValue("transparentText", FALSE) != 0; | |
2011 textColor = regQueryDwordValue("textColor", 0); | |
2012 textMethod = regQueryDwordValue("textMethod", 1); | |
2013 frameCounter = regQueryDwordValue("frameCounter", false) ? true : false; | |
2014 lagCounter = regQueryDwordValue("lagCounter", false) ? true : false; | |
2015 extraCounter = regQueryDwordValue("extraCounter", false) ? true : false; | |
2016 inputDisplay = regQueryDwordValue("inputDisplay", false) ? true : false; | |
2017 disableStatusMessage = regQueryDwordValue("disableStatus", 0) ? true : false; | |
2018 | |
2019 // UI | |
2020 windowPositionX = regQueryDwordValue("windowX", 0); | |
2021 if (windowPositionX < 0) | |
2022 windowPositionX = 0; | |
2023 windowPositionY = regQueryDwordValue("windowY", 0); | |
2024 if (windowPositionY < 0) | |
2025 windowPositionY = 0; | |
2026 | |
2027 autoHideMenu = regQueryDwordValue("autoHideMenu", 0) ? true : false; | |
2028 | |
2029 languageOption = regQueryDwordValue("language", 1); | |
2030 if (languageOption < 0 || languageOption > 2) | |
2031 languageOption = 1; | |
2032 buffer = regQueryStringValue("languageName", ""); | |
2033 if (!buffer.IsEmpty()) | |
2034 { | |
2035 languageName = buffer.Left(3); | |
2036 } | |
2037 else | |
2038 languageName = ""; | |
2039 winSetLanguageOption(languageOption, true); | |
2040 | |
2041 // preferences | |
2042 alwaysOnTop = regQueryDwordValue("alwaysOnTop", false) ? true : false; | |
2043 pauseWhenInactive = regQueryDwordValue("pauseWhenInactive", 1) ? true : false; | |
2044 enableBackgroundInput = regQueryDwordValue("enableBackgroundInput", 0) ? true : false; | |
2045 threadPriority = regQueryDwordValue("priority", 2); | |
2046 if (threadPriority < 0 || threadPriority > 3) | |
2047 threadPriority = 2; | |
2048 updatePriority(); | |
2049 | |
2050 filenamePreference = regQueryDwordValue("filenamePreference", 0); | |
2051 altAviRecordMethod = regQueryDwordValue("altAviRecordMethod", false) ? true : false; | |
2052 captureFormat = regQueryDwordValue("captureFormat", 0); | |
2053 | |
2054 rewindTimer = regQueryDwordValue("rewindTimer", 0); | |
2055 rewindSlots = regQueryDwordValue("rewindSlots", 64); | |
2056 if (rewindTimer < 0 || rewindTimer > 600) | |
2057 rewindTimer = 0; | |
2058 if (rewindSlots <= 0) | |
2059 rewindTimer = rewindSlots = 0; | |
2060 if (rewindSlots > MAX_REWIND_SLOTS) | |
2061 rewindSlots = MAX_REWIND_SLOTS; | |
2062 if (rewindTimer != 0) | |
2063 { | |
2064 if (rewindMemory == NULL) | |
2065 rewindMemory = (char *)malloc(rewindSlots * REWIND_SIZE); | |
2066 } | |
2067 | |
2068 if (frameSearchMemory == NULL) | |
2069 frameSearchMemory = (char *)malloc(3 * REWIND_SIZE); | |
2070 | |
2071 recentFreeze = regQueryDwordValue("recentFreeze", false) ? true : false; | |
2072 for (int i = 0, j = 0; i < 10; ++i) | |
2073 { | |
2074 buffer.Format("recent%d", i); | |
2075 const char *s = regQueryStringValue(buffer, NULL); | |
2076 if (s == NULL) | |
2077 continue; | |
2078 recentFiles[j] = s; | |
2079 ++j; | |
2080 } | |
2081 | |
2082 autoLoadMostRecent = regQueryDwordValue("autoLoadMostRecent", false) ? true : false; | |
2083 loadMakesRecent = regQueryDwordValue("loadMakesRecent", false) ? true : false; | |
2084 loadMakesCurrent = regQueryDwordValue("loadMakesCurrent", false) ? true : false; | |
2085 saveMakesCurrent = regQueryDwordValue("saveMakesCurrent", false) ? true : false; | |
2086 currentSlot = regQueryDwordValue("currentSlot", 0); | |
2087 showSlotTime = regQueryDwordValue("showSlotTime", 0) ? true : false; | |
2088 | |
2089 cheatsEnabled = regQueryDwordValue("cheatsEnabled", true) ? true : false; | |
2090 autoSaveLoadCheatList = regQueryDwordValue("autoSaveCheatList", 0) ? true : false; | |
2091 pauseDuringCheatSearch = regQueryDwordValue("pauseDuringCheatSearch2", 0) ? true : false; | |
2092 | |
2093 movieOnEndBehavior = regQueryDwordValue("movieOnEndBehavior", 0); | |
2094 movieOnEndPause = regQueryDwordValue("movieOnEndPause", 0) ? true : false; | |
2095 | |
2096 extern bool autoConvertMovieWhenPlaying; // from movie.cpp | |
2097 autoConvertMovieWhenPlaying = regQueryDwordValue("autoConvertMovieWhenPlaying", 0) ? true : false; | |
2098 | |
2099 // RamWatch Settings | |
2100 AutoRWLoad = regQueryDwordValue(AUTORWLOAD, false); | |
2101 RWSaveWindowPos = regQueryDwordValue(RWSAVEPOS, false); | |
2102 ramw_x = regQueryDwordValue(RAMWX, 0); | |
2103 ramw_y = regQueryDwordValue(RAMWY, 0); | |
2104 | |
2105 // this is FILO | |
2106 for (int i = MAX_RECENT_WATCHES; i > 0; --i) | |
2107 { | |
2108 buffer.Format("recentWatch%d", i); | |
2109 const char *s = regQueryStringValue(buffer, NULL); | |
2110 if (s == NULL) | |
2111 continue; | |
2112 RWAddRecentFile(s); | |
2113 } | |
2114 } | |
2115 | |
2116 void VBA::saveSettings() | |
2117 { | |
2118 regSetDwordValue("defaultVideoDriver", pVideoDriverGUID == NULL); | |
2119 if (pVideoDriverGUID) | |
2120 { | |
2121 regSetBinaryValue("videoDriverGUID", (char *)&videoDriverGUID, | |
2122 sizeof(GUID)); | |
2123 } | |
2124 regSetDwordValue("video", videoOption); | |
2125 | |
2126 regSetDwordValue("fsWidth", fsWidth); | |
2127 regSetDwordValue("fsHeight", fsHeight); | |
2128 regSetDwordValue("fsColorDepth", fsColorDepth); | |
2129 regSetDwordValue("fsMaxScale", fsMaxScale); | |
2130 | |
2131 regSetDwordValue("stretch", fullScreenStretch); | |
2132 | |
2133 regSetDwordValue("renderMethod", renderMethod); | |
2134 | |
2135 regSetDwordValue("ddrawEmulationOnly", ddrawEmulationOnly); | |
2136 regSetDwordValue("ddrawUseVideoMemory", ddrawUseVideoMemory); | |
2137 regSetDwordValue("tripleBuffering", tripleBuffering); | |
2138 regSetDwordValue("vsync", vsync); | |
2139 | |
2140 regSetDwordValue("d3dFilter", d3dFilter); | |
2141 regSetDwordValue("glFilter", glFilter); | |
2142 regSetDwordValue("glType", glType); | |
2143 | |
2144 // pixel filter & ifb | |
2145 regSetDwordValue("filter", filterType); | |
2146 regSetDwordValue("ifbType", ifbType); | |
2147 regSetDwordValue("disableMMX", disableMMX); | |
2148 | |
2149 // frame skipping | |
2150 regSetDwordValue("frameSkip", frameSkip); | |
2151 regSetDwordValue("gbFrameSkip", gbFrameSkip); | |
2152 /// regSetDwordValue("autoFrameSkip", autoFrameSkip); | |
2153 | |
2154 // input | |
2155 regSetDwordValue("joypadDefault", joypadDefault); | |
2156 regSetDwordValue("allowLeftRight", allowLeftRight); | |
2157 regSetDwordValue("autofireAccountforLag", autofireAccountForLag); | |
2158 regSetDwordValue("nextframeAccountforLag", nextframeAccountForLag); | |
2159 regSetDwordValue("AsscWithSaveState", theApp.AsscWithSaveState); | |
2160 | |
2161 | |
2162 // speed | |
2163 regSetDwordValue("throttle", throttle); | |
2164 regSetDwordValue("synchronize", synchronize); | |
2165 regSetDwordValue("accuratePitchThrottle", accuratePitchThrottle); | |
2166 | |
2167 // sound | |
2168 regSetDwordValue("soundEnable", soundGetEnabledChannels() & 0x030f); | |
2169 regSetDwordValue("soundOff", soundOffFlag); | |
2170 regSetDwordValue("soundQuality", soundQuality); | |
2171 regSetDwordValue("soundEcho", soundEcho); | |
2172 regSetDwordValue("soundLowPass", soundLowPass); | |
2173 regSetDwordValue("soundReverse", soundReverse); | |
2174 regSetDwordValue("soundVolume", soundVolume); | |
2175 regSetDwordValue("muteFrameAdvance", muteFrameAdvance); | |
2176 regSetDwordValue("muteWhenInactive", muteWhenInactive); | |
2177 | |
2178 // emulation | |
2179 regSetDwordValue("useBios", useBiosFile); | |
2180 regSetDwordValue("skipBios", skipBiosFile); | |
2181 if (!biosFileName.IsEmpty()) | |
2182 regSetStringValue("biosFile", biosFileName); | |
2183 // regSetDwordValue("removeIntros", removeIntros); | |
2184 | |
2185 regSetDwordValue("autoIPS", autoIPS); | |
2186 | |
2187 regSetDwordValue("memLagEnabled", memLagEnabled); | |
2188 regSetDwordValue("gbNullInputHackEnabled", gbNullInputHackEnabled); | |
2189 regSetDwordValue("useOldGBTiming", useOldFrameTiming); | |
2190 regSetDwordValue("useOldSync", useOldSync); | |
2191 | |
2192 regSetDwordValue("agbPrint", agbPrintIsEnabled()); | |
2193 regSetDwordValue("rtcEnabled", winRtcEnable); | |
2194 | |
2195 regSetDwordValue("saveType", winSaveType); | |
2196 regSetDwordValue("enhancedDetection", cpuEnhancedDetection); | |
2197 regSetDwordValue("flashSize", winFlashSize); | |
2198 | |
2199 regSetDwordValue("disableSfx", cpuDisableSfx); | |
2200 | |
2201 // GBx | |
2202 regSetDwordValue("emulatorType", gbEmulatorType); | |
2203 regSetDwordValue("gbPrinter", winGbPrinterEnabled); | |
2204 regSetDwordValue("borderOn", winGbBorderOn); | |
2205 regSetDwordValue("borderAutomatic", gbBorderAutomatic); | |
2206 | |
2207 regSetDwordValue("colorOption", gbColorOption); | |
2208 regSetDwordValue("gbPaletteOption", gbPaletteOption); | |
2209 regSetBinaryValue("gbPalette", (char *)systemGbPalette, 24 * sizeof(u16)); | |
2210 | |
2211 // head-up display | |
2212 regSetDwordValue("showSpeed", showSpeed); | |
2213 regSetDwordValue("showSpeedTransparent", showSpeedTransparent); | |
2214 | |
2215 regSetDwordValue("outlinedText", outlinedText); | |
2216 regSetDwordValue("transparentText", transparentText); | |
2217 regSetDwordValue("textColor", textColor); | |
2218 regSetDwordValue("textMethod", textMethod); | |
2219 regSetDwordValue("frameCounter", frameCounter); | |
2220 regSetDwordValue("lagCounter", lagCounter); | |
2221 regSetDwordValue("extraCounter", extraCounter); | |
2222 regSetDwordValue("inputDisplay", inputDisplay); | |
2223 regSetDwordValue("disableStatus", disableStatusMessage); | |
2224 | |
2225 // UI | |
2226 regSetDwordValue("windowX", windowPositionX); | |
2227 regSetDwordValue("windowY", windowPositionY); | |
2228 | |
2229 regSetDwordValue("autoHideMenu", autoHideMenu); | |
2230 | |
2231 regSetDwordValue("language", languageOption); | |
2232 regSetStringValue("languageName", languageName); | |
2233 | |
2234 // preferences | |
2235 regSetDwordValue("alwaysOnTop", alwaysOnTop); | |
2236 regSetDwordValue("pauseWhenInactive", pauseWhenInactive); | |
2237 regSetDwordValue("enableBackgroundInput", enableBackgroundInput); | |
2238 regSetDwordValue("priority", threadPriority); | |
2239 | |
2240 regSetDwordValue("filenamePreference", filenamePreference); | |
2241 regSetDwordValue("altAviRecordMethod", altAviRecordMethod); | |
2242 regSetDwordValue("captureFormat", captureFormat); | |
2243 | |
2244 regSetDwordValue("cheatsEnabled", cheatsEnabled); | |
2245 regSetDwordValue("autoSaveCheatList", autoSaveLoadCheatList); | |
2246 regSetDwordValue("pauseDuringCheatSearch2", pauseDuringCheatSearch); | |
2247 | |
2248 regSetDwordValue("rewindTimer", rewindTimer); | |
2249 regSetDwordValue("rewindSlots", rewindSlots); | |
2250 | |
2251 regSetDwordValue("recentFreeze", recentFreeze); | |
2252 CString buffer; | |
2253 for (int i = 0; i < 10; i++) | |
2254 { | |
2255 buffer.Format("recent%d", i); | |
2256 regSetStringValue(buffer, recentFiles[i]); | |
2257 } | |
2258 | |
2259 regSetDwordValue("autoLoadMostRecent", autoLoadMostRecent); | |
2260 regSetDwordValue("loadMakesRecent", loadMakesRecent); | |
2261 regSetDwordValue("loadMakesCurrent", loadMakesCurrent); | |
2262 regSetDwordValue("saveMakesCurrent", saveMakesCurrent); | |
2263 regSetDwordValue("currentSlot", currentSlot); | |
2264 regSetDwordValue("showSlotTime", showSlotTime); | |
2265 | |
2266 regSetDwordValue("movieOnEndBehavior", movieOnEndBehavior); | |
2267 regSetDwordValue("movieOnEndPause", movieOnEndPause); | |
2268 | |
2269 extern bool autoConvertMovieWhenPlaying; // from movie.cpp | |
2270 regSetDwordValue("autoConvertMovieWhenPlaying", autoConvertMovieWhenPlaying); | |
2271 } | |
2272 |