Remove state tracker - legacy code - we can revisit this later

and integrate it in a way so that it scales across all drivers
This commit is contained in:
twinaphex 2019-07-09 07:39:08 +02:00
parent e1d8cdffe9
commit f0f5c32b51
17 changed files with 3 additions and 1508 deletions

View File

@ -508,12 +508,6 @@ ifeq ($(HAVE_STDIN_CMD), 1)
DEFINES += -DHAVE_COMMAND -DHAVE_STDIN_CMD
endif
ifeq ($(HAVE_PYTHON), 1)
DEFINES += $(PYTHON_CFLAGS) -Wno-unused-parameter
LIBS += $(PYTHON_LIBS)
OBJ += gfx/drivers_tracker/video_state_python.o
endif
ifeq ($(HAVE_EMSCRIPTEN), 1)
OBJ += frontend/drivers/platform_emscripten.o \
input/drivers/rwebinput_input.o \
@ -1045,8 +1039,7 @@ endif
# Video
OBJ += gfx/drivers_context/gfx_null_ctx.o \
gfx/video_state_tracker.o
OBJ += gfx/drivers_context/gfx_null_ctx.o
ifeq ($(HAVE_KMS), 1)
HAVE_AND_WILL_USE_DRM = 1

View File

@ -53,7 +53,6 @@ typedef struct d3d9_renderchain_driver
bool smooth);
bool (*render)(d3d9_video_t *d3d,
const video_frame_info_t *video_info,
state_tracker_t *tracker,
const void *frame,
unsigned width, unsigned height, unsigned pitch, unsigned rotation);
const char *ident;
@ -82,7 +81,6 @@ typedef struct d3d9_video
math_matrix_4x4 mvp_rotate;
math_matrix_4x4 mvp_transposed;
state_tracker_t *state_tracker;
struct video_viewport vp;
struct video_shader shader;
video_info_t video_info;

View File

