comparison src/gtk/windowcallbacks.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
comparison
equal deleted inserted replaced
0:8ced16adf2e1 1:f9f4f1b99eed
1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 1999-2003 Forgotten
3 // Copyright (C) 2004 Forgotten and the VBA development team
4
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)
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 of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 #include "window.h"
20
21 #include <sys/stat.h>
22
23 #include <stdio.h>
24 #include <time.h>
25
26 #include <SDL.h>
27
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"
36
37 #include "tools.h"
38 #include "intl.h"
39
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);
54
55 #ifdef MMX
56 extern "C" bool cpu_mmx;
57 #endif // MMX
58
59 namespace VBA
60 {
61
62 using Gnome::Glade::Xml;
63
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 }
75
76 void Window::vOnFileLoad()
77 {
78 std::string sSaveDir = m_poDirConfig->sGetKey("saves");
79
80 #ifdef GTKMM20
81
82 Gtk::FileSelection oDialog(_("Load game"));
83 oDialog.set_transient_for(*this);
84
85 if (sSaveDir == "")
86 {
87 oDialog.set_filename(Glib::path_get_dirname(m_sRomFile) + "/");
88 }
89 else
90 {
91 oDialog.set_filename(sSaveDir + "/");
92 }
93
94 #else // ! GTKMM20
95
96 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);
99
100 if (sSaveDir == "")
101 {
102 oDialog.set_current_folder(Glib::path_get_dirname(m_sRomFile));
103 }
104 else
105 {
106 oDialog.set_current_folder(sSaveDir);
107 oDialog.add_shortcut_folder(sSaveDir);
108 }
109
110 Gtk::FileFilter oSaveFilter;
111 oSaveFilter.set_name(_("VisualBoyAdvance save game"));
112 oSaveFilter.add_pattern("*.[sS][gG][mM]");
113
114 oDialog.add_filter(oSaveFilter);
115
116 #endif // ! GTKMM20
117
118 while (oDialog.run() == Gtk::RESPONSE_OK)
119 {
120 if (m_stEmulator.emuReadState(oDialog.get_filename().c_str()))
121 {
122 break;
123 }
124 }
125 }
126
127 void Window::vOnFileSave()
128 {
129 Glib::ustring sSaveDir = m_poDirConfig->sGetKey("saves");
130
131 #ifdef GTKMM20
132
133 Gtk::FileSelection oDialog(_("Save game"));
134 oDialog.set_transient_for(*this);
135
136 if (sSaveDir == "")
137 {
138 oDialog.set_filename(sCutSuffix(m_sRomFile));
139 }
140 else
141 {
142 oDialog.set_filename(sSaveDir + "/" +
143 sCutSuffix(Glib::path_get_basename(m_sRomFile)));
144 }
145
146 #else // ! GTKMM20
147
148 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);
152
153 if (sSaveDir == "")
154 {
155 oDialog.set_current_folder(Glib::path_get_dirname(m_sRomFile));
156 }
157 else
158 {
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)));
163
164 Gtk::FileFilter oSaveFilter;
165 oSaveFilter.set_name(_("VisualBoyAdvance save game"));
166 oSaveFilter.add_pattern("*.[sS][gG][mM]");
167
168 oDialog.add_filter(oSaveFilter);
169
170 #endif // ! GTKMM20
171
172 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 }
179
180 if (Glib::file_test(sFile, Glib::FILE_TEST_EXISTS))
181 {
182 Gtk::MessageDialog oConfirmDialog(*this,
183 _("File already exists. Overwrite it?"),
184 #ifndef GTKMM20
185 false,
186 #endif // ! GTKMM20
187 Gtk::MESSAGE_QUESTION,
188 Gtk::BUTTONS_YES_NO);
189 if (oConfirmDialog.run() != Gtk::RESPONSE_YES)
190 {
191 continue;
192 }
193 }
194
195 if (m_stEmulator.emuWriteState(sFile.c_str()))
196 {
197 break;
198 }
199 }
200 }
201
202 void Window::vOnLoadGameMostRecent()
203 {
204 int iMostRecent = -1;
205 time_t uiTimeMax;
206
207 for (int i = 0; i < 10; i++)
208 {
209 if (! m_astGameSlot[i].m_bEmpty
210 && (iMostRecent < 0 || m_astGameSlot[i].m_uiTime > uiTimeMax))
211 {
212 iMostRecent = i;
213 uiTimeMax = m_astGameSlot[i].m_uiTime;
214 }
215 }
216
217 if (iMostRecent >= 0)
218 {
219 vOnLoadGame(iMostRecent + 1);
220 }
221 }
222
223 void Window::vOnLoadGameAutoToggled(Gtk::CheckMenuItem * _poCMI)
224 {
225 m_poCoreConfig->vSetKey("load_game_auto", _poCMI->get_active());
226 }
227
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 }
237
238 void Window::vOnSaveGameOldest()
239 {
240 int iOldest = -1;
241 time_t uiTimeMin;
242
243 for (int i = 0; i < 10; i++)
244 {
245 if (! m_astGameSlot[i].m_bEmpty
246 && (iOldest < 0 || m_astGameSlot[i].m_uiTime < uiTimeMin))
247 {
248 iOldest = i;
249 uiTimeMin = m_astGameSlot[i].m_uiTime;
250 }
251 }
252
253 if (iOldest >= 0)
254 {
255 vOnSaveGame(iOldest + 1);
256 }
257 else
258 {
259 vOnSaveGame(1);
260 }
261 }
262
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 }
269
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 else
281 {
282 vStartEmu();
283 soundResume();
284 }
285 }
286 }
287
288 void Window::vOnFileReset()
289 {
290 if (emulating)
291 {
292 m_stEmulator.emuReset(true);
293 m_poFilePauseItem->set_active(false);
294 }
295 }
296
297 void Window::vOnRecentReset()
298 {
299 m_listHistory.clear();
300 vClearHistoryMenu();
301 }
302
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 }
308
309 void Window::vOnRecentFile(std::string _sFile)
310 {
311 bLoadROM(_sFile);
312 }
313
314 void Window::vOnImportBatteryFile()
315 {
316 std::string BatteryDir = m_poDirConfig->sGetKey("batteries");
317
318 #ifdef GTKMM20
319
320 Gtk::FileSelection oDialog(_("Import battery file"));
321 oDialog.set_transient_for(*this);
322
323 if (BatteryDir == "")
324 {
325 oDialog.set_filename(Glib::path_get_dirname(m_sRomFile) + "/");
326 }
327 else
328 {
329 oDialog.set_filename(BatteryDir + "/");
330 }
331
332 #else // ! GTKMM20
333
334 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);
337
338 if (BatteryDir == "")
339 {
340 oDialog.set_current_folder(Glib::path_get_dirname(m_sRomFile));
341 }
342 else
343 {
344 oDialog.set_current_folder(BatteryDir);
345 oDialog.add_shortcut_folder(BatteryDir);
346 }
347
348 Gtk::FileFilter oBatteryFilter;
349 oBatteryFilter.set_name(_("Battery file"));
350 oBatteryFilter.add_pattern("*.[sS][aA][vV]");
351
352 Gtk::FileFilter oFlashFilter;
353 oFlashFilter.set_name(_("Flash save"));
354 oFlashFilter.add_pattern("*.[dD][aA][tT]");
355
356 oDialog.add_filter(oBatteryFilter);
357 oDialog.add_filter(oFlashFilter);
358
359 #endif // ! GTKMM20
360
361 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 GTKMM20
366 false,
367 #endif // ! GTKMM20
368 Gtk::MESSAGE_QUESTION,
369 Gtk::BUTTONS_YES_NO);
370 if (oConfirmDialog.run() != Gtk::RESPONSE_YES)
371 {
372 continue;
373 }
374
375 if (m_stEmulator.emuReadBattery(oDialog.get_filename().c_str()))
376 {
377 m_stEmulator.emuReset(false);
378 break;
379 }
380 else
381 {
382 vPopupError(_("Failed to import battery file %s."),
383 oDialog.get_filename().c_str());
384 }
385 }
386 }
387
388 void Window::vOnExportBatteryFile()
389 {
390 std::string sBatteryDir = m_poDirConfig->sGetKey("batteries");
391
392 #ifdef GTKMM20
393
394 Gtk::FileSelection oDialog(_("Export battery file"));
395 oDialog.set_transient_for(*this);
396
397 if (sBatteryDir == "")
398 {
399 oDialog.set_filename(sCutSuffix(m_sRomFile));
400 }
401 else
402 {
403 oDialog.set_filename(sBatteryDir + "/" +
404 sCutSuffix(Glib::path_get_basename(m_sRomFile)));
405 }
406
407 #else // ! GTKMM20
408
409 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);
413
414 if (sBatteryDir == "")
415 {
416 oDialog.set_current_folder(Glib::path_get_dirname(m_sRomFile));
417 }
418 else
419 {
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)));
424
425 Gtk::FileFilter oBatteryFilter;
426 oBatteryFilter.set_name(_("Battery file"));
427 oBatteryFilter.add_pattern("*.[sS][aA][vV]");
428
429 Gtk::FileFilter oFlashFilter;
430 oFlashFilter.set_name(_("Flash save"));
431 oFlashFilter.add_pattern("*.[dD][aA][tT]");
432
433 oDialog.add_filter(oBatteryFilter);
434 oDialog.add_filter(oFlashFilter);
435
436 #endif // ! GTKMM20
437
438 while (oDialog.run() == Gtk::RESPONSE_OK)
439 {
440 Glib::ustring sFile = oDialog.get_filename();
441 Glib::ustring sExt;
442
443 #ifdef GTKMM20
444
445 sExt = ".sav";
446
447 #else // ! GTKMM20
448
449 if (oDialog.get_filter() == &oBatteryFilter)
450 {
451 sExt = ".sav";
452 }
453 else
454 {
455 sExt = ".dat";
456 }
457
458 #endif // ! GTKMM20
459
460 if (! bHasSuffix(sFile, sExt, false))
461 {
462 sFile += sExt;
463 }
464
465 if (Glib::file_test(sFile, Glib::FILE_TEST_EXISTS))
466 {
467 Gtk::MessageDialog oConfirmDialog(*this,
468 _("File already exists. Overwrite it?"),
469 #ifndef GTKMM20
470 false,
471 #endif // ! GTKMM20
472 Gtk::MESSAGE_QUESTION,
473 Gtk::BUTTONS_YES_NO);
474 if (oConfirmDialog.run() != Gtk::RESPONSE_YES)
475 {
476 continue;
477 }
478 }
479
480 bool bResult;
481 if (m_eCartridge == CartridgeGB)
482 {
483 bResult = gbWriteBatteryFile(sFile.c_str(), false);
484 }
485 else
486 {
487 bResult = m_stEmulator.emuWriteBattery(sFile.c_str());
488 }
489
490 if (bResult)
491 {
492 break;
493 }
494 else
495 {
496 vPopupError(_("Failed to export battery file %s."),
497 sFile.c_str());
498 }
499 }
500 }
501
502 void Window::vOnFileScreenCapture()
503 {
504 std::string sCaptureDir = m_poDirConfig->sGetKey("captures");
505
506 #ifdef GTKMM20
507
508 Gtk::FileSelection oDialog(_("Save screenshot"));
509 oDialog.set_transient_for(*this);
510
511 if (sCaptureDir == "")
512 {
513 oDialog.set_filename(sCutSuffix(m_sRomFile));
514 }
515 else
516 {
517 oDialog.set_filename(sCaptureDir + "/" +
518 sCutSuffix(Glib::path_get_basename(m_sRomFile)));
519 }
520
521 #else // ! GTKMM20
522
523 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);
527
528 if (sCaptureDir == "")
529 {
530 oDialog.set_current_folder(Glib::path_get_dirname(m_sRomFile));
531 }
532 else
533 {
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)));
538
539 Gtk::FileFilter oPngFilter;
540 oPngFilter.set_name(_("PNG image"));
541 oPngFilter.add_pattern("*.[pP][nN][gG]");
542
543 Gtk::FileFilter oBmpFilter;
544 oBmpFilter.set_name(_("BMP image"));
545 oBmpFilter.add_pattern("*.[bB][mM][pP]");
546
547 oDialog.add_filter(oPngFilter);
548 oDialog.add_filter(oBmpFilter);
549
550 if (m_poCoreConfig->sGetKey("screenshot_format") == "bmp")
551 {
552 oDialog.set_filter(oBmpFilter);
553 }
554
555 #endif // ! GTKMM20
556
557 while (oDialog.run() == Gtk::RESPONSE_OK)
558 {
559 Glib::ustring sFile = oDialog.get_filename();
560 Glib::ustring sExt;
561
562 #ifdef GTKMM20
563
564 sExt = "." + m_poCoreConfig->sGetKey("screenshot_format");
565
566 #else // ! GTKMM20
567
568 if (oDialog.get_filter() == &oPngFilter)
569 {
570 sExt = ".png";
571 }
572 else
573 {
574 sExt = ".bmp";
575 }
576
577 #endif // ! GTKMM20
578
579 if (! bHasSuffix(sFile, sExt, false))
580 {
581 sFile += sExt;
582 }
583
584 if (Glib::file_test(sFile, Glib::FILE_TEST_EXISTS))
585 {
586 Gtk::MessageDialog oConfirmDialog(*this,
587 _("File already exists. Overwrite it?"),
588 #ifndef GTKMM20
589 false,
590 #endif // ! GTKMM20
591 Gtk::MESSAGE_QUESTION,
592 Gtk::BUTTONS_YES_NO);
593 if (oConfirmDialog.run() != Gtk::RESPONSE_YES)
594 {
595 continue;
596 }
597 }
598
599 bool bResult;
600 if (sExt == ".png")
601 {
602 bResult = m_stEmulator.emuWritePNG(sFile.c_str());
603 }
604 else
605 {
606 bResult = m_stEmulator.emuWriteBMP(sFile.c_str());
607 }
608
609 if (bResult)
610 {
611 break;
612 }
613 }
614 }
615
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;
628
629 vUpdateGameSlots();
630
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 }
637
638 m_poFilePauseItem->set_active(false);
639 }
640 }
641
642 void Window::vOnFileExit()
643 {
644 hide();
645 }
646
647 void Window::vOnFrameskipToggled(Gtk::CheckMenuItem * _poCMI, int _iValue)
648 {
649 if (! _poCMI->get_active())
650 {
651 return;
652 }
653
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 else
662 {
663 m_poCoreConfig->vSetKey("frameskip", "auto");
664 gbFrameSkip = 0;
665 systemFrameSkip = 0;
666 m_bAutoFrameskip = true;
667 }
668 }
669
670 void Window::vOnThrottleToggled(Gtk::CheckMenuItem * _poCMI, int _iPercent)
671 {
672 if (! _poCMI->get_active())
673 {
674 return;
675 }
676
677 vSetThrottle(_iPercent);
678
679 // Initialize the frameskip adjustment each time throttle is changed
680 if (m_bAutoFrameskip)
681 {
682 systemFrameSkip = 0;
683 }
684 }
685
686 void Window::vOnThrottleOther(Gtk::CheckMenuItem * _poCMI)
687 {
688 if (! _poCMI->get_active())
689 {
690 return;
691 }
692
693 Glib::RefPtr<Xml> poXml;
694 poXml = Xml::create(PKGDATADIR "/vba.glade", "ThrottleDialog");
695
696 Gtk::Dialog * poDialog = dynamic_cast<Gtk::Dialog *>(poXml->get_widget("ThrottleDialog"));
697 Gtk::SpinButton * poSpin = dynamic_cast<Gtk::SpinButton *>(poXml->get_widget("ThrottleSpin"));
698
699 poDialog->set_transient_for(*this);
700
701 if (m_iThrottle != 0)
702 {
703 poSpin->set_value(m_iThrottle);
704 }
705 else
706 {
707 poSpin->set_value(100);
708 }
709
710 if (poDialog->run() == Gtk::RESPONSE_OK)
711 {
712 vSetThrottle(poSpin->get_value_as_int());
713 }
714
715 delete poDialog;
716 vSelectBestThrottleItem();
717 }
718
719 void Window::vOnVideoScaleToggled(Gtk::CheckMenuItem * _poCMI, int _iScale)
720 {
721 if (! _poCMI->get_active())
722 {
723 return;
724 }
725
726 m_poDisplayConfig->vSetKey("scale", _iScale);
727 vUpdateScreen();
728 }
729
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 else
738 {
739 layerSettings &= ~iMask;
740 }
741 layerEnable = DISPCNT & layerSettings;
742
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 }
756
757 void Window::vOnDirectories()
758 {
759 Glib::RefPtr<Xml> poXml;
760 poXml = Xml::create(PKGDATADIR "/vba.glade", "DirectoriesDialog");
761
762 struct
763 {
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 };
777
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));
783
784 poEntry->set_text(m_poDirConfig->sGetKey(astRow[i].m_csKey));
785
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 }
793
794 Gtk::Dialog * poDialog = dynamic_cast<Gtk::Dialog *>(poXml->get_widget("DirectoriesDialog"));
795 poDialog->set_transient_for(*this);
796
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 }
809
810 // Needed if saves dir changed
811 vUpdateGameSlots();
812 }
813
814 delete poDialog;
815 }
816
817 void Window::vOnDirectoryReset(Gtk::Entry * _poEntry)
818 {
819 _poEntry->set_text("");
820 }
821
822 void Window::vOnDirectorySelect(Gtk::Entry * _poEntry)
823 {
824 #ifdef GTKMM20
825
826 Gtk::FileSelection oDialog(_("Select directory"));
827 oDialog.set_transient_for(*this);
828
829 if (_poEntry->get_text() != "")
830 {
831 oDialog.set_filename(_poEntry->get_text() + "/");
832 }
833
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 }
843
844 #else // ! GTKMM20
845
846 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);
850
851 if (_poEntry->get_text() != "")
852 {
853 oDialog.add_shortcut_folder(_poEntry->get_text());
854 oDialog.set_current_folder(_poEntry->get_text());
855 }
856
857 if (oDialog.run() == Gtk::RESPONSE_OK)
858 {
859 _poEntry->set_text(oDialog.get_filename());
860 }
861
862 #endif // ! GTKMM20
863 }
864
865 void Window::vOnPauseWhenInactiveToggled(Gtk::CheckMenuItem * _poCMI)
866 {
867 m_poDisplayConfig->vSetKey("pause_when_inactive", _poCMI->get_active());
868 }
869
870 void Window::vOnSelectBios()
871 {
872 #ifdef GTKMM20
873
874 Gtk::FileSelection oDialog(_("Select BIOS file"));
875 oDialog.set_transient_for(*this);
876
877 if (m_poCoreConfig->sGetKey("bios_file") != "")
878 {
879 oDialog.set_filename(m_poCoreConfig->sGetKey("bios_file"));
880 }
881
882 #else // ! GTKMM20
883
884 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);
887
888 if (m_poCoreConfig->sGetKey("bios_file") != "")
889 {
890 oDialog.set_filename(m_poCoreConfig->sGetKey("bios_file"));
891 }
892
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 };
898
899 Gtk::FileFilter oAllFilter;
900 oAllFilter.set_name(_("All files"));
901 oAllFilter.add_pattern("*");
902
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 }
909
910 oDialog.add_filter(oAllFilter);
911 oDialog.add_filter(oBiosFilter);
912
913 oDialog.set_filter(oBiosFilter);
914
915 #endif // ! GTKMM20
916
917 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 }
927
928 void Window::vOnUseBiosToggled(Gtk::CheckMenuItem * _poCMI)
929 {
930 m_poCoreConfig->vSetKey("use_bios_file", _poCMI->get_active());
931 }
932
933 void Window::vOnShowSpeedToggled(Gtk::CheckMenuItem * _poCMI, int _iShowSpeed)
934 {
935 if (! _poCMI->get_active())
936 {
937 return;
938 }
939
940 m_eShowSpeed = (EShowSpeed)_iShowSpeed;
941 if (m_eShowSpeed == ShowNone)
942 {
943 vSetDefaultTitle();
944 }
945 m_poDisplayConfig->vSetKey("show_speed", _iShowSpeed);
946 }
947
948 void Window::vOnSaveTypeToggled(Gtk::CheckMenuItem * _poCMI, int _iSaveType)
949 {
950 if (! _poCMI->get_active())
951 {
952 return;
953 }
954
955 cpuSaveType = _iSaveType;
956 m_poCoreConfig->vSetKey("save_type", _iSaveType);
957 }
958
959 void Window::vOnFlashSizeToggled(Gtk::CheckMenuItem * _poCMI, int _iFlashSize)
960 {
961 if (! _poCMI->get_active())
962 {
963 return;
964 }
965
966 if (_iFlashSize == 64)
967 {
968 flashSetSize(0x10000);
969 }
970 else
971 {
972 flashSetSize(0x20000);
973 }
974 m_poCoreConfig->vSetKey("flash_size", _iFlashSize);
975 }
976
977 void Window::vOnScreenshotFormatToggled(Gtk::CheckMenuItem * _poCMI, std::string _sFormat)
978 {
979 if (! _poCMI->get_active())
980 {
981 return;
982 }
983
984 m_poCoreConfig->vSetKey("screenshot_format", _sFormat);
985 }
986
987 void Window::vOnSoundStatusToggled(Gtk::CheckMenuItem * _poCMI, int _iSoundStatus)
988 {
989 if (! _poCMI->get_active())
990 {
991 return;
992 }
993
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 }
1025
1026 void Window::vOnSoundEchoToggled(Gtk::CheckMenuItem * _poCMI)
1027 {
1028 soundEcho = _poCMI->get_active();
1029 m_poSoundConfig->vSetKey("echo", soundEcho);
1030 }
1031
1032 void Window::vOnSoundLowPassToggled(Gtk::CheckMenuItem * _poCMI)
1033 {
1034 soundLowPass = _poCMI->get_active();
1035 m_poSoundConfig->vSetKey("low_pass", soundLowPass);
1036 }
1037
1038 void Window::vOnSoundReverseToggled(Gtk::CheckMenuItem * _poCMI)
1039 {
1040 soundReverse = _poCMI->get_active();
1041 m_poSoundConfig->vSetKey("reverse_stereo", soundReverse);
1042 }
1043
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 else
1058 {
1059 iActive &= ~iFlag;
1060 }
1061 soundEnableChannels(iActive);
1062 soundDisableChannels(~iActive & 0x30f);
1063
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 }
1075
1076 void Window::vOnSoundQualityToggled(Gtk::CheckMenuItem * _poCMI, int _iSoundQuality)
1077 {
1078 if (! _poCMI->get_active())
1079 {
1080 return;
1081 }
1082
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 }
1094
1095 void Window::vOnSoundVolumeToggled(Gtk::CheckMenuItem * _poCMI, int _iSoundVolume)
1096 {
1097 if (! _poCMI->get_active())
1098 {
1099 return;
1100 }
1101
1102 soundVolume = _iSoundVolume;
1103 m_poSoundConfig->vSetKey("volume", _iSoundVolume);
1104 }
1105
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 }
1116
1117 void Window::vOnGBPrinterToggled(Gtk::CheckMenuItem * _poCMI)
1118 {
1119 if (_poCMI->get_active())
1120 {
1121 gbSerialFunction = gbPrinterSend;
1122 }
1123 else
1124 {
1125 gbSerialFunction = NULL;
1126 }
1127 m_poCoreConfig->vSetKey("gb_printer", _poCMI->get_active());
1128 }
1129
1130 void Window::vOnEmulatorTypeToggled(Gtk::CheckMenuItem * _poCMI, int _iEmulatorType)
1131 {
1132 gbEmulatorType = _iEmulatorType;
1133 m_poCoreConfig->vSetKey("emulator_type", _iEmulatorType);
1134 }
1135
1136 void Window::vOnFilter2xToggled(Gtk::CheckMenuItem * _poCMI, int _iFilter2x)
1137 {
1138 if (! _poCMI->get_active())
1139 {
1140 return;
1141 }
1142
1143 m_poScreenArea->vSetFilter2x((EFilter2x)_iFilter2x);
1144 if (emulating)
1145 {
1146 vDrawScreen();
1147 }
1148 m_poDisplayConfig->vSetKey("filter2x", _iFilter2x);
1149 }
1150
1151 void Window::vOnFilterIBToggled(Gtk::CheckMenuItem * _poCMI, int _iFilterIB)
1152 {
1153 if (! _poCMI->get_active())
1154 {
1155 return;
1156 }
1157
1158 m_poScreenArea->vSetFilterIB((EFilterIB)_iFilterIB);
1159 if (emulating)
1160 {
1161 vDrawScreen();
1162 }
1163 m_poDisplayConfig->vSetKey("filterIB", _iFilterIB);
1164 }
1165
1166 #ifdef MMX
1167 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 // MMX
1173
1174 void Window::vOnJoypadConfigure(int _iJoypad)
1175 {
1176 Glib::RefPtr<Xml> poXml;
1177 poXml = Xml::create(PKGDATADIR "/vba.glade", "JoypadConfigDialog");
1178
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]);
1183
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 }
1196
1197 delete poDialog;
1198 }
1199
1200 void Window::vOnJoypadToggled(Gtk::CheckMenuItem * _poCMI, int _iJoypad)
1201 {
1202 if (! _poCMI->get_active())
1203 {
1204 return;
1205 }
1206
1207 if (m_poKeymap != NULL)
1208 {
1209 delete m_poKeymap;
1210 }
1211 m_poKeymap = m_oJoypads[_iJoypad - 1].poCreateKeymap();
1212
1213 m_poInputConfig->vSetKey("active_joypad", _iJoypad);
1214 }
1215
1216 void Window::vOnAutofireToggled(Gtk::CheckMenuItem * _poCMI, u32 _uiKeyFlag)
1217 {
1218 if (_poCMI->get_active())
1219 {
1220 m_uiAutofireState |= _uiKeyFlag;
1221 }
1222 else
1223 {
1224 m_uiAutofireState &= ~_uiKeyFlag;
1225 }
1226
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 }
1246
1247 void Window::vOnGDBWait()
1248 {
1249 Glib::RefPtr<Xml> poXml;
1250 poXml = Xml::create(PKGDATADIR "/vba.glade", "TcpPortDialog");
1251
1252 Gtk::Dialog * poDialog = dynamic_cast<Gtk::Dialog *>(poXml->get_widget("TcpPortDialog"));
1253 Gtk::SpinButton * poSpin = dynamic_cast<Gtk::SpinButton *>(poXml->get_widget("TcpPortSpin"));
1254
1255 poDialog->set_transient_for(*this);
1256
1257 int iPort = 55555;
1258 poSpin->set_value(iPort);
1259
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;
1267
1268 if (! bOk)
1269 {
1270 return;
1271 }
1272
1273 m_eCartridge = CartridgeGBA;
1274 m_sRomFile = "gnu_stub";
1275 m_stEmulator = GBASystem;
1276
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);
1286
1287 useBios = m_poCoreConfig->oGetKey<bool>("use_bios_file");
1288 //CPUInit(m_poCoreConfig->sGetKey("bios_file").c_str(), useBios);
1289 CPUInit();
1290 CPUReset();
1291
1292 for (std::list<Gtk::Widget *>::iterator it = m_listSensitiveWhenPlaying.begin();
1293 it != m_listSensitiveWhenPlaying.end();
1294 it++)
1295 {
1296 (*it)->set_sensitive();
1297 }
1298
1299 if (m_poCoreConfig->oGetKey<bool>("load_game_auto"))
1300 {
1301 vOnLoadGameMostRecent();
1302 }
1303
1304 vStartEmu();
1305
1306 emulating = 1;
1307
1308 dbgMain = remoteStubMain;
1309 dbgSignal = remoteStubSignal;
1310 dbgOutput = remoteOutput;
1311 debugger = true;
1312
1313 remoteSetProtocol(0);
1314 remoteSetPort(iPort);
1315 remoteInit();
1316 }
1317
1318 void Window::vOnGDBLoadAndWait()
1319 {
1320 bool bLoaded = false;
1321
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();
1331
1332 if (! bLoaded)
1333 {
1334 return;
1335 }
1336
1337 if (m_eCartridge != CartridgeGBA)
1338 {
1339 vPopupError(_("Only GBA images are supported."));
1340 vOnFileClose();
1341 return;
1342 }
1343
1344 Glib::RefPtr<Xml> poXml;
1345 poXml = Xml::create(PKGDATADIR "/vba.glade", "TcpPortDialog");
1346
1347 Gtk::Dialog * poDialog = dynamic_cast<Gtk::Dialog *>(poXml->get_widget("TcpPortDialog"));
1348 Gtk::SpinButton * poSpin = dynamic_cast<Gtk::SpinButton *>(poXml->get_widget("TcpPortSpin"));
1349
1350 poDialog->set_transient_for(*this);
1351
1352 int iPort = 55555;
1353 poSpin->set_value(iPort);
1354
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;
1362
1363 if (! bOk)
1364 {
1365 return;
1366 }
1367
1368 dbgMain = remoteStubMain;
1369 dbgSignal = remoteStubSignal;
1370 dbgOutput = remoteOutput;
1371 debugger = true;
1372
1373 remoteSetProtocol(0);
1374 remoteSetPort(iPort);
1375 remoteInit();
1376 }
1377
1378 void Window::vOnGDBBreak()
1379 {
1380 if (armState)
1381 {
1382 armNextPC -= 4;
1383 reg[15].I -= 4;
1384 }
1385 else
1386 {
1387 armNextPC -= 2;
1388 reg[15].I -= 2;
1389 }
1390
1391 debugger = true;
1392 }
1393
1394 void Window::vOnGDBDisconnect()
1395 {
1396 remoteCleanUp();
1397 debugger = false;
1398 }
1399
1400 void Window::vOnHelpAbout()
1401 {
1402 Glib::RefPtr<Xml> poXml;
1403 poXml = Xml::create(PKGDATADIR "/vba.glade", "AboutDialog");
1404
1405 Gtk::Dialog * poDialog = dynamic_cast<Gtk::Dialog *>(poXml->get_widget("AboutDialog"));
1406 poDialog->set_transient_for(*this);
1407
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);
1412
1413 Gtk::Label * poLabel = dynamic_cast<Gtk::Label *>(poXml->get_widget("VersionLabel"));
1414 poLabel->set_markup("<b><big>" PACKAGE " " VERSION "</big></b>");
1415
1416 poDialog->run();
1417 delete poDialog;
1418 }
1419
1420 bool Window::bOnEmuIdle()
1421 {
1422 if (debugger && m_stEmulator.emuHasDebugger)
1423 {
1424 dbgMain();
1425 return true;
1426 }
1427
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 else
1437 {
1438 return true;
1439 }
1440 }
1441
1442 m_stEmulator.emuMain(m_stEmulator.emuCount);
1443 return true;
1444 }
1445
1446 bool Window::on_focus_in_event(GdkEventFocus * _pstEvent)
1447 {
1448 if (emulating
1449 && ! m_bPaused
1450 && m_poDisplayConfig->oGetKey<bool>("pause_when_inactive"))
1451 {
1452 vStartEmu();
1453 soundResume();
1454 }
1455 return false;
1456 }
1457
1458 bool Window::on_focus_out_event(GdkEventFocus * _pstEvent)
1459 {
1460 if (emulating
1461 && ! m_bPaused
1462 && m_poDisplayConfig->oGetKey<bool>("pause_when_inactive"))
1463 {
1464 vStopEmu();
1465 soundPause();
1466 }
1467 return false;
1468 }
1469
1470 bool Window::on_key_press_event(GdkEventKey * _pstEvent)
1471 {
1472 EKey eKey;
1473
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 }
1479
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 }
1527
1528 bool Window::on_key_release_event(GdkEventKey * _pstEvent)
1529 {
1530 EKey eKey;
1531
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 }
1537
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 }
1581
1582 } // namespace VBA