diff --git a/gfx/shader_cg.c b/gfx/shader_cg.c index 7c951c22a7..7a7a37e2d8 100644 --- a/gfx/shader_cg.c +++ b/gfx/shader_cg.c @@ -393,6 +393,7 @@ static bool load_imports(const char *dir_path, config_file_t *conf) { char semantic_buf[64]; char wram_buf[64]; + char input_slot_buf[64]; char apuram_buf[64]; char oam_buf[64]; char cgram_buf[64]; @@ -401,6 +402,7 @@ static bool load_imports(const char *dir_path, config_file_t *conf) print_buf(semantic_buf, "%s_semantic", id); print_buf(wram_buf, "%s_wram", id); + print_buf(input_slot_buf, "%s_input_slot", id); print_buf(apuram_buf, "%s_apuram", id); print_buf(oam_buf, "%s_oam", id); print_buf(cgram_buf, "%s_cgram", id); @@ -445,7 +447,25 @@ static bool load_imports(const char *dir_path, config_file_t *conf) if (tracker_type != SSNES_STATE_PYTHON) { #endif - if (config_get_hex(conf, wram_buf, &addr)) + unsigned input_slot = 0; + if (config_get_hex(conf, input_slot_buf, &input_slot)) + { + switch (input_slot) + { + case 1: + ram_type = SSNES_STATE_INPUT_SLOT1; + break; + + case 2: + ram_type = SSNES_STATE_INPUT_SLOT2; + break; + + default: + SSNES_ERR("Invalid input slot for import.\n"); + goto error; + } + } + else if (config_get_hex(conf, wram_buf, &addr)) ram_type = SSNES_STATE_WRAM; else if (config_get_hex(conf, apuram_buf, &addr)) ram_type = SSNES_STATE_APURAM; @@ -482,8 +502,9 @@ static bool load_imports(const char *dir_path, config_file_t *conf) case SSNES_STATE_CGRAM: memtype = SNES_MEMORY_CGRAM; break; + default: - break; + memtype = SNES_MEMORY_WRAM; } if (addr >= psnes_get_memory_size(memtype)) diff --git a/gfx/shader_glsl.c b/gfx/shader_glsl.c index 44ff155e5a..55d2b668aa 100644 --- a/gfx/shader_glsl.c +++ b/gfx/shader_glsl.c @@ -446,6 +446,7 @@ 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 *input = xmlGetProp(ptr, (const xmlChar*)"input_slot"); xmlChar *apuram = xmlGetProp(ptr, (const xmlChar*)"apuram"); xmlChar *vram = xmlGetProp(ptr, (const xmlChar*)"vram"); xmlChar *oam = xmlGetProp(ptr, (const xmlChar*)"oam"); @@ -487,7 +488,24 @@ static bool get_import_value(xmlNodePtr ptr) if (tracker_type != SSNES_STATE_PYTHON) { #endif - if (wram) { addr = strtoul((const char*)wram, NULL, 16); ram_type = SSNES_STATE_WRAM; } + if (input) + { + unsigned slot = strtoul((const char*)input, NULL, 0); + switch (slot) + { + case 1: + ram_type = SSNES_STATE_INPUT_SLOT1; + break; + case 2: + ram_type = SSNES_STATE_INPUT_SLOT2; + break; + + default: + SSNES_ERR("Invalid input slot for import!\n"); + goto error; + } + } + else 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; } @@ -521,7 +539,7 @@ static bool get_import_value(xmlNodePtr ptr) break; default: - break; + memtype = SNES_MEMORY_WRAM; } if (addr >= psnes_get_memory_size(memtype)) @@ -544,6 +562,7 @@ static bool get_import_value(xmlNodePtr ptr) if (id) xmlFree(id); if (semantic) xmlFree(semantic); if (wram) xmlFree(wram); + if (input) xmlFree(input); if (apuram) xmlFree(apuram); if (vram) xmlFree(vram); if (oam) xmlFree(oam); @@ -555,6 +574,7 @@ error: if (id) xmlFree(id); if (semantic) xmlFree(semantic); if (wram) xmlFree(wram); + if (input) xmlFree(input); if (apuram) xmlFree(apuram); if (vram) xmlFree(vram); if (oam) xmlFree(oam); diff --git a/gfx/snes_state.c b/gfx/snes_state.c index 9580de880c..e8d785be7f 100644 --- a/gfx/snes_state.c +++ b/gfx/snes_state.c @@ -20,6 +20,7 @@ #include #include "strl.h" #include "general.h" +#include #ifdef HAVE_PYTHON #include "py_state/py_state.h" @@ -29,6 +30,9 @@ struct snes_tracker_internal { char id[64]; + bool is_input; + unsigned input_slot; + const uint16_t *input_ptr; const uint8_t *ptr; #ifdef HAVE_PYTHON py_state_t *py; @@ -39,10 +43,10 @@ struct snes_tracker_internal enum snes_tracker_type type; - uint8_t prev[2]; + uint32_t prev[2]; int frame_count; int frame_count_prev; - uint8_t old_value; + uint32_t old_value; int transition_count; }; @@ -51,6 +55,8 @@ struct snes_tracker struct snes_tracker_internal *info; unsigned info_elem; + uint16_t input_state[2]; + #ifdef HAVE_PYTHON py_state_t *py; #endif @@ -110,6 +116,16 @@ snes_tracker_t* snes_tracker_init(const struct snes_tracker_info *info) case SSNES_STATE_VRAM: tracker->info[i].ptr = info->vram; break; + case SSNES_STATE_INPUT_SLOT1: + tracker->info[i].input_ptr = &tracker->input_state[0]; + tracker->info[i].input_slot = 0; + tracker->info[i].is_input = true; + break; + case SSNES_STATE_INPUT_SLOT2: + tracker->info[i].input_ptr = &tracker->input_state[1]; + tracker->info[i].input_slot = 1; + tracker->info[i].is_input = true; + break; default: tracker->info[i].ptr = NULL; @@ -128,7 +144,7 @@ void snes_tracker_free(snes_tracker_t *tracker) free(tracker); } -#define fetch() (info->ptr[info->addr] & info->mask) +#define fetch() ((info->is_input ? info->input_ptr[info->input_slot] : info->ptr[info->addr]) & info->mask) static void update_element( struct snes_tracker_uniform *uniform, @@ -193,10 +209,52 @@ static void update_element( #undef fetch +// Updates 16-bit input in same format as SNES itself. +static void update_input(snes_tracker_t *tracker) +{ + if (!driver.input_data) + return; + + static const unsigned buttons[] = { + SNES_DEVICE_ID_JOYPAD_R, + SNES_DEVICE_ID_JOYPAD_L, + SNES_DEVICE_ID_JOYPAD_X, + SNES_DEVICE_ID_JOYPAD_A, + SNES_DEVICE_ID_JOYPAD_RIGHT, + SNES_DEVICE_ID_JOYPAD_LEFT, + SNES_DEVICE_ID_JOYPAD_DOWN, + SNES_DEVICE_ID_JOYPAD_UP, + SNES_DEVICE_ID_JOYPAD_START, + SNES_DEVICE_ID_JOYPAD_SELECT, + SNES_DEVICE_ID_JOYPAD_Y, + SNES_DEVICE_ID_JOYPAD_B + }; + + static const struct snes_keybind *binds[MAX_PLAYERS] = { + g_settings.input.binds[0], + g_settings.input.binds[1], + g_settings.input.binds[2], + g_settings.input.binds[3], + g_settings.input.binds[4] + }; + + uint16_t state[2] = {0}; + for (unsigned i = 4; i < 16; i++) + { + state[0] |= (driver.input->input_state(driver.input_data, binds, SNES_PORT_1, SNES_DEVICE_JOYPAD, 0, buttons[i - 4]) ? 1 : 0) << i; + state[1] |= (driver.input->input_state(driver.input_data, binds, SNES_PORT_2, SNES_DEVICE_JOYPAD, 0, buttons[i - 4]) ? 1 : 0) << i; + } + + for (unsigned i = 0; i < 2; i++) + tracker->input_state[i] = state[i]; +} + unsigned snes_get_uniform(snes_tracker_t *tracker, struct snes_tracker_uniform *uniforms, unsigned elem, unsigned frame_count) { unsigned elems = tracker->info_elem < elem ? tracker->info_elem : elem; + update_input(tracker); + for (unsigned i = 0; i < elems; i++) update_element(&uniforms[i], &tracker->info[i], frame_count); diff --git a/gfx/snes_state.h b/gfx/snes_state.h index 25be194610..90772aa1f9 100644 --- a/gfx/snes_state.h +++ b/gfx/snes_state.h @@ -43,7 +43,9 @@ enum snes_ram_type SSNES_STATE_APURAM, SSNES_STATE_OAM, SSNES_STATE_CGRAM, - SSNES_STATE_VRAM + SSNES_STATE_VRAM, + SSNES_STATE_INPUT_SLOT1, + SSNES_STATE_INPUT_SLOT2 }; struct snes_tracker_uniform_info diff --git a/ssnes.c b/ssnes.c index fa110ddf62..c31b926613 100644 --- a/ssnes.c +++ b/ssnes.c @@ -295,9 +295,13 @@ static int16_t input_state(bool port, unsigned device, unsigned index, unsigned } } - const struct snes_keybind *binds[MAX_PLAYERS]; - for (int i = 0; i < MAX_PLAYERS; i++) - binds[i] = g_settings.input.binds[i]; + static const struct snes_keybind *binds[MAX_PLAYERS] = { + g_settings.input.binds[0], + g_settings.input.binds[1], + g_settings.input.binds[2], + g_settings.input.binds[3], + g_settings.input.binds[4] + }; int16_t res = driver.input->input_state(driver.input_data, binds, port, device, index, id); if (g_extern.bsv_movie && !g_extern.bsv_movie_playback)