@ -99,51 +99,6 @@ static bool d3d9_set_resize(d3d9_video_t *d3d,
return true;
}
static bool d3d9_init_imports(d3d9_video_t *d3d)
{
retro_ctx_memory_info_t mem_info;
state_tracker_t *state_tracker = NULL;
struct state_tracker_info tracker_info = {0};
if (!d3d->shader.variables)
return true;
mem_info.id = RETRO_MEMORY_SYSTEM_RAM;
core_get_memory(&mem_info);
tracker_info.script_class = NULL;
tracker_info.wram = (uint8_t*)mem_info.data;
tracker_info.info = d3d->shader.variable;
tracker_info.info_elem = d3d->shader.variables;
tracker_info.script = NULL;
tracker_info.script_is_file = false;
#ifdef HAVE_PYTHON
if (*d3d->shader.script_path)
{
tracker_info.script = d3d->shader.script_path;
tracker_info.script_is_file = true;
}
if (*d3d->shader.script_class)
tracker_info.script_class = d3d->shader.script_class;
#endif
state_tracker =
state_tracker_init(&tracker_info);
if (!state_tracker)
{
RARCH_ERR("[D3D9]: Failed to initialize state tracker.\n");
return false;
}
d3d->state_tracker = state_tracker;
return true;
}
extern d3d9_renderchain_driver_t cg_d3d9_renderchain;
extern d3d9_renderchain_driver_t hlsl_d3d9_renderchain;
@ -334,12 +289,6 @@ static bool d3d9_init_chain(d3d9_video_t *d3d, const video_info_t *video_info)
}
}
}
if (!d3d9_init_imports(d3d))
{
RARCH_ERR("[D3D9]: Failed to init imports.\n");
return false;
}
}
return true;
@ -622,10 +571,6 @@ static void d3d9_deinitialize(d3d9_video_t *d3d)
d3d9_deinit_chain(d3d);
d3d9_vertex_buffer_free(d3d->menu_display.buffer, d3d->menu_display.decl);
if (d3d->state_tracker)
state_tracker_free(d3d->state_tracker);
d3d->state_tracker = NULL;
d3d->menu_display.buffer = NULL;
d3d->menu_display.decl = NULL;
}
@ -1682,7 +1627,6 @@ static bool d3d9_frame(void *data, const void *frame,
if (!d3d->renderchain_driver->render(
d3d, video_info,
d3d->state_tracker,
frame, frame_width, frame_height,
pitch, d3d->dev_rotation))
{

View File

@ -891,34 +891,9 @@ static void d3d9_cg_renderchain_set_vertices(
vp_width, vp_height);
}
static void d3d9_cg_renderchain_set_params(
d3d9_renderchain_t *chain,
LPDIRECT3DDEVICE9 dev,
struct shader_pass *pass,
state_tracker_t *tracker,
unsigned pass_index)
{
unsigned i;
/* Set state parameters. */
/* Only query uniforms in first pass. */
static struct state_tracker_uniform tracker_info[GFX_MAX_VARIABLES];
static unsigned cnt = 0;
if (pass_index == 1)
cnt = state_tracker_get_uniform(tracker, tracker_info,
GFX_MAX_VARIABLES, chain->frame_count);
for (i = 0; i < cnt; i++)
{
d3d9_cg_set_param_2f(pass->fprg, dev, tracker_info[i].id, &tracker_info[i].value);
d3d9_cg_set_param_2f(pass->vprg, dev, tracker_info[i].id, &tracker_info[i].value);
}
}
static void d3d9_cg_renderchain_render_pass(
d3d9_renderchain_t *chain,
struct shader_pass *pass,
state_tracker_t *tracker,
unsigned pass_index)
{
unsigned i;
@ -974,9 +949,6 @@ static void d3d9_cg_renderchain_render_pass(
if (pass_index >= 3)
d3d9_cg_renderchain_bind_pass(chain, chain->dev, pass, pass_index);
if (tracker)
d3d9_cg_renderchain_set_params(chain, chain->dev, pass, tracker, pass_index);
d3d9_draw_primitive(chain->dev, D3DPT_TRIANGLESTRIP, 0, 2);
/* So we don't render with linear filter into render targets,
@ -990,7 +962,6 @@ static void d3d9_cg_renderchain_render_pass(
static bool d3d9_cg_renderchain_render(
d3d9_video_t *d3d,
const video_frame_info_t *video_info,
state_tracker_t *tracker,
const void *frame_data,
unsigned width, unsigned height,
unsigned pitch, unsigned rotation)
@ -1063,7 +1034,7 @@ static bool d3d9_cg_renderchain_render(
out_width, out_height, 0);
d3d9_cg_renderchain_render_pass(chain,
from_pass, tracker,
from_pass,
i + 1);
current_width = out_width;
@ -1093,7 +1064,6 @@ static bool d3d9_cg_renderchain_render(
d3d9_cg_renderchain_render_pass(chain,
last_pass,
tracker,
chain->passes->count);
chain->frame_count++;

View File

@ -468,34 +468,9 @@ static void hlsl_d3d9_renderchain_set_final_viewport(
d3d9_recompute_pass_sizes(chain->dev, chain, d3d);
}
static void d3d9_hlsl_renderchain_set_params(
d3d9_renderchain_t *chain,
LPDIRECT3DDEVICE9 dev,
struct shader_pass *pass,
state_tracker_t *tracker,
unsigned pass_index)
{
unsigned i;
/* Set state parameters. */
/* Only query uniforms in first pass. */
static struct state_tracker_uniform tracker_info[GFX_MAX_VARIABLES];
static unsigned cnt = 0;
if (pass_index == 1)
cnt = state_tracker_get_uniform(tracker, tracker_info,
GFX_MAX_VARIABLES, chain->frame_count);
for (i = 0; i < cnt; i++)
{
d3d9_hlsl_set_param_2f(pass->fprg, dev, tracker_info[i].id, &tracker_info[i].value);
d3d9_hlsl_set_param_2f(pass->vprg, dev, tracker_info[i].id, &tracker_info[i].value);
}
}
static void hlsl_d3d9_renderchain_render_pass(
hlsl_renderchain_t *chain,
struct shader_pass *pass,
state_tracker_t *tracker,
unsigned pass_index)
{
unsigned i;
@ -553,9 +528,6 @@ static void hlsl_d3d9_renderchain_render_pass(
d3d9_hlsl_renderchain_bind_pass(chain, chain->chain.dev, pass, pass_index);
#endif
if (tracker)
d3d9_hlsl_renderchain_set_params(&chain->chain,
chain->chain.dev, pass, tracker, pass_index);
d3d9_draw_primitive(chain->chain.dev, D3DPT_TRIANGLESTRIP, 0, 2);
@ -570,7 +542,6 @@ static void hlsl_d3d9_renderchain_render_pass(
static bool hlsl_d3d9_renderchain_render(
d3d9_video_t *d3d,
const video_frame_info_t *video_info,
state_tracker_t *tracker,
const void *frame,
unsigned width, unsigned height,
unsigned pitch, unsigned rotation)
@ -649,7 +620,7 @@ static bool hlsl_d3d9_renderchain_render(
chain->chain.frame_count, 0);
hlsl_d3d9_renderchain_render_pass(chain,
from_pass, tracker,
from_pass,
i + 1);
current_width = out_width;
@ -679,7 +650,6 @@ static bool hlsl_d3d9_renderchain_render(
chain->chain.frame_count, rotation);
hlsl_d3d9_renderchain_render_pass(chain, last_pass,
tracker,
chain->chain.passes->count);
chain->chain.frame_count++;

View File

@ -109,7 +109,6 @@ typedef struct cg_shader_data
CGprofile cgFProf;
struct shader_program_cg prg[GFX_MAX_SHADERS];
GLuint lut_textures[GFX_MAX_TEXTURES];
state_tracker_t *state_tracker;
CGcontext cgCtx;
} cg_shader_data_t;
@ -397,28 +396,6 @@ static void gl_cg_set_params(void *dat, void *shader_data)
cg_gl_set_param_1f(param_v, cg->shader->parameters[i].current);
cg_gl_set_param_1f(param_f, cg->shader->parameters[i].current);
}
/* Set state parameters. */
if (cg->state_tracker)
{
/* Only query uniforms in first pass. */
static struct state_tracker_uniform tracker_info[GFX_MAX_VARIABLES];
static unsigned cnt = 0;
if (cg->active_idx == 1)
cnt = state_tracker_get_uniform(cg->state_tracker, tracker_info,
GFX_MAX_VARIABLES, frame_count);
for (i = 0; i < cnt; i++)
{
CGparameter param_v = cgGetNamedParameter(
cg->prg[cg->active_idx].vprg, tracker_info[i].id);
CGparameter param_f = cgGetNamedParameter(
cg->prg[cg->active_idx].fprg, tracker_info[i].id);
cg_gl_set_param_1f(param_v, tracker_info[i].value);
cg_gl_set_param_1f(param_f, tracker_info[i].value);
}
}
}
static void gl_cg_deinit_progs(void *data)
@ -466,12 +443,6 @@ static void gl_cg_destroy_resources(void *data)
memset(cg->lut_textures, 0, sizeof(cg->lut_textures));
}
if (cg->state_tracker)
{
state_tracker_free(cg->state_tracker);
cg->state_tracker = NULL;
}
free(cg->shader);
cg->shader = NULL;
}
@ -680,72 +651,6 @@ static bool gl_cg_load_plain(void *data, const char *path)
return true;
}
static bool gl_cg_load_imports(void *data)
{
unsigned i;
retro_ctx_memory_info_t mem_info;
struct state_tracker_info tracker_info;
cg_shader_data_t *cg = (cg_shader_data_t*)data;
if (!cg->shader->variables)
return true;
for (i = 0; i < cg->shader->variables; i++)
{
unsigned memtype;
switch (cg->shader->variable[i].ram_type)
{
case RARCH_STATE_WRAM:
memtype = RETRO_MEMORY_SYSTEM_RAM;
break;
default:
memtype = -1u;
}
mem_info.id = memtype;
core_get_memory(&mem_info);
if ((memtype != -1u) &&
(cg->shader->variable[i].addr >= mem_info.size))
{
RARCH_ERR("Address out of bounds.\n");
return false;
}
}
mem_info.data = NULL;
mem_info.size = 0;
mem_info.id = RETRO_MEMORY_SYSTEM_RAM;
core_get_memory(&mem_info);
tracker_info.wram = (uint8_t*)mem_info.data;
tracker_info.info = cg->shader->variable;
tracker_info.info_elem = cg->shader->variables;
tracker_info.script = NULL;
tracker_info.script_is_file = false;
#ifdef HAVE_PYTHON
if (*cg->shader->script_path)
{
tracker_info.script = cg->shader->script_path;
tracker_info.script_is_file = true;
}
tracker_info.script_class =
*cg->shader->script_class ? cg->shader->script_class : NULL;
#endif
cg->state_tracker = state_tracker_init(&tracker_info);
if (!cg->state_tracker)
RARCH_WARN("Failed to initialize state tracker.\n");
return true;
}
static bool gl_cg_load_shader(void *data, unsigned i)
{
struct shader_program_info program_info;
@ -829,12 +734,6 @@ static bool gl_cg_load_preset(void *data, const char *path)
return false;
}
if (!gl_cg_load_imports(cg))
{
RARCH_ERR("Failed to load imports ...\n");
return false;
}
return true;
}

