From 89f606874520566c317eb998c2ed5ee6b3f34841 Mon Sep 17 00:00:00 2001 From: Robbbert Date: Fri, 6 Oct 2017 04:11:37 +1100 Subject: (nw) sbrain : can boot from floppy, added keyboard, notes. --- src/mame/drivers/sbrain.cpp | 332 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 277 insertions(+), 55 deletions(-) diff --git a/src/mame/drivers/sbrain.cpp b/src/mame/drivers/sbrain.cpp index 910ef304943..75c4af96426 100644 --- a/src/mame/drivers/sbrain.cpp +++ b/src/mame/drivers/sbrain.cpp @@ -6,6 +6,8 @@ Intertec SuperBrain 2013-08-19 Skeleton +Intertec Compustar terminal appears to have identical hardware. Need roms for it. + Chips: 2x Z80; FD1791; 2x 8251; 8255; BR1941; CRT8002; KR3600; DP8350 Xtals: 16.0, 10.92, 5.0688 Disk parameters: 512 bytes x 10 sectors x 35 tracks. 1 and 2-sided disks supported. @@ -18,20 +20,20 @@ The main cpu does a busreq to gain access to the sub cpu's 1k static ram. When t responds with busack, then the main cpu switches bank2. In emulation, it isn't actually necessary to stop the sub cpu because of other handshaking. Our Z80 emulation doesn't support the busack signal anyway, so we just assume it is granted immediately. +When booted, the time (corrupted) is displayed at top right. You need to run TIME hh:mm:ss + to set the time (TIME.COM must be on the disk). The schematic in parts is difficult to read. Some assumptions have been made. To Do: -- Without a disk in, it should display a message to insert a disk. Doesn't happen. - It thinks a disk is in and tries to execute garbage in the disk buffer instead. -- Port 08 is largely a guess. -- No work done on the keyboard. Should be able to hook up the generic ascii keyboard. -- No software available to try. -- Bug in floppy code means the motor will turn off after a few seconds. It should stay on. +- Without a disk in, it should display a message to insert a disk. Doesn't happen. May + attempt to execute empty memory instead. (-bios 1, -bios 2) +- Improve keyboard. - Video chips need to be emulated (CRT8002 and DP8350), attributes etc. -- After each line of characters, an interrupt should be generated. 25 IRQs per screen. -- Hook the outputs of the baud rate generator to the uarts. - Probably lots of other stuff. +- PC0 when high will swap out lower 16k of RAM for the DP8350 device. The value of HL (the + "memory" address) is the data (cursor location, top of screen, etc). The byte "written" + to this address (d0,d1) is the command for the CRTC. *************************************************************************************************************/ @@ -42,6 +44,7 @@ To Do: #include "machine/i8251.h" #include "machine/i8255.h" #include "machine/wd_fdc.h" +#include "machine/timer.h" #include "sound/beep.h" #include "screen.h" #include "speaker.h" @@ -68,6 +71,7 @@ public: , m_bankr0(*this, "bankr0") , m_bankw0(*this, "bankw0") , m_bank2(*this, "bank2") + , m_keyboard(*this, "X%u", 0) {} DECLARE_DRIVER_INIT(sbrain); @@ -78,21 +82,26 @@ public: DECLARE_WRITE8_MEMBER(ppi_pb_w); DECLARE_READ8_MEMBER(ppi_pc_r); DECLARE_WRITE8_MEMBER(ppi_pc_w); - DECLARE_READ8_MEMBER(port08_r); - DECLARE_WRITE8_MEMBER(port08_w); + DECLARE_READ8_MEMBER(port48_r); + DECLARE_READ8_MEMBER(port50_r); + DECLARE_READ8_MEMBER(port10_r); + DECLARE_WRITE8_MEMBER(port10_w); DECLARE_WRITE8_MEMBER(baud_w); - DECLARE_WRITE_LINE_MEMBER(fr_w); - DECLARE_WRITE_LINE_MEMBER(ft_w); - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + TIMER_DEVICE_CALLBACK_MEMBER(kbd_scan); private: - uint8_t m_porta; - uint8_t m_portb; - uint8_t m_portc; - uint8_t m_port08; + bool m_busak; + u8 m_keydown; + u8 m_porta; + u8 m_portb; + u8 m_portc; + u8 m_port10; + u8 m_term_data; + u8 m_framecnt; required_device m_maincpu; required_device m_subcpu; - required_shared_ptr m_p_videoram; + required_shared_ptr m_p_videoram; required_region_ptr m_p_chargen; required_device m_beep; required_device m_brg; @@ -106,6 +115,7 @@ private: required_memory_bank m_bankr0; required_memory_bank m_bankw0; required_memory_bank m_bank2; + required_ioport_array<10> m_keyboard; }; static ADDRESS_MAP_START( sbrain_mem, AS_PROGRAM, 8, sbrain_state ) @@ -120,8 +130,8 @@ static ADDRESS_MAP_START( sbrain_io, AS_IO, 8, sbrain_state ) ADDRESS_MAP_GLOBAL_MASK(0xff) AM_RANGE(0x40, 0x40) AM_MIRROR(6) AM_DEVREADWRITE("uart0", i8251_device, data_r, data_w) AM_RANGE(0x41, 0x41) AM_MIRROR(6) AM_DEVREADWRITE("uart0", i8251_device, status_r, control_w) - //AM_RANGE(0x48, 0x4f) chr_int_latch - //AM_RANGE(0x50, 0x57) key_in + AM_RANGE(0x48, 0x4f) AM_READ(port48_r) //chr_int_latch + AM_RANGE(0x50, 0x57) AM_READ(port50_r) AM_RANGE(0x58, 0x58) AM_MIRROR(6) AM_DEVREADWRITE("uart1", i8251_device, data_r, data_w) AM_RANGE(0x59, 0x59) AM_MIRROR(6) AM_DEVREADWRITE("uart1", i8251_device, status_r, control_w) AM_RANGE(0x60, 0x67) AM_WRITE(baud_w) @@ -135,18 +145,29 @@ ADDRESS_MAP_END static ADDRESS_MAP_START( sbrain_subio, AS_IO, 8, sbrain_state ) ADDRESS_MAP_GLOBAL_MASK(0xff) - AM_RANGE(0x08, 0x08) AM_READWRITE(port08_r,port08_w) - AM_RANGE(0x10, 0x13) AM_DEVREADWRITE("fdc", fd1791_device, read, write) + AM_RANGE(0x08, 0x0b) AM_DEVREADWRITE("fdc", fd1791_device, read, write) + AM_RANGE(0x10, 0x10) AM_READWRITE(port10_r,port10_w) ADDRESS_MAP_END -// bit 0 is wrong, maybe the whole byte is wrong -READ8_MEMBER( sbrain_state::port08_r ) + +READ8_MEMBER( sbrain_state::port48_r ) +{ + m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE); + return 0xff; +} + +READ8_MEMBER( sbrain_state::port50_r ) { - return m_port08; + return m_term_data; +} + +READ8_MEMBER( sbrain_state::port10_r ) +{ + return m_port10; } /* Misc disk functions -d0 : disk busy? +d0 : ? d1 : SEL A (drive 0?) d2 : SEL B (drive 1?) d3 : SEL C @@ -154,34 +175,23 @@ d4 : SEL D d5 : side select d6,7 : not used */ -WRITE8_MEMBER( sbrain_state::port08_w ) +WRITE8_MEMBER( sbrain_state::port10_w ) { - m_port08 = data | 0xc0; + m_port10 = data | 0xc0; floppy_image_device *floppy = nullptr; - if (BIT(m_port08, 1)) floppy = m_floppy0->get_device(); - if (BIT(m_port08, 2)) floppy = m_floppy1->get_device(); + if (BIT(m_port10, 1)) floppy = m_floppy0->get_device(); + if (BIT(m_port10, 2)) floppy = m_floppy1->get_device(); m_fdc->set_floppy(floppy); if (floppy) - { - floppy->ss_w(BIT(m_port08, 5)); // might need inverting - } + floppy->ss_w(BIT(m_port10, 5)); - // refresh motor on, hopefully this will keep them turning m_floppy0->get_device()->mon_w(0); // motors run all the time m_floppy1->get_device()->mon_w(0); } -WRITE_LINE_MEMBER( sbrain_state::fr_w ) -{ -} - -WRITE_LINE_MEMBER( sbrain_state::ft_w ) -{ -} - WRITE8_MEMBER( sbrain_state::baud_w ) { m_brg->str_w(data & 0x0f); @@ -212,13 +222,17 @@ d1 : key held down d2 : Vert Blank d3 : not used d4 : /capslock -d5 : disk is busy +d5 : ? d6 : Ring Indicator line from main rs232 port, 1=normal, 0=set d7 : cpu2 /busak line */ READ8_MEMBER( sbrain_state::ppi_pb_r ) { - return m_portb | 0x50 | m_vs->read() | (BIT(m_port08, 0) << 5) | ((uint8_t)BIT(m_portc, 5) << 7); + u8 vertsync = m_vs->read(); // bit 2 + u8 capslock = BIT(ioport("MODIFIERS")->read(), 0) << 4; // bit 4, capslock + u8 p10d0 = BIT(m_port10, 0) << 5; // bit 5 + u8 busak = m_busak ? 128 : 0; // bit 7 + return busak | p10d0 | capslock | vertsync | m_keydown; } WRITE8_MEMBER( sbrain_state::ppi_pb_w ) @@ -247,20 +261,197 @@ WRITE8_MEMBER( sbrain_state::ppi_pc_w ) m_beep->set_state(BIT(data, 6)); m_bankr0->set_entry(BIT(data, 2)); m_bank2->set_entry(BIT(data, 4)); + if (!BIT(data, 7)) + m_keydown &= 2; // ack DR m_subcpu->set_input_line(INPUT_LINE_RESET, BIT(data, 3) ? ASSERT_LINE : CLEAR_LINE); + m_subcpu->set_input_line(Z80_INPUT_LINE_BUSRQ, BIT(data, 5) ? ASSERT_LINE : CLEAR_LINE); // ignored in z80.cpp + m_busak = BIT(data, 5); } +u8 translate_table[3][10][8] = { + // unshifted + { + { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 }, + { 0x38, 0x39, 0x2e, 0x2c, 0x2d, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x09, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67 }, + { 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f }, + { 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77 }, + { 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x7b, 0x03, 0x7f }, + { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 }, + { 0x38, 0x39, 0x2d, 0x3d, 0x5c, 0x08, 0x0a, 0x0d }, + { 0x1b, 0x00, 0x20, 0x3b, 0x27, 0x2c, 0x2e, 0x2f } + }, + // shift + { + { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 }, + { 0x38, 0x39, 0x2e, 0x2c, 0x2d, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x09, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 }, + { 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }, + { 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57 }, + { 0x58, 0x59, 0x5a, 0x5d, 0x7c, 0x7d, 0x03, 0x7f }, + { 0x29, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5e, 0x26 }, + { 0x2a, 0x28, 0x5f, 0x2b, 0x7e, 0x08, 0x0a, 0x0d }, + { 0x1b, 0x00, 0x20, 0x3a, 0x22, 0x3c, 0x3e, 0x3f } + }, + // ctrl + { + { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 }, + { 0x38, 0x39, 0x2e, 0x2c, 0x2d, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, + { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, + { 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x03, 0x1f }, + { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 }, + { 0x38, 0x39, 0x2d, 0x3d, 0x1e, 0x08, 0x0a, 0x0d }, + { 0x1b, 0x00, 0x20, 0x3b, 0x27, 0x2c, 0x2e, 0x2f } + } +}; + static INPUT_PORTS_START( sbrain ) + PORT_START("X0") + PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Keypad 0") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) + PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Keypad 1") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) + PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Keypad 2") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) + PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Keypad 3") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) + PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Keypad 4") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) + PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Keypad 5") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) + PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Keypad 6") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) + PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Keypad 7") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) + + PORT_START("X1") + PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Keypad 8") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) + PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Keypad 9") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) + PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Keypad .") PORT_CODE(KEYCODE_DEL_PAD) + PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Keypad ,") PORT_CODE(KEYCODE_ASTERISK) + PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Keypad -") PORT_CODE(KEYCODE_MINUS_PAD) + PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Insert") PORT_CODE(KEYCODE_ENTER_PAD) + + PORT_START("X2") + PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT) + PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) + PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Up") PORT_CODE(KEYCODE_UP) + PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) + + PORT_START("X3") + PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9) + PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') + PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') + PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') + PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') + PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') + PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') + PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') + + PORT_START("X4") + PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') + PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') + PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') + PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') + PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') + PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') + PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') + PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') + + PORT_START("X5") + PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') + PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') + PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') + PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') + PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') + PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') + PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') + PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') + + PORT_START("X6") + PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') + PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') + PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') + PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("[ ]") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR(']') + PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("\\ |") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') + PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("{ }") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('{') PORT_CHAR('}') + PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_END) PORT_CHAR(3) + PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Delete") PORT_CODE(KEYCODE_DEL) PORT_CHAR(127) + + PORT_START("X7") + PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') + PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') + PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') + PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') + PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') + PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') + PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') + PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') + + PORT_START("X8") + PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') + PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') + PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("- _") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') + PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("= +") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') + PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("\\ ~") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('\\') PORT_CHAR('~') + PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Backspace") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) + PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CODE(KEYCODE_INSERT) PORT_CHAR(10) + PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) + + PORT_START("X9") + PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) + PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Here Is") PORT_CODE(KEYCODE_HOME) + PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(32) + PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("; :") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') + PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("' \"") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('\"') + PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') + PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') + + PORT_START("MODIFIERS") + PORT_BIT(0x01,IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CapsLock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE + PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) + PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2) + /* vblank */ PORT_START("VS") PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_VBLANK("screen") INPUT_PORTS_END +TIMER_DEVICE_CALLBACK_MEMBER(sbrain_state::kbd_scan) +{ + // m_keydown: d0 = 1 after key pressed, and is reset by pc7; d1 = 1 while a key is down. + m_keydown &= 1; + u8 i, j, keyin, mods = ioport("MODIFIERS")->read() & 6; + u8 translate_set = 0; + if (BIT(mods, 1)) + translate_set = 1; + else + if (BIT(mods, 2)) + translate_set = 2; + + for (i = 0; i < 10; i++) + { + keyin = m_keyboard[i]->read(); + if (keyin) + { + for (j = 0; j < 8; j++) + { + if (BIT(keyin, j)) + { + u8 pressed = translate_table[translate_set][i][j]; + m_keydown = (m_term_data == pressed) ? (m_keydown | 2) : 3; + m_term_data = pressed; + return; + } + } + } + } + m_term_data = 0xff; +} + DRIVER_INIT_MEMBER( sbrain_state, sbrain ) { - uint8_t *main = memregion("maincpu")->base(); - uint8_t *sub = memregion("subcpu")->base(); + u8 *main = memregion("maincpu")->base(); + u8 *sub = memregion("subcpu")->base(); m_bankr0->configure_entry(0, &main[0x0000]); m_bankr0->configure_entry(1, &sub[0x0000]); @@ -275,16 +466,27 @@ SLOT_INTERFACE_END MACHINE_RESET_MEMBER( sbrain_state, sbrain ) { + m_keydown = 0; m_bankr0->set_entry(1); // point at rom m_bankw0->set_entry(0); // always write to ram m_bank2->set_entry(1); // point at maincpu bank m_subcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); // hold subcpu in reset } -uint32_t sbrain_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +u32 sbrain_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { - uint8_t y,ra,chr,gfx; + u8 y,ra,chr,gfx; uint16_t sy=0,ma=0,x; + m_framecnt++; + + // Where attributes come from: + // - Most systems use ram for character-based attributes, but this one uses strictly hardware which would seem cumbersome + // - d0,1 graphics from porta d0,d1 + // - d2 strike-through from porta d5 + // - d3 underline from porta d2 + // - d4 reverse-video from porta d7 + // - d5 blank from PC1 (scan-line based) + // - d6 flash from bit 7 of each character for (y = 0; y < 24; y++) { @@ -299,8 +501,15 @@ uint32_t sbrain_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap { chr = m_p_videoram[x+ma]; - if (chr) gfx = m_p_chargen[(chr<<4) | ra ]; + if (!BIT(chr, 7) || BIT(m_framecnt, 5)) + { + chr &= 0x7f; + + if (chr) + gfx = m_p_chargen[(chr<<4) | ra ]; + } } + /* Display a scanline of a character */ *p++ = BIT(gfx, 7); *p++ = BIT(gfx, 6); @@ -322,11 +531,14 @@ static MACHINE_CONFIG_START( sbrain ) MCFG_CPU_ADD("maincpu", Z80, XTAL_16MHz / 4) MCFG_CPU_PROGRAM_MAP(sbrain_mem) MCFG_CPU_IO_MAP(sbrain_io) - MCFG_MACHINE_RESET_OVERRIDE(sbrain_state, sbrain) + MCFG_CPU_VBLANK_INT_DRIVER("screen", sbrain_state, irq0_line_hold) + MCFG_CPU_ADD("subcpu", Z80, XTAL_16MHz / 4) MCFG_CPU_PROGRAM_MAP(sbrain_submem) MCFG_CPU_IO_MAP(sbrain_subio) + MCFG_MACHINE_RESET_OVERRIDE(sbrain_state, sbrain) + /* video hardware */ MCFG_SCREEN_ADD_MONOCHROME("screen", RASTER, rgb_t::amber()) MCFG_SCREEN_REFRESH_RATE(60) @@ -356,21 +568,31 @@ static MACHINE_CONFIG_START( sbrain ) MCFG_DEVICE_ADD("uart1", I8251, 0) - MCFG_DEVICE_ADD("brg", COM8116, XTAL_5_0688MHz) - MCFG_COM8116_FR_HANDLER(WRITELINE(sbrain_state, fr_w)) - MCFG_COM8116_FT_HANDLER(WRITELINE(sbrain_state, ft_w)) + MCFG_DEVICE_ADD("brg", COM8116, XTAL_5_0688MHz) // BR1941L + MCFG_COM8116_FR_HANDLER(DEVWRITELINE("uart0", i8251_device, write_txc)) + MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("uart0", i8251_device, write_rxc)) + MCFG_COM8116_FT_HANDLER(DEVWRITELINE("uart1", i8251_device, write_txc)) + MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("uart1", i8251_device, write_rxc)) MCFG_FD1791_ADD("fdc", XTAL_16MHz / 16) MCFG_FLOPPY_DRIVE_ADD("fdc:0", sbrain_floppies, "525dd", floppy_image_device::default_floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) MCFG_FLOPPY_DRIVE_ADD("fdc:1", sbrain_floppies, "525dd", floppy_image_device::default_floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) + + MCFG_TIMER_DRIVER_ADD_PERIODIC("timer_a", sbrain_state, kbd_scan, attotime::from_hz(15)) MACHINE_CONFIG_END ROM_START( sbrain ) ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF ) ROM_REGION( 0x10000, "subcpu", ROMREGION_ERASEFF ) - ROM_LOAD( "superbrain.bin", 0x0000, 0x0800, CRC(b6a2e6a5) SHA1(a646faaecb9ac45ee1a42764628e8971524d5c13) ) - + ROM_SYSTEM_BIOS( 0, "4_003", "4.003" ) + ROMX_LOAD( "4_003_vc8001.z69", 0x0000, 0x0800, CRC(3ce3cd53) SHA1(fb6ade6bd67de3d9f911a1a48481ca619bda65ae), ROM_BIOS(1) ) + ROM_SYSTEM_BIOS( 1, "3_1", "3.1" ) + ROMX_LOAD( "3_1.z69", 0x0000, 0x0800, CRC(b6a2e6a5) SHA1(a646faaecb9ac45ee1a42764628e8971524d5c13), ROM_BIOS(2) ) + ROM_SYSTEM_BIOS( 2, "3_05", "3.05" ) + ROMX_LOAD( "qd_3_05.z69", 0x0000, 0x0800, CRC(aedbe777) SHA1(9ee9ca3f05e11ceb80896f06c3a3ae352db214dc), ROM_BIOS(3) ) // Using the chargen from 'c10' for now. ROM_REGION( 0x2000, "chargen", 0 ) ROM_LOAD( "c10_char.bin", 0x0000, 0x2000, BAD_DUMP CRC(cb530b6f) SHA1(95590bbb433db9c4317f535723b29516b9b9fcbf)) -- cgit v1.2.3