summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/emu/ioport.cpp197
-rw-r--r--src/emu/ioport.h7
-rw-r--r--src/emu/ui/ui.cpp26
-rw-r--r--src/emu/ui/ui.h6
-rw-r--r--src/emu/video.cpp57
-rw-r--r--src/emu/video.h18
6 files changed, 308 insertions, 3 deletions
diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp
index 282cc5c256c..501ba5d783b 100644
--- a/src/emu/ioport.cpp
+++ b/src/emu/ioport.cpp
@@ -2454,6 +2454,9 @@ ioport_manager::ioport_manager(running_machine &machine)
m_playback_file(machine.options().input_directory(), OPEN_FLAG_READ),
m_playback_accumulated_speed(0),
m_playback_accumulated_frames(0),
+ m_timecode_file(machine.options().input_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS),
+ m_timecode_count(0),
+ m_timecode_last_time(attotime::zero),
m_has_configs(false),
m_has_analog(false),
m_has_dips(false),
@@ -2564,6 +2567,7 @@ time_t ioport_manager::initialize()
// open playback and record files if specified
time_t basetime = playback_init();
record_init();
+ timecode_init();
return basetime;
}
@@ -2657,6 +2661,7 @@ void ioport_manager::exit()
// close any playback or recording files
playback_end();
record_end();
+ timecode_end();
}
@@ -3428,6 +3433,12 @@ void ioport_manager::playback_end(const char *message)
m_playback_accumulated_speed /= m_playback_accumulated_frames;
osd_printf_info("Total playback frames: %d\n", UINT32(m_playback_accumulated_frames));
osd_printf_info("Average recorded speed: %d%%\n", UINT32((m_playback_accumulated_speed * 200 + 1) >> 21));
+
+ // Close the Mame at the end of inp file playback
+ //if (strcmp(message, "End of file")) {
+ osd_printf_info("Exiting MAME now...\n");
+ machine().schedule_exit();
+ //}
}
}
@@ -3510,6 +3521,29 @@ void ioport_manager::record_write<bool>(bool value)
record_write(byte);
}
+template<typename _Type>
+void ioport_manager::timecode_write(_Type value)
+{
+ // protect against NULL handles if previous reads fail
+ if (!m_timecode_file.is_open())
+ return;
+
+ // read the value; if we fail, end playback
+ if (m_timecode_file.write(&value, sizeof(value)) != sizeof(value))
+ timecode_end("Out of space");
+}
+
+/*template<>
+void ioport_manager::timecode_write<bool>(bool value)
+{
+ UINT8 byte = UINT8(value);
+ timecode_write(byte);
+}*/
+template<>
+void ioport_manager::timecode_write<std::string>(std::string value) {
+ timecode_write(value.c_str());
+}
+
//-------------------------------------------------
// record_init - initialize INP recording
@@ -3554,6 +3588,41 @@ void ioport_manager::record_init()
}
+void ioport_manager::timecode_init() {
+ // if no file, nothing to do
+ const char *record_filename = machine().options().record();
+ if (record_filename[0] == 0) {
+ machine().video().set_timecode_enabled(false);
+ return;
+ }
+ //osd_printf_error("DEBUG FILENAME-1: %s\n", record_filename);
+ machine().video().set_timecode_enabled(true);
+
+ // open the record file
+ std::string filename;
+ filename.append(record_filename).append(".timecode");
+ //sprintf(filename, "%s.timecode", record_filename);
+
+ //osd_printf_error("DEBUG FILENAME-2: %s\n", filename.c_str());
+
+ file_error filerr = m_timecode_file.open(filename.c_str());
+ assert_always(filerr == FILERR_NONE, "Failed to open file for timecode recording");
+
+ m_timecode_file.puts(std::string("# ==========================================\n").c_str());
+ m_timecode_file.puts(std::string("# TIMECODE FILE FOR VIDEO PREVIEW GENERATION\n").c_str());
+ m_timecode_file.puts(std::string("# ==========================================\n").c_str());
+ m_timecode_file.puts(std::string("#\n").c_str());
+ m_timecode_file.puts(std::string("# VIDEO_PART: code of video timecode\n").c_str());
+ m_timecode_file.puts(std::string("# START: start time (hh:mm:ss.mmm)\n").c_str());
+ m_timecode_file.puts(std::string("# ELAPSED: elapsed time (hh:mm:ss.mmm)\n").c_str());
+ m_timecode_file.puts(std::string("# MSEC_START: start time (milliseconds)\n").c_str());
+ m_timecode_file.puts(std::string("# MSEC_ELAPSED: elapsed time (milliseconds)\n").c_str());
+ m_timecode_file.puts(std::string("# FRAME_START: start time (frames)\n").c_str());
+ m_timecode_file.puts(std::string("# FRAME_ELAPSED: elapsed time (frames)\n").c_str());
+ m_timecode_file.puts(std::string("#\n").c_str());
+ m_timecode_file.puts(std::string("# VIDEO_PART======= START======= ELAPSED===== MSEC_START===== MSEC_ELAPSED=== FRAME_START==== FRAME_ELAPSED==\n").c_str());
+}
+
//-------------------------------------------------
// record_end - end INP recording
//-------------------------------------------------
@@ -3573,6 +3642,19 @@ void ioport_manager::record_end(const char *message)
}
+void ioport_manager::timecode_end(const char *message)
+{
+ // only applies if we have a live file
+ if (m_timecode_file.is_open()) {
+ // close the file
+ m_timecode_file.close();
+
+ // pop a message
+ if (message != nullptr)
+ machine().popmessage("Recording Timecode Ended\nReason: %s", message);
+ }
+}
+
//-------------------------------------------------
// record_frame - start of frame callback for
// recording
@@ -3584,12 +3666,123 @@ void ioport_manager::record_frame(const attotime &curtime)
if (m_record_file.is_open())
{
// first the absolute time
- record_write(curtime.seconds());
- record_write(curtime.attoseconds());
+ record_write(curtime.m_seconds);
+ record_write(curtime.m_attoseconds);
// then the current speed
record_write(UINT32(machine().video().speed_percent() * double(1 << 20)));
}
+
+ if (m_timecode_file.is_open() && machine().video().get_timecode_write()) {
+ // Display the timecode
+ std::string current_time_str;
+ m_timecode_count++;
+ strcatprintf(current_time_str, "%02d:%02d:%02d.%03d",
+ (int)curtime.m_seconds / (60 * 60),
+ (curtime.m_seconds / 60) % 60,
+ curtime.m_seconds % 60,
+ (int)(curtime.m_attoseconds/ATTOSECONDS_PER_MILLISECOND));
+
+ // Elapsed from previous timecode
+ attotime elapsed_time = curtime - m_timecode_last_time;
+ m_timecode_last_time = curtime;
+ std::string elapsed_time_str;
+ strcatprintf(elapsed_time_str, "%02d:%02d:%02d.%03d",
+ elapsed_time.m_seconds / (60 * 60),
+ (elapsed_time.m_seconds / 60) % 60,
+ elapsed_time.m_seconds % 60,
+ int(elapsed_time.m_attoseconds/ATTOSECONDS_PER_MILLISECOND));
+
+ // Number of ms from beginning of playback
+ int mseconds_start = curtime.m_seconds*1000 + curtime.m_attoseconds/ATTOSECONDS_PER_MILLISECOND;
+ std::string mseconds_start_str;
+ strcatprintf(mseconds_start_str, "%015d", mseconds_start);
+
+ // Number of ms from previous timecode
+ int mseconds_elapsed = elapsed_time.m_seconds*1000 + elapsed_time.m_attoseconds/ATTOSECONDS_PER_MILLISECOND;
+ std::string mseconds_elapsed_str;
+ strcatprintf(mseconds_elapsed_str, "%015d", mseconds_elapsed);
+
+ // Number of frames from beginning of playback
+ int frame_start = mseconds_start * 60 / 1000;
+ std::string frame_start_str;
+ strcatprintf(frame_start_str, "%015d", frame_start);
+
+ // Number of frames from previous timecode
+ int frame_elapsed = mseconds_elapsed * 60 / 1000;
+ std::string frame_elapsed_str;
+ strcatprintf(frame_elapsed_str, "%015d", frame_elapsed);
+
+ std::string messaggio;
+ std::string timecode_text;
+ std::string timecode_key;
+ bool show_timecode_counter = false;
+ if (m_timecode_count==1) {
+ messaggio += "INTRO STARTED AT " + current_time_str;
+ timecode_key = "INTRO_START";
+ timecode_text = "INTRO";
+ show_timecode_counter = true;
+ }
+ else if (m_timecode_count==2) {
+ messaggio += "INTRO DURATION " + elapsed_time_str;
+ timecode_key = "INTRO_STOP";
+ machine().video().add_to_total_time(elapsed_time);
+ //timecode_text += "INTRO";
+ }
+ else if (m_timecode_count==3) {
+ messaggio += "GAMEPLAY STARTED AT " + current_time_str;
+ timecode_key = "GAMEPLAY_START";
+ timecode_text += "GAMEPLAY";
+ show_timecode_counter = true;
+ }
+ else if (m_timecode_count==4) {
+ messaggio += "GAMEPLAY DURATION " + elapsed_time_str;
+ timecode_key = "GAMEPLAY_STOP";
+ machine().video().add_to_total_time(elapsed_time);
+ //timecode_text += "GAMEPLAY";
+ }
+ else if (m_timecode_count % 2 == 1) {
+ std::string timecode_count_str;
+ strcatprintf(timecode_count_str, "%03d", (m_timecode_count-3)/2);
+ timecode_key = "EXTRA_START_" + timecode_count_str;
+ timecode_count_str.clear();
+ strcatprintf(timecode_count_str, "%d", (m_timecode_count-3)/2);
+ messaggio += "EXTRA " + timecode_count_str + " STARTED AT " + current_time_str;
+ timecode_text += "EXTRA " + timecode_count_str;
+ show_timecode_counter = true;
+ }
+ else {
+ machine().video().add_to_total_time(elapsed_time);
+
+ std::string timecode_count_str;
+ strcatprintf(timecode_count_str, "%d", (m_timecode_count-4)/2);
+ messaggio += "EXTRA " + timecode_count_str + " DURATION " + elapsed_time_str;
+
+ //std::string timecode_count_str;
+ timecode_count_str.clear();
+ strcatprintf(timecode_count_str, "%03d", (m_timecode_count-4)/2);
+ timecode_key = "EXTRA_STOP_" + timecode_count_str;
+ }
+
+ osd_printf_info("%s \n", messaggio.c_str());
+ machine().popmessage("%s \n", messaggio.c_str());
+
+ std::string riga_file;
+ riga_file.append(timecode_key).append(19-timecode_key.length(), ' ');
+ //riga_file += "INTRO_START " +
+ riga_file +=
+ " " + current_time_str + " " + elapsed_time_str +
+ " " + mseconds_start_str + " " + mseconds_elapsed_str +
+ " " + frame_start_str + " " + frame_elapsed_str +
+ "\n";
+ m_timecode_file.puts(riga_file.c_str());
+
+ machine().video().set_timecode_write(false);
+ //machine().video().set_timecode_text(timecode_text);
+ machine().video().set_timecode_text(timecode_text);
+ machine().video().set_timecode_start(m_timecode_last_time);
+ machine().ui().set_show_timecode_counter(show_timecode_counter);
+ }
}
diff --git a/src/emu/ioport.h b/src/emu/ioport.h
index 9ba2818c5d0..3fbff3e852c 100644
--- a/src/emu/ioport.h
+++ b/src/emu/ioport.h
@@ -1452,6 +1452,10 @@ private:
void record_frame(const attotime &curtime);
void record_port(ioport_port &port);
+ template<typename _Type> void timecode_write(_Type value);
+ void timecode_init();
+ void timecode_end(const char *message = NULL);
+
// internal state
running_machine & m_machine; // reference to owning machine
bool m_safe_to_read; // clear at start; set after state is loaded
@@ -1474,6 +1478,9 @@ private:
emu_file m_playback_file; // playback file (NULL if not recording)
UINT64 m_playback_accumulated_speed; // accumulated speed during playback
UINT32 m_playback_accumulated_frames; // accumulated frames during playback
+ emu_file m_timecode_file; // timecode/frames playback file (NULL if not recording)
+ int m_timecode_count;
+ attotime m_timecode_last_time;
// has...
bool m_has_configs;
diff --git a/src/emu/ui/ui.cpp b/src/emu/ui/ui.cpp
index 6d996ac50a0..860da34e212 100644
--- a/src/emu/ui/ui.cpp
+++ b/src/emu/ui/ui.cpp
@@ -286,6 +286,8 @@ void ui_manager::init()
m_popup_text_end = 0;
m_use_natural_keyboard = false;
m_mouse_arrow_texture = nullptr;
+ m_show_timecode_counter = false;
+ m_show_timecode_total = false;
m_load_save_hold = false;
get_font_rows(&machine());
@@ -1035,6 +1037,16 @@ bool ui_manager::is_menu_active(void)
}
+bool ui_manager::show_timecode_counter()
+{
+ return m_show_timecode_counter;
+}
+bool ui_manager::show_timecode_total()
+{
+ return m_show_timecode_total;
+}
+
+
/***************************************************************************
TEXT GENERATORS
@@ -1559,6 +1571,20 @@ UINT32 ui_manager::handler_ingame(running_machine &machine, render_container *co
JUSTIFY_RIGHT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, nullptr, nullptr);
}
+ // Show the duration of current part (intro or gameplay or extra)
+ if (machine.ui().show_timecode_counter()) {
+ std::string tempstring;
+ machine.ui().draw_text_full(container, machine.video().timecode_text(tempstring).c_str(), 0.0f, 0.0f, 1.0f,
+ JUSTIFY_RIGHT, WRAP_WORD, DRAW_OPAQUE, rgb_t(0xf0,0xf0,0x10,0x10), ARGB_BLACK, NULL, NULL);
+ }
+ // Show the total time elapsed for the video preview (all parts intro, gameplay, extras)
+ if (machine.ui().show_timecode_total()) {
+ std::string tempstring;
+ machine.ui().draw_text_full(container, machine.video().timecode_total_text(tempstring).c_str(), 0.0f, 0.0f, 1.0f,
+ JUSTIFY_LEFT, WRAP_WORD, DRAW_OPAQUE, rgb_t(0xf0,0x10,0xf0,0x10), ARGB_BLACK, NULL, NULL);
+ }
+
+
// draw the profiler if visible
if (machine.ui().show_profiler())
{
diff --git a/src/emu/ui/ui.h b/src/emu/ui/ui.h
index 5a07a0800b5..3da9bfb1bab 100644
--- a/src/emu/ui/ui.h
+++ b/src/emu/ui/ui.h
@@ -171,6 +171,10 @@ public:
// other
void process_natural_keyboard();
+ void set_show_timecode_counter(bool value) { m_show_timecode_counter = value; m_show_timecode_total = true; }
+ bool show_timecode_counter();
+ bool show_timecode_total();
+
// word wrap
void wrap_text(render_container *container, const char *origs, float x, float y, float origwrapwidth, int &totallines, std::vector<int> &xstart, std::vector<int> &xend, float text_size = 1.0f);
@@ -195,6 +199,8 @@ private:
std::unique_ptr<UINT8[]> m_non_char_keys_down;
render_texture * m_mouse_arrow_texture;
bool m_mouse_show;
+ bool m_show_timecode_counter;
+ bool m_show_timecode_total;
bool m_load_save_hold;
ui_options m_ui_options;
diff --git a/src/emu/video.cpp b/src/emu/video.cpp
index d05a1b8327c..4b2a315d75c 100644
--- a/src/emu/video.cpp
+++ b/src/emu/video.cpp
@@ -108,7 +108,13 @@ video_manager::video_manager(running_machine &machine)
m_avi_frame_period(attotime::zero),
m_avi_next_frame_time(attotime::zero),
m_avi_frame(0),
- m_dummy_recording(false)
+ m_dummy_recording(false),
+ m_timecode_enabled(false),
+ m_timecode_write(false),
+ m_timecode_text(""),
+ m_timecode_start(attotime::zero),
+ m_timecode_total(attotime::zero)
+
{
// request a callback upon exiting
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(video_manager::exit), this));
@@ -335,6 +341,13 @@ void video_manager::save_snapshot(screen_device *screen, emu_file &file)
void video_manager::save_active_screen_snapshots()
{
+ // If record inp is acrive, no snapshot will be created
+ if (m_timecode_enabled) {
+ // This flag will write the line on file inp.timecode (see function ioport_manager::record_frame)
+ m_timecode_write = true;
+ return;
+ }
+
// if we're native, then write one snapshot per visible screen
if (m_snap_native)
{
@@ -360,6 +373,48 @@ void video_manager::save_active_screen_snapshots()
}
}
+std::string &video_manager::timecode_text(std::string &str) {
+ str.clear();
+ str += " ";
+
+ if (!m_timecode_text.empty()) {
+ str += m_timecode_text + " ";
+ }
+
+ attotime elapsed_time = machine().time() - m_timecode_start;
+ std::string elapsed_time_str;
+ strcatprintf(elapsed_time_str, "%02d:%02d",
+ (elapsed_time.m_seconds / 60) % 60,
+ elapsed_time.m_seconds % 60);
+ str += elapsed_time_str;
+
+ bool paused = machine().paused();
+ if (paused) {
+ str.append(" [paused]");
+ }
+
+ str += " ";
+
+ return str;
+}
+
+std::string &video_manager::timecode_total_text(std::string &str) {
+ str.clear();
+ str += " TOTAL ";
+
+ attotime elapsed_time = m_timecode_total;
+ if (machine().ui().show_timecode_counter()) {
+ elapsed_time += machine().time() - m_timecode_start;
+ }
+ std::string elapsed_time_str;
+ strcatprintf(elapsed_time_str, "%02d:%02d",
+ (elapsed_time.m_seconds / 60) % 60,
+ elapsed_time.m_seconds % 60);
+ str += elapsed_time_str + " ";
+ return str;
+}
+
+
//-------------------------------------------------
// begin_recording - begin recording of a movie
diff --git a/src/emu/video.h b/src/emu/video.h
index aef70a57f15..2403fe295f6 100644
--- a/src/emu/video.h
+++ b/src/emu/video.h
@@ -92,6 +92,17 @@ public:
void begin_recording(const char *name, movie_format format);
void end_recording(movie_format format);
void add_sound_to_recording(const INT16 *sound, int numsamples);
+
+ void set_timecode_enabled(bool value) { m_timecode_enabled = value; }
+ bool get_timecode_enabled() { return m_timecode_enabled; }
+ bool get_timecode_write() { return m_timecode_write; }
+ void set_timecode_write(bool value) { m_timecode_write = value; }
+ void set_timecode_text(std::string &str) { m_timecode_text = str; }
+ void set_timecode_start(attotime time) { m_timecode_start = time; }
+ void add_to_total_time(attotime time) { m_timecode_total += time; }
+ std::string &timecode_text(std::string &str);
+ std::string &timecode_total_text(std::string &str);
+
private:
// internal helpers
@@ -184,6 +195,13 @@ private:
static const attoseconds_t ATTOSECONDS_PER_SPEED_UPDATE = ATTOSECONDS_PER_SECOND / 4;
static const int PAUSED_REFRESH_RATE = 30;
+
+ bool m_timecode_enabled; // inp.timecode record enabled
+ bool m_timecode_write; // Show/hide timer at right (partial time)
+ std::string m_timecode_text; // Message for that video part (intro, gameplay, extra)
+ attotime m_timecode_start; // Starting timer for that video part (intro, gameplay, extra)
+ attotime m_timecode_total; // Show/hide timer at left (total elapsed on resulting video preview)
+
};
#endif /* __VIDEO_H__ */