mirror of
https://github.com/holub/mame
synced 2025-04-24 09:20:02 +03:00
parent
44f98845f7
commit
34bc216ef9
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user