taito/kikikai.cpp: hook up kikikai MCU (#11900)

This commit is contained in:
mamehaze 2024-01-05 12:52:50 +00:00 committed by GitHub
parent 2251902b44
commit 6cdb50dff3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 418 deletions

View File

@ -30,17 +30,6 @@ Notes:
turn wait forever. It's difficult to meet the required level of synchronization.
This is kludged by filtering the 2203's busy signal.
- KiKi KaiKai uses a custom MC6801U4 MCU which isn't dumped. The bootleg Knight Boy
replaces it with a 68705. The bootleg is NOT 100% equivalent to the original
(a situation similar to Bubble Bobble): collision detection is imperfect, the
player can't be killed by some enemies.
I think the bootleggers put the custom mcu in a test rig, examined its bus
activity and replicated the behaviour inaccurately because they couldn't
figure it all out. Indeed, the 68705 code reads all the memory locations
related to the missing collision detection, but does nothing with them.
- KiKi KaiKai coinage mode Type 2 doesn't work.
- Kick and Run is a rom swap for Kiki KaiKai as the pal chips are all A85-0x
A85 is the Taito rom code for Kiki KaiKai. Even the MCU is socketed!
@ -232,14 +221,14 @@ void kikikai_state::kicknrun_sub_cpu_map(address_map &map)
static INPUT_PORTS_START( kicknrun )
PORT_START("IN0")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("IN1")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1)
@ -354,129 +343,6 @@ static INPUT_PORTS_START( kicknrun )
PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNKNOWN )
INPUT_PORTS_END
static INPUT_PORTS_START( mexico86 )
PORT_START("IN0")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("IN1")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE ) /* service 2 */
PORT_START("IN2")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("DSW0")
/* When Bit 1 is On, the machine waits a signal from another one */
/* Seems like if you can join two cabinets, one as master */
/* and the other as slave, probably to play four players. */
PORT_DIPNAME( 0x01, 0x01, "Master/Slave Mode" ) PORT_DIPLOCATION("SWA:1")
PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWA:2") // Screen ?
PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_SERVICE( 0x04, IP_ACTIVE_LOW ) PORT_DIPLOCATION("SW1:3")
PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWA:4")// this should be Demo Sounds, but doesn't work?
PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x30, 0x30, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SWA:5,6")
PORT_DIPSETTING( 0x10, DEF_STR( 2C_1C ) )
PORT_DIPSETTING( 0x30, DEF_STR( 1C_1C ) )
PORT_DIPSETTING( 0x00, DEF_STR( 2C_3C ) )
PORT_DIPSETTING( 0x20, DEF_STR( 1C_2C ) )
PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SWA:7,8")
PORT_DIPSETTING( 0x40, DEF_STR( 2C_1C ) )
PORT_DIPSETTING( 0xc0, DEF_STR( 1C_1C ) )
PORT_DIPSETTING( 0x00, DEF_STR( 2C_3C ) )
PORT_DIPSETTING( 0x80, DEF_STR( 1C_2C ) )
PORT_START("DSW1")
PORT_DIPNAME( 0x03, 0x03, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SWB:1,2")
PORT_DIPSETTING( 0x03, DEF_STR( Easy ) )
PORT_DIPSETTING( 0x02, DEF_STR( Normal ) )
PORT_DIPSETTING( 0x01, DEF_STR( Hard ) )
PORT_DIPSETTING( 0x00, DEF_STR( Hardest ) )
PORT_DIPNAME( 0x0c, 0x08, "Playing Time" ) PORT_DIPLOCATION("SWB:3,4")
PORT_DIPSETTING( 0x00, "40 Seconds" )
PORT_DIPSETTING( 0x0c, "One Minute" )
PORT_DIPSETTING( 0x08, "One Minute and 20 Sec." )
PORT_DIPSETTING( 0x04, "One Minute and 40 Sec." )
PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWB:5")
PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
/* The following dip seems to be related with the first one */
PORT_DIPNAME( 0x20, 0x20, "Board ID" ) PORT_DIPLOCATION("SWB:6")
PORT_DIPSETTING( 0x20, "Master" )
PORT_DIPSETTING( 0x00, "Slave" )
PORT_DIPNAME( 0x40, 0x40, "Number of Matches" ) PORT_DIPLOCATION("SWB:7")
PORT_DIPSETTING( 0x00, "2" )
PORT_DIPSETTING( 0x40, "6" )
PORT_DIPNAME( 0x80, 0x80, "Single board 4 Players Mode" ) PORT_DIPLOCATION("SWB:8")
PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_START("IN3")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SERVICE1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_TILT )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("IN4")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(3)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(3)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(3)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(3)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(3)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) //p3 service
PORT_START("IN5")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(4)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(4)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(4)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(4)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(4)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(4)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) //p4 service
PORT_START("IN6")
PORT_BIT( 0x01, IP_ACTIVE_HIGH,IPT_COIN3 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START3 )
PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("IN7")
PORT_BIT( 0x01, IP_ACTIVE_HIGH,IPT_COIN4 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START4 )
PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNKNOWN )
INPUT_PORTS_END
static INPUT_PORTS_START( kikikai )
PORT_START("IN0")
@ -650,15 +516,6 @@ void mexico86_state::machine_start()
m_port_b_out = 0xff;
}
void kikikai_simulation_state::machine_start()
{
kikikai_state::machine_start();
save_item(NAME(m_kikikai_simulated_mcu_running));
save_item(NAME(m_kikikai_simulated_mcu_initialised));
save_item(NAME(m_coin_last));
save_item(NAME(m_coin_fract));
}
void kikikai_state::machine_reset()
@ -678,16 +535,6 @@ void mexico86_state::machine_reset()
m_latch = 0;
}
void kikikai_simulation_state::machine_reset()
{
kikikai_state::machine_reset();
m_kikikai_simulated_mcu_running = 0;
m_kikikai_simulated_mcu_initialised = 0;
m_coin_last[0] = false;
m_coin_last[1] = false;
m_coin_fract = 0;
}
void kikikai_state::base(machine_config &config)
{
@ -727,16 +574,14 @@ void kikikai_state::base(machine_config &config)
m_ymsnd->add_route(3, "mono", 1.00);
}
void kikikai_state::kicknrun(machine_config &config)
void kikikai_state::add_mcu(machine_config &config)
{
base(config);
// Not too sure IRQs are triggered by MCU..
m_maincpu->set_vblank_int("screen", FUNC(kikikai_state::kikikai_interrupt));
m_maincpu->set_irq_acknowledge_callback(FUNC(kikikai_state::mcram_vect_r));
M6801U4(config, m_mcu, XTAL(4'000'000)); // xtal is 4MHz, divided by 4 internally
m_mcu->in_p1_cb().set_ioport("IN0");
m_mcu->in_p1_cb().set_ioport("IN0").invert();
m_mcu->out_p1_cb().set(FUNC(kikikai_state::kikikai_mcu_port1_w));
m_mcu->out_p2_cb().set(FUNC(kikikai_state::kikikai_mcu_port2_w));
m_mcu->out_p3_cb().set(FUNC(kikikai_state::kikikai_mcu_port3_w));
@ -749,16 +594,20 @@ void kikikai_state::kicknrun(machine_config &config)
}
void kikikai_simulation_state::kikikai(machine_config &config)
void kikikai_state::kicknrun(machine_config &config)
{
base(config);
add_mcu(config);
}
void kikikai_state::kikikai_mcu(machine_config &config)
{
base(config);
config.device_remove("sub");
m_screen->set_screen_update(FUNC(kikikai_simulation_state::screen_update_kikikai));
m_screen->set_screen_update(FUNC(kikikai_state::screen_update_kikikai));
// IRQs should be triggered by the MCU, but we don't have it
m_maincpu->set_vblank_int("screen", FUNC(kikikai_simulation_state::kikikai_interrupt));
m_maincpu->set_irq_acknowledge_callback(FUNC(kikikai_simulation_state::mcram_vect_r));
add_mcu(config);
}
@ -1015,11 +864,11 @@ ROM_END
*
*************************************/
GAME( 1986, kikikai, 0, kikikai, kikikai, kikikai_simulation_state, empty_init, ROT90, "Taito Corporation", "KiKi KaiKai", MACHINE_SUPPORTS_SAVE )
GAME( 1986, knightb, kikikai, knightb, kikikai, mexico86_state, empty_init, ROT90, "bootleg", "Knight Boy", MACHINE_SUPPORTS_SAVE )
GAME( 1986, knightba, kikikai, knightba, knightba, kikikai_state, empty_init, ROT90, "bootleg (Game Corporation)", "Knight Boy (Game Corporation bootleg)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) // missing coins, can be played using service to coin
GAME( 1986, kikikai, 0, kikikai_mcu, kikikai, kikikai_state, empty_init, ROT90, "Taito Corporation", "KiKi KaiKai", MACHINE_SUPPORTS_SAVE )
GAME( 1986, knightb, kikikai, knightb, kikikai, mexico86_state, empty_init, ROT90, "bootleg", "Knight Boy", MACHINE_SUPPORTS_SAVE )
GAME( 1986, knightba, kikikai, knightba, knightba, kikikai_state, empty_init, ROT90, "bootleg (Game Corporation)", "Knight Boy (Game Corporation bootleg)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) // missing coins, can be played using service to coin
GAME( 1986, kicknrun, 0, kicknrun, kicknrun, kikikai_state, empty_init, ROT0, "Taito Corporation", "Kick and Run (World)", MACHINE_SUPPORTS_SAVE )
GAME( 1986, kicknrunu,kicknrun, kicknrun, kicknrun, kikikai_state, empty_init, ROT0, "Taito America Corp", "Kick and Run (US)", MACHINE_SUPPORTS_SAVE )
GAME( 1986, mexico86, kicknrun, mexico86_68705, mexico86, mexico86_state, empty_init, ROT0, "bootleg", "Mexico 86 (bootleg of Kick and Run) (set 1)", MACHINE_SUPPORTS_SAVE )
GAME( 1986, mexico86a,kicknrun, mexico86_68705, mexico86, mexico86_state, empty_init, ROT0, "bootleg", "Mexico 86 (bootleg of Kick and Run) (set 2)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
GAME( 1986, kicknrun, 0, kicknrun, kicknrun, kikikai_state, empty_init, ROT0, "Taito Corporation", "Kick and Run (World)", MACHINE_SUPPORTS_SAVE )
GAME( 1986, kicknrunu,kicknrun, kicknrun, kicknrun, kikikai_state, empty_init, ROT0, "Taito America Corp", "Kick and Run (US)", MACHINE_SUPPORTS_SAVE )
GAME( 1986, mexico86, kicknrun, mexico86_68705, kicknrun, mexico86_state, empty_init, ROT0, "bootleg", "Mexico 86 (bootleg of Kick and Run) (set 1)", MACHINE_SUPPORTS_SAVE )
GAME( 1986, mexico86a,kicknrun, mexico86_68705, kicknrun, mexico86_state, empty_init, ROT0, "bootleg", "Mexico 86 (bootleg of Kick and Run) (set 2)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )

View File

@ -28,6 +28,7 @@ public:
void kicknrun(machine_config &config);
void knightba(machine_config &config);
void kikikai_mcu(machine_config &config);
protected:
u32 screen_update_kicknrun(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
@ -46,13 +47,15 @@ protected:
optional_shared_ptr<u8> m_mcu_sharedram;
private:
void add_mcu(machine_config &config);
void kicknrun_sub_output_w(uint8_t data);
virtual void main_f008_w(uint8_t data);
void main_bankswitch_w(uint8_t data);
uint8_t kiki_ym2203_r(offs_t offset);
virtual INTERRUPT_GEN_MEMBER(kikikai_interrupt);
INTERRUPT_GEN_MEMBER(kikikai_interrupt);
void main_map(address_map &map);
void sound_map(address_map &map);
@ -124,31 +127,3 @@ private:
u8 m_latch = 0U;
};
class kikikai_simulation_state : public kikikai_state
{
public:
kikikai_simulation_state(const machine_config &mconfig, device_type type, const char *tag) :
kikikai_state(mconfig, type, tag)
{
}
void kikikai(machine_config &config);
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
private:
virtual void main_f008_w(uint8_t data) override;
virtual INTERRUPT_GEN_MEMBER(kikikai_interrupt) override;
void mcu_simulate( );
/* kikikai mcu simulation */
int m_kikikai_simulated_mcu_running = 0;
int m_kikikai_simulated_mcu_initialised = 0;
bool m_coin_last[2]{};
u8 m_coin_fract = 0U;
};

View File

@ -29,229 +29,17 @@ void mexico86_state::main_f008_w(uint8_t data)
m_68705mcu->set_input_line(INPUT_LINE_RESET, (data & 2) ? CLEAR_LINE : ASSERT_LINE);
}
void kikikai_simulation_state::main_f008_w(uint8_t data)
{
m_audiocpu->set_input_line(INPUT_LINE_RESET, (data & 4) ? CLEAR_LINE : ASSERT_LINE);
// simulation for KiKi KaiKai
m_kikikai_simulated_mcu_running = data & 2;
if (!m_kikikai_simulated_mcu_running)
m_kikikai_simulated_mcu_initialised = 0;
}
/***************************************************************************
KiKi KaiKai MCU simulation
This is derived from examination of the bootleg 68705 MCU code, with an
addition to fix collision detection which is missing from the bootleg.
***************************************************************************/
void kikikai_simulation_state::mcu_simulate( )
{
if (!m_kikikai_simulated_mcu_initialised)
{
if (m_mcu_sharedram[0x01] == 0x00)
{
logerror("initialising MCU\n");
m_mcu_sharedram[0x04] = 0xfc; // coin inputs
m_mcu_sharedram[0x02] = 0xff; // player 1
m_mcu_sharedram[0x03] = 0xff; // player 2
m_mcu_sharedram[0x1b] = 0xff; // active player
m_mcu_sharedram[0x06] = 0xff; // must be FF otherwise PS4 ERROR
m_mcu_sharedram[0x07] = 0x03; // must be 03 otherwise PS4 ERROR
m_mcu_sharedram[0x00] = 0x00;
m_kikikai_simulated_mcu_initialised = 1;
}
}
if (m_kikikai_simulated_mcu_initialised)
{
int i;
bool coin_curr;
u8 coin_in_read = ioport("IN0")->read() & 3;
// TODO: still needs Coinage B into account
for(int coin_idx = 0; coin_idx < 2; coin_idx++)
{
coin_curr = (coin_in_read & (1 << coin_idx)) == 0;
if (coin_curr && m_coin_last[coin_idx] == false)
{
u8 coinage_setting = (ioport("DSW0")->read() >> (coin_idx*2 + 4)) & 3;
// increase credits counter
switch(coinage_setting)
{
case 0: // 2c / 3c
case 1: // 2c / 1c
if(m_coin_fract == 1)
{
m_mcu_sharedram[0x01]+= (coinage_setting == 0) ? 3 : 1;
m_coin_fract = 0;
}
else
m_coin_fract ++;
break;
case 2: // 1c / 2c
case 3: // 1c / 1c
m_mcu_sharedram[0x01]+= (coinage_setting == 2) ? 2 : 1;
break;
}
m_mcu_sharedram[0x0a] = 0x01; // set flag (coin inserted sound is not played otherwise)
}
m_coin_last[coin_idx] = coin_curr;
}
// Purge any coin counter higher than 9 TODO: is this limit correct?
if(m_mcu_sharedram[0x01] > 9)
m_mcu_sharedram[0x01] = 9;
m_mcu_sharedram[0x04] = 0x3c | (coin_in_read ^ 3); // coin inputs
m_mcu_sharedram[0x02] = bitswap<8>(ioport("IN1")->read(), 7,6,5,4,2,3,1,0); // player 1
m_mcu_sharedram[0x03] = bitswap<8>(ioport("IN2")->read(), 7,6,5,4,2,3,1,0); // player 2
if (m_mcu_sharedram[0x19] == 0xaa) // player 2 active
m_mcu_sharedram[0x1b] = m_mcu_sharedram[0x03];
else
m_mcu_sharedram[0x1b] = m_mcu_sharedram[0x02];
for (i = 0; i < 0x10; i += 2)
m_mcu_sharedram[i + 0xb1] = m_mcu_sharedram[i + 0xb0];
for (i = 0; i < 0x0a; i++)
m_mcu_sharedram[i + 0xc0] = m_mcu_sharedram[i + 0x90] + 1;
if (m_mcu_sharedram[0xd1] == 0xff)
{
if (m_mcu_sharedram[0xd0] > 0 && m_mcu_sharedram[0xd0] < 4)
{
m_mcu_sharedram[0xd2] = 0x81;
m_mcu_sharedram[0xd0] = 0xff;
}
}
if (m_mcu_sharedram[0xe0] > 0 && m_mcu_sharedram[0xe0] < 4)
{
static const u8 answers[3][16] =
{
{ 0x00,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x80,0x88,0x00,0x00,0x00,0x00,0x00 },
{ 0x00,0x04,0x08,0x0C,0x10,0x14,0x18,0x1C,0x20,0x31,0x2B,0x35,0x00,0x00,0x00,0x00 },
{ 0x00,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x03,0x0A,0x0B,0x14,0x00,0x00,0x00,0x00 },
};
int table = m_mcu_sharedram[0xe0] - 1;
for (i = 1; i < 0x10; i++)
m_mcu_sharedram[0xe0 + i] = answers[table][i];
m_mcu_sharedram[0xe0] = 0xff;
}
if (m_mcu_sharedram[0xf0] > 0 && m_mcu_sharedram[0xf0] < 4)
{
m_mcu_sharedram[0xf1] = 0xb3;
m_mcu_sharedram[0xf0] = 0xff;
}
// The following is missing from Knight Boy
// this should be equivalent to the obfuscated kiki_clogic() below
{
static const u8 db[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x18,0x00,0x00,0x00,0x00};
u16 sy = m_mcu_sharedram[0xa0] + ((0x18) >> 1);
u16 sx = m_mcu_sharedram[0xa1] + ((0x18) >> 1);
for (i = 0; i < 0x38; i += 8)
{
u8 hw = db[m_mcu_sharedram[0x20 + i] & 0xf];
if (hw)
{
u16 xdiff = sx - (u16(m_mcu_sharedram[0x20 + i + 6]) << 8 | m_mcu_sharedram[0x20 + i + 7]);
if (xdiff < hw)
{
u16 ydiff = sy - (u16(m_mcu_sharedram[0x20 + i + 4]) << 8 | m_mcu_sharedram[0x20 + i + 5]);
if (ydiff < hw)
m_mcu_sharedram[0xa2] = 1; // we have a collision
}
}
}
}
}
}
INTERRUPT_GEN_MEMBER(kikikai_state::kikikai_interrupt)
{
device.execute().set_input_line(0, ASSERT_LINE);
}
INTERRUPT_GEN_MEMBER(kikikai_simulation_state::kikikai_interrupt)
{
if (m_kikikai_simulated_mcu_running)
mcu_simulate();
device.execute().set_input_line(0, ASSERT_LINE);
}
IRQ_CALLBACK_MEMBER(kikikai_state::mcram_vect_r)
{
m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE);
return m_mcu_sharedram[0];
}
#if 0
/***************************************************************************
Collision logic used by Kiki Kaikai (theoretical)
***************************************************************************/
#define KIKI_CL_OUT 0xa2
#define KIKI_CL_TRIGGER 0xa3
#define DCWIDTH 0
#define DCHEIGHT 0
void kikikai_state::kiki_clogic(int address, int latch)
{
static const u8 db[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x18,0x00,0x00,0x00,0x00};
int sy, sx, hw, i, qptr, diff1, diff2;
if (address != KIKI_CL_TRIGGER) // m_queue latched data
{
m_queue[m_qfront++] = latch;
m_qfront &= 0x3f;
}
else if (m_qstate ^= 1) // scan m_queue
{
sy = m_queue[(m_qfront-0x3a)&0x3f] + ((0x18-DCHEIGHT)>>1);
sx = m_queue[(m_qfront-0x39)&0x3f] + ((0x18-DCWIDTH)>>1);
for (i=0x38; i; i-=8)
{
qptr = m_qfront - i;
if (!(hw = db[m_queue[qptr&0x3f]&0xf])) continue;
diff1 = sx - (short)(m_queue[(qptr+6)&0x3f]<<8|m_queue[(qptr+7)&0x3f]) + DCWIDTH;
diff2 = diff1 - (hw + DCWIDTH);
if ((diff1^diff2)<0)
{
diff1 = sy - (short)(m_queue[(qptr+4)&0x3f]<<8|m_queue[(qptr+5)&0x3f]) + DCHEIGHT;
diff2 = diff1 - (hw + DCHEIGHT);
if ((diff1^diff2)<0)
m_mcu_sharedram[KIKI_CL_OUT] = 1; // we have a collision
}
}
}
}
#endif
/***************************************************************************
Mexico 86 68705 protection interface