From 93249b29bff7f1e4a662fa054c6ae9f6e6a31b9f Mon Sep 17 00:00:00 2001 From: "fabio.olimpieri" Date: Wed, 25 Apr 2012 21:13:57 +0000 Subject: [PATCH] Added extended mode key, new sdl menus controlled by joysticks --- FreeMono.ttf | Bin 0 -> 134512 bytes Makefile | 3 +- fbzx.pnproj | 2 +- fbzx.pnps | 2 +- src/computer.c | 15 +- src/computer.h | 3 + src/emulator.c | 12 +- src/gui_sdl.c | 679 ++++++++++++++++++++++++++++++++++ src/menu_sdl.c | 976 +++++++++++++++++++++++++++++++++++++++++++++++++ src/menu_sdl.h | 62 ++++ 10 files changed, 1740 insertions(+), 14 deletions(-) create mode 100644 FreeMono.ttf create mode 100644 src/gui_sdl.c create mode 100644 src/menu_sdl.c create mode 100644 src/menu_sdl.h diff --git a/FreeMono.ttf b/FreeMono.ttf new file mode 100644 index 0000000000000000000000000000000000000000..517ea95be0786e316e38bd88da112d4d23e45a21 GIT binary patch literal 134512 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 literal 0 HcmV?d00001 diff --git a/Makefile b/Makefile index ae1b7a0..46bc458 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project #--------------------------------------------------------------------------------- -LIBS := -lasnd -lSDL_mixer -lsmpeg -lvorbisidec -lSDL_image -lpng -ljpeg -lz -lSDL -lSDL_gfx -lfreetype -lfat -lwiiuse -lbte -logc -lm -lwiikeyboard +LIBS := -lasnd -lSDL_mixer -lsmpeg -lvorbisidec -lSDL_image -lpng -ljpeg -lz -lSDL_ttf -lSDL -lSDL_gfx -lfreetype -lfat -lwiiuse -lbte -logc -lm -lwiikeyboard #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing @@ -122,6 +122,7 @@ dist: $(BUILD) cp spectrum-roms/* $@/fbzx-wii/spectrum-roms cp keymap.bmp $@/fbzx-wii/fbzx cp ZXSpectrum48k.png $@/fbzx-wii/fbzx + cp FreeMono.ttf $@/fbzx-wii/fbzx cp AMSTRAD CAPABILITIES COPYING FAQ README README.TZX VERSIONS $@/apps/fbzx-wii/doc touch $@/fbzx-wii/tapes/dummy touch $@/fbzx-wii/snapshots/dummy diff --git a/fbzx.pnproj b/fbzx.pnproj index 0414710..dd3e0d5 100644 --- a/fbzx.pnproj +++ b/fbzx.pnproj @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/fbzx.pnps b/fbzx.pnps index 7e6c7be..580ae2a 100644 --- a/fbzx.pnps +++ b/fbzx.pnps @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/computer.c b/src/computer.c index 3f60675..e707192 100644 --- a/src/computer.c +++ b/src/computer.c @@ -82,6 +82,8 @@ void computer_init () { ordenador.mode128k = 0; ordenador.joystick[0] = 1; //Kemposton ordenador.joystick[1] = 0; // Cursor + ordenador.rumble[0] = 0; + ordenador.rumble[1] = 0; ordenador.tape_readed = 0; ordenador.pause = 1; // tape stop @@ -697,7 +699,6 @@ inline void read_keyboard () { unsigned int temporal_io; SDL_Event evento,*pevento; - static int countdown; enum joystate_x {JOY_CENTER_X, JOY_LEFT, JOY_RIGHT}; enum joystate_y {JOY_CENTER_Y, JOY_UP, JOY_DOWN}; int joy_axis_x[2],joy_axis_y[2], loop; @@ -758,7 +759,7 @@ inline void read_keyboard () { joy_axis_y[loop] = SDL_JoystickGetAxis(ordenador.joystick_sdl[loop], 1); ordenador.joy_fire[loop] = SDL_JoystickGetButton(ordenador.joystick_sdl[loop], 0); //Wii button A - if (SDL_JoystickGetButton(ordenador.joystick_sdl[loop], 6)) help_menu (); //Wii button Home + if (SDL_JoystickGetButton(ordenador.joystick_sdl[loop], 6)) main_menu(); //Wii button Home if (joy_axis_x[loop] > 16384) ordenador.joy_axis_x_state[loop] = JOY_RIGHT; else if (joy_axis_x[loop] < -16384) ordenador.joy_axis_x_state[loop] = JOY_LEFT; @@ -946,8 +947,7 @@ inline void read_keyboard () { } if (ordenador.key[SDLK_SPACE]) ordenador.k15|=1; - if (ordenador.key[SDLK_RCTRL]) ordenador.k15|=2; - if (ordenador.key[SDLK_LCTRL]) ordenador.k15|=2; + if (ordenador.key[SDLK_RCTRL]||ordenador.key[SDLK_LCTRL]) ordenador.k15|=2; //Symbol shift if (ordenador.key[SDLK_m]) ordenador.k15|=4; if (ordenador.key[SDLK_n]) ordenador.k15|=8; if (ordenador.key[SDLK_b]) ordenador.k15|=16; @@ -991,8 +991,7 @@ inline void read_keyboard () { if (ordenador.key[SDLK_f]) ordenador.k9 |=8; if (ordenador.key[SDLK_g]) ordenador.k9 |=16; - if (ordenador.key[SDLK_RSHIFT]) ordenador.k8 |=1; - if (ordenador.key[SDLK_LSHIFT]) ordenador.k8 |=1; + if (ordenador.key[SDLK_RSHIFT]||ordenador.key[SDLK_LSHIFT]) ordenador.k8 |=1; //Caps shift if (ordenador.key[SDLK_z]) ordenador.k8 |=2; if (ordenador.key[SDLK_x]) ordenador.k8 |=4; if (ordenador.key[SDLK_c]) ordenador.k8 |=8; @@ -1001,8 +1000,10 @@ inline void read_keyboard () { if (ordenador.key[SDLK_UP]) {ordenador.k12 |=8;ordenador.k8|=1;} if (ordenador.key[SDLK_DOWN]) {ordenador.k12 |=16;ordenador.k8|=1;} if (ordenador.key[SDLK_LEFT]) {ordenador.k11 |=16;ordenador.k8|=1;} - if (ordenador.key[SDLK_RIGHT]) {ordenador.k12 |=4;ordenador.k8|=1;} + if (ordenador.key[SDLK_RIGHT]) {ordenador.k12 |=4;ordenador.k8|=1;} + if (ordenador.key[SDLK_TAB]) {ordenador.k15|=2;ordenador.k8|=1;} //Extended mode + ordenador.s8 = (ordenador.s8 & 0xE0) | (ordenador.k8 ^ 0x1F); ordenador.s9 = (ordenador.s9 & 0xE0) | (ordenador.k9 ^ 0x1F); ordenador.s10 = (ordenador.s10 & 0xE0)| (ordenador.k10 ^ 0x1F); diff --git a/src/computer.h b/src/computer.h index 750f10a..2ce3455 100644 --- a/src/computer.h +++ b/src/computer.h @@ -31,6 +31,8 @@ enum tapmodes {TAP_GUIDE, TAP_DATA, TAP_PAUSE, TAP_TRASH, TAP_STOP, TAP_PAUSE2, TZX_SEQ_PULSES, TAP_FINAL_BIT, TAP_PAUSE3}; enum taptypes {TAP_TAP, TAP_TZX}; +int countdown; + struct computer { unsigned int temporal_io; @@ -200,6 +202,7 @@ struct computer { unsigned char joy_axis_x_state[2]; unsigned char joy_axis_y_state[2]; unsigned char joy_fire[2]; + unsigned char rumble[2]; }; void computer_init(); diff --git a/src/emulator.c b/src/emulator.c index 08cd7db..e549e40 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -64,10 +64,10 @@ char path_mdrs[2049]; unsigned int colors[80]; unsigned int jump_frames,curr_frames; char *filenames[5]; +static SDL_Surface *image; int load_zxspectrum_picture() { -SDL_Surface *image; image=IMG_Load("/fbzx-wii/fbzx/ZXSpectrum48k.png"); @@ -707,8 +707,12 @@ int main(int argc,char *argv[]) { ordenador.screenbuffer=ordenador.screen->pixels; ordenador.screen_width=ordenador.screen->w; + //Init SDL Menu + + menu_init(ordenador.screen); + //Load the splash screen - if (load_zxspectrum_picture()) sleep(3); + if (load_zxspectrum_picture()) {sleep(1); SDL_FreeSurface (image);} // assign initial values for PATH variables @@ -775,7 +779,7 @@ int main(int argc,char *argv[]) { load_main_game(gamefile); printf("Modo: %d\n",ordenador.mode128k); - sprintf(ordenador.osd_text,"Press F1 for help"); + sprintf(ordenador.osd_text,"Press Home for menu"); ordenador.osd_time=200; printf("BPP: %d\n",ordenador.bpp); @@ -841,7 +845,7 @@ int main(int argc,char *argv[]) { } } - save_config(&ordenador); + //save_config(&ordenador); #ifdef GEKKO fatUnmount(0); diff --git a/src/gui_sdl.c b/src/gui_sdl.c new file mode 100644 index 0000000..ada454d --- /dev/null +++ b/src/gui_sdl.c @@ -0,0 +1,679 @@ + /* + * UAE - The Un*x Amiga Emulator + * + * Interface to the Tcl/Tk GUI + * + * Copyright 1996 Bernd Schmidt + */ + +#include +#include + +#include "menu_sdl.h" +#include "emulator.h" +//#include "VirtualKeyboard.h" per ora + +#define ID_BUTTON_OFFSET 0 +#define ID_AXIS_OFFSET 32 + +//extern int usbismount, smbismount; per ora + +#ifdef DEBUG +extern FILE *fdebug; +#define printf(...) fprintf(fdebug,__VA_ARGS__) +#else + #ifdef GEKKO + #define printf(...) + #endif +#endif + +extern int countdown; + + +static const char *main_menu_messages[] = { + /*00*/ "Tape", + /*01*/ "^|Insert|Load|Play|Stop|Rewind|Create|Delete", + /*02*/ "Snapshot", + /*03*/ "^|Load|Save|Delete", + /*04*/ "#1---------------------------------------------", + /*05*/ "Wiimote configuration", + /*06*/ "^|Wiimote1|Wiimote2", + /*07*/ "Emulation settings", + /*08*/ "Microdrive", + /*09*/ "Tools", + /*10*/ "Save confs", + /*11*/ "Reset", + /*12*/ "Help", + /*13*/ "Quit", + NULL +}; + +static const char *emulation_messages[] = { + /*00*/ "Emulated machine", + /*01*/ "^|48k_2|48K_3|128k|+2|+2A/+3|128K_Sp", + /*02*/ "Volume", + /*03*/ "^|0%|25%|50%|75%|100%", + /*04*/ "Tap fast speed", + /*05*/ "^|on|off", + /*06*/ "Turbo mode", + /*07*/ "^|on|off", + /*08*/ "Double scan", + /*09*/ "^|on|off", + /*10*/ "TV mode", + /*11*/ "^|Color|B&W", + /*12*/ "AY-3-8912 Emulation", + /*13*/ "^|on|off", + NULL +}; + +static const char *input_messages[] = { + /*00*/ "Joystick type", + /*01*/ "^|Cursor|Kempston|Sinclair1|Sinclair2", + /*02*/ " ", + /*03*/ "Bind key to Wiimote", + /*04*/ "^|1|2|-", + /*05*/ " ", + /*06*/ "Bind key to Nunchuk", + /*07*/ "^|Z|C", + /*08*/ " ", + /*09*/ "Bind key to Classic", + /*10*/ "^|a|b|x|y|L|R|Zl|Zr|-", + /*11*/ " ", + /*12*/ "Rumble", + /*13*/ "^|On|Off", + NULL, +}; + +static const char *microdrive_messages[] = { + /*00*/ "Select microdrive", + /*01*/ " ", + /*02*/ "Create microdrive file", + /*03*/ " ", + /*04*/ "Interface I", + /*05*/ "^|on|off", + /*06*/ " ", + /*07*/ "Write protection", + /*08*/ "^|on|off", + NULL +}; + +static const char *tools_messages[] = { + /*00*/ "Show keyboard", + /*01*/ " ", + /*02*/ "Save SCR", + /*03*/ " ", + /*04*/ "Load SCR", + /*05*/ " ", + /*06*/ "Insert poke", + NULL +}; + +static const char *help_messages[] = { + /*00*/ "#2HOME enters the menu system, where arrow keys", + /*01*/ "#2and nunchuck are used to navigate up and down.", + /*02*/ "#2You can bind keyboard keys to the wiimote", + /*03*/ "#2buttons in the 'Wiimote' menu and", + /*04*/ "#2change emulation options in the Settings menu.", + /*05*/ "#2 ", + /*06*/ "#2 ", + /*07*/ "#2 ", + /*08*/ "#2 ", + /*09*/ "#2 ", + /*10*/ "#2 ", + /*11*/ "#2More information is available on the wiki:", + /*12*/ "#2 http://wiibrew.org/wiki/FBZX_Wii", + /*13*/ "#2 ", + /*14*/ "OK", + NULL, +}; + +static void insert_tape() +{ + unsigned char char_id[11]; + int retorno, retval; + + // Maybe should go after the first control?? + if(ordenador.tap_file!=NULL) + rewind_tape(ordenador.tap_file,1); + + ordenador.tape_current_bit=0; + ordenador.tape_current_mode=TAP_TRASH; + + const char *filename = menu_select_file(path_taps, ordenador.current_tap, 0); + + if (filename==NULL) // Aborted + return; + + if (strcmp(filename, "None") == 0) //TO FIX IT + { + ordenador.current_tap[0] = '\0'; + free((void *)filename); + return; + } + + if (!(ext_matches(filename, ".tap")|ext_matches(filename, ".TAP")|ext_matches(filename, ".tzx")| + ext_matches(filename, ".TZX"))) {free((void *)filename); return;} + + + if(ordenador.tap_file!=NULL) { + fclose(ordenador.tap_file); + } + + ordenador.tap_file=fopen(filename,"r+"); // read and write + + ordenador.tape_write = 0; // by default, can't record + + if(ordenador.tap_file==NULL) + retorno=-1; + else + retorno=0; + + strcpy(ordenador.current_tap,filename); + + free((void *)filename); + + switch(retorno) { + case 0: // all right + break; + case -1: + msgInfo("Error: Can't load that file",3000,NULL); + ordenador.current_tap[0]=0; + return; + break; + } + + retval=fread(char_id,10,1,ordenador.tap_file); // read the (maybe) TZX header + if((!strncmp(char_id,"ZXTape!",7)) && (char_id[7]==0x1A)&&(char_id[8]==1)) { + ordenador.tape_file_type = TAP_TZX; + rewind_tape(ordenador.tap_file,1); + } else { + ordenador.tape_file_type = TAP_TAP; + rewind_tape(ordenador.tap_file,1); + } +} + +static void delete_tape() +{ + const char *filename = menu_select_file(path_taps, NULL, -1); + + if (filename==NULL) // Aborted + return; + + if (strcmp(filename, "None") == 0) + { + free((void *)filename); + return; + } + + if (ext_matches(filename, ".tap")|ext_matches(filename, ".TAP")|ext_matches(filename, ".tzx")| + ext_matches(filename, ".TZX")) unlink(filename); + + free((void *)filename); +} + + +static void manage_tape(int which) +{ + switch (which) + { + case 0: //Insert + insert_tape(); + break; + case 1: //Emulate load "" + ordenador.kbd_buffer_pointer=6; + countdown=5; + break; + case 2: //Play + if ((ordenador.tape_fast_load == 0) || (ordenador.tape_file_type==TAP_TZX)) + ordenador.pause = 0; + break; + case 3: //Stop + if ((ordenador.tape_fast_load == 0) || (ordenador.tape_file_type==TAP_TZX)) + ordenador.pause = 1; + break; + case 4: //Rewind + ordenador.pause=1; + if(ordenador.tap_file!=NULL) { + ordenador.tape_current_mode=TAP_TRASH; + rewind_tape(ordenador.tap_file,1); + } + msgInfo("Tape rewinded",3000,NULL); + break; + case 5: //Create + // Create tape + break; + case 6: //Delete + delete_tape(); + break; + default: + break; + } +} + +static unsigned int get_machine_model(void) +{ + return ordenador.mode128k + (ordenador.issue==3); +} + +static void set_machine_model(int which) +{ + switch (which) + { + case 0: //48k issue2 + ordenador.issue=2; + ordenador.mode128k=0; + ordenador.ay_emul=0; + break; + case 1: //48k issue3 + ordenador.issue=3; + ordenador.mode128k=0; + ordenador.ay_emul=0; + break; + case 2: //128k + ordenador.issue=3; + ordenador.mode128k=1; + ordenador.ay_emul=1; + break; + case 3: //Amstrad +2 + ordenador.issue=3; + ordenador.mode128k=2; + ordenador.ay_emul=1; + break; + case 4: //Amstrad +2A/+3 + ordenador.issue=3; + ordenador.mode128k=3; + ordenador.ay_emul=1; + ordenador.mdr_active=0; + break; + case 5: //128K Spanish + ordenador.issue=3; + ordenador.mode128k=4; + ordenador.ay_emul=1; + break; + + } +} + +static void emulation_settings(void) +{ + unsigned int submenus[7],submenus_old[7]; + int opt, i; + + memset(submenus, 0, sizeof(submenus)); + + submenus[0] = get_machine_model(); + submenus[1] = (unsigned int) (ordenador.volume/16); + submenus[2] = !ordenador.tape_fast_load; + submenus[3] = !ordenador.turbo; + submenus[4] = !ordenador.dblscan; + submenus[5] = ordenador.bw; + submenus[6] = !ordenador.ay_emul; + + for (i=0; i<7; i++) submenus_old[i] = submenus[i]; + + opt = menu_select_title("Emulation settings menu", + emulation_messages, submenus); + if (opt < 0) + return; + + set_machine_model(submenus[0]); + if (submenus[0] != submenus_old[0]) ResetComputer(); else + ordenador.ay_emul = !submenus[6]; + + ordenador.volume = submenus[1]*16; + ordenador.tape_fast_load = !submenus[2]; + ordenador.turbo = !submenus[3]; + + if(ordenador.turbo){ + ordenador.tst_sample=12000000/ordenador.freq; //5,0 MHz max emulation speed for wii at full frames + jump_frames=3; + } else { + ordenador.tst_sample=3500000/ordenador.freq; + jump_frames=0; + } + + ordenador.dblscan = !submenus[4]; + ordenador.bw = submenus[5]; + if (submenus[5]!=submenus_old[5]) computer_set_palete(); + +} + +static void setup_joystick(int joy, const char *key, int sdl_key) +{ + /* + if (!strcmp(key, "None")) + { + changed_prefs.joystick_settings[1][joy].eventid[ID_BUTTON_OFFSET + sdl_key][0] = 0; + } + else + insert_keyboard_map(key, "input.1.joystick.%d.button.%d", joy, sdl_key); + */ +} + +static void input_options(int joy) +{ + const int wiimote_to_sdl[] = {2, 3, 4, 5}; + const int nunchuk_to_sdl[] = {7, 8}; + const int classic_to_sdl[] = {9, 10, 11, 12, 13, 14, 15, 16, 17, 18}; + int sdl_key = 1; + const char *key; + unsigned int submenus[5]; + int opt; + + //struct virtkey *virtualkey; + + memset(submenus, 0, sizeof(submenus)); + + submenus[0] = ordenador.joystick[joy]; + submenus[4] = !ordenador.rumble[joy]; + + opt = menu_select_title("Input menu", + input_messages, submenus); + if (opt < 0) + return; + + ordenador.joystick[joy] = submenus[0]; + ordenador.rumble[joy] = !submenus[4]; + + /* + virtualkey = virtkbd_get_key(); + if (virtualkey == NULL) + return; + key = virtualkey->ev_name; + */ + + switch(opt) + { + case 3: // wiimote + sdl_key = wiimote_to_sdl[submenus[1]]; break; + case 6: // nunchuk + sdl_key = nunchuk_to_sdl[submenus[2]]; break; + case 9: // classic + sdl_key = classic_to_sdl[submenus[3]]; break; + default: + break; + } + + setup_joystick(joy, key, sdl_key); + +} + +static void microdrive() +{ + + unsigned int submenus[2], submenus_old[2]; + int opt,retval ; + + memset(submenus, 0, sizeof(submenus)); + + submenus[0] = !ordenador.mdr_active; + submenus[1] = !ordenador.mdr_cartridge[137922]; + + submenus_old[0] = submenus[0]; + submenus_old[1] = submenus[1]; + + opt = menu_select_title("Microdrive menu", + microdrive_messages, submenus); + if (opt < 0) + return; + + ordenador.mdr_active = !submenus[0]; + + + if (submenus[0]!=submenus_old[0]) ResetComputer(); + if (submenus[1]!=submenus_old[1]) + {if(ordenador.mdr_cartridge[137922]) + ordenador.mdr_cartridge[137922]=0; + else + ordenador.mdr_cartridge[137922]=1; + ordenador.mdr_file=fopen(ordenador.mdr_current_mdr,"wb"); // create for write + if(ordenador.mdr_file!=NULL) { + retval=fwrite(ordenador.mdr_cartridge,137923,1,ordenador.mdr_file); // save cartridge + fclose(ordenador.mdr_file); + ordenador.mdr_file=NULL; + ordenador.mdr_modified=0; + } + } + + switch(opt) + { + case 0: // Select microdrive + //Select microdrive ; + break; + case 2: // Create microdrive file + // Create microdrive file ; + break; + default: + break; + } +} +void show_keyboard_layout() { + + FILE *fichero; + int bucle1,bucle2,retval; + unsigned char *buffer,valor; + + buffer=screen->pixels; + + fichero=myfopen("fbzx/keymap.bmp","r"); + if (fichero==NULL) { + msgInfo("Keymap picture not found",3000,NULL); + return; + } + + for (bucle1=0;bucle1<344;bucle1++) + for(bucle2=0;bucle2<640;bucle2++) { + retval=fscanf(fichero,"%c",&valor); + paint_one_pixel((unsigned char *)(colors+valor),buffer); + buffer+=ordenador.bpp; + } + SDL_Flip(ordenador.screen); + menu_wait_key_press(); +} + +static void tools() +{ + int opt ; + + opt = menu_select_title("Tools menu", + tools_messages, NULL); + if (opt < 0) + return; + + switch(opt) + { + case 0: // Show keyboard + show_keyboard_layout(); + break; + case 2: // Save SCR + // Save SCR ; + break; + case 4: // Load SCR + //Load SCR ; + break; + case 6: // Insert poke + // Insert poke ; + break; + default: + break; + } +} + + +/* + +static void set_Port(int which) +{ + switch (which) + { + case PORT_SD: + prefs_set_attr ("floppy_path", strdup_path_expand (TARGET_FLOPPY_PATH)); + changed_prefs.Port = which; + currprefs.Port = changed_prefs.Port; + break; + case PORT_USB: + if (usbismount) { + prefs_set_attr ("floppy_path", strdup_path_expand (TARGET_USB_PATH)); + changed_prefs.Port = which; + currprefs.Port = changed_prefs.Port;} + else + msgInfo("USB is not mounted",3000,NULL); + break; + case PORT_SMB: + if (smbismount) { + prefs_set_attr ("floppy_path", strdup_path_expand (TARGET_SMB_PATH)); + changed_prefs.Port = which; + currprefs.Port = changed_prefs.Port;} + else + msgInfo("SMB is not mounted",3000,NULL); + break; + default: + break; + } +} + +static void virtual_keyboard(void) +{ + int key_code; + + virtkey_t *key =virtkbd_get_key(); + if (key) {key_code = key->sdl_code;} else return; + + SDL_Event event_key; + + event_key.type=SDL_KEYDOWN; + event_key.key.keysym.sym=key_code; + SDL_PushEvent(&event_key); + DEBUG_LOG ("Push Event: keycode %d %s\n", key_code, "SDL_KEYDOWN"); + + event_key.type=SDL_KEYUP; + SDL_PushEvent(&event_key); + DEBUG_LOG ("Push Event: keycode %d %s\n", key_code, "SDL_KEYUP"); + +} + +*/ + +static void save_load_snapshot(int which) +{ + const char *dir = path_snaps; + const char *tape = ordenador.current_tap; + char db[256]; + char fb[81]; + int retorno; + + // Name (for saves) - TO CHECK + if (tape && strrchr(tape, '/')) + strncpy(fb, strrchr(tape, '/') + 1, 80); + else + strcpy(fb, "unknown"); + + switch(which) + { + case 2: + case 0: // Load or delete file + { + const char *filename = menu_select_file(dir, NULL,-1); + + if (!filename) + return; + + if (ext_matches(filename, ".z80")|ext_matches(filename, ".Z80")| + ext_matches(filename, ".sna")|ext_matches(filename, ".SNA")) + { + if (which == 0) // Load snapshot file + { + retorno=load_z80(filename); + + switch(retorno) { + case 0: // all right + break; + case -1: + msgInfo("Error: Can't load that file",3000,NULL); + break; + case -2: + case -3: + msgInfo("Error: unsuported snap file",3000,NULL); + break; + } + } + else // Delete snashot file + unlink(filename); + } + free((void*)filename); + } break; + case 1: // Save snapshot file + snprintf(db, 255, "%s/%s.z80", dir, fb); + retorno=save_z80(db); + msgInfo("State saved",3000,NULL); + break; + default: + break; + } +} + + +static void help(void) +{ + menu_select_title("FBZX-WII help", + help_messages, NULL); +} + +void main_menu() +{ + int submenus[3]; + int opt; + + memset(submenus, 0, sizeof(submenus)); + + do + { + opt = menu_select_title("Main menu", main_menu_messages, submenus); + if (opt < 0) + break; + + switch(opt) + { + case 0: + manage_tape(submenus[0]); + break; + case 2: + save_load_snapshot(submenus[1]); + break; + case 5: + input_options(submenus[2]); + break; + case 7: + emulation_settings(); + break; + case 8: + microdrive(); + break; + case 9: + tools(); + break; + case 10: + save_config(&ordenador); + msgInfo("Configurations saved",3000,NULL); + break; + case 11: + ResetComputer (); + ordenador.pause = 1; + if (ordenador.tap_file != NULL) { + ordenador.tape_current_mode = TAP_TRASH; + rewind_tape (ordenador.tap_file,1); + } + break; + case 12: + help(); + break; + case 13: + if (msgYesNo("Are you sure to quit?", 0, FULL_DISPLAY_X /2-138, FULL_DISPLAY_Y /2-48)) + {salir = 0;} + break; + default: + break; + } + } while (opt == 5 || opt == 7 || opt == 8 || opt == 9 || opt == 12); + +} diff --git a/src/menu_sdl.c b/src/menu_sdl.c new file mode 100644 index 0000000..4b18f36 --- /dev/null +++ b/src/menu_sdl.c @@ -0,0 +1,976 @@ +/********************************************************************* +* +* Copyright (C) 2004,2008, Simon Kagstrom +* +* Filename: menu.c +* Author: Simon Kagstrom +* Description: Code for menus (originally for Mophun) +* +* $Id$ +* +********************************************************************/ +#include +#include +#include +#include +#include +#include +#include + + +#include "menu_sdl.h" +#include "emulator.h" //Necessary to use ordenador.joystick_number and ordenador.joystick_sdl +//#include "VirtualKeyboard.h" + + + +typedef struct +{ + int n_entries; + int index; + int sel; +} submenu_t; + +typedef struct +{ + char title[256]; + const char **pp_msgs; + TTF_Font *p_font; + int x1,y1; + int x2,y2; + int text_w; + int text_h; + + int n_submenus; + submenu_t *p_submenus; + + int cur_sel; /* Main selection */ + int start_entry_visible; + int n_entries; +} menu_t; + +static SDL_Surface *real_screen; + +#define IS_SUBMENU(p_msg) ( (p_msg)[0] == '^' ) +#define IS_TEXT(p_msg) ( (p_msg)[0] == '#' || (p_msg)[0] == ' ' ) +#define IS_MARKER(p_msg) ( (p_msg)[0] == '@' ) + +static int is_inited = 0; +static TTF_Font *menu_font16, *menu_font20; +#if defined(GEKKO) +#define FONT_PATH "/fbzx-wii/fbzx/FreeMono.ttf" +#else +#define FONT_PATH "FreeMono.ttf" +#endif + +int fh, fw; + +int msgInfo(char *text, int duration, SDL_Rect *irc) +{ + int len = strlen(text); + int X, Y; + SDL_Rect src; + SDL_Rect rc; + SDL_Rect brc; + + X = (FULL_DISPLAY_X /2) - (len / 2 + 1)*12; + Y = (FULL_DISPLAY_Y /2) - 24; + + brc.x = FULL_DISPLAY_X/2-2*12; + brc.y=Y+42; + brc.w=48; + brc.h=20; + + rc.x = X; + rc.y=Y; + rc.w=12*(len + 2); + rc.h=duration > 0 ? 48 : 80; + + src.x=rc.x+4; + src.y=rc.y+4; + src.w=rc.w; + src.h=rc.h; + + + if (irc) + { + irc->x=rc.x; + irc->y=rc.y; + irc->w=src.w; + irc->h=src.h; + } + SDL_FillRect(real_screen, &src, SDL_MapRGB(real_screen->format, 0, 96, 0)); + SDL_FillRect(real_screen, &rc, SDL_MapRGB(real_screen->format, 128, 128, 128)); + menu_print_font(real_screen, 255,255,255, X+12, Y+12, text,20); + SDL_UpdateRect(real_screen, src.x, src.y, src.w, src.h); + SDL_UpdateRect(real_screen, rc.x, rc.y, rc.w,rc.h); + if (duration > 0) + SDL_Delay(duration); + else if (duration < 0) + { + SDL_FillRect(real_screen, &brc, SDL_MapRGB(real_screen->format, 0x00, 0x80, 0x00)); + menu_print_font(real_screen, 0,0,0, FULL_DISPLAY_X/2-12, Y+42, "OK",20); + SDL_UpdateRect(real_screen, brc.x, brc.y, brc.w, brc.h); + while (!(KEY_SELECT & menu_wait_key_press())) {} + + } + + return 1; +} + +/* +void msgKill(SDL_Rect *rc) +{ + SDL_UpdateRect(real_screen, rc->x, rc->y, rc->w,rc->h); +} +*/ + +int msgYesNo(char *text, int default_opt, int x, int y) +{ + int len = strlen(text); + int X, Y; + SDL_Rect src; + SDL_Rect rc; + SDL_Rect brc; + uint32_t key; + + if (x < 0) + X = (FULL_DISPLAY_X /2) - (len / 2 + 1)*12; + else + X = x; + + if (y < 0) + Y = (FULL_DISPLAY_Y /2) - 48; + else + Y = y; + + rc.x=X; + rc.y=Y; + rc.w=12*(len + 2); + rc.h=80; + + src.x=rc.x+4; + src.y=rc.y+4; + src.w=rc.w; + src.h=rc.h; + + while (1) + { + SDL_FillRect(real_screen, &src, SDL_MapRGB(real_screen->format, 0, 96, 0)); + SDL_FillRect(real_screen, &rc, SDL_MapRGB(real_screen->format, 128, 128, 128)); + menu_print_font(real_screen, 255,255,255, X+12, Y+12, text,20); + + if (default_opt) + { + brc.x=rc.x + rc.w/2-5*12; + brc.y=rc.y+42; + brc.w=12*3; + brc.h=20; + SDL_FillRect(real_screen, &brc, SDL_MapRGB(real_screen->format, 0x00, 0x80, 0x00)); + } + else + { + brc.x=rc.x + rc.w/2+5*12-2*12-6; + brc.y=rc.y+42; + brc.w=12*3; + brc.h=20; + SDL_FillRect(real_screen, &brc, SDL_MapRGB(real_screen->format, 0x80, 0x00, 0x00)); + } + + menu_print_font(real_screen, 255,255,255, rc.x + rc.w/2-5*12, Y+42, "YES",20); + menu_print_font(real_screen, 255,255,255, rc.x + rc.w/2-5*12+8*12, Y+42, "NO",20); + + SDL_UpdateRect(real_screen, src.x, src.y, src.w, src.h); + SDL_UpdateRect(real_screen, rc.x, rc.y, rc.w,rc.h); + SDL_UpdateRect(real_screen, brc.x, brc.y, brc.w,brc.h); + + //SDL_Flip(real_screen); + key = menu_wait_key_press(); + if (key & KEY_SELECT) + { + return default_opt; + } + else if (key & KEY_ESCAPE) + { + return 0; + } + else if (key & KEY_LEFT) + { + default_opt = !default_opt; + } + else if (key & KEY_RIGHT) + { + default_opt = !default_opt; + } + } +} + + + +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 */ + 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) */ +int ext_matches(const char *name, const char *ext) +{ + int len = strlen(name); + int ext_len = strlen(ext); + + if (len <= ext_len) + return 0; + return (strcmp(name + len - ext_len, ext) == 0); +} + +static int ext_matches_list(const char *name, const char **exts) +{ + const char **p; + + for (p = exts; *p; p++) + { + if (ext_matches(name, *p)) + return 1; + } + + return 0; +} + +static const char **get_file_list(const char *base_dir) +{ + 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]; + const char *exts[] = {".tap", ".TAP", ".tzx", ".TZX", ".z80",".Z80",".sna", ".SNA", + ".mdr", ".MDR", NULL}; + 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)&&strcmp(".", de->d_name)) + { + char *p; + size_t len = strlen(de->d_name) + 4; + + 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; +} + + +static submenu_t *find_submenu(menu_t *p_menu, int index) +{ + int i; + + for (i=0; in_submenus; i++) + { + if (p_menu->p_submenus[i].index == index) + return &p_menu->p_submenus[i]; + } + + return NULL; +} + +void menu_print_font(SDL_Surface *screen, int r, int g, int b, + int x, int y, const char *msg, int font_size) +{ +#define _MAX_STRING 64 + SDL_Surface *font_surf; + SDL_Rect dst = {x, y, 0, 0}; + SDL_Color color = {r, g, b}; + char buf[255]; + unsigned int i; + + memset(buf, 0, sizeof(buf)); + strncpy(buf, msg, 254); + if (buf[0] != '|' && buf[0] != '^' && buf[0] != '.' + && buf[0] != '-' && buf[0] != ' ' && !strstr(buf, " \"")) + { + if (strlen(buf)>_MAX_STRING) + { + //buf[_MAX_STRING-3] = '.'; + //buf[_MAX_STRING-2] = '.'; + //buf[_MAX_STRING-1] = '.'; + buf[_MAX_STRING] = '\0'; + } + } + /* Fixup multi-menu option look */ + for (i = 0; i < strlen(buf) ; i++) + { + if (buf[i] == '^' || buf[i] == '|') + buf[i] = ' '; + } + + if (font_size == 16) font_surf = TTF_RenderUTF8_Blended(menu_font16, buf, color); + else font_surf = TTF_RenderUTF8_Blended(menu_font20, buf, color); + if (!font_surf) + { + fprintf(stderr, "%s\n", TTF_GetError()); + exit(1); + } + + SDL_BlitSurface(font_surf, NULL, screen, &dst); + SDL_FreeSurface(font_surf); +} + + +static void menu_draw(SDL_Surface *screen, menu_t *p_menu, int sel, int font_size) +{ + int font_height = TTF_FontHeight(p_menu->p_font); + int line_height = (font_height + font_height / 4); + int x_start = p_menu->x1; + int y_start = p_menu->y1 + line_height; + SDL_Rect r; + int entries_visible = (p_menu->y2 - p_menu->y1) / line_height - 1; + + int i, y; + + if ( p_menu->n_entries * line_height > p_menu->y2 ) + y_start = p_menu->y1 + line_height; + + if (p_menu->cur_sel - p_menu->start_entry_visible > entries_visible) + { + while (p_menu->cur_sel - p_menu->start_entry_visible > entries_visible) + { + p_menu->start_entry_visible ++; + if (p_menu->start_entry_visible > p_menu->n_entries) + { + p_menu->start_entry_visible = 0; + break; + } + } + } + else if ( p_menu->cur_sel < p_menu->start_entry_visible ) + p_menu->start_entry_visible = p_menu->cur_sel; + + if (strlen(p_menu->title)) + { + r.x = p_menu->x1; + r.y = p_menu->y1; + r.w = p_menu->x2 - p_menu->x1; + r.h = line_height-1; + if (sel < 0) + SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 0x40, 0x00, 0x00)); + else + SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 0x00, 0xe7, 0xe7)); + menu_print_font(screen, 0,0,0, p_menu->x1, p_menu->y1, p_menu->title, font_size); + } + + for (i = p_menu->start_entry_visible; i <= p_menu->start_entry_visible + entries_visible; i++) + { + const char *msg = p_menu->pp_msgs[i]; + + if (i >= p_menu->n_entries) + break; + if (IS_MARKER(msg)) + p_menu->cur_sel = atoi(&msg[1]); + else + { + y = (i - p_menu->start_entry_visible) * line_height; + + if (sel < 0) + menu_print_font(screen, 0x40,0x40,0x40, + x_start, y_start + y, msg, font_size); + else if (p_menu->cur_sel == i) /* Selected - color */ + menu_print_font(screen, 0,200,0, + x_start, y_start + y, msg, font_size); + else if (IS_SUBMENU(msg)) + { + if (p_menu->cur_sel == i-1) + menu_print_font(screen, 0,200,0, + x_start, y_start + y, msg, font_size); + else + menu_print_font(screen, 0x40,0x40,0x40, + x_start, y_start + y, msg, font_size); + } + else if (msg[0] == '#') + { + switch (msg[1]) + { + case '1': + menu_print_font(screen, 0,0,255, + x_start, y_start + y, msg+2, font_size); + break; + case '2': + menu_print_font(screen, 0x40,0x40,0x40, + x_start, y_start + y, msg+2, font_size); + break; + default: + menu_print_font(screen, 0x40,0x40,0x40, + x_start, y_start + y, msg, font_size); + break; + } + } + else /* Otherwise white */ + menu_print_font(screen, 0x40,0x40,0x40, + x_start, y_start + y, msg, font_size); + if (IS_SUBMENU(msg)) + { + submenu_t *p_submenu = find_submenu(p_menu, i); + int n_pipe = 0; + int n; + + for (n=0; msg[n] != '\0'; n++) + { + /* Underline the selected entry */ + if (msg[n] == '|') + { + int16_t n_chars; + + for (n_chars = 1; msg[n+n_chars] && msg[n+n_chars] != '|'; n_chars++); + + n_pipe++; + if (p_submenu->sel == n_pipe-1) + { + int w; + int h; + + if (TTF_SizeText(p_menu->p_font, "X", &w, &h) < 0) + { + fw = w; + fh = h; + fprintf(stderr, "%s\n", TTF_GetError()); + exit(1); + } + + r = (SDL_Rect){ x_start + (n+1) * w-1, y_start + (i+ 1 - p_menu->start_entry_visible) * ((h + h/4)) -3, (n_chars - 1) * w, 2}; + if (p_menu->cur_sel == i-1) + SDL_FillRect(screen, &r, + SDL_MapRGB(screen->format, 255,0,0)); + else + SDL_FillRect(screen, &r, + SDL_MapRGB(screen->format, 0x40,0x40,0x40)); + break; + } + } + } + } + } + } +} + +static int get_next_seq_y(menu_t *p_menu, int v, int dy, int cicle) +{ + if (v + dy < 0) + {if (cicle) return (p_menu->n_entries - 1); else return 0;} + + if (v + dy > p_menu->n_entries - 1) + {if (cicle) return 0; else return (p_menu->n_entries - 1);} + return v + dy; +} + +static void select_next(menu_t *p_menu, int dx, int dy, int cicle) +{ + int next; + + + p_menu->cur_sel = get_next_seq_y(p_menu, p_menu->cur_sel, dy, cicle); + next = get_next_seq_y(p_menu, p_menu->cur_sel, dy + 1, cicle); + if (p_menu->pp_msgs[p_menu->cur_sel][0] == ' ' || + p_menu->pp_msgs[p_menu->cur_sel][0] == '#' || + IS_SUBMENU(p_menu->pp_msgs[p_menu->cur_sel]) ) + select_next(p_menu, dx, dy, cicle); + + /* If the next is a submenu */ + if (dx != 0 && IS_SUBMENU(p_menu->pp_msgs[next])) + { + submenu_t *p_submenu = find_submenu(p_menu, next); + + p_submenu->sel = (p_submenu->sel + dx) < 0 ? p_submenu->n_entries - 1 : + (p_submenu->sel + dx) % p_submenu->n_entries; + } + else if (dx == -1 && !strcmp(p_menu->pp_msgs[0], "[..]")) + p_menu->cur_sel = 0; +} + +static void select_one(menu_t *p_menu, int sel) +{ + if (sel >= p_menu->n_entries) + sel = 0; + p_menu->cur_sel = sel; + if (p_menu->pp_msgs[p_menu->cur_sel][0] == ' ' || + p_menu->pp_msgs[p_menu->cur_sel][0] == '#' || + IS_SUBMENU(p_menu->pp_msgs[p_menu->cur_sel])) + select_next(p_menu, 0, 1 , 1); +} + +/* +static int is_submenu_title(menu_t *p_menu, int n) +{ + if (n+1 >= p_menu->n_entries) + return 0; + else + return IS_SUBMENU(p_menu->pp_msgs[n+1]); +} +*/ + +static void menu_init_internal(menu_t *p_menu, const char *title, + TTF_Font *p_font, const char **pp_msgs, + int16_t x1, int16_t y1, int16_t x2, int16_t y2) +{ + int submenu; + int j; + + memset(p_menu, 0, sizeof(menu_t)); + + p_menu->pp_msgs = pp_msgs; + p_menu->p_font = p_font; + p_menu->x1 = x1; + p_menu->y1 = y1; + p_menu->x2 = x2; + p_menu->y2 = y2; + + p_menu->text_w = 0; + p_menu->n_submenus = 0; + strcpy(p_menu->title, title); + + for (p_menu->n_entries = 0; p_menu->pp_msgs[p_menu->n_entries]; p_menu->n_entries++) + { + int text_w_font; + + /* Is this a submenu? */ + if (IS_SUBMENU(p_menu->pp_msgs[p_menu->n_entries])) + { + p_menu->n_submenus++; + continue; /* Length of submenus is unimportant */ + } + + if (TTF_SizeText(p_font, p_menu->pp_msgs[p_menu->n_entries], &text_w_font, NULL) != 0) + { + fprintf(stderr, "%s\n", TTF_GetError()); + exit(1); + } + if (text_w_font > p_menu->text_w) + p_menu->text_w = text_w_font; + } + if (p_menu->text_w > p_menu->x2 - p_menu->x1) + p_menu->text_w = p_menu->x2 - p_menu->x1; + + if ( !(p_menu->p_submenus = (submenu_t *)malloc(sizeof(submenu_t) * p_menu->n_submenus)) ) + { + perror("malloc failed!\n"); + exit(1); + } + + j=0; + submenu = 0; + for (; j < p_menu->n_entries; j++) + { + if (IS_SUBMENU(p_menu->pp_msgs[j])) + { + int n; + + p_menu->p_submenus[submenu].index = j; + p_menu->p_submenus[submenu].sel = 0; + p_menu->p_submenus[submenu].n_entries = 0; + for (n=0; p_menu->pp_msgs[j][n] != '\0'; n++) + { + if (p_menu->pp_msgs[j][n] == '|') + p_menu->p_submenus[submenu].n_entries++; + } + submenu++; + } + } + p_menu->text_h = p_menu->n_entries * (TTF_FontHeight(p_font) + TTF_FontHeight(p_font) / 4); +} + +static void menu_fini(menu_t *p_menu) +{ + free(p_menu->p_submenus); +} + +uint32_t menu_wait_key_press(void) +{ + SDL_Event ev; + uint32_t keys = 0; + + while (1) + { + int i, hats, nr; + SDL_Joystick *joy; + static int joy_keys_changed; + static int joy_keys_last; + SDL_JoystickUpdate(); + /* Wii-specific, sorry */ + for (nr = 0; nr < ordenador.joystick_number; nr++) { + joy = ordenador.joystick_sdl[nr]; + if (!joy) + continue; + + hats = SDL_JoystickNumHats (joy); + for (i = 0; i < hats; i++) { + Uint8 v = SDL_JoystickGetHat (joy, i); + + if (v & SDL_HAT_UP) + keys |= KEY_UP; + if (v & SDL_HAT_DOWN) + keys |= KEY_DOWN; + if (v & SDL_HAT_LEFT) + keys |= KEY_LEFT; + if (v & SDL_HAT_RIGHT) + keys |= KEY_RIGHT; + } + + Sint16 axis0 = SDL_JoystickGetAxis(joy, 0); + Sint16 axis1 = SDL_JoystickGetAxis(joy, 1); + + if ( axis0 < -15000 ) keys |= KEY_LEFT; + else if (axis0 > 15000 ) keys |= KEY_RIGHT; + + if (axis1 < -15000 ) keys |= KEY_UP; + else if( axis1 > 15000 ) keys |= KEY_DOWN; + + + if (SDL_JoystickGetButton(joy, 0) != 0 || /* A */ + SDL_JoystickGetButton(joy, 3) != 0 || /* 2 */ + SDL_JoystickGetButton(joy, 9) != 0 || /* CA */ + SDL_JoystickGetButton(joy, 10) != 0) /* CB */ + keys |= KEY_SELECT; + if (SDL_JoystickGetButton(joy, 2) != 0 || /* 1 */ + SDL_JoystickGetButton(joy, 11) != 0 || /* CX */ + SDL_JoystickGetButton(joy, 12) != 0) /* CY */ + keys |= KEY_ESCAPE; + if (SDL_JoystickGetButton(joy, 5) != 0 || /* + */ + SDL_JoystickGetButton(joy, 18) != 0) /* C+ */ + keys |= KEY_PAGEUP; + if (SDL_JoystickGetButton(joy, 4) != 0 || /* + */ + SDL_JoystickGetButton(joy, 17) != 0) /* C+ */ + keys |= KEY_PAGEDOWN; + } + joy_keys_changed = keys != joy_keys_last; + joy_keys_last = keys; + if (!joy_keys_changed) + keys = 0; + + if (SDL_PollEvent(&ev)) + { + switch(ev.type) + { + case SDL_KEYDOWN: + switch (ev.key.keysym.sym) + { + case SDLK_UP: + keys |= KEY_UP; + break; + case SDLK_DOWN: + keys |= KEY_DOWN; + break; + case SDLK_LEFT: + keys |= KEY_LEFT; + break; + case SDLK_RIGHT: + keys |= KEY_RIGHT; + break; + case SDLK_PAGEDOWN: + keys |= KEY_PAGEDOWN; + break; + case SDLK_PAGEUP: + keys |= KEY_PAGEUP; + break; + case SDLK_RETURN: + case SDLK_SPACE: + keys |= KEY_SELECT; + break; + case SDLK_HOME: + case SDLK_ESCAPE: + keys |= KEY_ESCAPE; + break; + default: + break; + } + break; + case SDL_QUIT: + exit(0); + break; + default: + break; + + } + break; + } + + if (keys != 0) + break; + SDL_Delay(100); + } + return keys; +} + + +extern void PicDisplay(char *name, int off_x, int off_y, int wait); +extern const char **get_t64_list(char *t64); +extern const char **get_prg_list(char *t64); + +extern char curdir[256]; + +static int menu_select_internal(SDL_Surface *screen, + menu_t *p_menu, int *p_submenus, int sel, + void (*select_next_cb)(menu_t *p, void *data), + void *select_next_cb_data, int font_size) +{ + int ret = -1; + int i; + + for (i = 0; i < p_menu->n_submenus; i++) + p_menu->p_submenus[i].sel = p_submenus[i]; + + while(1) + { + SDL_Rect r = {p_menu->x1, p_menu->y1, + p_menu->x2 - p_menu->x1, p_menu->y2 - p_menu->y1}; + uint32_t keys; + int sel_last = p_menu->cur_sel; + + SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 0xff, 0xff, 0xff)); + + menu_draw(screen, p_menu, 0, font_size); + SDL_Flip(screen); + + keys = menu_wait_key_press(); + + if (keys & KEY_UP) + select_next(p_menu, 0, -1, 1); + else if (keys & KEY_DOWN) + select_next(p_menu, 0, 1, 1); + else if (keys & KEY_PAGEUP) + select_next(p_menu, 0, -18, 0); + else if (keys & KEY_PAGEDOWN) + select_next(p_menu, 0, 18, 0); + else if (keys & KEY_LEFT) + select_next(p_menu, -1, 0 ,1); + else if (keys & KEY_RIGHT) + select_next(p_menu, 1, 0 ,1); + else if (keys & KEY_ESCAPE) + break; + else if (keys & KEY_SELECT) + { + ret = p_menu->cur_sel; + int i; + + for (i=0; in_submenus; i++) + p_submenus[i] = p_menu->p_submenus[i].sel; + break; + } + /* Invoke the callback when an entry is selected */ + if (sel_last != p_menu->cur_sel && + select_next_cb != NULL) + select_next_cb(p_menu, select_next_cb_data); + } + + SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0)); + return ret; +} + +int menu_select_sized(const char *title, const char **msgs, int *submenus, int sel, + int x, int y, int x2, int y2, + void (*select_next_cb)(menu_t *p, void *data), + void *select_next_cb_data, int font_size) + +{ + menu_t menu; + int out; + + if (font_size == 16) menu_init_internal(&menu, title, menu_font16, msgs, x, y, x2, y2); + else menu_init_internal(&menu, title, menu_font20, msgs, x, y, x2, y2); + + if (sel >= 0) + select_one(&menu, sel); + out = menu_select_internal(real_screen, &menu, submenus, sel, + select_next_cb, select_next_cb_data, font_size); + + menu_fini(&menu); + + return out; +} + +int menu_select_title(const char *title, const char **msgs, int *submenus) +{ + SDL_FillRect(real_screen, 0, SDL_MapRGB(real_screen->format, 0, 0, 0)); + return menu_select_sized(title, msgs, submenus, 0, + 32, 32, FULL_DISPLAY_X-32, FULL_DISPLAY_Y-32, + NULL, NULL, 20); +} + +int menu_select(const char **msgs, int *submenus) +{ + return menu_select_title("", msgs, submenus); +} + +static const char *menu_select_file_internal(const char *dir_path, + int x, int y, int x2, int y2, const char *selected_file, int which) +{ + const char **file_list = get_file_list(dir_path); + char *sel; + char *out; + const char *ptr_selected_file; + int opt; + int i; + char buf[64]; + + if (file_list == NULL) + return NULL; + + if (selected_file) + { + ptr_selected_file= strrchr(selected_file,'/'); + if (ptr_selected_file) ptr_selected_file++; + else ptr_selected_file = selected_file; + snprintf(buf,64,"tp%d:%s",which, ptr_selected_file); + opt = menu_select_sized(buf, file_list, NULL, 0, x, y, x2, y2, NULL, NULL, 16); + } + else opt = menu_select_sized("Select file", file_list, NULL, 0, x, y, x2, y2, NULL, NULL ,16); + + if (opt < 0) + return NULL; + sel = strdup(file_list[opt]); + + /* Cleanup everything - file_list is NULL-terminated */ + for ( i = 0; file_list[i]; i++ ) + free((void*)file_list[i]); + free(file_list); + + if (!sel) + return NULL; + /* If this is a folder, enter it recursively */ + if (sel[0] == '[') + { + char buf[255]; + int len = strlen(sel); + int s; + + /* Remove trailing ] */ + sel[len-1] = '\0'; + s = snprintf(buf, 128, "%s/%s", dir_path, sel + 1); + + /* We don't need this anymore */ + free((void*)sel); + /* Too deep recursion! */ + if (s >= sizeof(buf)) + return NULL; + return menu_select_file(buf, selected_file, which); + } + + out = (char*)malloc(strlen(dir_path) + strlen(sel) + 4); + snprintf(out, strlen(dir_path) + strlen(sel) + 4, + "%s/%s", dir_path, sel); + + free(sel); + return out; +} + +/* +const char *menu_select_file_start(const char *dir_path, const char **d64_name) +{ + const char *file = menu_select_file_internal(dir_path, + 32, 32, FULL_DISPLAY_X, FULL_DISPLAY_Y - 32); + + if (!file) + return NULL; + + return file; +} +*/ +const char *menu_select_file(const char *dir_path,const char *selected_file, int which) +{ + if (dir_path == NULL) + dir_path = ""; + return menu_select_file_internal(dir_path, + 0, 32, FULL_DISPLAY_X, FULL_DISPLAY_Y - 32, selected_file, which); +} + +static TTF_Font *read_font(const char *path, int font_size) +{ + TTF_Font *out; + SDL_RWops *rw; + Uint8 *data = (Uint8*)malloc(1 * 1024*1024); + FILE *fp = fopen(path, "r"); + + if (!data) { + fprintf(stderr, "Malloc failed\n"); + exit(1); + } + if (!fp) { + fprintf(stderr, "Could not open font\n"); + exit(1); + } + 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()); + exit(1); + } + out = TTF_OpenFontRW(rw, 1, font_size); + if (!out) + { + fprintf(stderr, "Unable to open font %s\n", path); + exit(1); + } + fclose(fp); + + return out; +} + +void menu_init(SDL_Surface *screen) +{ + TTF_Init(); + + menu_font16 = read_font(FONT_PATH, 16); + menu_font20 = read_font(FONT_PATH, 20); + + real_screen = screen; + //virtkbd_init(screen, menu_font_alt16); per ora + is_inited = 1; +} + +int menu_is_inited(void) +{ + return is_inited; +} diff --git a/src/menu_sdl.h b/src/menu_sdl.h new file mode 100644 index 0000000..d455975 --- /dev/null +++ b/src/menu_sdl.h @@ -0,0 +1,62 @@ +/********************************************************************* + * + * Copyright (C) 2004, 2008, Simon Kagstrom + * + * Filename: menu.h + * Author: Simon Kagstrom + * Description: + * + * $Id$ + * + ********************************************************************/ +#ifndef __MENU_H__ +#define __MENU_H__ + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +#define KEY_UP 1 +#define KEY_DOWN 2 +#define KEY_LEFT 4 +#define KEY_RIGHT 8 +#define KEY_SELECT 16 +#define KEY_ESCAPE 32 +#define KEY_PAGEDOWN 64 +#define KEY_PAGEUP 128 +#define KEY_HELP 256 +#define FULL_DISPLAY_X 640 +#define FULL_DISPLAY_Y 480 + + +void menu_print_font(SDL_Surface *screen, int r, int g, int b, int x, int y, const char *msg, int font_size); + + +/* Various option selects */ +int menu_select_title(const char *title, const char **pp_msgs, int *p_submenus); +int menu_select(const char **pp_msgs, int *p_submenus); +const char *menu_select_file(const char *dir_path,const char *selected_file, int which); +const char *menu_select_file_start(const char *dir_path, const char **d64_name); + +uint32_t menu_wait_key_press(void); + +extern void msgKill(SDL_Rect *rc); +extern int msgInfo(char *text, int duration, SDL_Rect *rc); + +extern int msgYesNo(char *text, int def,int x, int y); + +void menu_init(SDL_Surface *screen); + +int menu_is_inited(void); + +int ext_matches(const char *name, const char *ext); + +#if defined(__cplusplus) +} +#endif + +#endif /* !__MENU_H__ */