// license: GPL-2.0+ // copyright-holders: Dirk Best /*************************************************************************** Kontron KDT6 This is the base board for various machines, it needs to be combined with an I/O board and a bus board. This gives us - KDT6 + 9xx/IOC + 9xx/BUS: PSI908/PSI9C - KDT6 + 98/IOC + 98/BUS: PSI98 ***************************************************************************/ #include "emu.h" #include "cpu/z80/z80.h" #include "machine/timer.h" #include "machine/z80ctc.h" #include "machine/z80dma.h" #include "machine/z80pio.h" #include "machine/z80sio.h" #include "machine/upd765.h" #include "machine/upd1990a.h" #include "machine/clock.h" #include "video/mc6845.h" #include "sound/beep.h" #include "sound/spkrdev.h" #include "bus/centronics/ctronics.h" #include "bus/psi_kbd/psi_kbd.h" #include "bus/rs232/rs232.h" #include "screen.h" #include "speaker.h" #include "softlist.h" #include "kdt6.lh" //************************************************************************** // TYPE DEFINITIONS //************************************************************************** class kdt6_state : public driver_device { public: kdt6_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_cpu(*this, "maincpu"), m_dma(*this, "dma"), m_sio(*this, "sio"), m_crtc(*this, "crtc"), m_page_r(*this, "page%x_r", 0), m_page_w(*this, "page%x_w", 0), m_boot(*this, "boot"), m_palette(*this, "palette"), m_gfx(*this, "gfx"), m_rtc(*this, "rtc"), m_fdc(*this, "fdc"), m_floppy0(*this, "fdc:0"), m_floppy1(*this, "fdc:1"), m_beeper(*this, "beeper"), m_beep_timer(*this, "beep_timer"), m_centronics(*this, "centronics"), m_dip_s2(*this, "S2"), m_keyboard(*this, "kbd"), m_rs232b(*this, "rs232b"), m_sasi_dma(false), m_dma_map(0), m_status0(0), m_status1(0), m_status2(0), m_video_address(0) { } DECLARE_WRITE_LINE_MEMBER(busreq_w); DECLARE_READ8_MEMBER(memory_r); DECLARE_WRITE8_MEMBER(memory_w); DECLARE_READ8_MEMBER(io_r); DECLARE_WRITE8_MEMBER(io_w); DECLARE_READ8_MEMBER(page0_r); DECLARE_READ8_MEMBER(page1_r); DECLARE_READ8_MEMBER(mapper_r); DECLARE_WRITE8_MEMBER(mapper_w); DECLARE_READ8_MEMBER(sasi_ctrl_r); DECLARE_WRITE8_MEMBER(sasi_ctrl_w); DECLARE_WRITE8_MEMBER(dma_map_w); DECLARE_WRITE8_MEMBER(status0_w); DECLARE_READ8_MEMBER(status1_r); DECLARE_WRITE8_MEMBER(status1_w); DECLARE_WRITE8_MEMBER(status2_w); DECLARE_READ8_MEMBER(video_data_r); DECLARE_WRITE8_MEMBER(video_data_w); DECLARE_WRITE8_MEMBER(video_data_inc_w); DECLARE_WRITE8_MEMBER(video_data_dec_w); DECLARE_WRITE8_MEMBER(video_address_latch_high_w); DECLARE_WRITE8_MEMBER(video_address_latch_low_w); TIMER_DEVICE_CALLBACK_MEMBER(beeper_off); DECLARE_WRITE8_MEMBER(fdc_tc_w); DECLARE_WRITE_LINE_MEMBER(fdc_drq_w); void drive0_led_cb(floppy_image_device *floppy, int state); void drive1_led_cb(floppy_image_device *floppy, int state); MC6845_UPDATE_ROW(crtc_update_row); uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); DECLARE_WRITE8_MEMBER(pio_porta_w); DECLARE_WRITE_LINE_MEMBER(keyboard_rx_w); DECLARE_WRITE_LINE_MEMBER(rs232b_rx_w); DECLARE_WRITE_LINE_MEMBER(siob_tx_w); void psi98(machine_config &config); void psi98_io(address_map &map); void psi98_mem(address_map &map); protected: virtual void machine_start() override; virtual void machine_reset() override; private: required_device m_cpu; required_device m_dma; required_device m_sio; required_device m_crtc; required_memory_bank_array<16> m_page_r, m_page_w; required_memory_region m_boot; required_device m_palette; required_region_ptr m_gfx; required_device m_rtc; required_device m_fdc; required_device m_floppy0; required_device m_floppy1; required_device m_beeper; required_device m_beep_timer; required_device m_centronics; required_ioport m_dip_s2; required_device m_keyboard; required_device m_rs232b; std::unique_ptr m_ram; std::unique_ptr m_vram; // 10-bit std::unique_ptr m_dummy_r, m_dummy_w; bool m_sasi_dma; uint8_t m_dma_map; uint8_t m_status0; uint8_t m_status1; uint8_t m_status2; uint16_t m_mapper[16]; // 12-bit uint16_t m_video_address; }; //************************************************************************** // ADDRESS MAPS //************************************************************************** void kdt6_state::psi98_mem(address_map &map) { map(0x0000, 0x0fff).bankr("page0_r").bankw("page0_w"); map(0x1000, 0x1fff).bankr("page1_r").bankw("page1_w"); map(0x2000, 0x2fff).bankr("page2_r").bankw("page2_w"); map(0x3000, 0x3fff).bankr("page3_r").bankw("page3_w"); map(0x4000, 0x4fff).bankr("page4_r").bankw("page4_w"); map(0x5000, 0x5fff).bankr("page5_r").bankw("page5_w"); map(0x6000, 0x6fff).bankr("page6_r").bankw("page6_w"); map(0x7000, 0x7fff).bankr("page7_r").bankw("page7_w"); map(0x8000, 0x8fff).bankr("page8_r").bankw("page8_w"); map(0x9000, 0x9fff).bankr("page9_r").bankw("page9_w"); map(0xa000, 0xafff).bankr("pagea_r").bankw("pagea_w"); map(0xb000, 0xbfff).bankr("pageb_r").bankw("pageb_w"); map(0xc000, 0xcfff).bankr("pagec_r").bankw("pagec_w"); map(0xd000, 0xdfff).bankr("paged_r").bankw("paged_w"); map(0xe000, 0xefff).bankr("pagee_r").bankw("pagee_w"); map(0xf000, 0xffff).bankr("pagef_r").bankw("pagef_w"); } void kdt6_state::psi98_io(address_map &map) { map.global_mask(0xff); map(0x00, 0x00).rw(m_dma, FUNC(z80dma_device::read), FUNC(z80dma_device::write)); map(0x04, 0x07).rw(m_sio, FUNC(z80sio_device::cd_ba_r), FUNC(z80sio_device::cd_ba_w)); map(0x08, 0x0b).rw("ctc1", FUNC(z80ctc_device::read), FUNC(z80ctc_device::write)); map(0x0c, 0x0f).rw("pio", FUNC(z80pio_device::read), FUNC(z80pio_device::write)); map(0x10, 0x13).rw("ctc2", FUNC(z80ctc_device::read), FUNC(z80ctc_device::write)); map(0x14, 0x14).r(m_fdc, FUNC(upd765a_device::msr_r)); map(0x15, 0x15).rw(m_fdc, FUNC(upd765a_device::fifo_r), FUNC(upd765a_device::fifo_w)); map(0x18, 0x18).w(m_crtc, FUNC(mc6845_device::address_w)); map(0x19, 0x19).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w)); map(0x1c, 0x1c).w(this, FUNC(kdt6_state::status0_w)); map(0x1d, 0x1d).r(m_keyboard, FUNC(psi_keyboard_bus_device::key_data_r)); map(0x1e, 0x1e).rw(m_fdc, FUNC(upd765a_device::mdma_r), FUNC(upd765a_device::mdma_w)); map(0x1f, 0x1f).w(this, FUNC(kdt6_state::fdc_tc_w)); map(0x20, 0x2f).rw(this, FUNC(kdt6_state::mapper_r), FUNC(kdt6_state::mapper_w)); map(0x30, 0x30).rw(this, FUNC(kdt6_state::video_data_r), FUNC(kdt6_state::video_data_w)); map(0x31, 0x31).w(this, FUNC(kdt6_state::video_data_inc_w)); map(0x36, 0x36).w(this, FUNC(kdt6_state::video_data_dec_w)); map(0x37, 0x37).w(this, FUNC(kdt6_state::video_data_inc_w)); map(0x38, 0x38).w(this, FUNC(kdt6_state::status1_w)); map(0x39, 0x39).r(this, FUNC(kdt6_state::status1_r)); map(0x3a, 0x3a).w(this, FUNC(kdt6_state::status2_w)); map(0x3b, 0x3b).rw(this, FUNC(kdt6_state::sasi_ctrl_r), FUNC(kdt6_state::sasi_ctrl_w)); map(0x3c, 0x3c).w(this, FUNC(kdt6_state::dma_map_w)); #if 0 map(0x3d, 0x3d) WATCHDOG map(0x3e, 0x3e) WATCHDOG TRIGGER map(0x3f, 0x3f) SASI DATA #endif map(0x40, 0x40).w(this, FUNC(kdt6_state::video_address_latch_high_w)); map(0x41, 0x41).w(this, FUNC(kdt6_state::video_address_latch_low_w)); } //************************************************************************** // INPUTS //************************************************************************** INPUT_PORTS_START( psi98 ) PORT_START("S2") PORT_DIPNAME(0x01, 0x01, "SIO B") PORT_DIPLOCATION("S2:1") PORT_DIPSETTING(0x00, "RS232") PORT_DIPSETTING(0x01, "Keyboard") INPUT_PORTS_END //************************************************************************** // FLOPPY //************************************************************************** static void kdt6_floppies(device_slot_interface &device) { device.option_add("fd55f", TEAC_FD_55F); } WRITE8_MEMBER( kdt6_state::fdc_tc_w ) { m_fdc->tc_w(1); m_fdc->tc_w(0); } WRITE_LINE_MEMBER( kdt6_state::fdc_drq_w ) { if (!m_sasi_dma && BIT(m_status0, 4) == 0) m_dma->rdy_w(state); } void kdt6_state::drive0_led_cb(floppy_image_device *floppy, int state) { machine().output().set_value("drive0_led", state); } void kdt6_state::drive1_led_cb(floppy_image_device *floppy, int state) { machine().output().set_value("drive1_led", state); } //************************************************************************** // VIDEO //************************************************************************** WRITE8_MEMBER( kdt6_state::video_address_latch_high_w ) { m_video_address &= 0x00ff; m_video_address |= (data << 8); } WRITE8_MEMBER( kdt6_state::video_address_latch_low_w ) { m_video_address &= 0xff00; m_video_address |= (data << 0); } READ8_MEMBER( kdt6_state::video_data_r ) { return m_vram[m_video_address]; } WRITE8_MEMBER( kdt6_state::video_data_w ) { m_vram[m_video_address] = ((m_status1 & 0x0c) << 6) | data; } WRITE8_MEMBER( kdt6_state::video_data_inc_w ) { m_vram[m_video_address++] = ((m_status1 & 0x0c) << 6) | data; } WRITE8_MEMBER( kdt6_state::video_data_dec_w ) { m_vram[m_video_address--] = ((m_status1 & 0x0c) << 6) | data; } uint32_t kdt6_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { m_crtc->screen_update(screen, bitmap, cliprect); return 0; } MC6845_UPDATE_ROW( kdt6_state::crtc_update_row ) { const pen_t *pen = m_palette->pens(); for (int i = 0; i < x_count; i++) { if (BIT(m_status1, 6)) { // text mode uint16_t code = m_vram[((m_status1 & 0x03) << 14) | (ma + i)]; uint8_t data = m_gfx[((code & 0xff) << 4) | ra]; int inverse = BIT(code, 8) | BIT(m_status1, 5) | ((i == cursor_x) ? 1 : 0); int blink = BIT(code, 9) & m_crtc->cursor_r(); // draw 8 pixels of the character for (int x = 0; x < 8; x++) { int color = BIT(data, 7 - x); bitmap.pix32(y, x + i*8) = pen[blink ? 0 : (color ^ inverse)]; } } else { // gfx mode uint8_t data = m_vram[(ma << 4) | (ra << 6) | i]; // draw 8 pixels of the cell for (int x = 0; x < 8; x++) bitmap.pix32(y, x + i*8) = pen[BIT(data, 7 - x)]; } } } //************************************************************************** // SOUND //************************************************************************** TIMER_DEVICE_CALLBACK_MEMBER( kdt6_state::beeper_off ) { m_beeper->set_state(0); } //************************************************************************** // EXTERNAL I/O //************************************************************************** WRITE8_MEMBER( kdt6_state::pio_porta_w ) { m_centronics->write_strobe(BIT(data, 0)); m_centronics->write_init(BIT(data, 1)); } WRITE_LINE_MEMBER( kdt6_state::keyboard_rx_w ) { if (machine().phase() >= machine_phase::RESET) { if ((m_dip_s2->read() & 0x01) == 0x01) m_sio->rxb_w(state); } } WRITE_LINE_MEMBER( kdt6_state::rs232b_rx_w ) { if (machine().phase() >= machine_phase::RESET) { if ((m_dip_s2->read() & 0x01) == 0x00) m_sio->rxb_w(state); } } WRITE_LINE_MEMBER( kdt6_state::siob_tx_w ) { if (machine().phase() >= machine_phase::RESET) { if ((m_dip_s2->read() & 0x01) == 0x01) m_keyboard->tx_w(state); else m_rs232b->write_txd(state); } } //************************************************************************** // MACHINE //************************************************************************** WRITE_LINE_MEMBER( kdt6_state::busreq_w ) { m_cpu->set_input_line(Z80_INPUT_LINE_BUSRQ, state); m_dma->bai_w(state); } READ8_MEMBER( kdt6_state::memory_r ) { return m_ram[m_dma_map << 16 | offset]; } WRITE8_MEMBER( kdt6_state::memory_w ) { m_ram[m_dma_map << 16 | offset] = data; } READ8_MEMBER( kdt6_state::io_r ) { return m_cpu->space(AS_IO).read_byte(offset); } WRITE8_MEMBER( kdt6_state::io_w ) { m_cpu->space(AS_IO).write_byte(offset, data); } READ8_MEMBER( kdt6_state::page0_r ) { if (BIT(m_status0, 5) == 0) return m_boot->as_u8(offset); return reinterpret_cast(m_page_r[0]->base())[offset]; } READ8_MEMBER( kdt6_state::page1_r ) { if (BIT(m_status0, 5) == 0) return m_boot->as_u8(0x1000 + offset); return reinterpret_cast(m_page_r[1]->base())[offset]; } READ8_MEMBER( kdt6_state::sasi_ctrl_r ) { uint8_t data = 0; // 7------- sasi select // -6------ sasi reset // --5----- sasi input/output // ---4---- sasi control/data // ----3--- sasi message // -----2-- sasi request // ------1- sasi busy // -------0 data output upd1990 data |= m_rtc->data_out_r() << 0; data |= 0xfe; return data; } WRITE8_MEMBER( kdt6_state::sasi_ctrl_w ) { logerror("sasi_ctrl_w: %02x\n", data); m_sasi_dma = bool(BIT(data, 2) == 0); } WRITE8_MEMBER( kdt6_state::dma_map_w ) { m_dma_map = data; } READ8_MEMBER( kdt6_state::mapper_r ) { return m_mapper[offset]; } WRITE8_MEMBER( kdt6_state::mapper_w ) { m_mapper[offset] = ((m_status2 & 0x0f) << 8) | data; if (BIT(m_status1, 7) == 0) { offs_t addr = bitswap(m_mapper[offset], 8, 9, 10, 11, 7, 6, 5, 4, 0, 1, 2, 3) << 12; m_page_r[offset]->set_base(addr < 0x40000 ? &m_ram[addr] : &m_dummy_r[0]); m_page_w[offset]->set_base(addr < 0x40000 ? &m_ram[addr] : &m_dummy_w[0]); if (0) logerror("map_page: %x -> %06x\n", offset, addr); } } WRITE8_MEMBER( kdt6_state::status0_w ) { logerror("status0_w: %02x\n", data); // 7------- floppy motor // -6------ floppy drive type // --5----- prom off // ---4---- dma trigger (floppy/sio) // ----3--- character generator a12 // -----2-- sound // ------1- system frequency (0 = half) // -------0 watchdog enable m_cpu->set_unscaled_clock((XTAL(16'000'000) / 4) * (BIT(data, 1) ? 1 : 0.5)); if ((BIT(m_status0, 2) ^ BIT(data, 2)) && BIT(data, 2)) { m_beeper->set_state(1); m_beep_timer->adjust(attotime::from_msec(250)); // timing unknown } if (m_floppy0->get_device()) m_floppy0->get_device()->mon_w(BIT(data, 7) ? 0 : 1); if (m_floppy1->get_device()) m_floppy1->get_device()->mon_w(BIT(data, 7) ? 0 : 1); m_status0 = data; } READ8_MEMBER( kdt6_state::status1_r ) { // 7------- disable memory mapper (1 = disable) // -6------ display mode (1 = text, 0 = gfx) // --5----- video invert // ---4---- select 3 video memory bank // ----3--- video bit 9 // -----2-- video bit 8 // ------1- video scroll address bit 15 // -------0 video scroll address bit 14 return m_status1; } WRITE8_MEMBER( kdt6_state::status1_w ) { logerror("status1_w: %02x\n", data); // memory mapper disabled? if (BIT(data, 7)) { for (unsigned i = 0; i < 16; i++) { m_page_r[i]->set_base(&m_ram[i * 0x1000]); m_page_w[i]->set_base(&m_ram[i * 0x1000]); } } // note that enabling the memory mapper doesn't mean that the pages are automatically mapped in // it still needs a write to the mapper register to activate m_status1 = data; } WRITE8_MEMBER( kdt6_state::status2_w ) { if (0) logerror("status2_w: %02x\n", data); // 7------- rtc chip select // -6------ rtc output enable // --5----- rtc strobe // ---4---- rtc clock // ----321- rtc control 2-0 // -------0 rtc data // ----3210 memory mapper bit 0-3 m_rtc->cs_w(BIT(data, 7)); m_rtc->oe_w(BIT(data, 6)); m_rtc->stb_w(BIT(data, 5)); m_rtc->clk_w(BIT(data, 4)); m_rtc->c2_w(BIT(data, 3)); m_rtc->c1_w(BIT(data, 2)); m_rtc->c0_w(BIT(data, 1)); m_rtc->data_in_w(BIT(data, 0)); m_status2 = data & 0x0f; } void kdt6_state::machine_start() { // 256 kb ram, 64 kb vram (and two dummy regions for invalid pages) m_ram = std::make_unique(0x40000); m_vram = std::make_unique(0x10000); m_dummy_r = std::make_unique(0x1000); m_dummy_w = std::make_unique(0x1000); // override the region 0x0000 to 0x1fff here to enable prom reading m_cpu->space(AS_PROGRAM).install_read_handler(0x0000, 0x0fff, read8_delegate(FUNC(kdt6_state::page0_r), this)); m_cpu->space(AS_PROGRAM).install_read_handler(0x1000, 0x1fff, read8_delegate(FUNC(kdt6_state::page1_r), this)); m_fdc->set_rate(250000); if (m_floppy0->get_device()) m_floppy0->get_device()->setup_led_cb(floppy_image_device::led_cb(&kdt6_state::drive0_led_cb, this)); if (m_floppy1->get_device()) m_floppy1->get_device()->setup_led_cb(floppy_image_device::led_cb(&kdt6_state::drive1_led_cb, this)); // register for save states save_pointer(NAME(m_ram.get()), 0x40000); save_pointer(NAME(m_vram.get()), 0x10000); save_item(NAME(m_sasi_dma)); save_item(NAME(m_dma_map)); save_item(NAME(m_status0)); save_item(NAME(m_status1)); save_item(NAME(m_status2)); save_pointer(NAME(m_mapper), 16); save_item(NAME(m_video_address)); } void kdt6_state::machine_reset() { // status0 is forced to 0 on reset status0_w(m_cpu->space(AS_IO), 0, 0); } //************************************************************************** // MACHINE DEFINITIONS //************************************************************************** static const z80_daisy_config daisy_chain_intf[] = { { "dma" }, { "ctc1" }, { "sio" }, { "ctc2" }, { "pio" }, { nullptr } }; MACHINE_CONFIG_START(kdt6_state::psi98) MCFG_DEVICE_ADD("maincpu", Z80, XTAL(16'000'000) / 4) MCFG_DEVICE_PROGRAM_MAP(psi98_mem) MCFG_DEVICE_IO_MAP(psi98_io) MCFG_Z80_DAISY_CHAIN(daisy_chain_intf) // video hardware MCFG_SCREEN_ADD_MONOCHROME("screen", RASTER, rgb_t::green()) MCFG_SCREEN_RAW_PARAMS(XTAL(13'516'800), 824, 48, 688, 274, 0, 250) MCFG_SCREEN_UPDATE_DRIVER(kdt6_state, screen_update) MCFG_PALETTE_ADD_MONOCHROME("palette") MCFG_DEFAULT_LAYOUT(layout_kdt6) MCFG_MC6845_ADD("crtc", MC6845, "screen", XTAL(13'516'800) / 8) MCFG_MC6845_SHOW_BORDER_AREA(false) MCFG_MC6845_CHAR_WIDTH(8) MCFG_MC6845_UPDATE_ROW_CB(kdt6_state, crtc_update_row) MCFG_MC6845_OUT_VSYNC_CB(WRITELINE("ctc2", z80ctc_device, trg2)) // sound hardware SPEAKER(config, "mono").front_center(); MCFG_DEVICE_ADD("beeper", BEEP, 1000) // frequency unknown MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) MCFG_DEVICE_ADD("speaker", SPEAKER_SOUND) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) MCFG_TIMER_DRIVER_ADD("beep_timer", kdt6_state, beeper_off) MCFG_DEVICE_ADD("dma", Z80DMA, XTAL(16'000'000) / 4) MCFG_Z80DMA_OUT_BUSREQ_CB(WRITELINE(*this, kdt6_state, busreq_w)) MCFG_Z80DMA_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0)) MCFG_Z80DMA_IN_MREQ_CB(READ8(*this, kdt6_state, memory_r)) MCFG_Z80DMA_OUT_MREQ_CB(WRITE8(*this, kdt6_state, memory_w)) MCFG_Z80DMA_IN_IORQ_CB(READ8(*this, kdt6_state, io_r)) MCFG_Z80DMA_OUT_IORQ_CB(WRITE8(*this, kdt6_state, io_w)) // jumper J3 allows selection of 16MHz / 8 instead MCFG_CLOCK_ADD("uart_clk", XTAL(9'830'400) / 8) MCFG_CLOCK_SIGNAL_HANDLER(WRITELINE("ctc1", z80ctc_device, trg1)) MCFG_DEVCB_CHAIN_OUTPUT(WRITELINE("ctc1", z80ctc_device, trg2)) MCFG_DEVICE_ADD("ctc1", Z80CTC, XTAL(16'000'000) / 4) MCFG_Z80CTC_INTR_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0)) MCFG_Z80CTC_ZC1_CB(WRITELINE("sio", z80sio_device, rxtxcb_w)) MCFG_Z80CTC_ZC2_CB(WRITELINE("sio", z80sio_device, rxca_w)) MCFG_DEVCB_CHAIN_OUTPUT(WRITELINE("sio", z80sio_device, txca_w)) MCFG_DEVICE_ADD("ctc2", Z80CTC, XTAL(16'000'000) / 4) MCFG_Z80CTC_INTR_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0)) MCFG_Z80CTC_ZC0_CB(WRITELINE("speaker", speaker_sound_device, level_w)) MCFG_Z80CTC_ZC2_CB(WRITELINE("ctc2", z80ctc_device, trg3)) MCFG_DEVICE_ADD("sio", Z80SIO, XTAL(16'000'000) / 4) MCFG_Z80SIO_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0)) MCFG_Z80SIO_OUT_TXDA_CB(WRITELINE("rs232a", rs232_port_device, write_txd)) MCFG_Z80SIO_OUT_DTRA_CB(WRITELINE("rs232a", rs232_port_device, write_dtr)) MCFG_Z80SIO_OUT_RTSA_CB(WRITELINE("rs232a", rs232_port_device, write_rts)) MCFG_Z80SIO_OUT_TXDB_CB(WRITELINE(*this, kdt6_state, siob_tx_w)) MCFG_Z80SIO_OUT_DTRB_CB(WRITELINE("rs232b", rs232_port_device, write_dtr)) MCFG_Z80SIO_OUT_RTSB_CB(WRITELINE("rs232b", rs232_port_device, write_rts)) MCFG_DEVICE_ADD("rs232a", RS232_PORT, default_rs232_devices, nullptr) MCFG_RS232_RXD_HANDLER(WRITELINE("sio", z80sio_device, rxa_w)) MCFG_RS232_DCD_HANDLER(WRITELINE("sio", z80sio_device, dcda_w)) MCFG_RS232_DSR_HANDLER(WRITELINE("sio", z80sio_device, synca_w)) MCFG_RS232_CTS_HANDLER(WRITELINE("sio", z80sio_device, ctsa_w)) MCFG_DEVCB_XOR(1) MCFG_DEVICE_ADD("rs232b", RS232_PORT, default_rs232_devices, nullptr) MCFG_RS232_RXD_HANDLER(WRITELINE(*this, kdt6_state, rs232b_rx_w)) MCFG_RS232_DCD_HANDLER(WRITELINE("sio", z80sio_device, dcdb_w)) MCFG_RS232_DSR_HANDLER(WRITELINE("sio", z80sio_device, syncb_w)) MCFG_RS232_CTS_HANDLER(WRITELINE("sio", z80sio_device, ctsb_w)) MCFG_DEVCB_XOR(1) MCFG_DEVICE_ADD("pio", Z80PIO, XTAL(16'000'000) / 4) MCFG_Z80PIO_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0)) MCFG_Z80PIO_OUT_PA_CB(WRITE8(*this, kdt6_state, pio_porta_w)) MCFG_Z80PIO_IN_PB_CB(READ8("cent_data_in", input_buffer_device, read)) MCFG_Z80PIO_OUT_PB_CB(WRITE8("cent_data_out", output_latch_device, write)) MCFG_CENTRONICS_ADD("centronics", centronics_devices, "printer") MCFG_CENTRONICS_DATA_INPUT_BUFFER("cent_data_in") MCFG_CENTRONICS_FAULT_HANDLER(WRITELINE("pio", z80pio_device, pa2_w)) MCFG_CENTRONICS_PERROR_HANDLER(WRITELINE("pio", z80pio_device, pa3_w)) MCFG_CENTRONICS_BUSY_HANDLER(WRITELINE("pio", z80pio_device, pa4_w)) MCFG_CENTRONICS_SELECT_HANDLER(WRITELINE("pio", z80pio_device, pa5_w)) MCFG_DEVICE_ADD("cent_data_in", INPUT_BUFFER, 0) MCFG_CENTRONICS_OUTPUT_LATCH_ADD("cent_data_out", "centronics") MCFG_UPD1990A_ADD("rtc", XTAL(32'768), NOOP, NOOP) MCFG_UPD765A_ADD("fdc", true, true) MCFG_UPD765_INTRQ_CALLBACK(WRITELINE("ctc1", z80ctc_device, trg0)) MCFG_UPD765_DRQ_CALLBACK(WRITELINE(*this, kdt6_state, fdc_drq_w)) MCFG_FLOPPY_DRIVE_ADD("fdc:0", kdt6_floppies, "fd55f", floppy_image_device::default_floppy_formats) MCFG_FLOPPY_DRIVE_ADD("fdc:1", kdt6_floppies, "fd55f", floppy_image_device::default_floppy_formats) MCFG_SOFTWARE_LIST_ADD("floppy_list", "psi98") MCFG_PSI_KEYBOARD_INTERFACE_ADD("kbd", "hle") MCFG_PSI_KEYBOARD_RX_HANDLER(WRITELINE(*this, kdt6_state, keyboard_rx_w)) MCFG_PSI_KEYBOARD_KEY_STROBE_HANDLER(WRITELINE("ctc2", z80ctc_device, trg1)) // 6 ECB slots MACHINE_CONFIG_END //************************************************************************** // ROM DEFINITIONS //************************************************************************** ROM_START( psi98 ) ROM_REGION(0x2000, "boot", 0) ROM_LOAD("td_62b60_1.prom1", 0x0000, 0x1000, CRC(dbc01eeb) SHA1(3ecab997623836599a5e0b2a05d0f743d93edf00)) // SUM16: 0a84 (file: 29ca) ROM_LOAD("boot_v61_a.prom2", 0x1000, 0x1000, CRC(6dd9a5e3) SHA1(b812947009d83e9c6119e731ba7d40fe3597d42c)) // SUM16: d4ec (file: b1fb) ROM_REGION(0x1000, "gfx", 0) ROM_LOAD("ch6_d-e.bin", 0x0000, 0x1000, CRC(e7bca335) SHA1(454ca3b8b8ac66464870e4bd5497050038d771c8)) // SUM16: 39b1 (file: 5f55) // PALs // 1-FF5B 12L6 memory address decoder // 2-0F61 12L8 i/o address decoder // 3-C7BF 10H8 interrupt priority controller // 4-EC5E 16L8 bus controller // 5-1126 16H2 fdc write precompensation // 6-1BA7 10L8 video memory access controller // 7-C1ED 16L8 video memory timing controller // 8-CD9F 12H6 fdc timing generator ROM_END //************************************************************************** // SYSTEM DRIVERS //************************************************************************** // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS COMP( 1984, psi98, 0, 0, psi98, psi98, kdt6_state, empty_init, "Kontron", "PSI98", 0 )