mirror of
https://github.com/libretro/RetroArch.git
synced 2025-02-22 02:30:56 +00:00
Inline XML python.
This commit is contained in:
parent
e02d9f41e8
commit
3717f7442c
@ -17,11 +17,15 @@
|
|||||||
|
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "dynamic.h"
|
#include "dynamic.h"
|
||||||
#include "libsnes.hpp"
|
#include "libsnes.hpp"
|
||||||
#include <stdlib.h>
|
|
||||||
#include "py_state.h"
|
#include "py_state.h"
|
||||||
#include "general.h"
|
#include "general.h"
|
||||||
|
#include "strl.h"
|
||||||
|
|
||||||
#define PY_READ_FUNC_DECL(RAMTYPE) py_read_##RAMTYPE
|
#define PY_READ_FUNC_DECL(RAMTYPE) py_read_##RAMTYPE
|
||||||
#define PY_READ_FUNC(RAMTYPE) \
|
#define PY_READ_FUNC(RAMTYPE) \
|
||||||
@ -85,7 +89,62 @@ struct py_state
|
|||||||
bool warned_type;
|
bool warned_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
py_state_t *py_state_new(const char *script_path, const char *pyclass)
|
static char *dupe_newline(const char *str)
|
||||||
|
{
|
||||||
|
if (!str)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
unsigned size = strlen(str) + 2;
|
||||||
|
char *ret = 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)
|
||||||
|
{
|
||||||
|
char *prog = strdup(program);
|
||||||
|
if (!prog)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
size_t prog_size = strlen(program) + 1;
|
||||||
|
char *new_prog = calloc(1, prog_size);
|
||||||
|
if (!new_prog)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char *line = dupe_newline(strtok(prog, "\n"));
|
||||||
|
if (!line)
|
||||||
|
{
|
||||||
|
free(prog);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned skip_chars = 0;
|
||||||
|
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(NULL, "\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
free(prog);
|
||||||
|
|
||||||
|
return new_prog;
|
||||||
|
}
|
||||||
|
|
||||||
|
py_state_t *py_state_new(const char *script, bool is_file, const char *pyclass)
|
||||||
{
|
{
|
||||||
PyImport_AppendInittab("snes", &PyInit_SNES);
|
PyImport_AppendInittab("snes", &PyInit_SNES);
|
||||||
Py_Initialize();
|
Py_Initialize();
|
||||||
@ -96,11 +155,23 @@ py_state_t *py_state_new(const char *script_path, const char *pyclass)
|
|||||||
if (!handle->main)
|
if (!handle->main)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
FILE *file = fopen(script_path, "r");
|
if (is_file)
|
||||||
if (!file)
|
{
|
||||||
goto error;
|
FILE *file = fopen(script, "r");
|
||||||
PyRun_SimpleFile(file, script_path);
|
if (!file)
|
||||||
fclose(file);
|
goto error;
|
||||||
|
PyRun_SimpleFile(file, script);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *script_ = align_program(script);
|
||||||
|
if (script_)
|
||||||
|
{
|
||||||
|
PyRun_SimpleString(script_);
|
||||||
|
free(script_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handle->dict = PyModule_GetDict(handle->main);
|
handle->dict = PyModule_GetDict(handle->main);
|
||||||
if (!handle->dict)
|
if (!handle->dict)
|
||||||
|
@ -19,10 +19,11 @@
|
|||||||
#define __SSNES_PY_STATE_H
|
#define __SSNES_PY_STATE_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef struct py_state py_state_t;
|
typedef struct py_state py_state_t;
|
||||||
|
|
||||||
py_state_t *py_state_new(const char *program, const char *pyclass);
|
py_state_t *py_state_new(const char *program, bool is_file, const char *pyclass);
|
||||||
void py_state_free(py_state_t *handle);
|
void py_state_free(py_state_t *handle);
|
||||||
|
|
||||||
int py_state_get(py_state_t *handle,
|
int py_state_get(py_state_t *handle,
|
||||||
|
@ -527,6 +527,8 @@ static bool load_imports(const char *dir_path, config_file_t *conf)
|
|||||||
}
|
}
|
||||||
if (config_get_string(conf, "import_script_class", &script_class))
|
if (config_get_string(conf, "import_script_class", &script_class))
|
||||||
tracker_info.script_class = script_class;
|
tracker_info.script_class = script_class;
|
||||||
|
|
||||||
|
tracker_info.script_is_file = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
snes_tracker = snes_tracker_init(&tracker_info);
|
snes_tracker = snes_tracker_init(&tracker_info);
|
||||||
|
@ -118,6 +118,7 @@ static struct snes_tracker_uniform_info gl_tracker_info[MAX_VARIABLES];
|
|||||||
static unsigned gl_tracker_info_cnt = 0;
|
static unsigned gl_tracker_info_cnt = 0;
|
||||||
static char gl_tracker_script[256];
|
static char gl_tracker_script[256];
|
||||||
static char gl_tracker_script_class[64];
|
static char gl_tracker_script_class[64];
|
||||||
|
static xmlChar *gl_script_program = NULL;
|
||||||
|
|
||||||
struct shader_program
|
struct shader_program
|
||||||
{
|
{
|
||||||
@ -380,6 +381,43 @@ error:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool get_script(xmlNodePtr ptr)
|
||||||
|
{
|
||||||
|
if (*gl_tracker_script)
|
||||||
|
{
|
||||||
|
SSNES_ERR("Script already imported.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlChar *script_class = xmlGetProp(ptr, (const xmlChar*)"class");
|
||||||
|
if (script_class)
|
||||||
|
{
|
||||||
|
strlcpy(gl_tracker_script_class, (const char*)script_class, sizeof(gl_tracker_script_class));
|
||||||
|
xmlFree(script_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlChar *language = xmlGetProp(ptr, (const xmlChar*)"language");
|
||||||
|
if (!language || strcmp((const char*)language, "python") != 0)
|
||||||
|
{
|
||||||
|
SSNES_ERR("Script language is not Python!\n");
|
||||||
|
if (language)
|
||||||
|
xmlFree(language);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (language)
|
||||||
|
xmlFree(language);
|
||||||
|
|
||||||
|
xmlChar *script = xmlNodeGetContent(ptr);
|
||||||
|
if (!script)
|
||||||
|
{
|
||||||
|
SSNES_ERR("No content in script!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gl_script_program = script;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool get_import_value(const char *path, xmlNodePtr ptr)
|
static bool get_import_value(const char *path, xmlNodePtr ptr)
|
||||||
{
|
{
|
||||||
if (gl_tracker_info_cnt >= MAX_VARIABLES)
|
if (gl_tracker_info_cnt >= MAX_VARIABLES)
|
||||||
@ -390,7 +428,7 @@ static bool get_import_value(const char *path, xmlNodePtr ptr)
|
|||||||
|
|
||||||
#ifdef HAVE_PYTHON
|
#ifdef HAVE_PYTHON
|
||||||
xmlChar *script = xmlGetProp(ptr, (const xmlChar*)"script");
|
xmlChar *script = xmlGetProp(ptr, (const xmlChar*)"script");
|
||||||
if (script && *gl_tracker_script)
|
if (script && (*gl_tracker_script || gl_script_program))
|
||||||
{
|
{
|
||||||
SSNES_ERR("Cannot define more than one script!\n");
|
SSNES_ERR("Cannot define more than one script!\n");
|
||||||
return false;
|
return false;
|
||||||
@ -635,6 +673,14 @@ static unsigned get_xml_shaders(const char *path, struct shader_program *prog, s
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (strcmp((const char*)cur->name, "script") == 0)
|
||||||
|
{
|
||||||
|
if (!get_script(cur))
|
||||||
|
{
|
||||||
|
SSNES_ERR("Script is invalid.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
@ -860,11 +906,20 @@ bool gl_glsl_init(const char *path)
|
|||||||
.oam = psnes_get_memory_data(SNES_MEMORY_OAM),
|
.oam = psnes_get_memory_data(SNES_MEMORY_OAM),
|
||||||
.info = gl_tracker_info,
|
.info = gl_tracker_info,
|
||||||
.info_elem = gl_tracker_info_cnt,
|
.info_elem = gl_tracker_info_cnt,
|
||||||
#ifdef HAVE_PYTHON
|
|
||||||
.script = *gl_tracker_script ? gl_tracker_script : NULL,
|
|
||||||
.script_class = *gl_tracker_script_class ? gl_tracker_script_class : NULL
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
if (*gl_tracker_script)
|
||||||
|
info.script = gl_tracker_script;
|
||||||
|
else if (gl_script_program)
|
||||||
|
info.script = (const char*)gl_script_program;
|
||||||
|
else
|
||||||
|
info.script = NULL;
|
||||||
|
|
||||||
|
info.script_class = *gl_tracker_script_class ? gl_tracker_script_class : NULL;
|
||||||
|
info.script_is_file = *gl_tracker_script;
|
||||||
|
#endif
|
||||||
|
|
||||||
gl_snes_tracker = snes_tracker_init(&info);
|
gl_snes_tracker = snes_tracker_init(&info);
|
||||||
if (!gl_snes_tracker)
|
if (!gl_snes_tracker)
|
||||||
SSNES_WARN("Failed to init SNES tracker!\n");
|
SSNES_WARN("Failed to init SNES tracker!\n");
|
||||||
@ -911,6 +966,11 @@ void gl_glsl_deinit(void)
|
|||||||
memset(gl_tracker_info, 0, sizeof(gl_tracker_info));
|
memset(gl_tracker_info, 0, sizeof(gl_tracker_info));
|
||||||
memset(gl_tracker_script, 0, sizeof(gl_tracker_script));
|
memset(gl_tracker_script, 0, sizeof(gl_tracker_script));
|
||||||
memset(gl_tracker_script_class, 0, sizeof(gl_tracker_script_class));
|
memset(gl_tracker_script_class, 0, sizeof(gl_tracker_script_class));
|
||||||
|
if (gl_script_program)
|
||||||
|
{
|
||||||
|
xmlFree(gl_script_program);
|
||||||
|
gl_script_program = NULL;
|
||||||
|
}
|
||||||
if (gl_snes_tracker)
|
if (gl_snes_tracker)
|
||||||
{
|
{
|
||||||
snes_tracker_free(gl_snes_tracker);
|
snes_tracker_free(gl_snes_tracker);
|
||||||
|
@ -64,7 +64,7 @@ snes_tracker_t* snes_tracker_init(const struct snes_tracker_info *info)
|
|||||||
#ifdef HAVE_PYTHON
|
#ifdef HAVE_PYTHON
|
||||||
if (info->script)
|
if (info->script)
|
||||||
{
|
{
|
||||||
tracker->py = py_state_new(info->script, info->script_class ? info->script_class : "GameAware");
|
tracker->py = py_state_new(info->script, info->script_is_file, info->script_class ? info->script_class : "GameAware");
|
||||||
if (!tracker->py)
|
if (!tracker->py)
|
||||||
{
|
{
|
||||||
free(tracker);
|
free(tracker);
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#define __SSNES_SNES_STATE_H
|
#define __SSNES_SNES_STATE_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -68,6 +69,7 @@ struct snes_tracker_info
|
|||||||
#ifdef HAVE_PYTHON
|
#ifdef HAVE_PYTHON
|
||||||
const char *script;
|
const char *script;
|
||||||
const char *script_class;
|
const char *script_class;
|
||||||
|
bool script_is_file;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user