1 #ifndef WX_WXVBAM_H
2 #define WX_WXVBAM_H
3
4 #include <list>
5 #include <typeinfo>
6 #include <stdexcept>
7 #include <wx/propdlg.h>
8
9 #include "wxhead.h"
10 #include "wx/sdljoy.h"
11 #include "wx/joyedit.h"
12 #include "wx/keyedit.h"
13 #include "wx/wxmisc.h"
14 #ifndef NO_FFMPEG
15 #include "../common/ffmpeg.h"
16 #endif
17
18 /* yeah, they aren't needed globally, but I'm too lazy to limit where needed */
19 #include "../System.h"
20 #include "../gba/Globals.h"
21 #include "../gb/gbGlobals.h"
22 #include "../gb/gbSound.h"
23 #include "../gb/gb.h"
24 #include "../gba/Sound.h"
25 #include "../Util.h"
26 #include "../gba/GBALink.h"
27 #include "../gb/gbCheats.h"
28 #include "../gba/Cheats.h"
29
30 template <typename T>
CheckPointer(T pointer)31 void CheckPointer(T pointer)
32 {
33 if (pointer == NULL)
34 {
35 std::string errormessage = "Pointer of type \"";
36 errormessage += typeid(pointer).name();
37 errormessage += "\" was not correctly created.";
38 throw std::runtime_error(errormessage);
39 }
40 }
41
42 ///Helper functions to convert WX's crazy string types to std::string
43
ToString(wxCharBuffer aString)44 inline std::string ToString(wxCharBuffer aString)
45 {
46 return std::string(aString);
47 }
48
ToString(const wxChar * aString)49 inline std::string ToString(const wxChar* aString)
50 {
51 return std::string(wxString(aString).mb_str(wxConvUTF8));
52 }
53
54 class MainFrame;
55
56 class wxvbamApp : public wxApp
57 {
58 public:
wxvbamApp()59 wxvbamApp() : wxApp(), pending_fullscreen(false) {}
60 virtual bool OnInit();
61 virtual void OnInitCmdLine(wxCmdLineParser &);
62 virtual bool OnCmdLineParsed(wxCmdLineParser &);
63 wxString GetConfigurationPath();
64 wxString GetAbsolutePath(wxString path);
65 // name of a file to load at earliest opportunity
66 wxString pending_load;
67 // list of options to set after config file loaded
68 wxArrayString pending_optset;
69 // set fullscreen mode after init
70 bool pending_fullscreen;
71 #if __WXMAC__
72 // I suppose making this work will require tweaking the bundle
MacOpenFile(const wxString & f)73 void MacOpenFile(const wxString &f) { pending_load = f; };
74 #endif
75 // without this, global accels don't always work
76 int FilterEvent(wxEvent &event);
77 wxAcceleratorEntry_v accels;
78
79 // the main configuration
80 wxFileConfig* cfg;
81 // vba-over.ini
82 wxFileConfig* overrides;
83
84 wxFileName rom_database;
85 wxFileName rom_database_scene;
86 wxFileName rom_database_nointro;
87
88 wxString data_path;
89
90 MainFrame* frame;
91 // use this to get ms since program lauch
92 wxStopWatch timer;
93 // append log messages to this for the log viewer
94 wxString log;
95 // there's no way to retrieve "current" locale, so this is public
96 wxLocale locale;
97
98 //Handle most exceptions
OnExceptionInMainLoop()99 virtual bool OnExceptionInMainLoop()
100 {
101 try {throw;}
102 catch (const std::exception &e)
103 {
104 std::cerr << "AN ERROR HAS OCCURRED: " << e.what() << std::endl;
105 return false;
106 }
107 }
108 private:
109 wxPathList config_path;
110 char* home;
111 };
112
113 DECLARE_APP(wxvbamApp);
114
115 // menu event handlers are declared with these macros in mainwind.cpp
116 // and mainwind-handlers.h, mainwind-cmd.cpp, and mainwind-evt.cpp are
117 // auto-generated from them
118 #define EVT_HANDLER(n, x) \
119 void MainFrame::On##n(wxCommandEvent& WXUNUSED(event))
120 // some commands are masked under some conditions
121 #define EVT_HANDLER_MASK(n, x, m) \
122 void MainFrame::On##n(wxCommandEvent& WXUNUSED(event)) \
123 { \
124 if(!(cmd_enable & (m))) \
125 return; \
126 Do##n(); \
127 } \
128 void MainFrame::Do##n() \
129
130 // here are those conditions
131 enum
132 {
133 CMDEN_GB = (1 << 0), // GB ROM loaded
134 CMDEN_GBA = (1 << 1), // GBA ROM loaded
135 // the rest imply the above, unless:
136 // _ANY -> does not imply either
137 // _GBA -> only implies GBA
138 CMDEN_REWIND = (1 << 2), // rewind states available
139 CMDEN_SREC = (1 << 3), // sound recording in progress
140 CMDEN_NSREC = (1 << 4), // no sound recording
141 CMDEN_VREC = (1 << 5), // video recording
142 CMDEN_NVREC = (1 << 6), // no video recording
143 CMDEN_GREC = (1 << 7), // game recording
144 CMDEN_NGREC = (1 << 8), // no game recording
145 CMDEN_GPLAY = (1 << 9), // game playback
146 CMDEN_NGPLAY = (1 << 10), // no game playback
147 CMDEN_SAVST = (1 << 11), // any save states
148 CMDEN_GDB = (1 << 12), // gdb connected
149 CMDEN_NGDB_GBA = (1 << 13), // gdb not connected
150 CMDEN_NGDB_ANY = (1 << 14), // gdb not connected
151 CMDEN_NREC_ANY = (1 << 15), // not a/v recording
152 CMDEN_LINK_ANY = (1 << 16), // link enabled
153
154 CMDEN_NEVER = (1 << 31) // never (for NOOP)
155 };
156 #define ONLOAD_CMDEN (CMDEN_NSREC|CMDEN_NVREC|CMDEN_NGREC|CMDEN_NGPLAY)
157 #define UNLOAD_CMDEN_KEEP (CMDEN_NGDB_ANY|CMDEN_NREC_ANY|CMDEN_LINK_ANY)
158
159 struct checkable_mi_t
160 {
161 int cmd;
162 wxMenuItem* mi;
163 bool* boolopt;
164 int* intopt, mask, val;
165 };
166
167 // wxArray is only for small types
168 typedef std::vector<checkable_mi_t> checkable_mi_array_t;
169
170 typedef std::list<wxDialog*> dialog_list_t;
171
172 class GameArea;
173
174 class LogDialog;
175
176 // true if pause should happen at next frame
177 extern bool pause_next;
178
179 class MainFrame : public wxFrame
180 {
181 public:
182 MainFrame();
183 ~MainFrame();
184
185 bool BindControls();
186 void MenuOptionIntMask(const char* menuName, int &field, int mask);
187 void MenuOptionIntRadioValue(const char* menuName, int &field, int mask);
188 void MenuOptionBool(const char* menuName, bool &field);
189 void GetMenuOptionInt(const char* menuName, int &field, int mask);
190 void GetMenuOptionBool(const char* menuName, bool &field);
191 void SetMenuOption(const char* menuName, int value);
192
193 void SetJoystick();
194
GetPanel()195 GameArea* GetPanel() { return panel; }
196
197 wxString GetGamePath(wxString path);
198
199 // wxMSW pauses the game for menu popups and modal dialogs, but wxGTK
200 // does not. It's probably desirable to pause the game. To do this for
201 // dialogs, use this function instead of dlg->ShowModal()
202 int ShowModal(wxDialog* dlg);
203 // and here are the wrapper functions for use when ShowModal() isn't
204 // possible
205 void StartModal();
206 void StopModal();
207 // however, adding a handler for open/close menu to do the same is unsafe.
208 // there is no guarantee every show will be matched by a hide.
209 void MenuPopped(wxMenuEvent &evt);
210
211 // flags for enabling commands
212 int cmd_enable;
213
214 // adjust menus based on current cmd_enable
215 void enable_menus();
216 void EnableNetworkMenu();
217
218 // adjust menus based on available save game states
219 void update_state_ts(bool force = false);
220
221 // retrieve oldest/newest slot
222 // returns lowest-numbered slot on ties
223 int oldest_state_slot(); // or empty slot if available
224 int newest_state_slot(); // or 0 if none
225
226 // system-defined accelerators
227 wxAcceleratorEntry_v sys_accels;
228 // adjust recent menu with accelerators
229 void SetRecentAccels();
230 // merge sys accels with user-defined accels (user overrides sys)
231 wxAcceleratorEntry_v get_accels(wxAcceleratorEntry_v user_accels);
232 // update menu and global accelerator table with sys+user accel defs
233 // probably not the quickest way to add/remove individual accels
234 void set_global_accels();
235
236 // 2.8 has no HasFocus(), and FindFocus() doesn't work right
HasFocus()237 bool HasFocus() { return focused; }
238
239 // Returns the link mode to set according to the options
240 LinkMode GetConfiguredLinkMode();
241
242 void IdentifyRom();
243
244 // Start GDB listener
245 void GDBBreak();
246
247 // The various viewer popups; these can be popped up as often as
248 // desired
249 void Disassemble();
250 void IOViewer();
251 void MapViewer();
252 void MemViewer();
253 void OAMViewer();
254 void PaletteViewer();
255 void TileViewer();
256
257 // since they will all have to be destroyed on game unload:
258 dialog_list_t popups;
259
260 // this won't actually be destroyed, but it needs to be tracked so only
261 // one is ever up and it needs to be pinged when new messages arrive
262 LogDialog* logdlg;
263
264 // the cheat search dialog isn't destroyed or tracked, but it needs
265 // to be cleared between games
266 void ResetCheatSearch();
267
268 // call this to update the viewers once a frame:
269 void UpdateViewers();
270
271 // Check for online updates to the emulator
272 bool CheckForUpdates();
273
274 // required for building from xrc
275 DECLARE_DYNAMIC_CLASS();
276 // required for event handling
277 DECLARE_EVENT_TABLE();
278
279 bool IsPaused(bool incendental = false)
280 {
281 return (paused && !pause_next && !incendental) || menus_opened || dialog_opened;
282 }
283 private:
284 GameArea* panel;
285
286 // the various reasons the game might be paused
287 bool paused;
288 int menus_opened, dialog_opened;
289
290 bool autoLoadMostRecent;
291 // copy of top-level menu bar as a context menu
292 wxMenu* ctx_menu;
293 // load/save states menu items
294 wxMenuItem* loadst_mi[10];
295 wxMenuItem* savest_mi[10];
296 wxDateTime state_ts[10];
297 // checkable menu items
298 checkable_mi_array_t checkable_mi;
299 // recent menu item accels
300 wxMenu* recent;
301 wxAcceleratorEntry recent_accel[10];
302 // joystick reader
303 wxSDLJoy joy;
304
305 // helper function for adding menu to accel editor
306 void add_menu_accels(wxTreeCtrl* tc, wxTreeItemId &parent, wxMenu* menu);
307
308 // for detecting window focus
309 void OnActivate(wxActivateEvent &);
310 // quicker & more accurate than FindFocus() != NULL
311 bool focused;
312 // may work, may not... if so, load dropped file
313 void OnDropFile(wxDropFilesEvent &);
314 // pop up menu in fullscreen mode
315 void OnMenu(wxContextMenuEvent &);
316 // Load a named wxDialog from the XRC file
317 wxDialog* LoadXRCDialog(const char* name);
318 // Load a named wxDialog from the XRC file
319 wxDialog* LoadXRCropertySheetDialog(const char* name);
320
321 void DownloadFile(wxString host, wxString url);
322 void UpdateFile(wxString host, wxString url);
323 wxString CheckForUpdates(wxString host, wxString url);
324
325 #include "cmdhandlers.h"
326 };
327
328 // a helper class to avoid forgetting StopModal()
329 class ModalPause
330 {
331 public:
ModalPause()332 ModalPause() { wxGetApp().frame->StartModal(); }
~ModalPause()333 ~ModalPause() { wxGetApp().frame->StopModal(); }
334 };
335
336 enum showspeed
337 {
338 // this order must match order of option enum and selector widget
339 SS_NONE, SS_PERCENT, SS_DETAILED
340 };
341
342 enum filtfunc
343 {
344 // this order must match order of option enum and selector widget
345 FF_NONE, FF_2XSAI, FF_SUPER2XSAI, FF_SUPEREAGLE, FF_PIXELATE,
346 FF_ADVMAME, FF_BILINEAR, FF_BILINEARPLUS, FF_SCANLINES, FF_TV,
347 FF_HQ2X, FF_LQ2X, FF_SIMPLE2X, FF_SIMPLE3X, FF_HQ3X, FF_SIMPLE4X,
348 FF_HQ4X, FF_XBRZ2X, FF_XBRZ3X, FF_XBRZ4X, FF_XBRZ5X, FF_XBRZ6X, FF_PLUGIN // plugin must always be last
349 };
350 #define builtin_ff_scale(x) \
351 ((x == FF_XBRZ6X) ? 6 : \
352 (x == FF_XBRZ5X) ? 5 : \
353 (x == FF_XBRZ4X || x == FF_HQ4X || x == FF_SIMPLE4X) ? 4 : \
354 (x == FF_XBRZ3X || x == FF_HQ3X || x == FF_SIMPLE3X) ? 3 : \
355 x == FF_PLUGIN ? 0 : x == FF_NONE ? 1 : 2)
356
357 enum ifbfunc
358 {
359 // this order must match order of option enum and selector widget
360 IFB_NONE, IFB_SMART, IFB_MOTION_BLUR
361 };
362
363 // make sure and keep this in sync with opts.cpp!
364 enum renderer
365 {
366 RND_SIMPLE, RND_OPENGL, RND_CAIRO, RND_DIRECT3D
367 };
368
369 // likewise
370 enum audioapi
371 {
372 AUD_SDL, AUD_OPENAL, AUD_DIRECTSOUND, AUD_XAUDIO2
373 };
374
375 // an unfortunate legacy default; should have a non-digit preceding %d
376 // the only reason to keep it is that user can set slotdir to old dir
377 // otoh, we already make some name changes (double ext strip), and
378 // rename is not that hard (esp. under UNIX), so I'm going ahead with a new
379 // name.
380 //#define SAVESLOT_FMT wxT("%s%d.sgm")
381 #define SAVESLOT_FMT wxT("%s-%02d.sgm")
382
383 // display time, in ms
384 #define OSD_TIME 3000
385
386 class DrawingPanel;
387
388 class GameArea : public wxPanel
389 {
390 public:
391 GameArea();
392 virtual ~GameArea();
393
394 // set to game title + link info
395 void SetFrameTitle();
396
397 void LoadGame(const wxString &name);
398 void UnloadGame(bool destruct = false);
399
game_type()400 IMAGE_TYPE game_type() { return loaded; }
game_size()401 u32 game_size() { return rom_size; }
game_dir()402 wxString game_dir() { return loaded_game.GetPath(); }
game_name()403 wxString game_name() { return loaded_game.GetFullName(); }
bat_dir()404 wxString bat_dir() { return batdir; }
state_dir()405 wxString state_dir() { return statedir; }
406 void recompute_dirs();
407
408 bool LoadState();
409 bool LoadState(int slot);
410 bool LoadState(const wxFileName &fname);
411
412 bool SaveState();
413 bool SaveState(int slot);
414 bool SaveState(const wxFileName &fname);
415
416 // save to default location
417 void SaveBattery(bool quiet = false);
418
419 // true if file at default location may not match memory
420 bool cheats_dirty;
421
422 static const int GBWidth = 160, GBHeight = 144,
423 SGBWidth = 256, SGBHeight = 224,
424 GBAWidth = 240, GBAHeight = 160;
425 void AddBorder();
426 void DelBorder();
427 // Delete() & set to NULL to force reinit
428 DrawingPanel* panel;
429 struct EmulatedSystem* emusys;
430
431 // pause game or signal a long operation, similar to pausing
432 void Pause();
433 void Resume();
434
435 // true if paused since last reset of flag
436 bool was_paused;
437
438 // osdstat is always displayed at top-left of screen
439 wxString osdstat;
440
441 // osdtext is displayed for 3 seconds after osdtime, and then cleared
442 wxString osdtext;
443 u32 osdtime;
444
445 // Rewind: count down to 0 and rewind
446 u32 rewind_time;
447 // Rewind: flag to OnIdle to do a rewind
448 bool do_rewind;
449 // Rewind: rewind states
450 char* rewind_mem; // should be u8, really
451 int num_rewind_states;
452 int next_rewind_state;
453
454 // Loaded rom information
455 IMAGE_TYPE loaded;
456 wxFileName loaded_game;
457 u32 rom_crc32;
458 wxString rom_name;
459 wxString rom_scene_rls;
460 wxString rom_scene_rls_name;
461 u32 rom_size;
462
463 // FIXME: size this properly
464 #define NUM_REWINDS 8
465 #define REWIND_SIZE 1024*512*NUM_REWINDS
466 // FIXME: make this a config option
467
468 void ShowFullScreen(bool full);
IsFullScreen()469 bool IsFullScreen() { return fullscreen; }
470 // set size of frame & panel to scaled screen size
471 void AdjustSize(bool force);
472 #ifndef NO_FFMPEG
473 void StartSoundRecording(const wxString &fname);
474 void StopSoundRecording();
475 void StartVidRecording(const wxString &fname);
476 void StopVidRecording();
477 void AddFrame(const u8* data); // video
478 void AddFrame(const u16* data, int length); // audio
IsRecording()479 bool IsRecording() { return snd_rec.IsRecording() || vid_rec.IsRecording(); }
480 #endif
481 void StartGameRecording(const wxString &fname);
482 void StopGameRecording();
483 void StartGamePlayback(const wxString &fname);
484 void StopGamePlayback();
485
486 protected:
487 // set minsize of frame & panel to unscaled screen size
488 void LowerMinSize();
489 // set minsize of frame & panel to scaled screen size
490 void AdjustMinSize();
491
492 wxString batdir, statedir;
493
494 int basic_width, basic_height;
495 bool fullscreen;
496
497 bool paused;
498 void OnIdle(wxIdleEvent &);
499 void OnKeyDown(wxKeyEvent &ev);
500 void OnKeyUp(wxKeyEvent &ev);
501 void OnSDLJoy(wxSDLJoyEvent &ev);
502
503 #ifndef NO_FFMPEG
504 MediaRecorder snd_rec, vid_rec;
505 #endif
506
507 public:
508 void ShowPointer();
509 void HidePointer();
510 protected:
MouseEvent(wxMouseEvent &)511 void MouseEvent(wxMouseEvent &) { ShowPointer(); }
512 bool pointer_blanked;
513 u32 mouse_active_time;
514
515 DECLARE_DYNAMIC_CLASS()
516 DECLARE_EVENT_TABLE()
517 };
518
519 // wxString version of OSD message
520 void systemScreenMessage(const wxString &msg);
521
522 // List of all commands with their descriptions
523 // sorted by cmd field for binary searching
524 // filled in by copy-events.cmake
525 extern struct cmditem
526 {
527 const wxChar* cmd, *name;
528 int cmd_id;
529 int mask_flags; // if non-0, one of the flags must be turned on in win
530 // to enable this command
531 wxMenuItem* mi; // the menu item to invoke command, if present
532 } cmdtab[];
533 extern const int ncmds;
534 // for binary search
535 extern bool cmditem_lt(const struct cmditem &cmd1, const struct cmditem &cmd2);
536
537 #include <wx/dynlib.h>
538 #include "../win32/rpi.h"
539
540 class FilterThread;
541
542 class DrawingPanel : public wxObject
543 {
544 public:
545 DrawingPanel(int _width, int _height);
546 ~DrawingPanel();
547 void DrawArea(u8** pixels);
548 // the following wouldn't be necessary with virtual inheritance
549 virtual wxWindow* GetWindow() = 0;
550 virtual void Delete() = 0;
551
552 protected:
553 virtual void DrawArea(wxWindowDC &) = 0;
554 virtual void DrawOSD(wxWindowDC &);
555 int width, height, scale;
556 u8* todraw;
557 u8* pixbuf1, *pixbuf2;
558 FilterThread* threads;
559 int nthreads;
560 wxSemaphore filt_done;
561 wxDynamicLibrary filt_plugin;
562 const RENDER_PLUGIN_INFO* rpi; // also flag indicating plugin loaded
563 // largest buffer required is 32-bit * (max width + 1) * (max height + 2)
564 u8 delta[257 * 4 * 226];
565
566 // following can't work in 2.8 as intended
567 // inheriting from wxEvtHandler is required, but also breaks subclasses
568 // due to lack of virtual inheritance (2.9 drops wxEvtHandler req)
569 // so each child must have a paint event handler (not override of this,
570 // but it's not virtual anyway, so that won't happen) that calls this
571 void PaintEv(wxPaintEvent &ev);
572
573 DECLARE_ABSTRACT_CLASS()
574 };
575
576 class LogDialog : public wxDialog
577 {
578 public:
579 LogDialog();
580 void Update();
581 private:
582 wxTextCtrl* log;
583 void Save(wxCommandEvent &ev);
584 void Clear(wxCommandEvent &ev);
585
586 DECLARE_EVENT_TABLE()
587 };
588
589 #include "opts.h"
590
591 class SoundDriver;
592 extern SoundDriver* newOpenAL();
593 // I should add this to SoundDriver, but wxArrayString is wx-specific
594 // I suppose I could make subclass wxSoundDriver. maybe later.
595 extern bool GetOALDevices(wxArrayString &names, wxArrayString &ids);
596 #ifdef __WXMSW__
597 extern SoundDriver* newDirectSound();
598 extern bool GetDSDevices(wxArrayString &names, wxArrayString &ids);
599 extern SoundDriver* newXAudio2_Output();
600 extern bool GetXA2Devices(wxArrayString &names, wxArrayString &ids);
601 #endif
602
603 extern bool debugger;
604 extern void (*dbgMain)();
605 extern void (*dbgSignal)(int, int);
606 extern void (*dbgOutput)(const char*, u32);
607 extern void remoteStubMain();
608 extern void remoteCleanUp();
609 extern void remoteStubSignal(int, int);
610 extern void remoteOutput(const char*, u32);
611
612 extern bool debugOpenPty();
613 extern const wxString &debugGetSlavePty();
614 extern bool debugWaitPty();
615 extern bool debugStartListen(int port);
616 extern bool debugWaitSocket();
617
618 // perhaps these functions should not be called systemXXX
619 // perhaps they should move to panel.cpp/GameArea
620 // but they must integrate with systemReadJoypad
621 void systemStartGameRecording(const wxString &fname);
622 void systemStopGameRecording();
623 void systemStartGamePlayback(const wxString &fname);
624 void systemStopGamePlayback();
625
626 // true if turbo mode (like pressing turbo button constantly)
627 extern bool turbo;
628
629 // mask of key press flags; see below
630 extern int joypress[4], autofire;
631
632 // FIXME: these defines should be global to project and used instead of raw numbers
633 #define KEYM_A (1<<0)
634 #define KEYM_B (1<<1)
635 #define KEYM_SELECT (1<<2)
636 #define KEYM_START (1<<3)
637 #define KEYM_RIGHT (1<<4)
638 #define KEYM_LEFT (1<<5)
639 #define KEYM_UP (1<<6)
640 #define KEYM_DOWN (1<<7)
641 #define KEYM_R (1<<8)
642 #define KEYM_L (1<<9)
643 #define KEYM_SPEED (1<<10)
644 #define KEYM_CAPTURE (1<<11)
645 #define KEYM_GS (1<<12)
646
647 // actually, the wx port adds the following, which could be local:
648 #define REALKEY_MASK ((1<<13)-1)
649
650 #define KEYM_AUTO_A (1<<13)
651 #define KEYM_AUTO_B (1<<14)
652 #define KEYM_MOTION_UP (1<<15)
653 #define KEYM_MOTION_DOWN (1<<16)
654 #define KEYM_MOTION_LEFT (1<<17)
655 #define KEYM_MOTION_RIGHT (1<<18)
656 #define KEYM_MOTION_IN (1<<19)
657 #define KEYM_MOTION_OUT (1<<20)
658
659 #include "filters.h"
660
661 #endif /* WX_WXVBAM_H */
662