Mercurial > vba-clojure
view src/gtk/windowcallbacks.cpp @ 8:08a8e09ca414
add files required by automake
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:54:39 -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/Flash.h"31 #include "../gba/GBASound.h"32 #include "../gb/GB.h"33 #include "../gb/gbGlobals.h"34 #include "../gb/gbPrinter.h"35 #include "../common/Util.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 void Window::vOnFileOpen()65 {66 while (m_poFileOpenDialog->run() == Gtk::RESPONSE_OK)67 {68 if (bLoadROM(m_poFileOpenDialog->get_filename()))69 {70 break;71 }72 }73 m_poFileOpenDialog->hide();74 }76 void Window::vOnFileLoad()77 {78 std::string sSaveDir = m_poDirConfig->sGetKey("saves");80 #ifdef GTKMM2082 Gtk::FileSelection oDialog(_("Load game"));83 oDialog.set_transient_for(*this);85 if (sSaveDir == "")86 {87 oDialog.set_filename(Glib::path_get_dirname(m_sRomFile) + "/");88 }89 else90 {91 oDialog.set_filename(sSaveDir + "/");92 }94 #else // ! GTKMM2096 Gtk::FileChooserDialog oDialog(*this, _("Load game"));97 oDialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);98 oDialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);100 if (sSaveDir == "")101 {102 oDialog.set_current_folder(Glib::path_get_dirname(m_sRomFile));103 }104 else105 {106 oDialog.set_current_folder(sSaveDir);107 oDialog.add_shortcut_folder(sSaveDir);108 }110 Gtk::FileFilter oSaveFilter;111 oSaveFilter.set_name(_("VisualBoyAdvance save game"));112 oSaveFilter.add_pattern("*.[sS][gG][mM]");114 oDialog.add_filter(oSaveFilter);116 #endif // ! GTKMM20118 while (oDialog.run() == Gtk::RESPONSE_OK)119 {120 if (m_stEmulator.emuReadState(oDialog.get_filename().c_str()))121 {122 break;123 }124 }125 }127 void Window::vOnFileSave()128 {129 Glib::ustring sSaveDir = m_poDirConfig->sGetKey("saves");131 #ifdef GTKMM20133 Gtk::FileSelection oDialog(_("Save game"));134 oDialog.set_transient_for(*this);136 if (sSaveDir == "")137 {138 oDialog.set_filename(sCutSuffix(m_sRomFile));139 }140 else141 {142 oDialog.set_filename(sSaveDir + "/" +143 sCutSuffix(Glib::path_get_basename(m_sRomFile)));144 }146 #else // ! GTKMM20148 Gtk::FileChooserDialog oDialog(*this, _("Save game"),149 Gtk::FILE_CHOOSER_ACTION_SAVE);150 oDialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);151 oDialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);153 if (sSaveDir == "")154 {155 oDialog.set_current_folder(Glib::path_get_dirname(m_sRomFile));156 }157 else158 {159 oDialog.set_current_folder(sSaveDir);160 oDialog.add_shortcut_folder(sSaveDir);161 }162 oDialog.set_current_name(sCutSuffix(Glib::path_get_basename(m_sRomFile)));164 Gtk::FileFilter oSaveFilter;165 oSaveFilter.set_name(_("VisualBoyAdvance save game"));166 oSaveFilter.add_pattern("*.[sS][gG][mM]");168 oDialog.add_filter(oSaveFilter);170 #endif // ! GTKMM20172 while (oDialog.run() == Gtk::RESPONSE_OK)173 {174 Glib::ustring sFile = oDialog.get_filename();175 if (! bHasSuffix(sFile, ".sgm", false))176 {177 sFile += ".sgm";178 }180 if (Glib::file_test(sFile, Glib::FILE_TEST_EXISTS))181 {182 Gtk::MessageDialog oConfirmDialog(*this,183 _("File already exists. Overwrite it?"),184 #ifndef GTKMM20185 false,186 #endif // ! GTKMM20187 Gtk::MESSAGE_QUESTION,188 Gtk::BUTTONS_YES_NO);189 if (oConfirmDialog.run() != Gtk::RESPONSE_YES)190 {191 continue;192 }193 }195 if (m_stEmulator.emuWriteState(sFile.c_str()))196 {197 break;198 }199 }200 }202 void Window::vOnLoadGameMostRecent()203 {204 int iMostRecent = -1;205 time_t uiTimeMax;207 for (int i = 0; i < 10; i++)208 {209 if (! m_astGameSlot[i].m_bEmpty210 && (iMostRecent < 0 || m_astGameSlot[i].m_uiTime > uiTimeMax))211 {212 iMostRecent = i;213 uiTimeMax = m_astGameSlot[i].m_uiTime;214 }215 }217 if (iMostRecent >= 0)218 {219 vOnLoadGame(iMostRecent + 1);220 }221 }223 void Window::vOnLoadGameAutoToggled(Gtk::CheckMenuItem * _poCMI)224 {225 m_poCoreConfig->vSetKey("load_game_auto", _poCMI->get_active());226 }228 void Window::vOnLoadGame(int _iSlot)229 {230 int i = _iSlot - 1;231 if (! m_astGameSlot[i].m_bEmpty)232 {233 m_stEmulator.emuReadState(m_astGameSlot[i].m_sFile.c_str());234 m_poFilePauseItem->set_active(false);235 }236 }238 void Window::vOnSaveGameOldest()239 {240 int iOldest = -1;241 time_t uiTimeMin;243 for (int i = 0; i < 10; i++)244 {245 if (! m_astGameSlot[i].m_bEmpty246 && (iOldest < 0 || m_astGameSlot[i].m_uiTime < uiTimeMin))247 {248 iOldest = i;249 uiTimeMin = m_astGameSlot[i].m_uiTime;250 }251 }253 if (iOldest >= 0)254 {255 vOnSaveGame(iOldest + 1);256 }257 else258 {259 vOnSaveGame(1);260 }261 }263 void Window::vOnSaveGame(int _iSlot)264 {265 int i = _iSlot - 1;266 m_stEmulator.emuWriteState(m_astGameSlot[i].m_sFile.c_str());267 vUpdateGameSlots();268 }270 void Window::vOnFilePauseToggled(Gtk::CheckMenuItem * _poCMI)271 {272 m_bPaused = _poCMI->get_active();273 if (emulating)274 {275 if (m_bPaused)276 {277 vStopEmu();278 soundPause();279 }280 else281 {282 vStartEmu();283 soundResume();284 }285 }286 }288 void Window::vOnFileReset()289 {290 if (emulating)291 {292 m_stEmulator.emuReset(true);293 m_poFilePauseItem->set_active(false);294 }295 }297 void Window::vOnRecentReset()298 {299 m_listHistory.clear();300 vClearHistoryMenu();301 }303 void Window::vOnRecentFreezeToggled(Gtk::CheckMenuItem * _poCMI)304 {305 m_poRecentResetItem->set_sensitive(! _poCMI->get_active());306 m_poHistoryConfig->vSetKey("freeze", _poCMI->get_active());307 }309 void Window::vOnRecentFile(std::string _sFile)310 {311 bLoadROM(_sFile);312 }314 void Window::vOnImportBatteryFile()315 {316 std::string BatteryDir = m_poDirConfig->sGetKey("batteries");318 #ifdef GTKMM20320 Gtk::FileSelection oDialog(_("Import battery file"));321 oDialog.set_transient_for(*this);323 if (BatteryDir == "")324 {325 oDialog.set_filename(Glib::path_get_dirname(m_sRomFile) + "/");326 }327 else328 {329 oDialog.set_filename(BatteryDir + "/");330 }332 #else // ! GTKMM20334 Gtk::FileChooserDialog oDialog(*this, _("Import battery file"));335 oDialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);336 oDialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);338 if (BatteryDir == "")339 {340 oDialog.set_current_folder(Glib::path_get_dirname(m_sRomFile));341 }342 else343 {344 oDialog.set_current_folder(BatteryDir);345 oDialog.add_shortcut_folder(BatteryDir);346 }348 Gtk::FileFilter oBatteryFilter;349 oBatteryFilter.set_name(_("Battery file"));350 oBatteryFilter.add_pattern("*.[sS][aA][vV]");352 Gtk::FileFilter oFlashFilter;353 oFlashFilter.set_name(_("Flash save"));354 oFlashFilter.add_pattern("*.[dD][aA][tT]");356 oDialog.add_filter(oBatteryFilter);357 oDialog.add_filter(oFlashFilter);359 #endif // ! GTKMM20361 while (oDialog.run() == Gtk::RESPONSE_OK)362 {363 Gtk::MessageDialog oConfirmDialog(*this,364 _("Importing a battery file will erase any saved games and reset the emulator. Do you want to continue?"),365 #ifndef GTKMM20366 false,367 #endif // ! GTKMM20368 Gtk::MESSAGE_QUESTION,369 Gtk::BUTTONS_YES_NO);370 if (oConfirmDialog.run() != Gtk::RESPONSE_YES)371 {372 continue;373 }375 if (m_stEmulator.emuReadBattery(oDialog.get_filename().c_str()))376 {377 m_stEmulator.emuReset(false);378 break;379 }380 else381 {382 vPopupError(_("Failed to import battery file %s."),383 oDialog.get_filename().c_str());384 }385 }386 }388 void Window::vOnExportBatteryFile()389 {390 std::string sBatteryDir = m_poDirConfig->sGetKey("batteries");392 #ifdef GTKMM20394 Gtk::FileSelection oDialog(_("Export battery file"));395 oDialog.set_transient_for(*this);397 if (sBatteryDir == "")398 {399 oDialog.set_filename(sCutSuffix(m_sRomFile));400 }401 else402 {403 oDialog.set_filename(sBatteryDir + "/" +404 sCutSuffix(Glib::path_get_basename(m_sRomFile)));405 }407 #else // ! GTKMM20409 Gtk::FileChooserDialog oDialog(*this, _("Export battery file"),410 Gtk::FILE_CHOOSER_ACTION_SAVE);411 oDialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);412 oDialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);414 if (sBatteryDir == "")415 {416 oDialog.set_current_folder(Glib::path_get_dirname(m_sRomFile));417 }418 else419 {420 oDialog.set_current_folder(sBatteryDir);421 oDialog.add_shortcut_folder(sBatteryDir);422 }423 oDialog.set_current_name(sCutSuffix(Glib::path_get_basename(m_sRomFile)));425 Gtk::FileFilter oBatteryFilter;426 oBatteryFilter.set_name(_("Battery file"));427 oBatteryFilter.add_pattern("*.[sS][aA][vV]");429 Gtk::FileFilter oFlashFilter;430 oFlashFilter.set_name(_("Flash save"));431 oFlashFilter.add_pattern("*.[dD][aA][tT]");433 oDialog.add_filter(oBatteryFilter);434 oDialog.add_filter(oFlashFilter);436 #endif // ! GTKMM20438 while (oDialog.run() == Gtk::RESPONSE_OK)439 {440 Glib::ustring sFile = oDialog.get_filename();441 Glib::ustring sExt;443 #ifdef GTKMM20445 sExt = ".sav";447 #else // ! GTKMM20449 if (oDialog.get_filter() == &oBatteryFilter)450 {451 sExt = ".sav";452 }453 else454 {455 sExt = ".dat";456 }458 #endif // ! GTKMM20460 if (! bHasSuffix(sFile, sExt, false))461 {462 sFile += sExt;463 }465 if (Glib::file_test(sFile, Glib::FILE_TEST_EXISTS))466 {467 Gtk::MessageDialog oConfirmDialog(*this,468 _("File already exists. Overwrite it?"),469 #ifndef GTKMM20470 false,471 #endif // ! GTKMM20472 Gtk::MESSAGE_QUESTION,473 Gtk::BUTTONS_YES_NO);474 if (oConfirmDialog.run() != Gtk::RESPONSE_YES)475 {476 continue;477 }478 }480 bool bResult;481 if (m_eCartridge == CartridgeGB)482 {483 bResult = gbWriteBatteryFile(sFile.c_str(), false);484 }485 else486 {487 bResult = m_stEmulator.emuWriteBattery(sFile.c_str());488 }490 if (bResult)491 {492 break;493 }494 else495 {496 vPopupError(_("Failed to export battery file %s."),497 sFile.c_str());498 }499 }500 }502 void Window::vOnFileScreenCapture()503 {504 std::string sCaptureDir = m_poDirConfig->sGetKey("captures");506 #ifdef GTKMM20508 Gtk::FileSelection oDialog(_("Save screenshot"));509 oDialog.set_transient_for(*this);511 if (sCaptureDir == "")512 {513 oDialog.set_filename(sCutSuffix(m_sRomFile));514 }515 else516 {517 oDialog.set_filename(sCaptureDir + "/" +518 sCutSuffix(Glib::path_get_basename(m_sRomFile)));519 }521 #else // ! GTKMM20523 Gtk::FileChooserDialog oDialog(*this, _("Save screenshot"),524 Gtk::FILE_CHOOSER_ACTION_SAVE);525 oDialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);526 oDialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);528 if (sCaptureDir == "")529 {530 oDialog.set_current_folder(Glib::path_get_dirname(m_sRomFile));531 }532 else533 {534 oDialog.set_current_folder(sCaptureDir);535 oDialog.add_shortcut_folder(sCaptureDir);536 }537 oDialog.set_current_name(sCutSuffix(Glib::path_get_basename(m_sRomFile)));539 Gtk::FileFilter oPngFilter;540 oPngFilter.set_name(_("PNG image"));541 oPngFilter.add_pattern("*.[pP][nN][gG]");543 Gtk::FileFilter oBmpFilter;544 oBmpFilter.set_name(_("BMP image"));545 oBmpFilter.add_pattern("*.[bB][mM][pP]");547 oDialog.add_filter(oPngFilter);548 oDialog.add_filter(oBmpFilter);550 if (m_poCoreConfig->sGetKey("screenshot_format") == "bmp")551 {552 oDialog.set_filter(oBmpFilter);553 }555 #endif // ! GTKMM20557 while (oDialog.run() == Gtk::RESPONSE_OK)558 {559 Glib::ustring sFile = oDialog.get_filename();560 Glib::ustring sExt;562 #ifdef GTKMM20564 sExt = "." + m_poCoreConfig->sGetKey("screenshot_format");566 #else // ! GTKMM20568 if (oDialog.get_filter() == &oPngFilter)569 {570 sExt = ".png";571 }572 else573 {574 sExt = ".bmp";575 }577 #endif // ! GTKMM20579 if (! bHasSuffix(sFile, sExt, false))580 {581 sFile += sExt;582 }584 if (Glib::file_test(sFile, Glib::FILE_TEST_EXISTS))585 {586 Gtk::MessageDialog oConfirmDialog(*this,587 _("File already exists. Overwrite it?"),588 #ifndef GTKMM20589 false,590 #endif // ! GTKMM20591 Gtk::MESSAGE_QUESTION,592 Gtk::BUTTONS_YES_NO);593 if (oConfirmDialog.run() != Gtk::RESPONSE_YES)594 {595 continue;596 }597 }599 bool bResult;600 if (sExt == ".png")601 {602 bResult = m_stEmulator.emuWritePNG(sFile.c_str());603 }604 else605 {606 bResult = m_stEmulator.emuWriteBMP(sFile.c_str());607 }609 if (bResult)610 {611 break;612 }613 }614 }616 void Window::vOnFileClose()617 {618 if (m_eCartridge != CartridgeNone)619 {620 soundPause();621 vStopEmu();622 vSetDefaultTitle();623 vDrawDefaultScreen();624 vSaveBattery();625 m_stEmulator.emuCleanUp();626 m_eCartridge = CartridgeNone;627 emulating = 0;629 vUpdateGameSlots();631 for (std::list<Gtk::Widget *>::iterator it = m_listSensitiveWhenPlaying.begin();632 it != m_listSensitiveWhenPlaying.end();633 it++)634 {635 (*it)->set_sensitive(false);636 }638 m_poFilePauseItem->set_active(false);639 }640 }642 void Window::vOnFileExit()643 {644 hide();645 }647 void Window::vOnFrameskipToggled(Gtk::CheckMenuItem * _poCMI, int _iValue)648 {649 if (! _poCMI->get_active())650 {651 return;652 }654 if (_iValue >= 0 && _iValue <= 9)655 {656 m_poCoreConfig->vSetKey("frameskip", _iValue);657 gbFrameSkip = _iValue;658 systemFrameSkip = _iValue;659 m_bAutoFrameskip = false;660 }661 else662 {663 m_poCoreConfig->vSetKey("frameskip", "auto");664 gbFrameSkip = 0;665 systemFrameSkip = 0;666 m_bAutoFrameskip = true;667 }668 }670 void Window::vOnThrottleToggled(Gtk::CheckMenuItem * _poCMI, int _iPercent)671 {672 if (! _poCMI->get_active())673 {674 return;675 }677 vSetThrottle(_iPercent);679 // Initialize the frameskip adjustment each time throttle is changed680 if (m_bAutoFrameskip)681 {682 systemFrameSkip = 0;683 }684 }686 void Window::vOnThrottleOther(Gtk::CheckMenuItem * _poCMI)687 {688 if (! _poCMI->get_active())689 {690 return;691 }693 Glib::RefPtr<Xml> poXml;694 poXml = Xml::create(PKGDATADIR "/vba.glade", "ThrottleDialog");696 Gtk::Dialog * poDialog = dynamic_cast<Gtk::Dialog *>(poXml->get_widget("ThrottleDialog"));697 Gtk::SpinButton * poSpin = dynamic_cast<Gtk::SpinButton *>(poXml->get_widget("ThrottleSpin"));699 poDialog->set_transient_for(*this);701 if (m_iThrottle != 0)702 {703 poSpin->set_value(m_iThrottle);704 }705 else706 {707 poSpin->set_value(100);708 }710 if (poDialog->run() == Gtk::RESPONSE_OK)711 {712 vSetThrottle(poSpin->get_value_as_int());713 }715 delete poDialog;716 vSelectBestThrottleItem();717 }719 void Window::vOnVideoScaleToggled(Gtk::CheckMenuItem * _poCMI, int _iScale)720 {721 if (! _poCMI->get_active())722 {723 return;724 }726 m_poDisplayConfig->vSetKey("scale", _iScale);727 vUpdateScreen();728 }730 void Window::vOnLayerToggled(Gtk::CheckMenuItem * _poCMI, int _iLayer)731 {732 int iMask = (0x0100 << _iLayer);733 if (_poCMI->get_active())734 {735 layerSettings |= iMask;736 }737 else738 {739 layerSettings &= ~iMask;740 }741 layerEnable = DISPCNT & layerSettings;743 const char * acsLayers[] =744 {745 "layer_bg0",746 "layer_bg1",747 "layer_bg2",748 "layer_bg3",749 "layer_obj",750 "layer_win0",751 "layer_win1",752 "layer_objwin"753 };754 m_poCoreConfig->vSetKey(acsLayers[_iLayer], _poCMI->get_active());755 }757 void Window::vOnDirectories()758 {759 Glib::RefPtr<Xml> poXml;760 poXml = Xml::create(PKGDATADIR "/vba.glade", "DirectoriesDialog");762 struct763 {764 const char * m_csKey;765 const char * m_csEntry;766 const char * m_csResetButton;767 const char * m_csSelectButton;768 }769 astRow[] =770 {771 { "gba_roms", "GBARomsDirEntry", "GBARomsDirResetButton", "GBARomsDirSelectButton" },772 { "gb_roms", "GBRomsDirEntry", "GBRomsDirResetButton", "GBRomsDirSelectButton" },773 { "batteries", "BatteriesDirEntry", "BatteriesDirResetButton", "BatteriesDirSelectButton" },774 { "saves", "SavesDirEntry", "SavesDirResetButton", "SavesDirSelectButton" },775 { "captures", "CapturesDirEntry", "CapturesDirResetButton", "CapturesDirSelectButton" }776 };778 for (guint i = 0; i < G_N_ELEMENTS(astRow); i++)779 {780 Gtk::Entry * poEntry = dynamic_cast<Gtk::Entry *>(poXml->get_widget(astRow[i].m_csEntry));781 Gtk::Button * poReset = dynamic_cast<Gtk::Button *>(poXml->get_widget(astRow[i].m_csResetButton));782 Gtk::Button * poSelect = dynamic_cast<Gtk::Button *>(poXml->get_widget(astRow[i].m_csSelectButton));784 poEntry->set_text(m_poDirConfig->sGetKey(astRow[i].m_csKey));786 poReset->signal_clicked().connect(SigC::bind<Gtk::Entry *>(787 SigC::slot(*this, &Window::vOnDirectoryReset),788 poEntry));789 poSelect->signal_clicked().connect(SigC::bind<Gtk::Entry *>(790 SigC::slot(*this, &Window::vOnDirectorySelect),791 poEntry));792 }794 Gtk::Dialog * poDialog = dynamic_cast<Gtk::Dialog *>(poXml->get_widget("DirectoriesDialog"));795 poDialog->set_transient_for(*this);797 if (poDialog->run() == Gtk::RESPONSE_OK)798 {799 for (guint i = 0; i < G_N_ELEMENTS(astRow); i++)800 {801 Gtk::Entry * poEntry = dynamic_cast<Gtk::Entry *>(poXml->get_widget(astRow[i].m_csEntry));802 Glib::ustring sDir = poEntry->get_text();803 if (! Glib::file_test(sDir, Glib::FILE_TEST_IS_DIR))804 {805 sDir = "";806 }807 m_poDirConfig->vSetKey(astRow[i].m_csKey, sDir);808 }810 // Needed if saves dir changed811 vUpdateGameSlots();812 }814 delete poDialog;815 }817 void Window::vOnDirectoryReset(Gtk::Entry * _poEntry)818 {819 _poEntry->set_text("");820 }822 void Window::vOnDirectorySelect(Gtk::Entry * _poEntry)823 {824 #ifdef GTKMM20826 Gtk::FileSelection oDialog(_("Select directory"));827 oDialog.set_transient_for(*this);829 if (_poEntry->get_text() != "")830 {831 oDialog.set_filename(_poEntry->get_text() + "/");832 }834 if (oDialog.run() == Gtk::RESPONSE_OK)835 {836 std::string sFile = oDialog.get_filename();837 if (! Glib::file_test(sFile, Glib::FILE_TEST_IS_DIR))838 {839 sFile = Glib::path_get_dirname(sFile);840 }841 _poEntry->set_text(sFile);842 }844 #else // ! GTKMM20846 Gtk::FileChooserDialog oDialog(*this, _("Select directory"),847 Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);848 oDialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);849 oDialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);851 if (_poEntry->get_text() != "")852 {853 oDialog.add_shortcut_folder(_poEntry->get_text());854 oDialog.set_current_folder(_poEntry->get_text());855 }857 if (oDialog.run() == Gtk::RESPONSE_OK)858 {859 _poEntry->set_text(oDialog.get_filename());860 }862 #endif // ! GTKMM20863 }865 void Window::vOnPauseWhenInactiveToggled(Gtk::CheckMenuItem * _poCMI)866 {867 m_poDisplayConfig->vSetKey("pause_when_inactive", _poCMI->get_active());868 }870 void Window::vOnSelectBios()871 {872 #ifdef GTKMM20874 Gtk::FileSelection oDialog(_("Select BIOS file"));875 oDialog.set_transient_for(*this);877 if (m_poCoreConfig->sGetKey("bios_file") != "")878 {879 oDialog.set_filename(m_poCoreConfig->sGetKey("bios_file"));880 }882 #else // ! GTKMM20884 Gtk::FileChooserDialog oDialog(*this, _("Select BIOS file"));885 oDialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);886 oDialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);888 if (m_poCoreConfig->sGetKey("bios_file") != "")889 {890 oDialog.set_filename(m_poCoreConfig->sGetKey("bios_file"));891 }893 const char * acsPattern[] =894 {895 "*.[bB][iI][nN]", "*.[aA][gG][bB]", "*.[gG][bB][aA]",896 "*.[bB][iI][oO][sS]", "*.[zZ][iI][pP]", "*.[zZ]", "*.[gG][zZ]"897 };899 Gtk::FileFilter oAllFilter;900 oAllFilter.set_name(_("All files"));901 oAllFilter.add_pattern("*");903 Gtk::FileFilter oBiosFilter;904 oBiosFilter.set_name(_("Gameboy Advance BIOS"));905 for (guint i = 0; i < G_N_ELEMENTS(acsPattern); i++)906 {907 oBiosFilter.add_pattern(acsPattern[i]);908 }910 oDialog.add_filter(oAllFilter);911 oDialog.add_filter(oBiosFilter);913 oDialog.set_filter(oBiosFilter);915 #endif // ! GTKMM20917 while (oDialog.run() == Gtk::RESPONSE_OK)918 {919 if (Glib::file_test(oDialog.get_filename(), Glib::FILE_TEST_IS_REGULAR))920 {921 m_poCoreConfig->vSetKey("bios_file", oDialog.get_filename());922 m_poUseBiosItem->set_sensitive();923 break;924 }925 }926 }928 void Window::vOnUseBiosToggled(Gtk::CheckMenuItem * _poCMI)929 {930 m_poCoreConfig->vSetKey("use_bios_file", _poCMI->get_active());931 }933 void Window::vOnShowSpeedToggled(Gtk::CheckMenuItem * _poCMI, int _iShowSpeed)934 {935 if (! _poCMI->get_active())936 {937 return;938 }940 m_eShowSpeed = (EShowSpeed)_iShowSpeed;941 if (m_eShowSpeed == ShowNone)942 {943 vSetDefaultTitle();944 }945 m_poDisplayConfig->vSetKey("show_speed", _iShowSpeed);946 }948 void Window::vOnSaveTypeToggled(Gtk::CheckMenuItem * _poCMI, int _iSaveType)949 {950 if (! _poCMI->get_active())951 {952 return;953 }955 cpuSaveType = _iSaveType;956 m_poCoreConfig->vSetKey("save_type", _iSaveType);957 }959 void Window::vOnFlashSizeToggled(Gtk::CheckMenuItem * _poCMI, int _iFlashSize)960 {961 if (! _poCMI->get_active())962 {963 return;964 }966 if (_iFlashSize == 64)967 {968 flashSetSize(0x10000);969 }970 else971 {972 flashSetSize(0x20000);973 }974 m_poCoreConfig->vSetKey("flash_size", _iFlashSize);975 }977 void Window::vOnScreenshotFormatToggled(Gtk::CheckMenuItem * _poCMI, std::string _sFormat)978 {979 if (! _poCMI->get_active())980 {981 return;982 }984 m_poCoreConfig->vSetKey("screenshot_format", _sFormat);985 }987 void Window::vOnSoundStatusToggled(Gtk::CheckMenuItem * _poCMI, int _iSoundStatus)988 {989 if (! _poCMI->get_active())990 {991 return;992 }994 std::string sSoundStatus;995 switch (_iSoundStatus)996 {997 case SoundOff:998 soundOffFlag = true;999 if (systemSoundOn)1000 {1001 soundShutdown();1002 }1003 sSoundStatus = "off";1004 break;1005 case SoundMute:1006 soundDisableChannels(0x30f);1007 sSoundStatus = "mute";1008 break;1009 case SoundOn:1010 if (soundOffFlag)1011 {1012 soundOffFlag = false;1013 if (! soundInit())1014 {1015 m_poSoundOffItem->set_active();1016 return;1017 }1018 }1019 soundEnableChannels(0x30f);1020 sSoundStatus = "on";1021 break;1022 }1023 m_poSoundConfig->vSetKey("status", sSoundStatus);1024 }1026 void Window::vOnSoundEchoToggled(Gtk::CheckMenuItem * _poCMI)1027 {1028 soundEcho = _poCMI->get_active();1029 m_poSoundConfig->vSetKey("echo", soundEcho);1030 }1032 void Window::vOnSoundLowPassToggled(Gtk::CheckMenuItem * _poCMI)1033 {1034 soundLowPass = _poCMI->get_active();1035 m_poSoundConfig->vSetKey("low_pass", soundLowPass);1036 }1038 void Window::vOnSoundReverseToggled(Gtk::CheckMenuItem * _poCMI)1039 {1040 soundReverse = _poCMI->get_active();1041 m_poSoundConfig->vSetKey("reverse_stereo", soundReverse);1042 }1044 void Window::vOnSoundChannelToggled(Gtk::CheckMenuItem * _poCMI, int _iSoundChannel)1045 {1046 int iShift = _iSoundChannel;1047 if (_iSoundChannel > 3)1048 {1049 iShift += 4;1050 }1051 int iFlag = 1 << iShift;1052 int iActive = soundGetEnabledChannels() & 0x30f;1053 if (_poCMI->get_active())1054 {1055 iActive |= iFlag;1056 }1057 else1058 {1059 iActive &= ~iFlag;1060 }1061 soundEnableChannels(iActive);1062 soundDisableChannels(~iActive & 0x30f);1064 const char * acsChannels[] =1065 {1066 "channel_1",1067 "channel_2",1068 "channel_3",1069 "channel_4",1070 "channel_A",1071 "channel_B"1072 };1073 m_poSoundConfig->vSetKey(acsChannels[_iSoundChannel], _poCMI->get_active());1074 }1076 void Window::vOnSoundQualityToggled(Gtk::CheckMenuItem * _poCMI, int _iSoundQuality)1077 {1078 if (! _poCMI->get_active())1079 {1080 return;1081 }1083 m_eSoundQuality = (ESoundQuality)_iSoundQuality;1084 if (m_eCartridge == CartridgeGBA)1085 {1086 soundSetQuality(_iSoundQuality);1087 }1088 else if (m_eCartridge == CartridgeGB)1089 {1090 gbSoundSetQuality(_iSoundQuality);1091 }1092 m_poSoundConfig->vSetKey("quality", _iSoundQuality);1093 }1095 void Window::vOnSoundVolumeToggled(Gtk::CheckMenuItem * _poCMI, int _iSoundVolume)1096 {1097 if (! _poCMI->get_active())1098 {1099 return;1100 }1102 soundVolume = _iSoundVolume;1103 m_poSoundConfig->vSetKey("volume", _iSoundVolume);1104 }1106 void Window::vOnGBBorderToggled(Gtk::CheckMenuItem * _poCMI)1107 {1108 gbBorderOn = _poCMI->get_active();1109 if (emulating && m_eCartridge == CartridgeGB && _poCMI->get_active())1110 {1111 gbSgbRenderBorder();1112 }1113 vUpdateScreen();1114 m_poCoreConfig->vSetKey("gb_border", _poCMI->get_active());1115 }1117 void Window::vOnGBPrinterToggled(Gtk::CheckMenuItem * _poCMI)1118 {1119 if (_poCMI->get_active())1120 {1121 gbSerialFunction = gbPrinterSend;1122 }1123 else1124 {1125 gbSerialFunction = NULL;1126 }1127 m_poCoreConfig->vSetKey("gb_printer", _poCMI->get_active());1128 }1130 void Window::vOnEmulatorTypeToggled(Gtk::CheckMenuItem * _poCMI, int _iEmulatorType)1131 {1132 gbEmulatorType = _iEmulatorType;1133 m_poCoreConfig->vSetKey("emulator_type", _iEmulatorType);1134 }1136 void Window::vOnFilter2xToggled(Gtk::CheckMenuItem * _poCMI, int _iFilter2x)1137 {1138 if (! _poCMI->get_active())1139 {1140 return;1141 }1143 m_poScreenArea->vSetFilter2x((EFilter2x)_iFilter2x);1144 if (emulating)1145 {1146 vDrawScreen();1147 }1148 m_poDisplayConfig->vSetKey("filter2x", _iFilter2x);1149 }1151 void Window::vOnFilterIBToggled(Gtk::CheckMenuItem * _poCMI, int _iFilterIB)1152 {1153 if (! _poCMI->get_active())1154 {1155 return;1156 }1158 m_poScreenArea->vSetFilterIB((EFilterIB)_iFilterIB);1159 if (emulating)1160 {1161 vDrawScreen();1162 }1163 m_poDisplayConfig->vSetKey("filterIB", _iFilterIB);1164 }1166 #ifdef MMX1167 void Window::vOnDisableMMXToggled(Gtk::CheckMenuItem * _poCMI)1168 {1169 cpu_mmx = ! _poCMI->get_active();1170 m_poDisplayConfig->vSetKey("filter_disable_mmx", _poCMI->get_active());1171 }1172 #endif // MMX1174 void Window::vOnJoypadConfigure(int _iJoypad)1175 {1176 Glib::RefPtr<Xml> poXml;1177 poXml = Xml::create(PKGDATADIR "/vba.glade", "JoypadConfigDialog");1179 JoypadConfigDialog * poDialog = NULL;1180 poXml->get_widget_derived<JoypadConfigDialog>("JoypadConfigDialog", poDialog);1181 poDialog->set_transient_for(*this);1182 poDialog->vSetConfig(m_oJoypads[_iJoypad - 1]);1184 if (poDialog->run() == Gtk::RESPONSE_OK)1185 {1186 m_oJoypads[_iJoypad - 1] = poDialog->stGetConfig();1187 if (_iJoypad == m_poInputConfig->oGetKey<int>("active_joypad"))1188 {1189 if (m_poKeymap != NULL)1190 {1191 delete m_poKeymap;1192 }1193 m_poKeymap = m_oJoypads[_iJoypad - 1].poCreateKeymap();1194 }1195 }1197 delete poDialog;1198 }1200 void Window::vOnJoypadToggled(Gtk::CheckMenuItem * _poCMI, int _iJoypad)1201 {1202 if (! _poCMI->get_active())1203 {1204 return;1205 }1207 if (m_poKeymap != NULL)1208 {1209 delete m_poKeymap;1210 }1211 m_poKeymap = m_oJoypads[_iJoypad - 1].poCreateKeymap();1213 m_poInputConfig->vSetKey("active_joypad", _iJoypad);1214 }1216 void Window::vOnAutofireToggled(Gtk::CheckMenuItem * _poCMI, u32 _uiKeyFlag)1217 {1218 if (_poCMI->get_active())1219 {1220 m_uiAutofireState |= _uiKeyFlag;1221 }1222 else1223 {1224 m_uiAutofireState &= ~_uiKeyFlag;1225 }1227 std::string sKey;1228 if (_uiKeyFlag == KeyFlagA)1229 {1230 sKey = "autofire_A";1231 }1232 else if (_uiKeyFlag == KeyFlagB)1233 {1234 sKey = "autofire_B";1235 }1236 else if (_uiKeyFlag == KeyFlagL)1237 {1238 sKey = "autofire_L";1239 }1240 else if (_uiKeyFlag == KeyFlagR)1241 {1242 sKey = "autofire_R";1243 }1244 m_poInputConfig->vSetKey(sKey, _poCMI->get_active());1245 }1247 void Window::vOnGDBWait()1248 {1249 Glib::RefPtr<Xml> poXml;1250 poXml = Xml::create(PKGDATADIR "/vba.glade", "TcpPortDialog");1252 Gtk::Dialog * poDialog = dynamic_cast<Gtk::Dialog *>(poXml->get_widget("TcpPortDialog"));1253 Gtk::SpinButton * poSpin = dynamic_cast<Gtk::SpinButton *>(poXml->get_widget("TcpPortSpin"));1255 poDialog->set_transient_for(*this);1257 int iPort = 55555;1258 poSpin->set_value(iPort);1260 bool bOk = false;1261 if (poDialog->run() == Gtk::RESPONSE_OK)1262 {1263 bOk = true;1264 iPort = poSpin->get_value_as_int();1265 }1266 delete poDialog;1268 if (! bOk)1269 {1270 return;1271 }1273 m_eCartridge = CartridgeGBA;1274 m_sRomFile = "gnu_stub";1275 m_stEmulator = GBASystem;1277 rom = (u8 *) malloc(0x2000000);1278 workRAM = (u8 *) calloc(1, 0x40000);1279 bios = (u8 *) calloc(1, 0x4000);1280 internalRAM = (u8 *) calloc(1, 0x8000);1281 paletteRAM = (u8 *) calloc(1, 0x400);1282 vram = (u8 *) calloc(1, 0x20000);1283 oam = (u8 *) calloc(1, 0x400);1284 pix = (u8 *) calloc(1, 4 * m_iGBAScreenWidth * m_iGBAScreenHeight);1285 ioMem = (u8 *) calloc(1, 0x400);1287 useBios = m_poCoreConfig->oGetKey<bool>("use_bios_file");1288 //CPUInit(m_poCoreConfig->sGetKey("bios_file").c_str(), useBios);1289 CPUInit();1290 CPUReset();1292 for (std::list<Gtk::Widget *>::iterator it = m_listSensitiveWhenPlaying.begin();1293 it != m_listSensitiveWhenPlaying.end();1294 it++)1295 {1296 (*it)->set_sensitive();1297 }1299 if (m_poCoreConfig->oGetKey<bool>("load_game_auto"))1300 {1301 vOnLoadGameMostRecent();1302 }1304 vStartEmu();1306 emulating = 1;1308 dbgMain = remoteStubMain;1309 dbgSignal = remoteStubSignal;1310 dbgOutput = remoteOutput;1311 debugger = true;1313 remoteSetProtocol(0);1314 remoteSetPort(iPort);1315 remoteInit();1316 }1318 void Window::vOnGDBLoadAndWait()1319 {1320 bool bLoaded = false;1322 while (m_poFileOpenDialog->run() == Gtk::RESPONSE_OK)1323 {1324 if (bLoadROM(m_poFileOpenDialog->get_filename()))1325 {1326 bLoaded = true;1327 break;1328 }1329 }1330 m_poFileOpenDialog->hide();1332 if (! bLoaded)1333 {1334 return;1335 }1337 if (m_eCartridge != CartridgeGBA)1338 {1339 vPopupError(_("Only GBA images are supported."));1340 vOnFileClose();1341 return;1342 }1344 Glib::RefPtr<Xml> poXml;1345 poXml = Xml::create(PKGDATADIR "/vba.glade", "TcpPortDialog");1347 Gtk::Dialog * poDialog = dynamic_cast<Gtk::Dialog *>(poXml->get_widget("TcpPortDialog"));1348 Gtk::SpinButton * poSpin = dynamic_cast<Gtk::SpinButton *>(poXml->get_widget("TcpPortSpin"));1350 poDialog->set_transient_for(*this);1352 int iPort = 55555;1353 poSpin->set_value(iPort);1355 bool bOk = false;1356 if (poDialog->run() == Gtk::RESPONSE_OK)1357 {1358 bOk = true;1359 iPort = poSpin->get_value_as_int();1360 }1361 delete poDialog;1363 if (! bOk)1364 {1365 return;1366 }1368 dbgMain = remoteStubMain;1369 dbgSignal = remoteStubSignal;1370 dbgOutput = remoteOutput;1371 debugger = true;1373 remoteSetProtocol(0);1374 remoteSetPort(iPort);1375 remoteInit();1376 }1378 void Window::vOnGDBBreak()1379 {1380 if (armState)1381 {1382 armNextPC -= 4;1383 reg[15].I -= 4;1384 }1385 else1386 {1387 armNextPC -= 2;1388 reg[15].I -= 2;1389 }1391 debugger = true;1392 }1394 void Window::vOnGDBDisconnect()1395 {1396 remoteCleanUp();1397 debugger = false;1398 }1400 void Window::vOnHelpAbout()1401 {1402 Glib::RefPtr<Xml> poXml;1403 poXml = Xml::create(PKGDATADIR "/vba.glade", "AboutDialog");1405 Gtk::Dialog * poDialog = dynamic_cast<Gtk::Dialog *>(poXml->get_widget("AboutDialog"));1406 poDialog->set_transient_for(*this);1408 Gtk::Image oIcon(PKGDATADIR "/vba-64.png");1409 oIcon.show();1410 Gtk::Container * poIconContainer = dynamic_cast<Gtk::Container *>(poXml->get_widget("AboutIconContainer"));1411 poIconContainer->add(oIcon);1413 Gtk::Label * poLabel = dynamic_cast<Gtk::Label *>(poXml->get_widget("VersionLabel"));1414 poLabel->set_markup("<b><big>" PACKAGE " " VERSION "</big></b>");1416 poDialog->run();1417 delete poDialog;1418 }1420 bool Window::bOnEmuIdle()1421 {1422 if (debugger && m_stEmulator.emuHasDebugger)1423 {1424 dbgMain();1425 return true;1426 }1428 if (m_uiThrottleDelay != 0)1429 {1430 u32 uiTime = SDL_GetTicks();1431 if (uiTime - m_uiThrottleLastTime >= m_uiThrottleDelay)1432 {1433 m_uiThrottleDelay = 0;1434 m_uiThrottleLastTime = uiTime;1435 }1436 else1437 {1438 return true;1439 }1440 }1442 m_stEmulator.emuMain(m_stEmulator.emuCount);1443 return true;1444 }1446 bool Window::on_focus_in_event(GdkEventFocus * _pstEvent)1447 {1448 if (emulating1449 && ! m_bPaused1450 && m_poDisplayConfig->oGetKey<bool>("pause_when_inactive"))1451 {1452 vStartEmu();1453 soundResume();1454 }1455 return false;1456 }1458 bool Window::on_focus_out_event(GdkEventFocus * _pstEvent)1459 {1460 if (emulating1461 && ! m_bPaused1462 && m_poDisplayConfig->oGetKey<bool>("pause_when_inactive"))1463 {1464 vStopEmu();1465 soundPause();1466 }1467 return false;1468 }1470 bool Window::on_key_press_event(GdkEventKey * _pstEvent)1471 {1472 EKey eKey;1474 if ((_pstEvent->state & Gtk::AccelGroup::get_default_mod_mask())1475 || (eKey = m_poKeymap->eGetKey(_pstEvent->hardware_keycode)) == KeyNone)1476 {1477 return Gtk::Window::on_key_press_event(_pstEvent);1478 }1480 switch (eKey)1481 {1482 case KeyA:1483 m_uiJoypadState |= KeyFlagA;1484 break;1485 case KeyB:1486 m_uiJoypadState |= KeyFlagB;1487 break;1488 case KeySelect:1489 m_uiJoypadState |= KeyFlagSelect;1490 break;1491 case KeyStart:1492 m_uiJoypadState |= KeyFlagStart;1493 break;1494 case KeyRight:1495 m_uiJoypadState |= KeyFlagRight;1496 m_uiJoypadState &= ~KeyFlagLeft;1497 break;1498 case KeyLeft:1499 m_uiJoypadState |= KeyFlagLeft;1500 m_uiJoypadState &= ~KeyFlagRight;1501 break;1502 case KeyUp:1503 m_uiJoypadState |= KeyFlagUp;1504 m_uiJoypadState &= ~KeyFlagDown;1505 break;1506 case KeyDown:1507 m_uiJoypadState |= KeyFlagDown;1508 m_uiJoypadState &= ~KeyFlagUp;1509 break;1510 case KeyR:1511 m_uiJoypadState |= KeyFlagR;1512 break;1513 case KeyL:1514 m_uiJoypadState |= KeyFlagL;1515 break;1516 case KeySpeed:1517 m_uiJoypadState |= KeyFlagSpeed;1518 break;1519 case KeyCapture:1520 m_uiJoypadState |= KeyFlagCapture;1521 break;1522 case KeyNone:1523 break;1524 }1525 return true;1526 }1528 bool Window::on_key_release_event(GdkEventKey * _pstEvent)1529 {1530 EKey eKey;1532 if ((_pstEvent->state & Gtk::AccelGroup::get_default_mod_mask())1533 || (eKey = m_poKeymap->eGetKey(_pstEvent->hardware_keycode)) == KeyNone)1534 {1535 return Gtk::Window::on_key_release_event(_pstEvent);1536 }1538 switch (eKey)1539 {1540 case KeyA:1541 m_uiJoypadState &= ~KeyFlagA;1542 break;1543 case KeyB:1544 m_uiJoypadState &= ~KeyFlagB;1545 break;1546 case KeySelect:1547 m_uiJoypadState &= ~KeyFlagSelect;1548 break;1549 case KeyStart:1550 m_uiJoypadState &= ~KeyFlagStart;1551 break;1552 case KeyRight:1553 m_uiJoypadState &= ~KeyFlagRight;1554 break;1555 case KeyLeft:1556 m_uiJoypadState &= ~KeyFlagLeft;1557 break;1558 case KeyUp:1559 m_uiJoypadState &= ~KeyFlagUp;1560 break;1561 case KeyDown:1562 m_uiJoypadState &= ~KeyFlagDown;1563 break;1564 case KeyR:1565 m_uiJoypadState &= ~KeyFlagR;1566 break;1567 case KeyL:1568 m_uiJoypadState &= ~KeyFlagL;1569 break;1570 case KeySpeed:1571 m_uiJoypadState &= ~KeyFlagSpeed;1572 break;1573 case KeyCapture:1574 m_uiJoypadState &= ~KeyFlagCapture;1575 break;1576 case KeyNone:1577 break;1578 }1579 return true;1580 }1582 } // namespace VBA