mirror of
https://github.com/holub/mame
synced 2025-06-06 12:53:46 +03:00
-emu/devfind.h: Made read_safe avaiable for optional I/O ports only.
-docs: Added the next couple of sections explaining object finders.
This commit is contained in:
parent
453aed194b
commit
ae8c70b7e6
@ -43,8 +43,8 @@ memory_bank_creator
|
|||||||
optional version, because the target object will always be found or
|
optional version, because the target object will always be found or
|
||||||
created.
|
created.
|
||||||
required_ioport, optional_ioport
|
required_ioport, optional_ioport
|
||||||
Finds and I/O port from a device’s input port definitions. The target is
|
Finds an I/O port from a device’s input port definitions. The target is the
|
||||||
the ``ioport_port`` object.
|
``ioport_port`` object.
|
||||||
required_address_space, optional_address_space
|
required_address_space, optional_address_space
|
||||||
Finds a device’s address space. The target is the ``address_space`` object.
|
Finds a device’s address space. The target is the ``address_space`` object.
|
||||||
required_region_ptr<PointerType>, optional_region_ptr<PointerType>
|
required_region_ptr<PointerType>, optional_region_ptr<PointerType>
|
||||||
@ -200,5 +200,238 @@ much the same way as pointers::
|
|||||||
return m_prom[offset];
|
return m_prom[offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
For convenience, object finders that target the base addresses of memory regions
|
For convenience, object finders that target the base pointer of memory regions
|
||||||
and shares can be indexed like arrays.
|
and shares can be indexed like arrays.
|
||||||
|
|
||||||
|
|
||||||
|
Connections between devices
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
Devices need to be connected together within a system. For example the Sun SBus
|
||||||
|
device needs access to the host CPU and address space. Here’s how we declare
|
||||||
|
the object finders in the device class (with all distractions removed)::
|
||||||
|
|
||||||
|
DECLARE_DEVICE_TYPE(SBUS, sbus_device)
|
||||||
|
|
||||||
|
class sbus_device : public device_t, public device_memory_interface
|
||||||
|
{
|
||||||
|
template <typename T, typename U>
|
||||||
|
sbus_device(
|
||||||
|
machine_config const &mconfig, char const *tag, device_t *owner, u32 clock,
|
||||||
|
T &&cpu_tag,
|
||||||
|
U &&space_tag, int space_num) :
|
||||||
|
sbus_device(mconfig, tag, owner, clock)
|
||||||
|
{
|
||||||
|
set_cpu(std::forward<T>(cpu_tag));
|
||||||
|
set_type1space(std::forward<U>(space_tag), space_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
sbus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
|
||||||
|
device_t(mconfig, type, tag, owner, clock),
|
||||||
|
device_memory_interface(mconfig, *this),
|
||||||
|
m_maincpu(*this, finder_base::DUMMY_TAG),
|
||||||
|
m_type1space(*this, finder_base::DUMMY_TAG, -1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void set_cpu(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); }
|
||||||
|
template <typename T> void set_type1space(T &&tag, int num) { m_type1space.set_tag(std::forward<T>(tag), num); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
required_device<sparc_base_device> m_maincpu;
|
||||||
|
required_address_space m_type1space;
|
||||||
|
};
|
||||||
|
|
||||||
|
There are several things to take note of here:
|
||||||
|
|
||||||
|
* Object finder members are declared for the things the device needs to access.
|
||||||
|
* The device doesn’t know how it will fit into a larger system, the object
|
||||||
|
finders are constructed with dummy arguments.
|
||||||
|
* Configuration member functions are provided to set the tag for the host CPU,
|
||||||
|
and the tag and index for the type 1 address space.
|
||||||
|
* In addition to the standard device constructor, a constructor with additional
|
||||||
|
parameters for setting the CPU and type 1 address space is provided.
|
||||||
|
|
||||||
|
The constant ``finder_base::DUMMY_TAG`` is guaranteed to be invalid and will not
|
||||||
|
resolve to an object. This makes it easy to detect incomplete configuration and
|
||||||
|
report an error. Address spaces are numbered from zero, so a negative address
|
||||||
|
space number is invalid.
|
||||||
|
|
||||||
|
The member functions for configuring object finders take a universal reference
|
||||||
|
to a tag-like object (templated type with ``&&`` qualifier), as well as any
|
||||||
|
other parameters needed by the specific type of object finder. An address space
|
||||||
|
finder needs an address space number in addition to a tag-like object.
|
||||||
|
|
||||||
|
So what’s a tag-like object? Three things are supported:
|
||||||
|
|
||||||
|
* A C string pointer (``char const *``) representing a tag relative to the
|
||||||
|
device being configured. Note that the object finder will not copy the
|
||||||
|
string. The caller must ensure it remains valid until resolution and/or
|
||||||
|
validation is complete.
|
||||||
|
* Another object finder. The object finder will take on its current target.
|
||||||
|
* For device finders, a reference to an instance of the target device type,
|
||||||
|
setting the target to that device. Note that this will not work if the device
|
||||||
|
is subsequently replaced in the machine configuration. It’s most often used
|
||||||
|
with ``*this``.
|
||||||
|
|
||||||
|
The additional constructor that sets initial configuration delegates to the
|
||||||
|
standard constructor and then calls the configuration member functions. It’s
|
||||||
|
purely for convenience.
|
||||||
|
|
||||||
|
When we want to instantiate this device and hook it up, we do this::
|
||||||
|
|
||||||
|
SPARCV7(config, m_maincpu, 20'000'000);
|
||||||
|
|
||||||
|
ADDRESS_MAP_BANK(config, m_type1space);
|
||||||
|
|
||||||
|
SBUS(config, m_sbus, 20'000'000);
|
||||||
|
m_sbus->set_cpu(m_maincpu);
|
||||||
|
m_sbus->set_type1space(m_type1space, 0);
|
||||||
|
|
||||||
|
We supply the same object finders to instantiate the CPU and address space
|
||||||
|
devices, and to configure the SBus device.
|
||||||
|
|
||||||
|
Note that we could also use literal C strings to configure the SBus device, at
|
||||||
|
the cost of needing to update the tags in multiple places if they change::
|
||||||
|
|
||||||
|
SBUS(config, m_sbus, 20'000'000);
|
||||||
|
m_sbus->set_cpu("maincpu");
|
||||||
|
m_sbus->set_type1space("type1", 0);
|
||||||
|
|
||||||
|
If we want to use the convenience constructor, we just supply additional
|
||||||
|
arguments when instantiating the device::
|
||||||
|
|
||||||
|
SBUS(config, m_sbus, 20'000'000, m_maincpu, m_type1space, 0);
|
||||||
|
|
||||||
|
|
||||||
|
Object finder arrays
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Many systems have multiple similar devices, I/O ports or other resources that
|
||||||
|
can be logically organised as an array. To simplify these use cases, object
|
||||||
|
finder array types are provided. The object finder array type names have
|
||||||
|
``_array`` added to them:
|
||||||
|
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| required_device | required_device_array |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| optional_device | optional_device_array |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| required_memory_region | required_memory_region_array |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| optional_memory_region | optional_memory_region_array |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| required_memory_bank | required_memory_bank_array |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| optional_memory_bank | optional_memory_bank_array |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| memory_bank_creator | memory_bank_array_creator |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| required_ioport | required_ioport_array |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| optional_ioport | optional_ioport_array |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| required_address_space | required_address_space_array |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| optional_address_space | optional_address_space_array |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| required_region_ptr | required_region_ptr_array |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| optional_region_ptr | optional_region_ptr_array |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| required_shared_ptr | required_shared_ptr_array |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
| optional_shared_ptr | optional_shared_ptr_array |
|
||||||
|
+------------------------+------------------------------+
|
||||||
|
|
||||||
|
A common case for an object array finder is a key matrix::
|
||||||
|
|
||||||
|
class keyboard_base : public device_t, public device_mac_keyboard_interface
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
keyboard_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
|
||||||
|
device_t(mconfig, type, tag, owner, clock),
|
||||||
|
device_mac_keyboard_interface(mconfig, *this),
|
||||||
|
m_rows(*this, "ROW%u", 0U)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 bus_r()
|
||||||
|
{
|
||||||
|
u8 result(0xffU);
|
||||||
|
for (unsigned i = 0U; m_rows.size() > i; ++i)
|
||||||
|
{
|
||||||
|
if (!BIT(m_row_drive, i))
|
||||||
|
result &= m_rows[i]->read();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
required_ioport_array<10> m_rows;
|
||||||
|
};
|
||||||
|
|
||||||
|
Constructing an object finder array is similar to constructing an object finder,
|
||||||
|
except that rather than just a tag you supply a tag format string and index
|
||||||
|
offset. In this case, the tags of the I/O ports in the array will be ``ROW0``,
|
||||||
|
``ROW1``, ``ROW2``, … ``ROW9``. Note that the object finder array allocates
|
||||||
|
dynamic storage for the tags, which remain valid until destruction.
|
||||||
|
|
||||||
|
The object finder array is used in much the same way as a ``std::array`` of the
|
||||||
|
underlying object finder type. It supports indexing, iterators, and range-based
|
||||||
|
``for`` loops.
|
||||||
|
|
||||||
|
Because an index offset is specified, the tags don’t need to use zero-based
|
||||||
|
indices. It’s common to use one-based indexing like this::
|
||||||
|
|
||||||
|
class dooyong_state : public driver_device
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
dooyong_state(machine_config const &mconfig, device_type type, char const *tag) :
|
||||||
|
driver_device(mconfig, type, tag),
|
||||||
|
m_bg(*this, "bg%u", 1U),
|
||||||
|
m_fg(*this, "fg%u", 1U)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
optional_device_array<dooyong_rom_tilemap_device, 2> m_bg;
|
||||||
|
optional_device_array<dooyong_rom_tilemap_device, 2> m_fg;
|
||||||
|
};
|
||||||
|
|
||||||
|
This causes ``m_bg`` to find devices with tags ``bg1`` and ``bg2``, while
|
||||||
|
``m_fg`` finds devices with tags ``fg1`` and ``fg2``. Note that the indexes
|
||||||
|
into the object finder arrays are still zero-based like any other C array.
|
||||||
|
|
||||||
|
It’s also possible to other format conversions, like hexadecimal (``%x`` and
|
||||||
|
``%X``) or character (``%c``)::
|
||||||
|
|
||||||
|
class eurit_state : public driver_device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
eurit_state(machine_config const &mconfig, device_type type, char const *tag) :
|
||||||
|
driver_device(mconfig, type, tag),
|
||||||
|
m_keys(*this, "KEY%c", 'A')
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
required_ioport_array<5> m_keys;
|
||||||
|
};
|
||||||
|
|
||||||
|
In this case, the key matrix ports use tags ``KEYA``, ``KEYB``, ``KEYC``,
|
||||||
|
``KEYD`` and ``KEYE``.
|
||||||
|
|
||||||
|
When the tags don’t follow a simple ascending sequence, you can supply a
|
||||||
|
brace-enclosed initialiser list of tags::
|
||||||
|
|
||||||
|
class seabattl_state : public driver_device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
seabattl_state(machine_config const &mconfig, device_type type, char const *tag) :
|
||||||
|
driver_device(mconfig, type, tag),
|
||||||
|
m_digits(*this, { "sc_thousand", "sc_hundred", "sc_half", "sc_unity", "tm_half", "tm_unity" })
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
required_device_array<dm9368_device, 6> m_digits;
|
||||||
|
};
|
||||||
|
@ -80,7 +80,7 @@ beckerport_device::~beckerport_device()
|
|||||||
device_start
|
device_start
|
||||||
-------------------------------------------------*/
|
-------------------------------------------------*/
|
||||||
|
|
||||||
void beckerport_device::device_start(void)
|
void beckerport_device::device_start()
|
||||||
{
|
{
|
||||||
char chAddress[64];
|
char chAddress[64];
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ void beckerport_device::device_start(void)
|
|||||||
device_stop
|
device_stop
|
||||||
-------------------------------------------------*/
|
-------------------------------------------------*/
|
||||||
|
|
||||||
void beckerport_device::device_stop(void)
|
void beckerport_device::device_stop()
|
||||||
{
|
{
|
||||||
if (m_pSocket)
|
if (m_pSocket)
|
||||||
{
|
{
|
||||||
@ -117,7 +117,7 @@ void beckerport_device::device_stop(void)
|
|||||||
device_config_complete
|
device_config_complete
|
||||||
-------------------------------------------------*/
|
-------------------------------------------------*/
|
||||||
|
|
||||||
void beckerport_device::device_config_complete(void)
|
void beckerport_device::device_config_complete()
|
||||||
{
|
{
|
||||||
m_hostname = "127.0.0.1";
|
m_hostname = "127.0.0.1";
|
||||||
m_dwtcpport = 65504;
|
m_dwtcpport = 65504;
|
||||||
@ -198,9 +198,9 @@ void beckerport_device::write(offs_t offset, u8 data)
|
|||||||
update_port
|
update_port
|
||||||
-------------------------------------------------*/
|
-------------------------------------------------*/
|
||||||
|
|
||||||
void beckerport_device::update_port(void)
|
void beckerport_device::update_port()
|
||||||
{
|
{
|
||||||
device_stop();
|
device_stop();
|
||||||
m_dwtcpport = m_dwconfigport.read_safe(65504);
|
m_dwtcpport = m_dwconfigport->read();
|
||||||
device_start();
|
device_start();
|
||||||
}
|
}
|
||||||
|
@ -165,14 +165,14 @@ uint16_t md_jcart_device::read(offs_t offset)
|
|||||||
|
|
||||||
if (m_jcart_io_data[0] & 0x40)
|
if (m_jcart_io_data[0] & 0x40)
|
||||||
{
|
{
|
||||||
joy[0] = m_jcart3.read_safe(0);
|
joy[0] = m_jcart3->read();
|
||||||
joy[1] = m_jcart4.read_safe(0);
|
joy[1] = m_jcart4->read();
|
||||||
return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
|
return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
joy[0] = ((m_jcart3.read_safe(0) & 0xc0) >> 2) | (m_jcart3.read_safe(0) & 0x03);
|
joy[0] = ((m_jcart3->read() & 0xc0) >> 2) | (m_jcart3->read() & 0x03);
|
||||||
joy[1] = ((m_jcart4.read_safe(0) & 0xc0) >> 2) | (m_jcart4.read_safe(0) & 0x03);
|
joy[1] = ((m_jcart4->read() & 0xc0) >> 2) | (m_jcart4->read() & 0x03);
|
||||||
return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
|
return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -208,14 +208,14 @@ uint16_t md_seprom_codemast_device::read(offs_t offset)
|
|||||||
|
|
||||||
if (m_jcart_io_data[0] & 0x40)
|
if (m_jcart_io_data[0] & 0x40)
|
||||||
{
|
{
|
||||||
joy[0] = m_jcart3.read_safe(0);
|
joy[0] = m_jcart3->read();
|
||||||
joy[1] = m_jcart4.read_safe(0);
|
joy[1] = m_jcart4->read();
|
||||||
return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
|
return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
joy[0] = ((m_jcart3.read_safe(0) & 0xc0) >> 2) | (m_jcart3.read_safe(0) & 0x03);
|
joy[0] = ((m_jcart3->read() & 0xc0) >> 2) | (m_jcart3->read() & 0x03);
|
||||||
joy[1] = ((m_jcart4.read_safe(0) & 0xc0) >> 2) | (m_jcart4.read_safe(0) & 0x03);
|
joy[1] = ((m_jcart4->read() & 0xc0) >> 2) | (m_jcart4->read() & 0x03);
|
||||||
return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
|
return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,7 +281,7 @@ uint8_t mtx_sdx_device::sdx_status_r()
|
|||||||
|
|
||||||
uint8_t data = 0x00;
|
uint8_t data = 0x00;
|
||||||
|
|
||||||
data |= m_dsw[BIT(m_control, 0)].read_safe(0x0f) & 0x0f;
|
data |= m_dsw[BIT(m_control, 0)]->read() & 0x0f;
|
||||||
|
|
||||||
data |= (m_floppy0->get_device() && m_floppy1->get_device()) ? 0x10 : 0x00;
|
data |= (m_floppy0->get_device() && m_floppy1->get_device()) ? 0x10 : 0x00;
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ sbus_device::sbus_device(const machine_config &mconfig, device_type type, const
|
|||||||
, device_memory_interface(mconfig, *this)
|
, device_memory_interface(mconfig, *this)
|
||||||
, m_space_config("SBus Space", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor())
|
, m_space_config("SBus Space", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor())
|
||||||
, m_maincpu(*this, finder_base::DUMMY_TAG)
|
, m_maincpu(*this, finder_base::DUMMY_TAG)
|
||||||
, m_type1space(*this, finder_base::DUMMY_TAG)
|
, m_type1space(*this, finder_base::DUMMY_TAG, -1)
|
||||||
, m_irq_cb(*this)
|
, m_irq_cb(*this)
|
||||||
, m_buserr(*this)
|
, m_buserr(*this)
|
||||||
{
|
{
|
||||||
|
@ -58,20 +58,18 @@ class sbus_device : public device_t,
|
|||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
sbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag, U &&space_tag)
|
sbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag, U &&space_tag, int space_num)
|
||||||
: sbus_device(mconfig, tag, owner, clock)
|
: sbus_device(mconfig, tag, owner, clock)
|
||||||
{
|
{
|
||||||
set_cpu_tag(std::forward<T>(cpu_tag));
|
set_cpu(std::forward<T>(cpu_tag));
|
||||||
set_space_tag(std::forward<U>(space_tag));
|
set_type1space(std::forward<U>(space_tag), space_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
sbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
sbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||||
|
|
||||||
// inline configuration
|
// inline configuration
|
||||||
template <typename T> void set_cpu_tag(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); }
|
template <typename T> void set_cpu(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); }
|
||||||
template <typename T> void set_space_tag(T &&tag) { m_type1space.set_tag(std::forward<T>(tag)); }
|
template <typename T> void set_type1space(T &&tag, int num) { m_type1space.set_tag(std::forward<T>(tag), num); }
|
||||||
|
|
||||||
// devcb3
|
|
||||||
template <unsigned Line> auto irq() { return m_irq_cb[Line].bind(); }
|
template <unsigned Line> auto irq() { return m_irq_cb[Line].bind(); }
|
||||||
auto buserr() { return m_buserr.bind(); }
|
auto buserr() { return m_buserr.bind(); }
|
||||||
|
|
||||||
@ -101,7 +99,7 @@ protected:
|
|||||||
|
|
||||||
// internal state
|
// internal state
|
||||||
required_device<sparc_base_device> m_maincpu;
|
required_device<sparc_base_device> m_maincpu;
|
||||||
required_device<address_map_bank_device> m_type1space;
|
required_address_space m_type1space;
|
||||||
address_space *m_space;
|
address_space *m_space;
|
||||||
|
|
||||||
devcb_write_line::array<7> m_irq_cb;
|
devcb_write_line::array<7> m_irq_cb;
|
||||||
|
@ -836,6 +836,44 @@ protected:
|
|||||||
template <unsigned Count> using memory_bank_array_creator = object_array_finder<memory_bank_creator, Count>;
|
template <unsigned Count> using memory_bank_array_creator = object_array_finder<memory_bank_creator, Count>;
|
||||||
|
|
||||||
|
|
||||||
|
/// \brief Base class for optional I/O port finders
|
||||||
|
///
|
||||||
|
/// Adds helpers for to test whether the I/O port was found, and to read
|
||||||
|
/// the port value or return a default if the I/O port was not found.
|
||||||
|
template <>
|
||||||
|
class object_finder_base<ioport_port, false> : public object_finder_common_base<ioport_port, false>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// \brief Read I/O port if found or return default value
|
||||||
|
///
|
||||||
|
/// If the I/O port was found, this reads a value from the I/O port
|
||||||
|
/// and returns it. If the I/O port was not found, the default
|
||||||
|
/// value (supplied as a parameter) is returned.
|
||||||
|
/// \param [in] defval Value to return if I/O port was not found.
|
||||||
|
/// \return Value read from I/O port if found, or supplied default
|
||||||
|
/// value otherwise.
|
||||||
|
ioport_value read_safe(ioport_value defval) { return this->m_target ? this->m_target->read() : defval; }
|
||||||
|
|
||||||
|
/// \brief Return whether target has been found
|
||||||
|
///
|
||||||
|
/// Works on the assumption that the target object pointer will
|
||||||
|
/// be non-null if the target has been found, and null
|
||||||
|
/// otherwise.
|
||||||
|
/// \return True if object has been found, or false otherwise.
|
||||||
|
bool found() const { return this->m_target != nullptr; }
|
||||||
|
|
||||||
|
/// \brief Cast-to-Boolean operator
|
||||||
|
///
|
||||||
|
/// Allows truth tests to test whether it's safe to dereference
|
||||||
|
/// the object, similar to pointers and various C++ standard
|
||||||
|
/// library objects.
|
||||||
|
/// \return True if safe to dereference, or false otherwise.
|
||||||
|
explicit operator bool() const { return this->m_target != nullptr; }
|
||||||
|
|
||||||
|
using object_finder_common_base<ioport_port, false>::object_finder_common_base;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// \brief I/O port finder template
|
/// \brief I/O port finder template
|
||||||
///
|
///
|
||||||
/// Template argument is whether the I/O port is required. It is a
|
/// Template argument is whether the I/O port is required. It is a
|
||||||
@ -854,16 +892,6 @@ public:
|
|||||||
/// remains valid until resolution time.
|
/// remains valid until resolution time.
|
||||||
ioport_finder(device_t &base, char const *tag);
|
ioport_finder(device_t &base, char const *tag);
|
||||||
|
|
||||||
/// \brief Read I/O port if found or return default value
|
|
||||||
///
|
|
||||||
/// If the I/O port was found, this reads a value from the I/O port
|
|
||||||
/// and returns it. If the I/O port was not found, the default
|
|
||||||
/// value (supplied as a parameter) is returned.
|
|
||||||
/// \param [in] defval Value to return if I/O port was not found.
|
|
||||||
/// \return Value read from I/O port if found, or supplied default
|
|
||||||
/// value otherwise.
|
|
||||||
ioport_value read_safe(ioport_value defval) { return this->m_target ? this->m_target->read() : defval; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// \brief Find I/O port
|
/// \brief Find I/O port
|
||||||
///
|
///
|
||||||
|
@ -285,12 +285,12 @@ INPUT_PORTS_END
|
|||||||
|
|
||||||
uint8_t maxaflex_state::pia_pa_r()
|
uint8_t maxaflex_state::pia_pa_r()
|
||||||
{
|
{
|
||||||
return atari_input_disabled() ? 0xff : m_joy01.read_safe(0);
|
return atari_input_disabled() ? 0xff : m_joy01->read();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t maxaflex_state::pia_pb_r()
|
uint8_t maxaflex_state::pia_pb_r()
|
||||||
{
|
{
|
||||||
return atari_input_disabled() ? 0xff : m_joy23.read_safe(0);
|
return atari_input_disabled() ? 0xff : m_joy23->read();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -244,10 +244,10 @@ uint8_t meyc8088_state::input_r()
|
|||||||
uint8_t ret = 0xff;
|
uint8_t ret = 0xff;
|
||||||
|
|
||||||
// multiplexed switch inputs
|
// multiplexed switch inputs
|
||||||
if (~m_common & 1) ret &= m_switches[0].read_safe(0); // bit switches
|
if (~m_common & 1) ret &= m_switches[0]->read(); // bit switches
|
||||||
if (~m_common & 2) ret &= m_switches[1].read_safe(0); // control switches
|
if (~m_common & 2) ret &= m_switches[1]->read(); // control switches
|
||||||
if (~m_common & 4) ret &= m_switches[2].read_safe(0); // light switches
|
if (~m_common & 4) ret &= m_switches[2]->read(); // light switches
|
||||||
if (~m_common & 8) ret &= m_switches[3].read_safe(0); // light switches
|
if (~m_common & 8) ret &= m_switches[3]->read(); // light switches
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1494,7 +1494,7 @@ void sun4c_state::sun4c(machine_config &config)
|
|||||||
m_maincpu->set_mmu(m_mmu);
|
m_maincpu->set_mmu(m_mmu);
|
||||||
|
|
||||||
// SBus
|
// SBus
|
||||||
SBUS(config, m_sbus, 20'000'000, "maincpu", "type1");
|
SBUS(config, m_sbus, 20'000'000, m_maincpu, m_type1space, 0);
|
||||||
m_sbus->irq<0>().set(FUNC(sun4c_state::sbus_irq_w<SPARC_IRQ1>));
|
m_sbus->irq<0>().set(FUNC(sun4c_state::sbus_irq_w<SPARC_IRQ1>));
|
||||||
m_sbus->irq<1>().set(FUNC(sun4c_state::sbus_irq_w<SPARC_IRQ2>));
|
m_sbus->irq<1>().set(FUNC(sun4c_state::sbus_irq_w<SPARC_IRQ2>));
|
||||||
m_sbus->irq<2>().set(FUNC(sun4c_state::sbus_irq_w<SPARC_IRQ3>));
|
m_sbus->irq<2>().set(FUNC(sun4c_state::sbus_irq_w<SPARC_IRQ3>));
|
||||||
|
@ -192,7 +192,7 @@ u8 topspeed_state::input_bypass_r()
|
|||||||
{
|
{
|
||||||
// Read port number
|
// Read port number
|
||||||
const u8 port = m_tc0040ioc->port_r();
|
const u8 port = m_tc0040ioc->port_r();
|
||||||
const u16 steer = 0xff80 + m_steer.read_safe(0);
|
const u16 steer = 0xff80 + m_steer->read();
|
||||||
|
|
||||||
switch (port)
|
switch (port)
|
||||||
{
|
{
|
||||||
@ -209,14 +209,14 @@ u8 topspeed_state::input_bypass_r()
|
|||||||
|
|
||||||
CUSTOM_INPUT_MEMBER(topspeed_state::gas_pedal_r)
|
CUSTOM_INPUT_MEMBER(topspeed_state::gas_pedal_r)
|
||||||
{
|
{
|
||||||
static const u8 retval[8] = { 0,1,3,2,6,7,5,4 };
|
static constexpr u8 retval[8] = { 0,1,3,2,6,7,5,4 };
|
||||||
return retval[m_gas.read_safe(0) & 7];
|
return retval[m_gas->read() & 7];
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_INPUT_MEMBER(topspeed_state::brake_pedal_r)
|
CUSTOM_INPUT_MEMBER(topspeed_state::brake_pedal_r)
|
||||||
{
|
{
|
||||||
static const u8 retval[8] = { 0,1,3,2,6,7,5,4 };
|
static constexpr u8 retval[8] = { 0,1,3,2,6,7,5,4 };
|
||||||
return retval[m_brake.read_safe(0) & 7];
|
return retval[m_brake->read() & 7];
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: proper motorcpu hook-up
|
// TODO: proper motorcpu hook-up
|
||||||
|
@ -16,7 +16,7 @@ DECLARE_DEVICE_TYPE(DOOYONG_RAM_TILEMAP, dooyong_ram_tilemap_device)
|
|||||||
class dooyong_tilemap_device_base : public device_t
|
class dooyong_tilemap_device_base : public device_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template <typename T> void set_gfxdecode_tag(T &&cpu_tag) { m_gfxdecode.set_tag(std::forward<T>(cpu_tag)); }
|
template <typename T> void set_gfxdecode_tag(T &&gfxdecode_tag) { m_gfxdecode.set_tag(std::forward<T>(gfxdecode_tag)); }
|
||||||
void set_gfxnum(int gfxnum) { m_gfxnum = gfxnum; }
|
void set_gfxnum(int gfxnum) { m_gfxnum = gfxnum; }
|
||||||
|
|
||||||
void draw(screen_device &screen, bitmap_ind16 &dest, rectangle const &cliprect, u32 flags, u8 priority, u8 priority_mask = 0xff);
|
void draw(screen_device &screen, bitmap_ind16 &dest, rectangle const &cliprect, u32 flags, u8 priority, u8 priority_mask = 0xff);
|
||||||
|
Loading…
Reference in New Issue
Block a user