diff --git a/src/devices/machine/nvram.cpp b/src/devices/machine/nvram.cpp
index 84c07477e9a..bd1f0e79a1c 100644
--- a/src/devices/machine/nvram.cpp
+++ b/src/devices/machine/nvram.cpp
@@ -22,14 +22,14 @@ DEFINE_DEVICE_TYPE(NVRAM, nvram_device, "nvram", "NVRAM")
// nvram_device - constructor
//-------------------------------------------------
-nvram_device::nvram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, NVRAM, tag, owner, clock),
- device_nvram_interface(mconfig, *this),
- m_region(*this, DEVICE_SELF),
- m_default_value(DEFAULT_ALL_1),
- m_custom_handler(*this),
- m_base(nullptr),
- m_length(0)
+nvram_device::nvram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, NVRAM, tag, owner, clock),
+ device_nvram_interface(mconfig, *this),
+ m_region(*this, DEVICE_SELF),
+ m_default_value(DEFAULT_ALL_1),
+ m_custom_handler(*this),
+ m_base(nullptr),
+ m_length(0)
{
}
diff --git a/src/devices/video/hlcd0515.cpp b/src/devices/video/hlcd0515.cpp
index 5598391bba2..ed9e5cb7b0a 100644
--- a/src/devices/video/hlcd0515.cpp
+++ b/src/devices/video/hlcd0515.cpp
@@ -30,9 +30,13 @@ DEFINE_DEVICE_TYPE(HLCD0601, hlcd0601_device, "hlcd0601", "Hughes HLCD 0601 LCD
hlcd0515_device::hlcd0515_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 colmax) :
device_t(mconfig, type, tag, owner, clock),
+ device_nvram_interface(mconfig, *this),
m_colmax(colmax),
m_write_cols(*this), m_write_data(*this)
-{ }
+{
+ // disable nvram by default
+ nvram_enable_backup(false);
+}
hlcd0515_device::hlcd0515_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
hlcd0515_device(mconfig, HLCD0515, tag, owner, clock, 25)
@@ -56,18 +60,9 @@ hlcd0601_device::hlcd0601_device(const machine_config &mconfig, const char *tag,
// device_start - device-specific startup
//-------------------------------------------------
-void hlcd0515_device::device_start()
+void hlcd0515_device::internal_clear()
{
- // timer
- m_lcd_timer = timer_alloc(FUNC(hlcd0515_device::scan_lcd), this);
- attotime period = attotime::from_hz(clock() / 2);
- m_lcd_timer->adjust(period, 0, period);
-
- // zerofill
- m_cs = 0;
- m_clk = 0;
- m_data = 0;
- m_dataout = 0;
+ // clear internal registers and RAM
m_count = 0;
m_control = 0;
m_blank = false;
@@ -76,6 +71,21 @@ void hlcd0515_device::device_start()
m_rowsel = 0;
m_buffer = 0;
memset(m_ram, 0, sizeof(m_ram));
+}
+
+void hlcd0515_device::device_start()
+{
+ // timer
+ m_lcd_timer = timer_alloc(FUNC(hlcd0515_device::scan_lcd), this);
+ attotime period = attotime::from_hz(clock() / 2);
+ m_lcd_timer->adjust(period, 0, period);
+
+ // zerofill
+ internal_clear();
+ m_cs = 0;
+ m_clk = 0;
+ m_data = 0;
+ m_dataout = 0;
// register for savestates
save_item(NAME(m_cs));
@@ -95,7 +105,63 @@ void hlcd0515_device::device_start()
//-------------------------------------------------
-// scan_lcd -
+// nvram (when VDD is battery-backed, rare occurence)
+//-------------------------------------------------
+
+bool hlcd0515_device::nvram_write(util::write_stream &file)
+{
+ size_t actual;
+
+ // misc internal registers
+ u8 buf[6];
+ buf[0] = m_count;
+ buf[1] = m_control;
+ buf[2] = m_blank ? 1 : 0;
+ buf[3] = m_rowmax;
+ buf[4] = m_rowout;
+ buf[5] = m_rowsel;
+
+ if (file.write(&buf, sizeof(buf), actual) || (sizeof(buf) != actual))
+ return false;
+
+ // shift register and RAM
+ if (file.write(&m_buffer, sizeof(m_buffer), actual) || (sizeof(m_buffer) != actual))
+ return false;
+ if (file.write(&m_ram, sizeof(m_ram), actual) || (sizeof(m_ram) != actual))
+ return false;
+
+ return true;
+}
+
+bool hlcd0515_device::nvram_read(util::read_stream &file)
+{
+ size_t actual;
+
+ // misc internal registers
+ u8 buf[6];
+ if (file.read(&buf, sizeof(buf), actual) || (sizeof(buf) != actual))
+ return false;
+
+ m_count = buf[0];
+ m_control = buf[1];
+ m_blank = bool(buf[2]);
+ m_rowmax = buf[3] & 7;
+ m_rowout = buf[4] & 7;
+ m_rowsel = buf[5] & 7;
+
+ // shift register and RAM
+ if (file.read(&m_buffer, sizeof(m_buffer), actual) || (sizeof(m_buffer) != actual))
+ return false;
+ if (file.read(&m_ram, sizeof(m_ram), actual) || (sizeof(m_ram) != actual))
+ return false;
+
+ return true;
+}
+
+
+
+//-------------------------------------------------
+// I/O handlers
//-------------------------------------------------
TIMER_CALLBACK_MEMBER(hlcd0515_device::scan_lcd)
@@ -109,11 +175,6 @@ TIMER_CALLBACK_MEMBER(hlcd0515_device::scan_lcd)
}
-
-//-------------------------------------------------
-// handlers
-//-------------------------------------------------
-
void hlcd0515_device::set_control()
{
// clock 0,1,2: row select
@@ -178,7 +239,6 @@ void hlcd0515_device::clock_w(int state)
if (m_count == 4)
set_control();
}
-
else
clock_data(m_count - 5);
diff --git a/src/devices/video/hlcd0515.h b/src/devices/video/hlcd0515.h
index 1e23f78a530..0bd5f871d8b 100644
--- a/src/devices/video/hlcd0515.h
+++ b/src/devices/video/hlcd0515.h
@@ -41,7 +41,7 @@
*/
-class hlcd0515_device : public device_t
+class hlcd0515_device : public device_t, public device_nvram_interface
{
public:
hlcd0515_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
@@ -61,6 +61,12 @@ protected:
// device-level overrides
virtual void device_start() override;
+ // device_nvram_interface overrides
+ virtual void nvram_default() override { internal_clear(); }
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
+
+ void internal_clear();
TIMER_CALLBACK_MEMBER(scan_lcd);
virtual void set_control();
@@ -72,7 +78,7 @@ protected:
int m_clk; // "
int m_data; // "
int m_dataout; // DATA OUT pin state
- int m_count;
+ u8 m_count;
u8 m_control;
bool m_blank; // display blank/visible
u8 m_rowmax; // number of rows output by lcd (max 8)
diff --git a/src/mame/layout/mchess.lay b/src/mame/layout/mchess.lay
index 031da14ea77..cb6eb28daf1 100644
--- a/src/mame/layout/mchess.lay
+++ b/src/mame/layout/mchess.lay
@@ -37,9 +37,8 @@ license:CC0-1.0
-
-
-
+
+
@@ -156,7 +155,8 @@ license:CC0-1.0
-
+
+
diff --git a/src/mame/mattel/chess.cpp b/src/mame/mattel/chess.cpp
index 3c5758c8ea4..db1f80df46f 100644
--- a/src/mame/mattel/chess.cpp
+++ b/src/mame/mattel/chess.cpp
@@ -5,6 +5,16 @@
Mattel Computer Chess
+The chess engine is by Julio Kaplan, before he was working for SciSys/Saitek.
+
+The power switch has a SAVE setting, this keeps the LCD chips powered on, and
+the program reads the chessboard position from LCD RAM on the next boot. To save
+a game in progress, make sure to press CLEAR before powering off. It does not
+save the level setting.
+
+There is no button to start a new game. The user is meant to switch power off/on.
+In MAME, reset (or exit/restart) while the save switch is off.
+
Hardware notes:
- INS8050 CPU @ 6MHz (4KB internal ROM, 256 bytes internal RAM)
- 2*HLCD0569(also seen with 2*HLCD0601, functionally same?)
@@ -16,8 +26,10 @@ assumed to be an unlicensed clone.
*******************************************************************************/
#include "emu.h"
+
#include "cpu/mcs48/mcs48.h"
#include "video/hlcd0515.h"
+
#include "screen.h"
// internal artwork
@@ -39,8 +51,6 @@ public:
void mchess(machine_config &config);
- DECLARE_INPUT_CHANGED_MEMBER(reset_switch) { update_reset(newval); }
-
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
@@ -52,8 +62,6 @@ private:
required_ioport_array<4> m_inputs;
output_finder<2, 8, 22> m_out_x;
- void update_reset(ioport_value state);
-
// I/O handlers
template void lcd_output_w(offs_t offset, u32 data);
void input_w(u8 data);
@@ -77,14 +85,12 @@ void mchess_state::machine_start()
void mchess_state::machine_reset()
{
- update_reset(m_inputs[3]->read());
-}
-
-void mchess_state::update_reset(ioport_value state)
-{
- // battery is disconnected from CPU VCC pin when power switch is in SAVE mode
- // (at reboot, the game will read the chessboard positions from LCD RAM)
- m_maincpu->set_input_line(INPUT_LINE_RESET, state ? ASSERT_LINE : CLEAR_LINE);
+ // clear nvram if SAVE is off
+ if (~m_inputs[3]->read() & 1)
+ {
+ m_lcd[0]->nvram_reset();
+ m_lcd[1]->nvram_reset();
+ }
}
@@ -96,12 +102,10 @@ void mchess_state::update_reset(ioport_value state)
template
void mchess_state::lcd_output_w(offs_t offset, u32 data)
{
- int enabled = ~m_inputs[3]->read() & m_lcd_control & 1;
-
// output to x.y.z where x = chip, y = row, z = col
// up to 22 columns used
for (int i = 0; i < 22; i++)
- m_out_x[Sel][offset][i] = BIT(data, i) & enabled;
+ m_out_x[Sel][offset][i] = BIT(data, i) & m_lcd_control;
}
void mchess_state::input_w(u8 data)
@@ -181,7 +185,7 @@ static INPUT_PORTS_START( mchess )
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_B) PORT_NAME("Take Back")
PORT_START("IN.3")
- PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_CODE(KEYCODE_F1) PORT_TOGGLE PORT_CHANGED_MEMBER(DEVICE_SELF, mchess_state, reset_switch, 0) PORT_NAME("Save Switch")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_CODE(KEYCODE_F1) PORT_TOGGLE PORT_NAME("Save Switch")
INPUT_PORTS_END
@@ -202,8 +206,11 @@ void mchess_state::mchess(machine_config &config)
// video hardware
HLCD0569(config, m_lcd[0], 500); // C=0.01uF
m_lcd[0]->write_cols().set(FUNC(mchess_state::lcd_output_w<0>));
+ m_lcd[0]->nvram_enable_backup(true);
+
HLCD0569(config, m_lcd[1], 500); // C=0.01uF
m_lcd[1]->write_cols().set(FUNC(mchess_state::lcd_output_w<1>));
+ m_lcd[1]->nvram_enable_backup(true);
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_SVG));
screen.set_refresh_hz(60);
diff --git a/src/mame/saitek/ccompan2.cpp b/src/mame/saitek/ccompan2.cpp
index 7395528654c..8ca73c59e19 100644
--- a/src/mame/saitek/ccompan2.cpp
+++ b/src/mame/saitek/ccompan2.cpp
@@ -104,9 +104,8 @@ private:
void led_w(u8 data);
void set_cpu_freq();
- TIMER_CALLBACK_MEMBER(set_pin);
+ TIMER_CALLBACK_MEMBER(delayed_nmi);
- emu_timer *m_standbytimer;
emu_timer *m_nmitimer;
bool m_power = false;
u8 m_inp_mux = 0;
@@ -114,8 +113,7 @@ private:
void ccompan2_state::machine_start()
{
- m_nmitimer = timer_alloc(FUNC(ccompan2_state::set_pin), this);
- m_standbytimer = timer_alloc(FUNC(ccompan2_state::set_pin), this);
+ m_nmitimer = timer_alloc(FUNC(ccompan2_state::delayed_nmi), this);
// register for savestates
save_item(NAME(m_power));
@@ -137,12 +135,11 @@ void ccompan2_state::set_cpu_freq()
void ccompan2_state::machine_reset()
{
m_power = true;
- m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
}
-TIMER_CALLBACK_MEMBER(ccompan2_state::set_pin)
+TIMER_CALLBACK_MEMBER(ccompan2_state::delayed_nmi)
{
- m_maincpu->set_input_line(param, ASSERT_LINE);
+ m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
}
INPUT_CHANGED_MEMBER(ccompan2_state::power_off)
@@ -152,12 +149,8 @@ INPUT_CHANGED_MEMBER(ccompan2_state::power_off)
m_power = false;
// when power switch is set to MEMORY, it triggers an NMI after a short delay
- attotime delay = attotime::from_msec(100);
- m_nmitimer->adjust(delay, INPUT_LINE_NMI);
-
- // afterwards, MCU STBY pin is asserted after a short delay
- delay += attotime::from_msec(10);
- m_standbytimer->adjust(delay, INPUT_LINE_RESET);
+ // (and shortly after that, MCU STBY is asserted)
+ m_nmitimer->adjust(attotime::from_msec(100));
}
}