Camputers Lynx: added cassette save and load, added lower case for pasting, added notes.

This commit is contained in:
Robbbert 2015-05-23 22:27:43 +10:00
parent 6b32b9407d
commit ca0054a8d9

View File

@ -64,16 +64,27 @@
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.
Notes:
- The screen doesn't scroll. This is normal.
- Variable names are case-sensitive.
- Break key is the Escape key.
- Typing a line number doesn't delete the line, you are in a calculator mode
(for example, typing 67-5 will print 62)
- DEL line-number deletes the line.
- To edit a line, press Ctrl-E, it asks for line number, type it in,
then arrows to move left-right, backspace to delete, press keys to insert them
- If you entered a line and got a syntax error, press Ctrl-Q to edit it.
- Cassette tapes made on 128k are a different speed to 48k tapes. To load a 128k
tape on a 48k system, enter TAPE 3 before loading. (2,3,4,5 all seem to work).
- When loading, there's no wildcard; you must specify the name.
To Do:
- find Break key
- banking (it is incomplete atm)
- devices (cassette, disk, printer, joysticks)
- finish memory banking
- how is alt-green bank selected on 48k?
- port 80 on 48k
- disk
- printer
- joysticks
- find out the mc6845 clock frequency
****************************************************************************/
@ -82,6 +93,8 @@
#include "cpu/z80/z80.h"
#include "video/mc6845.h"
#include "sound/dac.h"
#include "imagedev/cassette.h"
#include "sound/wave.h"
class camplynx_state : public driver_device
{
@ -90,30 +103,39 @@ public:
: driver_device(mconfig, type, tag)
, m_palette(*this, "palette")
, m_maincpu(*this, "maincpu")
//, m_cass(*this, "cassette")
//, m_wave(*this, WAVE_TAG)
, m_cass(*this, "cassette")
//, m_printer(*this, "centronics")
, m_crtc(*this, "crtc")
//, m_fdc(*this, "fdc")
, m_dac(*this, "dac")
{ }
DECLARE_WRITE8_MEMBER(lynx48k_bank_w);
DECLARE_WRITE8_MEMBER(lynx128k_bank_w);
DECLARE_WRITE8_MEMBER(lynx128k_irq);
// 48k
DECLARE_READ8_MEMBER(port80_r); // cassin for 48k
DECLARE_WRITE8_MEMBER(port80_w); // control port 48k
DECLARE_WRITE8_MEMBER(port84_w); // dac port 48k
DECLARE_WRITE8_MEMBER(lynx48k_bank_w); // banking 48k
DECLARE_DRIVER_INIT(lynx48k);
DECLARE_PALETTE_INIT(camplynx);
DECLARE_MACHINE_RESET(lynx128k);
MC6845_UPDATE_ROW(lynx48k_update_row);
// 128k
DECLARE_WRITE8_MEMBER(lynx128k_port80_w); // control port 128k
DECLARE_READ8_MEMBER(lynx128k_port82_r); // cassin for 128k
DECLARE_WRITE8_MEMBER(lynx128k_port84_w); // dac port 128k
DECLARE_WRITE8_MEMBER(lynx128k_bank_w); // banking 128k
DECLARE_WRITE8_MEMBER(lynx128k_irq);
DECLARE_MACHINE_RESET(lynx128k);
MC6845_UPDATE_ROW(lynx128k_update_row);
// common
DECLARE_PALETTE_INIT(camplynx);
required_device<palette_device> m_palette;
private:
virtual void video_start();
UINT8 m_port80;
required_device<cpu_device> m_maincpu;
//required_device<cassette_image_device> m_cass;
//required_device<> m_wave;
required_device<cassette_image_device> m_cass;
//required_device<> m_printer;
required_device<mc6845_device> m_crtc;
//optional_device<> m_fdc;
required_device<dac_device> m_dac;
};
/* These bankswitch handlers are very incomplete, just enough to get the
@ -211,8 +233,8 @@ 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(0x0080,0x0080) AM_MIRROR(0xff00) AM_WRITE(port80_w)
AM_RANGE(0x0080,0x0080) AM_READ(port80_r)
AM_RANGE(0x0180,0x0180) AM_READ_PORT("LINE1")
AM_RANGE(0x0280,0x0280) AM_READ_PORT("LINE2")
AM_RANGE(0x0380,0x0380) AM_READ_PORT("LINE3")
@ -222,8 +244,8 @@ static ADDRESS_MAP_START( lynx48k_io , AS_IO, 8, camplynx_state )
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(0x0084,0x0084) AM_MIRROR(0xff00) AM_WRITE(port84_w)
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
@ -236,7 +258,7 @@ static ADDRESS_MAP_START( lynx128k_io , AS_IO, 8, camplynx_state )
// 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_MIRROR(0xff00) AM_WRITE(lynx128k_port80_w)
AM_RANGE(0x0080,0x0080) AM_READ_PORT("LINE0")
AM_RANGE(0x0180,0x0180) AM_READ_PORT("LINE1")
AM_RANGE(0x0280,0x0280) AM_READ_PORT("LINE2")
@ -247,8 +269,8 @@ static ADDRESS_MAP_START( lynx128k_io , AS_IO, 8, camplynx_state )
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(0x0082,0x0082) AM_MIRROR(0xff00) AM_READWRITE(lynx128k_port82_r,lynx128k_bank_w) // read=serial buffer
AM_RANGE(0x0084,0x0084) AM_MIRROR(0xff00) AM_WRITE(lynx128k_port84_w)
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
@ -264,63 +286,63 @@ static INPUT_PORTS_START( lynx48k )
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(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C CONT") PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CHAR('c')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D DEL") PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHAR('d')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X WEND") PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHAR('x')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E DATA") PORT_CODE(KEYCODE_E) PORT_CHAR('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(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A AUTO") PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CHAR('a')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S STOP") PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CHAR('s')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z RESTORE") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CHAR('z')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W WHILE") PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CHAR('w')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q REM") PORT_CODE(KEYCODE_Q) PORT_CHAR('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(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F DEFPROC") PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CHAR('f')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G GOTO") PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CHAR('g')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V VERIFY") PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CHAR('v')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T TRACE") PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CHAR('t')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R REPEAT") PORT_CODE(KEYCODE_R) PORT_CHAR('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(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B BEEP") PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CHAR('b')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N NEXT") PORT_CODE(KEYCODE_N) PORT_CHAR('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(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H GOSUB") PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CHAR('h')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y RUN") PORT_CODE(KEYCODE_Y) PORT_CHAR('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(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J LABEL") PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHAR('j')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M RETURN") PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CHAR('m')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U UNTIL") PORT_CODE(KEYCODE_U) PORT_CHAR('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(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K MON") PORT_CODE(KEYCODE_K) PORT_CHAR('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(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O ENDPROC") PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHAR('o')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I INPUT") PORT_CODE(KEYCODE_I) PORT_CHAR('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(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L LIST") PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHAR('l')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P PROC") PORT_CODE(KEYCODE_P) PORT_CHAR('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(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR(0x5e)
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")
@ -329,10 +351,89 @@ static INPUT_PORTS_START( lynx48k )
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(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("]") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR(0x7f)
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Delete") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
INPUT_PORTS_END
READ8_MEMBER( camplynx_state::port80_r )
{
UINT8 data = ioport("LINE0")->read();
// when reading tape, bit 0 becomes cass-in signal
if BIT(m_port80, 1)
{
data &= 0xfe;
data |= (m_cass->input() > +0.02) ? 1 : 0;
}
return data;
}
// during normal operation continually outputs E4,40,0
// bit 1 is for the cassette motor. Other bits unknown.
WRITE8_MEMBER( camplynx_state::port80_w )
{
m_port80 = data;
m_cass->change_state( BIT(data, 1) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
}
/* DAC port. If writing cassette, output goes to tape as a sine wave, otherwise it goes to speaker.
There is code below to write as a sine wave or a square wave, both work and can be loaded successfully.
However the PALE emulator cannot load either of them, although it loads its own output.
MESS can load PALE's wav files though.
Currently square wave output is selected. */
WRITE8_MEMBER( camplynx_state::port84_w )
{
if BIT(m_port80, 1)
{
// Sine wave output
//float t = (float)(unsigned)data - 32.0f;
//m_cass->output(t/31);
// Square wave output
m_cass->output(BIT(data, 5) ? -1.0 : +1.0);
}
else // speaker output
m_dac->write_unsigned8(space, 0, data);
}
/*
d7 = clock
d2 = cass-in
d1 = serial data in
d0 = serial h/s in */
READ8_MEMBER( camplynx_state::lynx128k_port82_r )
{
UINT8 data = 0xfb; // guess
data |= (m_cass->input() > +0.02) ? 4 : 0;
return data;
}
/*
d7 = serial data out
d6 = interline control
d5 = cpu access
d4 = alt green or normal green
d3 = cass motor on
d2 = cass enable
d1 = serial h/s out
d0 = speaker */
WRITE8_MEMBER( camplynx_state::lynx128k_port80_w )
{
m_port80 = data;
m_cass->change_state( BIT(data, 3) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
}
// DAC port (6-bit)
WRITE8_MEMBER( camplynx_state::lynx128k_port84_w )
{
if BIT(m_port80, 3) // could be bit 2
{
// Square wave output
m_cass->output(BIT(data, 5) ? -1.0 : +1.0);
}
else // speaker output
m_dac->write_unsigned8(space, 0, data);
}
MACHINE_RESET_MEMBER(camplynx_state,lynx128k)
{
@ -390,14 +491,15 @@ 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);
UINT8 r,g,b,x;
UINT32 *p = &bitmap.pix32(y);
UINT16 mem = ((ma << 2) + (ra << 5)) & 0x3fff;
for (x = (y << 5); x < x_count + (y << 5); x++)
for (x = 0; x < x_count; x++)
{
r = RAM[0x14000+x];
g = RAM[0x1c000+x];
b = RAM[0x10000+x];
r = RAM[0x14000+mem+x];
g = RAM[0x1c000+mem+x];
b = RAM[0x10000+mem+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))];
@ -414,14 +516,20 @@ 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);
UINT8 r,g,b,x;
UINT32 green_bank, *p = &bitmap.pix32(y);
UINT16 mem = ((ma << 2) + (ra << 6)) & 0x3fff;
// determine green bank
if BIT(m_port80, 4)
green_bank = 0x2c000+mem; // alt green
else
green_bank = 0x28000+mem; // normal green
for (x = (y << 6); x < x_count + (y << 6); x++)
for (x = 0; x < x_count; x++)
{
r = RAM[0x20100+x];
g = RAM[0x28100+x];
b = RAM[0x24100+x];
r = RAM[0x20000+mem+x];
b = RAM[0x24000+mem+x];
g = RAM[green_bank+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))];
@ -434,10 +542,6 @@ MC6845_UPDATE_ROW( camplynx_state::lynx128k_update_row )
}
}
void camplynx_state::video_start()
{
}
static MACHINE_CONFIG_START( lynx48k, camplynx_state )
/* basic machine hardware */
@ -458,13 +562,19 @@ static MACHINE_CONFIG_START( lynx48k, camplynx_state )
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("dac", DAC, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.8)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.5)
MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette")
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
/* 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)
MCFG_CASSETTE_ADD("cassette")
MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_PLAY | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_DISABLED)
//MCFG_CASSETTE_INTERFACE("camplynx_cass")
MACHINE_CONFIG_END
static MACHINE_CONFIG_START( lynx128k, camplynx_state )
@ -489,7 +599,9 @@ static MACHINE_CONFIG_START( lynx128k, camplynx_state )
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("dac", DAC, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.8)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.5)
MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette")
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
/* devices */
MCFG_MC6845_ADD("crtc", MC6845, "screen", XTAL_12MHz / 8 /*? dot clock divided by dots per char */)
@ -497,6 +609,10 @@ static MACHINE_CONFIG_START( lynx128k, camplynx_state )
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))
MCFG_CASSETTE_ADD("cassette")
MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_PLAY | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_DISABLED)
//MCFG_CASSETTE_INTERFACE("camplynx_cass")
MACHINE_CONFIG_END
DRIVER_INIT_MEMBER(camplynx_state,lynx48k)
@ -538,4 +654,4 @@ ROM_END
/* 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)
COMP( 1983, lynx128k, lynx48k, 0, lynx128k, lynx48k, driver_device, 0, "Camputers", "Lynx 128k", GAME_NOT_WORKING)