diff --git a/src/mame/fairlight/cmi.cpp b/src/mame/fairlight/cmi.cpp index 732e54180fb..bb83fba54b1 100644 --- a/src/mame/fairlight/cmi.cpp +++ b/src/mame/fairlight/cmi.cpp @@ -91,6 +91,7 @@ #include "machine/6821pia.h" #include "machine/6850acia.h" #include "machine/6840ptm.h" +#include "machine/74259.h" #include "machine/7474.h" #include "machine/bankdev.h" #include "machine/clock.h" @@ -257,8 +258,8 @@ public: void q133_1_portb_w(u8 data); void cmi_iix_vblank(int state); - IRQ_CALLBACK_MEMBER(cpu1_interrupt_callback); - IRQ_CALLBACK_MEMBER(cpu2_interrupt_callback); + u8 vfetch1_r(offs_t offset); + u8 vfetch2_r(offs_t offset); // Video-related u8 video_r(offs_t offset); @@ -290,19 +291,16 @@ public: // Memory mapping template u8 rom_r(offs_t offset); void map_ram_w(offs_t offset, u8 data); - template u8 vector_r(offs_t offset); template u8 map_r(); template void map_w(u8 data); u8 atomic_r(); - void cpufunc_w(u8 data); + template void ipi_w(int state); + template void nmi_reset_w(int state); + template void ms_w(int state); u8 parity_r(offs_t offset); void mapsel_w(offs_t offset, u8 data); - template u8 irq_ram_r(offs_t offset); - template void irq_ram_w(offs_t offset, u8 data); template u8 scratch_ram_r(offs_t offset); template void scratch_ram_w(offs_t offset, u8 data); - template u8 scratch_ram_fa_r(offs_t offset); - template void scratch_ram_fa_w(offs_t offset, u8 data); // MIDI/SMPTE void midi_dma_w(offs_t offset, u16 data, u16 mem_mask = ~0); @@ -432,8 +430,6 @@ private: int m_cpu_active_space[2]{}; int m_cpu_map_switch[2]{}; u8 m_curr_mapinfo[2]{}; - u8 m_irq_address[2][2]{}; - int m_m6809_bs_hack_cnt[2]{}; /* Q219 lightpen/graphics card */ std::unique_ptr m_video_ram; @@ -915,11 +911,6 @@ void cmi_state::map_ram_w(offs_t offset, u8 data) } } -template u8 cmi_state::vector_r(offs_t offset) -{ - return m_q133_rom[(CpuNum ? 0xbfe : 0xffe) + offset]; -} - template u8 cmi_state::map_r() { return (m_cpu_active_space[1] << 2) | (m_cpu_active_space[0] << 1) | CpuNum; @@ -930,25 +921,6 @@ template void cmi_state::map_w(u8 data) m_map_switch_timer->adjust(attotime::from_ticks(data & 0xf, M6809_CLOCK), CpuNum); } -template u8 cmi_state::irq_ram_r(offs_t offset) -{ - if (machine().side_effects_disabled()) - return m_scratch_ram[CpuNum][0xf8 + offset]; - - if (m_m6809_bs_hack_cnt[CpuNum] > 0) - { - m_m6809_bs_hack_cnt[CpuNum]--; - LOG("CPU%d IRQ vector byte %d (offset %d): %02x\n", CpuNum + 1, 1 - m_m6809_bs_hack_cnt[CpuNum], offset, m_irq_address[CpuNum][offset]); - return m_irq_address[CpuNum][offset]; - } - return m_scratch_ram[CpuNum][0xf8 + offset]; -} - -template void cmi_state::irq_ram_w(offs_t offset, u8 data) -{ - m_scratch_ram[CpuNum][0xf8 + offset] = data; -} - TIMER_CALLBACK_MEMBER(cmi_state::switch_map) { m_cpu_active_space[param] = m_cpu_map_switch[param]; @@ -972,26 +944,19 @@ u8 cmi_state::atomic_r() return 0; } -void cmi_state::cpufunc_w(u8 data) +template void cmi_state::ipi_w(int state) { - int cpunum = data & 1; - int idx = data & 6; - int bit = (data & 8) >> 3; + set_interrupt(CpuNum, IRQ_IPI2_LEVEL, state ? ASSERT_LINE : CLEAR_LINE); +} - switch (idx) - { - case 0: set_interrupt(cpunum, IRQ_IPI2_LEVEL, bit ? ASSERT_LINE : CLEAR_LINE); - break; - case 2: // TODO: Hardware trace - break; - case 4: m_cpu_map_switch[cpunum] = bit; - break; - case 6: if (cpunum == CPU_1) - m_maincpu1->set_input_line(M6809_FIRQ_LINE, bit ? ASSERT_LINE : CLEAR_LINE); - else - m_maincpu2->set_input_line(M6809_FIRQ_LINE, bit ? ASSERT_LINE : CLEAR_LINE); - break; - } +template void cmi_state::nmi_reset_w(int state) +{ + // TODO: Hardware trace +} + +template void cmi_state::ms_w(int state) +{ + m_cpu_map_switch[CpuNum] = state; } u8 cmi_state::parity_r(offs_t offset) @@ -1140,7 +1105,7 @@ template void cmi_state::cpu_periphs_map(address_map &map) map(0x0800, 0x0bff).rom().region("q133", 0x2800 - CpuNum * 0x1000); map(0x0c40, 0x0c4f).rw(FUNC(cmi_state::parity_r), FUNC(cmi_state::mapsel_w)); map(0x0c5a, 0x0c5b).noprw(); // Q077 HDD controller - not installed - map(0x0c5e, 0x0c5e).rw(FUNC(cmi_state::atomic_r), FUNC(cmi_state::cpufunc_w)); + map(0x0c5e, 0x0c5e).r(FUNC(cmi_state::atomic_r)).w("cpulatch", FUNC(ls259_device::write_nibble_d3)); map(0x0c5f, 0x0c5f).rw(FUNC(cmi_state::map_r), FUNC(cmi_state::map_w)); map(0x0c80, 0x0c83).rw(m_q133_acia[0], FUNC(mos6551_device::read), FUNC(mos6551_device::write)); map(0x0c84, 0x0c87).rw(m_q133_acia[1], FUNC(mos6551_device::read), FUNC(mos6551_device::write)); @@ -1160,10 +1125,7 @@ template void cmi_state::cpu_periphs_map(address_map &map) map(0x0cfc, 0x0cfc).w(FUNC(cmi_state::i8214_cpu1_w)); map(0x0cfd, 0x0cfd).w(FUNC(cmi_state::i8214_cpu2_w)); map(0x0d00, 0x0eff).rw(FUNC(cmi_state::shared_ram_r), FUNC(cmi_state::shared_ram_w)); - map(0x0f00, 0x0ff7).rw(FUNC(cmi_state::scratch_ram_r), FUNC(cmi_state::scratch_ram_w)); - map(0x0ff8, 0x0ff9).rw(FUNC(cmi_state::irq_ram_r), FUNC(cmi_state::irq_ram_w)); - map(0x0ffa, 0x0ffd).rw(FUNC(cmi_state::scratch_ram_fa_r), FUNC(cmi_state::scratch_ram_fa_w)); - map(0x0ffe, 0x0fff).r(FUNC(cmi_state::vector_r)); + map(0x0f00, 0x0fff).rw(FUNC(cmi_state::scratch_ram_r), FUNC(cmi_state::scratch_ram_w)); } /* Input ports */ @@ -1188,16 +1150,6 @@ template void cmi_state::scratch_ram_w(offs_t offset, u8 data) m_scratch_ram[CpuNum][offset] = data; } -template u8 cmi_state::scratch_ram_fa_r(offs_t offset) -{ - return m_scratch_ram[CpuNum][0xfa + offset]; -} - -template void cmi_state::scratch_ram_fa_w(offs_t offset, u8 data) -{ - m_scratch_ram[CpuNum][0xfa + offset] = data; -} - bool cmi_state::map_is_active(int cpunum, int map, u8 *map_info) { if (m_cpu_active_space[cpunum] == MAPPING_A) @@ -1720,48 +1672,57 @@ void cmi_state::ptm_q219_irq(int state) set_interrupt(CPU_2, IRQ_RINT_LEVEL, state); } -IRQ_CALLBACK_MEMBER( cmi_state::cpu1_interrupt_callback ) +u8 cmi_state::vfetch1_r(offs_t offset) { - /* Switch to mapping A */ + // Switch to mapping A m_cpu_active_space[CPU_1] = MAPPING_A; update_address_space(CPU_1, m_map_sel[MAPSEL_P1_A]); - if (irqline == INPUT_LINE_IRQ0) + if ((offset & 0x000e) == 0x0008) { + // IRQ vector int vector = (m_hp_int ? 0xffe0 : 0xffd0); int level = (m_hp_int ? m_i8214[2]->a_r() : m_i8214[0]->a_r()) ^ 7; - m_irq_address[CPU_1][0] = m_cpu1space->read_byte(vector + level*2); - m_irq_address[CPU_1][1] = m_cpu1space->read_byte(vector + level*2 + 1); - - m_m6809_bs_hack_cnt[CPU_1] = 2; - - LOG("%s: CPU1 interrupt, will be pushing address %02x%02x\n", machine().describe_context(), m_irq_address[CPU_1][0], m_irq_address[CPU_1][1]); + u8 irq_address = m_cpu1space->read_byte(vector + level * 2 + BIT(offset, 0)); + LOG("%s: CPU1 IRQ vector %s byte: %02x\n", machine().describe_context(), BIT(offset, 0) ? "low" : "high", irq_address); + return irq_address; + } + else if ((offset & 0x000e) == 0x000e) + { + // RESET vector + return m_q133_rom[offset & 0xfff]; } else { - LOG("%s: Some other CPU1 interrupt, line %d\n", irqline); + LOG("%s: Some other CPU1 interrupt, fetching vector from $%04x\n", machine().describe_context(), offset); + return m_scratch_ram[CPU_1][offset & 0xff]; } - - return 0; } -IRQ_CALLBACK_MEMBER( cmi_state::cpu2_interrupt_callback ) +u8 cmi_state::vfetch2_r(offs_t offset) { - /* Switch to mapping A */ + // Switch to mapping A m_cpu_active_space[CPU_2] = MAPPING_A; update_address_space(CPU_2, m_map_sel[MAPSEL_P2_A]); - if (irqline == INPUT_LINE_IRQ0) + if ((offset & 0x000e) == 0x0008) { + // IRQ vector int level = m_i8214[1]->a_r() ^ 7; - m_irq_address[CPU_2][0] = m_cpu2space->read_byte(0xffe0 + level*2); - m_irq_address[CPU_2][1] = m_cpu2space->read_byte(0xffe0 + level*2 + 1); - - m_m6809_bs_hack_cnt[CPU_2] = 2; - - //osd_printf_debug("cpu1 interrupt, will be pushing address %02x%02x\n", m_irq_address[CPU_2][0], m_irq_address[CPU_2][1]); + u8 irq_address = m_cpu2space->read_byte(0xffe0 + level*2 + BIT(offset, 0)); + LOG("%s: CPU2 IRQ vector %s byte: %02x (%s)\n", machine().describe_context(), BIT(offset, 0) ? "low" : "high", irq_address); + return irq_address; + } + else if ((offset & 0x000e) == 0x000e) + { + // RESET vector + return m_q133_rom[offset & 0xbff]; + } + else + { + LOG("%s: Some other CPU2 interrupt, fetching vector from $%04x\n", machine().describe_context(), offset); + return m_scratch_ram[CPU_2][offset & 0xff]; } - return 0; } void cmi_state::set_interrupt(int cpunum, int level, int state) @@ -1931,9 +1892,6 @@ void cmi_state::machine_reset() /* Select A (system) spaces */ m_cpu_active_space[cpunum] = MAPPING_A; - - m_irq_address[cpunum][0] = space->read_byte(0xfff8); - m_irq_address[cpunum][1] = space->read_byte(0xfff9); } // TODO - we need to detect empty disk drive!! @@ -1954,8 +1912,6 @@ void cmi_state::machine_reset() m_cmi02_ptm->set_g1(0); m_cmi02_ptm->set_g2(0); m_cmi02_ptm->set_g3(0); - m_m6809_bs_hack_cnt[0] = 0; - m_m6809_bs_hack_cnt[1] = 0; //m_midi_ptm[0]->set_g1(1); // /G1 has unknown source, "TIMER 1A /GATE" per schematic m_midi_ptm[0]->set_g2(0); // /G2 and /G3 wired to ground per schematic @@ -2034,11 +1990,11 @@ void cmi_state::cmi2x(machine_config &config) { MC6809E(config, m_maincpu1, Q209_CPU_CLOCK); m_maincpu1->set_addrmap(AS_PROGRAM, &cmi_state::maincpu1_map); - m_maincpu1->set_irq_acknowledge_callback(FUNC(cmi_state::cpu1_interrupt_callback)); + m_maincpu1->interrupt_vector_read().set(FUNC(cmi_state::vfetch1_r)); MC6809E(config, m_maincpu2, Q209_CPU_CLOCK); m_maincpu2->set_addrmap(AS_PROGRAM, &cmi_state::maincpu2_map); - m_maincpu2->set_irq_acknowledge_callback(FUNC(cmi_state::cpu2_interrupt_callback)); + m_maincpu2->interrupt_vector_read().set(FUNC(cmi_state::vfetch2_r)); ADDRESS_MAP_BANK(config, m_cpu_periphs[0]).set_options(ENDIANNESS_BIG, 8, 16, 0x1000); m_cpu_periphs[0]->set_addrmap(AS_PROGRAM, &cmi_state::cpu_periphs_map<0>); @@ -2046,6 +2002,16 @@ void cmi_state::cmi2x(machine_config &config) ADDRESS_MAP_BANK(config, m_cpu_periphs[1]).set_options(ENDIANNESS_BIG, 8, 16, 0x1000); m_cpu_periphs[1]->set_addrmap(AS_PROGRAM, &cmi_state::cpu_periphs_map<1>); + ls259_device &cpulatch(LS259(config, "cpulatch")); // 6D (Q209) + cpulatch.q_out_cb<0>().set(FUNC(cmi_state::ipi_w<0>)); + cpulatch.q_out_cb<1>().set(FUNC(cmi_state::ipi_w<1>)); + cpulatch.q_out_cb<2>().set(FUNC(cmi_state::nmi_reset_w<0>)); + cpulatch.q_out_cb<3>().set(FUNC(cmi_state::nmi_reset_w<1>)); + cpulatch.q_out_cb<4>().set(FUNC(cmi_state::ms_w<0>)); + cpulatch.q_out_cb<5>().set(FUNC(cmi_state::ms_w<1>)); + cpulatch.q_out_cb<6>().set_inputline(m_maincpu1, M6809_FIRQ_LINE); + cpulatch.q_out_cb<7>().set_inputline(m_maincpu2, M6809_FIRQ_LINE); + M68000(config, m_midicpu, 20_MHz_XTAL / 2); m_midicpu->set_addrmap(AS_PROGRAM, &cmi_state::midicpu_map);