View File

@ -152,7 +152,6 @@ typedef struct glsl_shader_data
struct cache_vbo vbo[GFX_MAX_SHADERS];
struct shader_program_glsl_data prg[GFX_MAX_SHADERS];
struct video_shader *shader;
state_tracker_t *state_tracker;
} glsl_shader_data_t;
static bool glsl_core;
@ -660,7 +659,6 @@ static void gl_glsl_deinit_shader(glsl_shader_data_t *glsl)
free(glsl->shader->pass[i].source.string.fragment);
}
free(glsl->shader->script);
free(glsl->shader);
glsl->shader = NULL;
}
@ -695,10 +693,6 @@ static void gl_glsl_destroy_resources(glsl_shader_data_t *glsl)
gl_glsl_deinit_shader(glsl);
if (glsl->state_tracker)
state_tracker_free(glsl->state_tracker);
glsl->state_tracker = NULL;
gl_glsl_reset_attrib(glsl);
for (i = 0; i < GFX_MAX_SHADERS; i++)
@ -1022,34 +1016,6 @@ static void *gl_glsl_init(void *data, const char *path)
}
#endif
if (glsl->shader->variables)
{
retro_ctx_memory_info_t mem_info;
struct state_tracker_info info;
mem_info.id = RETRO_MEMORY_SYSTEM_RAM;
core_get_memory(&mem_info);
info.wram = (uint8_t*)mem_info.data;
info.info = glsl->shader->variable;
info.info_elem = glsl->shader->variables;
info.script = NULL;
info.script_class = NULL;
#ifdef HAVE_PYTHON
info.script = glsl->shader->script;
if (*glsl->shader->script_class)
info.script_class= glsl->shader->script_class;
#endif
info.script_is_file = false;
glsl->state_tracker = state_tracker_init(&info);
if (!glsl->state_tracker)
RARCH_WARN("Failed to init state tracker.\n");
}
glsl->prg[glsl->shader->passes + 1] = glsl->prg[0];
glsl->uniforms[glsl->shader->passes + 1] = glsl->uniforms[0];
@ -1399,25 +1365,6 @@ static void gl_glsl_set_params(void *dat, void *shader_data)
glsl->shader->parameters[i].id);
glUniform1f(location, glsl->shader->parameters[i].current);
}
/* Set state parameters. */
if (glsl->state_tracker)
{
static struct state_tracker_uniform state_info[GFX_MAX_VARIABLES];
static unsigned cnt = 0;
if (glsl->active_idx == 1)
cnt = state_tracker_get_uniform(glsl->state_tracker, state_info,
GFX_MAX_VARIABLES, frame_count);
for (i = 0; i < cnt; i++)
{
int location = glGetUniformLocation(
glsl->prg[glsl->active_idx].id,
state_info[i].id);
glUniform1f(location, state_info[i].value);
}
}
}
static bool gl_glsl_set_mvp(void *shader_data, const void *mat_data)

View File

