summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/video.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/video.cpp')
-rw-r--r--src/emu/video.cpp152
1 files changed, 101 insertions, 51 deletions
diff --git a/src/emu/video.cpp b/src/emu/video.cpp
index 652272f680b..06a16b76cda 100644
--- a/src/emu/video.cpp
+++ b/src/emu/video.cpp
@@ -9,19 +9,26 @@
***************************************************************************/
#include "emu.h"
-#include "emuopts.h"
-#include "debugger.h"
-#include "ui/uimain.h"
+
#include "crsshair.h"
-#include "rendersw.hxx"
+#include "debugger.h"
+#include "emuopts.h"
+#include "fileio.h"
+#include "main.h"
#include "output.h"
+#include "screen.h"
+
+#include "ui/uimain.h"
#include "corestr.h"
+#include "path.h"
#include "png.h"
#include "xmlfile.h"
#include "osdepend.h"
+#include "rendersw.hxx"
+
//**************************************************************************
// DEBUGGING
@@ -211,8 +218,9 @@ void video_manager::frame_update(bool from_debugger)
bool const update_screens = (phase == machine_phase::RUNNING) && (!machine().paused() || machine().options().update_in_pause());
bool anything_changed = update_screens && finish_screen_updates();
- // draw the user interface
- emulator_info::draw_user_interface(machine());
+ // update inputs and draw the user interface
+ machine().osd().input_update(true);
+ anything_changed = emulator_info::draw_user_interface(machine()) || anything_changed;
// let plugins draw over the UI
anything_changed = emulator_info::frame_hook() || anything_changed;
@@ -227,21 +235,20 @@ void video_manager::frame_update(bool from_debugger)
// if we're throttling, synchronize before rendering
attotime current_time = machine().time();
- if (!from_debugger && !skipped_it && phase > machine_phase::INIT && !m_low_latency && effective_throttle())
+ if (!from_debugger && phase > machine_phase::INIT && !m_low_latency && effective_throttle())
update_throttle(current_time);
// ask the OSD to update
- g_profiler.start(PROFILER_BLIT);
- machine().osd().update(!from_debugger && skipped_it);
- g_profiler.stop();
+ {
+ auto profile = g_profiler.start(PROFILER_BLIT);
+ machine().osd().update(!from_debugger && skipped_it);
+ }
// we synchronize after rendering instead of before, if low latency mode is enabled
- if (!from_debugger && !skipped_it && phase > machine_phase::INIT && m_low_latency && effective_throttle())
+ if (!from_debugger && phase > machine_phase::INIT && m_low_latency && effective_throttle())
update_throttle(current_time);
- // get most recent input now
- machine().osd().input_update();
-
+ machine().osd().input_update(false);
emulator_info::periodic_check();
if (!from_debugger)
@@ -299,7 +306,7 @@ std::string video_manager::speed_text()
// append the speed for all cases except paused
if (!paused)
- util::stream_format(str, "%4d%%", (int)(100 * m_speed_percent + 0.5));
+ util::stream_format(str, " %3d%%", int(100 * m_speed_percent + 0.5));
// display the number of partial updates as well
int partials = 0;
@@ -317,7 +324,7 @@ std::string video_manager::speed_text()
// file handle
//-------------------------------------------------
-void video_manager::save_snapshot(screen_device *screen, emu_file &file)
+void video_manager::save_snapshot(screen_device *screen, util::core_file &file)
{
// validate
assert(!m_snap_native || screen != nullptr);
@@ -378,18 +385,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)
{
- // determine the file extension
- const char *extension = movie_recording::format_file_extension(format);
-
// 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>(
is_absolute_path ? "" : machine().options().snapshot_directory(),
OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
// and open the actual file
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);
if (filerr)
{
@@ -427,26 +431,48 @@ void video_manager::begin_recording(const char *name, movie_recording::format fo
// clear out existing recordings
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)
{
+ std::string tempname;
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)
- 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(
- tempname,
- index,
- iter.current(),
- format);
+ tempname,
+ index,
+ iter.current(),
+ format);
}
}
else
{
create_snapshot_bitmap(nullptr);
- begin_recording_screen(name ? name : "", 0, iter.current(), format);
+ begin_recording_screen(std::string(basename) + extension, 0, iter.current(), format);
}
}
@@ -492,7 +518,7 @@ void video_manager::exit()
// when there are no screens to drive it
//-------------------------------------------------
-void video_manager::screenless_update_callback(void *ptr, int param)
+void video_manager::screenless_update_callback(s32 param)
{
// force an update
frame_update(false);
@@ -506,8 +532,13 @@ void video_manager::screenless_update_callback(void *ptr, int param)
void video_manager::postload()
{
+ attotime const emutime = machine().time();
for (const auto &x : m_movie_recordings)
- x->set_next_frame_time(machine().time());
+ x->set_next_frame_time(emutime);
+
+ // reset speed measurements
+ m_speed_last_realtime = osd_ticks();
+ m_speed_last_emutime = emutime;
}
@@ -590,7 +621,7 @@ bool video_manager::finish_screen_updates()
bool has_live_screen = false;
for (screen_device &screen : iter)
{
- if (screen.partial_scan_hpos() >= 0) // previous update ended mid-scanline
+ if (screen.partial_scan_hpos() > 0) // previous update ended mid-scanline
screen.update_now();
screen.update_partial(screen.visible_area().max_y);
@@ -776,7 +807,7 @@ osd_ticks_t video_manager::throttle_until_ticks(osd_ticks_t target_ticks)
bool const allowed_to_sleep = (machine().options().sleep() && (!effective_autoframeskip() || effective_frameskip() == 0)) || machine().paused();
// loop until we reach our target
- g_profiler.start(PROFILER_IDLE);
+ auto profile = g_profiler.start(PROFILER_IDLE);
osd_ticks_t current_ticks = osd_ticks();
while (current_ticks < target_ticks)
{
@@ -812,7 +843,6 @@ osd_ticks_t video_manager::throttle_until_ticks(osd_ticks_t target_ticks)
}
current_ticks = new_ticks;
}
- g_profiler.stop();
return current_ticks;
}
@@ -960,10 +990,23 @@ void video_manager::recompute_speed(const attotime &emutime)
if (m_seconds_to_run != 0 && emutime.seconds() >= m_seconds_to_run)
{
// create a final screenshot
- 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);
+ if (m_snap_native)
+ {
+ for (screen_device &screen : screen_device_enumerator(machine().root_device()))
+ {
+ 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());
// schedule our demise
@@ -1057,14 +1100,19 @@ std::error_condition video_manager::open_next(emu_file &file, const char *extens
// handle defaults
const char *snapname = machine().options().snap_name();
- if (snapname == nullptr || snapname[0] == 0)
+ if (!snapname || !snapname[0])
snapname = "%g/%i";
std::string snapstr(snapname);
- // strip any extension in the provided name
- int index = snapstr.find_last_of('.');
- if (index != -1)
- snapstr = snapstr.substr(0, index);
+ // strip desired extension if already present
+ std::string extstr;
+ extstr.reserve(1 + std::strlen(extension));
+ 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)
std::string snapdev("%d_");
@@ -1129,27 +1177,30 @@ std::error_condition video_manager::open_next(emu_file &file, const char *extens
if (pos_time != -1)
{
- char t_str[15];
+ char t_str[16];
const std::time_t cur_time = std::time(nullptr);
strftime(t_str, sizeof(t_str), "%Y%m%d_%H%M%S", std::localtime(&cur_time));
strreplace(snapstr, "%t", t_str);
}
- // add our own extension
- snapstr.append(".").append(extension);
+ // append extension
+ snapstr.append(extstr);
// substitute path and gamename up front
strreplace(snapstr, "/", PATH_SEPARATOR);
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;
if (snapstr.find("%i") == -1)
+ {
+ // if not, we always use the same name
fname.assign(snapstr);
-
- // otherwise, we scan for the next available filename
+ }
else
{
+ // otherwise, we scan for the next available filename
+
// try until we succeed
file.set_openflags(OPEN_FLAG_WRITE);
for (int seq = 0; ; seq++)
@@ -1182,7 +1233,7 @@ void video_manager::record_frame()
return;
// start the profiler and get the current time
- g_profiler.start(PROFILER_MOVIE_REC);
+ auto profile = g_profiler.start(PROFILER_MOVIE_REC);
attotime curtime = machine().time();
bool error = false;
@@ -1201,7 +1252,6 @@ void video_manager::record_frame()
if (error)
end_recording();
- g_profiler.stop();
}