risc2500/tasc: fixed high pitched sound problem

This commit is contained in:
hap 2021-04-22 22:51:45 +02:00
parent 4d532a9cfa
commit 9bb192141c
5 changed files with 208 additions and 69 deletions

View File

@ -497,10 +497,13 @@ void arm_cpu_device::device_start()
{
m_program = &space(AS_PROGRAM);
if(m_program->endianness() == ENDIANNESS_LITTLE) {
if(m_program->endianness() == ENDIANNESS_LITTLE)
{
m_program->cache(m_cachele);
m_pr32 = [this](offs_t address) -> u32 { return m_cachele.read_dword(address); };
} else {
}
else
{
m_program->cache(m_cachebe);
m_pr32 = [this](offs_t address) -> u32 { return m_cachebe.read_dword(address); };
}
@ -824,7 +827,7 @@ void arm_cpu_device::HandleALU( uint32_t insn )
{
op2 = decodeShift(insn, (insn & INSN_S) ? &sc : nullptr);
if (!(insn & INSN_S))
if (!(insn & INSN_S))
sc=0;
}

View File

@ -10,11 +10,13 @@ The SmartBoard can detect which piece is present on a specific square, more
info on the technology used in the piece recognition system can be found in
the US patent 5,129,654
SB30 (81 LEDs) is "SmartBoard I"
SB20 (64 LEDs) is "SmartBoard II"
SmartBoard I is SB30 (81 LEDs, analog chesspieces)
SmartBoard II is SB20 (64 LEDs, digital chesspieces)
SmartBoard III is SB30 again, but digital
SB20 is not emulated. It's on different hardware, with embedded CPU to reduce
I/O overhead. Note, SB20 is not compatible with old versions of Tasc R30.
SB20 and the newer SB30 are not emulated. They're on different hardware, with
embedded CPU to reduce I/O overhead. Note, These are not compatible with old
versions of Tasc R30.
******************************************************************************/

View File

@ -5,13 +5,13 @@
Mephisto Berlin 68000 / Berlin Professional 68020
Berlin Professional has the same engine as Mephisto Genius.
TODO:
- does it have ROM waitstates like mephisto_modular?
Undocumented buttons:
- holding ENTER and LEFT cursor on boot runs diagnostics
- holding CLEAR on boot clears battery backed RAM
TODO:
- does it have ROM waitstates like mephisto_modular?
******************************************************************************/
#include "emu.h"

View File

@ -5,34 +5,47 @@
Saitek RISC 2500, Mephisto Montreux
The chess engine is also compatible with Tasc's The ChessMachine software.
The hardware+software appears to have been subcontracted to Tasc. It has similarities
with Tasc R30, PCB label and Montreux repair manual schematics footnotes say TASC23C.
The hardware+software appears to have been subcontracted to Tasc. It has
similarities with Tasc R30.
To make sure it continues the game at next power-on, press the OFF button before
exiting MAME. If nvram is broken somehow, boot with the BACK button held down.
Hardware notes:
- PCB label: TASC23C
- ARM2 CPU(VY86C010) @ 14.16MHz
- 128KB ROM, 128KB RAM*
- SED1520, custom LCD screen
- 8*8 chessboard buttons, 16 leds, piezo
*: Sold with 128KB RAM by default. This can be easily increased up to 2MB
by the user(chesscomputer owner, but also the MAME user in this case).
The manual also says that RAM is expandable.
According to Saitek's repair manual, there is a GAL and a clock frequency
divider chip, ROM access goes through it. This allows reading from slow EPROM
while the chess engine resides in faster RAM. The piezo output routine is
also in ROM, it would be way too high-pitched at full speed.
Undocumented buttons:
- hold LEFT+RIGHT on boot to start the QC TestMode
- hold UP+DOWN on boot to start the TestMode
TODO:
- bootrom disable timer shouldn't be needed, real ARM has already fetched the next opcode
- Sound is too short and high pitched, better when you underclock the cpu.
Is cpu cycle timing wrong? I suspect conditional branch timing due to cache miss
(pipeline has to refill). The delay loop between writing to the speaker is simply:
SUBS R2, R2, #$1, BNE $2000cd8
- more accurate dynamic cpu clock divider (without the cost of emulation speed)
******************************************************************************/
#include "emu.h"
#include "cpu/arm/arm.h"
#include "machine/ram.h"
#include "machine/nvram.h"
#include "machine/ram.h"
#include "machine/sensorboard.h"
#include "machine/timer.h"
#include "video/sed1520.h"
#include "sound/dac.h"
#include "sound/spkrdev.h"
#include "emupal.h"
#include "screen.h"
@ -54,7 +67,7 @@ public:
, m_ram(*this, "ram")
, m_nvram(*this, "nvram")
, m_disable_bootrom(*this, "disable_bootrom")
, m_dac(*this, "dac")
, m_speaker(*this, "speaker")
, m_lcdc(*this, "lcdc")
, m_board(*this, "board")
, m_inputs(*this, "P%u", 0)
@ -79,7 +92,7 @@ private:
required_device<ram_device> m_ram;
required_device<nvram_device> m_nvram;
required_device<timer_device> m_disable_bootrom;
required_device<dac_byte_interface> m_dac;
required_device<speaker_sound_device> m_speaker;
required_device<sed1520_device> m_lcdc;
required_device<sensorboard_device> m_board;
required_ioport_array<8> m_inputs;
@ -93,6 +106,7 @@ private:
SED1520_UPDATE_CB(screen_update_cb);
u32 input_r();
void control_w(u32 data);
u32 rom_r(offs_t offset);
void power_off();
u32 disable_boot_rom_r();
@ -100,8 +114,10 @@ private:
TIMER_DEVICE_CALLBACK_MEMBER(disable_bootrom) { install_bootrom(false); }
bool m_bootrom_enabled = false;
u32 m_control = 0;
bool m_power = false;
u32 m_control = 0;
u32 m_prev_pc = 0;
u64 m_prev_cycle = 0;
};
void risc2500_state::machine_start()
@ -116,6 +132,8 @@ void risc2500_state::machine_start()
save_item(NAME(m_power));
save_item(NAME(m_bootrom_enabled));
save_item(NAME(m_control));
save_item(NAME(m_prev_pc));
save_item(NAME(m_prev_cycle));
}
void risc2500_state::machine_reset()
@ -124,6 +142,8 @@ void risc2500_state::machine_reset()
m_power = true;
m_control = 0;
m_prev_pc = m_maincpu->pc();
m_prev_cycle = m_maincpu->total_cycles();
}
@ -190,10 +210,10 @@ SED1520_UPDATE_CB(risc2500_state::screen_update_cb)
void risc2500_state::install_bootrom(bool enable)
{
address_space &program = m_maincpu->space(AS_PROGRAM);
program.unmap_readwrite(0, std::max(m_rom.bytes(), size_t(m_ram->size()) - 1));
program.unmap_readwrite(0, std::max(m_rom.bytes(), size_t(m_ram->size())) - 1);
if (enable)
program.install_rom(0, m_rom.bytes() - 1, m_rom);
program.install_read_handler(0, m_rom.bytes() - 1, read32sm_delegate(*this, FUNC(risc2500_state::rom_r)));
else
program.install_ram(0, m_ram->size() - 1, m_ram->pointer());
@ -238,7 +258,7 @@ void risc2500_state::power_off()
u32 risc2500_state::input_r()
{
u32 data = 0;
u32 data = (u32)m_lcdc->status_read() << 16;
for (int i = 0; i < 8; i++)
{
@ -249,7 +269,10 @@ u32 risc2500_state::input_r()
}
}
return data | ((u32)m_lcdc->status_read() << 16);
if (!machine().side_effects_disabled())
m_maincpu->set_input_line(ARM_FIRQ_LINE, CLEAR_LINE);
return data;
}
void risc2500_state::control_w(u32 data)
@ -278,7 +301,7 @@ void risc2500_state::control_w(u32 data)
}
// speaker
m_dac->write(data >> 28 & 3);
m_speaker->level_w(data >> 28 & 3);
// power-off
if (BIT(m_control & ~data, 24))
@ -287,6 +310,38 @@ void risc2500_state::control_w(u32 data)
m_control = data;
}
u32 risc2500_state::rom_r(offs_t offset)
{
if (!machine().side_effects_disabled())
{
// handle dynamic cpu clock divider when accessing rom
u64 cur_cycle = m_maincpu->total_cycles();
u64 prev_cycle = m_prev_cycle;
s64 diff = cur_cycle - prev_cycle;
u32 pc = m_maincpu->pc();
u32 prev_pc = m_prev_pc;
m_prev_pc = pc;
if (diff >= 0)
{
static constexpr int arm_branch_cycles = 3;
static constexpr int arm_max_cycles = 17; // block data transfer
static constexpr int divider = -8 + 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 - 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();
}
return m_rom[offset];
}
/******************************************************************************
@ -297,7 +352,7 @@ void risc2500_state::risc2500_mem(address_map &map)
{
map(0x01800000, 0x01800003).r(FUNC(risc2500_state::disable_boot_rom_r));
map(0x01000000, 0x01000003).rw(FUNC(risc2500_state::input_r), FUNC(risc2500_state::control_w));
map(0x02000000, 0x0203ffff).rom().region("maincpu", 0);
map(0x02000000, 0x0203ffff).r(FUNC(risc2500_state::rom_r));
}
@ -353,15 +408,17 @@ INPUT_PORTS_END
void risc2500_state::risc2500(machine_config &config)
{
/* basic machine hardware */
ARM(config, m_maincpu, 28.322_MHz_XTAL / 2); // VY86C010
ARM(config, m_maincpu, 28.322_MHz_XTAL / 2);
m_maincpu->set_addrmap(AS_PROGRAM, &risc2500_state::risc2500_mem);
m_maincpu->set_copro_type(arm_cpu_device::copro_type::VL86C020);
m_maincpu->set_periodic_int(FUNC(risc2500_state::irq1_line_hold), attotime::from_hz(32.768_kHz_XTAL/128)); // 256Hz
const attotime irq_period = attotime::from_hz(32.768_kHz_XTAL / 128); // 256Hz
m_maincpu->set_periodic_int(FUNC(risc2500_state::irq1_line_assert), irq_period);
TIMER(config, "disable_bootrom").configure_generic(FUNC(risc2500_state::disable_bootrom));
RAM(config, m_ram).set_extra_options("128K, 256K, 512K, 1M, 2M");
m_ram->set_default_size("2M");
m_ram->set_default_size("128K");
m_ram->set_default_value(0);
NVRAM(config, "nvram", nvram_device::DEFAULT_NONE);
@ -389,8 +446,10 @@ void risc2500_state::risc2500(machine_config &config)
m_lcdc->set_screen_update_cb(FUNC(risc2500_state::screen_update_cb));
/* sound hardware */
SPEAKER(config, "speaker").front_center();
DAC_2BIT_BINARY_WEIGHTED_ONES_COMPLEMENT(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25);
SPEAKER(config, "mono").front_center();
static const double speaker_levels[4] = { 0.0, 1.0, -1.0, 0.0 };
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
m_speaker->set_levels(4, speaker_levels);
}
@ -423,7 +482,7 @@ ROM_END
******************************************************************************/
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
CONS( 1992, risc2500, 0, 0, risc2500, risc2500, risc2500_state, empty_init, "Saitek / Tasc", "Kasparov RISC 2500 (v1.04)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_IMPERFECT_SOUND )
CONS( 1992, risc2500a, risc2500, 0, risc2500, risc2500, risc2500_state, empty_init, "Saitek / Tasc", "Kasparov RISC 2500 (v1.03)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_IMPERFECT_SOUND )
CONS( 1992, risc2500, 0, 0, risc2500, risc2500, risc2500_state, empty_init, "Saitek / Tasc", "Kasparov RISC 2500 (v1.04)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
CONS( 1992, risc2500a, risc2500, 0, risc2500, risc2500, risc2500_state, empty_init, "Saitek / Tasc", "Kasparov RISC 2500 (v1.03)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
CONS( 1995, montreux, 0, 0, risc2500, risc2500, risc2500_state, empty_init, "Saitek / Tasc", "Mephisto Montreux", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_IMPERFECT_SOUND ) // after Saitek bought Hegener + Glaser
CONS( 1995, montreux, 0, 0, risc2500, risc2500, risc2500_state, empty_init, "Saitek / Tasc", "Mephisto Montreux", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK ) // after Saitek bought Hegener + Glaser

View File

@ -8,6 +8,9 @@ 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 2.1(internally: Rebel 2.01) is not.
WARNING: Don't configure more than 512KB RAM for R30 The King 2.50, it will still
be playable but will actually use less than 512KB RAM and become weaker.
The King 2.23 version was not released to the public. It has an opening book
meant for chesscomputer competitions.
For more information, see: http://chesseval.com/ChessEvalJournal/R30v223.htm
@ -24,6 +27,14 @@ R40 hardware notes:
- +512KB extra RAM piggybacked
- rest same as R30
EPROMs are interchangable between R30 and R40, with some limitations with
The King 2.50 (see below).
Regarding RAM: The King 2.2x will work fine with RAM expanded up to 8MB.
The King 2.50 appears to be protected against RAM upgrades though, and will
limit itself to 128KB if it detects a non-default amount of RAM. Gideon doesn't
use RAM above 128KB either, perhaps the R30 prototype only had 128KB RAM.
Documentation for the Toshiba chips is hard to find, but similar chips exist:
T7778 is equivalent to T6A39, T7900 is equivalent to T6A40.
@ -39,7 +50,8 @@ notes:
TODO:
- bootrom disable timer shouldn't be needed, real ARM has already fetched the next opcode
- sound is too high pitched, same problem as in risc2500
- more accurate dynamic cpu clock divider (same problem as in saitek_risc2500.cpp),
sound pitch is correct now though
******************************************************************************/
@ -48,10 +60,11 @@ TODO:
#include "cpu/arm/arm.h"
#include "machine/bankdev.h"
#include "machine/nvram.h"
#include "machine/ram.h"
#include "machine/smartboard.h"
#include "machine/timer.h"
#include "video/t6963c.h"
#include "sound/dac.h"
#include "sound/spkrdev.h"
#include "speaker.h"
@ -68,10 +81,10 @@ public:
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_rom(*this, "maincpu"),
m_mainram(*this, "mainram"),
m_ram(*this, "ram"),
m_lcd(*this, "lcd"),
m_smartboard(*this, "smartboard"),
m_dac(*this, "dac"),
m_speaker(*this, "speaker"),
m_disable_bootrom(*this, "disable_bootrom"),
m_inputs(*this, "IN.%u", 0U),
m_out_leds(*this, "pled%u", 0U)
@ -79,19 +92,21 @@ public:
void tasc(machine_config &config);
DECLARE_INPUT_CHANGED_MEMBER(switch_cpu_freq) { set_cpu_freq(); }
protected:
virtual void machine_start() override;
virtual void machine_reset() override { install_bootrom(true); }
virtual void machine_reset() override;
virtual void device_post_load() override { install_bootrom(m_bootrom_enabled); }
private:
// devices/pointers
required_device<arm_cpu_device> m_maincpu;
required_region_ptr<u32> m_rom;
required_shared_ptr<u32> m_mainram;
required_device<ram_device> m_ram;
required_device<lm24014h_device> m_lcd;
required_device<tasc_sb30_device> m_smartboard;
required_device<dac_byte_interface> m_dac;
required_device<speaker_sound_device> m_speaker;
required_device<timer_device> m_disable_bootrom;
required_ioport_array<4> m_inputs;
output_finder<2> m_out_leds;
@ -101,14 +116,17 @@ private:
// I/O handlers
u32 input_r();
u32 rom_r(offs_t offset);
void control_w(offs_t offset, u32 data, u32 mem_mask = ~0);
void set_cpu_freq();
void install_bootrom(bool enable);
void disable_bootrom_next();
TIMER_DEVICE_CALLBACK_MEMBER(disable_bootrom) { install_bootrom(false); }
bool m_bootrom_enabled = false;
u32 m_control = 0;
u32 m_prev_pc = 0;
u64 m_prev_cycle = 0;
};
void tasc_state::machine_start()
@ -117,6 +135,23 @@ void tasc_state::machine_start()
save_item(NAME(m_bootrom_enabled));
save_item(NAME(m_control));
save_item(NAME(m_prev_pc));
save_item(NAME(m_prev_cycle));
}
void tasc_state::machine_reset()
{
install_bootrom(true);
set_cpu_freq();
m_prev_pc = m_maincpu->pc();
m_prev_cycle = m_maincpu->total_cycles();
}
void tasc_state::set_cpu_freq()
{
// R30 is 30MHz, R40 is 40MHz
m_maincpu->set_unscaled_clock((ioport("FAKE")->read() & 1) ? 40_MHz_XTAL : 30_MHz_XTAL);
}
@ -125,34 +160,30 @@ void tasc_state::machine_start()
I/O
******************************************************************************/
// bootrom bankswitch
void tasc_state::install_bootrom(bool enable)
{
address_space &program = m_maincpu->space(AS_PROGRAM);
program.unmap_readwrite(0, std::max(m_rom.bytes(), m_mainram.bytes()) - 1);
program.unmap_readwrite(0, std::max(m_rom.bytes(), size_t(m_ram->size())) - 1);
// bootrom bankswitch
if (enable)
program.install_rom(0, m_rom.bytes() - 1, m_rom);
program.install_read_handler(0, m_rom.bytes() - 1, read32sm_delegate(*this, FUNC(tasc_state::rom_r)));
else
program.install_ram(0, m_mainram.bytes() - 1, m_mainram);
program.install_ram(0, m_ram->size() - 1, m_ram->pointer());
m_bootrom_enabled = enable;
}
void tasc_state::disable_bootrom_next()
{
// disconnect bootrom from the bus after next opcode
if (m_bootrom_enabled && !m_disable_bootrom->enabled() && !machine().side_effects_disabled())
m_disable_bootrom->adjust(m_maincpu->cycles_to_attotime(5));
}
// main I/O
u32 tasc_state::input_r()
{
disable_bootrom_next();
if (!machine().side_effects_disabled())
{
// disconnect bootrom from the bus after next opcode
if (m_bootrom_enabled && !m_disable_bootrom->enabled())
m_disable_bootrom->adjust(m_maincpu->cycles_to_attotime(5));
m_maincpu->set_input_line(ARM_FIRQ_LINE, CLEAR_LINE);
}
// read chessboard
u32 data = m_smartboard->data_r();
@ -181,12 +212,44 @@ void tasc_state::control_w(offs_t offset, u32 data, u32 mem_mask)
{
m_out_leds[0] = BIT(data, 0);
m_out_leds[1] = BIT(data, 1);
m_dac->write((data >> 2) & 3);
m_speaker->level_w((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
u64 cur_cycle = m_maincpu->total_cycles();
u64 prev_cycle = m_prev_cycle;
s64 diff = cur_cycle - prev_cycle;
u32 pc = m_maincpu->pc();
u32 prev_pc = m_prev_pc;
m_prev_pc = pc;
if (diff >= 0)
{
static constexpr int arm_branch_cycles = 3;
static constexpr int arm_max_cycles = 17; // block data 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 - 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();
}
return m_rom[offset];
}
/******************************************************************************
@ -195,9 +258,8 @@ void tasc_state::control_w(offs_t offset, u32 data, u32 mem_mask)
void tasc_state::main_map(address_map &map)
{
map(0x00000000, 0x0007ffff).ram().share("mainram");
map(0x01000000, 0x01000003).rw(FUNC(tasc_state::input_r), FUNC(tasc_state::control_w));
map(0x02000000, 0x0203ffff).rom().region("maincpu", 0);
map(0x02000000, 0x0203ffff).r(FUNC(tasc_state::rom_r));
map(0x03000000, 0x0307ffff).m("nvram_map", FUNC(address_map_bank_device::amap8)).umask32(0x000000ff);
}
@ -233,6 +295,11 @@ static INPUT_PORTS_START( tasc )
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_ENTER) 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("FAKE")
PORT_CONFNAME( 0x01, 0x00, "CPU Frequency" ) PORT_CHANGED_MEMBER(DEVICE_SELF, tasc_state, switch_cpu_freq, 0)
PORT_CONFSETTING( 0x00, "30MHz (R30)" )
PORT_CONFSETTING( 0x01, "40MHz (R40)" )
INPUT_PORTS_END
@ -247,10 +314,16 @@ void tasc_state::tasc(machine_config &config)
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);
m_maincpu->set_periodic_int(FUNC(tasc_state::irq1_line_hold), attotime::from_hz(32.768_kHz_XTAL/128)); // 256Hz
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);
TIMER(config, "disable_bootrom").configure_generic(FUNC(tasc_state::disable_bootrom));
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);
ADDRESS_MAP_BANK(config, "nvram_map").set_map(&tasc_state::nvram_map).set_options(ENDIANNESS_LITTLE, 8, 17);
@ -264,8 +337,10 @@ void tasc_state::tasc(machine_config &config)
config.set_default_layout(layout_tascr30);
/* sound hardware */
SPEAKER(config, "speaker").front_center();
DAC_2BIT_BINARY_WEIGHTED_ONES_COMPLEMENT(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25);
SPEAKER(config, "mono").front_center();
static const double speaker_levels[4] = { 0.0, 1.0, -1.0, 0.0 };
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
m_speaker->set_levels(4, speaker_levels);
}
@ -307,7 +382,7 @@ ROM_END
******************************************************************************/
// YEAR NAME PARENT CMP MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
CONS( 1995, tascr30, 0, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (The King 2.50)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_IMPERFECT_SOUND )
CONS( 1993, tascr30a, tascr30, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (The King 2.20)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_IMPERFECT_SOUND )
CONS( 1993, tascr30b, tascr30, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (The King 2.23, TM version)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_IMPERFECT_SOUND ) // competed in several chesscomputer tournaments
CONS( 1993, tascr30g, tascr30, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (Gideon 2.1, prototype)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_IMPERFECT_SOUND ) // made in 1993, later released in 2012
CONS( 1995, tascr30, 0, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (The King 2.50)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
CONS( 1993, tascr30a, tascr30, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (The King 2.20)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
CONS( 1993, tascr30b, tascr30, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (The King 2.23, TM version)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK ) // competed in several chesscomputer tournaments
CONS( 1993, tascr30g, tascr30, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (Gideon 2.1, prototype)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK ) // made in 1993, later released in 2012