Clean up input handling some more. Removes the hack to set fast forward

toggles.
This commit is contained in:
Themaister 2011-01-08 18:37:45 +01:00
parent e5d2df13e7
commit 2a5addc79f
7 changed files with 102 additions and 116 deletions

View File

@ -142,28 +142,34 @@ static const bool audio_sync = true;
#define AXIS_NEG(x) ((uint32_t)(x << 16) | 0xFFFF) #define AXIS_NEG(x) ((uint32_t)(x << 16) | 0xFFFF)
#define AXIS_POS(x) ((uint32_t)(x) | 0xFFFF0000U) #define AXIS_POS(x) ((uint32_t)(x) | 0xFFFF0000U)
#define AXIS_NONE ((uint32_t)0xFFFFFFFFU) #define AXIS_NONE ((uint32_t)0xFFFFFFFFU)
#define NO_BTN 0xFFFF // I hope no joypad will ever have this many buttons ... ;)
// To figure out which joypad buttons to use, check jstest or similar. // To figure out which joypad buttons to use, check jstest or similar.
// Axes are configured using the axis number for the positive (up, right) // Axes are configured using the axis number for the positive (up, right)
// direction and the number's two's-complement (~) for negative directions. // direction and the number's two's-complement (~) for negative directions.
// To use the axis, set the button to -1. // To use the axis, set the button to -1.
// SDL sometimes reverses the axes for some odd reason, but hey. :D
// Player 1 // Player 1
static const struct snes_keybind snes_keybinds_1[] = { static const struct snes_keybind snes_keybinds_1[] = {
// SNES button | keyboard key | js btn | js axis | // SNES button | keyboard key | js btn | js axis |
{ SNES_DEVICE_ID_JOYPAD_A, SDLK_x, 1, AXIS_NONE }, { SNES_DEVICE_ID_JOYPAD_A, SDLK_x, 1, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_B, SDLK_z, 0, AXIS_NONE }, { SNES_DEVICE_ID_JOYPAD_B, SDLK_z, 0, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_X, SDLK_s, 3, AXIS_NONE }, { SNES_DEVICE_ID_JOYPAD_X, SDLK_s, 3, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_Y, SDLK_a, 2, AXIS_NONE }, { SNES_DEVICE_ID_JOYPAD_Y, SDLK_a, 2, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_L, SDLK_q, 4, AXIS_NONE }, { SNES_DEVICE_ID_JOYPAD_L, SDLK_q, 4, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_R, SDLK_w, 5, AXIS_NONE }, { SNES_DEVICE_ID_JOYPAD_R, SDLK_w, 5, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_LEFT, SDLK_LEFT, 11, AXIS_NEG(0) }, { SNES_DEVICE_ID_JOYPAD_LEFT, SDLK_LEFT, 11, AXIS_NEG(0) },
{ SNES_DEVICE_ID_JOYPAD_RIGHT, SDLK_RIGHT, 12, AXIS_POS(0) }, { SNES_DEVICE_ID_JOYPAD_RIGHT, SDLK_RIGHT, 12, AXIS_POS(0) },
{ SNES_DEVICE_ID_JOYPAD_UP, SDLK_UP, 13, AXIS_POS(1) }, { SNES_DEVICE_ID_JOYPAD_UP, SDLK_UP, 13, AXIS_NEG(1) },
{ SNES_DEVICE_ID_JOYPAD_DOWN, SDLK_DOWN, 14, AXIS_NEG(1) }, { SNES_DEVICE_ID_JOYPAD_DOWN, SDLK_DOWN, 14, AXIS_POS(1) },
{ SNES_DEVICE_ID_JOYPAD_START, SDLK_RETURN, 7, AXIS_NONE }, { SNES_DEVICE_ID_JOYPAD_START, SDLK_RETURN, 7, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_SELECT, SDLK_RSHIFT, 6, AXIS_NONE }, { SNES_DEVICE_ID_JOYPAD_SELECT, SDLK_RSHIFT, 6, AXIS_NONE },
{ SSNES_FAST_FORWARD_KEY, SDLK_SPACE, 10, AXIS_NONE }, { SSNES_FAST_FORWARD_KEY, SDLK_SPACE, 10, AXIS_NONE },
{ SSNES_SAVE_STATE_KEY, SDLK_F2, NO_BTN, AXIS_NONE },
{ SSNES_LOAD_STATE_KEY, SDLK_F4, NO_BTN, AXIS_NONE },
{ SSNES_FULLSCREEN_TOGGLE_KEY, SDLK_f, NO_BTN, AXIS_NONE },
{ SSNES_QUIT_KEY, SDLK_ESCAPE, NO_BTN, AXIS_NONE },
{ -1 } { -1 }
}; };
@ -178,21 +184,12 @@ static const struct snes_keybind snes_keybinds_2[] = {
{ SNES_DEVICE_ID_JOYPAD_R, SDLK_t, 5, AXIS_NONE }, { SNES_DEVICE_ID_JOYPAD_R, SDLK_t, 5, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_LEFT, SDLK_j, 11, AXIS_NEG(0) }, { SNES_DEVICE_ID_JOYPAD_LEFT, SDLK_j, 11, AXIS_NEG(0) },
{ SNES_DEVICE_ID_JOYPAD_RIGHT, SDLK_l, 12, AXIS_POS(0) }, { SNES_DEVICE_ID_JOYPAD_RIGHT, SDLK_l, 12, AXIS_POS(0) },
{ SNES_DEVICE_ID_JOYPAD_UP, SDLK_i, 13, AXIS_POS(1) }, { SNES_DEVICE_ID_JOYPAD_UP, SDLK_i, 13, AXIS_NEG(1) },
{ SNES_DEVICE_ID_JOYPAD_DOWN, SDLK_k, 14, AXIS_NEG(1) }, { SNES_DEVICE_ID_JOYPAD_DOWN, SDLK_k, 14, AXIS_POS(1) },
{ SNES_DEVICE_ID_JOYPAD_START, SDLK_p, 6, AXIS_NONE }, { SNES_DEVICE_ID_JOYPAD_START, SDLK_p, 6, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_SELECT, SDLK_o, 7, AXIS_NONE }, { SNES_DEVICE_ID_JOYPAD_SELECT, SDLK_o, 7, AXIS_NONE },
{ -1 } { -1 }
}; };
///// Save state
#define SAVE_STATE_KEY SDLK_F2
///// Load state
#define LOAD_STATE_KEY SDLK_F4
//// Toggles between fullscreen and windowed mode.
#define TOGGLE_FULLSCREEN SDLK_f
#endif #endif

