diff --git a/docs/config.txt b/docs/config.txt index f0eb9395aee..7865ecf96b7 100644 --- a/docs/config.txt +++ b/docs/config.txt @@ -525,10 +525,15 @@ Core state/playback options find the next empty value for %i and use that for a filename. The default is %g/%i, which creates a separate folder for each game, and names the snapshots under it starting with 0000 and increasing - from there. In the case of using different media, you can use the - %d_[media] indicator. Replace [media] with the default media being - used. In the example: 'mess nes megaman2u -snapname %g/%d_cart' - snapshots will then be placed in 'snaps\nes\megaman2u.png' + from there. In addition to the above, for drivers using different + media, like carts or floppy disks, you can also use the %d_[media] + indicator. Replace [media] with the media switch you want to use. + A few examples: if you use 'mame robby -snapname foo/%g%i' snapshots + will be saved as 'snaps\foo\robby0000.png' , 'snaps\foo\robby0001.png' + and so on ; if you use 'mess nes -cart robby -snapname %g/%d_cart' + snapshots will be saved as 'snaps\nes\robby.png' ; if you use + 'mess c64 -flop1 robby -snapname %g/%d_flop1/%i' snapshots will be + saved as 'snaps\c64\robby\0000.png'. -snapsize x @@ -554,6 +559,23 @@ Core state/playback options can also be 'auto', which selects the first view with all screens present. The default value is 'internal'. +-statename + + Describes how MAME should store save state files, relative to the + state_directory path. is a string that provides a template that + is used to generate a relative path. Two simple substitutions are + provided: the / character represents the path separator on any target + platform (even Windows); the string %g represents the driver name of + the current game. The default is %g, which creates a separate folder for + each game. In addition to the above, for drivers using different + media, like carts or floppy disks, you can also use the %d_[media] + indicator. Replace [media] with the media switch you want to use. + A few examples: if you use 'mame robby -statename foo/%g' save states + will be stored inside 'sta\foo\robby\' ; if you use 'mess nes -cart + robby -statename %g/%d_cart' save states will be stored inside + 'sta\nes\robby\' ; if you use 'mess c64 -flop1 robby -statename + %g/%d_flop1' save states will be stored inside 'sta\c64\robby\'. + -[no]burnin Tracks brightness of the screen during play and at the end of diff --git a/src/emu/emuopts.c b/src/emu/emuopts.c index b3608ee004d..d834227aa80 100644 --- a/src/emu/emuopts.c +++ b/src/emu/emuopts.c @@ -95,6 +95,7 @@ const options_entry emu_options::s_option_entries[] = { OPTION_SNAPNAME, "%g/%i", OPTION_STRING, "override of the default snapshot/movie naming; %g == gamename, %i == index" }, { OPTION_SNAPSIZE, "auto", OPTION_STRING, "specify snapshot/movie resolution (x) or 'auto' to use minimal size " }, { OPTION_SNAPVIEW, "internal", OPTION_STRING, "specify snapshot/movie view or 'internal' to use internal pixel-aspect views" }, + { OPTION_STATENAME, "%g", OPTION_STRING, "override of the default state subfolder naming; %g == gamename" }, { OPTION_BURNIN, "0", OPTION_BOOLEAN, "create burn-in snapshots for each screen" }, // performance options diff --git a/src/emu/emuopts.h b/src/emu/emuopts.h index 3af5dad2022..0006605efb7 100644 --- a/src/emu/emuopts.h +++ b/src/emu/emuopts.h @@ -107,6 +107,7 @@ enum #define OPTION_SNAPNAME "snapname" #define OPTION_SNAPSIZE "snapsize" #define OPTION_SNAPVIEW "snapview" +#define OPTION_STATENAME "statename" #define OPTION_BURNIN "burnin" // core performance options @@ -266,6 +267,7 @@ public: const char *snap_name() const { return value(OPTION_SNAPNAME); } const char *snap_size() const { return value(OPTION_SNAPSIZE); } const char *snap_view() const { return value(OPTION_SNAPVIEW); } + const char *state_name() const { return value(OPTION_STATENAME); } bool burnin() const { return bool_value(OPTION_BURNIN); } // core performance options diff --git a/src/emu/machine.c b/src/emu/machine.c index d3c7b34c4c9..b04c0019321 100644 --- a/src/emu/machine.c +++ b/src/emu/machine.c @@ -544,6 +544,101 @@ void running_machine::schedule_new_driver(const game_driver &driver) } +//------------------------------------------------- +// get_statename - allow to specify a subfolder of +// the state directory for state loading/saving, +// very useful for MESS and consoles or computers +// where you can have separate folders for diff +// software +//------------------------------------------------- + +astring running_machine::get_statename(const char *option) +{ + astring statename_str(""); + if (option == NULL || option[0] == 0) + statename_str.cpy("%g"); + else + statename_str.cpy(option); + + // strip any extension in the provided statename + int index = statename_str.rchr(0, '.'); + if (index != -1) + statename_str.substr(0, index); + + // handle %d in the template (for image devices) + astring statename_dev("%d_"); + int pos = statename_str.find(0, statename_dev); + + if (pos != -1) + { + // if more %d are found, revert to default and ignore them all + if (statename_str.find(pos + 3, statename_dev) != -1) + statename_str.cpy("%g"); + // else if there is a single %d, try to create the correct snapname + else + { + int name_found = 0; + + // find length of the device name + int end1 = statename_str.find(pos + 3, "/"); + int end2 = statename_str.find(pos + 3, "%"); + int end = -1; + + if ((end1 != -1) && (end2 != -1)) + end = MIN(end1, end2); + else if (end1 != -1) + end = end1; + else if (end2 != -1) + end = end2; + else + end = statename_str.len(); + + if (end - pos < 3) + fatalerror("Something very wrong is going on!!!\n"); + + // copy the device name to an astring + astring devname_str; + devname_str.cpysubstr(statename_str, pos + 3, end - pos - 3); + //printf("check template: %s\n", devname_str.cstr()); + + // verify that there is such a device for this system + image_interface_iterator iter(root_device()); + for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) + { + // get the device name + astring tempdevname(image->brief_instance_name()); + //printf("check device: %s\n", tempdevname.cstr()); + + if (devname_str.cmp(tempdevname) == 0) + { + // verify that such a device has an image mounted + if (image->basename_noext() != NULL) + { + astring filename(image->basename_noext()); + + // setup snapname and remove the %d_ + statename_str.replace(0, devname_str, filename); + statename_str.del(pos, 3); + //printf("check image: %s\n", filename.cstr()); + + name_found = 1; + } + } + } + + // or fallback to default + if (name_found == 0) + statename_str.cpy("%g"); + } + } + + // substitute path and gamename up front + statename_str.replace(0, "/", PATH_SEPARATOR); + statename_str.replace(0, "%g", basename()); + + return statename_str; +} + //------------------------------------------------- // set_saveload_filename - specifies the filename // for state loading/saving @@ -560,7 +655,10 @@ void running_machine::set_saveload_filename(const char *filename) else { m_saveload_searchpath = options().state_directory(); - m_saveload_pending_file.cpy(basename()).cat(PATH_SEPARATOR).cat(filename).cat(".sta"); + // take into account the statename option + const char *stateopt = options().state_name(); + astring statename = get_statename(stateopt); + m_saveload_pending_file.cpy(statename.cstr()).cat(PATH_SEPARATOR).cat(filename).cat(".sta"); } } diff --git a/src/emu/machine.h b/src/emu/machine.h index a211a4bddaa..11b2ed0f33a 100644 --- a/src/emu/machine.h +++ b/src/emu/machine.h @@ -318,6 +318,7 @@ private: // internal helpers void start(); void set_saveload_filename(const char *filename); + astring get_statename(const char *statename_opt); void fill_systime(system_time &systime, time_t t); void handle_saveload(); void soft_reset(void *ptr = NULL, INT32 param = 0);