diff --git a/src/devices/machine/z80dma.cpp b/src/devices/machine/z80dma.cpp index b89c4534914..2615c4e3b57 100644 --- a/src/devices/machine/z80dma.cpp +++ b/src/devices/machine/z80dma.cpp @@ -896,59 +896,3 @@ ua858d_device::ua858d_device(const machine_config &mconfig, const char *tag, dev : z80dma_device(mconfig, UA858D, tag, owner, clock, dma_mode::UA858D) { } - - -DEFINE_DEVICE_TYPE(SPECNEXT_DMA, specnext_dma_device, "specnext_dma", "Spectrum Next DMA") - -specnext_dma_device::specnext_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : z80dma_device(mconfig, SPECNEXT_DMA, tag, owner, clock, dma_mode::SPEC_NEXT) -{ -} - -void specnext_dma_device::do_write() -{ - if (m_dma_mode != dma_mode::SPEC_NEXT) - { - z80dma_device::do_write(); - } - else - { - if (m_byte_counter) - m_addressB += PORTB_FIXED ? 0 : PORTB_INC ? 1 : -1; - - switch (TRANSFER_MODE) - { - case TM_TRANSFER: - do_transfer_write(); - break; - - case TM_SEARCH: - do_search(); - break; - - case TM_SEARCH_TRANSFER: - do_transfer_write(); - do_search(); - break; - - default: - logerror("z80dma_do_operation: invalid mode %d!\n", TRANSFER_MODE); - break; - } - - m_addressA += PORTA_FIXED ? 0 : PORTA_INC ? 1 : -1; - - m_byte_counter++; - if ((m_byte_counter + 1) == m_count) - m_byte_counter++; - } -} - -void specnext_dma_device::write(u8 data) -{ - if (m_dma_mode == dma_mode::SPEC_NEXT && data == COMMAND_ENABLE_DMA && num_follow() == 0) - { - m_byte_counter = 0; - } - z80dma_device::write(data); -} diff --git a/src/devices/machine/z80dma.h b/src/devices/machine/z80dma.h index b7b2c3702db..11466cd197f 100644 --- a/src/devices/machine/z80dma.h +++ b/src/devices/machine/z80dma.h @@ -51,8 +51,7 @@ public: enum class dma_mode : u8 { ZILOG = 0, - UA858D = 1, - SPEC_NEXT = 2 + UA858D = 1 }; // construction/destruction @@ -179,20 +178,8 @@ public: ua858d_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); }; -class specnext_dma_device : public z80dma_device -{ -public: - specnext_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - - virtual void write(u8 data) override; - -protected: - virtual void do_write() override; -}; - // device type definition DECLARE_DEVICE_TYPE(Z80DMA, z80dma_device) DECLARE_DEVICE_TYPE(UA858D, ua858d_device) -DECLARE_DEVICE_TYPE(SPECNEXT_DMA, specnext_dma_device) #endif // MAME_MACHINE_Z80DMA_H diff --git a/src/mame/sinclair/specnext.cpp b/src/mame/sinclair/specnext.cpp index b2509995d6c..187c5166906 100644 --- a/src/mame/sinclair/specnext.cpp +++ b/src/mame/sinclair/specnext.cpp @@ -25,6 +25,7 @@ #include "specnext_copper.h" #include "specnext_ctc.h" #include "specnext_divmmc.h" +#include "specnext_dma.h" #include "specnext_multiface.h" #include "specnext_layer2.h" #include "specnext_lores.h" @@ -35,7 +36,6 @@ #include "cpu/z80/z80n.h" #include "machine/i2cmem.h" #include "machine/spi_sdcard.h" -#include "machine/z80dma.h" #include "sound/ay8910.h" #include "sound/dac.h" #include "speaker.h" @@ -1146,13 +1146,13 @@ void specnext_state::mmu_x2_w(offs_t bank, u8 data) u8 specnext_state::dma_r(bool dma_mode) { - m_dma->set_dma_mode(dma_mode ? z80dma_device::dma_mode::ZILOG : z80dma_device::dma_mode::SPEC_NEXT); + m_dma->dma_mode_w(dma_mode); return m_dma->read(); } void specnext_state::dma_w(bool dma_mode, u8 data) { - m_dma->set_dma_mode(dma_mode ? z80dma_device::dma_mode::ZILOG : z80dma_device::dma_mode::SPEC_NEXT); + m_dma->dma_mode_w(dma_mode); m_dma->write(data); } @@ -3035,7 +3035,7 @@ void specnext_state::reset_hard() m_nr_02_hard_reset = 0; m_bootrom_en = 1; - m_dma->set_dma_mode(z80dma_device::dma_mode::SPEC_NEXT); + m_dma->dma_mode_w(0); // nmi_mf = 0; // nmi_divmmc = 0; // nmi_expbus = 0; @@ -3162,7 +3162,7 @@ void specnext_state::machine_reset() m_port_ff_data = 0; m_divmmc_delayed_check = 0; - m_dma->set_dma_mode(z80dma_device::dma_mode::SPEC_NEXT); + m_dma->dma_mode_w(0); //z80_retn_seen_28_d = 0; //im2_dma_delay = 0; m_pulse_int_n = 1; @@ -3449,7 +3449,7 @@ void specnext_state::tbblue(machine_config &config) m_maincpu->in_nextreg_cb().set(FUNC(specnext_state::reg_r)); m_maincpu->out_retn_seen_cb().set(FUNC(specnext_state::leave_nmi)); m_maincpu->nomreq_cb().set_nop(); - m_maincpu->busack_cb().set(m_dma, FUNC(z80dma_device::bai_w)); + m_maincpu->busack_cb().set(m_dma, FUNC(specnext_dma_device::bai_w)); SPECNEXT_CTC(config, m_ctc, 28_MHz_XTAL / 8); m_ctc->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); diff --git a/src/mame/sinclair/specnext_dma.cpp b/src/mame/sinclair/specnext_dma.cpp new file mode 100644 index 00000000000..4c2b29a7d85 --- /dev/null +++ b/src/mame/sinclair/specnext_dma.cpp @@ -0,0 +1,101 @@ +// license:BSD-3-Clause +// copyright-holders:Andrei I. Holub +/********************************************************************** + Spectrum Next DMA + + Spectrum Next DMA operates in two mode: z80dma compatible and + N-mode with Next specific fixes. + + z80dma mode is implemented there based on intensive testing of + the device. Potentially any mismatches not related to N-mode + covered here must be moved to the z80dma parent. + +**********************************************************************/ + +#include "emu.h" +#include "specnext_dma.h" + +// device type definition +DEFINE_DEVICE_TYPE(SPECNEXT_DMA, specnext_dma_device, "specnext_dma", "Spectrum Next DMA") + + +// TODO: this stuff is copy/pasted from machine/z80dma.cpp - ideally it wouldn't need to be +#define WR0 REG(0, 0) +#define WR1 REG(1, 0) +#define WR2 REG(2, 0) + +#define PORTA_INC (WR1 & 0x10) +#define PORTB_INC (WR2 & 0x10) +#define PORTA_FIXED (((WR1 >> 4) & 0x02) == 0x02) +#define PORTB_FIXED (((WR2 >> 4) & 0x02) == 0x02) + +#define TRANSFER_MODE (WR0 & 0x03) + + +specnext_dma_device::specnext_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : z80dma_device(mconfig, SPECNEXT_DMA, tag, owner, clock, dma_mode::ZILOG) +{ +} + +void specnext_dma_device::write(u8 data) +{ + if (!m_ndma_mode && data == COMMAND_ENABLE_DMA && num_follow() == 0) + { + m_byte_counter = 0; + } + z80dma_device::write(data); +} + +void specnext_dma_device::do_write() +{ + if (m_ndma_mode) + { + z80dma_device::do_write(); + return; + } + // else (zxnDMA) + + if (m_byte_counter) + m_addressB += PORTB_FIXED ? 0 : PORTB_INC ? 1 : -1; + + switch (TRANSFER_MODE) + { + case TM_TRANSFER: + do_transfer_write(); + break; + + case TM_SEARCH: + do_search(); + break; + + case TM_SEARCH_TRANSFER: + do_transfer_write(); + do_search(); + break; + + default: + logerror("z80dma_do_operation: invalid mode %d!\n", TRANSFER_MODE); + break; + } + + m_addressA += PORTA_FIXED ? 0 : PORTA_INC ? 1 : -1; + + m_byte_counter++; + if ((m_byte_counter + 1) == m_count) + m_byte_counter++; +} + + +void specnext_dma_device::device_start() +{ + z80dma_device::device_start(); + + save_item(NAME(m_ndma_mode)); +} + +void specnext_dma_device::device_reset() +{ + z80dma_device::device_reset(); + + m_ndma_mode = 0; +} diff --git a/src/mame/sinclair/specnext_dma.h b/src/mame/sinclair/specnext_dma.h new file mode 100644 index 00000000000..66225b3c456 --- /dev/null +++ b/src/mame/sinclair/specnext_dma.h @@ -0,0 +1,31 @@ +// license:BSD-3-Clause +// copyright-holders:Andrei I. Holub +#ifndef MAME_SINCLAIR_SPECNEXT_DMA_H +#define MAME_SINCLAIR_SPECNEXT_DMA_H + +#pragma once + +#include "machine/z80dma.h" + +class specnext_dma_device : public z80dma_device +{ +public: + specnext_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + void dma_mode_w(bool dma_mode) { m_ndma_mode = dma_mode; } + + virtual void write(u8 data) override; + +protected: + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + virtual void do_write() override; + +private: + bool m_ndma_mode; // 0 = zxn dma, 1 = z80 dma +}; + +DECLARE_DEVICE_TYPE(SPECNEXT_DMA, specnext_dma_device) + +#endif // MAME_SINCLAIR_SPECNEXT_DMA_H