@ -1,438 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* 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 <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <Python.h>
#include <compat/strl.h>
#include <compat/posix_string.h>
#include <streams/file_stream.h>
#include <libretro.h>
#include "video_state_python.h"
#include "../../configuration.h"
#include "../../dynamic.h"
#include "../../core.h"
#include "../../verbosity.h"
#include "../../input/input_driver.h"
static PyObject* py_read_wram(PyObject *self, PyObject *args)
{
unsigned addr;
size_t max;
retro_ctx_memory_info_t mem_info;
const uint8_t *data = NULL;
mem_info.id = RETRO_MEMORY_SYSTEM_RAM;
core_get_memory(&mem_info);
data = (const uint8_t*)mem_info.data;
(void)self;
if (!data)
{
Py_INCREF(Py_None);
return Py_None;
}
max = mem_info.size;
if (!PyArg_ParseTuple(args, "I", &addr))
return NULL;
if (addr >= max)
{
Py_INCREF(Py_None);
return Py_None;
}
return PyLong_FromLong(data[addr]);
}
static PyObject* py_read_vram(PyObject *self, PyObject *args)
{
unsigned addr;
size_t max;
retro_ctx_memory_info_t mem_info;
const uint8_t *data = NULL;
mem_info.id = RETRO_MEMORY_VIDEO_RAM;
core_get_memory(&mem_info);
data = (const uint8_t*)mem_info.data;
(void)self;
if (!data)
{
Py_INCREF(Py_None);
return Py_None;
}
max = mem_info.size;
if (!PyArg_ParseTuple(args, "I", &addr))
return NULL;
if (addr >= max)
{
Py_INCREF(Py_None);
return Py_None;
}
return PyLong_FromLong(data[addr]);
}
static PyObject *py_read_input(PyObject *self, PyObject *args)
{
unsigned user, key, i;
rarch_joypad_info_t joypad_info;
const struct retro_keybind *py_binds[MAX_USERS];
int16_t res = 0;
settings_t *settings = config_get_ptr();
for (i = 0; i < MAX_USERS; i++)
py_binds[i] = input_config_binds[i];
(void)self;
if (!PyArg_ParseTuple(args, "II", &user, &key))
return NULL;
if (user > MAX_USERS || user < 1 || key >= RARCH_FIRST_META_KEY)
return NULL;
joypad_info.joy_idx = settings->uints.input_joypad_map[user - 1];
joypad_info.auto_binds = input_autoconf_binds[joypad_info.joy_idx];
if (!input_driver_is_libretro_input_blocked())
res = input_driver_input_state(joypad_info,
py_binds,
user - 1, RETRO_DEVICE_JOYPAD, 0, key);
return PyBool_FromLong(res);
}
static PyObject *py_read_analog(PyObject *self, PyObject *args)
{
unsigned user, index, id, i;
rarch_joypad_info_t joypad_info;
const struct retro_keybind *py_binds[MAX_USERS];
int16_t res = 0;
settings_t *settings = config_get_ptr();
for (i = 0; i < MAX_USERS; i++)
py_binds[i] = input_config_binds[i];
(void)self;
if (!PyArg_ParseTuple(args, "III", &user, &index, &id))
return NULL;
if (user > MAX_USERS || user < 1 || index > 1 || id > 1)
return NULL;
joypad_info.joy_idx = settings->uints.input_joypad_map[user - 1];
joypad_info.auto_binds = input_autoconf_binds[joypad_info.joy_idx];
res = input_driver_input_state(
joypad_info, py_binds,
user - 1, RETRO_DEVICE_ANALOG, index, id);
return PyFloat_FromDouble((double)res / 0x7fff);
}
static PyMethodDef RarchMethods[] = {
{ "read_wram", py_read_wram, METH_VARARGS, "Read WRAM from system." },
{ "read_vram", py_read_vram, METH_VARARGS, "Read VRAM from system." },
{ "input", py_read_input, METH_VARARGS, "Read input state from system." },
{ "input_analog", py_read_analog, METH_VARARGS, "Read analog input state from system." },
{ NULL, NULL, 0, NULL }
};
#define DECL_ATTR_RETRO(attr) PyObject_SetAttrString(mod, #attr, PyLong_FromLong(RETRO_DEVICE_ID_JOYPAD_##attr))
static void py_set_attrs(PyObject *mod)
{
DECL_ATTR_RETRO(B);
DECL_ATTR_RETRO(Y);
DECL_ATTR_RETRO(SELECT);
DECL_ATTR_RETRO(START);
DECL_ATTR_RETRO(UP);
DECL_ATTR_RETRO(DOWN);
DECL_ATTR_RETRO(LEFT);
DECL_ATTR_RETRO(RIGHT);
DECL_ATTR_RETRO(A);
DECL_ATTR_RETRO(X);
DECL_ATTR_RETRO(L);
DECL_ATTR_RETRO(R);
DECL_ATTR_RETRO(L2);
DECL_ATTR_RETRO(R2);
DECL_ATTR_RETRO(L3);
DECL_ATTR_RETRO(R3);
PyObject_SetAttrString(mod, "ANALOG_LEFT",
PyLong_FromLong(RETRO_DEVICE_INDEX_ANALOG_LEFT));
PyObject_SetAttrString(mod, "ANALOG_RIGHT",
PyLong_FromLong(RETRO_DEVICE_INDEX_ANALOG_RIGHT));
PyObject_SetAttrString(mod, "ANALOG_X",
PyLong_FromLong(RETRO_DEVICE_ID_ANALOG_X));
PyObject_SetAttrString(mod, "ANALOG_Y",
PyLong_FromLong(RETRO_DEVICE_ID_ANALOG_Y));
}
static PyModuleDef RarchModule = {
PyModuleDef_HEAD_INIT, "rarch", NULL, -1, RarchMethods,
NULL, NULL, NULL, NULL
};
static PyObject* PyInit_Retro(void)
{
PyObject *mod = PyModule_Create(&RarchModule);
if (!mod)
return NULL;
py_set_attrs(mod);
return mod;
}
struct py_state
{
PyObject *main;
PyObject *dict;
PyObject *inst;
bool warned_ret;
bool warned_type;
};
static char *dupe_newline(const char *str)
{
unsigned size;
char *ret = NULL;
if (!str)
return NULL;
size = strlen(str) + 2;
ret = (char*)malloc(size);
if (!ret)
return NULL;
strlcpy(ret, str, size);
ret[size - 2] = '\n';
ret[size - 1] = '\0';
return ret;
}
/* Need to make sure that first-line indentation is 0. */
static char *align_program(const char *program)
{
size_t prog_size;
char *new_prog = NULL;
char *save = NULL;
char *line = NULL;
unsigned skip_chars = 0;
char *prog = strdup(program);
if (!prog)
return NULL;
prog_size = strlen(program) + 1;
new_prog = (char*)calloc(1, prog_size);
if (!new_prog)
{
free(prog);
return NULL;
}
line = dupe_newline(strtok_r(prog, "\n", &save));
if (!line)
{
free(prog);
free(new_prog);
return NULL;
}
while (isblank(line[skip_chars]) && line[skip_chars])
skip_chars++;
while (line)
{
unsigned length = strlen(line);
unsigned skip_len = skip_chars > length ? length : skip_chars;
strlcat(new_prog, line + skip_len, prog_size);
free(line);
line = dupe_newline(strtok_r(NULL, "\n", &save));
}
free(prog);
return new_prog;
}
py_state_t *py_state_new(const char *script,
unsigned is_file, const char *pyclass)
{
py_state_t *handle;
PyObject *hook;
RARCH_LOG("Initializing Python runtime ...\n");
PyImport_AppendInittab("rarch", &PyInit_Retro);
Py_Initialize();
RARCH_LOG("Initialized Python runtime.\n");
handle = (py_state_t*)calloc(1, sizeof(*handle));
hook = NULL;
handle->main = PyImport_AddModule("__main__");
if (!handle->main)
goto error;
Py_INCREF(handle->main);
if (is_file)
{
/* Have to hack around the fact that the FILE struct
* isn't standardized across environments.
* PyRun_SimpleFile() breaks on Windows because it's
* compiled with MSVC. */
int64_t len;
char *script_ = NULL;
bool ret = filestream_read_file
(script, (void**)&script_, &len);
if (!ret || len < 0)
{
RARCH_ERR("Python: Failed to read script\n");
free(script_);
goto error;
}
PyRun_SimpleString(script_);
free(script_);
}
else
{
char *script_ = align_program(script);
if (script_)
{
PyRun_SimpleString(script_);
free(script_);
}
}
RARCH_LOG("Python: Script loaded.\n");
handle->dict = PyModule_GetDict(handle->main);
if (!handle->dict)
{
RARCH_ERR("Python: PyModule_GetDict() failed.\n");
goto error;
}
Py_INCREF(handle->dict);
hook = PyDict_GetItemString(handle->dict, pyclass);
if (!hook)
{
RARCH_ERR("Python: PyDict_GetItemString() failed.\n");
goto error;
}
handle->inst = PyObject_CallFunction(hook, NULL);
if (!handle->inst)
{
RARCH_ERR("Python: PyObject_CallFunction() failed.\n");
goto error;
}
Py_INCREF(handle->inst);
return handle;
error:
PyErr_Print();
PyErr_Clear();
py_state_free(handle);
return NULL;
}
void py_state_free(py_state_t *handle)
{
if (!handle)
return;
PyErr_Print();
PyErr_Clear();
Py_CLEAR(handle->inst);
Py_CLEAR(handle->dict);
Py_CLEAR(handle->main);
free(handle);
Py_Finalize();
}
float py_state_get(py_state_t *handle, const char *id,
unsigned frame_count)
{
unsigned i;
float retval;
PyObject *ret = NULL;
settings_t *settings = config_get_ptr();
for (i = 0; i < MAX_USERS; i++)
{
struct retro_keybind *general_binds = input_config_binds[i];
struct retro_keybind *auto_binds = input_autoconf_binds[i];
enum analog_dpad_mode dpad_mode = settings->uints.input_analog_dpad_mode[i];
if (dpad_mode == ANALOG_DPAD_NONE)
continue;
input_push_analog_dpad(general_binds, dpad_mode);
input_push_analog_dpad(auto_binds, dpad_mode);
}
ret = PyObject_CallMethod(handle->inst, (char*)id, (char*)"I", frame_count);
for (i = 0; i < MAX_USERS; i++)
{
struct retro_keybind *general_binds = input_config_binds[i];
struct retro_keybind *auto_binds = input_autoconf_binds[i];
input_pop_analog_dpad(general_binds);
input_pop_analog_dpad(auto_binds);
}
if (!ret)
{
if (!handle->warned_ret)
{
RARCH_WARN("Didn't get return value from script. Bug?\n");
PyErr_Print();
PyErr_Clear();
}
handle->warned_ret = true;
return 0.0f;
}
retval = (float)PyFloat_AsDouble(ret);
Py_DECREF(ret);
return retval;
}

