mirror of
https://github.com/holub/mame
synced 2025-04-19 23:12:11 +03:00
risc2500/tasc: fixed high pitched sound problem
This commit is contained in:
parent
4d532a9cfa
commit
9bb192141c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user