~sergio-br2/vbam/fixes_have-svg-icons

« back to all changes in this revision

Viewing changes to .pc/vbam-debian.patch/src/wx/cmdevents.cpp

  • Committer: Sérgio Benjamim
  • Date: 2014-03-22 16:27:59 UTC
  • Revision ID: sergio@sergio-x750jb-20140322162759-xblyhd3z3i55cuwo
vbam debian patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef NO_FFMPEG
 
2
#define __STDC_LIMIT_MACROS // required for ffmpeg
 
3
#define __STDC_CONSTANT_MACROS // required for ffmpeg
 
4
#endif
 
5
#include "wxvbam.h"
 
6
#include <algorithm>
 
7
#include <wx/aboutdlg.h>
 
8
#include <wx/ffile.h>
 
9
#include <wx/wfstream.h>
 
10
#include <wx/sstream.h>
 
11
#include <wx/regex.h>
 
12
#include <wx/numdlg.h>
 
13
#include <wx/progdlg.h>
 
14
#ifndef NO_FFMPEG
 
15
extern "C" {
 
16
#include <libavformat/avformat.h>
 
17
}
 
18
#endif
 
19
#include "../gb/gbPrinter.h"
 
20
#include "../gba/agbprint.h"
 
21
 
 
22
#define GetXRCDialog(n) \
 
23
    wxStaticCast(FindWindow(XRCID(n)), wxDialog)
 
24
 
 
25
bool cmditem_lt(const struct cmditem &cmd1, const struct cmditem &cmd2)
 
26
{
 
27
    return wxStrcmp(cmd1.cmd, cmd2.cmd) < 0;
 
28
}
 
29
 
 
30
#define update_bcheck(s, f) do { \
 
31
    f = !f; \
 
32
    int id = XRCID(s); \
 
33
    for(int i = 0; i < checkable_mi.size(); i++) { \
 
34
        if(checkable_mi[i].cmd != id) \
 
35
            continue; \
 
36
        f = checkable_mi[i].mi->IsChecked(); \
 
37
        break; \
 
38
    } \
 
39
} while(0)
 
40
 
 
41
#define update_icheck(s, f, m, v) do { \
 
42
    bool is_checked = ((f) & (m)) != (v); \
 
43
    int id = XRCID(s); \
 
44
    for(int i = 0; i < checkable_mi.size(); i++) { \
 
45
        if(checkable_mi[i].cmd != id) \
 
46
            continue; \
 
47
        is_checked = checkable_mi[i].mi->IsChecked(); \
 
48
        break; \
 
49
    } \
 
50
    f = ((f) & ~(m)) | (is_checked ? (v) : 0); \
 
51
} while(0)
 
52
#define update_icheck1(s, f, m) update_icheck(s, f, m, m)
 
53
 
 
54
#define update_check(s, v) do { \
 
55
    int id = XRCID(s); \
 
56
    for(int i = 0; i < checkable_mi.size(); i++) { \
 
57
        if(checkable_mi[i].cmd != id) \
 
58
            continue; \
 
59
        checkable_mi[i].mi->Check(v); \
 
60
        break; \
 
61
    } \
 
62
} while(0)
 
63
 
 
64
//// File menu
 
65
 
 
66
// formerly OpenGBA, OpenGBC, OpenGB
 
67
// having just one means separate ROM dirs only make sense on the cmd line
 
68
 
 
69
static int open_ft = 0;
 
70
static wxString open_dir;
 
71
 
 
72
EVT_HANDLER(wxID_OPEN, "Open ROM...")
 
73
{
 
74
    if(!open_dir.size())
 
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(""),
 
89
                     pats,
 
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();
 
96
}
 
97
 
 
98
EVT_HANDLER(RecentReset, "Reset recent ROM list")
 
99
{
 
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("/"));
 
108
        cfg->Flush();
 
109
    }
 
110
}
 
111
 
 
112
EVT_HANDLER(RecentFreeze, "Freeze recent ROM list (toggle)")
 
113
{
 
114
    update_bcheck("RecentFreeze", gopts.recent_freeze);
 
115
    update_opts();
 
116
}
 
117
 
 
118
// following 10 should really be a single ranged handler
 
119
// former names: Recent01 .. Recent10
 
120
EVT_HANDLER(wxID_FILE1, "Load recent ROM 1")
 
121
{
 
122
    panel->LoadGame(gopts.recent->GetHistoryFile(0));
 
123
}
 
124
 
 
125
EVT_HANDLER(wxID_FILE2, "Load recent ROM 2")
 
126
{
 
127
    panel->LoadGame(gopts.recent->GetHistoryFile(1));
 
128
}
 
129
 
 
130
EVT_HANDLER(wxID_FILE3, "Load recent ROM 3")
 
131
{
 
132
    panel->LoadGame(gopts.recent->GetHistoryFile(2));
 
133
}
 
134
 
 
135
EVT_HANDLER(wxID_FILE4, "Load recent ROM 4")
 
136
{
 
137
    panel->LoadGame(gopts.recent->GetHistoryFile(3));
 
138
}
 
139
 
 
140
EVT_HANDLER(wxID_FILE5, "Load recent ROM 5")
 
141
{
 
142
    panel->LoadGame(gopts.recent->GetHistoryFile(4));
 
143
}
 
144
 
 
145
EVT_HANDLER(wxID_FILE6, "Load recent ROM 6")
 
146
{
 
147
    panel->LoadGame(gopts.recent->GetHistoryFile(5));
 
148
}
 
149
 
 
150
EVT_HANDLER(wxID_FILE7, "Load recent ROM 7")
 
151
{
 
152
    panel->LoadGame(gopts.recent->GetHistoryFile(6));
 
153
}
 
154
 
 
155
EVT_HANDLER(wxID_FILE8, "Load recent ROM 8")
 
156
{
 
157
    panel->LoadGame(gopts.recent->GetHistoryFile(7));
 
158
}
 
159
 
 
160
EVT_HANDLER(wxID_FILE9, "Load recent ROM 9")
 
161
{
 
162
    panel->LoadGame(gopts.recent->GetHistoryFile(8));
 
163
}
 
164
 
 
165
EVT_HANDLER(wxID_FILE10, "Load recent ROM 10")
 
166
{
 
167
    panel->LoadGame(gopts.recent->GetHistoryFile(9));
 
168
}
 
169
 
 
170
static const struct rom_maker {
 
171
    const wxChar *code, *name;
 
172
} makers[] = {
 
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") }
 
393
};
 
394
#define num_makers (sizeof(makers)/sizeof(makers[0]))
 
395
static bool maker_lt(const rom_maker &r1, const rom_maker &r2)
 
396
{
 
397
    return wxStrcmp(r1.code, r2.code) < 0;
 
398
}
 
399
 
 
400
EVT_HANDLER_MASK(RomInformation, "ROM information...", CMDEN_GB|CMDEN_GBA)
 
401
{
 
402
    wxString s;
 
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); \
 
407
} while(0)
 
408
#define setblab(id, b) do { \
 
409
    s.Printf(wxT("%02x"), (unsigned int)b); \
 
410
    setlab(id); \
 
411
} while(0)
 
412
#define setblabs(id, b, ts) do { \
 
413
    s.Printf(wxT("%02x (%s)"), (unsigned int)b, ts); \
 
414
    setlab(id); \
 
415
} while(0)
 
416
#define setlabs(id, ts, l) do { \
 
417
    s = wxString((const char *)&(ts), wxConvLibc, l); \
 
418
    setlab(id); \
 
419
} while(0)
 
420
    switch(panel->game_type()) {
 
421
    case IMAGE_GB:
 
422
        {
 
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);
 
428
            else
 
429
                s.Printf(wxT("%02x"), gbRom[0x14b]);
 
430
            setlab("MakerCode");
 
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))
 
434
                s = rm->name;
 
435
            else
 
436
                s = _("Unknown");
 
437
            setlab("MakerName");
 
438
            setblab("UnitCode", gbRom[0x146]);
 
439
            const wxChar *type;
 
