From 328c6db22ed5e6a92e232ab3cd1aa788a1535e9c Mon Sep 17 00:00:00 2001 From: "simon.kagstrom" Date: Mon, 25 Jan 2010 13:01:22 +0000 Subject: [PATCH] Copy in the new GUI code. Builds but will not work now. --- Makefile.host | 12 +- Src/C64.cpp | 4 +- Src/C64.h | 36 +- Src/C64_SC.cpp | 1 + Src/C64_SDL.h | 386 +-------------- Src/Display_SDL.h | 4 +- Src/Network.cpp | 3 +- Src/Prefs.h | 8 + Src/gui/Makefile | 44 ++ Src/gui/bind_keys_menu.cpp | 468 +++++++++++++++++++ Src/gui/dialogue_box.cpp | 72 +++ Src/gui/dialogue_box.hh | 38 ++ Src/gui/disc_menu.cpp | 186 ++++++++ Src/gui/file_browser.hh | 57 +++ Src/gui/font.hh | 35 ++ Src/gui/game_info.cpp | 200 ++++++++ Src/gui/game_info.hh | 53 +++ Src/gui/game_info_box.hh | 102 ++++ Src/gui/game_info_menu.cpp | 115 +++++ Src/gui/gui.cpp | 414 ++++++++++++++++ Src/gui/gui.hh | 134 ++++++ Src/gui/gui_view.hh | 22 + Src/gui/help_box.hh | 41 ++ Src/gui/listener.cpp | 38 ++ Src/gui/listener.hh | 34 ++ Src/gui/main.cpp | 69 +++ Src/gui/main_menu.cpp | 182 ++++++++ Src/gui/menu.cpp | 373 +++++++++++++++ Src/gui/menu.hh | 108 +++++ Src/gui/menu_messages.cpp | 258 ++++++++++ Src/gui/menu_messages.hh | 21 + Src/gui/mocks/C64.h | 59 +++ Src/gui/mocks/Network.h | 9 + Src/gui/mocks/Prefs.h | 61 +++ Src/gui/network_menu.cpp | 174 +++++++ Src/gui/options_menu.cpp | 154 ++++++ Src/gui/save_game_menu.cpp | 143 ++++++ Src/gui/sdl_ttf_font.hh | 63 +++ Src/gui/status_bar.cpp | 70 +++ Src/gui/status_bar.hh | 37 ++ Src/gui/theme_menu.cpp | 99 ++++ Src/gui/themes/default/background.png | Bin 0 -> 13879 bytes Src/gui/themes/default/bg_left.png | Bin 0 -> 289 bytes Src/gui/themes/default/bg_middle.png | Bin 0 -> 186 bytes Src/gui/themes/default/bg_right.png | Bin 0 -> 321 bytes Src/gui/themes/default/bg_submenu_left.png | Bin 0 -> 312 bytes Src/gui/themes/default/bg_submenu_middle.png | Bin 0 -> 207 bytes Src/gui/themes/default/bg_submenu_right.png | Bin 0 -> 341 bytes Src/gui/themes/default/dialogue_box.png | Bin 0 -> 2107 bytes Src/gui/themes/default/disc_info.png | Bin 0 -> 2201 bytes Src/gui/themes/default/font.ttf | Bin 0 -> 320812 bytes Src/gui/themes/default/highlighted_key.png | Bin 0 -> 413 bytes Src/gui/themes/default/infobox.png | Bin 0 -> 1731 bytes Src/gui/themes/default/main_menu_bg.png | Bin 0 -> 2267 bytes Src/gui/themes/default/selected_key.png | Bin 0 -> 331 bytes Src/gui/themes/default/status_bar.png | Bin 0 -> 473 bytes Src/gui/themes/default/textbox.png | Bin 0 -> 1604 bytes Src/gui/timer.cpp | 68 +++ Src/gui/timer.hh | 46 ++ Src/gui/utils.cpp | 273 +++++++++++ Src/gui/utils.hh | 82 ++++ Src/gui/virtual_keyboard.cpp | 440 +++++++++++++++++ Src/gui/virtual_keyboard.hh | 100 ++++ Src/gui/widget.cpp | 76 +++ Src/gui/widget.hh | 42 ++ Src/main_wii.h | 2 - Src/main_x.h | 7 +- 67 files changed, 5109 insertions(+), 414 deletions(-) create mode 100644 Src/gui/Makefile create mode 100644 Src/gui/bind_keys_menu.cpp create mode 100644 Src/gui/dialogue_box.cpp create mode 100644 Src/gui/dialogue_box.hh create mode 100644 Src/gui/disc_menu.cpp create mode 100644 Src/gui/file_browser.hh create mode 100644 Src/gui/font.hh create mode 100644 Src/gui/game_info.cpp create mode 100644 Src/gui/game_info.hh create mode 100644 Src/gui/game_info_box.hh create mode 100644 Src/gui/game_info_menu.cpp create mode 100644 Src/gui/gui.cpp create mode 100644 Src/gui/gui.hh create mode 100644 Src/gui/gui_view.hh create mode 100644 Src/gui/help_box.hh create mode 100644 Src/gui/listener.cpp create mode 100644 Src/gui/listener.hh create mode 100644 Src/gui/main.cpp create mode 100644 Src/gui/main_menu.cpp create mode 100644 Src/gui/menu.cpp create mode 100644 Src/gui/menu.hh create mode 100644 Src/gui/menu_messages.cpp create mode 100644 Src/gui/menu_messages.hh create mode 100644 Src/gui/mocks/C64.h create mode 100644 Src/gui/mocks/Network.h create mode 100644 Src/gui/mocks/Prefs.h create mode 100644 Src/gui/network_menu.cpp create mode 100644 Src/gui/options_menu.cpp create mode 100644 Src/gui/save_game_menu.cpp create mode 100644 Src/gui/sdl_ttf_font.hh create mode 100644 Src/gui/status_bar.cpp create mode 100644 Src/gui/status_bar.hh create mode 100644 Src/gui/theme_menu.cpp create mode 100644 Src/gui/themes/default/background.png create mode 100644 Src/gui/themes/default/bg_left.png create mode 100644 Src/gui/themes/default/bg_middle.png create mode 100644 Src/gui/themes/default/bg_right.png create mode 100644 Src/gui/themes/default/bg_submenu_left.png create mode 100644 Src/gui/themes/default/bg_submenu_middle.png create mode 100644 Src/gui/themes/default/bg_submenu_right.png create mode 100644 Src/gui/themes/default/dialogue_box.png create mode 100644 Src/gui/themes/default/disc_info.png create mode 100644 Src/gui/themes/default/font.ttf create mode 100644 Src/gui/themes/default/highlighted_key.png create mode 100644 Src/gui/themes/default/infobox.png create mode 100644 Src/gui/themes/default/main_menu_bg.png create mode 100644 Src/gui/themes/default/selected_key.png create mode 100644 Src/gui/themes/default/status_bar.png create mode 100644 Src/gui/themes/default/textbox.png create mode 100644 Src/gui/timer.cpp create mode 100644 Src/gui/timer.hh create mode 100644 Src/gui/utils.cpp create mode 100644 Src/gui/utils.hh create mode 100644 Src/gui/virtual_keyboard.cpp create mode 100644 Src/gui/virtual_keyboard.hh create mode 100644 Src/gui/widget.cpp create mode 100644 Src/gui/widget.hh diff --git a/Makefile.host b/Makefile.host index 527ec78..a3fa751 100644 --- a/Makefile.host +++ b/Makefile.host @@ -24,7 +24,7 @@ datadir = ${PREFIX}/share #GCOV=-fprofile-arcs -ftest-coverage -CFLAGS ?=-ggdb -Iinclude -Wall `sdl-config --cflags` +CFLAGS ?=-ggdb -Wall `sdl-config --cflags` -ISrc DEFINES =-DFRODO_SC -DHAVE_CONFIG_H -DDATADIR=\"$(datadir)/frodo/\" -DBINDIR=\"$(bindir)/\" -DHAVE_SDL LDFLAGS ?= $(GCOV) `sdl-config --libs` -lSDL_ttf -lSDL_image @@ -32,11 +32,13 @@ LDFLAGS ?= $(GCOV) `sdl-config --libs` -lSDL_ttf -lSDL_image CPP_SRCS=Src/C64_SC.cpp Src/main.cpp Src/Display.cpp Src/Prefs.cpp Src/SID.cpp \ Src/REU.cpp Src/IEC.cpp Src/1541fs.cpp Src/1541d64.cpp Src/1541t64.cpp \ - Src/1541job.cpp Src/SAM.cpp Src/CPUC64_SC.cpp Src/VIC_SC.cpp Src/menu.cpp\ + Src/1541job.cpp Src/SAM.cpp Src/CPUC64_SC.cpp Src/VIC_SC.cpp \ Src/CIA_SC.cpp Src/CPU1541_SC.cpp Src/CPU_common.cpp Src/Network.cpp \ - Src/VirtualKeyboard.cpp - -C_SRCS=Src/d64-read.c Src/menutexts.c + Src/gui/menu_messages.cpp Src/gui/dialogue_box.cpp Src/gui/widget.cpp \ + Src/gui/game_info.cpp Src/gui/status_bar.cpp Src/gui/gui.cpp Src/gui/listener.cpp \ + Src/gui/timer.cpp Src/gui/utils.cpp Src/gui/virtual_keyboard.cpp Src/gui/menu.cpp + +C_SRCS=Src/d64-read.c OBJS=$(patsubst %.cpp,objs-host/%.o,$(CPP_SRCS)) $(patsubst %.c,objs-host/%.o,$(C_SRCS)) diff --git a/Src/C64.cpp b/Src/C64.cpp index 62f6ae5..9b1901a 100644 --- a/Src/C64.cpp +++ b/Src/C64.cpp @@ -530,7 +530,7 @@ bool C64::Load1541JobState(FILE *f) * snapshot is loaded into FrodoSC again. */ -void C64::SaveSnapshot(char *filename) +void C64::SaveSnapshot(const char *filename) { FILE *f; uint8 flags; @@ -595,7 +595,7 @@ void C64::SaveSnapshot(char *filename) * Load snapshot (emulation must be paused and in VBlank) */ -bool C64::LoadSnapshot(char *filename) +bool C64::LoadSnapshot(const char *filename) { FILE *f; diff --git a/Src/C64.h b/Src/C64.h index 7e39b9f..34e8019 100644 --- a/Src/C64.h +++ b/Src/C64.h @@ -21,9 +21,6 @@ #define _C64_H #if defined(HAVE_SDL) -/* SDL menu */ -#include "menu.h" -#include "VirtualKeyboard.h" #include "Network.h" #include "Prefs.h" #endif @@ -90,16 +87,24 @@ public: void Run(void); void Quit(void); - void Pause(void); - void Resume(void); + void Pause(void) + { + this->have_a_break = true; + } + + void Resume(void) + { + this->have_a_break = false; + } + void Reset(void); void NMI(void); void VBlank(bool draw_frame); void NewPrefs(Prefs *prefs); void PatchKernal(bool fast_reset, bool emul_1541_proc); void SaveRAM(char *filename); - void SaveSnapshot(char *filename); - bool LoadSnapshot(char *filename); + void SaveSnapshot(const char *filename); + bool LoadSnapshot(const char *filename); int SaveCPUState(FILE *f); int Save1541State(FILE *f); bool Save1541JobState(FILE *f); @@ -133,6 +138,11 @@ public: #ifdef FRODO_SC uint32 CycleCounter; #endif + bool IsPaused() + { + return this->have_a_break; + } + void enter_menu() { this->have_a_break = true; } @@ -201,12 +211,10 @@ public: double speed_index; #endif #ifdef HAVE_SDL - VirtualKeyboard *virtual_keyboard; char server_hostname[255]; int server_port; int network_connection_type; Network *peer; - TTF_Font *menu_font; int linecnt; bool fake_key_sequence; @@ -219,16 +227,8 @@ public: void network_vblank(); - void select_disc(Prefs *np, bool start); - void start_fake_key_sequence(const char *str); + void startFakeKeySequence(const char *str); void run_fake_key_sequence(); - char * bind_one_key(Prefs *np, int which); - void bind_keys(Prefs *np); - void select_fake_key_sequence(Prefs *np); - void advanced_options(Prefs *np); - void other_options(Prefs *np); - void networking_menu(Prefs *np); - void save_load_state(Prefs *np, int do_what); #endif #ifdef WIN32 diff --git a/Src/C64_SC.cpp b/Src/C64_SC.cpp index 29f9549..51a2ded 100644 --- a/Src/C64_SC.cpp +++ b/Src/C64_SC.cpp @@ -1,3 +1,4 @@ + /* * C64_SC.cpp - Put the pieces together (Frodo SC) * diff --git a/Src/C64_SDL.h b/Src/C64_SDL.h index ceabb98..0704308 100644 --- a/Src/C64_SDL.h +++ b/Src/C64_SDL.h @@ -10,6 +10,9 @@ #include #include +#include "gui/gui.hh" +#include "gui/virtual_keyboard.hh" + #if defined(GEKKO) #include #include @@ -24,8 +27,6 @@ #define C64_NETWORK_BROKER "c64-network.game-host.org" -#include "menutexts.h" - /* TODO: */ extern char *fixme_tmp_network_server; @@ -54,9 +55,6 @@ void C64::c64_ctor1(void) memset(this->save_game_name, 0, sizeof(this->save_game_name)); strcpy(this->save_game_name, "unknown"); - this->virtual_keyboard = new VirtualKeyboard(real_screen, this->menu_font); - virtual_keyboard = this->virtual_keyboard; - strncpy(this->server_hostname, C64_NETWORK_BROKER, sizeof(this->server_hostname)); this->server_port = 46214; @@ -85,265 +83,11 @@ void C64::c64_dtor(void) { } -void C64::select_disc(Prefs *np, bool start) -{ - const char *name; - const char *d64_name = NULL; - - if (!start) - name = menu_select_file(IMAGE_PATH); - else - name = menu_select_file_start(IMAGE_PATH, &d64_name); - - if (name== NULL) - return; - - if (strcmp(name, "None") == 0) - { - strcpy(np->DrivePath[0], "\0"); - strcpy(this->save_game_name, "unknown"); - } - else - { - const char *save_game = strrchr(name, '/'); - - if (!save_game) - save_game = name; - else - save_game = save_game + 1; /* Skip '/' */ - strncpy(np->DrivePath[0], name, 255); - strncpy(this->save_game_name, save_game, 255); - if (strstr(name, ".prg") || strstr(name, ".PRG") || - strstr(name, ".p00") || strstr(name, ".P00") || - strstr(name, ".s00") || strstr(name, ".S00")) { - FILE *src, *dst; - - /* Clean temp dir first (we only want one file) */ - unlink(TMP_PATH"/a"); - - src = fopen(np->DrivePath[0], "r"); - if (src != NULL) - { - snprintf(np->DrivePath[0], 255, "%s", TMP_PATH); - - /* Special handling of .prg: Copy to TMP_PATH and - * load that as a dir */ - dst = fopen(TMP_PATH"/a", "w"); - if (dst) - { - Uint8 buf[1024]; - size_t v; - - do { - v = fread(buf, 1, 1024, src); - fwrite(buf, 1, v, dst); - } while (v > 0); - fclose(dst); - } - fclose(src); - } - } - - NewPrefs(np); - ThePrefs = *np; - } - this->prefs_changed = true; - - /* Cleanup*/ - free((void*)name); - - /* And maybe start the game */ - if (d64_name) - { - static char buf[255]; - - snprintf(buf, 255, "\nLOAD \"%s\",8,1\nRUN\n", d64_name); - this->start_fake_key_sequence((const char*)buf); - free((void*)d64_name); - } - else if (start) - this->start_fake_key_sequence("\nLOAD \"*\",8,1\nRUN\n"); -} - - -char *C64::bind_one_key(Prefs *np, int which) -{ - static const char *which_to_button_name[N_WIIMOTE_BINDINGS] = { - "up", "down", "left", "right", - "2", "1", "A", "B", "+", "-", - "classic up", "classic down", "classic left", "classic right", "classic a", - "classic b", "classic X", "classic Y", "classic L", - "classic R", "classic ZR", "classic ZL" }; - static char strs[N_WIIMOTE_BINDINGS][255]; - char *out = strs[which]; - int cur = np->JoystickKeyBinding[which]; - - snprintf(out, 255, "Bind to %s (now %s)", which_to_button_name[which], - this->virtual_keyboard->keycode_to_string(cur)); - - return out; -} - -void C64::bind_keys(Prefs *np) -{ - const char *bind_key_messages[N_WIIMOTE_BINDINGS + 1]; - bool has_classic_controller = false; - -#if defined(GEKKO) - WPADData *wpad, *wpad_other; - - wpad = WPAD_Data(0); - wpad_other = WPAD_Data(1); - - if (wpad->exp.type == WPAD_EXP_CLASSIC || - wpad_other->exp.type == WPAD_EXP_CLASSIC) - has_classic_controller = true; -#endif - - memset(bind_key_messages, 0, sizeof(const char*) * (N_WIIMOTE_BINDINGS + 1)); - - for (int i = 0; i < (has_classic_controller ? N_WIIMOTE_BINDINGS : CLASSIC_UP); i++) - bind_key_messages[i] = this->bind_one_key(np, i); - - int opt = menu_select(bind_key_messages, NULL); - if (opt >= 0) - { - int key; - bool shifted; - - key = this->virtual_keyboard->get_key(); - /* -2 means abort */ - if (key != np->JoystickKeyBinding[opt] && key != -2) - { - this->prefs_changed = true; - np->JoystickKeyBinding[opt] = key; - } - } -} - -void C64::networking_menu(Prefs *np) -{ - int opt; - - do - { - char buf[3][255]; - const char *network_client_messages[] = { - buf[0], /* 0 */ - buf[1], /* 1 */ - buf[2], /* 2 */ - "#2 ", /* 3 */ - "Connect to the C64 network!", /* 4 */ - NULL, - }; - - snprintf(buf[0], 255, "Set username (%s)", - np->NetworkName); - snprintf(buf[1], 255, "Server hostname (%s)", - this->server_hostname); - snprintf(buf[2], 255, "Port (%d)", - this->server_port); - opt = menu_select("Networking", network_client_messages, NULL); - - if (opt >= 0 && opt <= 2) - { - const char *m = this->virtual_keyboard->get_string(); - - if (m) - { - if (opt == 0) - { - memset(np->NetworkName, 0, - sizeof(np->NetworkName)); - strncpy(np->NetworkName, m, - sizeof(np->NetworkName)); - } else if (opt == 1) - strncpy(this->server_hostname, m, - sizeof(this->server_hostname)); - if (opt == 2) - this->server_port = atoi(m); - } - } - else if (opt == 4) { - if (strncmp(np->NetworkName, "Unset", 5) == 0) - { - char *msg = "Select name first"; - - msgYesNo(msg, false, 160, 160); - continue; - } - - this->peer = new Network(this->server_hostname, this->server_port); - this->network_connection_type = CONNECT; - } - } while (opt >= 0 && opt <= 2); - - this->prefs_changed = true; -} - -void C64::advanced_options(Prefs *np) -{ - int submenus[4] = { np->DisplayOption, 0, - np->SpriteCollisions, 0 }; - -#define SPEED_95 30 -#define SPEED_100 20 -#define SPEED_110 18 - - switch (np->MsPerFrame) - { - case SPEED_95: - submenus[1] = 0; break; - case SPEED_110: - submenus[1] = 2; break; - default: - /* If it has some other value... */ - submenus[1] = 1; break; - } - - int opt = menu_select("Advanced options", - new_advanced_options_menu_messages, - submenus); - if (opt >= 0) - { - np->DisplayOption = submenus[0]; - np->SpriteCollisions = submenus[2]; - - switch(submenus[1]) - { - case 0: - np->MsPerFrame = SPEED_95; break; - case 1: - np->MsPerFrame = SPEED_100; break; - case 2: - default: - np->MsPerFrame = SPEED_110; break; - } - - this->prefs_changed = true; - } -} - -void C64::other_options(Prefs *np) -{ - int old_swap = np->JoystickSwap == true ? 1 : 0; - int submenus[3] = { old_swap, !np->Emul1541Proc, 0 }; - - int opt = menu_select("Options", new_options_menu_messages, - submenus); - if (opt >= 0) - { - np->Emul1541Proc = submenus[1] == 0 ? true : false; - np->JoystickSwap = submenus[0] == 0 ? false : true; - - this->prefs_changed = true; - } -} /* From dreamcast port but heavily modified */ void C64::run_fake_key_sequence() { - int kc = this->virtual_keyboard->char_to_keycode(this->fake_key_str[this->fake_key_index]); + int kc = Gui::gui->kbd->charToKeycode(this->fake_key_str[this->fake_key_index]); TheDisplay->FakeKeyPress(kc, TheCIA1->KeyMatrix, TheCIA1->RevMatrix); @@ -363,80 +107,12 @@ void C64::run_fake_key_sequence() } } -void C64::start_fake_key_sequence(const char *str) +void C64::startFakeKeySequence(const char *str) { this->fake_key_str = str; this->fake_key_sequence = true; } -void C64::select_fake_key_sequence(Prefs *np) -{ - static const char *fake_key_sequences[] = { - "\nLOAD \"*\",8,1\nRUN\n", - "\nLOAD \"$\",8\n", - "\nLIST\n", - NULL}; - const char *fake_key_messages[] = { - "LOAD \"*\",8,1 and RUN", - "LOAD \"$\",8", - "LIST", - NULL}; - int opt; - - opt = menu_select("Keyboard macros", fake_key_messages, NULL); - if (opt < 0) - return; - - this->start_fake_key_sequence(fake_key_sequences[opt]); -} - -void C64::save_load_state(Prefs *np, int opt) -{ - switch(opt) - { - case 1: /* save */ - { - char save_buf[255]; - char prefs_buf[255]; - - snprintf(save_buf, 255, "%s/%s.sav", SAVES_PATH, - this->save_game_name); - snprintf(prefs_buf, 255, "%s.prefs", save_buf); - - this->SaveSnapshot(save_buf); - np->Save(prefs_buf); - } break; - case 0: /* load/delete */ - case 2: - { - const char *name = menu_select_file(SAVES_PATH); - char save_buf[255]; - char prefs_buf[255]; - - if (name == NULL) - break; - - snprintf(save_buf, 255, "%s", name); - snprintf(prefs_buf, 255, "%s.prefs", save_buf); - if (opt == 2) - { - unlink(save_buf); - unlink(prefs_buf); - } - else /* Load the snapshot */ - { - this->LoadSnapshot(save_buf); - np->Load(prefs_buf); - this->prefs_changed = true; - } - - free((void*)name); - } break; - default: - break; - } -} - /* * Start main emulation thread */ @@ -642,63 +318,11 @@ void C64::VBlank(bool draw_frame) } if (this->have_a_break) { - int submenus[3] = {1, 0, 0}; - int opt; Prefs np = ThePrefs; this->prefs_changed = false; TheSID->PauseSound(); - opt = menu_select("Main menu", new_main_menu_messages, submenus); - - switch(opt) - { - case 0: /* Insert disc/tape */ - this->select_disc(&np, submenus[0] == 1); - break; - case 2: /* Save / load game */ - this->save_load_state(&np, submenus[1]); - break; - case 4: /* Bind keys to joystick */ - switch (submenus[2]) - { - case 0: /* type */ - { - const char *seq = this->virtual_keyboard->get_string(); - - if (seq != NULL) - this->start_fake_key_sequence(seq); - } break; - case 1: /* Macro */ - this->select_fake_key_sequence(&np); break; - default: - case 2: /* Bind to controller */ - this->bind_keys(&np); break; - } - break; - case 7: /* Reset the C64 */ - Reset(); - break; - case 8: /* Networking */ - this->networking_menu(&np); - break; - case 9: /* Other options */ - this->other_options(&np); - break; - case 10: /* Advanced options */ - this->advanced_options(&np); - break; - case 11: - { - menu_select("Frodo help", welcome, NULL); - } break; - case 12: /* Quit */ - quit_thyself = true; - break; - case -1: - default: - break; - } if (this->prefs_changed) { diff --git a/Src/Display_SDL.h b/Src/Display_SDL.h index 7f012c5..17ea3a8 100644 --- a/Src/Display_SDL.h +++ b/Src/Display_SDL.h @@ -24,6 +24,8 @@ #include "Version.h" #include "CIA.h" +#include "gui/gui.hh" +#include "gui/virtual_keyboard.hh" #include #if defined(GEKKO) @@ -626,7 +628,7 @@ void C64Display::TranslateKey(SDLKey key, bool key_up, uint8 *key_matrix, shift_on = false; else if (!key_up && this->entering_text_message) { - char c = virtual_keyboard->keycode_to_char(c64_key | (shift_on ? 0x80 : 0) ); + char c = Gui::gui->kbd->keycodeToChar(c64_key | (shift_on ? 0x80 : 0) ); if (this->text_message_idx >= sizeof(this->text_message) - 2 || c == '\n') diff --git a/Src/Network.cpp b/Src/Network.cpp index c66bf2d..827a400 100644 --- a/Src/Network.cpp +++ b/Src/Network.cpp @@ -24,7 +24,6 @@ #include "Prefs.h" #include "main.h" #include "C64.h" -#include "menu.h" #if defined(GEKKO) # include @@ -1088,7 +1087,7 @@ network_connection_error_t Network::WaitForPeerList() return VERSION_ERROR; } #endif - int sel = menu_select_peer(pi->peers, pi->n_peers); + int sel = 0; // FIXME! menu_select_peer(pi->peers, pi->n_peers); /* FIXME! What to do here??? */ if (sel < 0) diff --git a/Src/Prefs.h b/Src/Prefs.h index f3c214c..b48f06c 100644 --- a/Src/Prefs.h +++ b/Src/Prefs.h @@ -21,6 +21,10 @@ #ifndef _PREFS_H #define _PREFS_H +#define SPEED_95 30 +#define SPEED_100 20 +#define SPEED_110 18 + #define MAX_JOYSTICK_AXES 32 #define MAX_JOYSTICK_BUTTONS 32 #define MAX_JOYSTICK_HATS 8 @@ -165,9 +169,13 @@ private: uint32 MsPerFrame; #endif int JoystickAxes[MAX_JOYSTICK_AXES]; + int JoystickHats[MAX_JOYSTICK_AXES]; int JoystickButtons[MAX_JOYSTICK_BUTTONS]; char NetworkName[32]; + char NetworkServer[64]; + int NetworkPort; + int NetworkKey; uint32 NetworkAvatar; }; diff --git a/Src/gui/Makefile b/Src/gui/Makefile new file mode 100644 index 0000000..2b83d4d --- /dev/null +++ b/Src/gui/Makefile @@ -0,0 +1,44 @@ +CXX = g++ +CC = gcc +LD = g++ +CPP = cpp + +ERROR_FILTER := 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):/\1(\2):/g' + +CFLAGS ?=-ggdb -Iinclude -Wall `sdl-config --cflags` -Imocks +DEFINES = +LDFLAGS ?= $(GCOV) `sdl-config --libs` -lSDL_ttf -lSDL_image + + +CPP_SRCS=menu.cpp main.cpp utils.cpp gui.cpp dialogue_box.cpp menu_messages.cpp \ + timer.cpp game_info.cpp widget.cpp virtual_keyboard.cpp listener.cpp \ + status_bar.cpp + +OBJS=$(patsubst %.cpp,objs/%.o,$(CPP_SRCS)) $(patsubst %.c,objs/%.o,$(C_SRCS)) +DEPS=$(patsubst %.cpp,deps/%.d,$(CPP_SRCS)) $(patsubst %.c,deps/%.d,$(C_SRCS)) + +TARGET=menu + + +all: $(DEPS) $(TARGET) + + +deps/%.d: %.cpp + @echo makedep $(notdir $<) + @install -d deps/$(dir $<) + @$(CPP) -M -MT objs/$(patsubst %.cpp,%.o,$<) $(DEFINES) $(CFLAGS) -o $@ $< + +objs/%.o: %.cpp + @echo CXX $(notdir $<) + @install -d objs/$(dir $<) + @$(CXX) $(CFLAGS) $(DEFINES) -c -o $@ $< $(ERROR_FILTER) + +clean: + rm -rf $(TARGET) *~ objs deps + + +$(TARGET): $(OBJS) + @echo LD $@ + @$(LD) $(LDFLAGS) -o $@ $+ + +-include $(DEPS) diff --git a/Src/gui/bind_keys_menu.cpp b/Src/gui/bind_keys_menu.cpp new file mode 100644 index 0000000..29b495a --- /dev/null +++ b/Src/gui/bind_keys_menu.cpp @@ -0,0 +1,468 @@ +#include "gui.hh" +#include "menu.hh" +#include "help_box.hh" +#include "dialogue_box.hh" +#include "virtual_keyboard.hh" + +class BindKeysMenu; + +class AnalogueBindListener : public DialogueListener +{ +public: + AnalogueBindListener(BindKeysMenu *menu) + { + this->menu = menu; + } + + void escapeCallback(DialogueBox *which, int selected) + { + delete this; + } + + void selectCallback(DialogueBox *which, int selected); + +private: + BindKeysMenu *menu; +}; + +class BindKeysView; +class BindKeysMenu : public Menu, public KeyboardListener +{ + /* This is a very popular class with many friends */ + friend class BindKeysView; + friend class AnalogueBindListener; + +public: + BindKeysMenu(Font *font, HelpBox *help) : Menu(font) + { + this->help = help; + memset(this->hm, 0, sizeof(this->hm)); + this->setText(bind_key_menu_messages); + } + + ~BindKeysMenu() + { + this->freeHelpMessages(); + } + + virtual void selectCallback(int which) + { + int *ck = NULL; + /* Either the virtual keyboard or the analogue menu */ + bool use_virtkbd = true; + + switch(which) + { + case 0: /* Classic */ + switch (this->p_submenus[0].sel) + { + case 0: ck = &Gui::gui->np->JoystickHats[0]; break; + case 1: ck = &Gui::gui->np->JoystickHats[1]; break; + case 2: ck = &Gui::gui->np->JoystickHats[2]; break; + case 3: ck = &Gui::gui->np->JoystickHats[3]; break; + case 4: ck = &Gui::gui->np->JoystickButtons[0]; break; + case 5: ck = &Gui::gui->np->JoystickButtons[1]; break; + case 6: ck = &Gui::gui->np->JoystickButtons[2]; break; + case 7: ck = &Gui::gui->np->JoystickButtons[3]; break; + case 8: ck = &Gui::gui->np->JoystickButtons[4]; break; + default: + panic("Classic: impossible selection %d", this->p_submenus[0].sel); break; + } + break; + case 2: /* Nunchuk */ + switch (this->p_submenus[1].sel) + { + case 0: ck = &Gui::gui->np->JoystickAxes[0]; use_virtkbd = false; break; + case 1: ck = &Gui::gui->np->JoystickAxes[1]; use_virtkbd = false; break; + case 2: ck = &Gui::gui->np->JoystickButtons[7]; break; + case 3: ck = &Gui::gui->np->JoystickButtons[8]; break; + default: + panic("Nunchuk: impossible selection %d", this->p_submenus[1].sel); break; + } + break; + case 4: /* Classic */ + switch (this->p_submenus[2].sel) + { + case 0: ck = &Gui::gui->np->JoystickHats[0]; break; + case 1: ck = &Gui::gui->np->JoystickHats[1]; break; + case 2: ck = &Gui::gui->np->JoystickHats[2]; break; + case 3: ck = &Gui::gui->np->JoystickHats[3]; break; + case 4: ck = &Gui::gui->np->JoystickButtons[9]; break; + case 5: ck = &Gui::gui->np->JoystickButtons[10]; break; + case 6: ck = &Gui::gui->np->JoystickButtons[11]; break; + case 7: ck = &Gui::gui->np->JoystickButtons[12]; break; + case 8: ck = &Gui::gui->np->JoystickButtons[13]; break; + case 9: ck = &Gui::gui->np->JoystickButtons[14]; break; + case 10: ck = &Gui::gui->np->JoystickButtons[15]; break; + case 11: ck = &Gui::gui->np->JoystickButtons[16]; break; + case 12: ck = &Gui::gui->np->JoystickButtons[17]; break; + case 13: ck = &Gui::gui->np->JoystickButtons[18]; break; + default: + panic("Classic: impossible selection %d", this->p_submenus[2].sel); break; + } + break; + case 6: + switch (this->p_submenus[3].sel) + { + case 0: ck = &Gui::gui->np->JoystickAxes[0]; use_virtkbd = false; break; + case 1: ck = &Gui::gui->np->JoystickAxes[1]; use_virtkbd = false; break; + default: + panic("Classic: impossible selection %d", this->p_submenus[3].sel); break; + } + break; + case 8: + switch (this->p_submenus[4].sel) + { + case 0: ck = &Gui::gui->np->JoystickAxes[2]; use_virtkbd = false; break; + case 1: ck = &Gui::gui->np->JoystickAxes[3]; use_virtkbd = false; break; + default: + panic("Classic: impossible selection %d", this->p_submenus[4].sel); break; + } + break; + case 11: + printf("Resetting joystick setup to defaults\n"); + Gui::gui->popView(); + return; + default: + panic("Impossible menu option\n"); + break; + } + this->cur_key = ck; + + if (use_virtkbd) + { + VirtualKeyboard::kbd->activate(); + VirtualKeyboard::kbd->registerListener(this); + } + else + { + AnalogueBindListener *bl = new AnalogueBindListener(this); + DialogueBox *dlg = new DialogueBox(select_analogue_dlg); + + dlg->registerListener(bl); + Gui::gui->pushDialogueBox(dlg); + } + } + + virtual void hoverCallback(int which) + { + this->help->updateHelpMessage(which); + } + + virtual void escapeCallback(int which) + { + Gui::gui->popView(); + } + + virtual void keyCallback(bool shift, const char *str) + { + panic_if(!this->cur_key, "No key selected but keyboard active???\n"); + + *this->cur_key = this->stringToKeycode(str); + this->updateHelpMessages(); + this->help->updateHelpMessage(this->cur_sel); + VirtualKeyboard::kbd->deactivate(); + this->cur_key = NULL; + } + + void updateHelpMessages() + { + this->freeHelpMessages(); + + this->hm[0] = this->addOne(this->hm[0], this->allocOne("Up: %s", stringToPtr_Wiimote("Up"))); + this->hm[0] = this->addOne(this->hm[0], this->allocOne("Down: %s", stringToPtr_Wiimote("Down"))); + this->hm[0] = this->addOne(this->hm[0], this->allocOne("Left: %s", stringToPtr_Wiimote("Left"))); + this->hm[0] = this->addOne(this->hm[0], this->allocOne("Right: %s", stringToPtr_Wiimote("Right"))); + this->hm[0] = this->addOne(this->hm[0], this->allocOne("A: %s", stringToPtr_Wiimote("A"))); + this->hm[0] = this->addOne(this->hm[0], this->allocOne("B: %s", stringToPtr_Wiimote("B"))); + this->hm[0] = this->addOne(this->hm[0], this->allocOne("+: %s", stringToPtr_Wiimote("+"))); + this->hm[0] = this->addOne(this->hm[0], this->allocOne("-: %s", stringToPtr_Wiimote("-"))); + + /* Nunchuk */ + this->hm[2] = this->addOne(this->hm[2], this->allocOne("Horiz: %s", stringToPtr_Nunchuk("Horiz"))); + this->hm[2] = this->addOne(this->hm[2], this->allocOne("Vert: %s", stringToPtr_Nunchuk("Vert"))); + this->hm[2] = this->addOne(this->hm[2], this->allocOne("Z: %s", stringToPtr_Nunchuk("Z"))); + this->hm[2] = this->addOne(this->hm[2], this->allocOne("C: %s", stringToPtr_Nunchuk("C"))); + + /* Classic */ + this->hm[4] = this->addOne(this->hm[4], this->allocOne("Up: %s", stringToPtr_Classic("Up"))); + this->hm[4] = this->addOne(this->hm[4], this->allocOne("Down: %s", stringToPtr_Classic("Down"))); + this->hm[4] = this->addOne(this->hm[4], this->allocOne("Left: %s", stringToPtr_Classic("Left"))); + this->hm[4] = this->addOne(this->hm[4], this->allocOne("Right: %s", stringToPtr_Classic("Right"))); + this->hm[4] = this->addOne(this->hm[4], this->allocOne("a: %s", stringToPtr_Classic("a"))); + this->hm[4] = this->addOne(this->hm[4], this->allocOne("b: %s", stringToPtr_Classic("b"))); + this->hm[4] = this->addOne(this->hm[4], this->allocOne("x: %s", stringToPtr_Classic("x"))); + this->hm[4] = this->addOne(this->hm[4], this->allocOne("y: %s", stringToPtr_Classic("y"))); + this->hm[4] = this->addOne(this->hm[4], this->allocOne("Zl: %s", stringToPtr_Classic("Zl"))); + this->hm[4] = this->addOne(this->hm[4], this->allocOne("Zr: %s", stringToPtr_Classic("Zr"))); + this->hm[4] = this->addOne(this->hm[4], this->allocOne("+: %s", stringToPtr_Classic("+"))); + this->hm[4] = this->addOne(this->hm[4], this->allocOne("-: %s", stringToPtr_Classic("-"))); + + /* + this->hm[2] = this->addOne(this->hm[2], this->allocOne("l: %s", stringToPtr_Classic("l"))); + this->hm[2] = this->addOne(this->hm[2], this->allocOne("r: %s", stringToPtr_Classic("r"))); + this->hm[2] = this->addOne(this->hm[2], this->allocOne("R-toggle: %s", stringToPtr_Classic("RA"))); + this->hm[2] = this->addOne(this->hm[2], this->allocOne("L-toggle: %s", stringToPtr_Classic("LA"))); + */ + + this->hm[6] = this->addOne(this->hm[6], this->allocOne("Horiz: %s", stringToPtr_Classic("LAH"))); + this->hm[6] = this->addOne(this->hm[6], this->allocOne("Vert: %s", stringToPtr_Classic("LAV"))); + + this->hm[8] = this->addOne(this->hm[8], this->allocOne("Horiz: %s", stringToPtr_Classic("RAH"))); + this->hm[8] = this->addOne(this->hm[8], this->allocOne("Vert: %s", stringToPtr_Classic("RAV"))); + + this->hm[11] = this->addOne(this->hm[11], "Revert to defaults"); + + this->help->setHelpMessages(this->hm); + } + +private: + void freeHelpMessages() + { + for (unsigned i = 0; i < ARRAY_SIZE(this->hm); i++) + { + if (this->hm[i]) + { + for (int j = 0; this->hm[i][j]; j++) + free((void*)this->hm[i][j]); + free(this->hm[i]); + } + this->hm[i] = NULL; + } + } + +#define EQ(b) (strcmp(str, b) == 0) + int *stringToPtr_Classic(const char *str) + { + if (EQ("Up")) + return &Gui::gui->np->JoystickHats[0]; + if (EQ("Down")) + return &Gui::gui->np->JoystickHats[1]; + if (EQ("Left")) + return &Gui::gui->np->JoystickHats[2]; + if (EQ("Right")) + return &Gui::gui->np->JoystickHats[3]; + if (EQ("LAH")) + return &Gui::gui->np->JoystickAxes[0]; + if (EQ("LAV")) + return &Gui::gui->np->JoystickAxes[1]; + if (EQ("RAH")) + return &Gui::gui->np->JoystickAxes[2]; + if (EQ("RAV")) + return &Gui::gui->np->JoystickAxes[3]; + if (EQ("RA")) + return &Gui::gui->np->JoystickAxes[4]; + if (EQ("LA")) + return &Gui::gui->np->JoystickAxes[5]; + if (EQ("a")) + return &Gui::gui->np->JoystickButtons[9]; + if (EQ("b")) + return &Gui::gui->np->JoystickButtons[10]; + if (EQ("x")) + return &Gui::gui->np->JoystickButtons[11]; + if (EQ("y")) + return &Gui::gui->np->JoystickButtons[12]; + if (EQ("L")) + return &Gui::gui->np->JoystickButtons[13]; + if (EQ("R")) + return &Gui::gui->np->JoystickButtons[14]; + if (EQ("Zl")) + return &Gui::gui->np->JoystickButtons[15]; + if (EQ("Zr")) + return &Gui::gui->np->JoystickButtons[16]; + if (EQ("-")) + return &Gui::gui->np->JoystickButtons[17]; + if (EQ("+")) + return &Gui::gui->np->JoystickButtons[18]; + if (EQ("Home")) + return &Gui::gui->np->JoystickButtons[19]; + + /* Shound never happen! */ + panic("Illegal string %s\n", str); + + return NULL; + } + + int *stringToPtr_Nunchuk(const char *str) + { + if (EQ("Horiz")) + return &Gui::gui->np->JoystickAxes[0]; + if (EQ("Vert")) + return &Gui::gui->np->JoystickAxes[1]; + if (EQ("Z")) + return &Gui::gui->np->JoystickButtons[7]; + if (EQ("C")) + return &Gui::gui->np->JoystickButtons[8]; + + /* Shound never happen! */ + panic("Illegal string %s\n", str); + + return NULL; + } + + int *stringToPtr_Wiimote(const char *str) + { + if (EQ("Up")) + return &Gui::gui->np->JoystickHats[0]; + if (EQ("Down")) + return &Gui::gui->np->JoystickHats[1]; + if (EQ("Left")) + return &Gui::gui->np->JoystickHats[2]; + if (EQ("Right")) + return &Gui::gui->np->JoystickHats[3]; + if (EQ("A")) + return &Gui::gui->np->JoystickButtons[0]; + if (EQ("B")) + return &Gui::gui->np->JoystickButtons[1]; + if (EQ("1")) + return &Gui::gui->np->JoystickButtons[2]; + if (EQ("2")) + return &Gui::gui->np->JoystickButtons[3]; + if (EQ("+")) + return &Gui::gui->np->JoystickButtons[4]; + if (EQ("-")) + return &Gui::gui->np->JoystickButtons[5]; + if (EQ("Home")) + return &Gui::gui->np->JoystickButtons[6]; + + /* Shound never happen! */ + panic("Illegal string %s\n", str); + + return NULL; + } +#undef EQ + + const char **addOne(const char **dst, const char *what) + { + int cur; + int n = 0; + + if (dst != NULL) + { + for (n = 0; dst[n]; n++) + ; + } + cur = n; + n++; + dst = (const char **)xrealloc(dst, (n+1) * sizeof(const char*)); + dst[cur] = what; + dst[n] = NULL; + + return dst; + } + + const char *allocOne(const char *fmt, int *what) + { + const char *str = this->bindingToString(*what); + size_t len = strlen(str) + strlen(fmt) + 2; + char *out = (char *)xmalloc(len); + + sprintf(out, fmt, str); + + return out; + } + + int stringToKeycode(const char *str) + { + if (strcmp(str, "None") == 0) + return 0; + + /* default: */ + return VirtualKeyboard::kbd->stringToKeycode(str); + } + + const char *bindingToString(int val) + { + switch(val) + { + case JOY_NONE: + return "None"; + case JOY_HORIZ: + return "Horizontal"; + case JOY_VERT: + return "Vertical"; + case JOY_FIRE: + return "Fire"; + default: + break; + } + + /* default: */ + return VirtualKeyboard::kbd->keycodeToString(val); + } + + HelpBox *help; + int *cur_key; + const char **hm[12]; +}; + +void AnalogueBindListener::selectCallback(DialogueBox *which, int selected) +{ + switch(selected) + { + case 1: + *menu->cur_key = JOY_HORIZ; break; + case 2: + *menu->cur_key = JOY_VERT; break; + case 0: + default: + *menu->cur_key = JOY_NONE; break; + } + + this->menu->updateHelpMessages(); + this->menu->help->updateHelpMessage(this->menu->cur_sel); + + delete this; +} + + +class BindKeysView : public GuiView +{ +public: + BindKeysView() : GuiView() + { + this->help = new HelpBox(Gui::gui->small_font, NULL); + this->menu = new BindKeysMenu(Gui::gui->small_font, this->help); + } + + ~BindKeysView() + { + delete this->help; + delete this->menu; + } + + void viewPushCallback() + { + this->menu->updateHelpMessages(); + this->help->updateHelpMessage(0); + } + + void runLogic() + { + this->menu->runLogic(); + } + + void pushEvent(SDL_Event *ev) + { + this->menu->pushEvent(ev); + } + + void draw(SDL_Surface *where) + { + SDL_Rect dst; + + /* Blit the backgrounds */ + dst = (SDL_Rect){20,45,300,400}; + SDL_BlitSurface(Gui::gui->main_menu_bg, NULL, where, &dst); + + dst = (SDL_Rect){350,13,0,0}; + SDL_BlitSurface(Gui::gui->disc_info, NULL, where, &dst); + + this->menu->draw(where, 50, 70, 300, 400); + this->help->draw(where, 354, 24, 264, 210); + } + +protected: + BindKeysMenu *menu; + HelpBox *help; +}; diff --git a/Src/gui/dialogue_box.cpp b/Src/gui/dialogue_box.cpp new file mode 100644 index 0000000..838a0a0 --- /dev/null +++ b/Src/gui/dialogue_box.cpp @@ -0,0 +1,72 @@ +#include "dialogue_box.hh" + +void DialogueListener::escapeCallback(DialogueBox *which, int selected) +{ + Gui::gui->popDialogueBox(); +} + +void DialogueListener::selectCallback(DialogueBox *which, int selected) +{ + Gui::gui->popDialogueBox(); +} + +DialogueBox::DialogueBox(const char *msgs[], bool delete_on_action) : Menu(NULL), ListenerManager() +{ + this->setFont(Gui::gui->default_font); + this->setSelectedBackground(NULL, NULL, NULL, + Gui::gui->bg_left, Gui::gui->bg_middle, + Gui::gui->bg_right); + + this->setText(msgs, NULL); + /* Place on the second to last entry */ + this->cur_sel = this->n_entries - 2; + this->delete_on_action = delete_on_action; +} + +int DialogueBox::selectNext(event_t ev) +{ + /* No up/down movement please! */ + if (ev == KEY_UP || ev == KEY_DOWN) + return this->cur_sel; + return Menu::selectNext(ev); +} + +void DialogueBox::selectCallback(int which) +{ + for (int i = 0; i < this->nListeners(); i++) + if (this->listeners[i]) + ((DialogueListener*)this->listeners[i])->selectCallback(this, + this->p_submenus[0].sel); + Gui::gui->popDialogueBox(); + if (this->delete_on_action) + delete this; +} + +void DialogueBox::hoverCallback(int which) +{ +} + +void DialogueBox::escapeCallback(int which) +{ + for (int i = 0; i < this->nListeners(); i++) + if (this->listeners[i]) + ((DialogueListener*)this->listeners[i])->selectCallback(this, + this->p_submenus[0].sel); + Gui::gui->popDialogueBox(); + if (this->delete_on_action) + delete this; +} + +void DialogueBox::draw(SDL_Surface *where) +{ + int d_x = where->w / 2 - Gui::gui->dialogue_bg->w / 2; + int d_y = where->h / 2 - Gui::gui->dialogue_bg->h / 2; + + SDL_Rect dst = (SDL_Rect){d_x, d_y, + Gui::gui->dialogue_bg->w, Gui::gui->dialogue_bg->h}; + SDL_BlitSurface(Gui::gui->dialogue_bg, NULL, where, &dst); + + Menu::draw(where, d_x + 10, d_y + 10, + Gui::gui->dialogue_bg->w - 10, Gui::gui->dialogue_bg->h - 10); +} + diff --git a/Src/gui/dialogue_box.hh b/Src/gui/dialogue_box.hh new file mode 100644 index 0000000..a253aea --- /dev/null +++ b/Src/gui/dialogue_box.hh @@ -0,0 +1,38 @@ +#ifndef __DIALOGUE_BOX_HH__ +#define __DIALOGUE_BOX_HH__ + +#include "menu.hh" +#include "listener.hh" +#include "gui_view.hh" +#include "gui.hh" + +class DialogueBox; + +class DialogueListener : public Listener +{ +public: + virtual void selectCallback(DialogueBox *which, int selected); + + virtual void escapeCallback(DialogueBox *which, int selected); +}; + +class DialogueBox : public Menu, public ListenerManager +{ +public: + DialogueBox(const char *msgs[], bool delete_on_action = true); + + virtual void selectCallback(int which); + + virtual void escapeCallback(int which); + + virtual void hoverCallback(int which); + + virtual int selectNext(event_t ev); + + virtual void draw(SDL_Surface *where); + +protected: + bool delete_on_action; +}; + +#endif /* __DIALOGUE_BOX_HH__ */ diff --git a/Src/gui/disc_menu.cpp b/Src/gui/disc_menu.cpp new file mode 100644 index 0000000..5ccd1cd --- /dev/null +++ b/Src/gui/disc_menu.cpp @@ -0,0 +1,186 @@ +#include /* unlink */ + +#include + +#include "menu.hh" +#include "file_browser.hh" +#include "game_info.hh" +#include "game_info_box.hh" +#include "utils.hh" + +static const char *game_exts[] = {".d64", ".D64", ".t64", ".T64", + ".prg",".PRG", ".p00", ".P00", NULL}; +static const char *prg_exts[] = {".prg",".PRG", ".p00", ".P00", NULL}; + +class DiscMenu; + +class DiscView : public GuiView +{ +public: + DiscView(); + + ~DiscView(); + + void pushEvent(SDL_Event *ev); + + void loadGameInfo(const char *what); + + void setDirectory(const char *path); + + void runStartSequence(bool what); + + /* Inherited */ + void runLogic(); + + void draw(SDL_Surface *where); + + DiscMenu *menu; + GameInfoBox *gameInfo; +}; + + +class DiscMenu : public FileBrowser, TimeoutHandler +{ + friend class DiscView; + +public: + DiscMenu(Font *font) : + FileBrowser(game_exts, font), TimeoutHandler() + { + this->runStartSequence = false; + } + + ~DiscMenu() + { + } + + virtual void selectCallback(int which) + { + const char *fileName = this->pp_msgs[this->cur_sel]; + const char *save_game = strrchr(fileName, '/'); + + if (!save_game) + save_game = fileName; + else + save_game = save_game + 1; /* Skip '/' */ + strncpy(Gui::gui->np->DrivePath[0], fileName, sizeof(Gui::gui->np->DrivePath[0])); + + if (ext_matches_list(fileName, prg_exts)) { + char tmp_filename[255]; + FILE *src, *dst; + + snprintf(tmp_filename, sizeof(tmp_filename), "%s/a", Gui::gui->tmp_path); + + /* Clean temp dir first (we only want one file) */ + unlink(tmp_filename); + + src = fopen(Gui::gui->np->DrivePath[0], "r"); + if (src != NULL) + { + snprintf(Gui::gui->np->DrivePath[0], sizeof(Gui::gui->np->DrivePath[0]), + "%s", Gui::gui->tmp_path); + + /* Special handling of .prg: Copy to TMP_PATH and + * load that as a dir */ + dst = fopen(tmp_filename, "w"); + if (dst) + { + Uint8 buf[1024]; + size_t v; + + do { + v = fread(buf, 1, sizeof(buf), src); + fwrite(buf, 1, v, dst); + } while (v > 0); + fclose(dst); + } + fclose(src); + } + } + + Gui::gui->timerController->disarm(this); + Gui::gui->dv->loadGameInfo(fileName); + + if (Gui::gui->dv->gameInfo->gi) + Gui::gui->updateGameInfo(Gui::gui->dv->gameInfo->gi); + else + Gui::gui->updateGameInfo(new GameInfo(fileName)); + Gui::gui->popView(); + + if (this->runStartSequence) + TheC64->startFakeKeySequence("\nLOAD \"*\",8,1\nRUN\n"); + } + + virtual void hoverCallback(int which) + { + Gui::gui->timerController->arm(this, 100); + } + + virtual void timeoutCallback() + { + printf("Hovering timed out over %s\n", + this->pp_msgs[this->cur_sel]); + Gui::gui->dv->loadGameInfo(this->pp_msgs[this->cur_sel]); + } + + virtual void escapeCallback(int which) + { + Gui::gui->timerController->disarm(this); + Gui::gui->popView(); + } + + bool runStartSequence; +}; + + +DiscView::DiscView() : GuiView() +{ + this->menu = new DiscMenu(Gui::gui->default_font); + this->gameInfo = new GameInfoBox(Gui::gui->default_font); +} + +DiscView::~DiscView() +{ + delete this->menu; + delete this->gameInfo; +} + +void DiscView::loadGameInfo(const char *what) +{ + this->gameInfo->loadGameInfo(what); +} + +void DiscView::setDirectory(const char *path) +{ + this->menu->setDirectory(path); +} + +void DiscView::runStartSequence(bool what) +{ + this->menu->runStartSequence = what; +} + +void DiscView::runLogic() +{ + this->menu->runLogic(); +} + +void DiscView::pushEvent(SDL_Event *ev) +{ + this->menu->pushEvent(ev); +} + +void DiscView::draw(SDL_Surface *where) +{ + SDL_Rect dst; + + /* Blit the backgrounds */ + dst = (SDL_Rect){20,45,300,400}; + SDL_BlitSurface(Gui::gui->main_menu_bg, NULL, where, &dst); + + dst = (SDL_Rect){350,13,0,0}; + SDL_BlitSurface(Gui::gui->disc_info, NULL, where, &dst); + + this->menu->draw(where, 50, 70, 280, 375); + this->gameInfo->draw(where, 360, 55, 262, 447); +} diff --git a/Src/gui/file_browser.hh b/Src/gui/file_browser.hh new file mode 100644 index 0000000..f7cae80 --- /dev/null +++ b/Src/gui/file_browser.hh @@ -0,0 +1,57 @@ +#ifndef __FILE_BROWSER_HH__ +#define __FILE_BROWSER_HH__ + +#include "menu.hh" +#include "gui.hh" + +class FileBrowser : public Menu +{ +public: + FileBrowser(const char **exts, Font *font) : Menu(font) + { + this->path = NULL; + this->exts = exts; + + if (!this->exts) + this->exts = (const char **){ NULL }; + + /* If nothing else: Set the default list */ + this->setDefaultFileList(); + } + + ~FileBrowser() + { + this->freeFileList(); + } + + void setDirectory(const char *path) + { + this->freeFileList(); + this->file_list = get_file_list(path, this->exts); + if (!this->file_list) + this->setDefaultFileList(); + this->setText(this->file_list); + } + +protected: + void setDefaultFileList() + { + this->file_list = (const char **)xmalloc(2 * sizeof(char*)); + this->file_list[0] = xstrdup("None"); + } + + void freeFileList() + { + if (!this->file_list) + return; + for (int i = 0; this->file_list[i]; i++) + free((void*)this->file_list[i]); + free(this->file_list); + } + + const char *path; + const char **file_list; + const char **exts; +}; + +#endif /* __FILE_BROWSER_HH__ */ diff --git a/Src/gui/font.hh b/Src/gui/font.hh new file mode 100644 index 0000000..7945ecb --- /dev/null +++ b/Src/gui/font.hh @@ -0,0 +1,35 @@ +#ifndef __FONT_HH__ +#define __FONT_HH__ + +#include + +class Font +{ +public: + virtual ~Font() + { + } + + virtual int getHeight(const char *str) = 0; + + virtual int getHeight(const char c) + { + char buf[2] = {c, '\0'}; + + return this->getHeight(buf); + } + + virtual int getWidth(const char *str) = 0; + + virtual int getWidth(const char c) + { + char buf[2] = {c, '\0'}; + + return this->getWidth(buf); + } + + virtual void draw(SDL_Surface *where, const char *msg, + int x, int y, int w, int h) = 0; +}; + +#endif /* __FONT_HH__ */ diff --git a/Src/gui/game_info.cpp b/Src/gui/game_info.cpp new file mode 100644 index 0000000..a76a377 --- /dev/null +++ b/Src/gui/game_info.cpp @@ -0,0 +1,200 @@ +#include +#include +#include +#include + +#include "game_info.hh" +#include "utils.hh" + +#define VERSION_BASE (0x1978) +#define VERSION_MAGIC (VERSION_BASE + 0) + +struct game_info_v0 +{ + uint32_t sz; + uint16_t version_magic; + + uint16_t author_off; + uint16_t name_off; + uint16_t screenshot_off; /* In PNG format */ + uint16_t filename_off; + uint16_t flags; + uint8_t data[]; /* 4-byte aligned */ +}; + +GameInfo::GameInfo(const char *filename, + const char *name, const char *author, + SDL_Surface *image) +{ + this->filename = filename; + this->name = name; + this->author = author; + this->screenshot = image; +} + +GameInfo::GameInfo(GameInfo *gi) +{ + if (!gi) + { + this->filename = NULL; + this->name = NULL; + this->author = NULL; + this->screenshot = NULL; + return; + } + + this->name = gi->name ? xstrdup(gi->name) : NULL; + this->author = gi->author ? xstrdup(gi->author) : NULL; + this->filename = gi->filename ? xstrdup(gi->filename) : NULL; + this->screenshot = NULL; + + if (gi->screenshot) + this->screenshot = SDL_DisplayFormatAlpha(gi->screenshot); +} + +GameInfo::~GameInfo() +{ + this->resetDefaults(); +} + +void GameInfo::resetDefaults() +{ + free((void*)this->name); + free((void*)this->author); + SDL_FreeSurface(this->screenshot); + + this->name = NULL; + this->author = NULL; + this->screenshot = NULL; +} + +struct game_info *GameInfo::dump() +{ + size_t total_sz = sizeof(struct game_info); + size_t png_sz; + struct game_info *out; + void *png_data; + + if (!this->screenshot) + return NULL; + + /* Convert surface to PNG */ + png_data = sdl_surface_to_png(this->screenshot, &png_sz); + panic_if(!png_data, "Cannot create PNG from surface\n"); + + total_sz += strlen(this->author) + 1; + total_sz += strlen(this->name) + 1; + + total_sz += png_sz; + /* 4-byte align */ + total_sz += 4 - (total_sz & 3); + + /* Allocate everything */ + out = (struct game_info*)xmalloc(total_sz); + out->sz = total_sz; + out->version_magic = VERSION_MAGIC; + out->author_off = 0; /* Starts AFTER the header */ + out->name_off = out->author_off + strlen(this->author) + 1; + out->screenshot_off = out->name_off + strlen(this->name) + 1; + + memcpy(out->data + out->author_off, this->author, strlen(this->author) + 1); + memcpy(out->data + out->name_off, this->name, strlen(this->name) + 1); + memcpy(out->data + out->screenshot_off, png_data, png_sz); + + out->sz = htonl(out->sz); + out->author_off = htons(out->author_off); + out->version_magic = htons(out->version_magic); + out->name_off = htons(out->name_off); + out->screenshot_off = htons(out->screenshot_off); + + return out; +} + +bool GameInfo::fromDump(struct game_info *gi) +{ + SDL_RWops *rw; + + gi->sz = ntohl(gi->sz); + gi->version_magic = ntohs(gi->version_magic); + gi->author_off = ntohs(gi->author_off); + gi->name_off = ntohs(gi->name_off); + gi->screenshot_off = ntohs(gi->screenshot_off); + + this->author = xstrdup((char*)gi->data + gi->author_off); + this->name = xstrdup((char*)gi->data + gi->name_off); + + rw = SDL_RWFromMem(gi->data + gi->screenshot_off, + gi->sz - gi->screenshot_off); + if (!rw) + goto bail_out; + + this->screenshot = IMG_Load_RW(rw, 0); + SDL_FreeRW(rw); + if (!this->screenshot) + goto bail_out; + + return true; + +bail_out: + this->resetDefaults(); + + return false; +} + +GameInfo *GameInfo::loadFromFile(const char *fileName) +{ + struct stat st; + struct game_info *p; + GameInfo *out = NULL; + FILE *fp; + + printf("Woho! I'll load %s\n", fileName); + if (stat(fileName, &st) < 0) + return NULL; + if (st.st_size <= (signed)sizeof(struct game_info)) + { + warning("Size of %s is too small: %d vs minimum %d bytes\n", + fileName, (int)st.st_size, (signed)sizeof(struct game_info) + 4); + return NULL; + } + if (st.st_size % 4 != 0) + { + warning("Size of %s is unreasonable: %d\n", fileName, (int)st.st_size); + return NULL; + } + + fp = fopen(fileName, "r"); + if (!fp) + return NULL; + p = (struct game_info*)xmalloc(st.st_size); + if (fread(p, 1, st.st_size, fp) == (unsigned)st.st_size) + { + out = new GameInfo(); + if (out->fromDump(p) == false) + { + warning("Converting %s to GameInfo failed\n", + fileName); + delete out; + out = NULL; + } + } + else + warning("Could not read %s\n", fileName); + + free(p); + fclose(fp); + + return out; +} + +void GameInfo::setAuthor(const char *author) +{ + free((void*)this->author); + this->author = xstrdup(author); +} + +void GameInfo::setName(const char *name) +{ + free((void*)this->name); + this->name = xstrdup(name); +} diff --git a/Src/gui/game_info.hh b/Src/gui/game_info.hh new file mode 100644 index 0000000..6bfdca0 --- /dev/null +++ b/Src/gui/game_info.hh @@ -0,0 +1,53 @@ +#ifndef __GAME_INFO_HH__ +#define __GAME_INFO_HH__ + +#include + +struct game_info +{ + /* These two MUST stay the same */ + uint32_t sz; + uint16_t version_magic; + + uint16_t author_off; + uint16_t name_off; + uint16_t screenshot_off; /* In PNG format */ + uint16_t filename_off; + uint16_t flags; + uint8_t data[]; /* 4-byte aligned */ +}; + + +class GameInfo +{ +public: + GameInfo(const char *filename = NULL, const char *name = NULL, + const char *author = NULL, + SDL_Surface *image = NULL); + + GameInfo(GameInfo *gi); + + ~GameInfo(); + + void setAuthor(const char *author); + + void setName(const char *name); + + void resetDefaults(); + + /** Returns an allocated dump structure */ + struct game_info *dump(); + + /** Fill in this game info object from a structure */ + bool fromDump(struct game_info *data); + + static GameInfo *loadFromFile(const char *fileName); + + /* Should perhaps be protected but I trust you - just be careful! */ + const char *name; + const char *author; + const char *filename; + SDL_Surface *screenshot; +}; + +#endif /*__GAME_INFO_HH__ */ diff --git a/Src/gui/game_info_box.hh b/Src/gui/game_info_box.hh new file mode 100644 index 0000000..d84660a --- /dev/null +++ b/Src/gui/game_info_box.hh @@ -0,0 +1,102 @@ +#ifndef _GAME_INFO_BOX_H_ +#define _GAME_INFO_BOX_H_ + +#include "menu.hh" +#include "game_info.hh" + +class GameInfoBox : public Menu +{ +public: + GameInfoBox(Font *font) : Menu(font) + { + this->gi = NULL; + memset(this->gi_messages, 0, sizeof(this->gi_messages)); + this->setSelectedBackground(NULL, NULL, NULL, NULL, NULL, NULL); + } + + void setGameInfo(GameInfo *gi) + { + /* Make a copy */ + if (this->gi) + delete this->gi; + this->gi = new GameInfo(gi); + this->updateMessages(); + } + + void loadGameInfo(const char *what) + { + /* Reset the current game info */ + if (this->gi) + { + delete this->gi; + this->gi = NULL; + } + + /* No need to do this for directories or the special "None" field */ + if ( !(strcmp(what, "None") == 0 || + what[0] == '[') ) + { + size_t len = strlen(Gui::gui->metadata_base_path) + strlen(what) + 6; + char *tmp = (char*)xmalloc(len); + + sprintf(tmp, "%s/%s.lra", Gui::gui->metadata_base_path, what); + + /* Might return NULL, but that's OK */ + this->gi = GameInfo::loadFromFile(tmp); + free(tmp); + } + this->updateMessages(); + } + + virtual void selectCallback(int which) + { + } + virtual void hoverCallback(int which) + { + } + virtual void escapeCallback(int which) + { + } + + void draw(SDL_Surface *where, int x, int y, int w, int h) + { + if (!this->gi) + return; + if (this->gi->screenshot) + { + SDL_Rect dst; + + /* Blit the screenshot */ + dst = (SDL_Rect){x + w / 2 - this->gi->screenshot->w / 2, y, w, h}; + SDL_BlitSurface(this->gi->screenshot, NULL, where, &dst); + + Menu::draw(where, x, y + this->gi->screenshot->h + 10, + w, h - this->gi->screenshot->h - 10); + } + else + Menu::draw(where, x, y + 10, w, h - 10); + } + + void updateMessages() + { + this->setText(NULL); + memset(this->gi_messages, 0, sizeof(this->gi_messages)); + + this->gi_messages[0] = "Game:"; + this->gi_messages[1] = " "; + this->gi_messages[2] = "Author:"; + this->gi_messages[3] = " "; + if (this->gi) + { + this->gi_messages[1] = this->gi->name ? this->gi->name : " "; + this->gi_messages[3] = this->gi->author ? this->gi->author : " "; + } + + this->setText(this->gi_messages); + } + + const char *gi_messages[6]; + GameInfo *gi; +}; + +#endif /* _GAME_INFO_BOX_H_ */ diff --git a/Src/gui/game_info_menu.cpp b/Src/gui/game_info_menu.cpp new file mode 100644 index 0000000..10c356a --- /dev/null +++ b/Src/gui/game_info_menu.cpp @@ -0,0 +1,115 @@ +#include "gui.hh" +#include "menu.hh" +#include "game_info_box.hh" +#include "virtual_keyboard.hh" + +class GameInfoView; + +class GameInfoMenu : public Menu, public KeyboardListener +{ + friend class GameInfoView; + +public: + GameInfoMenu(Font *font, GameInfoBox *box) : Menu(font) + { + this->box = box; + this->setText(game_info_menu_messages); + } + + virtual void stringCallback(const char *str) + { + switch (this->cur_sel) + { + case 2: + this->box->gi->setName(str); + break; + case 3: + this->box->gi->setAuthor(str); + break; + default: + panic("Cur sel is %d, not possible!\n", this->cur_sel); + break; + } + this->box->updateMessages(); + } + + virtual void selectCallback(int which) + { + switch (which) + { + case 0: + break; + case 2: + case 3: + VirtualKeyboard::kbd->activate(); + VirtualKeyboard::kbd->registerListener(this); + break; + default: + panic("Impossible menu option\n"); + break; + } + } + + virtual void hoverCallback(int which) + { + } + + virtual void escapeCallback(int which) + { + Gui::gui->popView(); + } + +private: + GameInfoBox *box; +}; + + +class GameInfoView : public GuiView +{ +public: + GameInfoView() : GuiView() + { + this->gameInfo = new GameInfoBox(Gui::gui->default_font);; + this->menu = new GameInfoMenu(Gui::gui->default_font, this->gameInfo); + } + + ~GameInfoView() + { + delete this->gameInfo; + delete this->menu; + } + + void runLogic() + { + this->menu->runLogic(); + } + + void pushEvent(SDL_Event *ev) + { + this->menu->pushEvent(ev); + } + + void viewPushCallback() + { + this->gameInfo->setGameInfo(Gui::gui->cur_gameInfo); + } + + void draw(SDL_Surface *where) + { + SDL_Rect dst; + + /* Blit the backgrounds */ + dst = (SDL_Rect){20,45,300,400}; + SDL_BlitSurface(Gui::gui->main_menu_bg, NULL, where, &dst); + + dst = (SDL_Rect){350,13,0,0}; + SDL_BlitSurface(Gui::gui->disc_info, NULL, where, &dst); + + this->menu->draw(where, 50, 70, 280, 375); + this->gameInfo->draw(where, 360, 55, 262, 447); + } + +protected: + GameInfoMenu *menu; + GameInfoBox *gameInfo; +}; diff --git a/Src/gui/gui.cpp b/Src/gui/gui.cpp new file mode 100644 index 0000000..66567d0 --- /dev/null +++ b/Src/gui/gui.cpp @@ -0,0 +1,414 @@ +#include +#include +#include + +#include "menu.hh" +#include "gui.hh" +#include "menu_messages.hh" +#include "help_box.hh" +#include "dialogue_box.hh" +#include "sdl_ttf_font.hh" +#include "utils.hh" +#include "virtual_keyboard.hh" + +extern SDL_Surface *screen; + +#define THEME_ROOT_PATH "themes" +#define METADATA_ROOT_PATH "metadata" +#define GAME_ROOT_PATH "discs" +#define TMP_ROOT_PATH "tmp" +#define SAVE_GAME_ROOT_PATH "saves" + +static const char *get_theme_path(const char *dir, const char *what) +{ + static char buf[255]; + + memset(buf, 0, sizeof(buf)); + snprintf(buf, 254, "%s/%s/%s", + THEME_ROOT_PATH, dir, what); + + return buf; +} + +/* These are a bit of special cases... */ +#include "disc_menu.cpp" +#include "save_game_menu.cpp" +#include "bind_keys_menu.cpp" +#include "theme_menu.cpp" +#include "options_menu.cpp" +#include "network_menu.cpp" +#include "game_info_menu.cpp" +#include "main_menu.cpp" + +GuiView::GuiView() +{ +} + +void GuiView::updateTheme() +{ +} + +void GuiView::viewPushCallback() +{ +} + +void GuiView::viewPopCallback() +{ +} + +Gui::Gui() +{ + this->np = NULL; + + this->focus = NULL; + + this->bg_left = NULL; + this->bg_middle = NULL; + this->bg_right = NULL; + this->bg_submenu_left = NULL; + this->bg_submenu_middle = NULL; + this->bg_submenu_right = NULL; + this->background = NULL; + this->main_menu_bg = NULL; + this->infobox = NULL; + this->textbox = NULL; + this->status_bar_bg = NULL; + this->default_font = NULL; + this->dialogue_bg = NULL; + this->small_font = NULL; + + this->n_views = 0; + this->views = NULL; + this->timerController = new TimerController(); + + VirtualKeyboard::kbd = new VirtualKeyboard(NULL); + + this->theme_base_path = THEME_ROOT_PATH; + this->metadata_base_path = METADATA_ROOT_PATH; + this->game_base_path = GAME_ROOT_PATH; + this->tmp_path = TMP_ROOT_PATH; + this->save_game_path = SAVE_GAME_ROOT_PATH; + + this->cur_gameInfo = new GameInfo(); + this->gameInfoChanged = false; + + this->dlg = NULL; + this->kbd = NULL; + + this->mv = NULL; + this->dv = NULL; + this->sgv = NULL; + this->ov = NULL; + this->nv = NULL; + this->tv = NULL; + this->giv = NULL; + this->bkv = NULL; +} + +Gui::~Gui() +{ + delete this->mv; + delete this->dv; + delete this->sgv; + delete this->ov; + delete this->nv; + delete this->tv; + delete this->giv; + delete this->bkv; + + delete this->cur_gameInfo; + delete this->timerController; + + if (this->status_bar) + delete this->status_bar; + + if (this->dlg) + delete this->dlg; + + if (VirtualKeyboard::kbd) + delete VirtualKeyboard::kbd; + + SDL_FreeSurface(this->bg_left); + SDL_FreeSurface(this->bg_middle); + SDL_FreeSurface(this->bg_right); + SDL_FreeSurface(this->bg_submenu_left); + SDL_FreeSurface(this->bg_submenu_middle); + SDL_FreeSurface(this->bg_submenu_right); + SDL_FreeSurface(this->background); + SDL_FreeSurface(this->main_menu_bg); + SDL_FreeSurface(this->infobox); + SDL_FreeSurface(this->dialogue_bg); + SDL_FreeSurface(this->disc_info); + SDL_FreeSurface(this->textbox); + SDL_FreeSurface(this->selected_key); + SDL_FreeSurface(this->highlighted_key); + SDL_FreeSurface(this->status_bar_bg); + + if (this->default_font) + delete this->default_font; + if (this->small_font) + delete this->small_font; +} + +bool Gui::setTheme(const char *path) +{ + this->bg_left = this->loadThemeImage(path, "bg_left.png"); + this->bg_middle = this->loadThemeImage(path, "bg_middle.png"); + this->bg_right = this->loadThemeImage(path, "bg_right.png"); + this->bg_submenu_left = this->loadThemeImage(path, "bg_submenu_left.png"); + this->bg_submenu_middle = this->loadThemeImage(path, "bg_submenu_middle.png"); + this->bg_submenu_right = this->loadThemeImage(path, "bg_submenu_right.png"); + + this->background = this->loadThemeImage(path, "background.png"); + this->main_menu_bg = this->loadThemeImage(path, "main_menu_bg.png"); + this->status_bar_bg = this->loadThemeImage(path, "status_bar.png"); + this->infobox = this->loadThemeImage(path, "infobox.png"); + this->textbox = this->loadThemeImage(path, "textbox.png"); + this->dialogue_bg = this->loadThemeImage(path, "dialogue_box.png"); + this->disc_info = this->loadThemeImage(path, "disc_info.png"); + + this->highlighted_key = this->loadThemeImage(path, "highlighted_key.png"); + this->selected_key = this->loadThemeImage(path, "selected_key.png"); + + this->default_font = this->loadThemeFont(path, "font.ttf", 18); + this->small_font = this->loadThemeFont(path, "font.ttf", 16); + + if (!this->bg_left || !this->bg_right || !this->bg_middle || + !this->bg_submenu_left || !this->bg_submenu_right || + !this->bg_submenu_middle || + !this->dialogue_bg || + !this->disc_info || + !this->selected_key || + !this->highlighted_key || + !this->status_bar_bg || + !this->default_font || + !this->small_font) + { + SDL_FreeSurface(this->bg_left); + SDL_FreeSurface(this->bg_middle); + SDL_FreeSurface(this->bg_right); + SDL_FreeSurface(this->bg_submenu_left); + SDL_FreeSurface(this->bg_submenu_middle); + SDL_FreeSurface(this->bg_submenu_right); + SDL_FreeSurface(this->background); + SDL_FreeSurface(this->main_menu_bg); + SDL_FreeSurface(this->infobox); + SDL_FreeSurface(this->dialogue_bg); + SDL_FreeSurface(this->disc_info); + SDL_FreeSurface(this->textbox); + SDL_FreeSurface(this->selected_key); + SDL_FreeSurface(this->highlighted_key); + SDL_FreeSurface(this->status_bar_bg); + + if (this->default_font) + delete this->default_font; + if (this->small_font) + delete this->small_font; + + return false; + } + + /* Create the views */ + if (!this->mv) + { + this->status_bar = new StatusBar(); + + this->mv = new MainView(); + this->dv = new DiscView(); + this->sgv = new SaveGameView(); + this->ov = new OptionsView(); + this->nv = new NetworkView(); + this->tv = new ThemeView(); + this->bkv = new BindKeysView(); + this->giv = new GameInfoView(); + this->pushView(mv); + } + + VirtualKeyboard::kbd->updateTheme(); + + return true; +} + +void Gui::runLogic(void) +{ + GuiView *cur_view = this->peekView(); + + this->status_bar->runLogic(); + this->timerController->tick(); + + if (!this->is_active || !cur_view) + return; + if (this->dlg) + this->dlg->runLogic(); + else if (this->kbd) + this->kbd->runLogic(); + else + cur_view->runLogic(); +} + +void Gui::pushView(GuiView *view) +{ + int cur = this->n_views; + + this->n_views++; + this->views = (GuiView**)xrealloc(this->views, + sizeof(GuiView*) * this->n_views); + this->views[cur] = view; + view->viewPushCallback(); +} + +void Gui::pushDialogueBox(DialogueBox *dlg) +{ + this->dlg = dlg; +} + +DialogueBox *Gui::popDialogueBox() +{ + DialogueBox *out = this->dlg; + this->dlg = NULL; + + return out; +} + +GuiView *Gui::popView() +{ + GuiView *cur = this->peekView(); + + if (!cur) + return NULL; + cur->viewPopCallback(); + + this->n_views--; + if (this->n_views <= 0) + { + free(this->views); + this->views = NULL; + this->n_views = 0; + /* Deactivate when no views are left */ + this->is_active = false; + + return NULL; + } + + this->views = (GuiView**)xrealloc(this->views, + sizeof(GuiView*) * this->n_views); + return cur; +} + +void Gui::exitMenu() +{ + printf("Exiting the menu system\n"); + + /* Pop all views */ + while (this->popView()) + ; +} + +void Gui::pushEvent(SDL_Event *ev) +{ + GuiView *cur_view = this->peekView(); + + if (!this->is_active || !cur_view) + return; + if (this->dlg) + this->dlg->pushEvent(ev); + else if (this->kbd) + this->kbd->pushEvent(ev); + else + cur_view->pushEvent(ev); +} + +void Gui::draw(SDL_Surface *where) +{ + GuiView *cur_view = this->peekView(); + + if (!this->is_active || !cur_view) + { + this->status_bar->draw(where); + return; + } + + SDL_BlitSurface(this->background, NULL, where, NULL); + cur_view->draw(where); + if (this->kbd) + this->kbd->draw(where); + if (this->dlg) + this->dlg->draw(where); + this->status_bar->draw(where); +} + +void Gui::activate() +{ + this->is_active = true; + /* FIXME! TMP! TMP! */ + this->np = new Prefs(); +} + +void Gui::deActivate() +{ + /* FIXME! TMP! TMP! */ + delete this->np; + this->is_active = false; +} + +SDL_Surface *Gui::loadThemeImage(const char *dir, const char *what) +{ + return IMG_Load(get_theme_path(dir, what)); +} + +Font *Gui::loadThemeFont(const char *dir, const char *what, int size) +{ + TTF_Font *fnt; + + fnt = read_and_alloc_font(get_theme_path(dir, what), size); + if (!fnt) + return NULL; + + return new Font_TTF(fnt, 255,255,255); +} + +void Gui::updateGameInfo(GameInfo *gi) +{ + panic_if(!gi, "gi must be set\n"); + delete this->cur_gameInfo; + this->cur_gameInfo = gi; + this->gameInfoChanged = true; +} + +void Gui::saveGameInfo() +{ + struct game_info *p = this->cur_gameInfo->dump(); + + if (p) + { + char buf[255]; + FILE *fp; + + snprintf(buf, sizeof(buf), "%s/%s", + METADATA_ROOT_PATH, this->cur_gameInfo->filename); + fp = fopen(buf, "w"); + if (!fp) + { + warning("Could not open %s for writing\n", buf); + return; + } + int n = fwrite((const void*)p, 1, p->sz, fp); + if (n != (int)p->sz) + warning("Could only write %d bytes of %s\n", n, buf); + fclose(fp); + } + + this->gameInfoChanged = false; +} + + +/* The singleton/factory stuff */ +Gui *Gui::gui; +void Gui::init() +{ + Gui::gui = new Gui(); + + /* Set the default theme */ + panic_if(!Gui::gui->setTheme("default"), + "Setting default theme failed\n"); +} diff --git a/Src/gui/gui.hh b/Src/gui/gui.hh new file mode 100644 index 0000000..9bdd396 --- /dev/null +++ b/Src/gui/gui.hh @@ -0,0 +1,134 @@ +#ifndef __GUI_HH__ +#define __GUI_HH__ + +#include + +#include "menu.hh" +#include "font.hh" +#include "timer.hh" +#include "gui_view.hh" + +/* Frodo stuff */ +#include +#include +#include + +class DialogueBox; +class StatusBar; +class GameInfo; + +class MainView; +class BindKeysView; +class DiscView; +class SaveGameView; +class OptionsView; +class NetworkView; +class ThemeView; +class GameInfoView; + +class VirtualKeyboard; + +class Gui +{ +public: + Gui(); + + ~Gui(); + + bool setTheme(const char *path); + + void activate(); + + void deActivate(); + + void runLogic(void); + + void pushEvent(SDL_Event *ev); + + void draw(SDL_Surface *where); + + void pushView(GuiView *view); + + void pushVirtualKeyboard(VirtualKeyboard *kbd); + + void pushDialogueBox(DialogueBox *dlg); + + DialogueBox *popDialogueBox(); + + GuiView *popView(); + + GuiView *peekView() + { + if (!this->views) + return NULL; + return this->views[this->n_views-1]; + } + + void updateGameInfo(GameInfo *gi); + + void saveGameInfo(); + + void exitMenu(); + + /* These are private, keep off! */ + const char *getThemePath(const char *dir, const char *what); + + SDL_Surface *loadThemeImage(const char *dir, const char *what); + + Font *loadThemeFont(const char *dir, const char *what, int size); + + bool is_active; + Menu *focus; /* Where the focus goes */ + Menu *main_menu; + + SDL_Surface *background; + SDL_Surface *main_menu_bg; + SDL_Surface *status_bar_bg; + SDL_Surface *infobox; + SDL_Surface *textbox; + SDL_Surface *dialogue_bg; + SDL_Surface *disc_info; + SDL_Surface *bg_left, *bg_right, *bg_middle, + *bg_submenu_left, *bg_submenu_right, *bg_submenu_middle; + SDL_Surface *highlighted_key; + SDL_Surface *selected_key; + + Font *default_font; + Font *small_font; + TimerController *timerController; + + /* Handled specially */ + VirtualKeyboard *kbd; + DialogueBox *dlg; + StatusBar *status_bar; + + MainView *mv; + DiscView *dv; + SaveGameView *sgv; + OptionsView *ov; + NetworkView *nv; + GameInfoView *giv; + ThemeView *tv; + BindKeysView *bkv; + + GuiView **views; + int n_views; + + const char *metadata_base_path; + const char *theme_base_path; + const char *game_base_path; + const char *tmp_path; + const char *save_game_path; + + GameInfo *cur_gameInfo; + bool gameInfoChanged; + + /* New preferences */ + Prefs *np; + + /* Singleton */ + static void init(); + static Gui *gui; +}; + +#endif /* GUI_HH */ diff --git a/Src/gui/gui_view.hh b/Src/gui/gui_view.hh new file mode 100644 index 0000000..bb7fa94 --- /dev/null +++ b/Src/gui/gui_view.hh @@ -0,0 +1,22 @@ +#ifndef __GUI_VIEW_HH__ +#define __GUI_VIEW_HH__ + +#include + +#include "widget.hh" + +class GuiView : public Widget +{ +public: + GuiView(); + + virtual void updateTheme(); + + virtual void viewPushCallback(); + + virtual void viewPopCallback(); + + virtual void draw(SDL_Surface *where) = 0; +}; + +#endif /* __GUI_VIEW_HH__ */ diff --git a/Src/gui/help_box.hh b/Src/gui/help_box.hh new file mode 100644 index 0000000..50275e7 --- /dev/null +++ b/Src/gui/help_box.hh @@ -0,0 +1,41 @@ +#ifndef __HELP_BOX_HH__ +#define __HELP_BOX_HH__ + +#include "menu.hh" + +class HelpBox : public Menu +{ +public: + HelpBox(Font *font, const char ***all_messages) : Menu(font) + { + this->setHelpMessages(all_messages); + this->setSelectedBackground(NULL, NULL, NULL, NULL, NULL, NULL); + } + + void setHelpMessages(const char ***all_messages) + { + this->all_messages = all_messages; + } + + void updateHelpMessage(int which) + { + if (!this->all_messages) + return; + this->setText(this->all_messages[which]); + } + + virtual void selectCallback(int which) + { + } + virtual void hoverCallback(int which) + { + } + virtual void escapeCallback(int which) + { + } + +protected: + const char ***all_messages; +}; + +#endif /* __HELP_BOX_HH__ */ diff --git a/Src/gui/listener.cpp b/Src/gui/listener.cpp new file mode 100644 index 0000000..3949c9a --- /dev/null +++ b/Src/gui/listener.cpp @@ -0,0 +1,38 @@ +#include "listener.hh" +#include "utils.hh" + +ListenerManager::ListenerManager() +{ + printf("Flushing listeners\n"); + this->flushListeners(); +} + +void ListenerManager::registerListener(Listener *kl) +{ + int n_listeners = sizeof(this->listeners) / sizeof(*this->listeners); + int i; + + /* Don't register already registered listeners */ + for (i = 0; i < n_listeners; i++) + if (this->listeners[i] == kl) + return; + /* Find a free spot */ + for (i = 0; i < n_listeners; i++) + if (!this->listeners[i]) + break; + + panic_if(i == n_listeners, + "No free listeners!\n"); + this->listeners[i] = kl; +} + +void ListenerManager::unregisterListener(Listener *kl) +{ + int n_listeners = sizeof(this->listeners) / sizeof(*this->listeners); + + for (int i = 0; i < n_listeners; i++) + { + if (this->listeners[i] == kl) + this->listeners[i] = NULL; + } +} diff --git a/Src/gui/listener.hh b/Src/gui/listener.hh new file mode 100644 index 0000000..03db713 --- /dev/null +++ b/Src/gui/listener.hh @@ -0,0 +1,34 @@ +#ifndef __LISTENER_HH__ +#define __LISTENER_HH__ + +#include + +class Listener +{ + /* Implemented by the child */ +}; + +class ListenerManager +{ +public: + ListenerManager(); + + void registerListener(Listener *l); + + void unregisterListener(Listener *l); + + void flushListeners() + { + memset(this->listeners, 0, sizeof(this->listeners)); + } + + int nListeners() + { + return sizeof(this->listeners) / sizeof(*this->listeners); + } + +protected: + Listener *listeners[8]; +}; + +#endif /* __LISTENER_HH__ */ diff --git a/Src/gui/main.cpp b/Src/gui/main.cpp new file mode 100644 index 0000000..10b24eb --- /dev/null +++ b/Src/gui/main.cpp @@ -0,0 +1,69 @@ +#include +#include + +#include "gui.hh" +#include "utils.hh" +#include + +SDL_Surface *screen; +C64 *TheC64; + +#define MS_PER_FRAME 28 + +static void run(void) +{ + Uint32 last_frame = SDL_GetTicks(); + + while(1) + { + SDL_Event ev; + Uint32 now = SDL_GetTicks(); + + if (!Gui::gui->is_active) + break; + + while (SDL_PollEvent(&ev)) { + if (ev.type == SDL_QUIT) + exit(1); + + Gui::gui->pushEvent(&ev); + } + Gui::gui->runLogic(); + Gui::gui->draw(screen); + + SDL_Flip(screen); + + if ( (now - last_frame) < MS_PER_FRAME) + SDL_Delay( MS_PER_FRAME - (now - last_frame)); + } +} + +static void init(void) +{ + /* Creation of the mocks */ + TheC64 = new C64(); + + screen = SDL_SetVideoMode(640, 480, 16, + SDL_DOUBLEBUF); + panic_if(!screen, "Cannot initialize video: %s\n", SDL_GetError()); + TTF_Init(); + + Gui::init(); + Gui::gui->activate(); +} + +static void fini(void) +{ + delete Gui::gui; +} + +int main(int argc, char *argv[]) +{ + init(); + run(); + fini(); + + SDL_Quit(); + + return 0; +} diff --git a/Src/gui/main_menu.cpp b/Src/gui/main_menu.cpp new file mode 100644 index 0000000..d5f33e6 --- /dev/null +++ b/Src/gui/main_menu.cpp @@ -0,0 +1,182 @@ +#include "menu.hh" +#include "dialogue_box.hh" + +class KeyboardTypingListener : public KeyboardListener +{ + virtual void stringCallback(const char *str) + { + printf("string: %s\n", str); + /* Remove thyself! */ + delete this; + } + + virtual void keyCallback(bool shift, const char *str) + { + printf("Vobb: %d: %s\n", shift, str); + } +}; + +class ExitListener : public DialogueListener +{ + void escapeCallback(DialogueBox *which, int selected) + { + } + + void selectCallback(DialogueBox *which, int selected) + { + /* Cancel? */ + if (selected != 1) + exit(0); + } +}; + +class MainView; +class MainMenu : public Menu +{ + friend class MainView; + +public: + MainMenu(Font *font, HelpBox *help) : Menu(font) + { + this->help = help; + + this->updatePauseState(); + } + + virtual void selectCallback(int which) + { + printf("entry %d selected: %s\n", which, this->pp_msgs[which]); + switch (which) + { + case 0: + TheC64->IsPaused() ? TheC64->Resume() : TheC64->Pause(); + if (TheC64->IsPaused()) + Gui::gui->status_bar->queueMessage("C64 emulation paused"); + else + Gui::gui->status_bar->queueMessage("C64 emulation resumed"); + this->updatePauseState(); + break; + case 2: /* Insert disc */ + Gui::gui->dv->setDirectory(Gui::gui->game_base_path); + Gui::gui->pushView(Gui::gui->dv); + + Gui::gui->dv->runStartSequence(this->p_submenus[0].sel == 1); + break; + case 4: /* Load/save states */ + if (this->p_submenus[1].sel == 1) + Gui::gui->sgv->saveSnapshot(); + else + { + Gui::gui->sgv->setDirectory(Gui::gui->save_game_path); + Gui::gui->pushView(Gui::gui->sgv); + + Gui::gui->sgv->setLoadSnapshot(this->p_submenus[1].sel == 0); + } + break; + case 6: /* Keyboard */ + switch(this->p_submenus[2].sel) + { + case 0: + VirtualKeyboard::kbd->activate(); + VirtualKeyboard::kbd->registerListener(new KeyboardTypingListener()); + break; + case 1: + break; + case 2: + Gui::gui->pushView(Gui::gui->bkv); + break; + default: + panic("Illegal selection\n"); + } + break; + case 9: /* Game info */ + Gui::gui->pushView(Gui::gui->giv); + break; + case 10: /* Networking */ + Gui::gui->pushView(Gui::gui->nv); + break; + case 11: /* Options */ + Gui::gui->pushView(Gui::gui->ov); + break; + case 12: /* Exit */ + DialogueBox *exit_dialogue = new DialogueBox(exit_dialogue_messages); + exit_dialogue->registerListener(new ExitListener()); + Gui::gui->pushDialogueBox(exit_dialogue); + break; + } + } + + virtual void hoverCallback(int which) + { + this->help->updateHelpMessage(which); + } + + virtual void escapeCallback(int which) + { + Gui::gui->exitMenu(); + } + +private: + void updatePauseState() + { + if (TheC64->IsPaused()) + main_menu_messages[0] = "Resume"; + else + main_menu_messages[0] = "Pause"; + this->setText(main_menu_messages); + } + + HelpBox *help; +}; + + +class MainView : public GuiView +{ +public: + MainView() : GuiView() + { + panic_if(!Gui::gui->default_font, + "Theme does not seem correctly loaded\n"); + + this->help = new HelpBox(Gui::gui->small_font, main_menu_help); + this->menu = new MainMenu(Gui::gui->default_font, this->help); + } + + ~MainView() + { + delete this->help; + delete this->menu; + } + + void runLogic() + { + this->menu->runLogic(); + } + + void pushEvent(SDL_Event *ev) + { + this->menu->pushEvent(ev); + } + + void draw(SDL_Surface *where) + { + SDL_Rect dst; + + /* Blit the backgrounds */ + dst = (SDL_Rect){20,45,300,400}; + SDL_BlitSurface(Gui::gui->main_menu_bg, NULL, where, &dst); + + dst = (SDL_Rect){350,13,0,0}; + SDL_BlitSurface(Gui::gui->infobox, NULL, where, &dst); + + dst = (SDL_Rect){350,242,0,0}; + SDL_BlitSurface(Gui::gui->textbox, NULL, where, &dst); + + this->menu->draw(where, 50, 70, 300, 400); + this->help->draw(where, 354, 24, 264, 210); + } + +protected: + MainMenu *menu; + HelpBox *help; +}; diff --git a/Src/gui/menu.cpp b/Src/gui/menu.cpp new file mode 100644 index 0000000..6ccb24f --- /dev/null +++ b/Src/gui/menu.cpp @@ -0,0 +1,373 @@ +/********************************************************************* +* +* Copyright (C) 2004-2009, Simon Kagstrom +* +* Filename: menu.c +* Author: Simon Kagstrom +* Description: Code for menus (originally for Mophun) +* +* $Id$ +* +********************************************************************/ +#include +#include + +#include "menu.hh" +#include "font.hh" +#include "utils.hh" +#include "gui.hh" + +#define IS_SUBMENU(p_msg) ( (p_msg)[0] == '^' ) +#define IS_EMPTY(p_msg) ( (p_msg)[0] == '#' ) + +void Menu::printText(SDL_Surface *where, const char *msg, SDL_Color clr, + int x, int y, int w, int h) +{ + char *buf; + unsigned int i; + int tw; + + buf = xstrdup(msg); + tw = this->font->getWidth(buf); + + /* Crop text */ + if (tw > w) + { + int pixels_per_char = tw / strlen(buf); + int last_char = (w / pixels_per_char) - 1; + + if ((unsigned)last_char > strlen(buf)) + last_char = strlen(buf) - 3; + + /* FIXME! Handle some corner cases here (short strings etc) */ + if (last_char > 3) + { + buf[last_char - 2] = '.'; + buf[last_char - 1] = '.'; + buf[last_char] = '\0'; + } + } + + /* Fixup multi-menu option look */ + for (i = 0; i < strlen(buf) ; i++) + { + if (buf[i] == '^' || buf[i] == '|') + buf[i] = ' '; + } + if (IS_EMPTY(buf)) + buf[0] = ' '; + + this->font->draw(where, buf, x, y, w, h); + free(buf); +} + + +void Menu::draw(SDL_Surface *where, int x, int y, int w, int h) +{ + int font_height = this->font->getHeight("X"); + int line_height = (font_height + font_height / 4); + int x_start = x; + int entries_visible = h / line_height - 1; + int start_entry_visible = 0; + + /* No messages - nothing to draw */ + if (!this->pp_msgs) + return; + + if (this->cur_sel - start_entry_visible > entries_visible) + { + while (this->cur_sel - start_entry_visible > entries_visible) + { + start_entry_visible++; + if (start_entry_visible > this->n_entries) + { + start_entry_visible = 0; + break; + } + } + } + else if ( this->cur_sel < start_entry_visible ) + start_entry_visible = this->cur_sel; + + if (start_entry_visible + entries_visible > this->n_entries) + entries_visible = this->n_entries - start_entry_visible; + + for (int i = start_entry_visible; + i <= start_entry_visible + entries_visible; i++) + { + const char *msg = this->pp_msgs[i]; + int cur_y; + + if (i >= this->n_entries) + break; + + cur_y = y + (i - start_entry_visible) * line_height; + + /* Draw the background for the selected entry */ + if (this->cur_sel == i) { + int tw, th; + + tw = this->font->getWidth(msg); + th = this->font->getHeight(msg); + + highlight_background(where, this->font, + this->text_bg_left, this->text_bg_middle, this->text_bg_right, + x_start, cur_y, tw, th); + } + + if (IS_SUBMENU(msg)) + { + submenu_t *p_submenu = this->findSubmenu(i); + int n_pipe = 0; + int total_chars = 0; + int tw, th, tw_first; + int n_chars; + char *p; + int n; + + for (n = 0; msg[n] != '\0'; n++) + { + if (msg[n] != '|') + continue; + /* msg[n] == '|' */ + + /* Count the number of chars until next pipe */ + for (n_chars = 1; msg[n+n_chars] && msg[n+n_chars] != '|'; n_chars++); + + total_chars += n_chars; + + n_pipe++; + /* Found the selection yet? */ + if (p_submenu->sel == n_pipe-1) + break; + } + + p = (char*)xmalloc(total_chars + 1); + strncpy(p, msg, n + 1); + tw_first = this->font->getWidth(p); + + memset(p, 0, total_chars + 1); + strncpy(p, msg + n, n_chars - 1); + tw = this->font->getWidth(p); + th = this->font->getHeight(p); + + highlight_background(where, this->font, + this->submenu_bg_left, this->submenu_bg_middle, this->submenu_bg_right, + x_start + tw_first, cur_y, tw, th); + free(p); + } + + /* And print the text on top */ + this->printText(where, msg, this->text_color, + x_start, cur_y, w, h); + } +} + + +int Menu::getNextEntry(int dy) +{ + if (this->cur_sel + dy < 0) + return this->n_entries - 1; + if (this->cur_sel + dy > this->n_entries - 1) + return 0; + return this->cur_sel + dy; +} + +submenu_t *Menu::findSubmenu(int index) +{ + int i; + + for (i = 0; i < this->n_submenus; i++) + { + if (this->p_submenus[i].index == index) + return &this->p_submenus[i]; + } + + return NULL; +} + + +int Menu::selectOne(int which) +{ + panic_if(!this->pp_msgs, + "Can't select a message without any messages!"); + + if (which >= this->n_entries) + which = 0; + this->cur_sel = which; + + if (this->pp_msgs[this->cur_sel][0] == ' ' || + IS_SUBMENU(this->pp_msgs[this->cur_sel])) + this->selectNext(0, 1); + this->hoverCallback(this->cur_sel); + + return this->cur_sel; +} + +int Menu::selectNext(int dx, int dy) +{ + int next; + + panic_if(!this->pp_msgs, + "Can't select the next message without any messages!"); + + this->cur_sel = this->getNextEntry(dy); + next = this->getNextEntry(dy + 1); + + /* We want to skip this for some reason */ + if (this->pp_msgs[this->cur_sel][0] == ' ' || + IS_SUBMENU(this->pp_msgs[this->cur_sel]) ) { + return this->selectNext(dx, dy); + } + + /* If the next is a submenu */ + if (dx != 0 && IS_SUBMENU(this->pp_msgs[next])) + { + submenu_t *p_submenu = findSubmenu(next); + + panic_if(!p_submenu, "submenu in the menu text but no actual submenu\n"); + p_submenu->sel = (p_submenu->sel + dx) < 0 ? p_submenu->n_entries - 1 : + (p_submenu->sel + dx) % p_submenu->n_entries; + } + + return this->cur_sel; +} + +int Menu::selectNext(event_t ev) +{ + int now = this->cur_sel; + int next; + + switch (ev) + { + case KEY_UP: + next = this->selectNext(0, -1); break; + case KEY_DOWN: + next = this->selectNext(0, 1); break; + case KEY_LEFT: + next = this->selectNext(-1, 0); break; + case KEY_RIGHT: + next = this->selectNext(1, 0); break; + default: + panic("selectNext(ev) called with event %d\n", ev); + } + + if (now != next) + this->hoverCallback(this->cur_sel); + + return this->cur_sel; +} + +void Menu::runLogic() +{ + event_t ev; + + while ( (ev = this->popEvent()) != EVENT_NONE ) + { + switch (ev) + { + case KEY_UP: + case KEY_DOWN: + case KEY_LEFT: + case KEY_RIGHT: + this->selectNext(ev); + break; + case KEY_SELECT: + this->selectCallback(this->cur_sel); + /* Might be deleted */ + return; + case KEY_ESCAPE: + this->escapeCallback(this->cur_sel); + /* Might be deleted */ + return; + default: + break; + } + } +} + +void Menu::setText(const char **messages, int *submenu_defaults) +{ + int submenu; + + /* Free the old stuff */ + this->n_submenus = 0; + free(this->p_submenus); + free(this->pp_msgs); + + /* Empty messages are allowed */ + this->p_submenus = NULL; + this->pp_msgs = NULL; + if (!messages) + return; + + for (this->n_entries = 0; messages[this->n_entries]; this->n_entries++) + { + /* Is this a submenu? */ + if (IS_SUBMENU(messages[this->n_entries])) + { + this->n_submenus++; + continue; /* Length of submenus is unimportant */ + } + } + this->pp_msgs = (const char **)xmalloc(this->n_entries * sizeof(const char *)); + if (this->n_submenus) + this->p_submenus = (submenu_t *)xmalloc(this->n_submenus * sizeof(submenu_t)); + for (int i = 0; i < this->n_entries; i++) + this->pp_msgs[i] = xstrdup(messages[i]); + + submenu = 0; + + for (int i = 0; i < this->n_entries; i++) + { + if (IS_SUBMENU(this->pp_msgs[i])) + { + int n; + + this->p_submenus[submenu].index = i; + this->p_submenus[submenu].sel = submenu_defaults ? submenu_defaults[submenu] : 0; + this->p_submenus[submenu].n_entries = 0; + for (n = 0; this->pp_msgs[i][n] != '\0'; n++) + { + if (this->pp_msgs[i][n] == '|') + this->p_submenus[submenu].n_entries++; + } + submenu++; + } + } + + /* Move selection to the first entry */ + this->selectOne(0); +} + +Menu::Menu(Font *font) : Widget() +{ + this->setTextColor((SDL_Color){0xff,0xff,0xff,0}); + this->font = font; + + this->pp_msgs = NULL; + this->n_entries = 0; + this->p_submenus = NULL; + this->n_submenus = 0; + + this->cur_sel = 0; + this->mouse_x = -1; + this->mouse_y = -1; + + this->setSelectedBackground(Gui::gui->bg_left, Gui::gui->bg_middle, + Gui::gui->bg_right, Gui::gui->bg_submenu_left, + Gui::gui->bg_submenu_middle, Gui::gui->bg_submenu_right); +} + +void Menu::setTextColor(SDL_Color clr) +{ + this->text_color = clr; +} + +Menu::~Menu() +{ + for (int i = 0; i < this->n_entries; i++) + free((void*)this->pp_msgs[i]); + free(this->pp_msgs); + free(this->p_submenus); +} diff --git a/Src/gui/menu.hh b/Src/gui/menu.hh new file mode 100644 index 0000000..45261f2 --- /dev/null +++ b/Src/gui/menu.hh @@ -0,0 +1,108 @@ +/********************************************************************* + * + * Copyright (C) 2004, 2008, Simon Kagstrom + * + * Filename: menu.h + * Author: Simon Kagstrom + * Description: + * + * $Id$ + * + ********************************************************************/ +#ifndef __MENU_H__ +#define __MENU_H__ + +#include +#include +#include + +#include "font.hh" +#include "widget.hh" + +typedef struct +{ + int n_entries; + int index; + int sel; +} submenu_t; + + +class Menu : public Widget +{ +public: + Menu(Font *font); + + ~Menu(); + + void setFont(Font *font) + { + this->font = font; + } + + void setTextColor(SDL_Color clr); + + void setSelectedBackground(SDL_Surface *left, SDL_Surface *middle, SDL_Surface *right, + SDL_Surface *submenu_left, SDL_Surface *submenu_middle, SDL_Surface *submenu_right) + { + this->text_bg_left = left; + this->text_bg_middle = middle; + this->text_bg_right = right; + + this->submenu_bg_left = submenu_left; + this->submenu_bg_middle = submenu_middle; + this->submenu_bg_right = submenu_right; + } + + void setText(const char **messages, int *submenu_defaults = NULL); + + virtual void runLogic(); + + void draw(SDL_Surface *where, + int x, int y, int w, int h); + +protected: + void printText(SDL_Surface *where, const char *msg, SDL_Color clr, + int x, int y, int w, int h); + + virtual void hoverCallback(int which) = 0; + + virtual void selectCallback(int which) = 0; + + virtual void escapeCallback(int which) = 0; + + submenu_t *findSubmenu(int index); + +public: + virtual int getNextEntry(int dy); + + virtual int selectOne(int which); + + virtual int selectNext(int dx, int dy); + + virtual int selectNext(event_t ev); + +protected: + + const char **pp_msgs; + Font *font; + SDL_Color text_color; + + SDL_Surface *text_bg_left; + SDL_Surface *text_bg_right; + SDL_Surface *text_bg_middle; + + SDL_Surface *submenu_bg_left; + SDL_Surface *submenu_bg_right; + SDL_Surface *submenu_bg_middle; + + /* Relative to this menu */ + int mouse_x, mouse_y; + + int n_submenus; + submenu_t *p_submenus; + + int cur_sel; /* Main selection */ + int n_entries; +}; + +#endif /* !__MENU_H__ */ diff --git a/Src/gui/menu_messages.cpp b/Src/gui/menu_messages.cpp new file mode 100644 index 0000000..5de8723 --- /dev/null +++ b/Src/gui/menu_messages.cpp @@ -0,0 +1,258 @@ +#include + +#include "menu_messages.hh" + +const char **exit_dialogue_messages = (const char*[]){ + /*00*/ "Do you really want to exit", + /*01*/ "Frodo?", + /*02*/ "#", /* Empty line */ + /*03*/ "#", + /*04*/ "#", + /*05*/ "#", + /*06*/ "^|Yes|Cancel", + NULL +}; + +const char **network_port_dialogue_messages = (const char*[]){ + /*00*/ "Please supply a number as", + /*01*/ "network port.", + /*02*/ "#", /* Empty line */ + /*03*/ "#", + /*04*/ "#", + /*05*/ "#", + /*06*/ "^|OK", + NULL +}; + +const char **network_unset_name_dlg = (const char*[]){ + /*00*/ "Please setup a name to use", + /*01*/ "on network connections.", + /*02*/ "#", /* Empty line */ + /*03*/ "#", + /*04*/ "#", + /*05*/ "#", + /*06*/ "^|OK", + NULL +}; + +const char **broken_theme_dlg = (const char*[]){ + /*00*/ "The selected theme cannot be", + /*01*/ "loaded, probably some file", + /*02*/ "is missing or broken in it.", + /*03*/ "The default theme has been", + /*04*/ "reverted.", + /*05*/ "#", + /*06*/ "^|OK", + NULL +}; + +const char **select_analogue_dlg = (const char*[]){ + /*00*/ "Select axis of analogue", + /*01*/ "joystick to bind.", + /*02*/ "#", + /*03*/ "#", + /*04*/ "#", + /*05*/ "#", + /*06*/ "^|None|Horiz|Vert", + NULL +}; + + + +const char **main_menu_messages = (const char*[]){ + /*00*/ NULL, /* Setup dynamically */ + /*01*/ " ", + /*02*/ "File", + /*03*/ "^|Insert|Start", + /*04*/ "States", + /*05*/ "^|Load|Save|Delete", + /*06*/ "Keyboard", + /*07*/ "^|Type|Macro|Bind", + /*08*/ " ", + /*09*/ "Game info", + /*10*/ "Networking", + /*11*/ "Options", + /*12*/ "Quit", + NULL +}; + +const char **main_menu_help[] = { + (const char*[]){ + "Pause or resume the C64", + "emulation. Not available", + "when running in networked", + "mode.", + NULL, + }, + NULL, + (const char*[]){ + "Insert a disc/tape or", + "start it", + NULL, + }, + NULL, + (const char*[]){ + "Load/save or delete game", + "states", + NULL, + }, + NULL, + (const char*[]){ + "Bind keyboard keys to the", + "joysticks, use pre-defined", + "macros, or type with the", + "virtual keyboard", + NULL, + }, + NULL, + NULL, + (const char*[]){ + "View and configure game", + "information (author,", + "screenshots etc)", + NULL, + }, + (const char*[]){ + "Network setup for playing", + "C64 games against other", + "players online.", + NULL, + }, + (const char*[]){ + "Configure Frodo", + NULL, + }, + (const char*[]){ + "Quit Frodo", + NULL, + }, + NULL, +}; + + +const char **options_menu_messages = (const char*[]){ + /*00*/ "Map Controller 1 to:", + /*01*/ "^|Port 1|Port 2", + /*02*/ "True 1541 emulation", + /*03*/ "^|ON|OFF", + /*04*/ "1541 Floppy Drive LED", + /*05*/ "^|ON|OFF", + /*06*/ "Display resolution", + /*07*/ "^|double-center|stretched", + /*08*/ "Speed (approx. %)", + /*09*/ "^|95|100|110", + /*10*/ "Reset the C=64", + /*11*/ " ", + /*12*/ "Setup GUI theme", + NULL +}; + +const char **bind_key_menu_messages = (const char*[]){ + /*00*/ "Wiimote", + /*01*/ "^|Up|Down|Left|Right|A|B|1|2|+|-", + /*02*/ "Nunchuk", + /*03*/ "^|Horiz|Vert|Z|C", + /*04*/ "Classic", + /*05*/ "^|Up|Down|Left|a|b|x|y|Zl|Zr|+|-", + /*06*/ "Classic (left analogue)", + /*07*/ "^|Horiz|Vert", + /*08*/ "Classic(right analogue)", + /*09*/ "^|Horiz|Vert", + /*10*/ " ", + /*11*/ "Reset to defaults", + NULL +}; + +const char **options_menu_help[] = { + (const char*[]){ + "Switch controller to", + "C64 joystick port", + "mapping.", + NULL, + }, + NULL, + (const char*[]){ + "Turn on or off true 1541", + "floppy emulation. Might", + "be needed in some games", + "but slows down emulation.", + NULL, + }, + NULL, + (const char*[]){ + "Display 1541 drive LED to", + "show if the emulation got", + "stuck or is running.", + NULL, + }, + NULL, + (const char*[]){ + "Select display resolution", + "mapping. Double-center", + "removes some pixels on the", + "borders, stretched fills", + "the display but is slower.", + NULL, + }, + NULL, + (const char*[]){ + "Setup speed factor (in %).", + "Should normally be 100", + "unless Simon did some bad", + "mistake.", + NULL, + }, + NULL, + NULL, + (const char*[]){ + "Setup theme for the Frodo", + "menus.", + NULL, + }, + NULL, +}; + +const char **network_menu_help[] = { + (const char*[]){ + "Setup username to use on", + "the C64 network. Must be", + "set before connceting.", + NULL, + }, + (const char*[]){ + "Setup server hostname.", + "Only for debugging, so", + "leave as it is.", + NULL, + }, + (const char*[]){ + "UDP port to use. Only for", + "debugging, so leave as", + "it is", + NULL, + }, + NULL, + (const char*[]){ + "Connect to the C64", + "network, or disconnect if", + "you are already connected.", + NULL, + }, + NULL, + (const char*[]){ + "Post message to the C64", + "network server. You must", + "be connected to use this.", + NULL, + }, + NULL, +}; + + +const char **game_info_menu_messages = (const char*[]){ + /*00*/ "Capture game screenshot", + /*01*/ " ", + /*02*/ "Set game name", + /*02*/ "Set game author", + NULL +}; diff --git a/Src/gui/menu_messages.hh b/Src/gui/menu_messages.hh new file mode 100644 index 0000000..9334677 --- /dev/null +++ b/Src/gui/menu_messages.hh @@ -0,0 +1,21 @@ +#ifndef MENU_MESSAGES_HH +#define MENU_MESSAGES_HH + +extern const char **main_menu_messages; +extern const char **exit_dialogue_messages; +extern const char **main_menu_help[]; + +extern const char **bind_key_menu_messages; + +extern const char **options_menu_messages; +extern const char **options_menu_help[]; +extern const char **game_info_menu_messages; + +/* The menu messages are dynamically generated */ +extern const char **network_menu_help[]; +extern const char **network_port_dialogue_messages; +extern const char **network_unset_name_dlg; +extern const char **broken_theme_dlg; +extern const char **select_analogue_dlg; + +#endif diff --git a/Src/gui/mocks/C64.h b/Src/gui/mocks/C64.h new file mode 100644 index 0000000..194c1ca --- /dev/null +++ b/Src/gui/mocks/C64.h @@ -0,0 +1,59 @@ +#ifndef __MOCKS_C64_H__ +#define __MOCKS_C64_H__ + +/* Network connection type */ +enum +{ + NONE, + CONNECT, + MASTER, + CLIENT +}; + +class C64 +{ +public: + C64() + { + this->have_a_break = false; + } + + void Pause() + { + this->have_a_break = true; + } + + void Resume() + { + this->have_a_break = false; + } + + bool IsPaused() + { + return this->have_a_break; + } + + void startFakeKeySequence(const char *what) + { + printf("Faking %s\n", what); + } + + void LoadSnapshot(const char *name) + { + printf("Loading savegame %s\n", name); + } + + void SaveSnapshot(const char *name) + { + printf("Saving savegame %s\n", name); + } + + int network_connection_type; + +private: + bool have_a_break; +}; + +extern C64 *TheC64; + +#endif /*__MOCKS_C64_H__ */ diff --git a/Src/gui/mocks/Network.h b/Src/gui/mocks/Network.h new file mode 100644 index 0000000..188f470 --- /dev/null +++ b/Src/gui/mocks/Network.h @@ -0,0 +1,9 @@ +#ifndef __MOCKS_NETWORK_H__ +#define __MOCKS_NETWORK_H__ + +class Network +{ +public: +}; + +#endif /*__MOCKS_NETWORK_H__ */ diff --git a/Src/gui/mocks/Prefs.h b/Src/gui/mocks/Prefs.h new file mode 100644 index 0000000..7800515 --- /dev/null +++ b/Src/gui/mocks/Prefs.h @@ -0,0 +1,61 @@ +#ifndef __MOCK_PREFS_HH__ +#define __MOCK_PREFS_HH__ + +#include + +#define SPEED_95 30 +#define SPEED_100 20 +#define SPEED_110 18 + +enum +{ + /* ASCII values before these */ + JOY_NONE = 0, + JOY_HORIZ = 256, + JOY_VERT = 258, + JOY_FIRE = 259, +}; + +/* Insanely high, but the Wii has insanely many of these */ +#define MAX_JOYSTICK_AXES 32 +#define MAX_JOYSTICK_BUTTONS 32 +#define MAX_JOYSTICK_HATS 8 + +class Prefs +{ +public: + Prefs() + { + /* Set to NONE by default */ + memset(this->JoystickAxes, 0, sizeof(this->JoystickAxes)); + memset(this->JoystickButtons, 0, sizeof(this->JoystickButtons)); + memset(this->JoystickHats, 0, sizeof(this->JoystickHats)); + + strcpy(this->NetworkName, "Unset name"); + strcpy(this->NetworkServer, "play.c64-network.org"); + this->NetworkPort = 46214; + + this->Emul1541Proc = 0; + this->ShowLEDs = 0; + this->DisplayOption = 0; + this->MsPerFrame = SPEED_100; + memset(this->DrivePath, 0, sizeof(this->DrivePath)); + } + + char DrivePath[4][256]; // Path for drive 8..11 + + char NetworkName[32]; + char NetworkServer[128]; + int NetworkPort; + int Emul1541Proc; + int ShowLEDs; + int DisplayOption; + unsigned int MsPerFrame; + + /* This is borrowed from UAE */ + int JoystickAxes[MAX_JOYSTICK_AXES]; + int JoystickHats[MAX_JOYSTICK_HATS]; + int JoystickButtons[MAX_JOYSTICK_BUTTONS]; +}; + +#endif /* __MOCK_PREFS_HH__ */ diff --git a/Src/gui/network_menu.cpp b/Src/gui/network_menu.cpp new file mode 100644 index 0000000..f370366 --- /dev/null +++ b/Src/gui/network_menu.cpp @@ -0,0 +1,174 @@ +#include "gui.hh" +#include "menu.hh" +#include "help_box.hh" +#include "virtual_keyboard.hh" + +#include +#include + +class NetworkView; + +class NetworkMenu : public Menu, public KeyboardListener +{ + friend class NetworkView; + +public: + NetworkMenu(Font *font, HelpBox *help) : Menu(font) + { + this->help = help; + memset(this->messages, 0, sizeof(this->messages)); + memset(this->strs, 0, sizeof(this->strs)); + } + + ~NetworkMenu() + { + } + + virtual void stringCallback(const char *str) + { + switch (this->cur_sel) + { + case 0: + strncpy(Gui::gui->np->NetworkName, str, sizeof(Gui::gui->np->NetworkName)); + break; + case 1: + strncpy(Gui::gui->np->NetworkServer, str, sizeof(Gui::gui->np->NetworkName)); + break; + case 2: + { + char *endp; + unsigned long v; + + v = strtoul(str, &endp, 0); + if (endp == str) + { + DialogueBox *error_dialogue = new DialogueBox(network_port_dialogue_messages); + Gui::gui->pushDialogueBox(error_dialogue); + } + else + Gui::gui->np->NetworkPort = v; + } break; + default: + panic("Cur sel is %d, not possible!\n", this->cur_sel); + break; + } + this->updateMessages(); + } + + virtual void selectCallback(int which) + { + printf("option entry %d selected: %s\n", which, this->pp_msgs[which]); + switch (which) + { + case 0: + case 1: + case 2: + VirtualKeyboard::kbd->activate(); + VirtualKeyboard::kbd->registerListener(this); + break; + case 4: + if ( strncmp(Gui::gui->np->NetworkName, "Unset", strlen("Unset")) == 0) + Gui::gui->pushDialogueBox(new DialogueBox(network_unset_name_dlg)); + else + TheC64->network_connection_type = CONNECT; + break; + case 6: + printf("Send message NYI\n"); // FIXME! Send message + break; + default: + break; + } + } + + virtual void hoverCallback(int which) + { + this->help->updateHelpMessage(which); + } + + virtual void escapeCallback(int which) + { + Gui::gui->popView(); + } + +private: + void updateMessages() + { + memset(this->strs, 0, sizeof(this->strs)); + snprintf(this->strs[0], sizeof(this->strs[0]) - 1, "Set username (%s)", + Gui::gui->np->NetworkName); + snprintf(this->strs[1], sizeof(this->strs[1]) - 1, "Server (%s)", + Gui::gui->np->NetworkServer); + snprintf(this->strs[2], sizeof(this->strs[2]) - 1, "Server port (%d)", + Gui::gui->np->NetworkPort); + + this->messages[0] = this->strs[0]; + this->messages[1] = this->strs[1]; + this->messages[2] = this->strs[2]; + + this->messages[3] = " "; + this->messages[4] = "Connect to the network!"; + this->messages[5] = " "; + this->messages[6] = "Post network message"; + this->messages[7] = NULL; + this->setText(this->messages); + } + + char strs[3][255]; + const char *messages[8]; + + HelpBox *help; +}; + + +class NetworkView : public GuiView +{ +public: + NetworkView() : GuiView() + { + this->help = new HelpBox(Gui::gui->small_font, network_menu_help); + this->menu = new NetworkMenu(Gui::gui->default_font, this->help); + } + + ~NetworkView() + { + delete this->help; + delete this->menu; + } + + void runLogic() + { + this->menu->runLogic(); + } + + void pushEvent(SDL_Event *ev) + { + this->menu->pushEvent(ev); + } + + void viewPushCallback() + { + this->menu->updateMessages(); + } + + void draw(SDL_Surface *where) + { + SDL_Rect dst; + + /* Blit the backgrounds */ + dst = (SDL_Rect){20,45,300,400}; + SDL_BlitSurface(Gui::gui->main_menu_bg, NULL, where, &dst); + + dst = (SDL_Rect){350,13,0,0}; + SDL_BlitSurface(Gui::gui->infobox, NULL, where, &dst); + + dst = (SDL_Rect){350,242,0,0}; + SDL_BlitSurface(Gui::gui->textbox, NULL, where, &dst); + + this->menu->draw(where, 50, 70, 300, 400); + this->help->draw(where, 354, 24, 264, 210); + } + +protected: + NetworkMenu *menu; + HelpBox *help; +}; diff --git a/Src/gui/options_menu.cpp b/Src/gui/options_menu.cpp new file mode 100644 index 0000000..5586447 --- /dev/null +++ b/Src/gui/options_menu.cpp @@ -0,0 +1,154 @@ +#include "gui.hh" +#include "menu.hh" +#include "help_box.hh" +#include "status_bar.hh" + +#include + +class OptionsView; +class OptionsMenu : public Menu +{ + friend class OptionsView; + +public: + OptionsMenu(Font *font, HelpBox *help) : Menu(font) + { + this->help = help; + this->setText(options_menu_messages); + } + + ~OptionsMenu() + { + } + + virtual void selectCallback(int which) + { + if (which == 9) /* Game info */ + { + Gui::gui->status_bar->queueMessage("Resetting the C64"); + Gui::gui->popView(); + return; + } + /* Select theme */ + if (which == 12) + { + Gui::gui->tv->setDirectory(Gui::gui->theme_base_path); + Gui::gui->pushView(Gui::gui->tv); + return; + } + + /* Doesn't matter which otherwise, it's just selection */ + this->updatePrefs(); + Gui::gui->popView(); + } + + virtual void hoverCallback(int which) + { + this->help->updateHelpMessage(which); + } + + virtual void escapeCallback(int which) + { + this->updatePrefs(); + Gui::gui->popView(); + } + + void updatePrefs() + { + Gui::gui->np->Emul1541Proc = !this->p_submenus[1].sel; + Gui::gui->np->ShowLEDs = !this->p_submenus[2].sel; + Gui::gui->np->DisplayOption = this->p_submenus[3].sel; + + switch (this->p_submenus[4].sel) + { + case 0: + Gui::gui->np->MsPerFrame = SPEED_95; break; + case 1: + Gui::gui->np->MsPerFrame = SPEED_100; break; + case 2: + Gui::gui->np->MsPerFrame = SPEED_110; break; + default: + panic("Impossible submenu value: %d\n", this->p_submenus[4].sel); + } + } + + void updateSubmenus() + { + int submenu_defs[5]; + + submenu_defs[0] = 0; + submenu_defs[1] = !Gui::gui->np->Emul1541Proc; + submenu_defs[2] = !Gui::gui->np->ShowLEDs; + submenu_defs[3] = Gui::gui->np->DisplayOption; + + switch (Gui::gui->np->MsPerFrame) + { + case SPEED_95: + submenu_defs[4] = 0; break; + case SPEED_110: + submenu_defs[4] = 2; break; + default: + /* If it has some other value... */ + submenu_defs[4] = 1; break; + } + + this->setText(options_menu_messages, submenu_defs); + } + +private: + HelpBox *help; +}; + + +class OptionsView : public GuiView +{ +public: + OptionsView() : GuiView() + { + this->help = new HelpBox(Gui::gui->small_font, options_menu_help); + this->menu = new OptionsMenu(Gui::gui->default_font, this->help); + } + + ~OptionsView() + { + delete this->help; + delete this->menu; + } + + void viewPushCallback() + { + this->menu->updateSubmenus(); + } + + void runLogic() + { + this->menu->runLogic(); + } + + void pushEvent(SDL_Event *ev) + { + this->menu->pushEvent(ev); + } + + void draw(SDL_Surface *where) + { + SDL_Rect dst; + + /* Blit the backgrounds */ + dst = (SDL_Rect){20,45,300,400}; + SDL_BlitSurface(Gui::gui->main_menu_bg, NULL, where, &dst); + + dst = (SDL_Rect){350,13,0,0}; + SDL_BlitSurface(Gui::gui->infobox, NULL, where, &dst); + + dst = (SDL_Rect){350,242,0,0}; + SDL_BlitSurface(Gui::gui->textbox, NULL, where, &dst); + + this->menu->draw(where, 50, 70, 300, 400); + this->help->draw(where, 354, 24, 264, 210); + } + +protected: + OptionsMenu *menu; + HelpBox *help; +}; diff --git a/Src/gui/save_game_menu.cpp b/Src/gui/save_game_menu.cpp new file mode 100644 index 0000000..da7ab60 --- /dev/null +++ b/Src/gui/save_game_menu.cpp @@ -0,0 +1,143 @@ +#include /* unlink */ + +#include + +#include "menu.hh" +#include "file_browser.hh" +#include "game_info.hh" +#include "game_info_box.hh" +#include "utils.hh" + +static const char *save_exts[] = {".sav", ".SAV", NULL}; + +class SaveGameMenu; + +class SaveGameView : public GuiView +{ +public: + SaveGameView(); + + ~SaveGameView(); + + void pushEvent(SDL_Event *ev); + + void loadGameInfo(const char *what); + + void setDirectory(const char *path); + + void setLoadSnapshot(bool which); + + void saveSnapshot(); + + /* Inherited */ + void runLogic(); + + void draw(SDL_Surface *where); + + SaveGameMenu *menu; + GameInfoBox *gameInfo; +}; + + +class SaveGameMenu : public FileBrowser +{ + friend class SaveGameView; + +public: + SaveGameMenu(Font *font) : + FileBrowser(save_exts, font) + { + this->loadSnapshot = true; + } + + ~SaveGameMenu() + { + } + + virtual void selectCallback(int which) + { + const char *fileName = this->pp_msgs[this->cur_sel]; + + if (this->loadSnapshot) + TheC64->LoadSnapshot(fileName); + else + unlink(fileName); + Gui::gui->popView(); + } + + virtual void hoverCallback(int which) + { + } + + virtual void escapeCallback(int which) + { + Gui::gui->popView(); + } + + bool loadSnapshot; +}; + + +SaveGameView::SaveGameView() : GuiView() +{ + this->menu = new SaveGameMenu(Gui::gui->default_font); + this->gameInfo = new GameInfoBox(Gui::gui->default_font); +} + +SaveGameView::~SaveGameView() +{ + delete this->menu; + delete this->gameInfo; +} + +void SaveGameView::loadGameInfo(const char *what) +{ + this->gameInfo->loadGameInfo(what); +} + +void SaveGameView::setDirectory(const char *path) +{ + this->menu->setDirectory(path); +} + +void SaveGameView::setLoadSnapshot(bool what) +{ + this->menu->loadSnapshot = what; +} + +void SaveGameView::saveSnapshot() +{ + const char *name = "unknown"; + char buf[255]; + + if (strlen(Gui::gui->np->DrivePath[0]) != 0) + name = Gui::gui->np->DrivePath[0]; + snprintf(buf, sizeof(buf), "%s/%s.sav", Gui::gui->save_game_path, name); + + TheC64->SaveSnapshot(buf); +} + +void SaveGameView::runLogic() +{ + this->menu->runLogic(); +} + +void SaveGameView::pushEvent(SDL_Event *ev) +{ + this->menu->pushEvent(ev); +} + +void SaveGameView::draw(SDL_Surface *where) +{ + SDL_Rect dst; + + /* Blit the backgrounds */ + dst = (SDL_Rect){20,45,300,400}; + SDL_BlitSurface(Gui::gui->main_menu_bg, NULL, where, &dst); + + dst = (SDL_Rect){350,13,0,0}; + SDL_BlitSurface(Gui::gui->disc_info, NULL, where, &dst); + + this->menu->draw(where, 50, 70, 280, 375); + this->gameInfo->draw(where, 360, 55, 262, 447); +} diff --git a/Src/gui/sdl_ttf_font.hh b/Src/gui/sdl_ttf_font.hh new file mode 100644 index 0000000..84fd843 --- /dev/null +++ b/Src/gui/sdl_ttf_font.hh @@ -0,0 +1,63 @@ +#include +#include + +#include "font.hh" +#include "utils.hh" + +#ifndef __SDL_TTF_FONT_HH__ +#define __SDL_TTF_FONT_HH__ + +class Font_TTF : public Font +{ +public: + Font_TTF(TTF_Font *font, + int r, int g, int b) + { + this->clr = (SDL_Color){r, g, b}; + this->font = font; + } + + ~Font_TTF() + { + TTF_CloseFont(this->font); + } + + int getHeight(const char *str) + { + int tw, th; + + TTF_SizeText(this->font, str, &tw, &th); + + return th; + } + + int getWidth(const char *str) + { + int tw, th; + + TTF_SizeText(this->font, str, &tw, &th); + + return tw; + } + + void draw(SDL_Surface *where, const char *msg, + int x, int y, int w, int h) + { + SDL_Surface *p; + SDL_Rect dst; + + p = TTF_RenderText_Blended(this->font, msg, this->clr); + panic_if(!p, "TTF error for '%s': %s\n", msg, TTF_GetError()); + + dst = (SDL_Rect){x, y, w, h}; + + SDL_BlitSurface(p, NULL, where, &dst); + SDL_FreeSurface(p); + } + +protected: + TTF_Font *font; + SDL_Color clr; +}; + +#endif diff --git a/Src/gui/status_bar.cpp b/Src/gui/status_bar.cpp new file mode 100644 index 0000000..db066cc --- /dev/null +++ b/Src/gui/status_bar.cpp @@ -0,0 +1,70 @@ +#include "status_bar.hh" +#include "gui.hh" + +StatusBar::StatusBar() : Menu(Gui::gui->small_font), TimeoutHandler() +{ + memset(this->messages, 0, sizeof(this->messages)); + this->head = this->tail = 0; + this->cur_message = NULL; + this->setSelectedBackground(NULL, NULL, NULL, NULL, NULL, NULL); +} + + +void StatusBar::queueMessage(const char *message) +{ + this->messages[this->head] = message; + + /* If this is the first message, display it as soon as possible */ + if (this->head == this->tail) + Gui::gui->timerController->arm(this, 1); + + this->head = (this->head + 1) % N_STATUS_MESSAGES; + if (this->head == this->tail) + this->tail = (this->tail + 1) % N_STATUS_MESSAGES; +} + +const char *StatusBar::dequeueMessage() +{ + const char *out = this->messages[this->tail]; + + if (this->head == this->tail) + return NULL; + this->tail = (this->tail + 1) % N_STATUS_MESSAGES; + + return out; +} + +void StatusBar::timeoutCallback() +{ + static const char *text[2]; + + this->cur_message = this->dequeueMessage(); + text[0] = this->cur_message; + text[1] = NULL; + + if (this->cur_message) + { + Gui::gui->timerController->arm(this, 500); + this->setText(text); + } + else + this->setText(NULL); +} + +void StatusBar::draw(SDL_Surface *where) +{ + SDL_Rect dst; + int x = 130; + int y = 12; + int w = 496; + int h = 56; + + if (!this->cur_message) + return; + + /* Blit the backgrounds */ + dst = (SDL_Rect){x,y,0,0}; + SDL_BlitSurface(Gui::gui->status_bar_bg, NULL, where, &dst); + + Menu::draw(where, x+4, y+4, w, h); +} diff --git a/Src/gui/status_bar.hh b/Src/gui/status_bar.hh new file mode 100644 index 0000000..0f11bbb --- /dev/null +++ b/Src/gui/status_bar.hh @@ -0,0 +1,37 @@ +#ifndef __STATUS_BAR_HH__ +#define __STATUS_BAR_HH__ + +#include "menu.hh" +#include "gui.hh" +#include "timer.hh" + +#define N_STATUS_MESSAGES 8 + +class StatusBar : public Menu, TimeoutHandler +{ +public: + StatusBar(); + + void queueMessage(const char *message); + + virtual void draw(SDL_Surface *where); + + virtual void hoverCallback(int which) {}; + + virtual void selectCallback(int which) {}; + + virtual void escapeCallback(int which) {}; + +protected: + virtual void timeoutCallback(); + + const char *dequeueMessage(); + + const char *messages[N_STATUS_MESSAGES]; + const char *cur_message; + int head, tail; + int x; + int y; +}; + +#endif /* __DIALOGUE_BOX_HH__ */ diff --git a/Src/gui/theme_menu.cpp b/Src/gui/theme_menu.cpp new file mode 100644 index 0000000..028c520 --- /dev/null +++ b/Src/gui/theme_menu.cpp @@ -0,0 +1,99 @@ +#include "menu.hh" +#include "file_browser.hh" + +class ThemeMenu; + +class ThemeView : public GuiView +{ +public: + ThemeView(); + + ~ThemeView(); + + void pushEvent(SDL_Event *ev); + + void setDirectory(const char *path); + + /* Inherited */ + void runLogic(); + + void draw(SDL_Surface *where); + +protected: + ThemeMenu *menu; +}; + + +class ThemeMenu : public FileBrowser +{ + friend class ThemeView; + +public: + ThemeMenu(Font *font) : + FileBrowser(NULL, font) + { + } + + virtual void selectCallback(int which) + { + char *p = xstrdup(this->pp_msgs[this->cur_sel]); + + p[strlen(p) - 1] = '\0'; + if (!Gui::gui->setTheme(p + 1)) + { + /* Something is wrong, reset to default */ + Gui::gui->setTheme("default"); + Gui::gui->pushDialogueBox(new DialogueBox(broken_theme_dlg)); + } + free(p); + Gui::gui->popView(); + } + + virtual void hoverCallback(int which) + { + } + + virtual void escapeCallback(int which) + { + } +}; + + +ThemeView::ThemeView() : GuiView() +{ + this->menu = new ThemeMenu(Gui::gui->default_font); +} + +ThemeView::~ThemeView() +{ + delete this->menu; +} + +void ThemeView::setDirectory(const char *path) +{ + this->menu->setDirectory(path); +} + +void ThemeView::runLogic() +{ + this->menu->runLogic(); +} + +void ThemeView::pushEvent(SDL_Event *ev) +{ + this->menu->pushEvent(ev); +} + +void ThemeView::draw(SDL_Surface *where) +{ + SDL_Rect dst; + + /* Blit the backgrounds */ + dst = (SDL_Rect){20,45,300,400}; + SDL_BlitSurface(Gui::gui->main_menu_bg, NULL, where, &dst); + + dst = (SDL_Rect){350,13,0,0}; + SDL_BlitSurface(Gui::gui->infobox, NULL, where, &dst); + + this->menu->draw(where, 50, 70, 280, 375); +} diff --git a/Src/gui/themes/default/background.png b/Src/gui/themes/default/background.png new file mode 100644 index 0000000000000000000000000000000000000000..7e8e03f8cfbd8c6d5e7ec9e8d09700ef3065bdc5 GIT binary patch literal 13879 zcmeHucT|(zns4YJ3MkUM1OaIuBGL(h0uc}_h}0ledhZZG5EPISq&HEDN|O#!{peDH zAiacMq=eoACo8S)(h9l{fp%yPvY3@_T-Hqw_%R(goHF5D4TF zT>b7N2!uEY0wJ2ABnMX{e@-rdKSXYi)RZB`eeA2?4Y`?y+Fb~q@c(^7emuBB<*csn z27yr16JA7+)O2QWk-{CWb&q0W%BM!xGW%#7TX&#HzYGayxf7av@$n6<(jK-5 z8_O}VgkmikeFK`2ffqVXR<~I!6QAYD7&U15ZWzdX5O|ZY%$j)dCFPZnp7?NytcGD6 z&Kz4lODT}}^vB^K*Q$))Gn~T2^06Y;U@br;DlRaw)@`|+nfH})Ff%U?DGJJy)E$Rj zu6^!cPW+3+kK|);KyYcZfGKl7c0R;+|Hty~f~$;cEqg*jLMR=?yA)k@HZLnD*HsoJ z+^s(N&Ms?e4+TS8chG#StxbuDxKJj{+g{TmZjWany6}n^X3)q9N9}zXptL7_3egC< z*ZjEI%#`n|s>QZ--nDu=7 zTl?wy6cNL!Sj#a-4m}j~*T~3VotKlXtu6CS3rb$K=$vogQlq13ZrhJG>!J&%7k6Rf z`Kc!-zIh_XB+a<+OV?>9v+fHdc_NIYMj~G*}+2vdV|Bms@Xc+S_lJEuMEY$Mc2K} zsWg}Qc9+)6YR>(4D2Tq=4&6Z3*iX@*F0RVT$_hyqHz$u|60=(T zk#Lb+I+oUdhJ@X3y%Zw9+aobq(MT0UZ)e*7{*KYvh}ltwq(ApyzP9ynp?;x$dDzd7 zYP)eU{-F^O5yp+!Ec~gpW7CUN*y{_0i}4PCqZ;<70uH#A&6Oj;3Hc zso(W(LF(p8fQJYh)x;uB=a}TTTj?t*Dx7~kRCAeh>DUgFs(&8NO;WR*>36j0)zsaH z+w8W6;q=2Uv9*I2v$QjJjKTr4)Ra5DMv|!ITuB}lD<|<+q44qDTg36fIQ(UvVS)<-SENCtrHR`A*X3q9PFrLqk6bHYo?b_9(@Dk6#C$W(g1B;NX~aZn-3E zSQRzf5>D7?q8OqN9eD1RC~EwJ#X9}_LRUN$kIoCb*;@VbQRii+m1hlMMcRFNZc|pS zB7!!l0|{aJ_j0Zw?yMWDG&*tlzV(sV`+Wx!LX*9Oq4{`NLn6KMKBQ)&Y9d+Q=cX4X zKnk}}&D9c4Yu$8qAe8aJVd33*Da7CV2ein&zaqBF!9|mVqT)%U_%5iF31jz><;LK-o=KAXXqbH0$|3UiJQGqCA zxi5o_;v%yWI#WTv;>BfxkqAoRzdxWs#!|4V^;9J1>w*_m(K9=|MWi89Po!G zU2lcJqb#WIx;}Y35d*Z*)Kast`Bn%8U6ow(XkHhTU~?oDO_p`}b4gDN0zzYdzBU&j zo{0q>Yb^Dow9JNcnJDVYt>Ks4dOqv*Gupl`g(L(kk&7$qig+oOy%b9~^e+N2aI*=I zTta7Qr{)PG8q<}tn}I*vp$yK2HHJwd>SJT6Ta)R6p`LWFp`@}@3&cv?q@B4eHm^f( zsj=Qv4lO(~G`pvqzAd1Q@Z~WVJtnu#@L+5@87g`9)s%=39N2E#&lJ~f0u^MMt_>H} zuNh;_e!LT0OsU&%Iz}vU;jwM8TEuY1*V)V-Hk6^1!Ri;~n&53LN^sN@S61iocPW>! zX+X*h`~Z=(rIkudJZ}F5CpeOD)F0sFWqQw1ncz=G+_u}8NSsGV0_Pf*Cm~NR|LN(4 z_bh6msHmj z2Bi9kXhMQW!m+60WV|aJqwP(-v1ZuGKT)g_#dF0>&%b?+D9l(blSlxL%3Q9_9cy;W zdywA0BgPc;*y?r^QD$LbVU8De+J3SoE}RRQTx3|iQ&|%5mX7#Rpni`Z`k0F6t{EjA z5B$A1^0vsihINk43v$z$=HN--v~rhn>4o&}f*Ky=iv73ElDWQ6*=c;9xM>;$oflE-;i-+DWk*8hD)w_5v4E~D>>f=mz9 zuk45`UwN&>`sjfP!8-I%WEqhLn9eQ%)r_Is8?bFso(u2q^=BQ6rxdQ9&2J630PCn^j}MZB=6_H zGV&YTu%8^b*gE&lwEC!fMORP7(vqye36GiUc`l%Eixg#qte&Se{Wa2br!71D;n>dy z2I}wub#)148|%2@8Ny+zUHK6CquhN%=;_YNIS%EtkrTT>m7CQee8rV&h(c@TD@d*V z(?7WU4tV&kc+avZk?5eH4NB!AsW;1KlRwk*YvS`M2r^_ribT)6ZZvPJqA7v{k(pRg0(1Oqv|Cl4KJLWtcSknUcK;Y$B}gzap0!T z18vj)YU07Lcw|`X$~R)tC;`URG9LF-$7kEVWrY#M;~PmpPm@ zL2?)-hzraIRR{8}cbd7N{$RA8H516ZaUB{9g$@lZd@1N0+P?vl3T<9YLiBNXO+J*J zVjH_xy{DL$&NaJMiPtDnDUYG}v?0X1o+ zn~7BNtS4%k0 zG|!>SqmI$S{7;6il+X3j#q)1!N5z3EP>)}(; zJgX~65ew3lp~#Ac42m$?4;|mE28_y#109$Wa-DhGAIVs?o^Yb z$RRcw)Dk9Aq2tTr!Rm~W!OSYkYK=<0issVx-{TkOU)b8tg|Ru#)bIB3I@o-S?N(R+ z@tg(akndYAY(8D@qsb{1O<{L((_xjh597rpx`N5ViW)8H8KIyXJyJlpPpKfzpKA5UMm}VccyQc*SDA9sW5ifazR}D0Qr1bcVa@N| z4vGDjht5NtaLQrx{;{at1(HJ=m zaI z1{88;Kn*^K36PNl!n9Cy<~ce7{lmlUCFAr41_nQfM)&=K8uvXG;%Ul~!=ZFRHh2#h zR@yx=i#9t4#%sbI%yp{6@mXkFuZ6WC8Os3Re;plgwd0T@q#_(ahq+5|}@)r-Ngc@}MkzTGhzW_k@|sJ^FGmoNqFLGY0sBwSf|<2nkx z48Pyq>F#I`%__+0ue_+K>Eqa!rSCkP|EUnGy}Ogog2yyjGzSrZ2$8KL5K{n}Ovi6d zAdZyQ)jgP@A*ykn{qvc=epi3C3UEHYc6AL6YBniHi`}K(MJ1w@pC2h2{0{R#LchqR zm=3zuvga-2C;Mw1u{^J%;vw+(>)U5yfv-cfzoD2TC4AH5WPMt4sFPvybx)o= zaqg2@eut2Ph$me}sYlNpIKFyzvCMLw)+{Sm`;mgT*bUz&UXe}eP!^d_%qAHb>~1~c zb*D2pY!gh+#D@=#>NnB9GcfkhAeS$8t6pP&uBtAs+@D*&DYwQ>ecM%)GT4X_eysvj zC#YB<1->M!oMZM@_3c2N5vl^G8qO<}ujEg?R^6PKMkiv*39@^;0@{DpXJ;sWUxxOp&HLE5Kr>|>+Dgn60c5H))9h3#66qka~c z>BHx1k;osT)m6W&jin4oFBC{Iz@90hqgW(7k0&?Gg)}B2^8+;^;T^(jjEM|3IlO|I zW_=71F;uydXJvFecgu7pPek;LUgY`5!!;u$GI@kViIQ8D)I|B1NO(e`jgWPHlZhGN zAM!0|4m9E@@`$)F8<6#gCPGgRayJRBd^6z{!5{=OA!xExquIL%g)vRxT1iu8rQJxG z`|2Y`QKL@5{PaITH*jA~jl#S=>iPO;>8)G0w${thH{DlsSdqKBCWn1ubgniwPepWI z$31R3v3r0+%keO(y9V<#2zjkNrU}5}j_nS*97g8J)T``2_?*kzV!q-X8`|fbPWf44 z#l-sAg9~d^P2oHiIzh^sUE!g0JQ^sonOyztfNu09i@T_Sdm%$M42EtQ3)#u9bc0Q_ zhHfp6^W6PX=AQqM)qDZq1vi9*x&ZXE>*Kq(a;LFE!PqbHVFI+mngyOZ08j%EF!dD5 z$4i<(k6%2P*JFP)1b~W7|7?m^%)H%+B9ROX41~5DAR}9mh|`xW5?1}Aqn+CwT<9_D zEaPa@GJ=BH++uUGHa+nCIEo9F3BZJuJ0avhfBkCRsK)e#&?>421Sm9}E{aj{Z0$)D zj2=!UDT&gVk?9M(vzm@5NwNt3-caCOHH*6?DM@IqH=O(T_xA~PYHQzvP3+IKFa8(w z1#6YXTYs#HSj#n~T+<@19YD6apCLkjKnLzxJTj+;uU?OBS`LfyfZ@ofVdpMp+eYG4 zRA>BIok&gi1d5BK zUi5Q=NL;f&Y?z`LAPZnA(2=~C?$*7~L`SSGX59A0gH2{7Nc`9Sr|Y53N89r<3$ZGM zBZ0w9AASPCLF@5w2?BIR_M=~eCHka8>`EFE#d*W~kB)TL6=q?hsY^k`p*pEz6Ak^g z_V&W{SO+7Sz`0)EuZ<>A+GT?a683nz_{72BkkE-JSdoPN8ZDkU!j1#p?TdHY3x2ZF}jOGZibbXcrrE|EeoR!r64^B}R$ z=E-bV{n~34byR3y-va;{n3&wO!ljh+X(T!?rC7UeRE|8-GweO@LR}ai{4VdJvYhZ2Vatra?=}n7W@iV%2{;FX9qEzPZvX#p<3Kb#DYEp zq^MiG(C2k)rxE3$HUc^<*-AmexpN%Yh4*QZYq%-kJ4SB3l5zofQCh_#Zis^ow+3}9 z^Eb?$E7v%V*%S2dGhTZY8~e!rT!mJl)iTLg6$M=!F>3Uesh;*-qxqTAy(nl9rC&mV{1Wwrg?>5jPc^}P& zkCjwA?+aud@8JH!OS#M^f~Y>h9E zj*WF?cujXz*bF`^v!ME@`j*(V^L?XmiU&hR#w!Q53bIcE3Qbj2iG&_tf(Ujv=>}lF zy1mgkmpz#krR$Q8d=56xhcdikMV_hpO*|bw-Q@WqC9j4XzOL-HE!(cn{kiAzn(e3G z#%fc|!M_^!9iBupw|}J#4D~lQK5mGX+mr^V$q$k0$w%j74%Jht03Y#U?qrV0&(0Fl zB4*$atfiw8N40v&-k%@wQ0WErWJeGYiRUqs5kOHfN9|HIGcTz@CU{caYyz5G#My7X z*%|8;bgCPYJV+PF#8q_ z0J`do%(rvB0i0U1fYKnKz1Hb2S3{``g(xfRmNT)W?gDR))j?(#w{3d!sQ@o3^#nIh}V-WlzEKJ<)<4fFAzNw<5k z8RhP&iZUXrtbNzjv5u}x3jD?%NKrp8VZYk>GgH@jB<2Cn+c2$=f^D%ePnh)L~-K9=rY1C+ixE7c{pUA7H z;1MdnZI9Qu@^(fT*1RX)V9d>V|~Gb z;n!0}>CM*xwa0#VB73aF4V#?DEGqS!@m{A|eaY6UvJwRmItTlnOGjW};md`H}IJzwWhxt(cALZA z>!Df4$H!}Mn{_NQu23iBZd$jP`%>G8%T$S#N)IJm%Y_yL)$Wv~gqxNi6`siy)GSV{ z(PaI(bIGvFY{o<7w|xrDo=OUJrWT>d{j3rkuE3C0X6mn}vAMgh%Q3m7B_gm6k zXVDR8YF&#`5;Hyvj!>hV8_mNquxnXjnVv zB*g~1u1=g#ENVFf>#G10di9&Baf>WbSpQD~jJ>(i zv&;1{Y%7GX;PgZTRk18<2If2x)%fqCQWY78zb=?1^77quT=>KH@HbI&X$NQbkRGC! zjLAqRy6sq7Wd3C0ocQX9o6n))q1gs6V)=WPKXKXZvgDoh_M-Y-Ok{pyJRSE_I#efO z#6DZLOM0=UIoM#Pv;b;zU-@;RgRqHI5;WJ?gZEbD;u{-! z>nwNX+6r%LC+jGC2b)}-PHC?lo{OJKpjK3En(G2tt_r)mUYE<~&N|G)mh|yBr*hw6 zy{87f_p{ivb=0@Z}^jT%5h6{s8IEV zeiHJpr{^WE13B9kJZe0Vrz08VDT-@d4uNlC@2HRUkKRuuA4sO#(Um{zDK|P?gI(@i z(R}RKuw!0mcXXTNMEA1bR%9Kc%VAW%a5=y#ZR+uSDn@FO&&6OjdAaUlXVBp zv3B$1gbL>(VhmE35#9S3#gH^n*jr&C(L|I5i#E(%M$cqVoKa!R!EEK5%Lngjdz-Vx zxiZn?s3jjM=OMoQvJ-rxp2;xZl^Sfv^43|2fBH~h`qR^|;vxQ~CoS5}%TZ$$OI390 zlr|Q9Q<%I!jLAh#9dsoEr@sA+s&Le(9_P7)c#3*87q!%u&)z5p|@BEnHis#E%a;1aT{+Z+m%__01MbA7 zJ!0#(k-NX<3U|R(P_qBwJHb)ur0_x*{uDx7=^+`#Y*3FZ@+ukM*|}jOQ&!bmqZ^n1 zrL4wX)7asXcz49w#^Nq}K*v0|pgqSWb9ChGry+IemL;8DdtqZiCDH0SxhwMlt7u5)L4Qqa;!2Fu{4#If_ zWqBvzrHET6QEIHv79|>Xu+77k~o-8}cGk1A9NiAxhS z+g7hTSerWc;EiqV_bieZV?+ax)6^BlZ6IGqU#-)w!5w%CPuC<{? zDBjq(xUY`pkE`c}VjT_@l^Cl7UM^4hPyPJ$pp(oDB^GY4rAr21HRza+R;-zrck`jt zS7oFh=zEZwmil6P9Nsx0pGvW$n7Z!b4`%wO#LwldCP;xM+8z%I3|1v_Syj0+L6pzmMDkT(O}y$zqD!_Nnzl33YuVwV5=v<};Ld7i)uQ<| z=l1aE>+oHujJjKJ);YFt#~kA}?iG>IGxiz+VF)8|0r;4%>1K#P;mQt{)H1|z&Ebj) zm8YZh5Ae73vp@J>E!rT9Moz4)%Fd)Y28LFAbwFdrw2OJ#XlYaxnr9@gduQ%rEd*2j`{8%ESQSqSO{F6KOXql=0SF>)!WaGk&Wnn%b4 zTOBY+#(llbUI@EkD8I&xfJ3&dZeI9YrJQDkxIq_StS{nc0d$?YEF@>=E(D=#wi=$7im}jc;A`iARi( zvb9hO@m!HEi8+ku!oqHeRZm>j{MfPq73n}9aT0PVq>cX_Q`{zJptve>ueZE&F;c2{ za%)1ye{&6HIh>Vr)9wIqJUrxebF))SM_-ogJcR2ss5l^_E>jGSB2AwbffyPZvWT0J zf~Z2NtE=mOScf5-X;9;A#X8~G_Y-`|pgbDH8Lx=h*s9AKOQ|jhvZcv=T6@@=UMHFx z7?WwCWS6>}2@|#YS#J0m&aIYN&~!u;E%${vlL5~5D)!1i6tip{pTT&X5^G&n!`n8c z2z_N?dw%1A+P~GP6^A zVd-osa-lqQH14bCE~8_uAC1QFEe7kO@teq#jTqN{q7oraBT>OV-|G`EH&7a)JfTXM z>B>pJ4gEHA{&_Y0t^ihU9>?x=pzDuIq|k4ydXrdn+bjwMm2l+Q$#$Mp169z$foIbu z3Q83*(Xt3pj*46CPU>hl7>{HSdg{DCq$gqB$F6wtGsg9YU_PXc?ZWw9>lLJe`RzcH znncNh;Xk}PP1~ba(5vy7J|Y~ASjPx2zB0 z7=jA9!Bq5**=7)d&s`1%+t#*}+b3vP^^h3YDMtB%I4`Mp_tC>&Pn;%(=EsKElABia zk@zI**DR+K-#>cK*UVmA8A%iFeg*)q5DF$IXP@;q_a^t6@Ev)}2GSe&hF2dkF5I+d z&qX&ff^YRopKM9#JbYMRRgzno0aGYV<~ny})P^;@yv%#B6hMza%V88VvqP#y22LB; ztox6Qc*R3v*aMl(RWB~gMT(Kn*dcJN5Fx#iWxo*&TEt7CZ@8WD%MD&!G;^yBKYM$= z;>iQEsPq6&m#)-EvBqSqh{1Oo5l9Fd)CgS}{1^xSE$Hz5na6*S7|v5p?5zk&}49i92#9KI;$Hg-)ia z2+{7FRrX`bV3>{AO0H8JDW1j^miL*>{`ra>c{FR}yP7K|O(U*KK+r&u-~BwCL$&)d zmS_f$lw4ZIRsZs)nRvng2mV_8CP2>vve*ZfSH6c(JbwJRrQT<^=Imf1MZ%hpD)f3+PKkrABm>34JUojMH9|+IEN=Q3He2VCJhvnFme?(sCW&S zIxbt^DF(}}(T-|60JH<_AXXaLmG_P??E1O|AdqOL-dep^VrdAh4shQ2PTrVFo+wV= z6`pC(=?;`24jq1S2JAfqU=g#dyMTE|wB#&V=r}f3?QvfsqPx)>*y~7wSv&2jwrht5`^7t`5;fVlavj$8l z`>AgUf{*ib5C{YkDVj77s3zvXo==`WeI#)8Q*rSUebx~v0eb~7#gt;l7u|xI8|6|wGv^2r17Z&#y&7uHz?8c27pcu&oL&&_m>*M!FJ~)(o`0x@ipuh(& z937GO95pF%?Qgubz4fv9TUs`bj+<4E zh^V+PUv8+rWo-ipUFUeE-ElYK{7=BWSy>r9b`=97n#L+M6qTzCm=ovCjgg@~q1Fj7xcA!r4-o`gjw zo$tYV7l6*jz$%+mProEExh8O>fIwi3=i9ca*}J?8rlwQpK4AC27zD!sg_is5F71>q z@A{k^V$tvKgfQQFL04-O4FJ`z07wR4Ap!};d3(QyB25~6J>+yv3=OHTT1$Z`c<(ol zwG{)`d@xwpTN{bVRtX;fTrhCaQ@Rlx>VqjSL}OEpbjV?8qa--&K>(ZH+!_Vcy)as? zJ^)R2fA<2sxy9xCD5yie6G3K9NYB`LK48Fo1hxT|v$eAWRbnVzXPJGtegza9I8>hC zu|G0jPRCuLy1YEzNc1qG7vgEGQC(n1;q@0y56GLrsYe+M@I5fzvvF|9B}{*wJXzmj zHAYV${l7)?0UDZY`>2EGc3Uygx^DyFthGJv_VQ!@EhKa_I(=6AJ7oyj0Py#|C^X5( zEc{^FuoRJ2`tY=gVy_|a0>vy$RjjL^>9@o~`m;43u>VxF3$CNunnf4>NO8#i6pqSa`a_m>y{-Vz3Kvy8 zt$S+&D-~=>Dk`zE*d+O{Yggfp}LqKCV-ohLN z7LbE!8|ot9v_M%1Z*M}tpvM9NY}rLvgdz|_pafRJKVSHtz3(3$@DFeQ`Sbqy!vFm~ z|M`9YAi+Pp{SV*w_l5s=3jF(h|ETHz5$NCe=6}gm|E}r(2Noh)p#!Jxzmv24f27<0 zbJ+R2E&uV<{M{t~BhbHz=>LfT|L&|OBIlLKd9|rF1ipGy0e2U ze!wh5ZyGrdn5h*VqbSV`X&&N14r)*fjMT4!7U;FH;rFQ}ZxGEImZr!j4v5b)=6L|E zDD|*zgJg@PLxn)?#iqDI05zY7%+XyFe5Fabqp&2xhn#N4x8ok+^MXm=35pr>=t#nE zCx*@CNN2#rO*Tk~gN^Wi+$GF?oI}%BI%!TF$`$WePZfUQ7G`}Ga z(dhF4>_L=?gy)O846+$)kZK1gMpku8;xg=yN>w0<2jrRS-k>OH_^l;cIYmuj+I80a zs6&&m#?I#R>Sz%}IAQKhbQ<{1g5fuEX=f9bki=_SE|Z)Oz?z|z_D9{@DB`aR#2wm% zdzQ)AHpxhw!Q3G&_)sPc6gnlWSRu(t3}a9(Wj(z%8R+I3SSO#^N}U%&gk>lMr1QWU zeA$IuE5CdnTb0BQ(YSnc%Q?zi2&hnOIe8g-h$|yC6(r6l z$#ReSYn^}DuNQS9KA*9F01ae85Uz!U%d3q~Y|E3N$A;53U^^J%#<^th@Uubx++P-A z`me>$d$F>hQDq8tl07HvK?iYSIFH5BG(RFm64&%K5gY;5%8ySRY!tI2$oyhP5zk4G z=##n0?@L@I&%j0Ji(AmxLnnaY?v>rpFHTogNz(GY<6vXCG>Fc5suHU{d(oTj$7N*KLs=Q9kcM3d8i ztV%(QC#mmi$_3k@Hn@;ZuyO~YOA2nXs{QZ;@=;)ucX9=z3(8cAx4BPQ_wRRbosw8V zssUY81u{)!M7EB_7=Utic8O@2xQW29h6(>T&n7ymXJ#i!C-ZM_0(%*6F`_!%TC6WW z)V&-u@ye9X`44AV=TrNT-+OSkSlRUD{{n_BDjWa+ literal 0 HcmV?d00001 diff --git a/Src/gui/themes/default/bg_left.png b/Src/gui/themes/default/bg_left.png new file mode 100644 index 0000000000000000000000000000000000000000..1d87241fddd32ad7c0e05b077c9fe87fe821f1a4 GIT binary patch literal 289 zcmeAS@N?(olHy`uVBq!ia0vp^0zjBq!^2X+?^QKos)S9vL>4nJ za0`PlBg3pY5H=O_M6<|!Xn}yo_#wF6p}1)jVN)>&&^HED`9XhN=+d_wzLT@4mjtslxO{%yTR|D>SppRQ4wJ}d!$ii`vIp<%oX}uBt(DQ z*kC8{_|t3A6Eh7Me$-jF^5!HkOaEY8Ai|Ns%XG}(9`k}8E{o$oMAoo2zJ4UyvfKL7 fk*>opCY3TzZ!{J9T=Mt?&}9ssu6{1-oD!M<9Wi2j literal 0 HcmV?d00001 diff --git a/Src/gui/themes/default/bg_middle.png b/Src/gui/themes/default/bg_middle.png new file mode 100644 index 0000000000000000000000000000000000000000..eb206e367c20ef0f527501af566ffc1fb78473f6 GIT binary patch literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^0zjBq!^2X+?^QKos)S9vL>4nJ za0`PlBg3pY5H=O_M6<|!lK&8Chg`03Q3l@MwB?`=jNv7l`uFLr6!i7rYMwW zmSiZnd-?{1H}Z)C6{&l=IEHu}e|yG|k%57Q!QhMiSJj5gyICXrz8`TuI@v)%fP;mp a@j=w32h2rZ%07c!$KdJe=d#Wzp$P!KeKUao literal 0 HcmV?d00001 diff --git a/Src/gui/themes/default/bg_right.png b/Src/gui/themes/default/bg_right.png new file mode 100644 index 0000000000000000000000000000000000000000..9866819ea89bcea9dc65a19b7c92648953a569af GIT binary patch literal 321 zcmeAS@N?(olHy`uVBq!ia0vp^0zjBq!^2X+?^QKos)S9vL>4nJ za0`PlBg3pY5H=O_M6<|!lFFMGx*YgLXst}5hc#~xw)x%B@E6*sfi`2DGKG8 zB^e6tp1uL$jeO!jMe96W978;gzrD7Rx7k2|^}>4&vjsaZB{AhcoOLsSH%o0nDw9hk zuXI36*O8zpEe=1{?tgNwZqxa*<=3{g?d@Q=$E>(xuP$qy>(`CPE-EmYoMkULd~*d; zZ2FA!-E2#EnByk?Z)^!*VED4PutBSmnPG<7T_pLF#}!B N;OXk;vd$@?2>?+IanAq% literal 0 HcmV?d00001 diff --git a/Src/gui/themes/default/bg_submenu_left.png b/Src/gui/themes/default/bg_submenu_left.png new file mode 100644 index 0000000000000000000000000000000000000000..989e0eee596c0911dfa713282fa470577048e810 GIT binary patch literal 312 zcmeAS@N?(olHy`uVBq!ia0vp^0zjBq!^2X+?^QKos)S9lS| zxv6<249-QVi6yBi3gww484B*6z5(HleBwYwlRaG=Lp+YZy>^hZ!GMSLf_!)Z(?`7> zP0Ac|gI;i~3;3Wn_kiT1h3tZBGWLltv^3YxEb3gLwMno^$!$m8X}gKu2dejapJIN! z$}fFSXP2iP{y1VN6KUOf($3&I>qK3k^B6o`{an^LB{Ts5!f9x~ literal 0 HcmV?d00001 diff --git a/Src/gui/themes/default/bg_submenu_middle.png b/Src/gui/themes/default/bg_submenu_middle.png new file mode 100644 index 0000000000000000000000000000000000000000..327a5dda76ccede532423f54cef21c4cb4a00431 GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^0zjBq!^2X+?^QKos)S9lBq!^2X+?^QKos)S9l}Kf60fd&zJ8m{`|CNzebrBk7xqVgE?=$ zo={I{-TIbG>qBy-^Uv6r8FK3t95Gv@kL-#4ZuK?aYD%_~w{RTMlX|KoO)TCgrTNR$8V9>Ky>>-+C1 ezTR^8GmGFOozq%;y9|JCXYh3Ob6Mw<&;$UbR(Rk5 literal 0 HcmV?d00001 diff --git a/Src/gui/themes/default/dialogue_box.png b/Src/gui/themes/default/dialogue_box.png new file mode 100644 index 0000000000000000000000000000000000000000..52a2e45f05e38b813a20be670b7e893cf053e54e GIT binary patch literal 2107 zcmb_di9g%f7XKx&l~J!kX`6_lpOkKBQJSf=C8NexCQ~hGn^L8th^43{{TaMIOK7W> zsTduxrM5vwEr}#8VT86Qqf2a|ibiM%vChxD&-({n=W{>zoO91T=X}mR_uTJIKI>wy zuDV+l004D|Gj{F(06PiEb1F&@4LQUPfEX;y-TpLC^#U~oEtI?+?d^cgt?`Imnh9yP zQO;Zl0{}JT)`S5M>AH|oIo!dSp#0`5MYXRr_OzfUA=R#M!ufF9;J`rNpm4x8)b~ob z?^XTC>*4s|PKyKL%cBhC@Z^c4haONbMJ3qWSn2gT8RLIO6RId^;)k$}) zZahgXepbVFw#_Q*6GcyBUVU$+iM&4j1ph0cZmJ1=w*eSc@Mx&)eQcalOUB7oKi$<= z-5Y=EK9-6v@bVVaQmYsGrOR>aO&!+l@t(6SXhO(w_YljJF=El!)z`hGqQV`<+Ayd3 z+Ag;br_uz!8%Yy7Er{R1 z(zL#fPOaSN`HEZ`d3btC;P1kjEQ41U<4H6(IpK*;3vLZYnk_j)!0rCt(XHA7eS++o z#$VUH5v%7r+v;8ZO)QM{wpq7(DyyuxiJ|x@HN-k)W6nLcX|8`%gW6Q1|s@%kL%SPUGkn->E%@eIn7~a7dc28 z6Pd0sceGjw!>5>IQY(L7*C3ZJ1)=gxJUKt5cGtcGzChvuuLzL2`D_xczZ5mcY z_x;}Wjl1)Q?yMrYE)qs=Al0Xr`>VyfHSBSAhAcvj)%Y2SAMuZRjmLo?%>UP%;x45!acX zQ9-&KnvbCrS(LbZil|wTd5yR%<>%%%`bBf?q865qy^9MBTGbvQu6rR7SpIhB7&Fi# zMkns6PVR4&bMp;vn;TYlMm6S*o%b2ZKF4j{mBToXF{ei3d43)s(?1nsdhbW39@AgK zQVeoB^s}ZZ&ug?;j2N8C58D$%F6yG=?w?}$QbDx2>eCi!mOpJ^5=Fe zg7_>W!_T{>f0zW@*`|nu?e{6al?SURe(9u8mR9*8Q0X@}ypO?2-y0Uy9UdF92$qF3 z7_ypZZ|8jHrd8?;FQXS)5~|{_*;Yy9|WBm6goFHYp|0C0bW zf8tOo`u|96pp^dqY*@8)L&Ak?nZSNsF1@e|0STpD30k7iZs>M*vvMG8ZS?7N>FJNW zk0r@KR!u*v8%P%%z`}|AbJE^{OUnWOYfI9NMFyT^p-moJyi;B?IE_~)+qIUhJ-Z4f zFJ(e)twHOJ zG$b44l;=Gxj59pFsJ6=t)h&@d5F#1|JyRD)Sq^af;29h}qix{rjIyagA)9hcZ}DXw zmU8u*>4FT|GhxmNaX(d;&88gETf|%bFrv~b5&4^tVzNqSshZ=rAUHF7x5iJ5w`F~9 zmOXae+=Msm;zf!E7tl{%DQ~CMcGcL>Z)XKc@)S)Cyc=;keT%rm_h8hB1lk=l6ni1D zeMoU`3vWXz=J(kH%NHs%4!0K%b7U7Qh7N)|cI40E%zoG$h`bYzAT7pW_AoReR{q`2 zgM7-_sXg>d$)1mK$GI)KIgF1QCT*o^m&I)Y@kPMUAiLSvy(gXj`aaGP5p&Iaww)}J z8ih^Dy*$ys05)|Nv-zpfD@PvoNvxx}0aF?tK1AvcagszPnpiRcT|JVzjZ)Oy9192x zDu3cAH@)*nJ30I)eXikrFF>99jvEXbv*ryXQFqDT>sqL41ME(1Hr|v>NNSMzW|hKf7t*4 literal 0 HcmV?d00001 diff --git a/Src/gui/themes/default/disc_info.png b/Src/gui/themes/default/disc_info.png new file mode 100644 index 0000000000000000000000000000000000000000..dac041ddc41d29116a3ffe39db1cf95e086501aa GIT binary patch literal 2201 zcmeAS@N?(olHy`uVBq!ia0y~yU=#r2GaPI{5!r9w9f1^Mage(c!@6@aFM%AkByV>Y zhW{YAVDIwDKoQOYkH}&M25w;xW@MN(M*=9wUgGKN%6^lFmy1K}|I-W+ppayVYeb22 zer|4RUI~M9QEFmIYKlU6W=V#EyQgnJcq5-UP}>(z7srr_TW{}f^b5(9Ireb6arQ&8 zXbG zd%8`E;S9Lmu5#P+o?4{urb$mqC#~Id_h&^^{gDfvY)iJ9MXN~q8qG{mJIQ-p*6&W* zq;$_|lXIrLJ@>p=bi%b;Z?39b_7scp{_*VDBpdzPbIa4M6xMFNIotEu*0z!{-4}z9^8@k`?Rdecm5l$B~{Viu4lbuj?v-vl>7R5TmIXI zkms`9g#ldRH-jdv-1S^(D^t+XWXqGXpIf=#r%pO)C20ALXUVN?I$i8MJ=UILtFQmN z&Z=_PnE$qzgiiVD>vf-XeM*gXXG}BLu9gZ)DLOchD3u=<^Ip6GvO`1PfB;=9dR zjK50vdVF`h&hU3vsLD(O_63cdN+)+%GVu0@dmcN(n31r?!zhW*fmzvglJ+wOlMl{` zY!1%%IXN!OXkcJs;^0tFXlP)7QXoE%2N6cdGBJS_p~xa@g3Br>AT$l6k%Pq@@USE+ zw8+wgh=9QoYlFodlqEMd$uzLViFu`U4?)@z*_l*8m-x3ewzbYV_|RqhXehf`(g*7qhdew)4e)`Z7l z3Z9=#PF5Q;uM)F)`<3688ED@8Nq5Z56;8fg#rc&f$Th|Gf3tcyNa@U(!&R>i+SX9?z_$ueR1NSvYs@+~oS;?A&ibyXNoPoxHB#;a(r3${Rb~ z_iInM>wMKyTTr57s{7iCD|{#Bb=>JT7TmEyY|@?8(*3uhXUIj*`t2!pR$8xTU`ME#U7%exfohdG4vH4-eA5-l-05->Mz35%K!n``r87d!Ju?SFK)MyM|S( zs#aC)>JUl@@qoz0-@JKt+xGt*dVmm`3TdUsnmyWl@DpR6$LALKyza3M?VoT&cb$sQ zHwmd%_}CLqHhp5=li7qcScL?(w|^onV|wX~jf6DmiTIuR4C*zs$EP!%#OE!9c*ph` zHNyX6zGf%n$=Zal^u9x%9n^&l_>Pdyxro2^*t%IWce0h|%^`%P@RiN=Wp!fkXQA@{XMx zLFC9BLTcs>>NR?(J7}v(?`p?)Ky zh7NmXXoF97X+%DQ@@N(D4A&Of(|Fcp9`5~m*r2;1{{}T9s{uwT5Q$ADlucm^!R51j z@Qc`+;Fq!G;8(DJfM3nt2ET@_1^*6v2mCs=8T<$A-{5z!kHPO@d%*8yd%^FMqY0HO z$caRfljH&52g(D%50VFiA0od1{zW~EP~D+B3DaHrH{eg}=fI!0=b-emC>@BXiH&R^ zH;LM7Sg+nBxzCtk14-@Nz5_>)=Fbj$W&r6hu-6bj={m62h{2@4c#;Hzs2d>?u@U-2 z$EJRSTt>@N<~+9~{Pzbb!*epJO)M>+XzM4nTMODo(6;T{K+;a|9ozG7pJ@FAr$TZ! zC1p^rVFQR?&{RQd4;nCN0BJC6MDJYEROHK0GMOmg8Bw_%p;9*#yD{PQlPhL9GRpRF&LpKWg`{W6}#elq+PpENNDZP z@YzCW-3ACNAty=_U=>{NlnpIA501(KL4BZv=g0DR3Mdhmq$4&jJDy>Ev;s`%pP2Y z++DKNX4lv)iAbtsmpoFm8|7|{gt80DCGrZ zqB32XqbyJgl;z55Wv#MN*`n-F_9zFHW6BrGY2^pyqHM(V*`jR?XovF@K7phCumFgOGow`ZgrtVVrsfX3i z)UVVt>Us5&dPTjVmTFA1Xbvqxi_!dAvX-i4X!W$lS~IPc)x@}42`+%jG&d)Woh+Tz(9L0gD8HTdYk+-2vu9z+>3 zgS^jY3)(Z-1ALf)lCyqgYe1U|+PUl$c#}>Mk}N^9h5T_rbA+UUpiPCOr=Sx>%54Pg z5?q3Go(?Vr?II*C1??;(*@BueYYTa6A?d~`N((*H1;H%PYvS8ZoYJ$wdZ5zQWTZER(_<16Ju86=a-gk7kc2@ z&M{n|sX^pOg_dYn1KOZgBl@n~{C2bv0ZB8%{Rep)k%B)YzRXi2R|Nekgg?gnZ@K(f z5SlFKPmA2gmVJqoO?oysA2sS8eC4jhl)n~SCgdiq4n8;NM4UH+Bf<9%P5^(_sK9C2 zR?vDp1yjx%1Y1LLD)>0^{ffsVD}&weZH_Sra>M8)Qky2?BQ?n*(p+o21xfRum&XjI zh?q};?k?L4Nfu9swF!;`?a0#y9fEH+@R-b12Csv)DfN-I$Dfo=2+B>+abLsB(=pj^C%x_nZ>}|T0VmDQH7B(>6&y6uHQ}JgVvUt zkp%dctw}Ato&Go(qG#)!$#DHy{aNz7K3E?@M(e}$FUVN^EBK(_+1uJXl5_TKdp7ye z-pSsXT!LQy_Do;y%N+enUuLPwTYA2hdDkm3C0(=%e~>KEZrqh*tK5dFX}9i5%%{Fn zzWpCbx{BPFiKl+|WvuYkV}!>Rhxt8TPJrib#e9|wqyia0J)kkr3}^*(06IbUp&s4+ zyzueviIXR9fH(Al1}{>34VwCa?xTn4XY?z2hMuRF=oNZ{mNLdH%)ug94D+*OmdY|% zJ=T~tW35;R)`@jxy;&X`%to-WY&@IFX0zA$s)em$g=_=c%(k=LY(G27POww#EGuRu z>?*s-3`v%3l1qw|DoF`aWvPZ#TWTO>NzJ7;Qb#FA>MrF<{iUJODCq@hqBLEaBQ1~$ zq~+3TX|1$T+9K_c_DBb%W6~GWY3T>)qI4OSc1tF*D%)j`91U+UQLZYd%XQ?2a#Oj5 z+)mDxpO$;deX;r(CXbe1k|)bE<$3Z#d8xcoUL&uQH_6-NUGhHpu>6_)m3&4%FJF?c z$T#Ftg(()rp+qP#ieE`qQk4v)p3+!prnFKzD4mq9N^d1k8LW&@#wz2Lsmg5SHD!_V zrm{*YR5mD^mF>!IWxsM%IiZ|V&ML)9iE>rBsTiuP+EkYssa8@G)XHiNwYJ(o%~G4I zZPboxj@n(#Rr{+$)lupT>O^(AI!9fg7O2bB)#_Sxqq;@iq3%%+s>jqX)YIw@>P7Xk zdQH8BWw45sGFFW;AMJB3d<;LP_|aPr%Ui(bshA(($(DlFlb3_OAe{hBsw2KlB{%Iuw zw2S-(XiIrLXlEhG7PO8010=NtZLJi7@5U*er|`PelTmkiP0fP5yO8@uTUg}tcjdi> z{4<_A-6rT-QIZ_NZxnR3pp);DFO)9esVyP$eIn*=LHGPFXG7$+D8qJ9&O&)7_(k%6 zLE{y)3w>ANvrI8*@Geg2VJR7O0ecDGwio%D z8r~qR&Tjb%@*K-q(Ai1{&U1^R<7LQcCCm_%r7C=mYo_!C?W*$l9aP??c@nn)7vsEL z+7H@QS_&%5g6Anf!c$0>BS2GSZc*tn&nrvjwv>vcJ!O6+SJ0lw@un#A32yClgs||Q zGHi^VmQho>pO1+&U7iOzp7$fzc^2qbN>@-nPnkx`r;(anUJELVI$F3US%iZ0S(b#7 z&`nsSLMI~qdh&G0Ys=gpI4be=MW%EH{4Ww_YFKqMXn2!S4}7}lcXp*A_-4{<$WL<( z(EZXP(9sgop_O@>{3xS^h8c~spmmU)N7!}1b>BVmF!n} zEha0x)@yhQbdQ2GS)QoxWR=UmQig(#SB0FHhu!27c2m9y`C4TQ_<>3yXs)srw5NOm z@^ob>_&i=0)=;%Ta#kgvzbZdNVpAhPJ8(+(t1j?u)LhU!bvx*63FT*_rOBZ61kIK< zA?A6mJvvS52)SQ|M}+Ze6eO3pHdux<7W{fK8eEntK{83=*8Y%G1@cn<6kW}lL83@` z;D@pv;HyY2LH#04a||3J!+NDlmfDb?;8sMZ!3G#{misU_q+jvBWS)a3)0TW|?+Ab9jPPf^6aEa^fc!r`+gtWo z&{r*oiJeOSdtU$l(!8#Dv}nzzC2Cc*bghooP;08S(AsI)+S6K3t*WrcUeYFO zGqrizLT#zGQd^^~(>7__u`WHY%Pn zzcnR)P1#scs{84E8Ys`Pjwok{4ns@wKjmp{k-M3usH60kl$lz+pFXIxrhY;+|359E z8Q;`uC=J!BS!O0Ivz(fiU`p=iMSaUl63UycVAk&M@C8D9!n)Xlc+>Vozc8)K>?5I; z_CL^x$R*Tz&3wykQhfW@yd*5Ayd)vKTtB2PW{v)`P0ccw+q|%uQ2y`ND6}_)@_#>t z(3s{ZVfIH;9@-!8w2`Q3d3)W*|BYIg=ZJGEjEbQ)X4+DyMU|(<#}L-Z)bQ_5(F8HJ z+-E=VLwL#|^d4(B$14kuBZrKr(hiY}c#8hUzoq=-tUMh#N96UHkc%-&?r*?T3(X~z z4{c48XRGd}&u~7JNE#unW~3YViDVki;bxLWqyZ@)ZjMoyD+c&3Q_jAyQrU&!m^2KklblUt;eEG9v!lBLv2!^tWdNu$Vm8bjmA zyEK6Y$Okl;)*@SJ9Xfz~LjOzuOUmdk^cpd2MYdu}Y$di5Y)ewq3qB{x$9HsJ;B}6w z9f=*MsNV2vHmJMR{pwNmgnCLns}`#z>Q(ioYG|@%(_C7lR!K|HDr+^g+FAoGOKYyR z(K>25T6Zm1>#q&fMqxi>qBdQdqb<-1wB_1rZLPLZ+oJ8z_GkySW7-$mY3&E?qIOxk zrroj-i)yi3JeFvS&yr}VYDu@$u{5+awY0Fbvt$!uc^c?x>1!Ei8D<%6dC4-_GSf28 zve2^BveL4~vd*%}vdyv!KG|W*XO^!lXDsI}mn>H-H!P)AX0=!y)(C5i)lY~u8Nlw3 z6}vyydH{BRtj(;gtR1Y}>WH-~&>MhtSO)_mfU&@MV5)Vt^)-ZxfH#3vKq0UJ*lgWy z-HmWRa1=NJoC3~Ti>)QrtJa&~4MJ=(fc{`}0g*r@TY{~!tp?BAhB?O80LTKG18sng zKn~Cy$OZZXLxE8M+RHW(m~NY6TY#_tSPrZP)&d)CTWmWJ?g0)07~gGQ*iM7;QI^;) z0+)enz%4>_$aEF310En+_vwjxRXrVi9iSo56lejo1G4p}L3{GF^uEAAU>GnOcnO#c z%mn7?3q_oz;8y}`^mY0seVe`u{663?@EPzGa0WQ9UlQ@J=r{CI9PBf|Vt0T>05Nty zXflv$&j78* z27Ul80+)enz%BDQ+Mzn^4v!<+;d3N9syfmgbsP;HO&u*9?Ht*TryV^VeH{ZG!yKa> zFF7VVW;*6M7CM$XRyx)=);TsgwmEh=_BjqaK68BKIO90)xa7FvxZx;uGN;Aqa7H*| zoPKArGu4^ltmka(Z02m`?BML=?CR|8%ySNQj&P23j(1LV&UU`$T;zPyxyo7S+~C~o z-0s}%-0wW6EZ#oT^?6SFBu1HrUSAwgutA?w#tAQ)a)!fy_)zOvX z>h8*Q^>+<*jdH!^{n_gC&S?(^ra?o=%>wp5C53&tT68&sfiR&s5KB&ugAVo;N+KJcXVOp3R=^p531Po}-=< zo>QK)o?=gl=c?zX#|W3hZQ-u)$nZ+x3E`E)YlPPhZxEgp-aNcbc*pRZ@b2Nc;r+vh zhK~w=A$(%^^zb?13&IP+mxr$oUmLzLd`tL_@IB!N!;gi35q>)ShwzKxm&31x-->{x zM5urr@Bq<(4@d;60_epN=*1BYfu=wUpdFA6JPq^&`T_%iVZdnMB>=rRVkR&TKtGOH z3akXy0PBEFz&2nPurK0p#Agv-MVyH^A8{$-O2mzbQZMsbybf=KH^%GtCVNx88Qyx{ z#@=S$R^ATYPTsEG-rhX#VDAX;Snqi6RPSu>Yu-iPH@&O8h29O`&EDc4ULdtjOk(Z6Z5H=0u{`@mX6r z`TN`*!oMeY(f{55Z; zADY*L;)j;uL2>?C9-5a~&c8v&hS-&9d!~)uPs=rPUz+!{{(ay6$x|Z7Kat<}Y-q}% z{NH)DynRKQrfrxua6kQ9soht$d!7nymj}fRwKS7A>HYCd{fIP8d;UAr93{+B-J`1z zyE5C<)W8FIk-OPzLgN&eO`ux7o%{%=Fe{P+0>mBCCQL`!D7n6-EiA3ECK!-tkUln<@N z1LQU#=Uz4T2LxZ<2Ze@BKD3vG^7qVip?QVaKqrxAC$qjGWeCYjVq7jUQyXSFf)BOK z^1MRh+?VD(;7b`e`ikYHaFC$j$wz*9HH&cy_Sh2ZzQH z@=z~mh)8FMkeBl!elziGv(Wg0uP5Ty6TCR_V;uzlC*=u!Hna?a-z?JK%z0WW^Yh{4 z&^V#b{xxsv{QhT6xp=mY$g56hocs7bB2J(C@*+YGF-jQ9hw5;+$ZNPrGn5}Ko*jLk ze3g)w@5?=?{31^INd9;DkotytL6yX_l|t(qoP)ZAmOqqF6zO1KQym<tN?#nClK1oQ*Qi^f~BYcX`%!@LAkMBiOOUhZ^E{vbFcNBa_!9ObaM+M(q@ZAMJ zOz^`5KTq)U1fM5(Go4U=yO3`eaheFeiQsz)zL((p3BKQ7rW2axV>p5x*DL3F{^FkgM>wZ*m2nDdd@ge>OyK&xknB2zgJz_Z0k{8N__Mfv>gAUe-^{ zCjCU5d%Oj+rA#^EFyjBi4*4SNkQZQAytUXB?~h&a{bV@y!>^FhVh?;7xq&_H74$g% zMd98-F^%T?+q44xh1qEg-mvq~+IY+EAzGg`Vh__^>=E`D?TZ@%gXsXg2{(m~zzu;} zbSCZyOD zQ$o)muk*kqfZNYs_saj1v-&Vr*r56T0oc6)fA^e@^P+F z`MA9NuXz5Z_@Bjjko-Yu{!inJbUx$nJpD;I|EKcf4@l?#pzaT<%UwB6*5vjwAN_Fm zPTUhD;)Wn4cykSJ98;VJQoM0YNe6(hPr3rV!EdtQjTEx9S^Tr~^F>yE1jKL5ncjJ@09MADiD&+3H#m3^^VqFZ*ad6xOds_*sf^o(^+*<@LU;bL+}ou;JGbZ%+DCX3J7CM7{60%-lko{wt(NkJ_6m1`?3u0s_(}W5}t`9 z$sz@w9#6|wp0;$)XI%2bzdJEdHf=R8oAfMXLrJFIPamKU(ue5J=_B>$^>O-(`UHK7 zK0|*+e^sBazpm%&i}g4375YE)f9mh(@9OXCTlIhIAL)Db1NssDxPDUqQvX^{(qnbE z?$zV<3VNnqQ?IW#(jUMiy5`jdKF9h2?`VxJa{+9l>{x5yK{+|AU{-M58|5*P-Kcs)Ef382Ff1{`9 zaeBBOr3dtidR@Ji{*c~8uckkyx7HuW%?;>P`c1-{2-0ooHfmfZ^E;<1N}!x8HqY;Ugvrw9Z@^TE*N9!-?6ZNV3Onr`CpuefF)K}|;IA7hUZ^jAh4t=-2Pd}(1 z)j!ia>ZkN%oalP=NIgN1(d+0LdIP;N&Uc&Zt@I9hr~gysptw29(4v?Ph^+sByUrs8 z$8SAzjv@a~5H=REaCaK^;2;tDS$s1Dr@aiVikqu?zq{XjFTVLse1m%+_~!RiV!&IF zl1l9Sjx}koJ3!k&O7SiQF9##P&|?0CX{qvY_&Ml#N-bqE4BBUg(wC$!!&t<0)hbzJ z#^hp>5d4h%b{n0#GOUwy==*3cdZ#}aR3nTCTA&T0=Xw(QT@d%>#ecjv^FE#mpvP$E zkthBO9||ewQW3(=A(yo+$oUe48gAYY@)G@+o)b4heq-_MVfH9%%eJzQ*a3Egea_CX zA93gP7paN#2ySoml155nai?{rG+SCB9hJV9d&tA(CGuPFT0fNc;Qr}h`8UO_#Ht!@ zLD*HVT2YO|{f8%UCv=cHLLH}$$9>Rg>Z|G^b(Q*0bv^Do99DmGOvDNBbesXd;>dR_ zbG+sFhvRL>zZ_c~+Z{(-rLip58XFNC6&n{@Ber2|m)K`wN5_tfof7*&>`q^}uez_b zuaEC}-(ueq-wNM5zIT0FegF1-;ydE|)>q{F$#>oNTbws8Htx~5wsD=~o{H-d*DdbF zxJ_|;;y#c2Chq6BYjK9(=J)yo{$zh$e*=GGe@lN4|8xF1{ssQ`7Ft&WkJgNlpQJiQqHFQSmmcGx2vXAi%HE*9g_Nd>e$p5 zYed&bs!`+Z$hYI(o_%BQZFYOY?bmNFyZz4XA8!YZ5k{#I43=T0;s5!`a(Vq`a+1h_;@Lww@!sg*!P{aKmPvyb||~`Hh-Ss&?DL|nm&9)M5nr?~-Iwjl^Syw!Uglft+u+;m+wR-vJLvn$ zch+~&ciDF{j>JXB`Quu|btrG^9&zL2HplIY`y%e!xT|qD{KW6_N1?6L{Pq0}{g0xp zhx$kO=lPe5whoK;##gx8)>YBgPsGndTf5QLQ3)vt^%5RV7?dzK;q`>QXzNpGYZ9;o zq63uzNusUm1|AMP7HEyO?ilDC=pN`3$O{Yz3`bj!4@^f}F9{q?3?z}{ddc&WmnUyX zp($#LJ*5iTx;@%DC#4tKdQr-|DSOe@7tz+Y(AFNb_2ATzsbf-KKwBrEtu1d?e0v7k zn%?esd*pQRSxW4`Rhu61VU;oQH7uH;O>%!s-i!RK+Fzv$B z3sWwQJThyYcUQykm%%WOF=|we)l8O?G5{mpqaYeC3m5O4DDilQ( zd5a>7JVmY|N0F_Fo-aNB?fIGK)}32@ZsoaU=UzS6^xVVenw)EVuF<)M=jxxUcdpL4 z=yTq45$7B~T>s(n+5epV?(Ev{4xX8CX7riiXNH}5?(~@z;1g)7Xt z1Mjb_!<#JqojLZ4_6znRy~G^jMbG}<|S*=nEVMP!84~z|Iom=?w(1!^E&_!-fK9fggb}0Ct)L zCL!c`a7;F;LQ^WD*_Ilr_{>?`vf7@Lefac_ahu@f*nK%J#nx@2zk0Q z!J~}QY!keE(i~s~h|o+)pDC$}fEnL;zRdUZJkI7e{2A&&b2UFGM&GSOR_# z!j%Ajeigz(;63oG5pDyZFKGk9UBDjj8xf-1xb;SGe~ic|pUlez{mP#LXd?;FC@#Pa zz8E3))RkE9D4VJR8u$`~So^6q@X)1dH^IxRdQC`ZN425}=_kZU1C`>Er=*G32(tK-4fMToXkCxb`2>QrDFcII{1zV(f%BAHo{j-$f&bp0gw+l_COqqfo0&K1IG#gZ7TOd_zx3u zF2c7>$j=}|TRYI7aF#_J?*LoD=OIMky*-W6^%N(@0`dfg0dpXR+x3bS!U12>r%(0sk?=-T=xd ze~%D($BqVHgb?k0;sD3efm&0-%sF?t`Ggh zcOCru2yX(vfk(PfD~a=hN1fwP$GBMVClUIAN5OxCum#W-Hb)V506K%$5I$u>bt3Fy z0(*KSuA2$fjj#vsBI0`xjt4e@uZa+KjN1bq_7jJC#eEKbB*HHM;ZWc?@F<^u1TY6Y%IKd5EC3I^`j-RmgD)c_9(K;5 zg(FlriSRt>t3uK>h=uZS?#gvP@J6ZnM#5}#;7i$jQdacEFNd{v+t z_;`fq9~>I$AO8e^@@xD#lrsT&YtVlJ^5@XjBSbqTpp4oEgeVV(1|24#TnR{9+k`L$ zs1AMy!g@d>@Ou$H4DC3(`$^9asULr^lZ`J6KSjgd-+!my;ww zzX|An7M{<~CM;+tRDlFk$dPBj0-$V`CJ3Rg0Q6;Pi?9-adRy8fOadx{e-a_|!C`p{ zVWtUwmm$E@MO$0CAVm2C&A|6T_!xk8w>*omHGs4&{SkIBVL|-@9f54f2P5nZbOjHa z2y_Q}f`1+%PwN@*V-e;7(2wOsgad$~;9o{K9KiRMDG2#@faMj0KFiRWJB7iF92vG+kXhD5pBZuGeY#u8c??F3c?yD_??coEkGpX*AZ3(;^5Ch zr*F>yW`l=LZ=hZr_}xNs8#?D3VAxY5x1qn=6TrI=LZ`Q12cL!TO<)=LHV6v==!xG2 zxs9^kh8}eOTqzI)4;#g=*AQa_cifq8$x`~p`XXv`8S{pd=a5v37lu#-s&_6e(ys-zlr`l{pi4AV$D z;b*(Gut%JU-}|de>XG`m<@FG0NE%`HvkA!}595~-AHm7bqog@`3_JfVaRSs@>{GTQ z?Qst9IDP~13G6RFi4&pD*n@uxzZuvCCqvyxchZCOB)w3ZsklKlgUllH#VO!hWF<}l zSCfC>F4;fHzi=kFmb^pOlXYYRd6&FL-Y1)IM!1E1fOEnR$-l`CbvJI6<&tMeKXnhz z(^p_;eE`PvQKY|iiA*O2+J|H~Ze;yT@JmA4TiOO~y`*Tn@ymrTV70IYC-M_WA2L|` zfM(+s^xI?*c~RYmHPA#dh2+x+>Qy(ZA7GDhCw_D8L$cL6ntVhXU^KSk7gmn*-^Elv zCS%m?>MnIZnT#{7N#qsWY@18wkypta@;X_F8ZID9$s1$|`GxhxE!yYUFgBdw^pic$ zMl$qt)aH;tA$=8LUm=;sUWOgq`L~69j5tih+k#V%892{A1TB?Px- zEF#bc!jsAsd;@0^zjG6z1yBpFyVZ0%t;yPv&++^?k}Y+Wo|C?zQ{;gBy!0cPizAz! z_{Gsrm6LcAXD;UNxoTfJ2EX{j|BXXx(p3NY9A_qC(e=bILk3wb&T5eF1@PEsm8~lCp{4-rM z0}W=no@r1W_2*}73_FVaBrMNZDCa4wz-uIKJCP|W1`jx5Gqos_m`u|4oG7VDTqjCS zl%$8d_4KVqTcZK)RA?0M*bH)<-OxYF#?<91T3MJT= zC|7KjL!mQdq(x+=%CZH;In7IT4JoEmcR>7;US4;69TI`9atP}t@)2bR#@9H~Dl5HG zlr~!;6%^|8T4#qlb$3{tFSb&}nCPg;aF5&NbcES$R*Tt?c+t)8I&nCP7q{Vwh7C&_ za=Is@Bm)^rwZdyjwY>2Hf$)G72#?Q<7oY*D7F(Nlz2EYF*Nh97T2c7mh0yIo1XW|32EQ=$Oy0;rCvs`u1HE$(_1S;$^PRc0 z{mSeoS9Cb~)sNd*Gozg}BDdSK$LSmL(C(dbZ||bjl^RtxHEzo2!MM!}-}un+(@%;o z=ACM3vhjG_?t+4&a2T*0!#s#}Fh&_2^P>-QV13dlE6rCowsJxxXGO{Snls_Gy7Mc) zR^wIYeCf65N)@Z2EmfOWCpLSMt+pO#t7dQDg6)=;xGo!)>+=fow!Dm*8>l;K%|*P{ z5s|er>Y(0%1XZhDr&dNJs)_0a5|U{OjY@j(*KA9_c5Md?Y}2mav@KJ!hS#W(v2EJ) z%|?rW?5R>3)vtZqfdkvN9WZUnw5*ZUtJmB%b=nr%q+S03ZQBm)-+tQG^cra+noQaD z0gdTNSN1Gw-w$65=-&=sRIfhr;i+4?TB%AWX&mM~Yv8Xj*w*XfcyrF&faOeJyq5Q>6{aQ*E&f8+8O zN1;E{X53Nr(=h~TF2{es-VK!hXfB0Io=UJ%Zd7Ts7PpwFK#GF~5(qaZVN_h(uqdb= z7N-fjLu1r!OzW}$U7nIG(N(Ql7oKeQ#J2ul8O1YaWu$-d&cl};FG9AB2$7BpGd|=rlh84D>d_duCL203JRT_yEei$F! zutHzr2*Xd4dsGr_bKtp*66gvK^U+OZ-Uv@rAem*>_SBU|PMI`m%JTdL3-VRZdE=qt zBBMd^W%}{i@8}-v_v4o`uSzL*($#pn8r3a0hWF@5x3nbV_jGGTdb|-#3)Jys)@HP; zNOL(-S3M<0!|%Q~8kSt7`_7%mOLee{)vT3V4YuPZ?Xpr`VLFlRR*nB6vGj)Gw!dMc zj)fkJ-6mO8w}jgXq=Hk{trfylj~J>?V{qjI10Mrj*ZAPQhYRpIorX~@34^YZQk~XS z+_l_Eay6rX_N{Mh7;bE+Px~4L^=XIUw1fQJ?vHyPGN#cnhkAd!yU!sy#+Y`9>k^*l zbMhE@KKge`Rs>mLrOTBSnq+4&GO1*V!8tQ81I8@mZ8B&O9OEHV47F~yo&MW+WR1~` zZkOj9%?deFNb$Q=biVODyGqkAf<$NO5`0%xl4&ea`3!crym4xIF=EpjrF#qd(6mpD z3G`*NeRJt|(jYboqpy22SaEM$Cw?Zmv<^Be;b5U zr=Z`rLEGtAB?PD~D@OW<)syeD=SMH}El%|MDq?rHVuI5bAD0M&Lpm-D?XL6J5T3Z4 zp7liOS7a|(`;#a6Vik>VNIkaaucPA+C*z&X<}_+YofO&?P+_~ z-qv34L3+?0tcR_KzKkrR%h)n$nY>I{rY_T#S(aIs*_P?+@hcGP*?MWcyk1$auGiLE z)?3%x*6TaTPP&urly=HHm7VHNZKq|Yb*F8o-uyv@DbGskA@@*vs6DhEmL67~@q-dd z>_)p$F-DsMba(=DyF9frFnhBUK?6cU&$X>nuS5I#^;%DPW!9`$=FFNk=jZF!fByN} zHFmjfhYoe?wQIwc8pn(S#zEs4O~(&d)TQamjnT#gW1=w{?<&4TU#8PV+uguC)EsSR zBgt72QohXcmFXJEw^{jBDIUf`g=FCe`A`N*%O;v5s~)Nb8jD zFO)~N+0yFPNi1l&{Vzhg0km%=@_1GiQYlGMmFNmFQdGqxRaKh0+;4~FM=X>{J|iw0 zqc&euf=fz_b(JEoUAr)Im1lVEusQyU(UuRoQ5jDqBq8riEDyzW&Zo7^#=0 ztZ`LPUKIF538n&AX9>)c8z^@^Fo^JJR>m~ToeXmdu0}I|pNsDnTC&VvYW#Hl*)N{$ zyRY}^jT;vg6wF%s>eQ!p^`JL(q=+omc~5mG|Eblwb+<^%{|LCCn7%#e>P%z*kY~FC;1564qF0o#rb$6?3Kddo6T8--$sBxl}^P(&O`zEBo*+ZbCURsNGfJ`vtgz0n#^gt zYhQZd;IIC3?OUVtDh<$xRtt=8CoEVnVe0hh%BF2eDaLokh1>zgufJS{!#t9{O2^Vy z;>reYTeWK2yYH;qAo>sX-NcxxlFY0MN)nTplq4&1Qw1886bbJpCy+P|W!)nt&$MeL zcRC91B~K+lm&iJPmbA9)(&x-lmZ_ZVbZdfA4aa3<656Ys7<&Woy&uU+inf#d6gA&h zJ>P@TH|3w{(e}iuK5wGWY4v$4CP+SKd|W!3twgjN*Tx-l=ens6-Grzh>5k{a`(t?@ zNQ6fe9^z@TylL}apE7;^>&C$euUfxKUqBy+}j&14x6fNt3d|E$|1pQ?S-1$t0F)STn%G!awdCU|s6EjMTV$ zfZiQ2U4$^q?QH z%(XY~`vCTmcrv%YWA?SIDW6RKP##r*C#T5k=sTLqD$9hIr(wz6@`PtnULcVSe!Tgk z%|`dtM)wbBBb4PD`jiVc;=>-~xU8l+R>PWNSCcBlRFLojqmmR8Q=w^WjDq(@D>zA< zYnJmBdw%%BxT*1~ze1!{p(Ms{B@(q(iF8uG6c^xg;|cDXV8Sy07Zcaz8^*QEt|RCr zca{&bxqJ}8QwcPH?$AUm9K@E>6s-u~>d%(_rn6M%hm{PMb8S-NxSCcjj&T z_L1&6k0$RubcnuM(0fM5ryk0w`PAS?n{BUOZ`X=8le%_ln%yW3uRV#mprY}ST!0fx z9s8(5vuakZmKYNyIqcSowWak@*7bIGO5*xzQNHyxt7WEysg>Y2`eO{;hsAcLnG}u!9{yc?hzgSZhh0U!p1A()$!W+@bMAjy(;%#c%9IDFd&8p zGI`%gMs@j0NGw8$7&PnDjlws6^Ml7LJH`(fFk!-g0pn-SOPbVi#pj=|=rA>L!>c!p zZ)q#)sWY&CdXsStj3q`lI+`{-ev8FVSh8fo#3f6Ni$j_;ySjb*)#ih&Z6zHw=b_1^P`O{%6gb2!TE)0Cn>T9s7Z<c*6nJn35tEO6}(izOsjdY_@JmrpZycA%0C$S!T_c}drd~n(Ifyb3V znJlflRgF$Duz@IHCzi<1p*|L@e*Ao9t3dK?)_l)&ns0kI&aGF73%4+ZIDC;xMx~lo z;`5}(^Nw5Yt%%Kn65*|2^mdnfCD^Yrhrc9DYj=n5DwIC=^M-|QuKD?=*CtI^V6>v! zif&GtH2-b9X!o1ZoE<3pcHAqk&0u|v#zS9xE_e05_h-Br5&7xzL!YAW&ce7{6Me1% zsgV^^;XSf3GG7XN&%V)>Z(S%YjtS4OlbULJ3@_U6Q!YHH^rYYIqkIi*`oeYU$~D`r z>|%Uxd`z3r*e)yEwkqtjch8=^Isa^#S)~eHh$}gR>EbF?K5di*7x;*A)Hs&aNc4*t z&{@ZFomI~As`=LGB;TnLr&W_O>@_u?E8T;Fl=5}1sUQr#N&Y%+S8{y79WJc33U$*> zBzW*Zko3%@o$z-awi|`U@zu9!3)=ej?dO#=V}UUqZuaZQ2=&Lg5a!yG=!;ddB315R zW1BBue%D47YfTMqQ7yY@mOWU9rI`(4`a$L6;a+J}SvH$fHjM2oeV+R{%?r!UmHXIO zqsci)+e#9%!pqZ^-^Ji660U7C6E-Ii4E(~q;>iYnl!labWzUo?!KP%P(W0=dt{7+g zqOCfhtzt>TtoRBsBvOjWuXIm)`6^cM*-4%73^fyO97c&!zI-(OB;$m+-S!tP=MH4X z%N-s+G|D({?7>y4*zRjPJYLvi@7|sJ9(kt9*R)_<>$WtX4&e=$S?ANXEsamndHU^snoP$*_m!?vjp=>TEp|O_VjQpRrury8klj2 zRXKF1>`T5EyOibLs>VJktB+)n?g6B$igYoH+C(eK`Iw9AN`wmZ*uY)q~ zDie$K_ybZS;}crH^kZ7z_yiig{c>TUEc_Bm1_jSa+mWuDq-I6gH47yh<$R|l-!|R3 z*kjdvI?061VQ@9|2uI{7tS`N8`Ifp~$J;^#-a;&-dfu}K+aaIR|8>-O>q?XcS>SJ0Lsk4%!=4hQQ1Mp7vXe|l@92$exvcfUdL}NVvpRx~Gr)x%q0^TBd zY*E>prLVA(Rb_m0kdiM^AASPC_d4vnNwBdX)g-l5m>vd;wDV@`dgH%5#EzHdDksJ2 zQ``lU$KW|TnUa-if$OYE60=c8t&Gv8HjUu|1=OKqNXMauVpCN)&8Cv{FmBT3S}v_2 zwuA2O{wY`$@s-h?)zL<$jgoFziHgN$jiS*~lqK4lOsh!AmMYddIPR)rsb_UKHT<(l zSki~bV>ty2M7`aCPMG5v+;``P#*M|s^=+uQh26YWO-U*Jj}(6EYt)B;}27H z=6^U$8_C9MwrCXvR-4n7YG?W^%~SdG6CRJ5zzq_Zh07o}KMoSZ^09LAb}jkHt!na- z+qE!{j>H(zRruN1x5)~(<~yZ)??UI|Xp&*Cqh@$AqeY?aSaUjcF>}uXyBOgiyfkB4 z!QyGt78gwW{MWLw8^4xf-P_`^#g&ymJeQD?VU;rfZs<#txg zm%L&M!!PAUyX;O9?STTK?+lE53gLV3+;b9ZTx`X|O;8fhm4DyU(W10aov^uDjOEs^ zTo*HD?az1J(NIN3$HS8mN-)M4r;NodcH~OG-m5L>W-jdJICK+^U6=k@_295bHZ=)< z+(b!|WvQtu6R#wr)L58L*JZ^WX;txePu!%EL$X!Kkli&SY(9HBHesN}I>c9S?oIvF*4%A0490Z%}nb*|Be5 zos&P0eH1ZdwUI~1tmsxYLpgcovjrcrr^+r*oH}6!?*p*2RZ8<+(n2f#{l_y?^p- z_3B@?Y&K)u&{6&hX*-th|8ENFo`!Z@iFVXTr7VYP4tx#ZDl|~|$)MPbyE_Fz;c4=4 zqxvDE8fKnbC;1AWkDc?OzeY$S7Jdhg$vimuwB|=IcG2lRr_WuJVFnO0xNy2Kqj6<~ zqxVPf;~{u~d~=O|#KJsV-)<{}ZY9G|C z!b1%kK2)LWKNmAimBM@G=@V=W8 z1%IXj9yV5+EKN!0%ST0$o*qE+o zdm4Yr1veR!SygQ6R8=Zls#%ltWP2uSAZ5x8l!q)0thMzz_*+xi^l6qOb(T9RUDPgG zM@wgGj^54wtR>GrMj9oLv5wLMFiv-^ij@B^1#}wNJGb!jwR87=xAV|J?6u!+CMA@f zmUrB$COu!u`xV}ulKGjCPWENBwkAOz7H9$r`Q2Z@3Y%{=u_XMJ3LZ#ICpwgaAFkEm zNywOntf~&}VSOP#q^6OFY~1a_IThVm_x@2s_kMSA-DTUNa=Mb@L06k1uT zq9p4%`e-&rd0y8srt#lSwcyV^S>mx)t7b{kGvS3iWy#T>!7D8;KDol5;4TICDmr}) zFTCB?#>4cxuZ`D?k*DZ2Os_{+t+J-2Ke9<>FG^9|9`CFLE##@J8h@-Senpwr)zXwt zw{UGFMW!0w0atvap=K5RuYC2(>-s?B6vg7>VbYg$ARX|v5zk$mL2Q2MfwJDX^UKSD zw@u_%(H2(nXjUbQxyJ{qY>F2Gr%U+?d=x6D5tYyLaI`U_@C^UB(YMiJftB&)CFXB0 zKgP+V@f)QBrPt8%I{UROPB~d{dq`n{{3`OKpW-a;d7Qgz#Fyoi@um^mOy0+mL2AVJ zoJz%pOsUv(ipS(luAE7&&Uh+}}zu!=T*vocHj9Me1YZ-t!*b8Z=4r>?r*Y zKk!lK^Sqx%-t11^(q{UB!t*ALR2=LbMY%DskLdo5#;e9_8|i+i{&PCZ7|HN@2*q1- zvGQ^JH9Lto-^YtaGGS?adyIPt(4Kt!cA7D$LkCn9WsZ_Bvm0t(#7)Yw;vJ~1GHobM zws>x>H(0YHhTi^n~TOCb^s~w=LIKMlO$99=*K6@)$?A@}p-ypl8;FM(=FL zJVY~V@bAo{6F%m%9gSAJHFn^lb#&|2hu$0iufw;0`ISzc-+fn?z8~hy+S@4E&uTq4 z^qHZbZ>!R#Y{Kf?9v`jzaChv~F?DKhNlEG0F#|2k{j-lySJ(>bT8X4*#YEe!(rl-7 zws)~}N5v%-h{y9-v|UwWn#ZDU8F10KNec&wuX;lFj<7vu9(?iHhnu3baQc*~GiOen zGQI3v>XN<(FaCHacX5p^TUgo`r@lFP;`Avtx?>I&i$5Db8GAcF@d^row*DC9NrLVx zkhH8A`>e2CE;6gauE^PvYqoU<-+=I7`>S~jPQ>r*Ke+hj-St1)fGFS9sw*e8dZQ!m z8Gb{PsQh?AyO#62y|eAZwLKR-T)$d1T8~EHU%jfSA3faQ?6FV3f2c9n%Q%$7gCe<1 zy(lCiX0{_@wq>zn2VEjX$yh}_=Jx0VnQ#Ae%>zGGzQOC8eFTej3#oO|fU zO9!7RFr3q;Oqn%n%9QESarVe>C9gcunLdOaQ8%sI+0ef@b^64~Z%*AQPY(3rMR^|0 zO2%5B;>7C}HF7gmXNS>`D$EYw5wFXrAmE~;zm8$bJ;GYy6*z%X8TUX4pr_d*O=q>)nDu7hc~P}WD$p#Xa6V)(XV|;N)F{=`8Z2m1UCSXLIoy@c-%lg zWK$cav8l>uET+C*9?_6mRV8&4J3;Lw3NI-GB@5;WfMzAf8Kr?IXN8{CNtSb_$E7p+ zvw{A4(IA>-l#o;1J8m?Xm)~a?{?yNT$YQ>*lcv|_k496;1`l9M? z#n}&PmTI5IthAoD@P0=zufOn`vz^|q>R9ZsX&dY)VP)4rqoA>CAw-I@9TKjpdO0IJ z?$*5+m{tqtWg}J`=2y44bn`xO2?DOHs*>Hh7#+!xeYL2O6e5OdLiJf<8%G8^l{~%>=U+Q$+DWu zXQbb^V%(`1cRJ2mobZ%0DKyY*kaa>-gjQ!WRyd@S5of|II>Bnz_tN&Z_A>X54DA)( zC7zhC5zN=hnQ!>L(>X&L^0+#Ln_%+tZr;fw12^5nvAoW1X>yt-O`E1m)2A8I{L=gj zLkjJMp@m_E;e`=}k%du((JQ1C@(R_Mphg+0egKNNL&Px-_(UtIb9 z?8RTWmWwNI&!C_3h!J^(UA^ZOYY_x}q3?M;^WgIeBK&~!szUMC=T#nYfFDwKLWPlJ5ksK4vlM762;~e(rT1h#^w@UDlhVf}MVwHvb!$cC)~%J_{QAqc z-~956^vSiWS3dsu%GGN%%KOUaz^M;dE4X+^v(|KeQ9lM%P#1H4nCXo4^23v+o$Rc1 zCJMZ;8|R8Xk^*R|S5zSPtW5r%nmMvYW=GE z4N_iLzJ-|Z<{bZXH+Kn66u3ayNx7s=O&2PTG0P*F-2{DCW09STx>Nf;_I#whcYd5H0 z)$j1kf&4iMXJa+i$tsjU$FK8;@0L_;I%znggW6KigSNqIjd&guG?xh7)0_zw!NM$7 zhu~liYnlLquO-du6r8M+#c3@SN?EC;)EYPpItwz?dDk(-F0XFCsQaNhtlg>Ao#(Zc z7PfBj(IwXh@`#V;FOO?RYs7>rz!xpxNfPEdom?+tcdKRW(9d*?iVo$P8Jn<~otA?) z+fIj8Smla@lTgh>sj8Wh2(78RP8%H8rMb#3o2X_i%FiTy!3&SXTOZ#`kFx1LMGUFN zy$&|1qR00@daIAz^*&-yM;K633s*?u|qSnJk(`t>M| zH-*4W(L+|Gi>8=u%lG^(mcQ$2ti4{d8)q@y8EVq#%~G9UWoPttetLfc z)Qwt8psA_kaqCVVwu7^JGG;@Y;zR$eaJS#93?DxCozLDmNTP>kw{oV+Rl8)=w*42y z5mk)xNRhl6ArHUr{O|N*XN<(Fi@~%xzlM~-B^~$qS5-G;z4MBSiD&C4&seqT#EJB0 zXC6Ah4iLj8b}cTvyZ6AzG2qs;pJVWjQ{@r3PmOgZgNNY4Z&&aA;AdKR%HzhYrMvJM zC{ajTE_WBY=s*)V@4ER{x|yR%{9tz`-w$9Jpo`Fgzv?sql9V=pkCZlcAEnKizf#&@ zTZjt~IyF^6khhbnxKWiiP)Vq|{R)4B>>ne1Nk%kDraQ_$-&4J=vOw=T6 zlXda>md0EpYtGf?>N53t#xDBq1|)(q4uq9tkpB?lI1~dOCr{K&GK}?~2dl{f{Sw10 z|5j$dFp-o(VVW2}IC6_AngX#vljm3DH^gs}I8igfZ?U*sS|~4<7ipIGE%yt>x_NXw zjC4G8XKSC>d$vybb@ejOkRt%^cS9W7C|C`?bHhR7s4Y$5*STkU5z_`$8(&+hMs)iv0$wy=@NOx9!1MfY!FcfFRR7ScngQp-(` z$q4R7SV6B|j@*xY|Bn^bacfC5WFOr)Hc>Z^EktQ(23Y)Te(mHoer57NKRw>jAd(h` zt8?Vx%5+wL1%`kVS6IC={Sr%NN%9ES*RFc@s!}KxiJ{75hJZT4VdRjOSK?g*g<5Bq z0J|xGP{&_17)b)N+5;g0+RYY$epoF5rU0|uWD4kL2|~=8p+a}oYC02y@Q47?_@Yux zcT<-j;J5momYbv-&26IgZu+iR4tia@W=v9A_+6y)o{&Pa*QgWitU?Fd2p3}i9rjAYhb(01`7+Uiyu{8?v|Lpmd; zt*w-!?;;iJ2T6nVW2H%YB+AnJ`KXcpEwyqj6<0UB4BgqI@~8t1*LNJ0pd7=R-%yT9 zcOVBh6UI5S!pt^*ZGs`(VvF+EIASHizs?}kvDXc6*y@6gCm0QWnr0zkLX@8-NDLMn zVflV$O+w?94V0eWkW>L3x_Y`efdkOB((P9R(+SCu`QY;E+TpjhoVMb2$NkLkBP3J0 zE$rS|!m6M+R-PyHbz|d*a%LY`O+`9e7kJWRkX6?9rV_VgrEx$dnB`jh~&2Lo$ z>0QJ?B}zQ0je?Gc{N#`O_{le1;x{4jk)65>#WBUBE!OMX7Y9lx5Wp_LU@cV-+~BI{`QDj;g{*ZdVjts?lnlW zgSgX6Be1}`3L*5;jjNEtZgj33ST=py(1Dem3w}Q^xzg#ZoP6N-f|G+Qf2-LN5w_)t z-zo=JZM$)M$E>P3)j!_YuD;J;b_+gQlp{6K8OZ!)vtW{I!*H7XBL!1ZB(#qZ|1LM= zT_!(K0EJsMNjFJk74Xp^h1kjGM_$;Ys-$dYh<~r~nI)Codq2`IYfQ1xHfLDZjgs+j z`|M0VIX1L?;o-ctAu$@iZ1`n)(rnxr5Eo%H>Fh?3x|ry|E^#>amnjZPy}_Tu*#|p!>w_R$@i(XVAjEHA1z^Lr zCL-2D$Og}iW=xGMk`p?uDlA;xvHPmr@t-LTO!u$xxvP|at*Nb*vkogJJ)Q5DJ_QT?h;Gs|(f};j;=u zSJ)1VvDzdA82ok7<{+Cjl8zFoKggM%`zPQ4UC#4pK=>x9IuOVtT(O#|dSuC+3zm0U zx17yZD#fsd%v*1~@$n}eHfrkXTef`R^gpYV)Po1vdsROue?;+heM>ki_e4e$e^{ti zI>Q|y5q4AaRso^W5r!7VR!Olovn(0z#n>b2ncz&4?j;AbN{dNu<_NF{nqrfhY0b94 z7SW+bSt~3EF$FHvE@*Z3jnP<+0cC<~=*J9jlj2#zj^ za5FJUm!yW^WG7|Y`K3%6vt(%5(xqiXmxS&w+aDbj9dls#{?+zTKXX{?jA5{fo)9W5 zcXoz7!N6@N2Kpg^-UX9AA-JQc(^!mO1^U@FU)gk$u)!3{tgvoqB;23#{Iz2P4ACLh zu|i&uISiWz^#HUZ8Mi!SkPCZg&Y&;CL@pZN&uUex1GM%!DC0aTuO#fb#|lx`pu9Ga zJ*-T>sLW(lWy-~$RI7yRo$1x_(_ME&t%3j0{JqDVn6JlS1Z4NdN&`Lxt z>p>r(iXa#vg5u84t?TfQ!f^nhJakC&n9EQ6r9q(Y9B?5s+7TYe{PhrKXfXU&Uk(bm6NZlwuUhTFzqE!^6m z!vwzIb}Jp|SCu<*@>}7i%d3VC%Wrq-`Rr|0N4I^qP?}8_5kbY9I}kocwp=6G%Z;2xrg@ z7cOWm7cN}D7!tmg!sgi8v93Hg zKp5UqmlN#Jb^$DlQ^CQBpQO>Z}MeZ{Jr@fmGq~!{HuSps7!9y=+4Z4iWwbWf*elYjz(F{6!U{9S+18*H z!eadG;5N;FN)*1gC;mtKz0vCUG3JNJ@2$7vceF^12^Q=Isd-XpfMJsV;UuA>n^$;LCHd?=(+k%ZxlJ#mn-&jkT{5U>;_9lZ z^woV=?s)l7-Tb+kOFMO5Us!+0HCe22jgd<`_jdNGnjMv|IA?U|xM9x93c0L2K6ZIz z#o44l%V(yFv7q8+5`UlW5c!1V7z8qa@7JP{bW^atYle$vox zy7<7s?RD`(Qi1zlK<7Yi%|uoqaMJaLbY3?t%J(=DS7F^~>h|LC;`X@6#;|zcJ$HVw z$J=lgh$j3t+H2rJ#JiCadGDdoP}i%I5Tq3QDeIe zGif@tf9Y^(3*{rRuK(9<3k$N?zy}?O@eevW*pqzCC~2GK7f=#w9n8XNe4xiN3N&T; z;y~9y%`e+QuTqdzcR$XP2~w8BX|-K4yk)*5?1%{Mr|lou&lo|vU_t;aB+ROw)d1}U zHNYaMmLe>aIHAMbmaS3|J$$TwZOQbhC8aZGXl|#sZZ)gpnir3)U-#0=>7}Jpru8nF zq2f4lpzyd#*luB82sQlMUso&tJ3xbYMlB21%aKMQ+~jBB+=&<{2}Iyj_%$t?Ucu_+ zi&h>ZAdc}yTEb~_oATm8MWx0glwq!t#`0~qKzpTOzDn~)}-r%+-x;OW|?0)#gkB5&w`S*6S+IN}RYV5pe zQ#%$98#Q83%Ngyv%*}ZCz+icVZA$5qb++Jz5#fD07x$b}n3q!+YF}s#oHx4LFuc#l z@(-z$#v|1#V`LO@S*wC~7#ZiO!A3JGdF7TLQJ7tzR&G z`N|WHSVL4~V&}Mm9>&&dhm8gx&oRy z>0W#8iyQzCODpas8?>TH&<)Z^gIGEurmrJ-j|aS*%eZq6S0W;>^q2dfiCx+0%2Sme z-eMX!UX0Vm{QjBL+j^t^Gd?TicUq~Zx#%(8nv+OvIxhJ+4XO_nrQE;y`0ue^{ z?vc}kl#HBzTJaDDU~DkX#5T<*;G?-6{2{9dgjwLP28f3SU=y5dodKF1{`!&HLDEuT zBo83bi0JrG83-jfODgq|h~Z8c zH+%NDv2$mSKX~!Na|bV6d`{fwD%UKo*}Qqz6B{DG0mp}RBj zhWAy5pMve%c&hPNbV?`fHKu_Z}+L#S^UXi0))S`lh2S|hv!eLr`%CsI4?Wpji# z8wPqmukd+(?!73_^B`WY-unXUd<8e<1Ywo4+k<1GV%3-^fk#9MaqF5PENW-74T;)# zghj<@1SyJz$5T{Pl*G(&(ea7oNd!uFl{{5&RJc$?CkPZod5b#?{8eZa z&NI|-sjRkHh$+ex6CMy9)hSUtcj1EE`GMh4&i;i=Mp_XQl1<}H5euZ7Y)ORnO0epT zErG>z1)WnW@n^%*fqoC@)8a4tO!baK&P8)k%vlp)_0y#|4GwE6%+uxonFjTaIo#VH zuA1m?Ii`sZrv93ecxSNKq;GF;Uz|bojXb8Yny9aJhH1Gq%~WW0m{P5R$!yhgz~QCD z-)$<+jR|}Ds&kMrA;1_B8DUC@jEKfpR6=BAgd+g~o%jk!h&9I=6HG?4IkuxQ0@0q; z0n&M!VQavfj>xFUP)BS`K%h3-1jAQ^P#S91mIj9Qh)fOa5gTW@4u3z$Oe8kBRaC0j z3x=Eb<(DK1cdD9SR2z zZgAcAs0#8Qe)!=Itq+W*-n+Wz z)xqy^Jtt9we@XGoF2!2qjfketRNg|4pwE=rvGr`%f(s0RyY8SLwp>|>|A01=NDO=e zZKl{NOQLva3@9`*s;TX-;eC2@{BBOP0Qeoq=A!@o?Jb(L6CSJmTQzAX98}wr-R*B; zd@UazCx?#@+{F0zxAQaOZKv_kALmUyC;rDQ4%mDw-AA``pE>n;nosSg;=KMC3p5M5 z6zW8ooz!?LBW}6vow0TpnR9yVW zdur5|lJcnQGujWp)>StO@B>!7C!OzwINx$y5a7r8j&lZi&Nq*v;A@z19}Noi(xChM zG}55^`_S5|<9KM0F+4gDa~d4csYozn4)@R?bxfi`YJU$6GN#2+e@#i6Gqx#=v>$3; zbw47H!5519T4zKok4}pyjCMq%Mhg+b**8BOnZm{3NW)FN~wMKk7 zIptT^!ejYW7Vr>>n{jD=%mp4m`Eo|n9O>KsZxy?A90NzGEoX6qy!s0Nf@Z!7^ zO{fHI*5mHd<~XYk6srB}nI8T}8-n#BoHsQY=A0m8wlHLdVB^T86g$Ru>kh@bHU|Dc z>dbVI7>HQTc((1^-A_ERTj_ZLW!`@K4bGewjh{gUlOVVniw9PCbt+bZT zLf169LR>pS*b+kVQ54huS!58YcME}Xe=*30tDD{tTU$h2fkdao7kN9V6*|$8dO-WU2e%`y zqHq6f&p60D>DzAcv?Dj6PrFX*X&2{EJI-=4*8B*3O#E<`I|)_J?)ll~G-IID);~cn zM0fIMF`J_+BlHz<*_+#*GPm}x3udoonk$^`PBxF**%?s@p$Yj?YG7-PEwERrFgM!2 zS8yjyueK?(JF5;SlzxO;vbbc*Z+5uY!Ps*v1F|Us-|sZ4@pzXsry(sXt!-L%T8=!7 zWzk0P`=0x@9>p}V_erek6%e`(I9mJO=v7mMRg6i0cEON-<;Cp#UV{epWZyw6#>UPl zS(%Z&rrWef9Z73P);x9o)ZEd-bJi5}T9Y?)NkZ(JA%`DkFBO%|95Qk(t7=odcEb}X zRp$7(JzFy~4<)Dc?Oj@WXy0=$3|_DzCFwwXY@sv13; z`%6B_gZaJ}srznvaQnOmw~OPNwA21#9IIBCgmy^N&L}#?nExowaA!WxPfhUa{&o+( zG-}E{!OOc1EB-=)_=Q2Xukc@f%eH zOoDKQN`8t~UyCG($ks6*mMRi4$TEsUe)$~KCgi~g+X=b)Y9Q>fAAZIkWfCPEVVi%J z{`t$^gLF6~A@yFZyhDD)Ellf-8$0keuiU4v-;Igv%9)0TtmV6L+>u zX$g74;)sstU3AHIOB9OT2F7=`1lkK)a$VAWG6h5n_nr6$%Y8xx1PnxyaKj2PK{d0J zVM>SVk4KguYnDgGkfti>&Bk`9+-fX}AKhv5qbAelq~u?|8M8ZY+pv8tTK@9w_$P8} z%O#`hz0}l?ue6!|x3tz*FQm=sR@?3DO!COg&N5KEwV{c&WW4+-X>YNOffv>&tdnL*G`8jM49x>H1qM+v;hhaoJ%|n|RfI%^F*rZg{9;KI zH}dxdSLXCu9RqTik?t2-(q7;^1tF6nt=mKTQlUie6jJpLL0vbMuNPq)+)P0Cz2kr% ze5$!(NfPI>H~1$QiRMN7Ebs|xAL4le?L3DEmn(6@#C@-YP{!|jw2ujVU%*i?{yZ|Z zdHc_?B;lsFj4i<@cnpBd0FH-&wARhtYszH-73boq9h{u6wc4NK+@JevIc}N$+@J5|1N!s5Y}y|cE7KuKh9VNwWGIB|HiY_v_F5}2lVIf+jM-_S<113_j*oPaqqMH z;OUL_YWNtpRw2Us67Ci?!Vet9jUAN3h@22aIUL$l*j&v-IXIl0$2aNU1N}pV9!CQE zc%l@Yx*5U%oZKLEWP&XRwaAt&vqYNx^pMCp2{S=@;FvA(=@k$YZB+d{*@k)WFI$MCYBJ8Ba9kgT#vf2z< zlf}PlB+S>B8UPEfegp_K|JMNqxqxuTJuZ5ai#xPDfQr;R+!x3b8nJX~JsYV!`KN#; z`Imi*7VT5cAW8yz@Frl=>V^Y{xV8j)0R0pwZ%n8mnka8csMAmwnr281br?u8p>uW= z&vYhPi=-axCZtr}u8x)FrxKE9AMsIl+@SCv%CY61-?f+!oqd0_~@`Gs?T(-I?fDVL0m$BkBUJG3QK?k4u4Pfd@a@6ji{@rgSg4tU@%oI?)x|7AR!aOQssha*j(S7VL~6#o7HARJB} zp``kT!(pw?W}shg{|%x*gf!Ho`)$w$aY3Ug^MhBhzx<&T@R|oQ0m5r zngco{nQMc@vgEng8WIf&H8}q_$$x;7a3$Cw;eh@^A^PD(*1oqgpK>-mT#DiwuE#!} zuKa+sW@7tE(tn(CtsAy+$1qk|TWht(IibdBHlg_95`G#+$KM$l*kL)q?g4y?Ogtv`27V z%yVhf?(NUVr*Y7e%QY=j85`{pT*gLEl56g$<3QaZ@8I;h4}$1);s~WXK0w|V#6sk2 z{wqWY8HiwmONVT;R7dOx*FadvY4kg})WdZw&Z%Q;IbAG>g&ZT+&BPe@-iXwFWYR8vs!i1eRh&tALOFi3Od z_33jIh+hQHS-^w$1yu(;VQ@Q?Lo5|hC+%lKv~{`=9V|A*!J%4vSMs)i6!Cw9N9PV$ zYnzRXl6Hh76G$fj5+akkc0p)z|NgU|>puXoPHk1FmWdatw+t;ukTL~5W~9#~KO*dp zY6ofL!x?A}K4uZ65b#k$3HWd-Ze;3xjO#HxycnmvFZ$|_1&LA^bWPr|8hJ8}WjPkE z7aYWs=|1MG4{^(o?r|)~P&zT5`hkbL`+4m?#!Sw0X*`12t9KE%@^*p)&yd6`zY6)y z!fj$PrfQ?ruUfysE>s);j`9|IG1%-M9g2HOtKeu&IM410>paEB^COA_i?xSlB*7Nz zAiY#F!#Sn13Kt5i1px+D`Bm3b%0GX;1NBm0B*HI3T#oYh&71$84+rsHtcLAjJyav5 zyz)zBpR)f8c_pMu6YhsEaXoGbECUmrxf!Y4>(ZX+@XxUej?FQZ{z9ES(!V0!{;E}5 zk(GKfIeurZAY~+m8hV-L#z?*Foq~I{oSh5g;8~n-z*VIQXZWi987fJ zp_JrK9XoemNCiPDAqqMabRcys?PC@8>phj0+&j)`Nfx#9SkDchB}u3y^|nCNWPsWq zGy{3Ph?dMEnt|TDzXR=v4W;%C)Q;Xhn z4i9t`fb$CWPpi_laDrx_dwiaotMQJ3Pkj3~-l@F(AzLDs7vMa^@fN++@ktit@T=|K z{+PEI<0sO%oEEC~WfdN>Q=lio?;a-=;~-y_cl>O3`)af!ev{f^hSj1Tm^v@`sl1nu zkDgZ2A86rQ0XuVmLA5jE-B+WJUb_r);VHn-oY8&1F*lc4Xyvra#%e_5nu!y#b{Zt1 zGz#rdDg)f;7O^9ee{r(#KirGxJkb|VL*Y)^g?!MzUQ~X?4@%zUI(^V}O6+h@bYdPp zKVnZKgpN+AoQ)b=ojzC&t&3n`XN+}bqd7p-LcgiCg$3CoC;)^_}up&tClo<=$RCvkK!~j#GzMdqB>?H9i|b3kJ&_&O#2fZ z=41NMVH#6^%#4I#DjinGYNW#|bTN9t%;)sdVHLJUI;_GL=I+->hxvH=0l)!_1RgsF zev~Cx2le@Xq8(2H59gRa;P0%?55FQe-KP0z-PHbcE>yZr^YQgm#!`+p_xQMrMc!8X z18gEP z9Rs#k^zio?L)BsOF^qKXp~>X)tIv|17ti3_B!j`zxslCA@42Y~j1RkMNd%`Q$i0hs zFQVO|(vpER<}mk|YJYye{H1v(BCWnbJSUHcLveT)uue_g2Pr z)vK4t1QaIRo!682S@QgHUj}F^WznIuYy3vU7tKb_^==FBY(9;D|N$$H|C8Bgyj0CHN@im)!K=-UFZL5*|fp+cU|5!6H#4K zkoREC{6NVC%1{X@w@p%Fd{U-thhu_p_Pw zVuj=2K(#TpT|^I(Cy$Uim!i|90%Z5gvCyK5R0?R74$RW^iP%hj_FQl*cNG zN$+o1v#x9B&Ry57QKq!qHSWS3{JAuyXV2F4XHW`a2q2z1?aJk8)1X4!{U2q1vlWV(EZSOGb3~$VMnHB^&$H9}X zd$J~|*)z1d&B&>Z-1CLXS>-e2)b9T5V9KdI@L;iKcXF~a9@+G^DwB9pZPb&=fR}Ze z69s%S!Am%AOAHpV{)y8N6Gt zoxzzIxK?DX?@D>RfApsD#+<{k-m^7ZXtmWjQIrABJ58r_o9MHp(>}?%x^@c6$CS7) z+?TUUY|e5lv%1keX4&=*p1fVaQwZf;Kkd=|)Bh>Qav(Uf;91OgD}PfuA6{27*7X}t zdhl=B=B3q~W}{V4vhYSPGEHh~;;i(p$Di_elHHw8XMuP>9b_*Z#5(Z%8_p-? zR?Bx9kwY!R($)}?A!JeB7z8R3uR&EX%DMJ}L0cWLBPyhtg~6wqK8LT+ojaGog^k0!O*?Qxaim+qHbyVQ=M;RkHOonA7rlFb<7z3g{09*(FL-nH_$wEkV(BG3| zUT~lY(#~W8?-st%g^YZwc*p^{wt2$@)o66zix$;>VfCvwGR?K_|5!NT#?Ip_m6sg9I77utbA7^#l-DheEf#P@lx~Vi)T+=w14NS${lU8-fWim-P@180hkM+ zM|cEhA_yNzV;yNxGU3Z`mII;-`oZM!S**@N_2B7yQT?EMjuy!(A3gc&% z#_}0Q;!HoAXo-kCapFj*j*%&@Pv7HR(DN1sYyMG_B>CY;r5FaH)plLPpOWQ^LL~AT)oHpzS8XGZ ztiiF4EDKMsk;&ktn3<7f5wD?w!3d>@B`Rqju{mtcHP_zPKe{AtQVNy1w{9U7|4p%; z%8fScN4&x-n>Mj7>iOva8nqQ`iQ@zxS};3WGc{u{>Dzs^M^=0S91(wFaf#VMZBw6l zY}fMQ?hkeBwsimgUe+E1<~=6XDWC34ZzGG{JJztrm9aNJ8!_T4b2KKGTW3uFOr7^l z%-arlV8y)HE80Cf?lg8jsVFLMP%i$Kt;$ZYe;zC!qDeV;uwl{i{DS8ujeDJ+dwL%B z4_Xm^CF6pb$2vjhnkVx|6pQk!=uYYXJJa#B{}MR-QU3wpE@rsN>XqqMGskqFi&(D2>jXm5?c$XCHDW zzK1q+0*!qOV^f|vJK!Xe&(9Ua3g2{X9^IG5H*K5r?RGcHD^_29HO8#Pn3TT_V|uls z{36J;qL?AYs~1HjCS++d+_(WpT%M`z+!pbftqpH(A=q%!kf-9k&G=6Oymfi*UAQr! za*f!Dm6s}&>_4ZJQ%c<__H3N8qm->Yd`kYuf2Sc+!>i(Hms5JU`0jM($7PwR_rBnD z%iQuqTw)mfG`X6FBNOLSSVec{QZeVjiPdHyuNo?rDGh#$PkR-Ij#D)x^JBp?x3tmW5=SAWH&HtsP-n@m5?U9U=o}tJEsH z73-Z<@b>g=U;gdbbS3A8xFLVjriBYPZORwF5o?E-cCV�ksYDPP1jw@Jdfc|4N!; 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 GA^!(I^0iR_ literal 0 HcmV?d00001 diff --git a/Src/gui/themes/default/highlighted_key.png b/Src/gui/themes/default/highlighted_key.png new file mode 100644 index 0000000000000000000000000000000000000000..2a5072740e5cd7e29bf3985ed98c9a525ff89cf5 GIT binary patch literal 413 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|zjKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPgga9uZCh!zA_NCxAkdC9V-A&iT2y zsd*&~&PAz-C8;S2<(VZJ3hti10pX2&;y^_|JY5_^JdVG;X6Sv`LE_j)^?ciR3M~#& zcU+@1oIcF9=zMU=G3F1G-%O*QtTA(9xMcrIV z=pv)U$Qz-wIgw^pyCFZI7l-@(bB_V2N<(kuy7XRacZ* z3jfZnsw}ZkV>l5N`6Nm&HYrlO`~K6n#jpM|9A205Wx})iHNY@n@O1TaS?83{1OUIi Bp=SU9 literal 0 HcmV?d00001 diff --git a/Src/gui/themes/default/infobox.png b/Src/gui/themes/default/infobox.png new file mode 100644 index 0000000000000000000000000000000000000000..0ff3e46ee43ea8b0f69317a0c8e6d46eb84fefbf GIT binary patch literal 1731 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 literal 0 HcmV?d00001 diff --git a/Src/gui/themes/default/selected_key.png b/Src/gui/themes/default/selected_key.png new file mode 100644 index 0000000000000000000000000000000000000000..5963e1b0ca8b5e1e863c3709a0fe04024812547a GIT binary patch literal 331 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|zjKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPgga9uZCh@eNu|ra&Rd64!_l=ltB< z)VvY~=c3falGGH1^30M91$R&1fbd2>aiF4Qo-U3d9>?EaQxrO6AmDIuzE6L{Dci2I zj20}+ibP0l+XkKw&r+R literal 0 HcmV?d00001 diff --git a/Src/gui/themes/default/status_bar.png b/Src/gui/themes/default/status_bar.png new file mode 100644 index 0000000000000000000000000000000000000000..bb71fa7f951fc994261a4b50cc80b26ceca74c61 GIT binary patch literal 473 zcmeAS@N?(olHy`uVBq!ia0y~yVEh7P%W<#)$y;@AZUHIA;vjb?hIQv;UIIC6N#5=* z4F5rJ!QSPQfg+p*9+AZi4BWyX%*Zfnjs#GUy~NYkmHif@04FQ=_nN;gKq1Kz*N775 z{M_8syb=cIqSVBa)D(sC%#sWRcTeAd@J2pypj9TGE{-7;x8B}9o!jid;Ck`+nzQ=leWG!$er|NlFXzn zj0|!|r#zXGGH3Uw$ME69x8m!3+uJvF{cNAX>|pvUd-s387kP5U=FXS~W`U~pRJRfB$La;5Na7GJufYC+V9(M4N5($els|Ts(*g??SuY{>nrjh p{`Y zhW{YAVDIwDKoQOYkH}&M25w;xW@MN(M*=9wUgGKN%6^lFMbL~j{Hfs@ppayVYeb22 zer|4RUI~M9QEFmIYKlU6W=V#EyQgnJcq5-U0|V=PPZ!6Kid%1Q@AntUWH|n?Jk4c7 z7?<`P86K|^Q#GkQOxpSzTW(bBWI7x5;;(bi4nwi&ixmTAd8i)Uc=3paR4Th(b%@vv zrH;)pi2+Z3Z0x>MdFb<$*G7}{Ppa!5&Jp<*5awqc?p&m;vXFGy}Cx^_ORSu+wv3MP)XsxjLS*m1v;D~TQ9_8{Vg^X& z^eJ2C-Byhjl?>K%T^5~vJh5!vi{CHxFEh$3fBNtv?YoQFUs1J8d$V+-gym{~lohU4 zAJweSWxV!UPmDkGz3B37AP4AIo@2go<|Oyu+DOa2TT&fBZck&{wrQi_$LE*b&rdjh zx$*6i^z*Wj|CitWQ5@NK&yat^XU!+Y+K&Y6>QwH(WX|{^VifJ?U(e-Xo3}e#Y(Zf5 z*$!uphfnVus+`Qw8w+py4GlsnW-Pa zl(9=*_igJBU=$?=Gn}pZx2nvdEB?=}EUpCeBw+?7CJqh-g@y(OCu;K0Dh$if1pz2mcqnR?oL_R&V&`tfEw}k1egskN0%Ry%H?E;5D*-MR4YU{Ngixz=Lzb^SglFgQH zhwkLt>n#JOJwx6NbKl&&Tpqjs&&7W)S%jQ8zAoLq-Iw`IO0D*yum2y2Fqu^S`tgY6 z(?%Wca37YO+Fw653C6Ri=%)6^+0R=ugY(9Vua8f9MV*pcTd#ZTO>h0bd;2fN>c|;M z3OI3WzI<7}?nmXO)W@%9*Uhm9=D$=>e#w!Vuw}~G^C4<%XW7mGNuXoz7dY6tEwQo- zp1C8>&f>zy9rLEGimrQLcIzcm?sSMfvcT3%s6Rn$yZq3{xKf5?t z^xOWMFJJQid^CIA+Pd6KD~0S;-@Ag<^}l?dDe-Oj^?r42Tk~c5X21TexcOfJT7Jxn zX#J}UE?P1lo;vp2=9`VeeCJEXBHLy6Dyw|h+x{3_;Ow8hzJK30=^47qm%lE&eRp~> z_w)5}(msDY9{kTONzt*tdiA5qI{mwE^iuWrJ&U>+SC<@V`8J04n_handlers = 0; + this->handlers = NULL; +} + +int TimerController::arm(TimeoutHandler *which, int ms) +{ + int i; + + /* Set the timeout */ + which->timeout = MS_TO_TICKS(ms); + + if (which->timeout == 0) + which->timeout = 1; + + /* Re-register? */ + for (i = 0; i < this->n_handlers; i++) + if (this->handlers[i] == which) + return i; + + /* Not already there */ + for (i = 0; i < this->n_handlers; i++) + if (this->handlers[i] == NULL) + break; + + if (i == this->n_handlers) + { + this->n_handlers++; + this->handlers = (TimeoutHandler**)xrealloc(this->handlers, + this->n_handlers * sizeof(TimeoutHandler*)); + } + this->handlers[i] = which; + which->timer_id = i; + + return i; +} + +void TimerController::disarm(TimeoutHandler *which) +{ + panic_if(which->timer_id >= this->n_handlers, + "timer_id %d is too out of bounds (max %d)\n", + which->timer_id, this->n_handlers); + + this->handlers[which->timer_id] = NULL; + which->timer_id = -1; +} + +void TimerController::tick() +{ + for (int i = 0; i < this->n_handlers; i++) + { + TimeoutHandler *cur = this->handlers[i]; + + if (!cur) + continue; + + cur->tick(); + if (cur->timeout == 0) + this->disarm(cur); + } +} diff --git a/Src/gui/timer.hh b/Src/gui/timer.hh new file mode 100644 index 0000000..57801b8 --- /dev/null +++ b/Src/gui/timer.hh @@ -0,0 +1,46 @@ +#ifndef __TIMER_HH__ +#define __TIMER_HH__ + +class TimeoutHandler; + +class TimerController +{ +public: + TimerController(); + + int arm(TimeoutHandler *which, int ms); + + void disarm(TimeoutHandler *which); + + void tick(); + +private: + int n_handlers; + TimeoutHandler **handlers; +}; + +class TimeoutHandler +{ + friend class TimerController; +public: + TimeoutHandler() + { + this->timeout = 0; + this->timer_id = -1; + } + + void tick() + { + this->timeout--; + if (this->timeout == 0) + this->timeoutCallback(); + } + + virtual void timeoutCallback() = 0; + +protected: + int timeout; + int timer_id; +}; + +#endif /* __TIMER_HH__ */ diff --git a/Src/gui/utils.cpp b/Src/gui/utils.cpp new file mode 100644 index 0000000..cf28a04 --- /dev/null +++ b/Src/gui/utils.cpp @@ -0,0 +1,273 @@ +#include +#include +#include +#include +#include +#include + +#include "utils.hh" +#include "font.hh" + +TTF_Font *read_and_alloc_font(const char *path, int pt_size) +{ + TTF_Font *out; + SDL_RWops *rw; + Uint8 *data; + FILE *fp = fopen(path, "r"); + + if (!fp) { + fprintf(stderr, "Could not open font %s\n", path); + return NULL; + } + data = (Uint8*)xmalloc(1 * 1024*1024); + fread(data, 1, 1 * 1024 * 1024, fp); + rw = SDL_RWFromMem(data, 1 * 1024 * 1024); + if (!rw) + { + fprintf(stderr, "Could not create RW: %s\n", SDL_GetError()); + free(data); + return NULL; + } + out = TTF_OpenFontRW(rw, 1, pt_size); + if (!out) + { + fprintf(stderr, "TTF: Unable to create font %s (%s)\n", + path, TTF_GetError()); + } + fclose(fp); + + return out; +} + + + +static int cmpstringp(const void *p1, const void *p2) +{ + const char *p1_s = *(const char**)p1; + const char *p2_s = *(const char**)p2; + + /* Put directories first and handle some special cases */ + if (*p1_s == '[' && *p2_s != '[') + return -1; + if (*p1_s != '[' && *p2_s == '[') + return 1; + return strcmp(* (char * const *) p1, * (char * const *) p2); +} + +/* Return true if name ends with ext (for filenames) */ +static bool ext_matches(const char *name, const char *ext) +{ + int len = strlen(name); + int ext_len = strlen(ext); + + if (len <= ext_len) + return false; + return (strcmp(name + len - ext_len, ext) == 0); +} + +bool ext_matches_list(const char *name, const char **exts) +{ + for (const char **p = exts; *p; p++) + { + if (ext_matches(name, *p)) + return true; + } + + return false; +} + +const char **get_file_list(const char *base_dir, const char *exts[]) +{ + DIR *d = opendir(base_dir); + const char **file_list; + int cur = 0; + struct dirent *de; + int cnt = 16; + + if (!d) + return NULL; + + file_list = (const char**)malloc(cnt * sizeof(char*)); + file_list[cur++] = strdup("None"); + file_list[cur] = NULL; + + for (de = readdir(d); + de; + de = readdir(d)) + { + char buf[255]; + struct stat st; + + snprintf(buf, 255, "%s/%s", base_dir, de->d_name); + if (stat(buf, &st) < 0) + continue; + if (S_ISDIR(st.st_mode)) + { + char *p; + size_t len = strlen(de->d_name) + 4; + + /* We don't need the current dir */ + if (strcmp(de->d_name, ".") == 0) + continue; + p = (char*)malloc( len ); + snprintf(p, len, "[%s]", de->d_name); + file_list[cur++] = p; + file_list[cur] = NULL; + } + else if (ext_matches_list(de->d_name, exts)) + { + char *p; + + p = strdup(de->d_name); + file_list[cur++] = p; + file_list[cur] = NULL; + } + + if (cur > cnt - 2) + { + cnt = cnt + 32; + file_list = (const char**)realloc(file_list, cnt * sizeof(char*)); + if (!file_list) + return NULL; + } + } + closedir(d); + qsort(&file_list[1], cur-1, sizeof(const char *), cmpstringp); + + return file_list; +} + + +/* PNG writing */ +struct png_write_user_struct +{ + size_t sz; + void *data; +}; + +static void user_write_fn(png_structp png_ptr, png_bytep bytes, png_size_t sz) +{ + struct png_write_user_struct *out = (struct png_write_user_struct *)png_ptr->io_ptr; + + out->data = xrealloc(out->data, out->sz + sz); + memcpy((uint8_t*)out->data + out->sz, bytes, sz); + out->sz += sz; +} + + +static int png_colortype_from_surface(SDL_Surface *surface) +{ + int colortype = PNG_COLOR_MASK_COLOR; /* grayscale not supported */ + + if (surface->format->palette) + colortype |= PNG_COLOR_MASK_PALETTE; + else if (surface->format->Amask) + colortype |= PNG_COLOR_MASK_ALPHA; + + return colortype; +} + + +static void png_user_warn(png_structp ctx, png_const_charp str) +{ + fprintf(stderr, "libpng: warning: %s\n", str); +} + + +static void png_user_error(png_structp ctx, png_const_charp str) +{ + fprintf(stderr, "libpng: error: %s\n", str); +} + + +/* This is taken from http://encelo.netsons.org/programming/sdl (GPLed) */ +void *sdl_surface_to_png(SDL_Surface *surf, size_t *out_sz) +{ + png_structp png_ptr; + png_infop info_ptr; + int i, colortype; + png_bytep *row_pointers; + struct png_write_user_struct out; + + out.sz = 0; + out.data = NULL; + + /* Initializing png structures and callbacks */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, + NULL, png_user_error, png_user_warn); + if (png_ptr == NULL) { + printf("png_create_write_struct error!\n"); + return NULL; + } + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + printf("png_create_info_struct error!\n"); + exit(-1); + } + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + exit(-1); + } + + png_set_write_fn(png_ptr, (void *)&out, user_write_fn, NULL); + + colortype = png_colortype_from_surface(surf); + png_set_IHDR(png_ptr, info_ptr, surf->w, surf->h, 8, colortype, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + /* Writing the image */ + png_write_info(png_ptr, info_ptr); + png_set_packing(png_ptr); + + row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*surf->h); + for (i = 0; i < surf->h; i++) + row_pointers[i] = (png_bytep)(Uint8 *)surf->pixels + i*surf->pitch; + png_write_image(png_ptr, row_pointers); + png_write_end(png_ptr, info_ptr); + + /* Cleaning out... */ + free(row_pointers); + png_destroy_write_struct(&png_ptr, &info_ptr); + + *out_sz = out.sz; + + return out.data; +} + +void highlight_background(SDL_Surface *where, Font *font, + SDL_Surface *bg_left, SDL_Surface *bg_middle, SDL_Surface *bg_right, + int x, int y, int w, int h) +{ + SDL_Rect dst; + + /* Can't highlight without images */ + if (!bg_left || !bg_middle || !bg_right) + return; + + int font_height = font->getHeight("X"); + int bg_y_start = y + font_height / 2 - + bg_left->h / 2; + int bg_x_start = x - bg_left->w / 3; + int bg_x_end = x + w - (2 * bg_right->w) / 3; + int n_mid = (bg_x_end - bg_x_start) / bg_middle->w; + + /* Left */ + dst = (SDL_Rect){bg_x_start, bg_y_start, 0,0}; + SDL_BlitSurface(bg_left, NULL, where, &dst); + + /* Middle */ + for (int i = 1; i < n_mid; i++) + { + dst = (SDL_Rect){bg_x_start + i * bg_middle->w, bg_y_start, 0,0}; + SDL_BlitSurface(bg_middle, NULL, where, &dst); + } + dst = (SDL_Rect){bg_x_end - bg_middle->w, bg_y_start, 0,0}; + SDL_BlitSurface(bg_middle, NULL, where, &dst); + + /* Right */ + dst = (SDL_Rect){bg_x_end, bg_y_start, 0,0}; + SDL_BlitSurface(bg_right, NULL, where, &dst); +} diff --git a/Src/gui/utils.hh b/Src/gui/utils.hh new file mode 100644 index 0000000..aee5894 --- /dev/null +++ b/Src/gui/utils.hh @@ -0,0 +1,82 @@ +#ifndef __UTILS_H__ +#define __UTILS_H__ + +#include +#include +#include +#include + +#include +#include + +class Font; + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) + +#define BUG_ON(cond) + +#define panic(x...) do \ + { \ + fprintf(stderr, "=============PANIC PANIC PANIC===========\n"); \ + fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); fprintf(stderr, x); \ + fprintf(stderr, "=========================================\n"); \ + assert(0); \ + exit(1); \ + } while(0) + +#define warning(x...) do \ + { \ + fprintf(stderr, "==============WARNING WARNING============\n"); \ + fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); fprintf(stderr, x); \ + fprintf(stderr, "=========================================\n"); \ + } while(0) + +#define panic_if(cond, x...) \ + do { if ((cond)) panic(x); } while(0) + +static inline char *xstrdup(const char *s) +{ + char *out = strdup(s); + + panic_if(!out, "strdup failed"); + + return out; +} + +static inline void *xmalloc(size_t sz) +{ + void *out = malloc(sz); + + panic_if(!out, "malloc failed"); + memset(out, 0, sz); + + return out; +} + +static inline void *xrealloc(void *ptr, size_t sz) +{ + void *out = realloc(ptr, sz); + + panic_if(!out, "malloc failed"); + + return out; +} + +#define xsnprintf(buf, size, fmt, x...) do { \ + int r = snprintf(buf, size, fmt, x); \ + panic_if(r < 0 || r >= (int)(size), "snprintf failed for %s with %d\n", fmt, r); \ +} while(0) + +TTF_Font *read_and_alloc_font(const char *path, int pt_size); + +bool ext_matches_list(const char *name, const char **exts); + +const char **get_file_list(const char *base_dir, const char *exts[]); + +void *sdl_surface_to_png(SDL_Surface *src, size_t *out_sz); + +void highlight_background(SDL_Surface *where, Font *font, + SDL_Surface *bg_left, SDL_Surface *bg_middle, SDL_Surface *bg_right, + int x, int y, int w, int h); + +#endif /* __UTILS_H__ */ diff --git a/Src/gui/virtual_keyboard.cpp b/Src/gui/virtual_keyboard.cpp new file mode 100644 index 0000000..7feca89 --- /dev/null +++ b/Src/gui/virtual_keyboard.cpp @@ -0,0 +1,440 @@ +/********************************************************************* + * + * Copyright (C) 2009, Simon Kagstrom + * + * Filename: VirtualKeyboard.c + * Author: Simon Kagstrom + * Description: A virtual keyboard + * + * $Id$ + * + ********************************************************************/ +#include + +#include "virtual_keyboard.hh" +#include "utils.hh" +#include "gui.hh" + +typedef struct virtkey +{ + const char *name; + int kc; + bool is_shift; + bool is_done; +} virtkey_t; + +#define INVALID_VIRTKEY ((struct virtkey){NULL, -1, false, false}) + +static inline bool IS_INVALID_VIRTKEY(virtkey_t *k) +{ + return k->name == NULL && k->kc == -1 && + k->is_done == false && k->is_shift == false; +} +/* + C64 keyboard matrix: + + Bit 7 6 5 4 3 2 1 0 + 0 CUD F5 F3 F1 F7 CLR RET DEL + 1 SHL E S Z 4 A W 3 + 2 X T F C 6 D R 5 + 3 V U H B 8 G Y 7 + 4 N O K M 0 J I 9 + 5 , @ : . - L P + + 6 / ^ = SHR HOM ; * � + 7 R/S Q C= SPC 2 CTL <- 1 +*/ +#define MATRIX(a,b) (((a) << 3) | (b)) + +#define K(name, a,b) \ + { name, MATRIX(a,b), false, false } +#define S(name, a,b) \ + { name, MATRIX(a,b), true, false } +#define N(name) \ + { name, -1, false, false } +#define D(name) \ + { name, -1, false, true } +#define J(name, v) \ + { name, 0x40 | (v), false, false } + +#define KEY_COLS 15 +#define KEY_ROWS 8 + +static virtkey_t keys[KEY_COLS * KEY_ROWS] = { + K("<-",7,1), K("1", 7,0), K("2", 7,3), K("3", 1,0), K("4", 1,3), K("5", 2,0), K("6", 2,3), K("7", 3,0), K("8", 3,3), K("9", 4,0), K("0", 4,3), K("+", 5,0), K("-", 5,3), K("£", 6,0), K("Hom", 6,3), + K("Cr", 7,2), K("Q", 7,6), K("W", 1,1), K("E", 1,6), K("R", 2,1), K("T", 2,6), K("Y", 3,1), K("U", 3,6), K("I", 4,1), K("O", 4,6), K("P", 5,1), K("@", 5,6), K("*", 6,1), K("Au", 6,6),K("Rstr",4,0), + K("R/Stp", 7,7), K(NULL,0,0), K("A", 1,2), K("S", 1,5), K("D", 2,2), K("F", 2,5), K("G", 3,2), K("H", 3,5), K("J", 4,2), K("K", 4,5), K("L", 5,2), K(":", 5,5), K(";", 6,2), K("=", 6,5), K("Ret", 0,1), + K("C=", 7,5), S("Shft",1,7),K(NULL,0,0),K("Z", 1,4), K("X", 2,7), K("C", 2,4), K("V", 3,7), K("B", 3,4), K("N", 4,7), K("M", 4,4), K(",", 5,7), K(".", 5,4), K("/", 6,7), K("Dwn",0,7),K("Rgt", 0,2), + N("None"), K(NULL,0,0), K(NULL,0,0), K("space", 7,4),K(0, 0,0),K(NULL,0,0), K("f1",0,4), K("f3",0,5), K("f5",0,6), K("f7",0,3), K("Del",0,0),K(NULL,0,0), K(NULL,0,0), K(NULL,0,0), D("DONE"), + K(NULL,0,0), K(NULL,0,0), K(NULL,0,0), K(NULL,0,0), K(0, 0,0),K(0, 0,0),J("Joy up",1),K(NULL,0,0), K(NULL,0,0), K(NULL,0,0), K(NULL, 0,0),K(NULL,0,0), K(NULL,0,0), K(NULL,0,0), K(NULL, 0,0), + K(0, 0,0), K(NULL,0,0), K(NULL,0,0), J("Joy left",4), K(0,0,0),K(0,0,0),J("Joy fire",0x10),K(0,0,0), K(NULL,0,0),J("Joy right",8),K(0,0,0),K(0, 0,0),K(0, 0,0), K(NULL,0,0), K(NULL,0,0), + K(NULL,0,0), K(0, 0,0), K(NULL,0,0), K(NULL,0,0), K(0,0,0),K(0,0,0),J("Joy down",2),K(NULL,0,0),K(NULL,0,0), K(NULL,0,0), K(NULL,0,0), K(NULL,0,0), K(NULL, 0,0),K(NULL,0,0), K(NULL, 0,0), +}; + +static const char *shifted_names[KEY_COLS * KEY_ROWS] = { + NULL, "!", "\"", "#", "$", "%", "&", "'", "(", ")", NULL, NULL, NULL, NULL, "Clr", + NULL, "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", NULL, NULL, NULL, NULL, + NULL, NULL, "a", "s", "d", "f", "g", "h", "j", "k", "l", "[", "]", NULL, NULL, + NULL, NULL, NULL, "z", "x", "c", "v", "b", "n", "m", "<", ">", "?", "Up", "Lft", + NULL, NULL, NULL, NULL, NULL, NULL, "f2", "f4", "f6", "f8", "Ins", NULL, NULL, NULL, NULL, +}; + +VirtualKeyboard::VirtualKeyboard(Font *font) : GuiView(), ListenerManager() +{ + this->font = font; + this->sel_x = 0; + this->sel_y = 0; + this->shift_on = false; + this->kbd_only_input = false; + + this->is_active = false; + this->buf_head = 0; + this->buf_len = 255; + this->buf = (struct virtkey*)xmalloc(sizeof(struct virtkey) * this->buf_len); + memset(this->buf, 0, sizeof(struct virtkey) * this->buf_len); +} + +VirtualKeyboard::~VirtualKeyboard() +{ + free(this->buf); +} + +void VirtualKeyboard::draw(SDL_Surface *where, int x_base, int y_base, int w, int h) +{ + int key_w = w / KEY_COLS; + int key_h = h / KEY_ROWS; + SDL_Rect bg_rect = {x_base, y_base, + key_w * KEY_COLS, key_h * KEY_ROWS}; + + SDL_FillRect(where, &bg_rect, + SDL_MapRGB(where->format, 0x00, 0x80, 0x80)); + + for (int y = 0; y < KEY_ROWS; y++ ) + { + for (int x = 0; x < KEY_COLS; x++ ) + { + int which = y * KEY_COLS + x; + virtkey_t key = keys[which]; + const char *what = key.name; + + /* Skip empty positions */ + if (key.name == NULL) + continue; + if (this->shift_on && shifted_names[which]) + what = shifted_names[which]; + + if (this->sel_x == x && this->sel_y == y) + highlight_background(where, Gui::gui->small_font, + Gui::gui->bg_left, Gui::gui->bg_middle, Gui::gui->bg_right, + x * key_w + x_base, y * key_h + y_base, + this->font->getWidth(what), h); + this->font->draw(where, what, + x * key_w + x_base, y * key_h + y_base, w, h); + } + } +} + +void VirtualKeyboard::selectNext(int dx, int dy) +{ + int next_x = (this->sel_x + dx) % KEY_COLS; + int next_y = (this->sel_y + dy) % KEY_ROWS; + virtkey_t key; + + if (next_x < 0) + next_x = KEY_COLS + next_x; + if (next_y < 0) + next_y = KEY_ROWS + next_y; + this->sel_x = next_x; + this->sel_y = next_y; + + key = keys[ next_y * KEY_COLS + next_x ]; + + /* Skip the empty spots */ + if (key.name == NULL) + { + if (dy != 0) /* Look left */ + this->selectNext(-1, 0); + else + this->selectNext(dx, dy); + } +} + +void VirtualKeyboard::toggleShift() +{ + this->shift_on = !this->shift_on; +} + +const char *VirtualKeyboard::keycodeToString(int kc) +{ + bool shifted = kc & 0x80; + int kc_raw = kc & ~0x80; + const char *out = "Unknown"; + + if (kc < 0) + return "None"; + + /* Just loop through all of them */ + for (int i = 0; i < KEY_COLS * KEY_ROWS; i++) + { + virtkey_t key = keys[i]; + + if (key.kc == kc_raw && key.name != NULL) + { + out = key.name; + + if (shifted && shifted_names[i]) + out = shifted_names[i]; + break; + } + } + + return out; +} + +int VirtualKeyboard::charToKeycode(char c) +{ + for (int i = 0; i < KEY_COLS * KEY_ROWS; i++) + { + virtkey_t key = keys[i]; + + if (key.name != NULL) + { + if (strlen(key.name) == 1) + { + if (key.name[0] == c) + return key.kc; + if (shifted_names[i] && strlen(shifted_names[i]) == 1 && + shifted_names[i][0] == c) + return key.kc | 0x80; + } + + /* OK, ugly special cases, but these are pretty important */ + if (c == ' ' && strcmp(key.name, "space") == 0) + return key.kc; + if (c == '\n' && strcmp(key.name, "Ret") == 0) + return key.kc; + } + } + + return -1; +} + +virtkey_t VirtualKeyboard::eventToVirtkey(event_t ev) +{ + char c = (char)ev; + + for (int i = 0; i < KEY_COLS * KEY_ROWS; i++) + { + virtkey_t key = keys[i]; + + if (key.name != NULL) + { + if (strlen(key.name) == 1) + { + if (key.name[0] == c) + return key; + if (shifted_names[i] && strlen(shifted_names[i]) == 1 && + shifted_names[i][0] == c) + return key; + } + + /* OK, ugly special cases, but these are pretty important */ + if ( (c == ' ' && strcmp(key.name, "space") == 0) || + (c == '\n' && strcmp(key.name, "Ret") == 0) ) + return key; + } + } + + return INVALID_VIRTKEY; +} + +int VirtualKeyboard::stringToKeycode(const char *str) +{ + for (int i = 0; i < KEY_COLS * KEY_ROWS; i++) + { + virtkey_t key = keys[i]; + + if (key.name != NULL) + { + if (strcmp(key.name, str) == 0) + return key.kc; + } + } + + return 0; +} + +const char VirtualKeyboard::keycodeToChar(int kc) +{ + const char *s = this->keycodeToString(kc); + + if (strcmp(s, "space") == 0) + return ' '; + if (strcmp(s, "Ret") == 0) + return '\n'; + if (strcmp(s, "Del") == 0) + return '\b'; + + /* NULL is never, ever returned */ + return s[0]; +} + +void VirtualKeyboard::activate() +{ + Gui::gui->kbd = this; + this->is_active = true; + memset(this->buf, 0, sizeof(struct virtkey) * this->buf_len); + this->buf_head = 0; + + this->kbd_only_input = false; +} + + +void VirtualKeyboard::runLogic() +{ + event_t ev; + virtkey_t ev_key; + + if (!this->is_active) + return; + + ev = this->popEvent(); + if (ev == EVENT_NONE) + return; + + /* Something was typed on the keyboard */ + ev_key = this->eventToVirtkey(ev); + if ( !IS_INVALID_VIRTKEY(&ev_key) ) { + this->pushKey(&ev_key); + } + + if (ev & KEY_UP) + this->selectNext(0, -1); + else if (ev & KEY_DOWN) + this->selectNext(0, 1); + else if (ev & KEY_LEFT) + this->selectNext(-1, 0); + else if (ev & KEY_RIGHT) + this->selectNext(1, 0); + else if (ev & KEY_ESCAPE) + this->deactivate(); + else if (ev & KEY_SELECT) + { + virtkey_t *key = &keys[ this->sel_y * KEY_COLS + this->sel_x ]; + + if (!key) + return; + + if (key->is_shift == true) + this->toggleShift(); + else if (key->is_done) /* We're done! */ + this->done(); + else if (strcmp(key->name, "Del") == 0) + { + if (this->buf_head > 1) + { + this->buf[this->buf_head - 1] = (struct virtkey){NULL, -1, false, false}; + this->buf_head -= 2; + } + } + else + this->pushKey(key); + } +} + +void VirtualKeyboard::pushKey(struct virtkey *vk) +{ + int n_listeners = sizeof(this->listeners) / sizeof(*this->listeners); + + /* Add to buf */ + this->buf[this->buf_head] = *vk; + + this->buf_head++; + if (this->buf_head >= this->buf_len - 1) + this->buf_head = 0; /* OK, not good, but well... */ + for (int i = 0; i < n_listeners; i++) + { + if (this->listeners[i]) + ((KeyboardListener*)this->listeners[i])->keyCallback(this->shift_on, + vk->name); + } +} + +void VirtualKeyboard::deactivate() +{ + this->is_active = false; + this->flushListeners(); + Gui::gui->kbd = NULL; +} + +void VirtualKeyboard::done() +{ + int n_listeners = sizeof(this->listeners) / sizeof(*this->listeners); + char *buf = (char *)xmalloc(this->buf_head + 1); + + for (unsigned i = 0; i < this->buf_head; i++) + buf[i] = this->keycodeToChar(this->buf[i].kc); + + for (int i = 0; i < n_listeners; i++) + { + if (this->listeners[i]) + ((KeyboardListener*)this->listeners[i])->stringCallback(buf); + } + free(buf); + this->deactivate(); +} + +void VirtualKeyboard::draw(SDL_Surface *where) +{ + this->draw(where, 20, 240, 600, 240); +} + +void VirtualKeyboard::updateTheme() +{ + this->setFont(Gui::gui->small_font); +} + +void VirtualKeyboard::pushEvent(SDL_Event *ev) +{ + switch(ev->type) + { + case SDL_KEYDOWN: + switch (ev->key.keysym.sym) + { + case SDLK_UP: + case SDLK_DOWN: + case SDLK_LEFT: + case SDLK_RIGHT: + case SDLK_PAGEDOWN: + case SDLK_PAGEUP: + case SDLK_HOME: + case SDLK_ESCAPE: + /* Handle via the standard widget implementation (except for space) */ + this->kbd_only_input = false; + Widget::pushEvent(ev); + return; + case SDLK_RETURN: + if (this->kbd_only_input) + this->done(); + else + Widget::pushEvent(ev); + return; + case SDLK_SPACE ... SDLK_z: + Widget::pushEvent((event_t)(ev->key.keysym.sym)); + this->kbd_only_input = true; + default: + break; + } + default: + break; + + } +} + +/* The singleton */ +VirtualKeyboard *VirtualKeyboard::kbd; + + +KeyboardListener::~KeyboardListener() +{ + VirtualKeyboard::kbd->unregisterListener(this); +} diff --git a/Src/gui/virtual_keyboard.hh b/Src/gui/virtual_keyboard.hh new file mode 100644 index 0000000..df16936 --- /dev/null +++ b/Src/gui/virtual_keyboard.hh @@ -0,0 +1,100 @@ +/********************************************************************* + * + * Copyright (C) 2009, Simon Kagstrom + * + * Filename: VirtualKeyboard.c + * Author: Simon Kagstrom + * Description: A virtual keyboard + * + * $Id$ + * + ********************************************************************/ +#ifndef __VIRTUAL_KEYBORD_HH__ +#define __VIRTUAL_KEYBORD_HH__ + +#include + +#include "widget.hh" +#include "gui_view.hh" +#include "font.hh" +#include "listener.hh" + +struct virtkey; + +class KeyboardListener : public Listener +{ +public: + ~KeyboardListener(); + + /* Each key is a string */ + virtual void keyCallback(bool shift, const char *str) + { + } + + virtual void stringCallback(const char *str) + { + } +}; + +class VirtualKeyboard : public GuiView, public ListenerManager +{ +public: + VirtualKeyboard(Font *font); + ~VirtualKeyboard(); + + /* Conversions */ + const char *keycodeToString(int kc); + const char keycodeToChar(int kc); + int charToKeycode(char c); + int stringToKeycode(const char *str); + struct virtkey eventToVirtkey(event_t ev); + + void activate(); + + void setFont(Font *font) + { + this->font = font; + } + + void deactivate(); + + bool isActive() + { + return this->is_active; + } + + virtual void updateTheme(); + + void draw(SDL_Surface *where); + + void runLogic(); + + void draw(SDL_Surface *where, int x, int y, int w, int h); + + void pushEvent(SDL_Event *ev); + + /* Singleton object */ + static VirtualKeyboard *kbd; +private: + void selectNext(int dx, int dy); + + void toggleShift(); + + void pushKey(struct virtkey *vk); + + void done(); + + Font *font; + int sel_x; + int sel_y; + bool shift_on; + + bool kbd_only_input; + + bool is_active; + struct virtkey *buf; + unsigned buf_head; + size_t buf_len; +}; + +#endif /* __VIRTUAL_KEYBORD_HH__ */ diff --git a/Src/gui/widget.cpp b/Src/gui/widget.cpp new file mode 100644 index 0000000..1a19833 --- /dev/null +++ b/Src/gui/widget.cpp @@ -0,0 +1,76 @@ +#include "widget.hh" + +Widget::Widget() +{ + memset(this->event_stack, 0, sizeof(this->event_stack)); + this->ev_head = this->ev_tail = 0; +} + +event_t Widget::popEvent() +{ + event_t out; + + if (this->ev_head == this->ev_tail) + return EVENT_NONE; + out = this->event_stack[this->ev_tail]; + this->ev_tail = (this->ev_tail + 1) % 8; + + return out; +} + +void Widget::pushEvent(event_t ev) +{ + /* Push... */ + this->event_stack[this->ev_head] = ev; + + /* ... and update */ + this->ev_head = (this->ev_head + 1) % 8; + if (this->ev_head == this->ev_tail) + this->ev_tail = (this->ev_tail + 1) % 8; +} + +void Widget::pushEvent(SDL_Event *ev) +{ + switch(ev->type) + { + case SDL_KEYDOWN: + switch (ev->key.keysym.sym) + { + case SDLK_UP: + this->pushEvent(KEY_UP); + break; + case SDLK_DOWN: + this->pushEvent(KEY_DOWN); + break; + case SDLK_LEFT: + this->pushEvent(KEY_LEFT); + break; + case SDLK_RIGHT: + this->pushEvent(KEY_RIGHT); + break; + case SDLK_PAGEDOWN: + this->pushEvent(KEY_PAGEDOWN); + break; + case SDLK_PAGEUP: + this->pushEvent(KEY_PAGEUP); + break; + case SDLK_RETURN: + case SDLK_SPACE: + this->pushEvent(KEY_SELECT); + break; + case SDLK_HOME: + case SDLK_ESCAPE: + this->pushEvent(KEY_ESCAPE); + break; + default: + break; + } + default: + break; + + } +} + +void Widget::draw(SDL_Surface *where, int x, int y, int w, int h) +{ +} diff --git a/Src/gui/widget.hh b/Src/gui/widget.hh new file mode 100644 index 0000000..a2b60db --- /dev/null +++ b/Src/gui/widget.hh @@ -0,0 +1,42 @@ +#ifndef WIDGET_HH +#define WIDGET_HH + +#include + +enum key_event { + EVENT_NONE = (1 << 8), + KEY_UP = (1 << 9), + KEY_DOWN = (1 << 10), + KEY_LEFT = (1 << 11), + KEY_RIGHT = (1 << 12), + KEY_SELECT = (1 << 13), + KEY_ESCAPE = (1 << 14), + KEY_PAGEDOWN = (1 << 15), + KEY_PAGEUP = (1 << 16), + KEY_HELP = (1 << 17), +}; + +typedef enum key_event event_t; + +class Widget +{ +public: + Widget(); + + virtual void pushEvent(event_t ev); + + virtual void pushEvent(SDL_Event *ev); + + virtual void runLogic() = 0; + + virtual void draw(SDL_Surface *where, + int x, int y, int w, int h); + + virtual event_t popEvent(); + +protected: + int ev_head, ev_tail; + event_t event_stack[8]; +}; + +#endif diff --git a/Src/main_wii.h b/Src/main_wii.h index e2aed7d..4b6f2dc 100644 --- a/Src/main_wii.h +++ b/Src/main_wii.h @@ -11,8 +11,6 @@ #include #include -#include "menu.h" - extern int init_graphics(void); /* diff --git a/Src/main_x.h b/Src/main_x.h index e5b0b0d..06bc703 100644 --- a/Src/main_x.h +++ b/Src/main_x.h @@ -31,10 +31,10 @@ extern "C" int main(int argc, char *argv[]); #endif #if defined(HAVE_SDL) #include +#include +#include "gui/gui.hh" #endif -#include "menu.h" - extern int init_graphics(void); @@ -75,7 +75,8 @@ int main(int argc, char **argv) fprintf(stderr, "Unable to init TTF: %s\n", TTF_GetError() ); return 1; } - menu_init(); + Gui::gui = new Gui(); + Gui::gui->setTheme("default"); #endif if (!init_graphics()) return 1;