diff src/gtk/window.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/gtk/window.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,1944 @@
     1.4 +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
     1.5 +// Copyright (C) 1999-2003 Forgotten
     1.6 +// Copyright (C) 2004 Forgotten and the VBA development team
     1.7 +
     1.8 +// This program is free software; you can redistribute it and/or modify
     1.9 +// it under the terms of the GNU General Public License as published by
    1.10 +// the Free Software Foundation; either version 2, or(at your option)
    1.11 +// any later version.
    1.12 +//
    1.13 +// This program is distributed in the hope that it will be useful,
    1.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.16 +// GNU General Public License for more details.
    1.17 +//
    1.18 +// You should have received a copy of the GNU General Public License
    1.19 +// along with this program; if not, write to the Free Software Foundation,
    1.20 +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    1.21 +
    1.22 +#include "window.h"
    1.23 +
    1.24 +#include <sys/stat.h>
    1.25 +
    1.26 +#include <stdio.h>
    1.27 +#include <time.h>
    1.28 +
    1.29 +#include <SDL.h>
    1.30 +
    1.31 +#include "../gba/GBA.h"
    1.32 +#include "../gba/GBAGlobals.h"
    1.33 +#include "../gba/GBASound.h"
    1.34 +#include "../gb/GB.h"
    1.35 +#include "../gb/gbGlobals.h"
    1.36 +#include "../gb/gbPrinter.h"
    1.37 +#include "../common/Util.h"
    1.38 +
    1.39 +#include "menuitem.h"
    1.40 +#include "tools.h"
    1.41 +#include "intl.h"
    1.42 +
    1.43 +extern int systemRenderedFrames;
    1.44 +extern int systemFPS;
    1.45 +extern bool debugger;
    1.46 +extern int RGB_LOW_BITS_MASK;
    1.47 +extern void (*dbgMain)();
    1.48 +extern void (*dbgSignal)(int, int);
    1.49 +extern void (*dbgOutput)(char *, u32);
    1.50 +extern void remoteInit();
    1.51 +extern void remoteCleanUp();
    1.52 +extern void remoteStubMain();
    1.53 +extern void remoteStubSignal(int, int);
    1.54 +extern void remoteOutput(char *, u32);
    1.55 +extern void remoteSetProtocol(int);
    1.56 +extern void remoteSetPort(int);
    1.57 +
    1.58 +#ifdef MMX
    1.59 +extern "C" bool cpu_mmx;
    1.60 +#endif // MMX
    1.61 +
    1.62 +namespace VBA
    1.63 +{
    1.64 +
    1.65 +using Gnome::Glade::Xml;
    1.66 +
    1.67 +Window * Window::m_poInstance = NULL;
    1.68 +
    1.69 +Window::Window(GtkWindow * _pstWindow, const Glib::RefPtr<Xml> & _poXml) :
    1.70 +  Gtk::Window       (_pstWindow),
    1.71 +  m_iGBScreenWidth  (160),
    1.72 +  m_iGBScreenHeight (144),
    1.73 +  m_iSGBScreenWidth (256),
    1.74 +  m_iSGBScreenHeight(224),
    1.75 +  m_iGBAScreenWidth (240),
    1.76 +  m_iGBAScreenHeight(160),
    1.77 +  m_iFrameskipMin   (0),
    1.78 +  m_iFrameskipMax   (9),
    1.79 +  m_iThrottleMin    (5),
    1.80 +  m_iThrottleMax    (1000),
    1.81 +  m_iScaleMin       (1),
    1.82 +  m_iScaleMax       (6),
    1.83 +  m_iShowSpeedMin   (ShowNone),
    1.84 +  m_iShowSpeedMax   (ShowDetailed),
    1.85 +  m_iSaveTypeMin    (SaveAuto),
    1.86 +  m_iSaveTypeMax    (SaveNone),
    1.87 +  m_iSoundQualityMin(Sound44K),
    1.88 +  m_iSoundQualityMax(Sound11K),
    1.89 +  m_iSoundVolumeMin (Sound100),
    1.90 +  m_iSoundVolumeMax (Sound50),
    1.91 +  m_iEmulatorTypeMin(EmulatorAuto),
    1.92 +  m_iEmulatorTypeMax(EmulatorSGB2),
    1.93 +  m_iFilter2xMin    (FirstFilter),
    1.94 +  m_iFilter2xMax    (LastFilter),
    1.95 +  m_iFilterIBMin    (FirstFilterIB),
    1.96 +  m_iFilterIBMax    (LastFilterIB),
    1.97 +  m_iJoypadMin      (1),
    1.98 +  m_iJoypadMax      (4)
    1.99 +{
   1.100 +  m_poXml            = _poXml;
   1.101 +  m_poFileOpenDialog = NULL;
   1.102 +  m_iScreenWidth     = m_iGBAScreenWidth;
   1.103 +  m_iScreenHeight    = m_iGBAScreenHeight;
   1.104 +  m_eCartridge       = CartridgeNone;
   1.105 +  m_uiJoypadState    = 0;
   1.106 +
   1.107 +  vInitSystem();
   1.108 +  vInitSDL();
   1.109 +
   1.110 +  Gtk::Container * poC;
   1.111 +  poC = dynamic_cast<Gtk::Container *>(_poXml->get_widget("ScreenContainer"));
   1.112 +  m_poScreenArea = Gtk::manage(new ScreenArea(m_iScreenWidth, m_iScreenHeight));
   1.113 +  poC->add(*m_poScreenArea);
   1.114 +  vDrawDefaultScreen();
   1.115 +  m_poScreenArea->show();
   1.116 +
   1.117 +  // Get config
   1.118 +  //
   1.119 +  vInitConfig();
   1.120 +
   1.121 +  m_sUserDataDir = Glib::get_home_dir() + "/.gvba";
   1.122 +  m_sConfigFile  = m_sUserDataDir + "/config";
   1.123 +
   1.124 +  if (! Glib::file_test(m_sUserDataDir, Glib::FILE_TEST_EXISTS))
   1.125 +  {
   1.126 +    mkdir(m_sUserDataDir.c_str(), 0777);
   1.127 +  }
   1.128 +  if (Glib::file_test(m_sConfigFile, Glib::FILE_TEST_EXISTS))
   1.129 +  {
   1.130 +    vLoadConfig(m_sConfigFile);
   1.131 +    vCheckConfig();
   1.132 +  }
   1.133 +  else
   1.134 +  {
   1.135 +    vSaveConfig(m_sConfigFile);
   1.136 +  }
   1.137 +
   1.138 +  vCreateFileOpenDialog();
   1.139 +  vLoadHistoryFromConfig();
   1.140 +  vLoadJoypadsFromConfig();
   1.141 +
   1.142 +  Gtk::MenuItem *      poMI;
   1.143 +  Gtk::CheckMenuItem * poCMI;
   1.144 +
   1.145 +  // File menu
   1.146 +  //
   1.147 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileOpen"));
   1.148 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileOpen));
   1.149 +
   1.150 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileLoad"));
   1.151 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileLoad));
   1.152 +  m_listSensitiveWhenPlaying.push_back(poMI);
   1.153 +
   1.154 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileSave"));
   1.155 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileSave));
   1.156 +  m_listSensitiveWhenPlaying.push_back(poMI);
   1.157 +
   1.158 +  for (int i = 0; i < 10; i++)
   1.159 +  {
   1.160 +    char csName[20];
   1.161 +    snprintf(csName, 20, "LoadGameSlot%d", i + 1);
   1.162 +    m_apoLoadGameItem[i] = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget(csName));
   1.163 +    snprintf(csName, 20, "SaveGameSlot%d", i + 1);
   1.164 +    m_apoSaveGameItem[i] = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget(csName));
   1.165 +
   1.166 +    m_apoLoadGameItem[i]->signal_activate().connect(SigC::bind<int>(
   1.167 +                                                      SigC::slot(*this, &Window::vOnLoadGame),
   1.168 +                                                      i + 1));
   1.169 +    m_apoSaveGameItem[i]->signal_activate().connect(SigC::bind<int>(
   1.170 +                                                      SigC::slot(*this, &Window::vOnSaveGame),
   1.171 +                                                      i + 1));
   1.172 +  }
   1.173 +  vUpdateGameSlots();
   1.174 +
   1.175 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("LoadGameMostRecent"));
   1.176 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnLoadGameMostRecent));
   1.177 +  m_listSensitiveWhenPlaying.push_back(poMI);
   1.178 +
   1.179 +  poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("LoadGameAuto"));
   1.180 +  poCMI->set_active(m_poCoreConfig->oGetKey<bool>("load_game_auto"));
   1.181 +  vOnLoadGameAutoToggled(poCMI);
   1.182 +  poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(
   1.183 +                                    SigC::slot(*this, &Window::vOnLoadGameAutoToggled),
   1.184 +                                    poCMI));
   1.185 +
   1.186 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("SaveGameOldest"));
   1.187 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnSaveGameOldest));
   1.188 +  m_listSensitiveWhenPlaying.push_back(poMI);
   1.189 +
   1.190 +  m_poFilePauseItem = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("FilePause"));
   1.191 +  m_poFilePauseItem->set_active(false);
   1.192 +  vOnFilePauseToggled(m_poFilePauseItem);
   1.193 +  m_poFilePauseItem->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(
   1.194 +                                                SigC::slot(*this, &Window::vOnFilePauseToggled),
   1.195 +                                                m_poFilePauseItem));
   1.196 +  m_listSensitiveWhenPlaying.push_back(m_poFilePauseItem);
   1.197 +
   1.198 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileReset"));
   1.199 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileReset));
   1.200 +  m_listSensitiveWhenPlaying.push_back(poMI);
   1.201 +
   1.202 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileScreenCapture"));
   1.203 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileScreenCapture));
   1.204 +  m_listSensitiveWhenPlaying.push_back(poMI);
   1.205 +
   1.206 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileClose"));
   1.207 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileClose));
   1.208 +  m_listSensitiveWhenPlaying.push_back(poMI);
   1.209 +
   1.210 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileExit"));
   1.211 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileExit));
   1.212 +
   1.213 +  // Recent menu
   1.214 +  //
   1.215 +  m_poRecentMenu = dynamic_cast<Gtk::Menu *>(_poXml->get_widget("RecentMenu_menu"));
   1.216 +  vUpdateHistoryMenu();
   1.217 +
   1.218 +  m_poRecentResetItem = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("RecentReset"));
   1.219 +  m_poRecentResetItem->signal_activate().connect(SigC::slot(*this, &Window::vOnRecentReset));
   1.220 +
   1.221 +  poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("RecentFreeze"));
   1.222 +  poCMI->set_active(m_poHistoryConfig->oGetKey<bool>("freeze"));
   1.223 +  vOnRecentFreezeToggled(poCMI);
   1.224 +  poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(
   1.225 +                                    SigC::slot(*this, &Window::vOnRecentFreezeToggled),
   1.226 +                                    poCMI));
   1.227 +
   1.228 +  // Import menu
   1.229 +  //
   1.230 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("ImportBatteryFile"));
   1.231 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnImportBatteryFile));
   1.232 +  m_listSensitiveWhenPlaying.push_back(poMI);
   1.233 +
   1.234 +  // Export menu
   1.235 +  //
   1.236 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("ExportBatteryFile"));
   1.237 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnExportBatteryFile));
   1.238 +  m_listSensitiveWhenPlaying.push_back(poMI);
   1.239 +
   1.240 +  // Frameskip menu
   1.241 +  //
   1.242 +  struct
   1.243 +  {
   1.244 +    const char * m_csName;
   1.245 +    const int    m_iFrameskip;
   1.246 +  }
   1.247 +  astFrameskip[] =
   1.248 +  {
   1.249 +    { "FrameskipAutomatic", -1 },
   1.250 +    { "Frameskip0",          0 },
   1.251 +    { "Frameskip1",          1 },
   1.252 +    { "Frameskip2",          2 },
   1.253 +    { "Frameskip3",          3 },
   1.254 +    { "Frameskip4",          4 },
   1.255 +    { "Frameskip5",          5 },
   1.256 +    { "Frameskip6",          6 },
   1.257 +    { "Frameskip7",          7 },
   1.258 +    { "Frameskip8",          8 },
   1.259 +    { "Frameskip9",          9 }
   1.260 +  };
   1.261 +  int iDefaultFrameskip;
   1.262 +  if (m_poCoreConfig->sGetKey("frameskip") == "auto")
   1.263 +  {
   1.264 +    iDefaultFrameskip = -1;
   1.265 +  }
   1.266 +  else
   1.267 +  {
   1.268 +    iDefaultFrameskip = m_poCoreConfig->oGetKey<int>("frameskip");
   1.269 +  }
   1.270 +  for (guint i = 0; i < G_N_ELEMENTS(astFrameskip); i++)
   1.271 +  {
   1.272 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astFrameskip[i].m_csName));
   1.273 +    if (astFrameskip[i].m_iFrameskip == iDefaultFrameskip)
   1.274 +    {
   1.275 +      poCMI->set_active();
   1.276 +      vOnFrameskipToggled(poCMI, iDefaultFrameskip);
   1.277 +    }
   1.278 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.279 +                                      SigC::slot(*this, &Window::vOnFrameskipToggled),
   1.280 +                                      poCMI, astFrameskip[i].m_iFrameskip));
   1.281 +  }
   1.282 +
   1.283 +  // Throttle menu
   1.284 +  //
   1.285 +  struct
   1.286 +  {
   1.287 +    const char * m_csName;
   1.288 +    const int    m_iThrottle;
   1.289 +  }
   1.290 +  astThrottle[] =
   1.291 +  {
   1.292 +    { "ThrottleNoThrottle",   0 },
   1.293 +    { "Throttle25",          25 },
   1.294 +    { "Throttle50",          50 },
   1.295 +    { "Throttle100",        100 },
   1.296 +    { "Throttle150",        150 },
   1.297 +    { "Throttle200",        200 }
   1.298 +  };
   1.299 +  poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("ThrottleOther"));
   1.300 +  poCMI->set_active();
   1.301 +  poCMI->signal_activate().connect(SigC::bind<Gtk::CheckMenuItem *>(
   1.302 +                                     SigC::slot(*this, &Window::vOnThrottleOther),
   1.303 +                                     poCMI));
   1.304 +
   1.305 +  int iDefaultThrottle = m_poCoreConfig->oGetKey<int>("throttle");
   1.306 +  for (guint i = 0; i < G_N_ELEMENTS(astThrottle); i++)
   1.307 +  {
   1.308 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astThrottle[i].m_csName));
   1.309 +    if (astThrottle[i].m_iThrottle == iDefaultThrottle)
   1.310 +    {
   1.311 +      poCMI->set_active();
   1.312 +    }
   1.313 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.314 +                                      SigC::slot(*this, &Window::vOnThrottleToggled),
   1.315 +                                      poCMI, astThrottle[i].m_iThrottle));
   1.316 +  }
   1.317 +  vSetThrottle(iDefaultThrottle);
   1.318 +
   1.319 +  // Video menu
   1.320 +  //
   1.321 +  struct
   1.322 +  {
   1.323 +    const char * m_csName;
   1.324 +    const int    m_iScale;
   1.325 +  }
   1.326 +  astVideoScale[] =
   1.327 +  {
   1.328 +    { "Video1x", 1 },
   1.329 +    { "Video2x", 2 },
   1.330 +    { "Video3x", 3 },
   1.331 +    { "Video4x", 4 },
   1.332 +    { "Video5x", 5 },
   1.333 +    { "Video6x", 6 }
   1.334 +  };
   1.335 +  int iDefaultScale = m_poDisplayConfig->oGetKey<int>("scale");
   1.336 +  for (guint i = 0; i < G_N_ELEMENTS(astVideoScale); i++)
   1.337 +  {
   1.338 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astVideoScale[i].m_csName));
   1.339 +    if (astVideoScale[i].m_iScale == iDefaultScale)
   1.340 +    {
   1.341 +      poCMI->set_active();
   1.342 +      vOnVideoScaleToggled(poCMI, iDefaultScale);
   1.343 +    }
   1.344 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.345 +                                      SigC::slot(*this, &Window::vOnVideoScaleToggled),
   1.346 +                                      poCMI, astVideoScale[i].m_iScale));
   1.347 +  }
   1.348 +
   1.349 +  // Layers menu
   1.350 +  //
   1.351 +  struct
   1.352 +  {
   1.353 +    const char * m_csName;
   1.354 +    const char * m_csKey;
   1.355 +    const int    m_iLayer;
   1.356 +  }
   1.357 +  astLayer[] =
   1.358 +  {
   1.359 +    { "LayersBg0",    "layer_bg0",    0 },
   1.360 +    { "LayersBg1",    "layer_bg1",    1 },
   1.361 +    { "LayersBg2",    "layer_bg2",    2 },
   1.362 +    { "LayersBg3",    "layer_bg3",    3 },
   1.363 +    { "LayersObj",    "layer_obj",    4 },
   1.364 +    { "LayersWin0",   "layer_win0",   5 },
   1.365 +    { "LayersWin1",   "layer_win1",   6 },
   1.366 +    { "LayersObjWin", "layer_objwin", 7 }
   1.367 +  };
   1.368 +  for (guint i = 0; i < G_N_ELEMENTS(astLayer); i++)
   1.369 +  {
   1.370 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astLayer[i].m_csName));
   1.371 +    poCMI->set_active(m_poCoreConfig->oGetKey<bool>(astLayer[i].m_csKey));
   1.372 +    vOnLayerToggled(poCMI, astLayer[i].m_iLayer);
   1.373 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.374 +                                      SigC::slot(*this, &Window::vOnLayerToggled),
   1.375 +                                      poCMI, astLayer[i].m_iLayer));
   1.376 +  }
   1.377 +
   1.378 +  // Emulator menu
   1.379 +  //
   1.380 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("EmulatorDirectories"));
   1.381 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnDirectories));
   1.382 +
   1.383 +  poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("EmulatorPauseWhenInactive"));
   1.384 +  poCMI->set_active(m_poDisplayConfig->oGetKey<bool>("pause_when_inactive"));
   1.385 +  vOnPauseWhenInactiveToggled(poCMI);
   1.386 +  poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(
   1.387 +                                    SigC::slot(*this, &Window::vOnPauseWhenInactiveToggled),
   1.388 +                                    poCMI));
   1.389 +
   1.390 +  m_poUseBiosItem = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("EmulatorUseBios"));
   1.391 +  m_poUseBiosItem->set_active(m_poCoreConfig->oGetKey<bool>("use_bios_file"));
   1.392 +  if (m_poCoreConfig->sGetKey("bios_file") == "")
   1.393 +  {
   1.394 +    m_poUseBiosItem->set_sensitive(false);
   1.395 +  }
   1.396 +  m_poUseBiosItem->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(
   1.397 +                                              SigC::slot(*this, &Window::vOnUseBiosToggled),
   1.398 +                                              m_poUseBiosItem));
   1.399 +
   1.400 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("EmulatorSelectBios"));
   1.401 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnSelectBios));
   1.402 +
   1.403 +  // Show speed menu
   1.404 +  //
   1.405 +  struct
   1.406 +  {
   1.407 +    const char *     m_csName;
   1.408 +    const EShowSpeed m_eShowSpeed;
   1.409 +  }
   1.410 +  astShowSpeed[] =
   1.411 +  {
   1.412 +    { "ShowSpeedNone",       ShowNone       },
   1.413 +    { "ShowSpeedPercentage", ShowPercentage },
   1.414 +    { "ShowSpeedDetailed",   ShowDetailed   }
   1.415 +  };
   1.416 +  EShowSpeed eDefaultShowSpeed = (EShowSpeed)m_poDisplayConfig->oGetKey<int>("show_speed");
   1.417 +  for (guint i = 0; i < G_N_ELEMENTS(astShowSpeed); i++)
   1.418 +  {
   1.419 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astShowSpeed[i].m_csName));
   1.420 +    if (astShowSpeed[i].m_eShowSpeed == eDefaultShowSpeed)
   1.421 +    {
   1.422 +      poCMI->set_active();
   1.423 +      vOnShowSpeedToggled(poCMI, eDefaultShowSpeed);
   1.424 +    }
   1.425 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.426 +                                      SigC::slot(*this, &Window::vOnShowSpeedToggled),
   1.427 +                                      poCMI, astShowSpeed[i].m_eShowSpeed));
   1.428 +  }
   1.429 +
   1.430 +  // Save type menu
   1.431 +  //
   1.432 +  struct
   1.433 +  {
   1.434 +    const char *    m_csName;
   1.435 +    const ESaveType m_eSaveType;
   1.436 +  }
   1.437 +  astSaveType[] =
   1.438 +  {
   1.439 +    { "SaveTypeAutomatic",    SaveAuto         },
   1.440 +    { "SaveTypeEeprom",       SaveEEPROM       },
   1.441 +    { "SaveTypeSram",         SaveSRAM         },
   1.442 +    { "SaveTypeFlash",        SaveFlash        },
   1.443 +    { "SaveTypeEepromSensor", SaveEEPROMSensor },
   1.444 +    { "SaveTypeNone",         SaveNone         }
   1.445 +  };
   1.446 +  ESaveType eDefaultSaveType = (ESaveType)m_poCoreConfig->oGetKey<int>("save_type");
   1.447 +  for (guint i = 0; i < G_N_ELEMENTS(astSaveType); i++)
   1.448 +  {
   1.449 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astSaveType[i].m_csName));
   1.450 +    if (astSaveType[i].m_eSaveType == eDefaultSaveType)
   1.451 +    {
   1.452 +      poCMI->set_active();
   1.453 +      vOnSaveTypeToggled(poCMI, eDefaultSaveType);
   1.454 +    }
   1.455 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.456 +                                      SigC::slot(*this, &Window::vOnSaveTypeToggled),
   1.457 +                                      poCMI, astSaveType[i].m_eSaveType));
   1.458 +  }
   1.459 +
   1.460 +  // Flash size menu
   1.461 +  //
   1.462 +  struct
   1.463 +  {
   1.464 +    const char * m_csName;
   1.465 +    const int    m_iFlashSize;
   1.466 +  }
   1.467 +  astFlashSize[] =
   1.468 +  {
   1.469 +    { "SaveTypeFlash64K",   64 },
   1.470 +    { "SaveTypeFlash128K", 128 }
   1.471 +  };
   1.472 +  int iDefaultFlashSize = m_poCoreConfig->oGetKey<int>("flash_size");
   1.473 +  for (guint i = 0; i < G_N_ELEMENTS(astFlashSize); i++)
   1.474 +  {
   1.475 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astFlashSize[i].m_csName));
   1.476 +    if (astFlashSize[i].m_iFlashSize == iDefaultFlashSize)
   1.477 +    {
   1.478 +      poCMI->set_active();
   1.479 +      vOnFlashSizeToggled(poCMI, iDefaultFlashSize);
   1.480 +    }
   1.481 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.482 +                                      SigC::slot(*this, &Window::vOnFlashSizeToggled),
   1.483 +                                      poCMI, astFlashSize[i].m_iFlashSize));
   1.484 +  }
   1.485 +
   1.486 +  // Screenshot format menu
   1.487 +  //
   1.488 +  struct
   1.489 +  {
   1.490 +    const char * m_csName;
   1.491 +    const char * m_csScreenshotFormat;
   1.492 +  }
   1.493 +  astScreenshotFormat[] =
   1.494 +  {
   1.495 +    { "ScreenshotFormatPNG", "png" },
   1.496 +    { "ScreenshotFormatBMP", "bmp" }
   1.497 +  };
   1.498 +  std::string sDefaultScreenshotFormat = m_poCoreConfig->sGetKey("screenshot_format");
   1.499 +  for (guint i = 0; i < G_N_ELEMENTS(astScreenshotFormat); i++)
   1.500 +  {
   1.501 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astScreenshotFormat[i].m_csName));
   1.502 +    if (astScreenshotFormat[i].m_csScreenshotFormat == sDefaultScreenshotFormat)
   1.503 +    {
   1.504 +      poCMI->set_active();
   1.505 +      vOnScreenshotFormatToggled(poCMI, sDefaultScreenshotFormat);
   1.506 +    }
   1.507 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, std::string>(
   1.508 +                                      SigC::slot(*this, &Window::vOnScreenshotFormatToggled),
   1.509 +                                      poCMI, std::string(astScreenshotFormat[i].m_csScreenshotFormat)));
   1.510 +  }
   1.511 +
   1.512 +  // Sound menu
   1.513 +  //
   1.514 +  std::string sDefaultSoundStatus = m_poSoundConfig->sGetKey("status");
   1.515 +
   1.516 +  poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("SoundOff"));
   1.517 +  if (sDefaultSoundStatus == "off")
   1.518 +  {
   1.519 +    poCMI->set_active();
   1.520 +    vOnSoundStatusToggled(poCMI, SoundOff);
   1.521 +  }
   1.522 +  poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.523 +                                    SigC::slot(*this, &Window::vOnSoundStatusToggled),
   1.524 +                                    poCMI, SoundOff));
   1.525 +  m_poSoundOffItem = poCMI;
   1.526 +
   1.527 +  poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("SoundMute"));
   1.528 +  if (sDefaultSoundStatus == "mute")
   1.529 +  {
   1.530 +    poCMI->set_active();
   1.531 +    vOnSoundStatusToggled(poCMI, SoundMute);
   1.532 +  }
   1.533 +  poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.534 +                                    SigC::slot(*this, &Window::vOnSoundStatusToggled),
   1.535 +                                    poCMI, SoundMute));
   1.536 +
   1.537 +  poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("SoundOn"));
   1.538 +  if (sDefaultSoundStatus == "on")
   1.539 +  {
   1.540 +    poCMI->set_active();
   1.541 +    vOnSoundStatusToggled(poCMI, SoundOn);
   1.542 +  }
   1.543 +  poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.544 +                                    SigC::slot(*this, &Window::vOnSoundStatusToggled),
   1.545 +                                    poCMI, SoundOn));
   1.546 +
   1.547 +  poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("SoundEcho"));
   1.548 +  poCMI->set_active(m_poSoundConfig->oGetKey<bool>("echo"));
   1.549 +  vOnSoundEchoToggled(poCMI);
   1.550 +  poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(
   1.551 +                                    SigC::slot(*this, &Window::vOnSoundEchoToggled),
   1.552 +                                    poCMI));
   1.553 +
   1.554 +  poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("SoundLowPass"));
   1.555 +  poCMI->set_active(m_poSoundConfig->oGetKey<bool>("low_pass"));
   1.556 +  vOnSoundLowPassToggled(poCMI);
   1.557 +  poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(
   1.558 +                                    SigC::slot(*this, &Window::vOnSoundLowPassToggled),
   1.559 +                                    poCMI));
   1.560 +
   1.561 +  poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("SoundReverseStereo"));
   1.562 +  poCMI->set_active(m_poSoundConfig->oGetKey<bool>("reverse_stereo"));
   1.563 +  vOnSoundReverseToggled(poCMI);
   1.564 +  poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(
   1.565 +                                    SigC::slot(*this, &Window::vOnSoundReverseToggled),
   1.566 +                                    poCMI));
   1.567 +
   1.568 +  struct
   1.569 +  {
   1.570 +    const char * m_csName;
   1.571 +    const char * m_csKey;
   1.572 +    const int    m_iSoundChannel;
   1.573 +  }
   1.574 +  astSoundChannel[] =
   1.575 +  {
   1.576 +    { "SoundChannel1", "channel_1", 0 },
   1.577 +    { "SoundChannel2", "channel_2", 1 },
   1.578 +    { "SoundChannel3", "channel_3", 2 },
   1.579 +    { "SoundChannel4", "channel_4", 3 },
   1.580 +    { "SoundChannelA", "channel_A", 4 },
   1.581 +    { "SoundChannelB", "channel_B", 5 }
   1.582 +  };
   1.583 +  for (guint i = 0; i < G_N_ELEMENTS(astSoundChannel); i++)
   1.584 +  {
   1.585 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astSoundChannel[i].m_csName));
   1.586 +    poCMI->set_active(m_poSoundConfig->oGetKey<bool>(astSoundChannel[i].m_csKey));
   1.587 +    vOnSoundChannelToggled(poCMI, astSoundChannel[i].m_iSoundChannel);
   1.588 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.589 +                                      SigC::slot(*this, &Window::vOnSoundChannelToggled),
   1.590 +                                      poCMI, astSoundChannel[i].m_iSoundChannel));
   1.591 +  }
   1.592 +
   1.593 +  struct
   1.594 +  {
   1.595 +    const char *        m_csName;
   1.596 +    const ESoundQuality m_eSoundQuality;
   1.597 +  }
   1.598 +  astSoundQuality[] =
   1.599 +  {
   1.600 +    { "Sound11Khz", Sound11K },
   1.601 +    { "Sound22Khz", Sound22K },
   1.602 +    { "Sound44Khz", Sound44K }
   1.603 +  };
   1.604 +  ESoundQuality eDefaultSoundQuality = (ESoundQuality)m_poSoundConfig->oGetKey<int>("quality");
   1.605 +  for (guint i = 0; i < G_N_ELEMENTS(astSoundQuality); i++)
   1.606 +  {
   1.607 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astSoundQuality[i].m_csName));
   1.608 +    if (astSoundQuality[i].m_eSoundQuality == eDefaultSoundQuality)
   1.609 +    {
   1.610 +      poCMI->set_active();
   1.611 +      vOnSoundQualityToggled(poCMI, eDefaultSoundQuality);
   1.612 +    }
   1.613 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.614 +                                      SigC::slot(*this, &Window::vOnSoundQualityToggled),
   1.615 +                                      poCMI, astSoundQuality[i].m_eSoundQuality));
   1.616 +  }
   1.617 +
   1.618 +  // Volume menu
   1.619 +  //
   1.620 +  struct
   1.621 +  {
   1.622 +    const char *       m_csName;
   1.623 +    const ESoundVolume m_eSoundVolume;
   1.624 +  }
   1.625 +  astSoundVolume[] =
   1.626 +  {
   1.627 +    { "Volume25",   Sound25  },
   1.628 +    { "Volume50",   Sound50  },
   1.629 +    { "Volume100",  Sound100 },
   1.630 +    { "Volume200",  Sound200 },
   1.631 +    { "Volume300",  Sound300 },
   1.632 +    { "Volume400",  Sound400 }
   1.633 +  };
   1.634 +  ESoundVolume eDefaultSoundVolume = (ESoundVolume)m_poSoundConfig->oGetKey<int>("volume");
   1.635 +  for (guint i = 0; i < G_N_ELEMENTS(astSoundVolume); i++)
   1.636 +  {
   1.637 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astSoundVolume[i].m_csName));
   1.638 +    if (astSoundVolume[i].m_eSoundVolume == eDefaultSoundVolume)
   1.639 +    {
   1.640 +      poCMI->set_active();
   1.641 +      vOnSoundVolumeToggled(poCMI, eDefaultSoundVolume);
   1.642 +    }
   1.643 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.644 +                                      SigC::slot(*this, &Window::vOnSoundVolumeToggled),
   1.645 +                                      poCMI, astSoundVolume[i].m_eSoundVolume));
   1.646 +  }
   1.647 +
   1.648 +  // Gameboy menu
   1.649 +  //
   1.650 +  poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("GameboyBorder"));
   1.651 +  poCMI->set_active(m_poCoreConfig->oGetKey<bool>("gb_border"));
   1.652 +  vOnGBBorderToggled(poCMI);
   1.653 +  poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(
   1.654 +                                    SigC::slot(*this, &Window::vOnGBBorderToggled),
   1.655 +                                    poCMI));
   1.656 +
   1.657 +  poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("GameboyPrinter"));
   1.658 +  poCMI->set_active(m_poCoreConfig->oGetKey<bool>("gb_printer"));
   1.659 +  vOnGBPrinterToggled(poCMI);
   1.660 +  poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(
   1.661 +                                    SigC::slot(*this, &Window::vOnGBPrinterToggled),
   1.662 +                                    poCMI));
   1.663 +
   1.664 +  struct
   1.665 +  {
   1.666 +    const char *        m_csName;
   1.667 +    const EEmulatorType m_eEmulatorType;
   1.668 +  }
   1.669 +  astEmulatorType[] =
   1.670 +  {
   1.671 +    { "GameboyAutomatic", EmulatorAuto },
   1.672 +    { "GameboyGba",       EmulatorGBA  },
   1.673 +    { "GameboyCgb",       EmulatorCGB  },
   1.674 +    { "GameboySgb",       EmulatorSGB  },
   1.675 +    { "GameboySgb2",      EmulatorSGB2 },
   1.676 +    { "GameboyGb",        EmulatorGB   }
   1.677 +  };
   1.678 +  EEmulatorType eDefaultEmulatorType = (EEmulatorType)m_poCoreConfig->oGetKey<int>("emulator_type");
   1.679 +  for (guint i = 0; i < G_N_ELEMENTS(astEmulatorType); i++)
   1.680 +  {
   1.681 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astEmulatorType[i].m_csName));
   1.682 +    if (astEmulatorType[i].m_eEmulatorType == eDefaultEmulatorType)
   1.683 +    {
   1.684 +      poCMI->set_active();
   1.685 +      vOnEmulatorTypeToggled(poCMI, eDefaultEmulatorType);
   1.686 +    }
   1.687 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.688 +                                      SigC::slot(*this, &Window::vOnEmulatorTypeToggled),
   1.689 +                                      poCMI, astEmulatorType[i].m_eEmulatorType));
   1.690 +  }
   1.691 +
   1.692 +  // Filter menu
   1.693 +  //
   1.694 +  struct
   1.695 +  {
   1.696 +    const char *    m_csName;
   1.697 +    const EFilter2x m_eFilter2x;
   1.698 +  }
   1.699 +  astFilter2x[] =
   1.700 +  {
   1.701 +    { "FilterNone",          FilterNone         },
   1.702 +    { "FilterTVMode",        FilterScanlinesTV  },
   1.703 +    { "Filter2xSaI",         Filter2xSaI        },
   1.704 +    { "FilterSuper2xSaI",    FilterSuper2xSaI   },
   1.705 +    { "FilterSuperEagle",    FilterSuperEagle   },
   1.706 +    { "FilterPixelate",      FilterPixelate     },
   1.707 +    { "FilterMotionBlur",    FilterMotionBlur   },
   1.708 +    { "FilterAdvanceMame2x", FilterAdMame2x     },
   1.709 +    { "FilterSimple2x",      FilterSimple2x     },
   1.710 +    { "FilterBilinear",      FilterBilinear     },
   1.711 +    { "FilterBilinearPlus",  FilterBilinearPlus },
   1.712 +    { "FilterScanlines",     FilterScanlines    },
   1.713 +    { "FilterHq2x",          FilterHq2x         },
   1.714 +    { "FilterLq2x",          FilterLq2x         }
   1.715 +  };
   1.716 +  EFilter2x eDefaultFilter2x = (EFilter2x)m_poDisplayConfig->oGetKey<int>("filter2x");
   1.717 +  for (guint i = 0; i < G_N_ELEMENTS(astFilter2x); i++)
   1.718 +  {
   1.719 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astFilter2x[i].m_csName));
   1.720 +    if (astFilter2x[i].m_eFilter2x == eDefaultFilter2x)
   1.721 +    {
   1.722 +      poCMI->set_active();
   1.723 +      vOnFilter2xToggled(poCMI, eDefaultFilter2x);
   1.724 +    }
   1.725 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.726 +                                      SigC::slot(*this, &Window::vOnFilter2xToggled),
   1.727 +                                      poCMI, astFilter2x[i].m_eFilter2x));
   1.728 +  }
   1.729 +
   1.730 +  poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("FilterDisableMmx"));
   1.731 +#ifdef MMX
   1.732 +  poCMI->set_active(m_poDisplayConfig->oGetKey<bool>("filter_disable_mmx"));
   1.733 +  vOnDisableMMXToggled(poCMI);
   1.734 +  poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(
   1.735 +                                    SigC::slot(*this, &Window::vOnDisableMMXToggled),
   1.736 +                                    poCMI));
   1.737 +#else // ! MMX
   1.738 +  poCMI->set_active();
   1.739 +  poCMI->set_sensitive(false);
   1.740 +#endif // ! MMX
   1.741 +
   1.742 +  // Interframe blending menu
   1.743 +  //
   1.744 +  struct
   1.745 +  {
   1.746 +    const char *    m_csName;
   1.747 +    const EFilterIB m_eFilterIB;
   1.748 +  }
   1.749 +  astFilterIB[] =
   1.750 +  {
   1.751 +    { "IFBNone",       FilterIBNone       },
   1.752 +    { "IFBSmart",      FilterIBSmart      },
   1.753 +    { "IFBMotionBlur", FilterIBMotionBlur }
   1.754 +  };
   1.755 +  EFilterIB eDefaultFilterIB = (EFilterIB)m_poDisplayConfig->oGetKey<int>("filterIB");
   1.756 +  for (guint i = 0; i < G_N_ELEMENTS(astFilterIB); i++)
   1.757 +  {
   1.758 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astFilterIB[i].m_csName));
   1.759 +    if (astFilterIB[i].m_eFilterIB == eDefaultFilterIB)
   1.760 +    {
   1.761 +      poCMI->set_active();
   1.762 +      vOnFilterIBToggled(poCMI, eDefaultFilterIB);
   1.763 +    }
   1.764 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.765 +                                      SigC::slot(*this, &Window::vOnFilterIBToggled),
   1.766 +                                      poCMI, astFilterIB[i].m_eFilterIB));
   1.767 +  }
   1.768 +
   1.769 +  // Joypad menu
   1.770 +  //
   1.771 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("JoypadConfigure1"));
   1.772 +  poMI->signal_activate().connect(SigC::bind<int>(
   1.773 +                                    SigC::slot(*this, &Window::vOnJoypadConfigure), 1));
   1.774 +
   1.775 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("JoypadConfigure2"));
   1.776 +  poMI->signal_activate().connect(SigC::bind<int>(
   1.777 +                                    SigC::slot(*this, &Window::vOnJoypadConfigure), 2));
   1.778 +
   1.779 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("JoypadConfigure3"));
   1.780 +  poMI->signal_activate().connect(SigC::bind<int>(
   1.781 +                                    SigC::slot(*this, &Window::vOnJoypadConfigure), 3));
   1.782 +
   1.783 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("JoypadConfigure4"));
   1.784 +  poMI->signal_activate().connect(SigC::bind<int>(
   1.785 +                                    SigC::slot(*this, &Window::vOnJoypadConfigure), 4));
   1.786 +
   1.787 +  int iDefaultJoypad = m_poInputConfig->oGetKey<int>("active_joypad");
   1.788 +  for (int i = m_iJoypadMin; i <= m_iJoypadMax; i++)
   1.789 +  {
   1.790 +    char csName[20];
   1.791 +    snprintf(csName, sizeof(csName), "Joypad%d", i);
   1.792 +
   1.793 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(csName));
   1.794 +    if (i == iDefaultJoypad)
   1.795 +    {
   1.796 +      poCMI->set_active();
   1.797 +      vOnJoypadToggled(poCMI, iDefaultJoypad);
   1.798 +    }
   1.799 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(
   1.800 +                                      SigC::slot(*this, &Window::vOnJoypadToggled),
   1.801 +                                      poCMI, i));
   1.802 +  }
   1.803 +
   1.804 +  // Autofire menu
   1.805 +  //
   1.806 +  struct
   1.807 +  {
   1.808 +    const char *   m_csName;
   1.809 +    const char *   m_csKey;
   1.810 +    const EKeyFlag m_eKeyFlag;
   1.811 +  }
   1.812 +  astAutofire[] =
   1.813 +  {
   1.814 +    { "AutofireA", "autofire_A", KeyFlagA },
   1.815 +    { "AutofireB", "autofire_B", KeyFlagB },
   1.816 +    { "AutofireL", "autofire_L", KeyFlagL },
   1.817 +    { "AutofireR", "autofire_R", KeyFlagR }
   1.818 +  };
   1.819 +  for (guint i = 0; i < G_N_ELEMENTS(astAutofire); i++)
   1.820 +  {
   1.821 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astAutofire[i].m_csName));
   1.822 +    poCMI->set_active(m_poInputConfig->oGetKey<bool>(astAutofire[i].m_csKey));
   1.823 +    vOnAutofireToggled(poCMI, astAutofire[i].m_eKeyFlag);
   1.824 +    poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, u32>(
   1.825 +                                      SigC::slot(*this, &Window::vOnAutofireToggled),
   1.826 +                                      poCMI, astAutofire[i].m_eKeyFlag));
   1.827 +  }
   1.828 +
   1.829 +  // GDB menu
   1.830 +  //
   1.831 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("GdbWait"));
   1.832 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnGDBWait));
   1.833 +
   1.834 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("GdbLoadAndWait"));
   1.835 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnGDBLoadAndWait));
   1.836 +
   1.837 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("GdbBreak"));
   1.838 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnGDBBreak));
   1.839 +
   1.840 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("GdbDisconnect"));
   1.841 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnGDBDisconnect));
   1.842 +
   1.843 +  // Help menu
   1.844 +  //
   1.845 +  poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("HelpAbout"));
   1.846 +  poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnHelpAbout));
   1.847 +
   1.848 +  // Init widgets sensitivity
   1.849 +  for (std::list<Gtk::Widget *>::iterator it = m_listSensitiveWhenPlaying.begin();
   1.850 +       it != m_listSensitiveWhenPlaying.end();
   1.851 +       it++)
   1.852 +  {
   1.853 +    (*it)->set_sensitive(false);
   1.854 +  }
   1.855 +
   1.856 +  if (m_poInstance == NULL)
   1.857 +  {
   1.858 +    m_poInstance = this;
   1.859 +  }
   1.860 +  else
   1.861 +  {
   1.862 +    abort();
   1.863 +  }
   1.864 +}
   1.865 +
   1.866 +Window::~Window()
   1.867 +{
   1.868 +  vOnFileClose();
   1.869 +  vSaveHistoryToConfig();
   1.870 +  vSaveJoypadsToConfig();
   1.871 +  vSaveConfig(m_sConfigFile);
   1.872 +
   1.873 +  if (m_poFileOpenDialog != NULL)
   1.874 +  {
   1.875 +    delete m_poFileOpenDialog;
   1.876 +  }
   1.877 +
   1.878 +  if (m_poKeymap != NULL)
   1.879 +  {
   1.880 +    delete m_poKeymap;
   1.881 +  }
   1.882 +
   1.883 +  m_poInstance = NULL;
   1.884 +}
   1.885 +
   1.886 +void Window::vInitSystem()
   1.887 +{
   1.888 +#if G_BYTE_ORDER == G_LITTLE_ENDIAN
   1.889 +  systemRedShift    = 3;
   1.890 +  systemGreenShift  = 11;
   1.891 +  systemBlueShift   = 19;
   1.892 +  RGB_LOW_BITS_MASK = 0x00010101;
   1.893 +#else
   1.894 +  systemRedShift    = 27;
   1.895 +  systemGreenShift  = 19;
   1.896 +  systemBlueShift   = 11;
   1.897 +  RGB_LOW_BITS_MASK = 0x01010100;
   1.898 +#endif
   1.899 +
   1.900 +  systemColorDepth = 32;
   1.901 +  systemDebug = 0;
   1.902 +  systemVerbose = 0;
   1.903 +  systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
   1.904 +  systemFrameSkip = 0;
   1.905 +  systemSoundOn = false;
   1.906 +  soundOffFlag = true;
   1.907 +
   1.908 +  systemRenderedFrames = 0;
   1.909 +  systemFPS = 0;
   1.910 +
   1.911 +  emulating = 0;
   1.912 +  debugger = false;
   1.913 +
   1.914 +  for (int i = 0; i < 0x10000; i++)
   1.915 +  {
   1.916 +#if G_BYTE_ORDER == G_LITTLE_ENDIAN
   1.917 +    systemColorMap32[i] = (((i & 0x1f) << systemRedShift)
   1.918 +                           | (((i & 0x3e0) >> 5) << systemGreenShift)
   1.919 +                           | (((i & 0x7c00) >> 10) << systemBlueShift));
   1.920 +#else
   1.921 +    systemColorMap32[i] = (((i & 0x1f) << systemRedShift)
   1.922 +                           | (((i & 0x3e0) >> 5) << systemGreenShift)
   1.923 +                           | (((i & 0x7c00) >> 10) << systemBlueShift));
   1.924 +#endif
   1.925 +  }
   1.926 +
   1.927 +  gbFrameSkip = 0;
   1.928 +
   1.929 +  for (int i = 0; i < 24; )
   1.930 +  {
   1.931 +    systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10);
   1.932 +    systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10);
   1.933 +    systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10);
   1.934 +    systemGbPalette[i++] = 0;
   1.935 +  }
   1.936 +
   1.937 +  Init_2xSaI(32);
   1.938 +}
   1.939 +
   1.940 +void Window::vInitSDL()
   1.941 +{
   1.942 +  static bool bDone = false;
   1.943 +
   1.944 +  if (bDone)
   1.945 +    return;
   1.946 +
   1.947 +  int iFlags = (SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE);
   1.948 +
   1.949 +  if (SDL_Init(iFlags) < 0)
   1.950 +  {
   1.951 +    fprintf(stderr, "Failed to init SDL: %s", SDL_GetError());
   1.952 +    abort();
   1.953 +  }
   1.954 +
   1.955 +  bDone = true;
   1.956 +}
   1.957 +
   1.958 +void Window::vInitConfig()
   1.959 +{
   1.960 +  m_oConfig.vClear();
   1.961 +
   1.962 +  // History section
   1.963 +  //
   1.964 +  m_poHistoryConfig = m_oConfig.poAddSection("History");
   1.965 +  m_poHistoryConfig->vSetKey("freeze", false );
   1.966 +  m_poHistoryConfig->vSetKey("0",      ""    );
   1.967 +  m_poHistoryConfig->vSetKey("1",      ""    );
   1.968 +  m_poHistoryConfig->vSetKey("2",      ""    );
   1.969 +  m_poHistoryConfig->vSetKey("3",      ""    );
   1.970 +  m_poHistoryConfig->vSetKey("4",      ""    );
   1.971 +  m_poHistoryConfig->vSetKey("5",      ""    );
   1.972 +  m_poHistoryConfig->vSetKey("6",      ""    );
   1.973 +  m_poHistoryConfig->vSetKey("7",      ""    );
   1.974 +  m_poHistoryConfig->vSetKey("8",      ""    );
   1.975 +  m_poHistoryConfig->vSetKey("9",      ""    );
   1.976 +
   1.977 +  // Directories section
   1.978 +  //
   1.979 +  m_poDirConfig = m_oConfig.poAddSection("Directories");
   1.980 +  m_poDirConfig->vSetKey("gb_roms",   "" );
   1.981 +  m_poDirConfig->vSetKey("gba_roms",  "" );
   1.982 +  m_poDirConfig->vSetKey("batteries", "" );
   1.983 +  m_poDirConfig->vSetKey("saves",     "" );
   1.984 +  m_poDirConfig->vSetKey("captures",  "" );
   1.985 +
   1.986 +  // Core section
   1.987 +  //
   1.988 +  m_poCoreConfig = m_oConfig.poAddSection("Core");
   1.989 +  m_poCoreConfig->vSetKey("load_game_auto",    false        );
   1.990 +  m_poCoreConfig->vSetKey("frameskip",         "auto"       );
   1.991 +  m_poCoreConfig->vSetKey("throttle",          0            );
   1.992 +  m_poCoreConfig->vSetKey("layer_bg0",         true         );
   1.993 +  m_poCoreConfig->vSetKey("layer_bg1",         true         );
   1.994 +  m_poCoreConfig->vSetKey("layer_bg2",         true         );
   1.995 +  m_poCoreConfig->vSetKey("layer_bg3",         true         );
   1.996 +  m_poCoreConfig->vSetKey("layer_obj",         true         );
   1.997 +  m_poCoreConfig->vSetKey("layer_win0",        true         );
   1.998 +  m_poCoreConfig->vSetKey("layer_win1",        true         );
   1.999 +  m_poCoreConfig->vSetKey("layer_objwin",      true         );
  1.1000 +  m_poCoreConfig->vSetKey("use_bios_file",     false        );
  1.1001 +  m_poCoreConfig->vSetKey("bios_file",         ""           );
  1.1002 +  m_poCoreConfig->vSetKey("save_type",         SaveAuto     );
  1.1003 +  m_poCoreConfig->vSetKey("flash_size",        64           );
  1.1004 +  m_poCoreConfig->vSetKey("gb_border",         true         );
  1.1005 +  m_poCoreConfig->vSetKey("gb_printer",        false        );
  1.1006 +  m_poCoreConfig->vSetKey("emulator_type",     EmulatorAuto );
  1.1007 +  m_poCoreConfig->vSetKey("screenshot_format", "png"        );
  1.1008 +
  1.1009 +  // Display section
  1.1010 +  //
  1.1011 +  m_poDisplayConfig = m_oConfig.poAddSection("Display");
  1.1012 +  m_poDisplayConfig->vSetKey("scale",               1              );
  1.1013 +  m_poDisplayConfig->vSetKey("show_speed",          ShowPercentage );
  1.1014 +  m_poDisplayConfig->vSetKey("pause_when_inactive", true           );
  1.1015 +  m_poDisplayConfig->vSetKey("filter2x",            FilterNone     );
  1.1016 +  m_poDisplayConfig->vSetKey("filterIB",            FilterIBNone   );
  1.1017 +#ifdef MMX
  1.1018 +  m_poDisplayConfig->vSetKey("filter_disable_mmx",  false          );
  1.1019 +#endif // MMX
  1.1020 +
  1.1021 +  // Sound section
  1.1022 +  //
  1.1023 +  m_poSoundConfig = m_oConfig.poAddSection("Sound");
  1.1024 +  m_poSoundConfig->vSetKey("status",         "on"     );
  1.1025 +  m_poSoundConfig->vSetKey("echo",           false    );
  1.1026 +  m_poSoundConfig->vSetKey("low_pass",       false    );
  1.1027 +  m_poSoundConfig->vSetKey("reverse_stereo", false    );
  1.1028 +  m_poSoundConfig->vSetKey("channel_1",      true     );
  1.1029 +  m_poSoundConfig->vSetKey("channel_2",      true     );
  1.1030 +  m_poSoundConfig->vSetKey("channel_3",      true     );
  1.1031 +  m_poSoundConfig->vSetKey("channel_4",      true     );
  1.1032 +  m_poSoundConfig->vSetKey("channel_A",      true     );
  1.1033 +  m_poSoundConfig->vSetKey("channel_B",      true     );
  1.1034 +  m_poSoundConfig->vSetKey("quality",        Sound22K );
  1.1035 +  m_poSoundConfig->vSetKey("volume",         Sound100 );
  1.1036 +
  1.1037 +  // Input section
  1.1038 +  //
  1.1039 +  JoypadConfig oJoypadConfig;
  1.1040 +  oJoypadConfig.vSetDefault();
  1.1041 +  m_poInputConfig = m_oConfig.poAddSection("Input");
  1.1042 +  m_poInputConfig->vSetKey("active_joypad", m_iJoypadMin );
  1.1043 +  for (int i = m_iJoypadMin; i <= m_iJoypadMax; i++)
  1.1044 +  {
  1.1045 +    char csPrefix[20];
  1.1046 +    snprintf(csPrefix, sizeof(csPrefix), "joypad%d_", i);
  1.1047 +    std::string sPrefix(csPrefix);
  1.1048 +    m_poInputConfig->vSetKey(sPrefix + "up",      oJoypadConfig.m_uiUp      );
  1.1049 +    m_poInputConfig->vSetKey(sPrefix + "down",    oJoypadConfig.m_uiDown    );
  1.1050 +    m_poInputConfig->vSetKey(sPrefix + "left",    oJoypadConfig.m_uiLeft    );
  1.1051 +    m_poInputConfig->vSetKey(sPrefix + "right",   oJoypadConfig.m_uiRight   );
  1.1052 +    m_poInputConfig->vSetKey(sPrefix + "A",       oJoypadConfig.m_uiA       );
  1.1053 +    m_poInputConfig->vSetKey(sPrefix + "B",       oJoypadConfig.m_uiB       );
  1.1054 +    m_poInputConfig->vSetKey(sPrefix + "L",       oJoypadConfig.m_uiL       );
  1.1055 +    m_poInputConfig->vSetKey(sPrefix + "R",       oJoypadConfig.m_uiR       );
  1.1056 +    m_poInputConfig->vSetKey(sPrefix + "select",  oJoypadConfig.m_uiSelect  );
  1.1057 +    m_poInputConfig->vSetKey(sPrefix + "start",   oJoypadConfig.m_uiStart   );
  1.1058 +    m_poInputConfig->vSetKey(sPrefix + "speed",   oJoypadConfig.m_uiSpeed   );
  1.1059 +    m_poInputConfig->vSetKey(sPrefix + "capture", oJoypadConfig.m_uiCapture );
  1.1060 +  }
  1.1061 +  m_poInputConfig->vSetKey("autofire_A", false );
  1.1062 +  m_poInputConfig->vSetKey("autofire_B", false );
  1.1063 +  m_poInputConfig->vSetKey("autofire_L", false );
  1.1064 +  m_poInputConfig->vSetKey("autofire_R", false );
  1.1065 +}
  1.1066 +
  1.1067 +void Window::vCheckConfig()
  1.1068 +{
  1.1069 +  int iValue;
  1.1070 +  int iAdjusted;
  1.1071 +  std::string sValue;
  1.1072 +
  1.1073 +  // Directories section
  1.1074 +  //
  1.1075 +  sValue = m_poDirConfig->sGetKey("gb_roms");
  1.1076 +  if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR))
  1.1077 +  {
  1.1078 +    m_poDirConfig->vSetKey("gb_roms", "");
  1.1079 +  }
  1.1080 +  sValue = m_poDirConfig->sGetKey("gba_roms");
  1.1081 +  if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR))
  1.1082 +  {
  1.1083 +    m_poDirConfig->vSetKey("gba_roms", "");
  1.1084 +  }
  1.1085 +  sValue = m_poDirConfig->sGetKey("batteries");
  1.1086 +  if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR))
  1.1087 +  {
  1.1088 +    m_poDirConfig->vSetKey("batteries", "");
  1.1089 +  }
  1.1090 +  sValue = m_poDirConfig->sGetKey("saves");
  1.1091 +  if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR))
  1.1092 +  {
  1.1093 +    m_poDirConfig->vSetKey("saves", "");
  1.1094 +  }
  1.1095 +  sValue = m_poDirConfig->sGetKey("captures");
  1.1096 +  if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR))
  1.1097 +  {
  1.1098 +    m_poDirConfig->vSetKey("captures", "");
  1.1099 +  }
  1.1100 +
  1.1101 +  // Core section
  1.1102 +  //
  1.1103 +  if (m_poCoreConfig->sGetKey("frameskip") != "auto")
  1.1104 +  {
  1.1105 +    iValue = m_poCoreConfig->oGetKey<int>("frameskip");
  1.1106 +    iAdjusted = CLAMP(iValue, m_iFrameskipMin, m_iFrameskipMax);
  1.1107 +    if (iValue != iAdjusted)
  1.1108 +    {
  1.1109 +      m_poCoreConfig->vSetKey("frameskip", iAdjusted);
  1.1110 +    }
  1.1111 +  }
  1.1112 +
  1.1113 +  iValue = m_poCoreConfig->oGetKey<int>("throttle");
  1.1114 +  if (iValue != 0)
  1.1115 +  {
  1.1116 +    iAdjusted = CLAMP(iValue, m_iThrottleMin, m_iThrottleMax);
  1.1117 +    if (iValue != iAdjusted)
  1.1118 +    {
  1.1119 +      m_poCoreConfig->vSetKey("throttle", iAdjusted);
  1.1120 +    }
  1.1121 +  }
  1.1122 +
  1.1123 +  sValue = m_poCoreConfig->sGetKey("bios_file");
  1.1124 +  if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_REGULAR))
  1.1125 +  {
  1.1126 +    m_poCoreConfig->vSetKey("bios_file", "");
  1.1127 +  }
  1.1128 +  if (m_poCoreConfig->sGetKey("bios_file") == "")
  1.1129 +  {
  1.1130 +    m_poCoreConfig->vSetKey("use_bios_file", false);
  1.1131 +  }
  1.1132 +
  1.1133 +  iValue = m_poCoreConfig->oGetKey<int>("save_type");
  1.1134 +  if (iValue != 0)
  1.1135 +  {
  1.1136 +    iAdjusted = CLAMP(iValue, m_iSaveTypeMin, m_iSaveTypeMax);
  1.1137 +    if (iValue != iAdjusted)
  1.1138 +    {
  1.1139 +      m_poCoreConfig->vSetKey("save_type", iAdjusted);
  1.1140 +    }
  1.1141 +  }
  1.1142 +
  1.1143 +  iValue = m_poCoreConfig->oGetKey<int>("flash_size");
  1.1144 +  if (iValue != 64 && iValue != 128)
  1.1145 +  {
  1.1146 +    m_poCoreConfig->vSetKey("flash_size", 64);
  1.1147 +  }
  1.1148 +
  1.1149 +  iValue = m_poCoreConfig->oGetKey<int>("emulator_type");
  1.1150 +  iAdjusted = CLAMP(iValue, m_iEmulatorTypeMin, m_iEmulatorTypeMax);
  1.1151 +  if (iValue != iAdjusted)
  1.1152 +  {
  1.1153 +    m_poCoreConfig->vSetKey("emulator_type", iAdjusted);
  1.1154 +  }
  1.1155 +
  1.1156 +  sValue = m_poCoreConfig->sGetKey("screenshot_format");
  1.1157 +  if (sValue != "png" && sValue != "bmp")
  1.1158 +  {
  1.1159 +    sValue = "png";
  1.1160 +  }
  1.1161 +
  1.1162 +  // Display section
  1.1163 +  //
  1.1164 +  iValue = m_poDisplayConfig->oGetKey<int>("scale");
  1.1165 +  iAdjusted = CLAMP(iValue, m_iScaleMin, m_iScaleMax);
  1.1166 +  if (iValue != iAdjusted)
  1.1167 +  {
  1.1168 +    m_poDisplayConfig->vSetKey("scale", iAdjusted);
  1.1169 +  }
  1.1170 +
  1.1171 +  iValue = m_poDisplayConfig->oGetKey<int>("show_speed");
  1.1172 +  iAdjusted = CLAMP(iValue, m_iShowSpeedMin, m_iShowSpeedMax);
  1.1173 +  if (iValue != iAdjusted)
  1.1174 +  {
  1.1175 +    m_poDisplayConfig->vSetKey("show_speed", iAdjusted);
  1.1176 +  }
  1.1177 +
  1.1178 +  iValue = m_poDisplayConfig->oGetKey<int>("filter2x");
  1.1179 +  iAdjusted = CLAMP(iValue, m_iFilter2xMin, m_iFilter2xMax);
  1.1180 +  if (iValue != iAdjusted)
  1.1181 +  {
  1.1182 +    m_poDisplayConfig->vSetKey("filter2x", iAdjusted);
  1.1183 +  }
  1.1184 +
  1.1185 +  iValue = m_poDisplayConfig->oGetKey<int>("filterIB");
  1.1186 +  iAdjusted = CLAMP(iValue, m_iFilterIBMin, m_iFilterIBMax);
  1.1187 +  if (iValue != iAdjusted)
  1.1188 +  {
  1.1189 +    m_poDisplayConfig->vSetKey("filterIB", iAdjusted);
  1.1190 +  }
  1.1191 +
  1.1192 +  // Sound section
  1.1193 +  //
  1.1194 +  sValue = m_poSoundConfig->sGetKey("status");
  1.1195 +  if (sValue != "off" && sValue != "on" && sValue != "mute")
  1.1196 +  {
  1.1197 +    m_poSoundConfig->vSetKey("status", "on");
  1.1198 +  }
  1.1199 +
  1.1200 +  iValue = m_poSoundConfig->oGetKey<int>("quality");
  1.1201 +  iAdjusted = CLAMP(iValue, m_iSoundQualityMin, m_iSoundQualityMax);
  1.1202 +  if (iValue != iAdjusted)
  1.1203 +  {
  1.1204 +    m_poSoundConfig->vSetKey("quality", iAdjusted);
  1.1205 +  }
  1.1206 +
  1.1207 +  iValue = m_poSoundConfig->oGetKey<int>("volume");
  1.1208 +  iAdjusted = CLAMP(iValue, m_iSoundVolumeMin, m_iSoundVolumeMax);
  1.1209 +  if (iValue != iAdjusted)
  1.1210 +  {
  1.1211 +    m_poSoundConfig->vSetKey("volume", iAdjusted);
  1.1212 +  }
  1.1213 +
  1.1214 +  // Input section
  1.1215 +  //
  1.1216 +  iValue = m_poInputConfig->oGetKey<int>("active_joypad");
  1.1217 +  iAdjusted = CLAMP(iValue, m_iJoypadMin, m_iJoypadMax);
  1.1218 +  if (iValue != iAdjusted)
  1.1219 +  {
  1.1220 +    m_poInputConfig->vSetKey("active_joypad", iAdjusted);
  1.1221 +  }
  1.1222 +}
  1.1223 +
  1.1224 +void Window::vLoadConfig(const std::string & _rsFile)
  1.1225 +{
  1.1226 +  try
  1.1227 +  {
  1.1228 +    m_oConfig.vLoad(_rsFile, false, false);
  1.1229 +  }
  1.1230 +  catch (const Glib::Error & e)
  1.1231 +  {
  1.1232 +    vPopupError(e.what().c_str());
  1.1233 +  }
  1.1234 +}
  1.1235 +
  1.1236 +void Window::vSaveConfig(const std::string & _rsFile)
  1.1237 +{
  1.1238 +  try
  1.1239 +  {
  1.1240 +    m_oConfig.vSave(_rsFile);
  1.1241 +  }
  1.1242 +  catch (const Glib::Error & e)
  1.1243 +  {
  1.1244 +    vPopupError(e.what().c_str());
  1.1245 +  }
  1.1246 +}
  1.1247 +
  1.1248 +void Window::vLoadHistoryFromConfig()
  1.1249 +{
  1.1250 +  char csKey[] = "0";
  1.1251 +  for (int i = 0; i < 10; i++, csKey[0]++)
  1.1252 +  {
  1.1253 +    std::string sFile = m_poHistoryConfig->sGetKey(csKey);
  1.1254 +    if (sFile == "")
  1.1255 +    {
  1.1256 +      break;
  1.1257 +    }
  1.1258 +    m_listHistory.push_back(sFile);
  1.1259 +  }
  1.1260 +}
  1.1261 +
  1.1262 +void Window::vSaveHistoryToConfig()
  1.1263 +{
  1.1264 +  char csKey[] = "0";
  1.1265 +  for (std::list<std::string>::const_iterator it = m_listHistory.begin();
  1.1266 +       it != m_listHistory.end();
  1.1267 +       it++, csKey[0]++)
  1.1268 +  {
  1.1269 +    m_poHistoryConfig->vSetKey(csKey, *it);
  1.1270 +  }
  1.1271 +}
  1.1272 +
  1.1273 +void Window::vHistoryAdd(const std::string & _rsFile)
  1.1274 +{
  1.1275 +  if (m_poHistoryConfig->oGetKey<bool>("freeze"))
  1.1276 +  {
  1.1277 +    return;
  1.1278 +  }
  1.1279 +
  1.1280 +  m_listHistory.remove(_rsFile);
  1.1281 +  m_listHistory.push_front(_rsFile);
  1.1282 +  if (m_listHistory.size() > 10)
  1.1283 +  {
  1.1284 +    m_listHistory.pop_back();
  1.1285 +  }
  1.1286 +
  1.1287 +  vUpdateHistoryMenu();
  1.1288 +}
  1.1289 +
  1.1290 +void Window::vClearHistoryMenu()
  1.1291 +{
  1.1292 +  Gtk::Menu_Helpers::MenuList::iterator it = m_poRecentMenu->items().begin();
  1.1293 +  for (int i = 0; i < 3; i++, it++)
  1.1294 +    ;
  1.1295 +
  1.1296 +  m_poRecentMenu->items().erase(it, m_poRecentMenu->items().end());
  1.1297 +}
  1.1298 +
  1.1299 +void Window::vUpdateHistoryMenu()
  1.1300 +{
  1.1301 +  vClearHistoryMenu();
  1.1302 +
  1.1303 +  guint uiAccelKey = GDK_F1;
  1.1304 +  for (std::list<std::string>::const_iterator it = m_listHistory.begin();
  1.1305 +       it != m_listHistory.end();
  1.1306 +       it++, uiAccelKey++)
  1.1307 +  {
  1.1308 +    Gtk::Image * poImage = Gtk::manage(new Gtk::Image(Gtk::Stock::OPEN, Gtk::ICON_SIZE_MENU));
  1.1309 +    Glib::ustring sLabel = Glib::path_get_basename(*it);
  1.1310 +    VBA::ImageMenuItem * poIMI = Gtk::manage(new VBA::ImageMenuItem(*poImage, sLabel));
  1.1311 +
  1.1312 +    m_oTooltips.set_tip(*poIMI, *it);
  1.1313 +
  1.1314 +    poIMI->signal_activate().connect(SigC::bind<std::string>(
  1.1315 +                                      SigC::slot(*this, &Window::vOnRecentFile),
  1.1316 +                                      *it));
  1.1317 +
  1.1318 +    poIMI->set_accel_key(Gtk::AccelKey(uiAccelKey, Gdk::CONTROL_MASK));
  1.1319 +    poIMI->accelerate(*this);
  1.1320 +
  1.1321 +    poIMI->show();
  1.1322 +    m_poRecentMenu->items().push_back(*poIMI);
  1.1323 +  }
  1.1324 +}
  1.1325 +
  1.1326 +void Window::vLoadJoypadsFromConfig()
  1.1327 +{
  1.1328 +  m_oJoypads.clear();
  1.1329 +
  1.1330 +  for (int i = m_iJoypadMin; i <= m_iJoypadMax; i++)
  1.1331 +  {
  1.1332 +    char csPrefix[20];
  1.1333 +    snprintf(csPrefix, sizeof(csPrefix), "joypad%d_", i);
  1.1334 +    std::string sPrefix(csPrefix);
  1.1335 +
  1.1336 +    JoypadConfig oJoypadConfig;
  1.1337 +    oJoypadConfig.m_uiUp      = m_poInputConfig->oGetKey<guint>(sPrefix + "up");
  1.1338 +    oJoypadConfig.m_uiDown    = m_poInputConfig->oGetKey<guint>(sPrefix + "down");
  1.1339 +    oJoypadConfig.m_uiLeft    = m_poInputConfig->oGetKey<guint>(sPrefix + "left");
  1.1340 +    oJoypadConfig.m_uiRight   = m_poInputConfig->oGetKey<guint>(sPrefix + "right");
  1.1341 +    oJoypadConfig.m_uiA       = m_poInputConfig->oGetKey<guint>(sPrefix + "A");
  1.1342 +    oJoypadConfig.m_uiB       = m_poInputConfig->oGetKey<guint>(sPrefix + "B");
  1.1343 +    oJoypadConfig.m_uiL       = m_poInputConfig->oGetKey<guint>(sPrefix + "L");
  1.1344 +    oJoypadConfig.m_uiR       = m_poInputConfig->oGetKey<guint>(sPrefix + "R");
  1.1345 +    oJoypadConfig.m_uiSelect  = m_poInputConfig->oGetKey<guint>(sPrefix + "select");
  1.1346 +    oJoypadConfig.m_uiStart   = m_poInputConfig->oGetKey<guint>(sPrefix + "start");
  1.1347 +    oJoypadConfig.m_uiSpeed   = m_poInputConfig->oGetKey<guint>(sPrefix + "speed");
  1.1348 +    oJoypadConfig.m_uiCapture = m_poInputConfig->oGetKey<guint>(sPrefix + "capture");
  1.1349 +
  1.1350 +    m_oJoypads.push_back(oJoypadConfig);
  1.1351 +  }
  1.1352 +}
  1.1353 +
  1.1354 +void Window::vSaveJoypadsToConfig()
  1.1355 +{
  1.1356 +  for (int i = m_iJoypadMin; i <= m_iJoypadMax; i++)
  1.1357 +  {
  1.1358 +    char csPrefix[20];
  1.1359 +    snprintf(csPrefix, sizeof(csPrefix), "joypad%d_", i);
  1.1360 +    std::string sPrefix(csPrefix);
  1.1361 +
  1.1362 +    m_poInputConfig->vSetKey(sPrefix + "up",      m_oJoypads[i - 1].m_uiUp      );
  1.1363 +    m_poInputConfig->vSetKey(sPrefix + "down",    m_oJoypads[i - 1].m_uiDown    );
  1.1364 +    m_poInputConfig->vSetKey(sPrefix + "left",    m_oJoypads[i - 1].m_uiLeft    );
  1.1365 +    m_poInputConfig->vSetKey(sPrefix + "right",   m_oJoypads[i - 1].m_uiRight   );
  1.1366 +    m_poInputConfig->vSetKey(sPrefix + "A",       m_oJoypads[i - 1].m_uiA       );
  1.1367 +    m_poInputConfig->vSetKey(sPrefix + "B",       m_oJoypads[i - 1].m_uiB       );
  1.1368 +    m_poInputConfig->vSetKey(sPrefix + "L",       m_oJoypads[i - 1].m_uiL       );
  1.1369 +    m_poInputConfig->vSetKey(sPrefix + "R",       m_oJoypads[i - 1].m_uiR       );
  1.1370 +    m_poInputConfig->vSetKey(sPrefix + "select",  m_oJoypads[i - 1].m_uiSelect  );
  1.1371 +    m_poInputConfig->vSetKey(sPrefix + "start",   m_oJoypads[i - 1].m_uiStart   );
  1.1372 +    m_poInputConfig->vSetKey(sPrefix + "speed",   m_oJoypads[i - 1].m_uiSpeed   );
  1.1373 +    m_poInputConfig->vSetKey(sPrefix + "capture", m_oJoypads[i - 1].m_uiCapture );
  1.1374 +  }
  1.1375 +}
  1.1376 +
  1.1377 +void Window::vUpdateScreen()
  1.1378 +{
  1.1379 +  if (m_eCartridge == CartridgeGB)
  1.1380 +  {
  1.1381 +    if (gbBorderOn)
  1.1382 +    {
  1.1383 +      m_iScreenWidth     = m_iSGBScreenWidth;
  1.1384 +      m_iScreenHeight    = m_iSGBScreenHeight;
  1.1385 +      gbBorderLineSkip   = m_iSGBScreenWidth;
  1.1386 +      gbBorderColumnSkip = (m_iSGBScreenWidth - m_iGBScreenWidth) / 2;
  1.1387 +      gbBorderRowSkip    = (m_iSGBScreenHeight - m_iGBScreenHeight) / 2;
  1.1388 +    }
  1.1389 +    else
  1.1390 +    {
  1.1391 +      m_iScreenWidth     = m_iGBScreenWidth;
  1.1392 +      m_iScreenHeight    = m_iGBScreenHeight;
  1.1393 +      gbBorderLineSkip   = m_iGBScreenWidth;
  1.1394 +      gbBorderColumnSkip = 0;
  1.1395 +      gbBorderRowSkip    = 0;
  1.1396 +    }
  1.1397 +  }
  1.1398 +  else if (m_eCartridge == CartridgeGBA)
  1.1399 +  {
  1.1400 +    m_iScreenWidth  = m_iGBAScreenWidth;
  1.1401 +    m_iScreenHeight = m_iGBAScreenHeight;
  1.1402 +  }
  1.1403 +
  1.1404 +  g_return_if_fail(m_iScreenWidth >= 1 && m_iScreenHeight >= 1);
  1.1405 +
  1.1406 +  m_poScreenArea->vSetSize(m_iScreenWidth, m_iScreenHeight);
  1.1407 +  m_poScreenArea->vSetScale(m_poDisplayConfig->oGetKey<int>("scale"));
  1.1408 +
  1.1409 +  resize(1, 1);
  1.1410 +
  1.1411 +  if (emulating)
  1.1412 +  {
  1.1413 +    vDrawScreen();
  1.1414 +  }
  1.1415 +  else
  1.1416 +  {
  1.1417 +    vDrawDefaultScreen();
  1.1418 +  }
  1.1419 +}
  1.1420 +
  1.1421 +bool Window::bLoadROM(const std::string & _rsFile)
  1.1422 +{
  1.1423 +  vOnFileClose();
  1.1424 +
  1.1425 +  m_sRomFile = _rsFile;
  1.1426 +  const char * csFile = _rsFile.c_str();
  1.1427 +
  1.1428 +  IMAGE_TYPE eType = utilFindType(csFile);
  1.1429 +  if (eType == IMAGE_UNKNOWN)
  1.1430 +  {
  1.1431 +    vPopupError(_("Unknown file type %s"), csFile);
  1.1432 +    return false;
  1.1433 +  }
  1.1434 +
  1.1435 +  bool bLoaded = false;
  1.1436 +  if (eType == IMAGE_GB)
  1.1437 +  {
  1.1438 +    bLoaded = gbLoadRom(csFile);
  1.1439 +    if (bLoaded)
  1.1440 +    {
  1.1441 +      m_eCartridge = CartridgeGB;
  1.1442 +      m_stEmulator = GBSystem;
  1.1443 +    }
  1.1444 +  }
  1.1445 +  else if (eType == IMAGE_GBA)
  1.1446 +  {
  1.1447 +    int iSize = CPULoadRom(csFile);
  1.1448 +    bLoaded = (iSize > 0);
  1.1449 +    if (bLoaded)
  1.1450 +    {
  1.1451 +      m_eCartridge = CartridgeGBA;
  1.1452 +      m_stEmulator = GBASystem;
  1.1453 +
  1.1454 +      useBios = m_poCoreConfig->oGetKey<bool>("use_bios_file");
  1.1455 +      //CPUInit(m_poCoreConfig->sGetKey("bios_file").c_str(), useBios);
  1.1456 +      CPUInit();
  1.1457 +      CPUReset();
  1.1458 +
  1.1459 +      // If the bios file was rejected by CPUInit
  1.1460 +      if (m_poCoreConfig->oGetKey<bool>("use_bios_file") && ! useBios)
  1.1461 +      {
  1.1462 +        m_poUseBiosItem->set_active(false);
  1.1463 +        m_poUseBiosItem->set_sensitive(false);
  1.1464 +        m_poCoreConfig->vSetKey("bios_file", "");
  1.1465 +      }
  1.1466 +    }
  1.1467 +  }
  1.1468 +
  1.1469 +  if (! bLoaded)
  1.1470 +  {
  1.1471 +    return false;
  1.1472 +  }
  1.1473 +
  1.1474 +  vLoadBattery();
  1.1475 +  vUpdateScreen();
  1.1476 +
  1.1477 +  debugger = false; // May cause conflicts
  1.1478 +  emulating = 1;
  1.1479 +  m_bWasEmulating = false;
  1.1480 +  m_uiThrottleDelay = 0;
  1.1481 +
  1.1482 +  if (m_eCartridge == CartridgeGBA)
  1.1483 +  {
  1.1484 +    soundSetQuality(m_eSoundQuality);
  1.1485 +  }
  1.1486 +  else
  1.1487 +  {
  1.1488 +    gbSoundSetQuality(m_eSoundQuality);
  1.1489 +  }
  1.1490 +
  1.1491 +  vUpdateGameSlots();
  1.1492 +  vHistoryAdd(_rsFile);
  1.1493 +
  1.1494 +  for (std::list<Gtk::Widget *>::iterator it = m_listSensitiveWhenPlaying.begin();
  1.1495 +       it != m_listSensitiveWhenPlaying.end();
  1.1496 +       it++)
  1.1497 +  {
  1.1498 +    (*it)->set_sensitive();
  1.1499 +  }
  1.1500 +
  1.1501 +  if (m_poCoreConfig->oGetKey<bool>("load_game_auto"))
  1.1502 +  {
  1.1503 +    vOnLoadGameMostRecent();
  1.1504 +  }
  1.1505 +
  1.1506 +  vStartEmu();
  1.1507 +
  1.1508 +  return true;
  1.1509 +}
  1.1510 +
  1.1511 +void Window::vPopupError(const char * _csFormat, ...)
  1.1512 +{
  1.1513 +  va_list args;
  1.1514 +  va_start(args, _csFormat);
  1.1515 +  char * csMsg = g_strdup_vprintf(_csFormat, args);
  1.1516 +  va_end(args);
  1.1517 +
  1.1518 +  Gtk::MessageDialog oDialog(*this,
  1.1519 +                             csMsg,
  1.1520 +#ifndef GTKMM20
  1.1521 +                             false,
  1.1522 +#endif // ! GTKMM20
  1.1523 +                             Gtk::MESSAGE_ERROR,
  1.1524 +                             Gtk::BUTTONS_OK);
  1.1525 +  oDialog.run();
  1.1526 +  g_free(csMsg);
  1.1527 +}
  1.1528 +
  1.1529 +void Window::vPopupErrorV(const char * _csFormat, va_list _args)
  1.1530 +{
  1.1531 +  char * csMsg = g_strdup_vprintf(_csFormat, _args);
  1.1532 +
  1.1533 +  Gtk::MessageDialog oDialog(*this,
  1.1534 +                             csMsg,
  1.1535 +#ifndef GTKMM20
  1.1536 +                             false,
  1.1537 +#endif // ! GTKMM20
  1.1538 +                             Gtk::MESSAGE_ERROR,
  1.1539 +                             Gtk::BUTTONS_OK);
  1.1540 +  oDialog.run();
  1.1541 +  g_free(csMsg);
  1.1542 +}
  1.1543 +
  1.1544 +void Window::vDrawScreen()
  1.1545 +{
  1.1546 +  m_poScreenArea->vDrawPixels(pix);
  1.1547 +}
  1.1548 +
  1.1549 +void Window::vDrawDefaultScreen()
  1.1550 +{
  1.1551 +  m_poScreenArea->vDrawColor(0x000000); // Black
  1.1552 +}
  1.1553 +
  1.1554 +void Window::vSetDefaultTitle()
  1.1555 +{
  1.1556 +  set_title("VBA");
  1.1557 +}
  1.1558 +
  1.1559 +void Window::vShowSpeed(int _iSpeed)
  1.1560 +{
  1.1561 +  char csTitle[50];
  1.1562 +
  1.1563 +  if (m_eShowSpeed == ShowPercentage)
  1.1564 +  {
  1.1565 +    snprintf(csTitle, 50, "VBA - %d%%", _iSpeed);
  1.1566 +    set_title(csTitle);
  1.1567 +  }
  1.1568 +  else if (m_eShowSpeed == ShowDetailed)
  1.1569 +  {
  1.1570 +    snprintf(csTitle, 50, "VBA - %d%% (%d, %d fps)",
  1.1571 +             _iSpeed, systemFrameSkip, systemFPS);
  1.1572 +    set_title(csTitle);
  1.1573 +  }
  1.1574 +}
  1.1575 +
  1.1576 +void Window::vComputeFrameskip(int _iRate)
  1.1577 +{
  1.1578 +  static u32 uiLastTime = 0;
  1.1579 +  static int iFrameskipAdjust = 0;
  1.1580 +
  1.1581 +  u32 uiTime = SDL_GetTicks();
  1.1582 +
  1.1583 +  if (m_bWasEmulating)
  1.1584 +  {
  1.1585 +    int iWantedSpeed = 100;
  1.1586 +
  1.1587 +    if (m_iThrottle > 0)
  1.1588 +    {
  1.1589 +      if (! speedup)
  1.1590 +      {
  1.1591 +        u32 uiDiff  = uiTime - m_uiThrottleLastTime;
  1.1592 +        int iTarget = 1000000 / (_iRate * m_iThrottle);
  1.1593 +        int iDelay  = iTarget - uiDiff;
  1.1594 +        if (iDelay > 0)
  1.1595 +        {
  1.1596 +          m_uiThrottleDelay = iDelay;
  1.1597 +        }
  1.1598 +      }
  1.1599 +      iWantedSpeed = m_iThrottle;
  1.1600 +    }
  1.1601 +
  1.1602 +    if (m_bAutoFrameskip)
  1.1603 +    {
  1.1604 +      u32 uiDiff = uiTime - uiLastTime;
  1.1605 +      int iSpeed = iWantedSpeed;
  1.1606 +
  1.1607 +      if (uiDiff != 0)
  1.1608 +      {
  1.1609 +        iSpeed = (1000000 / _iRate) / uiDiff;
  1.1610 +      }
  1.1611 +
  1.1612 +      if (iSpeed >= iWantedSpeed - 2)
  1.1613 +      {
  1.1614 +        iFrameskipAdjust++;
  1.1615 +        if (iFrameskipAdjust >= 3)
  1.1616 +        {
  1.1617 +          iFrameskipAdjust = 0;
  1.1618 +          if (systemFrameSkip > 0)
  1.1619 +          {
  1.1620 +            systemFrameSkip--;
  1.1621 +          }
  1.1622 +        }
  1.1623 +      }
  1.1624 +      else
  1.1625 +      {
  1.1626 +        if (iSpeed < iWantedSpeed - 20)
  1.1627 +        {
  1.1628 +          iFrameskipAdjust -= ((iWantedSpeed - 10) - iSpeed) / 5;
  1.1629 +        }
  1.1630 +        else if (systemFrameSkip < 9)
  1.1631 +        {
  1.1632 +          iFrameskipAdjust--;
  1.1633 +        }
  1.1634 +
  1.1635 +        if (iFrameskipAdjust <= -2)
  1.1636 +        {
  1.1637 +          iFrameskipAdjust += 2;
  1.1638 +          if (systemFrameSkip < 9)
  1.1639 +          {
  1.1640 +            systemFrameSkip++;
  1.1641 +          }
  1.1642 +        }
  1.1643 +      }
  1.1644 +    }
  1.1645 +  }
  1.1646 +  else
  1.1647 +  {
  1.1648 +    m_bWasEmulating = true;
  1.1649 +  }
  1.1650 +
  1.1651 +  uiLastTime = uiTime;
  1.1652 +  m_uiThrottleLastTime = uiTime;
  1.1653 +}
  1.1654 +
  1.1655 +void Window::vCaptureScreen(int _iNum)
  1.1656 +{
  1.1657 +  std::string sBaseName;
  1.1658 +  std::string sCaptureDir = m_poDirConfig->sGetKey("captures");
  1.1659 +  if (sCaptureDir == "")
  1.1660 +  {
  1.1661 +    sBaseName = sCutSuffix(m_sRomFile);
  1.1662 +  }
  1.1663 +  else
  1.1664 +  {
  1.1665 +    sBaseName = sCaptureDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile));
  1.1666 +  }
  1.1667 +  std::string sFormat = m_poCoreConfig->sGetKey("screenshot_format");
  1.1668 +
  1.1669 +  char * csFile = g_strdup_printf("%s_%02d.%s",
  1.1670 +                                  sBaseName.c_str(),
  1.1671 +                                  _iNum,
  1.1672 +                                  sFormat.c_str());
  1.1673 +  if (sFormat == "png")
  1.1674 +  {
  1.1675 +    m_stEmulator.emuWritePNG(csFile);
  1.1676 +  }
  1.1677 +  else
  1.1678 +  {
  1.1679 +    m_stEmulator.emuWriteBMP(csFile);
  1.1680 +  }
  1.1681 +  g_free(csFile);
  1.1682 +}
  1.1683 +
  1.1684 +u32 Window::uiReadJoypad()
  1.1685 +{
  1.1686 +  u32 uiJoypad = m_uiJoypadState;
  1.1687 +
  1.1688 +  if (m_uiAutofireState != 0)
  1.1689 +  {
  1.1690 +    uiJoypad &= ~m_uiAutofireState;
  1.1691 +    if (m_bAutofireToggle)
  1.1692 +    {
  1.1693 +      uiJoypad |= m_uiAutofireState;
  1.1694 +    }
  1.1695 +    m_bAutofireToggle = ! m_bAutofireToggle;
  1.1696 +  }
  1.1697 +
  1.1698 +  return uiJoypad;
  1.1699 +}
  1.1700 +
  1.1701 +void Window::vCreateFileOpenDialog()
  1.1702 +{
  1.1703 +  if (m_poFileOpenDialog != NULL)
  1.1704 +  {
  1.1705 +    return;
  1.1706 +  }
  1.1707 +
  1.1708 +  std::string sGBDir  = m_poDirConfig->sGetKey("gb_roms");
  1.1709 +  std::string sGBADir = m_poDirConfig->sGetKey("gba_roms");
  1.1710 +
  1.1711 +#ifdef GTKMM20
  1.1712 +
  1.1713 +  Gtk::FileSelection * poDialog = new Gtk::FileSelection(_("Open"));
  1.1714 +  poDialog->set_transient_for(*this);
  1.1715 +
  1.1716 +  if (sGBADir != "")
  1.1717 +  {
  1.1718 +    poDialog->set_filename(sGBADir + "/");
  1.1719 +  }
  1.1720 +  else if (sGBDir != "")
  1.1721 +  {
  1.1722 +    poDialog->set_filename(sGBDir + "/");
  1.1723 +  }
  1.1724 +
  1.1725 +#else // ! GTKMM20
  1.1726 +
  1.1727 +  Gtk::FileChooserDialog * poDialog = new Gtk::FileChooserDialog(*this, _("Open"));
  1.1728 +  poDialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
  1.1729 +  poDialog->add_button(Gtk::Stock::OPEN,   Gtk::RESPONSE_OK);
  1.1730 +
  1.1731 +  if (sGBDir != "")
  1.1732 +  {
  1.1733 +    poDialog->add_shortcut_folder(sGBDir);
  1.1734 +    poDialog->set_current_folder(sGBDir);
  1.1735 +  }
  1.1736 +
  1.1737 +  if (sGBADir != "" && sGBADir != sGBDir)
  1.1738 +  {
  1.1739 +    poDialog->add_shortcut_folder(sGBADir);
  1.1740 +    poDialog->set_current_folder(sGBADir);
  1.1741 +  }
  1.1742 +
  1.1743 +  const char * acsPattern[] =
  1.1744 +  {
  1.1745 +    // GBA
  1.1746 +    "*.[bB][iI][nN]", "*.[aA][gG][bB]", "*.[gG][bB][aA]",
  1.1747 +    // GB
  1.1748 +    "*.[gG][bB]", "*.[sS][gG][bB]", "*.[cC][gG][bB]", "*.[gG][bB][cC]",
  1.1749 +    // Both
  1.1750 +    "*.[mM][bB]", "*.[eE][lL][fF]", "*.[zZ][iI][pP]", "*.[zZ]", "*.[gG][zZ]"
  1.1751 +  };
  1.1752 +
  1.1753 +  Gtk::FileFilter oAllGBAFilter;
  1.1754 +  oAllGBAFilter.set_name(_("All Gameboy Advance files"));
  1.1755 +  for (guint i = 0; i < G_N_ELEMENTS(acsPattern); i++)
  1.1756 +  {
  1.1757 +    oAllGBAFilter.add_pattern(acsPattern[i]);
  1.1758 +  }
  1.1759 +
  1.1760 +  Gtk::FileFilter oGBAFilter;
  1.1761 +  oGBAFilter.set_name(_("Gameboy Advance files"));
  1.1762 +  for (int i = 0; i < 3; i++)
  1.1763 +  {
  1.1764 +    oGBAFilter.add_pattern(acsPattern[i]);
  1.1765 +  }
  1.1766 +
  1.1767 +  Gtk::FileFilter oGBFilter;
  1.1768 +  oGBFilter.set_name(_("Gameboy files"));
  1.1769 +  for (int i = 3; i < 7; i++)
  1.1770 +  {
  1.1771 +    oGBFilter.add_pattern(acsPattern[i]);
  1.1772 +  }
  1.1773 +
  1.1774 +  poDialog->add_filter(oAllGBAFilter);
  1.1775 +  poDialog->add_filter(oGBAFilter);
  1.1776 +  poDialog->add_filter(oGBFilter);
  1.1777 +
  1.1778 +#endif // ! GTKMM20
  1.1779 +
  1.1780 +  m_poFileOpenDialog = poDialog;
  1.1781 +}
  1.1782 +
  1.1783 +void Window::vLoadBattery()
  1.1784 +{
  1.1785 +  std::string sBattery;
  1.1786 +  std::string sDir = m_poDirConfig->sGetKey("batteries");
  1.1787 +  if (sDir == "")
  1.1788 +  {
  1.1789 +    sBattery = sCutSuffix(m_sRomFile) + ".sav";
  1.1790 +  }
  1.1791 +  else
  1.1792 +  {
  1.1793 +    sBattery = sDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile)) + ".sav";
  1.1794 +  }
  1.1795 +
  1.1796 +  if (m_stEmulator.emuReadBattery(sBattery.c_str()))
  1.1797 +  {
  1.1798 +    systemScreenMessage(_("Loaded battery"));
  1.1799 +  }
  1.1800 +}
  1.1801 +
  1.1802 +void Window::vSaveBattery()
  1.1803 +{
  1.1804 +  std::string sBattery;
  1.1805 +  std::string sDir = m_poDirConfig->sGetKey("batteries");
  1.1806 +  if (sDir == "")
  1.1807 +  {
  1.1808 +    sBattery = sCutSuffix(m_sRomFile) + ".sav";
  1.1809 +  }
  1.1810 +  else
  1.1811 +  {
  1.1812 +    sBattery = sDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile)) + ".sav";
  1.1813 +  }
  1.1814 +
  1.1815 +  if (m_stEmulator.emuWriteBattery(sBattery.c_str()))
  1.1816 +  {
  1.1817 +    systemScreenMessage(_("Saved battery"));
  1.1818 +  }
  1.1819 +}
  1.1820 +
  1.1821 +void Window::vStartEmu()
  1.1822 +{
  1.1823 +  if (m_oEmuSig.connected())
  1.1824 +  {
  1.1825 +    return;
  1.1826 +  }
  1.1827 +
  1.1828 +  m_oEmuSig = Glib::signal_idle().connect(SigC::slot(*this, &Window::bOnEmuIdle),
  1.1829 +                                          Glib::PRIORITY_DEFAULT_IDLE);
  1.1830 +}
  1.1831 +
  1.1832 +void Window::vStopEmu()
  1.1833 +{
  1.1834 +  m_oEmuSig.disconnect();
  1.1835 +  m_bWasEmulating = false;
  1.1836 +}
  1.1837 +
  1.1838 +void Window::vSetThrottle(int _iPercent)
  1.1839 +{
  1.1840 +  m_iThrottle = _iPercent;
  1.1841 +  m_poCoreConfig->vSetKey("throttle", _iPercent);
  1.1842 +}
  1.1843 +
  1.1844 +void Window::vSelectBestThrottleItem()
  1.1845 +{
  1.1846 +  struct
  1.1847 +  {
  1.1848 +    const char * m_csName;
  1.1849 +    const int    m_iThrottle;
  1.1850 +  }
  1.1851 +  astThrottle[] =
  1.1852 +  {
  1.1853 +    { "ThrottleNoThrottle",   0 },
  1.1854 +    { "Throttle25",          25 },
  1.1855 +    { "Throttle50",          50 },
  1.1856 +    { "Throttle100",        100 },
  1.1857 +    { "Throttle150",        150 },
  1.1858 +    { "Throttle200",        200 }
  1.1859 +  };
  1.1860 +  for (guint i = 0; i < G_N_ELEMENTS(astThrottle); i++)
  1.1861 +  {
  1.1862 +    Gtk::CheckMenuItem * poCMI;
  1.1863 +    poCMI = dynamic_cast<Gtk::CheckMenuItem *>(m_poXml->get_widget(astThrottle[i].m_csName));
  1.1864 +    if (astThrottle[i].m_iThrottle == m_iThrottle)
  1.1865 +    {
  1.1866 +      poCMI->set_active();
  1.1867 +    }
  1.1868 +  }
  1.1869 +}
  1.1870 +
  1.1871 +void Window::vUpdateGameSlots()
  1.1872 +{
  1.1873 +  if (m_eCartridge == CartridgeNone)
  1.1874 +  {
  1.1875 +    std::string sDateTime = _("----/--/-- --:--:--");
  1.1876 +
  1.1877 +    for (int i = 0; i < 10; i++)
  1.1878 +    {
  1.1879 +      char csPrefix[10];
  1.1880 +      snprintf(csPrefix, sizeof(csPrefix), "%2d ", i + 1);
  1.1881 +
  1.1882 +      Gtk::Label * poLabel;
  1.1883 +      poLabel = dynamic_cast<Gtk::Label *>(m_apoLoadGameItem[i]->get_child());
  1.1884 +      poLabel->set_text(csPrefix + sDateTime);
  1.1885 +      m_apoLoadGameItem[i]->set_sensitive(false);
  1.1886 +
  1.1887 +      poLabel = dynamic_cast<Gtk::Label *>(m_apoSaveGameItem[i]->get_child());
  1.1888 +      poLabel->set_text(csPrefix + sDateTime);
  1.1889 +      m_apoSaveGameItem[i]->set_sensitive(false);
  1.1890 +
  1.1891 +      m_astGameSlot[i].m_bEmpty = true;
  1.1892 +    }
  1.1893 +  }
  1.1894 +  else
  1.1895 +  {
  1.1896 +    std::string sFileBase;
  1.1897 +    std::string sDir = m_poDirConfig->sGetKey("saves");
  1.1898 +    if (sDir == "")
  1.1899 +    {
  1.1900 +      sFileBase = sCutSuffix(m_sRomFile);
  1.1901 +    }
  1.1902 +    else
  1.1903 +    {
  1.1904 +      sFileBase = sDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile));
  1.1905 +    }
  1.1906 +
  1.1907 +    const char * csDateFormat = _("%Y/%m/%d %H:%M:%S");
  1.1908 +
  1.1909 +    for (int i = 0; i < 10; i++)
  1.1910 +    {
  1.1911 +      char csPrefix[10];
  1.1912 +      snprintf(csPrefix, sizeof(csPrefix), "%2d ", i + 1);
  1.1913 +
  1.1914 +      char csSlot[10];
  1.1915 +      snprintf(csSlot, sizeof(csSlot), "%d", i + 1);
  1.1916 +      m_astGameSlot[i].m_sFile = sFileBase + csSlot + ".sgm";
  1.1917 +
  1.1918 +      std::string sDateTime;
  1.1919 +      struct stat stStat;
  1.1920 +      if (stat(m_astGameSlot[i].m_sFile.c_str(), &stStat) == -1)
  1.1921 +      {
  1.1922 +        sDateTime = _("----/--/-- --:--:--");
  1.1923 +        m_astGameSlot[i].m_bEmpty = true;
  1.1924 +      }
  1.1925 +      else
  1.1926 +      {
  1.1927 +        char csDateTime[30];
  1.1928 +        strftime(csDateTime, sizeof(csDateTime), csDateFormat,
  1.1929 +                 localtime(&stStat.st_mtime));
  1.1930 +        sDateTime = csDateTime;
  1.1931 +        m_astGameSlot[i].m_bEmpty = false;
  1.1932 +        m_astGameSlot[i].m_uiTime = stStat.st_mtime;
  1.1933 +      }
  1.1934 +
  1.1935 +      Gtk::Label * poLabel;
  1.1936 +      poLabel = dynamic_cast<Gtk::Label *>(m_apoLoadGameItem[i]->get_child());
  1.1937 +      poLabel->set_text(csPrefix + sDateTime);
  1.1938 +      m_apoLoadGameItem[i]->set_sensitive(! m_astGameSlot[i].m_bEmpty);
  1.1939 +
  1.1940 +      poLabel = dynamic_cast<Gtk::Label *>(m_apoSaveGameItem[i]->get_child());
  1.1941 +      poLabel->set_text(csPrefix + sDateTime);
  1.1942 +      m_apoSaveGameItem[i]->set_sensitive();
  1.1943 +    }
  1.1944 +  }
  1.1945 +}
  1.1946 +
  1.1947 +} // VBA namespace