View File

@ -1,36 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* 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/>.
*/
#ifndef __VIDEO_STATE_PYTHON_H
#define __VIDEO_STATE_PYTHON_H
#include <stdint.h>
#include <boolean.h>
#ifndef PY_STATE_OMIT_DECLARATION
typedef struct py_state py_state_t;
#endif
py_state_t *py_state_new(const char *program,
unsigned is_file, const char *pyclass);
void py_state_free(py_state_t *handle);
float py_state_get(py_state_t *handle,
const char *id, unsigned frame_count);
#endif

View File

@ -570,144 +570,6 @@ bool video_shader_resolve_parameters(config_file_t *conf,
return true;
}
/**
* video_shader_parse_imports:
* @conf : Preset file to read from.
* @shader : Shader passes handle.
*
* Resolves import parameters belonging to shaders.
*
* Returns: true (1) if successful, otherwise false (0).
**/
static bool video_shader_parse_imports(config_file_t *conf,
struct video_shader *shader)
{
size_t path_size = PATH_MAX_LENGTH * sizeof(char);
const char *id = NULL;
char *save = NULL;
char *tmp_str = NULL;
char *imports = (char*)malloc(1024 * sizeof(char));
imports[0] = '\0';
if (!config_get_array(conf, "imports", imports,
1024 * sizeof(char)))
{
free(imports);
return true;
}
for (id = strtok_r(imports, ";", &save);
id && shader->variables < GFX_MAX_VARIABLES;
shader->variables++, id = strtok_r(NULL, ";", &save))
{
char semantic_buf[64];
char wram_buf[64];
char input_slot_buf[64];
char mask_buf[64];
char equal_buf[64];
char semantic[64];
unsigned addr = 0;
unsigned mask = 0;
unsigned equal = 0;
struct state_tracker_uniform_info *var =
&shader->variable[shader->variables];
semantic_buf[0] = wram_buf[0] = input_slot_buf[0] =
mask_buf[0] = equal_buf[0] = semantic[0] = '\0';
strlcpy(var->id, id, sizeof(var->id));
snprintf(semantic_buf, sizeof(semantic_buf), "%s_semantic", id);
if (!config_get_array(conf, semantic_buf, semantic, sizeof(semantic)))
{
RARCH_ERR("No semantic for import variable.\n");
goto error;
}
snprintf(wram_buf, sizeof(wram_buf), "%s_wram", id);
snprintf(input_slot_buf, sizeof(input_slot_buf), "%s_input_slot", id);
snprintf(mask_buf, sizeof(mask_buf), "%s_mask", id);
snprintf(equal_buf, sizeof(equal_buf), "%s_equal", id);
if (string_is_equal(semantic, "capture"))
var->type = RARCH_STATE_CAPTURE;
else if (string_is_equal(semantic, "transition"))
var->type = RARCH_STATE_TRANSITION;
else if (string_is_equal(semantic, "transition_count"))
var->type = RARCH_STATE_TRANSITION_COUNT;
else if (string_is_equal(semantic, "capture_previous"))
var->type = RARCH_STATE_CAPTURE_PREV;
else if (string_is_equal(semantic, "transition_previous"))
var->type = RARCH_STATE_TRANSITION_PREV;
else if (string_is_equal(semantic, "python"))
var->type = RARCH_STATE_PYTHON;
else
{
RARCH_ERR("Invalid semantic.\n");
goto error;
}
if (var->type != RARCH_STATE_PYTHON)
{
unsigned input_slot = 0;
if (config_get_uint(conf, input_slot_buf, &input_slot))
{
switch (input_slot)
{
case 1:
var->ram_type = RARCH_STATE_INPUT_SLOT1;
break;
case 2:
var->ram_type = RARCH_STATE_INPUT_SLOT2;
break;
default:
RARCH_ERR("Invalid input slot for import.\n");
goto error;
}
}
else if (config_get_hex(conf, wram_buf, &addr))
{
var->ram_type = RARCH_STATE_WRAM;
var->addr = addr;
}
else
{
RARCH_ERR("No address assigned to semantic.\n");
goto error;
}
}
if (config_get_hex(conf, mask_buf, &mask))
var->mask = mask;
if (config_get_hex(conf, equal_buf, &equal))
var->equal = equal;
}
tmp_str = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
if (!tmp_str)
goto error;
tmp_str[0] = '\0';
if (config_get_path(conf, "import_script", tmp_str, path_size))
strlcpy(shader->script_path, tmp_str, sizeof(shader->script_path));
config_get_array(conf, "import_script_class",
shader->script_class, sizeof(shader->script_class));
free(tmp_str);
free(imports);
return true;
error:
free(imports);
return false;
}
/**
* video_shader_read_conf_preset:
* @conf : Preset file to read from.
@ -799,9 +661,6 @@ bool video_shader_read_conf_preset(config_file_t *conf,
if (!video_shader_parse_textures(conf, shader))
return false;
if (!video_shader_parse_imports(conf, shader))
return false;
return true;
}
@ -863,87 +722,6 @@ static void shader_write_fbo(config_file_t *conf,
fbo->scale_y, fbo->abs_y, i);
}
/**
* import_semantic_to_string:
* @type : Import semantic type from state tracker.
*
* Translates import semantic to human-readable string identifier.
*
* Returns: human-readable string identifier of import semantic.
**/
static const char *import_semantic_to_str(enum state_tracker_type type)
{
switch (type)
{
case RARCH_STATE_CAPTURE:
return "capture";
case RARCH_STATE_TRANSITION:
return "transition";
case RARCH_STATE_TRANSITION_COUNT:
return "transition_count";
case RARCH_STATE_CAPTURE_PREV:
return "capture_previous";
case RARCH_STATE_TRANSITION_PREV:
return "transition_previous";
case RARCH_STATE_PYTHON:
return "python";
default:
break;
}
return "?";
}
/**
* shader_write_variable:
* @conf : Preset file to read from.
* @info : State tracker uniform info handle.
*
* Writes variable to shader preset file.
**/
static void shader_write_variable(config_file_t *conf,
const struct state_tracker_uniform_info *info)
{
char semantic_buf[64];
char wram_buf[64];
char input_slot_buf[64];
char mask_buf[64];
char equal_buf[64];
const char *id = info->id;
semantic_buf[0] = wram_buf[0] = input_slot_buf[0] =
mask_buf[0] = equal_buf[0] = '\0';
snprintf(semantic_buf, sizeof(semantic_buf), "%s_semantic", id);
snprintf(wram_buf, sizeof(wram_buf), "%s_wram", id);
snprintf(input_slot_buf, sizeof(input_slot_buf), "%s_input_slot", id);
snprintf(mask_buf, sizeof(mask_buf), "%s_mask", id);
snprintf(equal_buf, sizeof(equal_buf), "%s_equal", id);
config_set_string(conf, semantic_buf,
import_semantic_to_str(info->type));
config_set_hex(conf, mask_buf, info->mask);
config_set_hex(conf, equal_buf, info->equal);
switch (info->ram_type)
{
case RARCH_STATE_INPUT_SLOT1:
config_set_int(conf, input_slot_buf, 1);
break;
case RARCH_STATE_INPUT_SLOT2:
config_set_int(conf, input_slot_buf, 2);
break;
case RARCH_STATE_WRAM:
config_set_hex(conf, wram_buf, info->addr);
break;
case RARCH_STATE_NONE:
break;
}
}
/**
* video_shader_write_conf_preset:
* @conf : Preset file to write to.
@ -1096,36 +874,6 @@ void video_shader_write_conf_preset(config_file_t *conf,
}
}
}
if (*shader->script_path)
config_set_string(conf, "import_script", shader->script_path);
if (*shader->script_class)
config_set_string(conf, "import_script_class", shader->script_class);
if (shader->variables)
{
size_t var_tmp = 4096 * sizeof(char);
char *variables = (char*)malloc(var_tmp);
if (variables)
{
variables[0] = '\0';
strlcpy(variables, shader->variable[0].id, var_tmp);
for (i = 1; i < shader->variables; i++)
{
strlcat(variables, ";", var_tmp);
strlcat(variables, shader->variable[i].id, var_tmp);
}
config_set_string(conf, "imports", variables);
for (i = 0; i < shader->variables; i++)
shader_write_variable(conf, &shader->variable[i]);
free(variables);
}
}
}
const char *video_shader_to_str(enum rarch_shader_type type)
@ -1297,13 +1045,6 @@ void video_shader_resolve_relative(struct video_shader *shader,
ref_path, tmp_path, sizeof(shader->lut[i].path));
}
if (*shader->script_path)
{
strlcpy(tmp_path, shader->script_path, tmp_path_size);
fill_pathname_resolve_relative(shader->script_path,
ref_path, tmp_path, sizeof(shader->script_path));
}
free(tmp_path);
}

View File

@ -17,8 +17,6 @@
#ifndef __VIDEO_SHADER_PARSE_H
#define __VIDEO_SHADER_PARSE_H
#include "video_state_tracker.h"
#include <boolean.h>
#include <retro_common_api.h>
#include <retro_miscellaneous.h>
@ -142,11 +140,7 @@ struct video_shader_lut
struct video_shader
{
char prefix[64];
char script_class[512];
char script_path[PATH_MAX_LENGTH];
char path[PATH_MAX_LENGTH];
char *script; /* Dynamically allocated. Must be free'd. Only used by XML. */
bool modern; /* Only used for XML shaders. */
unsigned passes;
@ -163,7 +157,6 @@ struct video_shader
struct video_shader_lut lut[GFX_MAX_TEXTURES];
struct video_shader_parameter parameters[GFX_MAX_PARAMETERS];
struct state_tracker_uniform_info variable[GFX_MAX_VARIABLES];
};
/**

View File

@ -1,296 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* 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 <stdlib.h>
#include <compat/strl.h>
#include <retro_inline.h>
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#ifdef HAVE_PYTHON
#include "drivers_tracker/video_state_python.h"
#endif
#include "video_state_tracker.h"
#include "../input/input_driver.h"
#include "../verbosity.h"
struct state_tracker_internal
{
char id[64];
bool is_input;
const uint16_t *input_ptr;
const uint8_t *ptr;
#ifdef HAVE_PYTHON
py_state_t *py;
#endif
uint32_t addr;
uint16_t mask;
uint16_t equal;
enum state_tracker_type type;
uint32_t prev[2];
int frame_count;
int frame_count_prev;
uint32_t old_value;
int transition_count;
};
struct state_tracker
{
struct state_tracker_internal *info;
unsigned info_elem;
uint16_t input_state[2];
#ifdef HAVE_PYTHON
py_state_t *py;
#endif
};
/**
* state_tracker_init:
* @info : State tracker info handle.
*
* Creates and initializes graphics state tracker.
*
* Returns: new state tracker handle if successful, otherwise NULL.
**/
state_tracker_t* state_tracker_init(const struct state_tracker_info *info)
{
unsigned i;
struct state_tracker_internal *tracker_info = NULL;
state_tracker_t *tracker = (state_tracker_t*)
calloc(1, sizeof(*tracker));
if (!tracker)
return NULL;
#ifdef HAVE_PYTHON
if (info->script)
{
tracker->py = py_state_new(info->script, info->script_is_file,
info->script_class ? info->script_class : "GameAware");
if (!tracker->py)
{
RARCH_ERR("Failed to initialize Python script.\n");
goto error;
}
}
#endif
tracker_info = (struct state_tracker_internal*)
calloc(info->info_elem, sizeof(struct state_tracker_internal));
if (!tracker_info)
goto error;
tracker->info = tracker_info;
tracker->info_elem = info->info_elem;
for (i = 0; i < info->info_elem; i++)
{
/* If we don't have a valid pointer. */
static const uint8_t empty = 0;
strlcpy(tracker->info[i].id, info->info[i].id,
sizeof(tracker->info[i].id));
tracker->info[i].addr = info->info[i].addr;
tracker->info[i].type = info->info[i].type;
tracker->info[i].mask = (info->info[i].mask == 0)
? 0xffff : info->info[i].mask;
tracker->info[i].equal = info->info[i].equal;
#ifdef HAVE_PYTHON
if (info->info[i].type == RARCH_STATE_PYTHON)
{
if (!tracker->py)
{
RARCH_ERR("Python semantic was requested, but Python tracker is not loaded.\n");
free(tracker->info);
goto error;
}
tracker->info[i].py = tracker->py;
}
#endif
switch (info->info[i].ram_type)
{
case RARCH_STATE_WRAM:
tracker->info[i].ptr = info->wram ? info->wram : &empty;
break;
case RARCH_STATE_INPUT_SLOT1:
tracker->info[i].input_ptr = &tracker->input_state[0];
tracker->info[i].is_input = true;
break;
case RARCH_STATE_INPUT_SLOT2:
tracker->info[i].input_ptr = &tracker->input_state[1];
tracker->info[i].is_input = true;
break;
default:
tracker->info[i].ptr = &empty;
}
}
return tracker;
error:
RARCH_ERR("Allocation of state tracker info failed.\n");
free(tracker);
return NULL;
}
/**
* state_tracker_free:
* @tracker : State tracker handle.
*
* Frees a state tracker handle.
**/
void state_tracker_free(state_tracker_t *tracker)
{
if (tracker)
{
free(tracker->info);
#ifdef HAVE_PYTHON
py_state_free(tracker->py);
#endif
}
free(tracker);
}
static INLINE uint16_t state_tracker_fetch(
const struct state_tracker_internal *info)
{
uint16_t val = info->ptr[info->addr];
if (info->is_input)
val = *info->input_ptr;
val &= info->mask;
if (info->equal && val != info->equal)
val = 0;
return val;
}
static void state_tracker_update_element(
struct state_tracker_uniform *uniform,
struct state_tracker_internal *info,
unsigned frame_count)
{
uniform->id = info->id;
switch (info->type)
{
case RARCH_STATE_CAPTURE:
uniform->value = state_tracker_fetch(info);
break;
case RARCH_STATE_CAPTURE_PREV:
if (info->prev[0] != state_tracker_fetch(info))
{
info->prev[1] = info->prev[0];
info->prev[0] = state_tracker_fetch(info);
}
uniform->value = info->prev[1];
break;
case RARCH_STATE_TRANSITION:
if (info->old_value != state_tracker_fetch(info))
{
info->old_value = state_tracker_fetch(info);
info->frame_count = frame_count;
}
uniform->value = info->frame_count;
break;
case RARCH_STATE_TRANSITION_COUNT:
if (info->old_value != state_tracker_fetch(info))
{
info->old_value = state_tracker_fetch(info);
info->transition_count++;
}
uniform->value = info->transition_count;
break;
case RARCH_STATE_TRANSITION_PREV:
if (info->old_value != state_tracker_fetch(info))
{
info->old_value = state_tracker_fetch(info);
info->frame_count_prev = info->frame_count;
info->frame_count = frame_count;
}
uniform->value = info->frame_count_prev;
break;
#ifdef HAVE_PYTHON
case RARCH_STATE_PYTHON:
uniform->value = py_state_get(info->py, info->id, frame_count);
break;
#endif
default:
break;
}
}
void state_tracker_update_input(uint16_t *input1, uint16_t *input2);
/**
* state_tracker_get_uniform:
* @tracker : State tracker handle.
* @uniforms : State tracker uniforms.
* @elem : Amount of uniform elements.
* @frame_count : Frame count.
*
* Calls state_tracker_update_input(), and updates each uniform
* element accordingly.
*
* Returns: Amount of state elements (either equal to @elem
* or equal to @tracker->info_eleme).
**/
unsigned state_tracker_get_uniform(state_tracker_t *tracker,
struct state_tracker_uniform *uniforms,
unsigned elem, unsigned frame_count)
{
unsigned i, elems = elem;
if (tracker->info_elem < elem)
elems = tracker->info_elem;
state_tracker_update_input(&tracker->input_state[0], &tracker->input_state[1]);
for (i = 0; i < elems; i++)
state_tracker_update_element(
&uniforms[i], &tracker->info[i], frame_count);
return elems;
}

