Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/devices/cpu/z80/z80.lst
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ macro retn
m_iff1 = m_iff2;

macro z80n:retn
m_out_retn_seen_cb(0);
m_out_retn_seen_cb(1);
@pop
if (m_stackless) {
m_pc.b.l = m_in_nextreg_cb(0xc2);
Expand Down
74 changes: 27 additions & 47 deletions src/mame/sinclair/specnext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "specnext_ctc.h"
#include "specnext_divmmc.h"
#include "specnext_dma.h"
#include "specnext_im2.h"
#include "specnext_multiface.h"
#include "specnext_layer2.h"
#include "specnext_lores.h"
Expand Down Expand Up @@ -99,9 +100,10 @@ class specnext_state : public spectrum_128_state
, m_view5(*this, "mem_view5")
, m_view6(*this, "mem_view6")
, m_view7(*this, "mem_view7")
, m_im2(*this, "im2")
, m_copper(*this, "copper")
, m_ctc(*this, "ctc")
, m_dma(*this, "ndma")
, m_dma(*this, "dma")
, m_i2c(*this, "i2c")
, m_sdcard(*this, "sdcard")
, m_ay(*this, "ay%u", 0U)
Expand Down Expand Up @@ -135,7 +137,7 @@ class specnext_state : public spectrum_128_state

u8 do_m1(offs_t offset);
void do_mf_nmi();
void leave_nmi(int status);
void leave_nmi(int state);
void map_fetch(address_map &map) ATTR_COLD;
void map_mem(address_map &map) ATTR_COLD;
void map_io(address_map &map) ATTR_COLD;
Expand Down Expand Up @@ -176,12 +178,11 @@ class specnext_state : public spectrum_128_state
static const u8 G_VIDEO_INC = 0b11;
static const u16 UTM_FALLBACK_PEN = 0x800;

virtual TIMER_CALLBACK_MEMBER(irq_off) override;
virtual TIMER_CALLBACK_MEMBER(irq_on) override;
INTERRUPT_GEN_MEMBER(specnext_interrupt);
TIMER_CALLBACK_MEMBER(line_irq_on);
void ctc_irq_on(int state);
INTERRUPT_GEN_MEMBER(line_interrupt);
IRQ_CALLBACK_MEMBER(irq_callback);
TIMER_CALLBACK_MEMBER(spi_clock);
void line_irq_adjust();

Expand Down Expand Up @@ -262,7 +263,7 @@ class specnext_state : public spectrum_128_state
bool nr_8f_mapping_mode_pentagon_1024() const { return m_nr_8f_mapping_mode == 0b11; }
bool nr_8f_mapping_mode_pentagon_1024_en() const { return nr_8f_mapping_mode_pentagon_1024() && BIT(~m_port_eff7_data, 2); }

void nr_c0_im2_vector_w(u8 data) { m_nr_c0_im2_vector = data; m_ctc->write(0, m_nr_c0_im2_vector << 5); }
void nr_c0_im2_vector_w(u8 data) { m_nr_c0_im2_vector = data; m_ctc->write(0, m_nr_c0_im2_vector << 5); m_im2->vector_w(m_nr_c0_im2_vector << 5); }

u32 internal_port_enable() const;
bool port_ff_io_en() const { return BIT(internal_port_enable(), 0); }
Expand Down Expand Up @@ -318,6 +319,7 @@ class specnext_state : public spectrum_128_state
memory_bank_creator m_bank_boot_rom;
memory_bank_array_creator<8> m_bank_ram;
memory_view m_view0, m_view1, m_view2, m_view3, m_view4, m_view5, m_view6, m_view7;
required_device<specnext_im2_device> m_im2;
required_device<specnext_copper_device> m_copper;
required_device<specnext_ctc_device> m_ctc;
required_device<specnext_dma_device> m_dma;
Expand Down Expand Up @@ -568,8 +570,6 @@ class specnext_state : public spectrum_128_state
u8 m_spi_miso_dat;
bool m_i2c_scl_data;
bool m_i2c_sda_data;

u16 m_irq_mask;
};

