diff --git a/FreeMono.ttf b/FreeMono.ttf
new file mode 100644
index 0000000..517ea95
Binary files /dev/null and b/FreeMono.ttf differ
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__ */