From a716e677875da0bfbc239b4a95ba9c93bfb6700b Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Wed, 21 Jun 2017 23:33:36 +1000 Subject: [PATCH] taitosj: Made security MCU hookup a device --- scripts/target/mame/arcade.lua | 2 + src/mame/drivers/taitosj.cpp | 29 ++--- src/mame/includes/taitosj.h | 25 +--- src/mame/machine/taitosj.cpp | 163 ++--------------------- src/mame/machine/taitosjsec.cpp | 224 ++++++++++++++++++++++++++++++++ src/mame/machine/taitosjsec.h | 100 ++++++++++++++ 6 files changed, 360 insertions(+), 183 deletions(-) create mode 100644 src/mame/machine/taitosjsec.cpp create mode 100644 src/mame/machine/taitosjsec.h diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index ca8afa5f5a0..6466e3c6650 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -3632,6 +3632,8 @@ files { MAME_DIR .. "src/mame/includes/buggychl.h", MAME_DIR .. "src/mame/machine/taito68705interface.cpp", MAME_DIR .. "src/mame/machine/taito68705interface.h", + MAME_DIR .. "src/mame/machine/taitosjsec.cpp", + MAME_DIR .. "src/mame/machine/taitosjsec.h", MAME_DIR .. "src/mame/video/buggychl.cpp", MAME_DIR .. "src/mame/drivers/capr1.cpp", MAME_DIR .. "src/mame/drivers/caprcyc.cpp", diff --git a/src/mame/drivers/taitosj.cpp b/src/mame/drivers/taitosj.cpp index a826c7a9db8..004a1a4ec4b 100644 --- a/src/mame/drivers/taitosj.cpp +++ b/src/mame/drivers/taitosj.cpp @@ -256,8 +256,7 @@ ADDRESS_MAP_END /* only difference is taitosj_fake_ replaced with taitosj_mcu_ */ static ADDRESS_MAP_START( taitosj_main_mcu_map, AS_PROGRAM, 8, taitosj_state ) - AM_RANGE(0x8800, 0x8800) AM_MIRROR(0x07fe) AM_READWRITE(taitosj_mcu_data_r, taitosj_mcu_data_w) - AM_RANGE(0x8801, 0x8801) AM_MIRROR(0x07fe) AM_READ(taitosj_mcu_status_r) + AM_RANGE(0x8800, 0x8801) AM_MIRROR(0x07fe) AM_DEVREADWRITE("bmcu", taito_sj_security_mcu_device, data_r, data_w) AM_IMPORT_FROM( taitosj_main_nomcu_map ) ADDRESS_MAP_END @@ -289,8 +288,7 @@ static ADDRESS_MAP_START( kikstart_main_map, AS_PROGRAM, 8, taitosj_state ) AM_RANGE(0x0000, 0x5fff) AM_ROM AM_RANGE(0x6000, 0x7fff) AM_ROMBANK("bank1") AM_RANGE(0x8000, 0x87ff) AM_RAM - AM_RANGE(0x8800, 0x8800) AM_READWRITE(taitosj_mcu_data_r, taitosj_mcu_data_w) - AM_RANGE(0x8801, 0x8801) AM_READ(taitosj_mcu_status_r) + AM_RANGE(0x8800, 0x8801) AM_DEVREADWRITE("bmcu", taito_sj_security_mcu_device, data_r, data_w) AM_RANGE(0x8802, 0x8802) AM_NOP AM_RANGE(0x8a00, 0x8a5f) AM_WRITEONLY AM_SHARE("colscrolly") AM_RANGE(0x9000, 0xbfff) AM_WRITE(taitosj_characterram_w) AM_SHARE("characterram") @@ -1815,10 +1813,11 @@ static MACHINE_CONFIG_DERIVED( mcu, nomcu ) MCFG_CPU_MODIFY("maincpu") MCFG_CPU_PROGRAM_MAP(taitosj_main_mcu_map) - MCFG_CPU_ADD("mcu", M68705P3, XTAL_3MHz) /* xtal is 3MHz, divided by 4 internally */ - MCFG_M68705_PORTA_W_CB(WRITE8(taitosj_state, taitosj_68705_portA_w)) - MCFG_M68705_PORTB_W_CB(WRITE8(taitosj_state, taitosj_68705_portB_w)) - MCFG_M68705_PORTC_R_CB(READ8(taitosj_state, taitosj_68705_portC_r)) + MCFG_CPU_ADD("bmcu", TAITO_SJ_SECURITY_MCU, XTAL_3MHz) /* xtal is 3MHz, divided by 4 internally */ + MCFG_TAITO_SJ_SECURITY_MCU_68READ_CB(READ8(taitosj_state, mcu_mem_r)) + MCFG_TAITO_SJ_SECURITY_MCU_68WRITE_CB(WRITE8(taitosj_state, mcu_mem_w)) + MCFG_TAITO_SJ_SECURITY_MCU_68INTRQ_CB(WRITELINE(taitosj_state, mcu_intrq_w)) + MCFG_TAITO_SJ_SECURITY_MCU_BUSRQ_CB(WRITELINE(taitosj_state, mcu_busrq_w)) MCFG_QUANTUM_TIME(attotime::from_hz(6000)) MACHINE_CONFIG_END @@ -2274,7 +2273,7 @@ ROM_START( frontlin ) ROM_LOAD( "fl70.u70", 0x0000, 0x1000, CRC(15f4ed8c) SHA1(ec096234e4e594100180eb99c8c57eb97b9f57e2) ) ROM_LOAD( "fl71.u71", 0x1000, 0x1000, CRC(c3eb38e7) SHA1(427e5deb6a6e22d8c34923209a818f79d50e59d4) ) - ROM_REGION( 0x0800, "mcu", 0 ) /* 2k for the microcontroller */ + ROM_REGION( 0x0800, "bmcu:mcu", 0 ) /* 2k for the microcontroller */ ROM_LOAD( "aa1.13", 0x0000, 0x0800, CRC(7e78bdd3) SHA1(9eeb0e969fd013b9db074a15b0463216453e9364) ) ROM_REGION( 0x8000, "gfx1", 0 ) /* graphic ROMs used at runtime */ @@ -2441,7 +2440,7 @@ ROM_START( elevator ) // 5 board set, using 2732s on both mainboard and square r ROM_REGION( 0x0800, "pal", 0 ) // on GAME BOARD ROM_LOAD( "ww15.pal16l8.ic24.jed.bin", 0x0000, 0x0117, CRC(c3ec20d6) SHA1(4bcdd92ca6b75ba825a7f90b1f35d8dcaeaf8a96) ) // what format is this? jed2bin? - ROM_REGION( 0x0800, "mcu", 0 ) /* 2k for the microcontroller */ + ROM_REGION( 0x0800, "bmcu:mcu", 0 ) /* 2k for the microcontroller */ ROM_LOAD( "ba3__11.mc68705p3.ic4", 0x0000, 0x0800, CRC(9ce75afc) SHA1(4c8f5d926ae2bec8fcb70692125b9e1c863166c6) ) // IC4 on the older Z80+security daughterboard; The MCU itself has a strange custom from-factory silkscreen, rather than "MC68705P3S" it is labeled "15-00011-001 // DA68237" ROM_REGION( 0x8000, "gfx1", 0 ) /* graphic ROMs used at runtime, on Square ROM board */ @@ -2529,7 +2528,7 @@ ROM_START( elevator4 ) // later 4 board set, with rom data on 2764s, split betwe ROM_REGION( 0x0800, "pal", 0 ) // on GAME BOARD ROM_LOAD( "ww15.pal16l8.ic24.jed.bin", 0x0000, 0x0117, CRC(c3ec20d6) SHA1(4bcdd92ca6b75ba825a7f90b1f35d8dcaeaf8a96) ) // what format is this? jed2bin? - ROM_REGION( 0x0800, "mcu", 0 ) /* 2k for the microcontroller */ + ROM_REGION( 0x0800, "bmcu:mcu", 0 ) /* 2k for the microcontroller */ ROM_LOAD( "ba3__11.mc68705p3.ic24", 0x0000, 0x0800, CRC(9ce75afc) SHA1(4c8f5d926ae2bec8fcb70692125b9e1c863166c6) ) // IC24 on the later CPU BOARD; The MCU itself has a strange custom from-factory silkscreen, rather than "MC68705P3S" it is labeled "15-00011-001 // DA68237" ROM_REGION( 0x8000, "gfx1", 0 ) /* graphic ROMs used at runtime, on L-shaped rom board */ @@ -2559,7 +2558,7 @@ ROM_START( tinstar ) ROM_LOAD( "ts.71", 0x1000, 0x1000, CRC(03c91332) SHA1(3903e876ae02e9aea7ee6854bb4c6407dd7108d6) ) ROM_LOAD( "ts.72", 0x2000, 0x1000, CRC(beeed8f3) SHA1(2a18edecabbfd10b3238338cb5554edc8c18d93c) ) - ROM_REGION( 0x0800, "mcu", 0 ) /* 2k for the microcontroller */ + ROM_REGION( 0x0800, "bmcu:mcu", 0 ) /* 2k for the microcontroller */ ROM_LOAD( "a10-12", 0x0000, 0x0800, CRC(889eefc9) SHA1(1a31aa21c02215410eea27ed52fad67f007ee810) ) ROM_REGION( 0x8000, "gfx1", 0 ) /* graphic ROMs used at runtime */ @@ -2603,7 +2602,7 @@ ROM_START( tinstar2 ) ROM_LOAD( "a10-29.bin", 0x0000, 0x2000, CRC(771f1a6a) SHA1(c5d1841840ff35e2c20a285b1b7f35150356f50f) ) ROM_LOAD( "a10-10.bin", 0x2000, 0x1000, CRC(beeed8f3) SHA1(2a18edecabbfd10b3238338cb5554edc8c18d93c) ) - ROM_REGION( 0x0800, "mcu", 0 ) /* 2k for the microcontroller */ + ROM_REGION( 0x0800, "bmcu:mcu", 0 ) /* 2k for the microcontroller */ ROM_LOAD( "a10-12", 0x0000, 0x0800, CRC(889eefc9) SHA1(1a31aa21c02215410eea27ed52fad67f007ee810) ) ROM_REGION( 0x8000, "gfx1", 0 ) /* graphic ROMs used at runtime */ @@ -2684,7 +2683,7 @@ ROM_START( sfposeid ) ROM_LOAD( "a14-10.70", 0x0000, 0x1000, CRC(f1365f35) SHA1(34b3ea03eb9fbf5454858fa6e07ec49a7b3be8b4) ) ROM_LOAD( "a14-11.71", 0x1000, 0x1000, CRC(74a12fe2) SHA1(8678ea68bd283b7a63915717cdbbedef0b699198) ) - ROM_REGION( 0x0800, "mcu", 0 ) /* 2k for the microcontroller */ + ROM_REGION( 0x0800, "bmcu:mcu", 0 ) /* 2k for the microcontroller */ ROM_LOAD( "a14-12", 0x0000, 0x0800, CRC(091beed8) SHA1(263806aef01bbc258f5cfa92de8a9e355491fb3a) ) ROM_REGION( 0x8000, "gfx1", 0 ) /* graphic ROMs used at runtime */ @@ -2740,7 +2739,7 @@ ROM_START( kikstart ) ROM_LOAD( "a20-11", 0x1000, 0x1000, CRC(8db12dd9) SHA1(3b291d478b3f3f1bf93d95a78506d99a71f36d05) ) ROM_LOAD( "a20-12", 0x2000, 0x1000, CRC(e7eeb933) SHA1(26f3904f6d4dc814318221f1c9cd5dcc671fe05a) ) - ROM_REGION( 0x0800, "mcu", 0 ) /* 2k for the microcontroller */ + ROM_REGION( 0x0800, "bmcu:mcu", 0 ) /* 2k for the microcontroller */ ROM_LOAD( "a20-13.ic91", 0x0000, 0x0800, CRC(3fb6c4fb) SHA1(04b9458f21a793444cd587055e2e3ccfa3f835a2) ) ROM_REGION( 0x8000, "gfx1", 0 ) /* graphic ROMs used at runtime */ diff --git a/src/mame/includes/taitosj.h b/src/mame/includes/taitosj.h index 57a85fd2163..2cda1bba793 100644 --- a/src/mame/includes/taitosj.h +++ b/src/mame/includes/taitosj.h @@ -1,7 +1,7 @@ // license:BSD-3-Clause // copyright-holders:Nicola Salmoria -#include "cpu/m6805/m68705.h" +#include "machine/taitosjsec.h" #include "machine/gen_latch.h" @@ -33,7 +33,7 @@ public: m_kikstart_scrollram(*this, "kikstart_scroll"), m_maincpu(*this, "maincpu"), m_audiocpu(*this, "audiocpu"), - m_mcu(*this, "mcu"), + m_mcu(*this, "bmcu"), m_dac(*this, "dac"), m_dacvol(*this, "dacvol"), m_ay1(*this, "ay1"), @@ -63,12 +63,6 @@ public: required_shared_ptr m_video_priority; required_shared_ptr m_collision_reg; optional_shared_ptr m_kikstart_scrollram; - uint8_t m_fromz80; - uint8_t m_toz80; - uint8_t m_zaccept; - uint8_t m_zready; - uint8_t m_busreq; - uint8_t m_portA_out; uint8_t m_spacecr_prot_value; uint8_t m_protection_value; uint32_t m_address; @@ -91,12 +85,10 @@ public: DECLARE_READ8_MEMBER(taitosj_fake_data_r); DECLARE_WRITE8_MEMBER(taitosj_fake_data_w); DECLARE_READ8_MEMBER(taitosj_fake_status_r); - DECLARE_READ8_MEMBER(taitosj_mcu_data_r); - DECLARE_WRITE8_MEMBER(taitosj_mcu_data_w); - DECLARE_READ8_MEMBER(taitosj_mcu_status_r); - DECLARE_WRITE8_MEMBER(taitosj_68705_portA_w); - DECLARE_WRITE8_MEMBER(taitosj_68705_portB_w); - DECLARE_READ8_MEMBER(taitosj_68705_portC_r); + DECLARE_READ8_MEMBER(mcu_mem_r); + DECLARE_WRITE8_MEMBER(mcu_mem_w); + DECLARE_WRITE_LINE_MEMBER(mcu_intrq_w); + DECLARE_WRITE_LINE_MEMBER(mcu_busrq_w); DECLARE_READ8_MEMBER(spacecr_prot_r); DECLARE_WRITE8_MEMBER(alpine_protection_w); DECLARE_WRITE8_MEMBER(alpinea_bankswitch_w); @@ -120,9 +112,6 @@ public: virtual void video_start() override; uint32_t screen_update_taitosj(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update_kikstart(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - TIMER_CALLBACK_MEMBER(taitosj_mcu_real_data_w); - TIMER_CALLBACK_MEMBER(taitosj_mcu_data_real_r); - TIMER_CALLBACK_MEMBER(taitosj_mcu_status_real_w); void init_common(); void reset_common(); void set_pens(); @@ -144,7 +133,7 @@ public: int video_update_common(bitmap_ind16 &bitmap, const rectangle &cliprect, copy_layer_func_t copy_layer_func); required_device m_maincpu; required_device m_audiocpu; - optional_device m_mcu; + optional_device m_mcu; required_device m_dac; required_device m_dacvol; required_device m_ay1; diff --git a/src/mame/machine/taitosj.cpp b/src/mame/machine/taitosj.cpp index b8c23642891..d953654bafc 100644 --- a/src/mame/machine/taitosj.cpp +++ b/src/mame/machine/taitosj.cpp @@ -23,14 +23,6 @@ void taitosj_state::machine_start() membank("bank1")->configure_entry(0, memregion("maincpu")->base() + 0x6000); membank("bank1")->configure_entry(1, memregion("maincpu")->base() + 0x10000); - save_item(NAME(m_fromz80)); - save_item(NAME(m_toz80)); - save_item(NAME(m_zaccept)); - save_item(NAME(m_zready)); - save_item(NAME(m_busreq)); - - save_item(NAME(m_portA_out)); - save_item(NAME(m_address)); save_item(NAME(m_spacecr_prot_value)); save_item(NAME(m_protection_value)); } @@ -42,12 +34,8 @@ void taitosj_state::machine_reset() /* never write to the bank selector register) */ taitosj_bankswitch_w(space, 0, 0); - - m_zaccept = 1; - m_zready = 0; - m_busreq = 0; if (m_mcu) - m_mcu->set_input_line(M68705_IRQ_LINE, CLEAR_LINE); + m_mcu->reset_w(PULSE_LINE); m_spacecr_prot_value = 0; } @@ -107,153 +95,28 @@ READ8_MEMBER(taitosj_state::taitosj_fake_status_r) } -/* timer callback : */ -READ8_MEMBER(taitosj_state::taitosj_mcu_data_r) +READ8_MEMBER(taitosj_state::mcu_mem_r) { - LOG(("%04x: protection read %02x\n",space.device().safe_pc(),m_toz80)); - m_zaccept = 1; - return m_toz80; + return m_maincpu->space(AS_PROGRAM).read_byte(offset); } -/* timer callback : */ -TIMER_CALLBACK_MEMBER(taitosj_state::taitosj_mcu_real_data_w) +WRITE8_MEMBER(taitosj_state::mcu_mem_w) { - m_zready = 1; - m_mcu->set_input_line(M68705_IRQ_LINE, ASSERT_LINE); - m_fromz80 = param; + m_maincpu->space(AS_PROGRAM).write_byte(offset, data); } -WRITE8_MEMBER(taitosj_state::taitosj_mcu_data_w) +WRITE_LINE_MEMBER(taitosj_state::mcu_intrq_w) { - LOG(("%04x: protection write %02x\n",space.device().safe_pc(),data)); - machine().scheduler().synchronize(timer_expired_delegate(FUNC(taitosj_state::taitosj_mcu_real_data_w),this), data); - /* temporarily boost the interleave to sync things up */ - machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(10)); + // FIXME: there's a logic network here that makes this edge sensitive or something and mixes it with other interrupt sources + if (CLEAR_LINE != state) + LOG(("68705 68INTRQ **NOT SUPPORTED**!\n")); } -READ8_MEMBER(taitosj_state::taitosj_mcu_status_r) +WRITE_LINE_MEMBER(taitosj_state::mcu_busrq_w) { - /* temporarily boost the interleave to sync things up */ - machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(10)); - - /* bit 0 = the 68705 has read data from the Z80 */ - /* bit 1 = the 68705 has written data for the Z80 */ - return ~((m_zready << 0) | (m_zaccept << 1)); -} - -WRITE8_MEMBER(taitosj_state::taitosj_68705_portA_w) -{ - LOG(("%04x: 68705 port A write %02x\n",space.device().safe_pc(),data)); - m_portA_out = data; -} - - - -/* - * Port B connections: - * - * all bits are logical 1 when read (+5V pullup) - * - * 0 W !68INTRQ - * 1 W !68LRD (enables latch which holds command from the Z80) - * 2 W !68LWR (loads the latch which holds data for the Z80, and sets a - * status bit so the Z80 knows there's data waiting) - * 3 W to Z80 !BUSRQ (aka !WAIT) pin - * 4 W !68WRITE (triggers write to main Z80 memory area and increases low - * 8 bits of the latched address) - * 5 W !68READ (triggers read from main Z80 memory area and increases low - * 8 bits of the latched address) - * 6 W !LAL (loads the latch which holds the low 8 bits of the address of - * the main Z80 memory location to access) - * 7 W !UAL (loads the latch which holds the high 8 bits of the address of - * the main Z80 memory location to access) - */ - -/* timer callback : 68705 is going to read data from the Z80 */ -TIMER_CALLBACK_MEMBER(taitosj_state::taitosj_mcu_data_real_r) -{ - m_zready = 0; -} - -/* timer callback : 68705 is writing data for the Z80 */ -TIMER_CALLBACK_MEMBER(taitosj_state::taitosj_mcu_status_real_w) -{ - m_toz80 = param; - m_zaccept = 0; -} - -WRITE8_MEMBER(taitosj_state::taitosj_68705_portB_w) -{ - LOG(("%04x: 68705 port B write %02x\n", space.device().safe_pc(), data)); - - if (~data & 0x01) - { - LOG(("%04x: 68705 68INTRQ **NOT SUPPORTED**!\n", space.device().safe_pc())); - } - if (~data & 0x02) - { - /* 68705 is going to read data from the Z80 */ - machine().scheduler().synchronize(timer_expired_delegate(FUNC(taitosj_state::taitosj_mcu_data_real_r), this)); - m_mcu->pa_w(space, 0, m_fromz80); - m_mcu->set_input_line(M68705_IRQ_LINE, CLEAR_LINE); - LOG(("%04x: 68705 <- Z80 %02x\n", space.device().safe_pc(), m_fromz80)); - } - if (~data & 0x08) - m_busreq = 1; - else - m_busreq = 0; - if (~data & 0x04) - { - LOG(("%04x: 68705 -> Z80 %02x\n", space.device().safe_pc(), m_portA_out)); - - /* 68705 is writing data for the Z80 */ - machine().scheduler().synchronize(timer_expired_delegate(FUNC(taitosj_state::taitosj_mcu_status_real_w),this), m_portA_out); - } - if (~data & 0x10) - { - address_space &cpu0space = m_maincpu->space(AS_PROGRAM); - LOG(("%04x: 68705 write %02x to address %04x\n",space.device().safe_pc(), m_portA_out, m_address)); - - cpu0space.write_byte(m_address, m_portA_out); - - /* increase low 8 bits of latched address for burst writes */ - m_address = (m_address & 0xff00) | ((m_address + 1) & 0xff); - } - if (~data & 0x20) - { - u8 const value = m_maincpu->space(AS_PROGRAM).read_byte(m_address); - m_mcu->pa_w(space, 0, value); - LOG(("%04x: 68705 read %02x from address %04x\n", space.device().safe_pc(), value, m_address)); - } - if (~data & 0x40) - { - LOG(("%04x: 68705 address low %02x\n", space.device().safe_pc(), m_portA_out)); - m_address = (m_address & 0xff00) | m_portA_out; - } - if (~data & 0x80) - { - LOG(("%04x: 68705 address high %02x\n", space.device().safe_pc(), m_portA_out)); - m_address = (m_address & 0x00ff) | (m_portA_out << 8); - } -} - -/* - * Port C connections: - * - * 0 R ZREADY (1 when the Z80 has written a command in the latch) - * 1 R ZACCEPT (1 when the Z80 has read data from the latch) - * 2 R from Z80 !BUSAK pin - * 3 R 68INTAK (goes 0 when the interrupt request done with 68INTRQ - * passes through) - */ - -READ8_MEMBER(taitosj_state::taitosj_68705_portC_r) -{ - int res; - - res = (m_zready << 0) | (m_zaccept << 1) | ((m_busreq^1) << 2); - LOG(("%04x: 68705 port C read %02x\n",space.device().safe_pc(),res)); - return res; + // this actually goes to the Z80 BUSRQ (aka WAIT) pin, and the MCU waits for the bus to become available + // we're pretending this happens immediately to make life easier + m_mcu->busak_w(state); } diff --git a/src/mame/machine/taitosjsec.cpp b/src/mame/machine/taitosjsec.cpp new file mode 100644 index 00000000000..bb077be0d20 --- /dev/null +++ b/src/mame/machine/taitosjsec.cpp @@ -0,0 +1,224 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +#include "emu.h" +#include "taitosjsec.h" + +DEFINE_DEVICE_TYPE(TAITO_SJ_SECURITY_MCU, taito_sj_security_mcu_device, "taitosjsecmcu", "Taito SJ Security MCU Interface") + + +taito_sj_security_mcu_device::taito_sj_security_mcu_device( + machine_config const &mconfig, + char const *tag, + device_t *owner, + u32 clock) + : device_t(mconfig,TAITO_SJ_SECURITY_MCU, tag, owner, clock) + , m_mcu(*this, "mcu") + , m_68read_cb(*this) + , m_68write_cb(*this) + , m_68intrq_cb(*this) + , m_busrq_cb(*this) + , m_addr(0U) + , m_mcu_data(0U) + , m_host_data(0U) + , m_read_data(0U) + , m_zaccept(false) + , m_zready(false) + , m_pb_val(0U) + , m_busak(false) + , m_reset(false) +{ +} + +READ8_MEMBER(taito_sj_security_mcu_device::data_r) +{ + if (BIT(offset, 0)) + { + // ZLSTATUS + machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(10)); + return + (u8(space.unmap()) & 0xfc) | + u8(m_zaccept ? 0x00 : 0x02) | + u8(m_zready ? 0x00 : 0x01); + } + else + { + // ZLREAD + if (!machine().side_effect_disabled()) + m_zaccept = true; + return m_mcu_data; + } +} + +WRITE8_MEMBER(taito_sj_security_mcu_device::data_w) +{ + if (BIT(offset, 0)) + { + // ZINTRQ + // FIXME: this can be jumpered to /INT on the MCU + } + else + { + // ZLWRITE + device_scheduler &sched(machine().scheduler()); + sched.synchronize(timer_expired_delegate(FUNC(taito_sj_security_mcu_device::do_host_write), this), data); + sched.boost_interleave(attotime::zero, attotime::from_usec(10)); + } +} + +WRITE_LINE_MEMBER(taito_sj_security_mcu_device::busak_w) +{ + m_busak = (ASSERT_LINE == state); +} + +WRITE_LINE_MEMBER(taito_sj_security_mcu_device::reset_w) +{ + m_reset = (ASSERT_LINE == state); + if (CLEAR_LINE != state) + { + m_zaccept = true; + m_zready = false; + m_mcu->set_input_line(M68705_IRQ_LINE, CLEAR_LINE); + } + m_mcu->set_input_line(INPUT_LINE_RESET, state); +} + +void taito_sj_security_mcu_device::device_start() +{ + m_68read_cb.resolve_safe(0xff); + m_68write_cb.resolve_safe(); + m_68intrq_cb.resolve_safe(); + m_busrq_cb.resolve_safe(); + + save_item(NAME(m_addr)); + save_item(NAME(m_mcu_data)); + save_item(NAME(m_host_data)); + save_item(NAME(m_read_data)); + save_item(NAME(m_zaccept)); + save_item(NAME(m_zready)); + save_item(NAME(m_pb_val)); + save_item(NAME(m_busak)); + save_item(NAME(m_reset)); + + m_addr = 0xffffU; + m_mcu_data = 0xffU; + m_host_data = 0xffU; + m_read_data = 0xffU; + m_pb_val = 0xffU; + m_busak = false; + m_reset = false; +} + +void taito_sj_security_mcu_device::device_reset() +{ + m_zaccept = true; + m_zready = false; + m_mcu->set_input_line(M68705_IRQ_LINE, CLEAR_LINE); +} + +MACHINE_CONFIG_MEMBER(taito_sj_security_mcu_device::device_add_mconfig) + MCFG_CPU_ADD("mcu", M68705P5, DERIVED_CLOCK(1, 1)) + MCFG_M68705_PORTA_R_CB(READ8(taito_sj_security_mcu_device, mcu_pa_r)) + MCFG_M68705_PORTC_R_CB(READ8(taito_sj_security_mcu_device, mcu_pc_r)) + MCFG_M68705_PORTA_W_CB(WRITE8(taito_sj_security_mcu_device, mcu_pa_w)) + MCFG_M68705_PORTB_W_CB(WRITE8(taito_sj_security_mcu_device, mcu_pb_w)) +MACHINE_CONFIG_END + +READ8_MEMBER(taito_sj_security_mcu_device::mcu_pa_r) +{ + return get_bus_val(); +} + +READ8_MEMBER(taito_sj_security_mcu_device::mcu_pc_r) +{ + // FIXME 68INTAK is on PC3 but we're ignoring it + return + (m_zready ? 0x01U : 0x00U) | + (m_zaccept ? 0x02U : 0x00U) | + (m_busak ? 0x00U : 0x04U); +} + +WRITE8_MEMBER(taito_sj_security_mcu_device::mcu_pa_w) +{ + m_pa_val = data; + if (BIT(~m_pb_val, 6)) + m_addr = (m_addr & 0xff00U) | u16(get_bus_val()); +} + +WRITE8_MEMBER(taito_sj_security_mcu_device::mcu_pb_w) +{ + bool inc_addr(false); + u8 const diff(m_pb_val ^ data); + + // 68INTRQ + if (BIT(diff, 0)) + m_68intrq_cb(BIT(data, 0) ? CLEAR_LINE : ASSERT_LINE); + + // 68LRD + u8 const bus_val(get_bus_val()); + if (BIT(diff & data, 1)) + { + machine().scheduler().synchronize(timer_expired_delegate(FUNC(taito_sj_security_mcu_device::do_mcu_read), this)); + m_mcu->set_input_line(M68705_IRQ_LINE, CLEAR_LINE); + } + + // 68LWR + if (BIT(diff & data, 2)) + machine().scheduler().synchronize(timer_expired_delegate(FUNC(taito_sj_security_mcu_device::do_mcu_write), this), bus_val); + + // BUSRQ + if (BIT(diff, 3)) + m_busrq_cb(BIT(data, 3) ? CLEAR_LINE : ASSERT_LINE); + + // 68WRITE + if (BIT(diff, 4)) + { + if (BIT(~data, 4)) + m_68write_cb(space, m_addr, bus_val); + else if (BIT(data, 5)) + inc_addr = true; + } + + // 68READ + if (BIT(diff, 5)) + { + if (BIT(~data, 5)) + m_read_data = m_68read_cb(space, m_addr); + else if (BIT(data, 4)) + inc_addr = true; + } + + // LAL + if (BIT(~data, 6)) + m_addr = (m_addr & 0xff00U) | u16(bus_val); + else if (inc_addr) + m_addr = (m_addr & 0xff00U) | ((m_addr + 1) & 0x00ffU); + + // UAL + if (BIT(~data, 7)) + m_addr = (m_addr & 0x00ffU) | (u16(bus_val) << 8); + + m_pb_val = data; +} + +TIMER_CALLBACK_MEMBER(taito_sj_security_mcu_device::do_mcu_read) +{ + m_zready = false; +} + +TIMER_CALLBACK_MEMBER(taito_sj_security_mcu_device::do_mcu_write) +{ + m_mcu_data = u8(param); + if (!m_reset) + m_zaccept = false; +} + +TIMER_CALLBACK_MEMBER(taito_sj_security_mcu_device::do_host_write) +{ + m_host_data = u8(param); + if (!m_reset) + { + m_zready = true; + // FIXME: this can be jumpered off if ZINTRQ is being used + m_mcu->set_input_line(M68705_IRQ_LINE, ASSERT_LINE); + } +} diff --git a/src/mame/machine/taitosjsec.h b/src/mame/machine/taitosjsec.h new file mode 100644 index 00000000000..2835459bf7f --- /dev/null +++ b/src/mame/machine/taitosjsec.h @@ -0,0 +1,100 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +#ifndef MAME_MACHINE_TAITSJSEC_H +#define MAME_MACHINE_TAITSJSEC_H + +#pragma once + +#include "cpu/m6805/m68705.h" + +// TODO: there should be a device representing the whole security board with both the Z80 and 68705 + + +DECLARE_DEVICE_TYPE(TAITO_SJ_SECURITY_MCU, taito_sj_security_mcu_device) + + +#define MCFG_TAITO_SJ_SECURITY_MCU_68READ_CB(cb) \ + devcb = &taito_sj_security_mcu_device::set_68read_cb(*device, DEVCB_##cb); +#define MCFG_TAITO_SJ_SECURITY_MCU_68WRITE_CB(cb) \ + devcb = &taito_sj_security_mcu_device::set_68write_cb(*device, DEVCB_##cb); +#define MCFG_TAITO_SJ_SECURITY_MCU_68INTRQ_CB(cb) \ + devcb = &taito_sj_security_mcu_device::set_68intrq_cb(*device, DEVCB_##cb); +#define MCFG_TAITO_SJ_SECURITY_MCU_BUSRQ_CB(cb) \ + devcb = &taito_sj_security_mcu_device::set_busrq_cb(*device, DEVCB_##cb); + +class taito_sj_security_mcu_device : public device_t +{ +public: + template static devcb_base &set_68read_cb(device_t &device, Obj &&cb) + { return downcast(device).m_68read_cb.set_callback(std::forward(cb)); } + template static devcb_base &set_68write_cb(device_t &device, Obj &&cb) + { return downcast(device).m_68write_cb.set_callback(std::forward(cb)); } + template static devcb_base &set_68intrq_cb(device_t &device, Obj &&cb) + { return downcast(device).m_68intrq_cb.set_callback(std::forward(cb)); } + template static devcb_base &set_busrq_cb(device_t &device, Obj &&cb) + { return downcast(device).m_busrq_cb.set_callback(std::forward(cb)); } + + taito_sj_security_mcu_device( + machine_config const &mconfig, + char const *tag, + device_t *owner, + u32 clock); + + // uses two consecutive addresses + DECLARE_READ8_MEMBER(data_r); + DECLARE_WRITE8_MEMBER(data_w); + + DECLARE_WRITE_LINE_MEMBER(busak_w); + DECLARE_WRITE_LINE_MEMBER(reset_w); + +protected: + void device_start() override; + void device_reset() override; + void device_add_mconfig(machine_config &config) override; + + DECLARE_READ8_MEMBER(mcu_pa_r); + DECLARE_READ8_MEMBER(mcu_pc_r); + DECLARE_WRITE8_MEMBER(mcu_pa_w); + DECLARE_WRITE8_MEMBER(mcu_pb_w); + +private: + u8 const get_bus_val() const + { return (BIT(~m_pb_val, 1) ? m_host_data : 0xffU) & m_pa_val & ((m_busak && BIT(~m_pb_val, 5)) ? m_read_data : 0xffU); } + + TIMER_CALLBACK_MEMBER(do_mcu_read); + TIMER_CALLBACK_MEMBER(do_mcu_write); + TIMER_CALLBACK_MEMBER(do_host_write); + + required_device m_mcu; + + devcb_read8 m_68read_cb; + devcb_write8 m_68write_cb; + devcb_write_line m_68intrq_cb; + devcb_write_line m_busrq_cb; + + // IC6/IC10 latch/count the low byte, IC14 buffers low byte, IC3 latches high byte + u16 m_addr; + + // latched by IC9 + u8 m_mcu_data; + + // latched by IC13 + u8 m_host_data; + + // buffered by IC16 + u8 m_read_data; + + // IC7 pin 6, indicates CPU has accepted data from MCU + bool m_zaccept; + + // IC7 pin 9, indicates CPU has sent data to MCU + bool m_zready; + + // previous MCU port outputs for detecting edges + u8 m_pa_val, m_pb_val; + + // input state + bool m_busak, m_reset; +}; + +#endif // MAME_MACHINE_TATISJSEC_H