diff options
Diffstat (limited to 'src/mame/drivers/tec1.cpp')
-rw-r--r-- | src/mame/drivers/tec1.cpp | 492 |
1 files changed, 0 insertions, 492 deletions
diff --git a/src/mame/drivers/tec1.cpp b/src/mame/drivers/tec1.cpp deleted file mode 100644 index 59a548d0acb..00000000000 --- a/src/mame/drivers/tec1.cpp +++ /dev/null @@ -1,492 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Robbbert -/*************************************************************************** - - TEC-1 driver, written by Robbbert in April, 2009 for MESS. - -The TEC-1 was a single-board "computer" described in Talking Electronics -magazine, issues number 10 and 11. Talking Electronics do not have dates on -their issues, so the date is uncertain, although 1984 seems a reasonable -guess. Talking Electronics operated from Cheltenham, a suburb of Melbourne. - -The hardware is quite simple, consisting of a Z80 cpu, 2x 8212 8-bit latch, -74C923 keyboard scanner, 20 push-button keys, 6-digit LED display, a speaker, -a 2k EPROM and sundry parts. - -The cpu speed could be adjusted by using a potentiometer, the range being -250 kHz to 2MHz. This is a simple method of adjusting a game's difficulty. - -We emulate the original version. Later enhancements included more RAM, speech -synthesis and various attachments, however I have no information on these. - -2018-11-08 Obtained fresh dumps from the original designers. - -Pasting: - 0-F : as is - + (inc) : ^ - - (dec) : V - AD : - - GO : X - -Keys: -0 to 9, A to F are on the key of the same name. -AD (input an address) is the '-' key. -+ and - (increment / decrement address) are the up and down-arrow keys. -GO (execute program at current address) is the X key. -SHIFT - later monitor versions utilised an extra shift button. Hold - it down and press another key (use Left Shift). - -Whenever a program listing mentions RESET, press Left-Alt key. - -Each key causes a beep to be heard. You may need to press more than once -to get it to register. - -Inbuilt games - press the following sequence of keys: -- Welcome: RESET D 1 + 0 2 AD 0 2 7 0 GO GO (Paste: D1^02 -0270XX) -- Nim: RESET AD 3 E 0 GO GO (Paste: -3E0XX) -- Invaders: RESET AD 3 2 0 GO GO (Paste: -320XX) -- Luna Lander: RESET AD 4 9 0 GO GO (Paste: -490XX) - -Thanks to Chris Schwartz who dumped his ROM for me way back in the old days. -It's only taken 25 years to get around to emulating it... - - -Differences between tec1 and tecjmon: - -On the tec1 a keypress is indicated by an NMI from the 74C923; but on -the jmon it sets bit 6 of port 3 low instead. The NMI code is simply -a 'retn' in the jmon rom, so we can use the same code. -The jmon includes a cassette interface, a serial input connection, -and an optional LCD, but the games of the tec1 have been removed. - - -ToDo: -- After a Soft Reset, pressing keys can crash the emulation. -- The 74C923 code may need to be revisited to improve keyboard response. - Sometimes have to press a key a few times before it registers. -- The 10ms debounce is not emulated. - - -JMON ToDo: -- Add LCD display (2 rows by 16 characters) - - -***************************************************************************/ - -#include "emu.h" -#include "cpu/z80/z80.h" -#include "imagedev/cassette.h" -#include "sound/spkrdev.h" -#include "speaker.h" - -#include "tec1.lh" - - -class tec1_state : public driver_device -{ -public: - tec1_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_maincpu(*this, "maincpu") - , m_speaker(*this, "speaker") - , m_cass(*this, "cassette") - , m_key_pressed(0) - , m_io_line0(*this, "LINE0") - , m_io_line1(*this, "LINE1") - , m_io_line2(*this, "LINE2") - , m_io_line3(*this, "LINE3") - , m_io_shift(*this, "SHIFT") - , m_digits(*this, "digit%u", 0U) - { } - - void tec1(machine_config &config); - void tecjmon(machine_config &config); - - DECLARE_INPUT_CHANGED_MEMBER(reset_button); - -private: - required_device<cpu_device> m_maincpu; - required_device<speaker_sound_device> m_speaker; - optional_device<cassette_image_device> m_cass; - bool m_key_pressed; - required_ioport m_io_line0; - required_ioport m_io_line1; - required_ioport m_io_line2; - required_ioport m_io_line3; - required_ioport m_io_shift; - output_finder<6> m_digits; - emu_timer *m_kbd_timer; - DECLARE_READ8_MEMBER( tec1_kbd_r ); - DECLARE_READ8_MEMBER( latch_r ); - DECLARE_WRITE8_MEMBER( tec1_digit_w ); - DECLARE_WRITE8_MEMBER( tecjmon_digit_w ); - DECLARE_WRITE8_MEMBER( tec1_segment_w ); - uint8_t m_kbd; - uint8_t m_segment; - uint8_t m_digit; - uint8_t m_kbd_row; - uint8_t m_refresh[6]; - uint8_t tec1_convert_col_to_bin( uint8_t col, uint8_t row ); - virtual void machine_reset() override; - virtual void machine_start() override; - TIMER_CALLBACK_MEMBER(tec1_kbd_callback); - - void tec1_io(address_map &map); - void tec1_map(address_map &map); - void tecjmon_io(address_map &map); - void tecjmon_map(address_map &map); -}; - - - - -/*************************************************************************** - - Display - -***************************************************************************/ - -WRITE8_MEMBER( tec1_state::tec1_segment_w ) -{ -/* d7 segment d - d6 segment e - d5 segment c - d4 segment dot - d3 segment b - d2 segment g - d1 segment f - d0 segment a */ - - m_segment = bitswap<8>(data, 4, 2, 1, 6, 7, 5, 3, 0); -} - -WRITE8_MEMBER( tec1_state::tec1_digit_w ) -{ -/* d7 speaker - d6 not used - d5 data digit 1 - d4 data digit 2 - d3 address digit 1 - d2 address digit 2 - d1 address digit 3 - d0 address digit 4 */ - - m_speaker->level_w(BIT(data, 7)); - - m_digit = data & 0x3f; -} - -WRITE8_MEMBER( tec1_state::tecjmon_digit_w ) -{ -/* d7 speaker & cassout - d6 not used - d5 data digit 1 - d4 data digit 2 - d3 address digit 1 - d2 address digit 2 - d1 address digit 3 - d0 address digit 4 */ - - m_speaker->level_w(BIT(data, 7)); - m_cass->output(BIT(data, 7) ? -1.0 : +1.0); - m_digit = data & 0x3f; -} - - -/*************************************************************************** - - Keyboard - -***************************************************************************/ - -READ8_MEMBER( tec1_state::latch_r ) -{ -// bit 7 - cass in ; bit 6 low = key pressed - uint8_t data = (m_key_pressed) ? 0 : 0x40; - - if (m_cass->input() > 0.03) - data |= 0x80; - - return data; -} - - -READ8_MEMBER( tec1_state::tec1_kbd_r ) -{ - m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); - return m_kbd | m_io_shift->read(); -} - -uint8_t tec1_state::tec1_convert_col_to_bin( uint8_t col, uint8_t row ) -{ - uint8_t data = row; - - if (BIT(col, 1)) - data |= 4; - else - if (BIT(col, 2)) - data |= 8; - else - if (BIT(col, 3)) - data |= 12; - else - if (BIT(col, 4)) - data |= 16; - - return data; -} - -TIMER_CALLBACK_MEMBER(tec1_state::tec1_kbd_callback) -{ - uint8_t i; - - // Display the digits. Blank any digits that haven't been refreshed for a while. - // This will fix the problem reported by a user. - for (i = 0; i < 6; i++) - { - if (BIT(m_digit, i)) - { - m_refresh[i] = 1; - m_digits[i] = m_segment; - } - else - if (m_refresh[i] == 0x80) - { - m_digits[i] = 0; - m_refresh[i] = 0; - } - else - if (m_refresh[i]) - m_refresh[i]++; - } - - // 74C923 4 by 5 key encoder. - - /* Look at old row */ - if (m_kbd_row == 0) - i = m_io_line0->read(); - else - if (m_kbd_row == 1) - i = m_io_line1->read(); - else - if (m_kbd_row == 2) - i = m_io_line2->read(); - else - if (m_kbd_row == 3) - i = m_io_line3->read(); - - /* if previous key is still held, bail out */ - if (i) - if (tec1_convert_col_to_bin(i, m_kbd_row) == m_kbd) - return; - - m_kbd_row++; - m_kbd_row &= 3; - - /* Look at a new row */ - if (m_kbd_row == 0) - i = m_io_line0->read(); - else - if (m_kbd_row == 1) - i = m_io_line1->read(); - else - if (m_kbd_row == 2) - i = m_io_line2->read(); - else - if (m_kbd_row == 3) - i = m_io_line3->read(); - - /* see if a key pressed */ - if (i) - { - m_kbd = tec1_convert_col_to_bin(i, m_kbd_row); - m_maincpu->set_input_line(INPUT_LINE_NMI, HOLD_LINE); - m_key_pressed = true; - } - else - m_key_pressed = false; -} - - -/*************************************************************************** - - Machine - -***************************************************************************/ - -void tec1_state::machine_start() -{ - m_digits.resolve(); - m_kbd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(tec1_state::tec1_kbd_callback),this)); - m_kbd_timer->adjust( attotime::zero, 0, attotime::from_hz(500) ); -} - -void tec1_state::machine_reset() -{ - m_kbd = 0; -} - - - -/*************************************************************************** - - Address Map - -***************************************************************************/ - -void tec1_state::tec1_map(address_map &map) -{ - map.global_mask(0x3fff); - map(0x0000, 0x07ff).rom(); - map(0x0800, 0x0fff).ram(); // on main board - map(0x1000, 0x3fff).ram(); // expansion -} - -void tec1_state::tec1_io(address_map &map) -{ - map.global_mask(0x07); - map(0x00, 0x00).r(FUNC(tec1_state::tec1_kbd_r)); - map(0x01, 0x01).w(FUNC(tec1_state::tec1_digit_w)); - map(0x02, 0x02).w(FUNC(tec1_state::tec1_segment_w)); -} - - -void tec1_state::tecjmon_map(address_map &map) -{ - map.global_mask(0x3fff); - map(0x0000, 0x07ff).rom(); - map(0x0800, 0x37ff).ram(); - map(0x3800, 0x3fff).rom(); -} - -void tec1_state::tecjmon_io(address_map &map) -{ - map.global_mask(0xff); - map(0x00, 0x00).r(FUNC(tec1_state::tec1_kbd_r)); - map(0x01, 0x01).w(FUNC(tec1_state::tecjmon_digit_w)); - map(0x02, 0x02).w(FUNC(tec1_state::tec1_segment_w)); - map(0x03, 0x03).r(FUNC(tec1_state::latch_r)); - //map(0x04, 0x04).w(FUNC(tec1_state::lcd_en_w)); - //map(0x84, 0x84).w(FUNC(tec1_state::lcd_2nd_w)); -} - - -/************************************************************************** - - Keyboard Layout - -***************************************************************************/ - -static INPUT_PORTS_START( tec1 ) - PORT_START("LINE0") /* KEY ROW 0 */ - PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') - PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') - PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') - PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C') - PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("+") PORT_CODE(KEYCODE_UP) PORT_CHAR('^') - - PORT_START("LINE1") /* KEY ROW 1 */ - PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') - PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5') - PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') - PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D') - PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_DOWN) PORT_CHAR('V') - - PORT_START("LINE2") /* KEY ROW 2 */ - PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') - PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') - PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A') - PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E') - PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("GO") PORT_CODE(KEYCODE_X) PORT_CHAR('X') - - PORT_START("LINE3") /* KEY ROW 3 */ - PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3') - PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') - PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B') - PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F') - PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("AD") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') - - PORT_START("SHIFT") - PORT_BIT(0x1f, IP_ACTIVE_HIGH, IPT_UNUSED) - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) - PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED) - - PORT_START("RESET") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RESET") PORT_CODE(KEYCODE_LALT) PORT_CHANGED_MEMBER(DEVICE_SELF, tec1_state, reset_button, 0) -INPUT_PORTS_END - -INPUT_CHANGED_MEMBER(tec1_state::reset_button) -{ - m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? ASSERT_LINE : CLEAR_LINE); -} - - -/*************************************************************************** - - Machine driver - -***************************************************************************/ - -void tec1_state::tec1(machine_config &config) -{ - /* basic machine hardware */ - Z80(config, m_maincpu, 1000000); /* speed can be varied between 250kHz and 2MHz */ - m_maincpu->set_addrmap(AS_PROGRAM, &tec1_state::tec1_map); - m_maincpu->set_addrmap(AS_IO, &tec1_state::tec1_io); - - /* video hardware */ - config.set_default_layout(layout_tec1); - - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.50); -} - -void tec1_state::tecjmon(machine_config &config) -{ - /* basic machine hardware */ - Z80(config, m_maincpu, XTAL(3'579'545) / 2); - m_maincpu->set_addrmap(AS_PROGRAM, &tec1_state::tecjmon_map); - m_maincpu->set_addrmap(AS_IO, &tec1_state::tecjmon_io); - - /* video hardware */ - config.set_default_layout(layout_tec1); - - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.50); - - /* Devices */ - CASSETTE(config, m_cass); - m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED); -} - - -/*************************************************************************** - - Game driver - -***************************************************************************/ - -ROM_START(tec1) - ROM_REGION(0x10000, "maincpu", ROMREGION_ERASEFF) - ROM_SYSTEM_BIOS(0, "mon1", "MON1") - ROMX_LOAD( "mon1.rom", 0x0000, 0x0800, CRC(5d379e6c) SHA1(5c810885a3f0d03c54aea74aaaa8fae8a2fd9ad4), ROM_BIOS(0) ) - ROM_SYSTEM_BIOS(1, "mon1a", "MON1A") - ROMX_LOAD("mon1a.rom", 0x0000, 0x0800, CRC(b3390c36) SHA1(18aabc68d473206b7fc4e365c6b57a4e218482c3), ROM_BIOS(1)) - ROM_SYSTEM_BIOS(2, "mon1b", "MON1B") - //ROMX_LOAD("mon1b.rom", 0x0000, 0x0800, CRC(60daea3c) SHA1(383b7e7f02e91fb18c87eb03c5949e31156771d4), ROM_BIOS(2)) - ROMX_LOAD("mon1b.rom", 0x0000, 0x0800, CRC(6088811d) SHA1(2cec14a24fae769f22f6598b5a63fc79d90db394), ROM_BIOS(2)) // redump - ROM_SYSTEM_BIOS(3, "mon2", "MON2") - ROMX_LOAD("mon2.rom", 0x0000, 0x0800, CRC(082fd7e7) SHA1(7659add30ca22b15a03d1cbac0892a5c25e47ecd), ROM_BIOS(3)) -ROM_END - -ROM_START(tecjmon) - ROM_REGION(0x10000, "maincpu", ROMREGION_ERASEFF) - ROM_LOAD("jmon.rom", 0x0000, 0x0800, CRC(202c47a2) SHA1(701588ec5640d633d90d94b2ccd6f65422e19a70) ) - ROM_LOAD("util.rom", 0x3800, 0x0800, CRC(7c19700d) SHA1(dc5b3ade66bb11c54430056966ed99cdd299d82b) ) -ROM_END - -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -COMP( 1984, tec1, 0, 0, tec1, tec1, tec1_state, empty_init, "Talking Electronics magazine", "TEC-1", 0 ) -COMP( 1984, tecjmon, tec1, 0, tecjmon, tec1, tec1_state, empty_init, "Talking Electronics magazine", "TEC-1A with JMON", 0 ) |