From 8962638b779165a93817553a4d75cd15dcabecf6 Mon Sep 17 00:00:00 2001 From: Devin Acker Date: Wed, 13 Oct 2021 03:35:00 -0400 Subject: Casio CTK-551 [Daivn Acker] * New machine marked as NOT_WORKING ---------------------------------- Casio CTK-551 [Devin Acker] --- scripts/src/cpu.lua | 16 +- scripts/src/machine.lua | 16 ++ scripts/target/mame/mess.lua | 2 + src/devices/cpu/h8/gt913.cpp | 170 ++++++++++++++++++ src/devices/cpu/h8/gt913.h | 82 +++++++++ src/devices/cpu/h8/gt913.lst | 140 +++++++++++++++ src/devices/cpu/h8/gt913d.cpp | 17 ++ src/devices/cpu/h8/gt913d.h | 28 +++ src/devices/cpu/h8/h8.cpp | 93 +++++++--- src/devices/cpu/h8/h8.h | 3 +- src/devices/cpu/h8/h8.lst | 15 +- src/devices/cpu/h8/h8_intc.cpp | 29 +++- src/devices/cpu/h8/h8_intc.h | 15 +- src/devices/cpu/h8/h8_port.cpp | 5 + src/devices/cpu/h8/h8_port.h | 1 + src/devices/cpu/h8/h8d.cpp | 16 ++ src/devices/cpu/h8/h8d.h | 4 + src/devices/cpu/h8/h8make.py | 12 +- src/devices/machine/gt913_io.cpp | 156 +++++++++++++++++ src/devices/machine/gt913_io.h | 74 ++++++++ src/devices/machine/gt913_kbd.cpp | 104 +++++++++++ src/devices/machine/gt913_kbd.h | 62 +++++++ src/devices/machine/gt913_snd.cpp | 167 ++++++++++++++++++ src/devices/machine/gt913_snd.h | 45 +++++ src/mame/drivers/ctk551.cpp | 356 ++++++++++++++++++++++++++++++++++++++ src/mame/mame.lst | 3 + src/mame/mess.flt | 1 + 27 files changed, 1585 insertions(+), 47 deletions(-) create mode 100644 src/devices/cpu/h8/gt913.cpp create mode 100644 src/devices/cpu/h8/gt913.h create mode 100644 src/devices/cpu/h8/gt913.lst create mode 100644 src/devices/cpu/h8/gt913d.cpp create mode 100644 src/devices/cpu/h8/gt913d.h create mode 100644 src/devices/machine/gt913_io.cpp create mode 100644 src/devices/machine/gt913_io.h create mode 100644 src/devices/machine/gt913_kbd.cpp create mode 100644 src/devices/machine/gt913_kbd.h create mode 100644 src/devices/machine/gt913_snd.cpp create mode 100644 src/devices/machine/gt913_snd.h create mode 100644 src/mame/drivers/ctk551.cpp diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 4ceff62e718..9c612457313 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -700,6 +700,8 @@ if CPUS["H8"] then MAME_DIR .. "src/devices/cpu/h8/h8_sci.h", MAME_DIR .. "src/devices/cpu/h8/h8_watchdog.cpp", MAME_DIR .. "src/devices/cpu/h8/h8_watchdog.h", + MAME_DIR .. "src/devices/cpu/h8/gt913.cpp", + MAME_DIR .. "src/devices/cpu/h8/gt913.h", } dependency { @@ -707,6 +709,7 @@ if CPUS["H8"] then { MAME_DIR .. "src/devices/cpu/h8/h8h.cpp", GEN_DIR .. "emu/cpu/h8/h8h.hxx" }, { MAME_DIR .. "src/devices/cpu/h8/h8s2000.cpp", GEN_DIR .. "emu/cpu/h8/h8s2000.hxx" }, { MAME_DIR .. "src/devices/cpu/h8/h8s2600.cpp", GEN_DIR .. "emu/cpu/h8/h8s2600.hxx" }, + { MAME_DIR .. "src/devices/cpu/h8/gt913.cpp", GEN_DIR .. "emu/cpu/h8/gt913.hxx" }, } custombuildtask { @@ -714,19 +717,22 @@ if CPUS["H8"] then { MAME_DIR .. "src/devices/cpu/h8/h8.lst" , GEN_DIR .. "emu/cpu/h8/h8h.hxx", { MAME_DIR .. "src/devices/cpu/h8/h8make.py" }, {"@echo Generating H8-300H source file...", PYTHON .. " $(1) $(<) s h $(@)" }}, { MAME_DIR .. "src/devices/cpu/h8/h8.lst" , GEN_DIR .. "emu/cpu/h8/h8s2000.hxx", { MAME_DIR .. "src/devices/cpu/h8/h8make.py" }, {"@echo Generating H8S/2000 source file...", PYTHON .. " $(1) $(<) s s20 $(@)" }}, { MAME_DIR .. "src/devices/cpu/h8/h8.lst" , GEN_DIR .. "emu/cpu/h8/h8s2600.hxx", { MAME_DIR .. "src/devices/cpu/h8/h8make.py" }, {"@echo Generating H8S/2600 source file...", PYTHON .. " $(1) $(<) s s26 $(@)" }}, + { MAME_DIR .. "src/devices/cpu/h8/gt913.lst" , GEN_DIR .. "emu/cpu/h8/gt913.hxx", { MAME_DIR .. "src/devices/cpu/h8/h8make.py" }, {"@echo Generating GT913 source file...", PYTHON .. " $(1) $(<) s g $(@)" }}, } end if opt_tool(CPUS, "H8") then - table.insert(disasm_custombuildtask, { MAME_DIR .. "src/devices/cpu/h8/h8.lst" , GEN_DIR .. "emu/cpu/h8/h8d.hxx", { MAME_DIR .. "src/devices/cpu/h8/h8make.py" }, {"@echo Generating H8-300 disassembler source file...", PYTHON .. " $(1) $(<) d o $(@)" }}) - table.insert(disasm_custombuildtask, { MAME_DIR .. "src/devices/cpu/h8/h8.lst" , GEN_DIR .. "emu/cpu/h8/h8hd.hxx", { MAME_DIR .. "src/devices/cpu/h8/h8make.py" }, {"@echo Generating H8-300H disassembler source file...", PYTHON .. " $(1) $(<) d h $(@)" }}) - table.insert(disasm_custombuildtask, { MAME_DIR .. "src/devices/cpu/h8/h8.lst" , GEN_DIR .. "emu/cpu/h8/h8s2000d.hxx", { MAME_DIR .. "src/devices/cpu/h8/h8make.py" }, {"@echo Generating H8S/2000 disassembler source file...", PYTHON .. " $(1) $(<) d s20 $(@)" }}) - table.insert(disasm_custombuildtask, { MAME_DIR .. "src/devices/cpu/h8/h8.lst" , GEN_DIR .. "emu/cpu/h8/h8s2600d.hxx", { MAME_DIR .. "src/devices/cpu/h8/h8make.py" }, {"@echo Generating H8S/2600 disassembler source file...", PYTHON .. " $(1) $(<) d s26 $(@)" }}) + table.insert(disasm_custombuildtask, { MAME_DIR .. "src/devices/cpu/h8/h8.lst" , GEN_DIR .. "emu/cpu/h8/h8d.hxx", { MAME_DIR .. "src/devices/cpu/h8/h8make.py" }, {"@echo Generating H8-300 disassembler source file...", PYTHON .. " $(1) $(<) d o $(@)" }}) + table.insert(disasm_custombuildtask, { MAME_DIR .. "src/devices/cpu/h8/h8.lst" , GEN_DIR .. "emu/cpu/h8/h8hd.hxx", { MAME_DIR .. "src/devices/cpu/h8/h8make.py" }, {"@echo Generating H8-300H disassembler source file...", PYTHON .. " $(1) $(<) d h $(@)" }}) + table.insert(disasm_custombuildtask, { MAME_DIR .. "src/devices/cpu/h8/h8.lst" , GEN_DIR .. "emu/cpu/h8/h8s2000d.hxx", { MAME_DIR .. "src/devices/cpu/h8/h8make.py" }, {"@echo Generating H8S/2000 disassembler source file...", PYTHON .. " $(1) $(<) d s20 $(@)" }}) + table.insert(disasm_custombuildtask, { MAME_DIR .. "src/devices/cpu/h8/h8.lst" , GEN_DIR .. "emu/cpu/h8/h8s2600d.hxx", { MAME_DIR .. "src/devices/cpu/h8/h8make.py" }, {"@echo Generating H8S/2600 disassembler source file...", PYTHON .. " $(1) $(<) d s26 $(@)" }}) + table.insert(disasm_custombuildtask, { MAME_DIR .. "src/devices/cpu/h8/gt913.lst" , GEN_DIR .. "emu/cpu/h8/gt913d.hxx", { MAME_DIR .. "src/devices/cpu/h8/h8make.py" }, {"@echo Generating GT913 disassembler source file...", PYTHON .. " $(1) $(<) d g $(@)" }}) table.insert(disasm_dependency, { MAME_DIR .. "src/devices/cpu/h8/h8d.cpp", GEN_DIR .. "emu/cpu/h8/h8d.hxx" }) table.insert(disasm_dependency, { MAME_DIR .. "src/devices/cpu/h8/h8hd.cpp", GEN_DIR .. "emu/cpu/h8/h8hd.hxx" }) table.insert(disasm_dependency, { MAME_DIR .. "src/devices/cpu/h8/h8s2000d.cpp", GEN_DIR .. "emu/cpu/h8/h8s2000d.hxx" }) table.insert(disasm_dependency, { MAME_DIR .. "src/devices/cpu/h8/h8s2600d.cpp", GEN_DIR .. "emu/cpu/h8/h8s2600d.hxx" }) + table.insert(disasm_dependency, { MAME_DIR .. "src/devices/cpu/h8/gt913d.cpp", GEN_DIR .. "emu/cpu/h8/gt913d.hxx" }) table.insert(disasm_files, MAME_DIR .. "src/devices/cpu/h8/h8d.cpp") table.insert(disasm_files, MAME_DIR .. "src/devices/cpu/h8/h8d.h") @@ -736,6 +742,8 @@ if opt_tool(CPUS, "H8") then table.insert(disasm_files, MAME_DIR .. "src/devices/cpu/h8/h8s2000d.h") table.insert(disasm_files, MAME_DIR .. "src/devices/cpu/h8/h8s2600d.cpp") table.insert(disasm_files, MAME_DIR .. "src/devices/cpu/h8/h8s2600d.h") + table.insert(disasm_files, MAME_DIR .. "src/devices/cpu/h8/gt913d.cpp") + table.insert(disasm_files, MAME_DIR .. "src/devices/cpu/h8/gt913d.h") end -------------------------------------------------- diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 30f5c86408f..7d96d01761e 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -1391,6 +1391,22 @@ if (MACHINES["FGA002"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/gt913.h,MACHINES["GT913"] = true +--------------------------------------------------- + +if (MACHINES["GT913"]~=null) then + files { + MAME_DIR .. "src/devices/machine/gt913_io.cpp", + MAME_DIR .. "src/devices/machine/gt913_io.h", + MAME_DIR .. "src/devices/machine/gt913_kbd.cpp", + MAME_DIR .. "src/devices/machine/gt913_kbd.h", + MAME_DIR .. "src/devices/machine/gt913_snd.cpp", + MAME_DIR .. "src/devices/machine/gt913_snd.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/hd63450.h,MACHINES["HD63450"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index e1aa44ef18c..580e9460a3f 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -530,6 +530,7 @@ MACHINES["ER2055"] = true MACHINES["EXORTERM"] = true MACHINES["F3853"] = true MACHINES["F4702"] = true +MACHINES["GT913"] = true MACHINES["HD63450"] = true MACHINES["HD64610"] = true MACHINES["HP_DC100_TAPE"] = true @@ -2024,6 +2025,7 @@ files { MAME_DIR .. "src/mame/drivers/fp6000.cpp", MAME_DIR .. "src/mame/machine/fp6000_kbd.cpp", MAME_DIR .. "src/mame/machine/fp6000_kbd.h", + MAME_DIR .. "src/mame/drivers/ctk551.cpp", MAME_DIR .. "src/mame/drivers/ht6000.cpp", MAME_DIR .. "src/mame/drivers/pb1000.cpp", MAME_DIR .. "src/mame/drivers/pv1000.cpp", diff --git a/src/devices/cpu/h8/gt913.cpp b/src/devices/cpu/h8/gt913.cpp new file mode 100644 index 00000000000..3d8b939d8b7 --- /dev/null +++ b/src/devices/cpu/h8/gt913.cpp @@ -0,0 +1,170 @@ +// license:BSD-3-Clause +// copyright-holders:Devin Acker +/*************************************************************************** + Casio GT913 + + This chip powers several late-90s/early-2000s Casio keyboards. + It's based on the H8/300 instruction set, but with different encoding + for many opcodes, as well as: + + - Dedicated bank switching instructions (20-bit external address bus) + - Two timers, three 8-bit ports, two 8-bit ADCs + - Keyboard controller w/ key velocity detection + - MIDI UART + - 24-voice PCM sound (currently not emulated / fully understood) + + Earlier and later Casio keyboard models contain "uPD912" and "uPD914" chips, + which are presumably similar. + +***************************************************************************/ + +#include "emu.h" +#include "gt913.h" +#include "gt913d.h" + +DEFINE_DEVICE_TYPE(GT913, gt913_device, "gt913", "Casio GT913F") + +gt913_device::gt913_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + h8_device(mconfig, GT913, tag, owner, clock, address_map_constructor(FUNC(gt913_device::map), this)), + m_rom(*this, DEVICE_SELF), + m_bank(*this, "bank"), + m_intc(*this, "intc"), + m_sound(*this, "gt_sound"), + m_kbd(*this, "kbd"), + m_io_hle(*this, "io_hle"), + m_sci(*this, "sci"), + m_port(*this, "port%u", 1) +{ + has_hc = false; +} + +std::unique_ptr gt913_device::create_disassembler() +{ + return std::make_unique(); +} + +void gt913_device::map(address_map &map) +{ +// map.unmap_value_high(); + + map(0x0000, 0x7fff).rom(); + map(0x8000, 0xbfff).bankr("bank"); + map(0xfac0, 0xffbf).ram(); // CTK-551 zeroes out this range at $0418 + + /* ffc0-ffcb: sound */ + map(0xffc0, 0xffc5).rw(m_sound, FUNC(gt913_sound_hle_device::data_r), FUNC(gt913_sound_hle_device::data_w)); + map(0xffc6, 0xffc7).w(m_sound, FUNC(gt913_sound_hle_device::command_w)); + map(0xffca, 0xffcb).r(m_sound, FUNC(gt913_sound_hle_device::status_r)); + + /* ffd0-ffd5: key controller */ + map(0xffd0, 0xffd1).r(m_kbd, FUNC(gt913_kbd_hle_device::read)); + map(0xffd2, 0xffd3).rw(m_kbd, FUNC(gt913_kbd_hle_device::status_r), FUNC(gt913_kbd_hle_device::status_w)); + + /* ffd8-ffdf: timers */ + map(0xffd8, 0xffd9).rw(m_io_hle, FUNC(gt913_io_hle_device::timer_control_r), FUNC(gt913_io_hle_device::timer_control_w)); + map(0xffdc, 0xffdd).w(m_io_hle, FUNC(gt913_io_hle_device::timer_rate0_w)); + map(0xffdf, 0xffdf).w(m_io_hle, FUNC(gt913_io_hle_device::timer_rate1_w)); + + /* ffe0-ffe3: serial */ + map(0xffe0, 0xffe0).w(FUNC(gt913_device::uart_rate_w)); + map(0xffe1, 0xffe1).w(m_sci, FUNC(h8_sci_device::tdr_w)); + map(0xffe2, 0xffe2).rw(FUNC(gt913_device::uart_control_r), FUNC(gt913_device::uart_control_w)); + map(0xffe3, 0xffe3).r(m_sci, FUNC(h8_sci_device::rdr_r)); + + /* ffe9-ffea: ADC */ + map(0xffe9, 0xffe9).rw(m_io_hle, FUNC(gt913_io_hle_device::adc_control_r), FUNC(gt913_io_hle_device::adc_control_w)); + map(0xffea, 0xffea).r(m_io_hle, FUNC(gt913_io_hle_device::adc_data_r)); + + /* fff0-fff5: I/O ports */ + map(0xfff0, 0xfff0).rw(m_port[0], FUNC(h8_port_device::ddr_r), FUNC(h8_port_device::ddr_w)); + map(0xfff1, 0xfff1).rw(m_port[1], FUNC(h8_port_device::ddr_r), FUNC(h8_port_device::ddr_w)); + map(0xfff2, 0xfff2).rw(m_port[0], FUNC(h8_port_device::port_r), FUNC(h8_port_device::dr_w)); + map(0xfff3, 0xfff3).rw(m_port[1], FUNC(h8_port_device::port_r), FUNC(h8_port_device::dr_w)); +// map(0xfff4, 0xfff4).nopw(); probably not port 3 DDR - ctk551 writes 0x00 but uses port 3 for output only + map(0xfff5, 0xfff5).rw(m_port[2], FUNC(h8_port_device::port_r), FUNC(h8_port_device::dr_w)); +} + +void gt913_device::device_add_mconfig(machine_config &config) +{ + GT913_INTC(config, "intc"); + + GT913_SOUND_HLE(config, m_sound, 0); + GT913_KBD_HLE(config, m_kbd, "intc", 5); + GT913_IO_HLE(config, m_io_hle, "intc", 6, 7); + H8_SCI(config, m_sci, "intc", 8, 9, 10, 0); + + H8_PORT(config, m_port[0], h8_device::PORT_1, 0xff, 0x00); + H8_PORT(config, m_port[1], h8_device::PORT_2, 0xff, 0x00); + H8_PORT(config, m_port[2], h8_device::PORT_3, 0xff, 0x00); +} + + +void gt913_device::uart_rate_w(uint8_t data) +{ + m_sci->brr_w(data >> 1); +} + +void gt913_device::uart_control_w(uint8_t data) +{ + /* + upper 4 bits seem to correspond to the upper bits of SSR (Tx/Rx/error status) + lower 4 bits seem to correspond to the upper bits of SCR (Tx/Rx IRQ enable, Tx/Rx enable(?)) + */ + m_sci->ssr_w(data & 0xf0); + m_sci->scr_w((data & 0x0f) << 4); +} + +uint8_t gt913_device::uart_control_r() +{ + return (m_sci->ssr_r() & 0xf0) | (m_sci->scr_r() >> 4); +} + +void gt913_device::irq_setup() +{ + CCR |= F_H; +} + +void gt913_device::update_irq_filter() +{ + if (CCR & F_H) + m_intc->set_filter(2, -1); + else + m_intc->set_filter(0, -1); +} + +void gt913_device::interrupt_taken() +{ + standard_irq_callback(m_intc->interrupt_taken(taken_irq_vector)); +} + +void gt913_device::internal_update(uint64_t current_time) +{ + uint64_t event_time = 0; + + add_event(event_time, m_sci->internal_update(current_time)); + + recompute_bcount(event_time); +} + +void gt913_device::execute_set_input(int inputnum, int state) +{ + m_intc->set_input(inputnum, state); +} + +void gt913_device::device_start() +{ + h8_device::device_start(); + + m_bank->configure_entries(0, m_rom->bytes() >> 12, m_rom->base(), 1 << 12); + + save_item(NAME(m_banknum)); +} + +void gt913_device::device_reset() +{ + h8_device::device_reset(); + + m_banknum = 0; +} + +#include "cpu/h8/gt913.hxx" diff --git a/src/devices/cpu/h8/gt913.h b/src/devices/cpu/h8/gt913.h new file mode 100644 index 00000000000..d3962d51e87 --- /dev/null +++ b/src/devices/cpu/h8/gt913.h @@ -0,0 +1,82 @@ +// license:BSD-3-Clause +// copyright-holders:Devin Acker +/*************************************************************************** + + gt913.h + + Casio GT913 + +***************************************************************************/ + +#ifndef MAME_CPU_H8_GT913_H +#define MAME_CPU_H8_GT913_H + +#pragma once + +#include "h8.h" +#include "h8_intc.h" +#include "h8_port.h" +#include "h8_sci.h" +#include "machine/gt913_io.h" +#include "machine/gt913_kbd.h" +#include "machine/gt913_snd.h" + +class gt913_device : public h8_device { +public: + gt913_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual std::unique_ptr create_disassembler() override; + + void uart_rate_w(uint8_t data); + void uart_control_w(uint8_t data); + uint8_t uart_control_r(); + +protected: + + virtual void update_irq_filter() override; + virtual void interrupt_taken() override; + virtual void internal_update(uint64_t current_time) override; + virtual void irq_setup() override; + virtual void execute_set_input(int inputnum, int state) override; + + virtual void device_add_mconfig(machine_config &config) override; + void map(address_map &map); + + virtual void device_start() override; + virtual void device_reset() override; + + virtual void do_exec_full() override; + virtual void do_exec_partial() override; + +#define O(o) void o ## _full(); void o ## _partial() + O(ldbank_imm2l_bankl); O(ldbank_imm4l_bankh); O(ldbank_r8l_bankl); O(ldbank_r8l_bankh); + + O(dispatch_6600); O(dispatch_7000); O(dispatch_7200); +#undef O + + required_memory_region m_rom; + + required_memory_bank m_bank; + uint16_t m_banknum; + + required_device m_intc; + + /* sound */ + required_device m_sound; + + /* key controller */ + required_device m_kbd; + + /* misc. I/O (timers, ADCs) */ + required_device m_io_hle; + + /* serial port */ + required_device m_sci; + + /* 3x 8-bit I/O ports */ + required_device_array m_port; +}; + +DECLARE_DEVICE_TYPE(GT913, gt913_device) + +#endif // MAME_CPU_H8_GT913_H diff --git a/src/devices/cpu/h8/gt913.lst b/src/devices/cpu/h8/gt913.lst new file mode 100644 index 00000000000..7bbb26ecc33 --- /dev/null +++ b/src/devices/cpu/h8/gt913.lst @@ -0,0 +1,140 @@ +# license:BSD-3-Clause +# copyright-holders:Olivier Galibert, Devin Acker + +10000 reset +10001 irq + +0000 ffff 0 nop - - +0100 ffff 0 sleep - - +0240 fff0 0 stc ccr r8l +0340 fff0 0 ldc r8l ccr + +0380 fff0 0 ldbank r8l bankh g + TMP1 = r8_r(IR[0]); + m_banknum = (TMP1 << 2) | (m_banknum & 0x3); + m_bank->set_entry(m_banknum); + prefetch(); + +03c0 fff0 0 ldbank r8l bankl g + TMP1 = r8_r(IR[0]); + m_banknum = (m_banknum & 0xfffc) | (TMP1 & 0x3); + m_bank->set_entry(m_banknum); + prefetch(); + +0400 ff00 0 orc imm8 ccr +0500 ff00 0 xorc imm8 ccr +0600 ff00 0 andc imm8 ccr + +0780 fff0 0 ldbank imm4l bankh g + m_banknum = ((IR[0] & 0xf) << 2) | (m_banknum & 0x3); + m_bank->set_entry(m_banknum); + prefetch(); + +07c0 fff0 0 ldbank imm2l bankl g + m_banknum = (m_banknum & 0xfffc) | (IR[0] & 0x3); + m_bank->set_entry(m_banknum); + prefetch(); + +0800 ff00 0 add.b r8h r8l +0900 ff00 0 add.w r16h r16l +0a00 fff0 0 inc.b one r8l +0b00 fff8 0 adds.l one r16l +0b80 fff8 0 adds.l two r16l +0c00 ff00 0 mov.b r8h r8l +0d00 ff00 0 mov.w r16h r16l +0e00 ff00 0 addx.b r8h r8l +0f00 ff00 0 mulxu.b r8h r16l + +1000 fff0 0 shll.b r8l - +1080 fff0 0 shal.b r8l - +1100 fff0 0 shlr.b r8l - +1180 fff0 0 shar.b r8l - +1200 fff0 0 rotxl.b r8l - +1280 fff0 0 rotl.b r8l - +1300 fff0 0 rotxr.b r8l - +1380 fff0 0 rotr.b r8l - +1400 ff00 0 or.b r8h r8l +1500 ff00 0 xor.b r8h r8l +1600 ff00 0 and.b r8h r8l +1700 fff0 0 not.b r8l - +1780 fff0 0 neg.b r8l - +1800 ff00 0 sub.b r8h r8l +1900 ff00 0 sub.w r16h r16l +1a00 fff0 0 dec.b one r8l +# yes, this is the correct order for subs.l - one and two are swapped for some reason +1b00 fff8 0 subs.l two r16l +1b80 fff8 0 subs.l one r16l +1c00 ff00 0 cmp.b r8h r8l +1d00 ff00 0 cmp.w r16h r16l +1e00 ff00 0 subx.b r8h r8l +1f00 ff00 0 divxu.b r8h r16l + +2000 f000 0 mov.b abs8 r8u +3000 f000 0 mov.b r8u abs8 + +4000 ff00 0 bt rel8 - +4100 ff00 0 bf rel8 - +4200 ff00 0 bhi rel8 - +4300 ff00 0 bls rel8 - +4400 ff00 0 bcc rel8 - +4500 ff00 0 bcs rel8 - +4600 ff00 0 bne rel8 - +4700 ff00 0 beq rel8 - +4800 ff00 0 bvc rel8 - +4900 ff00 0 bvs rel8 - +4a00 ff00 0 bpl rel8 - +4b00 ff00 0 bmi rel8 - +4c00 ff00 0 bge rel8 - +4d00 ff00 0 blt rel8 - +4e00 ff00 0 bgt rel8 - +4f00 ff00 0 ble rel8 - + +5000 ff80 0 bset imm3 r8l +5100 ff00 0 bset r8h r8l +5200 ff80 0 bclr imm3 r8l +5300 ff00 0 bclr r8h r8l +5400 ff80 0 bnot imm3 r8l +5500 ff00 0 bnot r8h r8l +5600 ff80 0 btst imm3 r8l +5700 ff00 0 btst r8h r8l +5800 ffff 0 rts - - +5980 ffff 0 rte - - +5a00 ff8f 0 jmp r16h - +5a80 ffff 0 jmp abs16e - +5b00 ff00 0 jmp abs8i - +5c00 ff8f 0 jsr r16h - +5c80 ffff 0 jsr abs16e - +5e00 ff00 0 bsr rel8 - +5f00 fff0 0 mov.w imm16 r16l + +66000000 ff00ff8f 0 btst imm3 abs8 + +6800 ff80 0 mov.b r16ih r8l +6900 ff88 0 mov.w r16ih r16l +6a00 ff80 0 mov.b r16ph r8l +6b00 ff88 0 mov.w r16ph r16l +6c00 fff0 0 mov.b abs16 r8l +6d00 fff0 0 mov.w abs16 r16l +6e00 ff80 0 mov.b r16d16h r8l +6f00 ff80 0 mov.w r16d16h r16l + +70000000 ff00ff8f 0 bset imm3 abs8 +72000000 ff00ff8f 0 bclr imm3 abs8 + +7800 ff80 0 mov.b r8l r16ih +7900 ff88 0 mov.w r16l r16ih +7a00 ff80 0 mov.b r8l pr16h +7b00 ff88 0 mov.w r16l pr16h +7c00 fff0 0 mov.b r8l abs16 +7d00 fff0 0 mov.w r16l abs16 +7e00 ff80 0 mov.b r8l r16d16h +7f00 ff80 0 mov.w r16l r16d16h + +8000 f000 0 add.b imm8 r8u +9000 f000 0 addx.b imm8 r8u +a000 f000 0 cmp.b imm8 r8u +b000 f000 0 subx.b imm8 r8u +c000 f000 0 or.b imm8 r8u +d000 f000 0 xor.b imm8 r8u +e000 f000 0 and.b imm8 r8u +f000 f000 0 mov.b imm8 r8u diff --git a/src/devices/cpu/h8/gt913d.cpp b/src/devices/cpu/h8/gt913d.cpp new file mode 100644 index 00000000000..e2e36aafa9d --- /dev/null +++ b/src/devices/cpu/h8/gt913d.cpp @@ -0,0 +1,17 @@ +// license:BSD-3-Clause +// copyright-holders:Devin Acker +/*************************************************************************** + + gt913d.cpp + + GT913 base cpu emulation, disassembler + +***************************************************************************/ + +#include "emu.h" +#include "gt913d.h" +#include "cpu/h8/gt913d.hxx" + +gt913_disassembler::gt913_disassembler() : h8_disassembler(disasm_entries, false) +{ +} diff --git a/src/devices/cpu/h8/gt913d.h b/src/devices/cpu/h8/gt913d.h new file mode 100644 index 00000000000..ee9c6801615 --- /dev/null +++ b/src/devices/cpu/h8/gt913d.h @@ -0,0 +1,28 @@ +// license:BSD-3-Clause +// copyright-holders:Devin Acker +/*************************************************************************** + + gt913d.h + + GT913 base cpu emulation, disassembler + +***************************************************************************/ + +#ifndef MAME_CPU_H8_GT913D_H +#define MAME_CPU_H8_GT913D_H + +#pragma once + +#include "h8d.h" + +class gt913_disassembler : public h8_disassembler +{ +public: + gt913_disassembler(); + virtual ~gt913_disassembler() = default; + +protected: + static const disasm_entry disasm_entries[]; +}; + +#endif diff --git a/src/devices/cpu/h8/h8.cpp b/src/devices/cpu/h8/h8.cpp index 0b4d35ebbd5..985f9f6715d 100644 --- a/src/devices/cpu/h8/h8.cpp +++ b/src/devices/cpu/h8/h8.cpp @@ -28,6 +28,7 @@ h8_device::h8_device(const machine_config &mconfig, device_type type, const char has_exr = false; mac_saturating = false; has_trace = false; + has_hc = true; } void h8_device::device_config_complete() @@ -318,7 +319,7 @@ void h8_device::state_string_export(const device_state_entry &entry, std::string (CCR & F_Z) ? 'Z' : '-', (CCR & F_V) ? 'V' : '-', (CCR & F_C) ? 'C' : '-'); - else + else if(has_hc) str = string_format("%c%c%c%c%c%c%c%c", (CCR & F_I) ? 'I' : '-', (CCR & F_UI) ? 'u' : '-', @@ -328,6 +329,16 @@ void h8_device::state_string_export(const device_state_entry &entry, std::string (CCR & F_Z) ? 'Z' : '-', (CCR & F_V) ? 'V' : '-', (CCR & F_C) ? 'C' : '-'); + else + str = string_format("%c%c%c%c%c%c%c%c", + (CCR & F_I) ? '?' : '-', + (CCR & F_UI) ? 'u' : '-', + (CCR & F_H) ? 'I' : '-', + (CCR & F_U) ? 'U' : '-', + (CCR & F_N) ? 'N' : '-', + (CCR & F_Z) ? 'Z' : '-', + (CCR & F_V) ? 'V' : '-', + (CCR & F_C) ? 'C' : '-'); break; case H8_R0: case H8_R1: @@ -449,9 +460,13 @@ int h8_device::trapa_setup() uint8_t h8_device::do_addx8(uint8_t v1, uint8_t v2) { uint16_t res = v1 + v2 + (CCR & F_C ? 1 : 0); - CCR &= ~(F_N|F_V|F_Z|F_C|F_H); - if(((v1 & 0xf) + (v2 & 0xf) + (CCR & F_C ? 1 : 0)) & 0x10) - CCR |= F_H; + CCR &= ~(F_N|F_V|F_Z|F_C); + if (has_hc) + { + CCR &= ~F_H; + if(((v1 & 0xf) + (v2 & 0xf) + (CCR & F_C ? 1 : 0)) & 0x10) + CCR |= F_H; + } if(!uint8_t(res)) CCR |= F_Z; else if(int8_t(res) < 0) @@ -467,9 +482,13 @@ uint8_t h8_device::do_addx8(uint8_t v1, uint8_t v2) uint8_t h8_device::do_subx8(uint8_t v1, uint8_t v2) { uint16_t res = v1 - v2 - (CCR & F_C ? 1 : 0); - CCR &= ~(F_N|F_V|F_Z|F_C|F_H); - if(((v1 & 0xf) - (v2 & 0xf) - (CCR & F_C ? 1 : 0)) & 0x10) - CCR |= F_H; + CCR &= ~(F_N|F_V|F_Z|F_C); + if (has_hc) + { + CCR &= ~F_H; + if (((v1 & 0xf) - (v2 & 0xf) - (CCR & F_C ? 1 : 0)) & 0x10) + CCR |= F_H; + } if(!uint8_t(res)) CCR |= F_Z; else if(int8_t(res) < 0) @@ -524,9 +543,13 @@ uint32_t h8_device::do_inc32(uint32_t v1, uint32_t v2) uint8_t h8_device::do_add8(uint8_t v1, uint8_t v2) { uint16_t res = v1 + v2; - CCR &= ~(F_N|F_V|F_Z|F_C|F_H); - if(((v1 & 0xf) + (v2 & 0xf)) & 0x10) - CCR |= F_H; + CCR &= ~(F_N|F_V|F_Z|F_C); + if (has_hc) + { + CCR &= ~F_H; + if (((v1 & 0xf) + (v2 & 0xf)) & 0x10) + CCR |= F_H; + } if(!uint8_t(res)) CCR |= F_Z; else if(int8_t(res) < 0) @@ -542,9 +565,13 @@ uint8_t h8_device::do_add8(uint8_t v1, uint8_t v2) uint16_t h8_device::do_add16(uint16_t v1, uint16_t v2) { uint32_t res = v1 + v2; - CCR &= ~(F_N|F_V|F_Z|F_C|F_H); - if(((v1 & 0xfff) + (v2 & 0xffff)) & 0x1000) - CCR |= F_H; + CCR &= ~(F_N|F_V|F_Z|F_C); + if (has_hc) + { + CCR &= ~F_H; + if (((v1 & 0xfff) + (v2 & 0xffff)) & 0x1000) + CCR |= F_H; + } if(!uint16_t(res)) CCR |= F_Z; else if(int16_t(res) < 0) @@ -560,9 +587,13 @@ uint16_t h8_device::do_add16(uint16_t v1, uint16_t v2) uint32_t h8_device::do_add32(uint32_t v1, uint32_t v2) { uint64_t res = uint64_t(v1) + uint64_t(v2); - CCR &= ~(F_N|F_V|F_Z|F_C|F_H); - if(((v1 & 0xfffffff) + (v2 & 0xfffffff)) & 0x10000000) - CCR |= F_H; + CCR &= ~(F_N|F_V|F_Z|F_C); + if (has_hc) + { + CCR &= ~F_H; + if (((v1 & 0xfffffff) + (v2 & 0xfffffff)) & 0x10000000) + CCR |= F_H; + } if(!uint32_t(res)) CCR |= F_Z; else if(int32_t(res) < 0) @@ -616,9 +647,13 @@ uint32_t h8_device::do_dec32(uint32_t v1, uint32_t v2) uint8_t h8_device::do_sub8(uint8_t v1, uint8_t v2) { uint16_t res = v1 - v2; - CCR &= ~(F_N|F_V|F_Z|F_C|F_H); - if(((v1 & 0xf) - (v2 & 0xf)) & 0x10) - CCR |= F_H; + CCR &= ~(F_N|F_V|F_Z|F_C); + if (has_hc) + { + CCR &= ~F_H; + if (((v1 & 0xf) - (v2 & 0xf)) & 0x10) + CCR |= F_H; + } if(!uint8_t(res)) CCR |= F_Z; else if(int8_t(res) < 0) @@ -634,9 +669,13 @@ uint8_t h8_device::do_sub8(uint8_t v1, uint8_t v2) uint16_t h8_device::do_sub16(uint16_t v1, uint16_t v2) { uint32_t res = v1 - v2; - CCR &= ~(F_N|F_V|F_Z|F_C|F_H); - if(((v1 & 0xfff) - (v2 & 0xffff)) & 0x1000) - CCR |= F_H; + CCR &= ~(F_N|F_V|F_Z|F_C); + if (has_hc) + { + CCR &= ~F_H; + if (((v1 & 0xfff) - (v2 & 0xffff)) & 0x1000) + CCR |= F_H; + } if(!uint16_t(res)) CCR |= F_Z; else if(int16_t(res) < 0) @@ -652,9 +691,13 @@ uint16_t h8_device::do_sub16(uint16_t v1, uint16_t v2) uint32_t h8_device::do_sub32(uint32_t v1, uint32_t v2) { uint64_t res = uint64_t(v1) - uint64_t(v2); - CCR &= ~(F_N|F_V|F_Z|F_C|F_H); - if(((v1 & 0xfffffff) - (v2 & 0xfffffff)) & 0x10000000) - CCR |= F_H; + CCR &= ~(F_N|F_V|F_Z|F_C); + if (has_hc) + { + CCR &= ~F_H; + if (((v1 & 0xfffffff) - (v2 & 0xfffffff)) & 0x10000000) + CCR |= F_H; + } if(!uint32_t(res)) CCR |= F_Z; else if(int32_t(res) < 0) diff --git a/src/devices/cpu/h8/h8.h b/src/devices/cpu/h8/h8.h index e8e1647288e..71ff7ba9a7e 100644 --- a/src/devices/cpu/h8/h8.h +++ b/src/devices/cpu/h8/h8.h @@ -135,6 +135,7 @@ protected: uint32_t TMPR; /* For debugger ER register import */ bool has_exr, has_trace, supports_advanced, mode_advanced, mode_a20, mac_saturating; + bool has_hc; // GT913's CCR bit 5 is I, not H int inst_state, inst_substate, requested_state; int icount, bcount, count_before_instruction_step; @@ -334,7 +335,7 @@ protected: O(divxu_b_r8h_r16l); O(eepmov_b); O(inc_b_one_r8l); - O(jmp_abs8i); O(jmp_abs16e); + O(jmp_abs8i); O(jmp_abs16e); O(jmp_r16h); O(jsr_abs8i); O(jsr_abs16e); O(jsr_r16h); O(ldc_imm8_ccr); O(ldc_r8l_ccr); O(mov_b_abs16_r8l); O(mov_b_abs8_r8u); O(mov_b_imm8_r8u); O(mov_b_r8h_r8l); O(mov_b_r8l_abs16); O(mov_b_r8u_abs8); O(mov_b_r16ih_r8l); O(mov_b_r8l_r16ih); O(mov_b_r16d16h_r8l); O(mov_b_r8l_r16d16h); O(mov_b_r16ph_r8l); O(mov_b_r8l_pr16h); diff --git a/src/devices/cpu/h8/h8.lst b/src/devices/cpu/h8/h8.lst index a53e211b69c..a9026df8bc0 100644 --- a/src/devices/cpu/h8/h8.lst +++ b/src/devices/cpu/h8/h8.lst @@ -100,7 +100,7 @@ macro jsr32 %opc %spreg prefetch_done(); 10000 reset - CCR |= F_I; + CCR |= (has_hc ? F_I : F_H); EXR = EXR_I | EXR_NC; if(mode_advanced) { IR[0] = read16i(0); @@ -1007,7 +1007,7 @@ macro jsr32 %opc %spreg TMP1 = r8_r(IR[0]); TMP2 = 0; if(CCR & F_C) { - if(CCR & F_H) { + if(has_hc && (CCR & F_H)) { if((TMP1 & 0xf0) <= 0x30 && (TMP1 & 0x0f) <= 3) TMP2 = 0x66; } else { @@ -1015,7 +1015,7 @@ macro jsr32 %opc %spreg TMP2 = (TMP1 & 0x0f) <= 9 ? 0x60 : 0x66; } } else { - if(CCR & F_H) { + if(has_hc && (CCR & F_H)) { if((TMP1 & 0x0f) <= 3) TMP2 = (TMP1 & 0xf0) <= 0x90 ? 0x06 : 0x66; } else { @@ -1378,7 +1378,7 @@ macro jsr32 %opc %spreg TMP1 = r8_r(IR[0]); TMP2 = 0; if(CCR & F_C) { - if(CCR & F_H) { + if(has_hc && (CCR & F_H)) { if((TMP1 & 0xf0) >= 0x60 && (TMP1 & 0x0f) >= 6) TMP2 = 0x9a; } else { @@ -1386,7 +1386,7 @@ macro jsr32 %opc %spreg TMP2 = 0xa0; } } else { - if(CCR & F_H) { + if(has_hc && (CCR & F_H)) { if((TMP1 & 0xf0) <= 0x80 && (TMP1 & 0x0f) >= 6) TMP2 = 0xfa; } @@ -1647,6 +1647,11 @@ macro jsr32 %opc %spreg 58f0 ffff 0 ble rel16 - h bxx_16 (CCR & F_Z) || (CCR & (F_N|F_V)) == F_N || (CCR & (F_N|F_V)) == F_V +5900 ff8f 0 jmp r16h - o + fetch(); + PC = r16_r(IR[0] >> 4); + prefetch(); + 5900 ff8f 0 jmp r32h - h fetch(); PC = r32_r(IR[0] >> 4); diff --git a/src/devices/cpu/h8/h8_intc.cpp b/src/devices/cpu/h8/h8_intc.cpp index 290a95f3d3d..c27ceacfd06 100644 --- a/src/devices/cpu/h8/h8_intc.cpp +++ b/src/devices/cpu/h8/h8_intc.cpp @@ -3,9 +3,10 @@ #include "emu.h" #include "h8_intc.h" -DEFINE_DEVICE_TYPE(H8_INTC, h8_intc_device, "h8_intc", "H8 interrupt controller") -DEFINE_DEVICE_TYPE(H8H_INTC, h8h_intc_device, "h8h_intc", "H8H interrupt controller") -DEFINE_DEVICE_TYPE(H8S_INTC, h8s_intc_device, "h8s_intc", "H8S interrupt controller") +DEFINE_DEVICE_TYPE(H8_INTC, h8_intc_device, "h8_intc", "H8 interrupt controller") +DEFINE_DEVICE_TYPE(H8H_INTC, h8h_intc_device, "h8h_intc", "H8H interrupt controller") +DEFINE_DEVICE_TYPE(H8S_INTC, h8s_intc_device, "h8s_intc", "H8S interrupt controller") +DEFINE_DEVICE_TYPE(GT913_INTC, gt913_intc_device, "gt913_intc", "Casio GT913F interrupt controller") h8_intc_device::h8_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : h8_intc_device(mconfig, H8_INTC, tag, owner, clock) @@ -47,7 +48,7 @@ int h8_intc_device::interrupt_taken(int vector) if(0) logerror("taking internal interrupt %d\n", vector); pending_irqs[vector >> 5] &= ~(1 << (vector & 31)); - if(vector >= irq_vector_base && vector < irq_vector_base + 8) { + if(irq_vector_base >= 0 && vector >= irq_vector_base && vector < irq_vector_base + 8) { int irq = vector - irq_vector_base; if(irq_type[irq] != IRQ_LEVEL || !(irq_input & (1 << irq))) isr &= ~(1 << irq); @@ -159,8 +160,11 @@ void h8_intc_device::update_irq_types() void h8_intc_device::update_irq_state() { - pending_irqs[0] &= ~(255 << irq_vector_base); - pending_irqs[0] |= (isr & ier) << irq_vector_base; + if (irq_vector_base >= 0) + { + pending_irqs[0] &= ~(255 << irq_vector_base); + pending_irqs[0] |= (isr & ier) << irq_vector_base; + } int cur_vector = 0; int cur_level = -1; @@ -192,6 +196,19 @@ void h8_intc_device::get_priority(int vect, int &icr_pri, int &ipr_pri) const } +gt913_intc_device::gt913_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + gt913_intc_device(mconfig, GT913_INTC, tag, owner, clock) +{ + irq_vector_base = -1; // no external IRQs + irq_vector_nmi = 3; +} + +gt913_intc_device::gt913_intc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + h8_intc_device(mconfig, type, tag, owner, clock) +{ +} + + h8h_intc_device::h8h_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : h8h_intc_device(mconfig, H8H_INTC, tag, owner, clock) { diff --git a/src/devices/cpu/h8/h8_intc.h b/src/devices/cpu/h8/h8_intc.h index 787bafc48cc..2fd1280c432 100644 --- a/src/devices/cpu/h8/h8_intc.h +++ b/src/devices/cpu/h8/h8_intc.h @@ -60,6 +60,14 @@ protected: void check_level_irqs(bool force_update = false); }; +class gt913_intc_device : public h8_intc_device { +public: + gt913_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + +protected: + gt913_intc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); +}; + class h8h_intc_device : public h8_intc_device { public: h8h_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); @@ -105,8 +113,9 @@ private: virtual void device_reset() override; }; -DECLARE_DEVICE_TYPE(H8_INTC, h8_intc_device) -DECLARE_DEVICE_TYPE(H8H_INTC, h8h_intc_device) -DECLARE_DEVICE_TYPE(H8S_INTC, h8s_intc_device) +DECLARE_DEVICE_TYPE(H8_INTC, h8_intc_device) +DECLARE_DEVICE_TYPE(H8H_INTC, h8h_intc_device) +DECLARE_DEVICE_TYPE(H8S_INTC, h8s_intc_device) +DECLARE_DEVICE_TYPE(GT913_INTC, gt913_intc_device) #endif // MAME_CPU_H8_H8_INTC_H diff --git a/src/devices/cpu/h8/h8_port.cpp b/src/devices/cpu/h8/h8_port.cpp index 078a8c92a84..e366e0d49a5 100644 --- a/src/devices/cpu/h8/h8_port.cpp +++ b/src/devices/cpu/h8/h8_port.cpp @@ -25,6 +25,11 @@ void h8_port_device::ddr_w(uint8_t data) update_output(); } +uint8_t h8_port_device::ddr_r() +{ + return ddr; +} + void h8_port_device::dr_w(uint8_t data) { // logerror("dr_w %02x\n", data); diff --git a/src/devices/cpu/h8/h8_port.h b/src/devices/cpu/h8/h8_port.h index 887efcebf47..6c60b0c7621 100644 --- a/src/devices/cpu/h8/h8_port.h +++ b/src/devices/cpu/h8/h8_port.h @@ -28,6 +28,7 @@ public: void set_info(int address, uint8_t default_ddr, uint8_t mask); void ddr_w(uint8_t data); + uint8_t ddr_r(); void dr_w(uint8_t data); uint8_t dr_r(); uint8_t port_r(); diff --git a/src/devices/cpu/h8/h8d.cpp b/src/devices/cpu/h8/h8d.cpp index d5048cbb7d4..11a823c4b26 100644 --- a/src/devices/cpu/h8/h8d.cpp +++ b/src/devices/cpu/h8/h8d.cpp @@ -213,10 +213,18 @@ void h8_disassembler::disassemble_am(std::ostream &stream, int am, offs_t pc, co util::stream_format(stream, "#%x", (opcode >> 4) & 3); break; + case DASM_imm2l: + util::stream_format(stream, "#%x", opcode & 3); + break; + case DASM_imm3: util::stream_format(stream, "#%x", (opcode >> 4) & 7); break; + case DASM_imm4l: + util::stream_format(stream, "#%x", opcode & 15); + break; + case DASM_imm8: util::stream_format(stream, "#h'%02x", opcodes.r8(epc-1)); break; @@ -237,6 +245,14 @@ void h8_disassembler::disassemble_am(std::ostream &stream, int am, offs_t pc, co util::stream_format(stream, "exr"); break; + case DASM_bankl: + util::stream_format(stream, "bankl"); + break; + + case DASM_bankh: + util::stream_format(stream, "bankh"); + break; + case DASM_macl: util::stream_format(stream, "macl"); break; diff --git a/src/devices/cpu/h8/h8d.h b/src/devices/cpu/h8/h8d.h index c58208d4bfe..f6625fd9022 100644 --- a/src/devices/cpu/h8/h8d.h +++ b/src/devices/cpu/h8/h8d.h @@ -80,13 +80,17 @@ protected: DASM_four, /* immediate value 4 */ DASM_imm2, /* 2-bit immediate in bits 4-5 (trapa) */ + DASM_imm2l, /* 2-bit immediate in bits 0-1 (GT913) */ DASM_imm3, /* 3-bit immediate in bits 4-6 (bit selection */ + DASM_imm4l, /* 4-bit immediate in bits 0-3 (GT913) */ DASM_imm8, /* 8-bit immediate at +1 */ DASM_imm16, /* 16-bit immediate at +2 */ DASM_imm32, /* 32-bit immediate at +2 */ DASM_ccr, /* internal register ccr */ DASM_exr, /* internal register exr */ + DASM_bankl, /* internal register bankl (GT913) */ + DASM_bankh, /* internal register bankl (GT913) */ DASM_macl, /* internal register macl */ DASM_mach /* internal register mach */ }; diff --git a/src/devices/cpu/h8/h8make.py b/src/devices/cpu/h8/h8make.py index e89bc6ff725..48f4675ed81 100644 --- a/src/devices/cpu/h8/h8make.py +++ b/src/devices/cpu/h8/h8make.py @@ -18,6 +18,8 @@ def name_to_type(name): return 2 if name == "s26": return 3 + if name == "g": + return 4 sys.stderr.write("Unknown chip type name %s\n" % name) sys.exit(1) @@ -29,7 +31,9 @@ def type_to_device(dtype, mode): return "h8h_device" if dtype == 2: return "h8s2000_device" - return "h8s2600_device" + if dtype == 3: + return "h8s2600_device" + return "gt913_device" else: if dtype == 0: return "h8_disassembler" @@ -37,7 +41,9 @@ def type_to_device(dtype, mode): return "h8h_disassembler" if dtype == 2: return "h8s2000_disassembler" - return "h8s2600_disassembler" + if dtype == 3: + return "h8s2600_disassembler" + return "gt913_disassembler" def hexsplit(str): res = [] @@ -474,7 +480,7 @@ def main(argv): if mode == 's': opcodes.build_dispatch() opcodes.save_opcodes(f, dname) - if dtype == 0: + if dtype == 0 or dtype == 4: opcodes.save_dispatch(f, dname) opcodes.save_exec(f, dname, dtype, "full") opcodes.save_exec(f, dname, dtype, "partial") diff --git a/src/devices/machine/gt913_io.cpp b/src/devices/machine/gt913_io.cpp new file mode 100644 index 00000000000..e77efd91fd9 --- /dev/null +++ b/src/devices/machine/gt913_io.cpp @@ -0,0 +1,156 @@ +// license:BSD-3-Clause +// copyright-holders:Devin Acker +/*************************************************************************** + Casio GT913 I/O (HLE) + + TODO: + - timer behavior is unverified (see comment in timer_control_w and timer_adjust) + - various other unemulated registers + +***************************************************************************/ + +#include "emu.h" +#include "gt913_io.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(GT913_IO_HLE, gt913_io_hle_device, "gt913_io_hle", "Casio GT913F I/O (HLE)") + +gt913_io_hle_device::gt913_io_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, GT913_IO_HLE, tag, owner, clock), + m_cpu(*this, DEVICE_SELF_OWNER), + m_cpu_io(nullptr), m_intc(nullptr), m_intc_tag(nullptr) +{ + m_timer_irq[0] = m_timer_irq[1] = 0; +} + +void gt913_io_hle_device::device_start() +{ + m_cpu_io = &m_cpu->space(AS_IO); + m_intc = siblingdevice(m_intc_tag); + + m_timer[0] = timer_alloc(0); + m_timer[1] = timer_alloc(1); + + save_item(NAME(m_timer_control)); + save_item(NAME(m_timer_rate)); + save_item(NAME(m_timer_irq_pending)); + save_item(NAME(m_adc_enable)); + save_item(NAME(m_adc_channel)); + save_item(NAME(m_adc_data)); +} + +void gt913_io_hle_device::device_reset() +{ + m_timer_control[0] = m_timer_control[1] = 0x00; + m_timer_rate[0] = m_timer_rate[1] = 0; + m_timer_irq_pending[0] = m_timer_irq_pending[1] = false; + + m_adc_enable = false; + m_adc_channel = false; + m_adc_data[0] = m_adc_data[1] = 0; +} + +void gt913_io_hle_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + m_timer_irq_pending[id] = true; + timer_check_irq(id); +} + +void gt913_io_hle_device::timer_control_w(offs_t offset, uint8_t data) +{ + assert(offset < 2); + // TODO: ctk551 clears and sets bit 4 during the respective timer's IRQ, what should this do? pause/restart the timer? + m_timer_control[offset] = data; + timer_check_irq(offset); +} + +uint8_t gt913_io_hle_device::timer_control_r(offs_t offset) +{ + assert(offset < 2); + return m_timer_control[offset]; +} + +void gt913_io_hle_device::timer_rate0_w(uint16_t data) +{ + m_timer_rate[0] = data; + timer_adjust(0); +} + +void gt913_io_hle_device::timer_rate1_w(uint8_t data) +{ + m_timer_rate[1] = data; + timer_adjust(1); +} + +void gt913_io_hle_device::timer_adjust(offs_t num) +{ + assert(num < 2); + + /* + On the CTK-551, this behavior provides the expected rate for timer 0, which is the MIDI PPQN timer. + For timer 1, this is less certain, but it seems to provide an auto power off delay only a little + longer than the "about six minutes" mentioned in the user manual. + */ + u64 clocks = m_timer_rate[num]; + if (!clocks) + { + m_timer[num]->adjust(attotime::never); + } + else + { + switch (m_timer_control[num] & 0x7) + { + default: + logerror("unknown timer %u prescaler %u (pc = %04x)\n", num, m_timer_control[num] & 0x7, m_cpu->pc()); + [[fallthrough]]; + case 0: + clocks <<= 1; break; + case 2: + clocks <<= 10; break; + } + + attotime period = m_cpu->clocks_to_attotime(clocks); + m_timer[num]->adjust(period, 0, period); + } +} + +void gt913_io_hle_device::timer_check_irq(offs_t num) +{ + assert(num < 2); + + if (BIT(m_timer_control[num], 3) && m_timer_irq_pending[num]) + { + m_intc->internal_interrupt(m_timer_irq[num]); + m_timer_irq_pending[num] = false; + } +} + +void gt913_io_hle_device::adc_control_w(uint8_t data) +{ + m_adc_enable = BIT(data, 2); + m_adc_channel = BIT(data, 3); + if (m_adc_enable && BIT(data, 0)) + { + if (!m_adc_channel) + m_adc_data[0] = m_cpu_io->read_word(h8_device::ADC_0); + else + m_adc_data[1] = m_cpu_io->read_word(h8_device::ADC_1); + } +} + +uint8_t gt913_io_hle_device::adc_control_r() +{ + return (m_adc_enable << 2) | (m_adc_channel << 3); +} + +uint8_t gt913_io_hle_device::adc_data_r() +{ + if (!m_adc_channel) + return m_adc_data[0]; + else + return m_adc_data[1]; +} diff --git a/src/devices/machine/gt913_io.h b/src/devices/machine/gt913_io.h new file mode 100644 index 00000000000..08fc5f9595f --- /dev/null +++ b/src/devices/machine/gt913_io.h @@ -0,0 +1,74 @@ +// license:BSD-3-Clause +// copyright-holders: Devin Acker +/*************************************************************************** + Casio GT913 I/O (HLE) +***************************************************************************/ + +#ifndef MAME_MACHINE_GT913_IO_H +#define MAME_MACHINE_GT913_IO_H + +#pragma once + +#include "cpu/h8/h8_intc.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> gt913_kbd_hle_device + +class gt913_io_hle_device : public device_t +{ +public: + // construction/destruction + gt913_io_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + gt913_io_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, const char *intc, int t0irq, int t1irq) + : gt913_io_hle_device(mconfig, tag, owner, 0) + { + m_intc_tag = intc; + m_timer_irq[0] = t0irq; + m_timer_irq[1] = t1irq; + } + + void timer_control_w(offs_t offset, uint8_t data); + uint8_t timer_control_r(offs_t offset); + void timer_rate0_w(uint16_t data); + void timer_rate1_w(uint8_t data); + + void adc_control_w(uint8_t data); + uint8_t adc_control_r(); + uint8_t adc_data_r(); + +protected: + void timer_adjust(offs_t num); + void timer_check_irq(offs_t num); + + // device_t overrides + virtual void device_start() override; + virtual void device_reset() override; + + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + +private: + required_device m_cpu; + address_space *m_cpu_io; + h8_intc_device *m_intc; + const char *m_intc_tag; + + /* timers */ + uint8_t m_timer_control[2]; + uint16_t m_timer_rate[2]; + int m_timer_irq[2]; + bool m_timer_irq_pending[2]; + emu_timer *m_timer[2]; + + /* 2x ADC */ + bool m_adc_enable, m_adc_channel; + uint8_t m_adc_data[2]; + +}; + +// device type definition +DECLARE_DEVICE_TYPE(GT913_IO_HLE, gt913_io_hle_device) + +#endif // MAME_MACHINE_GT913_IO_H diff --git a/src/devices/machine/gt913_kbd.cpp b/src/devices/machine/gt913_kbd.cpp new file mode 100644 index 00000000000..92d80512cc2 --- /dev/null +++ b/src/devices/machine/gt913_kbd.cpp @@ -0,0 +1,104 @@ +// license:BSD-3-Clause +// copyright-holders:Devin Acker +/*************************************************************************** + Casio GT913 keyboard controller (HLE) + + This is the keyboard controller portion of the GT913. + The actual keyboard keys (as opposed to console buttons) have two + contacts per key, which allows the controller to detect the velocity + of the keypress. The detected velocity is read as a 7-bit value + from the data port, along with the actual key scan code. + + Right now, velocity is just simulated using an (optional) analog + control. The keyboard FIFO size is also basically a guess based on + the CTK-551's 16-key polyphony. + +***************************************************************************/ + +#include "emu.h" +#include "gt913_kbd.h" +#include "keyboard.ipp" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(GT913_KBD_HLE, gt913_kbd_hle_device, "gt913_kbd_hle", "Casio GT913F keyboard controller (HLE)") + +gt913_kbd_hle_device::gt913_kbd_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, GT913_KBD_HLE, tag, owner, clock), + device_matrix_keyboard_interface(mconfig, *this, "KO0", "KO1", "KO2", "KO3", "KO4", "KO5", "KO6", "KO7", "KO8", "KO9", "KO10", "KO11", "KO12"), + m_intc(nullptr), m_intc_tag(nullptr), m_irq(0), + m_velocity(*this, "VELOCITY") +{ +} + +void gt913_kbd_hle_device::device_start() +{ + m_intc = siblingdevice(m_intc_tag); + + save_item(NAME(m_status)); + save_item(NAME(m_fifo)); + save_item(NAME(m_fifo_read)); + save_item(NAME(m_fifo_write)); +} + +void gt913_kbd_hle_device::device_reset() +{ + m_status = 0x0000; + std::memset(m_fifo, 0xff, sizeof(m_fifo)); + m_fifo_read = m_fifo_write = 0; + + reset_key_state(); + start_processing(attotime::from_hz(1200)); +} + +void gt913_kbd_hle_device::key_add(uint8_t row, uint8_t column, int state) +{ + m_fifo[m_fifo_write] = (row << 3) | (column & 7); + if (state) + m_fifo[m_fifo_write] |= 0x80; + + if (((m_fifo_write + 1) & 15) != m_fifo_read) + { + (++m_fifo_write) &= 15; + update_status(); + } +} + +void gt913_kbd_hle_device::update_status() +{ + if (m_fifo_read == m_fifo_write) + m_status &= 0x7fff; + else + m_status |= 0x8000; + + if (BIT(m_status, 15) && BIT(m_status, 14)) + m_intc->internal_interrupt(m_irq); +} + +uint16_t gt913_kbd_hle_device::read() +{ + if (m_fifo_read == m_fifo_write) + return 0xff00; + + uint16_t data = (m_fifo[m_fifo_read] << 8) | m_velocity.read_safe(0x7f); + + if (!machine().side_effects_disabled()) + { + if (m_fifo_read != m_fifo_write) + { + (++m_fifo_read) &= 15; + update_status(); + } + } + + return data; +} + +void gt913_kbd_hle_device::status_w(uint16_t data) +{ + m_status = data; + update_status(); +} diff --git a/src/devices/machine/gt913_kbd.h b/src/devices/machine/gt913_kbd.h new file mode 100644 index 00000000000..3e44b1166cb --- /dev/null +++ b/src/devices/machine/gt913_kbd.h @@ -0,0 +1,62 @@ +// license:BSD-3-Clause +// copyright-holders: Devin Acker +/*************************************************************************** + Casio GT913 keyboard controller (HLE) +***************************************************************************/ + +#ifndef MAME_MACHINE_GT913_KBD_H +#define MAME_MACHINE_GT913_KBD_H + +#pragma once + +#include "cpu/h8/h8_intc.h" +#include "keyboard.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> gt913_kbd_hle_device + +class gt913_kbd_hle_device : public device_t, protected device_matrix_keyboard_interface<13> +{ +public: + // construction/destruction + gt913_kbd_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + gt913_kbd_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, const char *intc, int irq) + : gt913_kbd_hle_device(mconfig, tag, owner, 0) + { + m_intc_tag = intc; + m_irq = irq; + } + + uint16_t read(); + void status_w(uint16_t data); + uint16_t status_r() { return m_status; } + +protected: + // device_t overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_matrix_keyboard_interface overrides + virtual void key_make(uint8_t row, uint8_t column) override { key_add(row, column, 0); } + virtual void key_break(uint8_t row, uint8_t column) override { key_add(row, column, 1); } + + void key_add(uint8_t row, uint8_t column, int state); + void update_status(); +private: + h8_intc_device *m_intc; + const char *m_intc_tag; + int m_irq; + optional_ioport m_velocity; + + uint16_t m_status; + uint8_t m_fifo[16]; + uint8_t m_fifo_read, m_fifo_write; +}; + +// device type definition +DECLARE_DEVICE_TYPE(GT913_KBD_HLE, gt913_kbd_hle_device) + +#endif // MAME_MACHINE_GT913_KBD_H diff --git a/src/devices/machine/gt913_snd.cpp b/src/devices/machine/gt913_snd.cpp new file mode 100644 index 00000000000..8ffabac7077 --- /dev/null +++ b/src/devices/machine/gt913_snd.cpp @@ -0,0 +1,167 @@ +// license:BSD-3-Clause +// copyright-holders:Devin Acker +/*************************************************************************** + Casio GT913 sound (HLE) + + This is the sound portion of the GT913. + Up to 24 voices can be mixed into a 16-bit stereo serial bitstream, + which is then input to either a serial DAC or a HG51B-based DSP, + depending on the model of keyboard. + + Currently, the actual sample format in ROM is unknown. + The serial output is twos-complement 16-bit PCM, but the data in ROM + doesn't seem to be - reading it as such produces sounds that are + somewhat recognizable, but highly distorted. + + For now, all known (and unknown) register writes are just logged + without generating any sound. + +***************************************************************************/ + +#include "emu.h" +#include "gt913_snd.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(GT913_SOUND_HLE, gt913_sound_hle_device, "gt913_sound_hle", "Casio GT913F sound (HLE)") + +gt913_sound_hle_device::gt913_sound_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, GT913_SOUND_HLE, tag, owner, clock) +{ +} + +void gt913_sound_hle_device::device_start() +{ + save_item(NAME(m_gain)); + save_item(NAME(m_data)); + + save_item(NAME(m_volume_target)); + save_item(NAME(m_volume_rate)); +} + +void gt913_sound_hle_device::device_reset() +{ + m_gain = 0; + std::memset(m_data, 0, sizeof(m_data)); + std::memset(m_volume_target, 0, sizeof(m_volume_target)); + std::memset(m_volume_rate, 0, sizeof(m_volume_rate)); +} + +void gt913_sound_hle_device::data_w(offs_t offset, uint16_t data) +{ + assert(offset < 3); + m_data[offset] = data; +} + +uint16_t gt913_sound_hle_device::data_r(offs_t offset) +{ + assert(offset < 3); + return m_data[offset]; +} + +void gt913_sound_hle_device::command_w(uint16_t data) +{ + uint8_t voicenum = (data & 0x1f00) >> 8; + uint16_t voicecmd = data & 0x60ff; + + if (data == 0x0012) + { + uint8_t gain = m_data[0] & 0x3f; + if (gain != m_gain) + logerror("gain %u\n", gain); + m_gain = gain; + } + else if (voicenum >= 24) + { + return; + } + else if (voicecmd == 0x0008) + { + /* + Set the voice's sample start point as a ROM address. + This is usually word-aligned, but not always + (e.g. ctk551's lowest piano sample is at address 0x5a801) + */ + uint32_t samplestart = (m_data[1] | (m_data[2] << 16)) & 0xfffff; + logerror("voice %u sample start 0x%06x\n", voicenum, samplestart); + } + else if (voicecmd == 0x0000) + { + /* + Set the voice's sample end point as a ROM address. + */ + uint32_t sampleend = (m_data[0] | (m_data[1] << 16)) & 0xfffff; + logerror("voice %u sample end 0x%06x\n", voicenum, sampleend); + } + else if (voicecmd == 0x2000) + { + /* + Set the voice's sample loop point as a ROM address. + */ + uint32_t sampleloop = (m_data[0] | (m_data[1] << 16)) & 0xfffff; + logerror("voice %u sample loop 0x%06x\n", voicenum, sampleloop); + } + else if (voicecmd == 0x200b) + { + /* + Turn this voice on/off. + ctk551 turns output off before assigning a new note or instrument to this voice, + then turns output back on afterward + */ + logerror("voice %u output %s\n", voicenum, BIT(m_data[2], 7) ? "on" : "off"); + } + else if (voicecmd == 0x4004) + { + /* + Set this voice's panning, in the form of left and right volume levels (3 bits each) + */ + uint8_t left = (m_data[1] & 0xe0) >> 5; + uint8_t right = (m_data[1] & 0x1c) >> 2; + logerror("voice %u left %u right %u\n", voicenum, left, right); + } + else if (voicecmd == 0x4005) + { + /* + Set the current pitch of this voice. + The actual format of the value is unknown, but presumably some kind of fixed point + */ + uint32_t pitch = (m_data[0] << 8) | (m_data[1] >> 8); + logerror("voice %u pitch 0x%06x\n", voicenum, pitch); + } + else if (voicecmd == 0x6007) + { + /* + Raise or lower the volume to a specified level at a specified rate. + The actual volume level is probably 7.8 fixed point or something like that, but this command + only sets the most significant bits. + */ + logerror("voice %u volume %u rate %u\n", voicenum, (m_data[0] >> 8) & 0x7f, m_data[0] & 0xff); + m_volume_target[voicenum] = m_data[0] & 0x7f00; + m_volume_rate[voicenum] = m_data[0] & 0xff; + } + else if (voicecmd == 0x2028) + { + /* + ctk551 issues this command and then reads the voice's current volume from data0 + to determine if it's time to start the next part of the volume envelope or not. + For now, just return the "target" volume immediately + (TODO: also figure out what it expects to be returned in data1) + */ + m_data[0] = m_volume_target[voicenum]; + m_data[1] = 0; + } + else + { + logerror("unknown sound write %04x (data: %04x %04x %04x)\n", data, m_data[0], m_data[1], m_data[2]); + } +} + +uint16_t gt913_sound_hle_device::status_r() +{ + /* ctk551 reads the current gain level out of the lower 6 bits and ignores the rest + it's unknown what, if anything, the other bits are supposed to contain */ + return m_gain & 0x3f; +} diff --git a/src/devices/machine/gt913_snd.h b/src/devices/machine/gt913_snd.h new file mode 100644 index 00000000000..cc994690d3d --- /dev/null +++ b/src/devices/machine/gt913_snd.h @@ -0,0 +1,45 @@ +// license:BSD-3-Clause +// copyright-holders: Devin Acker +/*************************************************************************** + Casio GT913 sound (HLE) +***************************************************************************/ + +#ifndef MAME_AUDIO_GT913_H +#define MAME_AUDIO_GT913_H + +#pragma once + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> gt913_sound_hle_device + +class gt913_sound_hle_device : public device_t +{ +public: + // construction/destruction + gt913_sound_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + void data_w(offs_t offset, uint16_t data); + uint16_t data_r(offs_t offset); + void command_w(uint16_t data); + uint16_t status_r(); + +protected: + // device_t overrides + virtual void device_start() override; + virtual void device_reset() override; + +private: + uint8_t m_gain; + uint16_t m_data[3]; + + uint16_t m_volume_target[24]; + uint8_t m_volume_rate[24]; +}; + +// device type definition +DECLARE_DEVICE_TYPE(GT913_SOUND_HLE, gt913_sound_hle_device) + +#endif // MAME_AUDIO_GT913_H diff --git a/src/mame/drivers/ctk551.cpp b/src/mame/drivers/ctk551.cpp new file mode 100644 index 00000000000..1e3e324badd --- /dev/null +++ b/src/mame/drivers/ctk551.cpp @@ -0,0 +1,356 @@ +// license:BSD-3-Clause +// copyright-holders:Devin Acker +/* + Casio CTK-551 keyboard (and related models) + + Casio released several keyboard models with the same main board. + As usual, some of them were also rebranded by Radio Shack. + + - CTK-531, CTK-533 + Basic 61-key model + - CTK-541, Optimus MD-1150 + Adds velocity-sensitive keys + - CTK-551, CTK-558, Radio Shack MD-1160 + Adds pitch wheel and different selection of demo songs + + Main board (JCM456-MA1M): + + LSI1: CPU (Casio GT913F) + Custom chip based on H8/300 instruction set, built in peripheral controllers & sound generator + + LSI2: 8Mbit ROM (OKI MSM538002E) + + LSI3: LCD controller (HD44780 compatible) + May be either a Samsung KS0066U-10B or Epson SED1278F2A. + + IC1: stereo DAC (NEC uPD6379GR) + + CTK-541 service manual with schematics, pinouts, etc.: + https://revenant1.net/ctk541.pdf + + To access the test mode (not mentioned in the service manual): + Hold the "Start/Stop" and keypad 0 buttons together when turning on the keyboard. + Afterwards, press one of these buttons: + - Tone: LCD test (press repeatedly) + - Keypad 0: switch test (press all front panel buttons in a specific order, generally left to right) + - Keypad 1 or Rhythm: pedal and key test + - Keypad 2: ROM test + - Keypad 4/5/6: sound volume test + - Keypad 7/8: stereo test + - Keypad 9: MIDI loopback test + - Keypad + or Song Bank: power source test + - Keypad -: pitch wheel test + - FFWD: exit test mode + - Stop: power off + + */ + +#include "emu.h" + +#include "bus/midi/midiinport.h" +#include "bus/midi/midioutport.h" +#include "cpu/h8/gt913.h" +#include "video/hd44780.h" +#include "emupal.h" +#include "screen.h" + +namespace { + +class ctk551_state : public driver_device +{ +public: + ctk551_state(machine_config const &mconfig, device_type type, char const *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_lcdc(*this, "lcdc") + , m_led_touch(*this, "led_touch") + { + } + + void ctk551(machine_config &config); + + DECLARE_CUSTOM_INPUT_MEMBER(lcd_r) { return m_lcdc->db_r() >> 4; } + DECLARE_WRITE_LINE_MEMBER(lcd_w) { m_lcdc->db_w(state << 4); } + + DECLARE_CUSTOM_INPUT_MEMBER(switch_r) { return m_switch; } + DECLARE_INPUT_CHANGED_MEMBER(switch_w); + + DECLARE_WRITE_LINE_MEMBER(led_touch_w) { m_led_touch = state; } + DECLARE_WRITE_LINE_MEMBER(apo_w); + +private: + void ctk551_io_map(address_map &map); + + virtual void driver_start() override; + + HD44780_PIXEL_UPDATE(lcd_update); + void palette_init(palette_device &palette); + + required_device m_maincpu; + required_device m_lcdc; + + output_finder<> m_led_touch; + + ioport_value m_switch; +}; + + +INPUT_CHANGED_MEMBER(ctk551_state::switch_w) +{ + logerror("switch_w: %x\n", param); + if (!oldval && newval) + { + if (m_switch == 0x1 && param != m_switch) + m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE); + else + m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); + + m_switch = param; + } +} + +WRITE_LINE_MEMBER(ctk551_state::apo_w) +{ + logerror("apo_w: %x\n", state); + /* TODO: when 1, this should turn off the LCD, speakers, etc. + the CPU will go to sleep until the power switch triggers a NMI */ +} + +HD44780_PIXEL_UPDATE(ctk551_state::lcd_update) +{ + if (x < 6 && y < 8 && line < 2 && pos < 8) + bitmap.pix(line * 8 + y, pos * 6 + x) = state; +} + +void ctk551_state::palette_init(palette_device &palette) +{ + palette.set_pen_color(0, rgb_t(255, 255, 255)); + palette.set_pen_color(1, rgb_t(0, 0, 0)); +} + +void ctk551_state::ctk551_io_map(address_map &map) +{ + map(h8_device::PORT_1, h8_device::PORT_1).portr("P1_R").portw("P1_W").umask16(0x00ff); + map(h8_device::PORT_2, h8_device::PORT_2).portrw("P2").umask16(0x00ff); + map(h8_device::PORT_3, h8_device::PORT_3).portrw("P3").umask16(0x00ff); + map(h8_device::ADC_0, h8_device::ADC_0).portr("AN0"); + map(h8_device::ADC_1, h8_device::ADC_1).portr("AN1"); +} + +void ctk551_state::driver_start() +{ + m_led_touch.resolve(); + + m_switch = 0x2; + + save_item(NAME(m_switch)); +} + +void ctk551_state::ctk551(machine_config &config) +{ + // CPU + GT913(config, m_maincpu, 30'000'000); + m_maincpu->set_addrmap(AS_IO, &ctk551_state::ctk551_io_map); + + // MIDI + auto &mdin(MIDI_PORT(config, "mdin")); + midiin_slot(mdin); + mdin.rxd_handler().set("maincpu:sci", FUNC(h8_sci_device::rx_w)); + + auto &mdout(MIDI_PORT(config, "mdout")); + midiout_slot(mdout); + m_maincpu->subdevice("sci")->tx_handler().set(mdout, FUNC(midi_port_device::write_txd)); + + // LCD + HD44780(config, m_lcdc, 0); + m_lcdc->set_lcd_size(2, 8); + m_lcdc->set_pixel_update_cb(FUNC(ctk551_state::lcd_update)); + + // screen (for testing only) + // TODO: the actual LCD with custom segments + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD)); + screen.set_refresh_hz(60); + screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */ + screen.set_screen_update("lcdc", FUNC(hd44780_device::screen_update)); + screen.set_size(6 * 8, 8 * 2); + screen.set_visarea_full(); + screen.set_palette("palette"); + + PALETTE(config, "palette", FUNC(ctk551_state::palette_init), 2); +} + +INPUT_PORTS_START(ctk551) + PORT_START("maincpu:kbd:KO0") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C2") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C2#") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D2") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D2#") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E2") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F2") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F2#") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G2") + + PORT_START("maincpu:kbd:KO1") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G2#") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A2") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A2#") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B2") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C3") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C3#") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D3") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D3#") + + PORT_START("maincpu:kbd:KO2") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E3") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F3") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F3#") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G3") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G3#") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A3") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A3#") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B3") + + PORT_START("maincpu:kbd:KO3") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C4") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C4#") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D4") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D4#") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E4") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F4") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F4#") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G4") + + PORT_START("maincpu:kbd:KO4") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G4#") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A4") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A4#") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B4") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C5") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C5#") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D5") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D5#") + + PORT_START("maincpu:kbd:KO5") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E5") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F5") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F5#") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G5") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G5#") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A5") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A5#") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B5") + + PORT_START("maincpu:kbd:KO6") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C6") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C6#") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D6") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D6#") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E6") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F6") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F6#") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G6") + + PORT_START("maincpu:kbd:KO7") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G6#") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A6") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A6#") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B6") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C7") + PORT_BIT( 0xe0, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("maincpu:kbd:KO8") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 9") PORT_CODE(KEYCODE_9_PAD) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 8") PORT_CODE(KEYCODE_8_PAD) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 7") PORT_CODE(KEYCODE_7_PAD) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad +") PORT_CODE(KEYCODE_PLUS_PAD) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Touch Response") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Song Bank") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Rhythm") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Tone") + + PORT_START("maincpu:kbd:KO9") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 6") PORT_CODE(KEYCODE_6_PAD) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 5") PORT_CODE(KEYCODE_5_PAD) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 4") PORT_CODE(KEYCODE_4_PAD) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad -") PORT_CODE(KEYCODE_MINUS_PAD) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Accomp Volume") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Transpose / Tune / MIDI") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Chord Book") + + PORT_START("maincpu:kbd:KO10") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 3") PORT_CODE(KEYCODE_3_PAD) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 2") PORT_CODE(KEYCODE_2_PAD) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 1") PORT_CODE(KEYCODE_1_PAD) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 0") PORT_CODE(KEYCODE_0_PAD) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Play / Pause") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Rewind") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Start / Stop") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Sync / Fill In") + + PORT_START("maincpu:kbd:KO11") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right Hand On/Off") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left Hand On/Off") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fast Forward") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Stop") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Tempo Down") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Volume Down") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Tempo Up") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Volume Up") + + PORT_START("maincpu:kbd:KO12") + PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(ctk551_state, switch_r) + + PORT_START("maincpu:kbd:VELOCITY") + PORT_BIT( 0x7f, 0x7f, IPT_POSITIONAL ) PORT_NAME("Key Velocity") PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_CENTERDELTA(0) + + PORT_START("SWITCH") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Power Off") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_w, 0x1) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Normal") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_w, 0x2) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Casio Chord") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_w, 0x4) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fingered") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_w, 0x8) + + PORT_START("P1_R") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Pedal") + PORT_BIT( 0x0c, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(ctk551_state, lcd_r) + + PORT_START("P1_W") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(ctk551_state, led_touch_w) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OUTPUT ) // unknown + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("lcdc", hd44780_device, e_w) + PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(ctk551_state, lcd_w) + + PORT_START("P2") + PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("lcdc", hd44780_device, rs_w) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("lcdc", hd44780_device, rw_w) + PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + + PORT_START("P3") + PORT_BIT( 0x3f, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(ctk551_state, apo_w) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + + PORT_START("AN0") + PORT_CONFNAME( 0xff, 0x00, "Power Source" ) + PORT_CONFSETTING( 0x00, "AC Adapter" ) + PORT_CONFSETTING( 0xff, "Battery" ) + + PORT_START("AN1") + PORT_BIT( 0xff, 0x7f, IPT_PADDLE ) PORT_NAME("Pitch Wheel") PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_MINMAX(0x00, 0xff) + +INPUT_PORTS_END + +ROM_START(ctk551) + ROM_REGION(0x100000, "maincpu", 0) + ROM_LOAD16_WORD_SWAP("ctk551.lsi2", 0x000000, 0x100000, CRC(66fc34cd) SHA1(47e9559edc106132f8a83462ed17a6c5c3872157)) +ROM_END + +} // anonymous namespace + +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +SYST( 1999, ctk551, 0, 0, ctk551, ctk551, ctk551_state, empty_init, "Casio", "CTK-551", MACHINE_NO_SOUND | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 3788037bd54..3c9df882286 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -11567,6 +11567,9 @@ cswat // (c) 1984 @source:ct486.cpp ct486 // 1993? 486 with CS4031 +@source:ctk551.cpp +ctk551 // + @source:cubeqst.cpp cubeqst // (c) 1983 Simutrek Inc. cubeqsta // (c) 1983 Simutrek Inc. diff --git a/src/mame/mess.flt b/src/mame/mess.flt index 6a20e1480d1..feccd2dc9f5 100644 --- a/src/mame/mess.flt +++ b/src/mame/mess.flt @@ -207,6 +207,7 @@ crei680.cpp crimson.cpp crvision.cpp ct486.cpp +ctk551.cpp cvicny.cpp cxg_ch2001.cpp cxg_dominator.cpp -- cgit v1.2.3