diff --git a/scripts/src/video.lua b/scripts/src/video.lua index 210501f525f..77e3f9063dc 100644 --- a/scripts/src/video.lua +++ b/scripts/src/video.lua @@ -850,6 +850,17 @@ if (VIDEOS["SED1330"]~=null) then } end +-------------------------------------------------- +-- +--@src/devices/video/sed1500.h,VIDEOS["SED1500"] = true +-------------------------------------------------- +if (VIDEOS["SED1500"]~=null) then + files { + MAME_DIR .. "src/devices/video/sed1500.cpp", + MAME_DIR .. "src/devices/video/sed1500.h", + } +end + -------------------------------------------------- -- --@src/devices/video/sed1520.h,VIDEOS["SED1520"] = true diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 388c9984ba5..fd0a950e205 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -354,6 +354,7 @@ VIDEOS["SCN2674"] = true VIDEOS["PWM_DISPLAY"] = true --VIDEOS["SED1200"] = true --VIDEOS["SED1330"] = true +--VIDEOS["SED1500"] = true --VIDEOS["SED1520"] = true VIDEOS["SNES_PPU"] = true VIDEOS["STVVDP"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index c871902fe45..eac401549d8 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -382,6 +382,7 @@ VIDEOS["PWM_DISPLAY"] = true VIDEOS["SDA5708"] = true VIDEOS["SED1200"] = true VIDEOS["SED1330"] = true +VIDEOS["SED1500"] = true VIDEOS["SED1520"] = true VIDEOS["SNES_PPU"] = true VIDEOS["STVVDP"] = true diff --git a/src/devices/machine/tms1024.h b/src/devices/machine/tms1024.h index 127909d27f2..1920c5efb42 100644 --- a/src/devices/machine/tms1024.h +++ b/src/devices/machine/tms1024.h @@ -68,6 +68,7 @@ public: auto write_port5_callback() { return m_write_port[4].bind(); } auto write_port6_callback() { return m_write_port[5].bind(); } auto write_port7_callback() { return m_write_port[6].bind(); } + tms1024_device &set_ms(u8 i) { m_ms = i & 1; return *this; } // if hardwired, can just set MS pin state here void write_h(u8 data); u8 read_h(); diff --git a/src/devices/video/sed1500.cpp b/src/devices/video/sed1500.cpp new file mode 100644 index 00000000000..57d6fe5f281 --- /dev/null +++ b/src/devices/video/sed1500.cpp @@ -0,0 +1,116 @@ +// license:BSD-3-Clause +// copyright-holders:hap +/* + +Epson SED1500 series LCD Driver +128 bytes internal RAM. + +SED1500: 8 commons, 42 segments +SED1501: 10 commons, 40 segments +SED1502: 16 commons, 34 segments +SED1503: 8 commons, 42 segments, needs multiple of 2 chips to function + +The default input OSC frequency is 32768Hz, the frame output frequency is +divided by 64 and by number of commons, eg. 64Hz on a SED1500. + +TODO: +- bus mode (only mode 3 now) +- EI pin (master/slave mode) +- SYNC pin, used for frame synchronizing if multiple chips are used +- SED1503 only has 8 COM pins, the extra 8 outputs are from the slave chip + +*/ + +#include "emu.h" +#include "video/sed1500.h" + + +DEFINE_DEVICE_TYPE(SED1500, sed1500_device, "sed1500", "Epson SED1500 LCD Driver") +DEFINE_DEVICE_TYPE(SED1501, sed1501_device, "sed1501", "Epson SED1501 LCD Driver") +DEFINE_DEVICE_TYPE(SED1502, sed1502_device, "sed1502", "Epson SED1502 LCD Driver") +DEFINE_DEVICE_TYPE(SED1503, sed1503_device, "sed1503", "Epson SED1503 LCD Driver") + +//------------------------------------------------- +// constructor +//------------------------------------------------- + +sed1500_device::sed1500_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 cmax, u8 smax) : + device_t(mconfig, type, tag, owner, clock), + m_cmax(cmax), m_smax(smax), + m_write_segs(*this) +{ } + +sed1500_device::sed1500_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + sed1500_device(mconfig, SED1500, tag, owner, clock, 8, 42) +{ } + +sed1501_device::sed1501_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + sed1500_device(mconfig, SED1501, tag, owner, clock, 10, 40) +{ } + +sed1502_device::sed1502_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + sed1500_device(mconfig, SED1502, tag, owner, clock, 16, 34) +{ } + +sed1503_device::sed1503_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + sed1500_device(mconfig, SED1503, tag, owner, clock, 8+8, 42) +{ } + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void sed1500_device::device_start() +{ + memset(m_ram, 0, sizeof(m_ram)); + + // resolve callbacks + m_write_segs.resolve_safe(); + + // timer + m_lcd_timer = timer_alloc(); + attotime period = attotime::from_hz(clock() / 64); + m_lcd_timer->adjust(period, 0, period); + + // register for savestates + save_item(NAME(m_mode)); + save_item(NAME(m_cout)); + save_item(NAME(m_ram)); +} + + +//------------------------------------------------- +// handlers +//------------------------------------------------- + +void sed1500_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + u64 data = 0; + + for (int i = m_smax-1; i >= 0; i--) + data = data << 1 | BIT(m_ram[i | 0x40] << 8 | m_ram[i], m_cout); + + // transfer segments to output + m_write_segs(m_cout, data); + m_cout = (m_cout + 1) % m_cmax; +} + +void sed1500_device::write(offs_t offset, u8 data) +{ + offset &= 0x7f; + m_ram[offset] = data; + + // bus mode command: + // 0 = 4-bit addr, 4-bit data, combined + // 1 = 7-bit addr, 4-bit data, separate + // 2 = 7-bit addr, 8-bit data, combined + // 3 = 7-bit addr, 8-bit data, separate + if ((offset & 0x3f) == 0x3f && ~data & 1) + m_mode = data >> 1 & 3; +} + +u8 sed1500_device::read(offs_t offset) +{ + return m_ram[offset & 0x7f]; +} diff --git a/src/devices/video/sed1500.h b/src/devices/video/sed1500.h new file mode 100644 index 00000000000..e26360966bb --- /dev/null +++ b/src/devices/video/sed1500.h @@ -0,0 +1,85 @@ +// license:BSD-3-Clause +// copyright-holders:hap +/* + + Epson SED1500 series LCD Driver + +*/ + +#ifndef MAME_VIDEO_SED1500_H +#define MAME_VIDEO_SED1500_H + +#pragma once + +/* + +pinout reference (brief) + +OSC: oscillator (resistors or XTAL) +A0-A6: address +D0-D7: data (I/O) +WR/RD: write/read signal +CS: chip select +SYNC: frame synchronize (I/O) + +CL: OSC output +COM: LCD commons +SEG: LCD segments + +*/ + +class sed1500_device : public device_t +{ +public: + sed1500_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + // configuration helpers + auto write_segs() { return m_write_segs.bind(); } // common number in offset, segment data in data + + void write(offs_t offset, u8 data); + u8 read(offs_t offset); + +protected: + sed1500_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 cmax, u8 smax); + + // device-level overrides + virtual void device_start() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + emu_timer *m_lcd_timer; + + const u8 m_cmax; // number of COL pins + const u8 m_smax; // number of SEG pins + u8 m_mode = 0; + u8 m_cout = 0; + u8 m_ram[0x80]; + + // callbacks + devcb_write64 m_write_segs; +}; + +class sed1501_device : public sed1500_device +{ +public: + sed1501_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; + +class sed1502_device : public sed1500_device +{ +public: + sed1502_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; + +class sed1503_device : public sed1500_device +{ +public: + sed1503_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; + + +DECLARE_DEVICE_TYPE(SED1500, sed1500_device) +DECLARE_DEVICE_TYPE(SED1501, sed1501_device) +DECLARE_DEVICE_TYPE(SED1502, sed1502_device) +DECLARE_DEVICE_TYPE(SED1503, sed1503_device) + +#endif // MAME_VIDEO_SED1500_H diff --git a/src/mame/drivers/hh_tms1k.cpp b/src/mame/drivers/hh_tms1k.cpp index f6997ad23ec..a0326d3911e 100644 --- a/src/mame/drivers/hh_tms1k.cpp +++ b/src/mame/drivers/hh_tms1k.cpp @@ -5371,17 +5371,8 @@ public: virtual DECLARE_WRITE16_MEMBER(write_o); virtual DECLARE_READ8_MEMBER(read_k); void ginv2000(machine_config &config); - -protected: - virtual void machine_reset() override; }; -void ginv2000_state::machine_reset() -{ - hh_tms1k_state::machine_reset(); - m_expander->write_ms(1); // Vss -} - // handlers void ginv2000_state::update_display() @@ -5453,7 +5444,7 @@ void ginv2000_state::ginv2000(machine_config &config) m_maincpu->r().set(FUNC(ginv2000_state::write_r)); m_maincpu->o().set(FUNC(ginv2000_state::write_o)); - TMS1024(config, m_expander); + TMS1024(config, m_expander).set_ms(1); // MS tied high m_expander->write_port4_callback().set(FUNC(ginv2000_state::expander_w)); m_expander->write_port5_callback().set(FUNC(ginv2000_state::expander_w)); m_expander->write_port6_callback().set(FUNC(ginv2000_state::expander_w)); @@ -11926,7 +11917,6 @@ void tbreakup_state::machine_reset() { hh_tms1k_state::machine_reset(); set_clock(); - m_expander->write_ms(1); // Vss } // handlers @@ -12021,7 +12011,7 @@ void tbreakup_state::tbreakup(machine_config &config) m_maincpu->r().set(FUNC(tbreakup_state::write_r)); m_maincpu->o().set(FUNC(tbreakup_state::write_o)); - TMS1025(config, m_expander); + TMS1025(config, m_expander).set_ms(1); // MS tied high m_expander->write_port1_callback().set(FUNC(tbreakup_state::expander_w)); m_expander->write_port2_callback().set(FUNC(tbreakup_state::expander_w)); m_expander->write_port3_callback().set(FUNC(tbreakup_state::expander_w)); diff --git a/src/mame/drivers/monty.cpp b/src/mame/drivers/monty.cpp index abd558008a8..5094265a260 100644 --- a/src/mame/drivers/monty.cpp +++ b/src/mame/drivers/monty.cpp @@ -1,38 +1,49 @@ // license:BSD-3-Clause -// copyright-holders:Andrew Gardner +// copyright-holders:Andrew Gardner, hap /*************************************************************************** - 2015-05-08 Skeleton driver for Ritam Monty Plays Scrabble BRAND crossword game +Driver for Ritam Monty Plays Scrabble BRAND crossword game - Scrabble computer that allows you play a game of Scrabble by yourself (or you - can play with up to 3 players). Has a built-in 12,000 vocabulary, expandable - to 44,000 by way of 2 expansion modules each containing 16,000 more obscure words. - You can use the included 'score cards' (which look like little Scrabble boards), - or you can use a real Scrabble board and tiles to play. Also note, Monty - apparently originally came with a little pen. +Scrabble computer that allows you play a game of Scrabble by yourself (or you +can play with up to 3 players). Has a built-in 12,000 vocabulary, expandable +to 44,000 by way of 2 expansion modules each containing 16,000 more obscure words. +You can use the included 'score cards' (which look like little Scrabble boards), +or you can use a real Scrabble board and tiles to play. Also note, Monty +apparently originally came with a little pen. - This game was later upgraded by Ritam to Master Monty which had 24,000 words - built-in (expandable to a total of 56,000 with the same 2 expansion modules). - Two variations on Master Monty have been seen: one looks exactly the same as the - Monty but the electronics on the inside have been upgraded. The later version - is blue and says Master Monty at the top. Both of these versions are hand-upgraded - by adding chips and wires to the inside of the game. +This game was later upgraded by Ritam to Master Monty which had 24,000 words +built-in (expandable to a total of 56,000 with the same 2 expansion modules). +Two variations on Master Monty have been seen: one looks exactly the same as the +Monty but the electronics on the inside have been upgraded. The later version +is blue and says Master Monty at the top. Both of these versions are hand-upgraded +by adding chips and wires to the inside of the game. - TODO: - - Need instructions - - Proper SED1503F emulation (it's simulated in-driver for now) - - When it wants tiles, put 64 into FD1B (monty), 7D1B (mmonty) and press - Enter. +Hardware notes: +- Z80 @ ~3.58MHz +- 2KB SRAM, 16KB ROM(32KB on mmonty) +- 2*16KB ROM sockets for vocabulary expansion +- 2*SED1503F, 40*32 LCD screen, beeper + +TODO: +- put expansion roms in softwarelist? (note: slot #1 only accepts rom #1, + slot #2 only accepts rom #2) ****************************************************************************/ #include "emu.h" + #include "cpu/z80/z80.h" -#include "sound/spkrdev.h" -#include "video/sed1520.h" +#include "sound/dac.h" +#include "sound/volt_reg.h" +#include "video/sed1500.h" + #include "screen.h" #include "speaker.h" +#include "monty.lh" + + +namespace { class monty_state : public driver_device { @@ -40,72 +51,109 @@ 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) - , m_halt(0) - { - for (auto & elem : m_pixels) - elem = 0xff000000; - } + , m_lcd(*this, "lcd%u", 0) + , m_dac(*this, "dac") + { } DECLARE_WRITE_LINE_MEMBER(key_pressed); void monty(machine_config &config); void mmonty(machine_config &config); +protected: + virtual void machine_start() override; + private: - DECLARE_WRITE8_MEMBER(sound_w); - DECLARE_WRITE8_MEMBER(ioDisplayWrite_w); - DECLARE_WRITE8_MEMBER(ioCommandWrite0_w); - DECLARE_WRITE8_MEMBER(ioCommandWrite1_w); - DECLARE_WRITE_LINE_MEMBER(halt_changed); - - // screen updates - uint32_t lcd_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect); - SED1520_UPDATE_CB(screen_update); + required_device m_maincpu; + required_device_array m_lcd; + required_device m_dac; + void monty_mem(address_map &map); void mmonty_mem(address_map &map); void monty_io(address_map &map); - void monty_mem(address_map &map); - required_device m_maincpu; - required_device m_speaker; - required_device m_sed0; // TODO: This isn't actually a SED1520, it's a SED1503F - //required_device m_sed1; // TODO: Also, there are 2 SED1503Fs on the board - one is flipped upside down + template void lcd_output_w(offs_t offset, u64 data) { m_lcd_data[N << 4 | offset] = data; } // buffer for screen_update + u32 screen_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect); - // Test - uint8_t m_writeUpper; - uint32_t m_pixels[42*32]; - bool m_sound_sw; - bool m_dirty; - int m_halt; + DECLARE_WRITE8_MEMBER(control_w); + DECLARE_WRITE8_MEMBER(lcd_w) { m_lcd[m_lcd_cs]->write(offset, data); } + DECLARE_WRITE_LINE_MEMBER(halt_changed) { m_halt = state; } + + u64 m_lcd_data[32]; + int m_lcd_cs = 0; + int m_halt = 0; }; +void monty_state::machine_start() +{ + save_item(NAME(m_lcd_data)); + save_item(NAME(m_lcd_cs)); + save_item(NAME(m_halt)); +} + + + +/****************************************************************************** + Video +******************************************************************************/ + +u32 monty_state::screen_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect) +{ + bitmap.fill(0xffffff); + + // letters with width 5 with space in between them + for (int y = 0; y < 32; y++) + for (int x = 0; x < 40; x++) + bitmap.pix32(y + 1, x + x/5 + 1) = BIT(m_lcd_data[y], x) ? 0 : 0xffffff; + + return 0; +} + + + +/****************************************************************************** + I/O +******************************************************************************/ + +WRITE8_MEMBER(monty_state::control_w) +{ + // a0: speaker out + m_dac->write(BIT(offset, 0)); + + // a1: lcd chip select + m_lcd_cs = BIT(offset, 1); +} + +WRITE_LINE_MEMBER(monty_state::key_pressed) +{ + if (!state && m_halt) + m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero); +} + + + +/****************************************************************************** + Address Maps +******************************************************************************/ void monty_state::monty_mem(address_map &map) { map(0x0000, 0xbfff).rom(); - //map(0x4000, 0x4000) // The main rom checks to see if another program is here on startup map(0xf800, 0xffff).ram(); } void monty_state::mmonty_mem(address_map &map) { - map(0x0000, 0x3fff).rom(); - //map(0xc000, 0xc000) // The main rom checks to see if another program is here on startup - map(0x8000, 0xffff).rom(); + map(0x0000, 0x77ff).rom(); map(0x7800, 0x7fff).ram(); + map(0x8000, 0xffff).rom(); } - void monty_state::monty_io(address_map &map) { map.global_mask(0xff); - map(0x00, 0x00).w(FUNC(monty_state::ioCommandWrite0_w)); - map(0x01, 0x01).w(FUNC(monty_state::sound_w)); - map(0x02, 0x02).w(FUNC(monty_state::ioCommandWrite1_w)); - map(0x80, 0xff).w(FUNC(monty_state::ioDisplayWrite_w)); + map(0x00, 0x03).w(FUNC(monty_state::control_w)); + map(0x80, 0xff).w(FUNC(monty_state::lcd_w)); // 7 reads from a bit shifted IO port map(0x01, 0x01).portr("X1"); @@ -118,13 +166,17 @@ void monty_state::monty_io(address_map &map) } -// Input ports + +/****************************************************************************** + 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_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Left") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Erase") PORT_CODE(KEYCODE_DEL) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Option") PORT_CODE(KEYCODE_SPACE) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Blank") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED ) @@ -147,145 +199,61 @@ static INPUT_PORTS_START( monty ) PORT_START("X4") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CODE(KEYCODE_DOWN) PORT_CHAR('M') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) 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_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR('I') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CODE(KEYCODE_LEFT) PORT_CHAR('G') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) 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_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CODE(KEYCODE_UP) PORT_CHAR('C') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, monty_state, key_pressed) PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("X7") - PORT_BIT( 0xFF, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) INPUT_PORTS_END -WRITE8_MEMBER( monty_state::sound_w ) -{ - m_sound_sw ^= 1; - m_speaker->level_w(m_sound_sw); -} +/****************************************************************************** + Machine Configs +******************************************************************************/ -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_w ) -{ - //if (data == 0xfe) - // printf("---\n"); - - //printf("(%04x) Command Port 1 write : %02x\n", m_maincpu->pc(), data); - m_writeUpper = true; -} - - -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); - - uint8_t x = offset & 0x3f; - uint8_t 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 color - if (x < 42) - m_pixels[(y*42) + x] = BIT(data, i) ? 0xffffffff : 0xff000000; - - y++; - } -} - - -WRITE_LINE_MEMBER( monty_state::halt_changed ) -{ - m_halt = state; -} - - -WRITE_LINE_MEMBER( monty_state::key_pressed ) -{ - if (!state && m_halt) - m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero); -} - - -uint32_t monty_state::lcd_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect) -{ - if (!m_dirty) - return 1; - - uint8_t x,y,z; - m_dirty = false; - for (y = 0; y < 32; y++) - { - for (z = 0; z < 8; z++) - { - 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 0; -} - - -SED1520_UPDATE_CB(monty_state::screen_update) -{ - // TODO: Not really a SED1520 - there are two SED1503s - return 0x00; -} - - -// TODO: Additional machine definition - Master Monty has a different memory layout void monty_state::monty(machine_config &config) { // Basic machine hardware - Z80(config, m_maincpu, 3580000); // Ceramic resonator labeled 3.58MT + Z80(config, m_maincpu, 3.579545_MHz_XTAL); // Ceramic resonator labeled 3.58MT m_maincpu->set_addrmap(AS_PROGRAM, &monty_state::monty_mem); m_maincpu->set_addrmap(AS_IO, &monty_state::monty_io); m_maincpu->halt_cb().set(FUNC(monty_state::halt_changed)); // Video hardware screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD)); - screen.set_refresh_hz(50); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); // Not accurate - screen.set_size(50, 32); // Two SED1503s (42x16 pixels) control the top and bottom halves - screen.set_visarea(0, 50-1, 0, 32-1); - screen.set_screen_update(FUNC(monty_state::lcd_update)); + screen.set_refresh_hz(60); + screen.set_vblank_time(0); + screen.set_size(40+8+1, 32+1); + screen.set_visarea_full(); + screen.set_screen_update(FUNC(monty_state::screen_update)); - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.50); + SED1503(config, m_lcd[0], 32768).write_segs().set(FUNC(monty_state::lcd_output_w<0>)); + SED1503(config, m_lcd[1], 32768).write_segs().set(FUNC(monty_state::lcd_output_w<1>)); + config.set_default_layout(layout_monty); - // LCD controller interfaces - SED1520(config, m_sed0).set_screen_update_cb(FUNC(monty_state::screen_update)); + // Sound hardware + SPEAKER(config, "speaker").front_center(); + DAC_1BIT(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25); + VOLTAGE_REGULATOR(config, "vref").add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT); } void monty_state::mmonty(machine_config &config) @@ -295,23 +263,33 @@ void monty_state::mmonty(machine_config &config) } -// ROM definitions + +/****************************************************************************** + ROM Definitions +******************************************************************************/ + ROM_START( monty ) - ROM_REGION(0xc000, "maincpu", 0) - 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_REGION( 0x10000, "maincpu", 0 ) + 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_END ROM_START( mmonty ) - ROM_REGION(0x10000, "maincpu", 0) - 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_REGION( 0x10000, "maincpu", 0 ) + 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_END +} // anonymous namespace + + + +/****************************************************************************** + Drivers +******************************************************************************/ -// Drivers // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -COMP( 1980, monty, 0, 0, monty, monty, monty_state, empty_init, "Ritam", "Monty Plays Scrabble", MACHINE_NOT_WORKING ) -COMP( 1982, mmonty, 0, 0, mmonty, monty, monty_state, empty_init, "Ritam", "Master Monty", MACHINE_NOT_WORKING ) +COMP( 1983, monty, 0, 0, monty, monty, monty_state, empty_init, "Ritam", "Monty Plays Scrabble", MACHINE_SUPPORTS_SAVE ) +COMP( 1987, mmonty, 0, 0, mmonty, monty, monty_state, empty_init, "Ritam", "Master Monty", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/drivers/saitek_renaissance.cpp b/src/mame/drivers/saitek_renaissance.cpp index 078cf1b00e8..cd349ed44d7 100644 --- a/src/mame/drivers/saitek_renaissance.cpp +++ b/src/mame/drivers/saitek_renaissance.cpp @@ -22,7 +22,7 @@ The LCD screen is fairly large, it's the same one as in Saitek Simultano, so a chessboard display + 7seg info. TODO: -- LCD (need SED150x device + SVG screen) +- LCD (need SVG screen) - not sure about comm/module leds - make it a subdriver of saitek_leonardo.cpp? or too many differences - same TODO list as saitek_leonardo.cpp @@ -36,6 +36,7 @@ TODO: #include "sound/dac.h" #include "sound/volt_reg.h" #include "video/pwm.h" +#include "video/sed1500.h" #include "speaker.h" @@ -211,7 +212,7 @@ void ren_state::main_map(address_map &map) map(0x2400, 0x2400).w(FUNC(ren_state::leds_w)); map(0x2600, 0x2600).rw(FUNC(ren_state::control_r), FUNC(ren_state::control_w)); map(0x4000, 0x5fff).ram(); - map(0x6000, 0x607f).nopw(); // lcd + map(0x6000, 0x607f).w("lcd", FUNC(sed1502_device::write)); map(0x8000, 0xffff).rom(); } @@ -291,6 +292,7 @@ void ren_state::ren(machine_config &config) m_board->set_delay(attotime::from_msec(150)); /* video hardware */ + SED1502(config, "lcd", 32768); PWM_DISPLAY(config, m_display).set_size(9+1, 9); config.set_default_layout(layout_saitek_renaissance); diff --git a/src/mame/drivers/saitek_ssystem3.cpp b/src/mame/drivers/saitek_ssystem3.cpp index 4d0d6f81511..5cb0988702a 100644 --- a/src/mame/drivers/saitek_ssystem3.cpp +++ b/src/mame/drivers/saitek_ssystem3.cpp @@ -122,20 +122,14 @@ private: DECLARE_WRITE8_MEMBER(control_w); DECLARE_READ8_MEMBER(control_r); - u8 m_inp_mux; - u8 m_control; - u8 m_shift; - u32 m_lcd_q; + u8 m_inp_mux = 0; + u8 m_control = 0; + u8 m_shift = 0; + u32 m_lcd_q = 0; }; void ssystem3_state::machine_start() { - // zerofill - m_inp_mux = 0; - m_control = 0; - m_shift = 0; - m_lcd_q = 0; - // register for savestates save_item(NAME(m_inp_mux)); save_item(NAME(m_control)); diff --git a/src/mame/layout/monty.lay b/src/mame/layout/monty.lay new file mode 100644 index 00000000000..ea30f9c1d51 --- /dev/null +++ b/src/mame/layout/monty.lay @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + +