mirror of
https://git.code.sf.net/p/fuse-emulator/fuse
synced 2026-01-27 01:41:34 +03:00
769 lines
24 KiB
C
769 lines
24 KiB
C
/* menu.c: general menu widget
|
|
Copyright (c) 2001-2015 Philip Kendall
|
|
Copyright (c) 2015 Sergio Baldoví
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
Author contact information:
|
|
|
|
E-mail: philip-fuse@shadowmagic.org.uk
|
|
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "debugger/debugger.h"
|
|
#include "event.h"
|
|
#include "fuse.h"
|
|
#include "keyboard.h"
|
|
#include "machine.h"
|
|
#include "machines/specplus3.h"
|
|
#include "menu.h"
|
|
#include "peripherals/dck.h"
|
|
#include "peripherals/disk/beta.h"
|
|
#include "peripherals/joystick.h"
|
|
#include "psg.h"
|
|
#include "rzx.h"
|
|
#include "screenshot.h"
|
|
#include "settings.h"
|
|
#include "snapshot.h"
|
|
#include "tape.h"
|
|
#include "ui/uidisplay.h"
|
|
#include "utils.h"
|
|
#include "widget_internals.h"
|
|
#include "widget.h"
|
|
|
|
widget_menu_entry *menu;
|
|
static size_t highlight_line = 0;
|
|
static size_t count;
|
|
static int *current_settings[ 16 ];
|
|
|
|
#define GET_SET_KEY_FUNCTIONS( which ) \
|
|
\
|
|
static void \
|
|
set_key_for_button_ ## which ( int action ) \
|
|
{ \
|
|
*current_settings[ which ] = action; \
|
|
widget_end_all( WIDGET_FINISHED_OK ); \
|
|
} \
|
|
\
|
|
static const char* \
|
|
get_key_name_for_button_ ## which ( void ) \
|
|
{ \
|
|
return keyboard_key_text( *current_settings[ which ] ); \
|
|
}
|
|
|
|
GET_SET_KEY_FUNCTIONS( 1 )
|
|
GET_SET_KEY_FUNCTIONS( 2 )
|
|
GET_SET_KEY_FUNCTIONS( 3 )
|
|
GET_SET_KEY_FUNCTIONS( 4 )
|
|
GET_SET_KEY_FUNCTIONS( 5 )
|
|
#ifdef USE_JOYSTICK
|
|
GET_SET_KEY_FUNCTIONS( 6 )
|
|
GET_SET_KEY_FUNCTIONS( 7 )
|
|
GET_SET_KEY_FUNCTIONS( 8 )
|
|
#ifndef GEKKO
|
|
GET_SET_KEY_FUNCTIONS( 9 )
|
|
GET_SET_KEY_FUNCTIONS( 10 )
|
|
GET_SET_KEY_FUNCTIONS( 11 )
|
|
GET_SET_KEY_FUNCTIONS( 12 )
|
|
GET_SET_KEY_FUNCTIONS( 13 )
|
|
GET_SET_KEY_FUNCTIONS( 14 )
|
|
GET_SET_KEY_FUNCTIONS( 15 )
|
|
#endif /* #ifndef GEKKO */
|
|
#endif /* #ifdef USE_JOYSTICK */
|
|
|
|
#define SUBMENU_KEY_SELECTIONS( which ) \
|
|
\
|
|
static widget_menu_entry submenu_select_number_for_button_ ## which [] = { \
|
|
{ "Select a key" }, \
|
|
{ "\0120\011", INPUT_KEY_0, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_0 }, \
|
|
{ "\0121\011", INPUT_KEY_1, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_1 }, \
|
|
{ "\0122\011", INPUT_KEY_2, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_2 }, \
|
|
{ "\0123\011", INPUT_KEY_3, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_3 }, \
|
|
{ "\0124\011", INPUT_KEY_4, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_4 }, \
|
|
{ "\0125\011", INPUT_KEY_5, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_5 }, \
|
|
{ "\0126\011", INPUT_KEY_6, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_6 }, \
|
|
{ "\0127\011", INPUT_KEY_7, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_7 }, \
|
|
{ "\0128\011", INPUT_KEY_8, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_8 }, \
|
|
{ "\0129\011", INPUT_KEY_9, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_9 }, \
|
|
{ NULL } \
|
|
}; \
|
|
\
|
|
static widget_menu_entry submenu_select_letters1_for_button_ ## which [] = { \
|
|
{ "Select a key" }, \
|
|
{ "\012A\011", INPUT_KEY_a, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_a }, \
|
|
{ "\012B\011", INPUT_KEY_b, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_b }, \
|
|
{ "\012C\011", INPUT_KEY_c, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_c }, \
|
|
{ "\012D\011", INPUT_KEY_d, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_d }, \
|
|
{ "\012E\011", INPUT_KEY_e, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_e }, \
|
|
{ "\012F\011", INPUT_KEY_f, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_f }, \
|
|
{ "\012G\011", INPUT_KEY_g, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_g }, \
|
|
{ "\012H\011", INPUT_KEY_h, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_h }, \
|
|
{ "\012I\011", INPUT_KEY_i, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_i }, \
|
|
{ "\012J\011", INPUT_KEY_j, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_j }, \
|
|
{ "\012K\011", INPUT_KEY_k, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_k }, \
|
|
{ "\012L\011", INPUT_KEY_l, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_l }, \
|
|
{ "\012M\011", INPUT_KEY_m, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_m }, \
|
|
{ NULL } \
|
|
}; \
|
|
\
|
|
static widget_menu_entry submenu_select_letters2_for_button_ ## which [] = { \
|
|
{ "Select a key" }, \
|
|
{ "\012N\011", INPUT_KEY_n, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_n }, \
|
|
{ "\012O\011", INPUT_KEY_o, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_o }, \
|
|
{ "\012P\011", INPUT_KEY_p, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_p }, \
|
|
{ "\012Q\011", INPUT_KEY_q, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_q }, \
|
|
{ "\012R\011", INPUT_KEY_r, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_r }, \
|
|
{ "\012S\011", INPUT_KEY_s, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_s }, \
|
|
{ "\012T\011", INPUT_KEY_t, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_t }, \
|
|
{ "\012U\011", INPUT_KEY_u, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_u }, \
|
|
{ "\012V\011", INPUT_KEY_v, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_v }, \
|
|
{ "\012W\011", INPUT_KEY_w, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_w }, \
|
|
{ "\012X\011", INPUT_KEY_x, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_x }, \
|
|
{ "\012Y\011", INPUT_KEY_y, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_y }, \
|
|
{ "\012Z\011", INPUT_KEY_z, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_z }, \
|
|
{ NULL } \
|
|
}; \
|
|
\
|
|
static widget_menu_entry submenu_select_key_for_button_ ## which [] = { \
|
|
{ "Select a key" }, \
|
|
{ "\012J\011oystick fire", INPUT_KEY_j, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_JOYSTICK_FIRE }, \
|
|
{ "\012N\011umbers...", INPUT_KEY_n, submenu_select_number_for_button_ ## which , NULL, NULL, 0 }, \
|
|
{ "\012A\011-M...", INPUT_KEY_a, submenu_select_letters1_for_button_ ## which , NULL, NULL, 0 }, \
|
|
{ "N-\012Z\011...", INPUT_KEY_z, submenu_select_letters2_for_button_ ## which , NULL, NULL, 0 }, \
|
|
{ "\012S\011pace", INPUT_KEY_s, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_space }, \
|
|
{ "\012E\011nter", INPUT_KEY_e, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_Enter }, \
|
|
{ "\012C\011aps Shift", INPUT_KEY_c, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_Caps }, \
|
|
{ "S\012y\011mbol Shift", INPUT_KEY_y, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_Symbol }, \
|
|
{ "N\012o\011thing", INPUT_KEY_o, NULL, set_key_for_button_ ## which, NULL, KEYBOARD_NONE }, \
|
|
{ NULL } \
|
|
};
|
|
|
|
SUBMENU_KEY_SELECTIONS( 1 )
|
|
SUBMENU_KEY_SELECTIONS( 2 )
|
|
SUBMENU_KEY_SELECTIONS( 3 )
|
|
SUBMENU_KEY_SELECTIONS( 4 )
|
|
SUBMENU_KEY_SELECTIONS( 5 )
|
|
#ifdef USE_JOYSTICK
|
|
SUBMENU_KEY_SELECTIONS( 6 )
|
|
SUBMENU_KEY_SELECTIONS( 7 )
|
|
SUBMENU_KEY_SELECTIONS( 8 )
|
|
#ifndef GEKKO
|
|
SUBMENU_KEY_SELECTIONS( 9 )
|
|
SUBMENU_KEY_SELECTIONS( 10 )
|
|
SUBMENU_KEY_SELECTIONS( 11 )
|
|
SUBMENU_KEY_SELECTIONS( 12 )
|
|
SUBMENU_KEY_SELECTIONS( 13 )
|
|
SUBMENU_KEY_SELECTIONS( 14 )
|
|
SUBMENU_KEY_SELECTIONS( 15 )
|
|
#endif /* #ifndef GEKKO */
|
|
#endif /* #ifdef USE_JOYSTICK */
|
|
|
|
#ifdef USE_JOYSTICK
|
|
static widget_menu_entry submenu_joystick_buttons[] = {
|
|
{ "Select joystick button" },
|
|
#ifndef GEKKO
|
|
{ "Button \0121\011", INPUT_KEY_1, submenu_select_key_for_button_1, NULL, get_key_name_for_button_1, 0 },
|
|
{ "Button \0122\011", INPUT_KEY_2, submenu_select_key_for_button_2, NULL, get_key_name_for_button_2, 0 },
|
|
{ "Button \0123\011", INPUT_KEY_3, submenu_select_key_for_button_3, NULL, get_key_name_for_button_3, 0 },
|
|
{ "Button \0124\011", INPUT_KEY_4, submenu_select_key_for_button_4, NULL, get_key_name_for_button_4, 0 },
|
|
{ "Button \0125\011", INPUT_KEY_5, submenu_select_key_for_button_5, NULL, get_key_name_for_button_5, 0 },
|
|
{ "Button \0126\011", INPUT_KEY_6, submenu_select_key_for_button_6, NULL, get_key_name_for_button_6, 0 },
|
|
{ "Button \0127\011", INPUT_KEY_7, submenu_select_key_for_button_7, NULL, get_key_name_for_button_7, 0 },
|
|
{ "Button \0128\011", INPUT_KEY_8, submenu_select_key_for_button_8, NULL, get_key_name_for_button_8, 0 },
|
|
{ "Button \0129\011", INPUT_KEY_9, submenu_select_key_for_button_9, NULL, get_key_name_for_button_9, 0 },
|
|
{ "Button 1\0120\011", INPUT_KEY_0, submenu_select_key_for_button_10, NULL, get_key_name_for_button_10, 0 },
|
|
{ "Button 11(\012a\011)", INPUT_KEY_a, submenu_select_key_for_button_11, NULL, get_key_name_for_button_11, 0 },
|
|
{ "Button 12(\012b\011)", INPUT_KEY_b, submenu_select_key_for_button_12, NULL, get_key_name_for_button_12, 0 },
|
|
{ "Button 13(\012c\011)", INPUT_KEY_c, submenu_select_key_for_button_13, NULL, get_key_name_for_button_13, 0 },
|
|
{ "Button 14(\012d\011)", INPUT_KEY_d, submenu_select_key_for_button_14, NULL, get_key_name_for_button_14, 0 },
|
|
{ "Button 15(\012e\011)", INPUT_KEY_e, submenu_select_key_for_button_15, NULL, get_key_name_for_button_15, 0 },
|
|
#else /* #ifndef GEKKO */
|
|
{ "Button \0121\011", INPUT_KEY_1, submenu_select_key_for_button_1, NULL, get_key_name_for_button_1, 0 },
|
|
{ "Button \0122\011", INPUT_KEY_2, submenu_select_key_for_button_2, NULL, get_key_name_for_button_2, 0 },
|
|
{ "Button \012A\011", INPUT_KEY_a, submenu_select_key_for_button_3, NULL, get_key_name_for_button_3, 0 },
|
|
{ "Button \012B\011", INPUT_KEY_b, submenu_select_key_for_button_4, NULL, get_key_name_for_button_4, 0 },
|
|
{ "Button \012P\011lus", INPUT_KEY_p, submenu_select_key_for_button_5, NULL, get_key_name_for_button_5, 0 },
|
|
{ "Button \012M\011inus", INPUT_KEY_m, submenu_select_key_for_button_6, NULL, get_key_name_for_button_6, 0 },
|
|
{ "Button \012Z\011 on Nunchuck", INPUT_KEY_z, submenu_select_key_for_button_7, NULL, get_key_name_for_button_7, 0 },
|
|
{ "Button \012C\011 on Nunchuck", INPUT_KEY_c, submenu_select_key_for_button_8, NULL, get_key_name_for_button_8, 0 },
|
|
#endif /* #ifndef GEKKO */
|
|
{ NULL }
|
|
};
|
|
#endif /* #ifdef USE_JOYSTICK */
|
|
|
|
static widget_menu_entry submenu_keyboard_buttons[] = {
|
|
{ "Select keyboard key" },
|
|
{ "Button \012U\011p", INPUT_KEY_u, submenu_select_key_for_button_1, NULL, get_key_name_for_button_1, 0 },
|
|
{ "Button \012D\011own", INPUT_KEY_d, submenu_select_key_for_button_2, NULL, get_key_name_for_button_2, 0 },
|
|
{ "Button \012L\011eft", INPUT_KEY_l, submenu_select_key_for_button_3, NULL, get_key_name_for_button_3, 0 },
|
|
{ "Button \012R\011ight", INPUT_KEY_r, submenu_select_key_for_button_4, NULL, get_key_name_for_button_4, 0 },
|
|
{ "Button \012F\011ire", INPUT_KEY_f, submenu_select_key_for_button_5, NULL, get_key_name_for_button_5, 0 },
|
|
{ NULL }
|
|
};
|
|
|
|
#define MAX_JOYSTICK_TYPES 8
|
|
/* joystick types + title of the window + NULL */
|
|
static widget_menu_entry submenu_types[ MAX_JOYSTICK_TYPES + 2 ];
|
|
static char joystick_names[ MAX_JOYSTICK_TYPES ][ 100 ];
|
|
void set_joystick_type( int action );
|
|
|
|
#define SUBMENU_DEVICE_SELECTIONS( device ) \
|
|
\
|
|
static widget_menu_entry submenu_type_and_mapping_for_ ## device [] = { \
|
|
{ "Select type or map buttons" }, \
|
|
{ "\012T\011ype", INPUT_KEY_t, submenu_types, NULL, NULL, 0 }, \
|
|
{ "\012B\011utton Mapping", INPUT_KEY_b, submenu_ ## device ## _buttons, NULL, NULL, 0 }, \
|
|
{ NULL } \
|
|
};
|
|
|
|
#ifdef USE_JOYSTICK
|
|
SUBMENU_DEVICE_SELECTIONS( joystick )
|
|
#endif /* #ifdef USE_JOYSTICK */
|
|
SUBMENU_DEVICE_SELECTIONS( keyboard )
|
|
|
|
static void
|
|
print_items( void )
|
|
{
|
|
int i;
|
|
char buffer[128];
|
|
size_t height = 24;
|
|
int width = widget_calculate_menu_width(menu);
|
|
int menu_left_edge_x = (DISPLAY_WIDTH_COLS/2-width/2)*8+1;
|
|
|
|
for( i = 0; i < count; i++ ) {
|
|
int colour;
|
|
if( !menu[i+1].text[0] ) { height += 4; continue; }
|
|
|
|
snprintf( buffer, sizeof (buffer), "%s", menu[i+1].text );
|
|
colour = menu[i+1].inactive ?
|
|
WIDGET_COLOUR_DISABLED :
|
|
WIDGET_COLOUR_FOREGROUND;
|
|
|
|
if( i == highlight_line ) {
|
|
widget_rectangle( menu_left_edge_x, height, width*8-2, 1*8,
|
|
WIDGET_COLOUR_HIGHLIGHT );
|
|
} else {
|
|
widget_rectangle( menu_left_edge_x, height, width*8-2, 1*8,
|
|
WIDGET_COLOUR_BACKGROUND );
|
|
}
|
|
|
|
widget_printstring( menu_left_edge_x+8, height, colour, buffer );
|
|
|
|
if( menu[i+1].submenu ) {
|
|
widget_draw_submenu_arrow(DISPLAY_BORDER_ASPECT_WIDTH+menu_left_edge_x+
|
|
width*8-9, i*8+49, colour);
|
|
}
|
|
|
|
if( menu[i+1].detail ) {
|
|
size_t detail_width = widget_stringwidth( menu[i+1].detail() );
|
|
int x = menu_left_edge_x + (width-1)*8 - detail_width - 2;
|
|
widget_printstring( x, height, WIDGET_COLOUR_DISABLED, menu[i+1].detail() );
|
|
}
|
|
|
|
height += 8;
|
|
}
|
|
|
|
widget_display_lines( 2, count + 2 );
|
|
}
|
|
|
|
int widget_menu_draw( void *data )
|
|
{
|
|
widget_menu_entry *ptr;
|
|
size_t menu_entries, width, height = 0;
|
|
int menu_left_edge_x;
|
|
char buffer[128];
|
|
highlight_line = 0;
|
|
|
|
menu = (widget_menu_entry*)data;
|
|
|
|
/* How many menu items do we have? */
|
|
for( ptr = &menu[1]; ptr->text; ptr++ )
|
|
height += ptr->text[0] ? 2 : 1;
|
|
menu_entries = ptr - &menu[1];
|
|
count = menu_entries;
|
|
width = widget_calculate_menu_width(menu);
|
|
menu_left_edge_x = DISPLAY_WIDTH_COLS/2-width/2;
|
|
widget_dialog_with_border( menu_left_edge_x, 2, width, 2 + height / 2 );
|
|
|
|
snprintf( buffer, sizeof( buffer ), "%s", menu->text );
|
|
widget_printstring( menu_left_edge_x*8+2, 16, WIDGET_COLOUR_TITLE, buffer );
|
|
|
|
print_items();
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
widget_menu_keyhandler( input_key key )
|
|
{
|
|
widget_menu_entry *ptr;
|
|
int new_highlight_line = 0;
|
|
int cursor_pressed = 0;
|
|
|
|
switch( key ) {
|
|
|
|
#if 0
|
|
case INPUT_KEY_Resize: /* Fake keypress used on window resize */
|
|
widget_menu_draw( menu );
|
|
break;
|
|
#endif
|
|
|
|
case INPUT_KEY_Escape:
|
|
case INPUT_JOYSTICK_FIRE_2:
|
|
widget_end_widget( WIDGET_FINISHED_CANCEL );
|
|
return;
|
|
|
|
case INPUT_KEY_Return:
|
|
case INPUT_KEY_KP_Enter:
|
|
case INPUT_JOYSTICK_FIRE_1:
|
|
ptr=&menu[1 + highlight_line];
|
|
if(!ptr->inactive) {
|
|
if( ptr->submenu ) {
|
|
widget_do_menu( ptr->submenu );
|
|
} else {
|
|
ptr->callback( ptr->action );
|
|
}
|
|
}
|
|
return;
|
|
|
|
case INPUT_KEY_Up:
|
|
case INPUT_KEY_7:
|
|
case INPUT_JOYSTICK_UP:
|
|
if ( highlight_line ) {
|
|
new_highlight_line = highlight_line - 1;
|
|
cursor_pressed = 1;
|
|
}
|
|
break;
|
|
|
|
case INPUT_KEY_Down:
|
|
case INPUT_KEY_6:
|
|
case INPUT_JOYSTICK_DOWN:
|
|
if ( highlight_line + 1 < (ptrdiff_t)count ) {
|
|
new_highlight_line = highlight_line + 1;
|
|
cursor_pressed = 1;
|
|
}
|
|
break;
|
|
|
|
default: /* Keep gcc happy */
|
|
break;
|
|
|
|
}
|
|
|
|
if( cursor_pressed ) {
|
|
highlight_line = new_highlight_line;
|
|
print_items();
|
|
return;
|
|
}
|
|
|
|
for( ptr=&menu[1]; ptr->text; ptr++ ) {
|
|
if( !ptr->inactive && key == ptr->key ) {
|
|
|
|
if( ptr->submenu ) {
|
|
widget_do_menu( ptr->submenu );
|
|
} else {
|
|
ptr->callback( ptr->action );
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* General callbacks */
|
|
|
|
scaler_type
|
|
menu_get_scaler( scaler_available_fn selector )
|
|
{
|
|
size_t count, i;
|
|
const char *options[ SCALER_NUM ];
|
|
widget_select_t info;
|
|
int error;
|
|
|
|
count = 0; info.current = 0;
|
|
|
|
for( i = 0; i < SCALER_NUM; i++ )
|
|
if( selector( i ) ) {
|
|
if( current_scaler == i ) info.current = count;
|
|
options[ count++ ] = scaler_name( i );
|
|
}
|
|
|
|
info.title = "Select scaler";
|
|
info.options = options;
|
|
info.count = count;
|
|
info.finish_all = 1;
|
|
|
|
error = widget_do_select( &info );
|
|
if( error ) return SCALER_NUM;
|
|
|
|
if( info.result == -1 ) return SCALER_NUM;
|
|
|
|
for( i = 0; i < SCALER_NUM; i++ )
|
|
if( selector( i ) && !info.result-- ) return i;
|
|
|
|
ui_error( UI_ERROR_ERROR, "widget_select_scaler: ran out of scalers" );
|
|
fuse_abort();
|
|
}
|
|
|
|
void
|
|
menu_file_exit( int action )
|
|
{
|
|
static int menu_exit_open = 0;
|
|
|
|
if( menu_exit_open ) return;
|
|
|
|
menu_exit_open = 1;
|
|
if( widget_do_query( "Exit Fuse?" ) || !widget_query.confirm ) {
|
|
menu_exit_open = 0;
|
|
return;
|
|
}
|
|
|
|
if( menu_check_media_changed() ) {
|
|
menu_exit_open = 0;
|
|
return;
|
|
}
|
|
|
|
fuse_exiting = 1;
|
|
menu_exit_open = 0;
|
|
|
|
widget_end_all( WIDGET_FINISHED_OK );
|
|
}
|
|
|
|
void
|
|
menu_options_general( int action )
|
|
{
|
|
widget_do_general();
|
|
}
|
|
|
|
void
|
|
menu_options_media( int action )
|
|
{
|
|
widget_do_media();
|
|
}
|
|
|
|
void
|
|
menu_options_peripherals_general( int action )
|
|
{
|
|
widget_do_peripherals_general();
|
|
}
|
|
|
|
void
|
|
menu_options_peripherals_disk( int action )
|
|
{
|
|
widget_do_peripherals_disk();
|
|
}
|
|
|
|
void
|
|
menu_options_sound( int action )
|
|
{
|
|
widget_do_sound();
|
|
}
|
|
|
|
void
|
|
menu_options_rzx( int action )
|
|
{
|
|
widget_do_rzx();
|
|
}
|
|
|
|
void
|
|
menu_options_movie( int action )
|
|
{
|
|
widget_do_movie();
|
|
}
|
|
|
|
void
|
|
menu_options_diskoptions( int action )
|
|
{
|
|
widget_do_diskoptions();
|
|
}
|
|
|
|
void
|
|
menu_options_joysticks_select( int action )
|
|
{
|
|
int error = 0;
|
|
int i;
|
|
|
|
switch( action - 1 ) {
|
|
|
|
#ifdef USE_JOYSTICK
|
|
case 0:
|
|
current_settings[ 0 ] = &( settings_current.joystick_1_output );
|
|
current_settings[ 1 ] = &( settings_current.joystick_1_fire_1 );
|
|
current_settings[ 2 ] = &( settings_current.joystick_1_fire_2 );
|
|
current_settings[ 3 ] = &( settings_current.joystick_1_fire_3 );
|
|
current_settings[ 4 ] = &( settings_current.joystick_1_fire_4 );
|
|
current_settings[ 5 ] = &( settings_current.joystick_1_fire_5 );
|
|
current_settings[ 6 ] = &( settings_current.joystick_1_fire_6 );
|
|
current_settings[ 7 ] = &( settings_current.joystick_1_fire_7 );
|
|
current_settings[ 8 ] = &( settings_current.joystick_1_fire_8 );
|
|
current_settings[ 9 ] = &( settings_current.joystick_1_fire_9 );
|
|
current_settings[ 10 ] = &( settings_current.joystick_1_fire_10 );
|
|
current_settings[ 11 ] = &( settings_current.joystick_1_fire_11 );
|
|
current_settings[ 12 ] = &( settings_current.joystick_1_fire_12 );
|
|
current_settings[ 13 ] = &( settings_current.joystick_1_fire_13 );
|
|
current_settings[ 14 ] = &( settings_current.joystick_1_fire_14 );
|
|
current_settings[ 15 ] = &( settings_current.joystick_1_fire_15 );
|
|
submenu_type_and_mapping_for_joystick[ 1 ].detail = menu_joystick_1_detail;
|
|
break;
|
|
case 1:
|
|
current_settings[ 0 ] = &( settings_current.joystick_2_output );
|
|
current_settings[ 1 ] = &( settings_current.joystick_2_fire_1 );
|
|
current_settings[ 2 ] = &( settings_current.joystick_2_fire_2 );
|
|
current_settings[ 3 ] = &( settings_current.joystick_2_fire_3 );
|
|
current_settings[ 4 ] = &( settings_current.joystick_2_fire_4 );
|
|
current_settings[ 5 ] = &( settings_current.joystick_2_fire_5 );
|
|
current_settings[ 6 ] = &( settings_current.joystick_2_fire_6 );
|
|
current_settings[ 7 ] = &( settings_current.joystick_2_fire_7 );
|
|
current_settings[ 8 ] = &( settings_current.joystick_2_fire_8 );
|
|
current_settings[ 9 ] = &( settings_current.joystick_2_fire_9 );
|
|
current_settings[ 10 ] = &( settings_current.joystick_2_fire_10 );
|
|
current_settings[ 11 ] = &( settings_current.joystick_2_fire_11 );
|
|
current_settings[ 12 ] = &( settings_current.joystick_2_fire_12 );
|
|
current_settings[ 13 ] = &( settings_current.joystick_2_fire_13 );
|
|
current_settings[ 14 ] = &( settings_current.joystick_2_fire_14 );
|
|
current_settings[ 15 ] = &( settings_current.joystick_2_fire_15 );
|
|
submenu_type_and_mapping_for_joystick[ 1 ].detail = menu_joystick_2_detail;
|
|
break;
|
|
#endif /* #ifdef USE_JOYSTICK */
|
|
|
|
case JOYSTICK_KEYBOARD:
|
|
current_settings[ 0 ] = &( settings_current.joystick_keyboard_output );
|
|
current_settings[ 1 ] = &( settings_current.joystick_keyboard_up );
|
|
current_settings[ 2 ] = &( settings_current.joystick_keyboard_down );
|
|
current_settings[ 3 ] = &( settings_current.joystick_keyboard_left );
|
|
current_settings[ 4 ] = &( settings_current.joystick_keyboard_right );
|
|
current_settings[ 5 ] = &( settings_current.joystick_keyboard_fire );
|
|
submenu_type_and_mapping_for_keyboard[ 1 ].detail = menu_keyboard_joystick_detail;
|
|
break;
|
|
}
|
|
|
|
/* Populate joystick names */
|
|
if( JOYSTICK_TYPE_COUNT > MAX_JOYSTICK_TYPES )
|
|
ui_error( UI_ERROR_ERROR, "Not all joystick types are displayed" );
|
|
|
|
submenu_types[ 0 ].text = "Select joystick type";
|
|
for( i = 0; ( i < JOYSTICK_TYPE_COUNT ) && ( i < MAX_JOYSTICK_TYPES ); i++ ) {
|
|
char shortcut[ 2 ] = { 'A' + i, '\0' };
|
|
snprintf( ( char * ) joystick_names[ i ], 100, "\012%s\011 %s", shortcut,
|
|
joystick_name[ i ] );
|
|
submenu_types[ i + 1 ].text = joystick_names[ i ];
|
|
submenu_types[ i + 1 ].key = INPUT_KEY_a + i;
|
|
submenu_types[ i + 1 ].callback = set_joystick_type;
|
|
submenu_types[ i + 1 ].action = i;
|
|
}
|
|
submenu_types[ i + 1 ].text = NULL;
|
|
|
|
if( action - 1 == JOYSTICK_KEYBOARD )
|
|
error = widget_do_menu( submenu_type_and_mapping_for_keyboard );
|
|
|
|
#ifdef USE_JOYSTICK
|
|
else
|
|
error = widget_do_menu( submenu_type_and_mapping_for_joystick );
|
|
#endif /* #ifdef USE_JOYSTICK */
|
|
|
|
if( error ) return;
|
|
}
|
|
|
|
void
|
|
set_joystick_type( int action )
|
|
{
|
|
*current_settings[ 0 ] = action;
|
|
widget_end_all( WIDGET_FINISHED_OK );
|
|
}
|
|
|
|
/* Options/Select ROMs/<type> */
|
|
int
|
|
menu_select_roms_with_title( const char *title, size_t start, size_t count,
|
|
int is_peripheral )
|
|
{
|
|
widget_roms_info info;
|
|
|
|
info.title = title;
|
|
info.start = start;
|
|
info.count = count;
|
|
info.is_peripheral = is_peripheral;
|
|
info.initialised = 0;
|
|
|
|
return widget_do_rom( &info );
|
|
}
|
|
|
|
void
|
|
menu_machine_reset( int action )
|
|
{
|
|
int hard_reset = action;
|
|
const char *message = "Reset?";
|
|
|
|
if( hard_reset )
|
|
message = "Hard reset?";
|
|
|
|
if( widget_do_query( message ) ||
|
|
!widget_query.confirm )
|
|
return;
|
|
|
|
widget_end_all( WIDGET_FINISHED_OK );
|
|
|
|
/* Stop any ongoing RZX */
|
|
rzx_stop_recording();
|
|
rzx_stop_playback( 1 );
|
|
|
|
machine_reset( hard_reset );
|
|
}
|
|
|
|
void
|
|
menu_machine_select( int action )
|
|
{
|
|
widget_select_t info;
|
|
char **options, *buffer;
|
|
size_t i;
|
|
int error;
|
|
libspectrum_machine new_machine;
|
|
|
|
options = malloc( machine_count * sizeof( const char * ) );
|
|
if( !options ) {
|
|
ui_error( UI_ERROR_ERROR, "out of memory at %s:%d", __FILE__, __LINE__ );
|
|
return;
|
|
}
|
|
|
|
buffer = malloc( 40 * machine_count );
|
|
if( !buffer ) {
|
|
ui_error( UI_ERROR_ERROR, "out of memory at %s:%d", __FILE__, __LINE__ );
|
|
free( options );
|
|
return;
|
|
}
|
|
|
|
for( i = 0; i < machine_count; i++ ) {
|
|
options[i] = &buffer[ i * 40 ];
|
|
snprintf( options[i], 40, "%s",
|
|
libspectrum_machine_name( machine_types[i]->machine ) );
|
|
if( machine_current->machine == machine_types[i]->machine )
|
|
info.current = i;
|
|
}
|
|
|
|
info.title = "Select machine";
|
|
info.options = (const char**)options;
|
|
info.count = machine_count;
|
|
info.finish_all = 1;
|
|
|
|
error = widget_do_select( &info );
|
|
free( buffer ); free( options );
|
|
if( error ) return;
|
|
|
|
if( info.result == -1 ) return;
|
|
|
|
new_machine = machine_types[ info.result ]->machine;
|
|
|
|
if( machine_current->machine != new_machine ) machine_select( new_machine );
|
|
}
|
|
|
|
void
|
|
menu_machine_debugger( int action )
|
|
{
|
|
debugger_mode = DEBUGGER_MODE_HALTED;
|
|
widget_do_debugger();
|
|
}
|
|
|
|
void
|
|
menu_machine_pokememory( int action )
|
|
{
|
|
widget_do_pokemem();
|
|
}
|
|
|
|
void
|
|
menu_machine_pokefinder( int action )
|
|
{
|
|
widget_do_pokefinder();
|
|
}
|
|
|
|
void
|
|
menu_machine_memorybrowser( int action )
|
|
{
|
|
widget_do_memorybrowser();
|
|
}
|
|
|
|
void
|
|
menu_media_tape_browse( int action )
|
|
{
|
|
widget_do_browse();
|
|
}
|
|
|
|
void
|
|
menu_help_keyboard( int action )
|
|
{
|
|
utils_file screen;
|
|
widget_picture_data info;
|
|
|
|
static const char * const filename = "keyboard.scr";
|
|
|
|
if( utils_read_screen( filename, &screen ) ) {
|
|
return;
|
|
}
|
|
|
|
info.filename = filename;
|
|
info.screen = screen.buffer;
|
|
info.border = 0;
|
|
|
|
widget_do_picture( &info );
|
|
|
|
utils_close_file( &screen );
|
|
}
|
|
|
|
void
|
|
menu_help_about( int action )
|
|
{
|
|
widget_do_about();
|
|
}
|
|
|
|
static int
|
|
set_active( struct widget_menu_entry *menu, const char *path, int active )
|
|
{
|
|
if( *path == '/' ) path++;
|
|
|
|
/* Skip the menu title */
|
|
menu++;
|
|
|
|
for( ; menu->text; menu++ ) {
|
|
|
|
const char *p = menu->text, *q = path;
|
|
|
|
/* Compare the two strings, but skip hotkey-delimiter characters */
|
|
do {
|
|
if( *p == 9 || *p == 10 ) p++;
|
|
} while( *p && *p++ == *q++ );
|
|
|
|
if( *p ) continue; /* not matched */
|
|
|
|
/* match, but with a submenu */
|
|
if( *q == '/' ) return set_active( menu->submenu, q, active );
|
|
|
|
if( *q ) continue; /* not matched */
|
|
|
|
/* we have a match */
|
|
menu->inactive = !active;
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
ui_menu_item_set_active( const char *path, int active )
|
|
{
|
|
return set_active( widget_menu, path, active );
|
|
}
|