Mercurial > vba-clojure
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