From ec7eb50bf6d0a4d91d92d08184402e8c51eef38b Mon Sep 17 00:00:00 2001 From: Devin Acker Date: Wed, 16 Apr 2025 14:08:49 -0400 Subject: [PATCH] =?UTF-8?q?casio/cps200.cpp:=20Added=20a=20skeleton=20Casi?= =?UTF-8?q?o=20CPS-2000=20driver;=20also=20improved=20=C2=B5PD934=20and=20?= =?UTF-8?q?MSM6200=20emulation.=20(#13591)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * machine/msm6200.cpp: Scan matrix on a timer until a change is detected. * sound/upd934g.cpp: Fixed play sample command. * casio/cz1.cpp: Added MSM6200 clock input frequency. New systems marked not working --------------- Casio CPS-2000 [BCM, Devin Acker] --- src/devices/machine/msm6200.cpp | 30 ++- src/devices/machine/msm6200.h | 6 + src/devices/sound/upd934g.cpp | 45 ++-- src/devices/sound/upd934g.h | 15 +- src/emu/xtal.cpp | 2 + src/mame/casio/cps2000.cpp | 402 ++++++++++++++++++++++++++++++++ src/mame/casio/cz1.cpp | 2 +- src/mame/mame.lst | 3 + 8 files changed, 470 insertions(+), 35 deletions(-) create mode 100644 src/mame/casio/cps2000.cpp diff --git a/src/devices/machine/msm6200.cpp b/src/devices/machine/msm6200.cpp index 70e05aa1ddf..ef21d538c1f 100644 --- a/src/devices/machine/msm6200.cpp +++ b/src/devices/machine/msm6200.cpp @@ -21,6 +21,8 @@ msm6200_device::msm6200_device(const machine_config &mconfig, const char *tag, d /**************************************************************************/ void msm6200_device::device_start() { + m_timer = timer_alloc(FUNC(msm6200_device::scan_timer), this); + m_cmd = 0xf; save_item(NAME(m_cmd)); @@ -39,6 +41,18 @@ void msm6200_device::device_reset() std::fill(std::begin(m_last_state), std::end(m_last_state), 0); } +/**************************************************************************/ +TIMER_CALLBACK_MEMBER(msm6200_device::scan_timer) +{ + (++m_row) %= m_keys.size(); + m_key_state = m_keys[m_row].read_safe(0); + if (m_key_state != m_last_state[m_row]) + { + m_irq_cb(1); + m_timer->adjust(attotime::never); + } +} + /**************************************************************************/ void msm6200_device::write(offs_t offset, u8 data) { @@ -60,30 +74,32 @@ void msm6200_device::write(offs_t offset, u8 data) } } if (m_key_state == m_last_state[m_row]) + { m_irq_cb(0); + m_timer->adjust(attotime::zero, 0, attotime::from_ticks(TIMER_RATE, clock())); + } break; case 1: // read velocity m_key_data = m_velocity.read_safe(0x3f); break; - case 2: // next row? - (++m_row) %= m_keys.size(); + case 2: // TODO: what should this one actually be? // the cz1/ht6000 key MCU code outputs the result to port 1 for debugging m_key_data = m_row; break; - case 7: // capture current row? - m_key_state = m_keys[m_row].read_safe(0); - if (m_key_state != m_last_state[m_row]) - m_irq_cb(1); + case 7: // ? + // cz1/ht6000 writes this constantly, cps2000 much less frequently break; - case 8: // init all rows + case 8: // init all rows, start scanning for (int i = 0; i < m_keys.size(); i++) m_last_state[i] = m_keys[i].read_safe(0); + m_irq_cb(0); + m_timer->adjust(attotime::zero, 0, attotime::from_ticks(TIMER_RATE, clock())); break; default: diff --git a/src/devices/machine/msm6200.h b/src/devices/machine/msm6200.h index 758cc929392..584511fb808 100644 --- a/src/devices/machine/msm6200.h +++ b/src/devices/machine/msm6200.h @@ -24,11 +24,17 @@ protected: virtual void device_reset() override ATTR_COLD; private: + static constexpr unsigned TIMER_RATE = 256; // arbitrary + + TIMER_CALLBACK_MEMBER(scan_timer); + optional_ioport_array<38> m_keys; optional_ioport m_velocity; devcb_write_line m_irq_cb; + emu_timer *m_timer; + u8 m_cmd, m_row, m_key_data; u8 m_key_state; u8 m_last_state[38]; diff --git a/src/devices/sound/upd934g.cpp b/src/devices/sound/upd934g.cpp index 1178ef0a930..106d16dec6f 100644 --- a/src/devices/sound/upd934g.cpp +++ b/src/devices/sound/upd934g.cpp @@ -53,7 +53,8 @@ void upd934g_device::device_start() m_stream = stream_alloc(0, 4, 20000); // register for save states - save_pointer(NAME(m_addr), 16); + save_item(NAME(m_addr)); + save_item(NAME(m_valid)); save_item(STRUCT_MEMBER(m_channel, pos)); save_item(STRUCT_MEMBER(m_channel, playing)); @@ -71,8 +72,15 @@ void upd934g_device::device_reset() { m_ready = false; + for (unsigned i = 0; i < 16; i++) + m_addr[i] = m_valid[i] = 0; + for (unsigned i = 0; i < 4; i++) + { + m_channel[i].pos = 0; m_channel[i].playing = -1; + m_channel[i].effect = 0; + } } //------------------------------------------------- @@ -86,14 +94,15 @@ void upd934g_device::sound_stream_update(sound_stream &stream, std::vector(read_byte(m_channel[ch].pos)) * 4; // normal, muted, accented - const double adjust[] = { 0, 0.7, 0.4, 1.0 }; + // TODO: cps2000 regularly sets effect bits to 0 instead of 2 - are these the same? + const double adjust[] = { 0.4, 0.7, 0.4, 1.0 }; raw *= adjust[m_channel[ch].effect]; outputs[ch].put_int(i, raw, 32768 / 64); @@ -118,31 +127,26 @@ void upd934g_device::sound_stream_update(sound_stream &stream, std::vector> 2) & 0x0f; - switch (data >> 6) + // don't play a sample unless we're sure it's actually supposed to play: + // - all models write this with effect=0 to select which sample to set the address of + // - cps2000 writes this with effect=0 to play muted(?) samples + // - cps2000 also writes this with effect=1 and sample=f on boot even though there are only 12 valid samples + if (m_valid[m_sample]) { - case 0: - LOG("CMD STORE ADDRESS sample %x\n", m_sample); - break; - case 1: // normal - case 2: // muted - case 3: // accented - { - const u8 ch = (data & 3) ^ 2; // effective order seems to be "2, 3, 0, 1" - LOG("CMD PLAY sample %x (channel %d, effect %d)\n", m_sample, ch, data >> 6); - m_channel[ch].pos = m_addr[m_sample]; - m_channel[ch].playing = m_sample; - m_channel[ch].effect = data >> 6; - } - break; + const u8 ch = (data & 3) ^ 2; // effective order seems to be "2, 3, 0, 1" + LOG("CMD PLAY sample %x (channel %d, effect %d)\n", m_sample, ch, data >> 6); + m_channel[ch].pos = m_addr[m_sample]; + m_channel[ch].playing = m_sample; + m_channel[ch].effect = data >> 6; } break; case 1: @@ -150,6 +154,7 @@ void upd934g_device::write(offs_t offset, uint8_t data) break; case 2: m_addr[m_sample] = (m_addr[m_sample] & 0x00ff) | (data << 8); + m_valid[m_sample] = 1; LOG(" sample %x address = %04x\n", m_sample, m_addr[m_sample]); break; case 3: diff --git a/src/devices/sound/upd934g.h b/src/devices/sound/upd934g.h index 6652fb62c8e..41bcd038e08 100644 --- a/src/devices/sound/upd934g.h +++ b/src/devices/sound/upd934g.h @@ -27,7 +27,7 @@ public: // construction/destruction upd934g_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - void write(offs_t offset, uint8_t data); + void write(offs_t offset, u8 data); protected: // device-level overrides @@ -39,18 +39,19 @@ protected: private: sound_stream *m_stream; - uint16_t m_addr[16]; + u16 m_addr[16]; + u8 m_valid[16]; struct { - uint16_t pos; - int playing; - int effect; + u16 pos; + s8 playing; + u8 effect; } m_channel[4]; - int m_sample; - bool m_ready; + u8 m_sample; + u8 m_ready; }; // device type definition diff --git a/src/emu/xtal.cpp b/src/emu/xtal.cpp index f4541c40552..62d0370e661 100644 --- a/src/emu/xtal.cpp +++ b/src/emu/xtal.cpp @@ -83,6 +83,7 @@ const double XTAL::known_xtals[] = { 2'250'000, // 2.25_MHz_XTAL Resonator - YM2154 on Yamaha PSR-60 & PSR-70 2'376'000, // 2.376_MHz_XTAL CIT-101 keyboard 2'457'600, // 2.4576_MHz_XTAL Atari ST MFP + 2'470'000, // 2.47_MHz_XTAL CSA2.47MG ceramic oscillator - Casio CZ-1 2'500'000, // 2.5_MHz_XTAL Janken Man units 2'600'000, // 2.6_MHz_XTAL Sharp PC-1500 2'700'000, // 2.7_MHz_XTAL Resonator - YM2154 on Yamaha RX15 @@ -119,6 +120,7 @@ const double XTAL::known_xtals[] = { 4'433'619, // 4.433619_MHz_XTAL PAL color subcarrier (technically 4.43361875mhz) 4'608'000, // 4.608_MHz_XTAL Luxor ABC-77 keyboard (Keytronic custom part #48-300-107 is equivalent) 4'915'200, // 4.9152_MHz_XTAL - + 4'946'800, // 4.9468_MHz_XTAL Casio CPS-2000 4'946'864, // 4.946864_MHz_XTAL Casiotone 8000 4'952'000, // 4.952_MHz_XTAL IGS M036 based mahjong games, for TT5665 sound chip 5'000'000, // 5_MHz_XTAL Mutant Night diff --git a/src/mame/casio/cps2000.cpp b/src/mame/casio/cps2000.cpp new file mode 100644 index 00000000000..26c533aae44 --- /dev/null +++ b/src/mame/casio/cps2000.cpp @@ -0,0 +1,402 @@ +// license:BSD-3-Clause +// copyright-holders:Devin Acker +/* + Skeleton driver for Casio CPS-2000 piano. + + Sound hardware: + - 2x uPD932 consonant-vowel synth + - uPD934 PCM rhythm + - monophonic square wave bass w/ RC envelope and filter +*/ + +#include "emu.h" + +#include "cpu/upd7810/upd7810.h" +#include "machine/msm6200.h" +#include "sound/dac.h" +#include "sound/flt_rc.h" +#include "sound/upd934g.h" +#include "sound/va_eg.h" +#include "sound/va_vca.h" + +#include "speaker.h" + +namespace { + +class cps2000_state : public driver_device +{ +public: + cps2000_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_kbd(*this, "kbd") + , m_bass_env(*this, "bass_env") + , m_pcm(*this, "pcm") + , m_keys(*this, "KC%u", 0) + { } + + void cps2000(machine_config &config); + + void keys_w(ioport_value val) { m_key_sel = val; } + ioport_value keys_r(); + + void bass_w(ioport_value val); + +protected: + virtual void machine_start() override ATTR_COLD; + virtual void machine_reset() override ATTR_COLD; + +private: + void maincpu_map(address_map &map) ATTR_COLD; + + void io_w(offs_t offset, u8 data); + + required_device m_maincpu; + required_device m_kbd; + required_device m_bass_env; + required_device m_pcm; + + required_ioport_array<5> m_keys; + + ioport_value m_key_sel; + + u8 m_932a_regs[256]; + u8 m_932b_regs[256]; +}; + +/**************************************************************************/ +static INPUT_PORTS_START(cps2000) + PORT_START("PA") + PORT_BIT( 0x07, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(FUNC(cps2000_state::keys_w)) + PORT_BIT( 0xf8, IP_ACTIVE_HIGH, IPT_OUTPUT ) // LED outputs + + PORT_START("PB") + PORT_BIT( 0x3f, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(FUNC(cps2000_state::keys_r)) + PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_OUTPUT ) // LED outputs + + PORT_START("PC") + PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_OUTPUT ) // LED outputs + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_CUSTOM ) // 934 busy + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(FUNC(cps2000_state::bass_w)) + PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("kbd:KI1") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G7") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F#7") + + PORT_START("kbd:KI2") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F7") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E7") + + PORT_START("kbd:KI3") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D#7") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D7") + + PORT_START("kbd:KI4") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C#7") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C7") + + PORT_START("kbd:KI5") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B6") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A#6") + + PORT_START("kbd:KI6") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A6") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G#6") + + PORT_START("kbd:KI7") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G6") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F#6") + + PORT_START("kbd:KI8") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F6") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E6") + + PORT_START("kbd:KI9") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D#6") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D6") + + PORT_START("kbd:KI10") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C#6") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C6") + + PORT_START("kbd:KI11") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B5") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A#5") + + PORT_START("kbd:KI12") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A5") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G#5") + + PORT_START("kbd:KI13") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G5") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F#5") + + PORT_START("kbd:KI14") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F5") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E5") + + PORT_START("kbd:KI15") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D#5") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D5") + + PORT_START("kbd:KI16") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C#5") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C5") + + PORT_START("kbd:KI17") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B4") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A#4") + + PORT_START("kbd:KI18") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A4") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G#4") + + PORT_START("kbd:KI19") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G4") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F#4") + + PORT_START("kbd:KI20") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F4") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E4") + + PORT_START("kbd:KI21") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D#4") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D4") + + PORT_START("kbd:KI22") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C#4") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C4") + + PORT_START("kbd:KI23") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B3") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A#3") + + PORT_START("kbd:KI24") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A3") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G#3") + + PORT_START("kbd:KI25") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G3") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F#3") + + PORT_START("kbd:KI26") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F3") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E3") + + PORT_START("kbd:KI27") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D#3") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D3") + + PORT_START("kbd:KI28") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C#3") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C3") + + PORT_START("kbd:KI29") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B2") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A#2") + + PORT_START("kbd:KI30") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A2") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G#2") + + PORT_START("kbd:KI31") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G2") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F#2") + + PORT_START("kbd:KI32") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F2") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E2") + + PORT_START("kbd:KI33") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D#2") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D2") + + PORT_START("kbd:KI34") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C#2") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C2") + + PORT_START("kbd:KI35") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B1") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A#1") + + PORT_START("kbd:KI36") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A1") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G#1") + + PORT_START("kbd:KI37") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G1") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F#1") + + PORT_START("kbd:KI38") + PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F1") + PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E1") + + PORT_START("kbd:VELOCITY") + PORT_BIT(0x3f, 0x3f, IPT_POSITIONAL_V) PORT_NAME("Key Velocity") PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_CENTERDELTA(0) PORT_CODE_DEC(JOYCODE_X_LEFT_SWITCH) PORT_CODE_INC(JOYCODE_X_RIGHT_SWITCH) + + PORT_START("AN0") + PORT_BIT(0xff, 0x80, IPT_POSITIONAL_V) PORT_NAME("Tempo") PORT_SENSITIVITY(10) PORT_KEYDELTA(5) PORT_CENTERDELTA(0) PORT_CODE_DEC(JOYCODE_Y_DOWN_SWITCH) PORT_CODE_INC(JOYCODE_Y_UP_SWITCH) + + PORT_START("AN1") + PORT_BIT(0xff, 0x80, IPT_POSITIONAL_H) PORT_NAME("Tuning") PORT_SENSITIVITY(10) PORT_KEYDELTA(5) PORT_CENTERDELTA(0) PORT_PLAYER(2) PORT_CODE_DEC(JOYCODE_X_LEFT_SWITCH) PORT_CODE_INC(JOYCODE_X_RIGHT_SWITCH) + + PORT_START("KC0") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave Unison") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Sustain") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Chorus") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Fingered") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Casio Chord On") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Casio Chord Off") + PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("KC1") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Start / Stop") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Synchro") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Intro / Fill-In") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Super Accomp") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Memory") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Variation") + PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("KC2") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Tone 1") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Tone 2") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Tone 3") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Tone 4") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Rhythm Select") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Touch Response") + PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("KC3") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Tone 5") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Tone 6") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Tone 7") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Rhythm 1") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Rhythm 2") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Rhythm 3") + PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("KC4") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Tone Select") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Sustain Pedal") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Rhythm 4") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Rhythm 5") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Rhythm 6") + PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_UNUSED ) + +INPUT_PORTS_END + +/**************************************************************************/ +void cps2000_state::maincpu_map(address_map &map) +{ + map(0x0000, 0x7fff).rom(); + map(0x8000, 0xbfff).r(m_kbd, FUNC(msm6200_device::read)); + map(0x8000, 0xffff).w(FUNC(cps2000_state::io_w)); +} + +/**************************************************************************/ +void cps2000_state::cps2000(machine_config &config) +{ + UPD78C10(config, m_maincpu, 10'000'000); + m_maincpu->set_addrmap(AS_PROGRAM, &cps2000_state::maincpu_map); + m_maincpu->pa_out_cb().set_ioport("PA"); + m_maincpu->pb_in_cb().set_ioport("PB"); + m_maincpu->pb_out_cb().set_ioport("PB"); + m_maincpu->pc_in_cb().set_ioport("PC"); + m_maincpu->pc_out_cb().set_ioport("PC"); + m_maincpu->an0_func().set_ioport("AN0"); + m_maincpu->an1_func().set_ioport("AN1"); + + MSM6200(config, m_kbd, 4.9468_MHz_XTAL); + m_kbd->irq_cb().set_inputline(m_maincpu, UPD7810_INTF1); + + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + + // UPD932(config, "upd932a", 4.9468_MHz_XTAL); + // UPD932(config, "upd932b", 4.9468_MHz_XTAL); + + DAC_1BIT(config, "bass").add_route(0, "bass_vca", 1.0); + m_maincpu->co0_func().set("bass", FUNC(dac_1bit_device::write)); + + VA_RC_EG(config, m_bass_env).set_c(CAP_U(3.3)).add_route(0, "bass_vca", 1.0 / 5); + VA_VCA(config, "bass_vca").configure_streaming_cv(true).add_route(0, "bass_rc1", 1.0); + + FILTER_RC(config, "bass_rc1").set_lowpass(RES_K(47), CAP_N(47)).add_route(0, "bass_rc2", 1.0); + FILTER_RC(config, "bass_rc2").set_lowpass(RES_K(22), CAP_N(47)) + .add_route(0, "lspeaker", 0.25).add_route(0, "rspeaker", 0.25); + + UPD934G(config, m_pcm, 4.9468_MHz_XTAL / 4); + m_pcm->add_route(0, "lspeaker", 0.25); + m_pcm->add_route(0, "rspeaker", 0.125); + m_pcm->add_route(1, "lspeaker", 0.25); + m_pcm->add_route(1, "rspeaker", 0.125); + m_pcm->add_route(2, "lspeaker", 0.125); + m_pcm->add_route(2, "rspeaker", 0.25); + m_pcm->add_route(3, "lspeaker", 0.125); + m_pcm->add_route(3, "rspeaker", 0.25); +} + +/**************************************************************************/ +void cps2000_state::machine_start() +{ + m_key_sel = 0; + + std::fill(std::begin(m_932a_regs), std::end(m_932a_regs), 0); + std::fill(std::begin(m_932b_regs), std::end(m_932b_regs), 0); + + save_item(NAME(m_key_sel)); + save_item(NAME(m_932a_regs)); + save_item(NAME(m_932b_regs)); +} + +/**************************************************************************/ +void cps2000_state::machine_reset() +{ +} + +/**************************************************************************/ +ioport_value cps2000_state::keys_r() +{ + if (m_key_sel < 5) + return m_keys[m_key_sel]->read(); + + return 0xff; +} + +/**************************************************************************/ +void cps2000_state::bass_w(ioport_value val) +{ + if (val) + m_bass_env->set_r(RES_R(270)).set_target_v(5.0); + else + m_bass_env->set_r(RES_K(22)).set_target_v(0.0); +} + +/**************************************************************************/ +void cps2000_state::io_w(offs_t offset, u8 data) +{ + if (!BIT(offset, 14)) + m_kbd->write(offset, data); + if (!BIT(offset, 13)) + m_pcm->write(offset >> 8, offset); + if (!BIT(offset, 12)) + m_932a_regs[offset & 0xff] = data; + if (!BIT(offset, 11)) + m_932b_regs[offset & 0xff] = data; +} + +/**************************************************************************/ +ROM_START( cps2000 ) + ROM_REGION(0x8000, "maincpu", 0) + ROM_LOAD( "hn613256p-db6.bin", 0x0000, 0x8000, CRC(92b68074) SHA1(eda13d59a15077b06d95004b5f2a2a8432109893) ) + + ROM_REGION(0x10000, "pcm", 0) + ROM_LOAD( "hn613256p-da5.bin", 0x0000, 0x8000, CRC(63d6dd54) SHA1(231ffb6a4cc113133accd19dd9ed1e5165e3837e) ) +ROM_END + +} // anonymous namespace + +SYST( 1986, cps2000, 0, 0, cps2000, cps2000, cps2000_state, empty_init, "Casio", "CPS-2000", MACHINE_NOT_WORKING ) diff --git a/src/mame/casio/cz1.cpp b/src/mame/casio/cz1.cpp index 1f4f6e1963d..d43b02c289a 100644 --- a/src/mame/casio/cz1.cpp +++ b/src/mame/casio/cz1.cpp @@ -910,7 +910,7 @@ void cz1_state::cz1(machine_config &config) m_mcu->t0_in_cb().set(FUNC(cz1_state::sync49_r)); m_mcu->t1_in_cb().set([this] () { return BIT(m_main_port[2], 7); }); - MSM6200(config, "kbd").irq_cb().set_inputline(m_mcu, MCS48_INPUT_IRQ); + MSM6200(config, "kbd", 2.47_MHz_XTAL).irq_cb().set_inputline(m_mcu, MCS48_INPUT_IRQ); // CSA2.47MG ceramic oscillator config.set_default_layout(layout_cz1); } diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 0fa482ff5a4..989432c7ec9 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -16189,6 +16189,9 @@ casloopy cfx9850 cfx9850gb +@source:casio/cps2000.cpp +cps2000 + @source:casio/ct8000.cpp ct8000 ctfk1