// license:MAME // copyright-holders:Robbbert /*************************************************************************** Camputers Lynx 05/2009 Skeleton driver. The Lynx was an 8-bit British home computer that was first released in early 1983 as a 48 kB model. The designer of the Lynx was John Shireff and several models were available with 48 kB, 96 kB (from Sep 1983) or 128 kB RAM (from Dec 1983). It was possible reach 192 kB with RAM expansions on-board. The machine was based around a Z80A CPU clocked at 4 MHz, and featured a Motorola 6845 as video controller. It was possible to run CP/M with the optional 5.25" floppy disk-drive on the 96 kB and 128 kB models. Approximately 30,000 Lynx units were sold world-wide. Camputers ceased trading in June 1984. Anston Technology took over in November the same year and a re-launch was planned but never happened. In June 1986, Anston sold everything - hardware, design rights and thousands of cassettes - to the National Lynx User Group. The group planned to produce a Super-Lynx but was too busy supplying spares and technical information to owners of existing models, and the project never came into being. Hardware info: - CPU: Zilog Z80A 4 MHz - CO-PROCESSOR: Motorola 6845 (CRT controller) - RAM: 48 kb, 96 kb or 128 kb depending on models (max. 192 kb) - ROM: 16 kb (48K version), 24 KB (96K and 128K versions) - TEXT MODES: 40 x 24, 80 x 24 - GRAPHIC MODES: 256 x 248, 512 x 480 - SOUND: one voice beeper Lynx 128 Memory Map | 0000 2000 4000 6000 8000 a000 c000 e000 | 1fff 3fff 5fff 7fff 9fff bfff dfff ffff ------------------------------------------------------------------------- | | | | Bank 0 | BASIC ROM | Not Available | Ext | Ext | | | ROM1 | ROM2 ------------------------------------------------------------------------- | | Bank 1 | STORE | Workspace RAM | | ------------------------------------------------------------------------- | | | | Bank 2 | RED | BLUE | GREEN | Alt | | | | Green ------------------------------------------------------------------------- | Bank 3 | Available for Video Expansion | ------------------------------------------------------------------------- | Bank 4 | Available for User RAM Expansion | 48k and 96k are basically the same machine. 128k is different. The work so far is without the benefit of manuals, schematic etc [Robbbert] 48k, 96k: Cassette operation is strange indeed. Save takes the dac output and directs it to the tape. Load takes over line 0 of the keyboard and uses bits 0 and 5. To Do: - find Break key - banking (it is incomplete atm) - devices (cassette, disk, printer, joysticks) - find out the mc6845 clock frequency ****************************************************************************/ #include "emu.h" #include "cpu/z80/z80.h" #include "video/mc6845.h" #include "sound/dac.h" class camplynx_state : public driver_device { public: camplynx_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_palette(*this, "palette") , m_maincpu(*this, "maincpu") //, m_cass(*this, "cassette") //, m_wave(*this, WAVE_TAG) //, m_printer(*this, "centronics") , m_crtc(*this, "crtc") //, m_fdc(*this, "fdc") { } DECLARE_WRITE8_MEMBER(lynx48k_bank_w); DECLARE_WRITE8_MEMBER(lynx128k_bank_w); DECLARE_WRITE8_MEMBER(lynx128k_irq); DECLARE_DRIVER_INIT(lynx48k); DECLARE_PALETTE_INIT(camplynx); DECLARE_MACHINE_RESET(lynx128k); MC6845_UPDATE_ROW(lynx48k_update_row); MC6845_UPDATE_ROW(lynx128k_update_row); required_device m_palette; private: virtual void video_start(); required_device m_maincpu; //required_device m_cass; //required_device<> m_wave; //required_device<> m_printer; required_device m_crtc; //optional_device<> m_fdc; }; /* These bankswitch handlers are very incomplete, just enough to get the computer working. Also, as it happens 6 times for every scanline of every character, it causes a huge slowdown. */ WRITE8_MEMBER( camplynx_state::lynx48k_bank_w ) { if (!data) membank("bank1")->set_entry(0); else if (data & 2) membank("bank1")->set_entry(1); else if (data & 4) membank("bank1")->set_entry(2); else logerror("%04X: Cannot understand bankswitch command %X\n",m_maincpu->pc(), data); } WRITE8_MEMBER( camplynx_state::lynx128k_bank_w ) { /* get address space */ UINT8 *base = memregion("maincpu")->base(); /* Set read banks */ UINT8 bank = data & 0x0f; if (!bank) { membank("bank1")->set_base(base + 0x00000); membank("bank2")->set_base(base + 0x02000); membank("bank3")->set_base(base + 0x04000); membank("bank4")->set_base(base + 0x16000); membank("bank5")->set_base(base + 0x18000); membank("bank6")->set_base(base + 0x1a000); membank("bank7")->set_base(base + 0x0c000); membank("bank8")->set_base(base + 0x0e000); } else if (bank == 0x0e) { membank("bank1")->set_base(base + 0x20000); membank("bank2")->set_base(base + 0x22000); membank("bank3")->set_base(base + 0x24000); membank("bank4")->set_base(base + 0x26000); membank("bank5")->set_base(base + 0x28000); membank("bank6")->set_base(base + 0x2a000); membank("bank7")->set_base(base + 0x2c000); membank("bank8")->set_base(base + 0x2e000); } else logerror("%04X: Cannot understand bankswitch command %X\n",m_maincpu->pc(), data); /* Set write banks */ bank = data & 0xd0; if (!bank) { membank("bank11")->set_base(base + 0x10000); membank("bank12")->set_base(base + 0x12000); membank("bank13")->set_base(base + 0x14000); membank("bank14")->set_base(base + 0x16000); membank("bank15")->set_base(base + 0x18000); membank("bank16")->set_base(base + 0x1a000); membank("bank17")->set_base(base + 0x1c000); membank("bank18")->set_base(base + 0x1e000); } else if (bank == 0xc0) { membank("bank11")->set_base(base + 0x20000); membank("bank12")->set_base(base + 0x22000); membank("bank13")->set_base(base + 0x24000); membank("bank14")->set_base(base + 0x26000); membank("bank15")->set_base(base + 0x28000); membank("bank16")->set_base(base + 0x2a000); membank("bank17")->set_base(base + 0x2c000); membank("bank18")->set_base(base + 0x2e000); } else logerror("%04X: Cannot understand bankswitch command %X\n",m_maincpu->pc(), data); } static ADDRESS_MAP_START( lynx48k_mem, AS_PROGRAM, 8, camplynx_state ) ADDRESS_MAP_UNMAP_HIGH AM_RANGE(0x0000,0x5fff) AM_ROM AM_RANGE(0x6000,0x7fff) AM_RAM AM_RANGE(0x8000,0xffff) AM_RAMBANK("bank1") ADDRESS_MAP_END static ADDRESS_MAP_START( lynx128k_mem, AS_PROGRAM, 8, camplynx_state ) ADDRESS_MAP_END static ADDRESS_MAP_START( lynx48k_io , AS_IO, 8, camplynx_state ) ADDRESS_MAP_UNMAP_HIGH AM_RANGE(0x007f,0x007f) AM_MIRROR(0xff00) AM_WRITE(lynx48k_bank_w) AM_RANGE(0x0080,0x0080) AM_MIRROR(0xff00) AM_WRITENOP /* to be emulated */ AM_RANGE(0x0080,0x0080) AM_READ_PORT("LINE0") AM_RANGE(0x0180,0x0180) AM_READ_PORT("LINE1") AM_RANGE(0x0280,0x0280) AM_READ_PORT("LINE2") AM_RANGE(0x0380,0x0380) AM_READ_PORT("LINE3") AM_RANGE(0x0480,0x0480) AM_READ_PORT("LINE4") AM_RANGE(0x0580,0x0580) AM_READ_PORT("LINE5") AM_RANGE(0x0680,0x0680) AM_READ_PORT("LINE6") AM_RANGE(0x0780,0x0780) AM_READ_PORT("LINE7") AM_RANGE(0x0880,0x0880) AM_READ_PORT("LINE8") AM_RANGE(0x0980,0x0980) AM_READ_PORT("LINE9") AM_RANGE(0x0084,0x0084) AM_MIRROR(0xff00) AM_DEVWRITE("dac", dac_device, write_unsigned8) /* 6-bit dac */ AM_RANGE(0x0086,0x0086) AM_MIRROR(0xff00) AM_DEVWRITE("crtc", mc6845_device, address_w) AM_RANGE(0x0087,0x0087) AM_MIRROR(0xff00) AM_DEVREADWRITE("crtc", mc6845_device, register_r, register_w) ADDRESS_MAP_END static ADDRESS_MAP_START( lynx128k_io , AS_IO, 8, camplynx_state ) ADDRESS_MAP_UNMAP_HIGH // AM_RANGE(0x0050,0x0053) AM_MIRROR(0xff80) AM_READ(wd179x_r) // uses a 1793 // AM_RANGE(0x0054,0x0057) AM_MIRROR(0xff80) AM_WRITE(wd179x_w) // AM_RANGE(0x0058,0x0058) AM_MIRROR(0xff80) AM_WRITE(lynx128k_disk_w) // AM_RANGE(0x007a,0x007b) AM_MIRROR(0xff80) AM_READ(lynx128k_joysticks_r) // AM_RANGE(0x007c,0x007c) AM_MIRROR(0xff80) AM_READ(lynx128k_printer_r) // AM_RANGE(0x007d,0x007d) AM_MIRROR(0xff80) AM_WRITE(lynx128k_printer_init_w) // this is rw // AM_RANGE(0x007e,0x007e) AM_MIRROR(0xff80) AM_WRITE(lynx128k_printer_w) AM_RANGE(0x0080,0x0080) AM_MIRROR(0xff00) AM_WRITENOP /* to be emulated */ AM_RANGE(0x0080,0x0080) AM_READ_PORT("LINE0") AM_RANGE(0x0180,0x0180) AM_READ_PORT("LINE1") AM_RANGE(0x0280,0x0280) AM_READ_PORT("LINE2") AM_RANGE(0x0380,0x0380) AM_READ_PORT("LINE3") AM_RANGE(0x0480,0x0480) AM_READ_PORT("LINE4") AM_RANGE(0x0580,0x0580) AM_READ_PORT("LINE5") AM_RANGE(0x0680,0x0680) AM_READ_PORT("LINE6") AM_RANGE(0x0780,0x0780) AM_READ_PORT("LINE7") AM_RANGE(0x0880,0x0880) AM_READ_PORT("LINE8") AM_RANGE(0x0980,0x0980) AM_READ_PORT("LINE9") AM_RANGE(0x0082,0x0082) AM_MIRROR(0xff00) AM_WRITE(lynx128k_bank_w) // read=serial buffer AM_RANGE(0x0084,0x0084) AM_MIRROR(0xff00) AM_DEVWRITE("dac", dac_device, write_unsigned8) /* 6-bit dac. Read="single-step", causes a NMI */ AM_RANGE(0x0086,0x0086) AM_MIRROR(0xff00) AM_DEVREADWRITE("crtc", mc6845_device, status_r, address_w) AM_RANGE(0x0087,0x0087) AM_MIRROR(0xff00) AM_DEVREADWRITE("crtc", mc6845_device, register_r, register_w) ADDRESS_MAP_END /* Input ports */ static INPUT_PORTS_START( lynx48k ) PORT_START("LINE0") PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) PORT_CHAR(27) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Up") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_BIT(0x0e, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1 !") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_START("LINE1") PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C CONT") PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D DEL") PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X WEND") PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E DATA") PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4 $") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_START("LINE2") PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Control") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A AUTO") PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S STOP") PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z RESTORE") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W WHILE") PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q REM") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2 \"") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR(34) PORT_START("LINE3") PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F DEFPROC") PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G GOTO") PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V VERIFY") PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T TRACE") PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R REPEAT") PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5 %") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_START("LINE4") PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B BEEP") PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N NEXT") PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(32) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H GOSUB") PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y RUN") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6 &") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_START("LINE5") PORT_BIT(0xd0, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J LABEL") PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M RETURN") PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U UNTIL") PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8 (") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7 \'") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR(39) PORT_START("LINE6") PORT_BIT(0xd0, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K MON") PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O ENDPROC") PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I INPUT") PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9 )") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_START("LINE7") PORT_BIT(0xd0, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("; +") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L LIST") PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P PROC") PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0 _") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_START("LINE8") PORT_BIT(0xd0, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(": *") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':') PORT_CHAR('*') PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("@ \\") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('@') PORT_CHAR('\\') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("- =") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('=') PORT_START("LINE9") PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("End") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(END)) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("]") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Delete") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) INPUT_PORTS_END MACHINE_RESET_MEMBER(camplynx_state,lynx128k) { address_space &mem = m_maincpu->space(AS_PROGRAM); mem.install_read_bank (0x0000, 0x1fff, "bank1"); mem.install_read_bank (0x2000, 0x3fff, "bank2"); mem.install_read_bank (0x4000, 0x5fff, "bank3"); mem.install_read_bank (0x6000, 0x7fff, "bank4"); mem.install_read_bank (0x8000, 0x9fff, "bank5"); mem.install_read_bank (0xa000, 0xbfff, "bank6"); mem.install_read_bank (0xc000, 0xdfff, "bank7"); mem.install_read_bank (0xe000, 0xffff, "bank8"); mem.install_write_bank (0x0000, 0x1fff, "bank11"); mem.install_write_bank (0x2000, 0x3fff, "bank12"); mem.install_write_bank (0x4000, 0x5fff, "bank13"); mem.install_write_bank (0x6000, 0x7fff, "bank14"); mem.install_write_bank (0x8000, 0x9fff, "bank15"); mem.install_write_bank (0xa000, 0xbfff, "bank16"); mem.install_write_bank (0xc000, 0xdfff, "bank17"); mem.install_write_bank (0xe000, 0xffff, "bank18"); lynx128k_bank_w(mem, 0, 0); } WRITE8_MEMBER( camplynx_state::lynx128k_irq ) { m_maincpu->set_input_line(0, data); } static const UINT8 lynx48k_palette[8*3] = { 0x00, 0x00, 0x00, /* 0 Black */ 0x00, 0x00, 0xff, /* 1 Blue */ 0xff, 0x00, 0x00, /* 2 Red */ 0xff, 0x00, 0xff, /* 3 Magenta */ 0x00, 0xff, 0x00, /* 4 Green */ 0x00, 0xff, 0xff, /* 5 Cyan */ 0xff, 0xff, 0x00, /* 6 Yellow */ 0xff, 0xff, 0xff, /* 7 White */ }; PALETTE_INIT_MEMBER(camplynx_state, camplynx) { UINT8 r, b, g, i=0, color_count = 8; while (color_count--) { r = lynx48k_palette[i++]; g = lynx48k_palette[i++]; b = lynx48k_palette[i++]; palette.set_pen_color(7-color_count, rgb_t(r, g, b)); } } MC6845_UPDATE_ROW( camplynx_state::lynx48k_update_row ) { UINT8 *RAM = machine().root_device().memregion("maincpu")->base(); const rgb_t *palette = m_palette->palette()->entry_list_raw(); UINT8 r,g,b; UINT32 x, *p = &bitmap.pix32(y); for (x = (y << 5); x < x_count + (y << 5); x++) { r = RAM[0x14000+x]; g = RAM[0x1c000+x]; b = RAM[0x10000+x]; *p++ = palette[(BIT(r, 7) << 1) | (BIT(g, 7) << 2) | (BIT(b, 7))]; *p++ = palette[(BIT(r, 6) << 1) | (BIT(g, 6) << 2) | (BIT(b, 6))]; *p++ = palette[(BIT(r, 5) << 1) | (BIT(g, 5) << 2) | (BIT(b, 5))]; *p++ = palette[(BIT(r, 4) << 1) | (BIT(g, 4) << 2) | (BIT(b, 4))]; *p++ = palette[(BIT(r, 3) << 1) | (BIT(g, 3) << 2) | (BIT(b, 3))]; *p++ = palette[(BIT(r, 2) << 1) | (BIT(g, 2) << 2) | (BIT(b, 2))]; *p++ = palette[(BIT(r, 1) << 1) | (BIT(g, 1) << 2) | (BIT(b, 1))]; *p++ = palette[(BIT(r, 0) << 1) | (BIT(g, 0) << 2) | (BIT(b, 0))]; } } MC6845_UPDATE_ROW( camplynx_state::lynx128k_update_row ) { UINT8 *RAM = machine().root_device().memregion("maincpu")->base(); const rgb_t *palette = m_palette->palette()->entry_list_raw(); UINT8 r,g,b; UINT32 x, *p = &bitmap.pix32(y); for (x = (y << 6); x < x_count + (y << 6); x++) { r = RAM[0x20100+x]; g = RAM[0x28100+x]; b = RAM[0x24100+x]; *p++ = palette[(BIT(r, 7) << 1) | (BIT(g, 7) << 2) | (BIT(b, 7))]; *p++ = palette[(BIT(r, 6) << 1) | (BIT(g, 6) << 2) | (BIT(b, 6))]; *p++ = palette[(BIT(r, 5) << 1) | (BIT(g, 5) << 2) | (BIT(b, 5))]; *p++ = palette[(BIT(r, 4) << 1) | (BIT(g, 4) << 2) | (BIT(b, 4))]; *p++ = palette[(BIT(r, 3) << 1) | (BIT(g, 3) << 2) | (BIT(b, 3))]; *p++ = palette[(BIT(r, 2) << 1) | (BIT(g, 2) << 2) | (BIT(b, 2))]; *p++ = palette[(BIT(r, 1) << 1) | (BIT(g, 1) << 2) | (BIT(b, 1))]; *p++ = palette[(BIT(r, 0) << 1) | (BIT(g, 0) << 2) | (BIT(b, 0))]; } } void camplynx_state::video_start() { } static MACHINE_CONFIG_START( lynx48k, camplynx_state ) /* basic machine hardware */ MCFG_CPU_ADD("maincpu", Z80, XTAL_4MHz) MCFG_CPU_PROGRAM_MAP(lynx48k_mem) MCFG_CPU_IO_MAP(lynx48k_io) /* video hardware */ MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_REFRESH_RATE(50) MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ MCFG_SCREEN_SIZE(512, 480) MCFG_SCREEN_VISIBLE_AREA(0, 511, 0, 479) MCFG_SCREEN_UPDATE_DEVICE("crtc", mc6845_device, screen_update) MCFG_PALETTE_ADD("palette", 8) MCFG_PALETTE_INIT_OWNER(camplynx_state, camplynx) /* sound hardware */ MCFG_SPEAKER_STANDARD_MONO("mono") MCFG_SOUND_ADD("dac", DAC, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.8) /* devices */ MCFG_MC6845_ADD("crtc", MC6845, "screen", XTAL_12MHz / 8 /*? dot clock divided by dots per char */) MCFG_MC6845_SHOW_BORDER_AREA(false) MCFG_MC6845_CHAR_WIDTH(8) MCFG_MC6845_UPDATE_ROW_CB(camplynx_state, lynx48k_update_row) MACHINE_CONFIG_END static MACHINE_CONFIG_START( lynx128k, camplynx_state ) /* basic machine hardware */ MCFG_CPU_ADD("maincpu", Z80, XTAL_6MHz) MCFG_CPU_PROGRAM_MAP(lynx128k_mem) MCFG_CPU_IO_MAP(lynx128k_io) MCFG_MACHINE_RESET_OVERRIDE(camplynx_state,lynx128k) /* video hardware */ MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_REFRESH_RATE(50) MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ MCFG_SCREEN_SIZE(512, 480) MCFG_SCREEN_VISIBLE_AREA(0, 511, 0, 479) MCFG_SCREEN_UPDATE_DEVICE("crtc", mc6845_device, screen_update) MCFG_PALETTE_ADD("palette", 8) MCFG_PALETTE_INIT_OWNER(camplynx_state, camplynx) /* sound hardware */ MCFG_SPEAKER_STANDARD_MONO("mono") MCFG_SOUND_ADD("dac", DAC, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.8) /* devices */ MCFG_MC6845_ADD("crtc", MC6845, "screen", XTAL_12MHz / 8 /*? dot clock divided by dots per char */) MCFG_MC6845_SHOW_BORDER_AREA(false) MCFG_MC6845_CHAR_WIDTH(8) MCFG_MC6845_UPDATE_ROW_CB(camplynx_state, lynx128k_update_row) MCFG_MC6845_OUT_HSYNC_CB(WRITE8(camplynx_state, lynx128k_irq)) MACHINE_CONFIG_END DRIVER_INIT_MEMBER(camplynx_state,lynx48k) { UINT8 *RAM = memregion("maincpu")->base(); membank("bank1")->configure_entries(0, 3, &RAM[0x8000], 0x8000); } /* ROM definition */ ROM_START( lynx48k ) ROM_REGION( 0x20000, "maincpu", ROMREGION_ERASEFF ) ROM_SYSTEM_BIOS(0, "1", "Set1") ROMX_LOAD( "lynx48-1.rom", 0x0000, 0x2000, CRC(56feec44) SHA1(7ded5184561168e159a30fa8e9d3fde5e52aa91a), ROM_BIOS(1) ) ROMX_LOAD( "lynx48-2.rom", 0x2000, 0x2000, CRC(d894562e) SHA1(c08a78ecb4eb05baa4c52488fce3648cd2688744), ROM_BIOS(1) ) ROM_SYSTEM_BIOS(1, "2", "Set2") ROMX_LOAD( "lynx4811.rom", 0x0000, 0x2000, CRC(a933e577) SHA1(c7b30a28d99b38dbe63a1314c78e3e614287143b), ROM_BIOS(2) ) ROMX_LOAD( "lynx4812.rom", 0x2000, 0x2000, CRC(3d3fdd0e) SHA1(259d124f05367a96f891790f9418cc9c7798e2f8), ROM_BIOS(2) ) ROM_END ROM_START( lynx96k ) ROM_REGION( 0x20000, "maincpu", ROMREGION_ERASEFF ) ROM_LOAD( "lynx9646.rom", 0x0000, 0x2000, CRC(f86c5514) SHA1(77a4af7557382003d697d08f364839e2dc28f063) ) ROM_LOAD( "lynx9645.rom", 0x2000, 0x2000, CRC(f596b9a3) SHA1(3fca46bd68422d34c6cd801dd904507e52bd8846) ) ROM_LOAD( "lynx9644.rom", 0x4000, 0x1000, CRC(4b96b0de) SHA1(c372a8d26399b9b45e615b674d61ccda76491b8b) ) ROM_LOAD( "dosrom.rom", 0xe000, 0x2000, CRC(011e106a) SHA1(e77f0ca99790551a7122945f3194516b2390fb69) ) ROM_END ROM_START( lynx128k ) ROM_REGION( 0x50000, "maincpu", ROMREGION_ERASEFF ) ROM_LOAD( "lynx128-1.rom", 0x0000, 0x2000, CRC(65d292ce) SHA1(36567c2fbd9cf72f758e8cb80c21cb4d82040752) ) ROM_LOAD( "lynx128-2.rom", 0x2000, 0x2000, CRC(23288773) SHA1(e12a7ebea3fae5eb375c03e848dbb81070d9d189) ) ROM_LOAD( "lynx128-3.rom", 0x4000, 0x2000, CRC(9827b9e9) SHA1(1092367b2af51c72ce9be367179240d692aeb131) ) ROM_LOAD( "dosrom.rom", 0xe000, 0x2000, CRC(011e106a) SHA1(e77f0ca99790551a7122945f3194516b2390fb69) ) ROM_END /* Driver */ /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */ COMP( 1983, lynx48k, 0, 0, lynx48k, lynx48k, camplynx_state, lynx48k, "Camputers", "Lynx 48k", GAME_NOT_WORKING) COMP( 1983, lynx96k, lynx48k, 0, lynx48k, lynx48k, camplynx_state, lynx48k, "Camputers", "Lynx 96k", GAME_NOT_WORKING) COMP( 1983, lynx128k, lynx48k, 0, lynx128k, lynx48k, driver_device, 0, "Camputers", "Lynx 128k", GAME_NOT_WORKING)