From a7c5c7c6ceab9a9efe13dd1331d4deb6ae553871 Mon Sep 17 00:00:00 2001 From: hap Date: Tue, 8 Aug 2023 19:53:36 +0200 Subject: [PATCH] lkage5232: add mcu, add volume filters, promote to working --- src/devices/sound/ta7630.cpp | 27 +- src/devices/sound/ta7630.h | 13 +- src/mame/mame.lst | 4 +- src/mame/misc/beezer.cpp | 2 +- src/mame/taito/lkage.cpp | 620 ++++++++++++++++++----------------- 5 files changed, 335 insertions(+), 331 deletions(-) diff --git a/src/devices/sound/ta7630.cpp b/src/devices/sound/ta7630.cpp index 6dcb84455b9..7e005eddb4a 100644 --- a/src/devices/sound/ta7630.cpp +++ b/src/devices/sound/ta7630.cpp @@ -40,25 +40,21 @@ DEFINE_DEVICE_TYPE(TA7630, ta7630_device, "ta7630", "Toshiba TA7630P") ta7630_device::ta7630_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, TA7630, tag, owner, clock) -// ,device_sound_interface(mconfig, *this) { } - //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void ta7630_device::device_start() { - int i; - double db = 0.0; double db_step = 1.50; /* 1.50 dB step (at least, maybe more) */ double db_step_inc = 0.125; - for (i = 0; i < 16; i++) + for (int i = 0; i < 16; i++) { double max = 100.0 / pow(10.0, db/20.0 ); m_vol_ctrl[15 - i] = max / 100.0; @@ -72,29 +68,18 @@ void ta7630_device::device_start() } -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void ta7630_device::device_reset() -{ - -} - //************************************************************************** // filter setters //************************************************************************** -void ta7630_device::set_device_volume(device_sound_interface *device,uint8_t value) +void ta7630_device::set_device_volume(device_sound_interface *device, uint8_t value) { - device->set_output_gain(ALL_OUTPUTS,m_vol_ctrl[value & 0xf]); + device->set_output_gain(ALL_OUTPUTS, m_vol_ctrl[value & 0xf]); } -// TODO: Most Taito implementations uses this, is it correct? -void ta7630_device::set_channel_volume(device_sound_interface *device, uint8_t ch,uint8_t value) +// TODO: Most Taito implementations uses this, is it correct? +void ta7630_device::set_channel_volume(device_sound_interface *device, uint8_t ch, uint8_t value) { - device->set_output_gain(ch,m_vol_ctrl[value & 0xf]); + device->set_output_gain(ch, m_vol_ctrl[value & 0xf]); } - - diff --git a/src/devices/sound/ta7630.h b/src/devices/sound/ta7630.h index e32b4bab407..4851ba696b5 100644 --- a/src/devices/sound/ta7630.h +++ b/src/devices/sound/ta7630.h @@ -18,21 +18,18 @@ // ======================> ta7630_device class ta7630_device : public device_t - /*, public device_sound_interface*/ { public: // construction/destruction ta7630_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); // filter setters - void set_device_volume(device_sound_interface *device,uint8_t value); - void set_channel_volume(device_sound_interface *device, uint8_t ch,uint8_t value); + void set_device_volume(device_sound_interface *device, uint8_t value); + void set_channel_volume(device_sound_interface *device, uint8_t ch, uint8_t value); protected: // device-level overrides - //virtual void device_validity_check(validity_checker &valid) const override; virtual void device_start() override; - virtual void device_reset() override; private: double m_vol_ctrl[16]; // table for volume gains @@ -43,10 +40,4 @@ private: DECLARE_DEVICE_TYPE(TA7630, ta7630_device) - -//************************************************************************** -// GLOBAL VARIABLES -//************************************************************************** - - #endif // MAME_SOUND_TA7630_H diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 9ed7bc5aef0..50c9a5d52fb 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -42630,13 +42630,13 @@ lgpalt // (c) 1983 Taito @source:taito/lkage.cpp bygone // A53 (c) 1985 Taito Corporation - prototype ? lkage // A54 (c) 1984 Taito Corporation -lkage5232 // lkageb // bootleg lkageb2 // bootleg lkageb3 // bootleg lkageb4 // bootleg +lkagem // lkageo // A54 (c) 1984 Taito Corporation -lkageoo // A54 (c) 1984 Taito Corporation +lkageo2 // A54 (c) 1984 Taito Corporation @source:taito/lsasquad.cpp daikaiju // A74 (c) 1986 Taito diff --git a/src/mame/misc/beezer.cpp b/src/mame/misc/beezer.cpp index 69cfe53e93c..34b7a3618c9 100644 --- a/src/mame/misc/beezer.cpp +++ b/src/mame/misc/beezer.cpp @@ -5,7 +5,7 @@ Beezer - (c) 1982 Pacific Polytechnical Corp (PPC). / Tong Electronic + (c) 1982 Pacific Polytechnical Corp. (PPC) / Tong Electronic Notes: - To enter test mode, hold down 1P Start and 2P Start, then reset diff --git a/src/mame/taito/lkage.cpp b/src/mame/taito/lkage.cpp index 7b4407cc91a..fb44865f87d 100644 --- a/src/mame/taito/lkage.cpp +++ b/src/mame/taito/lkage.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders: Phil Stroffolino, Takahiro Nogi +// copyright-holders: Phil Stroffolino /*************************************************************************** @@ -66,13 +66,15 @@ Stephh's notes (based on the games Z80 code and some tests) : - MCU (same code as lkage) is not used - No music ? (could be emulation bug) (the 2nd YM is not used...) + TODO: - The high score display uses a video attribute flag whose purpose isn't known. - purpose of the 0x200 byte prom, "a54-10.2" is unknown. It contains values in range 0x0..0xf. - - SOUND: lots of unknown writes to the YM2203 I/O ports + - SOUND: lots of unknown writes to the YM2203 I/O ports. Does it have a TA7630 + or some sort of volume filtering, and if so, only on the SSG channels maybe? - Note that all the bootlegs are derived from a different version of the original which hasn't been found yet. @@ -83,6 +85,9 @@ TODO: The game works anyway, it never gives the usual Taito "BAD HW" message (because there is no test at 0x033b after call at routine at 0xde1d). + - lkageo, lkageo2, lkagem demo mode messes up, the rest of the game works ok. + Maybe it's MCU related? Since main char movement in demo depends on values + read from MCU. ***************************************************************************/ @@ -95,8 +100,8 @@ TODO: #include "machine/gen_latch.h" #include "machine/input_merger.h" #include "sound/ay8910.h" -#include "sound/dac.h" #include "sound/msm5232.h" +#include "sound/ta7630.h" #include "sound/ymopn.h" #include "emupal.h" @@ -129,7 +134,6 @@ public: void lkage(machine_config &config); void init_bygone(); - void init_lkage(); protected: virtual void machine_start() override; @@ -151,12 +155,11 @@ protected: uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void io_map(address_map &map); - void base_program_map(address_map &map); - void program_map(address_map &map); + virtual void program_map(address_map &map); + virtual void io_map(address_map &map); void bootleg_program_map(address_map &map); void mcu_map(address_map &map); - void sound_map(address_map &map); + virtual void sound_map(address_map &map); required_shared_ptr m_vreg; required_shared_ptr m_scroll; @@ -188,39 +191,83 @@ protected: uint8_t m_mcu_ready = 0; // CPU data/MCU ready status }; -class lkage5232_state : public lkage_state +class lkagem_state : public lkage_state { public: - lkage5232_state(const machine_config &mconfig, device_type type, const char *tag) : + lkagem_state(const machine_config &mconfig, device_type type, const char *tag) : lkage_state(mconfig, type, tag), + m_ta7630(*this, "ta7630"), + m_msm(*this, "msm"), + m_ay(*this, "ay%u", 1U), m_exrom(*this, "data") { } - void lkage5232(machine_config &config); - - void init_lkage5232(); + void lkagem(machine_config &config); protected: virtual void machine_start() override; private: - uint8_t unk_f0e1_r(offs_t offset); uint8_t exrom_data_r(offs_t offset); void exrom_offset_w(offs_t offset, uint8_t data); - uint8_t sound_unk_e000_r(offs_t offset); + void msm_volume_w(uint8_t data); + template void ay_volume_w(uint8_t data); - void program_map(address_map &map); - void sound_map(address_map &map); + virtual void program_map(address_map &map) override; + virtual void io_map(address_map &map) override { } + virtual void sound_map(address_map &map) override; + required_device m_ta7630; + required_device m_msm; + required_device_array m_ay; required_region_ptr m_exrom; - uint8_t m_exrom_offs[2] = { 0x00, 0x00 }; + uint8_t m_exrom_offs[2] = { }; }; -// video -/*************************************************************************** +/******************************************************************************* + Initialization +*******************************************************************************/ + +void lkage_state::machine_start() +{ + save_item(NAME(m_bg_tile_bank)); + save_item(NAME(m_fg_tile_bank)); + save_item(NAME(m_tx_tile_bank)); + + save_item(NAME(m_mcu_val)); +} + +void lkagem_state::machine_start() +{ + lkage_state::machine_start(); + + m_sprite_offset = 24; + save_item(NAME(m_exrom_offs)); +} + +void lkage_state::init_bygone() +{ + m_sprite_dx = 1; +} + +void lkage_state::machine_reset() +{ + m_bg_tile_bank = m_fg_tile_bank = m_tx_tile_bank = 0; + + m_mcu_ready = 3; + m_mcu_val = 0; + + m_soundnmi->in_w<1>(0); +} + + + +/******************************************************************************* + Video hardware +-------------------------------------------------------------------------------- lkage_scroll[0x00]: text layer horizontal scroll lkage_scroll[0x01]: text layer vertical scroll @@ -229,23 +276,7 @@ private: lkage_scroll[0x04]: background layer horizontal scroll lkage_scroll[0x05]: background layer vertical scroll - lkage_vreg[0]: 0x00,0x04 - 0x02: tx tile bank select (bygone only?) - 0x04: fg tile bank select - 0x08: ? - - lkage_vreg[1]: 0x7d - 0xf0: background/foreground palette select - 0x08: bg tile bank select - 0x07: priority config? - - lkage_vreg[2]: 0xf3 - 0x03: flip screen x/y - 0xf0: normally 1111, but 1001 and 0001 inbetween stages (while the - backgrounds are are being redrawn). These bits are probably used to enable - individual layers, but we have no way of knowing the mapping. - - lkage_vreg: + m_vreg: 04 7d f3 : title screen 101 0c 7d f3 : high score 101 04 06 f3 : attract#1 110 @@ -253,9 +284,23 @@ private: 04 1e f3 : attract#3 110 00 4e f3 : attract#4 110 + m_vreg[0]: 0x00,0x04 + 0x02: tx tile bank select (bygone only?) + 0x04: fg tile bank select + 0x08: ? -***************************************************************************/ + m_vreg[1]: 0x7d + 0xf0: background/foreground palette select + 0x08: bg tile bank select + 0x07: priority config? + m_vreg[2]: 0xf3 + 0x03: flip screen x/y + 0xf0: normally 1111, but 1001 and 0001 inbetween stages (while the + backgrounds are are being redrawn). These bits are probably used to enable + individual layers, but we have no way of knowing the mapping. + +*******************************************************************************/ void lkage_state::videoram_w(offs_t offset, uint8_t data) { @@ -316,7 +361,7 @@ void lkage_state::video_start() void lkage_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { uint8_t const *source = m_spriteram; - uint8_t const *const finish = source + std::min(m_spriteram.bytes(), 0x80); + uint8_t const *const finish = source + m_spriteram.bytes(); for ( ; source < finish; source += 4) { @@ -430,7 +475,10 @@ uint32_t lkage_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, } -// machine + +/******************************************************************************* + Common handlers +*******************************************************************************/ void lkage_state::sh_nmi_disable_w(uint8_t data) { @@ -447,35 +495,18 @@ uint8_t lkage_state::sound_status_r() return 0xff; } -uint8_t lkage5232_state::unk_f0e1_r(offs_t offset) +uint8_t lkage_state::mcu_status_r() { - // Protection? - return 0xff; + // bit 0 = when 1, MCU is ready to receive data from main CPU + // bit 1 = when 1, MCU has sent data to the main CPU + return + ((CLEAR_LINE == m_bmcu->host_semaphore_r()) ? 0x01 : 0x00) | + ((CLEAR_LINE != m_bmcu->mcu_semaphore_r()) ? 0x02 : 0x00); } -uint8_t lkage5232_state::exrom_data_r(offs_t offset) -{ - uint16_t const offs = ((m_exrom_offs[1] & 0x3f) << 8) + (m_exrom_offs[0] & 0xff); - uint8_t const data = m_exrom[offs]; +// address maps - if (offset != 0) - return 0xff; - else - return data; -} - -void lkage5232_state::exrom_offset_w(offs_t offset, uint8_t data) -{ - m_exrom_offs[offset] = data; -} - -uint8_t lkage5232_state::sound_unk_e000_r(offs_t offset) -{ - return 0xff; -} - - -void lkage_state::base_program_map(address_map &map) +void lkage_state::program_map(address_map &map) { map(0x0000, 0xdfff).rom(); map(0xe000, 0xe7ff).ram(); // work RAM @@ -493,26 +524,11 @@ void lkage_state::base_program_map(address_map &map) map(0xf0a0, 0xf0a3).ram(); // unknown map(0xf0c0, 0xf0c5).ram().share(m_scroll); map(0xf0e1, 0xf0e1).nopw(); // pulsed + map(0xf100, 0xf15f).writeonly().share(m_spriteram); + map(0xf160, 0xf1ff).nopw(); // bygone map(0xf400, 0xffff).ram().w(FUNC(lkage_state::videoram_w)).share(m_videoram); } -void lkage_state::program_map(address_map &map) -{ - base_program_map(map); - map(0xf100, 0xf15f).ram().share(m_spriteram); - map(0xf160, 0xf1ff).ram(); // unknown - no valid sprite data -} - -void lkage5232_state::program_map(address_map &map) -{ - base_program_map(map); - //map(0xf060, 0xf060).w(m_soundlatch, FUNC(generic_latch_8_device::write)); - map(0xf0a0, 0xf0a1).r(FUNC(lkage5232_state::exrom_data_r)).w(FUNC(lkage5232_state::exrom_offset_w)); // extend ROM read - map(0xf0a2, 0xf0a3).noprw(); // unknown - map(0xf0e1, 0xf0e1).r(FUNC(lkage5232_state::unk_f0e1_r)).nopw(); // unknown - map(0xf100, 0xf1ff).ram().share(m_spriteram); -} - void lkage_state::mcu_map(address_map &map) { program_map(map); @@ -520,6 +536,148 @@ void lkage_state::mcu_map(address_map &map) map(0xf087, 0xf087).r(FUNC(lkage_state::mcu_status_r)); } +void lkage_state::io_map(address_map &map) +{ + map(0x4000, 0x7fff).rom().region("data", 0); +} + +// sound hardware is almost identical to Bubble Bobble, YM2203 instead of YM3526 + +void lkage_state::sound_map(address_map &map) +{ + map(0x0000, 0x7fff).rom(); + map(0x8000, 0x87ff).ram(); + map(0x9000, 0x9001).rw("ym1", FUNC(ym2203_device::read), FUNC(ym2203_device::write)); + map(0xa000, 0xa001).rw("ym2", FUNC(ym2203_device::read), FUNC(ym2203_device::write)); + map(0xb000, 0xb000).r(m_soundlatch, FUNC(generic_latch_8_device::read)).nopw(); // write? + map(0xb001, 0xb001).nopr().w(FUNC(lkage_state::sh_nmi_enable_w)); // read? + map(0xb002, 0xb002).w(FUNC(lkage_state::sh_nmi_disable_w)); + map(0xb003, 0xb003).nopw(); + map(0xe000, 0xefff).rom(); // space for diagnostic ROM? +} + + + +/******************************************************************************* + MSM5232 version handlers +*******************************************************************************/ + +uint8_t lkagem_state::exrom_data_r(offs_t offset) +{ + uint16_t const offs = ((m_exrom_offs[1] & 0x3f) << 8) + (m_exrom_offs[0] & 0xff); + uint8_t const data = m_exrom[offs]; + + if (offset != 0) + return 0xff; + else + return data; +} + +void lkagem_state::exrom_offset_w(offs_t offset, uint8_t data) +{ + m_exrom_offs[offset] = data; +} + +void lkagem_state::msm_volume_w(uint8_t data) +{ + for (int i = 0; i < 4; i++) + { + m_ta7630->set_channel_volume(m_msm, i, data & 0xf); + m_ta7630->set_channel_volume(m_msm, i + 4, data >> 4); + } +} + +template +void lkagem_state::ay_volume_w(uint8_t data) +{ + m_ta7630->set_device_volume(m_ay[N], data >> 4); +} + +// address maps + +void lkagem_state::program_map(address_map &map) +{ + lkage_state::program_map(map); + map(0xf0a0, 0xf0a1).r(FUNC(lkagem_state::exrom_data_r)).w(FUNC(lkagem_state::exrom_offset_w)); // extend ROM read + map(0xf0a2, 0xf0a3).noprw(); // unknown + map(0xf0e0, 0xf0e0).rw(m_bmcu, FUNC(taito68705_mcu_device::data_r), FUNC(taito68705_mcu_device::data_w)); + map(0xf0e1, 0xf0e1).r(FUNC(lkagem_state::mcu_status_r)); + map(0xf140, 0xf15f).unmapw(); + map(0xf160, 0xf17f).lw8(NAME([this](offs_t offset, uint8_t data) { m_spriteram[offset | 0x40] = data; })); +} + +// lkagem sound hardware is more similar to Buggy Challenge and Metal Soldier Isaac II + +void lkagem_state::sound_map(address_map &map) +{ + map(0x0000, 0x3fff).rom(); + map(0x4000, 0x47ff).ram(); + map(0x8000, 0x8001).w(m_ay[0], FUNC(ym2149_device::address_data_w)); + map(0x8002, 0x8003).w(m_ay[1], FUNC(ym2149_device::address_data_w)); + map(0x8010, 0x801d).w(m_msm, FUNC(msm5232_device::write)); + map(0x8020, 0x8020).w(FUNC(lkagem_state::msm_volume_w)); + map(0xc000, 0xc000).r(m_soundlatch, FUNC(generic_latch_8_device::read)).nopw(); // write? + map(0xc001, 0xc001).nopr().w(FUNC(lkagem_state::sh_nmi_enable_w)); // read? + map(0xc002, 0xc002).w(FUNC(lkagem_state::sh_nmi_disable_w)); + map(0xc003, 0xc003).nopw(); + map(0xe000, 0xefff).rom(); // space for diagnostic ROM? +} + + + +/******************************************************************************* + Bootleg handlers +*******************************************************************************/ + +// Note: This probably uses another MCU program, which is undumped. + +uint8_t lkage_state::fake_mcu_r() +{ + int result = 0; + + switch (m_mcu_val) + { + // These are for the attract mode + case 0x01: + result = m_mcu_val - 1; + break; + + case 0x90: + result = m_mcu_val + 0x43; + break; + + // Gameplay Protection, checked in this order at a start of a play + case 0xa6: + result = m_mcu_val + 0x27; + break; + + case 0x34: + result = m_mcu_val + 0x7f; + break; + + case 0x48: + result = m_mcu_val + 0xb7; + break; + + default: + result = m_mcu_val; + break; + } + return result; +} + +void lkage_state::fake_mcu_w(uint8_t data) +{ + m_mcu_val = data; +} + +uint8_t lkage_state::fake_status_r() +{ + return m_mcu_ready; +} + +// address maps + void lkage_state::bootleg_program_map(address_map &map) { program_map(map); @@ -528,46 +686,10 @@ void lkage_state::bootleg_program_map(address_map &map) } -void lkage_state::io_map(address_map &map) -{ - map(0x4000, 0x7fff).rom().region("data", 0); -} - -/***************************************************************************/ - -// sound section is almost identical to Bubble Bobble, YM2203 instead of YM3526 - -void lkage_state::sound_map(address_map &map) -{ - map(0x0000, 0x7fff).rom(); - map(0x8000, 0x87ff).ram(); - map(0x9000, 0x9001).rw("ym1", FUNC(ym2203_device::read), FUNC(ym2203_device::write)); - map(0xa000, 0xa001).rw("ym2", FUNC(ym2203_device::read), FUNC(ym2203_device::write)); - map(0xb000, 0xb000).r(m_soundlatch, FUNC(generic_latch_8_device::read)).nopw(); // ??? - map(0xb001, 0xb001).nopr().w(FUNC(lkage_state::sh_nmi_enable_w)); // read ??? - map(0xb002, 0xb002).w(FUNC(lkage_state::sh_nmi_disable_w)); - map(0xb003, 0xb003).nopw(); - map(0xe000, 0xefff).rom(); // space for diagnostic ROM? -} - -void lkage5232_state::sound_map(address_map &map) -{ - map(0x0000, 0x3fff).rom(); - map(0x4000, 0x47ff).ram(); - map(0x8000, 0x8001).w("ay1", FUNC(ym2149_device::address_data_w)); - map(0x8002, 0x8003).w("ay2", FUNC(ym2149_device::address_data_w)); - map(0x8010, 0x801d).w("msm", FUNC(msm5232_device::write)); - map(0x8020, 0x8020).nopw(); // ? - map(0xc000, 0xc000).r(m_soundlatch, FUNC(generic_latch_8_device::read)); - map(0xc001, 0xc001).nopr().w(FUNC(lkage5232_state::sh_nmi_enable_w)); - map(0xc002, 0xc002).w(FUNC(lkage5232_state::sh_nmi_disable_w)); -// map(0xc003, 0xc003).w("dac", FUNC(dac_byte_interface::data_w)); - map(0xc003, 0xc003).nopw(); - map(0xe000, 0xe000).r(FUNC(lkage5232_state::sound_unk_e000_r)); -} - -/***************************************************************************/ +/******************************************************************************* + Input ports +*******************************************************************************/ static INPUT_PORTS_START( lkage ) PORT_START("DSW1") @@ -786,7 +908,6 @@ static INPUT_PORTS_START( bygone ) PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_START("SYSTEM") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 ) @@ -820,6 +941,10 @@ INPUT_PORTS_END +/******************************************************************************* + GFX layouts +*******************************************************************************/ + static const gfx_layout tile_layout = { 8,8, @@ -845,39 +970,15 @@ static const gfx_layout sprite_layout = }; static GFXDECODE_START( gfx_lkage ) - GFXDECODE_ENTRY( "gfx", 0x0000, tile_layout, /*128*/0, 64 ) + GFXDECODE_ENTRY( "gfx", 0x0000, tile_layout, 0, 64 ) GFXDECODE_ENTRY( "gfx", 0x0000, sprite_layout, 0, 16 ) GFXDECODE_END -void lkage_state::machine_start() -{ - save_item(NAME(m_bg_tile_bank)); - save_item(NAME(m_fg_tile_bank)); - save_item(NAME(m_tx_tile_bank)); - - save_item(NAME(m_mcu_val)); -} - -void lkage5232_state::machine_start() -{ - save_item(NAME(m_bg_tile_bank)); - save_item(NAME(m_fg_tile_bank)); - save_item(NAME(m_tx_tile_bank)); - - save_item(NAME(m_exrom_offs)); -} - -void lkage_state::machine_reset() -{ - m_bg_tile_bank = m_fg_tile_bank = m_tx_tile_bank =0; - - m_mcu_ready = 3; - m_mcu_val = 0; - - m_soundnmi->in_w<1>(0); -} +/******************************************************************************* + Machine configs +*******************************************************************************/ void lkage_state::lkage(machine_config &config) { @@ -925,49 +1026,45 @@ void lkage_state::lkage(machine_config &config) ym2.add_route(3, "mono", 0.40); } -void lkage_state::lkageb(machine_config &config) +void lkagem_state::lkagem(machine_config &config) { lkage(config); - m_maincpu->set_addrmap(AS_PROGRAM, &lkage_state::bootleg_program_map); - - config.device_remove("bmcu"); -} - -void lkage5232_state::lkage5232(machine_config &config) -{ - lkageb(config); - - m_maincpu->set_addrmap(AS_PROGRAM, &lkage5232_state::program_map); - - m_audiocpu->set_addrmap(AS_PROGRAM, &lkage5232_state::sound_map); - m_audiocpu->set_periodic_int(FUNC(lkage5232_state::irq0_line_hold), attotime::from_hz(60)); - - // 100 CPU slices per frame - a high value to ensure proper synchronization of the CPUs - config.set_maximum_quantum(attotime::from_hz(6000)); - - subdevice("screen")->set_screen_update(FUNC(lkage5232_state::screen_update)); + m_audiocpu->set_periodic_int(FUNC(lkagem_state::irq0_line_hold), attotime::from_hz(60)); config.device_remove("ym1"); config.device_remove("ym2"); - YM2149(config, "ay1", 2_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.18); - YM2149(config, "ay2", 2_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.18); + YM2149(config, m_ay[0], 2_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.15); + m_ay[0]->port_a_write_callback().set(FUNC(lkagem_state::ay_volume_w<0>)); + m_ay[0]->port_b_write_callback().set_nop(); // also TA7630? - msm5232_device &msm(MSM5232(config, "msm", 2_MHz_XTAL)); - msm.set_capacitors(0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6); - msm.add_route(0, "mono", 1.35); - msm.add_route(1, "mono", 1.35); - msm.add_route(2, "mono", 1.35); - msm.add_route(3, "mono", 1.35); - msm.add_route(4, "mono", 1.35); - msm.add_route(5, "mono", 1.35); - msm.add_route(6, "mono", 1.35); - msm.add_route(7, "mono", 1.35); + YM2149(config, m_ay[1], 2_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.15); + m_ay[1]->port_a_write_callback().set(FUNC(lkagem_state::ay_volume_w<1>)); + m_ay[1]->port_b_write_callback().set_nop(); // also TA7630? - DAC_8BIT_R2R(config, "dac", 0).add_route(ALL_OUTPUTS, "mono", 0.25); + MSM5232(config, m_msm, 2_MHz_XTAL); + m_msm->set_capacitors(0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6); + for (int i = 0; i < 8; i++) + m_msm->add_route(i, "mono", 1.00); + + TA7630(config, m_ta7630); } +void lkage_state::lkageb(machine_config &config) +{ + lkage(config); + + config.device_remove("bmcu"); + + m_maincpu->set_addrmap(AS_PROGRAM, &lkage_state::bootleg_program_map); +} + + + +/******************************************************************************* + ROM definitions +*******************************************************************************/ ROM_START( lkage ) ROM_REGION( 0x14000, "maincpu", 0 ) // Z80 code @@ -1029,7 +1126,7 @@ ROM_START( lkageo ) ROM_LOAD( "pal16l8a-a54-14.35", 0x0600, 0x0104, CRC(a89c644e) SHA1(b41a077d1d070d9563f924c776930c33a4ff27d0) ) ROM_END -ROM_START( lkageoo ) +ROM_START( lkageo2 ) ROM_REGION( 0x14000, "maincpu", 0 ) // Z80 code ROM_LOAD( "a54-01.37", 0x0000, 0x8000, CRC(34eab2c5) SHA1(25bf2dc80d21aa68c3af5debf10b24c75d83a738) ) ROM_LOAD( "a54-02.38", 0x8000, 0x8000, CRC(ea471d8a) SHA1(1ffc7f78e3e983e16a23e97019f7030f9846569b) ) @@ -1059,6 +1156,33 @@ ROM_START( lkageoo ) ROM_LOAD( "pal16l8a-a54-14.35", 0x0600, 0x0104, CRC(a89c644e) SHA1(b41a077d1d070d9563f924c776930c33a4ff27d0) ) ROM_END +ROM_START( lkagem ) + ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF ) // Z80 code + ROM_LOAD( "a51_11-2.ic", 0x0000, 0x4000, CRC(540fdb1f) SHA1(11d2a5b56d6d72458816aaf7687e490126b468cc) ) + ROM_LOAD( "a51_12-2.ic", 0x4000, 0x4000, CRC(a625a4b8) SHA1(417e7590f98eadc71cbed749350d6d3a1c1fd413) ) + ROM_LOAD( "a51_13-2.ic", 0x8000, 0x4000, CRC(aba8c6a3) SHA1(6723138f54a06d3e4719a43e8e3f11b3cabfb6f7) ) + ROM_LOAD( "a51_10-2.ic", 0xc000, 0x2000, CRC(f6243d5c) SHA1(7b2810afe9c128a290f15c6ea1a6a1c2757ddf55) ) + + ROM_REGION( 0x10000, "audiocpu", 0 ) // Z80 code + ROM_LOAD( "a51_01-1.ic", 0x0000, 0x4000, CRC(03c818ba) SHA1(80604726c647495ab76870806cd1fb448cffe34d) ) + + ROM_REGION( 0x00800, "bmcu:mcu", 0 ) // 68705 code + ROM_LOAD( "a54-09.53", 0x0000, 0x0800, CRC(0e8b8846) SHA1(a4a105462b0127229bb7edfadd2e581c7e40f1cc) ) // taken from lkage + + ROM_REGION( 0x10000, "gfx", 0 ) + ROM_LOAD( "a51_03-1.ic", 0x0000, 0x2000, CRC(99847f0a) SHA1(34ea492e82845d0366bd755ddf1cad7f574d867a) ) // tile + ROM_LOAD( "a51_07-1.ic", 0x2000, 0x2000, CRC(c9d01e5b) SHA1(16d689ccc9c3cb16e6b4d85f8e50386c78c439e5) ) // spr + ROM_LOAD( "a51_02-1.ic", 0x4000, 0x2000, CRC(28bbf964) SHA1(67fb767549d7326133c630f424703abe2b14273d) ) // tile + ROM_LOAD( "a51_06-1.ic", 0x6000, 0x2000, CRC(d16c7c95) SHA1(f3cfc995cc072311b3bd831b69ccb229e2734f53) ) // spr + ROM_LOAD( "a51_05-1.ic", 0x8000, 0x2000, CRC(38bb3ad0) SHA1(9c24d705e55acaaa99fbb39e06486ca932bda796) ) // tile + ROM_LOAD( "a51_09-1.ic", 0xa000, 0x2000, CRC(40fd3d86) SHA1(f92156e5e44483b2683457166cb5b9cfc7fbbf14) ) // spr + ROM_LOAD( "a51_04-1.ic", 0xc000, 0x2000, CRC(8e132cc6) SHA1(c7b196e6b8c3b6841a1f4ca0904597085a53cc25) ) // tile + ROM_LOAD( "a51_08-1.ic", 0xe000, 0x2000, CRC(2ab68af8) SHA1(6dd91311f2344936590577440898da5f26e35880) ) // spr + + ROM_REGION( 0x4000, "data", 0 ) + ROM_LOAD( "a51_14.ic", 0x0000, 0x4000, CRC(493e76d8) SHA1(13c6160edd94ba2801fd89bb33bcae3a1e3454ff) ) +ROM_END + ROM_START( lkageb ) ROM_REGION( 0x10000, "maincpu", 0 ) // Z80 code ROM_LOAD( "ic37_1", 0x0000, 0x8000, CRC(05694f7b) SHA1(08a3796d6cf04d64db52ed8208a51084c420e10a) ) @@ -1141,31 +1265,6 @@ ROM_START( lkageb4 ) ROM_END -ROM_START( lkage5232 ) - ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF ) // Z80 code - ROM_LOAD( "a51_11-2.ic", 0x0000, 0x4000, CRC(540fdb1f) SHA1(11d2a5b56d6d72458816aaf7687e490126b468cc) ) - ROM_LOAD( "a51_12-2.ic", 0x4000, 0x4000, CRC(a625a4b8) SHA1(417e7590f98eadc71cbed749350d6d3a1c1fd413) ) - ROM_LOAD( "a51_13-2.ic", 0x8000, 0x4000, CRC(aba8c6a3) SHA1(6723138f54a06d3e4719a43e8e3f11b3cabfb6f7) ) - ROM_LOAD( "a51_10-2.ic", 0xc000, 0x2000, CRC(f6243d5c) SHA1(7b2810afe9c128a290f15c6ea1a6a1c2757ddf55) ) - - ROM_REGION( 0x10000, "audiocpu", 0 ) // Z80 code - ROM_LOAD( "a51_01-1.ic", 0x0000, 0x4000, CRC(03c818ba) SHA1(80604726c647495ab76870806cd1fb448cffe34d) ) - ROM_FILL( 0xe000, 0x2000, 0xff ) // diagnostics ROM - - ROM_REGION( 0x10000, "gfx", 0 ) - ROM_LOAD( "a51_03-1.ic", 0x0000, 0x2000, CRC(99847f0a) SHA1(34ea492e82845d0366bd755ddf1cad7f574d867a) ) // tile - ROM_LOAD( "a51_07-1.ic", 0x2000, 0x2000, CRC(c9d01e5b) SHA1(16d689ccc9c3cb16e6b4d85f8e50386c78c439e5) ) // spr - ROM_LOAD( "a51_02-1.ic", 0x4000, 0x2000, CRC(28bbf964) SHA1(67fb767549d7326133c630f424703abe2b14273d) ) // tile - ROM_LOAD( "a51_06-1.ic", 0x6000, 0x2000, CRC(d16c7c95) SHA1(f3cfc995cc072311b3bd831b69ccb229e2734f53) ) // spr - ROM_LOAD( "a51_05-1.ic", 0x8000, 0x2000, CRC(38bb3ad0) SHA1(9c24d705e55acaaa99fbb39e06486ca932bda796) ) // tile - ROM_LOAD( "a51_09-1.ic", 0xa000, 0x2000, CRC(40fd3d86) SHA1(f92156e5e44483b2683457166cb5b9cfc7fbbf14) ) // spr - ROM_LOAD( "a51_04-1.ic", 0xc000, 0x2000, CRC(8e132cc6) SHA1(c7b196e6b8c3b6841a1f4ca0904597085a53cc25) ) // tile - ROM_LOAD( "a51_08-1.ic", 0xe000, 0x2000, CRC(2ab68af8) SHA1(6dd91311f2344936590577440898da5f26e35880) ) // spr - - ROM_REGION( 0x4000, "data", 0 ) - ROM_LOAD( "a51_14.ic", 0x0000, 0x4000, CRC(493e76d8) SHA1(13c6160edd94ba2801fd89bb33bcae3a1e3454ff) ) -ROM_END - /* Bygone Taito, 1985? @@ -1277,96 +1376,25 @@ ROM_START( bygone ) ROM_LOAD( "a53_04.ic87", 0xc000, 0x4000, CRC(65af72d3) SHA1(759a1dd7548075630ddb9c692bdb32ad4712c579) ) ROM_REGION( 0x0400, "proms", 0 ) - ROM_LOAD( "a54-10.ic2", 0x0000, 0x0400, CRC(369722d9) SHA1(2df9932ad8ce87c0a9d2c89222a4cec12c29046d) ) // unknown + ROM_LOAD( "a54-10.ic2", 0x0000, 0x0400, CRC(369722d9) SHA1(2df9932ad8ce87c0a9d2c89222a4cec12c29046d) ) // unknown ROM_END - -uint8_t lkage_state::mcu_status_r() -{ - // bit 0 = when 1, MCU is ready to receive data from main CPU - // bit 1 = when 1, MCU has sent data to the main CPU - return - ((CLEAR_LINE == m_bmcu->host_semaphore_r()) ? 0x01 : 0x00) | - ((CLEAR_LINE != m_bmcu->mcu_semaphore_r()) ? 0x02 : 0x00); -} - -// Note: This probably uses another MCU program, which is undumped. - -uint8_t lkage_state::fake_mcu_r() -{ - int result = 0; - - switch (m_mcu_val) - { - // These are for the attract mode - case 0x01: - result = m_mcu_val - 1; - break; - - case 0x90: - result = m_mcu_val + 0x43; - break; - - // Gameplay Protection, checked in this order at a start of a play - case 0xa6: - result = m_mcu_val + 0x27; - break; - - case 0x34: - result = m_mcu_val + 0x7f; - break; - - case 0x48: - result = m_mcu_val + 0xb7; - break; - - default: - result = m_mcu_val; - break; - } - return result; -} - -void lkage_state::fake_mcu_w(uint8_t data) -{ - m_mcu_val = data; -} - -uint8_t lkage_state::fake_status_r() -{ - return m_mcu_ready; -} - -void lkage_state::init_lkage() -{ - m_sprite_dx = 0; - - m_sprite_offset = 0; -} - -void lkage5232_state::init_lkage5232() -{ - init_lkage(); - - m_sprite_offset = 24; -} - -void lkage_state::init_bygone() -{ - m_sprite_dx = 1; - - m_sprite_offset = 0; -} - } // anonymous namespace -GAME( 1984, lkage, 0, lkage, lkage, lkage_state, init_lkage, ROT0, "Taito Corporation", "The Legend of Kage", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) -GAME( 1984, lkageo, lkage, lkage, lkage, lkage_state, init_lkage, ROT0, "Taito Corporation", "The Legend of Kage (older)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) -GAME( 1984, lkageoo, lkage, lkage, lkage, lkage_state, init_lkage, ROT0, "Taito Corporation", "The Legend of Kage (oldest)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) -GAME( 1984, lkageb, lkage, lkageb, lkageb, lkage_state, init_lkage, ROT0, "bootleg", "The Legend of Kage (bootleg set 1)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) -GAME( 1984, lkageb2, lkage, lkageb, lkageb, lkage_state, init_lkage, ROT0, "bootleg", "The Legend of Kage (bootleg set 2)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) -GAME( 1984, lkageb3, lkage, lkageb, lkageb, lkage_state, init_lkage, ROT0, "bootleg", "The Legend of Kage (bootleg set 3)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) -GAME( 1984, lkageb4, lkage, lkageb, lkageb, lkage_state, init_lkage, ROT0, "bootleg", "The Legend of Kage (bootleg set 4)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) -GAME( 1984, lkage5232, lkage, lkage5232, lkage, lkage5232_state, init_lkage5232, ROT0, "Taito Corporation", "The Legend of Kage (MSM5232 version)", MACHINE_NOT_WORKING | MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) // attract is broken, reads and writes from/to MCU addresses -GAME( 1985, bygone, 0, lkage, bygone, lkage_state, init_bygone, ROT0, "Taito Corporation", "Bygone (prototype)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) + +/******************************************************************************* + Game drivers +*******************************************************************************/ + +// YEAR NAME PARENT MACHINE INPUT CLASS INIT SCREEN COMPANY FULLNAME FLAGS +GAME( 1984, lkage, 0, lkage, lkage, lkage_state, empty_init, ROT0, "Taito Corporation", "The Legend of Kage", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) +GAME( 1984, lkageo, lkage, lkage, lkage, lkage_state, empty_init, ROT0, "Taito Corporation", "The Legend of Kage (older)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) +GAME( 1984, lkageo2, lkage, lkage, lkage, lkage_state, empty_init, ROT0, "Taito Corporation", "The Legend of Kage (oldest)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) +GAME( 1984, lkagem, lkage, lkagem, lkage, lkagem_state, empty_init, ROT0, "Taito Corporation", "The Legend of Kage (MSM5232 sound)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) +GAME( 1984, lkageb, lkage, lkageb, lkageb, lkage_state, empty_init, ROT0, "bootleg", "The Legend of Kage (bootleg set 1)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) +GAME( 1984, lkageb2, lkage, lkageb, lkageb, lkage_state, empty_init, ROT0, "bootleg", "The Legend of Kage (bootleg set 2)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) +GAME( 1984, lkageb3, lkage, lkageb, lkageb, lkage_state, empty_init, ROT0, "bootleg", "The Legend of Kage (bootleg set 3)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) +GAME( 1984, lkageb4, lkage, lkageb, lkageb, lkage_state, empty_init, ROT0, "bootleg", "The Legend of Kage (bootleg set 4)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) + +GAME( 1985, bygone, 0, lkage, bygone, lkage_state, init_bygone, ROT0, "Taito Corporation", "Bygone (prototype)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )