diff options
Diffstat (limited to 'src/emu')
151 files changed, 6979 insertions, 4910 deletions
diff --git a/src/emu/addrmap.cpp b/src/emu/addrmap.cpp index 8a6294e7279..81e91457e71 100644 --- a/src/emu/addrmap.cpp +++ b/src/emu/addrmap.cpp @@ -42,6 +42,9 @@ address_map_entry::address_map_entry(device_t &device, address_map &map, offs_t , m_share(nullptr) , m_region(nullptr) , m_rgnoffs(0) + , m_before_time(device) + , m_before_delay(device) + , m_after_delay(device) , m_rproto8(device) , m_rproto16(device) , m_rproto32(device) diff --git a/src/emu/addrmap.h b/src/emu/addrmap.h index 69e4a9ab8b7..7d350c14afd 100644 --- a/src/emu/addrmap.h +++ b/src/emu/addrmap.h @@ -71,13 +71,6 @@ class address_map_entry { friend class address_map; - template <typename T, typename Ret, typename... Params> - using is_addrmap_method = std::bool_constant<std::is_constructible_v<address_map_constructor, Ret (T::*)(Params...), const char *, T *> >; - - template <typename T, typename Ret, typename... Params> - static std::enable_if_t<is_addrmap_method<T, Ret, Params...>::value, address_map_constructor> make_delegate(Ret (T::*func)(Params...), const char *name, T *obj) - { return address_map_constructor(func, name, obj); } - template <typename T, bool Reqd> static device_t &find_device(const device_finder<T, Reqd> &finder) { const std::pair<device_t &, const char *> target(finder.finder_target()); @@ -212,109 +205,157 @@ public: // view initialization void view(memory_view &mv); + + // wait-states, implicit base -> delegate converter + template <typename T> + address_map_entry &before_time(u64 (T::*ws)(offs_t, u64), const char *name) + { m_before_time = ws_time_delegate(*make_pointer<T>(m_devbase), ws, name); return *this; } + + template <typename T> + address_map_entry &before_delay(u32 (T::*ws)(offs_t), const char *name) + { m_before_delay = ws_delay_delegate(*make_pointer<T>(m_devbase), ws, name); return *this; } + + template <typename T> + address_map_entry &after_delay(u32 (T::*ws)(offs_t), const char *name) + { m_after_delay = ws_delay_delegate(*make_pointer<T>(m_devbase), ws, name); return *this; } + + // wait-states, device tag -> delegate converter + template <typename T> + address_map_entry &before_time(const char *tag, u64 (T::*ws)(offs_t, u64), const char *name) + { m_before_time = ws_time_delegate(m_devbase, tag, ws, name); return *this; } + + template <typename T> + address_map_entry &before_delay(const char *tag, u32 (T::*ws)(offs_t), const char *name) + { m_before_delay = ws_delay_delegate(m_devbase, tag, ws, name); return *this; } + + template <typename T> + address_map_entry &after_delay(const char *tag, u32 (T::*ws)(offs_t), const char *name) + { m_after_delay = ws_delay_delegate(m_devbase, tag, ws, name); return *this; } + + // wait-states, device reference -> delegate converter + template <typename T, typename U> + address_map_entry &before_time(T &obj, u64 (U::*ws)(offs_t, u64), const char *name) + { m_before_time = ws_time_delegate(obj, ws, name); return *this; } + + template <typename T, typename U> + address_map_entry &before_delay(T &obj, u32 (U::*ws)(offs_t), const char *name) + { m_before_delay = ws_delay_delegate(obj, ws, name); return *this; } + + template <typename T, typename U> + address_map_entry &after_delay(T &obj, u32 (U::*ws)(offs_t), const char *name) + { m_after_delay = ws_delay_delegate(obj, ws, name); return *this; } + + // wait-states, lambda -> delegate converter + template <typename T> + address_map_entry &before_time(T &&ws, const char *name) + { m_before_time = ws_time_delegate(m_devbase, std::forward<T>(ws), name); return *this; } + + template <typename T> + address_map_entry &before_delay(T &&ws, const char *name) + { m_before_delay = ws_delay_delegate(m_devbase, std::forward<T>(ws), name); return *this; } + + template <typename T> + address_map_entry &after_delay(T &&ws, const char *name) + { m_after_delay = ws_delay_delegate(m_devbase, std::forward<T>(ws), name); return *this; } + + // implicit base -> delegate converter template <typename T, typename Ret, typename... Params> address_map_entry &r(Ret (T::*read)(Params...), const char *read_name) - { return r(emu::detail::make_delegate(*make_pointer<T>(m_devbase), read, read_name)); } + { return r(emu::rw_delegate(*make_pointer<T>(m_devbase), read, read_name)); } template <typename T, typename Ret, typename... Params> address_map_entry &w(Ret (T::*write)(Params...), const char *write_name) - { return w(emu::detail::make_delegate(*make_pointer<T>(m_devbase), write, write_name)); } + { return w(emu::rw_delegate(*make_pointer<T>(m_devbase), write, write_name)); } template <typename T, typename RetR, typename... ParamsR, typename U, typename RetW, typename... ParamsW> address_map_entry &rw(RetR (T::*read)(ParamsR...), const char *read_name, RetW (U::*write)(ParamsW...), const char *write_name) - { return r(emu::detail::make_delegate(*make_pointer<T>(m_devbase), read, read_name)).w(emu::detail::make_delegate(*make_pointer<U>(m_devbase), write, write_name)); } + { return r(emu::rw_delegate(*make_pointer<T>(m_devbase), read, read_name)).w(emu::rw_delegate(*make_pointer<U>(m_devbase), write, write_name)); } template <typename T, typename Ret, typename... Params> address_map_entry &m(Ret (T::*map)(Params...), const char *map_name) - { return m(&m_devbase, make_delegate(map, map_name, make_pointer<T>(m_devbase))); } + { return m(&m_devbase, address_map_constructor(map, map_name, make_pointer<T>(m_devbase))); } // device tag -> delegate converter template <typename T, typename Ret, typename... Params> address_map_entry &r(const char *tag, Ret (T::*read)(Params...), const char *read_name) - { return r(emu::detail::make_delegate(m_devbase, tag, read, read_name)); } + { return r(emu::rw_delegate(m_devbase, tag, read, read_name)); } template <typename T, typename Ret, typename... Params> address_map_entry &w(const char *tag, Ret (T::*write)(Params...), const char *write_name) - { return w(emu::detail::make_delegate(m_devbase, tag, write, write_name)); } + { return w(emu::rw_delegate(m_devbase, tag, write, write_name)); } template <typename T, typename RetR, typename... ParamsR, typename U, typename RetW, typename... ParamsW> address_map_entry &rw(const char *tag, RetR (T::*read)(ParamsR...), const char *read_name, RetW (U::*write)(ParamsW...), const char *write_name) - { return r(emu::detail::make_delegate(m_devbase, tag, read, read_name)).w(emu::detail::make_delegate(m_devbase, tag, write, write_name)); } + { return r(emu::rw_delegate(m_devbase, tag, read, read_name)).w(emu::rw_delegate(m_devbase, tag, write, write_name)); } template <typename T, typename Ret, typename... Params> address_map_entry &m(const char *tag, Ret (T::*map)(Params...), const char *map_name) - { return m(tag, make_delegate(map, map_name, static_cast<T *>(nullptr))); } + { return m(tag, address_map_constructor(map, map_name, static_cast<T *>(nullptr))); } // device reference -> delegate converter template <typename T, typename U, typename Ret, typename... Params> address_map_entry &r(T &obj, Ret (U::*read)(Params...), const char *read_name) - { return r(emu::detail::make_delegate(*make_pointer<U>(obj), read, read_name)); } + { return r(emu::rw_delegate(*make_pointer<U>(obj), read, read_name)); } template <typename T, typename U, typename Ret, typename... Params> address_map_entry &w(T &obj, Ret (U::*write)(Params...), const char *write_name) - { return w(emu::detail::make_delegate(*make_pointer<U>(obj), write, write_name)); } + { return w(emu::rw_delegate(*make_pointer<U>(obj), write, write_name)); } template <typename T, typename U, typename RetR, typename... ParamsR, typename V, typename RetW, typename... ParamsW> address_map_entry &rw(T &obj, RetR (U::*read)(ParamsR...), const char *read_name, RetW (V::*write)(ParamsW...), const char *write_name) - { return r(emu::detail::make_delegate(*make_pointer<U>(obj), read, read_name)).w(emu::detail::make_delegate(make_pointer<V>(obj), write, write_name)); } + { return r(emu::rw_delegate(*make_pointer<U>(obj), read, read_name)).w(emu::rw_delegate(make_pointer<V>(obj), write, write_name)); } template <typename T, typename U, typename Ret, typename... Params> address_map_entry &m(T &obj, Ret (U::*map)(Params...), const char *map_name) - { return m(make_pointer<device_t>(obj), make_delegate(map, map_name, make_pointer<U>(obj))); } + { return m(make_pointer<device_t>(obj), address_map_constructor(map, map_name, make_pointer<U>(obj))); } // device finder -> delegate converter template <typename T, bool Reqd, typename U, typename Ret, typename... Params> address_map_entry &r(device_finder<T, Reqd> &finder, Ret (U::*read)(Params...), const char *read_name) { - device_t &device(find_device(finder)); - return r(emu::detail::make_delegate(device, DEVICE_SELF, read, read_name)); + return r(emu::rw_delegate(finder, read, read_name)); } template <typename T, bool Reqd, typename U, typename Ret, typename... Params> address_map_entry &r(const device_finder<T, Reqd> &finder, Ret (U::*read)(Params...), const char *read_name) { - device_t &device(find_device(finder)); - return r(emu::detail::make_delegate(device, DEVICE_SELF, read, read_name)); + return r(emu::rw_delegate(finder, read, read_name)); } template <typename T, bool Reqd, typename U, typename Ret, typename... Params> address_map_entry &w(device_finder<T, Reqd> &finder, Ret (U::*write)(Params...), const char *write_name) { - device_t &device(find_device(finder)); - return w(emu::detail::make_delegate(device, DEVICE_SELF, write, write_name)); + return w(emu::rw_delegate(finder, write, write_name)); } template <typename T, bool Reqd, typename U, typename Ret, typename... Params> address_map_entry &w(const device_finder<T, Reqd> &finder, Ret (U::*write)(Params...), const char *write_name) { - device_t &device(find_device(finder)); - return w(emu::detail::make_delegate(device, DEVICE_SELF, write, write_name)); + return w(emu::rw_delegate(finder, write, write_name)); } template <typename T, bool Reqd, typename U, typename RetR, typename... ParamsR, typename V, typename RetW, typename... ParamsW> address_map_entry &rw(device_finder<T, Reqd> &finder, RetR (U::*read)(ParamsR...), const char *read_name, RetW (V::*write)(ParamsW...), const char *write_name) { - device_t &device(find_device(finder)); - return r(emu::detail::make_delegate(device, DEVICE_SELF, read, read_name)) - .w(emu::detail::make_delegate(device, DEVICE_SELF, write, write_name)); + return r(emu::rw_delegate(finder, read, read_name)) + .w(emu::rw_delegate(finder, write, write_name)); } template <typename T, bool Reqd, typename U, typename RetR, typename... ParamsR, typename V, typename RetW, typename... ParamsW> address_map_entry &rw(const device_finder<T, Reqd> &finder, RetR (U::*read)(ParamsR...), const char *read_name, RetW (V::*write)(ParamsW...), const char *write_name) { - device_t &device(find_device(finder)); - return r(emu::detail::make_delegate(device, DEVICE_SELF, read, read_name)) - .w(emu::detail::make_delegate(device, DEVICE_SELF, write, write_name)); + return r(emu::rw_delegate(finder, read, read_name)) + .w(emu::rw_delegate(finder, write, write_name)); } template <typename T, bool Reqd, typename U, typename Ret, typename... Params> address_map_entry &m(device_finder<T, Reqd> &finder, Ret (U::*map)(Params...), const char *map_name) { device_t &device(find_device(finder)); - return m(&device, make_delegate(map, map_name, make_pointer<U>(device))); + return m(&device, address_map_constructor(map, map_name, make_pointer<U>(device))); } template <typename T, bool Reqd, typename U, typename Ret, typename... Params> address_map_entry &m(const device_finder<T, Reqd> &finder, Ret (U::*map)(Params...), const char *map_name) { device_t &device(find_device(finder)); - return m(&device, make_delegate(map, map_name, make_pointer<U>(device))); + return m(&device, address_map_constructor(map, map_name, make_pointer<U>(device))); } @@ -374,6 +415,9 @@ public: const char * m_share; // tag of a shared memory block const char * m_region; // tag of region containing the memory backing this entry offs_t m_rgnoffs; // offset within the region + ws_time_delegate m_before_time; // before-time wait-state + ws_delay_delegate m_before_delay; // before-delay wait-state + ws_delay_delegate m_after_delay; // after-delay wait-state // handlers read8_delegate m_rproto8; // 8-bit read proto-delegate diff --git a/src/emu/attotime.cpp b/src/emu/attotime.cpp index a1ba4d9ed61..030c3193551 100644 --- a/src/emu/attotime.cpp +++ b/src/emu/attotime.cpp @@ -119,11 +119,11 @@ const char *attotime::as_string(int precision) const // special case: never if (*this == never) - sprintf(buffer, "%-*s", precision, "(never)"); + snprintf(buffer, 30, "%-*s", precision, "(never)"); // case 1: we want no precision; seconds only else if (precision == 0) - sprintf(buffer, "%d", m_seconds); + snprintf(buffer, 30, "%d", m_seconds); // case 2: we want 9 or fewer digits of precision else if (precision <= 9) @@ -135,7 +135,7 @@ const char *attotime::as_string(int precision) const upper /= 10; temp++; } - sprintf(buffer, "%d.%0*d", m_seconds, precision, upper); + snprintf(buffer, 30, "%d.%0*d", m_seconds, precision, upper); } // case 3: more than 9 digits of precision @@ -149,7 +149,7 @@ const char *attotime::as_string(int precision) const lower /= 10; temp++; } - sprintf(buffer, "%d.%09d%0*d", m_seconds, upper, precision - 9, lower); + snprintf(buffer, 30, "%d.%09d%0*d", m_seconds, upper, precision - 9, lower); } return buffer; } diff --git a/src/emu/attotime.h b/src/emu/attotime.h index 2b625459386..39fcf6e5310 100644 --- a/src/emu/attotime.h +++ b/src/emu/attotime.h @@ -38,9 +38,10 @@ #include "emucore.h" #include "xtal.h" +#include "eminline.h" + #include <cmath> -#undef min -#undef max + //************************************************************************** // CONSTANTS diff --git a/src/emu/config.cpp b/src/emu/config.cpp index a7d1218abe0..8e9423415ee 100644 --- a/src/emu/config.cpp +++ b/src/emu/config.cpp @@ -307,16 +307,21 @@ bool configuration_manager::save_xml(emu_file &file, config_type which_type) systemnode->set_attribute("name", (which_type == config_type::DEFAULT) ? "default" : machine().system().name); // loop over all registrants and call their save function + util::xml::data_node *curnode = nullptr; for (auto const &type : m_typelist) { - util::xml::data_node *const curnode = systemnode->add_child(type.first.c_str(), nullptr); + if (!curnode || (type.first != curnode->get_name())) + curnode = systemnode->add_child(type.first.c_str(), nullptr); if (!curnode) return false; type.second.save(which_type, curnode); // if nothing was added, just nuke the node if (!curnode->get_value() && !curnode->get_first_child() && !curnode->count_attributes()) + { curnode->delete_node(); + curnode = nullptr; + } } // restore unhandled settings diff --git a/src/emu/debug/debugbuf.cpp b/src/emu/debug/debugbuf.cpp index 93bfcba891b..616567b398e 100644 --- a/src/emu/debug/debugbuf.cpp +++ b/src/emu/debug/debugbuf.cpp @@ -82,6 +82,8 @@ void debug_disasm_buffer::debug_data_buffer::fill(offs_t lstart, offs_t size) co } } + // FIXME: This buffer tends to hog more memory than necessary for typical disassembly tasks. + // If the PC values supplied are far enough apart, the buffer may suddenly increase in size to a gigabyte or more. if(m_buffer.empty()) { m_lstart = lstart; m_lend = lend; @@ -209,8 +211,9 @@ void debug_disasm_buffer::debug_data_buffer::setup_methods() u16 *dest = get_ptr<u16>(lstart); for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask) { offs_t tpc = m_intf.pc_linear_to_real(lpc); - if (m_space->device().memory().translate(m_space->spacenum(), TRANSLATE_FETCH_DEBUG, tpc)) - *dest++ = m_space->read_word(tpc); + address_space *space; + if (m_space->device().memory().translate(m_space->spacenum(), device_memory_interface::TR_FETCH, tpc, space)) + *dest++ = space->read_word(tpc); else *dest++ = 0; } @@ -222,8 +225,9 @@ void debug_disasm_buffer::debug_data_buffer::setup_methods() u8 *dest = get_ptr<u8>(lstart); for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask) { offs_t tpc = m_intf.pc_linear_to_real(lpc); - if (m_space->device().memory().translate(m_space->spacenum(), TRANSLATE_FETCH_DEBUG, tpc)) - *dest++ = m_space->read_byte(tpc); + address_space *space; + if (m_space->device().memory().translate(m_space->spacenum(), device_memory_interface::TR_FETCH, tpc, space)) + *dest++ = space->read_byte(tpc); else *dest++ = 0; } @@ -239,8 +243,9 @@ void debug_disasm_buffer::debug_data_buffer::setup_methods() u64 *dest = get_ptr<u64>(lstart); for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask) { offs_t tpc = lpc; - if (m_space->device().memory().translate(m_space->spacenum(), TRANSLATE_FETCH_DEBUG, tpc)) - *dest++ = m_space->read_qword(tpc); + address_space *space; + if (m_space->device().memory().translate(m_space->spacenum(), device_memory_interface::TR_FETCH, tpc, space)) + *dest++ = space->read_qword(tpc); else *dest++ = 0; } @@ -253,8 +258,9 @@ void debug_disasm_buffer::debug_data_buffer::setup_methods() u32 *dest = get_ptr<u32>(lstart); for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask) { offs_t tpc = lpc; - if (m_space->device().memory().translate(m_space->spacenum(), TRANSLATE_FETCH_DEBUG, tpc)) - *dest++ = m_space->read_dword(tpc); + address_space *space; + if (m_space->device().memory().translate(m_space->spacenum(), device_memory_interface::TR_FETCH, tpc, space)) + *dest++ = space->read_dword(tpc); else *dest++ = 0; } @@ -267,8 +273,9 @@ void debug_disasm_buffer::debug_data_buffer::setup_methods() u16 *dest = get_ptr<u16>(lstart); for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask) { offs_t tpc = lpc; - if (m_space->device().memory().translate(m_space->spacenum(), TRANSLATE_FETCH_DEBUG, tpc)) - *dest++ = m_space->read_word(tpc); + address_space *space; + if (m_space->device().memory().translate(m_space->spacenum(), device_memory_interface::TR_FETCH, tpc, space)) + *dest++ = space->read_word(tpc); else *dest++ = 0; } @@ -281,8 +288,9 @@ void debug_disasm_buffer::debug_data_buffer::setup_methods() u8 *dest = get_ptr<u8>(lstart); for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 1) & m_pc_mask) { offs_t tpc = lpc; - if (m_space->device().memory().translate(m_space->spacenum(), TRANSLATE_FETCH_DEBUG, tpc)) - *dest++ = m_space->read_byte(tpc); + address_space *space; + if (m_space->device().memory().translate(m_space->spacenum(), device_memory_interface::TR_FETCH, tpc, space)) + *dest++ = space->read_byte(tpc); else *dest++ = 0; } @@ -295,8 +303,9 @@ void debug_disasm_buffer::debug_data_buffer::setup_methods() u16 *dest = reinterpret_cast<u16 *>(&m_buffer[0]) + ((lstart - m_lstart) >> 4); for(offs_t lpc = lstart; lpc != lend; lpc = (lpc + 0x10) & m_pc_mask) { offs_t tpc = lpc; - if (m_space->device().memory().translate(m_space->spacenum(), TRANSLATE_FETCH_DEBUG, tpc)) - *dest++ = m_space->read_word(tpc); + address_space *space; + if (m_space->device().memory().translate(m_space->spacenum(), device_memory_interface::TR_FETCH, tpc, space)) + *dest++ = space->read_word(tpc); else *dest++ = 0; } @@ -1388,7 +1397,7 @@ debug_disasm_buffer::debug_disasm_buffer(device_t &device) : // pc to string conversion int aw = pspace.logaddr_width(); bool is_octal = pspace.is_octal(); - if((m_flags & util::disasm_interface::PAGED2LEVEL) == util::disasm_interface::PAGED2LEVEL) { + if((m_flags & util::disasm_interface::PAGED2LEVEL) == util::disasm_interface::PAGED2LEVEL && aw > (m_dintf.page_address_bits() + m_dintf.page2_address_bits())) { int bits1 = m_dintf.page_address_bits(); int bits2 = m_dintf.page2_address_bits(); int bits3 = aw - bits1 - bits2; @@ -1419,7 +1428,7 @@ debug_disasm_buffer::debug_disasm_buffer(device_t &device) : }; } - } else if(m_flags & util::disasm_interface::PAGED) { + } else if((m_flags & util::disasm_interface::PAGED) && aw > m_dintf.page_address_bits()) { int bits1 = m_dintf.page_address_bits(); int bits2 = aw - bits1; offs_t sm1 = (1 << bits1) - 1; diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index 1e14db5b6df..ad463ace500 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -36,35 +36,6 @@ -namespace { - -template <typename T> -inline std::string_view::size_type find_delimiter(std::string_view str, T &&is_delim) -{ - unsigned parens = 0; - for (std::string_view::size_type i = 0; str.length() > i; ++i) - { - if (str[i] == '(') - { - ++parens; - } - else if (parens) - { - if (str[i] == ')') - --parens; - } - else if (is_delim(str[i])) - { - return i; - } - } - return std::string_view::npos; -} - -} // anonymous namespace - - - /*************************************************************************** CONSTANTS ***************************************************************************/ @@ -82,7 +53,8 @@ const size_t debugger_commands::MAX_GLOBALS = 1000; bool debugger_commands::cheat_address_is_valid(address_space &space, offs_t address) { - return space.device().memory().translate(space.spacenum(), TRANSLATE_READ, address) && (space.get_write_ptr(address) != nullptr); + address_space *tspace; + return space.device().memory().translate(space.spacenum(), device_memory_interface::TR_READ, address, tspace) && (tspace->get_write_ptr(address) != nullptr); } @@ -133,14 +105,15 @@ u64 debugger_commands::cheat_system::read_extended(offs_t address) const { address &= space->logaddrmask(); u64 value = space->unmap(); - if (space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, address)) + address_space *tspace; + if (space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, address, tspace)) { switch (width) { - case 1: value = space->read_byte(address); break; - case 2: value = space->read_word_unaligned(address); break; - case 4: value = space->read_dword_unaligned(address); break; - case 8: value = space->read_qword_unaligned(address); break; + case 1: value = tspace->read_byte(address); break; + case 2: value = tspace->read_word_unaligned(address); break; + case 4: value = tspace->read_dword_unaligned(address); break; + case 8: value = tspace->read_qword_unaligned(address); break; } } return sign_extend(byte_swap(value)); @@ -197,7 +170,7 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu if ((valcount == 1) && (blockcount == 1) && strstr(name, "/globals/")) { char symname[100]; - sprintf(symname, ".%s", strrchr(name, '/') + 1); + snprintf(symname, 100, ".%s", strrchr(name, '/') + 1); m_global_array[itemnum].base = base; m_global_array[itemnum].size = valsize; symtable.add( @@ -456,466 +429,9 @@ void debugger_commands::global_set(global_entry *global, u64 value) -/*************************************************************************** - PARAMETER VALIDATION HELPERS -***************************************************************************/ - -/// \brief Validate parameter as a Boolean value -/// -/// Validates a parameter as a Boolean value. Fixed strings and -/// expressions evaluating to numeric values are recognised. The result -/// is unchanged for an empty string. -/// \param [in] param The parameter string. -/// \param [in,out] result The default value on entry, and the value of -/// the parameter interpreted as a Boolean on success. Unchanged if -/// the parameter is an empty string. -/// \return true if the parameter is a valid Boolean value or an empty -/// string, or false otherwise. -bool debugger_commands::validate_boolean_parameter(std::string_view param, bool &result) -{ - // nullptr parameter does nothing and returns no error - if (param.empty()) - return true; - - // evaluate the expression; success if no error - using namespace std::literals; - bool const is_true = util::streqlower(param, "true"sv); - bool const is_false = util::streqlower(param, "false"sv); - - if (is_true || is_false) - { - result = is_true; - return true; - } - - // try to evaluate as a number - u64 val; - if (!validate_number_parameter(param, val)) - return false; - - result = val != 0; - return true; -} - - -/// \brief Validate parameter as a numeric value -/// -/// Parses the parameter as an expression and evaluates it as a number. -/// \param [in] param The parameter string. -/// \param [out] result The numeric value of the expression on success. -/// Unchanged on failure. -/// \return true if the parameter is a valid expression that evaluates -/// to a numeric value, or false otherwise. -bool debugger_commands::validate_number_parameter(std::string_view param, u64 &result) -{ - // evaluate the expression; success if no error - try - { - result = parsed_expression(m_console.visible_symtable(), param).execute(); - return true; - } - catch (expression_error const &error) - { - // print an error pointing to the character that caused it - m_console.printf("Error in expression: %s\n", param); - m_console.printf(" %*s^", error.offset(), ""); - m_console.printf("%s\n", error.code_string()); - return false; - } -} - - -/// \brief Validate parameter as a device -/// -/// Validates a parameter as a device identifier and retrieves the -/// device on success. A string corresponding to the tag of a device -/// refers to that device; an empty string refers to the current CPU -/// with debugger focus; any other string is parsed as an expression -/// and treated as an index of a device implementing -/// #device_execute_interface and #device_state_interface, and exposing -/// a generic PC base value. -/// \param [in] param The parameter string. -/// \param [out] result A pointer to the device on success, or unchanged -/// on failure. -/// \return true if the parameter refers to a device in the current -/// system, or false otherwise. -bool debugger_commands::validate_device_parameter(std::string_view param, device_t *&result) -{ - // if no parameter, use the visible CPU - if (param.empty()) - { - device_t *const current = m_console.get_visible_cpu(); - if (current) - { - result = current; - return true; - } - else - { - m_console.printf("No valid CPU is currently selected\n"); - return false; - } - } - - // next look for a tag match - std::string_view relative = param; - device_t &base = get_device_search_base(relative); - device_t *device = base.subdevice(strmakelower(relative)); - if (device) - { - result = device; - return true; - } - - // then evaluate as an expression; on an error assume it was a tag - u64 cpunum; - try - { - cpunum = parsed_expression(m_console.visible_symtable(), param).execute(); - } - catch (expression_error &) - { - m_console.printf("Unable to find device '%s'\n", param); - return false; - } - - // attempt to find by numerical index - device = get_cpu_by_index(cpunum); - if (device) - { - result = device; - return true; - } - else - { - // if out of range, complain - m_console.printf("Invalid CPU index %u\n", cpunum); - return false; - } -} - - -/// \brief Validate a parameter as a CPU -/// -/// Validates a parameter as a CPU identifier. Uses the same rules as -/// #validate_device_parameter to identify devices, but additionally -/// checks that the device is a "CPU" for the debugger's purposes. -/// \param [in] The parameter string. -/// \param [out] result The device on success, or unchanged on failure. -/// \return true if the parameter refers to a CPU-like device in the -/// current system, or false otherwise. -bool debugger_commands::validate_cpu_parameter(std::string_view param, device_t *&result) -{ - // first do the standard device thing - device_t *device; - if (!validate_device_parameter(param, device)) - return false; - - // check that it's a "CPU" for the debugger's purposes - device_execute_interface const *execute; - if (device->interface(execute)) - { - result = device; - return true; - } - - m_console.printf("Device %s is not a CPU\n", device->name()); - return false; -} - - -/// \brief Validate a parameter as an address space identifier -/// -/// Validates a parameter as an address space identifier. Uses the same -/// rules as #validate_device_parameter to identify devices. If the -/// default address space number is negative, the first address space -/// exposed by the device will be used as the default. -/// \param [in] The parameter string. -/// \param [in] spacenum The default address space index. If negative, -/// the first address space exposed by the device (i.e. the address -/// space with the lowest index) will be used as the default. -/// \param [out] result The address space on success, or unchanged on -/// failure. -/// \return true if the parameter refers to an address space in the -/// current system, or false otherwise. -bool debugger_commands::validate_device_space_parameter(std::string_view param, int spacenum, address_space *&result) -{ - device_t *device; - std::string spacename; - if (param.empty()) - { - // if no parameter, use the visible CPU - device = m_console.get_visible_cpu(); - if (!device) - { - m_console.printf("No valid CPU is currently selected\n"); - return false; - } - } - else - { - // look for a tag match on the whole parameter value - std::string_view relative = param; - device_t &base = get_device_search_base(relative); - device = base.subdevice(strmakelower(relative)); - - // if that failed, treat the last component as an address space - if (!device) - { - auto const delimiter = relative.find_last_of(":^"); - bool const found = std::string_view::npos != delimiter; - if (!found || (':' == relative[delimiter])) - { - spacename = strmakelower(relative.substr(found ? (delimiter + 1) : 0)); - relative = relative.substr(0, !found ? 0 : !delimiter ? 1 : delimiter); - if (!relative.empty()) - device = base.subdevice(strmakelower(relative)); - else if (m_console.get_visible_cpu()) - device = m_console.get_visible_cpu(); - else - device = &m_machine.root_device(); - } - } - } - - // if still no device found, evaluate as an expression - if (!device) - { - u64 cpunum; - try - { - cpunum = parsed_expression(m_console.visible_symtable(), param).execute(); - } - catch (expression_error const &) - { - // parsing failed - assume it was a tag - m_console.printf("Unable to find device '%s'\n", param); - return false; - } - - // attempt to find by numerical index - device = get_cpu_by_index(cpunum); - if (!device) - { - // if out of range, complain - m_console.printf("Invalid CPU index %u\n", cpunum); - return false; - } - } - - // ensure the device implements the memory interface - device_memory_interface *memory; - if (!device->interface(memory)) - { - m_console.printf("No memory interface found for device %s\n", device->name()); - return false; - } - - // fall back to supplied default space if appropriate - if (spacename.empty() && (0 <= spacenum)) - { - if (memory->has_space(spacenum)) - { - result = &memory->space(spacenum); - return true; - } - else - { - m_console.printf("No matching memory space found for device '%s'\n", device->tag()); - return false; - } - } - - // otherwise find the specified space or fall back to the first populated space - for (int i = 0; memory->max_space_count() > i; ++i) - { - if (memory->has_space(i) && (spacename.empty() || (memory->space(i).name() == spacename))) - { - result = &memory->space(i); - return true; - } - } - - // report appropriate error message - if (spacename.empty()) - m_console.printf("No memory spaces found for device '%s'\n", device->tag()); - else - m_console.printf("Memory space '%s' not found found for device '%s'\n", spacename, device->tag()); - return false; -} - - -/// \brief Validate a parameter as a target address -/// -/// Validates a parameter as an numeric expression to use as an address -/// optionally followed by a colon and a device identifier. If the -/// device identifier is not presnt, the current CPU with debugger focus -/// is assumed. See #validate_device_parameter for information on how -/// device parametersare interpreted. -/// \param [in] The parameter string. -/// \param [in] spacenum The default address space index. If negative, -/// the first address space exposed by the device (i.e. the address -/// space with the lowest index) will be used as the default. -/// \param [out] space The address space on success, or unchanged on -/// failure. -/// \param [out] addr The address on success, or unchanged on failure. -/// \return true if the address is a valid expression evaluating to a -/// number and the address space is found, or false otherwise. -bool debugger_commands::validate_target_address_parameter(std::string_view param, int spacenum, address_space *&space, u64 &addr) -{ - // check for the device delimiter - std::string_view::size_type const devdelim = find_delimiter(param, [] (char ch) { return ':' == ch; }); - std::string_view device; - if (devdelim != std::string::npos) - device = param.substr(devdelim + 1); - - // parse the address first - u64 addrval; - if (!validate_number_parameter(param.substr(0, devdelim), addrval)) - return false; - - // find the address space - if (!validate_device_space_parameter(device, spacenum, space)) - return false; - - // set the address now that we have the space - addr = addrval; - return true; -} - - -/// \brief Validate a parameter as a memory region -/// -/// Validates a parameter as a memory region tag and retrieves the -/// specified memory region. -/// \param [in] The parameter string. -/// \param [out] result The memory region on success, or unchanged on -/// failure. -/// \return true if the parameter refers to a memory region in the -/// current system, or false otherwise. -bool debugger_commands::validate_memory_region_parameter(std::string_view param, memory_region *&result) -{ - auto const ®ions = m_machine.memory().regions(); - std::string_view relative = param; - device_t &base = get_device_search_base(relative); - auto const iter = regions.find(base.subtag(strmakelower(relative))); - if (regions.end() != iter) - { - result = iter->second.get(); - return true; - } - else - { - m_console.printf("No matching memory region found for '%s'\n", param); - return false; - } -} - - -/// \brief Get search base for device or address space parameter -/// -/// Handles prefix prefixes used to indicate that a device tag should be -/// interpreted relative to the selected CPU. Removes the recognised -/// prefixes from the parameter value. -/// \param [in,out] param The parameter string. Recognised prefixes -/// affecting the search base are removed, leaving a tag relative to -/// the base device. -/// \return A reference to the base device that the tag should be -/// interpreted relative to. -device_t &debugger_commands::get_device_search_base(std::string_view ¶m) -{ - if (!param.empty()) - { - // handle ".:" or ".^" prefix for tag relative to current CPU if any - if (('.' == param[0]) && ((param.size() == 1) || (':' == param[1]) || ('^' == param[1]))) - { - param.remove_prefix(((param.size() > 1) && (':' == param[1])) ? 2 : 1); - device_t *const current = m_console.get_visible_cpu(); - return current ? *current : m_machine.root_device(); - } - - // a sibling path makes most sense relative to current CPU - if ('^' == param[0]) - { - device_t *const current = m_console.get_visible_cpu(); - return current ? *current : m_machine.root_device(); - } - } - - - // default to root device - return m_machine.root_device(); -} - - -/// \brief Get CPU by index -/// -/// Looks up a CPU by the number the debugger assigns it based on its -/// position in the device tree relative to other CPUs. -/// \param [in] cpunum Zero-based index of the CPU to find. -/// \return A pointer to the CPU if found, or \c nullptr if no CPU has -/// the specified index. -device_t *debugger_commands::get_cpu_by_index(u64 cpunum) -{ - unsigned index = 0; - for (device_execute_interface &exec : execute_interface_enumerator(m_machine.root_device())) - { - // real CPUs should have pcbase - device_state_interface const *state; - if (exec.device().interface(state) && state->state_find_entry(STATE_GENPCBASE)) - { - if (index++ == cpunum) - { - return &exec.device(); - } - } - } - return nullptr; -} - - -/*------------------------------------------------- - debug_command_parameter_expression - validates - an expression parameter --------------------------------------------------*/ - -bool debugger_commands::debug_command_parameter_expression(std::string_view param, parsed_expression &result) -{ - try - { - // parse the expression; success if no error - result.parse(param); - return true; - } - catch (expression_error const &err) - { - // output an error - m_console.printf("Error in expression: %s\n", param); - m_console.printf(" %*s^", err.offset(), ""); - m_console.printf("%s\n", err.code_string()); - return false; - } -} - - -/*------------------------------------------------- - debug_command_parameter_command - validates a - command parameter --------------------------------------------------*/ - -bool debugger_commands::debug_command_parameter_command(std::string_view param) -{ - /* validate the comment; success if no error */ - CMDERR err = m_console.validate_command(param); - if (err.error_class() == CMDERR::NONE) - return true; - - /* output an error */ - m_console.printf("Error in command: %s\n", param); - m_console.printf(" %*s^", err.error_offset(), ""); - m_console.printf("%s\n", debugger_console::cmderr_to_string(err)); - return 0; -} +//************************************************************************** +// COMMAND IMPLEMENTATIONS +//************************************************************************** /*------------------------------------------------- execute_help - execute the help command @@ -939,7 +455,7 @@ void debugger_commands::execute_print(const std::vector<std::string_view> ¶m /* validate the other parameters */ u64 values[MAX_COMMAND_PARAMS]; for (int i = 0; i < params.size(); i++) - if (!validate_number_parameter(params[i], values[i])) + if (!m_console.validate_number_parameter(params[i], values[i])) return; /* then print each one */ @@ -953,10 +469,14 @@ void debugger_commands::execute_print(const std::vector<std::string_view> ¶m mini_printf - safe printf to a buffer -------------------------------------------------*/ -bool debugger_commands::mini_printf(std::ostream &stream, std::string_view format, int params, u64 *param) +bool debugger_commands::mini_printf(std::ostream &stream, const std::vector<std::string_view> ¶ms) { + std::string_view const format(params[0]); auto f = format.begin(); + int param = 1; + u64 number; + // parse the string looking for % signs while (f != format.end()) { @@ -979,21 +499,48 @@ bool debugger_commands::mini_printf(std::ostream &stream, std::string_view forma // formatting else if (c == '%') { + bool left_justify = false; + bool zero_fill = false; int width = 0; - int zerofill = 0; + int precision = 0; - // parse out the width - while (f != format.end() && *f >= '0' && *f <= '9') + // parse optional left justification flag + if (f != format.end() && *f == '-') { - c = *f++; - if (c == '0' && width == 0) - zerofill = 1; - width = width * 10 + (c - '0'); + left_justify = true; + f++; + } + + // parse optional zero fill flag + if (f != format.end() && *f == '0') + { + zero_fill = true; + f++; + } + + // parse optional width + while (f != format.end() && isdigit(*f)) + width = width * 10 + (*f++ - '0'); + if (f == format.end()) + break; + + // apply left justification + if (left_justify) + width = -width; + + if ((c = *f++) == '.') + { + // parse optional precision + while (f != format.end() && isdigit(*f)) + precision = precision * 10 + (*f++ - '0'); + + // get the format + if (f != format.end()) + c = *f++; + else + break; } - if (f == format.end()) break; - // get the format - c = *f++; switch (c) { case '%': @@ -1001,70 +548,89 @@ bool debugger_commands::mini_printf(std::ostream &stream, std::string_view forma break; case 'X': + if (param < params.size() && m_console.validate_number_parameter(params[param++], number)) + util::stream_format(stream, zero_fill ? "%0*X" : "%*X", width, number); + else + { + m_console.printf("Not enough parameters for format!\n"); + return false; + } + break; case 'x': - if (params == 0) + if (param < params.size() && m_console.validate_number_parameter(params[param++], number)) + util::stream_format(stream, zero_fill ? "%0*x" : "%*x", width, number); + else { m_console.printf("Not enough parameters for format!\n"); return false; } - if (u32(*param >> 32) != 0) - util::stream_format(stream, zerofill ? "%0*X" : "%*X", (width <= 8) ? 1 : width - 8, u32(*param >> 32)); - else if (width > 8) - util::stream_format(stream, zerofill ? "%0*X" : "%*X", width - 8, 0); - util::stream_format(stream, zerofill ? "%0*X" : "%*X", (width < 8) ? width : 8, u32(*param)); - param++; - params--; break; case 'O': case 'o': - if (params == 0) + if (param < params.size() && m_console.validate_number_parameter(params[param++], number)) + util::stream_format(stream, zero_fill ? "%0*o" : "%*o", width, number); + else { m_console.printf("Not enough parameters for format!\n"); return false; } - if (u32(*param >> 60) != 0) - { - util::stream_format(stream, zerofill ? "%0*o" : "%*o", (width <= 20) ? 1 : width - 20, u32(*param >> 60)); - util::stream_format(stream, "%0*o", 10, u32(BIT(*param, 30, 30))); - } - else - { - if (width > 20) - util::stream_format(stream, zerofill ? "%0*o" : "%*o", width - 20, 0); - if (u32(BIT(*param, 30, 30)) != 0) - util::stream_format(stream, zerofill ? "%0*o" : "%*o", (width <= 10) ? 1 : width - 10, u32(BIT(*param, 30, 30))); - else if (width > 10) - util::stream_format(stream, zerofill ? "%0*o" : "%*o", width - 10, 0); - } - util::stream_format(stream, zerofill ? "%0*o" : "%*o", (width < 10) ? width : 10, u32(BIT(*param, 0, 30))); - param++; - params--; break; case 'D': case 'd': - if (params == 0) + if (param < params.size() && m_console.validate_number_parameter(params[param++], number)) + util::stream_format(stream, zero_fill ? "%0*d" : "%*d", width, number); + else { m_console.printf("Not enough parameters for format!\n"); return false; } - util::stream_format(stream, zerofill ? "%0*d" : "%*d", width, u32(*param)); - param++; - params--; break; + case 'C': case 'c': - if (params == 0) + if (param < params.size() && m_console.validate_number_parameter(params[param++], number)) + stream << char(number); + else { m_console.printf("Not enough parameters for format!\n"); return false; } - stream << char(*param); - param++; - params--; break; + case 's': + { + address_space *space; + if (param < params.size() && m_console.validate_target_address_parameter(params[param++], -1, space, number)) + { + address_space *tspace; + std::string s; + + for (u32 address = u32(number), taddress; space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, taddress = address, tspace); address++) + { + u8 const data = tspace->read_byte(taddress); + + if (!data) + break; + + s += data; + + if (precision == 1) + break; + else if (precision) + precision--; + } + + util::stream_format(stream, "%*s", width, s); + } + else + { + m_console.printf("Not enough parameters for format!\n"); + return false; + } + } + break; } } @@ -1088,7 +654,7 @@ void debugger_commands::execute_index_command(std::vector<std::string_view> cons std::vector<u64> index(params.size()); for (int paramnum = 0; paramnum < params.size(); paramnum++) { - if (!validate_number_parameter(params[paramnum], index[paramnum])) + if (!m_console.validate_number_parameter(params[paramnum], index[paramnum])) return; } @@ -1114,15 +680,9 @@ void debugger_commands::execute_index_command(std::vector<std::string_view> cons void debugger_commands::execute_printf(const std::vector<std::string_view> ¶ms) { - /* validate the other parameters */ - u64 values[MAX_COMMAND_PARAMS]; - for (int i = 1; i < params.size(); i++) - if (!validate_number_parameter(params[i], values[i])) - return; - /* then do a printf */ std::ostringstream buffer; - if (mini_printf(buffer, params[0], params.size() - 1, &values[1])) + if (mini_printf(buffer, params)) m_console.printf("%s\n", std::move(buffer).str()); } @@ -1133,15 +693,9 @@ void debugger_commands::execute_printf(const std::vector<std::string_view> ¶ void debugger_commands::execute_logerror(const std::vector<std::string_view> ¶ms) { - /* validate the other parameters */ - u64 values[MAX_COMMAND_PARAMS]; - for (int i = 1; i < params.size(); i++) - if (!validate_number_parameter(params[i], values[i])) - return; - /* then do a printf */ std::ostringstream buffer; - if (mini_printf(buffer, params[0], params.size() - 1, &values[1])) + if (mini_printf(buffer, params)) m_machine.logerror("%s", std::move(buffer).str()); } @@ -1152,15 +706,9 @@ void debugger_commands::execute_logerror(const std::vector<std::string_view> &pa void debugger_commands::execute_tracelog(const std::vector<std::string_view> ¶ms) { - /* validate the other parameters */ - u64 values[MAX_COMMAND_PARAMS]; - for (int i = 1; i < params.size(); i++) - if (!validate_number_parameter(params[i], values[i])) - return; - /* then do a printf */ std::ostringstream buffer; - if (mini_printf(buffer, params[0], params.size() - 1, &values[1])) + if (mini_printf(buffer, params)) m_console.get_visible_cpu()->debug()->trace_printf("%s", std::move(buffer).str()); } @@ -1173,7 +721,6 @@ void debugger_commands::execute_tracesym(const std::vector<std::string_view> &pa { // build a format string appropriate for the parameters and validate them std::stringstream format; - u64 values[MAX_COMMAND_PARAMS]; for (int i = 0; i < params.size(); i++) { // find this symbol @@ -1188,15 +735,15 @@ void debugger_commands::execute_tracesym(const std::vector<std::string_view> &pa util::stream_format(format, "%s=%s ", params[i], sym->format().empty() ? "%16X" : sym->format()); - - // validate the parameter - if (!validate_number_parameter(params[i], values[i])) - return; } + // build parameters for printf + std::vector<std::string_view> printf_params(params); + printf_params.insert(printf_params.begin(), format.str()); + // then do a printf std::ostringstream buffer; - if (mini_printf(buffer, format.str(), params.size(), values)) + if (mini_printf(buffer, printf_params)) m_console.get_visible_cpu()->debug()->trace_printf("%s", std::move(buffer).str()); } @@ -1229,7 +776,7 @@ void debugger_commands::execute_quit(const std::vector<std::string_view> ¶ms void debugger_commands::execute_do(const std::vector<std::string_view> ¶ms) { u64 dummy; - validate_number_parameter(params[0], dummy); + m_console.validate_number_parameter(params[0], dummy); } @@ -1241,7 +788,7 @@ void debugger_commands::execute_step(const std::vector<std::string_view> ¶ms { /* if we have a parameter, use it */ u64 steps = 1; - if (params.size() > 0 && !validate_number_parameter(params[0], steps)) + if (params.size() > 0 && !m_console.validate_number_parameter(params[0], steps)) return; m_console.get_visible_cpu()->debug()->single_step(steps); @@ -1256,7 +803,7 @@ void debugger_commands::execute_over(const std::vector<std::string_view> ¶ms { /* if we have a parameter, use it */ u64 steps = 1; - if (params.size() > 0 && !validate_number_parameter(params[0], steps)) + if (params.size() > 0 && !m_console.validate_number_parameter(params[0], steps)) return; m_console.get_visible_cpu()->debug()->single_step_over(steps); @@ -1282,7 +829,7 @@ void debugger_commands::execute_go(const std::vector<std::string_view> ¶ms) u64 addr = ~0; /* if we have a parameter, use it instead */ - if (params.size() > 0 && !validate_number_parameter(params[0], addr)) + if (params.size() > 0 && !m_console.validate_number_parameter(params[0], addr)) return; m_console.get_visible_cpu()->debug()->go(addr); @@ -1309,7 +856,7 @@ void debugger_commands::execute_go_interrupt(const std::vector<std::string_view> u64 irqline = -1; /* if we have a parameter, use it instead */ - if (params.size() > 0 && !validate_number_parameter(params[0], irqline)) + if (params.size() > 0 && !m_console.validate_number_parameter(params[0], irqline)) return; m_console.get_visible_cpu()->debug()->go_interrupt(irqline); @@ -1324,11 +871,11 @@ void debugger_commands::execute_go_exception(const std::vector<std::string_view> u64 exception = -1; /* if we have a parameter, use it instead */ - if (params.size() > 0 && !validate_number_parameter(params[0], exception)) + if (params.size() > 0 && !m_console.validate_number_parameter(params[0], exception)) return; parsed_expression condition(m_console.visible_symtable()); - if (params.size() > 1 && !debug_command_parameter_expression(params[1], condition)) + if (params.size() > 1 && !m_console.validate_expression_parameter(params[1], condition)) return; m_console.get_visible_cpu()->debug()->go_exception(exception, condition.is_empty() ? "1" : condition.original_string()); @@ -1344,7 +891,7 @@ void debugger_commands::execute_go_time(const std::vector<std::string_view> &par u64 milliseconds = -1; /* if we have a parameter, use it instead */ - if (params.size() > 0 && !validate_number_parameter(params[0], milliseconds)) + if (params.size() > 0 && !m_console.validate_number_parameter(params[0], milliseconds)) return; m_console.get_visible_cpu()->debug()->go_milliseconds(milliseconds); @@ -1358,7 +905,7 @@ void debugger_commands::execute_go_time(const std::vector<std::string_view> &par void debugger_commands::execute_go_privilege(const std::vector<std::string_view> ¶ms) { parsed_expression condition(m_console.visible_symtable()); - if (params.size() > 0 && !debug_command_parameter_expression(params[0], condition)) + if (params.size() > 0 && !m_console.validate_expression_parameter(params[0], condition)) return; m_console.get_visible_cpu()->debug()->go_privilege((condition.is_empty()) ? "1" : condition.original_string()); @@ -1372,7 +919,7 @@ void debugger_commands::execute_go_privilege(const std::vector<std::string_view> void debugger_commands::execute_go_branch(bool sense, const std::vector<std::string_view> ¶ms) { parsed_expression condition(m_console.visible_symtable()); - if (params.size() > 0 && !debug_command_parameter_expression(params[0], condition)) + if (params.size() > 0 && !m_console.validate_expression_parameter(params[0], condition)) return; m_console.get_visible_cpu()->debug()->go_branch(sense, (condition.is_empty()) ? "1" : condition.original_string()); @@ -1389,7 +936,7 @@ void debugger_commands::execute_go_next_instruction(const std::vector<std::strin static constexpr u64 MAX_COUNT = 512; // if we have a parameter, use it instead */ - if (params.size() > 0 && !validate_number_parameter(params[0], count)) + if (params.size() > 0 && !m_console.validate_number_parameter(params[0], count)) return; if (count == 0) return; @@ -1400,7 +947,7 @@ void debugger_commands::execute_go_next_instruction(const std::vector<std::strin } device_state_interface *stateintf; - device_t *cpu = m_machine.debugger().console().get_visible_cpu(); + device_t *cpu = m_console.get_visible_cpu(); if (!cpu->interface(stateintf)) { m_console.printf("No state interface available for %s\n", cpu->name()); @@ -1438,7 +985,7 @@ void debugger_commands::execute_focus(const std::vector<std::string_view> ¶m { // validate params device_t *cpu; - if (!validate_cpu_parameter(params[0], cpu)) + if (!m_console.validate_cpu_parameter(params[0], cpu)) return; // first clear the ignore flag on the focused CPU @@ -1488,7 +1035,7 @@ void debugger_commands::execute_ignore(const std::vector<std::string_view> ¶ // validate parameters for (int paramnum = 0; paramnum < params.size(); paramnum++) - if (!validate_cpu_parameter(params[paramnum], devicelist[paramnum])) + if (!m_console.validate_cpu_parameter(params[paramnum], devicelist[paramnum])) return; // set the ignore flags @@ -1551,7 +1098,7 @@ void debugger_commands::execute_observe(const std::vector<std::string_view> &par // validate parameters for (int paramnum = 0; paramnum < params.size(); paramnum++) - if (!validate_cpu_parameter(params[paramnum], devicelist[paramnum])) + if (!m_console.validate_cpu_parameter(params[paramnum], devicelist[paramnum])) return; // clear the ignore flags @@ -1597,7 +1144,7 @@ void debugger_commands::execute_suspend(const std::vector<std::string_view> &par // validate parameters for (int paramnum = 0; paramnum < params.size(); paramnum++) - if (!validate_cpu_parameter(params[paramnum], devicelist[paramnum])) + if (!m_console.validate_cpu_parameter(params[paramnum], devicelist[paramnum])) return; for (int paramnum = 0; paramnum < params.size(); paramnum++) @@ -1656,7 +1203,7 @@ void debugger_commands::execute_resume(const std::vector<std::string_view> ¶ // validate parameters for (int paramnum = 0; paramnum < params.size(); paramnum++) - if (!validate_cpu_parameter(params[paramnum], devicelist[paramnum])) + if (!m_console.validate_cpu_parameter(params[paramnum], devicelist[paramnum])) return; for (int paramnum = 0; paramnum < params.size(); paramnum++) @@ -1699,12 +1246,12 @@ void debugger_commands::execute_comment_add(const std::vector<std::string_view> { // param 1 is the address for the comment u64 address; - if (!validate_number_parameter(params[0], address)) + if (!m_console.validate_number_parameter(params[0], address)) return; // CPU parameter is implicit device_t *cpu; - if (!validate_cpu_parameter(std::string_view(), cpu)) + if (!m_console.validate_cpu_parameter(std::string_view(), cpu)) return; // make sure param 2 exists @@ -1729,12 +1276,12 @@ void debugger_commands::execute_comment_del(const std::vector<std::string_view> { // param 1 can either be a command or the address for the comment u64 address; - if (!validate_number_parameter(params[0], address)) + if (!m_console.validate_number_parameter(params[0], address)) return; // CPU parameter is implicit device_t *cpu; - if (!validate_cpu_parameter(std::string_view(), cpu)) + if (!m_console.validate_cpu_parameter(std::string_view(), cpu)) return; // If it's a number, it must be an address @@ -1804,7 +1351,7 @@ void debugger_commands::execute_bpset(const std::vector<std::string_view> ¶m // param 1 is the address/CPU u64 address; address_space *space; - if (!validate_target_address_parameter(params[0], AS_PROGRAM, space, address)) + if (!m_console.validate_target_address_parameter(params[0], AS_PROGRAM, space, address)) return; device_execute_interface const *execute; @@ -1823,12 +1370,12 @@ void debugger_commands::execute_bpset(const std::vector<std::string_view> ¶m // param 2 is the condition parsed_expression condition(debug->symtable()); - if (params.size() > 1 && !debug_command_parameter_expression(params[1], condition)) + if (params.size() > 1 && !m_console.validate_expression_parameter(params[1], condition)) return; // param 3 is the action std::string_view action; - if (params.size() > 2 && !debug_command_parameter_command(action = params[2])) + if (params.size() > 2 && !m_console.validate_command_parameter(action = params[2])) return; // set the breakpoint @@ -1929,7 +1476,7 @@ void debugger_commands::execute_bplist(const std::vector<std::string_view> ¶ if (!params.empty()) { device_t *cpu; - if (!validate_cpu_parameter(params[0], cpu)) + if (!m_console.validate_cpu_parameter(params[0], cpu)) return; apply(*cpu); if (!printed) @@ -1957,7 +1504,7 @@ void debugger_commands::execute_wpset(int spacenum, const std::vector<std::strin address_space *space; // param 1 is the address/CPU - if (!validate_target_address_parameter(params[0], spacenum, space, address)) + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, address)) return; device_execute_interface const *execute; @@ -1969,7 +1516,7 @@ void debugger_commands::execute_wpset(int spacenum, const std::vector<std::strin device_debug *const debug = space->device().debug(); // param 2 is the length - if (!validate_number_parameter(params[1], length)) + if (!m_console.validate_number_parameter(params[1], length)) return; // param 3 is the type @@ -1992,12 +1539,12 @@ void debugger_commands::execute_wpset(int spacenum, const std::vector<std::strin // param 4 is the condition parsed_expression condition(debug->symtable()); - if (params.size() > 3 && !debug_command_parameter_expression(params[3], condition)) + if (params.size() > 3 && !m_console.validate_expression_parameter(params[3], condition)) return; // param 5 is the action std::string_view action; - if (params.size() > 4 && !debug_command_parameter_command(action = params[4])) + if (params.size() > 4 && !m_console.validate_command_parameter(action = params[4])) return; // set the watchpoint @@ -2110,7 +1657,7 @@ void debugger_commands::execute_wplist(const std::vector<std::string_view> ¶ if (!params.empty()) { device_t *cpu; - if (!validate_cpu_parameter(params[0], cpu)) + if (!m_console.validate_cpu_parameter(params[0], cpu)) return; apply(*cpu); if (!printed) @@ -2136,17 +1683,17 @@ void debugger_commands::execute_rpset(const std::vector<std::string_view> ¶m { // CPU is implicit device_t *cpu; - if (!validate_cpu_parameter(std::string_view(), cpu)) + if (!m_console.validate_cpu_parameter(std::string_view(), cpu)) return; // param 1 is the condition parsed_expression condition(cpu->debug()->symtable()); - if (params.size() > 0 && !debug_command_parameter_expression(params[0], condition)) + if (params.size() > 0 && !m_console.validate_expression_parameter(params[0], condition)) return; // param 2 is the action std::string_view action; - if (params.size() > 1 && !debug_command_parameter_command(action = params[1])) + if (params.size() > 1 && !m_console.validate_command_parameter(action = params[1])) return; // set the registerpoint @@ -2222,22 +1769,22 @@ void debugger_commands::execute_epset(const std::vector<std::string_view> ¶m { // CPU is implicit device_t *cpu; - if (!validate_cpu_parameter(std::string_view(), cpu)) + if (!m_console.validate_cpu_parameter(std::string_view(), cpu)) return; // param 1 is the exception type u64 type; - if (!validate_number_parameter(params[0], type)) + if (!m_console.validate_number_parameter(params[0], type)) return; // param 2 is the condition parsed_expression condition(cpu->debug()->symtable()); - if (params.size() > 1 && !debug_command_parameter_expression(params[1], condition)) + if (params.size() > 1 && !m_console.validate_expression_parameter(params[1], condition)) return; // param 3 is the action std::string_view action; - if (params.size() > 2 && !debug_command_parameter_command(action = params[2])) + if (params.size() > 2 && !m_console.validate_command_parameter(action = params[2])) return; // set the exception point @@ -2338,7 +1885,7 @@ void debugger_commands::execute_eplist(const std::vector<std::string_view> ¶ if (!params.empty()) { device_t *cpu; - if (!validate_cpu_parameter(params[0], cpu)) + if (!m_console.validate_cpu_parameter(params[0], cpu)) return; apply(*cpu); if (!printed) @@ -2386,7 +1933,7 @@ void debugger_commands::execute_rplist(const std::vector<std::string_view> ¶ if (!params.empty()) { device_t *cpu; - if (!validate_cpu_parameter(params[0], cpu)) + if (!m_console.validate_cpu_parameter(params[0], cpu)) return; apply(*cpu); if (!printed) @@ -2461,9 +2008,9 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string address_space *space; // validate parameters - if (!validate_target_address_parameter(params[1], spacenum, space, offset)) + if (!m_console.validate_target_address_parameter(params[1], spacenum, space, offset)) return; - if (!validate_number_parameter(params[2], length)) + if (!m_console.validate_number_parameter(params[2], length)) return; // determine the addresses to write @@ -2488,8 +2035,9 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string for (u64 i = offset; i != endoffset; i++) { offs_t curaddr = i; - u64 data = space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr) ? - space->read_qword(curaddr) : space->unmap(); + address_space *tspace; + u64 data = space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace) ? + tspace->read_qword(curaddr) : space->unmap(); fwrite(&data, 8, 1, f); } break; @@ -2497,8 +2045,9 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string for (u64 i = offset; i != endoffset; i++) { offs_t curaddr = i; - u32 data = space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr) ? - space->read_dword(curaddr) : space->unmap(); + address_space *tspace; + u32 data = space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace) ? + tspace->read_dword(curaddr) : space->unmap(); fwrite(&data, 4, 1, f); } break; @@ -2506,8 +2055,9 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string for (u64 i = offset; i != endoffset; i++) { offs_t curaddr = i; - u16 data = space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr) ? - space->read_word(curaddr) : space->unmap(); + address_space *tspace; + u16 data = space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace) ? + tspace->read_word(curaddr) : space->unmap(); fwrite(&data, 2, 1, f); } break; @@ -2515,8 +2065,9 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string for (u64 i = offset; i != endoffset; i++) { offs_t curaddr = i; - u8 data = space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr) ? - space->read_byte(curaddr) : space->unmap(); + address_space *tspace; + u8 data = space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace) ? + tspace->read_byte(curaddr) : space->unmap(); fwrite(&data, 1, 1, f); } break; @@ -2526,8 +2077,9 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string for (u64 i = offset; i != endoffset; i+=16) { offs_t curaddr = i; - u16 data = space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr) ? - space->read_word(curaddr) : space->unmap(); + address_space *tspace; + u16 data = space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace) ? + tspace->read_word(curaddr) : space->unmap(); fwrite(&data, 2, 1, f); } break; @@ -2549,11 +2101,11 @@ void debugger_commands::execute_saveregion(const std::vector<std::string_view> & memory_region *region; // validate parameters - if (!validate_number_parameter(params[1], offset)) + if (!m_console.validate_number_parameter(params[1], offset)) return; - if (!validate_number_parameter(params[2], length)) + if (!m_console.validate_number_parameter(params[2], length)) return; - if (!validate_memory_region_parameter(params[3], region)) + if (!m_console.validate_memory_region_parameter(params[3], region)) return; if (offset >= region->bytes()) @@ -2589,9 +2141,9 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string address_space *space; // validate parameters - if (!validate_target_address_parameter(params[1], spacenum, space, offset)) + if (!m_console.validate_target_address_parameter(params[1], spacenum, space, offset)) return; - if (params.size() > 2 && !validate_number_parameter(params[2], length)) + if (params.size() > 2 && !m_console.validate_number_parameter(params[2], length)) return; // open the file @@ -2631,8 +2183,9 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string offs_t curaddr = i; u64 data; f.read((char *)&data, 8); - if (f && space->device().memory().translate(space->spacenum(), TRANSLATE_WRITE_DEBUG, curaddr)) - space->write_qword(curaddr, data); + address_space *tspace; + if (f && space->device().memory().translate(space->spacenum(), device_memory_interface::TR_WRITE, curaddr, tspace)) + tspace->write_qword(curaddr, data); } break; case -2: @@ -2641,8 +2194,9 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string offs_t curaddr = i; u32 data; f.read((char *)&data, 4); - if (f && space->device().memory().translate(space->spacenum(), TRANSLATE_WRITE_DEBUG, curaddr)) - space->write_dword(curaddr, data); + address_space *tspace; + if (f && space->device().memory().translate(space->spacenum(), device_memory_interface::TR_WRITE, curaddr, tspace)) + tspace->write_dword(curaddr, data); } break; case -1: @@ -2651,8 +2205,9 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string offs_t curaddr = i; u16 data; f.read((char *)&data, 2); - if (f && space->device().memory().translate(space->spacenum(), TRANSLATE_WRITE_DEBUG, curaddr)) - space->write_word(curaddr, data); + address_space *tspace; + if (f && space->device().memory().translate(space->spacenum(), device_memory_interface::TR_WRITE, curaddr, tspace)) + tspace->write_word(curaddr, data); } break; case 0: @@ -2661,8 +2216,9 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string offs_t curaddr = i; u8 data; f.read((char *)&data, 1); - if (f && space->device().memory().translate(space->spacenum(), TRANSLATE_WRITE_DEBUG, curaddr)) - space->write_byte(curaddr, data); + address_space *tspace; + if (f && space->device().memory().translate(space->spacenum(), device_memory_interface::TR_WRITE, curaddr, tspace)) + tspace->write_byte(curaddr, data); } break; case 3: @@ -2673,8 +2229,9 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string offs_t curaddr = i; u16 data; f.read((char *)&data, 2); - if (f && space->device().memory().translate(space->spacenum(), TRANSLATE_WRITE_DEBUG, curaddr)) - space->write_word(curaddr, data); + address_space *tspace; + if (f && space->device().memory().translate(space->spacenum(), device_memory_interface::TR_WRITE, curaddr, tspace)) + tspace->write_word(curaddr, data); } break; } @@ -2698,11 +2255,11 @@ void debugger_commands::execute_loadregion(const std::vector<std::string_view> & memory_region *region; // validate parameters - if (!validate_number_parameter(params[1], offset)) + if (!m_console.validate_number_parameter(params[1], offset)) return; - if (!validate_number_parameter(params[2], length)) + if (!m_console.validate_number_parameter(params[2], length)) return; - if (!validate_memory_region_parameter(params[3], region)) + if (!m_console.validate_memory_region_parameter(params[3], region)) return; if (offset >= region->bytes()) @@ -2746,23 +2303,23 @@ void debugger_commands::execute_dump(int spacenum, const std::vector<std::string // validate parameters address_space *space; u64 offset; - if (!validate_target_address_parameter(params[1], spacenum, space, offset)) + if (!m_console.validate_target_address_parameter(params[1], spacenum, space, offset)) return; u64 length; - if (!validate_number_parameter(params[2], length)) + if (!m_console.validate_number_parameter(params[2], length)) return; u64 width = 0; - if (params.size() > 3 && !validate_number_parameter(params[3], width)) + if (params.size() > 3 && !m_console.validate_number_parameter(params[3], width)) return; bool ascii = true; - if (params.size() > 4 && !validate_boolean_parameter(params[4], ascii)) + if (params.size() > 4 && !m_console.validate_boolean_parameter(params[4], ascii)) return; u64 rowsize = space->byte_to_address(16); - if (params.size() > 5 && !validate_number_parameter(params[5], rowsize)) + if (params.size() > 5 && !m_console.validate_number_parameter(params[5], rowsize)) return; int shift = space->addr_shift(); @@ -2824,21 +2381,22 @@ void debugger_commands::execute_dump(int spacenum, const std::vector<std::string if (i + j <= endoffset) { offs_t curaddr = i + j; - if (space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr)) + address_space *tspace; + if (space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace)) { switch (width) { case 8: - util::stream_format(output, " %016X", space->read_qword_unaligned(i+j)); + util::stream_format(output, " %016X", tspace->read_qword_unaligned(i+j)); break; case 4: - util::stream_format(output, " %08X", space->read_dword_unaligned(i+j)); + util::stream_format(output, " %08X", tspace->read_dword_unaligned(i+j)); break; case 2: - util::stream_format(output, " %04X", space->read_word_unaligned(i+j)); + util::stream_format(output, " %04X", tspace->read_word_unaligned(i+j)); break; case 1: - util::stream_format(output, " %02X", space->read_byte(i+j)); + util::stream_format(output, " %02X", tspace->read_byte(i+j)); break; } } @@ -2858,22 +2416,23 @@ void debugger_commands::execute_dump(int spacenum, const std::vector<std::string for (u64 j = 0; j < rowsize && (i + j) <= endoffset; j += delta) { offs_t curaddr = i + j; - if (space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr)) + address_space *tspace; + if (space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace)) { u64 data = 0; switch (width) { case 8: - data = space->read_qword_unaligned(i+j); + data = tspace->read_qword_unaligned(i+j); break; case 4: - data = space->read_dword_unaligned(i+j); + data = tspace->read_dword_unaligned(i+j); break; case 2: - data = space->read_word_unaligned(i+j); + data = tspace->read_word_unaligned(i+j); break; case 1: - data = space->read_byte(i+j); + data = tspace->read_byte(i+j); break; } for (unsigned int b = 0; b != width; b++) { @@ -2907,19 +2466,19 @@ void debugger_commands::execute_strdump(int spacenum, const std::vector<std::str { // validate parameters u64 offset; - if (!validate_number_parameter(params[1], offset)) + if (!m_console.validate_number_parameter(params[1], offset)) return; u64 length; - if (!validate_number_parameter(params[2], length)) + if (!m_console.validate_number_parameter(params[2], length)) return; u64 term = 0; - if (params.size() > 3 && !validate_number_parameter(params[3], term)) + if (params.size() > 3 && !m_console.validate_number_parameter(params[3], term)) return; address_space *space; - if (!validate_device_space_parameter((params.size() > 4) ? params[4] : std::string_view(), spacenum, space)) + if (!m_console.validate_device_space_parameter((params.size() > 4) ? params[4] : std::string_view(), spacenum, space)) return; // further validation @@ -2969,28 +2528,29 @@ void debugger_commands::execute_strdump(int spacenum, const std::vector<std::str // get the character data u64 data = 0; offs_t curaddr = offset; - if (space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr)) + address_space *tspace; + if (space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace)) { switch (width) { case 1: - data = space->read_byte(curaddr); + data = tspace->read_byte(curaddr); break; case 2: - data = space->read_word(curaddr); + data = tspace->read_word(curaddr); if (be) data = swapendian_int16(data); break; case 4: - data = space->read_dword(curaddr); + data = tspace->read_dword(curaddr); if (be) data = swapendian_int32(data); break; case 8: - data = space->read_qword(curaddr); + data = tspace->read_qword(curaddr); if (be) data = swapendian_int64(data); break; @@ -3150,7 +2710,7 @@ void debugger_commands::execute_cheatrange(bool init, const std::vector<std::str } // fourth argument is device/space - if (!validate_device_space_parameter((params.size() > 3) ? params[3] : std::string_view(), -1, space)) + if (!m_console.validate_device_space_parameter((params.size() > 3) ? params[3] : std::string_view(), -1, space)) return; } @@ -3160,9 +2720,9 @@ void debugger_commands::execute_cheatrange(bool init, const std::vector<std::str { // validate parameters u64 offset, length; - if (!validate_number_parameter(params[init ? 1 : 0], offset)) + if (!m_console.validate_number_parameter(params[init ? 1 : 0], offset)) return; - if (!validate_number_parameter(params[init ? 2 : 1], length)) + if (!m_console.validate_number_parameter(params[init ? 2 : 1], length)) return; // force region to the specified range @@ -3277,7 +2837,7 @@ void debugger_commands::execute_cheatnext(bool initial, const std::vector<std::s } u64 comp_value = 0; - if (params.size() > 1 && !validate_number_parameter(params[1], comp_value)) + if (params.size() > 1 && !m_console.validate_number_parameter(params[1], comp_value)) return; comp_value = m_cheat.sign_extend(comp_value); @@ -3580,9 +3140,9 @@ void debugger_commands::execute_find(int spacenum, const std::vector<std::string address_space *space; // validate parameters - if (!validate_target_address_parameter(params[0], spacenum, space, offset)) + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, offset)) return; - if (!validate_number_parameter(params[1], length)) + if (!m_console.validate_number_parameter(params[1], length)) return; // further validation @@ -3626,7 +3186,7 @@ void debugger_commands::execute_find(int spacenum, const std::vector<std::string data_size[data_count++] |= 0x10; // otherwise, validate as a number - else if (!validate_number_parameter(pdata, data_to_find[data_count++])) + else if (!m_console.validate_number_parameter(pdata, data_to_find[data_count++])) return; } } @@ -3644,36 +3204,37 @@ void debugger_commands::execute_find(int spacenum, const std::vector<std::string for (int j = 0; j < data_count && match; j++) { offs_t address = space->byte_to_address(i + suboffset); + address_space *tspace; switch (data_size[j]) { case 1: address &= space->logaddrmask(); - if (memory.translate(space->spacenum(), TRANSLATE_READ_DEBUG, address)) - match = space->read_byte(address) == u8(data_to_find[j]); + if (memory.translate(space->spacenum(), device_memory_interface::TR_READ, address, tspace)) + match = tspace->read_byte(address) == u8(data_to_find[j]); else match = false; break; case 2: address &= space->logaddrmask(); - if (memory.translate(space->spacenum(), TRANSLATE_READ_DEBUG, address)) - match = space->read_word_unaligned(address) == u16(data_to_find[j]); + if (memory.translate(space->spacenum(), device_memory_interface::TR_READ, address, tspace)) + match = tspace->read_word_unaligned(address) == u16(data_to_find[j]); else match = false; break; case 4: address &= space->logaddrmask(); - if (memory.translate(space->spacenum(), TRANSLATE_READ_DEBUG, address)) - match = space->read_dword_unaligned(address) == u32(data_to_find[j]); + if (memory.translate(space->spacenum(), device_memory_interface::TR_READ, address, tspace)) + match = tspace->read_dword_unaligned(address) == u32(data_to_find[j]); else match = false; break; case 8: address &= space->logaddrmask(); - if (memory.translate(space->spacenum(), TRANSLATE_READ_DEBUG, address)) - match = space->read_qword_unaligned(address) == u64(data_to_find[j]); + if (memory.translate(space->spacenum(), device_memory_interface::TR_READ, address, tspace)) + match = tspace->read_qword_unaligned(address) == u64(data_to_find[j]); else match = false; break; @@ -3709,9 +3270,9 @@ void debugger_commands::execute_fill(int spacenum, const std::vector<std::string address_space *space; // validate parameters - if (!validate_target_address_parameter(params[0], spacenum, space, offset)) + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, offset)) return; - if (!validate_number_parameter(params[1], length)) + if (!m_console.validate_number_parameter(params[1], length)) return; // further validation @@ -3753,7 +3314,7 @@ void debugger_commands::execute_fill(int spacenum, const std::vector<std::string } // validate as a number - if (!validate_number_parameter(pdata, fill_data[data_count++])) + if (!m_console.validate_number_parameter(pdata, fill_data[data_count++])) return; } } @@ -3770,7 +3331,8 @@ void debugger_commands::execute_fill(int spacenum, const std::vector<std::string for (int j = 0; j < data_count; j++) { offs_t address = space->byte_to_address(offset) & space->logaddrmask(); - if (!memory.translate(space->spacenum(), TRANSLATE_WRITE_DEBUG, address)) + address_space *tspace; + if (!memory.translate(space->spacenum(), device_memory_interface::TR_WRITE, address, tspace)) { m_console.printf("Fill aborted due to page fault at %0*X\n", space->logaddrchars(), space->byte_to_address(offset) & space->logaddrmask()); length = 0; @@ -3779,19 +3341,19 @@ void debugger_commands::execute_fill(int spacenum, const std::vector<std::string switch (fill_data_size[j]) { case 1: - space->write_byte(address, fill_data[j]); + tspace->write_byte(address, fill_data[j]); break; case 2: - space->write_word_unaligned(address, fill_data[j]); + tspace->write_word_unaligned(address, fill_data[j]); break; case 4: - space->write_dword_unaligned(address, fill_data[j]); + tspace->write_dword_unaligned(address, fill_data[j]); break; case 8: - space->read_qword_unaligned(address, fill_data[j]); + tspace->read_qword_unaligned(address, fill_data[j]); break; } offset += fill_data_size[j]; @@ -3818,13 +3380,13 @@ void debugger_commands::execute_dasm(const std::vector<std::string_view> ¶ms address_space *space; // validate parameters - if (!validate_number_parameter(params[1], offset)) + if (!m_console.validate_number_parameter(params[1], offset)) return; - if (!validate_number_parameter(params[2], length)) + if (!m_console.validate_number_parameter(params[2], length)) return; - if (params.size() > 3 && !validate_boolean_parameter(params[3], bytes)) + if (params.size() > 3 && !m_console.validate_boolean_parameter(params[3], bytes)) return; - if (!validate_device_space_parameter(params.size() > 4 ? params[4] : std::string_view(), AS_PROGRAM, space)) + if (!m_console.validate_device_space_parameter(params.size() > 4 ? params[4] : std::string_view(), AS_PROGRAM, space)) return; // determine the width of the bytes @@ -3922,7 +3484,7 @@ void debugger_commands::execute_trace(const std::vector<std::string_view> ¶m // validate parameters device_t *cpu; - if (!validate_cpu_parameter(params.size() > 1 ? params[1] : std::string_view(), cpu)) + if (!m_console.validate_cpu_parameter(params.size() > 1 ? params[1] : std::string_view(), cpu)) return; if (params.size() > 2) { @@ -3944,7 +3506,7 @@ void debugger_commands::execute_trace(const std::vector<std::string_view> ¶m } } } - if (params.size() > 3 && !debug_command_parameter_command(action = params[3])) + if (params.size() > 3 && !m_console.validate_command_parameter(action = params[3])) return; // open the file @@ -3999,11 +3561,11 @@ void debugger_commands::execute_history(const std::vector<std::string_view> &par { // validate parameters device_t *device; - if (!validate_cpu_parameter(!params.empty() ? params[0] : std::string_view(), device)) + if (!m_console.validate_cpu_parameter(!params.empty() ? params[0] : std::string_view(), device)) return; u64 count = device_debug::HISTORY_SIZE; - if (params.size() > 1 && !validate_number_parameter(params[1], count)) + if (params.size() > 1 && !m_console.validate_number_parameter(params[1], count)) return; // further validation @@ -4020,13 +3582,13 @@ void debugger_commands::execute_history(const std::vector<std::string_view> &par } // loop over lines - debug_disasm_buffer buffer(*device); std::string instruction; for (int index = int(unsigned(count)); index > 0; index--) { auto const pc = debug->history_pc(1 - index); if (pc.second) { + debug_disasm_buffer buffer(*device); offs_t next_offset; offs_t size; u32 info; @@ -4047,12 +3609,12 @@ void debugger_commands::execute_trackpc(const std::vector<std::string_view> &par { // Gather the on/off switch (if present) bool turnOn = true; - if (params.size() > 0 && !validate_boolean_parameter(params[0], turnOn)) + if (params.size() > 0 && !m_console.validate_boolean_parameter(params[0], turnOn)) return; // Gather the cpu id (if present) device_t *cpu = nullptr; - if (!validate_cpu_parameter((params.size() > 1) ? params[1] : std::string_view(), cpu)) + if (!m_console.validate_cpu_parameter((params.size() > 1) ? params[1] : std::string_view(), cpu)) return; const device_state_interface *state; @@ -4064,7 +3626,7 @@ void debugger_commands::execute_trackpc(const std::vector<std::string_view> &par // Should we clear the existing data? bool clear = false; - if (params.size() > 2 && !validate_boolean_parameter(params[2], clear)) + if (params.size() > 2 && !m_console.validate_boolean_parameter(params[2], clear)) return; cpu->debug()->set_track_pc((bool)turnOn); @@ -4096,7 +3658,7 @@ void debugger_commands::execute_trackmem(const std::vector<std::string_view> &pa { // Gather the on/off switch (if present) bool turnOn = true; - if (params.size() > 0 && !validate_boolean_parameter(params[0], turnOn)) + if (params.size() > 0 && !m_console.validate_boolean_parameter(params[0], turnOn)) return; // Gather the cpu id (if present) @@ -4104,17 +3666,17 @@ void debugger_commands::execute_trackmem(const std::vector<std::string_view> &pa if (params.size() > 1) cpuparam = params[1]; device_t *cpu = nullptr; - if (!validate_cpu_parameter(cpuparam, cpu)) + if (!m_console.validate_cpu_parameter(cpuparam, cpu)) return; // Should we clear the existing data? bool clear = false; - if (params.size() > 2 && !validate_boolean_parameter(params[2], clear)) + if (params.size() > 2 && !m_console.validate_boolean_parameter(params[2], clear)) return; // Get the address space for the given cpu address_space *space; - if (!validate_device_space_parameter(cpuparam, AS_PROGRAM, space)) + if (!m_console.validate_device_space_parameter(cpuparam, AS_PROGRAM, space)) return; // Inform the CPU it's time to start tracking memory writes @@ -4135,12 +3697,13 @@ void debugger_commands::execute_pcatmem(int spacenum, const std::vector<std::str // Gather the required target address/space parameter u64 address; address_space *space; - if (!validate_target_address_parameter(params[0], spacenum, space, address)) + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, address)) return; // Translate the address offs_t a = address & space->logaddrmask(); - if (!space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, a)) + address_space *tspace; + if (!space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, a, tspace)) { m_console.printf("Address translation failed\n"); return; @@ -4152,19 +3715,19 @@ void debugger_commands::execute_pcatmem(int spacenum, const std::vector<std::str switch (space->data_width()) { case 8: - data = space->read_byte(a); + data = tspace->read_byte(a); break; case 16: - data = space->read_word_unaligned(a); + data = tspace->read_word_unaligned(a); break; case 32: - data = space->read_dword_unaligned(a); + data = tspace->read_dword_unaligned(a); break; case 64: - data = space->read_qword_unaligned(a); + data = tspace->read_qword_unaligned(a); break; } @@ -4194,7 +3757,7 @@ void debugger_commands::execute_snap(const std::vector<std::string_view> ¶ms else { u64 scrnum = 0; - if (params.size() > 1 && !validate_number_parameter(params[1], scrnum)) + if (params.size() > 1 && !m_console.validate_number_parameter(params[1], scrnum)) return; screen_device_enumerator iter(m_machine.root_device()); @@ -4244,22 +3807,24 @@ void debugger_commands::execute_map(int spacenum, const std::vector<std::string_ // validate parameters u64 address; address_space *space; - if (!validate_target_address_parameter(params[0], spacenum, space, address)) + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, address)) return; + address &= space->logaddrmask(); // do the translation first - for (int intention = TRANSLATE_READ_DEBUG; intention <= TRANSLATE_FETCH_DEBUG; intention++) + for (int intention = device_memory_interface::TR_READ; intention <= device_memory_interface::TR_FETCH; intention++) { static const char *const intnames[] = { "Read", "Write", "Fetch" }; - offs_t taddress = address & space->addrmask(); - if (space->device().memory().translate(space->spacenum(), intention, taddress)) + offs_t taddress = address; + address_space *tspace; + if (space->device().memory().translate(space->spacenum(), intention, taddress, tspace)) { - std::string mapname = space->get_handler_string((intention == TRANSLATE_WRITE_DEBUG) ? read_or_write::WRITE : read_or_write::READ, taddress); + std::string mapname = tspace->get_handler_string((intention == device_memory_interface::TR_WRITE) ? read_or_write::WRITE : read_or_write::READ, taddress); m_console.printf( - "%7s: %0*X logical == %0*X physical -> %s\n", + "%7s: %0*X logical %s == %0*X physical %s -> %s\n", intnames[intention & 3], - space->logaddrchars(), address, - space->addrchars(), taddress, + space->logaddrchars(), address, space->name(), + tspace->addrchars(), taddress, tspace->name(), mapname); } else @@ -4275,7 +3840,7 @@ void debugger_commands::execute_map(int spacenum, const std::vector<std::string_ void debugger_commands::execute_memdump(const std::vector<std::string_view> ¶ms) { device_t *root = &m_machine.root_device(); - if ((params.size() >= 2) && !validate_device_parameter(params[1], root)) + if ((params.size() >= 2) && !m_console.validate_device_parameter(params[1], root)) return; using namespace std::literals; @@ -4349,7 +3914,7 @@ void debugger_commands::execute_symlist(const std::vector<std::string_view> &par { // validate parameters device_t *cpu; - if (!validate_cpu_parameter(params[0], cpu)) + if (!m_console.validate_cpu_parameter(params[0], cpu)) return; symtable = &cpu->debug()->symtable(); m_console.printf("CPU '%s' symbols:\n", cpu->tag()); @@ -4457,10 +4022,19 @@ void debugger_commands::execute_mount(const std::vector<std::string_view> ¶m { if ((img.instance_name() == params[0]) || (img.brief_instance_name() == params[0])) { - if (img.load(params[1]) != image_init_result::PASS) - m_console.printf("Unable to mount file %s on %s\n", params[1], params[0]); - else + auto [err, msg] = img.load(params[1]); + if (!err) + { m_console.printf("File %s mounted on %s\n", params[1], params[0]); + } + else + { + m_console.printf( + "Unable to mount file %s on %s: %s\n", + params[1], + params[0], + !msg.empty() ? msg : err.message()); + } return; } } diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h index 8c5e29fecae..134f838f8a7 100644 --- a/src/emu/debug/debugcmd.h +++ b/src/emu/debug/debugcmd.h @@ -24,27 +24,6 @@ class debugger_commands public: debugger_commands(running_machine &machine, debugger_cpu &cpu, debugger_console &console); - // validates a parameter as a boolean value - bool validate_boolean_parameter(std::string_view param, bool &result); - - // validates a parameter as a numeric value - bool validate_number_parameter(std::string_view param, u64 &result); - - // validates a parameter as a device - bool validate_device_parameter(std::string_view param, device_t *&result); - - // validates a parameter as a CPU - bool validate_cpu_parameter(std::string_view param, device_t *&result); - - // validates a parameter as an address space identifier - bool validate_device_space_parameter(std::string_view param, int spacenum, address_space *&result); - - // validates a parameter as a target address and retrieves the given address space and address - bool validate_target_address_parameter(std::string_view param, int spacenum, address_space *&space, u64 &addr); - - // validates a parameter as a memory region name and retrieves the given region - bool validate_memory_region_parameter(std::string_view param, memory_region *&result); - private: struct global_entry { @@ -87,11 +66,6 @@ private: u8 disabled = 0U; }; - device_t &get_device_search_base(std::string_view ¶m); - device_t *get_cpu_by_index(u64 cpunum); - bool debug_command_parameter_expression(std::string_view param, parsed_expression &result); - bool debug_command_parameter_command(std::string_view param); - bool cheat_address_is_valid(address_space &space, offs_t address); u64 get_cpunum(); @@ -99,7 +73,7 @@ private: u64 global_get(global_entry *global); void global_set(global_entry *global, u64 value); - bool mini_printf(std::ostream &stream, std::string_view format, int params, u64 *param); + bool mini_printf(std::ostream &stream, const std::vector<std::string_view> ¶ms); template <typename T> void execute_index_command(std::vector<std::string_view> const ¶ms, T &&apply, char const *unused_message); diff --git a/src/emu/debug/debugcon.cpp b/src/emu/debug/debugcon.cpp index 41e09d748f3..ec5bc154751 100644 --- a/src/emu/debug/debugcon.cpp +++ b/src/emu/debug/debugcon.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Aaron Giles +// copyright-holders:Aaron Giles, Vas Crabb /********************************************************************* debugcon.cpp @@ -17,6 +17,7 @@ #include "debugger.h" #include "fileio.h" +#include "main.h" #include "corestr.h" @@ -198,7 +199,7 @@ void debugger_console::execute_condump(const std::vector<std::string_view>& para // symbol table //------------------------------------------------- -symbol_table &debugger_console::visible_symtable() +symbol_table &debugger_console::visible_symtable() const { return m_visiblecpu->debug()->symtable(); } @@ -559,6 +560,494 @@ std::string debugger_console::cmderr_to_string(CMDERR error) } +//************************************************************************** +// PARAMETER VALIDATION HELPERS +//************************************************************************** + +namespace { + +template <typename T> +inline std::string_view::size_type find_delimiter(std::string_view str, T &&is_delim) +{ + unsigned parens = 0; + for (std::string_view::size_type i = 0; str.length() > i; ++i) + { + if (str[i] == '(') + { + ++parens; + } + else if (parens) + { + if (str[i] == ')') + --parens; + } + else if (is_delim(str[i])) + { + return i; + } + } + return std::string_view::npos; +} + +} // anonymous namespace + + +/// \brief Validate parameter as a Boolean value +/// +/// Validates a parameter as a Boolean value. Fixed strings and +/// expressions evaluating to numeric values are recognised. The result +/// is unchanged for an empty string. +/// \param [in] param The parameter string. +/// \param [in,out] result The default value on entry, and the value of +/// the parameter interpreted as a Boolean on success. Unchanged if +/// the parameter is an empty string. +/// \return true if the parameter is a valid Boolean value or an empty +/// string, or false otherwise. +bool debugger_console::validate_boolean_parameter(std::string_view param, bool &result) +{ + // nullptr parameter does nothing and returns no error + if (param.empty()) + return true; + + // evaluate the expression; success if no error + using namespace std::literals; + bool const is_true = util::streqlower(param, "true"sv); + bool const is_false = util::streqlower(param, "false"sv); + + if (is_true || is_false) + { + result = is_true; + return true; + } + + // try to evaluate as a number + u64 val; + if (!validate_number_parameter(param, val)) + return false; + + result = val != 0; + return true; +} + + +/// \brief Validate parameter as a numeric value +/// +/// Parses the parameter as an expression and evaluates it as a number. +/// \param [in] param The parameter string. +/// \param [out] result The numeric value of the expression on success. +/// Unchanged on failure. +/// \return true if the parameter is a valid expression that evaluates +/// to a numeric value, or false otherwise. +bool debugger_console::validate_number_parameter(std::string_view param, u64 &result) +{ + // evaluate the expression; success if no error + try + { + result = parsed_expression(visible_symtable(), param).execute(); + return true; + } + catch (expression_error const &error) + { + // print an error pointing to the character that caused it + printf("Error in expression: %s\n", param); + printf(" %*s^", error.offset(), ""); + printf("%s\n", error.code_string()); + return false; + } +} + + +/// \brief Validate parameter as a device +/// +/// Validates a parameter as a device identifier and retrieves the +/// device on success. A string corresponding to the tag of a device +/// refers to that device; an empty string refers to the current CPU +/// with debugger focus; any other string is parsed as an expression +/// and treated as an index of a device implementing +/// #device_execute_interface and #device_state_interface, and exposing +/// a generic PC base value. +/// \param [in] param The parameter string. +/// \param [out] result A pointer to the device on success, or unchanged +/// on failure. +/// \return true if the parameter refers to a device in the current +/// system, or false otherwise. +bool debugger_console::validate_device_parameter(std::string_view param, device_t *&result) +{ + // if no parameter, use the visible CPU + if (param.empty()) + { + device_t *const current = m_visiblecpu; + if (current) + { + result = current; + return true; + } + else + { + printf("No valid CPU is currently selected\n"); + return false; + } + } + + // next look for a tag match + std::string_view relative = param; + device_t &base = get_device_search_base(relative); + device_t *device = base.subdevice(strmakelower(relative)); + if (device) + { + result = device; + return true; + } + + // then evaluate as an expression; on an error assume it was a tag + u64 cpunum; + try + { + cpunum = parsed_expression(visible_symtable(), param).execute(); + } + catch (expression_error &) + { + printf("Unable to find device '%s'\n", param); + return false; + } + + // attempt to find by numerical index + device = get_cpu_by_index(cpunum); + if (device) + { + result = device; + return true; + } + else + { + // if out of range, complain + printf("Invalid CPU index %u\n", cpunum); + return false; + } +} + + +/// \brief Validate a parameter as a CPU +/// +/// Validates a parameter as a CPU identifier. Uses the same rules as +/// #validate_device_parameter to identify devices, but additionally +/// checks that the device is a "CPU" for the debugger's purposes. +/// \param [in] The parameter string. +/// \param [out] result The device on success, or unchanged on failure. +/// \return true if the parameter refers to a CPU-like device in the +/// current system, or false otherwise. +bool debugger_console::validate_cpu_parameter(std::string_view param, device_t *&result) +{ + // first do the standard device thing + device_t *device; + if (!validate_device_parameter(param, device)) + return false; + + // check that it's a "CPU" for the debugger's purposes + device_execute_interface const *execute; + if (device->interface(execute)) + { + result = device; + return true; + } + + printf("Device %s is not a CPU\n", device->name()); + return false; +} + + +/// \brief Validate a parameter as an address space identifier +/// +/// Validates a parameter as an address space identifier. Uses the same +/// rules as #validate_device_parameter to identify devices. If the +/// default address space number is negative, the first address space +/// exposed by the device will be used as the default. +/// \param [in] The parameter string. +/// \param [in] spacenum The default address space index. If negative, +/// the first address space exposed by the device (i.e. the address +/// space with the lowest index) will be used as the default. +/// \param [out] result The addresfs space on success, or unchanged on +/// failure. +/// \return true if the parameter refers to an address space in the +/// current system, or false otherwise. +bool debugger_console::validate_device_space_parameter(std::string_view param, int spacenum, address_space *&result) +{ + device_t *device; + std::string spacename; + if (param.empty()) + { + // if no parameter, use the visible CPU + device = m_visiblecpu; + if (!device) + { + printf("No valid CPU is currently selected\n"); + return false; + } + } + else + { + // look for a tag match on the whole parameter value + std::string_view relative = param; + device_t &base = get_device_search_base(relative); + device = base.subdevice(strmakelower(relative)); + + // if that failed, treat the last component as an address space + if (!device) + { + auto const delimiter = relative.find_last_of(":^"); + bool const found = std::string_view::npos != delimiter; + if (!found || (':' == relative[delimiter])) + { + spacename = strmakelower(relative.substr(found ? (delimiter + 1) : 0)); + relative = relative.substr(0, !found ? 0 : !delimiter ? 1 : delimiter); + if (!relative.empty()) + device = base.subdevice(strmakelower(relative)); + else if (m_visiblecpu) + device = m_visiblecpu; + else + device = &m_machine.root_device(); + } + } + } + + // if still no device found, evaluate as an expression + if (!device) + { + u64 cpunum; + try + { + cpunum = parsed_expression(visible_symtable(), param).execute(); + } + catch (expression_error const &) + { + // parsing failed - assume it was a tag + printf("Unable to find device '%s'\n", param); + return false; + } + + // attempt to find by numerical index + device = get_cpu_by_index(cpunum); + if (!device) + { + // if out of range, complain + printf("Invalid CPU index %u\n", cpunum); + return false; + } + } + + // ensure the device implements the memory interface + device_memory_interface *memory; + if (!device->interface(memory)) + { + printf("No memory interface found for device %s\n", device->name()); + return false; + } + + // fall back to supplied default space if appropriate + if (spacename.empty() && (0 <= spacenum)) + { + if (memory->has_space(spacenum)) + { + result = &memory->space(spacenum); + return true; + } + else + { + printf("No matching memory space found for device '%s'\n", device->tag()); + return false; + } + } + + // otherwise find the specified space or fall back to the first populated space + for (int i = 0; memory->max_space_count() > i; ++i) + { + if (memory->has_space(i) && (spacename.empty() || (memory->space(i).name() == spacename))) + { + result = &memory->space(i); + return true; + } + } + + // report appropriate error message + if (spacename.empty()) + printf("No memory spaces found for device '%s'\n", device->tag()); + else + printf("Memory space '%s' not found found for device '%s'\n", spacename, device->tag()); + return false; +} + + +/// \brief Validate a parameter as a target address +/// +/// Validates a parameter as an numeric expression to use as an address +/// optionally followed by a colon and a device identifier. If the +/// device identifier is not presnt, the current CPU with debugger focus +/// is assumed. See #validate_device_parameter for information on how +/// device parametersare interpreted. +/// \param [in] The parameter string. +/// \param [in] spacenum The default address space index. If negative, +/// the first address space exposed by the device (i.e. the address +/// space with the lowest index) will be used as the default. +/// \param [out] space The address space on success, or unchanged on +/// failure. +/// \param [out] addr The address on success, or unchanged on failure. +/// \return true if the address is a valid expression evaluating to a +/// number and the address space is found, or false otherwise. +bool debugger_console::validate_target_address_parameter(std::string_view param, int spacenum, address_space *&space, u64 &addr) +{ + // check for the device delimiter + std::string_view::size_type const devdelim = find_delimiter(param, [] (char ch) { return ':' == ch; }); + std::string_view device; + if (devdelim != std::string::npos) + device = param.substr(devdelim + 1); + + // parse the address first + u64 addrval; + if (!validate_number_parameter(param.substr(0, devdelim), addrval)) + return false; + + // find the address space + if (!validate_device_space_parameter(device, spacenum, space)) + return false; + + // set the address now that we have the space + addr = addrval; + return true; +} + + +/// \brief Validate a parameter as a memory region +/// +/// Validates a parameter as a memory region tag and retrieves the +/// specified memory region. +/// \param [in] The parameter string. +/// \param [out] result The memory region on success, or unchanged on +/// failure. +/// \return true if the parameter refers to a memory region in the +/// current system, or false otherwise. +bool debugger_console::validate_memory_region_parameter(std::string_view param, memory_region *&result) +{ + auto const ®ions = m_machine.memory().regions(); + std::string_view relative = param; + device_t &base = get_device_search_base(relative); + auto const iter = regions.find(base.subtag(strmakelower(relative))); + if (regions.end() != iter) + { + result = iter->second.get(); + return true; + } + else + { + printf("No matching memory region found for '%s'\n", param); + return false; + } +} + + +/// \brief Get search base for device or address space parameter +/// +/// Handles prefix prefixes used to indicate that a device tag should be +/// interpreted relative to the selected CPU. Removes the recognised +/// prefixes from the parameter value. +/// \param [in,out] param The parameter string. Recognised prefixes +/// affecting the search base are removed, leaving a tag relative to +/// the base device. +/// \return A reference to the base device that the tag should be +/// interpreted relative to. +device_t &debugger_console::get_device_search_base(std::string_view ¶m) const +{ + if (!param.empty()) + { + // handle ".:" or ".^" prefix for tag relative to current CPU if any + if (('.' == param[0]) && ((param.size() == 1) || (':' == param[1]) || ('^' == param[1]))) + { + param.remove_prefix(((param.size() > 1) && (':' == param[1])) ? 2 : 1); + device_t *const current = m_visiblecpu; + return current ? *current : m_machine.root_device(); + } + + // a sibling path makes most sense relative to current CPU + if ('^' == param[0]) + { + device_t *const current = m_visiblecpu; + return current ? *current : m_machine.root_device(); + } + } + + // default to root device + return m_machine.root_device(); +} + + +/// \brief Get CPU by index +/// +/// Looks up a CPU by the number the debugger assigns it based on its +/// position in the device tree relative to other CPUs. +/// \param [in] cpunum Zero-based index of the CPU to find. +/// \return A pointer to the CPU if found, or \c nullptr if no CPU has +/// the specified index. +device_t *debugger_console::get_cpu_by_index(u64 cpunum) const +{ + unsigned index = 0; + for (device_execute_interface &exec : execute_interface_enumerator(m_machine.root_device())) + { + // real CPUs should have pcbase + device_state_interface const *state; + if (exec.device().interface(state) && state->state_find_entry(STATE_GENPCBASE)) + { + if (index++ == cpunum) + { + return &exec.device(); + } + } + } + return nullptr; +} + + +//------------------------------------------------- +// validate_expression_parameter - validates +// an expression parameter +//-----------------------------------------------*/ + +bool debugger_console::validate_expression_parameter(std::string_view param, parsed_expression &result) +{ + try + { + // parse the expression; success if no error + result.parse(param); + return true; + } + catch (expression_error const &err) + { + // output an error + printf("Error in expression: %s\n", param); + printf(" %*s^", err.offset(), ""); + printf("%s\n", err.code_string()); + return false; + } +} + + +//------------------------------------------------- +// validate_command_parameter - validates a +// command parameter +//------------------------------------------------- + +bool debugger_console::validate_command_parameter(std::string_view param) +{ + // validate the comment; success if no error + CMDERR err = validate_command(param); + if (err.error_class() == CMDERR::NONE) + return true; + + // output an error + printf("Error in command: %s\n", param); + printf(" %*s^", err.error_offset(), ""); + printf("%s\n", cmderr_to_string(err)); + return false; +} + /*************************************************************************** @@ -597,7 +1086,7 @@ void debugger_console::print_core_wrap(std::string_view text, int wrapcol) // the format to the debug console //------------------------------------------------- -void debugger_console::vprintf(util::format_argument_pack<std::ostream> const &args) +void debugger_console::vprintf(util::format_argument_pack<char> const &args) { print_core(util::string_format(args)); @@ -605,7 +1094,7 @@ void debugger_console::vprintf(util::format_argument_pack<std::ostream> const &a m_machine.debug_view().update_all(DVT_CONSOLE); } -void debugger_console::vprintf(util::format_argument_pack<std::ostream> &&args) +void debugger_console::vprintf(util::format_argument_pack<char> &&args) { print_core(util::string_format(std::move(args))); @@ -619,7 +1108,7 @@ void debugger_console::vprintf(util::format_argument_pack<std::ostream> &&args) // using the format to the debug console //------------------------------------------------- -void debugger_console::vprintf_wrap(int wrapcol, util::format_argument_pack<std::ostream> const &args) +void debugger_console::vprintf_wrap(int wrapcol, util::format_argument_pack<char> const &args) { print_core_wrap(util::string_format(args), wrapcol); @@ -627,7 +1116,7 @@ void debugger_console::vprintf_wrap(int wrapcol, util::format_argument_pack<std: m_machine.debug_view().update_all(DVT_CONSOLE); } -void debugger_console::vprintf_wrap(int wrapcol, util::format_argument_pack<std::ostream> &&args) +void debugger_console::vprintf_wrap(int wrapcol, util::format_argument_pack<char> &&args) { print_core_wrap(util::string_format(std::move(args)), wrapcol); diff --git a/src/emu/debug/debugcon.h b/src/emu/debug/debugcon.h index 5c7b521426f..37b2e235348 100644 --- a/src/emu/debug/debugcon.h +++ b/src/emu/debug/debugcon.h @@ -30,10 +30,6 @@ constexpr u32 CMDFLAG_NONE = 0x0000; constexpr u32 CMDFLAG_KEEP_QUOTES = 0x0001; constexpr u32 CMDFLAG_CUSTOM_HELP = 0x0002; -// parameter separator macros -#define CMDPARAM_SEPARATOR "\0" -#define CMDPARAM_TERMINATOR "\0\0" - /*************************************************************************** @@ -88,10 +84,10 @@ public: void process_source_file(); // console management - void vprintf(util::format_argument_pack<std::ostream> const &args); - void vprintf(util::format_argument_pack<std::ostream> &&args); - void vprintf_wrap(int wrapcol, util::format_argument_pack<std::ostream> const &args); - void vprintf_wrap(int wrapcol, util::format_argument_pack<std::ostream> &&args); + void vprintf(util::format_argument_pack<char> const &args); + void vprintf(util::format_argument_pack<char> &&args); + void vprintf_wrap(int wrapcol, util::format_argument_pack<char> const &args); + void vprintf_wrap(int wrapcol, util::format_argument_pack<char> &&args); text_buffer &get_console_textbuf() const { return *m_console_textbuf; } // errorlog management @@ -110,12 +106,39 @@ public: vprintf_wrap(wrapcol, util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...)); } - device_t *get_visible_cpu() { return m_visiblecpu; } + device_t *get_visible_cpu() const { return m_visiblecpu; } void set_visible_cpu(device_t *visiblecpu) { m_visiblecpu = visiblecpu; } - symbol_table &visible_symtable(); + symbol_table &visible_symtable() const; static std::string cmderr_to_string(CMDERR error); + // validates a parameter as a boolean value + bool validate_boolean_parameter(std::string_view param, bool &result); + + // validates a parameter as a numeric value + bool validate_number_parameter(std::string_view param, u64 &result); + + // validates a parameter as a device + bool validate_device_parameter(std::string_view param, device_t *&result); + + // validates a parameter as a CPU + bool validate_cpu_parameter(std::string_view param, device_t *&result); + + // validates a parameter as an address space identifier + bool validate_device_space_parameter(std::string_view param, int spacenum, address_space *&result); + + // validates a parameter as a target address and retrieves the given address space and address + bool validate_target_address_parameter(std::string_view param, int spacenum, address_space *&space, u64 &addr); + + // validates a parameter as a memory region name and retrieves the given region + bool validate_memory_region_parameter(std::string_view param, memory_region *&result); + + // validates a parameter as a debugger expression + bool validate_expression_parameter(std::string_view param, parsed_expression &result); + + // validates a parameter as a debugger command + bool validate_command_parameter(std::string_view param); + private: void exit(); @@ -129,6 +152,9 @@ private: void print_core(std::string_view text); // core text output void print_core_wrap(std::string_view text, int wrapcol); // core text output + device_t &get_device_search_base(std::string_view ¶m) const; + device_t *get_cpu_by_index(u64 cpunum) const; + struct debug_command { debug_command(std::string_view _command, u32 _flags, int _minparams, int _maxparams, std::function<void (const std::vector<std::string_view> &)> &&_handler); diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp index 429f5766d68..fd0093bd283 100644 --- a/src/emu/debug/debugcpu.cpp +++ b/src/emu/debug/debugcpu.cpp @@ -20,11 +20,11 @@ #include "debugger.h" #include "emuopts.h" #include "fileio.h" +#include "main.h" #include "screen.h" #include "uiinput.h" #include "corestr.h" -#include "coreutil.h" #include "osdepend.h" #include "xmlfile.h" @@ -93,7 +93,7 @@ debugger_cpu::debugger_cpu(running_machine &machine) for (int regnum = 0; regnum < NUM_TEMP_VARIABLES; regnum++) { char symname[10]; - sprintf(symname, "temp%d", regnum); + snprintf(symname, 10, "temp%d", regnum); m_symtable->add(symname, symbol_table::READ_WRITE, &m_tempvar[regnum]); } } @@ -387,7 +387,7 @@ void debugger_cpu::go_vblank() m_execution_state = exec_state::RUNNING; } -void debugger_cpu::halt_on_next_instruction(device_t *device, util::format_argument_pack<std::ostream> &&args) +void debugger_cpu::halt_on_next_instruction(device_t *device, util::format_argument_pack<char> &&args) { // if something is pending on this CPU already, ignore this request if (device == m_breakcpu) @@ -636,15 +636,46 @@ void device_debug::stop_hook() // acknowledged //------------------------------------------------- -void device_debug::interrupt_hook(int irqline) +void device_debug::interrupt_hook(int irqline, offs_t pc) { // see if this matches a pending interrupt request if ((m_flags & DEBUG_FLAG_STOP_INTERRUPT) != 0 && (m_stopirq == -1 || m_stopirq == irqline)) { m_device.machine().debugger().cpu().set_execution_stopped(); - m_device.machine().debugger().console().printf("Stopped on interrupt (CPU '%s', IRQ %d)\n", m_device.tag(), irqline); + const address_space &space = m_memory->space(AS_PROGRAM); + if (space.is_octal()) + m_device.machine().debugger().console().printf("Stopped on interrupt (CPU '%s', IRQ %d, PC=%0*o)\n", m_device.tag(), irqline, (space.logaddr_width() + 2) / 3, pc); + else + m_device.machine().debugger().console().printf("Stopped on interrupt (CPU '%s', IRQ %d, PC=%0*X)\n", m_device.tag(), irqline, space.logaddrchars(), pc); compute_debug_flags(); } + + if (m_trace != nullptr) + m_trace->interrupt_update(irqline, pc); + + if ((m_flags & (DEBUG_FLAG_STEPPING_OVER | DEBUG_FLAG_STEPPING_OUT | DEBUG_FLAG_STEPPING_BRANCH)) != 0) + { + if ((m_flags & DEBUG_FLAG_CALL_IN_PROGRESS) == 0) + { + if ((m_flags & DEBUG_FLAG_TEST_IN_PROGRESS) != 0) + { + if ((m_stepaddr == pc && (m_flags & DEBUG_FLAG_STEPPING_BRANCH_FALSE) != 0) || + (m_stepaddr != pc && m_delay_steps == 1 && (m_flags & (DEBUG_FLAG_STEPPING_OUT | DEBUG_FLAG_STEPPING_BRANCH_TRUE)) != 0)) + { + // step over the interrupt and then call it finished + m_flags = (m_flags & ~(DEBUG_FLAG_TEST_IN_PROGRESS | DEBUG_FLAG_STEPPING_ANY)) | DEBUG_FLAG_STEPPING_OVER; + m_stepsleft = 1; + } + } + + // remember the interrupt return address + m_flags |= DEBUG_FLAG_CALL_IN_PROGRESS; + m_stepaddr = pc; + } + + m_flags &= ~DEBUG_FLAG_TEST_IN_PROGRESS; + m_delay_steps = 0; + } } @@ -674,7 +705,7 @@ void device_debug::exception_hook(int exception) if (matched) { m_device.machine().debugger().cpu().set_execution_stopped(); - m_device.machine().debugger().console().printf("Stopped on exception (CPU '%s', exception %X, PC=%X)\n", m_device.tag(), exception, m_state->pcbase()); + m_device.machine().debugger().console().printf("Stopped on exception (CPU '%s', exception %X, PC=%s)\n", m_device.tag(), exception, m_state->state_string(STATE_GENPC)); compute_debug_flags(); } } @@ -700,7 +731,7 @@ void device_debug::exception_hook(int exception) if (debugcpu.is_stopped()) { debugcpu.set_execution_stopped(); - m_device.machine().debugger().console().printf("Stopped at exception point %X (CPU '%s', PC=%X)\n", ep.m_index, m_device.tag(), exception, m_state->pcbase()); + m_device.machine().debugger().console().printf("Stopped at exception point %X (CPU '%s', PC=%s)\n", ep.m_index, m_device.tag(), m_state->state_string(STATE_GENPC)); compute_debug_flags(); } break; @@ -798,7 +829,7 @@ void device_debug::instruction_hook(offs_t curpc) m_delay_steps--; if (m_delay_steps == 0) { - // branch taken or subroutine entered (TODO: interrupt acknowledgment or interleaved multithreading can falsely trigger this) + // branch taken or subroutine entered (TODO: interleaved multithreading can falsely trigger this) if ((m_flags & DEBUG_FLAG_TEST_IN_PROGRESS) != 0 && (m_flags & (DEBUG_FLAG_STEPPING_OUT | DEBUG_FLAG_STEPPING_BRANCH_TRUE)) != 0) { debugcpu.set_execution_stopped(); @@ -846,7 +877,10 @@ void device_debug::instruction_hook(offs_t curpc) // check the temp running breakpoint and break if we hit it else if ((m_flags & DEBUG_FLAG_STOP_PC) != 0 && m_stopaddr == curpc) { - machine.debugger().console().printf("Stopped at temporary breakpoint %X on CPU '%s'\n", m_stopaddr, m_device.tag()); + if (is_octal()) + machine.debugger().console().printf("Stopped at temporary breakpoint %o on CPU '%s'\n", m_stopaddr, m_device.tag()); + else + machine.debugger().console().printf("Stopped at temporary breakpoint %X on CPU '%s'\n", m_stopaddr, m_device.tag()); debugcpu.set_execution_stopped(); } @@ -1141,7 +1175,7 @@ void device_debug::go_branch(bool sense, const char *condition) // to templates in C++ being janky as all get out //------------------------------------------------- -void device_debug::halt_on_next_instruction_impl(util::format_argument_pack<std::ostream> &&args) +void device_debug::halt_on_next_instruction_impl(util::format_argument_pack<char> &&args) { assert(m_exec != nullptr); m_device.machine().debugger().cpu().halt_on_next_instruction(&m_device, std::move(args)); @@ -1692,7 +1726,7 @@ u32 device_debug::compute_opcode_crc32(offs_t pc) const buffer.data_get(pc, dasmresult & util::disasm_interface::LENGTHMASK, true, opbuf); // return a CRC of the exact count of opcode bytes - return core_crc32(0, &opbuf[0], opbuf.size()); + return util::crc32_creator::simple(&opbuf[0], opbuf.size()); } @@ -2015,10 +2049,36 @@ void device_debug::tracer::update(offs_t pc) //------------------------------------------------- +// interrupt_update - log interrupt to tracefile +//------------------------------------------------- + +void device_debug::tracer::interrupt_update(int irqline, offs_t pc) +{ + if (m_trace_over) + { + if (m_trace_over_target != ~0) + return; + m_trace_over_target = pc; + } + + // if we just finished looping, indicate as much + *m_file << "\n"; + if (m_detect_loops && m_loops != 0) + { + util::stream_format(*m_file, " (loops for %d instructions)\n", m_loops); + m_loops = 0; + } + + util::stream_format(*m_file, " (interrupted at %s, IRQ %d)\n\n", debug_disasm_buffer(m_debug.device()).pc_to_string(pc), irqline); + m_file->flush(); +} + + +//------------------------------------------------- // vprintf - generic print to the trace file //------------------------------------------------- -void device_debug::tracer::vprintf(util::format_argument_pack<std::ostream> const &args) +void device_debug::tracer::vprintf(util::format_argument_pack<char> const &args) { // pass through to the file util::stream_format(*m_file, args); diff --git a/src/emu/debug/debugcpu.h b/src/emu/debug/debugcpu.h index 416581071a7..9a9f6e69f70 100644 --- a/src/emu/debug/debugcpu.h +++ b/src/emu/debug/debugcpu.h @@ -51,7 +51,7 @@ public: // hooks used by the rest of the system void start_hook(const attotime &endtime); void stop_hook(); - void interrupt_hook(int irqline); + void interrupt_hook(int irqline, offs_t pc); void exception_hook(int exception); void privilege_hook(); void instruction_hook(offs_t curpc); @@ -165,7 +165,7 @@ public: void compute_debug_flags(); private: - void halt_on_next_instruction_impl(util::format_argument_pack<std::ostream> &&args); + void halt_on_next_instruction_impl(util::format_argument_pack<char> &&args); // internal helpers void prepare_for_step_overout(offs_t pc); @@ -227,7 +227,8 @@ private: ~tracer(); void update(offs_t pc); - void vprintf(util::format_argument_pack<std::ostream> const &args); + void interrupt_update(int irqline, offs_t pc); + void vprintf(util::format_argument_pack<char> const &args); void flush(); bool logerror() const { return m_logerror; } @@ -405,7 +406,7 @@ public: void stop_hook(device_t *device); void go_next_device(device_t *device); void go_vblank(); - void halt_on_next_instruction(device_t *device, util::format_argument_pack<std::ostream> &&args); + void halt_on_next_instruction(device_t *device, util::format_argument_pack<char> &&args); void ensure_comments_loaded(); void reset_transient_flags(); diff --git a/src/emu/debug/debughlp.cpp b/src/emu/debug/debughlp.cpp index 85de3984020..76102402bcb 100644 --- a/src/emu/debug/debughlp.cpp +++ b/src/emu/debug/debughlp.cpp @@ -139,6 +139,7 @@ const help_item f_static_help_list[] = " gn[i] [<count>] -- resumes execution, sets temp breakpoint <count> instructions ahead\n" " ge[x] [<exception>[,<condition>]] -- resumes execution, setting temp breakpoint if <exception> is raised\n" " gi[nt] [<irqline>] -- resumes execution, setting temp breakpoint if <irqline> is taken (F7)\n" + " gp [<condition>] -- resumes execution, setting temp breakpoint if privilege level changes\n" " gt[ime] <milliseconds> -- resumes execution until the given delay has elapsed\n" " gv[blank] -- resumes execution, setting temp breakpoint on the next VBLANK (F8)\n" " n[ext] -- executes until the next CPU switch (F6)\n" @@ -201,7 +202,7 @@ const help_item f_static_help_list[] = " epclear [<epnum>] -- clears a given exception point or all if no <epnum> specified\n" " epdisable [<epnum>] -- disabled a given exception point or all if no <epnum> specified\n" " epenable [<epnum>] -- enables a given exception point or all if no <epnum> specified\n" - " eplist -- lists all the registerpoints\n" + " eplist -- lists all the exception points\n" }, { "expressions", @@ -358,16 +359,20 @@ const help_item f_static_help_list[] = "The printf command performs a C-style printf to the debugger console. Only a very limited set of " "formatting options are available:\n" "\n" - " %[0][<n>]d -- prints <item> as a decimal value with optional digit count and zero-fill\n" - " %[0][<n>]x -- prints <item> as a hexadecimal value with optional digit count and zero-fill\n" + " %c -- 8-bit character\n" + " %[-][0][<n>]d -- decimal number with optional left justification, zero fill and minimum width\n" + " %[-][0][<n>]o -- octal number with optional left justification, zero fill and minimum width\n" + " %[-][0][<n>]x -- lowercase hexadecimal number with optional left justification, zero fill and minimum width\n" + " %[-][0][<n>]X -- uppercase hexadecimal number with optional left justification, zero fill and minimum width\n" + " %[-][<n>][.[<n>]]s -- null-terminated string of 8-bit characters with optional left justification, minimum and maximum width\n" "\n" - "All remaining formatting options are ignored. Use %% together to output a % character. Multiple " - "lines can be printed by embedding a \\n in the text.\n" + "All remaining formatting options are ignored. Use %% to output a % character. Multiple lines can be " + "printed by embedding a \\n in the text.\n" "\n" "Examples:\n" "\n" "printf \"PC=%04X\",pc\n" - " Prints PC=<pcval> where <pcval> is displayed in hexadecimal with 4 digits with zero-fill.\n" + " Prints PC=<pcval> where <pcval> is displayed in uppercase hexadecimal with 4 digits and zero fill.\n" "\n" "printf \"A=%d, B=%d\\nC=%d\",a,b,a+b\n" " Prints A=<aval>, B=<bval> on one line, and C=<a+bval> on a second line.\n" @@ -378,18 +383,12 @@ const help_item f_static_help_list[] = " logerror <format>[,<item>[,...]]\n" "\n" "The logerror command performs a C-style printf to the error log. Only a very limited set of " - "formatting options are available:\n" - "\n" - " %[0][<n>]d -- logs <item> as a decimal value with optional digit count and zero-fill\n" - " %[0][<n>]x -- logs <item> as a hexadecimal value with optional digit count and zero-fill\n" - "\n" - "All remaining formatting options are ignored. Use %% together to output a % character. Multiple " - "lines can be printed by embedding a \\n in the text.\n" + "formatting options are available. See the 'printf' help for details.\n" "\n" "Examples:\n" "\n" - "logerror \"PC=%04X\",pc\n" - " Logs PC=<pcval> where <pcval> is displayed in hexadecimal with 4 digits with zero-fill.\n" + "logerror \"PC=%04x\",pc\n" + " Logs PC=<pcval> where <pcval> is displayed in lowercase hexadecimal with 4 digits and zero fill.\n" "\n" "logerror \"A=%d, B=%d\\nC=%d\",a,b,a+b\n" " Logs A=<aval>, B=<bval> on one line, and C=<a+bval> on a second line.\n" @@ -1049,6 +1048,27 @@ const help_item f_static_help_list[] = "acknowledged on the current CPU.\n" }, { + "gp", + "\n" + " gp [<condition>]\n" + "\n" + "The gp command resumes execution of the current code. Control will not be returned to " + "the debugger until a breakpoint or watchpoint is hit, or the privilege level of the current " + "CPU changes. The optional <condition> parameter lets you specify an expression that will " + "be evaluated each time the privilege level changes. If the expression evaluates to true " + "(non-zero), execution will halt; otherwise, execution will continue with no notification.\n" + "\n" + "Examples:\n" + "\n" + "gp\n" + " Resume execution until the next break/watchpoint or the privilege level of the current " + "CPU changes.\n" + "\n" + "gp {pc != 1234}\n" + " Resume execution until the next break/watchpoint or the privilege level of the current " + "CPU changes, disregarding the instruction at address 1234.\n" + }, + { "gtime", "\n" " gt[ime] <milliseconds>\n" @@ -2023,10 +2043,12 @@ private: help_map m_help_list; help_item const *m_uncached_help = std::begin(f_static_help_list); + util::ovectorstream m_message_buffer; + help_manager() = default; public: - char const *find(std::string_view tag) + std::string_view find(std::string_view tag) { // find a cached exact match if possible std::string const lower = strmakelower(tag); @@ -2062,16 +2084,17 @@ public: if ((m_help_list.end() == next) || (next->first.substr(0, lower.length()) != lower)) return candidate->second; - // TODO: pointers to static strings are bad, mmmkay? - static char ambig_message[1024]; - int msglen = std::sprintf(ambig_message, "Ambiguous help request, did you mean:\n"); + m_message_buffer.clear(); + m_message_buffer.reserve(1024); + m_message_buffer.seekp(0, util::ovectorstream::beg); + m_message_buffer << "Ambiguous help request, did you mean:\n"; do { - msglen += std::sprintf(&ambig_message[msglen], " help %.*s?\n", int(candidate->first.length()), &candidate->first[0]); + util::stream_format(m_message_buffer, " help %.*s?\n", int(candidate->first.length()), &candidate->first[0]); ++candidate; } while ((m_help_list.end() != candidate) && (candidate->first.substr(0, lower.length()) == lower)); - return ambig_message; + return util::buf_to_string_view(m_message_buffer); } // take the first help entry if no matches at all @@ -2093,7 +2116,7 @@ public: PUBLIC INTERFACE ***************************************************************************/ -const char *debug_get_help(std::string_view tag) +std::string_view debug_get_help(std::string_view tag) { return help_manager::instance().find(tag); } diff --git a/src/emu/debug/debughlp.h b/src/emu/debug/debughlp.h index 495d674eb0d..9efe12acaca 100644 --- a/src/emu/debug/debughlp.h +++ b/src/emu/debug/debughlp.h @@ -21,6 +21,6 @@ ***************************************************************************/ // help management -const char *debug_get_help(std::string_view tag); +std::string_view debug_get_help(std::string_view tag); #endif // MAME_EMU_DEBUG_DEBUGHLP_H diff --git a/src/emu/debug/dvmemory.cpp b/src/emu/debug/dvmemory.cpp index 1f1adcb138d..da792305c0d 100644 --- a/src/emu/debug/dvmemory.cpp +++ b/src/emu/debug/dvmemory.cpp @@ -309,7 +309,7 @@ void debug_view_memory::generate_row(debug_view_char *destmin, debug_view_char * // generate the address char addrtext[20]; - sprintf(addrtext, m_addrformat.c_str(), address); + snprintf(addrtext, 20, m_addrformat.c_str(), address); debug_view_char *dest = destrow + m_section[0].m_pos + 1; for (int ch = 0; addrtext[ch] != 0 && ch < m_section[0].m_width - 1; ch++, dest++) if (dest >= destmin && dest < destmax) @@ -359,15 +359,15 @@ void debug_view_memory::generate_row(debug_view_char *destmin, debug_view_char * switch (m_data_format) { case data_format::FLOAT_32BIT: - sprintf(valuetext, "%.8g", u32_to_float(u32(chunkdata))); + snprintf(valuetext, 64, "%.8g", u32_to_float(u32(chunkdata))); break; case data_format::FLOAT_64BIT: - sprintf(valuetext, "%.24g", u64_to_double(chunkdata)); + snprintf(valuetext, 64, "%.24g", u64_to_double(chunkdata)); break; case data_format::FLOAT_80BIT: { float64_t f64 = extF80M_to_f64(&chunkdata80); - sprintf(valuetext, "%.24g", u64_to_double(f64.v)); + snprintf(valuetext, 64, "%.24g", u64_to_double(f64.v)); break; } default: @@ -862,14 +862,17 @@ bool debug_view_memory::read(u8 size, offs_t offs, u64 &data) auto dis = machine().disable_side_effects(); bool ismapped = offs <= m_maxaddr; + address_space *tspace; if (ismapped && !m_no_translation) { offs_t dummyaddr = offs; - ismapped = source.m_memintf->translate(source.m_space->spacenum(), TRANSLATE_READ_DEBUG, dummyaddr); + ismapped = source.m_memintf->translate(source.m_space->spacenum(), device_memory_interface::TR_READ, dummyaddr, tspace); } + else + tspace = source.m_space; data = ~u64(0); if (ismapped) - data = m_expression.context().read_memory(*source.m_space, offs, size, !m_no_translation); + data = m_expression.context().read_memory(*tspace, offs, size, !m_no_translation); return ismapped; } diff --git a/src/emu/debug/express.cpp b/src/emu/debug/express.cpp index f9074147b7b..0d711d676d2 100644 --- a/src/emu/debug/express.cpp +++ b/src/emu/debug/express.cpp @@ -482,23 +482,25 @@ u64 symbol_table::read_memory(address_space &space, offs_t address, int size, bo { u64 result = ~u64(0) >> (64 - 8*size); + address_space *tspace = &space; + if (apply_translation) { // mask against the logical byte mask address &= space.logaddrmask(); // translate if necessary; if not mapped, return 0xffffffffffffffff - if (!space.device().memory().translate(space.spacenum(), TRANSLATE_READ_DEBUG, address)) + if (!space.device().memory().translate(space.spacenum(), device_memory_interface::TR_READ, address, tspace)) return result; } // otherwise, call the reading function for the translated address switch (size) { - case 1: result = space.read_byte(address); break; - case 2: result = space.read_word_unaligned(address); break; - case 4: result = space.read_dword_unaligned(address); break; - case 8: result = space.read_qword_unaligned(address); break; + case 1: result = tspace->read_byte(address); break; + case 2: result = tspace->read_word_unaligned(address); break; + case 4: result = tspace->read_dword_unaligned(address); break; + case 8: result = tspace->read_qword_unaligned(address); break; } return result; } @@ -511,23 +513,25 @@ u64 symbol_table::read_memory(address_space &space, offs_t address, int size, bo void symbol_table::write_memory(address_space &space, offs_t address, u64 data, int size, bool apply_translation) { + address_space *tspace = &space; + if (apply_translation) { // mask against the logical byte mask address &= space.logaddrmask(); // translate if necessary; if not mapped, we're done - if (!space.device().memory().translate(space.spacenum(), TRANSLATE_WRITE_DEBUG, address)) + if (!space.device().memory().translate(space.spacenum(), device_memory_interface::TR_WRITE, address, tspace)) return; } // otherwise, call the writing function for the translated address switch (size) { - case 1: space.write_byte(address, data); break; - case 2: space.write_word_unaligned(address, data); break; - case 4: space.write_dword_unaligned(address, data); break; - case 8: space.write_qword_unaligned(address, data); break; + case 1: tspace->write_byte(address, data); break; + case 2: tspace->write_word_unaligned(address, data); break; + case 4: tspace->write_dword_unaligned(address, data); break; + case 8: tspace->write_qword_unaligned(address, data); break; } notify_memory_modified(); diff --git a/src/emu/debug/express.h b/src/emu/debug/express.h index 74b52710959..251d8b4365c 100644 --- a/src/emu/debug/express.h +++ b/src/emu/debug/express.h @@ -86,17 +86,19 @@ public: }; // construction/destruction - expression_error(error_code code, int offset = 0, int num = 0) - : m_code(code), - m_offset(offset), - m_num(num) { } + constexpr expression_error(error_code code, int offset = 0, int num = 0) + : m_code(code) + , m_offset(offset) + , m_num(num) + { + } // operators - operator error_code() const { return m_code; } + constexpr operator error_code() const { return m_code; } // getters - error_code code() const { return m_code; } - int offset() const { return m_offset; } + constexpr error_code code() const { return m_code; } + constexpr int offset() const { return m_offset; } std::string code_string() const; private: diff --git a/src/emu/devcb.cpp b/src/emu/devcb.cpp index 19970f45c5f..b6e08f13b45 100644 --- a/src/emu/devcb.cpp +++ b/src/emu/devcb.cpp @@ -257,7 +257,6 @@ template class devcb_write8::creator_impl<devcb_write8::latched_inputline_builde template class devcb_write8::creator_impl<devcb_write8::ioport_builder>; template class devcb_write8::creator_impl<devcb_write8::membank_builder>; template class devcb_write8::creator_impl<devcb_write8::output_builder>; -template class devcb_write8::creator_impl<devcb_write8::log_builder>; template class devcb_write16::creator_impl<devcb_write16::delegate_builder<write8s_delegate> >; template class devcb_write16::creator_impl<devcb_write16::delegate_builder<write16s_delegate> >; @@ -277,7 +276,6 @@ template class devcb_write16::creator_impl<devcb_write16::latched_inputline_buil template class devcb_write16::creator_impl<devcb_write16::ioport_builder>; template class devcb_write16::creator_impl<devcb_write16::membank_builder>; template class devcb_write16::creator_impl<devcb_write16::output_builder>; -template class devcb_write16::creator_impl<devcb_write16::log_builder>; template class devcb_write32::creator_impl<devcb_write32::delegate_builder<write8s_delegate> >; template class devcb_write32::creator_impl<devcb_write32::delegate_builder<write16s_delegate> >; @@ -297,7 +295,6 @@ template class devcb_write32::creator_impl<devcb_write32::latched_inputline_buil template class devcb_write32::creator_impl<devcb_write32::ioport_builder>; template class devcb_write32::creator_impl<devcb_write32::membank_builder>; template class devcb_write32::creator_impl<devcb_write32::output_builder>; -template class devcb_write32::creator_impl<devcb_write32::log_builder>; template class devcb_write64::creator_impl<devcb_write64::delegate_builder<write8s_delegate> >; template class devcb_write64::creator_impl<devcb_write64::delegate_builder<write16s_delegate> >; @@ -317,7 +314,6 @@ template class devcb_write64::creator_impl<devcb_write64::latched_inputline_buil template class devcb_write64::creator_impl<devcb_write64::ioport_builder>; template class devcb_write64::creator_impl<devcb_write64::membank_builder>; template class devcb_write64::creator_impl<devcb_write64::output_builder>; -template class devcb_write64::creator_impl<devcb_write64::log_builder>; template class devcb_write_line::creator_impl<devcb_write_line::delegate_builder<write8s_delegate> >; template class devcb_write_line::creator_impl<devcb_write_line::delegate_builder<write16s_delegate> >; @@ -337,11 +333,11 @@ template class devcb_write_line::creator_impl<devcb_write_line::latched_inputlin template class devcb_write_line::creator_impl<devcb_write_line::ioport_builder>; template class devcb_write_line::creator_impl<devcb_write_line::membank_builder>; template class devcb_write_line::creator_impl<devcb_write_line::output_builder>; -template class devcb_write_line::creator_impl<devcb_write_line::log_builder>; devcb_base::devcb_base(device_t &owner) - : m_owner(owner) + : device_resolver_base(owner) + , m_owner(owner) { } diff --git a/src/emu/devcb.h b/src/emu/devcb.h index 7638f901296..be62d8b6365 100644 --- a/src/emu/devcb.h +++ b/src/emu/devcb.h @@ -64,11 +64,8 @@ template <typename T> struct rw_delegate_type<T, void_t<rw_device_class_t<write_ /// /// Provides utilities for supporting multiple read/write/transform /// signatures, and the base exclusive-or/mask transform methods. -class devcb_base +class devcb_base : protected device_resolver_base { -public: - virtual void validity_check(validity_checker &valid) const = 0; - protected: // This is in C++17 but not C++14 template <typename... T> struct void_wrapper { using type = void; }; @@ -174,9 +171,9 @@ protected: class array : public std::array<T, Count> { private: - template <unsigned... V> - array(device_t &owner, std::integer_sequence<unsigned, V...> const &) - : std::array<T, Count>{{ { make_one<V>(owner) }... }} + template <unsigned... V, typename... Params> + array(device_t &owner, std::integer_sequence<unsigned, V...>, Params &&... args) + : std::array<T, Count>{{ { make_one<V>(owner), std::forward<Params>(args)... }... }} { } @@ -185,12 +182,10 @@ protected: public: using std::array<T, Count>::array; - array(device_t &owner) : array(owner, std::make_integer_sequence<unsigned, Count>()) { } - - void resolve_all() + template <typename... Params> + array(device_t &owner, Params &&... args) + : array(owner, std::make_integer_sequence<unsigned, Count>(), std::forward<Params>(args)...) { - for (T &elem : *this) - elem.resolve(); } }; @@ -336,7 +331,7 @@ private: using ptr = std::unique_ptr<creator>; virtual ~creator() { } - virtual void validity_check(validity_checker &valid) const = 0; + virtual bool validity_check(validity_checker &valid) const = 0; virtual func_t create() = 0; std::make_unsigned_t<Result> mask() const { return m_mask; } @@ -353,7 +348,7 @@ private: public: creator_impl(T &&builder) : creator(builder.mask()), m_builder(std::move(builder)) { } - virtual void validity_check(validity_checker &valid) const override { m_builder.validity_check(valid); } + virtual bool validity_check(validity_checker &valid) const override { return m_builder.validity_check(valid); } virtual func_t create() override { @@ -366,28 +361,6 @@ private: T m_builder; }; - class log_creator : public creator - { - public: - log_creator(device_t &devbase, std::string &&message) : creator(0U), m_devbase(devbase), m_message(std::move(message)) { } - - virtual void validity_check(validity_checker &valid) const override { } - - virtual func_t create() override - { - return - [&devbase = m_devbase, message = std::move(m_message)] (offs_t offset, std::make_unsigned_t<Result> mem_mask) - { - devbase.logerror("%s: %s\n", devbase.machine().describe_context(), message); - return Result(0); - }; - } - - private: - device_t &m_devbase; - std::string m_message; - }; - template <typename Source, typename Func> class transform_builder; // workaround for MSVC class builder_base @@ -467,7 +440,7 @@ private: return transform_builder<transform_builder, std::remove_reference_t<T> >(this->m_target, this->m_append, std::move(*this), std::forward<T>(cb), m); } - void validity_check(validity_checker &valid) const { m_src.validity_check(valid); } + bool validity_check(validity_checker &valid) const { return m_src.validity_check(valid); } template <typename T> void build(T &&chain) @@ -535,7 +508,7 @@ private: return transform_builder<functoid_builder, std::remove_reference_t<T> >(this->m_target, this->m_append, std::move(*this), std::forward<T>(cb), m); } - void validity_check(validity_checker &valid) const { } + bool validity_check(validity_checker &valid) const { return true; } template <typename T> void build(T &&chain) @@ -595,11 +568,15 @@ private: return transform_builder<delegate_builder, std::remove_reference_t<T> >(this->m_target, this->m_append, std::move(*this), std::forward<T>(cb), m); } - void validity_check(validity_checker &valid) const + bool validity_check(validity_checker &valid) const { auto const target(m_delegate.finder_target()); if (target.second && !target.first.subdevice(target.second)) + { osd_printf_error("Read callback bound to non-existent object tag %s (%s)\n", target.first.subtag(target.second), m_delegate.name()); + return false; + } + return true; } template <typename T> @@ -655,7 +632,7 @@ private: return transform_builder<ioport_builder, std::remove_reference_t<T> >(this->m_target, this->m_append, std::move(*this), std::forward<T>(cb), m); } - void validity_check(validity_checker &valid) const { } + bool validity_check(validity_checker &valid) const { return true; } template <typename T> void build(T &&chain) @@ -716,6 +693,13 @@ private: return delegate_builder<delegate_type_t<T> >(m_target, m_append, m_target.owner(), devcb_read::cast_reference<delegate_device_class_t<T> >(obj), std::forward<T>(func), name); } + template <typename T> + std::enable_if_t<is_read_method<T>::value, delegate_builder<delegate_type_t<T> > > set(device_t &devbase, char const *tag, T &&func, char const *name) + { + set_used(); + return delegate_builder<delegate_type_t<T> >(m_target, m_append, devbase, tag, std::forward<T>(func), name); + } + template <typename T, typename U, bool R> std::enable_if_t<is_read_method<T>::value, delegate_builder<delegate_type_t<T> > > set(device_finder<U, R> &finder, T &&func, char const *name) { @@ -769,40 +753,6 @@ private: return set_ioport(std::forward<Params>(args)...); } - template <typename... Params> - void set_log(device_t &devbase, Params &&... args) - { - set_used(); - if (!m_append) - m_target.m_creators.clear(); - m_target.m_creators.emplace_back(std::make_unique<log_creator>(devbase, std::string(std::forward<Params>(args)...))); - } - - template <typename T, typename... Params> - std::enable_if_t<emu::detail::is_device_implementation<std::remove_reference_t<T> >::value> set_log(T &devbase, Params &&... args) - { - set_log(static_cast<device_t &>(devbase), std::forward<Params>(args)...); - } - - template <typename T, typename... Params> - std::enable_if_t<emu::detail::is_device_interface<std::remove_reference_t<T> >::value> set_log(T &devbase, Params &&... args) - { - set_log(devbase.device(), std::forward<Params>(args)...); - } - - template <typename... Params> - void set_log(Params &&... args) - { - set_log(m_target.owner().mconfig().current_device(), std::forward<Params>(args)...); - } - - template <typename... Params> - void append_log(Params &&... args) - { - m_append = true; - set_log(std::forward<Params>(args)...); - } - auto set_constant(Result val) { return set([val] () { return val; }); } auto append_constant(Result val) { return append([val] () { return val; }); } @@ -816,47 +766,46 @@ private: std::vector<func_t> m_functions; std::vector<typename creator::ptr> m_creators; + Result const m_default; + bool m_unset = false; + +protected: + virtual bool findit(validity_checker *valid) override; + virtual void end_configuration() override; public: template <unsigned Count> class array : public devcb_read_base::array<devcb_read<Result, DefaultMask>, Count> { public: - using devcb_read_base::array<devcb_read<Result, DefaultMask>, Count>::array; - - void resolve_all_safe(Result dflt) + array(device_t &owner, Result dflt) + : devcb_read_base::array<devcb_read<Result, DefaultMask>, Count>::array(owner, dflt) { - for (devcb_read<Result, DefaultMask> &elem : *this) - elem.resolve_safe(dflt); } }; - devcb_read(device_t &owner); + devcb_read(device_t &owner, Result dflt); binder bind(); void reset(); - virtual void validity_check(validity_checker &valid) const override; - - void resolve(); - void resolve_safe(Result dflt); - Result operator()(offs_t offset, std::make_unsigned_t<Result> mem_mask = DefaultMask); Result operator()(); - bool isnull() const { return m_functions.empty() && m_creators.empty(); } - explicit operator bool() const { return !m_functions.empty(); } + bool isunset() const noexcept { return m_unset || (m_functions.empty() && m_creators.empty()); } }; template <typename Result, std::make_unsigned_t<Result> DefaultMask> -devcb_read<Result, DefaultMask>::devcb_read(device_t &owner) +devcb_read<Result, DefaultMask>::devcb_read(device_t &owner, Result dflt) : devcb_read_base(owner) + , m_default(dflt & DefaultMask) { } template <typename Result, std::make_unsigned_t<Result> DefaultMask> typename devcb_read<Result, DefaultMask>::binder devcb_read<Result, DefaultMask>::bind() { + assert(m_functions.empty()); return binder(*this); } @@ -868,38 +817,48 @@ void devcb_read<Result, DefaultMask>::reset() } template <typename Result, std::make_unsigned_t<Result> DefaultMask> -void devcb_read<Result, DefaultMask>::validity_check(validity_checker &valid) const +bool devcb_read<Result, DefaultMask>::findit(validity_checker *valid) { assert(m_functions.empty()); - for (typename std::vector<typename creator::ptr>::const_iterator i = m_creators.begin(); m_creators.end() != i; ++i) + if (!valid) { - (*i)->validity_check(valid); - std::make_unsigned_t<Result> const m((*i)->mask()); - for (typename std::vector<typename creator::ptr>::const_iterator j = std::next(i); m_creators.end() != j; ++j) + // FIXME: report errors by returning false rather than throwing fatal errors + m_functions.reserve(m_creators.size()); + for (typename creator::ptr const &c : m_creators) + m_functions.emplace_back(c->create()); + m_creators.clear(); + if (m_functions.empty()) { - std::make_unsigned_t<Result> const n((*j)->mask()); - if (m & n) - osd_printf_error("Read callback masks %lX and %lX overlap\n", static_cast<unsigned long>(m), static_cast<unsigned long>(n)); // FIXME: doesn't work with u64 + m_functions.emplace_back([dflt = m_default] (offs_t offset, std::make_unsigned_t<Result> mem_mask) { return dflt; }); + m_unset = true; } + return true; + } + else + { + bool success(true); + for (typename std::vector<typename creator::ptr>::const_iterator i = m_creators.begin(); m_creators.end() != i; ++i) + { + if (!(*i)->validity_check(*valid)) + success = false; + std::make_unsigned_t<Result> const m((*i)->mask()); + for (typename std::vector<typename creator::ptr>::const_iterator j = std::next(i); m_creators.end() != j; ++j) + { + std::make_unsigned_t<Result> const n((*j)->mask()); + if (m & n) + { + osd_printf_error("Read callback masks 0x%X and 0x%X overlap\n", m, n); + success = false; + } + } + } + return success; } } template <typename Result, std::make_unsigned_t<Result> DefaultMask> -void devcb_read<Result, DefaultMask>::resolve() -{ - assert(m_functions.empty()); - m_functions.reserve(m_creators.size()); - for (typename creator::ptr const &c : m_creators) - m_functions.emplace_back(c->create()); - m_creators.clear(); -} - -template <typename Result, std::make_unsigned_t<Result> DefaultMask> -void devcb_read<Result, DefaultMask>::resolve_safe(Result dflt) +void devcb_read<Result, DefaultMask>::end_configuration() { - resolve(); - if (m_functions.empty()) - m_functions.emplace_back([dflt] (offs_t offset, std::make_unsigned_t<Result> mem_mask) { return dflt; }); } template <typename Result, std::make_unsigned_t<Result> DefaultMask> @@ -937,7 +896,7 @@ private: using ptr = std::unique_ptr<creator>; virtual ~creator() { } - virtual void validity_check(validity_checker &valid) const = 0; + virtual bool validity_check(validity_checker &valid) const = 0; virtual func_t create() = 0; }; @@ -947,7 +906,7 @@ private: public: creator_impl(T &&builder) : m_builder(std::move(builder)) { } - virtual void validity_check(validity_checker &valid) const override { m_builder.validity_check(valid); } + virtual bool validity_check(validity_checker &valid) const override { return m_builder.validity_check(valid); } virtual func_t create() override { @@ -961,7 +920,7 @@ private: class nop_creator : public creator { public: - virtual void validity_check(validity_checker &valid) const override { } + virtual bool validity_check(validity_checker &valid) const override { return true; } virtual func_t create() override { return [] (offs_t offset, Input data, std::make_unsigned_t<Input> mem_mask) { }; } }; @@ -1060,7 +1019,7 @@ private: }); } - void validity_check(validity_checker &valid) const { m_src.validity_check(valid); } + bool validity_check(validity_checker &valid) const { return m_src.validity_check(valid); } private: transform_builder(transform_builder const &) = delete; @@ -1117,7 +1076,7 @@ private: } ~first_transform_builder() { this->template register_creator<first_transform_builder>(); } - void validity_check(validity_checker &valid) const { m_sink.validity_check(valid); } + bool validity_check(validity_checker &valid) const { return m_sink.validity_check(valid); } template <typename T> std::enable_if_t<is_transform<output_t, output_t, T>::value, transform_builder<first_transform_builder, std::remove_reference_t<T> > > transform(T &&cb) @@ -1184,7 +1143,7 @@ private: wrapped_builder(functoid_builder &&that) : builder_base(std::move(that)), m_cb(std::move(that.m_cb)) { that.consume(); that.built(); } wrapped_builder(wrapped_builder &&that) : builder_base(std::move(that)), m_cb(std::move(that.m_cb)) { that.consume(); that.built(); } - void validity_check(validity_checker &valid) const { } + bool validity_check(validity_checker &valid) const { return true; } auto build() { @@ -1234,7 +1193,7 @@ private: return first_transform_builder<wrapped_builder, std::remove_reference_t<T> >(this->m_target, this->m_append, wrapped_builder(std::move(*this)), std::forward<T>(cb), this->exor(), this->mask(), DefaultMask); } - void validity_check(validity_checker &valid) const { } + bool validity_check(validity_checker &valid) const { return true; } auto build() { @@ -1272,11 +1231,15 @@ private: that.built(); } - void validity_check(validity_checker &valid) const + bool validity_check(validity_checker &valid) const { auto const target(m_delegate.finder_target()); if (target.second && !target.first.subdevice(target.second)) + { osd_printf_error("Write callback bound to non-existent object tag %s (%s)\n", target.first.subtag(target.second), m_delegate.name()); + return false; + } + return true; } auto build() @@ -1338,11 +1301,15 @@ private: return first_transform_builder<wrapped_builder, std::remove_reference_t<T> >(this->m_target, this->m_append, wrapped_builder(std::move(*this)), std::forward<T>(cb), this->exor(), in_mask, out_mask); } - void validity_check(validity_checker &valid) const + bool validity_check(validity_checker &valid) const { auto const target(m_delegate.finder_target()); if (target.second && !target.first.subdevice(target.second)) + { osd_printf_error("Write callback bound to non-existent object tag %s (%s)\n", target.first.subtag(target.second), m_delegate.name()); + return false; + } + return true; } auto build() @@ -1387,16 +1354,23 @@ private: that.built(); } - void validity_check(validity_checker &valid) const + bool validity_check(validity_checker &valid) const { if (!m_exec) { device_t *const device(m_devbase.subdevice(m_tag)); if (!device) + { osd_printf_error("Write callback bound to non-existent object tag %s\n", m_tag); + return false; + } else if (!dynamic_cast<device_execute_interface *>(device)) + { osd_printf_error("Write callback bound to device %s (%s) that does not implement device_execute_interface\n", device->tag(), device->name()); + return false; + } } + return true; } auto build() @@ -1478,16 +1452,23 @@ private: return first_transform_builder<wrapped_builder, std::remove_reference_t<T> >(this->m_target, this->m_append, wrapped_builder(std::move(*this)), std::forward<T>(cb), this->exor(), in_mask, 1U); } - void validity_check(validity_checker &valid) const + bool validity_check(validity_checker &valid) const { if (!m_exec) { device_t *const device(m_devbase.subdevice(m_tag)); if (!device) + { osd_printf_error("Write callback bound to non-existent object tag %s\n", m_tag); + return false; + } else if (!dynamic_cast<device_execute_interface *>(device)) + { osd_printf_error("Write callback bound to device %s (%s) that does not implement device_execute_interface\n", device->tag(), device->name()); + return false; + } } + return true; } auto build() @@ -1542,16 +1523,23 @@ private: that.built(); } - void validity_check(validity_checker &valid) const + bool validity_check(validity_checker &valid) const { if (!m_exec) { device_t *const device(m_devbase.subdevice(m_tag)); if (!device) + { osd_printf_error("Write callback bound to non-existent object tag %s\n", m_tag); + return false; + } else if (!dynamic_cast<device_execute_interface *>(device)) + { osd_printf_error("Write callback bound to device %s (%s) that does not implement device_execute_interface\n", device->tag(), device->name()); + return false; + } } + return true; } auto build() @@ -1637,16 +1625,23 @@ private: return first_transform_builder<wrapped_builder, std::remove_reference_t<T> >(this->m_target, this->m_append, wrapped_builder(std::move(*this)), std::forward<T>(cb), this->exor(), this->mask(), DefaultMask); } - void validity_check(validity_checker &valid) const + bool validity_check(validity_checker &valid) const { if (!m_exec) { device_t *const device(m_devbase.subdevice(m_tag)); if (!device) + { osd_printf_error("Write callback bound to non-existent object tag %s\n", m_tag); + return false; + } else if (!dynamic_cast<device_execute_interface *>(device)) + { osd_printf_error("Write callback bound to device %s (%s) that does not implement device_execute_interface\n", device->tag(), device->name()); + return false; + } } + return true; } auto build() @@ -1695,7 +1690,7 @@ private: that.built(); } - void validity_check(validity_checker &valid) const { } + bool validity_check(validity_checker &valid) const { return true; } auto build() { @@ -1753,7 +1748,7 @@ private: return first_transform_builder<wrapped_builder, std::remove_reference_t<T> >(this->m_target, this->m_append, wrapped_builder(std::move(*this)), std::forward<T>(cb), this->exor(), this->mask(), DefaultMask); } - void validity_check(validity_checker &valid) const { } + bool validity_check(validity_checker &valid) const { return true; } auto build() { @@ -1795,7 +1790,7 @@ private: that.built(); } - void validity_check(validity_checker &valid) const { } + bool validity_check(validity_checker &valid) const { return true; } auto build() { @@ -1853,7 +1848,7 @@ private: return first_transform_builder<wrapped_builder, std::remove_reference_t<T> >(this->m_target, this->m_append, wrapped_builder(std::move(*this)), std::forward<T>(cb), this->exor(), this->mask(), DefaultMask); } - void validity_check(validity_checker &valid) const { } + bool validity_check(validity_checker &valid) const { return true; } auto build() { @@ -1895,7 +1890,7 @@ private: that.built(); } - void validity_check(validity_checker &valid) const { } + bool validity_check(validity_checker &valid) const { return true; } auto build() { @@ -1950,7 +1945,7 @@ private: return first_transform_builder<wrapped_builder, std::remove_reference_t<T> >(this->m_target, this->m_append, wrapped_builder(std::move(*this)), std::forward<T>(cb), this->exor(), this->mask(), DefaultMask); } - void validity_check(validity_checker &valid) const { } + bool validity_check(validity_checker &valid) const { return true; } auto build() { @@ -1962,99 +1957,6 @@ private: } }; - class log_builder : public builder_base, public transform_base<std::make_unsigned_t<Input>, log_builder> - { - private: - class wrapped_builder : public builder_base - { - public: - template <typename T, typename U> friend class first_transform_builder; - - using input_t = Input; - - wrapped_builder(log_builder &&that) - : builder_base(std::move(that)) - , m_devbase(that.m_devbase) - , m_message(std::move(that.m_message)) - { - that.consume(); - that.built(); - } - wrapped_builder(wrapped_builder &&that) - : builder_base(std::move(that)) - , m_devbase(that.m_devbase) - , m_message(std::move(that.m_message)) - { - that.consume(); - that.built(); - } - - void validity_check(validity_checker &valid) const { } - - auto build() - { - assert(this->m_consumed); - this->built(); - return - [&devbase = m_devbase, message = std::move(m_message)] (offs_t offset, input_t data, std::make_unsigned_t<input_t> mem_mask) - { if (data) devbase.logerror("%s: %s\n", devbase.machine().describe_context(), message); }; - } - - private: - wrapped_builder(wrapped_builder const &) = delete; - wrapped_builder operator=(wrapped_builder const &) = delete; - wrapped_builder operator=(wrapped_builder &&that) = delete; - - device_t &m_devbase; - std::string m_message; - }; - - friend class wrapped_builder; // workaround for MSVC - - log_builder(log_builder const &) = delete; - log_builder &operator=(log_builder const &) = delete; - log_builder &operator=(log_builder &&that) = delete; - - device_t &m_devbase; - std::string m_message; - - public: - using input_t = Input; - - log_builder(devcb_write &target, bool append, device_t &devbase, std::string &&message) - : builder_base(target, append) - , transform_base<std::make_unsigned_t<Input>, log_builder>(DefaultMask) - , m_devbase(devbase) - , m_message(std::move(message)) - { } - log_builder(log_builder &&that) - : builder_base(std::move(that)) - , transform_base<std::make_unsigned_t<Input>, log_builder>(std::move(that)) - , m_devbase(that.m_devbase) - , m_message(std::move(that.m_message)) - { - that.consume(); - that.built(); - } - ~log_builder() { this->template register_creator<log_builder>(); } - - template <typename T> - std::enable_if_t<is_transform<input_t, input_t, T>::value, first_transform_builder<wrapped_builder, std::remove_reference_t<T> > > transform(T &&cb) - { - return first_transform_builder<wrapped_builder, std::remove_reference_t<T> >(this->m_target, this->m_append, wrapped_builder(std::move(*this)), std::forward<T>(cb), this->exor(), this->mask(), DefaultMask); - } - - void validity_check(validity_checker &valid) const { } - - auto build() - { - assert(this->m_consumed); - this->built(); - return - [&devbase = m_devbase, message = std::move(m_message), exor = this->exor(), mask = this->mask()] (offs_t offset, input_t data, std::make_unsigned_t<input_t> mem_mask) - { if ((data ^ exor) & mask) devbase.logerror("%s: %s\n", devbase.machine().describe_context(), message); }; - } - }; class binder { public: @@ -2092,6 +1994,13 @@ private: return delegate_builder<delegate_type_t<T> >(m_target, m_append, m_target.owner(), devcb_write::cast_reference<delegate_device_class_t<T> >(obj), std::forward<T>(func), name); } + template <typename T> + std::enable_if_t<is_write_method<T>::value, delegate_builder<delegate_type_t<T> > > set(device_t &devbase, char const *tag, T &&func, char const *name) + { + set_used(); + return delegate_builder<delegate_type_t<T> >(m_target, m_append, devbase, tag, std::forward<T>(func), name); + } + template <typename T, typename U, bool R> std::enable_if_t<is_write_method<T>::value, delegate_builder<delegate_type_t<T> > > set(device_finder<U, R> &finder, T &&func, char const *name) { @@ -2236,38 +2145,6 @@ private: return set_output(std::forward<Params>(args)...); } - template <typename... Params> - log_builder set_log(device_t &devbase, Params &&... args) - { - set_used(); - return log_builder(m_target, m_append, devbase, std::string(std::forward<Params>(args)...)); - } - - template <typename T, typename... Params> - std::enable_if_t<emu::detail::is_device_implementation<std::remove_reference_t<T> >::value, log_builder> set_log(T &devbase, Params &&... args) - { - return set_log(static_cast<device_t &>(devbase), std::forward<Params>(args)...); - } - - template <typename T, typename... Params> - std::enable_if_t<emu::detail::is_device_interface<std::remove_reference_t<T> >::value, log_builder> set_log(T &devbase, Params &&... args) - { - return set_log(devbase.device(), std::forward<Params>(args)...); - } - - template <typename... Params> - log_builder set_log(Params &&... args) - { - return set_log(m_target.owner().mconfig().current_device(), std::forward<Params>(args)...); - } - - template <typename... Params> - log_builder append_log(Params &&... args) - { - m_append = true; - return set_log(std::forward<Params>(args)...); - } - void set_nop() { set_used(); @@ -2285,18 +2162,20 @@ private: std::vector<func_t> m_functions; std::vector<typename creator::ptr> m_creators; + bool m_unset = false; + +protected: + virtual bool findit(validity_checker *valid) override; + virtual void end_configuration() override; public: template <unsigned Count> class array : public devcb_write_base::array<devcb_write<Input, DefaultMask>, Count> { public: - using devcb_write_base::array<devcb_write<Input, DefaultMask>, Count>::array; - - void resolve_all_safe() + array(device_t &owner) + : devcb_write_base::array<devcb_write<Input, DefaultMask>, Count>::array(owner) { - for (devcb_write<Input, DefaultMask> &elem : *this) - elem.resolve_safe(); } }; @@ -2305,16 +2184,10 @@ public: binder bind(); void reset(); - virtual void validity_check(validity_checker &valid) const override; - - void resolve(); - void resolve_safe(); - void operator()(offs_t offset, Input data, std::make_unsigned_t<Input> mem_mask = DefaultMask); void operator()(Input data); - bool isnull() const { return m_functions.empty() && m_creators.empty(); } - explicit operator bool() const { return !m_functions.empty(); } + bool isunset() const noexcept { return m_unset || (m_functions.empty() && m_creators.empty()); } }; template <typename Input, std::make_unsigned_t<Input> DefaultMask> @@ -2326,6 +2199,7 @@ devcb_write<Input, DefaultMask>::devcb_write(device_t &owner) template <typename Input, std::make_unsigned_t<Input> DefaultMask> typename devcb_write<Input, DefaultMask>::binder devcb_write<Input, DefaultMask>::bind() { + assert(m_functions.empty()); return binder(*this); } @@ -2337,29 +2211,38 @@ void devcb_write<Input, DefaultMask>::reset() } template <typename Input, std::make_unsigned_t<Input> DefaultMask> -void devcb_write<Input, DefaultMask>::validity_check(validity_checker &valid) const -{ - assert(m_functions.empty()); - for (typename creator::ptr const &c : m_creators) - c->validity_check(valid); -} - -template <typename Input, std::make_unsigned_t<Input> DefaultMask> -void devcb_write<Input, DefaultMask>::resolve() +bool devcb_write<Input, DefaultMask>::findit(validity_checker *valid) { assert(m_functions.empty()); - m_functions.reserve(m_creators.size()); - for (typename creator::ptr const &c : m_creators) - m_functions.emplace_back(c->create()); - m_creators.clear(); + if (!valid) + { + // FIXME: report errors by returning false rather than throwing fatal errors + m_functions.reserve(m_creators.size()); + for (typename creator::ptr const &c : m_creators) + m_functions.emplace_back(c->create()); + m_creators.clear(); + if (m_functions.empty()) + { + m_functions.emplace_back([] (offs_t offset, Input data, std::make_unsigned_t<Input> mem_mask) { }); + m_unset = true; + } + return true; + } + else + { + bool success(true); + for (typename creator::ptr const &c : m_creators) + { + if (!c->validity_check(*valid)) + success = false; + } + return success; + } } template <typename Input, std::make_unsigned_t<Input> DefaultMask> -void devcb_write<Input, DefaultMask>::resolve_safe() +void devcb_write<Input, DefaultMask>::end_configuration() { - resolve(); - if (m_functions.empty()) - m_functions.emplace_back([] (offs_t offset, Input data, std::make_unsigned_t<Input> mem_mask) { }); } template <typename Input, std::make_unsigned_t<Input> DefaultMask> @@ -2640,7 +2523,6 @@ extern template class devcb_write8::creator_impl<devcb_write8::latched_inputline extern template class devcb_write8::creator_impl<devcb_write8::ioport_builder>; extern template class devcb_write8::creator_impl<devcb_write8::membank_builder>; extern template class devcb_write8::creator_impl<devcb_write8::output_builder>; -extern template class devcb_write8::creator_impl<devcb_write8::log_builder>; extern template class devcb_write16::creator_impl<devcb_write16::delegate_builder<write8s_delegate> >; extern template class devcb_write16::creator_impl<devcb_write16::delegate_builder<write16s_delegate> >; @@ -2660,7 +2542,6 @@ extern template class devcb_write16::creator_impl<devcb_write16::latched_inputli extern template class devcb_write16::creator_impl<devcb_write16::ioport_builder>; extern template class devcb_write16::creator_impl<devcb_write16::membank_builder>; extern template class devcb_write16::creator_impl<devcb_write16::output_builder>; -extern template class devcb_write16::creator_impl<devcb_write16::log_builder>; extern template class devcb_write32::creator_impl<devcb_write32::delegate_builder<write8s_delegate> >; extern template class devcb_write32::creator_impl<devcb_write32::delegate_builder<write16s_delegate> >; @@ -2680,7 +2561,6 @@ extern template class devcb_write32::creator_impl<devcb_write32::latched_inputli extern template class devcb_write32::creator_impl<devcb_write32::ioport_builder>; extern template class devcb_write32::creator_impl<devcb_write32::membank_builder>; extern template class devcb_write32::creator_impl<devcb_write32::output_builder>; -extern template class devcb_write32::creator_impl<devcb_write32::log_builder>; extern template class devcb_write64::creator_impl<devcb_write64::delegate_builder<write8s_delegate> >; extern template class devcb_write64::creator_impl<devcb_write64::delegate_builder<write16s_delegate> >; @@ -2700,7 +2580,6 @@ extern template class devcb_write64::creator_impl<devcb_write64::latched_inputli extern template class devcb_write64::creator_impl<devcb_write64::ioport_builder>; extern template class devcb_write64::creator_impl<devcb_write64::membank_builder>; extern template class devcb_write64::creator_impl<devcb_write64::output_builder>; -extern template class devcb_write64::creator_impl<devcb_write64::log_builder>; extern template class devcb_write_line::creator_impl<devcb_write_line::delegate_builder<write8s_delegate> >; extern template class devcb_write_line::creator_impl<devcb_write_line::delegate_builder<write16s_delegate> >; @@ -2720,6 +2599,5 @@ extern template class devcb_write_line::creator_impl<devcb_write_line::latched_i extern template class devcb_write_line::creator_impl<devcb_write_line::ioport_builder>; extern template class devcb_write_line::creator_impl<devcb_write_line::membank_builder>; extern template class devcb_write_line::creator_impl<devcb_write_line::output_builder>; -extern template class devcb_write_line::creator_impl<devcb_write_line::log_builder>; #endif // MAME_EMU_DEVCB_H diff --git a/src/emu/devcpu.cpp b/src/emu/devcpu.cpp index 03df7990a3d..efd12d682a9 100644 --- a/src/emu/devcpu.cpp +++ b/src/emu/devcpu.cpp @@ -27,7 +27,9 @@ cpu_device::cpu_device(const machine_config &mconfig, device_type type, const ch device_memory_interface(mconfig, *this), device_state_interface(mconfig, *this), device_disasm_interface(mconfig, *this), - m_force_no_drc(false) + m_force_no_drc(false), + m_access_to_be_redone(false), + m_access_before_delay_tag(nullptr) { } @@ -49,3 +51,55 @@ bool cpu_device::allow_drc() const { return mconfig().options().drc() && !m_force_no_drc; } + + + +bool cpu_device::cpu_is_interruptible() const +{ + return false; +} + +bool cpu_device::access_before_time(u64 access_time, u64 current_time) noexcept +{ + s32 delta = access_time - current_time; + if(*m_icountptr <= delta) { + if(*m_icountptr > 0) + *m_icountptr = 0; + m_access_to_be_redone = true; + return true; + } + + *m_icountptr -= delta; + + return false; +} + +bool cpu_device::access_before_delay(u32 cycles, const void *tag) noexcept +{ + if(tag == m_access_before_delay_tag) { + m_access_before_delay_tag = nullptr; + return false; + } + + *m_icountptr -= cycles; + + if(*m_icountptr <= 0) { + m_access_before_delay_tag = tag; + m_access_to_be_redone = true; + return true; + } + + m_access_before_delay_tag = nullptr; + return false; +} + +void cpu_device::access_after_delay(u32 cycles) noexcept +{ + *m_icountptr -= cycles; +} + +void cpu_device::defer_access() noexcept +{ + m_access_to_be_redone = true; + *m_icountptr = 0; +} diff --git a/src/emu/devcpu.h b/src/emu/devcpu.h index 6e9251ab3a9..70f7b1667a5 100644 --- a/src/emu/devcpu.h +++ b/src/emu/devcpu.h @@ -16,6 +16,8 @@ #include "didisasm.h" #include "diexec.h" +#include <utility> + //************************************************************************** // TYPE DEFINITIONS @@ -36,6 +38,20 @@ public: void set_force_no_drc(bool value) { m_force_no_drc = value; } bool allow_drc() const; + virtual bool cpu_is_interruptible() const; + + // To be used only for interruptible cpus + bool access_to_be_redone() noexcept { return std::exchange(m_access_to_be_redone, false); } + bool access_to_be_redone_noclear() noexcept { return m_access_to_be_redone; } + + // Returns true if the access must be aborted + bool access_before_time(u64 access_time, u64 current_time) noexcept; + bool access_before_delay(u32 cycles, const void *tag) noexcept; + + // The access has already happened, nothing to abort + void access_after_delay(u32 cycles) noexcept; + void defer_access() noexcept; + protected: // construction/destruction cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); @@ -43,6 +59,9 @@ protected: private: // configured state bool m_force_no_drc; // whether or not to force DRC off + + bool m_access_to_be_redone; // whether an access needs to be redone + const void *m_access_before_delay_tag; // if the tag matches on access_before_delay, consider the delay to have already happened }; #endif // MAME_EMU_DEVCPU_H diff --git a/src/emu/devdelegate.h b/src/emu/devdelegate.h index 5f7af89383b..3a63c874d92 100644 --- a/src/emu/devdelegate.h +++ b/src/emu/devdelegate.h @@ -43,41 +43,6 @@ template <typename Signature, unsigned Count> class device_delegate_array; // TYPE DEFINITIONS //************************************************************************** -namespace detail { - -// ======================> device_delegate_helper - -// device_delegate_helper does non-template work -class device_delegate_helper -{ -public: - // accessors - char const *finder_tag() const { return m_tag; } - std::pair<device_t &, char const *> finder_target() const { return std::make_pair(m_base, m_tag); } - -protected: - // construct/assign - device_delegate_helper(device_t &owner, char const *tag = nullptr) : m_base(owner), m_tag(tag) { } - template <class DeviceClass, bool Required> device_delegate_helper(device_finder<DeviceClass, Required> const &finder); - device_delegate_helper(device_delegate_helper const &) = default; - device_delegate_helper &operator=(device_delegate_helper const &) = default; - - // internal helpers - delegate_late_bind &bound_object() const; - void set_tag(device_t &object) { m_base = object; m_tag = nullptr; } - void set_tag(device_t &base, char const *tag) { m_base = base; m_tag = tag; } - void set_tag(char const *tag); - template <class DeviceClass, bool Required> void set_tag(device_finder<DeviceClass, Required> const &finder); - -private: - std::reference_wrapper<device_t> m_base; - char const *m_tag; -}; - -} // namespace detail - - -// ======================> named_delegate template <typename Signature> class named_delegate : public delegate<Signature> { @@ -104,8 +69,8 @@ public: template <typename T> named_delegate(T &&funcptr, std::enable_if_t<suitable_functoid<T>::value, char const *> name) : basetype(std::forward<T>(funcptr)), m_name(name) { } // allow assignment - named_delegate &operator=(named_delegate const &src) = default; - named_delegate &operator=(named_delegate &&src) = default; + named_delegate &operator=(named_delegate const &) = default; + named_delegate &operator=(named_delegate &&) = default; named_delegate &operator=(std::nullptr_t) noexcept { reset(); return *this; } // getters @@ -115,14 +80,53 @@ public: void reset() noexcept { basetype::reset(); m_name = nullptr; } }; -// ======================> device_delegate +template <class FunctionClass, typename ReturnType, typename... Params> +named_delegate(ReturnType (FunctionClass::*)(Params...), char const *, FunctionClass *) -> named_delegate<ReturnType (Params...)>; -// device_delegate is a delegate that wraps with a device tag and can be easily -// late bound without replicating logic everywhere -template <typename Signature> class device_delegate; +template <class FunctionClass, typename ReturnType, typename... Params> +named_delegate(ReturnType (FunctionClass::*)(Params...) const, char const *, FunctionClass *) -> named_delegate<ReturnType (Params...)>; + +template <class FunctionClass, typename ReturnType, typename... Params> +named_delegate(ReturnType (*)(FunctionClass &, Params...), char const *, FunctionClass *) -> named_delegate<ReturnType (Params...)>; + + +namespace detail { + +// device_delegate_helper does non-template work + +class device_delegate_helper +{ +public: + // accessors + char const *finder_tag() const { return m_tag; } + std::pair<device_t &, char const *> finder_target() const { return std::make_pair(m_base, m_tag); } + +protected: + // construct/assign + device_delegate_helper(device_t &owner, char const *tag = nullptr) : m_base(owner), m_tag(tag) { } + template <class DeviceClass, bool Required> device_delegate_helper(device_finder<DeviceClass, Required> const &finder); + device_delegate_helper(device_delegate_helper const &) = default; + device_delegate_helper &operator=(device_delegate_helper const &) = default; + + // internal helpers + delegate_late_bind &bound_object() const; + void set_tag(device_t &object) { m_base = object; m_tag = nullptr; } + void set_tag(device_t &base, char const *tag) { m_base = base; m_tag = tag; } + void set_tag(char const *tag); + template <class DeviceClass, bool Required> void set_tag(device_finder<DeviceClass, Required> const &finder); + +private: + std::reference_wrapper<device_t> m_base; + char const *m_tag; +}; + + +// device_delegate_base doesn't need to be specialised on return type + +template <typename Signature> class device_delegate_base; template <typename ReturnType, typename... Params> -class device_delegate<ReturnType (Params...)> : protected named_delegate<ReturnType (Params...)>, public detail::device_delegate_helper +class device_delegate_base<ReturnType (Params...)> : protected named_delegate<ReturnType (Params...)>, public device_delegate_helper { private: using basetype = named_delegate<ReturnType (Params...)>; @@ -141,77 +145,72 @@ private: template <class T> static std::enable_if_t<is_related_device_interface<T, T>::value, device_t &> get_device(T &object) { return object.device(); } public: - template <unsigned Count> using array = device_delegate_array<ReturnType (Params...), Count>; - - template <typename T> - using supports_callback = std::bool_constant<std::is_constructible_v<device_delegate, device_t &, char const *, T, char const *> >; - // construct/assign - explicit device_delegate(device_t &owner) : basetype(), detail::device_delegate_helper(owner) { } - device_delegate(device_delegate const &) = default; - device_delegate &operator=(device_delegate const &) = default; + explicit device_delegate_base(device_t &owner) : basetype(), device_delegate_helper(owner) { } + device_delegate_base(device_delegate_base const &) = default; + device_delegate_base &operator=(device_delegate_base const &) = default; // construct with prototype and target - device_delegate(basetype const &proto, device_t &object) : basetype(proto, object), detail::device_delegate_helper(object) { } - device_delegate(device_delegate const &proto, device_t &object) : basetype(proto, object), detail::device_delegate_helper(object) { } + device_delegate_base(basetype const &proto, device_t &object) : basetype(proto, object), device_delegate_helper(object) { } + device_delegate_base(device_delegate_base const &proto, device_t &object) : basetype(proto, object), device_delegate_helper(object) { } // construct with base and tag template <class D> - device_delegate(device_t &base, char const *tag, ReturnType (D::*funcptr)(Params...), char const *name) + device_delegate_base(device_t &base, char const *tag, ReturnType (D::*funcptr)(Params...), char const *name) : basetype(funcptr, name, static_cast<D *>(nullptr)) - , detail::device_delegate_helper(base, tag) + , device_delegate_helper(base, tag) { } template <class D> - device_delegate(device_t &base, char const *tag, ReturnType (D::*funcptr)(Params...) const, char const *name) + device_delegate_base(device_t &base, char const *tag, ReturnType (D::*funcptr)(Params...) const, char const *name) : basetype(funcptr, name, static_cast<D *>(nullptr)) - , detail::device_delegate_helper(base, tag) + , device_delegate_helper(base, tag) { } template <class D> - device_delegate(device_t &base, char const *tag, ReturnType (*funcptr)(D &, Params...), char const *name) + device_delegate_base(device_t &base, char const *tag, ReturnType (*funcptr)(D &, Params...), char const *name) : basetype(funcptr, name, static_cast<D *>(nullptr)) - , detail::device_delegate_helper(base, tag) + , device_delegate_helper(base, tag) { } // construct with device finder template <class D, bool R, class E> - device_delegate(device_finder<D, R> const &finder, ReturnType (E::*funcptr)(Params...), char const *name) + device_delegate_base(device_finder<D, R> const &finder, ReturnType (E::*funcptr)(Params...), char const *name) : basetype(funcptr, name, static_cast<E *>(nullptr)) - , detail::device_delegate_helper(finder) + , device_delegate_helper(finder) { } template <class D, bool R, class E> - device_delegate(device_finder<D, R> const &finder, ReturnType (E::*funcptr)(Params...) const, char const *name) + device_delegate_base(device_finder<D, R> const &finder, ReturnType (E::*funcptr)(Params...) const, char const *name) : basetype(funcptr, name, static_cast<E *>(nullptr)) - , detail::device_delegate_helper(finder) + , device_delegate_helper(finder) { } template <class D, bool R, class E> - device_delegate(device_finder<D, R> const &finder, ReturnType (*funcptr)(E &, Params...), char const *name) + device_delegate_base(device_finder<D, R> const &finder, ReturnType (*funcptr)(E &, Params...), char const *name) : basetype(funcptr, name, static_cast<E *>(nullptr)) - , detail::device_delegate_helper(finder) + , device_delegate_helper(finder) { } // construct with target object template <class T, class D> - device_delegate(T &object, ReturnType (D::*funcptr)(Params...), std::enable_if_t<is_related_device<D, T>::value, char const *> name) + device_delegate_base(T &object, ReturnType (D::*funcptr)(Params...), std::enable_if_t<is_related_device<D, T>::value, char const *> name) : basetype(funcptr, name, static_cast<D *>(&object)) - , detail::device_delegate_helper(get_device(object)) + , device_delegate_helper(get_device(object)) { } template <class T, class D> - device_delegate(T &object, ReturnType (D::*funcptr)(Params...) const, std::enable_if_t<is_related_device<D, T>::value, char const *> name) + device_delegate_base(T &object, ReturnType (D::*funcptr)(Params...) const, std::enable_if_t<is_related_device<D, T>::value, char const *> name) : basetype(funcptr, name, static_cast<D *>(&object)) - , detail::device_delegate_helper(get_device(object)) + , device_delegate_helper(get_device(object)) { } template <class T, class D> - device_delegate(T &object, ReturnType (*funcptr)(D &, Params...), std::enable_if_t<is_related_device<D, T>::value, char const *> name) + device_delegate_base(T &object, ReturnType (*funcptr)(D &, Params...), std::enable_if_t<is_related_device<D, T>::value, char const *> name) : basetype(funcptr, name, static_cast<D *>(&object)) - , detail::device_delegate_helper(get_device(object)) + , device_delegate_helper(get_device(object)) { } // construct with callable object template <typename T> - device_delegate(device_t &owner, T &&funcptr, std::enable_if_t<suitable_functoid<T>::value, char const *> name) + device_delegate_base(device_t &owner, T &&funcptr, std::enable_if_t<suitable_functoid<T>::value, char const *> name) : basetype(std::forward<T>(funcptr), name) - , detail::device_delegate_helper(owner) - { basetype::operator=(basetype(std::forward<T>(funcptr), name)); } + , device_delegate_helper(owner) + { } // setters that implicitly bind to the current device template <class D> void set(ReturnType (D::*funcptr)(Params...), char const *name) @@ -247,18 +246,117 @@ public: void reset() { basetype::reset(); set_tag(finder_target().first); } - // perform the binding - void resolve() { if (!basetype::isnull() && !basetype::has_object()) basetype::late_bind(bound_object()); } - // accessors using basetype::operator(); using basetype::isnull; using basetype::has_object; using basetype::name; + + // perform the binding + void resolve() + { + if (!this->isnull() && !this->has_object()) + this->late_bind(bound_object()); + } +}; + +} // namespace detail + + +// device_delegate is a delegate that can be late bound to a device specification + +template <typename Signature> class device_delegate; + +template <typename ReturnType, typename... Params> +class device_delegate<ReturnType (Params...)> : protected detail::device_delegate_base<ReturnType (Params...)> +{ +public: + template <unsigned Count> using array = device_delegate_array<ReturnType (Params...), Count>; + + template <typename T> + using supports_callback = std::bool_constant<std::is_constructible_v<device_delegate, device_t &, char const *, T, char const *> >; + + // constructors + using detail::device_delegate_base<ReturnType (Params...)>::device_delegate_base; + device_delegate(device_delegate const &) = default; + device_delegate(device_delegate const &proto, device_t &object) : detail::device_delegate_base<ReturnType (Params...)>(proto, object) { } + + // assignment + device_delegate &operator=(device_delegate const &) = default; + device_delegate &operator=(std::nullptr_t) { this->reset(); } + + // setters/unsetters + void set(device_delegate const &src) { operator=(src); } + using detail::device_delegate_base<ReturnType (Params...)>::set; + using detail::device_delegate_base<ReturnType (Params...)>::reset; + + // accessors + using detail::device_delegate_base<ReturnType (Params...)>::operator(); + using detail::device_delegate_base<ReturnType (Params...)>::isnull; + using detail::device_delegate_base<ReturnType (Params...)>::has_object; + using detail::device_delegate_base<ReturnType (Params...)>::name; + using detail::device_delegate_base<ReturnType (Params...)>::finder_tag; + using detail::device_delegate_base<ReturnType (Params...)>::finder_target; + + // perform the binding + using detail::device_delegate_base<ReturnType (Params...)>::resolve; + + template <typename T> + void resolve_safe(T &&dflt) + { + if (this->isnull()) + this->set([result = std::decay_t<T>(std::forward<T>(dflt))] (Params...) { return ReturnType(result); }, "default"); + else if (!this->has_object()) + this->late_bind(this->bound_object()); + } +}; + +template <typename... Params> +class device_delegate<void (Params...)> : protected detail::device_delegate_base<void (Params...)> +{ +public: + template <unsigned Count> using array = device_delegate_array<void (Params...), Count>; + + template <typename T> + using supports_callback = std::bool_constant<std::is_constructible_v<device_delegate, device_t &, char const *, T, char const *> >; + + // constructors + using detail::device_delegate_base<void (Params...)>::device_delegate_base; + device_delegate(device_delegate const &) = default; + device_delegate(device_delegate const &proto, device_t &object) : detail::device_delegate_base<void (Params...)>(proto, object) { } + + // assignment + device_delegate &operator=(device_delegate const &) = default; + device_delegate &operator=(std::nullptr_t) { this->reset(); } + + // setters/unsetters + void set(device_delegate const &src) { operator=(src); } + using detail::device_delegate_base<void (Params...)>::set; + using detail::device_delegate_base<void (Params...)>::reset; + + // accessors + using detail::device_delegate_base<void (Params...)>::operator(); + using detail::device_delegate_base<void (Params...)>::isnull; + using detail::device_delegate_base<void (Params...)>::has_object; + using detail::device_delegate_base<void (Params...)>::name; + using detail::device_delegate_base<void (Params...)>::finder_tag; + using detail::device_delegate_base<void (Params...)>::finder_target; + + // perform the binding + using detail::device_delegate_base<void (Params...)>::resolve; + + void resolve_safe() + { + if (this->isnull()) + this->set([] (Params...) { }, "default"); + else if (!this->has_object()) + this->late_bind(this->bound_object()); + } }; // simplifies constructing an array of delegates with a single owner + template <typename Signature, unsigned Count> class device_delegate_array : public std::array<device_delegate<Signature>, Count> { @@ -288,8 +386,42 @@ public: for (device_delegate<Signature> &elem : *this) elem.resolve(); } + + template <typename... T> + void resolve_all_safe(T &&... args) + { + for (device_delegate<Signature> &elem : *this) + elem.resolve_safe(args...); + } }; +template <class D, typename ReturnType, typename... Params> +device_delegate(device_t &, char const *, ReturnType (D::*)(Params...), char const *) -> device_delegate<ReturnType (Params...)>; + +template <class D, typename ReturnType, typename... Params> +device_delegate(device_t &, char const *, ReturnType (D::*)(Params...) const, char const *) -> device_delegate<ReturnType (Params...)>; + +template <class D, typename ReturnType, typename... Params> +device_delegate(device_t &, char const *, ReturnType (*)(D &, Params...), char const *) -> device_delegate<ReturnType (Params...)>; + +template <class D, bool R, class E, typename ReturnType, typename... Params> +device_delegate(device_finder<D, R> const &, ReturnType (E::*)(Params...), char const *) -> device_delegate<ReturnType (Params...)>; + +template <class D, bool R, class E, typename ReturnType, typename... Params> +device_delegate(device_finder<D, R> const &, ReturnType (E::*)(Params...) const, char const *) -> device_delegate<ReturnType (Params...)>; + +template <class D, bool R, class E, typename ReturnType, typename... Params> +device_delegate(device_finder<D, R> const &, ReturnType (*)(E &, Params...), char const *) -> device_delegate<ReturnType (Params...)>; + +template <class T, class D, typename ReturnType, typename... Params> +device_delegate(T &, ReturnType (D::*)(Params...), char const *) -> device_delegate<ReturnType (Params...)>; + +template <class T, class D, typename ReturnType, typename... Params> +device_delegate(T &, ReturnType (D::*)(Params...) const, char const *) -> device_delegate<ReturnType (Params...)>; + +template <class T, class D, typename ReturnType, typename... Params> +device_delegate(T &, ReturnType (*)(D &, Params...), char const *) -> device_delegate<ReturnType (Params...)>; + } // namespace emu diff --git a/src/emu/devfind.cpp b/src/emu/devfind.cpp index d6bc984703e..6170b2fca8c 100644 --- a/src/emu/devfind.cpp +++ b/src/emu/devfind.cpp @@ -18,27 +18,42 @@ // BASE FINDER CLASS //************************************************************************** -constexpr char finder_base::DUMMY_TAG[]; +//------------------------------------------------- +// device_resolver_base - constructor +//------------------------------------------------- + +device_resolver_base::device_resolver_base(device_t &base) + : m_next(base.register_auto_finder(*this)) +{ +} //------------------------------------------------- -// finder_base - constructor +// ~device_resolver_base - destructor //------------------------------------------------- -finder_base::finder_base(device_t &base, char const *tag) - : m_next(base.register_auto_finder(*this)) - , m_base(base) - , m_tag(tag) - , m_resolved(false) +device_resolver_base::~device_resolver_base() { } + +//************************************************************************** +// BASE FINDER CLASS +//************************************************************************** + +constexpr char finder_base::DUMMY_TAG[]; + + //------------------------------------------------- -// ~finder_base - destructor +// finder_base - constructor //------------------------------------------------- -finder_base::~finder_base() +finder_base::finder_base(device_t &base, char const *tag) + : device_resolver_base(base) + , m_base(base) + , m_tag(tag) + , m_resolved(false) { } @@ -50,6 +65,7 @@ finder_base::~finder_base() void finder_base::set_tag(char const *tag) { assert(!m_resolved); + assert(tag); m_base = m_base.get().mconfig().current_device(); m_tag = tag; } diff --git a/src/emu/devfind.h b/src/emu/devfind.h index c8884d9582f..81ebb9f9812 100644 --- a/src/emu/devfind.h +++ b/src/emu/devfind.h @@ -216,21 +216,21 @@ public: /// Abstract non-template base class for object auto-discovery helpers. /// Provides the interface that the device_t uses to manage discovery at /// resolution time. -class finder_base +class device_resolver_base { public: /// \brief Destructor /// /// Destruction via base class pointer and dynamic type behaviour /// are allowed. - virtual ~finder_base(); + virtual ~device_resolver_base(); /// \brief Get next registered object discovery helper /// /// Implementation of basic single-linked list behaviour. /// \return Pointer to the next registered object discovery helper, /// or nullptr if this is the last. - finder_base *next() const { return m_next; } + device_resolver_base *next() const noexcept { return m_next; } /// \brief Attempt discovery /// @@ -254,6 +254,32 @@ public: /// subsequently removes or replaces devices. virtual void end_configuration() = 0; +protected: + /// \brief Designated constructor + /// + /// Construct base object discovery helper and register with device + /// to be invoked at resolution time. + /// \param [in] base Device to register with for resolution. + device_resolver_base(device_t &base); + + + /// \brief Pointer to next registered discovery helper + /// + /// This is a polymorphic class, so it can't be held in a standard + /// list container that requires elements of the same type. Hence + /// it implements basic intrusive single-linked list behaviour. + device_resolver_base *const m_next; +}; + + +/// \brief Base class for object discovery helpers +/// +/// Abstract non-template base class for object auto-discovery helpers. +/// Provides functionality for specifying a target as a base device and +/// relative tag. Also supplies helpers for looking up resources. +class finder_base : protected device_resolver_base +{ +public: /// \brief Get search tag /// /// Returns the search tag. @@ -280,6 +306,7 @@ public: void set_tag(device_t &base, char const *tag) { assert(!m_resolved); + assert(tag); m_base = base; m_tag = tag; } @@ -315,7 +342,9 @@ protected: /// /// Construct base object discovery helper and register with device /// to be invoked at resolution time. - /// \param [in] base Base device to search from. + /// \param [in] base Device to register with for resolution. Also + /// sets initial base device to search from. The tag must be + /// specified relative to this device. /// \param [in] tag Object tag to search for. This is not copied, /// it is the caller's responsibility to ensure this pointer /// remains valid until resolution time. @@ -419,13 +448,6 @@ protected: bool report_missing(bool found, char const *objname, bool required) const; - /// \brief Pointer to next registered discovery helper - /// - /// This is a polymorphic class, so it can't be held in a standard - /// list container that requires elements of the same type. Hence - /// it implements basic intrusive single-linked list behaviour. - finder_base *const m_next; - /// \brief Base device to search from std::reference_wrapper<device_t> m_base; @@ -600,6 +622,12 @@ public: return device; } + /// \brief Look up target during configuration + /// Look up the current target device during configuration, before + /// resolution. + /// \return Pointer to target device if found, or nullptr otherwise. + DeviceClass *lookup() const { return this->m_base.get().template subdevice<DeviceClass>(this->m_tag); } + private: /// \brief Check that device implementation has expected tag /// \param [in] device Reference to device. @@ -1186,6 +1214,33 @@ public: /// been found. size_t bytes() const { return m_bytes; } + /// \brief Get iterator to first element + /// + /// Returns an iterator to the first element of the memory share. + /// \return Iterator to first element. + PointerType *begin() const { return this->m_target; } + + /// \brief Get iterator beyond last element + /// + /// Returns an iterator one past the last element of the memory + /// share. + /// \return Iterator one past last element. + PointerType *end() const { return this->m_target + length(); } + + /// \brief Get constant iterator to first element + /// + /// Returns a constant iterator to the first element of the memory + /// share. + /// \return Constant iterator to first element. + PointerType const *cbegin() const { return this->m_target; } + + /// \brief Get constant iterator beyond last element + /// + /// Returns a constant iterator one past the last element of the + /// memory share. + /// \return Constant iterator one past last element. + PointerType const *cend() const { return this->m_target + length(); } + private: /// \brief Find memory share base pointer /// @@ -1312,6 +1367,34 @@ public: /// \return Memory share width in bytes. u8 bytewidth() const { return m_target->bytewidth(); } + /// \brief Get iterator to first element + /// + /// Returns an iterator to the first element of the memory share. + /// Must not be called before creation is attempted. + /// \return Iterator to first element. + PointerType *begin() const { return target(); } + + /// \brief Get iterator beyond last element + /// + /// Returns an iterator one past the last element of the memory + /// share. Must not be called before creation is attempted. + /// \return Iterator one past last element. + PointerType *end() const { return target() + length(); } + + /// \brief Get constant iterator to first element + /// + /// Returns a constant iterator to the first element of the memory + /// share. Must not be called before creation is attempted. + /// \return Constant iterator to first element. + PointerType const *cbegin() const { return target(); } + + /// \brief Get constant iterator beyond last element + /// + /// Returns a constant iterator one past the last element of the + /// memory share. Must not be called before creation is attempted. + /// \return Constant iterator one past last element. + PointerType const *cend() const { return target() + length(); } + protected: virtual bool findit(validity_checker *valid) override; virtual void end_configuration() override; diff --git a/src/emu/device.cpp b/src/emu/device.cpp index 425ce52d461..1940c619455 100644 --- a/src/emu/device.cpp +++ b/src/emu/device.cpp @@ -224,7 +224,7 @@ void device_t::add_machine_configuration(machine_config &config) assert(&config == &m_machine_config); machine_config::token const tok(config.begin_configuration(*this)); device_add_mconfig(config); - for (finder_base *autodev = m_auto_finder_list; autodev != nullptr; autodev = autodev->next()) + for (auto *autodev = m_auto_finder_list; autodev; autodev = autodev->next()) autodev->end_configuration(); } @@ -321,11 +321,7 @@ void device_t::config_complete() void device_t::validity_check(validity_checker &valid) const { - // validate callbacks - for (devcb_base const *callback : m_callbacks) - callback->validity_check(valid); - - // validate via the interfaces + // validate mixins for (device_interface &intf : interfaces()) intf.interface_validity_check(valid); @@ -478,26 +474,10 @@ void device_t::set_machine(running_machine &machine) bool device_t::findit(validity_checker *valid) const { bool allfound = true; - for (finder_base *autodev = m_auto_finder_list; autodev != nullptr; autodev = autodev->next()) + for (auto *autodev = m_auto_finder_list; autodev; autodev = autodev->next()) { - if (valid) - { - // sanity checking - char const *const tag = autodev->finder_tag(); - if (!tag) - { - osd_printf_error("Finder tag is null!\n"); - allfound = false; - continue; - } - if (tag[0] == '^' && tag[1] == ':') - { - osd_printf_error("Malformed finder tag: %s\n", tag); - allfound = false; - continue; - } - } - allfound &= autodev->findit(valid); + if (!autodev->findit(valid)) + allfound = false; } return allfound; } @@ -1006,18 +986,9 @@ void device_t::subdevice_list::remove(device_t &device) // list of stuff to find after we go live //------------------------------------------------- -finder_base *device_t::register_auto_finder(finder_base &autodev) -{ - // add to this list - finder_base *old = m_auto_finder_list; - m_auto_finder_list = &autodev; - return old; -} - - -void device_t::register_callback(devcb_base &callback) +device_resolver_base *device_t::register_auto_finder(device_resolver_base &autodev) { - m_callbacks.emplace_back(&callback); + return std::exchange(m_auto_finder_list, &autodev); } diff --git a/src/emu/device.h b/src/emu/device.h index 402bbb1ccff..87736144292 100644 --- a/src/emu/device.h +++ b/src/emu/device.h @@ -37,19 +37,6 @@ //************************************************************************** -// DEVICE CONFIGURATION MACROS -//************************************************************************** - -// configure devices - -#define DECLARE_READ_LINE_MEMBER(name) int name() -#define READ_LINE_MEMBER(name) int name() -#define DECLARE_WRITE_LINE_MEMBER(name) void name([[maybe_unused]] int state) -#define WRITE_LINE_MEMBER(name) void name([[maybe_unused]] int state) - - - -//************************************************************************** // GLOBAL VARIABLES //************************************************************************** @@ -478,8 +465,7 @@ class device_t : public delegate_late_bind friend class simple_list<device_t>; friend class running_machine; - friend class finder_base; - friend class devcb_base; + friend class device_resolver_base; class subdevice_list { @@ -647,8 +633,8 @@ public: // interface helpers interface_list &interfaces() { return m_interfaces; } const interface_list &interfaces() const { return m_interfaces; } - template<class DeviceClass> bool interface(DeviceClass *&intf) { intf = dynamic_cast<DeviceClass *>(this); return (intf != nullptr); } - template<class DeviceClass> bool interface(DeviceClass *&intf) const { intf = dynamic_cast<const DeviceClass *>(this); return (intf != nullptr); } + template <class DeviceClass> bool interface(DeviceClass *&intf) { intf = dynamic_cast<DeviceClass *>(this); return (intf != nullptr); } + template <class DeviceClass> bool interface(DeviceClass *&intf) const { intf = dynamic_cast<const DeviceClass *>(this); return (intf != nullptr); } // specialized helpers for common core interfaces bool interface(device_execute_interface *&intf) { intf = m_interfaces.m_execute; return (intf != nullptr); } @@ -671,8 +657,42 @@ public: ioport_port *ioport(std::string_view tag) const; device_t *subdevice(std::string_view tag) const; device_t *siblingdevice(std::string_view tag) const; - template<class DeviceClass> DeviceClass *subdevice(std::string_view tag) const { return downcast<DeviceClass *>(subdevice(tag)); } - template<class DeviceClass> DeviceClass *siblingdevice(std::string_view tag) const { return downcast<DeviceClass *>(siblingdevice(tag)); } + template <class DeviceClass> + DeviceClass *subdevice(std::string_view tag) const + { + device_t *const found = subdevice(tag); + if constexpr (std::is_base_of_v<device_t, DeviceClass>) + { + return downcast<DeviceClass *>(found); + } + else + { + auto const result = dynamic_cast<DeviceClass *>(found); +#if defined(MAME_DEBUG) + if (found && !result) + report_bad_device_cast(found, typeid(device_t), typeid(DeviceClass)); +#endif + return result; + } + } + template <class DeviceClass> + DeviceClass *siblingdevice(std::string_view tag) const + { + device_t *const found = siblingdevice(tag); + if constexpr (std::is_base_of_v<device_t, DeviceClass>) + { + return downcast<DeviceClass *>(found); + } + else + { + auto const result = dynamic_cast<DeviceClass *>(found); +#if defined(MAME_DEBUG) + if (found && !result) + report_bad_device_cast(found, typeid(device_t), typeid(DeviceClass)); +#endif + return result; + } + } std::string parameter(std::string_view tag) const; // configuration helpers @@ -771,7 +791,7 @@ public: /// \param [in] index A numeric value to distinguish between saved /// items with the same name. /// \sa save_item - template<typename ItemType> + template <typename ItemType> void ATTR_COLD save_pointer(ItemType &&value, const char *valname, u32 count, int index = 0) { assert(m_save); @@ -800,7 +820,7 @@ public: /// \param [in] index A numeric value to distinguish between saved /// items with the same name. /// \sa save_item - template<typename ItemType, typename StructType, typename ElementType> + template <typename ItemType, typename StructType, typename ElementType> void ATTR_COLD save_pointer(ItemType &&value, ElementType StructType::*element, const char *valname, u32 count, int index = 0) { assert(m_save); @@ -829,8 +849,7 @@ protected: void pre_save(); void post_load(); void notify_clock_changed(bool sync_on_new_clock_domain = false); - finder_base *register_auto_finder(finder_base &autodev); - void register_callback(devcb_base &callback); + device_resolver_base *register_auto_finder(device_resolver_base &autodev); //------------------- begin derived class overrides @@ -1009,9 +1028,8 @@ private: std::string m_basetag; // base part of the tag bool m_config_complete; // have we completed our configuration? bool m_started; // true if the start function has succeeded - finder_base * m_auto_finder_list; // list of objects to auto-find + device_resolver_base * m_auto_finder_list; // list of objects to auto-find mutable std::vector<rom_entry> m_rom_entries; - std::list<devcb_base *> m_callbacks; std::vector<memory_view *> m_viewlist; // list of views // string formatting buffer for logerror diff --git a/src/emu/device.ipp b/src/emu/device.ipp index c7b2d43346b..e633ead4bda 100644 --- a/src/emu/device.ipp +++ b/src/emu/device.ipp @@ -93,7 +93,7 @@ inline void device_t::logerror(Format &&fmt, Params &&... args) const { if (m_machine != nullptr && m_machine->allow_logging()) { - g_profiler.start(PROFILER_LOGERROR); + auto profile = g_profiler.start(PROFILER_LOGERROR); // dump to the buffer m_string_buffer.clear(); @@ -103,8 +103,6 @@ inline void device_t::logerror(Format &&fmt, Params &&... args) const m_string_buffer.put('\0'); m_machine->strlog(&m_string_buffer.vec()[0]); - - g_profiler.stop(); } } diff --git a/src/emu/diexec.cpp b/src/emu/diexec.cpp index b1f885e2b9d..4b06edc36d5 100644 --- a/src/emu/diexec.cpp +++ b/src/emu/diexec.cpp @@ -520,17 +520,12 @@ void device_execute_interface::interface_clock_changed(bool sync_on_new_clock_do //------------------------------------------------- -// standard_irq_callback_member - IRQ acknowledge +// standard_irq_callback - IRQ acknowledge // callback; handles HOLD_LINE case and signals // to the debugger //------------------------------------------------- -IRQ_CALLBACK_MEMBER( device_execute_interface::standard_irq_callback_member ) -{ - return device.execute().standard_irq_callback(irqline); -} - -int device_execute_interface::standard_irq_callback(int irqline) +int device_execute_interface::standard_irq_callback(int irqline, offs_t pc) { // get the default vector and acknowledge the interrupt if needed int vector = m_input[irqline].default_irq_callback(); @@ -543,7 +538,7 @@ int device_execute_interface::standard_irq_callback(int irqline) // notify the debugger if (device().machine().debug_flags & DEBUG_FLAG_ENABLED) - device().debug()->interrupt_hook(irqline); + device().debug()->interrupt_hook(irqline, pc); return vector; } diff --git a/src/emu/diexec.h b/src/emu/diexec.h index 5d3fb93ed59..51973ad19cc 100644 --- a/src/emu/diexec.h +++ b/src/emu/diexec.h @@ -161,10 +161,10 @@ public: void abort_timeslice() noexcept; // input and interrupt management - void set_input_line(int linenum, int state) { m_input[linenum].set_state_synced(state); } - void set_input_line_vector(int linenum, int vector) { m_input[linenum].set_vector(vector); } - void set_input_line_and_vector(int linenum, int state, int vector) { m_input[linenum].set_state_synced(state, vector); } - int input_state(int linenum) const { return m_input[linenum].m_curstate; } + void set_input_line(int linenum, int state) { assert(device().started()); m_input[linenum].set_state_synced(state); } + void set_input_line_vector(int linenum, int vector) { assert(device().started()); m_input[linenum].set_vector(vector); } + void set_input_line_and_vector(int linenum, int state, int vector) { assert(device().started()); m_input[linenum].set_state_synced(state, vector); } + int input_state(int linenum) const { assert(device().started()); return m_input[linenum].m_curstate; } void pulse_input_line(int irqline, const attotime &duration); // suspend/resume @@ -221,8 +221,7 @@ protected: // for use by devcpu for now... int current_input_state(unsigned i) const { return m_input[i].m_curstate; } void set_icountptr(int &icount) { assert(!m_icountptr); m_icountptr = &icount; } - IRQ_CALLBACK_MEMBER(standard_irq_callback_member); - int standard_irq_callback(int irqline); + int standard_irq_callback(int irqline, offs_t pc); // debugger hooks bool debugger_enabled() const { return bool(device().machine().debug_flags & DEBUG_FLAG_ENABLED); } @@ -304,7 +303,9 @@ private: // cycle counting and executing profile_type m_profiler; // profiler tag +protected: // TODO: decide whether to bring up the wait-state methods int * m_icountptr; // pointer to the icount +private: int m_cycles_running; // number of cycles we are executing int m_cycles_stolen; // number of cycles we artificially stole diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp index 016f577f071..59d1523a6b1 100644 --- a/src/emu/diimage.cpp +++ b/src/emu/diimage.cpp @@ -16,8 +16,6 @@ #include "softlist.h" #include "softlist_dev.h" -#include "ui/uimain.h" - #include "corestr.h" #include "opresolv.h" #include "path.h" @@ -67,10 +65,12 @@ image_device_format::~image_device_format() device_image_interface::device_image_interface(const machine_config &mconfig, device_t &device) : device_interface(device, "image") - , m_err() , m_file() , m_mame_file() + , m_default_region(-1) + , m_current_region(-1) , m_software_part_ptr(nullptr) + , m_sequence_counter(0) , m_readonly(false) , m_created(false) , m_create_format(0) @@ -91,6 +91,17 @@ device_image_interface::~device_image_interface() { } +//------------------------------------------------- +// add_region - register a region that may +// have a chd image +//------------------------------------------------- +void device_image_interface::add_region(std::string name, bool is_default) +{ + if (is_default) + m_default_region = m_possible_preset_regions.size(); + m_possible_preset_regions.push_back(name); +} + //------------------------------------------------- // interface_config_complete - perform any @@ -104,6 +115,133 @@ void device_image_interface::interface_config_complete() update_names(); } +//------------------------------------------------- +// check_preset_images - lookup the CHDs from the +// region(s), if any +//------------------------------------------------- + +void device_image_interface::check_preset_images() +{ + if (!m_possible_preset_regions.empty()) + { + for(const auto &r : m_possible_preset_regions) + m_preset_images.push_back(device().machine().rom_load().get_disk_handle(":" + r)); + if (m_default_region != -1 && m_preset_images[m_default_region]) + m_current_region = m_default_region; + else + { + for (m_current_region = 0; m_current_region != int(m_preset_images.size()) && !m_preset_images[m_current_region]; m_current_region++); + if (m_current_region == int(m_preset_images.size())) + fatalerror("%s: No configured region has an image\n", device().tag()); + } + set_image_tag(); + set_user_loadable(false); + } + else + { + std::string tag = device().owner()->tag(); + auto *const chd = device().machine().rom_load().get_disk_handle(tag); + if (chd) + { + m_possible_preset_regions.emplace_back(std::move(tag)); + m_preset_images.push_back(chd); + m_current_region = 0; + set_image_tag(); + set_user_loadable(false); + } + } +} + +//------------------------------------------------- +// has_preset_images - does the device have an +// image to retrieve through current_image_* +//------------------------------------------------- + +bool device_image_interface::has_preset_images() const +{ + return !m_possible_preset_regions.empty(); +} + +//------------------------------------------------- +// has_preset_images - does the device have +// multiple preset images with user selection +//------------------------------------------------- + +bool device_image_interface::has_preset_images_selection() const +{ + int icount = 0; + for (const auto *f : m_preset_images) + if (f) + icount ++; + return icount > 1; +} + + +//------------------------------------------------- +// preset_images_list -- generate the list of +// available image names +//------------------------------------------------- + +std::vector<std::string> device_image_interface::preset_images_list() const +{ + std::vector<std::string> result; + for (unsigned int i = 0; i != m_preset_images.size(); i++) + if (m_preset_images[i]) + result.push_back(m_possible_preset_regions[i]); + return result; +} + +//------------------------------------------------- +// current_preset_image_id -- current image id, +// recomputed to ignore non-present images. +// returns -1 if not in preset mode +//------------------------------------------------- + +int device_image_interface::current_preset_image_id() const +{ + if (m_current_region == -1) + return -1; + int id = 0; + for (int i = 0; i != m_current_region; i++) + if (m_preset_images[i]) + id++; + return id; +} + +//------------------------------------------------- +// current_preset_image_chd -- return the chd of +// the current active image, nullptr if non +//------------------------------------------------- + +chd_file *device_image_interface::current_preset_image_chd() const +{ + if (m_current_region == -1) + return nullptr; + return m_preset_images[m_current_region]; +} + +//------------------------------------------------- +// switch_preset_image -- change of preset image +//------------------------------------------------- + +void device_image_interface::switch_preset_image(int id) +{ + for (unsigned int i = 0; i != m_preset_images.size(); i++) + if (m_preset_images[i]) + { + if(!id) + { + call_unload(); + m_current_region = i; + call_load(); + break; + } + id--; + } + + return; +} + //------------------------------------------------- // set_image_filename - specifies the filename of @@ -118,9 +256,9 @@ void device_image_interface::set_image_filename(std::string_view filename) // find the last "path separator" auto iter = std::find_if( - m_image_name.rbegin(), - m_image_name.rend(), - [](char c) { return (c == '\\') || (c == '/') || (c == ':'); }); + m_image_name.rbegin(), + m_image_name.rend(), + [] (char c) { return (c == '\\') || (c == '/') || (c == ':'); }); if (iter != m_image_name.rend()) m_basename.assign(iter.base(), m_image_name.end()); @@ -133,6 +271,20 @@ void device_image_interface::set_image_filename(std::string_view filename) m_filetype = core_filename_extract_extension(m_basename, true); } +//------------------------------------------------- +// set_image_tag - specifies the filename of +// an image as the device tag +//------------------------------------------------- + +void device_image_interface::set_image_tag() +{ + m_image_name = device().owner()->tag(); + m_working_directory = ""; + m_basename = ""; + m_basename_noext = ""; + m_filetype = ""; +} + //------------------------------------------------- // is_filetype - check if the filetype matches @@ -144,9 +296,20 @@ bool device_image_interface::is_filetype(std::string_view candidate_filetype) co } -/**************************************************************************** - CREATION FORMATS -****************************************************************************/ +//------------------------------------------------- +// add_media_change_notifier - subscribe for +// media change notifications +//------------------------------------------------- + +util::notifier_subscription device_image_interface::add_media_change_notifier(delegate<void (media_change_event)> &&n) +{ + return m_media_change_notifier.subscribe(std::move(n)); +} + + +//*************************************************************************** +// CREATION FORMATS +//*************************************************************************** //------------------------------------------------- // device_get_named_creatable_format - @@ -184,21 +347,9 @@ void device_image_interface::add_format(std::string &&name, std::string &&descri } -/**************************************************************************** - ERROR HANDLING -****************************************************************************/ - -//------------------------------------------------- -// clear_error - clear out any specified error -//------------------------------------------------- - -void device_image_interface::clear_error() noexcept -{ - m_err.clear(); - m_err_message.clear(); -} - - +//*************************************************************************** +// ERROR HANDLING +//*************************************************************************** //------------------------------------------------- // error - returns the error text for an image @@ -220,7 +371,10 @@ std::error_category const &image_category() noexcept "Internal error"sv, "Unsupported operation"sv, "Invalid image"sv, + "Invalid image length"sv, "File already open"sv, + "Unrecognized software item"sv, + "Invalid software item"sv, "Unspecified error"sv }; if ((0 <= condition) && (std::size(s_messages) > condition)) return std::string(s_messages[condition]); @@ -232,50 +386,6 @@ std::error_category const &image_category() noexcept return s_image_category_instance; } -std::string_view device_image_interface::error() -{ - if (m_err && m_err_message.empty()) - m_err_message = m_err.message(); - return m_err_message; -} - - - -//------------------------------------------------- -// seterror - specifies an error on an image -//------------------------------------------------- - -void device_image_interface::seterror(std::error_condition err, const char *message) -{ - clear_error(); - m_err = err; - if (message) - m_err_message = message; -} - - - -//------------------------------------------------- -// message - used to display a message while -// loading -//------------------------------------------------- - -void device_image_interface::message(const char *format, ...) -{ - va_list args; - char buffer[256]; - - /* format the message */ - va_start(args, format); - vsnprintf(buffer, std::size(buffer), format, args); - va_end(args); - - /* display the popup for a standard amount of time */ - device().machine().ui().popup_time(5, "%s: %s", - basename(), - buffer); -} - //------------------------------------------------- // software_entry - return a pointer to the @@ -297,9 +407,8 @@ u8 *device_image_interface::get_software_region(std::string_view tag) if (!loaded_through_softlist()) return nullptr; - std::string full_tag = util::string_format("%s:%s", device().tag(), tag); - memory_region *region = device().machine().root_device().memregion(full_tag); - return region != nullptr ? region->base() : nullptr; + memory_region *const region = device().memregion(tag); + return region ? region->base() : nullptr; } @@ -309,9 +418,11 @@ u8 *device_image_interface::get_software_region(std::string_view tag) u32 device_image_interface::get_software_region_length(std::string_view tag) { - std::string full_tag = util::string_format("%s:%s", device().tag(), tag); - memory_region *region = device().machine().root_device().memregion(full_tag); - return region != nullptr ? region->bytes() : 0; + if (!loaded_through_softlist()) + return 0; + + memory_region *const region = device().memregion(tag); + return region ? region->bytes() : 0; } @@ -329,7 +440,7 @@ const char *device_image_interface::get_feature(std::string_view feature_name) c // load_software_region - //------------------------------------------------- -bool device_image_interface::load_software_region(std::string_view tag, std::unique_ptr<u8[]> &ptr) +std::error_condition device_image_interface::load_software_region(std::string_view tag, std::unique_ptr<u8[]> &ptr) { size_t size = get_software_region_length(tag); @@ -337,9 +448,10 @@ bool device_image_interface::load_software_region(std::string_view tag, std::uni { ptr = std::make_unique<u8[]>(size); memcpy(ptr.get(), get_software_region(tag), size); + return std::error_condition(); } - - return size > 0; + else + return image_error::UNSUPPORTED; } @@ -373,7 +485,7 @@ std::error_condition device_image_interface::run_hash(util::random_read &file, u -bool device_image_interface::image_checkhash() +std::error_condition device_image_interface::image_checkhash() { // only calculate CRC if it hasn't been calculated, and the open_mode is read only u32 crcval; @@ -382,17 +494,16 @@ bool device_image_interface::image_checkhash() // do not cause a linear read of 600 megs please // TODO: use SHA1 in the CHD header as the hash if (image_is_chd_type()) - return true; + return std::error_condition(); // Skip calculating the hash when we have an image mounted through a software list if (loaded_through_softlist()) - return true; + return std::error_condition(); // run the hash - if (run_hash(*m_file, unhashed_header_length(), m_hash, util::hash_collection::HASH_TYPES_ALL)) - return false; + return run_hash(*m_file, unhashed_header_length(), m_hash, util::hash_collection::HASH_TYPES_ALL); } - return true; + return std::error_condition(); } @@ -561,15 +672,20 @@ std::vector<u32> device_image_interface::determine_open_plan(bool is_create) { std::vector<u32> open_plan; - // emit flags into a vector - if (!is_create && is_readable() && is_writeable()) - open_plan.push_back(OPEN_FLAG_READ | OPEN_FLAG_WRITE); - if (!is_create && !is_readable() && is_writeable()) - open_plan.push_back(OPEN_FLAG_WRITE); - if (!is_create && is_readable()) - open_plan.push_back(OPEN_FLAG_READ); - if (is_create && is_writeable() && is_creatable()) - open_plan.push_back(OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); + if (!is_create) + { + if (is_writeable()) + open_plan.push_back(is_readable() ? (OPEN_FLAG_READ | OPEN_FLAG_WRITE) : OPEN_FLAG_WRITE); + if (is_readable()) + open_plan.push_back(OPEN_FLAG_READ); + } + else if (is_writeable() && is_creatable()) + { + if (is_readable()) + open_plan.push_back(OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); + else + open_plan.push_back(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); + } return open_plan; } @@ -621,9 +737,9 @@ static int verify_length_and_hash(emu_file *file, std::string_view name, u32 exp // load_software - software image loading //------------------------------------------------- -bool device_image_interface::load_software(software_list_device &swlist, std::string_view swname, const rom_entry *start) +std::error_condition device_image_interface::load_software(software_list_device &swlist, std::string_view swname, const rom_entry *start) { - bool retval = false; + std::error_condition retval; int warningcount = 0; for (const rom_entry *region = start; region; region = rom_next_region(region)) { @@ -635,7 +751,7 @@ bool device_image_interface::load_software(software_list_device &swlist, std::st { const software_info *const swinfo = swlist.find(std::string(swname)); if (!swinfo) - return false; + return image_error::NOSOFTWARE; if (swinfo->supported() == software_support::PARTIALLY_SUPPORTED) osd_printf_error("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist.list_name()); @@ -688,8 +804,8 @@ bool device_image_interface::load_software(software_list_device &swlist, std::st if (!filerr) filerr = util::core_file::open_proxy(*m_mame_file, m_file); - if (!filerr) - retval = true; + if (filerr) + retval = filerr; break; // load first item for start } @@ -707,16 +823,16 @@ bool device_image_interface::load_software(software_list_device &swlist, std::st // load_internal - core image loading //------------------------------------------------- -image_init_result device_image_interface::load_internal(std::string_view path, bool is_create, int create_format, util::option_resolution *create_args) +std::pair<std::error_condition, std::string> device_image_interface::load_internal(std::string_view path, bool is_create, int create_format, util::option_resolution *create_args) { + std::pair<std::error_condition, std::string> err; + // first unload the image unload(); - // clear any possible error messages - clear_error(); - // we are now loading m_is_loading = true; + m_sequence_counter++; // record the filename set_image_filename(path); @@ -724,50 +840,47 @@ image_init_result device_image_interface::load_internal(std::string_view path, b if (core_opens_image_file()) { // determine open plan - std::vector<u32> open_plan = determine_open_plan(is_create); + std::vector<u32> const open_plan = determine_open_plan(is_create); // attempt to open the file in various ways for (auto iter = open_plan.cbegin(); !m_file && iter != open_plan.cend(); iter++) { // open the file - m_err = load_image_by_path(*iter, path); - if (m_err && (m_err != std::errc::no_such_file_or_directory) && (m_err != std::errc::permission_denied)) - goto done; + err.first = load_image_by_path(*iter, path); + if (err.first && (err.first != std::errc::no_such_file_or_directory) && (err.first != std::errc::permission_denied)) + break; } // did we fail to find the file? - if (!m_file) - { - m_err = std::errc::no_such_file_or_directory; - goto done; - } + if (!err.first && !m_file) + err.first = std::errc::no_such_file_or_directory; } - // call device load or create - m_create_format = create_format; - m_create_args = create_args; - - if (!init_phase()) + if (!err.first) { - m_err = (finish_load() == image_init_result::PASS) ? std::error_condition() : image_error::INTERNAL; - if (m_err) - goto done; + // call device load or create + m_create_format = create_format; + m_create_args = create_args; + + if (!init_phase()) + err = finish_load(); } - // success! -done: - if (m_err) + if (err.first) { - if (!init_phase()) - { - if (device().machine().phase() == machine_phase::RUNNING) - device().popmessage("Error: Unable to %s image '%s': %s", is_create ? "create" : "load", path, error()); - else - osd_printf_error("Error: Unable to %s image '%s': %s\n", is_create ? "create" : "load", path, error()); - } + osd_printf_error( + !err.second.empty() + ? (is_create ? "Unable to create image '%1$s': %2$s (%3$s:%4$d %5$s)\n" : "Unable to load image '%1$s': %2$s (%3$s:%4$d %5$s)\n") + : (is_create ? "Unable to create image '%1$s': %5$s (%3$s:%4$d)\n" : "Unable to load image '%1$s': %5$s (%3$s:%4$d)\n"), + path, + err.second, + err.first.category().name(), + err.first.value(), + err.first.message()); clear(); } - return m_err ? image_init_result::FAIL : image_init_result::PASS; + + return err; } @@ -775,13 +888,13 @@ done: // load - load an image into MAME //------------------------------------------------- -image_init_result device_image_interface::load(std::string_view path) +std::pair<std::error_condition, std::string> device_image_interface::load(std::string_view path) { // is this a reset on load item? if (is_reset_on_load() && !init_phase()) { reset_and_load(path); - return image_init_result::PASS; + return std::make_pair(std::error_condition(), std::string()); } return load_internal(path, false, 0, nullptr); @@ -792,26 +905,26 @@ image_init_result device_image_interface::load(std::string_view path) // load_software - loads a softlist item by name //------------------------------------------------- -image_init_result device_image_interface::load_software(std::string_view software_identifier) +std::pair<std::error_condition, std::string> device_image_interface::load_software(std::string_view software_identifier) { // Is this a software part that forces a reset and we're at runtime? If so, get this loaded through reset_and_load if (is_reset_on_load() && !init_phase()) { reset_and_load(software_identifier); - return image_init_result::PASS; + return std::make_pair(std::error_condition(), std::string()); } // Prepare to load unload(); - clear_error(); m_is_loading = true; // Check if there's a software list defined for this device and use that if we're not creating an image - bool softload = load_software_part(software_identifier); - if (!softload) + std::pair<std::error_condition, std::string> err; + err.first = load_software_part(software_identifier); + if (err.first) { m_is_loading = false; - return image_init_result::FAIL; + return err; } // set up softlist stuff @@ -821,9 +934,10 @@ image_init_result device_image_interface::load_software(std::string_view softwar m_image_name = m_full_software_name; m_basename = m_full_software_name; m_basename_noext = m_full_software_name; - m_filetype = use_software_list_file_extension_for_filetype() && m_mame_file != nullptr - ? std::string(core_filename_extract_extension(m_mame_file->filename(), true)) - : ""; + if (use_software_list_file_extension_for_filetype() && m_mame_file) + m_filetype = core_filename_extract_extension(m_mame_file->filename(), true); + else + m_filetype.clear(); // Copy some image information when we have been loaded through a software list software_info &swinfo = m_software_part_ptr->info(); @@ -833,16 +947,31 @@ image_init_result device_image_interface::load_software(std::string_view softwar fatalerror("Each entry in an XML list must have all of the following fields: description, publisher, year!\n"); // set file type - std::string filename = (m_mame_file != nullptr) && (m_mame_file->filename() != nullptr) + std::string filename = (m_mame_file && m_mame_file->filename()) ? m_mame_file->filename() : ""; m_filetype = core_filename_extract_extension(filename, true); // call finish_load if necessary - if (init_phase() == false && (finish_load() != image_init_result::PASS)) - return image_init_result::FAIL; + if (!init_phase()) + { + err = finish_load(); + if (err.first) + { + osd_printf_error( + !err.second.empty() + ? "Unable to load software item '%1$s': %2$s (%3$s:%4$d %5$s)\n" + : "Unable to load software item '%1$s': %5$s (%3$s:%4$d)\n", + software_identifier, + err.second, + err.first.category().name(), + err.first.value(), + err.first.message()); + clear(); + } + } - return image_init_result::PASS; + return err; } @@ -851,53 +980,38 @@ image_init_result device_image_interface::load_software(std::string_view softwar // from core //------------------------------------------------- -image_init_result device_image_interface::finish_load() +std::pair<std::error_condition, std::string> device_image_interface::finish_load() { - image_init_result err = image_init_result::PASS; + std::pair<std::error_condition, std::string> err; if (m_is_loading) { - if (!image_checkhash()) - { - m_err = image_error::INVALIDIMAGE; - err = image_init_result::FAIL; - } + err.first = image_checkhash(); - if (err == image_init_result::PASS) + if (!err.first) { if (m_created) - { err = call_create(m_create_format, m_create_args); - if (err != image_init_result::PASS) - { - if (!m_err) - m_err = image_error::UNSPECIFIED; - } - } else - { - // using device load - err = call_load(); - if (err != image_init_result::PASS) - { - if (!m_err) - m_err = image_error::UNSPECIFIED; - } - } + err = call_load(); // using device load } } + m_is_loading = false; m_create_format = 0; m_create_args = nullptr; + if (!err.first) + m_media_change_notifier(media_change_event::LOADED); + return err; } //------------------------------------------------- -// create - create a image +// create - create an image //------------------------------------------------- -image_init_result device_image_interface::create(std::string_view path) +std::pair<std::error_condition, std::string> device_image_interface::create(std::string_view path) { return create(path, nullptr, nullptr); } @@ -907,13 +1021,14 @@ image_init_result device_image_interface::create(std::string_view path) // create - create a image //------------------------------------------------- -image_init_result device_image_interface::create(std::string_view path, const image_device_format *create_format, util::option_resolution *create_args) +std::pair<std::error_condition, std::string> device_image_interface::create(std::string_view path, const image_device_format *create_format, util::option_resolution *create_args) { int format_index = 0; int cnt = 0; for (auto &format : m_formatlist) { - if (create_format == format.get()) { + if (create_format == format.get()) + { format_index = cnt; break; } @@ -947,7 +1062,7 @@ void device_image_interface::reset_and_load(std::string_view path) // to an image //------------------------------------------------- -void device_image_interface::clear() +void device_image_interface::clear() noexcept { m_mame_file.reset(); m_file.reset(); @@ -967,6 +1082,8 @@ void device_image_interface::clear() m_software_list_name.clear(); m_hash.reset(); + + m_sequence_counter++; } @@ -978,10 +1095,15 @@ void device_image_interface::unload() { if (is_loaded() || loaded_through_softlist()) { + m_sequence_counter++; call_unload(); + clear(); + m_media_change_notifier(media_change_event::UNLOADED); + } + else + { + clear(); // just to make sure everything is reset } - clear(); - clear_error(); } @@ -1122,7 +1244,7 @@ const software_list_loader &device_image_interface::get_software_list_loader() c // sw_info and sw_part are also set. //------------------------------------------------- -bool device_image_interface::load_software_part(std::string_view identifier) +std::error_condition device_image_interface::load_software_part(std::string_view identifier) { // if no match has been found, we suggest similar shortnames software_list_device *swlist; @@ -1130,14 +1252,14 @@ bool device_image_interface::load_software_part(std::string_view identifier) if (m_software_part_ptr == nullptr) { software_list_device::display_matches(device().machine().config(), image_interface(), identifier); - return false; + return image_error::NOSOFTWARE; } // Load the software part const std::string &swname = m_software_part_ptr->info().shortname(); const rom_entry *start_entry = m_software_part_ptr->romdata().data(); const software_list_loader &loader = get_software_list_loader(); - bool result = loader.load_software(*this, *swlist, swname, start_entry); + std::error_condition result = loader.load_software(*this, *swlist, swname, start_entry); // check compatibility switch (swlist->is_compatible(*m_software_part_ptr)) diff --git a/src/emu/diimage.h b/src/emu/diimage.h index 08d48020cc3..aa9c991c955 100644 --- a/src/emu/diimage.h +++ b/src/emu/diimage.h @@ -17,11 +17,13 @@ #ifndef MAME_EMU_DIIMAGE_H #define MAME_EMU_DIIMAGE_H +#include "notifier.h" #include "utilfwd.h" #include <memory> #include <string> #include <system_error> +#include <utility> #include <vector> @@ -34,7 +36,10 @@ enum class image_error : int INTERNAL = 1, UNSUPPORTED, INVALIDIMAGE, + INVALIDLENGTH, ALREADYOPEN, + NOSOFTWARE, + BADSOFTWARE, UNSPECIFIED }; @@ -61,37 +66,26 @@ private: }; -enum class image_init_result { PASS, FAIL }; -enum class image_verify_result { PASS, FAIL }; - -//************************************************************************** -// MACROS -//************************************************************************** - -#define DEVICE_IMAGE_LOAD_MEMBER(_name) image_init_result _name(device_image_interface &image) -#define DECLARE_DEVICE_IMAGE_LOAD_MEMBER(_name) DEVICE_IMAGE_LOAD_MEMBER(_name) - -#define DEVICE_IMAGE_UNLOAD_MEMBER(_name) void _name(device_image_interface &image) -#define DECLARE_DEVICE_IMAGE_UNLOAD_MEMBER(_name) DEVICE_IMAGE_UNLOAD_MEMBER(_name) - - // ======================> device_image_interface // class representing interface-specific live image class device_image_interface : public device_interface { public: - typedef device_delegate<image_init_result (device_image_interface &)> load_delegate; - typedef device_delegate<void (device_image_interface &)> unload_delegate; + enum class media_change_event + { + LOADED, + UNLOADED + }; - typedef std::vector<std::unique_ptr<image_device_format>> formatlist_type; + using formatlist_type = std::vector<std::unique_ptr<image_device_format> >; // construction/destruction device_image_interface(const machine_config &mconfig, device_t &device); virtual ~device_image_interface(); - virtual image_init_result call_load() { return image_init_result::PASS; } - virtual image_init_result call_create(int format_type, util::option_resolution *format_options) { return image_init_result::PASS; } + virtual std::pair<std::error_condition, std::string> call_load() { return std::make_pair(std::error_condition(), std::string()); } + virtual std::pair<std::error_condition, std::string> call_create(int format_type, util::option_resolution *format_options) { return std::make_pair(std::error_condition(), std::string()); } virtual void call_unload() { } virtual std::string call_display() { return std::string(); } virtual u32 unhashed_header_length() const noexcept { return 0; } @@ -108,14 +102,20 @@ public: virtual const char *image_type_name() const noexcept = 0; virtual const char *image_brief_type_name() const noexcept = 0; + // Set block device image regions for arcade systems + void add_region(std::string name, bool is_default = false); + bool has_preset_images() const; + bool has_preset_images_selection() const; + std::vector<std::string> preset_images_list() const; + int current_preset_image_id() const; + void switch_preset_image(int id); + chd_file *current_preset_image_chd() const; + void check_preset_images(); + const image_device_format *device_get_indexed_creatable_format(int index) const noexcept { return (index < m_formatlist.size()) ? m_formatlist.at(index).get() : nullptr; } const image_device_format *device_get_named_creatable_format(std::string_view format_name) const noexcept; const util::option_guide &device_get_creation_option_guide() const { return create_option_guide(); } - std::string_view error(); - void seterror(std::error_condition err, const char *message = nullptr); - void message(const char *format, ...) ATTR_PRINTF(2,3); - bool exists() const noexcept { return !m_image_name.empty(); } // get image file path/name @@ -129,6 +129,12 @@ public: util::core_file &image_core_file() const noexcept { assert(is_open()); return *m_file; } bool is_readonly() const noexcept { return m_readonly; } + u32 sequence_counter() const { return m_sequence_counter; } // Increments on media load/unload/etc + util::notifier_subscription add_media_change_notifier(delegate<void (media_change_event)> &&n); + template <typename T> + util::notifier_subscription add_media_change_notifier(T &&n) + { return add_media_change_notifier(delegate<void (media_change_event)>(std::forward<T>(n))); } + // image file I/O wrappers // TODO: move away from using these and let implementations use the I/O interface directly // FIXME: don't swallow errors @@ -142,15 +148,13 @@ public: u32 fread(void *buffer, u32 length) { check_for_file(); - size_t actual; - m_file->read(buffer, length, actual); + auto const [err, actual] = read(*m_file, buffer, length); return actual; } u32 fwrite(const void *buffer, u32 length) { check_for_file(); - size_t actual; - m_file->write(buffer, length, actual); + auto const [err, actual] = write(*m_file, buffer, length); return actual; } std::error_condition fseek(s64 offset, int whence) @@ -165,15 +169,6 @@ public: m_file->tell(result); return result; } - bool image_feof() - { - check_for_file(); - return m_file->eof(); - } - - // allocate and read into buffers - u32 fread(std::unique_ptr<u8 []> &ptr, u32 length) { ptr = std::make_unique<u8 []>(length); return fread(ptr.get(), length); } - u32 fread(std::unique_ptr<u8 []> &ptr, u32 length, offs_t offset) { ptr = std::make_unique<u8 []>(length); return fread(ptr.get() + offset, length - offset); } // access to software list item information const software_info *software_entry() const noexcept; @@ -190,10 +185,10 @@ public: u8 *get_software_region(std::string_view tag); u32 get_software_region_length(std::string_view tag); const char *get_feature(std::string_view feature_name) const; - bool load_software_region(std::string_view tag, std::unique_ptr<u8[]> &ptr); + std::error_condition load_software_region(std::string_view tag, std::unique_ptr<u8[]> &ptr); u32 crc(); - util::hash_collection& hash() { return m_hash; } + util::hash_collection &hash() { return m_hash; } util::hash_collection calculate_hash_on_file(util::random_read &file) const; void battery_load(void *buffer, int length, int fill); @@ -206,16 +201,16 @@ public: const formatlist_type &formatlist() const { return m_formatlist; } // loads an image file - image_init_result load(std::string_view path); + std::pair<std::error_condition, std::string> load(std::string_view path); // loads a softlist item by name - image_init_result load_software(std::string_view software_identifier); + std::pair<std::error_condition, std::string> load_software(std::string_view software_identifier); - image_init_result finish_load(); + std::pair<std::error_condition, std::string> finish_load(); void unload(); - image_init_result create(std::string_view path, const image_device_format *create_format, util::option_resolution *create_args); - image_init_result create(std::string_view path); - bool load_software(software_list_device &swlist, std::string_view swname, const rom_entry *entry); + std::pair<std::error_condition, std::string> create(std::string_view path, const image_device_format *create_format, util::option_resolution *create_args); + std::pair<std::error_condition, std::string> create(std::string_view path); + std::error_condition load_software(software_list_device &swlist, std::string_view swname, const rom_entry *entry); std::error_condition reopen_for_write(std::string_view path); void set_user_loadable(bool user_loadable) noexcept { m_user_loadable = user_loadable; } @@ -227,26 +222,22 @@ public: const std::string &full_software_name() const noexcept { return m_full_software_name; } protected: - // interface-level overrides + // device_interface implementation virtual void interface_config_complete() override; virtual const software_list_loader &get_software_list_loader() const; - virtual const bool use_software_list_file_extension_for_filetype() const { return false; } + virtual bool use_software_list_file_extension_for_filetype() const noexcept { return false; } - image_init_result load_internal(std::string_view path, bool is_create, int create_format, util::option_resolution *create_args); std::error_condition load_image_by_path(u32 open_flags, std::string_view path); - void clear(); - bool is_loaded() const { return m_file != nullptr; } - - void set_image_filename(std::string_view filename); + bool is_loaded() const noexcept { return m_file != nullptr; } - void clear_error() noexcept; + void set_image_tag(); void check_for_file() const { if (!m_file) throw emu_fatalerror("%s(%s): Illegal operation on unmounted image", device().shortname(), device().tag()); } void make_readonly() noexcept { m_readonly = true; } - bool image_checkhash(); + std::error_condition image_checkhash(); const software_part *find_software_item(std::string_view identifier, bool restrict_to_interface, software_list_device **device = nullptr) const; std::string software_get_default_slot(std::string_view default_card_slot) const; @@ -254,11 +245,21 @@ protected: void add_format(std::unique_ptr<image_device_format> &&format); void add_format(std::string &&name, std::string &&description, std::string &&extensions, std::string &&optspec); - // error related info - std::error_condition m_err; - std::string m_err_message; - private: + std::vector<u32> determine_open_plan(bool is_create); + void update_names(); + void set_image_filename(std::string_view filename); + void clear() noexcept; + std::pair<std::error_condition, std::string> load_internal(std::string_view path, bool is_create, int create_format, util::option_resolution *create_args); + std::error_condition load_software_part(std::string_view identifier); + + bool init_phase() const; + static std::error_condition run_hash(util::random_read &file, u32 skip_bytes, util::hash_collection &hashes, const char *types); + + // loads an image or software items and resets - called internally when we + // load an is_reset_on_load() item + void reset_and_load(std::string_view path); + // variables that are only non-zero when an image is mounted util::core_file::ptr m_file; std::unique_ptr<emu_file> m_mame_file; @@ -267,29 +268,27 @@ private: std::string m_basename_noext; std::string m_filetype; + // preset images regions + std::vector<std::string> m_possible_preset_regions; + std::vector<chd_file *> m_preset_images; + int m_default_region, m_current_region; + // Software information std::string m_full_software_name; const software_part *m_software_part_ptr; std::string m_software_list_name; - std::vector<u32> determine_open_plan(bool is_create); - void update_names(); - bool load_software_part(std::string_view identifier); - - bool init_phase() const; - static std::error_condition run_hash(util::random_read &file, u32 skip_bytes, util::hash_collection &hashes, const char *types); - - // loads an image or software items and resets - called internally when we - // load an is_reset_on_load() item - void reset_and_load(std::string_view path); - // creation info formatlist_type m_formatlist; // working directory; persists across mounts std::string m_working_directory; + // to notify interested parties when media changes + util::notifier<media_change_event> m_media_change_notifier; + // flags + u32 m_sequence_counter; bool m_readonly; bool m_created; @@ -317,4 +316,4 @@ private: // iterator typedef device_interface_enumerator<device_image_interface> image_interface_enumerator; -#endif /* MAME_EMU_DIIMAGE_H */ +#endif // MAME_EMU_DIIMAGE_H diff --git a/src/emu/dimemory.cpp b/src/emu/dimemory.cpp index aa438fd22c0..81958b4f571 100644 --- a/src/emu/dimemory.cpp +++ b/src/emu/dimemory.cpp @@ -66,9 +66,10 @@ void device_memory_interface::set_addrmap(int spacenum, address_map_constructor // translation is supported //------------------------------------------------- -bool device_memory_interface::memory_translate(int spacenum, int intention, offs_t &address) +bool device_memory_interface::memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) { // by default it maps directly + target_space = &space(spacenum); return true; } diff --git a/src/emu/dimemory.h b/src/emu/dimemory.h index 119ec9bc6f9..14cd4d48ae2 100644 --- a/src/emu/dimemory.h +++ b/src/emu/dimemory.h @@ -19,34 +19,6 @@ #include <type_traits> - -//************************************************************************** -// CONSTANTS -//************************************************************************** - -// Translation intentions -constexpr int TRANSLATE_TYPE_MASK = 0x03; // read write or fetch -constexpr int TRANSLATE_USER_MASK = 0x04; // user mode or fully privileged -constexpr int TRANSLATE_DEBUG_MASK = 0x08; // debug mode (no side effects) - -constexpr int TRANSLATE_READ = 0; // translate for read -constexpr int TRANSLATE_WRITE = 1; // translate for write -constexpr int TRANSLATE_FETCH = 2; // translate for instruction fetch -constexpr int TRANSLATE_READ_USER = (TRANSLATE_READ | TRANSLATE_USER_MASK); -constexpr int TRANSLATE_WRITE_USER = (TRANSLATE_WRITE | TRANSLATE_USER_MASK); -constexpr int TRANSLATE_FETCH_USER = (TRANSLATE_FETCH | TRANSLATE_USER_MASK); -constexpr int TRANSLATE_READ_DEBUG = (TRANSLATE_READ | TRANSLATE_DEBUG_MASK); -constexpr int TRANSLATE_WRITE_DEBUG = (TRANSLATE_WRITE | TRANSLATE_DEBUG_MASK); -constexpr int TRANSLATE_FETCH_DEBUG = (TRANSLATE_FETCH | TRANSLATE_DEBUG_MASK); - - - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> device_memory_interface - class device_memory_interface : public device_interface { friend class device_scheduler; @@ -57,6 +29,13 @@ class device_memory_interface : public device_interface template <typename T, typename U> using is_unrelated_interface = std::bool_constant<emu::detail::is_device_interface<T>::value && !is_related_class<T, U>::value >; public: + // Translation intentions for the translate() call + enum { + TR_READ, + TR_WRITE, + TR_FETCH + }; + // construction/destruction device_memory_interface(const machine_config &mconfig, device_t &device); virtual ~device_memory_interface(); @@ -85,7 +64,7 @@ public: address_space &space(int index = 0) const { assert(index >= 0 && index < int(m_addrspace.size()) && m_addrspace[index]); return *m_addrspace[index]; } // address translation - bool translate(int spacenum, int intention, offs_t &address) { return memory_translate(spacenum, intention, address); } + bool translate(int spacenum, int intention, offs_t &address, address_space *&target_space) { return memory_translate(spacenum, intention, address, target_space); } // deliberately ambiguous functions; if you have the memory interface // just use it @@ -110,7 +89,7 @@ protected: virtual space_config_vector memory_space_config() const = 0; // optional operation overrides - virtual bool memory_translate(int spacenum, int intention, offs_t &address); + virtual bool memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space); // interface-level overrides virtual void interface_config_complete() override; diff --git a/src/emu/dinetwork.cpp b/src/emu/dinetwork.cpp index 2091ac6a2c3..bbc5ee3054d 100644 --- a/src/emu/dinetwork.cpp +++ b/src/emu/dinetwork.cpp @@ -3,16 +3,21 @@ #include "emu.h" #include "dinetwork.h" + #include "osdnet.h" +#include <algorithm> + + device_network_interface::device_network_interface(const machine_config &mconfig, device_t &device, u32 bandwidth, u32 mtu) : device_interface(device, "network") + , m_poll_timer(nullptr) + , m_send_timer(nullptr) + , m_recv_timer(nullptr) { - m_promisc = false; // Convert to Mibps to Bps m_bandwidth = bandwidth << (20 - 3); m_mtu = mtu; - set_mac("\0\0\0\0\0\0"); m_intf = -1; m_loopback_control = false; } @@ -21,15 +26,23 @@ device_network_interface::~device_network_interface() { } -void device_network_interface::interface_pre_start() +void device_network_interface::interface_post_start() { + m_poll_timer = device().machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(device_network_interface::poll_device), this)); m_send_timer = device().machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(device_network_interface::send_complete), this)); m_recv_timer = device().machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(device_network_interface::recv_complete), this)); + + device().save_item(NAME(m_loopback_control)); } -void device_network_interface::interface_post_start() +void device_network_interface::interface_post_load() { - device().save_item(NAME(m_loopback_control)); + if (!m_dev) + m_poll_timer->reset(); + else if (!m_loopback_control && !m_recv_timer->enabled()) + start_net_device(); + else + stop_net_device(); } int device_network_interface::send(u8 *buf, int len, int fcs) @@ -65,6 +78,25 @@ int device_network_interface::send(u8 *buf, int len, int fcs) return result; } +TIMER_CALLBACK_MEMBER(device_network_interface::poll_device) +{ + m_dev->poll(); +} + +void device_network_interface::start_net_device() +{ + // Set device polling time to transfer time for one MTU + m_dev->start(); + const attotime interval = attotime::from_hz(m_bandwidth / m_mtu); + m_poll_timer->adjust(attotime::zero, 0, interval); +} + +void device_network_interface::stop_net_device() +{ + m_poll_timer->reset(); + m_dev->stop(); +} + TIMER_CALLBACK_MEMBER(device_network_interface::send_complete) { send_complete_cb(param); @@ -85,7 +117,7 @@ void device_network_interface::recv_cb(u8 *buf, int len) { // stop receiving more data from the network if (m_dev) - m_dev->stop(); + stop_net_device(); // schedule receive complete callback m_recv_timer->adjust(attotime::from_ticks(len, m_bandwidth), result); @@ -98,28 +130,36 @@ TIMER_CALLBACK_MEMBER(device_network_interface::recv_complete) // start receiving data from the network again if (m_dev && !m_loopback_control) - m_dev->start(); + start_net_device(); } void device_network_interface::set_promisc(bool promisc) { m_promisc = promisc; - if(m_dev) m_dev->set_promisc(promisc); + if (m_dev) + m_dev->set_promisc(promisc); } -void device_network_interface::set_mac(const char *mac) +void device_network_interface::set_mac(const u8 *mac) { - memcpy(m_mac, mac, 6); - if(m_dev) m_dev->set_mac(m_mac); + std::copy_n(mac, std::size(m_mac), std::begin(m_mac)); + if (m_dev) + m_dev->set_mac(&m_mac[0]); } void device_network_interface::set_interface(int id) { - if(m_dev) - m_dev->stop(); - // Set device polling time to transfer time for one mtu - m_dev.reset(open_netdev(id, this, (int)(m_bandwidth / m_mtu))); - if(!m_dev) { + if (m_dev) + stop_net_device(); + + m_dev.reset(open_netdev(id, *this)); + if (m_dev) + { + if (!m_loopback_control) + start_net_device(); + } + else + { device().logerror("Network interface %d not found\n", id); id = -1; } @@ -136,8 +176,8 @@ void device_network_interface::set_loopback(bool loopback) if (m_dev) { if (loopback) - m_dev->stop(); + stop_net_device(); else if (!m_recv_timer->enabled()) - m_dev->start(); + start_net_device(); } } diff --git a/src/emu/dinetwork.h b/src/emu/dinetwork.h index c2629f665fc..522f8b8d041 100644 --- a/src/emu/dinetwork.h +++ b/src/emu/dinetwork.h @@ -3,30 +3,31 @@ #ifndef MAME_EMU_DINETWORK_H #define MAME_EMU_DINETWORK_H -class osd_netdev; +#include "interface/nethandler.h" -class device_network_interface : public device_interface + +class osd_network_device; + +class device_network_interface : public device_interface, public osd::network_handler { public: device_network_interface(const machine_config &mconfig, device_t &device, u32 bandwidth, u32 mtu = 1500); virtual ~device_network_interface(); - void interface_pre_start() override; - void interface_post_start() override; + void interface_post_start() override ATTR_COLD; + void interface_post_load() override ATTR_COLD; - void set_interface(int id); + void set_interface(int id) ATTR_COLD; void set_promisc(bool promisc); - void set_mac(const char *mac); + void set_mac(const u8 *mac); void set_loopback(bool loopback); - const char *get_mac() const { return m_mac; } - bool get_promisc() const { return m_promisc; } int get_interface() const { return m_intf; } int send(u8 *buf, int len, int fcs = 0); // TODO: de-virtualise this when existing devices implement delayed receive - virtual void recv_cb(u8 *buf, int len); + virtual void recv_cb(u8 *buf, int len) override; // delayed transmit/receive handlers virtual void send_complete_cb(int result) {} @@ -34,19 +35,25 @@ public: virtual void recv_complete_cb(int result) {} protected: - TIMER_CALLBACK_MEMBER(send_complete); - TIMER_CALLBACK_MEMBER(recv_complete); + bool has_net_device() const noexcept { return bool(m_dev); } - bool m_promisc; - char m_mac[6]; // bandwidth in bytes per second u32 m_bandwidth; // maximum transmission unit, used for device polling time u32 m_mtu; - std::unique_ptr<osd_netdev> m_dev; int m_intf; bool m_loopback_control; +private: + TIMER_CALLBACK_MEMBER(poll_device); + TIMER_CALLBACK_MEMBER(send_complete); + TIMER_CALLBACK_MEMBER(recv_complete); + + void start_net_device(); + void stop_net_device(); + + std::unique_ptr<osd_network_device> m_dev; + emu_timer *m_poll_timer; emu_timer *m_send_timer; emu_timer *m_recv_timer; }; diff --git a/src/emu/dipty.h b/src/emu/dipty.h index 9fc1ddbc7e1..d2e92f14969 100644 --- a/src/emu/dipty.h +++ b/src/emu/dipty.h @@ -27,7 +27,7 @@ public: bool is_open() const; - ssize_t read(u8 *rx_chars , size_t count) const; + ssize_t read(u8 *rx_chars, size_t count) const; void write(u8 tx_char) const; bool is_slave_connected() const; diff --git a/src/emu/dirom.h b/src/emu/dirom.h index 8243400c547..72d844f8b0e 100644 --- a/src/emu/dirom.h +++ b/src/emu/dirom.h @@ -22,6 +22,7 @@ public: template <typename... T> void set_map(T &&... args) { set_addrmap(0, std::forward<T>(args)...); } template <typename T> void set_device_rom_tag(T &&tag) { m_rom_region.set_tag(std::forward<T>(tag)); } + template <typename T> void set_space(T &&tag, int spacenum) { m_rom_space.set_tag(tag, spacenum); } u8 read_byte(offs_t addr) { return m_rom_cache.read_byte(addr); } u16 read_word(offs_t addr) { return m_rom_cache.read_word(addr); } @@ -32,13 +33,15 @@ public: void set_rom_bank(int bank); protected: - virtual void rom_bank_updated() = 0; + virtual void rom_bank_pre_change() { } + virtual void rom_bank_post_change() { } virtual space_config_vector memory_space_config() const override; void override_address_width(u8 width); private: optional_memory_region m_rom_region; + optional_address_space m_rom_space; address_space_config m_rom_config; typename memory_access<AddrWidth, DataWidth, AddrShift, Endian>::cache m_rom_cache; diff --git a/src/emu/dirom.ipp b/src/emu/dirom.ipp index 24697a0fbba..d41da70a618 100644 --- a/src/emu/dirom.ipp +++ b/src/emu/dirom.ipp @@ -9,6 +9,7 @@ template<int AddrWidth, int DataWidth, int AddrShift, endianness_t Endian> device_rom_interface<AddrWidth, DataWidth, AddrShift, Endian>::device_rom_interface(const machine_config &mconfig, device_t &device) : device_memory_interface(mconfig, device), m_rom_region(device, DEVICE_SELF), + m_rom_space(device, finder_base::DUMMY_TAG, -1), m_rom_config("rom", Endian, 8 << DataWidth, AddrWidth, AddrShift), m_bank(device, "bank"), m_cur_bank(-1) @@ -45,9 +46,10 @@ void device_rom_interface<AddrWidth, DataWidth, AddrShift, Endian>::set_rom_bank } if (m_cur_bank != bank) { + rom_bank_pre_change(); m_cur_bank = bank; m_bank->set_entry(bank); - rom_bank_updated(); + rom_bank_post_change(); } } @@ -108,6 +110,11 @@ void device_rom_interface<AddrWidth, DataWidth, AddrShift, Endian>::interface_pr { device_memory_interface::interface_pre_start(); + if(m_rom_space.spacenum() != -1) { + m_rom_space->cache(m_rom_cache); + return; + } + if(!has_space(0)) return; diff --git a/src/emu/dirtc.cpp b/src/emu/dirtc.cpp index f3c61dede01..bf1a9366578 100644 --- a/src/emu/dirtc.cpp +++ b/src/emu/dirtc.cpp @@ -30,6 +30,7 @@ static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, device_rtc_interface::device_rtc_interface(const machine_config &mconfig, device_t &device) : device_interface(device, "rtc") + , m_use_utc(false) { } @@ -78,8 +79,9 @@ void device_rtc_interface::set_time(bool update, int year, int month, int day, i void device_rtc_interface::set_current_time(const system_time &systime) { - set_time(true, systime.local_time.year, systime.local_time.month + 1, systime.local_time.mday, systime.local_time.weekday + 1, - systime.local_time.hour, systime.local_time.minute, systime.local_time.second); + const system_time::full_time &time = m_use_utc ? systime.utc_time : systime.local_time; + set_time(true, time.year, time.month + 1, time.mday, time.weekday + 1, + time.hour, time.minute, time.second); } diff --git a/src/emu/dirtc.h b/src/emu/dirtc.h index 89a08deb830..e741cfc2628 100644 --- a/src/emu/dirtc.h +++ b/src/emu/dirtc.h @@ -47,8 +47,11 @@ public: device_rtc_interface(const machine_config &mconfig, device_t &device); virtual ~device_rtc_interface(); + // use UTC instead of local time when syncing at startup + void set_use_utc(bool use_utc) { m_use_utc = use_utc; } + void set_time(bool update, int year, int month, int day, int day_of_week, int hour, int minute, int second); - void set_current_time(const system_time &systime); + virtual void set_current_time(const system_time &systime); bool has_battery() const { return rtc_battery_backed(); } @@ -72,6 +75,8 @@ protected: virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) = 0; int m_register[7]; + + bool m_use_utc; }; // iterator diff --git a/src/emu/diserial.cpp b/src/emu/diserial.cpp index 21da108c045..e88aaafc3ca 100644 --- a/src/emu/diserial.cpp +++ b/src/emu/diserial.cpp @@ -10,9 +10,9 @@ #include "emu.h" #include "diserial.h" -#define LOG_SETUP (1 << 1U) -#define LOG_TX (1 << 2U) -#define LOG_RX (1 << 3U) +#define LOG_SETUP (1U << 1) +#define LOG_TX (1U << 2) +#define LOG_RX (1U << 3) #define VERBOSE (0) #define LOG_OUTPUT_FUNC device().logerror @@ -138,7 +138,7 @@ void device_serial_interface::rcv_edge() } } -WRITE_LINE_MEMBER(device_serial_interface::tx_clock_w) +void device_serial_interface::tx_clock_w(int state) { if(state != m_tra_clock_state) { m_tra_clock_state = state; @@ -147,7 +147,7 @@ WRITE_LINE_MEMBER(device_serial_interface::tx_clock_w) } } -WRITE_LINE_MEMBER(device_serial_interface::rx_clock_w) +void device_serial_interface::rx_clock_w(int state) { if(state != m_rcv_clock_state) { m_rcv_clock_state = state; @@ -156,7 +156,7 @@ WRITE_LINE_MEMBER(device_serial_interface::rx_clock_w) } } -WRITE_LINE_MEMBER(device_serial_interface::clock_w) +void device_serial_interface::clock_w(int state) { tx_clock_w(state); rx_clock_w(state); @@ -216,19 +216,21 @@ void device_serial_interface::receive_register_reset() } } -WRITE_LINE_MEMBER(device_serial_interface::rx_w) +void device_serial_interface::rx_w(int state) { m_rcv_line = state; - if(m_rcv_flags & RECEIVE_REGISTER_SYNCHRONISED) + if (m_rcv_flags & RECEIVE_REGISTER_SYNCHRONISED) return; receive_register_update_bit(state); - if(m_rcv_flags & RECEIVE_REGISTER_SYNCHRONISED) + if (m_rcv_flags & RECEIVE_REGISTER_SYNCHRONISED) { LOGMASKED(LOG_RX, "Receiver is synchronized\n"); - if(m_rcv_clock && !(m_rcv_rate.is_never())) - // make start delay just a bit longer to make sure we are called after the sender - m_rcv_clock->adjust(((m_rcv_rate*3)/2), 0, m_rcv_rate); - else if(m_start_bit_hack_for_external_clocks) + if (m_rcv_clock && !(m_rcv_rate.is_never())) + { + // make start delay half a cycle longer to make sure we are called after the sender + m_rcv_clock->adjust(m_rcv_rate*2, 0, m_rcv_rate); + } + else if (m_start_bit_hack_for_external_clocks) m_rcv_bit_count_received--; } return; @@ -261,7 +263,7 @@ void device_serial_interface::receive_register_update_bit(int bit) /* yes */ if (bit==0) { - LOGMASKED(LOG_RX, "Receiver saw start bit\n"); + LOGMASKED(LOG_RX, "Receiver saw start bit (%s)\n", device().machine().time().to_string()); /* seen start bit! */ /* not waiting for start bit now! */ @@ -274,10 +276,9 @@ void device_serial_interface::receive_register_update_bit(int bit) } } } - else - if (m_rcv_flags & RECEIVE_REGISTER_SYNCHRONISED) + else if (m_rcv_flags & RECEIVE_REGISTER_SYNCHRONISED) { - LOGMASKED(LOG_RX, "Received bit %d as %d\n", m_rcv_bit_count_received, bit); + LOGMASKED(LOG_RX, "Received bit %d as %d (%s)\n", m_rcv_bit_count_received, bit, device().machine().time().to_string()); m_rcv_bit_count_received++; if (!bit && (m_rcv_bit_count_received > (m_rcv_bit_count - m_df_stop_bit_count))) @@ -312,6 +313,7 @@ void device_serial_interface::receive_register_extract() data &= ~(0xff<<m_df_word_length); m_rcv_byte_received = data; + LOGMASKED(LOG_RX, "Receive data 0x%02x\n", m_rcv_byte_received); if(m_df_parity == PARITY_NONE) return; @@ -437,9 +439,9 @@ u8 device_serial_interface::transmit_register_get_data_bit() bit = (m_tra_register_data>>(m_tra_bit_count-1-m_tra_bit_count_transmitted))&1; if (m_tra_bit_count_transmitted < m_df_start_bit_count) - LOGMASKED(LOG_TX, "Transmitting start bit as %d\n", m_tra_bit_count_transmitted, bit); + LOGMASKED(LOG_TX, "Transmitting start bit %d as %d (%s)\n", m_tra_bit_count_transmitted, bit, device().machine().time().to_string()); else - LOGMASKED(LOG_TX, "Transmitting bit %d as %d\n", m_tra_bit_count_transmitted - m_df_start_bit_count, bit); + LOGMASKED(LOG_TX, "Transmitting bit %d as %d (%s)\n", m_tra_bit_count_transmitted - m_df_start_bit_count, bit, device().machine().time().to_string()); m_tra_bit_count_transmitted++; /* have all bits of this stream formatted byte been sent? */ diff --git a/src/emu/diserial.h b/src/emu/diserial.h index 62b13c028a1..aab03940206 100644 --- a/src/emu/diserial.h +++ b/src/emu/diserial.h @@ -76,10 +76,10 @@ public: device_serial_interface(const machine_config &mconfig, device_t &device); virtual ~device_serial_interface(); - DECLARE_WRITE_LINE_MEMBER(rx_w); - DECLARE_WRITE_LINE_MEMBER(tx_clock_w); - DECLARE_WRITE_LINE_MEMBER(rx_clock_w); - DECLARE_WRITE_LINE_MEMBER(clock_w); + void rx_w(int state); + void tx_clock_w(int state); + void rx_clock_w(int state); + void clock_w(int state); protected: void set_data_frame(int start_bit_count, int data_bit_count, parity_t parity, stop_bits_t stop_bits); diff --git a/src/emu/dislot.cpp b/src/emu/dislot.cpp index 06ff055e293..43d2ed96cdd 100644 --- a/src/emu/dislot.cpp +++ b/src/emu/dislot.cpp @@ -28,7 +28,7 @@ device_slot_interface::~device_slot_interface() } -device_slot_interface::slot_option::slot_option(const char *name, const device_type &devtype, bool selectable) : +device_slot_interface::slot_option::slot_option(const char *name, device_type devtype, bool selectable) : m_name(name), m_devtype(devtype), m_selectable(selectable), @@ -47,7 +47,7 @@ void device_slot_interface::interface_validity_check(validity_checker &valid) co } -device_slot_interface::slot_option &device_slot_interface::option_add(const char *name, const device_type &devtype) +device_slot_interface::slot_option &device_slot_interface::option_add(const char *name, device_type devtype) { if (!name || !*name) throw emu_fatalerror("slot '%s' attempt to add option without name\n", device().tag()); @@ -60,7 +60,7 @@ device_slot_interface::slot_option &device_slot_interface::option_add(const char } -device_slot_interface::slot_option &device_slot_interface::option_add_internal(const char *name, const device_type &devtype) +device_slot_interface::slot_option &device_slot_interface::option_add_internal(const char *name, device_type devtype) { if (!name || !*name) throw emu_fatalerror("slot '%s' attempt to add option without name\n", device().tag()); @@ -73,7 +73,7 @@ device_slot_interface::slot_option &device_slot_interface::option_add_internal(c } -device_slot_interface::slot_option &device_slot_interface::option_replace(const char *name, const device_type &devtype) +device_slot_interface::slot_option &device_slot_interface::option_replace(const char *name, device_type devtype) { if (!name || !*name) throw emu_fatalerror("slot '%s' attempt to replace option without name\n", device().tag()); @@ -86,7 +86,7 @@ device_slot_interface::slot_option &device_slot_interface::option_replace(const } -device_slot_interface::slot_option &device_slot_interface::option_replace_internal(const char *name, const device_type &devtype) +device_slot_interface::slot_option &device_slot_interface::option_replace_internal(const char *name, device_type devtype) { if (!name || !*name) throw emu_fatalerror("slot '%s' attempt to replace option without name\n", device().tag()); diff --git a/src/emu/dislot.h b/src/emu/dislot.h index dd2fde5fac1..f6e1f86fcb3 100644 --- a/src/emu/dislot.h +++ b/src/emu/dislot.h @@ -46,10 +46,10 @@ public: class slot_option { public: - slot_option(char const *name, device_type const &devtype, bool selectable); + slot_option(char const *name, device_type devtype, bool selectable); char const *name() const { return m_name; } - device_type const &devtype() const { return m_devtype; } + device_type devtype() const { return m_devtype; } bool selectable() const { return m_selectable; } char const *default_bios() const { return m_default_bios; } std::function<void (device_t *)> const &machine_config() const { return m_machine_config; } @@ -83,7 +83,7 @@ public: /// \param [in] fixed True to mark the slot as fixed, or false to /// mark it user-configurable. /// \sa fixed - void set_fixed(bool fixed) { m_fixed = fixed; } + device_slot_interface &set_fixed(bool fixed) { m_fixed = fixed; return *this; } /// \brief Set the default option /// @@ -97,12 +97,12 @@ public: /// valid for the lifetime of the device (or until another default /// option is configured). /// \sa default_option - void set_default_option(const char *option) { m_default_option = option; } + device_slot_interface &set_default_option(const char *option) { m_default_option = option; return *this; } /// \brief Clear options /// /// This removes all previously added options. - void option_reset() { m_options.clear(); } + device_slot_interface &option_reset() { m_options.clear(); return *this; } /// \brief Add a user-selectable option /// @@ -116,7 +116,7 @@ public: /// description is used in the user interface. /// \return A reference to the added option for additional /// configuration. - slot_option &option_add(char const *option, const device_type &devtype); + slot_option &option_add(char const *option, device_type devtype); /// \brief Add an internal option /// @@ -130,10 +130,10 @@ public: /// description is used in the user interface. /// \return A reference to the added option for additional /// configuration. - slot_option &option_add_internal(const char *option, const device_type &devtype); + slot_option &option_add_internal(const char *option, device_type devtype); - slot_option &option_replace(const char *option, const device_type &devtype); - slot_option &option_replace_internal(const char *option, const device_type &devtype); + slot_option &option_replace(const char *option, device_type devtype); + slot_option &option_replace_internal(const char *option, device_type devtype); void option_remove(const char *option); void set_option_default_bios(const char *option, const char *default_bios) { config_option(option)->default_bios(default_bios); } @@ -166,7 +166,7 @@ public: device_t *get_card_device() const { return m_card_device; } void set_card_device(device_t *dev) { m_card_device = dev; } const char *slot_name() const { return device().tag() + 1; } - slot_option &option_set(const char *tag, const device_type &devtype) { m_default_option = tag; m_fixed = true; return option_add_internal(tag, devtype); } + slot_option &option_set(const char *tag, device_type devtype) { m_default_option = tag; m_fixed = true; return option_add_internal(tag, devtype); } protected: device_slot_interface(machine_config const &mconfig, device_t &device); diff --git a/src/emu/distate.cpp b/src/emu/distate.cpp index 0d94c4dcf81..76ede23dfe2 100644 --- a/src/emu/distate.cpp +++ b/src/emu/distate.cpp @@ -101,7 +101,7 @@ device_state_entry &device_state_entry::formatstr(const char *_format) // set the DSF_CUSTOM_STRING flag by formatting with a nullptr string m_flags &= ~DSF_CUSTOM_STRING; - format(nullptr); + format(nullptr, 0); return *this; } @@ -127,9 +127,7 @@ void device_state_entry::format_from_mask() // make up a format based on the mask if (m_datamask == 0) throw emu_fatalerror("%s state entry requires a nonzero mask\n", m_symbol); - int width = 0; - for (u64 tempmask = m_datamask; tempmask != 0; tempmask >>= 4) - width++; + int width = (63 - count_leading_zeros_64(m_datamask)) / 4 + 1; m_format = string_format("%%0%dX", width); } @@ -201,12 +199,10 @@ double device_state_entry::entry_dvalue() const // pieces of indexed state as a string //------------------------------------------------- -std::string device_state_entry::format(const char *string, bool maxout) const +std::string device_state_entry::format(const char *string, u64 result, bool maxout) const { - std::string dest; - u64 result = entry_value() & m_datamask; - // parse the format + std::string dest; bool leadzero = false; bool percent = false; bool explicitsign = false; @@ -400,7 +396,7 @@ std::string device_state_entry::to_string() const custom = string_format("%-12G", entry_dvalue()); // ask the entry to format itself - return format(custom.c_str()); + return format(custom.c_str(), value()); } @@ -412,7 +408,7 @@ std::string device_state_entry::to_string() const int device_state_entry::max_length() const { // ask the entry to format itself maximally - return format("", true).length(); + return format("", 0, true).length(); } diff --git a/src/emu/distate.h b/src/emu/distate.h index f0cf04eadeb..b4727c259f4 100644 --- a/src/emu/distate.h +++ b/src/emu/distate.h @@ -104,10 +104,10 @@ protected: private: // helpers void format_from_mask(); - std::string format(const char *string, bool maxout = false) const; + std::string format(const char *string, u64 result, bool maxout = false) const; // statics - static const u64 k_decimal_divisor[20]; // divisors for outputting decimal values + static const u64 k_decimal_divisor[20]; // divisors for outputting decimal values // public state description device_state_interface *m_device_state; // link to parent device state @@ -286,12 +286,14 @@ class device_state_interface : public device_interface friend class device_state_entry; public: + using entrylist_type = std::vector<std::unique_ptr<device_state_entry> >; + // construction/destruction device_state_interface(const machine_config &mconfig, device_t &device); virtual ~device_state_interface(); // configuration access - const std::vector<std::unique_ptr<device_state_entry>> &state_entries() const { return m_state_list; } + const entrylist_type &state_entries() const { return m_state_list; } // state getters u64 state_int(int index) const { const device_state_entry *entry = state_find_entry(index); return (entry == nullptr) ? 0 : entry->value(); } @@ -357,13 +359,12 @@ protected: virtual void interface_post_start() override; // constants - static constexpr int FAST_STATE_MIN = -4; // range for fast state - static constexpr int FAST_STATE_MAX = 256; // lookups + static constexpr int FAST_STATE_MIN = -4; // range for fast state + static constexpr int FAST_STATE_MAX = 256; // lookups // state - std::vector<std::unique_ptr<device_state_entry>> m_state_list; // head of state list - device_state_entry * m_fast_state[FAST_STATE_MAX + 1 - FAST_STATE_MIN]; - // fast access to common entries + entrylist_type m_state_list; // head of state list + device_state_entry *m_fast_state[FAST_STATE_MAX + 1 - FAST_STATE_MIN]; // fast access to common entries }; // iterator diff --git a/src/emu/divtlb.cpp b/src/emu/divtlb.cpp index 41a0aa96aad..ec0469cac02 100644 --- a/src/emu/divtlb.cpp +++ b/src/emu/divtlb.cpp @@ -68,7 +68,7 @@ void device_vtlb_interface::interface_validity_check(validity_checker &valid) co const address_space_config *spaceconfig = intf->space_config(m_space); if (spaceconfig == nullptr) osd_printf_error("No memory address space configuration found for space %d\n", m_space); - else if ((1 << spaceconfig->page_shift()) <= VTLB_FLAGS_MASK || spaceconfig->logaddr_width() <= spaceconfig->page_shift()) + else if ((1 << spaceconfig->page_shift()) <= FLAGS_MASK || spaceconfig->logaddr_width() <= spaceconfig->page_shift()) osd_printf_error("Invalid page shift %d for VTLB\n", spaceconfig->page_shift()); } } @@ -142,11 +142,10 @@ void device_vtlb_interface::interface_pre_reset() // response to an unmapped access //------------------------------------------------- -bool device_vtlb_interface::vtlb_fill(offs_t address, int intention) +bool device_vtlb_interface::vtlb_fill(offs_t address, offs_t taddress, int intention) { offs_t tableindex = address >> m_pageshift; vtlb_entry entry = m_table[tableindex]; - offs_t taddress; #if PRINTF_TLB osd_printf_debug("vtlb_fill: %08X(%X) ... ", address, intention); @@ -164,18 +163,8 @@ bool device_vtlb_interface::vtlb_fill(offs_t address, int intention) return false; } - // ask the CPU core to translate for us - taddress = address; - if (!device().memory().translate(m_space, intention, taddress)) - { -#if PRINTF_TLB - osd_printf_debug("failed: no translation\n"); -#endif - return false; - } - // if this is the first successful translation for this address, allocate a new entry - if ((entry & VTLB_FLAGS_MASK) == 0) + if ((entry & FLAGS_MASK) == 0) { int liveindex = m_dynindex; @@ -196,7 +185,7 @@ bool device_vtlb_interface::vtlb_fill(offs_t address, int intention) // form a new blank entry entry = (taddress >> m_pageshift) << m_pageshift; - entry |= VTLB_FLAG_VALID; + entry |= FLAG_VALID; #if PRINTF_TLB osd_printf_debug("success (%08X), new entry\n", taddress); @@ -207,7 +196,7 @@ bool device_vtlb_interface::vtlb_fill(offs_t address, int intention) else { assert((entry >> m_pageshift) == (taddress >> m_pageshift)); - assert(entry & VTLB_FLAG_VALID); + assert(entry & FLAG_VALID); #if PRINTF_TLB osd_printf_debug("success (%08X), existing entry\n", taddress); @@ -215,7 +204,7 @@ bool device_vtlb_interface::vtlb_fill(offs_t address, int intention) } // add the intention to the list of valid intentions and store - entry |= 1 << (intention & (TRANSLATE_TYPE_MASK | TRANSLATE_USER_MASK)); + entry |= 1 << intention; m_table[tableindex] = entry; return true; } @@ -256,7 +245,7 @@ void device_vtlb_interface::vtlb_load(int entrynum, int numpages, offs_t address m_refcnt[tableindex]++; // store the raw value, making sure the "fixed" flag is set - value |= VTLB_FLAG_FIXED; + value |= FLAG_FIXED; m_fixedpages[entrynum] = numpages; for (pagenum = 0; pagenum < numpages; pagenum++) m_table[tableindex + pagenum] = value + (pagenum << m_pageshift); @@ -283,7 +272,7 @@ void device_vtlb_interface::vtlb_dynload(u32 index, offs_t address, vtlb_entry v m_dynindex = (m_dynindex + 1) % m_dynamic; // is entry already live? - if (!(entry & VTLB_FLAG_VALID)) + if (!(entry & FLAG_VALID)) { // if an entry already exists at this index, free it if (m_live[liveindex] != 0) @@ -294,7 +283,7 @@ void device_vtlb_interface::vtlb_dynload(u32 index, offs_t address, vtlb_entry v } // form a new blank entry entry = (address >> m_pageshift) << m_pageshift; - entry |= VTLB_FLAG_VALID | value; + entry |= FLAG_VALID | value; #if PRINTF_TLB osd_printf_debug("success (%08X), new entry\n", address); @@ -356,7 +345,7 @@ void device_vtlb_interface::vtlb_flush_address(offs_t address) // the linear VTLB lookup table //------------------------------------------------- -const vtlb_entry *device_vtlb_interface::vtlb_table() const +const device_vtlb_interface::vtlb_entry *device_vtlb_interface::vtlb_table() const { return m_table_base; } diff --git a/src/emu/divtlb.h b/src/emu/divtlb.h index c64bca0a21c..13adbd4a4ce 100644 --- a/src/emu/divtlb.h +++ b/src/emu/divtlb.h @@ -13,38 +13,35 @@ #pragma once - - -/*************************************************************************** - CONSTANTS -***************************************************************************/ - -constexpr u32 VTLB_FLAGS_MASK = 0xff; - -constexpr u32 VTLB_READ_ALLOWED = 0x01; /* (1 << TRANSLATE_READ) */ -constexpr u32 VTLB_WRITE_ALLOWED = 0x02; /* (1 << TRANSLATE_WRITE) */ -constexpr u32 VTLB_FETCH_ALLOWED = 0x04; /* (1 << TRANSLATE_FETCH) */ -constexpr u32 VTLB_FLAG_VALID = 0x08; -constexpr u32 VTLB_USER_READ_ALLOWED = 0x10; /* (1 << TRANSLATE_READ_USER) */ -constexpr u32 VTLB_USER_WRITE_ALLOWED = 0x20; /* (1 << TRANSLATE_WRITE_USER) */ -constexpr u32 VTLB_USER_FETCH_ALLOWED = 0x40; /* (1 << TRANSLATE_FETCH_USER) */ -constexpr u32 VTLB_FLAG_FIXED = 0x80; - - - -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -/* represents an entry in the VTLB */ -typedef u32 vtlb_entry; - - -// ======================> device_vtlb_interface - class device_vtlb_interface : public device_interface { public: + using vtlb_entry = u32; + + // Translation type flags + // TR_READ/WRITE/FETCH come from device_memory_interface + enum { + TR_UREAD = 4, + TR_UWRITE = 5, + TR_UFETCH = 6, + + TR_TYPE = 3, + TR_USER = 4 + }; + + enum { + FLAGS_MASK = 0xff, + + READ_ALLOWED = 0x01, /* (1 << TR_READ) */ + WRITE_ALLOWED = 0x02, /* (1 << TR_WRITE) */ + FETCH_ALLOWED = 0x04, /* (1 << TR_FETCH) */ + FLAG_VALID = 0x08, + USER_READ_ALLOWED = 0x10, /* (1 << TR_UREAD) */ + USER_WRITE_ALLOWED = 0x20, /* (1 << TR_UWRITE) */ + USER_FETCH_ALLOWED = 0x40, /* (1 << TR_UFETCH) */ + FLAG_FIXED = 0x80 + }; + // construction/destruction device_vtlb_interface(const machine_config &mconfig, device_t &device, int space); virtual ~device_vtlb_interface(); @@ -54,7 +51,7 @@ public: void set_vtlb_fixed_entries(int entries) { m_fixed = entries; } // filling - bool vtlb_fill(offs_t address, int intention); + bool vtlb_fill(offs_t address, offs_t taddress, int intention); void vtlb_load(int entrynum, int numpages, offs_t address, vtlb_entry value); void vtlb_dynload(u32 index, offs_t address, vtlb_entry value); diff --git a/src/emu/drawgfxt.ipp b/src/emu/drawgfxt.ipp index 4d756497102..4277bf21634 100644 --- a/src/emu/drawgfxt.ipp +++ b/src/emu/drawgfxt.ipp @@ -421,7 +421,7 @@ while (0) template <typename BitmapType, typename FunctionClass> inline void gfx_element::drawgfx_core(BitmapType &dest, const rectangle &cliprect, u32 code, int flipx, int flipy, s32 destx, s32 desty, FunctionClass pixel_op) { - g_profiler.start(PROFILER_DRAWGFX); + auto profile = g_profiler.start(PROFILER_DRAWGFX); do { assert(dest.valid()); assert(dest.cliprect().contains(cliprect)); @@ -551,14 +551,13 @@ inline void gfx_element::drawgfx_core(BitmapType &dest, const rectangle &cliprec } } } while (0); - g_profiler.stop(); } template <typename BitmapType, typename PriorityType, typename FunctionClass> inline void gfx_element::drawgfx_core(BitmapType &dest, const rectangle &cliprect, u32 code, int flipx, int flipy, s32 destx, s32 desty, PriorityType &priority, FunctionClass pixel_op) { - g_profiler.start(PROFILER_DRAWGFX); + auto profile = g_profiler.start(PROFILER_DRAWGFX); do { assert(dest.valid()); assert(priority.valid()); @@ -695,7 +694,6 @@ inline void gfx_element::drawgfx_core(BitmapType &dest, const rectangle &cliprec } } } while (0); - g_profiler.stop(); } @@ -724,7 +722,7 @@ inline void gfx_element::drawgfx_core(BitmapType &dest, const rectangle &cliprec template <typename BitmapType, typename FunctionClass> inline void gfx_element::drawgfxzoom_core(BitmapType &dest, const rectangle &cliprect, u32 code, int flipx, int flipy, s32 destx, s32 desty, u32 scalex, u32 scaley, FunctionClass pixel_op) { - g_profiler.start(PROFILER_DRAWGFX); + auto profile = g_profiler.start(PROFILER_DRAWGFX); do { assert(dest.valid()); assert(dest.cliprect().contains(cliprect)); @@ -830,14 +828,13 @@ inline void gfx_element::drawgfxzoom_core(BitmapType &dest, const rectangle &cli } } } while (0); - g_profiler.stop(); } template <typename BitmapType, typename PriorityType, typename FunctionClass> inline void gfx_element::drawgfxzoom_core(BitmapType &dest, const rectangle &cliprect, u32 code, int flipx, int flipy, s32 destx, s32 desty, u32 scalex, u32 scaley, PriorityType &priority, FunctionClass pixel_op) { - g_profiler.start(PROFILER_DRAWGFX); + auto profile = g_profiler.start(PROFILER_DRAWGFX); do { assert(dest.valid()); assert(priority.valid()); @@ -877,10 +874,7 @@ inline void gfx_element::drawgfxzoom_core(BitmapType &dest, const rectangle &cli // compute final pixel in Y and exit if we are entirely clipped s32 destendy = desty + dstheight - 1; if (desty > cliprect.bottom() || destendy < cliprect.top()) - { - g_profiler.stop(); return; - } // apply top clip s32 srcy = 0; @@ -950,7 +944,6 @@ inline void gfx_element::drawgfxzoom_core(BitmapType &dest, const rectangle &cli } } } while (0); - g_profiler.stop(); } @@ -975,7 +968,7 @@ inline void gfx_element::drawgfxzoom_core(BitmapType &dest, const rectangle &cli template <typename BitmapType, typename FunctionClass> inline void copybitmap_core(BitmapType &dest, const BitmapType &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, FunctionClass pixel_op) { - g_profiler.start(PROFILER_COPYBITMAP); + auto profile = g_profiler.start(PROFILER_COPYBITMAP); do { assert(dest.valid()); assert(src.valid()); @@ -1108,14 +1101,13 @@ inline void copybitmap_core(BitmapType &dest, const BitmapType &src, int flipx, } } } while (0); - g_profiler.stop(); } template <typename BitmapType, typename PriorityType, typename FunctionClass> inline void copybitmap_core(BitmapType &dest, const BitmapType &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, PriorityType &priority, FunctionClass pixel_op) { - g_profiler.start(PROFILER_COPYBITMAP); + auto profile = g_profiler.start(PROFILER_COPYBITMAP); do { assert(dest.valid()); assert(src.valid()); @@ -1255,7 +1247,6 @@ inline void copybitmap_core(BitmapType &dest, const BitmapType &src, int flipx, } } } while (0); - g_profiler.stop(); } @@ -1283,7 +1274,7 @@ inline void copybitmap_core(BitmapType &dest, const BitmapType &src, int flipx, template <typename BitmapType, typename FunctionClass> inline void copyrozbitmap_core(BitmapType &dest, const rectangle &cliprect, const BitmapType &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, bool wraparound, FunctionClass pixel_op) { - g_profiler.start(PROFILER_COPYBITMAP); + auto profile = g_profiler.start(PROFILER_COPYBITMAP); assert(dest.valid()); assert(dest.valid()); @@ -1293,10 +1284,7 @@ inline void copyrozbitmap_core(BitmapType &dest, const rectangle &cliprect, cons // ignore empty/invalid cliprects if (cliprect.empty()) - { - g_profiler.stop(); return; - } // compute fixed-point 16.16 size of the source bitmap u32 srcfixwidth = src.width() << 16; @@ -1537,14 +1525,13 @@ inline void copyrozbitmap_core(BitmapType &dest, const rectangle &cliprect, cons } } } - g_profiler.stop(); } template <typename BitmapType, typename PriorityType, typename FunctionClass> inline void copyrozbitmap_core(BitmapType &dest, const rectangle &cliprect, const BitmapType &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, bool wraparound, PriorityType &priority, FunctionClass pixel_op) { - g_profiler.start(PROFILER_COPYBITMAP); + auto profile = g_profiler.start(PROFILER_COPYBITMAP); assert(dest.valid()); assert(dest.valid()); @@ -1555,10 +1542,7 @@ inline void copyrozbitmap_core(BitmapType &dest, const rectangle &cliprect, cons // ignore empty/invalid cliprects if (cliprect.empty()) - { - g_profiler.stop(); return; - } // compute fixed-point 16.16 size of the source bitmap u32 srcfixwidth = src.width() << 16; @@ -1811,7 +1795,6 @@ inline void copyrozbitmap_core(BitmapType &dest, const rectangle &cliprect, cons } } } - g_profiler.stop(); } diff --git a/src/emu/drivers/empty.cpp b/src/emu/drivers/empty.cpp index 6b60367403b..9b907214487 100644 --- a/src/emu/drivers/empty.cpp +++ b/src/emu/drivers/empty.cpp @@ -9,9 +9,12 @@ **************************************************************************/ #include "emu.h" + #include "emuopts.h" +#include "main.h" #include "screen.h" + //************************************************************************** // DRIVER STATE //************************************************************************** diff --git a/src/emu/emu.h b/src/emu/emu.h index 6f564f258ab..679687f772d 100644 --- a/src/emu/emu.h +++ b/src/emu/emu.h @@ -28,7 +28,6 @@ #include <map> #include <unordered_map> #include <unordered_set> -#include <cstdarg> // core emulator headers -- must be first (profiler needs attotime, attotime needs xtal) #include "emucore.h" @@ -80,7 +79,6 @@ #include "parameters.h" // the running machine -#include "main.h" #include "machine.h" #include "driver.h" diff --git a/src/emu/emucore.cpp b/src/emu/emucore.cpp index bc6139fe3cf..d9a314cfaa2 100644 --- a/src/emu/emucore.cpp +++ b/src/emu/emucore.cpp @@ -13,13 +13,13 @@ #include "emucore.h" #include "osdcore.h" -emu_fatalerror::emu_fatalerror(util::format_argument_pack<std::ostream> const &args) +emu_fatalerror::emu_fatalerror(util::format_argument_pack<char> const &args) : emu_fatalerror(0, args) { osd_break_into_debugger(m_text.c_str()); } -emu_fatalerror::emu_fatalerror(int _exitcode, util::format_argument_pack<std::ostream> const &args) +emu_fatalerror::emu_fatalerror(int _exitcode, util::format_argument_pack<char> const &args) : m_text(util::string_format(args)) , m_code(_exitcode) { diff --git a/src/emu/emucore.h b/src/emu/emucore.h index af78cb98565..ca54f5208cd 100644 --- a/src/emu/emucore.h +++ b/src/emu/emucore.h @@ -228,17 +228,19 @@ class emu_exception : public std::exception { }; class emu_fatalerror : public emu_exception { public: - emu_fatalerror(util::format_argument_pack<std::ostream> const &args); - emu_fatalerror(int _exitcode, util::format_argument_pack<std::ostream> const &args); + emu_fatalerror(emu_fatalerror const &) = default; + emu_fatalerror(emu_fatalerror &&) = default; + emu_fatalerror(util::format_argument_pack<char> const &args); + emu_fatalerror(int _exitcode, util::format_argument_pack<char> const &args); template <typename Format, typename... Params> - emu_fatalerror(Format const &fmt, Params &&... args) - : emu_fatalerror(static_cast<util::format_argument_pack<std::ostream> const &>(util::make_format_argument_pack(fmt, std::forward<Params>(args)...))) + emu_fatalerror(Format &&fmt, Params &&... args) + : emu_fatalerror(static_cast<util::format_argument_pack<char> const &>(util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...))) { } template <typename Format, typename... Params> - emu_fatalerror(int _exitcode, Format const &fmt, Params &&... args) - : emu_fatalerror(_exitcode, static_cast<util::format_argument_pack<std::ostream> const &>(util::make_format_argument_pack(fmt, std::forward<Params>(args)...))) + emu_fatalerror(int _exitcode, Format &&fmt, Params &&... args) + : emu_fatalerror(_exitcode, static_cast<util::format_argument_pack<char> const &>(util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...))) { } diff --git a/src/emu/emufwd.h b/src/emu/emufwd.h index 323a0f14898..89e15e4c541 100644 --- a/src/emu/emufwd.h +++ b/src/emu/emufwd.h @@ -14,6 +14,8 @@ #pragma once +#include "utilfwd.h" + #include <type_traits> @@ -36,25 +38,6 @@ class output_module; // declared in osdepend.h class osd_font; class osd_interface; -class osd_midi_device; - - - -//---------------------------------- -// lib/util -//---------------------------------- - -// declared in aviio.h -class avi_file; - -// declared in chd.h -class chd_file; - -// declared in unzip.h -namespace util { class archive_file; } - -// declared in xmlfile.h -namespace util::xml { class data_node; class file; } @@ -109,6 +92,7 @@ class devcb_base; template <typename Input, std::make_unsigned_t<Input> DefaultMask> class devcb_write; // declared in devfind.h +class device_resolver_base; class finder_base; template <class DeviceClass, bool Required> class device_finder; @@ -195,6 +179,9 @@ namespace emu::detail { class machine_config_replace; } struct internal_layout; class machine_config; +// declared in main.h +class machine_manager; + // declared in natkeyboard.h class natural_keyboard; @@ -210,6 +197,9 @@ class render_manager; class render_target; class render_texture; +// declared in rendertypes.h +struct render_bounds; + // declared in rendfont.h class render_font; diff --git a/src/emu/emumem.cpp b/src/emu/emumem.cpp index 0d20a1bda79..679c2374e78 100644 --- a/src/emu/emumem.cpp +++ b/src/emu/emumem.cpp @@ -861,6 +861,38 @@ void address_space_installer::populate_map_entry(const address_map_entry &entry, install_view(entry.m_addrstart, entry.m_addrend, entry.m_addrmirror, *entry.m_view); break; } + + if (data.m_type == AMH_VIEW) + return; + + offs_t lowbits_mask = (m_config.data_width() >> (3 - m_config.addr_shift())) - 1; + + if (!entry.m_before_time.isnull()) { + auto d = entry.m_before_time; + d.resolve(); + if (readorwrite == read_or_write::READ) + install_read_before_time(entry.m_addrstart & ~lowbits_mask, entry.m_addrend | lowbits_mask, entry.m_addrmirror, d); + else + install_write_before_time(entry.m_addrstart & ~lowbits_mask, entry.m_addrend | lowbits_mask, entry.m_addrmirror, d); + } + + if (!entry.m_before_delay.isnull()) { + auto d = entry.m_before_delay; + d.resolve(); + if (readorwrite == read_or_write::READ) + install_read_before_delay(entry.m_addrstart & ~lowbits_mask, entry.m_addrend | lowbits_mask, entry.m_addrmirror, d); + else + install_write_before_delay(entry.m_addrstart & ~lowbits_mask, entry.m_addrend | lowbits_mask, entry.m_addrmirror, d); + } + + if (!entry.m_after_delay.isnull()) { + auto d = entry.m_after_delay; + d.resolve(); + if (readorwrite == read_or_write::READ) + install_read_after_delay(entry.m_addrstart & ~lowbits_mask, entry.m_addrend | lowbits_mask, entry.m_addrmirror, d); + else + install_write_after_delay(entry.m_addrstart & ~lowbits_mask, entry.m_addrend | lowbits_mask, entry.m_addrmirror, d); + } } diff --git a/src/emu/emumem.h b/src/emu/emumem.h index b9a8ed08763..1b9b6363622 100644 --- a/src/emu/emumem.h +++ b/src/emu/emumem.h @@ -173,9 +173,15 @@ using write32smo_delegate = device_delegate<void (u32)>; using write64smo_delegate = device_delegate<void (u64)>; +// =====================-> Wait states delegates + +using ws_time_delegate = device_delegate<u64 (offs_t, u64)>; +using ws_delay_delegate = device_delegate<u32 (offs_t)>; + + namespace emu::detail { -// TODO: replace with std::void_t when we move to C++17 +// TODO: work out why this doesn't work with clang and/or libc++ void_t but works with this C++14 work-alike template <typename... T> struct void_wrapper { using type = void; }; template <typename... T> using void_t = typename void_wrapper<T...>::type; @@ -243,15 +249,6 @@ template <typename T> using rw_delegate_type_t = typename rw_delegate_type<T>::t template <typename T> using rw_delegate_device_class_t = typename rw_delegate_type<T>::device_class; -template <typename T> -inline rw_delegate_type_t<T> make_delegate(device_t &base, char const *tag, T &&func, char const *name) -{ return rw_delegate_type_t<T>(base, tag, std::forward<T>(func), name); } - -template <typename T> -inline rw_delegate_type_t<T> make_delegate(rw_delegate_device_class_t<T> &object, T &&func, char const *name) -{ return rw_delegate_type_t<T>(object, std::forward<T>(func), name); } - - template <typename L> inline std::enable_if_t<std::is_constructible<read8_delegate, device_t &, L, const char *>::value, read8_delegate> make_lr8_delegate(device_t &owner, L &&l, const char *name) { return read8_delegate(owner, std::forward<L>(l), name); } @@ -446,14 +443,69 @@ inline std::enable_if_t<std::is_constructible<write64smo_delegate, device_t &, L { return write64smo_delegate(owner, std::forward<L>(l), name); } +// =====================-> delegate -> Width + +template <typename Delegate> struct handler_width; +template <typename Delegate> inline constexpr int handler_width_v = handler_width<Delegate>::value; +template <> struct handler_width<read8_delegate> { static inline constexpr int value = 0; }; +template <> struct handler_width<read8m_delegate> { static inline constexpr int value = 0; }; +template <> struct handler_width<read8s_delegate> { static inline constexpr int value = 0; }; +template <> struct handler_width<read8sm_delegate> { static inline constexpr int value = 0; }; +template <> struct handler_width<read8mo_delegate> { static inline constexpr int value = 0; }; +template <> struct handler_width<read8smo_delegate> { static inline constexpr int value = 0; }; +template <> struct handler_width<write8_delegate> { static inline constexpr int value = 0; }; +template <> struct handler_width<write8m_delegate> { static inline constexpr int value = 0; }; +template <> struct handler_width<write8s_delegate> { static inline constexpr int value = 0; }; +template <> struct handler_width<write8sm_delegate> { static inline constexpr int value = 0; }; +template <> struct handler_width<write8mo_delegate> { static inline constexpr int value = 0; }; +template <> struct handler_width<write8smo_delegate> { static inline constexpr int value = 0; }; +template <> struct handler_width<read16_delegate> { static inline constexpr int value = 1; }; +template <> struct handler_width<read16m_delegate> { static inline constexpr int value = 1; }; +template <> struct handler_width<read16s_delegate> { static inline constexpr int value = 1; }; +template <> struct handler_width<read16sm_delegate> { static inline constexpr int value = 1; }; +template <> struct handler_width<read16mo_delegate> { static inline constexpr int value = 1; }; +template <> struct handler_width<read16smo_delegate> { static inline constexpr int value = 1; }; +template <> struct handler_width<write16_delegate> { static inline constexpr int value = 1; }; +template <> struct handler_width<write16m_delegate> { static inline constexpr int value = 1; }; +template <> struct handler_width<write16s_delegate> { static inline constexpr int value = 1; }; +template <> struct handler_width<write16sm_delegate> { static inline constexpr int value = 1; }; +template <> struct handler_width<write16mo_delegate> { static inline constexpr int value = 1; }; +template <> struct handler_width<write16smo_delegate> { static inline constexpr int value = 1; }; +template <> struct handler_width<read32_delegate> { static inline constexpr int value = 2; }; +template <> struct handler_width<read32m_delegate> { static inline constexpr int value = 2; }; +template <> struct handler_width<read32s_delegate> { static inline constexpr int value = 2; }; +template <> struct handler_width<read32sm_delegate> { static inline constexpr int value = 2; }; +template <> struct handler_width<read32mo_delegate> { static inline constexpr int value = 2; }; +template <> struct handler_width<read32smo_delegate> { static inline constexpr int value = 2; }; +template <> struct handler_width<write32_delegate> { static inline constexpr int value = 2; }; +template <> struct handler_width<write32m_delegate> { static inline constexpr int value = 2; }; +template <> struct handler_width<write32s_delegate> { static inline constexpr int value = 2; }; +template <> struct handler_width<write32sm_delegate> { static inline constexpr int value = 2; }; +template <> struct handler_width<write32mo_delegate> { static inline constexpr int value = 2; }; +template <> struct handler_width<write32smo_delegate> { static inline constexpr int value = 2; }; +template <> struct handler_width<read64_delegate> { static inline constexpr int value = 3; }; +template <> struct handler_width<read64m_delegate> { static inline constexpr int value = 3; }; +template <> struct handler_width<read64s_delegate> { static inline constexpr int value = 3; }; +template <> struct handler_width<read64sm_delegate> { static inline constexpr int value = 3; }; +template <> struct handler_width<read64mo_delegate> { static inline constexpr int value = 3; }; +template <> struct handler_width<read64smo_delegate> { static inline constexpr int value = 3; }; +template <> struct handler_width<write64_delegate> { static inline constexpr int value = 3; }; +template <> struct handler_width<write64m_delegate> { static inline constexpr int value = 3; }; +template <> struct handler_width<write64s_delegate> { static inline constexpr int value = 3; }; +template <> struct handler_width<write64sm_delegate> { static inline constexpr int value = 3; }; +template <> struct handler_width<write64mo_delegate> { static inline constexpr int value = 3; }; +template <> struct handler_width<write64smo_delegate> { static inline constexpr int value = 3; }; + + // =====================-> Width -> types -template<int Width> struct handler_entry_size {}; -template<> struct handler_entry_size<0> { using uX = u8; }; -template<> struct handler_entry_size<1> { using uX = u16; }; -template<> struct handler_entry_size<2> { using uX = u32; }; -template<> struct handler_entry_size<3> { using uX = u64; }; +template <int Width> struct handler_entry_size; +template <int Width> using handler_entry_size_t = typename handler_entry_size<Width>::type; +template<> struct handler_entry_size<0> { using type = u8; }; +template<> struct handler_entry_size<1> { using type = u16; }; +template<> struct handler_entry_size<2> { using type = u32; }; +template<> struct handler_entry_size<3> { using type = u64; }; // =====================-> Address segmentation for the search tree @@ -501,6 +553,23 @@ private: } // namespace emu::detail +namespace emu { + +template <typename T> +inline detail::rw_delegate_type_t<T> rw_delegate(device_t &base, char const *tag, T &&func, char const *name) +{ return detail::rw_delegate_type_t<T>(base, tag, std::forward<T>(func), name); } + +template <typename T> +inline detail::rw_delegate_type_t<T> rw_delegate(detail::rw_delegate_device_class_t<T> &object, T &&func, char const *name) +{ return detail::rw_delegate_type_t<T>(object, std::forward<T>(func), name); } + +template <typename D, bool Reqd, typename T> +inline detail::rw_delegate_type_t<T> rw_delegate(device_finder<D, Reqd> const &finder, T &&func, char const *name) +{ return detail::rw_delegate_type_t<T>(finder, std::forward<T>(func), name); } + +} // namespace emu + + // ======================> memory_units_descritor forwards declaration template<int Width, int AddrShift> class memory_units_descriptor; @@ -518,11 +587,14 @@ class handler_entry public: // Typing flags (low 16 bits are for the user) - static constexpr u32 F_UNMAP = 0x00010000; // the unmapped memory accessed handler - static constexpr u32 F_DISPATCH = 0x00020000; // handler that forwards the access to other handlers - static constexpr u32 F_UNITS = 0x00040000; // handler that merges/splits an access among multiple handlers (unitmask support) - static constexpr u32 F_PASSTHROUGH = 0x00080000; // handler that passes through the request to another handler - static constexpr u32 F_VIEW = 0x00100000; // handler for a view (kinda like dispatch except not entirely) + static constexpr u32 F_UNMAP = 0x00010000; // the unmapped memory accessed handler + static constexpr u32 F_DISPATCH = 0x00020000; // handler that forwards the access to other handlers + static constexpr u32 F_UNITS = 0x00040000; // handler that merges/splits an access among multiple handlers (unitmask support) + static constexpr u32 F_VIEW = 0x00080000; // handler for a view (kinda like dispatch except not entirely) + static constexpr u32 F_PT_BITS = 24; // position of the 4-bit priority for a passthrough handler. The highest the priority the earlier it is called in the chain. 0 = not passthrough + static constexpr u32 F_PT_REPLACE = 1 << F_PT_BITS; // a passthrough with a odd priority can only happen once in a path + + static constexpr u32 f_pt(u32 priority) { return (priority << F_PT_BITS); } // Start/end of range flags static constexpr u8 START = 1; @@ -552,7 +624,8 @@ public: inline bool is_dispatch() const { return m_flags & F_DISPATCH; } inline bool is_view() const { return m_flags & F_VIEW; } inline bool is_units() const { return m_flags & F_UNITS; } - inline bool is_passthrough() const { return m_flags & F_PASSTHROUGH; } + inline bool is_passthrough() const { return f_get_pt() != 0; } + inline u32 f_get_pt() const { return (m_flags >> F_PT_BITS) & 15; } virtual void dump_map(std::vector<memory_entry> &map) const; @@ -597,7 +670,7 @@ protected: template<int Width, int AddrShift> class handler_entry_read : public handler_entry { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; static constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? make_bitmask<u32>(Width + AddrShift) : 0; @@ -611,6 +684,7 @@ public: ~handler_entry_read() {} virtual uX read(offs_t offset, uX mem_mask) const = 0; + virtual uX read_interruptible(offs_t offset, uX mem_mask) const = 0; virtual std::pair<uX, u16> read_flags(offs_t offset, uX mem_mask) const = 0; virtual u16 lookup_flags(offs_t offset, uX mem_mask) const = 0; virtual void *get_ptr(offs_t offset) const; @@ -671,7 +745,7 @@ public: template<int Width, int AddrShift> class handler_entry_write : public handler_entry { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; static constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? make_bitmask<u32>(Width + AddrShift) : 0; @@ -685,6 +759,7 @@ public: virtual ~handler_entry_write() {} virtual void write(offs_t offset, uX data, uX mem_mask) const = 0; + virtual void write_interruptible(offs_t offset, uX data, uX mem_mask) const = 0; virtual u16 write_flags(offs_t offset, uX data, uX mem_mask) const = 0; virtual u16 lookup_flags(offs_t offset, uX mem_mask) const = 0; virtual void *get_ptr(offs_t offset) const; @@ -771,10 +846,10 @@ constexpr offs_t memory_offset_to_byte(offs_t offset, int AddrShift) { return Ad // ======================> generic read/write decomposition routines // generic direct read -template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename T> typename emu::detail::handler_entry_size<TargetWidth>::uX memory_read_generic(T rop, offs_t address, typename emu::detail::handler_entry_size<TargetWidth>::uX mask) +template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename T> emu::detail::handler_entry_size_t<TargetWidth> memory_read_generic(T rop, offs_t address, emu::detail::handler_entry_size_t<TargetWidth> mask) { - using TargetType = typename emu::detail::handler_entry_size<TargetWidth>::uX; - using NativeType = typename emu::detail::handler_entry_size<Width>::uX; + using TargetType = emu::detail::handler_entry_size_t<TargetWidth>; + using NativeType = emu::detail::handler_entry_size_t<Width>; constexpr u32 TARGET_BYTES = 1 << TargetWidth; constexpr u32 TARGET_BITS = 8 * TARGET_BYTES; @@ -905,9 +980,9 @@ template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Al } // generic direct write -template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename T> void memory_write_generic(T wop, offs_t address, typename emu::detail::handler_entry_size<TargetWidth>::uX data, typename emu::detail::handler_entry_size<TargetWidth>::uX mask) +template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename T> void memory_write_generic(T wop, offs_t address, emu::detail::handler_entry_size_t<TargetWidth> data, emu::detail::handler_entry_size_t<TargetWidth> mask) { - using NativeType = typename emu::detail::handler_entry_size<Width>::uX; + using NativeType = emu::detail::handler_entry_size_t<Width>; constexpr u32 TARGET_BYTES = 1 << TargetWidth; constexpr u32 TARGET_BITS = 8 * TARGET_BYTES; @@ -1029,10 +1104,10 @@ template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Al } // generic direct read with flags -template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename TF> std::pair<typename emu::detail::handler_entry_size<TargetWidth>::uX, u16> memory_read_generic_flags(TF ropf, offs_t address, typename emu::detail::handler_entry_size<TargetWidth>::uX mask) +template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename TF> std::pair<emu::detail::handler_entry_size_t<TargetWidth>, u16> memory_read_generic_flags(TF ropf, offs_t address, emu::detail::handler_entry_size_t<TargetWidth> mask) { - using TargetType = typename emu::detail::handler_entry_size<TargetWidth>::uX; - using NativeType = typename emu::detail::handler_entry_size<Width>::uX; + using TargetType = emu::detail::handler_entry_size_t<TargetWidth>; + using NativeType = emu::detail::handler_entry_size_t<Width>; constexpr u32 TARGET_BYTES = 1 << TargetWidth; constexpr u32 TARGET_BITS = 8 * TARGET_BYTES; @@ -1168,9 +1243,9 @@ template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Al } // generic direct write with flags -template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename TF> u16 memory_write_generic_flags(TF wopf, offs_t address, typename emu::detail::handler_entry_size<TargetWidth>::uX data, typename emu::detail::handler_entry_size<TargetWidth>::uX mask) +template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename TF> u16 memory_write_generic_flags(TF wopf, offs_t address, emu::detail::handler_entry_size_t<TargetWidth> data, emu::detail::handler_entry_size_t<TargetWidth> mask) { - using NativeType = typename emu::detail::handler_entry_size<Width>::uX; + using NativeType = emu::detail::handler_entry_size_t<Width>; constexpr u32 TARGET_BYTES = 1 << TargetWidth; constexpr u32 TARGET_BITS = 8 * TARGET_BYTES; @@ -1299,9 +1374,9 @@ template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Al //############################################## // generic direct read flags lookup -template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename TF> u16 lookup_memory_read_generic_flags(TF lropf, offs_t address, typename emu::detail::handler_entry_size<TargetWidth>::uX mask) +template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename TF> u16 lookup_memory_read_generic_flags(TF lropf, offs_t address, emu::detail::handler_entry_size_t<TargetWidth> mask) { - using NativeType = typename emu::detail::handler_entry_size<Width>::uX; + using NativeType = emu::detail::handler_entry_size_t<Width>; constexpr u32 TARGET_BYTES = 1 << TargetWidth; constexpr u32 TARGET_BITS = 8 * TARGET_BYTES; @@ -1432,9 +1507,9 @@ template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Al } // generic direct write flags lookup -template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename TF> u16 lookup_memory_write_generic_flags(TF lwopf, offs_t address, typename emu::detail::handler_entry_size<TargetWidth>::uX mask) +template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename TF> u16 lookup_memory_write_generic_flags(TF lwopf, offs_t address, emu::detail::handler_entry_size_t<TargetWidth> mask) { - using NativeType = typename emu::detail::handler_entry_size<Width>::uX; + using NativeType = emu::detail::handler_entry_size_t<Width>; constexpr u32 TARGET_BYTES = 1 << TargetWidth; constexpr u32 TARGET_BITS = 8 * TARGET_BYTES; @@ -1564,47 +1639,62 @@ template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Al // ======================> Direct dispatching -template<int Level, int Width, int AddrShift> typename emu::detail::handler_entry_size<Width>::uX dispatch_read(offs_t mask, offs_t offset, typename emu::detail::handler_entry_size<Width>::uX mem_mask, const handler_entry_read<Width, AddrShift> *const *dispatch) +template<int Level, int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> dispatch_read(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_read<Width, AddrShift> *const *dispatch) { static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift); return dispatch[(offset & mask) >> LowBits]->read(offset, mem_mask); } -template<int Level, int Width, int AddrShift> void dispatch_write(offs_t mask, offs_t offset, typename emu::detail::handler_entry_size<Width>::uX data, typename emu::detail::handler_entry_size<Width>::uX mem_mask, const handler_entry_write<Width, AddrShift> *const *dispatch) +template<int Level, int Width, int AddrShift> void dispatch_write(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> data, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_write<Width, AddrShift> *const *dispatch) { static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift); return dispatch[(offset & mask) >> LowBits]->write(offset, data, mem_mask); } -template<int Level, int Width, int AddrShift> std::pair<typename emu::detail::handler_entry_size<Width>::uX, u16> dispatch_read_flags(offs_t mask, offs_t offset, typename emu::detail::handler_entry_size<Width>::uX mem_mask, const handler_entry_read<Width, AddrShift> *const *dispatch) +template<int Level, int Width, int AddrShift> std::pair<emu::detail::handler_entry_size_t<Width>, u16> dispatch_read_flags(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_read<Width, AddrShift> *const *dispatch) { static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift); return dispatch[(offset & mask) >> LowBits]->read_flags(offset, mem_mask); } -template<int Level, int Width, int AddrShift> u16 dispatch_write_flags(offs_t mask, offs_t offset, typename emu::detail::handler_entry_size<Width>::uX data, typename emu::detail::handler_entry_size<Width>::uX mem_mask, const handler_entry_write<Width, AddrShift> *const *dispatch) +template<int Level, int Width, int AddrShift> u16 dispatch_write_flags(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> data, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_write<Width, AddrShift> *const *dispatch) { static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift); return dispatch[(offset & mask) >> LowBits]->write_flags(offset, data, mem_mask); } -template<int Level, int Width, int AddrShift> u16 dispatch_lookup_read_flags(offs_t mask, offs_t offset, typename emu::detail::handler_entry_size<Width>::uX mem_mask, const handler_entry_read<Width, AddrShift> *const *dispatch) +template<int Level, int Width, int AddrShift> u16 dispatch_lookup_read_flags(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_read<Width, AddrShift> *const *dispatch) { static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift); return dispatch[(offset & mask) >> LowBits]->lookup_flags(offset, mem_mask); } -template<int Level, int Width, int AddrShift> u16 dispatch_lookup_write_flags(offs_t mask, offs_t offset, typename emu::detail::handler_entry_size<Width>::uX mem_mask, const handler_entry_write<Width, AddrShift> *const *dispatch) +template<int Level, int Width, int AddrShift> u16 dispatch_lookup_write_flags(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_write<Width, AddrShift> *const *dispatch) { static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift); return dispatch[(offset & mask) >> LowBits]->lookup_flags(offset, mem_mask); } + +template<int Level, int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> dispatch_read_interruptible(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_read<Width, AddrShift> *const *dispatch) +{ + static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift); + return dispatch[(offset & mask) >> LowBits]->read_interruptible(offset, mem_mask); +} + + +template<int Level, int Width, int AddrShift> void dispatch_write_interruptible(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> data, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_write<Width, AddrShift> *const *dispatch) +{ + static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift); + return dispatch[(offset & mask) >> LowBits]->write_interruptible(offset, data, mem_mask); +} + + // ======================> memory_access_specific // memory_access_specific does uncached but faster accesses by shortcutting the address_space virtual call @@ -1615,7 +1705,7 @@ template<int Level, int Width, int AddrShift, endianness_t Endian> class memory_ { friend class ::address_space; - using NativeType = typename emu::detail::handler_entry_size<Width>::uX; + using NativeType = emu::detail::handler_entry_size_t<Width>; static constexpr u32 NATIVE_BYTES = 1 << Width; static constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? (1 << (Width + AddrShift)) - 1 : 0; @@ -1725,6 +1815,14 @@ public: u16 lookup_write_qword_unaligned_flags(offs_t address) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 3, false>(lwopf(), address, 0xffffffffffffffffU); } u16 lookup_write_qword_unaligned_flags(offs_t address, u64 mask) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 3, false>(lwopf(), address, mask); } + NativeType read_interruptible(offs_t address, NativeType mask = ~NativeType(0)) { + return dispatch_read_interruptible<Level, Width, AddrShift>(offs_t(-1), address & m_addrmask, mask, m_dispatch_read); + } + + void write_interruptible(offs_t address, NativeType data, NativeType mask = ~NativeType(0)) { + dispatch_write_interruptible<Level, Width, AddrShift>(offs_t(-1), address & m_addrmask, data, mask, m_dispatch_write); + } + private: address_space * m_space; @@ -1769,7 +1867,7 @@ template<int Width, int AddrShift, endianness_t Endian> class memory_access_cach { friend class ::address_space; - using NativeType = typename emu::detail::handler_entry_size<Width>::uX; + using NativeType = emu::detail::handler_entry_size_t<Width>; static constexpr u32 NATIVE_BYTES = 1 << Width; static constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? (1 << (Width + AddrShift)) - 1 : 0; @@ -2102,163 +2200,101 @@ public: void install_view(offs_t addrstart, offs_t addrend, memory_view &view) { install_view(addrstart, addrend, 0, view); } virtual void install_view(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_view &view) = 0; + // install wait state handlers + void install_read_before_time(offs_t addrstart, offs_t addrend, ws_time_delegate ws) { install_read_before_time(addrstart, addrend, 0, ws); } + virtual void install_read_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) = 0; + void install_read_before_delay(offs_t addrstart, offs_t addrend, ws_delay_delegate ws) { install_read_before_delay(addrstart, addrend, 0, ws); } + virtual void install_read_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) = 0; + void install_read_after_delay(offs_t addrstart, offs_t addrend, ws_delay_delegate ws) { install_read_after_delay(addrstart, addrend, 0, ws); } + virtual void install_read_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) = 0; + + void install_write_before_time(offs_t addrstart, offs_t addrend, ws_time_delegate ws) { install_write_before_time(addrstart, addrend, 0, ws); } + virtual void install_write_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) = 0; + void install_write_before_delay(offs_t addrstart, offs_t addrend, ws_delay_delegate ws) { install_write_before_delay(addrstart, addrend, 0, ws); } + virtual void install_write_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) = 0; + void install_write_after_delay(offs_t addrstart, offs_t addrend, ws_delay_delegate ws) { install_write_after_delay(addrstart, addrend, 0, ws); } + virtual void install_write_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) = 0; + + void install_readwrite_before_time(offs_t addrstart, offs_t addrend, ws_time_delegate ws) { install_readwrite_before_time(addrstart, addrend, 0, ws); } + virtual void install_readwrite_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) = 0; + void install_readwrite_before_delay(offs_t addrstart, offs_t addrend, ws_delay_delegate ws) { install_readwrite_before_delay(addrstart, addrend, 0, ws); } + virtual void install_readwrite_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) = 0; + void install_readwrite_after_delay(offs_t addrstart, offs_t addrend, ws_delay_delegate ws) { install_readwrite_after_delay(addrstart, addrend, 0, ws); } + virtual void install_readwrite_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) = 0; + // install new-style delegate handlers (short form) - void install_read_handler(offs_t addrstart, offs_t addrend, read8_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write8_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read8_delegate rhandler, write8_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read16_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write16_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read16_delegate rhandler, write16_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read32_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write32_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read32_delegate rhandler, write32_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read64_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write64_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read64_delegate rhandler, write64_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - - void install_read_handler(offs_t addrstart, offs_t addrend, read8m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write8m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read8m_delegate rhandler, write8m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read16m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write16m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read16m_delegate rhandler, write16m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read32m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write32m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read32m_delegate rhandler, write32m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read64m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write64m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read64m_delegate rhandler, write64m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - - void install_read_handler(offs_t addrstart, offs_t addrend, read8s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write8s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read8s_delegate rhandler, write8s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read16s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write16s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read16s_delegate rhandler, write16s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read32s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write32s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read32s_delegate rhandler, write32s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read64s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write64s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read64s_delegate rhandler, write64s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - - void install_read_handler(offs_t addrstart, offs_t addrend, read8sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write8sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read8sm_delegate rhandler, write8sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read16sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write16sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read16sm_delegate rhandler, write16sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read32sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write32sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read32sm_delegate rhandler, write32sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read64sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write64sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read64sm_delegate rhandler, write64sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - - void install_read_handler(offs_t addrstart, offs_t addrend, read8mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write8mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read8mo_delegate rhandler, write8mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read16mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write16mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read16mo_delegate rhandler, write16mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read32mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write32mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read32mo_delegate rhandler, write32mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read64mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write64mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read64mo_delegate rhandler, write64mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - - void install_read_handler(offs_t addrstart, offs_t addrend, read8smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write8smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read8smo_delegate rhandler, write8smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read16smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write16smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read16smo_delegate rhandler, write16smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read32smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write32smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read32smo_delegate rhandler, write32smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } - void install_read_handler(offs_t addrstart, offs_t addrend, read64smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth, flags); } - void install_write_handler(offs_t addrstart, offs_t addrend, write64smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth, flags); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, read64smo_delegate rhandler, write64smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) { install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth, flags); } + template <typename R> + void install_read_handler(offs_t addrstart, offs_t addrend, R &&rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) + { install_read_handler(addrstart, addrend, 0, 0, 0, std::forward<R>(rhandler), unitmask, cswidth, flags); } + template <typename W> + void install_write_handler(offs_t addrstart, offs_t addrend, W &&whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) + { install_write_handler(addrstart, addrend, 0, 0, 0, std::forward<W>(whandler), unitmask, cswidth, flags); } + template <typename R, typename W> + void install_readwrite_handler(offs_t addrstart, offs_t addrend, R &&rhandler, W &&whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) + { install_readwrite_handler(addrstart, addrend, 0, 0, 0, std::forward<R>(rhandler), std::forward<W>(whandler), unitmask, cswidth, flags); } // install new-style delegate handlers (with mirror/mask) virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8_delegate rhandler, write8_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16_delegate rhandler, write16_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32_delegate rhandler, write32_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64_delegate rhandler, write64_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8m_delegate rhandler, write8m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16m_delegate rhandler, write16m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32m_delegate rhandler, write32m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64m_delegate rhandler, write64m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8s_delegate rhandler, write8s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16s_delegate rhandler, write16s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32s_delegate rhandler, write32s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64s_delegate rhandler, write64s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8sm_delegate rhandler, write8sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16sm_delegate rhandler, write16sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32sm_delegate rhandler, write32sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64sm_delegate rhandler, write64sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8mo_delegate rhandler, write8mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16mo_delegate rhandler, write16mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32mo_delegate rhandler, write32mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64mo_delegate rhandler, write64mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8smo_delegate rhandler, write8smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16smo_delegate rhandler, write16smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32smo_delegate rhandler, write32smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; - virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64smo_delegate rhandler, write64smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0; + + template <typename R, typename W> + void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, R &&rhandler, W &&whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) + { + static_assert(emu::detail::handler_width_v<std::remove_reference_t<R> > == emu::detail::handler_width_v<std::remove_reference_t<W> >, "handler widths do not match"); + install_read_handler(addrstart, addrend, addrmask, addrmirror, addrselect, std::forward<R>(rhandler), unitmask, cswidth, flags); + install_write_handler(addrstart, addrend, addrmask, addrmirror, addrselect, std::forward<W>(whandler), unitmask, cswidth, flags); + } protected: virtual void unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, read_or_write readorwrite, bool quiet) = 0; @@ -2358,8 +2394,10 @@ public: virtual void remove_passthrough(std::unordered_set<handler_entry *> &handlers) = 0; u64 unmap() const { return m_unmap; } + void unmap_value_high() { m_unmap = ~0; } std::shared_ptr<emu::detail::memory_passthrough_handler_impl> make_mph(memory_passthrough_handler *mph); + std::shared_ptr<emu::detail::memory_passthrough_handler_impl> get_default_mpl() { return m_default_mpl; } // debug helpers virtual std::string get_handler_string(read_or_write readorwrite, offs_t byteaddress) const = 0; @@ -2440,6 +2478,9 @@ protected: util::notifier<read_or_write> m_notifiers; // notifier list for address map change u32 m_in_notification; // notification(s) currently being done + + // passthrough handler used for wait states + std::shared_ptr<emu::detail::memory_passthrough_handler_impl> m_default_mpl; }; @@ -2726,9 +2767,9 @@ private: template<int Width, int AddrShift, endianness_t Endian> -typename emu::detail::handler_entry_size<Width>::uX +emu::detail::handler_entry_size_t<Width> emu::detail::memory_access_cache<Width, AddrShift, Endian>:: -read_native(offs_t address, typename emu::detail::handler_entry_size<Width>::uX mask) +read_native(offs_t address, emu::detail::handler_entry_size_t<Width> mask) { address &= m_addrmask; check_address_r(address); @@ -2737,7 +2778,7 @@ read_native(offs_t address, typename emu::detail::handler_entry_size<Width>::uX template<int Width, int AddrShift, endianness_t Endian> void emu::detail::memory_access_cache<Width, AddrShift, Endian>:: -write_native(offs_t address, typename emu::detail::handler_entry_size<Width>::uX data, typename emu::detail::handler_entry_size<Width>::uX mask) +write_native(offs_t address, emu::detail::handler_entry_size_t<Width> data, emu::detail::handler_entry_size_t<Width> mask) { address &= m_addrmask; check_address_w(address); diff --git a/src/emu/emumem_aspace.cpp b/src/emu/emumem_aspace.cpp index 89849ad9aca..b0d00d6fca8 100644 --- a/src/emu/emumem_aspace.cpp +++ b/src/emu/emumem_aspace.cpp @@ -25,6 +25,7 @@ #include "emumem_hedw.h" #include "emumem_hep.h" #include "emumem_het.h" +#include "emumem_hws.h" //************************************************************************** @@ -48,58 +49,7 @@ template <typename Format, typename... Params> static void VPRINTF(Format &&, Pa // CONSTANTS //************************************************************************** -namespace { - -template <typename Delegate> struct handler_width; -template <> struct handler_width<read8_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<read8m_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<read8s_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<read8sm_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<read8mo_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<read8smo_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<write8_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<write8m_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<write8s_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<write8sm_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<write8mo_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<write8smo_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<read16_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<read16m_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<read16s_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<read16sm_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<read16mo_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<read16smo_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<write16_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<write16m_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<write16s_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<write16sm_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<write16mo_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<write16smo_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<read32_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<read32m_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<read32s_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<read32sm_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<read32mo_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<read32smo_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<write32_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<write32m_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<write32s_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<write32sm_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<write32mo_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<write32smo_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<read64_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<read64m_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<read64s_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<read64sm_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<read64mo_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<read64smo_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<write64_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<write64m_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<write64s_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<write64sm_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<write64mo_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<write64smo_delegate> { static constexpr int value = 3; }; -} // anonymous namespace +using emu::detail::handler_width_v; //************************************************************************** @@ -112,7 +62,7 @@ template <> struct handler_width<write64smo_delegate> { static constexpr int val template<int Level, int Width, int AddrShift, endianness_t Endian> class address_space_specific : public address_space { - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; using NativeType = uX; using this_type = address_space_specific<Level, Width, AddrShift, Endian>; @@ -138,155 +88,119 @@ public: void install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_constructor &map, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override; void install_view(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_view &view) override; + void install_read_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) override; + void install_read_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) override; + void install_read_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) override; + + void install_write_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) override; + void install_write_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) override; + void install_write_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) override; + + void install_readwrite_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) override; + void install_readwrite_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) override; + void install_readwrite_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) override; + void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8_delegate rhandler, write8_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16_delegate rhandler, write16_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32_delegate rhandler, write32_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64_delegate rhandler, write64_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8m_delegate rhandler, write8m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16m_delegate rhandler, write16m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32m_delegate rhandler, write32m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64m_delegate rhandler, write64m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8s_delegate rhandler, write8s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16s_delegate rhandler, write16s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32s_delegate rhandler, write32s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64s_delegate rhandler, write64s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8sm_delegate rhandler, write8sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16sm_delegate rhandler, write16sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32sm_delegate rhandler, write32sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64sm_delegate rhandler, write64sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8mo_delegate rhandler, write8mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16mo_delegate rhandler, write16mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32mo_delegate rhandler, write32mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64mo_delegate rhandler, write64mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8smo_delegate rhandler, write8smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16smo_delegate rhandler, write16smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32smo_delegate rhandler, write32smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64smo_delegate rhandler, write64smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } using address_space::install_read_tap; using address_space::install_write_tap; @@ -514,7 +428,7 @@ private: osd_printf_error("Binding error while installing read handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_r.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask); throw; } - install_read_handler_helper<handler_width<READ>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, handler_r); + install_read_handler_helper<handler_width_v<READ> >(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, handler_r); } template<typename WRITE> @@ -525,24 +439,7 @@ private: osd_printf_error("Binding error while installing write handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_w.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask); throw; } - install_write_handler_helper<handler_width<WRITE>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, handler_w); - } - - template<typename READ, typename WRITE> - void install_readwrite_handler_impl(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, u16 flags, READ &handler_r, WRITE &handler_w) - { - static_assert(handler_width<READ>::value == handler_width<WRITE>::value, "handler widths do not match"); - try { handler_r.resolve(); } - catch (const binding_type_exception &) { - osd_printf_error("Binding error while installing read handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_r.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask); - throw; - } - try { handler_w.resolve(); } - catch (const binding_type_exception &) { - osd_printf_error("Binding error while installing write handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_w.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask); - throw; - } - install_readwrite_handler_helper<handler_width<READ>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, handler_r, handler_w); + install_write_handler_helper<handler_width_v<WRITE> >(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, handler_w); } template<int AccessWidth, typename READ> @@ -609,50 +506,6 @@ private: invalidate_caches(read_or_write::WRITE); } } - - template<int AccessWidth, typename READ, typename WRITE> - void install_readwrite_handler_helper(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, u16 flags, - const READ &handler_r, - const WRITE &handler_w) - { - if constexpr (Width < AccessWidth) { - fatalerror("install_readwrite_handler: cannot install a %d-wide handler in a %d-wide bus", 8 << AccessWidth, 8 << Width); - } else { - VPRINTF("address_space::install_readwrite_handler(%*x-%*x mask=%*x mirror=%*x, space width=%d, handler width=%d, %s, %s, %*x)\n", - m_addrchars, addrstart, m_addrchars, addrend, - m_addrchars, addrmask, m_addrchars, addrmirror, - 8 << Width, 8 << AccessWidth, - handler_r.name(), handler_w.name(), data_width() / 4, unitmask); - - offs_t nstart, nend, nmask, nmirror; - u64 nunitmask; - int ncswidth; - check_optimize_all("install_readwrite_handler", 8 << AccessWidth, addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, nstart, nend, nmask, nmirror, nunitmask, ncswidth); - - if constexpr (Width == AccessWidth) { - auto hand_r = new handler_entry_read_delegate <Width, AddrShift, READ>(this, flags, handler_r); - hand_r->set_address_info(nstart, nmask); - m_root_read ->populate(nstart, nend, nmirror, hand_r); - - auto hand_w = new handler_entry_write_delegate<Width, AddrShift, WRITE>(this, flags, handler_w); - hand_w->set_address_info(nstart, nmask); - m_root_write->populate(nstart, nend, nmirror, hand_w); - } else { - auto hand_r = new handler_entry_read_delegate <AccessWidth, -AccessWidth, READ>(this, flags, handler_r); - memory_units_descriptor<Width, AddrShift> descriptor(AccessWidth, Endian, hand_r, nstart, nend, nmask, nunitmask, ncswidth); - hand_r->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask()); - m_root_read ->populate_mismatched(nstart, nend, nmirror, descriptor); - hand_r->unref(); - - auto hand_w = new handler_entry_write_delegate<AccessWidth, -AccessWidth, WRITE>(this, flags, handler_w); - descriptor.set_subunit_handler(hand_w); - hand_w->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask()); - m_root_write->populate_mismatched(nstart, nend, nmirror, descriptor); - hand_w->unref(); - } - invalidate_caches(read_or_write::READWRITE); - } - } }; @@ -760,7 +613,8 @@ address_space::address_space(memory_manager &manager, device_memory_interface &m m_spacenum(spacenum), m_log_unmap(true), m_name(memory.space_config(spacenum)->name()), - m_in_notification(0) + m_in_notification(0), + m_default_mpl(make_mph(nullptr)) { } @@ -1172,6 +1026,194 @@ template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passth //------------------------------------------------- +// install the wait state handlers +//------------------------------------------------- + + +template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_read_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_device.tag()); + + VPRINTF("address_space::install_read_before_time(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_read_before_time", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + auto hand_r = new handler_entry_read_before_time<Width, AddrShift>(this, *m_default_mpl, ws); + m_root_read->populate_passthrough(nstart, nend, nmirror, hand_r); +} + +template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_read_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_device.tag()); + + VPRINTF("address_space::install_read_before_delay(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_read_before_delay", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + auto hand_r = new handler_entry_read_before_delay<Width, AddrShift>(this, *m_default_mpl, ws); + m_root_read->populate_passthrough(nstart, nend, nmirror, hand_r); +} + +template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_read_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_device.tag()); + + VPRINTF("address_space::install_read_after_delay(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_read_after_delay", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + auto hand_r = new handler_entry_read_after_delay<Width, AddrShift>(this, *m_default_mpl, ws); + m_root_read->populate_passthrough(nstart, nend, nmirror, hand_r); +} + + + +template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_write_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_device.tag()); + + VPRINTF("address_space::install_write_before_time(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_write_before_time", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + auto hand_w = new handler_entry_write_before_time<Width, AddrShift>(this, *m_default_mpl, ws); + m_root_write->populate_passthrough(nstart, nend, nmirror, hand_w); +} + +template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_write_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_device.tag()); + + VPRINTF("address_space::install_write_before_delay(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_write_before_delay", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + auto hand_w = new handler_entry_write_before_delay<Width, AddrShift>(this, *m_default_mpl, ws); + m_root_write->populate_passthrough(nstart, nend, nmirror, hand_w); +} + +template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_write_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_device.tag()); + + VPRINTF("address_space::install_write_after_delay(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_write_after_delay", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + auto hand_w = new handler_entry_write_after_delay<Width, AddrShift>(this, *m_default_mpl, ws); + m_root_write->populate_passthrough(nstart, nend, nmirror, hand_w); +} + + +template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_readwrite_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_device.tag()); + + VPRINTF("address_space::install_readwrite_before_time(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_readwrite_before_time", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + auto hand_r = new handler_entry_read_before_time<Width, AddrShift>(this, *m_default_mpl, ws); + m_root_read->populate_passthrough(nstart, nend, nmirror, hand_r); + auto hand_w = new handler_entry_write_before_time<Width, AddrShift>(this, *m_default_mpl, ws); + m_root_write->populate_passthrough(nstart, nend, nmirror, hand_w); +} + +template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_readwrite_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_device.tag()); + + VPRINTF("address_space::install_readwrite_before_delay(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_readwrite_before_delay", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + auto hand_r = new handler_entry_read_before_delay<Width, AddrShift>(this, *m_default_mpl, ws); + m_root_read->populate_passthrough(nstart, nend, nmirror, hand_r); + auto hand_w = new handler_entry_write_before_delay<Width, AddrShift>(this, *m_default_mpl, ws); + m_root_write->populate_passthrough(nstart, nend, nmirror, hand_w); +} + +template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_readwrite_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_device.tag()); + + VPRINTF("address_space::install_readwrite_after_delay(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_readwrite_after_delay", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + auto hand_r = new handler_entry_read_after_delay<Width, AddrShift>(this, *m_default_mpl, ws); + m_root_read->populate_passthrough(nstart, nend, nmirror, hand_r); + auto hand_w = new handler_entry_write_after_delay<Width, AddrShift>(this, *m_default_mpl, ws); + m_root_write->populate_passthrough(nstart, nend, nmirror, hand_w); +} + + + + +//------------------------------------------------- // install_bank_generic - install a range as // mapping to a particular bank //------------------------------------------------- diff --git a/src/emu/emumem_hea.h b/src/emu/emumem_hea.h index e8308a73960..9ee6f8c8a1e 100644 --- a/src/emu/emumem_hea.h +++ b/src/emu/emumem_hea.h @@ -8,7 +8,7 @@ template<int Width, int AddrShift> class handler_entry_read_address : public handler_entry_read<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_read_address(address_space *space, u32 flags) : handler_entry_read<Width, AddrShift>(space, flags) {} ~handler_entry_read_address() = default; @@ -25,7 +25,7 @@ protected: template<int Width, int AddrShift> class handler_entry_write_address : public handler_entry_write<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; static constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? (1 << (Width + AddrShift)) - 1 : 0; diff --git a/src/emu/emumem_hedp.cpp b/src/emu/emumem_hedp.cpp index dbbcd19c6ee..b053f84c592 100644 --- a/src/emu/emumem_hedp.cpp +++ b/src/emu/emumem_hedp.cpp @@ -10,7 +10,7 @@ template<int Width, int AddrShift, typename READ> template<typename R> std::is_same<R, read16_delegate>::value || std::is_same<R, read32_delegate>::value || std::is_same<R, read64_delegate>::value, - typename emu::detail::handler_entry_size<Width>::uX> handler_entry_read_delegate<Width, AddrShift, READ>::read_impl(offs_t offset, uX mem_mask) const + emu::detail::handler_entry_size_t<Width> > handler_entry_read_delegate<Width, AddrShift, READ>::read_impl(offs_t offset, uX mem_mask) const { return m_delegate(*this->m_space, ((offset - this->m_address_base) & this->m_address_mask) >> (Width + AddrShift), mem_mask); } @@ -20,7 +20,7 @@ template<int Width, int AddrShift, typename READ> template<typename R> std::is_same<R, read16m_delegate>::value || std::is_same<R, read32m_delegate>::value || std::is_same<R, read64m_delegate>::value, - typename emu::detail::handler_entry_size<Width>::uX> handler_entry_read_delegate<Width, AddrShift, READ>::read_impl(offs_t offset, uX mem_mask) const + emu::detail::handler_entry_size_t<Width> > handler_entry_read_delegate<Width, AddrShift, READ>::read_impl(offs_t offset, uX mem_mask) const { return m_delegate(*this->m_space, ((offset - this->m_address_base) & this->m_address_mask) >> (Width + AddrShift)); } @@ -30,7 +30,7 @@ template<int Width, int AddrShift, typename READ> template<typename R> std::is_same<R, read16s_delegate>::value || std::is_same<R, read32s_delegate>::value || std::is_same<R, read64s_delegate>::value, - typename emu::detail::handler_entry_size<Width>::uX> handler_entry_read_delegate<Width, AddrShift, READ>::read_impl(offs_t offset, uX mem_mask) const + emu::detail::handler_entry_size_t<Width> > handler_entry_read_delegate<Width, AddrShift, READ>::read_impl(offs_t offset, uX mem_mask) const { return m_delegate(((offset - this->m_address_base) & this->m_address_mask) >> (Width + AddrShift), mem_mask); } @@ -40,7 +40,7 @@ template<int Width, int AddrShift, typename READ> template<typename R> std::is_same<R, read16sm_delegate>::value || std::is_same<R, read32sm_delegate>::value || std::is_same<R, read64sm_delegate>::value, - typename emu::detail::handler_entry_size<Width>::uX> handler_entry_read_delegate<Width, AddrShift, READ>::read_impl(offs_t offset, uX mem_mask) const + emu::detail::handler_entry_size_t<Width> > handler_entry_read_delegate<Width, AddrShift, READ>::read_impl(offs_t offset, uX mem_mask) const { return m_delegate(((offset - this->m_address_base) & this->m_address_mask) >> (Width + AddrShift)); } @@ -50,7 +50,7 @@ template<int Width, int AddrShift, typename READ> template<typename R> std::is_same<R, read16mo_delegate>::value || std::is_same<R, read32mo_delegate>::value || std::is_same<R, read64mo_delegate>::value, - typename emu::detail::handler_entry_size<Width>::uX> handler_entry_read_delegate<Width, AddrShift, READ>::read_impl(offs_t offset, uX mem_mask) const + emu::detail::handler_entry_size_t<Width> > handler_entry_read_delegate<Width, AddrShift, READ>::read_impl(offs_t offset, uX mem_mask) const { return m_delegate(*this->m_space); } @@ -60,17 +60,22 @@ template<int Width, int AddrShift, typename READ> template<typename R> std::is_same<R, read16smo_delegate>::value || std::is_same<R, read32smo_delegate>::value || std::is_same<R, read64smo_delegate>::value, - typename emu::detail::handler_entry_size<Width>::uX> handler_entry_read_delegate<Width, AddrShift, READ>::read_impl(offs_t offset, uX mem_mask) const + emu::detail::handler_entry_size_t<Width> > handler_entry_read_delegate<Width, AddrShift, READ>::read_impl(offs_t offset, uX mem_mask) const { return m_delegate(); } -template<int Width, int AddrShift, typename READ> typename emu::detail::handler_entry_size<Width>::uX handler_entry_read_delegate<Width, AddrShift, READ>::read(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift, typename READ> emu::detail::handler_entry_size_t<Width> handler_entry_read_delegate<Width, AddrShift, READ>::read(offs_t offset, uX mem_mask) const { return read_impl<READ>(offset, mem_mask); } -template<int Width, int AddrShift, typename READ> std::pair<typename emu::detail::handler_entry_size<Width>::uX, u16> handler_entry_read_delegate<Width, AddrShift, READ>::read_flags(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift, typename READ> emu::detail::handler_entry_size_t<Width> handler_entry_read_delegate<Width, AddrShift, READ>::read_interruptible(offs_t offset, uX mem_mask) const +{ + return read_impl<READ>(offset, mem_mask); +} + +template<int Width, int AddrShift, typename READ> std::pair<emu::detail::handler_entry_size_t<Width>, u16> handler_entry_read_delegate<Width, AddrShift, READ>::read_flags(offs_t offset, uX mem_mask) const { return std::pair<uX, u16>(read_impl<READ>(offset, mem_mask), this->m_flags); } @@ -150,6 +155,11 @@ template<int Width, int AddrShift, typename WRITE> void handler_entry_write_dele write_impl<WRITE>(offset, data, mem_mask); } +template<int Width, int AddrShift, typename WRITE> void handler_entry_write_delegate<Width, AddrShift, WRITE>::write_interruptible(offs_t offset, uX data, uX mem_mask) const +{ + write_impl<WRITE>(offset, data, mem_mask); +} + template<int Width, int AddrShift, typename WRITE> u16 handler_entry_write_delegate<Width, AddrShift, WRITE>::write_flags(offs_t offset, uX data, uX mem_mask) const { write_impl<WRITE>(offset, data, mem_mask); @@ -169,12 +179,17 @@ template<int Width, int AddrShift, typename WRITE> std::string handler_entry_wri -template<int Width, int AddrShift> typename emu::detail::handler_entry_size<Width>::uX handler_entry_read_ioport<Width, AddrShift>::read(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_ioport<Width, AddrShift>::read(offs_t offset, uX mem_mask) const { return m_port->read(); } -template<int Width, int AddrShift> std::pair<typename emu::detail::handler_entry_size<Width>::uX, u16> handler_entry_read_ioport<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_ioport<Width, AddrShift>::read_interruptible(offs_t offset, uX mem_mask) const +{ + return m_port->read(); +} + +template<int Width, int AddrShift> std::pair<emu::detail::handler_entry_size_t<Width>, u16> handler_entry_read_ioport<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const { return std::pair<uX, u16>(m_port->read(), this->m_flags); } @@ -194,6 +209,11 @@ template<int Width, int AddrShift> void handler_entry_write_ioport<Width, AddrSh m_port->write(data, mem_mask); } +template<int Width, int AddrShift> void handler_entry_write_ioport<Width, AddrShift>::write_interruptible(offs_t offset, uX data, uX mem_mask) const +{ + m_port->write(data, mem_mask); +} + template<int Width, int AddrShift> u16 handler_entry_write_ioport<Width, AddrShift>::write_flags(offs_t offset, uX data, uX mem_mask) const { m_port->write(data, mem_mask); diff --git a/src/emu/emumem_hedp.h b/src/emu/emumem_hedp.h index aa43cdce0df..6b8563bd5b5 100644 --- a/src/emu/emumem_hedp.h +++ b/src/emu/emumem_hedp.h @@ -12,12 +12,13 @@ template<int Width, int AddrShift, typename READ> class handler_entry_read_delegate : public handler_entry_read_address<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_read_delegate(address_space *space, u16 flags, const READ &delegate) : handler_entry_read_address<Width, AddrShift>(space, flags), m_delegate(delegate) {} ~handler_entry_read_delegate() = default; uX read(offs_t offset, uX mem_mask) const override; + uX read_interruptible(offs_t offset, uX mem_mask) const override; std::pair<uX, u16> read_flags(offs_t offset, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; @@ -72,12 +73,13 @@ private: template<int Width, int AddrShift, typename WRITE> class handler_entry_write_delegate : public handler_entry_write_address<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_write_delegate(address_space *space, u16 flags, const WRITE &delegate) : handler_entry_write_address<Width, AddrShift>(space, flags), m_delegate(delegate) {} ~handler_entry_write_delegate() = default; void write(offs_t offset, uX data, uX mem_mask) const override; + void write_interruptible(offs_t offset, uX data, uX mem_mask) const override; u16 write_flags(offs_t offset, uX data, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; @@ -137,12 +139,13 @@ private: template<int Width, int AddrShift> class handler_entry_read_ioport : public handler_entry_read<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_read_ioport(address_space *space, u16 flags, ioport_port *port) : handler_entry_read<Width, AddrShift>(space, flags), m_port(port) {} ~handler_entry_read_ioport() = default; uX read(offs_t offset, uX mem_mask) const override; + uX read_interruptible(offs_t offset, uX mem_mask) const override; std::pair<uX, u16> read_flags(offs_t offset, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; @@ -155,12 +158,13 @@ private: template<int Width, int AddrShift> class handler_entry_write_ioport : public handler_entry_write<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_write_ioport(address_space *space, u16 flags, ioport_port *port) : handler_entry_write<Width, AddrShift>(space, flags), m_port(port) {} ~handler_entry_write_ioport() = default; void write(offs_t offset, uX data, uX mem_mask) const override; + void write_interruptible(offs_t offset, uX data, uX mem_mask) const override; u16 write_flags(offs_t offset, uX data, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; diff --git a/src/emu/emumem_hedr.h b/src/emu/emumem_hedr.h index 07de814f54d..e1e9aa98743 100644 --- a/src/emu/emumem_hedr.h +++ b/src/emu/emumem_hedr.h @@ -13,7 +13,7 @@ template<int HighBits, int Width, int AddrShift> class handler_entry_read_dispatch : public handler_entry_read<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; using mapping = typename handler_entry_read<Width, AddrShift>::mapping; handler_entry_read_dispatch(address_space *space, const handler_entry::range &init, handler_entry_read<Width, AddrShift> *handler); @@ -22,6 +22,7 @@ public: ~handler_entry_read_dispatch(); uX read(offs_t offset, uX mem_mask) const override; + uX read_interruptible(offs_t offset, uX mem_mask) const override; std::pair<uX, u16> read_flags(offs_t offset, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; void *get_ptr(offs_t offset) const override; diff --git a/src/emu/emumem_hedr.ipp b/src/emu/emumem_hedr.ipp index 0efc37a478f..9994f251897 100644 --- a/src/emu/emumem_hedr.ipp +++ b/src/emu/emumem_hedr.ipp @@ -127,12 +127,17 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc } } -template<int HighBits, int Width, int AddrShift> typename emu::detail::handler_entry_size<Width>::uX handler_entry_read_dispatch<HighBits, Width, AddrShift>::read(offs_t offset, uX mem_mask) const +template<int HighBits, int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_dispatch<HighBits, Width, AddrShift>::read(offs_t offset, uX mem_mask) const { return dispatch_read<Level, Width, AddrShift>(HIGHMASK, offset, mem_mask, m_a_dispatch); } -template<int HighBits, int Width, int AddrShift> std::pair<typename emu::detail::handler_entry_size<Width>::uX, u16> handler_entry_read_dispatch<HighBits, Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const +template<int HighBits, int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_dispatch<HighBits, Width, AddrShift>::read_interruptible(offs_t offset, uX mem_mask) const +{ + return dispatch_read_interruptible<Level, Width, AddrShift>(HIGHMASK, offset, mem_mask, m_a_dispatch); +} + +template<int HighBits, int Width, int AddrShift> std::pair<emu::detail::handler_entry_size_t<Width>, u16> handler_entry_read_dispatch<HighBits, Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const { return dispatch_read_flags<Level, Width, AddrShift>(HIGHMASK, offset, mem_mask, m_a_dispatch); } @@ -201,6 +206,8 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc cur->unref(); m_u_dispatch[entry] = subdispatch; subdispatch->populate_nomirror(start, end, ostart, oend, handler); + range_cut_before((entry << LowBits) - 1, entry); + range_cut_after((entry + 1) << LowBits, entry); } } @@ -276,6 +283,8 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc cur->unref(); m_u_dispatch[entry] = subdispatch; subdispatch->populate_mirror(start, end, ostart, oend, mirror, handler); + range_cut_before((entry << LowBits) - 1, entry); + range_cut_after((entry + 1) << LowBits, entry); } } @@ -440,23 +449,64 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc } } - template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatch<HighBits, Width, AddrShift>::passthrough_patch(handler_entry_read_passthrough<Width, AddrShift> *handler, std::vector<mapping> &mappings, handler_entry_read<Width, AddrShift> *&target) { - handler_entry_read<Width, AddrShift> *original = target; - handler_entry_read<Width, AddrShift> *replacement = nullptr; + // Look in cache first for(const auto &p : mappings) - if(p.original == original) { - replacement = p.patched; - break; + if(p.original == target) { + p.patched->ref(); + target->unref(); + target = p.patched; + return; } - if(!replacement) { - replacement = handler->instantiate(original); + + handler_entry_read<Width, AddrShift> *original = target; + u32 target_priority = original->f_get_pt(); + u32 new_priority = handler->f_get_pt(); + + // 3 cases: new one on top, new one on bottom, or new one replaces old one + + if(!target_priority || new_priority > target_priority || (new_priority == target_priority && !(new_priority & 1))) { + // New one goes over the old one + // previous one is not passthrough (target_priority = 0) + // new one has higher priority + // both have the same priority, and the priority is even which means keep both + + // We instantiate the new one with the old one under it and put it in place and in the cache + + handler_entry_read<Width, AddrShift> *replacement = handler->instantiate(original); mappings.emplace_back(mapping{ original, replacement }); - } else - replacement->ref(); - target->unref(); - target = replacement; + target->unref(); + target = replacement; + + } else if(new_priority == target_priority) { + // New one replaces the old one + // both have the same priority, and the priority is odd which means keep only the new one + + // We instantiate the new one with the old one's subtarget and put it in place and in the cache + + handler_entry_read<Width, AddrShift> *replacement = handler->instantiate(static_cast<handler_entry_read_passthrough<Width, AddrShift> *>(original)->get_subhandler()); + mappings.emplace_back(mapping{ original, replacement }); + target->unref(); + target = replacement; + + } else { + // New one goes under the old one + // both are passthrough and new one has lower priority + // + // This can be recursive, so do the passthrough patch on the subhandler, then instantiate the old one with the result + + handler_entry_read<Width, AddrShift> *recursive = static_cast<handler_entry_read_passthrough<Width, AddrShift> *>(original)->get_subhandler(); + recursive->ref(); + + passthrough_patch(handler, mappings, recursive); + + handler_entry_read<Width, AddrShift> *replacement = static_cast<handler_entry_read_passthrough<Width, AddrShift> *>(original)->instantiate(recursive); + mappings.emplace_back(mapping{ original, replacement }); + target->unref(); + target = replacement; + recursive->unref(); + } } template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatch<HighBits, Width, AddrShift>::populate_passthrough_nomirror_subdispatch(offs_t entry, offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_read_passthrough<Width, AddrShift> *handler, std::vector<mapping> &mappings) diff --git a/src/emu/emumem_hedw.h b/src/emu/emumem_hedw.h index 18972814744..130293a73a4 100644 --- a/src/emu/emumem_hedw.h +++ b/src/emu/emumem_hedw.h @@ -13,7 +13,7 @@ template<int HighBits, int Width, int AddrShift> class handler_entry_write_dispatch : public handler_entry_write<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; using mapping = typename handler_entry_write<Width, AddrShift>::mapping; handler_entry_write_dispatch(address_space *space, const handler_entry::range &init, handler_entry_write<Width, AddrShift> *handler); @@ -22,6 +22,7 @@ public: ~handler_entry_write_dispatch(); void write(offs_t offset, uX data, uX mem_mask) const override; + void write_interruptible(offs_t offset, uX data, uX mem_mask) const override; u16 write_flags(offs_t offset, uX data, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; void *get_ptr(offs_t offset) const override; diff --git a/src/emu/emumem_hedw.ipp b/src/emu/emumem_hedw.ipp index a45b5eceef9..37c09ccfe11 100644 --- a/src/emu/emumem_hedw.ipp +++ b/src/emu/emumem_hedw.ipp @@ -131,6 +131,11 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_write_dispat dispatch_write<Level, Width, AddrShift>(HIGHMASK, offset, data, mem_mask, m_a_dispatch); } +template<int HighBits, int Width, int AddrShift> void handler_entry_write_dispatch<HighBits, Width, AddrShift>::write_interruptible(offs_t offset, uX data, uX mem_mask) const +{ + dispatch_write_interruptible<Level, Width, AddrShift>(HIGHMASK, offset, data, mem_mask, m_a_dispatch); +} + template<int HighBits, int Width, int AddrShift> u16 handler_entry_write_dispatch<HighBits, Width, AddrShift>::write_flags(offs_t offset, uX data, uX mem_mask) const { return dispatch_write_flags<Level, Width, AddrShift>(HIGHMASK, offset, data, mem_mask, m_a_dispatch); @@ -200,6 +205,8 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_write_dispat cur->unref(); m_u_dispatch[entry] = subdispatch; subdispatch->populate_nomirror(start, end, ostart, oend, handler); + range_cut_before((entry << LowBits) - 1, entry); + range_cut_after((entry + 1) << LowBits, entry); } } @@ -275,6 +282,8 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_write_dispat cur->unref(); m_u_dispatch[entry] = subdispatch; subdispatch->populate_mirror(start, end, ostart, oend, mirror, handler); + range_cut_before((entry << LowBits) - 1, entry); + range_cut_after((entry + 1) << LowBits, entry); } } @@ -442,20 +451,63 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_write_dispat template<int HighBits, int Width, int AddrShift> void handler_entry_write_dispatch<HighBits, Width, AddrShift>::passthrough_patch(handler_entry_write_passthrough<Width, AddrShift> *handler, std::vector<mapping> &mappings, handler_entry_write<Width, AddrShift> *&target) { - handler_entry_write<Width, AddrShift> *original = target; - handler_entry_write<Width, AddrShift> *replacement = nullptr; + // Look in cache first for(const auto &p : mappings) - if(p.original == original) { - replacement = p.patched; - break; + if(p.original == target) { + p.patched->ref(); + target->unref(); + target = p.patched; + return; } - if(!replacement) { - replacement = handler->instantiate(original); + + handler_entry_write<Width, AddrShift> *original = target; + u32 target_priority = original->f_get_pt(); + u32 new_priority = handler->f_get_pt(); + + // 3 cases: new one on top, new one on bottom, or new one replaces old one + + if(!target_priority || new_priority > target_priority || (new_priority == target_priority && !(new_priority & 1))) { + // New one goes over the old one + // previous one is not passthrough (target_priority = 0) + // new one has higher priority + // both have the same priority, and the priority is even which means keep both + + // We instantiate the new one with the old one under it and put it in place and in the cache + + handler_entry_write<Width, AddrShift> *replacement = handler->instantiate(original); mappings.emplace_back(mapping{ original, replacement }); - } else - replacement->ref(); - target->unref(); - target = replacement; + target->unref(); + target = replacement; + + } else if(new_priority == target_priority) { + // New one replaces the old one + // both have the same priority, and the priority is odd which means keep only the new one + + // We instantiate the new one with the old one's subtarget and put it in place and in the cache + + handler_entry_write<Width, AddrShift> *replacement = handler->instantiate(static_cast<handler_entry_write_passthrough<Width, AddrShift> *>(original)->get_subhandler()); + mappings.emplace_back(mapping{ original, replacement }); + target->unref(); + target = replacement; + + } else { + // New one goes under the old one + // both are passthrough and new one has lower priority + // + // This can be recursive, so do the passthrough patch on the subhandler, then instantiate the old one with the result + + handler_entry_write<Width, AddrShift> *recursive = static_cast<handler_entry_write_passthrough<Width, AddrShift> *>(original)->get_subhandler(); + recursive->ref(); + + passthrough_patch(handler, mappings, recursive); + + handler_entry_write<Width, AddrShift> *replacement = static_cast<handler_entry_write_passthrough<Width, AddrShift> *>(original)->instantiate(recursive); + mappings.emplace_back(mapping{ original, replacement }); + target->unref(); + target = replacement; + recursive->unref(); + } + } template<int HighBits, int Width, int AddrShift> void handler_entry_write_dispatch<HighBits, Width, AddrShift>::populate_passthrough_nomirror_subdispatch(offs_t entry, offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_write_passthrough<Width, AddrShift> *handler, std::vector<mapping> &mappings) diff --git a/src/emu/emumem_hem.cpp b/src/emu/emumem_hem.cpp index 57a02d254f6..e69206d7653 100644 --- a/src/emu/emumem_hem.cpp +++ b/src/emu/emumem_hem.cpp @@ -5,12 +5,17 @@ #include "emumem_hea.h" #include "emumem_hem.h" -template<int Width, int AddrShift> typename emu::detail::handler_entry_size<Width>::uX handler_entry_read_memory<Width, AddrShift>::read(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_memory<Width, AddrShift>::read(offs_t offset, uX mem_mask) const { return m_base[((offset - this->m_address_base) & this->m_address_mask) >> (Width + AddrShift)]; } -template<int Width, int AddrShift> std::pair<typename emu::detail::handler_entry_size<Width>::uX, u16> handler_entry_read_memory<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_memory<Width, AddrShift>::read_interruptible(offs_t offset, uX mem_mask) const +{ + return m_base[((offset - this->m_address_base) & this->m_address_mask) >> (Width + AddrShift)]; +} + +template<int Width, int AddrShift> std::pair<emu::detail::handler_entry_size_t<Width>, u16> handler_entry_read_memory<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const { return std::pair<uX, u16>(m_base[((offset - this->m_address_base) & this->m_address_mask) >> (Width + AddrShift)], this->m_flags); } @@ -37,6 +42,12 @@ template<int Width, int AddrShift> void handler_entry_write_memory<Width, AddrSh m_base[off] = (m_base[off] & ~mem_mask) | (data & mem_mask); } +template<int Width, int AddrShift> void handler_entry_write_memory<Width, AddrShift>::write_interruptible(offs_t offset, uX data, uX mem_mask) const +{ + offs_t off = ((offset - this->m_address_base) & this->m_address_mask) >> (Width + AddrShift); + m_base[off] = (m_base[off] & ~mem_mask) | (data & mem_mask); +} + template<int Width, int AddrShift> u16 handler_entry_write_memory<Width, AddrShift>::write_flags(offs_t offset, uX data, uX mem_mask) const { offs_t off = ((offset - this->m_address_base) & this->m_address_mask) >> (Width + AddrShift); @@ -54,6 +65,11 @@ template<> void handler_entry_write_memory<0, 0>::write(offs_t offset, u8 data, m_base[(offset - this->m_address_base) & this->m_address_mask] = data; } +template<> void handler_entry_write_memory<0, 0>::write_interruptible(offs_t offset, u8 data, u8 mem_mask) const +{ + m_base[(offset - this->m_address_base) & this->m_address_mask] = data; +} + template<> u16 handler_entry_write_memory<0, 0>::write_flags(offs_t offset, u8 data, u8 mem_mask) const { m_base[(offset - this->m_address_base) & this->m_address_mask] = data; @@ -74,12 +90,17 @@ template<int Width, int AddrShift> std::string handler_entry_write_memory<Width, -template<int Width, int AddrShift> typename emu::detail::handler_entry_size<Width>::uX handler_entry_read_memory_bank<Width, AddrShift>::read(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_memory_bank<Width, AddrShift>::read(offs_t offset, uX mem_mask) const { return static_cast<uX *>(m_bank.base())[((offset - this->m_address_base) & this->m_address_mask) >> (Width + AddrShift)]; } -template<int Width, int AddrShift> std::pair<typename emu::detail::handler_entry_size<Width>::uX, u16> handler_entry_read_memory_bank<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_memory_bank<Width, AddrShift>::read_interruptible(offs_t offset, uX mem_mask) const +{ + return static_cast<uX *>(m_bank.base())[((offset - this->m_address_base) & this->m_address_mask) >> (Width + AddrShift)]; +} + +template<int Width, int AddrShift> std::pair<emu::detail::handler_entry_size_t<Width>, u16> handler_entry_read_memory_bank<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const { return std::pair<uX, u16>(static_cast<uX *>(m_bank.base())[((offset - this->m_address_base) & this->m_address_mask) >> (Width + AddrShift)], this->m_flags); } @@ -106,6 +127,12 @@ template<int Width, int AddrShift> void handler_entry_write_memory_bank<Width, A static_cast<uX *>(m_bank.base())[off] = (static_cast<uX *>(m_bank.base())[off] & ~mem_mask) | (data & mem_mask); } +template<int Width, int AddrShift> void handler_entry_write_memory_bank<Width, AddrShift>::write_interruptible(offs_t offset, uX data, uX mem_mask) const +{ + offs_t off = ((offset - this->m_address_base) & this->m_address_mask) >> (Width + AddrShift); + static_cast<uX *>(m_bank.base())[off] = (static_cast<uX *>(m_bank.base())[off] & ~mem_mask) | (data & mem_mask); +} + template<int Width, int AddrShift> u16 handler_entry_write_memory_bank<Width, AddrShift>::write_flags(offs_t offset, uX data, uX mem_mask) const { offs_t off = ((offset - this->m_address_base) & this->m_address_mask) >> (Width + AddrShift); @@ -123,6 +150,11 @@ template<> void handler_entry_write_memory_bank<0, 0>::write(offs_t offset, u8 d static_cast<uX *>(m_bank.base())[(offset - this->m_address_base) & this->m_address_mask] = data; } +template<> void handler_entry_write_memory_bank<0, 0>::write_interruptible(offs_t offset, u8 data, u8 mem_mask) const +{ + static_cast<uX *>(m_bank.base())[(offset - this->m_address_base) & this->m_address_mask] = data; +} + template<> u16 handler_entry_write_memory_bank<0, 0>::write_flags(offs_t offset, u8 data, u8 mem_mask) const { static_cast<uX *>(m_bank.base())[(offset - this->m_address_base) & this->m_address_mask] = data; diff --git a/src/emu/emumem_hem.h b/src/emu/emumem_hem.h index a92661ca73f..d4c8c145860 100644 --- a/src/emu/emumem_hem.h +++ b/src/emu/emumem_hem.h @@ -12,12 +12,13 @@ template<int Width, int AddrShift> class handler_entry_read_memory : public handler_entry_read_address<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_read_memory(address_space *space, u16 flags, void *base) : handler_entry_read_address<Width, AddrShift>(space, flags), m_base(reinterpret_cast<uX *>(base)) {} ~handler_entry_read_memory() = default; uX read(offs_t offset, uX mem_mask) const override; + uX read_interruptible(offs_t offset, uX mem_mask) const override; std::pair<uX, u16> read_flags(offs_t offset, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; void *get_ptr(offs_t offset) const override; @@ -31,12 +32,13 @@ private: template<int Width, int AddrShift> class handler_entry_write_memory : public handler_entry_write_address<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_write_memory(address_space *space, u16 flags, void *base) : handler_entry_write_address<Width, AddrShift>(space, flags), m_base(reinterpret_cast<uX *>(base)) {} ~handler_entry_write_memory() = default; void write(offs_t offset, uX data, uX mem_mask) const override; + void write_interruptible(offs_t offset, uX data, uX mem_mask) const override; u16 write_flags(offs_t offset, uX data, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; void *get_ptr(offs_t offset) const override; @@ -55,12 +57,13 @@ private: template<int Width, int AddrShift> class handler_entry_read_memory_bank : public handler_entry_read_address<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_read_memory_bank(address_space *space, u16 flags, memory_bank &bank) : handler_entry_read_address<Width, AddrShift>(space, flags), m_bank(bank) {} ~handler_entry_read_memory_bank() = default; uX read(offs_t offset, uX mem_mask) const override; + uX read_interruptible(offs_t offset, uX mem_mask) const override; std::pair<uX, u16> read_flags(offs_t offset, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; void *get_ptr(offs_t offset) const override; @@ -74,12 +77,13 @@ private: template<int Width, int AddrShift> class handler_entry_write_memory_bank : public handler_entry_write_address<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_write_memory_bank(address_space *space, u16 flags, memory_bank &bank) : handler_entry_write_address<Width, AddrShift>(space, flags), m_bank(bank) {} ~handler_entry_write_memory_bank() = default; void write(offs_t offset, uX data, uX mem_mask) const override; + void write_interruptible(offs_t offset, uX data, uX mem_mask) const override; u16 write_flags(offs_t offset, uX data, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; void *get_ptr(offs_t offset) const override; diff --git a/src/emu/emumem_hep.h b/src/emu/emumem_hep.h index a98b44c267d..bc8616cea2b 100644 --- a/src/emu/emumem_hep.h +++ b/src/emu/emumem_hep.h @@ -8,9 +8,9 @@ template<int Width, int AddrShift> class handler_entry_read_passthrough : public handler_entry_read<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; - handler_entry_read_passthrough(address_space *space, emu::detail::memory_passthrough_handler_impl &mph) : handler_entry_read<Width, AddrShift>(space, handler_entry::F_PASSTHROUGH), m_mph(mph), m_next(nullptr) {} + handler_entry_read_passthrough(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, u32 prio) : handler_entry_read<Width, AddrShift>(space, handler_entry::f_pt(prio)), m_mph(mph), m_next(nullptr) {} ~handler_entry_read_passthrough(); virtual handler_entry_read_passthrough<Width, AddrShift> *instantiate(handler_entry_read<Width, AddrShift> *next) const = 0; @@ -23,15 +23,15 @@ protected: emu::detail::memory_passthrough_handler_impl &m_mph; handler_entry_read<Width, AddrShift> *m_next; - handler_entry_read_passthrough(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_read<Width, AddrShift> *next) : handler_entry_read<Width, AddrShift>(space, handler_entry::F_PASSTHROUGH), m_mph(mph), m_next(next) { next->ref(); mph.add_handler(this); } + handler_entry_read_passthrough(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, u32 prio, handler_entry_read<Width, AddrShift> *next) : handler_entry_read<Width, AddrShift>(space, handler_entry::f_pt(prio)), m_mph(mph), m_next(next) { next->ref(); mph.add_handler(this); } }; template<int Width, int AddrShift> class handler_entry_write_passthrough : public handler_entry_write<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; - handler_entry_write_passthrough(address_space *space, emu::detail::memory_passthrough_handler_impl &mph) : handler_entry_write<Width, AddrShift>(space, handler_entry::F_PASSTHROUGH), m_mph(mph), m_next(nullptr) {} + handler_entry_write_passthrough(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, u32 prio) : handler_entry_write<Width, AddrShift>(space, handler_entry::f_pt(prio)), m_mph(mph), m_next(nullptr) {} ~handler_entry_write_passthrough(); virtual handler_entry_write_passthrough<Width, AddrShift> *instantiate(handler_entry_write<Width, AddrShift> *next) const = 0; @@ -44,5 +44,5 @@ protected: emu::detail::memory_passthrough_handler_impl &m_mph; handler_entry_write<Width, AddrShift> *m_next; - handler_entry_write_passthrough(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_write<Width, AddrShift> *next) : handler_entry_write<Width, AddrShift>(space, handler_entry::F_PASSTHROUGH), m_mph(mph), m_next(next) { next->ref(); mph.add_handler(this); } + handler_entry_write_passthrough(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, u32 prio, handler_entry_write<Width, AddrShift> *next) : handler_entry_write<Width, AddrShift>(space, handler_entry::f_pt(prio)), m_mph(mph), m_next(next) { next->ref(); mph.add_handler(this); } }; diff --git a/src/emu/emumem_het.cpp b/src/emu/emumem_het.cpp index 05bf161fc7c..23349659a48 100644 --- a/src/emu/emumem_het.cpp +++ b/src/emu/emumem_het.cpp @@ -5,7 +5,7 @@ #include "emumem_hep.h" #include "emumem_het.h" -template<int Width, int AddrShift> typename emu::detail::handler_entry_size<Width>::uX handler_entry_read_tap<Width, AddrShift>::read(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_tap<Width, AddrShift>::read(offs_t offset, uX mem_mask) const { this->ref(); @@ -16,7 +16,18 @@ template<int Width, int AddrShift> typename emu::detail::handler_entry_size<Widt return data; } -template<int Width, int AddrShift> std::pair<typename emu::detail::handler_entry_size<Width>::uX, u16> handler_entry_read_tap<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_tap<Width, AddrShift>::read_interruptible(offs_t offset, uX mem_mask) const +{ + this->ref(); + + uX data = this->m_next->read_interruptible(offset, mem_mask); + m_tap(offset, data, mem_mask); + + this->unref(); + return data; +} + +template<int Width, int AddrShift> std::pair<emu::detail::handler_entry_size_t<Width>, u16> handler_entry_read_tap<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const { this->ref(); @@ -53,6 +64,16 @@ template<int Width, int AddrShift> void handler_entry_write_tap<Width, AddrShift this->unref(); } +template<int Width, int AddrShift> void handler_entry_write_tap<Width, AddrShift>::write_interruptible(offs_t offset, uX data, uX mem_mask) const +{ + this->ref(); + + m_tap(offset, data, mem_mask); + this->m_next->write_interruptible(offset, data, mem_mask); + + this->unref(); +} + template<int Width, int AddrShift> u16 handler_entry_write_tap<Width, AddrShift>::write_flags(offs_t offset, uX data, uX mem_mask) const { this->ref(); diff --git a/src/emu/emumem_het.h b/src/emu/emumem_het.h index 89aeebad867..97650c6cbe3 100644 --- a/src/emu/emumem_het.h +++ b/src/emu/emumem_het.h @@ -12,12 +12,13 @@ template<int Width, int AddrShift> class handler_entry_read_tap : public handler_entry_read_passthrough<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; - handler_entry_read_tap(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_read_passthrough<Width, AddrShift>(space, mph), m_name(name), m_tap(std::move(tap)) {} + handler_entry_read_tap(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_read_passthrough<Width, AddrShift>(space, mph, 4), m_name(name), m_tap(std::move(tap)) {} ~handler_entry_read_tap() = default; uX read(offs_t offset, uX mem_mask) const override; + uX read_interruptible(offs_t offset, uX mem_mask) const override; std::pair<uX, u16> read_flags(offs_t offset, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; @@ -29,18 +30,19 @@ protected: std::string m_name; std::function<void (offs_t offset, uX &data, uX mem_mask)> m_tap; - handler_entry_read_tap(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_read<Width, AddrShift> *next, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_read_passthrough<Width, AddrShift>(space, mph, next), m_name(name), m_tap(tap) {} + handler_entry_read_tap(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_read<Width, AddrShift> *next, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_read_passthrough<Width, AddrShift>(space, mph, 4, next), m_name(name), m_tap(tap) {} }; template<int Width, int AddrShift> class handler_entry_write_tap : public handler_entry_write_passthrough<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; - handler_entry_write_tap(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_write_passthrough<Width, AddrShift>(space, mph), m_name(name), m_tap(std::move(tap)) {} + handler_entry_write_tap(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_write_passthrough<Width, AddrShift>(space, mph, 4), m_name(name), m_tap(std::move(tap)) {} ~handler_entry_write_tap() = default; void write(offs_t offset, uX data, uX mem_mask) const override; + void write_interruptible(offs_t offset, uX data, uX mem_mask) const override; u16 write_flags(offs_t offset, uX data, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; @@ -52,7 +54,7 @@ protected: std::string m_name; std::function<void (offs_t offset, uX &data, uX mem_mask)> m_tap; - handler_entry_write_tap(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_write<Width, AddrShift> *next, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_write_passthrough<Width, AddrShift>(space, mph, next), m_name(name), m_tap(tap) {} + handler_entry_write_tap(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_write<Width, AddrShift> *next, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap) : handler_entry_write_passthrough<Width, AddrShift>(space, mph, 4, next), m_name(name), m_tap(tap) {} }; #endif // MAME_EMU_EMUMEM_HET_H diff --git a/src/emu/emumem_heu.cpp b/src/emu/emumem_heu.cpp index a5affb6daaf..ada5d56d63a 100644 --- a/src/emu/emumem_heu.cpp +++ b/src/emu/emumem_heu.cpp @@ -75,7 +75,7 @@ template<int Width, int AddrShift> void handler_entry_read_units<Width, AddrShif } -template<int Width, int AddrShift> typename emu::detail::handler_entry_size<Width>::uX handler_entry_read_units<Width, AddrShift>::read(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_units<Width, AddrShift>::read(offs_t offset, uX mem_mask) const { this->ref(); @@ -104,7 +104,12 @@ template<int Width, int AddrShift> typename emu::detail::handler_entry_size<Widt return result; } -template<int Width, int AddrShift> std::pair<typename emu::detail::handler_entry_size<Width>::uX, u16> handler_entry_read_units<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_units<Width, AddrShift>::read_interruptible(offs_t offset, uX mem_mask) const +{ + return read(offset, mem_mask); +} + +template<int Width, int AddrShift> std::pair<emu::detail::handler_entry_size_t<Width>, u16> handler_entry_read_units<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const { this->ref(); @@ -166,7 +171,7 @@ template<int Width, int AddrShift> u16 handler_entry_read_units<Width, AddrShift return flags; } -template<int Width, int AddrShift> std::string handler_entry_read_units<Width, AddrShift>::m2r(typename emu::detail::handler_entry_size<Width>::uX mask) +template<int Width, int AddrShift> std::string handler_entry_read_units<Width, AddrShift>::m2r(emu::detail::handler_entry_size_t<Width> mask) { constexpr u32 mbits = 8*sizeof(uX); u32 start, end; @@ -285,6 +290,11 @@ template<int Width, int AddrShift> void handler_entry_write_units<Width, AddrShi this->unref(); } +template<int Width, int AddrShift> void handler_entry_write_units<Width, AddrShift>::write_interruptible(offs_t offset, uX data, uX mem_mask) const +{ + write(offset, data, mem_mask); +} + template<int Width, int AddrShift> u16 handler_entry_write_units<Width, AddrShift>::write_flags(offs_t offset, uX data, uX mem_mask) const { this->ref(); @@ -344,7 +354,7 @@ template<int Width, int AddrShift> u16 handler_entry_write_units<Width, AddrShif } -template<int Width, int AddrShift> std::string handler_entry_write_units<Width, AddrShift>::m2r(typename emu::detail::handler_entry_size<Width>::uX mask) +template<int Width, int AddrShift> std::string handler_entry_write_units<Width, AddrShift>::m2r(emu::detail::handler_entry_size_t<Width> mask) { constexpr u32 mbits = 8*sizeof(uX); u32 start, end; diff --git a/src/emu/emumem_heu.h b/src/emu/emumem_heu.h index 5ec0c5e4fcf..8573cc4e334 100644 --- a/src/emu/emumem_heu.h +++ b/src/emu/emumem_heu.h @@ -12,7 +12,7 @@ template<int Width, int AddrShift> class handler_entry_read_units : public handler_entry_read<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_read_units(const memory_units_descriptor<Width, AddrShift> &descriptor, u8 ukey, address_space *space); handler_entry_read_units(const memory_units_descriptor<Width, AddrShift> &descriptor, u8 ukey, const handler_entry_read_units *src); @@ -20,6 +20,7 @@ public: ~handler_entry_read_units(); uX read(offs_t offset, uX mem_mask) const override; + uX read_interruptible(offs_t offset, uX mem_mask) const override; std::pair<uX, u16> read_flags(offs_t offset, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; @@ -55,7 +56,7 @@ private: template<int Width, int AddrShift> class handler_entry_write_units : public handler_entry_write<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_write_units(const memory_units_descriptor<Width, AddrShift> &descriptor, u8 ukey, address_space *space); handler_entry_write_units(const memory_units_descriptor<Width, AddrShift> &descriptor, u8 ukey, const handler_entry_write_units<Width, AddrShift> *src); @@ -63,6 +64,7 @@ public: ~handler_entry_write_units(); void write(offs_t offset, uX data, uX mem_mask) const override; + void write_interruptible(offs_t offset, uX data, uX mem_mask) const override; u16 write_flags(offs_t offset, uX data, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; diff --git a/src/emu/emumem_heun.cpp b/src/emu/emumem_heun.cpp index 6f6cab1d68d..5157c2c35df 100644 --- a/src/emu/emumem_heun.cpp +++ b/src/emu/emumem_heun.cpp @@ -5,7 +5,7 @@ #include "emumem_hea.h" #include "emumem_heun.h" -template<int Width, int AddrShift> typename emu::detail::handler_entry_size<Width>::uX handler_entry_read_unmapped<Width, AddrShift>::read(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_unmapped<Width, AddrShift>::read(offs_t offset, uX mem_mask) const { if (this->m_space->log_unmap() && !this->m_space->m_manager.machine().side_effects_disabled()) this->m_space->device().logerror(this->m_space->is_octal() @@ -17,7 +17,19 @@ template<int Width, int AddrShift> typename emu::detail::handler_entry_size<Widt return this->m_space->unmap(); } -template<int Width, int AddrShift> std::pair<typename emu::detail::handler_entry_size<Width>::uX, u16> handler_entry_read_unmapped<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_unmapped<Width, AddrShift>::read_interruptible(offs_t offset, uX mem_mask) const +{ + if (this->m_space->log_unmap() && !this->m_space->m_manager.machine().side_effects_disabled()) + this->m_space->device().logerror(this->m_space->is_octal() + ? "%s: unmapped %s memory read from %0*o & %0*o\n" + : "%s: unmapped %s memory read from %0*X & %0*X\n", + this->m_space->m_manager.machine().describe_context(), this->m_space->name(), + this->m_space->addrchars(), offset, + 2 << Width, mem_mask); + return this->m_space->unmap(); +} + +template<int Width, int AddrShift> std::pair<emu::detail::handler_entry_size_t<Width>, u16> handler_entry_read_unmapped<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const { if (this->m_space->log_unmap() && !this->m_space->m_manager.machine().side_effects_disabled()) this->m_space->device().logerror(this->m_space->is_octal() @@ -59,6 +71,18 @@ template<int Width, int AddrShift> void handler_entry_write_unmapped<Width, Addr 2 << Width, mem_mask); } +template<int Width, int AddrShift> void handler_entry_write_unmapped<Width, AddrShift>::write_interruptible(offs_t offset, uX data, uX mem_mask)const +{ + if (this->m_space->log_unmap() && !this->m_space->m_manager.machine().side_effects_disabled()) + this->m_space->device().logerror(this->m_space->is_octal() + ? "%s: unmapped %s memory write to %0*o = %0*o & %0*o\n" + : "%s: unmapped %s memory write to %0*X = %0*X & %0*X\n", + this->m_space->m_manager.machine().describe_context(), this->m_space->name(), + this->m_space->addrchars(), offset, + 2 << Width, data, + 2 << Width, mem_mask); +} + template<int Width, int AddrShift> u16 handler_entry_write_unmapped<Width, AddrShift>::write_flags(offs_t offset, uX data, uX mem_mask)const { if (this->m_space->log_unmap() && !this->m_space->m_manager.machine().side_effects_disabled()) @@ -92,12 +116,17 @@ template<int Width, int AddrShift> std::string handler_entry_write_unmapped<Widt -template<int Width, int AddrShift> typename emu::detail::handler_entry_size<Width>::uX handler_entry_read_nop<Width, AddrShift>::read(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_nop<Width, AddrShift>::read(offs_t offset, uX mem_mask) const { return this->m_space->unmap(); } -template<int Width, int AddrShift> std::pair<typename emu::detail::handler_entry_size<Width>::uX, u16> handler_entry_read_nop<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_nop<Width, AddrShift>::read_interruptible(offs_t offset, uX mem_mask) const +{ + return this->m_space->unmap(); +} + +template<int Width, int AddrShift> std::pair<emu::detail::handler_entry_size_t<Width>, u16> handler_entry_read_nop<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const { return std::pair<uX, u16>(this->m_space->unmap(), this->m_flags); } @@ -117,6 +146,10 @@ template<int Width, int AddrShift> void handler_entry_write_nop<Width, AddrShift { } +template<int Width, int AddrShift> void handler_entry_write_nop<Width, AddrShift>::write_interruptible(offs_t offset, uX data, uX mem_mask) const +{ +} + template<int Width, int AddrShift> u16 handler_entry_write_nop<Width, AddrShift>::write_flags(offs_t offset, uX data, uX mem_mask) const { return this->m_flags; diff --git a/src/emu/emumem_heun.h b/src/emu/emumem_heun.h index 57088774520..69a97e84f37 100644 --- a/src/emu/emumem_heun.h +++ b/src/emu/emumem_heun.h @@ -12,12 +12,13 @@ template<int Width, int AddrShift> class handler_entry_read_unmapped : public handler_entry_read<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_read_unmapped(address_space *space, u16 flags) : handler_entry_read<Width, AddrShift>(space, handler_entry::F_UNMAP | flags) {} ~handler_entry_read_unmapped() = default; uX read(offs_t offset, uX mem_mask) const override; + uX read_interruptible(offs_t offset, uX mem_mask) const override; std::pair<uX, u16> read_flags(offs_t offset, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; @@ -27,12 +28,13 @@ public: template<int Width, int AddrShift> class handler_entry_write_unmapped : public handler_entry_write<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_write_unmapped(address_space *space, u16 flags) : handler_entry_write<Width, AddrShift>(space, handler_entry::F_UNMAP | flags) {} ~handler_entry_write_unmapped() = default; void write(offs_t offset, uX data, uX mem_mask) const override; + void write_interruptible(offs_t offset, uX data, uX mem_mask) const override; u16 write_flags(offs_t offset, uX data, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; @@ -48,12 +50,13 @@ public: template<int Width, int AddrShift> class handler_entry_read_nop : public handler_entry_read<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_read_nop(address_space *space, u16 flags) : handler_entry_read<Width, AddrShift>(space, flags) {} ~handler_entry_read_nop() = default; uX read(offs_t offset, uX mem_mask) const override; + uX read_interruptible(offs_t offset, uX mem_mask) const override; std::pair<uX, u16> read_flags(offs_t offset, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; @@ -63,12 +66,13 @@ public: template<int Width, int AddrShift> class handler_entry_write_nop : public handler_entry_write<Width, AddrShift> { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; handler_entry_write_nop(address_space *space, u16 flags) : handler_entry_write<Width, AddrShift>(space, flags) {} ~handler_entry_write_nop() = default; void write(offs_t offset, uX data, uX mem_mask) const override; + void write_interruptible(offs_t offset, uX data, uX mem_mask) const override; u16 write_flags(offs_t offset, uX data, uX mem_mask) const override; u16 lookup_flags(offs_t offset, uX mem_mask) const override; diff --git a/src/emu/emumem_hws.cpp b/src/emu/emumem_hws.cpp new file mode 100644 index 00000000000..9aae20d9f4c --- /dev/null +++ b/src/emu/emumem_hws.cpp @@ -0,0 +1,311 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert + +#include "emu.h" +#include "emumem_hep.h" +#include "emumem_hws.h" + +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_before_time<Width, AddrShift>::read(offs_t offset, uX mem_mask) const +{ + return this->m_next->read(offset, mem_mask); +} + +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_before_time<Width, AddrShift>::read_interruptible(offs_t offset, uX mem_mask) const +{ + u64 tc = m_cpu.total_cycles(); + u64 ac = m_ws(offset, tc); + + if(ac < tc) + ac = tc; + + if(m_cpu.access_before_time(ac, tc)) + return 0; + + return this->m_next->read_interruptible(offset, mem_mask); +} + +template<int Width, int AddrShift> std::pair<emu::detail::handler_entry_size_t<Width>, u16> handler_entry_read_before_time<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const +{ + return this->m_next->read_flags(offset, mem_mask); +} + +template<int Width, int AddrShift> u16 handler_entry_read_before_time<Width, AddrShift>::lookup_flags(offs_t offset, uX mem_mask) const +{ + return this->m_next->lookup_flags(offset, mem_mask); +} + +template<int Width, int AddrShift> std::string handler_entry_read_before_time<Width, AddrShift>::name() const +{ + return util::string_format("(bt %s) %s", m_ws.name(), this->m_next->name()); +} + +template<int Width, int AddrShift> handler_entry_read_before_time<Width, AddrShift> *handler_entry_read_before_time<Width, AddrShift>::instantiate(handler_entry_read<Width, AddrShift> *next) const +{ + return new handler_entry_read_before_time<Width, AddrShift>(this->m_space, this->m_mph, next, m_ws); +} + + +template<int Width, int AddrShift> void handler_entry_write_before_time<Width, AddrShift>::write(offs_t offset, uX data, uX mem_mask) const +{ + this->m_next->write(offset, data, mem_mask); +} + +template<int Width, int AddrShift> void handler_entry_write_before_time<Width, AddrShift>::write_interruptible(offs_t offset, uX data, uX mem_mask) const +{ + u64 tc = m_cpu.total_cycles(); + u64 ac = m_ws(offset, tc); + + if(ac < tc) + ac = tc; + + if(m_cpu.access_before_time(ac, tc)) + return; + this->m_next->write_interruptible(offset, data, mem_mask); +} + +template<int Width, int AddrShift> u16 handler_entry_write_before_time<Width, AddrShift>::write_flags(offs_t offset, uX data, uX mem_mask) const +{ + return this->m_next->write_flags(offset, data, mem_mask); +} + +template<int Width, int AddrShift> u16 handler_entry_write_before_time<Width, AddrShift>::lookup_flags(offs_t offset, uX mem_mask) const +{ + return this->m_next->lookup_flags(offset, mem_mask); +} + +template<int Width, int AddrShift> std::string handler_entry_write_before_time<Width, AddrShift>::name() const +{ + return util::string_format("(bt %s) %s", m_ws.name(), this->m_next->name()); +} + + +template<int Width, int AddrShift> handler_entry_write_before_time<Width, AddrShift> *handler_entry_write_before_time<Width, AddrShift>::instantiate(handler_entry_write<Width, AddrShift> *next) const +{ + return new handler_entry_write_before_time<Width, AddrShift>(this->m_space, this->m_mph, next, m_ws); +} + + + +template class handler_entry_read_before_time<0, 1>; +template class handler_entry_read_before_time<0, 0>; +template class handler_entry_read_before_time<1, 3>; +template class handler_entry_read_before_time<1, 0>; +template class handler_entry_read_before_time<1, -1>; +template class handler_entry_read_before_time<2, 3>; +template class handler_entry_read_before_time<2, 0>; +template class handler_entry_read_before_time<2, -1>; +template class handler_entry_read_before_time<2, -2>; +template class handler_entry_read_before_time<3, 0>; +template class handler_entry_read_before_time<3, -1>; +template class handler_entry_read_before_time<3, -2>; +template class handler_entry_read_before_time<3, -3>; + +template class handler_entry_write_before_time<0, 1>; +template class handler_entry_write_before_time<0, 0>; +template class handler_entry_write_before_time<1, 3>; +template class handler_entry_write_before_time<1, 0>; +template class handler_entry_write_before_time<1, -1>; +template class handler_entry_write_before_time<2, 3>; +template class handler_entry_write_before_time<2, 0>; +template class handler_entry_write_before_time<2, -1>; +template class handler_entry_write_before_time<2, -2>; +template class handler_entry_write_before_time<3, 0>; +template class handler_entry_write_before_time<3, -1>; +template class handler_entry_write_before_time<3, -2>; +template class handler_entry_write_before_time<3, -3>; + + + +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_before_delay<Width, AddrShift>::read(offs_t offset, uX mem_mask) const +{ + return this->m_next->read(offset, mem_mask); +} + +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_before_delay<Width, AddrShift>::read_interruptible(offs_t offset, uX mem_mask) const +{ + if(m_cpu.access_before_delay(m_ws(offset), this)) + return 0; + + return this->m_next->read_interruptible(offset, mem_mask); +} + +template<int Width, int AddrShift> std::pair<emu::detail::handler_entry_size_t<Width>, u16> handler_entry_read_before_delay<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const +{ + return this->m_next->read_flags(offset, mem_mask); +} + +template<int Width, int AddrShift> u16 handler_entry_read_before_delay<Width, AddrShift>::lookup_flags(offs_t offset, uX mem_mask) const +{ + return this->m_next->lookup_flags(offset, mem_mask); +} + +template<int Width, int AddrShift> std::string handler_entry_read_before_delay<Width, AddrShift>::name() const +{ + return util::string_format("(bd %s) %s", m_ws.name(), this->m_next->name()); +} + +template<int Width, int AddrShift> handler_entry_read_before_delay<Width, AddrShift> *handler_entry_read_before_delay<Width, AddrShift>::instantiate(handler_entry_read<Width, AddrShift> *next) const +{ + return new handler_entry_read_before_delay<Width, AddrShift>(this->m_space, this->m_mph, next, m_ws); +} + + +template<int Width, int AddrShift> void handler_entry_write_before_delay<Width, AddrShift>::write(offs_t offset, uX data, uX mem_mask) const +{ + this->m_next->write(offset, data, mem_mask); +} + +template<int Width, int AddrShift> void handler_entry_write_before_delay<Width, AddrShift>::write_interruptible(offs_t offset, uX data, uX mem_mask) const +{ + if(m_cpu.access_before_delay(m_ws(offset), this)) + return; + this->m_next->write_interruptible(offset, data, mem_mask); +} + +template<int Width, int AddrShift> u16 handler_entry_write_before_delay<Width, AddrShift>::write_flags(offs_t offset, uX data, uX mem_mask) const +{ + return this->m_next->write_flags(offset, data, mem_mask); +} + +template<int Width, int AddrShift> u16 handler_entry_write_before_delay<Width, AddrShift>::lookup_flags(offs_t offset, uX mem_mask) const +{ + return this->m_next->lookup_flags(offset, mem_mask); +} + +template<int Width, int AddrShift> std::string handler_entry_write_before_delay<Width, AddrShift>::name() const +{ + return util::string_format("(bd %s) %s", m_ws.name(), this->m_next->name()); +} + + +template<int Width, int AddrShift> handler_entry_write_before_delay<Width, AddrShift> *handler_entry_write_before_delay<Width, AddrShift>::instantiate(handler_entry_write<Width, AddrShift> *next) const +{ + return new handler_entry_write_before_delay<Width, AddrShift>(this->m_space, this->m_mph, next, m_ws); +} + + + +template class handler_entry_read_before_delay<0, 1>; +template class handler_entry_read_before_delay<0, 0>; +template class handler_entry_read_before_delay<1, 3>; +template class handler_entry_read_before_delay<1, 0>; +template class handler_entry_read_before_delay<1, -1>; +template class handler_entry_read_before_delay<2, 3>; +template class handler_entry_read_before_delay<2, 0>; +template class handler_entry_read_before_delay<2, -1>; +template class handler_entry_read_before_delay<2, -2>; +template class handler_entry_read_before_delay<3, 0>; +template class handler_entry_read_before_delay<3, -1>; +template class handler_entry_read_before_delay<3, -2>; +template class handler_entry_read_before_delay<3, -3>; + +template class handler_entry_write_before_delay<0, 1>; +template class handler_entry_write_before_delay<0, 0>; +template class handler_entry_write_before_delay<1, 3>; +template class handler_entry_write_before_delay<1, 0>; +template class handler_entry_write_before_delay<1, -1>; +template class handler_entry_write_before_delay<2, 3>; +template class handler_entry_write_before_delay<2, 0>; +template class handler_entry_write_before_delay<2, -1>; +template class handler_entry_write_before_delay<2, -2>; +template class handler_entry_write_before_delay<3, 0>; +template class handler_entry_write_before_delay<3, -1>; +template class handler_entry_write_before_delay<3, -2>; +template class handler_entry_write_before_delay<3, -3>; + + + +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_after_delay<Width, AddrShift>::read(offs_t offset, uX mem_mask) const +{ + return this->m_next->read(offset, mem_mask); +} + +template<int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> handler_entry_read_after_delay<Width, AddrShift>::read_interruptible(offs_t offset, uX mem_mask) const +{ + auto r = this->m_next->read_interruptible(offset, mem_mask); + m_cpu.access_after_delay(m_ws(offset)); + return r; +} + +template<int Width, int AddrShift> std::pair<emu::detail::handler_entry_size_t<Width>, u16> handler_entry_read_after_delay<Width, AddrShift>::read_flags(offs_t offset, uX mem_mask) const +{ + return this->m_next->read_flags(offset, mem_mask); +} + +template<int Width, int AddrShift> u16 handler_entry_read_after_delay<Width, AddrShift>::lookup_flags(offs_t offset, uX mem_mask) const +{ + return this->m_next->lookup_flags(offset, mem_mask); +} + +template<int Width, int AddrShift> std::string handler_entry_read_after_delay<Width, AddrShift>::name() const +{ + return util::string_format("(ad %s) %s", m_ws.name(), this->m_next->name()); +} + +template<int Width, int AddrShift> handler_entry_read_after_delay<Width, AddrShift> *handler_entry_read_after_delay<Width, AddrShift>::instantiate(handler_entry_read<Width, AddrShift> *next) const +{ + return new handler_entry_read_after_delay<Width, AddrShift>(this->m_space, this->m_mph, next, m_ws); +} + + +template<int Width, int AddrShift> void handler_entry_write_after_delay<Width, AddrShift>::write(offs_t offset, uX data, uX mem_mask) const +{ + this->m_next->write(offset, data, mem_mask); +} + +template<int Width, int AddrShift> void handler_entry_write_after_delay<Width, AddrShift>::write_interruptible(offs_t offset, uX data, uX mem_mask) const +{ + this->m_next->write_interruptible(offset, data, mem_mask); + m_cpu.access_after_delay(m_ws(offset)); +} + +template<int Width, int AddrShift> u16 handler_entry_write_after_delay<Width, AddrShift>::write_flags(offs_t offset, uX data, uX mem_mask) const +{ + return this->m_next->write_flags(offset, data, mem_mask); +} + +template<int Width, int AddrShift> u16 handler_entry_write_after_delay<Width, AddrShift>::lookup_flags(offs_t offset, uX mem_mask) const +{ + return this->m_next->lookup_flags(offset, mem_mask); +} + +template<int Width, int AddrShift> std::string handler_entry_write_after_delay<Width, AddrShift>::name() const +{ + return util::string_format("(ad %s) %s", m_ws.name(), this->m_next->name()); +} + + +template<int Width, int AddrShift> handler_entry_write_after_delay<Width, AddrShift> *handler_entry_write_after_delay<Width, AddrShift>::instantiate(handler_entry_write<Width, AddrShift> *next) const +{ + return new handler_entry_write_after_delay<Width, AddrShift>(this->m_space, this->m_mph, next, m_ws); +} + + + +template class handler_entry_read_after_delay<0, 1>; +template class handler_entry_read_after_delay<0, 0>; +template class handler_entry_read_after_delay<1, 3>; +template class handler_entry_read_after_delay<1, 0>; +template class handler_entry_read_after_delay<1, -1>; +template class handler_entry_read_after_delay<2, 3>; +template class handler_entry_read_after_delay<2, 0>; +template class handler_entry_read_after_delay<2, -1>; +template class handler_entry_read_after_delay<2, -2>; +template class handler_entry_read_after_delay<3, 0>; +template class handler_entry_read_after_delay<3, -1>; +template class handler_entry_read_after_delay<3, -2>; +template class handler_entry_read_after_delay<3, -3>; + +template class handler_entry_write_after_delay<0, 1>; +template class handler_entry_write_after_delay<0, 0>; +template class handler_entry_write_after_delay<1, 3>; +template class handler_entry_write_after_delay<1, 0>; +template class handler_entry_write_after_delay<1, -1>; +template class handler_entry_write_after_delay<2, 3>; +template class handler_entry_write_after_delay<2, 0>; +template class handler_entry_write_after_delay<2, -1>; +template class handler_entry_write_after_delay<2, -2>; +template class handler_entry_write_after_delay<3, 0>; +template class handler_entry_write_after_delay<3, -1>; +template class handler_entry_write_after_delay<3, -2>; +template class handler_entry_write_after_delay<3, -3>; diff --git a/src/emu/emumem_hws.h b/src/emu/emumem_hws.h new file mode 100644 index 00000000000..baaad6c7a07 --- /dev/null +++ b/src/emu/emumem_hws.h @@ -0,0 +1,162 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +#ifndef MAME_EMU_EMUMEM_HWS_H +#define MAME_EMU_EMUMEM_HWS_H + +#pragma once + +// handler_entry_read_before_time/handler_entry_write_before_time +// handler_entry_read_before_delay/handler_entry_write_before_delay +// handler_entry_read_after_delay/handler_entry_write_after_delay + +// handlers which handle the different wait state cases + +template<int Width, int AddrShift> class handler_entry_read_before_time : public handler_entry_read_passthrough<Width, AddrShift> +{ +public: + using uX = emu::detail::handler_entry_size_t<Width>; + + handler_entry_read_before_time(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, const ws_time_delegate &ws) : handler_entry_read_passthrough<Width, AddrShift>(space, mph, 13), m_ws(ws), m_cpu(downcast<cpu_device &>(space->device())) {} + ~handler_entry_read_before_time() = default; + + uX read(offs_t offset, uX mem_mask) const override; + uX read_interruptible(offs_t offset, uX mem_mask) const override; + std::pair<uX, u16> read_flags(offs_t offset, uX mem_mask) const override; + u16 lookup_flags(offs_t offset, uX mem_mask) const override; + + std::string name() const override; + + handler_entry_read_before_time<Width, AddrShift> *instantiate(handler_entry_read<Width, AddrShift> *next) const override; + +protected: + ws_time_delegate m_ws; + cpu_device &m_cpu; + + handler_entry_read_before_time(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_read<Width, AddrShift> *next, const ws_time_delegate &ws) : handler_entry_read_passthrough<Width, AddrShift>(space, mph, 13, next), m_ws(ws), m_cpu(downcast<cpu_device &>(space->device())) {} +}; + +template<int Width, int AddrShift> class handler_entry_write_before_time : public handler_entry_write_passthrough<Width, AddrShift> +{ +public: + using uX = emu::detail::handler_entry_size_t<Width>; + + handler_entry_write_before_time(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, const ws_time_delegate &ws) : handler_entry_write_passthrough<Width, AddrShift>(space, mph, 13), m_ws(ws), m_cpu(downcast<cpu_device &>(space->device())) {} + ~handler_entry_write_before_time() = default; + + void write(offs_t offset, uX data, uX mem_mask) const override; + void write_interruptible(offs_t offset, uX data, uX mem_mask) const override; + u16 write_flags(offs_t offset, uX data, uX mem_mask) const override; + u16 lookup_flags(offs_t offset, uX mem_mask) const override; + + std::string name() const override; + + handler_entry_write_before_time<Width, AddrShift> *instantiate(handler_entry_write<Width, AddrShift> *next) const override; + +protected: + ws_time_delegate m_ws; + cpu_device &m_cpu; + + handler_entry_write_before_time(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_write<Width, AddrShift> *next, const ws_time_delegate &ws) : handler_entry_write_passthrough<Width, AddrShift>(space, mph, 13, next), m_ws(ws), m_cpu(downcast<cpu_device &>(space->device())) {} +}; + + + +template<int Width, int AddrShift> class handler_entry_read_before_delay : public handler_entry_read_passthrough<Width, AddrShift> +{ +public: + using uX = emu::detail::handler_entry_size_t<Width>; + + handler_entry_read_before_delay(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, const ws_delay_delegate &ws) : handler_entry_read_passthrough<Width, AddrShift>(space, mph, 13), m_ws(ws), m_cpu(downcast<cpu_device &>(space->device())) {} + ~handler_entry_read_before_delay() = default; + + uX read(offs_t offset, uX mem_mask) const override; + uX read_interruptible(offs_t offset, uX mem_mask) const override; + std::pair<uX, u16> read_flags(offs_t offset, uX mem_mask) const override; + u16 lookup_flags(offs_t offset, uX mem_mask) const override; + + std::string name() const override; + + handler_entry_read_before_delay<Width, AddrShift> *instantiate(handler_entry_read<Width, AddrShift> *next) const override; + +protected: + ws_delay_delegate m_ws; + cpu_device &m_cpu; + + handler_entry_read_before_delay(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_read<Width, AddrShift> *next, const ws_delay_delegate &ws) : handler_entry_read_passthrough<Width, AddrShift>(space, mph, 13, next), m_ws(ws), m_cpu(downcast<cpu_device &>(space->device())) {} +}; + +template<int Width, int AddrShift> class handler_entry_write_before_delay : public handler_entry_write_passthrough<Width, AddrShift> +{ +public: + using uX = emu::detail::handler_entry_size_t<Width>; + + handler_entry_write_before_delay(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, const ws_delay_delegate &ws) : handler_entry_write_passthrough<Width, AddrShift>(space, mph, 11), m_ws(ws), m_cpu(downcast<cpu_device &>(space->device())) {} + ~handler_entry_write_before_delay() = default; + + void write(offs_t offset, uX data, uX mem_mask) const override; + void write_interruptible(offs_t offset, uX data, uX mem_mask) const override; + u16 write_flags(offs_t offset, uX data, uX mem_mask) const override; + u16 lookup_flags(offs_t offset, uX mem_mask) const override; + + std::string name() const override; + + handler_entry_write_before_delay<Width, AddrShift> *instantiate(handler_entry_write<Width, AddrShift> *next) const override; + +protected: + ws_delay_delegate m_ws; + cpu_device &m_cpu; + + handler_entry_write_before_delay(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_write<Width, AddrShift> *next, const ws_delay_delegate &ws) : handler_entry_write_passthrough<Width, AddrShift>(space, mph, 11, next), m_ws(ws), m_cpu(downcast<cpu_device &>(space->device())) {} +}; + + + +template<int Width, int AddrShift> class handler_entry_read_after_delay : public handler_entry_read_passthrough<Width, AddrShift> +{ +public: + using uX = emu::detail::handler_entry_size_t<Width>; + + handler_entry_read_after_delay(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, const ws_delay_delegate &ws) : handler_entry_read_passthrough<Width, AddrShift>(space, mph, 9), m_ws(ws), m_cpu(downcast<cpu_device &>(space->device())) {} + ~handler_entry_read_after_delay() = default; + + uX read(offs_t offset, uX mem_mask) const override; + uX read_interruptible(offs_t offset, uX mem_mask) const override; + std::pair<uX, u16> read_flags(offs_t offset, uX mem_mask) const override; + u16 lookup_flags(offs_t offset, uX mem_mask) const override; + + std::string name() const override; + + handler_entry_read_after_delay<Width, AddrShift> *instantiate(handler_entry_read<Width, AddrShift> *next) const override; + +protected: + ws_delay_delegate m_ws; + cpu_device &m_cpu; + + handler_entry_read_after_delay(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_read<Width, AddrShift> *next, const ws_delay_delegate &ws) : handler_entry_read_passthrough<Width, AddrShift>(space, mph, 9, next), m_ws(ws), m_cpu(downcast<cpu_device &>(space->device())) {} +}; + +template<int Width, int AddrShift> class handler_entry_write_after_delay : public handler_entry_write_passthrough<Width, AddrShift> +{ +public: + using uX = emu::detail::handler_entry_size_t<Width>; + + handler_entry_write_after_delay(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, const ws_delay_delegate &ws) : handler_entry_write_passthrough<Width, AddrShift>(space, mph, 9), m_ws(ws), m_cpu(downcast<cpu_device &>(space->device())) {} + ~handler_entry_write_after_delay() = default; + + void write(offs_t offset, uX data, uX mem_mask) const override; + void write_interruptible(offs_t offset, uX data, uX mem_mask) const override; + u16 write_flags(offs_t offset, uX data, uX mem_mask) const override; + u16 lookup_flags(offs_t offset, uX mem_mask) const override; + + std::string name() const override; + + handler_entry_write_after_delay<Width, AddrShift> *instantiate(handler_entry_write<Width, AddrShift> *next) const override; + +protected: + ws_delay_delegate m_ws; + cpu_device &m_cpu; + + handler_entry_write_after_delay(address_space *space, emu::detail::memory_passthrough_handler_impl &mph, handler_entry_write<Width, AddrShift> *next, const ws_delay_delegate &ws) : handler_entry_write_passthrough<Width, AddrShift>(space, mph, 9, next), m_ws(ws), m_cpu(downcast<cpu_device &>(space->device())) {} +}; + +#endif // MAME_EMU_EMUMEM_HWS_H diff --git a/src/emu/emumem_mud.cpp b/src/emu/emumem_mud.cpp index b8fed565eea..4c52b5a1301 100644 --- a/src/emu/emumem_mud.cpp +++ b/src/emu/emumem_mud.cpp @@ -35,7 +35,7 @@ template<> u8 mask_to_ukey<u64>(u64 mask) (mask & 0x00000000000000ff ? 0x01 : 0x00); } -template<int Width, int AddrShift> memory_units_descriptor<Width, AddrShift>::memory_units_descriptor(u8 access_width, endianness_t access_endian, handler_entry *handler, offs_t addrstart, offs_t addrend, offs_t mask, typename emu::detail::handler_entry_size<Width>::uX unitmask, int cswidth) : m_handler(handler), m_access_width(access_width), m_access_endian(access_endian) +template<int Width, int AddrShift> memory_units_descriptor<Width, AddrShift>::memory_units_descriptor(u8 access_width, endianness_t access_endian, handler_entry *handler, offs_t addrstart, offs_t addrend, offs_t mask, emu::detail::handler_entry_size_t<Width> unitmask, int cswidth) : m_handler(handler), m_access_width(access_width), m_access_endian(access_endian) { u32 bits_per_access = 8 << access_width; constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? make_bitmask<u32>(Width + AddrShift) : 0; @@ -86,7 +86,7 @@ template<int Width, int AddrShift> memory_units_descriptor<Width, AddrShift>::me generate(m_keymap[i], unitmask, umasks[i], cswidth, bits_per_access, base_shift, shift, active_count); } -template<int Width, int AddrShift> void memory_units_descriptor<Width, AddrShift>::generate(u8 ukey, typename emu::detail::handler_entry_size<Width>::uX gumask, typename emu::detail::handler_entry_size<Width>::uX umask, u32 cswidth, u32 bits_per_access, u8 base_shift, s8 shift, u32 active_count) +template<int Width, int AddrShift> void memory_units_descriptor<Width, AddrShift>::generate(u8 ukey, emu::detail::handler_entry_size_t<Width> gumask, emu::detail::handler_entry_size_t<Width> umask, u32 cswidth, u32 bits_per_access, u8 base_shift, s8 shift, u32 active_count) { auto &entries = m_entries_for_key[ukey]; diff --git a/src/emu/emumem_mud.h b/src/emu/emumem_mud.h index 12c8cf92eb5..4a8b6509aa0 100644 --- a/src/emu/emumem_mud.h +++ b/src/emu/emumem_mud.h @@ -5,7 +5,7 @@ template<int Width, int AddrShift> class memory_units_descriptor { public: - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; struct entry { uX m_amask; diff --git a/src/emu/emumem_mview.cpp b/src/emu/emumem_mview.cpp index becf9fcf7d8..2456cadc7f9 100644 --- a/src/emu/emumem_mview.cpp +++ b/src/emu/emumem_mview.cpp @@ -25,6 +25,7 @@ #include "emumem_hedw.h" #include "emumem_hep.h" #include "emumem_het.h" +#include "emumem_hws.h" #define VERBOSE 0 @@ -37,58 +38,7 @@ template <typename Format, typename... Params> static void VPRINTF(Format &&fmt, template <typename Format, typename... Params> static void VPRINTF(Format &&, Params &&...) {} #endif -namespace { - -template <typename Delegate> struct handler_width; -template <> struct handler_width<read8_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<read8m_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<read8s_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<read8sm_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<read8mo_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<read8smo_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<write8_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<write8m_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<write8s_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<write8sm_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<write8mo_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<write8smo_delegate> { static constexpr int value = 0; }; -template <> struct handler_width<read16_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<read16m_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<read16s_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<read16sm_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<read16mo_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<read16smo_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<write16_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<write16m_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<write16s_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<write16sm_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<write16mo_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<write16smo_delegate> { static constexpr int value = 1; }; -template <> struct handler_width<read32_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<read32m_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<read32s_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<read32sm_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<read32mo_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<read32smo_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<write32_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<write32m_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<write32s_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<write32sm_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<write32mo_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<write32smo_delegate> { static constexpr int value = 2; }; -template <> struct handler_width<read64_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<read64m_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<read64s_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<read64sm_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<read64mo_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<read64smo_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<write64_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<write64m_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<write64s_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<write64sm_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<write64mo_delegate> { static constexpr int value = 3; }; -template <> struct handler_width<write64smo_delegate> { static constexpr int value = 3; }; -} // anonymous namespace +using emu::detail::handler_width_v; address_map_entry &memory_view::memory_view_entry::operator()(offs_t start, offs_t end) { @@ -98,7 +48,7 @@ address_map_entry &memory_view::memory_view_entry::operator()(offs_t start, offs template<int Level, int Width, int AddrShift> class memory_view_entry_specific : public memory_view::memory_view_entry { - using uX = typename emu::detail::handler_entry_size<Width>::uX; + using uX = emu::detail::handler_entry_size_t<Width>; using NativeType = uX; // constants describing the native size @@ -137,156 +87,119 @@ public: virtual void install_readwrite_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, std::string rtag, std::string wtag) override; virtual void install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_constructor &map, u64 unitmask, int cswidth, u16 flags) override; + void install_read_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) override; + void install_read_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) override; + void install_read_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) override; + + void install_write_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) override; + void install_write_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) override; + void install_write_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) override; + + void install_readwrite_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) override; + void install_readwrite_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) override; + void install_readwrite_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) override; void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8_delegate rhandler, write8_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16_delegate rhandler, write16_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32_delegate rhandler, write32_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64_delegate rhandler, write64_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8m_delegate rhandler, write8m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16m_delegate rhandler, write16m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32m_delegate rhandler, write32m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64m_delegate rhandler, write64m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8s_delegate rhandler, write8s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16s_delegate rhandler, write16s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32s_delegate rhandler, write32s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64s_delegate rhandler, write64s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8sm_delegate rhandler, write8sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16sm_delegate rhandler, write16sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32sm_delegate rhandler, write32sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64sm_delegate rhandler, write64sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8mo_delegate rhandler, write8mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16mo_delegate rhandler, write16mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32mo_delegate rhandler, write32mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64mo_delegate rhandler, write64mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8smo_delegate rhandler, write8smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16smo_delegate rhandler, write16smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32smo_delegate rhandler, write32smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler); } void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, whandler); } - void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64smo_delegate rhandler, write64smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) override - { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, rhandler, whandler); } template<typename READ> void install_read_handler_impl(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, u16 flags, READ &handler_r) @@ -296,7 +209,7 @@ public: osd_printf_error("Binding error while installing read handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_r.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask); throw; } - install_read_handler_helper<handler_width<READ>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, handler_r); + install_read_handler_helper<handler_width_v<READ> >(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, handler_r); } template<typename WRITE> @@ -307,24 +220,7 @@ public: osd_printf_error("Binding error while installing write handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_w.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask); throw; } - install_write_handler_helper<handler_width<WRITE>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, handler_w); - } - - template<typename READ, typename WRITE> - void install_readwrite_handler_impl(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, u16 flags, READ &handler_r, WRITE &handler_w) - { - static_assert(handler_width<READ>::value == handler_width<WRITE>::value, "handler widths do not match"); - try { handler_r.resolve(); } - catch (const binding_type_exception &) { - osd_printf_error("Binding error while installing read handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_r.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask); - throw; - } - try { handler_w.resolve(); } - catch (const binding_type_exception &) { - osd_printf_error("Binding error while installing write handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_w.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask); - throw; - } - install_readwrite_handler_helper<handler_width<READ>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, handler_r, handler_w); + install_write_handler_helper<handler_width_v<WRITE> >(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, flags, handler_w); } template<int AccessWidth, typename READ> @@ -339,6 +235,9 @@ public: 8 << Width, 8 << AccessWidth, handler_r.name(), data_width() / 4, unitmask); + r()->select_u(m_id); + w()->select_u(m_id); + offs_t nstart, nend, nmask, nmirror; u64 nunitmask; int ncswidth; @@ -372,6 +271,9 @@ public: 8 << Width, 8 << AccessWidth, handler_w.name(), data_width() / 4, unitmask); + r()->select_u(m_id); + w()->select_u(m_id); + offs_t nstart, nend, nmask, nmirror; u64 nunitmask; int ncswidth; @@ -391,50 +293,6 @@ public: invalidate_caches(read_or_write::WRITE); } } - - template<int AccessWidth, typename READ, typename WRITE> - void install_readwrite_handler_helper(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, u16 flags, - const READ &handler_r, - const WRITE &handler_w) - { - if constexpr (Width < AccessWidth) { - fatalerror("install_readwrite_handler: cannot install a %d-wide handler in a %d-wide bus", 8 << AccessWidth, 8 << Width); - } else { - VPRINTF("memory_view::install_readwrite_handler(%*x-%*x mask=%*x mirror=%*x, space width=%d, handler width=%d, %s, %s, %*x)\n", - m_addrchars, addrstart, m_addrchars, addrend, - m_addrchars, addrmask, m_addrchars, addrmirror, - 8 << Width, 8 << AccessWidth, - handler_r.name(), handler_w.name(), data_width() / 4, unitmask); - - offs_t nstart, nend, nmask, nmirror; - u64 nunitmask; - int ncswidth; - check_optimize_all("install_readwrite_handler", 8 << AccessWidth, addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, nstart, nend, nmask, nmirror, nunitmask, ncswidth); - - if constexpr (Width == AccessWidth) { - auto hand_r = new handler_entry_read_delegate <Width, AddrShift, READ>(m_view.m_space, flags, handler_r); - hand_r->set_address_info(nstart, nmask); - r() ->populate(nstart, nend, nmirror, hand_r); - - auto hand_w = new handler_entry_write_delegate<Width, AddrShift, WRITE>(m_view.m_space, flags, handler_w); - hand_w->set_address_info(nstart, nmask); - w()->populate(nstart, nend, nmirror, hand_w); - } else { - auto hand_r = new handler_entry_read_delegate <AccessWidth, -AccessWidth, READ>(m_view.m_space, flags, handler_r); - memory_units_descriptor<Width, AddrShift> descriptor(AccessWidth, endianness(), hand_r, nstart, nend, nmask, nunitmask, ncswidth); - hand_r->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask()); - r() ->populate_mismatched(nstart, nend, nmirror, descriptor); - hand_r->unref(); - - auto hand_w = new handler_entry_write_delegate<AccessWidth, -AccessWidth, WRITE>(m_view.m_space, flags, handler_w); - descriptor.set_subunit_handler(hand_w); - hand_w->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask()); - w()->populate_mismatched(nstart, nend, nmirror, descriptor); - hand_w->unref(); - } - invalidate_caches(read_or_write::READWRITE); - } - } }; namespace { @@ -578,7 +436,7 @@ void memory_view::memory_view_entry::prepare_map_generic(address_map &map, bool if (!allow_alloc) fatalerror("Trying to create memory in range %X-%X too late\n", entry.m_addrstart, entry.m_addrend); - entry.m_memory = m_manager.anonymous_alloc(*m_view.m_space, address_to_byte(entry.m_addrend + 1 - entry.m_addrstart), m_config.data_width(), entry.m_addrstart, entry.m_addrend); + entry.m_memory = m_manager.anonymous_alloc(*m_view.m_space, address_to_byte(entry.m_addrend + 1 - entry.m_addrstart), m_config.data_width(), entry.m_addrstart, entry.m_addrend, key()); } } } @@ -959,6 +817,10 @@ template<int Level, int Width, int AddrShift> memory_passthrough_handler memory_ template<int Level, int Width, int AddrShift> void memory_view_entry_specific<Level, Width, AddrShift>::install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_constructor &delegate, u64 unitmask, int cswidth, u16 flags) { check_range_address("install_device_delegate", addrstart, addrend); + + r()->select_u(m_id); + w()->select_u(m_id); + address_map map(*m_view.m_space, addrstart, addrend, unitmask, cswidth, flags, m_view.m_device, delegate); map.import_submaps(m_manager.machine(), device, data_width(), endianness(), addr_shift()); prepare_device_map(map); @@ -1005,6 +867,215 @@ template<int Level, int Width, int AddrShift> void memory_view_entry_specific<Le invalidate_caches(rtag != "" ? wtag != "" ? read_or_write::READWRITE : read_or_write::READ : read_or_write::WRITE); } + +template<int Level, int Width, int AddrShift> void memory_view_entry_specific<Level, Width, AddrShift>::install_read_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_view.m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_view.m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_view.m_device.tag()); + + VPRINTF("memory_view::install_read_before_time(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_read_before_time", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + r()->select_u(m_id); + w()->select_u(m_id); + + auto hand_r = new handler_entry_read_before_time<Width, AddrShift>(m_view.m_space, *m_view.m_space->get_default_mpl(), ws); + r()->populate_passthrough(nstart, nend, nmirror, hand_r); +} + +template<int Level, int Width, int AddrShift> void memory_view_entry_specific<Level, Width, AddrShift>::install_read_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_view.m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_view.m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_view.m_device.tag()); + + VPRINTF("memory_view::install_read_before_delay(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_read_before_delay", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + r()->select_u(m_id); + w()->select_u(m_id); + + auto hand_r = new handler_entry_read_before_delay<Width, AddrShift>(m_view.m_space, *m_view.m_space->get_default_mpl(), ws); + r()->populate_passthrough(nstart, nend, nmirror, hand_r); +} + +template<int Level, int Width, int AddrShift> void memory_view_entry_specific<Level, Width, AddrShift>::install_read_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_view.m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_view.m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_view.m_device.tag()); + + VPRINTF("memory_view::install_read_after_delay(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_read_after_delay", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + r()->select_u(m_id); + w()->select_u(m_id); + + auto hand_r = new handler_entry_read_after_delay<Width, AddrShift>(m_view.m_space, *m_view.m_space->get_default_mpl(), ws); + r()->populate_passthrough(nstart, nend, nmirror, hand_r); +} + + + +template<int Level, int Width, int AddrShift> void memory_view_entry_specific<Level, Width, AddrShift>::install_write_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_view.m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_view.m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_view.m_device.tag()); + + VPRINTF("memory_view::install_write_before_time(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_write_before_time", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + r()->select_u(m_id); + w()->select_u(m_id); + + auto hand_w = new handler_entry_write_before_time<Width, AddrShift>(m_view.m_space, *m_view.m_space->get_default_mpl(), ws); + w()->populate_passthrough(nstart, nend, nmirror, hand_w); +} + +template<int Level, int Width, int AddrShift> void memory_view_entry_specific<Level, Width, AddrShift>::install_write_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_view.m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_view.m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_view.m_device.tag()); + + VPRINTF("memory_view::install_write_before_delay(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_write_before_delay", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + r()->select_u(m_id); + w()->select_u(m_id); + + auto hand_w = new handler_entry_write_before_delay<Width, AddrShift>(m_view.m_space, *m_view.m_space->get_default_mpl(), ws); + w()->populate_passthrough(nstart, nend, nmirror, hand_w); +} + +template<int Level, int Width, int AddrShift> void memory_view_entry_specific<Level, Width, AddrShift>::install_write_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_view.m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_view.m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_view.m_device.tag()); + + VPRINTF("memory_view::install_write_after_delay(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_write_after_delay", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + r()->select_u(m_id); + w()->select_u(m_id); + + auto hand_w = new handler_entry_write_after_delay<Width, AddrShift>(m_view.m_space, *m_view.m_space->get_default_mpl(), ws); + w()->populate_passthrough(nstart, nend, nmirror, hand_w); +} + + +template<int Level, int Width, int AddrShift> void memory_view_entry_specific<Level, Width, AddrShift>::install_readwrite_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_view.m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_view.m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_view.m_device.tag()); + + VPRINTF("memory_view::install_readwrite_before_time(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_readwrite_before_time", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + r()->select_u(m_id); + w()->select_u(m_id); + + auto hand_r = new handler_entry_read_before_time<Width, AddrShift>(m_view.m_space, *m_view.m_space->get_default_mpl(), ws); + r()->populate_passthrough(nstart, nend, nmirror, hand_r); + auto hand_w = new handler_entry_write_before_time<Width, AddrShift>(m_view.m_space, *m_view.m_space->get_default_mpl(), ws); + w()->populate_passthrough(nstart, nend, nmirror, hand_w); +} + +template<int Level, int Width, int AddrShift> void memory_view_entry_specific<Level, Width, AddrShift>::install_readwrite_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_view.m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_view.m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_view.m_device.tag()); + + VPRINTF("memory_view::install_readwrite_before_delay(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_readwrite_before_delay", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + r()->select_u(m_id); + w()->select_u(m_id); + + auto hand_r = new handler_entry_read_before_delay<Width, AddrShift>(m_view.m_space, *m_view.m_space->get_default_mpl(), ws); + r()->populate_passthrough(nstart, nend, nmirror, hand_r); + auto hand_w = new handler_entry_write_before_delay<Width, AddrShift>(m_view.m_space, *m_view.m_space->get_default_mpl(), ws); + w()->populate_passthrough(nstart, nend, nmirror, hand_w); +} + +template<int Level, int Width, int AddrShift> void memory_view_entry_specific<Level, Width, AddrShift>::install_readwrite_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) +{ + auto *cpu = dynamic_cast<cpu_device *>(&m_view.m_device); + if (!cpu) + fatalerror("Attempted to a waitstate handler on non-cpu device '%s'\n", m_view.m_device.tag()); + if (!cpu->cpu_is_interruptible()) + fatalerror("Attempted to a waitstate handler on non-interruptible cpu device '%s'\n", m_view.m_device.tag()); + + VPRINTF("memory_view::install_readwrite_after_delay(%*x-%*x mirror=%*x ws=%s)\n", + m_addrchars, addrstart, m_addrchars, addrend, + m_addrchars, addrmirror, ws.name()); + + offs_t nstart, nend, nmask, nmirror; + check_optimize_mirror("install_readwrite_after_delay", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror); + + r()->select_u(m_id); + w()->select_u(m_id); + + auto hand_r = new handler_entry_read_after_delay<Width, AddrShift>(m_view.m_space, *m_view.m_space->get_default_mpl(), ws); + r()->populate_passthrough(nstart, nend, nmirror, hand_r); + auto hand_w = new handler_entry_write_after_delay<Width, AddrShift>(m_view.m_space, *m_view.m_space->get_default_mpl(), ws); + w()->populate_passthrough(nstart, nend, nmirror, hand_w); +} + + template<int Level, int Width, int AddrShift> void memory_view_entry_specific<Level, Width, AddrShift>::install_bank_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, memory_bank *rbank, memory_bank *wbank) { VPRINTF("memory_view::install_readwrite_bank(%*x-%*x mirror=%*x, read=\"%s\" / write=\"%s\")\n", diff --git a/src/emu/emuopts.cpp b/src/emu/emuopts.cpp index 827b7249e07..18b37734465 100644 --- a/src/emu/emuopts.cpp +++ b/src/emu/emuopts.cpp @@ -10,10 +10,13 @@ #include "emu.h" #include "emuopts.h" + #include "drivenum.h" -#include "softlist_dev.h" #include "hashfile.h" +#include "main.h" +#include "softlist_dev.h" +// lib/util #include "corestr.h" #include "path.h" @@ -37,30 +40,30 @@ const options_entry emu_options::s_option_entries[] = // search path options { nullptr, nullptr, core_options::option_type::HEADER, "CORE SEARCH PATH OPTIONS" }, - { OPTION_PLUGINDATAPATH, ".", core_options::option_type::STRING, "path to base folder for plugin data (read/write)" }, - { OPTION_MEDIAPATH ";rp;biospath;bp", "roms", core_options::option_type::STRING, "path to ROM sets and hard disk images" }, - { OPTION_HASHPATH ";hash_directory;hash", "hash", core_options::option_type::STRING, "path to software definition files" }, - { OPTION_SAMPLEPATH ";sp", "samples", core_options::option_type::STRING, "path to audio sample sets" }, - { OPTION_ARTPATH, "artwork", core_options::option_type::STRING, "path to artwork files" }, - { OPTION_CTRLRPATH, "ctrlr", core_options::option_type::STRING, "path to controller definitions" }, - { OPTION_INIPATH, ".;ini;ini/presets", core_options::option_type::STRING, "path to ini files" }, - { OPTION_FONTPATH, ".", core_options::option_type::STRING, "path to font files" }, - { OPTION_CHEATPATH, "cheat", core_options::option_type::STRING, "path to cheat files" }, - { OPTION_CROSSHAIRPATH, "crosshair", core_options::option_type::STRING, "path to crosshair files" }, - { OPTION_PLUGINSPATH, "plugins", core_options::option_type::STRING, "path to plugin files" }, - { OPTION_LANGUAGEPATH, "language", core_options::option_type::STRING, "path to UI translation files" }, - { OPTION_SWPATH, "software", core_options::option_type::STRING, "path to loose software" }, + { OPTION_PLUGINDATAPATH, ".", core_options::option_type::PATH, "path to base folder for plugin data (read/write)" }, + { OPTION_MEDIAPATH ";rp;biospath;bp", "roms", core_options::option_type::MULTIPATH, "path to ROM sets and hard disk images" }, + { OPTION_HASHPATH ";hash_directory;hash", "hash", core_options::option_type::MULTIPATH, "path to software definition files" }, + { OPTION_SAMPLEPATH ";sp", "samples", core_options::option_type::MULTIPATH, "path to audio sample sets" }, + { OPTION_ARTPATH, "artwork", core_options::option_type::MULTIPATH, "path to artwork files" }, + { OPTION_CTRLRPATH, "ctrlr", core_options::option_type::MULTIPATH, "path to controller definitions" }, + { OPTION_INIPATH, ".;ini;ini/presets", core_options::option_type::MULTIPATH, "path to ini files" }, + { OPTION_FONTPATH, ".", core_options::option_type::MULTIPATH, "path to font files" }, + { OPTION_CHEATPATH, "cheat", core_options::option_type::MULTIPATH, "path to cheat files" }, + { OPTION_CROSSHAIRPATH, "crosshair", core_options::option_type::MULTIPATH, "path to crosshair files" }, + { OPTION_PLUGINSPATH, "plugins", core_options::option_type::MULTIPATH, "path to plugin files" }, + { OPTION_LANGUAGEPATH, "language", core_options::option_type::MULTIPATH, "path to UI translation files" }, + { OPTION_SWPATH, "software", core_options::option_type::MULTIPATH, "path to loose software" }, // output directory options { nullptr, nullptr, core_options::option_type::HEADER, "CORE OUTPUT DIRECTORY OPTIONS" }, - { OPTION_CFG_DIRECTORY, "cfg", core_options::option_type::STRING, "directory to save configurations" }, - { OPTION_NVRAM_DIRECTORY, "nvram", core_options::option_type::STRING, "directory to save NVRAM contents" }, - { OPTION_INPUT_DIRECTORY, "inp", core_options::option_type::STRING, "directory to save input device logs" }, - { OPTION_STATE_DIRECTORY, "sta", core_options::option_type::STRING, "directory to save states" }, - { OPTION_SNAPSHOT_DIRECTORY, "snap", core_options::option_type::STRING, "directory to save/load screenshots" }, - { OPTION_DIFF_DIRECTORY, "diff", core_options::option_type::STRING, "directory to save hard drive image difference files" }, - { OPTION_COMMENT_DIRECTORY, "comments", core_options::option_type::STRING, "directory to save debugger comments" }, - { OPTION_SHARE_DIRECTORY, "share", core_options::option_type::STRING, "directory to share with emulated machines" }, + { OPTION_CFG_DIRECTORY, "cfg", core_options::option_type::PATH, "directory to save configurations" }, + { OPTION_NVRAM_DIRECTORY, "nvram", core_options::option_type::PATH, "directory to save NVRAM contents" }, + { OPTION_INPUT_DIRECTORY, "inp", core_options::option_type::PATH, "directory to save input device logs" }, + { OPTION_STATE_DIRECTORY, "sta", core_options::option_type::PATH, "directory to save states" }, + { OPTION_SNAPSHOT_DIRECTORY, "snap", core_options::option_type::PATH, "directory to save/load screenshots" }, + { OPTION_DIFF_DIRECTORY, "diff", core_options::option_type::PATH, "directory to save hard drive image difference files" }, + { OPTION_COMMENT_DIRECTORY, "comments", core_options::option_type::PATH, "directory to save debugger comments" }, + { OPTION_SHARE_DIRECTORY, "share", core_options::option_type::PATH, "directory to share with emulated machines" }, // state/playback options { nullptr, nullptr, core_options::option_type::HEADER, "CORE STATE/PLAYBACK OPTIONS" }, @@ -72,9 +75,9 @@ const options_entry emu_options::s_option_entries[] = { OPTION_RECORD ";rec", nullptr, core_options::option_type::STRING, "record an input file" }, { OPTION_EXIT_AFTER_PLAYBACK, "0", core_options::option_type::BOOLEAN, "close the program at the end of playback" }, - { OPTION_MNGWRITE, nullptr, core_options::option_type::STRING, "optional filename to write a MNG movie of the current session" }, - { OPTION_AVIWRITE, nullptr, core_options::option_type::STRING, "optional filename to write an AVI movie of the current session" }, - { OPTION_WAVWRITE, nullptr, core_options::option_type::STRING, "optional filename to write a WAV file of the current session" }, + { OPTION_MNGWRITE, nullptr, core_options::option_type::PATH, "optional filename to write a MNG movie of the current session" }, + { OPTION_AVIWRITE, nullptr, core_options::option_type::PATH, "optional filename to write an AVI movie of the current session" }, + { OPTION_WAVWRITE, nullptr, core_options::option_type::PATH, "optional filename to write a WAV file of the current session" }, { OPTION_SNAPNAME, "%g/%i", core_options::option_type::STRING, "override of the default snapshot/movie naming; %g == gamename, %i == index" }, { OPTION_SNAPSIZE, "auto", core_options::option_type::STRING, "specify snapshot/movie resolution (<width>x<height>) or 'auto' to use minimal size " }, { OPTION_SNAPVIEW, "auto", core_options::option_type::STRING, "snapshot/movie view - 'auto' for default, or 'native' for per-screen pixel-aspect views" }, @@ -157,8 +160,9 @@ const options_entry emu_options::s_option_entries[] = { OPTION_UI_ACTIVE, "0", core_options::option_type::BOOLEAN, "enable user interface on top of emulated keyboard (if present)" }, { OPTION_OFFSCREEN_RELOAD ";reload", "0", core_options::option_type::BOOLEAN, "convert lightgun button 2 into offscreen reload" }, { OPTION_JOYSTICK_MAP ";joymap", "auto", core_options::option_type::STRING, "explicit joystick map, or auto to auto-select" }, - { OPTION_JOYSTICK_DEADZONE ";joy_deadzone;jdz(0.00-1)", "0.3", core_options::option_type::FLOAT, "center deadzone range for joystick where change is ignored (0.0 center, 1.0 end)" }, - { OPTION_JOYSTICK_SATURATION ";joy_saturation;jsat(0.00-1)", "0.85", core_options::option_type::FLOAT, "end of axis saturation range for joystick where change is ignored (0.0 center, 1.0 end)" }, + { OPTION_JOYSTICK_DEADZONE ";joy_deadzone;jdz(0.00-1)", "0.15", core_options::option_type::FLOAT, "center deadzone range for joystick where change is ignored (0.0 center, 1.0 end)" }, + { OPTION_JOYSTICK_SATURATION ";joy_saturation;jsat(0.00-1)", "0.85", core_options::option_type::FLOAT, "end of axis saturation range for joystick where change is ignored (0.0 center, 1.0 end)" }, + { OPTION_JOYSTICK_THRESHOLD ";joy_threshold;jthresh(0.00-1)", "0.3", core_options::option_type::FLOAT, "threshold for joystick to be considered active as a switch (0.0 center, 1.0 end)" }, { OPTION_NATURAL_KEYBOARD ";nat", "0", core_options::option_type::BOOLEAN, "specifies whether to use a natural keyboard or not" }, { OPTION_JOYSTICK_CONTRADICTORY ";joy_contradictory","0", core_options::option_type::BOOLEAN, "enable contradictory direction digital joystick input at the same time" }, { OPTION_COIN_IMPULSE, "0", core_options::option_type::INTEGER, "set coin impulse time (n<0 disable impulse, n==0 obey driver, 0<n set time n)" }, @@ -181,7 +185,7 @@ const options_entry emu_options::s_option_entries[] = { OPTION_OSLOG, "0", core_options::option_type::BOOLEAN, "output error.log data to system diagnostic output (debugger or standard error)" }, { OPTION_DEBUG ";d", "0", core_options::option_type::BOOLEAN, "enable/disable debugger" }, { OPTION_UPDATEINPAUSE, "0", core_options::option_type::BOOLEAN, "keep calling video updates while in pause" }, - { OPTION_DEBUGSCRIPT, nullptr, core_options::option_type::STRING, "script for debugger" }, + { OPTION_DEBUGSCRIPT, nullptr, core_options::option_type::PATH, "script for debugger" }, { OPTION_DEBUGLOG, "0", core_options::option_type::BOOLEAN, "write debug console output to debug.log" }, // comm options @@ -212,7 +216,7 @@ const options_entry emu_options::s_option_entries[] = { nullptr, nullptr, core_options::option_type::HEADER, "SCRIPTING OPTIONS" }, { OPTION_AUTOBOOT_COMMAND ";ab", nullptr, core_options::option_type::STRING, "command to execute after machine boot" }, { OPTION_AUTOBOOT_DELAY, "0", core_options::option_type::INTEGER, "delay before executing autoboot command (seconds)" }, - { OPTION_AUTOBOOT_SCRIPT ";script", nullptr, core_options::option_type::STRING, "Lua script to execute after machine boot" }, + { OPTION_AUTOBOOT_SCRIPT ";script", nullptr, core_options::option_type::PATH, "Lua script to execute after machine boot" }, { OPTION_CONSOLE, "0", core_options::option_type::BOOLEAN, "enable emulator Lua console" }, { OPTION_PLUGINS, "1", core_options::option_type::BOOLEAN, "enable Lua plugin support" }, { OPTION_PLUGIN, nullptr, core_options::option_type::STRING, "list of plugins to enable" }, @@ -221,7 +225,7 @@ const options_entry emu_options::s_option_entries[] = { nullptr, nullptr, core_options::option_type::HEADER, "HTTP SERVER OPTIONS" }, { OPTION_HTTP, "0", core_options::option_type::BOOLEAN, "enable HTTP server" }, { OPTION_HTTP_PORT, "8080", core_options::option_type::INTEGER, "HTTP server port" }, - { OPTION_HTTP_ROOT, "web", core_options::option_type::STRING, "HTTP server document root" }, + { OPTION_HTTP_ROOT, "web", core_options::option_type::PATH, "HTTP server document root" }, { nullptr } }; @@ -255,7 +259,7 @@ namespace } protected: - virtual void internal_set_value(std::string &&newvalue) override + virtual void internal_set_value(std::string &&newvalue, bool perform_substitutions) override { m_host.set_system_name(std::move(newvalue)); } @@ -275,7 +279,7 @@ namespace } protected: - virtual void internal_set_value(std::string &&newvalue) override + virtual void internal_set_value(std::string &&newvalue, bool perform_substitutions) override { m_host.set_software(std::move(newvalue)); } @@ -313,7 +317,7 @@ namespace } protected: - virtual void internal_set_value(std::string &&newvalue) override + virtual void internal_set_value(std::string &&newvalue, bool perform_substitutions) override { m_host.specify(std::move(newvalue), false); } @@ -339,7 +343,7 @@ namespace } protected: - virtual void internal_set_value(std::string &&newvalue) override + virtual void internal_set_value(std::string &&newvalue, bool perform_substitutions) override { m_host.specify(std::move(newvalue), false); } @@ -615,8 +619,8 @@ bool emu_options::add_and_remove_slot_options() //------------------------------------------------- -// add_and_remove_slot_options - add any missing -// and/or purge extraneous slot options +// add_and_remove_image_options - add any missing +// and/or purge extraneous image options //------------------------------------------------- bool emu_options::add_and_remove_image_options() @@ -719,7 +723,7 @@ bool emu_options::add_and_remove_image_options() //------------------------------------------------- // reevaluate_default_card_software - based on recent -// changes in what images are mounted, give drivers +// changes in what images are mounted, give devices // a chance to specify new default slot options //------------------------------------------------- @@ -758,6 +762,16 @@ void emu_options::reevaluate_default_card_software() std::string default_card_software = get_default_card_software(slot); if (slot_opt.default_card_software() != default_card_software) { + // HACK: prevent option values set from "XXX_default" in software list entries + // from getting cleared out, using crude heuristic to distinguish these from + // values representing cartridge types and such + if (default_card_software.empty()) + { + auto *opt = slot.option(slot_opt.default_card_software().c_str()); + if (opt && opt->selectable()) + continue; + } + slot_opt.set_default_card_software(std::move(default_card_software)); // calling set_default_card_software() can cause a cascade of slot/image @@ -846,7 +860,8 @@ void emu_options::set_software(std::string &&new_software) } // keep any deferred options for the next round - softlist_opts = std::move(deferred_opts); + softlist_opts.slot = std::move(deferred_opts.slot); + softlist_opts.image = std::move(deferred_opts.image); // do we have any pending options after failing to distribute any? size_t after_size = softlist_opts.slot.size() + softlist_opts.image.size(); @@ -854,6 +869,14 @@ void emu_options::set_software(std::string &&new_software) throw options_error_exception("Could not assign software option"); } + // distribute slot option defaults + for (auto &slot_opt : softlist_opts.slot_defaults) + { + auto iter = m_slot_options.find(slot_opt.first); + if (iter != m_slot_options.end()) + iter->second.set_default_card_software(std::move(slot_opt.second)); + } + // we've succeeded; update the set name m_software_name = std::move(new_software); } @@ -961,7 +984,15 @@ emu_options::software_options emu_options::evaluate_initial_softlist_options(con && fi.name().compare(fi.name().size() - default_suffix.size(), default_suffix.size(), default_suffix) == 0) { std::string slot_name = fi.name().substr(0, fi.name().size() - default_suffix.size()); - results.slot[slot_name] = fi.value(); + + // only add defaults if they exist in this configuration + device_t *device = config.root_device().subdevice(slot_name.c_str()); + if (device) + { + device_slot_interface *intf; + if (device->interface(intf) && intf->option(fi.value().c_str())) + results.slot_defaults[slot_name] = fi.value(); + } } } } @@ -1054,8 +1085,9 @@ image_option &emu_options::image_option(const std::string &device_name) void emu_options::command_argument_processed() { // some command line arguments require that the system name be set, so we can get slot options - if (command_arguments().size() == 1 && !core_iswildstr(command_arguments()[0].c_str()) && - (command() == "listdevices" || (command() == "listslots") || (command() == "listmedia") || (command() == "listsoftware"))) + // FIXME: having this here is a massively leaky abstraction + if (command_arguments().size() == 1 && !core_iswildstr(command_arguments()[0]) && + (command() == "listdevices" || (command() == "listslots") || (command() == "listbios") || (command() == "listmedia") || (command() == "listsoftware"))) { set_system_name(command_arguments()[0]); } diff --git a/src/emu/emuopts.h b/src/emu/emuopts.h index 296e2e46590..0a1b1dcf413 100644 --- a/src/emu/emuopts.h +++ b/src/emu/emuopts.h @@ -136,6 +136,7 @@ #define OPTION_JOYSTICK_MAP "joystick_map" #define OPTION_JOYSTICK_DEADZONE "joystick_deadzone" #define OPTION_JOYSTICK_SATURATION "joystick_saturation" +#define OPTION_JOYSTICK_THRESHOLD "joystick_threshold" #define OPTION_NATURAL_KEYBOARD "natural" #define OPTION_JOYSTICK_CONTRADICTORY "joystick_contradictory" #define OPTION_COIN_IMPULSE "coin_impulse" @@ -426,6 +427,7 @@ public: const char *joystick_map() const { return value(OPTION_JOYSTICK_MAP); } float joystick_deadzone() const { return float_value(OPTION_JOYSTICK_DEADZONE); } float joystick_saturation() const { return float_value(OPTION_JOYSTICK_SATURATION); } + float joystick_threshold() const { return float_value(OPTION_JOYSTICK_THRESHOLD); } bool steadykey() const { return bool_value(OPTION_STEADYKEY); } bool ui_active() const { return bool_value(OPTION_UI_ACTIVE); } bool offscreen_reload() const { return bool_value(OPTION_OFFSCREEN_RELOAD); } @@ -502,6 +504,7 @@ private: struct software_options { std::unordered_map<std::string, std::string> slot; + std::unordered_map<std::string, std::string> slot_defaults; std::unordered_map<std::string, std::string> image; }; diff --git a/src/emu/fileio.cpp b/src/emu/fileio.cpp index a1bf4adbcb4..c0341b93368 100644 --- a/src/emu/fileio.cpp +++ b/src/emu/fileio.cpp @@ -14,6 +14,8 @@ #include "util/path.h" #include "util/unzip.h" +#include <tuple> + //#define VERBOSE 1 #define LOG_OUTPUT_FUNC osd_printf_verbose #include "logmacro.h" @@ -531,9 +533,10 @@ u32 emu_file::read(void *buffer, u32 length) return 0; // read the data if we can + std::error_condition err; size_t actual = 0; if (m_file) - m_file->read(buffer, length, actual); + std::tie(err, actual) = util::read(*m_file, buffer, length); return actual; } @@ -601,9 +604,10 @@ u32 emu_file::write(const void *buffer, u32 length) { // FIXME: need better interface to report errors // write the data if we can + std::error_condition err; size_t actual = 0; if (m_file) - m_file->write(buffer, length, actual); + std::tie(err, actual) = util::write(*m_file, buffer, length); return actual; } @@ -627,7 +631,7 @@ int emu_file::puts(std::string_view s) // vfprintf - vfprintf to a text file //------------------------------------------------- -int emu_file::vprintf(util::format_argument_pack<std::ostream> const &args) +int emu_file::vprintf(util::format_argument_pack<char> const &args) { // write the data if we can return m_file ? m_file->vprintf(args) : 0; diff --git a/src/emu/fileio.h b/src/emu/fileio.h index 7398e649c6e..225cebd0a81 100644 --- a/src/emu/fileio.h +++ b/src/emu/fileio.h @@ -182,7 +182,7 @@ public: // writing u32 write(const void *buffer, u32 length); int puts(std::string_view s); - int vprintf(util::format_argument_pack<std::ostream> const &args); + int vprintf(util::format_argument_pack<char> const &args); template <typename Format, typename... Params> int printf(Format &&fmt, Params &&...args) { return vprintf(util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...)); diff --git a/src/emu/gamedrv.h b/src/emu/gamedrv.h index 5ca3a653506..4f0050e2a19 100644 --- a/src/emu/gamedrv.h +++ b/src/emu/gamedrv.h @@ -30,44 +30,32 @@ struct machine_flags { enum type : u32 { - MASK_ORIENTATION = 0x00000007, - MASK_TYPE = 0x00000038, + MASK_ORIENTATION = 0x0000'0007, - FLIP_X = 0x00000001, - FLIP_Y = 0x00000002, - SWAP_XY = 0x00000004, - ROT0 = 0x00000000, + FLIP_X = 0x0000'0001, + FLIP_Y = 0x0000'0002, + SWAP_XY = 0x0000'0004, + ROT0 = 0x0000'0000, ROT90 = FLIP_X | SWAP_XY, ROT180 = FLIP_X | FLIP_Y, ROT270 = FLIP_Y | SWAP_XY, - TYPE_ARCADE = 0x00000008, // coin-operated machine for public use - TYPE_CONSOLE = 0x00000010, // console system - TYPE_COMPUTER = 0x00000018, // any kind of computer including home computers, minis, calculators, ... - TYPE_OTHER = 0x00000038, // any other emulated system (e.g. clock, satellite receiver, ...) - - NOT_WORKING = 0x00000040, - SUPPORTS_SAVE = 0x00000080, // system supports save states - NO_COCKTAIL = 0x00000100, // screen flip support is missing - IS_BIOS_ROOT = 0x00000200, // this driver entry is a BIOS root - REQUIRES_ARTWORK = 0x00000400, // requires external artwork for key game elements - CLICKABLE_ARTWORK = 0x00000800, // artwork is clickable and requires mouse cursor - UNOFFICIAL = 0x00001000, // unofficial hardware modification - NO_SOUND_HW = 0x00002000, // system has no sound output - MECHANICAL = 0x00004000, // contains mechanical parts (pinball, redemption games, ...) - IS_INCOMPLETE = 0x00008000 // official system with blatantly incomplete hardware/software + NOT_WORKING = 0x0000'0040, + SUPPORTS_SAVE = 0x0000'0080, // system supports save states + NO_COCKTAIL = 0x0000'0100, // screen flip support is missing + IS_BIOS_ROOT = 0x0000'0200, // this driver entry is a BIOS root + REQUIRES_ARTWORK = 0x0000'0400, // requires external artwork for key game elements + CLICKABLE_ARTWORK = 0x0000'0800, // artwork is clickable and requires mouse cursor + UNOFFICIAL = 0x0000'1000, // unofficial hardware modification + NO_SOUND_HW = 0x0000'2000, // system has no sound output + MECHANICAL = 0x0000'4000, // contains mechanical parts (pinball, redemption games, ...) + IS_INCOMPLETE = 0x0000'8000 // official system with blatantly incomplete hardware/software }; }; DECLARE_ENUM_BITWISE_OPERATORS(machine_flags::type); -constexpr u64 MACHINE_TYPE_ARCADE = machine_flags::TYPE_ARCADE; -constexpr u64 MACHINE_TYPE_CONSOLE = machine_flags::TYPE_CONSOLE; -constexpr u64 MACHINE_TYPE_COMPUTER = machine_flags::TYPE_COMPUTER; -constexpr u64 MACHINE_TYPE_OTHER = machine_flags::TYPE_OTHER; - - /// \addtogroup machinedef /// \{ /// \name System emulation status constants @@ -204,11 +192,9 @@ driver_device_creator< \ /// \addtogroup machinedef /// \{ -/// \brief Define a "game" system +/// \brief Define a system /// -/// Use this macro to define most systems intended for public use, -/// including arcade games, gambling machines, vending machines, and -/// information kiosks. Must be used in the global namespace. +/// Must be used in the global namespace. /// /// Creates an appropriately named and populated #game_driver structure /// describing the system. @@ -252,7 +238,7 @@ driver_device_creator< \ /// unemulated and imperfectly emulated feature flags that apply to /// all systems implemented using the class in the class itself to /// avoid repetition. -/// \sa GAMEL CONS COMP SYST +/// \sa GAMEL SYST #define GAME(YEAR, NAME, PARENT, MACHINE, INPUT, CLASS, INIT, MONITOR, COMPANY, FULLNAME, FLAGS) \ GAME_DRIVER_TRAITS(NAME, FULLNAME) \ extern game_driver const GAME_NAME(NAME) \ @@ -267,18 +253,18 @@ extern game_driver const GAME_NAME(NAME) \ ROM_NAME(NAME), \ nullptr, \ nullptr, \ - machine_flags::type(u32((MONITOR) | (FLAGS) | MACHINE_TYPE_ARCADE)),\ + machine_flags::type(u32((MONITOR) | (FLAGS))), \ #NAME \ }; -/// \brief Define a "game" system with an additional internal layout +/// \brief Define a system with an additional internal layout /// /// Equivalent to the #GAME macro, but with the additional ability to -/// supply system-specific internal artwork layout data. Views from the +/// supply a system-specific internal artwork layout. Views from the /// system-specific layout are available in addition to any views from -/// layout data specified in the machine configuration. Must be used in -/// the global namespace. +/// layouts specified in the machine configuration. Must be used in the +/// global namespace. /// /// Creates an appropriately named and populated #game_driver structure /// describing the system. @@ -324,7 +310,7 @@ extern game_driver const GAME_NAME(NAME) \ /// avoid repetition. /// \param LAYOUT An #internal_layout structure providing additional /// internal artwork for the system. -/// \sa GAME CONS COMP SYST +/// \sa GAME SYST #define GAMEL(YEAR, NAME, PARENT, MACHINE, INPUT, CLASS, INIT, MONITOR, COMPANY, FULLNAME, FLAGS, LAYOUT) \ GAME_DRIVER_TRAITS(NAME, FULLNAME) \ extern game_driver const GAME_NAME(NAME) \ @@ -339,15 +325,15 @@ extern game_driver const GAME_NAME(NAME) \ ROM_NAME(NAME), \ nullptr, \ &LAYOUT, \ - machine_flags::type(u32((MONITOR) | (FLAGS) | MACHINE_TYPE_ARCADE)),\ + machine_flags::type(u32((MONITOR) | (FLAGS))), \ #NAME \ }; -/// \brief Define a "console" system +/// \brief Define a system with software compatibility grouping /// -/// Use this macro to define appliance-like entertainment systems -/// designed for domestic use. Must be used in the global namespace. +/// Equivalent to the #GAME macro, but allows software-compatible +/// systems to be grouped. /// /// Creates an appropriately named and populated #game_driver structure /// describing the system. @@ -390,156 +376,31 @@ extern game_driver const GAME_NAME(NAME) \ /// unemulated and imperfectly emulated feature flags that apply to /// all systems implemented using the class in the class itself to /// avoid repetition. Screen orientation flags may be included here. -/// \sa GAME GAMEL COMP SYST -#define CONS(YEAR, NAME, PARENT, COMPAT, MACHINE, INPUT, CLASS, INIT, COMPANY, FULLNAME, FLAGS) \ -GAME_DRIVER_TRAITS(NAME, FULLNAME) \ -extern game_driver const GAME_NAME(NAME) \ -{ \ - GAME_DRIVER_TYPE(NAME, CLASS, FLAGS), \ - #PARENT, \ - #YEAR, \ - COMPANY, \ - [] (machine_config &config, device_t &owner) { downcast<CLASS &>(owner).MACHINE(config); }, \ - INPUT_PORTS_NAME(INPUT), \ - [] (device_t &owner) { downcast<CLASS &>(owner).INIT(); }, \ - ROM_NAME(NAME), \ - #COMPAT, \ - nullptr, \ - machine_flags::type(u32(ROT0 | (FLAGS) | MACHINE_TYPE_CONSOLE)), \ - #NAME \ -}; +/// \sa GAME GAMEL +#define SYST(YEAR, NAME, PARENT, COMPAT, MACHINE, INPUT, CLASS, INIT, COMPANY, FULLNAME, FLAGS) \ + GAME_DRIVER_TRAITS(NAME, FULLNAME) \ + extern game_driver const GAME_NAME(NAME) \ + { \ + GAME_DRIVER_TYPE(NAME, CLASS, FLAGS), \ + #PARENT, \ + #YEAR, \ + COMPANY, \ + [] (machine_config &config, device_t &owner) { downcast<CLASS &>(owner).MACHINE(config); }, \ + INPUT_PORTS_NAME(INPUT), \ + [] (device_t &owner) { downcast<CLASS &>(owner).INIT(); }, \ + ROM_NAME(NAME), \ + #COMPAT, \ + nullptr, \ + machine_flags::type(u32(ROT0 | (FLAGS))), \ + #NAME \ + }; -/// \brief Define a "computer" system -/// -/// Use this macro to define computer-like systems. Must be used in the -/// global namespace. -/// -/// Creates an appropriately named and populated #game_driver structure -/// describing the system. -/// \param YEAR The year that the system was first made available. Must -/// be a token containing only the digits zero to nine, question mark -/// and plus sign. -/// \param NAME The short name of the system, used for identification, -/// and in filesystem paths for assets and data. Must be a token no -/// longer than sixteen characters, containing only ASCII lowercase -/// letters, digits and underscores. Must be globally unique across -/// systems and devices. -/// \param PARENT Short name of the parent or BIOS system if applicable, -/// or a single digit zero otherwise. -/// \param COMPAT Short name of a system that this system is compatible -/// with if applicable, or a single digit zero otherwise. -/// \param MACHINE Function used to buid machine configuration for the -/// system. Must be a public member function of the system device -/// class (\p CLASS argument), returning void and taking a reference -/// to a #machine_config object as a parameter. -/// \param INPUT Input port definitions for the root device of the -/// system, usually defined using #INPUT_PORTS_START and associated -/// macros. -/// \param CLASS Class to instantiate as the root device of the system. -/// Must be an implementation of #driver_device. -/// \param INIT Initialisation function called after all child devices -/// have started, but before the driver start functions are called. -/// Often used for tasks like decrypting ROMs. Must be a public -/// member function of the system device class (\p CLASS argument), -/// returning void and accepting no parameters. The function -/// #driver_device::empty_init is supplied for systems that don't need -/// to perform additional tasks. -/// \param COMPANY Name of the developer or distributor of the system. -/// Must be a string. -/// \param FULLNAME Display name for the system. Must be a string, and -/// must be globally unique across systems and devices. -/// \param FLAGS Bitwise combination of emulation status flags for the -/// system, in addition to flags supplied by the system device class -/// (see #device_t::unemulated_features and -/// #device_t::imperfect_features). It is advisable to supply -/// unemulated and imperfectly emulated feature flags that apply to -/// all systems implemented using the class in the class itself to -/// avoid repetition. Screen orientation flags may be included here. -/// \sa GAME GAMEL CONS SYST -#define COMP(YEAR, NAME, PARENT, COMPAT, MACHINE, INPUT, CLASS, INIT, COMPANY, FULLNAME, FLAGS) \ -GAME_DRIVER_TRAITS(NAME, FULLNAME) \ -extern game_driver const GAME_NAME(NAME) \ -{ \ - GAME_DRIVER_TYPE(NAME, CLASS, FLAGS), \ - #PARENT, \ - #YEAR, \ - COMPANY, \ - [] (machine_config &config, device_t &owner) { downcast<CLASS &>(owner).MACHINE(config); }, \ - INPUT_PORTS_NAME(INPUT), \ - [] (device_t &owner) { downcast<CLASS &>(owner).INIT(); }, \ - ROM_NAME(NAME), \ - #COMPAT, \ - nullptr, \ - machine_flags::type(u32(ROT0 | (FLAGS) | MACHINE_TYPE_COMPUTER)), \ - #NAME \ -}; - +#define CONS(YEAR, NAME, PARENT, COMPAT, MACHINE, INPUT, CLASS, INIT, COMPANY, FULLNAME, FLAGS) \ + SYST(YEAR, NAME, PARENT, COMPAT, MACHINE, INPUT, CLASS, INIT, COMPANY, FULLNAME, FLAGS) -/// \brief Define a generic system -/// -/// Use this macro to define miscellaneous systems that don't fall into -/// one of the other categories. Must be used in the global namespace. -/// -/// Creates an appropriately named and populated #game_driver structure -/// describing the system. -/// \param YEAR The year that the system was first made available. Must -/// be a token containing only the digits zero to nine, question mark -/// and plus sign. -/// \param NAME The short name of the system, used for identification, -/// and in filesystem paths for assets and data. Must be a token no -/// longer than sixteen characters, containing only ASCII lowercase -/// letters, digits and underscores. Must be globally unique across -/// systems and devices. -/// \param PARENT Short name of the parent or BIOS system if applicable, -/// or a single digit zero otherwise. -/// \param COMPAT Short name of a system that this system is compatible -/// with if applicable, or a single digit zero otherwise. -/// \param MACHINE Function used to buid machine configuration for the -/// system. Must be a public member function of the system device -/// class (\p CLASS argument), returning void and taking a reference -/// to a #machine_config object as a parameter. -/// \param INPUT Input port definitions for the root device of the -/// system, usually defined using #INPUT_PORTS_START and associated -/// macros. -/// \param CLASS Class to instantiate as the root device of the system. -/// Must be an implementation of #driver_device. -/// \param INIT Initialisation function called after all child devices -/// have started, but before the driver start functions are called. -/// Often used for tasks like decrypting ROMs. Must be a public -/// member function of the system device class (\p CLASS argument), -/// returning void and accepting no parameters. The function -/// #driver_device::empty_init is supplied for systems that don't need -/// to perform additional tasks. -/// \param COMPANY Name of the developer or distributor of the system. -/// Must be a string. -/// \param FULLNAME Display name for the system. Must be a string, and -/// must be globally unique across systems and devices. -/// \param FLAGS Bitwise combination of emulation status flags for the -/// system, in addition to flags supplied by the system device class -/// (see #device_t::unemulated_features and -/// #device_t::imperfect_features). It is advisable to supply -/// unemulated and imperfectly emulated feature flags that apply to -/// all systems implemented using the class in the class itself to -/// avoid repetition. Screen orientation flags may be included here. -/// \sa GAME GAMEL CONS COMP -#define SYST(YEAR, NAME, PARENT, COMPAT, MACHINE, INPUT, CLASS, INIT, COMPANY, FULLNAME, FLAGS) \ -GAME_DRIVER_TRAITS(NAME, FULLNAME) \ -extern game_driver const GAME_NAME(NAME) \ -{ \ - GAME_DRIVER_TYPE(NAME, CLASS, FLAGS), \ - #PARENT, \ - #YEAR, \ - COMPANY, \ - [] (machine_config &config, device_t &owner) { downcast<CLASS &>(owner).MACHINE(config); }, \ - INPUT_PORTS_NAME(INPUT), \ - [] (device_t &owner) { downcast<CLASS &>(owner).INIT(); }, \ - ROM_NAME(NAME), \ - #COMPAT, \ - nullptr, \ - machine_flags::type(u32(ROT0 | (FLAGS) | MACHINE_TYPE_OTHER)), \ - #NAME \ -}; +#define COMP(YEAR, NAME, PARENT, COMPAT, MACHINE, INPUT, CLASS, INIT, COMPANY, FULLNAME, FLAGS) \ + SYST(YEAR, NAME, PARENT, COMPAT, MACHINE, INPUT, CLASS, INIT, COMPANY, FULLNAME, FLAGS) /// \} diff --git a/src/emu/image.cpp b/src/emu/image.cpp index e7f070eb9ea..3839a57549b 100644 --- a/src/emu/image.cpp +++ b/src/emu/image.cpp @@ -15,8 +15,10 @@ #include "drivenum.h" #include "emuopts.h" #include "fileio.h" +#include "main.h" #include "softlist.h" +// lib/util #include "corestr.h" #include "xmlfile.h" #include "zippath.h" @@ -38,6 +40,9 @@ image_manager::image_manager(running_machine &machine) // make sure that any required devices have been allocated for (device_image_interface &image : image_interface_enumerator(machine.root_device())) { + // see if region-based chds are available + image.check_preset_images(); + // ignore things not user loadable if (!image.user_loadable()) continue; @@ -49,27 +54,32 @@ image_manager::image_manager(running_machine &machine) if (!startup_image.empty()) { // we do have a startup image specified - load it - image_init_result result = image_init_result::FAIL; + std::pair<std::error_condition, std::string> result(image_error::UNSPECIFIED, std::string()); // try as a softlist if (software_name_parse(startup_image)) + { + osd_printf_verbose("%s: attempting to load software item %s\n", image.device().tag(), startup_image); result = image.load_software(startup_image); + } // failing that, try as an image - if (result != image_init_result::PASS) + if (result.first) + { + osd_printf_verbose("%s: attempting to load media image %s\n", image.device().tag(), startup_image); result = image.load(startup_image); + } // failing that, try creating it (if appropriate) - if (result != image_init_result::PASS && image.support_command_line_image_creation()) + if (result.first && image.support_command_line_image_creation()) + { + osd_printf_verbose("%s: attempting to create media image %s\n", image.device().tag(), startup_image); result = image.create(startup_image); + } // did the image load fail? - if (result != image_init_result::PASS) + if (result.first) { - // retrieve image error message - std::string image_err = std::string(image.error()); - std::string startup_image_name = startup_image; - // unload the bad image image.unload(); @@ -78,11 +88,18 @@ image_manager::image_manager(running_machine &machine) if (machine.options().write_config()) write_config(machine.options(), nullptr, &machine.system()); - throw emu_fatalerror(EMU_ERR_DEVICE, "Device %s load (-%s %s) failed: %s", + // retrieve image error message + throw emu_fatalerror(EMU_ERR_DEVICE, + !result.second.empty() + ? "Device %1$s load (-%2$s %3$s) failed: %4$s (%5$s:%6$d %7$s)" + : "Device %1$s load (-%2$s %3$s) failed: %7$s (%5$s:%6$d)", image.device().name(), image.instance_name(), - startup_image_name, - image_err); + startup_image, + result.second, + result.first.category().name(), + result.first.value(), + result.first.message()); } } } @@ -241,13 +258,14 @@ void image_manager::postdevice_init() /* make sure that any required devices have been allocated */ for (device_image_interface &image : image_interface_enumerator(machine().root_device())) { - image_init_result result = image.finish_load(); + auto [result, image_err] = image.finish_load(); /* did the image load fail? */ - if (result != image_init_result::PASS) + if (result) { /* retrieve image error message */ - std::string image_err = std::string(image.error()); + if (image_err.empty()) + image_err = result.message(); /* unload all images */ unload_all(); diff --git a/src/emu/inpttype.h b/src/emu/inpttype.h new file mode 100644 index 00000000000..fa711b7eabd --- /dev/null +++ b/src/emu/inpttype.h @@ -0,0 +1,353 @@ +// license:BSD-3-Clause +// copyright-holders:Aaron Giles +/*************************************************************************** + + inpttype.ipp + + Core-defined input types. + +***************************************************************************/ +#ifndef MAME_EMU_INPTTYPE_H +#define MAME_EMU_INPTTYPE_H + +#pragma once + +#include "interface/inputfwd.h" +#include "osdcomm.h" + + +enum ioport_type : osd::u32 +{ + // pseudo-port types + IPT_INVALID = 0, + IPT_UNUSED, + IPT_END, + IPT_UNKNOWN, + IPT_PORT, + IPT_DIPSWITCH, + IPT_CONFIG, + + // start buttons + IPT_START1, + IPT_START2, + IPT_START3, + IPT_START4, + IPT_START5, + IPT_START6, + IPT_START7, + IPT_START8, + IPT_START9, + IPT_START10, + + // coin slots + IPT_COIN1, + IPT_COIN2, + IPT_COIN3, + IPT_COIN4, + IPT_COIN5, + IPT_COIN6, + IPT_COIN7, + IPT_COIN8, + IPT_COIN9, + IPT_COIN10, + IPT_COIN11, + IPT_COIN12, + IPT_BILL1, + + // service coin + IPT_SERVICE1, + IPT_SERVICE2, + IPT_SERVICE3, + IPT_SERVICE4, + + // tilt inputs + IPT_TILT1, + IPT_TILT2, + IPT_TILT3, + IPT_TILT4, + + // misc other digital inputs + IPT_POWER_ON, + IPT_POWER_OFF, + IPT_SERVICE, + IPT_TILT, + IPT_INTERLOCK, + IPT_MEMORY_RESET, + IPT_VOLUME_UP, + IPT_VOLUME_DOWN, + IPT_START, // use the numbered start button(s) for coin-ops + IPT_SELECT, + IPT_KEYPAD, + IPT_KEYBOARD, + + // digital joystick inputs + IPT_DIGITAL_JOYSTICK_FIRST, + + // use IPT_JOYSTICK for panels where the player has one single joystick + IPT_JOYSTICK_UP, + IPT_JOYSTICK_DOWN, + IPT_JOYSTICK_LEFT, + IPT_JOYSTICK_RIGHT, + + // use IPT_JOYSTICKLEFT and IPT_JOYSTICKRIGHT for dual joystick panels + IPT_JOYSTICKRIGHT_UP, + IPT_JOYSTICKRIGHT_DOWN, + IPT_JOYSTICKRIGHT_LEFT, + IPT_JOYSTICKRIGHT_RIGHT, + IPT_JOYSTICKLEFT_UP, + IPT_JOYSTICKLEFT_DOWN, + IPT_JOYSTICKLEFT_LEFT, + IPT_JOYSTICKLEFT_RIGHT, + + IPT_DIGITAL_JOYSTICK_LAST, + + // action buttons + IPT_BUTTON1, + IPT_BUTTON2, + IPT_BUTTON3, + IPT_BUTTON4, + IPT_BUTTON5, + IPT_BUTTON6, + IPT_BUTTON7, + IPT_BUTTON8, + IPT_BUTTON9, + IPT_BUTTON10, + IPT_BUTTON11, + IPT_BUTTON12, + IPT_BUTTON13, + IPT_BUTTON14, + IPT_BUTTON15, + IPT_BUTTON16, + + // mahjong inputs + IPT_MAHJONG_FIRST, + + IPT_MAHJONG_A, + IPT_MAHJONG_B, + IPT_MAHJONG_C, + IPT_MAHJONG_D, + IPT_MAHJONG_E, + IPT_MAHJONG_F, + IPT_MAHJONG_G, + IPT_MAHJONG_H, + IPT_MAHJONG_I, + IPT_MAHJONG_J, + IPT_MAHJONG_K, + IPT_MAHJONG_L, + IPT_MAHJONG_M, + IPT_MAHJONG_N, + IPT_MAHJONG_O, + IPT_MAHJONG_P, + IPT_MAHJONG_Q, + IPT_MAHJONG_KAN, + IPT_MAHJONG_PON, + IPT_MAHJONG_CHI, + IPT_MAHJONG_REACH, + IPT_MAHJONG_RON, + IPT_MAHJONG_FLIP_FLOP, + IPT_MAHJONG_BET, + IPT_MAHJONG_SCORE, + IPT_MAHJONG_DOUBLE_UP, + IPT_MAHJONG_BIG, + IPT_MAHJONG_SMALL, + IPT_MAHJONG_LAST_CHANCE, + + IPT_MAHJONG_LAST, + + // hanafuda inputs + IPT_HANAFUDA_FIRST, + + IPT_HANAFUDA_A, + IPT_HANAFUDA_B, + IPT_HANAFUDA_C, + IPT_HANAFUDA_D, + IPT_HANAFUDA_E, + IPT_HANAFUDA_F, + IPT_HANAFUDA_G, + IPT_HANAFUDA_H, + IPT_HANAFUDA_YES, + IPT_HANAFUDA_NO, + + IPT_HANAFUDA_LAST, + + // gambling inputs + IPT_GAMBLING_FIRST, + + IPT_GAMBLE_KEYIN, // attendant + IPT_GAMBLE_KEYOUT, // attendant + IPT_GAMBLE_SERVICE, // attendant + IPT_GAMBLE_BOOK, // attendant + IPT_GAMBLE_DOOR, // attendant + // IPT_GAMBLE_DOOR2, // many gambling games have several doors. + // IPT_GAMBLE_DOOR3, + // IPT_GAMBLE_DOOR4, + // IPT_GAMBLE_DOOR5, + + IPT_GAMBLE_PAYOUT, // player + IPT_GAMBLE_BET, // player + IPT_GAMBLE_DEAL, // player + IPT_GAMBLE_STAND, // player + IPT_GAMBLE_TAKE, // player + IPT_GAMBLE_D_UP, // player + IPT_GAMBLE_HALF, // player + IPT_GAMBLE_HIGH, // player + IPT_GAMBLE_LOW, // player + + // poker-specific inputs + IPT_POKER_HOLD1, + IPT_POKER_HOLD2, + IPT_POKER_HOLD3, + IPT_POKER_HOLD4, + IPT_POKER_HOLD5, + IPT_POKER_CANCEL, + + // slot-specific inputs + IPT_SLOT_STOP1, + IPT_SLOT_STOP2, + IPT_SLOT_STOP3, + IPT_SLOT_STOP4, + IPT_SLOT_STOP_ALL, + + IPT_GAMBLING_LAST, + + // analog inputs + IPT_ANALOG_FIRST, + + IPT_ANALOG_ABSOLUTE_FIRST, + + IPT_AD_STICK_X, // absolute // autocenter + IPT_AD_STICK_Y, // absolute // autocenter + IPT_AD_STICK_Z, // absolute // autocenter + IPT_PADDLE, // absolute // autocenter + IPT_PADDLE_V, // absolute // autocenter + IPT_PEDAL, // absolute // autocenter + IPT_PEDAL2, // absolute // autocenter + IPT_PEDAL3, // absolute // autocenter + IPT_LIGHTGUN_X, // absolute + IPT_LIGHTGUN_Y, // absolute + IPT_POSITIONAL, // absolute // autocenter if not wraps + IPT_POSITIONAL_V, // absolute // autocenter if not wraps + + IPT_ANALOG_ABSOLUTE_LAST, + + IPT_DIAL, // relative + IPT_DIAL_V, // relative + IPT_TRACKBALL_X, // relative + IPT_TRACKBALL_Y, // relative + IPT_MOUSE_X, // relative + IPT_MOUSE_Y, // relative + + IPT_ANALOG_LAST, + + // analog adjuster support + IPT_ADJUSTER, + + // the following are special codes for user interface handling - not to be used by drivers! + IPT_UI_FIRST, + + IPT_UI_MENU, + IPT_UI_SELECT, + IPT_UI_BACK, + IPT_UI_CANCEL, + IPT_UI_CLEAR, + IPT_UI_HELP, + IPT_UI_UP, + IPT_UI_DOWN, + IPT_UI_LEFT, + IPT_UI_RIGHT, + IPT_UI_HOME, + IPT_UI_END, + IPT_UI_PAGE_UP, + IPT_UI_PAGE_DOWN, + IPT_UI_PREV_GROUP, + IPT_UI_NEXT_GROUP, + IPT_UI_ON_SCREEN_DISPLAY, + IPT_UI_TOGGLE_UI, + IPT_UI_DEBUG_BREAK, + IPT_UI_PAUSE, + IPT_UI_PAUSE_SINGLE, + IPT_UI_REWIND_SINGLE, + IPT_UI_SAVE_STATE, + IPT_UI_SAVE_STATE_QUICK, + IPT_UI_LOAD_STATE, + IPT_UI_LOAD_STATE_QUICK, + IPT_UI_RESET_MACHINE, + IPT_UI_SOFT_RESET, + IPT_UI_SHOW_GFX, + IPT_UI_FRAMESKIP_DEC, + IPT_UI_FRAMESKIP_INC, + IPT_UI_THROTTLE, + IPT_UI_FAST_FORWARD, + IPT_UI_SHOW_FPS, + IPT_UI_SNAPSHOT, + IPT_UI_RECORD_MNG, + IPT_UI_RECORD_AVI, + IPT_UI_TOGGLE_CHEAT, + IPT_UI_DISPLAY_COMMENT, + IPT_UI_ZOOM_IN, + IPT_UI_ZOOM_OUT, + IPT_UI_ZOOM_DEFAULT, + IPT_UI_ROTATE, + IPT_UI_SHOW_PROFILER, + IPT_UI_RELEASE_POINTER, + IPT_UI_PASTE, + IPT_UI_TAPE_START, + IPT_UI_TAPE_STOP, + IPT_UI_FOCUS_NEXT, + IPT_UI_FOCUS_PREV, + IPT_UI_DATS, + IPT_UI_FAVORITES, + IPT_UI_EXPORT, + IPT_UI_AUDIT, + + // additional OSD-specified UI port types (up to 16) + IPT_OSD_1, + IPT_OSD_2, + IPT_OSD_3, + IPT_OSD_4, + IPT_OSD_5, + IPT_OSD_6, + IPT_OSD_7, + IPT_OSD_8, + IPT_OSD_9, + IPT_OSD_10, + IPT_OSD_11, + IPT_OSD_12, + IPT_OSD_13, + IPT_OSD_14, + IPT_OSD_15, + IPT_OSD_16, + + IPT_UI_LAST, + + IPT_OTHER, // not mapped to standard defaults + + IPT_SPECIAL, // uninterpreted characters + IPT_CUSTOM, // handled by custom code + IPT_OUTPUT, + + IPT_COUNT, + + // aliases for some types + IPT_PADDLE_H = IPT_PADDLE, + IPT_PEDAL1 = IPT_PEDAL, + IPT_POSITIONAL_H = IPT_POSITIONAL, + IPT_DIAL_H = IPT_DIAL +}; + +DECLARE_ENUM_INCDEC_OPERATORS(ioport_type) + + +// sequence types for input_port_seq() call +enum input_seq_type : int +{ + SEQ_TYPE_INVALID = -1, + SEQ_TYPE_STANDARD = 0, + SEQ_TYPE_INCREMENT, + SEQ_TYPE_DECREMENT, + SEQ_TYPE_TOTAL +}; + +DECLARE_ENUM_INCDEC_OPERATORS(input_seq_type) + +#endif // MAME_EMU_INPTTYPE_H diff --git a/src/emu/inpttype.ipp b/src/emu/inpttype.ipp index fc4ca40b8d4..8c217a1d39c 100644 --- a/src/emu/inpttype.ipp +++ b/src/emu/inpttype.ipp @@ -19,36 +19,36 @@ namespace { #define CORE_INPUT_TYPES_P1 \ CORE_INPUT_TYPES_BEGIN(p1) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_RIGHT, N_p("input-name", "%p Right Stick/Right"), input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_BUTTON4_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_UP, N_p("input-name", "%p Left Stick/Up"), input_seq(KEYCODE_E, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq(KEYCODE_S, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(KEYCODE_LCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0), input_seq::or_code, MOUSECODE_BUTTON1_INDEXED(0), input_seq::or_code, GUNCODE_BUTTON1_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(KEYCODE_LALT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(0), input_seq::or_code, MOUSECODE_BUTTON3_INDEXED(0), input_seq::or_code, GUNCODE_BUTTON2_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(KEYCODE_SPACE, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(0), input_seq::or_code, MOUSECODE_BUTTON2_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(KEYCODE_LSHIFT, input_seq::or_code, JOYCODE_BUTTON4_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(KEYCODE_Z, input_seq::or_code, JOYCODE_BUTTON5_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(KEYCODE_X, input_seq::or_code, JOYCODE_BUTTON6_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(KEYCODE_C, input_seq::or_code, JOYCODE_BUTTON7_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(KEYCODE_V, input_seq::or_code, JOYCODE_BUTTON8_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(KEYCODE_B, input_seq::or_code, JOYCODE_BUTTON9_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(KEYCODE_N, input_seq::or_code, JOYCODE_BUTTON10_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(KEYCODE_M, input_seq::or_code, JOYCODE_BUTTON11_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(KEYCODE_COMMA, input_seq::or_code, JOYCODE_BUTTON12_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(KEYCODE_STOP, input_seq::or_code, JOYCODE_BUTTON13_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(KEYCODE_SLASH, input_seq::or_code, JOYCODE_BUTTON14_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(KEYCODE_RSHIFT, input_seq::or_code, JOYCODE_BUTTON15_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, START, N_p("input-name", "%p Start"), input_seq(KEYCODE_1, input_seq::or_code, JOYCODE_START_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, SELECT, N_p("input-name", "%p Select"), input_seq(KEYCODE_5, input_seq::or_code, JOYCODE_SELECT_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(KEYCODE_UP) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(KEYCODE_DOWN) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(KEYCODE_LEFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(KEYCODE_RIGHT) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq(KEYCODE_I) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq(KEYCODE_K) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq(KEYCODE_J) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_RIGHT, N_p("input-name", "%p Right Stick/Right"), input_seq(KEYCODE_L) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_UP, N_p("input-name", "%p Left Stick/Up"), input_seq(KEYCODE_E) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq(KEYCODE_D) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq(KEYCODE_S) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq(KEYCODE_F) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(KEYCODE_LCONTROL, input_seq::or_code, MOUSECODE_BUTTON1_INDEXED(0), input_seq::or_code, GUNCODE_BUTTON1_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(KEYCODE_LALT, input_seq::or_code, MOUSECODE_BUTTON3_INDEXED(0), input_seq::or_code, GUNCODE_BUTTON2_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(KEYCODE_SPACE, input_seq::or_code, MOUSECODE_BUTTON2_INDEXED(0)) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(KEYCODE_LSHIFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(KEYCODE_Z) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(KEYCODE_X) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(KEYCODE_C) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(KEYCODE_V) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(KEYCODE_B) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(KEYCODE_N) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(KEYCODE_M) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(KEYCODE_COMMA) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(KEYCODE_STOP) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(KEYCODE_SLASH) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(KEYCODE_RSHIFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON16, N_p("input-name", "%p Button 16"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, START, N_p("input-name", "%p Start"), input_seq(KEYCODE_1) ) \ + INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, SELECT, N_p("input-name", "%p Select"), input_seq(KEYCODE_5) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P1_MAHJONG \ @@ -137,10 +137,10 @@ namespace { #define CORE_INPUT_TYPES_P2 \ CORE_INPUT_TYPES_BEGIN(p2) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(KEYCODE_R, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(KEYCODE_G, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(KEYCODE_R) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(KEYCODE_F) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(KEYCODE_D) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(KEYCODE_G) ) \ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ @@ -149,24 +149,24 @@ namespace { INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(KEYCODE_A, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(1), input_seq::or_code, MOUSECODE_BUTTON1_INDEXED(1), input_seq::or_code, GUNCODE_BUTTON1_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(KEYCODE_S, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(1), input_seq::or_code, MOUSECODE_BUTTON3_INDEXED(1), input_seq::or_code, GUNCODE_BUTTON2_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(KEYCODE_Q, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(1), input_seq::or_code, MOUSECODE_BUTTON2_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(KEYCODE_W, input_seq::or_code, JOYCODE_BUTTON4_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(KEYCODE_E, input_seq::or_code, JOYCODE_BUTTON5_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, START, N_p("input-name", "%p Start"), input_seq(KEYCODE_2, input_seq::or_code, JOYCODE_START_INDEXED(1)) ) \ - INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, SELECT, N_p("input-name", "%p Select"), input_seq(KEYCODE_6, input_seq::or_code, JOYCODE_SELECT_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(KEYCODE_A, input_seq::or_code, MOUSECODE_BUTTON1_INDEXED(1), input_seq::or_code, GUNCODE_BUTTON1_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(KEYCODE_S, input_seq::or_code, MOUSECODE_BUTTON3_INDEXED(1), input_seq::or_code, GUNCODE_BUTTON2_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(KEYCODE_Q, input_seq::or_code, MOUSECODE_BUTTON2_INDEXED(1)) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(KEYCODE_W) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(KEYCODE_E) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON6, N_p("input-name", "%p Button 6"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON7, N_p("input-name", "%p Button 7"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON8, N_p("input-name", "%p Button 8"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON9, N_p("input-name", "%p Button 9"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON10, N_p("input-name", "%p Button 10"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON11, N_p("input-name", "%p Button 11"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON12, N_p("input-name", "%p Button 12"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON13, N_p("input-name", "%p Button 13"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON14, N_p("input-name", "%p Button 14"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON15, N_p("input-name", "%p Button 15"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON16, N_p("input-name", "%p Button 16"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, START, N_p("input-name", "%p Start"), input_seq(KEYCODE_2) ) \ + INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, SELECT, N_p("input-name", "%p Select"), input_seq(KEYCODE_6) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P2_MAHJONG \ @@ -218,10 +218,10 @@ namespace { #define CORE_INPUT_TYPES_P3 \ CORE_INPUT_TYPES_BEGIN(p3) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(KEYCODE_I) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(KEYCODE_K) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(KEYCODE_J) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(KEYCODE_L) ) \ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ @@ -230,24 +230,24 @@ namespace { INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(KEYCODE_RCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(2), input_seq::or_code, GUNCODE_BUTTON1_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(KEYCODE_RSHIFT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(2), input_seq::or_code, GUNCODE_BUTTON2_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(KEYCODE_ENTER, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, START, N_p("input-name", "%p Start"), input_seq(KEYCODE_3, input_seq::or_code, JOYCODE_START_INDEXED(2)) ) \ - INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, SELECT, N_p("input-name", "%p Select"), input_seq(KEYCODE_7, input_seq::or_code, JOYCODE_SELECT_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(KEYCODE_RCONTROL, input_seq::or_code, GUNCODE_BUTTON1_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(KEYCODE_RSHIFT, input_seq::or_code, GUNCODE_BUTTON2_INDEXED(2)) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(KEYCODE_ENTER) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON4, N_p("input-name", "%p Button 4"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON5, N_p("input-name", "%p Button 5"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON6, N_p("input-name", "%p Button 6"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON7, N_p("input-name", "%p Button 7"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON8, N_p("input-name", "%p Button 8"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON9, N_p("input-name", "%p Button 9"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON10, N_p("input-name", "%p Button 10"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON11, N_p("input-name", "%p Button 11"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON12, N_p("input-name", "%p Button 12"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON13, N_p("input-name", "%p Button 13"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON14, N_p("input-name", "%p Button 14"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON15, N_p("input-name", "%p Button 15"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON16, N_p("input-name", "%p Button 16"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, START, N_p("input-name", "%p Start"), input_seq(KEYCODE_3) ) \ + INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, SELECT, N_p("input-name", "%p Select"), input_seq(KEYCODE_7) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P3_MAHJONG \ @@ -285,10 +285,10 @@ namespace { #define CORE_INPUT_TYPES_P4 \ CORE_INPUT_TYPES_BEGIN(p4) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(KEYCODE_8_PAD, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(KEYCODE_2_PAD, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(KEYCODE_4_PAD, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(KEYCODE_6_PAD, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(KEYCODE_8_PAD) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(KEYCODE_2_PAD) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(KEYCODE_4_PAD) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(KEYCODE_6_PAD) ) \ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ @@ -297,24 +297,24 @@ namespace { INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(KEYCODE_0_PAD, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(KEYCODE_DEL_PAD, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(KEYCODE_ENTER_PAD, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, START, N_p("input-name", "%p Start"), input_seq(KEYCODE_4, input_seq::or_code, JOYCODE_START_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, SELECT, N_p("input-name", "%p Select"), input_seq(KEYCODE_8, input_seq::or_code, JOYCODE_SELECT_INDEXED(3)) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(KEYCODE_0_PAD) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(KEYCODE_DEL_PAD) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(KEYCODE_ENTER_PAD) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON4, N_p("input-name", "%p Button 4"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON5, N_p("input-name", "%p Button 5"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON6, N_p("input-name", "%p Button 6"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON7, N_p("input-name", "%p Button 7"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON8, N_p("input-name", "%p Button 8"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON9, N_p("input-name", "%p Button 9"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON10, N_p("input-name", "%p Button 10"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON11, N_p("input-name", "%p Button 11"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON12, N_p("input-name", "%p Button 12"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON13, N_p("input-name", "%p Button 13"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON14, N_p("input-name", "%p Button 14"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON15, N_p("input-name", "%p Button 15"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON16, N_p("input-name", "%p Button 16"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, START, N_p("input-name", "%p Start"), input_seq(KEYCODE_4) ) \ + INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, SELECT, N_p("input-name", "%p Select"), input_seq(KEYCODE_8) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P4_MAHJONG \ @@ -352,10 +352,10 @@ namespace { #define CORE_INPUT_TYPES_P5 \ CORE_INPUT_TYPES_BEGIN(p5) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ @@ -364,32 +364,32 @@ namespace { INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(4)) ) \ - INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON1, N_p("input-name", "%p Button 1"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON2, N_p("input-name", "%p Button 2"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON3, N_p("input-name", "%p Button 3"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON4, N_p("input-name", "%p Button 4"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON5, N_p("input-name", "%p Button 5"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON6, N_p("input-name", "%p Button 6"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON7, N_p("input-name", "%p Button 7"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON8, N_p("input-name", "%p Button 8"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON9, N_p("input-name", "%p Button 9"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON10, N_p("input-name", "%p Button 10"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON11, N_p("input-name", "%p Button 11"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON12, N_p("input-name", "%p Button 12"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON13, N_p("input-name", "%p Button 13"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON14, N_p("input-name", "%p Button 14"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON15, N_p("input-name", "%p Button 15"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON16, N_p("input-name", "%p Button 16"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, START, N_p("input-name", "%p Start"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, SELECT, N_p("input-name", "%p Select"), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P6 \ CORE_INPUT_TYPES_BEGIN(p6) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ @@ -398,32 +398,32 @@ namespace { INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(5)) ) \ - INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON1, N_p("input-name", "%p Button 1"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON2, N_p("input-name", "%p Button 2"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON3, N_p("input-name", "%p Button 3"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON4, N_p("input-name", "%p Button 4"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON5, N_p("input-name", "%p Button 5"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON6, N_p("input-name", "%p Button 6"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON7, N_p("input-name", "%p Button 7"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON8, N_p("input-name", "%p Button 8"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON9, N_p("input-name", "%p Button 9"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON10, N_p("input-name", "%p Button 10"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON11, N_p("input-name", "%p Button 11"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON12, N_p("input-name", "%p Button 12"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON13, N_p("input-name", "%p Button 13"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON14, N_p("input-name", "%p Button 14"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON15, N_p("input-name", "%p Button 15"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON16, N_p("input-name", "%p Button 16"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, START, N_p("input-name", "%p Start"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, SELECT, N_p("input-name", "%p Select"), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P7 \ CORE_INPUT_TYPES_BEGIN(p7) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ @@ -432,32 +432,32 @@ namespace { INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(6)) ) \ - INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON1, N_p("input-name", "%p Button 1"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON2, N_p("input-name", "%p Button 2"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON3, N_p("input-name", "%p Button 3"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON4, N_p("input-name", "%p Button 4"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON5, N_p("input-name", "%p Button 5"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON6, N_p("input-name", "%p Button 6"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON7, N_p("input-name", "%p Button 7"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON8, N_p("input-name", "%p Button 8"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON9, N_p("input-name", "%p Button 9"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON10, N_p("input-name", "%p Button 10"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON11, N_p("input-name", "%p Button 11"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON12, N_p("input-name", "%p Button 12"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON13, N_p("input-name", "%p Button 13"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON14, N_p("input-name", "%p Button 14"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON15, N_p("input-name", "%p Button 15"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON16, N_p("input-name", "%p Button 16"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, START, N_p("input-name", "%p Start"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, SELECT, N_p("input-name", "%p Select"), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P8 \ CORE_INPUT_TYPES_BEGIN(p8) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ @@ -466,32 +466,32 @@ namespace { INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(7)) ) \ - INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(7)) ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON1, N_p("input-name", "%p Button 1"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON2, N_p("input-name", "%p Button 2"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON3, N_p("input-name", "%p Button 3"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON4, N_p("input-name", "%p Button 4"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON5, N_p("input-name", "%p Button 5"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON6, N_p("input-name", "%p Button 6"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON7, N_p("input-name", "%p Button 7"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON8, N_p("input-name", "%p Button 8"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON9, N_p("input-name", "%p Button 9"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON10, N_p("input-name", "%p Button 10"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON11, N_p("input-name", "%p Button 11"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON12, N_p("input-name", "%p Button 12"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON13, N_p("input-name", "%p Button 13"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON14, N_p("input-name", "%p Button 14"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON15, N_p("input-name", "%p Button 15"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON16, N_p("input-name", "%p Button 16"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, START, N_p("input-name", "%p Start"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, SELECT, N_p("input-name", "%p Select"), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P9 \ CORE_INPUT_TYPES_BEGIN(p9) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ @@ -500,32 +500,32 @@ namespace { INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(8)) ) \ - INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(8)) ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON1, N_p("input-name", "%p Button 1"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON2, N_p("input-name", "%p Button 2"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON3, N_p("input-name", "%p Button 3"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON4, N_p("input-name", "%p Button 4"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON5, N_p("input-name", "%p Button 5"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON6, N_p("input-name", "%p Button 6"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON7, N_p("input-name", "%p Button 7"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON8, N_p("input-name", "%p Button 8"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON9, N_p("input-name", "%p Button 9"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON10, N_p("input-name", "%p Button 10"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON11, N_p("input-name", "%p Button 11"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON12, N_p("input-name", "%p Button 12"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON13, N_p("input-name", "%p Button 13"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON14, N_p("input-name", "%p Button 14"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON15, N_p("input-name", "%p Button 15"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, BUTTON16, N_p("input-name", "%p Button 16"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, START, N_p("input-name", "%p Start"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 9, PLAYER9, SELECT, N_p("input-name", "%p Select"), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_P10 \ CORE_INPUT_TYPES_BEGIN(p10) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_UP, N_p("input-name", "%p Up"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_DOWN, N_p("input-name", "%p Down"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_LEFT, N_p("input-name", "%p Left"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICK_RIGHT, N_p("input-name", "%p Right"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKRIGHT_UP, N_p("input-name", "%p Right Stick/Up"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKRIGHT_DOWN, N_p("input-name", "%p Right Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKRIGHT_LEFT, N_p("input-name", "%p Right Stick/Left"), input_seq() ) \ @@ -534,22 +534,22 @@ namespace { INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKLEFT_DOWN, N_p("input-name", "%p Left Stick/Down"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKLEFT_LEFT, N_p("input-name", "%p Left Stick/Left"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, JOYSTICKLEFT_RIGHT, N_p("input-name", "%p Left Stick/Right"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON1, N_p("input-name", "%p Button 1"), input_seq(JOYCODE_BUTTON1_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON2, N_p("input-name", "%p Button 2"), input_seq(JOYCODE_BUTTON2_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON3, N_p("input-name", "%p Button 3"), input_seq(JOYCODE_BUTTON3_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON4, N_p("input-name", "%p Button 4"), input_seq(JOYCODE_BUTTON4_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON5, N_p("input-name", "%p Button 5"), input_seq(JOYCODE_BUTTON5_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON6, N_p("input-name", "%p Button 6"), input_seq(JOYCODE_BUTTON6_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON7, N_p("input-name", "%p Button 7"), input_seq(JOYCODE_BUTTON7_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON8, N_p("input-name", "%p Button 8"), input_seq(JOYCODE_BUTTON8_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON9, N_p("input-name", "%p Button 9"), input_seq(JOYCODE_BUTTON9_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON10, N_p("input-name", "%p Button 10"), input_seq(JOYCODE_BUTTON10_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON11, N_p("input-name", "%p Button 11"), input_seq(JOYCODE_BUTTON11_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON12, N_p("input-name", "%p Button 12"), input_seq(JOYCODE_BUTTON12_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON13, N_p("input-name", "%p Button 13"), input_seq(JOYCODE_BUTTON13_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON14, N_p("input-name", "%p Button 14"), input_seq(JOYCODE_BUTTON14_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON15, N_p("input-name", "%p Button 15"), input_seq(JOYCODE_BUTTON15_INDEXED(9)) ) \ - INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON16, N_p("input-name", "%p Button 16"), input_seq(JOYCODE_BUTTON16_INDEXED(9)) ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON1, N_p("input-name", "%p Button 1"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON2, N_p("input-name", "%p Button 2"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON3, N_p("input-name", "%p Button 3"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON4, N_p("input-name", "%p Button 4"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON5, N_p("input-name", "%p Button 5"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON6, N_p("input-name", "%p Button 6"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON7, N_p("input-name", "%p Button 7"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON8, N_p("input-name", "%p Button 8"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON9, N_p("input-name", "%p Button 9"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON10, N_p("input-name", "%p Button 10"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON11, N_p("input-name", "%p Button 11"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON12, N_p("input-name", "%p Button 12"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON13, N_p("input-name", "%p Button 13"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON14, N_p("input-name", "%p Button 14"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON15, N_p("input-name", "%p Button 15"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, BUTTON16, N_p("input-name", "%p Button 16"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, START, N_p("input-name", "%p Start"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 10, PLAYER10, SELECT, N_p("input-name", "%p Select"), input_seq() ) \ CORE_INPUT_TYPES_END() @@ -560,10 +560,10 @@ namespace { INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START2, N_p("input-name", "2 Players Start"), input_seq(KEYCODE_2, input_seq::or_code, JOYCODE_START_INDEXED(1)) ) \ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START3, N_p("input-name", "3 Players Start"), input_seq(KEYCODE_3, input_seq::or_code, JOYCODE_START_INDEXED(2)) ) \ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START4, N_p("input-name", "4 Players Start"), input_seq(KEYCODE_4, input_seq::or_code, JOYCODE_START_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START5, N_p("input-name", "5 Players Start"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START6, N_p("input-name", "6 Players Start"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START7, N_p("input-name", "7 Players Start"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START8, N_p("input-name", "8 Players Start"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START5, N_p("input-name", "5 Players Start"), input_seq(JOYCODE_START_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START6, N_p("input-name", "6 Players Start"), input_seq(JOYCODE_START_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START7, N_p("input-name", "7 Players Start"), input_seq(JOYCODE_START_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START8, N_p("input-name", "8 Players Start"), input_seq(JOYCODE_START_INDEXED(7)) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_COIN \ @@ -572,15 +572,15 @@ namespace { INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN2, N_p("input-name", "Coin 2"), input_seq(KEYCODE_6, input_seq::or_code, JOYCODE_SELECT_INDEXED(1)) ) \ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN3, N_p("input-name", "Coin 3"), input_seq(KEYCODE_7, input_seq::or_code, JOYCODE_SELECT_INDEXED(2)) ) \ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN4, N_p("input-name", "Coin 4"), input_seq(KEYCODE_8, input_seq::or_code, JOYCODE_SELECT_INDEXED(3)) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN5, N_p("input-name", "Coin 5"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN6, N_p("input-name", "Coin 6"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN7, N_p("input-name", "Coin 7"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN8, N_p("input-name", "Coin 8"), input_seq() ) \ + INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN5, N_p("input-name", "Coin 5"), input_seq(JOYCODE_SELECT_INDEXED(4)) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN6, N_p("input-name", "Coin 6"), input_seq(JOYCODE_SELECT_INDEXED(5)) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN7, N_p("input-name", "Coin 7"), input_seq(JOYCODE_SELECT_INDEXED(6)) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN8, N_p("input-name", "Coin 8"), input_seq(JOYCODE_SELECT_INDEXED(7)) ) \ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN9, N_p("input-name", "Coin 9"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN10, N_p("input-name", "Coin 10"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN11, N_p("input-name", "Coin 11"), input_seq() ) \ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN12, N_p("input-name", "Coin 12"), input_seq() ) \ - INPUT_PORT_DIGITAL_TYPE( 0, OTHER, BILL1, N_p("input-name", "Bill 1"), input_seq(KEYCODE_BACKSPACE) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, OTHER, BILL1, N_p("input-name", "Banknote 1"), input_seq(KEYCODE_BACKSPACE) ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_SERVICE \ @@ -613,226 +613,226 @@ namespace { #define CORE_INPUT_TYPES_PEDAL \ CORE_INPUT_TYPES_BEGIN(pedal) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(0)), input_seq(), input_seq(KEYCODE_LCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0)) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(1)), input_seq(), input_seq(KEYCODE_A, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(1)) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(2)), input_seq(), input_seq(KEYCODE_RCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(2)) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(3)), input_seq(), input_seq(KEYCODE_0_PAD, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(3)) ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(4)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(4)) ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(5)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(5)) ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(6)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(6)) ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(7)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(7)) ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(8)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(8)) ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(JOYCODE_Z_NEG_ABSOLUTE_INDEXED(9)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(9)) ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(), input_seq(), input_seq(KEYCODE_LCONTROL) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(), input_seq(), input_seq(KEYCODE_A) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(), input_seq(), input_seq(KEYCODE_RCONTROL) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(), input_seq(), input_seq(KEYCODE_0_PAD) ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PEDAL, N_p("input-name", "%p Pedal 1"), input_seq(), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_PEDAL2 \ CORE_INPUT_TYPES_BEGIN(pedal2) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(0)), input_seq(), input_seq(KEYCODE_LALT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(0)) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(1)), input_seq(), input_seq(KEYCODE_S, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(1)) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(2)), input_seq(), input_seq(KEYCODE_RSHIFT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(2)) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(3)), input_seq(), input_seq(KEYCODE_DEL_PAD, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(3)) ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(4)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(4)) ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(5)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(5)) ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(6)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(6)) ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(7)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(7)) ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(8)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(8)) ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(JOYCODE_W_NEG_ABSOLUTE_INDEXED(9)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(9)) ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(), input_seq(), input_seq(KEYCODE_LALT) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(), input_seq(), input_seq(KEYCODE_S) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(), input_seq(), input_seq(KEYCODE_RSHIFT) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(), input_seq(), input_seq(KEYCODE_DEL_PAD) ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PEDAL2, N_p("input-name", "%p Pedal 2"), input_seq(), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_PEDAL3 \ CORE_INPUT_TYPES_BEGIN(pedal3) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_SPACE, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(0)) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_Q, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(1)) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_ENTER, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(2)) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_ENTER_PAD, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(3)) ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(4)) ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(5)) ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(6)) ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(7)) ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(8)) ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(9)) ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_SPACE) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_Q) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_ENTER) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq(KEYCODE_ENTER_PAD) ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PEDAL3, N_p("input-name", "%p Pedal 3"), input_seq(), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_PADDLE \ CORE_INPUT_TYPES_BEGIN(paddle) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PADDLE, N_p("input-name", "Paddle"), input_seq(JOYCODE_X_INDEXED(0), input_seq::or_code, MOUSECODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT), input_seq(KEYCODE_RIGHT) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PADDLE, N_p("input-name", "Paddle 2"), input_seq(JOYCODE_X_INDEXED(1), input_seq::or_code, MOUSECODE_X_INDEXED(1)), input_seq(KEYCODE_D), input_seq(KEYCODE_G) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PADDLE, N_p("input-name", "Paddle 3"), input_seq(JOYCODE_X_INDEXED(2), input_seq::or_code, MOUSECODE_X_INDEXED(2)), input_seq(KEYCODE_J), input_seq(KEYCODE_L) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PADDLE, N_p("input-name", "Paddle 4"), input_seq(JOYCODE_X_INDEXED(3), input_seq::or_code, MOUSECODE_X_INDEXED(3)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PADDLE, N_p("input-name", "Paddle 5"), input_seq(JOYCODE_X_INDEXED(4), input_seq::or_code, MOUSECODE_X_INDEXED(4)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PADDLE, N_p("input-name", "Paddle 6"), input_seq(JOYCODE_X_INDEXED(5), input_seq::or_code, MOUSECODE_X_INDEXED(5)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PADDLE, N_p("input-name", "Paddle 7"), input_seq(JOYCODE_X_INDEXED(6), input_seq::or_code, MOUSECODE_X_INDEXED(6)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PADDLE, N_p("input-name", "Paddle 8"), input_seq(JOYCODE_X_INDEXED(7), input_seq::or_code, MOUSECODE_X_INDEXED(7)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PADDLE, N_p("input-name", "Paddle 9"), input_seq(JOYCODE_X_INDEXED(8), input_seq::or_code, MOUSECODE_X_INDEXED(8)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PADDLE, N_p("input-name", "Paddle 10"), input_seq(JOYCODE_X_INDEXED(9), input_seq::or_code, MOUSECODE_X_INDEXED(9)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PADDLE, N_p("input-name", "Paddle"), input_seq(MOUSECODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT), input_seq(KEYCODE_RIGHT) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PADDLE, N_p("input-name", "Paddle 2"), input_seq(MOUSECODE_X_INDEXED(1)), input_seq(KEYCODE_D), input_seq(KEYCODE_G) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PADDLE, N_p("input-name", "Paddle 3"), input_seq(MOUSECODE_X_INDEXED(2)), input_seq(KEYCODE_J), input_seq(KEYCODE_L) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PADDLE, N_p("input-name", "Paddle 4"), input_seq(MOUSECODE_X_INDEXED(3)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PADDLE, N_p("input-name", "Paddle 5"), input_seq(MOUSECODE_X_INDEXED(4)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PADDLE, N_p("input-name", "Paddle 6"), input_seq(MOUSECODE_X_INDEXED(5)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PADDLE, N_p("input-name", "Paddle 7"), input_seq(MOUSECODE_X_INDEXED(6)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PADDLE, N_p("input-name", "Paddle 8"), input_seq(MOUSECODE_X_INDEXED(7)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PADDLE, N_p("input-name", "Paddle 9"), input_seq(MOUSECODE_X_INDEXED(8)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PADDLE, N_p("input-name", "Paddle 10"), input_seq(MOUSECODE_X_INDEXED(9)), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_PADDLE_V \ CORE_INPUT_TYPES_BEGIN(paddle_v) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PADDLE_V, N_p("input-name", "Paddle V"), input_seq(JOYCODE_Y_INDEXED(0), input_seq::or_code, MOUSECODE_Y_INDEXED(0)), input_seq(KEYCODE_UP), input_seq(KEYCODE_DOWN) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PADDLE_V, N_p("input-name", "Paddle V 2"), input_seq(JOYCODE_Y_INDEXED(1), input_seq::or_code, MOUSECODE_Y_INDEXED(1)), input_seq(KEYCODE_R), input_seq(KEYCODE_F) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PADDLE_V, N_p("input-name", "Paddle V 3"), input_seq(JOYCODE_Y_INDEXED(2), input_seq::or_code, MOUSECODE_Y_INDEXED(2)), input_seq(KEYCODE_I), input_seq(KEYCODE_K) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PADDLE_V, N_p("input-name", "Paddle V 4"), input_seq(JOYCODE_Y_INDEXED(3), input_seq::or_code, MOUSECODE_Y_INDEXED(3)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PADDLE_V, N_p("input-name", "Paddle V 5"), input_seq(JOYCODE_Y_INDEXED(4), input_seq::or_code, MOUSECODE_Y_INDEXED(4)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PADDLE_V, N_p("input-name", "Paddle V 6"), input_seq(JOYCODE_Y_INDEXED(5), input_seq::or_code, MOUSECODE_Y_INDEXED(5)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PADDLE_V, N_p("input-name", "Paddle V 7"), input_seq(JOYCODE_Y_INDEXED(6), input_seq::or_code, MOUSECODE_Y_INDEXED(6)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PADDLE_V, N_p("input-name", "Paddle V 8"), input_seq(JOYCODE_Y_INDEXED(7), input_seq::or_code, MOUSECODE_Y_INDEXED(7)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PADDLE_V, N_p("input-name", "Paddle V 9"), input_seq(JOYCODE_Y_INDEXED(8), input_seq::or_code, MOUSECODE_Y_INDEXED(8)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PADDLE_V, N_p("input-name", "Paddle V 10"), input_seq(JOYCODE_Y_INDEXED(9), input_seq::or_code, MOUSECODE_Y_INDEXED(9)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PADDLE_V, N_p("input-name", "Paddle V"), input_seq(MOUSECODE_Y_INDEXED(0)), input_seq(KEYCODE_UP), input_seq(KEYCODE_DOWN) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PADDLE_V, N_p("input-name", "Paddle V 2"), input_seq(MOUSECODE_Y_INDEXED(1)), input_seq(KEYCODE_R), input_seq(KEYCODE_F) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PADDLE_V, N_p("input-name", "Paddle V 3"), input_seq(MOUSECODE_Y_INDEXED(2)), input_seq(KEYCODE_I), input_seq(KEYCODE_K) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PADDLE_V, N_p("input-name", "Paddle V 4"), input_seq(MOUSECODE_Y_INDEXED(3)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PADDLE_V, N_p("input-name", "Paddle V 5"), input_seq(MOUSECODE_Y_INDEXED(4)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PADDLE_V, N_p("input-name", "Paddle V 6"), input_seq(MOUSECODE_Y_INDEXED(5)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PADDLE_V, N_p("input-name", "Paddle V 7"), input_seq(MOUSECODE_Y_INDEXED(6)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PADDLE_V, N_p("input-name", "Paddle V 8"), input_seq(MOUSECODE_Y_INDEXED(7)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, PADDLE_V, N_p("input-name", "Paddle V 9"), input_seq(MOUSECODE_Y_INDEXED(8)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, PADDLE_V, N_p("input-name", "Paddle V 10"), input_seq(MOUSECODE_Y_INDEXED(9)), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_POSITIONAL \ CORE_INPUT_TYPES_BEGIN(positional) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, POSITIONAL, N_p("input-name", "Positional"), input_seq(MOUSECODE_X_INDEXED(0), input_seq::or_code, JOYCODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT), input_seq(KEYCODE_RIGHT) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, POSITIONAL, N_p("input-name", "Positional 2"), input_seq(MOUSECODE_X_INDEXED(1), input_seq::or_code, JOYCODE_X_INDEXED(1)), input_seq(KEYCODE_D), input_seq(KEYCODE_G) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, POSITIONAL, N_p("input-name", "Positional 3"), input_seq(MOUSECODE_X_INDEXED(2), input_seq::or_code, JOYCODE_X_INDEXED(2)), input_seq(KEYCODE_J), input_seq(KEYCODE_L) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, POSITIONAL, N_p("input-name", "Positional 4"), input_seq(MOUSECODE_X_INDEXED(3), input_seq::or_code, JOYCODE_X_INDEXED(3)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, POSITIONAL, N_p("input-name", "Positional 5"), input_seq(MOUSECODE_X_INDEXED(4), input_seq::or_code, JOYCODE_X_INDEXED(4)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, POSITIONAL, N_p("input-name", "Positional 6"), input_seq(MOUSECODE_X_INDEXED(5), input_seq::or_code, JOYCODE_X_INDEXED(5)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, POSITIONAL, N_p("input-name", "Positional 7"), input_seq(MOUSECODE_X_INDEXED(6), input_seq::or_code, JOYCODE_X_INDEXED(6)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, POSITIONAL, N_p("input-name", "Positional 8"), input_seq(MOUSECODE_X_INDEXED(7), input_seq::or_code, JOYCODE_X_INDEXED(7)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, POSITIONAL, N_p("input-name", "Positional 9"), input_seq(MOUSECODE_X_INDEXED(8), input_seq::or_code, JOYCODE_X_INDEXED(8)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, POSITIONAL, N_p("input-name", "Positional 10"), input_seq(MOUSECODE_X_INDEXED(9), input_seq::or_code, JOYCODE_X_INDEXED(9)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, POSITIONAL, N_p("input-name", "Positional"), input_seq(MOUSECODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT), input_seq(KEYCODE_RIGHT) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, POSITIONAL, N_p("input-name", "Positional 2"), input_seq(MOUSECODE_X_INDEXED(1)), input_seq(KEYCODE_D), input_seq(KEYCODE_G) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, POSITIONAL, N_p("input-name", "Positional 3"), input_seq(MOUSECODE_X_INDEXED(2)), input_seq(KEYCODE_J), input_seq(KEYCODE_L) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, POSITIONAL, N_p("input-name", "Positional 4"), input_seq(MOUSECODE_X_INDEXED(3)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, POSITIONAL, N_p("input-name", "Positional 5"), input_seq(MOUSECODE_X_INDEXED(4)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, POSITIONAL, N_p("input-name", "Positional 6"), input_seq(MOUSECODE_X_INDEXED(5)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, POSITIONAL, N_p("input-name", "Positional 7"), input_seq(MOUSECODE_X_INDEXED(6)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, POSITIONAL, N_p("input-name", "Positional 8"), input_seq(MOUSECODE_X_INDEXED(7)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, POSITIONAL, N_p("input-name", "Positional 9"), input_seq(MOUSECODE_X_INDEXED(8)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, POSITIONAL, N_p("input-name", "Positional 10"), input_seq(MOUSECODE_X_INDEXED(9)), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_POSITIONAL_V \ CORE_INPUT_TYPES_BEGIN(positional_v) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, POSITIONAL_V, N_p("input-name", "Positional V"), input_seq(MOUSECODE_Y_INDEXED(0), input_seq::or_code, JOYCODE_Y_INDEXED(0)), input_seq(KEYCODE_UP), input_seq(KEYCODE_DOWN) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, POSITIONAL_V, N_p("input-name", "Positional V 2"), input_seq(MOUSECODE_Y_INDEXED(1), input_seq::or_code, JOYCODE_Y_INDEXED(1)), input_seq(KEYCODE_R), input_seq(KEYCODE_F) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, POSITIONAL_V, N_p("input-name", "Positional V 3"), input_seq(MOUSECODE_Y_INDEXED(2), input_seq::or_code, JOYCODE_Y_INDEXED(2)), input_seq(KEYCODE_I), input_seq(KEYCODE_K) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, POSITIONAL_V, N_p("input-name", "Positional V 4"), input_seq(MOUSECODE_Y_INDEXED(3), input_seq::or_code, JOYCODE_Y_INDEXED(3)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, POSITIONAL_V, N_p("input-name", "Positional V 5"), input_seq(MOUSECODE_Y_INDEXED(4), input_seq::or_code, JOYCODE_Y_INDEXED(4)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, POSITIONAL_V, N_p("input-name", "Positional V 6"), input_seq(MOUSECODE_Y_INDEXED(5), input_seq::or_code, JOYCODE_Y_INDEXED(5)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, POSITIONAL_V, N_p("input-name", "Positional V 7"), input_seq(MOUSECODE_Y_INDEXED(6), input_seq::or_code, JOYCODE_Y_INDEXED(6)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, POSITIONAL_V, N_p("input-name", "Positional V 8"), input_seq(MOUSECODE_Y_INDEXED(7), input_seq::or_code, JOYCODE_Y_INDEXED(7)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, POSITIONAL_V, N_p("input-name", "Positional V 9"), input_seq(MOUSECODE_Y_INDEXED(8), input_seq::or_code, JOYCODE_Y_INDEXED(8)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, POSITIONAL_V, N_p("input-name", "Positional V 10"), input_seq(MOUSECODE_Y_INDEXED(9), input_seq::or_code, JOYCODE_Y_INDEXED(9)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, POSITIONAL_V, N_p("input-name", "Positional V"), input_seq(MOUSECODE_Y_INDEXED(0)), input_seq(KEYCODE_UP), input_seq(KEYCODE_DOWN) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, POSITIONAL_V, N_p("input-name", "Positional V 2"), input_seq(MOUSECODE_Y_INDEXED(1)), input_seq(KEYCODE_R), input_seq(KEYCODE_F) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, POSITIONAL_V, N_p("input-name", "Positional V 3"), input_seq(MOUSECODE_Y_INDEXED(2)), input_seq(KEYCODE_I), input_seq(KEYCODE_K) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, POSITIONAL_V, N_p("input-name", "Positional V 4"), input_seq(MOUSECODE_Y_INDEXED(3)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, POSITIONAL_V, N_p("input-name", "Positional V 5"), input_seq(MOUSECODE_Y_INDEXED(4)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, POSITIONAL_V, N_p("input-name", "Positional V 6"), input_seq(MOUSECODE_Y_INDEXED(5)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, POSITIONAL_V, N_p("input-name", "Positional V 7"), input_seq(MOUSECODE_Y_INDEXED(6)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, POSITIONAL_V, N_p("input-name", "Positional V 8"), input_seq(MOUSECODE_Y_INDEXED(7)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, POSITIONAL_V, N_p("input-name", "Positional V 9"), input_seq(MOUSECODE_Y_INDEXED(8)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, POSITIONAL_V, N_p("input-name", "Positional V 10"), input_seq(MOUSECODE_Y_INDEXED(9)), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_DIAL \ CORE_INPUT_TYPES_BEGIN(dial) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, DIAL, N_p("input-name", "Dial"), input_seq(MOUSECODE_X_INDEXED(0), input_seq::or_code, JOYCODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT), input_seq(KEYCODE_RIGHT) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, DIAL, N_p("input-name", "Dial 2"), input_seq(MOUSECODE_X_INDEXED(1), input_seq::or_code, JOYCODE_X_INDEXED(1)), input_seq(KEYCODE_D), input_seq(KEYCODE_G) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, DIAL, N_p("input-name", "Dial 3"), input_seq(MOUSECODE_X_INDEXED(2), input_seq::or_code, JOYCODE_X_INDEXED(2)), input_seq(KEYCODE_J), input_seq(KEYCODE_L) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, DIAL, N_p("input-name", "Dial 4"), input_seq(MOUSECODE_X_INDEXED(3), input_seq::or_code, JOYCODE_X_INDEXED(3)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, DIAL, N_p("input-name", "Dial 5"), input_seq(MOUSECODE_X_INDEXED(4), input_seq::or_code, JOYCODE_X_INDEXED(4)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, DIAL, N_p("input-name", "Dial 6"), input_seq(MOUSECODE_X_INDEXED(5), input_seq::or_code, JOYCODE_X_INDEXED(5)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, DIAL, N_p("input-name", "Dial 7"), input_seq(MOUSECODE_X_INDEXED(6), input_seq::or_code, JOYCODE_X_INDEXED(6)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, DIAL, N_p("input-name", "Dial 8"), input_seq(MOUSECODE_X_INDEXED(7), input_seq::or_code, JOYCODE_X_INDEXED(7)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, DIAL, N_p("input-name", "Dial 9"), input_seq(MOUSECODE_X_INDEXED(8), input_seq::or_code, JOYCODE_X_INDEXED(8)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, DIAL, N_p("input-name", "Dial 10"), input_seq(MOUSECODE_X_INDEXED(9), input_seq::or_code, JOYCODE_X_INDEXED(9)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, DIAL, N_p("input-name", "Dial"), input_seq(MOUSECODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT), input_seq(KEYCODE_RIGHT) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, DIAL, N_p("input-name", "Dial 2"), input_seq(MOUSECODE_X_INDEXED(1)), input_seq(KEYCODE_D), input_seq(KEYCODE_G) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, DIAL, N_p("input-name", "Dial 3"), input_seq(MOUSECODE_X_INDEXED(2)), input_seq(KEYCODE_J), input_seq(KEYCODE_L) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, DIAL, N_p("input-name", "Dial 4"), input_seq(MOUSECODE_X_INDEXED(3)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, DIAL, N_p("input-name", "Dial 5"), input_seq(MOUSECODE_X_INDEXED(4)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, DIAL, N_p("input-name", "Dial 6"), input_seq(MOUSECODE_X_INDEXED(5)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, DIAL, N_p("input-name", "Dial 7"), input_seq(MOUSECODE_X_INDEXED(6)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, DIAL, N_p("input-name", "Dial 8"), input_seq(MOUSECODE_X_INDEXED(7)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, DIAL, N_p("input-name", "Dial 9"), input_seq(MOUSECODE_X_INDEXED(8)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, DIAL, N_p("input-name", "Dial 10"), input_seq(MOUSECODE_X_INDEXED(9)), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_DIAL_V \ CORE_INPUT_TYPES_BEGIN(dial_v) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, DIAL_V, N_p("input-name", "Dial V"), input_seq(MOUSECODE_Y_INDEXED(0), input_seq::or_code, JOYCODE_Y_INDEXED(0)), input_seq(KEYCODE_UP), input_seq(KEYCODE_DOWN) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, DIAL_V, N_p("input-name", "Dial V 2"), input_seq(MOUSECODE_Y_INDEXED(1), input_seq::or_code, JOYCODE_Y_INDEXED(1)), input_seq(KEYCODE_R), input_seq(KEYCODE_F) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, DIAL_V, N_p("input-name", "Dial V 3"), input_seq(MOUSECODE_Y_INDEXED(2), input_seq::or_code, JOYCODE_Y_INDEXED(2)), input_seq(KEYCODE_I), input_seq(KEYCODE_K) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, DIAL_V, N_p("input-name", "Dial V 4"), input_seq(MOUSECODE_Y_INDEXED(3), input_seq::or_code, JOYCODE_Y_INDEXED(3)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, DIAL_V, N_p("input-name", "Dial V 5"), input_seq(MOUSECODE_Y_INDEXED(4), input_seq::or_code, JOYCODE_Y_INDEXED(4)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, DIAL_V, N_p("input-name", "Dial V 6"), input_seq(MOUSECODE_Y_INDEXED(5), input_seq::or_code, JOYCODE_Y_INDEXED(5)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, DIAL_V, N_p("input-name", "Dial V 7"), input_seq(MOUSECODE_Y_INDEXED(6), input_seq::or_code, JOYCODE_Y_INDEXED(6)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, DIAL_V, N_p("input-name", "Dial V 8"), input_seq(MOUSECODE_Y_INDEXED(7), input_seq::or_code, JOYCODE_Y_INDEXED(7)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, DIAL_V, N_p("input-name", "Dial V 9"), input_seq(MOUSECODE_Y_INDEXED(8), input_seq::or_code, JOYCODE_Y_INDEXED(8)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, DIAL_V, N_p("input-name", "Dial V 10"), input_seq(MOUSECODE_Y_INDEXED(9), input_seq::or_code, JOYCODE_Y_INDEXED(9)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, DIAL_V, N_p("input-name", "Dial V"), input_seq(MOUSECODE_Y_INDEXED(0)), input_seq(KEYCODE_UP), input_seq(KEYCODE_DOWN) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, DIAL_V, N_p("input-name", "Dial V 2"), input_seq(MOUSECODE_Y_INDEXED(1)), input_seq(KEYCODE_R), input_seq(KEYCODE_F) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, DIAL_V, N_p("input-name", "Dial V 3"), input_seq(MOUSECODE_Y_INDEXED(2)), input_seq(KEYCODE_I), input_seq(KEYCODE_K) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, DIAL_V, N_p("input-name", "Dial V 4"), input_seq(MOUSECODE_Y_INDEXED(3)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, DIAL_V, N_p("input-name", "Dial V 5"), input_seq(MOUSECODE_Y_INDEXED(4)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, DIAL_V, N_p("input-name", "Dial V 6"), input_seq(MOUSECODE_Y_INDEXED(5)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, DIAL_V, N_p("input-name", "Dial V 7"), input_seq(MOUSECODE_Y_INDEXED(6)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, DIAL_V, N_p("input-name", "Dial V 8"), input_seq(MOUSECODE_Y_INDEXED(7)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, DIAL_V, N_p("input-name", "Dial V 9"), input_seq(MOUSECODE_Y_INDEXED(8)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, DIAL_V, N_p("input-name", "Dial V 10"), input_seq(MOUSECODE_Y_INDEXED(9)), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_TRACKBALL_X \ CORE_INPUT_TYPES_BEGIN(trackball_x) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, TRACKBALL_X, N_p("input-name", "Track X"), input_seq(MOUSECODE_X_INDEXED(0), input_seq::or_code, JOYCODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT), input_seq(KEYCODE_RIGHT) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, TRACKBALL_X, N_p("input-name", "Track X 2"), input_seq(MOUSECODE_X_INDEXED(1), input_seq::or_code, JOYCODE_X_INDEXED(1)), input_seq(KEYCODE_D), input_seq(KEYCODE_G) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, TRACKBALL_X, N_p("input-name", "Track X 3"), input_seq(MOUSECODE_X_INDEXED(2), input_seq::or_code, JOYCODE_X_INDEXED(2)), input_seq(KEYCODE_J), input_seq(KEYCODE_L) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, TRACKBALL_X, N_p("input-name", "Track X 4"), input_seq(MOUSECODE_X_INDEXED(3), input_seq::or_code, JOYCODE_X_INDEXED(3)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, TRACKBALL_X, N_p("input-name", "Track X 5"), input_seq(MOUSECODE_X_INDEXED(4), input_seq::or_code, JOYCODE_X_INDEXED(4)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, TRACKBALL_X, N_p("input-name", "Track X 6"), input_seq(MOUSECODE_X_INDEXED(5), input_seq::or_code, JOYCODE_X_INDEXED(5)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, TRACKBALL_X, N_p("input-name", "Track X 7"), input_seq(MOUSECODE_X_INDEXED(6), input_seq::or_code, JOYCODE_X_INDEXED(6)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, TRACKBALL_X, N_p("input-name", "Track X 8"), input_seq(MOUSECODE_X_INDEXED(7), input_seq::or_code, JOYCODE_X_INDEXED(7)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, TRACKBALL_X, N_p("input-name", "Track X 9"), input_seq(MOUSECODE_X_INDEXED(8), input_seq::or_code, JOYCODE_X_INDEXED(8)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, TRACKBALL_X, N_p("input-name", "Track X 10"), input_seq(MOUSECODE_X_INDEXED(9), input_seq::or_code, JOYCODE_X_INDEXED(9)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, TRACKBALL_X, N_p("input-name", "Trackball X"), input_seq(MOUSECODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT), input_seq(KEYCODE_RIGHT) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, TRACKBALL_X, N_p("input-name", "Trackball X 2"), input_seq(MOUSECODE_X_INDEXED(1)), input_seq(KEYCODE_D), input_seq(KEYCODE_G) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, TRACKBALL_X, N_p("input-name", "Trackball X 3"), input_seq(MOUSECODE_X_INDEXED(2)), input_seq(KEYCODE_J), input_seq(KEYCODE_L) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, TRACKBALL_X, N_p("input-name", "Trackball X 4"), input_seq(MOUSECODE_X_INDEXED(3)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, TRACKBALL_X, N_p("input-name", "Trackball X 5"), input_seq(MOUSECODE_X_INDEXED(4)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, TRACKBALL_X, N_p("input-name", "Trackball X 6"), input_seq(MOUSECODE_X_INDEXED(5)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, TRACKBALL_X, N_p("input-name", "Trackball X 7"), input_seq(MOUSECODE_X_INDEXED(6)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, TRACKBALL_X, N_p("input-name", "Trackball X 8"), input_seq(MOUSECODE_X_INDEXED(7)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, TRACKBALL_X, N_p("input-name", "Trackball X 9"), input_seq(MOUSECODE_X_INDEXED(8)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, TRACKBALL_X, N_p("input-name", "Trackball X 10"), input_seq(MOUSECODE_X_INDEXED(9)), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_TRACKBALL_Y \ CORE_INPUT_TYPES_BEGIN(trackball_y) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, TRACKBALL_Y, N_p("input-name", "Track Y"), input_seq(MOUSECODE_Y_INDEXED(0), input_seq::or_code, JOYCODE_Y_INDEXED(0)), input_seq(KEYCODE_UP), input_seq(KEYCODE_DOWN) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, TRACKBALL_Y, N_p("input-name", "Track Y 2"), input_seq(MOUSECODE_Y_INDEXED(1), input_seq::or_code, JOYCODE_Y_INDEXED(1)), input_seq(KEYCODE_R), input_seq(KEYCODE_F) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, TRACKBALL_Y, N_p("input-name", "Track Y 3"), input_seq(MOUSECODE_Y_INDEXED(2), input_seq::or_code, JOYCODE_Y_INDEXED(2)), input_seq(KEYCODE_I), input_seq(KEYCODE_K) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, TRACKBALL_Y, N_p("input-name", "Track Y 4"), input_seq(MOUSECODE_Y_INDEXED(3), input_seq::or_code, JOYCODE_Y_INDEXED(3)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, TRACKBALL_Y, N_p("input-name", "Track Y 5"), input_seq(MOUSECODE_Y_INDEXED(4), input_seq::or_code, JOYCODE_Y_INDEXED(4)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, TRACKBALL_Y, N_p("input-name", "Track Y 6"), input_seq(MOUSECODE_Y_INDEXED(5), input_seq::or_code, JOYCODE_Y_INDEXED(5)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, TRACKBALL_Y, N_p("input-name", "Track Y 7"), input_seq(MOUSECODE_Y_INDEXED(6), input_seq::or_code, JOYCODE_Y_INDEXED(6)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, TRACKBALL_Y, N_p("input-name", "Track Y 8"), input_seq(MOUSECODE_Y_INDEXED(7), input_seq::or_code, JOYCODE_Y_INDEXED(7)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, TRACKBALL_Y, N_p("input-name", "Track Y 9"), input_seq(MOUSECODE_Y_INDEXED(8), input_seq::or_code, JOYCODE_Y_INDEXED(8)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, TRACKBALL_Y, N_p("input-name", "Track Y 10"), input_seq(MOUSECODE_Y_INDEXED(9), input_seq::or_code, JOYCODE_Y_INDEXED(9)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, TRACKBALL_Y, N_p("input-name", "Trackball Y"), input_seq(MOUSECODE_Y_INDEXED(0)), input_seq(KEYCODE_UP), input_seq(KEYCODE_DOWN) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, TRACKBALL_Y, N_p("input-name", "Trackball Y 2"), input_seq(MOUSECODE_Y_INDEXED(1)), input_seq(KEYCODE_R), input_seq(KEYCODE_F) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, TRACKBALL_Y, N_p("input-name", "Trackball Y 3"), input_seq(MOUSECODE_Y_INDEXED(2)), input_seq(KEYCODE_I), input_seq(KEYCODE_K) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, TRACKBALL_Y, N_p("input-name", "Trackball Y 4"), input_seq(MOUSECODE_Y_INDEXED(3)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, TRACKBALL_Y, N_p("input-name", "Trackball Y 5"), input_seq(MOUSECODE_Y_INDEXED(4)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, TRACKBALL_Y, N_p("input-name", "Trackball Y 6"), input_seq(MOUSECODE_Y_INDEXED(5)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, TRACKBALL_Y, N_p("input-name", "Trackball Y 7"), input_seq(MOUSECODE_Y_INDEXED(6)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, TRACKBALL_Y, N_p("input-name", "Trackball Y 8"), input_seq(MOUSECODE_Y_INDEXED(7)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, TRACKBALL_Y, N_p("input-name", "Trackball Y 9"), input_seq(MOUSECODE_Y_INDEXED(8)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, TRACKBALL_Y, N_p("input-name", "Trackball Y 10"), input_seq(MOUSECODE_Y_INDEXED(9)), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_AD_STICK_X \ CORE_INPUT_TYPES_BEGIN(ad_stick_x) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, AD_STICK_X, N_p("input-name", "AD Stick X"), input_seq(JOYCODE_X_INDEXED(0), input_seq::or_code, MOUSECODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT), input_seq(KEYCODE_RIGHT) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, AD_STICK_X, N_p("input-name", "AD Stick X 2"), input_seq(JOYCODE_X_INDEXED(1), input_seq::or_code, MOUSECODE_X_INDEXED(1)), input_seq(KEYCODE_D), input_seq(KEYCODE_G) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, AD_STICK_X, N_p("input-name", "AD Stick X 3"), input_seq(JOYCODE_X_INDEXED(2), input_seq::or_code, MOUSECODE_X_INDEXED(2)), input_seq(KEYCODE_J), input_seq(KEYCODE_L) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, AD_STICK_X, N_p("input-name", "AD Stick X 4"), input_seq(JOYCODE_X_INDEXED(3), input_seq::or_code, MOUSECODE_X_INDEXED(3)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, AD_STICK_X, N_p("input-name", "AD Stick X 5"), input_seq(JOYCODE_X_INDEXED(4), input_seq::or_code, MOUSECODE_X_INDEXED(4)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, AD_STICK_X, N_p("input-name", "AD Stick X 6"), input_seq(JOYCODE_X_INDEXED(5), input_seq::or_code, MOUSECODE_X_INDEXED(5)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, AD_STICK_X, N_p("input-name", "AD Stick X 7"), input_seq(JOYCODE_X_INDEXED(6), input_seq::or_code, MOUSECODE_X_INDEXED(6)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, AD_STICK_X, N_p("input-name", "AD Stick X 8"), input_seq(JOYCODE_X_INDEXED(7), input_seq::or_code, MOUSECODE_X_INDEXED(7)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, AD_STICK_X, N_p("input-name", "AD Stick X 9"), input_seq(JOYCODE_X_INDEXED(8), input_seq::or_code, MOUSECODE_X_INDEXED(8)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, AD_STICK_X, N_p("input-name", "AD Stick X 10"), input_seq(JOYCODE_X_INDEXED(9), input_seq::or_code, MOUSECODE_X_INDEXED(9)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, AD_STICK_X, N_p("input-name", "AD Stick X"), input_seq(MOUSECODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT), input_seq(KEYCODE_RIGHT) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, AD_STICK_X, N_p("input-name", "AD Stick X 2"), input_seq(MOUSECODE_X_INDEXED(1)), input_seq(KEYCODE_D), input_seq(KEYCODE_G) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, AD_STICK_X, N_p("input-name", "AD Stick X 3"), input_seq(MOUSECODE_X_INDEXED(2)), input_seq(KEYCODE_J), input_seq(KEYCODE_L) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, AD_STICK_X, N_p("input-name", "AD Stick X 4"), input_seq(MOUSECODE_X_INDEXED(3)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, AD_STICK_X, N_p("input-name", "AD Stick X 5"), input_seq(MOUSECODE_X_INDEXED(4)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, AD_STICK_X, N_p("input-name", "AD Stick X 6"), input_seq(MOUSECODE_X_INDEXED(5)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, AD_STICK_X, N_p("input-name", "AD Stick X 7"), input_seq(MOUSECODE_X_INDEXED(6)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, AD_STICK_X, N_p("input-name", "AD Stick X 8"), input_seq(MOUSECODE_X_INDEXED(7)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, AD_STICK_X, N_p("input-name", "AD Stick X 9"), input_seq(MOUSECODE_X_INDEXED(8)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, AD_STICK_X, N_p("input-name", "AD Stick X 10"), input_seq(MOUSECODE_X_INDEXED(9)), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_AD_STICK_Y \ CORE_INPUT_TYPES_BEGIN(ad_stick_y) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, AD_STICK_Y, N_p("input-name", "AD Stick Y"), input_seq(JOYCODE_Y_INDEXED(0), input_seq::or_code, MOUSECODE_Y_INDEXED(0)), input_seq(KEYCODE_UP), input_seq(KEYCODE_DOWN) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, AD_STICK_Y, N_p("input-name", "AD Stick Y 2"), input_seq(JOYCODE_Y_INDEXED(1), input_seq::or_code, MOUSECODE_Y_INDEXED(1)), input_seq(KEYCODE_R), input_seq(KEYCODE_F) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, AD_STICK_Y, N_p("input-name", "AD Stick Y 3"), input_seq(JOYCODE_Y_INDEXED(2), input_seq::or_code, MOUSECODE_Y_INDEXED(2)), input_seq(KEYCODE_I), input_seq(KEYCODE_K) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, AD_STICK_Y, N_p("input-name", "AD Stick Y 4"), input_seq(JOYCODE_Y_INDEXED(3), input_seq::or_code, MOUSECODE_Y_INDEXED(3)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, AD_STICK_Y, N_p("input-name", "AD Stick Y 5"), input_seq(JOYCODE_Y_INDEXED(4), input_seq::or_code, MOUSECODE_Y_INDEXED(4)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, AD_STICK_Y, N_p("input-name", "AD Stick Y 6"), input_seq(JOYCODE_Y_INDEXED(5), input_seq::or_code, MOUSECODE_Y_INDEXED(5)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, AD_STICK_Y, N_p("input-name", "AD Stick Y 7"), input_seq(JOYCODE_Y_INDEXED(6), input_seq::or_code, MOUSECODE_Y_INDEXED(6)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, AD_STICK_Y, N_p("input-name", "AD Stick Y 8"), input_seq(JOYCODE_Y_INDEXED(7), input_seq::or_code, MOUSECODE_Y_INDEXED(7)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, AD_STICK_Y, N_p("input-name", "AD Stick Y 9"), input_seq(JOYCODE_Y_INDEXED(8), input_seq::or_code, MOUSECODE_Y_INDEXED(8)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, AD_STICK_Y, N_p("input-name", "AD Stick Y 10"), input_seq(JOYCODE_Y_INDEXED(9), input_seq::or_code, MOUSECODE_Y_INDEXED(9)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, AD_STICK_Y, N_p("input-name", "AD Stick Y"), input_seq(MOUSECODE_Y_INDEXED(0)), input_seq(KEYCODE_UP), input_seq(KEYCODE_DOWN) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, AD_STICK_Y, N_p("input-name", "AD Stick Y 2"), input_seq(MOUSECODE_Y_INDEXED(1)), input_seq(KEYCODE_R), input_seq(KEYCODE_F) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, AD_STICK_Y, N_p("input-name", "AD Stick Y 3"), input_seq(MOUSECODE_Y_INDEXED(2)), input_seq(KEYCODE_I), input_seq(KEYCODE_K) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, AD_STICK_Y, N_p("input-name", "AD Stick Y 4"), input_seq(MOUSECODE_Y_INDEXED(3)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, AD_STICK_Y, N_p("input-name", "AD Stick Y 5"), input_seq(MOUSECODE_Y_INDEXED(4)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, AD_STICK_Y, N_p("input-name", "AD Stick Y 6"), input_seq(MOUSECODE_Y_INDEXED(5)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, AD_STICK_Y, N_p("input-name", "AD Stick Y 7"), input_seq(MOUSECODE_Y_INDEXED(6)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, AD_STICK_Y, N_p("input-name", "AD Stick Y 8"), input_seq(MOUSECODE_Y_INDEXED(7)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, AD_STICK_Y, N_p("input-name", "AD Stick Y 9"), input_seq(MOUSECODE_Y_INDEXED(8)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, AD_STICK_Y, N_p("input-name", "AD Stick Y 10"), input_seq(MOUSECODE_Y_INDEXED(9)), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_AD_STICK_Z \ CORE_INPUT_TYPES_BEGIN(ad_stick_z) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, AD_STICK_Z, N_p("input-name", "AD Stick Z"), input_seq(JOYCODE_Z_INDEXED(0)), input_seq(KEYCODE_A), input_seq(KEYCODE_Z) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, AD_STICK_Z, N_p("input-name", "AD Stick Z 2"), input_seq(JOYCODE_Z_INDEXED(1)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, AD_STICK_Z, N_p("input-name", "AD Stick Z 3"), input_seq(JOYCODE_Z_INDEXED(2)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, AD_STICK_Z, N_p("input-name", "AD Stick Z 4"), input_seq(JOYCODE_Z_INDEXED(3)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, AD_STICK_Z, N_p("input-name", "AD Stick Z 5"), input_seq(JOYCODE_Z_INDEXED(4)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, AD_STICK_Z, N_p("input-name", "AD Stick Z 6"), input_seq(JOYCODE_Z_INDEXED(5)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, AD_STICK_Z, N_p("input-name", "AD Stick Z 7"), input_seq(JOYCODE_Z_INDEXED(6)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, AD_STICK_Z, N_p("input-name", "AD Stick Z 8"), input_seq(JOYCODE_Z_INDEXED(7)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, AD_STICK_Z, N_p("input-name", "AD Stick Z 9"), input_seq(JOYCODE_Z_INDEXED(8)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, AD_STICK_Z, N_p("input-name", "AD Stick Z 10"), input_seq(JOYCODE_Z_INDEXED(9)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, AD_STICK_Z, N_p("input-name", "AD Stick Z"), input_seq(), input_seq(KEYCODE_A), input_seq(KEYCODE_Z) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, AD_STICK_Z, N_p("input-name", "AD Stick Z 2"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, AD_STICK_Z, N_p("input-name", "AD Stick Z 3"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, AD_STICK_Z, N_p("input-name", "AD Stick Z 4"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, AD_STICK_Z, N_p("input-name", "AD Stick Z 5"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, AD_STICK_Z, N_p("input-name", "AD Stick Z 6"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, AD_STICK_Z, N_p("input-name", "AD Stick Z 7"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, AD_STICK_Z, N_p("input-name", "AD Stick Z 8"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, AD_STICK_Z, N_p("input-name", "AD Stick Z 9"), input_seq(), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, AD_STICK_Z, N_p("input-name", "AD Stick Z 10"), input_seq(), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_LIGHTGUN_X \ CORE_INPUT_TYPES_BEGIN(lightgun_x) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, LIGHTGUN_X, N_p("input-name", "Lightgun X"), input_seq(GUNCODE_X_INDEXED(0), input_seq::or_code, MOUSECODE_X_INDEXED(0), input_seq::or_code, JOYCODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT), input_seq(KEYCODE_RIGHT) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, LIGHTGUN_X, N_p("input-name", "Lightgun X 2"), input_seq(GUNCODE_X_INDEXED(1), input_seq::or_code, MOUSECODE_X_INDEXED(1), input_seq::or_code, JOYCODE_X_INDEXED(1)), input_seq(KEYCODE_D), input_seq(KEYCODE_G) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, LIGHTGUN_X, N_p("input-name", "Lightgun X 3"), input_seq(GUNCODE_X_INDEXED(2), input_seq::or_code, MOUSECODE_X_INDEXED(2), input_seq::or_code, JOYCODE_X_INDEXED(2)), input_seq(KEYCODE_J), input_seq(KEYCODE_L) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, LIGHTGUN_X, N_p("input-name", "Lightgun X 4"), input_seq(GUNCODE_X_INDEXED(3), input_seq::or_code, MOUSECODE_X_INDEXED(3), input_seq::or_code, JOYCODE_X_INDEXED(3)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, LIGHTGUN_X, N_p("input-name", "Lightgun X 5"), input_seq(GUNCODE_X_INDEXED(4), input_seq::or_code, MOUSECODE_X_INDEXED(4), input_seq::or_code, JOYCODE_X_INDEXED(4)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, LIGHTGUN_X, N_p("input-name", "Lightgun X 6"), input_seq(GUNCODE_X_INDEXED(5), input_seq::or_code, MOUSECODE_X_INDEXED(5), input_seq::or_code, JOYCODE_X_INDEXED(5)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, LIGHTGUN_X, N_p("input-name", "Lightgun X 7"), input_seq(GUNCODE_X_INDEXED(6), input_seq::or_code, MOUSECODE_X_INDEXED(6), input_seq::or_code, JOYCODE_X_INDEXED(6)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, LIGHTGUN_X, N_p("input-name", "Lightgun X 8"), input_seq(GUNCODE_X_INDEXED(7), input_seq::or_code, MOUSECODE_X_INDEXED(7), input_seq::or_code, JOYCODE_X_INDEXED(7)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, LIGHTGUN_X, N_p("input-name", "Lightgun X 9"), input_seq(GUNCODE_X_INDEXED(8), input_seq::or_code, MOUSECODE_X_INDEXED(8), input_seq::or_code, JOYCODE_X_INDEXED(8)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, LIGHTGUN_X, N_p("input-name", "Lightgun X 10"), input_seq(GUNCODE_X_INDEXED(9), input_seq::or_code, MOUSECODE_X_INDEXED(9), input_seq::or_code, JOYCODE_X_INDEXED(9)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, LIGHTGUN_X, N_p("input-name", "Lightgun X"), input_seq(GUNCODE_X_INDEXED(0), input_seq::or_code, MOUSECODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT), input_seq(KEYCODE_RIGHT) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, LIGHTGUN_X, N_p("input-name", "Lightgun X 2"), input_seq(GUNCODE_X_INDEXED(1), input_seq::or_code, MOUSECODE_X_INDEXED(1)), input_seq(KEYCODE_D), input_seq(KEYCODE_G) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, LIGHTGUN_X, N_p("input-name", "Lightgun X 3"), input_seq(GUNCODE_X_INDEXED(2), input_seq::or_code, MOUSECODE_X_INDEXED(2)), input_seq(KEYCODE_J), input_seq(KEYCODE_L) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, LIGHTGUN_X, N_p("input-name", "Lightgun X 4"), input_seq(GUNCODE_X_INDEXED(3), input_seq::or_code, MOUSECODE_X_INDEXED(3)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, LIGHTGUN_X, N_p("input-name", "Lightgun X 5"), input_seq(GUNCODE_X_INDEXED(4), input_seq::or_code, MOUSECODE_X_INDEXED(4)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, LIGHTGUN_X, N_p("input-name", "Lightgun X 6"), input_seq(GUNCODE_X_INDEXED(5), input_seq::or_code, MOUSECODE_X_INDEXED(5)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, LIGHTGUN_X, N_p("input-name", "Lightgun X 7"), input_seq(GUNCODE_X_INDEXED(6), input_seq::or_code, MOUSECODE_X_INDEXED(6)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, LIGHTGUN_X, N_p("input-name", "Lightgun X 8"), input_seq(GUNCODE_X_INDEXED(7), input_seq::or_code, MOUSECODE_X_INDEXED(7)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, LIGHTGUN_X, N_p("input-name", "Lightgun X 9"), input_seq(GUNCODE_X_INDEXED(8), input_seq::or_code, MOUSECODE_X_INDEXED(8)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, LIGHTGUN_X, N_p("input-name", "Lightgun X 10"), input_seq(GUNCODE_X_INDEXED(9), input_seq::or_code, MOUSECODE_X_INDEXED(9)), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_LIGHTGUN_Y \ CORE_INPUT_TYPES_BEGIN(lightgun_y) \ - INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, LIGHTGUN_Y, N_p("input-name", "Lightgun Y"), input_seq(GUNCODE_Y_INDEXED(0), input_seq::or_code, MOUSECODE_Y_INDEXED(0), input_seq::or_code, JOYCODE_Y_INDEXED(0)), input_seq(KEYCODE_UP), input_seq(KEYCODE_DOWN) ) \ - INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 2"), input_seq(GUNCODE_Y_INDEXED(1), input_seq::or_code, MOUSECODE_Y_INDEXED(1), input_seq::or_code, JOYCODE_Y_INDEXED(1)), input_seq(KEYCODE_R), input_seq(KEYCODE_F) ) \ - INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 3"), input_seq(GUNCODE_Y_INDEXED(2), input_seq::or_code, MOUSECODE_Y_INDEXED(2), input_seq::or_code, JOYCODE_Y_INDEXED(2)), input_seq(KEYCODE_I), input_seq(KEYCODE_K) ) \ - INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 4"), input_seq(GUNCODE_Y_INDEXED(3), input_seq::or_code, MOUSECODE_Y_INDEXED(3), input_seq::or_code, JOYCODE_Y_INDEXED(3)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 5"), input_seq(GUNCODE_Y_INDEXED(4), input_seq::or_code, MOUSECODE_Y_INDEXED(4), input_seq::or_code, JOYCODE_Y_INDEXED(4)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 6"), input_seq(GUNCODE_Y_INDEXED(5), input_seq::or_code, MOUSECODE_Y_INDEXED(5), input_seq::or_code, JOYCODE_Y_INDEXED(5)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 7"), input_seq(GUNCODE_Y_INDEXED(6), input_seq::or_code, MOUSECODE_Y_INDEXED(6), input_seq::or_code, JOYCODE_Y_INDEXED(6)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 8"), input_seq(GUNCODE_Y_INDEXED(7), input_seq::or_code, MOUSECODE_Y_INDEXED(7), input_seq::or_code, JOYCODE_Y_INDEXED(7)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 9"), input_seq(GUNCODE_Y_INDEXED(8), input_seq::or_code, MOUSECODE_Y_INDEXED(8), input_seq::or_code, JOYCODE_Y_INDEXED(8)), input_seq(), input_seq() ) \ - INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 10"), input_seq(GUNCODE_Y_INDEXED(9), input_seq::or_code, MOUSECODE_Y_INDEXED(9), input_seq::or_code, JOYCODE_Y_INDEXED(9)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, LIGHTGUN_Y, N_p("input-name", "Lightgun Y"), input_seq(GUNCODE_Y_INDEXED(0), input_seq::or_code, MOUSECODE_Y_INDEXED(0)), input_seq(KEYCODE_UP), input_seq(KEYCODE_DOWN) ) \ + INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 2"), input_seq(GUNCODE_Y_INDEXED(1), input_seq::or_code, MOUSECODE_Y_INDEXED(1)), input_seq(KEYCODE_R), input_seq(KEYCODE_F) ) \ + INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 3"), input_seq(GUNCODE_Y_INDEXED(2), input_seq::or_code, MOUSECODE_Y_INDEXED(2)), input_seq(KEYCODE_I), input_seq(KEYCODE_K) ) \ + INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 4"), input_seq(GUNCODE_Y_INDEXED(3), input_seq::or_code, MOUSECODE_Y_INDEXED(3)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 5"), input_seq(GUNCODE_Y_INDEXED(4), input_seq::or_code, MOUSECODE_Y_INDEXED(4)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 6"), input_seq(GUNCODE_Y_INDEXED(5), input_seq::or_code, MOUSECODE_Y_INDEXED(5)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 7"), input_seq(GUNCODE_Y_INDEXED(6), input_seq::or_code, MOUSECODE_Y_INDEXED(6)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 8"), input_seq(GUNCODE_Y_INDEXED(7), input_seq::or_code, MOUSECODE_Y_INDEXED(7)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 9, PLAYER9, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 9"), input_seq(GUNCODE_Y_INDEXED(8), input_seq::or_code, MOUSECODE_Y_INDEXED(8)), input_seq(), input_seq() ) \ + INPUT_PORT_ANALOG_TYPE( 10, PLAYER10, LIGHTGUN_Y, N_p("input-name", "Lightgun Y 10"), input_seq(GUNCODE_Y_INDEXED(9), input_seq::or_code, MOUSECODE_Y_INDEXED(9)), input_seq(), input_seq() ) \ CORE_INPUT_TYPES_END() #define CORE_INPUT_TYPES_MOUSE_X \ @@ -871,16 +871,36 @@ namespace { #define CORE_INPUT_TYPES_UI \ CORE_INPUT_TYPES_BEGIN(ui) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ON_SCREEN_DISPLAY, N_p("input-name", "On Screen Display"), input_seq(KEYCODE_TILDE, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DEBUG_BREAK, N_p("input-name", "Break in Debugger"), input_seq(KEYCODE_TILDE, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CONFIGURE, N_p("input-name", "Config Menu"), input_seq(KEYCODE_TAB) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAUSE, N_p("input-name", "Pause"), input_seq(KEYCODE_P, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAUSE_SINGLE, N_p("input-name", "Pause - Single Step"), input_seq(KEYCODE_P, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_P, KEYCODE_RSHIFT) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_REWIND_SINGLE, N_p("input-name", "Rewind - Single Step"), input_seq(KEYCODE_TILDE, KEYCODE_LSHIFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_MENU, N_p("input-name", "Show/Hide Menu"), input_seq(KEYCODE_TAB) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SELECT, N_p("input-name", "UI Select"), input_seq(KEYCODE_ENTER, input_seq::not_code, KEYCODE_LALT, input_seq::not_code, KEYCODE_RALT, input_seq::or_code, KEYCODE_ENTER_PAD) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_BACK, N_p("input-name", "UI Back"), input_seq(KEYCODE_ESC) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CANCEL, N_p("input-name", "UI Cancel"), input_seq(KEYCODE_ESC) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CLEAR, N_p("input-name", "UI Clear"), input_seq(KEYCODE_DEL) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_HELP, N_p("input-name", "UI Help"), input_seq(KEYCODE_F1) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_UP, N_p("input-name", "UI Up"), input_seq(KEYCODE_UP) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DOWN, N_p("input-name", "UI Down"), input_seq(KEYCODE_DOWN) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_LEFT, N_p("input-name", "UI Left"), input_seq(KEYCODE_LEFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RIGHT, N_p("input-name", "UI Right"), input_seq(KEYCODE_RIGHT) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_HOME, N_p("input-name", "UI Home"), input_seq(KEYCODE_HOME) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_END, N_p("input-name", "UI End"), input_seq(KEYCODE_END) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAGE_UP, N_p("input-name", "UI Page Up"), input_seq(KEYCODE_PGUP) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAGE_DOWN, N_p("input-name", "UI Page Down"), input_seq(KEYCODE_PGDN) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PREV_GROUP, N_p("input-name", "UI Previous Group"), input_seq(KEYCODE_OPENBRACE) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_NEXT_GROUP, N_p("input-name", "UI Next Group"), input_seq(KEYCODE_CLOSEBRACE) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ON_SCREEN_DISPLAY, N_p("input-name", "On Screen Display"), input_seq(KEYCODE_TILDE) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_UI, N_p("input-name", "Toggle UI Controls"), input_seq(KEYCODE_SCRLOCK, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DEBUG_BREAK, N_p("input-name", "Break in Debugger"), input_seq(KEYCODE_TILDE) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAUSE, N_p("input-name", "Pause"), input_seq(KEYCODE_F5, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAUSE_SINGLE, N_p("input-name", "Pause - Single Step"), input_seq(KEYCODE_F5, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_F5, KEYCODE_RSHIFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_REWIND_SINGLE, N_p("input-name", "Rewind - Single Step"), input_seq(KEYCODE_F4, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_F4, KEYCODE_RSHIFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SAVE_STATE, N_p("input-name", "Save State"), input_seq(KEYCODE_F6, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SAVE_STATE_QUICK, N_p("input-name", "Quick Save State"), input_seq(KEYCODE_F6, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_F6, KEYCODE_RSHIFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_LOAD_STATE, N_p("input-name", "Load State"), input_seq(KEYCODE_F7, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_LOAD_STATE_QUICK, N_p("input-name", "Quick Load State"), input_seq(KEYCODE_F7, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_F7, KEYCODE_RSHIFT) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RESET_MACHINE, N_p("input-name", "Reset Machine"), input_seq(KEYCODE_F3, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_F3, KEYCODE_RSHIFT) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SOFT_RESET, N_p("input-name", "Soft Reset"), input_seq(KEYCODE_F3, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SHOW_GFX, N_p("input-name", "Show Decoded Graphics"), input_seq(KEYCODE_F4) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FRAMESKIP_DEC, N_p("input-name", "Frameskip Dec"), input_seq(KEYCODE_F8) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SHOW_GFX, N_p("input-name", "Show Decoded Graphics"), input_seq(KEYCODE_F4, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FRAMESKIP_DEC, N_p("input-name", "Frameskip Dec"), input_seq(KEYCODE_F8, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FRAMESKIP_INC, N_p("input-name", "Frameskip Inc"), input_seq(KEYCODE_F9) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_THROTTLE, N_p("input-name", "Throttle"), input_seq(KEYCODE_F10) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FAST_FORWARD, N_p("input-name", "Fast Forward"), input_seq(KEYCODE_INSERT) ) \ @@ -888,37 +908,21 @@ namespace { INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SNAPSHOT, N_p("input-name", "Save Snapshot"), input_seq(KEYCODE_F12, input_seq::not_code, KEYCODE_LSHIFT) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RECORD_MNG, N_p("input-name", "Record MNG"), input_seq(KEYCODE_F12, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_LCONTROL) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RECORD_AVI, N_p("input-name", "Record AVI"), input_seq(KEYCODE_F12, KEYCODE_LSHIFT, KEYCODE_LCONTROL) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_CHEAT, N_p("input-name", "Toggle Cheat"), input_seq(KEYCODE_F6) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_UP, N_p("input-name", "UI Up"), input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DOWN, N_p("input-name", "UI Down"), input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_LEFT, N_p("input-name", "UI Left"), input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RIGHT, N_p("input-name", "UI Right"), input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_HOME, N_p("input-name", "UI Home"), input_seq(KEYCODE_HOME) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_END, N_p("input-name", "UI End"), input_seq(KEYCODE_END) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAGE_UP, N_p("input-name", "UI Page Up"), input_seq(KEYCODE_PGUP) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAGE_DOWN, N_p("input-name", "UI Page Down"), input_seq(KEYCODE_PGDN) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_NEXT, N_p("input-name", "UI Focus Next"), input_seq(KEYCODE_TAB, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_PREV, N_p("input-name", "UI Focus Previous"), input_seq(KEYCODE_TAB, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_TAB, KEYCODE_RSHIFT) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SELECT, N_p("input-name", "UI Select"), input_seq(KEYCODE_ENTER, input_seq::not_code, KEYCODE_LALT, input_seq::not_code, KEYCODE_RALT, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0), input_seq::or_code, KEYCODE_ENTER_PAD) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CANCEL, N_p("input-name", "UI Cancel"), input_seq(KEYCODE_ESC) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_CHEAT, N_p("input-name", "Toggle Cheat"), input_seq(KEYCODE_F8, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_F8, KEYCODE_RSHIFT) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DISPLAY_COMMENT, N_p("input-name", "UI Display Comment"), input_seq(KEYCODE_SPACE) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CLEAR, N_p("input-name", "UI Clear"), input_seq(KEYCODE_DEL) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ZOOM_IN, N_p("input-name", "UI Zoom In"), input_seq(KEYCODE_EQUALS) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ZOOM_OUT, N_p("input-name", "UI Zoom Out"), input_seq(KEYCODE_MINUS) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ZOOM_DEFAULT, N_p("input-name", "UI Default Zoom"), input_seq(KEYCODE_0) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PREV_GROUP, N_p("input-name", "UI Previous Group"), input_seq(KEYCODE_OPENBRACE) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_NEXT_GROUP, N_p("input-name", "UI Next Group"), input_seq(KEYCODE_CLOSEBRACE) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ROTATE, N_p("input-name", "UI Rotate"), input_seq(KEYCODE_R) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SHOW_PROFILER, N_p("input-name", "Show Profiler"), input_seq(KEYCODE_F11, KEYCODE_LSHIFT) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_UI, N_p("input-name", "UI Toggle"), input_seq(KEYCODE_SCRLOCK, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RELEASE_POINTER, N_p("input-name", "UI Release Pointer"), input_seq(KEYCODE_RCONTROL, KEYCODE_RALT) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PASTE, N_p("input-name", "UI Paste Text"), input_seq(KEYCODE_SCRLOCK, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_SCRLOCK, KEYCODE_RSHIFT) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SAVE_STATE, N_p("input-name", "Save State"), input_seq(KEYCODE_F7, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_F7, KEYCODE_RSHIFT) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_LOAD_STATE, N_p("input-name", "Load State"), input_seq(KEYCODE_F7, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TAPE_START, N_p("input-name", "UI (First) Tape Start"), input_seq(KEYCODE_F2, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TAPE_STOP, N_p("input-name", "UI (First) Tape Stop"), input_seq(KEYCODE_F2, KEYCODE_LSHIFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_NEXT, N_p("input-name", "UI Focus Next"), input_seq(KEYCODE_TAB, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_PREV, N_p("input-name", "UI Focus Previous"), input_seq(KEYCODE_TAB, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_TAB, KEYCODE_RSHIFT) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DATS, N_p("input-name", "UI External DAT View"), input_seq(KEYCODE_LALT, KEYCODE_D) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FAVORITES, N_p("input-name", "UI Add/Remove favorite"), input_seq(KEYCODE_LALT, KEYCODE_F) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FAVORITES, N_p("input-name", "UI Add/Remove Favorite"), input_seq(KEYCODE_LALT, KEYCODE_F) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_EXPORT, N_p("input-name", "UI Export List"), input_seq(KEYCODE_LALT, KEYCODE_E) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_AUDIT, N_p("input-name", "UI Audit Media"), input_seq(KEYCODE_F1, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ CORE_INPUT_TYPES_END() diff --git a/src/emu/input.cpp b/src/emu/input.cpp index 6c3699a833a..9e82f290bf7 100644 --- a/src/emu/input.cpp +++ b/src/emu/input.cpp @@ -24,6 +24,8 @@ +namespace { + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -49,8 +51,8 @@ struct code_string_table return nullptr; } - u32 m_code; - const char * m_string; + u32 m_code; + const char * m_string; }; @@ -60,7 +62,7 @@ struct code_string_table //************************************************************************** // token strings for device classes -static const code_string_table devclass_token_table[] = +const code_string_table devclass_token_table[] = { { DEVICE_CLASS_KEYBOARD, "KEYCODE" }, { DEVICE_CLASS_MOUSE, "MOUSECODE" }, @@ -70,7 +72,7 @@ static const code_string_table devclass_token_table[] = }; // friendly strings for device classes -static const code_string_table devclass_string_table[] = +const code_string_table devclass_string_table[] = { { DEVICE_CLASS_KEYBOARD, "Kbd" }, { DEVICE_CLASS_MOUSE, "Mouse" }, @@ -80,7 +82,7 @@ static const code_string_table devclass_string_table[] = }; // token strings for item modifiers -static const code_string_table modifier_token_table[] = +const code_string_table modifier_token_table[] = { { ITEM_MODIFIER_REVERSE, "REVERSE" }, { ITEM_MODIFIER_POS, "POS" }, @@ -93,7 +95,7 @@ static const code_string_table modifier_token_table[] = }; // friendly strings for item modifiers -static const code_string_table modifier_string_table[] = +const code_string_table modifier_string_table[] = { { ITEM_MODIFIER_REVERSE, "Reverse" }, { ITEM_MODIFIER_POS, "+" }, @@ -106,7 +108,7 @@ static const code_string_table modifier_string_table[] = }; // token strings for item classes -static const code_string_table itemclass_token_table[] = +const code_string_table itemclass_token_table[] = { { ITEM_CLASS_SWITCH, "SWITCH" }, { ITEM_CLASS_ABSOLUTE, "ABSOLUTE" }, @@ -115,7 +117,7 @@ static const code_string_table itemclass_token_table[] = }; // token strings for standard item ids -static const code_string_table itemid_token_table[] = +const code_string_table itemid_token_table[] = { // standard keyboard codes { ITEM_ID_A, "A" }, @@ -355,6 +357,48 @@ static const code_string_table itemid_token_table[] = //************************************************************************** +// UTILITY FUNCTIONS +//************************************************************************** + +inline void accumulate_axis_value( + s32 &result, + input_item_class &resultclass, + input_item_class &resultclasszero, + s32 value, + input_item_class valueclass, + input_item_class valueclasszero) +{ + if (!value) + { + // track the highest-priority zero + if ((ITEM_CLASS_ABSOLUTE == valueclasszero) || (ITEM_CLASS_INVALID == resultclasszero)) + resultclasszero = valueclasszero; + } + else if (ITEM_CLASS_ABSOLUTE == valueclass) + { + // absolute values override relative values + if (ITEM_CLASS_ABSOLUTE == resultclass) + result += value; + else + result = value; + resultclass = ITEM_CLASS_ABSOLUTE; + } + else if (ITEM_CLASS_RELATIVE == valueclass) + { + // relative values accumulate + if (resultclass != ITEM_CLASS_ABSOLUTE) + { + result += value; + resultclass = ITEM_CLASS_RELATIVE; + } + } +} + +} // anonymous namespace + + + +//************************************************************************** // INPUT MANAGER //************************************************************************** @@ -393,6 +437,18 @@ input_manager::~input_manager() //------------------------------------------------- +// class_enabled - return whether input device +// class is enabled +//------------------------------------------------- + +bool input_manager::class_enabled(input_device_class devclass) const +{ + assert(devclass >= DEVICE_CLASS_FIRST_VALID && devclass <= DEVICE_CLASS_LAST_VALID); + return m_class[devclass]->enabled(); +} + + +//------------------------------------------------- // add_device - add a representation of a host // input device //------------------------------------------------- @@ -410,42 +466,38 @@ osd::input_device &input_manager::add_device(input_device_class devclass, std::s s32 input_manager::code_value(input_code code) { - g_profiler.start(PROFILER_INPUT); - s32 result = 0; - - // dummy loop to allow clean early exits - do + auto profile = g_profiler.start(PROFILER_INPUT); + + // return 0 for any invalid devices + input_device *const device = device_from_code(code); + if (!device) + return 0; + + // also return 0 if the device class is disabled + input_class &devclass = *m_class[code.device_class()]; + if (!devclass.enabled()) + return 0; + + // if this is not a multi device, only return data for item 0 and iterate over all + int startindex = code.device_index(); + int stopindex = startindex; + if (!devclass.multi()) { - // return 0 for any invalid devices - input_device *device = device_from_code(code); - if (device == nullptr) - break; - - // also return 0 if the device class is disabled - input_class &devclass = *m_class[code.device_class()]; - if (!devclass.enabled()) - break; - - // if this is not a multi device, only return data for item 0 and iterate over all - int startindex = code.device_index(); - int stopindex = startindex; - if (!devclass.multi()) - { - if (startindex != 0) - break; - stopindex = devclass.maxindex(); - } + if (startindex != 0) + return 0; + stopindex = devclass.maxindex(); + } - // iterate over all device indices - input_item_class targetclass = code.item_class(); - for (int curindex = startindex; curindex <= stopindex; curindex++) + // iterate over all device indices + s32 result = 0; + input_item_class targetclass = code.item_class(); + for (int curindex = startindex; curindex <= stopindex; curindex++) + { + // lookup the item for the appropriate index + code.set_device_index(curindex); + input_device_item *const item = item_from_code(code); + if (item) { - // lookup the item for the appropriate index - code.set_device_index(curindex); - input_device_item *item = item_from_code(code); - if (item == nullptr) - continue; - // process items according to their native type switch (targetclass) { @@ -466,10 +518,8 @@ s32 input_manager::code_value(input_code code) break; } } - } while (0); + } - // stop the profiler before exiting - g_profiler.stop(); return result; } @@ -594,50 +644,45 @@ input_code input_manager::code_from_itemid(input_item_id itemid) const std::string input_manager::code_name(input_code code) const { // if nothing there, return an empty string - input_device_item *item = item_from_code(code); - if (item == nullptr) + input_device_item const *const item = item_from_code(code); + if (!item) return std::string(); - // determine the devclass part - const char *devclass = (*devclass_string_table)[code.device_class()]; - - // determine the devindex part - std::string devindex = string_format("%d", code.device_index() + 1); - - // if we're unifying all devices, don't display a number - if (!m_class[code.device_class()]->multi()) - devindex.clear(); + std::string str; // keyboard 0 doesn't show a class or index if it is the only one - input_device_class device_class = item->device().devclass(); - if (device_class == DEVICE_CLASS_KEYBOARD && m_class[device_class]->maxindex() == 0) + input_device_class const device_class = item->device().devclass(); + if ((device_class != DEVICE_CLASS_KEYBOARD) || (m_class[device_class]->maxindex() > 0)) { - devclass = ""; - devindex.clear(); - } + // determine the devclass part + str = (*devclass_string_table)[code.device_class()]; - // devcode part comes from the item name - std::string_view devcode = item->name(); - - // determine the modifier part - const char *modifier = (*modifier_string_table)[code.item_modifier()]; - - // devcode is redundant with joystick switch left/right/up/down - if (device_class == DEVICE_CLASS_JOYSTICK && code.item_class() == ITEM_CLASS_SWITCH) - if (code.item_modifier() >= ITEM_MODIFIER_LEFT && code.item_modifier() <= ITEM_MODIFIER_DOWN) - devcode = std::string_view(); + // if we're unifying all devices, don't display a number + if (m_class[code.device_class()]->multi()) + str.append(util::string_format(" %d ", code.device_index() + 1)); + else + str.append(" "); + } - // concatenate the strings - std::string str(devclass); - if (!devindex.empty()) - str.append(" ").append(devindex); - if (!devcode.empty()) - str.append(" ").append(devcode); - if (modifier != nullptr) - str.append(" ").append(modifier); + // append item name - redundant with joystick switch left/right/up/down + bool const joydir = + (device_class == DEVICE_CLASS_JOYSTICK) && + (code.item_class() == ITEM_CLASS_SWITCH) && + (code.item_modifier() >= ITEM_MODIFIER_LEFT) && + (code.item_modifier() <= ITEM_MODIFIER_DOWN); + if (joydir) + { + str.append((*modifier_string_table)[code.item_modifier()]); + } + else + { + str.append(item->name()); + char const *const modifier = (*modifier_string_table)[code.item_modifier()]; + if (modifier && *modifier) + str.append(" ").append(modifier); + } - // delete any leading spaces - return std::string(strtrimspace(str)); + return str; } @@ -861,91 +906,83 @@ bool input_manager::seq_pressed(const input_seq &seq) s32 input_manager::seq_axis_value(const input_seq &seq, input_item_class &itemclass) { - // start with no valid classes - input_item_class itemclasszero = ITEM_CLASS_INVALID; + // start with zero result and no valid classes + s32 result = 0; itemclass = ITEM_CLASS_INVALID; + input_item_class itemclasszero = ITEM_CLASS_INVALID; // iterate over all of the codes - s32 result = 0; + s32 groupval = 0; + input_item_class groupclass = ITEM_CLASS_INVALID; + input_item_class groupclasszero = ITEM_CLASS_INVALID; bool invert = false; bool enable = true; for (int codenum = 0; ; codenum++) { - input_code code = seq[codenum]; + input_code const code = seq[codenum]; if (code == input_seq::not_code) { - // handle NOT + // handle NOT - invert the next code invert = true; } else if (code == input_seq::end_code) { - // handle END + // handle END - commit group and break out of loop + accumulate_axis_value( + result, itemclass, itemclasszero, + groupval, groupclass, groupclasszero); break; } else if (code == input_seq::or_code) { - // handle OR - - // reset invert and enable for the next group + // handle OR - commit group and reset for the next group + accumulate_axis_value( + result, itemclass, itemclasszero, + groupval, groupclass, groupclasszero); + groupval = 0; + groupclasszero = ITEM_CLASS_INVALID; + groupclass = ITEM_CLASS_INVALID; invert = false; enable = true; } else if (enable) { // handle everything else only if we're still enabled + input_item_class const codeclass = code.item_class(); // switch codes serve as enables - if (code.item_class() == ITEM_CLASS_SWITCH) + if (ITEM_CLASS_SWITCH == codeclass) { // AND against previous digital codes if (enable) + { enable = code_pressed(code) ^ invert; - // FIXME: need to clear current group value if enable became false - // you can't create a sequence where this matters using the internal UI, - // but you can by editing a CFG file (or controller config file) + if (!enable) + { + // clear current group if enable became false - only way out is an OR code + groupval = 0; + groupclasszero = ITEM_CLASS_INVALID; + groupclass = ITEM_CLASS_INVALID; + } + } } else { // non-switch codes are analog values - s32 value = code_value(code); - - // if we got a 0 value, don't do anything except remember the first type - if (value == 0) - { - if (itemclasszero == ITEM_CLASS_INVALID) - itemclasszero = code.item_class(); - } - else if (code.item_class() == ITEM_CLASS_ABSOLUTE) - { - // non-zero absolute values override relative values - if (itemclass == ITEM_CLASS_ABSOLUTE) - result += value; - else - result = value; - itemclass = ITEM_CLASS_ABSOLUTE; - } - else if (code.item_class() == ITEM_CLASS_RELATIVE) - { - // non-zero relative values accumulate in the absence of absolute values - if (itemclass != ITEM_CLASS_ABSOLUTE) - { - result += value; - itemclass = ITEM_CLASS_RELATIVE; - } - } + accumulate_axis_value( + groupval, groupclass, groupclasszero, + code_value(code), codeclass, codeclass); } - // clear the invert flag + // clear the invert flag - it only applies to one item invert = false; } } - // saturate mixed absolute values - if (itemclass == ITEM_CLASS_ABSOLUTE) - result = std::clamp(result, osd::INPUT_ABSOLUTE_MIN, osd::INPUT_ABSOLUTE_MAX); - - // if the caller wants to know the type, provide it - if (result == 0) + // saturate mixed absolute values, report neutral type + if (ITEM_CLASS_ABSOLUTE == itemclass) + result = std::clamp(result, osd::input_device::ABSOLUTE_MIN, osd::input_device::ABSOLUTE_MAX); + else if (ITEM_CLASS_INVALID == itemclass) itemclass = itemclasszero; return result; } diff --git a/src/emu/input.h b/src/emu/input.h index 1b6b1caca93..7c00a590a8d 100644 --- a/src/emu/input.h +++ b/src/emu/input.h @@ -52,6 +52,7 @@ public: ~input_manager(); // OSD interface + virtual bool class_enabled(input_device_class devclass) const override; virtual osd::input_device &add_device(input_device_class devclass, std::string_view name, std::string_view id, void *internal) override; // getters diff --git a/src/emu/inputdev.cpp b/src/emu/inputdev.cpp index 2ce5720cf9b..a9caaf7788d 100644 --- a/src/emu/inputdev.cpp +++ b/src/emu/inputdev.cpp @@ -28,7 +28,13 @@ class input_device_switch_item : public input_device_item { public: // construction/destruction - input_device_switch_item(input_device &device, std::string_view name, void *internal, input_item_id itemid, item_get_state_func getstate); + input_device_switch_item( + input_device &device, + std::string_view name, + std::string_view tokenhint, + void *internal, + input_item_id itemid, + item_get_state_func getstate); // readers virtual s32 read_as_switch(input_item_modifier modifier) override; @@ -54,7 +60,13 @@ class input_device_relative_item : public input_device_item { public: // construction/destruction - input_device_relative_item(input_device &device, std::string_view name, void *internal, input_item_id itemid, item_get_state_func getstate); + input_device_relative_item( + input_device &device, + std::string_view name, + std::string_view tokenhint, + void *internal, + input_item_id itemid, + item_get_state_func getstate); // readers virtual s32 read_as_switch(input_item_modifier modifier) override; @@ -71,7 +83,13 @@ class input_device_absolute_item : public input_device_item { public: // construction/destruction - input_device_absolute_item(input_device &device, std::string_view name, void *internal, input_item_id itemid, item_get_state_func getstate); + input_device_absolute_item( + input_device &device, + std::string_view name, + std::string_view tokenhint, + void *internal, + input_item_id itemid, + item_get_state_func getstate); // readers virtual s32 read_as_switch(input_item_modifier modifier) override; @@ -233,8 +251,8 @@ std::string joystick_map::to_string() const u8 joystick_map::update(s32 xaxisval, s32 yaxisval) { // now map the X and Y axes to a 9x9 grid using the raw values - xaxisval = ((xaxisval - osd::INPUT_ABSOLUTE_MIN) * 9) / (osd::INPUT_ABSOLUTE_MAX - osd::INPUT_ABSOLUTE_MIN + 1); - yaxisval = ((yaxisval - osd::INPUT_ABSOLUTE_MIN) * 9) / (osd::INPUT_ABSOLUTE_MAX - osd::INPUT_ABSOLUTE_MIN + 1); + xaxisval = ((xaxisval - osd::input_device::ABSOLUTE_MIN) * 9) / (osd::input_device::ABSOLUTE_MAX - osd::input_device::ABSOLUTE_MIN + 1); + yaxisval = ((yaxisval - osd::input_device::ABSOLUTE_MIN) * 9) / (osd::input_device::ABSOLUTE_MAX - osd::input_device::ABSOLUTE_MIN + 1); u8 mapval = m_map[yaxisval][xaxisval]; // handle stickiness @@ -258,14 +276,15 @@ u8 joystick_map::update(s32 xaxisval, s32 yaxisval) //------------------------------------------------- input_device::input_device(input_manager &manager, std::string_view name, std::string_view id, void *internal) - : m_manager(manager), - m_name(name), - m_id(id), - m_devindex(-1), - m_maxitem(input_item_id(0)), - m_internal(internal), - m_steadykey_enabled(manager.machine().options().steadykey()), - m_lightgun_reload_button(manager.machine().options().offscreen_reload()) + : m_manager(manager) + , m_name(name) + , m_id(id) + , m_devindex(-1) + , m_maxitem(input_item_id(0)) + , m_internal(internal) + , m_threshold(std::max<s32>(s32(manager.machine().options().joystick_threshold() * osd::input_device::ABSOLUTE_MAX), 1)) + , m_steadykey_enabled(manager.machine().options().steadykey()) + , m_lightgun_reload_button(manager.machine().options().offscreen_reload()) { } @@ -283,7 +302,12 @@ input_device::~input_device() // add_item - add a new item to an input device //------------------------------------------------- -input_item_id input_device::add_item(std::string_view name, input_item_id itemid, item_get_state_func getstate, void *internal) +input_item_id input_device::add_item( + std::string_view name, + std::string_view tokenhint, + input_item_id itemid, + item_get_state_func getstate, + void *internal) { if (machine().phase() != machine_phase::INIT) throw emu_fatalerror("Can only call input_device::add_item at init time!"); @@ -305,15 +329,15 @@ input_item_id input_device::add_item(std::string_view name, input_item_id itemid switch (m_manager.device_class(devclass()).standard_item_class(originalid)) { case ITEM_CLASS_SWITCH: - m_item[itemid] = std::make_unique<input_device_switch_item>(*this, name, internal, itemid, getstate); + m_item[itemid] = std::make_unique<input_device_switch_item>(*this, name, tokenhint, internal, itemid, getstate); break; case ITEM_CLASS_RELATIVE: - m_item[itemid] = std::make_unique<input_device_relative_item>(*this, name, internal, itemid, getstate); + m_item[itemid] = std::make_unique<input_device_relative_item>(*this, name, tokenhint, internal, itemid, getstate); break; case ITEM_CLASS_ABSOLUTE: - m_item[itemid] = std::make_unique<input_device_absolute_item>(*this, name, internal, itemid, getstate); + m_item[itemid] = std::make_unique<input_device_absolute_item>(*this, name, tokenhint, internal, itemid, getstate); break; default: @@ -328,6 +352,17 @@ input_item_id input_device::add_item(std::string_view name, input_item_id itemid //------------------------------------------------- +// set_default_assignments - set additional input +// assignments suitable for device +//------------------------------------------------- + +void input_device::set_default_assignments(assignment_vector &&assignments) +{ + m_default_assignments = std::move(assignments); +} + + +//------------------------------------------------- // match_device_id - match device id via // substring search //------------------------------------------------- @@ -411,9 +446,10 @@ input_device_lightgun::input_device_lightgun(input_manager &manager, std::string //------------------------------------------------- input_device_joystick::input_device_joystick(input_manager &manager, std::string_view _name, std::string_view _id, void *_internal) - : input_device(manager, _name, _id, _internal), - m_joystick_deadzone(s32(manager.machine().options().joystick_deadzone() * osd::INPUT_ABSOLUTE_MAX)), - m_joystick_saturation(s32(manager.machine().options().joystick_saturation() * osd::INPUT_ABSOLUTE_MAX)) + : input_device(manager, _name, _id, _internal) + , m_deadzone(s32(manager.machine().options().joystick_deadzone() * osd::input_device::ABSOLUTE_MAX)) + , m_saturation(s32(manager.machine().options().joystick_saturation() * osd::input_device::ABSOLUTE_MAX)) + , m_range(m_saturation - m_deadzone) { // get the default joystick map const char *mapstring = machine().options().joystick_map(); @@ -440,24 +476,16 @@ input_device_joystick::input_device_joystick(input_manager &manager, std::string s32 input_device_joystick::adjust_absolute_value(s32 result) const { // properties are symmetric - bool negative = false; - if (result < 0) - { - negative = true; + bool const negative = result < 0; + if (negative) result = -result; - } - // if in the deadzone, return 0 - if (result < m_joystick_deadzone) + if (result < m_deadzone) // if in the deadzone, return 0 result = 0; - - // if saturated, return the max - else if (result > m_joystick_saturation) - result = osd::INPUT_ABSOLUTE_MAX; - - // otherwise, scale - else - result = s64(result - m_joystick_deadzone) * s64(osd::INPUT_ABSOLUTE_MAX) / s64(m_joystick_saturation - m_joystick_deadzone); + else if (result >= m_saturation) // if saturated, return the max + result = osd::input_device::ABSOLUTE_MAX; + else // otherwise, scale + result = s64(result - m_deadzone) * s64(osd::input_device::ABSOLUTE_MAX) / m_range; // re-apply sign and return return negative ? -result : result; @@ -538,17 +566,21 @@ input_device &input_class::add_device(std::unique_ptr<input_device> &&new_device input_item_class input_class::standard_item_class(input_item_id itemid) const { - // most everything standard is a switch, apart from the axes if (itemid == ITEM_ID_OTHER_SWITCH || itemid < ITEM_ID_XAXIS || (itemid > ITEM_ID_SLIDER2 && itemid < ITEM_ID_ADD_ABSOLUTE1)) + { + // most everything standard is a switch, apart from the axes return ITEM_CLASS_SWITCH; - - // standard mouse axes are relative + } else if (m_devclass == DEVICE_CLASS_MOUSE || itemid == ITEM_ID_OTHER_AXIS_RELATIVE || (itemid >= ITEM_ID_ADD_RELATIVE1 && itemid <= ITEM_ID_ADD_RELATIVE16)) + { + // standard mouse axes are relative return ITEM_CLASS_RELATIVE; - - // all other standard axes are absolute + } else + { + // all other standard axes are absolute return ITEM_CLASS_ABSOLUTE; + } } @@ -667,25 +699,37 @@ bool input_class_joystick::set_global_joystick_map(const char *mapstring) // input_device_item - constructor //------------------------------------------------- -input_device_item::input_device_item(input_device &device, std::string_view name, void *internal, input_item_id itemid, item_get_state_func getstate, input_item_class itemclass) - : m_device(device), - m_name(name), - m_internal(internal), - m_itemid(itemid), - m_itemclass(itemclass), - m_getstate(getstate), - m_current(0) +input_device_item::input_device_item( + input_device &device, + std::string_view name, + std::string_view tokenhint, + void *internal, + input_item_id itemid, + item_get_state_func getstate, + input_item_class itemclass) + : m_device(device) + , m_name(name) + , m_internal(internal) + , m_itemid(itemid) + , m_itemclass(itemclass) + , m_getstate(getstate) + , m_current(0) { const char *standard_token = manager().standard_token(itemid); if (standard_token) { - // use a standard token name for know item IDs - m_token.assign(standard_token); + // use a standard token name for known item IDs + m_token = standard_token; + } + else if (!tokenhint.empty()) + { + // fall back to token hint if supplied + m_token = tokenhint; } else { // otherwise, create a tokenized name - m_token.assign(strmakeupper(name)); + m_token = strmakeupper(name); strdelchr(m_token, ' '); strdelchr(m_token, '_'); } @@ -709,7 +753,7 @@ input_device_item::~input_device_item() bool input_device_item::check_axis(input_item_modifier modifier, s32 memory) { // use osd::INVALID_AXIS_VALUE as a short-circuit - return (memory != osd::INVALID_AXIS_VALUE) && item_check_axis(modifier, memory); + return (memory != osd::input_device::INVALID_AXIS_VALUE) && item_check_axis(modifier, memory); } @@ -721,10 +765,16 @@ bool input_device_item::check_axis(input_item_modifier modifier, s32 memory) // input_device_switch_item - constructor //------------------------------------------------- -input_device_switch_item::input_device_switch_item(input_device &device, std::string_view name, void *internal, input_item_id itemid, item_get_state_func getstate) - : input_device_item(device, name, internal, itemid, getstate, ITEM_CLASS_SWITCH), - m_steadykey(0), - m_oldkey(0) +input_device_switch_item::input_device_switch_item( + input_device &device, + std::string_view name, + std::string_view tokenhint, + void *internal, + input_item_id itemid, + item_get_state_func getstate) + : input_device_item(device, name, tokenhint, internal, itemid, getstate, ITEM_CLASS_SWITCH) + , m_steadykey(0) + , m_oldkey(0) { } @@ -826,8 +876,14 @@ bool input_device_switch_item::steadykey_changed() // input_device_relative_item - constructor //------------------------------------------------- -input_device_relative_item::input_device_relative_item(input_device &device, std::string_view name, void *internal, input_item_id itemid, item_get_state_func getstate) - : input_device_item(device, name, internal, itemid, getstate, ITEM_CLASS_RELATIVE) +input_device_relative_item::input_device_relative_item( + input_device &device, + std::string_view name, + std::string_view tokenhint, + void *internal, + input_item_id itemid, + item_get_state_func getstate) + : input_device_item(device, name, tokenhint, internal, itemid, getstate, ITEM_CLASS_RELATIVE) { } @@ -894,7 +950,7 @@ bool input_device_relative_item::item_check_axis(input_item_modifier modifier, s const s32 curval = read_as_relative(modifier); // for relative axes, look for ~20 pixels movement - return std::abs(curval - memory) > (20 * osd::INPUT_RELATIVE_PER_PIXEL); + return std::abs(curval - memory) > (20 * osd::input_device::RELATIVE_PER_PIXEL); } @@ -907,8 +963,14 @@ bool input_device_relative_item::item_check_axis(input_item_modifier modifier, s // input_device_absolute_item - constructor //------------------------------------------------- -input_device_absolute_item::input_device_absolute_item(input_device &device, std::string_view name, void *internal, input_item_id itemid, item_get_state_func getstate) - : input_device_item(device, name, internal, itemid, getstate, ITEM_CLASS_ABSOLUTE) +input_device_absolute_item::input_device_absolute_item( + input_device &device, + std::string_view name, + std::string_view tokenhint, + void *internal, + input_item_id itemid, + item_get_state_func getstate) + : input_device_item(device, name, tokenhint, internal, itemid, getstate, ITEM_CLASS_ABSOLUTE) { } @@ -921,8 +983,7 @@ input_device_absolute_item::input_device_absolute_item(input_device &device, std s32 input_device_absolute_item::read_as_switch(input_item_modifier modifier) { // start with the current value - s32 result = m_device.adjust_absolute(update_value()); - assert(result >= osd::INPUT_ABSOLUTE_MIN && result <= osd::INPUT_ABSOLUTE_MAX); + s32 const result = update_value(); // left/right/up/down: if this is a joystick, fetch the paired X/Y axis values and convert if (m_device.devclass() == DEVICE_CLASS_JOYSTICK && modifier >= ITEM_MODIFIER_LEFT && modifier <= ITEM_MODIFIER_DOWN) @@ -940,18 +1001,24 @@ s32 input_device_absolute_item::read_as_switch(input_item_modifier modifier) // now map the X and Y axes to a 9x9 grid using the raw values joystick_map &joymap = downcast<input_device_joystick &>(m_device).joymap(); - return (joymap.update(xaxis_item->current(), yaxis_item->current()) >> (modifier - ITEM_MODIFIER_LEFT)) & 1; + return BIT(joymap.update(xaxis_item->current(), yaxis_item->current()), modifier - ITEM_MODIFIER_LEFT); } } - // positive/negative: true if past the deadzone in either direction - if (modifier == ITEM_MODIFIER_POS || modifier == ITEM_MODIFIER_RIGHT || modifier == ITEM_MODIFIER_DOWN) - return (result > 0); - else if (modifier == ITEM_MODIFIER_NEG || modifier == ITEM_MODIFIER_LEFT || modifier == ITEM_MODIFIER_UP) - return (result < 0); - - // all other cases just return 0 - return 0; + // positive/negative: true if past the threshold in either direction, otherwise zero + switch (modifier) + { + case ITEM_MODIFIER_POS: + case ITEM_MODIFIER_RIGHT: + case ITEM_MODIFIER_DOWN: + return result >= m_device.threshold(); + case ITEM_MODIFIER_NEG: + case ITEM_MODIFIER_LEFT: + case ITEM_MODIFIER_UP: + return -result >= m_device.threshold(); + default: + return 0; + } } @@ -977,7 +1044,7 @@ s32 input_device_absolute_item::read_as_absolute(input_item_modifier modifier) { // start with the current value s32 result = m_device.adjust_absolute(update_value()); - assert(result >= osd::INPUT_ABSOLUTE_MIN && result <= osd::INPUT_ABSOLUTE_MAX); + assert(result >= osd::input_device::ABSOLUTE_MIN && result <= osd::input_device::ABSOLUTE_MAX); // if we're doing a lightgun reload hack, override the value if (m_device.devclass() == DEVICE_CLASS_LIGHTGUN && m_device.lightgun_reload_button()) @@ -985,16 +1052,16 @@ s32 input_device_absolute_item::read_as_absolute(input_item_modifier modifier) // if it is pressed, return (min,max) input_device_item *button2_item = m_device.item(ITEM_ID_BUTTON2); if (button2_item != nullptr && button2_item->update_value()) - result = (m_itemid == ITEM_ID_XAXIS) ? osd::INPUT_ABSOLUTE_MIN : osd::INPUT_ABSOLUTE_MAX; + result = (m_itemid == ITEM_ID_XAXIS) ? osd::input_device::ABSOLUTE_MIN : osd::input_device::ABSOLUTE_MAX; } // positive/negative: scale to full axis if (modifier == ITEM_MODIFIER_REVERSE) result = -result; else if (modifier == ITEM_MODIFIER_POS) - result = std::max(result, 0) * 2 + osd::INPUT_ABSOLUTE_MIN; + result = std::max(result, 0) * 2 + osd::input_device::ABSOLUTE_MIN; else if (modifier == ITEM_MODIFIER_NEG) - result = std::max(-result, 0) * 2 + osd::INPUT_ABSOLUTE_MIN; + result = std::max(-result, 0) * 2 + osd::input_device::ABSOLUTE_MIN; return result; } @@ -1010,9 +1077,9 @@ bool input_device_absolute_item::item_check_axis(input_item_modifier modifier, s // so the selection will not be affected by a gun going out of range const s32 curval = read_as_absolute(modifier); if (m_device.devclass() == DEVICE_CLASS_LIGHTGUN && - (curval == osd::INPUT_ABSOLUTE_MAX || curval == osd::INPUT_ABSOLUTE_MIN)) + (curval == osd::input_device::ABSOLUTE_MAX || curval == osd::input_device::ABSOLUTE_MIN)) return false; // for absolute axes, look for 25% of maximum - return std::abs(curval - memory) > ((osd::INPUT_ABSOLUTE_MAX - osd::INPUT_ABSOLUTE_MIN) / 4); + return std::abs(curval - memory) > ((osd::input_device::ABSOLUTE_MAX - osd::input_device::ABSOLUTE_MIN) / 4); } diff --git a/src/emu/inputdev.h b/src/emu/inputdev.h index 78f2b6eeb95..8e914094610 100644 --- a/src/emu/inputdev.h +++ b/src/emu/inputdev.h @@ -13,7 +13,7 @@ #pragma once -#include "interface/inputman.h" +#include "interface/inputdev.h" //************************************************************************** @@ -100,7 +100,14 @@ public: protected: // construction/destruction - input_device_item(input_device &device, std::string_view name, void *internal, input_item_id itemid, item_get_state_func getstate, input_item_class itemclass); + input_device_item( + input_device &device, + std::string_view name, + std::string_view tokenhint, + void *internal, + input_item_id itemid, + item_get_state_func getstate, + input_item_class itemclass); // internal state input_device & m_device; // reference to our owning device @@ -136,16 +143,24 @@ public: const std::string &id() const { return m_id; } int devindex() const { return m_devindex; } input_device_item *item(input_item_id index) const { return m_item[index].get(); } + const assignment_vector &default_assignments() const { return m_default_assignments; } input_item_id maxitem() const { return m_maxitem; } void *internal() const { return m_internal; } + s32 threshold() const { return m_threshold; } bool steadykey_enabled() const { return m_steadykey_enabled; } bool lightgun_reload_button() const { return m_lightgun_reload_button; } // setters void set_devindex(int devindex) { m_devindex = devindex; } - // item management - virtual input_item_id add_item(std::string_view name, input_item_id itemid, item_get_state_func getstate, void *internal) override; + // interface for host input device + virtual input_item_id add_item( + std::string_view name, + std::string_view tokenhint, + input_item_id itemid, + item_get_state_func getstate, + void *internal) override; + virtual void set_default_assignments(assignment_vector &&assignments) override; // helpers s32 adjust_absolute(s32 value) const { return adjust_absolute_value(value); } @@ -163,11 +178,13 @@ private: std::string m_id; // id of device int m_devindex; // device index of this device std::unique_ptr<input_device_item> m_item[ITEM_ID_ABSOLUTE_MAXIMUM+1]; // array of pointers to items + assignment_vector m_default_assignments; // additional assignments input_item_id m_maxitem; // maximum item index - void * m_internal; // internal callback pointer + void *const m_internal; // internal callback pointer - bool m_steadykey_enabled; // steadykey enabled for keyboards - bool m_lightgun_reload_button; // lightgun reload hack + s32 const m_threshold; // threshold for treating absolute axis as active + bool const m_steadykey_enabled; // steadykey enabled for keyboards + bool const m_lightgun_reload_button; // lightgun reload hack }; @@ -238,9 +255,10 @@ protected: private: // joystick information - joystick_map m_joymap; // joystick map for this device - s32 m_joystick_deadzone; // deadzone for joystick - s32 m_joystick_saturation; // saturation position for joystick + joystick_map m_joymap; // joystick map for this device + s32 const m_deadzone; // deadzone for joystick + s32 const m_saturation; // saturation position for joystick + s64 const m_range; // difference between saturation and deadzone }; diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp index 1a16accd94c..aed29b6324f 100644 --- a/src/emu/ioport.cpp +++ b/src/emu/ioport.cpp @@ -6,107 +6,30 @@ Input/output port handling. -**************************************************************************** - - Theory of operation - - ------------ - OSD controls - ------------ - - There are three types of controls that the OSD can provide as potential - input devices: digital controls, absolute analog controls, and relative - analog controls. - - Digital controls have only two states: on or off. They are generally - mapped to buttons and digital joystick directions (like a gamepad or a - joystick hat). The OSD layer must return either 0 (off) or 1 (on) for - these types of controls. - - Absolute analog controls are analog in the sense that they return a - range of values depending on how much a given control is moved, but they - are physically bounded. This means that there is a minimum and maximum - limit to how far the control can be moved. They are generally mapped to - analog joystick axes, lightguns, most PC steering wheels, and pedals. - The OSD layer must determine the minimum and maximum range of each - analog device and scale that to a value between -65536 and +65536 - representing the position of the control. -65536 generally refers to - the topmost or leftmost position, while +65536 refers to the bottommost - or rightmost position. Note that pedals are a special case here, the - OSD layer needs to return half axis as full -65536 to + 65536 range. - - Relative analog controls are analog as well, but are not physically - bounded. They can be moved continually in one direction without limit. - They are generally mapped to trackballs and mice. Because they are - unbounded, the OSD layer can only return delta values since the last - read. Because of this, it is difficult to scale appropriately. For - MAME's purposes, when mapping a mouse devices to a relative analog - control, one pixel of movement should correspond to 512 units. Other - analog control types should be scaled to return values of a similar - magnitude. Like absolute analog controls, negative values refer to - upward or leftward movement, while positive values refer to downward - or rightward movement. - - ------------- - Game controls - ------------- - - Similarly, the types of controls used by arcade games fall into the same - three categories: digital, absolute analog, and relative analog. The - tricky part is how to map any arbitrary type of OSD control to an - arbitrary type of game control. - - Digital controls: used for game buttons and standard 4/8-way joysticks, - as well as many other types of game controls. Mapping an OSD digital - control to a game's OSD control is trivial. For OSD analog controls, - the MAME core does not directly support mapping any OSD analog devices - to digital controls. However, the OSD layer is free to enumerate digital - equivalents for analog devices. For example, each analog axis in the - Windows OSD code enumerates to two digital controls, one for the - negative direction (up/left) and one for the position direction - (down/right). When these "digital" inputs are queried, the OSD layer - checks the axis position against the center, adding in a dead zone, - and returns 0 or 1 to indicate its position. - - Absolute analog controls: used for analog joysticks, lightguns, pedals, - and wheel controls. Mapping an OSD absolute analog control to this type - is easy. OSD relative analog controls can be mapped here as well by - accumulating the deltas and bounding the results. OSD digital controls - are mapped to these types of controls in pairs, one for a decrement and - one for an increment, but apart from that, operate the same as the OSD - relative analog controls by accumulating deltas and applying bounds. - The speed of the digital delta is user-configurable per analog input. - In addition, most absolute analog control types have an autocentering - feature that is activated when using the digital increment/decrement - sequences, which returns the control back to the center at a user- - controllable speed if no digital sequences are pressed. - - Relative analog controls: used for trackballs and dial controls. Again, - mapping an OSD relative analog control to this type is straightforward. - OSD absolute analog controls can't map directly to these, but if the OSD - layer provides a digital equivalent for each direction, it can be done. - OSD digital controls map just like they do for absolute analog controls, - except that the accumulated deltas are not bounded, but rather wrap. - ***************************************************************************/ #include "emu.h" -#include "emuopts.h" + #include "config.h" +#include "emuopts.h" #include "fileio.h" -#include "xmlfile.h" -#include "profiler.h" -#include "ui/uimain.h" #include "inputdev.h" +#include "main.h" #include "natkeyboard.h" +#include "profiler.h" + +#include "ui/uimain.h" #include "util/corestr.h" #include "util/ioprocsfilter.h" #include "util/language.h" +#include "util/multibyte.h" #include "util/unicode.h" +#include "util/xmlfile.h" #include "osdepend.h" +#include <algorithm> #include <cctype> #include <ctime> @@ -163,6 +86,22 @@ inline s32 apply_scale(s32 value, s64 scale) return (s64(value) * scale) / (1 << 24); } +//------------------------------------------------- +// compute_shift -- get shift required to right- +// align an I/O port field value +//------------------------------------------------- + +inline u8 compute_shift(ioport_value mask) +{ + u8 result = 0U; + while (mask && !BIT(mask, 0)) + { + mask >>= 1; + ++result; + } + return result; +} + //************************************************************************** @@ -367,15 +306,7 @@ public: } u64 get_basetime() const { - return - (u64(m_data[OFFS_BASETIME + 0]) << (0 * 8)) | - (u64(m_data[OFFS_BASETIME + 1]) << (1 * 8)) | - (u64(m_data[OFFS_BASETIME + 2]) << (2 * 8)) | - (u64(m_data[OFFS_BASETIME + 3]) << (3 * 8)) | - (u64(m_data[OFFS_BASETIME + 4]) << (4 * 8)) | - (u64(m_data[OFFS_BASETIME + 5]) << (5 * 8)) | - (u64(m_data[OFFS_BASETIME + 6]) << (6 * 8)) | - (u64(m_data[OFFS_BASETIME + 7]) << (7 * 8)); + return get_u64le(m_data + OFFS_BASETIME); } unsigned get_majversion() const { @@ -400,14 +331,7 @@ public: } void set_basetime(u64 time) { - m_data[OFFS_BASETIME + 0] = u8((time >> (0 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 1] = u8((time >> (1 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 2] = u8((time >> (2 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 3] = u8((time >> (3 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 4] = u8((time >> (4 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 5] = u8((time >> (5 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 6] = u8((time >> (6 * 8)) & 0x00ff); - m_data[OFFS_BASETIME + 7] = u8((time >> (7 * 8)) & 0x00ff); + put_u64le(m_data + OFFS_BASETIME, time); } void set_version() { @@ -948,7 +872,7 @@ ioport_type_class ioport_field::type_class() const noexcept return INPUT_CLASS_KEYBOARD; // configuration settings (specific names required) - if (m_type == IPT_CONFIG) + if (m_type == IPT_CONFIG || m_type == IPT_ADJUSTER) return INPUT_CLASS_CONFIG; // DIP switches (specific names required) @@ -1562,12 +1486,16 @@ ioport_field_live::ioport_field_live(ioport_field &field, analog_field *analog) name.append(string_format("%-*s ", std::max(SPACE_COUNT - 1, 0), field.key_name(which))); } - // trim extra spaces - name = strtrimspace(name); - // special case if (name.empty()) name.assign("Unnamed Key"); + else + { + // trim extra spaces + auto pos = name.find_last_not_of(' '); + assert(pos < name.size()); + name.erase(pos + 1); + } } } @@ -1742,14 +1670,14 @@ void ioport_port::insert_field(ioport_field &newfield, ioport_value &disallowedb for (ioport_field *field = m_fieldlist.first(); field != nullptr; field = nextfield) { nextfield = field->next(); - if ((field->mask() & newfield.mask()) != 0 && + if ((field->mask() & newfield.mask()) && (newfield.condition().none() || field->condition().none() || field->condition() == newfield.condition())) { // reduce the mask of the field we found field->reduce_mask(newfield.mask()); // if the new entry fully overrides the previous one, we nuke - if (INPUT_PORT_OVERRIDE_FULLY_NUKES_PREVIOUS || field->mask() == 0) + if (!field->mask() || (INPUT_PORT_OVERRIDE_FULLY_NUKES_PREVIOUS && (field->type() != IPT_UNUSED) && (field->type() != IPT_UNKNOWN))) m_fieldlist.remove(*field); } } @@ -1849,6 +1777,7 @@ ioport_manager::ioport_manager(running_machine &machine) , m_playback_accumulated_speed(0) , m_playback_accumulated_frames(0) , m_deselected_card_config() + , m_applied_device_defaults(false) { for (auto &entries : m_type_to_entry) std::fill(std::begin(entries), std::end(entries), nullptr); @@ -1907,14 +1836,14 @@ time_t ioport_manager::initialize() port.second->init_live_state(); // handle autoselection of devices - init_autoselect_devices(IPT_AD_STICK_X, IPT_AD_STICK_Y, IPT_AD_STICK_Z, OPTION_ADSTICK_DEVICE, "analog joystick"); - init_autoselect_devices(IPT_PADDLE, IPT_PADDLE_V, 0, OPTION_PADDLE_DEVICE, "paddle"); - init_autoselect_devices(IPT_PEDAL, IPT_PEDAL2, IPT_PEDAL3, OPTION_PEDAL_DEVICE, "pedal"); - init_autoselect_devices(IPT_LIGHTGUN_X, IPT_LIGHTGUN_Y, 0, OPTION_LIGHTGUN_DEVICE, "lightgun"); - init_autoselect_devices(IPT_POSITIONAL, IPT_POSITIONAL_V, 0, OPTION_POSITIONAL_DEVICE, "positional"); - init_autoselect_devices(IPT_DIAL, IPT_DIAL_V, 0, OPTION_DIAL_DEVICE, "dial"); - init_autoselect_devices(IPT_TRACKBALL_X, IPT_TRACKBALL_Y, 0, OPTION_TRACKBALL_DEVICE, "trackball"); - init_autoselect_devices(IPT_MOUSE_X, IPT_MOUSE_Y, 0, OPTION_MOUSE_DEVICE, "mouse"); + init_autoselect_devices({ IPT_AD_STICK_X, IPT_AD_STICK_Y, IPT_AD_STICK_Z }, OPTION_ADSTICK_DEVICE, "analog joystick"); + init_autoselect_devices({ IPT_PADDLE, IPT_PADDLE_V }, OPTION_PADDLE_DEVICE, "paddle"); + init_autoselect_devices({ IPT_PEDAL, IPT_PEDAL2, IPT_PEDAL3 }, OPTION_PEDAL_DEVICE, "pedal"); + init_autoselect_devices({ IPT_LIGHTGUN_X, IPT_LIGHTGUN_Y }, OPTION_LIGHTGUN_DEVICE, "lightgun"); + init_autoselect_devices({ IPT_POSITIONAL, IPT_POSITIONAL_V }, OPTION_POSITIONAL_DEVICE, "positional"); + init_autoselect_devices({ IPT_DIAL, IPT_DIAL_V }, OPTION_DIAL_DEVICE, "dial"); + init_autoselect_devices({ IPT_TRACKBALL_X, IPT_TRACKBALL_Y }, OPTION_TRACKBALL_DEVICE, "trackball"); + init_autoselect_devices({ IPT_MOUSE_X, IPT_MOUSE_Y }, OPTION_MOUSE_DEVICE, "mouse"); // look for 4-way diagonal joysticks and change the default map if we find any const char *joystick_map_default = machine().options().joystick_map(); @@ -1972,39 +1901,71 @@ void ioport_manager::init_port_types() // in and the corresponding option //------------------------------------------------- -void ioport_manager::init_autoselect_devices(int type1, int type2, int type3, const char *option, const char *ananame) +void ioport_manager::init_autoselect_devices(std::initializer_list<ioport_type> types, std::string_view option, std::string_view ananame) { + static std::pair<char const *, char const *> const CLASS_OPTIONS[] = { + { "mouse", OPTION_MOUSE }, + { "joystick", OPTION_JOYSTICK }, + { "lightgun", OPTION_LIGHTGUN } }; + // if nothing specified, ignore the option - const char *stemp = machine().options().value(option); - if (stemp[0] == 0 || strcmp(stemp, "none") == 0) + auto const autooption = machine().options().get_entry(option); + char const *const autoclass = autooption->value(); + if (!autoclass || !*autoclass || !std::strcmp(autoclass, "none")) return; - // extract valid strings + // if the device class is enabled anyway or disabled at a higher priority level, do nothing + auto const classname = std::find_if( + std::begin(CLASS_OPTIONS), + std::end(CLASS_OPTIONS), + [&autoclass] (auto const &x) { return !std::strcmp(autoclass, x.first); }); + if (std::end(CLASS_OPTIONS) != classname) + { + if (machine().options().bool_value(classname->second)) + return; + + auto const classoption = machine().options().get_entry(classname->second); + if (classoption->priority() > autooption->priority()) + { + osd_printf_verbose("Input: Won't autoenable %s in presence of a %s as it's disabled at a higher priority\n", autoclass, ananame); + return; + } + } + + // find matching device class input_class *autoenable_class = nullptr; for (input_device_class devclass = DEVICE_CLASS_FIRST_VALID; devclass <= DEVICE_CLASS_LAST_VALID; ++devclass) - if (strcmp(stemp, machine().input().device_class(devclass).name()) == 0) + { + if (!std::strcmp(autoclass, machine().input().device_class(devclass).name())) { autoenable_class = &machine().input().device_class(devclass); break; } - if (autoenable_class == nullptr) + } + if (!autoenable_class) { - osd_printf_error("Invalid %s value %s; reverting to keyboard\n", option, stemp); + osd_printf_error("Invalid %s value %s; reverting to keyboard\n", option, autoclass); autoenable_class = &machine().input().device_class(DEVICE_CLASS_KEYBOARD); } - // only scan the list if we haven't already enabled this class of control - if (!autoenable_class->enabled()) - for (auto &port : m_portlist) - for (ioport_field const &field : port.second->fields()) + // nothing to do if the class is already enabled + if (autoenable_class->enabled()) + return; - // if this port type is in use, apply the autoselect criteria - if ((type1 != 0 && field.type() == type1) || (type2 != 0 && field.type() == type2) || (type3 != 0 && field.type() == type3)) - { - osd_printf_verbose("Input: Autoenabling %s due to presence of a %s\n", autoenable_class->name(), ananame); - autoenable_class->enable(); - break; - } + // scan the port list + for (auto &port : m_portlist) + { + for (ioport_field const &field : port.second->fields()) + { + // if this port type is in use, apply the autoselect criteria + if (std::find(std::begin(types), std::end(types), field.type()) != std::end(types)) + { + osd_printf_verbose("Input: Autoenabling %s due to presence of a %s\n", autoenable_class->name(), ananame); + autoenable_class->enable(); + return; + } + } + } } @@ -2195,7 +2156,7 @@ void ioport_manager::frame_update_callback() void ioport_manager::frame_update() { - g_profiler.start(PROFILER_INPUT); + auto profile = g_profiler.start(PROFILER_INPUT); // record/playback information about the current frame attotime curtime = machine().time(); @@ -2232,8 +2193,6 @@ void ioport_manager::frame_update() if (dynfield.field().type() != IPT_OUTPUT) dynfield.write(newvalue); } - - g_profiler.stop(); } @@ -2261,6 +2220,17 @@ s32 ioport_manager::frame_interpolate(s32 oldval, s32 newval) void ioport_manager::load_config(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode) { + // make sure device defaults get applied at some point + if ((cfg_type > config_type::CONTROLLER) && !m_applied_device_defaults) + { + apply_device_defaults(); + + // after applying controller config, push that to the backup, as it's what we'll diff against + for (input_type_entry &entry : m_typelist) + for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype) + entry.defseq(seqtype) = entry.seq(seqtype); + } + // in the completion phase, we finish the initialization with the final ports if (cfg_type == config_type::FINAL) { @@ -2275,9 +2245,7 @@ void ioport_manager::load_config(config_type cfg_type, config_level cfg_level, u // load device map table for controller configs only if (cfg_type == config_type::CONTROLLER) { - // iterate over all the remap nodes - load_remap_table(*parentnode); - + // iterate over device remapping entries input_manager::devicemap_table devicemap; for (util::xml::data_node const *mapdevice_node = parentnode->get_child("mapdevice"); mapdevice_node != nullptr; mapdevice_node = mapdevice_node->get_next_sibling("mapdevice")) { @@ -2287,9 +2255,23 @@ void ioport_manager::load_config(config_type cfg_type, config_level cfg_level, u devicemap.emplace(devicename, controllername); } - // map device to controller if we have a device map - if (!devicemap.empty()) - machine().input().map_device_to_controller(devicemap); + // we can't rearrange controllers after applying device-supplied defaults + if (!m_applied_device_defaults) + { + // map device to controller if we have a device map + if (!devicemap.empty()) + machine().input().map_device_to_controller(devicemap); + + // add extra default assignments for input devices + apply_device_defaults(); + } + else if (!devicemap.empty()) + { + osd_printf_warning("Controller configuration: Only <mapdevice> elements from the first applicable <system> element are applied\n"); + } + + // iterate over any input code remapping nodes + load_remap_table(*parentnode); } // iterate over all the port nodes @@ -2332,16 +2314,16 @@ void ioport_manager::load_config(config_type cfg_type, config_level cfg_level, u load_default_config(type, player, newseq); } - // after applying the controller config, push that back into the backup, since that is - // what we will diff against if (cfg_type == config_type::CONTROLLER) + { + // after applying the controller config, push that back into the backup, since that is what we will diff against for (input_type_entry &entry : m_typelist) for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype) entry.defseq(seqtype) = entry.seq(seqtype); - - // load keyboard enable/disable state - if (cfg_type == config_type::SYSTEM) + } + else if (cfg_type == config_type::SYSTEM) { + // load keyboard enable/disable state std::vector<bool> kbd_enable_set; bool keyboard_enabled = false, missing_enabled = false; natural_keyboard &natkbd = machine().natkeyboard(); @@ -2498,6 +2480,7 @@ bool ioport_manager::load_controller_config( // find the matching field ioport_value const defvalue = portnode.get_attribute_int("defvalue", 0); + bool matched = false; for (ioport_field &field : port->second->fields()) { // find the matching mask and default value @@ -2559,13 +2542,16 @@ bool ioport_manager::load_controller_config( #endif } - // successfully applied - return true; + // only break out of the loop for unconditional inputs + if (field.condition().condition() == ioport_condition::ALWAYS) + return true; + else + matched = true; } } - // no matching field - return false; + // return whether any field matched + return matched; } @@ -2636,7 +2622,10 @@ void ioport_manager::load_system_config( else if (revstring && !strcmp(revstring, "no")) field.live().analog->m_reverse = false; } - break; + + // only break out of the loop for unconditional inputs + if (field.condition().condition() == ioport_condition::ALWAYS) + break; } } } @@ -2673,6 +2662,82 @@ void ioport_manager::load_system_config( } +//------------------------------------------------- +// apply_device_defaults - add default assignments +// supplied by input devices +//------------------------------------------------- + +void ioport_manager::apply_device_defaults() +{ + // make sure this only happens once + assert(!m_applied_device_defaults); + m_applied_device_defaults = true; + + // TODO: come up with a way to deal with non-multi device classes here? + for (input_device_class classno = DEVICE_CLASS_FIRST_VALID; DEVICE_CLASS_LAST_VALID >= classno; ++classno) + { + input_class &devclass = machine().input().device_class(classno); + for (int devnum = 0; devclass.maxindex() >= devnum; ++devnum) + { + // make sure device exists + input_device const *const device = devclass.device(devnum); + if (!device) + continue; + + // iterate over default assignments + for (auto [porttype, seqtype, seq] : device->default_assignments()) + { + assert(!seq.empty()); + assert(seq.is_valid()); + assert(!seq.is_default()); + + // only apply UI assignments for first device in a class + if ((IPT_UI_FIRST < porttype) && (IPT_UI_LAST > porttype) && (device->devindex() != 0)) + continue; + + // limit to maximum player count + if (device->devindex() >= MAX_PLAYERS) + continue; + + // find a matching port in the list + auto const found = std::find_if( + m_typelist.begin(), + m_typelist.end(), + [type = porttype, device] (input_type_entry const &entry) + { + return (entry.type() == type) && (entry.player() == device->devindex()); + }); + if (m_typelist.end() == found) + continue; + + // start with the current setting + input_seq remapped(found->seq(seqtype)); + if (!remapped.empty()) + remapped += input_seq::or_code; + + // append adjusting the device index + for (int i = 0, len = seq.length(); i < len; ++i) + { + input_code code = seq[i]; + if (!code.internal()) + { + assert(code.device_class() == classno); + assert(code.device_index() == 0); + assert(code.item_id() >= ITEM_ID_FIRST_VALID); + assert(code.item_id() <= ITEM_ID_ABSOLUTE_MAXIMUM); + code.set_device_index(device->devindex()); + } + remapped += code; + } + + // apply to the entry + found->set_seq(seqtype, remapped); + } + } + } +} + + //************************************************************************** // SETTINGS SAVE @@ -2784,7 +2849,7 @@ void ioport_manager::save_game_inputs(util::xml::data_node &parentnode) // iterate over ports for (auto &port : m_portlist) for (ioport_field const &field : port.second->fields()) - if (save_this_input_field_type(field.type())) + if (save_this_input_field_type(field.type()) && field.enabled()) { // determine if we changed bool changed = false; @@ -2881,9 +2946,13 @@ Type ioport_manager::playback_read(Type &result) return result = Type(0); // read the value; if we fail, end playback - size_t read; - m_playback_stream->read(&result, sizeof(result), read); - if (sizeof(result) != read) + auto const [err, actual] = read(*m_playback_stream, &result, sizeof(result)); + if (err) + { + playback_end("Read error"); + return result = Type(0); + } + else if (sizeof(result) != actual) { playback_end("End of file"); return result = Type(0); @@ -3067,9 +3136,8 @@ void ioport_manager::record_write(Type value) value = little_endianize_int16(value); // write the value; if we fail, end recording - size_t written; - if (m_record_stream->write(&value, sizeof(value), written) || (sizeof(value) != written)) - record_end("Out of space"); + if (write(*m_record_stream, &value, sizeof(value)).first) + record_end("Write error"); } template<> @@ -3345,7 +3413,7 @@ ioport_configurer& ioport_configurer::setting_alloc(ioport_value value, const ch { // make sure we have a field if (!m_curfield) - throw emu_fatalerror("alloc_setting called with no active field (value=%X name=%s)\n", value, name); + throw emu_fatalerror("setting_alloc called with no active field (value=%X name=%s)\n", value, name); // append a new setting m_cursetting = &m_curfield->m_settinglist.emplace_back(*m_curfield, value & m_curfield->mask(), string_from_token(name)); @@ -3398,9 +3466,9 @@ ioport_configurer& ioport_configurer::onoff_alloc(const char *name, ioport_value //------------------------------------------------- dynamic_field::dynamic_field(ioport_field &field) - : m_field(field), - m_shift(0), - m_oldval(field.defvalue()) + : m_field(field) + , m_shift(0) + , m_oldval(field.defvalue()) { // fill in the data for (ioport_value mask = field.mask(); !(mask & 1); mask >>= 1) @@ -3455,45 +3523,36 @@ void dynamic_field::write(ioport_value newval) //------------------------------------------------- analog_field::analog_field(ioport_field &field) - : m_field(field), - m_shift(0), - m_adjdefvalue(field.defvalue() & field.mask()), - m_adjmin(field.minval() & field.mask()), - m_adjmax(field.maxval() & field.mask()), - m_adjoverride(field.defvalue() & field.mask()), - m_sensitivity(field.sensitivity()), - m_reverse(field.analog_reverse()), - m_delta(field.delta()), - m_centerdelta(field.centerdelta()), - m_accum(0), - m_previous(0), - m_previousanalog(0), - m_minimum(osd::INPUT_ABSOLUTE_MIN), - m_maximum(osd::INPUT_ABSOLUTE_MAX), - m_center(0), - m_reverse_val(0), - m_scalepos(0), - m_scaleneg(0), - m_keyscalepos(0), - m_keyscaleneg(0), - m_positionalscale(0), - m_absolute(false), - m_wraps(false), - m_autocenter(false), - m_single_scale(false), - m_interpolate(false), - m_lastdigital(false), - m_use_adjoverride(false) -{ - // compute the shift amount and number of bits - for (ioport_value mask = field.mask(); !(mask & 1); mask >>= 1) - m_shift++; - - // initialize core data - m_adjdefvalue >>= m_shift; - m_adjmin >>= m_shift; - m_adjmax >>= m_shift; - + : m_field(field) + , m_shift(compute_shift(field.mask())) + , m_adjdefvalue((field.defvalue() & field.mask()) >> m_shift) + , m_adjmin((field.minval() & field.mask()) >> m_shift) + , m_adjmax((field.maxval() & field.mask()) >> m_shift) + , m_adjoverride((field.defvalue() & field.mask()) >> m_shift) + , m_sensitivity(field.sensitivity()) + , m_reverse(field.analog_reverse()) + , m_delta(field.delta()) + , m_centerdelta(field.centerdelta()) + , m_accum(0) + , m_previous(0) + , m_previousanalog(0) + , m_minimum(osd::input_device::ABSOLUTE_MIN) + , m_maximum(osd::input_device::ABSOLUTE_MAX) + , m_center(0) + , m_reverse_val(0) + , m_scalepos(0) + , m_scaleneg(0) + , m_keyscalepos(0) + , m_keyscaleneg(0) + , m_positionalscale(0) + , m_absolute(false) + , m_wraps(false) + , m_autocenter(false) + , m_single_scale(false) + , m_interpolate(false) + , m_lastdigital(false) + , m_use_adjoverride(false) +{ // set basic parameters based on the configured type switch (field.type()) { @@ -3512,7 +3571,7 @@ analog_field::analog_field(ioport_field &field) case IPT_PEDAL: case IPT_PEDAL2: case IPT_PEDAL3: - m_center = osd::INPUT_ABSOLUTE_MIN; + m_center = osd::input_device::ABSOLUTE_MIN; m_accum = apply_inverse_sensitivity(m_center); m_absolute = true; m_autocenter = true; @@ -3531,7 +3590,7 @@ analog_field::analog_field(ioport_field &field) // set each position to be 512 units case IPT_POSITIONAL: case IPT_POSITIONAL_V: - m_positionalscale = compute_scale(field.maxval(), osd::INPUT_ABSOLUTE_MAX - osd::INPUT_ABSOLUTE_MIN); + m_positionalscale = compute_scale(field.maxval(), osd::input_device::ABSOLUTE_MAX - osd::input_device::ABSOLUTE_MIN); m_adjmin = 0; m_adjmax = field.maxval() - 1; m_wraps = field.analog_wraps(); @@ -3557,21 +3616,23 @@ analog_field::analog_field(ioport_field &field) fatalerror("Unknown analog port type -- don't know if it is absolute or not\n"); } - // further processing for absolute controls if (m_absolute) { + // further processing for absolute controls + // if the default value is pegged at the min or max, use a single scale value for the whole axis m_single_scale = (m_adjdefvalue == m_adjmin) || (m_adjdefvalue == m_adjmax); // if not "single scale", compute separate scales for each side of the default if (!m_single_scale) { - // unsigned - m_scalepos = compute_scale(m_adjmax - m_adjdefvalue, osd::INPUT_ABSOLUTE_MAX - 0); - m_scaleneg = compute_scale(m_adjdefvalue - m_adjmin, 0 - osd::INPUT_ABSOLUTE_MIN); - - if (m_adjmin > m_adjmax) - m_scaleneg = -m_scaleneg; + // unsigned, potentially passing through zero + m_scalepos = compute_scale( + (m_adjmax - m_adjdefvalue) & (field.mask() >> m_shift), + osd::input_device::ABSOLUTE_MAX); + m_scaleneg = compute_scale( + (m_adjdefvalue - m_adjmin) & (field.mask() >> m_shift), + -osd::input_device::ABSOLUTE_MIN); // reverse point is at center m_reverse_val = 0; @@ -3579,7 +3640,7 @@ analog_field::analog_field(ioport_field &field) else { // single axis that increases from default - m_scalepos = compute_scale(m_adjmax - m_adjmin, osd::INPUT_ABSOLUTE_MAX - osd::INPUT_ABSOLUTE_MIN); + m_scalepos = compute_scale(m_adjmax - m_adjmin, osd::input_device::ABSOLUTE_MAX - osd::input_device::ABSOLUTE_MIN); // make the scaling the same for easier coding when we need to scale m_scaleneg = m_scalepos; @@ -3588,11 +3649,11 @@ analog_field::analog_field(ioport_field &field) m_reverse_val = m_maximum; } } - - // relative and positional controls all map directly with a 512x scale factor else { - // The relative code is set up to allow specifing PORT_MINMAX and default values. + // relative and positional controls all map directly with a 512x scale factor + + // The relative code is set up to allow specifying PORT_MINMAX and default values. // The validity checks are purposely set up to not allow you to use anything other // a default of 0 and PORT_MINMAX(0,mask). This is in case the need arises to use // this feature in the future. Keeping the code in does not hurt anything. @@ -3603,15 +3664,17 @@ analog_field::analog_field(ioport_field &field) if (m_wraps) m_adjmax++; - m_minimum = (m_adjmin - m_adjdefvalue) * osd::INPUT_RELATIVE_PER_PIXEL; - m_maximum = (m_adjmax - m_adjdefvalue) * osd::INPUT_RELATIVE_PER_PIXEL; + m_minimum = (m_adjmin - m_adjdefvalue) * osd::input_device::RELATIVE_PER_PIXEL; + m_maximum = (m_adjmax - m_adjdefvalue) * osd::input_device::RELATIVE_PER_PIXEL; // make the scaling the same for easier coding when we need to scale - m_scaleneg = m_scalepos = compute_scale(1, osd::INPUT_RELATIVE_PER_PIXEL); + m_scaleneg = m_scalepos = compute_scale(1, osd::input_device::RELATIVE_PER_PIXEL); if (m_field.analog_reset()) + { // delta values reverse from center m_reverse_val = 0; + } else { // positional controls reverse from their max range @@ -3620,11 +3683,11 @@ analog_field::analog_field(ioport_field &field) // relative controls reverse from 1 past their max range if (m_wraps) { - // FIXME: positional needs -1, using osd::INPUT_RELATIVE_PER_PIXEL skips a position (and reads outside the table array) - if(field.type() == IPT_POSITIONAL || field.type() == IPT_POSITIONAL_V) - m_reverse_val --; + // FIXME: positional needs -1, using osd::input_device::RELATIVE_PER_PIXEL skips a position (and reads outside the table array) + if (field.type() == IPT_POSITIONAL || field.type() == IPT_POSITIONAL_V) + m_reverse_val--; else - m_reverse_val -= osd::INPUT_RELATIVE_PER_PIXEL; + m_reverse_val -= osd::input_device::RELATIVE_PER_PIXEL; } } } @@ -3697,7 +3760,7 @@ s32 analog_field::apply_settings(s32 value) const else if (m_single_scale) // it's a pedal or the default value is equal to min/max // so we need to adjust the center to the minimum - value -= osd::INPUT_ABSOLUTE_MIN; + value -= osd::input_device::ABSOLUTE_MIN; // map differently for positive and negative values if (value >= 0) @@ -3802,7 +3865,7 @@ void analog_field::frame_update(running_machine &machine) // if port is positional, we will take the full analog control and divide it // into positions, that way as the control is moved full scale, // it moves through all the positions - rawvalue = apply_scale(rawvalue - osd::INPUT_ABSOLUTE_MIN, m_positionalscale) * osd::INPUT_RELATIVE_PER_PIXEL + m_minimum; + rawvalue = apply_scale(rawvalue - osd::input_device::ABSOLUTE_MIN, m_positionalscale) * osd::input_device::RELATIVE_PER_PIXEL + m_minimum; // clamp the high value so it does not roll over rawvalue = std::min(rawvalue, m_maximum); diff --git a/src/emu/ioport.h b/src/emu/ioport.h index b290da8f794..bbff70db21d 100644 --- a/src/emu/ioport.h +++ b/src/emu/ioport.h @@ -17,12 +17,15 @@ #ifndef MAME_EMU_IOPORT_H #define MAME_EMU_IOPORT_H +#include "inpttype.h" + #include "ioprocs.h" #include <array> #include <cstdint> #include <cstring> #include <ctime> +#include <initializer_list> #include <list> #include <memory> #include <vector> @@ -48,18 +51,6 @@ constexpr char32_t UCHAR_SHIFT_END = UCHAR_SHIFT_2; constexpr char32_t UCHAR_MAMEKEY_BEGIN = UCHAR_PRIVATE + 2; -// sequence types for input_port_seq() call -enum input_seq_type -{ - SEQ_TYPE_INVALID = -1, - SEQ_TYPE_STANDARD = 0, - SEQ_TYPE_INCREMENT, - SEQ_TYPE_DECREMENT, - SEQ_TYPE_TOTAL -}; -DECLARE_ENUM_INCDEC_OPERATORS(input_seq_type) - - // crosshair types enum crosshair_axis_t { @@ -89,323 +80,6 @@ enum ioport_group }; -// various input port types -enum ioport_type -{ - // pseudo-port types - IPT_INVALID = 0, - IPT_UNUSED, - IPT_END, - IPT_UNKNOWN, - IPT_PORT, - IPT_DIPSWITCH, - IPT_CONFIG, - - // start buttons - IPT_START1, - IPT_START2, - IPT_START3, - IPT_START4, - IPT_START5, - IPT_START6, - IPT_START7, - IPT_START8, - IPT_START9, - IPT_START10, - - // coin slots - IPT_COIN1, - IPT_COIN2, - IPT_COIN3, - IPT_COIN4, - IPT_COIN5, - IPT_COIN6, - IPT_COIN7, - IPT_COIN8, - IPT_COIN9, - IPT_COIN10, - IPT_COIN11, - IPT_COIN12, - IPT_BILL1, - - // service coin - IPT_SERVICE1, - IPT_SERVICE2, - IPT_SERVICE3, - IPT_SERVICE4, - - // tilt inputs - IPT_TILT1, - IPT_TILT2, - IPT_TILT3, - IPT_TILT4, - - // misc other digital inputs - IPT_POWER_ON, - IPT_POWER_OFF, - IPT_SERVICE, - IPT_TILT, - IPT_INTERLOCK, - IPT_MEMORY_RESET, - IPT_VOLUME_UP, - IPT_VOLUME_DOWN, - IPT_START, // use the numbered start button(s) for coin-ops - IPT_SELECT, - IPT_KEYPAD, - IPT_KEYBOARD, - - // digital joystick inputs - IPT_DIGITAL_JOYSTICK_FIRST, - - // use IPT_JOYSTICK for panels where the player has one single joystick - IPT_JOYSTICK_UP, - IPT_JOYSTICK_DOWN, - IPT_JOYSTICK_LEFT, - IPT_JOYSTICK_RIGHT, - - // use IPT_JOYSTICKLEFT and IPT_JOYSTICKRIGHT for dual joystick panels - IPT_JOYSTICKRIGHT_UP, - IPT_JOYSTICKRIGHT_DOWN, - IPT_JOYSTICKRIGHT_LEFT, - IPT_JOYSTICKRIGHT_RIGHT, - IPT_JOYSTICKLEFT_UP, - IPT_JOYSTICKLEFT_DOWN, - IPT_JOYSTICKLEFT_LEFT, - IPT_JOYSTICKLEFT_RIGHT, - - IPT_DIGITAL_JOYSTICK_LAST, - - // action buttons - IPT_BUTTON1, - IPT_BUTTON2, - IPT_BUTTON3, - IPT_BUTTON4, - IPT_BUTTON5, - IPT_BUTTON6, - IPT_BUTTON7, - IPT_BUTTON8, - IPT_BUTTON9, - IPT_BUTTON10, - IPT_BUTTON11, - IPT_BUTTON12, - IPT_BUTTON13, - IPT_BUTTON14, - IPT_BUTTON15, - IPT_BUTTON16, - - // mahjong inputs - IPT_MAHJONG_FIRST, - - IPT_MAHJONG_A, - IPT_MAHJONG_B, - IPT_MAHJONG_C, - IPT_MAHJONG_D, - IPT_MAHJONG_E, - IPT_MAHJONG_F, - IPT_MAHJONG_G, - IPT_MAHJONG_H, - IPT_MAHJONG_I, - IPT_MAHJONG_J, - IPT_MAHJONG_K, - IPT_MAHJONG_L, - IPT_MAHJONG_M, - IPT_MAHJONG_N, - IPT_MAHJONG_O, - IPT_MAHJONG_P, - IPT_MAHJONG_Q, - IPT_MAHJONG_KAN, - IPT_MAHJONG_PON, - IPT_MAHJONG_CHI, - IPT_MAHJONG_REACH, - IPT_MAHJONG_RON, - IPT_MAHJONG_FLIP_FLOP, - IPT_MAHJONG_BET, - IPT_MAHJONG_SCORE, - IPT_MAHJONG_DOUBLE_UP, - IPT_MAHJONG_BIG, - IPT_MAHJONG_SMALL, - IPT_MAHJONG_LAST_CHANCE, - - IPT_MAHJONG_LAST, - - // hanafuda inputs - IPT_HANAFUDA_FIRST, - - IPT_HANAFUDA_A, - IPT_HANAFUDA_B, - IPT_HANAFUDA_C, - IPT_HANAFUDA_D, - IPT_HANAFUDA_E, - IPT_HANAFUDA_F, - IPT_HANAFUDA_G, - IPT_HANAFUDA_H, - IPT_HANAFUDA_YES, - IPT_HANAFUDA_NO, - - IPT_HANAFUDA_LAST, - - // gambling inputs - IPT_GAMBLING_FIRST, - - IPT_GAMBLE_KEYIN, // attendant - IPT_GAMBLE_KEYOUT, // attendant - IPT_GAMBLE_SERVICE, // attendant - IPT_GAMBLE_BOOK, // attendant - IPT_GAMBLE_DOOR, // attendant - // IPT_GAMBLE_DOOR2, // many gambling games have several doors. - // IPT_GAMBLE_DOOR3, - // IPT_GAMBLE_DOOR4, - // IPT_GAMBLE_DOOR5, - - IPT_GAMBLE_PAYOUT, // player - IPT_GAMBLE_BET, // player - IPT_GAMBLE_DEAL, // player - IPT_GAMBLE_STAND, // player - IPT_GAMBLE_TAKE, // player - IPT_GAMBLE_D_UP, // player - IPT_GAMBLE_HALF, // player - IPT_GAMBLE_HIGH, // player - IPT_GAMBLE_LOW, // player - - // poker-specific inputs - IPT_POKER_HOLD1, - IPT_POKER_HOLD2, - IPT_POKER_HOLD3, - IPT_POKER_HOLD4, - IPT_POKER_HOLD5, - IPT_POKER_CANCEL, - - // slot-specific inputs - IPT_SLOT_STOP1, - IPT_SLOT_STOP2, - IPT_SLOT_STOP3, - IPT_SLOT_STOP4, - IPT_SLOT_STOP_ALL, - - IPT_GAMBLING_LAST, - - // analog inputs - IPT_ANALOG_FIRST, - - IPT_ANALOG_ABSOLUTE_FIRST, - - IPT_AD_STICK_X, // absolute // autocenter - IPT_AD_STICK_Y, // absolute // autocenter - IPT_AD_STICK_Z, // absolute // autocenter - IPT_PADDLE, // absolute // autocenter - IPT_PADDLE_V, // absolute // autocenter - IPT_PEDAL, // absolute // autocenter - IPT_PEDAL2, // absolute // autocenter - IPT_PEDAL3, // absolute // autocenter - IPT_LIGHTGUN_X, // absolute - IPT_LIGHTGUN_Y, // absolute - IPT_POSITIONAL, // absolute // autocenter if not wraps - IPT_POSITIONAL_V, // absolute // autocenter if not wraps - - IPT_ANALOG_ABSOLUTE_LAST, - - IPT_DIAL, // relative - IPT_DIAL_V, // relative - IPT_TRACKBALL_X, // relative - IPT_TRACKBALL_Y, // relative - IPT_MOUSE_X, // relative - IPT_MOUSE_Y, // relative - - IPT_ANALOG_LAST, - - // analog adjuster support - IPT_ADJUSTER, - - // the following are special codes for user interface handling - not to be used by drivers! - IPT_UI_FIRST, - - IPT_UI_CONFIGURE, - IPT_UI_ON_SCREEN_DISPLAY, - IPT_UI_DEBUG_BREAK, - IPT_UI_PAUSE, - IPT_UI_PAUSE_SINGLE, - IPT_UI_REWIND_SINGLE, - IPT_UI_RESET_MACHINE, - IPT_UI_SOFT_RESET, - IPT_UI_SHOW_GFX, - IPT_UI_FRAMESKIP_DEC, - IPT_UI_FRAMESKIP_INC, - IPT_UI_THROTTLE, - IPT_UI_FAST_FORWARD, - IPT_UI_SHOW_FPS, - IPT_UI_SNAPSHOT, - IPT_UI_RECORD_MNG, - IPT_UI_RECORD_AVI, - IPT_UI_TOGGLE_CHEAT, - IPT_UI_UP, - IPT_UI_DOWN, - IPT_UI_LEFT, - IPT_UI_RIGHT, - IPT_UI_HOME, - IPT_UI_END, - IPT_UI_PAGE_UP, - IPT_UI_PAGE_DOWN, - IPT_UI_FOCUS_NEXT, - IPT_UI_FOCUS_PREV, - IPT_UI_SELECT, - IPT_UI_CANCEL, - IPT_UI_DISPLAY_COMMENT, - IPT_UI_CLEAR, - IPT_UI_ZOOM_IN, - IPT_UI_ZOOM_OUT, - IPT_UI_ZOOM_DEFAULT, - IPT_UI_PREV_GROUP, - IPT_UI_NEXT_GROUP, - IPT_UI_ROTATE, - IPT_UI_SHOW_PROFILER, - IPT_UI_TOGGLE_UI, - IPT_UI_RELEASE_POINTER, - IPT_UI_PASTE, - IPT_UI_SAVE_STATE, - IPT_UI_LOAD_STATE, - IPT_UI_TAPE_START, - IPT_UI_TAPE_STOP, - IPT_UI_DATS, - IPT_UI_FAVORITES, - IPT_UI_EXPORT, - IPT_UI_AUDIT, - - // additional OSD-specified UI port types (up to 16) - IPT_OSD_1, - IPT_OSD_2, - IPT_OSD_3, - IPT_OSD_4, - IPT_OSD_5, - IPT_OSD_6, - IPT_OSD_7, - IPT_OSD_8, - IPT_OSD_9, - IPT_OSD_10, - IPT_OSD_11, - IPT_OSD_12, - IPT_OSD_13, - IPT_OSD_14, - IPT_OSD_15, - IPT_OSD_16, - - IPT_UI_LAST, - - IPT_OTHER, // not mapped to standard defaults - - IPT_SPECIAL, // uninterpreted characters - IPT_CUSTOM, // handled by custom code - IPT_OUTPUT, - - IPT_COUNT -}; -DECLARE_ENUM_INCDEC_OPERATORS(ioport_type) -// aliases for some types -#define IPT_PADDLE_H IPT_PADDLE -#define IPT_PEDAL1 IPT_PEDAL -#define IPT_POSITIONAL_H IPT_POSITIONAL -#define IPT_DIAL_H IPT_DIAL - - // input type classes enum ioport_type_class { @@ -1165,8 +839,8 @@ private: ioport_field & m_field; // pointer to the input field referenced // adjusted values (right-justified and tweaked) - u8 m_shift; // shift to align final value in the port - s32 m_adjdefvalue; // adjusted default value from the config + u8 const m_shift; // shift to align final value in the port + s32 const m_adjdefvalue; // adjusted default value from the config s32 m_adjmin; // adjusted minimum value from the config s32 m_adjmax; // adjusted maximum value from the config s32 m_adjoverride; // programmatically set adjusted value @@ -1288,7 +962,7 @@ public: private: // internal helpers void init_port_types(); - void init_autoselect_devices(int type1, int type2, int type3, const char *option, const char *ananame); + void init_autoselect_devices(std::initializer_list<ioport_type> types, std::string_view option, std::string_view ananame); void frame_update_callback(); void frame_update(); @@ -1303,6 +977,7 @@ private: bool load_default_config(int type, int player, const std::pair<input_seq, char const *> (&newseq)[SEQ_TYPE_TOTAL]); bool load_controller_config(util::xml::data_node const &portnode, int type, int player, const std::pair<input_seq, char const *> (&newseq)[SEQ_TYPE_TOTAL]); void load_system_config(util::xml::data_node const &portnode, int type, int player, const std::pair<input_seq, char const *> (&newseq)[SEQ_TYPE_TOTAL]); + void apply_device_defaults(); void save_config(config_type cfg_type, util::xml::data_node *parentnode); bool save_this_input_field_type(ioport_type type); @@ -1347,6 +1022,7 @@ private: // storage for inactive configuration std::unique_ptr<util::xml::file> m_deselected_card_config; + bool m_applied_device_defaults; }; @@ -1547,10 +1223,10 @@ ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, s configurer.field_set_crosshair(CROSSHAIR_AXIS_##axis, altaxis, scale, offset); #define PORT_CROSSHAIR_MAPPER(_callback) \ - configurer.field_set_crossmapper(ioport_field_crossmap_delegate(_callback, #_callback, DEVICE_SELF, (device_t *)nullptr)); + configurer.field_set_crossmapper(ioport_field_crossmap_delegate(owner, DEVICE_SELF, _callback, #_callback)); #define PORT_CROSSHAIR_MAPPER_MEMBER(_device, _class, _member) \ - configurer.field_set_crossmapper(ioport_field_crossmap_delegate(&_class::_member, #_class "::" #_member, _device, (_class *)nullptr)); + configurer.field_set_crossmapper(ioport_field_crossmap_delegate(owner, _device, &_class::_member, #_class "::" #_member)); // how many optical counts for 1 full turn of the control #define PORT_FULL_TURN_COUNT(_count) \ diff --git a/src/emu/layout/dualhovu.lay b/src/emu/layout/dualhovu.lay index e4fdb3bf943..0cd46b2d5c7 100644 --- a/src/emu/layout/dualhovu.lay +++ b/src/emu/layout/dualhovu.lay @@ -1,6 +1,6 @@ <?xml version="1.0"?> <!-- -license:CC0 +license:CC0-1.0 --> <mamelayout version="2"> <view name="Dual Over-Under"> diff --git a/src/emu/layout/dualhsxs.lay b/src/emu/layout/dualhsxs.lay index 18a9eaf908a..f032d0fd48d 100644 --- a/src/emu/layout/dualhsxs.lay +++ b/src/emu/layout/dualhsxs.lay @@ -1,6 +1,6 @@ <?xml version="1.0"?> <!-- -license:CC0 +license:CC0-1.0 --> <mamelayout version="2"> <view name="Dual Side-by-Side"> diff --git a/src/emu/layout/dualhuov.lay b/src/emu/layout/dualhuov.lay index b03d7a93258..8a94ca43dc7 100644 --- a/src/emu/layout/dualhuov.lay +++ b/src/emu/layout/dualhuov.lay @@ -1,6 +1,6 @@ <?xml version="1.0"?> <!-- -license:CC0 +license:CC0-1.0 --> <mamelayout version="2"> <view name="Dual Under-Over"> diff --git a/src/emu/layout/ex800.lay b/src/emu/layout/ex800.lay index 013ea3c4e4c..208fa7bc890 100644 --- a/src/emu/layout/ex800.lay +++ b/src/emu/layout/ex800.lay @@ -1,6 +1,6 @@ <?xml version="1.0"?> <!-- -license:CC0 +license:CC0-1.0 copyright-holders:Dirk Best --> <mamelayout version="2"> diff --git a/src/emu/layout/exorterm155.lay b/src/emu/layout/exorterm155.lay index 9da2b5ed7ef..28bb61c0d68 100644 --- a/src/emu/layout/exorterm155.lay +++ b/src/emu/layout/exorterm155.lay @@ -1,6 +1,6 @@ <?xml version="1.0"?> <!-- -license:CC0 +license:CC0-1.0 LEDs for the Motorola EXORterm 155 --> diff --git a/src/emu/layout/hp9122c.lay b/src/emu/layout/hp9122c.lay index 46c197908fc..418d8964fbf 100644 --- a/src/emu/layout/hp9122c.lay +++ b/src/emu/layout/hp9122c.lay @@ -1,6 +1,6 @@ <?xml version="1.0"?> <!-- -license:CC0 +license:CC0-1.0 copyright-holders:Sven Schnelle Hewlett-Packard HP 9122C floppy drive Layout --> diff --git a/src/emu/layout/ie15.lay b/src/emu/layout/ie15.lay index 255e2022ef8..287fcbdf77a 100644 --- a/src/emu/layout/ie15.lay +++ b/src/emu/layout/ie15.lay @@ -1,6 +1,6 @@ <?xml version="1.0"?> <!-- -license:CC0 +license:CC0-1.0 --> <mamelayout version="2"> diff --git a/src/emu/layout/lx800.lay b/src/emu/layout/lx800.lay index 90a7dbbc742..20303e50eab 100644 --- a/src/emu/layout/lx800.lay +++ b/src/emu/layout/lx800.lay @@ -1,6 +1,6 @@ <?xml version="1.0"?> <!-- -license:CC0 +license:CC0-1.0 copyright-holders:Dirk Best --> <mamelayout version="2"> diff --git a/src/emu/layout/monitors.lay b/src/emu/layout/monitors.lay index c6391b16a12..b7a4f82f75a 100644 --- a/src/emu/layout/monitors.lay +++ b/src/emu/layout/monitors.lay @@ -1,6 +1,6 @@ <?xml version="1.0"?> <!-- -license:CC0 +license:CC0-1.0 --> <mamelayout version="2"> <view name="4:3 Standard"> diff --git a/src/emu/layout/nes_rob.lay b/src/emu/layout/nes_rob.lay index 2cff2a814ad..c5b10747151 100644 --- a/src/emu/layout/nes_rob.lay +++ b/src/emu/layout/nes_rob.lay @@ -1,6 +1,7 @@ <?xml version="1.0"?> <!-- -license:CC0 +license:CC0-1.0 +authors:hap --> <mamelayout version="2"> diff --git a/src/emu/layout/noscreens.lay b/src/emu/layout/noscreens.lay index 39913376cbb..e74d12e31a5 100644 --- a/src/emu/layout/noscreens.lay +++ b/src/emu/layout/noscreens.lay @@ -1,6 +1,6 @@ <?xml version="1.0"?> <!-- -license:CC0 +license:CC0-1.0 --> <mamelayout version="2"> <element name="warning"> @@ -9,9 +9,9 @@ license:CC0 </text> </element> <view name="No screens attached"> - <bounds left="0" top="0" right="280" bottom="150" /> + <bounds left="0" top="0" right="400" bottom="300" /> <element name="warning_txt" ref="warning"> - <bounds left="50" right="230" top="50" bottom="65" /> + <bounds xc="200" yc="150" width="400" height="25" /> </element> </view> </mamelayout> diff --git a/src/emu/layout/quadhsxs.lay b/src/emu/layout/quadhsxs.lay index 1da154bb024..d8f776cb238 100644 --- a/src/emu/layout/quadhsxs.lay +++ b/src/emu/layout/quadhsxs.lay @@ -1,6 +1,6 @@ <?xml version="1.0"?> <!-- -license:CC0 +license:CC0-1.0 --> <mamelayout version="2"> <view name="Quad Side-by-Side"> diff --git a/src/emu/layout/qx10ascii.lay b/src/emu/layout/qx10ascii.lay new file mode 100644 index 00000000000..c00c7c88876 --- /dev/null +++ b/src/emu/layout/qx10ascii.lay @@ -0,0 +1,98 @@ +<?xml version="1.0"?> +<!-- +license:CC0-1.0 +--> +<mamelayout version="2"> + <element name="led" defstate="1"> + <disk state="0"> + <color red="0.75" green="0.0" blue="0.0" /> + </disk> + <disk state="1"> + <color red="0.20" green="0.0" blue="0.0" /> + </disk> + </element> + + <element name="capslock"> + <text string="CAPS"> + <color red="1.0" green="1.0" blue="1.0" /> + </text> + </element> + <element name="insert"> + <text string="INS"> + <color red="1.0" green="1.0" blue="1.0" /> + </text> + </element> + <element name="sf1"> + <text string="SF1"> + <color red="1.0" green="1.0" blue="1.0" /> + </text> + </element> + <element name="sf2"> + <text string="SF2"> + <color red="1.0" green="1.0" blue="1.0" /> + </text> + </element> + <element name="sf3"> + <text string="SF3"> + <color red="1.0" green="1.0" blue="1.0" /> + </text> + </element> + <element name="sf4"> + <text string="SF4"> + <color red="1.0" green="1.0" blue="1.0" /> + </text> + </element> + + <view name="Default Layout"> + <screen index="0"> + <bounds x="0" y="30" width="640" height="480" /> + </screen> + + <element name="led0" ref="led"> + <bounds x="33" y="17" width="10" height="10" /> + </element> + + <element name="led2" ref="led"> + <bounds x="53" y="17" width="10" height="10" /> + </element> + + <element name="led7" ref="led"> + <bounds x="83" y="17" width="10" height="10" /> + </element> + + <element name="led6" ref="led"> + <bounds x="103" y="17" width="10" height="10" /> + </element> + + <element name="led5" ref="led"> + <bounds x="123" y="17" width="10" height="10" /> + </element> + <element name="led4" ref="led"> + <bounds x="143" y="17" width="10" height="10" /> + </element> + + <element name="label1" ref="capslock"> + <bounds x="31" y="0" width="15" height="15" /> + </element> + + <element name="label2" ref="insert"> + <bounds x="51" y="0" width="15" height="15" /> + </element> + + <element name="label3" ref="sf1"> + <bounds x="81" y="0" width="15" height="15" /> + </element> + + <element name="label4" ref="sf2"> + <bounds x="101" y="0" width="15" height="15" /> + </element> + + <element name="label5" ref="sf3"> + <bounds x="121" y="0" width="15" height="15" /> + </element> + + <element name="label6" ref="sf4"> + <bounds x="141" y="0" width="15" height="15" /> + </element> + </view> +</mamelayout> diff --git a/src/emu/layout/qx10hasci.lay b/src/emu/layout/qx10hasci.lay new file mode 100644 index 00000000000..f0dadc6a0fa --- /dev/null +++ b/src/emu/layout/qx10hasci.lay @@ -0,0 +1,86 @@ +<?xml version="1.0"?> +<!-- +license:CC0-1.0 +--> +<mamelayout version="2"> + <element name="led" defstate="1"> + <disk state="0"> + <color red="0.75" green="0.0" blue="0.0" /> + </disk> + <disk state="1"> + <color red="0.20" green="0.0" blue="0.0" /> + </disk> + </element> + + <element name="capslock"> + <text string="CAPS"> + <color red="1.0" green="1.0" blue="1.0" /> + </text> + </element> + <element name="insert"> + <text string="INS"> + <color red="1.0" green="1.0" blue="1.0" /> + </text> + </element> + <element name="sf1"> + <text string="CALC"> + <color red="1.0" green="1.0" blue="1.0" /> + </text> + </element> + <element name="sf2"> + <text string="SCHED"> + <color red="1.0" green="1.0" blue="1.0" /> + </text> + </element> + <element name="sf3"> + <text string="DRAW"> + <color red="1.0" green="1.0" blue="1.0" /> + </text> + </element> + + <view name="Default Layout"> + <screen index="0"> + <bounds x="0" y="30" width="640" height="480" /> + </screen> + + <element name="led3" ref="led"> + <bounds x="33" y="17" width="10" height="10" /> + </element> + + <element name="led2" ref="led"> + <bounds x="53" y="17" width="10" height="10" /> + </element> + + <element name="led7" ref="led"> + <bounds x="83" y="17" width="10" height="10" /> + </element> + + <element name="led6" ref="led"> + <bounds x="103" y="17" width="10" height="10" /> + </element> + + <element name="led5" ref="led"> + <bounds x="123" y="17" width="10" height="10" /> + </element> + + <element name="label1" ref="capslock"> + <bounds x="31" y="0" width="15" height="15" /> + </element> + + <element name="label2" ref="insert"> + <bounds x="51" y="0" width="15" height="15" /> + </element> + + <element name="label3" ref="sf1"> + <bounds x="81" y="0" width="15" height="15" /> + </element> + + <element name="label4" ref="sf2"> + <bounds x="101" y="0" width="15" height="15" /> + </element> + + <element name="label5" ref="sf3"> + <bounds x="121" y="0" width="15" height="15" /> + </element> + </view> +</mamelayout> diff --git a/src/emu/layout/smartboard.lay b/src/emu/layout/smartboard.lay index 885f914ec67..1b028bc23fe 100644 --- a/src/emu/layout/smartboard.lay +++ b/src/emu/layout/smartboard.lay @@ -1,6 +1,7 @@ <?xml version="1.0"?> <!-- -license:CC0 +license:CC0-1.0 +authors:Sandro Ronco, hap --> <mamelayout version="2"> @@ -12,7 +13,7 @@ license:CC0 <disk><color red="0.1" green="0.05" blue="0.07" /></disk> </element> <element name="ledr" defstate="0"> - <disk state="1"> <color red="1" green="0" blue="0" /> </disk> + <disk state="1"><color red="1" green="0" blue="0" /></disk> </element> <element name="piece" defstate="0"> @@ -84,22 +85,22 @@ license:CC0 <image file="chess/bp.svg" state="64"><color alpha="0.5" /></image> </element> - <element name="text_1"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="1"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_2"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="2"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_3"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="3"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_4"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="4"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_5"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="5"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_6"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="6"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_7"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="7"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_8"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="8"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_a"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="A"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_b"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="B"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_c"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="C"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_d"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="D"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_e"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="E"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_f"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="F"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_g"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="G"> <color red="1" green="1" blue="1" /></text> </element> - <element name="text_h"> <rect><color red="0.56" green="0.33" blue="0.12" /></rect> <text string="H"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_1"> <text string="1"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_2"> <text string="2"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_3"> <text string="3"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_4"> <text string="4"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_5"> <text string="5"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_6"> <text string="6"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_7"> <text string="7"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_8"> <text string="8"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_a"> <text string="A"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_b"> <text string="B"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_c"> <text string="C"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_d"> <text string="D"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_e"> <text string="E"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_f"> <text string="F"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_g"> <text string="G"> <color red="1" green="1" blue="1" /></text> </element> + <element name="text_h"> <text string="H"> <color red="1" green="1" blue="1" /></text> </element> <!-- sb board --> @@ -317,43 +318,23 @@ license:CC0 <element name="text_uit1"><text string="S.BOARD"><color red="0.81" green="0.8" blue="0.79" /></text></element> <element name="text_uit2"><text string="INTERFACE"><color red="0.81" green="0.8" blue="0.79" /></text></element> <element name="text_uib1"><text string="BOARD:"><color red="0.81" green="0.8" blue="0.79" /></text></element> - <element name="text_uib2"> - <rect><color red="0.84" green="0.75" blue="0.50" /></rect> - <text string="RESET"><color red="0.01" green="0.01" blue="0.01" /></text> - </element> - <element name="text_uib3"> - <rect><color red="0.84" green="0.75" blue="0.50" /></rect> - <text string="CLEAR"><color red="0.01" green="0.01" blue="0.01" /></text> - </element> + <element name="text_uib2"><text string="RESET"><color red="0.01" green="0.01" blue="0.01" /></text></element> + <element name="text_uib3"><text string="CLEAR"><color red="0.01" green="0.01" blue="0.01" /></text></element> <element name="text_uis1"><text string="SPAWN:"><color red="0.81" green="0.8" blue="0.79" /></text></element> <element name="text_uih1"><text string="HAND:"><color red="0.81" green="0.8" blue="0.79" /></text></element> - <element name="text_uih2"> - <rect><color red="0.84" green="0.75" blue="0.50" /></rect> - <text string="REMOVE"><color red="0.01" green="0.01" blue="0.01" /></text> - </element> + <element name="text_uih2"><text string="REMOVE"><color red="0.01" green="0.01" blue="0.01" /></text></element> <element name="text_uiu1"><text string="UNDO:"><color red="0.81" green="0.8" blue="0.79" /></text></element> - <element name="text_uiu2a"> - <rect><color red="0.84" green="0.75" blue="0.50" /></rect> - <text string=" <<"><color red="0.01" green="0.01" blue="0.01" /></text> - </element> - <element name="text_uiu2b"> - <rect><color red="0.84" green="0.75" blue="0.50" /></rect> - <text string=" < "><color red="0.01" green="0.01" blue="0.01" /></text> - </element> - <element name="text_uiu2c"> - <rect><color red="0.84" green="0.75" blue="0.50" /></rect> - <text string=" >"><color red="0.01" green="0.01" blue="0.01" /></text> - </element> - <element name="text_uiu2d"> - <rect><color red="0.84" green="0.75" blue="0.50" /></rect> - <text string=" >>"><color red="0.01" green="0.01" blue="0.01" /></text> - </element> + <element name="text_uiu2a"><text string=" <<"><color red="0.01" green="0.01" blue="0.01" /></text></element> + <element name="text_uiu2b"><text string=" < "><color red="0.01" green="0.01" blue="0.01" /></text></element> + <element name="text_uiu2c"><text string=" >"><color red="0.01" green="0.01" blue="0.01" /></text></element> + <element name="text_uiu2d"><text string=" >>"><color red="0.01" green="0.01" blue="0.01" /></text></element> + <element name="text_uiu3b"><text string="/"><color red="0.81" green="0.8" blue="0.79" /></text></element> + <element name="text_uiu3a" defstate="0"> <simplecounter maxstate="999" digits="1" align="2"> <color red="0.81" green="0.8" blue="0.79" /> </simplecounter> </element> - <element name="text_uiu3b"><text string="/"><color red="0.81" green="0.8" blue="0.79" /></text></element> <element name="text_uiu3c" defstate="0"> <simplecounter maxstate="999" digits="1" align="1"> <color red="0.81" green="0.8" blue="0.79" /> diff --git a/src/emu/layout/triphsxs.lay b/src/emu/layout/triphsxs.lay index 4988b808100..4d7c0733956 100644 --- a/src/emu/layout/triphsxs.lay +++ b/src/emu/layout/triphsxs.lay @@ -1,6 +1,6 @@ <?xml version="1.0"?> <!-- -license:CC0 +license:CC0-1.0 --> <mamelayout version="2"> <view name="Triple Side-by-Side"> diff --git a/src/emu/machine.cpp b/src/emu/machine.cpp index 6174537a6d6..573c1b9e095 100644 --- a/src/emu/machine.cpp +++ b/src/emu/machine.cpp @@ -20,6 +20,7 @@ #include "fileio.h" #include "http.h" #include "image.h" +#include "main.h" #include "natkeyboard.h" #include "network.h" #include "render.h" @@ -59,29 +60,28 @@ osd_interface &running_machine::osd() const //------------------------------------------------- running_machine::running_machine(const machine_config &_config, machine_manager &manager) - : m_side_effects_disabled(0), - debug_flags(0), - m_config(_config), - m_system(_config.gamedrv()), - m_manager(manager), - m_current_phase(machine_phase::PREINIT), - m_paused(false), - m_hard_reset_pending(false), - m_exit_pending(false), - m_soft_reset_timer(nullptr), - m_rand_seed(0x9d14abd7), - m_ui_active(_config.options().ui_active()), - m_basename(_config.gamedrv().name), - m_sample_rate(_config.options().sample_rate()), - m_saveload_schedule(saveload_schedule::NONE), - m_saveload_schedule_time(attotime::zero), - m_saveload_searchpath(nullptr), - - m_save(*this), - m_memory(*this), - m_ioport(*this), - m_parameters(*this), - m_scheduler(*this) + : m_side_effects_disabled(0) + , debug_flags(0) + , m_config(_config) + , m_system(_config.gamedrv()) + , m_manager(manager) + , m_current_phase(machine_phase::PREINIT) + , m_paused(false) + , m_hard_reset_pending(false) + , m_exit_pending(false) + , m_soft_reset_timer(nullptr) + , m_rand_seed(0x9d14abd7) + , m_basename(_config.gamedrv().name) + , m_sample_rate(_config.options().sample_rate()) + , m_saveload_schedule(saveload_schedule::NONE) + , m_saveload_schedule_time(attotime::zero) + , m_saveload_searchpath(nullptr) + + , m_save(*this) + , m_memory(*this) + , m_ioport(*this) + , m_parameters(*this) + , m_scheduler(*this) { memset(&m_base_time, 0, sizeof(m_base_time)); @@ -124,7 +124,10 @@ std::string running_machine::describe_context() const } } - return std::string("(no context)"); + if (m_current_phase == machine_phase::RESET) + return std::string("(reset phase)"); + else + return std::string("(no context)"); } @@ -147,12 +150,13 @@ void running_machine::start() // initialize UI input m_ui_input = std::make_unique<ui_input_manager>(*this); - // init the osd layer + // init the OSD layer m_manager.osd().init(*this); - // create the video manager + // create the video manager and UI manager m_video = std::make_unique<video_manager>(*this); m_ui = manager().create_ui(*this); + m_ui->set_startup_text("Initializing...", true); // initialize the base time (needed for doing record/playback) ::time(&m_base_time); @@ -322,7 +326,7 @@ int running_machine::run(bool quiet) // run the CPUs until a reset or exit while ((!m_hard_reset_pending && !m_exit_pending) || m_saveload_schedule != saveload_schedule::NONE) { - g_profiler.start(PROFILER_EXTRA); + auto profile = g_profiler.start(PROFILER_EXTRA); // execute CPUs if not paused if (!m_paused) @@ -334,8 +338,6 @@ int running_machine::run(bool quiet) // handle save/load if (m_saveload_schedule != saveload_schedule::NONE) handle_saveload(); - - g_profiler.stop(); } m_manager.http()->clear(); @@ -348,29 +350,29 @@ int running_machine::run(bool quiet) nvram_save(); m_configuration->save_settings(); } - catch (emu_fatalerror &fatal) + catch (emu_fatalerror const &fatal) { osd_printf_error("Fatal error: %s\n", fatal.what()); error = EMU_ERR_FATALERROR; if (fatal.exitcode() != 0) error = fatal.exitcode(); } - catch (emu_exception &) + catch (emu_exception const &) { osd_printf_error("Caught unhandled emulator exception\n"); error = EMU_ERR_FATALERROR; } - catch (binding_type_exception &btex) + catch (binding_type_exception const &btex) { osd_printf_error("Error performing a late bind of function expecting type %s to instance of type %s\n", btex.target_type().name(), btex.actual_type().name()); error = EMU_ERR_FATALERROR; } - catch (tag_add_exception &aex) + catch (tag_add_exception const &aex) { osd_printf_error("Tag '%s' already exists in tagged map\n", aex.tag()); error = EMU_ERR_FATALERROR; } - catch (std::exception &ex) + catch (std::exception const &ex) { osd_printf_error("Caught unhandled %s exception: %s\n", typeid(ex).name(), ex.what()); error = EMU_ERR_FATALERROR; @@ -861,6 +863,7 @@ void running_machine::handle_saveload() if (!m_saveload_pending_file.empty()) { const char *const opname = (m_saveload_schedule == saveload_schedule::LOAD) ? "load" : "save"; + const char *const preposname = (m_saveload_schedule == saveload_schedule::LOAD) ? "from" : "to"; // if there are anonymous timers, we can't save just yet, and we can't load yet either // because the timers might overwrite data we have loaded @@ -868,7 +871,7 @@ void running_machine::handle_saveload() { // if more than a second has passed, we're probably screwed if ((this->time() - m_saveload_schedule_time) > attotime::from_seconds(1)) - popmessage("Unable to %s due to pending anonymous timers. See error.log for details.", opname); + popmessage("Error: Unable to %s state %s %s due to pending anonymous timers. See error.log for details.", opname, preposname, m_saveload_pending_file); else return; // return without cancelling the operation } @@ -881,39 +884,36 @@ void running_machine::handle_saveload() auto const filerr = file.open(m_saveload_pending_file); if (!filerr) { - const char *const opnamed = (m_saveload_schedule == saveload_schedule::LOAD) ? "loaded" : "saved"; - // read/write the save state save_error saverr = (m_saveload_schedule == saveload_schedule::LOAD) ? m_save.read_file(file) : m_save.write_file(file); // handle the result switch (saverr) { - case STATERR_ILLEGAL_REGISTRATIONS: - popmessage("Error: Unable to %s state due to illegal registrations. See error.log for details.", opname); - break; - case STATERR_INVALID_HEADER: - popmessage("Error: Unable to %s state due to an invalid header. Make sure the save state is correct for this machine.", opname); + popmessage("Error: Unable to %s state %s %s due to an invalid header. Make sure the save state is correct for this system.", opname, preposname, m_saveload_pending_file); break; case STATERR_READ_ERROR: - popmessage("Error: Unable to %s state due to a read error (file is likely corrupt).", opname); + popmessage("Error: Unable to %s state %s %s due to a read error (file is likely corrupt).", opname, preposname, m_saveload_pending_file); break; case STATERR_WRITE_ERROR: - popmessage("Error: Unable to %s state due to a write error. Verify there is enough disk space.", opname); + popmessage("Error: Unable to %s state %s %s due to a write error. Verify there is enough disk space.", opname, preposname, m_saveload_pending_file); break; case STATERR_NONE: + { + const char *const opnamed = (m_saveload_schedule == saveload_schedule::LOAD) ? "Loaded" : "Saved"; if (!(m_system.flags & MACHINE_SUPPORTS_SAVE)) - popmessage("State successfully %s.\nWarning: Save states are not officially supported for this machine.", opnamed); + popmessage("%s state %s %s.\nWarning: Save states are not officially supported for this system.", opnamed, preposname, m_saveload_pending_file); else - popmessage("State successfully %s.", opnamed); + popmessage("%s state %s %s.", opnamed, preposname, m_saveload_pending_file); break; + } default: - popmessage("Error: Unknown error during state %s.", opnamed); + popmessage("Error: Unknown error during %s state %s %s.", opname, preposname, m_saveload_pending_file); break; } @@ -924,11 +924,11 @@ void running_machine::handle_saveload() else if ((openflags == OPEN_FLAG_READ) && (std::errc::no_such_file_or_directory == filerr)) { // attempt to load a non-existent savestate, report empty slot - popmessage("Error: No savestate file to load.", opname); + popmessage("Error: Load state file %s not found.", m_saveload_pending_file); } else { - popmessage("Error: Failed to open file for %s operation.", opname); + popmessage("Error: Failed to open %s for %s state operation.", m_saveload_pending_file, opname); } } } @@ -1158,8 +1158,17 @@ void running_machine::nvram_save() emu_file file(options().nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); if (!file.open(nvram_filename(nvram.device()))) { + bool error = false; + if (!nvram.nvram_save(file)) + { + error = true; osd_printf_error("Error writing NVRAM file %s\n", file.filename()); + } + + // close and perhaps delete the file + if (error || file.size() == 0) + file.remove_on_close(); file.close(); } } @@ -1176,7 +1185,7 @@ void running_machine::popup_clear() const ui().popup_time(0, " "); } -void running_machine::popup_message(util::format_argument_pack<std::ostream> const &args) const +void running_machine::popup_message(util::format_argument_pack<char> const &args) const { std::string const temp(string_format(args)); ui().popup_time(temp.length() / 40 + 2, "%s", temp); @@ -1298,7 +1307,7 @@ void running_machine::emscripten_main_loop() { running_machine *machine = emscripten_running_machine; - g_profiler.start(PROFILER_EXTRA); + auto profile = g_profiler.start(PROFILER_EXTRA); // execute CPUs if not paused if (!machine->m_paused) @@ -1331,8 +1340,6 @@ void running_machine::emscripten_main_loop() { emscripten_cancel_main_loop(); } - - g_profiler.stop(); } void running_machine::emscripten_set_running_machine(running_machine *machine) diff --git a/src/emu/machine.h b/src/emu/machine.h index a49c5f1dbf9..7b4efec70da 100644 --- a/src/emu/machine.h +++ b/src/emu/machine.h @@ -145,7 +145,6 @@ public: bool paused() const { return m_paused || (m_current_phase != machine_phase::RUNNING); } bool exit_pending() const { return m_exit_pending; } bool hard_reset_pending() const { return m_hard_reset_pending; } - bool ui_active() const { return m_ui_active; } const std::string &basename() const { return m_basename; } int sample_rate() const { return m_sample_rate; } bool save_or_load_pending() const { return !m_saveload_pending_file.empty(); } @@ -172,7 +171,6 @@ public: void add_notifier(machine_notification event, machine_notify_delegate callback, bool first = false); void call_notifiers(machine_notification which); void add_logerror_callback(logerror_callback callback); - void set_ui_active(bool active) { m_ui_active = active; } void debug_break(); void export_http_api(); @@ -253,7 +251,7 @@ private: void nvram_load(); void nvram_save(); void popup_clear() const; - void popup_message(util::format_argument_pack<std::ostream> const &args) const; + void popup_message(util::format_argument_pack<char> const &args) const; // internal callbacks void logfile_callback(const char *buffer); @@ -297,7 +295,6 @@ private: // misc state u32 m_rand_seed; // current random number seed - bool m_ui_active; // ui active or not (useful for games / systems with keyboard inputs) time_t m_base_time; // real time at initial emulation time std::string m_basename; // basename used for game-related paths int m_sample_rate; // the digital audio sample rate @@ -400,7 +397,7 @@ inline void running_machine::logerror(Format &&fmt, Params &&... args) const // process only if there is a target if (allow_logging()) { - g_profiler.start(PROFILER_LOGERROR); + auto profile = g_profiler.start(PROFILER_LOGERROR); // dump to the buffer m_string_buffer.clear(); @@ -409,9 +406,7 @@ inline void running_machine::logerror(Format &&fmt, Params &&... args) const m_string_buffer.put('\0'); strlog(&m_string_buffer.vec()[0]); - - g_profiler.stop(); } } -#endif /* MAME_EMU_MACHINE_H */ +#endif // MAME_EMU_MACHINE_H diff --git a/src/emu/main.cpp b/src/emu/main.cpp index 6ce109ae1ef..12cde5cf299 100644 --- a/src/emu/main.cpp +++ b/src/emu/main.cpp @@ -9,20 +9,25 @@ ***************************************************************************/ #include "emu.h" +#include "main.h" + #include "emuopts.h" #include "http.h" -machine_manager::machine_manager(emu_options& options, osd_interface& osd) - : m_osd(osd), + +machine_manager::machine_manager(emu_options& options, osd_interface& osd) : + m_osd(osd), m_options(options), m_machine(nullptr) { } + machine_manager::~machine_manager() { } + void machine_manager::start_http_server() { m_http = std::make_unique<http_manager>(options().http(), options().http_port(), options().http_root()); diff --git a/src/emu/main.h b/src/emu/main.h index 89399e21690..78553ca5236 100644 --- a/src/emu/main.h +++ b/src/emu/main.h @@ -6,18 +6,17 @@ Controls execution of the core emulator system. ***************************************************************************/ +#ifndef MAME_EMU_MAIN_H +#define MAME_EMU_MAIN_H #pragma once -#ifndef __EMU_H__ -#error Dont include this file directly; include emu.h instead. -#endif +#include "emufwd.h" -#ifndef MAME_EMU_MAIN_H -#define MAME_EMU_MAIN_H +#include <memory> +#include <string> +#include <vector> -#include <thread> -#include <ctime> //************************************************************************** // CONSTANTS @@ -55,7 +54,7 @@ public: static void display_ui_chooser(running_machine &machine); static int start_frontend(emu_options &options, osd_interface &osd, std::vector<std::string> &args); static int start_frontend(emu_options &options, osd_interface &osd, int argc, char *argv[]); - static void draw_user_interface(running_machine& machine); + static bool draw_user_interface(running_machine& machine); static void periodic_check(); static bool frame_hook(); static void sound_hook(); @@ -66,10 +65,11 @@ public: class machine_manager { - DISABLE_COPYING(machine_manager); protected: // construction/destruction - machine_manager(emu_options& options, osd_interface& osd); + machine_manager(emu_options &options, osd_interface &osd); + machine_manager(machine_manager const &) = delete; + public: virtual ~machine_manager(); diff --git a/src/emu/memarray.cpp b/src/emu/memarray.cpp index 660e07ad9a1..eb03974ff1c 100644 --- a/src/emu/memarray.cpp +++ b/src/emu/memarray.cpp @@ -134,8 +134,8 @@ void memory_array::write8_to_32le(int index, u32 data) { reinterpret_cast<u8 *>( u32 memory_array::read8_from_32be(int index) const { return reinterpret_cast<u8 *>(m_base)[BYTE4_XOR_BE(index)]; } void memory_array::write8_to_32be(int index, u32 data) { reinterpret_cast<u8 *>(m_base)[BYTE4_XOR_BE(index)] = data; } -u32 memory_array::read8_from_64le(int index) const { return reinterpret_cast<u8 *>(m_base)[BYTE8_XOR_BE(index)]; } -void memory_array::write8_to_64le(int index, u32 data) { reinterpret_cast<u8 *>(m_base)[BYTE8_XOR_BE(index)] = data; } +u32 memory_array::read8_from_64le(int index) const { return reinterpret_cast<u8 *>(m_base)[BYTE8_XOR_LE(index)]; } +void memory_array::write8_to_64le(int index, u32 data) { reinterpret_cast<u8 *>(m_base)[BYTE8_XOR_LE(index)] = data; } u32 memory_array::read8_from_64be(int index) const { return reinterpret_cast<u8 *>(m_base)[BYTE8_XOR_BE(index)]; } void memory_array::write8_to_64be(int index, u32 data) { reinterpret_cast<u8 *>(m_base)[BYTE8_XOR_BE(index)] = data; } diff --git a/src/emu/network.cpp b/src/emu/network.cpp index 0ffff1616cc..f5e065ac9cb 100644 --- a/src/emu/network.cpp +++ b/src/emu/network.cpp @@ -57,7 +57,7 @@ void network_manager::config_load(config_type cfg_type, config_level cfg_level, network.set_interface(interface); const char *mac_addr = node->get_attribute_string("mac", nullptr); if (mac_addr != nullptr && strlen(mac_addr) == 17) { - char mac[7]; + uint8_t mac[6]; unsigned int mac_num[6]; sscanf(mac_addr, "%02x:%02x:%02x:%02x:%02x:%02x", &mac_num[0], &mac_num[1], &mac_num[2], &mac_num[3], &mac_num[4], &mac_num[5]); for (int i = 0; i<6; i++) mac[i] = mac_num[i]; @@ -87,9 +87,9 @@ void network_manager::config_save(config_type cfg_type, util::xml::data_node *pa { node->set_attribute("tag", network.device().tag()); node->set_attribute_int("interface", network.get_interface()); - const char *mac = network.get_mac(); + const std::array<u8, 6> &mac = network.get_mac(); char mac_addr[6 * 3]; - sprintf(mac_addr, "%02x:%02x:%02x:%02x:%02x:%02x", u8(mac[0]), u8(mac[1]), u8(mac[2]), u8(mac[3]), u8(mac[4]), u8(mac[5])); + sprintf(mac_addr, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); node->set_attribute("mac", mac_addr); } } diff --git a/src/emu/profiler.cpp b/src/emu/profiler.cpp index 765373e34e7..19f3908f097 100644 --- a/src/emu/profiler.cpp +++ b/src/emu/profiler.cpp @@ -89,8 +89,11 @@ real_profiler_state::real_profiler_state() // reset - initializes state //------------------------------------------------- -void real_profiler_state::reset(bool enabled) +void real_profiler_state::reset(bool enabled) noexcept { + // disabling the profiler from the UI happens while PROFILER_EXTRA is active + //assert(!m_filoptr || (m_filoptr == m_filo)); + m_text_time = attotime::never; if (enabled) @@ -117,10 +120,10 @@ void real_profiler_state::reset(bool enabled) const char *real_profiler_state::text(running_machine &machine) { - start(PROFILER_PROFILER); + auto profile = start(PROFILER_PROFILER); // get the current time - attotime current_time = machine.scheduler().time(); + attotime const current_time = machine.scheduler().time(); // we only want to update the text periodically if ((m_text_time == attotime::never) || ((current_time - m_text_time).as_double() >= TEXT_UPDATE_TIME)) @@ -129,7 +132,6 @@ const char *real_profiler_state::text(running_machine &machine) m_text_time = current_time; } - stop(); return m_text.c_str(); } diff --git a/src/emu/profiler.h b/src/emu/profiler.h index 8341e075eae..8ea65ac7f07 100644 --- a/src/emu/profiler.h +++ b/src/emu/profiler.h @@ -8,11 +8,11 @@ **************************************************************************** - Profiling is scope-based. To start profiling, put a profiler_scope + Profiling is scope-based. To start profiling, put a profiler scope object on the stack. To end profiling, just end the scope: { - profiler_scope scope(PROFILER_VIDEO); + auto scope = g_profiler.start(PROFILER_VIDEO); your_work_here(); } @@ -26,6 +26,17 @@ #pragma once +#include "emufwd.h" + +#include "attotime.h" + +#include "eminline.h" // for get_profile_ticks() +#include "osdcore.h" + +#include <cstdio> +#include <cstdlib> +#include <string> + //************************************************************************** // CONSTANTS @@ -83,18 +94,57 @@ DECLARE_ENUM_INCDEC_OPERATORS(profile_type) class real_profiler_state { public: + class scope + { + private: + real_profiler_state &m_host; + bool m_active; + + public: + scope(scope const &) = delete; + scope &operator=(scope const &) = delete; + + scope(scope &&that) noexcept : m_host(that.m_host), m_active(that.m_active) + { + that.m_active = false; + } + + scope(real_profiler_state &host, profile_type type) noexcept : m_host(host), m_active(false) + { + if (m_host.enabled()) + { + m_host.real_start(type); + m_active = true; + } + } + + ~scope() + { + stop(); + } + + void stop() noexcept + { + if (m_active) + { + m_host.real_stop(); + m_active = false; + } + } + }; + // construction/destruction real_profiler_state(); // getters - bool enabled() const + bool enabled() const noexcept { return m_filoptr != nullptr; } const char *text(running_machine &machine); // enable/disable - void enable(bool state = true) + void enable(bool state = true) noexcept { if (state != enabled()) { @@ -103,22 +153,31 @@ public: } // start/stop - void start(profile_type type) { if (enabled()) real_start(type); } - void stop() { if (enabled()) real_stop(); } + [[nodiscard]] auto start(profile_type type) noexcept { return scope(*this, type); } private: - void reset(bool enabled); + // an entry in the FILO + struct filo_entry + { + int type; // type of entry + osd_ticks_t start; // start time + }; + + void reset(bool enabled) noexcept; void update_text(running_machine &machine); //------------------------------------------------- // real_start - mark the beginning of a // profiler entry //------------------------------------------------- - ATTR_FORCE_INLINE void real_start(profile_type type) + ATTR_FORCE_INLINE void real_start(profile_type type) noexcept { // fail if we overflow - if (m_filoptr >= &m_filo[std::size(m_filo) - 1]) - throw emu_fatalerror("Profiler FILO overflow (type = %d)\n", type); + if (UNEXPECTED(m_filoptr >= &m_filo[std::size(m_filo) - 1])) + { + std::fprintf(stderr, "Profiler FILO overflow (type = %d)\n", int(type)); + std::abort(); + } // get current tick count osd_ticks_t curticks = get_profile_ticks(); @@ -137,7 +196,7 @@ private: //------------------------------------------------- // real_stop - mark the end of a profiler entry //------------------------------------------------- - ATTR_FORCE_INLINE void real_stop() + ATTR_FORCE_INLINE void real_stop() noexcept { // degenerate scenario if (UNEXPECTED(m_filoptr <= m_filo)) @@ -156,13 +215,6 @@ private: m_filoptr->start = curticks; } - // an entry in the FILO - struct filo_entry - { - int type; // type of entry - osd_ticks_t start; // start time - }; - // internal state filo_entry * m_filoptr; // current FILO index std::string m_text; // profiler text @@ -177,19 +229,35 @@ private: class dummy_profiler_state { public: + class scope + { + private: + dummy_profiler_state &m_host; + + public: + scope(scope const &) = delete; + scope &operator=(scope const &) = delete; + scope(scope &&that) noexcept = default; + scope(dummy_profiler_state &host, profile_type type) noexcept : m_host(host) { } + ~scope() { m_host.real_stop(); } + void stop() noexcept { } + }; + // construction/destruction dummy_profiler_state(); // getters - bool enabled() const { return false; } + bool enabled() const noexcept { return false; } const char *text(running_machine &machine) { return ""; } // enable/disable - void enable(bool state = true) { } + void enable(bool state = true) noexcept { } // start/stop - void start(profile_type type) { } - void stop() { } + [[nodiscard]] auto start(profile_type type) noexcept { return scope(*this, type); } + +private: + void real_stop() noexcept { } }; @@ -210,4 +278,4 @@ typedef dummy_profiler_state profiler_state; extern profiler_state g_profiler; -#endif /* MAME_EMU_PROFILER_H */ +#endif // MAME_EMU_PROFILER_H diff --git a/src/emu/recording.cpp b/src/emu/recording.cpp index 611e5ae327b..d9c25c57767 100644 --- a/src/emu/recording.cpp +++ b/src/emu/recording.cpp @@ -11,6 +11,7 @@ #include "emu.h" #include "fileio.h" +#include "main.h" #include "screen.h" #include "aviio.h" @@ -178,8 +179,8 @@ bool avi_movie_recording::initialize(running_machine &machine, std::unique_ptr<e // build up information about this new movie avi_file::movie_info info; info.video_format = 0; - info.video_timescale = 1000 * (screen() ? screen()->frame_period().as_hz() : screen_device::DEFAULT_FRAME_RATE); - info.video_sampletime = 1000; + info.video_timescale = 0x3fff'fffc; // multiple of 60, for screenless machines + info.video_sampletime = screen() ? screen()->frame_period().as_ticks(info.video_timescale) : 0x0111'1111; info.video_numsamples = 0; info.video_width = width; info.video_height = height; @@ -194,7 +195,7 @@ bool avi_movie_recording::initialize(running_machine &machine, std::unique_ptr<e info.audio_samplerate = machine.sample_rate(); // compute the frame time - set_frame_period(attotime::from_seconds(1000) / info.video_timescale); + set_frame_period(attotime::from_ticks(info.video_sampletime, info.video_timescale)); // create the file avi_file::error avierr = avi_file::create(fullpath, info, m_avi_file); @@ -221,14 +222,13 @@ bool avi_movie_recording::append_single_video_frame(bitmap_rgb32 &bitmap, const bool avi_movie_recording::add_sound_to_recording(const s16 *sound, int numsamples) { - g_profiler.start(PROFILER_MOVIE_REC); + auto profile = g_profiler.start(PROFILER_MOVIE_REC); // write the next frame avi_file::error avierr = m_avi_file->append_sound_samples(0, sound + 0, numsamples, 1); if (avierr == avi_file::error::NONE) avierr = m_avi_file->append_sound_samples(1, sound + 1, numsamples, 1); - g_profiler.stop(); return avierr == avi_file::error::NONE; } diff --git a/src/emu/render.cpp b/src/emu/render.cpp index 32aebcf8eb7..617b1bf3756 100644 --- a/src/emu/render.cpp +++ b/src/emu/render.cpp @@ -353,6 +353,7 @@ void render_texture::release() m_bitmap = nullptr; m_sbounds.set(0, -1, 0, -1); m_format = TEXFORMAT_ARGB32; + m_scaler = nullptr; m_curseq = 0; } @@ -431,6 +432,7 @@ void render_texture::get_scaled(u32 dwidth, u32 dheight, render_texinfo &texinfo texinfo.base = m_bitmap->raw_pixptr(m_sbounds.top(), m_sbounds.left()); texinfo.rowpixels = m_bitmap->rowpixels(); texinfo.width = swidth; + texinfo.width_margin = m_sbounds.left(); texinfo.height = sheight; // palette will be set later texinfo.seqid = ++m_curseq; @@ -1013,9 +1015,9 @@ void render_target::set_bounds(s32 width, s32 height, float pixel_aspect) m_width = width; m_height = height; m_bounds.x0 = m_bounds.y0 = 0; - m_bounds.x1 = (float)width; - m_bounds.y1 = (float)height; - m_pixel_aspect = pixel_aspect != 0.0? pixel_aspect : 1.0; + m_bounds.x1 = float(width); + m_bounds.y1 = float(height); + m_pixel_aspect = pixel_aspect != 0.0F ? pixel_aspect : 1.0F; } @@ -1071,28 +1073,29 @@ void render_target::set_visibility_toggle(unsigned index, bool enable) unsigned render_target::configured_view(const char *viewname, int targetindex, int numtargets) { - layout_view *view = nullptr; - // if it isn't "auto" or an empty string, try to match it as a view name prefix if (viewname && *viewname && strcmp(viewname, "auto")) { // scan for a matching view name size_t const viewlen = strlen(viewname); - for (unsigned i = 0; !view && (m_views.size() > i); ++i) + for (unsigned i = 0; m_views.size() > i; ++i) + { if (!core_strnicmp(m_views[i].first.name().c_str(), viewname, viewlen)) - view = &m_views[i].first; + return i; + } } // if we don't have a match, default to the nth view std::vector<std::reference_wrapper<screen_device> > screens; for (screen_device &screen : screen_device_enumerator(m_manager.machine().root_device())) screens.push_back(screen); - if (!view && !screens.empty()) + if (!screens.empty()) { // if we have enough targets to be one per screen, assign in order if (numtargets >= screens.size()) { // find the first view with this screen and this screen only + layout_view *view = nullptr; screen_device const &screen = screens[index() % screens.size()]; for (unsigned i = 0; !view && (m_views.size() > i); ++i) { @@ -1110,22 +1113,21 @@ unsigned render_target::configured_view(const char *viewname, int targetindex, i } } } + if (view) + return view_index(*view); } // otherwise, find the first view that has all the screens - if (!view) + for (unsigned i = 0; m_views.size() > i; ++i) { - for (unsigned i = 0; !view && (m_views.size() > i); ++i) - { - layout_view &curview = m_views[i].first; - if (std::find_if(screens.begin(), screens.end(), [&curview] (screen_device &screen) { return !curview.has_screen(screen); }) == screens.end()) - view = &curview; - } + layout_view &curview = m_views[i].first; + if (std::find_if(screens.begin(), screens.end(), [&curview] (screen_device &screen) { return !curview.has_screen(screen); }) == screens.end()) + return i; } } - // make sure it's a valid view - return view ? view_index(*view) : 0; + // default to the first view + return 0; } @@ -2117,11 +2119,10 @@ bool render_target::load_layout_file(const char *dirname, const internal_layout size_t decompressed = 0; do { - size_t actual; - std::error_condition const err = inflater->read( + auto const [err, actual] = read( + *inflater, &tempout[decompressed], - layout_data.decompressed_size - decompressed, - actual); + layout_data.decompressed_size - decompressed); decompressed += actual; if (err) { @@ -2214,7 +2215,7 @@ bool render_target::load_layout_file(device_t &device, util::xml::data_node cons { m_filelist.emplace_back(device, rootnode, searchpath, dirname); } - catch (emu_fatalerror &err) + catch (emu_fatalerror const &err) { osd_printf_warning("%s\n", err.what()); return false; @@ -2660,20 +2661,22 @@ void render_target::config_load(util::xml::data_node const *targetnode) if (!targetnode) return; + // TODO: consider option priority - command line should take precedence over CFG + // not practical at the moment because view selection options are in the OSD layer + // find the view const char *viewname = targetnode->get_attribute_string("view", nullptr); - if (viewname != nullptr) - for (int viewnum = 0; viewnum < 1000; viewnum++) + if (viewname) + { + for (unsigned viewnum = 0; m_views.size() > viewnum; viewnum++) { - const char *testname = view_name(viewnum); - if (testname == nullptr) - break; - if (!strcmp(viewname, testname)) + if (!strcmp(viewname, view_name(viewnum))) { set_view(viewnum); break; } } + } // modify the artwork config int const zoom = targetnode->get_attribute_int("zoom", -1); @@ -3256,12 +3259,7 @@ float render_manager::ui_aspect(render_container *rc) } // clamp for extreme proportions - if (aspect < 0.66f) - aspect = 0.66f; - if (aspect > 1.5f) - aspect = 1.5f; - - return aspect; + return std::clamp(aspect, 0.66f, 1.5f); } diff --git a/src/emu/render.h b/src/emu/render.h index 27205206d1f..2faa5f46394 100644 --- a/src/emu/render.h +++ b/src/emu/render.h @@ -157,6 +157,7 @@ struct render_texinfo void * base; // base of the data u32 rowpixels; // pixels per row u32 width; // width of the image + u32 width_margin; // left margin of the scaled bounds, if applicable u32 height; // height of the image u32 seqid; // sequence ID u64 unique_id; // unique identifier to pass to osd @@ -339,7 +340,7 @@ private: void get_scaled(u32 dwidth, u32 dheight, render_texinfo &texinfo, render_primitive_list &primlist, u32 flags = 0); const rgb_t *get_adjusted_palette(render_container &container, u32 &out_length); - static constexpr int MAX_TEXTURE_SCALES = 20; + static constexpr int MAX_TEXTURE_SCALES = 100; // a scaled_texture contains a single scaled entry for a texture struct scaled_texture diff --git a/src/emu/rendersw.hxx b/src/emu/rendersw.hxx index aa7b2253795..5561928e7df 100644 --- a/src/emu/rendersw.hxx +++ b/src/emu/rendersw.hxx @@ -153,7 +153,10 @@ private: } else { - u16 const *const texbase = reinterpret_cast<u16 const *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 16); + s32 u = std::clamp<s32>(curu >> 16, 0, texture.width - 1); + s32 v = std::clamp<s32>(curv >> 16, 0, texture.height - 1); + + u16 const *const texbase = reinterpret_cast<u16 const *>(texture.base) + v * texture.rowpixels + u; return palbase[texbase[0]]; } } @@ -185,7 +188,10 @@ private: } else { - u16 const *const texbase = reinterpret_cast<u16 const *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 16); + s32 u = std::clamp<s32>(curu >> 16, 0, texture.width - 1); + s32 v = std::clamp<s32>(curv >> 16, 0, texture.height - 1); + + u16 const *const texbase = reinterpret_cast<u16 const *>(texture.base) + v * texture.rowpixels + u; return palbase[texbase[0]]; } } @@ -247,8 +253,11 @@ private: } else { - const u16 *texbase = reinterpret_cast<const u16 *>(texture.base) + (curv >> 16) * texture.rowpixels + (curu >> 17) * 2; - return (texbase[(curu >> 16) & 1] >> 8) | ((texbase[0] & 0xff) << 8) | ((texbase[1] & 0xff) << 16); + s32 u = std::clamp<s32>(curu >> 16, 0, texture.width - 1); + s32 v = std::clamp<s32>(curv >> 16, 0, texture.height - 1); + + const u16 *texbase = reinterpret_cast<const u16 *>(texture.base) + v * texture.rowpixels + (u >> 1) * 2; + return (texbase[u & 1] >> 8) | ((texbase[0] & 0xff) << 8) | ((texbase[1] & 0xff) << 16); } } diff --git a/src/emu/rendfont.cpp b/src/emu/rendfont.cpp index 998e825b61d..259d7731fe5 100644 --- a/src/emu/rendfont.cpp +++ b/src/emu/rendfont.cpp @@ -13,9 +13,10 @@ #include "emuopts.h" #include "fileio.h" +#include "render.h" #include "corestr.h" -#include "coreutil.h" +#include "multibyte.h" #include "path.h" #include "osdepend.h" @@ -127,13 +128,12 @@ public: bool read(util::read_stream &f) { - std::size_t actual(0); - return !f.read(m_data, sizeof(m_data), actual) && actual == sizeof(m_data); + auto const [err, actual] = util::read(f, m_data, sizeof(m_data)); + return !err && (actual == sizeof(m_data)); } bool write(util::write_stream &f) { - std::size_t actual(0); - return !f.write(m_data, sizeof(m_data), actual) && actual == sizeof(m_data); + return !util::write(f, m_data, sizeof(m_data)).first; } bool check_magic() const @@ -150,51 +150,27 @@ public: } u64 get_original_length() const { - return - (u64(m_data[OFFS_ORIGLENGTH + 0]) << (7 * 8)) | - (u64(m_data[OFFS_ORIGLENGTH + 1]) << (6 * 8)) | - (u64(m_data[OFFS_ORIGLENGTH + 2]) << (5 * 8)) | - (u64(m_data[OFFS_ORIGLENGTH + 3]) << (4 * 8)) | - (u64(m_data[OFFS_ORIGLENGTH + 4]) << (3 * 8)) | - (u64(m_data[OFFS_ORIGLENGTH + 5]) << (2 * 8)) | - (u64(m_data[OFFS_ORIGLENGTH + 6]) << (1 * 8)) | - (u64(m_data[OFFS_ORIGLENGTH + 7]) << (0 * 8)); + return get_u64be(m_data + OFFS_ORIGLENGTH); } u32 get_original_hash() const { - return - (u32(m_data[OFFS_ORIGHASH + 0]) << (3 * 8)) | - (u32(m_data[OFFS_ORIGHASH + 1]) << (2 * 8)) | - (u32(m_data[OFFS_ORIGHASH + 2]) << (1 * 8)) | - (u32(m_data[OFFS_ORIGHASH + 3]) << (0 * 8)); + return get_u32be(m_data + OFFS_ORIGHASH); } u32 get_glyph_count() const { - return - (u32(m_data[OFFS_GLYPHCOUNT + 0]) << (3 * 8)) | - (u32(m_data[OFFS_GLYPHCOUNT + 1]) << (2 * 8)) | - (u32(m_data[OFFS_GLYPHCOUNT + 2]) << (1 * 8)) | - (u32(m_data[OFFS_GLYPHCOUNT + 3]) << (0 * 8)); + return get_u32be(m_data + OFFS_GLYPHCOUNT); } u16 get_height() const { - return - (u16(m_data[OFFS_HEIGHT + 0]) << (1 * 8)) | - (u16(m_data[OFFS_HEIGHT + 1]) << (0 * 8)); + return get_u16be(m_data + OFFS_HEIGHT); } s16 get_y_offset() const { - return - (u16(m_data[OFFS_YOFFSET + 0]) << (1 * 8)) | - (u16(m_data[OFFS_YOFFSET + 1]) << (0 * 8)); + return get_u16be(m_data + OFFS_YOFFSET); } s32 get_default_character() const { - return - (u32(m_data[OFFS_DEFCHAR + 0]) << (3 * 8)) | - (u32(m_data[OFFS_DEFCHAR + 1]) << (2 * 8)) | - (u32(m_data[OFFS_DEFCHAR + 2]) << (1 * 8)) | - (u32(m_data[OFFS_DEFCHAR + 3]) << (0 * 8)); + return get_u32be(m_data + OFFS_DEFCHAR); } void set_magic() @@ -208,45 +184,27 @@ public: } void set_original_length(u64 value) { - m_data[OFFS_ORIGLENGTH + 0] = u8((value >> (7 * 8)) & 0x00ff); - m_data[OFFS_ORIGLENGTH + 1] = u8((value >> (6 * 8)) & 0x00ff); - m_data[OFFS_ORIGLENGTH + 2] = u8((value >> (5 * 8)) & 0x00ff); - m_data[OFFS_ORIGLENGTH + 3] = u8((value >> (4 * 8)) & 0x00ff); - m_data[OFFS_ORIGLENGTH + 4] = u8((value >> (3 * 8)) & 0x00ff); - m_data[OFFS_ORIGLENGTH + 5] = u8((value >> (2 * 8)) & 0x00ff); - m_data[OFFS_ORIGLENGTH + 6] = u8((value >> (1 * 8)) & 0x00ff); - m_data[OFFS_ORIGLENGTH + 7] = u8((value >> (0 * 8)) & 0x00ff); + put_u64be(m_data + OFFS_ORIGLENGTH, value); } void set_original_hash(u32 value) { - m_data[OFFS_ORIGHASH + 0] = u8((value >> (3 * 8)) & 0x00ff); - m_data[OFFS_ORIGHASH + 1] = u8((value >> (2 * 8)) & 0x00ff); - m_data[OFFS_ORIGHASH + 2] = u8((value >> (1 * 8)) & 0x00ff); - m_data[OFFS_ORIGHASH + 3] = u8((value >> (0 * 8)) & 0x00ff); + put_u32be(m_data + OFFS_ORIGHASH, value); } void set_glyph_count(u32 value) { - m_data[OFFS_GLYPHCOUNT + 0] = u8((value >> (3 * 8)) & 0x00ff); - m_data[OFFS_GLYPHCOUNT + 1] = u8((value >> (2 * 8)) & 0x00ff); - m_data[OFFS_GLYPHCOUNT + 2] = u8((value >> (1 * 8)) & 0x00ff); - m_data[OFFS_GLYPHCOUNT + 3] = u8((value >> (0 * 8)) & 0x00ff); + put_u32be(m_data + OFFS_GLYPHCOUNT, value); } void set_height(u16 value) { - m_data[OFFS_HEIGHT + 0] = u8((value >> (1 * 8)) & 0x00ff); - m_data[OFFS_HEIGHT + 1] = u8((value >> (0 * 8)) & 0x00ff); + put_u16be(m_data + OFFS_HEIGHT, value); } void set_y_offset(s16 value) { - m_data[OFFS_YOFFSET + 0] = u8((value >> (1 * 8)) & 0x00ff); - m_data[OFFS_YOFFSET + 1] = u8((value >> (0 * 8)) & 0x00ff); + put_u16be(m_data + OFFS_YOFFSET, value); } void set_default_character(s32 value) { - m_data[OFFS_DEFCHAR + 0] = u8((value >> (3 * 8)) & 0x00ff); - m_data[OFFS_DEFCHAR + 1] = u8((value >> (2 * 8)) & 0x00ff); - m_data[OFFS_DEFCHAR + 2] = u8((value >> (1 * 8)) & 0x00ff); - m_data[OFFS_DEFCHAR + 3] = u8((value >> (0 * 8)) & 0x00ff); + put_u32be(m_data + OFFS_DEFCHAR, value); } private: @@ -286,74 +244,52 @@ public: u32 get_encoding() const { - return - (u32(m_ptr[OFFS_ENCODING + 0]) << (3 * 8)) | - (u32(m_ptr[OFFS_ENCODING + 1]) << (2 * 8)) | - (u32(m_ptr[OFFS_ENCODING + 2]) << (1 * 8)) | - (u32(m_ptr[OFFS_ENCODING + 3]) << (0 * 8)); + return get_u32be(m_ptr + OFFS_ENCODING); } u16 get_x_advance() const { - return - (u16(m_ptr[OFFS_XADVANCE + 0]) << (1 * 8)) | - (u16(m_ptr[OFFS_XADVANCE + 1]) << (0 * 8)); + return get_u16be(m_ptr + OFFS_XADVANCE); } s16 get_bb_x_offset() const { - return - (u16(m_ptr[OFFS_BBXOFFSET + 0]) << (1 * 8)) | - (u16(m_ptr[OFFS_BBXOFFSET + 1]) << (0 * 8)); + return get_u16be(m_ptr + OFFS_BBXOFFSET); } s16 get_bb_y_offset() const { - return - (u16(m_ptr[OFFS_BBYOFFSET + 0]) << (1 * 8)) | - (u16(m_ptr[OFFS_BBYOFFSET + 1]) << (0 * 8)); + return get_u16be(m_ptr + OFFS_BBYOFFSET); } u16 get_bb_width() const { - return - (u16(m_ptr[OFFS_BBWIDTH + 0]) << (1 * 8)) | - (u16(m_ptr[OFFS_BBWIDTH + 1]) << (0 * 8)); + return get_u16be(m_ptr + OFFS_BBWIDTH); } u16 get_bb_height() const { - return - (u16(m_ptr[OFFS_BBHEIGHT + 0]) << (1 * 8)) | - (u16(m_ptr[OFFS_BBHEIGHT + 1]) << (0 * 8)); + return get_u16be(m_ptr + OFFS_BBHEIGHT); } void set_encoding(u32 value) { - m_ptr[OFFS_ENCODING + 0] = u8((value >> (3 * 8)) & 0x00ff); - m_ptr[OFFS_ENCODING + 1] = u8((value >> (2 * 8)) & 0x00ff); - m_ptr[OFFS_ENCODING + 2] = u8((value >> (1 * 8)) & 0x00ff); - m_ptr[OFFS_ENCODING + 3] = u8((value >> (0 * 8)) & 0x00ff); + put_u32be(m_ptr + OFFS_ENCODING, value); } void set_x_advance(u16 value) { - m_ptr[OFFS_XADVANCE + 0] = u8((value >> (1 * 8)) & 0x00ff); - m_ptr[OFFS_XADVANCE + 1] = u8((value >> (0 * 8)) & 0x00ff); + put_u16be(m_ptr + OFFS_XADVANCE, value); } void set_bb_x_offset(s16 value) { - m_ptr[OFFS_BBXOFFSET + 0] = u8((value >> (1 * 8)) & 0x00ff); - m_ptr[OFFS_BBXOFFSET + 1] = u8((value >> (0 * 8)) & 0x00ff); + put_u16be(m_ptr + OFFS_BBXOFFSET, value); } void set_bb_y_offset(s16 value) { - m_ptr[OFFS_BBYOFFSET + 0] = u8((value >> (1 * 8)) & 0x00ff); - m_ptr[OFFS_BBYOFFSET + 1] = u8((value >> (0 * 8)) & 0x00ff); + put_u16be(m_ptr + OFFS_BBYOFFSET, value); } void set_bb_width(u16 value) { - m_ptr[OFFS_BBWIDTH + 0] = u8((value >> (1 * 8)) & 0x00ff); - m_ptr[OFFS_BBWIDTH + 1] = u8((value >> (0 * 8)) & 0x00ff); + put_u16be(m_ptr + OFFS_BBWIDTH, value); } void set_bb_height(u16 value) { - m_ptr[OFFS_BBHEIGHT + 0] = u8((value >> (1 * 8)) & 0x00ff); - m_ptr[OFFS_BBHEIGHT + 1] = u8((value >> (0 * 8)) & 0x00ff); + put_u16be(m_ptr + OFFS_BBHEIGHT, value); } bdc_table_entry &operator=(bdc_table_entry const &that) = default; @@ -673,7 +609,7 @@ void render_font::char_expand(char32_t chnum, glyph &gl) if (accumbit == 7) accum = *ptr++; if (dest != nullptr) - *dest++ = (accum & (1 << accumbit)) ? fgcol : bgcol; + *dest++ = BIT(accum, accumbit) ? fgcol : bgcol; accumbit = (accumbit - 1) & 7; } } @@ -769,7 +705,7 @@ void render_font::char_expand(char32_t chnum, glyph &gl) if (accumbit == 7) accum = *ptr++; if (dest != nullptr) - *dest++ = (accum & (1 << accumbit)) ? fgcol : bgcol; + *dest++ = BIT(accum, accumbit) ? fgcol : bgcol; accumbit = (accumbit - 1) & 7; } } @@ -822,7 +758,8 @@ void render_font::get_scaled_bitmap_and_bounds(bitmap_argb32 &dest, float height bounds.min_y = 0; // compute x1,y1 from there based on the bitmap size - bounds.set_width(float(gl.bmwidth) * scale * aspect); + float width = float(gl.bmwidth) * scale * aspect; + bounds.set_width(width < 0.5f ? 0 : std::max(int(width), 1)); bounds.set_height(float(m_height) * scale); // if the bitmap isn't big enough, bail @@ -946,7 +883,7 @@ bool render_font::load_cached_bdf(std::string_view filename) m_rawdata.clear(); return false; } - u32 const hash(core_crc32(0, reinterpret_cast<u8 const *>(&m_rawdata[0]), bytes)); + u32 const hash(util::crc32_creator::simple(&m_rawdata[0], bytes)); // create the cached filename, changing the 'F' to a 'C' on the extension std::string cachedname(filename, 0, filename.length() - ((4U < filename.length()) && core_filename_ends_with(filename, ".bdf") ? 4 : 0)); @@ -1408,6 +1345,11 @@ bool render_font::load_cached(util::random_read &file, u64 length, u32 hash) // now read the rest of the data u64 const remaining(filesize - filepos); + if (remaining > std::numeric_limits<std::size_t>::max()) + { + osd_printf_error("render_font::load_cached: BDC file is too large to read into memory\n"); + return false; + } try { m_rawdata.resize(std::size_t(remaining)); @@ -1415,18 +1357,14 @@ bool render_font::load_cached(util::random_read &file, u64 length, u32 hash) catch (...) { osd_printf_error("render_font::load_cached: allocation error\n"); + return false; } - for (u64 bytes_read = 0; remaining > bytes_read; ) + auto const [err, bytes] = read(file, &m_rawdata[0], remaining); + if (err || (bytes != remaining)) { - u32 const chunk((std::min)(u64(std::numeric_limits<u32>::max()), remaining)); - std::size_t bytes(0); - if (file.read(&m_rawdata[bytes_read], chunk, bytes) || bytes != chunk) - { - osd_printf_error("render_font::load_cached: error reading BDC data\n"); - m_rawdata.clear(); - return false; - } - bytes_read += chunk; + osd_printf_error("render_font::load_cached: error reading BDC data\n"); + m_rawdata.clear(); + return false; } // extract the data from the data @@ -1508,11 +1446,11 @@ bool render_font::save_cached(util::random_write &file, u64 length, u32 hash) hdr.set_y_offset(m_yoffs); hdr.set_default_character(m_defchar); if (!hdr.write(file)) - throw emu_fatalerror("Error writing cached file"); + throw emu_fatalerror("Error writing cached font file"); } u64 table_offs; if (file.tell(table_offs)) - throw emu_fatalerror("Error writing cached file"); + throw emu_fatalerror("Error writing cached font file"); // allocate an array to hold the character data std::vector<u8> chartable(std::size_t(numchars) * bdc_table_entry::size(), 0); @@ -1521,9 +1459,8 @@ bool render_font::save_cached(util::random_write &file, u64 length, u32 hash) std::vector<u8> tempbuffer(65536); // write the empty table to the beginning of the file - std::size_t bytes_written(0); - if (file.write(&chartable[0], chartable.size(), bytes_written) || bytes_written != chartable.size()) - throw emu_fatalerror("Error writing cached file"); + if (write(file, &chartable[0], chartable.size()).first) + throw emu_fatalerror("Error writing cached font file"); // loop over all characters bdc_table_entry table_entry(chartable.empty() ? nullptr : &chartable[0]); @@ -1565,8 +1502,8 @@ bool render_font::save_cached(util::random_write &file, u64 length, u32 hash) *dest++ = accum; // write the data - if (file.write(&tempbuffer[0], dest - &tempbuffer[0], bytes_written) || bytes_written != dest - &tempbuffer[0]) - throw emu_fatalerror("Error writing cached file"); + if (write(file, &tempbuffer[0], dest - &tempbuffer[0]).first) + throw emu_fatalerror("Error writing cached font file"); // free the bitmap and texture m_manager.texture_free(gl.texture); @@ -1591,15 +1528,8 @@ bool render_font::save_cached(util::random_write &file, u64 length, u32 hash) LOG("render_font::save_cached: writing character table\n"); if (file.seek(table_offs, SEEK_SET)) return false; - u8 const *bytes(&chartable[0]); - for (u64 remaining = chartable.size(); remaining; ) - { - u32 const chunk((std::min<u64>)(std::numeric_limits<u32>::max(), remaining)); - if (file.write(bytes, chunk, bytes_written) || chunk != bytes_written) - throw emu_fatalerror("Error writing cached file"); - bytes += chunk; - remaining -= chunk; - } + if (write(file, &chartable[0], chartable.size()).first) + throw emu_fatalerror("Error writing cached font file"); } // no trouble? @@ -1650,6 +1580,11 @@ void render_font::render_font_command_glyph() // now read the rest of the data u64 const remaining(filesize - filepos); + if (remaining > std::numeric_limits<std::size_t>::max()) + { + osd_printf_error("render_font::render_font_command_glyph: BDC file is too large to read into memory\n"); + return; + } try { m_rawdata_cmd.resize(std::size_t(remaining)); @@ -1657,18 +1592,14 @@ void render_font::render_font_command_glyph() catch (...) { osd_printf_error("render_font::render_font_command_glyph: allocation error\n"); + return; } - for (u64 bytes_read = 0; remaining > bytes_read; ) + auto const [err, bytes] = read(*file, &m_rawdata_cmd[0], remaining); + if (err || (bytes != remaining)) { - u32 const chunk((std::min)(u64(std::numeric_limits<u32>::max()), remaining)); - std::size_t bytes(0); - if (file->read(&m_rawdata_cmd[bytes_read], chunk, bytes) || bytes != chunk) - { - osd_printf_error("render_font::render_font_command_glyph: error reading BDC data\n"); - m_rawdata_cmd.clear(); - return; - } - bytes_read += chunk; + osd_printf_error("render_font::render_font_command_glyph: error reading BDC data\n"); + m_rawdata_cmd.clear(); + return; } // extract the data from the data diff --git a/src/emu/rendfont.h b/src/emu/rendfont.h index 2d812860ae4..9ada358ed5d 100644 --- a/src/emu/rendfont.h +++ b/src/emu/rendfont.h @@ -11,8 +11,6 @@ #ifndef MAME_EMU_RENDFONT_H #define MAME_EMU_RENDFONT_H -#include "render.h" - //************************************************************************** // TYPE DEFINITIONS //************************************************************************** diff --git a/src/emu/rendlay.cpp b/src/emu/rendlay.cpp index 2e54112f269..c6e053fc713 100644 --- a/src/emu/rendlay.cpp +++ b/src/emu/rendlay.cpp @@ -14,6 +14,7 @@ #include "emuopts.h" #include "fileio.h" +#include "main.h" #include "rendfont.h" #include "rendutil.h" #include "video/rgbutil.h" @@ -224,12 +225,18 @@ private: { if (m_float_valid) { - m_text = std::to_string(m_float); + std::ostringstream stream; + stream.imbue(std::locale::classic()); + stream << m_float; + m_text = std::move(stream).str(); m_text_valid = true; } else if (m_int_valid) { - m_text = std::to_string(m_int); + std::ostringstream stream; + stream.imbue(std::locale::classic()); + stream << m_int; + m_text = std::move(stream).str(); m_text_valid = true; } } @@ -1270,6 +1277,7 @@ layout_element::layout_element(environment &env, util::xml::data_node const &ele , m_defstate(env.get_attribute_int(elemnode, "defstate", -1)) , m_statemask(0) , m_foldhigh(false) + , m_invalidated(false) { // parse components in order bool first = true; @@ -1640,6 +1648,17 @@ render_texture *layout_element::state_texture(int state) //------------------------------------------------- +// set_draw_callback - set handler called after +// drawing components +//------------------------------------------------- + +void layout_element::set_draw_callback(draw_delegate &&handler) +{ + m_draw = std::move(handler); +} + + +//------------------------------------------------- // preload - perform expensive loading upfront // for all components //------------------------------------------------- @@ -1652,6 +1671,25 @@ void layout_element::preload() //------------------------------------------------- +// prepare - perform additional tasks before +// drawing a frame +//------------------------------------------------- + +void layout_element::prepare() +{ + if (m_invalidated) + { + m_invalidated = false; + for (texture &tex : m_elemtex) + { + machine().render().texture_free(tex.m_texture); + tex.m_texture = nullptr; + } + } +} + + +//------------------------------------------------- // element_scale - scale an element by rendering // all the components at the appropriate // resolution @@ -1667,6 +1705,10 @@ void layout_element::element_scale(bitmap_argb32 &dest, bitmap_argb32 &source, c if ((elemtex.m_state & curcomp->statemask()) == curcomp->stateval()) curcomp->draw(elemtex.m_element->machine(), dest, elemtex.m_state); } + + // if there's a callback for additional drawing, invoke it + if (!elemtex.m_element->m_draw.isnull()) + elemtex.m_element->m_draw(elemtex.m_state, dest); } @@ -1748,10 +1790,10 @@ private: { u8 const *const src(reinterpret_cast<u8 const *>(dst)); rgb_t const d( - u8((float(src[3]) * c.a) + 0.5), - u8((float(src[0]) * c.r) + 0.5), - u8((float(src[1]) * c.g) + 0.5), - u8((float(src[2]) * c.b) + 0.5)); + u8((float(src[3]) * c.a) + 0.5F), + u8((float(src[0]) * c.r) + 0.5F), + u8((float(src[1]) * c.g) + 0.5F), + u8((float(src[2]) * c.b) + 0.5F)); *dst = d; havealpha = havealpha || (d.a() < 255U); } @@ -2027,17 +2069,12 @@ private: return; } svgbuf[len] = '\0'; - for (char *ptr = svgbuf.get(); len; ) + size_t actual; + std::tie(filerr, actual) = read(file, svgbuf.get(), len); + if (filerr || (actual < len)) { - size_t read; - filerr = file.read(ptr, size_t(len), read); - if (filerr || !read) - { - osd_printf_warning("Error reading component image '%s'\n", m_imagefile); - return; - } - ptr += read; - len -= read; + osd_printf_warning("Error reading component image '%s'\n", m_imagefile); + return; } parse_svg(svgbuf.get()); } @@ -2261,17 +2298,13 @@ public: if ((x >= minfill) && (x <= maxfill)) { if (255 <= a) - { dst = std::fill_n(dst, maxfill - x + 1, f); - x = maxfill; - } else - { while (x++ <= maxfill) alpha_blend(*dst++, a, r, g, b, inva); - --x; - } + --dst; + x = maxfill; } else { @@ -2373,17 +2406,13 @@ public: if ((x >= minfill) && (x <= maxfill)) { if (255 <= a) - { dst = std::fill_n(dst, maxfill - x + 1, f); - x = maxfill; - } else - { while (x++ <= maxfill) alpha_blend(*dst++, a, r, g, b, inva); - --x; - } + --dst; + x = maxfill; } else { @@ -3197,10 +3226,10 @@ protected: width = font->string_width(ourheight / num_shown, aspect, m_stopnames[fruit]); if (width < bounds.width()) break; - aspect *= 0.9f; + aspect *= 0.95f; } - s32 curx = bounds.left() + (bounds.width() - width) / 2; + float curx = bounds.left() + (bounds.width() - width) / 2.0f; // loop over characters std::string_view s = m_stopnames[fruit]; @@ -3227,7 +3256,7 @@ protected: u32 *const d = &dest.pix(effy); for (int x = 0; x < chbounds.width(); x++) { - int effx = curx + x + chbounds.left(); + int effx = int(curx) + x + chbounds.left(); if (effx >= bounds.left() && effx <= bounds.right()) { u32 spix = rgb_t(src[x]).a(); @@ -3345,10 +3374,10 @@ private: width = font->string_width(dest.height(), aspect, m_stopnames[fruit]); if (width < bounds.width()) break; - aspect *= 0.9f; + aspect *= 0.95f; } - s32 curx = bounds.left(); + float curx = bounds.left(); // allocate a temporary bitmap bitmap_argb32 tempbitmap(dest.width(), dest.height()); @@ -3378,7 +3407,7 @@ private: u32 *const d = &dest.pix(effy); for (int x = 0; x < chbounds.width(); x++) { - int effx = basex + curx + x; + int effx = basex + int(curx) + x; if (effx >= bounds.left() && effx <= bounds.right()) { u32 spix = rgb_t(src[x]).a(); @@ -3483,7 +3512,7 @@ layout_element::texture::texture(texture &&that) : texture() layout_element::texture::~texture() { - if (m_element != nullptr) + if (m_element) m_element->machine().render().texture_free(m_texture); } @@ -3685,12 +3714,6 @@ void layout_element::component::draw_text( int align, const render_color &color) { - // compute premultiplied color - u32 const r(color.r * 255.0f); - u32 const g(color.g * 255.0f); - u32 const b(color.b * 255.0f); - u32 const a(color.a * 255.0f); - // get the width of the string float aspect = 1.0f; s32 width; @@ -3700,11 +3723,11 @@ void layout_element::component::draw_text( width = font.string_width(bounds.height(), aspect, str); if (width < bounds.width()) break; - aspect *= 0.9f; + aspect *= 0.95f; } // get alignment - s32 curx; + float curx; switch (align) { // left @@ -3719,7 +3742,7 @@ void layout_element::component::draw_text( // default to center default: - curx = bounds.left() + (bounds.width() - width) / 2; + curx = bounds.left() + (bounds.width() - width) / 2.0f; break; } @@ -3749,18 +3772,13 @@ void layout_element::component::draw_text( u32 *const d = &dest.pix(effy); for (int x = 0; x < chbounds.width(); x++) { - int effx = curx + x + chbounds.left(); + int effx = int(curx) + x + chbounds.left(); if (effx >= bounds.left() && effx <= bounds.right()) { u32 spix = rgb_t(src[x]).a(); if (spix != 0) { - rgb_t dpix = d[effx]; - u32 ta = (a * (spix + 1)) >> 8; - u32 tr = (r * ta + dpix.r() * (0x100 - ta)) >> 8; - u32 tg = (g * ta + dpix.g() * (0x100 - ta)) >> 8; - u32 tb = (b * ta + dpix.b() * (0x100 - ta)) >> 8; - d[effx] = rgb_t(tr, tg, tb); + alpha_blend(d[effx], color, spix / 255.0); } } } @@ -3979,6 +3997,7 @@ layout_view::layout_view( : m_effaspect(1.0f) , m_name(make_name(env, viewnode)) , m_unqualified_name(env.get_attribute_string(viewnode, "name")) + , m_elemmap(elemmap) , m_defvismask(0U) , m_has_art(false) { @@ -4125,6 +4144,21 @@ bool layout_view::has_visible_screen(screen_device const &screen) const //------------------------------------------------- +// prepare_items - perform additional tasks +// before rendering a frame +//------------------------------------------------- + +void layout_view::prepare_items() +{ + if (!m_prepare_items.isnull()) + m_prepare_items(); + + for (auto &[name, element] : m_elemmap) + element.prepare(); +} + + +//------------------------------------------------- // recompute - recompute the bounds and aspect // ratio of a view and all of its contained items //------------------------------------------------- diff --git a/src/emu/rendlay.h b/src/emu/rendlay.h index 29b38fdd5d0..0391bc6e961 100644 --- a/src/emu/rendlay.h +++ b/src/emu/rendlay.h @@ -71,6 +71,7 @@ class layout_element { public: using environment = emu::render::detail::layout_environment; + using draw_delegate = delegate<void (int, bitmap_argb32 &)>; // construction/destruction layout_element(environment &env, util::xml::data_node const &elemnode); @@ -81,8 +82,13 @@ public: int default_state() const { return m_defstate; } render_texture *state_texture(int state); + // set handlers + void set_draw_callback(draw_delegate &&handler); + // operations void preload(); + void invalidate() { m_invalidated = true; } + void prepare(); private: /// \brief A drawing component within a layout element @@ -192,6 +198,8 @@ private: int m_statemask; // mask to apply to state values bool m_foldhigh; // whether we need to fold state values above the mask range std::vector<texture> m_elemtex; // array of element textures used for managing the scaled bitmaps + draw_delegate m_draw; // draw delegate (called after components are drawn) + bool m_invalidated; // force redrawing on next frame if set }; @@ -521,7 +529,7 @@ public: void set_recomputed_callback(recomputed_delegate &&handler); // operations - void prepare_items() { if (!m_prepare_items.isnull()) m_prepare_items(); } + void prepare_items(); void recompute(u32 visibility_mask, bool zoom_to_screens); void preload(); @@ -572,6 +580,7 @@ private: // cold items std::string m_name; // display name for the view std::string m_unqualified_name; // the name exactly as specified in the layout file + element_map & m_elemmap; // reference to shared elements item_id_map m_items_by_id; // items with non-empty ID indexed by ID visibility_toggle_vector m_vistoggles; // collections of items that can be shown/hidden render_bounds m_expbounds; // explicit bounds of the view @@ -598,6 +607,7 @@ public: // getters device_t &device() const { return m_device; } + element_map &elements() { return m_elemmap; } element_map const &elements() const { return m_elemmap; } view_list &views() { return m_viewlist; } view_list const &views() const { return m_viewlist; } diff --git a/src/emu/rendutil.cpp b/src/emu/rendutil.cpp index cffef8263d7..5d09061ab70 100644 --- a/src/emu/rendutil.cpp +++ b/src/emu/rendutil.cpp @@ -26,23 +26,22 @@ namespace { struct jpeg_corefile_source : public jpeg_source_mgr { - static void source(j_decompress_ptr cinfo, util::random_read &file); + static void source(j_decompress_ptr cinfo, util::random_read &file) noexcept; private: static constexpr unsigned INPUT_BUF_SIZE = 4096; - static void do_init(j_decompress_ptr cinfo) + static void do_init(j_decompress_ptr cinfo) noexcept { jpeg_corefile_source &src = *static_cast<jpeg_corefile_source *>(cinfo->src); src.start_of_file = true; } - static boolean do_fill(j_decompress_ptr cinfo) + static boolean do_fill(j_decompress_ptr cinfo) noexcept { jpeg_corefile_source &src = *static_cast<jpeg_corefile_source *>(cinfo->src); - size_t nbytes; - src.infile->read(src.buffer, INPUT_BUF_SIZE, nbytes); // TODO: check error return + auto [err, nbytes] = read(*src.infile, src.buffer, INPUT_BUF_SIZE); // TODO: check error return if (0 >= nbytes) { @@ -61,7 +60,7 @@ private: return TRUE; } - static void do_skip(j_decompress_ptr cinfo, long num_bytes) + static void do_skip(j_decompress_ptr cinfo, long num_bytes) noexcept { jpeg_corefile_source &src = *static_cast<jpeg_corefile_source *>(cinfo->src); @@ -70,14 +69,14 @@ private: while (long(src.bytes_in_buffer) < num_bytes) { num_bytes -= long(src.bytes_in_buffer); - (void)(*src.fill_input_buffer)(cinfo); + std::ignore = (*src.fill_input_buffer)(cinfo); } src.next_input_byte += size_t(num_bytes); src.bytes_in_buffer -= size_t(num_bytes); } } - static void do_term(j_decompress_ptr cinfo) + static void do_term(j_decompress_ptr cinfo) noexcept { } @@ -86,7 +85,7 @@ private: bool start_of_file; }; -void jpeg_corefile_source::source(j_decompress_ptr cinfo, util::random_read &file) +void jpeg_corefile_source::source(j_decompress_ptr cinfo, util::random_read &file) noexcept { jpeg_corefile_source *src; if (!cinfo->src) @@ -121,7 +120,7 @@ void jpeg_corefile_source::source(j_decompress_ptr cinfo, util::random_read &fil struct jpeg_setjmp_error_mgr : public jpeg_error_mgr { - jpeg_setjmp_error_mgr() + jpeg_setjmp_error_mgr() noexcept { jpeg_std_error(this); error_exit = [] (j_common_ptr cinfo) { std::longjmp(static_cast<jpeg_setjmp_error_mgr *>(cinfo->err)->m_jump_buffer, 1); }; @@ -138,9 +137,9 @@ struct jpeg_setjmp_error_mgr : public jpeg_error_mgr ***************************************************************************/ /* utilities */ -static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy); -static void resample_argb_bitmap_bilinear(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy); -static bool copy_png_alpha_to_bitmap(bitmap_argb32 &bitmap, const util::png_info &png); +static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy) noexcept; +static void resample_argb_bitmap_bilinear(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy) noexcept; +static bool copy_png_alpha_to_bitmap(bitmap_argb32 &bitmap, const util::png_info &png) noexcept; @@ -153,15 +152,15 @@ static bool copy_png_alpha_to_bitmap(bitmap_argb32 &bitmap, const util::png_info quality resampling of a texture -------------------------------------------------*/ -void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, const render_color &color, bool force) +void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, const render_color &color, bool force) noexcept { if (dest.width() == 0 || dest.height() == 0) return; - /* adjust the source base */ + // adjust the source base const u32 *sbase = &source.pix(0); - /* determine the steppings */ + // determine the steppings u32 swidth = source.width(); u32 sheight = source.height(); u32 dwidth = dest.width(); @@ -169,7 +168,7 @@ void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, u32 dx = (swidth << 12) / dwidth; u32 dy = (sheight << 12) / dheight; - /* if the source is higher res than the target, use full averaging */ + // if the source is higher res than the target, use full averaging if (dx > 0x1000 || dy > 0x1000 || force) resample_argb_bitmap_average(&dest.pix(0), dest.rowpixels(), dwidth, dheight, sbase, source.rowpixels(), swidth, sheight, color, dx, dy); else @@ -183,62 +182,58 @@ void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, all contributing pixels -------------------------------------------------*/ -static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy) +static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy) noexcept { - u64 sumscale = u64(dx) * u64(dy); - u32 r, g, b, a; - u32 x, y; - - /* precompute premultiplied R/G/B/A factors */ - r = color.r * color.a * 256.0f; - g = color.g * color.a * 256.0f; - b = color.b * color.a * 256.0f; - a = color.a * 256.0f; - - /* loop over the target vertically */ - for (y = 0; y < dheight; y++) + u64 const sumscale = u64(dx) * u64(dy); + + // precompute premultiplied R/G/B/A factors + u32 const r = color.r * color.a * 256.0f; + u32 const g = color.g * color.a * 256.0f; + u32 const b = color.b * color.a * 256.0f; + u32 const a = color.a * 256.0f; + + // loop over the target vertically + for (u32 y = 0; y < dheight; y++) { - u32 starty = y * dy; + u32 const starty = y * dy; - /* loop over the target horizontally */ - for (x = 0; x < dwidth; x++) + // loop over the target horizontally + for (u32 x = 0; x < dwidth; x++) { u64 sumr = 0, sumg = 0, sumb = 0, suma = 0; - u32 startx = x * dx; - u32 xchunk, ychunk; - u32 curx, cury; + u32 const startx = x * dx; u32 yremaining = dy; + u32 ychunk; - /* accumulate all source pixels that contribute to this pixel */ - for (cury = starty; yremaining; cury += ychunk) + // accumulate all source pixels that contribute to this pixel + for (u32 cury = starty; yremaining; cury += ychunk) { u32 xremaining = dx; + u32 xchunk; - /* determine the Y contribution, clamping to the amount remaining */ + // determine the Y contribution, clamping to the amount remaining ychunk = 0x1000 - (cury & 0xfff); if (ychunk > yremaining) ychunk = yremaining; yremaining -= ychunk; - /* loop over all source pixels in the X direction */ - for (curx = startx; xremaining; curx += xchunk) + // loop over all source pixels in the X direction + for (u32 curx = startx; xremaining; curx += xchunk) { - u32 factor; - - /* determine the X contribution, clamping to the amount remaining */ + // determine the X contribution, clamping to the amount remaining xchunk = 0x1000 - (curx & 0xfff); if (xchunk > xremaining) xchunk = xremaining; xremaining -= xchunk; - /* total contribution = x * y */ - factor = xchunk * ychunk; + // total contribution = x * y + u32 const factor = xchunk * ychunk; - /* fetch the source pixel */ - rgb_t pix = source[(cury >> 12) * srowpixels + (curx >> 12)]; + // fetch the source pixel + rgb_t const pix = source[(cury >> 12) * srowpixels + (curx >> 12)]; - /* accumulate the RGBA values */ + // accumulate the RGBA values sumr += factor * pix.r(); sumg += factor * pix.g(); sumb += factor * pix.b(); @@ -246,23 +241,23 @@ static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, } } - /* apply scaling */ + // apply scaling suma = (suma / sumscale) * a / 256; sumr = (sumr / sumscale) * r / 256; sumg = (sumg / sumscale) * g / 256; sumb = (sumb / sumscale) * b / 256; - /* if we're translucent, add in the destination pixel contribution */ + // if we're translucent, add in the destination pixel contribution if (a < 256) { - rgb_t dpix = dest[y * drowpixels + x]; + rgb_t const dpix = dest[y * drowpixels + x]; suma += dpix.a() * (256 - a); sumr += dpix.r() * (256 - a); sumg += dpix.g() * (256 - a); sumb += dpix.b() * (256 - a); } - /* store the target pixel, dividing the RGBA values by the overall scale factor */ + // store the target pixel, dividing the RGBA values by the overall scale factor dest[y * drowpixels + x] = rgb_t(suma, sumr, sumg, sumb); } } @@ -274,44 +269,37 @@ static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, sampling via a bilinear filter -------------------------------------------------*/ -static void resample_argb_bitmap_bilinear(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy) +static void resample_argb_bitmap_bilinear(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy) noexcept { - u32 maxx = swidth << 12, maxy = sheight << 12; - u32 r, g, b, a; - u32 x, y; - - /* precompute premultiplied R/G/B/A factors */ - r = color.r * color.a * 256.0f; - g = color.g * color.a * 256.0f; - b = color.b * color.a * 256.0f; - a = color.a * 256.0f; - - /* loop over the target vertically */ - for (y = 0; y < dheight; y++) + u32 const maxx = swidth << 12, maxy = sheight << 12; + + // precompute premultiplied R/G/B/A factors + u32 const r = color.r * color.a * 256.0f; + u32 const g = color.g * color.a * 256.0f; + u32 const b = color.b * color.a * 256.0f; + u32 const a = color.a * 256.0f; + + // loop over the target vertically + for (u32 y = 0; y < dheight; y++) { - u32 starty = y * dy; + u32 const starty = y * dy; - /* loop over the target horizontally */ - for (x = 0; x < dwidth; x++) + // loop over the target horizontally + for (u32 x = 0; x < dwidth; x++) { - u32 startx = x * dx; - rgb_t pix0, pix1, pix2, pix3; - u32 sumr, sumg, sumb, suma; - u32 nextx, nexty; - u32 curx, cury; - u32 factor; + u32 const startx = x * dx; - /* adjust start to the center; note that this math will tend to produce */ - /* negative results on the first pixel, which is why we clamp below */ - curx = startx + dx / 2 - 0x800; - cury = starty + dy / 2 - 0x800; + // adjust start to the center; note that this math will tend to produce + // negative results on the first pixel, which is why we clamp below + u32 curx = startx + dx / 2 - 0x800; + u32 cury = starty + dy / 2 - 0x800; - /* compute the neighboring pixel */ - nextx = curx + 0x1000; - nexty = cury + 0x1000; + // compute the neighboring pixel + u32 const nextx = curx + 0x1000; + u32 const nexty = cury + 0x1000; - /* fetch the four relevant pixels */ - pix0 = pix1 = pix2 = pix3 = 0; + // fetch the four relevant pixels + rgb_t pix0 = 0, pix1 = 0, pix2 = 0, pix3 = 0; if (s32(cury) >= 0 && cury < maxy && s32(curx) >= 0 && curx < maxx) pix0 = source[(cury >> 12) * srowpixels + (curx >> 12)]; if (s32(cury) >= 0 && cury < maxy && s32(nextx) >= 0 && nextx < maxx) @@ -321,55 +309,58 @@ static void resample_argb_bitmap_bilinear(u32 *dest, u32 drowpixels, u32 dwidth, if (s32(nexty) >= 0 && nexty < maxy && s32(nextx) >= 0 && nextx < maxx) pix3 = source[(nexty >> 12) * srowpixels + (nextx >> 12)]; - /* compute the x/y scaling factors */ + // compute the x/y scaling factors curx &= 0xfff; cury &= 0xfff; - /* contributions from pixel 0 (top,left) */ + u32 factor; + u32 sumr, sumg, sumb, suma; + + // contributions from pixel 0 (top,left) factor = (0x1000 - curx) * (0x1000 - cury); sumr = factor * pix0.r(); sumg = factor * pix0.g(); sumb = factor * pix0.b(); suma = factor * pix0.a(); - /* contributions from pixel 1 (top,right) */ + // contributions from pixel 1 (top,right) factor = curx * (0x1000 - cury); sumr += factor * pix1.r(); sumg += factor * pix1.g(); sumb += factor * pix1.b(); suma += factor * pix1.a(); - /* contributions from pixel 2 (bottom,left) */ + // contributions from pixel 2 (bottom,left) factor = (0x1000 - curx) * cury; sumr += factor * pix2.r(); sumg += factor * pix2.g(); sumb += factor * pix2.b(); suma += factor * pix2.a(); - /* contributions from pixel 3 (bottom,right) */ + // contributions from pixel 3 (bottom,right) factor = curx * cury; sumr += factor * pix3.r(); sumg += factor * pix3.g(); sumb += factor * pix3.b(); suma += factor * pix3.a(); - /* apply scaling */ + // apply scaling suma = (suma >> 24) * a / 256; sumr = (sumr >> 24) * r / 256; sumg = (sumg >> 24) * g / 256; sumb = (sumb >> 24) * b / 256; - /* if we're translucent, add in the destination pixel contribution */ + // if we're translucent, add in the destination pixel contribution if (a < 256) { - rgb_t dpix = dest[y * drowpixels + x]; + rgb_t const dpix = dest[y * drowpixels + x]; suma += dpix.a() * (256 - a); sumr += dpix.r() * (256 - a); sumg += dpix.g() * (256 - a); sumb += dpix.b() * (256 - a); } - /* store the target pixel, dividing the RGBA values by the overall scale factor */ + // store the target pixel, dividing the RGBA values by the overall scale factor dest[y * drowpixels + x] = rgb_t(suma, sumr, sumg, sumb); } } @@ -653,7 +644,7 @@ std::pair<render_bounds, render_bounds> render_line_to_quad(const render_bounds into a bitmap -------------------------------------------------*/ -void render_load_msdib(bitmap_argb32 &bitmap, util::random_read &file) +void render_load_msdib(bitmap_argb32 &bitmap, util::random_read &file) noexcept { // deallocate previous bitmap bitmap.reset(); @@ -673,7 +664,7 @@ void render_load_msdib(bitmap_argb32 &bitmap, util::random_read &file) bitmap -------------------------------------------------*/ -void render_load_jpeg(bitmap_argb32 &bitmap, util::random_read &file) +void render_load_jpeg(bitmap_argb32 &bitmap, util::random_read &file) noexcept { // deallocate previous bitmap bitmap.reset(); @@ -711,30 +702,39 @@ void render_load_jpeg(bitmap_argb32 &bitmap, util::random_read &file) // allocates a buffer to receive the information and copy them into the bitmap row_stride = cinfo.output_width * cinfo.output_components; buffer = reinterpret_cast<JSAMPARRAY>(std::malloc(sizeof(JSAMPROW))); - buffer[0] = reinterpret_cast<JSAMPROW>(std::malloc(sizeof(JSAMPLE) * row_stride)); + if (buffer) + buffer[0] = reinterpret_cast<JSAMPROW>(std::malloc(sizeof(JSAMPLE) * row_stride)); - while (cinfo.output_scanline < cinfo.output_height) + if (bitmap.valid() && buffer && buffer[0]) { - j = cinfo.output_scanline; - jpeg_read_scanlines(&cinfo, buffer, 1); - - if (s == 1) + while (cinfo.output_scanline < cinfo.output_height) { - for (i = 0; i < w; ++i) - bitmap.pix(j, i) = rgb_t(0xff, buffer[0][i], buffer[0][i], buffer[0][i]); + j = cinfo.output_scanline; + jpeg_read_scanlines(&cinfo, buffer, 1); + if (s == 1) + { + for (i = 0; i < w; ++i) + bitmap.pix(j, i) = rgb_t(0xff, buffer[0][i], buffer[0][i], buffer[0][i]); + + } + else if (s == 3) + { + for (i = 0; i < w; ++i) + bitmap.pix(j, i) = rgb_t(0xff, buffer[0][i * s], buffer[0][i * s + 1], buffer[0][i * s + 2]); + } + else + { + osd_printf_error("Cannot read JPEG data from file.\n"); + bitmap.reset(); + break; + } } - else if (s == 3) - { - for (i = 0; i < w; ++i) - bitmap.pix(j, i) = rgb_t(0xff, buffer[0][i * s], buffer[0][i * s + 1], buffer[0][i * s + 2]); - } - else - { - osd_printf_error("Cannot read JPEG data from file.\n"); - bitmap.reset(); - break; - } + } + else + { + osd_printf_error("Error allocating memory for JPEG image.\n"); + bitmap.reset(); } // finish decompression and free the memory @@ -755,7 +755,7 @@ cleanup: bitmap -------------------------------------------------*/ -bool render_load_png(bitmap_argb32 &bitmap, util::random_read &file, bool load_as_alpha_to_existing) +bool render_load_png(bitmap_argb32 &bitmap, util::random_read &file, bool load_as_alpha_to_existing) noexcept { // deallocate if we're not overlaying alpha if (!load_as_alpha_to_existing) @@ -810,7 +810,7 @@ bool render_load_png(bitmap_argb32 &bitmap, util::random_read &file, bool load_a to the alpha channel of a bitmap -------------------------------------------------*/ -static bool copy_png_alpha_to_bitmap(bitmap_argb32 &bitmap, const util::png_info &png) +static bool copy_png_alpha_to_bitmap(bitmap_argb32 &bitmap, const util::png_info &png) noexcept { // FIXME: this function is basically copy/pasted from the PNG code in util, and should be unified with it u8 accumalpha = 0xff; @@ -921,7 +921,7 @@ static bool copy_png_alpha_to_bitmap(bitmap_argb32 &bitmap, const util::png_info render_detect_image - detect image format -------------------------------------------------*/ -ru_imgformat render_detect_image(util::random_read &file) +ru_imgformat render_detect_image(util::random_read &file) noexcept { // PNG: check for valid header { diff --git a/src/emu/rendutil.h b/src/emu/rendutil.h index de29ed64d2a..71e5bdc95c3 100644 --- a/src/emu/rendutil.h +++ b/src/emu/rendutil.h @@ -42,14 +42,14 @@ enum ru_imgformat /* ----- render utilities ----- */ -void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, const render_color &color, bool force = false); +void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, const render_color &color, bool force = false) noexcept; bool render_clip_line(render_bounds &bounds, const render_bounds &clip); bool render_clip_quad(render_bounds &bounds, const render_bounds &clip, render_quad_texuv *texcoords); std::pair<render_bounds, render_bounds> render_line_to_quad(const render_bounds &bounds, float width, float length_extension); -void render_load_msdib(bitmap_argb32 &bitmap, util::random_read &file); -void render_load_jpeg(bitmap_argb32 &bitmap, util::random_read &file); -bool render_load_png(bitmap_argb32 &bitmap, util::random_read &file, bool load_as_alpha_to_existing = false); -ru_imgformat render_detect_image(util::random_read &file); +void render_load_msdib(bitmap_argb32 &bitmap, util::random_read &file) noexcept; +void render_load_jpeg(bitmap_argb32 &bitmap, util::random_read &file) noexcept; +bool render_load_png(bitmap_argb32 &bitmap, util::random_read &file, bool load_as_alpha_to_existing = false) noexcept; +ru_imgformat render_detect_image(util::random_read &file) noexcept; diff --git a/src/emu/romentry.h b/src/emu/romentry.h index ff73e432c65..2a315c2a03e 100644 --- a/src/emu/romentry.h +++ b/src/emu/romentry.h @@ -29,18 +29,17 @@ CONSTANTS #define ROMENTRY_TYPEMASK 0x0000000f /* type of entry */ enum { - ROMENTRYTYPE_ROM = 0, /* this entry is an actual ROM definition */ - ROMENTRYTYPE_REGION, /* this entry marks the start of a region */ - ROMENTRYTYPE_END, /* this entry marks the end of a region */ - ROMENTRYTYPE_RELOAD, /* this entry reloads the previous ROM */ - ROMENTRYTYPE_CONTINUE, /* this entry continues loading the previous ROM */ - ROMENTRYTYPE_FILL, /* this entry fills an area with a constant value */ - ROMENTRYTYPE_COPY, /* this entry copies data from another region/offset */ - ROMENTRYTYPE_CARTRIDGE, /* this entry specifies a cartridge (MESS) */ - ROMENTRYTYPE_IGNORE, /* this entry continues loading the previous ROM but throws the data away */ - ROMENTRYTYPE_SYSTEM_BIOS, /* this entry specifies a bios */ - ROMENTRYTYPE_DEFAULT_BIOS, /* this entry specifies a default bios */ - ROMENTRYTYPE_PARAMETER, /* this entry specifies a per-game parameter */ + ROMENTRYTYPE_ROM = 0, // starts loading a ROM file + ROMENTRYTYPE_REGION, // starts a new ROM region + ROMENTRYTYPE_END, // sentinel marking the end of a ROM definition + ROMENTRYTYPE_RELOAD, // starts loading the current ROM file from the beginning again + ROMENTRYTYPE_CONTINUE, // continues loading the current ROM file at a different offset + ROMENTRYTYPE_FILL, // fills an area with a constant value + ROMENTRYTYPE_COPY, // copies data from another region/offset + ROMENTRYTYPE_IGNORE, // ignores a portion of the current ROM file + ROMENTRYTYPE_SYSTEM_BIOS, // specifies a BIOS option + ROMENTRYTYPE_DEFAULT_BIOS, // specifies the default BIOS option + ROMENTRYTYPE_PARAMETER, // specifies a per-game parameter ROMENTRYTYPE_COUNT }; diff --git a/src/emu/romload.cpp b/src/emu/romload.cpp index 4ce34832c78..a429153be3f 100644 --- a/src/emu/romload.cpp +++ b/src/emu/romload.cpp @@ -14,12 +14,16 @@ #include "drivenum.h" #include "emuopts.h" #include "fileio.h" +#include "main.h" #include "softlist_dev.h" + #include "ui/uimain.h" #include "corestr.h" +#include "path.h" #include <algorithm> +#include <cstdarg> #include <set> @@ -39,6 +43,25 @@ namespace { +/*------------------------------------------------- + debugload - log data to a file +-------------------------------------------------*/ + +void ATTR_PRINTF(1,2) debugload(const char *string, ...) +{ + static int opened = 0; + FILE *const f(fopen("romload.log", opened++ ? "a" : "w")); + if (f) + { + va_list arg; + va_start(arg, string); + vfprintf(f, string, arg); + va_end(arg); + fclose(f); + } +} + + auto next_parent_system(game_driver const &system) { return @@ -50,13 +73,41 @@ auto next_parent_system(game_driver const &system) if (0 > parent) { sys = nullptr; + roms.clear(); + roms.shrink_to_fit(); return nullptr; } else { sys = &driver_list::driver(parent); roms = rom_build_entries(sys->rom); - return &roms[0]; + return &roms.front(); + } + }; +} + + +auto next_parent_device(device_t const &device, emu_options &options) +{ + return + [&options, type = &device.type(), roms = std::vector<rom_entry>()] () mutable -> rom_entry const * + { + if (!type) + return nullptr; + type = type->parent_rom_device_type(); + if (!type) + { + roms.clear(); + roms.shrink_to_fit(); + return nullptr; + } + else + { + machine_config config(GAME_NAME(___empty), options); + machine_config::token const tok(config.begin_configuration(config.root_device())); + roms = config.device_add("_tmp", *type, 0)->rom_region_vector(); + config.device_remove("_tmp"); + return &roms.front(); } }; } @@ -91,7 +142,7 @@ std::vector<std::string> make_software_searchpath(software_list_device &swlist, if (std::find(parents.begin(), parents.end(), i) != parents.end()) break; parents.emplace_back(i); - result.emplace_back(util::string_format("%s" PATH_SEPARATOR "%s", swlist.list_name(), i->shortname())); + result.emplace_back(util::path_concat(swlist.list_name(), i->shortname())); i = i->parentname().empty() ? nullptr : swlist.find(i->parentname()); } @@ -103,13 +154,19 @@ std::vector<std::string> make_software_searchpath(software_list_device &swlist, } -std::error_condition do_open_disk(const emu_options &options, std::initializer_list<std::reference_wrapper<const std::vector<std::string> > > searchpath, const rom_entry *romp, chd_file &chd, std::function<const rom_entry * ()> next_parent) +std::error_condition do_open_disk( + emu_options const &options, + std::initializer_list<std::reference_wrapper<std::vector<std::string> const> > searchpath, + rom_entry const *romp, + chd_file &chd, + std::function<rom_entry const * ()> next_parent, + chd_file::open_parent_func const &open_parent) { // hashes are fixed, but we might need to try multiple filenames std::set<std::string> tried; - const util::hash_collection hashes(romp->hashdata()); + util::hash_collection const hashes(romp->hashdata()); std::string filename, fullpath; - const rom_entry *parent(nullptr); + rom_entry const *parent(nullptr); std::error_condition result(std::errc::no_such_file_or_directory); while (romp && result) { @@ -118,11 +175,11 @@ std::error_condition do_open_disk(const emu_options &options, std::initializer_l { // piggyback on emu_file to find the disk image file std::unique_ptr<emu_file> imgfile; - for (const std::vector<std::string> &paths : searchpath) + for (std::vector<std::string> const &paths : searchpath) { imgfile.reset(new emu_file(options.media_path(), paths, OPEN_FLAG_READ)); imgfile->set_restrict_to_mediapath(1); - const std::error_condition filerr(imgfile->open(filename, OPEN_FLAG_READ)); + std::error_condition const filerr(imgfile->open(filename, OPEN_FLAG_READ)); if (!filerr) break; else @@ -134,7 +191,7 @@ std::error_condition do_open_disk(const emu_options &options, std::initializer_l { fullpath = imgfile->fullpath(); imgfile.reset(); - result = chd.open(fullpath); + result = chd.open(fullpath, false, nullptr, open_parent); } } @@ -156,10 +213,7 @@ std::error_condition do_open_disk(const emu_options &options, std::initializer_l romp = nullptr; break; } - while (ROMENTRY_ISPARAMETER(parent) || ROMENTRY_ISSYSTEM_BIOS(parent) || ROMENTRY_ISDEFAULT_BIOS(parent)) - ++parent; - if (ROMENTRY_ISEND(parent)) - parent = nullptr; + parent = rom_first_region(parent); } else { @@ -180,6 +234,46 @@ std::error_condition do_open_disk(const emu_options &options, std::initializer_l return result; } + +auto open_parent_disk( + emu_options const &options, + std::initializer_list<std::reference_wrapper<std::vector<std::string> const> > searchpath, + std::function<rom_entry const * ()> const &next_parent) +{ + return + [&options, searchpath, next_parent] (util::sha1_t const &sha1) -> std::unique_ptr<chd_file> + { + util::hash_collection hashes; + hashes.add_sha1(sha1); + std::function<rom_entry const * ()> np(next_parent); // important - copy mutable lambda + for (rom_entry const *parent = np(); parent; parent = np()) + { + parent = rom_first_region(parent); + while (parent) + { + while (parent && !ROMREGION_ISDISKDATA(parent)) + parent = rom_next_region(parent); + if (parent) + { + rom_entry const *romp(rom_first_file(parent)); + while (romp) + { + if (util::hash_collection(romp->hashdata()) == hashes) + { + std::unique_ptr<chd_file> chd(new chd_file); + if (!do_open_disk(options, searchpath, romp, *chd, next_parent, nullptr)) + return chd; + } + romp = rom_next_file(romp); + } + parent = rom_next_region(parent); + } + } + } + return nullptr; + }; +} + } // anonymous namespace @@ -259,7 +353,7 @@ const rom_entry *rom_first_parameter(const device_t &device) const rom_entry *romp = &device.rom_region_vector().front(); while (romp && !ROMENTRY_ISEND(romp) && !ROMENTRY_ISPARAMETER(romp)) romp++; - return (romp != nullptr && !ROMENTRY_ISEND(romp)) ? romp : nullptr; + return (romp && !ROMENTRY_ISEND(romp)) ? romp : nullptr; } @@ -284,17 +378,17 @@ const rom_entry *rom_next_parameter(const rom_entry *romp) u32 rom_file_size(const rom_entry *romp) { - u32 maxlength = 0; + u32 maxlength(0); - /* loop until we run out of reloads */ + // loop until we run out of reloads do { - /* loop until we run out of continues/ignores */ + // loop until we run out of continues/ignores u32 curlength = ROM_GETLENGTH(romp++); while (ROMENTRY_ISCONTINUE(romp) || ROMENTRY_ISIGNORE(romp)) curlength += ROM_GETLENGTH(romp++); - /* track the maximum length */ + // track the maximum length maxlength = std::max(maxlength, curlength); } while (ROMENTRY_ISRELOAD(romp)); @@ -303,27 +397,6 @@ u32 rom_file_size(const rom_entry *romp) } -/*------------------------------------------------- - debugload - log data to a file --------------------------------------------------*/ - -static void CLIB_DECL ATTR_PRINTF(1,2) debugload(const char *string, ...) -{ - static int opened; - va_list arg; - FILE *f; - - f = fopen("romload.log", opened++ ? "a" : "w"); - if (f) - { - va_start(arg, string); - vfprintf(f, string, arg); - va_end(arg); - fclose(f); - } -} - - /*************************************************************************** HARD DISK HANDLING ***************************************************************************/ @@ -336,8 +409,10 @@ static void CLIB_DECL ATTR_PRINTF(1,2) debugload(const char *string, ...) chd_file *rom_load_manager::get_disk_handle(std::string_view region) { for (auto &curdisk : m_chd_list) + { if (curdisk->region() == region) return &curdisk->chd(); + } return nullptr; } @@ -347,37 +422,36 @@ chd_file *rom_load_manager::get_disk_handle(std::string_view region) file associated with the given region -------------------------------------------------*/ -std::error_condition rom_load_manager::set_disk_handle(std::string_view region, const char *fullpath) +std::error_condition rom_load_manager::set_disk_handle(std::string_view region, std::string_view fullpath) { - auto chd = std::make_unique<open_chd>(region); - auto err = chd->orig_chd().open(fullpath); + auto chd(std::make_unique<open_chd>(region)); + std::error_condition const err(chd->orig_chd().open(fullpath)); if (!err) - m_chd_list.push_back(std::move(chd)); + m_chd_list.emplace_back(std::move(chd)); return err; } /*------------------------------------------------- determine_bios_rom - determine system_bios - from SystemBios structure and OPTION_BIOS + from SYSTEM_BIOS structure and OPTION_BIOS -------------------------------------------------*/ -void rom_load_manager::determine_bios_rom(device_t &device, const char *specbios) +void rom_load_manager::determine_bios_rom(device_t &device, std::string_view specbios) { // default is applied by the device at config complete time - if (specbios && *specbios && core_stricmp(specbios, "default")) + using namespace std::literals; + if (!specbios.empty() && !util::streqlower(specbios, "default"sv)) { bool found(false); - for (const rom_entry &rom : device.rom_region_vector()) + for (rom_entry const &rom : device.rom_region_vector()) { if (ROMENTRY_ISSYSTEM_BIOS(&rom)) { char const *const biosname = ROM_GETNAME(&rom); int const bios_flags = ROM_GETBIOSFLAGS(&rom); - char bios_number[20]; // Allow '-bios n' to still be used - sprintf(bios_number, "%d", bios_flags - 1); - if (!core_stricmp(bios_number, specbios) || !core_stricmp(biosname, specbios)) + if ((specbios == std::to_string(bios_flags - 1)) || util::streqlower(specbios, biosname)) { found = true; device.set_system_bios(bios_flags); @@ -406,21 +480,29 @@ void rom_load_manager::determine_bios_rom(device_t &device, const char *specbios void rom_load_manager::count_roms() { - const rom_entry *region, *rom; - - /* start with 0 */ + // start with 0 m_romstotal = 0; m_romstotalsize = 0; - /* loop over regions, then over files */ + // loop over regions, and files within regions for (device_t &device : device_enumerator(machine().config().root_device())) - for (region = rom_first_region(device); region != nullptr; region = rom_next_region(region)) - for (rom = rom_first_file(region); rom != nullptr; rom = rom_next_file(rom)) - if (ROM_GETBIOSFLAGS(rom) == 0 || ROM_GETBIOSFLAGS(rom) == device.system_bios()) + { + rom_entry const *region(rom_first_region(device)); + while (region) + { + rom_entry const *rom(rom_first_file(region)); + while (rom) + { + if ((ROM_GETBIOSFLAGS(rom) == 0) || (ROM_GETBIOSFLAGS(rom) == device.system_bios())) { m_romstotal++; m_romstotalsize += rom_file_size(rom); } + rom = rom_next_file(rom); + } + region = rom_next_region(region); + } + } } @@ -458,7 +540,7 @@ void rom_load_manager::handle_missing_file(const rom_entry *romp, const std::vec const bool is_chd(chderr); const std::string name(is_chd ? romp->name() + ".chd" : romp->name()); - const bool is_chd_error(is_chd && chderr != std::errc::no_such_file_or_directory); + const bool is_chd_error(is_chd && (chderr != std::errc::no_such_file_or_directory)); if (is_chd_error) m_errorstring.append(string_format("%s CHD ERROR: %s\n", name, chderr.message())); @@ -511,7 +593,7 @@ void rom_load_manager::verify_length_and_hash(emu_file *file, std::string_view n return; // verify length - u64 const actlength = file->size(); + u64 const actlength(file->size()); if (explength != actlength) { m_errorstring.append(string_format("%s WRONG LENGTH (expected: %08x found: %08x)\n", name, explength, actlength)); @@ -527,7 +609,7 @@ void rom_load_manager::verify_length_and_hash(emu_file *file, std::string_view n else { // verify checksums - util::hash_collection const &acthashes = file->hashes(hashes.hash_types()); + util::hash_collection const &acthashes(file->hashes(hashes.hash_types())); if (hashes != acthashes) { // otherwise, it's just bad @@ -573,19 +655,19 @@ void rom_load_manager::display_loading_rom_message(const char *name, bool from_l void rom_load_manager::display_rom_load_results(bool from_list) { - /* final status display */ + // final status display display_loading_rom_message(nullptr, from_list); - /* if we had errors, they are fatal */ + // if we had errors, they are fatal if (m_errors != 0) { - /* create the error message and exit fatally */ + // create the error message and exit fatally osd_printf_error("%s", m_errorstring); throw emu_fatalerror(EMU_ERR_MISSING_FILES, "Required files are missing, the machine cannot be run."); } - /* if we had warnings, output them, but continue */ - if ((m_warnings) || (m_knownbad)) + // if we had warnings, output them, but continue + if (m_warnings || m_knownbad) { m_errorstring.append("WARNING: the machine might not run correctly."); osd_printf_warning("%s\n", m_errorstring); @@ -601,27 +683,28 @@ void rom_load_manager::display_rom_load_results(bool from_list) void rom_load_manager::region_post_process(memory_region *region, bool invert) { // do nothing if no region - if (region == nullptr) + if (!region) return; - LOG("+ datawidth=%dbit endian=%s\n", region->bitwidth(), - region->endianness() == ENDIANNESS_LITTLE ? "little" : "big"); + LOG("+ datawidth=%dbit endian=%s\n", + region->bitwidth(), + (region->endianness() == ENDIANNESS_LITTLE) ? "little" : "big"); - /* if the region is inverted, do that now */ + // if the region is inverted, do that now if (invert) { LOG("+ Inverting region\n"); - u8 *base = region->base(); + u8 *base(region->base()); for (int i = 0; i < region->bytes(); i++) *base++ ^= 0xff; } - /* swap the endianness if we need to */ - if (region->bytewidth() > 1 && region->endianness() != ENDIANNESS_NATIVE) + // swap the endianness if we need to + int const datawidth(region->bytewidth()); + if ((datawidth > 1) && (region->endianness() != ENDIANNESS_NATIVE)) { LOG("+ Byte swapping region\n"); - int datawidth = region->bytewidth(); - u8 *base = region->base(); + u8 *base(region->base()); for (int i = 0; i < region->bytes(); i += datawidth) { u8 temp[8]; @@ -638,7 +721,11 @@ void rom_load_manager::region_post_process(memory_region *region, bool invert) up the parent and loading by checksum -------------------------------------------------*/ -std::unique_ptr<emu_file> rom_load_manager::open_rom_file(std::initializer_list<std::reference_wrapper<const std::vector<std::string> > > searchpath, const rom_entry *romp, std::vector<std::string> &tried_file_names, bool from_list) +std::unique_ptr<emu_file> rom_load_manager::open_rom_file( + const std::vector<std::string> &searchpath, + const rom_entry *romp, + std::vector<std::string> &tried_file_names, + bool from_list) { std::error_condition filerr = std::errc::no_such_file_or_directory; u32 const romsize = rom_file_size(romp); @@ -653,13 +740,8 @@ std::unique_ptr<emu_file> rom_load_manager::open_rom_file(std::initializer_list< // attempt reading up the chain through the parents // it also automatically attempts any kind of load by checksum supported by the archives. - std::unique_ptr<emu_file> result; - for (const std::vector<std::string> &paths : searchpath) - { - result = open_rom_file(paths, tried_file_names, has_crc, crc, ROM_GETNAME(romp), filerr); - if (result) - break; - } + std::unique_ptr<emu_file> result( + open_rom_file(searchpath, tried_file_names, has_crc, crc, ROM_GETNAME(romp), filerr)); // update counters m_romsloaded++; @@ -673,7 +755,13 @@ std::unique_ptr<emu_file> rom_load_manager::open_rom_file(std::initializer_list< } -std::unique_ptr<emu_file> rom_load_manager::open_rom_file(const std::vector<std::string> &paths, std::vector<std::string> &tried, bool has_crc, u32 crc, std::string_view name, std::error_condition &filerr) +std::unique_ptr<emu_file> rom_load_manager::open_rom_file( + const std::vector<std::string> &paths, + std::vector<std::string> &tried, + bool has_crc, + u32 crc, + std::string_view name, + std::error_condition &filerr) { // record the set names we search tried.insert(tried.end(), paths.begin(), paths.end()); @@ -716,50 +804,52 @@ int rom_load_manager::rom_fread(emu_file *file, u8 *buffer, int length, const ro entry -------------------------------------------------*/ -int rom_load_manager::read_rom_data(emu_file *file, const rom_entry *parent_region, const rom_entry *romp) +int rom_load_manager::read_rom_data( + emu_file *file, + memory_region ®ion, + const rom_entry *parent_region, + const rom_entry *romp) { - int datashift = ROM_GETBITSHIFT(romp); - int datamask = ((1 << ROM_GETBITWIDTH(romp)) - 1) << datashift; - int numbytes = ROM_GETLENGTH(romp); - int groupsize = ROM_GETGROUPSIZE(romp); - int skip = ROM_GETSKIPCOUNT(romp); - int reversed = ROM_ISREVERSED(romp); - int numgroups = (numbytes + groupsize - 1) / groupsize; - u8 *base = m_region->base() + ROM_GETOFFSET(romp); - u32 tempbufsize; - int i; + int const datashift(ROM_GETBITSHIFT(romp)); + int const datamask(((1 << ROM_GETBITWIDTH(romp)) - 1) << datashift); + int numbytes(ROM_GETLENGTH(romp)); + int const groupsize(ROM_GETGROUPSIZE(romp)); + int skip(ROM_GETSKIPCOUNT(romp)); + int const reversed(ROM_ISREVERSED(romp)); + int const numgroups((numbytes + groupsize - 1) / groupsize); + u8 *base = region.base() + ROM_GETOFFSET(romp); LOG("Loading ROM data: offs=%X len=%X mask=%02X group=%d skip=%d reverse=%d\n", ROM_GETOFFSET(romp), numbytes, datamask, groupsize, skip, reversed); - /* make sure the length was an even multiple of the group size */ - if (numbytes % groupsize != 0) + // make sure the length was a whole multiple of the group size + if ((numbytes % groupsize) != 0) osd_printf_warning("Warning in RomModule definition: %s length not an even multiple of group size\n", romp->name()); - /* make sure we only fill within the region space */ - if (ROM_GETOFFSET(romp) + numgroups * groupsize + (numgroups - 1) * skip > m_region->bytes()) + // make sure we only fill within the region space + if (ROM_GETOFFSET(romp) + numgroups * groupsize + (numgroups - 1) * skip > region.bytes()) throw emu_fatalerror("Error in RomModule definition: %s out of memory region space\n", romp->name()); - /* make sure the length was valid */ + // make sure the length was valid if (numbytes == 0) throw emu_fatalerror("Error in RomModule definition: %s has an invalid length\n", romp->name()); - /* special case for simple loads */ - if (datamask == 0xff && (groupsize == 1 || !reversed) && skip == 0) + // special case for simple loads + if ((datamask == 0xff) && ((groupsize == 1) || !reversed) && (skip == 0)) return rom_fread(file, base, numbytes, parent_region); - /* use a temporary buffer for complex loads */ - tempbufsize = std::min(TEMPBUFFER_MAX_SIZE, numbytes); - std::vector<u8> tempbuf(tempbufsize); + // use a temporary buffer for complex loads + u32 const tempbufsize(std::min(TEMPBUFFER_MAX_SIZE, numbytes)); + std::unique_ptr<u8 []> const tempbuf(new u8 [tempbufsize]); - /* chunky reads for complex loads */ + // chunky reads for complex loads skip += groupsize; while (numbytes > 0) { - int evengroupcount = (tempbufsize / groupsize) * groupsize; - int bytesleft = (numbytes > evengroupcount) ? evengroupcount : numbytes; - u8 *bufptr = &tempbuf[0]; + int evengroupcount((tempbufsize / groupsize) * groupsize); + int bytesleft((numbytes > evengroupcount) ? evengroupcount : numbytes); + u8 *bufptr(tempbuf.get()); - /* read as much as we can */ + // read as much as we can LOG(" Reading %X bytes into buffer\n", bytesleft); if (rom_fread(file, bufptr, bytesleft, parent_region) != bytesleft) return 0; @@ -767,58 +857,65 @@ int rom_load_manager::read_rom_data(emu_file *file, const rom_entry *parent_regi LOG(" Copying to %p\n", base); - /* unmasked cases */ if (datamask == 0xff) { - /* non-grouped data */ + // unmasked cases if (groupsize == 1) - for (i = 0; i < bytesleft; i++, base += skip) + { + // non-grouped data + for (int i = 0; i < bytesleft; i++, base += skip) *base = *bufptr++; - - /* grouped data -- non-reversed case */ + } else if (!reversed) + { + // grouped data -- non-reversed case while (bytesleft) { - for (i = 0; i < groupsize && bytesleft; i++, bytesleft--) + for (int i = 0; i < groupsize && bytesleft; i++, bytesleft--) base[i] = *bufptr++; base += skip; } - - /* grouped data -- reversed case */ + } else + { + // grouped data -- reversed case while (bytesleft) { - for (i = groupsize - 1; i >= 0 && bytesleft; i--, bytesleft--) + for (int i = groupsize - 1; i >= 0 && bytesleft; i--, bytesleft--) base[i] = *bufptr++; base += skip; } + } } - - /* masked cases */ else { - /* non-grouped data */ + // masked cases if (groupsize == 1) - for (i = 0; i < bytesleft; i++, base += skip) + { + // non-grouped data + for (int i = 0; i < bytesleft; i++, base += skip) *base = (*base & ~datamask) | ((*bufptr++ << datashift) & datamask); - - /* grouped data -- non-reversed case */ + } else if (!reversed) + { + // grouped data -- non-reversed case while (bytesleft) { - for (i = 0; i < groupsize && bytesleft; i++, bytesleft--) + for (int i = 0; i < groupsize && bytesleft; i++, bytesleft--) base[i] = (base[i] & ~datamask) | ((*bufptr++ << datashift) & datamask); base += skip; } - - /* grouped data -- reversed case */ + } else + { + // grouped data -- reversed case while (bytesleft) { - for (i = groupsize - 1; i >= 0 && bytesleft; i--, bytesleft--) + for (int i = groupsize - 1; i >= 0 && bytesleft; i--, bytesleft--) base[i] = (base[i] & ~datamask) | ((*bufptr++ << datashift) & datamask); base += skip; } + } } } @@ -831,14 +928,14 @@ int rom_load_manager::read_rom_data(emu_file *file, const rom_entry *parent_regi fill_rom_data - fill a region of ROM space -------------------------------------------------*/ -void rom_load_manager::fill_rom_data(const rom_entry *romp) +void rom_load_manager::fill_rom_data(memory_region ®ion, const rom_entry *romp) { u32 numbytes = ROM_GETLENGTH(romp); int skip = ROM_GETSKIPCOUNT(romp); - u8 *base = m_region->base() + ROM_GETOFFSET(romp); + u8 *base = region.base() + ROM_GETOFFSET(romp); // make sure we fill within the region space - if (ROM_GETOFFSET(romp) + numbytes > m_region->bytes()) + if (ROM_GETOFFSET(romp) + numbytes > region.bytes()) throw emu_fatalerror("Error in RomModule definition: FILL out of memory region space\n"); // make sure the length was valid @@ -863,15 +960,15 @@ void rom_load_manager::fill_rom_data(const rom_entry *romp) copy_rom_data - copy a region of ROM space -------------------------------------------------*/ -void rom_load_manager::copy_rom_data(const rom_entry *romp) +void rom_load_manager::copy_rom_data(memory_region ®ion, const rom_entry *romp) { - u8 *base = m_region->base() + ROM_GETOFFSET(romp); + u8 *base = region.base() + ROM_GETOFFSET(romp); const std::string &srcrgntag = romp->name(); u32 numbytes = ROM_GETLENGTH(romp); u32 srcoffs = u32(strtol(romp->hashdata().c_str(), nullptr, 0)); /* srcoffset in place of hashdata */ /* make sure we copy within the region space */ - if (ROM_GETOFFSET(romp) + numbytes > m_region->bytes()) + if (ROM_GETOFFSET(romp) + numbytes > region.bytes()) throw emu_fatalerror("Error in RomModule definition: COPY out of target memory region space\n"); /* make sure the length was valid */ @@ -879,16 +976,16 @@ void rom_load_manager::copy_rom_data(const rom_entry *romp) throw emu_fatalerror("Error in RomModule definition: COPY has an invalid length\n"); /* make sure the source was valid */ - memory_region *region = machine().root_device().memregion(srcrgntag); - if (region == nullptr) + memory_region *src = machine().root_device().memregion(srcrgntag); + if (!src) throw emu_fatalerror("Error in RomModule definition: COPY from an invalid region\n"); /* make sure we find within the region space */ - if (srcoffs + numbytes > region->bytes()) + if (srcoffs + numbytes > src->bytes()) throw emu_fatalerror("Error in RomModule definition: COPY out of source memory region space\n"); /* fill the data */ - memcpy(base, region->base() + srcoffs, numbytes); + memcpy(base, src->base() + srcoffs, numbytes); } @@ -897,7 +994,13 @@ void rom_load_manager::copy_rom_data(const rom_entry *romp) for a region -------------------------------------------------*/ -void rom_load_manager::process_rom_entries(std::initializer_list<std::reference_wrapper<const std::vector<std::string> > > searchpath, u8 bios, const rom_entry *parent_region, const rom_entry *romp, bool from_list) +void rom_load_manager::process_rom_entries( + const std::vector<std::string> &searchpath, + u8 bios, + memory_region ®ion, + const rom_entry *parent_region, + const rom_entry *romp, + bool from_list) { u32 lastflags = 0; std::vector<std::string> tried_file_names; @@ -919,13 +1022,13 @@ void rom_load_manager::process_rom_entries(std::initializer_list<std::reference_ if (ROMENTRY_ISFILL(romp)) { if (!ROM_GETBIOSFLAGS(romp) || (ROM_GETBIOSFLAGS(romp) == bios)) - fill_rom_data(romp); + fill_rom_data(region, romp); romp++; } else if (ROMENTRY_ISCOPY(romp)) { - copy_rom_data(romp++); + copy_rom_data(region, romp++); } else if (ROMENTRY_ISFILE(romp)) { @@ -963,7 +1066,7 @@ void rom_load_manager::process_rom_entries(std::initializer_list<std::reference_ // attempt to read using the modified entry if (!ROMENTRY_ISIGNORE(&modified_romp) && !irrelevantbios) - /*readresult = */read_rom_data(file.get(), parent_region, &modified_romp); + /*readresult = */read_rom_data(file.get(), region, parent_region, &modified_romp); } while (ROMENTRY_ISCONTINUE(romp) || ROMENTRY_ISIGNORE(romp)); @@ -1002,7 +1105,11 @@ void rom_load_manager::process_rom_entries(std::initializer_list<std::reference_ open_disk_diff - open a DISK diff file -------------------------------------------------*/ -std::error_condition rom_load_manager::open_disk_diff(emu_options &options, const rom_entry *romp, chd_file &source, chd_file &diff_chd) +std::error_condition rom_load_manager::open_disk_diff( + emu_options &options, + const rom_entry *romp, + chd_file &source, + chd_file &diff_chd) { // TODO: use system name and/or software list name in the path - the current setup doesn't scale std::string fname = romp->name() + ".dif"; @@ -1048,28 +1155,38 @@ std::error_condition rom_load_manager::open_disk_diff(emu_options &options, cons for a region -------------------------------------------------*/ -void rom_load_manager::process_disk_entries(std::initializer_list<std::reference_wrapper<const std::vector<std::string> > > searchpath, std::string_view regiontag, const rom_entry *romp, std::function<const rom_entry * ()> next_parent) +void rom_load_manager::process_disk_entries( + search_paths searchpath, + std::string_view regiontag, + rom_entry const *romp, + std::function<rom_entry const * ()> next_parent, + chd_file::open_parent_func const &open_parent) { - /* remove existing disk entries for this region */ - m_chd_list.erase(std::remove_if(m_chd_list.begin(), m_chd_list.end(), - [regiontag] (std::unique_ptr<open_chd> &chd) { return chd->region() == regiontag; }), m_chd_list.end()); + // remove existing disk entries for this region + m_chd_list.erase( + std::remove_if( + m_chd_list.begin(), + m_chd_list.end(), + [®iontag] (std::unique_ptr<open_chd> &chd) { return chd->region() == regiontag; }), + m_chd_list.end()); - /* loop until we hit the end of this region */ + // loop until we hit the end of this region for ( ; !ROMENTRY_ISREGIONEND(romp); romp++) { - /* handle files */ + // handle files if (ROMENTRY_ISFILE(romp)) { - auto chd = std::make_unique<open_chd>(regiontag); + auto chd(std::make_unique<open_chd>(regiontag)); std::error_condition err; - /* make the filename of the source */ - const std::string filename = romp->name() + ".chd"; + // make the filename of the source + std::string const filename(romp->name() + ".chd"); - /* first open the source drive */ - // FIXME: we've lost the ability to search parents here + // first open the reference disk image LOG("Opening disk image: %s\n", filename.c_str()); - err = do_open_disk(machine().options(), searchpath, romp, chd->orig_chd(), next_parent); + err = do_open_disk(machine().options(), searchpath, romp, chd->orig_chd(), next_parent, open_parent); + if (!err && chd->orig_chd().parent_missing()) + err = chd_file::error::REQUIRES_PARENT; if (err) { std::vector<std::string> tried; @@ -1079,16 +1196,14 @@ void rom_load_manager::process_disk_entries(std::initializer_list<std::reference tried.emplace_back(path); } handle_missing_file(romp, tried, err); - chd = nullptr; + chd.reset(); continue; } - /* get the header and extract the SHA1 */ + // get the header and verify the SHA1 digest util::hash_collection acthashes; acthashes.add_sha1(chd->orig_chd().sha1()); - - /* verify the hash */ - const util::hash_collection hashes(romp->hashdata()); + util::hash_collection const hashes(romp->hashdata()); if (hashes != acthashes) { m_errorstring.append(string_format("%s WRONG CHECKSUMS:\n", filename)); @@ -1101,23 +1216,22 @@ void rom_load_manager::process_disk_entries(std::initializer_list<std::reference m_knownbad++; } - /* if not read-only, make the diff file */ + // if not read-only, open or create the diff file if (!DISK_ISREADONLY(romp)) { - /* try to open or create the diff */ err = open_disk_diff(machine().options(), romp, chd->orig_chd(), chd->diff_chd()); if (err) { m_errorstring.append(string_format("%s DIFF CHD ERROR: %s\n", filename, err.message())); m_errors++; - chd = nullptr; + chd.reset(); continue; } } - /* we're okay, add to the list of disks */ + // we're okay, add to the list of disks LOG("Assigning to handle %d\n", DISK_GETINDEX(romp)); - m_chd_list.push_back(std::move(chd)); + m_chd_list.emplace_back(std::move(chd)); } } } @@ -1140,7 +1254,11 @@ std::vector<std::string> rom_load_manager::get_software_searchpath(software_list device -------------------------------------------------*/ -std::error_condition rom_load_manager::open_disk_image(const emu_options &options, const device_t &device, const rom_entry *romp, chd_file &image_chd) +std::error_condition rom_load_manager::open_disk_image( + emu_options &options, + const device_t &device, + const rom_entry *romp, + chd_file &image_chd) { const std::vector<std::string> searchpath(device.searchpath()); @@ -1149,8 +1267,14 @@ std::error_condition rom_load_manager::open_disk_image(const emu_options &option if (driver) next_parent = next_parent_system(driver->system()); else - next_parent = [] () { return nullptr; }; - return do_open_disk(options, { searchpath }, romp, image_chd, std::move(next_parent)); + next_parent = next_parent_device(device, options); + chd_file::open_parent_func open_parent(open_parent_disk(options, { searchpath }, next_parent)); + std::error_condition const err( + do_open_disk(options, { searchpath }, romp, image_chd, std::move(next_parent), open_parent)); + if (!err && image_chd.parent_missing()) + return chd_file::error::REQUIRES_PARENT; + else + return err; } @@ -1159,12 +1283,24 @@ std::error_condition rom_load_manager::open_disk_image(const emu_options &option software item -------------------------------------------------*/ -std::error_condition rom_load_manager::open_disk_image(const emu_options &options, software_list_device &swlist, const software_info &swinfo, const rom_entry *romp, chd_file &image_chd) +std::error_condition rom_load_manager::open_disk_image( + emu_options &options, + software_list_device &swlist, + const software_info &swinfo, + const rom_entry *romp, + chd_file &image_chd) { std::vector<software_info const *> parents; - std::vector<std::string> searchpath = make_software_searchpath(swlist, swinfo, parents); + std::vector<std::string> searchpath(make_software_searchpath(swlist, swinfo, parents)); searchpath.emplace_back(swlist.list_name()); // look for loose disk images in software list directory - return do_open_disk(options, { searchpath }, romp, image_chd, next_parent_software(parents)); + std::function<const rom_entry * ()> next_parent(next_parent_software(parents)); + chd_file::open_parent_func open_parent(open_parent_disk(options, { searchpath }, next_parent)); + std::error_condition const err( + do_open_disk(options, { searchpath }, romp, image_chd, std::move(next_parent), open_parent)); + if (!err && image_chd.parent_missing()) + return chd_file::error::REQUIRES_PARENT; + else + return err; } @@ -1224,7 +1360,7 @@ void rom_load_manager::load_software_part_region(device_t &device, software_list m_romsloadedsize = 0; std::vector<const software_info *> parents; - std::vector<std::string> swsearch, disksearch, devsearch; + std::vector<std::string> swsearch, disksearch; const software_info *const swinfo = swlist.find(std::string(swname)); if (swinfo) { @@ -1253,13 +1389,9 @@ void rom_load_manager::load_software_part_region(device_t &device, software_list // this is convenient for CD-only lists so you don't need an extra level of directories containing one file each disksearch.emplace_back(swlist.list_name()); - // for historical reasons, add the search path for the software list device's owner - const device_t *const listowner = swlist.owner(); - if (listowner) - devsearch = listowner->searchpath(); - // loop until we hit the end std::function<const rom_entry * ()> next_parent; + chd_file::open_parent_func open_parent; for (const rom_entry *region = start_region; region != nullptr; region = rom_next_region(region)) { u32 regionlength = ROMREGION_GETLENGTH(region); @@ -1274,7 +1406,7 @@ void rom_load_manager::load_software_part_region(device_t &device, software_list endianness_t endianness = ROMREGION_ISBIGENDIAN(region) ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; u8 width = ROMREGION_GETWIDTH(region) / 8; memory_region *memregion = machine().root_device().memregion(regiontag); - if (memregion != nullptr) + if (memregion) { normalize_flags_for_device(regiontag, width, endianness); @@ -1283,16 +1415,16 @@ void rom_load_manager::load_software_part_region(device_t &device, software_list } // remember the base and length - m_region = machine().memory().region_alloc(regiontag, regionlength, width, endianness); - LOG("Allocated %X bytes @ %p\n", m_region->bytes(), m_region->base()); + memregion = machine().memory().region_alloc(regiontag, regionlength, width, endianness); + LOG("Allocated %X bytes @ %p\n", memregion->bytes(), memregion->base()); if (ROMREGION_ISERASE(region)) // clear the region if it's requested - memset(m_region->base(), ROMREGION_GETERASEVAL(region), m_region->bytes()); - else if (m_region->bytes() <= 0x400000) // or if it's sufficiently small (<= 4MB) - memset(m_region->base(), 0, m_region->bytes()); + memset(memregion->base(), ROMREGION_GETERASEVAL(region), memregion->bytes()); + else if (memregion->bytes() <= 0x400000) // or if it's sufficiently small (<= 4MB) + memset(memregion->base(), 0, memregion->bytes()); #ifdef MAME_DEBUG else // if we're debugging, fill region with random data to catch errors - fill_random(m_region->base(), m_region->bytes()); + fill_random(memregion->base(), memregion->bytes()); #endif // update total number of roms @@ -1305,10 +1437,7 @@ void rom_load_manager::load_software_part_region(device_t &device, software_list // now process the entries in the region if (ROMREGION_ISROMDATA(region)) { - if (devsearch.empty()) - process_rom_entries({ swsearch }, 0U, region, region + 1, true); - else - process_rom_entries({ swsearch, devsearch }, 0U, region, region + 1, true); + process_rom_entries(swsearch, 0U, *memregion, region, region + 1, true); } else if (ROMREGION_ISDISKDATA(region)) { @@ -1318,11 +1447,9 @@ void rom_load_manager::load_software_part_region(device_t &device, software_list next_parent = next_parent_software(parents); else next_parent = [] () { return nullptr; }; + open_parent = open_parent_disk(machine().options(), { swsearch, disksearch }, next_parent); } - if (devsearch.empty()) - process_disk_entries({ swsearch, disksearch }, regiontag, region + 1, next_parent); - else - process_disk_entries({ swsearch, disksearch, devsearch }, regiontag, region + 1, next_parent); + process_disk_entries({ swsearch, disksearch }, regiontag, region + 1, next_parent, open_parent); } } @@ -1348,6 +1475,7 @@ void rom_load_manager::process_region_list() { searchpath.clear(); std::function<const rom_entry * ()> next_parent; + chd_file::open_parent_func open_parent; for (const rom_entry *region = rom_first_region(device); region != nullptr; region = rom_next_region(region)) { u32 regionlength = ROMREGION_GETLENGTH(region); @@ -1366,23 +1494,23 @@ void rom_load_manager::process_region_list() normalize_flags_for_device(regiontag, width, endianness); // remember the base and length - m_region = machine().memory().region_alloc(regiontag, regionlength, width, endianness); - LOG("Allocated %X bytes @ %p\n", m_region->bytes(), m_region->base()); + memory_region *const memregion = machine().memory().region_alloc(regiontag, regionlength, width, endianness); + LOG("Allocated %X bytes @ %p\n", memregion->bytes(), memregion->base()); if (ROMREGION_ISERASE(region)) // clear the region if it's requested - memset(m_region->base(), ROMREGION_GETERASEVAL(region), m_region->bytes()); - else if (m_region->bytes() <= 0x400000) // or if it's sufficiently small (<= 4MB) - memset(m_region->base(), 0, m_region->bytes()); + memset(memregion->base(), ROMREGION_GETERASEVAL(region), memregion->bytes()); + else if (memregion->bytes() <= 0x400000) // or if it's sufficiently small (<= 4MB) + memset(memregion->base(), 0, memregion->bytes()); #ifdef MAME_DEBUG else // if we're debugging, fill region with random data to catch errors - fill_random(m_region->base(), m_region->bytes()); + fill_random(memregion->base(), memregion->bytes()); #endif // now process the entries in the region if (searchpath.empty()) searchpath = device.searchpath(); assert(!searchpath.empty()); - process_rom_entries({ searchpath }, device.system_bios(), region, region + 1, false); + process_rom_entries(searchpath, device.system_bios(), *memregion, region, region + 1, false); } else if (ROMREGION_ISDISKDATA(region)) { @@ -1395,9 +1523,10 @@ void rom_load_manager::process_region_list() if (driver) next_parent = next_parent_system(driver->system()); else - next_parent = [] () { return nullptr; }; + next_parent = next_parent_device(device, machine().options()); + open_parent = open_parent_disk(machine().options(), { searchpath }, next_parent); } - process_disk_entries({ searchpath }, regiontag, region + 1, next_parent); + process_disk_entries({ searchpath }, regiontag, region + 1, next_parent, open_parent); } } } @@ -1434,7 +1563,6 @@ rom_load_manager::rom_load_manager(running_machine &machine) , m_romsloadedsize(0) , m_romstotalsize(0) , m_chd_list() - , m_region(nullptr) , m_errorstring() , m_softwarningstring() { @@ -1467,7 +1595,7 @@ rom_load_manager::rom_load_manager(running_machine &machine) card_bios.erase(found); } } - determine_bios_rom(device, specbios.c_str()); + determine_bios_rom(device, specbios); } } diff --git a/src/emu/romload.h b/src/emu/romload.h index 76fdb111cc6..4ad0303a9f6 100644 --- a/src/emu/romload.h +++ b/src/emu/romload.h @@ -17,7 +17,9 @@ #include <functional> #include <initializer_list> +#include <memory> #include <string> +#include <string_view> #include <system_error> #include <type_traits> #include <vector> @@ -102,11 +104,11 @@ protected: const_entry_iterator &operator=(const_entry_iterator &&) noexcept = default; public: - typedef T value_type; - typedef value_type const *pointer; - typedef value_type const &reference; - typedef std::ptrdiff_t difference_type; - typedef std::forward_iterator_tag iterator_category; + using value_type = T; + using pointer = value_type const *; + using reference = value_type const &; + using difference_type = std::ptrdiff_t; + using iterator_category = std::forward_iterator_tag; reference operator*() const noexcept { return reinterpret_cast<reference>(*m_data); } pointer operator->() const noexcept { return reinterpret_cast<pointer>(m_data); } @@ -387,6 +389,7 @@ class rom_load_manager { public: open_chd(std::string_view region) : m_region(region) { } + open_chd(std::string &®ion) : m_region(std::move(region)) { } std::string_view region() const { return m_region; } chd_file &chd() { return m_diffchd.opened() ? m_diffchd : m_origchd; } @@ -394,9 +397,9 @@ class rom_load_manager chd_file &diff_chd() { return m_diffchd; } private: - std::string m_region; /* disk region we came from */ - chd_file m_origchd; /* handle to the original CHD */ - chd_file m_diffchd; /* handle to the diff CHD */ + std::string m_region; // disk region we came from + chd_file m_origchd; // handle to the original CHD + chd_file m_diffchd; // handle to the diff CHD }; public: @@ -420,7 +423,7 @@ public: chd_file *get_disk_handle(std::string_view region); /* set a pointer to the CHD file associated with the given region */ - std::error_condition set_disk_handle(std::string_view region, const char *fullpath); + std::error_condition set_disk_handle(std::string_view region, std::string_view fullpath); void load_software_part_region(device_t &device, software_list_device &swlist, std::string_view swname, const rom_entry *start_region); @@ -428,11 +431,13 @@ public: static std::vector<std::string> get_software_searchpath(software_list_device &swlist, const software_info &swinfo); /* open a disk image, searching up the parent and loading by checksum */ - static std::error_condition open_disk_image(const emu_options &options, const device_t &device, const rom_entry *romp, chd_file &image_chd); - static std::error_condition open_disk_image(const emu_options &options, software_list_device &swlist, const software_info &swinfo, const rom_entry *romp, chd_file &image_chd); + static std::error_condition open_disk_image(emu_options &options, const device_t &device, const rom_entry *romp, chd_file &image_chd); + static std::error_condition open_disk_image(emu_options &options, software_list_device &swlist, const software_info &swinfo, const rom_entry *romp, chd_file &image_chd); private: - void determine_bios_rom(device_t &device, const char *specbios); + using search_paths = std::initializer_list<std::reference_wrapper<const std::vector<std::string> > >; + + void determine_bios_rom(device_t &device, std::string_view specbios); void count_roms(); void fill_random(u8 *base, u32 length); void handle_missing_file(const rom_entry *romp, const std::vector<std::string> &tried_file_names, std::error_condition chderr); @@ -441,15 +446,40 @@ private: void display_loading_rom_message(const char *name, bool from_list); void display_rom_load_results(bool from_list); void region_post_process(memory_region *region, bool invert); - std::unique_ptr<emu_file> open_rom_file(std::initializer_list<std::reference_wrapper<const std::vector<std::string> > > searchpath, const rom_entry *romp, std::vector<std::string> &tried_file_names, bool from_list); - std::unique_ptr<emu_file> open_rom_file(const std::vector<std::string> &paths, std::vector<std::string> &tried, bool has_crc, u32 crc, std::string_view name, std::error_condition &filerr); + std::unique_ptr<emu_file> open_rom_file( + const std::vector<std::string> &searchpath, + const rom_entry *romp, + std::vector<std::string> &tried_file_names, + bool from_list); + std::unique_ptr<emu_file> open_rom_file( + const std::vector<std::string> &paths, + std::vector<std::string> &tried, + bool has_crc, + u32 crc, + std::string_view name, + std::error_condition &filerr); int rom_fread(emu_file *file, u8 *buffer, int length, const rom_entry *parent_region); - int read_rom_data(emu_file *file, const rom_entry *parent_region, const rom_entry *romp); - void fill_rom_data(const rom_entry *romp); - void copy_rom_data(const rom_entry *romp); - void process_rom_entries(std::initializer_list<std::reference_wrapper<const std::vector<std::string> > > searchpath, u8 bios, const rom_entry *parent_region, const rom_entry *romp, bool from_list); - std::error_condition open_disk_diff(emu_options &options, const rom_entry *romp, chd_file &source, chd_file &diff_chd); - void process_disk_entries(std::initializer_list<std::reference_wrapper<const std::vector<std::string> > > searchpath, std::string_view regiontag, const rom_entry *romp, std::function<const rom_entry * ()> next_parent); + int read_rom_data(emu_file *file, memory_region ®ion, const rom_entry *parent_region, const rom_entry *romp); + void fill_rom_data(memory_region ®ion, const rom_entry *romp); + void copy_rom_data(memory_region ®ion, const rom_entry *romp); + void process_rom_entries( + const std::vector<std::string> &searchpath, + u8 bios, + memory_region ®ion, + const rom_entry *parent_region, + const rom_entry *romp, + bool from_list); + std::error_condition open_disk_diff( + emu_options &options, + const rom_entry *romp, + chd_file &source, + chd_file &diff_chd); + void process_disk_entries( + search_paths searchpath, + std::string_view regiontag, + const rom_entry *romp, + std::function<const rom_entry * ()> next_parent, + const chd_file::open_parent_func &open_parent); void normalize_flags_for_device(std::string_view rgntag, u8 &width, endianness_t &endian); void process_region_list(); @@ -467,8 +497,6 @@ private: std::vector<std::unique_ptr<open_chd>> m_chd_list; /* disks */ - memory_region * m_region; // info about current region - std::string m_errorstring; // error string std::string m_softwarningstring; // software warning string }; diff --git a/src/emu/save.cpp b/src/emu/save.cpp index b8acfa24b0a..8c3329e7b38 100644 --- a/src/emu/save.cpp +++ b/src/emu/save.cpp @@ -25,7 +25,8 @@ #include "emu.h" #include "emuopts.h" -#include "util/coreutil.h" +#include "main.h" + #include "util/ioprocs.h" #include "util/ioprocsfilter.h" @@ -66,7 +67,6 @@ enum save_manager::save_manager(running_machine &machine) : m_machine(machine) , m_reg_allowed(true) - , m_illegal_regs(0) { m_rewind = std::make_unique<rewinder>(*this); } @@ -185,9 +185,7 @@ void save_manager::save_memory(device_t *device, const char *module, const char if (!m_reg_allowed) { machine().logerror("Attempt to register save state entry after state registration is closed!\nModule %s tag %s name %s\n", module, tag, name); - if (machine().system().flags & machine_flags::SUPPORTS_SAVE) - fatalerror("Attempt to register save state entry after state registration is closed!\nModule %s tag %s name %s\n", module, tag, name); - m_illegal_regs++; + fatalerror("Attempt to register save state entry after state registration is closed!\nModule %s tag %s name %s\n", module, tag, name); return; } @@ -217,11 +215,11 @@ save_error save_manager::check_file(running_machine &machine, util::core_file &f // seek to the beginning and read the header file.seek(0, SEEK_SET); u8 header[HEADER_SIZE]; - size_t actual(0); - if (file.read(header, sizeof(header), actual) || actual != sizeof(header)) + auto const [err, actual] = read(file, header, sizeof(header)); + if (err || (actual != sizeof(header))) { if (errormsg != nullptr) - (*errormsg)("Could not read %s save file header",emulator_info::get_appname()); + (*errormsg)("Could not read %s save file header", emulator_info::get_appname()); return STATERR_READ_ERROR; } @@ -265,9 +263,8 @@ save_error save_manager::write_file(util::core_file &file) [] (size_t total_size) { return true; }, [&writer] (const void *data, size_t size) { - size_t written; - std::error_condition filerr = writer->write(data, size, written); - return !filerr && (size == written); + auto const [filerr, written] = write(*writer, data, size); + return !filerr; }, [&file, &writer] () { @@ -298,9 +295,8 @@ save_error save_manager::read_file(util::core_file &file) [] (size_t total_size) { return true; }, [&reader] (void *data, size_t size) { - std::size_t read; - std::error_condition filerr = reader->read(data, size, read); - return !filerr && (read == size); + auto const [filerr, actual] = read(*reader, data, size); + return !filerr && (actual == size); }, [&file, &reader] () { @@ -406,10 +402,6 @@ save_error save_manager::read_buffer(const void *buf, size_t size) template <typename T, typename U, typename V, typename W> inline save_error save_manager::do_write(T check_space, U write_block, V start_header, W start_data) { - // if we have illegal registrations, return an error - if (m_illegal_regs > 0) - return STATERR_ILLEGAL_REGISTRATIONS; - // check for sufficient space size_t total_size = HEADER_SIZE; for (const auto &entry : m_entry_list) @@ -453,10 +445,6 @@ inline save_error save_manager::do_write(T check_space, U write_block, V start_h template <typename T, typename U, typename V, typename W> inline save_error save_manager::do_read(T check_length, U read_block, V start_header, W start_data) { - // if we have illegal registrations, return an error - if (m_illegal_regs > 0) - return STATERR_ILLEGAL_REGISTRATIONS; - // check for sufficient space size_t total_size = HEADER_SIZE; for (const auto &entry : m_entry_list) @@ -506,11 +494,11 @@ inline save_error save_manager::do_read(T check_length, U read_block, V start_he u32 save_manager::signature() const { // iterate over entries - u32 crc = 0; + util::crc32_creator crc; for (auto &entry : m_entry_list) { // add the entry name to the CRC - crc = core_crc32(crc, (u8 *)entry->m_name.c_str(), entry->m_name.length()); + crc.append(entry->m_name.data(), entry->m_name.length()); // add the type and size to the CRC u32 temp[4]; @@ -518,9 +506,9 @@ u32 save_manager::signature() const temp[1] = little_endianize_int32(entry->m_typecount); temp[2] = little_endianize_int32(entry->m_blockcount); temp[3] = little_endianize_int32(entry->m_stride); - crc = core_crc32(crc, (u8 *)&temp[0], sizeof(temp)); + crc.append(&temp[0], sizeof(temp)); } - return crc; + return crc.finish(); } @@ -548,7 +536,7 @@ save_error save_manager::validate_header(const u8 *header, const char *gamename, if (memcmp(header, STATE_MAGIC_NUM, 8)) { if (errormsg != nullptr) - (*errormsg)("%sThis is not a %s save file", error_prefix,emulator_info::get_appname()); + (*errormsg)("%sThis is not a %s save file", error_prefix, emulator_info::get_appname()); return STATERR_INVALID_HEADER; } @@ -661,10 +649,6 @@ save_error ram_state::load() // initialize m_data.seekg(0); - // if we have illegal registrations, return an error - if (m_save.m_illegal_regs > 0) - return STATERR_ILLEGAL_REGISTRATIONS; - // get the save manager to load state return m_save.read_stream(m_data); } @@ -914,11 +898,6 @@ void rewinder::report_error(save_error error, rewind_operation operation) switch (error) { // internal saveload failures - case STATERR_ILLEGAL_REGISTRATIONS: - m_save.machine().logerror("Rewind error: Unable to %s state due to illegal registrations.", opname); - m_save.machine().popmessage("Rewind error occured. See error.log for details."); - break; - case STATERR_INVALID_HEADER: m_save.machine().logerror("Rewind error: Unable to %s state due to an invalid header. " "Make sure the save state is correct for this machine.\n", opname); diff --git a/src/emu/save.h b/src/emu/save.h index 677f127853a..e473f408317 100644 --- a/src/emu/save.h +++ b/src/emu/save.h @@ -34,7 +34,6 @@ enum save_error { STATERR_NONE, STATERR_NOT_FOUND, - STATERR_ILLEGAL_REGISTRATIONS, STATERR_INVALID_HEADER, STATERR_READ_ERROR, STATERR_WRITE_ERROR, @@ -334,7 +333,6 @@ private: running_machine & m_machine; // reference to our machine std::unique_ptr<rewinder> m_rewind; // rewinder bool m_reg_allowed; // are registrations allowed? - s32 m_illegal_regs; // number of illegal registrations std::vector<std::unique_ptr<state_entry>> m_entry_list; // list of registered entries std::vector<std::unique_ptr<ram_state>> m_ramstate_list; // list of ram states diff --git a/src/emu/schedule.cpp b/src/emu/schedule.cpp index 838e70c22b6..acc596d6798 100644 --- a/src/emu/schedule.cpp +++ b/src/emu/schedule.cpp @@ -76,7 +76,7 @@ inline emu_timer &emu_timer::init( running_machine &machine, timer_expired_delegate &&callback, attotime start_delay, - int param, + s32 param, bool temporary) { // ensure the entire timer state is clean @@ -445,7 +445,7 @@ void device_scheduler::timeslice() // if we're not suspended, actually execute if (exec->m_suspend == 0) { - g_profiler.start(exec->m_profiler); + auto profile = g_profiler.start(exec->m_profiler); // note that this global variable cycles_stolen can be modified // via the call to cpu_execute @@ -466,7 +466,6 @@ void device_scheduler::timeslice() ran -= *exec->m_icountptr; assert(ran >= exec->m_cycles_stolen); ran -= exec->m_cycles_stolen; - g_profiler.stop(); } // account for these cycles @@ -614,7 +613,7 @@ emu_timer *device_scheduler::timer_alloc(timer_expired_delegate callback) // amount of time //------------------------------------------------- -void device_scheduler::timer_set(const attotime &duration, timer_expired_delegate callback, int param) +void device_scheduler::timer_set(const attotime &duration, timer_expired_delegate callback, s32 param) { [[maybe_unused]] emu_timer &timer = m_timer_allocator.alloc()->init( machine(), @@ -631,7 +630,7 @@ void device_scheduler::timer_set(const attotime &duration, timer_expired_delegat // timer and set it to go off as soon as possible //------------------------------------------------- -void device_scheduler::synchronize(timer_expired_delegate callback, int param) +void device_scheduler::synchronize(timer_expired_delegate callback, s32 param) { m_timer_allocator.alloc()->init( machine(), @@ -704,6 +703,7 @@ void device_scheduler::postload() assert(!timer.expire().is_never()); // temporary timers go away entirely (except our special never-expiring one) + timer.m_callback.reset(); m_timer_allocator.reclaim(timer_list_remove(timer)); } else @@ -943,15 +943,13 @@ inline void device_scheduler::execute_timers() // call the callback if (was_enabled) { - g_profiler.start(PROFILER_TIMER_CALLBACK); + auto profile = g_profiler.start(PROFILER_TIMER_CALLBACK); if (!timer.m_callback.isnull()) { LOG("execute_timers: timer callback %s\n", timer.m_callback.name()); timer.m_callback(timer.m_param); } - - g_profiler.stop(); } // reset or remove the timer, but only if it wasn't modified during the callback @@ -965,6 +963,7 @@ inline void device_scheduler::execute_timers() else { // otherwise, remove it now + timer.m_callback.reset(); m_timer_allocator.reclaim(timer_list_remove(timer)); } } diff --git a/src/emu/schedule.h b/src/emu/schedule.h index 338560594d9..e13fc18d573 100644 --- a/src/emu/schedule.h +++ b/src/emu/schedule.h @@ -39,11 +39,11 @@ class emu_timer public: // getters bool enabled() const noexcept { return m_enabled; } - int param() const noexcept { return m_param; } + s32 param() const noexcept { return m_param; } // setters bool enable(bool enable = true) noexcept; - void set_param(int param) noexcept { m_param = param; } + void set_param(s32 param) noexcept { m_param = param; } // control void reset(const attotime &duration = attotime::never) noexcept { adjust(duration, m_param, m_period); } @@ -66,7 +66,7 @@ private: running_machine &machine, timer_expired_delegate &&callback, attotime start_delay, - int param, + s32 param, bool temporary); // internal helpers @@ -121,9 +121,9 @@ public: // timers, specified by callback/name emu_timer *timer_alloc(timer_expired_delegate callback); - [[deprecated("timer_set is deprecated; please avoid anonymous timers. Use TIMER_CALLBACK_MEMBER and an allocated emu_timer instead.")]] - void timer_set(const attotime &duration, timer_expired_delegate callback, int param = 0); - void synchronize(timer_expired_delegate callback = timer_expired_delegate(), int param = 0); + [[deprecated("timer_set is deprecated; please avoid anonymous timers. Use an allocated emu_timer instead.")]] + void timer_set(const attotime &duration, timer_expired_delegate callback, s32 param = 0); + void synchronize(timer_expired_delegate callback = timer_expired_delegate(), s32 param = 0); // debugging void dump_timers() const; diff --git a/src/emu/screen.cpp b/src/emu/screen.cpp index f69a03ac13e..cf311fb21eb 100644 --- a/src/emu/screen.cpp +++ b/src/emu/screen.cpp @@ -13,6 +13,7 @@ #include "emuopts.h" #include "fileio.h" +#include "main.h" #include "render.h" #include "rendutil.h" @@ -771,8 +772,6 @@ void screen_device::device_resolve_objects() // bind our handlers m_screen_update_ind16.resolve(); m_screen_update_rgb32.resolve(); - m_screen_vblank.resolve_safe(); - m_scanline_cb.resolve(); // assign our format to the palette before it starts if (m_palette) @@ -842,7 +841,7 @@ void screen_device::device_start() m_scanline0_timer = timer_alloc(FUNC(screen_device::first_scanline_tick), this); // allocate a timer to generate per-scanline updates - if ((m_video_attributes & VIDEO_UPDATE_SCANLINE) != 0 || m_scanline_cb) + if ((m_video_attributes & VIDEO_UPDATE_SCANLINE) != 0 || !m_scanline_cb.isunset()) m_scanline_timer = timer_alloc(FUNC(screen_device::scanline_tick), this); // configure the screen with the default parameters @@ -853,7 +852,7 @@ void screen_device::device_start() m_vblank_end_time = attotime(0, m_vblank_period); // start the timer to generate per-scanline updates - if ((m_video_attributes & VIDEO_UPDATE_SCANLINE) != 0 || m_scanline_cb) + if ((m_video_attributes & VIDEO_UPDATE_SCANLINE) != 0 || !m_scanline_cb.isunset()) m_scanline_timer->adjust(time_until_pos(0)); // create burn-in bitmap @@ -888,7 +887,7 @@ void screen_device::device_start() save_item(NAME(m_vblank_end_time)); save_item(NAME(m_frame_number)); if (m_oldstyle_vblank_supplied) - logerror("%s: Deprecated legacy Old Style screen configured (MCFG_SCREEN_VBLANK_TIME), please use MCFG_SCREEN_RAW_PARAMS instead.\n",this->tag()); + logerror("%s: Deprecated legacy Old Style screen configured (set_vblank_time), please use set_raw instead.\n",this->tag()); m_is_primary_screen = (this == screen_device_enumerator(machine().root_device()).first()); } @@ -956,7 +955,7 @@ TIMER_CALLBACK_MEMBER(screen_device::scanline_tick) // force a partial update to the current scanline update_partial(param); } - if (m_scanline_cb) + if (!m_scanline_cb.isunset()) m_scanline_cb(param); // compute the next visible scanline @@ -1182,49 +1181,50 @@ bool screen_device::update_partial(int scanline) // otherwise, render LOG_PARTIAL_UPDATES(("updating %d-%d\n", clip.top(), clip.bottom())); - g_profiler.start(PROFILER_VIDEO); u32 flags = 0; - if (m_video_attributes & VIDEO_VARIABLE_WIDTH) { - rectangle scan_clip(clip); - for (int y = clip.top(); y <= clip.bottom(); y++) + auto profile = g_profiler.start(PROFILER_VIDEO); + if (m_video_attributes & VIDEO_VARIABLE_WIDTH) { - scan_clip.sety(y, y); - pre_update_scanline(y); - - screen_bitmap &curbitmap = m_bitmap[m_curbitmap]; - switch (curbitmap.format()) + rectangle scan_clip(clip); + for (int y = clip.top(); y <= clip.bottom(); y++) { - default: - case BITMAP_FORMAT_IND16: flags |= m_screen_update_ind16(*this, *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][y], scan_clip); break; - case BITMAP_FORMAT_RGB32: flags |= m_screen_update_rgb32(*this, *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][y], scan_clip); break; - } + scan_clip.sety(y, y); + pre_update_scanline(y); - m_partial_updates_this_frame++; - } - } - else - { - if (m_type != SCREEN_TYPE_SVG) - { - screen_bitmap &curbitmap = m_bitmap[m_curbitmap]; - switch (curbitmap.format()) - { - default: - case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, curbitmap.as_ind16(), clip); break; - case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, curbitmap.as_rgb32(), clip); break; + screen_bitmap &curbitmap = m_bitmap[m_curbitmap]; + switch (curbitmap.format()) + { + default: + case BITMAP_FORMAT_IND16: flags |= m_screen_update_ind16(*this, *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][y], scan_clip); break; + case BITMAP_FORMAT_RGB32: flags |= m_screen_update_rgb32(*this, *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][y], scan_clip); break; + } + + m_partial_updates_this_frame++; } } else { - flags = m_svg->render(*this, m_bitmap[m_curbitmap].as_rgb32(), clip); + if (m_type != SCREEN_TYPE_SVG) + { + screen_bitmap &curbitmap = m_bitmap[m_curbitmap]; + switch (curbitmap.format()) + { + default: + case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, curbitmap.as_ind16(), clip); break; + case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, curbitmap.as_rgb32(), clip); break; + } + } + else + { + flags = m_svg->render(*this, m_bitmap[m_curbitmap].as_rgb32(), clip); + } + m_partial_updates_this_frame++; } - m_partial_updates_this_frame++; + // stop profiling } - g_profiler.stop(); - // if we modified the bitmap, we have to commit m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED; @@ -1295,7 +1295,7 @@ void screen_device::update_now() // if there's something to draw, do it if (!clip.empty()) { - g_profiler.start(PROFILER_VIDEO); + auto profile = g_profiler.start(PROFILER_VIDEO); u32 flags = 0; screen_bitmap &curbitmap = m_bitmap[m_curbitmap]; @@ -1319,7 +1319,6 @@ void screen_device::update_now() } } - g_profiler.stop(); m_partial_updates_this_frame++; // if we modified the bitmap, we have to commit @@ -1348,7 +1347,7 @@ void screen_device::update_now() // and if there's something to draw, do it if (!clip.empty()) { - g_profiler.start(PROFILER_VIDEO); + auto profile = g_profiler.start(PROFILER_VIDEO); LOG_PARTIAL_UPDATES(("doing scanline partial draw: Y %d X %d-%d\n", clip.bottom(), clip.left(), clip.right())); @@ -1375,7 +1374,6 @@ void screen_device::update_now() } m_partial_updates_this_frame++; - g_profiler.stop(); // if we modified the bitmap, we have to commit m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED; diff --git a/src/emu/screen.h b/src/emu/screen.h index 685d4c913a9..a2d9e7f7f2e 100644 --- a/src/emu/screen.h +++ b/src/emu/screen.h @@ -385,8 +385,8 @@ public: // beam positioning and state int vpos() const; int hpos() const; - DECLARE_READ_LINE_MEMBER(vblank) const { return (machine().time() < m_vblank_end_time) ? 1 : 0; } - DECLARE_READ_LINE_MEMBER(hblank) const { int const curpos = hpos(); return (curpos < m_visarea.left() || curpos > m_visarea.right()) ? 1 : 0; } + int vblank() const { return (machine().time() < m_vblank_end_time) ? 1 : 0; } + int hblank() const { int const curpos = hpos(); return (curpos < m_visarea.left() || curpos > m_visarea.right()) ? 1 : 0; } // timing attotime time_until_pos(int vpos, int hpos = 0) const; diff --git a/src/emu/softlist.cpp b/src/emu/softlist.cpp index 4892a5ca5d8..c6bb7161be3 100644 --- a/src/emu/softlist.cpp +++ b/src/emu/softlist.cpp @@ -286,8 +286,7 @@ softlist_parser::softlist_parser( char buffer[1024]; for (bool done = false; !done; ) { - size_t length; - file.read(buffer, sizeof(buffer), length); // TODO: better error handling + auto const [err, length] = read(file, buffer, sizeof(buffer)); // TODO: better error handling if (!length) done = true; if (XML_Parse(m_parser, buffer, length, done) == XML_STATUS_ERROR) diff --git a/src/emu/softlist_dev.cpp b/src/emu/softlist_dev.cpp index 07ece5ec42f..b65f5f28300 100644 --- a/src/emu/softlist_dev.cpp +++ b/src/emu/softlist_dev.cpp @@ -50,9 +50,9 @@ image_software_list_loader image_software_list_loader::s_instance; // false_software_list_loader::load_software //------------------------------------------------- -bool false_software_list_loader::load_software(device_image_interface &image, software_list_device &swlist, std::string_view swname, const rom_entry *start_entry) const +std::error_condition false_software_list_loader::load_software(device_image_interface &image, software_list_device &swlist, std::string_view swname, const rom_entry *start_entry) const { - return false; + return image_error::UNSUPPORTED; } @@ -60,10 +60,10 @@ bool false_software_list_loader::load_software(device_image_interface &image, so // rom_software_list_loader::load_software //------------------------------------------------- -bool rom_software_list_loader::load_software(device_image_interface &image, software_list_device &swlist, std::string_view swname, const rom_entry *start_entry) const +std::error_condition rom_software_list_loader::load_software(device_image_interface &image, software_list_device &swlist, std::string_view swname, const rom_entry *start_entry) const { swlist.machine().rom_load().load_software_part_region(image.device(), swlist, swname, start_entry); - return true; + return std::error_condition(); } @@ -71,7 +71,7 @@ bool rom_software_list_loader::load_software(device_image_interface &image, soft // image_software_list_loader::load_software //------------------------------------------------- -bool image_software_list_loader::load_software(device_image_interface &image, software_list_device &swlist, std::string_view swname, const rom_entry *start_entry) const +std::error_condition image_software_list_loader::load_software(device_image_interface &image, software_list_device &swlist, std::string_view swname, const rom_entry *start_entry) const { return image.load_software(swlist, swname, start_entry); } @@ -250,7 +250,7 @@ void software_list_device::display_matches(const machine_config &config, const c // from an intermediate point //------------------------------------------------- -const software_info *software_list_device::find(const std::string &look_for) +const software_info *software_list_device::find(std::string_view look_for) { // empty search returns nothing if (look_for.empty()) @@ -265,8 +265,8 @@ const software_info *software_list_device::find(const std::string &look_for) info_list.end(), [&look_for, iswild] (const software_info &info) { - const char *shortname = info.shortname().c_str(); - return (iswild && core_strwildcmp(look_for.c_str(), shortname) == 0) + std::string_view shortname = info.shortname(); + return (iswild && core_strwildcmp(look_for, shortname) == 0) || util::streqlower(look_for, shortname); }); @@ -454,6 +454,9 @@ void software_list_device::internal_validity_check(validity_checker &valid) if (m_shortname.length() > NAME_LEN_LIST) osd_printf_error("%s: %s software list name must be %d characters or less\n", m_filename, m_shortname, NAME_LEN_LIST); + + if (std::find_if_not(m_shortname.begin(), m_shortname.end(), valid_name_char) != m_shortname.end()) + osd_printf_error("%s: %s software list name contains invalid characters\n", m_filename, m_shortname); } // now check the software items @@ -573,6 +576,8 @@ void software_list_device::internal_validity_check(validity_checker &valid) current_length = ROMREGION_GETLENGTH(romp); if (!data_area_map.emplace(romp->name(), current_length).second) osd_printf_error("%s: %s part %s data area has duplicate name '%s'\n", m_filename, shortname, part.name(), romp->name()); + if (current_length == 0) + osd_printf_error("%s: %s part %s data area '%s' has zero length\n", m_filename, shortname, part.name(), romp->name()); } else if (ROMENTRY_ISFILE(romp)) // if this is a file, make sure it is properly formatted { diff --git a/src/emu/softlist_dev.h b/src/emu/softlist_dev.h index e0e912a67f1..772bb970c99 100644 --- a/src/emu/softlist_dev.h +++ b/src/emu/softlist_dev.h @@ -43,7 +43,7 @@ enum software_compatibility class software_list_loader { public: - virtual bool load_software(device_image_interface &image, software_list_device &swlist, std::string_view swname, const rom_entry *start_entry) const = 0; + virtual std::error_condition load_software(device_image_interface &image, software_list_device &swlist, std::string_view swname, const rom_entry *start_entry) const = 0; }; @@ -52,7 +52,7 @@ public: class false_software_list_loader : public software_list_loader { public: - virtual bool load_software(device_image_interface &image, software_list_device &swlist, std::string_view swname, const rom_entry *start_entry) const override; + virtual std::error_condition load_software(device_image_interface &image, software_list_device &swlist, std::string_view swname, const rom_entry *start_entry) const override; static const software_list_loader &instance() { return s_instance; } private: @@ -65,7 +65,7 @@ private: class rom_software_list_loader : public software_list_loader { public: - virtual bool load_software(device_image_interface &image, software_list_device &swlist, std::string_view swname, const rom_entry *start_entry) const override; + virtual std::error_condition load_software(device_image_interface &image, software_list_device &swlist, std::string_view swname, const rom_entry *start_entry) const override; static const software_list_loader &instance() { return s_instance; } private: @@ -78,7 +78,7 @@ private: class image_software_list_loader : public software_list_loader { public: - virtual bool load_software(device_image_interface &image, software_list_device &swlist, std::string_view swname, const rom_entry *start_entry) const override; + virtual std::error_condition load_software(device_image_interface &image, software_list_device &swlist, std::string_view swname, const rom_entry *start_entry) const override; static const software_list_loader &instance() { return s_instance; } private: @@ -121,7 +121,7 @@ public: const std::list<software_info> &get_info() { if (!m_parsed) parse(); return m_infolist; } // operations - const software_info *find(const std::string &look_for); + const software_info *find(std::string_view look_for); void find_approx_matches(std::string_view name, int matches, const software_info **list, const char *interface); void release(); software_compatibility is_compatible(const software_part &part) const; diff --git a/src/emu/sound.cpp b/src/emu/sound.cpp index 1fb401f0ef1..c9626855197 100644 --- a/src/emu/sound.cpp +++ b/src/emu/sound.cpp @@ -12,6 +12,7 @@ #include "config.h" #include "emuopts.h" +#include "main.h" #include "speaker.h" #include "wavwrite.h" @@ -32,13 +33,6 @@ #define LOG_OUTPUT_WAV (0) - -//************************************************************************** -// CONSTANTS -//************************************************************************** - - - //************************************************************************** // GLOBAL VARIABLES //************************************************************************** @@ -46,7 +40,6 @@ const attotime sound_manager::STREAMS_UPDATE_ATTOTIME = attotime::from_hz(STREAMS_UPDATE_FREQUENCY); - //************************************************************************** // STREAM BUFFER //************************************************************************** @@ -711,7 +704,7 @@ read_stream_view sound_stream::update_view(attotime start, attotime end, u32 out if (start > end) start = end; - g_profiler.start(PROFILER_SOUND); + auto profile = g_profiler.start(PROFILER_SOUND); // reposition our start to coincide with the current buffer end attotime update_start = m_output[outputnum].end_time(); @@ -759,7 +752,6 @@ read_stream_view sound_stream::update_view(attotime start, attotime end, u32 out #endif } } - g_profiler.stop(); // return the requested view return read_stream_view(m_output_view[outputnum], start); @@ -1093,14 +1085,6 @@ sound_manager::sound_manager(running_machine &machine) : m_wavfile(), m_first_reset(true) { - // get filename for WAV file or AVI file if specified - const char *wavfile = machine.options().wav_write(); - const char *avifile = machine.options().avi_write(); - - // handle -nosound and lower sample rate if not recording WAV or AVI - if (m_nosound_mode && wavfile[0] == 0 && avifile[0] == 0) - machine.m_sample_rate = 11025; - // count the mixers #if VERBOSE mixer_interface_enumerator iter(machine.root_device()); @@ -1385,18 +1369,42 @@ void sound_manager::config_load(config_type cfg_type, config_level cfg_level, ut // master volume attenuation if (util::xml::data_node const *node = parentnode->get_child("attenuation")) - set_attenuation(std::clamp(int(node->get_attribute_int("value", 0)), -32, 0)); + { + // treat source INI files or more specific as higher priority than CFG + // FIXME: leaky abstraction - this depends on a front-end implementation detail + if ((OPTION_PRIORITY_NORMAL + 5) > machine().options().get_entry(OPTION_VOLUME)->priority()) + set_attenuation(std::clamp(int(node->get_attribute_int("value", 0)), -32, 0)); + } // iterate over channel nodes - for (util::xml::data_node const *channelnode = parentnode->get_child("channel"); channelnode != nullptr; channelnode = channelnode->get_next_sibling("channel")) + for (util::xml::data_node const *node = parentnode->get_child("channel"); node != nullptr; node = node->get_next_sibling("channel")) { mixer_input info; - if (indexed_mixer_input(channelnode->get_attribute_int("index", -1), info)) + if (indexed_mixer_input(node->get_attribute_int("index", -1), info)) + { + // note that this doesn't disallow out-of-range values + float value = node->get_attribute_float("value", std::nanf("")); + + if (!std::isnan(value)) + info.stream->input(info.inputnum).set_user_gain(value); + } + } + + // iterate over speaker panning nodes + for (util::xml::data_node const *node = parentnode->get_child("panning"); node != nullptr; node = node->get_next_sibling("panning")) + { + char const *const tag = node->get_attribute_string("tag", nullptr); + if (tag != nullptr) { - float defvol = channelnode->get_attribute_float("defvol", 1.0f); - float newvol = channelnode->get_attribute_float("newvol", -1000.0f); - if (newvol != -1000.0f) - info.stream->input(info.inputnum).set_user_gain(newvol / defvol); + for (speaker_device &speaker : speaker_device_enumerator(machine().root_device())) + { + if (!strcmp(tag, speaker.tag())) + { + float value = node->get_attribute_float("value", speaker.defpan()); + speaker.set_pan(value); + break; + } + } } } } @@ -1420,21 +1428,36 @@ void sound_manager::config_save(config_type cfg_type, util::xml::data_node *pare node->set_attribute_int("value", m_attenuation); } - // iterate over mixer channels + // iterate over mixer channels for per-channel volume for (int mixernum = 0; ; mixernum++) { mixer_input info; if (!indexed_mixer_input(mixernum, info)) break; - float const newvol = info.stream->input(info.inputnum).user_gain(); - if (newvol != 1.0f) + float const value = info.stream->input(info.inputnum).user_gain(); + if (value != 1.0f) + { + util::xml::data_node *const node = parentnode->add_child("channel", nullptr); + if (node) + { + node->set_attribute_int("index", mixernum); + node->set_attribute_float("value", value); + } + } + } + + // iterate over speakers for panning + for (speaker_device &speaker : speaker_device_enumerator(machine().root_device())) + { + float const value = speaker.pan(); + if (value != speaker.defpan()) { - util::xml::data_node *const channelnode = parentnode->add_child("channel", nullptr); - if (channelnode) + util::xml::data_node *const node = parentnode->add_child("panning", nullptr); + if (node) { - channelnode->set_attribute_int("index", mixernum); - channelnode->set_attribute_float("newvol", newvol); + node->set_attribute("tag", speaker.tag()); + node->set_attribute_float("value", value); } } } @@ -1485,11 +1508,11 @@ stream_buffer::sample_t sound_manager::adjust_toward_compressor_scale(stream_buf // and send it to the OSD layer //------------------------------------------------- -void sound_manager::update(int param) +void sound_manager::update(s32 param) { LOG("sound_update\n"); - g_profiler.start(PROFILER_SOUND); + auto profile = g_profiler.start(PROFILER_SOUND); // determine the duration of this update attotime update_period = machine().time() - m_last_update; @@ -1625,6 +1648,4 @@ void sound_manager::update(int param) // notify that new samples have been generated emulator_info::sound_hook(); - - g_profiler.stop(); } diff --git a/src/emu/speaker.cpp b/src/emu/speaker.cpp index 3cbb14355a4..33b1e8d329a 100644 --- a/src/emu/speaker.cpp +++ b/src/emu/speaker.cpp @@ -37,6 +37,8 @@ speaker_device::speaker_device(const machine_config &mconfig, const char *tag, d , m_x(0.0) , m_y(0.0) , m_z(0.0) + , m_pan(0.0) + , m_defpan(0.0) , m_current_max(0) , m_samples_this_bucket(0) { @@ -53,6 +55,34 @@ speaker_device::~speaker_device() //------------------------------------------------- +// set_position - set speaker position +//------------------------------------------------- + +speaker_device &speaker_device::set_position(double x, double y, double z) +{ + // as mentioned in the header file, y and z params currently have no effect + m_x = x; + m_y = y; + m_z = z; + + // hard pan to left + if (m_x < 0.0) + set_pan(-1.0f); + + // hard pan to right + else if (m_x > 0.0) + set_pan(1.0f); + + // center (mono) + else + set_pan(0.0f); + + m_defpan = m_pan; + return *this; +} + + +//------------------------------------------------- // mix - mix in samples from the speaker's stream //------------------------------------------------- @@ -89,24 +119,29 @@ void speaker_device::mix(stream_buffer::sample_t *leftmix, stream_buffer::sample // mix if sound is enabled if (!suppress) { - // if the speaker is centered, send to both left and right - if (m_x == 0) + // if the speaker is hard panned to the left, send only to the left + if (m_pan == -1.0f) for (int sample = 0; sample < expected_samples; sample++) - { - stream_buffer::sample_t cursample = view.get(sample); - leftmix[sample] += cursample; - rightmix[sample] += cursample; - } + leftmix[sample] += view.get(sample); - // if the speaker is to the left, send only to the left - else if (m_x < 0) + // if the speaker is hard panned to the right, send only to the right + else if (m_pan == 1.0f) for (int sample = 0; sample < expected_samples; sample++) - leftmix[sample] += view.get(sample); + rightmix[sample] += view.get(sample); - // if the speaker is to the right, send only to the right + // otherwise, send to both else + { + const float leftpan = (m_pan <= 0.0f) ? 1.0f : 1.0f - m_pan; + const float rightpan = (m_pan >= 0.0f) ? 1.0f : 1.0f + m_pan; + for (int sample = 0; sample < expected_samples; sample++) - rightmix[sample] += view.get(sample); + { + stream_buffer::sample_t cursample = view.get(sample); + leftmix[sample] += cursample * leftpan; + rightmix[sample] += cursample * rightpan; + } + } } } @@ -117,7 +152,6 @@ void speaker_device::mix(stream_buffer::sample_t *leftmix, stream_buffer::sample void speaker_device::device_start() { - // dummy save to make device.c happy } @@ -187,4 +221,3 @@ void speaker_device::device_stop() } } } - diff --git a/src/emu/speaker.h b/src/emu/speaker.h index 54aa00603c9..3cb0794d998 100644 --- a/src/emu/speaker.h +++ b/src/emu/speaker.h @@ -53,8 +53,8 @@ public: speaker_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); virtual ~speaker_device(); - // inline configuration helpers - speaker_device &set_position(double x, double y, double z) { m_x = x; m_y = y; m_z = z; return *this; } + // configuration helpers + speaker_device &set_position(double x, double y, double z); speaker_device &front_center() { set_position( 0.0, 0.0, 1.0); return *this; } speaker_device &front_left() { set_position(-0.2, 0.0, 1.0); return *this; } speaker_device &front_floor() { set_position( 0.0, -0.5, 1.0); return *this; } @@ -71,15 +71,22 @@ public: // internally for use by the sound system void mix(stream_buffer::sample_t *leftmix, stream_buffer::sample_t *rightmix, attotime start, attotime end, int expected_samples, bool suppress); + // user panning configuration + void set_pan(float pan) { m_pan = std::clamp(pan, -1.0f, 1.0f); } + float pan() { return m_pan; } + float defpan() { return m_defpan; } + protected: // device-level overrides virtual void device_start() override ATTR_COLD; virtual void device_stop() override ATTR_COLD; - // inline configuration state + // configuration state double m_x; double m_y; double m_z; + float m_pan; + float m_defpan; // internal state static constexpr int BUCKETS_PER_SECOND = 10; diff --git a/src/emu/tilemap.cpp b/src/emu/tilemap.cpp index 5757f35341f..1aa18eef168 100644 --- a/src/emu/tilemap.cpp +++ b/src/emu/tilemap.cpp @@ -772,7 +772,7 @@ void tilemap_t::pixmap_update() if (m_all_tiles_clean) return; -g_profiler.start(PROFILER_TILEMAP_DRAW); + auto profile = g_profiler.start(PROFILER_TILEMAP_DRAW); // flush the dirty state to all tiles as appropriate realize_all_dirty_tiles(); @@ -786,8 +786,6 @@ g_profiler.start(PROFILER_TILEMAP_DRAW); // mark it all clean m_all_tiles_clean = true; - -g_profiler.stop(); } @@ -797,7 +795,7 @@ g_profiler.stop(); void tilemap_t::tile_update(logical_index logindex, u32 col, u32 row) { -g_profiler.start(PROFILER_TILEMAP_UPDATE); + auto profile = g_profiler.start(PROFILER_TILEMAP_UPDATE); // call the get info callback for the associated memory index tilemap_memory_index memindex = m_logical_to_memory[logindex]; @@ -822,8 +820,6 @@ g_profiler.start(PROFILER_TILEMAP_UPDATE); m_gfx_used |= 1 << m_tileinfo.gfxnum; m_gfx_dirtyseq[m_tileinfo.gfxnum] = m_tileinfo.decoder->gfx(m_tileinfo.gfxnum)->dirtyseq(); } - -g_profiler.stop(); } @@ -997,7 +993,8 @@ void tilemap_t::draw_common(screen_device &screen, _BitmapClass &dest, const rec if (!m_enable) return; -g_profiler.start(PROFILER_TILEMAP_DRAW); + auto profile = g_profiler.start(PROFILER_TILEMAP_DRAW); + // configure the blit parameters based on the input parameters blit_parameters blit; configure_blit_parameters(blit, screen.priority(), cliprect, flags, priority, priority_mask); @@ -1095,7 +1092,6 @@ g_profiler.start(PROFILER_TILEMAP_DRAW); } } } -g_profiler.stop(); } void tilemap_t::draw(screen_device &screen, bitmap_ind16 &dest, const rectangle &cliprect, u32 flags, u8 priority, u8 priority_mask) @@ -1134,7 +1130,8 @@ void tilemap_t::draw_roz_common(screen_device &screen, _BitmapClass &dest, const return; } -g_profiler.start(PROFILER_TILEMAP_DRAW_ROZ); + auto profile = g_profiler.start(PROFILER_TILEMAP_DRAW_ROZ); + // configure the blit parameters blit_parameters blit; configure_blit_parameters(blit, screen.priority(), cliprect, flags, priority, priority_mask); @@ -1146,7 +1143,6 @@ g_profiler.start(PROFILER_TILEMAP_DRAW_ROZ); // then do the roz copy draw_roz_core(screen, dest, blit, startx, starty, incxx, incxy, incyx, incyy, wraparound); -g_profiler.stop(); } void tilemap_t::draw_roz(screen_device &screen, bitmap_ind16 &dest, const rectangle &cliprect, @@ -1182,7 +1178,16 @@ void tilemap_t::draw_instance(screen_device &screen, _BitmapClass &dest, const b // look up priority and destination base addresses for y1 bitmap_ind8 &priority_bitmap = *blit.priority; - u8 *priority_baseaddr = &priority_bitmap.pix(y1, xpos); + u8 *priority_baseaddr = nullptr; + int prio_rowpixels = 0; + if (priority_bitmap.valid()) + { + prio_rowpixels = priority_bitmap.rowpixels(); + priority_baseaddr = &priority_bitmap.pix(y1, xpos); + } + else + assert((blit.tilemap_priority_code & 0xffff) == 0xff00); + typename _BitmapClass::pixel_t *dest_baseaddr = nullptr; int dest_rowpixels = 0; if (dest.valid()) @@ -1260,7 +1265,7 @@ void tilemap_t::draw_instance(screen_device &screen, _BitmapClass &dest, const b { const u16 *source0 = source_baseaddr + x_start; typename _BitmapClass::pixel_t *dest0 = dest_baseaddr + x_start; - u8 *pmap0 = priority_baseaddr + x_start; + u8 *pmap0 = priority_baseaddr ? (priority_baseaddr + x_start) : nullptr; // if we were opaque, use the opaque renderer if (prev_trans == WHOLLY_OPAQUE) @@ -1278,7 +1283,7 @@ void tilemap_t::draw_instance(screen_device &screen, _BitmapClass &dest, const b dest0 += dest_rowpixels; source0 += m_pixmap.rowpixels(); - pmap0 += priority_bitmap.rowpixels(); + pmap0 += prio_rowpixels; } } @@ -1300,7 +1305,7 @@ void tilemap_t::draw_instance(screen_device &screen, _BitmapClass &dest, const b dest0 += dest_rowpixels; source0 += m_pixmap.rowpixels(); mask0 += m_flagsmap.rowpixels(); - pmap0 += priority_bitmap.rowpixels(); + pmap0 += prio_rowpixels; } } } @@ -1315,7 +1320,7 @@ void tilemap_t::draw_instance(screen_device &screen, _BitmapClass &dest, const b break; // advance to the next row on all our bitmaps - priority_baseaddr += priority_bitmap.rowpixels() * (nexty - y); + priority_baseaddr += prio_rowpixels * (nexty - y); source_baseaddr += m_pixmap.rowpixels() * (nexty - y); mask_baseaddr += m_flagsmap.rowpixels() * (nexty - y); dest_baseaddr += dest_rowpixels * (nexty - y); @@ -1559,10 +1564,14 @@ void tilemap_t::get_info_debug(u32 col, u32 row, u8 &gfxnum, u32 &code, u32 &col // get the GFX number and code gfxnum = m_tileinfo.gfxnum; code = m_tileinfo.code; + color = m_tileinfo.palette_base; - // work back from the palette base to get the color - const gfx_element &gfx = *m_tileinfo.decoder->gfx(gfxnum); - color = (m_tileinfo.palette_base - gfx.colorbase()) / gfx.granularity(); + if (gfxnum != 0xff) + { + // work back from the palette base to get the color + const gfx_element &gfx = *m_tileinfo.decoder->gfx(gfxnum); + color = (color - gfx.colorbase()) / gfx.granularity(); + } } @@ -1604,8 +1613,7 @@ tilemap_manager::~tilemap_manager() //------------------------------------------------- -// set_flip_all - set a global flip for all the -// tilemaps +// create - allocate a tilemap //------------------------------------------------- tilemap_t &tilemap_manager::create(device_gfx_interface &decoder, tilemap_get_info_delegate tile_get_info, tilemap_mapper_delegate mapper, u16 tilewidth, u16 tileheight, u32 cols, u32 rows, tilemap_t *allocated) diff --git a/src/emu/uiinput.cpp b/src/emu/uiinput.cpp index d1398591687..138bf67055d 100644 --- a/src/emu/uiinput.cpp +++ b/src/emu/uiinput.cpp @@ -254,10 +254,10 @@ bool ui_input_manager::pressed_repeat(int code, int speed) { bool pressed; -g_profiler.start(PROFILER_INPUT); + auto profile = g_profiler.start(PROFILER_INPUT); /* get the status of this key (assumed to be only in the defaults) */ - assert(code >= IPT_UI_CONFIGURE && code <= IPT_OSD_16); + assert(code > IPT_UI_FIRST && code < IPT_UI_LAST); pressed = (m_seqpressed[code] == SEQ_PRESSED_TRUE); /* if down, handle it specially */ @@ -289,8 +289,6 @@ g_profiler.start(PROFILER_INPUT); else m_next_repeat[code] = 0; -g_profiler.stop(); - return pressed; } diff --git a/src/emu/validity.cpp b/src/emu/validity.cpp index 8fed2d6def0..4cb6202b4d9 100644 --- a/src/emu/validity.cpp +++ b/src/emu/validity.cpp @@ -12,6 +12,7 @@ #include "validity.h" #include "emuopts.h" +#include "main.h" #include "romload.h" #include "speaker.h" #include "video/rgbutil.h" @@ -50,12 +51,10 @@ using test_delegate = delegate<char (void const *&)>; // type //------------------------------------------------- -#if !defined(_LIBCPP_VERSION) || (_LIBCPP_VERSION >= 7000) test_delegate make_diamond_class_delegate(char (diamond_inheritance::*func)(void const *&), diamond_inheritance *obj) { return test_delegate(func, obj); } -#endif // !defined(_LIBCPP_VERSION) || (_LIBCPP_VERSION >= 7000) //------------------------------------------------- @@ -835,6 +834,15 @@ void validate_rgb() rgb.shl(rgbaint_t(19, 3, 21, 6)); check_expected("rgbaint_t::shl"); + // test shift left out of range + expected_a = (actual_a = random_i32()) & 0; + expected_r = (actual_r = random_i32()) & 0; + expected_g = (actual_g = random_i32()) & 0; + expected_b = (actual_b = random_i32()) & 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.shl(rgbaint_t(-19, 32, -21, 38)); + check_expected("rgbaint_t::shl"); + // test shift left immediate expected_a = (actual_a = random_i32()) << 7; expected_r = (actual_r = random_i32()) << 7; @@ -844,6 +852,15 @@ void validate_rgb() rgb.shl_imm(7); check_expected("rgbaint_t::shl_imm"); + // test shift left immediate out of range + expected_a = (actual_a = random_i32()) & 0; + expected_r = (actual_r = random_i32()) & 0; + expected_g = (actual_g = random_i32()) & 0; + expected_b = (actual_b = random_i32()) & 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.shl_imm(32); + check_expected("rgbaint_t::shl_imm"); + // test logical shift right expected_a = s32(u32(actual_a = random_i32()) >> 8); expected_r = s32(u32(actual_r = random_i32()) >> 18); @@ -862,6 +879,15 @@ void validate_rgb() rgb.shr(rgbaint_t(21, 13, 11, 17)); check_expected("rgbaint_t::shr"); + // test logical shift right out of range + expected_a = (actual_a = random_i32()) & 0; + expected_r = (actual_r = random_i32()) & 0; + expected_g = (actual_g = random_i32()) & 0; + expected_b = (actual_b = random_i32()) & 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.shr(rgbaint_t(40, -18, -26, 32)); + check_expected("rgbaint_t::shr"); + // test logical shift right immediate expected_a = s32(u32(actual_a = random_i32()) >> 5); expected_r = s32(u32(actual_r = random_i32()) >> 5); @@ -880,6 +906,15 @@ void validate_rgb() rgb.shr_imm(15); check_expected("rgbaint_t::shr_imm"); + // test logical shift right immediate out of range + expected_a = (actual_a = random_i32()) & 0; + expected_r = (actual_r = random_i32()) & 0; + expected_g = (actual_g = random_i32()) & 0; + expected_b = (actual_b = random_i32()) & 0; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.shr_imm(35); + check_expected("rgbaint_t::shr_imm"); + // test arithmetic shift right expected_a = (actual_a = random_i32()) >> 16; expected_r = (actual_r = random_i32()) >> 20; @@ -898,6 +933,15 @@ void validate_rgb() rgb.sra(rgbaint_t(1, 29, 10, 22)); check_expected("rgbaint_t::sra"); + // test arithmetic shift right out of range + expected_a = (actual_a = random_i32()) >> 31; + expected_r = (actual_r = random_i32()) >> 31; + expected_g = (actual_g = random_i32()) >> 31; + expected_b = (actual_b = random_i32()) >> 31; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.sra(rgbaint_t(-16, -20, 46, 32)); + check_expected("rgbaint_t::sra"); + // test arithmetic shift right immediate (method) expected_a = (actual_a = random_i32()) >> 12; expected_r = (actual_r = random_i32()) >> 12; @@ -916,6 +960,15 @@ void validate_rgb() rgb.sra_imm(9); check_expected("rgbaint_t::sra_imm"); + // test arithmetic shift right immediate out of range (method) + expected_a = (actual_a = random_i32()) >> 31; + expected_r = (actual_r = random_i32()) >> 31; + expected_g = (actual_g = random_i32()) >> 31; + expected_b = (actual_b = random_i32()) >> 31; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb.sra_imm(38); + check_expected("rgbaint_t::sra_imm"); + // test arithmetic shift right immediate (operator) expected_a = (actual_a = random_i32()) >> 7; expected_r = (actual_r = random_i32()) >> 7; @@ -934,6 +987,15 @@ void validate_rgb() rgb >>= 11; check_expected("rgbaint_t::operator>>="); + // test arithmetic shift right immediate out of range (operator) + expected_a = (actual_a = random_i32()) >> 31; + expected_r = (actual_r = random_i32()) >> 31; + expected_g = (actual_g = random_i32()) >> 31; + expected_b = (actual_b = random_i32()) >> 31; + rgb.set(actual_a, actual_r, actual_g, actual_b); + rgb >>= 41; + check_expected("rgbaint_t::operator>>="); + // test RGB equality comparison actual_a = random_i32_nolimit(); actual_r = random_i32_nolimit(); @@ -1424,7 +1486,6 @@ void validate_delegates_mfp() if (&o != addr) osd_printf_error("Error testing delegate this pointer adjustment for virtual member function through base class pointer %p -> %p (expected %p)\n", static_cast<void const *>(static_cast<base_b *>(&o)), addr, static_cast<void const *>(&o)); -#if !defined(_LIBCPP_VERSION) || (_LIBCPP_VERSION >= 7000) // test creating delegates for a forward-declared class cb1 = make_diamond_class_delegate(&diamond_inheritance::get_derived_a, &d); cb2 = make_diamond_class_delegate(&diamond_inheritance::get_derived_b, &d); @@ -1454,7 +1515,6 @@ void validate_delegates_mfp() if (static_cast<virtual_base *>(&d) != addr) osd_printf_error("Error testing delegate this pointer adjustment for incomplete class %p -> %p (expected %p)\n", static_cast<void const *>(&d), addr, static_cast<void const *>(static_cast<virtual_base *>(&d))); #endif // defined(_MSC_VER) && !defined(__clang__) -#endif // !defined(_LIBCPP_VERSION) || (_LIBCPP_VERSION >= 7000) } @@ -2144,34 +2204,46 @@ void validity_checker::validate_roms(device_t &root) current_length = ROMREGION_GETLENGTH(romp); if (!m_region_map.emplace(fulltag, current_length).second) osd_printf_error("Multiple ROM_REGIONs with the same tag '%s' defined\n", fulltag); + if (current_length == 0) + osd_printf_error("ROM region '%s' has zero length\n", fulltag); } else if (ROMENTRY_ISSYSTEM_BIOS(romp)) // If this is a system bios, make sure it is using the next available bios number { int const bios_flags = ROM_GETBIOSFLAGS(romp); char const *const biosname = romp->name; if (bios_flags != last_bios + 1) - osd_printf_error("Non-sequential BIOS %s (specified as %d, expected to be %d)\n", biosname, bios_flags - 1, last_bios); + osd_printf_error("Non-sequential BIOS %s (specified as %d, expected to be %d)\n", biosname ? biosname : "UNNAMED", bios_flags - 1, last_bios); last_bios = bios_flags; // validate the name - if (strlen(biosname) > 16) - osd_printf_error("BIOS name %s exceeds maximum 16 characters\n", biosname); - for (char const *s = biosname; *s; ++s) + if (!biosname || biosname[0] == 0) + osd_printf_error("BIOS %d is missing a name\n", bios_flags - 1); + else { - if (((*s < '0') || (*s > '9')) && ((*s < 'a') || (*s > 'z')) && (*s != '.') && (*s != '_') && (*s != '-')) + if (strlen(biosname) > 16) + osd_printf_error("BIOS name %s exceeds maximum 16 characters\n", biosname); + for (char const *s = biosname; *s; ++s) { - osd_printf_error("BIOS name %s contains invalid characters\n", biosname); - break; + if (((*s < '0') || (*s > '9')) && ((*s < 'a') || (*s > 'z')) && (*s != '.') && (*s != '_') && (*s != '-')) + { + osd_printf_error("BIOS name %s contains invalid characters\n", biosname); + break; + } } - } - // check for duplicate names/descriptions - auto const nameins = bios_names.emplace(biosname, bios_flags); - if (!nameins.second) - osd_printf_error("Duplicate BIOS name %s specified (%d and %d)\n", biosname, nameins.first->second, bios_flags - 1); - auto const descins = bios_descs.emplace(romp->hashdata, biosname); - if (!descins.second) - osd_printf_error("BIOS %s has duplicate description '%s' (was %s)\n", biosname, romp->hashdata, descins.first->second); + // check for duplicate names/descriptions + auto const nameins = bios_names.emplace(biosname, bios_flags); + if (!nameins.second) + osd_printf_error("Duplicate BIOS name %s specified (%d and %d)\n", biosname, nameins.first->second, bios_flags - 1); + if (!romp->hashdata || romp->hashdata[0] == 0) + osd_printf_error("BIOS %s has empty description\n", biosname); + else + { + auto const descins = bios_descs.emplace(romp->hashdata, biosname); + if (!descins.second) + osd_printf_error("BIOS %s has duplicate description '%s' (was %s)\n", biosname, romp->hashdata, descins.first->second); + } + } } else if (ROMENTRY_ISDEFAULT_BIOS(romp)) // if this is a default BIOS setting, remember it so it to check at the end { @@ -2324,7 +2396,7 @@ void validity_checker::validate_dip_settings(const ioport_field &field) { char const *const demo_sounds = ioport_string_from_index(INPUT_STRING_Demo_Sounds); char const *const flipscreen = ioport_string_from_index(INPUT_STRING_Flip_Screen); - char const *const name = field.specific_name(); + char const *const name = field.specific_name() ? field.specific_name() : "UNNAMED"; u8 coin_list[__input_string_coinage_end + 1 - __input_string_coinage_start] = { 0 }; bool coin_error = false; @@ -2393,6 +2465,12 @@ void validity_checker::validate_dip_settings(const ioport_field &field) void validity_checker::validate_condition(const ioport_condition &condition, device_t &device) { + if (condition.tag() == nullptr) + { + osd_printf_error("Condition referencing null ioport tag\n"); + return; + } + // resolve the tag, then find a matching port if (m_ioport_set.find(device.subtag(condition.tag())) == m_ioport_set.end()) osd_printf_error("Condition referencing non-existent ioport tag '%s'\n", condition.tag()); @@ -2457,34 +2535,43 @@ void validity_checker::validate_inputs(device_t &root) if (field.is_analog()) validate_analog_input_field(field); - // look for invalid (0) types which should be mapped to IPT_OTHER - if (field.type() == IPT_INVALID) + // checks based on field type + if ((field.type() > IPT_UI_FIRST) && (field.type() < IPT_UI_LAST)) + { + osd_printf_error("Field has invalid UI control type\n"); + } + else if (field.type() == IPT_INVALID) + { osd_printf_error("Field has an invalid type (0); use IPT_OTHER instead\n"); - - if (field.type() == IPT_SPECIAL) + } + else if (field.type() == IPT_SPECIAL) + { osd_printf_error("Field has an invalid type IPT_SPECIAL\n"); - - // verify dip switches - if (field.type() == IPT_DIPSWITCH) + } + else if (field.type() == IPT_DIPSWITCH) { - // dip switch fields must have a specific name + // DIP switch fields must have a specific name if (field.specific_name() == nullptr) osd_printf_error("DIP switch has no specific name\n"); // verify the settings list validate_dip_settings(field); } - - // verify config settings - if (field.type() == IPT_CONFIG) + else if (field.type() == IPT_CONFIG) { // config fields must have a specific name if (field.specific_name() == nullptr) osd_printf_error("Config switch has no specific name\n"); } + else if (field.type() == IPT_ADJUSTER) + { + // adjuster fields must have a specific name + if (field.specific_name() == nullptr) + osd_printf_error("Adjuster has no specific name\n"); + } // verify names - const char *name = field.specific_name(); + char const *const name = field.specific_name(); if (name != nullptr) { // check for empty string @@ -2806,7 +2893,7 @@ void validity_checker::build_output_prefix(std::ostream &str) const // error_output - error message output override //------------------------------------------------- -void validity_checker::output_callback(osd_output_channel channel, const util::format_argument_pack<std::ostream> &args) +void validity_checker::output_callback(osd_output_channel channel, const util::format_argument_pack<char> &args) { std::ostringstream output; switch (channel) diff --git a/src/emu/validity.h b/src/emu/validity.h index 54687716bd7..fbf5f239323 100644 --- a/src/emu/validity.h +++ b/src/emu/validity.h @@ -51,7 +51,7 @@ public: protected: // osd_output interface - virtual void output_callback(osd_output_channel channel, const util::format_argument_pack<std::ostream> &args) override; + virtual void output_callback(osd_output_channel channel, const util::format_argument_pack<char> &args) override; private: // internal map types diff --git a/src/emu/video.cpp b/src/emu/video.cpp index 8f9e9e3623a..06a16b76cda 100644 --- a/src/emu/video.cpp +++ b/src/emu/video.cpp @@ -9,15 +9,17 @@ ***************************************************************************/ #include "emu.h" -#include "emuopts.h" + +#include "crsshair.h" #include "debugger.h" +#include "emuopts.h" #include "fileio.h" -#include "ui/uimain.h" -#include "crsshair.h" -#include "rendersw.hxx" +#include "main.h" #include "output.h" #include "screen.h" +#include "ui/uimain.h" + #include "corestr.h" #include "path.h" #include "png.h" @@ -25,6 +27,8 @@ #include "osdepend.h" +#include "rendersw.hxx" + //************************************************************************** // DEBUGGING @@ -214,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; @@ -230,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) @@ -514,7 +518,7 @@ void video_manager::exit() // when there are no screens to drive it //------------------------------------------------- -void video_manager::screenless_update_callback(int param) +void video_manager::screenless_update_callback(s32 param) { // force an update frame_update(false); @@ -803,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) { @@ -839,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; } @@ -1230,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; @@ -1249,7 +1252,6 @@ void video_manager::record_frame() if (error) end_recording(); - g_profiler.stop(); } diff --git a/src/emu/video.h b/src/emu/video.h index da57d6b8a98..efc819ae793 100644 --- a/src/emu/video.h +++ b/src/emu/video.h @@ -90,7 +90,7 @@ public: private: // internal helpers void exit(); - void screenless_update_callback(int param); + void screenless_update_callback(s32 param); void postload(); // effective value helpers diff --git a/src/emu/video/rgbgen.h b/src/emu/video/rgbgen.h index e460208d9fd..b20d79c94d8 100644 --- a/src/emu/video/rgbgen.h +++ b/src/emu/video/rgbgen.h @@ -151,16 +151,21 @@ public: inline void shl(const rgbaint_t& shift) { - m_a <<= shift.m_a; - m_r <<= shift.m_r; - m_g <<= shift.m_g; - m_b <<= shift.m_b; + m_a = (u32(shift.m_a) > 31) ? 0 : (m_a << shift.m_a); + m_r = (u32(shift.m_r) > 31) ? 0 : (m_r << shift.m_r); + m_g = (u32(shift.m_g) > 31) ? 0 : (m_g << shift.m_g); + m_b = (u32(shift.m_b) > 31) ? 0 : (m_b << shift.m_b); } inline void shl_imm(const u8 shift) { if (shift == 0) return; + if (shift > 31) + { + zero(); + return; + } m_a <<= shift; m_r <<= shift; @@ -170,16 +175,21 @@ public: inline void shr(const rgbaint_t& shift) { - m_a = s32(u32(m_a) >> shift.m_a); - m_r = s32(u32(m_r) >> shift.m_r); - m_g = s32(u32(m_g) >> shift.m_g); - m_b = s32(u32(m_b) >> shift.m_b); + m_a = (u32(shift.m_a) > 31) ? 0 : s32(u32(m_a) >> shift.m_a); + m_r = (u32(shift.m_r) > 31) ? 0 : s32(u32(m_r) >> shift.m_r); + m_g = (u32(shift.m_g) > 31) ? 0 : s32(u32(m_g) >> shift.m_g); + m_b = (u32(shift.m_b) > 31) ? 0 : s32(u32(m_b) >> shift.m_b); } inline void shr_imm(const u8 shift) { if (shift == 0) return; + if (shift > 31) + { + zero(); + return; + } m_a = s32(u32(m_a) >> shift); m_r = s32(u32(m_r) >> shift); @@ -189,43 +199,19 @@ public: inline void sra(const rgbaint_t& shift) { - m_a >>= shift.m_a; - if (m_a & (1 << (31 - shift.m_a))) - m_a |= ~0 << (32 - shift.m_a); - - m_r >>= shift.m_r; - if (m_r & (1 << (31 - shift.m_r))) - m_r |= ~0 << (32 - shift.m_r); - - m_g >>= shift.m_g; - if (m_g & (1 << (31 - shift.m_g))) - m_g |= ~0 << (32 - shift.m_g); - - m_b >>= shift.m_b; - if (m_b & (1 << (31 - shift.m_b))) - m_b |= ~0 << (32 - shift.m_b); + m_a >>= (u32(shift.m_a) > 31) ? 31 : shift.m_a; + m_r >>= (u32(shift.m_r) > 31) ? 31 : shift.m_r; + m_g >>= (u32(shift.m_g) > 31) ? 31 : shift.m_g; + m_b >>= (u32(shift.m_b) > 31) ? 31 : shift.m_b; } inline void sra_imm(const u8 shift) { - const u32 high_bit = 1 << (31 - shift); - const u32 high_mask = ~0 << (32 - shift); - - m_a >>= shift; - if (m_a & high_bit) - m_a |= high_mask; - - m_r >>= shift; - if (m_r & high_bit) - m_r |= high_mask; - - m_g >>= shift; - if (m_g & high_bit) - m_g |= high_mask; - - m_b >>= shift; - if (m_b & high_bit) - m_b |= high_mask; + const u8 s = std::min<u8>(shift, 31); + m_a >>= s; + m_r >>= s; + m_g >>= s; + m_b >>= s; } void or_reg(const rgbaint_t& color) { or_imm_rgba(color.m_a, color.m_r, color.m_g, color.m_b); } diff --git a/src/emu/video/rgbvmx.cpp b/src/emu/video/rgbvmx.cpp index 608f7024565..62bd25b3578 100644 --- a/src/emu/video/rgbvmx.cpp +++ b/src/emu/video/rgbvmx.cpp @@ -190,7 +190,7 @@ void rgbaint_t::scale_and_clamp(const rgbaint_t& scale) clamp_to_uint8(); } -void rgbaint_t::scale_imm_and_clamp(const s32 scale) +void rgbaint_t::scale_imm_and_clamp(s32 scale) { mul_imm(scale); sra_imm(8); diff --git a/src/emu/video/rgbvmx.h b/src/emu/video/rgbvmx.h index 05d26cd9e21..dd1946bfa28 100644 --- a/src/emu/video/rgbvmx.h +++ b/src/emu/video/rgbvmx.h @@ -76,7 +76,7 @@ public: } // This function sets all elements to the same val - void set_all(const s32& val) { set(val, val, val, val); } + void set_all(const s32 &val) { set(val, val, val, val); } // This function zeros all elements void zero() { set_all(0); } // This function zeros only the alpha element @@ -100,31 +100,31 @@ public: return result; } - void set_a16(const s32 value) + void set_a16(s32 value) { const VECS32 temp = { value, value, value, value }; m_value = vec_perm(m_value, temp, alpha_perm); } - void set_a(const s32 value) + void set_a(s32 value) { const VECS32 temp = { value, value, value, value }; m_value = vec_perm(m_value, temp, alpha_perm); } - void set_r(const s32 value) + void set_r(s32 value) { const VECS32 temp = { value, value, value, value }; m_value = vec_perm(m_value, temp, red_perm); } - void set_g(const s32 value) + void set_g(s32 value) { const VECS32 temp = { value, value, value, value }; m_value = vec_perm(m_value, temp, green_perm); } - void set_b(const s32 value) + void set_b(s32 value) { const VECS32 temp = { value, value, value, value }; m_value = vec_perm(m_value, temp, blue_perm); @@ -229,13 +229,13 @@ public: m_value = vec_add(m_value, color2.m_value); } - inline void add_imm(const s32 imm) + inline void add_imm(s32 imm) { const VECS32 temp = { imm, imm, imm, imm }; m_value = vec_add(m_value, temp); } - inline void add_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) + inline void add_imm_rgba(s32 a, s32 r, s32 g, s32 b) { #ifdef __LITTLE_ENDIAN__ const VECS32 temp = { b, g, r, a }; @@ -250,13 +250,13 @@ public: m_value = vec_sub(m_value, color2.m_value); } - inline void sub_imm(const s32 imm) + inline void sub_imm(s32 imm) { const VECS32 temp = { imm, imm, imm, imm }; m_value = vec_sub(m_value, temp); } - inline void sub_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) + inline void sub_imm_rgba(s32 a, s32 r, s32 g, s32 b) { #ifdef __LITTLE_ENDIAN__ const VECS32 temp = { b, g, r, a }; @@ -271,13 +271,13 @@ public: m_value = vec_sub(color2.m_value, m_value); } - inline void subr_imm(const s32 imm) + inline void subr_imm(s32 imm) { const VECS32 temp = { imm, imm, imm, imm }; m_value = vec_sub(temp, m_value); } - inline void subr_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) + inline void subr_imm_rgba(s32 a, s32 r, s32 g, s32 b) { #ifdef __LITTLE_ENDIAN__ const VECS32 temp = { b, g, r, a }; @@ -298,7 +298,7 @@ public: #endif } - inline void mul_imm(const s32 imm) + inline void mul_imm(s32 imm) { const VECU32 value = { u32(imm), u32(imm), u32(imm), u32(imm) }; const VECU32 shift = vec_splat_u32(-16); @@ -310,7 +310,7 @@ public: #endif } - inline void mul_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) + inline void mul_imm_rgba(s32 a, s32 r, s32 g, s32 b) { #ifdef __LITTLE_ENDIAN__ const VECU32 value = { u32(b), u32(g), u32(r), u32(a) }; @@ -332,10 +332,17 @@ public: m_value = vec_and(vec_sl(m_value, VECU32(shift.m_value)), vec_cmpgt(limit, VECU32(shift.m_value))); } - inline void shl_imm(const u8 shift) + inline void shl_imm(u8 shift) { - const VECU32 temp = { shift, shift, shift, shift }; - m_value = vec_sl(m_value, temp); + if (32 > shift) + { + const VECU32 temp = { shift, shift, shift, shift }; + m_value = vec_sl(m_value, temp); + } + else + { + m_value = vec_splat_s32(0); + } } inline void shr(const rgbaint_t& shift) @@ -344,10 +351,17 @@ public: m_value = vec_and(vec_sr(m_value, VECU32(shift.m_value)), vec_cmpgt(limit, VECU32(shift.m_value))); } - inline void shr_imm(const u8 shift) + inline void shr_imm(u8 shift) { - const VECU32 temp = { shift, shift, shift, shift }; - m_value = vec_sr(m_value, temp); + if (32 > shift) + { + const VECU32 temp = { shift, shift, shift, shift }; + m_value = vec_sr(m_value, temp); + } + else + { + m_value = vec_splat_s32(0); + } } inline void sra(const rgbaint_t& shift) @@ -356,8 +370,9 @@ public: m_value = vec_sra(m_value, vec_min(VECU32(shift.m_value), limit)); } - inline void sra_imm(const u8 shift) + inline void sra_imm(u8 shift) { + shift = std::min<u8>(shift, 31); const VECU32 temp = { shift, shift, shift, shift }; m_value = vec_sra(m_value, temp); } @@ -367,13 +382,13 @@ public: m_value = vec_or(m_value, color2.m_value); } - inline void or_imm(const s32 value) + inline void or_imm(s32 value) { const VECS32 temp = { value, value, value, value }; m_value = vec_or(m_value, temp); } - inline void or_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) + inline void or_imm_rgba(s32 a, s32 r, s32 g, s32 b) { #ifdef __LITTLE_ENDIAN__ const VECS32 temp = { b, g, r, a }; @@ -393,13 +408,13 @@ public: m_value = vec_andc(m_value, color.m_value); } - inline void and_imm(const s32 value) + inline void and_imm(s32 value) { const VECS32 temp = { value, value, value, value }; m_value = vec_and(m_value, temp); } - inline void and_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) + inline void and_imm_rgba(s32 a, s32 r, s32 g, s32 b) { #ifdef __LITTLE_ENDIAN__ const VECS32 temp = { b, g, r, a }; @@ -414,13 +429,13 @@ public: m_value = vec_xor(m_value, color2.m_value); } - inline void xor_imm(const s32 value) + inline void xor_imm(s32 value) { const VECS32 temp = { value, value, value, value }; m_value = vec_xor(m_value, temp); } - inline void xor_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) + inline void xor_imm_rgba(s32 a, s32 r, s32 g, s32 b) { #ifdef __LITTLE_ENDIAN__ const VECS32 temp = { b, g, r, a }; @@ -430,7 +445,7 @@ public: m_value = vec_xor(m_value, temp); } - inline void clamp_and_clear(const u32 sign) + inline void clamp_and_clear(u32 sign) { const VECS32 vzero = { 0, 0, 0, 0 }; VECS32 vsign = { s32(sign), s32(sign), s32(sign), s32(sign) }; @@ -454,7 +469,7 @@ public: #endif } - inline void sign_extend(const u32 compare, const u32 sign) + inline void sign_extend(u32 compare, u32 sign) { const VECS32 compare_vec = { s32(compare), s32(compare), s32(compare), s32(compare) }; const VECS32 compare_mask = VECS32(vec_cmpeq(vec_and(m_value, compare_vec), compare_vec)); @@ -462,13 +477,13 @@ public: m_value = vec_or(m_value, vec_and(sign_vec, compare_mask)); } - inline void min(const s32 value) + inline void min(s32 value) { const VECS32 temp = { value, value, value, value }; m_value = vec_min(m_value, temp); } - inline void max(const s32 value) + inline void max(s32 value) { const VECS32 temp = { value, value, value, value }; m_value = vec_max(m_value, temp); @@ -477,7 +492,7 @@ public: void blend(const rgbaint_t& other, u8 factor); void scale_and_clamp(const rgbaint_t& scale); - void scale_imm_and_clamp(const s32 scale); + void scale_imm_and_clamp(s32 scale); void scale_add_and_clamp(const rgbaint_t& scale, const rgbaint_t& other) { @@ -503,13 +518,13 @@ public: m_value = VECS32(vec_cmpeq(m_value, value.m_value)); } - inline void cmpeq_imm(const s32 value) + inline void cmpeq_imm(s32 value) { const VECS32 temp = { value, value, value, value }; m_value = VECS32(vec_cmpeq(m_value, temp)); } - inline void cmpeq_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) + inline void cmpeq_imm_rgba(s32 a, s32 r, s32 g, s32 b) { #ifdef __LITTLE_ENDIAN__ const VECS32 temp = { b, g, r, a }; @@ -524,13 +539,13 @@ public: m_value = VECS32(vec_cmpgt(m_value, value.m_value)); } - inline void cmpgt_imm(const s32 value) + inline void cmpgt_imm(s32 value) { const VECS32 temp = { value, value, value, value }; m_value = VECS32(vec_cmpgt(m_value, temp)); } - inline void cmpgt_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) + inline void cmpgt_imm_rgba(s32 a, s32 r, s32 g, s32 b) { #ifdef __LITTLE_ENDIAN__ const VECS32 temp = { b, g, r, a }; @@ -545,13 +560,13 @@ public: m_value = VECS32(vec_cmplt(m_value, value.m_value)); } - inline void cmplt_imm(const s32 value) + inline void cmplt_imm(s32 value) { const VECS32 temp = { value, value, value, value }; m_value = VECS32(vec_cmplt(m_value, temp)); } - inline void cmplt_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) + inline void cmplt_imm_rgba(s32 a, s32 r, s32 g, s32 b) { #ifdef __LITTLE_ENDIAN__ const VECS32 temp = { b, g, r, a }; @@ -567,7 +582,7 @@ public: return *this; } - inline rgbaint_t& operator+=(const s32 other) + inline rgbaint_t& operator+=(s32 other) { const VECS32 temp = { other, other, other, other }; m_value = vec_add(m_value, temp); @@ -592,7 +607,7 @@ public: return *this; } - inline rgbaint_t& operator*=(const s32 other) + inline rgbaint_t& operator*=(s32 other) { const VECS32 value = { other, other, other, other }; const VECU32 shift = vec_splat_u32(-16); @@ -605,19 +620,20 @@ public: return *this; } - inline rgbaint_t& operator>>=(const s32 shift) + inline rgbaint_t& operator>>=(s32 shift) { + shift = s32(std::min<u32>(shift, 31)); const VECU32 temp = { u32(shift), u32(shift), u32(shift), u32(shift) }; m_value = vec_sra(m_value, temp); return *this; } - inline void merge_alpha16(const rgbaint_t& alpha) + inline void merge_alpha16(const rgbaint_t &alpha) { m_value = vec_perm(m_value, alpha.m_value, alpha_perm); } - inline void merge_alpha(const rgbaint_t& alpha) + inline void merge_alpha(const rgbaint_t &alpha) { m_value = vec_perm(m_value, alpha.m_value, alpha_perm); } diff --git a/src/emu/xtal.cpp b/src/emu/xtal.cpp index e6d4ab3fe9a..188ed1d46d6 100644 --- a/src/emu/xtal.cpp +++ b/src/emu/xtal.cpp @@ -123,6 +123,7 @@ const double XTAL::known_xtals[] = { 5'185'000, /* 5.185_MHz_XTAL Intel INTELLEC® 4 */ 5'370'000, /* 5.37_MHz_XTAL HP 95LX */ 5'460'000, /* 5.46_MHz_XTAL ec1840 and ec1841 keyboard */ + 5'500'000, /* 5.5_MHz_XTAL Yamaha PSS-480 */ 5'529'600, /* 5.5296_MHz_XTAL Kontron PSI98 keyboard */ 5'626'000, /* 5.626_MHz_XTAL RCA CDP1869 PAL dot clock */ 5'659'200, /* 5.6592_MHz_XTAL Digilog 320 dot clock */ @@ -141,8 +142,9 @@ const double XTAL::known_xtals[] = { 7'000'000, /* 7_MHz_XTAL Jaleco Mega System PCBs */ 7'056'000, /* 7.056_MHz_XTAL Alesis QS FXCHIP (LCM of 44.1 kHz and 48 kHz) */ 7'159'090, /* 7.15909_MHz_XTAL Blood Bros (2x NTSC subcarrier) */ - 7'200'000, /* 7.2_MHz_XTAL Image Fight bootleg I80C031 MCU */ + 7'200'000, /* 7.2_MHz_XTAL Novag Constellation (later models, with /2 divider), Kawai K1 keyscan IC */ 7'372'800, /* 7.3728_MHz_XTAL - */ + 7'680'000, /* 7.68_MHz_XTAL Psion Series 3 */ 7'864'300, /* 7.8643_MHz_XTAL Used on InterFlip games as video clock */ 7'987'000, /* 7.987_MHz_XTAL PC9801-86 YM2608 clock */ 7'995'500, /* 7.9955_MHz_XTAL Used on Electronic Devices Italy Galaxy Gunners sound board */ @@ -162,6 +164,7 @@ const double XTAL::known_xtals[] = { 9'000'000, /* 9_MHz_XTAL Homedata PCBs */ 9'216'000, /* 9.216_MHz_XTAL Univac UTS 20 */ 9'400'000, /* 9.4_MHz_XTAL Yamaha MU-5 and TG-100 */ + 9'426'500, /* 9.4265_MHz_XTAL Yamaha DX7, and DX9 */ 9'600'000, /* 9.6_MHz_XTAL WD37C65 second clock (for 300 KB/sec rate) */ 9'732'000, /* 9.732_MHz_XTAL CTA Invader */ 9'828'000, /* 9.828_MHz_XTAL Universal PCBs */ @@ -176,6 +179,7 @@ const double XTAL::known_xtals[] = { 10'480'000, /* 10.48_MHz_XTAL System-80 (50 Hz) */ 10'500'000, /* 10.5_MHz_XTAL Agat-7 */ 10'595'000, /* 10.595_MHz_XTAL Mad Alien */ + 10'644'000, /* 10.644_MHz_XTAL Northwest Digitial Systems GP-19 */ 10'644'500, /* 10.6445_MHz_XTAL TRS-80 Model I */ 10'687'500, /* 10.6875_MHz_XTAL BBC Bridge Companion */ 10'694'250, /* 10.69425_MHz_XTAL Xerox 820 */ @@ -195,13 +199,16 @@ const double XTAL::known_xtals[] = { 11'289'600, /* 11.2896_MHz_XTAL Frantic Fred */ 11'400'000, /* 11.4_MHz_XTAL HP 9845 */ 11'668'800, /* 11.6688_MHz_XTAL Gameplan pixel clock */ + 11'730'000, /* 11.73_MHz_XTAL Irem M-11 */ 11'800'000, /* 11.8_MHz_XTAL IBM PC Music Feature Card */ 11'980'800, /* 11.9808_MHz_XTAL Luxor ABC 80 */ 12'000'000, /* 12_MHz_XTAL Extremely common, used on 100's of PCBs */ 12'057'600, /* 12.0576_MHz_XTAL Poly 1 (38400 * 314) */ 12'096'000, /* 12.096_MHz_XTAL Some early 80's Atari games */ 12'288'000, /* 12.288_MHz_XTAL Sega Model 3 digital audio board */ + 12'292'000, /* 12.292_MHz_XTAL Northwest Digitial Systems GP-19 */ 12'324'000, /* 12.324_MHz_XTAL Otrona Attache */ + 12'335'600, /* 12.3356_MHz_XTAL RasterOps ColorBoard 264 (~784x NTSC line rate) */ 12'432'000, /* 12.432_MHz_XTAL Kaneko Fly Boy/Fast Freddie Hardware */ 12'472'500, /* 12.4725_MHz_XTAL Bonanza's Mini Boy 7 */ 12'480'000, /* 12.48_MHz_XTAL TRS-80 Model II */ @@ -221,12 +228,15 @@ const double XTAL::known_xtals[] = { 13'495'200, /* 13.4952_MHz_XTAL Used on Shadow Force pcb and maybe other Technos pcbs? */ 13'500'000, /* 13.5_MHz_XTAL Microbee */ 13'516'800, /* 13.5168_MHz_XTAL Kontron KDT6 */ + 13'560'000, /* 13.560_MHz_XTAL Tong Zi Maque */ 13'608'000, /* 13.608_MHz_XTAL TeleVideo 910 & 925 */ 13'824'000, /* 13.824_MHz_XTAL Robotron PC-1715 display circuit */ + 13'977'600, /* 13.9776_MHz_XTAL Kaypro II dot clock */ 14'000'000, /* 14_MHz_XTAL - */ 14'112'000, /* 14.112_MHz_XTAL Timex/Sinclair TS2068 */ 14'192'640, /* 14.19264_MHz_XTAL Central Data 2650 */ 14'218'000, /* 14.218_MHz_XTAL Dragon */ + 14'250'450, /* 14.25045_MHz_XTAL Apple II Europlus */ 14'300'000, /* 14.3_MHz_XTAL Agat-7 */ 14'314'000, /* 14.314_MHz_XTAL Taito TTL Board */ 14'318'181, /* 14.318181_MHz_XTAL Extremely common, used on 100's of PCBs (4x NTSC subcarrier) */ @@ -237,6 +247,7 @@ const double XTAL::known_xtals[] = { 14'742'800, /* 14.7428_MHz_XTAL ADM 23 */ 14'745'000, /* 14.745_MHz_XTAL Synertek KTM-3 */ 14'745'600, /* 14.7456_MHz_XTAL Namco System 12 & System Super 22/23 for JVS */ + 14'746'000, /* 14.746_MHz_XTAL Namco System 10 MGEXIO */ 14'784'000, /* 14.784_MHz_XTAL Zenith Z-29 */ 14'916'000, /* 14.916_MHz_XTAL ADDS Viewpoint 122 */ 14'976'000, /* 14.976_MHz_XTAL CIT-101 80-column display clock */ @@ -249,6 +260,7 @@ const double XTAL::known_xtals[] = { 15'400'000, /* 15.4_MHz_XTAL DVK KSM */ 15'468'480, /* 15.46848_MHz_XTAL Bank Panic h/w, Sega G80 */ 15'582'000, /* 15.582_MHz_XTAL Zentec Zephyr */ + 15'625'000, /* 15.625_MHz_XTAL Zaccaria The Invaders */ 15'667'200, /* 15.6672_MHz_XTAL Apple Macintosh */ 15'700'000, /* 15.7_MHz_XTAL Motogonki */ 15'741'000, /* 15.741_MHz_XTAL DECmate II 80-column display clock */ @@ -269,6 +281,7 @@ const double XTAL::known_xtals[] = { 16'572'000, /* 16.572_MHz_XTAL Micro-Term ACT-5A */ 16'588'800, /* 16.5888_MHz_XTAL SM 7238 */ 16'666'600, /* 16.6666_MHz_XTAL Firebeat GCU */ + 16'667'000, /* 16.667_MHz_XTAL Visual XDS-19P */ 16'669'800, /* 16.6698_MHz_XTAL Qume QVT-102 */ 16'670'000, /* 16.67_MHz_XTAL - */ 16'777'216, /* 16.777216_MHz_XTAL Nintendo Game Boy Advance */ @@ -276,6 +289,7 @@ const double XTAL::known_xtals[] = { 17'010'000, /* 17.01_MHz_XTAL Epic 14E */ 17'064'000, /* 17.064_MHz_XTAL Memorex 1377 */ 17'074'800, /* 17.0748_MHz_XTAL SWTPC 8212 */ + 17'320'000, /* 17.320_MHz_XTAL Visual 50 */ 17'350'000, /* 17.35_MHz_XTAL ITT Courier 1700 */ 17'360'000, /* 17.36_MHz_XTAL OMTI Series 10 SCSI controller */ 17'430'000, /* 17.43_MHz_XTAL Videx Videoterm */ @@ -309,6 +323,7 @@ const double XTAL::known_xtals[] = { 20'000'000, /* 20_MHz_XTAL - */ 20'160'000, /* 20.16_MHz_XTAL Nintendo 8080 */ 20'275'200, /* 20.2752_MHz_XTAL TRS-80 Model III */ + 20'282'000, /* 20.282_MHz_XTAL Northwest Digitial Systems GP-19 */ 20'375'040, /* 20.37504_MHz_XTAL Apple Lisa dot clock (197-0019A) */ 20'625'000, /* 20.625_MHz_XTAL SM 7238 */ 20'790'000, /* 20.79_MHz_XTAL Blockade-hardware Gremlin games */ @@ -331,7 +346,7 @@ const double XTAL::known_xtals[] = { 22'321'000, /* 22.321_MHz_XTAL Apple LaserWriter II NT */ 22'464'000, /* 22.464_MHz_XTAL CIT-101 132-column display clock */ 22'579'000, /* 22.579_MHz_XTAL Sega System H1 SCSP clock */ - 22'579'200, /* 22.5792_MHz_XTAL (44100 * 512) */ + 22'579'200, /* 22.5792_MHz_XTAL Enhanced Apple Digital Sound Chip clock (44100 * 512) */ 22'656'000, /* 22.656_MHz_XTAL Super Pinball Action (~1440x NTSC line rate) */ 22'680'000, /* 22.680_MHz_XTAL HDS200 80-columns display clock */ 22'896'000, /* 22.896_MHz_XTAL DEC VT220 132-column display clock */ @@ -340,6 +355,7 @@ const double XTAL::known_xtals[] = { 23'961'600, /* 23.9616_MHz_XTAL Osborne 4 (Vixen) */ 24'000'000, /* 24_MHz_XTAL Mario, 80's Data East games, 80's Konami games */ 24'073'400, /* 24.0734_MHz_XTAL DEC Rainbow 100 */ + 24'167'829, /* 24.167829_MHz_XTAL Neo Geo AES rev. 3-3 and later (~1536x NTSC line rate) */ 24'270'000, /* 24.27_MHz_XTAL CIT-101XL */ 24'300'000, /* 24.3_MHz_XTAL ADM 36 132-column display clock */ 24'576'000, /* 24.576_MHz_XTAL Pole Position h/w, Model 3 CPU board */ @@ -399,6 +415,7 @@ const double XTAL::known_xtals[] = { 32'256'000, /* 32.256_MHz_XTAL Hitachi MB-6890 */ 32'317'400, /* 32.3174_MHz_XTAL DEC VT330, VT340 */ 32'530'470, /* 32.53047_MHz_XTAL Seta 2 */ + 32'640'000, /* 32.64_MHz_XTAL Vector 4 */ 32'768'000, /* 32.768_MHz_XTAL Roland D-50 audio clock */ 33'000'000, /* 33_MHz_XTAL Sega Model 3 video board */ 33'264'000, /* 33.264_MHz_XTAL Hazeltine 1500 terminal */ |