From e5011b3f0c4f93822ee0c0166ca50d83909ffa4b Mon Sep 17 00:00:00 2001 From: hap Date: Sun, 28 Jul 2024 21:33:36 +0200 Subject: New working systems ------------------- Kasparov Blitz [hap, Berger] --- src/mame/chess/conic_cchess2.cpp | 2 +- src/mame/excalibur/mirage.cpp | 6 +- src/mame/layout/saitek_blitz.lay | 374 +++++++++++++++++++++++++++++++++++++++ src/mame/mame.lst | 3 + src/mame/saitek/blitz.cpp | 356 +++++++++++++++++++++++++++++++++++++ src/mame/saitek/mark5.cpp | 20 ++- src/mame/saitek/prisma.cpp | 5 +- 7 files changed, 756 insertions(+), 10 deletions(-) create mode 100644 src/mame/layout/saitek_blitz.lay create mode 100644 src/mame/saitek/blitz.cpp diff --git a/src/mame/chess/conic_cchess2.cpp b/src/mame/chess/conic_cchess2.cpp index b94c3a00b7b..c1196a3cc8b 100644 --- a/src/mame/chess/conic_cchess2.cpp +++ b/src/mame/chess/conic_cchess2.cpp @@ -75,7 +75,7 @@ private: u8 m_inp_mux = 0; u8 m_led_data = 0; - int m_dac_on = 0; + u8 m_dac_on = 0; // address maps void main_map(address_map &map); diff --git a/src/mame/excalibur/mirage.cpp b/src/mame/excalibur/mirage.cpp index 6c32938a06d..5fe5ab68181 100644 --- a/src/mame/excalibur/mirage.cpp +++ b/src/mame/excalibur/mirage.cpp @@ -15,8 +15,8 @@ of the chessboard. Hardware notes: - PCB label: EXCALIBUR ELECTRONICS, INC. 6/5/96, MIRAGE, 00-55052-000 -- Hitachi H8/3256 MCU (only 32KB out of 48KB internal ROM used), either mask ROM - or OTP ROM, 20MHz XTAL +- Hitachi H8/3256 MCU (only 32KB out of 48KB internal ROM used), either Mask ROM + or PROM, 20MHz XTAL - 2*L293DNE motor drivers, 2 DC motors (like a plotter), electromagnet under the chessboard for automatically moving the pieces - LCD with 5 7segs and custom segments @@ -27,7 +27,7 @@ most likely the same hardware. TODO: - like fphantom, sensorboard undo buffer fills up pretty quickly -- dump/add OTP version, maybe they improved the motor drift issue? +- dump/add PROM version, maybe they improved the motor drift issue? - it does a cold boot at every reset, so nvram won't work properly unless MAME adds some kind of auxillary autosave state feature at power-off diff --git a/src/mame/layout/saitek_blitz.lay b/src/mame/layout/saitek_blitz.lay new file mode 100644 index 00000000000..29fc0f440c0 --- /dev/null +++ b/src/mame/layout/saitek_blitz.lay @@ -0,0 +1,374 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 37b9ae54fc4..a94476f1ef5 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -38804,6 +38804,9 @@ r9751 // ROLM 9751 phone system @source:sage/sage2.cpp sage2 +@source:saitek/blitz.cpp +kblitz + @source:saitek/chessac.cpp chessac schachak diff --git a/src/mame/saitek/blitz.cpp b/src/mame/saitek/blitz.cpp new file mode 100644 index 00000000000..7b7fca36c11 --- /dev/null +++ b/src/mame/saitek/blitz.cpp @@ -0,0 +1,356 @@ +// license:BSD-3-Clause +// copyright-holders:hap +// thanks-to:Berger +/******************************************************************************* + +Saitek Kasparov Blitz (model 291) + +NOTE: Turn the power switch off before exiting MAME, otherwise NVRAM won't save +properly. + +This is the last Saitek chess computer with Julio Kaplan's involement (Heuristic +Software), although Craig Barnes continued working for Saitek. Julio Kaplan kept +programming his chess engine for a few more years, he stopped altogether after +the release of Kasparov's Gambit (Socrates II) for MS-DOS in 1993. + +At first power-on, the chessboard gets calibrated, this is done automatically +in MAME. Not counting the chessboard, the whole user interface is with 2 vertical +dials at the right edge. There are no pushbuttons. + +Hardware notes: +- PCB label: SA9-PE-020 REV3, P/N 51290-02013 +- Hitachi H8/325 MCU (either Mask ROM or PROM), 20MHz XTAL +- LCD with 10 7segs and custom segments +- piezo, 64 LEDs, metal sensors chessboard*, 2 dials + +*: The chessboard technology is not with magnets (reed switches or hall effect +sensors). There are of copper wires beneath the chessboard, each square resembles +a metal detector. Chess pieces have aluminium washers at the bottom. + +TODO: +- if/when MAME supports an exit callback, hook up power-off switch to that +- dump/add newer Mask ROM version (might be same ROM contents) + +*******************************************************************************/ + +#include "emu.h" + +#include "cpu/h8/h8325.h" +#include "machine/sensorboard.h" +#include "sound/spkrdev.h" +#include "video/pwm.h" + +#include "screen.h" +#include "speaker.h" + +// internal artwork +#include "saitek_blitz.lh" + + +namespace { + +class blitz_state : public driver_device +{ +public: + blitz_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_board(*this, "board"), + m_led_pwm(*this, "led_pwm"), + m_lcd_pwm(*this, "lcd_pwm"), + m_dac(*this, "dac"), + m_inputs(*this, "IN.0"), + m_out_lcd(*this, "s%u.%u", 0U, 0U) + { } + + void blitz(machine_config &config); + + DECLARE_INPUT_CHANGED_MEMBER(power_off) { m_power = false; } + +protected: + virtual void machine_start() override; + virtual void machine_reset() override { m_power = true; } + +private: + // devices/pointers + required_device m_maincpu; + required_device m_board; + required_device m_led_pwm; + required_device m_lcd_pwm; + required_device m_dac; + required_ioport m_inputs; + output_finder<4, 22> m_out_lcd; + + u8 m_inp_mux = 0; + u8 m_sensor_strength = 0; + bool m_sensor_state = false; + u32 m_lcd_segs = 0; + u8 m_lcd_com = 0; + bool m_power = false; + + u8 m_port3 = 0xff; + u8 m_port6 = 0xff; + + attotime m_board_init_time; + + void init_board(u8 data); + bool board_active() { return machine().time() > m_board_init_time; } + + // I/O handlers + void standby(int state); + u8 power_r(); + + void lcd_pwm_w(offs_t offset, u8 data); + void update_lcd(); + template void lcd_segs_w(u8 data); + + void p1_w(u8 data); + void p2_w(u8 data); + u8 p3_r(); + void p3_w(u8 data); + u8 p6_r(); + void p6_w(u8 data); +}; + +void blitz_state::machine_start() +{ + m_out_lcd.resolve(); + + // register for savestates + save_item(NAME(m_inp_mux)); + save_item(NAME(m_sensor_strength)); + save_item(NAME(m_sensor_state)); + save_item(NAME(m_lcd_segs)); + save_item(NAME(m_lcd_com)); + save_item(NAME(m_power)); + save_item(NAME(m_port3)); + save_item(NAME(m_port6)); + save_item(NAME(m_board_init_time)); +} + +void blitz_state::init_board(u8 data) +{ + // briefly deactivate board after a cold boot to give it time to calibrate + if (~data & 1) + m_board_init_time = machine().time() + attotime::from_msec(1750); +} + + + +/******************************************************************************* + I/O +*******************************************************************************/ + +// power + +void blitz_state::standby(int state) +{ + // clear display + if (state) + { + m_lcd_pwm->clear(); + m_led_pwm->clear(); + } +} + +u8 blitz_state::power_r() +{ + // P46: power switch state + return m_power ? 0xbf : 0xff; +} + + +// LCD + +void blitz_state::lcd_pwm_w(offs_t offset, u8 data) +{ + m_out_lcd[offset & 0x3f][offset >> 6] = data; +} + +void blitz_state::update_lcd() +{ + u32 lcd_segs = bitswap<22>(m_lcd_segs,26,27,28,29,30,31,0,1,2,3,4,5,19,7,8,9,10,11,12,13,24,25); + + for (int i = 0; i < 4; i++) + { + // LCD common is analog (voltage level) + const u8 com = population_count_32(m_lcd_com >> (i * 2) & 3); + const u32 data = (com == 0) ? lcd_segs : (com == 2) ? ~lcd_segs : 0; + m_lcd_pwm->write_row(i, data); + } +} + +template +void blitz_state::lcd_segs_w(u8 data) +{ + // P4x, P5x, P63, P7x: LCD segments + const u8 shift = 8 * N; + m_lcd_segs = (m_lcd_segs & ~(0xff << shift)) | (data << shift); + update_lcd(); +} + + +// misc + +void blitz_state::p1_w(u8 data) +{ + // P10-P15: board sensor strength (higher is more sensitive) + m_sensor_strength = bitswap<6>(data,0,1,2,3,4,5); + + // P16: ext power (no need to emulate it) +} + +void blitz_state::p2_w(u8 data) +{ + // P20-P27: LED select + m_led_pwm->write_my(~data); +} + +u8 blitz_state::p3_r() +{ + // P37: board sensor state + return m_sensor_state ? 0x7f : 0xff; +} + +void blitz_state::p3_w(u8 data) +{ + // P36: reset board sensor on falling edge + if (m_port3 & ~data & 0x40) + { + // P30-P32: board x + // P33-P35: board y + const u8 x = data & 7; + const u8 y = data >> 3 & 7; + const u8 s = m_sensor_strength; + + m_sensor_state = (s > 0x38) || (s > 0x30 && board_active() && m_board->read_sensor(x, y)); + } + + m_port3 = data; +} + +u8 blitz_state::p6_r() +{ + // P66: multiplexed inputs + return (m_inp_mux & m_inputs->read()) ? 0xbf : 0xff; +} + +void blitz_state::p6_w(u8 data) +{ + // P62: speaker out + m_dac->level_w(BIT(data, 2)); + + // P60: 74164(1) CP + // P61: 74164(1) DSB, outputs to input mux / LED data + if (~m_port6 & data & 1) + m_inp_mux = m_inp_mux << 1 | BIT(~data, 1); + m_led_pwm->write_mx(m_inp_mux); + + // P64: 74164(2) CP + // P65: 74164(2) DSB, output to LCD commons + if (~m_port6 & data & 0x10) + m_lcd_com = m_lcd_com << 1 | BIT(data, 5); + + m_port6 = data; + update_lcd(); +} + + + +/******************************************************************************* + Input Ports +*******************************************************************************/ + +// mode dial, rotary switch with 12 stops (duplicate halves) +// 1: ready, 2: options, 3: info, 4: game, 5: set up, 6: level +static const ioport_value mode_dial[6] = { 5, 1, 2, 4, 6, 3 }; + +// shuttle dial, free running dial with 6 magnets and 2 reed switches +static const ioport_value shuttle_dial[4] = { 0, 1, 3, 2 }; + +static INPUT_PORTS_START( blitz ) + PORT_START("IN.0") + PORT_BIT(0x07, 0x00, IPT_POSITIONAL_V) PORT_POSITIONS(6) PORT_WRAPS PORT_REMAP_TABLE(mode_dial) PORT_SENSITIVITY(4) PORT_KEYDELTA(1) PORT_CENTERDELTA(0) PORT_NAME("Mode Dial") + PORT_BIT(0x18, 0x00, IPT_POSITIONAL_H) PORT_POSITIONS(4) PORT_WRAPS PORT_REMAP_TABLE(shuttle_dial) PORT_SENSITIVITY(12) PORT_KEYDELTA(1) PORT_CENTERDELTA(0) PORT_NAME("Shuttle Dial") + PORT_BIT(0x60, IP_ACTIVE_HIGH, IPT_CUSTOM) // freq sel + PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN) + + PORT_START("POWER") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_CODE(KEYCODE_F1) PORT_CHANGED_MEMBER(DEVICE_SELF, blitz_state, power_off, 0) PORT_NAME("Power Off") +INPUT_PORTS_END + + + +/******************************************************************************* + Machine Configs +*******************************************************************************/ + +void blitz_state::blitz(machine_config &config) +{ + // basic machine hardware + H8325(config, m_maincpu, 20_MHz_XTAL); + m_maincpu->nvram_enable_backup(true); + m_maincpu->nvram_set_default_value(~0); + m_maincpu->standby_cb().set(m_maincpu, FUNC(h8325_device::nvram_set_battery)); + m_maincpu->standby_cb().append(FUNC(blitz_state::standby)); + m_maincpu->write_port1().set(FUNC(blitz_state::p1_w)); + m_maincpu->write_port2().set(FUNC(blitz_state::p2_w)); + m_maincpu->read_port3().set(FUNC(blitz_state::p3_r)); + m_maincpu->write_port3().set(FUNC(blitz_state::p3_w)); + m_maincpu->read_port4().set(FUNC(blitz_state::power_r)); + m_maincpu->write_port4().set(FUNC(blitz_state::lcd_segs_w<0>)); + m_maincpu->write_port5().set(FUNC(blitz_state::lcd_segs_w<1>)); + m_maincpu->read_port6().set(FUNC(blitz_state::p6_r)); + m_maincpu->write_port6().set(FUNC(blitz_state::p6_w)); + m_maincpu->write_port6().append(FUNC(blitz_state::lcd_segs_w<2>)); + m_maincpu->write_port7().set(FUNC(blitz_state::lcd_segs_w<3>)); + + SENSORBOARD(config, m_board).set_type(sensorboard_device::MAGNETS); + m_board->init_cb().set(m_board, FUNC(sensorboard_device::preset_chess)); + m_board->init_cb().append(FUNC(blitz_state::init_board)); + m_board->set_delay(attotime::from_msec(150)); + m_board->set_nvram_enable(true); + + // video hardware + PWM_DISPLAY(config, m_lcd_pwm).set_size(4, 22); + m_lcd_pwm->output_x().set(FUNC(blitz_state::lcd_pwm_w)); + + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_SVG)); + screen.set_refresh_hz(60); + screen.set_size(1920/5, 406/5); + screen.set_visarea_full(); + + PWM_DISPLAY(config, m_led_pwm).set_size(8, 8); + m_led_pwm->set_bri_levels(0.15); + + config.set_default_layout(layout_saitek_blitz); + + // sound hardware + SPEAKER(config, "speaker").front_center(); + SPEAKER_SOUND(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25); +} + + + +/******************************************************************************* + ROM Definitions +*******************************************************************************/ + +ROM_START( kblitz ) + ROM_REGION16_BE( 0x8000, "maincpu", 0 ) + ROM_LOAD("h8_325_hd6473258p10_sa9_702g.u1", 0x0000, 0x8000, CRC(a5d17819) SHA1(e46c0b70aff31809ae02a5c5973935cf118f2324) ) + + ROM_REGION( 94712, "screen", 0 ) + ROM_LOAD("kblitz.svg", 0, 94712, CRC(b3bda86b) SHA1(9b64d3d6f6a275acd05a0f78899a5aee48d6b86b) ) +ROM_END + +} // anonymous namespace + + + +/******************************************************************************* + Drivers +*******************************************************************************/ + +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS +SYST( 1990, kblitz, 0, 0, blitz, blitz, blitz_state, empty_init, "Saitek / Heuristic Software", "Kasparov Blitz", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/saitek/mark5.cpp b/src/mame/saitek/mark5.cpp index a5f1b6d9334..22ea1faac58 100644 --- a/src/mame/saitek/mark5.cpp +++ b/src/mame/saitek/mark5.cpp @@ -13,9 +13,6 @@ by Nick Toop. These credits are in the ROM data. Mark VI/Philidor was released a year later, it was a plug-in module for the Mark V. It's not much stronger than Mark V(retroactively called Mark V/Travemunde). -When using the MAME sensorboard interface with MK VI, reset the board by pressing -CLEAR before RESET, needed when starting a new game. - Hardware notes: - SY6502A @ ~2MHz (19.6608MHz XTAL, bunch of 74113 dividers) - 16KB RAM (8*HM4716AP-4N) @@ -106,7 +103,11 @@ private: u8 m_lcd_rowsel = 0; u8 m_cb_mux = 0; - emu_timer *m_irqtimer = nullptr; + attotime m_board_init_time; + emu_timer *m_irqtimer; + + void init_board(u8 data); + bool board_active() { return machine().time() > m_board_init_time; } // address maps void mark5_map(address_map &map); @@ -142,6 +143,7 @@ void mark5_state::machine_start() save_item(NAME(m_lcd_lcd)); save_item(NAME(m_lcd_rowsel)); save_item(NAME(m_cb_mux)); + save_item(NAME(m_board_init_time)); } void mark5_state::machine_reset() @@ -149,6 +151,13 @@ void mark5_state::machine_reset() reset_irq_w(0); } +void mark5_state::init_board(u8 data) +{ + // ccmk6 expects an empty chessboard after a cold boot + if (~data & 1) + m_board_init_time = machine().time() + attotime::from_msec(1500); +} + /******************************************************************************* @@ -272,7 +281,7 @@ void mark5_state::cb_w(u8 data) u8 mark5_state::cb_r() { - if (~m_inputs[6]->read() & 0x20) + if (~m_inputs[6]->read() & 0x20 || !board_active()) return 0xff; // read chessboard sensors @@ -454,6 +463,7 @@ void mark5_state::mark6(machine_config &config) SENSORBOARD(config, m_board).set_type(sensorboard_device::MAGNETS); m_board->init_cb().set(m_board, FUNC(sensorboard_device::preset_chess)); + m_board->init_cb().append(FUNC(mark5_state::init_board)); m_board->set_delay(attotime::from_msec(150)); m_board->set_nvram_enable(true); diff --git a/src/mame/saitek/prisma.cpp b/src/mame/saitek/prisma.cpp index 905ee577058..ab208df821e 100644 --- a/src/mame/saitek/prisma.cpp +++ b/src/mame/saitek/prisma.cpp @@ -22,6 +22,9 @@ Hardware notes: In 1992, it was also sold by Tandy as Chess Champion 2150L, still manufactured by Saitek. Overall, the hardware is the same, but with a slower CPU (16MHz XTAL). +TODO: +- are older versions of Prisma on PROM H8/325 just like with Blitz? + *******************************************************************************/ #include "emu.h" @@ -162,7 +165,7 @@ void prisma_state::lcd_output_w(offs_t offset, u64 data) } -// MCU ports +// misc void prisma_state::update_leds() { -- cgit v1.2.3