summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/ravens.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/ravens.c')
-rw-r--r--src/mame/drivers/ravens.c388
1 files changed, 388 insertions, 0 deletions
diff --git a/src/mame/drivers/ravens.c b/src/mame/drivers/ravens.c
new file mode 100644
index 00000000000..e122ab12f72
--- /dev/null
+++ b/src/mame/drivers/ravens.c
@@ -0,0 +1,388 @@
+// license:BSD-3-Clause
+// copyright-holders:Robbbert
+/***************************************************************************
+
+Ravensburger Selbstbaucomputer
+
+This is a project described in "Ravensburger" magazine. You had to make
+the entire thing (including the circuit boards) yourself.
+
+http://petersieg.bplaced.com/?2650_Computer:2650_Selbstbaucomputer
+
+ 2013-04-23 Skeleton driver.
+
+
+No instructions, no schematics - it's all guesswork.
+
+The cassette saves a noise but it returns a bad load.
+
+
+Version 0.9
+-----------
+Hardware:
+ 0000-07FF ROM "MON1"
+ 0800-1FFF RAM (3x HM6116)
+ 24 pushbuttons and 6-digit LED display on front panel.
+ Other buttons and switches on the main board.
+
+The few photos show the CPU and a number of ordinary 74LSxxx chips.
+There is a XTAL of unknown frequency.
+
+The buttons are labelled CMD, RUN, GOTO, RST, F, MON, PC, NXT but at
+this time not all buttons are identified.
+
+What is known:
+- Press NXT to read memory. Press NXT again to read the next address.
+- Press PC and it says PCxxxx
+- Press CMD, it says CND=, you can choose one of these:
+-- A displays value of a register. Press A again to see more registers.
+-- B sets a breakpoint
+-- C clears a breakpoint
+-- D dumps blocks to tape
+-- E examine tape file
+-- F fetch (load) from tape
+
+Quickload: Load the program then press Y. There are 6 that work and
+ 6 that do nothing.
+
+ToDo:
+- Cassette
+
+Version V2.0
+------------
+This used a terminal interface with a few non-standard control codes.
+The pushbuttons and LEDs appear to have been done away with.
+
+Commands (must be in uppercase):
+A Examine memory; press C to alter memory
+B Set breakpoint?
+C View breakpoint?
+D Dump to screen and tape (at the same time)
+E Execute
+I ?
+L Load
+R ?
+V Verify?
+
+ToDo:
+- Cassette
+
+****************************************************************************/
+
+#include "emu.h"
+#include "cpu/s2650/s2650.h"
+#include "imagedev/cassette.h"
+#include "imagedev/snapquik.h"
+#include "machine/terminal.h"
+#include "sound/wave.h"
+#include "ravens.lh"
+
+#define TERMINAL_TAG "terminal"
+
+class ravens_state : public driver_device
+{
+public:
+ ravens_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_terminal(*this, TERMINAL_TAG),
+ m_cass(*this, "cassette")
+ {
+ }
+
+ DECLARE_READ8_MEMBER(port07_r);
+ DECLARE_READ8_MEMBER(port17_r);
+ DECLARE_WRITE8_MEMBER(port1b_w);
+ DECLARE_WRITE8_MEMBER(port1c_w);
+ DECLARE_WRITE8_MEMBER(display_w);
+ DECLARE_WRITE8_MEMBER(leds_w);
+ DECLARE_WRITE8_MEMBER(kbd_put);
+ DECLARE_MACHINE_RESET(ravens2);
+ DECLARE_READ8_MEMBER(cass_r);
+ DECLARE_WRITE_LINE_MEMBER(cass_w);
+ DECLARE_QUICKLOAD_LOAD_MEMBER( ravens );
+ UINT8 m_term_char;
+ UINT8 m_term_data;
+ required_device<cpu_device> m_maincpu;
+ optional_device<generic_terminal_device> m_terminal;
+ required_device<cassette_image_device> m_cass;
+};
+
+WRITE_LINE_MEMBER( ravens_state::cass_w )
+{
+ m_cass->output(state ? -1.0 : +1.0);
+}
+
+READ8_MEMBER( ravens_state::cass_r )
+{
+ return (m_cass->input() > 0.03) ? 1 : 0;
+}
+
+WRITE8_MEMBER( ravens_state::display_w )
+{
+ output_set_digit_value(offset, data);
+}
+
+WRITE8_MEMBER( ravens_state::leds_w )
+{
+ char ledname[8];
+ for (int i = 0; i < 8; i++)
+ {
+ sprintf(ledname,"led%d",i);
+ output_set_value(ledname, !BIT(data, i));
+ }
+}
+
+READ8_MEMBER( ravens_state::port07_r )
+{
+ UINT8 ret = m_term_data;
+ m_term_data = 0x80;
+ return ret;
+}
+
+READ8_MEMBER( ravens_state::port17_r )
+{
+ UINT8 keyin, i;
+
+ keyin = ioport("X0")->read();
+ if (keyin != 0xff)
+ for (i = 0; i < 8; i++)
+ if BIT(~keyin, i)
+ return i | 0x80;
+
+ keyin = ioport("X1")->read();
+ if (keyin != 0xff)
+ for (i = 0; i < 8; i++)
+ if BIT(~keyin, i)
+ return i | 0x88;
+
+ keyin = ioport("X2")->read();
+ if (!BIT(keyin, 0))
+ m_maincpu->reset();
+ if (keyin != 0xff)
+ for (i = 0; i < 8; i++)
+ if BIT(~keyin, i)
+ return (i<<4) | 0x80;
+
+ return 0;
+}
+
+WRITE8_MEMBER( ravens_state::port1b_w )
+{
+ if (BIT(data, 7))
+ return;
+ else
+ if ((data == 0x08 && m_term_char == 0x20))
+ data = 0x0c; // FormFeed
+ else
+ if ((data == 0x0a && m_term_char == 0x20))
+ data = 0x0a; // LineFeed
+ else
+ if ((data == 0x01 && m_term_char == 0xc2))
+ data = 0x0d; // CarriageReturn
+ else
+ data = m_term_char;
+
+ m_terminal->write(space, 0, data);
+}
+
+WRITE8_MEMBER( ravens_state::port1c_w )
+{
+ m_term_char = data;
+}
+
+MACHINE_RESET_MEMBER( ravens_state, ravens2 )
+{
+ m_term_data = 0x80;
+ output_set_digit_value(6, 0);
+}
+
+
+static ADDRESS_MAP_START( ravens_mem, AS_PROGRAM, 8, ravens_state )
+ ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE( 0x0000, 0x07ff) AM_ROM
+ AM_RANGE( 0x0800, 0x1fff) AM_RAM
+ AM_RANGE( 0x2000, 0x7FFF) AM_RAM // for quickload, optional
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( ravens_io, AS_IO, 8, ravens_state )
+ ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE(0x09, 0x09) AM_WRITE(leds_w) // LED output port
+ AM_RANGE(0x10, 0x15) AM_WRITE(display_w) // 6-led display
+ AM_RANGE(0x17, 0x17) AM_READ(port17_r) // pushbuttons
+ AM_RANGE(S2650_SENSE_PORT, S2650_SENSE_PORT) AM_READ(cass_r)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( ravens2_io, AS_IO, 8, ravens_state )
+ ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE(0x07, 0x07) AM_READ(port07_r)
+ AM_RANGE(0x1b, 0x1b) AM_WRITE(port1b_w)
+ AM_RANGE(0x1c, 0x1c) AM_WRITE(port1c_w)
+ AM_RANGE(S2650_SENSE_PORT, S2650_SENSE_PORT) AM_READ(cass_r)
+ADDRESS_MAP_END
+
+/* Input ports */
+static INPUT_PORTS_START( ravens )
+ PORT_START("X0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7')
+
+ PORT_START("X1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F')
+
+ PORT_START("X2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RST") PORT_CODE(KEYCODE_F3)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("NXT") PORT_CODE(KEYCODE_UP) PORT_CHAR('^')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RUN") PORT_CODE(KEYCODE_X) PORT_CHAR('X')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PC") PORT_CODE(KEYCODE_P) PORT_CHAR('P')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("???") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("???") PORT_CODE(KEYCODE_U) PORT_CHAR('U')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CMD") PORT_CODE(KEYCODE_M) PORT_CHAR('M')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("???") PORT_CODE(KEYCODE_O) PORT_CHAR('O')
+INPUT_PORTS_END
+
+WRITE8_MEMBER( ravens_state::kbd_put )
+{
+ if (data > 0x60) data -= 0x20; // fold to uppercase
+ m_term_data = data;
+}
+
+QUICKLOAD_LOAD_MEMBER( ravens_state, ravens )
+{
+ address_space &space = m_maincpu->space(AS_PROGRAM);
+ int i;
+ int quick_addr = 0x900;
+ int exec_addr;
+ int quick_length;
+ dynamic_buffer quick_data;
+ int read_;
+ int result = IMAGE_INIT_FAIL;
+
+ quick_length = image.length();
+ if (quick_length < 0x0900)
+ {
+ image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too short");
+ image.message(" File too short");
+ }
+ else if (quick_length > 0x8000)
+ {
+ image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too long");
+ image.message(" File too long");
+ }
+ else
+ {
+ quick_data.resize(quick_length);
+ read_ = image.fread( &quick_data[0], quick_length);
+ if (read_ != quick_length)
+ {
+ image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Cannot read the file");
+ image.message(" Cannot read the file");
+ }
+ else if (quick_data[0] != 0xc6)
+ {
+ image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid header");
+ image.message(" Invalid header");
+ }
+ else
+ {
+ exec_addr = quick_data[2] * 256 + quick_data[3];
+
+ if (exec_addr >= quick_length)
+ {
+ image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Exec address beyond end of file");
+ image.message(" Exec address beyond end of file");
+ }
+ else
+ {
+ for (i = quick_addr; i < read_; i++)
+ space.write_byte(i, quick_data[i]);
+
+ /* display a message about the loaded quickload */
+ image.message(" Quickload: size=%04X : exec=%04X",quick_length,exec_addr);
+
+ // Start the quickload
+ m_maincpu->set_state_int(S2650_PC, exec_addr);
+
+ result = IMAGE_INIT_PASS;
+ }
+ }
+ }
+
+ return result;
+}
+
+static MACHINE_CONFIG_START( ravens, ravens_state )
+ /* basic machine hardware */
+ MCFG_CPU_ADD("maincpu",S2650, XTAL_1MHz) // frequency is unknown
+ MCFG_CPU_PROGRAM_MAP(ravens_mem)
+ MCFG_CPU_IO_MAP(ravens_io)
+ MCFG_S2650_FLAG_HANDLER(WRITELINE(ravens_state, cass_w))
+
+ /* video hardware */
+ MCFG_DEFAULT_LAYOUT(layout_ravens)
+
+ /* quickload */
+ MCFG_QUICKLOAD_ADD("quickload", ravens_state, ravens, "pgm", 1)
+
+ /* cassette */
+ MCFG_CASSETTE_ADD( "cassette" )
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette")
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_START( ravens2, ravens_state )
+ /* basic machine hardware */
+ MCFG_CPU_ADD("maincpu",S2650, XTAL_1MHz) // frequency is unknown
+ MCFG_CPU_PROGRAM_MAP(ravens_mem)
+ MCFG_CPU_IO_MAP(ravens2_io)
+ MCFG_S2650_FLAG_HANDLER(WRITELINE(ravens_state, cass_w))
+
+ MCFG_MACHINE_RESET_OVERRIDE(ravens_state, ravens2)
+
+ /* video hardware */
+ MCFG_DEVICE_ADD(TERMINAL_TAG, GENERIC_TERMINAL, 0)
+ MCFG_GENERIC_TERMINAL_KEYBOARD_CB(WRITE8(ravens_state, kbd_put))
+
+ /* quickload */
+ MCFG_QUICKLOAD_ADD("quickload", ravens_state, ravens, "pgm", 1)
+
+ /* cassette */
+ MCFG_CASSETTE_ADD( "cassette" )
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette")
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+MACHINE_CONFIG_END
+
+/* ROM definition */
+ROM_START( ravens )
+ ROM_REGION( 0x8000, "maincpu", 0 )
+ ROM_SYSTEM_BIOS( 0, "v1.0", "V1.0" )
+ ROMX_LOAD( "mon_v1.0.bin", 0x0000, 0x0800, CRC(785eb1ad) SHA1(c316b8ac32ab6aa37746af37b9f81a23367fedd8), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS( 1, "v0.9", "V0.9" )
+ ROMX_LOAD( "mon_v0_9.bin", 0x0000, 0x07b5, CRC(2f9b9178) SHA1(ec2ebbc80ee9ff2502c1409ab4f99127032ed724), ROM_BIOS(2))
+ROM_END
+
+ROM_START( ravens2 )
+ ROM_REGION( 0x8000, "maincpu", 0 )
+ ROM_LOAD( "mon_v2.0.bin", 0x0000, 0x0800, CRC(bcd47c58) SHA1(f261a3f128fbedbf59a8b5480758fff4d7f76de1))
+ROM_END
+
+/* Driver */
+
+/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
+COMP( 1984, ravens, 0, 0, ravens, ravens, driver_device, 0, "Joseph Glagla and Dieter Feiler", "Ravensburger Selbstbaucomputer V0.9", MACHINE_NO_SOUND_HW )
+COMP( 1985, ravens2, ravens, 0, ravens2, ravens, driver_device, 0, "Joseph Glagla and Dieter Feiler", "Ravensburger Selbstbaucomputer V2.0", MACHINE_NO_SOUND_HW )