summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2017-06-21 23:33:36 +1000
committer Vas Crabb <vas@vastheman.com>2017-06-21 23:33:36 +1000
commita716e677875da0bfbc239b4a95ba9c93bfb6700b (patch)
treee3315588e1cfaa79fd1b6de4b50071188e518518
parent9ef9bee33b4c50668d0646ec4ad78fdf1de5c041 (diff)
taitosj: Made security MCU hookup a device
-rw-r--r--scripts/target/mame/arcade.lua2
-rw-r--r--src/mame/drivers/taitosj.cpp29
-rw-r--r--src/mame/includes/taitosj.h25
-rw-r--r--src/mame/machine/taitosj.cpp163
-rw-r--r--src/mame/machine/taitosjsec.cpp224
-rw-r--r--src/mame/machine/taitosjsec.h100
6 files changed, 360 insertions, 183 deletions
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<uint8_t> m_video_priority;
required_shared_ptr<uint8_t> m_collision_reg;
optional_shared_ptr<uint8_t> 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<cpu_device> m_maincpu;
required_device<cpu_device> m_audiocpu;
- optional_device<m68705p_device> m_mcu;
+ optional_device<taito_sj_security_mcu_device> m_mcu;
required_device<dac_8bit_r2r_device> m_dac;
required_device<discrete_device> m_dacvol;
required_device<ay8910_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)
-{
- LOG(("%04x: protection read %02x\n",space.device().safe_pc(),m_toz80));
- m_zaccept = 1;
- return m_toz80;
-}
-
-/* timer callback : */
-TIMER_CALLBACK_MEMBER(taitosj_state::taitosj_mcu_real_data_w)
-{
- m_zready = 1;
- m_mcu->set_input_line(M68705_IRQ_LINE, ASSERT_LINE);
- m_fromz80 = param;
-}
-
-WRITE8_MEMBER(taitosj_state::taitosj_mcu_data_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));
-}
-
-READ8_MEMBER(taitosj_state::taitosj_mcu_status_r)
-{
- /* 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)
+READ8_MEMBER(taitosj_state::mcu_mem_r)
{
- LOG(("%04x: 68705 port A write %02x\n",space.device().safe_pc(),data));
- m_portA_out = data;
+ return m_maincpu->space(AS_PROGRAM).read_byte(offset);
}
-
-
-/*
- * 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)
+WRITE8_MEMBER(taitosj_state::mcu_mem_w)
{
- m_zready = 0;
+ m_maincpu->space(AS_PROGRAM).write_byte(offset, data);
}
-/* timer callback : 68705 is writing data for the Z80 */
-TIMER_CALLBACK_MEMBER(taitosj_state::taitosj_mcu_status_real_w)
+WRITE_LINE_MEMBER(taitosj_state::mcu_intrq_w)
{
- m_toz80 = param;
- m_zaccept = 0;
+ // 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"));
}
-WRITE8_MEMBER(taitosj_state::taitosj_68705_portB_w)
+WRITE_LINE_MEMBER(taitosj_state::mcu_busrq_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 <typename Obj> static devcb_base &set_68read_cb(device_t &device, Obj &&cb)
+ { return downcast<taito_sj_security_mcu_device &>(device).m_68read_cb.set_callback(std::forward<Obj>(cb)); }
+ template <typename Obj> static devcb_base &set_68write_cb(device_t &device, Obj &&cb)
+ { return downcast<taito_sj_security_mcu_device &>(device).m_68write_cb.set_callback(std::forward<Obj>(cb)); }
+ template <typename Obj> static devcb_base &set_68intrq_cb(device_t &device, Obj &&cb)
+ { return downcast<taito_sj_security_mcu_device &>(device).m_68intrq_cb.set_callback(std::forward<Obj>(cb)); }
+ template <typename Obj> static devcb_base &set_busrq_cb(device_t &device, Obj &&cb)
+ { return downcast<taito_sj_security_mcu_device &>(device).m_busrq_cb.set_callback(std::forward<Obj>(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<m68705p_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