summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/addrmap.cpp3
-rw-r--r--src/emu/addrmap.h114
-rw-r--r--src/emu/attotime.cpp8
-rw-r--r--src/emu/attotime.h5
-rw-r--r--src/emu/config.cpp7
-rw-r--r--src/emu/debug/debugbuf.cpp41
-rw-r--r--src/emu/debug/debugcmd.cpp1018
-rw-r--r--src/emu/debug/debugcmd.h28
-rw-r--r--src/emu/debug/debugcon.cpp501
-rw-r--r--src/emu/debug/debugcon.h46
-rw-r--r--src/emu/debug/debugcpu.cpp84
-rw-r--r--src/emu/debug/debugcpu.h9
-rw-r--r--src/emu/debug/debughlp.cpp67
-rw-r--r--src/emu/debug/debughlp.h2
-rw-r--r--src/emu/debug/dvmemory.cpp15
-rw-r--r--src/emu/debug/express.cpp24
-rw-r--r--src/emu/debug/express.h16
-rw-r--r--src/emu/devcb.cpp8
-rw-r--r--src/emu/devcb.h454
-rw-r--r--src/emu/devcpu.cpp56
-rw-r--r--src/emu/devcpu.h19
-rw-r--r--src/emu/devdelegate.h284
-rw-r--r--src/emu/devfind.cpp34
-rw-r--r--src/emu/devfind.h105
-rw-r--r--src/emu/device.cpp43
-rw-r--r--src/emu/device.h68
-rw-r--r--src/emu/device.ipp4
-rw-r--r--src/emu/diexec.cpp11
-rw-r--r--src/emu/diexec.h13
-rw-r--r--src/emu/diimage.cpp478
-rw-r--r--src/emu/diimage.h137
-rw-r--r--src/emu/dimemory.cpp3
-rw-r--r--src/emu/dimemory.h39
-rw-r--r--src/emu/dinetwork.cpp76
-rw-r--r--src/emu/dinetwork.h35
-rw-r--r--src/emu/dipty.h2
-rw-r--r--src/emu/dirom.h5
-rw-r--r--src/emu/dirom.ipp9
-rw-r--r--src/emu/dirtc.cpp6
-rw-r--r--src/emu/dirtc.h7
-rw-r--r--src/emu/diserial.cpp40
-rw-r--r--src/emu/diserial.h8
-rw-r--r--src/emu/dislot.cpp10
-rw-r--r--src/emu/dislot.h20
-rw-r--r--src/emu/distate.cpp16
-rw-r--r--src/emu/distate.h17
-rw-r--r--src/emu/divtlb.cpp31
-rw-r--r--src/emu/divtlb.h57
-rw-r--r--src/emu/drawgfxt.ipp33
-rw-r--r--src/emu/drivers/empty.cpp3
-rw-r--r--src/emu/emu.h2
-rw-r--r--src/emu/emucore.cpp4
-rw-r--r--src/emu/emucore.h14
-rw-r--r--src/emu/emufwd.h28
-rw-r--r--src/emu/emumem.cpp32
-rw-r--r--src/emu/emumem.h339
-rw-r--r--src/emu/emumem_aspace.cpp372
-rw-r--r--src/emu/emumem_hea.h4
-rw-r--r--src/emu/emumem_hedp.cpp40
-rw-r--r--src/emu/emumem_hedp.h12
-rw-r--r--src/emu/emumem_hedr.h3
-rw-r--r--src/emu/emumem_hedr.ipp78
-rw-r--r--src/emu/emumem_hedw.h3
-rw-r--r--src/emu/emumem_hedw.ipp74
-rw-r--r--src/emu/emumem_hem.cpp40
-rw-r--r--src/emu/emumem_hem.h12
-rw-r--r--src/emu/emumem_hep.h12
-rw-r--r--src/emu/emumem_het.cpp25
-rw-r--r--src/emu/emumem_het.h14
-rw-r--r--src/emu/emumem_heu.cpp18
-rw-r--r--src/emu/emumem_heu.h6
-rw-r--r--src/emu/emumem_heun.cpp41
-rw-r--r--src/emu/emumem_heun.h12
-rw-r--r--src/emu/emumem_hws.cpp311
-rw-r--r--src/emu/emumem_hws.h162
-rw-r--r--src/emu/emumem_mud.cpp4
-rw-r--r--src/emu/emumem_mud.h2
-rw-r--r--src/emu/emumem_mview.cpp401
-rw-r--r--src/emu/emuopts.cpp114
-rw-r--r--src/emu/emuopts.h3
-rw-r--r--src/emu/fileio.cpp10
-rw-r--r--src/emu/fileio.h2
-rw-r--r--src/emu/gamedrv.h239
-rw-r--r--src/emu/image.cpp46
-rw-r--r--src/emu/inpttype.h353
-rw-r--r--src/emu/inpttype.ipp830
-rw-r--r--src/emu/input.cpp289
-rw-r--r--src/emu/input.h1
-rw-r--r--src/emu/inputdev.cpp223
-rw-r--r--src/emu/inputdev.h38
-rw-r--r--src/emu/ioport.cpp515
-rw-r--r--src/emu/ioport.h344
-rw-r--r--src/emu/layout/dualhovu.lay2
-rw-r--r--src/emu/layout/dualhsxs.lay2
-rw-r--r--src/emu/layout/dualhuov.lay2
-rw-r--r--src/emu/layout/ex800.lay2
-rw-r--r--src/emu/layout/exorterm155.lay2
-rw-r--r--src/emu/layout/hp9122c.lay2
-rw-r--r--src/emu/layout/ie15.lay2
-rw-r--r--src/emu/layout/lx800.lay2
-rw-r--r--src/emu/layout/monitors.lay2
-rw-r--r--src/emu/layout/nes_rob.lay3
-rw-r--r--src/emu/layout/noscreens.lay6
-rw-r--r--src/emu/layout/quadhsxs.lay2
-rw-r--r--src/emu/layout/qx10ascii.lay98
-rw-r--r--src/emu/layout/qx10hasci.lay86
-rw-r--r--src/emu/layout/smartboard.lay75
-rw-r--r--src/emu/layout/triphsxs.lay2
-rw-r--r--src/emu/machine.cpp113
-rw-r--r--src/emu/machine.h11
-rw-r--r--src/emu/main.cpp9
-rw-r--r--src/emu/main.h20
-rw-r--r--src/emu/memarray.cpp4
-rw-r--r--src/emu/network.cpp6
-rw-r--r--src/emu/profiler.cpp10
-rw-r--r--src/emu/profiler.h114
-rw-r--r--src/emu/recording.cpp10
-rw-r--r--src/emu/render.cpp66
-rw-r--r--src/emu/render.h3
-rw-r--r--src/emu/rendersw.hxx17
-rw-r--r--src/emu/rendfont.cpp197
-rw-r--r--src/emu/rendfont.h2
-rw-r--r--src/emu/rendlay.cpp136
-rw-r--r--src/emu/rendlay.h12
-rw-r--r--src/emu/rendutil.cpp234
-rw-r--r--src/emu/rendutil.h10
-rw-r--r--src/emu/romentry.h23
-rw-r--r--src/emu/romload.cpp532
-rw-r--r--src/emu/romload.h72
-rw-r--r--src/emu/save.cpp51
-rw-r--r--src/emu/save.h2
-rw-r--r--src/emu/schedule.cpp15
-rw-r--r--src/emu/schedule.h12
-rw-r--r--src/emu/screen.cpp78
-rw-r--r--src/emu/screen.h4
-rw-r--r--src/emu/softlist.cpp3
-rw-r--r--src/emu/softlist_dev.cpp21
-rw-r--r--src/emu/softlist_dev.h10
-rw-r--r--src/emu/sound.cpp93
-rw-r--r--src/emu/speaker.cpp61
-rw-r--r--src/emu/speaker.h13
-rw-r--r--src/emu/tilemap.cpp48
-rw-r--r--src/emu/uiinput.cpp6
-rw-r--r--src/emu/validity.cpp153
-rw-r--r--src/emu/validity.h2
-rw-r--r--src/emu/video.cpp40
-rw-r--r--src/emu/video.h2
-rw-r--r--src/emu/video/rgbgen.h68
-rw-r--r--src/emu/video/rgbvmx.cpp2
-rw-r--r--src/emu/video/rgbvmx.h102
-rw-r--r--src/emu/xtal.cpp21
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 &regions = 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 &param)
-{
- 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> &param
/* 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> &param
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> &params)
{
+ 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> &params)
{
- /* 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> &para
void debugger_commands::execute_logerror(const std::vector<std::string_view> &params)
{
- /* 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> &params)
{
- /* 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> &params
void debugger_commands::execute_do(const std::vector<std::string_view> &params)
{
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> &params
{
/* 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> &params
{
/* 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> &params)
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> &params)
{
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> &params)
{
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> &param
{
// 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> &para
// 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> &para
// 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> &param
// 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> &param
// 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> &para
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> &para
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> &param
{
// 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> &param
{
// 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> &para
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> &para
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> &params
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> &param
// 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> &param
}
}
}
- 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> &params
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> &params)
{
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> &param
{
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 &param);
- 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> &params);
template <typename T>
void execute_index_command(std::vector<std::string_view> const &params, 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 &regions = 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 &param) 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 &param) 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=" &lt;&lt;"><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=" &lt; "><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=" &gt;"><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=" &gt;&gt;"><color red="0.01" green="0.01" blue="0.01" /></text>
- </element>
+ <element name="text_uiu2a"><text string=" &lt;&lt;"><color red="0.01" green="0.01" blue="0.01" /></text></element>
+ <element name="text_uiu2b"><text string=" &lt; "><color red="0.01" green="0.01" blue="0.01" /></text></element>
+ <element name="text_uiu2c"><text string=" &gt;"><color red="0.01" green="0.01" blue="0.01" /></text></element>
+ <element name="text_uiu2d"><text string=" &gt;&gt;"><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 &region,
+ 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 &region, 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 &region, 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 &region,
+ 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(),
+ [&regiontag] (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 &&region) : 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 &region, const rom_entry *parent_region, const rom_entry *romp);
+ void fill_rom_data(memory_region &region, const rom_entry *romp);
+ void copy_rom_data(memory_region &region, const rom_entry *romp);
+ void process_rom_entries(
+ const std::vector<std::string> &searchpath,
+ u8 bios,
+ memory_region &region,
+ 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 */