diff options
Diffstat (limited to 'src/mame/drivers/cmi.cpp')
-rw-r--r-- | src/mame/drivers/cmi.cpp | 1794 |
1 files changed, 0 insertions, 1794 deletions
diff --git a/src/mame/drivers/cmi.cpp b/src/mame/drivers/cmi.cpp deleted file mode 100644 index db105420969..00000000000 --- a/src/mame/drivers/cmi.cpp +++ /dev/null @@ -1,1794 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Phil Bennett -/*************************************************************************** - - Fairlight CMI Series - - driver by Phil Bennett - - Systems supported: - - * CMI IIx - - To do: - - * MASTER 'TIM' test fails - * LGTST 'TIM' test is out of tolerance without 6840 hack. - - Information from: - - CMI SYSTEM SERVICE MANUAL - FAIRLIGHT INSTRUMENTS, FEBRUARY 1985 - Revision 2.1 - - This document is available on archive.org at the following URL: - - https://archive.org/details/fairlight_CMI-IIx_SERVICE_MANUAL - - Summary: - - The Fairlight CMI system conists typically of: - - One velocity-sensitive unweighted keyboard, with a numeric - keypad and several control surfaces - - (Optionally) one additional keyboard, not velocity-sensitive - - One alphanumeric keyboard for manual control - - A 15-inch green-screen monitor and light pen for more direct - control - - A box consisting of: - * An audio board including balanced line drivers for eight - channels and mixed output - * A 500-watt power supply - * A 21-slot backplane - * Two 8-inch double-density floppy disk drives. The format - used is soft-sectored, 128 bytes per sector (single density), - or 256 bytes per sector (double density), using FM - recording. - * And the following cards: - Slot 1: Master Card CMI-02 - Slot 2: General Interface Card CMI-08/28 (Optional) - Slots 3-11: 8 Channel Controller Cards & 1 Voice Master Module Card, order unknown - Slot 12: 64K System RAM Q-096 - Slot 13: 256K System RAM Q-256 - Slot 14: 256K System RAM Q-256 - Slot 15: 4-Port ACIA Module Q-014 (Optional) - Slot 16: Processor Control Module Q-133 - Slot 17: Central Processor Module Q-209 - Slot 18: Lightpen/Graphics Interface Q-219 - Slot 19: Floppy Disk Controller QFC-9 - Slot 20: Hard Disk Controller Q-077 (Optional) - - Q209 Dual 6809 Central Processor Card - ------------------------------------- - - The CPU card has two 6809 processors, with robust inter-CPU - communications capabilities including: - - Uninterruptible instructions - - CPU-specific ID register and memory map registers - - Interprocessor interrupts - - Automatic memory map-switching register - - The CPUs are multiplexed onto the address and data buses - in an interleaved manner such that there is no contention - on simultaneous memory accesses. - - All system timing is derived from a 40MHz clock crystal, which - is divided into two opposite-phase 20MHz squre waves. - - Other data entry from service manual to be completed later - RH 12 Aug 2016 - -****************************************************************************/ - -#include "emu.h" - -#include "audio/cmi01a.h" -#include "machine/cmi_ankbd.h" -#include "machine/cmi_mkbd.h" - -#include "cpu/m6809/m6809.h" -#include "cpu/m68000/m68000.h" - -#include "imagedev/floppy.h" -#include "machine/6821pia.h" -#include "machine/6840ptm.h" -#include "machine/7474.h" -#include "machine/clock.h" -#include "machine/i8214.h" -#include "machine/input_merger.h" -#include "machine/mos6551.h" -#include "machine/msm5832.h" -#include "machine/wd_fdc.h" - -#include "emupal.h" -#include "screen.h" -#include "speaker.h" - - -#define Q209_CPU_CLOCK 40.21_MHz_XTAL / 40 // divider not verified (very complex circuit) - -#define M6809_CLOCK 8000000 // wrong -#define MASTER_OSCILLATOR 34.291712_MHz_XTAL - -#define CPU_1 0 -#define CPU_2 1 - -#define MAPPING_A 1 -#define MAPPING_B 0 - -#define NUM_Q256_CARDS 1 // Max of 2 -#define NUM_CHANNEL_CARDS 8 - -#define PAGE_SIZE 2048 -#define PAGE_COUNT (65536 / PAGE_SIZE) -#define PAGE_MASK (PAGE_SIZE - 1) -#define PAGE_SHIFT 5 - -#define PIXEL_CLOCK 10.38_MHz_XTAL -#define HTOTAL 672 -#define HBLANK_END 0 -#define HBLANK_START 512 -#define VTOTAL 304 -#define VBLANK_END 0 -#define VBLANK_START 256 - -#define HBLANK_FREQ (PIXEL_CLOCK / HTOTAL) -#define VBLANK_FREQ (HBLANK_FREQ / VTOTAL) - -#define MAPSEL_P2_B 0x00 -#define MAPSEL_P2_A 0x03 -#define MAPSEL_P2_A_DMA1 0x04 -#define MAPSEL_P2_A_DMA2 0x05 -#define MAPSEL_P2_A_DMA3 0x06 -#define MAPSEL_P2_A_DMA4 0x07 -#define MAPSEL_P1_B 0x08 -#define MAPSEL_P1_A 0x0b -#define MAPSEL_P1_A_DMA1 0x0c -#define MAPSEL_P1_A_DMA2 0x0d -#define MAPSEL_P1_A_DMA3 0x0e -#define MAPSEL_P1_A_DMA4 0x0f - -#define IRQ_ACINT_LEVEL (0 ^ 7) -#define IRQ_MIDINT_LEVEL (0 ^ 7) -#define IRQ_TIMINT_LEVEL (1 ^ 7) -#define IRQ_INTP1_LEVEL (2 ^ 7) -#define IRQ_IPI1_LEVEL (3 ^ 7) -#define IRQ_SMIDINT_LEVEL (3 ^ 7) -#define IRQ_AIC_LEVEL (4 ^ 7) - -#define IRQ_CHINT8_LEVEL (15 ^ 7) -#define IRQ_CHINT7_LEVEL (14 ^ 7) -#define IRQ_CHINT6_LEVEL (13 ^ 7) -#define IRQ_CHINT5_LEVEL (12 ^ 7) -#define IRQ_CHINT4_LEVEL (11 ^ 7) -#define IRQ_CHINT3_LEVEL (10 ^ 7) -#define IRQ_CHINT2_LEVEL (9 ^ 7) -#define IRQ_CHINT1_LEVEL (8 ^ 7) - -static const int ch_int_levels[8] = -{ - 12, 8, 13, 9, 14, 10, 15, 11 //IRQ_CHINT8_LEVEL, IRQ_CHINT7_LEVEL, IRQ_CHINT6_LEVEL, IRQ_CHINT5_LEVEL, IRQ_CHINT4_LEVEL, IRQ_CHINT3_LEVEL, IRQ_CHINT2_LEVEL, IRQ_CHINT1_LEVEL -}; - -#define IRQ_PERRINT_LEVEL (0 ^ 7) -#define IRQ_RTCINT_LEVEL (0 ^ 7) -#define IRQ_RINT_LEVEL (1 ^ 7) -#define IRQ_INTP2_LEVEL (2 ^ 7) -#define IRQ_IPI2_LEVEL (3 ^ 7) -#define IRQ_TOUCHINT_LEVEL (4 ^ 7) -#define IRQ_PENINT_LEVEL (5 ^ 7) -#define IRQ_ADINT_LEVEL (6 ^ 7) -#define IRQ_DISKINT_LEVEL (7 ^ 7) - -#define FDC_CONTROL_INTEN (1 << 2) - -#define FDC_STATUS_READY (1 << 3) -#define FDC_STATUS_TWO_SIDED (1 << 4) -#define FDC_STATUS_DISK_CHANGE (1 << 5) -#define FDC_STATUS_INTERRUPT (1 << 6) -#define FDC_STATUS_DRIVER_LOAD (1 << 7) - - -class cmi_state : public driver_device -{ -public: - cmi_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_maincpu1(*this, "maincpu1") - , m_maincpu2(*this, "maincpu2") - , m_midicpu(*this, "smptemidi") - , m_cmi07cpu(*this, "cmi07cpu") - , m_msm5832(*this, "msm5832") - , m_i8214(*this, "i8214_%u", 1U) - , m_q133_pia(*this, "q133_pia_%u", 1U) - , m_q133_ptm(*this, "q133_ptm") - , m_q133_acia(*this, "q133_acia_%u", 0U) - , m_q133_region(*this, "q133") - , m_q219_pia(*this, "q219_pia") - , m_q219_ptm(*this, "q219_ptm") - , m_cmi02_pia(*this, "cmi02_pia_%u", 1U) - , m_cmi02_ptm(*this, "cmi02_ptm") - , m_cmi07_ptm(*this, "cmi07_ptm") - , m_qfc9_region(*this, "qfc9") - , m_floppy0(*this, "wd1791:0") - , m_floppy1(*this, "wd1791:1") - , m_wd1791(*this, "wd1791") - , m_channels(*this, "cmi01a_%u", 0) - , m_screen(*this, "screen") - , m_palette(*this, "palette") - , m_lp_x_port(*this, "LP_X") - , m_lp_y_port(*this, "LP_Y") - , m_lp_touch_port(*this, "LP_TOUCH") - , m_cmi07_ram(*this, "cmi07_ram") - { - } - - void set_interrupt(int cpunum, int level, int state); - - virtual void machine_reset() override; - virtual void machine_start() override; - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; - - static const device_timer_id TIMER_MAP_SWITCH = 0; - static const device_timer_id TIMER_HBLANK = 1; - static const device_timer_id TIMER_JAM_TIMEOUT = 2; - - void init_cmi2x(); - - // CPU card - DECLARE_WRITE_LINE_MEMBER( q133_acia_irq ); - DECLARE_WRITE8_MEMBER( i8214_cpu1_w ); - DECLARE_WRITE8_MEMBER( i8214_cpu2_w ); - DECLARE_WRITE_LINE_MEMBER( i8214_1_int_w ); - DECLARE_WRITE_LINE_MEMBER( i8214_2_int_w ); - DECLARE_WRITE_LINE_MEMBER( i8214_3_int_w ); - DECLARE_WRITE_LINE_MEMBER( i8214_3_enlg ); - DECLARE_READ8_MEMBER( shared_ram_r ); - DECLARE_WRITE8_MEMBER( shared_ram_w ); - - DECLARE_READ8_MEMBER( q133_1_porta_r ); - DECLARE_WRITE8_MEMBER( q133_1_porta_w ); - DECLARE_WRITE8_MEMBER( q133_1_portb_w ); - - DECLARE_WRITE_LINE_MEMBER( cmi_iix_vblank ); - IRQ_CALLBACK_MEMBER( cpu1_interrupt_callback ); - IRQ_CALLBACK_MEMBER( cpu2_interrupt_callback ); - - // Video-related - DECLARE_READ8_MEMBER( video_r ); - DECLARE_READ8_MEMBER( lightpen_r ); - DECLARE_READ8_MEMBER( pia_q219_b_r ); - DECLARE_WRITE8_MEMBER( video_w ); - DECLARE_WRITE8_MEMBER( vscroll_w ); - DECLARE_WRITE8_MEMBER( video_attr_w ); - DECLARE_READ8_MEMBER( vram_r ); - DECLARE_WRITE8_MEMBER( vram_w ); - DECLARE_WRITE_LINE_MEMBER( pia_q219_irqa ); - DECLARE_WRITE_LINE_MEMBER( pia_q219_irqb ); - DECLARE_WRITE_LINE_MEMBER( ptm_q219_irq ); - uint32_t screen_update_cmi2x(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - - // Memory mapping - template<int cpunum> DECLARE_READ8_MEMBER( rom_r ); - DECLARE_WRITE8_MEMBER( map_ram_w ); - template<int cpunum> DECLARE_READ8_MEMBER( vector_r ); - template<int cpunum> DECLARE_READ8_MEMBER( map_r ); - template<int cpunum> DECLARE_WRITE8_MEMBER( map_w ); - DECLARE_READ8_MEMBER( atomic_r ); - DECLARE_WRITE8_MEMBER( cpufunc_w ); - DECLARE_READ8_MEMBER( parity_r ); - DECLARE_WRITE8_MEMBER( mapsel_w ); - template<int cpunum> DECLARE_READ8_MEMBER( irq_ram_r ); - template<int cpunum> DECLARE_WRITE8_MEMBER( irq_ram_w ); - - // MIDI/SMPTE - DECLARE_WRITE16_MEMBER( midi_dma_w ); - DECLARE_READ16_MEMBER( midi_dma_r ); - - // Floppy - DECLARE_WRITE8_MEMBER( fdc_w ); - DECLARE_READ8_MEMBER( fdc_r ); - DECLARE_WRITE_LINE_MEMBER( wd1791_irq ); - DECLARE_WRITE_LINE_MEMBER( wd1791_drq ); - - // Master card - DECLARE_READ8_MEMBER( cmi02_r ); - DECLARE_WRITE8_MEMBER( cmi02_w ); - DECLARE_WRITE8_MEMBER( master_tune_w ); - DECLARE_WRITE_LINE_MEMBER( cmi02_ptm_irq ); - DECLARE_WRITE_LINE_MEMBER( cmi02_ptm_o2 ); - - // ??? - DECLARE_READ8_MEMBER( cmi07_r ); - DECLARE_WRITE8_MEMBER( cmi07_w ); - - DECLARE_WRITE_LINE_MEMBER( msm5832_irq ); - DECLARE_WRITE_LINE_MEMBER( cmi07_irq ); - DECLARE_WRITE_LINE_MEMBER( q133_acia_clock ); - - template<int Channel> DECLARE_WRITE_LINE_MEMBER( channel_irq ); - - void cmi2x(machine_config &config); - void cmi07cpu_map(address_map &map); - void maincpu1_map(address_map &map); - void maincpu2_map(address_map &map); - void midicpu_map(address_map &map); - -protected: - required_device<mc6809e_device> m_maincpu1; - required_device<mc6809e_device> m_maincpu2; - required_device<m68000_device> m_midicpu; - required_device<mc6809e_device> m_cmi07cpu; - - required_device<msm5832_device> m_msm5832; - required_device_array<i8214_device, 3> m_i8214; - required_device_array<pia6821_device, 2> m_q133_pia; - required_device<ptm6840_device> m_q133_ptm; - required_device_array<mos6551_device, 4> m_q133_acia; - required_memory_region m_q133_region; - - required_device<pia6821_device> m_q219_pia; - required_device<ptm6840_device> m_q219_ptm; - - required_device_array<pia6821_device, 2> m_cmi02_pia; - required_device<ptm6840_device> m_cmi02_ptm; - - required_device<ptm6840_device> m_cmi07_ptm; - - required_memory_region m_qfc9_region; - required_device<floppy_connector> m_floppy0; - required_device<floppy_connector> m_floppy1; - required_device<fd1791_device> m_wd1791; - - required_device_array<cmi01a_device, 8> m_channels; - - required_device<screen_device> m_screen; - required_device<palette_device> m_palette; - - required_ioport m_lp_x_port; - required_ioport m_lp_y_port; - required_ioport m_lp_touch_port; - - required_shared_ptr<uint8_t> m_cmi07_ram; - - address_space *m_cpu1space; - address_space *m_cpu2space; - -private: - emu_timer *m_map_switch_timer; - emu_timer *m_hblank_timer; - emu_timer *m_jam_timeout_timer; - - uint8_t m_video_data; - - // Memory - bool map_is_active(int cpunum, int map, uint8_t *map_info); - void update_address_space(int cpunum, uint8_t mapinfo); - void install_video_ram(int cpunum); - void install_peripherals(int cpunum); - - // Video - void hblank(); - void update_video_pos(int y, int x, int byte_size); - void video_write(int offset); - - // Floppy - void dma_fdc_rom(); - void write_fdc_ctrl(uint8_t data); - void fdc_dma_transfer(); - - // Q133 CPU Card - uint8_t *m_q133_rom; - - uint8_t m_hp_int; - std::unique_ptr<uint8_t[]> m_shared_ram; - std::unique_ptr<uint8_t[]> m_scratch_ram[2]; - - /* Memory management */ - uint8_t m_map_sel[16]; - std::unique_ptr<uint8_t[]> m_map_ram[2]; - std::unique_ptr<uint8_t[]> m_q256_ram[2]; - uint8_t m_map_ram_latch; - int m_cpu_active_space[2]; // TODO: Make one register - int m_cpu_map_switch[2]; - uint8_t m_irq_address[2][2]; - int m_m6809_bs_hack_cnt; - int m_m6809_bs_hack_cpu; - - /* Q219 lightpen/graphics card */ - std::unique_ptr<uint8_t[]> m_video_ram; - uint16_t m_x_pos; - uint8_t m_y_pos; - uint16_t m_lp_x; - uint8_t m_lp_y; - uint8_t m_q219_b_touch; - - /* QFC9 floppy disk controller card */ - uint8_t * m_qfc9_region_ptr; - int m_fdc_drq; - uint8_t m_fdc_addr; - uint8_t m_fdc_ctrl; - uint8_t m_fdc_status; - PAIR m_fdc_dma_addr; - PAIR m_fdc_dma_cnt; - - /* CMI-07 */ - uint8_t m_cmi07_ctrl; - - uint8_t m_msm5832_addr; - - // Master card (CMI-02) - int m_cmi02_ptm_irq; -}; - -/************************************** - * - * Video hardware - * - *************************************/ - -uint32_t cmi_state::screen_update_cmi2x(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - const pen_t *pen = m_palette->pens(); - uint8_t y_scroll = m_q219_pia->a_output(); - uint8_t invert = (!BIT(m_q219_pia->b_output(), 3)) & 1; - - for (int y = cliprect.min_y; y <= cliprect.max_y; ++y) - { - uint8_t *src = &m_video_ram[(512/8) * ((y + y_scroll) & 0xff)]; - uint32_t *dest = &bitmap.pix32(y, cliprect.min_x); - - for (int x = cliprect.min_x; x <= cliprect.max_x; x += 8) - { - uint8_t data = *src++; - - /* Store 8 pixels */ - for (int i = 0; i < 8; ++i) - *dest++ = pen[BIT(data, 7 - i) ^ invert]; - } - } - - /* Get lightpen position */ - //if (LPCEN && NOT_TOUCHING) - if (m_lp_touch_port->read() && BIT(m_q219_pia->b_output(), 1)) - { - /* Invert target pixel */ - bitmap.pix32(m_lp_y_port->read(), m_lp_x_port->read()) ^= 0x00ffffff; - } - - - - return 0; -} - -void cmi_state::hblank() -{ - int v = m_screen->vpos(); - - if (!m_screen->vblank()) - { - int _touch = m_lp_touch_port->read(); - int _tfh = !BIT(m_q219_pia->b_output(), 2); - - if (v == m_lp_y_port->read()) - { - if (_touch) - m_q219_b_touch = 0; - else - m_q219_b_touch = 1 << 5; - - m_q219_pia->ca1_w(!_touch ? 1 : 0); - - if (!_touch || !_tfh) - { - /* Latch the counters */ - m_lp_x = m_lp_x_port->read(); - m_lp_y = m_lp_y_port->read(); - - /* LPSTB */ - m_q219_pia->cb1_w(1); - } - } - } - /* Adjust for next scanline */ - if (++v >= VTOTAL) - v = 0; - - m_hblank_timer->adjust(m_screen->time_until_pos(v, HBLANK_START)); - -} - -void cmi_state::update_video_pos(int y, int x, int byte_size) -{ - uint8_t *video_addr = &m_video_ram[m_y_pos * (512 / 8) + (m_x_pos / 8)]; - - if (byte_size) - { - *video_addr = m_video_data; - } - else - { - int bit_mask = 1 << ((7 ^ m_x_pos) & 7); - - *video_addr &= ~bit_mask; - *video_addr |= m_video_data & bit_mask; - } - - if (y > 0) - m_y_pos = (m_y_pos + 1) & 0xff; - else if (y < 0) - m_y_pos = (m_y_pos - 1) & 0xff; - - if (x > 0) - m_x_pos = (m_x_pos + 1) & 0x1ff; - else if (x < 0) - m_x_pos = (m_x_pos - 1) & 0x1ff; -} - -void cmi_state::video_write(int offset) -{ - switch (offset) - { - case 0x0: update_video_pos( 0, 0, 0); break; - case 0x1: update_video_pos( 0, 1, 0); break; - case 0x2: update_video_pos( 0, -1, 0); break; - case 0x3: update_video_pos( 0, 0, 1); break; - case 0x4: update_video_pos( 1, 0, 0); break; - case 0x5: update_video_pos( 1, 1, 0); break; - case 0x6: update_video_pos( 1, -1, 0); break; - case 0x7: update_video_pos( 1, 0, 1); break; - case 0x8: update_video_pos(-1, 0, 0); break; - case 0x9: update_video_pos(-1, 1, 0); break; - case 0xa: update_video_pos(-1, -1, 0); break; - case 0xb: update_video_pos(-1, 0, 1); break; -// default: printf("Video Write %x %x\n", offset, m_video_data); - } -} - -READ8_MEMBER( cmi_state::video_r ) -{ - if (machine().side_effects_disabled()) - return m_video_data; - - m_video_data = m_video_ram[m_y_pos * (512 / 8) + (m_x_pos / 8)]; - - video_write(offset); - return m_video_data; -} - -READ8_MEMBER( cmi_state::lightpen_r ) -{ - if (offset & 2) - return m_lp_y; - else - return m_lp_x >> 1; -} - -READ8_MEMBER( cmi_state::pia_q219_b_r ) -{ - return ((m_lp_x << 7) & 0x80) | m_q219_b_touch; -} - - -WRITE8_MEMBER( cmi_state::video_w ) -{ - m_video_data = data; - video_write(offset); -} - -WRITE8_MEMBER( cmi_state::vscroll_w ) -{ - // TODO: Partial updates. Also, this should be done through a PIA -} - -WRITE8_MEMBER( cmi_state::video_attr_w ) -{ - // TODO -} - -WRITE8_MEMBER( cmi_state::vram_w ) -{ - m_video_ram[offset] = data; -} - -READ8_MEMBER( cmi_state::vram_r ) -{ - if (machine().side_effects_disabled()) - return m_video_ram[offset]; - - /* Latch the current video position */ - m_y_pos = (offset >> 6) & 0xff; - m_x_pos = (offset & 0x3f) << 3; - - return m_video_ram[offset]; -} - - - -/* Memory handling */ - -template<int cpunum> READ8_MEMBER( cmi_state::rom_r ) -{ - uint16_t base = (cpunum ? 0x1000 : 0x2000); - return *(((uint8_t *)m_q133_region->base()) + base + offset); -} - -WRITE8_MEMBER( cmi_state::map_ram_w ) -{ - if ((offset & 1) == 0) - { - m_map_ram_latch = data; - } - else - { - for (int i = 0; i < NUM_Q256_CARDS; ++i) - { - uint8_t map_info; - int map = (offset >> 6); - int page_enable = ((m_map_ram_latch & 0x80) && (i == (m_map_ram_latch & 7))) ? 0x80 : 0; - - m_map_ram[i][offset >> 1] = page_enable | (data & 0x7f); - - /* Determine if this map is in use by either CPU */ - if (map_is_active(CPU_1, map, &map_info)) - update_address_space(0, map_info); - - if (map_is_active(CPU_2, map, &map_info)) - update_address_space(1, map_info); - } - } -} - -template<int cpunum> READ8_MEMBER( cmi_state::vector_r ) -{ - return m_q133_rom[(cpunum ? 0xbfe : 0xffe) + offset]; -} - -template<int cpunum> READ8_MEMBER( cmi_state::map_r ) -{ - uint8_t data = (m_cpu_active_space[1] << 2) | (m_cpu_active_space[0] << 1) | cpunum; - return data; -} - -template<int cpunum> WRITE8_MEMBER( cmi_state::map_w ) -{ - m_map_switch_timer->adjust(attotime::from_ticks(data & 0xf, M6809_CLOCK), cpunum); -} - -template<int cpunum> READ8_MEMBER( cmi_state::irq_ram_r ) -{ - if (machine().side_effects_disabled()) - return m_scratch_ram[cpunum][0xf8 + offset]; - - if (m_m6809_bs_hack_cnt > 0 && m_m6809_bs_hack_cpu == cpunum) - { - m_m6809_bs_hack_cnt--; - return m_irq_address[cpunum][offset]; - } - return m_scratch_ram[cpunum][0xf8 + offset]; -} - -template<int cpunum> WRITE8_MEMBER( cmi_state::irq_ram_w ) -{ - m_scratch_ram[cpunum][0xf8 + offset] = data; -} - -void cmi_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - switch (id) - { - case TIMER_MAP_SWITCH: - { - m_cpu_active_space[param] = m_cpu_map_switch[param]; - uint8_t map_info = (m_cpu_map_switch[param] == MAPPING_A) ? - m_map_sel[param ? MAPSEL_P2_A : MAPSEL_P1_A] : - m_map_sel[param ? MAPSEL_P2_B : MAPSEL_P1_B]; - update_address_space(param, map_info); - m_map_switch_timer->adjust(attotime::never); - break; - } - - case TIMER_HBLANK: - hblank(); - break; - - case TIMER_JAM_TIMEOUT: - m_maincpu2->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); - m_jam_timeout_timer->adjust(attotime::never); - break; - } -} - -READ8_MEMBER( cmi_state::atomic_r ) -{ - // TODO - //printf("atomic access\n"); - return 0; -} - -WRITE8_MEMBER( cmi_state::cpufunc_w ) -{ - int cpunum = data & 1; - int idx = data & 6; - int bit = (data & 8) >> 3; - - switch (idx) - { - case 0: set_interrupt(cpunum, IRQ_IPI2_LEVEL, bit ? ASSERT_LINE : CLEAR_LINE); - break; - case 2: // TODO: Hardware trace - printf("TODO: Hardware trace %02x\n", data); - 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; - } -} - -READ8_MEMBER( cmi_state::parity_r ) -{ - //printf("parity_r %04x\n", offset); - // TODO - return 0xff; -} - -WRITE8_MEMBER( cmi_state::mapsel_w ) -{ - data ^= 0x1f; - m_map_sel[offset] = data; - - if ((offset == MAPSEL_P1_A) && (m_cpu_active_space[0] == MAPPING_A)) - update_address_space(0, data); - else if ((offset == MAPSEL_P1_B) && (m_cpu_active_space[0] == MAPPING_B)) - update_address_space(0, data); - - if ((offset == MAPSEL_P2_A) && (m_cpu_active_space[1] == MAPPING_A)) - update_address_space(1, data); - else if ((offset == MAPSEL_P2_B) && (m_cpu_active_space[1] == MAPPING_B)) - update_address_space(1, data); -} - - - -WRITE16_MEMBER( cmi_state::midi_dma_w ) -{ - address_space *cmi_space = ((offset & 0x8000) ? m_cpu2space : m_cpu1space); - offset &= 0x7fff; - - if (ACCESSING_BITS_0_7) - cmi_space->write_byte(offset * 2 + 1, data); - if (ACCESSING_BITS_8_15) - cmi_space->write_byte(offset * 2, data >> 8); -} - -READ16_MEMBER( cmi_state::midi_dma_r ) -{ - address_space *cmi_space = ((offset & 0x8000) ? m_cpu2space : m_cpu1space); - offset &= 0x7fff; - return cmi_space->read_word(offset * 2); -} - -/* The maps are dynamically populated */ -void cmi_state::maincpu1_map(address_map &map) -{ - map(0xfffe, 0xffff).r(FUNC(cmi_state::vector_r<0>)); -} - -void cmi_state::maincpu2_map(address_map &map) -{ - map(0xfffe, 0xffff).r(FUNC(cmi_state::vector_r<1>)); -} - -void cmi_state::midicpu_map(address_map &map) -{ - map(0x000000, 0x003fff).rom(); - map(0x040000, 0x05ffff).rw(FUNC(cmi_state::midi_dma_r), FUNC(cmi_state::midi_dma_w)); -// map(0x060000, 0x06001f) TIMERS -// map(0x060050, 0x06005f) ACIA -// map(0x060070, 0x06007f) SMPTE - map(0x080000, 0x083fff).ram(); -} - -void cmi_state::cmi07cpu_map(address_map &map) -{ - map(0x0000, 0x3fff).noprw(); // TODO - map(0x4000, 0x4fff).noprw(); // TODO - map(0x8000, 0x8fff).rw(m_cmi07_ptm, FUNC(ptm6840_device::read), FUNC(ptm6840_device::write)); - map(0xc000, 0xffff).ram().share("cmi07_ram"); -} - -/* Input ports */ -static INPUT_PORTS_START( cmi2x ) - PORT_START("LP_X") - PORT_BIT( 0xffff, HBLANK_START/2, IPT_LIGHTGUN_X) PORT_NAME ("Lightpen X") PORT_MINMAX(0, HBLANK_START - 1) PORT_SENSITIVITY(50) PORT_CROSSHAIR(X, 1.0, 0.0, 0) - - PORT_START("LP_Y") - PORT_BIT( 0xffff, VBLANK_START/2, IPT_LIGHTGUN_Y) PORT_NAME ("Lightpen Y") PORT_MINMAX(0, VBLANK_START - 1) PORT_SENSITIVITY(50) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) - - PORT_START("LP_TOUCH") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME ( "Lightpen Touch" ) PORT_CODE( MOUSECODE_BUTTON1 ) -INPUT_PORTS_END - -bool cmi_state::map_is_active(int cpunum, int map, uint8_t *map_info) -{ - if (m_cpu_active_space[cpunum] == MAPPING_A) - { - *map_info = m_map_sel[cpunum ? MAPSEL_P2_A : MAPSEL_P1_A]; - - if ((*map_info & 0x1f) == map) - return 1; - } - else - { - *map_info = m_map_sel[cpunum ? MAPSEL_P2_B : MAPSEL_P1_B]; - - if ((*map_info & 0x1f) == map) - return 1; - } - - return 0; -} - -void cmi_state::update_address_space(int cpunum, uint8_t mapinfo) -{ - int map = mapinfo & 0x1f; - bool vram_en = !BIT(mapinfo, 5); - bool periph_en = !BIT(mapinfo, 7); - int i; - - address_space *space = (cpunum == 0 ? m_cpu1space : m_cpu2space); - - space->unmap_readwrite(0x0000, 0xffff); - - /* Step through the map RAM assignments */ - for (int page = 0; page < PAGE_COUNT; ++page) - { - int address = page * PAGE_SIZE; - uint8_t page_info = 0; - - /* Scan through the cards */ - for (i = 0; i < NUM_Q256_CARDS; ++i) - { - page_info = m_map_ram[i][(map << PAGE_SHIFT) + page]; - - /* Page is enabled in this bank */ - if (page_info & 0x80) - break; - } - - if (BIT(m_cmi07_ctrl, 6)) - { - if ((cpunum == 0) || !BIT(m_cmi07_ctrl, 7)) - { - if (m_cmi07_ctrl & 0x30) - if ((address & 0xc000) == ((m_cmi07_ctrl & 0x30) << 10)) - { - space->install_ram(address, address + PAGE_SIZE - 1, &m_cmi07_ram[(page * PAGE_SIZE) & 0x3fff]); - continue; - } - } - } - - /* No banks had this page enabled - skip */ - if ((page_info & 0x80) == 0) - continue; - - /* If Video RAM is enabled, don't install RAM here */ - if (vram_en && address >= 0x8000 && address <= 0xbfff) - continue; - - /* If peripherals are enabled, don't install RAM here */ - if (periph_en && address >= 0xf000 && address <= 0xffff) // TODO - continue; - - /* Now map the RAM page */ - space->install_ram(address, address + PAGE_SIZE - 1, &m_q256_ram[i][(page_info & 0x7f) * PAGE_SIZE]); - } - - if (vram_en) - install_video_ram(cpunum); - - if (periph_en) - install_peripherals(cpunum); -} - -WRITE8_MEMBER( cmi_state::cmi07_w ) -{ - m_cmi07_ctrl = data; - - m_cmi07cpu->set_input_line(INPUT_LINE_RESET, BIT(data, 0) ? CLEAR_LINE : ASSERT_LINE); - m_cmi07cpu->set_input_line(M6809_FIRQ_LINE, BIT(data, 1) ? CLEAR_LINE : ASSERT_LINE); - m_cmi07cpu->set_input_line(INPUT_LINE_NMI, BIT(data, 2) ? CLEAR_LINE : ASSERT_LINE); - m_cmi07cpu->set_input_line(INPUT_LINE_HALT, BIT(data, 3) ? CLEAR_LINE : ASSERT_LINE); - - /* We need to update the address spaces */ - uint8_t map_info = (m_cpu_active_space[0] == MAPPING_A) ? m_map_sel[MAPSEL_P1_A] : m_map_sel[MAPSEL_P1_B]; - update_address_space(0, map_info); - - map_info = (m_cpu_active_space[1] == MAPPING_A) ? m_map_sel[MAPSEL_P2_A] : m_map_sel[MAPSEL_P2_B]; - update_address_space(1, map_info); -} - -READ8_MEMBER( cmi_state::cmi07_r ) -{ - //printf("CMI 07 R: %x\n", offset); - return 0xff; -} - -WRITE_LINE_MEMBER( cmi_state::q133_acia_irq ) -{ - set_interrupt(CPU_1, IRQ_ACINT_LEVEL, state ? ASSERT_LINE : CLEAR_LINE); -} - - -/************************************** - * - * Floppy disk interface - * - *************************************/ - -void cmi_state::dma_fdc_rom() -{ - /* DMA channel 1 is used*/ - uint8_t map_info = m_map_sel[MAPSEL_P2_A_DMA1]; - int map = map_info & 0x1f; - int addr = m_fdc_dma_addr.w.l & ~PAGE_MASK; - int page = addr / PAGE_SIZE; - uint8_t p_info = 0; - - /* Active low */ - m_fdc_status &= ~FDC_STATUS_DRIVER_LOAD; - - int i; - for (i = 0; i < NUM_Q256_CARDS; ++i) - { - p_info = m_map_ram[i][(map << PAGE_SHIFT) | page]; - - if (p_info & 0x80) - break; - } - - if ((p_info & 0x80) == 0) - { - printf("Trying to DMA FDC driver to a non-enabled page!\n"); - return; - } - - /* TODO: This should be stuck in a deferred write */ - int cnt = std::min(m_fdc_dma_cnt.w.l ^ 0xffff, 2048); - memcpy(&m_q256_ram[i][(p_info & 0x7f) * PAGE_SIZE], m_qfc9_region_ptr, cnt); - m_fdc_status |= FDC_STATUS_DRIVER_LOAD; - - /* TODO: Is this correct? */ - m_fdc_dma_addr.w.l += 0x800; - m_fdc_dma_cnt.w.l = 0; -} - -void cmi_state::write_fdc_ctrl(uint8_t data) -{ - int drive = data & 1; - int side = BIT(data, 5) ? 1 : 0; - - switch (drive) - { - case 0: m_wd1791->set_floppy(m_floppy0->get_device()); break; - case 1: m_wd1791->set_floppy(m_floppy1->get_device()); break; - } - - if (m_floppy0->get_device()) m_floppy0->get_device()->ss_w(side); - if (m_floppy1->get_device()) m_floppy1->get_device()->ss_w(side); - - m_wd1791->dden_w(BIT(data, 7) ? true : false); - - m_fdc_ctrl = data; -} - -WRITE8_MEMBER( cmi_state::fdc_w ) -{ - if (offset == 0) - { - switch (m_fdc_addr) - { - case 0x0: write_fdc_ctrl(data); break; - case 0x2: m_fdc_dma_addr.b.l = data; break; - case 0x4: m_fdc_dma_addr.b.h = data; break; - case 0x6: m_fdc_dma_cnt.b.l = data; break; - case 0x8: m_fdc_dma_cnt.b.h = data; break; - case 0xa: dma_fdc_rom(); break; - case 0xc: m_wd1791->cmd_w(data ^ 0xff); break; - case 0xd: m_wd1791->track_w(data ^ 0xff); break; - case 0xe: m_wd1791->sector_w(data ^ 0xff); break; - case 0xf: m_wd1791->data_w(data ^ 0xff); break; - default: printf("fdc_w: Invalid access (%x with %x)", m_fdc_addr, data); - } - } - else - m_fdc_addr = data; -} - -READ8_MEMBER( cmi_state::fdc_r ) -{ - if (machine().side_effects_disabled()) - return 0; - - if (offset == 0) - { - switch (m_fdc_addr) - { - case 0xc: return m_wd1791->status_r() ^ 0xff; - case 0xd: return m_wd1791->track_r() ^ 0xff; - case 0xe: return m_wd1791->sector_r() ^ 0xff; - case 0xf: return m_wd1791->data_r() ^ 0xff; - default: return 0; - } - } - else - return m_fdc_status; -} - -void cmi_state::fdc_dma_transfer() -{ - /* DMA channel 1 is used*/ - uint8_t map_info = m_map_sel[MAPSEL_P2_A_DMA1]; - int map = map_info & 0x1f; - - int cpu_page = (m_fdc_dma_addr.w.l & ~PAGE_MASK) / PAGE_SIZE; - int phys_page = 0; - - int i; - for (i = 0; i < NUM_Q256_CARDS; ++i) - { - phys_page = m_map_ram[i][(map << PAGE_SHIFT) | cpu_page]; - - if (phys_page & 0x80) - break; - } - - //phys_page &= 0x7f; - - /* Transfer from disk to RAM */ - if (!BIT(m_fdc_ctrl, 4)) - { - /* Read a byte at a time */ - uint8_t data = m_wd1791->data_r() ^ 0xff; - - if (m_fdc_dma_cnt.w.l == 0xffff) - return; - - if (m_cmi07_ctrl & 0x30) - if (BIT(m_cmi07_ctrl, 6) && !BIT(m_cmi07_ctrl, 7)) - { - if ((m_fdc_dma_addr.w.l & 0xc000) == ((m_cmi07_ctrl & 0x30) << 10)) - m_cmi07_ram[m_fdc_dma_addr.w.l & 0x3fff] = data; - } - - if (phys_page & 0x80) - m_q256_ram[i][((phys_page & 0x7f) * PAGE_SIZE) + (m_fdc_dma_addr.w.l & PAGE_MASK)] = data; - - if (!BIT(m_fdc_ctrl, 3)) - m_fdc_dma_addr.w.l++; - } - - // Transfer from RAM to disk - else - { - if (m_fdc_dma_cnt.w.l == 0xffff) - return; - - /* Write a byte at a time */ - uint8_t data = 0; - - /* TODO: This should be stuck in a deferred write */ - if (phys_page & 0x80) - data = m_q256_ram[i][((phys_page & 0x7f) * PAGE_SIZE) + (m_fdc_dma_addr.w.l & PAGE_MASK)]; - - m_wd1791->data_w(data ^ 0xff); - - if (!BIT(m_fdc_ctrl, 3)) - m_fdc_dma_addr.w.l++; - } - - m_fdc_dma_cnt.w.l++; -} - -WRITE_LINE_MEMBER( cmi_state::wd1791_irq ) -{ - if (state) - { - m_fdc_status |= FDC_STATUS_INTERRUPT; - - if (m_fdc_ctrl & FDC_CONTROL_INTEN) - set_interrupt(CPU_2, IRQ_DISKINT_LEVEL, ASSERT_LINE); - - } - else - { - m_fdc_status &= ~FDC_STATUS_INTERRUPT; - set_interrupt(CPU_2, IRQ_DISKINT_LEVEL, CLEAR_LINE); - } -} - -WRITE_LINE_MEMBER( cmi_state::wd1791_drq ) -{ - m_fdc_drq = state; - if (state) - fdc_dma_transfer(); -} - - - -/************************************** - * - * Master card and channel cards - * - *************************************/ - -/* -0 - 1f -20 = PIA -21 = PIA -22 = PIA -23 = PIA - -24 = ADC -25 = ADC -26 = HALT CPU 2 -27 = UNHALT CPU 2 -28 - 2B = PIA -*/ - -WRITE8_MEMBER( cmi_state::master_tune_w ) -{ -// double mfreq = (double)data * ((double)MASTER_OSCILLATOR / 2.0) / 256.0; -} - -WRITE_LINE_MEMBER( cmi_state::cmi02_ptm_irq ) -{ - //printf("cmi02_ptm_irq: %d\n", state); - m_cmi02_ptm_irq = state; - set_interrupt(CPU_1, IRQ_TIMINT_LEVEL, m_cmi02_ptm_irq ? ASSERT_LINE : CLEAR_LINE); -} - -WRITE_LINE_MEMBER( cmi_state::cmi02_ptm_o2 ) -{ - m_cmi02_ptm->set_c1(state); - m_cmi02_ptm->set_c3(state); -} - -READ8_MEMBER( cmi_state::cmi02_r ) -{ - if (machine().side_effects_disabled()) - return 0; - - if (offset <= 0x1f) - { - int ch_mask = m_cmi02_pia[0]->a_output(); - - for (int i = 0; i < 8; ++i) - { - if (ch_mask & (1 << i)) - { - return m_channels[i]->read(offset & 0x1f); - } - } - - return 0xff; - } - else - { - switch (offset) - { - case 0x20: case 0x21: case 0x22: case 0x23: - return m_cmi02_pia[0]->read(offset & 3); - - case 0x26: - m_maincpu2->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); - /* LS123 one-shot with 10n and 150k */ - m_jam_timeout_timer->adjust(attotime::from_usec(675)); - return 0xff; - - case 0x27: - m_maincpu2->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); - return 0xff; - - case 0x28: case 0x29: case 0x2a: case 0x2b: - return m_cmi02_pia[1]->read(offset & 3); - - case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: - return m_cmi02_ptm->read(offset & 7); - - default: - logerror("CMI02 R: %x\n", offset); - return 0; - } - } -} - -WRITE8_MEMBER( cmi_state::cmi02_w ) -{ - if (offset <= 0x1f) - { - int ch_mask = m_cmi02_pia[0]->a_output(); - - for (int i = 0; i < 8; ++i) - { - if (ch_mask & (1 << i)) - m_channels[i]->write(offset & 0x1f, data); - } - } - else - { - switch (offset) - { - case 0x20: case 0x21: case 0x22: case 0x23: - m_cmi02_pia[0]->write(offset & 3, data); - break; - - case 0x28: case 0x29: case 0x2a: case 0x2b: - m_cmi02_pia[1]->write(offset & 3, data); - break; - - case 0x30: - m_maincpu1->set_input_line(M6809_IRQ_LINE, CLEAR_LINE); - data ^= 0xff; - m_i8214[2]->sgs_w((data >> 3) & 1); - m_i8214[2]->b_w(data & 0x7); - break; - - case 0x31: case 0x32: - set_interrupt(0, IRQ_INTP1_LEVEL, (offset & 2) ? CLEAR_LINE : ASSERT_LINE); - break; - - case 0x33: case 0x34: - set_interrupt(1, IRQ_INTP2_LEVEL, (offset & 4) ? CLEAR_LINE : ASSERT_LINE); - break; - - case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: - m_cmi02_ptm->write(offset & 7, data); - break; - - default: - logerror("CMI02 W: %x %x\n", offset, data); - } - } -} - -template<int Channel> -WRITE_LINE_MEMBER(cmi_state::channel_irq) -{ - set_interrupt(CPU_1, ch_int_levels[Channel], state); -} - -void cmi_state::install_video_ram(int cpunum) -{ - address_space *space = (cpunum == CPU_1 ? m_cpu1space : m_cpu2space); - - space->install_readwrite_handler(0x8000, 0xbfff, read8_delegate(*this, FUNC(cmi_state::vram_r)), write8_delegate(*this, FUNC(cmi_state::vram_w))); -} - -WRITE8_MEMBER( cmi_state::i8214_cpu1_w ) -{ - //printf("i8214_cpu1_w: %02x\n", data); - m_maincpu1->set_input_line(M6809_IRQ_LINE, CLEAR_LINE); - data ^= 0xff; - m_i8214[0]->sgs_w((data >> 3) & 1); - m_i8214[0]->b_w(data & 0x7); -} - - -WRITE8_MEMBER( cmi_state::i8214_cpu2_w ) -{ - //printf("i8214_cpu2_w: %02x\n", data); - m_maincpu2->set_input_line(M6809_IRQ_LINE, CLEAR_LINE); - data ^= 0xff; - m_i8214[1]->sgs_w((data >> 3) & 1); - m_i8214[1]->b_w(data & 0x7); -} - -// TODO: replace with share() -READ8_MEMBER( cmi_state::shared_ram_r ) -{ - return m_shared_ram[offset]; -} - -WRITE8_MEMBER( cmi_state::shared_ram_w ) -{ - m_shared_ram[offset] = data; -} - -void cmi_state::install_peripherals(int cpunum) -{ - address_space *space = (cpunum == CPU_1 ? m_cpu1space : m_cpu2space); - - space->install_readwrite_handler(0xe000, 0xe03f, read8_delegate(*this, FUNC(cmi_state::cmi02_r)), write8_delegate(*this, FUNC(cmi_state::cmi02_w))); - - if (cpunum) - space->install_readwrite_handler(0xf000, 0xf7ff, read8_delegate(*this, FUNC(cmi_state::rom_r<1>)), write8_delegate(*this, FUNC(cmi_state::map_ram_w))); - else - space->install_readwrite_handler(0xf000, 0xf7ff, read8_delegate(*this, FUNC(cmi_state::rom_r<0>)), write8_delegate(*this, FUNC(cmi_state::map_ram_w))); - - space->install_rom(0xf800, 0xfbff, m_q133_rom + (cpunum == CPU_2 ? 0x1800 : 0x2800)); - - space->install_readwrite_handler(0xfc40, 0xfc4f, read8_delegate(*this, FUNC(cmi_state::parity_r)), write8_delegate(*this, FUNC(cmi_state::mapsel_w))); - space->nop_readwrite(0xfc5a, 0xfc5b); // Q077 HDD controller - not installed - space->install_readwrite_handler(0xfc5e, 0xfc5e, read8_delegate(*this, FUNC(cmi_state::atomic_r)), write8_delegate(*this, FUNC(cmi_state::cpufunc_w))); - if (cpunum) - space->install_readwrite_handler(0xfc5f, 0xfc5f, read8_delegate(*this, FUNC(cmi_state::map_r<1>)), write8_delegate(*this, FUNC(cmi_state::map_w<1>))); - else - space->install_readwrite_handler(0xfc5f, 0xfc5f, read8_delegate(*this, FUNC(cmi_state::map_r<0>)), write8_delegate(*this, FUNC(cmi_state::map_w<0>))); - - space->install_readwrite_handler(0xfc80, 0xfc83, read8sm_delegate(*m_q133_acia[0], FUNC(mos6551_device::read)), write8sm_delegate(*m_q133_acia[0], FUNC(mos6551_device::write))); - space->install_readwrite_handler(0xfc84, 0xfc87, read8sm_delegate(*m_q133_acia[1], FUNC(mos6551_device::read)), write8sm_delegate(*m_q133_acia[1], FUNC(mos6551_device::write))); - space->install_readwrite_handler(0xfc88, 0xfc8b, read8sm_delegate(*m_q133_acia[2], FUNC(mos6551_device::read)), write8sm_delegate(*m_q133_acia[2], FUNC(mos6551_device::write))); - space->install_readwrite_handler(0xfc8c, 0xfc8f, read8sm_delegate(*m_q133_acia[3], FUNC(mos6551_device::read)), write8sm_delegate(*m_q133_acia[3], FUNC(mos6551_device::write))); - space->install_readwrite_handler(0xfc90, 0xfc97, read8sm_delegate(*m_q133_ptm, FUNC(ptm6840_device::read)), write8sm_delegate(*m_q133_ptm, FUNC(ptm6840_device::write))); - - space->install_readwrite_handler(0xfcbc, 0xfcbc, read8_delegate(*this, FUNC(cmi_state::cmi07_r)), write8_delegate(*this, FUNC(cmi_state::cmi07_w))); - - space->install_read_handler(0xfcc0, 0xfcc3, read8_delegate(*this, FUNC(cmi_state::lightpen_r))); - space->install_readwrite_handler(0xfcc4, 0xfcc7, read8sm_delegate(*m_q219_pia, FUNC(pia6821_device::read)), write8sm_delegate(*m_q219_pia, FUNC(pia6821_device::write))); - space->install_readwrite_handler(0xfcc8, 0xfccf, read8sm_delegate(*m_q219_ptm, FUNC(ptm6840_device::read)), write8sm_delegate(*m_q219_ptm, FUNC(ptm6840_device::write))); - space->install_readwrite_handler(0xfcd0, 0xfcdc, read8_delegate(*this, FUNC(cmi_state::video_r)), write8_delegate(*this, FUNC(cmi_state::video_w))); - space->install_readwrite_handler(0xfce0, 0xfce1, read8_delegate(*this, FUNC(cmi_state::fdc_r)), write8_delegate(*this, FUNC(cmi_state::fdc_w))); - space->nop_readwrite(0xfce2, 0xfcef); // Monitor ROM will attempt to detect floppy disk controller cards in this entire range - space->install_readwrite_handler(0xfcf0, 0xfcf7, read8sm_delegate(*m_q133_pia[0], FUNC(pia6821_device::read)), write8sm_delegate(*m_q133_pia[0], FUNC(pia6821_device::write))); - space->install_readwrite_handler(0xfcf8, 0xfcff, read8sm_delegate(*m_q133_pia[1], FUNC(pia6821_device::read)), write8sm_delegate(*m_q133_pia[1], FUNC(pia6821_device::write))); - - space->install_write_handler(0xfcfc, 0xfcfc, write8_delegate(*this, FUNC(cmi_state::i8214_cpu1_w))); - space->install_write_handler(0xfcfd, 0xfcfd, write8_delegate(*this, FUNC(cmi_state::i8214_cpu2_w))); - - space->install_readwrite_handler(0xfd00, 0xfeff, read8_delegate(*this, FUNC(cmi_state::shared_ram_r)), write8_delegate(*this, FUNC(cmi_state::shared_ram_w))); - - space->install_ram(0xff00, 0xfff7, &m_scratch_ram[cpunum][0]); - space->install_ram(0xfffa, 0xfffd, &m_scratch_ram[cpunum][0xfa]); - - if (cpunum) - { - space->install_readwrite_handler(0xfff8, 0xfff9, read8_delegate(*this, FUNC(cmi_state::irq_ram_r<1>)), write8_delegate(*this, FUNC(cmi_state::irq_ram_w<1>))); - space->install_read_handler(0xfffe, 0xffff, read8_delegate(*this, FUNC(cmi_state::vector_r<1>))); - } - else - { - space->install_readwrite_handler(0xfff8, 0xfff9, read8_delegate(*this, FUNC(cmi_state::irq_ram_r<0>)), write8_delegate(*this, FUNC(cmi_state::irq_ram_w<0>))); - space->install_read_handler(0xfffe, 0xffff, read8_delegate(*this, FUNC(cmi_state::vector_r<0>))); - } -} - - -/************************************* - * - * Interrupt Handling - * - *************************************/ - -WRITE_LINE_MEMBER( cmi_state::ptm_q219_irq ) -{ - set_interrupt(CPU_2, IRQ_RINT_LEVEL, state); -} - -IRQ_CALLBACK_MEMBER( cmi_state::cpu1_interrupt_callback ) -{ - /* 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) - { - 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 = 2; - m_m6809_bs_hack_cpu = CPU_1; - - //printf("cpu1 interrupt, will be pushing address %02x%02x\n", m_irq_address[CPU_1][0], m_irq_address[CPU_1][1]); - } - - return 0; -} - -IRQ_CALLBACK_MEMBER( cmi_state::cpu2_interrupt_callback ) -{ - /* 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) - { - int level = m_i8214[1]->a_r() ^ 0x7; - 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 = 2; - m_m6809_bs_hack_cpu = CPU_2; - - //printf("cpu1 interrupt, will be pushing address %02x%02x\n", m_irq_address[CPU_2][0], m_irq_address[CPU_2][1]); - } - return 0; -} - -void cmi_state::set_interrupt(int cpunum, int level, int state) -{ - //printf("CPU%d Int: %x State: %x\n", cpunum + 1, level, state); - - i8214_device *i8214 = ((cpunum == CPU_2) ? m_i8214[1] : (level < 8 ? m_i8214[2] : m_i8214[0])); - i8214->r_w(level & 7, state ? 0 : 1); -} - -WRITE_LINE_MEMBER( cmi_state::i8214_1_int_w ) -{ - //printf("i8214_1_int_w: %d\n", state); - if (state) - m_maincpu1->set_input_line(M6809_IRQ_LINE, ASSERT_LINE); -} - -WRITE_LINE_MEMBER( cmi_state::i8214_2_int_w ) -{ - //printf("i8214_2_int_w: %d\n", state); - if (state) - m_maincpu2->set_input_line(M6809_IRQ_LINE, ASSERT_LINE); -} - -WRITE_LINE_MEMBER( cmi_state::i8214_3_int_w ) -{ - //printf("i8214_3_int_w: %d\n", state); - m_hp_int = state; - if (state) - m_maincpu1->set_input_line(M6809_IRQ_LINE, ASSERT_LINE); -} - - -WRITE_LINE_MEMBER( cmi_state::i8214_3_enlg ) -{ - // Not needed? -// m_hp_int = state; -} - -WRITE_LINE_MEMBER( cmi_state::pia_q219_irqa ) -{ - set_interrupt(CPU_2, IRQ_TOUCHINT_LEVEL, state); -} - -WRITE_LINE_MEMBER( cmi_state::pia_q219_irqb ) -{ - set_interrupt(CPU_2, IRQ_PENINT_LEVEL, state); -} - - -/* E9 - E11 - MSM5832RS */ -/* - A0-A3 = MSM5832 A0-A3 - A4+CA1 = MSM5832 D0 - A5+CB1 = MSM5832 D1 - A6 = MSM5832 D2 - A7 = MSM5832 D3 - B0 = HOLD - B1 = READ - B2 = WRITE - CB2 = OPTO - B3 = ---- - B4-B7 = PC0-3 - - IRQA/B = /RTINT? -*/ - -READ8_MEMBER( cmi_state::q133_1_porta_r ) -{ - if (BIT(m_q133_pia[0]->b_output(), 1)) - { - return m_msm5832->data_r() << 4; - } - return 0xff; -} - -WRITE8_MEMBER( cmi_state::q133_1_porta_w ) -{ - m_msm5832_addr = data & 0xf; - m_msm5832->address_w(data & 0x0f); -} - -WRITE8_MEMBER( cmi_state::q133_1_portb_w ) -{ - m_msm5832->hold_w(BIT(data, 0)); - m_msm5832->read_w(BIT(data, 1)); - m_msm5832->write_w(BIT(data, 2)); -} - - /************************************* - * - * 6551 ACIAs - * - *************************************/ - -//static int kbd_to_cmi; -//static int cmi_to_kbd; - -WRITE_LINE_MEMBER( cmi_state::q133_acia_clock ) -{ - for (auto &acia : m_q133_acia) - acia->write_rxc(state); -} - -WRITE_LINE_MEMBER( cmi_state::msm5832_irq ) -{ -#if 0 - set_interrupt(CPU_2, IRQ_RTCINT_LEVEL, state ? ASSERT_LINE : CLEAR_LINE); -#endif -} - -WRITE_LINE_MEMBER( cmi_state::cmi07_irq ) -{ - m_cmi07cpu->set_input_line(INPUT_LINE_IRQ0, state ? ASSERT_LINE : CLEAR_LINE); -} - -void cmi_state::machine_reset() -{ - m_cpu1space = &m_maincpu1->space(AS_PROGRAM); - m_cpu2space = &m_maincpu2->space(AS_PROGRAM); - - m_qfc9_region_ptr = (uint8_t *)m_qfc9_region->base(); - - /* Set 8214 interrupt lines */ - m_i8214[0]->etlg_w(1); - m_i8214[0]->inte_w(1); - m_i8214[1]->etlg_w(1); - m_i8214[1]->inte_w(1); - m_i8214[2]->etlg_w(1); - m_i8214[2]->inte_w(1); - - m_hblank_timer->adjust(m_screen->time_until_pos(0, HBLANK_START)); - - for (int cpunum = 0; cpunum < 2; ++cpunum) - { - address_space *space = (cpunum == CPU_1 ? m_cpu1space : m_cpu2space); - - space->unmap_readwrite(0x0000, 0xffff); - - /* Select A (system) spaces */ - m_cpu_active_space[cpunum] = MAPPING_A; - - install_peripherals(cpunum); - - 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!! - m_fdc_status |= FDC_STATUS_READY; - - /* CMI-07 */ - m_cmi07_ctrl = 0; - m_cmi07cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - - m_cmi02_ptm_irq = 0; - m_m6809_bs_hack_cnt = 0; - m_m6809_bs_hack_cpu = 0; -} - -void cmi_state::machine_start() -{ - m_q133_rom = (uint8_t *)m_q133_region->base(); - - // allocate timers for the built-in two channel timer - m_map_switch_timer = timer_alloc(TIMER_MAP_SWITCH); - m_hblank_timer = timer_alloc(TIMER_HBLANK); - m_jam_timeout_timer = timer_alloc(TIMER_JAM_TIMEOUT); - - m_map_switch_timer->adjust(attotime::never); - m_hblank_timer->adjust(attotime::never); - m_jam_timeout_timer->adjust(attotime::never); - - /* Allocate 1kB memory mapping RAM */ - m_map_ram[0] = std::make_unique<uint8_t[]>(0x400); - m_map_ram[1] = std::make_unique<uint8_t[]>(0x400); - - /* Allocate 256kB for each Q256 RAM card */ - m_q256_ram[0] = std::make_unique<uint8_t[]>(0x40000); - m_q256_ram[1] = std::make_unique<uint8_t[]>(0x40000); - - /* Allocate 16kB video RAM */ - m_video_ram = std::make_unique<uint8_t[]>(0x4000); - - /* Allocate 512B shared RAM */ - m_shared_ram = std::make_unique<uint8_t[]>(0x200); - - /* Allocate 256B scratch RAM per CPU */ - m_scratch_ram[0] = std::make_unique<uint8_t[]>(0x100); - m_scratch_ram[1] = std::make_unique<uint8_t[]>(0x100); - - m_msm5832->cs_w(1); -} - -WRITE_LINE_MEMBER( cmi_state::cmi_iix_vblank ) -{ - if (state) - { - /* VSYNC */ - m_q219_pia->cb2_w(1); - m_q219_pia->cb2_w(0); - - /* LPSTB */ - m_q219_pia->cb1_w(0); - } -} - -static void cmi2x_floppies(device_slot_interface &device) -{ - device.option_add("8dsdd", FLOPPY_8_DSDD); - device.option_add("8dssd", FLOPPY_8_DSSD); -} - -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)); - config.set_perfect_quantum(m_maincpu1); - - 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)); - - M68000(config, m_midicpu, 20_MHz_XTAL / 2); - m_midicpu->set_addrmap(AS_PROGRAM, &cmi_state::midicpu_map); - - MC6809E(config, m_cmi07cpu, Q209_CPU_CLOCK); // ? - m_cmi07cpu->set_addrmap(AS_PROGRAM, &cmi_state::cmi07cpu_map); - - /* video hardware */ - SCREEN(config, m_screen, SCREEN_TYPE_RASTER, rgb_t::green()); - m_screen->set_raw(PIXEL_CLOCK, HTOTAL, HBLANK_END, HBLANK_START, VTOTAL, VBLANK_END, VBLANK_START); - m_screen->set_screen_update(FUNC(cmi_state::screen_update_cmi2x)); - m_screen->screen_vblank().set(FUNC(cmi_state::cmi_iix_vblank)); - - PALETTE(config, m_palette, palette_device::MONOCHROME); - - MSM5832(config, m_msm5832, 32.768_kHz_XTAL); - - I8214(config, m_i8214[0], 1000000); // cmi_8214_intf_1 - m_i8214[0]->int_wr_callback().set(FUNC(cmi_state::i8214_1_int_w)); - I8214(config, m_i8214[1], 1000000); // cmi_8214_intf_2 - m_i8214[1]->int_wr_callback().set(FUNC(cmi_state::i8214_2_int_w)); - I8214(config, m_i8214[2], 1000000); // cmi_8214_intf_3 - m_i8214[2]->int_wr_callback().set(FUNC(cmi_state::i8214_3_int_w)); - m_i8214[2]->enlg_wr_callback().set(FUNC(cmi_state::i8214_3_enlg)); - - PIA6821(config, m_q133_pia[0]); // pia_q133_1_config - m_q133_pia[0]->readpa_handler().set(FUNC(cmi_state::q133_1_porta_r)); - m_q133_pia[0]->writepa_handler().set(FUNC(cmi_state::q133_1_porta_w)); - m_q133_pia[0]->writepb_handler().set(FUNC(cmi_state::q133_1_portb_w)); - - PIA6821(config, m_q133_pia[1]); // pia_q133_2_config - - PTM6840(config, m_q133_ptm, 2000000); // ptm_q133_config - m_q133_ptm->set_external_clocks(1024, 1, 111); // Third is todo - - PIA6821(config, m_q219_pia); // pia_q219_config - m_q219_pia->readpb_handler().set(FUNC(cmi_state::pia_q219_b_r)); - m_q219_pia->writepa_handler().set(FUNC(cmi_state::vscroll_w)); - m_q219_pia->writepb_handler().set(FUNC(cmi_state::video_attr_w)); - m_q219_pia->irqa_handler().set(FUNC(cmi_state::pia_q219_irqa)); - m_q219_pia->irqb_handler().set(FUNC(cmi_state::pia_q219_irqb)); - - PTM6840(config, m_q219_ptm, 2000000); // ptm_q219_config - m_q219_ptm->set_external_clocks(HBLANK_FREQ.dvalue(), VBLANK_FREQ.dvalue(), 1'000'000); // TODO: does the third thing come from a crystal? - m_q219_ptm->irq_callback().set(FUNC(cmi_state::ptm_q219_irq)); - - PIA6821(config, m_cmi02_pia[0]); // pia_cmi02_1_config - m_cmi02_pia[0]->writepb_handler().set(FUNC(cmi_state::master_tune_w)); - - PIA6821(config, m_cmi02_pia[1]); // pia_cmi02_2_config - - PTM6840(config, m_cmi02_ptm, 2000000); // ptm_cmi02_config TODO - m_cmi02_ptm->o2_callback().set(FUNC(cmi_state::cmi02_ptm_o2)); - m_cmi02_ptm->irq_callback().set(FUNC(cmi_state::cmi02_ptm_irq)); - - clock_device &q133_acia_clock(CLOCK(config, "q133_acia_clock", 1.8432_MHz_XTAL / 12)); - q133_acia_clock.signal_handler().set(FUNC(cmi_state::q133_acia_clock)); - - for (auto &acia : m_q133_acia) - MOS6551(config, acia, 1.8432_MHz_XTAL).set_xtal(1.8432_MHz_XTAL); - m_q133_acia[0]->irq_handler().set("q133_acia_irq", FUNC(input_merger_device::in_w<0>)); - m_q133_acia[1]->irq_handler().set("q133_acia_irq", FUNC(input_merger_device::in_w<1>)); - m_q133_acia[2]->irq_handler().set("q133_acia_irq", FUNC(input_merger_device::in_w<2>)); - m_q133_acia[3]->irq_handler().set("q133_acia_irq", FUNC(input_merger_device::in_w<3>)); - - INPUT_MERGER_ANY_HIGH(config, "q133_acia_irq").output_handler().set(FUNC(cmi_state::q133_acia_irq)); - - m_q133_acia[0]->txd_handler().set("mkbd", FUNC(cmi_music_keyboard_device::cmi_rxd_w)); - m_q133_acia[0]->rts_handler().set("mkbd", FUNC(cmi_music_keyboard_device::cmi_cts_w)); - - // Musical keyboard - cmi_music_keyboard_device &mkbd(CMI_MUSIC_KEYBOARD(config, "mkbd")); - mkbd.cmi_txd_handler().set(m_q133_acia[0], FUNC(mos6551_device::write_rxd)); - mkbd.cmi_rts_handler().set(m_q133_acia[0], FUNC(mos6551_device::write_cts)); - mkbd.kbd_txd_handler().set("alphakeys", FUNC(cmi_alphanumeric_keyboard_device::rxd_w)); - mkbd.kbd_rts_handler().set("alphakeys", FUNC(cmi_alphanumeric_keyboard_device::cts_w)); - - // Alphanumeric keyboard - cmi_alphanumeric_keyboard_device &alphakeys(CMI_ALPHANUMERIC_KEYBOARD(config, "alphakeys")); - alphakeys.txd_handler().set("mkbd", FUNC(cmi_music_keyboard_device::kbd_rxd_w)); - alphakeys.rts_handler().set("mkbd", FUNC(cmi_music_keyboard_device::kbd_cts_w)); - - PTM6840(config, m_cmi07_ptm, 2000000); // ptm_cmi07_config TODO - m_cmi07_ptm->irq_callback().set(FUNC(cmi_state::cmi07_irq)); - - FD1791(config, m_wd1791, 16_MHz_XTAL / 8); // wd1791_interface - m_wd1791->intrq_wr_callback().set(FUNC(cmi_state::wd1791_irq)); - m_wd1791->drq_wr_callback().set(FUNC(cmi_state::wd1791_drq)); - FLOPPY_CONNECTOR(config, "wd1791:0", cmi2x_floppies, "8dsdd", floppy_image_device::default_floppy_formats); - FLOPPY_CONNECTOR(config, "wd1791:1", cmi2x_floppies, "8dsdd", floppy_image_device::default_floppy_formats); - - SPEAKER(config, "mono").front_center(); - - // Channel cards - cmi01a_device &cmi01a_0(CMI01A_CHANNEL_CARD(config, "cmi01a_0", 0)); - cmi01a_0.add_route(ALL_OUTPUTS, "mono", 0.25); - cmi01a_0.irq_callback().set(FUNC(cmi_state::channel_irq<0>)); - cmi01a_device &cmi01a_1(CMI01A_CHANNEL_CARD(config, "cmi01a_1", 0)); - cmi01a_1.add_route(ALL_OUTPUTS, "mono", 0.25); - cmi01a_1.irq_callback().set(FUNC(cmi_state::channel_irq<1>)); - cmi01a_device &cmi01a_2(CMI01A_CHANNEL_CARD(config, "cmi01a_2", 0)); - cmi01a_2.add_route(ALL_OUTPUTS, "mono", 0.25); - cmi01a_2.irq_callback().set(FUNC(cmi_state::channel_irq<2>)); - cmi01a_device &cmi01a_3(CMI01A_CHANNEL_CARD(config, "cmi01a_3", 0)); - cmi01a_3.add_route(ALL_OUTPUTS, "mono", 0.25); - cmi01a_3.irq_callback().set(FUNC(cmi_state::channel_irq<3>)); - cmi01a_device &cmi01a_4(CMI01A_CHANNEL_CARD(config, "cmi01a_4", 0)); - cmi01a_4.add_route(ALL_OUTPUTS, "mono", 0.25); - cmi01a_4.irq_callback().set(FUNC(cmi_state::channel_irq<4>)); - cmi01a_device &cmi01a_5(CMI01A_CHANNEL_CARD(config, "cmi01a_5", 0)); - cmi01a_5.add_route(ALL_OUTPUTS, "mono", 0.25); - cmi01a_5.irq_callback().set(FUNC(cmi_state::channel_irq<5>)); - cmi01a_device &cmi01a_6(CMI01A_CHANNEL_CARD(config, "cmi01a_6", 0)); - cmi01a_6.add_route(ALL_OUTPUTS, "mono", 0.25); - cmi01a_6.irq_callback().set(FUNC(cmi_state::channel_irq<6>)); - cmi01a_device &cmi01a_7(CMI01A_CHANNEL_CARD(config, "cmi01a_7", 0)); - cmi01a_7.add_route(ALL_OUTPUTS, "mono", 0.25); - cmi01a_7.irq_callback().set(FUNC(cmi_state::channel_irq<7>)); -} - -ROM_START( cmi2x ) - /* Q133 Processor control card */ - ROM_REGION( 0x3000, "q133", 0 ) - ROM_LOAD( "q9f0mrk1.bin", 0x000, 0x800, CRC(16f195cc) SHA1(fcc4be370ba60ae5a4145c36cdbdc97a7be91f8f) ) - ROM_LOAD( "f8lmrk5.bin", 0x800, 0x800, CRC(cfc7967f) SHA1(0695cc757cf6fab35414dc068dd2a3e50084685c) ) - - /* For CPU1 */ - ROM_COPY( "q133", 0x000, 0x1000, 0x800 ) - ROM_COPY( "q133", 0x800, 0x1800, 0x400 ) - - /* For CPU2 */ - ROM_COPY( "q133", 0x000, 0x2000, 0x800 ) - ROM_COPY( "q133", 0xc00, 0x2800, 0x400 ) - - /* General Interface (SMPTE/MIDI) CPU */ - ROM_REGION( 0x4000, "smptemidi", 0 ) - ROM_LOAD16_BYTE( "mon1110e.bin", 0x0000, 0x2000, CRC(476f7d5f) SHA1(9af21e0072eaa58cae42947c20dca05d35dfadd0) ) - ROM_LOAD16_BYTE( "mon1110o.bin", 0x0001, 0x2000, CRC(150c8ebe) SHA1(bbd371bebac29628f60537832d0587e83323ad01) ) - - /* QFC9 Floppy disk controller driver */ - ROM_REGION( 0x800, "qfc9", 0 ) - ROM_LOAD( "dqfc911.bin", 0x00, 0x800, CRC(5bc38db2) SHA1(bd840e19e51a336e669c40b9e18cdaf6b3c62a8a) ) - - // All of these PROM dumps have been trimmed to size from within a roughly 2x-bigger file. - // The actual sizes are known from the schematics and the starting address of the actual PROM data was obvious - // based on repeated data in some of the 256x4 PROMs, but it would be nice to get redumps, in the extremely - // unlikely event that someone finds a CMI IIx for sale. - ROM_REGION( 0x420, "proms", 0 ) - ROM_LOAD( "brom.bin", 0x000, 0x100, CRC(3f730d15) SHA1(095df6eee95b9ad6418b910fb5d2ae46913750f9) ) // Unknown use, lightgun/graphics card - ROM_LOAD( "srom.bin", 0x100, 0x100, CRC(a1b4b71b) SHA1(6ea96480af2f1e43967f209218a74fc17972ce0e) ) // Used to generate signal timing for lightpen - ROM_LOAD( "mrom.bin", 0x200, 0x100, CRC(dc26642c) SHA1(49b207ff80d1b055c3b855dc954129846c49bfe3) ) // Unknown use, master card - ROM_LOAD( "timrom.bin", 0x300, 0x100, CRC(a426e4a2) SHA1(6b7ea128c730f5afd1042820ccd55bbda683afd8) ) // Unknown use, master card - ROM_LOAD( "wrom.bin", 0x400, 0x020, CRC(68a9e17f) SHA1(c3364a37a8d19a1882d7910add1c1df9b63ee32c) ) // Unknown use, lightgun/graphics card -ROM_END - -/* TODO: Machine start? */ -void cmi_state::init_cmi2x() -{ -} - -CONS( 1983, cmi2x, 0, 0, cmi2x, cmi2x, cmi_state, init_cmi2x, "Fairlight", "CMI IIx", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) |