diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 916c4be6903..a3df4b152e3 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -3566,6 +3566,7 @@ files { MAME_DIR .. "src/mame/drivers/tecnbras.cpp", MAME_DIR .. "src/mame/drivers/terak.cpp", MAME_DIR .. "src/mame/drivers/ti630.cpp", + MAME_DIR .. "src/mame/drivers/trs80dt1.cpp", MAME_DIR .. "src/mame/drivers/tsispch.cpp", MAME_DIR .. "src/mame/includes/tsispch.h", MAME_DIR .. "src/mame/drivers/tvgame.cpp", diff --git a/src/mame/drivers/trs80dt1.cpp b/src/mame/drivers/trs80dt1.cpp new file mode 100644 index 00000000000..5aeac48e95c --- /dev/null +++ b/src/mame/drivers/trs80dt1.cpp @@ -0,0 +1,296 @@ +// license:BSD-3-Clause +// copyright-holders: Robbbert +/********************************************************************************** + +TRS-80 DT-1 + +Tandy's Data Terminal. + +Skeleton driver commenced on 2017-10-25. + +Core bugs noted: +- If AM_REGION used to locate the main rom in another region, validation + complains that region ':maincpu' not found. +- If region 'maincpu' changed to 0x1000 (same size as the rom), a fatal error + of duplicate save state occurs at start. + + +ToDo: +- Serial i/o +- Centronics printer +- Fix video (it is hooked up as per schematic, but when text is present it + scrolls crazily and flickers, also in debug the input-line queue can overflow). +- Check that attributes are correctly applied +- Keyboard is coded but not tested. +- Add the nvram + +**********************************************************************************/ + +#include "emu.h" +#include "cpu/mcs51/mcs51.h" +#include "video/i8275.h" +#include "screen.h" +//#include "logmacro.h" + +class trs80dt1_state : public driver_device +{ +public: + trs80dt1_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_p_videoram(*this, "videoram") + , m_p_chargen(*this, "chargen") + , m_maincpu(*this, "maincpu") + , m_palette(*this, "palette") + , m_crtc(*this, "crtc") + , m_keyboard(*this, "X%u", 0) + { } + + DECLARE_READ8_MEMBER(dma_r); + DECLARE_READ8_MEMBER(key_r); + DECLARE_WRITE_LINE_MEMBER(irq_w); + DECLARE_WRITE_LINE_MEMBER(hrtc_w); + I8275_DRAW_CHARACTER_MEMBER(crtc_update_row); + +private: + bool m_irq_state; + virtual void machine_reset() override; + virtual void machine_start() override; + required_shared_ptr m_p_videoram; + required_region_ptr m_p_chargen; + required_device m_maincpu; + required_device m_palette; + required_device m_crtc; + required_ioport_array<9> m_keyboard; +}; + +void trs80dt1_state::machine_reset() +{ + m_irq_state = 0; +} + +READ8_MEMBER( trs80dt1_state::dma_r ) +{ + m_crtc->dack_w(space, 0, m_p_videoram[offset]); // write to /BS pin + return 0x7f; +} + +READ8_MEMBER( trs80dt1_state::key_r ) +{ + offset &= 15; + if (offset < 9) + return m_keyboard[offset]->read(); + else + return 0xff; +} + +WRITE_LINE_MEMBER( trs80dt1_state::irq_w ) +{ + m_irq_state = state; + if (!state) + m_maincpu->set_input_line(MCS51_INT1_LINE, CLEAR_LINE); +} + +WRITE_LINE_MEMBER( trs80dt1_state::hrtc_w ) +{ + m_maincpu->set_input_line(MCS51_INT1_LINE, m_irq_state ? HOLD_LINE : CLEAR_LINE); +} + +static ADDRESS_MAP_START( prg_map, AS_PROGRAM, 8, trs80dt1_state ) + AM_RANGE(0x0000, 0x0fff) AM_ROM // AM_REGION("roms", 0) AM_REGION ignored for this cpu + AM_RANGE(0x2000, 0x27ff) AM_READ(dma_r) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( data_map, AS_DATA, 8, trs80dt1_state ) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( io_map, AS_IO, 8, trs80dt1_state ) + ADDRESS_MAP_GLOBAL_MASK(0xbfff) // A14 not used + AM_RANGE(0xa000, 0xa7ff) AM_RAM AM_SHARE("videoram") + //AM_RANGE(0xa800, 0xabff) AM_RAM //NVRAM array select + AM_RANGE(0xac00, 0xafff) AM_READ(key_r) + AM_RANGE(0xb000, 0xb3ff) AM_READ_PORT("X9") //keyboard/RS232 input read + //AM_RANGE(0xb400, 0xb7ff) AM_RAM //NVRAM write select + AM_RANGE(0xbc00, 0xbc01) AM_MIRROR(0x3fe) AM_DEVREADWRITE("crtc", i8275_device, read, write) // i8276 + //AM_RANGE(MCS51_PORT_P0, MCS51_PORT_P3) AM_READWRITE(port_r, port_w) +ADDRESS_MAP_END + +/* Input ports */ +static INPUT_PORTS_START( trs80dt1 ) + PORT_START("X0") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL) PORT_CHAR(0x7f) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(9) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(32) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) + + PORT_START("X1") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("BS") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) + + PORT_START("X2") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) + + PORT_START("X3") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('\"') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR('1') PORT_CHAR('\\') + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) + + PORT_START("X4") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR('3') PORT_CHAR('~') + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD) + + PORT_START("X5") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_END) PORT_CHAR(3) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(27) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER_PAD) + + PORT_START("X6") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Clear") PORT_CODE(KEYCODE_HOME) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Linefeed") PORT_CODE(KEYCODE_INSERT) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("X7") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('}') PORT_CHAR(']') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("X8") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('{') PORT_CHAR('[') + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("X9") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CODE(KEYCODE_LSHIFT) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RCONTROL) PORT_CODE(KEYCODE_LCONTROL) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) +INPUT_PORTS_END + +void trs80dt1_state::machine_start() +{ + m_palette->set_pen_color(0, rgb_t(0x00,0x00,0x00)); // black + m_palette->set_pen_color(1, rgb_t(0x00,0xa0,0x00)); // normal + m_palette->set_pen_color(2, rgb_t(0x00,0xff,0x00)); // highlight +} + +const gfx_layout trs80dt1_charlayout = +{ + 8, 8, /* 8x16 characters - the last 8 lines are always blank */ + 128, /* 128 characters */ + 1, /* 1 bits per pixel */ + {0}, /* no bitplanes; 1 bit per pixel */ + {0,1,2,3,4,5,6,7}, + {0, 8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 }, + 8*16 /* space between characters */ +}; + +static GFXDECODE_START( trs80dt1 ) + GFXDECODE_ENTRY( "chargen", 0x0000, trs80dt1_charlayout, 0, 1 ) +GFXDECODE_END + + +I8275_DRAW_CHARACTER_MEMBER( trs80dt1_state::crtc_update_row ) +{ + charcode &= 0x7f; + linecount &= 15; + + const rgb_t *palette = m_palette->palette()->entry_list_raw(); + u8 gfx = (lten) ? 0xff : 0; + if (!vsp) + gfx = m_p_chargen[linecount | (charcode << 4)]; + + if (rvv) + gfx ^= 0xff; + + for(u8 i=0; i<8; i++) + bitmap.pix32(y, x + i) = palette[BIT(gfx, 7-i) ? (hlgt ? 2 : 1) : 0]; +} + + +static MACHINE_CONFIG_START( trs80dt1 ) + /* basic machine hardware */ + MCFG_CPU_ADD("maincpu", I8051, 7372800) + MCFG_CPU_PROGRAM_MAP(prg_map) + MCFG_CPU_DATA_MAP(data_map) + MCFG_CPU_IO_MAP(io_map) + + /* video hardware */ + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_UPDATE_DEVICE("crtc", i8275_device, screen_update) + MCFG_SCREEN_REFRESH_RATE(50) + MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ + MCFG_SCREEN_SIZE(40*12, 16*16) + MCFG_SCREEN_VISIBLE_AREA(0, 40*12-1, 0, 16*16-1) + MCFG_GFXDECODE_ADD("gfxdecode", "palette", trs80dt1 ) + + MCFG_DEVICE_ADD("crtc", I8275, 12480000 / 8) + MCFG_I8275_CHARACTER_WIDTH(8) + MCFG_I8275_DRAW_CHARACTER_CALLBACK_OWNER(trs80dt1_state, crtc_update_row) + MCFG_I8275_DRQ_CALLBACK(INPUTLINE("maincpu", MCS51_INT0_LINE)) // BRDY pin + MCFG_I8275_IRQ_CALLBACK(WRITELINE(trs80dt1_state, irq_w)) // INT pin + MCFG_I8275_HRTC_CALLBACK(WRITELINE(trs80dt1_state, hrtc_w)) + MCFG_VIDEO_SET_SCREEN("screen") + MCFG_PALETTE_ADD("palette", 3) +MACHINE_CONFIG_END + +ROM_START( trs80dt1 ) + + ROM_REGION( 0x10000, "maincpu", 0 ) + ROM_LOAD( "trs80dt1.u12", 0x0000, 0x1000, CRC(04e8a53f) SHA1(7b5d5047319ef8f230b82684d97a918b564d466e) ) + + ROM_REGION( 0x0800, "chargen", 0 ) + ROM_LOAD( "8045716.u8", 0x0000, 0x0800, CRC(e2c5e59b) SHA1(0d571888d5f9fea4e565486ea8d3af8998ca46b1) ) +ROM_END + +COMP( 1989, trs80dt1, 0, 0, trs80dt1, trs80dt1, trs80dt1_state, 0, "Radio Shack", "TRS-80 DT-1", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index e54b6e9a650..804851f6342 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -36894,6 +36894,9 @@ trs80m3 // TRS-80 Model III - Radio Shack/Tandy trs80m4 // trs80m4p // +@source:trs80dt1.cpp +trs80dt1 // TRS-80 Data Terminal 1 + @source:trs80m2.cpp trs80m16 // trs80m2 //