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_POS(x) ((uint32_t)(x) | 0xFFFF0000U)
#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.
// Axes are configured using the axis number for the positive (up, right)
// direction and the number's two's-complement (~) for negative directions.
// To use the axis, set the button to -1.
// SDL sometimes reverses the axes for some odd reason, but hey. :D
// Player 1
static const struct snes_keybind snes_keybinds_1[] = {
// SNES button | keyboard key | js btn | js axis |
{ SNES_DEVICE_ID_JOYPAD_A, SDLK_x, 1, 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_Y, SDLK_a, 2, 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_LEFT, SDLK_LEFT, 11, AXIS_NEG(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_DOWN, SDLK_DOWN, 14, AXIS_NEG(1) },
{ SNES_DEVICE_ID_JOYPAD_START, SDLK_RETURN, 7, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_SELECT, SDLK_RSHIFT, 6, AXIS_NONE },
{ SSNES_FAST_FORWARD_KEY, SDLK_SPACE, 10, 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_X, SDLK_s, 3, 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_R, SDLK_w, 5, AXIS_NONE },
{ 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_UP, SDLK_UP, 13, 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_SELECT, SDLK_RSHIFT, 6, 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 }
};
@ -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_LEFT, SDLK_j, 11, AXIS_NEG(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_DOWN, SDLK_k, 14, AXIS_NEG(1) },
{ SNES_DEVICE_ID_JOYPAD_UP, SDLK_i, 13, 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_SELECT, SDLK_o, 7, AXIS_NONE },
{ -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

View File

@ -25,8 +25,14 @@
#include <stdint.h>
#include <unistd.h>
#define SSNES_FAST_FORWARD_KEY 0x666 // Hurr, durr
void set_fast_forward_button(bool state);
enum
{
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
{

View File

@ -33,8 +33,8 @@
#endif
#define MAX_PLAYERS 2
#define MAX_BINDS 14
#define MAX_PLAYERS 2 // Should be 5 when multi-tap stuff is added ...
#define MAX_BINDS 18 // Needs to be increased every time there are new binds added.
struct settings
{
struct
@ -70,10 +70,6 @@ struct settings
{
char driver[32];
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;
} input;

View File

@ -56,6 +56,7 @@ static void* sdl_input_init(void)
return sdl;
}
static bool sdl_key_pressed(void *data, int key)
{
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;
}
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)
{
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];
// Checks if button is pressed, and sets fast-forwarding state
bool pressed = false;
// Checks if button is pressed.
int port_num = port == SNES_PORT_1 ? 0 : 1;
for (int i = 0; snes_keybinds[i].id != -1; i++)
{
if (snes_keybinds[i].id == SSNES_FAST_FORWARD_KEY)
set_fast_forward_button(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]);
if (snes_keybinds[i].id == (int)id)
return sdl_is_pressed(sdl, port_num, &snes_keybinds[i]);
}
return pressed;
return false;
}
static void sdl_input_free(void *data)
@ -170,7 +179,7 @@ const input_driver_t input_sdl = {
.init = sdl_input_init,
.poll = sdl_input_poll,
.input_state = sdl_input_state,
.key_pressed = sdl_key_pressed,
.key_pressed = sdl_bind_button_pressed,
.free = sdl_input_free,
.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[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.exit_emulator_key = SDLK_ESCAPE;
}
void parse_config(void)
@ -311,37 +307,47 @@ struct bind_map
int snes_key;
};
#define DECLARE_BIND(x, bind) { "input_" #x, "input_" #x "_btn", "input_" #x "_axis", bind },
// 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 },
{ "input_player1_b", "input_player1_b_btn", NULL, SNES_DEVICE_ID_JOYPAD_B },
{ "input_player1_y", "input_player1_y_btn", NULL, SNES_DEVICE_ID_JOYPAD_Y },
{ "input_player1_x", "input_player1_x_btn", NULL, SNES_DEVICE_ID_JOYPAD_X },
{ "input_player1_start", "input_player1_start_btn", NULL, SNES_DEVICE_ID_JOYPAD_START },
{ "input_player1_select", "input_player1_select_btn", NULL, SNES_DEVICE_ID_JOYPAD_SELECT },
{ "input_player1_l", "input_player1_l_btn", NULL, SNES_DEVICE_ID_JOYPAD_L },
{ "input_player1_r", "input_player1_r_btn", NULL, SNES_DEVICE_ID_JOYPAD_R },
{ "input_player1_left", "input_player1_left_btn", "input_player1_left_axis", SNES_DEVICE_ID_JOYPAD_LEFT },
{ "input_player1_right", "input_player1_right_btn", "input_player1_right_axis", SNES_DEVICE_ID_JOYPAD_RIGHT },
{ "input_player1_up", "input_player1_up_btn", "input_player1_up_axis", SNES_DEVICE_ID_JOYPAD_UP },
{ "input_player1_down", "input_player1_down_btn", "input_player1_down_axis", SNES_DEVICE_ID_JOYPAD_DOWN },
{ "input_toggle_fast_forward", "input_toggle_fast_forward_btn", NULL, SSNES_FAST_FORWARD_KEY }
},
DECLARE_BIND(player1_a, SNES_DEVICE_ID_JOYPAD_A)
DECLARE_BIND(player1_b, SNES_DEVICE_ID_JOYPAD_B)
DECLARE_BIND(player1_y, SNES_DEVICE_ID_JOYPAD_Y)
DECLARE_BIND(player1_x, SNES_DEVICE_ID_JOYPAD_X)
DECLARE_BIND(player1_start, SNES_DEVICE_ID_JOYPAD_START)
DECLARE_BIND(player1_select, SNES_DEVICE_ID_JOYPAD_SELECT)
DECLARE_BIND(player1_l, SNES_DEVICE_ID_JOYPAD_L)
DECLARE_BIND(player1_r, SNES_DEVICE_ID_JOYPAD_R)
DECLARE_BIND(player1_left, SNES_DEVICE_ID_JOYPAD_LEFT)
DECLARE_BIND(player1_right, SNES_DEVICE_ID_JOYPAD_RIGHT)
DECLARE_BIND(player1_up, SNES_DEVICE_ID_JOYPAD_UP)
DECLARE_BIND(player1_down, SNES_DEVICE_ID_JOYPAD_DOWN)
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 },
{ "input_player2_b", "input_player2_b_btn", NULL, SNES_DEVICE_ID_JOYPAD_B },
{ "input_player2_y", "input_player2_y_btn", NULL, SNES_DEVICE_ID_JOYPAD_Y },
{ "input_player2_x", "input_player2_x_btn", NULL, SNES_DEVICE_ID_JOYPAD_X },
{ "input_player2_start", "input_player2_start_btn", NULL, SNES_DEVICE_ID_JOYPAD_START },
{ "input_player2_select", "input_player2_select_btn", NULL, SNES_DEVICE_ID_JOYPAD_SELECT },
{ "input_player2_l", "input_player2_l_btn", NULL, SNES_DEVICE_ID_JOYPAD_L },
{ "input_player2_r", "input_player2_r_btn", NULL, SNES_DEVICE_ID_JOYPAD_R },
{ "input_player2_left", "input_player2_left_btn", "input_player2_left_axis", SNES_DEVICE_ID_JOYPAD_LEFT },
{ "input_player2_right", "input_player2_right_btn", "input_player2_right_axis", SNES_DEVICE_ID_JOYPAD_RIGHT },
{ "input_player2_up", "input_player2_up_btn", "input_player2_up_axis", SNES_DEVICE_ID_JOYPAD_UP },
{ "input_player2_down", "input_player2_down_btn", "input_player2_down_axis", SNES_DEVICE_ID_JOYPAD_DOWN },
{ "input_toggle_fast_forward", "input_toggle_fast_forward_btn", NULL, SSNES_FAST_FORWARD_KEY }
DECLARE_BIND(player2_a, SNES_DEVICE_ID_JOYPAD_A)
DECLARE_BIND(player2_b, SNES_DEVICE_ID_JOYPAD_B)
DECLARE_BIND(player2_y, SNES_DEVICE_ID_JOYPAD_Y)
DECLARE_BIND(player2_x, SNES_DEVICE_ID_JOYPAD_X)
DECLARE_BIND(player2_start, SNES_DEVICE_ID_JOYPAD_START)
DECLARE_BIND(player2_select, SNES_DEVICE_ID_JOYPAD_SELECT)
DECLARE_BIND(player2_l, SNES_DEVICE_ID_JOYPAD_L)
DECLARE_BIND(player2_r, SNES_DEVICE_ID_JOYPAD_R)
DECLARE_BIND(player2_left, SNES_DEVICE_ID_JOYPAD_LEFT)
DECLARE_BIND(player2_right, SNES_DEVICE_ID_JOYPAD_RIGHT)
DECLARE_BIND(player2_up, SNES_DEVICE_ID_JOYPAD_UP)
DECLARE_BIND(player2_down, SNES_DEVICE_ID_JOYPAD_DOWN)
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.
// 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[] = {
{ "left", SDLK_LEFT },
{ "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_NONBLOCKING 2048 // So we don't get complete line-noise when fast-forwarding audio.
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 syncing_state = false;
@ -426,21 +426,24 @@ int main(int argc, char *argv[])
}
#endif
// Main loop
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))
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);
}
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);
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;
uninit_drivers();

View File

@ -102,7 +102,9 @@
# input_player1_up_btn = 13
# 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_right_axis = +0
# input_player1_up_axis = +1
@ -138,8 +140,8 @@
# input_player2_left_axis = -0
# input_player2_right_axis = +0
# input_player2_up_axis = +1
# input_player2_down_axis = -1
# input_player2_up_axis = -1
# input_player2_down_axis = +1
# Toggles fullscreen.
# input_toggle_fullscreen = f
@ -150,8 +152,7 @@
# Toggles between fast-forwarding and normal speed.
# 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