From 4cc3f7aaabc0d4db22a83a1b2824aa6d4552eeaf Mon Sep 17 00:00:00 2001 From: Themaister Date: Thu, 6 Jan 2011 18:34:11 +0100 Subject: [PATCH] Start moving over to SDL rather than GLFW to minimize dependencies. --- Makefile | 10 +-- config.def.h | 62 +++++++++-------- driver.c | 31 ++++++++- driver.h | 2 + gfx/gl.c | 167 ++++++++------------------------------------ gfx/shader_glsl.c | 31 +++++---- input/sdl.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++ qb/config.libs.sh | 6 +- settings.c | 101 +++++++++++++++------------ ssnes.c | 11 ++- 10 files changed, 352 insertions(+), 240 deletions(-) create mode 100644 input/sdl.c diff --git a/Makefile b/Makefile index 4017c073b5..30cae318a8 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ TARGET = ssnes OBJ = ssnes.o file.o driver.o conf/config_file.o settings.o dynamic.o -LIBS = -lsamplerate +LIBS = -lsamplerate -lSDL DEFINES = ifeq ($(HAVE_RSOUND), 1) @@ -31,9 +31,10 @@ ifeq ($(HAVE_JACK),1) LIBS += -ljack endif -ifeq ($(HAVE_GLFW), 1) - OBJ += gfx/gl.o - LIBS += -lglfw +ifeq ($(HAVE_SDL), 1) + OBJ += gfx/gl.o input/sdl.o + LIBS += $(SDL_LIBS) -lGL + DEFINES += $(SDL_CFLAGS) endif ifeq ($(HAVE_CG), 1) @@ -93,6 +94,7 @@ clean: rm -f audio/*.o rm -f conf/*.o rm -f gfx/*.o + rm -f record/*.o rm -f hqflt/*.o rm -f hqflt/snes_ntsc/*.o rm -f $(TARGET) diff --git a/config.def.h b/config.def.h index 0bf44024f2..a30f08adc0 100644 --- a/config.def.h +++ b/config.def.h @@ -22,7 +22,7 @@ #ifndef __CONFIG_DEF_H #define __CONFIG_DEF_H -#include +#include #include #include "libsnes.hpp" #include "driver.h" @@ -39,9 +39,12 @@ #define AUDIO_AL 5 #define AUDIO_JACK 6 //////////////////////// +#define INPUT_SDL 7 +//////////////////////// #define VIDEO_DEFAULT_DRIVER VIDEO_GL #define AUDIO_DEFAULT_DRIVER AUDIO_ALSA +#define INPUT_DEFAULT_DRIVER INPUT_SDL //////////////// @@ -115,48 +118,47 @@ static const bool audio_sync = true; // Player 1 static const struct snes_keybind snes_keybinds_1[] = { // SNES button | keyboard key | js btn | js axis | - { SNES_DEVICE_ID_JOYPAD_A, 'X', 1, AXIS_NONE }, - { SNES_DEVICE_ID_JOYPAD_B, 'Z', 0, AXIS_NONE }, - { SNES_DEVICE_ID_JOYPAD_X, 'S', 3, AXIS_NONE }, - { SNES_DEVICE_ID_JOYPAD_Y, 'A', 2, AXIS_NONE }, - { SNES_DEVICE_ID_JOYPAD_L, 'Q', 4, AXIS_NONE }, - { SNES_DEVICE_ID_JOYPAD_R, 'W', 5, AXIS_NONE }, - { SNES_DEVICE_ID_JOYPAD_LEFT, GLFW_KEY_LEFT, 11, AXIS_NEG(0) }, - { SNES_DEVICE_ID_JOYPAD_RIGHT, GLFW_KEY_RIGHT, 12, AXIS_POS(0) }, - { SNES_DEVICE_ID_JOYPAD_UP, GLFW_KEY_UP, 13, AXIS_POS(1) }, - { SNES_DEVICE_ID_JOYPAD_DOWN, GLFW_KEY_DOWN, 14, AXIS_NEG(1) }, - { SNES_DEVICE_ID_JOYPAD_START, GLFW_KEY_ENTER, 7, AXIS_NONE }, - { SNES_DEVICE_ID_JOYPAD_SELECT, GLFW_KEY_RSHIFT, 6, AXIS_NONE }, - { SSNES_FAST_FORWARD_KEY, GLFW_KEY_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_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 }, { -1 } }; // Player 2 static const struct snes_keybind snes_keybinds_2[] = { // SNES button | keyboard key | js btn | js axis | - { SNES_DEVICE_ID_JOYPAD_A, 'B', 1, AXIS_NONE }, - { SNES_DEVICE_ID_JOYPAD_B, 'V', 0, AXIS_NONE }, - { SNES_DEVICE_ID_JOYPAD_X, 'G', 3, AXIS_NONE }, - { SNES_DEVICE_ID_JOYPAD_Y, 'F', 2, AXIS_NONE }, - { SNES_DEVICE_ID_JOYPAD_L, 'R', 4, AXIS_NONE }, - { SNES_DEVICE_ID_JOYPAD_R, 'T', 5, AXIS_NONE }, - { SNES_DEVICE_ID_JOYPAD_LEFT, 'J', 11, AXIS_NEG(0) }, - { SNES_DEVICE_ID_JOYPAD_RIGHT, 'L', 12, AXIS_POS(0) }, - { SNES_DEVICE_ID_JOYPAD_UP, 'I', 13, AXIS_POS(1) }, - { SNES_DEVICE_ID_JOYPAD_DOWN, 'K', 14, AXIS_NEG(1) }, - { SNES_DEVICE_ID_JOYPAD_START, 'P', 6, AXIS_NONE }, - { SNES_DEVICE_ID_JOYPAD_SELECT, 'O', 7, AXIS_NONE }, + { SNES_DEVICE_ID_JOYPAD_A, SDLK_b, 1, AXIS_NONE }, + { SNES_DEVICE_ID_JOYPAD_B, SDLK_v, 0, AXIS_NONE }, + { SNES_DEVICE_ID_JOYPAD_X, SDLK_g, 3, AXIS_NONE }, + { SNES_DEVICE_ID_JOYPAD_Y, SDLK_f, 2, AXIS_NONE }, + { SNES_DEVICE_ID_JOYPAD_L, SDLK_r, 4, 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_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_START, SDLK_p, 6, AXIS_NONE }, + { SNES_DEVICE_ID_JOYPAD_SELECT, SDLK_o, 7, AXIS_NONE }, { -1 } }; ///// Save state -#define SAVE_STATE_KEY GLFW_KEY_F2 +#define SAVE_STATE_KEY SDLK_F2 ///// Load state -#define LOAD_STATE_KEY GLFW_KEY_F4 +#define LOAD_STATE_KEY SDLK_F4 //// Toggles between fullscreen and windowed mode. -#define TOGGLE_FULLSCREEN 'F' - +#define TOGGLE_FULLSCREEN SDLK_f #endif diff --git a/driver.c b/driver.c index 4e694af930..656f869006 100644 --- a/driver.c +++ b/driver.c @@ -50,6 +50,12 @@ static const video_driver_t *video_drivers[] = { #endif }; +static const input_driver_t *input_drivers[] = { +#ifdef HAVE_SDL + &input_sdl, +#endif +}; + static void find_audio_driver(void) { for (int i = 0; i < sizeof(audio_drivers) / sizeof(audio_driver_t*); i++) @@ -86,6 +92,24 @@ static void find_video_driver(void) exit(1); } +static void find_input_driver(void) +{ + for (int i = 0; i < sizeof(input_drivers) / sizeof(input_driver_t*); i++) + { + if (strcasecmp(g_settings.input.driver, input_drivers[i]->ident) == 0) + { + driver.input = input_drivers[i]; + return; + } + } + SSNES_ERR("Couldn't find any input driver named \"%s\"\n", g_settings.input.driver); + fprintf(stderr, "Available video drivers are:\n"); + for (int i = 0; i < sizeof(input_drivers) / sizeof(input_driver_t*); i++) + fprintf(stderr, "\t%s\n", video_drivers[i]->ident); + + exit(1); +} + void init_drivers(void) { init_video_input(); @@ -141,6 +165,7 @@ void init_video_input(void) int scale = 2; find_video_driver(); + find_input_driver(); // We multiply scales with 2 to allow for hi-res games. #if HAVE_FILTER @@ -177,18 +202,22 @@ void init_video_input(void) exit(1); } + // Video driver also provides an input driver. if ( driver.input != NULL ) { driver.input_data = driver.video_data; } - else + else // We use our configured input driver. { driver.input = tmp; if (driver.input != NULL) { driver.input_data = driver.input->init(); if ( driver.input_data == NULL ) + { + SSNES_ERR("Cannot init input driver. Exiting ...\n"); exit(1); + } } else { diff --git a/driver.h b/driver.h index 0deb3672d7..9d8a0f55b7 100644 --- a/driver.h +++ b/driver.h @@ -65,6 +65,7 @@ typedef struct input_driver void* (*init)(void); void (*poll)(void* data); int16_t (*input_state)(void* data, const struct snes_keybind **snes_keybinds, bool port, unsigned device, unsigned index, unsigned id); + bool (*key_pressed)(void* data, int key); void (*free)(void* data); const char *ident; } input_driver_t; @@ -108,6 +109,7 @@ extern const audio_driver_t audio_roar; extern const audio_driver_t audio_openal; extern const audio_driver_t audio_jack; extern const video_driver_t video_gl; +extern const input_driver_t input_sdl; //////////////////////////////////////////////// #endif diff --git a/gfx/gl.c b/gfx/gl.c index 04d8606c2e..44dd7f7346 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -15,11 +15,9 @@ * If not, see . */ -#define GL_GLEXT_PROTOTYPES #include "driver.h" -#include -#include + #include #include "libsnes.hpp" #include @@ -28,6 +26,12 @@ #include "general.h" #include "config.h" +#define NO_SDL_GLEXT +#include +#include + +#define GL_GLEXT_PROTOTYPES +#include #ifdef HAVE_CG #include "shader_cg.h" @@ -66,110 +70,6 @@ typedef struct gl } gl_t; -static void glfw_input_poll(void *data) -{ - (void)data; - glfwPollEvents(); -} - -#define BUTTONS_MAX 128 -#define AXES_MAX 128 - -static unsigned joypad_id[2]; -static unsigned joypad_buttons[2]; -static unsigned joypad_axes[2]; -static bool joypad_inited = false; -static unsigned joypad_count = 0; - -static int init_joypads(int max_pads) -{ - // Finds the first (two) joypads that are alive - int count = 0; - for ( int i = GLFW_JOYSTICK_1; (i <= GLFW_JOYSTICK_LAST) && (count < max_pads); i++ ) - { - if ( glfwGetJoystickParam(i, GLFW_PRESENT) == GL_TRUE ) - { - joypad_id[count] = i; - joypad_buttons[count] = glfwGetJoystickParam(i, GLFW_BUTTONS); - if (joypad_buttons[count] > BUTTONS_MAX) - joypad_buttons[count] = BUTTONS_MAX; - joypad_axes[count] = glfwGetJoystickParam(i, GLFW_AXES); - if (joypad_axes[count] > AXES_MAX) - joypad_axes[count] = AXES_MAX; - count++; - } - } - joypad_inited = true; - return count; -} - -static bool glfw_is_pressed(int port_num, const struct snes_keybind *key, unsigned char *buttons, float *axes) -{ - if (glfwGetKey(key->key)) - return true; - if (port_num >= joypad_count) - return false; - if (key->joykey < joypad_buttons[port_num] && buttons[key->joykey] == GLFW_PRESS) - return true; - - if (key->joyaxis != AXIS_NONE) - { - if (AXIS_NEG_GET(key->joyaxis) < joypad_axes[port_num] && axes[AXIS_NEG_GET(key->joyaxis)] <= -g_settings.input.axis_threshold) - return true; - if (AXIS_POS_GET(key->joyaxis) < joypad_axes[port_num] && axes[AXIS_POS_GET(key->joyaxis)] >= g_settings.input.axis_threshold) - return true; - } - return false; -} - -static int16_t glfw_input_state(void *data, const struct snes_keybind **binds, bool port, unsigned device, unsigned index, unsigned id) -{ - if ( device != SNES_DEVICE_JOYPAD ) - return 0; - - if ( !joypad_inited ) - joypad_count = init_joypads(2); - - int port_num = port ? 1 : 0; - unsigned char buttons[BUTTONS_MAX]; - float axes[AXES_MAX]; - - if ( joypad_count > port_num ) - { - glfwGetJoystickButtons(joypad_id[port_num], buttons, joypad_buttons[port_num]); - glfwGetJoystickPos(joypad_id[port_num], axes, joypad_axes[port_num]); - } - - - const struct snes_keybind *snes_keybinds; - if (port == SNES_PORT_1) - snes_keybinds = binds[0]; - else - snes_keybinds = binds[1]; - - // Checks if button is pressed, and sets fast-forwarding state - bool pressed = false; - for ( int i = 0; snes_keybinds[i].id != -1; i++ ) - if ( snes_keybinds[i].id == SSNES_FAST_FORWARD_KEY ) - set_fast_forward_button(glfw_is_pressed(port_num, &snes_keybinds[i], buttons, axes)); - else if ( !pressed && snes_keybinds[i].id == (int)id ) - pressed = glfw_is_pressed(port_num, &snes_keybinds[i], buttons, axes); - - return pressed; -} - -static void glfw_free_input(void *data) -{ - free(data); -} - -static const input_driver_t input_glfw = { - .poll = glfw_input_poll, - .input_state = glfw_input_state, - .free = glfw_free_input, - .ident = "glfw" -}; - static inline bool gl_shader_init(void) { if (strlen(g_settings.video.cg_shader_path) > 0 && strlen(g_settings.video.bsnes_shader_path) > 0) @@ -225,7 +125,7 @@ static inline void gl_shader_set_params(unsigned width, unsigned height, #define SNES_ASPECT_RATIO (4.0/3) -static void GLFWCALL resize(int width, int height) +static void set_viewport(int width, int height) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -273,7 +173,7 @@ static float tv_to_fps(const struct timeval *tv, const struct timeval *new_tv, i return frames/time; } -static inline void show_fps(void) +static void show_fps(void) { // Shows FPS in taskbar. static int frames = 0; @@ -292,8 +192,8 @@ static inline void show_fps(void) float fps = tv_to_fps(&tmp_tv, &new_tv, 180); - snprintf(tmpstr, sizeof(tmpstr) - 1, "SSNES || FPS: %6.1f || Frames: %d", fps, frames); - glfwSetWindowTitle(tmpstr); + snprintf(tmpstr, sizeof(tmpstr), "SSNES || FPS: %6.1f || Frames: %d", fps, frames); + SDL_WM_SetCaption(tmpstr, NULL); } frames++; } @@ -335,7 +235,7 @@ static bool gl_frame(void *data, const uint16_t* frame, int width, int height, i glDrawArrays(GL_QUADS, 0, 4); show_fps(); - glfwSwapBuffers(); + SDL_GL_SwapBuffers(); return true; } @@ -348,7 +248,7 @@ static void gl_free(void *data) glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDeleteTextures(1, &gl->texture); - glfwTerminate(); + SDL_QuitSubSystem(SDL_INIT_VIDEO); } static void gl_set_nonblock_state(void *data, bool state) @@ -356,15 +256,22 @@ static void gl_set_nonblock_state(void *data, bool state) gl_t *gl = data; if (gl->vsync) { - if (state) - glfwSwapInterval(0); - else - glfwSwapInterval(1); + SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, state ? 0 : 1); + //SDL_SetVideoMode(gl->width, gl->height, 32, SDL_OPENGL | (video->fullscreen ? SDL_FULLSCREEN : 0)); } } static void* gl_init(video_info_t *video, const input_driver_t **input) { + if (SDL_Init(SDL_INIT_VIDEO) < 0) + return NULL; + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, video->vsync ? 1 : 0); + + if (!SDL_SetVideoMode(video->width, video->height, 32, SDL_OPENGL | (video->fullscreen ? SDL_FULLSCREEN : 0))) + return NULL; + gl_t *gl = calloc(1, sizeof(gl_t)); if ( gl == NULL ) return NULL; @@ -375,25 +282,7 @@ static void* gl_init(video_info_t *video, const input_driver_t **input) else gl->tex_filter = GL_NEAREST; - glfwInit(); - - int res; - res = glfwOpenWindow(video->width, video->height, 0, 0, 0, 0, 0, 0, (video->fullscreen) ? GLFW_FULLSCREEN : GLFW_WINDOW); - - if (!res) - { - glfwTerminate(); - free(gl); - return NULL; - } - - glfwSetWindowSizeCallback(resize); - - if ( video->vsync ) - glfwSwapInterval(1); // Force vsync - else - glfwSwapInterval(0); - gl->vsync = video->vsync; + set_viewport(video->width, video->height); glEnable(GL_TEXTURE_2D); glDisable(GL_DITHER); @@ -401,7 +290,7 @@ static void* gl_init(video_info_t *video, const input_driver_t **input) glColor3f(1, 1, 1); glClearColor(0, 0, 0, 0); - glfwSetWindowTitle("SSNES"); + SDL_WM_SetCaption("SSNES", NULL); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -434,7 +323,7 @@ static void* gl_init(video_info_t *video, const input_driver_t **input) gl_shader_init(); - *input = &input_glfw; + *input = NULL; return gl; } @@ -443,7 +332,7 @@ const video_driver_t video_gl = { .frame = gl_frame, .set_nonblock_state = gl_set_nonblock_state, .free = gl_free, - .ident = "glfw" + .ident = "gl" }; diff --git a/gfx/shader_glsl.c b/gfx/shader_glsl.c index 5e2ea1a8e3..4a5af0b8ef 100644 --- a/gfx/shader_glsl.c +++ b/gfx/shader_glsl.c @@ -23,8 +23,11 @@ #include #include "general.h" +#define NO_SDL_GLEXT #include -#include +//#include +#include +#include #include #include #include @@ -135,19 +138,19 @@ error: bool gl_glsl_init(const char *path) { // Load shader functions. - glCreateProgram = glfwGetProcAddress("glCreateProgram"); - glUseProgram = glfwGetProcAddress("glUseProgram"); - glCreateShader = glfwGetProcAddress("glCreateShader"); - glDeleteShader = glfwGetProcAddress("glDeleteShader"); - glShaderSource = glfwGetProcAddress("glShaderSource"); - glCompileShader = glfwGetProcAddress("glCompileShader"); - glAttachShader = glfwGetProcAddress("glAttachShader"); - glDetachShader = glfwGetProcAddress("glDetachShader"); - glLinkProgram = glfwGetProcAddress("glLinkProgram"); - glGetUniformLocation = glfwGetProcAddress("glGetUniformLocation"); - glUniform1i = glfwGetProcAddress("glUniform1i"); - glUniform2fv = glfwGetProcAddress("glUniform2fv"); - glUniform4fv = glfwGetProcAddress("glUniform4fv"); + glCreateProgram = SDL_GL_GetProcAddress("glCreateProgram"); + glUseProgram = SDL_GL_GetProcAddress("glUseProgram"); + glCreateShader = SDL_GL_GetProcAddress("glCreateShader"); + glDeleteShader = SDL_GL_GetProcAddress("glDeleteShader"); + glShaderSource = SDL_GL_GetProcAddress("glShaderSource"); + glCompileShader = SDL_GL_GetProcAddress("glCompileShader"); + glAttachShader = SDL_GL_GetProcAddress("glAttachShader"); + glDetachShader = SDL_GL_GetProcAddress("glDetachShader"); + glLinkProgram = SDL_GL_GetProcAddress("glLinkProgram"); + glGetUniformLocation = SDL_GL_GetProcAddress("glGetUniformLocation"); + glUniform1i = SDL_GL_GetProcAddress("glUniform1i"); + glUniform2fv = SDL_GL_GetProcAddress("glUniform2fv"); + glUniform4fv = SDL_GL_GetProcAddress("glUniform4fv"); SSNES_LOG("Checking GLSL shader support ...\n"); bool shader_support = glCreateProgram && glUseProgram && glCreateShader diff --git a/input/sdl.c b/input/sdl.c new file mode 100644 index 0000000000..68c4c058ac --- /dev/null +++ b/input/sdl.c @@ -0,0 +1,171 @@ +/* SSNES - A Super Ninteno Entertainment System (SNES) Emulator frontend for libsnes. + * Copyright (C) 2010 - Hans-Kristian Arntzen + * + * Some code herein may be based on code found in BSNES. + * + * SSNES 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 Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SSNES 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 SSNES. + * If not, see . + */ + +#include "driver.h" + +#include +#include +#include "general.h" +#include +#include +#include + +typedef struct sdl_input +{ + bool quitting; + SDL_Joystick *joysticks[2]; + unsigned num_axes[2]; + unsigned num_buttons[2]; + unsigned num_joysticks; +} sdl_input_t; + +static void* sdl_input_init(void) +{ + sdl_input_t *sdl = calloc(1, sizeof(*sdl)); + if (!sdl) + return NULL; + + if (SDL_Init(SDL_INIT_JOYSTICK) < 0) + return NULL; + + sdl->num_joysticks = SDL_NumJoysticks(); + for (unsigned i = 0; i < sdl->num_joysticks; i++) + { + sdl->joysticks[i] = SDL_JoystickOpen(i); + if (!sdl->joysticks[i]) + { + SSNES_ERR("Couldn't open SDL joystick %d\n", i); + free(sdl); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + return NULL; + } + + SSNES_LOG("Opened Joystick: %s\n", SDL_JoystickName(i)); + sdl->num_axes[i] = SDL_JoystickNumAxes(sdl->joysticks[i]); + sdl->num_buttons[i] = SDL_JoystickNumButtons(sdl->joysticks[i]); + } + + return sdl; +} + +static bool sdl_key_pressed(void *data, int key) +{ + // Check to see if we have to exit. + sdl_input_t *sdl = data; + if (sdl->quitting && key == g_settings.input.exit_emulator_key) + return true; + + int num_keys; + Uint8 *keymap = SDL_GetKeyState(&num_keys); + + if (key >= num_keys) + return false; + + return keymap[key]; +} + +static bool sdl_is_pressed(sdl_input_t *sdl, int port_num, const struct snes_keybind *key) +{ + if (sdl_key_pressed(sdl, key->key)) + return true; + if (port_num >= sdl->num_joysticks) + return false; + if (key->joykey < sdl->num_buttons[port_num] && SDL_JoystickGetButton(sdl->joysticks[port_num], key->joykey)) + return true; + + if (key->joyaxis != AXIS_NONE) + { + if (AXIS_NEG_GET(key->joyaxis) < sdl->num_axes[port_num]) + { + Sint16 val = SDL_JoystickGetAxis(sdl->joysticks[port_num], AXIS_NEG_GET(key->joyaxis)); + float scaled = (float)val / 0x8000; + if (scaled < -g_settings.input.axis_threshold) + return true; + } + if (AXIS_POS_GET(key->joyaxis) < sdl->num_axes[port_num]) + { + Sint16 val = SDL_JoystickGetAxis(sdl->joysticks[port_num], AXIS_NEG_GET(key->joyaxis)); + float scaled = (float)val / 0x8000; + if (scaled > g_settings.input.axis_threshold) + return true; + } + } + + 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; + if (device != SNES_DEVICE_JOYPAD) + return 0; + + 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; + 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]); + } + + return pressed; +} + +static void sdl_input_free(void *data) +{ + if (data) + { + sdl_input_t *sdl = data; + for (int i = 0; i < sdl->num_joysticks; i++) + SDL_JoystickClose(i); + + free(data); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + } +} + +static void sdl_input_poll(void *data) +{ + SDL_PumpEvents(); + SDL_Event event; + + // Search for SDL_QUIT + while (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + sdl_input_t *sdl = data; + sdl->quitting = true; + break; + } + } +} + +const input_driver_t input_sdl = { + .init = sdl_input_init, + .poll = sdl_input_poll, + .input_state = sdl_input_state, + .key_pressed = sdl_key_pressed, + .free = sdl_input_free, + .ident = "sdl" +}; + diff --git a/qb/config.libs.sh b/qb/config.libs.sh index 20ad85e671..a5e0b281f4 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -16,8 +16,8 @@ check_lib RSOUND -lrsound rsd_init check_lib ROAR -lroar roar_vs_new check_lib JACK -ljack jack_client_open -check_lib GLFW -lglfw glfwInit -check_critical GLFW "Cannot find GLFW library." +check_pkgconf SDL SDL_gfx +check_critical SDL "Cannot find SDL library." check_lib CG -lCg cgCreateContext check_pkgconf XML libxml-2.0 @@ -37,7 +37,7 @@ check_lib SRC -lsamplerate src_callback_new check_lib DYNAMIC -ldl dlopen # Creates config.mk and config.h. -VARS="ALSA OSS AL RSOUND ROAR JACK GLFW FILTER CG XML DYNAMIC FFMPEG AVCODEC AVFORMAT AVCORE AVUTIL SWSCALE" +VARS="ALSA OSS AL RSOUND ROAR JACK SDL FILTER CG XML DYNAMIC FFMPEG AVCODEC AVFORMAT AVCORE AVUTIL SWSCALE" create_config_make config.mk $VARS create_config_header config.h $VARS diff --git a/settings.c b/settings.c index 71b7c1be82..3bcf33db48 100644 --- a/settings.c +++ b/settings.c @@ -32,11 +32,12 @@ static void set_defaults(void) { const char *def_video = NULL; const char *def_audio = NULL; + const char *def_input = NULL; switch (VIDEO_DEFAULT_DRIVER) { case VIDEO_GL: - def_video = "glfw"; + def_video = "gl"; break; default: break; @@ -63,12 +64,23 @@ static void set_defaults(void) break; } + switch (INPUT_DEFAULT_DRIVER) + { + case INPUT_SDL: + def_input = "sdl"; + break; + default: + break; + } + // No input atm ... It is in the GLFW driver. if (def_video) strncpy(g_settings.video.driver, def_video, sizeof(g_settings.video.driver) - 1); if (def_audio) strncpy(g_settings.audio.driver, def_audio, sizeof(g_settings.audio.driver) - 1); + if (def_input) + strncpy(g_settings.input.driver, def_input, sizeof(g_settings.input.driver) - 1); g_settings.video.xscale = xscale; g_settings.video.yscale = yscale; @@ -97,7 +109,7 @@ static void set_defaults(void) 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 = GLFW_KEY_ESC; + g_settings.input.exit_emulator_key = SDLK_ESCAPE; } void parse_config(void) @@ -261,6 +273,11 @@ void parse_config(void) strncpy(g_settings.audio.driver, tmp_str, sizeof(g_settings.audio.driver) - 1); free(tmp_str); } + if (config_get_string(conf, "input_driver", &tmp_str)) + { + strncpy(g_settings.input.driver, tmp_str, sizeof(g_settings.input.driver) - 1); + free(tmp_str); + } if (config_get_string(conf, "libsnes_path", &tmp_str)) { strncpy(g_settings.libsnes, tmp_str, sizeof(g_settings.libsnes) - 1); @@ -314,40 +331,40 @@ static const struct bind_map bind_maps[2][13] = { } }; -struct glfw_map +struct key_map { const char *str; int key; }; // Edit: Not portable to different input systems atm. Might move this map into the driver itself or something. -static const struct glfw_map glfw_map[] = { - { "left", GLFW_KEY_LEFT }, - { "right", GLFW_KEY_RIGHT }, - { "up", GLFW_KEY_UP }, - { "down", GLFW_KEY_DOWN }, - { "enter", GLFW_KEY_ENTER }, - { "tab", GLFW_KEY_TAB }, - { "insert", GLFW_KEY_INSERT }, - { "del", GLFW_KEY_DEL }, - { "rshift", GLFW_KEY_RSHIFT }, - { "shift", GLFW_KEY_LSHIFT }, - { "ctrl", GLFW_KEY_LCTRL }, - { "alt", GLFW_KEY_LALT }, - { "space", GLFW_KEY_SPACE }, - { "escape", GLFW_KEY_ESC }, - { "f1", GLFW_KEY_F1 }, - { "f2", GLFW_KEY_F2 }, - { "f3", GLFW_KEY_F3 }, - { "f4", GLFW_KEY_F4 }, - { "f5", GLFW_KEY_F5 }, - { "f6", GLFW_KEY_F6 }, - { "f7", GLFW_KEY_F7 }, - { "f8", GLFW_KEY_F8 }, - { "f9", GLFW_KEY_F9 }, - { "f10", GLFW_KEY_F10 }, - { "f11", GLFW_KEY_F11 }, - { "f12", GLFW_KEY_F12 }, +static const struct key_map sdlk_map[] = { + { "left", SDLK_LEFT }, + { "right", SDLK_RIGHT }, + { "up", SDLK_UP }, + { "down", SDLK_DOWN }, + { "enter", SDLK_RETURN }, + { "tab", SDLK_TAB }, + { "insert", SDLK_INSERT }, + { "del", SDLK_DELETE }, + { "rshift", SDLK_RSHIFT }, + { "shift", SDLK_LSHIFT }, + { "ctrl", SDLK_LCTRL }, + { "alt", SDLK_LALT }, + { "space", SDLK_SPACE }, + { "escape", SDLK_ESCAPE }, + { "f1", SDLK_F1 }, + { "f2", SDLK_F2 }, + { "f3", SDLK_F3 }, + { "f4", SDLK_F4 }, + { "f5", SDLK_F5 }, + { "f6", SDLK_F6 }, + { "f7", SDLK_F7 }, + { "f8", SDLK_F8 }, + { "f9", SDLK_F9 }, + { "f10", SDLK_F10 }, + { "f11", SDLK_F11 }, + { "f12", SDLK_F12 }, }; static struct snes_keybind *find_snes_bind(unsigned port, int id) @@ -362,23 +379,23 @@ static struct snes_keybind *find_snes_bind(unsigned port, int id) return NULL; } -static int find_glfw_bind(const char *str) +static int find_sdlk_bind(const char *str) { - for (int i = 0; i < sizeof(glfw_map)/sizeof(struct glfw_map); i++) + for (int i = 0; i < sizeof(sdlk_map)/sizeof(struct key_map); i++) { - if (strcasecmp(glfw_map[i].str, str) == 0) - return glfw_map[i].key; + if (strcasecmp(sdlk_map[i].str, str) == 0) + return sdlk_map[i].key; } return -1; } -static int find_glfw_key(const char *str) +static int find_sdlk_key(const char *str) { // If the bind is a normal key-press ... if (strlen(str) == 1 && isalpha(*str)) - return toupper(*str); + return (int)SDLK_a + (tolower(*str) - (int)'a'); else // Check if we have a special mapping for it. - return find_glfw_bind(str); + return find_sdlk_bind(str); } static void read_keybinds(config_file_t *conf) @@ -397,7 +414,7 @@ static void read_keybinds(config_file_t *conf) if (bind_maps[j][i].key && config_get_string(conf, bind_maps[j][i].key, &tmp_key)) { - int key = find_glfw_key(tmp_key); + int key = find_sdlk_key(tmp_key); if (key >= 0) bind->key = key; @@ -432,28 +449,28 @@ static void read_keybinds(config_file_t *conf) char *tmp_str; if (config_get_string(conf, "input_toggle_fullscreen", &tmp_str)) { - int key = find_glfw_key(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_glfw_key(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_glfw_key(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_glfw_key(tmp_str); + int key = find_sdlk_key(tmp_str); if (key >= 0) g_settings.input.exit_emulator_key = key; free(tmp_str); diff --git a/ssnes.c b/ssnes.c index eae767bddd..75ffc0da2d 100644 --- a/ssnes.c +++ b/ssnes.c @@ -17,7 +17,6 @@ #include -#include #include #include #include @@ -421,20 +420,18 @@ int main(int argc, char *argv[]) ///// TODO: Modular friendly!!! for(;;) { - bool quitting = glfwGetKey(g_settings.input.exit_emulator_key) || !glfwGetWindowParam(GLFW_OPENED); - - if ( quitting ) + if (driver.input->key_pressed(driver.input_data, g_settings.input.exit_emulator_key)) break; - if ( glfwGetKey( g_settings.input.save_state_key )) + if (driver.input->key_pressed(driver.input_data, g_settings.input.save_state_key)) { write_file(statefile_name, serial_data, serial_size); } - else if ( glfwGetKey( g_settings.input.load_state_key ) ) + else if (driver.input->key_pressed(driver.input_data, g_settings.input.load_state_key)) load_state(statefile_name, serial_data, serial_size); - else if ( glfwGetKey( g_settings.input.toggle_fullscreen_key ) ) + else if (driver.input->key_pressed(driver.input_data, g_settings.input.toggle_fullscreen_key)) { g_settings.video.fullscreen = !g_settings.video.fullscreen; uninit_drivers();