diff --git a/docs/ssnes.1 b/docs/ssnes.1 index bfbdb1e713..0177d0e024 100644 --- a/docs/ssnes.1 +++ b/docs/ssnes.1 @@ -134,6 +134,11 @@ Network port used for netplay. This defaults to 55435. This option affects both Attempts to apply an UPS patch to the current ROM image. No files are altered. If this flag is not specified, SSNES will look for a .ups file with same basename as ROM specified. +.TP +\fB--xml MAP, -X MAP\fR +Specifies path to XML memory map for the given ROM. +If this flag is not specified, SSNES will look for a .xml file with same basename as ROM specified. + .TP \fB-D, --detach\fR Detach from the current console. This is currently only relevant for Microsoft Windows. diff --git a/file.c b/file.c index e482053fbb..d9352b0f07 100644 --- a/file.c +++ b/file.c @@ -51,7 +51,7 @@ ssize_t read_file(const char *path, void **buf) long len = ftell(file); ssize_t rc = 0; rewind(file); - rom_buf = malloc(len); + rom_buf = malloc(len + 1); if (!rom_buf) { SSNES_ERR("Couldn't allocate memory!\n"); @@ -62,6 +62,7 @@ ssize_t read_file(const char *path, void **buf) SSNES_WARN("Didn't read whole file.\n"); *buf = rom_buf; + ((char*)rom_buf)[len] = '\0'; // Allow for easy reading of strings. fclose(file); return rc; @@ -270,6 +271,20 @@ void save_ram_file(const char* path, int type) dump_to_file(path, data, size); } +static char* load_xml_map(const char *path) +{ + char *xml_buf = NULL; + if (*path) + { + if (read_file(path, (void**)&xml_buf) < 0) + SSNES_LOG("Did not find XML memory map in \"%s\"\n", path); + else + SSNES_LOG("Found XML memory map in \"%s\"\n", path); + } + + return xml_buf; +} + static bool load_sgb_rom(void) { void *rom_buf = NULL; @@ -291,14 +306,19 @@ static bool load_sgb_rom(void) goto error; } + char *xml_buf = load_xml_map(g_extern.xml_name); + if (!psnes_load_cartridge_super_game_boy( - NULL, rom_buf, rom_len, + xml_buf, rom_buf, rom_len, NULL, extra_rom_buf, extra_rom_len)) { SSNES_ERR("Cannot load SGB/GameBoy rom.\n"); goto error; } + if (xml_buf) + free(xml_buf); + if (g_extern.rom_file) fclose(g_extern.rom_file); if (extra_rom) @@ -338,10 +358,12 @@ static bool load_bsx_rom(bool slotted) goto error; } + char *xml_buf = load_xml_map(g_extern.xml_name); + if (slotted) { if (!psnes_load_cartridge_bsx_slotted( - NULL, rom_buf, rom_len, + xml_buf, rom_buf, rom_len, NULL, extra_rom_buf, extra_rom_len)) { SSNES_ERR("Cannot load BSX slotted rom.\n"); @@ -360,6 +382,9 @@ static bool load_bsx_rom(bool slotted) } } + if (xml_buf) + free(xml_buf); + if (g_extern.rom_file) fclose(g_extern.rom_file); if (extra_rom) @@ -407,8 +432,10 @@ static bool load_sufami_rom(void) } } + char *xml_buf = load_xml_map(g_extern.xml_name); + if (!psnes_load_cartridge_sufami_turbo( - NULL, rom_buf, rom_len, + xml_buf, rom_buf, rom_len, NULL, extra_rom_buf[0], extra_rom_len[0], NULL, extra_rom_buf[1], extra_rom_len[1])) { @@ -416,6 +443,8 @@ static bool load_sufami_rom(void) goto error; } + if (xml_buf) + free(xml_buf); if (g_extern.rom_file) fclose(g_extern.rom_file); @@ -457,13 +486,18 @@ static bool load_normal_rom(void) SSNES_LOG("ROM size: %d bytes\n", (int)rom_len); - if (!psnes_load_cartridge_normal(NULL, rom_buf, rom_len)) + char *xml_buf = load_xml_map(g_extern.xml_name); + + if (!psnes_load_cartridge_normal(xml_buf, rom_buf, rom_len)) { SSNES_ERR("ROM file is not valid!\n"); free(rom_buf); return false; } + if (xml_buf) + free(xml_buf); + free(rom_buf); return true; } diff --git a/general.h b/general.h index e6164a44a3..abc84a4936 100644 --- a/general.h +++ b/general.h @@ -177,6 +177,7 @@ struct global char savefile_name_bsrm[512]; char savestate_name[256]; char ups_name[512]; + char xml_name[512]; unsigned state_slot; diff --git a/ssnes.c b/ssnes.c index e2612453fd..4acb70339a 100644 --- a/ssnes.c +++ b/ssnes.c @@ -411,6 +411,7 @@ static void print_help(void) #endif puts("\t-v/--verbose: Verbose logging."); puts("\t-U/--ups: Specifies path for UPS patch that will be applied to ROM."); + puts("\t-X/--xml: Specifies path to XML memory map."); puts("\t-D/--detach: Detach SSNES from the running console. Not relevant for all platforms.\n"); print_features(); @@ -464,6 +465,7 @@ static void parse_input(int argc, char *argv[]) { "frames", 1, NULL, 'F' }, { "port", 1, &val, 'p' }, { "ups", 1, NULL, 'U' }, + { "xml", 1, NULL, 'X' }, { "detach", 0, NULL, 'D' }, { NULL, 0, NULL, 0 } }; @@ -482,7 +484,7 @@ static void parse_input(int argc, char *argv[]) #define CONFIG_FILE_ARG #endif - char optstring[] = "hs:vS:m:p4jJg:b:B:Y:Z:P:HC:F:U:DN:" FFMPEG_RECORD_ARG CONFIG_FILE_ARG; + char optstring[] = "hs:vS:m:p4jJg:b:B:Y:Z:P:HC:F:U:DN:X:" FFMPEG_RECORD_ARG CONFIG_FILE_ARG; for(;;) { val = 0; @@ -612,6 +614,10 @@ static void parse_input(int argc, char *argv[]) strlcpy(g_extern.ups_name, optarg, sizeof(g_extern.ups_name)); break; + case 'X': + strlcpy(g_extern.xml_name, optarg, sizeof(g_extern.xml_name)); + break; + case 'D': #ifdef _WIN32 FreeConsole(); @@ -1029,6 +1035,9 @@ static void fill_pathnames(void) if (!(*g_extern.ups_name) && *g_extern.basename) fill_pathname_noext(g_extern.ups_name, g_extern.basename, ".ups", sizeof(g_extern.ups_name)); + + if (!(*g_extern.xml_name && *g_extern.basename)) + fill_pathname_noext(g_extern.xml_name, g_extern.basename, ".xml", sizeof(g_extern.xml_name)); } // Save or load state here.