View File

@ -25,8 +25,14 @@
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
#define SSNES_FAST_FORWARD_KEY 0x666 // Hurr, durr enum
void set_fast_forward_button(bool state); {
SSNES_FAST_FORWARD_KEY = 0x666, // Hurr, durr
SSNES_LOAD_STATE_KEY,
SSNES_SAVE_STATE_KEY,
SSNES_FULLSCREEN_TOGGLE_KEY,
SSNES_QUIT_KEY,
};
struct snes_keybind struct snes_keybind
{ {

View File

@ -33,8 +33,8 @@
#endif #endif
#define MAX_PLAYERS 2 #define MAX_PLAYERS 2 // Should be 5 when multi-tap stuff is added ...
#define MAX_BINDS 14 #define MAX_BINDS 18 // Needs to be increased every time there are new binds added.
struct settings struct settings
{ {
struct struct
@ -70,10 +70,6 @@ struct settings
{ {
char driver[32]; char driver[32];
struct snes_keybind binds[MAX_PLAYERS][MAX_BINDS]; struct snes_keybind binds[MAX_PLAYERS][MAX_BINDS];
int save_state_key;
int load_state_key;
int toggle_fullscreen_key;
int exit_emulator_key;
float axis_threshold; float axis_threshold;
} input; } input;

View File

@ -56,6 +56,7 @@ static void* sdl_input_init(void)
return sdl; return sdl;
} }
static bool sdl_key_pressed(void *data, int key) static bool sdl_key_pressed(void *data, int key)
{ {
int num_keys; int num_keys;
@ -97,6 +98,17 @@ static bool sdl_is_pressed(sdl_input_t *sdl, int port_num, const struct snes_key
return false; return false;
} }
static bool sdl_bind_button_pressed(void *data, int key)
{
const struct snes_keybind *binds = g_settings.input.binds[0];
for (int i = 0; binds[i].id != -1; i++)
{
if (binds[i].id == key)
return sdl_is_pressed(data, 0, &binds[i]);
}
return false;
}
static int16_t sdl_input_state(void *data, const struct snes_keybind **binds, bool port, unsigned device, unsigned index, unsigned id) static int16_t sdl_input_state(void *data, const struct snes_keybind **binds, bool port, unsigned device, unsigned index, unsigned id)
{ {
sdl_input_t *sdl = data; sdl_input_t *sdl = data;
@ -105,18 +117,15 @@ static int16_t sdl_input_state(void *data, const struct snes_keybind **binds, bo
const struct snes_keybind *snes_keybinds = binds[port == SNES_PORT_1 ? 0 : 1]; const struct snes_keybind *snes_keybinds = binds[port == SNES_PORT_1 ? 0 : 1];
// Checks if button is pressed, and sets fast-forwarding state // Checks if button is pressed.
bool pressed = false;
int port_num = port == SNES_PORT_1 ? 0 : 1; int port_num = port == SNES_PORT_1 ? 0 : 1;
for (int i = 0; snes_keybinds[i].id != -1; i++) for (int i = 0; snes_keybinds[i].id != -1; i++)
{ {
if (snes_keybinds[i].id == SSNES_FAST_FORWARD_KEY) if (snes_keybinds[i].id == (int)id)
set_fast_forward_button(sdl_is_pressed(sdl, port_num, &snes_keybinds[i])); return sdl_is_pressed(sdl, port_num, &snes_keybinds[i]);
else if (!pressed && snes_keybinds[i].id == (int)id)
pressed = sdl_is_pressed(sdl, port_num, &snes_keybinds[i]);
} }
return pressed; return false;
} }
static void sdl_input_free(void *data) static void sdl_input_free(void *data)
@ -170,7 +179,7 @@ const input_driver_t input_sdl = {
.init = sdl_input_init, .init = sdl_input_init,
.poll = sdl_input_poll, .poll = sdl_input_poll,
.input_state = sdl_input_state, .input_state = sdl_input_state,
.key_pressed = sdl_key_pressed, .key_pressed = sdl_bind_button_pressed,
.free = sdl_input_free, .free = sdl_input_free,
.ident = "sdl" .ident = "sdl"
}; };

View File

@ -111,11 +111,7 @@ static void set_defaults(void)
memcpy(g_settings.input.binds[0], snes_keybinds_1, sizeof(snes_keybinds_1)); memcpy(g_settings.input.binds[0], snes_keybinds_1, sizeof(snes_keybinds_1));
memcpy(g_settings.input.binds[1], snes_keybinds_2, sizeof(snes_keybinds_2)); memcpy(g_settings.input.binds[1], snes_keybinds_2, sizeof(snes_keybinds_2));
g_settings.input.save_state_key = SAVE_STATE_KEY;
g_settings.input.load_state_key = LOAD_STATE_KEY;
g_settings.input.toggle_fullscreen_key = TOGGLE_FULLSCREEN;
g_settings.input.axis_threshold = AXIS_THRESHOLD; g_settings.input.axis_threshold = AXIS_THRESHOLD;
g_settings.input.exit_emulator_key = SDLK_ESCAPE;
} }
void parse_config(void) void parse_config(void)
@ -311,37 +307,47 @@ struct bind_map
int snes_key; int snes_key;
}; };
#define DECLARE_BIND(x, bind) { "input_" #x, "input_" #x "_btn", "input_" #x "_axis", bind },
// Big and nasty bind map... :) // Big and nasty bind map... :)
static const struct bind_map bind_maps[2][13] = { static const struct bind_map bind_maps[2][MAX_BINDS - 1] = {
{ {
{ "input_player1_a", "input_player1_a_btn", NULL, SNES_DEVICE_ID_JOYPAD_A }, DECLARE_BIND(player1_a, SNES_DEVICE_ID_JOYPAD_A)
{ "input_player1_b", "input_player1_b_btn", NULL, SNES_DEVICE_ID_JOYPAD_B }, DECLARE_BIND(player1_b, SNES_DEVICE_ID_JOYPAD_B)
{ "input_player1_y", "input_player1_y_btn", NULL, SNES_DEVICE_ID_JOYPAD_Y }, DECLARE_BIND(player1_y, SNES_DEVICE_ID_JOYPAD_Y)
{ "input_player1_x", "input_player1_x_btn", NULL, SNES_DEVICE_ID_JOYPAD_X }, DECLARE_BIND(player1_x, SNES_DEVICE_ID_JOYPAD_X)
{ "input_player1_start", "input_player1_start_btn", NULL, SNES_DEVICE_ID_JOYPAD_START }, DECLARE_BIND(player1_start, SNES_DEVICE_ID_JOYPAD_START)
{ "input_player1_select", "input_player1_select_btn", NULL, SNES_DEVICE_ID_JOYPAD_SELECT }, DECLARE_BIND(player1_select, SNES_DEVICE_ID_JOYPAD_SELECT)
{ "input_player1_l", "input_player1_l_btn", NULL, SNES_DEVICE_ID_JOYPAD_L }, DECLARE_BIND(player1_l, SNES_DEVICE_ID_JOYPAD_L)
{ "input_player1_r", "input_player1_r_btn", NULL, SNES_DEVICE_ID_JOYPAD_R }, DECLARE_BIND(player1_r, SNES_DEVICE_ID_JOYPAD_R)
{ "input_player1_left", "input_player1_left_btn", "input_player1_left_axis", SNES_DEVICE_ID_JOYPAD_LEFT }, DECLARE_BIND(player1_left, SNES_DEVICE_ID_JOYPAD_LEFT)
{ "input_player1_right", "input_player1_right_btn", "input_player1_right_axis", SNES_DEVICE_ID_JOYPAD_RIGHT }, DECLARE_BIND(player1_right, SNES_DEVICE_ID_JOYPAD_RIGHT)
{ "input_player1_up", "input_player1_up_btn", "input_player1_up_axis", SNES_DEVICE_ID_JOYPAD_UP }, DECLARE_BIND(player1_up, SNES_DEVICE_ID_JOYPAD_UP)
{ "input_player1_down", "input_player1_down_btn", "input_player1_down_axis", SNES_DEVICE_ID_JOYPAD_DOWN }, DECLARE_BIND(player1_down, SNES_DEVICE_ID_JOYPAD_DOWN)
{ "input_toggle_fast_forward", "input_toggle_fast_forward_btn", NULL, SSNES_FAST_FORWARD_KEY } DECLARE_BIND(toggle_fast_forward, SSNES_FAST_FORWARD_KEY)
}, DECLARE_BIND(save_state, SSNES_SAVE_STATE_KEY)
DECLARE_BIND(load_state, SSNES_LOAD_STATE_KEY)
DECLARE_BIND(exit_emulator, SSNES_QUIT_KEY)
DECLARE_BIND(toggle_fullscreen, SSNES_FULLSCREEN_TOGGLE_KEY)
},
{ {
{ "input_player2_a", "input_player2_a_btn", NULL, SNES_DEVICE_ID_JOYPAD_A }, DECLARE_BIND(player2_a, SNES_DEVICE_ID_JOYPAD_A)
{ "input_player2_b", "input_player2_b_btn", NULL, SNES_DEVICE_ID_JOYPAD_B }, DECLARE_BIND(player2_b, SNES_DEVICE_ID_JOYPAD_B)
{ "input_player2_y", "input_player2_y_btn", NULL, SNES_DEVICE_ID_JOYPAD_Y }, DECLARE_BIND(player2_y, SNES_DEVICE_ID_JOYPAD_Y)
{ "input_player2_x", "input_player2_x_btn", NULL, SNES_DEVICE_ID_JOYPAD_X }, DECLARE_BIND(player2_x, SNES_DEVICE_ID_JOYPAD_X)
{ "input_player2_start", "input_player2_start_btn", NULL, SNES_DEVICE_ID_JOYPAD_START }, DECLARE_BIND(player2_start, SNES_DEVICE_ID_JOYPAD_START)
{ "input_player2_select", "input_player2_select_btn", NULL, SNES_DEVICE_ID_JOYPAD_SELECT }, DECLARE_BIND(player2_select, SNES_DEVICE_ID_JOYPAD_SELECT)
{ "input_player2_l", "input_player2_l_btn", NULL, SNES_DEVICE_ID_JOYPAD_L }, DECLARE_BIND(player2_l, SNES_DEVICE_ID_JOYPAD_L)
{ "input_player2_r", "input_player2_r_btn", NULL, SNES_DEVICE_ID_JOYPAD_R }, DECLARE_BIND(player2_r, SNES_DEVICE_ID_JOYPAD_R)
{ "input_player2_left", "input_player2_left_btn", "input_player2_left_axis", SNES_DEVICE_ID_JOYPAD_LEFT }, DECLARE_BIND(player2_left, SNES_DEVICE_ID_JOYPAD_LEFT)
{ "input_player2_right", "input_player2_right_btn", "input_player2_right_axis", SNES_DEVICE_ID_JOYPAD_RIGHT }, DECLARE_BIND(player2_right, SNES_DEVICE_ID_JOYPAD_RIGHT)
{ "input_player2_up", "input_player2_up_btn", "input_player2_up_axis", SNES_DEVICE_ID_JOYPAD_UP }, DECLARE_BIND(player2_up, SNES_DEVICE_ID_JOYPAD_UP)
{ "input_player2_down", "input_player2_down_btn", "input_player2_down_axis", SNES_DEVICE_ID_JOYPAD_DOWN }, DECLARE_BIND(player2_down, SNES_DEVICE_ID_JOYPAD_DOWN)
{ "input_toggle_fast_forward", "input_toggle_fast_forward_btn", NULL, SSNES_FAST_FORWARD_KEY } DECLARE_BIND(toggle_fast_forward, SSNES_FAST_FORWARD_KEY)
DECLARE_BIND(save_state, SSNES_SAVE_STATE_KEY)
DECLARE_BIND(load_state, SSNES_LOAD_STATE_KEY)
DECLARE_BIND(exit_emulator, SSNES_QUIT_KEY)
DECLARE_BIND(toggle_fullscreen, SSNES_FULLSCREEN_TOGGLE_KEY)
} }
}; };
@ -352,6 +358,7 @@ struct key_map
}; };
// Edit: Not portable to different input systems atm. Might move this map into the driver itself or something. // Edit: Not portable to different input systems atm. Might move this map into the driver itself or something.
// However, this should map nicely over to other systems aswell since the definition are mostly the same anyways.
static const struct key_map sdlk_map[] = { static const struct key_map sdlk_map[] = {
{ "left", SDLK_LEFT }, { "left", SDLK_LEFT },
{ "right", SDLK_RIGHT }, { "right", SDLK_RIGHT },
@ -459,38 +466,5 @@ static void read_keybinds(config_file_t *conf)
} }
} }
} }
char *tmp_str;
if (config_get_string(conf, "input_toggle_fullscreen", &tmp_str))
{
int key = find_sdlk_key(tmp_str);
if (key >= 0)
g_settings.input.toggle_fullscreen_key = key;
free(tmp_str);
}
if (config_get_string(conf, "input_save_state", &tmp_str))
{
int key = find_sdlk_key(tmp_str);
if (key >= 0)
g_settings.input.save_state_key = key;
free(tmp_str);
}
if (config_get_string(conf, "input_load_state", &tmp_str))
{
int key = find_sdlk_key(tmp_str);
if (key >= 0)
g_settings.input.load_state_key = key;
free(tmp_str);
}
if (config_get_string(conf, "input_exit_emulator", &tmp_str))
{
int key = find_sdlk_key(tmp_str);
if (key >= 0)
g_settings.input.exit_emulator_key = key;
free(tmp_str);
}
} }

