Start moving over to SDL rather than GLFW to minimize dependencies.

This commit is contained in:
Themaister 2011-01-06 18:34:11 +01:00
parent 889924283f
commit 4cc3f7aaab
10 changed files with 352 additions and 240 deletions

View File

@ -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)

View File

@ -22,7 +22,7 @@
#ifndef __CONFIG_DEF_H
#define __CONFIG_DEF_H
#include <GL/glfw.h>
#include <SDL/SDL.h>
#include <stdbool.h>
#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

View File

@ -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
{

View File

@ -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

167
gfx/gl.c
View File

@ -15,11 +15,9 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#define GL_GLEXT_PROTOTYPES
#include "driver.h"
#include <GL/glfw.h>
#include <GL/glext.h>
#include <stdint.h>
#include "libsnes.hpp"
#include <stdio.h>
@ -28,6 +26,12 @@
#include "general.h"
#include "config.h"
#define NO_SDL_GLEXT
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#define GL_GLEXT_PROTOTYPES
#include <GL/glext.h>
#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"
};

View File

@ -23,8 +23,11 @@
#include <string.h>
#include "general.h"
#define NO_SDL_GLEXT
#include <GL/gl.h>
#include <GL/glfw.h>
//#include <GL/glfw.h>
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <stdlib.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
@ -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

171
input/sdl.c Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "driver.h"
#include <SDL/SDL.h>
#include <stdbool.h>
#include "general.h"
#include <stdint.h>
#include <stdlib.h>
#include <libsnes.hpp>
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"
};

View File

@ -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

View File

@ -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);

11
ssnes.c
View File

@ -17,7 +17,6 @@
#include <stdbool.h>
#include <GL/glfw.h>
#include <samplerate.h>
#include <libsnes.hpp>
#include <stdio.h>
@ -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();