From d845093c7b8147355cd9c2ca700daa41fb2e3158 Mon Sep 17 00:00:00 2001 From: Alcaro Date: Sat, 4 Jun 2016 17:41:14 +0200 Subject: [PATCH] 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);