440
            switch(gbRom[0x147]) {
 
441
            case 0x00:
 
442
                type = _("ROM");
 
443
                break;
 
444
            case 0x01:
 
445
                type = _("ROM+MBC1");
 
446
                break;
 
447
            case 0x02:
 
448
                type = _("ROM+MBC1+RAM");
 
449
                break;
 
450
            case 0x03:
 
451
                type = _("ROM+MBC1+RAM+BATT");
 
452
                break;
 
453
            case 0x05:
 
454
                type = _("ROM+MBC2");
 
455
                break;
 
456
            case 0x06:
 
457
                type = _("ROM+MBC2+BATT");
 
458
                break;
 
459
            case 0x0b:
 
460
                type = _("ROM+MMM01");
 
461
                break;
 
462
            case 0x0c:
 
463
                type = _("ROM+MMM01+RAM");
 
464
                break;
 
465
            case 0x0d:
 
466
                type = _("ROM+MMM01+RAM+BATT");
 
467
                break;
 
468
            case 0x0f:
 
469
                type = _("ROM+MBC3+TIMER+BATT");
 
470
                break;
 
471
            case 0x10:
 
472
                type = _("ROM+MBC3+TIMER+RAM+BATT");
 
473
                break;
 
474
            case 0x11:
 
475
                type = _("ROM+MBC3");
 
476
                break;
 
477
            case 0x12:
 
478
                type = _("ROM+MBC3+RAM");
 
479
                break;
 
480
            case 0x13:
 
481
                type = _("ROM+MBC3+RAM+BATT");
 
482
                break;
 
483
            case 0x19:
 
484
                type = _("ROM+MBC5");
 
485
                break;
 
486
            case 0x1a:
 
487
                type = _("ROM+MBC5+RAM");
 
488
                break;
 
489
            case 0x1b:
 
490
                type = _("ROM+MBC5+RAM+BATT");
 
491
                break;
 
492
            case 0x1c:
 
493
                type = _("ROM+MBC5+RUMBLE");
 
494
                break;
 
495
            case 0x1d:
 
496
                type = _("ROM+MBC5+RUMBLE+RAM");
 
497
                break;
 
498
            case 0x1e:
 
499
                type = _("ROM+MBC5+RUMBLE+RAM+BATT");
 
500
                break;
 
501
            case 0x22:
 
502
                type = _("ROM+MBC7+BATT");
 
503
                break;
 
504
            case 0x55:
 
505
                type = _("GameGenie");
 
506
                break;
 
507
            case 0x56:
 
508
                type = _("GameShark V3.0");
 
509
                break;
 
510
            case 0xfc:
 
511
                type = _("ROM+POCKET CAMERA");
 
512
                break;
 
513
            case 0xfd:
 
514
                type = _("ROM+BANDAI TAMA5");
 
515
                break;
 
516
            case 0xfe:
 
517
                type = _("ROM+HuC-3");
 
518
                break;
 
519
            case 0xff:
 
520
                type = _("ROM+HuC-1");
 
521
                break;
 
522
            default:
 
523
                type = _("Unknown");
 
524
            }
 
525
            setblabs("DeviceType", gbRom[0x147], type);
 
526
            switch(gbRom[0x148]) {
 
527
            case 0:
 
528
                type = wxT("32K");
 
529
                break;
 
530
            case 1:
 
531
                type = wxT("64K");
 
532
                break;
 
533
            case 2:
 
534
                type = wxT("128K");
 
535
                break;
 
536
            case 3:
 
537
                type = wxT("256K");
 
538
                break;
 
539
            case 4:
 
540
                type = wxT("512K");
 
541
                break;
 
542
            case 5:
 
543
                type = wxT("1M");
 
544
                break;
 
545
            case 6:
 
546
                type = wxT("2M");
 
547
                break;
 
548
            case 7:
 
549
                type = wxT("4M");
 
550
                break;
 
551
            default:
 
552
                type = _("Unknown");
 
553
            }
 
554
            setblabs("ROMSize", gbRom[0x148], type);
 
555
            switch(gbRom[0x149]) {
 
556
            case 0:
 
557
                type = _("None");
 
558
                break;
 
559
            case 1:
 
560
                type = wxT("2K");
 
561
                break;
 
562
            case 2:
 
563
                type = wxT("8K");
 
564
                break;
 
565
            case 3:
 
566
                type = wxT("32K");
 
567
                break;
 
568
            case 4:
 
569
                type = wxT("128K");
 
570
                break;
 
571
            case 5:
 
572
                type = wxT("64K");
 
573
                break;
 
574
            }
 
575
            setblabs("RAMSize", gbRom[0x149], type);
 
576
            setblab("DestCode", gbRom[0x14a]);
 
577
            setblab("LicCode", gbRom[0x14b]);
 
578
            setblab("Version", gbRom[0x14c]);
 
579
            u8 crc = 25;
 
580
            for(int i = 0x134; i < 0x14d; i++)
 
581
                crc += gbRom[i];
 
582
            crc = 256 - crc;
 
583
            s.Printf(wxT("%02x (%02x)"), crc, gbRom[0x14d]);
 
584
            setlab("CRC");
 
585
            u16 crc16 = 0;
 
586
            for(int i = 0; i < gbRomSize; i++)
 
587
                crc16 += gbRom[i];
 
588
            crc16 -= gbRom[0x14e] + gbRom[0x14f];
 
589
            s.Printf(wxT("%04x (%04x)"), crc16, gbRom[0x14e]*256+gbRom[0x14f]);
 
590
            setlab("Checksum");
 
591
            dlg->Fit();
 
592
            ShowModal(dlg);
 
593
        }
 
594
        break;
 
595
    case IMAGE_GBA:
 
596
        {
 
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))
 
604
                s = rm->name;
 
605
            else
 
606
                s = _("Unknown");
 
607
            setlab("MakerName");
 
608
            setblab("UnitCode", rom[0xb3]);
 
609
            s.Printf(wxT("%02x"), (unsigned int)rom[0xb4]);
 
610
            if(rom[0xb4] & 0x80)
 
611
                s.append(wxT(" (DACS)"));
 
612
            setlab("DeviceType");
 
613
            setblab("Version", rom[0xbc]);
 
614
            u8 crc = 0x19;
 
615
            for(int i = 0xa0; i < 0xbd; i++)
 
616
                crc += rom[i];
 
617
            crc = -crc;
 
618
            s.Printf(wxT("%02x (%02x)"), crc, rom[0xbd]);
 
619
            setlab("CRC");
 
620
            dlg->Fit();
 
621
            ShowModal(dlg);
 
622
        }
 
623
        break;
 
624
    }
 
625
}
 
626
 
 
627
static wxString batimp_path;
 
628
 
 
629
EVT_HANDLER_MASK(ImportBatteryFile, "Import battery file...", CMDEN_GB|CMDEN_GBA)
 
630
{
 
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();
 
637
    if(ret != wxID_OK)
 
638
        return;
 
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);
 
642
    if(ret == wxYES) {
 
643
        wxString msg;
 
644
        if(panel->emusys->emuReadBattery(fn.mb_fn_str()))
 
645
            msg.Printf(_("Loaded battery %s"), fn.c_str());
 
646
        else
 
647
            msg.Printf(_("Error loading battery %s"), fn.c_str());
 
648
        systemScreenMessage(msg);
 
649
    }
 
650
}
 
651
 
 
652
EVT_HANDLER_MASK(ImportGamesharkCodeFile, "Import GameShark code file...", CMDEN_GB|CMDEN_GBA)
 
653
{
 
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();
 
662
    if(ret != wxID_OK)
 
663
        return;
 
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);
 
667
    if(ret == wxYES) {
 
668
        wxString msg;
 
669
        bool res;
 
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());
 
675
        else {
 
676
            // need to select game first
 
677
            wxFFile f(fn, wxT("rb"));
 
678
            if(!f.IsOpened()) {
 
679
                wxLogError(_("Cannot open file %s"), fn.c_str());
 
680
                return;
 
681
            }
 
682
            // FIXME: in my code, I assume file format is little-endian
 
683
            // however, in core code, it is assumed to be native-endian
 
684
            u32 len;
 
685
            char buf[14];
 
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());
 
690
                return;
 
691
            }
 
692
            f.Seek(0x1e);
 
693
            if(f.Read(&len, sizeof(len)) != sizeof(len))
 
694
                len = 0;
 
695
            u32 game = 0;
 
696
            if(len > 1) {
 
697
                wxDialog *seldlg = GetXRCDialog("CodeSelect");
 
698
                wxControlWithItems *lst = XRCCTRL(*seldlg, "CodeList", wxControlWithItems);
 
699
                lst->Clear();
 
700
                while(len-- > 0) {
 
701
                    u32 slen;
 
702
                    if(f.Read(&slen, sizeof(slen)) != sizeof(slen) ||
 
703
                      slen > 1024) // arbitrary upper bound
 
704
                        break;
 
705
                    char buf[slen];
 
706
                    if(f.Read(buf, slen) != slen)
 
707
                        break;
 
708
                    lst->Append(wxString(buf, wxConvLibc, slen));
 
709
                    u32 ncodes;
 
710
                    if(f.Read(&ncodes, sizeof(ncodes)) != sizeof(ncodes))
 
711
                        break;
 
712
                    for(; ncodes > 0; ncodes--) {
 
713
                        if(f.Read(&slen, sizeof(slen)) != sizeof(slen))
 
714
                            break;
 
715
                        f.Seek(slen, wxFromCurrent);
 
716
                        if(f.Read(&slen, sizeof(slen)) != sizeof(slen))
 
717
                            break;
 
718
                        f.Seek(slen + 4, wxFromCurrent);
 
719
                        if(f.Read(&slen, sizeof(slen)) != sizeof(slen))
 
720
                            break;
 
721
                        f.Seek(slen * 12, wxFromCurrent);
 
722
                    }
 
723
                }
 
724
                int sel = ShowModal(seldlg);
 
725
                if(sel != wxID_OK)
 
726
                    return;
 
727
                game = lst->GetSelection();
 
728
                if(game == wxNOT_FOUND)
 
729
                    game = 0;
 
730
            }
 
