summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/chess
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/chess')
-rw-r--r--src/mame/chess/README.md3
-rw-r--r--src/mame/chess/ave_arb.cpp357
-rw-r--r--src/mame/chess/compuchess.cpp510
-rw-r--r--src/mame/chess/conchess.cpp389
-rw-r--r--src/mame/chess/conic_cchess2.cpp285
-rw-r--r--src/mame/chess/conic_cchess3.cpp161
-rw-r--r--src/mame/chess/krypton_regency.cpp350
-rw-r--r--src/mame/chess/regence.cpp249
-rw-r--r--src/mame/chess/tasc.cpp369
9 files changed, 2673 insertions, 0 deletions
diff --git a/src/mame/chess/README.md b/src/mame/chess/README.md
new file mode 100644
index 00000000000..920114aeeda
--- /dev/null
+++ b/src/mame/chess/README.md
@@ -0,0 +1,3 @@
+# **src/mame/chess** #
+
+Generic folder for chess computer drivers, where the number of drivers is too small to place them in specific company folders. \ No newline at end of file
diff --git a/src/mame/chess/ave_arb.cpp b/src/mame/chess/ave_arb.cpp
new file mode 100644
index 00000000000..9b2ee1f60fe
--- /dev/null
+++ b/src/mame/chess/ave_arb.cpp
@@ -0,0 +1,357 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+// thanks-to:Berger
+/*******************************************************************************
+
+AVE Micro Systems ARB chess computer driver, in some regions redistributed
+by Chafitz, and in Germany by Sandy Electronic.
+
+Auto Response Board (ARB) overview:
+- R6502P CPU @ 2MHz(4MHz XTAL), R6522P VIA
+- 2KB RAM(4*2114), cartridge port
+- magnetic chessboard, 8*8+12 leds
+- PCB label AV001C01 REV A
+
+The electronic magnetic chessboard is the first of its kind. AVE later licensed
+it to Fidelity (see fidelity/elite.cpp).
+
+ARB is a romless system, the program ROM is on a cartridge.
+
+Known chess modules:
+- Grand Master Series 3
+- Grand Master Series 4.0
+- Sargon 2.5
+- Sargon 3.5 (unofficial)
+
+Other games:
+- Avelan (checkers)
+
+Sandy Electronic renamed GMS 3 and GMS 4.0 to "3000 GMS" and "4,0 - 50 S".
+Sargon 3.5 was an unofficial module published by them. It was also a free EPROM
+upgrade for their customers who were unhappy with GMS 3.
+
+GMS 4.0 included button label stickers for OPTIONS, Verify, Take Back, Clear.
+
+Around 2012, Steve Braid(aka Trilobyte/Steve UK) started manufacturing ARB V2
+boards without a module slot. CPU and VIA were replaced with new WDC 14MHz-rated
+chips, running at 16MHz.
+
+TODO:
+- avelan, gms3, gms4, sargon35 rom labels
+
+*******************************************************************************/
+
+#include "emu.h"
+
+#include "bus/generic/carts.h"
+#include "bus/generic/slot.h"
+#include "cpu/m6502/m6502.h"
+#include "cpu/m6502/w65c02s.h"
+#include "video/pwm.h"
+#include "machine/6522via.h"
+#include "machine/nvram.h"
+#include "machine/sensorboard.h"
+#include "sound/dac.h"
+
+#include "speaker.h"
+#include "softlist_dev.h"
+
+// internal artwork
+#include "ave_arb.lh"
+
+
+namespace {
+
+class arb_state : public driver_device
+{
+public:
+ arb_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_display(*this, "display"),
+ m_board(*this, "board"),
+ m_via(*this, "via"),
+ m_extram(*this, "extram", 0x800, ENDIANNESS_LITTLE),
+ m_dac(*this, "dac"),
+ m_cart(*this, "cartslot"),
+ m_inputs(*this, "IN.%u", 0)
+ { }
+
+ // halt button is tied to NMI, reset button to RESET(but only if halt button is held)
+ DECLARE_INPUT_CHANGED_MEMBER(reset_button) { update_reset(); }
+ DECLARE_INPUT_CHANGED_MEMBER(halt_button) { m_maincpu->set_input_line(M6502_NMI_LINE, newval ? ASSERT_LINE : CLEAR_LINE); update_reset(); }
+ void update_reset();
+
+ void arb(machine_config &config);
+ void v2(machine_config &config);
+
+protected:
+ virtual void machine_start() override ATTR_COLD;
+
+private:
+ // devices/pointers
+ required_device<cpu_device> m_maincpu;
+ required_device<pwm_display_device> m_display;
+ required_device<sensorboard_device> m_board;
+ required_device<via6522_device> m_via;
+ memory_share_creator<u8> m_extram;
+ required_device<dac_1bit_device> m_dac;
+ optional_device<generic_slot_device> m_cart;
+ required_ioport_array<2> m_inputs;
+
+ u16 m_inp_mux = 0;
+ u16 m_led_select = 0;
+ u8 m_led_group = 0;
+ u8 m_led_latch = 0;
+ u16 m_led_data = 0;
+
+ bool m_altboard = false;
+
+ void main_map(address_map &map) ATTR_COLD;
+ void v2_map(address_map &map) ATTR_COLD;
+
+ void init_board(u8 data);
+ DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load);
+
+ void update_display();
+ void leds_w(u8 data);
+ void control_w(u8 data);
+ u8 input_r();
+};
+
+void arb_state::machine_start()
+{
+ // register for savestates
+ save_item(NAME(m_inp_mux));
+ save_item(NAME(m_led_select));
+ save_item(NAME(m_led_group));
+ save_item(NAME(m_led_latch));
+ save_item(NAME(m_led_data));
+}
+
+void arb_state::update_reset()
+{
+ bool state = m_inputs[1]->read() == 3;
+
+ // RESET goes to 6502+6522
+ m_maincpu->set_input_line(INPUT_LINE_RESET, state ? ASSERT_LINE : CLEAR_LINE);
+ if (state)
+ m_via->reset();
+}
+
+
+
+/*******************************************************************************
+ I/O
+*******************************************************************************/
+
+// sensorboard
+
+void arb_state::init_board(u8 data)
+{
+ // different board setup for checkers
+ if (m_altboard)
+ {
+ for (int i = 0; i < 12; i++)
+ {
+ m_board->write_piece((i % 4) * 2 + ((i / 4) & 1), i / 4, 13); // white
+ m_board->write_piece((i % 4) * 2 + (~(i / 4) & 1), i / 4 + 5, 14); // black
+ }
+ }
+ else
+ m_board->preset_chess(data);
+}
+
+
+// cartridge
+
+DEVICE_IMAGE_LOAD_MEMBER(arb_state::cart_load)
+{
+ u32 size = m_cart->common_get_size("rom");
+ m_cart->rom_alloc(size, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
+ m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom");
+
+ // extra ram (optional)
+ if (image.get_feature("ram"))
+ m_maincpu->space(AS_PROGRAM).install_ram(0x0800, 0x0fff, 0x1000, m_extram);
+
+ m_altboard = bool(image.get_feature("altboard"));
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+
+// R6522 ports
+
+void arb_state::update_display()
+{
+ // 12 led column data lines via 3 7475
+ u16 mask = 0;
+ mask |= (m_led_group & 1) ? 0xf00 : 0;
+ mask |= (m_led_group & 2) ? 0x0ff : 0;
+
+ m_led_data = (m_led_data & ~mask) | ((m_led_latch << 8 | m_led_latch) & mask);
+ m_display->matrix(m_led_select | 0x200, m_led_data);
+}
+
+void arb_state::leds_w(u8 data)
+{
+ // PA0-PA7: led latch input
+ m_led_latch = ~data & 0xff;
+ update_display();
+}
+
+void arb_state::control_w(u8 data)
+{
+ // PB0-PB3: 74145 A-D
+ // 74145 0-8: input mux, led row select
+ m_inp_mux = data & 0xf;
+ m_led_select = 1 << (data & 0xf) & 0x1ff;
+
+ // PB4,PB5: led group select
+ m_led_group = data >> 4 & 3;
+ update_display();
+
+ // PB7: speaker out
+ m_dac->write(BIT(data, 7));
+}
+
+u8 arb_state::input_r()
+{
+ u8 data = 0;
+
+ // PA0-PA7: multiplexed inputs
+ if (m_inp_mux < 8)
+ data = m_board->read_file(m_inp_mux);
+ else if (m_inp_mux < 9)
+ data = m_inputs[m_inp_mux - 8]->read();
+
+ return ~data;
+}
+
+
+
+/*******************************************************************************
+ Address Maps
+*******************************************************************************/
+
+void arb_state::main_map(address_map &map)
+{
+ // external slot is A0-A14, potential bus conflict with RAM/VIA
+ map(0x0000, 0x7fff).mirror(0x8000).r(m_cart, FUNC(generic_slot_device::read_rom));
+ map(0x0000, 0x07ff).mirror(0x1000).ram().share("nvram");
+ map(0x8000, 0x800f).mirror(0x1ff0).m(m_via, FUNC(via6522_device::map));
+}
+
+void arb_state::v2_map(address_map &map)
+{
+ map(0x0000, 0x7fff).ram().share("nvram"); // BS62LV256
+ map(0x8000, 0x800f).mirror(0x1ff0).m(m_via, FUNC(via6522_device::map));
+ map(0xa000, 0xffff).rom();
+}
+
+
+
+/*******************************************************************************
+ Input Ports
+*******************************************************************************/
+
+static INPUT_PORTS_START( arb )
+ PORT_START("IN.0")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_H) PORT_CODE(KEYCODE_7) PORT_NAME("Hint / Black")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_V) PORT_CODE(KEYCODE_6) PORT_NAME("Variable / Clear / White / 6")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_M) PORT_CODE(KEYCODE_5) PORT_NAME("Monitor / Take Back / King / 5")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_S) PORT_CODE(KEYCODE_4) PORT_NAME("Self Play / Verify / Queen / 4")
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_B) PORT_CODE(KEYCODE_3) PORT_NAME("Change Board / Rook / 3")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_C) PORT_CODE(KEYCODE_2) PORT_NAME("Change Color / Bishop / 2")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_L) PORT_CODE(KEYCODE_1) PORT_NAME("Change Level / Knight / 1")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_N) PORT_CODE(KEYCODE_0) PORT_NAME("New Game / Options / Pawn / 0")
+
+ PORT_START("IN.1")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_R) PORT_CODE(KEYCODE_F1) PORT_NAME("Reset") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(arb_state::reset_button), 0)
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_T) PORT_CODE(KEYCODE_F1) PORT_NAME("Halt") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(arb_state::halt_button), 0)
+INPUT_PORTS_END
+
+
+
+/*******************************************************************************
+ Machine Configs
+*******************************************************************************/
+
+void arb_state::v2(machine_config &config)
+{
+ // basic machine hardware
+ W65C02S(config, m_maincpu, 16_MHz_XTAL); // W65C02S6TPG-14
+ m_maincpu->set_addrmap(AS_PROGRAM, &arb_state::v2_map);
+
+ W65C22S(config, m_via, 16_MHz_XTAL); // W65C22S6TPG-14
+ m_via->writepa_handler().set(FUNC(arb_state::leds_w));
+ m_via->writepb_handler().set(FUNC(arb_state::control_w));
+ m_via->readpa_handler().set(FUNC(arb_state::input_r));
+ m_via->irq_handler().set_inputline(m_maincpu, M6502_IRQ_LINE);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ SENSORBOARD(config, m_board).set_type(sensorboard_device::MAGNETS);
+ m_board->init_cb().set(FUNC(arb_state::init_board));
+ m_board->set_spawnpoints(12+2); // +2 checkers pieces
+ m_board->set_delay(attotime::from_msec(100));
+
+ // video hardware
+ PWM_DISPLAY(config, m_display).set_size(9+1, 12);
+ config.set_default_layout(layout_ave_arb);
+
+ // sound hardware
+ SPEAKER(config, "speaker").front_center();
+ DAC_1BIT(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25);
+}
+
+void arb_state::arb(machine_config &config)
+{
+ v2(config);
+
+ // basic machine hardware
+ M6502(config.replace(), m_maincpu, 4_MHz_XTAL/2); // R6502P
+ m_maincpu->set_addrmap(AS_PROGRAM, &arb_state::main_map);
+
+ MOS6522(config.replace(), m_via, 4_MHz_XTAL/4); // R6522P
+ m_via->writepa_handler().set(FUNC(arb_state::leds_w));
+ m_via->writepb_handler().set(FUNC(arb_state::control_w));
+ m_via->readpa_handler().set(FUNC(arb_state::input_r));
+ m_via->irq_handler().set_inputline(m_maincpu, M6502_IRQ_LINE);
+
+ // cartridge
+ GENERIC_CARTSLOT(config, m_cart, generic_linear_slot, "arb");
+ m_cart->set_device_load(FUNC(arb_state::cart_load));
+ m_cart->set_must_be_loaded(true);
+
+ SOFTWARE_LIST(config, "cart_list").set_original("arb");
+}
+
+
+
+/*******************************************************************************
+ ROM Definitions
+*******************************************************************************/
+
+ROM_START( arb )
+ ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 )
+ // none here, it's in the module slot
+ROM_END
+
+ROM_START( arbv2 )
+ ROM_REGION( 0x10000, "maincpu", 0 )
+ ROM_LOAD( "sargon_4.0", 0x0000, 0x10000, CRC(c519c9e8) SHA1(d7597d50c0f4f9aa6d990c8d3b485e39cb44ff06) ) // AT27C512R
+ROM_END
+
+} // anonymous namespace
+
+
+
+/*******************************************************************************
+ Drivers
+*******************************************************************************/
+
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
+SYST( 1980, arb, 0, 0, arb, arb, arb_state, empty_init, "AVE Micro Systems", "Auto Response Board", MACHINE_SUPPORTS_SAVE )
+SYST( 2012, arbv2, arb, 0, v2, arb, arb_state, empty_init, "hack (Steve Braid)", "ARB V2 Sargon 4.0", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/chess/compuchess.cpp b/src/mame/chess/compuchess.cpp
new file mode 100644
index 00000000000..882924eaf5c
--- /dev/null
+++ b/src/mame/chess/compuchess.cpp
@@ -0,0 +1,510 @@
+// license:BSD-3-Clause
+// copyright-holders:Peter Trauner, Wilbert Pol, hap
+// thanks-to:Sean Riddle, Berger
+/*******************************************************************************
+
+DCS CompuChess / Novag Chess Champion MK I
+Initial driver version by PeT mess@utanet.at 2000,2001.
+Driver largely rewritten over the years.
+
+To start playing, enter difficulty level (1-6), then when it says "bP", press A
+for new game, B for empty board, or C for continue.
+
+TODO:
+- cncchess sound is wrong, it should be a long dual-tone alarm sound
+
+BTANB:
+- cmpchess/cmpchess2 accepts illegal moves (Conic fixed that)
+- digits may flash briefly after entering a command, eg. the "b" or "P" digit
+ after setting board preset, this happens on the real device
+
+================================================================================
+
+DataCash Systems's CompuChess released mid-1977. One of the first chess
+computers, the first one being Fidelity Chess Challenger (fidelity/cc1.cpp)
+
+Hardware notes:
+- PCB label: CompuChess 1, STAID INC, REV A, 7-77
+- Fairchild 3850PK, 2MHz XTAL
+- Fairchild 3853PK
+- 2KB ROM, 256 bytes RAM(2*D2101AL-4)
+- 4-digit 7seg led display, no sound
+
+CompuChess 2nd edition is on the same PCB, but with a 3.57MHz XTAL(!), a 3850PC,
+and Mostek MK3853N. The MCU speed was also confirmed with move calculation time.
+
+2nd edition added 3 new game modes: E for "Game of Knights", F for "Amazon Queen",
+and G for "Survival".
+
+================================================================================
+
+The game underneath CompuChess is better known as Novag's MK I, it was an
+unlicensed clone. The ROM is identical. DCS sued JS&A / Novag Industries for
+copyright infringement and somehow didn't manage to win the case.
+see: https://law.justia.com/cases/federal/district-courts/FSupp/480/1063/1531498/
+
+Unlike CompuChess, MK I was a large success, we can assume that it kickstarted
+Novag's chess computer generation. It was also distributed as "Computer Chess"
+by JS&A, in the same housing as MK I.
+
+MCU frequency is with an LC circuit. The first version was around 5% faster than
+CompuChess, the JS&A version was measured 2.18MHz on average. The 2nd version was
+much faster, judging from move calculation time: around 3.5MHz(give or take 0.2).
+
+1st (slow) version:
+- Novag MK I with Boris Spassky photo on the box
+- JS&A Computer Chess
+
+2nd (fast) version:
+- Novag MK I with Karpov photo on the box, later advertised with message
+ "Neu: Mit Quick-Electronic für Schnelle Gegenzüge"
+- Waddingtons Videomaster Chess Champion
+
+MK I hardware description:
+- An F8 3850 CPU accompanied by a 3853 memory interface
+ Variations seen:
+ - MOSTEK MK 3853N 7915 Philippines (static memory interface for F8)
+ - MOSTEK MK 3850N-3 7917 Philipines (Fairchild F8 CPU)
+ - 3850PK F7901 SINGAPORE (Fairchild F8 CPU)
+ - 3853PK F7851 SINGAPORE (static memory interface for F8)
+- 2KB 2316 compatible ROM
+ Variations seen:
+ - Signetics 7916E C48091 82S210-1 COPYRIGHT
+ - RO-3-8316A 8316A-4480 7904 TAIWAN
+- 2 x 2111 256x4 SRAM to provide 256 bytes of RAM
+ Variations seen:
+ - AM9111 BPC / P2111A-4 7851
+- 16 keys placed in a 4 x 4 matrix
+- Power on switch
+- L/S switch. This switch is directly tied to the RESET pin of the F8 CPU.
+ This allows the user to reset the CPU without destroying the RAM contents.
+- A 4 character 11 segment digit display using a 15 pin interface. Of the 15
+ pins 3 pins are not connected, so three segments are never used and this
+ leaves a standard 7 segments display with a dot in the lower right.
+- The digit display is driven by two other components:
+ - SN75492N MALAYSIA 7840B
+ - ULN2033A 7847
+- Hardware addressing is controlled by a HBF4001AE.
+- No speaker.
+
+================================================================================
+
+Conic Computer Chess (aka Master I in Germany) is also based on DCS CompuChess,
+this time the 2nd edition. Conic have done a few changes, not enough to hide that
+they 'borrowed' code. They also added a piezo circuit.
+
+Hardware notes:
+- Fairchild 3850PK CPU @ 2MHz (LC circuit), 3853PK
+- 2KB ROM (3216), 256 bytes RAM (2*2111A)
+- discrete sound
+
+"bP" buttons are F, G, H (instead of A, B, C)
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "cpu/f8/f8.h"
+#include "machine/f3853.h"
+#include "machine/timer.h"
+#include "sound/beep.h"
+#include "video/pwm.h"
+#include "speaker.h"
+
+// internal artwork
+#include "cmpchess.lh"
+#include "novag_mk1.lh"
+#include "conic_cchess.lh"
+
+
+namespace {
+
+class cmpchess_state : public driver_device
+{
+public:
+ cmpchess_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_display(*this, "display"),
+ m_beeper_off(*this, "beeper_off"),
+ m_beeper(*this, "beeper"),
+ m_inputs(*this, "IN.%u", 0)
+ { }
+
+ DECLARE_INPUT_CHANGED_MEMBER(reset_switch) { update_reset(newval); }
+ DECLARE_INPUT_CHANGED_MEMBER(change_cpu_freq);
+
+ // machine configs
+ void cmpchess(machine_config &config);
+ void cmpchess2(machine_config &config);
+ void mk1(machine_config &config);
+ void cncchess(machine_config &config);
+
+protected:
+ virtual void machine_start() override ATTR_COLD;
+ virtual void machine_reset() override ATTR_COLD;
+
+private:
+ // devices/pointers
+ required_device<cpu_device> m_maincpu;
+ required_device<pwm_display_device> m_display;
+ optional_device<timer_device> m_beeper_off;
+ optional_device<beep_device> m_beeper;
+ required_ioport_array<4> m_inputs;
+
+ u8 m_inp_mux = 0;
+ u8 m_digit_select = 0;
+ u8 m_digit_data = 0;
+ bool m_blink = false;
+
+ // address maps
+ void main_map(address_map &map) ATTR_COLD;
+ void main_io(address_map &map) ATTR_COLD;
+ void cncchess_map(address_map &map) ATTR_COLD;
+ void cncchess_io(address_map &map) ATTR_COLD;
+
+ TIMER_DEVICE_CALLBACK_MEMBER(beeper_off) { m_beeper->set_state(0); }
+ TIMER_DEVICE_CALLBACK_MEMBER(blink) { m_blink = !m_blink; update_display(); }
+ void update_display();
+ void update_reset(ioport_value state);
+
+ // I/O handlers
+ void input_w(u8 data);
+ u8 input_r();
+ void digit_select_w(u8 data);
+ void digit_data_w(u8 data);
+ u8 digit_data_r();
+ u8 beeper_r(offs_t offset);
+
+ void input_digit_select_w(u8 data) { input_w(data); digit_select_w(data); }
+ void input_digit_data_w(u8 data) { input_w(data); digit_data_w(data); }
+};
+
+
+
+/*******************************************************************************
+ Initialization
+*******************************************************************************/
+
+void cmpchess_state::machine_start()
+{
+ // register for savestates
+ save_item(NAME(m_inp_mux));
+ save_item(NAME(m_digit_select));
+ save_item(NAME(m_digit_data));
+ save_item(NAME(m_blink));
+}
+
+void cmpchess_state::machine_reset()
+{
+ update_reset(ioport("RESET")->read());
+}
+
+void cmpchess_state::update_reset(ioport_value state)
+{
+ // reset switch is tied to F3850 RESET pin
+ m_maincpu->set_input_line(INPUT_LINE_RESET, state ? ASSERT_LINE : CLEAR_LINE);
+
+ // clear display
+ if (state)
+ m_display->clear();
+}
+
+INPUT_CHANGED_MEMBER(cmpchess_state::change_cpu_freq)
+{
+ // 2 MK I versions, 2nd one was a lot faster
+ const u32 freq = (newval & 1) ? 3'500'000 : 2'250'000;
+ m_maincpu->set_unscaled_clock(freq);
+ subdevice<f3853_device>("smi")->set_unscaled_clock(freq);
+}
+
+
+
+/*******************************************************************************
+ I/O
+*******************************************************************************/
+
+void cmpchess_state::update_display()
+{
+ // display panel goes into automated blink mode if DP segment is held high,
+ // and DP segment itself by default only appears to be active if no other segments are
+ u8 dmask = (m_digit_data == 1) ? 0x80 : 0x7f;
+ u8 bmask = (m_blink && m_digit_data & 1) ? 0 : 0xff;
+ u8 bstate = m_digit_data & bmask & 1; // DP state for ignoring dmask
+
+ u8 digit_data = bitswap<8>(m_digit_data,0,2,1,3,4,5,6,7) & dmask & bmask;
+ m_display->matrix(m_digit_select, bstate << 8 | digit_data);
+}
+
+void cmpchess_state::digit_data_w(u8 data)
+{
+ // digit segment data
+ m_digit_data = data;
+ update_display();
+}
+
+u8 cmpchess_state::digit_data_r()
+{
+ return m_digit_data;
+}
+
+void cmpchess_state::digit_select_w(u8 data)
+{
+ // d0-d3: digit select (active low)
+ m_digit_select = ~data & 0xf;
+ update_display();
+}
+
+void cmpchess_state::input_w(u8 data)
+{
+ // input matrix is shared with either digit_data_w, or digit_select_w
+ m_inp_mux = data;
+}
+
+u8 cmpchess_state::input_r()
+{
+ u8 data = m_inp_mux;
+
+ // d0-d3: multiplexed inputs from d4-d7
+ for (int i = 0; i < 4; i++)
+ if (m_inp_mux & m_inputs[i]->read() << 4)
+ data |= 1 << i;
+
+ // d4-d7: multiplexed inputs from d0-d3
+ for (int i = 0; i < 4; i++)
+ if (BIT(m_inp_mux, i))
+ data |= m_inputs[i]->read() << 4;
+
+ return data;
+}
+
+u8 cmpchess_state::beeper_r(offs_t offset)
+{
+ // cncchess: trigger beeper
+ if (!machine().side_effects_disabled())
+ {
+ m_beeper->set_state(1);
+ m_beeper_off->adjust(attotime::from_msec(50)); // wrong, see TODO
+ }
+
+ return m_maincpu->space(AS_PROGRAM).read_byte(offset);
+}
+
+
+
+/*******************************************************************************
+ Address Maps
+*******************************************************************************/
+
+void cmpchess_state::main_map(address_map &map)
+{
+ map.global_mask(0x0fff);
+ map(0x0000, 0x07ff).rom();
+ map(0x0800, 0x08ff).mirror(0x0700).ram();
+}
+
+void cmpchess_state::main_io(address_map &map)
+{
+ map(0x00, 0x00).rw(FUNC(cmpchess_state::input_r), FUNC(cmpchess_state::input_digit_data_w));
+ map(0x01, 0x01).w(FUNC(cmpchess_state::digit_select_w));
+ map(0x0c, 0x0f).rw("smi", FUNC(f3853_device::read), FUNC(f3853_device::write));
+}
+
+void cmpchess_state::cncchess_map(address_map &map)
+{
+ map(0x0000, 0x07ff).rom();
+ map(0x1800, 0x18ff).ram();
+ map(0x8000, 0xffff).r(FUNC(cmpchess_state::beeper_r));
+}
+
+void cmpchess_state::cncchess_io(address_map &map)
+{
+ map(0x00, 0x00).rw(FUNC(cmpchess_state::digit_data_r), FUNC(cmpchess_state::digit_data_w));
+ map(0x01, 0x01).rw(FUNC(cmpchess_state::input_r), FUNC(cmpchess_state::input_digit_select_w));
+ map(0x0c, 0x0f).rw("smi", FUNC(f3853_device::read), FUNC(f3853_device::write));
+}
+
+
+
+/*******************************************************************************
+ Input Ports
+*******************************************************************************/
+
+static INPUT_PORTS_START( cmpchess )
+ PORT_START("IN.0")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_D) PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("D / Play")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_C) PORT_NAME("C / White Bishop")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_B) PORT_NAME("B / White Queen")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_A) PORT_NAME("A / White King")
+
+ PORT_START("IN.1")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_H) PORT_CODE(KEYCODE_M) PORT_NAME("H / md") // more data
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_G) PORT_NAME("G / White Pawn")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_F) PORT_NAME("F / White Rook")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_E) PORT_NAME("E / White Knight")
+
+ PORT_START("IN.2")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("4 / fp") // find piece(position)
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("3 / Black Bishop")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("2 / Black Queen")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("1 / Black King")
+
+ PORT_START("IN.3")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("8 / ep") // enter piece(position)
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("7 / Black Pawn")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("6 / Black Rook")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("5 / Black Knight")
+
+ PORT_START("RESET")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_CODE(KEYCODE_F1) PORT_TOGGLE PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(cmpchess_state::reset_switch), 0) PORT_NAME("Reset Switch")
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( mk1 )
+ PORT_INCLUDE( cmpchess )
+
+ PORT_MODIFY("RESET")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_CODE(KEYCODE_F1) PORT_TOGGLE PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(cmpchess_state::reset_switch), 0) PORT_NAME("L.S. Switch")
+
+ PORT_START("CPU")
+ PORT_CONFNAME( 0x01, 0x00, "CPU Frequency" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(cmpchess_state::change_cpu_freq), 0) // factory set
+ PORT_CONFSETTING( 0x00, "2.25MHz (Spassky packaging)" )
+ PORT_CONFSETTING( 0x01, "3.5MHz (Karpov packaging)" )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( cncchess )
+ PORT_START("IN.0")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("4 / Black Bishop")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("3 / Black Knight")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("2 / Black Rook")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("1 / Black Pawn")
+
+ PORT_START("IN.1")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_CODE(KEYCODE_I) PORT_NAME("8 / IP") // insert piece (same as ep)
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_CODE(KEYCODE_S) PORT_NAME("7 / SP") // search piece (same as fp)
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("6 / Black King")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("5 / Black Queen")
+
+ PORT_START("IN.2")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_D) PORT_NAME("D / White Bishop")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_C) PORT_NAME("C / White Knight")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_B) PORT_NAME("B / White Rook")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_A) PORT_NAME("A / White Pawn")
+
+ PORT_START("IN.3")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_H) PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("H / GO")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_G) PORT_CODE(KEYCODE_M) PORT_NAME("G / MD") // more data
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_F) PORT_NAME("F / White King")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_E) PORT_NAME("E / White Queen")
+
+ PORT_START("RESET")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_F1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(cmpchess_state::reset_switch), 0) PORT_NAME("Reset")
+INPUT_PORTS_END
+
+
+
+/*******************************************************************************
+ Machine Configs
+*******************************************************************************/
+
+void cmpchess_state::cmpchess(machine_config &config)
+{
+ // basic machine hardware
+ F8(config, m_maincpu, 2_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &cmpchess_state::main_map);
+ m_maincpu->set_addrmap(AS_IO, &cmpchess_state::main_io);
+ m_maincpu->set_irq_acknowledge_callback("smi", FUNC(f3853_device::int_acknowledge));
+
+ f3853_device &smi(F3853(config, "smi", 2_MHz_XTAL));
+ smi.int_req_callback().set_inputline("maincpu", F8_INPUT_LINE_INT_REQ);
+
+ // video hardware
+ PWM_DISPLAY(config, m_display).set_size(4, 8+1);
+ m_display->set_segmask(0xf, 0xff);
+ config.set_default_layout(layout_cmpchess);
+
+ const attotime blink_period = attotime::from_msec(200); // approximation
+ TIMER(config, "blink_display").configure_periodic(FUNC(cmpchess_state::blink), blink_period);
+}
+
+void cmpchess_state::cmpchess2(machine_config &config)
+{
+ cmpchess(config);
+
+ // basic machine hardware
+ m_maincpu->set_clock(3.579545_MHz_XTAL);
+ subdevice<f3853_device>("smi")->set_clock(3.579545_MHz_XTAL);
+}
+
+void cmpchess_state::mk1(machine_config &config)
+{
+ cmpchess(config);
+
+ // basic machine hardware
+ m_maincpu->set_clock(2'250'000); // see notes
+ subdevice<f3853_device>("smi")->set_clock(2'250'000);
+
+ config.set_default_layout(layout_novag_mk1);
+}
+
+void cmpchess_state::cncchess(machine_config &config)
+{
+ cmpchess2(config);
+
+ // basic machine hardware
+ m_maincpu->set_clock(2'000'000); // LC circuit, measured 2MHz
+ m_maincpu->set_addrmap(AS_PROGRAM, &cmpchess_state::cncchess_map);
+ m_maincpu->set_addrmap(AS_IO, &cmpchess_state::cncchess_io);
+
+ subdevice<f3853_device>("smi")->set_clock(2'000'000);
+
+ config.set_default_layout(layout_conic_cchess);
+
+ // sound hardware
+ SPEAKER(config, "speaker").front_center();
+ BEEP(config, m_beeper, 2000); // wrong, see TODO
+ m_beeper->add_route(ALL_OUTPUTS, "speaker", 0.25);
+ TIMER(config, "beeper_off").configure_generic(FUNC(cmpchess_state::beeper_off));
+}
+
+
+
+/*******************************************************************************
+ ROM Definitions
+*******************************************************************************/
+
+ROM_START( cmpchess )
+ ROM_REGION( 0x0800, "maincpu", 0 )
+ ROM_LOAD("32014-4950_cmcsi_staid.u3", 0x0000, 0x0800, CRC(278f7bf3) SHA1(b384c95ba691d52dfdddd35987a71e9746a46170) )
+ROM_END
+
+ROM_START( cmpchess2 )
+ ROM_REGION( 0x0800, "maincpu", 0 )
+ ROM_LOAD("8316a-4952_cmc2_staid.u3", 0x0000, 0x0800, CRC(aee49c5f) SHA1(8a10f74207f2646164cc0deed81bd082143ac38a) )
+ROM_END
+
+
+ROM_START( ccmk1 )
+ ROM_REGION( 0x0800, "maincpu", 0 )
+ ROM_LOAD("82c210-1", 0x0000, 0x0800, CRC(278f7bf3) SHA1(b384c95ba691d52dfdddd35987a71e9746a46170) )
+ROM_END
+
+
+ROM_START( cncchess )
+ ROM_REGION( 0x0800, "maincpu", 0 )
+ ROM_LOAD("c48170.u1", 0x0000, 0x0800, CRC(5beace32) SHA1(9df924037614831a86b73eb3a16bbc80c63257a2) ) // 2316B
+ROM_END
+
+} // anonymous namespace
+
+
+
+/*******************************************************************************
+ Drivers
+*******************************************************************************/
+
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
+SYST( 1977, cmpchess, 0, 0, cmpchess, cmpchess, cmpchess_state, empty_init, "DataCash Systems / Staid", "CompuChess", MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE ) // aka CompuChess I
+SYST( 1978, cmpchess2, 0, 0, cmpchess2, cmpchess, cmpchess_state, empty_init, "DataCash Systems / Staid", "CompuChess: The Second Edition", MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE )
+
+SYST( 1978, ccmk1, cmpchess, 0, mk1, mk1, cmpchess_state, empty_init, "bootleg (Novag Industries)", "Chess Champion: MK I", MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE )
+
+SYST( 1979, cncchess, 0, 0, cncchess, cncchess, cmpchess_state, empty_init, "Conic", "Computer Chess (Conic, model 7011)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/chess/conchess.cpp b/src/mame/chess/conchess.cpp
new file mode 100644
index 00000000000..05f858a33ca
--- /dev/null
+++ b/src/mame/chess/conchess.cpp
@@ -0,0 +1,389 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+// thanks-to:Berger, Mr. Lars
+/*******************************************************************************
+
+Conchess, a series of modular chess computers by Consumenta Computer.
+
+Hardware development by Loproc (Germany), manufactured at Wallharn Electronics
+(Ireland). The core people involved were Ulf Rathsman for the chess engine,
+and Johan Enroth. After Consumenta went under in 1983, the Conchess brand was
+continued by Systemhuset.
+
+TODO:
+- concglap/concglapa rom labels
+- dump/add concvicp library module (L/L16 don't work, manual says it has its own add-on)
+- concvicp unmapped reads/writes
+- verify irq/beeper for concvicp, though it is probably correct
+
+================================================================================
+
+Hardware notes:
+
+Chess boards released were Escorter, Ambassador, and Monarch, each should be the
+same hardware, they just differ in size and material.
+- TTL, 2 module slots
+- 16+64 leds, 16 buttons, reed sensors for magnet chesspieces
+
+All chess modules appear to be on similar PCBs, with room a 6502/65C02,
+and 8 ROM/RAM chips.
+
+For the newer programs, higher clocked versions were also available, the CPU speed
+was labeled on a sticker on the module (eg. A2/5.5MHz). A German redistributor
+named them "S"(speed) or "T"(top speed).
+
+A0 (untitled standard pack-in module):
+- SY6502A @ 2MHz (4MHz XTAL)
+- 3*8KB ROM, 4KB RAM(2*TMM2016P)
+- TTL, beeper
+
+note: XTAL goes to 4020, 4020 /2 goes to CPU clock, and other dividers to
+IRQ and beeper. On A0, IRQ is active for ~31.2us.
+
+A1(P) + A0(M) (Princhess, aka Glasgow)
+- dual-module, 2nd module has no CPU (according to the manual, A0 is modified and
+ won't work stand-alone)
+- dual-module Amsterdam version also exists
+
+A2(C) (Plymate, aka Amsterdam)
+- R65C02P4 @ 5.5MHz (11MHz XTAL) (5.5MHz version)
+- 32KB ROM, rest similar to A0
+
+A3 (Plymate Victoria)
+- W65C02S8P-14(14? probably replaced chip from a repair) @ 6.144MHz (12.288MHz XTAL)
+- 32KB ROM, rest similar to A0
+
+Library modules:
+- L: small PCB, PCB label: CCL L-2, 8KB EPROM no label
+- L16: 2*8KB EPROM (have no photo of PCB)
+
+There are also modern bootleg boards from SteveUK in circulation. The library ROM
+is integrated.
+
+*******************************************************************************/
+
+#include "emu.h"
+
+#include "bus/generic/carts.h"
+#include "bus/generic/slot.h"
+#include "cpu/m6502/m6502.h"
+#include "cpu/m6502/r65c02.h"
+#include "cpu/m6502/w65c02.h"
+#include "machine/sensorboard.h"
+#include "sound/beep.h"
+#include "video/pwm.h"
+
+#include "softlist_dev.h"
+#include "speaker.h"
+
+// internal artwork
+#include "conchess.lh"
+
+
+namespace {
+
+class conchess_state : public driver_device
+{
+public:
+ conchess_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_display(*this, "display"),
+ m_board(*this, "board"),
+ m_beeper(*this, "beeper"),
+ m_inputs(*this, "IN.%u", 0)
+ { }
+
+ // machine configs
+ void conc(machine_config &config);
+ void concgla(machine_config &config);
+ void concams(machine_config &config);
+ void concams5(machine_config &config);
+ void concvicp(machine_config &config);
+
+protected:
+ virtual void machine_start() override ATTR_COLD;
+
+private:
+ // devices/pointers
+ required_device<cpu_device> m_maincpu;
+ required_device<pwm_display_device> m_display;
+ required_device<sensorboard_device> m_board;
+ required_device<beep_device> m_beeper;
+ required_ioport_array<2> m_inputs;
+
+ u8 m_inp_mux = 0;
+
+ // address maps
+ void main_map(address_map &map) ATTR_COLD;
+
+ // I/O handlers
+ void clear_irq();
+ u8 input_r();
+ void leds_w(offs_t offset, u8 data);
+ void sound_w(u8 data);
+};
+
+void conchess_state::machine_start()
+{
+ save_item(NAME(m_inp_mux));
+}
+
+
+
+/*******************************************************************************
+ I/O
+*******************************************************************************/
+
+void conchess_state::clear_irq()
+{
+ m_maincpu->set_input_line(0, CLEAR_LINE);
+}
+
+u8 conchess_state::input_r()
+{
+ if (!machine().side_effects_disabled())
+ clear_irq();
+
+ u8 data = 0;
+
+ // read side panel buttons
+ if (m_inp_mux == 0 || m_inp_mux == 9)
+ data = m_inputs[m_inp_mux & 1]->read();
+
+ // read chessboard sensors
+ else
+ data = m_board->read_file((m_inp_mux - 1) ^ 7);
+
+ return ~data;
+}
+
+void conchess_state::leds_w(offs_t offset, u8 data)
+{
+ clear_irq();
+
+ // a0-a3: CD4028B to led select/input mux
+ m_inp_mux = offset;
+ if (m_inp_mux & 8)
+ m_inp_mux &= 9;
+
+ // d0-d7: led data
+ m_display->matrix(1 << m_inp_mux, data);
+}
+
+void conchess_state::sound_w(u8 data)
+{
+ // d7: enable beeper
+ m_beeper->set_state(BIT(data, 7));
+}
+
+
+
+/*******************************************************************************
+ Address Maps
+*******************************************************************************/
+
+void conchess_state::main_map(address_map &map)
+{
+ map(0x0000, 0x0fff).ram();
+ map(0x1000, 0x1000).mirror(0x07ff).r(FUNC(conchess_state::input_r));
+ map(0x1000, 0x100f).mirror(0x07f0).w(FUNC(conchess_state::leds_w));
+ map(0x1800, 0x1800).mirror(0x07ff).w(FUNC(conchess_state::sound_w));
+ map(0x4000, 0x7fff).r("cartslot", FUNC(generic_slot_device::read_rom));
+ map(0x8000, 0xffff).rom();
+}
+
+
+
+/*******************************************************************************
+ Input Ports
+*******************************************************************************/
+
+static INPUT_PORTS_START( conchess )
+ PORT_START("IN.0")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Q) PORT_NAME("O. (Clear)")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_W) PORT_NAME("Stop")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_E) PORT_NAME("Dice Symbol (Alternate)")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_R) PORT_NAME("?-Sign (Analyze)")
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_T) PORT_NAME("Section Sign (Referee)")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Y) PORT_NAME("4-Way Arrow (Piece)")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_U) PORT_NAME("2-Way Arrow (Level)")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_I) PORT_NAME(". (Continue)")
+
+ PORT_START("IN.1")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("Pawn")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("Knight")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("Bishop")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("Rook")
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("Queen")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("King")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("White")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("Black")
+INPUT_PORTS_END
+
+
+
+/*******************************************************************************
+ Machine Configs
+*******************************************************************************/
+
+void conchess_state::conc(machine_config &config)
+{
+ // basic machine hardware
+ M6502(config, m_maincpu, 4_MHz_XTAL/2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &conchess_state::main_map);
+
+ const attotime irq_period = attotime::from_hz(4_MHz_XTAL / 0x2000);
+ m_maincpu->set_periodic_int(FUNC(conchess_state::irq0_line_assert), irq_period);
+
+ SENSORBOARD(config, m_board).set_type(sensorboard_device::MAGNETS);
+ m_board->init_cb().set(m_board, FUNC(sensorboard_device::preset_chess));
+ m_board->set_delay(attotime::from_msec(150));
+
+ GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "conchess_cart");
+ SOFTWARE_LIST(config, "cart_list").set_original("conchess").set_filter("l");
+
+ // video hardware
+ PWM_DISPLAY(config, m_display).set_size(10, 8);
+ config.set_default_layout(layout_conchess);
+
+ // sound hardware
+ SPEAKER(config, "mono").front_center();
+ BEEP(config, m_beeper, 4_MHz_XTAL / 0x400);
+ m_beeper->add_route(ALL_OUTPUTS, "mono", 0.25);
+}
+
+void conchess_state::concgla(machine_config &config)
+{
+ conc(config);
+
+ // basic machine hardware
+ R65C02(config.replace(), m_maincpu, 4_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &conchess_state::main_map);
+
+ const attotime irq_period = attotime::from_hz(4_MHz_XTAL / 0x2000);
+ m_maincpu->set_periodic_int(FUNC(conchess_state::irq0_line_assert), irq_period);
+
+ subdevice<software_list_device>("cart_list")->set_filter("none");
+
+ // sound hardware
+ BEEP(config.replace(), m_beeper, 4_MHz_XTAL / 0x400);
+ m_beeper->add_route(ALL_OUTPUTS, "mono", 0.25);
+}
+
+void conchess_state::concams(machine_config &config)
+{
+ concgla(config);
+
+ // basic machine hardware
+ subdevice<software_list_device>("cart_list")->set_filter("l16");
+}
+
+void conchess_state::concams5(machine_config &config)
+{
+ concams(config);
+
+ // basic machine hardware
+ m_maincpu->set_clock(11_MHz_XTAL/2);
+
+ const attotime irq_period = attotime::from_hz(11_MHz_XTAL / 0x4000);
+ m_maincpu->set_periodic_int(FUNC(conchess_state::irq0_line_assert), irq_period);
+
+ // sound hardware
+ BEEP(config.replace(), m_beeper, 11_MHz_XTAL / 0x800);
+ m_beeper->add_route(ALL_OUTPUTS, "mono", 0.25);
+}
+
+void conchess_state::concvicp(machine_config &config)
+{
+ concams5(config);
+
+ // basic machine hardware
+ W65C02(config.replace(), m_maincpu, 12.288_MHz_XTAL/2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &conchess_state::main_map);
+
+ const attotime irq_period = attotime::from_hz(12.288_MHz_XTAL / 0x4000);
+ m_maincpu->set_periodic_int(FUNC(conchess_state::irq0_line_assert), irq_period);
+
+ subdevice<software_list_device>("cart_list")->set_filter("l1024");
+
+ // sound hardware
+ BEEP(config.replace(), m_beeper, 12.288_MHz_XTAL / 0x1000);
+ m_beeper->add_route(ALL_OUTPUTS, "mono", 0.25);
+}
+
+
+
+/*******************************************************************************
+ ROM Definitions
+*******************************************************************************/
+
+ROM_START( conc ) // 2 bytes different (bookrom fix)
+ ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 )
+ ROM_LOAD("ccp2.a", 0xa000, 0x1000, CRC(fddd155b) SHA1(ccb67543f4d680b47d2956b284d5c6b7a8d21520) ) // MBM2732A-30
+ ROM_LOAD("ccp2.b", 0xb000, 0x1000, CRC(81cf6b20) SHA1(7f6e30e50c6f9b633767a04b7d7a9c291d301614) ) // "
+ ROM_LOAD("ccp2.c", 0xc000, 0x1000, CRC(151eca1a) SHA1(40b97bce2ff0cae528efa3a9bab5767d5d15d369) ) // "
+ ROM_LOAD("ccp2.d", 0xd000, 0x1000, CRC(ed5dafeb) SHA1(3f0cea45bf26d9a1d120963480fc883a00185224) ) // "
+ ROM_LOAD("ccp2.e", 0xe000, 0x1000, CRC(f07bf0e2) SHA1(e4f2f415144ed5e43f4940c7c9618e89707d19e9) ) // "
+ ROM_LOAD("ccp2.f", 0xf000, 0x1000, CRC(7a04b000) SHA1(72d702b91adc643201ac6cea7aeb9394a3afc8be) ) // "
+ROM_END
+
+ROM_START( conca ) // 6 EPROMs version also exists, same ROM contents
+ ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 )
+ ROM_LOAD("c87011_ccp2ab.b3", 0xa000, 0x2000, CRC(915e414c) SHA1(80c94712d1c79fa469576c37b80ab66f77c77cc4) ) // C2C076 serial also seen, same ROM contents
+ ROM_LOAD("c87010_ccp2cd.b2", 0xc000, 0x2000, CRC(088c8737) SHA1(9f841b3c47de9ef1da8ce98c0a33a919cba873c6) )
+ ROM_LOAD("c87009_ccp2ef.b1", 0xe000, 0x2000, CRC(e1c648e2) SHA1(725a6ac1c69f788a7bba0573e5609b55b12899ac) )
+ROM_END
+
+ROM_START( concgla ) // 8 EPROMs version also exists, same ROM contents
+ ROM_REGION( 0x10000, "maincpu", 0 )
+ ROM_LOAD("9128c-0133", 0x8000, 0x4000, CRC(a6ac88eb) SHA1(d1fcd990e5196c00210d380e0e04155a5ea19824) ) // GI 9128C
+ ROM_LOAD("9128c-0134", 0xc000, 0x4000, CRC(b694a275) SHA1(e4e49379b4eb45402ca8bb82c20d0169db62ed7a) ) // "
+ROM_END
+
+ROM_START( concglap ) // 2 bytes different
+ ROM_REGION( 0x10000, "maincpu", 0 )
+ ROM_LOAD("ccplus", 0x8000, 0x8000, CRC(c62e522b) SHA1(28ea9af35f9f4e96e52c19597d62e0af135c7672) )
+ROM_END
+
+ROM_START( concglapa )
+ ROM_REGION( 0x10000, "maincpu", 0 )
+ ROM_LOAD("ccplus", 0x8000, 0x8000, CRC(0bf4d2d0) SHA1(0ce670d3be1ae4da5467be6b062cfe73dcfbf229) )
+ROM_END
+
+ROM_START( concams )
+ ROM_REGION( 0x10000, "maincpu", 0 )
+ ROM_LOAD("8b_4.0_133", 0x8000, 0x4000, CRC(e021e3d8) SHA1(7a2c079664ed5cbaa7e5c55d4d2e8936b7be4219) ) // SEEQ DQ5143-250
+ ROM_LOAD("cf_4.0_134", 0xc000, 0x4000, CRC(fc827c7f) SHA1(51acd881c4d5fe29f2a83d35a48ba323344122db) ) // "
+ROM_END
+
+ROM_START( concams5 )
+ ROM_REGION( 0x10000, "maincpu", 0 )
+ ROM_LOAD("s5.a1", 0x8000, 0x8000, CRC(9a9d1ec1) SHA1(75dbd1f96502775ed304f6b085d958f1b07d08f9) ) // AT27C256
+ROM_END
+
+ROM_START( concvicp )
+ ROM_REGION( 0x10000, "maincpu", 0 )
+ ROM_LOAD("cc8-f.a2", 0x8000, 0x8000, CRC(5b0a1d09) SHA1(07cbc970a8dfbca386396ce5d5cc8ce77ad4ee1b) )
+ROM_END
+
+} // anonymous namespace
+
+
+
+/*******************************************************************************
+ Drivers
+*******************************************************************************/
+
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
+SYST( 1982, conc, 0, 0, conc, conchess, conchess_state, empty_init, "Consumenta Computer / Loproc", "Conchess (standard, set 1)", MACHINE_SUPPORTS_SAVE )
+SYST( 1982, conca, conc, 0, conc, conchess, conchess_state, empty_init, "Consumenta Computer / Loproc", "Conchess (standard, set 2)", MACHINE_SUPPORTS_SAVE )
+
+SYST( 1984, concgla, 0, 0, concgla, conchess, conchess_state, empty_init, "Systemhuset / Loproc", "Conchess Princhess Glasgow", MACHINE_SUPPORTS_SAVE )
+SYST( 1984, concglap, 0, 0, concgla, conchess, conchess_state, empty_init, "Systemhuset / Loproc", "Conchess Plymate Glasgow Plus (set 1)", MACHINE_SUPPORTS_SAVE )
+SYST( 1984, concglapa, concglap, 0, concgla, conchess, conchess_state, empty_init, "Systemhuset / Loproc", "Conchess Plymate Glasgow Plus (set 2)", MACHINE_SUPPORTS_SAVE )
+
+SYST( 1985, concams, 0, 0, concams, conchess, conchess_state, empty_init, "Systemhuset / Loproc", "Conchess Plymate Amsterdam", MACHINE_SUPPORTS_SAVE )
+SYST( 1985, concams5, concams, 0, concams5, conchess, conchess_state, empty_init, "Systemhuset / Loproc", "Conchess Plymate Amsterdam 5.5MHz", MACHINE_SUPPORTS_SAVE )
+
+SYST( 1990, concvicp, 0, 0, concvicp, conchess, conchess_state, empty_init, "Systemhuset / Loproc", "Conchess Plymate Victoria (prototype)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/chess/conic_cchess2.cpp b/src/mame/chess/conic_cchess2.cpp
new file mode 100644
index 00000000000..5ceefadad1b
--- /dev/null
+++ b/src/mame/chess/conic_cchess2.cpp
@@ -0,0 +1,285 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+// thanks-to:bataais
+/*******************************************************************************
+
+Conic Computer Chess (model 07012), also sold under the same name by
+Hanimex (model HMG 1200) and Westrak (model CC 1). It's also known as
+Tracer Chess, this title is from an advertisement flyer, the actual chess
+computer was simply named Computer Chess.
+
+The chessboard sensors aren't buttons or magnets, but 64 jacks. There is
+a metal plug under each chesspiece. From MAME's perspective, it works the
+same as a magnet sensorboard.
+
+After the player's move, the user needs to press Enter. This does not apply
+to the computer's move.
+
+Hardware notes:
+- Synertek 6504 @ ~1MHz
+- 2*Motorola MC6821P PIA
+- 4KB ROM(AMI), 1KB RAM(2*Synertek 1024x4)
+- beeper, 8*8 leds, plug board
+
+BTANB:
+- Learn button still works when in modify-mode
+
+*******************************************************************************/
+
+#include "emu.h"
+
+#include "cpu/m6502/m6504.h"
+#include "machine/6821pia.h"
+#include "machine/sensorboard.h"
+#include "sound/dac.h"
+#include "video/pwm.h"
+
+#include "speaker.h"
+
+// internal artwork
+#include "conic_cchess2.lh"
+
+
+namespace {
+
+class cchess2_state : public driver_device
+{
+public:
+ cchess2_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_pia(*this, "pia%u", 0),
+ m_board(*this, "board"),
+ m_display(*this, "display"),
+ m_dac(*this, "dac"),
+ m_inputs(*this, "IN.%u", 0)
+ { }
+
+ // machine configs
+ void cncchess2(machine_config &config);
+
+ // assume that RESET button is tied to 6504 reset pin
+ DECLARE_INPUT_CHANGED_MEMBER(reset_button) { m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? ASSERT_LINE : CLEAR_LINE); }
+
+protected:
+ virtual void machine_start() override ATTR_COLD;
+
+private:
+ // devices/pointers
+ required_device<cpu_device> m_maincpu;
+ required_device_array<pia6821_device, 2> m_pia;
+ required_device<sensorboard_device> m_board;
+ required_device<pwm_display_device> m_display;
+ required_device<dac_1bit_device> m_dac;
+ required_ioport_array<8> m_inputs;
+
+ u8 m_inp_mux = 0;
+ u8 m_led_data = 0;
+ u8 m_dac_on = 0;
+
+ // address maps
+ void main_map(address_map &map) ATTR_COLD;
+
+ // I/O handlers
+ void update_display();
+ void update_dac();
+ void pia0_pa_w(u8 data);
+ void pia0_pb_w(u8 data);
+ u8 pia1_pa_r();
+ u8 pia1_pb_r();
+ void pia1_pb_w(u8 data);
+};
+
+void cchess2_state::machine_start()
+{
+ save_item(NAME(m_inp_mux));
+ save_item(NAME(m_led_data));
+ save_item(NAME(m_dac_on));
+}
+
+
+
+/*******************************************************************************
+ I/O
+*******************************************************************************/
+
+void cchess2_state::update_display()
+{
+ m_display->matrix(m_inp_mux, m_led_data);
+}
+
+void cchess2_state::update_dac()
+{
+ m_dac->write(m_dac_on & BIT(m_inp_mux, 1));
+}
+
+void cchess2_state::pia0_pa_w(u8 data)
+{
+ // d0-d7: input mux/led select
+ // d1: dac data
+ m_inp_mux = data;
+ update_display();
+ update_dac();
+}
+
+void cchess2_state::pia0_pb_w(u8 data)
+{
+ // d0-d7: led data
+ m_led_data = data;
+ update_display();
+}
+
+u8 cchess2_state::pia1_pa_r()
+{
+ u8 data = 0;
+
+ // d0-d7: chessboard sensors
+ for (int i = 0; i < 8; i++)
+ if (BIT(m_inp_mux, i))
+ data |= m_board->read_rank(i);
+
+ return ~data;
+}
+
+u8 cchess2_state::pia1_pb_r()
+{
+ u8 data = 0;
+
+ // d0-d3: multiplexed inputs
+ for (int i = 0; i < 8; i++)
+ if (BIT(m_inp_mux, i))
+ data |= m_inputs[i]->read();
+
+ return data;
+}
+
+void cchess2_state::pia1_pb_w(u8 data)
+{
+ // d7: dac on
+ m_dac_on = BIT(data, 7);
+ update_dac();
+}
+
+
+
+/*******************************************************************************
+ Address Maps
+*******************************************************************************/
+
+void cchess2_state::main_map(address_map &map)
+{
+ map.global_mask(0x1fff);
+ map(0x0000, 0x03ff).ram();
+ map(0x0a00, 0x0a03).mirror(0x00fc).rw(m_pia[0], FUNC(pia6821_device::read), FUNC(pia6821_device::write));
+ map(0x0c00, 0x0c03).mirror(0x00fc).rw(m_pia[1], FUNC(pia6821_device::read), FUNC(pia6821_device::write));
+ map(0x1000, 0x1fff).rom();
+}
+
+
+
+/*******************************************************************************
+ Input Ports
+*******************************************************************************/
+
+static INPUT_PORTS_START( cncchess2 )
+ PORT_START("IN.0")
+ PORT_BIT(0x03, IP_ACTIVE_HIGH, IPT_UNUSED)
+ PORT_CONFNAME( 0x0c, 0x08, "Mode" )
+ PORT_CONFSETTING( 0x04, "Modify" )
+ PORT_CONFSETTING( 0x08, "Play" )
+
+ PORT_START("IN.1")
+ PORT_CONFNAME( 0x03, 0x02, "Color" )
+ PORT_CONFSETTING( 0x01, "Black" ) // from the bottom
+ PORT_CONFSETTING( 0x02, "White" )
+ PORT_BIT(0x0c, IP_ACTIVE_HIGH, IPT_UNUSED)
+
+ PORT_START("IN.2")
+ PORT_BIT(0x0f, IP_ACTIVE_HIGH, IPT_UNUSED)
+
+ PORT_START("IN.3")
+ PORT_BIT(0x0f, IP_ACTIVE_HIGH, IPT_UNUSED)
+
+ PORT_START("IN.4")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("Enter")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_N) PORT_NAME("Learn")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_L) PORT_NAME("Level")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) PORT_NAME("6 / White King")
+
+ PORT_START("IN.5")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) PORT_NAME("5 / White Queen")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_4) PORT_NAME("4 / White Rook")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3) PORT_NAME("3 / White Bishop")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) PORT_NAME("2 / White Knight")
+
+ PORT_START("IN.6")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) PORT_NAME("1 / White Pawn")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_DEL) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("Clear")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_7) PORT_NAME("7 / Black Pawn")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_8) PORT_NAME("8 / Black Knight")
+
+ PORT_START("IN.7")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_9) PORT_NAME("9 / Black Bishop")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_0) PORT_NAME("10 / Black Rook")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_MINUS) PORT_NAME("11 / Black Queen")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_EQUALS) PORT_NAME("12 / Black King")
+
+ PORT_START("RESET")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_R) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(cchess2_state::reset_button), 0) PORT_NAME("Reset")
+INPUT_PORTS_END
+
+
+
+/*******************************************************************************
+ Machine Configs
+*******************************************************************************/
+
+void cchess2_state::cncchess2(machine_config &config)
+{
+ // basic machine hardware
+ M6504(config, m_maincpu, 1'000'000); // approximation, no XTAL
+ m_maincpu->set_addrmap(AS_PROGRAM, &cchess2_state::main_map);
+
+ PIA6821(config, m_pia[0]);
+ m_pia[0]->writepa_handler().set(FUNC(cchess2_state::pia0_pa_w));
+ m_pia[0]->writepb_handler().set(FUNC(cchess2_state::pia0_pb_w));
+
+ PIA6821(config, m_pia[1]);
+ m_pia[1]->readpa_handler().set(FUNC(cchess2_state::pia1_pa_r));
+ m_pia[1]->readpb_handler().set(FUNC(cchess2_state::pia1_pb_r));
+ m_pia[1]->writepb_handler().set(FUNC(cchess2_state::pia1_pb_w));
+
+ SENSORBOARD(config, m_board).set_type(sensorboard_device::MAGNETS);
+ m_board->init_cb().set(m_board, FUNC(sensorboard_device::preset_chess));
+ m_board->set_delay(attotime::from_msec(150));
+
+ // video hardware
+ PWM_DISPLAY(config, m_display).set_size(8, 8);
+ config.set_default_layout(layout_conic_cchess2);
+
+ // sound hardware
+ SPEAKER(config, "speaker").front_center();
+ DAC_1BIT(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25);
+}
+
+
+
+/*******************************************************************************
+ ROM Definitions
+*******************************************************************************/
+
+ROM_START( cncchess2 )
+ ROM_REGION( 0x2000, "maincpu", 0 )
+ ROM_LOAD("c11485.u2", 0x1000, 0x1000, CRC(b179d536) SHA1(0b1f9c247a4a3e2ccbf8d3ae5efa62b8938f572f) ) // AMI 2332
+ROM_END
+
+} // anonymous namespace
+
+
+
+/*******************************************************************************
+ Drivers
+*******************************************************************************/
+
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
+SYST( 1980, cncchess2, 0, 0, cncchess2, cncchess2, cchess2_state, empty_init, "Conic", "Computer Chess (Conic, model 7012)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/chess/conic_cchess3.cpp b/src/mame/chess/conic_cchess3.cpp
new file mode 100644
index 00000000000..3f9de4aa4ad
--- /dev/null
+++ b/src/mame/chess/conic_cchess3.cpp
@@ -0,0 +1,161 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+// thanks-to:Berger
+/*******************************************************************************
+
+Conic Computer Chess (model 07013), more commonly known as Conic "Korchnoi".
+
+The interface is similar to the previous model (07012), where the user needs
+to press Enter after their move.
+
+Hardware notes:
+- Synertek 6502A @ 2MHz
+- OKI MSM5840H-41RS @ 3.57MHz (2KB internal ROM)
+- 2*4KB ROM(AMI), 1KB RAM(2*2114)
+- beeper, 8*8+4 leds, magnets chessboard
+
+TODO:
+- It does not work, MSM5840 is unemulated, and the internal ROM is not dumped.
+ MCU handles inputs, leds, sound, and it communicates with maincpu after
+ triggering an IRQ.
+
+*******************************************************************************/
+
+#include "emu.h"
+
+#include "cpu/m6502/m6502.h"
+#include "machine/sensorboard.h"
+#include "sound/dac.h"
+#include "video/pwm.h"
+
+#include "speaker.h"
+
+// internal artwork
+//#include "conic_cchess3.lh"
+
+
+namespace {
+
+class cchess3_state : public driver_device
+{
+public:
+ cchess3_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_display(*this, "display"),
+ m_dac(*this, "dac")
+ { }
+
+ // machine configs
+ void cncchess3(machine_config &config);
+
+protected:
+ virtual void machine_start() override ATTR_COLD;
+
+private:
+ // devices/pointers
+ required_device<cpu_device> m_maincpu;
+ required_device<sensorboard_device> m_board;
+ required_device<pwm_display_device> m_display;
+ required_device<dac_1bit_device> m_dac;
+
+ void main_map(address_map &map) ATTR_COLD;
+
+ // I/O handlers
+ void main_comm_w(u8 data);
+ u8 main_comm_r();
+};
+
+void cchess3_state::machine_start()
+{
+}
+
+
+
+/*******************************************************************************
+ I/O
+*******************************************************************************/
+
+void cchess3_state::main_comm_w(u8 data)
+{
+}
+
+u8 cchess3_state::main_comm_r()
+{
+ return 0;
+}
+
+
+
+/*******************************************************************************
+ Address Maps
+*******************************************************************************/
+
+void cchess3_state::main_map(address_map &map)
+{
+ map.global_mask(0x3fff);
+ map(0x0000, 0x03ff).ram();
+ map(0x1000, 0x1000).rw(FUNC(cchess3_state::main_comm_r), FUNC(cchess3_state::main_comm_w));
+ map(0x2000, 0x3fff).rom();
+}
+
+
+
+/*******************************************************************************
+ Input Ports
+*******************************************************************************/
+
+static INPUT_PORTS_START( cncchess3 )
+INPUT_PORTS_END
+
+
+
+/*******************************************************************************
+ Machine Configs
+*******************************************************************************/
+
+void cchess3_state::cncchess3(machine_config &config)
+{
+ // basic machine hardware
+ M6502(config, m_maincpu, 2_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &cchess3_state::main_map);
+
+ SENSORBOARD(config, m_board).set_type(sensorboard_device::MAGNETS);
+ m_board->init_cb().set(m_board, FUNC(sensorboard_device::preset_chess));
+ m_board->set_delay(attotime::from_msec(150));
+
+ // video hardware
+ PWM_DISPLAY(config, m_display).set_size(8+1, 8);
+ //config.set_default_layout(layout_conic_cchess3);
+
+ // sound hardware
+ SPEAKER(config, "speaker").front_center();
+ DAC_1BIT(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25);
+}
+
+
+
+/*******************************************************************************
+ ROM Definitions
+*******************************************************************************/
+
+ROM_START( cncchess3 )
+ ROM_REGION( 0x4000, "maincpu", 0 )
+ ROM_LOAD("ci07013-1", 0x2000, 0x1000, CRC(3251a529) SHA1(729b22d7653761ff0951ce1da58fdfcd474a700d) ) // AMI 2332
+ ROM_LOAD("ci07013-2", 0x3000, 0x1000, CRC(0f38dcef) SHA1(f8fb7e12b41753fe52dd2eb2edb843211b5ca7c1) ) // "
+
+ ROM_REGION( 0x0800, "mcu", 0 )
+ ROM_LOAD("msm5840h-41rs", 0x0000, 0x0800, NO_DUMP )
+ROM_END
+
+} // anonymous namespace
+
+
+
+/*******************************************************************************
+ Drivers
+*******************************************************************************/
+
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
+SYST( 1981, cncchess3, 0, 0, cncchess3, cncchess3, cchess3_state, empty_init, "Conic", "Computer Chess (Conic, model 7013)", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
diff --git a/src/mame/chess/krypton_regency.cpp b/src/mame/chess/krypton_regency.cpp
new file mode 100644
index 00000000000..c1453f8b5ef
--- /dev/null
+++ b/src/mame/chess/krypton_regency.cpp
@@ -0,0 +1,350 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+// thanks-to:Berger
+/*******************************************************************************
+
+Krypton Regency (model 933)
+
+It was manufactured by Timorite, Ltd. (Eric White's company), the chess engine is
+by Gyula Horváth, similar to the one in CXG Sphinx Legend.
+
+To start a new game, keep holding the NEW GAME button until the display says HELLO.
+
+Hardware notes (Systema Challenge fitted with Regency MCU):
+- PCB label: LCD CHESS 938, JAN.1994, REV.1, EB-093801-01
+- Hitachi H8/3256 MCU, 20MHz XTAL
+- LCD with 5 7segs and custom segments
+- piezo, 16 LEDs (optional), button sensors chessboard
+
+A26 MCU was used in:
+- Krypton Regency (with or without LEDs)
+- Excalibur Avenger (suspected, Excalibur brand Comet, with newer MCU)
+- Excalibur Legend III (suspected, Excalibur brand Regency)
+- Systema Challenge (1996 version)
+
+TODO:
+- CXG Sphinx Legend may be on the same hardware? if so, move driver to cxg folder
+- is Krypton a product brand, or a company alias for the Chinese factory behind it?
+- 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
+
+*******************************************************************************/
+
+#include "emu.h"
+
+#include "cpu/h8/h8325.h"
+#include "machine/sensorboard.h"
+#include "sound/dac.h"
+#include "video/pwm.h"
+
+#include "screen.h"
+#include "speaker.h"
+
+// internal artwork
+#include "krypton_regency.lh"
+
+
+namespace {
+
+class regency_state : public driver_device
+{
+public:
+ regency_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.%u", 0),
+ m_out_lcd(*this, "s%u.%u", 0U, 0U)
+ { }
+
+ void regency(machine_config &config);
+
+ DECLARE_INPUT_CHANGED_MEMBER(in1_changed) { update_irq2(); }
+
+protected:
+ virtual void machine_start() override ATTR_COLD;
+
+private:
+ // devices/pointers
+ required_device<h83256_device> m_maincpu;
+ required_device<sensorboard_device> m_board;
+ required_device<pwm_display_device> m_led_pwm;
+ required_device<pwm_display_device> m_lcd_pwm;
+ required_device<dac_1bit_device> m_dac;
+ required_ioport_array<3> m_inputs;
+ output_finder<2, 24> m_out_lcd;
+
+ u16 m_inp_mux = 0;
+ u8 m_inp_mux2 = 0;
+ u32 m_lcd_segs = 0;
+ u8 m_lcd_com = 0;
+
+ // I/O handlers
+ void lcd_pwm_w(offs_t offset, u8 data);
+ void update_lcd();
+ template <int N> void lcd_segs_w(u8 data);
+
+ void standby(int state);
+ int update_irq2();
+
+ void p2_w(u8 data);
+ void p5_w(offs_t offset, u8 data, u8 mem_mask);
+ u8 p6_r();
+ void p6_w(offs_t offset, u8 data, u8 mem_mask);
+ u8 p7_r();
+ void p7_w(u8 data);
+};
+
+void regency_state::machine_start()
+{
+ m_out_lcd.resolve();
+
+ // register for savestates
+ save_item(NAME(m_inp_mux));
+ save_item(NAME(m_inp_mux2));
+ save_item(NAME(m_lcd_segs));
+ save_item(NAME(m_lcd_com));
+}
+
+
+
+/*******************************************************************************
+ I/O
+*******************************************************************************/
+
+// power
+
+void regency_state::standby(int state)
+{
+ // clear display
+ if (state)
+ {
+ m_lcd_pwm->clear();
+ m_led_pwm->clear();
+ }
+}
+
+int regency_state::update_irq2()
+{
+ // 2nd button row is tied to IRQ2 (used for on/off button)
+ int state = (m_inp_mux2 & m_inputs[1]->read()) ? ASSERT_LINE : CLEAR_LINE;
+ m_maincpu->set_input_line(INPUT_LINE_IRQ2, state);
+
+ return state;
+}
+
+
+// LCD
+
+void regency_state::lcd_pwm_w(offs_t offset, u8 data)
+{
+ m_out_lcd[offset & 0x3f][offset >> 6] = data;
+}
+
+void regency_state::update_lcd()
+{
+ u32 lcd_segs = bitswap<24>(m_lcd_segs,1,0, 15,14,13,12,11,10,9,8, 16,17,23,22,21,20,19,18, 25,26,27,28,29,31);
+
+ for (int i = 0; i < 2; i++)
+ {
+ // LCD common is 0/1/Hi-Z
+ const u32 data = BIT(m_lcd_com, i + 2) ? (BIT(m_lcd_com, i) ? ~lcd_segs : lcd_segs) : 0;
+ m_lcd_pwm->write_row(i, data);
+ }
+}
+
+template <int N>
+void regency_state::lcd_segs_w(u8 data)
+{
+ // P1x, P3x, P4x, P6x: LCD segments
+ const u8 shift = 8 * N;
+ m_lcd_segs = (m_lcd_segs & ~(0xff << shift)) | (data << shift);
+ update_lcd();
+}
+
+
+// misc
+
+void regency_state::p2_w(u8 data)
+{
+ // P20-P27: input mux (chessboard), LED data
+ m_inp_mux = (m_inp_mux & 0x300) | (data ^ 0xff);
+ m_led_pwm->write_mx(~data);
+}
+
+void regency_state::p5_w(offs_t offset, u8 data, u8 mem_mask)
+{
+ // P50: LCD common 2
+ m_lcd_com = (m_lcd_com & 5) | (data << 1 & 2) | (mem_mask << 3 & 8);
+ update_lcd();
+
+ // P51: speaker out
+ m_dac->write(BIT(~data, 1));
+
+ // P52: input mux part
+ m_inp_mux = (m_inp_mux & 0x2ff) | (BIT(~data, 2) << 8);
+
+ // P54,P55: LED select
+ m_led_pwm->write_my(~data >> 4 & 3);
+}
+
+u8 regency_state::p6_r()
+{
+ // P65: battery status
+ u8 data = m_inputs[2]->read() << 5 & 0x20;
+
+ // P66: IRQ2 pin
+ if (!machine().side_effects_disabled() && update_irq2())
+ data |= 0x40;
+
+ return ~data;
+}
+
+void regency_state::p6_w(offs_t offset, u8 data, u8 mem_mask)
+{
+ // P60,P61: LCD segs
+ lcd_segs_w<0>(data & 3);
+
+ // P62: LCD common 1
+ m_lcd_com = (m_lcd_com & 0xa) | (BIT(data, 2)) | (mem_mask & 4);
+ update_lcd();
+
+ // P66: input mux part
+ m_inp_mux = (m_inp_mux & 0x1ff) | (BIT(~data, 6) << 9);
+}
+
+u8 regency_state::p7_r()
+{
+ // P70-P77: multiplexed inputs
+ u8 data = 0;
+
+ // read buttons
+ for (int i = 0; i < 2; i++)
+ if (BIT(m_inp_mux, i + 8))
+ data |= m_inputs[i]->read();
+
+ // read chessboard
+ for (int i = 0; i < 8; i++)
+ if (BIT(m_inp_mux, i))
+ data |= m_board->read_file(i ^ 7);
+
+ return ~data;
+}
+
+void regency_state::p7_w(u8 data)
+{
+ // P70-P77: input mux (other way around)
+ m_inp_mux2 = ~data;
+ update_irq2();
+}
+
+
+
+/*******************************************************************************
+ Input Ports
+*******************************************************************************/
+
+#define PORT_CHANGED_IN1() \
+ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(regency_state::in1_changed), 0)
+
+static INPUT_PORTS_START( regency )
+ PORT_START("IN.0")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("Knight / Lose")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("Queen")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_S) PORT_NAME("Set-Up / Features")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_L) PORT_NAME("Level")
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_F) PORT_NAME("Step Forward")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_U) PORT_NAME("Multi-Move / Analysis")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("Rook / Win")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("Pawn / Rating")
+
+ PORT_START("IN.1")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CHANGED_IN1() PORT_CODE(KEYCODE_F1) PORT_NAME("On / Off")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CHANGED_IN1() PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("King")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CHANGED_IN1() PORT_CODE(KEYCODE_M) PORT_NAME("Move / Swap Board")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CHANGED_IN1() PORT_CODE(KEYCODE_O) PORT_NAME("Sound / Style")
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CHANGED_IN1() PORT_CODE(KEYCODE_T) PORT_NAME("Take Back")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CHANGED_IN1() PORT_CODE(KEYCODE_H) PORT_NAME("Hint / Info")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CHANGED_IN1() PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("Bishop / Draw")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CHANGED_IN1() PORT_CODE(KEYCODE_N) PORT_NAME("New Game / Clear Board")
+
+ PORT_START("IN.2")
+ PORT_CONFNAME( 0x01, 0x01, "Battery Status" )
+ PORT_CONFSETTING( 0x00, "Low" )
+ PORT_CONFSETTING( 0x01, DEF_STR( Normal ) )
+INPUT_PORTS_END
+
+
+
+/*******************************************************************************
+ Machine Configs
+*******************************************************************************/
+
+void regency_state::regency(machine_config &config)
+{
+ // basic machine hardware
+ H83256(config, m_maincpu, 20_MHz_XTAL);
+ m_maincpu->nvram_enable_backup(true);
+ m_maincpu->standby_cb().set(m_maincpu, FUNC(h83256_device::nvram_set_battery));
+ m_maincpu->standby_cb().append(FUNC(regency_state::standby));
+ m_maincpu->write_port1().set(FUNC(regency_state::lcd_segs_w<2>));
+ m_maincpu->read_port2().set_constant(0xef); // hardware config?
+ m_maincpu->write_port2().set(FUNC(regency_state::p2_w));
+ m_maincpu->write_port3().set(FUNC(regency_state::lcd_segs_w<1>));
+ m_maincpu->write_port4().set(FUNC(regency_state::lcd_segs_w<3>));
+ m_maincpu->read_port5().set_constant(0xff);
+ m_maincpu->write_port5().set(FUNC(regency_state::p5_w));
+ m_maincpu->read_port6().set(FUNC(regency_state::p6_r));
+ m_maincpu->write_port6().set(FUNC(regency_state::p6_w));
+ m_maincpu->read_port7().set(FUNC(regency_state::p7_r));
+ m_maincpu->write_port7().set(FUNC(regency_state::p7_w));
+
+ SENSORBOARD(config, m_board).set_type(sensorboard_device::BUTTONS);
+ m_board->init_cb().set(m_board, FUNC(sensorboard_device::preset_chess));
+ m_board->set_delay(attotime::from_msec(150));
+ //m_board->set_nvram_enable(true);
+
+ // video hardware
+ PWM_DISPLAY(config, m_lcd_pwm).set_size(2, 24);
+ m_lcd_pwm->output_x().set(FUNC(regency_state::lcd_pwm_w));
+
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_SVG));
+ screen.set_refresh_hz(60);
+ screen.set_size(1920/5, 697/5);
+ screen.set_visarea_full();
+
+ PWM_DISPLAY(config, m_led_pwm).set_size(2, 8);
+ config.set_default_layout(layout_krypton_regency);
+
+ // sound hardware
+ SPEAKER(config, "speaker").front_center();
+ DAC_1BIT(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25);
+}
+
+
+
+/*******************************************************************************
+ ROM Definitions
+*******************************************************************************/
+
+ROM_START( regency )
+ ROM_REGION16_BE( 0xc000, "maincpu", 0 )
+ ROM_LOAD("1996_933_timorite_hd6433256a26p.ic1", 0x0000, 0xc000, CRC(72eb3f2b) SHA1(30e4166e351210475cf9709b0feb717d9d3ac747) )
+
+ ROM_REGION( 109652, "screen", 0 )
+ ROM_LOAD("regency.svg", 0, 109652, CRC(6840c49e) SHA1(a9c91143c5bea5ab41fe323e719da4a46ab9d631) )
+ROM_END
+
+} // anonymous namespace
+
+
+
+/*******************************************************************************
+ Drivers
+*******************************************************************************/
+
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
+SYST( 1996, regency, 0, 0, regency, regency, regency_state, empty_init, "Krypton / Timorite", "Regency", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/chess/regence.cpp b/src/mame/chess/regence.cpp
new file mode 100644
index 00000000000..851cc980bb2
--- /dev/null
+++ b/src/mame/chess/regence.cpp
@@ -0,0 +1,249 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/*******************************************************************************
+
+La Régence
+
+NOTE: The hardware triggers an NMI on power-off (or power-failure). If this isn't
+done, NVRAM fails at next power-on.
+
+French chess computer by "France Double R". German distribution by Sandy Electronic,
+who sub-titled it TSB 4 (Turniersensorbrett), the EPROM contents is the same.
+There is no English version.
+
+the chess engine is Richard Lang's Cyrus. This was from when he was working for
+Intelligent Software, before he got hired by Hegener + Glaser.
+
+Hardware notes:
+- PCB label: FRANCE DOUBLE R, MADE IN FRANCE
+- Sharp LH0080A Z80A @ 4 MHz (8MHz XTAL)
+- 3*4KB ROM, sockets support up to 48KB ROM
+- 2KB battery-backed RAM (MSM5128-15RS), 3 sockets, only middle one used
+- TTL, piezo, 8*8+4 LEDs, magnetic sensors
+
+TODO:
+- if/when MAME supports an exit callback, hook up power-off switch to that
+
+*******************************************************************************/
+
+#include "emu.h"
+
+#include "cpu/z80/z80.h"
+#include "machine/nvram.h"
+#include "machine/sensorboard.h"
+#include "sound/dac.h"
+#include "video/pwm.h"
+
+#include "speaker.h"
+
+// internal artwork
+#include "regence.lh"
+
+
+namespace {
+
+class regence_state : public driver_device
+{
+public:
+ regence_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_display(*this, "display"),
+ m_board(*this, "board"),
+ m_dac(*this, "dac"),
+ m_inputs(*this, "IN.%u", 0)
+ { }
+
+ DECLARE_INPUT_CHANGED_MEMBER(power_off);
+
+ void regence(machine_config &config);
+
+protected:
+ virtual void machine_start() override ATTR_COLD;
+ virtual void machine_reset() override ATTR_COLD { m_power = true; }
+
+private:
+ // devices/pointers
+ required_device<cpu_device> m_maincpu;
+ required_device<pwm_display_device> m_display;
+ required_device<sensorboard_device> m_board;
+ required_device<dac_1bit_device> m_dac;
+ required_ioport_array<2> m_inputs;
+
+ bool m_power = false;
+ u8 m_inp_mux = 0;
+ u8 m_led_data = 0;
+
+ void main_map(address_map &map) ATTR_COLD;
+
+ // I/O handlers
+ void update_display();
+ void control_w(u8 data);
+ void leds_w(u8 data);
+ u8 input_r();
+};
+
+void regence_state::machine_start()
+{
+ // register for savestates
+ save_item(NAME(m_power));
+ save_item(NAME(m_inp_mux));
+ save_item(NAME(m_led_data));
+}
+
+INPUT_CHANGED_MEMBER(regence_state::power_off)
+{
+ // NMI at power-off (it prepares nvram for next power-on)
+ if (newval && m_power)
+ {
+ m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
+ m_power = false;
+ }
+}
+
+
+
+/*******************************************************************************
+ I/O
+*******************************************************************************/
+
+void regence_state::update_display()
+{
+ m_display->matrix(1 << m_inp_mux, m_led_data);
+}
+
+void regence_state::control_w(u8 data)
+{
+ // d0-d3: input mux/led select
+ m_inp_mux = data & 0xf;
+ update_display();
+
+ // d7: speaker out
+ m_dac->write(BIT(data, 7));
+
+ // other: ?
+}
+
+void regence_state::leds_w(u8 data)
+{
+ // d0-d7: led data
+ m_led_data = data;
+ update_display();
+}
+
+u8 regence_state::input_r()
+{
+ u8 data = 0;
+
+ // d0-d7: multiplexed inputs
+ // read chessboard sensors
+ if (m_inp_mux < 8)
+ data = m_board->read_file(m_inp_mux, true);
+
+ // read other buttons
+ else if (m_inp_mux < 10)
+ data = m_inputs[m_inp_mux - 8]->read();
+
+ return data;
+}
+
+
+
+/*******************************************************************************
+ Address Maps
+*******************************************************************************/
+
+void regence_state::main_map(address_map &map)
+{
+ map(0x0000, 0x0fff).rom();
+ map(0x4000, 0x4fff).rom();
+ map(0x8000, 0x8fff).rom();
+ map(0xd000, 0xd7ff).ram().share("nvram");
+ map(0xf000, 0xf000).rw(FUNC(regence_state::input_r), FUNC(regence_state::control_w));
+ map(0xf800, 0xf800).w(FUNC(regence_state::leds_w));
+}
+
+
+
+/*******************************************************************************
+ Input Ports
+*******************************************************************************/
+
+static INPUT_PORTS_START( regence ) // see comments for German version labels
+ PORT_START("IN.0")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_S) PORT_NAME("Changement de Position (Set Up)") // Veränderung
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_T) PORT_NAME(u8"Retour en Arrière (Take Back)") // Zug Zurück
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_N) PORT_NAME("Nouvelle Partie (New Game)") // Neues Spiel (press after setup)
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("King")
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("Queen")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("Rook")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("Bishop")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNUSED)
+
+ PORT_START("IN.1")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_O) PORT_NAME("Son (Sound)") // Ton
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_L) PORT_NAME("Niveau (Level)") // Stufe
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_M) PORT_CODE(KEYCODE_H) PORT_NAME("Marche/Arret (Move/Halt)") // Zug-Halt
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_B) PORT_NAME("Noir (Black)") // Schwarz
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_W) PORT_NAME("Blanc (White)") // Weiss
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("Pawn")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("Knight")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNUSED)
+
+ PORT_START("POWER") // needs to be triggered for nvram to work
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_POWER_OFF) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(regence_state::power_off), 0)
+INPUT_PORTS_END
+
+
+
+/*******************************************************************************
+ Machine Configs
+*******************************************************************************/
+
+void regence_state::regence(machine_config &config)
+{
+ // basic machine hardware
+ Z80(config, m_maincpu, 8_MHz_XTAL/2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &regence_state::main_map);
+
+ m_maincpu->set_periodic_int(FUNC(regence_state::irq0_line_hold), attotime::from_hz(448)); // from 555, measured
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ SENSORBOARD(config, m_board).set_type(sensorboard_device::MAGNETS);
+ m_board->init_cb().set(m_board, FUNC(sensorboard_device::preset_chess));
+ m_board->set_delay(attotime::from_msec(150));
+ m_board->set_nvram_enable(true);
+
+ // video hardware
+ PWM_DISPLAY(config, m_display).set_size(10, 8);
+ config.set_default_layout(layout_regence);
+
+ // sound hardware
+ SPEAKER(config, "speaker").front_center();
+ DAC_1BIT(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25);
+}
+
+
+
+/*******************************************************************************
+ ROM Definitions
+*******************************************************************************/
+
+ROM_START( regence )
+ ROM_REGION( 0x10000, "maincpu", 0 )
+ ROM_LOAD("arc0.ic13", 0x0000, 0x1000, CRC(ac6a0a67) SHA1(52b115c7cd372dfbad14b00854aa4f6f75a937d3) ) // M5L2732K
+ ROM_LOAD("arc1.ic12", 0x4000, 0x1000, CRC(5c2fb0c7) SHA1(811ab3d7cefcf872741eb2265115080aaf913f0f) ) // "
+ ROM_LOAD("arc2.ic11", 0x8000, 0x1000, CRC(e4c39dbd) SHA1(b6a6d1d39f73a2ff1ade6205bdf180be13e84df3) ) // "
+ROM_END
+
+} // anonymous namespace
+
+
+
+/*******************************************************************************
+ Drivers
+*******************************************************************************/
+
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
+SYST( 1982, regence, 0, 0, regence, regence, regence_state, empty_init, "France Double R / Intelligent Software", u8"La Régence", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/chess/tasc.cpp b/src/mame/chess/tasc.cpp
new file mode 100644
index 00000000000..876a57da608
--- /dev/null
+++ b/src/mame/chess/tasc.cpp
@@ -0,0 +1,369 @@
+// license:BSD-3-Clause
+// copyright-holders:hap, Sandro Ronco
+/*******************************************************************************
+
+Tasc ChessSystem
+
+Commonly known as Tasc R30, it's basically a dedicated ChessMachine.
+The King chess engines are also compatible with Tasc's The ChessMachine software
+on PC, however the prototype Gideon 3.1(internally: 2.1, Rebel 2.01) is not.
+
+The King 2.23 version was not sold to consumers. It has an opening book meant
+for chesscomputer competitions.
+For more information, see: http://chesseval.com/ChessEvalJournal/R30v223.htm
+
+Gideon only uses 128KB program RAM, no matter the RAM configuration.
+
+R30 hardware notes:
+- ARM6 CPU(P60ARM/CG) @ 30MHz
+- 256KB system ROM (2*27C010)
+- 512KB program RAM (4*MT5C1008), 128KB permanent RAM (KM681000ALP-7L)
+- Toshiba LCD drivers (3*T7778A, T7900, T6963C), TC5565AFL-15
+- SB20 or SB30 "SmartBoard" chessboard with piece recognition
+
+R40 hardware notes:
+- ARM6 CPU(VY86C061PSTC) @ 40MHz
+- +512KB extra RAM piggybacked
+- rest same as R30
+
+Documentation for the Toshiba chips is hard to find, but similar chips exist:
+T7778 is equivalent to T6A39, T7900 is equivalent to T6A40.
+
+EPROMs are interchangeable between R30 and R40.
+
+references:
+- https://www.schach-computer.info/wiki/index.php?title=Tasc_R30
+- https://www.schach-computer.info/wiki/index.php?title=Tasc_R40
+- https://www.schach-computer.info/wiki/index.php?title=Tasc_SmartBoard
+- https://www.miclangschach.de/index.php?n=Main.TascR30
+
+notes:
+- holding LEFT+RIGHT on boot load the QC TestMode
+- holding UP+DOWN on boot load the TestMode
+
+TODO:
+- bootrom disable timer shouldn't be needed, real ARM has already fetched the next opcode
+- more accurate dynamic cpu clock divider (same problem as in saitek/risc2500.cpp),
+ sound pitch is correct now though
+- does the R40 version have the same clock divider value?
+
+BTANB:
+- R40 calls itself "R30" on the system information screen (there is a photo of
+ an R40 that does say "R40", but it appears to be a modified ROM)
+
+*******************************************************************************/
+
+#include "emu.h"
+
+#include "cpu/arm/arm.h"
+#include "machine/nvram.h"
+#include "machine/ram.h"
+#include "machine/smartboard.h"
+#include "sound/dac.h"
+#include "video/t6963c.h"
+
+#include "speaker.h"
+
+// internal artwork
+#include "tascr30.lh"
+
+
+namespace {
+
+class tasc_state : public driver_device
+{
+public:
+ tasc_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_boot_view(*this, "boot_view"),
+ m_rom(*this, "maincpu"),
+ m_ram(*this, "ram"),
+ m_nvram(*this, "nvram", 0x20000, ENDIANNESS_LITTLE),
+ m_lcd(*this, "lcd"),
+ m_smartboard(*this, "smartboard"),
+ m_dac(*this, "dac"),
+ m_inputs(*this, "IN.%u", 0U),
+ m_out_leds(*this, "pled%u", 0U)
+ { }
+
+ void tasc(machine_config &config);
+
+ DECLARE_INPUT_CHANGED_MEMBER(change_cpu_freq);
+
+protected:
+ virtual void machine_start() override ATTR_COLD;
+ virtual void machine_reset() override ATTR_COLD;
+
+private:
+ // devices/pointers
+ required_device<arm_cpu_device> m_maincpu;
+ memory_view m_boot_view;
+ required_region_ptr<u32> m_rom;
+ required_device<ram_device> m_ram;
+ memory_share_creator<u8> m_nvram;
+ required_device<lm24014h_device> m_lcd;
+ required_device<tasc_sb30_device> m_smartboard;
+ required_device<dac_2bit_ones_complement_device> m_dac;
+ required_ioport_array<4> m_inputs;
+ output_finder<2> m_out_leds;
+
+ emu_timer *m_boot_timer;
+
+ u32 m_control = 0;
+ u32 m_prev_pc = 0;
+ u64 m_prev_cycle = 0;
+
+ void main_map(address_map &map) ATTR_COLD;
+
+ // I/O handlers
+ u32 input_r();
+ u32 rom_r(offs_t offset);
+ void control_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+
+ u8 nvram_r(offs_t offset) { return m_nvram[offset]; }
+ void nvram_w(offs_t offset, u8 data) { m_nvram[offset] = data; }
+
+ TIMER_CALLBACK_MEMBER(disable_bootrom) { m_boot_view.select(1); }
+};
+
+
+
+/*******************************************************************************
+ Initialization
+*******************************************************************************/
+
+void tasc_state::machine_start()
+{
+ m_out_leds.resolve();
+
+ m_boot_timer = timer_alloc(FUNC(tasc_state::disable_bootrom), this);
+ m_boot_view[1].install_ram(0, m_ram->size() - 1, m_ram->pointer());
+
+ // register for savestates
+ save_item(NAME(m_control));
+ save_item(NAME(m_prev_pc));
+ save_item(NAME(m_prev_cycle));
+}
+
+void tasc_state::machine_reset()
+{
+ m_boot_view.select(0);
+ m_boot_timer->adjust(attotime::never);
+
+ m_prev_pc = m_maincpu->pc();
+ m_prev_cycle = m_maincpu->total_cycles();
+}
+
+INPUT_CHANGED_MEMBER(tasc_state::change_cpu_freq)
+{
+ // R30 is 30MHz, R40 is 40MHz
+ m_maincpu->set_unscaled_clock((newval & 1) ? 40_MHz_XTAL : 30_MHz_XTAL);
+}
+
+
+
+/*******************************************************************************
+ I/O
+*******************************************************************************/
+
+u32 tasc_state::input_r()
+{
+ if (!machine().side_effects_disabled())
+ {
+ // disconnect bootrom from the bus after next opcode
+ if (m_boot_timer->remaining().is_never())
+ m_boot_timer->adjust(m_maincpu->cycles_to_attotime(10));
+
+ m_maincpu->set_input_line(ARM_FIRQ_LINE, CLEAR_LINE);
+ }
+
+ // read chessboard
+ u32 data = m_smartboard->data_r();
+
+ // read keypad
+ for (int i = 0; i < 4; i++)
+ {
+ if (BIT(m_control, i))
+ data |= (m_inputs[i]->read() << 24);
+ }
+
+ return data;
+}
+
+void tasc_state::control_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ if (ACCESSING_BITS_24_31)
+ {
+ if (BIT(data, 27))
+ m_lcd->write(BIT(data, 26), data & 0xff);
+
+ m_smartboard->data0_w(BIT(data, 30));
+ m_smartboard->data1_w(BIT(data, 31));
+ }
+ else
+ {
+ m_out_leds[0] = BIT(data, 0);
+ m_out_leds[1] = BIT(data, 1);
+ m_dac->write((data >> 2) & 3);
+ }
+
+ COMBINE_DATA(&m_control);
+}
+
+u32 tasc_state::rom_r(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ // handle dynamic cpu clock divider when accessing rom
+ s64 diff = m_maincpu->total_cycles() - m_prev_cycle;
+ u32 pc = m_maincpu->pc();
+
+ if (diff > 0)
+ {
+ static constexpr int arm_branch_cycles = 3;
+ static constexpr int arm_max_cycles = 17; // datablock transfer
+ static constexpr int divider = -7 + 1;
+
+ // this takes care of almost all cases, otherwise, total cycles taken can't be determined
+ if (diff <= arm_branch_cycles || (diff <= arm_max_cycles && (pc - m_prev_pc) == 4 && (pc & ~0x02000000) == (offset * 4)))
+ m_maincpu->adjust_icount(divider * (int)diff);
+ else
+ m_maincpu->adjust_icount(divider);
+ }
+
+ m_prev_cycle = m_maincpu->total_cycles();
+ m_prev_pc = pc;
+ }
+
+ return m_rom[offset];
+}
+
+
+
+/*******************************************************************************
+ Address Maps
+*******************************************************************************/
+
+void tasc_state::main_map(address_map &map)
+{
+ map(0x00000000, 0x007fffff).view(m_boot_view);
+ m_boot_view[0](0x00000000, 0x0003ffff).r(FUNC(tasc_state::rom_r));
+
+ map(0x01000000, 0x01000003).rw(FUNC(tasc_state::input_r), FUNC(tasc_state::control_w));
+ map(0x02000000, 0x0203ffff).r(FUNC(tasc_state::rom_r));
+ map(0x03000000, 0x0307ffff).rw(FUNC(tasc_state::nvram_r), FUNC(tasc_state::nvram_w)).umask32(0x000000ff);
+}
+
+
+
+/*******************************************************************************
+ Input Ports
+*******************************************************************************/
+
+static INPUT_PORTS_START( tasc )
+ PORT_START("IN.0")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_P) PORT_NAME("Play")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_LEFT) PORT_NAME("Left")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNUSED)
+
+ PORT_START("IN.1")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_B) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("Back")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_RIGHT) PORT_NAME("Right")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNUSED)
+
+ PORT_START("IN.2")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_M) PORT_NAME("Menu")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_UP) PORT_NAME("Up")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_L) PORT_NAME("Left Clock")
+
+ PORT_START("IN.3")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("Enter")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_DOWN) PORT_NAME("Down")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_R) PORT_NAME("Right Clock")
+
+ PORT_START("CPU")
+ PORT_CONFNAME( 0x01, 0x00, "CPU Frequency" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(tasc_state::change_cpu_freq), 0)
+ PORT_CONFSETTING( 0x00, "30MHz (R30)" )
+ PORT_CONFSETTING( 0x01, "40MHz (R40)" )
+INPUT_PORTS_END
+
+
+
+/*******************************************************************************
+ Machine Configs
+*******************************************************************************/
+
+void tasc_state::tasc(machine_config &config)
+{
+ // basic machine hardware
+ ARM(config, m_maincpu, 30_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &tasc_state::main_map);
+ m_maincpu->set_copro_type(arm_cpu_device::copro_type::VL86C020);
+
+ const attotime irq_period = attotime::from_hz(32.768_kHz_XTAL / 128); // 256Hz
+ m_maincpu->set_periodic_int(FUNC(tasc_state::irq1_line_assert), irq_period);
+
+ RAM(config, m_ram).set_extra_options("512K, 1M, 2M, 4M, 8M"); // see driver notes
+ m_ram->set_default_size("512K");
+ m_ram->set_default_value(0);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ TASC_SB30(config, m_smartboard);
+ subdevice<sensorboard_device>("smartboard:board")->set_nvram_enable(true);
+
+ // video hardware
+ LM24014H(config, m_lcd, 0);
+ m_lcd->set_fs(1); // font size 6x8
+
+ config.set_default_layout(layout_tascr30);
+
+ // sound hardware
+ SPEAKER(config, "speaker").front_center();
+ DAC_2BIT_ONES_COMPLEMENT(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.125);
+}
+
+
+
+/*******************************************************************************
+ ROM Definitions
+*******************************************************************************/
+
+ROM_START( tascr30 ) // system version V1.01 (17-Mar-95), program version 2.50 (26-Feb-95)
+ ROM_REGION32_LE( 0x40000, "maincpu", 0 )
+ ROM_LOAD32_WORD("r30_lo_1.01_king_2.5", 0x00000, 0x20000, CRC(9711c158) SHA1(87c60d2097cb437482df11916543f6ef7f18b0d3) )
+ ROM_LOAD32_WORD_SWAP("r30_hi_1.01_king_2.5", 0x00002, 0x20000, CRC(df913abf) SHA1(1bc2ea4b6514bf9fec18f52c264f1440ba7c8c01) )
+ROM_END
+
+ROM_START( tascr30a ) // system version V0.31 (3-May-93), program version 2.20 (23-Apr-93)
+ ROM_REGION32_LE( 0x40000, "maincpu", 0 )
+ ROM_LOAD32_WORD("0.31_l", 0x00000, 0x20000, CRC(d30f81fe) SHA1(81957c7266bedec66b2c14b97008c4261bd67828) )
+ ROM_LOAD32_WORD_SWAP("0.31_h", 0x00002, 0x20000, CRC(aeac3b46) SHA1(a757e0086636dfd3bf78e61cee46c7d92b39d3b9) )
+ROM_END
+
+ROM_START( tascr30b ) // system version V0.31 (3-May-93), program version 2.23 (16-May-93)
+ ROM_REGION32_LE( 0x40000, "maincpu", 0 )
+ ROM_LOAD32_WORD("r30_v2.23_lo", 0x00000, 0x20000, CRC(37251b1a) SHA1(4be768e861002b20ba59a18329f488dba0a0c9bf) )
+ ROM_LOAD32_WORD_SWAP("r30_v2.23_hi", 0x00002, 0x20000, CRC(e546be93) SHA1(943ae65cf97ec4389b9730c6006e805935333072) )
+ROM_END
+
+ROM_START( tascr30g ) // system version V0.31 (3-May-93), program version 2.1 (3-Feb-93)
+ ROM_REGION32_LE( 0x40000, "maincpu", 0 )
+ ROM_LOAD32_WORD("r30_gideon_l", 0x00000, 0x20000, CRC(7041d051) SHA1(266843f375a8621320fc2cd1300775fb7a505c6e) )
+ ROM_LOAD32_WORD_SWAP("r30_gideon_h", 0x00002, 0x20000, CRC(7345ee08) SHA1(9cad608bd32d804468b23196151be0a5f8cee214) )
+ROM_END
+
+} // anonymous namespace
+
+
+
+/*******************************************************************************
+ Drivers
+*******************************************************************************/
+
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
+SYST( 1995, tascr30, 0, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (The King 2.50)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_TIMING )
+SYST( 1993, tascr30a, tascr30, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (The King 2.20)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_TIMING )
+SYST( 1993, tascr30b, tascr30, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (The King 2.23, TM version)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_TIMING ) // competed in several chesscomputer tournaments
+SYST( 1993, tascr30g, tascr30, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (Gideon 3.1, prototype)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_TIMING ) // made in 1993, later released in 2012