Mercurial > vba-clojure
view src/gtk/window.cpp @ 5:8fe0c57e53d2
concentrating on lua first
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:39:40 -0600 |
parents | f9f4f1b99eed |
children |
line wrap: on
line source
1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.2 // Copyright (C) 1999-2003 Forgotten3 // Copyright (C) 2004 Forgotten and the VBA development team5 // This program is free software; you can redistribute it and/or modify6 // it under the terms of the GNU General Public License as published by7 // the Free Software Foundation; either version 2, or(at your option)8 // any later version.9 //10 // This program is distributed in the hope that it will be useful,11 // but WITHOUT ANY WARRANTY; without even the implied warranty of12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13 // GNU General Public License for more details.14 //15 // You should have received a copy of the GNU General Public License16 // along with this program; if not, write to the Free Software Foundation,17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.19 #include "window.h"21 #include <sys/stat.h>23 #include <stdio.h>24 #include <time.h>26 #include <SDL.h>28 #include "../gba/GBA.h"29 #include "../gba/GBAGlobals.h"30 #include "../gba/GBASound.h"31 #include "../gb/GB.h"32 #include "../gb/gbGlobals.h"33 #include "../gb/gbPrinter.h"34 #include "../common/Util.h"36 #include "menuitem.h"37 #include "tools.h"38 #include "intl.h"40 extern int systemRenderedFrames;41 extern int systemFPS;42 extern bool debugger;43 extern int RGB_LOW_BITS_MASK;44 extern void (*dbgMain)();45 extern void (*dbgSignal)(int, int);46 extern void (*dbgOutput)(char *, u32);47 extern void remoteInit();48 extern void remoteCleanUp();49 extern void remoteStubMain();50 extern void remoteStubSignal(int, int);51 extern void remoteOutput(char *, u32);52 extern void remoteSetProtocol(int);53 extern void remoteSetPort(int);55 #ifdef MMX56 extern "C" bool cpu_mmx;57 #endif // MMX59 namespace VBA60 {62 using Gnome::Glade::Xml;64 Window * Window::m_poInstance = NULL;66 Window::Window(GtkWindow * _pstWindow, const Glib::RefPtr<Xml> & _poXml) :67 Gtk::Window (_pstWindow),68 m_iGBScreenWidth (160),69 m_iGBScreenHeight (144),70 m_iSGBScreenWidth (256),71 m_iSGBScreenHeight(224),72 m_iGBAScreenWidth (240),73 m_iGBAScreenHeight(160),74 m_iFrameskipMin (0),75 m_iFrameskipMax (9),76 m_iThrottleMin (5),77 m_iThrottleMax (1000),78 m_iScaleMin (1),79 m_iScaleMax (6),80 m_iShowSpeedMin (ShowNone),81 m_iShowSpeedMax (ShowDetailed),82 m_iSaveTypeMin (SaveAuto),83 m_iSaveTypeMax (SaveNone),84 m_iSoundQualityMin(Sound44K),85 m_iSoundQualityMax(Sound11K),86 m_iSoundVolumeMin (Sound100),87 m_iSoundVolumeMax (Sound50),88 m_iEmulatorTypeMin(EmulatorAuto),89 m_iEmulatorTypeMax(EmulatorSGB2),90 m_iFilter2xMin (FirstFilter),91 m_iFilter2xMax (LastFilter),92 m_iFilterIBMin (FirstFilterIB),93 m_iFilterIBMax (LastFilterIB),94 m_iJoypadMin (1),95 m_iJoypadMax (4)96 {97 m_poXml = _poXml;98 m_poFileOpenDialog = NULL;99 m_iScreenWidth = m_iGBAScreenWidth;100 m_iScreenHeight = m_iGBAScreenHeight;101 m_eCartridge = CartridgeNone;102 m_uiJoypadState = 0;104 vInitSystem();105 vInitSDL();107 Gtk::Container * poC;108 poC = dynamic_cast<Gtk::Container *>(_poXml->get_widget("ScreenContainer"));109 m_poScreenArea = Gtk::manage(new ScreenArea(m_iScreenWidth, m_iScreenHeight));110 poC->add(*m_poScreenArea);111 vDrawDefaultScreen();112 m_poScreenArea->show();114 // Get config115 //116 vInitConfig();118 m_sUserDataDir = Glib::get_home_dir() + "/.gvba";119 m_sConfigFile = m_sUserDataDir + "/config";121 if (! Glib::file_test(m_sUserDataDir, Glib::FILE_TEST_EXISTS))122 {123 mkdir(m_sUserDataDir.c_str(), 0777);124 }125 if (Glib::file_test(m_sConfigFile, Glib::FILE_TEST_EXISTS))126 {127 vLoadConfig(m_sConfigFile);128 vCheckConfig();129 }130 else131 {132 vSaveConfig(m_sConfigFile);133 }135 vCreateFileOpenDialog();136 vLoadHistoryFromConfig();137 vLoadJoypadsFromConfig();139 Gtk::MenuItem * poMI;140 Gtk::CheckMenuItem * poCMI;142 // File menu143 //144 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileOpen"));145 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileOpen));147 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileLoad"));148 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileLoad));149 m_listSensitiveWhenPlaying.push_back(poMI);151 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileSave"));152 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileSave));153 m_listSensitiveWhenPlaying.push_back(poMI);155 for (int i = 0; i < 10; i++)156 {157 char csName[20];158 snprintf(csName, 20, "LoadGameSlot%d", i + 1);159 m_apoLoadGameItem[i] = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget(csName));160 snprintf(csName, 20, "SaveGameSlot%d", i + 1);161 m_apoSaveGameItem[i] = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget(csName));163 m_apoLoadGameItem[i]->signal_activate().connect(SigC::bind<int>(164 SigC::slot(*this, &Window::vOnLoadGame),165 i + 1));166 m_apoSaveGameItem[i]->signal_activate().connect(SigC::bind<int>(167 SigC::slot(*this, &Window::vOnSaveGame),168 i + 1));169 }170 vUpdateGameSlots();172 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("LoadGameMostRecent"));173 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnLoadGameMostRecent));174 m_listSensitiveWhenPlaying.push_back(poMI);176 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("LoadGameAuto"));177 poCMI->set_active(m_poCoreConfig->oGetKey<bool>("load_game_auto"));178 vOnLoadGameAutoToggled(poCMI);179 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(180 SigC::slot(*this, &Window::vOnLoadGameAutoToggled),181 poCMI));183 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("SaveGameOldest"));184 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnSaveGameOldest));185 m_listSensitiveWhenPlaying.push_back(poMI);187 m_poFilePauseItem = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("FilePause"));188 m_poFilePauseItem->set_active(false);189 vOnFilePauseToggled(m_poFilePauseItem);190 m_poFilePauseItem->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(191 SigC::slot(*this, &Window::vOnFilePauseToggled),192 m_poFilePauseItem));193 m_listSensitiveWhenPlaying.push_back(m_poFilePauseItem);195 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileReset"));196 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileReset));197 m_listSensitiveWhenPlaying.push_back(poMI);199 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileScreenCapture"));200 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileScreenCapture));201 m_listSensitiveWhenPlaying.push_back(poMI);203 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileClose"));204 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileClose));205 m_listSensitiveWhenPlaying.push_back(poMI);207 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileExit"));208 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileExit));210 // Recent menu211 //212 m_poRecentMenu = dynamic_cast<Gtk::Menu *>(_poXml->get_widget("RecentMenu_menu"));213 vUpdateHistoryMenu();215 m_poRecentResetItem = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("RecentReset"));216 m_poRecentResetItem->signal_activate().connect(SigC::slot(*this, &Window::vOnRecentReset));218 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("RecentFreeze"));219 poCMI->set_active(m_poHistoryConfig->oGetKey<bool>("freeze"));220 vOnRecentFreezeToggled(poCMI);221 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(222 SigC::slot(*this, &Window::vOnRecentFreezeToggled),223 poCMI));225 // Import menu226 //227 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("ImportBatteryFile"));228 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnImportBatteryFile));229 m_listSensitiveWhenPlaying.push_back(poMI);231 // Export menu232 //233 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("ExportBatteryFile"));234 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnExportBatteryFile));235 m_listSensitiveWhenPlaying.push_back(poMI);237 // Frameskip menu238 //239 struct240 {241 const char * m_csName;242 const int m_iFrameskip;243 }244 astFrameskip[] =245 {246 { "FrameskipAutomatic", -1 },247 { "Frameskip0", 0 },248 { "Frameskip1", 1 },249 { "Frameskip2", 2 },250 { "Frameskip3", 3 },251 { "Frameskip4", 4 },252 { "Frameskip5", 5 },253 { "Frameskip6", 6 },254 { "Frameskip7", 7 },255 { "Frameskip8", 8 },256 { "Frameskip9", 9 }257 };258 int iDefaultFrameskip;259 if (m_poCoreConfig->sGetKey("frameskip") == "auto")260 {261 iDefaultFrameskip = -1;262 }263 else264 {265 iDefaultFrameskip = m_poCoreConfig->oGetKey<int>("frameskip");266 }267 for (guint i = 0; i < G_N_ELEMENTS(astFrameskip); i++)268 {269 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astFrameskip[i].m_csName));270 if (astFrameskip[i].m_iFrameskip == iDefaultFrameskip)271 {272 poCMI->set_active();273 vOnFrameskipToggled(poCMI, iDefaultFrameskip);274 }275 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(276 SigC::slot(*this, &Window::vOnFrameskipToggled),277 poCMI, astFrameskip[i].m_iFrameskip));278 }280 // Throttle menu281 //282 struct283 {284 const char * m_csName;285 const int m_iThrottle;286 }287 astThrottle[] =288 {289 { "ThrottleNoThrottle", 0 },290 { "Throttle25", 25 },291 { "Throttle50", 50 },292 { "Throttle100", 100 },293 { "Throttle150", 150 },294 { "Throttle200", 200 }295 };296 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("ThrottleOther"));297 poCMI->set_active();298 poCMI->signal_activate().connect(SigC::bind<Gtk::CheckMenuItem *>(299 SigC::slot(*this, &Window::vOnThrottleOther),300 poCMI));302 int iDefaultThrottle = m_poCoreConfig->oGetKey<int>("throttle");303 for (guint i = 0; i < G_N_ELEMENTS(astThrottle); i++)304 {305 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astThrottle[i].m_csName));306 if (astThrottle[i].m_iThrottle == iDefaultThrottle)307 {308 poCMI->set_active();309 }310 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(311 SigC::slot(*this, &Window::vOnThrottleToggled),312 poCMI, astThrottle[i].m_iThrottle));313 }314 vSetThrottle(iDefaultThrottle);316 // Video menu317 //318 struct319 {320 const char * m_csName;321 const int m_iScale;322 }323 astVideoScale[] =324 {325 { "Video1x", 1 },326 { "Video2x", 2 },327 { "Video3x", 3 },328 { "Video4x", 4 },329 { "Video5x", 5 },330 { "Video6x", 6 }331 };332 int iDefaultScale = m_poDisplayConfig->oGetKey<int>("scale");333 for (guint i = 0; i < G_N_ELEMENTS(astVideoScale); i++)334 {335 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astVideoScale[i].m_csName));336 if (astVideoScale[i].m_iScale == iDefaultScale)337 {338 poCMI->set_active();339 vOnVideoScaleToggled(poCMI, iDefaultScale);340 }341 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(342 SigC::slot(*this, &Window::vOnVideoScaleToggled),343 poCMI, astVideoScale[i].m_iScale));344 }346 // Layers menu347 //348 struct349 {350 const char * m_csName;351 const char * m_csKey;352 const int m_iLayer;353 }354 astLayer[] =355 {356 { "LayersBg0", "layer_bg0", 0 },357 { "LayersBg1", "layer_bg1", 1 },358 { "LayersBg2", "layer_bg2", 2 },359 { "LayersBg3", "layer_bg3", 3 },360 { "LayersObj", "layer_obj", 4 },361 { "LayersWin0", "layer_win0", 5 },362 { "LayersWin1", "layer_win1", 6 },363 { "LayersObjWin", "layer_objwin", 7 }364 };365 for (guint i = 0; i < G_N_ELEMENTS(astLayer); i++)366 {367 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astLayer[i].m_csName));368 poCMI->set_active(m_poCoreConfig->oGetKey<bool>(astLayer[i].m_csKey));369 vOnLayerToggled(poCMI, astLayer[i].m_iLayer);370 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(371 SigC::slot(*this, &Window::vOnLayerToggled),372 poCMI, astLayer[i].m_iLayer));373 }375 // Emulator menu376 //377 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("EmulatorDirectories"));378 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnDirectories));380 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("EmulatorPauseWhenInactive"));381 poCMI->set_active(m_poDisplayConfig->oGetKey<bool>("pause_when_inactive"));382 vOnPauseWhenInactiveToggled(poCMI);383 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(384 SigC::slot(*this, &Window::vOnPauseWhenInactiveToggled),385 poCMI));387 m_poUseBiosItem = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("EmulatorUseBios"));388 m_poUseBiosItem->set_active(m_poCoreConfig->oGetKey<bool>("use_bios_file"));389 if (m_poCoreConfig->sGetKey("bios_file") == "")390 {391 m_poUseBiosItem->set_sensitive(false);392 }393 m_poUseBiosItem->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(394 SigC::slot(*this, &Window::vOnUseBiosToggled),395 m_poUseBiosItem));397 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("EmulatorSelectBios"));398 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnSelectBios));400 // Show speed menu401 //402 struct403 {404 const char * m_csName;405 const EShowSpeed m_eShowSpeed;406 }407 astShowSpeed[] =408 {409 { "ShowSpeedNone", ShowNone },410 { "ShowSpeedPercentage", ShowPercentage },411 { "ShowSpeedDetailed", ShowDetailed }412 };413 EShowSpeed eDefaultShowSpeed = (EShowSpeed)m_poDisplayConfig->oGetKey<int>("show_speed");414 for (guint i = 0; i < G_N_ELEMENTS(astShowSpeed); i++)415 {416 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astShowSpeed[i].m_csName));417 if (astShowSpeed[i].m_eShowSpeed == eDefaultShowSpeed)418 {419 poCMI->set_active();420 vOnShowSpeedToggled(poCMI, eDefaultShowSpeed);421 }422 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(423 SigC::slot(*this, &Window::vOnShowSpeedToggled),424 poCMI, astShowSpeed[i].m_eShowSpeed));425 }427 // Save type menu428 //429 struct430 {431 const char * m_csName;432 const ESaveType m_eSaveType;433 }434 astSaveType[] =435 {436 { "SaveTypeAutomatic", SaveAuto },437 { "SaveTypeEeprom", SaveEEPROM },438 { "SaveTypeSram", SaveSRAM },439 { "SaveTypeFlash", SaveFlash },440 { "SaveTypeEepromSensor", SaveEEPROMSensor },441 { "SaveTypeNone", SaveNone }442 };443 ESaveType eDefaultSaveType = (ESaveType)m_poCoreConfig->oGetKey<int>("save_type");444 for (guint i = 0; i < G_N_ELEMENTS(astSaveType); i++)445 {446 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astSaveType[i].m_csName));447 if (astSaveType[i].m_eSaveType == eDefaultSaveType)448 {449 poCMI->set_active();450 vOnSaveTypeToggled(poCMI, eDefaultSaveType);451 }452 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(453 SigC::slot(*this, &Window::vOnSaveTypeToggled),454 poCMI, astSaveType[i].m_eSaveType));455 }457 // Flash size menu458 //459 struct460 {461 const char * m_csName;462 const int m_iFlashSize;463 }464 astFlashSize[] =465 {466 { "SaveTypeFlash64K", 64 },467 { "SaveTypeFlash128K", 128 }468 };469 int iDefaultFlashSize = m_poCoreConfig->oGetKey<int>("flash_size");470 for (guint i = 0; i < G_N_ELEMENTS(astFlashSize); i++)471 {472 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astFlashSize[i].m_csName));473 if (astFlashSize[i].m_iFlashSize == iDefaultFlashSize)474 {475 poCMI->set_active();476 vOnFlashSizeToggled(poCMI, iDefaultFlashSize);477 }478 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(479 SigC::slot(*this, &Window::vOnFlashSizeToggled),480 poCMI, astFlashSize[i].m_iFlashSize));481 }483 // Screenshot format menu484 //485 struct486 {487 const char * m_csName;488 const char * m_csScreenshotFormat;489 }490 astScreenshotFormat[] =491 {492 { "ScreenshotFormatPNG", "png" },493 { "ScreenshotFormatBMP", "bmp" }494 };495 std::string sDefaultScreenshotFormat = m_poCoreConfig->sGetKey("screenshot_format");496 for (guint i = 0; i < G_N_ELEMENTS(astScreenshotFormat); i++)497 {498 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astScreenshotFormat[i].m_csName));499 if (astScreenshotFormat[i].m_csScreenshotFormat == sDefaultScreenshotFormat)500 {501 poCMI->set_active();502 vOnScreenshotFormatToggled(poCMI, sDefaultScreenshotFormat);503 }504 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, std::string>(505 SigC::slot(*this, &Window::vOnScreenshotFormatToggled),506 poCMI, std::string(astScreenshotFormat[i].m_csScreenshotFormat)));507 }509 // Sound menu510 //511 std::string sDefaultSoundStatus = m_poSoundConfig->sGetKey("status");513 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("SoundOff"));514 if (sDefaultSoundStatus == "off")515 {516 poCMI->set_active();517 vOnSoundStatusToggled(poCMI, SoundOff);518 }519 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(520 SigC::slot(*this, &Window::vOnSoundStatusToggled),521 poCMI, SoundOff));522 m_poSoundOffItem = poCMI;524 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("SoundMute"));525 if (sDefaultSoundStatus == "mute")526 {527 poCMI->set_active();528 vOnSoundStatusToggled(poCMI, SoundMute);529 }530 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(531 SigC::slot(*this, &Window::vOnSoundStatusToggled),532 poCMI, SoundMute));534 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("SoundOn"));535 if (sDefaultSoundStatus == "on")536 {537 poCMI->set_active();538 vOnSoundStatusToggled(poCMI, SoundOn);539 }540 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(541 SigC::slot(*this, &Window::vOnSoundStatusToggled),542 poCMI, SoundOn));544 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("SoundEcho"));545 poCMI->set_active(m_poSoundConfig->oGetKey<bool>("echo"));546 vOnSoundEchoToggled(poCMI);547 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(548 SigC::slot(*this, &Window::vOnSoundEchoToggled),549 poCMI));551 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("SoundLowPass"));552 poCMI->set_active(m_poSoundConfig->oGetKey<bool>("low_pass"));553 vOnSoundLowPassToggled(poCMI);554 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(555 SigC::slot(*this, &Window::vOnSoundLowPassToggled),556 poCMI));558 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("SoundReverseStereo"));559 poCMI->set_active(m_poSoundConfig->oGetKey<bool>("reverse_stereo"));560 vOnSoundReverseToggled(poCMI);561 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(562 SigC::slot(*this, &Window::vOnSoundReverseToggled),563 poCMI));565 struct566 {567 const char * m_csName;568 const char * m_csKey;569 const int m_iSoundChannel;570 }571 astSoundChannel[] =572 {573 { "SoundChannel1", "channel_1", 0 },574 { "SoundChannel2", "channel_2", 1 },575 { "SoundChannel3", "channel_3", 2 },576 { "SoundChannel4", "channel_4", 3 },577 { "SoundChannelA", "channel_A", 4 },578 { "SoundChannelB", "channel_B", 5 }579 };580 for (guint i = 0; i < G_N_ELEMENTS(astSoundChannel); i++)581 {582 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astSoundChannel[i].m_csName));583 poCMI->set_active(m_poSoundConfig->oGetKey<bool>(astSoundChannel[i].m_csKey));584 vOnSoundChannelToggled(poCMI, astSoundChannel[i].m_iSoundChannel);585 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(586 SigC::slot(*this, &Window::vOnSoundChannelToggled),587 poCMI, astSoundChannel[i].m_iSoundChannel));588 }590 struct591 {592 const char * m_csName;593 const ESoundQuality m_eSoundQuality;594 }595 astSoundQuality[] =596 {597 { "Sound11Khz", Sound11K },598 { "Sound22Khz", Sound22K },599 { "Sound44Khz", Sound44K }600 };601 ESoundQuality eDefaultSoundQuality = (ESoundQuality)m_poSoundConfig->oGetKey<int>("quality");602 for (guint i = 0; i < G_N_ELEMENTS(astSoundQuality); i++)603 {604 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astSoundQuality[i].m_csName));605 if (astSoundQuality[i].m_eSoundQuality == eDefaultSoundQuality)606 {607 poCMI->set_active();608 vOnSoundQualityToggled(poCMI, eDefaultSoundQuality);609 }610 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(611 SigC::slot(*this, &Window::vOnSoundQualityToggled),612 poCMI, astSoundQuality[i].m_eSoundQuality));613 }615 // Volume menu616 //617 struct618 {619 const char * m_csName;620 const ESoundVolume m_eSoundVolume;621 }622 astSoundVolume[] =623 {624 { "Volume25", Sound25 },625 { "Volume50", Sound50 },626 { "Volume100", Sound100 },627 { "Volume200", Sound200 },628 { "Volume300", Sound300 },629 { "Volume400", Sound400 }630 };631 ESoundVolume eDefaultSoundVolume = (ESoundVolume)m_poSoundConfig->oGetKey<int>("volume");632 for (guint i = 0; i < G_N_ELEMENTS(astSoundVolume); i++)633 {634 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astSoundVolume[i].m_csName));635 if (astSoundVolume[i].m_eSoundVolume == eDefaultSoundVolume)636 {637 poCMI->set_active();638 vOnSoundVolumeToggled(poCMI, eDefaultSoundVolume);639 }640 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(641 SigC::slot(*this, &Window::vOnSoundVolumeToggled),642 poCMI, astSoundVolume[i].m_eSoundVolume));643 }645 // Gameboy menu646 //647 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("GameboyBorder"));648 poCMI->set_active(m_poCoreConfig->oGetKey<bool>("gb_border"));649 vOnGBBorderToggled(poCMI);650 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(651 SigC::slot(*this, &Window::vOnGBBorderToggled),652 poCMI));654 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("GameboyPrinter"));655 poCMI->set_active(m_poCoreConfig->oGetKey<bool>("gb_printer"));656 vOnGBPrinterToggled(poCMI);657 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(658 SigC::slot(*this, &Window::vOnGBPrinterToggled),659 poCMI));661 struct662 {663 const char * m_csName;664 const EEmulatorType m_eEmulatorType;665 }666 astEmulatorType[] =667 {668 { "GameboyAutomatic", EmulatorAuto },669 { "GameboyGba", EmulatorGBA },670 { "GameboyCgb", EmulatorCGB },671 { "GameboySgb", EmulatorSGB },672 { "GameboySgb2", EmulatorSGB2 },673 { "GameboyGb", EmulatorGB }674 };675 EEmulatorType eDefaultEmulatorType = (EEmulatorType)m_poCoreConfig->oGetKey<int>("emulator_type");676 for (guint i = 0; i < G_N_ELEMENTS(astEmulatorType); i++)677 {678 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astEmulatorType[i].m_csName));679 if (astEmulatorType[i].m_eEmulatorType == eDefaultEmulatorType)680 {681 poCMI->set_active();682 vOnEmulatorTypeToggled(poCMI, eDefaultEmulatorType);683 }684 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(685 SigC::slot(*this, &Window::vOnEmulatorTypeToggled),686 poCMI, astEmulatorType[i].m_eEmulatorType));687 }689 // Filter menu690 //691 struct692 {693 const char * m_csName;694 const EFilter2x m_eFilter2x;695 }696 astFilter2x[] =697 {698 { "FilterNone", FilterNone },699 { "FilterTVMode", FilterScanlinesTV },700 { "Filter2xSaI", Filter2xSaI },701 { "FilterSuper2xSaI", FilterSuper2xSaI },702 { "FilterSuperEagle", FilterSuperEagle },703 { "FilterPixelate", FilterPixelate },704 { "FilterMotionBlur", FilterMotionBlur },705 { "FilterAdvanceMame2x", FilterAdMame2x },706 { "FilterSimple2x", FilterSimple2x },707 { "FilterBilinear", FilterBilinear },708 { "FilterBilinearPlus", FilterBilinearPlus },709 { "FilterScanlines", FilterScanlines },710 { "FilterHq2x", FilterHq2x },711 { "FilterLq2x", FilterLq2x }712 };713 EFilter2x eDefaultFilter2x = (EFilter2x)m_poDisplayConfig->oGetKey<int>("filter2x");714 for (guint i = 0; i < G_N_ELEMENTS(astFilter2x); i++)715 {716 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astFilter2x[i].m_csName));717 if (astFilter2x[i].m_eFilter2x == eDefaultFilter2x)718 {719 poCMI->set_active();720 vOnFilter2xToggled(poCMI, eDefaultFilter2x);721 }722 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(723 SigC::slot(*this, &Window::vOnFilter2xToggled),724 poCMI, astFilter2x[i].m_eFilter2x));725 }727 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("FilterDisableMmx"));728 #ifdef MMX729 poCMI->set_active(m_poDisplayConfig->oGetKey<bool>("filter_disable_mmx"));730 vOnDisableMMXToggled(poCMI);731 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *>(732 SigC::slot(*this, &Window::vOnDisableMMXToggled),733 poCMI));734 #else // ! MMX735 poCMI->set_active();736 poCMI->set_sensitive(false);737 #endif // ! MMX739 // Interframe blending menu740 //741 struct742 {743 const char * m_csName;744 const EFilterIB m_eFilterIB;745 }746 astFilterIB[] =747 {748 { "IFBNone", FilterIBNone },749 { "IFBSmart", FilterIBSmart },750 { "IFBMotionBlur", FilterIBMotionBlur }751 };752 EFilterIB eDefaultFilterIB = (EFilterIB)m_poDisplayConfig->oGetKey<int>("filterIB");753 for (guint i = 0; i < G_N_ELEMENTS(astFilterIB); i++)754 {755 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astFilterIB[i].m_csName));756 if (astFilterIB[i].m_eFilterIB == eDefaultFilterIB)757 {758 poCMI->set_active();759 vOnFilterIBToggled(poCMI, eDefaultFilterIB);760 }761 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(762 SigC::slot(*this, &Window::vOnFilterIBToggled),763 poCMI, astFilterIB[i].m_eFilterIB));764 }766 // Joypad menu767 //768 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("JoypadConfigure1"));769 poMI->signal_activate().connect(SigC::bind<int>(770 SigC::slot(*this, &Window::vOnJoypadConfigure), 1));772 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("JoypadConfigure2"));773 poMI->signal_activate().connect(SigC::bind<int>(774 SigC::slot(*this, &Window::vOnJoypadConfigure), 2));776 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("JoypadConfigure3"));777 poMI->signal_activate().connect(SigC::bind<int>(778 SigC::slot(*this, &Window::vOnJoypadConfigure), 3));780 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("JoypadConfigure4"));781 poMI->signal_activate().connect(SigC::bind<int>(782 SigC::slot(*this, &Window::vOnJoypadConfigure), 4));784 int iDefaultJoypad = m_poInputConfig->oGetKey<int>("active_joypad");785 for (int i = m_iJoypadMin; i <= m_iJoypadMax; i++)786 {787 char csName[20];788 snprintf(csName, sizeof(csName), "Joypad%d", i);790 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(csName));791 if (i == iDefaultJoypad)792 {793 poCMI->set_active();794 vOnJoypadToggled(poCMI, iDefaultJoypad);795 }796 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, int>(797 SigC::slot(*this, &Window::vOnJoypadToggled),798 poCMI, i));799 }801 // Autofire menu802 //803 struct804 {805 const char * m_csName;806 const char * m_csKey;807 const EKeyFlag m_eKeyFlag;808 }809 astAutofire[] =810 {811 { "AutofireA", "autofire_A", KeyFlagA },812 { "AutofireB", "autofire_B", KeyFlagB },813 { "AutofireL", "autofire_L", KeyFlagL },814 { "AutofireR", "autofire_R", KeyFlagR }815 };816 for (guint i = 0; i < G_N_ELEMENTS(astAutofire); i++)817 {818 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget(astAutofire[i].m_csName));819 poCMI->set_active(m_poInputConfig->oGetKey<bool>(astAutofire[i].m_csKey));820 vOnAutofireToggled(poCMI, astAutofire[i].m_eKeyFlag);821 poCMI->signal_toggled().connect(SigC::bind<Gtk::CheckMenuItem *, u32>(822 SigC::slot(*this, &Window::vOnAutofireToggled),823 poCMI, astAutofire[i].m_eKeyFlag));824 }826 // GDB menu827 //828 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("GdbWait"));829 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnGDBWait));831 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("GdbLoadAndWait"));832 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnGDBLoadAndWait));834 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("GdbBreak"));835 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnGDBBreak));837 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("GdbDisconnect"));838 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnGDBDisconnect));840 // Help menu841 //842 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("HelpAbout"));843 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnHelpAbout));845 // Init widgets sensitivity846 for (std::list<Gtk::Widget *>::iterator it = m_listSensitiveWhenPlaying.begin();847 it != m_listSensitiveWhenPlaying.end();848 it++)849 {850 (*it)->set_sensitive(false);851 }853 if (m_poInstance == NULL)854 {855 m_poInstance = this;856 }857 else858 {859 abort();860 }861 }863 Window::~Window()864 {865 vOnFileClose();866 vSaveHistoryToConfig();867 vSaveJoypadsToConfig();868 vSaveConfig(m_sConfigFile);870 if (m_poFileOpenDialog != NULL)871 {872 delete m_poFileOpenDialog;873 }875 if (m_poKeymap != NULL)876 {877 delete m_poKeymap;878 }880 m_poInstance = NULL;881 }883 void Window::vInitSystem()884 {885 #if G_BYTE_ORDER == G_LITTLE_ENDIAN886 systemRedShift = 3;887 systemGreenShift = 11;888 systemBlueShift = 19;889 RGB_LOW_BITS_MASK = 0x00010101;890 #else891 systemRedShift = 27;892 systemGreenShift = 19;893 systemBlueShift = 11;894 RGB_LOW_BITS_MASK = 0x01010100;895 #endif897 systemColorDepth = 32;898 systemDebug = 0;899 systemVerbose = 0;900 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;901 systemFrameSkip = 0;902 systemSoundOn = false;903 soundOffFlag = true;905 systemRenderedFrames = 0;906 systemFPS = 0;908 emulating = 0;909 debugger = false;911 for (int i = 0; i < 0x10000; i++)912 {913 #if G_BYTE_ORDER == G_LITTLE_ENDIAN914 systemColorMap32[i] = (((i & 0x1f) << systemRedShift)915 | (((i & 0x3e0) >> 5) << systemGreenShift)916 | (((i & 0x7c00) >> 10) << systemBlueShift));917 #else918 systemColorMap32[i] = (((i & 0x1f) << systemRedShift)919 | (((i & 0x3e0) >> 5) << systemGreenShift)920 | (((i & 0x7c00) >> 10) << systemBlueShift));921 #endif922 }924 gbFrameSkip = 0;926 for (int i = 0; i < 24; )927 {928 systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10);929 systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10);930 systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10);931 systemGbPalette[i++] = 0;932 }934 Init_2xSaI(32);935 }937 void Window::vInitSDL()938 {939 static bool bDone = false;941 if (bDone)942 return;944 int iFlags = (SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE);946 if (SDL_Init(iFlags) < 0)947 {948 fprintf(stderr, "Failed to init SDL: %s", SDL_GetError());949 abort();950 }952 bDone = true;953 }955 void Window::vInitConfig()956 {957 m_oConfig.vClear();959 // History section960 //961 m_poHistoryConfig = m_oConfig.poAddSection("History");962 m_poHistoryConfig->vSetKey("freeze", false );963 m_poHistoryConfig->vSetKey("0", "" );964 m_poHistoryConfig->vSetKey("1", "" );965 m_poHistoryConfig->vSetKey("2", "" );966 m_poHistoryConfig->vSetKey("3", "" );967 m_poHistoryConfig->vSetKey("4", "" );968 m_poHistoryConfig->vSetKey("5", "" );969 m_poHistoryConfig->vSetKey("6", "" );970 m_poHistoryConfig->vSetKey("7", "" );971 m_poHistoryConfig->vSetKey("8", "" );972 m_poHistoryConfig->vSetKey("9", "" );974 // Directories section975 //976 m_poDirConfig = m_oConfig.poAddSection("Directories");977 m_poDirConfig->vSetKey("gb_roms", "" );978 m_poDirConfig->vSetKey("gba_roms", "" );979 m_poDirConfig->vSetKey("batteries", "" );980 m_poDirConfig->vSetKey("saves", "" );981 m_poDirConfig->vSetKey("captures", "" );983 // Core section984 //985 m_poCoreConfig = m_oConfig.poAddSection("Core");986 m_poCoreConfig->vSetKey("load_game_auto", false );987 m_poCoreConfig->vSetKey("frameskip", "auto" );988 m_poCoreConfig->vSetKey("throttle", 0 );989 m_poCoreConfig->vSetKey("layer_bg0", true );990 m_poCoreConfig->vSetKey("layer_bg1", true );991 m_poCoreConfig->vSetKey("layer_bg2", true );992 m_poCoreConfig->vSetKey("layer_bg3", true );993 m_poCoreConfig->vSetKey("layer_obj", true );994 m_poCoreConfig->vSetKey("layer_win0", true );995 m_poCoreConfig->vSetKey("layer_win1", true );996 m_poCoreConfig->vSetKey("layer_objwin", true );997 m_poCoreConfig->vSetKey("use_bios_file", false );998 m_poCoreConfig->vSetKey("bios_file", "" );999 m_poCoreConfig->vSetKey("save_type", SaveAuto );1000 m_poCoreConfig->vSetKey("flash_size", 64 );1001 m_poCoreConfig->vSetKey("gb_border", true );1002 m_poCoreConfig->vSetKey("gb_printer", false );1003 m_poCoreConfig->vSetKey("emulator_type", EmulatorAuto );1004 m_poCoreConfig->vSetKey("screenshot_format", "png" );1006 // Display section1007 //1008 m_poDisplayConfig = m_oConfig.poAddSection("Display");1009 m_poDisplayConfig->vSetKey("scale", 1 );1010 m_poDisplayConfig->vSetKey("show_speed", ShowPercentage );1011 m_poDisplayConfig->vSetKey("pause_when_inactive", true );1012 m_poDisplayConfig->vSetKey("filter2x", FilterNone );1013 m_poDisplayConfig->vSetKey("filterIB", FilterIBNone );1014 #ifdef MMX1015 m_poDisplayConfig->vSetKey("filter_disable_mmx", false );1016 #endif // MMX1018 // Sound section1019 //1020 m_poSoundConfig = m_oConfig.poAddSection("Sound");1021 m_poSoundConfig->vSetKey("status", "on" );1022 m_poSoundConfig->vSetKey("echo", false );1023 m_poSoundConfig->vSetKey("low_pass", false );1024 m_poSoundConfig->vSetKey("reverse_stereo", false );1025 m_poSoundConfig->vSetKey("channel_1", true );1026 m_poSoundConfig->vSetKey("channel_2", true );1027 m_poSoundConfig->vSetKey("channel_3", true );1028 m_poSoundConfig->vSetKey("channel_4", true );1029 m_poSoundConfig->vSetKey("channel_A", true );1030 m_poSoundConfig->vSetKey("channel_B", true );1031 m_poSoundConfig->vSetKey("quality", Sound22K );1032 m_poSoundConfig->vSetKey("volume", Sound100 );1034 // Input section1035 //1036 JoypadConfig oJoypadConfig;1037 oJoypadConfig.vSetDefault();1038 m_poInputConfig = m_oConfig.poAddSection("Input");1039 m_poInputConfig->vSetKey("active_joypad", m_iJoypadMin );1040 for (int i = m_iJoypadMin; i <= m_iJoypadMax; i++)1041 {1042 char csPrefix[20];1043 snprintf(csPrefix, sizeof(csPrefix), "joypad%d_", i);1044 std::string sPrefix(csPrefix);1045 m_poInputConfig->vSetKey(sPrefix + "up", oJoypadConfig.m_uiUp );1046 m_poInputConfig->vSetKey(sPrefix + "down", oJoypadConfig.m_uiDown );1047 m_poInputConfig->vSetKey(sPrefix + "left", oJoypadConfig.m_uiLeft );1048 m_poInputConfig->vSetKey(sPrefix + "right", oJoypadConfig.m_uiRight );1049 m_poInputConfig->vSetKey(sPrefix + "A", oJoypadConfig.m_uiA );1050 m_poInputConfig->vSetKey(sPrefix + "B", oJoypadConfig.m_uiB );1051 m_poInputConfig->vSetKey(sPrefix + "L", oJoypadConfig.m_uiL );1052 m_poInputConfig->vSetKey(sPrefix + "R", oJoypadConfig.m_uiR );1053 m_poInputConfig->vSetKey(sPrefix + "select", oJoypadConfig.m_uiSelect );1054 m_poInputConfig->vSetKey(sPrefix + "start", oJoypadConfig.m_uiStart );1055 m_poInputConfig->vSetKey(sPrefix + "speed", oJoypadConfig.m_uiSpeed );1056 m_poInputConfig->vSetKey(sPrefix + "capture", oJoypadConfig.m_uiCapture );1057 }1058 m_poInputConfig->vSetKey("autofire_A", false );1059 m_poInputConfig->vSetKey("autofire_B", false );1060 m_poInputConfig->vSetKey("autofire_L", false );1061 m_poInputConfig->vSetKey("autofire_R", false );1062 }1064 void Window::vCheckConfig()1065 {1066 int iValue;1067 int iAdjusted;1068 std::string sValue;1070 // Directories section1071 //1072 sValue = m_poDirConfig->sGetKey("gb_roms");1073 if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR))1074 {1075 m_poDirConfig->vSetKey("gb_roms", "");1076 }1077 sValue = m_poDirConfig->sGetKey("gba_roms");1078 if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR))1079 {1080 m_poDirConfig->vSetKey("gba_roms", "");1081 }1082 sValue = m_poDirConfig->sGetKey("batteries");1083 if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR))1084 {1085 m_poDirConfig->vSetKey("batteries", "");1086 }1087 sValue = m_poDirConfig->sGetKey("saves");1088 if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR))1089 {1090 m_poDirConfig->vSetKey("saves", "");1091 }1092 sValue = m_poDirConfig->sGetKey("captures");1093 if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR))1094 {1095 m_poDirConfig->vSetKey("captures", "");1096 }1098 // Core section1099 //1100 if (m_poCoreConfig->sGetKey("frameskip") != "auto")1101 {1102 iValue = m_poCoreConfig->oGetKey<int>("frameskip");1103 iAdjusted = CLAMP(iValue, m_iFrameskipMin, m_iFrameskipMax);1104 if (iValue != iAdjusted)1105 {1106 m_poCoreConfig->vSetKey("frameskip", iAdjusted);1107 }1108 }1110 iValue = m_poCoreConfig->oGetKey<int>("throttle");1111 if (iValue != 0)1112 {1113 iAdjusted = CLAMP(iValue, m_iThrottleMin, m_iThrottleMax);1114 if (iValue != iAdjusted)1115 {1116 m_poCoreConfig->vSetKey("throttle", iAdjusted);1117 }1118 }1120 sValue = m_poCoreConfig->sGetKey("bios_file");1121 if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_REGULAR))1122 {1123 m_poCoreConfig->vSetKey("bios_file", "");1124 }1125 if (m_poCoreConfig->sGetKey("bios_file") == "")1126 {1127 m_poCoreConfig->vSetKey("use_bios_file", false);1128 }1130 iValue = m_poCoreConfig->oGetKey<int>("save_type");1131 if (iValue != 0)1132 {1133 iAdjusted = CLAMP(iValue, m_iSaveTypeMin, m_iSaveTypeMax);1134 if (iValue != iAdjusted)1135 {1136 m_poCoreConfig->vSetKey("save_type", iAdjusted);1137 }1138 }1140 iValue = m_poCoreConfig->oGetKey<int>("flash_size");1141 if (iValue != 64 && iValue != 128)1142 {1143 m_poCoreConfig->vSetKey("flash_size", 64);1144 }1146 iValue = m_poCoreConfig->oGetKey<int>("emulator_type");1147 iAdjusted = CLAMP(iValue, m_iEmulatorTypeMin, m_iEmulatorTypeMax);1148 if (iValue != iAdjusted)1149 {1150 m_poCoreConfig->vSetKey("emulator_type", iAdjusted);1151 }1153 sValue = m_poCoreConfig->sGetKey("screenshot_format");1154 if (sValue != "png" && sValue != "bmp")1155 {1156 sValue = "png";1157 }1159 // Display section1160 //1161 iValue = m_poDisplayConfig->oGetKey<int>("scale");1162 iAdjusted = CLAMP(iValue, m_iScaleMin, m_iScaleMax);1163 if (iValue != iAdjusted)1164 {1165 m_poDisplayConfig->vSetKey("scale", iAdjusted);1166 }1168 iValue = m_poDisplayConfig->oGetKey<int>("show_speed");1169 iAdjusted = CLAMP(iValue, m_iShowSpeedMin, m_iShowSpeedMax);1170 if (iValue != iAdjusted)1171 {1172 m_poDisplayConfig->vSetKey("show_speed", iAdjusted);1173 }1175 iValue = m_poDisplayConfig->oGetKey<int>("filter2x");1176 iAdjusted = CLAMP(iValue, m_iFilter2xMin, m_iFilter2xMax);1177 if (iValue != iAdjusted)1178 {1179 m_poDisplayConfig->vSetKey("filter2x", iAdjusted);1180 }1182 iValue = m_poDisplayConfig->oGetKey<int>("filterIB");1183 iAdjusted = CLAMP(iValue, m_iFilterIBMin, m_iFilterIBMax);1184 if (iValue != iAdjusted)1185 {1186 m_poDisplayConfig->vSetKey("filterIB", iAdjusted);1187 }1189 // Sound section1190 //1191 sValue = m_poSoundConfig->sGetKey("status");1192 if (sValue != "off" && sValue != "on" && sValue != "mute")1193 {1194 m_poSoundConfig->vSetKey("status", "on");1195 }1197 iValue = m_poSoundConfig->oGetKey<int>("quality");1198 iAdjusted = CLAMP(iValue, m_iSoundQualityMin, m_iSoundQualityMax);1199 if (iValue != iAdjusted)1200 {1201 m_poSoundConfig->vSetKey("quality", iAdjusted);1202 }1204 iValue = m_poSoundConfig->oGetKey<int>("volume");1205 iAdjusted = CLAMP(iValue, m_iSoundVolumeMin, m_iSoundVolumeMax);1206 if (iValue != iAdjusted)1207 {1208 m_poSoundConfig->vSetKey("volume", iAdjusted);1209 }1211 // Input section1212 //1213 iValue = m_poInputConfig->oGetKey<int>("active_joypad");1214 iAdjusted = CLAMP(iValue, m_iJoypadMin, m_iJoypadMax);1215 if (iValue != iAdjusted)1216 {1217 m_poInputConfig->vSetKey("active_joypad", iAdjusted);1218 }1219 }1221 void Window::vLoadConfig(const std::string & _rsFile)1222 {1223 try1224 {1225 m_oConfig.vLoad(_rsFile, false, false);1226 }1227 catch (const Glib::Error & e)1228 {1229 vPopupError(e.what().c_str());1230 }1231 }1233 void Window::vSaveConfig(const std::string & _rsFile)1234 {1235 try1236 {1237 m_oConfig.vSave(_rsFile);1238 }1239 catch (const Glib::Error & e)1240 {1241 vPopupError(e.what().c_str());1242 }1243 }1245 void Window::vLoadHistoryFromConfig()1246 {1247 char csKey[] = "0";1248 for (int i = 0; i < 10; i++, csKey[0]++)1249 {1250 std::string sFile = m_poHistoryConfig->sGetKey(csKey);1251 if (sFile == "")1252 {1253 break;1254 }1255 m_listHistory.push_back(sFile);1256 }1257 }1259 void Window::vSaveHistoryToConfig()1260 {1261 char csKey[] = "0";1262 for (std::list<std::string>::const_iterator it = m_listHistory.begin();1263 it != m_listHistory.end();1264 it++, csKey[0]++)1265 {1266 m_poHistoryConfig->vSetKey(csKey, *it);1267 }1268 }1270 void Window::vHistoryAdd(const std::string & _rsFile)1271 {1272 if (m_poHistoryConfig->oGetKey<bool>("freeze"))1273 {1274 return;1275 }1277 m_listHistory.remove(_rsFile);1278 m_listHistory.push_front(_rsFile);1279 if (m_listHistory.size() > 10)1280 {1281 m_listHistory.pop_back();1282 }1284 vUpdateHistoryMenu();1285 }1287 void Window::vClearHistoryMenu()1288 {1289 Gtk::Menu_Helpers::MenuList::iterator it = m_poRecentMenu->items().begin();1290 for (int i = 0; i < 3; i++, it++)1291 ;1293 m_poRecentMenu->items().erase(it, m_poRecentMenu->items().end());1294 }1296 void Window::vUpdateHistoryMenu()1297 {1298 vClearHistoryMenu();1300 guint uiAccelKey = GDK_F1;1301 for (std::list<std::string>::const_iterator it = m_listHistory.begin();1302 it != m_listHistory.end();1303 it++, uiAccelKey++)1304 {1305 Gtk::Image * poImage = Gtk::manage(new Gtk::Image(Gtk::Stock::OPEN, Gtk::ICON_SIZE_MENU));1306 Glib::ustring sLabel = Glib::path_get_basename(*it);1307 VBA::ImageMenuItem * poIMI = Gtk::manage(new VBA::ImageMenuItem(*poImage, sLabel));1309 m_oTooltips.set_tip(*poIMI, *it);1311 poIMI->signal_activate().connect(SigC::bind<std::string>(1312 SigC::slot(*this, &Window::vOnRecentFile),1313 *it));1315 poIMI->set_accel_key(Gtk::AccelKey(uiAccelKey, Gdk::CONTROL_MASK));1316 poIMI->accelerate(*this);1318 poIMI->show();1319 m_poRecentMenu->items().push_back(*poIMI);1320 }1321 }1323 void Window::vLoadJoypadsFromConfig()1324 {1325 m_oJoypads.clear();1327 for (int i = m_iJoypadMin; i <= m_iJoypadMax; i++)1328 {1329 char csPrefix[20];1330 snprintf(csPrefix, sizeof(csPrefix), "joypad%d_", i);1331 std::string sPrefix(csPrefix);1333 JoypadConfig oJoypadConfig;1334 oJoypadConfig.m_uiUp = m_poInputConfig->oGetKey<guint>(sPrefix + "up");1335 oJoypadConfig.m_uiDown = m_poInputConfig->oGetKey<guint>(sPrefix + "down");1336 oJoypadConfig.m_uiLeft = m_poInputConfig->oGetKey<guint>(sPrefix + "left");1337 oJoypadConfig.m_uiRight = m_poInputConfig->oGetKey<guint>(sPrefix + "right");1338 oJoypadConfig.m_uiA = m_poInputConfig->oGetKey<guint>(sPrefix + "A");1339 oJoypadConfig.m_uiB = m_poInputConfig->oGetKey<guint>(sPrefix + "B");1340 oJoypadConfig.m_uiL = m_poInputConfig->oGetKey<guint>(sPrefix + "L");1341 oJoypadConfig.m_uiR = m_poInputConfig->oGetKey<guint>(sPrefix + "R");1342 oJoypadConfig.m_uiSelect = m_poInputConfig->oGetKey<guint>(sPrefix + "select");1343 oJoypadConfig.m_uiStart = m_poInputConfig->oGetKey<guint>(sPrefix + "start");1344 oJoypadConfig.m_uiSpeed = m_poInputConfig->oGetKey<guint>(sPrefix + "speed");1345 oJoypadConfig.m_uiCapture = m_poInputConfig->oGetKey<guint>(sPrefix + "capture");1347 m_oJoypads.push_back(oJoypadConfig);1348 }1349 }1351 void Window::vSaveJoypadsToConfig()1352 {1353 for (int i = m_iJoypadMin; i <= m_iJoypadMax; i++)1354 {1355 char csPrefix[20];1356 snprintf(csPrefix, sizeof(csPrefix), "joypad%d_", i);1357 std::string sPrefix(csPrefix);1359 m_poInputConfig->vSetKey(sPrefix + "up", m_oJoypads[i - 1].m_uiUp );1360 m_poInputConfig->vSetKey(sPrefix + "down", m_oJoypads[i - 1].m_uiDown );1361 m_poInputConfig->vSetKey(sPrefix + "left", m_oJoypads[i - 1].m_uiLeft );1362 m_poInputConfig->vSetKey(sPrefix + "right", m_oJoypads[i - 1].m_uiRight );1363 m_poInputConfig->vSetKey(sPrefix + "A", m_oJoypads[i - 1].m_uiA );1364 m_poInputConfig->vSetKey(sPrefix + "B", m_oJoypads[i - 1].m_uiB );1365 m_poInputConfig->vSetKey(sPrefix + "L", m_oJoypads[i - 1].m_uiL );1366 m_poInputConfig->vSetKey(sPrefix + "R", m_oJoypads[i - 1].m_uiR );1367 m_poInputConfig->vSetKey(sPrefix + "select", m_oJoypads[i - 1].m_uiSelect );1368 m_poInputConfig->vSetKey(sPrefix + "start", m_oJoypads[i - 1].m_uiStart );1369 m_poInputConfig->vSetKey(sPrefix + "speed", m_oJoypads[i - 1].m_uiSpeed );1370 m_poInputConfig->vSetKey(sPrefix + "capture", m_oJoypads[i - 1].m_uiCapture );1371 }1372 }1374 void Window::vUpdateScreen()1375 {1376 if (m_eCartridge == CartridgeGB)1377 {1378 if (gbBorderOn)1379 {1380 m_iScreenWidth = m_iSGBScreenWidth;1381 m_iScreenHeight = m_iSGBScreenHeight;1382 gbBorderLineSkip = m_iSGBScreenWidth;1383 gbBorderColumnSkip = (m_iSGBScreenWidth - m_iGBScreenWidth) / 2;1384 gbBorderRowSkip = (m_iSGBScreenHeight - m_iGBScreenHeight) / 2;1385 }1386 else1387 {1388 m_iScreenWidth = m_iGBScreenWidth;1389 m_iScreenHeight = m_iGBScreenHeight;1390 gbBorderLineSkip = m_iGBScreenWidth;1391 gbBorderColumnSkip = 0;1392 gbBorderRowSkip = 0;1393 }1394 }1395 else if (m_eCartridge == CartridgeGBA)1396 {1397 m_iScreenWidth = m_iGBAScreenWidth;1398 m_iScreenHeight = m_iGBAScreenHeight;1399 }1401 g_return_if_fail(m_iScreenWidth >= 1 && m_iScreenHeight >= 1);1403 m_poScreenArea->vSetSize(m_iScreenWidth, m_iScreenHeight);1404 m_poScreenArea->vSetScale(m_poDisplayConfig->oGetKey<int>("scale"));1406 resize(1, 1);1408 if (emulating)1409 {1410 vDrawScreen();1411 }1412 else1413 {1414 vDrawDefaultScreen();1415 }1416 }1418 bool Window::bLoadROM(const std::string & _rsFile)1419 {1420 vOnFileClose();1422 m_sRomFile = _rsFile;1423 const char * csFile = _rsFile.c_str();1425 IMAGE_TYPE eType = utilFindType(csFile);1426 if (eType == IMAGE_UNKNOWN)1427 {1428 vPopupError(_("Unknown file type %s"), csFile);1429 return false;1430 }1432 bool bLoaded = false;1433 if (eType == IMAGE_GB)1434 {1435 bLoaded = gbLoadRom(csFile);1436 if (bLoaded)1437 {1438 m_eCartridge = CartridgeGB;1439 m_stEmulator = GBSystem;1440 }1441 }1442 else if (eType == IMAGE_GBA)1443 {1444 int iSize = CPULoadRom(csFile);1445 bLoaded = (iSize > 0);1446 if (bLoaded)1447 {1448 m_eCartridge = CartridgeGBA;1449 m_stEmulator = GBASystem;1451 useBios = m_poCoreConfig->oGetKey<bool>("use_bios_file");1452 //CPUInit(m_poCoreConfig->sGetKey("bios_file").c_str(), useBios);1453 CPUInit();1454 CPUReset();1456 // If the bios file was rejected by CPUInit1457 if (m_poCoreConfig->oGetKey<bool>("use_bios_file") && ! useBios)1458 {1459 m_poUseBiosItem->set_active(false);1460 m_poUseBiosItem->set_sensitive(false);1461 m_poCoreConfig->vSetKey("bios_file", "");1462 }1463 }1464 }1466 if (! bLoaded)1467 {1468 return false;1469 }1471 vLoadBattery();1472 vUpdateScreen();1474 debugger = false; // May cause conflicts1475 emulating = 1;1476 m_bWasEmulating = false;1477 m_uiThrottleDelay = 0;1479 if (m_eCartridge == CartridgeGBA)1480 {1481 soundSetQuality(m_eSoundQuality);1482 }1483 else1484 {1485 gbSoundSetQuality(m_eSoundQuality);1486 }1488 vUpdateGameSlots();1489 vHistoryAdd(_rsFile);1491 for (std::list<Gtk::Widget *>::iterator it = m_listSensitiveWhenPlaying.begin();1492 it != m_listSensitiveWhenPlaying.end();1493 it++)1494 {1495 (*it)->set_sensitive();1496 }1498 if (m_poCoreConfig->oGetKey<bool>("load_game_auto"))1499 {1500 vOnLoadGameMostRecent();1501 }1503 vStartEmu();1505 return true;1506 }1508 void Window::vPopupError(const char * _csFormat, ...)1509 {1510 va_list args;1511 va_start(args, _csFormat);1512 char * csMsg = g_strdup_vprintf(_csFormat, args);1513 va_end(args);1515 Gtk::MessageDialog oDialog(*this,1516 csMsg,1517 #ifndef GTKMM201518 false,1519 #endif // ! GTKMM201520 Gtk::MESSAGE_ERROR,1521 Gtk::BUTTONS_OK);1522 oDialog.run();1523 g_free(csMsg);1524 }1526 void Window::vPopupErrorV(const char * _csFormat, va_list _args)1527 {1528 char * csMsg = g_strdup_vprintf(_csFormat, _args);1530 Gtk::MessageDialog oDialog(*this,1531 csMsg,1532 #ifndef GTKMM201533 false,1534 #endif // ! GTKMM201535 Gtk::MESSAGE_ERROR,1536 Gtk::BUTTONS_OK);1537 oDialog.run();1538 g_free(csMsg);1539 }1541 void Window::vDrawScreen()1542 {1543 m_poScreenArea->vDrawPixels(pix);1544 }1546 void Window::vDrawDefaultScreen()1547 {1548 m_poScreenArea->vDrawColor(0x000000); // Black1549 }1551 void Window::vSetDefaultTitle()1552 {1553 set_title("VBA");1554 }1556 void Window::vShowSpeed(int _iSpeed)1557 {1558 char csTitle[50];1560 if (m_eShowSpeed == ShowPercentage)1561 {1562 snprintf(csTitle, 50, "VBA - %d%%", _iSpeed);1563 set_title(csTitle);1564 }1565 else if (m_eShowSpeed == ShowDetailed)1566 {1567 snprintf(csTitle, 50, "VBA - %d%% (%d, %d fps)",1568 _iSpeed, systemFrameSkip, systemFPS);1569 set_title(csTitle);1570 }1571 }1573 void Window::vComputeFrameskip(int _iRate)1574 {1575 static u32 uiLastTime = 0;1576 static int iFrameskipAdjust = 0;1578 u32 uiTime = SDL_GetTicks();1580 if (m_bWasEmulating)1581 {1582 int iWantedSpeed = 100;1584 if (m_iThrottle > 0)1585 {1586 if (! speedup)1587 {1588 u32 uiDiff = uiTime - m_uiThrottleLastTime;1589 int iTarget = 1000000 / (_iRate * m_iThrottle);1590 int iDelay = iTarget - uiDiff;1591 if (iDelay > 0)1592 {1593 m_uiThrottleDelay = iDelay;1594 }1595 }1596 iWantedSpeed = m_iThrottle;1597 }1599 if (m_bAutoFrameskip)1600 {1601 u32 uiDiff = uiTime - uiLastTime;1602 int iSpeed = iWantedSpeed;1604 if (uiDiff != 0)1605 {1606 iSpeed = (1000000 / _iRate) / uiDiff;1607 }1609 if (iSpeed >= iWantedSpeed - 2)1610 {1611 iFrameskipAdjust++;1612 if (iFrameskipAdjust >= 3)1613 {1614 iFrameskipAdjust = 0;1615 if (systemFrameSkip > 0)1616 {1617 systemFrameSkip--;1618 }1619 }1620 }1621 else1622 {1623 if (iSpeed < iWantedSpeed - 20)1624 {1625 iFrameskipAdjust -= ((iWantedSpeed - 10) - iSpeed) / 5;1626 }1627 else if (systemFrameSkip < 9)1628 {1629 iFrameskipAdjust--;1630 }1632 if (iFrameskipAdjust <= -2)1633 {1634 iFrameskipAdjust += 2;1635 if (systemFrameSkip < 9)1636 {1637 systemFrameSkip++;1638 }1639 }1640 }1641 }1642 }1643 else1644 {1645 m_bWasEmulating = true;1646 }1648 uiLastTime = uiTime;1649 m_uiThrottleLastTime = uiTime;1650 }1652 void Window::vCaptureScreen(int _iNum)1653 {1654 std::string sBaseName;1655 std::string sCaptureDir = m_poDirConfig->sGetKey("captures");1656 if (sCaptureDir == "")1657 {1658 sBaseName = sCutSuffix(m_sRomFile);1659 }1660 else1661 {1662 sBaseName = sCaptureDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile));1663 }1664 std::string sFormat = m_poCoreConfig->sGetKey("screenshot_format");1666 char * csFile = g_strdup_printf("%s_%02d.%s",1667 sBaseName.c_str(),1668 _iNum,1669 sFormat.c_str());1670 if (sFormat == "png")1671 {1672 m_stEmulator.emuWritePNG(csFile);1673 }1674 else1675 {1676 m_stEmulator.emuWriteBMP(csFile);1677 }1678 g_free(csFile);1679 }1681 u32 Window::uiReadJoypad()1682 {1683 u32 uiJoypad = m_uiJoypadState;1685 if (m_uiAutofireState != 0)1686 {1687 uiJoypad &= ~m_uiAutofireState;1688 if (m_bAutofireToggle)1689 {1690 uiJoypad |= m_uiAutofireState;1691 }1692 m_bAutofireToggle = ! m_bAutofireToggle;1693 }1695 return uiJoypad;1696 }1698 void Window::vCreateFileOpenDialog()1699 {1700 if (m_poFileOpenDialog != NULL)1701 {1702 return;1703 }1705 std::string sGBDir = m_poDirConfig->sGetKey("gb_roms");1706 std::string sGBADir = m_poDirConfig->sGetKey("gba_roms");1708 #ifdef GTKMM201710 Gtk::FileSelection * poDialog = new Gtk::FileSelection(_("Open"));1711 poDialog->set_transient_for(*this);1713 if (sGBADir != "")1714 {1715 poDialog->set_filename(sGBADir + "/");1716 }1717 else if (sGBDir != "")1718 {1719 poDialog->set_filename(sGBDir + "/");1720 }1722 #else // ! GTKMM201724 Gtk::FileChooserDialog * poDialog = new Gtk::FileChooserDialog(*this, _("Open"));1725 poDialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);1726 poDialog->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);1728 if (sGBDir != "")1729 {1730 poDialog->add_shortcut_folder(sGBDir);1731 poDialog->set_current_folder(sGBDir);1732 }1734 if (sGBADir != "" && sGBADir != sGBDir)1735 {1736 poDialog->add_shortcut_folder(sGBADir);1737 poDialog->set_current_folder(sGBADir);1738 }1740 const char * acsPattern[] =1741 {1742 // GBA1743 "*.[bB][iI][nN]", "*.[aA][gG][bB]", "*.[gG][bB][aA]",1744 // GB1745 "*.[gG][bB]", "*.[sS][gG][bB]", "*.[cC][gG][bB]", "*.[gG][bB][cC]",1746 // Both1747 "*.[mM][bB]", "*.[eE][lL][fF]", "*.[zZ][iI][pP]", "*.[zZ]", "*.[gG][zZ]"1748 };1750 Gtk::FileFilter oAllGBAFilter;1751 oAllGBAFilter.set_name(_("All Gameboy Advance files"));1752 for (guint i = 0; i < G_N_ELEMENTS(acsPattern); i++)1753 {1754 oAllGBAFilter.add_pattern(acsPattern[i]);1755 }1757 Gtk::FileFilter oGBAFilter;1758 oGBAFilter.set_name(_("Gameboy Advance files"));1759 for (int i = 0; i < 3; i++)1760 {1761 oGBAFilter.add_pattern(acsPattern[i]);1762 }1764 Gtk::FileFilter oGBFilter;1765 oGBFilter.set_name(_("Gameboy files"));1766 for (int i = 3; i < 7; i++)1767 {1768 oGBFilter.add_pattern(acsPattern[i]);1769 }1771 poDialog->add_filter(oAllGBAFilter);1772 poDialog->add_filter(oGBAFilter);1773 poDialog->add_filter(oGBFilter);1775 #endif // ! GTKMM201777 m_poFileOpenDialog = poDialog;1778 }1780 void Window::vLoadBattery()1781 {1782 std::string sBattery;1783 std::string sDir = m_poDirConfig->sGetKey("batteries");1784 if (sDir == "")1785 {1786 sBattery = sCutSuffix(m_sRomFile) + ".sav";1787 }1788 else1789 {1790 sBattery = sDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile)) + ".sav";1791 }1793 if (m_stEmulator.emuReadBattery(sBattery.c_str()))1794 {1795 systemScreenMessage(_("Loaded battery"));1796 }1797 }1799 void Window::vSaveBattery()1800 {1801 std::string sBattery;1802 std::string sDir = m_poDirConfig->sGetKey("batteries");1803 if (sDir == "")1804 {1805 sBattery = sCutSuffix(m_sRomFile) + ".sav";1806 }1807 else1808 {1809 sBattery = sDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile)) + ".sav";1810 }1812 if (m_stEmulator.emuWriteBattery(sBattery.c_str()))1813 {1814 systemScreenMessage(_("Saved battery"));1815 }1816 }1818 void Window::vStartEmu()1819 {1820 if (m_oEmuSig.connected())1821 {1822 return;1823 }1825 m_oEmuSig = Glib::signal_idle().connect(SigC::slot(*this, &Window::bOnEmuIdle),1826 Glib::PRIORITY_DEFAULT_IDLE);1827 }1829 void Window::vStopEmu()1830 {1831 m_oEmuSig.disconnect();1832 m_bWasEmulating = false;1833 }1835 void Window::vSetThrottle(int _iPercent)1836 {1837 m_iThrottle = _iPercent;1838 m_poCoreConfig->vSetKey("throttle", _iPercent);1839 }1841 void Window::vSelectBestThrottleItem()1842 {1843 struct1844 {1845 const char * m_csName;1846 const int m_iThrottle;1847 }1848 astThrottle[] =1849 {1850 { "ThrottleNoThrottle", 0 },1851 { "Throttle25", 25 },1852 { "Throttle50", 50 },1853 { "Throttle100", 100 },1854 { "Throttle150", 150 },1855 { "Throttle200", 200 }1856 };1857 for (guint i = 0; i < G_N_ELEMENTS(astThrottle); i++)1858 {1859 Gtk::CheckMenuItem * poCMI;1860 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(m_poXml->get_widget(astThrottle[i].m_csName));1861 if (astThrottle[i].m_iThrottle == m_iThrottle)1862 {1863 poCMI->set_active();1864 }1865 }1866 }1868 void Window::vUpdateGameSlots()1869 {1870 if (m_eCartridge == CartridgeNone)1871 {1872 std::string sDateTime = _("----/--/-- --:--:--");1874 for (int i = 0; i < 10; i++)1875 {1876 char csPrefix[10];1877 snprintf(csPrefix, sizeof(csPrefix), "%2d ", i + 1);1879 Gtk::Label * poLabel;1880 poLabel = dynamic_cast<Gtk::Label *>(m_apoLoadGameItem[i]->get_child());1881 poLabel->set_text(csPrefix + sDateTime);1882 m_apoLoadGameItem[i]->set_sensitive(false);1884 poLabel = dynamic_cast<Gtk::Label *>(m_apoSaveGameItem[i]->get_child());1885 poLabel->set_text(csPrefix + sDateTime);1886 m_apoSaveGameItem[i]->set_sensitive(false);1888 m_astGameSlot[i].m_bEmpty = true;1889 }1890 }1891 else1892 {1893 std::string sFileBase;1894 std::string sDir = m_poDirConfig->sGetKey("saves");1895 if (sDir == "")1896 {1897 sFileBase = sCutSuffix(m_sRomFile);1898 }1899 else1900 {1901 sFileBase = sDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile));1902 }1904 const char * csDateFormat = _("%Y/%m/%d %H:%M:%S");1906 for (int i = 0; i < 10; i++)1907 {1908 char csPrefix[10];1909 snprintf(csPrefix, sizeof(csPrefix), "%2d ", i + 1);1911 char csSlot[10];1912 snprintf(csSlot, sizeof(csSlot), "%d", i + 1);1913 m_astGameSlot[i].m_sFile = sFileBase + csSlot + ".sgm";1915 std::string sDateTime;1916 struct stat stStat;1917 if (stat(m_astGameSlot[i].m_sFile.c_str(), &stStat) == -1)1918 {1919 sDateTime = _("----/--/-- --:--:--");1920 m_astGameSlot[i].m_bEmpty = true;1921 }1922 else1923 {1924 char csDateTime[30];1925 strftime(csDateTime, sizeof(csDateTime), csDateFormat,1926 localtime(&stStat.st_mtime));1927 sDateTime = csDateTime;1928 m_astGameSlot[i].m_bEmpty = false;1929 m_astGameSlot[i].m_uiTime = stStat.st_mtime;1930 }1932 Gtk::Label * poLabel;1933 poLabel = dynamic_cast<Gtk::Label *>(m_apoLoadGameItem[i]->get_child());1934 poLabel->set_text(csPrefix + sDateTime);1935 m_apoLoadGameItem[i]->set_sensitive(! m_astGameSlot[i].m_bEmpty);1937 poLabel = dynamic_cast<Gtk::Label *>(m_apoSaveGameItem[i]->get_child());1938 poLabel->set_text(csPrefix + sDateTime);1939 m_apoSaveGameItem[i]->set_sensitive();1940 }1941 }1942 }1944 } // VBA namespace