void specnext_state::bank_update(u8 bank, u8 count)
Expand Down Expand Up @@ -2343,6 +2343,10 @@ void specnext_state::reg_w(offs_t nr_wr_reg, u8 nr_wr_dat)
m_nr_ce_dma_int_en_2_654 = BIT(nr_wr_dat, 4, 3);
m_nr_ce_dma_int_en_2_210 = BIT(nr_wr_dat, 0, 3);
break;
case 0xcf:
if (nr_wr_dat)
LOG("wR: CF <- %x, but 0 expected\n", nr_wr_dat);
break;
case 0xd8:
m_nr_d8_io_trap_fdc_en = BIT(nr_wr_dat, 0);
break;
Expand Down Expand Up @@ -2401,6 +2405,7 @@ void specnext_state::nr_07_cpu_speed_w(u8 data)
m_maincpu->set_clock_scale(1 << m_nr_07_cpu_speed);
m_ctc->set_clock_scale(1 << m_nr_07_cpu_speed);
m_dma->set_clock_scale(1 << m_nr_07_cpu_speed);
m_im2->set_clock_scale(1 << m_nr_07_cpu_speed);
}

void specnext_state::nr_14_global_transparent_rgb_w(u8 data)
Expand All @@ -2421,30 +2426,26 @@ void specnext_state::nr_1a_ula_clip_y2_w(u8 data)

static const z80_daisy_config z80_daisy_chain[] =
{
{ "ndma" },
{ "im2" },
{ "ctc" },
//{ "dma" },
{ nullptr }
};

TIMER_CALLBACK_MEMBER(specnext_state::irq_off)
{
m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE);
m_irq_mask = 0;
}

TIMER_CALLBACK_MEMBER(specnext_state::irq_on)
{
m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE);
m_irq_mask |= 1 << 11;
m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32));
m_im2->int_w((m_nr_02_bus_reset || !m_nr_c0_int_mode_pulse_0_im2_1) ? 0xff : (11 << 1));
}

TIMER_CALLBACK_MEMBER(specnext_state::line_irq_on)
{
m_screen->update_now();
m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE);
m_irq_mask |= 1 << 0;
m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32));
m_im2->int_w((m_nr_02_bus_reset || !m_nr_c0_int_mode_pulse_0_im2_1) ? 0xff : (1 << 1));
}

void specnext_state::ctc_irq_on(int state)
{
m_maincpu->set_input_line(INPUT_LINE_IRQ0, state);
}

INTERRUPT_GEN_MEMBER(specnext_state::specnext_interrupt)
Expand Down Expand Up @@ -2474,27 +2475,6 @@ void specnext_state::line_irq_adjust()
m_irq_line_timer->reset();
}

IRQ_CALLBACK_MEMBER(specnext_state::irq_callback)
{
if (!m_nr_02_bus_reset)
{
return 0xff;
}
else
{
u8 vector = 11;
if (m_irq_mask)
{
vector = 0;
u16 i = 1;
for (; ~m_irq_mask & i; ++vector, i <<= 1);
m_irq_mask &= ~i;

}
return (m_nr_c0_im2_vector << 5) | (vector << 2);
}
}

INPUT_CHANGED_MEMBER(specnext_state::on_mf_nmi)
{
m_nr_02_generate_mf_nmi = newval & 1;
Expand All @@ -2520,7 +2500,7 @@ void specnext_state::do_mf_nmi()
}
}

void specnext_state::leave_nmi(int status)
void specnext_state::leave_nmi(int state)
{
m_mf->cpu_retn_seen_w(1);
m_mf->clock_w();
Expand Down Expand Up @@ -3210,7 +3190,6 @@ void specnext_state::machine_start()
save_item(NAME(m_spi_miso_dat));
save_item(NAME(m_i2c_scl_data));
save_item(NAME(m_i2c_sda_data));
save_item(NAME(m_irq_mask));
}

void specnext_state::reset_hard()
Expand Down Expand Up @@ -3581,7 +3560,6 @@ void specnext_state::machine_reset()
mmu_x2_w(6, 0x00);

m_ay_select = 0;
m_irq_mask = 0;
}

