Start on XVideo
This commit is contained in:
parent
bb79dbaa98
commit
adfd461c3e
5
Makefile
5
Makefile
|
@ -72,6 +72,11 @@ else
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(HAVE_XVIDEO), 1)
|
||||||
|
OBJ += gfx/xvideo.o input/x11_input.o
|
||||||
|
LIBS += -lXv -lX11
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(HAVE_CG), 1)
|
ifeq ($(HAVE_CG), 1)
|
||||||
OBJ += gfx/shader_cg.o
|
OBJ += gfx/shader_cg.o
|
||||||
LIBS += -lCg -lCgGL
|
LIBS += -lCg -lCgGL
|
||||||
|
|
10
config.def.h
10
config.def.h
|
@ -43,6 +43,7 @@
|
||||||
|
|
||||||
///////////////// Drivers
|
///////////////// Drivers
|
||||||
#define VIDEO_GL 0
|
#define VIDEO_GL 0
|
||||||
|
#define VIDEO_XVIDEO 11
|
||||||
////////////////////////
|
////////////////////////
|
||||||
#define AUDIO_RSOUND 1
|
#define AUDIO_RSOUND 1
|
||||||
#define AUDIO_OSS 2
|
#define AUDIO_OSS 2
|
||||||
|
@ -55,9 +56,14 @@
|
||||||
#define AUDIO_PULSE 10
|
#define AUDIO_PULSE 10
|
||||||
////////////////////////
|
////////////////////////
|
||||||
#define INPUT_SDL 7
|
#define INPUT_SDL 7
|
||||||
|
#define INPUT_X 12
|
||||||
////////////////////////
|
////////////////////////
|
||||||
|
|
||||||
|
#if defined(HAVE_SDL)
|
||||||
#define VIDEO_DEFAULT_DRIVER VIDEO_GL
|
#define VIDEO_DEFAULT_DRIVER VIDEO_GL
|
||||||
|
#elif defined(HAVE_XVIDEO)
|
||||||
|
#define VIDEO_DEFAULT_DRIVER VIDEO_XVIDEO
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_ALSA)
|
#if defined(HAVE_ALSA)
|
||||||
#define AUDIO_DEFAULT_DRIVER AUDIO_ALSA
|
#define AUDIO_DEFAULT_DRIVER AUDIO_ALSA
|
||||||
|
@ -81,7 +87,11 @@
|
||||||
#error Need at least one audio driver!
|
#error Need at least one audio driver!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_SDL)
|
||||||
#define INPUT_DEFAULT_DRIVER INPUT_SDL
|
#define INPUT_DEFAULT_DRIVER INPUT_SDL
|
||||||
|
#elif defined(HAVE_XVIDEO)
|
||||||
|
#define INPUT_DEFAULT_DRIVER INPUT_X
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
|
|
6
driver.c
6
driver.c
|
@ -61,12 +61,18 @@ static const video_driver_t *video_drivers[] = {
|
||||||
#ifdef HAVE_SDL
|
#ifdef HAVE_SDL
|
||||||
&video_gl,
|
&video_gl,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_XVIDEO
|
||||||
|
&video_xvideo,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static const input_driver_t *input_drivers[] = {
|
static const input_driver_t *input_drivers[] = {
|
||||||
#ifdef HAVE_SDL
|
#ifdef HAVE_SDL
|
||||||
&input_sdl,
|
&input_sdl,
|
||||||
#endif
|
#endif
|
||||||
|
//#ifdef HAVE_XVIDEO
|
||||||
|
// &input_x,
|
||||||
|
//#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static void find_audio_driver(void)
|
static void find_audio_driver(void)
|
||||||
|
|
2
driver.h
2
driver.h
|
@ -148,7 +148,9 @@ extern const audio_driver_t audio_sdl;
|
||||||
extern const audio_driver_t audio_xa;
|
extern const audio_driver_t audio_xa;
|
||||||
extern const audio_driver_t audio_pulse;
|
extern const audio_driver_t audio_pulse;
|
||||||
extern const video_driver_t video_gl;
|
extern const video_driver_t video_gl;
|
||||||
|
extern const video_driver_t video_xvideo;
|
||||||
extern const input_driver_t input_sdl;
|
extern const input_driver_t input_sdl;
|
||||||
|
extern const input_driver_t input_x;
|
||||||
////////////////////////////////////////////////
|
////////////////////////////////////////////////
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,298 @@
|
||||||
|
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
|
||||||
|
* Copyright (C) 2010-2011 - 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 "general.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
#include <sys/ipc.h>
|
||||||
|
#include <sys/shm.h>
|
||||||
|
#include <X11/extensions/XShm.h>
|
||||||
|
#include <X11/extensions/Xv.h>
|
||||||
|
#include <X11/extensions/Xvlib.h>
|
||||||
|
|
||||||
|
typedef struct xv
|
||||||
|
{
|
||||||
|
Display *display;
|
||||||
|
GC gc;
|
||||||
|
Window window;
|
||||||
|
Colormap colormap;
|
||||||
|
XShmSegmentInfo shminfo;
|
||||||
|
|
||||||
|
int port;
|
||||||
|
int depth;
|
||||||
|
int visualid;
|
||||||
|
|
||||||
|
XvImage *image;
|
||||||
|
|
||||||
|
unsigned width;
|
||||||
|
unsigned height;
|
||||||
|
|
||||||
|
uint8_t *ytable;
|
||||||
|
uint8_t *utable;
|
||||||
|
uint8_t *vtable;
|
||||||
|
} xv_t;
|
||||||
|
|
||||||
|
static void init_yuv_tables(xv_t *xv)
|
||||||
|
{
|
||||||
|
xv->ytable = malloc(0x10000);
|
||||||
|
xv->utable = malloc(0x10000);
|
||||||
|
xv->vtable = malloc(0x10000);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < 0x10000; i++)
|
||||||
|
{
|
||||||
|
// Extract RGB555 color data from i
|
||||||
|
uint8_t r = (i >> 10) & 31, g = (i >> 5) & 31, b = (i) & 31;
|
||||||
|
r = (r << 3) | (r >> 2); //R5->R8
|
||||||
|
g = (g << 3) | (g >> 2); //G5->G8
|
||||||
|
b = (b << 3) | (b >> 2); //B5->B8
|
||||||
|
|
||||||
|
int y = (int)( +((double)r * 0.257) + ((double)g * 0.504) + ((double)b * 0.098) + 16.0 );
|
||||||
|
int u = (int)( -((double)r * 0.148) - ((double)g * 0.291) + ((double)b * 0.439) + 128.0 );
|
||||||
|
int v = (int)( +((double)r * 0.439) - ((double)g * 0.368) - ((double)b * 0.071) + 128.0 );
|
||||||
|
|
||||||
|
xv->ytable[i] = y < 0 ? 0 : y > 255 ? 255 : y;
|
||||||
|
xv->utable[i] = u < 0 ? 0 : u > 255 ? 255 : u;
|
||||||
|
xv->vtable[i] = v < 0 ? 0 : v > 255 ? 255 : v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void render_yuy2(xv_t *xv, const uint16_t *input, unsigned width, unsigned height, unsigned pitch)
|
||||||
|
{
|
||||||
|
uint16_t *output = (uint16_t*)xv->image->data;
|
||||||
|
|
||||||
|
for (unsigned y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
for (unsigned x = 0; x < width >> 1; x++)
|
||||||
|
{
|
||||||
|
uint16_t p0 = *input++;
|
||||||
|
uint16_t p1 = *input++;
|
||||||
|
|
||||||
|
uint8_t u = (xv->utable[p0] + xv->utable[p1]) >> 1;
|
||||||
|
uint8_t v = (xv->vtable[p0] + xv->vtable[p1]) >> 1;
|
||||||
|
|
||||||
|
*output++ = (u << 8) | xv->ytable[p0];
|
||||||
|
*output++ = (v << 8) | xv->ytable[p1];
|
||||||
|
}
|
||||||
|
|
||||||
|
input += (pitch >> 1) - width;
|
||||||
|
output += xv->width - width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* xv_init(video_info_t *video, const input_driver_t **input, void **input_data)
|
||||||
|
{
|
||||||
|
xv_t *xv = calloc(1, sizeof(*xv));
|
||||||
|
if (!xv)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
xv->display = XOpenDisplay(NULL);
|
||||||
|
|
||||||
|
if (!XShmQueryExtension(xv->display))
|
||||||
|
{
|
||||||
|
SSNES_ERR("XVideo: XShm extension not found.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find an appropriate Xv port.
|
||||||
|
xv->port = -1;
|
||||||
|
XvAdaptorInfo *adaptor_info;
|
||||||
|
unsigned adaptor_count = 0;
|
||||||
|
XvQueryAdaptors(xv->display, DefaultRootWindow(xv->display), &adaptor_count, &adaptor_info);
|
||||||
|
for (unsigned i = 0; i < adaptor_count; i++)
|
||||||
|
{
|
||||||
|
// Find adaptor that supports both input (memory->drawable) and image (drawable->screen) masks.
|
||||||
|
if (adaptor_info[i].num_formats < 1) continue;
|
||||||
|
if (!(adaptor_info[i].type & XvInputMask)) continue;
|
||||||
|
if (!(adaptor_info[i].type & XvImageMask)) continue;
|
||||||
|
|
||||||
|
xv->port = adaptor_info[i].base_id;
|
||||||
|
xv->depth = adaptor_info[i].formats->depth;
|
||||||
|
xv->visualid = adaptor_info[i].formats->visual_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
XvFreeAdaptorInfo(adaptor_info);
|
||||||
|
|
||||||
|
if (xv->port < 0)
|
||||||
|
{
|
||||||
|
SSNES_ERR("XVideo: Failed to find valid XvPort.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
XVisualInfo visualtemplate;
|
||||||
|
visualtemplate.visualid = xv->visualid;
|
||||||
|
visualtemplate.screen = DefaultScreen(xv->display);
|
||||||
|
visualtemplate.depth = xv->depth;
|
||||||
|
visualtemplate.visual = 0;
|
||||||
|
int visualmatches = 0;
|
||||||
|
XVisualInfo *visualinfo = XGetVisualInfo(xv->display, VisualIDMask | VisualScreenMask | VisualDepthMask, &visualtemplate, &visualmatches);
|
||||||
|
if (visualmatches < 1 || !visualinfo->visual)
|
||||||
|
{
|
||||||
|
if (visualinfo) XFree(visualinfo);
|
||||||
|
SSNES_ERR("XVideo: Unable to find Xv-compatible visual.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
xv->colormap = XCreateColormap(xv->display, DefaultRootWindow(xv->display), visualinfo->visual, AllocNone);
|
||||||
|
XSetWindowAttributes attributes;
|
||||||
|
attributes.colormap = xv->colormap;
|
||||||
|
attributes.border_pixel = 0;
|
||||||
|
attributes.event_mask = StructureNotifyMask;
|
||||||
|
xv->window = XCreateWindow(xv->display, DefaultRootWindow(xv->display),
|
||||||
|
/* x = */ 0, /* y = */ 0, video->width, video->height,
|
||||||
|
/* border_width = */ 0, xv->depth, InputOutput, visualinfo->visual,
|
||||||
|
CWColormap | CWBorderPixel | CWEventMask, &attributes);
|
||||||
|
XFree(visualinfo);
|
||||||
|
XSetWindowBackground(xv->display, xv->window, /* color = */ 0);
|
||||||
|
XMapWindow(xv->display, xv->window);
|
||||||
|
|
||||||
|
xv->gc = XCreateGC(xv->display, xv->window, 0, 0);
|
||||||
|
|
||||||
|
// Set colorkey to auto paint, so that Xv video output is always visible
|
||||||
|
Atom atom = XInternAtom(xv->display, "XV_AUTOPAINT_COLORKEY", true);
|
||||||
|
if(atom != None) XvSetPortAttribute(xv->display, xv->port, atom, 1);
|
||||||
|
|
||||||
|
int format_count;
|
||||||
|
XvImageFormatValues *format = XvListImageFormats(xv->display, xv->port, &format_count);
|
||||||
|
|
||||||
|
bool has_format = false;
|
||||||
|
uint32_t fourcc = 0;
|
||||||
|
for (int i = 0; i < format_count; i++)
|
||||||
|
{
|
||||||
|
if (format[i].type == XvYUV && format[i].bits_per_pixel == 16 && format[i].format == XvPacked)
|
||||||
|
{
|
||||||
|
if (format[i].component_order[0] == 'Y' && format[i].component_order[1] == 'U'
|
||||||
|
&& format[i].component_order[2] == 'Y' && format[i].component_order[3] == 'V')
|
||||||
|
{
|
||||||
|
has_format = true;
|
||||||
|
fourcc = format[i].id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(format);
|
||||||
|
if(!has_format)
|
||||||
|
{
|
||||||
|
SSNES_ERR("XVideo: unable to find a supported image format.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
xv->width = 256 * video->input_scale;
|
||||||
|
xv->height = 256 * video->input_scale;
|
||||||
|
|
||||||
|
xv->image = XvShmCreateImage(xv->display, xv->port, fourcc, 0, xv->width, xv->height, &xv->shminfo);
|
||||||
|
if(!xv->image)
|
||||||
|
{
|
||||||
|
SSNES_ERR("XVideo: XShmCreateImage failed.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
xv->shminfo.shmid = shmget(IPC_PRIVATE, xv->image->data_size, IPC_CREAT | 0777);
|
||||||
|
xv->shminfo.shmaddr = xv->image->data = shmat(xv->shminfo.shmid, 0, 0);
|
||||||
|
xv->shminfo.readOnly = false;
|
||||||
|
if (!XShmAttach(xv->display, &xv->shminfo))
|
||||||
|
{
|
||||||
|
SSNES_ERR("XVideo: XShmAttach failed.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *xinput = input_x.init();
|
||||||
|
if (xinput)
|
||||||
|
{
|
||||||
|
*input = &input_x;
|
||||||
|
*input_data = xinput;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*input = NULL;
|
||||||
|
|
||||||
|
init_yuv_tables(xv);
|
||||||
|
return xv;
|
||||||
|
|
||||||
|
error:
|
||||||
|
free(xv);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool xv_frame(void *data, const void* frame, unsigned width, unsigned height, unsigned pitch, const char *msg)
|
||||||
|
{
|
||||||
|
(void)msg;
|
||||||
|
xv_t *xv = data;
|
||||||
|
|
||||||
|
XWindowAttributes target;
|
||||||
|
XGetWindowAttributes(xv->display, xv->window, &target);
|
||||||
|
render_yuy2(xv, frame, width, height, pitch);
|
||||||
|
XvShmPutImage(xv->display, xv->port, xv->window, xv->gc, xv->image,
|
||||||
|
0, 0, width, height,
|
||||||
|
0, 0, target.width, target.height,
|
||||||
|
true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool xv_alive(void *data)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool xv_focus(void *data)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xv_set_nonblock_state(void *data, bool state)
|
||||||
|
{
|
||||||
|
xv_t *xv = data;
|
||||||
|
Atom atom = XInternAtom(xv->display, "XV_SYNC_TO_VBLANK", true);
|
||||||
|
if (atom != None && xv->port >= 0)
|
||||||
|
XvSetPortAttribute(xv->display, xv->port, atom, !state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xv_free(void *data)
|
||||||
|
{
|
||||||
|
xv_t *xv = data;
|
||||||
|
XShmDetach(xv->display, &xv->shminfo);
|
||||||
|
shmdt(xv->shminfo.shmaddr);
|
||||||
|
shmctl(xv->shminfo.shmid, IPC_RMID, NULL);
|
||||||
|
XFree(xv->image);
|
||||||
|
|
||||||
|
if(xv->window)
|
||||||
|
XUnmapWindow(xv->display, xv->window);
|
||||||
|
if(xv->colormap)
|
||||||
|
XFreeColormap(xv->display, xv->colormap);
|
||||||
|
|
||||||
|
XCloseDisplay(xv->display);
|
||||||
|
|
||||||
|
free(xv->ytable);
|
||||||
|
free(xv->utable);
|
||||||
|
free(xv->vtable);
|
||||||
|
free(xv);
|
||||||
|
}
|
||||||
|
|
||||||
|
const video_driver_t video_xvideo = {
|
||||||
|
.init = xv_init,
|
||||||
|
.frame = xv_frame,
|
||||||
|
.alive = xv_alive,
|
||||||
|
.set_nonblock_state = xv_set_nonblock_state,
|
||||||
|
.focus = xv_focus,
|
||||||
|
.free = xv_free,
|
||||||
|
.ident = "xvideo"
|
||||||
|
};
|
||||||
|
|
|
@ -248,7 +248,7 @@ static int16_t sdl_input_state(void *data, const struct snes_keybind **binds, bo
|
||||||
switch (device)
|
switch (device)
|
||||||
{
|
{
|
||||||
case SNES_DEVICE_JOYPAD:
|
case SNES_DEVICE_JOYPAD:
|
||||||
return sdl_joypad_device_state(data, binds, port == SNES_PORT_1 ? 0 : 1, device, index, id);
|
return sdl_joypad_device_state(data, binds, (port == SNES_PORT_1) ? 0 : 1, device, index, id);
|
||||||
case SNES_DEVICE_MULTITAP:
|
case SNES_DEVICE_MULTITAP:
|
||||||
return sdl_joypad_device_state(data, binds, (port == SNES_PORT_2) ? 1 + index : 0, device, index, id);
|
return sdl_joypad_device_state(data, binds, (port == SNES_PORT_2) ? 1 + index : 0, device, index, id);
|
||||||
case SNES_DEVICE_MOUSE:
|
case SNES_DEVICE_MOUSE:
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
|
||||||
|
* Copyright (C) 2010-2011 - 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.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "general.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "ssnes_sdl_input.h"
|
||||||
|
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
|
||||||
|
typedef struct x11_input
|
||||||
|
{
|
||||||
|
sdl_input_t *sdl;
|
||||||
|
Display *display;
|
||||||
|
char state[32];
|
||||||
|
} x11_input_t;
|
||||||
|
|
||||||
|
static void* x_input_init(void)
|
||||||
|
{
|
||||||
|
x11_input_t *x11 = calloc(1, sizeof(*x11));
|
||||||
|
if (!x11)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
x11->display = XOpenDisplay(NULL);
|
||||||
|
if (!x11->display)
|
||||||
|
{
|
||||||
|
free(x11);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
x11->sdl = input_sdl.init();
|
||||||
|
if (!x11->sdl)
|
||||||
|
{
|
||||||
|
free(x11);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
x11->sdl->use_keyboard = false;
|
||||||
|
return x11;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int sdl2xlut[] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, // 0
|
||||||
|
XK_BackSpace, XK_Tab, 0, 0, 0, XK_Return, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||||
|
0, 0, 0, XK_Escape, 0, 0, 0, 0,
|
||||||
|
XK_space, 0, 0, 0, 0, 0, 0, 0, // 32
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
XK_0, XK_1, XK_2, XK_3, XK_4, XK_5, XK_6, XK_7, // 48
|
||||||
|
XK_8, XK_9, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, // 64
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, // 80
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, // 96
|
||||||
|
};
|
||||||
|
|
||||||
|
static int sdl_to_xkeysym(int key)
|
||||||
|
{
|
||||||
|
if (key < sizeof(sdl2xlut) / sizeof(int))
|
||||||
|
return sdl2xlut[key];
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool x_key_pressed(x11_input_t *x11, int key)
|
||||||
|
{
|
||||||
|
key = sdl_to_xkeysym(key);
|
||||||
|
|
||||||
|
int keycode = XKeysymToKeycode(x11->display, key);
|
||||||
|
fprintf(stderr, "key: %d -> keycode: %d\n", key, keycode);
|
||||||
|
return x11->state[keycode >> 3] & (1 << (keycode & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool x_is_pressed(x11_input_t *x11, const struct snes_keybind *binds, unsigned id)
|
||||||
|
{
|
||||||
|
for (int i = 0; binds[i].id != -1; i++)
|
||||||
|
{
|
||||||
|
if (binds[i].id == id)
|
||||||
|
return x_key_pressed(x11, binds[i].key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool x_bind_button_pressed(void *data, int key)
|
||||||
|
{
|
||||||
|
x11_input_t *x11 = data;
|
||||||
|
const struct snes_keybind *binds = g_settings.input.binds[0];
|
||||||
|
for (int i = 0; binds[i].id != -1; i++)
|
||||||
|
{
|
||||||
|
if (binds[i].id == key)
|
||||||
|
{
|
||||||
|
bool pressed = x_key_pressed(x11, binds[i].key);
|
||||||
|
if (!pressed)
|
||||||
|
return input_sdl.key_pressed(x11->sdl, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int16_t x_input_state(void *data, const struct snes_keybind **binds, bool port, unsigned device, unsigned index, unsigned id)
|
||||||
|
{
|
||||||
|
x11_input_t *x11 = data;
|
||||||
|
bool pressed = false;
|
||||||
|
|
||||||
|
switch (device)
|
||||||
|
{
|
||||||
|
case SNES_DEVICE_JOYPAD:
|
||||||
|
pressed = x_is_pressed(x11, binds[(port == SNES_PORT_1) ? 0 : 1], id);
|
||||||
|
if (!pressed)
|
||||||
|
pressed = input_sdl.input_state(x11->sdl, binds, port, device, index, id);
|
||||||
|
return pressed;
|
||||||
|
|
||||||
|
case SNES_DEVICE_MULTITAP:
|
||||||
|
pressed = x_is_pressed(x11, binds[(port == SNES_PORT_2) ? 1 + index : 0], id);
|
||||||
|
if (!pressed)
|
||||||
|
pressed = input_sdl.input_state(x11->sdl, binds, port, device, index, id);
|
||||||
|
return pressed;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void x_input_free(void *data)
|
||||||
|
{
|
||||||
|
x11_input_t *x11 = data;
|
||||||
|
input_sdl.free(x11->sdl);
|
||||||
|
XCloseDisplay(x11->display);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void x_input_poll(void *data)
|
||||||
|
{
|
||||||
|
x11_input_t *x11 = data;
|
||||||
|
XQueryKeymap(x11->display, x11->state);
|
||||||
|
//for (int i = 0; i < 32; i++)
|
||||||
|
//{
|
||||||
|
// fprintf(stderr, "State %d: 0x%x\n", i, (unsigned)x11->state[i]);
|
||||||
|
//}
|
||||||
|
input_sdl.poll(x11->sdl);
|
||||||
|
}
|
||||||
|
|
||||||
|
const input_driver_t input_x = {
|
||||||
|
.init = x_input_init,
|
||||||
|
.poll = x_input_poll,
|
||||||
|
.input_state = x_input_state,
|
||||||
|
.key_pressed = x_bind_button_pressed,
|
||||||
|
.free = x_input_free,
|
||||||
|
.ident = "x"
|
||||||
|
};
|
||||||
|
|
|
@ -52,9 +52,10 @@ check_pkgconf SRC samplerate
|
||||||
check_lib DYNAMIC -ldl dlopen
|
check_lib DYNAMIC -ldl dlopen
|
||||||
|
|
||||||
check_pkgconf FREETYPE freetype2
|
check_pkgconf FREETYPE freetype2
|
||||||
|
check_lib XVIDEO -lXv XvShmCreateImage
|
||||||
|
|
||||||
# Creates config.mk and config.h.
|
# Creates config.mk and config.h.
|
||||||
VARS="ALSA OSS AL RSOUND ROAR JACK PULSE SDL FILTER CG XML DYNAMIC FFMPEG AVCODEC AVFORMAT AVCORE AVUTIL SWSCALE SRC CONFIGFILE FREETYPE"
|
VARS="ALSA OSS AL RSOUND ROAR JACK PULSE SDL FILTER CG XML DYNAMIC FFMPEG AVCODEC AVFORMAT AVCORE AVUTIL SWSCALE SRC CONFIGFILE FREETYPE XVIDEO"
|
||||||
create_config_make config.mk $VARS
|
create_config_make config.mk $VARS
|
||||||
create_config_header config.h $VARS
|
create_config_header config.h $VARS
|
||||||
|
|
||||||
|
|
|
@ -23,3 +23,4 @@ add_command_line_enable AL "Enable OpenAL support" auto
|
||||||
add_command_line_enable JACK "Enable JACK support" auto
|
add_command_line_enable JACK "Enable JACK support" auto
|
||||||
add_command_line_enable PULSE "Enable PulseAudio support" auto
|
add_command_line_enable PULSE "Enable PulseAudio support" auto
|
||||||
add_command_line_enable FREETYPE "Enable FreeType support" auto
|
add_command_line_enable FREETYPE "Enable FreeType support" auto
|
||||||
|
add_command_line_enable XVIDEO "Enable XVideo support" auto
|
||||||
|
|
|
@ -44,6 +44,9 @@ static void set_defaults(void)
|
||||||
case VIDEO_GL:
|
case VIDEO_GL:
|
||||||
def_video = "gl";
|
def_video = "gl";
|
||||||
break;
|
break;
|
||||||
|
case VIDEO_XVIDEO:
|
||||||
|
def_video = "xvideo";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -83,6 +86,9 @@ static void set_defaults(void)
|
||||||
case INPUT_SDL:
|
case INPUT_SDL:
|
||||||
def_input = "sdl";
|
def_input = "sdl";
|
||||||
break;
|
break;
|
||||||
|
case INPUT_X:
|
||||||
|
def_input = "x";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue