2
#define __STDC_LIMIT_MACROS // required for ffmpeg
3
#define __STDC_CONSTANT_MACROS // required for ffmpeg
7
#include <wx/aboutdlg.h>
9
#include <wx/wfstream.h>
10
#include <wx/sstream.h>
12
#include <wx/numdlg.h>
13
#include <wx/progdlg.h>
16
#include <libavformat/avformat.h>
19
#include "../gb/gbPrinter.h"
20
#include "../gba/agbprint.h"
22
#define GetXRCDialog(n) \
23
wxStaticCast(FindWindow(XRCID(n)), wxDialog)
25
bool cmditem_lt(const struct cmditem &cmd1, const struct cmditem &cmd2)
27
return wxStrcmp(cmd1.cmd, cmd2.cmd) < 0;
30
#define update_bcheck(s, f) do { \
33
for(int i = 0; i < checkable_mi.size(); i++) { \
34
if(checkable_mi[i].cmd != id) \
36
f = checkable_mi[i].mi->IsChecked(); \
41
#define update_icheck(s, f, m, v) do { \
42
bool is_checked = ((f) & (m)) != (v); \
44
for(int i = 0; i < checkable_mi.size(); i++) { \
45
if(checkable_mi[i].cmd != id) \
47
is_checked = checkable_mi[i].mi->IsChecked(); \
50
f = ((f) & ~(m)) | (is_checked ? (v) : 0); \
52
#define update_icheck1(s, f, m) update_icheck(s, f, m, m)
54
#define update_check(s, v) do { \
56
for(int i = 0; i < checkable_mi.size(); i++) { \
57
if(checkable_mi[i].cmd != id) \
59
checkable_mi[i].mi->Check(v); \
66
// formerly OpenGBA, OpenGBC, OpenGB
67
// having just one means separate ROM dirs only make sense on the cmd line
69
static int open_ft = 0;
70
static wxString open_dir;
72
EVT_HANDLER(wxID_OPEN, "Open ROM...")
75
open_dir = gopts.gba_rom_dir;
76
// FIXME: ignore if non-existent or not a dir
77
wxString pats = _("GameBoy Advance Files (*.agb;*.gba;*.bin;*.elf;*.mb)|"
78
"*.agb;*.gba;*.bin;*.elf;*.mb"
79
"*.agb.gz;*.gba.gz;*.bin.gz;*.elf.gz;*.mb.gz"
80
"*.agb.z;*.gba.z;*.bin.z;*.elf.z;*.mb.z"
81
"|GameBoy Files (*.dmg;*.gb;*.gbc;*.cgb;*.sgb)|"
82
"*.dmg;*.gb;*.gbc;*.cgb;*.sgb"
83
"*.dmg.gz;*.gb.gz;*.gbc.gz;*.cgb.gz;*.sgb.gz"
84
"*.dmg.z;*.gb.z;*.gbc.z;*.cgb.z;*.sgb.z"
85
"|Archives (*.zip;*.7z;*.rar)"
86
"|*.zip;*.7z;*.rar|");
87
pats.append(wxALL_FILES);
88
wxFileDialog dlg(this, _("Open ROM file"), open_dir, wxT(""),
90
wxFD_OPEN|wxFD_FILE_MUST_EXIST);
91
dlg.SetFilterIndex(open_ft);
92
if(ShowModal(&dlg) == wxID_OK)
93
wxGetApp().pending_load = dlg.GetPath();
94
open_ft = dlg.GetFilterIndex();
95
open_dir = dlg.GetDirectory();
98
EVT_HANDLER(RecentReset, "Reset recent ROM list")
100
// only save config if there were items to remove
101
if(gopts.recent->GetCount()) {
102
while(gopts.recent->GetCount())
103
gopts.recent->RemoveFileFromHistory(0);
104
wxConfig *cfg = wxGetApp().cfg;
105
cfg->SetPath(wxT("/Recent"));
106
gopts.recent->Save(*cfg);
107
cfg->SetPath(wxT("/"));
112
EVT_HANDLER(RecentFreeze, "Freeze recent ROM list (toggle)")
114
update_bcheck("RecentFreeze", gopts.recent_freeze);
118
// following 10 should really be a single ranged handler
119
// former names: Recent01 .. Recent10
120
EVT_HANDLER(wxID_FILE1, "Load recent ROM 1")
122
panel->LoadGame(gopts.recent->GetHistoryFile(0));
125
EVT_HANDLER(wxID_FILE2, "Load recent ROM 2")
127
panel->LoadGame(gopts.recent->GetHistoryFile(1));
130
EVT_HANDLER(wxID_FILE3, "Load recent ROM 3")
132
panel->LoadGame(gopts.recent->GetHistoryFile(2));
135
EVT_HANDLER(wxID_FILE4, "Load recent ROM 4")
137
panel->LoadGame(gopts.recent->GetHistoryFile(3));
140
EVT_HANDLER(wxID_FILE5, "Load recent ROM 5")
142
panel->LoadGame(gopts.recent->GetHistoryFile(4));
145
EVT_HANDLER(wxID_FILE6, "Load recent ROM 6")
147
panel->LoadGame(gopts.recent->GetHistoryFile(5));
150
EVT_HANDLER(wxID_FILE7, "Load recent ROM 7")
152
panel->LoadGame(gopts.recent->GetHistoryFile(6));
155
EVT_HANDLER(wxID_FILE8, "Load recent ROM 8")
157
panel->LoadGame(gopts.recent->GetHistoryFile(7));
160
EVT_HANDLER(wxID_FILE9, "Load recent ROM 9")
162
panel->LoadGame(gopts.recent->GetHistoryFile(8));
165
EVT_HANDLER(wxID_FILE10, "Load recent ROM 10")
167
panel->LoadGame(gopts.recent->GetHistoryFile(9));
170
static const struct rom_maker {
171
const wxChar *code, *name;
173
{ wxT("01"), wxT("Nintendo") },
174
{ wxT("02"), wxT("Rocket Games") },
175
{ wxT("08"), wxT("Capcom") },
176
{ wxT("09"), wxT("Hot B Co.") },
177
{ wxT("0A"), wxT("Jaleco") },
178
{ wxT("0B"), wxT("Coconuts Japan") },
179
{ wxT("0C"), wxT("Coconuts Japan/G.X.Media") },
180
{ wxT("0H"), wxT("Starfish") },
181
{ wxT("0L"), wxT("Warashi Inc.") },
182
{ wxT("0N"), wxT("Nowpro") },
183
{ wxT("0P"), wxT("Game Village") },
184
{ wxT("13"), wxT("Electronic Arts Japan") },
185
{ wxT("18"), wxT("Hudson Soft Japan") },
186
{ wxT("19"), wxT("S.C.P.") },
187
{ wxT("1A"), wxT("Yonoman") },
188
{ wxT("1G"), wxT("SMDE") },
189
{ wxT("1P"), wxT("Creatures Inc.") },
190
{ wxT("1Q"), wxT("TDK Deep Impresion") },
191
{ wxT("20"), wxT("Destination Software") },
192
{ wxT("22"), wxT("VR 1 Japan") },
193
{ wxT("25"), wxT("San-X") },
194
{ wxT("28"), wxT("Kemco Japan") },
195
{ wxT("29"), wxT("Seta") },
196
{ wxT("2H"), wxT("Ubisoft Japan") },
197
{ wxT("2K"), wxT("NEC InterChannel") },
198
{ wxT("2L"), wxT("Tam") },
199
{ wxT("2M"), wxT("Jordan") },
200
{ wxT("2N"), wxT("Smilesoft") },
201
{ wxT("2Q"), wxT("Mediakite") },
202
{ wxT("36"), wxT("Codemasters") },
203
{ wxT("37"), wxT("GAGA Communications") },
204
{ wxT("38"), wxT("Laguna") },
205
{ wxT("39"), wxT("Telstar Fun and Games") },
206
{ wxT("41"), wxT("Ubi Soft Entertainment") },
207
{ wxT("42"), wxT("Sunsoft") },
208
{ wxT("47"), wxT("Spectrum Holobyte") },
209
{ wxT("49"), wxT("IREM") },
210
{ wxT("4D"), wxT("Malibu Games") },
211
{ wxT("4F"), wxT("Eidos/U.S. Gold") },
212
{ wxT("4J"), wxT("Fox Interactive") },
213
{ wxT("4K"), wxT("Time Warner Interactive") },
214
{ wxT("4Q"), wxT("Disney") },
215
{ wxT("4S"), wxT("Black Pearl") },
216
{ wxT("4X"), wxT("GT Interactive") },
217
{ wxT("4Y"), wxT("RARE") },
218
{ wxT("4Z"), wxT("Crave Entertainment") },
219
{ wxT("50"), wxT("Absolute Entertainment") },
220
{ wxT("51"), wxT("Acclaim") },
221
{ wxT("52"), wxT("Activision") },
222
{ wxT("53"), wxT("American Sammy Corp.") },
223
{ wxT("54"), wxT("Take 2 Interactive") },
224
{ wxT("55"), wxT("Hi Tech") },
225
{ wxT("56"), wxT("LJN LTD.") },
226
{ wxT("58"), wxT("Mattel") },
227
{ wxT("5A"), wxT("Mindscape/Red Orb Ent.") },
228
{ wxT("5C"), wxT("Taxan") },
229
{ wxT("5D"), wxT("Midway") },
230
{ wxT("5F"), wxT("American Softworks") },
231
{ wxT("5G"), wxT("Majesco Sales Inc") },
232
{ wxT("5H"), wxT("3DO") },
233
{ wxT("5K"), wxT("Hasbro") },
234
{ wxT("5L"), wxT("NewKidCo") },
235
{ wxT("5M"), wxT("Telegames") },
236
{ wxT("5N"), wxT("Metro3D") },
237
{ wxT("5P"), wxT("Vatical Entertainment") },
238
{ wxT("5Q"), wxT("LEGO Media") },
239
{ wxT("5S"), wxT("Xicat Interactive") },
240
{ wxT("5T"), wxT("Cryo Interactive") },
241
{ wxT("5W"), wxT("Red Storm Ent./BKN Ent.") },
242
{ wxT("5X"), wxT("Microids") },
243
{ wxT("5Z"), wxT("Conspiracy Entertainment Corp.") },
244
{ wxT("60"), wxT("Titus Interactive Studios") },
245
{ wxT("61"), wxT("Virgin Interactive") },
246
{ wxT("62"), wxT("Maxis") },
247
{ wxT("64"), wxT("LucasArts Entertainment") },
248
{ wxT("67"), wxT("Ocean") },
249
{ wxT("69"), wxT("Electronic Arts") },
250
{ wxT("6E"), wxT("Elite Systems Ltd.") },
251
{ wxT("6F"), wxT("Electro Brain") },
252
{ wxT("6G"), wxT("The Learning Company") },
253
{ wxT("6H"), wxT("BBC") },
254
{ wxT("6J"), wxT("Software 2000") },
255
{ wxT("6L"), wxT("BAM! Entertainment") },
256
{ wxT("6M"), wxT("Studio 3") },
257
{ wxT("6Q"), wxT("Classified Games") },
258
{ wxT("6S"), wxT("TDK Mediactive") },
259
{ wxT("6U"), wxT("DreamCatcher") },
260
{ wxT("6V"), wxT("JoWood Productions") },
261
{ wxT("6W"), wxT("SEGA") },
262
{ wxT("6X"), wxT("Wannado Edition") },
263
{ wxT("6Y"), wxT("LSP") },
264
{ wxT("6Z"), wxT("ITE Media") },
265
{ wxT("70"), wxT("Infogrames") },
266
{ wxT("71"), wxT("Interplay") },
267
{ wxT("72"), wxT("JVC Musical Industries Inc") },
268
{ wxT("73"), wxT("Parker Brothers") },
269
{ wxT("75"), wxT("SCI") },
270
{ wxT("78"), wxT("THQ") },
271
{ wxT("79"), wxT("Accolade") },
272
{ wxT("7A"), wxT("Triffix Ent. Inc.") },
273
{ wxT("7C"), wxT("Microprose Software") },
274
{ wxT("7D"), wxT("Universal Interactive Studios") },
275
{ wxT("7F"), wxT("Kemco") },
276
{ wxT("7G"), wxT("Rage Software") },
277
{ wxT("7H"), wxT("Encore") },
278
{ wxT("7J"), wxT("Zoo") },
279
{ wxT("7K"), wxT("BVM") },
280
{ wxT("7L"), wxT("Simon & Schuster Interactive") },
281
{ wxT("7M"), wxT("Asmik Ace Entertainment Inc./AIA") },
282
{ wxT("7N"), wxT("Empire Interactive") },
283
{ wxT("7Q"), wxT("Jester Interactive") },
284
{ wxT("7T"), wxT("Scholastic") },
285
{ wxT("7U"), wxT("Ignition Entertainment") },
286
{ wxT("7W"), wxT("Stadlbauer") },
287
{ wxT("80"), wxT("Misawa") },
288
{ wxT("83"), wxT("LOZC") },
289
{ wxT("8B"), wxT("Bulletproof Software") },
290
{ wxT("8C"), wxT("Vic Tokai Inc.") },
291
{ wxT("8J"), wxT("General Entertainment") },
292
{ wxT("8N"), wxT("Success") },
293
{ wxT("8P"), wxT("SEGA Japan") },
294
{ wxT("91"), wxT("Chun Soft") },
295
{ wxT("92"), wxT("Video System") },
296
{ wxT("93"), wxT("BEC") },
297
{ wxT("96"), wxT("Yonezawa/S'pal") },
298
{ wxT("97"), wxT("Kaneko") },
299
{ wxT("99"), wxT("Victor Interactive Software") },
300
{ wxT("9A"), wxT("Nichibutsu/Nihon Bussan") },
301
{ wxT("9B"), wxT("Tecmo") },
302
{ wxT("9C"), wxT("Imagineer") },
303
{ wxT("9F"), wxT("Nova") },
304
{ wxT("9H"), wxT("Bottom Up") },
305
{ wxT("9L"), wxT("Hasbro Japan") },
306
{ wxT("9N"), wxT("Marvelous Entertainment") },
307
{ wxT("9P"), wxT("Keynet Inc.") },
308
{ wxT("9Q"), wxT("Hands-On Entertainment") },
309
{ wxT("A0"), wxT("Telenet") },
310
{ wxT("A1"), wxT("Hori") },
311
{ wxT("A4"), wxT("Konami") },
312
{ wxT("A6"), wxT("Kawada") },
313
{ wxT("A7"), wxT("Takara") },
314
{ wxT("A9"), wxT("Technos Japan Corp.") },
315
{ wxT("AA"), wxT("JVC") },
316
{ wxT("AC"), wxT("Toei Animation") },
317
{ wxT("AD"), wxT("Toho") },
318
{ wxT("AF"), wxT("Namco") },
319
{ wxT("AG"), wxT("Media Rings Corporation") },
320
{ wxT("AH"), wxT("J-Wing") },
321
{ wxT("AK"), wxT("KID") },
322
{ wxT("AL"), wxT("MediaFactory") },
323
{ wxT("AP"), wxT("Infogrames Hudson") },
324
{ wxT("AQ"), wxT("Kiratto. Ludic Inc") },
325
{ wxT("B0"), wxT("Acclaim Japan") },
326
{ wxT("B1"), wxT("ASCII") },
327
{ wxT("B2"), wxT("Bandai") },
328
{ wxT("B4"), wxT("Enix") },
329
{ wxT("B6"), wxT("HAL Laboratory") },
330
{ wxT("B7"), wxT("SNK") },
331
{ wxT("B9"), wxT("Pony Canyon Hanbai") },
332
{ wxT("BA"), wxT("Culture Brain") },
333
{ wxT("BB"), wxT("Sunsoft") },
334
{ wxT("BD"), wxT("Sony Imagesoft") },
335
{ wxT("BF"), wxT("Sammy") },
336
{ wxT("BG"), wxT("Magical") },
337
{ wxT("BJ"), wxT("Compile") },
338
{ wxT("BL"), wxT("MTO Inc.") },
339
{ wxT("BN"), wxT("Sunrise Interactive") },
340
{ wxT("BP"), wxT("Global A Entertainment") },
341
{ wxT("BQ"), wxT("Fuuki") },
342
{ wxT("C0"), wxT("Taito") },
343
{ wxT("C2"), wxT("Kemco") },
344
{ wxT("C3"), wxT("Square Soft") },
345
{ wxT("C5"), wxT("Data East") },
346
{ wxT("C6"), wxT("Tonkin House") },
347
{ wxT("C8"), wxT("Koei") },
348
{ wxT("CA"), wxT("Konami/Palcom/Ultra") },
349
{ wxT("CB"), wxT("Vapinc/NTVIC") },
350
{ wxT("CC"), wxT("Use Co.,Ltd.") },
351
{ wxT("CD"), wxT("Meldac") },
352
{ wxT("CE"), wxT("FCI/Pony Canyon") },
353
{ wxT("CF"), wxT("Angel") },
354
{ wxT("CM"), wxT("Konami Computer Entertainment Osaka") },
355
{ wxT("CP"), wxT("Enterbrain") },
356
{ wxT("D1"), wxT("Sofel") },
357
{ wxT("D2"), wxT("Quest") },
358
{ wxT("D3"), wxT("Sigma Enterprises") },
359
{ wxT("D4"), wxT("Ask Kodansa") },
360
{ wxT("D6"), wxT("Naxat") },
361
{ wxT("D7"), wxT("Copya System") },
362
{ wxT("D9"), wxT("Banpresto") },
363
{ wxT("DA"), wxT("TOMY") },
364
{ wxT("DB"), wxT("LJN Japan") },
365
{ wxT("DD"), wxT("NCS") },
366
{ wxT("DF"), wxT("Altron Corporation") },
367
{ wxT("DH"), wxT("Gaps Inc.") },
368
{ wxT("DN"), wxT("ELF") },
369
{ wxT("E2"), wxT("Yutaka") },
370
{ wxT("E3"), wxT("Varie") },
371
{ wxT("E5"), wxT("Epoch") },
372
{ wxT("E7"), wxT("Athena") },
373
{ wxT("E8"), wxT("Asmik Ace Entertainment Inc.") },
374
{ wxT("E9"), wxT("Natsume") },
375
{ wxT("EA"), wxT("King Records") },
376
{ wxT("EB"), wxT("Atlus") },
377
{ wxT("EC"), wxT("Epic/Sony Records") },
378
{ wxT("EE"), wxT("IGS") },
379
{ wxT("EL"), wxT("Spike") },
380
{ wxT("EM"), wxT("Konami Computer Entertainment Tokyo") },
381
{ wxT("EN"), wxT("Alphadream Corporation") },
382
{ wxT("F0"), wxT("A Wave") },
383
{ wxT("G1"), wxT("PCCW") },
384
{ wxT("G4"), wxT("KiKi Co Ltd") },
385
{ wxT("G5"), wxT("Open Sesame Inc.") },
386
{ wxT("G6"), wxT("Sims") },
387
{ wxT("G7"), wxT("Broccoli") },
388
{ wxT("G8"), wxT("Avex") },
389
{ wxT("G9"), wxT("D3 Publisher") },
390
{ wxT("GB"), wxT("Konami Computer Entertainment Japan") },
391
{ wxT("GD"), wxT("Square-Enix") },
392
{ wxT("HY"), wxT("Sachen") }
394
#define num_makers (sizeof(makers)/sizeof(makers[0]))
395
static bool maker_lt(const rom_maker &r1, const rom_maker &r2)
397
return wxStrcmp(r1.code, r2.code) < 0;
400
EVT_HANDLER_MASK(RomInformation, "ROM information...", CMDEN_GB|CMDEN_GBA)
403
#define setlab(id) do { \
404
/* SetLabelText is not in 2.8 */ \
405
s.Replace(wxT("&"), wxT("&&"), true); \
406
XRCCTRL(*dlg, id, wxControl)->SetLabel(s); \
408
#define setblab(id, b) do { \
409
s.Printf(wxT("%02x"), (unsigned int)b); \
412
#define setblabs(id, b, ts) do { \
413
s.Printf(wxT("%02x (%s)"), (unsigned int)b, ts); \
416
#define setlabs(id, ts, l) do { \
417
s = wxString((const char *)&(ts), wxConvLibc, l); \
420
switch(panel->game_type()) {
423
wxDialog *dlg = GetXRCDialog("GBROMInfo");
424
setlabs("Title", gbRom[0x134], 15);
425
setblab("Color", gbRom[0x143]);
426
if(gbRom[0x14b] == 0x33)
427
s = wxString((const char *)&gbRom[0x144], wxConvUTF8, 2);
429
s.Printf(wxT("%02x"), gbRom[0x14b]);
431
const rom_maker m = { s.c_str() }, *rm;
432
rm = std::lower_bound(&makers[0], &makers[num_makers], m, maker_lt);
433
if(rm < &makers[num_makers] && !wxStrcmp(m.code, rm->code))
438
setblab("UnitCode", gbRom[0x146]);
440
switch(gbRom[0x147]) {
445
type = _("ROM+MBC1");
448
type = _("ROM+MBC1+RAM");
451
type = _("ROM+MBC1+RAM+BATT");
454
type = _("ROM+MBC2");
457
type = _("ROM+MBC2+BATT");
460
type = _("ROM+MMM01");
463
type = _("ROM+MMM01+RAM");
466
type = _("ROM+MMM01+RAM+BATT");
469
type = _("ROM+MBC3+TIMER+BATT");
472
type = _("ROM+MBC3+TIMER+RAM+BATT");
475
type = _("ROM+MBC3");
478
type = _("ROM+MBC3+RAM");
481
type = _("ROM+MBC3+RAM+BATT");
484
type = _("ROM+MBC5");
487
type = _("ROM+MBC5+RAM");
490
type = _("ROM+MBC5+RAM+BATT");
493
type = _("ROM+MBC5+RUMBLE");
496
type = _("ROM+MBC5+RUMBLE+RAM");
499
type = _("ROM+MBC5+RUMBLE+RAM+BATT");
502
type = _("ROM+MBC7+BATT");
505
type = _("GameGenie");
508
type = _("GameShark V3.0");
511
type = _("ROM+POCKET CAMERA");
514
type = _("ROM+BANDAI TAMA5");
517
type = _("ROM+HuC-3");
520
type = _("ROM+HuC-1");
525
setblabs("DeviceType", gbRom[0x147], type);
526
switch(gbRom[0x148]) {
554
setblabs("ROMSize", gbRom[0x148], type);
555
switch(gbRom[0x149]) {
575
setblabs("RAMSize", gbRom[0x149], type);
576
setblab("DestCode", gbRom[0x14a]);
577
setblab("LicCode", gbRom[0x14b]);
578
setblab("Version", gbRom[0x14c]);
580
for(int i = 0x134; i < 0x14d; i++)
583
s.Printf(wxT("%02x (%02x)"), crc, gbRom[0x14d]);
586
for(int i = 0; i < gbRomSize; i++)
588
crc16 -= gbRom[0x14e] + gbRom[0x14f];
589
s.Printf(wxT("%04x (%04x)"), crc16, gbRom[0x14e]*256+gbRom[0x14f]);
597
wxDialog *dlg = GetXRCDialog("GBAROMInfo");
598
setlabs("Title", rom[0xa0], 12);
599
setlabs("GameCode", rom[0xac], 4);
600
setlabs("MakerCode", rom[0xb0], 2);
601
const rom_maker m = { s.c_str() }, *rm;
602
rm = std::lower_bound(&makers[0], &makers[num_makers], m, maker_lt);
603
if(rm < &makers[num_makers] && !wxStrcmp(m.code, rm->code))
608
setblab("UnitCode", rom[0xb3]);
609
s.Printf(wxT("%02x"), (unsigned int)rom[0xb4]);
611
s.append(wxT(" (DACS)"));
612
setlab("DeviceType");
613
setblab("Version", rom[0xbc]);
615
for(int i = 0xa0; i < 0xbd; i++)
618
s.Printf(wxT("%02x (%02x)"), crc, rom[0xbd]);
627
static wxString batimp_path;
629
EVT_HANDLER_MASK(ImportBatteryFile, "Import battery file...", CMDEN_GB|CMDEN_GBA)
631
if(!batimp_path.size())
632
batimp_path = panel->bat_dir();
633
wxFileDialog dlg(this, _("Select battery file"), batimp_path, wxEmptyString,
634
_("Battery file (*.sav)|*.sav|Flash save (*.dat)|*.dat"), wxFD_OPEN|wxFD_FILE_MUST_EXIST);
635
int ret = ShowModal(&dlg);
636
batimp_path = dlg.GetDirectory();
639
wxString fn = dlg.GetPath();
640
ret = wxMessageBox(_("Importing a battery file will erase any saved games (permanently after the next write). Do you want to continue?"),
641
_("Confirm import"), wxYES_NO|wxICON_EXCLAMATION);
644
if(panel->emusys->emuReadBattery(fn.mb_fn_str()))
645
msg.Printf(_("Loaded battery %s"), fn.c_str());
647
msg.Printf(_("Error loading battery %s"), fn.c_str());
648
systemScreenMessage(msg);
652
EVT_HANDLER_MASK(ImportGamesharkCodeFile, "Import GameShark code file...", CMDEN_GB|CMDEN_GBA)
654
static wxString path;
655
wxFileDialog dlg(this, _("Select code file"), path, wxEmptyString,
656
panel->game_type() == IMAGE_GBA ?
657
_("Gameshark Code File (*.spc;*.xpc)|*.spc;*.xpc"):
658
_("Gameshark Code File (*.gcf)|*.gcf"),
659
wxFD_OPEN|wxFD_FILE_MUST_EXIST);
660
int ret = ShowModal(&dlg);
661
path = dlg.GetDirectory();
664
wxString fn = dlg.GetPath();
665
ret = wxMessageBox(_("Importing a code file will replace any loaded cheats. Do you want to continue?"),
666
_("Confirm import"), wxYES_NO|wxICON_EXCLAMATION);
670
if(panel->game_type() == IMAGE_GB)
671
// FIXME: this routine will not work on big-endian systems
672
// if the underlying file format is little-endian
673
// (fix in gb/gbCheats.cpp)
674
res = gbCheatReadGSCodeFile(fn.mb_fn_str());
676
// need to select game first
677
wxFFile f(fn, wxT("rb"));
679
wxLogError(_("Cannot open file %s"), fn.c_str());
682
// FIXME: in my code, I assume file format is little-endian
683
// however, in core code, it is assumed to be native-endian
686
if(f.Read(&len, sizeof(len)) != sizeof(len) ||
687
wxUINT32_SWAP_ON_BE(len) != 14 ||
688
f.Read(buf, 14) != 14 || memcmp(buf, "SharkPortCODES", 14)) {
689
wxLogError(_("Unsupported code file %s"), fn.c_str());
693
if(f.Read(&len, sizeof(len)) != sizeof(len))
697
wxDialog *seldlg = GetXRCDialog("CodeSelect");
698
wxControlWithItems *lst = XRCCTRL(*seldlg, "CodeList", wxControlWithItems);
702
if(f.Read(&slen, sizeof(slen)) != sizeof(slen) ||
703
slen > 1024) // arbitrary upper bound
706
if(f.Read(buf, slen) != slen)
708
lst->Append(wxString(buf, wxConvLibc, slen));
710
if(f.Read(&ncodes, sizeof(ncodes)) != sizeof(ncodes))
712
for(; ncodes > 0; ncodes--) {
713
if(f.Read(&slen, sizeof(slen)) != sizeof(slen))
715
f.Seek(slen, wxFromCurrent);
716
if(f.Read(&slen, sizeof(slen)) != sizeof(slen))
718
f.Seek(slen + 4, wxFromCurrent);
719
if(f.Read(&slen, sizeof(slen)) != sizeof(slen))
721
f.Seek(slen * 12, wxFromCurrent);
724
int sel = ShowModal(seldlg);
727
game = lst->GetSelection();
728
if(game == wxNOT_FOUND)
731
bool v3 = fn.size() >= 4 &&
732
wxString(fn.substr(fn.size() - 4)).IsSameAs(wxT(".xpc"), false);
734
// FIXME: this routine will not work on big-endian systems
735
// if the underlying file format is little-endian
736
// (fix in gba/Cheats.cpp)
737
res = cheatsImportGSACodeFile(fn.mb_fn_str(), game, v3);
740
msg.Printf(_("Loaded code file %s"), fn.c_str());
742
msg.Printf(_("Error loading code file %s"), fn.c_str());
743
systemScreenMessage(msg);
747
static wxString gss_path;
749
EVT_HANDLER_MASK(ImportGamesharkActionReplaySnapshot,
750
"Import GameShark Action Replay snapshot...", CMDEN_GB|CMDEN_GBA)
752
wxFileDialog dlg(this, _("Select snapshot file"), gss_path, wxEmptyString,
753
panel->game_type() == IMAGE_GBA ?
754
_("GS & PAC Snapshots (*.sps;*.xps)|*.sps;*.xps|GameShark SP Snapshots (*.gsv)|*.gsv"):
755
_("Gameboy Snapshot (*.gbs)|*.gbs"),
756
wxFD_OPEN|wxFD_FILE_MUST_EXIST);
757
int ret = ShowModal(&dlg);
758
gss_path = dlg.GetDirectory();
761
wxString fn = dlg.GetPath();
762
ret = wxMessageBox(_("Importing a snapshot file will erase any saved games (permanently after the next write). Do you want to continue?"),
763
_("Confirm import"), wxYES_NO|wxICON_EXCLAMATION);
767
if(panel->game_type() == IMAGE_GB)
768
res = gbReadGSASnapshot(fn.mb_fn_str());
770
bool gsv = fn.size() >= 4 &&
771
wxString(fn.substr(fn.size() - 4)).IsSameAs(wxT(".gsv"), false);
773
// FIXME: this will fail on big-endian machines if
774
// file format is little-endian
776
res = CPUReadGSASPSnapshot(fn.mb_fn_str());
778
// FIXME: this will fail on big-endian machines if
779
// file format is little-endian
781
res = CPUReadGSASnapshot(fn.mb_fn_str());
784
msg.Printf(_("Loaded snapshot file %s"), fn.c_str());
786
msg.Printf(_("Error loading snapshot file %s"), fn.c_str());
787
systemScreenMessage(msg);
791
EVT_HANDLER_MASK(ExportBatteryFile, "Export battery file...", CMDEN_GB|CMDEN_GBA)
793
if(!batimp_path.size())
794
batimp_path = panel->bat_dir();
795
wxFileDialog dlg(this, _("Select battery file"), batimp_path, wxEmptyString,
796
_("Battery file (*.sav)|*.sav|Flash save (*.dat)|*.dat"), wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
797
int ret = ShowModal(&dlg);
798
batimp_path = dlg.GetDirectory();
801
wxString fn = dlg.GetPath();
803
if(panel->emusys->emuWriteBattery(fn.mb_fn_str()))
804
msg.Printf(_("Wrote battery %s"), fn.c_str());
806
msg.Printf(_("Error writing battery %s"), fn.c_str());
807
systemScreenMessage(msg);
810
EVT_HANDLER_MASK(ExportGamesharkSnapshot, "Export GameShark snapshot...", CMDEN_GBA)
813
wxLogError(_("EEPROM saves cannot be exported"));
816
wxString def_name = panel->game_name();
817
def_name.append(wxT(".sps"));
818
wxFileDialog dlg(this, _("Select snapshot file"), gss_path, def_name,
819
_("Gameshark Snapshot (*.sps)|*.sps"), wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
820
int ret = ShowModal(&dlg);
821
gss_path = dlg.GetDirectory();
824
wxString fn = dlg.GetPath();
825
wxDialog *infodlg = GetXRCDialog("ExportSPS");
826
wxTextCtrl *tit = XRCCTRL(*infodlg, "Title", wxTextCtrl),
827
*dsc = XRCCTRL(*infodlg, "Description", wxTextCtrl),
828
*n = XRCCTRL(*infodlg, "Notes", wxTextCtrl);
829
tit->SetValue(wxString((const char *)&rom[0xa0], wxConvLibc, 12));
830
dsc->SetValue(wxDateTime::Now().Format(wxT("%c")));
831
n->SetValue(_("Exported from VisualBoyAdvance-M"));
832
if(ShowModal(infodlg) != wxID_OK)
836
// FIXME: this will fail on big-endian machines if file format is
839
if(CPUWriteGSASnapshot(fn.mb_fn_str(), tit->GetValue().utf8_str(),
840
dsc->GetValue().utf8_str(), n->GetValue().utf8_str()))
841
msg.Printf(_("Saved snapshot file %s"), fn.c_str());
843
msg.Printf(_("Error saving snapshot file %s"), fn.c_str());
844
systemScreenMessage(msg);
847
EVT_HANDLER_MASK(ScreenCapture, "Screen capture...", CMDEN_GB|CMDEN_GBA)
849
static wxString scap_path;
850
if(!scap_path.size()) {
851
scap_path = gopts.scrshot_dir;
852
if(scap_path.size()) {
853
wxFileName sp(scap_path, wxEmptyString);
855
scap_path = panel->game_dir() + wxT('/') + gopts.scrshot_dir;
856
wxFileName::Mkdir(scap_path, 0777, wxPATH_MKDIR_FULL);
859
wxString def_name = panel->game_name();
860
if(gopts.cap_format == 0)
861
def_name.append(wxT(".png"));
863
def_name.append(wxT(".bmp"));
864
wxFileDialog dlg(this, _("Select output file"), scap_path, def_name,
865
_("PNG images|*.png|BMP images|*.bmp"), wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
866
dlg.SetFilterIndex(gopts.cap_format);
867
int ret = ShowModal(&dlg);
868
scap_path = dlg.GetDirectory();
871
wxString fn = dlg.GetPath();
872
int fmt = dlg.GetFilterIndex();
874
if(wxString(fn.substr(fn.size() - 4)).IsSameAs(wxT(".bmp"), false))
876
else if(wxString(fn.substr(fn.size() - 4)).IsSameAs(wxT(".png"), false))
880
panel->emusys->emuWritePNG(fn.mb_fn_str());
882
panel->emusys->emuWriteBMP(fn.mb_fn_str());
884
msg.Printf(_("Wrote snapshot %s"), fn.c_str());
885
systemScreenMessage(msg);
888
EVT_HANDLER_MASK(RecordSoundStartRecording, "Start sound recording...", CMDEN_NSREC)
891
static wxString sound_exts;
892
static int sound_extno;
893
static wxString sound_path;
895
if(!sound_exts.size()) {
899
for(fmt = NULL, extno = 0; (fmt = av_oformat_next(fmt)); ) {
902
if(fmt->audio_codec == CODEC_ID_NONE)
904
sound_exts.append(wxString(fmt->long_name ? fmt->long_name : fmt->name, wxConvLibc));
905
sound_exts.append(_(" files ("));
906
wxString ext(fmt->extensions, wxConvLibc);
907
ext.Replace(wxT(","), wxT(";*."));
908
ext.insert(0, wxT("*."));
909
if(sound_extno < 0 && ext.find(wxT("*.wav")) != wxString::npos)
911
sound_exts.append(ext);
912
sound_exts.append(wxT(")|"));
913
sound_exts.append(ext);
914
sound_exts.append(wxT('|'));
917
sound_exts.append(wxALL_FILES);
921
if(!sound_path.size()) {
922
if(!gopts.recording_dir.size())
923
sound_path = panel->game_dir();
925
wxFileName sp(gopts.recording_dir, wxEmptyString);
927
sound_path = gopts.recording_dir;
929
sound_path = panel->game_dir() + wxT('/') + gopts.recording_dir;
931
wxFileName::Mkdir(sound_path, 0777, wxPATH_MKDIR_FULL);
933
wxString def_name = panel->game_name();
934
const wxChar *extoff = sound_exts.c_str();
935
for(int i = 0; i < sound_extno; i++) {
936
extoff = wxStrchr(extoff, wxT('|')) + 1;
937
extoff = wxStrchr(extoff, wxT('|')) + 1;
939
extoff = wxStrchr(extoff, wxT('|')) + 2; // skip *
940
def_name += wxString(extoff, wxStrcspn(extoff, wxT(";|")));
941
wxFileDialog dlg(this, _("Select output file"), sound_path, def_name,
942
sound_exts, wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
943
dlg.SetFilterIndex(sound_extno);
944
int ret = ShowModal(&dlg);
945
sound_extno = dlg.GetFilterIndex();
946
sound_path = dlg.GetDirectory();
949
panel->StartSoundRecording(dlg.GetPath());
953
EVT_HANDLER_MASK(RecordSoundStopRecording, "Stop sound recording", CMDEN_SREC)
956
panel->StopSoundRecording();
960
EVT_HANDLER_MASK(RecordAVIStartRecording, "Start video recording...", CMDEN_NVREC)
963
static wxString vid_exts;
964
static int vid_extno;
965
static wxString vid_path;
967
if(!vid_exts.size()) {
971
for(fmt = NULL, extno = 0; (fmt = av_oformat_next(fmt)); ) {
974
if(fmt->video_codec == CODEC_ID_NONE)
976
vid_exts.append(wxString(fmt->long_name ? fmt->long_name : fmt->name, wxConvLibc));
977
vid_exts.append(_(" files ("));
978
wxString ext(fmt->extensions, wxConvLibc);
979
ext.Replace(wxT(","), wxT(";*."));
980
ext.insert(0, wxT("*."));
981
if(vid_extno < 0 && ext.find(wxT("*.avi")) != wxString::npos)
983
vid_exts.append(ext);
984
vid_exts.append(wxT(")|"));
985
vid_exts.append(ext);
986
vid_exts.append(wxT('|'));
989
vid_exts.append(wxALL_FILES);
993
if(!vid_path.size()) {
994
if(!gopts.recording_dir.size())
995
vid_path = panel->game_dir();
997
wxFileName sp(gopts.recording_dir, wxEmptyString);
999
vid_path = gopts.recording_dir;
1001
vid_path = panel->game_dir() + wxT('/') + gopts.recording_dir;
1003
wxFileName::Mkdir(vid_path, 0777, wxPATH_MKDIR_FULL);
1005
wxString def_name = panel->game_name();
1006
const wxChar *extoff = vid_exts.c_str();
1007
for(int i = 0; i < vid_extno; i++) {
1008
extoff = wxStrchr(extoff, wxT('|')) + 1;
1009
extoff = wxStrchr(extoff, wxT('|')) + 1;
1011
extoff = wxStrchr(extoff, wxT('|')) + 2; // skip *
1012
def_name += wxString(extoff, wxStrcspn(extoff, wxT(";|")));
1013
wxFileDialog dlg(this, _("Select output file"), vid_path, def_name,
1014
vid_exts, wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
1015
dlg.SetFilterIndex(vid_extno);
1016
int ret = ShowModal(&dlg);
1017
vid_extno = dlg.GetFilterIndex();
1018
vid_path = dlg.GetDirectory();
1021
panel->StartVidRecording(dlg.GetPath());
1025
EVT_HANDLER_MASK(RecordAVIStopRecording, "Stop video recording", CMDEN_VREC)
1028
panel->StopVidRecording();
1032
static wxString mov_path;
1034
EVT_HANDLER_MASK(RecordMovieStartRecording, "Start game recording...", CMDEN_NGREC)
1036
if(!mov_path.size()) {
1037
if(!gopts.recording_dir.size())
1038
mov_path = panel->game_dir();
1040
wxFileName sp(gopts.recording_dir, wxEmptyString);
1042
mov_path = gopts.recording_dir;
1044
mov_path = panel->game_dir() + wxT('/') + gopts.recording_dir;
1046
wxFileName::Mkdir(mov_path, 0777, wxPATH_MKDIR_FULL);
1048
wxString def_name = panel->game_name() + wxT(".vmv");
1049
wxFileDialog dlg(this, _("Select output file"), mov_path, def_name,
1050
_("VBA Movie files|*.vmv"), wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
1051
int ret = ShowModal(&dlg);
1052
mov_path = dlg.GetDirectory();
1055
systemStartGameRecording(dlg.GetPath());
1058
EVT_HANDLER_MASK(RecordMovieStopRecording, "Stop game recording", CMDEN_GREC)
1060
systemStopGameRecording();
1063
EVT_HANDLER_MASK(PlayMovieStartPlaying, "Start playing movie...", CMDEN_NGREC|CMDEN_NGPLAY)
1065
if(!mov_path.size()) {
1066
if(!gopts.recording_dir.size())
1067
mov_path = panel->game_dir();
1069
wxFileName sp(gopts.recording_dir, wxEmptyString);
1071
mov_path = gopts.recording_dir;
1073
mov_path = panel->game_dir() + wxT('/') + gopts.recording_dir;
1075
if(!wxFileName::DirExists(mov_path))
1076
mov_path = wxFileName::GetCwd();
1078
systemStopGamePlayback();
1079
wxString def_name = panel->game_name() + wxT(".vmv");
1080
wxFileDialog dlg(this, _("Select file"), mov_path, def_name,
1081
_("VBA Movie files|*.vmv"), wxFD_OPEN|wxFD_FILE_MUST_EXIST);
1082
int ret = ShowModal(&dlg);
1083
mov_path = dlg.GetDirectory();
1086
systemStartGamePlayback(dlg.GetPath());
1089
EVT_HANDLER_MASK(PlayMovieStopPlaying, "Stop playing movie", CMDEN_GPLAY)
1091
systemStopGamePlayback();
1095
EVT_HANDLER_MASK(wxID_CLOSE, "Close", CMDEN_GB|CMDEN_GBA)
1097
panel->UnloadGame();
1101
EVT_HANDLER(wxID_EXIT, "Exit")
1108
EVT_HANDLER(Pause, "Pause (toggle)")
1110
update_bcheck("Pause", paused);
1113
else if(!IsPaused())
1115
// undo next-frame's zeroing of frameskip
1116
int fs = panel->game_type() == IMAGE_GB ? gopts.gb_frameskip : gopts.gba_frameskip;
1118
systemFrameSkip = fs;
1122
EVT_HANDLER_MASK(EmulatorSpeedupToggle, "Turbo mode (toggle)", CMDEN_GB|CMDEN_GBA)
1124
update_bcheck("EmulatorSpeedupToggle", turbo);
1127
EVT_HANDLER_MASK(Reset, "Reset", CMDEN_GB|CMDEN_GBA)
1129
panel->emusys->emuReset();
1130
// systemScreenMessage("Reset");
1133
EVT_HANDLER(ToggleFullscreen, "Full screen (toggle)")
1135
panel->ShowFullScreen(!IsFullScreen());
1138
EVT_HANDLER(JoypadAutofireA, "Autofire A (toggle)")
1140
update_icheck1("JoypadAutofireA", autofire, KEYM_A);
1143
EVT_HANDLER(JoypadAutofireB, "Autofire B (toggle)")
1145
update_icheck1("JoypadAutofireB", autofire, KEYM_B);
1148
EVT_HANDLER(JoypadAutofireL, "Autofire L (toggle)")
1150
update_icheck1("JoypadAutofireL", autofire, KEYM_LEFT);
1153
EVT_HANDLER(JoypadAutofireR, "Autofire R (toggle)")
1155
update_icheck1("JoypadAutofireR", autofire, KEYM_RIGHT);
1159
EVT_HANDLER_MASK(LanLink, "Start LAN link", CMDEN_LINK_ANY)
1162
if(lanlink.connected) {
1163
// while we could deactivate the command when connected, it is more
1164
// user-friendly to display a message indidcating why
1165
wxLogError(_("LAN link is already active. Disable link mode to disconnect."));
1169
// see above comment
1170
wxLogError(_("RFU is currently only supported in local mode."));
1173
wxDialog *dlg = GetXRCDialog("NetLink");
1175
panel->SetFrameTitle();
1179
EVT_HANDLER_MASK(LoadGameRecent, "Load most recent save", CMDEN_SAVST)
1184
EVT_HANDLER(LoadGameAutoLoad, "Auto load most recent save (toggle)")
1186
update_bcheck("LoadGameAutoLoad", gopts.autoload_state);
1190
EVT_HANDLER_MASK(LoadGame01, "Load saved state 1", CMDEN_SAVST)
1192
panel->LoadState(1);
1195
EVT_HANDLER_MASK(LoadGame02, "Load saved state 2", CMDEN_SAVST)
1197
panel->LoadState(2);
1200
EVT_HANDLER_MASK(LoadGame03, "Load saved state 3", CMDEN_SAVST)
1202
panel->LoadState(3);
1205
EVT_HANDLER_MASK(LoadGame04, "Load saved state 4", CMDEN_SAVST)
1207
panel->LoadState(4);
1210
EVT_HANDLER_MASK(LoadGame05, "Load saved state 5", CMDEN_SAVST)
1212
panel->LoadState(5);
1215
EVT_HANDLER_MASK(LoadGame06, "Load saved state 6", CMDEN_SAVST)
1217
panel->LoadState(6);
1220
EVT_HANDLER_MASK(LoadGame07, "Load saved state 7", CMDEN_SAVST)
1222
panel->LoadState(7);
1225
EVT_HANDLER_MASK(LoadGame08, "Load saved state 8", CMDEN_SAVST)
1227
panel->LoadState(8);
1230
EVT_HANDLER_MASK(LoadGame09, "Load saved state 9", CMDEN_SAVST)
1232
panel->LoadState(9);
1235
EVT_HANDLER_MASK(LoadGame10, "Load saved state 10", CMDEN_SAVST)
1237
panel->LoadState(10);
1240
static wxString st_dir;
1242
EVT_HANDLER_MASK(Load, "Load state...", CMDEN_GB|CMDEN_GBA)
1245
st_dir = panel->state_dir();
1246
wxFileDialog dlg(this, _("Select state file"), st_dir, wxEmptyString,
1247
_("VisualBoyAdvance saved game files|*.sgm"), wxFD_OPEN|wxFD_FILE_MUST_EXIST);
1248
int ret = ShowModal(&dlg);
1249
st_dir = dlg.GetDirectory();
1252
panel->LoadState(dlg.GetPath());
1256
EVT_HANDLER(KeepSaves, "Do not load battery saves (toggle)")
1258
update_bcheck("KeepSaves", skipSaveGameBattery);
1263
EVT_HANDLER(KeepCheats, "Do not change cheat list (toggle)")
1265
update_bcheck("KeepCheats", skipSaveGameCheats);
1269
EVT_HANDLER_MASK(SaveGameOldest, "Save state to oldest slot", CMDEN_GB|CMDEN_GBA)
1274
EVT_HANDLER_MASK(SaveGame01, "Save state 1", CMDEN_GB|CMDEN_GBA)
1276
panel->SaveState(1);
1279
EVT_HANDLER_MASK(SaveGame02, "Save state 2", CMDEN_GB|CMDEN_GBA)
1281
panel->SaveState(2);
1284
EVT_HANDLER_MASK(SaveGame03, "Save state 3", CMDEN_GB|CMDEN_GBA)
1286
panel->SaveState(3);
1289
EVT_HANDLER_MASK(SaveGame04, "Save state 4", CMDEN_GB|CMDEN_GBA)
1291
panel->SaveState(4);
1294
EVT_HANDLER_MASK(SaveGame05, "Save state 5", CMDEN_GB|CMDEN_GBA)
1296
panel->SaveState(5);
1299
EVT_HANDLER_MASK(SaveGame06, "Save state 6", CMDEN_GB|CMDEN_GBA)
1301
panel->SaveState(6);
1304
EVT_HANDLER_MASK(SaveGame07, "Save state 7", CMDEN_GB|CMDEN_GBA)
1306
panel->SaveState(7);
1309
EVT_HANDLER_MASK(SaveGame08, "Save state 8", CMDEN_GB|CMDEN_GBA)
1311
panel->SaveState(8);
1314
EVT_HANDLER_MASK(SaveGame09, "Save state 9", CMDEN_GB|CMDEN_GBA)
1316
panel->SaveState(9);
1319
EVT_HANDLER_MASK(SaveGame10, "Save state 10", CMDEN_GB|CMDEN_GBA)
1321
panel->SaveState(10);
1324
EVT_HANDLER_MASK(Save, "Save state as...", CMDEN_GB|CMDEN_GBA)
1327
st_dir = panel->state_dir();
1328
wxFileDialog dlg(this, _("Select state file"), st_dir, wxEmptyString,
1329
_("VisualBoyAdvance saved game files|*.sgm"), wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
1330
int ret = ShowModal(&dlg);
1331
st_dir = dlg.GetDirectory();
1334
panel->SaveState(dlg.GetPath());
1337
static int state_slot = 0;
1340
EVT_HANDLER_MASK(LoadGameSlot, "Load current state slot", CMDEN_GB|CMDEN_GBA)
1342
panel->LoadState(state_slot + 1);
1346
EVT_HANDLER_MASK(SaveGameSlot, "Save current state slot", CMDEN_GB|CMDEN_GBA)
1348
panel->SaveState(state_slot + 1);
1352
EVT_HANDLER_MASK(IncrGameSlot, "Increase state slot number", CMDEN_GB|CMDEN_GBA)
1354
state_slot = (state_slot + 1) % 10;
1358
EVT_HANDLER_MASK(DecrGameSlot, "Decrease state slot number", CMDEN_GB|CMDEN_GBA)
1360
state_slot = (state_slot + 9) % 10;
1364
EVT_HANDLER_MASK(IncrGameSlotSave, "Increase state slot number and save", CMDEN_GB|CMDEN_GBA)
1366
state_slot = (state_slot + 1) % 10;
1367
panel->SaveState(state_slot + 1);
1370
EVT_HANDLER_MASK(Rewind, "Rewind", CMDEN_REWIND)
1372
MainFrame *mf = wxGetApp().frame;
1373
GameArea *panel = mf->GetPanel();
1374
int rew_st = (panel->next_rewind_state + NUM_REWINDS - 1) % NUM_REWINDS;
1375
// if within 5 seconds of last one, and > 1 state, delete last state & move back
1376
// FIXME: 5 should actually be user-configurable
1377
// maybe instead of 5, 10% of rewind_interval
1378
if(panel->num_rewind_states > 1 &&
1379
(gopts.rewind_interval <= 5 ||
1380
panel->rewind_time / 6 > gopts.rewind_interval - 5)) {
1381
--panel->num_rewind_states;
1382
panel->next_rewind_state = rew_st;
1383
if(gopts.rewind_interval > 5)
1384
rew_st = (rew_st + NUM_REWINDS - 1) % NUM_REWINDS;
1386
panel->emusys->emuReadMemState(&panel->rewind_mem[rew_st * REWIND_SIZE],
1388
InterframeCleanup();
1389
// FIXME: if(paused) blank screen
1390
panel->do_rewind = false;
1391
panel->rewind_time = gopts.rewind_interval * 6;
1392
// systemScreenMessage(_("Rewinded"));
1395
EVT_HANDLER_MASK(CheatsList, "List cheats...", CMDEN_GB|CMDEN_GBA)
1397
wxDialog *dlg = GetXRCDialog("CheatList");
1401
EVT_HANDLER_MASK(CheatsSearch, "Create cheat...", CMDEN_GB|CMDEN_GBA)
1403
wxDialog *dlg = GetXRCDialog("CheatCreate");
1408
EVT_HANDLER(CheatsAutoSaveLoad, "Auto save/load cheats (toggle)")
1410
update_bcheck("CheatsAutoSaveLoad", gopts.autoload_cheats);
1414
// was CheatsDisable
1415
// changed for convenience to match internal variable functionality
1416
EVT_HANDLER(CheatsEnable, "Enable cheats (toggle)")
1418
update_bcheck("CheatsEnable", cheatsEnabled);
1424
EVT_HANDLER_MASK(VideoLayersBG0, "Video layer BG0 (toggle)", CMDEN_GB|CMDEN_GBA)
1426
update_icheck1("VideoLayersBG0", layerSettings, (1<<8));
1427
layerEnable = DISPCNT & layerSettings;
1428
CPUUpdateRenderBuffers(false);
1431
EVT_HANDLER_MASK(VideoLayersBG1, "Video layer BG1 (toggle)", CMDEN_GB|CMDEN_GBA)
1433
update_icheck1("VideoLayersBG1", layerSettings, (1<<9));
1434
layerEnable = DISPCNT & layerSettings;
1435
CPUUpdateRenderBuffers(false);
1438
EVT_HANDLER_MASK(VideoLayersBG2, "Video layer BG2 (toggle)", CMDEN_GB|CMDEN_GBA)
1440
update_icheck1("VideoLayersBG2", layerSettings, (1<<10));
1441
layerEnable = DISPCNT & layerSettings;
1442
CPUUpdateRenderBuffers(false);
1445
EVT_HANDLER_MASK(VideoLayersBG3, "Video layer BG3 (toggle)", CMDEN_GB|CMDEN_GBA)
1447
update_icheck1("VideoLayersBG3", layerSettings, (1<<11));
1448
layerEnable = DISPCNT & layerSettings;
1449
CPUUpdateRenderBuffers(false);
1452
EVT_HANDLER_MASK(VideoLayersOBJ, "Video layer OBJ (toggle)", CMDEN_GB|CMDEN_GBA)
1454
update_icheck1("VideoLayersOBJ", layerSettings, (1<<12));
1455
layerEnable = DISPCNT & layerSettings;
1456
CPUUpdateRenderBuffers(false);
1459
EVT_HANDLER_MASK(VideoLayersWIN0, "Video layer WIN0 (toggle)", CMDEN_GB|CMDEN_GBA)
1461
update_icheck1("VideoLayersWIN0", layerSettings, (1<<13));
1462
layerEnable = DISPCNT & layerSettings;
1463
CPUUpdateRenderBuffers(false);
1466
EVT_HANDLER_MASK(VideoLayersWIN1, "Video layer WIN1 (toggle)", CMDEN_GB|CMDEN_GBA)
1468
update_icheck1("VideoLayersWIN1", layerSettings, (1<<14));
1469
layerEnable = DISPCNT & layerSettings;
1470
CPUUpdateRenderBuffers(false);
1473
EVT_HANDLER_MASK(VideoLayersOBJWIN, "Video layer OBJWIN (toggle)", CMDEN_GB|CMDEN_GBA)
1475
update_icheck1("VideoLayersOBJWIN", layerSettings, (1<<15));
1476
layerEnable = DISPCNT & layerSettings;
1477
CPUUpdateRenderBuffers(false);
1481
EVT_HANDLER_MASK(VideoLayersReset, "Show all video layers", CMDEN_GB|CMDEN_GBA)
1483
#define set_vl(s) do { \
1484
int id = XRCID(s); \
1485
for(int i = 0; i < checkable_mi.size(); i++) \
1486
if(checkable_mi[i].cmd == id) { \
1487
checkable_mi[i].mi->Check(true); \
1491
layerSettings = 0x7f00;
1492
layerEnable = DISPCNT & layerSettings;
1493
set_vl("VideoLayersBG0");
1494
set_vl("VideoLayersBG1");
1495
set_vl("VideoLayersBG2");
1496
set_vl("VideoLayersBG3");
1497
set_vl("VideoLayersOBJ");
1498
set_vl("VideoLayersWIN0");
1499
set_vl("VideoLayersWIN1");
1500
set_vl("VideoLayersOBJWIN");
1501
CPUUpdateRenderBuffers(false);
1504
EVT_HANDLER_MASK(SoundChannel1, "Sound Channel 1 (toggle)", CMDEN_GB|CMDEN_GBA)
1506
update_icheck1("SoundChannel1", gopts.sound_en, (1<<0));
1507
soundSetEnable(gopts.sound_en);
1511
EVT_HANDLER_MASK(SoundChannel2, "Sound Channel 2 (toggle)", CMDEN_GB|CMDEN_GBA)
1513
update_icheck1("SoundChannel2", gopts.sound_en, (1<<1));
1514
soundSetEnable(gopts.sound_en);
1518
EVT_HANDLER_MASK(SoundChannel3, "Sound Channel 3 (toggle)", CMDEN_GB|CMDEN_GBA)
1520
update_icheck1("SoundChannel3", gopts.sound_en, (1<<2));
1521
soundSetEnable(gopts.sound_en);
1525
EVT_HANDLER_MASK(SoundChannel4, "Sound Channel 4 (toggle)", CMDEN_GB|CMDEN_GBA)
1527
update_icheck1("SoundChannel4", gopts.sound_en, (1<<3));
1528
soundSetEnable(gopts.sound_en);
1532
EVT_HANDLER_MASK(DirectSoundA, "Direct Sound A (toggle)", CMDEN_GBA)
1534
update_icheck1("DirectSoundA", gopts.sound_en, (1<<8));
1535
soundSetEnable(gopts.sound_en);
1539
EVT_HANDLER_MASK(DirectSoundB, "Direct Sound B (toggle)", CMDEN_GBA)
1541
update_icheck1("DirectSoundB", gopts.sound_en, (1<<9));
1542
soundSetEnable(gopts.sound_en);
1546
EVT_HANDLER(ToggleSound, "Enable/disable all sound channels")
1548
bool en = gopts.sound_en == 0;
1549
gopts.sound_en = en ? 0x30f : 0;
1550
update_check("SoundChannel1", en);
1551
update_check("SoundChannel2", en);
1552
update_check("SoundChannel3", en);
1553
update_check("SoundChannel4", en);
1554
update_check("DirectSoundA", en);
1555
update_check("DirectSoundB", en);
1556
soundSetEnable(gopts.sound_en);
1558
systemScreenMessage(en ? _("Sound enabled") : _("Sound disabled"));
1561
EVT_HANDLER(IncreaseVolume, "Increase volume")
1563
gopts.sound_vol += 5;
1564
if(gopts.sound_vol > 200)
1565
gopts.sound_vol = 200;
1567
soundSetVolume((float)gopts.sound_vol / 100.0);
1569
msg.Printf(_("Volume: %d%%"), gopts.sound_vol);
1570
systemScreenMessage(msg);
1573
EVT_HANDLER(DecreaseVolume, "Decrease volume")
1575
gopts.sound_vol -= 5;
1576
if(gopts.sound_vol < 0)
1577
gopts.sound_vol = 0;
1579
soundSetVolume((float)gopts.sound_vol / 100.0);
1581
msg.Printf(_("Volume: %d%%"), gopts.sound_vol);
1582
systemScreenMessage(msg);
1585
EVT_HANDLER_MASK(NextFrame, "Next Frame", CMDEN_GB|CMDEN_GBA)
1587
update_check("Pause", true);
1592
systemFrameSkip = 0;
1595
EVT_HANDLER_MASK(Disassemble, "Disassemble...", CMDEN_GB|CMDEN_GBA)
1600
// only GBA generates the log messages this handles
1601
// you could view them even w/o a gba cart, but why?
1602
EVT_HANDLER_MASK(Logging, "Logging...", CMDEN_GBA)
1604
wxDialog *dlg = wxGetApp().frame->logdlg;
1609
EVT_HANDLER_MASK(IOViewer, "I/O Viewer...", CMDEN_GBA)
1614
EVT_HANDLER_MASK(MapViewer, "Map Viewer...", CMDEN_GB|CMDEN_GBA)
1619
EVT_HANDLER_MASK(MemoryViewer, "Memory Viewer...", CMDEN_GB|CMDEN_GBA)
1624
EVT_HANDLER_MASK(OAMViewer, "OAM Viewer...", CMDEN_GB|CMDEN_GBA)
1629
EVT_HANDLER_MASK(PaletteViewer, "Palette Viewer...", CMDEN_GB|CMDEN_GBA)
1634
EVT_HANDLER_MASK(TileViewer, "Tile Viewer...", CMDEN_GB|CMDEN_GBA)
1639
extern int remotePort;
1641
EVT_HANDLER_MASK(DebugGDB, "Wait for GDB connection...", CMDEN_NGDB_GBA)
1644
int port = wxGetNumberFromUser(
1648
_("Set to 0 for pseudo tty"),
1650
_("Port to wait for connection:"),
1651
_("GDB Connection"), remotePort,
1666
msg.Printf(_("Waiting for connection at %s"), debugGetSlavePty().c_str());
1670
if(!debugStartListen(port))
1672
msg.Printf(_("Waiting for connection on port %d"), port);
1674
wxProgressDialog dlg(_("Waiting for GDB..."), msg, 100, this,
1675
wxPD_APP_MODAL|wxPD_CAN_ABORT|wxPD_ELAPSED_TIME);
1676
bool connected = false;
1677
while(dlg.Pulse()) {
1680
connected = debugWaitPty();
1683
connected = debugWaitSocket();
1686
// sleep a bit more in case of infinite loop
1693
dbgMain = remoteStubMain;
1694
dbgSignal = remoteStubSignal;
1695
dbgOutput = remoteOutput;
1696
cmd_enable &= ~(CMDEN_NGDB_ANY|CMDEN_NGDB_GBA);
1697
cmd_enable |= CMDEN_GDB;
1702
EVT_HANDLER_MASK(DebugGDBLoad, "Load and wait for GDB...", CMDEN_NGDB_ANY)
1707
if(wxGetApp().pending_load.empty())
1709
panel->UnloadGame();
1713
EVT_HANDLER_MASK(DebugGDBBreak, "Break into GDB", CMDEN_GDB)
1725
EVT_HANDLER_MASK(DebugGDBDisconnect, "Disconnect GDB", CMDEN_GDB)
1732
cmd_enable &= ~CMDEN_GDB;
1733
cmd_enable |= CMDEN_NGDB_GBA|CMDEN_NGDB_ANY;
1739
EVT_HANDLER(GeneralConfigure, "General options...")
1741
int rew = gopts.rewind_interval;
1742
wxDialog *dlg = GetXRCDialog("GeneralConfig");
1743
if(ShowModal(dlg) == wxID_OK)
1745
if(panel->game_type() != IMAGE_UNKNOWN)
1746
soundSetThrottle(gopts.throttle);
1747
if(rew != gopts.rewind_interval) {
1748
if(!gopts.rewind_interval) {
1749
if(panel->num_rewind_states) {
1750
cmd_enable &= ~CMDEN_REWIND;
1753
panel->num_rewind_states = 0;
1754
panel->do_rewind = false;
1756
if(!panel->num_rewind_states)
1757
panel->do_rewind = true;
1758
panel->rewind_time = gopts.rewind_interval * 6;
1763
EVT_HANDLER(GameBoyConfigure, "Game Boy options...")
1765
wxDialog *dlg = GetXRCDialog("GameBoyConfig");
1766
wxChoice *c = XRCCTRL(*dlg, "Borders", wxChoice);
1767
bool borderon = gbBorderOn;
1768
bool printeron = gopts.gbprint;
1769
if(!gbBorderOn && !gbBorderAutomatic)
1775
if(ShowModal(dlg) != wxID_OK)
1777
switch(c->GetSelection()) {
1779
gbBorderOn = gbBorderAutomatic = false;
1786
gbBorderAutomatic = true;
1789
// this value might have been overwritten by FrameSkip
1790
if(XRCCTRL(*dlg, "FrameSkipAuto", wxCheckBox)->GetValue())
1791
gopts.gb_frameskip = -1;
1793
if(panel->game_type() == IMAGE_GB) {
1794
if(borderon != gbBorderOn) {
1797
gbSgbRenderBorder();
1801
// autoskip will self-adjust
1802
if(gopts.gb_frameskip >= 0)
1803
systemFrameSkip = gopts.gb_frameskip;
1804
// don't want to have to reset to change colors
1805
memcpy(gbPalette, &systemGbPalette[gbPaletteOption * 8], 8 * sizeof(systemGbPalette[0]));
1807
if(printeron != gopts.gbprint) {
1809
gbSerialFunction = gbPrinterSend;
1811
gbSerialFunction = NULL;
1815
EVT_HANDLER(GameBoyAdvanceConfigure, "Game Boy Advance options...")
1817
wxDialog *dlg = GetXRCDialog("GameBoyAdvanceConfig");
1818
wxTextCtrl *ovcmt = XRCCTRL(*dlg, "Comment", wxTextCtrl);
1820
wxChoice *ovrtc = XRCCTRL(*dlg, "OvRTC", wxChoice),
1821
*ovst = XRCCTRL(*dlg, "OvSaveType", wxChoice),
1822
*ovfs = XRCCTRL(*dlg, "OvFlashSize", wxChoice),
1823
*ovmir = XRCCTRL(*dlg, "OvMirroring", wxChoice);
1824
if(panel->game_type() == IMAGE_GBA) {
1825
wxString s = wxString((const char *)&rom[0xac], wxConvLibc, 4);
1826
XRCCTRL(*dlg, "GameCode", wxControl)->SetLabel(s);
1827
cmt = wxString((const char *)&rom[0xa0], wxConvLibc, 12);
1828
wxFileConfig *cfg = wxGetApp().overrides;
1829
if(cfg->HasGroup(s)) {
1831
cmt = cfg->Read(wxT("comment"), cmt);
1832
ovcmt->SetValue(cmt);
1833
ovrtc->SetSelection(cfg->Read(wxT("rtcEnabled"), -1) + 1);
1834
ovst->SetSelection(cfg->Read(wxT("saveType"), -1) + 1);
1835
ovfs->SetSelection((cfg->Read(wxT("flashSize"), -1) >> 17) + 1);
1836
ovmir->SetSelection(cfg->Read(wxT("mirroringEnabled"), -1) + 1);
1837
cfg->SetPath(wxT("/"));
1839
ovcmt->SetValue(cmt);
1840
ovrtc->SetSelection(0);
1841
ovst->SetSelection(0);
1842
ovfs->SetSelection(0);
1843
ovmir->SetSelection(0);
1846
XRCCTRL(*dlg, "GameCode", wxControl)->SetLabel(wxEmptyString);
1847
ovcmt->SetValue(wxEmptyString);
1848
ovrtc->SetSelection(0);
1849
ovst->SetSelection(0);
1850
ovfs->SetSelection(0);
1851
ovmir->SetSelection(0);
1853
if(ShowModal(dlg) != wxID_OK)
1855
// this value might have been overwritten by FrameSkip
1856
if(XRCCTRL(*dlg, "FrameSkipAuto", wxCheckBox)->GetValue())
1857
gopts.gba_frameskip = -1;
1859
if(panel->game_type() == IMAGE_GBA) {
1860
// autoskip will self-adjust
1861
if(gopts.gba_frameskip >= 0)
1862
systemFrameSkip = gopts.gba_frameskip;
1863
agbPrintEnable(gopts.agbprint);
1864
#if 0 // disabled in win32 version for undocumented "problems"
1865
if(gopts.skip_intro)
1866
*((u32 *)rom) = 0xea00002e;
1868
*((u32 *)rom) = /* original value */;
1870
wxString s = wxString((const char *)&rom[0xac], wxConvLibc, 4);
1871
wxFileConfig *cfg = wxGetApp().overrides;
1873
if(cfg->HasGroup(s)) {
1876
ovcmt->GetValue() != cmt ||
1877
ovrtc->GetSelection() != cfg->Read(wxT("rtcEnabled"), -1) + 1 ||
1878
ovst->GetSelection() != cfg->Read(wxT("saveType"), -1) + 1 ||
1879
ovfs->GetSelection() != (cfg->Read(wxT("flashSize"), -1) >> 17) + 1 ||
1880
ovmir->GetSelection() != cfg->Read(wxT("mirroringEnabled"), -1) + 1;
1881
cfg->SetPath(wxT("/"));
1883
chg = ovrtc->GetSelection() != 0 || ovst->GetSelection() != 0 ||
1884
ovfs->GetSelection() != 0 || ovmir->GetSelection() != 0;
1887
wxFileName fn(wxStandardPaths::Get().GetUserDataDir(), wxT("vba-over.ini"));
1888
if(fn.FileExists()) {
1889
wxFileInputStream fis(fn.GetFullPath());
1890
wxStringOutputStream sos(&vba_over);
1893
if(cfg->HasGroup(s)) {
1895
if(cfg->Read(wxT("path"), wxEmptyString) == fn.GetPath()) {
1896
// EOL can be either \n (unix), \r\n (dos), or \r (old mac)
1897
wxString res(wxT("(^|[\n\r])" // a new line
1898
"(" // capture group as \2
1899
"(#[^\n\r]*(\r?\n|\r))?" // an optional comment line
1900
"\\[")); // the group header
1903
"([^[#]" // non-comment non-group-start chars
1904
"|[^\r\n \t][ \t]*[[#]" // or comment/grp start chars in middle of line
1905
"|#[^\n\r]*(\r?\n|\r)[^[]" // or comments not followed by grp start
1908
// no need to try to describe what's next
1909
// as the regex should maximize match size
1912
// there may be more than one group if it was hand-edited
1913
// so remove them all
1914
// could use re.Replace(), but this is more reliable
1915
while(re.Matches(vba_over)) {
1917
re.GetMatch(&beg, &end, 2);
1918
vba_over.erase(beg, end - beg);
1921
cfg->SetPath(wxT("/"));
1922
cfg->DeleteGroup(s);
1925
cfg->Write(wxT("path"), fn.GetPath());
1926
cfg->Write(wxT("comment"), ovcmt->GetValue());
1927
vba_over.append(wxT("# "));
1928
vba_over.append(ovcmt->GetValue());
1929
vba_over.append(wxTextFile::GetEOL());
1930
vba_over.append(wxT('['));
1932
vba_over.append(wxT(']'));
1933
vba_over.append(wxTextFile::GetEOL());
1935
#define appendval(n) do { \
1936
vba_over.append(wxT(n)); \
1937
vba_over.append(wxT('=')); \
1938
vba_over.append((wxChar)(wxT('0') + sel - 1)); \
1939
vba_over.append(wxTextFile::GetEOL()); \
1940
cfg->Write(wxT(n), sel - 1); \
1942
if((sel = ovrtc->GetSelection()) > 0)
1943
appendval("rtcEnabled");
1944
if((sel = ovst->GetSelection()) > 0)
1945
appendval("saveType");
1946
if((sel = ovfs->GetSelection()) > 0) {
1947
vba_over.append(wxT("flashSize="));
1948
vba_over.append(sel == 1 ? wxT("65536") : wxT("131072"));
1949
vba_over.append(wxTextFile::GetEOL());
1950
cfg->Write(wxT("flashSize"), 0x10000 << (sel - 1));
1952
if((sel = ovmir->GetSelection()) > 0)
1953
appendval("mirroringEnabled");
1954
cfg->SetPath(wxT("/"));
1955
vba_over.append(wxTextFile::GetEOL());
1956
fn.Mkdir(0777, wxPATH_MKDIR_FULL);
1957
wxTempFileOutputStream fos(fn.GetFullPath());
1958
fos.Write(vba_over.mb_str(), vba_over.size());
1964
EVT_HANDLER_MASK(DisplayConfigure, "Display options...", CMDEN_NREC_ANY)
1966
bool fs = gopts.fullscreen;
1967
int max_scale = gopts.max_scale;
1968
int renderer = gopts.render_method;
1969
bool bilinear = gopts.bilinear;
1970
int filt = gopts.filter;
1971
wxString fp = gopts.filter_plugin;
1972
wxVideoMode dm = gopts.fs_mode;
1973
bool vsync = gopts.vsync;
1975
if(gopts.max_threads == 1)
1976
gopts.max_threads = 0;
1978
gopts.max_threads = wxThread::GetCPUCount();
1979
if(gopts.max_threads > 8)
1980
gopts.max_threads = 8;
1982
wxDialog *dlg = GetXRCDialog("DisplayConfig");
1983
if(ShowModal(dlg) != wxID_OK)
1985
if(!gopts.max_threads)
1986
gopts.max_threads = 1;
1988
if(max_scale != gopts.max_scale && panel->panel) {
1989
if(gopts.max_scale) {
1990
panel->panel->GetWindow()->SetMaxSize(wxDefaultSize);
1991
if(fs == gopts.fullscreen && (!panel->IsFullScreen() ||
1992
dm == gopts.fs_mode))
1994
// else the window will be resized anyway
1995
else if(fs == gopts.fullscreen && (!panel->IsFullScreen() ||
1996
dm == gopts.fs_mode)) {
1997
// can't compute max size here, so just destroy & rebuild
1999
panel->panel->Delete();
2000
panel->panel = NULL;
2004
if(fs != gopts.fullscreen)
2005
panel->ShowFullScreen(gopts.fullscreen);
2006
else if(panel->IsFullScreen() && dm != gopts.fs_mode) {
2007
// maybe not the best way to do this..
2008
panel->ShowFullScreen(false);
2009
panel->ShowFullScreen(true);
2012
// change in renderer obviously requires restart
2013
(renderer != gopts.render_method ||
2014
// change in bilinear filter requires restart only for 3d renderers
2015
// but restart for all anyway
2016
bilinear != gopts.bilinear ||
2017
// change in scale requires buffer resizing
2018
builtin_ff_scale(filt) != builtin_ff_scale(gopts.filter) ||
2019
// plugin is only loaded on init
2020
(filt == FF_PLUGIN && fp != gopts.filter_plugin) ||
2021
// ifb doesn't support 24-bit
2022
(gopts.ifb != IFB_NONE && systemColorDepth == 24) ||
2023
// standard prefers 24-bit
2024
(gopts.ifb == IFB_NONE && gopts.filter == FF_NONE &&
2025
systemColorDepth == 32 && gopts.render_method == 0) ||
2026
// vsync is only set in init
2027
vsync != gopts.vsync)) {
2028
panel->panel->Delete();
2029
panel->panel = NULL;
2033
EVT_HANDLER_MASK(ChangeFilter, "Change Pixel Filter", CMDEN_NREC_ANY)
2035
int filt = gopts.filter;
2036
if(filt == FF_PLUGIN ||
2037
++gopts.filter == FF_PLUGIN && gopts.filter_plugin.empty())
2041
builtin_ff_scale(filt) != builtin_ff_scale(gopts.filter)) {
2042
panel->panel->Delete();
2043
panel->panel = NULL;
2047
EVT_HANDLER_MASK(ChangeIFB, "Change Interframe Blending", CMDEN_NREC_ANY)
2049
gopts.ifb = (gopts.ifb + 1) % 3;
2052
// ifb doesn't support 24-bit
2053
(gopts.ifb != IFB_NONE && systemColorDepth == 24) ||
2054
// standard prefers 24-bit
2055
(gopts.ifb == IFB_NONE && gopts.filter == FF_NONE &&
2056
systemColorDepth == 32 && gopts.render_method == 0)) {
2057
panel->panel->Delete();
2058
panel->panel = NULL;
2062
EVT_HANDLER_MASK(SoundConfigure, "Sound options...", CMDEN_NREC_ANY)
2064
int oqual = gopts.sound_qual, oapi = gopts.audio_api;
2065
bool oupmix = gopts.upmix, ohw = gopts.dsound_hw_accel;
2066
wxString odev = gopts.audio_dev;
2067
wxDialog *dlg = GetXRCDialog("SoundConfig");
2068
if(ShowModal(dlg) != wxID_OK)
2071
switch(panel->game_type()) {
2075
gb_effects_config.echo = (float)gopts.gb_echo / 100.0;
2076
gb_effects_config.stereo = (float)gopts.gb_stereo / 100.0;
2077
// note that setting declick may reset gb sound engine
2078
gbSoundSetDeclicking(gopts.gb_declick);
2079
gbSoundSetSampleRate(!gopts.sound_qual ? 48000 :
2080
44100 / (1 << (gopts.sound_qual - 1)));
2083
soundSetSampleRate(!gopts.sound_qual ? 48000 :
2084
44100 / (1 << (gopts.sound_qual - 1)));
2087
// changing sample rate causes driver reload, so no explicit reload needed
2088
if(oqual == gopts.sound_qual &&
2089
// otherwise reload if API changes
2090
(oapi != gopts.audio_api || odev != gopts.audio_dev ||
2091
// or init-only options
2092
(oapi == AUD_XAUDIO2 && oupmix != gopts.upmix) ||
2093
(oapi == AUD_DIRECTSOUND && ohw != gopts.dsound_hw_accel))) {
2097
soundSetVolume((float)gopts.sound_vol / 100.0);
2100
EVT_HANDLER(EmulatorDirectories, "Directories...")
2102
wxDialog *dlg = GetXRCDialog("DirectoriesConfig");
2103
if(ShowModal(dlg) == wxID_OK)
2107
EVT_HANDLER(JoypadConfigure, "Joypad options...")
2109
wxDialog *dlg = GetXRCDialog("JoypadConfig");
2112
if(ShowModal(dlg) == wxID_OK)
2118
EVT_HANDLER(LinkConfigure, "Link options...")
2121
bool jb = gba_joybus_enabled;
2122
wxString jh = gopts.joybus_host;
2123
wxDialog *dlg = GetXRCDialog("LinkConfig");
2124
if(ShowModal(dlg) != wxID_OK)
2127
if(jb != gba_joybus_enabled) {
2128
if(gba_joybus_enabled)
2132
} else if(jh != gopts.joybus_host) {
2133
joybusHostAddr = std::string(gopts.joybus_host.mb_str());
2136
if(gba_link_enabled != did_link_init) {
2137
if(gba_link_enabled) {
2138
if((did_link_init = InitLink()))
2139
cmd_enable |= CMDEN_LINK_ANY;
2141
did_link_init = false;
2143
lanlink.active = false;
2144
cmd_enable &= ~CMDEN_LINK_ANY;
2151
EVT_HANDLER(Customize, "Customize UI...")
2153
wxDialog *dlg = GetXRCDialog("AccelConfig");
2154
if(ShowModal(dlg) == wxID_OK)
2158
EVT_HANDLER(BugReport, "Report bugs...")
2160
wxLaunchDefaultBrowser(wxT("http://sourceforge.net/tracker/?group_id=212795&atid=1023154"));
2163
EVT_HANDLER(FAQ, "VBA-M support forum")
2165
wxLaunchDefaultBrowser(wxT("http://vba-m.com/forum/"));
2169
EVT_HANDLER(wxID_ABOUT, "About...")
2171
wxAboutDialogInfo ai;
2172
ai.SetName(wxT("VisualBoyAdvance-M"));
2173
ai.SetVersion(wxT(VERSION));
2174
// setting website, icon, license uses custom aboutbox on win32 & macosx
2175
// but at least win32 standard about is nothing special
2176
ai.SetWebSite(wxT("http://www.vba-m.com/"));
2177
ai.SetIcon(GetIcon());
2178
ai.SetDescription(_("Nintendo GameBoy (+Color+Advance) emulator."));
2179
ai.SetCopyright(_("Copyright (C) 1999-2003 Forgotten\nCopyright (C) 2004-2006 VBA development team\nCopyright (C) 2007-2011 VBA-M development team"));
2180
ai.SetLicense(_("This program is free software: you can redistribute it and/or modify\n"
2181
"it under the terms of the GNU General Public License as published by\n"
2182
"the Free Software Foundation, either version 2 of the License, or\n"
2183
"(at your option) any later version.\n\n"
2184
"This program is distributed in the hope that it will be useful,\n"
2185
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2186
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
2187
"GNU General Public License for more details.\n\n"
2188
"You should have received a copy of the GNU General Public License\n"
2189
"along with this program. If not, see http://www.gnu.org/licenses ."));
2191
ai.AddDeveloper(wxT("Forgotten"));
2192
ai.AddDeveloper(wxT("kxu"));
2193
ai.AddDeveloper(wxT("Pokemonhacker"));
2194
ai.AddDeveloper(wxT("Spacy51"));
2195
ai.AddDeveloper(wxT("mudlord"));
2196
ai.AddDeveloper(wxT("Nach"));
2197
ai.AddDeveloper(wxT("jbo_85"));
2198
ai.AddDeveloper(wxT("bgK"));
2199
ai.AddArtist(wxT("Matteo Drera"));
2200
ai.AddArtist(wxT("Jakub Steiner"));
2201
ai.AddArtist(wxT("Jones Lee"));
2203
ai.AddDeveloper(wxT("Jonas Quinn"));
2204
ai.AddDeveloper(wxT("DJRobX"));
2205
ai.AddDeveloper(wxT("Spacy"));
2206
ai.AddDeveloper(wxT("Squall Leonhart"));
2208
ai.AddDeveloper(wxT("Thomas J. Moore"));
2209
// from win32 "thanks"
2210
ai.AddDeveloper(wxT("blargg"));
2211
ai.AddDeveloper(wxT("Costis"));
2212
ai.AddDeveloper(wxT("chrono"));
2213
ai.AddDeveloper(wxT("xKiv"));
2214
ai.AddDeveloper(wxT("Orig. VBA team"));
2219
// Dummy for disabling system key bindings
2220
EVT_HANDLER_MASK(NOOP, "Do nothing", CMDEN_NEVER)
2224
// The following have been moved to dialogs
2225
// I will not implement as command unless there is great demand
2227
//EVT_HANDLER(CheatsLoad, "Load Cheats...")
2228
//EVT_HANDLER(CheatsSave, "Save Cheats...")
2230
//EVT_HANDLER(EmulatorRewindInterval, "EmulatorRewindInterval")
2231
//EVT_HANDLER(EmulatorAutoApplyPatchFiles, "EmulatorAutoApplyPatchFiles")
2232
//EVT_HANDLER(ThrottleNone, "ThrottleNone")
2233
//EVT_HANDLER(Throttle025%, "Throttle025%")
2234
//EVT_HANDLER(Throttle050%, "Throttle050%")
2235
//EVT_HANDLER(Throttle100%, "Throttle100%")
2236
//EVT_HANDLER(Throttle150%, "Throttle150%")
2237
//EVT_HANDLER(Throttle200%, "Throttle200%")
2238
//EVT_HANDLER(ThrottleOther, "ThrottleOther")
2239
//GameBoyConfigure/GameBoyAdvanceConfigure
2240
//EVT_HANDLER(FrameSkip0, "FrameSkip0")
2241
//EVT_HANDLER(FrameSkip1, "FrameSkip1")
2242
//EVT_HANDLER(FrameSkip2, "FrameSkip2")
2243
//EVT_HANDLER(FrameSkip3, "FrameSkip3")
2244
//EVT_HANDLER(FrameSkip4, "FrameSkip4")
2245
//EVT_HANDLER(FrameSkip5, "FrameSkip5")
2246
//EVT_HANDLER(FrameSkip6, "FrameSkip6")
2247
//EVT_HANDLER(FrameSkip7, "FrameSkip7")
2248
//EVT_HANDLER(FrameSkip8, "FrameSkip8")
2249
//EVT_HANDLER(FrameSkip9, "FrameSkip9")
2251
//EVT_HANDLER(GameboyBorder, "GameboyBorder")
2252
//EVT_HANDLER(GameboyBorderAutomatic, "GameboyBorderAutomatic")
2253
//EVT_HANDLER(GameboyColors, "GameboyColors")
2254
//GameBoyAdvanceConfigure
2255
//EVT_HANDLER(EmulatorAGBPrint, "EmulatorAGBPrint")
2256
//EVT_HANDLER(EmulatorSaveAuto, "EmulatorSaveAuto")
2257
//EVT_HANDLER(EmulatorSaveEEPROM, "EmulatorSaveEEPROM")
2258
//EVT_HANDLER(EmulatorSaveSRAM, "EmulatorSaveSRAM")
2259
//EVT_HANDLER(EmulatorSaveFLASH, "EmulatorSaveFLASH")
2260
//EVT_HANDLER(EmulatorSaveEEPROMSensor, "EmulatorSaveEEPROMSensor")
2261
//EVT_HANDLER(EmulatorSaveFlash64K, "EmulatorSaveFlash64K")
2262
//EVT_HANDLER(EmulatorSaveFlash128K, "EmulatorSaveFlash128K")
2263
//EVT_HANDLER(EmulatorSaveDetectNow, "EmulatorSaveDetectNow")
2264
//EVT_HANDLER(EmulatorRTC, "EmulatorRTC")
2266
//EVT_HANDLER(EmulatorShowSpeedNone, "EmulatorShowSpeedNone")
2267
//EVT_HANDLER(EmulatorShowSpeedPercentage, "EmulatorShowSpeedPercentage")
2268
//EVT_HANDLER(EmulatorShowSpeedDetailed, "EmulatorShowSpeedDetailed")
2269
//EVT_HANDLER(EmulatorShowSpeedTransparent, "EmulatorShowSpeedTransparent")
2270
//EVT_HANDLER(VideoX1, "VideoX1")
2271
//EVT_HANDLER(VideoX2, "VideoX2")
2272
//EVT_HANDLER(VideoX3, "VideoX3")
2273
//EVT_HANDLER(VideoX4, "VideoX4")
2274
//EVT_HANDLER(VideoX5, "VideoX5")
2275
//EVT_HANDLER(VideoX6, "VideoX6")
2276
//EVT_HANDLER(Video320x240, "Video320x240")
2277
//EVT_HANDLER(Video640x480, "Video640x480")
2278
//EVT_HANDLER(Video800x600, "Video800x600")
2279
//EVT_HANDLER(VideoFullscreen, "VideoFullscreen")
2280
//EVT_HANDLER(VideoFullscreenMaxScale, "VideoFullscreenMaxScale")
2281
//EVT_HANDLER(VideoRenderDDRAW, "VideoRenderDDRAW")
2282
//EVT_HANDLER(VideoRenderD3D, "VideoRenderD3D")
2283
//EVT_HANDLER(VideoRenderOGL, "VideoRenderOGL")
2284
//EVT_HANDLER(VideoVsync, "VideoVsync")
2285
//EVT_HANDLER(FilterNormal, "FilterNormal")
2286
//EVT_HANDLER(FilterTVMode, "FilterTVMode")
2287
//EVT_HANDLER(Filter2xSaI, "Filter2xSaI")
2288
//EVT_HANDLER(FilterSuper2xSaI, "FilterSuper2xSaI")
2289
//EVT_HANDLER(FilterSuperEagle, "FilterSuperEagle")
2290
//EVT_HANDLER(FilterPixelate, "FilterPixelate")
2291
//EVT_HANDLER(FilterMotionBlur, "FilterMotionBlur")
2292
//EVT_HANDLER(FilterAdMameScale2x, "FilterAdMameScale2x")
2293
//EVT_HANDLER(FilterSimple2x, "FilterSimple2x")
2294
//EVT_HANDLER(FilterBilinear, "FilterBilinear")
2295
//EVT_HANDLER(FilterBilinearPlus, "FilterBilinearPlus")
2296
//EVT_HANDLER(FilterScanlines, "FilterScanlines")
2297
//EVT_HANDLER(FilterHq2x, "FilterHq2x")
2298
//EVT_HANDLER(FilterLq2x, "FilterLq2x")
2299
//EVT_HANDLER(FilterIFBNone, "FilterIFBNone")
2300
//EVT_HANDLER(FilterIFBMotionBlur, "FilterIFBMotionBlur")
2301
//EVT_HANDLER(FilterIFBSmart, "FilterIFBSmart")
2302
//EVT_HANDLER(FilterDisableMMX, "FilterDisableMMX")
2304
//EVT_HANDLER(JoypadConfigure1, "JoypadConfigure1")
2305
//EVT_HANDLER(JoypadConfigure2, "JoypadConfigure2")
2306
//EVT_HANDLER(JoypadConfigure3, "JoypadConfigure3")
2307
//EVT_HANDLER(JoypadConfigure4, "JoypadConfigure4")
2308
//EVT_HANDLER(JoypadMotionConfigure, "JoypadMotionConfigure")
2310
// The following functionality has been removed
2311
// It should be done in OS, rather than in vbam
2312
//EVT_HANDLER(EmulatorAssociate, "EmulatorAssociate")
2314
// The following functionality has been removed
2315
// It should be done at OS level (e.g. window manager)
2316
//EVT_HANDLER(SystemMinimize, "SystemMinimize")