mirror of
https://github.com/libretro/RetroArch
synced 2025-02-05 06:40:07 +00:00
Add support for reading and writing core RAM over the command interfaces.
This commit is contained in:
parent
c63f11f6fd
commit
d845093c7b
122
cheevos.c
122
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)
|
||||
{
|
||||
|
114
command.c
114
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<nbytes;i++)
|
||||
{
|
||||
sprintf(reply_at+3*i, " %.2X", data[i]);
|
||||
}
|
||||
reply_at[3*nbytes] = '\n';
|
||||
|
||||
command_reply(reply, reply_at+3*nbytes+1 - reply);
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool command_write_ram(const char *arg)
|
||||
{
|
||||
#ifdef HAVE_CHEEVOS
|
||||
cheevos_var_t var;
|
||||
uint8_t * data;
|
||||
unsigned nbytes;
|
||||
int i;
|
||||
char reply[256];
|
||||
|
||||
cheevos_parse_guest_addr(&var, strtoul(arg, (char**)&arg, 16));
|
||||
data = cheevos_get_memory(&var);
|
||||
|
||||
while (*arg)
|
||||
{
|
||||
*data = strtoul(arg, (char**)&arg, 16);
|
||||
data++;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const struct cmd_action_map action_map[] = {
|
||||
{ "SET_SHADER", command_set_shader, "<shader path>" },
|
||||
#ifdef HAVE_CHEEVOS
|
||||
{ "READ_CORE_RAM", command_read_ram, "<address> <number of bytes>" },
|
||||
{ "WRITE_CORE_RAM", command_write_ram, "<address> <byte1> <byte2> ..." },
|
||||
#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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user