From af31f4b3deaf74cdcc4e4a8ff3447f4247f86f4f Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Mon, 12 Mar 2018 17:31:40 +1100 Subject: [PATCH] better handling for arbitrary numbers of screens (nw) --- src/emu/debug/dvstate.cpp | 2 +- src/emu/layout/snap.lay | 50 --------- src/emu/render.cpp | 72 +++++++++---- src/emu/render.h | 6 ++ src/emu/screen.h | 2 - src/emu/video.cpp | 210 ++++++++++++++++++++------------------ src/emu/video.h | 4 +- 7 files changed, 173 insertions(+), 173 deletions(-) delete mode 100644 src/emu/layout/snap.lay diff --git a/src/emu/debug/dvstate.cpp b/src/emu/debug/dvstate.cpp index 092c6885ca0..e0004f9bb60 100644 --- a/src/emu/debug/dvstate.cpp +++ b/src/emu/debug/dvstate.cpp @@ -136,7 +136,7 @@ void debug_view_state::recompute() } else if (screen_count > 1) { - for (int i = 0; i < screen_count; i++, iter++) + for (int i = 0; (i < screen_count) && (i < 8); i++, iter++) { m_state_list.emplace_back(REG_BEAMX_S0 - i, string_format("beamx%d", i).c_str(), 4); m_state_list.emplace_back(REG_BEAMY_S0 - i, string_format("beamy%d", i).c_str(), 4); diff --git a/src/emu/layout/snap.lay b/src/emu/layout/snap.lay deleted file mode 100644 index 76dfb93d60c..00000000000 --- a/src/emu/layout/snap.lay +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emu/render.cpp b/src/emu/render.cpp index 318ff1c384f..d33590731e8 100644 --- a/src/emu/render.cpp +++ b/src/emu/render.cpp @@ -906,21 +906,31 @@ render_container::user_settings::user_settings() //------------------------------------------------- render_target::render_target(render_manager &manager, const internal_layout *layoutfile, u32 flags) - : m_next(nullptr), - m_manager(manager), - m_curview(nullptr), - m_flags(flags), - m_listindex(0), - m_width(640), - m_height(480), - m_pixel_aspect(0.0f), - m_max_refresh(0), - m_orientation(0), - m_base_view(nullptr), - m_base_orientation(ROT0), - m_maxtexwidth(65536), - m_maxtexheight(65536), - m_transform_container(true) + : render_target(manager, layoutfile, flags, CONSTRUCTOR_IMPL) +{ +} + +render_target::render_target(render_manager &manager, util::xml::data_node const &layout, u32 flags) + : render_target(manager, layout, flags, CONSTRUCTOR_IMPL) +{ +} + +template render_target::render_target(render_manager &manager, T &&layout, u32 flags, constructor_impl_t) + : m_next(nullptr) + , m_manager(manager) + , m_curview(nullptr) + , m_flags(flags) + , m_listindex(0) + , m_width(640) + , m_height(480) + , m_pixel_aspect(0.0f) + , m_max_refresh(0) + , m_orientation(0) + , m_base_view(nullptr) + , m_base_orientation(ROT0) + , m_maxtexwidth(65536) + , m_maxtexheight(65536) + , m_transform_container(true) { // determine the base layer configuration based on options m_base_layerconfig.set_backdrops_enabled(manager.machine().options().use_backdrops()); @@ -967,7 +977,7 @@ render_target::render_target(render_manager &manager, const internal_layout *lay m_layerconfig = m_base_layerconfig; // load the layout files - load_layout_files(layoutfile, flags & RENDER_CREATE_SINGLE_FILE); + load_layout_files(std::forward(layout), flags & RENDER_CREATE_SINGLE_FILE); // set the current view to the first one set_view(0); @@ -1574,9 +1584,7 @@ void render_target::update_layer_config() void render_target::load_layout_files(const internal_layout *layoutfile, bool singlefile) { - bool have_default = false; bool have_artwork = false; - bool have_override = false; // if there's an explicit file, load that first const char *basename = m_manager.machine().basename(); @@ -1584,8 +1592,27 @@ void render_target::load_layout_files(const internal_layout *layoutfile, bool si have_artwork |= load_layout_file(basename, layoutfile); // if we're only loading this file, we know our final result - if (singlefile) - return; + if (!singlefile) + load_additional_layout_files(basename, have_artwork); +} + +void render_target::load_layout_files(util::xml::data_node const &rootnode, bool singlefile) +{ + bool have_artwork = false; + + // if there's an explicit file, load that first + const char *basename = m_manager.machine().basename(); + have_artwork |= load_layout_file(basename, rootnode); + + // if we're only loading this file, we know our final result + if (!singlefile) + load_additional_layout_files(basename, have_artwork); +} + +void render_target::load_additional_layout_files(const char *basename, bool have_artwork) +{ + bool have_default = false; + bool have_override = false; // if override_artwork defined, load that and skip artwork other than default if (m_manager.machine().options().override_artwork()) @@ -2873,6 +2900,11 @@ render_target *render_manager::target_alloc(const internal_layout *layoutfile, u return &m_targetlist.append(*global_alloc(render_target(*this, layoutfile, flags))); } +render_target *render_manager::target_alloc(util::xml::data_node const &layout, u32 flags) +{ + return &m_targetlist.append(*global_alloc(render_target(*this, layout, flags))); +} + //------------------------------------------------- // target_free - free a target diff --git a/src/emu/render.h b/src/emu/render.h index e7ac98e8dfb..c68c4e04e23 100644 --- a/src/emu/render.h +++ b/src/emu/render.h @@ -934,6 +934,7 @@ class render_target // construction/destruction render_target(render_manager &manager, const internal_layout *layoutfile = nullptr, u32 flags = 0); + render_target(render_manager &manager, util::xml::data_node const &layout, u32 flags = 0); ~render_target(); public: @@ -1012,8 +1013,12 @@ public: private: // internal helpers + enum constructor_impl_t { CONSTRUCTOR_IMPL }; + template render_target(render_manager &manager, T&& layout, u32 flags, constructor_impl_t); void update_layer_config(); void load_layout_files(const internal_layout *layoutfile, bool singlefile); + void load_layout_files(util::xml::data_node const &rootnode, bool singlefile); + void load_additional_layout_files(const char *basename, bool have_artwork); bool load_layout_file(const char *dirname, const char *filename); bool load_layout_file(const char *dirname, const internal_layout *layout_data); bool load_layout_file(const char *dirname, util::xml::data_node const &rootnode); @@ -1095,6 +1100,7 @@ public: // targets render_target *target_alloc(const internal_layout *layoutfile = nullptr, u32 flags = 0); + render_target *target_alloc(util::xml::data_node const &layout, u32 flags = 0); void target_free(render_target *target); const simple_list &targets() const { return m_targetlist; } render_target *first_target() const { return m_targetlist.first(); } diff --git a/src/emu/screen.h b/src/emu/screen.h index 1ccda1f6eb0..e3c74cf2faf 100644 --- a/src/emu/screen.h +++ b/src/emu/screen.h @@ -43,8 +43,6 @@ enum texture_format // screen_update callback flags constexpr u32 UPDATE_HAS_NOT_CHANGED = 0x0001; // the video has not changed -constexpr u32 MAX_NUM_SCREENS = 9; - /*! @defgroup flags for video_attributes @{ diff --git a/src/emu/video.cpp b/src/emu/video.cpp index 6cc6af39454..434e51be969 100644 --- a/src/emu/video.cpp +++ b/src/emu/video.cpp @@ -10,18 +10,19 @@ #include "emu.h" #include "emuopts.h" -#include "png.h" #include "debugger.h" #include "ui/uimain.h" -#include "aviio.h" #include "crsshair.h" #include "rendersw.hxx" #include "output.h" -#include "snap.lh" +#include "aviio.h" +#include "png.h" +#include "xmlfile.h" #include "osdepend.h" + //************************************************************************** // DEBUGGING //************************************************************************** @@ -70,42 +71,41 @@ static void video_notifier_callback(const char *outname, s32 value, void *param) //------------------------------------------------- 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) - + : 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)); @@ -114,7 +114,8 @@ video_manager::video_manager(running_machine &machine) // extract initial execution state from global configuration settings update_refresh_speed(); - const bool no_screens = screen_device_iterator(machine.root_device()).count() == 0; + 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(); @@ -123,7 +124,34 @@ video_manager::video_manager(running_machine &machine) if (m_snap_native) { // the native target is hard-coded to our internal layout and has all options disabled - m_snap_target = machine.render().target_alloc(&layout_snap, RENDER_CREATE_SINGLE_FILE | RENDER_CREATE_HIDDEN); + 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); @@ -537,6 +565,8 @@ void video_manager::begin_recording(const char *name, movie_format format) switch (format) { case MF_AVI: + if (m_avis.empty()) + m_avis.resize(count); if (m_snap_native) { for (uint32_t index = 0; index < count; index++, iter++) @@ -553,6 +583,8 @@ void video_manager::begin_recording(const char *name, movie_format format) break; case MF_MNG: + if (m_mngs.empty()) + m_mngs.resize(count); if (m_snap_native) { for (uint32_t index = 0; index < count; index++, iter++) @@ -564,7 +596,7 @@ void video_manager::begin_recording(const char *name, movie_format format) else { create_snapshot_bitmap(nullptr); - begin_recording_avi(name, 0, iter.current()); + begin_recording_mng(name, 0, iter.current()); } break; @@ -615,17 +647,11 @@ void video_manager::end_recording_mng(uint32_t index) void video_manager::add_sound_to_recording(const s16 *sound, int numsamples) { - if (m_snap_native) + for (uint32_t index = 0; index < m_avis.size(); index++) { - const uint32_t count = (uint32_t)screen_device_iterator(machine().root_device()).count(); - for (uint32_t index = 0; index < count; index++) - { - add_sound_to_avi_recording(sound, numsamples, index); - } - } - else - { - add_sound_to_avi_recording(sound, numsamples, 0); + add_sound_to_avi_recording(sound, numsamples, index); + if (!m_snap_native) + break; } } @@ -660,19 +686,16 @@ void video_manager::add_sound_to_avi_recording(const s16 *sound, int numsamples, void video_manager::exit() { // stop recording any movie - - screen_device_iterator device_iterator = screen_device_iterator(machine().root_device()); - screen_device_iterator::auto_iterator iter = device_iterator.begin(); - const uint32_t count = (uint32_t)device_iterator.count(); - - for (uint32_t index = 0; index < count; index++, iter++) + for (uint32_t index = 0; index < (std::max)(m_mngs.size(), m_avis.size()); index++) { - end_recording_avi(index); - end_recording_mng(index); + if (index < m_avis.size()) + end_recording_avi(index); + + if (index < m_mngs.size()) + end_recording_mng(index); + if (!m_snap_native) - { break; - } } // free the snapshot target @@ -709,18 +732,16 @@ void video_manager::screenless_update_callback(void *ptr, int param) void video_manager::postload() { - screen_device_iterator device_iterator = screen_device_iterator(machine().root_device()); - screen_device_iterator::auto_iterator iter = device_iterator.begin(); - const uint32_t count = (uint32_t)device_iterator.count(); - - for (uint32_t index = 0; index < count; index++, iter++) + for (uint32_t index = 0; index < (std::max)(m_mngs.size(), m_avis.size()); index++) { - m_avis[index].m_avi_next_frame_time = machine().time(); - m_mngs[index].m_mng_next_frame_time = machine().time(); + if (index < m_avis.size()) + m_avis[index].m_avi_next_frame_time = machine().time(); + + if (index < m_mngs.size()) + m_mngs[index].m_mng_next_frame_time = machine().time(); + if (!m_snap_native) - { break; - } } } @@ -732,22 +753,20 @@ void video_manager::postload() bool video_manager::is_recording() const { - screen_device_iterator device_iterator = screen_device_iterator(machine().root_device()); - screen_device_iterator::auto_iterator iter = device_iterator.begin(); - const uint32_t count = (uint32_t)device_iterator.count(); - - for (uint32_t index = 0; index < count; index++, iter++) + for (mng_info_t const &mng : m_mngs) { - if (m_mngs[index].m_mng_file || m_avis[index].m_avi_file) - { + if (mng.m_mng_file) return true; - } - if (!m_snap_native) - { + else if (!m_snap_native) + break; + } + for (avi_info_t const &avi : m_avis) + { + if (avi.m_avi_file) + return true; + else if (!m_snap_native) break; - } } - return false; } @@ -1395,13 +1414,7 @@ osd_file::error video_manager::open_next(emu_file &file, const char *extension, void video_manager::record_frame() { // ignore if nothing to do - bool any_recording = false; - for (uint32_t index = 0; index < MAX_NUM_SCREENS && !any_recording; index++) - { - if (m_mngs[index].m_mng_file != nullptr || m_avis[index].m_avi_file != nullptr) - any_recording = true; - } - if (!any_recording) + if (!is_recording()) return; // start the profiler and get the current time @@ -1410,17 +1423,17 @@ void video_manager::record_frame() screen_device_iterator device_iterator = screen_device_iterator(machine().root_device()); screen_device_iterator::auto_iterator iter = device_iterator.begin(); - const uint32_t count = (uint32_t)device_iterator.count(); - for (uint32_t index = 0; index < count; index++, iter++) + for (uint32_t index = 0; index < (std::max)(m_mngs.size(), m_avis.size()); index++, iter++) { // create the bitmap create_snapshot_bitmap(iter.current()); // handle an AVI recording - avi_info_t &avi_info = m_avis[index]; - if (avi_info.m_avi_file != nullptr) + if ((index < m_avis.size()) && m_avis[index].m_avi_file) { + avi_info_t &avi_info = m_avis[index]; + // loop until we hit the right time while (avi_info.m_avi_next_frame_time <= curtime) { @@ -1428,7 +1441,7 @@ void video_manager::record_frame() avi_file::error avierr = avi_info.m_avi_file->append_video_frame(m_snap_bitmap); if (avierr != avi_file::error::NONE) { - g_profiler.stop(); + g_profiler.stop(); // FIXME: double exit if this happens? end_recording_avi(index); break; } @@ -1440,9 +1453,10 @@ void video_manager::record_frame() } // handle a MNG recording - mng_info_t &mng_info = m_mngs[index]; - if (mng_info.m_mng_file != nullptr) + if ((index < m_mngs.size()) && m_mngs[index].m_mng_file) { + mng_info_t &mng_info = m_mngs[index]; + // loop until we hit the right time while (mng_info.m_mng_next_frame_time <= curtime) { @@ -1463,7 +1477,7 @@ void video_manager::record_frame() png_error error = mng_capture_frame(*mng_info.m_mng_file, pnginfo, m_snap_bitmap, entries, palette); if (error != PNGERR_NONE) { - g_profiler.stop(); + g_profiler.stop(); // FIXME: double exit if this happens? end_recording_mng(index); break; } diff --git a/src/emu/video.h b/src/emu/video.h index ac8de0064cd..fa9fc6abbe7 100644 --- a/src/emu/video.h +++ b/src/emu/video.h @@ -193,7 +193,7 @@ private: attotime m_mng_next_frame_time; // time of next frame u32 m_mng_frame; // current movie frame number }; - mng_info_t m_mngs[9]; + std::vector m_mngs; // movie recording - AVI class avi_info_t @@ -210,7 +210,7 @@ private: attotime m_avi_next_frame_time; // time of next frame u32 m_avi_frame; // current movie frame number }; - avi_info_t m_avis[9]; + std::vector m_avis; static const bool s_skiptable[FRAMESKIP_LEVELS][FRAMESKIP_LEVELS];