731
            bool v3 = fn.size() >= 4 &&
 
732
                wxString(fn.substr(fn.size() - 4)).IsSameAs(wxT(".xpc"), false);
 
733
 
 
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);
 
738
        }
 
739
        if(res)
 
740
            msg.Printf(_("Loaded code file %s"), fn.c_str());
 
741
        else
 
742
            msg.Printf(_("Error loading code file %s"), fn.c_str());
 
743
        systemScreenMessage(msg);
 
744
    }
 
745
}
 
746
 
 
747
static wxString gss_path;
 
748
 
 
749
EVT_HANDLER_MASK(ImportGamesharkActionReplaySnapshot,
 
750
            "Import GameShark Action Replay snapshot...", CMDEN_GB|CMDEN_GBA)
 
751
{
 
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();
 
759
    if(ret != wxID_OK)
 
760
        return;
 
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);
 
764
    if(ret == wxYES) {
 
765
        wxString msg;
 
766
        bool res;
 
767
        if(panel->game_type() == IMAGE_GB)
 
768
            res = gbReadGSASnapshot(fn.mb_fn_str());
 
769
        else {
 
770
            bool gsv = fn.size() >= 4 &&
 
771
                wxString(fn.substr(fn.size() - 4)).IsSameAs(wxT(".gsv"), false);
 
772
            if(gsv)
 
773
                // FIXME: this will fail on big-endian machines if
 
774
                // file format is little-endian
 
775
                // fix in GBA.cpp
 
776
                res = CPUReadGSASPSnapshot(fn.mb_fn_str());
 
777
            else
 
778
                // FIXME: this will fail on big-endian machines if
 
779
                // file format is little-endian
 
780
                // fix in GBA.cpp
 
781
                res = CPUReadGSASnapshot(fn.mb_fn_str());
 
782
        }
 
783
        if(res)
 
784
            msg.Printf(_("Loaded snapshot file %s"), fn.c_str());
 
785
        else
 
786
            msg.Printf(_("Error loading snapshot file %s"), fn.c_str());
 
787
        systemScreenMessage(msg);
 
788
    }
 
789
}
 
790
 
 
791
EVT_HANDLER_MASK(ExportBatteryFile, "Export battery file...", CMDEN_GB|CMDEN_GBA)
 
792
{
 
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();
 
799
    if(ret != wxID_OK)
 
800
        return;
 
801
    wxString fn = dlg.GetPath();
 
802
    wxString msg;
 
803
    if(panel->emusys->emuWriteBattery(fn.mb_fn_str()))
 
804
        msg.Printf(_("Wrote battery %s"), fn.c_str());
 
805
    else
 
806
        msg.Printf(_("Error writing battery %s"), fn.c_str());
 
807
    systemScreenMessage(msg);
 
808
}
 
809
 
 
810
EVT_HANDLER_MASK(ExportGamesharkSnapshot, "Export GameShark snapshot...", CMDEN_GBA)
 
811
{
 
812
    if(eepromInUse) {
 
813
        wxLogError(_("EEPROM saves cannot be exported"));
 
814
        return;
 
815
    }
 
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();
 
822
    if(ret != wxID_OK)
 
823
        return;
 
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)
 
833
        return;
 
834
    wxString msg;
 
835
 
 
836
    // FIXME: this will fail on big-endian machines if file format is
 
837
    // little-endian
 
838
    // fix in GBA.cpp
 
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());
 
842
    else
 
843
        msg.Printf(_("Error saving snapshot file %s"), fn.c_str());
 
844
    systemScreenMessage(msg);
 
845
}
 
846
 
 
847
EVT_HANDLER_MASK(ScreenCapture, "Screen capture...", CMDEN_GB|CMDEN_GBA)
 
848
{
 
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);
 
854
            if(!sp.IsAbsolute())
 
855
                scap_path = panel->game_dir() + wxT('/') + gopts.scrshot_dir;
 
856
            wxFileName::Mkdir(scap_path, 0777, wxPATH_MKDIR_FULL);
 
857
        }
 
858
    }
 
859
    wxString def_name = panel->game_name();
 
860
    if(gopts.cap_format == 0)
 
861
        def_name.append(wxT(".png"));
 
862
    else
 
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();
 
869
    if(ret != wxID_OK)
 
870
        return;
 
871
    wxString fn = dlg.GetPath();
 
872
    int fmt = dlg.GetFilterIndex();
 
873
    if(fn.size() >= 4) {
 
874
        if(wxString(fn.substr(fn.size() - 4)).IsSameAs(wxT(".bmp"), false))
 
875
            fmt = 1;
 
876
        else if(wxString(fn.substr(fn.size() - 4)).IsSameAs(wxT(".png"), false))
 
877
            fmt = 0;
 
878
    }
 
879
    if(fmt == 0)
 
880
        panel->emusys->emuWritePNG(fn.mb_fn_str());
 
881
    else
 
882
        panel->emusys->emuWriteBMP(fn.mb_fn_str());
 
883
    wxString msg;
 
884
    msg.Printf(_("Wrote snapshot %s"), fn.c_str());
 
885
    systemScreenMessage(msg);
 
886
}
 
887
 
 
888
EVT_HANDLER_MASK(RecordSoundStartRecording, "Start sound recording...", CMDEN_NSREC)
 
889
{
 
890
#ifndef NO_FFMPEG
 
891
    static wxString sound_exts;
 
892
    static int sound_extno;
 
893
    static wxString sound_path;
 
894
 
 
895
    if(!sound_exts.size()) {
 
896
        sound_extno = -1;
 
897
        int extno;
 
898
        AVOutputFormat *fmt;
 
899
        for(fmt = NULL, extno = 0; (fmt = av_oformat_next(fmt)); ) {
 
900
            if(!fmt->extensions)
 
901
                continue;
 
902
            if(fmt->audio_codec == CODEC_ID_NONE)
 
903
                continue;
 
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)
 
910
                sound_extno = extno;
 
911
            sound_exts.append(ext);
 
912
            sound_exts.append(wxT(")|"));
 
913
            sound_exts.append(ext);
 
914
            sound_exts.append(wxT('|'));
 
915
            extno++;
 
916
        }
 
917
        sound_exts.append(wxALL_FILES);
 
918
        if(sound_extno < 0)
 
919
            sound_extno = extno;
 
920
    }
 
921
    if(!sound_path.size()) {
 
922
        if(!gopts.recording_dir.size())
 
923
            sound_path = panel->game_dir();
 
924
        else {
 
925
            wxFileName sp(gopts.recording_dir, wxEmptyString);
 
926
            if(sp.IsAbsolute())
 
927
                sound_path = gopts.recording_dir;
 
928
            else
 
929
                sound_path = panel->game_dir() + wxT('/') + gopts.recording_dir;
 
930
        }
 
931
        wxFileName::Mkdir(sound_path, 0777, wxPATH_MKDIR_FULL);
 
932
    }
 
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;
 
938
    }
 
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();
 
947
    if(ret != wxID_OK)
 
948
        return;
 
949
    panel->StartSoundRecording(dlg.GetPath());
 
950
#endif
 
951
}
 
952
 
 
953
EVT_HANDLER_MASK(RecordSoundStopRecording, "Stop sound recording", CMDEN_SREC)
 
954
{
 
955
#ifndef NO_FFMPEG
 
956
    panel->StopSoundRecording();
 
957
#endif
 
958
}
 
959
 
 
960
EVT_HANDLER_MASK(RecordAVIStartRecording, "Start video recording...", CMDEN_NVREC)
 
961
{
 
962
#ifndef NO_FFMPEG
 
963
    static wxString vid_exts;
 
964
    static int vid_extno;
 
965
    static wxString vid_path;
 
966
 
 
967
    if(!vid_exts.size()) {
 
968
        vid_extno = -1;
 
969
        int extno;
 
970
        AVOutputFormat *fmt;
 
971
        for(fmt = NULL, extno = 0; (fmt = av_oformat_next(fmt)); ) {
 
972
            if(!fmt->extensions)
 
973
                continue;
 
974
            if(fmt->video_codec == CODEC_ID_NONE)
 
975
                continue;
 
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)
 
982
                vid_extno = extno;
 
983
            vid_exts.append(ext);
 
984
            vid_exts.append(wxT(")|"));
 
985
            vid_exts.append(ext);
 
986
            vid_exts.append(wxT('|'));
 
987
            extno++;
 
988
        }
 
989
        vid_exts.append(wxALL_FILES);
 
990
        if(vid_extno < 0)
 
991
            vid_extno = extno;
 
992
    }
 
