1
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2
// Copyright (C) 1999-2003 Forgotten
3
// Copyright (C) 2004 Forgotten and the VBA development team
5
// This program is free software; you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation; either version 2, or(at your option)
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
// GNU General Public License for more details.
15
// You should have received a copy of the GNU General Public License
16
// along with this program; if not, write to the Free Software Foundation,
17
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
#include <gtkmm/stock.h>
22
#include <gtkmm/messagedialog.h>
23
#include <gtkmm/aboutdialog.h>
24
#include <gtkmm/builder.h>
28
#include "../gba/GBA.h"
29
#include "../gba/Sound.h"
31
#include "../gb/gbGlobals.h"
33
#include "../sdl/inputSDL.h"
37
#include "joypadconfig.h"
38
#include "directoriesconfig.h"
39
#include "displayconfig.h"
40
#include "soundconfig.h"
41
#include "gameboyconfig.h"
42
#include "gameboyadvanceconfig.h"
43
#include "generalconfig.h"
44
#include "gameboyadvancecheatlist.h"
45
#include "gameboycheatlist.h"
50
void Window::vOnMenuEnter()
52
if (emulating && ! m_bPaused)
59
void Window::vOnMenuExit()
61
if (emulating && ! m_bPaused)
68
void Window::vOnFileOpen()
70
while (m_poFileOpenDialog->run() == Gtk::RESPONSE_OK)
72
if (bLoadROM(m_poFileOpenDialog->get_filename()))
77
m_poFileOpenDialog->hide();
80
void Window::vOnFileLoad()
82
std::string sSaveDir = m_poDirConfig->sGetKey("saves");
84
Gtk::FileChooserDialog oDialog(*this, _("Load game"));
85
oDialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
86
oDialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
90
oDialog.set_current_folder(Glib::path_get_dirname(m_sRomFile));
94
oDialog.set_current_folder(sSaveDir);
95
oDialog.add_shortcut_folder(sSaveDir);
98
Gtk::FileFilter oSaveFilter;
99
oSaveFilter.set_name(_("VisualBoyAdvance save game"));
100
oSaveFilter.add_pattern("*.[sS][gG][mM]");
102
oDialog.add_filter(oSaveFilter);
104
while (oDialog.run() == Gtk::RESPONSE_OK)
106
if (m_stEmulator.emuReadState(oDialog.get_filename().c_str()))
113
void Window::vOnFileSave()
115
Glib::ustring sSaveDir = m_poDirConfig->sGetKey("saves");
117
Gtk::FileChooserDialog oDialog(*this, _("Save game"),
118
Gtk::FILE_CHOOSER_ACTION_SAVE);
119
oDialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
120
oDialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
124
oDialog.set_current_folder(Glib::path_get_dirname(m_sRomFile));
128
oDialog.set_current_folder(sSaveDir);
129
oDialog.add_shortcut_folder(sSaveDir);
131
oDialog.set_current_name(sCutSuffix(Glib::path_get_basename(m_sRomFile)));
133
Gtk::FileFilter oSaveFilter;
134
oSaveFilter.set_name(_("VisualBoyAdvance save game"));
135
oSaveFilter.add_pattern("*.[sS][gG][mM]");
137
oDialog.add_filter(oSaveFilter);
139
while (oDialog.run() == Gtk::RESPONSE_OK)
141
Glib::ustring sFile = oDialog.get_filename();
142
if (! bHasSuffix(sFile, ".sgm", false))
147
if (Glib::file_test(sFile, Glib::FILE_TEST_EXISTS))
149
Gtk::MessageDialog oConfirmDialog(*this,
150
_("File already exists. Overwrite it?"),
152
Gtk::MESSAGE_QUESTION,
153
Gtk::BUTTONS_YES_NO);
154
if (oConfirmDialog.run() != Gtk::RESPONSE_YES)
160
if (m_stEmulator.emuWriteState(sFile.c_str()))
167
void Window::vOnLoadGameMostRecent()
169
int iMostRecent = -1;
170
time_t uiTimeMax = 0;
172
for (int i = 0; i < 10; i++)
174
if (! m_astGameSlot[i].m_bEmpty
175
&& (iMostRecent < 0 || m_astGameSlot[i].m_uiTime > uiTimeMax))
178
uiTimeMax = m_astGameSlot[i].m_uiTime;
182
if (iMostRecent >= 0)
184
vOnLoadGame(iMostRecent + 1);
188
void Window::vOnLoadGameAutoToggled(Gtk::CheckMenuItem * _poCMI)
190
m_poCoreConfig->vSetKey("load_game_auto", _poCMI->get_active());
193
void Window::vOnLoadGame(int _iSlot)
196
if (! m_astGameSlot[i].m_bEmpty)
198
m_stEmulator.emuReadState(m_astGameSlot[i].m_sFile.c_str());
199
m_poFilePauseItem->set_active(false);
203
void Window::vOnSaveGameOldest()
206
time_t uiTimeMin = 0;
208
for (int i = 0; i < 10; i++)
210
if (! m_astGameSlot[i].m_bEmpty
211
&& (iOldest < 0 || m_astGameSlot[i].m_uiTime < uiTimeMin))
214
uiTimeMin = m_astGameSlot[i].m_uiTime;
220
vOnSaveGame(iOldest + 1);
228
void Window::vOnSaveGame(int _iSlot)
231
m_stEmulator.emuWriteState(m_astGameSlot[i].m_sFile.c_str());
235
void Window::vOnFilePauseToggled(Gtk::CheckMenuItem * _poCMI)
237
m_bPaused = _poCMI->get_active();
253
void Window::vOnFileReset()
257
m_stEmulator.emuReset();
258
m_poFilePauseItem->set_active(false);
262
void Window::vOnRecentFile()
264
Glib::ustring sURI = m_poRecentChooserMenu->get_current_uri();
268
std::string sFileName = Glib::filename_from_uri(sURI);
273
void Window::vOnFileScreenCapture()
275
std::string sCaptureDir = m_poDirConfig->sGetKey("captures");
277
Gtk::FileChooserDialog oDialog(*this, _("Save screenshot"),
278
Gtk::FILE_CHOOSER_ACTION_SAVE);
279
oDialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
280
oDialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
282
if (sCaptureDir == "")
284
oDialog.set_current_folder(Glib::path_get_dirname(m_sRomFile));
288
oDialog.set_current_folder(sCaptureDir);
289
oDialog.add_shortcut_folder(sCaptureDir);
291
oDialog.set_current_name(sCutSuffix(Glib::path_get_basename(m_sRomFile)));
293
Gtk::FileFilter oPngFilter;
294
oPngFilter.set_name(_("PNG image"));
295
oPngFilter.add_pattern("*.[pP][nN][gG]");
297
oDialog.add_filter(oPngFilter);
299
while (oDialog.run() == Gtk::RESPONSE_OK)
301
Glib::ustring sFile = oDialog.get_filename();
302
Glib::ustring sExt = ".png";
304
if (! bHasSuffix(sFile, sExt, false))
309
if (Glib::file_test(sFile, Glib::FILE_TEST_EXISTS))
311
Gtk::MessageDialog oConfirmDialog(*this,
312
_("File already exists. Overwrite it?"),
314
Gtk::MESSAGE_QUESTION,
315
Gtk::BUTTONS_YES_NO);
316
if (oConfirmDialog.run() != Gtk::RESPONSE_YES)
322
if (m_stEmulator.emuWritePNG(sFile.c_str()))
329
void Window::vOnFileClose()
331
if (m_eCartridge != CartridgeNone)
336
vDrawDefaultScreen();
339
m_stEmulator.emuCleanUp();
340
m_eCartridge = CartridgeNone;
345
for (std::list<Gtk::Widget *>::iterator it = m_listSensitiveWhenPlaying.begin();
346
it != m_listSensitiveWhenPlaying.end();
349
(*it)->set_sensitive(false);
352
m_poFilePauseItem->set_active(false);
356
void Window::vOnFileExit()
361
void Window::vOnVideoFullscreen()
366
void Window::vOnDirectories()
368
DirectoriesConfigDialog oDialog(m_poDirConfig);
369
oDialog.set_transient_for(*this);
372
// Needed if saves dir changed
376
void Window::vOnJoypadConfigure()
378
JoypadConfigDialog oDialog(m_poInputConfig);
379
oDialog.set_transient_for(*this);
383
void Window::vOnDisplayConfigure()
385
std::string sUiFile = sGetUiFilePath("display.ui");
386
Glib::RefPtr<Gtk::Builder> poBuilder = Gtk::Builder::create_from_file(sUiFile);
388
DisplayConfigDialog * poDialog = 0;
389
poBuilder->get_widget_derived("DisplayConfigDialog", poDialog);
390
poDialog->vSetConfig(m_poDisplayConfig, this);
391
poDialog->set_transient_for(*this);
396
void Window::vOnSoundConfigure()
398
std::string sUiFile = sGetUiFilePath("sound.ui");
399
Glib::RefPtr<Gtk::Builder> poBuilder = Gtk::Builder::create_from_file(sUiFile);
401
SoundConfigDialog * poDialog = 0;
402
poBuilder->get_widget_derived("SoundConfigDialog", poDialog);
403
poDialog->vSetConfig(m_poSoundConfig, this);
404
poDialog->set_transient_for(*this);
409
void Window::vOnGameBoyConfigure()
411
std::string sUiFile = sGetUiFilePath("gameboy.ui");
412
Glib::RefPtr<Gtk::Builder> poBuilder = Gtk::Builder::create_from_file(sUiFile);
414
GameBoyConfigDialog * poDialog = 0;
415
poBuilder->get_widget_derived("GameBoyConfigDialog", poDialog);
416
poDialog->vSetConfig(m_poCoreConfig, this);
417
poDialog->set_transient_for(*this);
422
void Window::vOnGameBoyAdvanceConfigure()
424
std::string sUiFile = sGetUiFilePath("gameboyadvance.ui");
425
Glib::RefPtr<Gtk::Builder> poBuilder = Gtk::Builder::create_from_file(sUiFile);
427
GameBoyAdvanceConfigDialog * poDialog = 0;
428
poBuilder->get_widget_derived("GameBoyAdvanceConfigDialog", poDialog);
429
poDialog->vSetConfig(m_poCoreConfig, this);
430
poDialog->set_transient_for(*this);
435
void Window::vOnGeneralConfigure()
437
std::string sUiFile = sGetUiFilePath("preferences.ui");
438
Glib::RefPtr<Gtk::Builder> poBuilder = Gtk::Builder::create_from_file(sUiFile);
440
PreferencesDialog * poDialog = 0;
441
poBuilder->get_widget_derived("PreferencesDialog", poDialog);
442
poDialog->vSetConfig(m_poCoreConfig, this);
443
poDialog->set_transient_for(*this);
448
void Window::vOnCheatList()
450
if (m_eCartridge == CartridgeGBA)
452
std::string sUiFile = sGetUiFilePath("cheatlist.ui");
453
Glib::RefPtr<Gtk::Builder> poBuilder = Gtk::Builder::create_from_file(sUiFile);
455
GameBoyAdvanceCheatListDialog * poDialog = 0;
456
poBuilder->get_widget_derived("CheatListDialog", poDialog);
457
poDialog->set_transient_for(*this);
458
poDialog->vSetWindow(this);
462
else if (m_eCartridge == CartridgeGB)
464
std::string sUiFile = sGetUiFilePath("cheatlist.ui");
465
Glib::RefPtr<Gtk::Builder> poBuilder = Gtk::Builder::create_from_file(sUiFile);
467
GameBoyCheatListDialog * poDialog = 0;
468
poBuilder->get_widget_derived("CheatListDialog", poDialog);
469
poDialog->set_transient_for(*this);
470
poDialog->vSetWindow(this);
476
void Window::vOnCheatDisableToggled(Gtk::CheckMenuItem * _poCMI)
478
if (m_eCartridge == CartridgeGB) {
479
cheatsEnabled = !cheatsEnabled;
481
else if (m_eCartridge == CartridgeGBA) {
482
cheatsEnabled = !cheatsEnabled;
485
_poCMI->set_active(!cheatsEnabled);
488
void Window::vOnHelpAbout()
490
Gtk::AboutDialog oAboutDialog;
491
const char csGPLHeader[] = "This program is free software: you can redistribute it and/or modify\n"
492
"it under the terms of the GNU General Public License as published by\n"
493
"the Free Software Foundation, either version 2 of the License, or\n"
494
"(at your option) any later version.\n\n"
495
"This program is distributed in the hope that it will be useful,\n"
496
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
497
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
498
"GNU General Public License for more details.\n\n"
499
"You should have received a copy of the GNU General Public License\n"
500
"along with this program. If not, see <http://www.gnu.org/licenses/>.";
501
const char csCopyright[] = "Copyright (C) 1999-2003 Forgotten\n"
502
"Copyright (C) 2004-2006 VBA development team\n"
503
"Copyright (C) 2007-2011 VBA-M development team";
505
oAboutDialog.set_transient_for(*this);
507
oAboutDialog.set_name(_("VBA-M"));
508
oAboutDialog.set_version(VERSION);
509
oAboutDialog.set_comments(_("Nintendo GameBoy Advance emulator."));
510
oAboutDialog.set_license(csGPLHeader);
511
oAboutDialog.set_copyright(csCopyright);
512
oAboutDialog.set_logo_icon_name("vbam");
514
oAboutDialog.set_website("http://www.vba-m.com/");
516
std::list<Glib::ustring> list_authors;
517
list_authors.push_back("Forgotten");
518
list_authors.push_back("kxu");
519
list_authors.push_back("Pokemonhacker");
520
list_authors.push_back("Spacy51");
521
list_authors.push_back("mudlord");
522
list_authors.push_back("Nach");
523
list_authors.push_back("jbo_85");
524
list_authors.push_back("bgK");
525
oAboutDialog.set_authors(list_authors);
527
std::list<Glib::ustring> list_artists;
528
list_artists.push_back("Matteo Drera");
529
list_artists.push_back("Jakub Steiner");
530
list_artists.push_back("Jones Lee");
531
oAboutDialog.set_artists(list_artists);
536
bool Window::bOnEmuIdle()
540
m_stEmulator.emuMain(m_stEmulator.emuCount);
544
bool Window::on_focus_in_event(GdkEventFocus * _pstEvent)
546
if (emulating && !m_bPaused)
554
bool Window::on_focus_out_event(GdkEventFocus * _pstEvent)
558
&& m_poCoreConfig->oGetKey<bool>("pause_when_inactive"))
566
bool Window::on_key_press_event(GdkEventKey * _pstEvent)
568
// The menu accelerators are disabled when it is hidden
569
if (_pstEvent->keyval == GDK_F11 && !m_poMenuBar->is_visible())
575
// Forward the keyboard event to the input module by faking a SDL event
577
event.type = SDL_KEYDOWN;
578
event.key.keysym.sym = (SDLKey)_pstEvent->keyval;
579
inputProcessSDLEvent(event);
581
return Gtk::Window::on_key_press_event(_pstEvent);
584
bool Window::on_key_release_event(GdkEventKey * _pstEvent)
586
// Forward the keyboard event to the input module by faking a SDL event
588
event.type = SDL_KEYUP;
589
event.key.keysym.sym = (SDLKey)_pstEvent->keyval;
590
inputProcessSDLEvent(event);
593
return Gtk::Window::on_key_release_event(_pstEvent);
596
bool Window::on_window_state_event(GdkEventWindowState* _pstEvent)
598
if (_pstEvent->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
600
m_bFullscreen = _pstEvent->new_window_state & GDK_WINDOW_STATE_FULLSCREEN;