summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/addrmap.cpp2
-rw-r--r--src/emu/attotime.h2
-rw-r--r--src/emu/devfind.h30
-rw-r--r--src/emu/device.h295
-rw-r--r--src/emu/disound.cpp34
-rw-r--r--src/emu/distate.cpp2
-rw-r--r--src/emu/driver.cpp10
-rw-r--r--src/emu/driver.h18
-rw-r--r--src/emu/emucore.h2
-rw-r--r--src/emu/render.cpp13
-rw-r--r--src/emu/render.h5
-rw-r--r--src/emu/screen.cpp9
-rw-r--r--src/emu/screen.h196
-rw-r--r--src/emu/xtal.cpp5
14 files changed, 451 insertions, 172 deletions
diff --git a/src/emu/addrmap.cpp b/src/emu/addrmap.cpp
index 968b32e85c6..eca9457e76e 100644
--- a/src/emu/addrmap.cpp
+++ b/src/emu/addrmap.cpp
@@ -1111,7 +1111,7 @@ void address_map::map_validity_check(validity_checker &valid, int spacenum) cons
{
// address map entries that reference regions but are NOPs are pointless
if (entry.m_read.m_type == AMH_NONE && entry.m_write.m_type == AMH_NONE)
- osd_printf_error("%s space references memory region %s, but is AM_NOP\n", spaceconfig.m_name, entry.m_region);
+ osd_printf_error("%s space references memory region %s, but is noprw()\n", spaceconfig.m_name, entry.m_region);
// make sure we can resolve the full path to the region
bool found = false;
diff --git a/src/emu/attotime.h b/src/emu/attotime.h
index c3efeca4ad5..cad95177724 100644
--- a/src/emu/attotime.h
+++ b/src/emu/attotime.h
@@ -369,4 +369,4 @@ inline attotime attotime::from_double(double _time)
}
-#endif // MAME_EMU_ATTOTIME_H
+#endif // MAME_EMU_ATTOTIME_H
diff --git a/src/emu/devfind.h b/src/emu/devfind.h
index 2428e1a7325..b2993bf6361 100644
--- a/src/emu/devfind.h
+++ b/src/emu/devfind.h
@@ -1,13 +1,9 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles, Vas Crabb
-/**
- * \file devfind.h
- * Object auto-discovery helpers
- * \defgroup devfind
- * \{
- * Object auto-discovery helpers
- */
-
+/// \file
+/// \brief Object auto-discovery helpers
+/// \defgroup devfind Object auto-discovery helpers
+/// \{
#ifndef __EMU_H__
#error Dont include this file directly; include emu.h instead.
#endif
@@ -100,8 +96,8 @@ public:
/// int argument.
/// \param [in] start Number to add to element index when
/// calculating values for string format argument.
- /// \arg [in] Optional additional constructor argument(s) passed to
- /// all elements.
+ /// \param [in] arg Optional additional constructor argument(s) passed
+ /// to all elements.
/// \sa util::string_format
template <typename F, typename... Param>
object_array_finder(device_t &base, F const &fmt, unsigned start, Param const &... arg)
@@ -117,8 +113,8 @@ public:
/// \param [in] tags Tags to search for, e.g. { "player", "dips" }.
/// The tags are not copied, it is the caller's responsibility to
/// ensure the pointers remain valid until resolution time.
- /// \arg [in] Optional additional constructor argument(s) passed to
- /// all elements.
+ /// \param [in] arg Optional additional constructor argument(s) passed
+ /// to all elements.
template <typename... Param>
object_array_finder(device_t &base, std::array<char const *, Count> const &tags, Param const &... arg)
: object_array_finder(base, tags, std::make_integer_sequence<unsigned, Count>(), arg...)
@@ -368,9 +364,9 @@ protected:
/// with the requested tag is found, but it doesn't match the
/// desired width.
/// \param [in] width Desired memory share width in bits.
- /// \param [out] bytes Set to memoyr share length in bytes if a
+ /// \param [out] bytes Set to memory share length in bytes if a
/// matching memory share is found, otherwise left unchanged.
- /// \param [in] required. Whether warning message should be printed
+ /// \param [in] required Whether warning message should be printed
/// if a memory share with matching tag of incorrect width is
/// found.
/// \return Pointer to base of memory share if a matching memory
@@ -387,7 +383,7 @@ protected:
/// or a space with the designated number.
/// \param [in] spacenum Address space number.
/// \param [in] width Specific data width, or 0.
- /// \param [in] required. Whether warning message should be printed
+ /// \param [in] required Whether warning message should be printed
/// if a device with no memory interface or space of that number
/// is found.
/// \return Pointer to address space if a matching address space
@@ -400,7 +396,7 @@ protected:
/// found, or false otherwise.
/// \param [in] spacenum Address space number.
/// \param [in] width Specific data width, or 0.
- /// \param [in] required. Whether warning message should be printed
+ /// \param [in] required Whether warning message should be printed
/// if a device with no memory interface or space of that number
/// is found.
/// \return True if the space is optional, or if the space is
@@ -1212,4 +1208,4 @@ extern template class shared_ptr_finder<s64, false>;
extern template class shared_ptr_finder<s64, true>;
#endif // MAME_EMU_DEVFIND_H
-/** \} */
+/// \}
diff --git a/src/emu/device.h b/src/emu/device.h
index fc8da68f65c..257311deb7f 100644
--- a/src/emu/device.h
+++ b/src/emu/device.h
@@ -489,7 +489,34 @@ public:
// device flags
using feature = emu::detail::device_feature;
using feature_type = emu::detail::device_feature::type;
+
+ /// \brief Report unemulated features
+ ///
+ /// Implement this member in a derived class to declare features
+ /// that are not emulated. This will propagate to all other devices
+ /// and systems that use the device. Unemulated features are shown
+ /// in the system selection UI, and cause a red warning to be
+ /// displayed on starting a system.
+ /// \return Bitwise or of the feature constants for unemulated
+ /// features of the device.
+ /// \sa imperfect_features
static constexpr feature_type unemulated_features() { return feature::NONE; }
+
+ /// \brief Report imperfectly emulated features
+ ///
+ /// Implement this member in a derived class to declare features
+ /// that are imperfectly emulated. This will propagate to all other
+ /// devices and systems that use the device. Imperfectly emulated
+ /// features are shown in the system selection UI, and cause a
+ /// yellow warning to be displayed on starting a system (provided
+ /// there are no unemulated features, which take precedence and
+ /// cause the warning to be red).
+ ///
+ /// An exception is imperfectly emulated protection, which results
+ /// in a red warning being displayed when starting a system.
+ /// \return Bitwise or of the feature constants for imperfectly
+ /// emulated features of the device.
+ /// \sa unemulated_features
static constexpr feature_type imperfect_features() { return feature::NONE; }
virtual ~device_t();
@@ -616,15 +643,132 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const;
virtual void device_add_mconfig(machine_config &config);
virtual ioport_constructor device_input_ports() const;
+
+ /// \brief Finalise device configuration
+ ///
+ /// Perform any final configuration tasks after all devices in the
+ /// system have added machine configuration. This is called after
+ /// any #device_interface mix-in interface_config_complete members
+ /// have completed.
+ ///
+ /// Note that automatic object finders will not have been resolved
+ /// at the time this member is called.
virtual void device_config_complete();
+
+ /// \brief Additional device validity checks
+ ///
+ /// Implement this member to provide additional validity checks.
+ /// Report errors using #osd_printf_error and report warnings using
+ /// #osd_printf_warning. The system being validated, device type
+ /// and device tag are collected automatically. Do not throw
+ /// exceptions to report errors.
+ ///
+ /// This provides an opportunity to check that the device has been
+ /// configured correctly. Systems are validated on start, and also
+ /// when the user manually runs a validity check. Validity checks
+ /// are only run for devices configured in runnable systems, not
+ /// when checking that a device can be instantiated in isolation.
+ /// \param [in] valid Reference to the validity checker object
+ /// performing validation (provides some helper member functions).
+ /// \sa device_interface::interface_validity_check
virtual void device_validity_check(validity_checker &valid) const ATTR_COLD;
+
+ /// \brief Resolve objects that may be needed while starting
+ ///
+ /// Implement this member to complete object resolution before any
+ /// devices are started. For example it may be necessary to resolve
+ /// callbacks before any devices start so initial input conditions
+ /// can be set. This is called after all registerd automatic object
+ /// finders are resolved.
virtual void device_resolve_objects() ATTR_COLD;
+
+ /// \brief Device start handler
+ ///
+ /// Implement this member to set up the initial state of the device
+ /// on start. This will be called after all #device_interface
+ // /mix-in interface_pre_start members have completed successfully.
+ /// If the device can't start until another device has completed
+ /// starting, throw a #device_missing_dependencies exception.
+ /// Starting will be postponed until additional devices have been
+ /// started.
+ ///
+ /// If a device's base class is not device_t, it's good practice to
+ /// check start order dependencies (and throw
+ /// #device_missing_dependencies if necessary) before calling the
+ /// base implementation. This will ensure that the base
+ /// implementation won't be called twice if starting needs to be
+ /// postponed.
+ ///
+ /// This is the correct place to register for save states.
+ /// \sa device_reset device_stop
+ /// device_interface::interface_pre_start
+ /// device_interface::interface_post_start
virtual void device_start() ATTR_COLD = 0;
+
+ /// \brief Device stop handler
+ ///
+ /// Implement this member to perform additional tasks on ending an
+ /// emulation session. You may deallocate memory here. This is
+ /// called after interface_pre_stop is called for all
+ /// #device_interface mix-ins, and before interface_post_stop is
+ /// called for any #device_interface mix-ins.
+ /// \sa device_interface::interface_pre_stop
+ /// device_interface::interface_post_stop
virtual void device_stop() ATTR_COLD;
+
+ /// \brief Device reset handler
+ ///
+ /// Implement this member to provide reset behaviour. This is
+ /// called after all #device_interface mix-in interface_pre_reset
+ /// members have completed, and before any child devices are reset.
+ /// All devices are reset at the beginning of an emulation session
+ /// (after all devices have been started), and also when the user
+ /// requests a soft reset (by pressing F3 by default, and also
+ /// available from the debugger).
+ ///
+ /// Note that child devices are reset automatically when a device is
+ /// reset. You should not reset child devices manually from this
+ /// member. If you need to provide additional behaviour after child
+ /// devices are reset, implement #device_reset_after_children.
+ ///
+ /// Only implement warm reset behaviour in this member. Initial
+ /// cold reset conditions should be set up in #device_start.
+ /// \sa device_reset_after_children device_start
+ /// device_interface::interface_pre_reset
+ /// device_interface::interface_post_reset
virtual void device_reset() ATTR_COLD;
+
+ /// \brief Additional reset behaviour after child device reset
+ ///
+ /// Implement this member to provide additional reset behaviour
+ /// after child devices are reset. This is called when resetting a
+ /// device after #device_reset has been called and all child devices
+ /// have been reset, and before any #device_interface mix-in
+ /// interface_post_reset members are called.
+ /// \sa device_reset device_interface::interface_pre_reset
+ /// device_interface::interface_post_reset
virtual void device_reset_after_children() ATTR_COLD;
+
+ /// \brief Prepare for a save state to be written
+ ///
+ /// Implement this member to perform any tasks necessary before any
+ /// registered save state items are recorded. For example it may be
+ /// necessary to flush caches, serialise self-referencing members or
+ /// pointers into data structures. This is called after all
+ /// #device_interface mix-in interface_pre_save members are called.
+ /// \sa device_post_load device_interface::interface_pre_save
virtual void device_pre_save() ATTR_COLD;
+
+ /// \brief Complete save state loading
+ ///
+ /// Implement this member to perform any tasks necessary after
+ /// registered save state items are loaded. For example it may be
+ /// necessary to update or invalidate caches, or de-serialise
+ /// pointers into data structures. This is called after all
+ /// #device_interface mix-in interface_post_load members are called.
+ /// \sa device_pre_save device_interface::interface_post_load
virtual void device_post_load() ATTR_COLD;
+
virtual void device_clock_changed();
virtual void device_debug_setup();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
@@ -677,9 +821,12 @@ private:
};
-// ======================> device_interface
-
-// device_interface represents runtime information for a particular device interface
+/// \brief Device mix-in base
+///
+/// Provides a base for #device_t mix-ins that integrate with the device
+/// lifecycle. Derived classes are used to implement a number of
+/// standard concepts and interfaces, and integrate with the scheduler,
+/// debugger and user interface.
class device_interface
{
DISABLE_COPYING(device_interface);
@@ -701,24 +848,138 @@ public:
device_interface *interface_next() const { return m_interface_next; }
// optional operation overrides
- //
- // WARNING: interface_pre_start must be callable multiple times in
- // case another interface throws a missing dependency. In
- // particular, state saving registrations should be done in post.
+
+ /// \brief Finalise mix-in configuration
+ ///
+ /// Perform any final configuration tasks after all devices in the
+ /// system have added machine configuration. This is called before
+ /// device_config_complete is called for the device.
+ ///
+ /// Note that automatic object finders will not have been resolved
+ /// at this time.
+ /// \sa device_t::device_config_complete
virtual void interface_config_complete();
- virtual void interface_validity_check(validity_checker &valid) const;
- virtual void interface_pre_start();
- virtual void interface_post_start();
- virtual void interface_pre_reset();
- virtual void interface_post_reset();
- virtual void interface_pre_stop();
- virtual void interface_post_stop();
- virtual void interface_pre_save();
- virtual void interface_post_load();
+
+ /// \brief Additional mix-in validity checks
+ ///
+ /// Implement this member to provide additional validity checks.
+ /// Report errors using #osd_printf_error and report warnings using
+ /// #osd_printf_warning. The system being validated, device type
+ /// and device tag are collected automatically. Do not throw
+ /// exceptions to report errors.
+ ///
+ /// This provides an opportunity to check that the mix-in has been
+ /// configured correctly. Systems are validated on start, and also
+ /// when the user manually runs a validity check. Validity checks
+ /// are only run for devices configured in runnable systems, not
+ /// when checking that a device can be instantiated in isolation.
+ /// \param [in] valid Reference to the validity checker object
+ /// performing validation (provides some helper member functions).
+ /// \sa device_t::device_validity_check
+ virtual void interface_validity_check(validity_checker &valid) const ATTR_COLD;
+
+ /// \brief Mix-in start handler
+ ///
+ /// Implement this member to set up the initial state of the mix-in
+ /// on start. This is called before the device_start member is
+ /// called for the device. If the mix-in can't be started until
+ /// another device has started, throw a #device_missing_dependencies
+ /// exception. Starting will be postponed until additional devices
+ /// have been started.
+ ///
+ /// Note that this member may be called multiple times if another
+ /// device_interface mix-in throws a #device_missing_dependencies
+ /// exception from its interface_pre_start member, or if the device
+ /// throws a #device_missing_dependencies exception from its
+ /// device_start member. You must check to ensure that operations
+ /// like resource allocation are not performed multiple times, or
+ /// postpone them until #interface_post_start is called.
+ ///
+ /// It's simpler to register for save states when
+ /// #interface_post_start is called.
+ /// \sa interface_post_start device_t::device_start
+ virtual void interface_pre_start() ATTR_COLD;
+
+ /// \brief Mix-in start completion handler
+ ///
+ /// Implement this member to complete mix-in start-up. This is
+ /// called after #interface_pre_start is called for all
+ /// device_interface mix-ins, and after device_start is called for
+ /// the device. This member will only be called once, it will not
+ /// be called multiple times if device starting is postponed.
+ ///
+ /// This member must not throw #device_missing_dependencies (start
+ /// order dependencies should be checked in #interface_pre_start).
+ /// This is the appropriate place to allocate resources like
+ /// timers and register for save states.
+ /// \sa interface_pre_start device_t::device_start
+ virtual void interface_post_start() ATTR_COLD;
+
+ /// \brief Mix-in reset handler
+ ///
+ /// Implement this member to provide reset behaviour. This is
+ /// called before device_reset is called for the device, and before
+ /// any child devices are reset. Only implement warm reset
+ /// behaviour in this member. Initial cold reset conditions should
+ /// be set up in #interface_pre_start and/or #interface_post_start.
+ /// If you need to provide additional behaviour after child devices
+ /// are reset, implement #interface_post_reset.
+ /// \sa interface_post_reset device_t::device_reset
+ virtual void interface_pre_reset() ATTR_COLD;
+
+ /// \brief Mix-in reset completion handler
+ ///
+ /// Implement this member to provide additional reset behaviour
+ /// after child devices are reset. This is called after
+ /// device_reset_after_children has been called for the device.
+ /// \sa interface_pre_reset device_t::device_reset
+ /// device_t::device_reset_after_children
+ virtual void interface_post_reset() ATTR_COLD;
+
+ /// \brief Mix-in stop handler
+ ///
+ /// Implement this member to perform additional tasks on ending an
+ /// emulation session. Do not deallocate anything that may need to
+ /// be referenced from another device_interface mix-in's
+ /// interface_pre_stop member or from the device's device_stop
+ /// member. This is called before device_stop is called for the
+ /// device.
+ /// \sa interface_post_stop device_t::device_stop
+ virtual void interface_pre_stop() ATTR_COLD;
+
+ /// \brief Mix-in stop completion handler
+ ///
+ /// Implement this member to perform additional tasks on ending an
+ /// emulation session after the device is stopped. You can
+ /// deallocate memory here. This is called after device_stop is
+ /// called for the device.
+ /// \sa interface_pre_stop device_t::device_stop
+ virtual void interface_post_stop() ATTR_COLD;
+
+ /// \brief Prepare for a save state to be written
+ ///
+ /// Implement this member to perform any tasks necessary before any
+ /// registered save state items are recorded. For example it may be
+ /// necessary to flush caches, serialise self-referencing members or
+ /// pointers into data structures. This is called before
+ /// device_pre_save is called for the device.
+ /// \sa interface_post_load device_t::device_pre_save
+ virtual void interface_pre_save() ATTR_COLD;
+
+ /// \brief Complete save state loading
+ ///
+ /// Implement this member to perform any tasks necessary after
+ /// registered save state items are loaded. For example it may be
+ /// necessary to update or invalidate caches, or de-serialise
+ /// pointers into data structures. This is called before
+ /// device_post_load is called for the device.
+ /// \sa interface_pre_save device_t::device_post_load
+ virtual void interface_post_load() ATTR_COLD;
+
virtual void interface_clock_changed();
virtual void interface_debug_setup();
-protected:
+private:
// internal state
device_interface * m_interface_next;
device_t & m_device;
diff --git a/src/emu/disound.cpp b/src/emu/disound.cpp
index f3ab6b236f7..a8a0a55ad38 100644
--- a/src/emu/disound.cpp
+++ b/src/emu/disound.cpp
@@ -85,8 +85,8 @@ int device_sound_interface::inputs() const
{
// scan the list counting streams we own and summing their inputs
int inputs = 0;
- for (auto &stream : m_device.machine().sound().streams())
- if (&stream->device() == &m_device)
+ for (auto &stream : device().machine().sound().streams())
+ if (&stream->device() == &device())
inputs += stream->input_count();
return inputs;
}
@@ -101,8 +101,8 @@ int device_sound_interface::outputs() const
{
// scan the list counting streams we own and summing their outputs
int outputs = 0;
- for (auto &stream : m_device.machine().sound().streams())
- if (&stream->device() == &m_device)
+ for (auto &stream : device().machine().sound().streams())
+ if (&stream->device() == &device())
outputs += stream->output_count();
return outputs;
}
@@ -119,8 +119,8 @@ sound_stream *device_sound_interface::input_to_stream_input(int inputnum, int &s
assert(inputnum >= 0);
// scan the list looking for streams owned by this device
- for (auto &stream : m_device.machine().sound().streams())
- if (&stream->device() == &m_device)
+ for (auto &stream : device().machine().sound().streams())
+ if (&stream->device() == &device())
{
if (inputnum < stream->input_count())
{
@@ -146,7 +146,7 @@ sound_stream *device_sound_interface::output_to_stream_output(int outputnum, int
assert(outputnum >= 0);
// scan the list looking for streams owned by this device
- for (auto &stream : m_device.machine().sound().streams())
+ for (auto &stream : device().machine().sound().streams())
if (&stream->device() == &device())
{
if (outputnum < stream->output_count())
@@ -212,7 +212,7 @@ void device_sound_interface::set_output_gain(int outputnum, float gain)
// handle ALL_OUTPUTS as a special case
if (outputnum == ALL_OUTPUTS)
{
- for (auto &stream : m_device.machine().sound().streams())
+ for (auto &stream : device().machine().sound().streams())
if (&stream->device() == &device())
for (int num = 0; num < stream->output_count(); num++)
stream->set_output_gain(num, gain);
@@ -237,7 +237,7 @@ void device_sound_interface::set_output_gain(int outputnum, float gain)
int device_sound_interface::inputnum_from_device(device_t &source_device, int outputnum) const
{
int overall = 0;
- for (auto &stream : m_device.machine().sound().streams())
+ for (auto &stream : device().machine().sound().streams())
if (&stream->device() == &device())
for (int inputnum = 0; inputnum < stream->input_count(); inputnum++, overall++)
if (stream->input_source_device(inputnum) == &source_device && stream->input_source_outputnum(inputnum) == outputnum)
@@ -278,7 +278,7 @@ void device_sound_interface::interface_validity_check(validity_checker &valid) c
void device_sound_interface::interface_pre_start()
{
// scan all the sound devices
- sound_interface_iterator iter(m_device.machine().root_device());
+ sound_interface_iterator iter(device().machine().root_device());
for (device_sound_interface const &sound : iter)
{
// scan each route on the device
@@ -286,7 +286,7 @@ void device_sound_interface::interface_pre_start()
{
// see if we are the target of this route; if we are, make sure the source device is started
device_t *const target_device = route.m_base.get().subdevice(route.m_target.c_str());
- if ((target_device == &m_device) && !sound.device().started())
+ if ((target_device == &device()) && !sound.device().started())
throw device_missing_dependencies();
}
}
@@ -300,7 +300,7 @@ void device_sound_interface::interface_pre_start()
{
// see if we are the target of this route
device_t *const target_device = route.m_base.get().subdevice(route.m_target.c_str());
- if ((target_device == &m_device) && (route.m_input == AUTO_ALLOC_INPUT))
+ if ((target_device == &device()) && (route.m_input == AUTO_ALLOC_INPUT))
{
route.m_input = m_auto_allocated_inputs;
m_auto_allocated_inputs += (route.m_output == ALL_OUTPUTS) ? sound.outputs() : 1;
@@ -318,14 +318,14 @@ void device_sound_interface::interface_pre_start()
void device_sound_interface::interface_post_start()
{
// iterate over all the sound devices
- for (device_sound_interface &sound : sound_interface_iterator(m_device.machine().root_device()))
+ for (device_sound_interface &sound : sound_interface_iterator(device().machine().root_device()))
{
// scan each route on the device
for (sound_route const &route : sound.routes())
{
// if we are the target of this route, hook it up
device_t *const target_device = route.m_base.get().subdevice(route.m_target.c_str());
- if (target_device == &m_device)
+ if (target_device == &device())
{
// iterate over all outputs, matching any that apply
int inputnum = route.m_input;
@@ -343,7 +343,7 @@ void device_sound_interface::interface_post_start()
int streaminputnum;
sound_stream *const inputstream = input_to_stream_input(inputnum++, streaminputnum);
if (!inputstream)
- fatalerror("Sound device '%s' targeted output #%d to nonexistent device '%s' input %d\n", sound.device().tag(), outputnum, m_device.tag(), inputnum - 1);
+ fatalerror("Sound device '%s' targeted output #%d to nonexistent device '%s' input %d\n", sound.device().tag(), outputnum, device().tag(), inputnum - 1);
// set the input
inputstream->set_input(streaminputnum, outputstream, streamoutputnum, route.m_gain);
@@ -362,7 +362,7 @@ void device_sound_interface::interface_post_start()
void device_sound_interface::interface_pre_reset()
{
// update all streams on this device prior to reset
- for (auto &stream : m_device.machine().sound().streams())
+ for (auto &stream : device().machine().sound().streams())
if (&stream->device() == &device())
stream->update();
}
@@ -415,7 +415,7 @@ void device_mixer_interface::interface_pre_start()
m_outputmap.resize(m_auto_allocated_inputs);
// iterate through all routes that point to us and note their mixer output
- for (device_sound_interface const &sound : sound_interface_iterator(m_device.machine().root_device()))
+ for (device_sound_interface const &sound : sound_interface_iterator(device().machine().root_device()))
{
for (sound_route const &route : sound.routes())
{
diff --git a/src/emu/distate.cpp b/src/emu/distate.cpp
index 2dcf4301ac4..b96d3c6aad3 100644
--- a/src/emu/distate.cpp
+++ b/src/emu/distate.cpp
@@ -624,7 +624,7 @@ void device_state_interface::interface_post_start()
{
// make sure we got something during startup
if (m_state_list.size() == 0)
- throw emu_fatalerror("No state registered for device '%s' that supports it!", m_device.tag());
+ throw emu_fatalerror("No state registered for device '%s' that supports it!", device().tag());
}
diff --git a/src/emu/driver.cpp b/src/emu/driver.cpp
index 8dde7622da6..d13a4899136 100644
--- a/src/emu/driver.cpp
+++ b/src/emu/driver.cpp
@@ -236,10 +236,7 @@ void driver_device::device_start()
else
machine_start();
- if (!m_callbacks[CB_SOUND_START].isnull())
- m_callbacks[CB_SOUND_START]();
- else
- sound_start();
+ sound_start();
if (!m_callbacks[CB_VIDEO_START].isnull())
m_callbacks[CB_VIDEO_START]();
@@ -268,10 +265,7 @@ void driver_device::device_reset_after_children()
else
machine_reset();
- if (!m_callbacks[CB_SOUND_RESET].isnull())
- m_callbacks[CB_SOUND_RESET]();
- else
- sound_reset();
+ sound_reset();
if (!m_callbacks[CB_VIDEO_RESET].isnull())
m_callbacks[CB_VIDEO_RESET]();
diff --git a/src/emu/driver.h b/src/emu/driver.h
index 4f6576aa737..0a92151d07c 100644
--- a/src/emu/driver.h
+++ b/src/emu/driver.h
@@ -32,13 +32,6 @@
#define MCFG_MACHINE_RESET_REMOVE() \
driver_device::static_set_callback(config.root_device(), driver_device::CB_MACHINE_RESET, driver_callback_delegate());
-// core sound callbacks
-#define MCFG_SOUND_START_OVERRIDE(_class, _func) \
- driver_device::static_set_callback(config.root_device(), driver_device::CB_SOUND_START, driver_callback_delegate(&_class::SOUND_START_NAME(_func), this));
-
-#define MCFG_SOUND_RESET_OVERRIDE(_class, _func) \
- driver_device::static_set_callback(config.root_device(), driver_device::CB_SOUND_RESET, driver_callback_delegate(&_class::SOUND_RESET_NAME(_func), this));
-
// core video callbacks
#define MCFG_VIDEO_START_OVERRIDE(_class, _func) \
@@ -63,15 +56,6 @@
#define DECLARE_MACHINE_RESET(name) void MACHINE_RESET_NAME(name)()
#define MACHINE_RESET_MEMBER(cls,name) void cls::MACHINE_RESET_NAME(name)()
-#define SOUND_START_NAME(name) sound_start_##name
-#define DECLARE_SOUND_START(name) void SOUND_START_NAME(name)() ATTR_COLD
-#define SOUND_START_MEMBER(cls,name) void cls::SOUND_START_NAME(name)()
-
-#define SOUND_RESET_NAME(name) sound_reset_##name
-#define SOUND_RESET_CALL_MEMBER(name) SOUND_RESET_NAME(name)()
-#define DECLARE_SOUND_RESET(name) void SOUND_RESET_NAME(name)()
-#define SOUND_RESET_MEMBER(cls,name) void cls::SOUND_RESET_NAME(name)()
-
#define VIDEO_START_NAME(name) video_start_##name
#define VIDEO_START_CALL_MEMBER(name) VIDEO_START_NAME(name)()
#define DECLARE_VIDEO_START(name) void VIDEO_START_NAME(name)() ATTR_COLD
@@ -110,8 +94,6 @@ public:
{
CB_MACHINE_START,
CB_MACHINE_RESET,
- CB_SOUND_START,
- CB_SOUND_RESET,
CB_VIDEO_START,
CB_VIDEO_RESET,
CB_COUNT
diff --git a/src/emu/emucore.h b/src/emu/emucore.h
index 4c8b9c96056..92135e7ae84 100644
--- a/src/emu/emucore.h
+++ b/src/emu/emucore.h
@@ -373,4 +373,4 @@ inline u64 d2u(double d)
return u.vv;
}
-#endif /* MAME_EMU_EMUCORE_H */
+#endif // MAME_EMU_EMUCORE_H
diff --git a/src/emu/render.cpp b/src/emu/render.cpp
index 58d2c2961c9..0c598345ea1 100644
--- a/src/emu/render.cpp
+++ b/src/emu/render.cpp
@@ -496,7 +496,7 @@ void render_texture::get_scaled(u32 dwidth, u32 dheight, render_texinfo &texinfo
// palette for a texture
//-------------------------------------------------
-const rgb_t *render_texture::get_adjusted_palette(render_container &container)
+const rgb_t *render_texture::get_adjusted_palette(render_container &container, u32 &out_length)
{
// override the palette with our adjusted palette
switch (m_format)
@@ -506,7 +506,7 @@ const rgb_t *render_texture::get_adjusted_palette(render_container &container)
assert(m_bitmap->palette() != nullptr);
// return our adjusted palette
- return container.bcg_lookup_table(m_format, m_bitmap->palette());
+ return container.bcg_lookup_table(m_format, out_length, m_bitmap->palette());
case TEXFORMAT_RGB32:
case TEXFORMAT_ARGB32:
@@ -515,7 +515,7 @@ const rgb_t *render_texture::get_adjusted_palette(render_container &container)
// if no adjustment necessary, return nullptr
if (!container.has_brightness_contrast_gamma_changes())
return nullptr;
- return container.bcg_lookup_table(m_format);
+ return container.bcg_lookup_table(m_format, out_length);
default:
assert(false);
@@ -679,7 +679,7 @@ float render_container::apply_brightness_contrast_gamma_fp(float value)
// given texture mode
//-------------------------------------------------
-const rgb_t *render_container::bcg_lookup_table(int texformat, palette_t *palette)
+const rgb_t *render_container::bcg_lookup_table(int texformat, u32 &out_length, palette_t *palette)
{
switch (texformat)
{
@@ -691,14 +691,17 @@ const rgb_t *render_container::bcg_lookup_table(int texformat, palette_t *palett
recompute_lookups();
}
assert (palette == &m_palclient->palette());
+ out_length = palette->max_index();
return &m_bcglookup[0];
case TEXFORMAT_RGB32:
case TEXFORMAT_ARGB32:
case TEXFORMAT_YUY16:
+ out_length = 256;
return m_bcglookup256;
default:
+ out_length = 0;
return nullptr;
}
}
@@ -2267,7 +2270,7 @@ void render_target::add_container_primitives(render_primitive_list &list, const
curitem.texture()->get_scaled(width, height, prim->texture, list, curitem.flags());
// set the palette
- prim->texture.palette = curitem.texture()->get_adjusted_palette(container);
+ prim->texture.palette = curitem.texture()->get_adjusted_palette(container, prim->texture.palette_length);
// determine UV coordinates
prim->texcoords = oriented_texcoords[finalorient];
diff --git a/src/emu/render.h b/src/emu/render.h
index 0d70dc7684b..b9706907aed 100644
--- a/src/emu/render.h
+++ b/src/emu/render.h
@@ -218,6 +218,7 @@ struct render_texinfo
u64 unique_id; // unique identifier to pass to osd
u64 old_id; // previously allocated id, if applicable
const rgb_t * palette; // palette for PALETTE16 textures, bcg lookup table for RGB32/YUY16
+ u32 palette_length;
};
@@ -436,7 +437,7 @@ public:
private:
// internal helpers
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);
+ const rgb_t *get_adjusted_palette(render_container &container, u32 &out_length);
static const int MAX_TEXTURE_SCALES = 16;
@@ -527,7 +528,7 @@ public:
bool has_brightness_contrast_gamma_changes() const { return (m_user.m_brightness != 1.0f || m_user.m_contrast != 1.0f || m_user.m_gamma != 1.0f); }
u8 apply_brightness_contrast_gamma(u8 value);
float apply_brightness_contrast_gamma_fp(float value);
- const rgb_t *bcg_lookup_table(int texformat, palette_t *palette = nullptr);
+ const rgb_t *bcg_lookup_table(int texformat, u32 &out_length, palette_t *palette = nullptr);
private:
// an item describes a high level primitive that is added to a container
diff --git a/src/emu/screen.cpp b/src/emu/screen.cpp
index 835e12995f5..db6f7c91ad4 100644
--- a/src/emu/screen.cpp
+++ b/src/emu/screen.cpp
@@ -546,7 +546,7 @@ screen_device::screen_device(const machine_config &mconfig, const char *tag, dev
, m_scanline_cb(*this)
, m_palette(*this, finder_base::DUMMY_TAG)
, m_video_attributes(0)
- , m_svg_region(tag)
+ , m_svg_region(*this, DEVICE_SELF)
, m_container(nullptr)
, m_width(100)
, m_height(100)
@@ -717,10 +717,9 @@ void screen_device::device_start()
if (m_type == SCREEN_TYPE_SVG)
{
- memory_region *reg = owner()->memregion(m_svg_region);
- if (!reg)
- fatalerror("%s: SVG region \"%s\" does not exist\n", tag(), m_svg_region);
- m_svg = std::make_unique<svg_renderer>(reg);
+ if (!m_svg_region)
+ fatalerror("%s: SVG region \"%s\" does not exist\n", tag(), m_svg_region.finder_tag());
+ m_svg = std::make_unique<svg_renderer>(m_svg_region);
machine().output().set_notifier(nullptr, svg_renderer::output_notifier, m_svg.get());
// don't do this - SVG units are arbitrary and interpreting them as pixels causes bad things to happen
diff --git a/src/emu/screen.h b/src/emu/screen.h
index 0ae11f85b9b..6754d66f071 100644
--- a/src/emu/screen.h
+++ b/src/emu/screen.h
@@ -207,7 +207,24 @@ public:
void set_orientation(int orientation) { assert(!configured()); m_orientation = orientation; }
void set_physical_aspect(unsigned x, unsigned y) { assert(!configured()); m_phys_aspect = std::make_pair(x, y); }
void set_native_aspect() { assert(!configured()); m_phys_aspect = std::make_pair(~0U, ~0U); }
- void set_raw(u32 pixclock, u16 htotal, u16 hbend, u16 hbstart, u16 vtotal, u16 vbend, u16 vbstart)
+
+ /// \brief Configure screen parameters
+ ///
+ /// \param [in] pixclock Pixel clock frequency in Hertz.
+ /// \param [in] htotal Total pixel clocks per line, including
+ /// horizontal blanking period.
+ /// \param [in] hbend Index of first visible pixel after horizontal
+ /// blanking period ends.
+ /// \param [in] hbstart Index of first pixel in horzontal blanking
+ /// period after visible pixels.
+ /// \param [in] vtotal Total lines per frame, including vertical
+ /// blanking period.
+ /// \param [in] vbend Index of first visible line after vertical
+ /// blanking period ends.
+ /// \param [in] vbstart Index of first line in vertical blanking
+ /// period after visible lines.
+ /// \return Reference to device for method chaining.
+ screen_device &set_raw(u32 pixclock, u16 htotal, u16 hbend, u16 hbstart, u16 vtotal, u16 vbend, u16 vbstart)
{
assert(pixclock != 0);
m_clock = pixclock;
@@ -216,15 +233,101 @@ public:
m_width = htotal;
m_height = vtotal;
m_visarea.set(hbend, hbstart - 1, vbend, vbstart - 1);
+ return *this;
+ }
+ screen_device &set_raw(const XTAL &xtal, u16 htotal, u16 hbend, u16 hbstart, u16 vtotal, u16 vbend, u16 vbstart)
+ {
+ xtal.validate(std::string("Configuring screen ") + tag());
+ return set_raw(xtal.value(), htotal, hbend, hbstart, vtotal, vbend, vbstart);
}
- void set_raw(const XTAL &xtal, u16 htotal, u16 hbend, u16 hbstart, u16 vtotal, u16 vbend, u16 vbstart) { set_raw(xtal.value(), htotal, hbend, hbstart, vtotal, vbend, vbstart); }
void set_refresh(attoseconds_t rate) { m_refresh = rate; }
- template <typename T> void set_refresh_hz(T &&hz) { set_refresh(HZ_TO_ATTOSECONDS(std::forward<T>(hz))); }
- void set_vblank_time(attoseconds_t time) { m_vblank = time; m_oldstyle_vblank_supplied = true; }
- void set_size(u16 width, u16 height) { m_width = width; m_height = height; }
- void set_visarea(s16 minx, s16 maxx, s16 miny, s16 maxy) { m_visarea.set(minx, maxx, miny, maxy); }
- void set_visarea_full() { m_visarea.set(0, m_width - 1, 0, m_height - 1); } // call after set_size
- void set_default_position(double xscale, double xoffs, double yscale, double yoffs) {
+
+ /// \brief Set refresh rate in Hertz
+ ///
+ /// Sets refresh rate in Hertz (frames per second). Used in
+ /// conjunction with #set_vblank_time, #set_size and #set_visarea.
+ /// For raster displays, please use #set_raw to configure screen
+ /// parameters in terms of pixel clock.
+ /// \param [in] hz Desired refresh rate.
+ /// \return Reference to device for method chaining.
+ template <typename T> screen_device &set_refresh_hz(T &&hz)
+ {
+ set_refresh(HZ_TO_ATTOSECONDS(std::forward<T>(hz)));
+ return *this;
+ }
+
+ /// \brief Set vertical blanking interval time
+ ///
+ /// Sets vertical blanking interval period. Used in conjunction
+ /// with #set_refresh_hz, #set_size and #set_visarea. For raster
+ /// displays, please use #set_raw to configure screen parameters in
+ /// terms of pixel clock.
+ /// \param [in] time Length of vertical blanking interval.
+ /// \return Reference to device for method chaining.
+ screen_device &set_vblank_time(attoseconds_t time)
+ {
+ m_vblank = time;
+ m_oldstyle_vblank_supplied = true;
+ return *this;
+ }
+
+ /// \brief Set total screen size
+ ///
+ /// Set the total screen size in pixels, including blanking areas if
+ /// applicable. This sets the size of the screen bitmap. Used in
+ /// conjunction with #set_refresh_hz, #set_vblank_time and
+ /// #set_visarea. For raster displays, please use #set_raw to
+ /// configure screen parameters in terms of pixel clock.
+ /// \param [in] width Total width in pixels, including horizontal
+ /// blanking period if applicable.
+ /// \param [in] height Total height in lines, including vertical
+ /// blanking period if applicable.
+ /// \return Reference to device for method chaining.
+ screen_device &set_size(u16 width, u16 height)
+ {
+ m_width = width;
+ m_height = height;
+ return *this;
+ }
+
+ /// \brief Set visible screen area
+ ///
+ /// Set visible screen area. This should fit within the total
+ /// screen area. Used in conjunction with #set_refresh_hz,
+ /// #set_vblank_time and #set_size. For raster displays, please
+ /// use #set_raw to configure screen parameters in terms of pixel
+ /// clock.
+ /// \param [in] minx First visible pixel index after horizontal
+ /// blanking period ends.
+ /// \param [in] maxx Last visible pixel index before horizontal
+ /// blanking period starts.
+ /// \param [in] miny First visible line index after vertical
+ /// blanking period ends.
+ /// \param [in] maxy Last visible line index before vertical
+ /// blanking period starts.
+ /// \return Reference to device for method chaining.
+ screen_device &set_visarea(s16 minx, s16 maxx, s16 miny, s16 maxy)
+ {
+ m_visarea.set(minx, maxx, miny, maxy);
+ return *this;
+ }
+
+ /// \brief Set visible area to full area
+ ///
+ /// Set visible screen area to the full screen area (i.e. noi
+ /// horizontal or vertical blanking period). This is generally not
+ /// possible for raster displays, but is useful for other display
+ /// simulations. Must be called after calling #set_size.
+ /// \return Reference to device for method chaining.
+ /// \sa set_visarea
+ screen_device &set_visarea_full()
+ {
+ m_visarea.set(0, m_width - 1, 0, m_height - 1);
+ return *this;
+ }
+
+ void set_default_position(double xscale, double xoffs, double yscale, double yoffs)
+ {
m_xscale = xscale;
m_xoffset = xoffs;
m_yscale = yscale;
@@ -265,10 +368,11 @@ public:
auto screen_vblank() { return m_screen_vblank.bind(); }
auto scanline() { m_video_attributes |= VIDEO_UPDATE_SCANLINE; return m_scanline_cb.bind(); }
- template<typename T> void set_palette(T &&tag) { m_palette.set_tag(std::forward<T>(tag)); }
- void set_video_attributes(u32 flags) { m_video_attributes = flags; }
- void set_color(rgb_t color) { m_color = color; }
- void set_svg_region(const char *region) { m_svg_region = region; } // default region is device tag
+ template <typename T> screen_device &set_palette(T &&tag) { m_palette.set_tag(std::forward<T>(tag)); return *this; }
+ screen_device &set_no_palette() { m_palette.set_tag(finder_base::DUMMY_TAG); return *this; }
+ screen_device &set_video_attributes(u32 flags) { m_video_attributes = flags; return *this; }
+ screen_device &set_color(rgb_t color) { m_color = color; return *this; }
+ template <typename T> screen_device &set_svg_region(T &&tag) { m_svg_region.set_tag(std::forward<T>(tag)); return *this; } // default region is device tag
// information getters
render_container &container() const { assert(m_container != nullptr); return *m_container; }
@@ -365,7 +469,7 @@ private:
devcb_write32 m_scanline_cb; // screen scanline callback
optional_device<device_palette_interface> m_palette; // our palette
u32 m_video_attributes; // flags describing the video system
- const char * m_svg_region; // the region in which the svg data is in
+ optional_memory_region m_svg_region; // the region in which the svg data is in
// internal state
render_container * m_container; // pointer to our container
@@ -445,72 +549,6 @@ typedef device_type_iterator<screen_device> screen_device_iterator;
@def set_type
Modify the screen device type
@see screen_type_enum
-
- @def set_raw
- Configures screen parameters for the given screen.
- @remark It's better than using @see set_refresh_hz and @see set_vblank_time but still not enough.
-
- @param _pixclock
- Pixel Clock frequency value
-
- @param _htotal
- Total number of horizontal pixels, including hblank period.
-
- @param _hbend
- Horizontal pixel position for HBlank end event, also first pixel where screen rectangle is visible.
-
- @param _hbstart
- Horizontal pixel position for HBlank start event, also last pixel where screen rectangle is visible.
-
- @param _vtotal
- Total number of vertical pixels, including vblank period.
-
- @param _vbend
- Vertical pixel position for VBlank end event, also first pixel where screen rectangle is visible.
-
- @param _vbstart
- Vertical pixel position for VBlank start event, also last pixel where screen rectangle is visible.
-
- @def set_refresh_hz
- Sets the number of Frames Per Second for this screen
- @remarks Please use @see set_raw instead. Gives imprecise timings.
-
- @param _rate
- FPS number
-
- @def set_vblank_time
- Sets the vblank time of the given screen
- @remarks Please use @see MCFG_SCREEN_RAW_PARAMS instead. Gives imprecise timings.
-
- @param _time
- Time parameter, in attotime value
-
- @def set_size
- Sets total screen size, including H/V-Blanks
- @remarks Please use @see set_raw instead. Gives imprecise timings.
-
- @param _width
- Screen horizontal size
-
- @param _height
- Screen vertical size
-
- @def set_visarea
- Sets screen visible area
- @remarks Please use @see set_raw instead. Gives imprecise timings.
-
- @param _minx
- Screen left border
-
- @param _maxx
- Screen right border, must be in N-1 format
-
- @param _miny
- Screen top border
-
- @param _maxx
- Screen bottom border, must be in N-1 format
-
@}
*/
diff --git a/src/emu/xtal.cpp b/src/emu/xtal.cpp
index 172b032fe4d..c83af7fb2c5 100644
--- a/src/emu/xtal.cpp
+++ b/src/emu/xtal.cpp
@@ -243,6 +243,7 @@ const double XTAL::known_xtals[] = {
16'934'400, /* 16.9344_MHz_XTAL Usually used to drive 90's Yamaha OPL/FM chips (44100 * 384) */
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'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 */
@@ -259,6 +260,7 @@ const double XTAL::known_xtals[] = {
18'720'000, /* 18.72_MHz_XTAL Nokia MikroMikko 1 */
18'867'000, /* 18.867_MHz_XTAL Decision Data IS-482 */
18'869'600, /* 18.8696_MHz_XTAL Memorex 2178 */
+ 19'170'000, /* 19.17_MHz_XTAL Ericsson ISA8 Monochrome HR Graphics Board */
19'339'600, /* 19.3396_MHz_XTAL TeleVideo TVI-955 80-column display clock */
19'584'000, /* 19.584_MHz_XTAL ADM-42 */
19'600'000, /* 19.6_MHz_XTAL Universal Mr. Do - Model 8021 PCB */
@@ -331,9 +333,11 @@ const double XTAL::known_xtals[] = {
29'491'200, /* 29.4912_MHz_XTAL Xerox Alto-II system clock (tagged 29.4MHz in the schematics) */
30'000'000, /* 30_MHz_XTAL Impera Magic Card */
30'209'800, /* 30.2098_MHz_XTAL Philips CD-i NTSC (1920x NTSC line rate) */
+ 30'240'000, /* 30.24_MHz_XTAL Macintosh IIci RBV, 12- or 13-inch display */
30'476'180, /* 30.47618_MHz_XTAL Taito F3, JC, Under Fire */
30'800'000, /* 30.8_MHz_XTAL 15IE-00-013 */
31'279'500, /* 31.2795_MHz_XTAL Wyse WY-30+ */
+ 31'334'400, /* 31.3344_MHz_XTAL Macintosh II */
31'684'000, /* 31.684_MHz_XTAL TeleVideo TVI-955 132-column display clock */
31'948'800, /* 31.9488_MHz_XTAL NEC PC-88xx, PC-98xx */
32'000'000, /* 32_MHz_XTAL - */
@@ -395,6 +399,7 @@ const double XTAL::known_xtals[] = {
54'000'000, /* 54_MHz_XTAL Taito JC */
55'000'000, /* 55_MHz_XTAL Eolith Vega */
57'272'727, /* 57.272727_MHz_XTAL Psikyo SH2 with /2 divider (16x NTSC subcarrier)*/
+ 57'283'200, /* 57.2832_MHz_XTAL Macintosh IIci RBV, 15-inch portrait display */
58'000'000, /* 58_MHz_XTAL Magic Reel (Play System) */
59'292'000, /* 59.292_MHz_XTAL Data General D461 */
60'000'000, /* 60_MHz_XTAL ARM610 */