From 82e294044499d0668620d8a7d81977171201303c Mon Sep 17 00:00:00 2001 From: hap Date: Sun, 23 Jul 2023 01:07:58 +0200 Subject: mos6530n: timer goes back to count mode when irq flag is cleared --- src/devices/machine/mos6530n.cpp | 101 +++++++++++++++++++++++---------------- src/devices/machine/mos6530n.h | 10 ++-- src/mame/gameplan/gameplan.cpp | 9 ++-- 3 files changed, 72 insertions(+), 48 deletions(-) diff --git a/src/devices/machine/mos6530n.cpp b/src/devices/machine/mos6530n.cpp index dd0560b7a53..3ede6240b0d 100644 --- a/src/devices/machine/mos6530n.cpp +++ b/src/devices/machine/mos6530n.cpp @@ -110,8 +110,7 @@ mos6530_device_base::mos6530_device_base(const machine_config &mconfig, device_t m_irq_timer(false), m_ie_edge(false), m_irq_edge(false) -{ -} +{ } //------------------------------------------------- @@ -197,10 +196,12 @@ void mos6530_device_base::update_pa() { uint8_t data = (m_pa_out & m_pa_ddr) | (m_pa_ddr ^ 0xff); - if (m_out8_pa_cb.isunset()) { + if (m_out8_pa_cb.isunset()) + { for (int i = 0; i < 8; i++) m_out_pa_cb[i](BIT(data, i)); - } else + } + else m_out8_pa_cb(data); } @@ -213,10 +214,12 @@ void mos6530_device_base::update_pb() { uint8_t data = (m_pb_out & m_pb_ddr) | (m_pb_ddr ^ 0xff); - if (m_out8_pb_cb.isunset()) { + if (m_out8_pb_cb.isunset()) + { for (int i = 0; i < 8; i++) m_out_pb_cb[i](BIT(data, i)); - } else + } + else m_out8_pb_cb(data); } @@ -224,7 +227,8 @@ void mos6530_new_device::update_pb() { uint8_t data = (m_pb_out & m_pb_ddr) | (m_pb_ddr ^ 0xff); - if (!BIT(m_pb_ddr, 7)) { + if (!BIT(m_pb_ddr, 7)) + { // active low! if (m_ie_timer && m_irq_timer) data &= ~IRQ_TIMER; @@ -232,10 +236,12 @@ void mos6530_new_device::update_pb() data |= IRQ_TIMER; } - if (m_out8_pb_cb.isunset()) { + if (m_out8_pb_cb.isunset()) + { for (int i = 0; i < 8; i++) m_out_pb_cb[i](BIT(data, i)); - } else + } + else m_out8_pb_cb(data); } @@ -300,6 +306,19 @@ uint8_t mos6530_device_base::get_timer() } +//------------------------------------------------- +// timer_start - restart timer counter +//------------------------------------------------- + +void mos6530_device_base::timer_start(uint8_t data) +{ + m_timerstate = TIMER_COUNTING; + attotime curtime = machine().time(); + int64_t target = curtime.as_ticks(clock()) + 1 + (data << m_timershift); + m_timer->adjust(attotime::from_ticks(target, clock()) - curtime); +} + + //------------------------------------------------- // timer_end - //------------------------------------------------- @@ -307,7 +326,8 @@ uint8_t mos6530_device_base::get_timer() TIMER_CALLBACK_MEMBER(mos6530_device_base::timer_end) { // if we finished counting, signal timer IRQ - if (m_timerstate == TIMER_COUNTING) { + if (m_timerstate == TIMER_COUNTING) + { m_timeout = machine().time(); m_irq_timer = true; update_irq(); @@ -319,22 +339,6 @@ TIMER_CALLBACK_MEMBER(mos6530_device_base::timer_end) } -//------------------------------------------------- -// timer_irq_enable - enable/clear timer IRQ -//------------------------------------------------- - -void mos6530_device_base::timer_irq_enable(bool ie) -{ - m_ie_timer = ie; - - // IRQ is not cleared if access is at same time IRQ is raised - if (m_timeout <= machine().time() - attotime::from_hz(clock())) - m_irq_timer = false; - - update_irq(); -} - - //------------------------------------------------- // edge_detect - //------------------------------------------------- @@ -344,7 +348,8 @@ void mos6530_device_base::edge_detect() uint8_t data = (m_pa_out & m_pa_ddr) | (m_pa_in & ~m_pa_ddr); int state = BIT(data, 7); - if ((m_pa7 ^ state) && !(m_pa7_dir ^ state) && !m_irq_edge) { + if ((m_pa7 ^ state) && !(m_pa7_dir ^ state) && !m_irq_edge) + { LOG("%s %s edge-detect IRQ\n", machine().time().as_string(), name()); m_irq_edge = true; @@ -391,10 +396,12 @@ uint8_t mos6530_device_base::pa_data_r() { uint8_t in = 0; - if (m_in8_pa_cb.isunset()) { + if (m_in8_pa_cb.isunset()) + { for (int i = 0; i < 8; i++) in |= (m_in_pa_cb[i].isunset() ? BIT(m_pa_in, i) : m_in_pa_cb[i]()) << i; - } else + } + else in = m_in8_pa_cb(); uint8_t data = (m_pa_out & m_pa_ddr) | (in & ~m_pa_ddr); @@ -443,10 +450,12 @@ uint8_t mos6530_device_base::pb_data_r() { uint8_t in = 0; - if (m_in8_pb_cb.isunset()) { + if (m_in8_pb_cb.isunset()) + { for (int i = 0; i < 8; i++) in |= (m_in_pb_cb[i].isunset() ? BIT(m_pb_in, i) : m_in_pb_cb[i]()) << i; - } else + } + else in = m_in8_pb_cb(); uint8_t data = (m_pb_out & m_pb_ddr) | (in & ~m_pb_ddr); @@ -503,8 +512,20 @@ uint8_t mos6530_device_base::timer_r(bool ie) { uint8_t data = get_timer(); - if (!machine().side_effects_disabled()) { - timer_irq_enable(ie); + if (!machine().side_effects_disabled()) + { + // IRQ is not cleared when reading at the same time IRQ is raised + if (m_timeout <= machine().time() - attotime::from_hz(clock())) + { + m_irq_timer = false; + + // timer goes back to count mode + if (m_timerstate == TIMER_SPINNING) + timer_start(data); + } + + m_ie_timer = ie; + update_irq(); LOGTIMER("%s %s %s Timer read %02x IE %u\n", machine().time().as_string(), machine().describe_context(), name(), data, m_ie_timer ? 1 : 0); } @@ -521,7 +542,8 @@ uint8_t mos6530_device_base::irq_r() { uint8_t data = get_irq_flags(); - if (!machine().side_effects_disabled() && m_irq_edge) { + if (!machine().side_effects_disabled() && m_irq_edge) + { m_irq_edge = false; update_irq(); } @@ -549,16 +571,13 @@ void mos6530_device_base::timer_w(offs_t offset, uint8_t data, bool ie) // A0-A1 contain the prescaler static const uint8_t timershift[4] = { 0, 3, 6, 10 }; m_timershift = timershift[offset & 3]; + timer_start(data); - timer_irq_enable(ie); + m_irq_timer = false; + m_ie_timer = ie; + update_irq(); LOGTIMER("%s %s %s Timer value %02x prescale %u IE %u\n", machine().time().as_string(), machine().describe_context(), name(), data, 1 << m_timershift, m_ie_timer ? 1 : 0); - - // update the timer - m_timerstate = TIMER_COUNTING; - attotime curtime = machine().time(); - int64_t target = curtime.as_ticks(clock()) + 1 + (data << m_timershift); - m_timer->adjust(attotime::from_ticks(target, clock()) - curtime); } diff --git a/src/devices/machine/mos6530n.h b/src/devices/machine/mos6530n.h index 0434b7f6e3b..f7030df218f 100644 --- a/src/devices/machine/mos6530n.h +++ b/src/devices/machine/mos6530n.h @@ -92,12 +92,14 @@ protected: virtual void device_start() override; virtual void device_reset() override; - enum { + enum + { IRQ_EDGE = 0x40, IRQ_TIMER = 0x80 }; - enum { + enum + { TIMER_COUNTING, TIMER_SPINNING }; @@ -106,9 +108,9 @@ protected: virtual void update_pb(); virtual void update_irq(); virtual uint8_t get_irq_flags(); - TIMER_CALLBACK_MEMBER(timer_end); uint8_t get_timer(); - void timer_irq_enable(bool ie); + void timer_start(uint8_t data); + TIMER_CALLBACK_MEMBER(timer_end); void edge_detect(); void pa_w(int bit, int state); diff --git a/src/mame/gameplan/gameplan.cpp b/src/mame/gameplan/gameplan.cpp index 70fbe0a85f3..897be8ac5e6 100644 --- a/src/mame/gameplan/gameplan.cpp +++ b/src/mame/gameplan/gameplan.cpp @@ -80,6 +80,9 @@ TODO: reading from VIA1. It's possible to fix with a simple wire mod/pcb cut trace, like done with piratetr_main_map. Let's assume they did something like that. +BTANB: +- BGM stops in leprechn when you touch a tree + ****************************************************************************/ #include "emu.h" @@ -163,8 +166,8 @@ uint32_t gameplan_state::screen_update(screen_device &screen, bitmap_ind16 &bitm TIMER_CALLBACK_MEMBER(gameplan_state::hblank_callback) { - // screen !HBLANK is tied to VIA1 PB6 - m_via[0]->write_pb6(param ^ 1); + // screen HBLANK is tied to VIA1 PB6 + m_via[0]->write_pb6(param); } @@ -1110,7 +1113,7 @@ void gameplan_state::gameplan_video(machine_config &config) SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_raw(11.6688_MHz_XTAL / 2, 352, 0, 256, 280, 0, 256); m_screen->set_screen_update(FUNC(gameplan_state::screen_update)); - m_screen->screen_vblank().set(m_via[0], FUNC(via6522_device::write_ca1)).invert(); // !VBLANK is connected to CA1 + m_screen->screen_vblank().set(m_via[0], FUNC(via6522_device::write_ca1)); // VBLANK is connected to CA1 m_screen->set_palette("palette"); PALETTE(config, "palette", palette_device::RGB_3BIT); -- cgit v1.2.3