mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-23 16:09:47 +00:00
Merge branch 'master' into overlay
This commit is contained in:
commit
9056946079
1
Makefile
1
Makefile
@ -248,7 +248,6 @@ else ifeq ($(HAVE_CG), 1)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_DYLIB), 1)
|
||||
OBJ += gfx/ext_gfx.o audio/ext_audio.o
|
||||
LIBS += $(DYLIB_LIB)
|
||||
endif
|
||||
|
||||
|
@ -182,10 +182,6 @@ ifeq ($(HAVE_FBO), 1)
|
||||
DEFINES += -DHAVE_FBO
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_DYLIB), 1)
|
||||
OBJ += gfx/ext_gfx.o audio/ext_audio.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_PYTHON), 1)
|
||||
LIBS += -lpython32
|
||||
DEFINES += -DHAVE_PYTHON -Ipython
|
||||
|
@ -1,128 +0,0 @@
|
||||
/////
|
||||
// API header for external RetroArch audio driver plugins.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __RARCH_AUDIO_DRIVER_PLUGIN_H
|
||||
#define __RARCH_AUDIO_DRIVER_PLUGIN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef RARCH_DLL_IMPORT
|
||||
#define RARCH_API_EXPORT __declspec(dllimport)
|
||||
#else
|
||||
#define RARCH_API_EXPORT __declspec(dllexport)
|
||||
#endif
|
||||
#define RARCH_API_CALLTYPE __cdecl
|
||||
#else
|
||||
#define RARCH_API_EXPORT
|
||||
#define RARCH_API_CALLTYPE
|
||||
#endif
|
||||
|
||||
#ifndef RARCH_TRUE
|
||||
#define RARCH_TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef RARCH_FALSE
|
||||
#define RARCH_FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef RARCH_OK
|
||||
#define RARCH_OK 1
|
||||
#endif
|
||||
|
||||
#ifndef RARCH_ERROR
|
||||
#define RARCH_ERROR 0
|
||||
#endif
|
||||
|
||||
#define RARCH_AUDIO_API_VERSION 2
|
||||
|
||||
typedef struct rarch_audio_driver_info
|
||||
{
|
||||
// A hint for a subdevice of the audio driver.
|
||||
// This is driver independent, and not relevant for all
|
||||
// audio drivers. I.e. ALSA driver might use "hw:0",
|
||||
// OSS "/dev/audio", etc.
|
||||
const char *device;
|
||||
|
||||
// Audio sample rate.
|
||||
unsigned sample_rate;
|
||||
|
||||
// Maximum audio latency requested for output,
|
||||
// measured in milliseconds.
|
||||
// If driver is not able to provide this latency, it can
|
||||
// be disregarded.
|
||||
unsigned latency;
|
||||
} rarch_audio_driver_info_t;
|
||||
|
||||
typedef struct rarch_audio_driver
|
||||
{
|
||||
// Initializes the device.
|
||||
void *(*init)(const rarch_audio_driver_info_t *info);
|
||||
|
||||
// Write data in buffer to audio driver.
|
||||
// A frame here is defined as one combined sample of left and right
|
||||
// channels. (I.e. 44.1kHz, 16-bit stereo has 88.2k samples/s, and
|
||||
// 44.1k frames/s.)
|
||||
//
|
||||
// Samples are interleaved in format LRLRLRLRLR ...
|
||||
// If the driver returns true in use_float(), a floating point
|
||||
// format will be used, with range [-1.0, 1.0].
|
||||
// If not, signed 16-bit samples in native byte ordering will be used.
|
||||
//
|
||||
// This function returns the number of frames successfully written.
|
||||
// If an error occurs, -1 should be returned.
|
||||
// Note that non-blocking behavior that cannot write at this time
|
||||
// should return 0 as returning -1 will terminate the driver.
|
||||
//
|
||||
// Unless said otherwise with set_nonblock_state(), all writes
|
||||
// are blocking, and it should block till it has written all frames.
|
||||
int (*write)(void *data, const void *buffer, unsigned frames);
|
||||
|
||||
// Temporarily pauses the audio driver.
|
||||
int (*stop)(void *data);
|
||||
|
||||
// Resumes audio driver from the paused state.
|
||||
int (*start)(void *data);
|
||||
|
||||
// If state is true, nonblocking operation is assumed.
|
||||
// This is typically used for fast-forwarding. If driver cannot
|
||||
// implement nonblocking writes, this can be disregarded, but should
|
||||
// log a message to stderr.
|
||||
void (*set_nonblock_state)(void *data, int state);
|
||||
|
||||
// Stops and frees the audio driver.
|
||||
void (*free)(void *data);
|
||||
|
||||
// If true is returned, the audio driver is capable of using
|
||||
// floating point data. This will likely increase performance as the
|
||||
// resampler unit uses floating point. The sample range is
|
||||
// [-1.0, 1.0].
|
||||
int (*use_float)(void *data);
|
||||
|
||||
// The driver might be forced to use a certain output frequency
|
||||
// (i.e. Jack), and thus to avoid double resampling, the driver
|
||||
// can request RetroArch to resample to a different sample rate.
|
||||
// This function can be set to NULL if the driver does not
|
||||
// desire to override the sample rate.
|
||||
unsigned (*sample_rate)(void *data);
|
||||
|
||||
// Human readable identification string for the driver.
|
||||
const char *ident;
|
||||
|
||||
// Must be set to RARCH_AUDIO_API_VERSION.
|
||||
// Used for detecting API mismatch.
|
||||
int api_version;
|
||||
} rarch_audio_driver_t;
|
||||
|
||||
RARCH_API_EXPORT const rarch_audio_driver_t* RARCH_API_CALLTYPE
|
||||
rarch_audio_driver_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,162 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
|
||||
*
|
||||
* RetroArch 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.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ext/rarch_audio.h"
|
||||
#include "../boolean.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "../driver.h"
|
||||
#include "../dynamic.h"
|
||||
#include "../general.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef struct audio_ext
|
||||
{
|
||||
dylib_t lib;
|
||||
const rarch_audio_driver_t *driver;
|
||||
void *handle;
|
||||
bool is_float;
|
||||
} audio_ext_t;
|
||||
|
||||
static void audio_ext_free(void *data)
|
||||
{
|
||||
audio_ext_t *ext = (audio_ext_t*)data;
|
||||
if (ext)
|
||||
{
|
||||
if (ext->driver && ext->handle)
|
||||
ext->driver->free(ext->handle);
|
||||
if (ext->lib)
|
||||
dylib_close(ext->lib);
|
||||
free(ext);
|
||||
}
|
||||
}
|
||||
|
||||
static void *audio_ext_init(const char *device, unsigned rate, unsigned latency)
|
||||
{
|
||||
if (!(*g_settings.audio.external_driver))
|
||||
{
|
||||
RARCH_ERR("Please define an external audio driver.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
audio_ext_t *ext = (audio_ext_t*)calloc(1, sizeof(*ext));
|
||||
if (!ext)
|
||||
return NULL;
|
||||
|
||||
rarch_audio_driver_info_t info = {0};
|
||||
const rarch_audio_driver_t *(*plugin_load)(void) = NULL;
|
||||
|
||||
ext->lib = dylib_load(g_settings.audio.external_driver);
|
||||
if (!ext->lib)
|
||||
{
|
||||
RARCH_ERR("Failed to load external library \"%s\"\n", g_settings.audio.external_driver);
|
||||
goto error;
|
||||
}
|
||||
|
||||
plugin_load = (const rarch_audio_driver_t *(*)(void))dylib_proc(ext->lib, "rarch_audio_driver_init");
|
||||
|
||||
if (!plugin_load)
|
||||
{
|
||||
RARCH_ERR("Failed to find symbol \"rarch_audio_driver_init\" in plugin.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ext->driver = plugin_load();
|
||||
if (!ext->driver)
|
||||
{
|
||||
RARCH_ERR("Received invalid driver from plugin.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
RARCH_LOG("Loaded external audio driver: \"%s\"\n", ext->driver->ident ? ext->driver->ident : "Unknown");
|
||||
|
||||
if (ext->driver->api_version != RARCH_AUDIO_API_VERSION)
|
||||
{
|
||||
RARCH_ERR("API mismatch in external audio plugin. RetroArch: %d, Plugin: %d ...\n", RARCH_AUDIO_API_VERSION, ext->driver->api_version);
|
||||
goto error;
|
||||
}
|
||||
|
||||
info.device = device;
|
||||
info.sample_rate = rate;
|
||||
info.latency = latency;
|
||||
|
||||
ext->handle = ext->driver->init(&info);
|
||||
if (!ext->handle)
|
||||
{
|
||||
RARCH_ERR("Failed to init audio driver.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ext->driver->sample_rate)
|
||||
g_settings.audio.out_rate = ext->driver->sample_rate(ext->handle);
|
||||
|
||||
if (!g_settings.audio.sync)
|
||||
ext->driver->set_nonblock_state(ext->handle, RARCH_TRUE);
|
||||
|
||||
return ext;
|
||||
|
||||
error:
|
||||
audio_ext_free(ext);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ssize_t audio_ext_write(void *data, const void *buf, size_t size)
|
||||
{
|
||||
audio_ext_t *ext = (audio_ext_t*)data;
|
||||
unsigned frame_size = ext->is_float ? (2 * sizeof(float)) : (2 * sizeof(int16_t));
|
||||
size /= frame_size;
|
||||
|
||||
int ret = ext->driver->write(ext->handle, buf, size);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return ret * frame_size;
|
||||
}
|
||||
|
||||
static bool audio_ext_start(void *data)
|
||||
{
|
||||
audio_ext_t *ext = (audio_ext_t*)data;
|
||||
return ext->driver->start(ext->handle);
|
||||
}
|
||||
|
||||
static bool audio_ext_stop(void *data)
|
||||
{
|
||||
audio_ext_t *ext = (audio_ext_t*)data;
|
||||
return ext->driver->stop(ext->handle);
|
||||
}
|
||||
|
||||
static void audio_ext_set_nonblock_state(void *data, bool toggle)
|
||||
{
|
||||
audio_ext_t *ext = (audio_ext_t*)data;
|
||||
ext->driver->set_nonblock_state(ext->handle, toggle);
|
||||
}
|
||||
|
||||
static bool audio_ext_use_float(void *data)
|
||||
{
|
||||
audio_ext_t *ext = (audio_ext_t*)data;
|
||||
ext->is_float = ext->driver->use_float(ext->handle);
|
||||
return ext->is_float;
|
||||
}
|
||||
|
||||
const audio_driver_t audio_ext = {
|
||||
audio_ext_init,
|
||||
audio_ext_write,
|
||||
audio_ext_stop,
|
||||
audio_ext_start,
|
||||
audio_ext_set_nonblock_state,
|
||||
audio_ext_free,
|
||||
audio_ext_use_float,
|
||||
"ext"
|
||||
};
|
||||
|
6
driver.c
6
driver.c
@ -67,9 +67,6 @@ static const audio_driver_t *audio_drivers[] = {
|
||||
#ifdef HAVE_PULSE
|
||||
&audio_pulse,
|
||||
#endif
|
||||
#ifdef HAVE_DYLIB
|
||||
&audio_ext,
|
||||
#endif
|
||||
#ifdef __CELLOS_LV2__
|
||||
&audio_ps3,
|
||||
#endif
|
||||
@ -110,9 +107,6 @@ static const video_driver_t *video_drivers[] = {
|
||||
#ifdef HAVE_XVIDEO
|
||||
&video_xvideo,
|
||||
#endif
|
||||
#ifdef HAVE_DYLIB
|
||||
&video_ext,
|
||||
#endif
|
||||
#ifdef GEKKO
|
||||
&video_gx,
|
||||
#endif
|
||||
|
2
driver.h
2
driver.h
@ -305,7 +305,6 @@ extern const audio_driver_t audio_jack;
|
||||
extern const audio_driver_t audio_sdl;
|
||||
extern const audio_driver_t audio_xa;
|
||||
extern const audio_driver_t audio_pulse;
|
||||
extern const audio_driver_t audio_ext;
|
||||
extern const audio_driver_t audio_dsound;
|
||||
extern const audio_driver_t audio_coreaudio;
|
||||
extern const audio_driver_t audio_xenon360;
|
||||
@ -323,7 +322,6 @@ extern const video_driver_t video_xvideo;
|
||||
extern const video_driver_t video_xdk_d3d;
|
||||
extern const video_driver_t video_sdl;
|
||||
extern const video_driver_t video_vg;
|
||||
extern const video_driver_t video_ext;
|
||||
extern const video_driver_t video_null;
|
||||
extern const input_driver_t input_android;
|
||||
extern const input_driver_t input_sdl;
|
||||
|
@ -147,7 +147,6 @@ struct settings
|
||||
bool gpu_screenshot;
|
||||
|
||||
bool allow_rotate;
|
||||
char external_driver[PATH_MAX];
|
||||
} video;
|
||||
|
||||
struct
|
||||
@ -162,7 +161,6 @@ struct settings
|
||||
bool sync;
|
||||
|
||||
char dsp_plugin[PATH_MAX];
|
||||
char external_driver[PATH_MAX];
|
||||
|
||||
bool rate_control;
|
||||
float rate_control_delta;
|
||||
|
@ -1,285 +0,0 @@
|
||||
/////
|
||||
// API header for external RetroArch video and input plugins.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __RARCH_VIDEO_DRIVER_H
|
||||
#define __RARCH_VIDEO_DRIVER_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef RARCH_DLL_IMPORT
|
||||
#define RARCH_API_EXPORT __declspec(dllimport)
|
||||
#else
|
||||
#define RARCH_API_EXPORT __declspec(dllexport)
|
||||
#endif
|
||||
#define RARCH_API_CALLTYPE __cdecl
|
||||
#else
|
||||
#define RARCH_API_EXPORT
|
||||
#define RARCH_API_CALLTYPE
|
||||
#endif
|
||||
|
||||
#define RARCH_GRAPHICS_API_VERSION 5
|
||||
|
||||
// Since we don't want to rely on C++ or C99 for a proper boolean type,
|
||||
// make sure return semantics are perfectly clear ... ;)
|
||||
|
||||
#ifndef RARCH_OK
|
||||
#define RARCH_OK 1
|
||||
#endif
|
||||
|
||||
#ifndef RARCH_ERROR
|
||||
#define RARCH_ERROR 0
|
||||
#endif
|
||||
|
||||
#ifndef RARCH_TRUE
|
||||
#define RARCH_TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef RARCH_FALSE
|
||||
#define RARCH_FALSE 0
|
||||
#endif
|
||||
|
||||
#define RARCH_COLOR_FORMAT_RGB565 0
|
||||
#define RARCH_COLOR_FORMAT_XRGB8888 1
|
||||
|
||||
#define RARCH_INPUT_SCALE_BASE 256
|
||||
|
||||
typedef struct py_state py_state_t;
|
||||
|
||||
// Create a new runtime for Python.
|
||||
// py_script: The python script to be loaded. If is_file is true, this will be the full path to a file.
|
||||
// If false, it will be an UTF-8 encoded string of the script.
|
||||
// is_file: Tells if py_script is the path to a script, or a script itself.
|
||||
// py_class: name of the class being instantiated.
|
||||
typedef py_state_t *(*python_state_new_cb)(const char *py_script, unsigned is_file, const char *py_class);
|
||||
// Grabs a value from the Python runtime.
|
||||
// id: The uniform (class method) to be called.
|
||||
// frame_count: Passes frame_count as an argument to the script.
|
||||
typedef float (*python_state_get_cb)(py_state_t *handle, const char *id, unsigned frame_count);
|
||||
// Frees the runtime.
|
||||
typedef void (*python_state_free_cb)(py_state_t *handle);
|
||||
|
||||
typedef struct rarch_video_info
|
||||
{
|
||||
// Width of window.
|
||||
// If fullscreen mode is requested,
|
||||
// a width of 0 means the resolution of the desktop should be used.
|
||||
unsigned width;
|
||||
|
||||
// Height of window.
|
||||
// If fullscreen mode is requested,
|
||||
// a height of 0 means the resolutiof the desktop should be used.
|
||||
unsigned height;
|
||||
|
||||
// If true, start the window in fullscreen mode.
|
||||
int fullscreen;
|
||||
|
||||
// If true, VSync should be enabled.
|
||||
int vsync;
|
||||
|
||||
// If true, the output image should have the aspect ratio
|
||||
// as set in aspect_ratio.
|
||||
int force_aspect;
|
||||
|
||||
// Aspect ratio. Only takes effect if force_aspect is enabled.
|
||||
float aspect_ratio;
|
||||
|
||||
// Requests that the image is smoothed,
|
||||
// using bilinear filtering or otherwise.
|
||||
// If this cannot be implemented efficiently, this can be disregarded.
|
||||
// If smooth is false, nearest-neighbor scaling is requested.
|
||||
int smooth;
|
||||
|
||||
// input_scale defines the maximum size of the picture that will
|
||||
// ever be used with the frame callback.
|
||||
// The maximum resolution is a multiple of 256x256 size (RARCH_INPUT_SCALE_BASE),
|
||||
// so an input scale of 2
|
||||
// means you should allocate a texture or of 512x512.
|
||||
unsigned input_scale;
|
||||
|
||||
// Defines the coloring format used of the input frame.
|
||||
// XRGB1555 format is 16-bit and has byte ordering: 0RRRRRGGGGGBBBBB,
|
||||
// in native endian.
|
||||
// ARGB8888 is AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB, native endian.
|
||||
// Alpha channel should be disregarded.
|
||||
int color_format;
|
||||
|
||||
// If non-NULL, requests the use of an XML shader.
|
||||
// Can be disregarded.
|
||||
const char *xml_shader;
|
||||
// If non-NULL, requests the use of a Cg shader.
|
||||
// Can be disregarded.
|
||||
// If both are non-NULL,
|
||||
// Cg or XML could be used at the discretion of the plugin.
|
||||
const char *cg_shader;
|
||||
|
||||
// Requestes that a certain
|
||||
// TTF font is used for rendering messages to the screen.
|
||||
// Can be disregarded.
|
||||
const char *ttf_font;
|
||||
unsigned ttf_font_size;
|
||||
unsigned ttf_font_color; // Font color, in format ARGB8888. Alpha should be disregarded.
|
||||
|
||||
// A title that should be displayed in the title bar of the window.
|
||||
const char *title_hint;
|
||||
|
||||
// Functions to peek into the python runtime for shaders.
|
||||
// Check typedefs above for explanation.
|
||||
// These may be NULL if RetroArch is not built with Python support.
|
||||
python_state_new_cb python_state_new;
|
||||
python_state_get_cb python_state_get;
|
||||
python_state_free_cb python_state_free;
|
||||
} rarch_video_info_t;
|
||||
|
||||
// Some convenience macros.
|
||||
// Extract which axes to test for in negative or positive direction.
|
||||
// May be equal to RARCH_NO_AXIS, which means testing should not occur.
|
||||
#define RARCH_AXIS_NEG_GET(x) (((unsigned)(x) >> 16) & 0xFFFFU)
|
||||
#define RARCH_AXIS_POS_GET(x) ((unsigned)(x) & 0xFFFFU)
|
||||
|
||||
// I hope no joypad will ever have this many buttons or axes ... ;)
|
||||
// If joykey is this value, do not check that button.
|
||||
#define RARCH_NO_AXIS (0xFFFFFFFFU)
|
||||
#define RARCH_NO_BTN ((unsigned short)0xFFFFU)
|
||||
|
||||
// Masks to test on joykey which hat direction is to be tested for.
|
||||
#define RARCH_HAT_UP_MASK (1 << 15)
|
||||
#define RARCH_HAT_DOWN_MASK (1 << 14)
|
||||
#define RARCH_HAT_LEFT_MASK (1 << 13)
|
||||
#define RARCH_HAT_RIGHT_MASK (1 << 12)
|
||||
#define RARCH_HAT_MAP(x, hat) ((x & ((1 << 12) - 1)) | hat)
|
||||
|
||||
#define RARCH_HAT_MASK (RARCH_HAT_UP_MASK | RARCH_HAT_DOWN_MASK | \
|
||||
RARCH_HAT_LEFT_MASK | RARCH_HAT_RIGHT_MASK)
|
||||
|
||||
// Test this on the joykey. If true, we want to test for a joypad hat
|
||||
// rather than a button.
|
||||
#define RARCH_GET_HAT_DIR(x) (x & RARCH_HAT_MASK)
|
||||
|
||||
// Gets the joypad hat to be tested for.
|
||||
// Only valid when RARCH_GET_HAT_DIR() returns true.
|
||||
#define RARCH_GET_HAT(x) (x & (~RARCH_HAT_MASK))
|
||||
|
||||
// key, joykey and joyaxis are all checked at the same time.
|
||||
// If any one of these are pressed, return 1 in state callback.
|
||||
struct rarch_keybind
|
||||
{
|
||||
// Keyboard key. The key values use the SDL 1.2 keysyms,
|
||||
// which probably need to be transformed to the native format.
|
||||
// The actual keysyms RetroArch uses are found in libretro.h.
|
||||
unsigned short key;
|
||||
|
||||
// Joypad key. Joypad POV (hats) are embedded into this key as well.
|
||||
unsigned short joykey;
|
||||
|
||||
// Joypad axis. Negative and positive axes are embedded into this variable.
|
||||
unsigned joyaxis;
|
||||
};
|
||||
|
||||
typedef struct rarch_input_driver
|
||||
{
|
||||
// Inits input driver.
|
||||
// Joypad index denotes which joypads are desired for the various players.
|
||||
// Should an entry be negative,
|
||||
// do not open joypad for that player.
|
||||
// Threshold states the minimum offset that a joypad axis
|
||||
// has to be held for it to be registered.
|
||||
// The range of this is [0, 1],
|
||||
// where 0 means any displacement will register,
|
||||
// and 1 means the axis has to be pressed all the way to register.
|
||||
void *(*init)(const int joypad_index[8], float axis_threshold);
|
||||
|
||||
// Polls input. Called once every frame.
|
||||
void (*poll)(void *data);
|
||||
|
||||
// Queries input state for a certain key on a certain player.
|
||||
// Players are 1 - 8.
|
||||
// For digital inputs, pressed key is 1, not pressed key is 0.
|
||||
// Analog values have same range as a signed 16-bit integer.
|
||||
short (*input_state)(void *data, const struct rarch_keybind *bind,
|
||||
unsigned player);
|
||||
|
||||
// Queries analog input state for a certain key on a certain player in the range of [-0x8000, 0x7fff].
|
||||
// Only the direction of the bind should be returned.
|
||||
//
|
||||
// E.g. if the bind has bind for negative axis 5, and the axis is pressed to the positive
|
||||
// axis, the returned value should be 0.
|
||||
short (*input_state_analog)(void *data, unsigned joyaxis,
|
||||
unsigned player);
|
||||
|
||||
// Frees the input struct.
|
||||
void (*free)(void *data);
|
||||
|
||||
// Human readable indentification string.
|
||||
const char *ident;
|
||||
} rarch_input_driver_t;
|
||||
|
||||
typedef struct rarch_video_driver
|
||||
{
|
||||
// Inits the video driver. Returns an opaque handle pointer to the driver.
|
||||
// Returns NULL on error.
|
||||
//
|
||||
// Should the video driver request that a certain input driver is used,
|
||||
// it is possible to set the driver to *input.
|
||||
// If no certain driver is desired, set *input to NULL.
|
||||
void *(*init)(const rarch_video_info_t *video,
|
||||
const rarch_input_driver_t **input);
|
||||
|
||||
// Updates frame on the screen.
|
||||
// Frame can be either XRGB1555 or ARGB32 format
|
||||
// depending on rgb32 setting in rarch_video_info_t.
|
||||
// Pitch is the distance in bytes between two scanlines in memory.
|
||||
//
|
||||
// When msg is non-NULL,
|
||||
// it's a message that should be displayed to the user.
|
||||
int (*frame)(void *data, const void *frame,
|
||||
unsigned width, unsigned height, unsigned pitch, const char *msg);
|
||||
|
||||
// Requests nonblocking operation.
|
||||
// True = VSync is turned off.
|
||||
// False = VSync is turned on.
|
||||
void (*set_nonblock_state)(void *data, int toggle);
|
||||
|
||||
// This must return false when the user exits the emulator.
|
||||
int (*alive)(void *data);
|
||||
|
||||
// Does the window have focus?
|
||||
int (*focus)(void *data);
|
||||
|
||||
// Frees the video driver.
|
||||
void (*free)(void *data);
|
||||
|
||||
// A human-readable identification of the video driver.
|
||||
const char *ident;
|
||||
|
||||
// Needs to be defined to RARCH_GRAPHICS_API_VERSION.
|
||||
// This is used to detect API/ABI mismatches.
|
||||
int api_version;
|
||||
|
||||
// The final image should be rotated counter-clockwise by rot * 90 degrees.
|
||||
void (*set_rotation)(void *data, unsigned rot);
|
||||
|
||||
// Gets the current width/height of the viewport.
|
||||
void (*viewport_size)(void *data, unsigned *width, unsigned *height);
|
||||
|
||||
// Reads the content of the viewport into memory.
|
||||
// Tightly packed BGR888. Pitch is width * 3.
|
||||
int (*read_viewport)(void *data, unsigned char *buffer);
|
||||
} rarch_video_driver_t;
|
||||
|
||||
// Called by RetroArch on startup to get a driver handle.
|
||||
// This is NOT dynamically allocated.
|
||||
RARCH_API_EXPORT const rarch_video_driver_t* RARCH_API_CALLTYPE
|
||||
rarch_video_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
424
gfx/ext_gfx.c
424
gfx/ext_gfx.c
@ -1,424 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
|
||||
*
|
||||
* RetroArch 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.
|
||||
*
|
||||
* RetroArch 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 RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Loader for external API plugins.
|
||||
|
||||
#define RARCH_DLL_IMPORT
|
||||
#include "ext/rarch_video.h"
|
||||
#include "../boolean.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "../dynamic.h"
|
||||
#include "../general.h"
|
||||
#include "gfx_common.h"
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
#include "fonts/fonts.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
#define PY_STATE_OMIT_DECLARATION
|
||||
#include "py_state/py_state.h"
|
||||
#endif
|
||||
|
||||
static bool g_input_dead = true;
|
||||
static bool g_video_dead = true;
|
||||
static dylib_t g_lib = NULL;
|
||||
|
||||
/////////// Input hook
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const rarch_input_driver_t *driver;
|
||||
void *handle;
|
||||
} input_ext_t;
|
||||
|
||||
static void *input_ext_init(void)
|
||||
{
|
||||
g_input_dead = false;
|
||||
return calloc(1, sizeof(input_ext_t));
|
||||
}
|
||||
|
||||
static void input_ext_poll(void *data)
|
||||
{
|
||||
input_ext_t *ext = (input_ext_t*)data;
|
||||
ext->driver->poll(ext->handle);
|
||||
}
|
||||
|
||||
static int16_t input_ext_input_state(void *data, const struct retro_keybind **retro_keybinds, unsigned port, unsigned device, unsigned index, unsigned id)
|
||||
{
|
||||
input_ext_t *ext = (input_ext_t*)data;
|
||||
unsigned player = port + 1;
|
||||
struct rarch_keybind bind = {0};
|
||||
|
||||
switch (device)
|
||||
{
|
||||
case RETRO_DEVICE_JOYPAD:
|
||||
{
|
||||
if (id >= RARCH_BIND_LIST_END)
|
||||
return 0;
|
||||
|
||||
const struct retro_keybind *rarch_bind = &retro_keybinds[player - 1][id];
|
||||
if (!rarch_bind->valid)
|
||||
return 0;
|
||||
|
||||
bind.key = rarch_bind->key;
|
||||
bind.joykey = rarch_bind->joykey;
|
||||
bind.joyaxis = rarch_bind->joyaxis;
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: RETRO_DEVICE_ANALOG.
|
||||
|
||||
case RETRO_DEVICE_KEYBOARD:
|
||||
if (id >= RETROK_LAST)
|
||||
return 0;
|
||||
|
||||
bind.key = id;
|
||||
bind.joykey = NO_BTN;
|
||||
bind.joyaxis = AXIS_NONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ext->driver->input_state(ext->handle, &bind, player);
|
||||
}
|
||||
|
||||
static bool input_ext_key_pressed(void *data, int key)
|
||||
{
|
||||
input_ext_t *ext = (input_ext_t*)data;
|
||||
|
||||
if (key >= 0 && key < RARCH_BIND_LIST_END)
|
||||
{
|
||||
const struct retro_keybind *rarch_bind = &g_settings.input.binds[0][key];
|
||||
if (!rarch_bind->valid)
|
||||
return false;
|
||||
|
||||
struct rarch_keybind bind = {0};
|
||||
bind.key = rarch_bind->key;
|
||||
bind.joykey = rarch_bind->joykey;
|
||||
bind.joyaxis = rarch_bind->joyaxis;
|
||||
|
||||
return ext->driver->input_state(ext->handle, &bind, 1);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static void input_ext_free(void *data)
|
||||
{
|
||||
input_ext_t *ext = (input_ext_t*)data;
|
||||
if (ext)
|
||||
{
|
||||
if (ext->driver && ext->handle)
|
||||
ext->driver->free(ext->handle);
|
||||
|
||||
if (g_video_dead)
|
||||
{
|
||||
dylib_close(g_lib);
|
||||
g_lib = NULL;
|
||||
}
|
||||
|
||||
g_input_dead = true;
|
||||
|
||||
free(ext);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RARCH_CONSOLE
|
||||
static void input_ext_set_default_keybind_lut(unsigned device, unsigned port)
|
||||
{
|
||||
(void)device;
|
||||
(void)port;
|
||||
}
|
||||
|
||||
static void input_ext_set_analog_dpad_mapping(unsigned device, unsigned map_dpad_enum, unsigned controller_id)
|
||||
{
|
||||
(void)device;
|
||||
(void)map_dpad_enum;
|
||||
(void)controller_id;
|
||||
}
|
||||
|
||||
static void input_ext_input_post_init(void) {}
|
||||
#endif
|
||||
|
||||
static const input_driver_t input_ext = {
|
||||
input_ext_init,
|
||||
input_ext_poll,
|
||||
input_ext_input_state,
|
||||
input_ext_key_pressed,
|
||||
input_ext_free,
|
||||
#ifdef RARCH_CONSOLE
|
||||
input_ext_set_default_keybind_lut,
|
||||
input_ext_set_analog_dpad_mapping,
|
||||
input_ext_input_post_init,
|
||||
2,
|
||||
#endif
|
||||
"ext"
|
||||
};
|
||||
|
||||
//////////// Video hook
|
||||
typedef struct
|
||||
{
|
||||
const rarch_video_driver_t *driver;
|
||||
void *handle;
|
||||
} ext_t;
|
||||
|
||||
static void video_ext_free(void *data)
|
||||
{
|
||||
ext_t *ext = (ext_t*)data;
|
||||
if (ext)
|
||||
{
|
||||
if (ext->driver && ext->handle)
|
||||
ext->driver->free(ext->handle);
|
||||
|
||||
if (g_input_dead)
|
||||
{
|
||||
dylib_close(g_lib);
|
||||
g_lib = NULL;
|
||||
}
|
||||
|
||||
g_video_dead = true;
|
||||
|
||||
free(ext);
|
||||
}
|
||||
}
|
||||
|
||||
static bool video_ext_focus(void *data)
|
||||
{
|
||||
ext_t *ext = (ext_t*)data;
|
||||
return ext->driver->focus(ext->handle);
|
||||
}
|
||||
|
||||
static bool video_ext_alive(void *data)
|
||||
{
|
||||
ext_t *ext = (ext_t*)data;
|
||||
return ext->driver->alive(ext->handle);
|
||||
}
|
||||
|
||||
static void video_ext_set_nonblock_state(void *data, bool state)
|
||||
{
|
||||
ext_t *ext = (ext_t*)data;
|
||||
ext->driver->set_nonblock_state(ext->handle, state);
|
||||
}
|
||||
|
||||
static bool video_ext_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch, const char *msg)
|
||||
{
|
||||
if (!frame)
|
||||
return true;
|
||||
|
||||
ext_t *ext = (ext_t*)data;
|
||||
return ext->driver->frame(ext->handle, frame, width, height, pitch, msg);
|
||||
}
|
||||
|
||||
static void *setup_input(ext_t *ext, const rarch_input_driver_t *driver)
|
||||
{
|
||||
int joypad_index[8];
|
||||
for (unsigned i = 0; i < 8; i++)
|
||||
joypad_index[i] = g_settings.input.joypad_map[i] < 0 ? -1 : g_settings.input.joypad_map[i];
|
||||
|
||||
void *handle = driver->init(joypad_index, g_settings.input.axis_threshold);
|
||||
if (!handle)
|
||||
return NULL;
|
||||
|
||||
input_ext_t *wrap_handle = (input_ext_t*)input_ext.init();
|
||||
if (!wrap_handle)
|
||||
return NULL;
|
||||
|
||||
wrap_handle->handle = handle;
|
||||
wrap_handle->driver = driver;
|
||||
|
||||
return wrap_handle;
|
||||
}
|
||||
|
||||
static bool setup_video(ext_t *ext, const video_info_t *video, const input_driver_t **input, void **input_data)
|
||||
{
|
||||
RARCH_LOG("Loaded driver: \"%s\"\n", ext->driver->ident ? ext->driver->ident : "Unknown");
|
||||
|
||||
if (RARCH_GRAPHICS_API_VERSION != ext->driver->api_version)
|
||||
{
|
||||
RARCH_ERR("API version mismatch detected.\n");
|
||||
RARCH_ERR("Required API version: %d, Library version: %d\n", RARCH_GRAPHICS_API_VERSION, ext->driver->api_version);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *cg_shader = NULL;
|
||||
const char *xml_shader = NULL;
|
||||
|
||||
enum rarch_shader_type type = g_settings.video.shader_type;
|
||||
|
||||
if ((type == RARCH_SHADER_CG || type == RARCH_SHADER_AUTO) && *g_settings.video.cg_shader_path)
|
||||
cg_shader = g_settings.video.cg_shader_path;
|
||||
else if ((type == RARCH_SHADER_BSNES || type == RARCH_SHADER_AUTO) && *g_settings.video.bsnes_shader_path)
|
||||
xml_shader = g_settings.video.bsnes_shader_path;
|
||||
|
||||
int font_color_r = g_settings.video.msg_color_r * 255;
|
||||
int font_color_g = g_settings.video.msg_color_g * 255;
|
||||
int font_color_b = g_settings.video.msg_color_b * 255;
|
||||
font_color_r = font_color_r > 255 ? 255 : (font_color_r < 0 ? 0 : font_color_r);
|
||||
font_color_g = font_color_g > 255 ? 255 : (font_color_g < 0 ? 0 : font_color_g);
|
||||
font_color_b = font_color_b > 255 ? 255 : (font_color_b < 0 ? 0 : font_color_b);
|
||||
|
||||
const char *font = NULL;
|
||||
if (g_settings.video.font_enable)
|
||||
{
|
||||
font = *g_settings.video.font_path ?
|
||||
g_settings.video.font_path : NULL;
|
||||
}
|
||||
|
||||
char title_buf[128];
|
||||
gfx_window_title_reset();
|
||||
gfx_get_fps(title_buf, sizeof(title_buf), false);
|
||||
|
||||
rarch_video_info_t info = {0};
|
||||
info.width = video->width;
|
||||
info.height = video->height;
|
||||
info.fullscreen = video->fullscreen;
|
||||
info.vsync = video->vsync;
|
||||
info.force_aspect = video->force_aspect;
|
||||
info.aspect_ratio = g_settings.video.aspect_ratio;
|
||||
info.smooth = video->smooth;
|
||||
info.input_scale = video->input_scale;
|
||||
info.color_format = video->rgb32 ? RARCH_COLOR_FORMAT_XRGB8888 : RARCH_COLOR_FORMAT_RGB565;
|
||||
info.xml_shader = xml_shader;
|
||||
info.cg_shader = cg_shader;
|
||||
info.ttf_font = font;
|
||||
info.ttf_font_size = g_settings.video.font_size;
|
||||
info.ttf_font_color = (font_color_r << 16) | (font_color_g << 8) | (font_color_b << 0);
|
||||
info.title_hint = title_buf;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
info.python_state_new = py_state_new;
|
||||
info.python_state_get = py_state_get;
|
||||
info.python_state_free = py_state_free;
|
||||
#endif
|
||||
|
||||
const rarch_input_driver_t *input_driver = NULL;
|
||||
ext->handle = ext->driver->init(&info, &input_driver);
|
||||
if (!ext->handle)
|
||||
return false;
|
||||
|
||||
*input = input_driver ? &input_ext : NULL;
|
||||
if (input_driver)
|
||||
*input_data = setup_input(ext, input_driver);
|
||||
else
|
||||
*input_data = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void *video_ext_init(const video_info_t *video, const input_driver_t **input, void **input_data)
|
||||
{
|
||||
ext_t *ext = (ext_t*)calloc(1, sizeof(*ext));
|
||||
if (!ext)
|
||||
return NULL;
|
||||
|
||||
const rarch_video_driver_t *(*video_init)(void) = NULL;
|
||||
|
||||
if (!(*g_settings.video.external_driver))
|
||||
{
|
||||
RARCH_ERR("External driver needs video_external_driver path to be set.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_lib = dylib_load(g_settings.video.external_driver);
|
||||
if (!g_lib)
|
||||
{
|
||||
RARCH_ERR("Failed to open library: \"%s\"\n", g_settings.video.external_driver);
|
||||
goto error;
|
||||
}
|
||||
|
||||
video_init = (const rarch_video_driver_t *(*)(void))dylib_proc(g_lib, "rarch_video_init");
|
||||
|
||||
if (!video_init)
|
||||
{
|
||||
RARCH_ERR("Couldn't find function rarch_video_init in library ...\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ext->driver = video_init();
|
||||
if (!ext->driver)
|
||||
{
|
||||
RARCH_ERR("External driver returned invalid driver handle.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!setup_video(ext, video, input, input_data))
|
||||
{
|
||||
RARCH_ERR("Failed to start driver.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_video_dead = false;
|
||||
return ext;
|
||||
|
||||
error:
|
||||
video_ext_free(ext);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void video_set_rotation(void *data, unsigned rot)
|
||||
{
|
||||
ext_t *ext = (ext_t*)data;
|
||||
ext->driver->set_rotation(ext->handle, rot);
|
||||
}
|
||||
|
||||
static void video_viewport_info(void *data, struct rarch_viewport *vp)
|
||||
{
|
||||
ext_t *ext = (ext_t*)data;
|
||||
|
||||
unsigned width = 0, height = 0;
|
||||
ext->driver->viewport_size(ext->handle, &width, &height);
|
||||
vp->x = vp->y = 0;
|
||||
vp->width = width;
|
||||
vp->height = height;
|
||||
}
|
||||
|
||||
static bool video_read_viewport(void *data, uint8_t *buffer)
|
||||
{
|
||||
ext_t *ext = (ext_t*)data;
|
||||
return ext->driver->read_viewport(ext->handle, buffer);
|
||||
}
|
||||
|
||||
#ifdef RARCH_CONSOLE
|
||||
static void video_ext_gfx_start(void) {}
|
||||
static void video_ext_gfx_restart(void) {}
|
||||
static void video_ext_gfx_stop(void) {}
|
||||
static void video_ext_gfx_apply_state_changes(void) {}
|
||||
#endif
|
||||
|
||||
const video_driver_t video_ext = {
|
||||
video_ext_init,
|
||||
video_ext_frame,
|
||||
video_ext_set_nonblock_state,
|
||||
video_ext_alive,
|
||||
video_ext_focus,
|
||||
NULL,
|
||||
video_ext_free,
|
||||
"ext",
|
||||
#ifdef RARCH_CONSOLE
|
||||
video_ext_gfx_start,
|
||||
video_ext_gfx_stop,
|
||||
video_ext_gfx_restart,
|
||||
video_ext_gfx_apply_state_changes,
|
||||
#endif
|
||||
|
||||
video_set_rotation,
|
||||
video_viewport_info,
|
||||
video_read_viewport,
|
||||
};
|
||||
|
@ -588,7 +588,7 @@ static void print_features(void)
|
||||
_PSUPP(dsound, "DirectSound", "audio driver");
|
||||
_PSUPP(xaudio, "XAudio2", "audio driver");
|
||||
_PSUPP(al, "OpenAL", "audio driver");
|
||||
_PSUPP(dylib, "External", "External filter and driver support");
|
||||
_PSUPP(dylib, "External", "External filter and plugin support");
|
||||
_PSUPP(cg, "Cg", "Cg pixel shaders");
|
||||
_PSUPP(xml, "XML", "bSNES XML pixel shaders");
|
||||
_PSUPP(sdl_image, "SDL_image", "SDL_image image loading");
|
||||
|
@ -36,12 +36,9 @@
|
||||
|
||||
#### Video
|
||||
|
||||
# Video driver to use. "gl", "xvideo", "sdl" or "ext" (external API driver)
|
||||
# Video driver to use. "gl", "xvideo", "sdl"
|
||||
# video_driver = "gl"
|
||||
|
||||
# Path to external video driver using the RetroArch driver API.
|
||||
# video_external_driver =
|
||||
|
||||
# Windowed xscale and yscale
|
||||
# (Real x res: base_size * xscale * aspect_ratio, real y res: base_size * yscale)
|
||||
# video_xscale = 3.0
|
||||
@ -158,12 +155,9 @@
|
||||
# When altering audio_in_rate on-the-fly, define by how much each time.
|
||||
# audio_rate_step = 0.25
|
||||
|
||||
# Audio driver backend. Depending on configuration possible candidates are: alsa, pulse, oss, jack, rsound, roar, openal, sdl, xaudio and ext (external driver).
|
||||
# Audio driver backend. Depending on configuration possible candidates are: alsa, pulse, oss, jack, rsound, roar, openal, sdl, xaudio.
|
||||
# audio_driver =
|
||||
|
||||
# Path to external audio driver using the RetroArch audio driver API.
|
||||
# audio_external_driver =
|
||||
|
||||
# Override the default audio device the audio_driver uses. This is driver dependant. E.g. ALSA wants a PCM device, OSS wants a path (e.g. /dev/dsp), Jack wants portnames (e.g. system:playback1,system:playback_2), and so on ...
|
||||
# audio_device =
|
||||
|
||||
|
@ -478,8 +478,6 @@ bool config_load_file(const char *path)
|
||||
|
||||
#ifdef HAVE_DYLIB
|
||||
CONFIG_GET_PATH(video.filter_path, "video_filter");
|
||||
CONFIG_GET_PATH(video.external_driver, "video_external_driver");
|
||||
CONFIG_GET_PATH(audio.external_driver, "audio_external_driver");
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CG) || defined(HAVE_XML)
|
||||
|
Loading…
Reference in New Issue
Block a user