View File

@ -1,112 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* 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/>.
*/
#ifndef __VIDEO_STATE_TRACKER_H
#define __VIDEO_STATE_TRACKER_H
#include <stdint.h>
#include <boolean.h>
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
enum state_tracker_type
{
RARCH_STATE_CAPTURE = 0,
RARCH_STATE_CAPTURE_PREV,
RARCH_STATE_TRANSITION,
RARCH_STATE_TRANSITION_COUNT,
RARCH_STATE_TRANSITION_PREV,
RARCH_STATE_PYTHON
};
enum state_ram_type
{
RARCH_STATE_NONE,
RARCH_STATE_WRAM,
RARCH_STATE_INPUT_SLOT1,
RARCH_STATE_INPUT_SLOT2
};
struct state_tracker_uniform_info
{
enum state_tracker_type type;
enum state_ram_type ram_type;
char id[64];
uint16_t mask;
uint16_t equal;
uint32_t addr;
};
struct state_tracker_info
{
const char *script;
const char *script_class;
bool script_is_file;
const uint8_t *wram;
unsigned info_elem;
const struct state_tracker_uniform_info *info;
};
struct state_tracker_uniform
{
const char *id;
float value;
};
typedef struct state_tracker state_tracker_t;
/**
* state_tracker_init:
* @info : State tracker info handle.
*
* Creates and initializes graphics state tracker.
*
* Returns: new state tracker handle if successful, otherwise NULL.
**/
state_tracker_t* state_tracker_init(const struct state_tracker_info *info);
/**
* state_tracker_free:
* @tracker : State tracker handle.
*
* Frees a state tracker handle.
**/
void state_tracker_free(state_tracker_t *tracker);
/**
* state_tracker_get_uniform:
* @tracker : State tracker handle.
* @uniforms : State tracker uniforms.
* @elem : Amount of uniform elements.
* @frame_count : Frame count.
*
* Calls update_input(), and updates each uniform
* element accordingly.
*
* Returns: Amount of state elements (either equal to @elem
* or equal to @tracker->info_eleme).
**/
unsigned state_tracker_get_uniform(state_tracker_t *tracker,
struct state_tracker_uniform *uniforms,
unsigned elem, unsigned frame_count);
void state_tracker_update_input(uint16_t *input1, uint16_t *input2);
RETRO_END_DECLS
#endif

