mirror of
https://github.com/libretro/RetroArch
synced 2024-12-29 12:31:05 +00:00
Start moving over to SDL rather than GLFW to minimize dependencies.
This commit is contained in:
parent
889924283f
commit
4cc3f7aaab
10
Makefile
10
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)
|
||||
|
62
config.def.h
62
config.def.h
@ -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
|
||||
|
31
driver.c
31
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
|
||||
{
|
||||
|
2
driver.h
2
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
|
||||
|
167
gfx/gl.c
167
gfx/gl.c
@ -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"
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
171
input/sdl.c
Normal 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"
|
||||
};
|
||||
|
@ -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
|
||||
|
||||
|
101
settings.c
101
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);
|
||||
|
11
ssnes.c
11
ssnes.c
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user