view 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
line wrap: on
line source
1 // VBA.cpp : Defines the class behaviors for the application.
2 //
3 #include "stdafx.h"
4 #include <mmsystem.h>
5 #include <cassert>
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"
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"
37 extern IDisplay *newGDIDisplay();
38 extern IDisplay *newDirectDrawDisplay();
39 extern IDisplay *newDirect3DDisplay();
40 extern IDisplay *newOpenGLDisplay();
42 extern Input *newDirectInput();
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;
51 void winlog(const char *msg, ...);
53 bool debugger = false;
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;
65 void winSignal(int, int);
66 void winOutput(char *, u32);
68 void (*dbgSignal)(int, int) = winSignal;
69 void (*dbgOutput)(char *, u32) = winOutput;
71 #ifdef MMX
72 extern "C" bool cpu_mmx;
73 #endif
75 // nowhere good to put them to
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 }
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);
123 ++copyOffsetY; // don't know why it's needed
125 VBALuaGui(&pix[copyOffsetY * pitch + copyOffsetX * (systemColorDepth / 8)], copyX, screenX, screenY);
126 VBALuaClearGui();
127 }
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 }
137 void winlog(const char *msg, ...)
138 {
139 CString buffer;
140 va_list valist;
142 va_start(valist, msg);
143 buffer.FormatV(msg, valist);
145 FILE *winout = fopen("vba-trace.log", "w");
147 fputs(buffer, winout);
149 fclose(winout);
151 va_end(valist);
152 }
154 // code from SDL_main.c for Windows
155 /* Parse a command line buffer into arguments */
157 static int parseCommandLine(char *cmdline, char * *argv)
158 {
159 char *bufp;
160 int argc;
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 }
220 static void debugSystemScreenMessage1(const char *msg)
221 {
222 systemScreenMessage(msg, 3);
223 }
225 static void debugSystemScreenMessage2(const char *msg)
226 {
227 systemScreenMessage(msg, 4);
228 }
230 static void winSignal(int, int)
231 {}
233 #define CPUReadByteQuick(addr) \
234 map[(addr) >> 24].address[(addr) & map[(addr) >> 24].mask]
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;
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 }
259 typedef BOOL (WINAPI * GETMENUBARINFO)(HWND, LONG, LONG, PMENUBARINFO);
261 static int winGetMenuBarHeight()
262 {
263 HINSTANCE hinstDll = /**/ ::LoadLibrary("USER32.DLL");
265 if (hinstDll)
266 {
267 GETMENUBARINFO func = (GETMENUBARINFO)GetProcAddress(hinstDll, "GetMenuBarInfo");
269 if (func)
270 {
271 MENUBARINFO info;
272 info.cbSize = sizeof(info);
274 func(AfxGetMainWnd()->GetSafeHwnd(), OBJID_MENU, 0, &info);
276 /**/ ::FreeLibrary(hinstDll);
278 return info.rcBar.bottom - info.rcBar.top + 1;
279 }
280 }
282 return GetSystemMetrics(SM_CYMENU);
283 }
285 /////////////////////////////////////////////////////////////////////////////
286 // VBA
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()
295 /////////////////////////////////////////////////////////////////////////////
296 // The one and only VBA object
298 VBA theApp;
300 /////////////////////////////////////////////////////////////////////////////
301 // VBA construction
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));
315 #ifdef MULTITHREAD_STDLOCALE_WORKAROUND
316 if (iPreviousFlag > 0 )
317 ::_configthreadlocale(iPreviousFlag);
318 #endif
319 }
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;
459 updateCount = 0;
461 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
463 ZeroMemory(&emulator, sizeof(emulator));
465 hAccel = NULL;
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 }
475 VBAMovieInit();
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 }
490 VBA::~VBA()
491 {
492 if (VBAMovieActive())
493 VBAMovieStop(true);
495 saveSettings();
497 InterframeCleanup();
499 if (aviRecorder)
500 {
501 delete aviRecorder;
502 aviRecorder = NULL;
503 aviRecording = false;
504 }
506 if (soundRecorder)
507 {
508 delete soundRecorder;
509 soundRecorder = NULL;
510 }
511 soundRecording = false;
512 soundPause();
513 soundShutdown();
515 ((MainWnd *)(m_pMainWnd))->winFileClose();
517 if (input)
518 delete input;
520 shutdownDisplay();
522 if (rewindMemory)
523 free(rewindMemory);
525 if (frameSearchMemory)
526 free(frameSearchMemory);
528 timeEndPeriod(wmTimerRes);
529 }
531 /////////////////////////////////////////////////////////////////////////////
532 // VBA initialization
534 #include <afxdisp.h>
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.
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
550 SetRegistryKey(_T("VBA"));
552 remoteSetProtocol(0);
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;
558 wndClass = AfxRegisterWndClass(0, LoadCursor(IDC_ARROW), (HBRUSH)GetStockObject(BLACK_BRUSH), LoadIcon(IDI_ICON));
560 char winBuffer[2048];
561 GetModuleFileName(NULL, winBuffer, 2048);
562 char *p = strrchr(winBuffer, '\\');
563 if (p)
564 *p = 0;
565 exeDir = winBuffer;
567 regInit(winBuffer);
569 loadSettings();
570 theApp.LuaFastForward = -1;
571 if (!initInput())
572 return FALSE;
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 }
585 hAccel = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR));
587 winAccelMgr.Connect((MainWnd *)m_pMainWnd);
589 extern void winAccelAddCommandsFromMenu(CAcceleratorManager & mgr, CMenu * pMenu, const CString &parentStr);
590 extern void winAccelAddCommandsFromTable(CAcceleratorManager & mgr);
592 winAccelAddCommandsFromMenu(winAccelMgr, &m_menu, CString());
593 winAccelAddCommandsFromTable(winAccelMgr);
595 winAccelMgr.CreateDefaultTable();
596 winAccelMgr.Load();
597 winAccelMgr.UpdateWndTable();
598 winAccelMgr.UpdateMenu(menu);
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);
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);
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 }
791 /*
792 int index = filename.ReverseFind('.');
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 }
804 return TRUE;
805 }
807 void VBA::adjustDestRect()
808 {
809 POINT point;
811 point.x = 0;
812 point.y = 0;
814 m_pMainWnd->ClientToScreen(&point);
815 dest.top = point.y;
816 dest.left = point.x;
818 point.x = surfaceSizeX;
819 point.y = surfaceSizeY;
821 m_pMainWnd->ClientToScreen(&point);
822 dest.bottom = point.y;
823 dest.right = point.x;
825 if (videoOption > VIDEO_4X)
826 {
827 int menuSkip = 0;
828 if (menuToggle)
829 {
830 menuSkip = winGetMenuBarHeight();
831 }
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 }
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 }
890 void VBA::updateFilter()
891 {
892 filterWidth = sizeX;
893 filterHeight = sizeY;
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;
1064 switch (filterType)
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;
1091 else
1092 filterFunction = NULL;
1095 if (display)
1096 display->changeRenderSize(rect.right, rect.bottom);
1099 void VBA::recreateMenuBar()
1101 m_menu.Detach();
1102 m_menu.Attach(winResLoadMenu(MAKEINTRESOURCE(IDR_MENU)));
1104 if (m_pMainWnd && menuToggle) // assuming that whether the menu has been set is always kept tracked
1106 m_pMainWnd->SetMenu(&m_menu);
1109 if (menu != NULL)
1111 DestroyMenu(menu);
1114 menu = m_menu.GetSafeHmenu();
1117 void VBA::updateMenuBar()
1119 if (flagHideMenu)
1120 return;
1122 recreateMenuBar();
1124 if (popup != NULL)
1126 // force popup recreation if language changed
1127 DestroyMenu(popup);
1128 popup = NULL;
1132 void VBA::saveRewindStateIfNecessary()
1134 if (rewindSaveNeeded && rewindMemory && emulator.emuWriteMemState)
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))
1142 rewindPos = ++rewindPos % rewindSlots;
1143 assert(rewindPos >= 0 && rewindPos < rewindSlots);
1144 if (rewindCount == rewindSlots)
1145 rewindTopPos = ++rewindTopPos % rewindSlots;
1149 // also update/cache some frame search stuff
1150 if (frameSearching)
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;
1158 if (curFrame == endFrame)
1160 // cache intermediate state to speed up searching forward
1161 emulator.emuWriteMemState(&frameSearchMemory[REWIND_SIZE * 1], REWIND_SIZE);
1164 if (curFrame == endFrame + 1)
1166 emulator.emuWriteMemState(&frameSearchMemory[REWIND_SIZE * 2], REWIND_SIZE);
1167 frameSearchLoadValid = true;
1170 else
1172 frameSearchFirstStep = false;
1174 assert(!frameSearchSkipping);
1175 // just in case
1176 frameSearchSkipping = false;
1180 BOOL VBA::OnIdle(LONG lCount)
1182 if (emulating && debugger)
1184 MSG msg;
1185 remoteStubMain();
1186 if (debugger)
1187 return TRUE; // continue loop
1188 return !::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE);
1190 else if (emulating && active && !paused)
1192 /// for(int i = 0; i < 2; i++)
1194 emulator.emuMain(emulator.emuCount);
1196 // save the state for rewinding, if necessary
1197 saveRewindStateIfNecessary();
1199 rewindSaveNeeded = false;
1202 if (mouseCounter)
1204 if (--mouseCounter == 0)
1206 SetCursor(NULL);
1209 return TRUE;
1211 else if (emulating) // this fixes display if resetting while paused
1213 // VBAUpdateButtonPressDisplay();
1214 VBAUpdateFrameCountDisplay();
1215 systemRefreshScreen();
1218 return FALSE;
1220 // return CWinApp::OnIdle(lCount);
1223 void VBA::addRecentFile(const CString &file)
1225 // Do not change recent list if frozen
1226 if (recentFreeze)
1227 return;
1228 int i = 0;
1229 for (i = 0; i < 10; ++i)
1231 if (recentFiles[i].GetLength() == 0)
1232 break;
1234 if (recentFiles[i].Compare(file) == 0)
1236 if (i == 0)
1237 return;
1238 CString p = recentFiles[i];
1239 for (int j = i; j > 0; --j)
1241 recentFiles[j] = recentFiles[j - 1];
1243 recentFiles[0] = p;
1244 return;
1247 int num = 0;
1248 for (i = 0; i < 10; ++i)
1250 if (recentFiles[i].GetLength() != 0)
1251 ++num;
1253 if (num == 10)
1255 --num;
1258 for (i = num; i >= 1; --i)
1260 recentFiles[i] = recentFiles[i - 1];
1262 recentFiles[0] = file;
1265 void VBA::updateFrameSkip()
1267 switch (systemCartridgeType)
1269 case 0:
1270 systemFrameSkip = frameSkip;
1271 break;
1272 case 1:
1273 systemFrameSkip = gbFrameSkip;
1274 break;
1278 void VBA::updateVideoSize(UINT id)
1280 int value = 0;
1281 bool forceUpdate = false;
1283 switch (id)
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;
1325 if (videoOption != value || forceUpdate)
1326 updateWindowSize(value);
1329 void VBA::updateWindowSize(int value)
1331 regSetDwordValue("video", value);
1333 if (value == VIDEO_OTHER)
1335 regSetDwordValue("fsWidth", fsWidth);
1336 regSetDwordValue("fsHeight", fsHeight);
1337 regSetDwordValue("fsColorDepth", fsColorDepth);
1340 if (display &&
1341 (((value >= VIDEO_320x240 || videoOption >= VIDEO_320x240) && videoOption != value) ||
1342 fsForceChange))
1344 fsForceChange = false;
1345 videoOption = value;
1346 initDisplay();
1349 videoOption = value;
1351 if (systemCartridgeType == 1)
1353 if (gbBorderOn)
1355 sizeX = 256;
1356 sizeY = 224;
1357 gbBorderLineSkip = 256;
1358 gbBorderColumnSkip = 48;
1359 gbBorderRowSkip = 40;
1361 else
1363 sizeX = 160;
1364 sizeY = 144;
1365 gbBorderLineSkip = 160;
1366 gbBorderColumnSkip = 0;
1367 gbBorderRowSkip = 0;
1370 else
1372 sizeX = 240;
1373 sizeY = 160;
1376 switch (videoOption)
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)
1401 surfaceSizeX = fsWidth;
1402 surfaceSizeY = fsHeight;
1404 else
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);
1414 break;
1417 rect.left = 0;
1418 rect.top = 0;
1419 rect.right = sizeX;
1420 rect.bottom = sizeY;
1422 int winSizeX = 0;
1423 int winSizeY = 0;
1424 int x = 0;
1425 int y = 0;
1427 DWORD style = WS_POPUP | WS_VISIBLE;
1428 DWORD styleEx = alwaysOnTop ? WS_EX_TOPMOST : 0;
1430 if (videoOption <= VIDEO_4X)
1432 style |= WS_OVERLAPPEDWINDOW;
1434 dest.left = 0;
1435 dest.top = 0;
1436 dest.right = surfaceSizeX;
1437 dest.bottom = surfaceSizeY;
1439 x = windowPositionX;
1440 y = windowPositionY;
1442 else
1444 dest.left = 0;
1445 dest.top = 0;
1446 dest.right = fsWidth;
1447 dest.bottom = fsHeight;
1450 AdjustWindowRectEx(&dest, style, flagHideMenu ? FALSE : TRUE, styleEx);
1451 winSizeX = dest.right - dest.left;
1452 winSizeY = dest.bottom - dest.top;
1454 if (m_pMainWnd == NULL)
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);
1466 if (!(HWND)*m_pMainWnd)
1468 winlog("Error creating Window %08x\n", GetLastError());
1469 AfxPostQuitMessage(0);
1470 return;
1473 else
1475 m_pMainWnd->SetWindowPos(0, //HWND_TOPMOST,
1476 x,
1477 y,
1478 winSizeX,
1479 winSizeY,
1480 SWP_NOMOVE | SWP_SHOWWINDOW);
1483 updateMenuBar(); // add menubar first of all, or winGetMenuBarHeight() will get random height.
1484 winAccelMgr.UpdateMenu(menu);
1485 adjustDestRect();
1487 updateIFB();
1488 updateFilter();
1490 m_pMainWnd->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
1493 bool VBA::initDisplay()
1495 if (display)
1497 changingVideoSize = true;
1498 shutdownDisplay();
1499 if (input)
1501 delete input;
1502 input = NULL;
1504 CWnd *pWnd = m_pMainWnd;
1506 m_pMainWnd = NULL;
1507 pWnd->DragAcceptFiles(FALSE);
1508 pWnd->DestroyWindow();
1509 delete pWnd;
1511 display = NULL;
1514 if (display == NULL)
1516 updateWindowSize(videoOption);
1518 switch (renderMethod)
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;
1534 if (display->initialize())
1536 if (input == NULL)
1538 if (!initInput())
1540 changingVideoSize = false;
1541 AfxPostQuitMessage(0);
1542 return false;
1546 input->checkKeys();
1548 changingVideoSize = false;
1550 else
1552 if (videoOption == VIDEO_320x240 ||
1553 videoOption == VIDEO_640x480 ||
1554 videoOption == VIDEO_800x600 ||
1555 videoOption == VIDEO_OTHER)
1557 regSetDwordValue("video", VIDEO_1X);
1558 if (pVideoDriverGUID)
1559 regSetDwordValue("defaultVideoDriver", TRUE);
1561 changingVideoSize = false;
1562 return false;
1565 changingVideoSize = false;
1566 return true;
1569 bool VBA::updateRenderMethod(bool force)
1571 bool res = true;
1572 if (force || (display && display->getType() != renderMethod))
1574 res = initDisplay();
1576 while (!res && renderMethod > 0)
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;
1585 res = initDisplay();
1589 updateIFB();
1590 updateFilter();
1592 m_pMainWnd->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
1594 regSetDwordValue("renderMethod", renderMethod);
1596 return res;
1599 void VBA::winCheckFullscreen()
1601 if (videoOption > VIDEO_4X && tripleBuffering)
1603 if (display)
1604 display->checkFullScreen();
1608 void VBA::shutdownDisplay()
1610 if (display != NULL)
1612 display->cleanup();
1613 delete display;
1614 display = NULL;
1618 void VBA::updatePriority()
1620 switch (threadPriority)
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);
1636 #ifdef MMX
1637 bool VBA::detectMMX()
1639 bool support = false;
1640 char brand[13];
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;
1652 __except(EXCEPTION_EXECUTE_HANDLER) {
1653 if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION)
1655 return false;
1657 return false;
1659 // Check for Intel or AMD CPUs
1660 if (strncmp(brand, "GenuineIntel", 12))
1662 if (strncmp(brand, "AuthenticAMD", 12))
1664 return false;
1668 __asm {
1669 mov eax, 1;
1670 cpuid;
1671 test edx, 00800000h;
1672 jz NotFound;
1673 mov [support], 1;
1674 NotFound:
1676 return support;
1679 #endif
1681 void VBA::winSetLanguageOption(int option, bool force)
1683 if (((option == languageOption) && option != 2) && !force)
1684 return;
1685 switch (option)
1687 case 0:
1689 char lbuffer[10];
1691 if (GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SABBREVLANGNAME,
1692 lbuffer, 10))
1694 HINSTANCE l = winLoadLanguage(lbuffer);
1695 if (l == NULL)
1697 LCID locIdBase = MAKELCID(MAKELANGID(PRIMARYLANGID(GetSystemDefaultLangID()), SUBLANG_NEUTRAL), SORT_DEFAULT);
1698 if (GetLocaleInfo(locIdBase, LOCALE_SABBREVLANGNAME,
1699 lbuffer, 10))
1701 l = winLoadLanguage(lbuffer);
1702 if (l == NULL)
1704 systemMessage(IDS_FAILED_TO_LOAD_LIBRARY,
1705 "Failed to load library %s",
1706 lbuffer);
1707 return;
1711 AfxSetResourceHandle(l);
1712 if (languageModule != NULL)
1713 /**/ ::FreeLibrary(languageModule);
1714 languageModule = l;
1716 else
1718 systemMessage(IDS_FAILED_TO_GET_LOCINFO,
1719 "Failed to get locale information");
1720 return;
1722 break;
1724 case 1:
1725 if (languageModule != NULL)
1726 /**/ ::FreeLibrary(languageModule);
1727 languageModule = NULL;
1728 AfxSetResourceHandle(AfxGetInstanceHandle());
1729 break;
1730 case 2:
1732 if (!force)
1734 LangSelect dlg;
1735 if (dlg.DoModal())
1737 HINSTANCE l = winLoadLanguage(languageName);
1738 if (l == NULL)
1740 systemMessage(IDS_FAILED_TO_LOAD_LIBRARY,
1741 "Failed to load library %s",
1742 languageName);
1743 return;
1745 AfxSetResourceHandle(l);
1746 if (languageModule != NULL)
1747 /**/ ::FreeLibrary(languageModule);
1748 languageModule = l;
1751 else
1753 if (languageName.IsEmpty())
1754 return;
1755 HINSTANCE l = winLoadLanguage(languageName);
1756 if (l == NULL)
1758 systemMessage(IDS_FAILED_TO_LOAD_LIBRARY,
1759 "Failed to load library %s",
1760 languageName);
1761 return;
1763 AfxSetResourceHandle(l);
1764 if (languageModule != NULL)
1765 FreeLibrary(languageModule);
1766 languageModule = l;
1768 break;
1771 languageOption = option;
1772 updateMenuBar();
1773 theApp.winAccelMgr.UpdateMenu(theApp.menu);
1776 HINSTANCE VBA::winLoadLanguage(const char *name)
1778 CString buffer;
1780 buffer.Format("vba_%s.dll", name);
1782 HINSTANCE l = /**/ ::LoadLibrary(buffer);
1784 if (l == NULL)
1786 if (strlen(name) == 3)
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);
1794 return /**/ ::LoadLibrary(buffer);
1797 return l;
1800 bool VBA::initInput()
1802 if (input)
1803 delete input;
1804 input = newDirectInput();
1805 if (input->initialize())
1807 input->loadSettings();
1808 input->checkKeys();
1809 return true;
1811 delete input;
1812 return false;
1815 void VBA::winAddUpdateListener(IUpdateListener *l)
1817 updateList.AddTail(l);
1818 updateCount++;
1821 void VBA::winRemoveUpdateListener(IUpdateListener *l)
1823 POSITION pos = updateList.Find(l);
1824 if (pos)
1826 updateList.RemoveAt(pos);
1827 updateCount--;
1828 if (updateCount < 0)
1829 updateCount = 0;
1833 void VBA::loadSettings()
1835 CString buffer;
1836 // video
1837 bool defaultVideoDriver = regQueryDwordValue("defaultVideoDriver", true) ? true : false;
1838 if (!regQueryBinaryValue("videoDriverGUID", (char *)&videoDriverGUID, sizeof(GUID)))
1840 defaultVideoDriver = TRUE;
1842 if (defaultVideoDriver)
1843 pVideoDriverGUID = NULL;
1844 else
1845 pVideoDriverGUID = &videoDriverGUID;
1847 videoOption = regQueryDwordValue("video", 0);
1848 if (videoOption < 0 || videoOption > VIDEO_OTHER)
1849 videoOption = 0;
1850 switch (videoOption)
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;
1868 if (videoOption == VIDEO_OTHER)
1870 if (fsWidth < 0 || fsWidth > 4095 || fsHeight < 0 || fsHeight > 4095)
1871 videoOption = 0;
1872 if (fsColorDepth != 16 && fsColorDepth != 24 && fsColorDepth != 32)
1873 videoOption = 0;
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;
1882 renderMethod = (DISPLAY_TYPE)regQueryDwordValue("renderMethod", DIRECT_DRAW);
1883 if (renderMethod < GDI || renderMethod > OPENGL)
1884 renderMethod = DIRECT_DRAW;
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;
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;
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;
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;
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;
1928 // speed
1929 throttle = regQueryDwordValue("throttle", 0);
1930 if (throttle < 5 || throttle > 1000)
1931 throttle = 100;
1933 synchronize = regQueryDwordValue("synchronize", 1) ? true : false;
1934 accuratePitchThrottle = regQueryDwordValue("accuratePitchThrottle", FALSE) ? TRUE : FALSE;
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;
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;
1959 useBiosFile = regQueryDwordValue("useBios", 0) ? true : false;
1960 skipBiosFile = regQueryDwordValue("skipBios", 0) ? true : false;
1961 buffer = regQueryStringValue("biosFile", "");
1962 if (!buffer.IsEmpty())
1964 biosFileName = buffer;
1966 // removeIntros = regQueryDwordValue("removeIntros", false) ? true : false;
1968 autoIPS = regQueryDwordValue("autoIPS", true) ? true : false;
1970 agbPrintEnable(regQueryDwordValue("agbPrint", 0) ? true : false);
1971 winRtcEnable = regQueryDwordValue("rtcEnabled", 0) ? true : false;
1972 rtcEnable(winRtcEnable);
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;
1982 cpuDisableSfx = regQueryDwordValue("disableSfx", 0) ? true : false;
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);
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));
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;
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;
2027 autoHideMenu = regQueryDwordValue("autoHideMenu", 0) ? true : false;
2029 languageOption = regQueryDwordValue("language", 1);
2030 if (languageOption < 0 || languageOption > 2)
2031 languageOption = 1;
2032 buffer = regQueryStringValue("languageName", "");
2033 if (!buffer.IsEmpty())
2035 languageName = buffer.Left(3);
2037 else
2038 languageName = "";
2039 winSetLanguageOption(languageOption, true);
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();
2050 filenamePreference = regQueryDwordValue("filenamePreference", 0);
2051 altAviRecordMethod = regQueryDwordValue("altAviRecordMethod", false) ? true : false;
2052 captureFormat = regQueryDwordValue("captureFormat", 0);
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)
2064 if (rewindMemory == NULL)
2065 rewindMemory = (char *)malloc(rewindSlots * REWIND_SIZE);
2068 if (frameSearchMemory == NULL)
2069 frameSearchMemory = (char *)malloc(3 * REWIND_SIZE);
2071 recentFreeze = regQueryDwordValue("recentFreeze", false) ? true : false;
2072 for (int i = 0, j = 0; i < 10; ++i)
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;
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;
2089 cheatsEnabled = regQueryDwordValue("cheatsEnabled", true) ? true : false;
2090 autoSaveLoadCheatList = regQueryDwordValue("autoSaveCheatList", 0) ? true : false;
2091 pauseDuringCheatSearch = regQueryDwordValue("pauseDuringCheatSearch2", 0) ? true : false;
2093 movieOnEndBehavior = regQueryDwordValue("movieOnEndBehavior", 0);
2094 movieOnEndPause = regQueryDwordValue("movieOnEndPause", 0) ? true : false;
2096 extern bool autoConvertMovieWhenPlaying; // from movie.cpp
2097 autoConvertMovieWhenPlaying = regQueryDwordValue("autoConvertMovieWhenPlaying", 0) ? true : false;
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);
2105 // this is FILO
2106 for (int i = MAX_RECENT_WATCHES; i > 0; --i)
2108 buffer.Format("recentWatch%d", i);
2109 const char *s = regQueryStringValue(buffer, NULL);
2110 if (s == NULL)
2111 continue;
2112 RWAddRecentFile(s);
2116 void VBA::saveSettings()
2118 regSetDwordValue("defaultVideoDriver", pVideoDriverGUID == NULL);
2119 if (pVideoDriverGUID)
2121 regSetBinaryValue("videoDriverGUID", (char *)&videoDriverGUID,
2122 sizeof(GUID));
2124 regSetDwordValue("video", videoOption);
2126 regSetDwordValue("fsWidth", fsWidth);
2127 regSetDwordValue("fsHeight", fsHeight);
2128 regSetDwordValue("fsColorDepth", fsColorDepth);
2129 regSetDwordValue("fsMaxScale", fsMaxScale);
2131 regSetDwordValue("stretch", fullScreenStretch);
2133 regSetDwordValue("renderMethod", renderMethod);
2135 regSetDwordValue("ddrawEmulationOnly", ddrawEmulationOnly);
2136 regSetDwordValue("ddrawUseVideoMemory", ddrawUseVideoMemory);
2137 regSetDwordValue("tripleBuffering", tripleBuffering);
2138 regSetDwordValue("vsync", vsync);
2140 regSetDwordValue("d3dFilter", d3dFilter);
2141 regSetDwordValue("glFilter", glFilter);
2142 regSetDwordValue("glType", glType);
2144 // pixel filter & ifb
2145 regSetDwordValue("filter", filterType);
2146 regSetDwordValue("ifbType", ifbType);
2147 regSetDwordValue("disableMMX", disableMMX);
2149 // frame skipping
2150 regSetDwordValue("frameSkip", frameSkip);
2151 regSetDwordValue("gbFrameSkip", gbFrameSkip);
2152 /// regSetDwordValue("autoFrameSkip", autoFrameSkip);
2154 // input
2155 regSetDwordValue("joypadDefault", joypadDefault);
2156 regSetDwordValue("allowLeftRight", allowLeftRight);
2157 regSetDwordValue("autofireAccountforLag", autofireAccountForLag);
2158 regSetDwordValue("nextframeAccountforLag", nextframeAccountForLag);
2159 regSetDwordValue("AsscWithSaveState", theApp.AsscWithSaveState);
2162 // speed
2163 regSetDwordValue("throttle", throttle);
2164 regSetDwordValue("synchronize", synchronize);
2165 regSetDwordValue("accuratePitchThrottle", accuratePitchThrottle);
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);
2178 // emulation
2179 regSetDwordValue("useBios", useBiosFile);
2180 regSetDwordValue("skipBios", skipBiosFile);
2181 if (!biosFileName.IsEmpty())
2182 regSetStringValue("biosFile", biosFileName);
2183 // regSetDwordValue("removeIntros", removeIntros);
2185 regSetDwordValue("autoIPS", autoIPS);
2187 regSetDwordValue("memLagEnabled", memLagEnabled);
2188 regSetDwordValue("gbNullInputHackEnabled", gbNullInputHackEnabled);
2189 regSetDwordValue("useOldGBTiming", useOldFrameTiming);
2190 regSetDwordValue("useOldSync", useOldSync);
2192 regSetDwordValue("agbPrint", agbPrintIsEnabled());
2193 regSetDwordValue("rtcEnabled", winRtcEnable);
2195 regSetDwordValue("saveType", winSaveType);
2196 regSetDwordValue("enhancedDetection", cpuEnhancedDetection);
2197 regSetDwordValue("flashSize", winFlashSize);
2199 regSetDwordValue("disableSfx", cpuDisableSfx);
2201 // GBx
2202 regSetDwordValue("emulatorType", gbEmulatorType);
2203 regSetDwordValue("gbPrinter", winGbPrinterEnabled);
2204 regSetDwordValue("borderOn", winGbBorderOn);
2205 regSetDwordValue("borderAutomatic", gbBorderAutomatic);
2207 regSetDwordValue("colorOption", gbColorOption);
2208 regSetDwordValue("gbPaletteOption", gbPaletteOption);
2209 regSetBinaryValue("gbPalette", (char *)systemGbPalette, 24 * sizeof(u16));
2211 // head-up display
2212 regSetDwordValue("showSpeed", showSpeed);
2213 regSetDwordValue("showSpeedTransparent", showSpeedTransparent);
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);
2225 // UI
2226 regSetDwordValue("windowX", windowPositionX);
2227 regSetDwordValue("windowY", windowPositionY);
2229 regSetDwordValue("autoHideMenu", autoHideMenu);
2231 regSetDwordValue("language", languageOption);
2232 regSetStringValue("languageName", languageName);
2234 // preferences
2235 regSetDwordValue("alwaysOnTop", alwaysOnTop);
2236 regSetDwordValue("pauseWhenInactive", pauseWhenInactive);
2237 regSetDwordValue("enableBackgroundInput", enableBackgroundInput);
2238 regSetDwordValue("priority", threadPriority);
2240 regSetDwordValue("filenamePreference", filenamePreference);
2241 regSetDwordValue("altAviRecordMethod", altAviRecordMethod);
2242 regSetDwordValue("captureFormat", captureFormat);
2244 regSetDwordValue("cheatsEnabled", cheatsEnabled);
2245 regSetDwordValue("autoSaveCheatList", autoSaveLoadCheatList);
2246 regSetDwordValue("pauseDuringCheatSearch2", pauseDuringCheatSearch);
2248 regSetDwordValue("rewindTimer", rewindTimer);
2249 regSetDwordValue("rewindSlots", rewindSlots);
2251 regSetDwordValue("recentFreeze", recentFreeze);
2252 CString buffer;
2253 for (int i = 0; i < 10; i++)
2255 buffer.Format("recent%d", i);
2256 regSetStringValue(buffer, recentFiles[i]);
2259 regSetDwordValue("autoLoadMostRecent", autoLoadMostRecent);
2260 regSetDwordValue("loadMakesRecent", loadMakesRecent);
2261 regSetDwordValue("loadMakesCurrent", loadMakesCurrent);
2262 regSetDwordValue("saveMakesCurrent", saveMakesCurrent);
2263 regSetDwordValue("currentSlot", currentSlot);
2264 regSetDwordValue("showSlotTime", showSlotTime);
2266 regSetDwordValue("movieOnEndBehavior", movieOnEndBehavior);
2267 regSetDwordValue("movieOnEndPause", movieOnEndPause);
2269 extern bool autoConvertMovieWhenPlaying; // from movie.cpp
2270 regSetDwordValue("autoConvertMovieWhenPlaying", autoConvertMovieWhenPlaying);