video_manager::video_manager(running_machine &machine) : m_machine(machine), m_screenless_frame_timer(nullptr), m_output_changed(false), m_throttle_last_ticks(0), m_throttle_realtime(attotime::zero), m_throttle_emutime(attotime::zero), m_throttle_history(0), m_speed_last_realtime(0), m_speed_last_emutime(attotime::zero), m_speed_percent(1.0), m_overall_real_seconds(0), m_overall_real_ticks(0), m_overall_emutime(attotime::zero), m_overall_valid_counter(0), m_throttled(machine.options().throttle()), m_throttle_rate(1.0f), m_fastforward(false), m_seconds_to_run(machine.options().seconds_to_run()), m_auto_frameskip(machine.options().auto_frameskip()), m_speed(original_speed_setting()), m_empty_skip_count(0), m_frameskip_level(machine.options().frameskip()), m_frameskip_counter(0), m_frameskip_adjust(0), m_skipping_this_frame(false), m_average_oversleep(0), m_snap_target(nullptr), m_snap_native(true), m_snap_width(0), m_snap_height(0), m_mng_frame_period(attotime::zero), m_mng_next_frame_time(attotime::zero), m_mng_frame(0), m_avi_file(nullptr), m_avi_frame_period(attotime::zero), m_avi_next_frame_time(attotime::zero), m_avi_frame(0), 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)); machine.save().register_postload(save_prepost_delegate(FUNC(video_manager::postload), this)); // extract initial execution state from global configuration settings update_refresh_speed(); // create a render target for snapshots const char *viewname = machine.options().snap_view(); m_snap_native = (machine.first_screen() != nullptr && (viewname[0] == 0 || strcmp(viewname, "native") == 0)); // the native target is hard-coded to our internal layout and has all options disabled if (m_snap_native) { m_snap_target = machine.render().target_alloc(layout_snap, RENDER_CREATE_SINGLE_FILE | RENDER_CREATE_HIDDEN); m_snap_target->set_backdrops_enabled(false); m_snap_target->set_overlays_enabled(false); m_snap_target->set_bezels_enabled(false); m_snap_target->set_cpanels_enabled(false); m_snap_target->set_marquees_enabled(false); m_snap_target->set_screen_overlay_enabled(false); m_snap_target->set_zoom_to_screen(false); } // other targets select the specified view and turn off effects else { m_snap_target = machine.render().target_alloc(nullptr, RENDER_CREATE_HIDDEN); m_snap_target->set_view(m_snap_target->configured_view(viewname, 0, 1)); m_snap_target->set_screen_overlay_enabled(false); } // extract snap resolution if present if (sscanf(machine.options().snap_size(), "%dx%d", &m_snap_width, &m_snap_height) != 2) m_snap_width = m_snap_height = 0; // start recording movie if specified const char *filename = machine.options().mng_write(); if (filename[0] != 0) begin_recording(filename, MF_MNG); filename = machine.options().avi_write(); if (filename[0] != 0) begin_recording(filename, MF_AVI); #ifdef MAME_DEBUG m_dummy_recording = machine.options().dummy_write(); #endif // if no screens, create a periodic timer to drive updates if (machine.first_screen() == nullptr) { m_screenless_frame_timer = machine.scheduler().timer_alloc(timer_expired_delegate(FUNC(video_manager::screenless_update_callback), this)); m_screenless_frame_timer->adjust(screen_device::DEFAULT_FRAME_PERIOD, 0, screen_device::DEFAULT_FRAME_PERIOD); machine.output().set_notifier(nullptr, video_notifier_callback, this); } }
video_manager::video_manager(running_machine &machine) : m_machine(machine) , m_screenless_frame_timer(nullptr) , m_output_changed(false) , m_throttle_last_ticks(0) , m_throttle_realtime(attotime::zero) , m_throttle_emutime(attotime::zero) , m_throttle_history(0) , m_speed_last_realtime(0) , m_speed_last_emutime(attotime::zero) , m_speed_percent(1.0) , m_overall_real_seconds(0) , m_overall_real_ticks(0) , m_overall_emutime(attotime::zero) , m_overall_valid_counter(0) , m_throttled(machine.options().throttle()) , m_throttle_rate(1.0f) , m_fastforward(false) , m_seconds_to_run(machine.options().seconds_to_run()) , m_auto_frameskip(machine.options().auto_frameskip()) , m_speed(original_speed_setting()) , m_empty_skip_count(0) , m_frameskip_level(machine.options().frameskip()) , m_frameskip_counter(0) , m_frameskip_adjust(0) , m_skipping_this_frame(false) , m_average_oversleep(0) , m_snap_target(nullptr) , m_snap_native(true) , m_snap_width(0) , m_snap_height(0) , 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(&video_manager::exit, this)); machine.save().register_postload(save_prepost_delegate(FUNC(video_manager::postload), this)); // extract initial execution state from global configuration settings update_refresh_speed(); const unsigned screen_count(screen_device_iterator(machine.root_device()).count()); const bool no_screens(!screen_count); // create a render target for snapshots const char *viewname = machine.options().snap_view(); m_snap_native = !no_screens && (viewname[0] == 0 || strcmp(viewname, "native") == 0); if (m_snap_native) { // the native target is hard-coded to our internal layout and has all options disabled util::xml::file::ptr const root(util::xml::file::create()); if (!root) throw emu_fatalerror("Couldn't create XML document??"); util::xml::data_node *const layoutnode(root->add_child("mamelayout", nullptr)); if (!layoutnode) throw emu_fatalerror("Couldn't create XML node??"); layoutnode->set_attribute_int("version", 2); for (unsigned i = 0; screen_count > i; ++i) { util::xml::data_node *const viewnode(layoutnode->add_child("view", nullptr)); if (!viewnode) throw emu_fatalerror("Couldn't create XML node??"); viewnode->set_attribute("name", util::xml::normalize_string(util::string_format("s%1$u", i).c_str())); util::xml::data_node *const screennode(viewnode->add_child("screen", nullptr)); if (!screennode) throw emu_fatalerror("Couldn't create XML node??"); screennode->set_attribute_int("index", i); util::xml::data_node *const boundsnode(screennode->add_child("bounds", nullptr)); if (!boundsnode) throw emu_fatalerror("Couldn't create XML node??"); boundsnode->set_attribute_int("left", 0); boundsnode->set_attribute_int("top", 0); boundsnode->set_attribute_int("right", 1); boundsnode->set_attribute_int("bottom", 1); } m_snap_target = machine.render().target_alloc(*root, RENDER_CREATE_SINGLE_FILE | RENDER_CREATE_HIDDEN); m_snap_target->set_backdrops_enabled(false); m_snap_target->set_overlays_enabled(false); m_snap_target->set_bezels_enabled(false); m_snap_target->set_cpanels_enabled(false); m_snap_target->set_marquees_enabled(false); m_snap_target->set_screen_overlay_enabled(false); m_snap_target->set_zoom_to_screen(false); } else { // otherwise, non-default targets select the specified view and turn off effects m_snap_target = machine.render().target_alloc(nullptr, RENDER_CREATE_HIDDEN); m_snap_target->set_view(m_snap_target->configured_view(viewname, 0, 1)); m_snap_target->set_screen_overlay_enabled(false); } // extract snap resolution if present if (sscanf(machine.options().snap_size(), "%dx%d", &m_snap_width, &m_snap_height) != 2) m_snap_width = m_snap_height = 0; // start recording movie if specified const char *filename = machine.options().mng_write(); if (filename[0] != 0) begin_recording(filename, MF_MNG); filename = machine.options().avi_write(); if (filename[0] != 0) begin_recording(filename, MF_AVI); // if no screens, create a periodic timer to drive updates if (no_screens) { m_screenless_frame_timer = machine.scheduler().timer_alloc(timer_expired_delegate(FUNC(video_manager::screenless_update_callback), this)); m_screenless_frame_timer->adjust(screen_device::DEFAULT_FRAME_PERIOD, 0, screen_device::DEFAULT_FRAME_PERIOD); machine.output().set_notifier(nullptr, video_notifier_callback, this); } }