993
    if(!vid_path.size()) {
 
994
        if(!gopts.recording_dir.size())
 
995
            vid_path = panel->game_dir();
 
996
        else {
 
997
            wxFileName sp(gopts.recording_dir, wxEmptyString);
 
998
            if(sp.IsAbsolute())
 
999
                vid_path = gopts.recording_dir;
 
1000
            else
 
1001
                vid_path = panel->game_dir() + wxT('/') + gopts.recording_dir;
 
1002
        }
 
1003
        wxFileName::Mkdir(vid_path, 0777, wxPATH_MKDIR_FULL);
 
1004
    }
 
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;
 
1010
    }
 
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();
 
1019
    if(ret != wxID_OK)
 
1020
        return;
 
1021
    panel->StartVidRecording(dlg.GetPath());
 
1022
#endif
 
1023
}
 
1024
 
 
1025
EVT_HANDLER_MASK(RecordAVIStopRecording, "Stop video recording", CMDEN_VREC)
 
1026
{
 
1027
#ifndef NO_FFMPEG
 
1028
    panel->StopVidRecording();
 
1029
#endif
 
1030
}
 
1031
 
 
1032
static wxString mov_path;
 
1033
 
 
1034
EVT_HANDLER_MASK(RecordMovieStartRecording, "Start game recording...", CMDEN_NGREC)
 
1035
{
 
1036
    if(!mov_path.size()) {
 
1037
        if(!gopts.recording_dir.size())
 
1038
            mov_path = panel->game_dir();
 
1039
        else {
 
1040
            wxFileName sp(gopts.recording_dir, wxEmptyString);
 
1041
            if(sp.IsAbsolute())
 
1042
                mov_path = gopts.recording_dir;
 
1043
            else
 
1044
                mov_path = panel->game_dir() + wxT('/') + gopts.recording_dir;
 
1045
        }
 
1046
        wxFileName::Mkdir(mov_path, 0777, wxPATH_MKDIR_FULL);
 
1047
    }
 
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();
 
1053
    if(ret != wxID_OK)
 
1054
        return;
 
1055
    systemStartGameRecording(dlg.GetPath());
 
1056
}
 
1057
 
 
1058
EVT_HANDLER_MASK(RecordMovieStopRecording, "Stop game recording", CMDEN_GREC)
 
1059
{
 
1060
    systemStopGameRecording();
 
1061
}
 
1062
 
 
1063
EVT_HANDLER_MASK(PlayMovieStartPlaying, "Start playing movie...", CMDEN_NGREC|CMDEN_NGPLAY)
 
1064
{
 
1065
    if(!mov_path.size()) {
 
1066
        if(!gopts.recording_dir.size())
 
1067
            mov_path = panel->game_dir();
 
1068
        else {
 
1069
            wxFileName sp(gopts.recording_dir, wxEmptyString);
 
1070
            if(sp.IsAbsolute())
 
1071
                mov_path = gopts.recording_dir;
 
1072
            else
 
1073
                mov_path = panel->game_dir() + wxT('/') + gopts.recording_dir;
 
1074
        }
 
1075
        if(!wxFileName::DirExists(mov_path))
 
1076
            mov_path = wxFileName::GetCwd();
 
1077
    }
 
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();
 
1084
    if(ret != wxID_OK)
 
1085
        return;
 
1086
    systemStartGamePlayback(dlg.GetPath());
 
1087
}
 
1088
 
 
1089
EVT_HANDLER_MASK(PlayMovieStopPlaying, "Stop playing movie", CMDEN_GPLAY)
 
1090
{
 
1091
    systemStopGamePlayback();
 
1092
}
 
1093
 
 
1094
// formerly Close
 
1095
EVT_HANDLER_MASK(wxID_CLOSE, "Close", CMDEN_GB|CMDEN_GBA)
 
1096
{
 
1097
    panel->UnloadGame();
 
1098
}
 
1099
 
 
1100
// formerly Exit
 
1101
EVT_HANDLER(wxID_EXIT, "Exit")
 
1102
{
 
1103
    Close(false);
 
1104
}
 
1105
 
 
1106
 
 
1107
// Emulation menu
 
1108
EVT_HANDLER(Pause, "Pause (toggle)")
 
1109
{
 
1110
    update_bcheck("Pause", paused);
 
1111
    if(paused)
 
1112
        panel->Pause();
 
1113
    else if(!IsPaused())
 
1114
        panel->Resume();
 
1115
    // undo next-frame's zeroing of frameskip
 
1116
    int fs = panel->game_type() == IMAGE_GB ? gopts.gb_frameskip : gopts.gba_frameskip;
 
1117
    if(fs > 0)
 
1118
        systemFrameSkip = fs;
 
1119
}
 
1120
 
 
1121
// new
 
1122
EVT_HANDLER_MASK(EmulatorSpeedupToggle, "Turbo mode (toggle)", CMDEN_GB|CMDEN_GBA)
 
1123
{
 
1124
    update_bcheck("EmulatorSpeedupToggle", turbo);
 
1125
}
 
1126
 
 
1127
EVT_HANDLER_MASK(Reset, "Reset", CMDEN_GB|CMDEN_GBA)
 
1128
{
 
1129
    panel->emusys->emuReset();
 
1130
    // systemScreenMessage("Reset");
 
1131
}
 
1132
 
 
1133
EVT_HANDLER(ToggleFullscreen, "Full screen (toggle)")
 
1134
{
 
1135
    panel->ShowFullScreen(!IsFullScreen());
 
1136
}
 
1137
 
 
1138
EVT_HANDLER(JoypadAutofireA, "Autofire A (toggle)")
 
1139
{
 
1140
    update_icheck1("JoypadAutofireA", autofire, KEYM_A);
 
1141
}
 
1142
 
 
1143
EVT_HANDLER(JoypadAutofireB, "Autofire B (toggle)")
 
1144
{
 
1145
    update_icheck1("JoypadAutofireB", autofire, KEYM_B);
 
1146
}
 
1147
 
 
1148
EVT_HANDLER(JoypadAutofireL, "Autofire L (toggle)")
 
1149
{
 
1150
    update_icheck1("JoypadAutofireL", autofire, KEYM_LEFT);
 
1151
}
 
1152
 
 
1153
EVT_HANDLER(JoypadAutofireR, "Autofire R (toggle)")
 
1154
{
 
1155
    update_icheck1("JoypadAutofireR", autofire, KEYM_RIGHT);
 
1156
}
 
1157
 
 
1158
// new
 
1159
EVT_HANDLER_MASK(LanLink, "Start LAN link", CMDEN_LINK_ANY)
 
1160
{
 
1161
#ifndef NO_LINK
 
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."));
 
1166
        return;
 
1167
    }
 
1168
    if(rfu_enabled) {
 
1169
        // see above comment
 
1170
        wxLogError(_("RFU is currently only supported in local mode."));
 
1171
        return;
 
1172
    }
 
1173
    wxDialog *dlg = GetXRCDialog("NetLink");
 
1174
    ShowModal(dlg);
 
1175
    panel->SetFrameTitle();
 
1176
#endif
 
1177
}
 
1178
 
 
1179
EVT_HANDLER_MASK(LoadGameRecent, "Load most recent save", CMDEN_SAVST)
 
1180
{
 
1181
    panel->LoadState();
 
1182
}
 
1183
 
 
1184
EVT_HANDLER(LoadGameAutoLoad, "Auto load most recent save (toggle)")
 
1185
{
 
1186
    update_bcheck("LoadGameAutoLoad", gopts.autoload_state);
 
1187
    update_opts();
 
1188
}
 
1189
 
 
1190
EVT_HANDLER_MASK(LoadGame01, "Load saved state 1", CMDEN_SAVST)
 
1191
{
 
1192
    panel->LoadState(1);
 
1193
}
 
1194
 
 
1195
EVT_HANDLER_MASK(LoadGame02, "Load saved state 2", CMDEN_SAVST)
 
1196
{
 
1197
    panel->LoadState(2);
 
1198
}
 
1199
 
 
1200
EVT_HANDLER_MASK(LoadGame03, "Load saved state 3", CMDEN_SAVST)
 
1201
{
 
1202
    panel->LoadState(3);
 
1203
}
 
1204
 
 
1205
EVT_HANDLER_MASK(LoadGame04, "Load saved state 4", CMDEN_SAVST)
 
1206
{
 
1207
    panel->LoadState(4);
 
1208
}
 
1209
 
 
1210
EVT_HANDLER_MASK(LoadGame05, "Load saved state 5", CMDEN_SAVST)
 
