summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/trs80m2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/trs80m2.cpp')
-rw-r--r--src/mame/drivers/trs80m2.cpp954
1 files changed, 954 insertions, 0 deletions
diff --git a/src/mame/drivers/trs80m2.cpp b/src/mame/drivers/trs80m2.cpp
new file mode 100644
index 00000000000..7aa50ad6dfd
--- /dev/null
+++ b/src/mame/drivers/trs80m2.cpp
@@ -0,0 +1,954 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/*
+
+ Tandy Radio Shack TRS-80 Model II/12/16/16B/6000
+
+ http://home.iae.nl/users/pb0aia/cm/modelii.html
+
+*/
+
+/*
+
+ TODO:
+
+ - CP/M won't load prompt (z80dma_do_operation: invalid mode 0 when reading track 0)
+ - keyboard CPU ROM
+ - graphics board
+ - Tandy 6000 HD
+
+ chdman -createblankhd tandy6000hd.chd 306 6 34 256
+
+*/
+
+#include "includes/trs80m2.h"
+#include "softlist.h"
+
+#define KEYBOARD_TAG "keyboard"
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+READ8_MEMBER( trs80m2_state::read )
+{
+ UINT8 data = 0;
+
+ if (offset < 0x800)
+ {
+ if (m_boot_rom)
+ {
+ data = m_rom->base()[offset];
+ }
+ else
+ {
+ data = m_ram->pointer()[offset];
+ }
+ }
+ else if (offset < 0x8000)
+ {
+ data = m_ram->pointer()[offset];
+ }
+ else
+ {
+ if (m_msel && offset >= 0xf800)
+ {
+ data = m_video_ram[offset & 0x7ff];
+ }
+ else if (m_bank)
+ {
+ offs_t addr = (m_bank << 15) | (offset & 0x7fff);
+
+ if (addr < m_ram->size())
+ {
+ data = m_ram->pointer()[addr];
+ }
+ }
+ }
+
+ return data;
+}
+
+WRITE8_MEMBER( trs80m2_state::write )
+{
+ if (offset < 0x8000)
+ {
+ m_ram->pointer()[offset] = data;
+ }
+ else
+ {
+ if (m_msel && offset >= 0xf800)
+ {
+ m_video_ram[offset & 0x7ff] = data;
+ }
+ else if (m_bank)
+ {
+ offs_t addr = (m_bank << 15) | (offset & 0x7fff);
+
+ if (addr < m_ram->size())
+ {
+ m_ram->pointer()[addr] = data;
+ }
+ }
+ }
+}
+
+WRITE8_MEMBER( trs80m2_state::rom_enable_w )
+{
+ /*
+
+ bit description
+
+ 0 BOOT ROM
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+
+ */
+
+ m_boot_rom = BIT(data, 0);
+}
+
+WRITE8_MEMBER( trs80m2_state::drvslt_w )
+{
+ /*
+
+ bit signal
+
+ 0 DS1
+ 1 DS2
+ 2 DS3
+ 3 DS4
+ 4
+ 5
+ 6 SDSEL
+ 7 FM/MFM
+
+ */
+
+ // drive select
+ m_floppy = NULL;
+
+ if (!BIT(data, 0)) m_floppy = m_floppy0->get_device();
+ if (!BIT(data, 1)) m_floppy = m_floppy1->get_device();
+ if (!BIT(data, 2)) m_floppy = m_floppy2->get_device();
+ if (!BIT(data, 3)) m_floppy = m_floppy3->get_device();
+
+ m_fdc->set_floppy(m_floppy);
+
+ if (m_floppy)
+ {
+ // side select
+ m_floppy->ss_w(!BIT(data, 6));
+ }
+
+ // FM/MFM
+ m_fdc->dden_w(!BIT(data, 7));
+}
+
+READ8_MEMBER( trs80m2_state::keyboard_r )
+{
+ // clear keyboard interrupt
+ if (!m_kbirq)
+ {
+ m_kbirq = 1;
+ m_ctc->trg3(m_kbirq);
+ m_kb->busy_w(m_kbirq);
+ }
+
+ m_key_bit = 0;
+
+ return m_key_data;
+}
+
+READ8_MEMBER( trs80m2_state::rtc_r )
+{
+ // clear RTC interrupt
+ m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
+
+ return 0;
+}
+
+READ8_MEMBER( trs80m2_state::nmi_r )
+{
+ /*
+
+ bit signal description
+
+ 0
+ 1
+ 2
+ 3
+ 4 80/40 CHAR EN 80/40 character mode
+ 5 ENABLE RTC INT RTC interrupt enable
+ 6 DE display enabled
+ 7 KBIRQ keyboard interrupt
+
+ */
+
+ UINT8 data = 0;
+
+ // 80/40 character mode*/
+ data |= m_80_40_char_en << 4;
+
+ // RTC interrupt enable
+ data |= m_enable_rtc_int << 5;
+
+ // display enabled
+ data |= m_de << 6;
+
+ // keyboard interrupt
+ data |= !m_kbirq << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( trs80m2_state::nmi_w )
+{
+ /*
+
+ bit signal description
+
+ 0 memory bank select bit 0
+ 1 memory bank select bit 1
+ 2 memory bank select bit 2
+ 3 memory bank select bit 3
+ 4 80/40 CHAR EN 80/40 character mode
+ 5 ENABLE RTC INT RTC interrupt enable
+ 6 BLNKVID video display enable
+ 7 video RAM enable
+
+ */
+
+ // memory bank select
+ m_bank = data & 0x0f;
+
+ // 80/40 character mode
+ m_80_40_char_en = BIT(data, 4);
+ m_crtc->set_clock(m_80_40_char_en ? XTAL_12_48MHz/16 : XTAL_12_48MHz/8);
+
+ // RTC interrupt enable
+ m_enable_rtc_int = BIT(data, 5);
+
+ if (m_enable_rtc_int && m_rtc_int)
+ {
+ // trigger RTC interrupt
+ m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
+ }
+
+ // video display enable
+ m_blnkvid = BIT(data, 6);
+
+ // video RAM enable
+ m_msel = BIT(data, 7);
+}
+
+READ8_MEMBER( trs80m2_state::fdc_r )
+{
+ return m_fdc->gen_r(offset) ^ 0xff;
+}
+
+WRITE8_MEMBER( trs80m2_state::fdc_w )
+{
+ m_fdc->gen_w(offset, data ^ 0xff);
+}
+
+WRITE8_MEMBER( trs80m16_state::tcl_w )
+{
+ /*
+
+ bit description
+
+ 0 CONT0
+ 1 CONT1
+ 2 HALT
+ 3 RESET
+ 4 CONT4
+ 5 CONT5
+ 6 CONT6
+ 7 A14
+
+ */
+
+ m_subcpu->set_input_line(INPUT_LINE_HALT, BIT(data, 2) ? ASSERT_LINE : CLEAR_LINE);
+ m_subcpu->set_input_line(INPUT_LINE_RESET, BIT(data, 3) ? ASSERT_LINE : CLEAR_LINE);
+
+ m_pic->ir0_w(BIT(data, 4));
+ m_pic->ir1_w(BIT(data, 5));
+ m_pic->ir2_w(BIT(data, 6));
+
+ m_ual = (m_ual & 0x1fe) | BIT(data, 7);
+}
+
+WRITE8_MEMBER( trs80m16_state::ual_w )
+{
+ /*
+
+ bit description
+
+ 0 A15
+ 1 A16
+ 2 A17
+ 3 A18
+ 4 A19
+ 5 A20
+ 6 A21
+ 7 A22
+
+ */
+
+ m_ual = (data << 1) | BIT(m_ual, 0);
+}
+
+
+
+//**************************************************************************
+// ADDRESS MAPS
+//**************************************************************************
+
+//-------------------------------------------------
+// ADDRESS_MAP( z80_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( z80_mem, AS_PROGRAM, 8, trs80m2_state )
+ AM_RANGE(0x0000, 0xffff) AM_READWRITE(read, write)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( z80_io )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( z80_io, AS_IO, 8, trs80m2_state )
+ ADDRESS_MAP_GLOBAL_MASK(0xff)
+ AM_RANGE(0xe0, 0xe3) AM_DEVREADWRITE(Z80PIO_TAG, z80pio_device, read, write)
+ AM_RANGE(0xe4, 0xe7) AM_READWRITE(fdc_r, fdc_w)
+ AM_RANGE(0xef, 0xef) AM_WRITE(drvslt_w)
+ AM_RANGE(0xf0, 0xf3) AM_DEVREADWRITE(Z80CTC_TAG, z80ctc_device, read, write)
+ AM_RANGE(0xf4, 0xf7) AM_DEVREADWRITE(Z80SIO_TAG, z80sio0_device, cd_ba_r, cd_ba_w)
+ AM_RANGE(0xf8, 0xf8) AM_DEVREADWRITE(Z80DMA_TAG, z80dma_device, read, write)
+ AM_RANGE(0xf9, 0xf9) AM_WRITE(rom_enable_w)
+ AM_RANGE(0xfc, 0xfc) AM_READ(keyboard_r) AM_DEVWRITE(MC6845_TAG, mc6845_device, address_w)
+ AM_RANGE(0xfd, 0xfd) AM_DEVREADWRITE(MC6845_TAG, mc6845_device, register_r, register_w)
+ AM_RANGE(0xfe, 0xfe) AM_READ(rtc_r)
+ AM_RANGE(0xff, 0xff) AM_READWRITE(nmi_r, nmi_w)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( m16_z80_io )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( m16_z80_io, AS_IO, 8, trs80m16_state )
+ AM_IMPORT_FROM(z80_io)
+ AM_RANGE(0xde, 0xde) AM_WRITE(tcl_w)
+ AM_RANGE(0xdf, 0xdf) AM_WRITE(ual_w)
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( m68000_mem )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( m68000_mem, AS_PROGRAM, 16, trs80m2_state )
+// AM_RANGE(0x7800d0, 0x7800d1) PIC
+// AM_RANGE(0x7800d2, 0x7800d3) limit/offset 2
+// AM_RANGE(0x7800d4, 0x7800d5) limit/offset 1
+// AM_RANGE(0x7800d6, 0x7800d7) Z80 IRQ
+ADDRESS_MAP_END
+
+
+
+//**************************************************************************
+// INPUT PORTS
+//**************************************************************************
+
+//-------------------------------------------------
+// INPUT_PORTS( trs80m2 )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( trs80m2 )
+INPUT_PORTS_END
+
+
+
+//**************************************************************************
+// VIDEO
+//**************************************************************************
+
+MC6845_UPDATE_ROW( trs80m2_state::crtc_update_row )
+{
+ const pen_t *pen = m_palette->pens();
+
+ int x = 0;
+
+ for (int column = 0; column < x_count; column++)
+ {
+ UINT8 code = m_video_ram[(ma + column) & 0x7ff];
+ offs_t address = ((code & 0x7f) << 4) | (ra & 0x0f);
+ UINT8 data = m_char_rom->base()[address];
+
+ int dcursor = (column == cursor_x);
+ int drevid = BIT(code, 7);
+
+ for (int bit = 0; bit < 8; bit++)
+ {
+ int dout = BIT(data, 7);
+ int color = (dcursor ^ drevid ^ dout) && de;
+
+ bitmap.pix32(vbp + y, hbp + x++) = pen[color];
+
+ data <<= 1;
+ }
+ }
+}
+
+WRITE_LINE_MEMBER( trs80m2_state::de_w )
+{
+ m_de = state;
+}
+
+WRITE_LINE_MEMBER( trs80m2_state::vsync_w )
+{
+ if (state)
+ {
+ m_rtc_int = !m_rtc_int;
+
+ if (m_enable_rtc_int && m_rtc_int)
+ {
+ // trigger RTC interrupt
+ m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
+ }
+ }
+}
+
+void trs80m2_state::video_start()
+{
+ // allocate memory
+ m_video_ram.allocate(0x800);
+}
+
+UINT32 trs80m2_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ if (m_blnkvid)
+ {
+ bitmap.fill(rgb_t::black, cliprect);
+ }
+ else
+ {
+ m_crtc->screen_update(screen, bitmap, cliprect);
+ }
+
+ return 0;
+}
+
+
+
+//**************************************************************************
+// DEVICE CONFIGURATION
+//**************************************************************************
+
+//-------------------------------------------------
+// TRS80M2_KEYBOARD_INTERFACE( kb_intf )
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( trs80m2_state::kb_clock_w )
+{
+ int kbdata = m_kb->data_r();
+
+ if (m_key_bit == 8)
+ {
+ if (!m_kbdata && kbdata)
+ {
+ // trigger keyboard interrupt
+ m_kbirq = 0;
+ m_ctc->trg3(m_kbirq);
+ m_kb->busy_w(m_kbirq);
+ }
+ }
+ else
+ {
+ if (!m_kbclk && state)
+ {
+ // shift in keyboard data bit
+ m_key_data <<= 1;
+ m_key_data |= kbdata;
+ m_key_bit++;
+ }
+ }
+
+ m_kbdata = kbdata;
+ m_kbclk = state;
+}
+
+WRITE8_MEMBER( trs80m2_state::kbd_w )
+{
+ // latch key data
+ m_key_data = data;
+
+ // trigger keyboard interrupt
+ m_kbirq = 0;
+ m_ctc->trg3(m_kbirq);
+}
+
+//-------------------------------------------------
+// Z80DMA
+//-------------------------------------------------
+
+READ8_MEMBER(trs80m2_state::io_read_byte)
+{
+ address_space& prog_space = m_maincpu->space(AS_IO);
+ return prog_space.read_byte(offset);
+}
+
+WRITE8_MEMBER(trs80m2_state::io_write_byte)
+{
+ address_space& prog_space = m_maincpu->space(AS_IO);
+ return prog_space.write_byte(offset, data);
+}
+
+//-------------------------------------------------
+// Z80PIO
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( trs80m2_state::write_centronics_busy )
+{
+ m_centronics_busy = state;
+}
+
+WRITE_LINE_MEMBER( trs80m2_state::write_centronics_fault )
+{
+ m_centronics_fault = state;
+}
+
+WRITE_LINE_MEMBER( trs80m2_state::write_centronics_perror )
+{
+ m_centronics_perror = state;
+}
+
+READ8_MEMBER( trs80m2_state::pio_pa_r )
+{
+ /*
+
+ bit signal description
+
+ 0 INTRQ FDC INT request
+ 1 _TWOSID 2-sided diskette
+ 2 _DSKCHG disk change
+ 3 PRIME prime
+ 4 FAULT printer fault
+ 5 PSEL printer select
+ 6 PE paper empty
+ 7 BUSY printer busy
+
+ */
+
+ UINT8 data = 0;
+
+ // floppy interrupt
+ data |= (m_fdc->intrq_r() ? 0x01 : 0x00);
+
+ // 2-sided diskette
+ data |= (m_floppy ? m_floppy->twosid_r() : 1) << 1;
+
+ // disk change
+ data |= (m_floppy ? m_floppy->dskchg_r() : 1) << 2;
+
+ // printer fault
+ data |= m_centronics_fault << 4;
+
+ // paper empty
+ data |= m_centronics_perror << 6;
+
+ // printer busy
+ data |= m_centronics_busy << 7;
+
+ return data;
+}
+
+WRITE8_MEMBER( trs80m2_state::pio_pa_w )
+{
+ /*
+
+ bit signal description
+
+ 0 INTRQ FDC INT request
+ 1 _TWOSID 2-sided diskette
+ 2 _DSKCHG disk change
+ 3 PRIME prime
+ 4 FAULT printer fault
+ 5 PSEL printer select
+ 6 PE paper empty
+ 7 BUSY printer busy
+
+ */
+
+ // prime
+ m_centronics->write_init(BIT(data, 3));
+}
+
+WRITE_LINE_MEMBER( trs80m2_state::strobe_w )
+{
+ m_centronics->write_strobe(!state);
+}
+
+//-------------------------------------------------
+// Z80CTC
+//-------------------------------------------------
+
+TIMER_DEVICE_CALLBACK_MEMBER(trs80m2_state::ctc_tick)
+{
+ m_ctc->trg0(1);
+ m_ctc->trg0(0);
+
+ m_ctc->trg1(1);
+ m_ctc->trg1(0);
+
+ m_ctc->trg2(1);
+ m_ctc->trg2(0);
+}
+
+static SLOT_INTERFACE_START( trs80m2_floppies )
+ SLOT_INTERFACE( "8ssdd", FLOPPY_8_SSDD ) // Shugart SA-800
+ SLOT_INTERFACE( "8dsdd", FLOPPY_8_DSDD ) // Shugart SA-850
+SLOT_INTERFACE_END
+
+
+//-------------------------------------------------
+// z80_daisy_config trs80m2_daisy_chain
+//-------------------------------------------------
+
+static const z80_daisy_config trs80m2_daisy_chain[] =
+{
+ { Z80CTC_TAG },
+ { Z80SIO_TAG },
+ { Z80DMA_TAG },
+ { Z80PIO_TAG },
+ { NULL }
+};
+
+//**************************************************************************
+// MACHINE INITIALIZATION
+//**************************************************************************
+
+//-------------------------------------------------
+// machine_start
+//-------------------------------------------------
+
+void trs80m2_state::machine_start()
+{
+ // register for state saving
+ save_item(NAME(m_boot_rom));
+ save_item(NAME(m_bank));
+ save_item(NAME(m_msel));
+ save_item(NAME(m_key_latch));
+ save_item(NAME(m_key_data));
+ save_item(NAME(m_key_bit));
+ save_item(NAME(m_kbclk));
+ save_item(NAME(m_kbdata));
+ save_item(NAME(m_kbirq));
+ save_item(NAME(m_blnkvid));
+ save_item(NAME(m_80_40_char_en));
+ save_item(NAME(m_de));
+ save_item(NAME(m_rtc_int));
+ save_item(NAME(m_enable_rtc_int));
+}
+
+void trs80m16_state::machine_start()
+{
+ trs80m2_state::machine_start();
+
+ // register for state saving
+ save_item(NAME(m_ual));
+ save_item(NAME(m_limit));
+ save_item(NAME(m_offset));
+}
+
+
+//-------------------------------------------------
+// machine_reset
+//-------------------------------------------------
+
+void trs80m2_state::machine_reset()
+{
+ // clear keyboard interrupt
+ m_kbirq = 1;
+ m_ctc->trg3(m_kbirq);
+ m_kb->busy_w(m_kbirq);
+
+ // enable boot ROM
+ m_boot_rom = 1;
+
+ // disable video RAM
+ m_msel = 0;
+}
+
+
+
+//**************************************************************************
+// MACHINE DRIVERS
+//**************************************************************************
+
+//-------------------------------------------------
+// MACHINE_CONFIG( trs80m2 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_START( trs80m2, trs80m2_state )
+ // basic machine hardware
+ MCFG_CPU_ADD(Z80_TAG, Z80, XTAL_8MHz/2)
+ MCFG_CPU_CONFIG(trs80m2_daisy_chain)
+ MCFG_CPU_PROGRAM_MAP(z80_mem)
+ MCFG_CPU_IO_MAP(z80_io)
+
+ // video hardware
+ MCFG_SCREEN_ADD(SCREEN_TAG, RASTER)
+ MCFG_SCREEN_REFRESH_RATE(60)
+ MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
+ MCFG_SCREEN_UPDATE_DRIVER(trs80m2_state, screen_update)
+ MCFG_SCREEN_SIZE(640, 480)
+ MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 479)
+
+ MCFG_PALETTE_ADD_MONOCHROME_GREEN("palette")
+
+ MCFG_MC6845_ADD(MC6845_TAG, MC6845, SCREEN_TAG, XTAL_12_48MHz/8)
+ MCFG_MC6845_SHOW_BORDER_AREA(true)
+ MCFG_MC6845_CHAR_WIDTH(8)
+ MCFG_MC6845_UPDATE_ROW_CB(trs80m2_state, crtc_update_row)
+ MCFG_MC6845_OUT_DE_CB(WRITELINE(trs80m2_state, de_w))
+ MCFG_MC6845_OUT_VSYNC_CB(WRITELINE(trs80m2_state, vsync_w))
+
+ // devices
+ MCFG_FD1791_ADD(FD1791_TAG, XTAL_8MHz/4)
+ MCFG_WD_FDC_INTRQ_CALLBACK(DEVWRITE8(Z80PIO_TAG, z80pio_device, pa_w))
+ MCFG_WD_FDC_DRQ_CALLBACK(DEVWRITELINE(Z80DMA_TAG, z80dma_device, rdy_w))
+ MCFG_FLOPPY_DRIVE_ADD(FD1791_TAG":0", trs80m2_floppies, "8dsdd", floppy_image_device::default_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(FD1791_TAG":1", trs80m2_floppies, NULL, floppy_image_device::default_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(FD1791_TAG":2", trs80m2_floppies, NULL, floppy_image_device::default_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(FD1791_TAG":3", trs80m2_floppies, NULL, floppy_image_device::default_floppy_formats)
+
+ MCFG_DEVICE_ADD(Z80CTC_TAG, Z80CTC, XTAL_8MHz/2)
+ MCFG_Z80CTC_INTR_CB(INPUTLINE(Z80_TAG, INPUT_LINE_IRQ0))
+ MCFG_Z80CTC_ZC0_CB(DEVWRITELINE(Z80SIO_TAG, z80dart_device, rxca_w))
+ MCFG_Z80CTC_ZC1_CB(DEVWRITELINE(Z80SIO_TAG, z80dart_device, txca_w))
+ MCFG_Z80CTC_ZC2_CB(DEVWRITELINE(Z80SIO_TAG, z80dart_device, rxtxcb_w))
+
+ MCFG_TIMER_DRIVER_ADD_PERIODIC("ctc", trs80m2_state, ctc_tick, attotime::from_hz(XTAL_8MHz/2/2))
+
+ MCFG_DEVICE_ADD(Z80DMA_TAG, Z80DMA, XTAL_8MHz/2)
+ MCFG_Z80DMA_OUT_BUSREQ_CB(INPUTLINE(Z80_TAG, INPUT_LINE_HALT))
+ MCFG_Z80DMA_OUT_INT_CB(INPUTLINE(Z80_TAG, INPUT_LINE_IRQ0))
+ MCFG_Z80DMA_IN_MREQ_CB(READ8(trs80m2_state, read))
+ MCFG_Z80DMA_OUT_MREQ_CB(WRITE8(trs80m2_state, write))
+ MCFG_Z80DMA_IN_IORQ_CB(READ8(trs80m2_state, io_read_byte))
+ MCFG_Z80DMA_OUT_IORQ_CB(WRITE8(trs80m2_state, io_write_byte))
+
+ MCFG_DEVICE_ADD(Z80PIO_TAG, Z80PIO, XTAL_8MHz/2)
+ MCFG_Z80PIO_OUT_INT_CB(INPUTLINE(Z80_TAG, INPUT_LINE_IRQ0))
+ MCFG_Z80PIO_IN_PA_CB(READ8(trs80m2_state, pio_pa_r))
+ MCFG_Z80PIO_OUT_PA_CB(WRITE8(trs80m2_state, pio_pa_w))
+ MCFG_Z80PIO_OUT_PB_CB(DEVWRITE8("cent_data_out", output_latch_device, write))
+ MCFG_Z80PIO_OUT_BRDY_CB(WRITELINE(trs80m2_state, strobe_w))
+
+ MCFG_Z80SIO0_ADD(Z80SIO_TAG, XTAL_8MHz/2, 0, 0, 0, 0)
+ MCFG_Z80DART_OUT_INT_CB(INPUTLINE(Z80_TAG, INPUT_LINE_IRQ0))
+
+ MCFG_CENTRONICS_ADD(CENTRONICS_TAG, centronics_devices, "printer")
+ MCFG_CENTRONICS_ACK_HANDLER(DEVWRITELINE(Z80PIO_TAG, z80pio_device, strobe_b))
+ MCFG_CENTRONICS_BUSY_HANDLER(WRITELINE(trs80m2_state, write_centronics_busy))
+ MCFG_CENTRONICS_FAULT_HANDLER(WRITELINE(trs80m2_state, write_centronics_fault))
+ MCFG_CENTRONICS_PERROR_HANDLER(WRITELINE(trs80m2_state, write_centronics_perror))
+ MCFG_CENTRONICS_OUTPUT_LATCH_ADD("cent_data_out", CENTRONICS_TAG)
+
+ MCFG_DEVICE_ADD(TRS80M2_KEYBOARD_TAG, TRS80M2_KEYBOARD, 0)
+ MCFG_TRS80M2_KEYBOARD_CLOCK_CALLBACK(WRITELINE(trs80m2_state, kb_clock_w))
+ MCFG_DEVICE_ADD(KEYBOARD_TAG, GENERIC_KEYBOARD, 0)
+ MCFG_GENERIC_KEYBOARD_CB(WRITE8(trs80m2_state, kbd_w))
+
+ // internal RAM
+ MCFG_RAM_ADD(RAM_TAG)
+ MCFG_RAM_DEFAULT_SIZE("64K")
+ MCFG_RAM_EXTRA_OPTIONS("32K,96K,128K,160K,192K,224K,256K,288K,320K,352K,384K,416K,448K,480K,512K")
+
+ // software list
+ MCFG_SOFTWARE_LIST_ADD("flop_list", "trs80m2")
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// MACHINE_CONFIG( trs80m16 )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_START( trs80m16, trs80m16_state )
+ // basic machine hardware
+ MCFG_CPU_ADD(Z80_TAG, Z80, XTAL_8MHz/2)
+ MCFG_CPU_CONFIG(trs80m2_daisy_chain)
+ MCFG_CPU_PROGRAM_MAP(z80_mem)
+ MCFG_CPU_IO_MAP(m16_z80_io)
+ MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE(AM9519A_TAG, pic8259_device, inta_cb)
+
+ MCFG_CPU_ADD(M68000_TAG, M68000, XTAL_24MHz/4)
+ MCFG_CPU_PROGRAM_MAP(m68000_mem)
+ MCFG_DEVICE_DISABLE()
+
+ // video hardware
+ MCFG_SCREEN_ADD(SCREEN_TAG, RASTER)
+ MCFG_SCREEN_REFRESH_RATE(60)
+ MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
+ MCFG_SCREEN_UPDATE_DRIVER(trs80m2_state, screen_update)
+ MCFG_SCREEN_SIZE(640, 480)
+ MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 479)
+
+ MCFG_PALETTE_ADD_MONOCHROME_GREEN("palette")
+
+ MCFG_MC6845_ADD(MC6845_TAG, MC6845, SCREEN_TAG, XTAL_12_48MHz/8)
+ MCFG_MC6845_SHOW_BORDER_AREA(true)
+ MCFG_MC6845_CHAR_WIDTH(8)
+ MCFG_MC6845_UPDATE_ROW_CB(trs80m2_state, crtc_update_row)
+ MCFG_MC6845_OUT_DE_CB(WRITELINE(trs80m2_state, de_w))
+ MCFG_MC6845_OUT_VSYNC_CB(WRITELINE(trs80m2_state, vsync_w))
+
+ // devices
+ MCFG_FD1791_ADD(FD1791_TAG, XTAL_8MHz/4)
+ MCFG_WD_FDC_INTRQ_CALLBACK(DEVWRITE8(Z80PIO_TAG, z80pio_device, pa_w))
+ MCFG_WD_FDC_DRQ_CALLBACK(DEVWRITELINE(Z80DMA_TAG, z80dma_device, rdy_w))
+ MCFG_FLOPPY_DRIVE_ADD(FD1791_TAG":0", trs80m2_floppies, "8dsdd", floppy_image_device::default_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(FD1791_TAG":1", trs80m2_floppies, NULL, floppy_image_device::default_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(FD1791_TAG":2", trs80m2_floppies, NULL, floppy_image_device::default_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(FD1791_TAG":3", trs80m2_floppies, NULL, floppy_image_device::default_floppy_formats)
+
+ MCFG_DEVICE_ADD(Z80CTC_TAG, Z80CTC, XTAL_8MHz/2)
+ MCFG_Z80CTC_INTR_CB(INPUTLINE(Z80_TAG, INPUT_LINE_IRQ0))
+ MCFG_Z80CTC_ZC0_CB(DEVWRITELINE(Z80SIO_TAG, z80dart_device, rxca_w))
+ MCFG_Z80CTC_ZC1_CB(DEVWRITELINE(Z80SIO_TAG, z80dart_device, txca_w))
+ MCFG_Z80CTC_ZC2_CB(DEVWRITELINE(Z80SIO_TAG, z80dart_device, rxtxcb_w))
+
+ MCFG_TIMER_DRIVER_ADD_PERIODIC("ctc", trs80m2_state, ctc_tick, attotime::from_hz(XTAL_8MHz/2/2))
+
+ MCFG_DEVICE_ADD(Z80DMA_TAG, Z80DMA, XTAL_8MHz/2)
+ MCFG_Z80DMA_OUT_BUSREQ_CB(INPUTLINE(Z80_TAG, INPUT_LINE_HALT))
+ MCFG_Z80DMA_OUT_INT_CB(INPUTLINE(Z80_TAG, INPUT_LINE_IRQ0))
+ MCFG_Z80DMA_IN_MREQ_CB(READ8(trs80m2_state, read))
+ MCFG_Z80DMA_OUT_MREQ_CB(WRITE8(trs80m2_state, write))
+ MCFG_Z80DMA_IN_IORQ_CB(READ8(trs80m2_state, io_read_byte))
+ MCFG_Z80DMA_OUT_IORQ_CB(WRITE8(trs80m2_state, io_write_byte))
+
+ MCFG_DEVICE_ADD(Z80PIO_TAG, Z80PIO, XTAL_8MHz/2)
+ MCFG_Z80PIO_OUT_INT_CB(INPUTLINE(Z80_TAG, INPUT_LINE_IRQ0))
+ MCFG_Z80PIO_IN_PA_CB(READ8(trs80m2_state, pio_pa_r))
+ MCFG_Z80PIO_OUT_PA_CB(WRITE8(trs80m2_state, pio_pa_w))
+ MCFG_Z80PIO_OUT_PB_CB(DEVWRITE8("cent_data_out", output_latch_device, write))
+ MCFG_Z80PIO_OUT_BRDY_CB(WRITELINE(trs80m2_state, strobe_w))
+
+ MCFG_Z80SIO0_ADD(Z80SIO_TAG, XTAL_8MHz/2, 0, 0, 0, 0)
+ MCFG_Z80DART_OUT_INT_CB(INPUTLINE(Z80_TAG, INPUT_LINE_IRQ0))
+
+ MCFG_PIC8259_ADD(AM9519A_TAG, INPUTLINE(M68000_TAG, M68K_IRQ_5), VCC, NULL )
+
+ MCFG_CENTRONICS_ADD(CENTRONICS_TAG, centronics_devices, "printer")
+ MCFG_CENTRONICS_ACK_HANDLER(DEVWRITELINE(Z80PIO_TAG, z80pio_device, strobe_b))
+ MCFG_CENTRONICS_BUSY_HANDLER(WRITELINE(trs80m2_state, write_centronics_busy))
+ MCFG_CENTRONICS_FAULT_HANDLER(WRITELINE(trs80m2_state, write_centronics_fault))
+ MCFG_CENTRONICS_PERROR_HANDLER(WRITELINE(trs80m2_state, write_centronics_perror))
+ MCFG_CENTRONICS_OUTPUT_LATCH_ADD("cent_data_out", CENTRONICS_TAG)
+
+ MCFG_DEVICE_ADD(TRS80M2_KEYBOARD_TAG, TRS80M2_KEYBOARD, 0)
+ MCFG_TRS80M2_KEYBOARD_CLOCK_CALLBACK(WRITELINE(trs80m2_state, kb_clock_w))
+ MCFG_DEVICE_ADD(KEYBOARD_TAG, GENERIC_KEYBOARD, 0)
+ MCFG_GENERIC_KEYBOARD_CB(WRITE8(trs80m2_state, kbd_w))
+
+ // internal RAM
+ MCFG_RAM_ADD(RAM_TAG)
+ MCFG_RAM_DEFAULT_SIZE("256K")
+ MCFG_RAM_EXTRA_OPTIONS("512K,768K,1M")
+
+ // software list
+ MCFG_SOFTWARE_LIST_ADD("flop_list", "trs80m2")
+MACHINE_CONFIG_END
+
+
+
+//**************************************************************************
+// ROMS
+//**************************************************************************
+
+/*
+
+ TRS-80 Model II/16 Z80 CPU Board ROM
+
+ It would seem that every processor board I find has a different ROM on it! It seems that the early ROMs
+ don't boot directly from a hard drive. But there seems to be many versions of ROMs. I've placed them in
+ order of serial number in the list below. There also appears to be at least two board revisions, "C" and "D".
+
+ cpu_c8ff.bin/hex:
+ Mask Programmable PROM, Equivilant to Intel 2716 EPROM, with checksum C8FF came from a cpu board with
+ serial number 120353 out of a Model II with serial number 2002102 and catalog number 26-6002. The board
+ was labeled, "Revision C". This appears to be an early ROM and according to a very helpful fellow
+ collector, Aaron in Australia, doesn't allow boot directly from a hard disk.
+
+ cpu_9733.bin/hex:
+ An actual SGS-Ates (Now STMicroelectronics) 2716 EPROM, with checksum 9733 came from a cpu board with
+ serial number 161993 out of a pile of random cards that I have. I don't know what machine it originated
+ from. The board was labeled, "Revision C". This appears to be a later ROM in that it is able to boot
+ directly from an 8MB hard disk. The EPROM had a windows sticker on it labeled, "U54".
+
+ cpu_2119.bin/hex:
+ An actual Texas Instruments TMS2516 EPROM, with checksum 2119 came from a cpu board with serial number
+ 178892 out of a Model 16 with serial number 64014509 and catalog number 26-4002. The board was labeled,
+ "Revision D". This appears to be a later ROM and does appear to allow boot directly from an 8MB hard disk.
+
+ cpu_2bff.bin/hex:
+ Mask Programmable PROM, Equivilant to Intel 2716 EPROM, with checksum 2BFF came from a cpu board with
+ serial number 187173 our of a pile of random cards that I have. I don't know what machine it originated
+ from. The board was labeled, "Revision D". This appears to be a later ROM in that it is able to boot
+ directly from an 8MB hard disk.
+
+*/
+
+//-------------------------------------------------
+// ROM( trs80m2 )
+//-------------------------------------------------
+
+ROM_START( trs80m2 )
+ ROM_REGION( 0x800, Z80_TAG, 0 )
+ ROM_DEFAULT_BIOS( "9733" )
+ ROM_SYSTEM_BIOS( 0, "c8ff", "Version 1" )
+ ROMX_LOAD( "8043216.u11", 0x0000, 0x0800, CRC(7017a373) SHA1(1c7127fcc99fc351a40d3a3199ba478e783c452e), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 1, "2bff", "Version 2 (1981-07-29)" )
+ ROMX_LOAD( "8047316.u11", 0x0000, 0x0800, CRC(c6c71d8b) SHA1(7107e2cbbe769851a4460680c2deff8e76a101b5), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS( 2, "2119", "Version 3 (1982-05-07)" )
+ ROMX_LOAD( "cpu_2119.u11", 0x0000, 0x0800, CRC(7a663049) SHA1(f308439ce266df717bfe79adcdad6024b4faa141), ROM_BIOS(3) )
+ ROM_SYSTEM_BIOS( 3, "1bbe", "Version 3 (1982-05-07, Alt)" )
+ ROMX_LOAD( "cpu_11be.u11", 0x0000, 0x0800, CRC(8edceea7) SHA1(3d797acedd8a71a82c695129ca764f85aa9022b2), ROM_BIOS(4) )
+ ROM_SYSTEM_BIOS( 4, "fc86", "Version 4 (1982-11-18)" )
+ ROMX_LOAD( "cpu_fc86.u11", 0x0000, 0x0800, NO_DUMP, ROM_BIOS(5) )
+ ROM_SYSTEM_BIOS( 5, "9733", "Version 5 (1983-07-29)" )
+ ROMX_LOAD( "u54.u11", 0x0000, 0x0800, CRC(823924b1) SHA1(aee0625bcbd8620b28ab705e15ad9bea804c8476), ROM_BIOS(6) )
+
+ ROM_REGION( 0x800, MC6845_TAG, 0 )
+ ROM_LOAD( "8043316.u9", 0x0000, 0x0800, CRC(04425b03) SHA1(32a29dc202b7fcf21838289cc3bffc51ef943dab) )
+ROM_END
+
+
+//-------------------------------------------------
+// ROM( trs80m16 )
+//-------------------------------------------------
+
+#define rom_trs80m16 rom_trs80m2
+
+
+
+//**************************************************************************
+// SYSTEM DRIVERS
+//**************************************************************************
+
+// YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS
+COMP( 1979, trs80m2, 0, 0, trs80m2, trs80m2, driver_device, 0, "Tandy Radio Shack", "TRS-80 Model II", MACHINE_NO_SOUND_HW | MACHINE_IMPERFECT_KEYBOARD )
+COMP( 1982, trs80m16, trs80m2, 0, trs80m16, trs80m2, driver_device, 0, "Tandy Radio Shack", "TRS-80 Model 16", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_IMPERFECT_KEYBOARD )
+//COMP( 1983, trs80m12, trs80m2, 0, trs80m16, trs80m2, driver_device, 0, "Tandy Radio Shack", "TRS-80 Model 12", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_IMPERFECT_KEYBOARD )
+//COMP( 1984, trs80m16b,trs80m2, 0, trs80m16, trs80m2, driver_device, 0, "Tandy Radio Shack", "TRS-80 Model 16B", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_IMPERFECT_KEYBOARD )
+//COMP( 1985, tandy6k, trs80m2, 0, tandy6k, trs80m2, driver_device, 0, "Tandy Radio Shack", "Tandy 6000 HD", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_IMPERFECT_KEYBOARD )