From d5110f65a44f443beb2649368c21cec9e043e0c1 Mon Sep 17 00:00:00 2001 From: holub Date: Sun, 12 Mar 2023 12:47:09 -0400 Subject: sinclair/tsconf.cpp: Improved interrupt priorities. (#10976) --- src/mame/sinclair/spectrum.h | 4 +-- src/mame/sinclair/tsconf.cpp | 7 ++++- src/mame/sinclair/tsconf.h | 12 ++++--- src/mame/sinclair/tsconf_m.cpp | 71 ++++++++++++++++++++++++++++-------------- 4 files changed, 64 insertions(+), 30 deletions(-) diff --git a/src/mame/sinclair/spectrum.h b/src/mame/sinclair/spectrum.h index 58256cccf10..8cee77b453c 100644 --- a/src/mame/sinclair/spectrum.h +++ b/src/mame/sinclair/spectrum.h @@ -94,8 +94,8 @@ protected: virtual void spectrum_128_update_memory() { } virtual void ts2068_update_memory() { } - TIMER_CALLBACK_MEMBER(irq_on); - TIMER_CALLBACK_MEMBER(irq_off); + virtual TIMER_CALLBACK_MEMBER(irq_on); + virtual TIMER_CALLBACK_MEMBER(irq_off); TIMER_CALLBACK_MEMBER(finish_screen_update); emu_timer *m_irq_on_timer; diff --git a/src/mame/sinclair/tsconf.cpp b/src/mame/sinclair/tsconf.cpp index 7b96902865e..df86bcfadd9 100644 --- a/src/mame/sinclair/tsconf.cpp +++ b/src/mame/sinclair/tsconf.cpp @@ -177,7 +177,7 @@ void tsconf_state::video_start() m_ts_tilemap[TM_TILES1]->set_transparent_pen(0); m_frame_irq_timer = timer_alloc(FUNC(tsconf_state::irq_frame), this); - m_line_irq_timer = timer_alloc(FUNC(tsconf_state::irq_scanline), this); + m_scanline_irq_timer = timer_alloc(FUNC(tsconf_state::irq_scanline), this); } void tsconf_state::machine_start() @@ -196,6 +196,10 @@ void tsconf_state::machine_start() void tsconf_state::machine_reset() { + m_frame_irq_timer->adjust(attotime::never); + m_scanline_irq_timer->adjust(attotime::never); + m_int_mask = 0; + m_bank0_rom.select(0); m_glukrs->disable(); @@ -247,6 +251,7 @@ void tsconf_state::tsconf(machine_config &config) m_maincpu->set_addrmap(AS_PROGRAM, &tsconf_state::tsconf_mem); m_maincpu->set_addrmap(AS_IO, &tsconf_state::tsconf_io); m_maincpu->set_addrmap(AS_OPCODES, &tsconf_state::tsconf_switch); + m_maincpu->set_irq_acknowledge_callback(FUNC(tsconf_state::irq_vector)); m_maincpu->set_vblank_int("screen", FUNC(tsconf_state::tsconf_vblank_interrupt)); diff --git a/src/mame/sinclair/tsconf.h b/src/mame/sinclair/tsconf.h index e39c8491792..1cacdc93757 100644 --- a/src/mame/sinclair/tsconf.h +++ b/src/mame/sinclair/tsconf.h @@ -46,10 +46,12 @@ public: static constexpr u16 with_vblank(u16 pixclocks) { return 32 + pixclocks; } protected: - virtual void video_start() override; - virtual void machine_start() override; - virtual void machine_reset() override; + void video_start() override; + void machine_start() override; + void machine_reset() override; + TIMER_CALLBACK_MEMBER(irq_on) override; + TIMER_CALLBACK_MEMBER(irq_off) override; TIMER_CALLBACK_MEMBER(irq_frame); TIMER_CALLBACK_MEMBER(irq_scanline); @@ -132,9 +134,11 @@ private: void update_frame_timer(); emu_timer *m_frame_irq_timer = nullptr; - emu_timer *m_line_irq_timer = nullptr; + emu_timer *m_scanline_irq_timer = nullptr; INTERRUPT_GEN_MEMBER(tsconf_vblank_interrupt); + IRQ_CALLBACK_MEMBER(irq_vector); + u8 m_int_mask; DECLARE_VIDEO_START(tsconf); TILE_GET_INFO_MEMBER(get_tile_info_txt); diff --git a/src/mame/sinclair/tsconf_m.cpp b/src/mame/sinclair/tsconf_m.cpp index 2964eee326a..0d9a7cb8994 100644 --- a/src/mame/sinclair/tsconf_m.cpp +++ b/src/mame/sinclair/tsconf_m.cpp @@ -613,7 +613,7 @@ void tsconf_state::tsconf_port_xxaf_w(offs_t port, u8 data) case SYS_CONFIG: // 0 - 3.5MHz, 1 - 7MHz, 2 - 14MHz, 3 - reserved - m_maincpu->set_clock(3.5_MHz_XTAL * (1 << (data & 0x03))); + m_maincpu->set_clock_scale(1 << (data & 0x03)); m_regs[CACHE_CONFIG] = BIT(data, 2) ? 0x0f : 0x00; break; @@ -745,15 +745,48 @@ void tsconf_state::tsconf_spi_miso_w(u8 data) m_zctl_di |= data; } +IRQ_CALLBACK_MEMBER(tsconf_state::irq_vector) +{ + u8 vector = 0xff; + if (m_int_mask & 1) + m_int_mask &= ~1; + else if (m_int_mask & 2) + { + m_int_mask &= ~2; + vector = 0xfd; + } + else if (m_int_mask & 4) + { + m_int_mask &= ~4; + vector = 0xfb; + } + + if (!m_int_mask) + m_maincpu->set_input_line(0, CLEAR_LINE); + + return vector; +} + +TIMER_CALLBACK_MEMBER(tsconf_state::irq_on) +{ + m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); + m_irq_off_timer->adjust(attotime::from_ticks(32, m_maincpu->unscaled_clock())); +} + +TIMER_CALLBACK_MEMBER(tsconf_state::irq_off) +{ + m_int_mask = 0; + m_maincpu->set_input_line(0, CLEAR_LINE); +} + void tsconf_state::update_frame_timer() { u16 vpos = OFFS_512(VS_INT_L); u16 hpos = m_regs[HS_INT]; - if (hpos > 0 && vpos <= 319 && hpos <= 223) - // Only if not overlapping with scanline. Otherwise we need to prioritize. - m_frame_irq_timer->adjust(m_screen->time_until_pos(vpos, hpos << 1)); - else - m_frame_irq_timer->adjust(attotime::never); + attotime at = (BIT(m_regs[INT_MASK], 0) && vpos <= 319 && hpos <= 223) ? m_screen->time_until_pos(vpos, hpos << 1) : m_screen->time_until_pos(0, 0); + if (at >= m_screen->frame_period()) + at = attotime::zero; + m_frame_irq_timer->adjust(at); m_gfx_y_frame_offset = -get_screen_area().top(); } @@ -761,43 +794,35 @@ void tsconf_state::update_frame_timer() INTERRUPT_GEN_MEMBER(tsconf_state::tsconf_vblank_interrupt) { update_frame_timer(); - m_line_irq_timer->adjust(attotime::zero); + m_scanline_irq_timer->adjust(attotime::zero); } void tsconf_state::dma_ready(int line) { if (BIT(m_regs[INT_MASK], 4)) { - m_maincpu->set_input_line_and_vector(line, ASSERT_LINE, 0xfb); - m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03)))); + m_int_mask |= 4; + m_irq_on_timer->adjust(attotime::zero); } } TIMER_CALLBACK_MEMBER(tsconf_state::irq_frame) { if (BIT(m_regs[INT_MASK], 0)) - { - m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xff); - m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03)))); - } + m_int_mask |= 1; + m_irq_on_timer->adjust(attotime::zero); } TIMER_CALLBACK_MEMBER(tsconf_state::irq_scanline) { - u16 screen_vpos = m_screen->vpos(); - m_line_irq_timer->adjust(m_screen->time_until_pos(screen_vpos + 1)); if (BIT(m_regs[INT_MASK], 1)) { - m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xfd); - // Not quite precise. Scanline can't be skipped. - m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03)))); - } - if (BIT(m_regs[INT_MASK], 0) && OFFS_512(VS_INT_L) == screen_vpos && m_regs[HS_INT] == 0) - { - m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xff); - m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03)))); + m_int_mask |= 2; + m_irq_on_timer->adjust(attotime::zero); } + u16 screen_vpos = m_screen->vpos(); + m_scanline_irq_timer->adjust(m_screen->time_until_pos(screen_vpos + 1)); m_screen->update_now(); for (const auto &[reg, val] : m_scanline_delayed_regs_update) { -- cgit v1.2.3