diff --git a/src/devices/cpu/mb88xx/mb88xx.cpp b/src/devices/cpu/mb88xx/mb88xx.cpp index fe07ba80d2c..f606f8a80ec 100644 --- a/src/devices/cpu/mb88xx/mb88xx.cpp +++ b/src/devices/cpu/mb88xx/mb88xx.cpp @@ -368,8 +368,10 @@ int mb88_cpu_device::pla( int inA, int inB ) void mb88_cpu_device::execute_set_input(int inputnum, int state) { - /* on rising edge trigger interrupt */ - if ( (m_pio & 0x04) && !m_nf && state != CLEAR_LINE ) + /* On rising edge trigger interrupt. + * Note this is a logical level, the actual pin is high-to-low voltage + * triggered. */ + if ( (m_pio & INT_CAUSE_EXTERNAL) && !m_nf && state != CLEAR_LINE ) { m_pending_interrupt |= INT_CAUSE_EXTERNAL; } @@ -437,6 +439,9 @@ void mb88_cpu_device::update_pio( int cycles ) { /* if we have a live external source, call the irqcallback */ standard_irq_callback( 0 ); + /* The datasheet doesn't mention if the interrupt flag + * is cleared, but it seems to be only for this case. */ + m_pio &= ~INT_CAUSE_EXTERNAL; m_PC = 0x02; } else if (m_pending_interrupt & m_pio & INT_CAUSE_TIMER) diff --git a/src/mame/audio/namco52.cpp b/src/mame/audio/namco52.cpp index 65e25c87382..48513fb6b2e 100644 --- a/src/mame/audio/namco52.cpp +++ b/src/mame/audio/namco52.cpp @@ -56,11 +56,6 @@ WRITE_LINE_MEMBER( namco_52xx_device::reset ) m_cpu->set_input_line(INPUT_LINE_RESET, !state); } -TIMER_CALLBACK_MEMBER( namco_52xx_device::latch_callback ) -{ - m_latched_cmd = param; -} - uint8_t namco_52xx_device::K_r() { return m_latched_cmd & 0x0f; @@ -108,16 +103,17 @@ void namco_52xx_device::O_w(uint8_t data) void namco_52xx_device::write(uint8_t data) { - machine().scheduler().synchronize(timer_expired_delegate(FUNC(namco_52xx_device::latch_callback),this), data); + machine().scheduler().synchronize(timer_expired_delegate(FUNC(namco_52xx_device::write_sync),this), data); +} - // TODO: should use chip_select line for this - m_cpu->pulse_input_line(0, m_irq_duration); +TIMER_CALLBACK_MEMBER( namco_52xx_device::write_sync ) +{ + m_latched_cmd = param; } WRITE_LINE_MEMBER( namco_52xx_device::chip_select ) { - // TODO: broken sound when using this - //m_cpu->set_input_line(0, state); + m_cpu->set_input_line(0, state); } TIMER_CALLBACK_MEMBER( namco_52xx_device::external_clock_pulse ) @@ -143,7 +139,6 @@ namco_52xx_device::namco_52xx_device(const machine_config &mconfig, const char * : device_t(mconfig, NAMCO_52XX, tag, owner, clock), m_cpu(*this, "mcu"), m_discrete(*this, finder_base::DUMMY_TAG), - m_irq_duration(attotime::from_usec(100)), m_basenode(0), m_extclock(0), m_romread(*this), diff --git a/src/mame/audio/namco52.h b/src/mame/audio/namco52.h index b4f56762c9d..a775921b6a7 100644 --- a/src/mame/audio/namco52.h +++ b/src/mame/audio/namco52.h @@ -16,7 +16,6 @@ public: void set_extclock(attoseconds_t clk) { m_extclock = clk; } auto romread_callback() { return m_romread.bind(); } auto si_callback() { return m_si.bind(); } - namco_52xx_device &set_irq_duration(attotime t) { m_irq_duration = t; return *this; } DECLARE_WRITE_LINE_MEMBER( reset ); WRITE_LINE_MEMBER( chip_select ); @@ -28,7 +27,7 @@ protected: virtual const tiny_rom_entry *device_rom_region() const override; virtual void device_add_mconfig(machine_config &config) override; - TIMER_CALLBACK_MEMBER( latch_callback ); + TIMER_CALLBACK_MEMBER( write_sync ); TIMER_CALLBACK_MEMBER( external_clock_pulse ); private: @@ -36,7 +35,6 @@ private: required_device m_cpu; required_device m_discrete; - attotime m_irq_duration; int m_basenode; attoseconds_t m_extclock; emu_timer *m_extclock_pulse_timer; diff --git a/src/mame/audio/namco54.cpp b/src/mame/audio/namco54.cpp index 0c908b523ec..891cb957d0c 100644 --- a/src/mame/audio/namco54.cpp +++ b/src/mame/audio/namco54.cpp @@ -52,10 +52,6 @@ #include "emu.h" #include "namco54.h" -TIMER_CALLBACK_MEMBER( namco_54xx_device::latch_callback ) -{ - m_latched_cmd = param; -} WRITE_LINE_MEMBER( namco_54xx_device::reset ) { @@ -92,16 +88,18 @@ void namco_54xx_device::R1_w(uint8_t data) void namco_54xx_device::write(uint8_t data) { - machine().scheduler().synchronize(timer_expired_delegate(FUNC(namco_54xx_device::latch_callback),this), data); - - // TODO: should use chip_select line for this - m_cpu->pulse_input_line(0, m_irq_duration); + machine().scheduler().synchronize(timer_expired_delegate(FUNC(namco_54xx_device::write_sync),this), data); } +TIMER_CALLBACK_MEMBER( namco_54xx_device::write_sync ) +{ + m_latched_cmd = param; +} + + WRITE_LINE_MEMBER( namco_54xx_device::chip_select ) { - // TODO: broken sound when using this - //m_cpu->set_input_line(0, state); + m_cpu->set_input_line(0, state); } @@ -120,7 +118,6 @@ namco_54xx_device::namco_54xx_device(const machine_config &mconfig, const char * : device_t(mconfig, NAMCO_54XX, tag, owner, clock), m_cpu(*this, "mcu"), m_discrete(*this, finder_base::DUMMY_TAG), - m_irq_duration(attotime::from_usec(100)), m_basenode(0), m_latched_cmd(0) { diff --git a/src/mame/audio/namco54.h b/src/mame/audio/namco54.h index b809a59a115..6bb0264820f 100644 --- a/src/mame/audio/namco54.h +++ b/src/mame/audio/namco54.h @@ -14,7 +14,6 @@ public: template void set_discrete(T &&tag) { m_discrete.set_tag(std::forward(tag)); } void set_basenote(int node) { m_basenode = node; } - namco_54xx_device &set_irq_duration(attotime t) { m_irq_duration = t; return *this; } DECLARE_WRITE_LINE_MEMBER( reset ); WRITE_LINE_MEMBER( chip_select ); @@ -26,14 +25,11 @@ protected: virtual const tiny_rom_entry *device_rom_region() const override; virtual void device_add_mconfig(machine_config &config) override; - TIMER_CALLBACK_MEMBER( latch_callback ); - private: // internal state required_device m_cpu; required_device m_discrete; - attotime m_irq_duration; int m_basenode; uint8_t m_latched_cmd; @@ -41,6 +37,7 @@ private: uint8_t R0_r(); void O_w(uint8_t data); void R1_w(uint8_t data); + TIMER_CALLBACK_MEMBER( write_sync ); }; DECLARE_DEVICE_TYPE(NAMCO_54XX, namco_54xx_device) diff --git a/src/mame/drivers/galaga.cpp b/src/mame/drivers/galaga.cpp index 3e086ca8fde..4fa12aef4cf 100644 --- a/src/mame/drivers/galaga.cpp +++ b/src/mame/drivers/galaga.cpp @@ -1607,7 +1607,6 @@ void bosco_state::bosco(machine_config &config) namco_54xx_device &n54xx(NAMCO_54XX(config, "54xx", MASTER_CLOCK/6/2)); /* 1.536 MHz */ n54xx.set_discrete("discrete"); n54xx.set_basenote(NODE_01); - n54xx.set_irq_duration(attotime::from_usec(200)); namco_06xx_device &n06xx_0(NAMCO_06XX(config, "06xx_0", MASTER_CLOCK/6/64)); n06xx_0.set_maincpu(m_maincpu); @@ -1615,18 +1614,19 @@ void bosco_state::bosco(machine_config &config) n06xx_0.rw_callback<0>().set("51xx", FUNC(namco_51xx_device::rw)); n06xx_0.read_callback<0>().set("51xx", FUNC(namco_51xx_device::read)); n06xx_0.write_callback<0>().set("51xx", FUNC(namco_51xx_device::write)); - n06xx_0.read_callback<2>().set("50xx_1", FUNC(namco_50xx_device::read)); n06xx_0.chip_select_callback<2>().set("50xx_1", FUNC(namco_50xx_device::chip_select)); n06xx_0.rw_callback<2>().set("50xx_1", FUNC(namco_50xx_device::rw)); + n06xx_0.read_callback<2>().set("50xx_1", FUNC(namco_50xx_device::read)); n06xx_0.write_callback<2>().set("50xx_1", FUNC(namco_50xx_device::write)); - n06xx_0.write_callback<3>().set("54xx", FUNC(namco_54xx_device::write)); n06xx_0.chip_select_callback<3>().set("54xx", FUNC(namco_54xx_device::chip_select)); + n06xx_0.write_callback<3>().set("54xx", FUNC(namco_54xx_device::write)); - namco_06xx_device &n06xx_1(NAMCO_06XX(config, "06xx_1", MASTER_CLOCK/6/64)); + // The clock should be hblank, but approx with 512. + namco_06xx_device &n06xx_1(NAMCO_06XX(config, "06xx_1", MASTER_CLOCK/6/512)); n06xx_1.set_maincpu(m_subcpu); n06xx_1.read_callback<0>().set("50xx_2", FUNC(namco_50xx_device::read)); n06xx_1.chip_select_callback<0>().set("50xx_2", FUNC(namco_50xx_device::chip_select)); - n06xx_1.rw_callback<2>().set("50xx_2", FUNC(namco_50xx_device::rw)); + n06xx_1.rw_callback<0>().set("50xx_2", FUNC(namco_50xx_device::rw)); n06xx_1.write_callback<0>().set("50xx_2", FUNC(namco_50xx_device::write)); n06xx_1.write_callback<1>().set("52xx", FUNC(namco_52xx_device::write)); n06xx_1.chip_select_callback<1>().set("52xx", FUNC(namco_52xx_device::chip_select)); diff --git a/src/mame/machine/namco06.cpp b/src/mame/machine/namco06.cpp index 37ec9688327..df37c79d1c6 100644 --- a/src/mame/machine/namco06.cpp +++ b/src/mame/machine/namco06.cpp @@ -106,23 +106,16 @@ TIMER_CALLBACK_MEMBER( namco_06xx_device::nmi_generate ) // // During reads, the first NMI pulse is supressed to give the chip a // cycle to write. - // - // If the control register is written while CS is asserted, RW won't be - // changed until the next rising edge. - if (m_rw_change && m_next_timer_state) + if (m_next_timer_state) { - if (!m_rw_stretch) - { - m_rw[0](0, BIT(m_control, 4)); - m_rw[1](0, BIT(m_control, 4)); - m_rw[2](0, BIT(m_control, 4)); - m_rw[3](0, BIT(m_control, 4)); - m_rw_change = false; - } + m_rw[0](0, BIT(m_control, 4)); + m_rw[1](0, BIT(m_control, 4)); + m_rw[2](0, BIT(m_control, 4)); + m_rw[3](0, BIT(m_control, 4)); } - if (m_next_timer_state && !m_nmi_stretch ) + if (m_next_timer_state && !m_read_stretch) { set_nmi(ASSERT_LINE); } @@ -130,6 +123,7 @@ TIMER_CALLBACK_MEMBER( namco_06xx_device::nmi_generate ) { set_nmi(CLEAR_LINE); } + m_read_stretch = false; m_chipsel[0](0, BIT(m_control, 0) && m_next_timer_state); m_chipsel[1](0, BIT(m_control, 1) && m_next_timer_state); @@ -137,8 +131,6 @@ TIMER_CALLBACK_MEMBER( namco_06xx_device::nmi_generate ) m_chipsel[3](0, BIT(m_control, 3) && m_next_timer_state); m_next_timer_state = !m_next_timer_state; - m_nmi_stretch = false; - m_rw_stretch = false; } uint8_t namco_06xx_device::data_r(offs_t offset) @@ -161,16 +153,21 @@ uint8_t namco_06xx_device::data_r(offs_t offset) void namco_06xx_device::data_w(offs_t offset, uint8_t data) +{ + machine().scheduler().synchronize(timer_expired_delegate(FUNC(namco_06xx_device::write_sync),this), data); +} + +TIMER_CALLBACK_MEMBER( namco_06xx_device::write_sync ) { if (BIT(m_control, 4)) { logerror("%s: 06XX '%s' write in read mode %02x\n",machine().describe_context(),tag(),m_control); return; } - if (BIT(m_control, 0)) m_write[0](0, data); - if (BIT(m_control, 1)) m_write[1](0, data); - if (BIT(m_control, 2)) m_write[2](0, data); - if (BIT(m_control, 3)) m_write[3](0, data); + if (BIT(m_control, 0)) m_write[0](0, param); + if (BIT(m_control, 1)) m_write[1](0, param); + if (BIT(m_control, 2)) m_write[2](0, param); + if (BIT(m_control, 3)) m_write[3](0, param); } @@ -181,34 +178,56 @@ uint8_t namco_06xx_device::ctrl_r() void namco_06xx_device::ctrl_w(uint8_t data) { - m_control = data; + machine().scheduler().synchronize(timer_expired_delegate(FUNC(namco_06xx_device::ctrl_w_sync),this), data); +} + +TIMER_CALLBACK_MEMBER( namco_06xx_device::ctrl_w_sync ) +{ + m_control = param; // The upper 3 control bits are the clock divider. if ((m_control & 0xe0) == 0) { m_nmi_timer->adjust(attotime::never); + m_next_timer_state = true; set_nmi(CLEAR_LINE); m_chipsel[0](0, CLEAR_LINE); m_chipsel[1](0, CLEAR_LINE); m_chipsel[2](0, CLEAR_LINE); m_chipsel[3](0, CLEAR_LINE); - // Setting this to true makes the next RW change not stretch. - m_next_timer_state = true; + // RW is left as-is } else { - m_rw_stretch = !m_next_timer_state; - m_rw_change = true; - m_next_timer_state = true; - m_nmi_stretch = BIT(m_control, 4); - // NMI is cleared immediately if its to be stretched. - if (m_nmi_stretch) set_nmi(CLEAR_LINE); + // NMI is cleared immediately if this is a read + // It will be supressed the next clock cycle. + if (BIT(m_control, 4)) + { + set_nmi(CLEAR_LINE); + m_read_stretch = true; + } else { + m_read_stretch = false; + } + uint8_t num_shifts = (m_control & 0xe0) >> 5; uint8_t divisor = 1 << num_shifts; - // The next change should happen on the next clock falling edge. - // Xevious' race causes this to bootloopsif it isn't 0. - m_nmi_timer->adjust(attotime::zero, 0, attotime::from_hz(clock() / divisor) / 2); + attotime period = attotime::from_hz(clock() / divisor) / 2; + // This delay should be the next falling clock. + // That's complicated to get, as it's derived from the master + // clock. The CPU uses this same clock, so writes will come at + // a specific pace. + // Instead, just approximate a quarter cycle. + // Xevious is very sensitive to this. It will bootloop if it + // isn't correct. + attotime delay = attotime::from_hz(clock()) / 4; // average of one clock + if (!m_next_timer_state) + { + // NMI is asserted, wait one additional clock to start + m_nmi_timer->adjust(delay + attotime::from_hz(clock() / divisor), 0, period); + } else { + m_nmi_timer->adjust(delay, 0, period); + } } } @@ -228,9 +247,7 @@ namco_06xx_device::namco_06xx_device(const machine_config &mconfig, const char * : device_t(mconfig, NAMCO_06XX, tag, owner, clock) , m_control(0) , m_next_timer_state(false) - , m_nmi_stretch(false) - , m_rw_stretch(false) - , m_rw_change(false) + , m_read_stretch(false) , m_nmicpu(*this, finder_base::DUMMY_TAG) , m_chipsel(*this) , m_rw(*this) @@ -255,9 +272,7 @@ void namco_06xx_device::device_start() save_item(NAME(m_control)); save_item(NAME(m_next_timer_state)); - save_item(NAME(m_nmi_stretch)); - save_item(NAME(m_rw_stretch)); - save_item(NAME(m_rw_change)); + save_item(NAME(m_read_stretch)); } //------------------------------------------------- diff --git a/src/mame/machine/namco06.h b/src/mame/machine/namco06.h index fad249135a6..885305ef902 100644 --- a/src/mame/machine/namco06.h +++ b/src/mame/machine/namco06.h @@ -33,14 +33,14 @@ private: void set_nmi(int state); TIMER_CALLBACK_MEMBER( nmi_generate ); + TIMER_CALLBACK_MEMBER( write_sync ); + TIMER_CALLBACK_MEMBER( ctrl_w_sync ); // internal state emu_timer *m_nmi_timer; uint8_t m_control; bool m_next_timer_state; - bool m_nmi_stretch; - bool m_rw_stretch; - bool m_rw_change; + bool m_read_stretch; required_device m_nmicpu; diff --git a/src/mame/machine/namco50.cpp b/src/mame/machine/namco50.cpp index d9dad75941e..8baf8cb4bd5 100644 --- a/src/mame/machine/namco50.cpp +++ b/src/mame/machine/namco50.cpp @@ -159,8 +159,13 @@ uint8_t namco_50xx_device::R2_r() void namco_50xx_device::O_w(uint8_t data) { - uint8_t out = (data & 0x0f); - if (data & 0x10) + machine().scheduler().synchronize(timer_expired_delegate(FUNC(namco_50xx_device::O_w_sync),this), data); +} + +TIMER_CALLBACK_MEMBER( namco_50xx_device::O_w_sync ) +{ + uint8_t out = (param & 0x0f); + if (param & 0x10) m_portO = (m_portO & 0x0f) | (out << 4); else m_portO = (m_portO & 0xf0) | (out); diff --git a/src/mame/machine/namco50.h b/src/mame/machine/namco50.h index 28d8b4eed04..d24a52b8f35 100644 --- a/src/mame/machine/namco50.h +++ b/src/mame/machine/namco50.h @@ -32,6 +32,7 @@ private: uint8_t m_cmd; uint8_t m_portO; + TIMER_CALLBACK_MEMBER( O_w_sync ); TIMER_CALLBACK_MEMBER( rw_sync ); TIMER_CALLBACK_MEMBER( write_sync ); diff --git a/src/mame/machine/namco51.cpp b/src/mame/machine/namco51.cpp index fb4965cfd5f..1e574993a89 100644 --- a/src/mame/machine/namco51.cpp +++ b/src/mame/machine/namco51.cpp @@ -130,8 +130,13 @@ uint8_t namco_51xx_device::R3_r() void namco_51xx_device::O_w(uint8_t data) { - uint8_t out = (data & 0x0f); - if (data & 0x10) + machine().scheduler().synchronize(timer_expired_delegate(FUNC(namco_51xx_device::O_w_sync),this), data); +} + +TIMER_CALLBACK_MEMBER( namco_51xx_device::O_w_sync ) +{ + uint8_t out = (param & 0x0f); + if (param & 0x10) m_portO = (m_portO & 0x0f) | (out << 4); else m_portO = (m_portO & 0xf0) | (out); diff --git a/src/mame/machine/namco51.h b/src/mame/machine/namco51.h index 392e94c735f..35cec6458f2 100644 --- a/src/mame/machine/namco51.h +++ b/src/mame/machine/namco51.h @@ -49,6 +49,7 @@ private: TIMER_CALLBACK_MEMBER( rw_sync ); TIMER_CALLBACK_MEMBER( write_sync ); + TIMER_CALLBACK_MEMBER( O_w_sync ); }; DECLARE_DEVICE_TYPE(NAMCO_51XX, namco_51xx_device)