1211
{
 
1212
    panel->LoadState(5);
 
1213
}
 
1214
 
 
1215
EVT_HANDLER_MASK(LoadGame06, "Load saved state 6", CMDEN_SAVST)
 
1216
{
 
1217
    panel->LoadState(6);
 
1218
}
 
1219
 
 
1220
EVT_HANDLER_MASK(LoadGame07, "Load saved state 7", CMDEN_SAVST)
 
1221
{
 
1222
    panel->LoadState(7);
 
1223
}
 
1224
 
 
1225
EVT_HANDLER_MASK(LoadGame08, "Load saved state 8", CMDEN_SAVST)
 
1226
{
 
1227
    panel->LoadState(8);
 
1228
}
 
1229
 
 
1230
EVT_HANDLER_MASK(LoadGame09, "Load saved state 9", CMDEN_SAVST)
 
1231
{
 
1232
    panel->LoadState(9);
 
1233
}
 
1234
 
 
1235
EVT_HANDLER_MASK(LoadGame10, "Load saved state 10", CMDEN_SAVST)
 
1236
{
 
1237
    panel->LoadState(10);
 
1238
}
 
1239
 
 
1240
static wxString st_dir;
 
1241
 
 
1242
EVT_HANDLER_MASK(Load, "Load state...", CMDEN_GB|CMDEN_GBA)
 
1243
{
 
1244
    if(st_dir.empty())
 
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();
 
1250
    if(ret != wxID_OK)
 
1251
        return;
 
1252
    panel->LoadState(dlg.GetPath());
 
1253
}
 
1254
 
 
1255
// new
 
1256
EVT_HANDLER(KeepSaves, "Do not load battery saves (toggle)")
 
1257
{
 
1258
    update_bcheck("KeepSaves", skipSaveGameBattery);
 
1259
    update_opts();
 
1260
}
 
1261
 
 
1262
// new
 
1263
EVT_HANDLER(KeepCheats, "Do not change cheat list (toggle)")
 
1264
{
 
1265
    update_bcheck("KeepCheats", skipSaveGameCheats);
 
1266
    update_opts();
 
1267
}
 
1268
 
 
1269
EVT_HANDLER_MASK(SaveGameOldest, "Save state to oldest slot", CMDEN_GB|CMDEN_GBA)
 
1270
{
 
1271
    panel->SaveState();
 
1272
}
 
1273
 
 
1274
EVT_HANDLER_MASK(SaveGame01, "Save state 1", CMDEN_GB|CMDEN_GBA)
 
1275
{
 
1276
    panel->SaveState(1);
 
1277
}
 
1278
 
 
1279
EVT_HANDLER_MASK(SaveGame02, "Save state 2", CMDEN_GB|CMDEN_GBA)
 
1280
{
 
1281
    panel->SaveState(2);
 
1282
}
 
1283
 
 
1284
EVT_HANDLER_MASK(SaveGame03, "Save state 3", CMDEN_GB|CMDEN_GBA)
 
1285
{
 
1286
    panel->SaveState(3);
 
1287
}
 
1288
 
 
1289
EVT_HANDLER_MASK(SaveGame04, "Save state 4", CMDEN_GB|CMDEN_GBA)
 
1290
{
 
1291
    panel->SaveState(4);
 
1292
}
 
1293
 
 
1294
EVT_HANDLER_MASK(SaveGame05, "Save state 5", CMDEN_GB|CMDEN_GBA)
 
1295
{
 
1296
    panel->SaveState(5);
 
1297
}
 
1298
 
 
1299
EVT_HANDLER_MASK(SaveGame06, "Save state 6", CMDEN_GB|CMDEN_GBA)
 
1300
{
 
1301
    panel->SaveState(6);
 
1302
}
 
1303
 
 
1304
EVT_HANDLER_MASK(SaveGame07, "Save state 7", CMDEN_GB|CMDEN_GBA)
 
1305
{
 
1306
    panel->SaveState(7);
 
1307
}
 
1308
 
 
1309
EVT_HANDLER_MASK(SaveGame08, "Save state 8", CMDEN_GB|CMDEN_GBA)
 
1310
{
 
1311
    panel->SaveState(8);
 
1312
}
 
1313
 
 
1314
EVT_HANDLER_MASK(SaveGame09, "Save state 9", CMDEN_GB|CMDEN_GBA)
 
1315
{
 
1316
    panel->SaveState(9);
 
1317
}
 
1318
 
 
1319
EVT_HANDLER_MASK(SaveGame10, "Save state 10", CMDEN_GB|CMDEN_GBA)
 
1320
{
 
1321
    panel->SaveState(10);
 
1322
}
 
1323
 
 
1324
EVT_HANDLER_MASK(Save, "Save state as...", CMDEN_GB|CMDEN_GBA)
 
1325
{
 
1326
    if(st_dir.empty())
 
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();
 
1332
    if(ret != wxID_OK)
 
1333
        return;
 
1334
    panel->SaveState(dlg.GetPath());
 
1335
}
 
1336
 
 
1337
static int state_slot = 0;
 
1338
 
 
1339
// new
 
1340
EVT_HANDLER_MASK(LoadGameSlot, "Load current state slot", CMDEN_GB|CMDEN_GBA)
 
1341
{
 
1342
    panel->LoadState(state_slot + 1);
 
1343
}
 
1344
 
 
1345
// new
 
1346
EVT_HANDLER_MASK(SaveGameSlot, "Save current state slot", CMDEN_GB|CMDEN_GBA)
 
1347
{
 
1348
    panel->SaveState(state_slot + 1);
 
1349
}
 
1350
 
 
1351
// new
 
1352
EVT_HANDLER_MASK(IncrGameSlot, "Increase state slot number", CMDEN_GB|CMDEN_GBA)
 
1353
{
 
1354
    state_slot = (state_slot + 1) % 10;
 
1355
}
 
1356
 
 
1357
// new
 
1358
EVT_HANDLER_MASK(DecrGameSlot, "Decrease state slot number", CMDEN_GB|CMDEN_GBA)
 
1359
{
 
1360
    state_slot = (state_slot + 9) % 10;
 
1361
}
 
1362
 
 
1363
// new
 
1364
EVT_HANDLER_MASK(IncrGameSlotSave, "Increase state slot number and save", CMDEN_GB|CMDEN_GBA)
 
1365
{
 
1366
    state_slot = (state_slot + 1) % 10;
 
1367
    panel->SaveState(state_slot + 1);
 
1368
}
 
1369
 
 
1370
EVT_HANDLER_MASK(Rewind, "Rewind", CMDEN_REWIND)
 
1371
{
 
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;
 
1385
    }
 
1386
    panel->emusys->emuReadMemState(&panel->rewind_mem[rew_st * REWIND_SIZE],
 
1387
                                   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"));
 
1393
}
 
1394
 
 
1395
EVT_HANDLER_MASK(CheatsList, "List cheats...", CMDEN_GB|CMDEN_GBA)
 
1396
{
 
1397
    wxDialog *dlg = GetXRCDialog("CheatList");
 
1398
    ShowModal(dlg);
 
1399
}
 
1400
 
 
1401
EVT_HANDLER_MASK(CheatsSearch, "Create cheat...", CMDEN_GB|CMDEN_GBA)
 
1402
{
 
1403
    wxDialog *dlg = GetXRCDialog("CheatCreate");
 
1404
    ShowModal(dlg);
 
1405
}
 
1406
 
 
1407
// new
 
1408
EVT_HANDLER(CheatsAutoSaveLoad, "Auto save/load cheats (toggle)")
 
1409
{
 
1410
    update_bcheck("CheatsAutoSaveLoad", gopts.autoload_cheats);
 
1411
    update_opts();
 
1412
}
 
1413
 
 
1414
// was CheatsDisable
 
1415
// changed for convenience to match internal variable functionality
 
1416
EVT_HANDLER(CheatsEnable, "Enable cheats (toggle)")
 
1417
{
 
1418
    update_bcheck("CheatsEnable", cheatsEnabled);
 
1419
    update_opts();
 
1420
}
 
1421
 
 
1422
 
 
1423
// Debug menu
 
1424
EVT_HANDLER_MASK(VideoLayersBG0, "Video layer BG0 (toggle)", CMDEN_GB|CMDEN_GBA)
 
1425
{
 
1426
    update_icheck1("VideoLayersBG0", layerSettings, (1<<8));
 
1427
    layerEnable = DISPCNT & layerSettings;
 
1428
    CPUUpdateRenderBuffers(false);
 
1429
}
 
1430
 
 
1431
EVT_HANDLER_MASK(VideoLayersBG1, "Video layer BG1 (toggle)", CMDEN_GB|CMDEN_GBA)
 
