summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/sinclair/specnext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/sinclair/specnext.cpp')
-rw-r--r--src/mame/sinclair/specnext.cpp131
1 files changed, 37 insertions, 94 deletions
diff --git a/src/mame/sinclair/specnext.cpp b/src/mame/sinclair/specnext.cpp
index 33ed31b7d16..d9d124b993a 100644
--- a/src/mame/sinclair/specnext.cpp
+++ b/src/mame/sinclair/specnext.cpp
@@ -157,8 +157,7 @@ public:
void ks2(machine_config &config);
void ks3(machine_config &config);
- INPUT_CHANGED_MEMBER(on_mf_nmi);
- INPUT_CHANGED_MEMBER(on_divmmc_nmi);
+ INPUT_CHANGED_MEMBER(on_nmi_button);
protected:
virtual void machine_start() override ATTR_COLD;
@@ -171,8 +170,7 @@ protected:
void update_video_mode();
u8 do_m1(offs_t offset);
- void do_mf_nmi();
- void nmi();
+ void nmi_rq();
void leave_nmi(int state);
void map_fetch(address_map &map) ATTR_COLD;
void map_mem(address_map &map) ATTR_COLD;
@@ -234,6 +232,8 @@ private:
bool machine_type_128() const { return m_nr_03_machine_type == 2 || m_nr_03_machine_type == 4; }
bool machine_type_p3() const { return !machine_type_48() && !machine_type_128(); }
+ bool nmi_assert_mf() { return ((m_io_nmi->read() & 1) || m_nr_02_generate_mf_nmi) && m_nr_06_button_m1_nmi_en; }
+ bool nmi_assert_divmmc() { return ((m_io_nmi->read() & 2) || m_nr_02_generate_divmmc_nmi) && m_nr_06_button_drive_nmi_en; }
void nr_02_w(u8 nr_wr_dat);
bool nr_02_iotrap() { return m_nr_da_iotrap_cause & 3; }
void nr_07_cpu_speed_w(u8 data);
@@ -416,9 +416,6 @@ private:
u8 m_nr_register;
u8 m_port_e3_reg;
bool m_divmmc_delayed_check;
- bool m_copper_req;
- u8 m_copper_nr_reg;
- u8 m_copper_nr_dat;
u8 m_sram_rom;
bool m_sram_rom3;
@@ -769,8 +766,6 @@ void specnext_state::bank_update(u8 bank)
m_divmmc->en_w(port_divmmc_io_en());
m_divmmc->automap_reset_w(!port_divmmc_io_en() || !m_nr_0a_divmmc_automap_en);
m_divmmc->automap_active_w(sram_divmmc_automap_en);
- m_divmmc->retn_seen_w(0);
- m_divmmc->divmmc_button_w(m_nr_02_generate_divmmc_nmi);
for (s8 cpu_rd_n = 1; cpu_rd_n >= 0; --cpu_rd_n) // check W then R
{
@@ -1948,18 +1943,6 @@ u8 specnext_state::reg_r(offs_t nr_register)
void specnext_state::reg_w(offs_t nr_wr_reg, u8 nr_wr_dat)
{
- if (m_copper_req)
- {
- if (nr_wr_reg == 0x02)
- {
- LOGINTVVV("Copper write: reg=%02x data=%02x\n", nr_wr_reg, nr_wr_dat);
- m_copper_nr_reg = nr_wr_reg;
- m_copper_nr_dat = nr_wr_dat;
- return;
- }
- m_copper_req = false;
- }
-
switch (nr_wr_reg)
{
case 0x02:
@@ -2606,28 +2589,8 @@ void specnext_state::nr_02_w(u8 nr_wr_dat)
m_nr_da_iotrap_cause = 0;
m_nr_02_generate_mf_nmi = BIT(nr_wr_dat, 3);
- do_mf_nmi();
-
- if (BIT(nr_wr_dat, 2))
- {
- if (m_nr_06_button_drive_nmi_en)
- {
- m_nr_02_generate_divmmc_nmi = 1;
- nmi();
- }
- }
- else
- {
- m_nr_02_generate_divmmc_nmi = 0;
- }
-
- const u16 mask = 1 << INT_PRIORITY_NMI;
- if (!m_nr_02_generate_mf_nmi && !m_nr_02_generate_divmmc_nmi && (m_im2_int_status & mask))
- {
- m_maincpu->nmi(CLEAR_LINE);
- m_im2_int_status &= ~mask;
- update_dma_delay();
- }
+ m_nr_02_generate_divmmc_nmi = BIT(nr_wr_dat, 2);
+ nmi_rq();
if (BIT(nr_wr_dat, 1)) // hard reset
{
@@ -2769,45 +2732,30 @@ void specnext_state::line_irq_adjust()
m_irq_line_timer->reset();
}
-INPUT_CHANGED_MEMBER(specnext_state::on_mf_nmi)
+INPUT_CHANGED_MEMBER(specnext_state::on_nmi_button)
{
- if (m_nr_03_config_mode)
- return;
-
- m_nr_02_generate_mf_nmi = newval & 1;
- do_mf_nmi();
- m_nr_02_generate_mf_nmi = 0;
+ nmi_rq();
}
-INPUT_CHANGED_MEMBER(specnext_state::on_divmmc_nmi)
+void specnext_state::nmi_rq()
{
- if (m_nr_03_config_mode)
- return;
-
- m_nr_02_generate_divmmc_nmi = newval & 1;
- if (m_nr_06_button_drive_nmi_en && m_nr_02_generate_divmmc_nmi)
- nmi();
-}
-
-void specnext_state::do_mf_nmi()
-{
- if (m_nr_06_button_m1_nmi_en && m_nr_02_generate_mf_nmi)
+ if (!m_nr_03_config_mode)
{
- nmi();
- m_mf->button_w(1);
+ m_mf->button_w(nmi_assert_mf());
m_mf->clock_w();
- m_mf->button_w(0);
- }
-}
-void specnext_state::nmi()
-{
- const u16 mask = 1 << INT_PRIORITY_NMI;
- if (~m_im2_int_status & mask)
- {
- m_maincpu->nmi(ASSERT_LINE);
- m_im2_int_status |= mask;
- update_dma_delay();
+ m_divmmc->divmmc_button_w(nmi_assert_divmmc());
+ m_divmmc->clock_w();
+
+ if ((nmi_assert_mf() || nmi_assert_divmmc()))
+ {
+ LOGINTVVV("NMI: on (%s)\n", nmi_assert_mf() ? "MF" : "DivMMC");
+ m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
+ m_maincpu->abort_timeslice();
+
+ m_im2_int_status |= 1 << INT_PRIORITY_NMI;
+ update_dma_delay();
+ }
}
}
@@ -2815,14 +2763,20 @@ void specnext_state::leave_nmi(int state)
{
m_mf->cpu_retn_seen_w(1);
m_mf->clock_w();
+ m_mf->cpu_retn_seen_w(0);
+ m_mf->clock_w();
m_divmmc->retn_seen_w(1);
m_divmmc->clock_w();
+ m_divmmc->retn_seen_w(0);
+ m_divmmc->clock_w();
- m_mf->cpu_retn_seen_w(0);
- m_mf->clock_w();
-
+ m_im2_int_status &= ~(1 << INT_PRIORITY_NMI);
+ update_dma_delay();
bank_update(0, 2);
+
+ LOGINTVVV("NMI: off\n");
+ m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
}
u8 specnext_state::do_m1(offs_t offset)
@@ -2866,7 +2820,7 @@ void specnext_state::map_fetch(address_map &map)
if (m_divmmc_delayed_check)
{
/* Happens after RW cycles (before next M1 fetch).
- Fell like side effects check must be ignored here,
+ Feels like side effects check must be ignored here,
because doesn't matter who reset this lines and such
approach gives better experience in debugger UI. */
do_m1(offset);
@@ -2878,12 +2832,6 @@ void specnext_state::map_fetch(address_map &map)
m_maincpu->adjust_icount(1);
}
}
-
- if (m_copper_req)
- {
- m_copper_req = 0;
- reg_w(m_copper_nr_reg, m_copper_nr_dat);
- }
}
return m_program.read_byte(offset);
@@ -3314,8 +3262,8 @@ INPUT_PORTS_START(specnext)
PORT_BIT(0x800, IP_ACTIVE_HIGH, IPT_BUTTON7) PORT_PLAYER(2) PORT_CODE(JOYCODE_BUTTON7) PORT_NAME("Joystick (R) Mode")
PORT_MODIFY("NMI")
- PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("NMI MF") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(specnext_state::on_mf_nmi), 0)
- PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("NMI DivMMC") PORT_CODE(KEYCODE_F11) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(specnext_state::on_divmmc_nmi), 0)
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("NMI MF") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(specnext_state::on_nmi_button), 0)
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("NMI DivMMC") PORT_CODE(KEYCODE_F11) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(specnext_state::on_nmi_button), 0)
PORT_START("LYRS")
PORT_CONFNAME(0x08, 0x00, "Disable Sprites")
@@ -3375,9 +3323,6 @@ void specnext_state::machine_start()
save_item(NAME(m_nr_register));
save_item(NAME(m_port_e3_reg));
save_item(NAME(m_divmmc_delayed_check));
- save_item(NAME(m_copper_req));
- save_item(NAME(m_copper_nr_reg));
- save_item(NAME(m_copper_nr_dat));
save_item(NAME(m_sram_rom));
save_item(NAME(m_sram_rom3));
save_item(NAME(m_sram_alt_128_n));
@@ -3729,6 +3674,7 @@ void specnext_state::machine_reset()
// TODO prevent from soft reset in config mode?
spectrum_128_state::machine_reset();
+ m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
m_irq_line_timer->reset();
if (m_nr_02_hard_reset)
@@ -3794,9 +3740,6 @@ void specnext_state::machine_reset()
port_ff3b_ulap_en_w(0);
m_nr_register = 0x24;
//copper_requester_d = 0;
- m_copper_req = 0;
- m_copper_nr_reg = 0x00;
- m_copper_nr_dat = 0x00;
//cpu_requester_d = 0;
//cpu_req = 0;
//cpu_nr_reg = 0x00;
@@ -4158,7 +4101,7 @@ void specnext_state::tbblue(machine_config &config)
SPECNEXT_SPRITES(config, m_sprites, 0).set_palette(m_palette->device().tag(), 0x600, 0x700);
SPECNEXT_COPPER(config, m_copper, 28_MHz_XTAL);
- m_copper->out_nextreg_cb().set([this](offs_t offset, u8 data) { m_copper_req = 1; m_next_regs.write_byte(offset, data); });
+ m_copper->out_nextreg_cb().set([this](offs_t offset, u8 data) { m_next_regs.write_byte(offset, data); });
m_copper->set_in_until_pos_cb(FUNC(specnext_state::copper_until_pos_r));
SOFTWARE_LIST(config, "sd_list").set_original("specnext_sd");