Mercurial > vba-clojure
comparison src/gtk/window.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
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/GBASound.h" | |
31 #include "../gb/GB.h" | |
32 #include "../gb/gbGlobals.h" | |
33 #include "../gb/gbPrinter.h" | |
34 #include "../common/Util.h" | |
35 | |
36 #include "menuitem.h" | |
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 Window * Window::m_poInstance = NULL; | |
65 | |
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; | |
103 | |
104 vInitSystem(); | |
105 vInitSDL(); | |
106 | |
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(); | |
113 | |
114 // Get config | |
115 // | |
116 vInitConfig(); | |
117 | |
118 m_sUserDataDir = Glib::get_home_dir() + "/.gvba"; | |
119 m_sConfigFile = m_sUserDataDir + "/config"; | |
120 | |
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 else | |
131 { | |
132 vSaveConfig(m_sConfigFile); | |
133 } | |
134 | |
135 vCreateFileOpenDialog(); | |
136 vLoadHistoryFromConfig(); | |
137 vLoadJoypadsFromConfig(); | |
138 | |
139 Gtk::MenuItem * poMI; | |
140 Gtk::CheckMenuItem * poCMI; | |
141 | |
142 // File menu | |
143 // | |
144 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileOpen")); | |
145 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileOpen)); | |
146 | |
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); | |
150 | |
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); | |
154 | |
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)); | |
162 | |
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(); | |
171 | |
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); | |
175 | |
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)); | |
182 | |
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); | |
186 | |
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); | |
194 | |
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); | |
198 | |
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); | |
202 | |
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); | |
206 | |
207 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("FileExit")); | |
208 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnFileExit)); | |
209 | |
210 // Recent menu | |
211 // | |
212 m_poRecentMenu = dynamic_cast<Gtk::Menu *>(_poXml->get_widget("RecentMenu_menu")); | |
213 vUpdateHistoryMenu(); | |
214 | |
215 m_poRecentResetItem = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("RecentReset")); | |
216 m_poRecentResetItem->signal_activate().connect(SigC::slot(*this, &Window::vOnRecentReset)); | |
217 | |
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)); | |
224 | |
225 // Import menu | |
226 // | |
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); | |
230 | |
231 // Export menu | |
232 // | |
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); | |
236 | |
237 // Frameskip menu | |
238 // | |
239 struct | |
240 { | |
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 else | |
264 { | |
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 } | |
279 | |
280 // Throttle menu | |
281 // | |
282 struct | |
283 { | |
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)); | |
301 | |
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); | |
315 | |
316 // Video menu | |
317 // | |
318 struct | |
319 { | |
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 } | |
345 | |
346 // Layers menu | |
347 // | |
348 struct | |
349 { | |
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 } | |
374 | |
375 // Emulator menu | |
376 // | |
377 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("EmulatorDirectories")); | |
378 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnDirectories)); | |
379 | |
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)); | |
386 | |
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)); | |
396 | |
397 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("EmulatorSelectBios")); | |
398 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnSelectBios)); | |
399 | |
400 // Show speed menu | |
401 // | |
402 struct | |
403 { | |
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 } | |
426 | |
427 // Save type menu | |
428 // | |
429 struct | |
430 { | |
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 } | |
456 | |
457 // Flash size menu | |
458 // | |
459 struct | |
460 { | |
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 } | |
482 | |
483 // Screenshot format menu | |
484 // | |
485 struct | |
486 { | |
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 } | |
508 | |
509 // Sound menu | |
510 // | |
511 std::string sDefaultSoundStatus = m_poSoundConfig->sGetKey("status"); | |
512 | |
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; | |
523 | |
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)); | |
533 | |
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)); | |
543 | |
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)); | |
550 | |
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)); | |
557 | |
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)); | |
564 | |
565 struct | |
566 { | |
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 } | |
589 | |
590 struct | |
591 { | |
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 } | |
614 | |
615 // Volume menu | |
616 // | |
617 struct | |
618 { | |
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 } | |
644 | |
645 // Gameboy menu | |
646 // | |
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)); | |
653 | |
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)); | |
660 | |
661 struct | |
662 { | |
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 } | |
688 | |
689 // Filter menu | |
690 // | |
691 struct | |
692 { | |
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 } | |
726 | |
727 poCMI = dynamic_cast<Gtk::CheckMenuItem *>(_poXml->get_widget("FilterDisableMmx")); | |
728 #ifdef MMX | |
729 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 // ! MMX | |
735 poCMI->set_active(); | |
736 poCMI->set_sensitive(false); | |
737 #endif // ! MMX | |
738 | |
739 // Interframe blending menu | |
740 // | |
741 struct | |
742 { | |
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 } | |
765 | |
766 // Joypad menu | |
767 // | |
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)); | |
771 | |
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)); | |
775 | |
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)); | |
779 | |
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)); | |
783 | |
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); | |
789 | |
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 } | |
800 | |
801 // Autofire menu | |
802 // | |
803 struct | |
804 { | |
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 } | |
825 | |
826 // GDB menu | |
827 // | |
828 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("GdbWait")); | |
829 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnGDBWait)); | |
830 | |
831 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("GdbLoadAndWait")); | |
832 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnGDBLoadAndWait)); | |
833 | |
834 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("GdbBreak")); | |
835 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnGDBBreak)); | |
836 | |
837 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("GdbDisconnect")); | |
838 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnGDBDisconnect)); | |
839 | |
840 // Help menu | |
841 // | |
842 poMI = dynamic_cast<Gtk::MenuItem *>(_poXml->get_widget("HelpAbout")); | |
843 poMI->signal_activate().connect(SigC::slot(*this, &Window::vOnHelpAbout)); | |
844 | |
845 // Init widgets sensitivity | |
846 for (std::list<Gtk::Widget *>::iterator it = m_listSensitiveWhenPlaying.begin(); | |
847 it != m_listSensitiveWhenPlaying.end(); | |
848 it++) | |
849 { | |
850 (*it)->set_sensitive(false); | |
851 } | |
852 | |
853 if (m_poInstance == NULL) | |
854 { | |
855 m_poInstance = this; | |
856 } | |
857 else | |
858 { | |
859 abort(); | |
860 } | |
861 } | |
862 | |
863 Window::~Window() | |
864 { | |
865 vOnFileClose(); | |
866 vSaveHistoryToConfig(); | |
867 vSaveJoypadsToConfig(); | |
868 vSaveConfig(m_sConfigFile); | |
869 | |
870 if (m_poFileOpenDialog != NULL) | |
871 { | |
872 delete m_poFileOpenDialog; | |
873 } | |
874 | |
875 if (m_poKeymap != NULL) | |
876 { | |
877 delete m_poKeymap; | |
878 } | |
879 | |
880 m_poInstance = NULL; | |
881 } | |
882 | |
883 void Window::vInitSystem() | |
884 { | |
885 #if G_BYTE_ORDER == G_LITTLE_ENDIAN | |
886 systemRedShift = 3; | |
887 systemGreenShift = 11; | |
888 systemBlueShift = 19; | |
889 RGB_LOW_BITS_MASK = 0x00010101; | |
890 #else | |
891 systemRedShift = 27; | |
892 systemGreenShift = 19; | |
893 systemBlueShift = 11; | |
894 RGB_LOW_BITS_MASK = 0x01010100; | |
895 #endif | |
896 | |
897 systemColorDepth = 32; | |
898 systemDebug = 0; | |
899 systemVerbose = 0; | |
900 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; | |
901 systemFrameSkip = 0; | |
902 systemSoundOn = false; | |
903 soundOffFlag = true; | |
904 | |
905 systemRenderedFrames = 0; | |
906 systemFPS = 0; | |
907 | |
908 emulating = 0; | |
909 debugger = false; | |
910 | |
911 for (int i = 0; i < 0x10000; i++) | |
912 { | |
913 #if G_BYTE_ORDER == G_LITTLE_ENDIAN | |
914 systemColorMap32[i] = (((i & 0x1f) << systemRedShift) | |
915 | (((i & 0x3e0) >> 5) << systemGreenShift) | |
916 | (((i & 0x7c00) >> 10) << systemBlueShift)); | |
917 #else | |
918 systemColorMap32[i] = (((i & 0x1f) << systemRedShift) | |
919 | (((i & 0x3e0) >> 5) << systemGreenShift) | |
920 | (((i & 0x7c00) >> 10) << systemBlueShift)); | |
921 #endif | |
922 } | |
923 | |
924 gbFrameSkip = 0; | |
925 | |
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 } | |
933 | |
934 Init_2xSaI(32); | |
935 } | |
936 | |
937 void Window::vInitSDL() | |
938 { | |
939 static bool bDone = false; | |
940 | |
941 if (bDone) | |
942 return; | |
943 | |
944 int iFlags = (SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE); | |
945 | |
946 if (SDL_Init(iFlags) < 0) | |
947 { | |
948 fprintf(stderr, "Failed to init SDL: %s", SDL_GetError()); | |
949 abort(); | |
950 } | |
951 | |
952 bDone = true; | |
953 } | |
954 | |
955 void Window::vInitConfig() | |
956 { | |
957 m_oConfig.vClear(); | |
958 | |
959 // History section | |
960 // | |
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", "" ); | |
973 | |
974 // Directories section | |
975 // | |
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", "" ); | |
982 | |
983 // Core section | |
984 // | |
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" ); | |
1005 | |
1006 // Display section | |
1007 // | |
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 MMX | |
1015 m_poDisplayConfig->vSetKey("filter_disable_mmx", false ); | |
1016 #endif // MMX | |
1017 | |
1018 // Sound section | |
1019 // | |
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 ); | |
1033 | |
1034 // Input section | |
1035 // | |
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 } | |
1063 | |
1064 void Window::vCheckConfig() | |
1065 { | |
1066 int iValue; | |
1067 int iAdjusted; | |
1068 std::string sValue; | |
1069 | |
1070 // Directories section | |
1071 // | |
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 } | |
1097 | |
1098 // Core section | |
1099 // | |
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 } | |
1109 | |
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 } | |
1119 | |
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 } | |
1129 | |
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 } | |
1139 | |
1140 iValue = m_poCoreConfig->oGetKey<int>("flash_size"); | |
1141 if (iValue != 64 && iValue != 128) | |
1142 { | |
1143 m_poCoreConfig->vSetKey("flash_size", 64); | |
1144 } | |
1145 | |
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 } | |
1152 | |
1153 sValue = m_poCoreConfig->sGetKey("screenshot_format"); | |
1154 if (sValue != "png" && sValue != "bmp") | |
1155 { | |
1156 sValue = "png"; | |
1157 } | |
1158 | |
1159 // Display section | |
1160 // | |
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 } | |
1167 | |
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 } | |
1174 | |
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 } | |
1181 | |
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 } | |
1188 | |
1189 // Sound section | |
1190 // | |
1191 sValue = m_poSoundConfig->sGetKey("status"); | |
1192 if (sValue != "off" && sValue != "on" && sValue != "mute") | |
1193 { | |
1194 m_poSoundConfig->vSetKey("status", "on"); | |
1195 } | |
1196 | |
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 } | |
1203 | |
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 } | |
1210 | |
1211 // Input section | |
1212 // | |
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 } | |
1220 | |
1221 void Window::vLoadConfig(const std::string & _rsFile) | |
1222 { | |
1223 try | |
1224 { | |
1225 m_oConfig.vLoad(_rsFile, false, false); | |
1226 } | |
1227 catch (const Glib::Error & e) | |
1228 { | |
1229 vPopupError(e.what().c_str()); | |
1230 } | |
1231 } | |
1232 | |
1233 void Window::vSaveConfig(const std::string & _rsFile) | |
1234 { | |
1235 try | |
1236 { | |
1237 m_oConfig.vSave(_rsFile); | |
1238 } | |
1239 catch (const Glib::Error & e) | |
1240 { | |
1241 vPopupError(e.what().c_str()); | |
1242 } | |
1243 } | |
1244 | |
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 } | |
1258 | |
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 } | |
1269 | |
1270 void Window::vHistoryAdd(const std::string & _rsFile) | |
1271 { | |
1272 if (m_poHistoryConfig->oGetKey<bool>("freeze")) | |
1273 { | |
1274 return; | |
1275 } | |
1276 | |
1277 m_listHistory.remove(_rsFile); | |
1278 m_listHistory.push_front(_rsFile); | |
1279 if (m_listHistory.size() > 10) | |
1280 { | |
1281 m_listHistory.pop_back(); | |
1282 } | |
1283 | |
1284 vUpdateHistoryMenu(); | |
1285 } | |
1286 | |
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 ; | |
1292 | |
1293 m_poRecentMenu->items().erase(it, m_poRecentMenu->items().end()); | |
1294 } | |
1295 | |
1296 void Window::vUpdateHistoryMenu() | |
1297 { | |
1298 vClearHistoryMenu(); | |
1299 | |
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)); | |
1308 | |
1309 m_oTooltips.set_tip(*poIMI, *it); | |
1310 | |
1311 poIMI->signal_activate().connect(SigC::bind<std::string>( | |
1312 SigC::slot(*this, &Window::vOnRecentFile), | |
1313 *it)); | |
1314 | |
1315 poIMI->set_accel_key(Gtk::AccelKey(uiAccelKey, Gdk::CONTROL_MASK)); | |
1316 poIMI->accelerate(*this); | |
1317 | |
1318 poIMI->show(); | |
1319 m_poRecentMenu->items().push_back(*poIMI); | |
1320 } | |
1321 } | |
1322 | |
1323 void Window::vLoadJoypadsFromConfig() | |
1324 { | |
1325 m_oJoypads.clear(); | |
1326 | |
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); | |
1332 | |
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"); | |
1346 | |
1347 m_oJoypads.push_back(oJoypadConfig); | |
1348 } | |
1349 } | |
1350 | |
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); | |
1358 | |
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 } | |
1373 | |
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 else | |
1387 { | |
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 } | |
1400 | |
1401 g_return_if_fail(m_iScreenWidth >= 1 && m_iScreenHeight >= 1); | |
1402 | |
1403 m_poScreenArea->vSetSize(m_iScreenWidth, m_iScreenHeight); | |
1404 m_poScreenArea->vSetScale(m_poDisplayConfig->oGetKey<int>("scale")); | |
1405 | |
1406 resize(1, 1); | |
1407 | |
1408 if (emulating) | |
1409 { | |
1410 vDrawScreen(); | |
1411 } | |
1412 else | |
1413 { | |
1414 vDrawDefaultScreen(); | |
1415 } | |
1416 } | |
1417 | |
1418 bool Window::bLoadROM(const std::string & _rsFile) | |
1419 { | |
1420 vOnFileClose(); | |
1421 | |
1422 m_sRomFile = _rsFile; | |
1423 const char * csFile = _rsFile.c_str(); | |
1424 | |
1425 IMAGE_TYPE eType = utilFindType(csFile); | |
1426 if (eType == IMAGE_UNKNOWN) | |
1427 { | |
1428 vPopupError(_("Unknown file type %s"), csFile); | |
1429 return false; | |
1430 } | |
1431 | |
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; | |
1450 | |
1451 useBios = m_poCoreConfig->oGetKey<bool>("use_bios_file"); | |
1452 //CPUInit(m_poCoreConfig->sGetKey("bios_file").c_str(), useBios); | |
1453 CPUInit(); | |
1454 CPUReset(); | |
1455 | |
1456 // If the bios file was rejected by CPUInit | |
1457 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 } | |
1465 | |
1466 if (! bLoaded) | |
1467 { | |
1468 return false; | |
1469 } | |
1470 | |
1471 vLoadBattery(); | |
1472 vUpdateScreen(); | |
1473 | |
1474 debugger = false; // May cause conflicts | |
1475 emulating = 1; | |
1476 m_bWasEmulating = false; | |
1477 m_uiThrottleDelay = 0; | |
1478 | |
1479 if (m_eCartridge == CartridgeGBA) | |
1480 { | |
1481 soundSetQuality(m_eSoundQuality); | |
1482 } | |
1483 else | |
1484 { | |
1485 gbSoundSetQuality(m_eSoundQuality); | |
1486 } | |
1487 | |
1488 vUpdateGameSlots(); | |
1489 vHistoryAdd(_rsFile); | |
1490 | |
1491 for (std::list<Gtk::Widget *>::iterator it = m_listSensitiveWhenPlaying.begin(); | |
1492 it != m_listSensitiveWhenPlaying.end(); | |
1493 it++) | |
1494 { | |
1495 (*it)->set_sensitive(); | |
1496 } | |
1497 | |
1498 if (m_poCoreConfig->oGetKey<bool>("load_game_auto")) | |
1499 { | |
1500 vOnLoadGameMostRecent(); | |
1501 } | |
1502 | |
1503 vStartEmu(); | |
1504 | |
1505 return true; | |
1506 } | |
1507 | |
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); | |
1514 | |
1515 Gtk::MessageDialog oDialog(*this, | |
1516 csMsg, | |
1517 #ifndef GTKMM20 | |
1518 false, | |
1519 #endif // ! GTKMM20 | |
1520 Gtk::MESSAGE_ERROR, | |
1521 Gtk::BUTTONS_OK); | |
1522 oDialog.run(); | |
1523 g_free(csMsg); | |
1524 } | |
1525 | |
1526 void Window::vPopupErrorV(const char * _csFormat, va_list _args) | |
1527 { | |
1528 char * csMsg = g_strdup_vprintf(_csFormat, _args); | |
1529 | |
1530 Gtk::MessageDialog oDialog(*this, | |
1531 csMsg, | |
1532 #ifndef GTKMM20 | |
1533 false, | |
1534 #endif // ! GTKMM20 | |
1535 Gtk::MESSAGE_ERROR, | |
1536 Gtk::BUTTONS_OK); | |
1537 oDialog.run(); | |
1538 g_free(csMsg); | |
1539 } | |
1540 | |
1541 void Window::vDrawScreen() | |
1542 { | |
1543 m_poScreenArea->vDrawPixels(pix); | |
1544 } | |
1545 | |
1546 void Window::vDrawDefaultScreen() | |
1547 { | |
1548 m_poScreenArea->vDrawColor(0x000000); // Black | |
1549 } | |
1550 | |
1551 void Window::vSetDefaultTitle() | |
1552 { | |
1553 set_title("VBA"); | |
1554 } | |
1555 | |
1556 void Window::vShowSpeed(int _iSpeed) | |
1557 { | |
1558 char csTitle[50]; | |
1559 | |
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 } | |
1572 | |
1573 void Window::vComputeFrameskip(int _iRate) | |
1574 { | |
1575 static u32 uiLastTime = 0; | |
1576 static int iFrameskipAdjust = 0; | |
1577 | |
1578 u32 uiTime = SDL_GetTicks(); | |
1579 | |
1580 if (m_bWasEmulating) | |
1581 { | |
1582 int iWantedSpeed = 100; | |
1583 | |
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 } | |
1598 | |
1599 if (m_bAutoFrameskip) | |
1600 { | |
1601 u32 uiDiff = uiTime - uiLastTime; | |
1602 int iSpeed = iWantedSpeed; | |
1603 | |
1604 if (uiDiff != 0) | |
1605 { | |
1606 iSpeed = (1000000 / _iRate) / uiDiff; | |
1607 } | |
1608 | |
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 else | |
1622 { | |
1623 if (iSpeed < iWantedSpeed - 20) | |
1624 { | |
1625 iFrameskipAdjust -= ((iWantedSpeed - 10) - iSpeed) / 5; | |
1626 } | |
1627 else if (systemFrameSkip < 9) | |
1628 { | |
1629 iFrameskipAdjust--; | |
1630 } | |
1631 | |
1632 if (iFrameskipAdjust <= -2) | |
1633 { | |
1634 iFrameskipAdjust += 2; | |
1635 if (systemFrameSkip < 9) | |
1636 { | |
1637 systemFrameSkip++; | |
1638 } | |
1639 } | |
1640 } | |
1641 } | |
1642 } | |
1643 else | |
1644 { | |
1645 m_bWasEmulating = true; | |
1646 } | |
1647 | |
1648 uiLastTime = uiTime; | |
1649 m_uiThrottleLastTime = uiTime; | |
1650 } | |
1651 | |
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 else | |
1661 { | |
1662 sBaseName = sCaptureDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile)); | |
1663 } | |
1664 std::string sFormat = m_poCoreConfig->sGetKey("screenshot_format"); | |
1665 | |
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 else | |
1675 { | |
1676 m_stEmulator.emuWriteBMP(csFile); | |
1677 } | |
1678 g_free(csFile); | |
1679 } | |
1680 | |
1681 u32 Window::uiReadJoypad() | |
1682 { | |
1683 u32 uiJoypad = m_uiJoypadState; | |
1684 | |
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 } | |
1694 | |
1695 return uiJoypad; | |
1696 } | |
1697 | |
1698 void Window::vCreateFileOpenDialog() | |
1699 { | |
1700 if (m_poFileOpenDialog != NULL) | |
1701 { | |
1702 return; | |
1703 } | |
1704 | |
1705 std::string sGBDir = m_poDirConfig->sGetKey("gb_roms"); | |
1706 std::string sGBADir = m_poDirConfig->sGetKey("gba_roms"); | |
1707 | |
1708 #ifdef GTKMM20 | |
1709 | |
1710 Gtk::FileSelection * poDialog = new Gtk::FileSelection(_("Open")); | |
1711 poDialog->set_transient_for(*this); | |
1712 | |
1713 if (sGBADir != "") | |
1714 { | |
1715 poDialog->set_filename(sGBADir + "/"); | |
1716 } | |
1717 else if (sGBDir != "") | |
1718 { | |
1719 poDialog->set_filename(sGBDir + "/"); | |
1720 } | |
1721 | |
1722 #else // ! GTKMM20 | |
1723 | |
1724 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); | |
1727 | |
1728 if (sGBDir != "") | |
1729 { | |
1730 poDialog->add_shortcut_folder(sGBDir); | |
1731 poDialog->set_current_folder(sGBDir); | |
1732 } | |
1733 | |
1734 if (sGBADir != "" && sGBADir != sGBDir) | |
1735 { | |
1736 poDialog->add_shortcut_folder(sGBADir); | |
1737 poDialog->set_current_folder(sGBADir); | |
1738 } | |
1739 | |
1740 const char * acsPattern[] = | |
1741 { | |
1742 // GBA | |
1743 "*.[bB][iI][nN]", "*.[aA][gG][bB]", "*.[gG][bB][aA]", | |
1744 // GB | |
1745 "*.[gG][bB]", "*.[sS][gG][bB]", "*.[cC][gG][bB]", "*.[gG][bB][cC]", | |
1746 // Both | |
1747 "*.[mM][bB]", "*.[eE][lL][fF]", "*.[zZ][iI][pP]", "*.[zZ]", "*.[gG][zZ]" | |
1748 }; | |
1749 | |
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 } | |
1756 | |
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 } | |
1763 | |
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 } | |
1770 | |
1771 poDialog->add_filter(oAllGBAFilter); | |
1772 poDialog->add_filter(oGBAFilter); | |
1773 poDialog->add_filter(oGBFilter); | |
1774 | |
1775 #endif // ! GTKMM20 | |
1776 | |
1777 m_poFileOpenDialog = poDialog; | |
1778 } | |
1779 | |
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 else | |
1789 { | |
1790 sBattery = sDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile)) + ".sav"; | |
1791 } | |
1792 | |
1793 if (m_stEmulator.emuReadBattery(sBattery.c_str())) | |
1794 { | |
1795 systemScreenMessage(_("Loaded battery")); | |
1796 } | |
1797 } | |
1798 | |
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 else | |
1808 { | |
1809 sBattery = sDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile)) + ".sav"; | |
1810 } | |
1811 | |
1812 if (m_stEmulator.emuWriteBattery(sBattery.c_str())) | |
1813 { | |
1814 systemScreenMessage(_("Saved battery")); | |
1815 } | |
1816 } | |
1817 | |
1818 void Window::vStartEmu() | |
1819 { | |
1820 if (m_oEmuSig.connected()) | |
1821 { | |
1822 return; | |
1823 } | |
1824 | |
1825 m_oEmuSig = Glib::signal_idle().connect(SigC::slot(*this, &Window::bOnEmuIdle), | |
1826 Glib::PRIORITY_DEFAULT_IDLE); | |
1827 } | |
1828 | |
1829 void Window::vStopEmu() | |
1830 { | |
1831 m_oEmuSig.disconnect(); | |
1832 m_bWasEmulating = false; | |
1833 } | |
1834 | |
1835 void Window::vSetThrottle(int _iPercent) | |
1836 { | |
1837 m_iThrottle = _iPercent; | |
1838 m_poCoreConfig->vSetKey("throttle", _iPercent); | |
1839 } | |
1840 | |
1841 void Window::vSelectBestThrottleItem() | |
1842 { | |
1843 struct | |
1844 { | |
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 } | |
1867 | |
1868 void Window::vUpdateGameSlots() | |
1869 { | |
1870 if (m_eCartridge == CartridgeNone) | |
1871 { | |
1872 std::string sDateTime = _("----/--/-- --:--:--"); | |
1873 | |
1874 for (int i = 0; i < 10; i++) | |
1875 { | |
1876 char csPrefix[10]; | |
1877 snprintf(csPrefix, sizeof(csPrefix), "%2d ", i + 1); | |
1878 | |
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); | |
1883 | |
1884 poLabel = dynamic_cast<Gtk::Label *>(m_apoSaveGameItem[i]->get_child()); | |
1885 poLabel->set_text(csPrefix + sDateTime); | |
1886 m_apoSaveGameItem[i]->set_sensitive(false); | |
1887 | |
1888 m_astGameSlot[i].m_bEmpty = true; | |
1889 } | |
1890 } | |
1891 else | |
1892 { | |
1893 std::string sFileBase; | |
1894 std::string sDir = m_poDirConfig->sGetKey("saves"); | |
1895 if (sDir == "") | |
1896 { | |
1897 sFileBase = sCutSuffix(m_sRomFile); | |
1898 } | |
1899 else | |
1900 { | |
1901 sFileBase = sDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile)); | |
1902 } | |
1903 | |
1904 const char * csDateFormat = _("%Y/%m/%d %H:%M:%S"); | |
1905 | |
1906 for (int i = 0; i < 10; i++) | |
1907 { | |
1908 char csPrefix[10]; | |
1909 snprintf(csPrefix, sizeof(csPrefix), "%2d ", i + 1); | |
1910 | |
1911 char csSlot[10]; | |
1912 snprintf(csSlot, sizeof(csSlot), "%d", i + 1); | |
1913 m_astGameSlot[i].m_sFile = sFileBase + csSlot + ".sgm"; | |
1914 | |
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 else | |
1923 { | |
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 } | |
1931 | |
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); | |
1936 | |
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 } | |
1943 | |
1944 } // VBA namespace |