1432
{
 
1433
    update_icheck1("VideoLayersBG1", layerSettings, (1<<9));
 
1434
    layerEnable = DISPCNT & layerSettings;
 
1435
    CPUUpdateRenderBuffers(false);
 
1436
}
 
1437
 
 
1438
EVT_HANDLER_MASK(VideoLayersBG2, "Video layer BG2 (toggle)", CMDEN_GB|CMDEN_GBA)
 
1439
{
 
1440
    update_icheck1("VideoLayersBG2", layerSettings, (1<<10));
 
1441
    layerEnable = DISPCNT & layerSettings;
 
1442
    CPUUpdateRenderBuffers(false);
 
1443
}
 
1444
 
 
1445
EVT_HANDLER_MASK(VideoLayersBG3, "Video layer BG3 (toggle)", CMDEN_GB|CMDEN_GBA)
 
1446
{
 
1447
    update_icheck1("VideoLayersBG3", layerSettings, (1<<11));
 
1448
    layerEnable = DISPCNT & layerSettings;
 
1449
    CPUUpdateRenderBuffers(false);
 
1450
}
 
1451
 
 
1452
EVT_HANDLER_MASK(VideoLayersOBJ, "Video layer OBJ (toggle)", CMDEN_GB|CMDEN_GBA)
 
1453
{
 
1454
    update_icheck1("VideoLayersOBJ", layerSettings, (1<<12));
 
1455
    layerEnable = DISPCNT & layerSettings;
 
1456
    CPUUpdateRenderBuffers(false);
 
1457
}
 
1458
 
 
1459
EVT_HANDLER_MASK(VideoLayersWIN0, "Video layer WIN0 (toggle)", CMDEN_GB|CMDEN_GBA)
 
1460
{
 
1461
    update_icheck1("VideoLayersWIN0", layerSettings, (1<<13));
 
1462
    layerEnable = DISPCNT & layerSettings;
 
1463
    CPUUpdateRenderBuffers(false);
 
1464
}
 
1465
 
 
1466
EVT_HANDLER_MASK(VideoLayersWIN1, "Video layer WIN1 (toggle)", CMDEN_GB|CMDEN_GBA)
 
1467
{
 
1468
    update_icheck1("VideoLayersWIN1", layerSettings, (1<<14));
 
1469
    layerEnable = DISPCNT & layerSettings;
 
1470
    CPUUpdateRenderBuffers(false);
 
1471
}
 
1472
 
 
1473
EVT_HANDLER_MASK(VideoLayersOBJWIN, "Video layer OBJWIN (toggle)", CMDEN_GB|CMDEN_GBA)
 
1474
{
 
1475
    update_icheck1("VideoLayersOBJWIN", layerSettings, (1<<15));
 
1476
    layerEnable = DISPCNT & layerSettings;
 
1477
    CPUUpdateRenderBuffers(false);
 
1478
}
 
1479
 
 
1480
// not in menu
 
1481
EVT_HANDLER_MASK(VideoLayersReset, "Show all video layers", CMDEN_GB|CMDEN_GBA)
 
1482
{
 
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); \
 
1488
            break; \
 
1489
        } \
 
1490
} while(0)
 
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);
 
1502
}
 
1503
 
 
1504
EVT_HANDLER_MASK(SoundChannel1, "Sound Channel 1 (toggle)", CMDEN_GB|CMDEN_GBA)
 
1505
{
 
1506
    update_icheck1("SoundChannel1", gopts.sound_en, (1<<0));
 
1507
    soundSetEnable(gopts.sound_en);
 
1508
    update_opts();
 
1509
}
 
1510
 
 
1511
EVT_HANDLER_MASK(SoundChannel2, "Sound Channel 2 (toggle)", CMDEN_GB|CMDEN_GBA)
 
1512
{
 
1513
    update_icheck1("SoundChannel2", gopts.sound_en, (1<<1));
 
1514
    soundSetEnable(gopts.sound_en);
 
1515
    update_opts();
 
1516
}
 
1517
 
 
1518
EVT_HANDLER_MASK(SoundChannel3, "Sound Channel 3 (toggle)", CMDEN_GB|CMDEN_GBA)
 
1519
{
 
1520
    update_icheck1("SoundChannel3", gopts.sound_en, (1<<2));
 
1521
    soundSetEnable(gopts.sound_en);
 
1522
    update_opts();
 
1523
}
 
1524
 
 
1525
EVT_HANDLER_MASK(SoundChannel4, "Sound Channel 4 (toggle)", CMDEN_GB|CMDEN_GBA)
 
1526
{
 
1527
    update_icheck1("SoundChannel4", gopts.sound_en, (1<<3));
 
1528
    soundSetEnable(gopts.sound_en);
 
1529
    update_opts();
 
1530
}
 
1531
 
 
1532
EVT_HANDLER_MASK(DirectSoundA, "Direct Sound A (toggle)", CMDEN_GBA)
 
1533
{
 
1534
    update_icheck1("DirectSoundA", gopts.sound_en, (1<<8));
 
1535
    soundSetEnable(gopts.sound_en);
 
1536
    update_opts();
 
1537
}
 
1538
 
 
1539
EVT_HANDLER_MASK(DirectSoundB, "Direct Sound B (toggle)", CMDEN_GBA)
 
1540
{
 
1541
    update_icheck1("DirectSoundB", gopts.sound_en, (1<<9));
 
1542
    soundSetEnable(gopts.sound_en);
 
1543
    update_opts();
 
1544
}
 
1545
 
 
1546
EVT_HANDLER(ToggleSound, "Enable/disable all sound channels")
 
1547
{
 
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);
 
1557
    update_opts();
 
1558
    systemScreenMessage(en ? _("Sound enabled") : _("Sound disabled"));
 
1559
}
 
1560
 
 
1561
EVT_HANDLER(IncreaseVolume, "Increase volume")
 
1562
{
 
1563
    gopts.sound_vol += 5;
 
1564
    if(gopts.sound_vol > 200)
 
1565
        gopts.sound_vol = 200;
 
1566
    update_opts();
 
1567
    soundSetVolume((float)gopts.sound_vol / 100.0);
 
1568
    wxString msg;
 
1569
    msg.Printf(_("Volume: %d%%"), gopts.sound_vol);
 
1570
    systemScreenMessage(msg);
 
1571
}
 
1572
 
 
1573
EVT_HANDLER(DecreaseVolume, "Decrease volume")
 
1574
{
 
1575
    gopts.sound_vol -= 5;
 
1576
    if(gopts.sound_vol < 0)
 
1577
        gopts.sound_vol = 0;
 
1578
    update_opts();
 
1579
    soundSetVolume((float)gopts.sound_vol / 100.0);
 
1580
    wxString msg;
 
1581
    msg.Printf(_("Volume: %d%%"), gopts.sound_vol);
 
1582
    systemScreenMessage(msg);
 
1583
}
 
1584
 
 
1585
EVT_HANDLER_MASK(NextFrame, "Next Frame", CMDEN_GB|CMDEN_GBA)
 
1586
{
 
1587
    update_check("Pause", true);
 
1588
    paused = true;
 
1589
    pause_next = true;
 
1590
    if(!IsPaused())
 
1591
        panel->Resume();
 
1592
    systemFrameSkip = 0;
 
1593
}
 
1594
 
 
1595
EVT_HANDLER_MASK(Disassemble, "Disassemble...", CMDEN_GB|CMDEN_GBA)
 
1596
{
 
1597
    Disassemble();
 
1598
}
 
1599
 
 
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)
 
1603
{
 
1604
    wxDialog *dlg = wxGetApp().frame->logdlg;
 
1605
    dlg->Show();
 
1606
    dlg->Raise();
 
1607
}
 
1608
 
 
1609
EVT_HANDLER_MASK(IOViewer, "I/O Viewer...", CMDEN_GBA)
 
1610
{
 
1611
    IOViewer();
 
1612
}
 
1613
 
 
1614
EVT_HANDLER_MASK(MapViewer, "Map Viewer...", CMDEN_GB|CMDEN_GBA)
 
1615
{
 
1616
    MapViewer();
 
1617
}
 
1618
 
 
1619
EVT_HANDLER_MASK(MemoryViewer, "Memory Viewer...", CMDEN_GB|CMDEN_GBA)
 
1620
{
 
1621
    MemViewer();
 
1622
}
 
1623
 
 
1624
EVT_HANDLER_MASK(OAMViewer, "OAM Viewer...", CMDEN_GB|CMDEN_GBA)
 
1625
{
 
1626
    OAMViewer();
 
1627
}
 
1628
 
 
1629
EVT_HANDLER_MASK(PaletteViewer, "Palette Viewer...", CMDEN_GB|CMDEN_GBA)
 
1630
{
 
1631
    PaletteViewer();
 
1632
}
 
1633
 
 
1634
EVT_HANDLER_MASK(TileViewer, "Tile Viewer...", CMDEN_GB|CMDEN_GBA)
 
