1 #if (_MSC_VER == 1600 && _M_IX86_FP >= 0 && (_MSC_FULL_VER < 160040219))
2 #error The version of Visual Studio 2010 you are using generates SSE2 instructions when /arch:SSE is specified. Please update to Service Pack 1.
3 #endif
4
5 #ifdef NO_D3D
6 #ifdef NO_OGL
7 #error NO_D3D and NO_OGL must not be defined at the same time.
8 #endif
9 #endif
10
11 #include "stdafx.h"
12 #include "VBA.h"
13
14 #include <intrin.h>
15
16 #include "AVIWrite.h"
17 #include "LangSelect.h"
18 #include "MainWnd.h"
19 #include "Reg.h"
20 #include "resource.h"
21 #include "WavWriter.h"
22 #include "WinResUtil.h"
23 #include "Logging.h"
24 #include "rpi.h"
25
26 #include "../System.h"
27 #include "../gba/agbprint.h"
28 #include "../gba/cheatSearch.h"
29 #include "../gba/GBA.h"
30 #include "../gba/Globals.h"
31 #include "../gba/RTC.h"
32 #include "../gba/Sound.h"
33 #include "../Util.h"
34 #include "../gb/gbGlobals.h"
35 #include "../gb/gbPrinter.h"
36 #include "../gb/gbSound.h"
37 #include "../common/SoundDriver.h"
38 #include "../common/ConfigManager.h"
39
40 #include "../version.h"
41
42 /* Link
43 ---------------------*/
44 #include "../gba/GBALink.h"
45 /* ---------------- */
46
47 extern void Pixelate(u8*,u32,u8*,u8*,u32,int,int);
48 extern void Pixelate32(u8*,u32,u8*,u8*,u32,int,int);
49 extern void _2xSaI(u8*,u32,u8*,u8*,u32,int,int);
50 extern void _2xSaI32(u8*,u32,u8*,u8*,u32,int,int);
51 extern void Super2xSaI(u8*,u32,u8*,u8*,u32,int,int);
52 extern void Super2xSaI32(u8*,u32,u8*,u8*,u32,int,int);
53 extern void SuperEagle(u8*,u32,u8*,u8*,u32,int,int);
54 extern void SuperEagle32(u8*,u32,u8*,u8*,u32,int,int);
55 extern void AdMame2x(u8*,u32,u8*,u8*,u32,int,int);
56 extern void AdMame2x32(u8*,u32,u8*,u8*,u32,int,int);
57 extern void Bilinear(u8*,u32,u8*,u8*,u32,int,int);
58 extern void Bilinear32(u8*,u32,u8*,u8*,u32,int,int);
59 extern void BilinearPlus(u8*,u32,u8*,u8*,u32,int,int);
60 extern void BilinearPlus32(u8*,u32,u8*,u8*,u32,int,int);
61 extern void Scanlines(u8*,u32,u8*,u8*,u32,int,int);
62 extern void Scanlines32(u8*,u32,u8*,u8*,u32,int,int);
63 extern void ScanlinesTV(u8*,u32,u8*,u8*,u32,int,int);
64 extern void ScanlinesTV32(u8*,u32,u8*,u8*,u32,int,int);
65 extern void hq2x(u8*,u32,u8*,u8*,u32,int,int);
66 extern void hq2x32(u8*,u32,u8*,u8*,u32,int,int);
67 extern void lq2x(u8*,u32,u8*,u8*,u32,int,int);
68 extern void lq2x32(u8*,u32,u8*,u8*,u32,int,int);
69 extern void Simple2x16(u8*,u32,u8*,u8*,u32,int,int);
70 extern void Simple2x32(u8*,u32,u8*,u8*,u32,int,int);
71 extern void Simple3x16(u8*,u32,u8*,u8*,u32,int,int);
72 extern void Simple3x32(u8*,u32,u8*,u8*,u32,int,int);
73 extern void Simple4x16(u8*,u32,u8*,u8*,u32,int,int);
74 extern void Simple4x32(u8*,u32,u8*,u8*,u32,int,int);
75 #ifndef WIN64
76 extern void hq3x16(u8*,u32,u8*,u8*,u32,int,int);
77 extern void hq4x16(u8*,u32,u8*,u8*,u32,int,int);
78 extern void hq3x32(u8*,u32,u8*,u8*,u32,int,int);
79 extern void hq4x32(u8*,u32,u8*,u8*,u32,int,int);
80 #endif
81 extern void xbrz2x32(u8*,u32,u8*,u8*,u32,int,int);
82 extern void xbrz3x32(u8*,u32,u8*,u8*,u32,int,int);
83 extern void xbrz4x32(u8*,u32,u8*,u8*,u32,int,int);
84 extern void xbrz5x32(u8*,u32,u8*,u8*,u32,int,int);
85 extern void xbrz6x32(u8*,u32,u8*,u8*,u32,int,int);
86
87 extern void SmartIB(u8*,u32,int,int);
88 extern void SmartIB32(u8*,u32,int,int);
89 extern void MotionBlurIB(u8*,u32,int,int);
90 extern void MotionBlurIB32(u8*,u32,int,int);
91
92 extern IDisplay *newGDIDisplay();
93 extern IDisplay *newDirectDrawDisplay();
94 #ifndef NO_OGL
95 extern IDisplay *newOpenGLDisplay();
96 #endif
97 #ifndef NO_D3D
98 extern IDisplay *newDirect3DDisplay();
99 #endif
100
101 extern Input *newDirectInput();
102
103 extern SoundDriver *newDirectSound();
104 #ifndef NO_OAL
105 extern SoundDriver *newOpenAL();
106 #endif
107 #ifndef NO_XAUDIO2
108 extern SoundDriver *newXAudio2_Output();
109 #endif
110
111 extern void remoteStubSignal(int, int);
112 extern void remoteOutput(char *, u32);
113 extern void remoteStubMain();
114 extern void remoteSetProtocol(int);
115 extern void remoteCleanUp();
116 extern int remoteSocket;
117
118 extern void InterframeCleanup();
119
120 void winlog(const char *msg, ...);
121
122 /* Link
123 ---------------------*/
124 extern char inifile[];
125 /* ------------------- */
126 #ifdef _DEBUG
127 #define new DEBUG_NEW
128 #undef THIS_FILE
129 static char THIS_FILE[] = __FILE__;
130 #endif
131
132 int emulating = 0;
133 int RGB_LOW_BITS_MASK = 0;
134 bool b16to32Video = false;
135 int systemFrameSkip = 0;
136 int systemSpeed = 0;
137 u32 systemColorMap32[0x10000];
138 u16 systemColorMap16[0x10000];
139 u16 systemGbPalette[24];
140 int systemRedShift = 0;
141 int systemBlueShift = 0;
142 int systemGreenShift = 0;
143 int systemColorDepth = 16;
144 int realsystemRedShift = 0;
145 int realsystemBlueShift = 0;
146 int realsystemGreenShift = 0;
147 int realsystemColorDepth = 16;
148 int systemVerbose = 0;
149 int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
150 bool soundBufferLow = 0;
151 void winSignal(int,int);
152 void winOutput(const char *, u32);
153
154 #ifdef MMX
155 extern "C" bool cpu_mmx;
156 #endif
157
158 namespace Sm60FPS
159 {
160 float K_fCpuSpeed = 100.0f; // was 98.0f before, but why?
161 float K_fTargetFps = 60.0f * K_fCpuSpeed / 100;
162 float K_fDT = 1000.0f / K_fTargetFps;
163
164 u32 dwTimeElapse;
165 u32 dwTime0;
166 u32 dwTime1;
167 u32 nFrameCnt;
168 float fWantFPS;
169 float fCurFPS;
170 bool bLastSkip;
171 int nCurSpeed;
172 int bSaveMoreCPU;
173 };
174
175 #ifdef LOG_PERFORMANCE
176 #ifndef PERFORMANCE_INTERVAL
177 #define PERFORMANCE_INTERVAL 3600
178 #endif
179 int systemSpeedTable[PERFORMANCE_INTERVAL];
180 unsigned int systemSpeedCounter;
181 #endif
182
directXMessage(const char * msg)183 void directXMessage(const char *msg)
184 {
185 systemMessage(IDS_DIRECTX_7_REQUIRED,
186 "DirectX 7.0 or greater is required to run.\nDownload at http://www.microsoft.com/directx.\n\nError found at: %s",
187 msg);
188 }
189
190 /////////////////////////////////////////////////////////////////////////////
191 // VBA
192
VBA()193 VBA::VBA()
194 {
195 // COINIT_MULTITHREADED is not supported by SHBrowseForFolder with BIF_USENEWUI
196 // OpenAL also causes trouble when COINIT_MULTITHREADED is used
197 if( S_OK != CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ) ) {
198 systemMessage( IDS_COM_FAILURE, NULL );
199 }
200
201 // ! keep in mind that many of the following values will be really initialized in loadSettings()
202 maxCpuCores = 1;
203 windowPositionX = 0;
204 windowPositionY = 0;
205 filterFunction = NULL;
206 ifbFunction = NULL;
207 ifbType = kIFBNone;
208 filter = FILTER_NONE;
209 filterWidth = 0;
210 filterHeight = 0;
211 filterMT = false;
212 fsAdapter = 0;
213 fsWidth = 0;
214 fsHeight = 0;
215 fsColorDepth = 0;
216 fsFrequency = 0;
217 fsForceChange = false;
218 surfaceSizeX = 0;
219 surfaceSizeY = 0;
220 sizeX = 0;
221 sizeY = 0;
222 videoOption = 0;
223 fullScreenStretch = false;
224 showSpeed = 0;
225 showSpeedTransparent = true;
226 showRenderedFrames = 0;
227 screenMessage = false;
228 screenMessageTime = 0;
229 display = NULL;
230 menu = NULL;
231 popup = NULL;
232 cartridgeType = IMAGE_GBA;
233 soundInitialized = false;
234 useBiosFileGBA = false;
235 useBiosFileGBC = false;
236 useBiosFileGB = false;
237 skipBios = false;
238 biosFileNameGBA = _T("");
239 biosFileNameGBC = _T("");
240 biosFileNameGB = _T("");
241 active = true;
242 paused = false;
243 recentFreeze = false;
244 autoSaveLoadCheatList = true;
245 winout = NULL;
246 autoPatch = true;
247 winGbBorderOn = 0;
248 winFlashSize = 0x20000;
249 rtcEnabled = false;
250 cpuSaveType = 0;
251 rewindMemory = NULL;
252 rewindPos = 0;
253 rewindTopPos = 0;
254 rewindCounter = 0;
255 rewindCount = 0;
256 rewindSaveNeeded = false;
257 rewindTimer = 0;
258 captureFormat = 0;
259 tripleBuffering = true;
260 throttle = 0;
261 autoFrameSkipLastTime = 0;
262 autoFrameSkip = false;
263 vsync = false;
264 changingVideoSize = false;
265 renderMethod = DIRECT_3D;
266 audioAPI = DIRECTSOUND;
267 #ifndef NO_OAL
268 oalDevice = NULL;
269 oalBufferCount = 5;
270 #endif
271 #ifndef NO_XAUDIO2
272 audioAPI = XAUDIO2;
273 xa2Device = 0;
274 xa2BufferCount = 4;
275 xa2Upmixing = false;
276 #endif
277 #ifndef NO_D3D
278 d3dFilter = 0;
279 d3dMotionBlur = false;
280 #endif
281 iconic = false;
282 glFilter = 0;
283 regEnabled = false;
284 pauseWhenInactive = true;
285 speedupToggle = false;
286 winGbPrinterEnabled = false;
287 gdbBreakOnLoad = false;
288 threadPriority = 2;
289 disableMMX = false;
290 languageOption = 0;
291 languageModule = NULL;
292 languageName = "";
293 renderedFrames = 0;
294 input = NULL;
295 joypadDefault = 0;
296 autoFire = 0;
297 autoFireToggle = false;
298 winPauseNextFrame = false;
299 soundRecording = false;
300 soundRecorder = NULL;
301 dsoundDisableHardwareAcceleration = true;
302 aviRecording = false;
303 aviRecorder = NULL;
304 painting = false;
305 skipAudioFrames = 0;
306 movieRecording = false;
307 moviePlaying = false;
308 movieFrame = 0;
309 moviePlayFrame = 0;
310 movieFile = NULL;
311 movieLastJoypad = 0;
312 movieNextJoypad = 0;
313 sensorX = 2047;
314 sensorY = 2047;
315 sunBars = 500;
316 mouseCounter = 0;
317 wasPaused = false;
318 frameskipadjust = 0;
319 autoLoadMostRecent = false;
320 maxScale = 0;
321 romSize = 0;
322 lastWindowed = VIDEO_3X;
323 lastFullscreen = VIDEO_1024x768;
324
325 updateCount = 0;
326
327 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
328
329 ZeroMemory(&emulator, sizeof(emulator));
330
331 hAccel = NULL;
332
333 for(int i = 0; i < 24;) {
334 systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10);
335 systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10);
336 systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10);
337 systemGbPalette[i++] = 0;
338 }
339 }
340
~VBA()341 VBA::~VBA()
342 {
343 rpiCleanup();
344 InterframeCleanup();
345
346 char winBuffer[2048];
347
348 GetModuleFileName(NULL, winBuffer, 2048);
349 char *p = strrchr(winBuffer, '\\');
350 if(p)
351 *p = 0;
352
353 regInit(winBuffer);
354 #ifndef NO_LINK
355 CloseLink();
356 #endif
357 saveSettings();
358
359 if(moviePlaying) {
360 if(movieFile != NULL) {
361 fclose(movieFile);
362 movieFile = NULL;
363 }
364 moviePlaying = false;
365 movieLastJoypad = 0;
366 }
367
368 if(movieRecording) {
369 if(movieFile != NULL) {
370 // record the last joypad change so that the correct time can be
371 // recorded
372 fwrite(&movieFrame, 1, sizeof(int), movieFile);
373 fwrite(&movieLastJoypad, 1, sizeof(u32), movieFile);
374 fclose(movieFile);
375 movieFile = NULL;
376 }
377 movieRecording = false;
378 moviePlaying = false;
379 movieLastJoypad = 0;
380 }
381
382 soundPause();
383 soundShutdown();
384
385 if(gbRom != NULL || rom != NULL) {
386 if(autoSaveLoadCheatList)
387 ((MainWnd *)m_pMainWnd)->winSaveCheatListDefault();
388 ((MainWnd *)m_pMainWnd)->writeBatteryFile();
389 cheatSearchCleanup(&cheatSearchData);
390 emulator.emuCleanUp();
391 }
392
393 if(input)
394 delete input;
395
396 shutdownDisplay();
397
398 if(rewindMemory)
399 free(rewindMemory);
400
401 #ifndef NO_OAL
402 if( oalDevice ) {
403 free( oalDevice );
404 }
405 #endif
406
407 CoUninitialize();
408 }
409
410 /////////////////////////////////////////////////////////////////////////////
411 // The one and only VBA object
412
413 VBA theApp;
414 /////////////////////////////////////////////////////////////////////////////
415 // VBA initialization
416
InitInstance()417 BOOL VBA::InitInstance()
418 {
419 #if _MSC_VER < 1400
420 #ifdef _AFXDLL
421 Enable3dControls(); // Call this when using MFC in a shared DLL
422 #else
423 Enable3dControlsStatic(); // Call this when linking to MFC statically
424 #endif
425 #endif
426
427 SetRegistryKey(_T("VBA"));
428
429 remoteSetProtocol(0);
430
431 systemVerbose = GetPrivateProfileInt("config",
432 "verbose",
433 0,
434 MakeInstanceFilename("vbam.ini"));
435
436 wndClass = AfxRegisterWndClass(0, LoadCursor(IDC_ARROW), (HBRUSH)GetStockObject(BLACK_BRUSH), LoadIcon(IDI_MAINICON));
437
438 char winBuffer[2048];
439
440 GetModuleFileName(NULL, winBuffer, 2048);
441 char *p = strrchr(winBuffer, '\\');
442 if(p)
443 *p = 0;
444
445 bool force = false;
446
447 if (m_lpCmdLine[0])
448 {
449 if(__argc > 0) {
450 if( 0 == strcmp( __argv[1], "--configpath" ) ) {
451 if( __argc > 2 ) {
452 strcpy( winBuffer, __argv[2] );
453 force = true;
454 if( __argc > 3 ) {
455 szFile = __argv[3]; filename = szFile;
456 int index = filename.ReverseFind('.');
457 if(index != -1)
458 filename = filename.Left(index);
459 }
460 }
461 } else {
462 szFile = __argv[1]; filename = szFile;
463 int index = filename.ReverseFind('.');
464 if(index != -1)
465 filename = filename.Left(index);
466 }
467 }
468 }
469
470 regInit(winBuffer, force);
471
472 loadSettings();
473
474 if(!initDisplay()) {
475 if(videoOption >= VIDEO_320x240) {
476 regSetDwordValue("video", VIDEO_2X);
477 }
478 return FALSE;
479 }
480
481 if(!initInput())
482 return FALSE;
483
484 hAccel = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR));
485
486 winAccelMgr.Connect((MainWnd *)m_pMainWnd);
487
488 winAccelMgr.SetRegKey(HKEY_CURRENT_USER, "Software\\Emulators\\VisualBoyAdvance");
489
490 extern void winAccelAddCommands(CAcceleratorManager&);
491
492 winAccelAddCommands(winAccelMgr);
493
494 winAccelMgr.CreateDefaultTable();
495
496 winAccelMgr.Load();
497
498 winAccelMgr.UpdateWndTable();
499
500 winAccelMgr.UpdateMenu(menu);
501
502 if( !filename.IsEmpty() ) {
503 if(((MainWnd*)m_pMainWnd)->FileRun())
504 emulating = true;
505 else
506 emulating = false;
507 }
508
509 return TRUE;
510 }
511
adjustDestRect()512 void VBA::adjustDestRect()
513 {
514 POINT point;
515
516 point.x = 0;
517 point.y = 0;
518
519 m_pMainWnd->ClientToScreen(&point);
520 dest.top = point.y;
521 dest.left = point.x;
522
523 point.x = surfaceSizeX;
524 point.y = surfaceSizeY;
525
526 m_pMainWnd->ClientToScreen(&point);
527 dest.bottom = point.y;
528 dest.right = point.x;
529
530 // make sure that dest rect lies in the monitor
531 if(videoOption >= VIDEO_320x240) {
532 dest.top -= windowPositionY;
533 dest.left -= windowPositionX;
534 dest.bottom-= windowPositionY;
535 dest.right -= windowPositionX;
536 }
537
538 if(videoOption > VIDEO_6X) {
539 if(fullScreenStretch) {
540 dest.top = 0;
541 dest.left = 0;
542 dest.right = fsWidth;
543 dest.bottom = fsHeight;
544 } else {
545 int top = (fsHeight - surfaceSizeY) / 2;
546 int left = (fsWidth - surfaceSizeX) / 2;
547 dest.top += top;
548 dest.bottom += top;
549 dest.left += left;
550 dest.right += left;
551 }
552 }
553 }
554
555
updateIFB()556 void VBA::updateIFB()
557 {
558 if(systemColorDepth == 16) {
559 switch(ifbType) {
560 case 0:
561 default:
562 ifbFunction = NULL;
563 break;
564 case 1:
565 ifbFunction = MotionBlurIB;
566 break;
567 case 2:
568 ifbFunction = SmartIB;
569 break;
570 }
571 } else if(systemColorDepth == 32) {
572 switch(ifbType) {
573 case 0:
574 default:
575 ifbFunction = NULL;
576 break;
577 case 1:
578 ifbFunction = MotionBlurIB32;
579 break;
580 case 2:
581 ifbFunction = SmartIB32;
582 break;
583 }
584 } else
585 ifbFunction = NULL;
586 }
587
updateFilter()588 void VBA::updateFilter()
589 {
590 // BEGIN hacky ugly code
591
592 // HQ3X asm wants 16 bit input. When we switch
593 // away from 16 bits we need to restore the driver values
594
595 // This hack is also necessary for Kega Fusion filter plugins
596
597 if ( b16to32Video )
598 {
599 b16to32Video = false;
600 systemColorDepth = realsystemColorDepth;
601 systemRedShift = realsystemRedShift;
602 systemGreenShift = realsystemGreenShift;
603 systemBlueShift = realsystemBlueShift;
604 utilUpdateSystemColorMaps(theApp.cartridgeType == IMAGE_GBA && gbColorOption == 1);
605 }
606 // END hacky ugly code
607
608 filterWidth = sizeX;
609 filterHeight = sizeY;
610 filterMagnification = 1;
611
612
613 if ( videoOption == VIDEO_1X || videoOption == VIDEO_320x240 )
614 {
615 filterFunction = NULL;
616 filterMagnification = 1;
617 }
618 else
619 {
620 if ( systemColorDepth == 16 )
621 {
622 switch(filter)
623 {
624 default:
625 case FILTER_NONE:
626 filterFunction = NULL;
627 filterMagnification = 1;
628 break;
629 case FILTER_PLUGIN:
630 if( rpiInit( pluginName ) ) {
631 filterFunction = rpiFilter;
632 filterMagnification = rpiScaleFactor();
633 } else {
634 filter = FILTER_NONE;
635 updateFilter();
636 return;
637 }
638 break;
639 case FILTER_TVMODE:
640 filterFunction = ScanlinesTV;
641 filterMagnification = 2;
642 break;
643 case FILTER_2XSAI:
644 filterFunction = _2xSaI;
645 filterMagnification = 2;
646 break;
647 case FILTER_SUPER2XSAI:
648 filterFunction = Super2xSaI;
649 filterMagnification = 2;
650 break;
651 case FILTER_SUPEREAGLE:
652 filterFunction = SuperEagle;
653 filterMagnification = 2;
654 break;
655 case FILTER_PIXELATE:
656 filterFunction = Pixelate;
657 filterMagnification = 2;
658 break;
659 case FILTER_MAMESCALE2X:
660 filterFunction = AdMame2x;
661 filterMagnification = 2;
662 break;
663 case FILTER_SIMPLE2X:
664 filterFunction = Simple2x16;
665 filterMagnification = 2;
666 break;
667 case FILTER_BILINEAR:
668 filterFunction = Bilinear;
669 filterMagnification = 2;
670 break;
671 case FILTER_BILINEARPLUS:
672 filterFunction = BilinearPlus;
673 filterMagnification = 2;
674 break;
675 case FILTER_SCANLINES:
676 filterFunction = Scanlines;
677 filterMagnification = 2;
678 break;
679 case FILTER_HQ2X:
680 filterFunction = hq2x;
681 filterMagnification = 2;
682 break;
683 case FILTER_LQ2X:
684 filterFunction = lq2x;
685 filterMagnification = 2;
686 break;
687 case FILTER_SIMPLE3X:
688 filterFunction = Simple3x16;
689 filterMagnification = 3;
690 break;
691 case FILTER_SIMPLE4X:
692 filterFunction = Simple4x16;
693 filterMagnification = 4;
694 break;
695 #ifndef WIN64
696 case FILTER_HQ3X:
697 filterFunction = hq3x16;
698 filterMagnification = 3;
699 break;
700 case FILTER_HQ4X:
701 filterFunction = hq4x16;
702 filterMagnification = 4;
703 break;
704 #endif
705 }
706 }
707
708 if ( systemColorDepth == 32 )
709 {
710 switch(filter)
711 {
712 default:
713 case FILTER_NONE:
714 filterFunction = NULL;
715 filterMagnification = 1;
716 break;
717 case FILTER_PLUGIN:
718 if( rpiInit( pluginName ) ) {
719 filterFunction = rpiFilter;
720 filterMagnification = rpiScaleFactor();
721 b16to32Video=true;
722 } else {
723 filter = FILTER_NONE;
724 updateFilter();
725 return;
726 }
727 break;
728 case FILTER_TVMODE:
729 filterFunction = ScanlinesTV32;
730 filterMagnification = 2;
731 break;
732 case FILTER_2XSAI:
733 filterFunction = _2xSaI32;
734 filterMagnification = 2;
735 break;
736 case FILTER_SUPER2XSAI:
737 filterFunction = Super2xSaI32;
738 filterMagnification = 2;
739 break;
740 case FILTER_SUPEREAGLE:
741 filterFunction = SuperEagle32;
742 filterMagnification = 2;
743 break;
744 case FILTER_PIXELATE:
745 filterFunction = Pixelate32;
746 filterMagnification = 2;
747 break;
748 case FILTER_MAMESCALE2X:
749 filterFunction = AdMame2x32;
750 filterMagnification = 2;
751 break;
752 case FILTER_SIMPLE2X:
753 filterFunction = Simple2x32;
754 filterMagnification = 2;
755 break;
756 case FILTER_BILINEAR:
757 filterFunction = Bilinear32;
758 filterMagnification = 2;
759 break;
760 case FILTER_BILINEARPLUS:
761 filterFunction = BilinearPlus32;
762 filterMagnification = 2;
763 break;
764 case FILTER_SCANLINES:
765 filterFunction = Scanlines32;
766 filterMagnification = 2;
767 break;
768 case FILTER_HQ2X:
769 filterFunction = hq2x32;
770 filterMagnification = 2;
771 break;
772 case FILTER_LQ2X:
773 filterFunction = lq2x32;
774 filterMagnification = 2;
775 break;
776 case FILTER_SIMPLE3X:
777 filterFunction = Simple3x32;
778 filterMagnification = 3;
779 break;
780 case FILTER_SIMPLE4X:
781 filterFunction = Simple4x32;
782 filterMagnification = 4;
783 break;
784 #ifndef WIN64
785 case FILTER_HQ3X:
786 filterFunction = hq3x32;
787 filterMagnification = 3;
788 #ifndef NO_ASM
789 b16to32Video=true;
790 #endif
791 break;
792 case FILTER_HQ4X:
793 filterFunction = hq4x32;
794 filterMagnification = 4;
795 #ifndef NO_ASM
796 b16to32Video=true;
797 #endif
798 break;
799 #endif
800 case FILTER_XBRZ2X:
801 filterFunction = xbrz2x32;
802 filterMagnification = 2;
803 break;
804 case FILTER_XBRZ3X:
805 filterFunction = xbrz3x32;
806 filterMagnification = 3;
807 break;
808 case FILTER_XBRZ4X:
809 filterFunction = xbrz4x32;
810 filterMagnification = 4;
811 break;
812 case FILTER_XBRZ5X:
813 filterFunction = xbrz5x32;
814 filterMagnification = 5;
815 break;
816 case FILTER_XBRZ6X:
817 filterFunction = xbrz6x32;
818 filterMagnification = 6;
819 break;
820 }
821 }
822 }
823
824 rect.right = sizeX * filterMagnification;
825 rect.bottom = sizeY * filterMagnification;
826
827
828 if( filter != FILTER_NONE )
829 memset(delta, 0xFF, sizeof(delta));
830
831 if( display )
832 display->changeRenderSize(rect.right, rect.bottom);
833
834 if (b16to32Video && systemColorDepth!=16)
835 {
836 realsystemColorDepth = systemColorDepth;
837 systemColorDepth = 16;
838 realsystemRedShift = systemRedShift;
839 systemRedShift = 11;
840 realsystemGreenShift = systemGreenShift;
841 systemGreenShift = 6;
842 realsystemBlueShift = systemBlueShift;
843 systemBlueShift = 0;
844 utilUpdateSystemColorMaps(theApp.cartridgeType == IMAGE_GBA && gbColorOption == 1);
845 }
846
847 #ifdef LOG_PERFORMANCE
848 memset( systemSpeedTable, 0x00, sizeof(systemSpeedTable) );
849 systemSpeedCounter = 0;
850 #endif
851 }
852
853
updateThrottle(unsigned short _throttle)854 void VBA::updateThrottle( unsigned short _throttle )
855 {
856 if( _throttle ) {
857 Sm60FPS::K_fCpuSpeed = (float)_throttle;
858 Sm60FPS::K_fTargetFps = 60.0f * Sm60FPS::K_fCpuSpeed / 100;
859 Sm60FPS::K_fDT = 1000.0f / Sm60FPS::K_fTargetFps;
860 autoFrameSkip = false;
861 frameSkip = 0;
862 systemFrameSkip = 0;
863 }
864
865 throttle = _throttle;
866 soundSetThrottle(_throttle);
867 }
868
869
updateMenuBar()870 void VBA::updateMenuBar()
871 {
872 if(menu != NULL) {
873 if(m_pMainWnd)
874 m_pMainWnd->SetMenu(NULL);
875 m_menu.Detach();
876 DestroyMenu(menu);
877 }
878
879 if(popup != NULL) {
880 // force popup recreation if language changed
881 DestroyMenu(popup);
882 popup = NULL;
883 }
884
885 if( ( videoOption >= VIDEO_320x240 ) ) {
886 return;
887 }
888
889 m_menu.Attach(winResLoadMenu(MAKEINTRESOURCE(IDR_MENU)));
890 menu = (HMENU)m_menu;
891
892 if(m_pMainWnd)
893 m_pMainWnd->SetMenu(&m_menu);
894 }
895
log(const char * msg,...)896 void log(const char *msg, ...)
897 {
898 CString buffer;
899 va_list valist;
900
901 va_start(valist, msg);
902 buffer.FormatV(msg, valist);
903
904 toolsLog(buffer);
905
906 va_end(valist);
907 }
908
systemReadJoypads()909 bool systemReadJoypads()
910 {
911 if(theApp.input)
912 return theApp.input->readDevices();
913 return false;
914 }
915
systemReadJoypad(int which)916 u32 systemReadJoypad(int which)
917 {
918 if(theApp.input)
919 return theApp.input->readDevice(which);
920 return 0;
921 }
922
923 static u8 sensorDarkness = 0xE8; // total darkness (including daylight on rainy days)
924
925 // TODO: implement
systemCartridgeRumble(bool)926 void systemCartridgeRumble(bool) { }
systemPossibleCartridgeRumble(bool)927 void systemPossibleCartridgeRumble(bool) { }
updateRumbleFrame()928 void updateRumbleFrame() { }
systemGetSensorZ()929 int systemGetSensorZ() { return 0; }
930
systemGetSensorDarkness()931 u8 systemGetSensorDarkness()
932 {
933 return sensorDarkness;
934 }
935
systemDrawScreen()936 void systemDrawScreen()
937 {
938 if(theApp.display == NULL)
939 return;
940
941 renderedFrames++;
942
943 if(theApp.updateCount) {
944 POSITION pos = theApp.updateList.GetHeadPosition();
945 while(pos) {
946 IUpdateListener *up = theApp.updateList.GetNext(pos);
947 up->update();
948 }
949 }
950
951 if (Sm60FPS_CanSkipFrame())
952 return;
953
954 if( aviRecording ) {
955 if (theApp.painting) {
956 theApp.skipAudioFrames++;
957 } else {
958 unsigned char *bmp;
959 unsigned short srcPitch = sizeX * ( systemColorDepth >> 3 ) + 4;
960 switch( systemColorDepth )
961 {
962 case 16:
963 bmp = new unsigned char[ sizeX * sizeY * 2 ];
964 cpyImg16bmp( bmp, pix + srcPitch, srcPitch, sizeX, sizeY );
965 break;
966 case 32:
967 // use 24 bit colors to reduce video size
968 bmp = new unsigned char[ sizeX * sizeY * 3 ];
969 cpyImg32bmp( bmp, pix + srcPitch, srcPitch, sizeX, sizeY );
970 break;
971 }
972 if( false == theApp.aviRecorder->AddVideoFrame( bmp ) ) {
973 systemMessage( IDS_AVI_CANNOT_WRITE_VIDEO, "Cannot write video frame to AVI file." );
974 delete theApp.aviRecorder;
975 theApp.aviRecorder = NULL;
976 aviRecording = false;
977 }
978 delete [] bmp;
979 }
980 }
981
982 if( theApp.ifbFunction ) {
983 theApp.ifbFunction( pix + (filterWidth * (systemColorDepth>>3)) + 4,
984 (filterWidth * (systemColorDepth>>3)) + 4,
985 filterWidth, filterHeight );
986 }
987
988 if(!soundBufferLow)
989 {
990 theApp.display->render();
991 Sm60FPS_Sleep();
992 }
993 else
994 soundBufferLow = false;
995
996 }
997
systemScreenCapture(int captureNumber)998 void systemScreenCapture(int captureNumber)
999 {
1000 if(theApp.m_pMainWnd)
1001 ((MainWnd *)theApp.m_pMainWnd)->screenCapture(captureNumber);
1002 }
1003
systemGetClock()1004 u32 systemGetClock()
1005 {
1006 return GetTickCount();
1007 }
1008
systemMessage(int number,const char * defaultMsg,...)1009 void systemMessage(int number, const char *defaultMsg, ...)
1010 {
1011 CString buffer;
1012 va_list valist;
1013 CString msg = defaultMsg;
1014 if(number)
1015 msg = winResLoadString(number);
1016
1017 va_start(valist, defaultMsg);
1018 buffer.FormatV(msg, valist);
1019
1020 CWnd *win = AfxGetApp()->GetMainWnd();
1021 if (win)
1022 win = win->GetLastActivePopup(); // possible modal dialog
1023 if (!win)
1024 win = AfxGetApp()->m_pMainWnd;
1025 win->MessageBox(buffer, winResLoadString(IDS_ERROR), MB_OK|MB_ICONERROR);
1026
1027 va_end(valist);
1028 }
1029
systemSetTitle(const char * title)1030 void systemSetTitle(const char *title)
1031 {
1032 if(theApp.m_pMainWnd != NULL) {
1033 AfxGetApp()->m_pMainWnd->SetWindowText(title);
1034 }
1035 }
1036
systemShowSpeed(int speed)1037 void systemShowSpeed(int speed)
1038 {
1039 systemSpeed = speed;
1040 showRenderedFrames = renderedFrames;
1041 renderedFrames = 0;
1042 if(videoOption <= VIDEO_6X && showSpeed) {
1043 CString buffer;
1044 if(showSpeed == 1)
1045 buffer.Format(VBA_NAME_AND_SUBVERSION "-%3d%%", systemSpeed);
1046 else
1047 buffer.Format(VBA_NAME_AND_SUBVERSION "-%3d%%(%d, %d fps)", systemSpeed,
1048 systemFrameSkip,
1049 showRenderedFrames);
1050
1051 systemSetTitle(buffer);
1052 }
1053 }
1054
1055
systemFrame()1056 void systemFrame()
1057 {
1058 if( movieRecording || moviePlaying ) {
1059 movieFrame++;
1060 }
1061
1062 #ifdef LOG_PERFORMANCE
1063 systemSpeedTable[systemSpeedCounter++ % PERFORMANCE_INTERVAL] = systemSpeed;
1064 #endif
1065 }
1066
1067
system10Frames(int rate)1068 void system10Frames(int rate)
1069 {
1070
1071 if( autoFrameSkip )
1072 {
1073 u32 time = systemGetClock();
1074 u32 diff = time - autoFrameSkipLastTime;
1075 autoFrameSkipLastTime = time;
1076 if( diff ) {
1077 // countermeasure against div/0 when debugging
1078 Sm60FPS::nCurSpeed = (1000000/rate)/diff;
1079 } else {
1080 Sm60FPS::nCurSpeed = 100;
1081 }
1082 }
1083
1084
1085 if(theApp.rewindMemory) {
1086 if(++rewindCounter >= (rewindTimer)) {
1087 rewindSaveNeeded = true;
1088 rewindCounter = 0;
1089 }
1090 }
1091 if(systemSaveUpdateCounter) {
1092 if(--systemSaveUpdateCounter <= SYSTEM_SAVE_NOT_UPDATED) {
1093 ((MainWnd *)theApp.m_pMainWnd)->writeBatteryFile();
1094 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
1095 }
1096 }
1097
1098 wasPaused = false;
1099
1100 // Old autoframeskip crap... might be useful later. autoframeskip Ifdef above might be useless as well now
1101 // autoFrameSkipLastTime = time;
1102
1103 #ifdef LOG_PERFORMANCE
1104 if( systemSpeedCounter >= PERFORMANCE_INTERVAL ) {
1105 // log performance every PERFORMANCE_INTERVAL frames
1106 float a = 0.0f;
1107 for( unsigned short i = 0 ; i < PERFORMANCE_INTERVAL ; i++ ) {
1108 a += (float)systemSpeedTable[i];
1109 }
1110 a /= (float)PERFORMANCE_INTERVAL;
1111 log( _T("Speed: %f\n"), a );
1112 systemSpeedCounter = 0;
1113 }
1114 #endif
1115 }
1116
systemScreenMessage(const char * msg)1117 void systemScreenMessage(const char *msg)
1118 {
1119 screenMessage = true;
1120 theApp.screenMessageTime = GetTickCount();
1121 theApp.screenMessageBuffer = msg;
1122
1123 if(theApp.screenMessageBuffer.GetLength() > 40)
1124 theApp.screenMessageBuffer = theApp.screenMessageBuffer.Left(40);
1125 }
1126
systemUpdateSolarSensor()1127 void systemUpdateSolarSensor()
1128 {
1129 u8 sun = 0x0; //sun = 0xE8 - 0xE8 (case 0 and default)
1130 int level = sunBars / 10;
1131 switch (level)
1132 {
1133 case 1:
1134 sun = 0xE8 - 0xE0;
1135 break;
1136 case 2:
1137 sun = 0xE8 - 0xDA;
1138 break;
1139 case 3:
1140 sun = 0xE8 - 0xD0;
1141 break;
1142 case 4:
1143 sun = 0xE8 - 0xC8;
1144 break;
1145 case 5:
1146 sun = 0xE8 - 0xC0;
1147 break;
1148 case 6:
1149 sun = 0xE8 - 0xB0;
1150 break;
1151 case 7:
1152 sun = 0xE8 - 0xA0;
1153 break;
1154 case 8:
1155 sun = 0xE8 - 0x88;
1156 break;
1157 case 9:
1158 sun = 0xE8 - 0x70;
1159 break;
1160 case 10:
1161 sun = 0xE8 - 0x50;
1162 break;
1163 default:
1164 break;
1165 }
1166 struct tm *newtime;
1167 time_t long_time;
1168 // regardless of the weather, there should be no sun at night time!
1169 time(&long_time); // Get time as long integer.
1170 newtime = localtime(&long_time); // Convert to local time.
1171 if (newtime->tm_hour > 21 || newtime->tm_hour < 5)
1172 {
1173 sun = 0; // total darkness, 9pm - 5am
1174 }
1175 else if (newtime->tm_hour > 20 || newtime->tm_hour < 6)
1176 {
1177 sun /= 9; // almost total darkness 8pm-9pm, 5am-6am
1178 }
1179 else if (newtime->tm_hour > 18 || newtime->tm_hour < 7)
1180 {
1181 sun >>= 1;
1182 }
1183 sensorDarkness = 0xE8 - sun;
1184 }
1185
systemUpdateMotionSensor()1186 void systemUpdateMotionSensor()
1187 {
1188 if(theApp.input)
1189 theApp.input->checkMotionKeys();
1190
1191 systemUpdateSolarSensor();
1192 }
1193
systemGetSensorX()1194 int systemGetSensorX()
1195 {
1196 return sensorX;
1197 }
1198
systemGetSensorY()1199 int systemGetSensorY()
1200 {
1201 return sensorY;
1202 }
1203
1204
systemSoundInit()1205 SoundDriver * systemSoundInit()
1206 {
1207 SoundDriver * drv = 0;
1208 soundShutdown();
1209
1210 switch( theApp.audioAPI )
1211 {
1212 case DIRECTSOUND:
1213 drv = newDirectSound();
1214 break;
1215 #ifndef NO_OAL
1216 case OPENAL_SOUND:
1217 drv = newOpenAL();
1218 break;
1219 #endif
1220 #ifndef NO_XAUDIO2
1221 case XAUDIO2:
1222 drv = newXAudio2_Output();
1223 break;
1224 #endif
1225 }
1226
1227 if( drv ) {
1228 if (throttle)
1229 drv->setThrottle( throttle );
1230 }
1231
1232 return drv;
1233 }
1234
1235
systemOnSoundShutdown()1236 void systemOnSoundShutdown()
1237 {
1238 if( theApp.aviRecorder ) {
1239 delete theApp.aviRecorder;
1240 theApp.aviRecorder = NULL;
1241 }
1242 aviRecording = false;
1243
1244
1245 if( theApp.soundRecorder ) {
1246 delete theApp.soundRecorder;
1247 theApp.soundRecorder = NULL;
1248 }
1249 soundRecording = false;
1250 }
1251
systemOnWriteDataToSoundBuffer(const u16 * finalWave,int length)1252 void systemOnWriteDataToSoundBuffer(const u16 * finalWave, int length)
1253 {
1254 if( soundRecording ) {
1255 if( theApp.soundRecorder ) {
1256 theApp.soundRecorder->AddSound( (const u8 *)finalWave, length );
1257 } else {
1258 WAVEFORMATEX format;
1259 format.cbSize = 0;
1260 format.wFormatTag = WAVE_FORMAT_PCM;
1261 format.nChannels = 2;
1262 format.nSamplesPerSec = soundGetSampleRate();
1263 format.wBitsPerSample = 16;
1264 format.nBlockAlign = format.nChannels * ( format.wBitsPerSample >> 3 );
1265 format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
1266 theApp.soundRecorder = new WavWriter;
1267 if( theApp.soundRecorder->Open( theApp.soundRecordName ) ) {
1268 theApp.soundRecorder->SetFormat( &format );
1269 }
1270 }
1271 }
1272
1273 if( aviRecording && theApp.aviRecorder ) {
1274 if( theApp.skipAudioFrames ) {
1275 theApp.skipAudioFrames--;
1276 } else {
1277 if( false == theApp.aviRecorder->AddAudioFrame( ( u8 *)finalWave ) ) {
1278 systemMessage( IDS_AVI_CANNOT_WRITE_AUDIO, "Cannot write audio frame to AVI file." );
1279 delete theApp.aviRecorder;
1280 theApp.aviRecorder = NULL;
1281 aviRecording = false;
1282 }
1283 }
1284 }
1285 }
1286
systemCanChangeSoundQuality()1287 bool systemCanChangeSoundQuality()
1288 {
1289 return true;
1290 }
1291
systemPauseOnFrame()1292 bool systemPauseOnFrame()
1293 {
1294 if(winPauseNextFrame) {
1295 paused = true;
1296 winPauseNextFrame = false;
1297 return true;
1298 }
1299 return false;
1300 }
1301
systemGbBorderOn()1302 void systemGbBorderOn()
1303 {
1304 if(emulating && theApp.cartridgeType == IMAGE_GB && gbBorderOn) {
1305 theApp.updateWindowSize(videoOption);
1306 }
1307 }
1308
OnIdle(LONG lCount)1309 BOOL VBA::OnIdle(LONG lCount)
1310 {
1311 if(emulating && debugger) {
1312 MSG msg;
1313 remoteStubMain();
1314 if(debugger)
1315 return TRUE; // continue loop
1316 return !::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE);
1317 } else if(emulating && active && !paused) {
1318 emulator.emuMain(emulator.emuCount);
1319
1320 if(rewindSaveNeeded && rewindMemory && emulator.emuWriteMemState) {
1321 rewindCount++;
1322 if(rewindCount > 8)
1323 rewindCount = 8;
1324 long resize;
1325 if(emulator.emuWriteMemState(&rewindMemory[rewindPos*REWIND_SIZE],
1326 REWIND_SIZE, resize)) { /* available and actual size */
1327 rewindPos = ++rewindPos & 7;
1328 if(rewindCount == 8)
1329 rewindTopPos = ++rewindTopPos & 7;
1330 }
1331 }
1332
1333 rewindSaveNeeded = false;
1334
1335 if(mouseCounter) {
1336 if(--mouseCounter == 0) {
1337 SetCursor(NULL);
1338 }
1339 }
1340 return TRUE;
1341 }
1342 return FALSE;
1343
1344 // return CWinApp::OnIdle(lCount);
1345 }
1346
addRecentFile(CString file)1347 void VBA::addRecentFile(CString file)
1348 {
1349 // Do not change recent list if frozen
1350 if(recentFreeze)
1351 return;
1352 int i = 0;
1353 for(i = 0; i < 10; i++) {
1354 if(recentFiles[i].GetLength() == 0)
1355 break;
1356
1357 if(recentFiles[i].Compare(file) == 0) {
1358 if(i == 0)
1359 return;
1360 CString p = recentFiles[i];
1361 for(int j = i; j > 0; j--) {
1362 recentFiles[j] = recentFiles[j-1];
1363 }
1364 recentFiles[0] = p;
1365 return;
1366 }
1367 }
1368 int num = 0;
1369 for(i = 0; i < 10; i++) {
1370 if(recentFiles[i].GetLength() != 0)
1371 num++;
1372 }
1373 if(num == 10) {
1374 num--;
1375 }
1376
1377 for(i = num; i >= 1; i--) {
1378 recentFiles[i] = recentFiles[i-1];
1379 }
1380 recentFiles[0] = file;
1381 }
1382
loadSettings()1383 void VBA::loadSettings()
1384 {
1385 CString buffer;
1386
1387 lastFullscreen = (VIDEO_SIZE)regQueryDwordValue("lastFullscreen", VIDEO_1024x768);
1388
1389 languageOption = regQueryDwordValue("language", 1);
1390 if(languageOption < 0 || languageOption > 2)
1391 languageOption = 1;
1392
1393 buffer = regQueryStringValue("languageName", "");
1394 if(!buffer.IsEmpty()) {
1395 languageName = buffer.Left(3);
1396 } else
1397 languageName = "";
1398
1399 winSetLanguageOption(languageOption, true);
1400
1401 frameSkip = regQueryDwordValue("frameSkip", 0);
1402 if(frameSkip < 0 || frameSkip > 9)
1403 frameSkip = 0;
1404
1405 gbFrameSkip = regQueryDwordValue("gbFrameSkip", 0);
1406 if(gbFrameSkip < 0 || gbFrameSkip > 9)
1407 gbFrameSkip = 0;
1408
1409 autoFrameSkip = regQueryDwordValue("autoFrameSkip", FALSE) ? TRUE : FALSE;
1410
1411 vsync = regQueryDwordValue("vsync", false) ? true : false ;
1412 fullScreenStretch = regQueryDwordValue("stretch", 0) ? true : false;
1413
1414 videoOption = regQueryDwordValue("video", VIDEO_3X);
1415
1416 strcpy(pluginName, regQueryStringValue("pluginName", ""));
1417
1418 if(videoOption < VIDEO_1X || videoOption > VIDEO_OTHER)
1419 videoOption = VIDEO_3X;
1420
1421 fsAdapter = regQueryDwordValue("fsAdapter", 0);
1422 fsWidth = regQueryDwordValue("fsWidth", 800);
1423 fsHeight = regQueryDwordValue("fsHeight", 600);
1424 fsColorDepth = regQueryDwordValue("fsColorDepth", 32);
1425 fsFrequency = regQueryDwordValue("fsFrequency", 60);
1426
1427 if(videoOption == VIDEO_OTHER) {
1428 if(fsWidth < 0 || fsWidth > 4095 || fsHeight < 0 || fsHeight > 4095)
1429 videoOption = 0;
1430 if(fsColorDepth != 16 && fsColorDepth != 24 && fsColorDepth != 32)
1431 videoOption = 0;
1432 }
1433
1434 renderMethod = (DISPLAY_TYPE)regQueryDwordValue("renderMethod", DIRECT_3D);
1435 #ifdef NO_OGL
1436 if( renderMethod == OPENGL ) {
1437 renderMethod = DIRECT_3D;
1438 }
1439 #endif
1440 #ifdef NO_D3D
1441 if( renderMethod == DIRECT_3D ) {
1442 renderMethod = OPENGL;
1443 }
1444 #endif
1445 #ifndef NO_XAUDIO2
1446 audioAPI = (AUDIO_API)regQueryDwordValue( "audioAPI", XAUDIO2 );
1447 #else
1448 audioAPI = (AUDIO_API)regQueryDwordValue( "audioAPI", DIRECTSOUND );
1449 #endif
1450 if( ( audioAPI != DIRECTSOUND )
1451 #ifndef NO_OAL
1452 && ( audioAPI != OPENAL_SOUND )
1453 #endif
1454 #ifndef NO_XAUDIO2
1455 && ( audioAPI != XAUDIO2 )
1456 #endif
1457 ) {
1458 #ifndef NO_XAUDIO2
1459 audioAPI = XAUDIO2;
1460 #else
1461 audioAPI = DIRECTSOUND;
1462 #endif
1463 }
1464
1465 windowPositionX = regQueryDwordValue("windowX", 0);
1466 if(windowPositionX < 0)
1467 windowPositionX = 0;
1468 windowPositionY = regQueryDwordValue("windowY", 0);
1469 if(windowPositionY < 0)
1470 windowPositionY = 0;
1471
1472 maxCpuCores = regQueryDwordValue("maxCpuCores", 0);
1473 if(maxCpuCores == 0) {
1474 maxCpuCores = detectCpuCores();
1475 }
1476
1477 useBiosFileGBA = ( regQueryDwordValue("useBiosGBA", 0) == 1 ) ? true : false;
1478
1479 useBiosFileGBC = ( regQueryDwordValue("useBiosGBC", 0) == 1 ) ? true : false;
1480
1481 useBiosFileGB = ( regQueryDwordValue("useBiosGB", 0) == 1 ) ? true : false;
1482
1483 skipBios = regQueryDwordValue("skipBios", 0) ? true : false;
1484
1485 buffer = regQueryStringValue("biosFileGBA", "");
1486
1487 if(!buffer.IsEmpty()) {
1488 biosFileNameGBA = buffer;
1489 }
1490
1491 buffer = regQueryStringValue("biosFileGBC", "");
1492
1493 if(!buffer.IsEmpty()) {
1494 biosFileNameGBC = buffer;
1495 }
1496
1497 buffer = regQueryStringValue("biosFileGB", "");
1498
1499 if(!buffer.IsEmpty()) {
1500 biosFileNameGB = buffer;
1501 }
1502
1503 int res = regQueryDwordValue("soundEnable", 0x30f);
1504 soundSetEnable(res);
1505
1506 long soundQuality = regQueryDwordValue("soundQuality", 1);
1507 soundSetSampleRate(44100 / soundQuality);
1508
1509 soundSetVolume( (float)(regQueryDwordValue("soundVolume", 100)) / 100.0f );
1510
1511 gb_effects_config.enabled = 1 == regQueryDwordValue( "gbSoundEffectsEnabled", 0 );
1512 gb_effects_config.surround = 1 == regQueryDwordValue( "gbSoundEffectsSurround", 0 );
1513 gb_effects_config.echo = (float)regQueryDwordValue( "gbSoundEffectsEcho", 20 ) / 100.0f;
1514 gb_effects_config.stereo = (float)regQueryDwordValue( "gbSoundEffectsStereo", 15 ) / 100.0f;
1515
1516 gbSoundSetDeclicking( 1 == regQueryDwordValue( "gbSoundDeclicking", 1 ) );
1517
1518 soundInterpolation = 1 == regQueryDwordValue( "gbaSoundInterpolation", 1 );
1519 soundFiltering = (float)regQueryDwordValue( "gbaSoundFiltering", 50 ) / 100.0f;
1520
1521 tripleBuffering = regQueryDwordValue("tripleBuffering", false) ? true : false;
1522
1523 #ifndef NO_D3D
1524 d3dFilter = regQueryDwordValue("d3dFilter", 1);
1525 if(d3dFilter < 0 || d3dFilter > 1)
1526 d3dFilter = 1;
1527
1528 d3dMotionBlur = ( regQueryDwordValue("d3dMotionBlur", 0) == 1 ) ? true : false;
1529 #endif
1530
1531 glFilter = regQueryDwordValue("glFilter", 1);
1532 if(glFilter < 0 || glFilter > 1)
1533 glFilter = 1;
1534
1535
1536 filter = regQueryDwordValue("filter", 0);
1537 if(filter < FILTER_NONE || filter > FILTER_LAST)
1538 filter = FILTER_NONE;
1539
1540 filterMT = ( 1 == regQueryDwordValue("filterEnableMultiThreading", 0) );
1541
1542 disableMMX = regQueryDwordValue("disableMMX", false) ? true: false;
1543
1544 disableStatusMessages = regQueryDwordValue("disableStatus", 0) ? true : false;
1545
1546 showSpeed = regQueryDwordValue("showSpeed", 0);
1547 if(showSpeed < 0 || showSpeed > 2)
1548 showSpeed = 0;
1549
1550 showSpeedTransparent = regQueryDwordValue("showSpeedTransparent", TRUE) ?
1551 TRUE : FALSE;
1552
1553 winGbPrinterEnabled = regQueryDwordValue("gbPrinter", false) ? true : false;
1554
1555 if(winGbPrinterEnabled)
1556 gbSerialFunction = gbPrinterSend;
1557 else
1558 #ifndef NO_LINK
1559 gbSerialFunction = gbStartLink;
1560 #else
1561 gbSerialFunction = NULL;
1562 #endif
1563
1564 pauseWhenInactive = regQueryDwordValue("pauseWhenInactive", 1) ?
1565 true : false;
1566 captureFormat = regQueryDwordValue("captureFormat", 0);
1567
1568 recentFreeze = regQueryDwordValue("recentFreeze", false) ? true : false;
1569
1570 autoPatch = regQueryDwordValue("autoPatch", 1) == 1 ? true : false;
1571
1572 cpuDisableSfx = regQueryDwordValue("disableSfx", 0) ? true : false;
1573
1574 cpuSaveType = regQueryDwordValue("saveType", 0);
1575 if(cpuSaveType < 0 || cpuSaveType > 5)
1576 cpuSaveType = 0;
1577
1578 ifbType = (IFBFilter)regQueryDwordValue("ifbType", 0);
1579 if(ifbType < 0 || ifbType > 2)
1580 ifbType = kIFBNone;
1581
1582 winFlashSize = regQueryDwordValue("flashSize", 0x10000);
1583 if(winFlashSize != 0x10000 && winFlashSize != 0x20000)
1584 winFlashSize = 0x10000;
1585
1586 agbPrintEnable(regQueryDwordValue("agbPrint", 0) ? true : false);
1587
1588 rtcEnabled = regQueryDwordValue("rtcEnabled", 0) ? true : false;
1589 rtcEnable(rtcEnabled);
1590
1591 switch(videoOption) {
1592 case VIDEO_320x240:
1593 fsWidth = 320;
1594 fsHeight = 240;
1595 fsColorDepth = 16;
1596 fsFrequency = 60;
1597 break;
1598 case VIDEO_640x480:
1599 fsWidth = 640;
1600 fsHeight = 480;
1601 fsColorDepth = 16;
1602 fsFrequency = 60;
1603 break;
1604 case VIDEO_800x600:
1605 fsWidth = 800;
1606 fsHeight = 600;
1607 fsColorDepth = 16;
1608 fsFrequency = 60;
1609 break;
1610 case VIDEO_1024x768:
1611 fsWidth = 1024;
1612 fsHeight = 768;
1613 fsColorDepth = 16;
1614 fsFrequency = 60;
1615 break;
1616 case VIDEO_1280x1024:
1617 fsWidth = 1280;
1618 fsHeight = 1024;
1619 fsColorDepth = 16;
1620 fsFrequency = 60;
1621 break;
1622 }
1623
1624 winGbBorderOn = regQueryDwordValue("borderOn", 0);
1625 gbBorderAutomatic = regQueryDwordValue("borderAutomatic", 0);
1626 gbEmulatorType = regQueryDwordValue("emulatorType", 1);
1627 if(gbEmulatorType < 0 || gbEmulatorType > 5)
1628 gbEmulatorType = 1;
1629 gbColorOption = regQueryDwordValue("colorOption", 0);
1630
1631 threadPriority = regQueryDwordValue("priority", 2);
1632
1633 if(threadPriority < 0 || threadPriority >3)
1634 threadPriority = 2;
1635 updatePriority();
1636
1637 autoSaveLoadCheatList = ( 1 == regQueryDwordValue( "autoSaveCheatList", 1 ) ) ? true : false;
1638
1639 gbPaletteOption = regQueryDwordValue("gbPaletteOption", 0);
1640 if(gbPaletteOption < 0)
1641 gbPaletteOption = 0;
1642 if(gbPaletteOption > 2)
1643 gbPaletteOption = 2;
1644
1645 regQueryBinaryValue("gbPalette", (char *)systemGbPalette,
1646 24*sizeof(u16));
1647
1648 rewindTimer = regQueryDwordValue("rewindTimer", 0);
1649
1650 if(rewindTimer < 0 || rewindTimer > 600)
1651 rewindTimer = 0;
1652
1653 rewindTimer *= 6; // convert to 10 frames multiple
1654
1655 if(rewindTimer != 0)
1656 rewindMemory = (char *)malloc(8*REWIND_SIZE);
1657
1658 for(int i = 0; i < 10; i++) {
1659 buffer.Format("recent%d", i);
1660 char *s = regQueryStringValue(buffer, NULL);
1661 if(s == NULL)
1662 break;
1663 recentFiles[i] = s;
1664 }
1665
1666 joypadDefault = regQueryDwordValue("joypadDefault", 0);
1667 if(joypadDefault < 0 || joypadDefault > 3)
1668 joypadDefault = 0;
1669
1670 autoLoadMostRecent = ( 1 == regQueryDwordValue("autoLoadMostRecent", 0) ) ? true : false;
1671
1672 skipSaveGameBattery = ( 1 == regQueryDwordValue("skipSaveGameBattery", 0) ) ? true : false;
1673
1674 skipSaveGameCheats = ( 1 == regQueryDwordValue("skipSaveGameCheats", 0) ) ? true : false;
1675
1676 cheatsEnabled = regQueryDwordValue("cheatsEnabled", false) ? true : false;
1677
1678 maxScale = regQueryDwordValue("maxScale", 0);
1679
1680 updateThrottle( (unsigned short)regQueryDwordValue( "throttle", 0 ) );
1681
1682 #ifndef NO_LINK
1683 linkTimeout = regQueryDwordValue("LinkTimeout", 1);
1684
1685 linkMode = regQueryDwordValue("LinkMode", LINK_DISCONNECTED);
1686
1687 linkHostAddr = regQueryStringValue("LinkHostAddr", "localhost");
1688
1689 linkAuto = regQueryDwordValue("LinkAuto", true);
1690
1691 linkHacks = regQueryDwordValue("LinkHacks", false);
1692
1693 linkNumPlayers = regQueryDwordValue("LinkNumPlayers", 2);
1694 #endif
1695
1696 gdbPort = regQueryDwordValue("gdbPort", 55555);
1697 gdbBreakOnLoad = regQueryDwordValue("gdbBreakOnLoad", false) ? true : false;
1698
1699 Sm60FPS::bSaveMoreCPU = regQueryDwordValue("saveMoreCPU", 0);
1700
1701 #ifndef NO_OAL
1702 buffer = regQueryStringValue( "oalDevice", "Generic Software" );
1703 if( oalDevice ) {
1704 free( oalDevice );
1705 }
1706 oalDevice = (TCHAR*)malloc( ( buffer.GetLength() + 1 ) * sizeof( TCHAR ) );
1707 _tcscpy( oalDevice, buffer.GetBuffer() );
1708
1709 oalBufferCount = regQueryDwordValue( "oalBufferCount", 5 );
1710 #endif
1711
1712 #ifndef NO_XAUDIO2
1713 xa2Device = regQueryDwordValue( "xa2Device", 0 );
1714 xa2BufferCount = regQueryDwordValue( "xa2BufferCount", 4 );
1715 xa2Upmixing = ( 1 == regQueryDwordValue( "xa2Upmixing", 0 ) );
1716 #endif
1717
1718 if( ( maxCpuCores == 1 ) && filterMT ) {
1719 // multi-threading use useless for just one core
1720 filterMT = false;
1721 }
1722 }
1723
updateFrameSkip()1724 void VBA::updateFrameSkip()
1725 {
1726 switch(cartridgeType) {
1727 case 0:
1728 systemFrameSkip = frameSkip;
1729 break;
1730 case 1:
1731 systemFrameSkip = gbFrameSkip;
1732 break;
1733 }
1734 }
1735
updateVideoSize(UINT id)1736 void VBA::updateVideoSize(UINT id)
1737 {
1738 int value = 0;
1739
1740 switch(id) {
1741 case ID_OPTIONS_VIDEO_X1:
1742 value = VIDEO_1X;
1743 break;
1744 case ID_OPTIONS_VIDEO_X2:
1745 value = VIDEO_2X;
1746 break;
1747 case ID_OPTIONS_VIDEO_X3:
1748 value = VIDEO_3X;
1749 break;
1750 case ID_OPTIONS_VIDEO_X4:
1751 value = VIDEO_4X;
1752 break;
1753 case ID_OPTIONS_VIDEO_X5:
1754 value = VIDEO_5X;
1755 break;
1756 case ID_OPTIONS_VIDEO_X6:
1757 value = VIDEO_6X;
1758 break;
1759 case ID_OPTIONS_VIDEO_FULLSCREEN320X240:
1760 value = VIDEO_320x240;
1761 fsWidth = 320;
1762 fsHeight = 240;
1763 fsColorDepth = 16;
1764 break;
1765 case ID_OPTIONS_VIDEO_FULLSCREEN640X480:
1766 value = VIDEO_640x480;
1767 fsWidth = 640;
1768 fsHeight = 480;
1769 fsColorDepth = 16;
1770 break;
1771 case ID_OPTIONS_VIDEO_FULLSCREEN800X600:
1772 value = VIDEO_800x600;
1773 fsWidth = 800;
1774 fsHeight = 600;
1775 fsColorDepth = 16;
1776 break;
1777 case ID_OPTIONS_VIDEO_FULLSCREEN1024X768:
1778 value = VIDEO_1024x768;
1779 fsWidth = 1024;
1780 fsHeight = 768;
1781 fsColorDepth = 32;
1782 break;
1783 case ID_OPTIONS_VIDEO_FULLSCREEN1280X1024:
1784 value = VIDEO_1280x1024;
1785 fsWidth = 1280;
1786 fsHeight = 1024;
1787 fsColorDepth = 32;
1788 break;
1789 case ID_OPTIONS_VIDEO_FULLSCREEN:
1790 value = VIDEO_OTHER;
1791 break;
1792 }
1793
1794 updateWindowSize(value);
1795 }
1796
1797
updateWindowSize(int value)1798 void VBA::updateWindowSize(int value)
1799 {
1800 regSetDwordValue("video", value);
1801
1802 if(value == VIDEO_OTHER) {
1803 regSetDwordValue("fsWidth", fsWidth);
1804 regSetDwordValue("fsHeight", fsHeight);
1805 regSetDwordValue("fsColorDepth", fsColorDepth);
1806 }
1807
1808 if(((value >= VIDEO_320x240) &&
1809 (videoOption != value)) ||
1810 (videoOption >= VIDEO_320x240 &&
1811 value <= VIDEO_6X) ||
1812 fsForceChange) {
1813 fsForceChange = false;
1814 changingVideoSize = true;
1815 if( videoOption <= VIDEO_6X ) {
1816 lastWindowed = (VIDEO_SIZE)videoOption; // save for when leaving full screen
1817 } else {
1818 lastFullscreen = (VIDEO_SIZE)videoOption; // save for when using quick switch to fullscreen
1819 }
1820 shutdownDisplay();
1821 if(input) {
1822 delete input;
1823 input = NULL;
1824 }
1825 m_pMainWnd->DragAcceptFiles(FALSE);
1826 CWnd *pWnd = m_pMainWnd;
1827 m_pMainWnd = NULL;
1828 pWnd->DestroyWindow();
1829 delete pWnd;
1830 videoOption = value;
1831 if(!initDisplay()) {
1832 if(videoOption == VIDEO_320x240 ||
1833 videoOption == VIDEO_640x480 ||
1834 videoOption == VIDEO_800x600 ||
1835 videoOption == VIDEO_1024x768 ||
1836 videoOption == VIDEO_1280x1024 ||
1837 videoOption == VIDEO_OTHER) {
1838 regSetDwordValue("video", VIDEO_1X);
1839 }
1840 changingVideoSize = false;
1841 AfxPostQuitMessage(0);
1842 return;
1843 }
1844 if(!initInput()) {
1845 changingVideoSize = false;
1846 AfxPostQuitMessage(0);
1847 return;
1848 }
1849 input->checkKeys();
1850
1851
1852 changingVideoSize = FALSE;
1853 updateWindowSize(videoOption);
1854 return;
1855 }
1856
1857 sizeX = 240;
1858 sizeY = 160;
1859
1860 videoOption = value;
1861
1862 if(cartridgeType == IMAGE_GB) {
1863 if(gbBorderOn) {
1864 sizeX = 256;
1865 sizeY = 224;
1866 gbBorderLineSkip = 256;
1867 gbBorderColumnSkip = 48;
1868 gbBorderRowSkip = 40;
1869 } else {
1870 sizeX = 160;
1871 sizeY = 144;
1872 gbBorderLineSkip = 160;
1873 gbBorderColumnSkip = 0;
1874 gbBorderRowSkip = 0;
1875 }
1876 }
1877
1878 surfaceSizeX = sizeX;
1879 surfaceSizeY = sizeY;
1880
1881 switch(videoOption) {
1882 case VIDEO_1X:
1883 surfaceSizeX = sizeX;
1884 surfaceSizeY = sizeY;
1885 break;
1886 case VIDEO_2X:
1887 surfaceSizeX = sizeX * 2;
1888 surfaceSizeY = sizeY * 2;
1889 break;
1890 case VIDEO_3X:
1891 surfaceSizeX = sizeX * 3;
1892 surfaceSizeY = sizeY * 3;
1893 break;
1894 case VIDEO_4X:
1895 surfaceSizeX = sizeX * 4;
1896 surfaceSizeY = sizeY * 4;
1897 break;
1898 case VIDEO_5X:
1899 surfaceSizeX = sizeX * 5;
1900 surfaceSizeY = sizeY * 5;
1901 break;
1902 case VIDEO_6X:
1903 surfaceSizeX = sizeX * 6;
1904 surfaceSizeY = sizeY * 6;
1905 break;
1906 case VIDEO_320x240:
1907 case VIDEO_640x480:
1908 case VIDEO_800x600:
1909 case VIDEO_1024x768:
1910 case VIDEO_1280x1024:
1911 case VIDEO_OTHER:
1912 {
1913 int scaleX = 1;
1914 int scaleY = 1;
1915 scaleX = (fsWidth / sizeX);
1916 scaleY = (fsHeight / sizeY);
1917 int min = scaleX < scaleY ? scaleX : scaleY;
1918 if(maxScale)
1919 min = min > maxScale ? maxScale : min;
1920 surfaceSizeX = min * sizeX;
1921 surfaceSizeY = min * sizeY;
1922 if((fullScreenStretch && (display != NULL &&
1923 (display->getType() != DIRECT_3D)))
1924 || (display != NULL && display->getType() >= DIRECT_3D)) {
1925 surfaceSizeX = fsWidth;
1926 surfaceSizeY = fsHeight;
1927 }
1928 }
1929 break;
1930 }
1931
1932 rect.right = sizeX;
1933 rect.bottom = sizeY;
1934
1935 int winSizeX = sizeX;
1936 int winSizeY = sizeY;
1937
1938 if(videoOption <= VIDEO_6X) {
1939 dest.left = 0;
1940 dest.top = 0;
1941 dest.right = surfaceSizeX;
1942 dest.bottom = surfaceSizeY;
1943
1944 DWORD style = WS_POPUP | WS_VISIBLE;
1945
1946 style |= WS_OVERLAPPEDWINDOW;
1947
1948 AdjustWindowRectEx(&dest, style, TRUE, 0); //WS_EX_TOPMOST);
1949
1950 winSizeX = dest.right-dest.left;
1951 winSizeY = dest.bottom-dest.top;
1952
1953 m_pMainWnd->SetWindowPos(0, //HWND_TOPMOST,
1954 windowPositionX,
1955 windowPositionY,
1956 winSizeX,
1957 winSizeY,
1958 SWP_NOMOVE | SWP_SHOWWINDOW);
1959
1960 // content of old seperate 'winCheckMenuBarInfo' function:
1961 MENUBARINFO info;
1962 info.cbSize = sizeof(MENUBARINFO);
1963 GetMenuBarInfo( theApp.m_pMainWnd->GetSafeHwnd(), OBJID_MENU, 0, &info );
1964 int menuHeight = GetSystemMetrics(SM_CYMENU); // includes white line
1965 if((info.rcBar.bottom - info.rcBar.top) > menuHeight) // check for double height menu
1966 {
1967 winSizeY += (info.rcBar.bottom - info.rcBar.top) - menuHeight + 1;
1968 m_pMainWnd->SetWindowPos(
1969 0, //HWND_TOPMOST,
1970 windowPositionX,
1971 windowPositionY,
1972 winSizeX,
1973 winSizeY,
1974 SWP_NOMOVE | SWP_SHOWWINDOW);
1975 }
1976 }
1977
1978 adjustDestRect();
1979
1980 updateIFB();
1981 updateFilter();
1982
1983 if(display)
1984 display->resize(theApp.dest.right-theApp.dest.left, theApp.dest.bottom-theApp.dest.top);
1985
1986 m_pMainWnd->RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
1987 }
1988
1989
initDisplay()1990 bool VBA::initDisplay()
1991 {
1992 return updateRenderMethod(false);
1993 }
1994
1995
preInitialize()1996 bool VBA::preInitialize()
1997 {
1998 switch( cartridgeType )
1999 {
2000 case IMAGE_GBA:
2001 sizeX = 240;
2002 sizeY = 160;
2003 break;
2004 case IMAGE_GB:
2005 if( gbBorderOn ) {
2006 sizeX = 256;
2007 sizeY = 224;
2008 } else {
2009 sizeX = 160;
2010 sizeY = 144;
2011 }
2012 break;
2013 }
2014
2015 switch( videoOption )
2016 {
2017 case VIDEO_1X:
2018 surfaceSizeX = sizeX;
2019 surfaceSizeY = sizeY;
2020 break;
2021 case VIDEO_2X:
2022 surfaceSizeX = sizeX * 2;
2023 surfaceSizeY = sizeY * 2;
2024 break;
2025 case VIDEO_3X:
2026 surfaceSizeX = sizeX * 3;
2027 surfaceSizeY = sizeY * 3;
2028 break;
2029 case VIDEO_4X:
2030 surfaceSizeX = sizeX * 4;
2031 surfaceSizeY = sizeY * 4;
2032 break;
2033 case VIDEO_5X:
2034 surfaceSizeX = sizeX * 5;
2035 surfaceSizeY = sizeY * 5;
2036 break;
2037 case VIDEO_6X:
2038 surfaceSizeX = sizeX * 6;
2039 surfaceSizeY = sizeY * 6;
2040 break;
2041 case VIDEO_320x240:
2042 case VIDEO_640x480:
2043 case VIDEO_800x600:
2044 case VIDEO_1024x768:
2045 case VIDEO_1280x1024:
2046 case VIDEO_OTHER:
2047 float scaleX = (float)fsWidth / sizeX;
2048 float scaleY = (float)fsHeight / sizeY;
2049 float min = ( scaleX < scaleY ) ? scaleX : scaleY;
2050 if( fullScreenStretch ) {
2051 surfaceSizeX = fsWidth;
2052 surfaceSizeY = fsHeight;
2053 } else {
2054 surfaceSizeX = (int)( sizeX * min );
2055 surfaceSizeY = (int)( sizeY * min );
2056 }
2057 break;
2058 }
2059
2060 rect.left = 0;
2061 rect.top = 0;
2062 rect.right = sizeX;
2063 rect.bottom = sizeY;
2064
2065 dest.left = 0;
2066 dest.top = 0;
2067 dest.right = surfaceSizeX;
2068 dest.bottom = surfaceSizeY;
2069
2070
2071 DWORD style = WS_POPUP | WS_VISIBLE;
2072 DWORD styleEx = 0;
2073
2074 if( videoOption <= VIDEO_6X ) {
2075 style |= WS_OVERLAPPEDWINDOW;
2076 } else {
2077 styleEx = 0;
2078 }
2079
2080 if( videoOption <= VIDEO_6X ) {
2081 AdjustWindowRectEx( &dest, style, TRUE, styleEx );
2082 } else {
2083 AdjustWindowRectEx( &dest, style, FALSE, styleEx );
2084 }
2085
2086 int winSizeX = dest.right-dest.left;
2087 int winSizeY = dest.bottom-dest.top;
2088
2089 if( videoOption > VIDEO_6X ) {
2090 winSizeX = fsWidth;
2091 winSizeY = fsHeight;
2092 }
2093
2094 int x = 0, y = 0;
2095
2096 if( videoOption <= VIDEO_6X ) {
2097 x = windowPositionX;
2098 y = windowPositionY;
2099 }
2100
2101
2102 // Create a window
2103 MainWnd *pWnd = new MainWnd;
2104 m_pMainWnd = pWnd;
2105
2106 pWnd->CreateEx(
2107 styleEx,
2108 wndClass,
2109 _T(VBA_NAME_AND_SUBVERSION),
2110 style,
2111 x, y,
2112 winSizeX, winSizeY,
2113 NULL,
2114 0
2115 );
2116
2117 if( !((HWND)*pWnd) ) {
2118 winlog( "Error creating Window %08x\n", GetLastError() );
2119 return false;
2120 }
2121 pWnd->DragAcceptFiles( TRUE );
2122 updateMenuBar();
2123 adjustDestRect();
2124
2125 return true;
2126 }
2127
2128
updateRenderMethod(bool force)2129 bool VBA::updateRenderMethod(bool force)
2130 {
2131 bool ret = true;
2132
2133 Sm60FPS_Init();
2134
2135 if( !updateRenderMethod0( force ) ) {
2136 // fall back to safe configuration
2137 renderMethod = DIRECT_3D;
2138 fsAdapter = 0;
2139 videoOption = VIDEO_1X;
2140 ret = updateRenderMethod( true );
2141 }
2142
2143 return ret;
2144 }
2145
2146
updateRenderMethod0(bool force)2147 bool VBA::updateRenderMethod0(bool force)
2148 {
2149 bool initInput = false;
2150 b16to32Video = false;
2151
2152 if(display) {
2153 if(display->getType() != renderMethod || force) {
2154 toolsLoggingClose(); // close log dialog
2155 initInput = true;
2156 changingVideoSize = true;
2157 shutdownDisplay();
2158 if(input) {
2159 delete input;
2160 input = NULL;
2161 }
2162 CWnd *pWnd = m_pMainWnd;
2163
2164 m_pMainWnd = NULL;
2165 pWnd->DragAcceptFiles(FALSE);
2166 pWnd->DestroyWindow();
2167 delete pWnd;
2168
2169 display = NULL;
2170 regSetDwordValue("renderMethod", renderMethod);
2171 }
2172 }
2173 if(display == NULL) {
2174 switch(renderMethod) {
2175 #ifndef NO_OGL
2176 case OPENGL:
2177 display = newOpenGLDisplay();
2178 break;
2179 #endif
2180 #ifndef NO_D3D
2181 case DIRECT_3D:
2182 display = newDirect3DDisplay();
2183 break;
2184 #endif
2185 }
2186
2187 if( preInitialize() ) {
2188 if( display->initialize() ) {
2189 if( initInput ) {
2190 if( !this->initInput() ) {
2191 changingVideoSize = false;
2192 AfxPostQuitMessage(0);
2193 return false;
2194 }
2195 input->checkKeys();
2196 updateMenuBar();
2197 changingVideoSize = false;
2198 updateWindowSize(videoOption);
2199
2200 m_pMainWnd->ShowWindow(SW_SHOW);
2201 m_pMainWnd->UpdateWindow();
2202 m_pMainWnd->SetFocus();
2203
2204 return true;
2205 } else {
2206 changingVideoSize = false;
2207 return true;
2208 }
2209 }
2210 }
2211 changingVideoSize = false;
2212 }
2213 return true;
2214 }
2215
2216
shutdownDisplay()2217 void VBA::shutdownDisplay()
2218 {
2219 if(display != NULL) {
2220 display->cleanup();
2221 delete display;
2222 display = NULL;
2223 }
2224 }
2225
directXMessage(const char * msg)2226 void VBA::directXMessage(const char *msg)
2227 {
2228 systemMessage(IDS_DIRECTX_7_REQUIRED,
2229 "DirectX 7.0 or greater is required to run.\nDownload at http://www.microsoft.com/directx.\n\nError found at: %s",
2230 msg);
2231 }
2232
updatePriority()2233 void VBA::updatePriority()
2234 {
2235 switch(threadPriority) {
2236 case 0:
2237 SetThreadPriority(THREAD_PRIORITY_HIGHEST);
2238 break;
2239 case 1:
2240 SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL);
2241 break;
2242 case 3:
2243 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
2244 break;
2245 default:
2246 SetThreadPriority(THREAD_PRIORITY_NORMAL);
2247 }
2248 }
2249
2250 #ifdef MMX
detectMMX()2251 bool VBA::detectMMX()
2252 {
2253 bool support = false;
2254 char brand[12]; // not zero terminated
2255
2256 // check for Intel chip
2257 __try {
2258 __asm {
2259 mov eax, 0;
2260 cpuid;
2261 mov [dword ptr brand+0], ebx;
2262 mov [dword ptr brand+4], edx;
2263 mov [dword ptr brand+8], ecx;
2264 }
2265 }
2266 __except(EXCEPTION_EXECUTE_HANDLER) {
2267 if(_exception_code() == STATUS_ILLEGAL_INSTRUCTION) {
2268 return false;
2269 }
2270 return false;
2271 }
2272 // Check for Intel or AMD CPUs
2273 if(strncmp(brand, "GenuineIntel", 12)) {
2274 if(strncmp(brand, "AuthenticAMD", 12)) {
2275 return false;
2276 }
2277 }
2278
2279 __asm {
2280 mov eax, 1;
2281 cpuid;
2282 test edx, 00800000h;
2283 jz NotFound;
2284 mov [support], 1;
2285 NotFound:
2286 }
2287 return support;
2288 }
2289 #endif
2290
winSetLanguageOption(int option,bool force)2291 void VBA::winSetLanguageOption(int option, bool force)
2292 {
2293 if(((option == languageOption) && option != 2) && !force)
2294 return;
2295 switch(option) {
2296 case 0:
2297 {
2298 char lbuffer[10];
2299
2300 if(GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SABBREVLANGNAME,
2301 lbuffer, 10)) {
2302 HINSTANCE l = winLoadLanguage(lbuffer);
2303 if(l == NULL) {
2304 LCID locIdBase = MAKELCID( MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANG_NEUTRAL ), SORT_DEFAULT );
2305 if(GetLocaleInfo(locIdBase, LOCALE_SABBREVLANGNAME,
2306 lbuffer, 10)) {
2307 l = winLoadLanguage(lbuffer);
2308 if(l == NULL) {
2309 systemMessage(IDS_FAILED_TO_LOAD_LIBRARY,
2310 "Failed to load library %s",
2311 lbuffer);
2312 return;
2313 }
2314 }
2315 }
2316 AfxSetResourceHandle(l);
2317 if(languageModule != NULL)
2318 #ifdef _AFXDLL
2319 AfxFreeLibrary( languageModule );
2320 #else
2321 FreeLibrary( languageModule );
2322 #endif
2323 languageModule = l;
2324 } else {
2325 systemMessage(IDS_FAILED_TO_GET_LOCINFO,
2326 "Failed to get locale information");
2327 return;
2328 }
2329 }
2330 break;
2331 case 1:
2332 if(languageModule != NULL)
2333 #ifdef _AFXDLL
2334 AfxFreeLibrary( languageModule );
2335 #else
2336 FreeLibrary( languageModule );
2337 #endif
2338 languageModule = NULL;
2339 AfxSetResourceHandle(AfxGetInstanceHandle());
2340 break;
2341 case 2:
2342 {
2343 if(!force) {
2344 LangSelect dlg;
2345 if(dlg.DoModal()) {
2346 HINSTANCE l = winLoadLanguage(languageName);
2347 if(l == NULL) {
2348 systemMessage(IDS_FAILED_TO_LOAD_LIBRARY,
2349 "Failed to load library %s",
2350 languageName);
2351 return;
2352 }
2353 AfxSetResourceHandle(l);
2354 if(languageModule != NULL)
2355 {
2356 #ifdef _AFXDLL
2357 AfxFreeLibrary( languageModule );
2358 #else
2359 FreeLibrary( languageModule );
2360 #endif
2361 }
2362 languageModule = l;
2363 }
2364 } else {
2365 if(languageName.IsEmpty())
2366 return;
2367 HINSTANCE l = winLoadLanguage(languageName);
2368 if(l == NULL) {
2369 systemMessage(IDS_FAILED_TO_LOAD_LIBRARY,
2370 "Failed to load library %s",
2371 languageName);
2372 return;
2373 }
2374 AfxSetResourceHandle(l);
2375 if(languageModule != NULL)
2376 FreeLibrary(languageModule);
2377 languageModule = l;
2378 }
2379 }
2380 break;
2381 }
2382 languageOption = option;
2383 updateMenuBar();
2384 }
2385
winLoadLanguage(const char * name)2386 HINSTANCE VBA::winLoadLanguage(const char *name)
2387 {
2388 CString buffer;
2389
2390 buffer.Format( _T("vba_%s.dll"), name);
2391
2392 #ifdef _AFXDLL
2393 HINSTANCE l = AfxLoadLibrary( buffer );
2394 #else
2395 HMODULE l = LoadLibrary( buffer );
2396 #endif
2397
2398 if(l == NULL) {
2399 if(strlen(name) == 3) {
2400 char buffer2[3];
2401 buffer2[0] = name[0];
2402 buffer2[1] = name[1];
2403 buffer2[2] = 0;
2404 buffer.Format("vba_%s.dll", buffer2);
2405
2406 #ifdef _AFXDLL
2407 return AfxLoadLibrary( buffer );
2408 #else
2409 return LoadLibrary( buffer );
2410 #endif
2411 }
2412 }
2413 return l;
2414 }
2415
2416
initInput()2417 bool VBA::initInput()
2418 {
2419 if(input)
2420 delete input;
2421 input = newDirectInput();
2422 if(input->initialize()) {
2423 input->loadSettings();
2424 input->checkKeys();
2425 return true;
2426 }
2427 delete input;
2428 return false;
2429 }
2430
winAddUpdateListener(IUpdateListener * l)2431 void VBA::winAddUpdateListener(IUpdateListener *l)
2432 {
2433 updateList.AddTail(l);
2434 updateCount++;
2435 }
2436
winRemoveUpdateListener(IUpdateListener * l)2437 void VBA::winRemoveUpdateListener(IUpdateListener *l)
2438 {
2439 POSITION pos = updateList.Find(l);
2440 if(pos) {
2441 updateList.RemoveAt(pos);
2442 updateCount--;
2443 if(updateCount < 0)
2444 updateCount = 0;
2445 }
2446 }
2447
winLoadFilter(UINT id)2448 CString VBA::winLoadFilter(UINT id)
2449 {
2450 CString res = winResLoadString(id);
2451 res.Replace('_','|');
2452
2453 return res;
2454 }
2455
movieReadNext()2456 void VBA::movieReadNext()
2457 {
2458 if(movieFile) {
2459 bool movieEnd = false;
2460
2461 if(fread(&moviePlayFrame, 1, sizeof(int), movieFile) == sizeof(int)) {
2462 if(fread(&movieNextJoypad, 1, sizeof(u32), movieFile) == sizeof(int)) {
2463 // make sure we don't have spurious entries on the movie that can
2464 // cause us to play it forever
2465 if(moviePlayFrame <= movieFrame)
2466 movieEnd = true;
2467 } else
2468 movieEnd = true;
2469 } else
2470 movieEnd = true;
2471 if(movieEnd) {
2472 CString string = winResLoadString(IDS_END_OF_MOVIE);
2473 systemScreenMessage(string);
2474 moviePlaying = false;
2475 fclose(movieFile);
2476 movieFile = NULL;
2477 return;
2478 }
2479 } else
2480 moviePlaying = false;
2481 }
2482
saveSettings()2483 void VBA::saveSettings()
2484 {
2485 regSetDwordValue("language", languageOption);
2486
2487 regSetStringValue("languageName", languageName);
2488
2489 regSetDwordValue("frameSkip", frameSkip);
2490
2491 regSetDwordValue("gbFrameSkip", gbFrameSkip);
2492
2493 regSetDwordValue("autoFrameSkip", autoFrameSkip);
2494 regSetDwordValue("vsync", vsync);
2495 regSetDwordValue("stretch", fullScreenStretch);
2496
2497 regSetDwordValue("video", videoOption);
2498
2499 regSetDwordValue("fsAdapter", fsAdapter);
2500 regSetDwordValue("fsWidth", fsWidth);
2501 regSetDwordValue("fsHeight", fsHeight);
2502 regSetDwordValue("fsColorDepth", fsColorDepth);
2503 regSetDwordValue("fsFrequency", fsFrequency);
2504
2505 regSetDwordValue("renderMethod", renderMethod);
2506 regSetDwordValue( "audioAPI", audioAPI );
2507
2508 regSetDwordValue("windowX", windowPositionX);
2509 regSetDwordValue("windowY", windowPositionY);
2510
2511 regSetDwordValue("maxCpuCores", maxCpuCores);
2512
2513 regSetDwordValue("useBiosGBA", useBiosFileGBA);
2514
2515 regSetDwordValue("useBiosGBC", useBiosFileGBC);
2516
2517 regSetDwordValue("useBiosGB", useBiosFileGB);
2518
2519 regSetDwordValue("skipBios", skipBios);
2520
2521 if(!biosFileNameGBA.IsEmpty())
2522 regSetStringValue("biosFileGBA", biosFileNameGBA);
2523
2524 if(!biosFileNameGBC.IsEmpty())
2525 regSetStringValue("biosFileGBC", biosFileNameGBC);
2526
2527 if(!biosFileNameGB.IsEmpty())
2528 regSetStringValue("biosFileGB", biosFileNameGB);
2529
2530 regSetDwordValue("soundEnable", soundGetEnable() & 0x30f);
2531
2532 regSetDwordValue("soundQuality", 44100 / soundGetSampleRate() );
2533
2534 regSetDwordValue("soundVolume", (DWORD)(soundGetVolume() * 100.0f));
2535
2536 regSetDwordValue( "gbSoundEffectsEnabled", gb_effects_config.enabled ? 1 : 0 );
2537 regSetDwordValue( "gbSoundEffectsSurround", gb_effects_config.surround ? 1 : 0 );
2538 regSetDwordValue( "gbSoundEffectsEcho", (DWORD)( gb_effects_config.echo * 100.0f ) );
2539 regSetDwordValue( "gbSoundEffectsStereo", (DWORD)( gb_effects_config.stereo * 100.0f ) );
2540
2541 regSetDwordValue( "gbSoundDeclicking", gbSoundGetDeclicking() ? 1 : 0 );
2542
2543 regSetDwordValue( "gbaSoundInterpolation", soundInterpolation ? 1 : 0 );
2544 regSetDwordValue( "gbaSoundFiltering", (DWORD)( soundFiltering * 100.0f ) );
2545
2546 regSetDwordValue("tripleBuffering", tripleBuffering);
2547
2548 #ifndef NO_D3D
2549 regSetDwordValue("d3dFilter", d3dFilter);
2550 regSetDwordValue("d3dMotionBlur", d3dMotionBlur ? 1 : 0);
2551 #endif
2552
2553 regSetDwordValue("glFilter", glFilter);
2554
2555 regSetDwordValue("filter", filter);
2556
2557 regSetDwordValue("filterEnableMultiThreading", filterMT ? 1 : 0);
2558
2559 regSetDwordValue("disableMMX", disableMMX);
2560
2561 regSetDwordValue("disableStatus", disableStatusMessages);
2562
2563 regSetDwordValue("showSpeed", showSpeed);
2564
2565 regSetDwordValue("showSpeedTransparent", showSpeedTransparent);
2566
2567 regSetDwordValue("gbPrinter", winGbPrinterEnabled);
2568
2569 regSetDwordValue("captureFormat", captureFormat);
2570
2571 regSetDwordValue("recentFreeze", recentFreeze);
2572
2573 regSetDwordValue("autoPatch", autoPatch ? 1 : 0);
2574
2575 regSetDwordValue("disableSfx", cpuDisableSfx);
2576
2577 regSetDwordValue("saveType", cpuSaveType);
2578
2579 regSetDwordValue("ifbType", ifbType);
2580
2581 regSetDwordValue("flashSize", winFlashSize);
2582
2583 regSetDwordValue("agbPrint", agbPrintIsEnabled());
2584
2585 regSetDwordValue("rtcEnabled", rtcEnabled);
2586
2587 regSetDwordValue("borderOn", winGbBorderOn);
2588 regSetDwordValue("borderAutomatic", gbBorderAutomatic);
2589 regSetDwordValue("emulatorType", gbEmulatorType);
2590 regSetDwordValue("colorOption", gbColorOption);
2591
2592 regSetDwordValue("priority", threadPriority);
2593
2594 regSetDwordValue("autoSaveCheatList", autoSaveLoadCheatList);
2595
2596 regSetDwordValue("gbPaletteOption", gbPaletteOption);
2597
2598 regSetBinaryValue("gbPalette", (char *)systemGbPalette,
2599 24*sizeof(u16));
2600
2601 regSetDwordValue("rewindTimer", rewindTimer/6);
2602
2603 CString buffer;
2604 for(int i = 0; i < 10; i++) {
2605 buffer.Format("recent%d", i);
2606 regSetStringValue(buffer, recentFiles[i]);
2607 }
2608
2609 regSetDwordValue("joypadDefault", joypadDefault);
2610 regSetDwordValue("autoLoadMostRecent", autoLoadMostRecent);
2611 regSetDwordValue("skipSaveGameBattery", skipSaveGameBattery);
2612 regSetDwordValue("skipSaveGameCheats", skipSaveGameCheats);
2613 regSetDwordValue("cheatsEnabled", cheatsEnabled);
2614 regSetDwordValue("maxScale", maxScale);
2615 regSetDwordValue("throttle", throttle);
2616 regSetStringValue("pluginName", pluginName);
2617 regSetDwordValue("saveMoreCPU", Sm60FPS::bSaveMoreCPU);
2618
2619 #ifndef NO_LINK
2620 regSetDwordValue("LinkTimeout", linkTimeout);
2621 regSetDwordValue("LinkMode", linkMode);
2622 regSetStringValue("LinkHostAddr", linkHostAddr);
2623 regSetDwordValue("LinkAuto", linkAuto);
2624 regSetDwordValue("LinkHacks", linkHacks);
2625 regSetDwordValue("LinkNumPlayers", linkNumPlayers);
2626 #endif
2627
2628 regSetDwordValue("gdbPort", gdbPort);
2629 regSetDwordValue("gdbBreakOnLoad", gdbBreakOnLoad);
2630
2631 regSetDwordValue("lastFullscreen", lastFullscreen);
2632 regSetDwordValue("pauseWhenInactive", pauseWhenInactive);
2633
2634 #ifndef NO_OAL
2635 regSetStringValue( "oalDevice", oalDevice );
2636 regSetDwordValue( "oalBufferCount", oalBufferCount );
2637 #endif
2638
2639 #ifndef NO_XAUDIO2
2640 regSetDwordValue( "xa2Device", xa2Device );
2641 regSetDwordValue( "xa2BufferCount", xa2BufferCount );
2642 regSetDwordValue( "xa2Upmixing", xa2Upmixing ? 1 : 0 );
2643 #endif
2644 }
2645
detectCpuCores()2646 unsigned int VBA::detectCpuCores()
2647 {
2648 SYSTEM_INFO info;
2649
2650 GetSystemInfo( &info );
2651
2652 return info.dwNumberOfProcessors;
2653 }
2654
winSignal(int,int)2655 void winSignal(int, int)
2656 {
2657 }
2658
2659 #define CPUReadByteQuick(addr) \
2660 map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
2661
winOutput(const char * s,u32 addr)2662 void winOutput(const char *s, u32 addr)
2663 {
2664 if(s) {
2665 toolsLog(s);
2666 } else {
2667 CString str;
2668 char c;
2669
2670 c = CPUReadByteQuick(addr);
2671 addr++;
2672 while(c) {
2673 str += c;
2674 c = CPUReadByteQuick(addr);
2675 addr++;
2676 }
2677 toolsLog(str);
2678 }
2679 }
2680
2681
Sm60FPS_Init()2682 void Sm60FPS_Init()
2683 {
2684 Sm60FPS::dwTimeElapse = 0;
2685 Sm60FPS::fWantFPS = 60.f;
2686 Sm60FPS::fCurFPS = 0.f;
2687 Sm60FPS::nFrameCnt = 0;
2688 Sm60FPS::bLastSkip = false;
2689 Sm60FPS::nCurSpeed = 100;
2690 }
2691
2692
Sm60FPS_CanSkipFrame()2693 bool Sm60FPS_CanSkipFrame()
2694 {
2695 if( autoFrameSkip ) {
2696 if( Sm60FPS::nFrameCnt == 0 ) {
2697 Sm60FPS::nFrameCnt = 0;
2698 Sm60FPS::dwTimeElapse = 0;
2699 Sm60FPS::dwTime0 = GetTickCount();
2700 } else {
2701 if( Sm60FPS::nFrameCnt >= 10 ) {
2702 Sm60FPS::nFrameCnt = 0;
2703 Sm60FPS::dwTimeElapse = 0;
2704
2705 if( Sm60FPS::nCurSpeed > Sm60FPS::K_fCpuSpeed ) {
2706 Sm60FPS::fWantFPS += 1;
2707 if( Sm60FPS::fWantFPS > Sm60FPS::K_fTargetFps ){
2708 Sm60FPS::fWantFPS = Sm60FPS::K_fTargetFps;
2709 }
2710 } else {
2711 if( Sm60FPS::nCurSpeed < (Sm60FPS::K_fCpuSpeed - 5) ) {
2712 Sm60FPS::fWantFPS -= 1;
2713 if( Sm60FPS::fWantFPS < 30.f ) {
2714 Sm60FPS::fWantFPS = 30.f;
2715 }
2716 }
2717 }
2718 } else { // between frame 1-10
2719 Sm60FPS::dwTime1 = GetTickCount();
2720 Sm60FPS::dwTimeElapse += (Sm60FPS::dwTime1 - Sm60FPS::dwTime0);
2721 Sm60FPS::dwTime0 = Sm60FPS::dwTime1;
2722 if( !Sm60FPS::bLastSkip &&
2723 ( (Sm60FPS::fWantFPS < Sm60FPS::K_fTargetFps) || Sm60FPS::bSaveMoreCPU) ) {
2724 Sm60FPS::fCurFPS = (float)Sm60FPS::nFrameCnt * 1000 / Sm60FPS::dwTimeElapse;
2725 if( (Sm60FPS::fCurFPS < Sm60FPS::K_fTargetFps) || Sm60FPS::bSaveMoreCPU ) {
2726 Sm60FPS::bLastSkip = true;
2727 Sm60FPS::nFrameCnt++;
2728 return true;
2729 }
2730 }
2731 }
2732 }
2733 Sm60FPS::bLastSkip = false;
2734 Sm60FPS::nFrameCnt++;
2735 }
2736 return false;
2737 }
2738
2739
Sm60FPS_Sleep()2740 void Sm60FPS_Sleep()
2741 {
2742 if( autoFrameSkip ) {
2743 u32 dwTimePass = Sm60FPS::dwTimeElapse + (GetTickCount() - Sm60FPS::dwTime0);
2744 u32 dwTimeShould = (u32)(Sm60FPS::nFrameCnt * Sm60FPS::K_fDT);
2745 if (dwTimeShould > dwTimePass && !gba_joybus_active) {
2746 Sleep(dwTimeShould - dwTimePass);
2747 }
2748 }
2749 }
2750