home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / win32 / VBA.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  51.0 KB  |  2,204 lines

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