Skip to content

Commit

Permalink
taito/kikikai.cpp: hook up kikikai MCU (#11900)
Browse files Browse the repository at this point in the history
  • Loading branch information
mamehaze committed Jan 5, 2024
1 parent 2251902 commit 6cdb50d
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 414 deletions.
195 changes: 22 additions & 173 deletions src/mame/taito/kikikai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,6 @@ ernesto@imagina.com
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!
Expand Down Expand Up @@ -231,130 +220,6 @@ 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_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( Demo_Sounds ) ) PORT_DIPLOCATION("SWA:4") // Demo Sounds only play every 8th Demo
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x08, 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( mexico86 )
PORT_START("IN0")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
Expand Down Expand Up @@ -396,9 +261,9 @@ static INPUT_PORTS_START( mexico86 )
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( 0x08, 0x08, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SWA:4") // Demo Sounds only play every 8th Demo
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x08, 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 ) )
Expand Down Expand Up @@ -478,6 +343,7 @@ static INPUT_PORTS_START( mexico86 )
PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNKNOWN )
INPUT_PORTS_END


static INPUT_PORTS_START( kikikai )
PORT_START("IN0")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
Expand Down Expand Up @@ -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()
Expand All @@ -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)
{
Expand Down Expand Up @@ -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));
Expand All @@ -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);
}


Expand Down Expand Up @@ -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 )
33 changes: 4 additions & 29 deletions src/mame/taito/kikikai.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class kikikai_state : public driver_device

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);
Expand All @@ -46,13 +47,15 @@ class kikikai_state : public driver_device
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);
Expand Down Expand Up @@ -124,31 +127,3 @@ class mexico86_state : public kikikai_state
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;
};
Loading

0 comments on commit 6cdb50d

Please sign in to comment.