13
ssnes.c
View File

@ -43,7 +43,7 @@ struct global g_extern = {
#define AUDIO_CHUNK_SIZE_BLOCKING 64 #define AUDIO_CHUNK_SIZE_BLOCKING 64
#define AUDIO_CHUNK_SIZE_NONBLOCKING 2048 // So we don't get complete line-noise when fast-forwarding audio. #define AUDIO_CHUNK_SIZE_NONBLOCKING 2048 // So we don't get complete line-noise when fast-forwarding audio.
static size_t audio_chunk_size = AUDIO_CHUNK_SIZE_BLOCKING; static size_t audio_chunk_size = AUDIO_CHUNK_SIZE_BLOCKING;
void set_fast_forward_button(bool new_button_state) static void set_fast_forward_button(bool new_button_state)
{ {
static bool old_button_state = false; static bool old_button_state = false;
static bool syncing_state = false; static bool syncing_state = false;
@ -426,21 +426,24 @@ int main(int argc, char *argv[])
} }
#endif #endif
// Main loop
for(;;) for(;;)
{ {
if (driver.input->key_pressed(driver.input_data, g_settings.input.exit_emulator_key) || if (driver.input->key_pressed(driver.input_data, SSNES_QUIT_KEY) ||
!driver.video->alive(driver.video_data)) !driver.video->alive(driver.video_data))
break; break;
if (driver.input->key_pressed(driver.input_data, g_settings.input.save_state_key)) set_fast_forward_button(driver.input->key_pressed(driver.input_data, SSNES_FAST_FORWARD_KEY));
if (driver.input->key_pressed(driver.input_data, SSNES_SAVE_STATE_KEY))
{ {
write_file(statefile_name, serial_data, serial_size); write_file(statefile_name, serial_data, serial_size);
} }
else if (driver.input->key_pressed(driver.input_data, g_settings.input.load_state_key)) else if (driver.input->key_pressed(driver.input_data, SSNES_LOAD_STATE_KEY))
load_state(statefile_name, serial_data, serial_size); load_state(statefile_name, serial_data, serial_size);
else if (driver.input->key_pressed(driver.input_data, g_settings.input.toggle_fullscreen_key)) else if (driver.input->key_pressed(driver.input_data, SSNES_FULLSCREEN_TOGGLE_KEY))
{ {
g_settings.video.fullscreen = !g_settings.video.fullscreen; g_settings.video.fullscreen = !g_settings.video.fullscreen;
uninit_drivers(); uninit_drivers();

View File

@ -102,7 +102,9 @@
# input_player1_up_btn = 13 # input_player1_up_btn = 13
# input_player1_down_btn = 14 # input_player1_down_btn = 14
# Axis for DPAD. Needs to be either '+' or '-' in the first character signaling either positive or negative direction of the axis, then the axis number. # Axis for DPAD.
# Needs to be either '+' or '-' in the first character signaling either positive or negative direction of the axis, then the axis number.
# Do note that every other input option has the corresponding _btn and _axis binds as well; they are omitted here for clarity.
# input_player1_left_axis = -0 # input_player1_left_axis = -0
# input_player1_right_axis = +0 # input_player1_right_axis = +0
# input_player1_up_axis = +1 # input_player1_up_axis = +1
@ -138,8 +140,8 @@
# input_player2_left_axis = -0 # input_player2_left_axis = -0
# input_player2_right_axis = +0 # input_player2_right_axis = +0
# input_player2_up_axis = +1 # input_player2_up_axis = -1
# input_player2_down_axis = -1 # input_player2_down_axis = +1
# Toggles fullscreen. # Toggles fullscreen.
# input_toggle_fullscreen = f # input_toggle_fullscreen = f
@ -150,8 +152,7 @@
# Toggles between fast-forwarding and normal speed. # Toggles between fast-forwarding and normal speed.
# input_toggle_fast_forward = space # input_toggle_fast_forward = space
# Same, just mapping to a joypad button.
# input_toggle_fast_forward_btn = 10
# Key to exit emulator cleanly. # Key to exit emulator cleanly.
# Killing it in any hard way (SIGTERM, SIGKILL, etc, will terminate emulator without saving RAM, etc.)
# input_exit_emulator = escape # input_exit_emulator = escape