View File

@ -729,15 +729,6 @@ INPUT (HID)
#include "../input/drivers_keyboard/keyboard_event_xkb.c"
#endif
/*============================================================
STATE TRACKER
============================================================ */
#include "../gfx/video_state_tracker.c"
#ifdef HAVE_PYTHON
#include "../gfx/drivers_tracker/video_state_python.c"
#endif
/*============================================================
FIFO BUFFER
============================================================ */

View File

@ -484,8 +484,6 @@ else
check_lib '' VULKAN -lvulkan vkCreateInstance
fi
check_pkgconf PYTHON 'python3 python3 python-3.7 python-3.6 python-3.5 python-3.4 python-3.3 python-3.2'
if [ "$HAVE_MENU" != 'no' ]; then
if [ "$HAVE_OPENGL" = 'no' ] && [ "$HAVE_OPENGLES" = 'no' ] && [ "$HAVE_VULKAN" = 'no' ]; then
if [ "$OS" = 'Win32' ]; then

View File

@ -103,8 +103,6 @@ HAVE_STB_IMAGE=yes # stb image loading support
HAVE_STB_VORBIS=yes # stb vorbis support
HAVE_IBXM=yes # IBXM support
HAVE_XVIDEO=auto # XVideo support
HAVE_PYTHON=no # Python 3 support for shaders
C89_PYTHON=no
HAVE_V4L2=auto # Video4linux2 support
HAVE_NEON=no # ARM NEON optimizations
HAVE_SSE=no # x86 SSE optimizations (SSE, SSE2)

