diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 37db2a904a887..7a1226540d7a6 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -2577,6 +2577,21 @@ if (BUSES["SS50"]~=null) then end +--------------------------------------------------- +-- +--@src/devices/bus/technics/hdae5000.h,BUSES["TECHNICS"] = true +--------------------------------------------------- + +if (BUSES["TECHNICS"]~=null) then + files { + MAME_DIR .. "src/devices/bus/technics/kn5000_extension.cpp", + MAME_DIR .. "src/devices/bus/technics/kn5000_extension.h", + MAME_DIR .. "src/devices/bus/technics/hdae5000.cpp", + MAME_DIR .. "src/devices/bus/technics/hdae5000.h", + } +end + + --------------------------------------------------- -- --@src/devices/bus/tiki100/exp.h,BUSES["TIKI100"] = true diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 85de8acd3c8aa..397d6c0ceee4e 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -2938,6 +2938,8 @@ if CPUS["TLCS900"] then MAME_DIR .. "src/devices/cpu/tlcs900/tlcs900.h", MAME_DIR .. "src/devices/cpu/tlcs900/900tbl.hxx", MAME_DIR .. "src/devices/cpu/tlcs900/900htbl.hxx", + MAME_DIR .. "src/devices/cpu/tlcs900/tmp94c241.cpp", + MAME_DIR .. "src/devices/cpu/tlcs900/tmp94c241.h", MAME_DIR .. "src/devices/cpu/tlcs900/tmp95c061.cpp", MAME_DIR .. "src/devices/cpu/tlcs900/tmp95c061.h", MAME_DIR .. "src/devices/cpu/tlcs900/tmp95c063.cpp", diff --git a/src/devices/bus/technics/hdae5000.cpp b/src/devices/bus/technics/hdae5000.cpp new file mode 100644 index 0000000000000..c682dbb36a2c7 --- /dev/null +++ b/src/devices/bus/technics/hdae5000.cpp @@ -0,0 +1,110 @@ +// license:BSD-3-Clause +// copyright-holders:Antoine Mine, Olivier Galibert, Felipe Sanches +// +// HD-AE5000, Hard Disk & Audio Extension for Technics KN5000 emulation +// +// The HD-AE5000 was an extension board for the Technics KN5000 musical keyboard. +// It provided a hard-disk, additional audio outputs and a serial port to interface +// with a computer to transfer files to/from the hard-drive. + +#include "emu.h" +#include "bus/ata/hdd.h" +#include "hdae5000.h" +#include "machine/i8255.h" + +namespace { + +class hdae5000_device : public device_t, public kn5000_extension_interface +{ +public: + static constexpr feature_type unemulated_features() { return feature::DISK | feature::SOUND; } + + hdae5000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void rom_map(address_map &map) override; + virtual void io_map(address_map &map) override; + +protected: + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + virtual void device_reset() override; + virtual const tiny_rom_entry *device_rom_region() const override; + +private: + required_device m_hdd; + required_device m_ppi; + required_memory_region m_rom; +}; + +hdae5000_device::hdae5000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, HDAE5000, tag, owner, clock) + , kn5000_extension_interface(mconfig, *this) + , m_hdd(*this, "hdd") + , m_ppi(*this, "ppi") + , m_rom(*this, "rom") +{ +} + +ROM_START(hdae5000) + ROM_REGION16_LE(0x80000, "rom" , 0) + ROM_DEFAULT_BIOS("v2.01i") + + ROM_SYSTEM_BIOS(0, "v1.10i", "Version 1.10i - July 6th, 1998") + ROMX_LOAD("hd-ae5000_v1_10i.ic4", 0x000000, 0x80000, CRC(7461374b) SHA1(6019f3c28b6277730418974dde4dc6893fced00e), ROM_BIOS(0)) + + ROM_SYSTEM_BIOS(1, "v1.15i", "Version 1.15i - October 13th, 1998") + ROMX_LOAD("hd-ae5000_v1_15i.ic4", 0x000000, 0x80000, CRC(e76d4b9f) SHA1(581fa58e2cd6fe381cfc312c73771d25ff2e662c), ROM_BIOS(1)) + + // Version 2.01i is described as having "additions like lyrics display etc." + ROM_SYSTEM_BIOS(2, "v2.01i", "Version 2.01i - January 15th, 1999") // installation file indicated "v2.0i" but signature inside the ROM is "v2.01i" + ROMX_LOAD("hd-ae5000_v2_01i.ic4", 0x000000, 0x80000, CRC(961e6dcd) SHA1(0160c17baa7b026771872126d8146038a19ef53b), ROM_BIOS(2)) +ROM_END + +void hdae5000_device::rom_map(address_map &map) +{ + map(0x00000, 0x7ffff).rom().region(m_rom, 0); +} + +void hdae5000_device::io_map(address_map &map) +{ + //map(0x130000, 0x13ffff).m(m_hddc, FUNC(?_device::?)); // Hard-drive Controller (model?) IC? on HD-AE5000 board + //map(0x160000, 0x16ffff) ... Optional parallel port interface (NEC uPD71055) IC9 + map(0x160000, 0x160000).lrw8([this](offs_t a) { return m_ppi->read(0); }, "ppi_r0", [this](offs_t a, u8 data) { m_ppi->write(0, data); }, "ppi_w0"); + map(0x160002, 0x160002).lrw8([this](offs_t a) { return m_ppi->read(1); }, "ppi_r1", [this](offs_t a, u8 data) { m_ppi->write(1, data); }, "ppi_w1"); + map(0x160004, 0x160004).lrw8([this](offs_t a) { return m_ppi->read(2); }, "ppi_r2", [this](offs_t a, u8 data) { m_ppi->write(2, data); }, "ppi_w2"); + map(0x160006, 0x160006).lrw8([this](offs_t a) { return m_ppi->read(3); }, "ppi_r3", [this](offs_t a, u8 data) { m_ppi->write(3, data); }, "ppi_w3"); +} + +const tiny_rom_entry *hdae5000_device::device_rom_region() const +{ + return ROM_NAME(hdae5000); +} + +void hdae5000_device::device_add_mconfig(machine_config &config) +{ + /* Optional Hard Disk - HD-AE5000 */ + IDE_HARDDISK(config, m_hdd, 0); + + /* Optional Parallel Port */ + I8255(config, m_ppi); // actual chip is a NEC uPD71055 @ IC9 on the HD-AE5000 board + // m_ppi->in_pa_callback().set(FUNC(?_device::ppi_in_a)); + // m_ppi->out_pb_callback().set(FUNC(?_device::ppi_out_b)); + // m_ppi->in_pc_callback().set(FUNC(?_device::ppi_in_c)); + // m_ppi->out_pc_callback().set(FUNC(?_device::ppi_out_c)); + +// we may later add this, for the auxiliary audio output provided by this extension board: +// SPEAKER(config, "mono").front_center(); +} + +void hdae5000_device::device_start() +{ +// save_item(NAME(m_...)); +} + +void hdae5000_device::device_reset() +{ +} + +} // anonymous namespace + +DEFINE_DEVICE_TYPE_PRIVATE(HDAE5000, kn5000_extension_interface, hdae5000_device, "hdae5000", "HD-AE5000, Hard Disk & Audio Extension") diff --git a/src/devices/bus/technics/hdae5000.h b/src/devices/bus/technics/hdae5000.h new file mode 100644 index 0000000000000..05633a6519969 --- /dev/null +++ b/src/devices/bus/technics/hdae5000.h @@ -0,0 +1,16 @@ +// license:BSD-3-Clause +// copyright-holders:Antoine Mine, Olivier Galibert, Felipe Sanches +// +// HD-AE5000 emulation +// +#ifndef MAME_BUS_TECHNICS_HDAE5000_H +#define MAME_BUS_TECHNICS_HDAE5000_H + +#pragma once + +#include "kn5000_extension.h" + +// device type declaration +DECLARE_DEVICE_TYPE(HDAE5000, kn5000_extension_interface) + +#endif // MAME_BUS_TECHNICS_HDAE5000_H diff --git a/src/devices/bus/technics/kn5000_extension.cpp b/src/devices/bus/technics/kn5000_extension.cpp new file mode 100644 index 0000000000000..ab891a32c7e2c --- /dev/null +++ b/src/devices/bus/technics/kn5000_extension.cpp @@ -0,0 +1,56 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert, Felipe Sanches + +// Generic Technics KN5000 extension slot + + +#include "emu.h" +#include "kn5000_extension.h" + +DEFINE_DEVICE_TYPE(KN5000_EXTENSION, kn5000_extension_device, "kn5000_extension", "Technics KN5000 extension port") + +kn5000_extension_device::kn5000_extension_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, KN5000_EXTENSION, tag, owner, clock), + device_single_card_slot_interface(mconfig, *this) +// FIXME: do we need these? +// m_firq_callback(*this), +// m_irq_callback(*this) +{ +} + +void kn5000_extension_device::rom_map(address_space_installer &space, offs_t start, offs_t end) +{ + auto dev = get_card_device(); + if(dev) + space.install_device(start, end, *dev, &kn5000_extension_interface::rom_map); +} + +void kn5000_extension_device::io_map(address_space_installer &space, offs_t start, offs_t end) +{ + auto dev = get_card_device(); + if(dev) + space.install_device(start, end, *dev, &kn5000_extension_interface::io_map); +} + +void kn5000_extension_device::device_start() +{ +} + +kn5000_extension_interface::kn5000_extension_interface(const machine_config &mconfig, device_t &device) : + device_interface(device, "extension"), + m_ext(dynamic_cast(device.owner())) +{ +} + +// FIXME: do we need these? +//WRITE_LINE_MEMBER(kn5000_extension_interface::firq_w) +//{ +// if(m_ext) +// m_ext->m_firq_callback(state); +//} +// +//WRITE_LINE_MEMBER(kn5000_extension_interface::irq_w) +//{ +// if(m_ext) +// m_ext->m_irq_callback(state); +//} diff --git a/src/devices/bus/technics/kn5000_extension.h b/src/devices/bus/technics/kn5000_extension.h new file mode 100644 index 0000000000000..3bf486b3579bd --- /dev/null +++ b/src/devices/bus/technics/kn5000_extension.h @@ -0,0 +1,47 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert, Felipe Sanches +// +// Generic Technics KN5000 extension slot + +#ifndef MAME_BUS_TECHNICS_KN5000_EXTENSION_H +#define MAME_BUS_TECHNICS_KN5000_EXTENSION_H + +#pragma once + +class kn5000_extension_device; + +class kn5000_extension_interface : public device_interface +{ +public: + kn5000_extension_interface(const machine_config &mconfig, device_t &device); + + virtual void rom_map(address_map &map) = 0; + virtual void io_map(address_map &map) = 0; + +// FIXME: do we need these? +//protected: +// DECLARE_WRITE_LINE_MEMBER(firq_w); +// DECLARE_WRITE_LINE_MEMBER(irq_w); + +private: + kn5000_extension_device *const m_ext; +}; + + +class kn5000_extension_device : public device_t, public device_single_card_slot_interface +{ + friend class kn5000_extension_interface; + +public: + kn5000_extension_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + void rom_map(address_space_installer &space, offs_t start, offs_t end); + void io_map(address_space_installer &space, offs_t start, offs_t end); + +protected: + virtual void device_start() override; +}; + +DECLARE_DEVICE_TYPE(KN5000_EXTENSION, kn5000_extension_device) + +#endif // MAME_BUS_TECHNICS_KN5000_EXTENSION_H diff --git a/src/devices/cpu/tlcs900/dasm900.cpp b/src/devices/cpu/tlcs900/dasm900.cpp index af78c98b8e565..be555b9f58be5 100644 --- a/src/devices/cpu/tlcs900/dasm900.cpp +++ b/src/devices/cpu/tlcs900/dasm900.cpp @@ -9,6 +9,11 @@ Toshiba TLCS-900/H disassembly #include "emu.h" #include "dasm900.h" +tlcs900_disassembler::tlcs900_disassembler(uint16_t num_sfr, const char *const sfr_names[]) + : m_num_sfr(num_sfr), m_sfr_names(sfr_names) +{ +} + const char *const tlcs900_disassembler::s_mnemonic[] = { "adc", "add", "and", "andcf", "bit", "bs1b", @@ -1369,12 +1374,260 @@ const char *const tlcs900_disassembler::s_cond[16] = "F","LT","LE","ULE","PE/OV","M/MI","Z","C","T","GE","GT","UGT","PO/NOV","P/PL","NZ","NC" }; +tmp94c241_disassembler::tmp94c241_disassembler() + : tlcs900_disassembler(0x170, s_sfr_names) +{ +} + +const char *const tmp94c241_disassembler::s_sfr_names[0x170] = { + /* TLCS-900/H2 type 8 bit I/O: */ + /* 00:*/ "P0", "0x01", "P0CR", "P0FC", "P1", "0x05", "P1CR", "P1FC", + /* 08:*/ "P2", "0x09", "P2CR", "P2FC", "P3", "0x0d", "P3CR", "P3FC", + /* 10:*/ "P4", "0x11", "P4CR", "P4FC", "P5", "0x15", "P5CR", "P5FC", + /* 18:*/ "P6", "0x19", "P6CR", "P6FC", "P7", "0x1d", "P7CR", "P7FC", + /* 20:*/ "P8", "0x21", "P8CR", "P8FC", "0x24", "0x25", "0x26", "0x27", + /* 28:*/ "PA", "0x29", "0x2a", "PAFC", "PB", "0x2d", "0x2e", "PBFC", + /* 30:*/ "PC", "0x31", "PCCR", "PCFC", "PD", "0x35", "PDCR", "PDFC", + /* 38:*/ "PE", "0x39", "PECR", "PEFC", "PF", "0x3d", "PFCR", "PFFC", + /* 40:*/ "PG", "0x41", "0x42", "0x43", "PH", "0x45", "PHCR", "PHFC", + /* 48:*/ "0x48", "0x49", "0x4a", "0x4b", "0x4c", "0x4d", "0x4e", "0x4f", + /* 50:*/ "0x50", "0x51", "0x52", "0x53", "0x54", "0x55", "0x56", "0x57", + /* 58:*/ "0x58", "0x59", "0x5a", "0x5b", "0x5c", "0x5d", "0x5e", "0x5f", + /* 60:*/ "0x60", "0x61", "0x62", "0x63", "0x64", "0x65", "0x66", "0x67", + /* 68:*/ "PZ", "0x69", "PZCR", "0x6b", "0x6c", "0x6d", "0x6e", "0x6f", + /* 70:*/ "0x70", "0x71", "0x72", "0x73", "0x74", "0x75", "0x76", "0x77", + /* 78:*/ "0x78", "0x79", "0x7a", "0x7b", "0x7c", "0x7d", "0x7e", "0x7f", + + /* TLCS-90 type I/O: */ + /* 80:*/ "T8RUN", "TRDC", "T02FFCR", "0x83", "T01MOD", "T23MOD", "0x86", "0x87", + /* 88:*/ "TREG0", "TREG1", "TREG2", "TREG3", "0x8c", "0x8d", "0x8e", "0x8f", + /* 90:*/ "TREG4L", "TREG4H", "TREG5L", "TREG5H", "CAP4L", "CAP4H", "CAP5L", "CAP5H", + /* 98:*/ "T4MOD", "T4FFCR", "0x9a", "0x9b", "0x9c", "0x9d", "T16RUN", "T16CR", + /* a0:*/ "TREG6L", "TREG6H", "TREG7L", "TREG7H", "CAP6L", "CAP6H", "CAP7L", "CAP7H", + /* a8:*/ "T6MOD", "T6FFCR", "0xaa", "0xab", "0xac", "0xad", "0xae", "0xaf", + /* b0:*/ "TREG8L", "TREG8H", "TREG9L", "TREG9H", "CAP8L", "CAP8H", "CAP9L", "CAP9H", + /* b8:*/ "T8MOD", "T8FFCR", "0xba", "0xbb", "0xbc", "0xbd", "0xbe", "0xbf", + /* c0:*/ "TREGAL", "TREGAH", "TREGBL", "TREGBH", "CAPAL", "CAPAH", "CAPBL", "CAPBH", + /* c8:*/ "TAMOD", "TAFFCR", "0xca", "0xcb", "0xcc", "0xcd", "0xce", "0xcf", + /* d0:*/ "SC0BUF", "SC0CR", "SC0MOD", "BR0CR", "SC1BUF", "SC1CR", "SC1MOD", "BR1CR", + /* d8:*/ "0xd8", "0xd9", "0xda", "0xdb", "0xdc", "0xdd", "0xde", "0xdf", + + /* TLCS-900/H2 type 8 bit I/O: */ + /* e0:*/ "INTE45", "INTE67", "INTE89", "INTEAB", "INTET01", "INTET23", "INTET45", "INTET67", + /* e8:*/ "INTET89", "INTETAB", "INTES0", "INTES1", "INTETC01","INTETC23","INTETC45","INTETC67", + /* f0:*/ "INTE0AD", "0xf1", "0xf2", "0xf3", "0xf4", "0xf5", "IIMC", "INTNMWDT", + /* f8:*/ "INTCLR", "0xf9", "0xfa", "0xfb", "0xfc", "0xfd", "0xfe", "0xff", + /*100:*/ "DMA0V", "DMA1V", "DMA2V" , "DMA3V", "DMA4V", "DMA5V", "DMA6V", "DMA7V", + /*108:*/ "DMAB", "DMAR", "CLKMOD" , "0x10b", "0x10c", "0x10d", "0x10e", "0x10f", + + /* TLCS-90 type I/O: */ + /*110:*/ "WDMOD", "WDCR", "0x112" , "0x113", "0x114", "0x115", "0x116", "0x117", + /*118:*/ "0x118", "0x119", "0x11a", "0x11b", "0x11c", "0x11d", "0x11e", "0x11f", + /*120:*/ "ADREG04L","ADREG04H","ADREG15L","ADREG15H","ADREG26L","ADREG26H","ADREG37L","ADREG37H", + /*128:*/ "ADMOD1", "ADMOD2", "0x12a", "0x12b", "0x12c", "0x12d", "0x12e", "0x12f", + /*130:*/ "DAREG0", "DAREG1", "DADRV", "0x133", "0x134", "0x135", "0x136", "0x137", + /*138:*/ "0x138", "0x139", "0x13a", "0x13b", "0x13c", "0x13d", "0x13e", "0x13f", + + /* TLCS-900/H2 type 8 bit I/O: */ + /*140:*/ "B0CSL", "B0CSH", "MAMR0", "MSAR0", "B1CSL", "B1CSH", "MAMR1", "MSAR1", + /*148:*/ "B2CSL", "B2CSH", "MAMR2", "MSAR2", "B3CSL", "B3CSH", "MAMR3", "MSAR3", + /*150:*/ "B4CSL", "B4CSH", "MAMR4", "MSAR4", "B5CSL", "B5CSH", "MAMR5", "MSAR5", + /*158:*/ "0x158", "0x159", "0x15a", "0x15b", "0x15c", "0x15d", "0x15e", "0x15f", + /*160:*/ "DRAM0CRL","DRAM0CRH","DRAM1CRL","DRAM1CRH","DRAM0REF","DRAM1REF","PMEMCR", "0x167", + /*168:*/ "0x168", "0x169", "0x16a", "0x16b", "0x16c", "0x16d", "0x16e", "0x16f", +}; + +tmp95c061_disassembler::tmp95c061_disassembler() + : tlcs900_disassembler(0x80, s_sfr_names) +{ +} + +const char *const tmp95c061_disassembler::s_sfr_names[0x80] = { + /*00:*/ "0x00", "P1", "0x02", "0x03", "P1CR", "0x05", "P2", "0x07", + /*08:*/ "0x08", "P2FC", "0x0a", "0x0b", "0x0c", "P5", "0x0e", "0x0f", + /*10:*/ "P5CR", "P5FC", "P6", "P7", "0x14", "P6FC", "P7CR", "P7FC", + /*18:*/ "P8", "P9", "P8CR", "P8FC", "0x1c", "0x1d", "PA", "PB", + /*20:*/ "TRUN", "0x21", "TREG0", "TREG1", "T01MOD", "TFFCR", "TREG2", "TREG3", + /*28:*/ "T23MOD", "TRDC", "0x2a", "0x2b", "PACR", "PAFC", "PBCR", "PBFC", + /*30:*/ "TREG4L", "TREG4H", "TREG5L", "TREG5H", "CAP1L", "CAP1H", "CAP2L", "CAP2H", + /*38:*/ "T4MOD", "T4FFCR", "T45CR", "0x3b", "MSAR0", "MAMR0", "MSAR1", "MAMR1", + /*40:*/ "TREG6L", "TREG6H", "TREG7L", "TREG7H", "CAP3L", "CAP3H", "CAP4L", "CAP4H", + /*48:*/ "T5MOD", "T5FFCR", "0x4a", "0x4b", "PG0REG", "PG1REG", "PG01CR", "0x4f", + /*50:*/ "SC0BUF", "SC0CR", "SC0MOD", "BR0CR", "SC1BUF", "SC1CR", "SC1MOD", "BR1CR", + /*58:*/ "ODE", "0x59", "DREFCR", "DMEMCR", "MSAR2", "MAMR2", "MSAR3", "MAMR3", + /*60:*/ "ADREG0L", "ADREG0H", "ADREG1L", "ADREG1H", "ADREG2L", "ADREG2H", "ADREG3L", "ADREG3H", + /*68:*/ "B0CS", "B1CS", "B2CS", "B3CS", "BEXCS", "ADMOD", "WDMOD", "WDCR", + /*70:*/ "INTE0AD", "INTE45", "INTE67", "INTET10", "INTET32", "INTET54", "INTET76", "INTES0", + /*78:*/ "INTES1", "INTETC01","INTETC23","IIMC", "DMA0V", "DMA1V", "DMA2V", "DMA3V" +}; + +tmp95c063_disassembler::tmp95c063_disassembler() + : tlcs900_disassembler(0xa0, s_sfr_names) +{ +} + +const char *const tmp95c063_disassembler::s_sfr_names[0xa0] = { + /*00:*/ "0x00", "P1", "0x02", "0x03", "P1CR", "0x05", "P2", "0x07", + /*08:*/ "0x08", "P2FC", "0x0a", "0x0b", "0x0c", "P5", "0x0e", "0x0f", + /*10:*/ "P5CR", "P5FC", "P6", "P7", "0x14", "P6FC", "P7CR", "P7FC", + /*18:*/ "P8", "P9", "P8CR", "P8FC", "P9CR", "P9FC", "PA", "PB", + /*20:*/ "T8RUN", "TRDC", "TREG0", "TREG1", "T01MOD", "T02FFCR", "TREG2", "TREG3", + /*28:*/ "T23MOD", "TREG4", "TREG5", "T45MOD", "TA46FFCR","TREG6", "TREG7", "T67MOD", + /*30:*/ "TREG8L", "TREG8H", "TREG9L", "TREG9H", "CAP1L", "CAP1H", "CAP2L", "CAP2H", + /*38:*/ "T8MOD", "T8FFCR", "T89CR", "T16RUN", "0x3c", "0x3d", "0x3e", "0x3f", + /*40:*/ "TREGAL", "TREGAH", "TREGBL", "TREGBH", "CAP3L", "CAP3H", "CAP4L", "CAP4H", + /*48:*/ "T9MOD", "T9FFCR", "DAREG0", "DAREG1", "PG0REG", "PG1REG", "PG01CR", "DADRV", + /*50:*/ "SC0BUF", "SC0CR", "SC0MOD", "BR0CR", "SC1BUF", "SC1CR", "SC1MOD", "BR1CR", + /*58:*/ "ODE", "0x59", "DMA0V", "DMA1V", "DMA2V", "DMA3V", "ADMOD1", "ADMOD2", + /*60:*/ "ADREG04L","ADREG04H","ADREG15L","ADREG15H","ADREG26L","ADREG26H","ADREG37L","ADREG37H", + /*68:*/ "0x68", "0x69", "SDMACR0", "SDMACR1", "SDMACR2", "SDMACR3", "WDMOD", "WDCR", + /*70:*/ "INTE_0AD","INTE12", "INTE34", "INTE56", "INT78", "INTET01", "INTET32", "INTET45", + /*78:*/ "INTET67", "INTET89", "INTETAB", "INTES0", "INTES1", "INTETC01","INTETC23","IIMC" + /*80:*/ "PACR", "PAFC", "PBCR", "PBFC", "PC", "PD", "0x86", "0x87", + /*88:*/ "PDCR", "0x89", "PE", "0x8B", "PECR", "0x8D", "0x8E", "BEXCS", + /*90:*/ "B0CS", "B1CS", "B2CS", "B3CS", "MSAR0", "MAMR0", "MSAR1", "MAMR1", + /*98:*/ "MSAR2", "MAMR2", "MSAR3", "MAMR3", "DREFCR1", "DMEMCR1", "DREFCR3", "DMEMCR3" +}; + +tmp96c141_disassembler::tmp96c141_disassembler() + : tlcs900_disassembler(0x80, s_sfr_names) +{ +} + +const char *const tmp96c141_disassembler::s_sfr_names[0x80] = { + /*00:*/ "P0", "P1", "P0CR", "0x03", "P1CR", "P1FC", "P2", "P3", + /*08:*/ "P2CR", "P2FC", "P3CR", "P3FC", "P4", "P5", "P4CR", "0x0f", + /*10:*/ "P4FC", "0x11", "P6", "P7", "P6CR", "P7CR", "P6FC", "P7FC", + /*18:*/ "P8", "P9", "P8CR", "P9CR", "P8FC", "P9FC", "0x1e", "0x1f", + /*20:*/ "TRUN", "0x21", "TREG0", "TREG1", "TMOD", "TFFCR", "TREG2", "TREG3", + /*28:*/ "P0MOD", "P1MOD", "PFFCR", "0x2b", "0x2c", "0x2d", "0x2e", "0x2f", + /*30:*/ "TREG4L", "TREG4H", "TREG5L", "TREG5H", "CAP1L", "CAP1H", "CAP2L", "CAP2H", + /*38:*/ "T4MOD", "T4FFCR", "T45CR", "0x3b", "0x3c", "0x3d", "0x3e", "0x3f", + /*40:*/ "TREG6L", "TREG6H", "TREG7L", "TREG7H", "CAP3L", "CAP3H", "CAP4L", "CAP4H", + /*48:*/ "T5MOD", "T5FFCR", "0x4a", "0x4b", "PG0REG", "PG1REG", "PG01CR", "0x4f", + /*50:*/ "SC0BUF", "SC0CR", "SC0MOD", "BR0CR", "SC1BUF", "SC1CR", "SC1MOD", "BR1CR", + /*58:*/ "ODE", "0x59", "0x5a", "0x5b", "WDMOD", "WDCR", "ADMOD", "0x5f", + /*60:*/ "ADREG0L", "ADREG0H", "ADREG1L", "ADREG1H", "ADREG2L", "ADREG2H", "ADREG3L", "ADREG3H", + /*68:*/ "B0CS", "B1CS", "B2CS", "0x6b", "0x6c", "0x6d", "0x6e", "0x6f", + /*70:*/ "INTE0AD", "INTE45", "INTE67", "INTET10", "INTEPW10","INTET54", "INTET76", "INTES0", + /*78:*/ "INTES1", "0x79", "0x7a", "IIMC", "DMA0V", "DMA1V", "DMA2V", "DMA3V" +}; + u32 tlcs900_disassembler::opcode_alignment() const { return 1; } +void tlcs900_disassembler::decode_control_register_8(std::ostream &stream, uint8_t imm){ + switch( imm ) + { + case 0x22: util::stream_format(stream, " DMAM0"); break; + case 0x26: util::stream_format(stream, " DMAM1"); break; + case 0x2a: util::stream_format(stream, " DMAM2"); break; + case 0x2e: util::stream_format(stream, " DMAM3"); break; + default: + util::stream_format(stream, " unknown (encoding is 0x%02x)", imm); + break; + } +} + + +void tmp94c241_disassembler::decode_control_register_8(std::ostream &stream, uint8_t imm){ + switch( imm ) + { + case 0x42: util::stream_format(stream, " DMAM0"); break; + case 0x46: util::stream_format(stream, " DMAM1"); break; + case 0x4a: util::stream_format(stream, " DMAM2"); break; + case 0x4e: util::stream_format(stream, " DMAM3"); break; + case 0x52: util::stream_format(stream, " DMAM4"); break; + case 0x56: util::stream_format(stream, " DMAM5"); break; + case 0x5a: util::stream_format(stream, " DMAM6"); break; + case 0x5e: util::stream_format(stream, " DMAM7"); break; + default: + util::stream_format(stream, " unknown (encoding is 0x%02x)", imm); + break; + } +} + + +void tlcs900_disassembler::decode_control_register_16(std::ostream &stream, uint8_t imm){ + switch( imm ) + { + case 0x20: util::stream_format(stream, " DMAC0"); break; + case 0x24: util::stream_format(stream, " DMAC1"); break; + case 0x28: util::stream_format(stream, " DMAC2"); break; + case 0x2c: util::stream_format(stream, " DMAC3"); break; + case 0x7c: util::stream_format(stream, " NSP"); break; + default: + util::stream_format(stream, " unknown (encoding is 0x%02x)", imm); + break; + } +} + + +void tmp94c241_disassembler::decode_control_register_16(std::ostream &stream, uint8_t imm){ + switch( imm ) + { + case 0x40: util::stream_format(stream, " DMAC0"); break; + case 0x44: util::stream_format(stream, " DMAC1"); break; + case 0x48: util::stream_format(stream, " DMAC2"); break; + case 0x4c: util::stream_format(stream, " DMAC3"); break; + case 0x50: util::stream_format(stream, " DMAC4"); break; + case 0x54: util::stream_format(stream, " DMAC5"); break; + case 0x58: util::stream_format(stream, " DMAC6"); break; + case 0x5c: util::stream_format(stream, " DMAC7"); break; + default: + util::stream_format(stream, " unknown (encoding is 0x%02x)", imm); + break; + } +} + + +void tlcs900_disassembler::decode_control_register_32(std::ostream &stream, uint8_t imm){ + switch( imm ) + { + case 0x00: util::stream_format(stream, " DMAS0"); break; + case 0x04: util::stream_format(stream, " DMAS1"); break; + case 0x08: util::stream_format(stream, " DMAS2"); break; + case 0x0c: util::stream_format(stream, " DMAS3"); break; + case 0x10: util::stream_format(stream, " DMAD0"); break; + case 0x14: util::stream_format(stream, " DMAD1"); break; + case 0x18: util::stream_format(stream, " DMAD2"); break; + case 0x1c: util::stream_format(stream, " DMAD3"); break; + default: + util::stream_format(stream, " unknown (encoding is 0x%02x)", imm); + break; + } +} + + +void tmp94c241_disassembler::decode_control_register_32(std::ostream &stream, uint8_t imm){ + switch( imm ) + { + case 0x00: util::stream_format(stream, " DMAS0"); break; + case 0x04: util::stream_format(stream, " DMAS1"); break; + case 0x08: util::stream_format(stream, " DMAS2"); break; + case 0x0c: util::stream_format(stream, " DMAS3"); break; + case 0x10: util::stream_format(stream, " DMAS4"); break; + case 0x14: util::stream_format(stream, " DMAS5"); break; + case 0x18: util::stream_format(stream, " DMAS6"); break; + case 0x1c: util::stream_format(stream, " DMAS7"); break; + case 0x20: util::stream_format(stream, " DMAD0"); break; + case 0x24: util::stream_format(stream, " DMAD1"); break; + case 0x28: util::stream_format(stream, " DMAD2"); break; + case 0x2c: util::stream_format(stream, " DMAD3"); break; + case 0x30: util::stream_format(stream, " DMAD4"); break; + case 0x34: util::stream_format(stream, " DMAD5"); break; + case 0x38: util::stream_format(stream, " DMAD6"); break; + case 0x3c: util::stream_format(stream, " DMAD7"); break; + default: + util::stream_format(stream, " unknown (encoding is 0x%02x)", imm); + break; + } +} + + offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) { const tlcs900inst *dasm; @@ -1449,25 +1702,46 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case M_C0: switch( op & 0x07 ) { - case 0x00: /* 0xC0 */ + case 0x00: /* 0xc0 */ imm = opcodes.r8( pos++ ); - buf = string_format("0x%02x", imm); + if( imm < m_num_sfr ) + { + buf = string_format("%s", m_sfr_names[imm]); + } + else + { + buf = string_format("0x%02x", imm); + } break; - case 0x01: /* 0xC1 */ + case 0x01: /* 0xc1 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); - buf = string_format("0x%04x", imm); + if( imm < m_num_sfr ) + { + buf = string_format("%s", m_sfr_names[imm]); + } + else + { + buf = string_format("0x%04x", imm); + } break; - case 0x02: /* 0xC2 */ + case 0x02: /* 0xc2 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); imm = imm | (opcodes.r8( pos++ ) << 16); - buf = string_format("0x%06x", imm); + if( imm < m_num_sfr ) + { + buf = string_format("%s", m_sfr_names[imm]); + } + else + { + buf = string_format("0x%06x", imm); + } break; - case 0x03: /* 0xC3 */ + case 0x03: /* 0xc3 */ imm = opcodes.r8( pos++ ); switch( imm & 0x03 ) { @@ -1511,12 +1785,12 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const } break; - case 0x04: /* 0xC4 */ + case 0x04: /* 0xc4 */ imm = opcodes.r8( pos++ ); buf = string_format("-%s", s_allreg32[imm]); break; - case 0x05: /* 0xC5 */ + case 0x05: /* 0xc5 */ imm = opcodes.r8( pos++ ); buf = string_format("%s+", s_allreg32[imm]); break; @@ -1526,7 +1800,7 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const break; case oC8: - if ( op & 0x08 ) + if( op & 0x08 ) { buf = string_format("%s", s_reg8[ op & 0x07 ]); } @@ -1542,25 +1816,25 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case M_D0: switch( op & 0x07 ) { - case 0x00: /* 0xD0 */ + case 0x00: /* 0xd0 */ imm = opcodes.r8( pos++ ); buf = string_format("0x%02x", imm); break; - case 0x01: /* 0xD1 */ + case 0x01: /* 0xd1 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); buf = string_format("0x%04x", imm); break; - case 0x02: /* 0xD2 */ + case 0x02: /* 0xd2 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); imm = imm | (opcodes.r8( pos++ ) << 16); buf = string_format("0x%06x", imm); break; - case 0x03: /* 0xD3 */ + case 0x03: /* 0xd3 */ imm = opcodes.r8( pos++ ); switch( imm & 0x03 ) { @@ -1604,12 +1878,12 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const } break; - case 0x04: /* 0xD4 */ + case 0x04: /* 0xd4 */ imm = opcodes.r8( pos++ ); buf = string_format("-%s", s_allreg32[imm]); break; - case 0x05: /* 0xD5 */ + case 0x05: /* 0xd5 */ imm = opcodes.r8( pos++ ); buf = string_format("%s+", s_allreg32[imm]); break; @@ -1619,7 +1893,7 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const break; case oD8: - if ( op & 0x08 ) + if( op & 0x08 ) { buf = string_format("%s", s_reg16[ op & 0x07 ]); } @@ -1636,25 +1910,25 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case M_E0: switch( op & 0x07 ) { - case 0x00: /* 0xE0 */ + case 0x00: /* 0xe0 */ imm = opcodes.r8( pos++ ); buf = string_format("0x%02x", imm); break; - case 0x01: /* 0xE1 */ + case 0x01: /* 0xe1 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); buf = string_format("0x%04x", imm); break; - case 0x02: /* 0xE2 */ + case 0x02: /* 0xe2 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); imm = imm | (opcodes.r8( pos++ ) << 16); buf = string_format("0x%06x", imm); break; - case 0x03: /* 0xE3 */ + case 0x03: /* 0xe3 */ imm = opcodes.r8( pos++ ); switch( imm & 0x03 ) { @@ -1698,12 +1972,12 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const } break; - case 0x04: /* 0xE4 */ + case 0x04: /* 0xe4 */ imm = opcodes.r8( pos++ ); buf = string_format("-%s", s_allreg32[imm]); break; - case 0x05: /* 0xE5 */ + case 0x05: /* 0xe5 */ imm = opcodes.r8( pos++ ); buf = string_format("%s+", s_allreg32[imm]); break; @@ -1713,7 +1987,7 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const break; case M_E8: - if ( op & 0x08 ) + if( op & 0x08 ) { buf = string_format("%s", s_reg32[ op & 0x07 ]); } @@ -1729,25 +2003,46 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case M_F0: switch( op & 0x07 ) { - case 0x00: /* 0xF0 */ + case 0x00: /* 0xf0 */ imm = opcodes.r8( pos++ ); - buf = string_format("0x%02x", imm); + if( imm < m_num_sfr ) + { + buf = string_format("%s", m_sfr_names[imm]); + } + else + { + buf = string_format("0x%02x", imm); + } break; - case 0x01: /* 0xF1 */ + case 0x01: /* 0xf1 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); - buf = string_format("0x%04x", imm); + if( imm < m_num_sfr ) + { + buf = string_format("%s", m_sfr_names[imm]); + } + else + { + buf = string_format("0x%04x", imm); + } break; - case 0x02: /* 0xF2 */ + case 0x02: /* 0xf2 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); imm = imm | (opcodes.r8( pos++ ) << 16); - buf = string_format("0x%06x", imm); + if( imm < m_num_sfr ) + { + buf = string_format("%s", m_sfr_names[imm]); + } + else + { + buf = string_format("0x%06x", imm); + } break; - case 0x03: /* 0xF3 */ + case 0x03: /* 0xf3 */ imm = opcodes.r8( pos++ ); switch( imm & 0x03 ) { @@ -1791,12 +2086,12 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const } break; - case 0x04: /* 0xF4 */ + case 0x04: /* 0xf4 */ imm = opcodes.r8( pos++ ); buf = string_format("-%s", s_allreg32[imm]); break; - case 0x05: /* 0xF5 */ + case 0x05: /* 0xf5 */ imm = opcodes.r8( pos++ ); buf = string_format("%s+", s_allreg32[imm]); break; @@ -1854,97 +2149,36 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case O_CC: util::stream_format(stream, " %s", s_cond[op & 0x0F]); - if ((op & 0x07) != 0 && dasm->mnemonic != M_SCC) + if( (op & 0x07) != 0 && dasm->mnemonic != M_SCC ) + { flags |= STEP_COND; + } break; case O_CR8: imm = opcodes.r8( pos++ ); - switch( imm ) - { - case 0x22: - util::stream_format(stream, " DMAM0"); - break; - case 0x26: - util::stream_format(stream, " DMAM1"); - break; - case 0x2a: - util::stream_format(stream, " DMAM2"); - break; - case 0x2e: - util::stream_format(stream, " DMAM3"); - break; - default: - util::stream_format(stream, " unknown"); - break; - } + decode_control_register_8(stream, imm); break; case O_CR16: imm = opcodes.r8( pos++ ); - switch( imm ) - { - case 0x20: - util::stream_format(stream, " DMAC0"); - break; - case 0x24: - util::stream_format(stream, " DMAC1"); - break; - case 0x28: - util::stream_format(stream, " DMAC2"); - break; - case 0x2c: - util::stream_format(stream, " DMAC3"); - break; - default: - util::stream_format(stream, " unknown"); - break; - } + decode_control_register_16(stream, imm); break; case O_CR32: imm = opcodes.r8( pos++ ); - switch( imm ) - { - case 0x00: - util::stream_format(stream, " DMAS0"); - break; - case 0x04: - util::stream_format(stream, " DMAS1"); - break; - case 0x08: - util::stream_format(stream, " DMAS2"); - break; - case 0x0c: - util::stream_format(stream, " DMAS3"); - break; - case 0x10: - util::stream_format(stream, " DMAD0"); - break; - case 0x14: - util::stream_format(stream, " DMAD1"); - break; - case 0x18: - util::stream_format(stream, " DMAD2"); - break; - case 0x1c: - util::stream_format(stream, " DMAD3"); - break; - default: - util::stream_format(stream, " unknown"); - break; - } + decode_control_register_32(stream, imm); break; case O_D8: imm = opcodes.r8( pos++ ); - util::stream_format(stream, " 0x%06x", ( pos + (int8_t)imm ) & 0xFFFFFF); + util::stream_format(stream, " 0x%06x", ( pos + (int8_t)imm ) & 0xffffff); break; case O_D16: imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); - util::stream_format(stream, " 0x%06x", ( pos + (int16_t)imm ) & 0xFFFFFF); + util::stream_format(stream, " 0x%06x", ( pos + (int16_t)imm ) & 0xffffff); break; case O_F: @@ -1997,13 +2231,27 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case O_M8: imm = opcodes.r8( pos++ ); - util::stream_format(stream, " (0x%02x)", imm); + if( imm <= m_num_sfr ) + { + util::stream_format(stream, " (%s)", m_sfr_names[imm]); + } + else + { + util::stream_format(stream, " (0x%02x)", imm); + } break; case O_M16: imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); - util::stream_format(stream, " (0x%04x)", imm); + if( imm <= m_num_sfr ) + { + util::stream_format(stream, " (%s)", m_sfr_names[imm]); + } + else + { + util::stream_format(stream, " (0x%04x)", imm); + } break; case O_R: @@ -2042,97 +2290,39 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case O_CC: util::stream_format(stream, ",%s", s_cond[op & 0x0F]); - if ((op & 0x07) != 0 && dasm->mnemonic != M_SCC) + if( (op & 0x07) != 0 && dasm->mnemonic != M_SCC ) + { flags |= STEP_COND; + } break; case O_CR8: imm = opcodes.r8( pos++ ); - switch( imm ) - { - case 0x22: - util::stream_format(stream, ",DMAM0"); - break; - case 0x26: - util::stream_format(stream, ",DMAM1"); - break; - case 0x2a: - util::stream_format(stream, ",DMAM2"); - break; - case 0x2e: - util::stream_format(stream, ",DMAM3"); - break; - default: - util::stream_format(stream, ",unknown"); - break; - } + util::stream_format(stream, ","); + decode_control_register_8(stream, imm); break; case O_CR16: imm = opcodes.r8( pos++ ); - switch( imm ) - { - case 0x20: - util::stream_format(stream, ",DMAC0"); - break; - case 0x24: - util::stream_format(stream, ",DMAC1"); - break; - case 0x28: - util::stream_format(stream, ",DMAC2"); - break; - case 0x2c: - util::stream_format(stream, ",DMAC3"); - break; - default: - util::stream_format(stream, ",unknown"); - break; - } + util::stream_format(stream, ","); + decode_control_register_16(stream, imm); break; case O_CR32: imm = opcodes.r8( pos++ ); - switch( imm ) - { - case 0x00: - util::stream_format(stream, ",DMAS0"); - break; - case 0x04: - util::stream_format(stream, ",DMAS1"); - break; - case 0x08: - util::stream_format(stream, ",DMAS2"); - break; - case 0x0c: - util::stream_format(stream, ",DMAS3"); - break; - case 0x10: - util::stream_format(stream, ",DMAD0"); - break; - case 0x14: - util::stream_format(stream, ",DMAD1"); - break; - case 0x18: - util::stream_format(stream, ",DMAD2"); - break; - case 0x1c: - util::stream_format(stream, ",DMAD3"); - break; - default: - util::stream_format(stream, ",unknown"); - break; - } + util::stream_format(stream, ","); + decode_control_register_32(stream, imm); break; case O_D8: imm = opcodes.r8( pos++ ); - util::stream_format(stream, ",0x%06x", ( pos + (int8_t)imm ) & 0xFFFFFF); + util::stream_format(stream, ",0x%06x", ( pos + (int8_t)imm ) & 0xffffff); break; case O_D16: imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); - util::stream_format(stream, ",0x%06x", ( pos + (int16_t)imm ) & 0xFFFFFF); + util::stream_format(stream, ",0x%06x", ( pos + (int16_t)imm ) & 0xffffff); break; case O_F: @@ -2185,13 +2375,27 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case O_M8: imm = opcodes.r8( pos++ ); - util::stream_format(stream, ",(0x%02x)", imm); + if( imm <= m_num_sfr ) + { + util::stream_format(stream, " (%s)", m_sfr_names[imm]); + } + else + { + util::stream_format(stream, " (0x%02x)", imm); + } break; case O_M16: imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); - util::stream_format(stream, ",(0x%04x)", imm); + if( imm <= m_num_sfr ) + { + util::stream_format(stream, " (%s)", m_sfr_names[imm]); + } + else + { + util::stream_format(stream, " (0x%04x)", imm); + } break; case O_R: diff --git a/src/devices/cpu/tlcs900/dasm900.h b/src/devices/cpu/tlcs900/dasm900.h index 8fb067a299a8b..a84363fc91f3b 100644 --- a/src/devices/cpu/tlcs900/dasm900.h +++ b/src/devices/cpu/tlcs900/dasm900.h @@ -13,8 +13,13 @@ Toshiba TLCS-900/H disassembly class tlcs900_disassembler : public util::disasm_interface { +protected: + tlcs900_disassembler(uint16_t num_sfr, const char *const sfr_names[]); + virtual void decode_control_register_8(std::ostream &stream, uint8_t imm); + virtual void decode_control_register_16(std::ostream &stream, uint8_t imm); + virtual void decode_control_register_32(std::ostream &stream, uint8_t imm); + public: - tlcs900_disassembler() = default; virtual ~tlcs900_disassembler() = default; virtual u32 opcode_alignment() const override; @@ -106,6 +111,51 @@ class tlcs900_disassembler : public util::disasm_interface static const char *const s_allreg32[256]; static const char *const s_cond[16]; + const uint16_t m_num_sfr; + const char *const *m_sfr_names; +}; + + +class tmp94c241_disassembler : public tlcs900_disassembler +{ +public: + tmp94c241_disassembler(); + void decode_control_register_8(std::ostream &stream, uint8_t imm) override; + void decode_control_register_16(std::ostream &stream, uint8_t imm) override; + void decode_control_register_32(std::ostream &stream, uint8_t imm) override; + +private: + static const char *const s_sfr_names[]; +}; + + +class tmp95c061_disassembler : public tlcs900_disassembler +{ +public: + tmp95c061_disassembler(); + +private: + static const char *const s_sfr_names[]; +}; + + +class tmp95c063_disassembler : public tlcs900_disassembler +{ +public: + tmp95c063_disassembler(); + +private: + static const char *const s_sfr_names[]; +}; + + +class tmp96c141_disassembler : public tlcs900_disassembler +{ +public: + tmp96c141_disassembler(); + +private: + static const char *const s_sfr_names[]; }; #endif diff --git a/src/devices/cpu/tlcs900/tlcs900.cpp b/src/devices/cpu/tlcs900/tlcs900.cpp index 166a07db6e856..cc041cf9e303e 100644 --- a/src/devices/cpu/tlcs900/tlcs900.cpp +++ b/src/devices/cpu/tlcs900/tlcs900.cpp @@ -12,7 +12,6 @@ Toshiba TLCS-900 emulation #include "emu.h" #include "tlcs900.h" -#include "dasm900.h" tlcs900_device::tlcs900_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : @@ -64,12 +63,6 @@ device_memory_interface::space_config_vector tlcs900_device::memory_space_config } -std::unique_ptr tlcs900_device::create_disassembler() -{ - return std::make_unique(); -} - - /* Flag defines */ #define FLAG_CF 0x01 #define FLAG_NF 0x02 diff --git a/src/devices/cpu/tlcs900/tlcs900.h b/src/devices/cpu/tlcs900/tlcs900.h index a700735e4bebb..40146214655ca 100644 --- a/src/devices/cpu/tlcs900/tlcs900.h +++ b/src/devices/cpu/tlcs900/tlcs900.h @@ -20,6 +20,9 @@ enum tlcs900_inputs TLCS900_INT6, TLCS900_INT7, TLCS900_INT8, + TLCS900_INT9, + TLCS900_INTA, + TLCS900_INTB, TLCS900_TIO, TLCS900_NUM_INPUTS }; @@ -68,9 +71,6 @@ class tlcs900_device : public cpu_device virtual void state_import(const device_state_entry &entry) override; virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; - // device_disasm_interface overrides - virtual std::unique_ptr create_disassembler() override; - protected: int m_am8_16; address_space_config m_program_config; @@ -103,8 +103,8 @@ class tlcs900_device : public cpu_device /* Internal timers, irqs, etc */ uint32_t m_timer_pre; - uint8_t m_timer[6]; - int m_timer_change[4]; + uint8_t m_timer[10]; + int m_timer_change[8]; bool m_prefetch_clear; uint8_t m_prefetch_index; uint8_t m_prefetch[4]; diff --git a/src/devices/cpu/tlcs900/tmp94c241.cpp b/src/devices/cpu/tlcs900/tmp94c241.cpp new file mode 100644 index 0000000000000..61e837af6f2fa --- /dev/null +++ b/src/devices/cpu/tlcs900/tmp94c241.cpp @@ -0,0 +1,2273 @@ +// license:BSD-3-Clause +// copyright-holders:AJR,Wilbert Pol,Felipe Sanches +/**************************************************************************** + + Toshiba TMP94C241 microcontroller + +****************************************************************************/ + +#include "emu.h" +#include "tmp94c241.h" +#include "dasm900.h" +#include "debugger.h" + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(TMP94C241, tmp94c241_device, "tmp94c241", "Toshiba TMP94C241") + +#define SFR_T01MOD m_tmod[0] +#define SFR_T23MOD m_tmod[1] +#define SFR_T4MOD m_tmod[2] +#define SFR_T6MOD m_tmod[3] +#define SFR_T8MOD m_tmod[4] +#define SFR_TAMOD m_tmod[5] +#define SFR_T8RUN m_t8run +#define SFR_T16RUN m_t16run +#define SFR_T02FFCR m_ffcr[0] +#define SFR_T4FFCR m_ffcr[1] +#define SFR_T6FFCR m_ffcr[2] +#define SFR_T8FFCR m_ffcr[3] +#define SFR_TAFFCR m_ffcr[4] +#define SFR_MSAR0 m_mem_start_reg[0] +#define SFR_MSAR1 m_mem_start_reg[1] +#define SFR_MSAR2 m_mem_start_reg[2] +#define SFR_MSAR3 m_mem_start_reg[3] +#define SFR_MSAR4 m_mem_start_reg[4] +#define SFR_MSAR5 m_mem_start_reg[5] +#define SFR_MAMR0 m_mem_start_mask[0] +#define SFR_MAMR1 m_mem_start_mask[1] +#define SFR_MAMR2 m_mem_start_mask[2] +#define SFR_MAMR3 m_mem_start_mask[3] +#define SFR_MAMR4 m_mem_start_mask[4] +#define SFR_MAMR5 m_mem_start_mask[5] + +#define TIMER_0_IS_RUNNING BIT(SFR_T8RUN, 0) +#define TIMER_1_IS_RUNNING BIT(SFR_T8RUN, 1) +#define TIMER_2_IS_RUNNING BIT(SFR_T8RUN, 2) +#define TIMER_3_IS_RUNNING BIT(SFR_T8RUN, 3) +#define TIMER_4_IS_RUNNING BIT(SFR_T16RUN, 0) +#define TIMER_6_IS_RUNNING BIT(SFR_T16RUN, 1) +#define TIMER_8_IS_RUNNING BIT(SFR_T16RUN, 2) +#define TIMER_A_IS_RUNNING BIT(SFR_T16RUN, 3) +#define PRESCALER_IS_ACTIVE BIT(SFR_T16RUN, 7) + +#define T0_INPUT_CLOCK ((SFR_T01MOD >> 0) & 0x03) +#define T1_INPUT_CLOCK ((SFR_T01MOD >> 2) & 0x03) +#define PWM1_INTERVAL_SELECTION ((SFR_T01MOD >> 4) & 0x03) +#define TO1_OPERATING_MODE ((SFR_T01MOD >> 6) & 0x03) +#define T2_INPUT_CLOCK ((SFR_T23MOD >> 0) & 0x03) +#define T3_INPUT_CLOCK ((SFR_T23MOD >> 2) & 0x03) +#define PWM2_INTERVAL_SELECTION ((SFR_T23MOD >> 4) & 0x03) +#define T23_OPERATING_MODE ((SFR_T23MOD >> 6) & 0x03) +#define T4_INPUT_CLOCK ((SFR_T4MOD >> 0) & 0x03) +#define UC4_CLEAR ((SFR_T4MOD >> 2) & 0x01) +#define T4_CAPTURE_TIMING ((SFR_T4MOD >> 3) & 0x03) +#define CAP4IN ((SFR_T4MOD >> 5) & 0x01) +#define T6_INPUT_CLOCK ((SFR_T6MOD >> 0) & 0x03) +#define T8_INPUT_CLOCK ((SFR_T8MOD >> 0) & 0x03) +#define TA_INPUT_CLOCK ((SFR_TAMOD >> 0) & 0x03) +#define EQ4T4 BIT(SFR_T4FFCR, 2) +#define EQ5T4 BIT(SFR_T4FFCR, 3) +#define EQ6T6 BIT(SFR_T6FFCR, 2) +#define EQ7T6 BIT(SFR_T6FFCR, 3) +#define EQ8T8 BIT(SFR_T8FFCR, 2) +#define EQ9T8 BIT(SFR_T8FFCR, 3) +#define EQATA BIT(SFR_TAFFCR, 2) +#define EQBTA BIT(SFR_TAFFCR, 3) + +// Field values for timer mode selection on TnMOD SFRs: +#define MODE_8BIT_TIMER 0 +#define MODE_16BIT_TIMER 1 +#define MODE_PPG 2 +#define MODE_PWM 3 + +#define UPCOUNTER_0 m_timer[0] +#define UPCOUNTER_1 m_timer[1] +#define UPCOUNTER_2 m_timer[2] +#define UPCOUNTER_3 m_timer[3] +#define UPCOUNTER_4 m_timer16[0] +#define UPCOUNTER_6 m_timer16[1] +#define UPCOUNTER_8 m_timer16[2] +#define UPCOUNTER_A m_timer16[3] +#define SFR_TREG0 m_t8_reg[0] +#define SFR_TREG1 m_t8_reg[1] +#define SFR_TREG2 m_t8_reg[2] +#define SFR_TREG3 m_t8_reg[3] +#define SFR_TREG4 m_t16_reg[0] +#define SFR_TREG5 m_t16_reg[1] +#define SFR_TREG6 m_t16_reg[2] +#define SFR_TREG7 m_t16_reg[3] +#define SFR_TREG8 m_t16_reg[4] +#define SFR_TREG9 m_t16_reg[5] +#define SFR_TREGA m_t16_reg[6] +#define SFR_TREGB m_t16_reg[7] +#define TIMER_CHANGE_0 m_timer_change[0] +#define TIMER_CHANGE_1 m_timer_change[1] +#define TIMER_CHANGE_2 m_timer_change[2] +#define TIMER_CHANGE_3 m_timer_change[3] +#define TIMER_CHANGE_4 m_timer_change[4] +#define TIMER_CHANGE_6 m_timer_change[5] +#define TIMER_CHANGE_8 m_timer_change[6] +#define TIMER_CHANGE_A m_timer_change[7] + +#define TMP94C241_NUM_MASKABLE_IRQS 34 +static const struct { + uint8_t reg; + uint8_t iff; + uint8_t vector; + uint8_t dma_start_vector; +} tmp94c241_irq_vector_map[TMP94C241_NUM_MASKABLE_IRQS] = +{ + { TMP94C241_INTE0AD, 0x08, 0x28, 0x0a}, /* INT0 Pin */ + { TMP94C241_INTE45, 0x08, 0x2c, 0x0b}, /* INT4 Pin */ + { TMP94C241_INTE45, 0x80, 0x30, 0x0c}, /* INT5 Pin */ + { TMP94C241_INTE67, 0x08, 0x34, 0x0d}, /* INT6 Pin */ + { TMP94C241_INTE67, 0x80, 0x38, 0x0e}, /* INT7 Pin */ + /* 0x3c - reserved */ + { TMP94C241_INTE89, 0x08, 0x40, 0x10}, /* INT8 Pin */ + { TMP94C241_INTE89, 0x80, 0x44, 0x11}, /* INT9 Pin */ + { TMP94C241_INTEAB, 0x08, 0x48, 0x12}, /* INTA Pin */ + { TMP94C241_INTEAB, 0x80, 0x4c, 0x13}, /* INTB Pin */ + { TMP94C241_INTET01, 0x08, 0x50, 0x14}, /* INTT0: 8-bit timer (Timer 0) */ + { TMP94C241_INTET01, 0x80, 0x54, 0x15}, /* INTT1: 8-bit timer (Timer 1) */ + { TMP94C241_INTET23, 0x08, 0x58, 0x16}, /* INTT2: 8-bit timer (Timer 2) */ + { TMP94C241_INTET23, 0x80, 0x5c, 0x17}, /* INTT3: 8-bit timer (Timer 3) */ + { TMP94C241_INTET45, 0x08, 0x60, 0x18}, /* INTTR4: 16-bit timer (Treg 4) */ + { TMP94C241_INTET45, 0x80, 0x64, 0x19}, /* INTTR5: 16-bit timer (Treg 5) */ + { TMP94C241_INTET67, 0x08, 0x68, 0x1a}, /* INTTR6: 16-bit timer (Treg 6) */ + { TMP94C241_INTET67, 0x80, 0x6c, 0x1b}, /* INTTR7: 16-bit timer (Treg 7) */ + { TMP94C241_INTET89, 0x08, 0x70, 0x1c}, /* INTTR8: 16-bit timer (Treg 8) */ + { TMP94C241_INTET89, 0x80, 0x74, 0x1d}, /* INTTR9: 16-bit timer (Treg 9) */ + { TMP94C241_INTETAB, 0x08, 0x78, 0x1e}, /* INTTRA: 16-bit timer (Treg A) */ + { TMP94C241_INTETAB, 0x80, 0x7c, 0x1f}, /* INTTRB: 16-bit timer (Treg B) */ + { TMP94C241_INTES0, 0x08, 0x80, 0x20}, /* INTRX0: Serial receive 0 */ + { TMP94C241_INTES0, 0x80, 0x84, 0x21}, /* INTTX0: Serial send 0 */ + { TMP94C241_INTES1, 0x08, 0x88, 0x22}, /* INTRX1: Serial receive 1 */ + { TMP94C241_INTES1, 0x80, 0x8c, 0x23}, /* INTTX1: Serial send 1 */ + { TMP94C241_INTE0AD, 0x80, 0x90, 0x24}, /* INTAD: AD conversion completion */ + { TMP94C241_INTETC01, 0x08, 0x94, 0x25}, /* INTTC0: micro-DMA completion Ch.0 */ + { TMP94C241_INTETC01, 0x80, 0x98, 0x26}, /* INTTC1: micro-DMA completion Ch.1 */ + { TMP94C241_INTETC23, 0x08, 0x9c, 0x27}, /* INTTC2: micro-DMA completion Ch.2 */ + { TMP94C241_INTETC23, 0x80, 0xa0, 0x28}, /* INTTC3: micro-DMA completion Ch.3 */ + { TMP94C241_INTETC45, 0x08, 0xa4, 0x29}, /* INTTC4: micro-DMA completion Ch.4 */ + { TMP94C241_INTETC45, 0x80, 0xa8, 0x2a}, /* INTTC5: micro-DMA completion Ch.5 */ + { TMP94C241_INTETC67, 0x08, 0xac, 0x2b}, /* INTTC6: micro-DMA completion Ch.6 */ + { TMP94C241_INTETC67, 0x80, 0xb0, 0x2c}, /* INTTC7: micro-DMA completion Ch.7 */ + /* 0xb4 ... 0xfc (Reserved) */ +}; + + +//************************************************************************** +// DEVICE CONSTRUCTION AND INITIALIZATION +//************************************************************************** + +//------------------------------------------------- +// tmp94c241_device - constructor +//------------------------------------------------- + +tmp94c241_device::tmp94c241_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + tlcs900h_device(mconfig, TMP94C241, tag, owner, clock), + m_port0_read(*this, 0), + m_port0_write(*this), + m_port1_read(*this, 0), + m_port1_write(*this), + m_port2_read(*this, 0), + m_port2_write(*this), + m_port3_read(*this, 0), + m_port3_write(*this), + m_port4_read(*this, 0), + m_port4_write(*this), + m_port5_read(*this, 0), + m_port5_write(*this), + m_port6_read(*this, 0), + m_port6_write(*this), + m_port7_read(*this, 0), + m_port7_write(*this), + m_port8_read(*this, 0), + m_port8_write(*this), + m_porta_read(*this, 0), + m_porta_write(*this), + m_portb_read(*this, 0), + m_portb_write(*this), + m_portc_read(*this, 0), + m_portc_write(*this), + m_portd_read(*this, 0), + m_portd_write(*this), + m_porte_read(*this, 0), + m_porte_write(*this), + m_portf_read(*this, 0), + m_portf_write(*this), + m_portg_read(*this, 0), + m_porth_read(*this, 0), + m_porth_write(*this), + m_portz_read(*this, 0), + m_portz_write(*this), + m_an_read(*this, 0), + m_port_latch{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + m_port_control{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + m_port_function{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + m_t8run(0), + m_t8_reg{ 0, 0, 0, 0, 0, 0, 0, 0 }, + m_tmod{ 0, 0, 0, 0, 0, 0 }, + m_ffcr{ 0, 0, 0, 0, 0 }, + m_trdc(0), + m_t16_reg{ 0, 0, 0, 0, 0, 0, 0, 0 }, + m_t16_cap{ 0, 0, 0, 0, 0, 0, 0, 0 }, + m_t16run(0), + m_timer16{ 0, 0, 0, 0 }, + m_watchdog_mode(0), + m_serial_control{ 0, 0 }, + m_serial_mode{ 0, 0 }, + m_baud_rate{ 0, 0 }, + m_od_enable(0), + m_ad_mode1(0), + m_ad_mode2(0), + m_ad_result{ 0, 0, 0, 0 }, + m_int_reg{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + m_iimc(0), + m_dma_vector{ 0, 0, 0, 0 }, + m_block_cs{ 0, 0, 0, 0 }, + m_external_cs(0), + m_mem_start_reg{ 0, 0, 0, 0 }, + m_mem_start_mask{ 0, 0, 0, 0 }, + m_dram_refresh{ 0, 0 }, + m_dram_access{ 0, 0 }, + m_da_drive(0) +{ +} + + +//------------------------------------------------- +// device_config_complete - device-specific startup +//------------------------------------------------- + +void tmp94c241_device::device_config_complete() +{ + if (m_am8_16 == 0) + m_program_config = address_space_config("program", ENDIANNESS_LITTLE, 16, 24, 0, address_map_constructor(FUNC(tmp94c241_device::internal_mem), this)); + else + m_program_config = address_space_config("program", ENDIANNESS_LITTLE, 8, 24, 0, address_map_constructor(FUNC(tmp94c241_device::internal_mem), this)); +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void tmp94c241_device::device_start() +{ + tlcs900h_device::device_start(); + + save_item(NAME(m_port_latch)); + save_item(NAME(m_port_control)); + save_item(NAME(m_port_function)); + save_item(NAME(m_t8run)); + save_item(NAME(m_t8_reg)); + save_item(NAME(m_tmod)); + save_item(NAME(m_trdc)); + save_item(NAME(m_t16_reg)); + save_item(NAME(m_t16_cap)); + save_item(NAME(m_ffcr)); + save_item(NAME(m_t16run)); + save_item(NAME(m_watchdog_mode)); + save_item(NAME(m_serial_control)); + save_item(NAME(m_serial_mode)); + save_item(NAME(m_baud_rate)); + save_item(NAME(m_od_enable)); + save_item(NAME(m_ad_mode1)); + save_item(NAME(m_ad_mode2)); + save_item(NAME(m_ad_result)); + save_item(NAME(m_int_reg)); + save_item(NAME(m_iimc)); + save_item(NAME(m_dma_vector)); + save_item(NAME(m_block_cs)); + save_item(NAME(m_external_cs)); + save_item(NAME(m_mem_start_reg)); + save_item(NAME(m_mem_start_mask)); + save_item(NAME(m_dram_refresh)); + save_item(NAME(m_dram_access)); + save_item(NAME(m_da_drive)); + + m_nmi_state = CLEAR_LINE; + for( int i = 0; i < TLCS900_NUM_INPUTS; i++ ) + { + m_level[i] = CLEAR_LINE; + } +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void tmp94c241_device::device_reset() +{ + tlcs900h_device::device_reset(); + + m_ad_cycles_left = 0; + m_timer_pre = 0; + TIMER_CHANGE_0 = 0; + TIMER_CHANGE_1 = 0; + TIMER_CHANGE_2 = 0; + TIMER_CHANGE_3 = 0; + TIMER_CHANGE_4 = 0; + TIMER_CHANGE_6 = 0; + TIMER_CHANGE_8 = 0; + TIMER_CHANGE_A = 0; + + m_port_latch[0] = 0x00; + m_port_latch[1] = 0x00; + m_port_latch[2] = 0x00; + m_port_latch[3] = 0x00; + m_port_latch[4] = 0x00; + m_port_latch[5] = 0x00; + m_port_latch[6] = 0x00; + m_port_latch[7] = 0x7f; + m_port_latch[8] = 0x3b; + m_port_latch[0xa] = 0x1f; + m_port_latch[0xb] = 0x1f; + m_port_latch[0xc] = 0x00; + m_port_latch[0xd] = 0x00; + m_port_latch[0xe] = 0x00; + m_port_latch[0xf] = 0x00; + m_port_latch[0x11] = 0x00; // Port H + m_port_latch[0x12] = 0x00; // Port Z + + m_port_function[0] = 0x01; + m_port_function[1] = 0x01; + m_port_function[2] = 0x01; + m_port_function[3] = 0x01; + m_port_function[4] = 0xff; + m_port_function[5] = 0xff; + m_port_function[6] = 0xff; + m_port_function[7] = 0x01; + m_port_function[8] = 0x00; + m_port_function[0xa] = 0x00; + m_port_function[0xb] = 0x00; + m_port_function[0xc] = 0x00; + m_port_function[0xd] = 0x00; + m_port_function[0xe] = 0x00; + m_port_function[0xf] = 0x00; + m_port_function[0x11] = 0x00; // Port H + m_port_function[0x12] = 0x00; // Port Z + + std::fill_n(&m_port_control[0], 0x13, 0x00); + m_t8run = 0x00; + m_trdc = 0x00; + std::fill_n(&m_tmod[0], 8, 0x00); + std::fill_n(&m_ffcr[0], 6, 0x00); + std::fill_n(&m_timer[0], 4, 0x00); + std::fill_n(&m_timer16[0], 4, 0x00); + m_watchdog_mode = 0x80; + for( int i = 0; i < 2; i++ ) + { + m_serial_control[i] &= 0x80; + m_serial_mode[i] &= 0x80; + m_baud_rate[i] = 0x00; + } + m_od_enable = 0x00; + m_ad_mode1 = 0x00; + m_ad_mode2 = 0x00; + std::fill_n(&m_int_reg[0], 18, 0x00); + m_iimc = 0x00; + std::fill_n(&m_dma_vector[0], 4, 0x00); + m_block_cs[0] = 0x0000; + m_block_cs[1] = 0x0000; + m_block_cs[2] = 0x1000; //FIXME! + m_block_cs[3] = 0x0000; + m_block_cs[4] = 0x0000; + m_block_cs[5] = 0x0000; + m_external_cs = 0x0000; + std::fill_n(&m_mem_start_reg[0], 6, 0xff); + std::fill_n(&m_mem_start_mask[0], 6, 0xff); + std::fill_n(&m_dram_refresh[0], 2, 0x00); + std::fill_n(&m_dram_access[0], 2, 0x80); + m_da_drive = 0x00; +} + + +uint8_t tmp94c241_device::p0_r() +{ + return m_port0_read(0); +} + +void tmp94c241_device::p0_w(uint8_t data) +{ + m_port_latch[0] = data; + m_port0_write(0, data, 0xff); +} + +void tmp94c241_device::p0cr_w(uint8_t data) +{ + m_port_control[0] = data; +} + +void tmp94c241_device::p0fc_w(uint8_t data) +{ + m_port_function[0] = data; +} + +uint8_t tmp94c241_device::p1_r() +{ + return m_port1_read(0); +} + +void tmp94c241_device::p1_w(uint8_t data) +{ + m_port_latch[1] = data; + m_port1_write(0, data, 0xff); +} + +void tmp94c241_device::p1cr_w(uint8_t data) +{ + m_port_control[1] = data; +} + +void tmp94c241_device::p1fc_w(uint8_t data) +{ + m_port_function[1] = data; +} + +uint8_t tmp94c241_device::p2_r() +{ + return m_port2_read(0); +} + +void tmp94c241_device::p2_w(uint8_t data) +{ + m_port_latch[2] = data; + m_port2_write(0, data, 0xff); +} + +void tmp94c241_device::p2cr_w(uint8_t data) +{ + m_port_control[2] = data; +} + +void tmp94c241_device::p2fc_w(uint8_t data) +{ + m_port_function[2] = data; +} + +uint8_t tmp94c241_device::p3_r() +{ + return m_port3_read(0); +} + +void tmp94c241_device::p3_w(uint8_t data) +{ + m_port_latch[3] = data; + m_port3_write(0, data, 0xff); +} + +void tmp94c241_device::p3cr_w(uint8_t data) +{ + m_port_control[3] = data; +} + +void tmp94c241_device::p3fc_w(uint8_t data) +{ + m_port_function[3] = data; +} + +uint8_t tmp94c241_device::p4_r() +{ + return m_port4_read(0); +} + +void tmp94c241_device::p4_w(uint8_t data) +{ + m_port_latch[4] = data; + m_port4_write(0, data, 0xff); +} + +void tmp94c241_device::p4cr_w(uint8_t data) +{ + m_port_control[4] = data; +} + +void tmp94c241_device::p4fc_w(uint8_t data) +{ + m_port_function[4] = data; +} + +uint8_t tmp94c241_device::p5_r() +{ + return m_port5_read(0); +} + +void tmp94c241_device::p5_w(uint8_t data) +{ + m_port_latch[5] = data; + m_port5_write(0, data, 0xff); +} + +void tmp94c241_device::p5cr_w(uint8_t data) +{ + m_port_control[5] = data; +} + +void tmp94c241_device::p5fc_w(uint8_t data) +{ + m_port_function[5] = data; +} + +uint8_t tmp94c241_device::p6_r() +{ + return m_port6_read(0); +} + +void tmp94c241_device::p6_w(uint8_t data) +{ + m_port_latch[6] = data; + m_port6_write(0, data, 0xff); +} + +void tmp94c241_device::p6cr_w(uint8_t data) +{ + m_port_control[6] = data; +} + +void tmp94c241_device::p6fc_w(uint8_t data) +{ + m_port_function[6] = data; +} + +uint8_t tmp94c241_device::p7_r() +{ + return m_port7_read(0); +} + +void tmp94c241_device::p7_w(uint8_t data) +{ + m_port_latch[7] = data; + m_port7_write(0, data, 0xff); +} + +void tmp94c241_device::p7cr_w(uint8_t data) +{ + m_port_control[7] = data; +} + +void tmp94c241_device::p7fc_w(uint8_t data) +{ + m_port_function[7] = data; +} + +uint8_t tmp94c241_device::p8_r() +{ + return m_port8_read(0); +} + +void tmp94c241_device::p8_w(uint8_t data) +{ + m_port_latch[8] = data; + m_port8_write(0, data, 0xff); +} + +void tmp94c241_device::p8cr_w(uint8_t data) +{ + m_port_control[8] = data; +} + +void tmp94c241_device::p8fc_w(uint8_t data) +{ + m_port_function[8] = data; +} + +uint8_t tmp94c241_device::pa_r() +{ + return m_porta_read(0); +} + +void tmp94c241_device::pa_w(uint8_t data) +{ + m_port_latch[0xa] = data; + m_porta_write(0, data, 0xff); +} + +void tmp94c241_device::pafc_w(uint8_t data) +{ + m_port_function[0xa] = data; +} + +uint8_t tmp94c241_device::pb_r() +{ + return m_portb_read(0); +} + +void tmp94c241_device::pb_w(uint8_t data) +{ + m_port_latch[0xb] = data; + m_portb_write(0, data, 0xff); +} + +void tmp94c241_device::pbfc_w(uint8_t data) +{ + m_port_function[0xb] = data; +} + +uint8_t tmp94c241_device::pc_r() +{ + return m_portc_read(0); +} + +void tmp94c241_device::pc_w(uint8_t data) +{ + m_port_latch[0xc] = data; + m_portc_write(0, data, 0xff); +} + +void tmp94c241_device::pccr_w(uint8_t data) +{ + m_port_control[0xc] = data; +} + +void tmp94c241_device::pcfc_w(uint8_t data) +{ + m_port_function[0xc] = data; +} + +uint8_t tmp94c241_device::pd_r() +{ + return m_portd_read(0); +} + +void tmp94c241_device::pd_w(uint8_t data) +{ + m_port_latch[0xd] = data; + m_portd_write(0, data, 0xff); +} + +void tmp94c241_device::pdcr_w(uint8_t data) +{ + m_port_control[0xd] = data; +} + +void tmp94c241_device::pdfc_w(uint8_t data) +{ + m_port_function[0xd] = data; +} + +uint8_t tmp94c241_device::pe_r() +{ + return m_porte_read(0); +} + +void tmp94c241_device::pe_w(uint8_t data) +{ + m_port_latch[0xe] = data; + m_porte_write(0, data, 0xff); +} + +void tmp94c241_device::pecr_w(uint8_t data) +{ + m_port_control[0xe] = data; +} + +void tmp94c241_device::pefc_w(uint8_t data) +{ + m_port_function[0xe] = data; +} + +uint8_t tmp94c241_device::pf_r() +{ + return m_portf_read(0); +} + +void tmp94c241_device::pf_w(uint8_t data) +{ + m_port_latch[0xf] = data; + m_portf_write(0, data, 0xff); +} + +void tmp94c241_device::pfcr_w(uint8_t data) +{ + m_port_control[0xf] = data; +} + +void tmp94c241_device::pffc_w(uint8_t data) +{ + m_port_function[0xf] = data; +} + +uint8_t tmp94c241_device::pg_r() +{ + return m_portg_read(0); +} + +uint8_t tmp94c241_device::ph_r() +{ + return m_porth_read(0); +} + +void tmp94c241_device::ph_w(uint8_t data) +{ + m_port_latch[0x11] = data; + m_porth_write(0, data, 0xff); +} + +void tmp94c241_device::phcr_w(uint8_t data) +{ + m_port_control[0x11] = data; +} + +void tmp94c241_device::phfc_w(uint8_t data) +{ + m_port_function[0x11] = data; +} + +uint8_t tmp94c241_device::pz_r() +{ + return m_portz_read(0); +} + +void tmp94c241_device::pz_w(uint8_t data) +{ + m_port_latch[0x12] = data; + m_portz_write(0, data, 0xff); +} + +void tmp94c241_device::pzcr_w(uint8_t data) +{ + m_port_control[0x12] = data; +} + +uint8_t tmp94c241_device::inte_r(offs_t offset) +{ + return m_int_reg[offset]; +} + +void tmp94c241_device::inte_w(offs_t offset, uint8_t data) +{ + if ( data & 0x80 ) + data = ( data & 0x7f ) | ( m_int_reg[offset] & 0x80 ); + if ( data & 0x08 ) + data = ( data & 0xf7 ) | ( m_int_reg[offset] & 0x08 ); + + m_int_reg[offset] = data; + m_check_irqs = 1; +} + +uint8_t tmp94c241_device::intnmwdt_r(offs_t offset) +{ + return m_int_reg[TMP94C241_INTNMWDT]; +} + +void tmp94c241_device::intnmwdt_w(offs_t offset, uint8_t data) +{ + if ( data & 0x80 ) + data = ( data & 0x7f ) | ( m_int_reg[TMP94C241_INTNMWDT] & 0x80 ); + if ( data & 0x08 ) + data = ( data & 0xf7 ) | ( m_int_reg[TMP94C241_INTNMWDT] & 0x08 ); + + m_int_reg[TMP94C241_INTNMWDT] = data; + m_check_irqs = 1; +} + +void tmp94c241_device::iimc_w(uint8_t data) +{ + m_iimc = data; + m_check_irqs = 1; +} + +void tmp94c241_device::intclr_w(uint8_t data) +{ + for( int i = 0; i < TMP94C241_NUM_MASKABLE_IRQS; i++ ) + { + if ( data == tmp94c241_irq_vector_map[i].dma_start_vector ) + { + // clear interrupt request + m_int_reg[tmp94c241_irq_vector_map[i].reg] &= ~ tmp94c241_irq_vector_map[i].iff; + return; + } + } +} + +void tmp94c241_device::dmav_w(offs_t offset, uint8_t data) +{ + m_dma_vector[offset] = data; +} + +void tmp94c241_device::b0cs_w(offs_t offset, uint8_t data) +{ + if (BIT(offset, 0)) + m_block_cs[0] = (m_block_cs[0] & 0xff) | (data << 8); + else + m_block_cs[0] = (m_block_cs[0] & 0xff00) | data; +} + +void tmp94c241_device::b1cs_w(offs_t offset, uint8_t data) +{ + if (BIT(offset, 0)) + m_block_cs[1] = (m_block_cs[1] & 0xff) | (data << 8); + else + m_block_cs[1] = (m_block_cs[1] & 0xff00) | data; +} + +void tmp94c241_device::b2cs_w(offs_t offset, uint8_t data) +{ + if (BIT(offset, 0)) + m_block_cs[2] = (m_block_cs[2] & 0xff) | (data << 8); + else + m_block_cs[2] = (m_block_cs[2] & 0xff00) | data; +} + +void tmp94c241_device::b3cs_w(offs_t offset, uint8_t data) +{ + if (BIT(offset, 0)) + m_block_cs[3] = (m_block_cs[3] & 0xff) | (data << 8); + else + m_block_cs[3] = (m_block_cs[3] & 0xff00) | data; +} + +void tmp94c241_device::b4cs_w(offs_t offset, uint8_t data) +{ + if (BIT(offset, 0)) + m_block_cs[4] = (m_block_cs[4] & 0xff) | (data << 8); + else + m_block_cs[4] = (m_block_cs[4] & 0xff00) | data; +} + +void tmp94c241_device::b5cs_w(offs_t offset, uint8_t data) +{ + if (BIT(offset, 0)) + m_block_cs[5] = (m_block_cs[5] & 0xff) | (data << 8); + else + m_block_cs[5] = (m_block_cs[5] & 0xff00) | data; +} + +void tmp94c241_device::mamr0_w(offs_t offset, uint8_t data) +{ + SFR_MAMR0 = data; +} + +void tmp94c241_device::msar0_w(offs_t offset, uint8_t data) +{ + SFR_MSAR0 = data; +} + +uint8_t tmp94c241_device::mamr0_r() +{ + return SFR_MAMR0; +} + +uint8_t tmp94c241_device::msar0_r() +{ + return SFR_MSAR0; +} + +void tmp94c241_device::mamr1_w(offs_t offset, uint8_t data) +{ + SFR_MAMR1 = data; +} + +void tmp94c241_device::msar1_w(offs_t offset, uint8_t data) +{ + SFR_MSAR1 = data; +} + +uint8_t tmp94c241_device::mamr1_r() +{ + return SFR_MAMR1; +} + +uint8_t tmp94c241_device::msar1_r() +{ + return SFR_MSAR1; +} + +void tmp94c241_device::mamr2_w(offs_t offset, uint8_t data) +{ + SFR_MAMR2 = data; +} + +void tmp94c241_device::msar2_w(offs_t offset, uint8_t data) +{ + SFR_MSAR2 = data; +} + +uint8_t tmp94c241_device::mamr2_r() +{ + return SFR_MAMR2; +} + +uint8_t tmp94c241_device::msar2_r() +{ + return SFR_MSAR2; +} + +void tmp94c241_device::mamr3_w(offs_t offset, uint8_t data) +{ + SFR_MAMR3 = data; +} + +void tmp94c241_device::msar3_w(offs_t offset, uint8_t data) +{ + SFR_MSAR3 = data; +} + +uint8_t tmp94c241_device::mamr3_r() +{ + return SFR_MAMR3; +} + +uint8_t tmp94c241_device::msar3_r() +{ + return SFR_MSAR3; +} + +void tmp94c241_device::mamr4_w(offs_t offset, uint8_t data) +{ + SFR_MAMR4 = data; +} + +void tmp94c241_device::msar4_w(offs_t offset, uint8_t data) +{ + SFR_MSAR4 = data; +} + +uint8_t tmp94c241_device::mamr4_r() +{ + return SFR_MAMR4; +} + +uint8_t tmp94c241_device::msar4_r() +{ + return SFR_MSAR4; +} + +void tmp94c241_device::mamr5_w(offs_t offset, uint8_t data) +{ + SFR_MAMR5 = data; +} + +void tmp94c241_device::msar5_w(offs_t offset, uint8_t data) +{ + SFR_MSAR5 = data; +} + +uint8_t tmp94c241_device::mamr5_r() +{ + return SFR_MAMR5; +} + +uint8_t tmp94c241_device::msar5_r() +{ + return SFR_MSAR5; +} + +uint8_t tmp94c241_device::t8run_r() +{ + return SFR_T8RUN; +} + +void tmp94c241_device::t8run_w(uint8_t data) +{ + SFR_T8RUN = data; + + if ( !TIMER_0_IS_RUNNING ) + { + UPCOUNTER_0 = 0; + TIMER_CHANGE_0 = 0; + } + if ( !TIMER_1_IS_RUNNING ) + { + UPCOUNTER_1 = 0; + TIMER_CHANGE_1 = 0; + } + if ( !TIMER_2_IS_RUNNING ) + { + UPCOUNTER_2 = 0; + TIMER_CHANGE_2 = 0; + } + if ( !TIMER_3_IS_RUNNING ) + { + UPCOUNTER_3 = 0; + TIMER_CHANGE_3 = 0; + } +} + +void tmp94c241_device::treg01_w(offs_t offset, uint8_t data) +{ + + if (BIT(0, offset)) + SFR_TREG1 = data; + else + SFR_TREG0 = data; +} + +uint8_t tmp94c241_device::t01mod_r() +{ + return SFR_T01MOD; +} + +void tmp94c241_device::t01mod_w(uint8_t data) +{ + logerror("T01MOD = %02X\n", data); + SFR_T01MOD = data; +} + +uint8_t tmp94c241_device::t02ffcr_r() +{ + return SFR_T02FFCR; +} + +void tmp94c241_device::change_timer_flipflop(uint8_t flipflop, uint8_t operation) +{ + switch(operation) + { + case FLIPFLOP_INVERT: + switch( flipflop ) + { + case 0x1: if ((m_port_function[0xc] & 0x03) == 0x02) pc_w(m_port_latch[0xc] ^ 0x01); break; + case 0x3: if ((m_port_function[0xc] & 0x03) == 0x02) pc_w(m_port_latch[0xc] ^ 0x02); break; + case 0x4: if ((m_port_function[0xd] & 0x01) == 0x01) pd_w(m_port_latch[0xd] ^ 0x01); break; + case 0x6: if ((m_port_function[0xd] & 0x10) == 0x10) pd_w(m_port_latch[0xd] ^ 0x10); break; + case 0x7: if ((m_port_function[0xc] & 0x03) == 0x03) pc_w(m_port_latch[0xc] ^ 0x01); break; + case 0x8: if ((m_port_function[0xe] & 0x01) == 0x01) pe_w(m_port_latch[0xe] ^ 0x01); break; + case 0xa: if ((m_port_function[0xe] & 0x10) == 0x10) pe_w(m_port_latch[0xe] ^ 0x10); break; + case 0xb: if ((m_port_function[0xc] & 0x03) == 0x03) pc_w(m_port_latch[0xc] ^ 0x02); break; + } + break; + case FLIPFLOP_SET: + switch( flipflop ) + { + case 0x1: if ((m_port_function[0xc] & 0x03) == 0x02) pc_w(m_port_latch[0xc] & 0x01); break; + case 0x3: if ((m_port_function[0xc] & 0x03) == 0x02) pc_w(m_port_latch[0xc] & 0x02); break; + case 0x4: if ((m_port_function[0xd] & 0x01) == 0x01) pd_w(m_port_latch[0xd] & 0x01); break; + case 0x6: if ((m_port_function[0xd] & 0x10) == 0x10) pd_w(m_port_latch[0xd] & 0x10); break; + case 0x7: if ((m_port_function[0xc] & 0x03) == 0x03) pc_w(m_port_latch[0xc] & 0x01); break; + case 0x8: if ((m_port_function[0xe] & 0x01) == 0x01) pe_w(m_port_latch[0xe] & 0x01); break; + case 0xa: if ((m_port_function[0xe] & 0x10) == 0x10) pe_w(m_port_latch[0xe] & 0x10); break; + case 0xb: if ((m_port_function[0xc] & 0x03) == 0x03) pc_w(m_port_latch[0xc] & 0x02); break; + } + break; + case FLIPFLOP_CLEAR: + switch( flipflop ) + { + case 0x1: if ((m_port_function[0xc] & 0x03) == 0x02) pc_w(m_port_latch[0xc] | ~0x01); break; + case 0x3: if ((m_port_function[0xc] & 0x03) == 0x02) pc_w(m_port_latch[0xc] | ~0x02); break; + case 0x4: if ((m_port_function[0xd] & 0x01) == 0x01) pd_w(m_port_latch[0xd] | ~0x01); break; + case 0x6: if ((m_port_function[0xd] & 0x10) == 0x10) pd_w(m_port_latch[0xd] | ~0x10); break; + case 0x7: if ((m_port_function[0xc] & 0x03) == 0x03) pc_w(m_port_latch[0xc] | ~0x01); break; + case 0x8: if ((m_port_function[0xe] & 0x01) == 0x01) pe_w(m_port_latch[0xe] | ~0x01); break; + case 0xa: if ((m_port_function[0xe] & 0x10) == 0x10) pe_w(m_port_latch[0xe] | ~0x10); break; + case 0xb: if ((m_port_function[0xc] & 0x03) == 0x03) pc_w(m_port_latch[0xc] | ~0x02); break; + } + break; + } +} + +void tmp94c241_device::t02ffcr_w(uint8_t data) +{ + switch( data & 0x0c ) + { + case 0x00: + change_timer_flipflop( 1, FLIPFLOP_INVERT ); + break; + case 0x04: + change_timer_flipflop( 1, FLIPFLOP_SET ); + break; + case 0x08: + change_timer_flipflop( 1, FLIPFLOP_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + change_timer_flipflop( 3, FLIPFLOP_INVERT ); + break; + case 0x40: + change_timer_flipflop( 3, FLIPFLOP_SET ); + break; + case 0x80: + change_timer_flipflop( 3, FLIPFLOP_CLEAR ); + break; + } + + SFR_T02FFCR = data | 0xcc; +} + +void tmp94c241_device::treg23_w(offs_t offset, uint8_t data) +{ + + if (BIT(0, offset)) + SFR_TREG3 = data; + else + SFR_TREG2 = data; +} + +uint8_t tmp94c241_device::t23mod_r() +{ + return SFR_T23MOD; +} + +void tmp94c241_device::t23mod_w(uint8_t data) +{ + logerror("T23MOD = %02X\n", data); + + SFR_T23MOD = data; +} + +uint8_t tmp94c241_device::trdc_r() +{ + return m_trdc; +} + +void tmp94c241_device::trdc_w(uint8_t data) +{ + m_trdc = data; +} + +void tmp94c241_device::treg45_w(offs_t offset, uint16_t data) +{ + if (offset < 2) + SFR_TREG4 = data; + else + SFR_TREG5 = data; +} + +void tmp94c241_device::treg67_w(offs_t offset, uint16_t data) +{ + if (offset < 2) + SFR_TREG6 = data; + else + SFR_TREG7 = data; +} + +void tmp94c241_device::treg89_w(offs_t offset, uint16_t data) +{ + if (offset < 2) + SFR_TREG8 = data; + else + SFR_TREG9 = data; +} + +void tmp94c241_device::tregab_w(offs_t offset, uint16_t data) +{ + if (offset < 2) + SFR_TREGA = data; + else + SFR_TREGB = data; +} + +uint8_t tmp94c241_device::t4mod_r() +{ + return SFR_T4MOD; +} + +void tmp94c241_device::t4mod_w(uint8_t data) +{ + logerror("T4MOD = %02X\n", data); + SFR_T4MOD = data; +} + +uint8_t tmp94c241_device::t6mod_r() +{ + return SFR_T6MOD; +} + +void tmp94c241_device::t6mod_w(uint8_t data) +{ + logerror("T6MOD = %02X\n", data); + SFR_T6MOD = data; +} + +uint8_t tmp94c241_device::t8mod_r() +{ + return SFR_T8MOD; +} + +void tmp94c241_device::t8mod_w(uint8_t data) +{ + logerror("T8MOD = %02X\n", data); + SFR_T8MOD = data; +} + +uint8_t tmp94c241_device::tamod_r() +{ + return SFR_TAMOD; +} + +void tmp94c241_device::tamod_w(uint8_t data) +{ + logerror("TAMOD = %02X\n", data); + SFR_TAMOD = data; +} + + +uint8_t tmp94c241_device::t4ffcr_r() +{ + return SFR_T4FFCR; +} + +void tmp94c241_device::t4ffcr_w(uint8_t data) +{ + switch( data & 0x03 ) + { + case 0x00: + change_timer_flipflop( 4, FLIPFLOP_INVERT ); + break; + case 0x01: + change_timer_flipflop( 4, FLIPFLOP_SET ); + break; + case 0x02: + change_timer_flipflop( 4, FLIPFLOP_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + change_timer_flipflop( 5, FLIPFLOP_INVERT ); + break; + case 0x40: + change_timer_flipflop( 5, FLIPFLOP_SET ); + break; + case 0x80: + change_timer_flipflop( 5, FLIPFLOP_CLEAR ); + break; + } + + SFR_T4FFCR = data | 0xc3; +} + +uint8_t tmp94c241_device::t8ffcr_r() +{ + return SFR_T8FFCR; +} + +void tmp94c241_device::t8ffcr_w(uint8_t data) +{ + switch( data & 0x03 ) + { + case 0x00: + change_timer_flipflop( 8, FLIPFLOP_INVERT ); + break; + case 0x01: + change_timer_flipflop( 8, FLIPFLOP_SET ); + break; + case 0x02: + change_timer_flipflop( 8, FLIPFLOP_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + change_timer_flipflop( 9, FLIPFLOP_INVERT ); + break; + case 0x40: + change_timer_flipflop( 9, FLIPFLOP_SET ); + break; + case 0x80: + change_timer_flipflop( 9, FLIPFLOP_CLEAR ); + break; + } + + SFR_T8FFCR = data | 0xc3; +} + + +uint8_t tmp94c241_device::t6ffcr_r() +{ + return SFR_T6FFCR; +} + +void tmp94c241_device::t6ffcr_w(uint8_t data) +{ + switch( data & 0x03 ) + { + case 0x00: + change_timer_flipflop( 6, FLIPFLOP_INVERT ); + break; + case 0x01: + change_timer_flipflop( 6, FLIPFLOP_SET ); + break; + case 0x02: + change_timer_flipflop( 6, FLIPFLOP_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + change_timer_flipflop( 7, FLIPFLOP_INVERT ); + break; + case 0x40: + change_timer_flipflop( 7, FLIPFLOP_SET ); + break; + case 0x80: + change_timer_flipflop( 7, FLIPFLOP_CLEAR ); + break; + } + + SFR_T6FFCR = data | 0xc3; +} + +uint8_t tmp94c241_device::taffcr_r() +{ + return SFR_TAFFCR; +} + +void tmp94c241_device::taffcr_w(uint8_t data) +{ + switch( data & 0x03 ) + { + case 0x00: + change_timer_flipflop( 0xa, FLIPFLOP_INVERT ); + break; + case 0x01: + change_timer_flipflop( 0xa, FLIPFLOP_SET ); + break; + case 0x02: + change_timer_flipflop( 0xa, FLIPFLOP_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + change_timer_flipflop( 0xb, FLIPFLOP_INVERT ); + break; + case 0x40: + change_timer_flipflop( 0xb, FLIPFLOP_SET ); + break; + case 0x80: + change_timer_flipflop( 0xb, FLIPFLOP_CLEAR ); + break; + } + + SFR_TAFFCR = data | 0xc3; +} + +uint8_t tmp94c241_device::t16run_r() +{ + return SFR_T16RUN; +} + +void tmp94c241_device::t16run_w(uint8_t data) +{ + SFR_T16RUN = data; + + if ( !TIMER_4_IS_RUNNING ) + { + UPCOUNTER_4 = 0; + TIMER_CHANGE_4 = 0; + } + if ( !TIMER_6_IS_RUNNING ) + { + UPCOUNTER_6 = 0; + TIMER_CHANGE_6 = 0; + } + if ( !TIMER_8_IS_RUNNING ) + { + UPCOUNTER_8 = 0; + TIMER_CHANGE_8 = 0; + } + if ( !TIMER_A_IS_RUNNING ) + { + UPCOUNTER_A = 0; + TIMER_CHANGE_A = 0; + } +} + + +uint8_t tmp94c241_device::cap45_r(offs_t offset) +{ + if (BIT(offset, 0)) + return m_t16_cap[(offset >> 1) + 0] >> 8; + else + return m_t16_cap[(offset >> 1) + 0] & 0x00ff; +} + +uint8_t tmp94c241_device::cap67_r(offs_t offset) +{ + if (BIT(offset, 0)) + return m_t16_cap[(offset >> 1) + 2] >> 8; + else + return m_t16_cap[(offset >> 1) + 2] & 0x00ff; +} + +uint8_t tmp94c241_device::cap89_r(offs_t offset) +{ + if (BIT(offset, 0)) + return m_t16_cap[(offset >> 1) + 4] >> 8; + else + return m_t16_cap[(offset >> 1) + 4] & 0x00ff; +} + +uint8_t tmp94c241_device::capab_r(offs_t offset) +{ + if (BIT(offset, 0)) + return m_t16_cap[(offset >> 1) + 6] >> 8; + else + return m_t16_cap[(offset >> 1) + 6] & 0x00ff; +} + +uint8_t tmp94c241_device::wdmod_r() +{ + return m_watchdog_mode; +} + +void tmp94c241_device::wdmod_w(uint8_t data) +{ + m_watchdog_mode = data; +} + +void tmp94c241_device::wdcr_w(uint8_t data) +{ +} + + +uint8_t tmp94c241_device::sc0buf_r() +{ + return 0; +} + +void tmp94c241_device::sc0buf_w(uint8_t data) +{ + // Fake finish sending data + m_int_reg[TMP94C241_INTES0] |= 0x80; + m_check_irqs = 1; +} + +uint8_t tmp94c241_device::sc0cr_r() +{ + uint8_t reg = m_serial_control[0]; + if (!machine().side_effects_disabled()) + m_serial_control[0] &= 0xe3; + return reg; +} + +void tmp94c241_device::sc0cr_w(uint8_t data) +{ + m_serial_control[0] = data; +} + +uint8_t tmp94c241_device::sc0mod_r() +{ + return m_serial_mode[0]; +} + +void tmp94c241_device::sc0mod_w(uint8_t data) +{ + m_serial_mode[0] = data; +} + +uint8_t tmp94c241_device::br0cr_r() +{ + return m_baud_rate[0]; +} + +void tmp94c241_device::br0cr_w(uint8_t data) +{ + m_baud_rate[0] = data; +} + +uint8_t tmp94c241_device::sc1buf_r() +{ + //machine().debugger().debug_break(); + return 0; +} + +void tmp94c241_device::sc1buf_w(uint8_t data) +{ + //machine().debugger().debug_break(); + // Fake finish sending data +// m_int_reg[TMP94C241_INTES1] |= 0x80; +// m_check_irqs = 1; +} + +uint8_t tmp94c241_device::sc1cr_r() +{ + //machine().debugger().debug_break(); + uint8_t reg = m_serial_control[1]; + if (!machine().side_effects_disabled()) + m_serial_control[1] &= 0xe3; + return reg; +} + +void tmp94c241_device::sc1cr_w(uint8_t data) +{ + //machine().debugger().debug_break(); + m_serial_control[1] = data; +} + +uint8_t tmp94c241_device::sc1mod_r() +{ + //machine().debugger().debug_break(); + return m_serial_mode[1]; +} + +void tmp94c241_device::sc1mod_w(uint8_t data) +{ + //machine().debugger().debug_break(); + m_serial_mode[1] = data; +} + +uint8_t tmp94c241_device::br1cr_r() +{ + //machine().debugger().debug_break(); + return m_baud_rate[1]; +} + +void tmp94c241_device::br1cr_w(uint8_t data) +{ + //machine().debugger().debug_break(); + m_baud_rate[1] = data; +} + +uint8_t tmp94c241_device::ode_r() +{ + return m_od_enable; +} + +void tmp94c241_device::ode_w(uint8_t data) +{ + m_od_enable = data; +} + +uint8_t tmp94c241_device::admod1_r() +{ + return m_ad_mode1; +} + +void tmp94c241_device::admod1_w(uint8_t data) +{ + // Preserve read-only bits + data = ( m_ad_mode1 & 0xc0 ) | ( data & 0x34 ); + + // Check for A/D conversion start + if (data & 0x04) + { + data &= ~0x04; + data |= 0x40; + + switch ((m_ad_mode2 >> 4) & 3) + { + case 0: m_ad_cycles_left = 160; break; + case 1: m_ad_cycles_left = 320; break; + case 2: m_ad_cycles_left = 640; break; + case 3: m_ad_cycles_left = 1280; break; + } + } + + m_ad_mode1 = data; +} + +uint8_t tmp94c241_device::admod2_r() +{ + return m_ad_mode2; +} + +void tmp94c241_device::admod2_w(uint8_t data) +{ + m_ad_mode2 = data; +} + +uint8_t tmp94c241_device::adreg_r(offs_t offset) +{ + if (BIT(offset, 0)) + return m_ad_result[offset >> 1] >> 2; + else + return m_ad_result[offset >> 1] << 6 | 0x3f; +} + +uint8_t tmp94c241_device::dadrv_r() +{ + return m_da_drive; +} + +void tmp94c241_device::dadrv_w(uint8_t data) +{ + m_da_drive = data; +} + +void tmp94c241_device::dareg_w(offs_t offset, uint8_t data) +{ +} + + +//************************************************************************** +// INTERNAL REGISTERS +//************************************************************************** + +//------------------------------------------------- +// internal_mem - memory map for internal RAM and +// I/O registers +//------------------------------------------------- + +void tmp94c241_device::internal_mem(address_map &map) +{ + map(0x000000, 0x000000).rw(FUNC(tmp94c241_device::p0_r), FUNC(tmp94c241_device::p0_w)); + map(0x000002, 0x000002).w(FUNC(tmp94c241_device::p0cr_w)); + map(0x000003, 0x000003).w(FUNC(tmp94c241_device::p0fc_w)); + map(0x000004, 0x000004).rw(FUNC(tmp94c241_device::p1_r), FUNC(tmp94c241_device::p1_w)); + map(0x000006, 0x000006).w(FUNC(tmp94c241_device::p1cr_w)); + map(0x000007, 0x000007).w(FUNC(tmp94c241_device::p1fc_w)); + map(0x000008, 0x000008).rw(FUNC(tmp94c241_device::p2_r), FUNC(tmp94c241_device::p2_w)); + map(0x00000a, 0x00000a).w(FUNC(tmp94c241_device::p2cr_w)); + map(0x00000b, 0x00000b).w(FUNC(tmp94c241_device::p2fc_w)); + map(0x00000c, 0x00000c).rw(FUNC(tmp94c241_device::p3_r), FUNC(tmp94c241_device::p3_w)); + map(0x00000e, 0x00000e).w(FUNC(tmp94c241_device::p3cr_w)); + map(0x00000f, 0x00000f).w(FUNC(tmp94c241_device::p3fc_w)); + map(0x000010, 0x000010).rw(FUNC(tmp94c241_device::p4_r), FUNC(tmp94c241_device::p4_w)); + map(0x000012, 0x000012).w(FUNC(tmp94c241_device::p4cr_w)); + map(0x000013, 0x000013).w(FUNC(tmp94c241_device::p4fc_w)); + map(0x000014, 0x000014).rw(FUNC(tmp94c241_device::p5_r), FUNC(tmp94c241_device::p5_w)); + map(0x000016, 0x000016).w(FUNC(tmp94c241_device::p5cr_w)); + map(0x000017, 0x000017).w(FUNC(tmp94c241_device::p5fc_w)); + map(0x000018, 0x000018).rw(FUNC(tmp94c241_device::p6_r), FUNC(tmp94c241_device::p6_w)); + map(0x00001a, 0x00001a).w(FUNC(tmp94c241_device::p6cr_w)); + map(0x00001b, 0x00001b).w(FUNC(tmp94c241_device::p6fc_w)); + map(0x00001c, 0x00001c).rw(FUNC(tmp94c241_device::p7_r), FUNC(tmp94c241_device::p7_w)); + map(0x00001e, 0x00001e).w(FUNC(tmp94c241_device::p7cr_w)); + map(0x00001f, 0x00001f).w(FUNC(tmp94c241_device::p7fc_w)); + map(0x000020, 0x000020).rw(FUNC(tmp94c241_device::p8_r), FUNC(tmp94c241_device::p8_w)); + map(0x000022, 0x000022).w(FUNC(tmp94c241_device::p8cr_w)); + map(0x000023, 0x000023).w(FUNC(tmp94c241_device::p8fc_w)); + map(0x000028, 0x000028).rw(FUNC(tmp94c241_device::pa_r), FUNC(tmp94c241_device::pa_w)); + map(0x00002b, 0x00002b).w(FUNC(tmp94c241_device::pafc_w)); + map(0x00002c, 0x00002c).rw(FUNC(tmp94c241_device::pb_r), FUNC(tmp94c241_device::pb_w)); + map(0x00002f, 0x00002f).w(FUNC(tmp94c241_device::pbfc_w)); + map(0x000030, 0x000030).rw(FUNC(tmp94c241_device::pc_r), FUNC(tmp94c241_device::pc_w)); + map(0x000032, 0x000032).w(FUNC(tmp94c241_device::pccr_w)); + map(0x000033, 0x000033).w(FUNC(tmp94c241_device::pcfc_w)); + map(0x000034, 0x000034).rw(FUNC(tmp94c241_device::pd_r), FUNC(tmp94c241_device::pd_w)); + map(0x000036, 0x000036).w(FUNC(tmp94c241_device::pdcr_w)); + map(0x000037, 0x000037).w(FUNC(tmp94c241_device::pdfc_w)); + map(0x000038, 0x000038).rw(FUNC(tmp94c241_device::pe_r), FUNC(tmp94c241_device::pe_w)); + map(0x00003a, 0x00003a).w(FUNC(tmp94c241_device::pecr_w)); + map(0x00003b, 0x00003b).w(FUNC(tmp94c241_device::pefc_w)); + map(0x00003c, 0x00003c).rw(FUNC(tmp94c241_device::pf_r), FUNC(tmp94c241_device::pf_w)); + map(0x00003e, 0x00003e).w(FUNC(tmp94c241_device::pfcr_w)); + map(0x00003f, 0x00003f).w(FUNC(tmp94c241_device::pffc_w)); + map(0x000040, 0x000040).r(FUNC(tmp94c241_device::pg_r)); + map(0x000044, 0x000044).rw(FUNC(tmp94c241_device::ph_r), FUNC(tmp94c241_device::ph_w)); + map(0x000046, 0x000046).w(FUNC(tmp94c241_device::phcr_w)); + map(0x000047, 0x000047).w(FUNC(tmp94c241_device::phfc_w)); + map(0x000068, 0x000068).rw(FUNC(tmp94c241_device::pz_r), FUNC(tmp94c241_device::pz_w)); + map(0x00006a, 0x00006a).w(FUNC(tmp94c241_device::pzcr_w)); + map(0x000080, 0x000080).rw(FUNC(tmp94c241_device::t8run_r), FUNC(tmp94c241_device::t8run_w)); + map(0x000081, 0x000081).rw(FUNC(tmp94c241_device::trdc_r), FUNC(tmp94c241_device::trdc_w)); + map(0x000082, 0x000082).rw(FUNC(tmp94c241_device::t02ffcr_r), FUNC(tmp94c241_device::t02ffcr_w)); + map(0x000084, 0x000084).rw(FUNC(tmp94c241_device::t01mod_r), FUNC(tmp94c241_device::t01mod_w)); + map(0x000085, 0x000085).rw(FUNC(tmp94c241_device::t23mod_r), FUNC(tmp94c241_device::t23mod_w)); + map(0x000088, 0x000089).w(FUNC(tmp94c241_device::treg01_w)); + map(0x00008a, 0x00008b).w(FUNC(tmp94c241_device::treg23_w)); + map(0x000090, 0x000093).w(FUNC(tmp94c241_device::treg45_w)); + map(0x000094, 0x000097).r(FUNC(tmp94c241_device::cap45_r)); + map(0x000098, 0x000098).rw(FUNC(tmp94c241_device::t4mod_r), FUNC(tmp94c241_device::t4mod_w)); + map(0x000099, 0x000099).rw(FUNC(tmp94c241_device::t4ffcr_r), FUNC(tmp94c241_device::t4ffcr_w)); + map(0x00009e, 0x00009e).rw(FUNC(tmp94c241_device::t16run_r), FUNC(tmp94c241_device::t16run_w)); + map(0x0000a0, 0x0000a3).w(FUNC(tmp94c241_device::treg67_w)); + map(0x0000a4, 0x0000a7).r(FUNC(tmp94c241_device::cap67_r)); + map(0x0000a8, 0x0000a8).rw(FUNC(tmp94c241_device::t6mod_r), FUNC(tmp94c241_device::t6mod_w)); + map(0x0000a9, 0x0000a9).rw(FUNC(tmp94c241_device::t6ffcr_r), FUNC(tmp94c241_device::t6ffcr_w)); + map(0x0000b0, 0x0000b3).w(FUNC(tmp94c241_device::treg89_w)); + map(0x0000b4, 0x0000b7).r(FUNC(tmp94c241_device::cap89_r)); + map(0x0000b8, 0x0000b8).rw(FUNC(tmp94c241_device::t8mod_r), FUNC(tmp94c241_device::t8mod_w)); + map(0x0000b9, 0x0000b9).rw(FUNC(tmp94c241_device::t8ffcr_r), FUNC(tmp94c241_device::t8ffcr_w)); + map(0x0000c0, 0x0000c3).w(FUNC(tmp94c241_device::tregab_w)); + map(0x0000c4, 0x0000c7).r(FUNC(tmp94c241_device::capab_r)); + map(0x0000c8, 0x0000c8).rw(FUNC(tmp94c241_device::tamod_r), FUNC(tmp94c241_device::tamod_w)); + map(0x0000c9, 0x0000c9).rw(FUNC(tmp94c241_device::taffcr_r), FUNC(tmp94c241_device::taffcr_w)); + map(0x0000d0, 0x0000d0).rw(FUNC(tmp94c241_device::sc0buf_r), FUNC(tmp94c241_device::sc0buf_w)); + map(0x0000d1, 0x0000d1).rw(FUNC(tmp94c241_device::sc0cr_r), FUNC(tmp94c241_device::sc0cr_w)); + map(0x0000d2, 0x0000d2).rw(FUNC(tmp94c241_device::sc0mod_r), FUNC(tmp94c241_device::sc0mod_w)); + map(0x0000d3, 0x0000d3).rw(FUNC(tmp94c241_device::br0cr_r), FUNC(tmp94c241_device::br0cr_w)); + map(0x0000d4, 0x0000d4).rw(FUNC(tmp94c241_device::sc1buf_r), FUNC(tmp94c241_device::sc1buf_w)); + map(0x0000d5, 0x0000d5).rw(FUNC(tmp94c241_device::sc1cr_r), FUNC(tmp94c241_device::sc1cr_w)); + map(0x0000d6, 0x0000d6).rw(FUNC(tmp94c241_device::sc1mod_r), FUNC(tmp94c241_device::sc1mod_w)); + map(0x0000d7, 0x0000d7).rw(FUNC(tmp94c241_device::br1cr_r), FUNC(tmp94c241_device::br1cr_w)); + map(0x0000e0, 0x0000f0).rw(FUNC(tmp94c241_device::inte_r), FUNC(tmp94c241_device::inte_w)); + map(0x0000f6, 0x0000f6).w(FUNC(tmp94c241_device::iimc_w)); + map(0x0000f7, 0x0000f7).rw(FUNC(tmp94c241_device::intnmwdt_r), FUNC(tmp94c241_device::intnmwdt_w)); + map(0x0000f8, 0x0000f8).w(FUNC(tmp94c241_device::intclr_w)); + map(0x000100, 0x000103).w(FUNC(tmp94c241_device::dmav_w)); + map(0x000110, 0x000110).rw(FUNC(tmp94c241_device::wdmod_r), FUNC(tmp94c241_device::wdmod_w)); + map(0x000111, 0x000111).w(FUNC(tmp94c241_device::wdcr_w)); + map(0x000120, 0x000127).r(FUNC(tmp94c241_device::adreg_r)); + map(0x000128, 0x000128).rw(FUNC(tmp94c241_device::admod1_r), FUNC(tmp94c241_device::admod1_w)); + map(0x000129, 0x000129).rw(FUNC(tmp94c241_device::admod2_r), FUNC(tmp94c241_device::admod2_w)); + map(0x000130, 0x000131).w(FUNC(tmp94c241_device::dareg_w)); + map(0x000132, 0x000132).rw(FUNC(tmp94c241_device::dadrv_r), FUNC(tmp94c241_device::dadrv_w)); + map(0x000140, 0x000141).w(FUNC(tmp94c241_device::b0cs_w)); + map(0x000142, 0x000142).rw(FUNC(tmp94c241_device::mamr0_r), FUNC(tmp94c241_device::mamr0_w)); + map(0x000143, 0x000143).rw(FUNC(tmp94c241_device::msar0_r), FUNC(tmp94c241_device::msar0_w)); + map(0x000144, 0x000145).w(FUNC(tmp94c241_device::b1cs_w)); + map(0x000146, 0x000146).rw(FUNC(tmp94c241_device::mamr1_r), FUNC(tmp94c241_device::mamr1_w)); + map(0x000147, 0x000147).rw(FUNC(tmp94c241_device::msar1_r), FUNC(tmp94c241_device::msar1_w)); + map(0x000148, 0x000149).w(FUNC(tmp94c241_device::b2cs_w)); + map(0x00014a, 0x00014a).rw(FUNC(tmp94c241_device::mamr2_r), FUNC(tmp94c241_device::mamr2_w)); + map(0x00014b, 0x00014b).rw(FUNC(tmp94c241_device::msar2_r), FUNC(tmp94c241_device::msar2_w)); + map(0x00014c, 0x00014d).w(FUNC(tmp94c241_device::b3cs_w)); + map(0x00014e, 0x00014e).rw(FUNC(tmp94c241_device::mamr3_r), FUNC(tmp94c241_device::mamr3_w)); + map(0x00014f, 0x00014f).rw(FUNC(tmp94c241_device::msar3_r), FUNC(tmp94c241_device::msar3_w)); + map(0x000150, 0x000151).w(FUNC(tmp94c241_device::b4cs_w)); + map(0x000152, 0x000152).rw(FUNC(tmp94c241_device::mamr4_r), FUNC(tmp94c241_device::mamr4_w)); + map(0x000153, 0x000153).rw(FUNC(tmp94c241_device::msar4_r), FUNC(tmp94c241_device::msar4_w)); + map(0x000154, 0x000155).w(FUNC(tmp94c241_device::b5cs_w)); + map(0x000156, 0x000156).rw(FUNC(tmp94c241_device::mamr5_r), FUNC(tmp94c241_device::mamr5_w)); + map(0x000157, 0x000157).rw(FUNC(tmp94c241_device::msar5_r), FUNC(tmp94c241_device::msar5_w)); + map(0x000400, 0x000bff).ram(); +} + +//************************************************************************** +// EXECUTION CALLBACKS +//************************************************************************** + +//------------------------------------------------- +// tlcs900_check_hdma - +//------------------------------------------------- + +void tmp94c241_device::tlcs900_check_hdma() +{ +} + + +//------------------------------------------------- +// tlcs900_check_irqs - +//------------------------------------------------- + +void tmp94c241_device::tlcs900_check_irqs() +{ + int irq_vectors[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; + int level = 0; + int irq = -1; + int i; + + /* Check for NMI */ + if ( m_nmi_state == ASSERT_LINE ) + { + m_xssp.d -= 4; + WRMEML( m_xssp.d, m_pc.d ); + m_xssp.d -= 2; + WRMEMW( m_xssp.d, m_sr.w.l ); + m_pc.d = RDMEML( 0xffff00 + 0x20 ); + m_cycles += 18; + m_prefetch_clear = true; + m_halted = 0; + m_nmi_state = CLEAR_LINE; + return; + } + + /* Check regular irqs */ + // the smaller the vector value, the higher the priority + for( i = TMP94C241_NUM_MASKABLE_IRQS - 1; i >= 0; i-- ) + { + if ( m_int_reg[tmp94c241_irq_vector_map[i].reg] & tmp94c241_irq_vector_map[i].iff ) + { + switch( tmp94c241_irq_vector_map[i].iff ) + { + case 0x80: + irq_vectors[ ( m_int_reg[ tmp94c241_irq_vector_map[i].reg ] >> 4 ) & 0x07 ] = i; + break; + case 0x08: + irq_vectors[ m_int_reg[ tmp94c241_irq_vector_map[i].reg ] & 0x07 ] = i; + break; + } + } + } + + /* Check highest allowed priority irq */ + for( i = std::max( 1, ( ( m_sr.b.h & 0x70 ) >> 4 ) ); i < 7; i++ ) + { + if ( irq_vectors[i] >= 0 ) + { + irq = irq_vectors[i]; + level = i + 1; + } + } + + /* Take irq */ + if ( irq >= 0 ) + { + uint8_t vector = tmp94c241_irq_vector_map[irq].vector; + + m_xssp.d -= 4; + WRMEML( m_xssp.d, m_pc.d ); + m_xssp.d -= 2; + WRMEMW( m_xssp.d, m_sr.w.l ); + + /* Mask off any lower priority interrupts */ + m_sr.b.h = ( m_sr.b.h & 0x8f ) | ( level << 4 ); + + m_pc.d = RDMEML( 0xffff00 + vector ); + + m_cycles += 18; + m_prefetch_clear = true; + + m_halted = 0; + + /* Clear taken IRQ */ + m_int_reg[ tmp94c241_irq_vector_map[irq].reg ] &= ~ tmp94c241_irq_vector_map[irq].iff; +// machine().debugger().debug_break(); + } +} + + +//------------------------------------------------- +// tlcs900_handle_ad - +//------------------------------------------------- + +void tmp94c241_device::tlcs900_handle_ad() +{ +} + + +//------------------------------------------------- +// tlcs900_handle_timers - +//------------------------------------------------- + +void tmp94c241_device::tlcs900_handle_timers() +{ + uint32_t old_pre = m_timer_pre; + + if ( PRESCALER_IS_ACTIVE ) + m_timer_pre += m_cycles; + + /* Timer 0 */ + if ( TIMER_0_IS_RUNNING ) + { + switch( T0_INPUT_CLOCK ) + { + case 0: /* TIO */ + break; + case 1: /* T1 */ + TIMER_CHANGE_0 += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 2: /* T4 */ + TIMER_CHANGE_0 += ( m_timer_pre >> 5 ) - ( old_pre >> 5 ); + break; + case 3: /* T16 */ + TIMER_CHANGE_0 += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + } + + for( ; TIMER_CHANGE_0 > 0; TIMER_CHANGE_0-- ) + { + UPCOUNTER_0++; + if ( UPCOUNTER_0 == SFR_TREG0 ) + { + if ( TO1_OPERATING_MODE == MODE_8BIT_TIMER ) + TIMER_CHANGE_1++; + + if ( (m_ffcr[0] & 0x03) == 0b10 ) + change_timer_flipflop( 1, FLIPFLOP_INVERT ); + + /* In 16bit timer mode the timer should not be reset */ + if ( TO1_OPERATING_MODE != MODE_16BIT_TIMER ) + { + UPCOUNTER_0 = 0; + m_int_reg[TMP94C241_INTET01] |= 0x08; + m_check_irqs = 1; + } + } + } + } + + /* Timer 1 */ + if ( TIMER_1_IS_RUNNING ) + { + switch( T1_INPUT_CLOCK ) + { + case 0x00: /* TO0TRG */ + break; + case 0x01: /* T1 */ + TIMER_CHANGE_1 += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 0x02: /* T16 */ + TIMER_CHANGE_1 += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + case 0x03: /* T256 */ + TIMER_CHANGE_1 += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); + break; + } + + for( ; TIMER_CHANGE_1 > 0; TIMER_CHANGE_1-- ) + { + UPCOUNTER_1 += 1; + if ( UPCOUNTER_1 == SFR_TREG1 ) + { + UPCOUNTER_1 = 0; + m_int_reg[TMP94C241_INTET01] |= 0x80; + m_check_irqs = 1; + + if ( (m_ffcr[0] & 0x03) == 0b11 ) + change_timer_flipflop( 1, FLIPFLOP_INVERT ); + + /* In 16bit timer mode also reset timer 0 */ + if ( TO1_OPERATING_MODE == MODE_16BIT_TIMER ) + UPCOUNTER_1 = 0; + } + } + } + + /* Timer 2 */ + if ( TIMER_2_IS_RUNNING ) + { + switch( T2_INPUT_CLOCK ) + { + case 0: /* invalid */ + case 1: /* T1 */ + TIMER_CHANGE_2 += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 2: /* T4 */ + TIMER_CHANGE_2 += ( m_timer_pre >> 5 ) - ( old_pre >> 5 ); + break; + case 3: /* T16 */ + TIMER_CHANGE_2 += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + } + + for( ; TIMER_CHANGE_2 > 0; TIMER_CHANGE_2-- ) + { + UPCOUNTER_2++; + if ( UPCOUNTER_2 == SFR_TREG2 ) + { + if ( T23_OPERATING_MODE == MODE_8BIT_TIMER ) + TIMER_CHANGE_3++; + + if ( ((m_ffcr[0] & 0x30) >> 4) == 0b10 ) + change_timer_flipflop( 3, FLIPFLOP_INVERT ); + + /* In 16bit timer mode the timer should not be reset */ + if ( T23_OPERATING_MODE != MODE_16BIT_TIMER ) + { + UPCOUNTER_2 = 0; + m_int_reg[TMP94C241_INTET23] |= 0x08; + m_check_irqs = 1; + } + } + } + } + + /* Timer 3 */ + if ( TIMER_3_IS_RUNNING ) + { + switch( T3_INPUT_CLOCK ) + { + case 0: /* TO2TRG */ + break; + case 1: /* T1 */ + TIMER_CHANGE_3 += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 2: /* T16 */ + TIMER_CHANGE_3 += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + case 3: /* T256 */ + TIMER_CHANGE_3 += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); + break; + } + + for( ; TIMER_CHANGE_3 > 0; TIMER_CHANGE_3-- ) + { + UPCOUNTER_3++; + if ( UPCOUNTER_3 == SFR_TREG3 ) + { + UPCOUNTER_3 = 0; + m_int_reg[TMP94C241_INTET23] |= 0x80; + m_check_irqs = 1; + + if ( ((m_ffcr[0] & 0x30) >> 4) == 0b11 ) + change_timer_flipflop( 3, FLIPFLOP_INVERT ); + + /* In 16bit timer mode also reset timer 2 */ + if ( T23_OPERATING_MODE == MODE_16BIT_TIMER ) + UPCOUNTER_2 = 0; + } + } + } + + /* Timer 4 */ + if ( TIMER_4_IS_RUNNING ) + { + switch( T4_INPUT_CLOCK ) + { + case 0x00: /* TIA */ + // TODO: implement-me! + break; + case 0x01: /* T1 */ + TIMER_CHANGE_4 += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 0x02: /* T4 */ + TIMER_CHANGE_4 += ( m_timer_pre >> 5 ) - ( old_pre >> 5 ); + break; + case 0x03: /* T16 */ + TIMER_CHANGE_4 += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + } + + for( ; TIMER_CHANGE_4 > 0; TIMER_CHANGE_4-- ) + { + UPCOUNTER_4++; + if ( ((UPCOUNTER_4 == SFR_TREG5) && EQ5T4) || + ((UPCOUNTER_4 == SFR_TREG4) && EQ4T4) ) + { + change_timer_flipflop( 4, FLIPFLOP_INVERT ); + UPCOUNTER_4 = 0; + m_int_reg[TMP94C241_INTET45] |= 0x08; + m_check_irqs = 1; + } + } + } + + + /* Timer 6 */ + if ( TIMER_6_IS_RUNNING ) + { + switch( T6_INPUT_CLOCK ) + { + case 0: /* TIA */ + // TODO: implement-me! + break; + case 1: /* T1 */ + TIMER_CHANGE_6 += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 2: /* T4 */ + TIMER_CHANGE_6 += ( m_timer_pre >> 5 ) - ( old_pre >> 5 ); + break; + case 3: /* T16 */ + TIMER_CHANGE_6 += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + } + + for( ; TIMER_CHANGE_6 > 0; TIMER_CHANGE_6-- ) + { + UPCOUNTER_6++; + if ( ((UPCOUNTER_6 == SFR_TREG7) && EQ7T6) || + ((UPCOUNTER_6 == SFR_TREG6) && EQ6T6) ) + { + change_timer_flipflop( 6, FLIPFLOP_INVERT ); + UPCOUNTER_6 = 0; + m_int_reg[TMP94C241_INTET67] |= 0x08; + m_check_irqs = 1; + } + } + } + + + /* Timer 8 */ + if ( TIMER_8_IS_RUNNING ) + { + switch( T8_INPUT_CLOCK ) + { + case 0x00: /* TIA */ + // TODO: implement-me! + break; + case 0x01: /* T1 */ + TIMER_CHANGE_8 += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 0x02: /* T4 */ + TIMER_CHANGE_8 += ( m_timer_pre >> 5 ) - ( old_pre >> 5 ); + break; + case 0x03: /* T16 */ + TIMER_CHANGE_8 += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + } + + for( ; TIMER_CHANGE_8 > 0; TIMER_CHANGE_8-- ) + { + UPCOUNTER_8++; + if ( ((UPCOUNTER_8 == SFR_TREG9) && EQ9T8) || + ((UPCOUNTER_8 == SFR_TREG8) && EQ8T8) ) + { + change_timer_flipflop( 8, FLIPFLOP_INVERT ); + UPCOUNTER_8 = 0; + m_int_reg[TMP94C241_INTET89] |= 0x08; + m_check_irqs = 1; + } + } + } + + + /* Timer A */ + if ( TIMER_A_IS_RUNNING ) + { + switch( TA_INPUT_CLOCK ) + { + case 0: /* TIA */ + // TODO: implement-me! + break; + case 1: /* T1 */ + TIMER_CHANGE_A += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 2: /* T4 */ + TIMER_CHANGE_A += ( m_timer_pre >> 5 ) - ( old_pre >> 5 ); + break; + case 3: /* T16 */ + TIMER_CHANGE_A += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + } + + for( ; TIMER_CHANGE_A > 0; TIMER_CHANGE_A-- ) + { + UPCOUNTER_A++; + if ( ((UPCOUNTER_A == SFR_TREGA) && EQATA) || + ((UPCOUNTER_A == SFR_TREGB) && EQBTA) ) + { + change_timer_flipflop( 0xa, FLIPFLOP_INVERT ); + UPCOUNTER_A = 0; + m_int_reg[TMP94C241_INTETAB] |= 0x08; + m_check_irqs = 1; + } + } + } + + m_timer_pre &= 0xffffff; +} + + +//------------------------------------------------- +// execute_set_input - called when a synchronized +// input is changed +//------------------------------------------------- + +void tmp94c241_device::execute_set_input(int input, int level) +{ + switch( input ) + { + case INPUT_LINE_NMI: + case TLCS900_NMI: + if ( m_level[TLCS900_NMI] == CLEAR_LINE && level == ASSERT_LINE ) + { + m_nmi_state = level; + } + m_level[TLCS900_NMI] = level; + break; + + case TLCS900_INTWD: + break; + + case TLCS900_INT0: + /* Is INT0 functionality enabled? */ + if (m_iimc & 0x04) + { + if (m_iimc & 0x02) + { + /* Rising edge detect */ + if (m_level[TLCS900_INT0] == CLEAR_LINE && level == ASSERT_LINE) + { + /* Leave HALT state */ + m_halted = 0; + m_int_reg[TMP94C241_INTE0AD] |= 0x08; + } + } + else + { + /* Level detect */ + if (level == ASSERT_LINE) + m_int_reg[TMP94C241_INTE0AD] |= 0x08; + else + m_int_reg[TMP94C241_INTE0AD] &= ~ 0x08; + } + } + m_level[TLCS900_INT0] = level; + break; + + case TLCS900_INT4: + if (m_level[TLCS900_INT4] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[TMP94C241_INTE45] |= 0x08; + } + else if (m_level[TLCS900_INT4] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[TMP94C241_INTE45] &= ~0x08; + } + m_level[TLCS900_INT4] = level; + break; + + case TLCS900_INT5: + if (m_level[TLCS900_INT5] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[TMP94C241_INTE45] |= 0x80; + } + else if (m_level[TLCS900_INT5] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[TMP94C241_INTE45] &= ~0x80; + } + m_level[TLCS900_INT5] = level; + break; + + case TLCS900_INT6: + if (m_level[TLCS900_INT6] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[TMP94C241_INTE67] |= 0x08; + } + else if (m_level[TLCS900_INT6] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[TMP94C241_INTE67] &= ~0x08; + } + m_level[TLCS900_INT3] = level; + break; + + case TLCS900_INT7: + if (m_level[TLCS900_INT7] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[TMP94C241_INTE67] |= 0x80; + } + else if (m_level[TLCS900_INT7] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[TMP94C241_INTE67] &= ~0x80; + } + m_level[TLCS900_INT7] = level; + break; + + case TLCS900_INT8: + if (m_level[TLCS900_INT8] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[TMP94C241_INTE89] |= 0x08; + } + else if (m_level[TLCS900_INT8] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[TMP94C241_INTE89] &= ~0x08; + } + m_level[TLCS900_INT8] = level; + break; + + case TLCS900_INT9: + if (m_level[TLCS900_INT9] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[TMP94C241_INTE89] |= 0x80; + } + else if (m_level[TLCS900_INT9] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[TMP94C241_INTE89] &= ~0x80; + } + m_level[TLCS900_INT9] = level; + break; + + case TLCS900_INTA: + if (m_level[TLCS900_INTA] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[TMP94C241_INTEAB] |= 0x08; + } + else if (m_level[TLCS900_INTA] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[TMP94C241_INTEAB] &= ~0x08; + } + m_level[TLCS900_INTA] = level; + break; + + case TLCS900_INTB: + if (m_level[TLCS900_INTB] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[TMP94C241_INTEAB] |= 0x80; + } + else if (m_level[TLCS900_INTB] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[TMP94C241_INTEAB] &= ~0x80; + } + m_level[TLCS900_INTB] = level; + break; + } + m_check_irqs = 1; +} + +std::unique_ptr tmp94c241_device::create_disassembler() +{ + return std::make_unique(); +} + diff --git a/src/devices/cpu/tlcs900/tmp94c241.h b/src/devices/cpu/tlcs900/tmp94c241.h new file mode 100644 index 0000000000000..3b9d1791457f4 --- /dev/null +++ b/src/devices/cpu/tlcs900/tmp94c241.h @@ -0,0 +1,419 @@ +// license:BSD-3-Clause +// copyright-holders:AJR,Wilbert Pol,Felipe Sanches +/**************************************************************************** + + Toshiba TMP94C241 microcontroller + +****************************************************************************/ + +#ifndef MAME_CPU_TLCS900_TMP94C241_H +#define MAME_CPU_TLCS900_TMP94C241_H + +#pragma once + +#include "tlcs900.h" + +#define TMP94C241_INTE45 0 +#define TMP94C241_INTE67 1 +#define TMP94C241_INTE89 2 +#define TMP94C241_INTEAB 3 +#define TMP94C241_INTET01 4 +#define TMP94C241_INTET23 5 +#define TMP94C241_INTET45 6 +#define TMP94C241_INTET67 7 +#define TMP94C241_INTET89 8 +#define TMP94C241_INTETAB 9 +#define TMP94C241_INTES0 10 +#define TMP94C241_INTES1 11 +#define TMP94C241_INTETC01 12 +#define TMP94C241_INTETC23 13 +#define TMP94C241_INTETC45 14 +#define TMP94C241_INTETC67 15 +#define TMP94C241_INTE0AD 16 +#define TMP94C241_INTNMWDT 17 + +// Flip-Flop operations: +#define FLIPFLOP_INVERT 0b00 +#define FLIPFLOP_SET 0b01 +#define FLIPFLOP_CLEAR 0b10 +#define FLIPFLOP_DONTCARE 0b11 + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> tmp94c241_device + +class tmp94c241_device : public tlcs900h_device +{ +public: + // device type constructor + tmp94c241_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + // configuration helpers + auto port0_read() { return m_port0_read.bind(); } + auto port0_write() { return m_port0_write.bind(); } + auto port1_read() { return m_port1_read.bind(); } + auto port1_write() { return m_port1_write.bind(); } + auto port2_read() { return m_port2_read.bind(); } + auto port2_write() { return m_port2_write.bind(); } + auto port3_read() { return m_port3_read.bind(); } + auto port3_write() { return m_port3_write.bind(); } + auto port4_read() { return m_port4_read.bind(); } + auto port4_write() { return m_port4_write.bind(); } + auto port5_read() { return m_port5_read.bind(); } + auto port5_write() { return m_port5_write.bind(); } + auto port6_read() { return m_port6_read.bind(); } + auto port6_write() { return m_port6_write.bind(); } + auto port7_read() { return m_port7_read.bind(); } + auto port7_write() { return m_port7_write.bind(); } + auto port8_read() { return m_port8_read.bind(); } + auto port8_write() { return m_port8_write.bind(); } + auto porta_read() { return m_porta_read.bind(); } + auto porta_write() { return m_porta_write.bind(); } + auto portb_read() { return m_portb_read.bind(); } + auto portb_write() { return m_portb_write.bind(); } + auto portc_read() { return m_portc_read.bind(); } + auto portc_write() { return m_portc_write.bind(); } + auto portd_read() { return m_portd_read.bind(); } + auto portd_write() { return m_portd_write.bind(); } + auto porte_read() { return m_porte_read.bind(); } + auto porte_write() { return m_porte_write.bind(); } + auto portf_read() { return m_portf_read.bind(); } + auto portf_write() { return m_portf_write.bind(); } + auto portg_read() { return m_portg_read.bind(); } + auto porth_read() { return m_porth_read.bind(); } + auto porth_write() { return m_porth_write.bind(); } + auto portz_read() { return m_portz_read.bind(); } + auto portz_write() { return m_portz_write.bind(); } + +protected: + // device-level overrides + virtual void device_config_complete() override; + virtual void device_start() override; + virtual void device_reset() override; + + // device_execute_interface overrides + virtual void execute_set_input(int inputnum, int state) override; + + // tlcs900_device overrides + virtual void tlcs900_check_hdma() override; + virtual void tlcs900_check_irqs() override; + virtual void tlcs900_handle_ad() override; + virtual void tlcs900_handle_timers() override; + + // device_disasm_interface overrides + virtual std::unique_ptr create_disassembler() override; + +private: + void change_timer_flipflop(uint8_t flipflop, uint8_t operation); + uint8_t p0_r(); + void p0_w(uint8_t data); + void p0cr_w(uint8_t data); + void p0fc_w(uint8_t data); + uint8_t p1_r(); + void p1_w(uint8_t data); + void p1cr_w(uint8_t data); + void p1fc_w(uint8_t data); + uint8_t p2_r(); + void p2_w(uint8_t data); + void p2cr_w(uint8_t data); + void p2fc_w(uint8_t data); + uint8_t p3_r(); + void p3_w(uint8_t data); + void p3cr_w(uint8_t data); + void p3fc_w(uint8_t data); + uint8_t p4_r(); + void p4_w(uint8_t data); + void p4cr_w(uint8_t data); + void p4fc_w(uint8_t data); + uint8_t p5_r(); + void p5_w(uint8_t data); + void p5cr_w(uint8_t data); + void p5fc_w(uint8_t data); + uint8_t p6_r(); + void p6_w(uint8_t data); + void p6cr_w(uint8_t data); + void p6fc_w(uint8_t data); + uint8_t p7_r(); + void p7_w(uint8_t data); + void p7cr_w(uint8_t data); + void p7fc_w(uint8_t data); + uint8_t p8_r(); + void p8_w(uint8_t data); + void p8cr_w(uint8_t data); + void p8fc_w(uint8_t data); + uint8_t pa_r(); + void pa_w(uint8_t data); + void pacr_w(uint8_t data); + void pafc_w(uint8_t data); + uint8_t pb_r(); + void pb_w(uint8_t data); + void pbcr_w(uint8_t data); + void pbfc_w(uint8_t data); + uint8_t pc_r(); + void pc_w(uint8_t data); + void pccr_w(uint8_t data); + void pcfc_w(uint8_t data); + uint8_t pd_r(); + void pd_w(uint8_t data); + void pdcr_w(uint8_t data); + void pdfc_w(uint8_t data); + uint8_t pe_r(); + void pe_w(uint8_t data); + void pecr_w(uint8_t data); + void pefc_w(uint8_t data); + uint8_t pf_r(); + void pf_w(uint8_t data); + void pfcr_w(uint8_t data); + void pffc_w(uint8_t data); + uint8_t pg_r(); + uint8_t ph_r(); + void ph_w(uint8_t data); + void phcr_w(uint8_t data); + void phfc_w(uint8_t data); + uint8_t pz_r(); + void pz_w(uint8_t data); + void pzcr_w(uint8_t data); + uint8_t t8run_r(); + void t8run_w(uint8_t data); + void treg01_w(offs_t offset, uint8_t data); + void treg23_w(offs_t offset, uint8_t data); + uint8_t t01mod_r(); + void t01mod_w(uint8_t data); + uint8_t t02ffcr_r(); + void t02ffcr_w(uint8_t data); + uint8_t t23mod_r(); + void t23mod_w(uint8_t data); + uint8_t trdc_r(); + void trdc_w(uint8_t data); + uint8_t t4mod_r(); + uint8_t t6mod_r(); + uint8_t t8mod_r(); + uint8_t tamod_r(); + void t4mod_w(uint8_t data); + void t6mod_w(uint8_t data); + void t8mod_w(uint8_t data); + void tamod_w(uint8_t data); + uint8_t t4ffcr_r(); + void t4ffcr_w(uint8_t data); + uint8_t t8ffcr_r(); + void t8ffcr_w(uint8_t data); + uint8_t t6ffcr_r(); + void t6ffcr_w(uint8_t data); + uint8_t taffcr_r(); + void taffcr_w(uint8_t data); + void treg45_w(offs_t offset, uint16_t data); + void treg67_w(offs_t offset, uint16_t data); + void treg89_w(offs_t offset, uint16_t data); + void tregab_w(offs_t offset, uint16_t data); + uint8_t cap45_r(offs_t offset); + uint8_t cap67_r(offs_t offset); + uint8_t cap89_r(offs_t offset); + uint8_t capab_r(offs_t offset); + uint8_t t16run_r(); + void t16run_w(uint8_t data); + uint8_t wdmod_r(); + void wdmod_w(uint8_t data); + void wdcr_w(uint8_t data); + uint8_t sc0buf_r(); + void sc0buf_w(uint8_t data); + uint8_t sc0cr_r(); + void sc0cr_w(uint8_t data); + uint8_t sc0mod_r(); + void sc0mod_w(uint8_t data); + uint8_t br0cr_r(); + void br0cr_w(uint8_t data); + uint8_t sc1buf_r(); + void sc1buf_w(uint8_t data); + uint8_t sc1cr_r(); + void sc1cr_w(uint8_t data); + uint8_t sc1mod_r(); + void sc1mod_w(uint8_t data); + uint8_t br1cr_r(); + void br1cr_w(uint8_t data); + uint8_t ode_r(); + void ode_w(uint8_t data); + uint8_t admod1_r(); + void admod1_w(uint8_t data); + uint8_t admod2_r(); + void admod2_w(uint8_t data); + uint8_t adreg_r(offs_t offset); + uint8_t inte_r(offs_t offset); + void inte_w(offs_t offset, uint8_t data); + uint8_t intnmwdt_r(offs_t offset); + void intnmwdt_w(offs_t offset, uint8_t data); + void iimc_w(uint8_t data); + void intclr_w(uint8_t data); + void dmav_w(offs_t offset, uint8_t data); + void b0cs_w(offs_t offset, uint8_t data); + void b1cs_w(offs_t offset, uint8_t data); + void b2cs_w(offs_t offset, uint8_t data); + void b3cs_w(offs_t offset, uint8_t data); + void b4cs_w(offs_t offset, uint8_t data); + void b5cs_w(offs_t offset, uint8_t data); + uint8_t msar0_r(); + void msar0_w(offs_t offset, uint8_t data); + uint8_t mamr0_r(); + void mamr0_w(offs_t offset, uint8_t data); + uint8_t msar1_r(); + void msar1_w(offs_t offset, uint8_t data); + uint8_t mamr1_r(); + void mamr1_w(offs_t offset, uint8_t data); + uint8_t msar2_r(); + void msar2_w(offs_t offset, uint8_t data); + uint8_t mamr2_r(); + void mamr2_w(offs_t offset, uint8_t data); + uint8_t msar3_r(); + void msar3_w(offs_t offset, uint8_t data); + uint8_t mamr3_r(); + void mamr3_w(offs_t offset, uint8_t data); + uint8_t msar4_r(); + void msar4_w(offs_t offset, uint8_t data); + uint8_t mamr4_r(); + void mamr4_w(offs_t offset, uint8_t data); + uint8_t msar5_r(); + void msar5_w(offs_t offset, uint8_t data); + uint8_t mamr5_r(); + void mamr5_w(offs_t offset, uint8_t data); + uint8_t drefcr1_r(); + void drefcr1_w(uint8_t data); + uint8_t dmemcr1_r(); + void dmemcr1_w(uint8_t data); + uint8_t drefcr3_r(); + void drefcr3_w(uint8_t data); + uint8_t dmemcr3_r(); + void dmemcr3_w(uint8_t data); + uint8_t dadrv_r(); + void dadrv_w(uint8_t data); + void dareg_w(offs_t offset, uint8_t data); + + void internal_mem(address_map &map); + + // Port 0: 8 bit I/O. Shared with d0-d7 + devcb_read8 m_port0_read; + devcb_write8 m_port0_write; + + // Port 1: 8 bit I/O. Shared with d8-d15 + devcb_read8 m_port1_read; + devcb_write8 m_port1_write; + + // Port 2: 8 bit I/O. Shared with d16-d23 + devcb_read8 m_port2_read; + devcb_write8 m_port2_write; + + // Port 3: 8 bit I/O. Shared with d24-d31 + devcb_read8 m_port3_read; + devcb_write8 m_port3_write; + + // Port 4: 8 bit I/O. Shared with a0-a7 + devcb_read8 m_port4_read; + devcb_write8 m_port4_write; + + // Port 5: 8 bit I/O. Shared with a8-a15 + devcb_read8 m_port5_read; + devcb_write8 m_port5_write; + + // Port 6: 8 bit I/O. Shared with a16-a23 + devcb_read8 m_port6_read; + devcb_write8 m_port6_write; + + // Port 7: 8 bit I/O. Shared with external memory & bus signals + devcb_read8 m_port7_read; + devcb_write8 m_port7_write; + + // Port 8: 7 bit I/O. Shared with chip-select signals + devcb_read8 m_port8_read; + devcb_write8 m_port8_write; + + // Port A: 5 bit I/O. Shared with external DRAM (channel 0) + devcb_read8 m_porta_read; + devcb_write8 m_porta_write; + + // Port B: 5 bit I/O. Shared with external DRAM (channel 1) + devcb_read8 m_portb_read; + devcb_write8 m_portb_write; + + // Port C: 2 bit I/O. Shared with outputs for 8-bit or 16-bit timers + devcb_read8 m_portc_read; + devcb_write8 m_portc_write; + + // Port D: 6 bit I/O. Shared with 16-bit timer I/O and interrupt input + devcb_read8 m_portd_read; + devcb_write8 m_portd_write; + + // Port E: 6 bit I/O. Shared with 8-bit or 16-bit timer output and interrupt input + devcb_read8 m_porte_read; + devcb_write8 m_porte_write; + + // Port F: 6 bit I/O. Shared with I/O functions of serial interface + devcb_read8 m_portf_read; + devcb_write8 m_portf_write; + + // Port G: 8 bit input-only. Shared with AD converter. + devcb_read8 m_portg_read; + + // Port H: 5 bit I/O. Shared with /INT0 and micro DMA + devcb_read8 m_porth_read; + devcb_write8 m_porth_write; + + // Port Z: 8 bit I/O. + devcb_read8 m_portz_read; + devcb_write8 m_portz_write; + + // analogue inputs, sampled at 10 bits + devcb_read16::array<8> m_an_read; + + // I/O Port Control + uint8_t m_port_latch[0x13]; + uint8_t m_port_control[0x13]; + uint8_t m_port_function[0x13]; + + // Timer Control + uint8_t m_t8run; + uint8_t m_t8_reg[8]; + uint8_t m_tmod[8]; + uint8_t m_ffcr[5]; + uint8_t m_trdc; + uint16_t m_t16_reg[8]; + uint16_t m_t16_cap[8]; + uint8_t m_t16run; + uint16_t m_timer16[4]; + + // Watchdog Timer + uint8_t m_watchdog_mode; + + // Serial Channel + uint8_t m_serial_control[2]; + uint8_t m_serial_mode[2]; + uint8_t m_baud_rate[2]; + uint8_t m_od_enable; + + // A/D Converter Control + uint8_t m_ad_mode1; + uint8_t m_ad_mode2; + uint16_t m_ad_result[4]; + + // Interrupt Control + uint8_t m_int_reg[18]; + uint8_t m_iimc; + uint8_t m_dma_vector[4]; + + // Chip Select/Wait Control + uint16_t m_block_cs[6]; + uint8_t m_external_cs; + uint8_t m_mem_start_reg[6]; + uint8_t m_mem_start_mask[6]; + + // DRAM Control + uint8_t m_dram_refresh[2]; + uint8_t m_dram_access[2]; + + // D/A Converter Control + uint8_t m_da_drive; +}; + +// device type declaration +DECLARE_DEVICE_TYPE(TMP94C241, tmp94c241_device) + +#endif // MAME_CPU_TLCS900_TMP94C241_H diff --git a/src/devices/cpu/tlcs900/tmp95c061.cpp b/src/devices/cpu/tlcs900/tmp95c061.cpp index d74d7baa0a114..c40a1e40ca22c 100644 --- a/src/devices/cpu/tlcs900/tmp95c061.cpp +++ b/src/devices/cpu/tlcs900/tmp95c061.cpp @@ -8,6 +8,7 @@ Toshiba TMP95C061 emulation #include "emu.h" #include "tmp95c061.h" +#include "dasm900.h" DEFINE_DEVICE_TYPE(TMP95C061, tmp95c061_device, "tmp95c061", "Toshiba TMP95C061") @@ -190,6 +191,12 @@ void tmp95c061_device::device_start() save_item(NAME(m_mem_start_mask)); save_item(NAME(m_dram_refresh)); save_item(NAME(m_dram_access)); + + m_nmi_state = CLEAR_LINE; + for( int i = 0; i < TLCS900_NUM_INPUTS; i++ ) + { + m_level[i] = CLEAR_LINE; + } } void tmp95c061_device::device_reset() @@ -200,7 +207,6 @@ void tmp95c061_device::device_reset() m_to3 = 0; m_ad_cycles_left = 0; - m_nmi_state = CLEAR_LINE; m_timer_pre = 0; m_timer_change[0] = 0; m_timer_change[1] = 0; @@ -250,11 +256,6 @@ void tmp95c061_device::device_reset() std::fill_n(&m_mem_start_mask[0], 4, 0xff); m_dram_refresh = 0x00; m_dram_access = 0x80; - - for (int i = 0; i < TLCS900_NUM_INPUTS; i++) - { - m_level[i] = CLEAR_LINE; - } } @@ -574,11 +575,11 @@ void tmp95c061_device::tlcs900_handle_ad() } -enum ff_change +enum flipflop_change { - FF_CLEAR, - FF_SET, - FF_INVERT + FLIPFLOP_CLEAR, + FLIPFLOP_SET, + FLIPFLOP_INVERT }; @@ -589,13 +590,13 @@ void tmp95c061_device::tlcs900_change_tff( int which, int change ) case 1: switch( change ) { - case FF_CLEAR: + case FLIPFLOP_CLEAR: m_to1 = 0; break; - case FF_SET: + case FLIPFLOP_SET: m_to1 = 1; break; - case FF_INVERT: + case FLIPFLOP_INVERT: m_to1 ^= 1; break; } @@ -604,13 +605,13 @@ void tmp95c061_device::tlcs900_change_tff( int which, int change ) case 3: switch( change ) { - case FF_CLEAR: + case FLIPFLOP_CLEAR: m_to3 = 0; break; - case FF_SET: + case FLIPFLOP_SET: m_to3 = 1; break; - case FF_INVERT: + case FLIPFLOP_INVERT: m_to3 ^= 1; break; } @@ -695,7 +696,7 @@ void tmp95c061_device::tlcs900_handle_timers() if ( m_t8_invert & 0x02 ) { - tlcs900_change_tff( 1, FF_INVERT ); + tlcs900_change_tff( 1, FLIPFLOP_INVERT ); } /* In 16bit timer mode also reset timer 0 */ @@ -772,7 +773,7 @@ void tmp95c061_device::tlcs900_handle_timers() if ( m_t8_invert & 0x20 ) { - tlcs900_change_tff( 3, FF_INVERT ); + tlcs900_change_tff( 3, FLIPFLOP_INVERT ); } /* In 16bit timer mode also reset timer 2 */ @@ -1090,25 +1091,25 @@ void tmp95c061_device::tffcr_w(uint8_t data) switch( data & 0x0c ) { case 0x00: - tlcs900_change_tff( 1, FF_INVERT ); + tlcs900_change_tff( 1, FLIPFLOP_INVERT ); break; case 0x04: - tlcs900_change_tff( 1, FF_SET ); + tlcs900_change_tff( 1, FLIPFLOP_SET ); break; case 0x08: - tlcs900_change_tff( 1, FF_CLEAR ); + tlcs900_change_tff( 1, FLIPFLOP_CLEAR ); break; } switch( data & 0xc0 ) { case 0x00: - tlcs900_change_tff( 3, FF_INVERT ); + tlcs900_change_tff( 3, FLIPFLOP_INVERT ); break; case 0x40: - tlcs900_change_tff( 3, FF_SET ); + tlcs900_change_tff( 3, FLIPFLOP_SET ); break; case 0x80: - tlcs900_change_tff( 3, FF_CLEAR ); + tlcs900_change_tff( 3, FLIPFLOP_CLEAR ); break; } @@ -1480,3 +1481,8 @@ void tmp95c061_device::dmemcr_w(uint8_t data) { m_dram_access = data; } + +std::unique_ptr tmp95c061_device::create_disassembler() +{ + return std::make_unique(); +} diff --git a/src/devices/cpu/tlcs900/tmp95c061.h b/src/devices/cpu/tlcs900/tmp95c061.h index 106ca5c57ce71..2364048aa1c27 100644 --- a/src/devices/cpu/tlcs900/tmp95c061.h +++ b/src/devices/cpu/tlcs900/tmp95c061.h @@ -50,6 +50,9 @@ class tmp95c061_device : public tlcs900h_device int tlcs900_process_hdma( int channel ); void update_porta(); + // device_disasm_interface overrides + virtual std::unique_ptr create_disassembler() override; + private: uint8_t p1_r(); void p1_w(uint8_t data); diff --git a/src/devices/cpu/tlcs900/tmp95c063.cpp b/src/devices/cpu/tlcs900/tmp95c063.cpp index c70a19e85cc31..5156b01a2df83 100644 --- a/src/devices/cpu/tlcs900/tmp95c063.cpp +++ b/src/devices/cpu/tlcs900/tmp95c063.cpp @@ -8,6 +8,7 @@ Toshiba TMP95C063 emulation #include "emu.h" #include "tmp95c063.h" +#include "dasm900.h" DEFINE_DEVICE_TYPE(TMP95C063, tmp95c063_device, "tmp95c063", "Toshiba TMP95C063") @@ -589,6 +590,12 @@ void tmp95c063_device::device_start() save_item(NAME(m_dram_refresh)); save_item(NAME(m_dram_access)); save_item(NAME(m_da_drive)); + + m_nmi_state = CLEAR_LINE; + for( int i = 0; i < TLCS900_NUM_INPUTS; i++ ) + { + m_level[i] = CLEAR_LINE; + } } void tmp95c063_device::device_reset() @@ -596,7 +603,6 @@ void tmp95c063_device::device_reset() tlcs900h_device::device_reset(); m_ad_cycles_left = 0; - m_nmi_state = CLEAR_LINE; m_timer_pre = 0; m_timer_change[0] = 0; m_timer_change[1] = 0; @@ -647,9 +653,6 @@ void tmp95c063_device::device_reset() std::fill_n(&m_dram_refresh[0], 2, 0x00); std::fill_n(&m_dram_access[0], 2, 0x80); m_da_drive = 0x00; - - for (int i = 0; i < TLCS900_NUM_INPUTS; i++) - m_level[i] = CLEAR_LINE; } @@ -1601,3 +1604,8 @@ void tmp95c063_device::execute_set_input(int input, int level) } m_check_irqs = 1; } + +std::unique_ptr tmp95c063_device::create_disassembler() +{ + return std::make_unique(); +} diff --git a/src/devices/cpu/tlcs900/tmp95c063.h b/src/devices/cpu/tlcs900/tmp95c063.h index 4c9c05bb4334b..d24857d17a0bc 100644 --- a/src/devices/cpu/tlcs900/tmp95c063.h +++ b/src/devices/cpu/tlcs900/tmp95c063.h @@ -53,6 +53,9 @@ class tmp95c063_device : public tlcs900h_device virtual void tlcs900_handle_ad() override; virtual void tlcs900_handle_timers() override; + // device_disasm_interface overrides + virtual std::unique_ptr create_disassembler() override; + private: uint8_t p1_r(); void p1_w(uint8_t data); diff --git a/src/devices/cpu/tlcs900/tmp96c141.cpp b/src/devices/cpu/tlcs900/tmp96c141.cpp index b5e64be8da3e5..49dca16c434ca 100644 --- a/src/devices/cpu/tlcs900/tmp96c141.cpp +++ b/src/devices/cpu/tlcs900/tmp96c141.cpp @@ -12,6 +12,7 @@ #include "emu.h" #include "tmp96c141.h" +#include "dasm900.h" //************************************************************************** @@ -195,3 +196,8 @@ void tmp96c141_device::tlcs900_handle_timers() void tmp96c141_device::execute_set_input(int inputnum, int state) { } + +std::unique_ptr tmp96c141_device::create_disassembler() +{ + return std::make_unique(); +} diff --git a/src/devices/cpu/tlcs900/tmp96c141.h b/src/devices/cpu/tlcs900/tmp96c141.h index 973693a201be1..7bf6b0b8509e4 100644 --- a/src/devices/cpu/tlcs900/tmp96c141.h +++ b/src/devices/cpu/tlcs900/tmp96c141.h @@ -88,6 +88,9 @@ class tmp96c141_device : public tlcs900_device virtual void tlcs900_handle_ad() override; virtual void tlcs900_handle_timers() override; + // device_disasm_interface overrides + virtual std::unique_ptr create_disassembler() override; + private: void internal_mem(address_map &map); }; diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 2f643f419f874..ea8f21508be79 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -25083,14 +25083,14 @@ jr100u // jr200 // jr200u // +@source:matsushita/kn5000.cpp +kn5000 // (c) 1998 Technics SX KN-5000 PCM Keyboard + @source:matsushita/myb3k.cpp myb3k // jb3000 // stepone // -@source:matsushita/kn5000.cpp -kn5000 // (c) 199? Technics SX-KN5000 PCM Keyboard - @source:mattel/aquarius.cpp aquarius // 1983 Aquarius (NTSC) aquariusp // 1983 Aquarius (PAL) diff --git a/src/mame/matsushita/kn5000.cpp b/src/mame/matsushita/kn5000.cpp index 2ed7180a0dabf..189daf6fe123e 100644 --- a/src/mame/matsushita/kn5000.cpp +++ b/src/mame/matsushita/kn5000.cpp @@ -7,7 +7,8 @@ ******************************************************************************/ #include "emu.h" -#include "cpu/tlcs900/tmp95c061.h" // TODO: tmp94c241.h +#include "bus/technics/hdae5000.h" +#include "cpu/tlcs900/tmp94c241.h" #include "imagedev/floppy.h" #include "machine/gen_latch.h" #include "machine/upd765.h" @@ -95,6 +96,8 @@ class kn5000_state : public driver_device , m_maincpu_latch(*this, "maincpu_latch") , m_subcpu_latch(*this, "subcpu_latch") , m_fdc(*this, "fdc") + , m_extension(*this, "extension") + , m_extension_view(*this, "extension_view") , m_CPL_SEG(*this, "CPL_SEG%u", 0U) , m_CPR_SEG(*this, "CPR_SEG%u", 0U) , m_checking_device_led_cn11(*this, "checking_device_led_cn11") @@ -109,11 +112,14 @@ class kn5000_state : public driver_device void kn5000(machine_config &config); private: - required_device m_maincpu; - required_device m_subcpu; + required_device m_maincpu; + required_device m_subcpu; required_device m_maincpu_latch; required_device m_subcpu_latch; required_device m_fdc; + required_device m_extension; + memory_view m_extension_view; + required_ioport_array<11> m_CPL_SEG; // buttons on "Control Panel Left" PCB required_ioport_array<11> m_CPR_SEG; // buttons on "Control Panel Right" PCB output_finder<> m_checking_device_led_cn11; @@ -131,10 +137,30 @@ class kn5000_state : public driver_device uint8_t cpanel_right_buttons_r(offs_t offset); void cpanel_leds_w(offs_t offset, uint8_t data); +// void maincpu_portb_w(offs_t offset, uint8_t data); +// void maincpu_port5_w(offs_t offset, uint8_t data); +// void maincpu_port6_w(offs_t offset, uint8_t data); +// void maincpu_port7_w(offs_t offset, uint8_t data); void maincpu_mem(address_map &map); void subcpu_mem(address_map &map); +// uint16_t tone_generator_r(offs_t offset); +// void tone_generator_w(offs_t offset, uint16_t data); }; +/* +MSAR0: 0x1e MAMR0: 0x0f start: 0x1e0000 mask: 0x01ffff (128kB) SRAM @ IC21 +MSAR1: 0x10 MAMR1: 0x3f start: 0x100000 mask: 0x0fffff (1MByte) +MSAR2: 0xc0 MAMR2: 0x7f start: 0xc00000 mask: 0x3fffff (4MByte) table data ROM (also boot?) +MSAR3: 0x00 MAMR3: 0x1f start: 0x000000 mask: 0x0fffff (1MByte) DRAM ? +MSAR4: 0x80 MAMR4: 0xff start: 0x800000 mask: 0x7fffff (8MByte) +MSAR5: 0x00 MAMR5: 0xff start: 0x000000 mask: 0x7fffff (8MByte) + CS5: optional HSRAM at A22=0 A21=X A20=0 A19=0 (0x200000) (512k) + CS5: optional HSROM at A22=0 A21=X A20=0 A19=1 (0x280000) (512k) + CS5: custom data at A22=0 A21=X A20=1 (0x300000) (1MB) + CS5: rhythm data at A22=1 (0x400000) (4MB) +*/ + + void kn5000_state::maincpu_mem(address_map &map) { map(0x000000, 0x0fffff).ram(); // 1Mbyte = 2 * 4Mbit DRAMs @ IC9, IC10 (CS3) @@ -148,11 +174,14 @@ void kn5000_state::maincpu_mem(address_map &map) map(0x1703b0, 0x1703df).m("vga", FUNC(mn89304_vga_device::io_map)); // LCD controller @ IC206 map(0x1a0000, 0x1bffff).rw("vga", FUNC(mn89304_vga_device::mem_linear_r), FUNC(mn89304_vga_device::mem_linear_w)); map(0x1e0000, 0x1fffff).ram(); // 1Mbit SRAM @ IC21 (CS0) Note: I think this is the message "ERROR in back-up SRAM" - map(0x200000, 0x2fffff).noprw(); // Extension board goes here. + map(0x200000, 0x2fffff).view(m_extension_view); + m_extension_view[0](0x200000, 0x2fffff).noprw(); + m_extension_view[1](0x200000, 0x27ffff).ram(); // optional hsram: 2 * 256k bytes Static RAM @ IC5, IC6 (CS5) map(0x300000, 0x3fffff).rom().region("custom_data", 0); // 8MBit FLASH ROM @ IC19 (CS5) map(0x400000, 0x7fffff).rom().region("rhythm_data", 0); // 32MBit ROM @ IC14 (A22=1 and CS5) - map(0x800000, 0x82ffff).rom().region("subprogram", 0); // not sure yet in which chip this is stored, but I suspect it should be IC19 -// map(0xc00000, 0xdfffff).mirror(0x200000).rom().region("table_data", 0); //2 * 8MBit ROMs @ IC1, IC3 (CS2) + + map(0x800000, 0x82ffff).rom().region("subprogram", 0); // FIXME: not sure yet in which chip this is stored, but I suspect it should be IC19 + //FIXME: map(0xc00000, 0xdfffff).mirror(0x200000).rom().region("table_data", 0); //2 * 8MBit ROMs @ IC1, IC3 (CS2) map(0xe00000, 0xffffff).mask(0x1fffff).rom().region("program", 0); //2 * 8MBit FLASH ROMs @ IC4, IC6 } @@ -554,13 +583,12 @@ void kn5000_state::cpanel_leds_w(offs_t offset, uint8_t data) break; case 0xc3: - // FIXME: bits 2 and 3 used twice m_CPL_LED[25] = BIT(data, 0); // D125 - VARIATION & MSA 1 m_CPL_LED[26] = BIT(data, 1); // D126 - VARIATION & MSA 2 m_CPL_LED[27] = BIT(data, 2); // D127 - VARIATION & MSA 3 m_CPL_LED[28] = BIT(data, 3); // D128 - VARIATION & MSA 4 - m_CPL_LED[29] = BIT(data, 2); // D129 - MUSIC STYLE ARRANGER - m_CPL_LED[30] = BIT(data, 3); // D130 - AUTO PLAY CHORD + m_CPL_LED[29] = BIT(data, 4); // D129 - MUSIC STYLE ARRANGER + m_CPL_LED[30] = BIT(data, 5); // D130 - AUTO PLAY CHORD break; case 0xc4: @@ -575,7 +603,6 @@ void kn5000_state::cpanel_leds_w(offs_t offset, uint8_t data) break; case 0xc8: - // I'm not sure yet about this one... m_CPL_LED[49] = BIT(data, 0); // D149 - OTHER PARTS/TR break; @@ -591,6 +618,16 @@ void kn5000_state::machine_start() save_item(NAME(m_mstat)); save_item(NAME(m_sstat)); + if(m_extension) + { + m_extension->rom_map(m_extension_view[1], 0x280000, 0x2fffff); + m_extension_view.select(1); + } + else + { + m_extension_view.select(0); + } + m_checking_device_led_cn11.resolve(); m_checking_device_led_cn12.resolve(); m_CPL_LED.resolve(); @@ -606,7 +643,7 @@ void kn5000_state::machine_reset() void kn5000_state::kn5000(machine_config &config) { // Note: The CPU has an internal clock doubler - TMP95C061(config, m_maincpu, 2 * 8_MHz_XTAL); // actual cpu is TMP94C241F @ IC5 + TMP94C241(config, m_maincpu, 2 * 8_MHz_XTAL); // TMP94C241F @ IC5 // Address bus is set to 32 bits by the pins AM1=+5v and AM0=GND m_maincpu->set_addrmap(AS_PROGRAM, &kn5000_state::maincpu_mem); // Interrupt 4: FDCINT @@ -638,14 +675,14 @@ void kn5000_state::kn5000(machine_config &config) // MAINCPU PORT C: // bit 0 (input) = "check terminal" switch // bit 1 (output) = "check terminal" LED - // TODO: m_maincpu->portc_read().set([this] { return ioport("CN11")->read(); }); - // TODO: m_maincpu->portc_write().set([this] (u8 data) { m_checking_device_led_cn11 = (BIT(data, 1) == 0); }); + m_maincpu->portc_read().set([this] { return ioport("CN11")->read(); }); + m_maincpu->portc_write().set([this] (u8 data) { m_checking_device_led_cn11 = (BIT(data, 1) == 0); }); // MAINCPU PORT D: // bit 0 (output) = FDCRST // bit 6 (input) = FD.I/O - // TODO: m_maincpu->portd_write().set([this] (u8 data) { m_fdc->reset_w(BIT(data, 0)); }); + m_maincpu->portd_write().set([this] (u8 data) { m_fdc->reset_w(BIT(data, 0)); }); // TODO: bit 6! @@ -653,7 +690,7 @@ void kn5000_state::kn5000(machine_config &config) // bit 0 (input) = +5v // bit 2 (input) = HDDRDY // bit 4 (?) = MICSNS - // TODO: m_maincpu->porte_read().set([] { return 1; }); //checked at EF05A6 (v10 ROM) + m_maincpu->porte_read().set([] { return 1; }); //checked at EF05A6 (v10 ROM) // FIXME: Bit 0 should only be 1 if the // optional hard-drive extension board is disabled; @@ -673,7 +710,7 @@ void kn5000_state::kn5000(machine_config &config) // MAINCPU PORT H: // bit 1 = TC1 Terminal count - microDMA - // TODO: m_maincpu->porth_read().set([] { return 2; }); // area/region detection: checked at EF083E (v10 ROM) + m_maincpu->porth_read().set([] { return 2; }); // area/region detection: checked at EF083E (v10 ROM) // FIXME: These are resistors on the pcb, but could be declared // in the driver as a 2 bit DIP-Switch for area/region selection. @@ -687,12 +724,12 @@ void kn5000_state::kn5000(machine_config &config) // bit 5 = (input) COM.PC1 // bit 6 = (input) COM.MAC // bit 7 = (input) COM.MIDI - // TODO: m_maincpu->portz_read().set([this] { - // TODO: return ioport("COM_SELECT")->read() | (m_sstat << 2); - // TODO: }); - // TODO: m_maincpu->portz_write().set([this] (u8 data) { - // TODO: m_mstat = data & 3; - // TODO: }); + m_maincpu->portz_read().set([this] { + return ioport("COM_SELECT")->read() | (m_sstat << 2); + }); + m_maincpu->portz_write().set([this] (u8 data) { + m_mstat = data & 3; + }); // RX0/TX0 = MRXD/MTXD @@ -703,15 +740,16 @@ void kn5000_state::kn5000(machine_config &config) // AN1 = AFT // Note: The CPU has an internal clock doubler - TMP95C061(config, m_subcpu, 2*10_MHz_XTAL); // actual cpu is TMP94C241F @ IC27 + TMP94C241(config, m_subcpu, 2*10_MHz_XTAL); // TMP94C241F @ IC27 // Address bus is set to 8 bits by the pins AM1=GND and AM0=GND m_subcpu->set_addrmap(AS_PROGRAM, &kn5000_state::subcpu_mem); // SUBCPU PORT C: // bit 0 (input) = "check terminal" switch // bit 1 (output) = "check terminal" LED - // TODO: m_subcpu->portc_read().set([this] { return ioport("CN12")->read(); }); - // TODO: m_subcpu->portc_write().set([this] (u8 data) { m_checking_device_led_cn12 = (BIT(data, 1) == 0); }); + m_subcpu->portc_read().set([this] { return ioport("CN12")->read(); }); + m_subcpu->portc_write().set([this] (u8 data) { m_checking_device_led_cn12 = (BIT(data, 1) == 0); }); + // SUBCPU PORT D: // bit 0 = (output) SSTAT0 @@ -719,12 +757,12 @@ void kn5000_state::kn5000(machine_config &config) // bit 2 = (input) MSTAT0 // bit 3 (not used) // bit 4 = (input) MSTAT1 - // TODO: m_subcpu->portd_read().set([this] { - // TODO: return (BIT(m_mstat, 0) << 2) | (BIT(m_mstat, 1) << 4); - // TODO: }); - // TODO: m_subcpu->portd_write().set([this] (u8 data) { - // TODO: m_sstat = data & 3; - // TODO: }); + m_subcpu->portd_read().set([this] { + return (BIT(m_mstat, 0) << 2) | (BIT(m_mstat, 1) << 4); + }); + m_subcpu->portd_write().set([this] (u8 data) { + m_sstat = data & 3; + }); GENERIC_LATCH_8(config, m_maincpu_latch); // @ IC23 @@ -746,6 +784,16 @@ void kn5000_state::kn5000(machine_config &config) FLOPPY_CONNECTOR(config, "fdc:0", kn5000_floppies, "35dd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true); + /* extension port */ + KN5000_EXTENSION(config, m_extension, 16_MHz_XTAL / 16); //FIXME: which clock signal should be passed to the extension port? +// m_extension->firq_callback().set("mainfirq", FUNC(input_merger_device::in_w<3>)); // FIXME: do we need something like this? +// m_extension->irq_callback().set("mainirq", FUNC(input_merger_device::in_w<3>)); // FIXME: do we need something like this? + m_extension->option_add("hdae5000", HDAE5000); + + /* sound hardware */ + //SPEAKER(config, "lspeaker").front_left(); + //SPEAKER(config, "rspeaker").front_right(); + /* video hardware */ // LCD Controller MN89304 @ IC206 24_MHz_XTAL screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD)); diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index da562db857ba6..c6d6a452bf438 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -637,10 +637,13 @@ static const dasm_table_entry dasm_table[] = { "superfx", le, 0, []() -> util::disasm_interface * { return new superfx_disassembler(&superfx_unidasm); } }, { "t11", le, 0, []() -> util::disasm_interface * { return new t11_disassembler; } }, { "tlcs870", le, 0, []() -> util::disasm_interface * { return new tlcs870_disassembler; } }, - { "tlcs900", le, 0, []() -> util::disasm_interface * { return new tlcs900_disassembler; } }, { "tmp90c051", le, 0, []() -> util::disasm_interface * { return new tmp90c051_disassembler; } }, { "tmp90840", le, 0, []() -> util::disasm_interface * { return new tmp90840_disassembler; } }, { "tmp90844", le, 0, []() -> util::disasm_interface * { return new tmp90844_disassembler; } }, + { "tmp94c241", le, 0, []() -> util::disasm_interface * { return new tmp94c241_disassembler; } }, + { "tmp95c061", le, 0, []() -> util::disasm_interface * { return new tmp95c061_disassembler; } }, + { "tmp95c063", le, 0, []() -> util::disasm_interface * { return new tmp95c063_disassembler; } }, + { "tmp96c141", le, 0, []() -> util::disasm_interface * { return new tmp96c141_disassembler; } }, { "tms0980", be, 0, []() -> util::disasm_interface * { return new tms0980_disassembler; } }, { "tms1000", le, 0, []() -> util::disasm_interface * { return new tms1000_disassembler; } }, { "tms1100", le, 0, []() -> util::disasm_interface * { return new tms1100_disassembler; } },