1635
{
 
1636
    TileViewer();
 
1637
}
 
1638
 
 
1639
extern int remotePort;
 
1640
 
 
1641
EVT_HANDLER_MASK(DebugGDB, "Wait for GDB connection...", CMDEN_NGDB_GBA)
 
1642
{
 
1643
    ModalPause mp;
 
1644
    int port = wxGetNumberFromUser(
 
1645
#ifdef __WXMSW__
 
1646
                                   wxEmptyString,
 
1647
#else
 
1648
                                   _("Set to 0 for pseudo tty"),
 
1649
#endif
 
1650
                                   _("Port to wait for connection:"),
 
1651
                                   _("GDB Connection"), remotePort,
 
1652
#ifdef __WXMSW__
 
1653
                                   1025,
 
1654
#else
 
1655
                                   0,
 
1656
#endif
 
1657
                                   65535, this);
 
1658
    if(port < 0)
 
1659
        return;
 
1660
    remotePort = port;
 
1661
    wxString msg;
 
1662
#ifndef __WXMSW__
 
1663
    if(!port) {
 
1664
        if(!debugOpenPty())
 
1665
            return;
 
1666
        msg.Printf(_("Waiting for connection at %s"), debugGetSlavePty().c_str());
 
1667
    } else
 
1668
#endif
 
1669
    {
 
1670
        if(!debugStartListen(port))
 
1671
            return;
 
1672
        msg.Printf(_("Waiting for connection on port %d"), port);
 
1673
    }
 
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()) {
 
1678
#ifndef __WXMSW__
 
1679
        if(!port)
 
1680
            connected = debugWaitPty();
 
1681
        else
 
1682
#endif
 
1683
            connected = debugWaitSocket();
 
1684
        if(connected)
 
1685
            break;
 
1686
        // sleep a bit more in case of infinite loop
 
1687
        wxMilliSleep(10);
 
1688
    }
 
1689
    if(!connected)
 
1690
        remoteCleanUp();
 
1691
    else {
 
1692
        debugger = true;
 
1693
        dbgMain = remoteStubMain;
 
1694
        dbgSignal = remoteStubSignal;
 
1695
        dbgOutput = remoteOutput;
 
1696
        cmd_enable &= ~(CMDEN_NGDB_ANY|CMDEN_NGDB_GBA);
 
1697
        cmd_enable |= CMDEN_GDB;
 
1698
        enable_menus();
 
1699
    }
 
1700
}
 
1701
 
 
1702
EVT_HANDLER_MASK(DebugGDBLoad, "Load and wait for GDB...", CMDEN_NGDB_ANY)
 
1703
{
 
1704
    wxCommandEvent ev;
 
1705
    ModalPause mp;
 
1706
    OnwxID_OPEN(ev);
 
1707
    if(wxGetApp().pending_load.empty())
 
1708
        return;
 
1709
    panel->UnloadGame();
 
1710
    DoDebugGDB();
 
1711
}
 
1712
 
 
1713
EVT_HANDLER_MASK(DebugGDBBreak, "Break into GDB", CMDEN_GDB)
 
1714
{
 
1715
    if(armState) {
 
1716
        armNextPC -= 4;
 
1717
        reg[15].I -= 4;
 
1718
    } else {
 
1719
        armNextPC -= 2;
 
1720
        reg[15].I -= 2;
 
1721
    }
 
1722
    debugger = true;
 
1723
}
 
1724
 
 
1725
EVT_HANDLER_MASK(DebugGDBDisconnect, "Disconnect GDB", CMDEN_GDB)
 
1726
{
 
1727
    debugger = false;
 
1728
    dbgMain = NULL;
 
1729
    dbgSignal = NULL;
 
1730
    dbgOutput = NULL;
 
1731
    remoteCleanUp();
 
1732
    cmd_enable &= ~CMDEN_GDB;
 
1733
    cmd_enable |= CMDEN_NGDB_GBA|CMDEN_NGDB_ANY;
 
1734
    enable_menus();
 
1735
}
 
1736
 
 
1737
 
 
1738
// Options menu
 
1739
EVT_HANDLER(GeneralConfigure, "General options...")
 
1740
{
 
1741
    int rew = gopts.rewind_interval;
 
1742
    wxDialog *dlg = GetXRCDialog("GeneralConfig");
 
1743
    if(ShowModal(dlg) == wxID_OK)
 
1744
        update_opts();
 
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;
 
1751
                enable_menus();
 
1752
            }
 
1753
            panel->num_rewind_states = 0;
 
1754
            panel->do_rewind = false;
 
1755
        } else {
 
1756
            if(!panel->num_rewind_states)
 
1757
                panel->do_rewind = true;
 
1758
            panel->rewind_time = gopts.rewind_interval * 6;
 
1759
        }
 
1760
    }
 
1761
}
 
1762
 
 
1763
EVT_HANDLER(GameBoyConfigure, "Game Boy options...")
 
1764
{
 
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)
 
1770
        c->SetSelection(0);
 
1771
    else if(gbBorderOn)
 
1772
        c->SetSelection(1);
 
1773
    else
 
1774
        c->SetSelection(2);
 
1775
    if(ShowModal(dlg) != wxID_OK)
 
1776
        return;
 
1777
    switch(c->GetSelection()) {
 
1778
    case 0:
 
1779
        gbBorderOn = gbBorderAutomatic = false;
 
1780
        break;
 
1781
    case 1:
 
1782
        gbBorderOn = true;
 
1783
        break;
 
1784
    case 2:
 
1785
        gbBorderOn = false;
 
1786
        gbBorderAutomatic = true;
 
1787
        break;
 
1788
    }
 
1789
    // this value might have been overwritten by FrameSkip
 
1790
    if(XRCCTRL(*dlg, "FrameSkipAuto", wxCheckBox)->GetValue())
 
1791
        gopts.gb_frameskip = -1;
 
1792
    update_opts();
 
1793
    if(panel->game_type() == IMAGE_GB) {
 
1794
        if(borderon != gbBorderOn) {
 
1795
            if(gbBorderOn) {
 
1796
                panel->AddBorder();
 
1797
                gbSgbRenderBorder();
 
1798
            } else
 
1799
                panel->DelBorder();
 
1800
        }
 
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]));
 
1806
    }
 
1807
    if(printeron != gopts.gbprint) {
 
1808
        if(gopts.gbprint)
 
1809
            gbSerialFunction = gbPrinterSend;
 
1810
        else
 
1811
            gbSerialFunction = NULL;
 
1812
    }
 
1813
}
 
1814
 
 
1815
EVT_HANDLER(GameBoyAdvanceConfigure, "Game Boy Advance options...")
 
1816
{
 
1817
    wxDialog *dlg = GetXRCDialog("GameBoyAdvanceConfig");
 
1818
    wxTextCtrl *ovcmt = XRCCTRL(*dlg, "Comment", wxTextCtrl);
 
1819
    wxString cmt;
 
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)) {
 
1830
            cfg->SetPath(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("/"));
 
1838
        } else {
 
1839
            ovcmt->SetValue(cmt);
 
1840
            ovrtc->SetSelection(0);
 
1841
            ovst->SetSelection(0);
 
1842
            ovfs->SetSelection(0);
 
1843
            ovmir->SetSelection(0);
 
1844
        }
 
1845
    } else {
 
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);
 
1852
    }
 
1853
    if(ShowModal(dlg) != wxID_OK)
 
1854
        return;
 
1855
    // this value might have been overwritten by FrameSkip
 
1856
    if(XRCCTRL(*dlg, "FrameSkipAuto", wxCheckBox)->GetValue())
 
1857
        gopts.gba_frameskip = -1;
 
1858
    update_opts();
 
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;
 
1867
        else
 
1868
            *((u32 *)rom) = /* original value */;
 
1869
#endif
 
1870
        wxString s = wxString((const char *)&rom[0xac], wxConvLibc, 4);
 
1871
        wxFileConfig *cfg = wxGetApp().overrides;
 
1872
        bool chg;
 
1873
        if(cfg->HasGroup(s)) {
 
1874
            cfg->SetPath(s);
 
1875
            chg =
 
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("/"));
 
1882
        } else
 
1883
            chg = ovrtc->GetSelection() != 0 || ovst->GetSelection() != 0 ||
 
1884
                  ovfs->GetSelection() != 0 || ovmir->GetSelection() != 0;
 