View File

@ -3659,71 +3659,6 @@ int16_t input_state(unsigned port, unsigned device,
return result;
}
/**
* state_tracker_update_input:
*
* Updates 16-bit input in same format as libretro API itself.
**/
void state_tracker_update_input(uint16_t *input1, uint16_t *input2)
{
unsigned i;
const struct retro_keybind *binds[MAX_USERS];
settings_t *settings = configuration_settings;
uint8_t max_users = (uint8_t)input_driver_max_users;
for (i = 0; i < max_users; i++)
{
struct retro_keybind *general_binds = input_config_binds[i];
struct retro_keybind *auto_binds = input_autoconf_binds[i];
enum analog_dpad_mode dpad_mode = (enum analog_dpad_mode)settings->uints.input_analog_dpad_mode[i];
binds[i] = input_config_binds[i];
if (dpad_mode == ANALOG_DPAD_NONE)
continue;
input_push_analog_dpad(general_binds, dpad_mode);
input_push_analog_dpad(auto_binds, dpad_mode);
}
if (!input_driver_block_libretro_input)
{
rarch_joypad_info_t joypad_info;
joypad_info.axis_threshold = input_driver_axis_threshold;
for (i = 4; i < 16; i++)
{
unsigned id = buttons[i - 4];
if (binds[0][id].valid)
{
joypad_info.joy_idx = settings->uints.input_joypad_map[0];
joypad_info.auto_binds = input_autoconf_binds[joypad_info.joy_idx];
*input1 |= (current_input->input_state(current_input_data, joypad_info,
binds,
0, RETRO_DEVICE_JOYPAD, 0, id) ? 1 : 0) << i;
}
if (binds[1][id].valid)
{
joypad_info.joy_idx = settings->uints.input_joypad_map[1];
joypad_info.auto_binds = input_autoconf_binds[joypad_info.joy_idx];
*input2 |= (current_input->input_state(current_input_data, joypad_info,
binds,
1, RETRO_DEVICE_JOYPAD, 0, id) ? 1 : 0) << i;
}
}
}
for (i = 0; i < max_users; i++)
{
struct retro_keybind *general_binds = input_config_binds[i];
struct retro_keybind *auto_binds = input_autoconf_binds[i];
input_pop_analog_dpad(general_binds);
input_pop_analog_dpad(auto_binds);
}
}
static INLINE bool input_keys_pressed_other_sources(unsigned i,
input_bits_t* p_new_state)
{