From 7a691be059ad085922723f332c484c6aba086252 Mon Sep 17 00:00:00 2001 From: hap Date: Thu, 9 Nov 2023 16:21:07 +0100 Subject: [PATCH] ccompan2: remove standbytimer, hlcd0515/mattelchess: add nvram --- src/devices/machine/nvram.cpp | 16 +++--- src/devices/video/hlcd0515.cpp | 98 +++++++++++++++++++++++++++------- src/devices/video/hlcd0515.h | 10 +++- src/mame/layout/mchess.lay | 8 +-- src/mame/mattel/chess.cpp | 39 ++++++++------ src/mame/saitek/ccompan2.cpp | 19 +++---- 6 files changed, 128 insertions(+), 62 deletions(-) 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)); } }