1885
        if(chg) {
 
1886
            wxString vba_over;
 
1887
            wxFileName fn(wxStandardPaths::Get().GetUserDataDir(), wxT("vba-over.ini"));
 
1888
            if(fn.FileExists()) {
 
1889
                wxFileInputStream fis(fn.GetFullPath());
 
1890
                wxStringOutputStream sos(&vba_over);
 
1891
                fis.Read(sos);
 
1892
            }
 
1893
            if(cfg->HasGroup(s)) {
 
1894
                cfg->SetPath(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
 
1901
                    res += s;
 
1902
                    res += wxT( "\\]"
 
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
 
1906
                                ")*"
 
1907
                               ")" // end of group
 
1908
                                // no need to try to describe what's next
 
1909
                                // as the regex should maximize match size
 
1910
                              );
 
1911
                    wxRegEx re(res);
 
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)) {
 
1916
                        size_t beg, end;
 
1917
                        re.GetMatch(&beg, &end, 2);
 
1918
                        vba_over.erase(beg, end - beg);
 
1919
                    }
 
1920
                }
 
1921
                cfg->SetPath(wxT("/"));
 
1922
                cfg->DeleteGroup(s);
 
1923
            }
 
1924
            cfg->SetPath(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('['));
 
1931
            vba_over.append(s);
 
1932
            vba_over.append(wxT(']'));
 
1933
            vba_over.append(wxTextFile::GetEOL());
 
1934
            int sel;
 
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); \
 
1941
} while(0)
 
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));
 
1951
            }
 
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());
 
1959
            fos.Commit();
 
1960
        }
 
1961
    }
 
1962
}
 
1963
 
 
1964
EVT_HANDLER_MASK(DisplayConfigure, "Display options...", CMDEN_NREC_ANY)
 
1965
{
 
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;
 
1974
 
 
1975
    if(gopts.max_threads == 1)
 
1976
        gopts.max_threads = 0;
 
1977
    else {
 
1978
        gopts.max_threads = wxThread::GetCPUCount();
 
1979
        if(gopts.max_threads > 8)
 
1980
            gopts.max_threads = 8;
 
1981
    }
 
1982
    wxDialog *dlg = GetXRCDialog("DisplayConfig");
 
1983
    if(ShowModal(dlg) != wxID_OK)
 
1984
        return;
 
1985
    if(!gopts.max_threads)
 
1986
        gopts.max_threads = 1;
 
1987
    update_opts();
 
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))
 
1993
                panel->Layout();
 
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
 
1998
                // drawing panel
 
1999
                panel->panel->Delete();
 
2000
                panel->panel = NULL;
 
2001
            }
 
2002
        }
 
2003
    }
 
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);
 
2010
    }
 
2011
    if(panel->panel &&
 
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;
 
2030
    }
 
2031
}
 
2032
 
 
2033
EVT_HANDLER_MASK(ChangeFilter, "Change Pixel Filter", CMDEN_NREC_ANY)
 
2034
{
 
2035
    int filt = gopts.filter;
 
2036
    if(filt == FF_PLUGIN ||
 
2037
       ++gopts.filter == FF_PLUGIN && gopts.filter_plugin.empty())
 
2038
        gopts.filter = 0;
 
2039
    update_opts();
 
2040
    if(panel->panel &&
 
2041
       builtin_ff_scale(filt) != builtin_ff_scale(gopts.filter)) {
 
2042
        panel->panel->Delete();
 
2043
        panel->panel = NULL;
 
2044
    }
 
2045
}
 
2046
 
 
2047
EVT_HANDLER_MASK(ChangeIFB, "Change Interframe Blending", CMDEN_NREC_ANY)
 
2048
{
 
2049
    gopts.ifb = (gopts.ifb + 1) % 3;
 
2050
    update_opts();
 
2051
    if(panel->panel &&
 
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;
 
2059
    }
 
2060
}
 
2061
 
 
2062
EVT_HANDLER_MASK(SoundConfigure, "Sound options...", CMDEN_NREC_ANY)
 
2063
{
 
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)
 
2069
        return;
 
2070
    update_opts();
 
2071
    switch(panel->game_type()) {
 
2072
    case IMAGE_UNKNOWN:
 
2073
        return;
 
2074
    case IMAGE_GB:
 
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)));
 
2081
        break;
 
2082
    case IMAGE_GBA:
 
2083
        soundSetSampleRate(!gopts.sound_qual ? 48000 :
 
2084
                           44100 / (1 << (gopts.sound_qual - 1)));
 
2085
        break;
 
2086
    }
 
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))) {
 
2094
        soundShutdown();
 
2095
        soundInit();
 
2096
    }
 
2097
    soundSetVolume((float)gopts.sound_vol / 100.0);
 
2098
}
 
2099
 
 
2100
EVT_HANDLER(EmulatorDirectories, "Directories...")
 
2101
{
 
2102
    wxDialog *dlg = GetXRCDialog("DirectoriesConfig");
 
2103
    if(ShowModal(dlg) == wxID_OK)
 
2104
        update_opts();
 
2105
}
 
2106
 
 
2107
EVT_HANDLER(JoypadConfigure, "Joypad options...")
 
2108
{
 
2109
    wxDialog *dlg = GetXRCDialog("JoypadConfig");
 
2110
    joy.Attach(NULL);
 
2111
    joy.Add();
 
2112
    if(ShowModal(dlg) == wxID_OK)
 
2113
        update_opts();
 
2114
    SetJoystick();
 
2115
}
 
2116
 
 
2117
// new
 
2118
EVT_HANDLER(LinkConfigure, "Link options...")
 
2119
{
 
2120
#ifndef NO_LINK
 
2121
    bool jb = gba_joybus_enabled;
 
2122
    wxString jh = gopts.joybus_host;
 
2123
    wxDialog *dlg = GetXRCDialog("LinkConfig");
 
2124
    if(ShowModal(dlg) != wxID_OK)
 
2125
        return;
 
2126
    update_opts();
 
2127
    if(jb != gba_joybus_enabled) {
 
2128
        if(gba_joybus_enabled)
 
2129
            JoyBusConnect();
 
2130
        else
 
2131
            JoyBusShutdown();
 
2132
    } else if(jh != gopts.joybus_host) {
 
2133
        joybusHostAddr = std::string(gopts.joybus_host.mb_str());
 
2134
        JoyBusConnect();
 
2135
    }
 
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;
 
2140
        } else {
 
2141
            did_link_init = false;
 
2142
            CloseLink();
 
2143
            lanlink.active = false;
 
2144
            cmd_enable &= ~CMDEN_LINK_ANY;
 
2145
        }
 
2146
        enable_menus();
 
2147
    }
 
2148
#endif
 
2149
}
 
2150
 
 
2151
EVT_HANDLER(Customize, "Customize UI...")
 
2152
{
 
2153
    wxDialog *dlg = GetXRCDialog("AccelConfig");
 
2154
    if(ShowModal(dlg) == wxID_OK)
 
2155
        update_opts();
 
2156
}
 
2157
 
 
2158
EVT_HANDLER(BugReport, "Report bugs...")
 
2159
{
 
2160
    wxLaunchDefaultBrowser(wxT("http://sourceforge.net/tracker/?group_id=212795&atid=1023154"));
 
2161
}
 
2162
 
 
2163
EVT_HANDLER(FAQ, "VBA-M support forum")
 
2164
{
 
2165
    wxLaunchDefaultBrowser(wxT("http://vba-m.com/forum/"));
 
2166
}
 
2167
 
 
2168
// was About
 
2169
EVT_HANDLER(wxID_ABOUT, "About...")
 
2170
{
 
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 ."));
 
2190
    // from gtk
 
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"));
 
2202
    // from win32
 
2203
    ai.AddDeveloper(wxT("Jonas Quinn"));
 
2204
    ai.AddDeveloper(wxT("DJRobX"));
 
2205
    ai.AddDeveloper(wxT("Spacy"));
 
2206
    ai.AddDeveloper(wxT("Squall Leonhart"));
 
2207
    // wx
 
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"));
 
2215
 
 
2216
    wxAboutBox(ai);
 
2217
}
 
2218
 
 
2219
// Dummy for disabling system key bindings
 
2220
EVT_HANDLER_MASK(NOOP, "Do nothing", CMDEN_NEVER)
 
2221
{
 
2222
}
 
2223
 
 
2224
// The following have been moved to dialogs
 
2225
// I will not implement as command unless there is great demand
 
2226
// CheatsList
 
2227
//EVT_HANDLER(CheatsLoad, "Load Cheats...")
 
2228
//EVT_HANDLER(CheatsSave, "Save Cheats...")
 
2229
//GeneralConfigure
 
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")
 
2250
// GameBoyConfigure
 
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")
 
2265
//DisplayConfigure
 
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")
 
2303
//JoypadConfigure
 
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")
 
2309
 
 
2310
// The following functionality has been removed
 
2311
// It should be done in OS, rather than in vbam
 
2312
//EVT_HANDLER(EmulatorAssociate, "EmulatorAssociate")
 
2313
 
 
2314
// The following functionality has been removed
 
2315
// It should be done at OS level (e.g. window manager)
 
2316
//EVT_HANDLER(SystemMinimize, "SystemMinimize")