summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/drivers/monty.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/drivers/monty.c')
-rw-r--r--src/mess/drivers/monty.c181
1 files changed, 129 insertions, 52 deletions
diff --git a/src/mess/drivers/monty.c b/src/mess/drivers/monty.c
index 256e01de83e..42172a6c357 100644
--- a/src/mess/drivers/monty.c
+++ b/src/mess/drivers/monty.c
@@ -19,14 +19,19 @@
by adding chips and wires to the inside of the game.
TODO:
- - Input from the keyboard
+ - Need instructions
- Proper SED1503F emulation (it's simulated in-driver for now)
+ - After each keypress it hits a HALT instruction. I guess the controller's
+ sync pin is involved somehow.
+ - When it wants tiles, put 64 into FD1B (monty), 7D1B (mmonty) and press
+ Enter.
****************************************************************************/
#include "emu.h"
#include "cpu/z80/z80.h"
#include "video/sed1520.h"
+#include "sound/speaker.h"
class monty_state : public driver_device
@@ -35,6 +40,7 @@ public:
monty_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_sed0(*this, "sed1520_0")
, m_writeUpper(false)
{
@@ -42,78 +48,130 @@ public:
m_pixels[i] = 0xff000000;
}
- DECLARE_READ8_MEMBER(ioInputRead);
-
- DECLARE_WRITE8_MEMBER(ioDisplayWrite);
- DECLARE_WRITE8_MEMBER(ioCommandWrite0);
- DECLARE_WRITE8_MEMBER(ioCommandWrite1);
+ DECLARE_WRITE8_MEMBER(sound_w);
+ DECLARE_WRITE8_MEMBER(ioDisplayWrite_w);
+ DECLARE_WRITE8_MEMBER(ioCommandWrite0_w);
+ DECLARE_WRITE8_MEMBER(ioCommandWrite1_w);
// screen updates
UINT32 lcd_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect);
private:
required_device<cpu_device> m_maincpu;
+ required_device<speaker_sound_device> m_speaker;
required_device<sed1520_device> m_sed0; // TODO: This isn't actually a SED1520, it's a SED1503F
//required_device<sed1520_device> m_sed1; // TODO: Also, there are 2 SED1503Fs on the board - one is flipped upside down
// Test
UINT8 m_writeUpper;
UINT32 m_pixels[42*32];
+ bool m_sound_sw;
+ bool m_dirty;
};
-static ADDRESS_MAP_START(monty_mem, AS_PROGRAM, 8, monty_state)
- AM_RANGE(0x0000, 0x3fff) AM_ROM
+static ADDRESS_MAP_START( monty_mem, AS_PROGRAM, 8, monty_state )
+ AM_RANGE(0x0000, 0xbfff) AM_ROM
//AM_RANGE(0x4000, 0x4000) // The main rom checks to see if another program is here on startup
AM_RANGE(0xf800, 0xffff) AM_RAM
ADDRESS_MAP_END
+static ADDRESS_MAP_START( mmonty_mem, AS_PROGRAM, 8, monty_state )
+ AM_RANGE(0x0000, 0x3fff) AM_ROM
+ //AM_RANGE(0xc000, 0xc000) // The main rom checks to see if another program is here on startup
+ AM_RANGE(0x8000, 0xffff) AM_ROM
+ AM_RANGE(0x7800, 0x7fff) AM_RAM
+ADDRESS_MAP_END
+
-static ADDRESS_MAP_START(monty_io, AS_IO, 8, monty_state)
+static ADDRESS_MAP_START( monty_io, AS_IO, 8, monty_state )
ADDRESS_MAP_GLOBAL_MASK(0xff)
- AM_RANGE(0x00, 0x00) AM_WRITE(ioCommandWrite0)
- AM_RANGE(0x02, 0x02) AM_WRITE(ioCommandWrite1)
- AM_RANGE(0x80, 0xff) AM_WRITE(ioDisplayWrite)
+ AM_RANGE(0x00, 0x00) AM_WRITE(ioCommandWrite0_w)
+ AM_RANGE(0x01, 0x01) AM_WRITE(sound_w)
+ AM_RANGE(0x02, 0x02) AM_WRITE(ioCommandWrite1_w)
+ AM_RANGE(0x80, 0xff) AM_WRITE(ioDisplayWrite_w)
// 7 reads from a bit shifted IO port
- AM_RANGE(0x01, 0x01) AM_READ(ioInputRead)
- AM_RANGE(0x02, 0x02) AM_READ(ioInputRead)
- AM_RANGE(0x04, 0x04) AM_READ(ioInputRead)
- AM_RANGE(0x08, 0x08) AM_READ(ioInputRead)
- AM_RANGE(0x10, 0x10) AM_READ(ioInputRead)
- AM_RANGE(0x20, 0x20) AM_READ(ioInputRead)
- AM_RANGE(0x40, 0x40) AM_READ(ioInputRead)
+ AM_RANGE(0x01, 0x01) AM_READ_PORT("X1")
+ AM_RANGE(0x02, 0x02) AM_READ_PORT("X2")
+ AM_RANGE(0x04, 0x04) AM_READ_PORT("X3")
+ AM_RANGE(0x08, 0x08) AM_READ_PORT("X4")
+ AM_RANGE(0x10, 0x10) AM_READ_PORT("X5")
+ AM_RANGE(0x20, 0x20) AM_READ_PORT("X6")
+ AM_RANGE(0x40, 0x40) AM_READ_PORT("X7")
ADDRESS_MAP_END
// Input ports
static INPUT_PORTS_START( monty )
+ PORT_START("X1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Left") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z')
+ PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("X2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('X')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('W')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('V')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('U')
+ PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("X3")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('T')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('S')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('R')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('P')
+ PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("X4")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('O')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('N')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('M')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('L')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('K')
+ PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("X5")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('J')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('I')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('H')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('G')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F')
+ PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("X6")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C')
+ 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("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A')
+ PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("X7")
+ PORT_BIT( 0xFF, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
-READ8_MEMBER( monty_state::ioInputRead )
+WRITE8_MEMBER( monty_state::sound_w )
{
- //UINT8 foo; // = machine().rand() & 0xff;
- //if (m_maincpu->pc() == 0x135f)
- // foo = 0x14;
- //if (m_maincpu->pc() == 0x1371)
- // foo = 0x1f;
-
- UINT8 foo = (machine().rand() & 0xff) | 0x14;
-
- //printf("(%04x) %02x %02x\n", m_maincpu->pc(), foo, (foo & 0x14));
- return foo;
+ m_sound_sw ^= 1;
+ m_speaker->level_w(m_sound_sw);
}
-WRITE8_MEMBER( monty_state::ioCommandWrite0 )
+WRITE8_MEMBER( monty_state::ioCommandWrite0_w )
{
//printf("(%04x) Command Port 0 write : %02x\n", m_maincpu->pc(), data);
m_writeUpper = false;
}
-WRITE8_MEMBER( monty_state::ioCommandWrite1 )
+WRITE8_MEMBER( monty_state::ioCommandWrite1_w )
{
//if (data == 0xfe)
// printf("---\n");
@@ -123,42 +181,49 @@ WRITE8_MEMBER( monty_state::ioCommandWrite1 )
}
-WRITE8_MEMBER( monty_state::ioDisplayWrite )
+WRITE8_MEMBER( monty_state::ioDisplayWrite_w )
{
+ m_dirty = true;
// Offset directly corresponds to sed1503, DD RAM address (offset 0x7f may be special?)
//printf("(%04x) %02x %02x\n", m_maincpu->pc(), offset, data);
- const UINT8 localUpper = (offset & 0x40) >> 6;
- const UINT8 seg = offset & 0x3f;
- const UINT8 com = data;
+ UINT8 x = offset & 0x3f;
+ UINT8 y = (BIT(offset, 6) + (m_writeUpper ? 2 : 0)) << 3;
// Skip the controller and write straight to the LCD (pc=134f)
for (int i = 0; i < 8; i++)
{
- // Pixel location
- const int upperSedOffset = m_writeUpper ? 8*2 : 0;
-
- const size_t x = seg;
- const size_t y = i + (localUpper*8) + upperSedOffset;
-
// Pixel color
- const bool on = (com >> i) & 0x01;
- m_pixels[(y*42) + x] = on ? 0xffffffff : 0xff000000;
+ if (x < 42)
+ m_pixels[(y*42) + x] = BIT(data, i) ? 0xffffffff : 0xff000000;
+
+ y++;
}
}
UINT32 monty_state::lcd_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect)
{
- for (int y = 0; y < 32; y++)
+ if (!m_dirty)
+ return 1;
+
+ UINT8 x,y,z;
+ m_dirty = false;
+ for (y = 0; y < 32; y++)
{
- for (int x = 0; x < 42; x++)
+ for (z = 0; z < 8; z++)
{
- bitmap.pix32(y, x) = m_pixels[(y*42) + x];
+ for (x = 0; x < 5; x++)
+ {
+ bitmap.pix32(y, x+z*6) = m_pixels[y*42 + z*5 + x];
+ }
+ bitmap.pix32(y, 5+z*6) = 0; // space between letters
}
+ bitmap.pix32(y, 48) = m_pixels[y*42 + 40];
+ bitmap.pix32(y, 49) = m_pixels[y*42 + 41];
}
- return 0x00;
+ return 0;
}
@@ -180,14 +245,24 @@ static MACHINE_CONFIG_START( monty, monty_state )
MCFG_SCREEN_ADD("screen", LCD)
MCFG_SCREEN_REFRESH_RATE(50)
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) // Not accurate
- MCFG_SCREEN_SIZE(42, 32) // Two SED1503s (42x16 pixels) control the top and bottom halves
- MCFG_SCREEN_VISIBLE_AREA(0, 42-1, 0, 32-1)
+ MCFG_SCREEN_SIZE(50, 32) // Two SED1503s (42x16 pixels) control the top and bottom halves
+ MCFG_SCREEN_VISIBLE_AREA(0, 50-1, 0, 32-1)
MCFG_SCREEN_UPDATE_DRIVER(monty_state, lcd_update)
+ /* sound hardware */
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+
// LCD controller interfaces
MCFG_SED1520_ADD("sed1520_0", monty_screen_update)
MACHINE_CONFIG_END
+static MACHINE_CONFIG_DERIVED( mmonty, monty )
+ MCFG_CPU_MODIFY( "maincpu" )
+ MCFG_CPU_PROGRAM_MAP(mmonty_mem)
+MACHINE_CONFIG_END
+
// ROM definitions
ROM_START( monty )
@@ -195,6 +270,7 @@ ROM_START( monty )
ROM_LOAD( "monty_main.bin", 0x0000, 0x4000, CRC(720b4f55) SHA1(0106eb88d3fbbf25a745b9b6ee785ba13689d095) ) // 27128
ROM_LOAD( "monty_module1.bin", 0x4000, 0x4000, CRC(2725d8c3) SHA1(8273b9779c0915f9c7c43ea4fb460f43ce036358) ) // 27128
ROM_LOAD( "monty_module2.bin", 0x8000, 0x4000, CRC(db672e47) SHA1(bb14fe86df06cfa4b19625ba417d1a5bc8eae155) ) // 27128
+ ROM_FILL(0x1193,1,0) // patch out HALT so we can type in our names
ROM_END
ROM_START( mmonty )
@@ -202,10 +278,11 @@ ROM_START( mmonty )
ROM_LOAD( "master_monty_main.bin", 0x0000, 0x8000, CRC(bb5ef4d4) SHA1(ba2c759e429f8740df419f9abb60832eddfba8ab) ) // 27C256
ROM_LOAD( "monty_module1.bin", 0x8000, 0x4000, CRC(2725d8c3) SHA1(8273b9779c0915f9c7c43ea4fb460f43ce036358) ) // 27128
ROM_LOAD( "monty_module2.bin", 0xc000, 0x4000, CRC(db672e47) SHA1(bb14fe86df06cfa4b19625ba417d1a5bc8eae155) ) // 27128
+ ROM_FILL(0x1487,1,0) // patch out HALT so we can type in our names
ROM_END
// Drivers
// YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS
-COMP( 1980, monty, 0, 0, monty, monty, driver_device, 0, "Ritam", "Monty Plays Scrabble", GAME_IS_SKELETON )
-COMP( 1980, mmonty, 0, 0, monty, monty, driver_device, 0, "Ritam", "Master Monty", GAME_IS_SKELETON )
+COMP( 1980, monty, 0, 0, monty, monty, driver_device, 0, "Ritam", "Monty Plays Scrabble", GAME_NOT_WORKING )
+COMP( 1982, mmonty, 0, 0, mmonty, monty, driver_device, 0, "Ritam", "Master Monty", GAME_NOT_WORKING )