taitosj: Made security MCU hookup a device

This commit is contained in:
Vas Crabb 2017-06-21 23:33:36 +10:00
parent 9ef9bee33b
commit a716e67787
6 changed files with 360 additions and 183 deletions

View File

@ -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",

View File

@ -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 */

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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