From 3717f7442c8000f0bddbe998c3b91ab6a941fb04 Mon Sep 17 00:00:00 2001 From: Themaister Date: Tue, 7 Jun 2011 15:33:29 +0200 Subject: [PATCH] Inline XML python. --- gfx/py_state/py_state.c | 85 +++++++++++++++++++++++++++++++++++++---- gfx/py_state/py_state.h | 3 +- gfx/shader_cg.c | 2 + gfx/shader_glsl.c | 70 ++++++++++++++++++++++++++++++--- gfx/snes_state.c | 2 +- gfx/snes_state.h | 2 + 6 files changed, 150 insertions(+), 14 deletions(-) diff --git a/gfx/py_state/py_state.c b/gfx/py_state/py_state.c index ae060090e0..da39cdef81 100644 --- a/gfx/py_state/py_state.c +++ b/gfx/py_state/py_state.c @@ -17,11 +17,15 @@ #include #include +#include +#include +#include + #include "dynamic.h" #include "libsnes.hpp" -#include #include "py_state.h" #include "general.h" +#include "strl.h" #define PY_READ_FUNC_DECL(RAMTYPE) py_read_##RAMTYPE #define PY_READ_FUNC(RAMTYPE) \ @@ -85,7 +89,62 @@ struct py_state 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); Py_Initialize(); @@ -96,11 +155,23 @@ py_state_t *py_state_new(const char *script_path, const char *pyclass) if (!handle->main) goto error; - FILE *file = fopen(script_path, "r"); - if (!file) - goto error; - PyRun_SimpleFile(file, script_path); - fclose(file); + if (is_file) + { + FILE *file = fopen(script, "r"); + if (!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); if (!handle->dict) diff --git a/gfx/py_state/py_state.h b/gfx/py_state/py_state.h index 6fb398c672..d3a1db7af7 100644 --- a/gfx/py_state/py_state.h +++ b/gfx/py_state/py_state.h @@ -19,10 +19,11 @@ #define __SSNES_PY_STATE_H #include +#include 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); int py_state_get(py_state_t *handle, diff --git a/gfx/shader_cg.c b/gfx/shader_cg.c index 8d954aaa0d..cb94efcacb 100644 --- a/gfx/shader_cg.c +++ b/gfx/shader_cg.c @@ -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)) tracker_info.script_class = script_class; + + tracker_info.script_is_file = true; #endif snes_tracker = snes_tracker_init(&tracker_info); diff --git a/gfx/shader_glsl.c b/gfx/shader_glsl.c index 51762b731d..3b95553feb 100644 --- a/gfx/shader_glsl.c +++ b/gfx/shader_glsl.c @@ -118,6 +118,7 @@ static struct snes_tracker_uniform_info gl_tracker_info[MAX_VARIABLES]; static unsigned gl_tracker_info_cnt = 0; static char gl_tracker_script[256]; static char gl_tracker_script_class[64]; +static xmlChar *gl_script_program = NULL; struct shader_program { @@ -380,6 +381,43 @@ error: 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) { if (gl_tracker_info_cnt >= MAX_VARIABLES) @@ -390,7 +428,7 @@ static bool get_import_value(const char *path, xmlNodePtr ptr) #ifdef HAVE_PYTHON 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"); return false; @@ -635,6 +673,14 @@ static unsigned get_xml_shaders(const char *path, struct shader_program *prog, s 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) @@ -860,11 +906,20 @@ bool gl_glsl_init(const char *path) .oam = psnes_get_memory_data(SNES_MEMORY_OAM), .info = gl_tracker_info, .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); if (!gl_snes_tracker) 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_script, 0, sizeof(gl_tracker_script)); 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) { snes_tracker_free(gl_snes_tracker); diff --git a/gfx/snes_state.c b/gfx/snes_state.c index 187a7a5ea0..d1b706f00b 100644 --- a/gfx/snes_state.c +++ b/gfx/snes_state.c @@ -64,7 +64,7 @@ snes_tracker_t* snes_tracker_init(const struct snes_tracker_info *info) #ifdef HAVE_PYTHON 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) { free(tracker); diff --git a/gfx/snes_state.h b/gfx/snes_state.h index dd615cd685..8c3f071975 100644 --- a/gfx/snes_state.h +++ b/gfx/snes_state.h @@ -19,6 +19,7 @@ #define __SSNES_SNES_STATE_H #include +#include #ifdef HAVE_CONFIG_H #include "config.h" @@ -68,6 +69,7 @@ struct snes_tracker_info #ifdef HAVE_PYTHON const char *script; const char *script_class; + bool script_is_file; #endif };