diff --git a/gfx/shader_glsl.c b/gfx/shader_glsl.c index 068a103daf..305ff43171 100644 --- a/gfx/shader_glsl.c +++ b/gfx/shader_glsl.c @@ -20,6 +20,8 @@ #include "general.h" #include "shader_glsl.h" #include "strl.h" +#include "snes_state.h" +#include "dynamic.h" #ifdef __APPLE__ #include @@ -91,6 +93,7 @@ static PFNGLVERTEXATTRIBPOINTERPROC pglVertexAttribPointer = NULL; #define MAX_PROGRAMS 16 #define MAX_TEXTURES 8 +#define MAX_VARIABLES 256 enum filter_type { @@ -110,6 +113,10 @@ static GLuint gl_teximage[MAX_TEXTURES]; static unsigned gl_teximage_cnt = 0; static char gl_teximage_uniforms[MAX_TEXTURES][64]; +static snes_tracker_t *gl_snes_tracker = NULL; +static struct snes_tracker_uniform_info gl_tracker_info[MAX_VARIABLES]; +static unsigned gl_tracker_info_cnt = 0; + struct shader_program { char *vertex; @@ -371,6 +378,102 @@ error: return false; } +static bool get_import_value(xmlNodePtr ptr) +{ + xmlChar *id = xmlGetProp(ptr, (const xmlChar*)"id"); + xmlChar *semantic = xmlGetProp(ptr, (const xmlChar*)"semantic"); + xmlChar *wram = xmlGetProp(ptr, (const xmlChar*)"wram"); + xmlChar *apuram = xmlGetProp(ptr, (const xmlChar*)"apuram"); + xmlChar *vram = xmlGetProp(ptr, (const xmlChar*)"vram"); + xmlChar *oam = xmlGetProp(ptr, (const xmlChar*)"oam"); + xmlChar *cgram = xmlGetProp(ptr, (const xmlChar*)"cgram"); + + if (!semantic || !id) + { + SSNES_ERR("No semantic or ID for import value!\n"); + goto error; + } + + enum snes_ram_type ram_type; + enum snes_tracker_type tracker_type; + uint32_t addr = 0; + + if (wram) { addr = strtoul((const char*)wram, NULL, 16); ram_type = SSNES_STATE_WRAM; } + else if (apuram) { addr = strtoul((const char*)apuram, NULL, 16); ram_type = SSNES_STATE_APURAM; } + else if (vram) { addr = strtoul((const char*)vram, NULL, 16); ram_type = SSNES_STATE_VRAM; } + else if (oam) { addr = strtoul((const char*)oam, NULL, 16); ram_type = SSNES_STATE_OAM; } + else if (cgram) { addr = strtoul((const char*)cgram, NULL, 16); ram_type = SSNES_STATE_CGRAM; } + else + { + SSNES_ERR("No RAM address specificed for import value.\n"); + goto error; + } + + switch (ram_type) + { + case SSNES_STATE_WRAM: + if (addr >= psnes_get_memory_size(SNES_MEMORY_WRAM)) + goto error; + break; + case SSNES_STATE_VRAM: + if (addr >= psnes_get_memory_size(SNES_MEMORY_VRAM)) + goto error; + break; + case SSNES_STATE_APURAM: + if (addr >= psnes_get_memory_size(SNES_MEMORY_APURAM)) + goto error; + break; + case SSNES_STATE_OAM: + if (addr >= psnes_get_memory_size(SNES_MEMORY_OAM)) + goto error; + break; + case SSNES_STATE_CGRAM: + if (addr >= psnes_get_memory_size(SNES_MEMORY_CGRAM)) + goto error; + break; + + default: + break; + } + + if (strcmp((const char*)semantic, "capture") == 0) + tracker_type = SSNES_STATE_CAPTURE; + else if (strcmp((const char*)semantic, "capture_previous") == 0) + tracker_type = SSNES_STATE_CAPTURE_PREV; + else if (strcmp((const char*)semantic, "transition")) + tracker_type = SSNES_STATE_TRANSITION; + else + { + SSNES_ERR("Invalid semantic for import value.\n"); + goto error; + } + + strlcpy(gl_tracker_info[gl_tracker_info_cnt].id, (const char*)id, sizeof(gl_tracker_info[0].id)); + gl_tracker_info[gl_tracker_info_cnt].addr = addr; + gl_tracker_info[gl_tracker_info_cnt].type = tracker_type; + gl_tracker_info[gl_tracker_info_cnt].ram_type = ram_type; + gl_tracker_info_cnt++; + + if (id) xmlFree(id); + if (semantic) xmlFree(semantic); + if (wram) xmlFree(wram); + if (apuram) xmlFree(apuram); + if (vram) xmlFree(vram); + if (oam) xmlFree(oam); + if (cgram) xmlFree(cgram); + return true; + +error: + if (id) xmlFree(id); + if (semantic) xmlFree(semantic); + if (wram) xmlFree(wram); + if (apuram) xmlFree(apuram); + if (vram) xmlFree(vram); + if (oam) xmlFree(oam); + if (cgram) xmlFree(cgram); + return false; +} + static unsigned get_xml_shaders(const char *path, struct shader_program *prog, size_t size) { LIBXML_TEST_VERSION; @@ -460,6 +563,14 @@ static unsigned get_xml_shaders(const char *path, struct shader_program *prog, s goto error; } } + else if (strcmp((const char*)cur->name, "import") == 0) + { + if (!get_import_value(cur)) + { + SSNES_ERR("Import value is invalid.\n"); + goto error; + } + } } if (num == 0) @@ -670,6 +781,22 @@ bool gl_glsl_init(const char *path) if (!gl_check_error()) return false; + + if (gl_tracker_info_cnt > 0) + { + struct snes_tracker_info info = { + .wram = psnes_get_memory_data(SNES_MEMORY_WRAM), + .vram = psnes_get_memory_data(SNES_MEMORY_VRAM), + .cgram = psnes_get_memory_data(SNES_MEMORY_CGRAM), + .apuram = psnes_get_memory_data(SNES_MEMORY_APURAM), + .oam = psnes_get_memory_data(SNES_MEMORY_OAM), + .info = gl_tracker_info, + .info_elem = gl_tracker_info_cnt + }; + gl_snes_tracker = snes_tracker_init(&info); + if (!gl_snes_tracker) + SSNES_WARN("Failed to init SNES tracker!\n"); + } glsl_enable = true; gl_num_programs = num_progs; @@ -707,6 +834,14 @@ void gl_glsl_deinit(void) memset(gl_program, 0, sizeof(gl_program)); glsl_enable = false; active_index = 0; + + gl_tracker_info_cnt = 0; + memset(gl_tracker_info, 0, sizeof(gl_tracker_info)); + if (gl_snes_tracker) + { + snes_tracker_free(gl_snes_tracker); + gl_snes_tracker = NULL; + } } void gl_glsl_set_params(unsigned width, unsigned height, @@ -817,6 +952,17 @@ void gl_glsl_set_params(unsigned width, unsigned height, } pglActiveTexture(GL_TEXTURE0); + + if (gl_snes_tracker) + { + struct snes_tracker_uniform info[MAX_VARIABLES]; + unsigned cnt = snes_get_uniform(gl_snes_tracker, info, MAX_VARIABLES, frame_count); + for (unsigned i = 0; i < cnt; i++) + { + location = pglGetUniformLocation(gl_program[active_index], info[i].id); + pglUniform1i(location, info[i].value); + } + } } } diff --git a/gfx/snes_state.h b/gfx/snes_state.h index fbb6cb449d..a8f370ffc2 100644 --- a/gfx/snes_state.h +++ b/gfx/snes_state.h @@ -38,7 +38,7 @@ enum snes_ram_type struct snes_tracker_uniform_info { - const char *id; + char id[64]; uint32_t addr; enum snes_tracker_type type; enum snes_ram_type ram_type;