diff --git a/src/devices/machine/z80dma.cpp b/src/devices/machine/z80dma.cpp index 1e6ce280b0fa3..050b1e66e3b83 100644 --- a/src/devices/machine/z80dma.cpp +++ b/src/devices/machine/z80dma.cpp @@ -179,6 +179,7 @@ void z80dma_device::device_start() save_item(NAME(m_rdy)); save_item(NAME(m_force_ready)); save_item(NAME(m_wait)); + save_item(NAME(m_waits_extra)); save_item(NAME(m_busrq_ack)); save_item(NAME(m_is_pulse)); save_item(NAME(m_latch)); @@ -197,6 +198,7 @@ void z80dma_device::device_reset() m_rdy = 0; m_force_ready = 0; m_wait = 0; + m_waits_extra = 0; m_num_follow = 0; m_read_num_follow = m_read_cur_follow = 0; m_reset_pointer = 0; @@ -497,7 +499,8 @@ TIMER_CALLBACK_MEMBER(z80dma_device::clock_w) } const attotime clock = clocks_to_attotime(1); - const attotime next = clock * (3 - ((PORTA_IS_SOURCE ? PORTA_TIMING : PORTB_TIMING) & 0x03)); + const attotime next = clock * (3 - ((PORTA_IS_SOURCE ? PORTA_TIMING : PORTB_TIMING) & 0x03) + m_waits_extra); + m_waits_extra = 0; m_timer->adjust(next, 0, clock); m_dma_seq = SEQ_TRANS1_READ_SOURCE; @@ -517,7 +520,8 @@ TIMER_CALLBACK_MEMBER(z80dma_device::clock_w) case SEQ_TRANS1_INC_DEC_DEST_ADDRESS: { const attotime clock = clocks_to_attotime(1); - const attotime next = clock * (3 - ((PORTB_IS_SOURCE ? PORTA_TIMING : PORTB_TIMING) & 0x03)); + const attotime next = clock * (3 - ((PORTB_IS_SOURCE ? PORTA_TIMING : PORTB_TIMING) & 0x03) + m_waits_extra); + m_waits_extra = 0; m_timer->adjust(next, 0, clock); m_dma_seq = SEQ_TRANS1_WRITE_DEST; diff --git a/src/devices/machine/z80dma.h b/src/devices/machine/z80dma.h index b461330eab027..08af2e5889090 100644 --- a/src/devices/machine/z80dma.h +++ b/src/devices/machine/z80dma.h @@ -66,6 +66,7 @@ class z80dma_device : public device_t, void iei_w(int state) { m_iei = state; interrupt_check(); } void rdy_w(int state); void wait_w(int state) { m_wait = state; } + void adjust_wait(int count) { m_waits_extra += count; } void bai_w(int state); protected: @@ -153,6 +154,7 @@ class z80dma_device : public device_t, u8 m_reset_pointer; int m_wait; + int m_waits_extra; int m_busrq_ack; bool m_is_pulse; u8 m_latch; diff --git a/src/mame/sinclair/specnext.cpp b/src/mame/sinclair/specnext.cpp index b005d2a34a4b3..de4afadcf2a7d 100644 --- a/src/mame/sinclair/specnext.cpp +++ b/src/mame/sinclair/specnext.cpp @@ -123,6 +123,7 @@ class specnext_state : public spectrum_128_state void mmu_x2_w(offs_t bank, u8 data); u8 dma_r(bool dma_mode); void dma_w(bool dma_mode, u8 data); + u8 dma_mreq_r(offs_t offset); u8 spi_data_r(); void spi_data_w(u8 data); void spi_miso_w(u8 data); @@ -1154,6 +1155,15 @@ void specnext_state::dma_w(bool dma_mode, u8 data) m_dma->write(data); } +u8 specnext_state::dma_mreq_r(offs_t offset) +{ + if (m_nr_07_cpu_speed == 0b11) + { + m_dma->adjust_wait(1); + } + return m_program.read_byte(offset); +} + u8 specnext_state::reg_r(offs_t nr_register) { u8 port_253b_dat; @@ -2405,6 +2415,12 @@ void specnext_state::map_fetch(address_map &map) approach gives better experience in debugger UI. */ do_m1(offset); m_divmmc_delayed_check = 0; + + // do_m1 performs read from m_program with waits, we need to take it back + if (!machine().side_effects_disabled() && (m_nr_07_cpu_speed == 0b11)) + { + m_maincpu->adjust_icount(1); + } } return m_program.read_byte(offset); @@ -3426,6 +3442,14 @@ void specnext_state::video_start() to[offset & 0x1fff] = data; } }); + prg.install_read_tap(0x0000, 0xffff, "mem_wait_r", [this](offs_t offset, u8 &data, u8 mem_mask) + { + // The 28MHz with core 3.0.5 is adding extra wait state to every instruction opcode fetch and memory read + if (!machine().side_effects_disabled() && (m_nr_07_cpu_speed == 0b11)) + { + m_maincpu->adjust_icount(-1); + } + }); } void specnext_state::tbblue(machine_config &config) @@ -3453,7 +3477,7 @@ void specnext_state::tbblue(machine_config &config) SPECNEXT_DMA(config, m_dma, 28_MHz_XTAL / 8); m_dma->out_busreq_callback().set_inputline(m_maincpu, Z80_INPUT_LINE_BUSRQ); m_dma->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); - m_dma->in_mreq_callback().set([this](offs_t offset) { return m_program.read_byte(offset); }); + m_dma->in_mreq_callback().set(FUNC(specnext_state::dma_mreq_r)); m_dma->out_mreq_callback().set([this](offs_t offset, u8 data) { m_program.write_byte(offset, data); }); m_dma->in_iorq_callback().set([this](offs_t offset) { return m_io.read_byte(offset); }); m_dma->out_iorq_callback().set([this](offs_t offset, u8 data) { m_io.write_byte(offset, data); });