From d057dca066e7b80d24484a7f568cf48595f79cfd Mon Sep 17 00:00:00 2001 From: Robbbert Date: Sat, 21 Jul 2018 00:25:49 +1000 Subject: trs80 work in progress - split into separate sources - fixed paste - added uart and rs232 - added baud rate clock or brg depending on hardware - fixed uart status on sys80 - fixed cassette waveform - lots of tidy up --- scripts/target/mame/mess.lua | 5 + src/mame/drivers/meritum.cpp | 452 +++++++++++++++++++++++++++++ src/mame/drivers/trs80.cpp | 650 ++++++++++++----------------------------- src/mame/drivers/trs80m3.cpp | 551 +++++++++++++++++++++++++++++++++++ src/mame/includes/trs80.h | 170 +++-------- src/mame/includes/trs80m3.h | 159 ++++++++++ src/mame/machine/trs80.cpp | 670 ++++++------------------------------------- src/mame/machine/trs80m3.cpp | 660 ++++++++++++++++++++++++++++++++++++++++++ src/mame/mame.lst | 16 +- src/mame/mess.flt | 2 + src/mame/video/trs80.cpp | 239 +-------------- src/mame/video/trs80m3.cpp | 125 ++++++++ 12 files changed, 2301 insertions(+), 1398 deletions(-) create mode 100644 src/mame/drivers/meritum.cpp create mode 100644 src/mame/drivers/trs80m3.cpp create mode 100644 src/mame/includes/trs80m3.h create mode 100644 src/mame/machine/trs80m3.cpp create mode 100644 src/mame/video/trs80m3.cpp diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 86b3700e682..3ba22ef4866 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -3367,6 +3367,7 @@ files { MAME_DIR .. "src/mame/includes/dgnalpha.h", MAME_DIR .. "src/mame/video/gime.cpp", MAME_DIR .. "src/mame/video/gime.h", + MAME_DIR .. "src/mame/drivers/meritum.cpp", MAME_DIR .. "src/mame/drivers/trs80.cpp", MAME_DIR .. "src/mame/includes/trs80.h", MAME_DIR .. "src/mame/machine/trs80.cpp", @@ -3375,6 +3376,10 @@ files { MAME_DIR .. "src/mame/includes/trs80m2.h", MAME_DIR .. "src/mame/machine/trs80m2kb.cpp", MAME_DIR .. "src/mame/machine/trs80m2kb.h", + MAME_DIR .. "src/mame/drivers/trs80m3.cpp", + MAME_DIR .. "src/mame/includes/trs80m3.h", + MAME_DIR .. "src/mame/machine/trs80m3.cpp", + MAME_DIR .. "src/mame/video/trs80m3.cpp", MAME_DIR .. "src/mame/drivers/tandy2k.cpp", MAME_DIR .. "src/mame/includes/tandy2k.h", MAME_DIR .. "src/mame/machine/tandy2kb.cpp", diff --git a/src/mame/drivers/meritum.cpp b/src/mame/drivers/meritum.cpp new file mode 100644 index 00000000000..c45b7deea94 --- /dev/null +++ b/src/mame/drivers/meritum.cpp @@ -0,0 +1,452 @@ +// license:BSD-3-Clause +// copyright-holders:Robbbert +/*************************************************************************** + +Mera-Elzab Meritum II (Poland) + +Meritum I was a basic unit with no expansion, expensive, and so very rare. +Meritum II had all the standard TRS80 expansions, but the i/o is different +and thus not compatible. +Meritum III was planned, but seems to have been cancelled before release. + +Split from trs80.cpp on 2018-07-15 + +It is quite similar to the TRS80 Model 1 Level II, however the extra chips +are quite different, being Intel ones (i8251, i8253, i8255, i8272, etc). + +There's no lowercase, so the shift key will select Polish characters if +available, as well as the usual standard punctuation. +The control key appears to do nothing. +There's also a Reset key, a NMI key, and 2 blank ones. + +Status: +- Starts up, runs Basic. Cassette works. Quickload mostly works. +- Some quickloads have corrupt text due to no lowercase. +- Some quickloads don't run at all. Some may crash the emulator. +- Intel chips need adding, along with the peripherals they control. +- A speaker has been included (which works), but real machine might not have + one at that address. To be checked. +- On meritum_net, type NET to activate the networking features. +- Add Reset key, NMI key, and 2 blank keys. +- Need software specific to test the hardware. +- Need boot disks (MER-DOS, CP/M 2.2) + +Depending on which website you read, the following might be for II, or +perhaps III: +- Add 4-colour mode, 4 shades of grey mode, and 512x192 monochrome. + +****************************************************************************/ +#include "emu.h" +#include "cpu/z80/z80.h" +#include "imagedev/cassette.h" +#include "imagedev/snapquik.h" +#include "sound/spkrdev.h" +#include "sound/wave.h" +#include "screen.h" +#include "speaker.h" +#include "emupal.h" + +class meritum_state : public driver_device +{ +public: + meritum_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_p_chargen(*this, "chargen") + , m_p_videoram(*this, "videoram") + , m_speaker(*this, "speaker") + , m_cassette(*this, "cassette") + , m_io_keyboard(*this, "LINE%u", 0) + { } + + void meritum(machine_config &config); + +private: + DECLARE_WRITE8_MEMBER(port_ff_w); + DECLARE_READ8_MEMBER(port_ff_r); + DECLARE_READ8_MEMBER(keyboard_r); + + TIMER_CALLBACK_MEMBER(cassette_data_callback); + DECLARE_QUICKLOAD_LOAD_MEMBER(trs80_cmd); + uint32_t screen_update_meritum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + void mem_map(address_map &map); + void io_map(address_map &map); + + bool m_mode; + bool m_size_store; + uint8_t m_irq; + uint8_t m_mask; + bool m_cassette_data; + emu_timer *m_cassette_data_timer; + double m_old_cassette_val; + virtual void machine_start() override; + virtual void machine_reset() override; + required_device m_maincpu; + required_region_ptr m_p_chargen; + required_shared_ptr m_p_videoram; + required_device m_speaker; + required_device m_cassette; + required_ioport_array<8> m_io_keyboard; +}; + +void meritum_state::mem_map(address_map &map) +{ + map(0x0000, 0x37ff).rom(); + map(0x3800, 0x38ff).mirror(0x300).r(FUNC(meritum_state::keyboard_r)); + map(0x3c00, 0x3fff).ram().share(m_p_videoram); + map(0x4000, 0xffff).ram(); +} + +void meritum_state::io_map(address_map &map) +{ + map.global_mask(0xff); + map.unmap_value_high(); + // map(0x00, 0x03).rw 8253-2 (optional audio interface?) + // map(0xf0, 0xf3).rw 8255-2 (floppy disk interface) + // map(0xf4, 0xf7).rw 8255-1 (parallel interface) + // map(0xf8, 0xfb).rw 8253-1 (nmi, int, baud pulse generators) + // map(0xfc, 0xfd).rw 8251 (RS-232) + // map(0xfe, 0xfe) audio interface + map(0xff, 0xff).rw(FUNC(meritum_state::port_ff_r), FUNC(meritum_state::port_ff_w)); +} + + +static INPUT_PORTS_START( meritum ) + PORT_START("LINE0") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("@") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@') + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') + PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') + PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') + PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') + PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') + PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') + + PORT_START("LINE1") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') + PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') + PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') + PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') + PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') + PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') + + PORT_START("LINE2") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') + PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') + PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') + PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') + PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') + PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') + + PORT_START("LINE3") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') + PORT_BIT(0xF8, 0x00, IPT_UNUSED) + + PORT_START("LINE4") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) + PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) + PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) + PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) + PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) + PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) + + PORT_START("LINE5") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME(": *") PORT_CODE(KEYCODE_MINUS) PORT_CHAR(':') PORT_CHAR('*') + PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("; +") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+') + PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("- =") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('-') PORT_CHAR('=') + PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) + PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') + + PORT_START("LINE6") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("Clear") PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(F8)) + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(F9)) + PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) + PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) + PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) + PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) + PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') + + PORT_START("LINE7") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("CTL") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2) + PORT_BIT(0xFC, 0x00, IPT_UNUSED) +INPUT_PORTS_END + +uint32_t meritum_state::screen_update_meritum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +/* lores characters are in the character generator. Each character is 6x11. */ +{ + uint8_t y,ra,chr,gfx; + uint16_t sy=0,ma=0,x; + uint8_t cols = m_mode ? 32 : 64; + uint8_t skip = m_mode ? 2 : 1; + + if (m_mode != m_size_store) + { + m_size_store = m_mode; + screen.set_visible_area(0, cols*6-1, 0, 16*11-1); + } + + for (y = 0; y < 16; y++) + { + for (ra = 0; ra < 11; ra++) + { + uint16_t *p = &bitmap.pix16(sy++); + + for (x = ma; x < ma + 64; x+=skip) + { + chr = m_p_videoram[x]; + + /* get pattern of pixels for that character scanline */ + gfx = m_p_chargen[(chr<<4) | ra]; + + /* Display a scanline of a character (6 pixels) */ + *p++ = BIT(gfx, 5); + *p++ = BIT(gfx, 4); + *p++ = BIT(gfx, 3); + *p++ = BIT(gfx, 2); + *p++ = BIT(gfx, 1); + *p++ = BIT(gfx, 0); + } + } + ma+=64; + } + return 0; +} + +TIMER_CALLBACK_MEMBER(meritum_state::cassette_data_callback) +{ + double new_val = (m_cassette->input()); + + /* Check for HI-LO transition */ + if ( m_old_cassette_val > -0.2 && new_val < -0.2 ) + m_cassette_data = true; /* 500 baud */ + + m_old_cassette_val = new_val; +} + +READ8_MEMBER( meritum_state::port_ff_r ) +{ +/* ModeSel and cassette data + d7 cassette data from tape + d6 modesel setting */ + + return (m_mode ? 0 : 0x40) | (m_cassette_data ? 0x80 : 0) | 0x3f; +} + +WRITE8_MEMBER( meritum_state::port_ff_w ) +{ +/* Standard output port of Model I + d3 ModeSel bit + d2 Relay + d1, d0 Cassette output */ + + static const double levels[4] = { 0.0, 1.0, -1.0, 0.0 }; + static bool init = 0; + + m_cassette->change_state(BIT(data, 2) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR ); + m_cassette->output(levels[data & 3]); + m_cassette_data = false; + + m_mode = BIT(data, 3); + + if (!init) + { + init = 1; + static int16_t speaker_levels[4] = { 0, -32767, 0, 32767 }; + m_speaker->set_levels(4, speaker_levels); + + } +} + +READ8_MEMBER( meritum_state::keyboard_r ) +{ + u8 i, result = 0; + + for (i = 0; i < 8; i++) + if (BIT(offset, i)) + result |= m_io_keyboard[i]->read(); + + return result; +} + +void meritum_state::machine_start() +{ + m_cassette_data_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(meritum_state::cassette_data_callback),this)); + m_cassette_data_timer->adjust( attotime::zero, 0, attotime::from_hz(11025) ); +} + +void meritum_state::machine_reset() +{ + m_cassette_data = false; + m_size_store = true; + m_mode = false; +} + +#define CMD_TYPE_OBJECT_CODE 0x01 +#define CMD_TYPE_TRANSFER_ADDRESS 0x02 +#define CMD_TYPE_END_OF_PARTITIONED_DATA_SET_MEMBER 0x04 +#define CMD_TYPE_LOAD_MODULE_HEADER 0x05 +#define CMD_TYPE_PARTITIONED_DATA_SET_HEADER 0x06 +#define CMD_TYPE_PATCH_NAME_HEADER 0x07 +#define CMD_TYPE_ISAM_DIRECTORY_ENTRY 0x08 +#define CMD_TYPE_END_OF_ISAM_DIRECTORY_ENTRY 0x0a +#define CMD_TYPE_PDS_DIRECTORY_ENTRY 0x0c +#define CMD_TYPE_END_OF_PDS_DIRECTORY_ENTRY 0x0e +#define CMD_TYPE_YANKED_LOAD_BLOCK 0x10 +#define CMD_TYPE_COPYRIGHT_BLOCK 0x1f + +/*************************************************************************** + IMPLEMENTATION +***************************************************************************/ + +QUICKLOAD_LOAD_MEMBER( meritum_state, trs80_cmd ) +{ + address_space &program = m_maincpu->space(AS_PROGRAM); + + uint8_t type, length; + uint8_t data[0x100]; + uint8_t addr[2]; + void *ptr; + + while (!image.image_feof()) + { + image.fread( &type, 1); + image.fread( &length, 1); + + length -= 2; + int block_length = length ? length : 256; + + switch (type) + { + case CMD_TYPE_OBJECT_CODE: + { + image.fread( &addr, 2); + uint16_t address = (addr[1] << 8) | addr[0]; + ptr = program.get_write_ptr(address); + image.fread( ptr, block_length); + } + break; + + case CMD_TYPE_TRANSFER_ADDRESS: + { + image.fread( &addr, 2); + uint16_t address = (addr[1] << 8) | addr[0]; + m_maincpu->set_state_int(Z80_PC, address); + } + break; + + case CMD_TYPE_LOAD_MODULE_HEADER: + image.fread( &data, block_length); + break; + + case CMD_TYPE_COPYRIGHT_BLOCK: + image.fread( &data, block_length); + break; + + default: + image.fread( &data, block_length); + logerror("/CMD unsupported block type %u!\n", type); + } + } + + return image_init_result::PASS; +} + + +/**************************** F4 CHARACTER DISPLAYER ***********************************************************/ +static const gfx_layout meritum_charlayout = +{ + 6, 11, /* 8 x 16 characters */ + 256, /* 256 characters */ + 1, /* 1 bits per pixel */ + { 0 }, /* no bitplanes */ + /* x offsets */ + { 2, 3, 4, 5, 6, 7 }, + /* y offsets */ + { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8 }, + 8*16 /* every char takes 16 bytes (unused scanlines are blank) */ +}; + +static GFXDECODE_START(gfx_meritum) + GFXDECODE_ENTRY( "chargen", 0, meritum_charlayout, 0, 1 ) +GFXDECODE_END + + + +MACHINE_CONFIG_START(meritum_state::meritum) + /* basic machine hardware */ + MCFG_DEVICE_ADD("maincpu", Z80, 10.6445_MHz_XTAL / 6) + MCFG_DEVICE_PROGRAM_MAP(mem_map) + MCFG_DEVICE_IO_MAP(io_map) + + /* video hardware */ + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_RAW_PARAMS(10.6445_MHz_XTAL, 672, 0, 384, 264, 0, 192) + MCFG_SCREEN_UPDATE_DRIVER(meritum_state, screen_update_meritum) + MCFG_SCREEN_PALETTE("palette") + + MCFG_DEVICE_ADD("gfxdecode", GFXDECODE, "palette", gfx_meritum) + MCFG_PALETTE_ADD_MONOCHROME("palette") + + /* sound hardware */ + SPEAKER(config, "mono").front_center(); + SPEAKER_SOUND(config, "speaker").add_route(ALL_OUTPUTS, "mono", 0.50); + WAVE(config, "wave", "cassette").add_route(ALL_OUTPUTS, "mono", 0.05); + + /* devices */ + MCFG_CASSETTE_ADD("cassette") + MCFG_QUICKLOAD_ADD("quickload", meritum_state, trs80_cmd, "cmd", 1.0) +MACHINE_CONFIG_END + +/*************************************************************************** + + Game driver(s) + +***************************************************************************/ + + +ROM_START( meritum) + ROM_REGION(0x3800, "maincpu",0) + ROM_LOAD( "01.bin", 0x0000, 0x0800, CRC(ed705a47) SHA1(dae8b14eb2ddb2a8b4458215180ebc0fb781816a)) + ROM_LOAD( "02.bin", 0x0800, 0x0800, CRC(ac297d99) SHA1(ccf31d3f9d02c3b68a0ee3be4984424df0e83ab0)) + ROM_LOAD( "03.bin", 0x1000, 0x0800, CRC(a21d0d62) SHA1(6dfdf3806ed2b6502e09a1b6922f21494134cc05)) + ROM_LOAD( "04.bin", 0x1800, 0x0800, CRC(3610bdda) SHA1(602f0ba1e1267f24620f993acac019ac6342a594)) + ROM_LOAD( "05.bin", 0x2000, 0x0800, CRC(461fbf0d) SHA1(bd19187dd992168af43bd68055343d515f152624)) + ROM_LOAD( "06.bin", 0x2800, 0x0800, CRC(ed547445) SHA1(20102de89a3ee4a65366bc2d62be94da984a156b)) + ROM_LOAD( "07.bin", 0x3000, 0x0800, CRC(044b1459) SHA1(faace7353ffbef6587b1b9e7f8b312e0892e3427)) + + ROM_REGION(0x1000, "chargen", ROMREGION_INVERT) + ROM_LOAD( "chargen.bin", 0x0000, 0x1000, CRC(3dfc6439) SHA1(6e45a27f68c3491c403b4eafe45a108f348dd2fd)) +ROM_END + +ROM_START( meritum_net ) + ROM_REGION(0x3800, "maincpu",0) + ROM_LOAD( "01_447_m07_015m.bin", 0x0000, 0x0800, CRC(6d30cb49) SHA1(558241340a84eebcbbf8d92540e028e9164b6f8a)) + ROM_LOAD( "02_440_m08_01.bin", 0x0800, 0x0800, CRC(ac297d99) SHA1(ccf31d3f9d02c3b68a0ee3be4984424df0e83ab0)) + ROM_LOAD( "03_440_m09_015m.bin", 0x1000, 0x0800, CRC(88e267da) SHA1(9cb8626801f8e969f35291de43c1b643c809a3c3)) + ROM_LOAD( "04_447_m10_015m.bin", 0x1800, 0x0800, CRC(e51991e4) SHA1(a7d42436da1af405970f9f99ab34b6d9abd05adf)) + ROM_LOAD( "05_440_m11_02.bin", 0x2000, 0x0800, CRC(461fbf0d) SHA1(bd19187dd992168af43bd68055343d515f152624)) + ROM_LOAD( "06_440_m12_01.bin", 0x2800, 0x0800, CRC(ed547445) SHA1(20102de89a3ee4a65366bc2d62be94da984a156b)) + ROM_LOAD( "07_447_m13_015m.bin", 0x3000, 0x0800, CRC(789f6964) SHA1(9b2231ca7ffd82bbca1f53988a7df833290ddbf2)) + + ROM_REGION(0x1000, "chargen", ROMREGION_INVERT) + ROM_LOAD( "char.bin", 0x0000, 0x1000, CRC(2c09a5a7) SHA1(146891b3ddfc2de95e6a5371536394a657880054)) +ROM_END + + +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +COMP( 1985, meritum, 0, trs80l2, meritum, meritum, meritum_state, empty_init, "Mera-Elzab", "Meritum I (Model 2)", 0 ) +COMP( 1985, meritum_net, meritum, 0, meritum, meritum, meritum_state, empty_init, "Mera-Elzab", "Meritum I (Model 2) (network)", 0 ) diff --git a/src/mame/drivers/trs80.cpp b/src/mame/drivers/trs80.cpp index 546e7aeb630..d51ed215686 100644 --- a/src/mame/drivers/trs80.cpp +++ b/src/mame/drivers/trs80.cpp @@ -36,17 +36,13 @@ Interrupts: IRQ mode 1 NMI -Printer: Level II usually 37e8; System80 uses port FD; Model 4 uses port F8. -Uart: TR1602, equivalent to the uart used in the Exidy Sorcerer. +Printer: Level II usually 37e8; System80 uses port FD. + System80 has non-addressable dip switches to set the UART control register. System80 and LNW80 have non-addressable links to set the baud rate. Receive and Transmit clocks are tied together. -It is assumed that the TRS80L2 UART setup is identical to the System80, apart from the address ports used. -Due to the above, the only working emulated UART is for the Model 3. Cassette baud rates: Model I level I - 250 baud Model I level II and all clones - 500 baud - Model III/4 - 500 and 1500 baud selectable at boot time - - When it says "Cass?" press L for 500 baud, or Enter otherwise. LNW-80 - 500 baud @1.77MHz and 1000 baud @4MHz. I/O ports @@ -72,26 +68,12 @@ F9: F8: - UART data (read) status (write) on a system-80 -- Write to printer (Model III/4) -- Read printer status (Model III/4) - -EB: -- UART data (read and write) on a Model III/4 - -EA: -- UART status (read and write) on a Model III/4 -E9: -- UART Configuration jumpers (read) on a Model III/4 -- Set baud rate (Model III/4) +Shift and Right-arrow will enable 32 cpl, if the hardware allows it. -E8: -- UART Modem Status register (read) on a Model III/4 -- UART Master Reset (write) on a Model III/4 - -Model 4 - C0-CF = hard drive (optional) - - 90-93 write sound (optional) - - 80-8F hires graphics (optional) +About the system80 - Asian version of trs80l2, known as EACA Video Genie. In USA called + PMC-80, in South Africa called TRZ-80, and Dick Smith imported them to Australia and + New Zealand as the System 80. The Hungarian version is the ht1080z. About the ht1080z - This was made for schools in Hungary. Each comes with a BASIC extension roms which activated Hungarian features. To activate - start emulation - enter SYSTEM @@ -101,24 +83,8 @@ About the ht1080z - This was made for schools in Hungary. Each comes with a BASI About the RTC - The time is incremented while ever the cursor is flashing. It is stored in a series of bytes in the computer's work area. The bytes are in a certain order, this is: - seconds, minutes, hours, year, day, month. On a model 1, the seconds are stored at - 0x4041, while on the model 4 it is 0x4217. A reboot always sets the time to zero. - -Model 4 memory organisation - - Mode 0: ROM=0-37E7 and 37EA-3FFF; Printer=37E8-37E9; Keyboard=3800-3BFF; Video=3C00-3FFF - Mode 1: Keyboard and Video as above; 0-3FFF read=ROM and write=RAM - Mode 2: Keyboard=F400-F7FF; Video=F800-FFFF; the rest is RAM - Mode 3: All RAM - In the "maincpu" memory map, the first 64k is given to the ROM, keyboard, printer and video, - while the second 64k is RAM that is switched in as needed. The area from 4800-FFFF - is considered a "black hole", any writes to there will disappear. - The video is organised as 2 banks of 0x400 bytes, except in Mode 2 where it becomes contiguous. - -Model 4P - is the same as Model 4 except: - - ROM is only 0000-0FFF, while 1000-37FF is given over to RAM - - There is no cassette support in hardware. - -*************************************************************************** + seconds, minutes, hours, year, day, month. The seconds are stored at 0x4041. + A reboot always sets the time to zero. Not dumped (to our knowledge): TRS80 Japanese bios @@ -131,11 +97,45 @@ Not emulated: TRS80 Japanese kana/ascii switch and alternate keyboard TRS80 Model III/4 Hard drive, Graphics board, Alternate Character set LNW80 1.77 / 4.0 MHz switch (this is a physical switch) + Radionic has 16 colours with a byte at 350B controlling the operation. See manual. Virtual floppy disk formats are JV1, JV3, and DMK. Only the JV1 is emulated. -There don't seem to be any JV1 boot disks for Model III/4. -***************************************************************************/ +******************************************************************************************************** + +To Do / Status: +-------------- + +For those machines that allow it, add cass2 as an image device and hook it up. + +trs80: works + +trs80l2: works + expansion-box to be slotified + +sys80: works + investigate expansion-box + add 32 / 64 cpl switch + +ht1080z works + add AY-3-8910 + investigate expansion-box + +radionic: works + floppy not working (@6C0, DRQ never gets set) + add colour + expansion-box? + uart? + add i8255 + when pasting, upper and lower case are reversed + +lnw80: works + add 1.77 / 4 MHz switch + find out if it really did support 32-cpl mode or not + hi-res and colour are coded but do not work + investigate expansion-box + +*******************************************************************************************************/ #include "emu.h" #include "includes/trs80.h" @@ -147,11 +147,11 @@ There don't seem to be any JV1 boot disks for Model III/4. #include "formats/dmk_dsk.h" -void trs80_state::trs80_map(address_map &map) +void trs80_state::trs80_mem(address_map &map) { map(0x0000, 0x0fff).rom(); - map(0x3800, 0x38ff).r(FUNC(trs80_state::trs80_keyboard_r)); - map(0x3c00, 0x3fff).rw(FUNC(trs80_state::trs80_videoram_r), FUNC(trs80_state::trs80_videoram_w)).share("videoram"); + map(0x3800, 0x3bff).r(FUNC(trs80_state::keyboard_r)); + map(0x3c00, 0x3fff).ram().share(m_p_videoram); map(0x4000, 0x7fff).ram(); } @@ -159,185 +159,79 @@ void trs80_state::trs80_io(address_map &map) { map.global_mask(0xff); map.unmap_value_high(); - map(0xff, 0xff).rw(FUNC(trs80_state::trs80_ff_r), FUNC(trs80_state::trs80_ff_w)); + map(0xff, 0xff).rw(FUNC(trs80_state::port_ff_r), FUNC(trs80_state::port_ff_w)); } -void trs80_state::model1_map(address_map &map) +void trs80_state::m1_mem(address_map &map) { map(0x0000, 0x377f).rom(); // sys80,ht1080 needs up to 375F map(0x37de, 0x37de).rw(FUNC(trs80_state::sys80_f9_r), FUNC(trs80_state::sys80_f8_w)); - map(0x37df, 0x37df).rw("uart", FUNC(ay31015_device::receive), FUNC(ay31015_device::transmit)); - map(0x37e0, 0x37e3).rw(FUNC(trs80_state::trs80_irq_status_r), FUNC(trs80_state::trs80_motor_w)); - map(0x37e4, 0x37e7).w(FUNC(trs80_state::trs80_cassunit_w)); - map(0x37e8, 0x37eb).rw(FUNC(trs80_state::trs80_printer_r), FUNC(trs80_state::trs80_printer_w)); - map(0x37ec, 0x37ec).r(FUNC(trs80_state::trs80_wd179x_r)); + map(0x37df, 0x37df).rw(m_uart, FUNC(ay31015_device::receive), FUNC(ay31015_device::transmit)); + map(0x37e0, 0x37e3).rw(FUNC(trs80_state::irq_status_r), FUNC(trs80_state::motor_w)); + map(0x37e4, 0x37e7).w(FUNC(trs80_state::cassunit_w)); + map(0x37e8, 0x37eb).rw(FUNC(trs80_state::printer_r), FUNC(trs80_state::printer_w)); + map(0x37ec, 0x37ec).r(FUNC(trs80_state::wd179x_r)); map(0x37ec, 0x37ec).w(m_fdc, FUNC(fd1793_device::cmd_w)); map(0x37ed, 0x37ed).rw(m_fdc, FUNC(fd1793_device::track_r), FUNC(fd1793_device::track_w)); map(0x37ee, 0x37ee).rw(m_fdc, FUNC(fd1793_device::sector_r), FUNC(fd1793_device::sector_w)); map(0x37ef, 0x37ef).rw(m_fdc, FUNC(fd1793_device::data_r), FUNC(fd1793_device::data_w)); - map(0x3800, 0x38ff).mirror(0x300).r(FUNC(trs80_state::trs80_keyboard_r)); - map(0x3c00, 0x3fff).rw(FUNC(trs80_state::trs80_videoram_r), FUNC(trs80_state::trs80_videoram_w)).share("videoram"); + map(0x3800, 0x3bff).r(FUNC(trs80_state::keyboard_r)); + map(0x3c00, 0x3fff).ram().share(m_p_videoram); map(0x4000, 0xffff).ram(); } -void trs80_state::model1_io(address_map &map) +void trs80_state::m1_io(address_map &map) { map.global_mask(0xff); map.unmap_value_high(); - map(0xff, 0xff).rw(FUNC(trs80_state::trs80_ff_r), FUNC(trs80_state::trs80_ff_w)); + map(0xe8, 0xe8).rw(FUNC(trs80_state::port_e8_r), FUNC(trs80_state::port_e8_w)); + map(0xe9, 0xe9).portr("E9").w(m_brg, FUNC(com8116_device::stt_str_w)); + map(0xea, 0xea).rw(FUNC(trs80_state::port_ea_r), FUNC(trs80_state::port_ea_w)); + map(0xeb, 0xeb).rw(m_uart, FUNC(ay31015_device::receive), FUNC(ay31015_device::transmit)); + map(0xff, 0xff).rw(FUNC(trs80_state::port_ff_r), FUNC(trs80_state::port_ff_w)); } void trs80_state::sys80_io(address_map &map) { map.global_mask(0xff); map.unmap_value_high(); - map(0xf8, 0xf8).r("uart", FUNC(ay31015_device::receive)).w(FUNC(trs80_state::sys80_f8_w)); - map(0xf9, 0xf9).r(FUNC(trs80_state::sys80_f9_r)).w("uart", FUNC(ay31015_device::transmit)); - map(0xfd, 0xfd).rw(FUNC(trs80_state::trs80_printer_r), FUNC(trs80_state::trs80_printer_w)); + map(0xf8, 0xf8).r(m_uart, FUNC(ay31015_device::receive)).w(FUNC(trs80_state::sys80_f8_w)); + map(0xf9, 0xf9).r(FUNC(trs80_state::sys80_f9_r)).w(m_uart, FUNC(ay31015_device::transmit)); + map(0xfd, 0xfd).rw(FUNC(trs80_state::printer_r), FUNC(trs80_state::printer_w)); map(0xfe, 0xfe).w(FUNC(trs80_state::sys80_fe_w)); - map(0xff, 0xff).rw(FUNC(trs80_state::trs80_ff_r), FUNC(trs80_state::trs80_ff_w)); + map(0xff, 0xff).rw(FUNC(trs80_state::port_ff_r), FUNC(trs80_state::port_ff_w)); } -void trs80_state::lnw80_map(address_map &map) +void trs80_state::lnw80_mem(address_map &map) { + map(0x0000, 0x3fff).m(m_lnw_bank, FUNC(address_map_bank_device::amap8)); map(0x4000, 0xffff).ram(); } -void trs80_state::lnw80_io(address_map &map) -{ - map.global_mask(0xff); - map.unmap_value_high(); - map(0xe8, 0xe8).rw(FUNC(trs80_state::trs80m4_e8_r), FUNC(trs80_state::trs80m4_e8_w)); - map(0xe9, 0xe9).portr("E9"); - map(0xea, 0xea).rw(FUNC(trs80_state::trs80m4_ea_r), FUNC(trs80_state::trs80m4_ea_w)); - map(0xeb, 0xeb).rw("uart", FUNC(ay31015_device::receive), FUNC(ay31015_device::transmit)); - map(0xfe, 0xfe).rw(FUNC(trs80_state::lnw80_fe_r), FUNC(trs80_state::lnw80_fe_w)); - map(0xff, 0xff).rw(FUNC(trs80_state::trs80_ff_r), FUNC(trs80_state::trs80_ff_w)); -} - -void trs80_state::model3_map(address_map &map) +void trs80_state::lnw_banked_mem(address_map &map) { + map(0x0000, 0x2fff).rom().region("maincpu", 0); + map(0x37e0, 0x37e3).rw(FUNC(trs80_state::irq_status_r), FUNC(trs80_state::motor_w)); + map(0x37e8, 0x37eb).rw(FUNC(trs80_state::printer_r), FUNC(trs80_state::printer_w)); + map(0x37ec, 0x37ec).r(FUNC(trs80_state::wd179x_r)); + map(0x37ec, 0x37ec).w(m_fdc, FUNC(fd1793_device::cmd_w)); + map(0x37ed, 0x37ed).rw(m_fdc, FUNC(fd1793_device::track_r), FUNC(fd1793_device::track_w)); + map(0x37ee, 0x37ee).rw(m_fdc, FUNC(fd1793_device::sector_r), FUNC(fd1793_device::sector_w)); + map(0x37ef, 0x37ef).rw(m_fdc, FUNC(fd1793_device::data_r), FUNC(fd1793_device::data_w)); + map(0x3800, 0x3bff).r(FUNC(trs80_state::keyboard_r)); + map(0x3c00, 0x3fff).ram().share(m_p_videoram); + map(0x4000, 0x7fff).ram().share(m_p_gfxram).region("gfx2", 0); } -void trs80_state::model3_io(address_map &map) -{ - map.global_mask(0xff); - map.unmap_value_high(); - map(0xe0, 0xe3).rw(FUNC(trs80_state::trs80m4_e0_r), FUNC(trs80_state::trs80m4_e0_w)); - map(0xe4, 0xe4).rw(FUNC(trs80_state::trs80m4_e4_r), FUNC(trs80_state::trs80m4_e4_w)); - map(0xe8, 0xe8).rw(FUNC(trs80_state::trs80m4_e8_r), FUNC(trs80_state::trs80m4_e8_w)); - map(0xe9, 0xe9).portr("E9").w(FUNC(trs80_state::trs80m4_e9_w)); - map(0xea, 0xea).rw(FUNC(trs80_state::trs80m4_ea_r), FUNC(trs80_state::trs80m4_ea_w)); - map(0xeb, 0xeb).rw("uart", FUNC(ay31015_device::receive), FUNC(ay31015_device::transmit)); - map(0xec, 0xef).rw(FUNC(trs80_state::trs80m4_ec_r), FUNC(trs80_state::trs80m4_ec_w)); - map(0xf0, 0xf0).r(FUNC(trs80_state::trs80_wd179x_r)); - map(0xf0, 0xf0).w(m_fdc, FUNC(fd1793_device::cmd_w)); - map(0xf1, 0xf1).rw(m_fdc, FUNC(fd1793_device::track_r), FUNC(fd1793_device::track_w)); - map(0xf2, 0xf2).rw(m_fdc, FUNC(fd1793_device::sector_r), FUNC(fd1793_device::sector_w)); - map(0xf3, 0xf3).rw(m_fdc, FUNC(fd1793_device::data_r), FUNC(fd1793_device::data_w)); - map(0xf4, 0xf4).w(FUNC(trs80_state::trs80m4_f4_w)); - map(0xf8, 0xfb).rw(FUNC(trs80_state::trs80_printer_r), FUNC(trs80_state::trs80_printer_w)); - map(0xfc, 0xff).rw(FUNC(trs80_state::trs80m4_ff_r), FUNC(trs80_state::trs80m4_ff_w)); -} - -void trs80_state::model4_io(address_map &map) -{ - map.global_mask(0xff); - map.unmap_value_high(); - map(0x84, 0x87).w(FUNC(trs80_state::trs80m4_84_w)); - map(0x88, 0x89).w(FUNC(trs80_state::trs80m4_88_w)); - map(0x90, 0x93).w(FUNC(trs80_state::trs80m4_90_w)); - map(0xe0, 0xe3).rw(FUNC(trs80_state::trs80m4_e0_r), FUNC(trs80_state::trs80m4_e0_w)); - map(0xe4, 0xe4).rw(FUNC(trs80_state::trs80m4_e4_r), FUNC(trs80_state::trs80m4_e4_w)); - map(0xe8, 0xe8).rw(FUNC(trs80_state::trs80m4_e8_r), FUNC(trs80_state::trs80m4_e8_w)); - map(0xe9, 0xe9).portr("E9").w(FUNC(trs80_state::trs80m4_e9_w)); - map(0xea, 0xea).rw(FUNC(trs80_state::trs80m4_ea_r), FUNC(trs80_state::trs80m4_ea_w)); - map(0xeb, 0xeb).rw("uart", FUNC(ay31015_device::receive), FUNC(ay31015_device::transmit)); - map(0xec, 0xef).rw(FUNC(trs80_state::trs80m4_ec_r), FUNC(trs80_state::trs80m4_ec_w)); - map(0xf0, 0xf0).r(FUNC(trs80_state::trs80_wd179x_r)); - map(0xf0, 0xf0).w(m_fdc, FUNC(fd1793_device::cmd_w)); - map(0xf1, 0xf1).rw(m_fdc, FUNC(fd1793_device::track_r), FUNC(fd1793_device::track_w)); - map(0xf2, 0xf2).rw(m_fdc, FUNC(fd1793_device::sector_r), FUNC(fd1793_device::sector_w)); - map(0xf3, 0xf3).rw(m_fdc, FUNC(fd1793_device::data_r), FUNC(fd1793_device::data_w)); - map(0xf4, 0xf4).w(FUNC(trs80_state::trs80m4_f4_w)); - map(0xf8, 0xfb).rw(FUNC(trs80_state::trs80_printer_r), FUNC(trs80_state::trs80_printer_w)); - map(0xfc, 0xff).rw(FUNC(trs80_state::trs80m4_ff_r), FUNC(trs80_state::trs80m4_ff_w)); -} - -void trs80_state::model4p_io(address_map &map) -{ - map.global_mask(0xff); - map.unmap_value_high(); - map(0x84, 0x87).w(FUNC(trs80_state::trs80m4_84_w)); - map(0x88, 0x89).w(FUNC(trs80_state::trs80m4_88_w)); - map(0x90, 0x93).w(FUNC(trs80_state::trs80m4_90_w)); - map(0x9c, 0x9f).w(FUNC(trs80_state::trs80m4p_9c_w)); - map(0xe0, 0xe3).rw(FUNC(trs80_state::trs80m4_e0_r), FUNC(trs80_state::trs80m4_e0_w)); - map(0xe4, 0xe4).rw(FUNC(trs80_state::trs80m4_e4_r), FUNC(trs80_state::trs80m4_e4_w)); - map(0xe8, 0xe8).rw(FUNC(trs80_state::trs80m4_e8_r), FUNC(trs80_state::trs80m4_e8_w)); - map(0xe9, 0xe9).portr("E9").w(FUNC(trs80_state::trs80m4_e9_w)); - map(0xea, 0xea).rw(FUNC(trs80_state::trs80m4_ea_r), FUNC(trs80_state::trs80m4_ea_w)); - map(0xeb, 0xeb).rw("uart", FUNC(ay31015_device::receive), FUNC(ay31015_device::transmit)); - map(0xec, 0xef).rw(FUNC(trs80_state::trs80m4_ec_r), FUNC(trs80_state::trs80m4_ec_w)); - map(0xf0, 0xf0).r(FUNC(trs80_state::trs80_wd179x_r)); - map(0xf0, 0xf0).w(m_fdc, FUNC(fd1793_device::cmd_w)); - map(0xf1, 0xf1).rw(m_fdc, FUNC(fd1793_device::track_r), FUNC(fd1793_device::track_w)); - map(0xf2, 0xf2).rw(m_fdc, FUNC(fd1793_device::sector_r), FUNC(fd1793_device::sector_w)); - map(0xf3, 0xf3).rw(m_fdc, FUNC(fd1793_device::data_r), FUNC(fd1793_device::data_w)); - map(0xf4, 0xf4).w(FUNC(trs80_state::trs80m4_f4_w)); - map(0xf8, 0xfb).rw(FUNC(trs80_state::trs80_printer_r), FUNC(trs80_state::trs80_printer_w)); - map(0xfc, 0xff).rw(FUNC(trs80_state::trs80m4_ff_r), FUNC(trs80_state::trs80m4_ff_w)); -} - -void trs80_state::meritum_map(address_map &map) -{ - map(0x0000, 0x37ff).rom(); - map(0x3800, 0x38ff).mirror(0x300).r(FUNC(trs80_state::trs80_keyboard_r)); - map(0x3c00, 0x3fff).rw(FUNC(trs80_state::trs80_videoram_r), FUNC(trs80_state::trs80_videoram_w)).share("videoram"); - map(0x4000, 0xffff).ram(); -} - -void trs80_state::meritum_io(address_map &map) +void trs80_state::lnw80_io(address_map &map) { map.global_mask(0xff); map.unmap_value_high(); - // There are specific writes to ports 03, F3, F7, F8, FA, FB, FD - // so perhaps this system uses devices at these locations. - // The disk input expects values that are different to the usual, - // eg. port F0 should be 5, port F2 should have bit 3 set. - //AM_RANGE(0x03, 0x03) unknown - map(0xf0, 0xf0).r(FUNC(trs80_state::trs80_wd179x_r)); - map(0xf0, 0xf0).w(m_fdc, FUNC(fd1793_device::cmd_w)); - map(0xf1, 0xf1).rw(m_fdc, FUNC(fd1793_device::track_r), FUNC(fd1793_device::track_w)); - map(0xf2, 0xf2).rw(m_fdc, FUNC(fd1793_device::sector_r), FUNC(fd1793_device::sector_w)); - map(0xf3, 0xf3).rw(m_fdc, FUNC(fd1793_device::data_r), FUNC(fd1793_device::data_w)); - map(0xf4, 0xf4).w(FUNC(trs80_state::trs80m4_f4_w)); - map(0xf8, 0xfb).rw(FUNC(trs80_state::trs80_printer_r), FUNC(trs80_state::trs80_printer_w)); - //AM_RANGE(0xfc, 0xfd) unknown - map(0xff, 0xff).rw(FUNC(trs80_state::trs80_ff_r), FUNC(trs80_state::trs80_ff_w)); + m1_io(map); + map(0xe9, 0xe9).nopw(); + map(0xfe, 0xfe).rw(FUNC(trs80_state::lnw80_fe_r), FUNC(trs80_state::lnw80_fe_w)); } -void trs80_state::cp500_io(address_map &map) -{ - map.global_mask(0xff); - map.unmap_value_high(); - map(0xe0, 0xe3).rw(FUNC(trs80_state::trs80m4_e0_r), FUNC(trs80_state::trs80m4_e0_w)); - map(0xe4, 0xe4).rw(FUNC(trs80_state::trs80m4_e4_r), FUNC(trs80_state::trs80m4_e4_w)); - map(0xe8, 0xe8).rw(FUNC(trs80_state::trs80m4_e8_r), FUNC(trs80_state::trs80m4_e8_w)); - map(0xe9, 0xe9).portr("E9").w(FUNC(trs80_state::trs80m4_e9_w)); - map(0xea, 0xea).rw(FUNC(trs80_state::trs80m4_ea_r), FUNC(trs80_state::trs80m4_ea_w)); - map(0xeb, 0xeb).rw("uart", FUNC(ay31015_device::receive), FUNC(ay31015_device::transmit)); - map(0xec, 0xef).rw(FUNC(trs80_state::trs80m4_ec_r), FUNC(trs80_state::trs80m4_ec_w)); - map(0xf0, 0xf0).r(FUNC(trs80_state::trs80_wd179x_r)); - map(0xf0, 0xf0).w(m_fdc, FUNC(fd1793_device::cmd_w)); - map(0xf1, 0xf1).rw(m_fdc, FUNC(fd1793_device::track_r), FUNC(fd1793_device::track_w)); - map(0xf2, 0xf2).rw(m_fdc, FUNC(fd1793_device::sector_r), FUNC(fd1793_device::sector_w)); - map(0xf3, 0xf3).rw(m_fdc, FUNC(fd1793_device::data_r), FUNC(fd1793_device::data_w)); - map(0xf4, 0xf4).w(FUNC(trs80_state::trs80m4_f4_w)); - map(0xf4, 0xf7).r(FUNC(trs80_state::cp500_a11_flipflop_toggle)); - map(0xf8, 0xfb).rw(FUNC(trs80_state::trs80_printer_r), FUNC(trs80_state::trs80_printer_w)); - map(0xfc, 0xff).rw(FUNC(trs80_state::trs80m4_ff_r), FUNC(trs80_state::trs80m4_ff_w)); -} /************************************************************************** w/o SHIFT with SHIFT @@ -382,13 +276,7 @@ NB4: when it was added a 15-key keypad, there were ***************************************************************************/ static INPUT_PORTS_START( trs80 ) - PORT_START("CONFIG") /* IN0 */ - PORT_CONFNAME( 0x80, 0x00, "Floppy Disc Drives") - PORT_CONFSETTING( 0x00, DEF_STR( Off ) ) - PORT_CONFSETTING( 0x80, DEF_STR( On ) ) - PORT_BIT(0x7f, 0x7f, IPT_UNUSED) - - PORT_START("LINE0") /* KEY ROW 0 */ + PORT_START("LINE0") PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("@") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@') PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') @@ -398,7 +286,7 @@ static INPUT_PORTS_START( trs80 ) PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') - PORT_START("LINE1") /* KEY ROW 1 */ + PORT_START("LINE1") PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') @@ -408,7 +296,7 @@ static INPUT_PORTS_START( trs80 ) PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') - PORT_START("LINE2") /* KEY ROW 2 */ + PORT_START("LINE2") PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') @@ -418,20 +306,13 @@ static INPUT_PORTS_START( trs80 ) PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') - PORT_START("LINE3") /* KEY ROW 3 */ + PORT_START("LINE3") PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') - /* on Model I and Model III keyboards, there are only 53 keys (+ 12 keypad keys) and these are not connected: - on Model I, they produce arrows and '_', on Model III either produce garbage or overlap with other keys; - on Model 4 (which has a 15-key with 3 function keys) here are mapped 'F1', 'F2', 'F3' */ - PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("(n/c)") - PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("(n/c)") - PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("(n/c)") - PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("(n/c)") - PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("(n/c)") - - PORT_START("LINE4") /* KEY ROW 4 */ + PORT_BIT(0xF8, 0x00, IPT_UNUSED) + + PORT_START("LINE4") PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) @@ -441,7 +322,7 @@ static INPUT_PORTS_START( trs80 ) PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) - PORT_START("LINE5") /* KEY ROW 5 */ + PORT_START("LINE5") PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME(": *") PORT_CODE(KEYCODE_MINUS) PORT_CHAR(':') PORT_CHAR('*') @@ -451,7 +332,7 @@ static INPUT_PORTS_START( trs80 ) PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') - PORT_START("LINE6") /* KEY ROW 6 */ + PORT_START("LINE6") PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("Clear") PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(F8)) // 3rd line, 1st key from right PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(F9)) // 1st line, 1st key from right @@ -462,20 +343,20 @@ static INPUT_PORTS_START( trs80 ) PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') - PORT_START("LINE7") /* KEY ROW 7 */ - PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("Left Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) - /* These keys are only on a Model 4. The one marked CTL seems to be another shift key (4 in total). */ - PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("Right Shift") PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) - PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("CTL") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2) - PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("Caps") PORT_CODE(KEYCODE_CAPSLOCK) - PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) - PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) - PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) - PORT_BIT(0x80, 0x00, IPT_UNUSED) + PORT_START("LINE7") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("Left Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) + PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("Control") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) + PORT_BIT(0xee, 0x00, IPT_UNUSED) INPUT_PORTS_END -static INPUT_PORTS_START( trs80m3 ) +static INPUT_PORTS_START(trs80l2) PORT_INCLUDE (trs80) + PORT_START("CONFIG") + PORT_CONFNAME( 0x80, 0x00, "Floppy Disc Drives") + PORT_CONFSETTING( 0x00, DEF_STR( Off ) ) + PORT_CONFSETTING( 0x80, DEF_STR( On ) ) + PORT_BIT(0x7f, 0x7f, IPT_UNUSED) + PORT_START("E9") // these are the power-on uart settings PORT_BIT(0x07, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_DIPNAME( 0x88, 0x08, "Parity") @@ -492,6 +373,21 @@ static INPUT_PORTS_START( trs80m3 ) PORT_DIPSETTING( 0x60, "8") INPUT_PORTS_END +static INPUT_PORTS_START(sys80) + PORT_INCLUDE (trs80l2) + PORT_START("BAUD") + PORT_DIPNAME( 0xff, 0x06, "Baud Rate") + PORT_DIPSETTING( 0x00, "110") + PORT_DIPSETTING( 0x01, "300") + PORT_DIPSETTING( 0x02, "600") + PORT_DIPSETTING( 0x03, "1200") + PORT_DIPSETTING( 0x04, "2400") + PORT_DIPSETTING( 0x05, "4800") + PORT_DIPSETTING( 0x06, "9600") + PORT_DIPSETTING( 0x07, "19200") +INPUT_PORTS_END + + /**************************** F4 CHARACTER DISPLAYER ***********************************************************/ static const gfx_layout trs80_charlayout = @@ -520,19 +416,6 @@ static const gfx_layout ht1080z_charlayout = 8*16 /* every char takes 16 bytes */ }; -static const gfx_layout trs80m4_charlayout = -{ - 8, 8, /* 8 x 8 characters */ - 256, /* 256 characters */ - 1, /* 1 bits per pixel */ - { 0 }, /* no bitplanes */ - /* x offsets */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, - /* y offsets */ - { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 }, - 8*8 /* every char takes 8 bytes */ -}; - static const gfx_layout lnw80_charlayout = { 8, 8, /* 8 x 8 characters */ @@ -559,19 +442,6 @@ static const gfx_layout radionic_charlayout = 8*8 /* every char takes 16 bytes */ }; -static const gfx_layout meritum_charlayout = -{ - 6, 11, /* 8 x 16 characters */ - 256, /* 256 characters */ - 1, /* 1 bits per pixel */ - { 0 }, /* no bitplanes */ - /* x offsets */ - { 2, 3, 4, 5, 6, 7 }, - /* y offsets */ - { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8 }, - 8*16 /* every char takes 16 bytes (unused scanlines are blank) */ -}; - static GFXDECODE_START(gfx_trs80) GFXDECODE_ENTRY( "chargen", 0, trs80_charlayout, 0, 1 ) GFXDECODE_END @@ -580,10 +450,6 @@ static GFXDECODE_START(gfx_ht1080z) GFXDECODE_ENTRY( "chargen", 0, ht1080z_charlayout, 0, 1 ) GFXDECODE_END -static GFXDECODE_START(gfx_trs80m4) - GFXDECODE_ENTRY( "chargen", 0, trs80m4_charlayout, 0, 1 ) -GFXDECODE_END - static GFXDECODE_START(gfx_lnw80) GFXDECODE_ENTRY( "chargen", 0, lnw80_charlayout, 0, 4 ) GFXDECODE_END @@ -592,10 +458,6 @@ static GFXDECODE_START(gfx_radionic) GFXDECODE_ENTRY( "chargen", 0, radionic_charlayout, 0, 1 ) GFXDECODE_END -static GFXDECODE_START(gfx_meritum) - GFXDECODE_ENTRY( "chargen", 0, meritum_charlayout, 0, 1 ) -GFXDECODE_END - FLOPPY_FORMATS_MEMBER( trs80_state::floppy_formats ) FLOPPY_TRS80_FORMAT, @@ -610,9 +472,8 @@ static void trs80_floppies(device_slot_interface &device) MACHINE_CONFIG_START(trs80_state::trs80) // the original model I, level I, with no extras /* basic machine hardware */ - MCFG_DEVICE_ADD("maincpu", Z80, 10.6445_MHz_XTAL / 6) // "a little over 1.774 MHz" - // MAME driver previously configured CPU at "1.796 MHz"; where did this number come from? - MCFG_DEVICE_PROGRAM_MAP(trs80_map) + MCFG_DEVICE_ADD("maincpu", Z80, 10.6445_MHz_XTAL / 6) + MCFG_DEVICE_PROGRAM_MAP(trs80_mem) MCFG_DEVICE_IO_MAP(trs80_io) /* video hardware */ @@ -636,26 +497,28 @@ MACHINE_CONFIG_END MACHINE_CONFIG_START(trs80_state::model1) // model I, level II trs80(config); MCFG_DEVICE_MODIFY("maincpu") - MCFG_DEVICE_PROGRAM_MAP(model1_map) - MCFG_DEVICE_IO_MAP(model1_io) - MCFG_DEVICE_PERIODIC_INT_DRIVER(trs80_state, trs80_rtc_interrupt, 40) + MCFG_DEVICE_PROGRAM_MAP(m1_mem) + MCFG_DEVICE_IO_MAP(m1_io) + MCFG_DEVICE_PERIODIC_INT_DRIVER(trs80_state, rtc_interrupt, 40) /* devices */ MCFG_CASSETTE_MODIFY("cassette") MCFG_CASSETTE_FORMATS(trs80l2_cassette_formats) MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_PLAY) - MCFG_QUICKLOAD_ADD("quickload", trs80_state, trs80_cmd, "cmd", 0.5) + MCFG_QUICKLOAD_ADD("quickload", trs80_state, trs80_cmd, "cmd", 1.0) MCFG_DEVICE_ADD("fdc", FD1793, 4_MHz_XTAL / 4) // todo: should be fd1771 - MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(*this, trs80_state,trs80_fdc_intrq_w)) + MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(*this, trs80_state, intrq_w)) MCFG_FLOPPY_DRIVE_ADD("fdc:0", trs80_floppies, "sssd", trs80_state::floppy_formats) MCFG_FLOPPY_DRIVE_SOUND(true) MCFG_FLOPPY_DRIVE_ADD("fdc:1", trs80_floppies, "sssd", trs80_state::floppy_formats) MCFG_FLOPPY_DRIVE_SOUND(true) MCFG_FLOPPY_DRIVE_ADD("fdc:2", trs80_floppies, "", trs80_state::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) MCFG_FLOPPY_DRIVE_ADD("fdc:3", trs80_floppies, "", trs80_state::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) MCFG_DEVICE_ADD(m_centronics, CENTRONICS, centronics_devices, "printer") MCFG_CENTRONICS_BUSY_HANDLER(WRITELINE("cent_status_in", input_buffer_device, write_bit7)) @@ -667,45 +530,23 @@ MACHINE_CONFIG_START(trs80_state::model1) // model I, level II MCFG_CENTRONICS_OUTPUT_LATCH_ADD("cent_data_out", "centronics") - MCFG_DEVICE_ADD("uart", AY31015, 0) - MCFG_AY31015_RX_CLOCK(0.0) - MCFG_AY31015_TX_CLOCK(0.0) - MCFG_AY31015_AUTO_RDAV(true) -MACHINE_CONFIG_END - -MACHINE_CONFIG_START(trs80_state::model3) - model1(config); - MCFG_DEVICE_MODIFY("maincpu") - MCFG_DEVICE_CLOCK(20.2752_MHz_XTAL / 10) - MCFG_DEVICE_PROGRAM_MAP(model3_map) - MCFG_DEVICE_IO_MAP(model3_io) - MCFG_DEVICE_PERIODIC_INT_DRIVER(trs80_state, trs80_rtc_interrupt, 20.2752_MHz_XTAL / 10 / 67584) - - MCFG_MACHINE_RESET_OVERRIDE(trs80_state, trs80m4) - - MCFG_GFXDECODE_MODIFY("gfxdecode", gfx_trs80m4) - - MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_UPDATE_DRIVER(trs80_state, screen_update_trs80m4) - MCFG_SCREEN_RAW_PARAMS(12.672_MHz_XTAL, 800, 0, 640, 264, 0, 240) -MACHINE_CONFIG_END + COM8116(config, m_brg, 5.0688_MHz_XTAL); // BR1941L + m_brg->fr_handler().set(m_uart, FUNC(ay31015_device::write_rcp)); + m_brg->ft_handler().set(m_uart, FUNC(ay31015_device::write_tcp)); -MACHINE_CONFIG_START(trs80_state::model4) - model3(config); - MCFG_DEVICE_MODIFY("maincpu") - MCFG_DEVICE_IO_MAP(model4_io) -MACHINE_CONFIG_END - -MACHINE_CONFIG_START(trs80_state::model4p) - model3(config); - MCFG_DEVICE_MODIFY("maincpu") - MCFG_DEVICE_IO_MAP(model4p_io) + MCFG_DEVICE_ADD("uart", AY31015, 0) + MCFG_AY51013_READ_SI_CB(READLINE("rs232", rs232_port_device, rxd_r)) + MCFG_AY51013_WRITE_SO_CB(WRITELINE("rs232", rs232_port_device, write_txd)) + //MCFG_AY51013_WRITE_DAV_CB(WRITELINE( , , )) + MCFG_AY51013_AUTO_RDAV(true) + MCFG_DEVICE_ADD("rs232", RS232_PORT, default_rs232_devices, nullptr) MACHINE_CONFIG_END MACHINE_CONFIG_START(trs80_state::sys80) model1(config); MCFG_DEVICE_MODIFY("maincpu") MCFG_DEVICE_IO_MAP(sys80_io) + MCFG_DEVICE_REMOVE("brg") MACHINE_CONFIG_END MACHINE_CONFIG_START(trs80_state::ht1080z) @@ -718,9 +559,17 @@ MACHINE_CONFIG_END MACHINE_CONFIG_START(trs80_state::lnw80) model1(config); MCFG_DEVICE_MODIFY("maincpu") - MCFG_DEVICE_CLOCK(16_MHz_XTAL / 4) // or 16MHz / 9; 4MHz or 1.77MHz operation selected by HI/LO switch - MCFG_DEVICE_PROGRAM_MAP(lnw80_map) + //MCFG_DEVICE_CLOCK(16_MHz_XTAL / 4) // or 16MHz / 9; 4MHz or 1.77MHz operation selected by HI/LO switch + MCFG_DEVICE_CLOCK(16_MHz_XTAL / 9) // need this so cassette can work + MCFG_DEVICE_PROGRAM_MAP(lnw80_mem) MCFG_DEVICE_IO_MAP(lnw80_io) + + ADDRESS_MAP_BANK(config, m_lnw_bank, 0); + m_lnw_bank->set_addrmap(0, &trs80_state::lnw_banked_mem); + m_lnw_bank->set_data_width(8); + m_lnw_bank->set_addr_width(16); + m_lnw_bank->set_stride(0x4000); + MCFG_MACHINE_RESET_OVERRIDE(trs80_state, lnw80) MCFG_GFXDECODE_MODIFY("gfxdecode", gfx_lnw80) @@ -749,23 +598,6 @@ MACHINE_CONFIG_START(trs80_state::radionic) MCFG_GFXDECODE_MODIFY("gfxdecode", gfx_radionic) MACHINE_CONFIG_END -MACHINE_CONFIG_START(trs80_state::meritum) - sys80(config); - MCFG_DEVICE_MODIFY("maincpu") - MCFG_DEVICE_PROGRAM_MAP(meritum_map) - MCFG_DEVICE_IO_MAP(meritum_io) - MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_UPDATE_DRIVER(trs80_state, screen_update_meritum) - MCFG_GFXDECODE_MODIFY("gfxdecode", gfx_meritum) -MACHINE_CONFIG_END - -MACHINE_CONFIG_START(trs80_state::cp500) - model3(config); - MCFG_DEVICE_MODIFY("maincpu") - MCFG_DEVICE_IO_MAP(cp500_io) - - MCFG_MACHINE_RESET_OVERRIDE(trs80_state, cp500) -MACHINE_CONFIG_END /*************************************************************************** @@ -774,15 +606,16 @@ MACHINE_CONFIG_END ***************************************************************************/ ROM_START(trs80) - ROM_REGION(0x10000, "maincpu",0) + ROM_REGION(0x3800, "maincpu",0) ROM_LOAD("level1.rom", 0x0000, 0x1000, CRC(70d06dff) SHA1(20d75478fbf42214381e05b14f57072f3970f765)) - ROM_REGION(0x00400, "chargen",0) + ROM_REGION(0x0400, "chargen",0) ROM_LOAD("trs80m1.chr", 0x0000, 0x0400, CRC(0033f2b9) SHA1(0d2cd4197d54e2e872b515bbfdaa98efe502eda7)) ROM_END + ROM_START(trs80l2) - ROM_REGION(0x10000, "maincpu",0) + ROM_REGION(0x3800, "maincpu",0) ROM_SYSTEM_BIOS(0, "level2", "Radio Shack Level II Basic") ROMX_LOAD("trs80.z33", 0x0000, 0x1000, CRC(37c59db2) SHA1(e8f8f6a4460a6f6755873580be6ff70cebe14969), ROM_BIOS(0)) ROMX_LOAD("trs80.z34", 0x1000, 0x1000, CRC(05818718) SHA1(43c538ca77623af6417474ca5b95fb94205500c1), ROM_BIOS(0)) @@ -792,38 +625,39 @@ ROM_START(trs80l2) ROMX_LOAD("trs80alt.z34",0x1000, 0x1000, CRC(6c791c2d) SHA1(2a38e0a248f6619d38f1a108eea7b95761cf2aee), ROM_BIOS(1)) ROMX_LOAD("trs80alt.zl2",0x2000, 0x1000, CRC(55b3ad13) SHA1(6279f6a68f927ea8628458b278616736f0b3c339), ROM_BIOS(1)) - ROM_REGION(0x00400, "chargen",0) + ROM_REGION(0x0400, "chargen",0) ROM_LOAD("trs80m1.chr", 0x0000, 0x0400, CRC(0033f2b9) SHA1(0d2cd4197d54e2e872b515bbfdaa98efe502eda7)) ROM_END + ROM_START(radionic) - ROM_REGION(0x10000, "maincpu",0) + ROM_REGION(0x4000, "maincpu",0) ROM_LOAD("ep1.bin", 0x0000, 0x1000, CRC(e8908f44) SHA1(7a5a60c3afbeb6b8434737dd302332179a7fca59)) ROM_LOAD("ep2.bin", 0x1000, 0x1000, CRC(46e88fbf) SHA1(a3ca32757f269e09316e1e91ba1502774e2f5155)) ROM_LOAD("ep3.bin", 0x2000, 0x1000, CRC(306e5d66) SHA1(1e1abcfb5b02d4567cf6a81ffc35318723442369)) - ROM_LOAD("ep4.bin", 0x3000, 0x0400, CRC(70f90f26) SHA1(cbee70da04a3efac08e50b8e3a270262c2440120)) - ROM_CONTINUE(0x3000, 0x400) - ROM_CONTINUE(0x3000, 0x600) - ROM_IGNORE(0x200) + ROM_LOAD("ep4.bin", 0x3000, 0x0800, CRC(70f90f26) SHA1(cbee70da04a3efac08e50b8e3a270262c2440120)) + ROM_CONTINUE( 0x3000, 0x0800) - ROM_REGION(0x01000, "chargen",0) + ROM_REGION(0x1000, "chargen",0) ROM_LOAD("trschar.bin", 0x0000, 0x1000, CRC(02e767b6) SHA1(c431fcc6bd04ce2800ca8c36f6f8aeb2f91ce9f7)) ROM_END + ROM_START(sys80) - ROM_REGION(0x10000, "maincpu",0) + ROM_REGION(0x3800, "maincpu",0) ROM_LOAD("sys80rom.1", 0x0000, 0x1000, CRC(8f5214de) SHA1(d8c052be5a2d0ec74433043684791d0554bf203b)) ROM_LOAD("sys80rom.2", 0x1000, 0x1000, CRC(46e88fbf) SHA1(a3ca32757f269e09316e1e91ba1502774e2f5155)) ROM_LOAD("trs80.zl2", 0x2000, 0x1000, CRC(306e5d66) SHA1(1e1abcfb5b02d4567cf6a81ffc35318723442369)) /* This rom turns the system80 into the "blue label" version. SYSTEM then /12288 to activate. */ ROM_LOAD("sys80.ext", 0x3000, 0x0800, CRC(2a851e33) SHA1(dad21ec60973eb66e499fe0ecbd469118826a715)) - ROM_REGION(0x00400, "chargen",0) + ROM_REGION(0x0400, "chargen",0) ROM_LOAD("trs80m1.chr", 0x0000, 0x0400, CRC(0033f2b9) SHA1(0d2cd4197d54e2e872b515bbfdaa98efe502eda7)) ROM_END + ROM_START(lnw80) - ROM_REGION(0x10000, "maincpu",0) + ROM_REGION(0x3800, "maincpu",0) ROM_LOAD("lnw_a.bin", 0x0000, 0x0800, CRC(e09f7e91) SHA1(cd28e72efcfebde6cf1c7dbec4a4880a69e683da)) ROM_LOAD("lnw_a1.bin", 0x0800, 0x0800, CRC(ac297d99) SHA1(ccf31d3f9d02c3b68a0ee3be4984424df0e83ab0)) ROM_LOAD("lnw_b.bin", 0x1000, 0x0800, CRC(c4303568) SHA1(13e3d81c6f0de0e93956fa58c465b5368ea51682)) @@ -831,180 +665,60 @@ ROM_START(lnw80) ROM_LOAD("lnw_c.bin", 0x2000, 0x0800, CRC(2ba025d7) SHA1(232efbe23c3f5c2c6655466ebc0a51cf3697be9b)) ROM_LOAD("lnw_c1.bin", 0x2800, 0x0800, CRC(ed547445) SHA1(20102de89a3ee4a65366bc2d62be94da984a156b)) - ROM_REGION(0x00800, "chargen",0) + ROM_REGION(0x0800, "chargen",0) ROM_LOAD("lnw_chr.bin", 0x0000, 0x0800, CRC(c89b27df) SHA1(be2a009a07e4378d070002a558705e9a0de59389)) - ROM_REGION(0x04400, "gfx2", ROMREGION_ERASEFF) /* 0x4000 for trs80_gfxram + 0x400 for videoram */ + ROM_REGION(0x4000, "gfx2", ROMREGION_ERASEFF) // for trs80_gfxram ROM_END -ROM_START(trs80m3) -/* ROMS we have and are missing: -HAVE TRS-80 Model III Level 1 ROM (U104) -MISSING TRS-80 Model III Level 2 (ENGLISH) ROM A (U104) ver. CRC BBC4 -MISSING TRS-80 Model III Level 2 (ENGLISH) ROM A (U104) ver. CRC DA75 -HAVE TRS-80 Model III Level 2 (ENGLISH) ROM A (U104) ver. CRC 9639 -HAVE TRS-80 Model III Level 2 (ENGLISH) ROM B (U105) ver. CRC 407C -MISSING TRS-80 Model III Level 2 (ENGLISH) ROM C (U106) ver. CRC 2B91 - early mfg. #80040316 -MISSING TRS-80 Model III Level 2 (ENGLISH) ROM C (U106) ver. CRC 278A - no production REV A -HAVE TRS-80 Model III Level 2 (ENGLISH) ROM C (U106) ver. CRC 2EF8 - Manufacturing #80040316 REV B -HAVE TRS-80 Model III Level 2 (ENGLISH) ROM C (U106) ver. CRC 2F84 - Manufacturing #80040316 REV C -MISSING TRS-80 Model III Level 2 (ENGLISH) ROM C ver. CRC 2764 - Network III v1 -HAVE TRS-80 Model III Level 2 (ENGLISH) ROM C ver. CRC 276A - Network III v2 -MISSING TRS-80 Model III Level 2 (BELGIUM) CRC ???? -Note: Be careful when dumping rom C: if dumped on the trs-80 m3 with software, bytes 0x7e8 and 0x7e9 (addresses 0x37e8, 0x0x37e9) - will read as 0xFF 0xFF; on the original rom, these bytes are 0x00 0x00 (for eproms) or 0xAA 0xAA (for mask roms), those two bytes are used for printer status on the trs-80 and are mapped on top of the rom; This problem should be avoided by pulling the rom chips and dumping them directly. -*/ - ROM_REGION(0x20000, "maincpu",0) - ROM_SYSTEM_BIOS(0, "trs80m3_revc", "Level 2 bios, RomC Rev C") - ROMX_LOAD("8041364.u104", 0x0000, 0x2000, CRC(ec0c6daa) SHA1(257cea6b9b46912d4681251019ec2b84f1b95fc8), ROM_BIOS(0)) // Label: "SCM91248C // Tandy (c) 80 // 8041364 // 8134" (Level 2 bios ROM A '9639') - ROMX_LOAD("8040332.u105", 0x2000, 0x1000, CRC(ed4ee921) SHA1(ec0a19d4b72f71e51965de63250009c3c4e4cab3), ROM_BIOS(0)) // Label: "SCM91619P // Tandy (c) 80 // 8040332 // QQ8117", (Level 2 bios ROM B '407c') - ROMX_LOAD("8040316c.u106", 0x3000, 0x0800, CRC(c8f79433) SHA1(6f395bba822d39d3cd2b73c8ea25aab4c4c26da7), ROM_BIOS(0)) // Label: "SCM91692P // Tandy (c) 81 // 8040316-C // QQ8220" (Level 2 bios ROM C REV C '2f84') - ROM_SYSTEM_BIOS(1, "trs80m3_revb", "Level 2 bios, RomC Rev B") - ROMX_LOAD("8041364.u104", 0x0000, 0x2000, CRC(ec0c6daa) SHA1(257cea6b9b46912d4681251019ec2b84f1b95fc8), ROM_BIOS(1)) // Label: "SCM91248C // Tandy (c) 80 // 8041364 // 8134" (Level 2 bios ROM A '9639') - ROMX_LOAD("8040332.u105", 0x2000, 0x1000, CRC(ed4ee921) SHA1(ec0a19d4b72f71e51965de63250009c3c4e4cab3), ROM_BIOS(1)) // Label: "SCM91619P // Tandy (c) 80 // 8040332 // QQ8117", (Level 2 bios ROM B '407c') - ROMX_LOAD("8040316b.u106", 0x3000, 0x0800, CRC(84a5702d) SHA1(297dca756a9d3c6fd13e0fa6f93d172ff795b520), ROM_BIOS(1)) // Label: "SCM91692P // Tandy (c) 80 // 8040316B // QQ8040" (Level 2 bios ROM C REV B '2ef8') - ROM_SYSTEM_BIOS(2, "trs80m3_n3v2", "Level 2 bios, Network III v2 (student)") - ROMX_LOAD("8041364.u104", 0x0000, 0x2000, CRC(ec0c6daa) SHA1(257cea6b9b46912d4681251019ec2b84f1b95fc8), ROM_BIOS(2)) // Label: "SCM91248C // Tandy (c) 80 // 8041364 // 8134" (Level 2 bios ROM A '9639') - ROMX_LOAD("8040332.u105", 0x2000, 0x1000, CRC(ed4ee921) SHA1(ec0a19d4b72f71e51965de63250009c3c4e4cab3), ROM_BIOS(2)) // Label: "SCM91619P // Tandy (c) 80 // 8040332 // QQ8117" (Level 2 bios ROM B '407c') - ROMX_LOAD("276a.u106", 0x3000, 0x0800, CRC(7d38720a) SHA1(bef621e5ae2a8c1f9e7f6325b7841f5ab8ab7e6a), ROM_BIOS(2)) // 2716 EPROM Label: "MOD.III // ROM C // (276A)" (Network III v2 ROM C '276a') - ROM_SYSTEM_BIOS(3, "trs80m3_l1", "Level 1 bios") - ROMX_LOAD("8040032.u104", 0x0000, 0x1000, CRC(6418d641) SHA1(f823ab6ceb102588d27e5f5c751e31175289291c), ROM_BIOS(3) ) // Label: "8040032 // (M) QQ8028 // SCM91616P"; Silkscreen: "TANDY // (C) '80"; (Level 1 bios) - - ROM_REGION(0x00800, "chargen",0) /* correct for later systems; the trs80m3_l1 bios uses the non-a version of this rom, dump is pending */ - ROM_LOAD("8044316.u36", 0x0000, 0x0800, NO_DUMP) // Label: "(M) // SCM91665P // 8044316 // QQ8029" ('no-letter' revision) - ROM_LOAD("8044316a.u36", 0x0000, 0x0800, CRC(444c8b60) SHA1(c52ee41439bd5e57c3b113ebfd61c951e2af4446)) // Label: "Tandy (C) 81 // 8044316A // 8206" (rev A) -ROM_END - -// for model 4 and 4p info, see http://vt100.net/mirror/harte/Radio%20Shack/TRS-80%20Model%204_4P%20Soft%20Tech%20Ref.pdf -ROM_START(trs80m4) - ROM_REGION(0x20000, "maincpu",0) - ROM_LOAD("trs80m4.rom", 0x0000, 0x3800, BAD_DUMP CRC(1a92d54d) SHA1(752555fdd0ff23abc9f35c6e03d9d9b4c0e9677b)) // should be split into 3 roms, roms A, B, C, exactly like trs80m3; in fact, roms A and B are shared between both systems. - - ROM_REGION(0x00800, "chargen",0) - ROM_LOAD("8044316a.u36", 0x0000, 0x0800, CRC(444c8b60) SHA1(c52ee41439bd5e57c3b113ebfd61c951e2af4446)) // according to parts catalog, this is the correct rom for both model 3 and 4 -ROM_END - -ROM_START(trs80m4p) // uses a completely different memory map scheme to the others; the trs-80 model 3 roms are loaded from a boot disk, the only rom on the machine is a bootloader; bootloader can be banked out of 0x0000-0x1000 space which is replaced with ram; see the tech ref pdf, pdf page 62 - ROM_REGION(0x20000, "maincpu",0) - ROM_SYSTEM_BIOS(0, "trs80m4p", "Level 2 bios, gate array machine") - ROMX_LOAD("8075332.u69", 0x0000, 0x1000, CRC(3a738aa9) SHA1(6393396eaa10a84b9e9f0cf5930aba73defc5c52), ROM_BIOS(0)) // Label: "SCM95060P // 8075332 // TANDY (C) 1983 // 8421" at location U69 (may be located at U70 on some pcb revisions) - ROM_SYSTEM_BIOS(1, "trs80m4p_hack", "Disk loader hack") - ROMX_LOAD("trs80m4p_loader_hack.rom", 0x0000, 0x01f8, CRC(7ff336f4) SHA1(41184f5240b4b54f3804f5a22b4d78bbba52ed1d), ROM_BIOS(1)) - - ROM_REGION(0x00800, "chargen",0) - ROM_LOAD("8049007.u103", 0x0000, 0x0800, CRC(1ac44bea) SHA1(c9426ab2b2aa5380dc97a7b9c048ccd1bbde92ca)) // Label: "SCM95987P // 8049007 // TANDY (C) 1983 // 8447" at location U103 (may be located at U43 on some pcb revisions) -ROM_END ROM_START(ht1080z) - ROM_REGION(0x10000, "maincpu",0) + ROM_REGION(0x3800, "maincpu",0) ROM_LOAD("ht1080z.rom", 0x0000, 0x3000, CRC(2bfef8f7) SHA1(7a350925fd05c20a3c95118c1ae56040c621be8f)) ROM_LOAD("sys80.ext", 0x3000, 0x0800, CRC(2a851e33) SHA1(dad21ec60973eb66e499fe0ecbd469118826a715)) - ROM_REGION(0x00800, "chargen",0) + ROM_REGION(0x0800, "chargen",0) ROM_LOAD("ht1080z.chr", 0x0000, 0x0800, CRC(e8c59d4f) SHA1(a15f30a543e53d3e30927a2e5b766fcf80f0ae31)) ROM_END + ROM_START(ht1080z2) - ROM_REGION(0x10000, "maincpu",0) + ROM_REGION(0x3800, "maincpu",0) ROM_LOAD("ht1080z.rom", 0x0000, 0x3000, CRC(2bfef8f7) SHA1(7a350925fd05c20a3c95118c1ae56040c621be8f)) ROM_LOAD("ht1080z2.ext", 0x3000, 0x0800, CRC(07415ac6) SHA1(b08746b187946e78c4971295c0aefc4e3de97115)) - ROM_REGION(0x00800, "chargen",0) + ROM_REGION(0x0800, "chargen",0) ROM_LOAD("ht1080z2.chr", 0x0000, 0x0800, CRC(6728f0ab) SHA1(1ba949f8596f1976546f99a3fdcd3beb7aded2c5)) ROM_END + ROM_START(ht108064) - ROM_REGION(0x10000, "maincpu",0) + ROM_REGION(0x3800, "maincpu",0) ROM_LOAD("ht108064.rom", 0x0000, 0x3000, CRC(48985a30) SHA1(e84cf3121f9e0bb9e1b01b095f7a9581dcfaaae4)) ROM_LOAD("ht108064.ext", 0x3000, 0x0800, CRC(fc12bd28) SHA1(0da93a311f99ec7a1e77486afe800a937778e73b)) - ROM_REGION(0x00800, "chargen",0) + ROM_REGION(0x0800, "chargen",0) ROM_LOAD("ht108064.chr", 0x0000, 0x0800, CRC(e76b73a4) SHA1(6361ee9667bf59d50059d09b0baf8672fdb2e8af)) ROM_END -ROM_START( meritum) - ROM_REGION(0x10000, "maincpu",0) - ROM_LOAD( "01.bin", 0x0000, 0x0800, CRC(ed705a47) SHA1(dae8b14eb2ddb2a8b4458215180ebc0fb781816a)) - ROM_LOAD( "02.bin", 0x0800, 0x0800, CRC(ac297d99) SHA1(ccf31d3f9d02c3b68a0ee3be4984424df0e83ab0)) - ROM_LOAD( "03.bin", 0x1000, 0x0800, CRC(a21d0d62) SHA1(6dfdf3806ed2b6502e09a1b6922f21494134cc05)) - ROM_LOAD( "04.bin", 0x1800, 0x0800, CRC(3610bdda) SHA1(602f0ba1e1267f24620f993acac019ac6342a594)) - ROM_LOAD( "05.bin", 0x2000, 0x0800, CRC(461fbf0d) SHA1(bd19187dd992168af43bd68055343d515f152624)) - ROM_LOAD( "06.bin", 0x2800, 0x0800, CRC(ed547445) SHA1(20102de89a3ee4a65366bc2d62be94da984a156b)) - ROM_LOAD( "07.bin", 0x3000, 0x0800, CRC(044b1459) SHA1(faace7353ffbef6587b1b9e7f8b312e0892e3427)) - ROM_REGION(0x1000, "chargen", ROMREGION_INVERT) - ROM_LOAD( "chargen.bin", 0x0000, 0x1000, CRC(3dfc6439) SHA1(6e45a27f68c3491c403b4eafe45a108f348dd2fd)) -ROM_END - -ROM_START( meritum_net ) - ROM_REGION(0x10000, "maincpu",0) - ROM_LOAD( "01_447_m07_015m.bin", 0x0000, 0x0800, CRC(6d30cb49) SHA1(558241340a84eebcbbf8d92540e028e9164b6f8a)) - ROM_LOAD( "02_440_m08_01.bin", 0x0800, 0x0800, CRC(ac297d99) SHA1(ccf31d3f9d02c3b68a0ee3be4984424df0e83ab0)) - ROM_LOAD( "03_440_m09_015m.bin", 0x1000, 0x0800, CRC(88e267da) SHA1(9cb8626801f8e969f35291de43c1b643c809a3c3)) - ROM_LOAD( "04_447_m10_015m.bin", 0x1800, 0x0800, CRC(e51991e4) SHA1(a7d42436da1af405970f9f99ab34b6d9abd05adf)) - ROM_LOAD( "05_440_m11_02.bin", 0x2000, 0x0800, CRC(461fbf0d) SHA1(bd19187dd992168af43bd68055343d515f152624)) - ROM_LOAD( "06_440_m12_01.bin", 0x2800, 0x0800, CRC(ed547445) SHA1(20102de89a3ee4a65366bc2d62be94da984a156b)) - ROM_LOAD( "07_447_m13_015m.bin", 0x3000, 0x0800, CRC(789f6964) SHA1(9b2231ca7ffd82bbca1f53988a7df833290ddbf2)) - ROM_REGION(0x1000, "chargen", ROMREGION_INVERT) - ROM_LOAD( "char.bin", 0x0000, 0x1000, CRC(2c09a5a7) SHA1(146891b3ddfc2de95e6a5371536394a657880054)) -ROM_END - -ROM_START( cp500 ) - ROM_REGION(0x20000, "maincpu", 0) - ROM_LOAD("s_8407_cn62516n_cp500a_prologica_83.ci111", 0x0000, 0x4000, CRC(c2fc1b92) SHA1(0eb07baee80f1ee1f28a609eb63a9245dcb68adb)) - - ROM_REGION(0x20000, "bootrom", 0) - ROM_LOAD("s_8407_cn62516n_cp500a_prologica_83.ci111", 0x0000, 0x4000, CRC(c2fc1b92) SHA1(0eb07baee80f1ee1f28a609eb63a9245dcb68adb)) - - ROM_REGION(0x0800, "chargen", 0) - ROM_LOAD( "100.105.ci36", 0x0000, 0x800, CRC(1765931e) SHA1(49176ceea6cc003efa04fad2f31829b9432fe10f)) -ROM_END void trs80_state::init_trs80() { m_mode = 0; - m_model4 = 0; } void trs80_state::init_trs80l2() { m_mode = 2; - m_model4 = 0; -} - -void trs80_state::init_trs80m4() -{ - m_mode = 0; - m_model4 = 2; - m_p_videoram.set_target(memregion("maincpu")->base()+0x4000,m_p_videoram.bytes()); } -void trs80_state::init_trs80m4p() -{ - m_mode = 0; - m_model4 = 4; - m_p_videoram.set_target(memregion("maincpu")->base()+0x4000,m_p_videoram.bytes()); -} - -void trs80_state::init_lnw80() -{ - m_mode = 0; - m_model4 = 0; - m_p_gfxram = memregion("gfx2")->base(); - m_p_videoram.set_target(memregion("maincpu")->base()+0x4000,m_p_videoram.bytes()); -} -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -COMP( 1977, trs80, 0, 0, trs80, trs80, trs80_state, init_trs80, "Tandy Radio Shack", "TRS-80 Model I (Level I Basic)", 0 ) -COMP( 1978, trs80l2, trs80, 0, model1, trs80, trs80_state, init_trs80l2, "Tandy Radio Shack", "TRS-80 Model I (Level II Basic)", 0 ) -COMP( 1983, radionic, trs80, 0, radionic, trs80, trs80_state, init_trs80, "Komtek", "Radionic", 0 ) -COMP( 1980, sys80, trs80, 0, sys80, trs80, trs80_state, init_trs80l2, "EACA Computers Ltd", "System-80", 0 ) -COMP( 1981, lnw80, trs80, 0, lnw80, trs80m3, trs80_state, init_lnw80, "LNW Research", "LNW-80", 0 ) -COMP( 1980, trs80m3, trs80, 0, model3, trs80m3, trs80_state, init_trs80m4, "Tandy Radio Shack", "TRS-80 Model III", 0 ) -COMP( 1980, trs80m4, trs80, 0, model4, trs80m3, trs80_state, init_trs80m4, "Tandy Radio Shack", "TRS-80 Model 4", 0 ) -COMP( 1983, trs80m4p, trs80, 0, model4p, trs80m3, trs80_state, init_trs80m4p, "Tandy Radio Shack", "TRS-80 Model 4P", 0 ) -COMP( 1983, ht1080z, trs80, 0, ht1080z, trs80, trs80_state, init_trs80l2, "Hiradastechnika Szovetkezet", "HT-1080Z Series I", 0 ) -COMP( 1984, ht1080z2, trs80, 0, ht1080z, trs80, trs80_state, init_trs80l2, "Hiradastechnika Szovetkezet", "HT-1080Z Series II", 0 ) -COMP( 1985, ht108064, trs80, 0, ht1080z, trs80, trs80_state, init_trs80, "Hiradastechnika Szovetkezet", "HT-1080Z/64", 0 ) -COMP( 1985, meritum, trs80, 0, meritum, trs80, trs80_state, init_trs80l2, "Mera-Elzab", "Meritum I (Model 2)", 0 ) -COMP( 1985, meritum_net, trs80, 0, meritum, trs80, trs80_state, init_trs80l2, "Mera-Elzab", "Meritum I (Model 2) (network)", 0 ) -COMP( 1982, cp500, trs80, 0, cp500, trs80m3, trs80_state, init_trs80m4, "Prológica", "CP-500 (PVIII REV.3)", 0 ) +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +COMP( 1977, trs80, 0, 0, trs80, trs80, trs80_state, init_trs80, "Tandy Radio Shack", "TRS-80 Model I (Level I Basic)", 0 ) +COMP( 1978, trs80l2, 0, 0, model1, trs80l2, trs80_state, init_trs80l2, "Tandy Radio Shack", "TRS-80 Model I (Level II Basic)", 0 ) +COMP( 1983, radionic, trs80l2, 0, radionic, trs80l2, trs80_state, init_trs80, "Komtek", "Radionic", 0 ) +COMP( 1980, sys80, trs80l2, 0, sys80, sys80, trs80_state, init_trs80l2, "EACA Computers Ltd", "System-80", 0 ) +COMP( 1981, lnw80, trs80l2, 0, lnw80, sys80, trs80_state, init_trs80, "LNW Research", "LNW-80", 0 ) +COMP( 1983, ht1080z, trs80l2, 0, ht1080z, sys80, trs80_state, init_trs80l2, "Hiradastechnika Szovetkezet", "HT-1080Z Series I", 0 ) +COMP( 1984, ht1080z2, trs80l2, 0, ht1080z, sys80, trs80_state, init_trs80l2, "Hiradastechnika Szovetkezet", "HT-1080Z Series II", 0 ) +COMP( 1985, ht108064, trs80l2, 0, ht1080z, sys80, trs80_state, init_trs80, "Hiradastechnika Szovetkezet", "HT-1080Z/64", 0 ) diff --git a/src/mame/drivers/trs80m3.cpp b/src/mame/drivers/trs80m3.cpp new file mode 100644 index 00000000000..0867872799d --- /dev/null +++ b/src/mame/drivers/trs80m3.cpp @@ -0,0 +1,551 @@ +// license:BSD-3-Clause +// copyright-holders:Robbbert +/*************************************************************************** +Cassette baud rates: + Model III/4 - 500 and 1500 baud selectable at boot time + - When it says "Cass?" press L for 500 baud, or Enter otherwise. + +I/O ports +FF: +- bits 0 and 1 are for writing a cassette +- bit 3 switches the display between 64 or 32 characters per line +- bit 6 remembers the 32/64 screen mode (inverted) +- bit 7 is for reading from a cassette + +F8: +- Write to printer (Model III/4) +- Read printer status (Model III/4) + +EB: +- UART data (read and write) on a Model III/4 + +EA: +- UART status (read and write) on a Model III/4 + +E9: +- UART Configuration jumpers (read) on a Model III/4 +- Set baud rate (Model III/4) + +E8: +- UART Modem Status register (read) on a Model III/4 +- UART Master Reset (write) on a Model III/4 + +Model 4 - C0-CF = hard drive (optional) + - 90-93 write sound (optional) + - 80-8F hires graphics (optional) + +About the RTC - The time is incremented while ever the cursor is flashing. It is stored in a series + of bytes in the computer's work area. The bytes are in a certain order, this is: + seconds, minutes, hours, year, day, month. On a model 1, the seconds are stored at + 0x4041, while on the model 4 it is 0x4217. A reboot always sets the time to zero. + +Model 4 memory organisation - + Mode 0: ROM=0-37E7 and 37EA-3FFF; Printer=37E8-37E9; Keyboard=3800-3BFF; Video=3C00-3FFF + Mode 1: Keyboard and Video as above; 0-3FFF read=ROM and write=RAM + Mode 2: Keyboard=F400-F7FF; Video=F800-FFFF; the rest is RAM + Mode 3: All RAM + In the "maincpu" memory map, the first 64k is given to the ROM, keyboard, printer and video, + while the second 64k is RAM that is switched in as needed. The area from 4800-FFFF + is considered a "black hole", any writes to there will disappear. + The video is organised as 2 banks of 0x400 bytes, except in Mode 2 where it becomes contiguous. + +Model 4P - is the same as Model 4 except: + - ROM is only 0000-0FFF, while 1000-37FF is given over to RAM + - There is no cassette support in hardware. + +*************************************************************************** + + +To Do / Status: +-------------- + +trs80m3: works + floppy not working + +trs80m4: works + floppy not working + +trs80m4p: floppy not working, so machine is useless + +***************************************************************************/ + +#include "emu.h" +#include "includes/trs80m3.h" + +#include "screen.h" +#include "speaker.h" + +#include "formats/trs80_dsk.h" +#include "formats/dmk_dsk.h" + + + +void trs80m3_state::m3_mem(address_map &map) +{ + map(0x0000, 0x37ff).rom(); + map(0x37e8, 0x37e9).rw(FUNC(trs80m3_state::printer_r), FUNC(trs80m3_state::printer_w)); + map(0x3800, 0x3bff).r(FUNC(trs80m3_state::keyboard_r)); + map(0x3c00, 0x3fff).ram().share(m_p_videoram); + map(0x4000, 0xffff).ram(); +} + +void trs80m3_state::m3_io(address_map &map) +{ + map.global_mask(0xff); + map.unmap_value_high(); + map(0xe0, 0xe3).rw(FUNC(trs80m3_state::port_e0_r), FUNC(trs80m3_state::port_e0_w)); + map(0xe4, 0xe4).rw(FUNC(trs80m3_state::port_e4_r), FUNC(trs80m3_state::port_e4_w)); + map(0xe8, 0xe8).rw(FUNC(trs80m3_state::port_e8_r), FUNC(trs80m3_state::port_e8_w)); + map(0xe9, 0xe9).portr("E9").w(m_brg, FUNC(com8116_device::stt_str_w)); + map(0xea, 0xea).rw(FUNC(trs80m3_state::port_ea_r), FUNC(trs80m3_state::port_ea_w)); + map(0xeb, 0xeb).rw(m_uart, FUNC(ay31015_device::receive), FUNC(ay31015_device::transmit)); + map(0xec, 0xef).rw(FUNC(trs80m3_state::port_ec_r), FUNC(trs80m3_state::port_ec_w)); + map(0xf0, 0xf0).r(FUNC(trs80m3_state::wd179x_r)); + map(0xf0, 0xf0).w(m_fdc, FUNC(fd1793_device::cmd_w)); + map(0xf1, 0xf1).rw(m_fdc, FUNC(fd1793_device::track_r), FUNC(fd1793_device::track_w)); + map(0xf2, 0xf2).rw(m_fdc, FUNC(fd1793_device::sector_r), FUNC(fd1793_device::sector_w)); + map(0xf3, 0xf3).rw(m_fdc, FUNC(fd1793_device::data_r), FUNC(fd1793_device::data_w)); + map(0xf4, 0xf7).w(FUNC(trs80m3_state::port_f4_w)); + map(0xf8, 0xfb).rw(FUNC(trs80m3_state::printer_r), FUNC(trs80m3_state::printer_w)); + map(0xfc, 0xff).rw(FUNC(trs80m3_state::port_ff_r), FUNC(trs80m3_state::port_ff_w)); +} + +void trs80m3_state::m4_banked_mem(address_map &map) +{ + // Memory Map I - Model III Mode + map(0x00000, 0x037ff).rom().region("maincpu", 0); + map(0x037e8, 0x037e9).rw(FUNC(trs80m3_state::printer_r), FUNC(trs80m3_state::printer_w)); + map(0x03800, 0x03bff).r(FUNC(trs80m3_state::keyboard_r)); + map(0x03c00, 0x03fff).bankrw(m_vidbank); // Video RAM (Page bit selects 1K of 2K) + map(0x04000, 0x07fff).bankrw(m_16kbank); // RAM + map(0x08000, 0x0ffff).bankrw(m_32kbanks[1]); // RAM + + // Memory Map II + map(0x10000, 0x137ff).bankrw(m_32kbanks[0]); // RAM (14K) + map(0x13800, 0x13bff).r(FUNC(trs80m3_state::keyboard_r)); + map(0x13c00, 0x13fff).bankrw(m_vidbank); // Video RAM + map(0x14000, 0x17fff).bankrw(m_16kbank); // RAM (16K) + map(0x18000, 0x1ffff).bankrw(m_32kbanks[1]); // RAM (32K) + + // Memory Map III + map(0x20000, 0x27fff).bankrw(m_32kbanks[0]); // RAM (32K) + map(0x28000, 0x2f3ff).bankrw(m_32kbanks[1]); // RAM (29K) + map(0x2f400, 0x2f7ff).r(FUNC(trs80m3_state::keyboard_r)); + map(0x2f800, 0x2ffff).ram().share(m_p_videoram); // Video RAM + + // Memory Map IV + map(0x30000, 0x37fff).bankrw(m_32kbanks[0]); // RAM (32K) + map(0x38000, 0x3ffff).bankrw(m_32kbanks[1]); // RAM (32K) +} + +void trs80m3_state::m4_io(address_map &map) +{ + map.global_mask(0xff); + map.unmap_value_high(); + m3_io(map); + map(0x84, 0x87).w(FUNC(trs80m3_state::port_84_w)); + map(0x88, 0x89).w(FUNC(trs80m3_state::port_88_w)); + map(0x90, 0x93).w(FUNC(trs80m3_state::port_90_w)); +} + +void trs80m3_state::m4p_banked_mem(address_map &map) +{ + // Memory Map I - Model III Mode + map(0x00000, 0x00fff).rom().region("maincpu", 0); + map(0x01000, 0x037ff).bankr(m_32kbanks[0]); // readonly RAM + map(0x037e8, 0x037e9).rw(FUNC(trs80m3_state::printer_r), FUNC(trs80m3_state::printer_w)); + map(0x03800, 0x03bff).r(FUNC(trs80m3_state::keyboard_r)); + map(0x03c00, 0x03fff).bankrw(m_vidbank); // Video RAM (Page bit selects 1K of 2K) + map(0x04000, 0x07fff).bankrw(m_16kbank); // RAM + map(0x08000, 0x0ffff).bankrw(m_32kbanks[1]); // RAM + // Memory Map II + map(0x10000, 0x137ff).bankrw(m_32kbanks[0]); // RAM + map(0x10000, 0x10fff).rom().region("maincpu", 0); // the ram under here is writeonly + map(0x13800, 0x13bff).r(FUNC(trs80m3_state::keyboard_r)); + map(0x13c00, 0x13fff).bankrw(m_vidbank); // Video RAM + map(0x14000, 0x17fff).bankrw(m_16kbank); // RAM (16K) + map(0x18000, 0x1ffff).bankrw(m_32kbanks[1]); // RAM (32K) + // Memory Map III + map(0x20000, 0x27fff).bankrw(m_32kbanks[0]); // RAM (32K) + map(0x28000, 0x2f3ff).bankrw(m_32kbanks[1]); // RAM (29K) + map(0x2f400, 0x2f7ff).r(FUNC(trs80m3_state::keyboard_r)); + map(0x2f800, 0x2ffff).ram().share(m_p_videoram); // Video RAM + // Memory Map IV + map(0x30000, 0x37fff).bankrw(m_32kbanks[0]); // RAM (32K) + map(0x38000, 0x3ffff).bankrw(m_32kbanks[1]); // RAM (32K) + // Map I with no rom + map(0x40000, 0x437ff).bankr(m_32kbanks[0]); // readonly RAM + map(0x437e8, 0x437e9).rw(FUNC(trs80m3_state::printer_r), FUNC(trs80m3_state::printer_w)); + map(0x43800, 0x43bff).r(FUNC(trs80m3_state::keyboard_r)); + map(0x43c00, 0x43fff).bankrw(m_vidbank); // Video RAM + map(0x44000, 0x47fff).bankrw(m_16kbank); // RAM (16K) + map(0x48000, 0x4ffff).bankrw(m_32kbanks[1]); // RAM (32K) + // Map II with no rom + map(0x50000, 0x537ff).bankrw(m_32kbanks[0]); // RAM (32K) + map(0x53800, 0x53bff).r(FUNC(trs80m3_state::keyboard_r)); + map(0x53c00, 0x53fff).bankrw(m_vidbank); // Video RAM + map(0x54000, 0x57fff).bankrw(m_16kbank); // RAM (16K) + map(0x58000, 0x5ffff).bankrw(m_32kbanks[1]); // RAM (32K) +} + +void trs80m3_state::m4p_io(address_map &map) +{ + map.global_mask(0xff); + map.unmap_value_high(); + m4_io(map); + map(0x9c, 0x9f).w(FUNC(trs80m3_state::port_9c_w)); + map(0xf0, 0xf0).rw(m_fdc, FUNC(fd1793_device::status_r), FUNC(fd1793_device::cmd_w)); +} + +void trs80m3_state::cp500_io(address_map &map) +{ + map.global_mask(0xff); + map.unmap_value_high(); + m3_io(map); + map(0xf4, 0xf7).r(FUNC(trs80m3_state::cp500_port_f4_r)); +} + + +static INPUT_PORTS_START( trs80m4p ) + PORT_START("LINE0") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("@") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@') + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') + PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') + PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') + PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') + PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') + PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') + + PORT_START("LINE1") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') + PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') + PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') + PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') + PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') + PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') + + PORT_START("LINE2") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') + PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') + PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') + PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') + PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') + PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') + + PORT_START("LINE3") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') + PORT_BIT(0xF8, 0x00, IPT_UNUSED) + + PORT_START("LINE4") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) + PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) + PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) + PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) + PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) + PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) + + PORT_START("LINE5") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME(": *") PORT_CODE(KEYCODE_MINUS) PORT_CHAR(':') PORT_CHAR('*') + PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("; +") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+') + PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("- =") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('-') PORT_CHAR('=') + PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) + PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') + + PORT_START("LINE6") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("Clear") PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(F8)) // 3rd line, 1st key from right + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(F9)) // 1st line, 1st key from right + PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) + PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) + /* backspace do the same as cursor left */ + PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) + PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) + PORT_BIT(0x80, 0x00, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') + + PORT_START("LINE7") + PORT_BIT(0x01, 0x00, IPT_KEYBOARD) PORT_NAME("Left Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) + /* These keys are only on a Model 4. The one marked CTL seems to be another shift key (4 in total). */ + PORT_BIT(0x02, 0x00, IPT_KEYBOARD) PORT_NAME("Right Shift") PORT_CODE(KEYCODE_RSHIFT) + PORT_BIT(0x04, 0x00, IPT_KEYBOARD) PORT_NAME("CTL") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2) + PORT_BIT(0x08, 0x00, IPT_KEYBOARD) PORT_NAME("Caps") PORT_CODE(KEYCODE_CAPSLOCK) + PORT_BIT(0x10, 0x00, IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) + PORT_BIT(0x20, 0x00, IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) + PORT_BIT(0x40, 0x00, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) + PORT_BIT(0x80, 0x00, IPT_UNUSED) + + PORT_START("E9") // these are the power-on uart settings + PORT_BIT(0x07, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_DIPNAME( 0x88, 0x08, "Parity") + PORT_DIPSETTING( 0x08, DEF_STR(None)) + PORT_DIPSETTING( 0x00, "Odd") + PORT_DIPSETTING( 0x80, "Even") + PORT_DIPNAME( 0x10, 0x10, "Stop Bits") + PORT_DIPSETTING( 0x10, "2") + PORT_DIPSETTING( 0x00, "1") + PORT_DIPNAME( 0x60, 0x60, "Bits") + PORT_DIPSETTING( 0x00, "5") + PORT_DIPSETTING( 0x20, "6") + PORT_DIPSETTING( 0x40, "7") + PORT_DIPSETTING( 0x60, "8") +INPUT_PORTS_END + +static INPUT_PORTS_START( trs80m3 ) + PORT_INCLUDE( trs80m4p ) + PORT_START("CONFIG") + PORT_CONFNAME( 0x80, 0x00, "Floppy Disc Drives") + PORT_CONFSETTING( 0x00, DEF_STR( Off ) ) + PORT_CONFSETTING( 0x80, DEF_STR( On ) ) + PORT_BIT(0x7f, 0x7f, IPT_UNUSED) +INPUT_PORTS_END + + +/**************************** F4 CHARACTER DISPLAYER ***********************************************************/ +static const gfx_layout trs80m3_charlayout = +{ + 8, 8, /* 8 x 8 characters */ + 256, /* 256 characters */ + 1, /* 1 bits per pixel */ + { 0 }, /* no bitplanes */ + /* x offsets */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, + /* y offsets */ + { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 }, + 8*8 /* every char takes 8 bytes */ +}; + +static GFXDECODE_START(gfx_trs80m3) + GFXDECODE_ENTRY( "chargen", 0, trs80m3_charlayout, 0, 1 ) +GFXDECODE_END + + +FLOPPY_FORMATS_MEMBER( trs80m3_state::floppy_formats ) + FLOPPY_TRS80_FORMAT, + FLOPPY_DMK_FORMAT +FLOPPY_FORMATS_END + +static void trs80_floppies(device_slot_interface &device) +{ + device.option_add("sssd", FLOPPY_525_QD); +} + + +MACHINE_CONFIG_START(trs80m3_state::model3) + /* basic machine hardware */ + MCFG_DEVICE_ADD("maincpu", Z80, 20.2752_MHz_XTAL / 10) + MCFG_DEVICE_PROGRAM_MAP(m3_mem) + MCFG_DEVICE_IO_MAP(m3_io) + MCFG_DEVICE_PERIODIC_INT_DRIVER(trs80m3_state, rtc_interrupt, 20.2752_MHz_XTAL / 10 / 67584) + + /* video hardware */ + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_RAW_PARAMS(12.672_MHz_XTAL, 800, 0, 640, 264, 0, 240) + MCFG_SCREEN_UPDATE_DRIVER(trs80m3_state, screen_update_trs80m3) + MCFG_SCREEN_PALETTE("palette") + + MCFG_DEVICE_ADD("gfxdecode", GFXDECODE, "palette", gfx_trs80m3) + MCFG_PALETTE_ADD_MONOCHROME("palette") + + /* sound hardware */ + SPEAKER(config, "mono").front_center(); + SPEAKER_SOUND(config, "speaker").add_route(ALL_OUTPUTS, "mono", 0.50); + WAVE(config, "wave", "cassette").add_route(ALL_OUTPUTS, "mono", 0.05); + + /* devices */ + MCFG_CASSETTE_ADD("cassette") + MCFG_CASSETTE_FORMATS(trs80l2_cassette_formats) + MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_PLAY) + + MCFG_QUICKLOAD_ADD("quickload", trs80m3_state, trs80_cmd, "cmd", 1.0) + + MCFG_DEVICE_ADD("fdc", FD1793, 4_MHz_XTAL / 4) + MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(*this, trs80m3_state, intrq_w)) + MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(*this, trs80m3_state, drq_w)) + + // Internal drives + MCFG_FLOPPY_DRIVE_ADD("fdc:0", trs80_floppies, "sssd", trs80m3_state::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) + MCFG_FLOPPY_DRIVE_ADD("fdc:1", trs80_floppies, "sssd", trs80m3_state::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) + // Optional external unit + MCFG_FLOPPY_DRIVE_ADD("fdc:2", trs80_floppies, "", trs80m3_state::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) + MCFG_FLOPPY_DRIVE_ADD("fdc:3", trs80_floppies, "", trs80m3_state::floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) + + MCFG_DEVICE_ADD(m_centronics, CENTRONICS, centronics_devices, "printer") + MCFG_CENTRONICS_BUSY_HANDLER(WRITELINE("cent_status_in", input_buffer_device, write_bit7)) + MCFG_CENTRONICS_PERROR_HANDLER(WRITELINE("cent_status_in", input_buffer_device, write_bit6)) + MCFG_CENTRONICS_SELECT_HANDLER(WRITELINE("cent_status_in", input_buffer_device, write_bit5)) + MCFG_CENTRONICS_FAULT_HANDLER(WRITELINE("cent_status_in", input_buffer_device, write_bit4)) + + MCFG_DEVICE_ADD("cent_status_in", INPUT_BUFFER, 0) + + MCFG_CENTRONICS_OUTPUT_LATCH_ADD("cent_data_out", "centronics") + + COM8116(config, m_brg, 5.0688_MHz_XTAL); // BR1943 (or BR1941L) + m_brg->fr_handler().set(m_uart, FUNC(ay31015_device::write_rcp)); + m_brg->ft_handler().set(m_uart, FUNC(ay31015_device::write_tcp)); + + MCFG_DEVICE_ADD("uart", AY31015, 0) + MCFG_AY51013_READ_SI_CB(READLINE("rs232", rs232_port_device, rxd_r)) + MCFG_AY51013_WRITE_SO_CB(WRITELINE("rs232", rs232_port_device, write_txd)) + //MCFG_AY51013_WRITE_DAV_CB(WRITELINE( , , )) + MCFG_AY51013_AUTO_RDAV(true) + MCFG_DEVICE_ADD("rs232", RS232_PORT, default_rs232_devices, nullptr) + + MCFG_MACHINE_RESET_OVERRIDE(trs80m3_state, trs80m3) +MACHINE_CONFIG_END + +MACHINE_CONFIG_START(trs80m3_state::model4) + model3(config); + MCFG_DEVICE_MODIFY("maincpu") + MCFG_DEVICE_IO_MAP(m4_io) + + RAM(config, m_mainram, 0); + m_mainram->set_default_size("64K"); + m_mainram->set_extra_options("16K,128K"); + + ADDRESS_MAP_BANK(config, m_m4_bank, 0); + m_m4_bank->set_map(&trs80m3_state::m4_banked_mem); + m_m4_bank->set_endianness(ENDIANNESS_LITTLE); + m_m4_bank->set_data_width(8); + m_m4_bank->set_addr_width(18); + m_m4_bank->set_stride(0x10000); +MACHINE_CONFIG_END + +MACHINE_CONFIG_START(trs80m3_state::model4p) + model3(config); + MCFG_DEVICE_MODIFY("maincpu") + MCFG_DEVICE_IO_MAP(m4p_io) + + RAM(config, m_mainram, 0); + m_mainram->set_default_size("64K"); + m_mainram->set_extra_options("16K,128K"); + + ADDRESS_MAP_BANK(config, m_m4p_bank, 0); + m_m4p_bank->set_map(&trs80m3_state::m4p_banked_mem); + m_m4p_bank->set_endianness(ENDIANNESS_LITTLE); + m_m4p_bank->set_data_width(8); + m_m4p_bank->set_addr_width(19); + m_m4p_bank->set_stride(0x10000); + + MCFG_DEVICE_REMOVE("quickload") +MACHINE_CONFIG_END + +MACHINE_CONFIG_START(trs80m3_state::cp500) + model3(config); + MCFG_DEVICE_MODIFY("maincpu") + MCFG_DEVICE_IO_MAP(cp500_io) + + MCFG_MACHINE_RESET_OVERRIDE(trs80m3_state, cp500) +MACHINE_CONFIG_END + +/*************************************************************************** + + Game driver(s) + +***************************************************************************/ + + +ROM_START(trs80m3) +/* ROMS we have and are missing: +HAVE TRS-80 Model III Level 1 ROM (U104) +MISSING TRS-80 Model III Level 2 (ENGLISH) ROM A (U104) ver. CRC BBC4 +MISSING TRS-80 Model III Level 2 (ENGLISH) ROM A (U104) ver. CRC DA75 +HAVE TRS-80 Model III Level 2 (ENGLISH) ROM A (U104) ver. CRC 9639 +HAVE TRS-80 Model III Level 2 (ENGLISH) ROM B (U105) ver. CRC 407C +MISSING TRS-80 Model III Level 2 (ENGLISH) ROM C (U106) ver. CRC 2B91 - early mfg. #80040316 +MISSING TRS-80 Model III Level 2 (ENGLISH) ROM C (U106) ver. CRC 278A - no production REV A +HAVE TRS-80 Model III Level 2 (ENGLISH) ROM C (U106) ver. CRC 2EF8 - Manufacturing #80040316 REV B +HAVE TRS-80 Model III Level 2 (ENGLISH) ROM C (U106) ver. CRC 2F84 - Manufacturing #80040316 REV C +MISSING TRS-80 Model III Level 2 (ENGLISH) ROM C ver. CRC 2764 - Network III v1 +HAVE TRS-80 Model III Level 2 (ENGLISH) ROM C ver. CRC 276A - Network III v2 +MISSING TRS-80 Model III Level 2 (BELGIUM) CRC ???? +Note: Be careful when dumping rom C: if dumped on the trs-80 m3 with software, bytes 0x7e8 and 0x7e9 (addresses 0x37e8, 0x0x37e9) + will read as 0xFF 0xFF; on the original rom, these bytes are 0x00 0x00 (for eproms) or 0xAA 0xAA (for mask roms), those two bytes are used for printer status on the trs-80 and are mapped on top of the rom; This problem should be avoided by pulling the rom chips and dumping them directly. +*/ + ROM_REGION(0x3800, "maincpu",0) + ROM_SYSTEM_BIOS(0, "trs80m3_revc", "Level 2 bios, RomC Rev C") + ROMX_LOAD("8041364.u104", 0x0000, 0x2000, CRC(ec0c6daa) SHA1(257cea6b9b46912d4681251019ec2b84f1b95fc8), ROM_BIOS(0)) // Label: "SCM91248C // Tandy (c) 80 // 8041364 // 8134" (Level 2 bios ROM A '9639') + ROMX_LOAD("8040332.u105", 0x2000, 0x1000, CRC(ed4ee921) SHA1(ec0a19d4b72f71e51965de63250009c3c4e4cab3), ROM_BIOS(0)) // Label: "SCM91619P // Tandy (c) 80 // 8040332 // QQ8117", (Level 2 bios ROM B '407c') + ROMX_LOAD("8040316c.u106", 0x3000, 0x0800, CRC(c8f79433) SHA1(6f395bba822d39d3cd2b73c8ea25aab4c4c26da7), ROM_BIOS(0)) // Label: "SCM91692P // Tandy (c) 81 // 8040316-C // QQ8220" (Level 2 bios ROM C REV C '2f84') + ROM_SYSTEM_BIOS(1, "trs80m3_revb", "Level 2 bios, RomC Rev B") + ROMX_LOAD("8041364.u104", 0x0000, 0x2000, CRC(ec0c6daa) SHA1(257cea6b9b46912d4681251019ec2b84f1b95fc8), ROM_BIOS(1)) // Label: "SCM91248C // Tandy (c) 80 // 8041364 // 8134" (Level 2 bios ROM A '9639') + ROMX_LOAD("8040332.u105", 0x2000, 0x1000, CRC(ed4ee921) SHA1(ec0a19d4b72f71e51965de63250009c3c4e4cab3), ROM_BIOS(1)) // Label: "SCM91619P // Tandy (c) 80 // 8040332 // QQ8117", (Level 2 bios ROM B '407c') + ROMX_LOAD("8040316b.u106", 0x3000, 0x0800, CRC(84a5702d) SHA1(297dca756a9d3c6fd13e0fa6f93d172ff795b520), ROM_BIOS(1)) // Label: "SCM91692P // Tandy (c) 80 // 8040316B // QQ8040" (Level 2 bios ROM C REV B '2ef8') + ROM_SYSTEM_BIOS(2, "trs80m3_n3v2", "Level 2 bios, Network III v2 (student)") + ROMX_LOAD("8041364.u104", 0x0000, 0x2000, CRC(ec0c6daa) SHA1(257cea6b9b46912d4681251019ec2b84f1b95fc8), ROM_BIOS(2)) // Label: "SCM91248C // Tandy (c) 80 // 8041364 // 8134" (Level 2 bios ROM A '9639') + ROMX_LOAD("8040332.u105", 0x2000, 0x1000, CRC(ed4ee921) SHA1(ec0a19d4b72f71e51965de63250009c3c4e4cab3), ROM_BIOS(2)) // Label: "SCM91619P // Tandy (c) 80 // 8040332 // QQ8117" (Level 2 bios ROM B '407c') + ROMX_LOAD("276a.u106", 0x3000, 0x0800, CRC(7d38720a) SHA1(bef621e5ae2a8c1f9e7f6325b7841f5ab8ab7e6a), ROM_BIOS(2)) // 2716 EPROM Label: "MOD.III // ROM C // (276A)" (Network III v2 ROM C '276a') + ROM_SYSTEM_BIOS(3, "trs80m3_l1", "Level 1 bios") + ROMX_LOAD("8040032.u104", 0x0000, 0x1000, CRC(6418d641) SHA1(f823ab6ceb102588d27e5f5c751e31175289291c), ROM_BIOS(3) ) // Label: "8040032 // (M) QQ8028 // SCM91616P"; Silkscreen: "TANDY // (C) '80"; (Level 1 bios) + + ROM_REGION(0x0800, "chargen",0) /* correct for later systems; the trs80m3_l1 bios uses the non-a version of this rom, dump is pending */ + ROM_LOAD("8044316.u36", 0x0000, 0x0800, NO_DUMP) // Label: "(M) // SCM91665P // 8044316 // QQ8029" ('no-letter' revision) + ROM_LOAD("8044316a.u36", 0x0000, 0x0800, CRC(444c8b60) SHA1(c52ee41439bd5e57c3b113ebfd61c951e2af4446)) // Label: "Tandy (C) 81 // 8044316A // 8206" (rev A) +ROM_END + +// for model 4 and 4p info, see http://vt100.net/mirror/harte/Radio%20Shack/TRS-80%20Model%204_4P%20Soft%20Tech%20Ref.pdf +ROM_START(trs80m4) + ROM_REGION(0x3800, "maincpu",0) + ROM_LOAD("trs80m4.rom", 0x0000, 0x3800, BAD_DUMP CRC(1a92d54d) SHA1(752555fdd0ff23abc9f35c6e03d9d9b4c0e9677b)) // should be split into 3 roms, roms A, B, C, exactly like trs80m3; in fact, roms A and B are shared between both systems. + + ROM_REGION(0x0800, "chargen",0) + ROM_LOAD("8044316a.u36", 0x0000, 0x0800, CRC(444c8b60) SHA1(c52ee41439bd5e57c3b113ebfd61c951e2af4446)) // according to parts catalog, this is the correct rom for both model 3 and 4 +ROM_END + +ROM_START(trs80m4p) // uses a completely different memory map scheme to the others; the trs-80 model 3 roms are loaded from a boot disk, the only rom on the machine is a bootloader; bootloader can be banked out of 0x0000-0x1000 space which is replaced with ram; see the tech ref pdf, pdf page 62 + ROM_REGION(0x3800, "maincpu",0) + ROM_SYSTEM_BIOS(0, "trs80m4p", "Level 2 bios, gate array machine") + ROMX_LOAD("8075332.u69", 0x0000, 0x1000, CRC(3a738aa9) SHA1(6393396eaa10a84b9e9f0cf5930aba73defc5c52), ROM_BIOS(0)) // Label: "SCM95060P // 8075332 // TANDY (C) 1983 // 8421" at location U69 (may be located at U70 on some pcb revisions) + ROM_SYSTEM_BIOS(1, "trs80m4p_hack", "Disk loader hack") + ROMX_LOAD("trs80m4p_loader_hack.rom", 0x0000, 0x01f8, CRC(7ff336f4) SHA1(41184f5240b4b54f3804f5a22b4d78bbba52ed1d), ROM_BIOS(1)) + + ROM_REGION(0x0800, "chargen",0) + ROM_LOAD("8049007.u103", 0x0000, 0x0800, CRC(1ac44bea) SHA1(c9426ab2b2aa5380dc97a7b9c048ccd1bbde92ca)) // Label: "SCM95987P // 8049007 // TANDY (C) 1983 // 8447" at location U103 (may be located at U43 on some pcb revisions) +ROM_END + +ROM_START( cp500 ) + ROM_REGION(0x4000, "maincpu", 0) + ROM_LOAD("s_8407_cn62516n_cp500a_prologica_83.ci111", 0x0000, 0x4000, CRC(c2fc1b92) SHA1(0eb07baee80f1ee1f28a609eb63a9245dcb68adb)) + + ROM_REGION(0x4000, "bootrom", 0) + ROM_LOAD("s_8407_cn62516n_cp500a_prologica_83.ci111", 0x0000, 0x4000, CRC(c2fc1b92) SHA1(0eb07baee80f1ee1f28a609eb63a9245dcb68adb)) + + ROM_REGION(0x0800, "chargen", 0) + ROM_LOAD( "100.105.ci36", 0x0000, 0x800, CRC(1765931e) SHA1(49176ceea6cc003efa04fad2f31829b9432fe10f)) +ROM_END + +void trs80m3_state::init_trs80m3() +{ + m_model4 = 0; +} + +void trs80m3_state::init_trs80m4() +{ + m_model4 = 2; +} + +void trs80m3_state::init_trs80m4p() +{ + m_model4 = 4; +} + + +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +COMP( 1980, trs80m3, 0, trs80l2, model3, trs80m3, trs80m3_state, init_trs80m3, "Tandy Radio Shack", "TRS-80 Model III", 0 ) +COMP( 1980, trs80m4, trs80m3, 0, model4, trs80m3, trs80m3_state, init_trs80m4, "Tandy Radio Shack", "TRS-80 Model 4", 0 ) +COMP( 1983, trs80m4p, trs80m3, 0, model4p, trs80m4p, trs80m3_state, init_trs80m4p, "Tandy Radio Shack", "TRS-80 Model 4P", 0 ) +COMP( 1982, cp500, trs80m3, 0, cp500, trs80m3, trs80m3_state, init_trs80m3, "Prológica", "CP-500 (PVIII REV.3)", 0 ) diff --git a/src/mame/includes/trs80.h b/src/mame/includes/trs80.h index b4fa3970dd8..128c46438e0 100644 --- a/src/mame/includes/trs80.h +++ b/src/mame/includes/trs80.h @@ -1,10 +1,6 @@ // license:BSD-3-Clause // copyright-holders:Juergen Buchmueller, Robbbert -/***************************************************************************** - * - * includes/trs80.h - * - ****************************************************************************/ +//***************************************************************************** #ifndef MAME_INCLUDES_TRS80_H #define MAME_INCLUDES_TRS80_H @@ -13,10 +9,13 @@ #include "bus/centronics/ctronics.h" #include "cpu/z80/z80.h" +#include "machine/bankdev.h" #include "imagedev/cassette.h" #include "imagedev/flopdrv.h" #include "imagedev/snapquik.h" #include "machine/ay31015.h" +#include "machine/com8116.h" +#include "bus/rs232/rs232.h" #include "machine/buffer.h" #include "machine/wd_fdc.h" #include "sound/spkrdev.h" @@ -35,10 +34,13 @@ public: , m_region_maincpu(*this, "maincpu") , m_p_chargen(*this, "chargen") , m_p_videoram(*this, "videoram") + , m_p_gfxram(*this, "gfxram") // LNW80 only + , m_lnw_bank(*this, "lnw_banked_mem") // LNW80 only , m_centronics(*this, "centronics") , m_cent_data_out(*this, "cent_data_out") , m_cent_status_in(*this, "cent_status_in") , m_uart(*this, "uart") + , m_brg(*this, "brg") , m_fdc(*this, "fdc") , m_floppy0(*this, "fdc:0") , m_floppy1(*this, "fdc:1") @@ -46,153 +48,88 @@ public: , m_floppy3(*this, "fdc:3") , m_speaker(*this, "speaker") , m_cassette(*this, "cassette") + , m_io_baud(*this, "BAUD") , m_io_config(*this, "CONFIG") , m_io_keyboard(*this, "LINE%u", 0) - , m_bank1(nullptr) - , m_bank2(nullptr) - , m_bank3(nullptr) - , m_bank4(nullptr) - , m_bank5(nullptr) - , m_bank6(nullptr) - , m_bank7(nullptr) - , m_bank8(nullptr) - , m_bank9(nullptr) - , m_bank11(nullptr) - , m_bank12(nullptr) - , m_bank13(nullptr) - , m_bank14(nullptr) - , m_bank15(nullptr) - , m_bank16(nullptr) - , m_bank17(nullptr) - , m_bank18(nullptr) - , m_bank19(nullptr) { } void sys80(machine_config &config); void trs80(machine_config &config); void lnw80(machine_config &config); - void model4p(machine_config &config); - void meritum(machine_config &config); - void model3(machine_config &config); void radionic(machine_config &config); void model1(machine_config &config); void ht1080z(machine_config &config); - void cp500(machine_config &config); - void model4(machine_config &config); - void init_trs80m4(); void init_trs80l2(); - void init_trs80m4p(); - void init_lnw80(); void init_trs80(); private: DECLARE_FLOPPY_FORMATS(floppy_formats); - DECLARE_WRITE8_MEMBER ( trs80_ff_w ); - DECLARE_WRITE8_MEMBER ( lnw80_fe_w ); - DECLARE_WRITE8_MEMBER ( sys80_fe_w ); - DECLARE_WRITE8_MEMBER ( sys80_f8_w ); - DECLARE_WRITE8_MEMBER ( trs80m4_ff_w ); - DECLARE_WRITE8_MEMBER ( trs80m4_f4_w ); - DECLARE_WRITE8_MEMBER ( trs80m4_ec_w ); - DECLARE_WRITE8_MEMBER ( trs80m4_ea_w ); - DECLARE_WRITE8_MEMBER ( trs80m4_e9_w ); - DECLARE_WRITE8_MEMBER ( trs80m4_e8_w ); - DECLARE_WRITE8_MEMBER ( trs80m4_e4_w ); - DECLARE_WRITE8_MEMBER ( trs80m4_e0_w ); - DECLARE_WRITE8_MEMBER ( trs80m4p_9c_w ); - DECLARE_WRITE8_MEMBER ( trs80m4_90_w ); - DECLARE_WRITE8_MEMBER ( trs80m4_84_w ); - DECLARE_READ8_MEMBER ( lnw80_fe_r ); - DECLARE_READ8_MEMBER ( trs80_ff_r ); - DECLARE_READ8_MEMBER ( sys80_f9_r ); - DECLARE_READ8_MEMBER ( trs80m4_ff_r ); - DECLARE_READ8_MEMBER ( trs80m4_ec_r ); - DECLARE_READ8_MEMBER ( trs80m4_ea_r ); - DECLARE_READ8_MEMBER ( trs80m4_e8_r ); - DECLARE_READ8_MEMBER ( trs80m4_e4_r ); - DECLARE_READ8_MEMBER ( trs80m4_e0_r ); - DECLARE_READ8_MEMBER( trs80_irq_status_r ); - DECLARE_READ8_MEMBER( trs80_printer_r ); - DECLARE_WRITE8_MEMBER( trs80_printer_w ); - DECLARE_WRITE8_MEMBER( trs80_cassunit_w ); - DECLARE_WRITE8_MEMBER( trs80_motor_w ); - DECLARE_READ8_MEMBER( trs80_keyboard_r ); - DECLARE_WRITE8_MEMBER ( trs80m4_88_w ); - DECLARE_READ8_MEMBER( trs80_videoram_r ); - DECLARE_WRITE8_MEMBER( trs80_videoram_w ); - DECLARE_READ8_MEMBER( trs80_gfxram_r ); - DECLARE_WRITE8_MEMBER( trs80_gfxram_w ); - DECLARE_READ8_MEMBER (trs80_wd179x_r); - DECLARE_READ8_MEMBER (cp500_a11_flipflop_toggle); + DECLARE_WRITE8_MEMBER(port_ff_w); + DECLARE_WRITE8_MEMBER(lnw80_fe_w); + DECLARE_WRITE8_MEMBER(sys80_fe_w); + DECLARE_WRITE8_MEMBER(sys80_f8_w); + DECLARE_WRITE8_MEMBER(port_ea_w); + DECLARE_WRITE8_MEMBER(port_e8_w); + DECLARE_READ8_MEMBER(lnw80_fe_r); + DECLARE_READ8_MEMBER(port_ff_r); + DECLARE_READ8_MEMBER(sys80_f9_r); + DECLARE_READ8_MEMBER(port_ea_r); + DECLARE_READ8_MEMBER(port_e8_r); + DECLARE_READ8_MEMBER(irq_status_r); + DECLARE_READ8_MEMBER(printer_r); + DECLARE_WRITE8_MEMBER(printer_w); + DECLARE_WRITE8_MEMBER(cassunit_w); + DECLARE_WRITE8_MEMBER(motor_w); + DECLARE_READ8_MEMBER(keyboard_r); + DECLARE_READ8_MEMBER(wd179x_r); - INTERRUPT_GEN_MEMBER(trs80_rtc_interrupt); - INTERRUPT_GEN_MEMBER(trs80_fdc_interrupt); + INTERRUPT_GEN_MEMBER(rtc_interrupt); + INTERRUPT_GEN_MEMBER(fdc_interrupt); TIMER_CALLBACK_MEMBER(cassette_data_callback); - DECLARE_WRITE_LINE_MEMBER(trs80_fdc_intrq_w); + DECLARE_WRITE_LINE_MEMBER(intrq_w); DECLARE_QUICKLOAD_LOAD_MEMBER( trs80_cmd ); - DECLARE_MACHINE_RESET(trs80m4); DECLARE_MACHINE_RESET(lnw80); - DECLARE_MACHINE_RESET(cp500); DECLARE_PALETTE_INIT(lnw80); uint32_t screen_update_trs80(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - uint32_t screen_update_trs80m4(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update_ht1080z(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update_lnw80(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update_radionic(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - uint32_t screen_update_meritum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void cp500_io(address_map &map); void lnw80_io(address_map &map); - void lnw80_map(address_map &map); - void meritum_io(address_map &map); - void meritum_map(address_map &map); - void model1_io(address_map &map); - void model1_map(address_map &map); - void model3_io(address_map &map); - void model3_map(address_map &map); - void model4_io(address_map &map); - void model4p_io(address_map &map); + void lnw80_mem(address_map &map); + void lnw_banked_mem(address_map &map); + void m1_io(address_map &map); + void m1_mem(address_map &map); void sys80_io(address_map &map); void trs80_io(address_map &map); - void trs80_map(address_map &map); + void trs80_mem(address_map &map); - uint8_t *m_p_gfxram; - uint8_t m_model4; uint8_t m_mode; uint8_t m_irq; uint8_t m_mask; - uint8_t m_nmi_mask; - uint8_t m_port_ec; uint8_t m_tape_unit; - uint8_t m_reg_load; - uint8_t m_nmi_data; -#ifdef USE_TRACK - uint8_t m_track[4]; -#endif - uint8_t m_head; -#ifdef USE_SECTOR - uint8_t m_sector[4]; -#endif - uint8_t m_cassette_data; + bool m_reg_load; + u8 m_lnw_mode; + bool m_cassette_data; emu_timer *m_cassette_data_timer; double m_old_cassette_val; - uint16_t m_start_address; - uint8_t m_crtc_reg; uint8_t m_size_store; - bool m_a11_flipflop; - void trs80_fdc_interrupt_internal(); + uint16_t m_timeout; + floppy_image_device *m_floppy; virtual void machine_start() override; virtual void machine_reset() override; - virtual void video_start() override; required_device m_maincpu; required_memory_region m_region_maincpu; required_region_ptr m_p_chargen; - optional_shared_ptr m_p_videoram; + optional_shared_ptr m_p_videoram; + optional_shared_ptr m_p_gfxram; + optional_device m_lnw_bank; optional_device m_centronics; optional_device m_cent_data_out; optional_device m_cent_status_in; optional_device m_uart; + optional_device m_brg; optional_device m_fdc; optional_device m_floppy0; optional_device m_floppy1; @@ -200,26 +137,9 @@ private: optional_device m_floppy3; required_device m_speaker; required_device m_cassette; - required_ioport m_io_config; + optional_ioport m_io_baud; + optional_ioport m_io_config; required_ioport_array<8> m_io_keyboard; - memory_bank *m_bank1; - memory_bank *m_bank2; - memory_bank *m_bank3; - memory_bank *m_bank4; - memory_bank *m_bank5; - memory_bank *m_bank6; - memory_bank *m_bank7; - memory_bank *m_bank8; - memory_bank *m_bank9; - memory_bank *m_bank11; - memory_bank *m_bank12; - memory_bank *m_bank13; - memory_bank *m_bank14; - memory_bank *m_bank15; - memory_bank *m_bank16; - memory_bank *m_bank17; - memory_bank *m_bank18; - memory_bank *m_bank19; }; #endif // MAME_INCLUDES_TRS80_H diff --git a/src/mame/includes/trs80m3.h b/src/mame/includes/trs80m3.h new file mode 100644 index 00000000000..446b03757cf --- /dev/null +++ b/src/mame/includes/trs80m3.h @@ -0,0 +1,159 @@ +// license:BSD-3-Clause +// copyright-holders:Robbbert +//***************************************************************************** + +#ifndef MAME_INCLUDES_TRS80M3_H +#define MAME_INCLUDES_TRS80M3_H + +#pragma once + +#include "bus/centronics/ctronics.h" +#include "cpu/z80/z80.h" +#include "machine/ram.h" +#include "machine/bankdev.h" +#include "imagedev/cassette.h" +#include "imagedev/flopdrv.h" +#include "imagedev/snapquik.h" +#include "machine/ay31015.h" +#include "machine/com8116.h" +#include "bus/rs232/rs232.h" +#include "machine/buffer.h" +#include "machine/wd_fdc.h" +#include "sound/spkrdev.h" +#include "sound/wave.h" +#include "emupal.h" + +#include "formats/trs_cas.h" + + +class trs80m3_state : public driver_device +{ +public: + trs80m3_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_region_maincpu(*this, "maincpu") + , m_p_chargen(*this, "chargen") + , m_p_videoram(*this, "videoram") + , m_bankdev(*this, "bankdev") + , m_centronics(*this, "centronics") + , m_cent_data_out(*this, "cent_data_out") + , m_cent_status_in(*this, "cent_status_in") + , m_uart(*this, "uart") + , m_brg(*this, "brg") + , m_fdc(*this, "fdc") + , m_floppy0(*this, "fdc:0") + , m_floppy1(*this, "fdc:1") + , m_floppy2(*this, "fdc:2") + , m_floppy3(*this, "fdc:3") + , m_speaker(*this, "speaker") + , m_cassette(*this, "cassette") + , m_io_config(*this, "CONFIG") + , m_io_keyboard(*this, "LINE%u", 0) + , m_mainram(*this, RAM_TAG) + , m_m4_bank(*this, "m4_banked_mem") + , m_m4p_bank(*this, "m4p_banked_mem") + , m_32kbanks(*this, "bank%u", 0U) + , m_16kbank(*this, "16kbank") + , m_vidbank(*this, "vidbank") + { } + + void model4p(machine_config &config); + void model3(machine_config &config); + void cp500(machine_config &config); + void model4(machine_config &config); + + void init_trs80m3(); + void init_trs80m4(); + void init_trs80m4p(); + +private: + DECLARE_FLOPPY_FORMATS(floppy_formats); + DECLARE_WRITE8_MEMBER(port_ff_w); + DECLARE_WRITE8_MEMBER(port_f4_w); + DECLARE_WRITE8_MEMBER(port_ec_w); + DECLARE_WRITE8_MEMBER(port_ea_w); + DECLARE_WRITE8_MEMBER(port_e8_w); + DECLARE_WRITE8_MEMBER(port_e4_w); + DECLARE_WRITE8_MEMBER(port_e0_w); + DECLARE_WRITE8_MEMBER(port_9c_w); + DECLARE_WRITE8_MEMBER(port_90_w); + DECLARE_WRITE8_MEMBER(port_88_w); + DECLARE_WRITE8_MEMBER(port_84_w); + DECLARE_READ8_MEMBER(port_ff_r); + DECLARE_READ8_MEMBER(port_ec_r); + DECLARE_READ8_MEMBER(port_ea_r); + DECLARE_READ8_MEMBER(port_e8_r); + DECLARE_READ8_MEMBER(port_e4_r); + DECLARE_READ8_MEMBER(port_e0_r); + DECLARE_READ8_MEMBER(printer_r); + DECLARE_WRITE8_MEMBER(printer_w); + DECLARE_READ8_MEMBER(keyboard_r); + DECLARE_READ8_MEMBER(wd179x_r); + DECLARE_READ8_MEMBER(cp500_port_f4_r); + + INTERRUPT_GEN_MEMBER(rtc_interrupt); + INTERRUPT_GEN_MEMBER(fdc_interrupt); + TIMER_CALLBACK_MEMBER(cassette_data_callback); + DECLARE_WRITE_LINE_MEMBER(intrq_w); + DECLARE_WRITE_LINE_MEMBER(drq_w); + DECLARE_QUICKLOAD_LOAD_MEMBER(trs80_cmd); + DECLARE_MACHINE_RESET(trs80m3); + DECLARE_MACHINE_RESET(cp500); + uint32_t screen_update_trs80m3(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + void cp500_io(address_map &map); + void m3_io(address_map &map); + void m3_mem(address_map &map); + void m4_io(address_map &map); + void m4p_io(address_map &map); + void m4_banked_mem(address_map &map); + void m4p_banked_mem(address_map &map); + + uint8_t m_model4; + uint8_t m_mode; + uint8_t m_irq; + uint8_t m_mask; + uint8_t m_nmi_mask; + uint8_t m_port_ec; + bool m_reg_load; + uint8_t m_nmi_data; + uint8_t m_cassette_data; + emu_timer *m_cassette_data_timer; + double m_old_cassette_val; + uint16_t m_start_address; + uint8_t m_crtc_reg; + uint8_t m_size_store; + bool m_a11_flipflop; + uint16_t m_timeout; + floppy_image_device *m_floppy; + virtual void machine_start() override; + virtual void machine_reset() override; + required_device m_maincpu; + required_memory_region m_region_maincpu; + required_region_ptr m_p_chargen; + optional_shared_ptr m_p_videoram; + optional_device m_bankdev; + optional_device m_centronics; + optional_device m_cent_data_out; + optional_device m_cent_status_in; + optional_device m_uart; + optional_device m_brg; + optional_device m_fdc; + optional_device m_floppy0; + optional_device m_floppy1; + optional_device m_floppy2; + optional_device m_floppy3; + required_device m_speaker; + required_device m_cassette; + optional_ioport m_io_config; + required_ioport_array<8> m_io_keyboard; + optional_device m_mainram; + optional_device m_m4_bank; + optional_device m_m4p_bank; + optional_memory_bank_array<2> m_32kbanks; + optional_memory_bank m_16kbank; + optional_memory_bank m_vidbank; +}; + +#endif // MAME_INCLUDES_TRS80M3_H diff --git a/src/mame/machine/trs80.cpp b/src/mame/machine/trs80.cpp index ed481085290..0f9005839c7 100644 --- a/src/mame/machine/trs80.cpp +++ b/src/mame/machine/trs80.cpp @@ -1,17 +1,6 @@ // license:BSD-3-Clause // copyright-holders:Juergen Buchmueller, Robbbert -/*************************************************************************** - - machine.c - - Functions to emulate general aspects of the machine (RAM, ROM, interrupts, - I/O ports) - -MAX_LUMPS 192 crude storage units - don't know much about it -MAX_GRANULES 8 lumps consisted of granules.. aha -MAX_SECTORS 5 and granules of sectors - -***************************************************************************/ +//*************************************************************************** #include "emu.h" #include "includes/trs80.h" @@ -19,10 +8,6 @@ MAX_SECTORS 5 and granules of sectors #define IRQ_M1_RTC 0x80 /* RTC on Model I */ #define IRQ_M1_FDC 0x40 /* FDC on Model I */ -#define IRQ_M4_RTC 0x04 /* RTC on Model 4 */ -#define CASS_RISE 0x01 /* high speed cass on Model III/4) */ -#define CASS_FALL 0x02 /* high speed cass on Model III/4) */ -#define MODEL4_MASTER_CLOCK 20275200 TIMER_CALLBACK_MEMBER(trs80_state::cassette_data_callback) @@ -34,25 +19,7 @@ TIMER_CALLBACK_MEMBER(trs80_state::cassette_data_callback) /* Check for HI-LO transition */ if ( m_old_cassette_val > -0.2 && new_val < -0.2 ) - { - m_cassette_data |= 0x80; /* 500 baud */ - if (m_mask & CASS_FALL) /* see if 1500 baud */ - { - m_cassette_data = 0; - m_irq |= CASS_FALL; - m_maincpu->set_input_line(0, HOLD_LINE); - } - } - else - if ( m_old_cassette_val < -0.2 && new_val > -0.2 ) - { - if (m_mask & CASS_RISE) /* 1500 baud */ - { - m_cassette_data = 1; - m_irq |= CASS_RISE; - m_maincpu->set_input_line(0, HOLD_LINE); - } - } + m_cassette_data = true; m_old_cassette_val = new_val; } @@ -65,44 +32,7 @@ TIMER_CALLBACK_MEMBER(trs80_state::cassette_data_callback) *************************************/ -READ8_MEMBER( trs80_state::trs80m4_e0_r ) -{ -/* Indicates which devices are interrupting - d6..d3 not emulated. - Whenever an interrupt occurs, this port is immediately read - to find out which device requires service. Lowest-numbered - bit takes precedence. We take this opportunity to clear the - cpu INT line. - - d6 RS232 Error (Any of {FE, PE, OR} errors has occurred) - d5 RS232 Rcv (DAV indicates a char ready to be picked up from uart) - d4 RS232 Xmit (TBMT indicates ready to accept another char from cpu) - d3 I/O Bus - d2 RTC - d1 Cass 1500 baud Falling - d0 Cass 1500 baud Rising */ - - m_maincpu->set_input_line(0, CLEAR_LINE); - return ~(m_mask & m_irq); -} - -READ8_MEMBER( trs80_state::trs80m4_e4_r ) -{ -/* Indicates which devices are interrupting - d6..d5 not emulated. - Whenever an NMI occurs, this port is immediately read - to find out which device requires service. Lowest-numbered - bit takes precedence. We take this opportunity to clear the - cpu NMI line. - - d7 status of FDC INTREQ (0=true) - d6 status of Motor Timeout (0=true) - d5 status of Reset signal (0=true - this will reboot the computer) */ - - m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); - - return ~(m_nmi_mask & m_nmi_data); -} - -READ8_MEMBER( trs80_state::trs80m4_e8_r ) +READ8_MEMBER( trs80_state::port_e8_r ) { /* not emulated d7 Clear-to-Send (CTS), Pin 5 @@ -115,7 +45,7 @@ READ8_MEMBER( trs80_state::trs80m4_e8_r ) return 0; } -READ8_MEMBER( trs80_state::trs80m4_ea_r ) +READ8_MEMBER( trs80_state::port_ea_r ) { /* UART Status Register d7 Data Received ('1'=condition true) @@ -137,308 +67,12 @@ READ8_MEMBER( trs80_state::trs80m4_ea_r ) return data; } -READ8_MEMBER( trs80_state::trs80m4_ec_r ) +WRITE8_MEMBER( trs80_state::port_e8_w ) { -/* Reset the RTC interrupt */ - m_irq &= ~IRQ_M4_RTC; - return 0; + m_reg_load = BIT(data, 1); } -READ8_MEMBER( trs80_state::sys80_f9_r ) -{ -/* UART Status Register - d6..d4 not emulated - d7 Transmit buffer empty (inverted) - d6 CTS pin - d5 DSR pin - d4 CD pin - d3 Parity Error - d2 Framing Error - d1 Overrun - d0 Data Available */ - - uint8_t data = 70; - m_uart->write_swe(0); - data |= m_uart->tbmt_r() ? 0 : 0x80; - data |= m_uart->dav_r( ) ? 0x01 : 0; - data |= m_uart->or_r( ) ? 0x02 : 0; - data |= m_uart->fe_r( ) ? 0x04 : 0; - data |= m_uart->pe_r( ) ? 0x08 : 0; - m_uart->write_swe(1); - - return data; -} - -READ8_MEMBER( trs80_state::lnw80_fe_r ) -{ - return ((m_mode & 0x78) >> 3) | 0xf0; -} - -READ8_MEMBER( trs80_state::trs80_ff_r ) -{ -/* ModeSel and cassette data - d7 cassette data from tape - d2 modesel setting */ - - uint8_t data = (~m_mode & 1) << 5; - return data | m_cassette_data; -} - -READ8_MEMBER( trs80_state::trs80m4_ff_r ) -{ -/* Return of cassette data stream from tape - d7 Low-speed data - d6..d1 info from write of port EC - d0 High-speed data */ - - m_irq &= 0xfc; /* clear cassette interrupts */ - - return m_port_ec | m_cassette_data; -} - -READ8_MEMBER( trs80_state::cp500_a11_flipflop_toggle ) -{ - /* The A11 flipflop is used for enabling access to - the system monitor code at the EPROM address range 3800-3fff */ - uint8_t *rom = memregion("maincpu")->base(); - uint8_t *bootrom = memregion("bootrom")->base(); - int block; - - m_a11_flipflop ^= 1; //toggle the flip-flop at every read at io addresses 0xf4-f7 - - for (block=0; block<8; block++){ - memcpy(&rom[block * 0x800], &bootrom[(block | m_a11_flipflop) * 0x800], 0x800); - } - - return 0x00; //really?! -} - - -WRITE8_MEMBER( trs80_state::trs80m4_84_w ) -{ -/* Hi-res graphics control - d6..d4 not emulated - d7 Page Control - d6 Fix upper memory - d5 Memory bit 1 - d4 Memory bit 0 - d3 Invert Video - d2 80/64 width - d1 Select bit 1 - d0 Select bit 0 */ - - /* get address space instead of io space */ - address_space &mem = m_maincpu->space(AS_PROGRAM); - uint8_t *base = m_region_maincpu->base(); - - m_mode = (m_mode & 0x73) | (data & 0x8c); - - m_model4 &= 0xce; - m_model4 |= (data & 3) << 4; - - switch (data & 3) - { - case 0: /* normal operation */ - - if (m_model4 & 4) /* Model 4P gets RAM while Model 4 gets ROM */ - { - if (m_model4 & 8) - m_bank1->set_base(base); - else - m_bank1->set_base(base + 0x10000); - - m_bank2->set_base(base + 0x11000); - m_bank4->set_base(base + 0x137ea); - } - else - { - m_bank1->set_base(base); - m_bank2->set_base(base + 0x01000); - m_bank4->set_base(base + 0x037ea); - } - - m_bank7->set_base(base + 0x14000); - m_bank8->set_base(base + 0x1f400); - m_bank9->set_base(base + 0x1f800); - m_bank11->set_base(base + 0x05000); - m_bank12->set_base(base + 0x06000); - m_bank14->set_base(base + 0x09000); - m_bank15->set_base(base + 0x0a000); - m_bank17->set_base(base + 0x14000); - m_bank18->set_base(base + 0x1f400); - m_bank19->set_base(base + 0x1f800); - mem.install_readwrite_handler (0x37e8, 0x37e9, read8_delegate(FUNC(trs80_state::trs80_printer_r), this), write8_delegate(FUNC(trs80_state::trs80_printer_w), this)); /* 3 & 13 */ - mem.install_read_handler (0x3800, 0x3bff, read8_delegate(FUNC(trs80_state::trs80_keyboard_r), this)); /* 5 */ - mem.install_readwrite_handler (0x3c00, 0x3fff, read8_delegate(FUNC(trs80_state::trs80_videoram_r), this), write8_delegate(FUNC(trs80_state::trs80_videoram_w), this)); /* 6 & 16 */ - break; - - case 1: /* write-only ram backs up the rom */ - - if (m_model4 & 4) /* Model 4P gets RAM while Model 4 gets ROM */ - { - if (m_model4 & 8) - m_bank1->set_base(base); - else - m_bank1->set_base(base + 0x10000); - - m_bank2->set_base(base + 0x11000); - m_bank3->set_base(base + 0x137e8); - m_bank4->set_base(base + 0x137ea); - } - else - { - m_bank1->set_base(base); - m_bank2->set_base(base + 0x01000); - m_bank3->set_base(base + 0x037e8); - m_bank4->set_base(base + 0x037ea); - } - - m_bank7->set_base(base + 0x14000); - m_bank8->set_base(base + 0x1f400); - m_bank9->set_base(base + 0x1f800); - m_bank11->set_base(base + 0x10000); - m_bank12->set_base(base + 0x11000); - m_bank13->set_base(base + 0x137e8); - m_bank14->set_base(base + 0x137ea); - m_bank15->set_base(base + 0x0a000); - m_bank17->set_base(base + 0x14000); - m_bank18->set_base(base + 0x1f400); - m_bank19->set_base(base + 0x1f800); - mem.install_read_handler (0x3800, 0x3bff, read8_delegate(FUNC(trs80_state::trs80_keyboard_r), this)); /* 5 */ - mem.install_readwrite_handler (0x3c00, 0x3fff, read8_delegate(FUNC(trs80_state::trs80_videoram_r), this), write8_delegate(FUNC(trs80_state::trs80_videoram_w), this)); /* 6 & 16 */ - break; - - case 2: /* keyboard and video are moved to high memory, and the rest is ram */ - m_bank1->set_base(base + 0x10000); - m_bank2->set_base(base + 0x11000); - m_bank3->set_base(base + 0x137e8); - m_bank4->set_base(base + 0x137ea); - m_bank5->set_base(base + 0x13800); - m_bank6->set_base(base + 0x13c00); - m_bank7->set_base(base + 0x14000); - m_bank11->set_base(base + 0x10000); - m_bank12->set_base(base + 0x11000); - m_bank13->set_base(base + 0x137e8); - m_bank14->set_base(base + 0x137ea); - m_bank15->set_base(base + 0x13800); - m_bank16->set_base(base + 0x13c00); - m_bank17->set_base(base + 0x14000); - m_bank18->set_base(base + 0x0a000); - mem.install_read_handler (0xf400, 0xf7ff, read8_delegate(FUNC(trs80_state::trs80_keyboard_r), this)); /* 8 */ - mem.install_readwrite_handler (0xf800, 0xffff, read8_delegate(FUNC(trs80_state::trs80_videoram_r), this), write8_delegate(FUNC(trs80_state::trs80_videoram_w), this)); /* 9 & 19 */ - m_model4++; - break; - - case 3: /* 64k of ram */ - m_bank1->set_base(base + 0x10000); - m_bank2->set_base(base + 0x11000); - m_bank3->set_base(base + 0x137e8); - m_bank4->set_base(base + 0x137ea); - m_bank5->set_base(base + 0x13800); - m_bank6->set_base(base + 0x13c00); - m_bank7->set_base(base + 0x14000); - m_bank8->set_base(base + 0x1f400); - m_bank9->set_base(base + 0x1f800); - m_bank11->set_base(base + 0x10000); - m_bank12->set_base(base + 0x11000); - m_bank13->set_base(base + 0x137e8); - m_bank14->set_base(base + 0x137ea); - m_bank15->set_base(base + 0x13800); - m_bank16->set_base(base + 0x13c00); - m_bank17->set_base(base + 0x14000); - m_bank18->set_base(base + 0x1f400); - m_bank19->set_base(base + 0x1f800); - break; - } -} - -WRITE8_MEMBER( trs80_state::trs80m4_90_w ) -{ - m_speaker->level_w(~data & 1); -} - -WRITE8_MEMBER( trs80_state::trs80m4p_9c_w ) /* model 4P only - swaps the ROM with read-only RAM */ -{ - /* Meaning of model4 variable: - d5..d4 memory mode (as described in section above) - d3 rom switch (1=enabled) only effective in mode0 and 1 - d2 this is a Model 4P - d1 this is a Model 4 - d0 Video banking exists yes/no (1=not banked) */ - - m_model4 &= 0xf7; - m_model4 |= (data << 3); - - if ((m_model4) && (~m_model4 & 0x20)) - { - switch (m_model4 & 8) - { - case 0: /* Read-only RAM replaces rom */ - m_bank1->set_base(m_region_maincpu->base() + 0x10000); - break; - case 8: /* Normal setup - rom enabled */ - m_bank1->set_base(m_region_maincpu->base()); - break; - } - } -} - -WRITE8_MEMBER( trs80_state::trs80m4_e0_w ) -{ -/* Interrupt settings - which devices are allowed to interrupt - bits align with read of E0 - d6 Enable Rec Err - d5 Enable Rec Data - d4 Enable Xmit Emp - d3 Enable I/O int - d2 Enable RT int - d1 C fall Int - d0 C Rise Int */ - - m_mask = data; -} - -WRITE8_MEMBER( trs80_state::trs80m4_e4_w ) -{ -/* Disk to NMI interface - d7 1=enable disk INTRQ to generate NMI - d6 1=enable disk Motor Timeout to generate NMI */ - - m_nmi_mask = data; -} - -WRITE8_MEMBER( trs80_state::trs80m4_e8_w ) -{ -/* d1 when '1' enables control register load (see below) */ - - m_reg_load = data & 2; -} - -WRITE8_MEMBER( trs80_state::trs80m4_e9_w ) -{ -/* UART set baud rate. Rx = bits 0..3, Tx = bits 4..7 - 00h 50 - 11h 75 - 22h 110 - 33h 134.5 - 44h 150 - 55h 300 - 66h 600 - 77h 1200 - 88h 1800 - 99h 2000 - AAh 2400 - BBh 3600 - CCh 4800 - DDh 7200 - EEh 9600 - FFh 19200 -Note: this may be a COM5016 dual baud rate generator, or may be an equivalent circuit embedded in the gate array ASIC on the trs80 model 4 - */ - - static const int baud_clock[]={ 800, 1200, 1760, 2152, 2400, 4800, 9600, 19200, 28800, 32000, 38400, 57600, 76800, 115200, 153600, 307200 }; - m_uart->set_receiver_clock(baud_clock[data & 0x0f]); - m_uart->set_transmitter_clock(baud_clock[data >> 4]); -} - -WRITE8_MEMBER( trs80_state::trs80m4_ea_w ) +WRITE8_MEMBER( trs80_state::port_ea_w ) { if (m_reg_load) @@ -477,54 +111,43 @@ WRITE8_MEMBER( trs80_state::trs80m4_ea_w ) } } -WRITE8_MEMBER( trs80_state::trs80m4_ec_w ) -{ -/* Hardware settings - d5..d4 not emulated - d6 CPU fast (1=4MHz, 0=2MHz) - d5 1=Enable Video Wait - d4 1=Enable External I/O bus - d3 1=Enable Alternate Character Set - d2 Mode Select (0=64 chars, 1=32chars) - d1 Cassette Motor (1=On) */ - - m_maincpu->set_unscaled_clock(data & 0x40 ? MODEL4_MASTER_CLOCK/5 : MODEL4_MASTER_CLOCK/10); - m_mode = (m_mode & 0xde) | ((data & 4) ? 1 : 0) | ((data & 8) ? 0x20 : 0); +READ8_MEMBER( trs80_state::sys80_f9_r ) +{ +/* UART Status Register - d6..d4 not emulated + d7 Transmit buffer empty (inverted) + d6 CTS pin + d5 DSR pin + d4 CD pin + d3 Parity Error + d2 Framing Error + d1 Overrun + d0 Data Available */ - m_cassette->change_state(( data & 2 ) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR ); + uint8_t data = 0x70; + m_uart->write_swe(0); + data |= m_uart->tbmt_r() ? 0 : 0x80; + data |= m_uart->dav_r( ) ? 0x01 : 0; + data |= m_uart->or_r( ) ? 0x02 : 0; + data |= m_uart->fe_r( ) ? 0x04 : 0; + data |= m_uart->pe_r( ) ? 0x08 : 0; + m_uart->write_swe(1); - m_port_ec = data & 0x7e; + return data; } -/* Selection of drive and parameters - d6..d5 not emulated. - A write also causes the selected drive motor to turn on for about 3 seconds. - When the motor turns off, the drive is deselected. - d7 1=MFM, 0=FM - d6 1=Wait - d5 1=Write Precompensation enabled - d4 0=Side 0, 1=Side 1 - d3 1=select drive 3 - d2 1=select drive 2 - d1 1=select drive 1 - d0 1=select drive 0 */ -WRITE8_MEMBER( trs80_state::trs80m4_f4_w ) +READ8_MEMBER( trs80_state::lnw80_fe_r ) { - floppy_image_device *floppy = nullptr; - - if (BIT(data, 0)) floppy = m_floppy0->get_device(); - if (BIT(data, 1)) floppy = m_floppy1->get_device(); - if (BIT(data, 2)) floppy = m_floppy2->get_device(); - if (BIT(data, 3)) floppy = m_floppy3->get_device(); - - m_fdc->set_floppy(floppy); + return m_lnw_mode; +} - if (floppy) - { - floppy->mon_w(0); - floppy->ss_w(BIT(data, 4)); - } +READ8_MEMBER( trs80_state::port_ff_r ) +{ +/* ModeSel and cassette data + d7 cassette data from tape + d6 modesel setting */ - m_fdc->dden_w(!BIT(data, 7)); + return (BIT(m_mode, 0) ? 0 : 0x40) | (m_cassette_data ? 0x80 : 0) | 0x3f; } WRITE8_MEMBER( trs80_state::sys80_f8_w ) @@ -540,7 +163,7 @@ WRITE8_MEMBER( trs80_state::sys80_fe_w ) /* not emulated d4 select internal or external cassette player */ - m_tape_unit = (data & 0x10) ? 2 : 1; + m_tape_unit = BIT(data, 4) ? 2 : 1; } /* lnw80 can switch out all the devices, roms and video ram to be replaced by graphics ram. */ @@ -549,137 +172,77 @@ WRITE8_MEMBER( trs80_state::lnw80_fe_w ) /* lnw80 video options d3 bankswitch lower 16k between roms and hires ram (1=hires) d2 enable colour \ - d1 hres / these 2 are the bits from the MODE command of LNWBASIC + d1 hres / these 2 are the bits from the MODE command of LNWBASIC d0 inverse video (entire screen) */ - /* get address space instead of io space */ - address_space &mem = m_maincpu->space(AS_PROGRAM); - - m_mode = (m_mode & 0x87) | ((data & 0x0f) << 3); + m_lnw_mode = data; - if (data & 8) - { - mem.unmap_readwrite (0x0000, 0x3fff); - mem.install_readwrite_handler (0x0000, 0x3fff, read8_delegate(FUNC(trs80_state::trs80_gfxram_r), this), write8_delegate(FUNC(trs80_state::trs80_gfxram_w), this)); - } - else - { - mem.unmap_readwrite (0x0000, 0x3fff); - mem.install_read_bank (0x0000, 0x2fff, "bank1"); - membank("bank1")->set_base(m_region_maincpu->base()); - mem.install_readwrite_handler (0x37e0, 0x37e3, read8_delegate(FUNC(trs80_state::trs80_irq_status_r), this), write8_delegate(FUNC(trs80_state::trs80_motor_w), this)); - mem.install_readwrite_handler (0x37e8, 0x37eb, read8_delegate(FUNC(trs80_state::trs80_printer_r), this), write8_delegate(FUNC(trs80_state::trs80_printer_w), this)); - mem.install_read_handler (0x37ec, 0x37ec, read8_delegate(FUNC(trs80_state::trs80_wd179x_r), this)); - mem.install_write_handler (0x37ec, 0x37ec, write8_delegate(FUNC(fd1793_device::cmd_w),(fd1793_device*)m_fdc)); - mem.install_readwrite_handler (0x37ed, 0x37ed, read8_delegate(FUNC(fd1793_device::track_r),(fd1793_device*)m_fdc), write8_delegate(FUNC(fd1793_device::track_w),(fd1793_device*)m_fdc)); - mem.install_readwrite_handler (0x37ee, 0x37ee, read8_delegate(FUNC(fd1793_device::sector_r),(fd1793_device*)m_fdc), write8_delegate(FUNC(fd1793_device::sector_w),(fd1793_device*)m_fdc)); - mem.install_readwrite_handler (0x37ef, 0x37ef, read8_delegate(FUNC(fd1793_device::data_r),(fd1793_device*)m_fdc),write8_delegate( FUNC(fd1793_device::data_w),(fd1793_device*)m_fdc)); - mem.install_read_handler (0x3800, 0x38ff, 0, 0x0300, 0, read8_delegate(FUNC(trs80_state::trs80_keyboard_r), this)); - mem.install_readwrite_handler (0x3c00, 0x3fff, read8_delegate(FUNC(trs80_state::trs80_videoram_r), this), write8_delegate(FUNC(trs80_state::trs80_videoram_w), this)); - } + m_lnw_bank->set_bank(BIT(data, 3)); } -WRITE8_MEMBER( trs80_state::trs80_ff_w ) +WRITE8_MEMBER( trs80_state::port_ff_w ) { /* Standard output port of Model I d3 ModeSel bit d2 Relay d1, d0 Cassette output */ - static const double levels[4] = { 0.0, -1.0, 0.0, 1.0 }; - static int init = 0; + static const double levels[4] = { 0.0, 1.0, -1.0, 0.0 }; + static bool init = 0; - m_cassette->change_state(( data & 4 ) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR ); + m_cassette->change_state(BIT(data, 2) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR ); m_cassette->output(levels[data & 3]); - m_cassette_data &= ~0x80; + m_cassette_data = false; - m_mode = (m_mode & 0xfe) | ((data & 8) >> 3); + m_mode = (m_mode & 0xfe) | BIT(data, 3); if (!init) { init = 1; - static int16_t speaker_levels[4] = { 0, -32768, 0, 32767 }; + static int16_t speaker_levels[4] = { 0, -32767, 0, 32767 }; m_speaker->set_levels(4, speaker_levels); } /* Speaker for System-80 MK II - only sounds if relay is off */ - if (~data & 4) + if (!(BIT(data, 2))) m_speaker->level_w(data & 3); } -WRITE8_MEMBER( trs80_state::trs80m4_ff_w ) -{ -/* Cassette port - d1, d0 Cassette output */ - - static const double levels[4] = { 0.0, -1.0, 0.0, 1.0 }; - m_cassette->output(levels[data & 3]); - m_cassette_data &= ~0x80; -} - - /************************************* * * Interrupt handlers. * *************************************/ -INTERRUPT_GEN_MEMBER(trs80_state::trs80_rtc_interrupt) +INTERRUPT_GEN_MEMBER(trs80_state::rtc_interrupt) { /* This enables the processing of interrupts for the clock and the flashing cursor. - The OS counts one tick for each interrupt. The Model I has 40 ticks per - second, while the Model III/4 has 30. */ + The OS counts one tick for each interrupt. It is called 40 times per second. */ - if (m_model4) // Model 4 - { - if (m_mask & IRQ_M4_RTC) - { - m_irq |= IRQ_M4_RTC; - device.execute().set_input_line(0, HOLD_LINE); - } - } - else // Model 1 - { - m_irq |= IRQ_M1_RTC; - device.execute().set_input_line(0, HOLD_LINE); - } -} + m_irq |= IRQ_M1_RTC; + m_maincpu->set_input_line(0, HOLD_LINE); -void trs80_state::trs80_fdc_interrupt_internal() -{ - if (m_model4) - { - if (m_nmi_mask & 0x80) // Model 4 does a NMI - { - m_nmi_data = 0x80; - m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero); - } - } - else // Model 1 does a IRQ - { - m_irq |= IRQ_M1_FDC; - m_maincpu->set_input_line(0, HOLD_LINE); - } + // While we're here, let's countdown the motor timeout too. + // Let's not... LDOS often freezes +// if (m_timeout) +// { +// m_timeout--; +// if (m_timeout == 0) +// if (m_floppy) +// m_floppy->mon_w(1); // motor off +// } } -INTERRUPT_GEN_MEMBER(trs80_state::trs80_fdc_interrupt)/* not used - should it be? */ -{ - trs80_fdc_interrupt_internal(); -} -WRITE_LINE_MEMBER(trs80_state::trs80_fdc_intrq_w) +WRITE_LINE_MEMBER(trs80_state::intrq_w) { if (state) { - trs80_fdc_interrupt_internal(); + m_irq |= IRQ_M1_FDC; + m_maincpu->set_input_line(0, HOLD_LINE); } else - { - if (m_model4) - m_nmi_data = 0; - else - m_irq &= ~IRQ_M1_FDC; - } + m_irq &= ~IRQ_M1_FDC; } @@ -689,7 +252,7 @@ WRITE_LINE_MEMBER(trs80_state::trs80_fdc_intrq_w) * * *************************************/ -READ8_MEMBER( trs80_state::trs80_wd179x_r ) +READ8_MEMBER( trs80_state::wd179x_r ) { uint8_t data = 0xff; if (BIT(m_io_config->read(), 7)) @@ -698,19 +261,19 @@ READ8_MEMBER( trs80_state::trs80_wd179x_r ) return data; } -READ8_MEMBER( trs80_state::trs80_printer_r ) +READ8_MEMBER( trs80_state::printer_r ) { return m_cent_status_in->read(); } -WRITE8_MEMBER( trs80_state::trs80_printer_w ) +WRITE8_MEMBER( trs80_state::printer_w ) { m_cent_data_out->write(data); m_centronics->write_strobe(0); m_centronics->write_strobe(1); } -WRITE8_MEMBER( trs80_state::trs80_cassunit_w ) +WRITE8_MEMBER( trs80_state::cassunit_w ) { /* not emulated 01 for unit 1 (default) @@ -719,7 +282,7 @@ WRITE8_MEMBER( trs80_state::trs80_cassunit_w ) m_tape_unit = data; } -READ8_MEMBER( trs80_state::trs80_irq_status_r ) +READ8_MEMBER( trs80_state::irq_status_r ) { /* (trs80l2) Whenever an interrupt occurs, 37E0 is read to see what devices require service. d7 = RTC @@ -728,28 +291,29 @@ READ8_MEMBER( trs80_state::trs80_irq_status_r ) All interrupting devices are serviced in a single interrupt. There is a mask byte, which is dealt with by the DOS. We take the opportunity to reset the cpu INT line. */ - int result = m_irq; + u8 result = m_irq; m_maincpu->set_input_line(0, CLEAR_LINE); m_irq = 0; return result; } -WRITE8_MEMBER( trs80_state::trs80_motor_w ) +WRITE8_MEMBER( trs80_state::motor_w ) { - floppy_image_device *floppy = nullptr; + m_floppy = nullptr; - if (BIT(data, 0)) floppy = m_floppy0->get_device(); - if (BIT(data, 1)) floppy = m_floppy1->get_device(); - if (BIT(data, 2)) floppy = m_floppy2->get_device(); - if (BIT(data, 3)) floppy = m_floppy3->get_device(); + 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(floppy); + m_fdc->set_floppy(m_floppy); - if (floppy) + if (m_floppy) { - floppy->mon_w(0); - floppy->ss_w(BIT(data, 4)); + m_floppy->mon_w(0); + m_floppy->ss_w(BIT(data, 4)); + m_timeout = 200; } // switch to fm @@ -759,7 +323,7 @@ WRITE8_MEMBER( trs80_state::trs80_motor_w ) /************************************* * Keyboard * *************************************/ -READ8_MEMBER( trs80_state::trs80_keyboard_r ) +READ8_MEMBER( trs80_state::keyboard_r ) { u8 i, result = 0; @@ -777,9 +341,9 @@ READ8_MEMBER( trs80_state::trs80_keyboard_r ) void trs80_state::machine_start() { + m_size_store = 0xff; m_tape_unit=1; m_reg_load=1; - m_nmi_data=0xff; m_cassette_data_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(trs80_state::cassette_data_callback),this)); m_cassette_data_timer->adjust( attotime::zero, 0, attotime::from_hz(11025) ); @@ -787,69 +351,25 @@ void trs80_state::machine_start() void trs80_state::machine_reset() { - m_cassette_data = 0; -} - -MACHINE_RESET_MEMBER(trs80_state,trs80m4) -{ - address_space &mem = m_maincpu->space(AS_PROGRAM); - m_cassette_data = 0; - - mem.install_read_bank (0x0000, 0x0fff, "bank1"); - m_bank1 = membank("bank1"); - mem.install_read_bank (0x1000, 0x37e7, "bank2"); - m_bank2 = membank("bank2"); - mem.install_read_bank (0x37e8, 0x37e9, "bank3"); - m_bank3 = membank("bank3"); - mem.install_read_bank (0x37ea, 0x37ff, "bank4"); - m_bank4 = membank("bank4"); - mem.install_read_bank (0x3800, 0x3bff, "bank5"); - m_bank5 = membank("bank5"); - mem.install_read_bank (0x3c00, 0x3fff, "bank6"); - m_bank6 = membank("bank6"); - mem.install_read_bank (0x4000, 0xf3ff, "bank7"); - m_bank7 = membank("bank7"); - mem.install_read_bank (0xf400, 0xf7ff, "bank8"); - m_bank8 = membank("bank8"); - mem.install_read_bank (0xf800, 0xffff, "bank9"); - m_bank9 = membank("bank9"); - - mem.install_write_bank (0x0000, 0x0fff, "bank11"); - m_bank11 = membank("bank11"); - mem.install_write_bank (0x1000, 0x37e7, "bank12"); - m_bank12 = membank("bank12"); - mem.install_write_bank (0x37e8, 0x37e9, "bank13"); - m_bank13 = membank("bank13"); - mem.install_write_bank (0x37ea, 0x37ff, "bank14"); - m_bank14 = membank("bank14"); - mem.install_write_bank (0x3800, 0x3bff, "bank15"); - m_bank15 = membank("bank15"); - mem.install_write_bank (0x3c00, 0x3fff, "bank16"); - m_bank16 = membank("bank16"); - mem.install_write_bank (0x4000, 0xf3ff, "bank17"); - m_bank17 = membank("bank17"); - mem.install_write_bank (0xf400, 0xf7ff, "bank18"); - m_bank18 = membank("bank18"); - mem.install_write_bank (0xf800, 0xffff, "bank19"); - m_bank19 = membank("bank19"); - trs80m4p_9c_w(mem, 0, 1); /* Enable the ROM */ - trs80m4_84_w(mem, 0, 0); /* switch in devices at power-on */ + m_cassette_data = false; + if (m_io_baud) + { + const uint16_t s_bauds[8]={ 110, 300, 600, 1200, 2400, 4800, 9600, 19200 }; + u16 s_clock = s_bauds[m_io_baud->read()] << 4; + m_uart->set_receiver_clock(s_clock); + m_uart->set_transmitter_clock(s_clock); + } } MACHINE_RESET_MEMBER(trs80_state,lnw80) { - address_space &space = m_maincpu->space(AS_PROGRAM); - m_cassette_data = 0; + machine_reset(); + address_space &space = m_maincpu->space(AS_IO); m_reg_load = 1; + m_lnw_mode = 0; lnw80_fe_w(space, 0, 0); } -MACHINE_RESET_MEMBER(trs80_state,cp500) -{ - m_a11_flipflop = 0; - MACHINE_RESET_CALL_MEMBER( trs80m4 ); -} - /*************************************************************************** PARAMETERS diff --git a/src/mame/machine/trs80m3.cpp b/src/mame/machine/trs80m3.cpp new file mode 100644 index 00000000000..01d8ce05ecc --- /dev/null +++ b/src/mame/machine/trs80m3.cpp @@ -0,0 +1,660 @@ +// license:BSD-3-Clause +// copyright-holders:Robbbert +//************************************************************************************************************************** + +#include "emu.h" +#include "includes/trs80m3.h" + + +#define IRQ_M4_RTC 0x04 /* RTC on Model 4 */ +#define CASS_RISE 0x01 /* high speed cass on Model III/4) */ +#define CASS_FALL 0x02 /* high speed cass on Model III/4) */ +#define MODEL4_MASTER_CLOCK 20275200 + + +TIMER_CALLBACK_MEMBER(trs80m3_state::cassette_data_callback) +{ +/* This does all baud rates. 250 baud (trs80), and 500 baud (all others) set bit 7 of "cassette_data". + 1500 baud (trs80m3, trs80m4) is interrupt-driven and uses bit 0 of "cassette_data" */ + + double new_val = (m_cassette->input()); + + /* Check for HI-LO transition */ + if ( m_old_cassette_val > -0.2 && new_val < -0.2 ) + { + m_cassette_data |= 0x80; /* 500 baud */ + if (m_mask & CASS_FALL) /* see if 1500 baud */ + { + m_cassette_data = 0; + m_irq |= CASS_FALL; + m_maincpu->set_input_line(0, HOLD_LINE); + } + } + else + if ( m_old_cassette_val < -0.2 && new_val > -0.2 ) + { + if (m_mask & CASS_RISE) /* 1500 baud */ + { + m_cassette_data = 1; + m_irq |= CASS_RISE; + m_maincpu->set_input_line(0, HOLD_LINE); + } + } + + m_old_cassette_val = new_val; +} + + +/************************************* + * + * Port handlers. + * + *************************************/ + + +READ8_MEMBER( trs80m3_state::port_e0_r ) +{ +/* Indicates which devices are interrupting - d6..d3 not emulated. + Whenever an interrupt occurs, this port is immediately read + to find out which device requires service. Lowest-numbered + bit takes precedence. We take this opportunity to clear the + cpu INT line. + + d6 RS232 Error (Any of {FE, PE, OR} errors has occurred) + d5 RS232 Rcv (DAV indicates a char ready to be picked up from uart) + d4 RS232 Xmit (TBMT indicates ready to accept another char from cpu) + d3 I/O Bus + d2 RTC + d1 Cass 1500 baud Falling + d0 Cass 1500 baud Rising */ + + m_maincpu->set_input_line(0, CLEAR_LINE); + return ~(m_mask & m_irq); +} + +READ8_MEMBER( trs80m3_state::port_e4_r ) +{ +/* Indicates which devices are interrupting - d6..d5 not emulated. + Whenever an NMI occurs, this port is immediately read + to find out which device requires service. Lowest-numbered + bit takes precedence. We take this opportunity to clear the + cpu NMI line. + + d7 status of FDC INTREQ (0=true) + d6 status of Motor Timeout (0=true) + d5 status of Reset signal (0=true - this will reboot the computer) */ + + m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); + + return ~(m_nmi_mask & m_nmi_data); +} + +READ8_MEMBER( trs80m3_state::port_e8_r ) +{ +/* not emulated + d7 Clear-to-Send (CTS), Pin 5 + d6 Data-Set-Ready (DSR), pin 6 + d5 Carrier Detect (CD), pin 8 + d4 Ring Indicator (RI), pin 22 + d3,d2,d0 Not used + d1 UART Receiver Input, pin 20 (pin 20 is also DTR) */ + + return 0; +} + +READ8_MEMBER( trs80m3_state::port_ea_r ) +{ +/* UART Status Register + d7 Data Received ('1'=condition true) + d6 Transmitter Holding Register empty ('1'=condition true) + d5 Overrun Error ('1'=condition true) + d4 Framing Error ('1'=condition true) + d3 Parity Error ('1'=condition true) + d2..d0 Not used */ + + uint8_t data=7; + m_uart->write_swe(0); + data |= m_uart->tbmt_r() ? 0x40 : 0; + data |= m_uart->dav_r( ) ? 0x80 : 0; + data |= m_uart->or_r( ) ? 0x20 : 0; + data |= m_uart->fe_r( ) ? 0x10 : 0; + data |= m_uart->pe_r( ) ? 0x08 : 0; + m_uart->write_swe(1); + + return data; +} + +READ8_MEMBER( trs80m3_state::port_ec_r ) +{ +/* Reset the RTC interrupt */ + m_irq &= ~IRQ_M4_RTC; + return 0; +} + +READ8_MEMBER( trs80m3_state::port_ff_r ) +{ +/* Return of cassette data stream from tape + d7 Low-speed data + d6..d1 info from write of port EC + d0 High-speed data */ + + m_irq &= 0xfc; /* clear cassette interrupts */ + + return m_port_ec | m_cassette_data; +} + +READ8_MEMBER( trs80m3_state::cp500_port_f4_r ) +{ + /* The A11 flipflop is used for enabling access to + the system monitor code at the EPROM address range 3800-3fff */ + uint8_t *rom = memregion("maincpu")->base(); + uint8_t *bootrom = memregion("bootrom")->base(); + + m_a11_flipflop ^= 1; //toggle the flip-flop at every read at io addresses 0xf4-f7 + + for (u8 block=0; block<8; block++) + memcpy(&rom[block * 0x800], &bootrom[(block | m_a11_flipflop) * 0x800], 0x800); + + return 0x00; //really?! +} + + +WRITE8_MEMBER( trs80m3_state::port_84_w ) // Model 4 & 4P only +{ +/* Hi-res graphics control - d6..d4 not emulated + d7 Page Control + d6 Fix upper memory + d5 Memory bit 1 + d4 Memory bit 0 + d3 Invert Video + d2 80/64 width + d1 Select bit 1 + d0 Select bit 0 */ + + if (!(m_model4 & 6)) // Model 3 leave now + return; + + m_mode = (m_mode & 0x73) | (data & 0x8c); + + m_model4 &= 0xce; + m_model4 |= (data & 3) << 4; + + if (BIT(m_model4, 1)) // Model 4 + { + if (m_mainram->size() >= (64 * 1024)) + { + m_m4_bank->set_bank(data & 0x03); + m_32kbanks[0]->set_entry((data >> 4) & 0x07); + m_32kbanks[1]->set_entry((data >> 4) & 0x07); + m_16kbank->set_entry((data >> 4) & 0x07); + } + m_vidbank->set_entry(BIT(data, 7)); + return; + } + + if (BIT(m_model4, 2)) // Model 4P + { + if (m_mainram->size() >= (64 * 1024)) + { + m_32kbanks[0]->set_entry((data >> 4) & 0x07); + m_32kbanks[1]->set_entry((data >> 4) & 0x07); + m_16kbank->set_entry((data >> 4) & 0x07); + } + m_vidbank->set_entry(BIT(data, 7)); + + switch (data & 3) + { + case 0: /* normal operation */ + if (BIT(m_model4, 3)) + m_m4p_bank->set_bank(0); + else + m_m4p_bank->set_bank(4); + break; + + case 1: /* write-only ram backs up the rom */ + if (BIT(m_model4, 3)) + m_m4p_bank->set_bank(1); + else + m_m4p_bank->set_bank(5); + break; + + case 2: /* keyboard and video are moved to high memory, and the rest is ram */ + m_m4p_bank->set_bank(2); + m_model4 |= 1; + break; + + case 3: /* 64k of ram */ + m_m4p_bank->set_bank(3); + break; + } + } +} + +WRITE8_MEMBER( trs80m3_state::port_90_w ) +{ + m_speaker->level_w(!(BIT(data, 0))); +} + +WRITE8_MEMBER( trs80m3_state::port_9c_w ) /* model 4P only - swaps the ROM with read-only RAM */ +{ + /* Meaning of model4 variable: + d5..d4 memory mode (as described in section above) + d3 rom switch (1=enabled) only effective in mode0 and 1 + d2 this is a Model 4P + d1 this is a Model 4 + d0 Video banking exists yes/no (1=not banked) */ + + if (!(BIT(m_model4, 2))) // If not Model 4P, leave now + return; + + m_model4 &= 0xf7; + m_model4 |= (data << 3); + + switch (m_model4 & 0x38) + { + case 0x00: + m_m4p_bank->set_bank(4); + break; + + case 0x08: + m_m4p_bank->set_bank(0); + break; + + case 0x10: + m_m4p_bank->set_bank(5); + break; + + case 0x18: + m_m4p_bank->set_bank(1); + break; + + default: + break; + } +} + +WRITE8_MEMBER( trs80m3_state::port_e0_w ) +{ +/* Interrupt settings - which devices are allowed to interrupt - bits align with read of E0 + d6 Enable Rec Err + d5 Enable Rec Data + d4 Enable Xmit Emp + d3 Enable I/O int + d2 Enable RT int + d1 C fall Int + d0 C Rise Int */ + + m_mask = data; +} + +WRITE8_MEMBER( trs80m3_state::port_e4_w ) +{ +/* Disk to NMI interface + d7 1=enable disk INTRQ to generate NMI + d6 1=enable disk Motor Timeout to generate NMI */ + + m_nmi_mask = data; +} + +WRITE8_MEMBER( trs80m3_state::port_e8_w ) +{ +/* d1 when '1' enables control register load (see below) */ + + m_reg_load = BIT(data, 1); +} + +WRITE8_MEMBER( trs80m3_state::port_ea_w ) +{ + if (m_reg_load) + +/* d2..d0 not emulated + d7 Even Parity Enable ('1'=even, '0'=odd) + d6='1',d5='1' for 8 bits + d6='0',d5='1' for 7 bits + d6='1',d5='0' for 6 bits + d6='0',d5='0' for 5 bits + d4 Stop Bit Select ('1'=two stop bits, '0'=one stop bit) + d3 Parity Inhibit ('1'=disable; No parity, '0'=parity enabled) + d2 Break ('0'=disable transmit data; continuous RS232 'SPACE' condition) + d1 Request-to-Send (RTS), pin 4 + d0 Data-Terminal-Ready (DTR), pin 20 */ + + { + m_uart->write_cs(0); + m_uart->write_nb1(BIT(data, 6)); + m_uart->write_nb2(BIT(data, 5)); + m_uart->write_tsb(BIT(data, 4)); + m_uart->write_eps(BIT(data, 7)); + m_uart->write_np(BIT(data, 3)); + m_uart->write_cs(1); + } + else + { +/* not emulated + d7,d6 Not used + d5 Secondary Unassigned, pin 18 + d4 Secondary Transmit Data, pin 14 + d3 Secondary Request-to-Send, pin 19 + d2 Break ('0'=disable transmit data; continuous RS232 'SPACE' condition) + d1 Data-Terminal-Ready (DTR), pin 20 + d0 Request-to-Send (RTS), pin 4 */ + + } +} + +WRITE8_MEMBER( trs80m3_state::port_ec_w ) +{ +/* Hardware settings - d5..d4 not emulated + d6 CPU fast (1=4MHz, 0=2MHz) + d5 1=Enable Video Wait + d4 1=Enable External I/O bus + d3 1=Enable Alternate Character Set + d2 Mode Select (0=64 chars, 1=32chars) + d1 Cassette Motor (1=On) */ + + m_maincpu->set_unscaled_clock(data & 0x40 ? MODEL4_MASTER_CLOCK/5 : MODEL4_MASTER_CLOCK/10); + + m_mode = (m_mode & 0xde) | ((data & 4) ? 1 : 0) | ((data & 8) ? 0x20 : 0); + + m_cassette->change_state(( data & 2 ) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR ); + + m_port_ec = data & 0x7e; +} + +/* Selection of drive and parameters - d6..d5 not emulated. + A write also causes the selected drive motor to turn on for about 3 seconds. + When the motor turns off, the drive is deselected. + d7 1=MFM, 0=FM + d6 1=Wait + d5 1=Write Precompensation enabled + d4 0=Side 0, 1=Side 1 + d3 1=select drive 3 + d2 1=select drive 2 + d1 1=select drive 1 + d0 1=select drive 0 */ +WRITE8_MEMBER( trs80m3_state::port_f4_w ) +{ + m_maincpu->set_input_line(Z80_INPUT_LINE_WAIT, BIT(data, 6) ? ASSERT_LINE : CLEAR_LINE); + + m_floppy = nullptr; + + 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) + { + m_floppy->mon_w(0); + m_floppy->ss_w(BIT(data, 4)); + m_timeout = 160; + } + + m_fdc->dden_w(!BIT(data, 7)); +} + +WRITE8_MEMBER( trs80m3_state::port_ff_w ) +{ +/* Cassette port + d1, d0 Cassette output */ + + static const double levels[4] = { 0.0, 1.0, -1.0, 0.0 }; + m_cassette->output(levels[data & 3]); + m_cassette_data &= ~0x80; +} + + +/************************************* + * + * Interrupt handlers. + * + *************************************/ + +INTERRUPT_GEN_MEMBER(trs80m3_state::rtc_interrupt) +{ +/* This enables the processing of interrupts for the clock and the flashing cursor. + The OS counts one tick for each interrupt. It is called 30 times per second. */ + + if (m_mask & IRQ_M4_RTC) + { + m_irq |= IRQ_M4_RTC; + m_maincpu->set_input_line(0, HOLD_LINE); + } + + // While we're here, let's countdown the motor timeout too. + if (m_timeout) + { + m_timeout--; + if (m_timeout == 0) + if (m_floppy) + m_floppy->mon_w(1); // motor off + } +} + +// The floppy sector has been read. Enable CPU and NMI. +WRITE_LINE_MEMBER(trs80m3_state::intrq_w) +{ + if (state) + { + //m_maincpu->set_input_line(Z80_INPUT_LINE_WAIT, CLEAR_LINE); + if (BIT(m_nmi_mask, 7)) + { + m_nmi_data = 0x80; + //m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero); + m_maincpu->set_input_line(INPUT_LINE_NMI, HOLD_LINE); + } + } + else + m_nmi_data = 0; +} + +// The next byte from floppy is available. Enable CPU so it can get the byte. +WRITE_LINE_MEMBER(trs80m3_state::drq_w) +{ + if (state) + m_maincpu->set_input_line(Z80_INPUT_LINE_WAIT, CLEAR_LINE); +} + + +/************************************* + * * + * Memory handlers * + * * + *************************************/ + +READ8_MEMBER( trs80m3_state::wd179x_r ) +{ + uint8_t data = 0xff; + if (BIT(m_io_config->read(), 7)) + data = m_fdc->status_r(space, offset); + + return data; +} + +READ8_MEMBER( trs80m3_state::printer_r ) +{ + return m_cent_status_in->read(); +} + +WRITE8_MEMBER( trs80m3_state::printer_w ) +{ + m_cent_data_out->write(data); + m_centronics->write_strobe(0); + m_centronics->write_strobe(1); +} + +/************************************* + * Keyboard * + *************************************/ +READ8_MEMBER( trs80m3_state::keyboard_r ) +{ + u8 i, result = 0; + + for (i = 0; i < 8; i++) + if (BIT(offset, i)) + result |= m_io_keyboard[i]->read(); + + return result; +} + + +/************************************* + * Machine * + *************************************/ + +void trs80m3_state::machine_start() +{ + m_mode = 0; + m_reg_load = 1; + m_nmi_data = 0xff; + m_timeout = 1; + + m_cassette_data_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(trs80m3_state::cassette_data_callback),this)); + m_cassette_data_timer->adjust( attotime::zero, 0, attotime::from_hz(11025) ); + if (!(m_model4 & 6)) // Model 3 leave now + return; + + if (m_mainram->size() < (64 * 1024)) + { + if (BIT(m_model4, 1)) // Model 4 + { + m_m4_bank->set_stride(0x00000); + m_m4_bank->space(0).unmap_readwrite(0x08000, 0x0ffff); + } + else + if (BIT(m_model4, 2)) // Model 4P + { + m_m4p_bank->set_stride(0x00000); + m_m4p_bank->space(0).unmap_readwrite(0x08000, 0x0ffff); + } + m_16kbank->configure_entries(0, 8, m_mainram->pointer() + 0x00000, 0x00000); + } + else + if (m_mainram->size() < (128 * 1024)) + { + m_32kbanks[0]->configure_entries(0, 8, m_mainram->pointer() + 0x00000, 0x00000); + m_32kbanks[1]->configure_entries(0, 8, m_mainram->pointer() + 0x08000, 0x00000); + m_16kbank->configure_entries(0, 8, m_mainram->pointer() + 0x04000, 0x00000); + } + else + { + m_32kbanks[0]->configure_entries(0, 4, m_mainram->pointer() + 0x00000, 0x00000); + m_32kbanks[0]->configure_entries(4, 2, m_mainram->pointer() + 0x00000, 0x00000); + m_32kbanks[0]->configure_entries(6, 2, m_mainram->pointer() + 0x10000, 0x08000); + + m_32kbanks[1]->configure_entries(0, 2, m_mainram->pointer() + 0x08000, 0x00000); + m_32kbanks[1]->configure_entries(2, 2, m_mainram->pointer() + 0x10000, 0x08000); + m_32kbanks[1]->configure_entries(4, 4, m_mainram->pointer() + 0x08000, 0x00000); + + m_16kbank->configure_entries(0, 4, m_mainram->pointer() + 0x04000, 0x00000); + m_16kbank->configure_entries(4, 2, m_mainram->pointer() + 0x04000, 0x00000); + m_16kbank->configure_entries(6, 2, m_mainram->pointer() + 0x14000, 0x08000); + } + m_vidbank->configure_entries(0, 2, &m_p_videoram[0], 0x0400); +} + +void trs80m3_state::machine_reset() +{ + m_cassette_data = 0; +} + +MACHINE_RESET_MEMBER(trs80m3_state, trs80m3) +{ + address_space &mem = m_maincpu->space(AS_PROGRAM); + m_cassette_data = 0; + m_size_store = 0xff; + + if (m_model4 & 4) + port_9c_w(mem, 0, 1); // 4P - enable rom + if (m_model4 & 6) + port_84_w(mem, 0, 0); // 4 & 4P - switch in devices +} + +MACHINE_RESET_MEMBER(trs80m3_state, cp500) +{ + m_a11_flipflop = 0; + MACHINE_RESET_CALL_MEMBER( trs80m3 ); +} + + +/*************************************************************************** + PARAMETERS +***************************************************************************/ + +#define LOG 1 + +#define CMD_TYPE_OBJECT_CODE 0x01 +#define CMD_TYPE_TRANSFER_ADDRESS 0x02 +#define CMD_TYPE_END_OF_PARTITIONED_DATA_SET_MEMBER 0x04 +#define CMD_TYPE_LOAD_MODULE_HEADER 0x05 +#define CMD_TYPE_PARTITIONED_DATA_SET_HEADER 0x06 +#define CMD_TYPE_PATCH_NAME_HEADER 0x07 +#define CMD_TYPE_ISAM_DIRECTORY_ENTRY 0x08 +#define CMD_TYPE_END_OF_ISAM_DIRECTORY_ENTRY 0x0a +#define CMD_TYPE_PDS_DIRECTORY_ENTRY 0x0c +#define CMD_TYPE_END_OF_PDS_DIRECTORY_ENTRY 0x0e +#define CMD_TYPE_YANKED_LOAD_BLOCK 0x10 +#define CMD_TYPE_COPYRIGHT_BLOCK 0x1f + +/*************************************************************************** + IMPLEMENTATION +***************************************************************************/ + +QUICKLOAD_LOAD_MEMBER( trs80m3_state, trs80_cmd ) +{ + address_space &program = m_maincpu->space(AS_PROGRAM); + + uint8_t type, length; + uint8_t data[0x100]; + uint8_t addr[2]; + void *ptr; + + while (!image.image_feof()) + { + image.fread( &type, 1); + image.fread( &length, 1); + + length -= 2; + int block_length = length ? length : 256; + + switch (type) + { + case CMD_TYPE_OBJECT_CODE: + { + image.fread( &addr, 2); + uint16_t address = (addr[1] << 8) | addr[0]; + if (LOG) logerror("/CMD object code block: address %04x length %u\n", address, block_length); + ptr = program.get_write_ptr(address); + image.fread( ptr, block_length); + } + break; + + case CMD_TYPE_TRANSFER_ADDRESS: + { + image.fread( &addr, 2); + uint16_t address = (addr[1] << 8) | addr[0]; + if (LOG) logerror("/CMD transfer address %04x\n", address); + m_maincpu->set_state_int(Z80_PC, address); + } + break; + + case CMD_TYPE_LOAD_MODULE_HEADER: + image.fread( &data, block_length); + if (LOG) logerror("/CMD load module header '%s'\n", data); + break; + + case CMD_TYPE_COPYRIGHT_BLOCK: + image.fread( &data, block_length); + if (LOG) logerror("/CMD copyright block '%s'\n", data); + break; + + default: + image.fread( &data, block_length); + logerror("/CMD unsupported block type %u!\n", type); + } + } + + return image_init_result::PASS; +} diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 480e2fcd5e4..671aa741bf4 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -20982,6 +20982,10 @@ realbrod // (c) 1996 Merit realbroda // (c) 1995 Merit spitboss // (c) 1988 Merit +@source:meritum.cpp +meritum // +meritum_net // + @source:mermaid.cpp mermaid // (c) 1982 Rock-ola, made by Sanritsu rougien // (c) 1982 Sanritsu @@ -37545,16 +37549,10 @@ ht108064 // Hradstechnika Szvetkezet HT-1080Z/64 ht1080z // Hradstechnika Szvetkezet HT-1080Z ht1080z2 // Hradstechnika Szvetkezet HT-1080Z Series II lnw80 // LNW Research LNW-80 -meritum // -meritum_net // radionic // Radionic sys80 // EACA System 80 trs80 // TRS-80 Model I - Level I BASIC trs80l2 // TRS-80 Model I - Level II BASIC -trs80m3 // TRS-80 Model III - Radio Shack/Tandy -trs80m4 // -trs80m4p // -cp500 // Prologica CP500 @source:trs80dt1.cpp trs80dt1 // TRS-80 Data Terminal 1 @@ -37563,6 +37561,12 @@ trs80dt1 // TRS-80 Data Terminal 1 trs80m16 // trs80m2 // +@source:trs80m3.cpp +trs80m3 // TRS-80 Model III - Radio Shack/Tandy +trs80m4 // +trs80m4p // +cp500 // Prologica CP500 + @source:truco.cpp truco // (c) 198? Playtronic SRL diff --git a/src/mame/mess.flt b/src/mame/mess.flt index 9e32c73b06c..5a83f1f3e76 100644 --- a/src/mame/mess.flt +++ b/src/mame/mess.flt @@ -389,6 +389,7 @@ megadriv_rad.cpp mekd2.cpp mephisto.cpp mephisto_montec.cpp +meritum.cpp mes.cpp mfabfz.cpp mice.cpp @@ -727,6 +728,7 @@ tricep.cpp trs80.cpp trs80dt1.cpp trs80m2.cpp +trs80m3.cpp ts802.cpp ts803.cpp ts816.cpp diff --git a/src/mame/video/trs80.cpp b/src/mame/video/trs80.cpp index 389833f01e4..36dfab8e3b5 100644 --- a/src/mame/video/trs80.cpp +++ b/src/mame/video/trs80.cpp @@ -1,58 +1,16 @@ // license:BSD-3-Clause // copyright-holders:Juergen Buchmueller, Robbbert -/*************************************************************************** - - trs80.c - - Functions to emulate the video hardware of the TRS80. - -***************************************************************************/ +//*************************************************************************** #include "emu.h" #include "includes/trs80.h" #include "screen.h" -/* Bit assignment for "state->m_mode" - d7 Page select - d6 LNW80 switch to graphics ram - d5 LNW80 colour or monochrome (1=colour) - d4 LNW80 lores or hires (1=hires) also does 64 or 80 chars per line - d3 LNW80 invert entire screen / Model III/4 Invert characters with bit 7 set (1=invert) - d2 80/40 or 64/32 characters per line (1=80) +/* Bit assignment for "m_mode" d1 7 or 8 bit video (1=requires 7-bit, 0=don't care) d0 80/64 or 40/32 characters per line (1=32) */ -WRITE8_MEMBER( trs80_state::trs80m4_88_w ) -{ -/* This is for the programming of the CRTC registers. - However this CRTC is mask-programmed, and only the - start address register can be used. The cursor and - light-pen facilities are ignored. The character clock - is changed depending on the screen size chosen. - Therefore it is easier to use normal - coding rather than the mc6845 device. */ - - if (!offset) m_crtc_reg = data & 0x1f; - - if (offset) switch (m_crtc_reg) - { - case 12: - m_start_address = (m_start_address & 0x00ff) | (data << 8); - break; - case 13: - m_start_address = (m_start_address & 0xff00) | data; - } -} - - -void trs80_state::video_start() -{ - m_size_store = 0xff; - m_mode &= 2; -} - - /* 7 or 8-bit video, 32/64 characters per line = trs80, trs80l2, sys80 */ uint32_t trs80_state::screen_update_trs80(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { @@ -63,7 +21,7 @@ uint32_t trs80_state::screen_update_trs80(screen_device &screen, bitmap_ind16 &b if (m_mode != m_size_store) { - m_size_store = m_mode & 1; + m_size_store = m_mode; screen.set_visible_area(0, cols*6-1, 0, 16*12-1); } @@ -124,99 +82,6 @@ uint32_t trs80_state::screen_update_trs80(screen_device &screen, bitmap_ind16 &b return 0; } -/* 8-bit video, 32/64/40/80 characters per line = trs80m3, trs80m4. */ -uint32_t trs80_state::screen_update_trs80m4(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - uint8_t y,ra,chr,gfx,gfxbit; - uint16_t sy=0,ma=0,x; - uint8_t skip=1; - uint8_t cols = BIT(m_mode, 2) ? 80 : 64; - uint8_t rows = BIT(m_mode, 2) ? 24 : 16; - uint8_t lines = BIT(m_mode, 2) ? 10 : 12; - uint8_t s_cols = cols; - uint8_t mask = BIT(m_mode, 5) ? 0xff : 0xbf; /* Select Japanese or extended chars */ - - if (m_mode & 1) - { - s_cols >>= 1; - skip = 2; - } - - if ((m_mode & 0x7f) != m_size_store) - { - m_size_store = m_mode & 5; - screen.set_visible_area(0, s_cols*8-1, 0, rows*lines-1); - } - - for (y = 0; y < rows; y++) - { - for (ra = 0; ra < lines; ra++) - { - uint16_t *p = &bitmap.pix16(sy++); - - for (x = ma; x < ma + cols; x+=skip) - { - chr = m_p_videoram[x+m_start_address]; - - if (((chr & 0xc0) == 0xc0) && (~m_mode & 8)) - { - if (ra < 8) - gfx = m_p_chargen[((chr&mask)<<3) | ra ]; - else - gfx = 0; - - *p++ = BIT(gfx, 7); - *p++ = BIT(gfx, 6); - *p++ = BIT(gfx, 5); - *p++ = BIT(gfx, 4); - *p++ = BIT(gfx, 3); - *p++ = BIT(gfx, 2); - *p++ = BIT(gfx, 1); - *p++ = BIT(gfx, 0); - } - else - if ((chr & 0x80) && (~m_mode & 8)) - { - gfxbit = (ra & 0x0c)>>1; - /* Display one line of a lores character */ - *p++ = BIT(chr, gfxbit); - *p++ = BIT(chr, gfxbit); - *p++ = BIT(chr, gfxbit); - *p++ = BIT(chr, gfxbit); - gfxbit++; - *p++ = BIT(chr, gfxbit); - *p++ = BIT(chr, gfxbit); - *p++ = BIT(chr, gfxbit); - *p++ = BIT(chr, gfxbit); - } - else - { - /* get pattern of pixels for that character scanline */ - if (ra < 8) - gfx = m_p_chargen[((chr&0x7f)<<3) | ra ]; - else - gfx = 0; - - /* if inverse mode, and bit 7 set, invert gfx */ - if (BIT(m_mode, 3) & BIT(chr, 7)) - gfx ^= 0xff; - - /* Display a scanline of a character */ - *p++ = BIT(gfx, 7); - *p++ = BIT(gfx, 6); - *p++ = BIT(gfx, 5); - *p++ = BIT(gfx, 4); - *p++ = BIT(gfx, 3); - *p++ = BIT(gfx, 2); - *p++ = BIT(gfx, 1); - *p++ = BIT(gfx, 0); - } - } - } - ma+=cols; - } - return 0; -} /* 7 or 8-bit video, 64/32 characters per line = ht1080z, ht1080z2, ht108064 */ uint32_t trs80_state::screen_update_ht1080z(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) @@ -228,7 +93,7 @@ uint32_t trs80_state::screen_update_ht1080z(screen_device &screen, bitmap_ind16 if (m_mode != m_size_store) { - m_size_store = m_mode & 1; + m_size_store = m_mode; screen.set_visible_area(0, cols*6-1, 0, 16*12-1); } @@ -256,7 +121,7 @@ uint32_t trs80_state::screen_update_ht1080z(screen_device &screen, bitmap_ind16 } else { - if ((m_mode & 2) && (chr < 32)) chr+=64; + if (BIT(m_mode, 1) && (chr < 32)) chr+=64; /* get pattern of pixels for that character scanline */ gfx = m_p_chargen[(chr<<4) | ra ]; @@ -282,22 +147,22 @@ uint32_t trs80_state::screen_update_lnw80(screen_device &screen, bitmap_ind16 &b static const uint16_t rows[] = { 0, 0x200, 0x100, 0x300, 1, 0x201, 0x101, 0x301 }; uint8_t chr,gfx,gfxbit,bg=7,fg=0; uint16_t sy=0,ma=0,x,y,ra; - uint8_t cols = BIT(m_mode, 4) ? 80 : 64; + uint8_t cols = BIT(m_lnw_mode, 1) ? 80 : 64; /* Although the OS can select 32-character mode, it is not supported by hardware */ - if (m_mode != m_size_store) + if (m_lnw_mode != m_size_store) { - m_size_store = m_mode & 0x10; + m_size_store = m_lnw_mode; screen.set_visible_area(0, cols*6-1, 0, 16*12-1); } - if (m_mode & 8) + if (BIT(m_lnw_mode, 1)) { bg = 0; fg = 7; } - switch (m_mode & 0x30) + switch (m_lnw_mode & 0x06) { case 0: // MODE 0 for (y = 0; y < 16; y++) @@ -344,7 +209,7 @@ uint32_t trs80_state::screen_update_lnw80(screen_device &screen, bitmap_ind16 &b } break; - case 0x10: // MODE 1 + case 0x02: // MODE 1 for (y = 0; y < 0x400; y+=0x40) { for (ra = 0; ra < 0x3000; ra+=0x400) @@ -378,7 +243,7 @@ uint32_t trs80_state::screen_update_lnw80(screen_device &screen, bitmap_ind16 &b } break; - case 0x20: // MODE 2 + case 0x04: // MODE 2 /* it seems the text video ram can have an effect in this mode, not explained clearly, so not emulated */ for (y = 0; y < 0x400; y+=0x40) @@ -404,7 +269,7 @@ uint32_t trs80_state::screen_update_lnw80(screen_device &screen, bitmap_ind16 &b } break; - case 0x30: // MODE 3 + case 0x06: // MODE 3 /* the manual does not explain at all how colour is determined for the extended area. Further, the background colour is not mentioned anywhere. Black is assumed. */ @@ -417,7 +282,7 @@ uint32_t trs80_state::screen_update_lnw80(screen_device &screen, bitmap_ind16 &b for (x = 0; x < 0x40; x++) { gfx = m_p_gfxram[ y | x | ra]; - fg = (m_p_videoram[ 0x3c00 | x | y ] & 0x38) >> 3; + fg = (m_p_videoram[ x | y ] & 0x38) >> 3; /* Display 6 pixels in normal region */ *p++ = BIT(gfx, 0) ? fg : bg; *p++ = BIT(gfx, 1) ? fg : bg; @@ -458,7 +323,7 @@ uint32_t trs80_state::screen_update_radionic(screen_device &screen, bitmap_ind16 if (m_mode != m_size_store) { - m_size_store = m_mode & 1; + m_size_store = m_mode; screen.set_visible_area(0, cols*8-1, 0, 16*16-1); } @@ -491,80 +356,6 @@ uint32_t trs80_state::screen_update_radionic(screen_device &screen, bitmap_ind16 return 0; } -uint32_t trs80_state::screen_update_meritum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -/* lores characters are in the character generator. Each character is 6x11. */ -{ - uint8_t y,ra,chr,gfx; - uint16_t sy=0,ma=0,x; - uint8_t cols = BIT(m_mode, 0) ? 32 : 64; - uint8_t skip = BIT(m_mode, 0) ? 2 : 1; - - if (m_mode != m_size_store) - { - m_size_store = m_mode; - screen.set_visible_area(0, cols*6-1, 0, 16*11-1); - } - - for (y = 0; y < 16; y++) - { - for (ra = 0; ra < 11; ra++) - { - uint16_t *p = &bitmap.pix16(sy++); - - for (x = ma; x < ma + 64; x+=skip) - { - chr = m_p_videoram[x]; - - /* get pattern of pixels for that character scanline */ - gfx = m_p_chargen[(chr<<4) | ra]; - - /* Display a scanline of a character (6 pixels) */ - *p++ = BIT(gfx, 5); - *p++ = BIT(gfx, 4); - *p++ = BIT(gfx, 3); - *p++ = BIT(gfx, 2); - *p++ = BIT(gfx, 1); - *p++ = BIT(gfx, 0); - } - } - ma+=64; - } - return 0; -} - - - -/*************************************************************************** - Write to video ram -***************************************************************************/ - -READ8_MEMBER( trs80_state::trs80_videoram_r ) -{ - if ((m_mode & 0x80) && (~m_model4 & 1)) offset |= 0x400; - return m_p_videoram[offset]; -} - -WRITE8_MEMBER( trs80_state::trs80_videoram_w ) -{ - if ((m_mode & 0x80) && (~m_model4 & 1)) offset |= 0x400; - m_p_videoram[offset] = data; -} - - -/*************************************************************************** - Write to graphics ram -***************************************************************************/ - -READ8_MEMBER( trs80_state::trs80_gfxram_r ) -{ - return m_p_gfxram[offset]; -} - -WRITE8_MEMBER( trs80_state::trs80_gfxram_w ) -{ - m_p_gfxram[offset] = data; -} - /*************************************************************************** Palettes diff --git a/src/mame/video/trs80m3.cpp b/src/mame/video/trs80m3.cpp new file mode 100644 index 00000000000..5bf75c72651 --- /dev/null +++ b/src/mame/video/trs80m3.cpp @@ -0,0 +1,125 @@ +// license:BSD-3-Clause +// copyright-holders:Robbbert +//*************************************************************************** + +#include "emu.h" +#include "includes/trs80m3.h" +#include "screen.h" + +WRITE8_MEMBER( trs80m3_state::port_88_w ) +{ +/* This is for the programming of the CRTC registers. + However this CRTC is mask-programmed, and only the + start address register can be used. The cursor and + light-pen facilities are ignored. The character clock + is changed depending on the screen size chosen. + Therefore it is easier to use normal + coding rather than the mc6845 device. */ + + if (!offset) m_crtc_reg = data & 0x1f; + + if (offset) switch (m_crtc_reg) + { + case 12: + m_start_address = (m_start_address & 0x00ff) | (data << 8); + break; + case 13: + m_start_address = (m_start_address & 0xff00) | data; + } +} + + +/* 8-bit video, 32/64/40/80 characters per line = trs80m3, trs80m4. */ +uint32_t trs80m3_state::screen_update_trs80m3(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + uint8_t y,ra,chr,gfx,gfxbit; + uint16_t sy=0,ma=0,x; + uint8_t skip=1; + uint8_t cols = BIT(m_mode, 2) ? 80 : 64; + uint8_t rows = BIT(m_mode, 2) ? 24 : 16; + uint8_t lines = BIT(m_mode, 2) ? 10 : 12; + uint8_t s_cols = cols; + uint8_t mask = BIT(m_mode, 5) ? 0xff : 0xbf; /* Select Japanese or extended chars */ + + if (m_mode & 1) + { + s_cols >>= 1; + skip = 2; + } + + if ((m_mode & 0x7f) != m_size_store) + { + m_size_store = m_mode & 5; + screen.set_visible_area(0, s_cols*8-1, 0, rows*lines-1); + } + + for (y = 0; y < rows; y++) + { + for (ra = 0; ra < lines; ra++) + { + uint16_t *p = &bitmap.pix16(sy++); + + for (x = ma; x < ma + cols; x+=skip) + { + chr = m_p_videoram[x+m_start_address]; + + if (((chr & 0xc0) == 0xc0) && (~m_mode & 8)) + { + if (ra < 8) + gfx = m_p_chargen[((chr&mask)<<3) | ra ]; + else + gfx = 0; + + *p++ = BIT(gfx, 7); + *p++ = BIT(gfx, 6); + *p++ = BIT(gfx, 5); + *p++ = BIT(gfx, 4); + *p++ = BIT(gfx, 3); + *p++ = BIT(gfx, 2); + *p++ = BIT(gfx, 1); + *p++ = BIT(gfx, 0); + } + else + if ((chr & 0x80) && (~m_mode & 8)) + { + gfxbit = (ra & 0x0c)>>1; + /* Display one line of a lores character */ + *p++ = BIT(chr, gfxbit); + *p++ = BIT(chr, gfxbit); + *p++ = BIT(chr, gfxbit); + *p++ = BIT(chr, gfxbit); + gfxbit++; + *p++ = BIT(chr, gfxbit); + *p++ = BIT(chr, gfxbit); + *p++ = BIT(chr, gfxbit); + *p++ = BIT(chr, gfxbit); + } + else + { + /* get pattern of pixels for that character scanline */ + if (ra < 8) + gfx = m_p_chargen[((chr&0x7f)<<3) | ra ]; + else + gfx = 0; + + /* if inverse mode, and bit 7 set, invert gfx */ + if (BIT(m_mode, 3) & BIT(chr, 7)) + gfx ^= 0xff; + + /* Display a scanline of a character */ + *p++ = BIT(gfx, 7); + *p++ = BIT(gfx, 6); + *p++ = BIT(gfx, 5); + *p++ = BIT(gfx, 4); + *p++ = BIT(gfx, 3); + *p++ = BIT(gfx, 2); + *p++ = BIT(gfx, 1); + *p++ = BIT(gfx, 0); + } + } + } + ma+=cols; + } + return 0; +} + -- cgit v1.2.3