From d845093c7b8147355cd9c2ca700daa41fb2e3158 Mon Sep 17 00:00:00 2001 From: Alcaro Date: Sat, 4 Jun 2016 17:41:14 +0200 Subject: [PATCH 1/4] Add support for reading and writing core RAM over the command interfaces. --- cheevos.c | 122 ++++++++++++++++++++++++++++-------------------------- command.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 176 insertions(+), 60 deletions(-) diff --git a/cheevos.c b/cheevos.c index 2c903e2d40..f7b67c0f20 100644 --- a/cheevos.c +++ b/cheevos.c @@ -605,6 +605,68 @@ static unsigned cheevos_parse_operator(const char **memaddr) return op; } +void cheevos_parse_guest_addr(cheevos_var_t *var, unsigned value) +{ + rarch_system_info_t *system; + runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); + + var->bank_id = -1; + var->value = value; + + if (system->mmaps.num_descriptors != 0) + { + const struct retro_memory_descriptor *desc; + const struct retro_memory_descriptor *end; + + if (cheevos_locals.console_id == CHEEVOS_CONSOLE_GAMEBOY_ADVANCE) + { + /* Patch the address to correctly map it to the mmaps */ + if (var->value < 0x8000) + { + /* Internal RAM */ + var->value += 0x3000000; + } + else + { + /* Work RAM */ + var->value += 0x2000000 - 0x8000; + } + } + else if (cheevos_locals.console_id == CHEEVOS_CONSOLE_PC_ENGINE) + { + var->value += 0x1f0000; + } + + desc = system->mmaps.descriptors; + end = desc + system->mmaps.num_descriptors; + + for (; desc < end; desc++) + { + if ((var->value & desc->select) == desc->start) + { + var->bank_id = desc - system->mmaps.descriptors; + var->value = var->value - desc->start + desc->offset; + break; + } + } + } + else + { + unsigned i; + + for (i = 0; i < sizeof(cheevos_locals.meminfo) / sizeof(cheevos_locals.meminfo[0]); i++) + { + if (var->value < cheevos_locals.meminfo[i].size) + { + var->bank_id = i; + break; + } + + var->value -= cheevos_locals.meminfo[i].size; + } + } +} + static void cheevos_parse_var(cheevos_var_t *var, const char **memaddr) { char *end = NULL; @@ -647,63 +709,7 @@ static void cheevos_parse_var(cheevos_var_t *var, const char **memaddr) if ( var->type == CHEEVOS_VAR_TYPE_ADDRESS || var->type == CHEEVOS_VAR_TYPE_DELTA_MEM) { - rarch_system_info_t *system; - runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); - - var->bank_id = -1; - - if (system->mmaps.num_descriptors != 0) - { - const struct retro_memory_descriptor *desc; - const struct retro_memory_descriptor *end; - - if (cheevos_locals.console_id == CHEEVOS_CONSOLE_GAMEBOY_ADVANCE) - { - /* Patch the address to correctly map it to the mmaps */ - if (var->value < 0x8000) - { - /* Internal RAM */ - var->value += 0x3000000; - } - else - { - /* Work RAM */ - var->value += 0x2000000 - 0x8000; - } - } - else if (cheevos_locals.console_id == CHEEVOS_CONSOLE_PC_ENGINE) - { - var->value += 0x1f0000; - } - - desc = system->mmaps.descriptors; - end = desc + system->mmaps.num_descriptors; - - for (; desc < end; desc++) - { - if ((var->value & desc->select) == desc->start) - { - var->bank_id = desc - system->mmaps.descriptors; - var->value = var->value - desc->start + desc->offset; - break; - } - } - } - else - { - unsigned i; - - for (i = 0; i < sizeof(cheevos_locals.meminfo) / sizeof(cheevos_locals.meminfo[0]); i++) - { - if (var->value < cheevos_locals.meminfo[i].size) - { - var->bank_id = i; - break; - } - - var->value -= cheevos_locals.meminfo[i].size; - } - } + cheevos_parse_guest_addr(var, var->value); #ifdef CHEEVOS_DUMP_ADDRS RARCH_LOG("CHEEVOS var %03d:%08X\n", var->bank_id + 1, var->value); #endif @@ -1072,7 +1078,7 @@ static int cheevos_parse(const char *json) Test all the achievements (call once per frame). *****************************************************************************/ -static const uint8_t *cheevos_get_memory(const cheevos_var_t *var) +uint8_t *cheevos_get_memory(const cheevos_var_t *var) { if (var->bank_id >= 0) { diff --git a/command.c b/command.c index 5e366a3211..675719b17a 100644 --- a/command.c +++ b/command.c @@ -102,6 +102,33 @@ struct command bool state[RARCH_BIND_LIST_END]; }; +enum lastcmd_source_t { cmd_none, cmd_stdin, cmd_network }; +static int lastcmd_source_type; +#if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY) +static int lastcmd_net_fd; +static struct sockaddr_storage lastcmd_net_source; +static socklen_t lastcmd_net_source_len; +#endif + +static bool command_reply(const char * data, size_t len) +{ +#ifdef HAVE_STDIN_CMD + if (lastcmd_source_type == cmd_stdin) + { + fwrite(data, 1,len, stdout); + return true; + } +#endif +#if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY) + if (lastcmd_source_type == cmd_network) + { + sendto(lastcmd_net_fd, data, len, 0, (struct sockaddr*)&lastcmd_net_source, lastcmd_net_source_len); + return true; + } +#endif + return false; +} + struct cmd_map { const char *str; @@ -157,8 +184,82 @@ static bool command_set_shader(const char *arg) return video_driver_set_shader(type, arg); } +#ifdef HAVE_CHEEVOS +typedef struct +{ + unsigned size; + unsigned type; + int bank_id; + unsigned value; + unsigned previous; +} cheevos_var_t; + +void cheevos_parse_guest_addr(cheevos_var_t *var, unsigned value); +uint8_t *cheevos_get_memory(const cheevos_var_t *var); +#endif + +static bool command_read_ram(const char *arg) +{ +#ifdef HAVE_CHEEVOS + cheevos_var_t var; + const uint8_t * data; + unsigned nbytes; + int i; + char reply[256]; + strcpy(reply, "READ_CORE_RAM "); + char * reply_at = reply + strlen("READ_CORE_RAM "); + strcpy(reply_at, arg); + + cheevos_parse_guest_addr(&var, strtoul(reply_at, (char**)&reply_at, 16)); + data = cheevos_get_memory(&var); + + nbytes = strtol(reply_at, NULL, 10); + *reply_at = '\0'; + + for (i=0;i" }, +#ifdef HAVE_CHEEVOS + { "READ_CORE_RAM", command_read_ram, "
" }, + { "WRITE_CORE_RAM", command_write_ram, "
..." }, +#endif }; static const struct cmd_map map[] = { @@ -182,7 +283,7 @@ static const struct cmd_map map[] = { { "CHEAT_TOGGLE", RARCH_CHEAT_TOGGLE }, { "SCREENSHOT", RARCH_SCREENSHOT }, { "MUTE", RARCH_MUTE }, - { "OSK", RARCH_OSK }, + { "OSK", RARCH_OSK }, { "NETPLAY_FLIP", RARCH_NETPLAY_FLIP }, { "SLOWMOTION", RARCH_SLOWMOTION }, { "VOLUME_UP", RARCH_VOLUME_UP }, @@ -199,6 +300,7 @@ static const struct cmd_map map[] = { { "MENU_RIGHT", RETRO_DEVICE_ID_JOYPAD_RIGHT }, { "MENU_A", RETRO_DEVICE_ID_JOYPAD_A }, { "MENU_B", RETRO_DEVICE_ID_JOYPAD_B }, + { "MENU_B", RETRO_DEVICE_ID_JOYPAD_B }, }; static bool command_get_arg(const char *tok, @@ -449,14 +551,20 @@ static void command_network_poll(command_t *handle) for (;;) { char buf[1024]; + + lastcmd_source_type = cmd_network; + lastcmd_net_fd = handle->net_fd; + lastcmd_net_source_len = sizeof(lastcmd_net_source); ssize_t ret = recvfrom(handle->net_fd, buf, - sizeof(buf) - 1, 0, NULL, NULL); + sizeof(buf) - 1, 0, (struct sockaddr*)&lastcmd_net_source, &lastcmd_net_source_len); if (ret <= 0) break; buf[ret] = '\0'; + command_parse_msg(handle, buf); + lastcmd_source_type = cmd_none; } } #endif @@ -659,7 +767,9 @@ static void command_stdin_poll(command_t *handle) *last_newline++ = '\0'; msg_len = last_newline - handle->stdin_buf; + lastcmd_source_type = cmd_stdin; command_parse_msg(handle, handle->stdin_buf); + lastcmd_source_type = cmd_none; memmove(handle->stdin_buf, last_newline, handle->stdin_buf_ptr - msg_len); From 1a64520a234576f00fd4b072c1fb021c2363c4ec Mon Sep 17 00:00:00 2001 From: Alcaro Date: Sat, 4 Jun 2016 17:45:48 +0200 Subject: [PATCH 2/4] Fix some silly copypasta. --- cheevos.c | 9 --------- cheevos.h | 13 +++++++++++++ command.c | 14 -------------- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/cheevos.c b/cheevos.c index f7b67c0f20..44e9386777 100644 --- a/cheevos.c +++ b/cheevos.c @@ -156,15 +156,6 @@ enum CHEEVOS_DIRTY_ALL = (1 << 9) - 1 }; -typedef struct -{ - unsigned size; - unsigned type; - int bank_id; - unsigned value; - unsigned previous; -} cheevos_var_t; - typedef struct { unsigned type; diff --git a/cheevos.h b/cheevos.h index 8642f7cc57..c5d3f529d3 100644 --- a/cheevos.h +++ b/cheevos.h @@ -48,6 +48,19 @@ bool cheevos_set_cheats(void); void cheevos_set_support_cheevos(bool state); + +typedef struct +{ + unsigned size; + unsigned type; + int bank_id; + unsigned value; + unsigned previous; +} cheevos_var_t; + +void cheevos_parse_guest_addr(cheevos_var_t *var, unsigned value); +uint8_t *cheevos_get_memory(const cheevos_var_t *var); + RETRO_END_DECLS #endif /* __RARCH_CHEEVOS_H */ diff --git a/command.c b/command.c index 675719b17a..c56fefa531 100644 --- a/command.c +++ b/command.c @@ -184,20 +184,6 @@ static bool command_set_shader(const char *arg) return video_driver_set_shader(type, arg); } -#ifdef HAVE_CHEEVOS -typedef struct -{ - unsigned size; - unsigned type; - int bank_id; - unsigned value; - unsigned previous; -} cheevos_var_t; - -void cheevos_parse_guest_addr(cheevos_var_t *var, unsigned value); -uint8_t *cheevos_get_memory(const cheevos_var_t *var); -#endif - static bool command_read_ram(const char *arg) { #ifdef HAVE_CHEEVOS From 6484fb0c75468733bb2201a237c6b41f3c915a8e Mon Sep 17 00:00:00 2001 From: Alcaro Date: Sat, 4 Jun 2016 17:51:27 +0200 Subject: [PATCH 3/4] This fits better as an argument. --- command.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/command.c b/command.c index c56fefa531..5151b31aeb 100644 --- a/command.c +++ b/command.c @@ -102,8 +102,8 @@ struct command bool state[RARCH_BIND_LIST_END]; }; -enum lastcmd_source_t { cmd_none, cmd_stdin, cmd_network }; -static int lastcmd_source_type; +enum cmd_source_t { cmd_none, cmd_stdin, cmd_network }; +static enum cmd_source_t lastcmd_source; #if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY) static int lastcmd_net_fd; static struct sockaddr_storage lastcmd_net_source; @@ -113,14 +113,14 @@ static socklen_t lastcmd_net_source_len; static bool command_reply(const char * data, size_t len) { #ifdef HAVE_STDIN_CMD - if (lastcmd_source_type == cmd_stdin) + if (lastcmd_source == cmd_stdin) { fwrite(data, 1,len, stdout); return true; } #endif #if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY) - if (lastcmd_source_type == cmd_network) + if (lastcmd_source == cmd_network) { sendto(lastcmd_net_fd, data, len, 0, (struct sockaddr*)&lastcmd_net_source, lastcmd_net_source_len); return true; @@ -352,16 +352,19 @@ static void command_parse_sub_msg(command_t *handle, const char *tok) msg_hash_to_str(MSG_RECEIVED)); } -static void command_parse_msg(command_t *handle, char *buf) +static void command_parse_msg(command_t *handle, char *buf, enum cmd_source_t source) { char *save = NULL; const char *tok = strtok_r(buf, "\n", &save); + lastcmd_source = source; + while (tok) { command_parse_sub_msg(handle, tok); tok = strtok_r(NULL, "\n", &save); } + lastcmd_source = cmd_none; } #if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY) @@ -538,7 +541,6 @@ static void command_network_poll(command_t *handle) { char buf[1024]; - lastcmd_source_type = cmd_network; lastcmd_net_fd = handle->net_fd; lastcmd_net_source_len = sizeof(lastcmd_net_source); ssize_t ret = recvfrom(handle->net_fd, buf, @@ -549,8 +551,7 @@ static void command_network_poll(command_t *handle) buf[ret] = '\0'; - command_parse_msg(handle, buf); - lastcmd_source_type = cmd_none; + command_parse_msg(handle, buf, cmd_network); } } #endif @@ -753,9 +754,7 @@ static void command_stdin_poll(command_t *handle) *last_newline++ = '\0'; msg_len = last_newline - handle->stdin_buf; - lastcmd_source_type = cmd_stdin; - command_parse_msg(handle, handle->stdin_buf); - lastcmd_source_type = cmd_none; + command_parse_msg(handle, handle->stdin_buf, cmd_stdin); memmove(handle->stdin_buf, last_newline, handle->stdin_buf_ptr - msg_len); From e3f594564a1d140e37044007afdb13921fa8e6ad Mon Sep 17 00:00:00 2001 From: Alcaro Date: Sat, 4 Jun 2016 18:25:30 +0200 Subject: [PATCH 4/4] Fix segfault if no game is loaded. --- command.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/command.c b/command.c index 5151b31aeb..a30b312d3c 100644 --- a/command.c +++ b/command.c @@ -198,17 +198,24 @@ static bool command_read_ram(const char *arg) cheevos_parse_guest_addr(&var, strtoul(reply_at, (char**)&reply_at, 16)); data = cheevos_get_memory(&var); - - nbytes = strtol(reply_at, NULL, 10); - *reply_at = '\0'; - - for (i=0;i