From 962f44a5fa1cfcd33bee527cb0ac376f4acaf3cd Mon Sep 17 00:00:00 2001 From: hap Date: Mon, 10 Apr 2023 19:41:35 +0200 Subject: smc1102: add opcode placeholders and microinstructions --- src/devices/cpu/tms1000/smc1102.cpp | 110 ++++++++++++++++++++++++++++++- src/devices/cpu/tms1000/smc1102.h | 14 ++++ src/devices/cpu/tms1000/tms1k_base.cpp | 4 ++ src/devices/cpu/tms1000/tms1k_base.h | 115 +++++++++++++++++---------------- src/devices/cpu/tms1000/tms1k_dasm.cpp | 6 +- src/mame/coleco/wrinkles.cpp | 56 +++++++++------- src/mame/handheld/hh_tms1k.cpp | 1 + src/mame/miltonbradley/microvsn.cpp | 2 +- 8 files changed, 223 insertions(+), 85 deletions(-) diff --git a/src/devices/cpu/tms1000/smc1102.cpp b/src/devices/cpu/tms1000/smc1102.cpp index f0ad714fdc1..9f8ae066ff9 100644 --- a/src/devices/cpu/tms1000/smc1102.cpp +++ b/src/devices/cpu/tms1000/smc1102.cpp @@ -7,7 +7,7 @@ SMC1102 is a CMOS MCU based on TMS1100, keeping the same ALU and opcode mnemonics. They added a timer, interrupts, and a built-in LCD controller. -In the USA, it was marketed by S-MOS Systems, an affiliate of the Seiko Group. +In the USA, it was marketed by S-MOS Systems, an affiliate of Seiko Group. SMC1112 die notes (SMC1102 is assumed to be the same): - 128x4 RAM array at top-left @@ -18,7 +18,10 @@ SMC1112 die notes (SMC1102 is assumed to be the same): - no output PLA TODO: -- x +- row(pc) order is unknown +- each opcode is 4 cycles instead of 6 +- does it have CL (call latch) +- everything else */ @@ -60,10 +63,111 @@ void smc1102_cpu_device::device_start() u32 smc1102_cpu_device::decode_micro(offs_t offset) { - return 0; + // TCY, YNEC, TCMIY + static const u16 micro1[3] = { 0x0402, 0x1204, 0x1032 }; + + // 0x20, 0x30, 0x00, 0x70 + static const u16 micro2[0x40] = + { + 0x0102, 0x0801, 0x0802, 0x1001, 0x306a, 0x303a, 0x2021, 0x2020, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0e04, 0x0e04, 0x0e04, 0x0e04, 0x0899, 0x0099, 0x0819, 0x0804, + + 0x0904, 0x0898, 0x1104, 0x2821, 0x104a, 0x101a, 0x0909, 0x0849, + 0x0401, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000, + + 0x0519, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0519, + 0x0000, 0x0519, 0x0519, 0x0000, 0x0000, 0x0000, 0x0519, 0x0419, + }; + + u16 mask = 0; + + if (offset >= 0x40 && offset < 0x70) + mask = micro1[offset >> 4 & 3]; + else if (offset < 0x80 && (offset & 0xf0) != 0x10) + mask = micro2[((offset ^ 0x20) | (offset >> 1 & 0x20)) & 0x3f]; + + // does not have M_MTN or M_STSL + const u32 md[14] = { M_AUTA, M_AUTY, M_NE, M_C8, M_CIN, M_CKM, M_15TN, M_NATN, M_ATN, M_CKN, M_CKP, M_MTP, M_YTP, M_STO }; + u32 decode = 0; + + for (int bit = 0; bit < 14; bit++) + if (mask & (1 << bit)) + decode |= md[bit]; + + return decode; } void smc1102_cpu_device::device_reset() { tms1100_cpu_device::device_reset(); + + // changed/added fixed instructions (mostly handled in op_extra) + m_fixed_decode[0x0a] = F_EXTRA; + m_fixed_decode[0x71] = F_EXTRA; + m_fixed_decode[0x74] = F_EXTRA; + m_fixed_decode[0x75] = F_EXTRA; + m_fixed_decode[0x76] = F_RETN; + m_fixed_decode[0x78] = F_EXTRA; + m_fixed_decode[0x7b] = F_EXTRA; + + m_fixed_decode[0x72] = m_fixed_decode[0x73] = F_EXTRA; + m_fixed_decode[0x7c] = m_fixed_decode[0x7d] = F_EXTRA; +} + + +// opcode deviations +void smc1102_cpu_device::op_tasr() +{ + // TASR: transfer A to LCD S/R +} + +void smc1102_cpu_device::op_tsg() +{ + // TSG: transfer LCD S/R to RAM +} + +void smc1102_cpu_device::op_intdis() +{ + // INTDIS: disable interrupt +} + +void smc1102_cpu_device::op_inten() +{ + // INTEN: enable interrupt after next instruction +} + +void smc1102_cpu_device::op_selin() +{ + // SELIN: select interrupt +} + +void smc1102_cpu_device::op_tmset() +{ + // TMSET: transfer A to timer latch +} + +void smc1102_cpu_device::op_halt() +{ + // HALT: stop CPU +} + +void smc1102_cpu_device::op_extra() +{ + switch (m_opcode) + { + case 0x0a: op_tasr(); break; + case 0x71: op_halt(); break; + case 0x74: op_inten(); break; + case 0x75: op_intdis(); break; + case 0x78: op_selin(); break; + case 0x7b: op_tmset(); break; + + case 0x72: case 0x73: case 0x7c: case 0x7d: + op_tsg(); break; + + default: break; + } } diff --git a/src/devices/cpu/tms1000/smc1102.h b/src/devices/cpu/tms1000/smc1102.h index c400b124f71..3c55ccd33fa 100644 --- a/src/devices/cpu/tms1000/smc1102.h +++ b/src/devices/cpu/tms1000/smc1102.h @@ -53,6 +53,20 @@ protected: virtual u32 decode_micro(offs_t offset) override; virtual void write_o_reg(u8 index) override { } // no O pins + + virtual void op_setr() override { tms1k_base_device::op_setr(); } // no anomaly with MSB of X register + virtual void op_rstr() override { tms1k_base_device::op_rstr(); } // " + + virtual void op_extra() override; + +private: + void op_halt(); + void op_intdis(); + void op_inten(); + void op_selin(); + void op_tasr(); + void op_tmset(); + void op_tsg(); }; class smc1112_cpu_device : public smc1102_cpu_device diff --git a/src/devices/cpu/tms1000/tms1k_base.cpp b/src/devices/cpu/tms1000/tms1k_base.cpp index 8034c2c7b4c..03de6984237 100644 --- a/src/devices/cpu/tms1000/tms1k_base.cpp +++ b/src/devices/cpu/tms1000/tms1k_base.cpp @@ -696,10 +696,12 @@ void tms1k_base_device::execute_one() if (m_fixed & F_LDP) op_ldp(); if (m_fixed & F_COMC) op_comc(); if (m_fixed & F_TPC) op_tpc(); + if (m_fixed & F_TAX) op_tax(); if (m_fixed & F_TAC) op_tac(); if (m_fixed & F_TADM) op_tadm(); if (m_fixed & F_TMA) op_tma(); + if (m_fixed & F_OFF) op_off(); if (m_fixed & F_SEAC) op_seac(); if (m_fixed & F_REAC) op_reac(); @@ -707,6 +709,8 @@ void tms1k_base_device::execute_one() if (m_fixed & F_SBL) op_sbl(); if (m_fixed & F_XDA) op_xda(); + if (m_fixed & F_EXTRA) op_extra(); + // after fixed opcode handling: store status, write ram m_status = status; if (m_ram_out != -1) diff --git a/src/devices/cpu/tms1000/tms1k_base.h b/src/devices/cpu/tms1000/tms1k_base.h index 7674ffe266f..27f6dcfcb78 100644 --- a/src/devices/cpu/tms1000/tms1k_base.h +++ b/src/devices/cpu/tms1000/tms1k_base.h @@ -73,67 +73,69 @@ protected: // microinstructions enum { - M_15TN = (1U << 0), // 15 to -ALU - M_ATN = (1U << 1), // ACC to -ALU - M_AUTA = (1U << 2), // ALU to ACC - M_AUTY = (1U << 3), // ALU to Y - M_C8 = (1U << 4), // CARRY8 to STATUS - M_CIN = (1U << 5), // Carry In to ALU - M_CKM = (1U << 6), // CKB to MEM - M_CKN = (1U << 7), // CKB to -ALU - M_CKP = (1U << 8), // CKB to +ALU - M_MTN = (1U << 9), // MEM to -ALU - M_MTP = (1U << 10), // MEM to +ALU - M_NATN = (1U << 11), // ~ACC to -ALU - M_NE = (1U << 12), // COMP to STATUS - M_STO = (1U << 13), // ACC to MEM - M_STSL = (1U << 14), // STATUS to Status Latch - M_YTP = (1U << 15), // Y to +ALU - - M_CME = (1U << 16), // Conditional Memory Enable - M_DMTP = (1U << 17), // DAM to +ALU - M_NDMTP = (1U << 18), // ~DAM to +ALU - M_SSE = (1U << 19), // Special Status Enable - M_SSS = (1U << 20), // Special Status Sample - - M_SETR = (1U << 21), // -> line #0d, F_SETR (TP0320 custom) - M_RSTR = (1U << 22), // -> line #36, F_RSTR (TMS02x0 custom) - M_UNK1 = (1U << 23) // -> line #37, F_???? (TMS0270 custom) + M_15TN = (1U << 0), // 15 to -ALU + M_ATN = (1U << 1), // ACC to -ALU + M_AUTA = (1U << 2), // ALU to ACC + M_AUTY = (1U << 3), // ALU to Y + M_C8 = (1U << 4), // CARRY8 to STATUS + M_CIN = (1U << 5), // Carry In to ALU + M_CKM = (1U << 6), // CKB to MEM + M_CKN = (1U << 7), // CKB to -ALU + M_CKP = (1U << 8), // CKB to +ALU + M_MTN = (1U << 9), // MEM to -ALU + M_MTP = (1U << 10), // MEM to +ALU + M_NATN = (1U << 11), // ~ACC to -ALU + M_NE = (1U << 12), // COMP to STATUS + M_STO = (1U << 13), // ACC to MEM + M_STSL = (1U << 14), // STATUS to Status Latch + M_YTP = (1U << 15), // Y to +ALU + + M_CME = (1U << 16), // Conditional Memory Enable + M_DMTP = (1U << 17), // DAM to +ALU + M_NDMTP = (1U << 18), // ~DAM to +ALU + M_SSE = (1U << 19), // Special Status Enable + M_SSS = (1U << 20), // Special Status Sample + + M_SETR = (1U << 21), // -> line #0d, F_SETR (TP0320 custom) + M_RSTR = (1U << 22), // -> line #36, F_RSTR (TMS02x0 custom) + M_UNK1 = (1U << 23) // -> line #37, F_???? (TMS0270 custom) }; // standard/fixed instructions - these are documented more in their specific handlers enum { - F_BR = (1ULL << 0), - F_CALL = (1ULL << 1), - F_CLO = (1ULL << 2), - F_COMC = (1ULL << 3), - F_COMX = (1ULL << 4), - F_COMX8 = (1ULL << 5), - F_LDP = (1ULL << 6), - F_LDX = (1ULL << 7), - F_RBIT = (1ULL << 8), - F_RETN = (1ULL << 9), - F_RSTR = (1ULL << 10), - F_SBIT = (1ULL << 11), - F_SETR = (1ULL << 12), - F_TDO = (1ULL << 13), - F_TPC = (1ULL << 14), - - F_TAX = (1ULL << 15), - F_TXA = (1ULL << 16), - F_TRA = (1ULL << 17), - F_TAC = (1ULL << 18), - F_TCA = (1ULL << 19), - F_TADM = (1ULL << 20), - F_TMA = (1ULL << 21), - - F_OFF = (1ULL << 22), - F_REAC = (1ULL << 23), - F_SAL = (1ULL << 24), - F_SBL = (1ULL << 25), - F_SEAC = (1ULL << 26), - F_XDA = (1ULL << 27) + F_BR = (1ULL << 0), + F_CALL = (1ULL << 1), + F_CLO = (1ULL << 2), + F_COMC = (1ULL << 3), + F_COMX = (1ULL << 4), + F_COMX8 = (1ULL << 5), + F_LDP = (1ULL << 6), + F_LDX = (1ULL << 7), + F_RBIT = (1ULL << 8), + F_RETN = (1ULL << 9), + F_RSTR = (1ULL << 10), + F_SBIT = (1ULL << 11), + F_SETR = (1ULL << 12), + F_TDO = (1ULL << 13), + F_TPC = (1ULL << 14), + + F_TAX = (1ULL << 15), + F_TXA = (1ULL << 16), + F_TRA = (1ULL << 17), + F_TAC = (1ULL << 18), + F_TCA = (1ULL << 19), + F_TADM = (1ULL << 20), + F_TMA = (1ULL << 21), + + F_OFF = (1ULL << 22), + F_REAC = (1ULL << 23), + F_SAL = (1ULL << 24), + F_SBL = (1ULL << 25), + F_SEAC = (1ULL << 26), + F_XDA = (1ULL << 27), + + F_EXTRA = (1ULL << 28), // custom opcodes }; void rom_10bit(address_map &map); @@ -152,6 +154,7 @@ protected: virtual void set_cki_bus(); virtual void dynamic_output() { } // not used by default virtual void read_opcode(); + virtual void op_extra() { } virtual void op_br(); virtual void op_call(); diff --git a/src/devices/cpu/tms1000/tms1k_dasm.cpp b/src/devices/cpu/tms1000/tms1k_dasm.cpp index 60afe6b4cdc..9ed183a778c 100644 --- a/src/devices/cpu/tms1000/tms1k_dasm.cpp +++ b/src/devices/cpu/tms1000/tms1k_dasm.cpp @@ -40,13 +40,13 @@ tms1000_base_disassembler::tms1000_base_disassembler(const u8 *lut_mnemonic, boo } } -tms1000_disassembler::tms1000_disassembler() : tms1000_base_disassembler(tms1000_mnemonic, false, 6) -{ } - tms1100_disassembler::tms1100_disassembler(const u8 *lut_mnemonic, bool opcode_9bits, int pc_bits) : tms1000_base_disassembler(lut_mnemonic, opcode_9bits, pc_bits) { } +tms1000_disassembler::tms1000_disassembler() : tms1000_base_disassembler(tms1000_mnemonic, false, 6) +{ } + tms1100_disassembler::tms1100_disassembler() : tms1100_disassembler(tms1100_mnemonic, false, 6) { } diff --git a/src/mame/coleco/wrinkles.cpp b/src/mame/coleco/wrinkles.cpp index dccc6678e48..61577cfef5f 100644 --- a/src/mame/coleco/wrinkles.cpp +++ b/src/mame/coleco/wrinkles.cpp @@ -1,16 +1,28 @@ // license:BSD-3-Clause // copyright-holders:hap -/****************************************************************************** +/******************************************************************************* -Coleco Talking Wrinkles, a plushie dog handpuppet toy +Talking Wrinkles, a plushie dog handpuppet toy -Hardware is a P80C31BH @ 11MHz and a 32KB ROM, RAM is in the MCU. -It also has a cartridge slot, but no known cartridges were released. -The speech technology is by Electronic Speech Systems. +Published by Lakeside (a Coleco subsidiary at that time, after Coleco purchased +Leisure Dynamics in 1985). Programming by Steve Beck. The speech technology is +by Electronic Speech Systems. The plushie itself is licensed from Ganz Bros. + +Hardware notes: + +PCB 1: +- PCB label: REV 4.1 DIGITAL, 201239C, (C) COLECO 1986 +- P80C31BH, 11MHz XTAL +- 32KB EPROM +- cartridge slot (no known cartridges were released) + +PCB 2: +- PCB label: ANALOG REV 6.2, 201238D, (C) COLECO 1986 +- button, motion sensor, microphone Known sensors: - 0x02: bellybutton, literally a button -- 0x04: detect violent motion (Wrinkles will cry) +- 0x04: detect violent motion (drop Wrinkles and he will cry) - 0x10: detect light motion - 0x40: detect open mouth (use as handpuppet to make it 'talk') - 0x80: detect magnet in mouth (the toy came with a 'bone' that has a magnet in it) @@ -19,7 +31,7 @@ TODO: - where is the microphone? or are they the same inputs as the motion sensors? - power-on by pressing button -******************************************************************************/ +*******************************************************************************/ #include "emu.h" @@ -49,9 +61,9 @@ private: -/****************************************************************************** +/******************************************************************************* Address Maps -******************************************************************************/ +*******************************************************************************/ void wrinkles_state::main_map(address_map &map) { @@ -61,15 +73,15 @@ void wrinkles_state::main_map(address_map &map) -/****************************************************************************** +/******************************************************************************* Input Ports -******************************************************************************/ +*******************************************************************************/ static INPUT_PORTS_START( wrinkles ) PORT_START("INPUTS") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_1) PORT_NAME("Tickle Button") - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_CODE(KEYCODE_5) PORT_NAME("Shake Sensor") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_CODE(KEYCODE_5) PORT_NAME("Impact Sensor") PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN ) PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_CODE(KEYCODE_4) PORT_NAME("Motion Sensor") PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNKNOWN ) @@ -79,28 +91,28 @@ INPUT_PORTS_END -/****************************************************************************** +/******************************************************************************* Machine Configs -******************************************************************************/ +*******************************************************************************/ void wrinkles_state::wrinkles(machine_config &config) { - /* basic machine hardware */ + // basic machine hardware I80C31(config, m_maincpu, 11_MHz_XTAL); m_maincpu->set_addrmap(AS_PROGRAM, &wrinkles_state::main_map); m_maincpu->port_in_cb<1>().set_ioport("INPUTS"); m_maincpu->port_out_cb<3>().set("dac", FUNC(dac_8bit_r2r_device::write)); - /* sound hardware */ + // sound hardware SPEAKER(config, "speaker").front_center(); DAC_8BIT_R2R(config, "dac").add_route(ALL_OUTPUTS, "speaker", 0.5); } -/****************************************************************************** +/******************************************************************************* ROM Definitions -******************************************************************************/ +*******************************************************************************/ ROM_START( wrinkles ) ROM_REGION( 0x8000, "maincpu", 0 ) @@ -111,9 +123,9 @@ ROM_END -/****************************************************************************** +/******************************************************************************* Drivers -******************************************************************************/ +*******************************************************************************/ -// YEAR NAME PARENT CMP MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS -CONS( 1986, wrinkles, 0, 0, wrinkles, wrinkles, wrinkles_state, empty_init, "Coleco / Ganz", "Talking Wrinkles", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_CONTROLS | MACHINE_NOT_WORKING ) +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS +CONS( 1986, wrinkles, 0, 0, wrinkles, wrinkles, wrinkles_state, empty_init, "Lakeside / Coleco / Ganz Bros", "Talking Wrinkles", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_CONTROLS | MACHINE_NOT_WORKING ) diff --git a/src/mame/handheld/hh_tms1k.cpp b/src/mame/handheld/hh_tms1k.cpp index 42fe79974b7..09761d7eb4f 100644 --- a/src/mame/handheld/hh_tms1k.cpp +++ b/src/mame/handheld/hh_tms1k.cpp @@ -173,6 +173,7 @@ on Joerg Woerner's datamath.org: http://www.datamath.org/IC_List.htm *M34014 TMS1100 1981, Coleco Bowlatronic M34017 TMS1100 1981, Microvision cartridge: Cosmic Hunter @M34018 TMS1100 1981, Coleco Head to Head: Electronic Boxing + *M34033 TMS1100 1982, Spartus Electronic Talking Clock (1411-61) @M34038 TMS1100 1982, Parker Brothers Lost Treasure M34047 TMS1100 1982, Microvision cartridge: Super Blockbuster @M34078A TMS1100 1983, Milton Bradley Electronic Arcade Mania diff --git a/src/mame/miltonbradley/microvsn.cpp b/src/mame/miltonbradley/microvsn.cpp index dc4ffe08cc3..92f9dd06206 100644 --- a/src/mame/miltonbradley/microvsn.cpp +++ b/src/mame/miltonbradley/microvsn.cpp @@ -160,7 +160,7 @@ u32 microvision_state::tms1100_micro_pla(offs_t offset) // default TMS1100 microinstructions PLA - this should work for all games // verified for: blckbstr, bowling, pinball, vegasslt - // TCY, YNEC, TMCIY, AxAAC + // TCY, YNEC, TCMIY, AxAAC static const u16 micro1[4] = { 0x0108, 0x9080, 0x8068, 0x0136 }; // 0x20, 0x30, 0x00 -- cgit v1.2.3