static const gfx_layout bootrom_charlayout =
Expand Down Expand Up @@ -3637,18 +3615,20 @@ void specnext_state::tbblue(machine_config &config)
m_maincpu->set_memory_map(&specnext_state::map_mem);
m_maincpu->set_io_map(&specnext_state::map_io);
m_maincpu->set_vblank_int("screen", FUNC(specnext_state::specnext_interrupt));
m_maincpu->set_irq_acknowledge_callback(FUNC(specnext_state::irq_callback));
m_maincpu->set_irq_acknowledge_callback(NAME([](device_t &, int){ return 0xff; }));
m_maincpu->out_nextreg_cb().set(FUNC(specnext_state::reg_w));
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->busack_cb().set(m_dma, FUNC(specnext_dma_device::bai_w));

SPECNEXT_IM2(config, m_im2, 28_MHz_XTAL / 8);
m_im2->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);

SPECNEXT_CTC(config, m_ctc, 28_MHz_XTAL / 8);
m_ctc->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
m_ctc->intr_callback().set(FUNC(specnext_state::ctc_irq_on));

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(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); });
Expand Down
2 changes: 1 addition & 1 deletion src/mame/sinclair/specnext_ctc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ int specnext_ctc_device::z80daisy_irq_ack()
{
int const channel = (z80ctc_device::z80daisy_irq_ack() - m_vector) / 2;
return ((channel > 0) || (channel_int_state(0) == Z80_DAISY_IEO))
? (m_vector + (channel + 3) * 2)
? (m_vector + ((channel + 3) << 1))
: m_vector;
}
68 changes: 68 additions & 0 deletions src/mame/sinclair/specnext_im2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// license:BSD-3-Clause
// copyright-holders:Andrei I. Holub
/**********************************************************************
Spectrum Next IM2
**********************************************************************/

#include "emu.h"
#include "specnext_im2.h"


// device type definition
DEFINE_DEVICE_TYPE(SPECNEXT_IM2, specnext_im2_device, "specnext_im2", "Spectrum Next IM2")


specnext_im2_device::specnext_im2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, SPECNEXT_IM2, tag, owner, clock)
, device_z80daisy_interface(mconfig, *this)
, m_intr_cb(*this)
{
}


int specnext_im2_device::z80daisy_irq_state()
{
return m_state;
}

int specnext_im2_device::z80daisy_irq_ack()
{
return m_vector_base | m_vector_lo;
}

void specnext_im2_device::z80daisy_irq_reti()
{
}

TIMER_CALLBACK_MEMBER(specnext_im2_device::irq_off)
{
m_state = 0;
m_intr_cb(CLEAR_LINE);
}

void specnext_im2_device::int_w(u8 vector_lo)
{
m_vector_lo = vector_lo;
m_state = Z80_DAISY_INT;
m_intr_cb(ASSERT_LINE);
m_irq_off_timer->adjust(clocks_to_attotime(32));
}


void specnext_im2_device::device_start()
{
m_irq_off_timer = timer_alloc(FUNC(specnext_im2_device::irq_off), this);

save_item(NAME(m_state));
save_item(NAME(m_vector_base));
save_item(NAME(m_vector_lo));
}

void specnext_im2_device::device_reset()
{
m_irq_off_timer->reset();

m_state = 0;
m_vector_base = 0;
m_vector_lo = 0xff;
}
44 changes: 44 additions & 0 deletions src/mame/sinclair/specnext_im2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// license:BSD-3-Clause
// copyright-holders:Andrei I. Holub
#ifndef MAME_SINCLAIR_SPECNEXT_IM2_H
#define MAME_SINCLAIR_SPECNEXT_IM2_H

#pragma once

#include "machine/z80daisy.h"

class specnext_im2_device : public device_t,
public device_z80daisy_interface
{

public:
specnext_im2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);

auto intr_callback() { return m_intr_cb.bind(); }

void vector_w(u8 vector) { m_vector_base = vector; }
void int_w(u8 vector_lo = 0xff);

protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;

virtual int z80daisy_irq_state() override;
virtual int z80daisy_irq_ack() override;
virtual void z80daisy_irq_reti() override;

TIMER_CALLBACK_MEMBER(irq_off);

emu_timer *m_irq_off_timer;
devcb_write_line m_intr_cb;

private:
u8 m_state;
u8 m_vector_base;
u8 m_vector_lo;

};

DECLARE_DEVICE_TYPE(SPECNEXT_IM2, specnext_im2_device)

#endif // MAME_SINCLAIR_SPECNEXT_IM2_H
Loading