From 0e6677c070975eb5c62512c24332234970210640 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Thu, 24 Jun 2021 14:38:59 +1000 Subject: machine/latch8.cpp: Clean up a little. Making the bit read functions honour the XOR mask is easy in theory, but dkong.cpp is doing scary things with the XOR mask and bit read handlers on one of its latches, so it could end up breaking something. Honouring the read callbacks would add two tests to each of the bit read functions, which could hurt performance. The whole design of this device seems somewhat incoherent. --- src/devices/machine/latch8.cpp | 62 +++++++++++++++--------------- src/devices/machine/latch8.h | 86 ++++++++++++++++++++---------------------- src/mame/audio/dkong.cpp | 22 +++++------ src/mame/drivers/ladybug.cpp | 22 +++++------ 4 files changed, 94 insertions(+), 98 deletions(-) diff --git a/src/devices/machine/latch8.cpp b/src/devices/machine/latch8.cpp index 4db3d302195..bfccdc48a30 100644 --- a/src/devices/machine/latch8.cpp +++ b/src/devices/machine/latch8.cpp @@ -13,7 +13,7 @@ void latch8_device::update(uint8_t new_val, uint8_t mask) { - uint8_t old_val = m_value; + const uint8_t old_val = m_value; m_value = (m_value & ~mask) | (new_val & mask); @@ -28,21 +28,19 @@ void latch8_device::update(uint8_t new_val, uint8_t mask) TIMER_CALLBACK_MEMBER( latch8_device::timerproc ) { - uint8_t new_val = param & 0xFF; - uint8_t mask = param >> 8; + const uint8_t new_val = param & 0xff; + const uint8_t mask = param >> 8; - update( new_val, mask); + update(new_val, mask); } /* ----------------------------------------------------------------------- */ uint8_t latch8_device::read(offs_t offset) { - uint8_t res; - assert(offset == 0); - res = m_value; + uint8_t res = m_value; if (m_has_read) { for (int i = 0; i < 8; i++) @@ -60,9 +58,9 @@ void latch8_device::write(offs_t offset, uint8_t data) assert(offset == 0); if (m_nosync != 0xff) - machine().scheduler().synchronize(timer_expired_delegate(FUNC(latch8_device::timerproc),this), (0xFF << 8) | data); + machine().scheduler().synchronize(timer_expired_delegate(FUNC(latch8_device::timerproc),this), (0xff << 8) | data); else - update(data, 0xFF); + update(data, 0xff); } @@ -73,15 +71,15 @@ void latch8_device::reset_w(offs_t offset, uint8_t data) m_value = 0; } -/* write bit x from data into bit determined by offset */ -/* latch = (latch & ~(1<> x) & 0x01) << offset) */ +// write bit x from data into bit determined by offset +// latch = (latch & ~(1<> x) & 0x01) << offset) -void latch8_device::bitx_w(int bit, offs_t offset, uint8_t data) +template inline void latch8_device::bitx_w(offs_t offset, uint8_t data) { - uint8_t mask = (1<> bit) & 0x01) << offset); + const uint8_t mask = 1 << offset; + const uint8_t masked_data = BIT(data, Bit) << offset; - assert( offset < 8); + assert(offset < 8); /* No need to synchronize ? */ if (m_nosync & mask) @@ -90,27 +88,27 @@ void latch8_device::bitx_w(int bit, offs_t offset, uint8_t data) machine().scheduler().synchronize(timer_expired_delegate(FUNC(latch8_device::timerproc),this), (mask << 8) | masked_data); } -void latch8_device::bit0_w(offs_t offset, uint8_t data) { bitx_w(0, offset, data); } -void latch8_device::bit1_w(offs_t offset, uint8_t data) { bitx_w(1, offset, data); } -void latch8_device::bit2_w(offs_t offset, uint8_t data) { bitx_w(2, offset, data); } -void latch8_device::bit3_w(offs_t offset, uint8_t data) { bitx_w(3, offset, data); } -void latch8_device::bit4_w(offs_t offset, uint8_t data) { bitx_w(4, offset, data); } -void latch8_device::bit5_w(offs_t offset, uint8_t data) { bitx_w(5, offset, data); } -void latch8_device::bit6_w(offs_t offset, uint8_t data) { bitx_w(6, offset, data); } -void latch8_device::bit7_w(offs_t offset, uint8_t data) { bitx_w(7, offset, data); } +void latch8_device::bit0_w(offs_t offset, uint8_t data) { bitx_w<0>(offset, data); } +void latch8_device::bit1_w(offs_t offset, uint8_t data) { bitx_w<1>(offset, data); } +void latch8_device::bit2_w(offs_t offset, uint8_t data) { bitx_w<2>(offset, data); } +void latch8_device::bit3_w(offs_t offset, uint8_t data) { bitx_w<3>(offset, data); } +void latch8_device::bit4_w(offs_t offset, uint8_t data) { bitx_w<4>(offset, data); } +void latch8_device::bit5_w(offs_t offset, uint8_t data) { bitx_w<5>(offset, data); } +void latch8_device::bit6_w(offs_t offset, uint8_t data) { bitx_w<6>(offset, data); } +void latch8_device::bit7_w(offs_t offset, uint8_t data) { bitx_w<7>(offset, data); } DEFINE_DEVICE_TYPE(LATCH8, latch8_device, "latch8", "8-bit latch") latch8_device::latch8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, LATCH8, tag, owner, clock) + , m_write_cb(*this) + , m_read_cb(*this) , m_value(0) - , m_has_write(0) - , m_has_read(0) + , m_has_write(false) + , m_has_read(false) , m_maskout(0) , m_xorvalue(0) , m_nosync(0) - , m_write_cb(*this) - , m_read_cb(*this) { } @@ -133,17 +131,19 @@ void latch8_device::device_validity_check(validity_checker &valid) const void latch8_device::device_start() { - /* setup nodemap */ + // setup nodemap for (auto &cb : m_write_cb) { - if (!cb.isnull()) m_has_write = 1; + if (!cb.isnull()) + m_has_write = true; cb.resolve(); } - /* setup device read handlers */ + // setup device read handlers for (auto &cb : m_read_cb) { - if (!cb.isnull()) m_has_read = 1; + if (!cb.isnull()) + m_has_read = true; cb.resolve(); } diff --git a/src/devices/machine/latch8.h b/src/devices/machine/latch8.h index 750a9c752b5..0609d3949ff 100644 --- a/src/devices/machine/latch8.h +++ b/src/devices/machine/latch8.h @@ -16,25 +16,38 @@ #ifndef MAME_MACHINE_LATCH8_H #define MAME_MACHINE_LATCH8_H -#include "sound/discrete.h" +#pragma once + class latch8_device : public device_t { public: latch8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); - /* write & read full byte */ + // Write bit to discrete node + template auto write_cb() { return m_write_cb[N].bind(); } + + // Upon read, replace bits by reading from another device handler + template auto read_cb() { return m_read_cb[N].bind(); } + + // Bit mask specifying bits to be masked *out* + void set_maskout(uint32_t maskout) { m_maskout = maskout; } + + // Bit mask specifying bits to be inverted + void set_xorvalue(uint32_t xorvalue) { m_xorvalue = xorvalue; } + + // Bit mask specifying bits not needing cpu synchronization. + void set_nosync(uint32_t nosync) { m_nosync = nosync; } + // write & read full byte uint8_t read(offs_t offset); void write(offs_t offset, uint8_t data); - /* reset the latch */ - + // reset the latch void reset_w(offs_t offset, uint8_t data); - /* read bit x */ - /* return (latch >> x) & 0x01 */ - + // read bit x + // FIXME: does not honour read callbacks or XOR mask DECLARE_READ_LINE_MEMBER( bit0_r ) { return BIT(m_value, 0); } DECLARE_READ_LINE_MEMBER( bit1_r ) { return BIT(m_value, 1); } DECLARE_READ_LINE_MEMBER( bit2_r ) { return BIT(m_value, 2); } @@ -44,21 +57,19 @@ public: DECLARE_READ_LINE_MEMBER( bit6_r ) { return BIT(m_value, 6); } DECLARE_READ_LINE_MEMBER( bit7_r ) { return BIT(m_value, 7); } - /* read inverted bit x */ - /* return (latch >> x) & 0x01 */ - - DECLARE_READ_LINE_MEMBER( bit0_q_r ) { return BIT(m_value, 0) ^ 1; } - DECLARE_READ_LINE_MEMBER( bit1_q_r ) { return BIT(m_value, 1) ^ 1; } - DECLARE_READ_LINE_MEMBER( bit2_q_r ) { return BIT(m_value, 2) ^ 1; } - DECLARE_READ_LINE_MEMBER( bit3_q_r ) { return BIT(m_value, 3) ^ 1; } - DECLARE_READ_LINE_MEMBER( bit4_q_r ) { return BIT(m_value, 4) ^ 1; } - DECLARE_READ_LINE_MEMBER( bit5_q_r ) { return BIT(m_value, 5) ^ 1; } - DECLARE_READ_LINE_MEMBER( bit6_q_r ) { return BIT(m_value, 6) ^ 1; } - DECLARE_READ_LINE_MEMBER( bit7_q_r ) { return BIT(m_value, 7) ^ 1; } - - /* write bit x from data into bit determined by offset */ - /* latch = (latch & ~(1<> x) & 0x01) << offset) */ - + // read inverted bit + // FIXME: does not honour read callbacks or XOR mask + DECLARE_READ_LINE_MEMBER( bit0_q_r ) { return BIT(~m_value, 0); } + DECLARE_READ_LINE_MEMBER( bit1_q_r ) { return BIT(~m_value, 1); } + DECLARE_READ_LINE_MEMBER( bit2_q_r ) { return BIT(~m_value, 2); } + DECLARE_READ_LINE_MEMBER( bit3_q_r ) { return BIT(~m_value, 3); } + DECLARE_READ_LINE_MEMBER( bit4_q_r ) { return BIT(~m_value, 4); } + DECLARE_READ_LINE_MEMBER( bit5_q_r ) { return BIT(~m_value, 5); } + DECLARE_READ_LINE_MEMBER( bit6_q_r ) { return BIT(~m_value, 6); } + DECLARE_READ_LINE_MEMBER( bit7_q_r ) { return BIT(~m_value, 7); } + + // write bit x from data into bit determined by offset + // latch = (latch & ~(1<> x) & 0x01) << offset) void bit0_w(offs_t offset, uint8_t data); void bit1_w(offs_t offset, uint8_t data); void bit2_w(offs_t offset, uint8_t data); @@ -68,21 +79,6 @@ public: void bit6_w(offs_t offset, uint8_t data); void bit7_w(offs_t offset, uint8_t data); - /* Bit mask specifying bits to be masked *out* */ - void set_maskout(uint32_t maskout) { m_maskout = maskout; } - - /* Bit mask specifying bits to be inverted */ - void set_xorvalue(uint32_t xorvalue) { m_xorvalue = xorvalue; } - - /* Bit mask specifying bits not needing cpu synchronization. */ - void set_nosync(uint32_t nosync) { m_nosync = nosync; } - - /* Write bit to discrete node */ - template auto write_cb() { return m_write_cb[N].bind(); } - - /* Upon read, replace bits by reading from another device handler */ - template auto read_cb() { return m_read_cb[N].bind(); } - protected: // device-level overrides virtual void device_start() override; @@ -91,21 +87,21 @@ protected: TIMER_CALLBACK_MEMBER( timerproc ); void update(uint8_t new_val, uint8_t mask); - inline void bitx_w(int bit, offs_t offset, uint8_t data); + template void bitx_w(offs_t offset, uint8_t data); private: + devcb_write_line::array<8> m_write_cb; + devcb_read_line::array<8> m_read_cb; + // internal state uint8_t m_value; - uint8_t m_has_write; - uint8_t m_has_read; + bool m_has_write; + bool m_has_read; - /* only for byte reads, does not affect bit reads and node_map */ + // only for byte reads, does not affect bit reads and node_map uint32_t m_maskout; - uint32_t m_xorvalue; /* after mask */ + uint32_t m_xorvalue; // after mask uint32_t m_nosync; - - devcb_write_line::array<8> m_write_cb; - devcb_read_line::array<8> m_read_cb; }; DECLARE_DEVICE_TYPE(LATCH8, latch8_device) diff --git a/src/mame/audio/dkong.cpp b/src/mame/audio/dkong.cpp index e623ef5530a..a2c69a86009 100644 --- a/src/mame/audio/dkong.cpp +++ b/src/mame/audio/dkong.cpp @@ -1233,7 +1233,7 @@ uint8_t dkong_state::dkong_tune_r(offs_t offset) if ( page & 0x40 ) { - return (m_ls175_3d->read(0) & 0x0F) | (dkong_voice_status_r() << 4); + return (m_ls175_3d->read(0) & 0x0f) | (dkong_voice_status_r() << 4); } else { @@ -1343,10 +1343,10 @@ void dkong_state::dkong2b_audio(machine_config &config) m_soundcpu->bus_in_cb().set(FUNC(dkong_state::dkong_tune_r)); m_soundcpu->bus_out_cb().set(FUNC(dkong_state::dkong_voice_w)); m_soundcpu->p1_out_cb().set(FUNC(dkong_state::dkong_p1_w)); // only write to dac - m_soundcpu->p2_in_cb().set("virtual_p2", FUNC(latch8_device::read)); - m_soundcpu->p2_out_cb().set("virtual_p2", FUNC(latch8_device::write)); - m_soundcpu->t0_in_cb().set("ls259.6h", FUNC(latch8_device::bit5_q_r)); - m_soundcpu->t1_in_cb().set("ls259.6h", FUNC(latch8_device::bit4_q_r)); + m_soundcpu->p2_in_cb().set(m_dev_vp2, FUNC(latch8_device::read)); + m_soundcpu->p2_out_cb().set(m_dev_vp2, FUNC(latch8_device::write)); + m_soundcpu->t0_in_cb().set(m_dev_6h, FUNC(latch8_device::bit5_q_r)); + m_soundcpu->t1_in_cb().set(m_dev_6h, FUNC(latch8_device::bit4_q_r)); SPEAKER(config, "mono").front_center(); DISCRETE(config, "discrete", dkong2b_discrete).add_route(ALL_OUTPUTS, "mono", 1.0); @@ -1401,11 +1401,11 @@ void dkong_state::dkongjr_audio(machine_config &config) latch8_device &dev_5h(LATCH8(config, "ls259.5h")); dev_5h.write_cb<1>().set("discrete", FUNC(discrete_device::write_line)); - latch8_device &dev_4h(LATCH8(config, "ls259.4h")); + LATCH8(config, "ls259.4h"); LATCH8(config, m_dev_vp2); /* virtual latch for port B */ m_dev_vp2->set_xorvalue(0x70); /* all signals are inverted */ - m_dev_vp2->read_cb<6>().set(dev_4h, FUNC(latch8_device::bit1_r)); + m_dev_vp2->read_cb<6>().set("ls259.4h", FUNC(latch8_device::bit1_r)); m_dev_vp2->read_cb<5>().set(m_dev_6h, FUNC(latch8_device::bit3_r)); m_dev_vp2->read_cb<4>().set(m_dev_6h, FUNC(latch8_device::bit6_r)); m_dev_vp2->write_cb<7>().set("discrete", FUNC(discrete_device::write_line)); @@ -1414,10 +1414,10 @@ void dkong_state::dkongjr_audio(machine_config &config) m_soundcpu->set_addrmap(AS_PROGRAM, &dkong_state::dkong_sound_map); m_soundcpu->set_addrmap(AS_IO, &dkong_state::dkongjr_sound_io_map); m_soundcpu->p1_out_cb().set(FUNC(dkong_state::dkong_p1_w)); // only write to dac - m_soundcpu->p2_in_cb().set("virtual_p2", FUNC(latch8_device::read)); - m_soundcpu->p2_out_cb().set("virtual_p2", FUNC(latch8_device::write)); - m_soundcpu->t0_in_cb().set("ls259.6h", FUNC(latch8_device::bit5_q_r)); - m_soundcpu->t1_in_cb().set("ls259.6h", FUNC(latch8_device::bit4_q_r)); + m_soundcpu->p2_in_cb().set(m_dev_vp2, FUNC(latch8_device::read)); + m_soundcpu->p2_out_cb().set(m_dev_vp2, FUNC(latch8_device::write)); + m_soundcpu->t0_in_cb().set(m_dev_6h, FUNC(latch8_device::bit5_q_r)); + m_soundcpu->t1_in_cb().set(m_dev_6h, FUNC(latch8_device::bit4_q_r)); SPEAKER(config, "mono").front_center(); diff --git a/src/mame/drivers/ladybug.cpp b/src/mame/drivers/ladybug.cpp index ddd822e762b..b65ae59dd21 100644 --- a/src/mame/drivers/ladybug.cpp +++ b/src/mame/drivers/ladybug.cpp @@ -74,7 +74,7 @@ unknown dips #include "cpu/z80/z80.h" #include "machine/74259.h" -#include "machine/latch8.h" +#include "machine/gen_latch.h" #include "sound/sn76496.h" #include "screen.h" #include "speaker.h" @@ -157,8 +157,8 @@ void mrsdyna_state::mrsdyna_cpu1_map(address_map &map) // LS138 @ N3 (bottom 3 bits) // (all of these are read/write) map(0x8005, 0x8005).mirror(0x1ff8).r(FUNC(mrsdyna_state::mrsdyna_protection_r)); // OE on PAL @ K2 (16R6, U001) (100x xxxx xxxx x101) - map(0x8006, 0x8006).mirror(0x1ff8).w("soundlatch_low", FUNC(latch8_device::write)); // LS374 @ P6 - map(0x8007, 0x8007).mirror(0x1ff8).w("soundlatch_high", FUNC(latch8_device::write)); // LS374 @ R6 + map(0x8006, 0x8006).mirror(0x1ff8).w("soundlatch_low", FUNC(generic_latch_8_device::write)); // LS374 @ P6 + map(0x8007, 0x8007).mirror(0x1ff8).w("soundlatch_high", FUNC(generic_latch_8_device::write)); // LS374 @ R6 map(0x8000, 0x8000).mirror(0x1ff8).portr("IN0"); map(0x8001, 0x8001).mirror(0x1ff8).portr("IN1"); map(0x8002, 0x8002).mirror(0x1ff8).portr("DSW0"); @@ -176,8 +176,8 @@ void mrsdyna_state::mrsdyna_cpu2_map(address_map &map) // LS138 @ P7 map(0x0000, 0x5fff).rom(); // 2764s at H6,J6, and L6 map(0x6000, 0x63ff).mirror(0x0400).ram(); // 2x2114 @ M6/N6 - map(0x8000, 0x8000).mirror(0x1fff).r("soundlatch_low", FUNC(latch8_device::read)); // LS374 @ P6 - map(0xa000, 0xa000).mirror(0x1fff).r("soundlatch_high", FUNC(latch8_device::read)); // LS374 @ R6 + map(0x8000, 0x8000).mirror(0x1fff).r("soundlatch_low", FUNC(generic_latch_8_device::read)); // LS374 @ P6 + map(0xa000, 0xa000).mirror(0x1fff).r("soundlatch_high", FUNC(generic_latch_8_device::read)); // LS374 @ R6 map(0xc000, 0xc000).mirror(0x1fff).r(FUNC(mrsdyna_state::mrsdyna_rnd_r)); // LS125 @ P8 - reads 556 outputs to D1 and D0? // LS138 @ P7 (nY7) and LS139 @ H4 map(0xe000, 0xe0ff).mirror(0x0300).writeonly().share("grid_data"); // HD6148P @ D6 @@ -191,8 +191,8 @@ void sraider_state::sraider_cpu2_map(address_map &map) // LS138 @ P7 map(0x0000, 0x5fff).rom(); // 2764s at H6, J6, and L6 map(0x6000, 0x63ff).mirror(0x0400).ram(); // 2x2114 @ M6/N6 - map(0x8000, 0x8000).mirror(0x1fff).r("soundlatch_low", FUNC(latch8_device::read)); // LS374 @ P6 - map(0xa000, 0xa000).mirror(0x1fff).r("soundlatch_high", FUNC(latch8_device::read)); // LS374 @ R6 + map(0x8000, 0x8000).mirror(0x1fff).r("soundlatch_low", FUNC(generic_latch_8_device::read)); // LS374 @ P6 + map(0xa000, 0xa000).mirror(0x1fff).r("soundlatch_high", FUNC(generic_latch_8_device::read)); // LS374 @ R6 map(0xc000, 0xc000).mirror(0x1fff).r(FUNC(sraider_state::mrsdyna_rnd_r)); // LS125 @ P8 - reads 556 outputs to D1 and D0? // LS138 @ P7 (nY7) and LS139 @ H4 map(0xe000, 0xe0ff).mirror(0x0300).writeonly().share("grid_data"); // HD6148P @ D6 @@ -870,8 +870,8 @@ void mrsdyna_state::mrsdyna(machine_config &config) maincpu.set_addrmap(AS_PROGRAM, &mrsdyna_state::mrsdyna_cpu1_map); maincpu.set_vblank_int("screen", FUNC(mrsdyna_state::irq0_line_hold)); - LATCH8(config, "soundlatch_low"); - LATCH8(config, "soundlatch_high"); + GENERIC_LATCH_8(config, "soundlatch_low"); + GENERIC_LATCH_8(config, "soundlatch_high"); z80_device &sub(Z80(config, "sub", 4000000)); /* 4 MHz */ sub.set_addrmap(AS_PROGRAM, &mrsdyna_state::mrsdyna_cpu2_map); @@ -907,8 +907,8 @@ void sraider_state::sraider(machine_config &config) maincpu.set_addrmap(AS_PROGRAM, &sraider_state::mrsdyna_cpu1_map); maincpu.set_vblank_int("screen", FUNC(mrsdyna_state::irq0_line_hold)); - LATCH8(config, "soundlatch_low"); - LATCH8(config, "soundlatch_high"); + GENERIC_LATCH_8(config, "soundlatch_low"); + GENERIC_LATCH_8(config, "soundlatch_high"); z80_device &sub(Z80(config, "sub", 4000000)); /* 4 MHz */ sub.set_addrmap(AS_PROGRAM, &sraider_state::sraider_cpu2_map); -- cgit v1.2.3