emu: Fixed issues with memory views and snapshot naming.

Include device tag in memory view save item registration names.  Without
this, instantiating two of the same device (or two devices with
identically named memory views) causes a fatal error on start.

Fixed -aviwrite/-mngwrite with -snapview native more than two screens.
Previously it would attempt to use the same file name for all screens
but the first.

Improved naming of snapshots, especially when using -snapview native
with -aviwrite/-mngwrite (see GitHub #10005).  The automatically
included screen number should come before the extension if supplied.
Also, assume that users actually know what they’re doing if they include
a dot in a snapshot filename pattern.
This commit is contained in:
Vas Crabb 2022-07-01 15:47:17 +10:00
parent 08e728c765
commit 875ee33542
2 changed files with 69 additions and 29 deletions

View File

@ -645,8 +645,8 @@ memory_view::~memory_view()
void memory_view::register_state() void memory_view::register_state()
{ {
m_device.machine().save().save_item(&m_device, "view", m_name.c_str(), 0, NAME(m_cur_slot)); m_device.machine().save().save_item(&m_device, "view", m_device.subtag(m_name).c_str(), 0, NAME(m_cur_slot));
m_device.machine().save().save_item(&m_device, "view", m_name.c_str(), 0, NAME(m_cur_id)); m_device.machine().save().save_item(&m_device, "view", m_device.subtag(m_name).c_str(), 0, NAME(m_cur_id));
m_device.machine().save().register_postload(save_prepost_delegate(NAME([this]() { m_handler_read->select_a(m_cur_id); m_handler_write->select_a(m_cur_id); }))); m_device.machine().save().register_postload(save_prepost_delegate(NAME([this]() { m_handler_read->select_a(m_cur_id); m_handler_write->select_a(m_cur_id); })));
} }

View File

@ -380,18 +380,15 @@ void video_manager::save_active_screen_snapshots()
void video_manager::begin_recording_screen(const std::string &filename, uint32_t index, screen_device *screen, movie_recording::format format) void video_manager::begin_recording_screen(const std::string &filename, uint32_t index, screen_device *screen, movie_recording::format format)
{ {
// determine the file extension
const char *extension = movie_recording::format_file_extension(format);
// create the emu_file // create the emu_file
bool is_absolute_path = !filename.empty() && osd_is_absolute_path(filename); bool const is_absolute_path = !filename.empty() && osd_is_absolute_path(filename);
std::unique_ptr<emu_file> movie_file = std::make_unique<emu_file>( std::unique_ptr<emu_file> movie_file = std::make_unique<emu_file>(
is_absolute_path ? "" : machine().options().snapshot_directory(), is_absolute_path ? "" : machine().options().snapshot_directory(),
OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
// and open the actual file // and open the actual file
std::error_condition filerr = filename.empty() std::error_condition filerr = filename.empty()
? open_next(*movie_file, extension) ? open_next(*movie_file, movie_recording::format_file_extension(format))
: movie_file->open(filename); : movie_file->open(filename);
if (filerr) if (filerr)
{ {
@ -429,26 +426,48 @@ void video_manager::begin_recording(const char *name, movie_recording::format fo
// clear out existing recordings // clear out existing recordings
m_movie_recordings.clear(); m_movie_recordings.clear();
// check if the supplied name already has the desired extension
std::string_view basename;
std::string extension;
if (name)
{
std::string_view const desired_ext = movie_recording::format_file_extension(format);
basename = name;
extension.reserve(1 + desired_ext.length());
extension.assign(1, '.').append(desired_ext);
if (core_filename_ends_with(basename, extension))
{
extension = basename.substr(basename.length() - extension.length());
basename.remove_suffix(extension.length());
}
}
if (m_snap_native) if (m_snap_native)
{ {
std::string tempname;
for (uint32_t index = 0; index < count; index++, iter++) for (uint32_t index = 0; index < count; index++, iter++)
{ {
create_snapshot_bitmap(iter.current()); create_snapshot_bitmap(iter.current()); // TODO: only do this when starting on-the-fly, and make name match AVI file name
std::string tempname;
if (name) if (name)
tempname = index > 0 ? name : util::string_format("%s%d", name, index); {
if (1 < count)
tempname = util::string_format("%s%d%s", basename, index, extension);
else
tempname.assign(name).append(extension);
}
begin_recording_screen( begin_recording_screen(
tempname, tempname,
index, index,
iter.current(), iter.current(),
format); format);
} }
} }
else else
{ {
create_snapshot_bitmap(nullptr); create_snapshot_bitmap(nullptr);
begin_recording_screen(name ? name : "", 0, iter.current(), format); begin_recording_screen(std::string(basename) + extension, 0, iter.current(), format);
} }
} }
@ -967,10 +986,23 @@ void video_manager::recompute_speed(const attotime &emutime)
if (m_seconds_to_run != 0 && emutime.seconds() >= m_seconds_to_run) if (m_seconds_to_run != 0 && emutime.seconds() >= m_seconds_to_run)
{ {
// create a final screenshot // create a final screenshot
emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); if (m_snap_native)
std::error_condition const filerr = open_next(file, "png"); {
if (!filerr) for (screen_device &screen : screen_device_enumerator(machine().root_device()))
save_snapshot(nullptr, file); {
emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
std::error_condition const filerr = open_next(file, "png");
if (!filerr)
save_snapshot(&screen, file);
}
}
else
{
emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
std::error_condition const filerr = open_next(file, "png");
if (!filerr)
save_snapshot(nullptr, file);
}
//printf("Scheduled exit at %f\n", emutime.as_double()); //printf("Scheduled exit at %f\n", emutime.as_double());
// schedule our demise // schedule our demise
@ -1064,14 +1096,19 @@ std::error_condition video_manager::open_next(emu_file &file, const char *extens
// handle defaults // handle defaults
const char *snapname = machine().options().snap_name(); const char *snapname = machine().options().snap_name();
if (snapname == nullptr || snapname[0] == 0) if (!snapname || !snapname[0])
snapname = "%g/%i"; snapname = "%g/%i";
std::string snapstr(snapname); std::string snapstr(snapname);
// strip any extension in the provided name // strip desired extension if already present
int index = snapstr.find_last_of('.'); std::string extstr;
if (index != -1) extstr.reserve(1 + std::strlen(extension));
snapstr = snapstr.substr(0, index); extstr.assign(1, '.').append(extension);
if (core_filename_ends_with(snapstr, extstr))
{
extstr = snapstr.substr(snapstr.length() - extstr.length());
snapstr.resize(snapstr.length() - extstr.length());
}
// handle %d in the template (for image devices) // handle %d in the template (for image devices)
std::string snapdev("%d_"); std::string snapdev("%d_");
@ -1142,21 +1179,24 @@ std::error_condition video_manager::open_next(emu_file &file, const char *extens
strreplace(snapstr, "%t", t_str); strreplace(snapstr, "%t", t_str);
} }
// add our own extension // append extension
snapstr.append(".").append(extension); snapstr.append(extstr);
// substitute path and gamename up front // substitute path and gamename up front
strreplace(snapstr, "/", PATH_SEPARATOR); strreplace(snapstr, "/", PATH_SEPARATOR);
strreplace(snapstr, "%g", machine().basename()); strreplace(snapstr, "%g", machine().basename());
// determine if the template has an index; if not, we always use the same name // determine if the template has an index
std::string fname; std::string fname;
if (snapstr.find("%i") == -1) if (snapstr.find("%i") == -1)
{
// if not, we always use the same name
fname.assign(snapstr); fname.assign(snapstr);
}
// otherwise, we scan for the next available filename
else else
{ {
// otherwise, we scan for the next available filename
// try until we succeed // try until we succeed
file.set_openflags(OPEN_FLAG_WRITE); file.set_openflags(OPEN_FLAG_WRITE);
for (int seq = 0; ; seq++) for (int seq = 0; ; seq++)