summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2026-02-01 23:43:45 +0100
committer hap <happppp@users.noreply.github.com>2026-02-01 23:43:45 +0100
commitec17cdf7d34bf9cbb3e173205753547fc4205777 (patch)
tree2981d5a6913a51ce227ad5cbdad98453b578742b
parent178fd5bd96109352b1bf68df339cbd40aeaad10d (diff)
lwings: make spriteram size same for all games, add sprite dma delay, small cleanup
-rw-r--r--src/mame/capcom/lwings.cpp463
1 files changed, 210 insertions, 253 deletions
diff --git a/src/mame/capcom/lwings.cpp b/src/mame/capcom/lwings.cpp
index dfb9e2c0d3c..e7d416b70b2 100644
--- a/src/mame/capcom/lwings.cpp
+++ b/src/mame/capcom/lwings.cpp
@@ -24,7 +24,9 @@ Notes:
Avengers has a protection chip underneath the sound module. The protection
is extensive: palette data, calculates player movement, even a hand in the
-sound. The Trojan schematics also include the MCU, but the PCB doesn't?
+sound. The PCB has wiremods connected to MREQ and WAIT for keeping the Z80
+in sync with the MCU during comms. The Trojan schematics also include the MCU,
+but the PCB doesn't?
avengers061gre2: corrupted graphics in Avengers' ending not fixed. This bug
is not in the Japanese set "Buraiken".
@@ -33,16 +35,12 @@ image are just not present in the US version, replaced by more tiles
for the title animation. The tile map ROM is the same between the two
versions.
-trojan37b1gre: stage 2-1 boss x flip glitches not fixed. This could be a
-side effect of sprite RAM buffering. Suggest buffering on-screen content
-instead of sprite memory.
-
Previous clock settings were too low. Sometimes Avengers and Trojan could
not finish clearing VRAM before a new frame is drawn and left behind
screen artifacts. Avengers' second CPU was forced to pre-empt during
soundlatch operations, resulting in double or missing sound effects.
-Trojan (Romstar) Manual has some bonus live values as well as locations
+Trojan (Romstar) Manual has some bonus life values as well as locations
which do no jive with actual emulation. One can only assume this means
the manual is incorrect and software was adjusted later but the game could
use some PCB comparisons of DIP selections to be certain.
@@ -124,7 +122,6 @@ private:
required_memory_bank m_bank1;
optional_memory_bank m_bank2;
optional_memory_bank m_samplebank;
- memory_access<16, 0, 0, ENDIANNESS_LITTLE>::specific m_maincpu_program;
// video-related
tilemap_t *m_fg_tilemap = nullptr;
@@ -135,16 +132,14 @@ private:
uint8_t m_scroll_y[2]{};
// misc
- uint8_t m_adpcm = 0U;
uint8_t m_nmi_mask = 0U;
uint8_t m_sprbank = 0;
+ emu_timer *m_sprite_dma_timer = nullptr;
// MCU-related (avengers)
uint8_t m_mcu_data[2]{};
uint8_t m_mcu_control = 0xff;
- void avengers_adpcm_w(uint8_t data) { m_adpcm = data; }
- uint8_t avengers_adpcm_r() { return m_adpcm; }
void lwings_bankswitch_w(uint8_t data);
uint8_t avengers_soundlatch_ack_r();
void lwings_fgvideoram_w(offs_t offset, uint8_t data);
@@ -153,7 +148,9 @@ private:
void lwings_bg1_scrolly_w(offs_t offset, uint8_t data);
void trojan_bg2_scrollx_w(uint8_t data);
void trojan_bg2_image_w(uint8_t data);
- void sprite_dma_w(uint8_t data);
+ void sprite_dma_trigger_w(uint8_t data);
+ void sprite_dma_start_w(int state);
+ TIMER_CALLBACK_MEMBER(sprite_dma_end);
void msm5205_w(uint8_t data);
void fball_oki_bank_w(uint8_t data);
@@ -173,13 +170,10 @@ private:
uint32_t screen_update_lwings(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
uint32_t screen_update_trojan(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
TIMER_DEVICE_CALLBACK_MEMBER(scanline);
- bool is_sprite_on(uint8_t const *buffered_spriteram, int offs);
void lwings_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
void trojan_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
- void avengers_adpcm_io_map(address_map &map) ATTR_COLD;
void avengers_map(address_map &map) ATTR_COLD;
- void buraikenb_map(address_map &map) ATTR_COLD;
void fball_map(address_map &map) ATTR_COLD;
void fball_oki_map(address_map &map) ATTR_COLD;
void fball_sound_map(address_map &map) ATTR_COLD;
@@ -283,92 +277,78 @@ VIDEO_START_MEMBER(lwings_state,trojan)
*
*************************************/
-inline bool lwings_state::is_sprite_on(uint8_t const *buffered_spriteram, int offs)
-{
- int const sx = buffered_spriteram[offs + 3] - 0x100 * (buffered_spriteram[offs + 1] & 0x01);
- int const sy = buffered_spriteram[offs + 2];
-
- return sx || sy;
-}
-
void lwings_state::lwings_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
- uint8_t const *const buffered_spriteram = m_spriteram->buffer();
+ uint8_t const *const spriteram = m_spriteram->buffer();
for (int offs = m_spriteram->bytes() - 4; offs >= 0; offs -= 4)
{
- if (is_sprite_on(buffered_spriteram, offs))
+ int sx = spriteram[offs + 3] - 0x100 * (spriteram[offs + 1] & 0x01);
+ int sy = spriteram[offs + 2];
+ if (sy > 0xf8)
+ sy -= 0x100;
+ int code = spriteram[offs] | (spriteram[offs + 1] & 0xc0) << 2;
+ int color = (spriteram[offs + 1] & 0x38) >> 3;
+ int flipx = spriteram[offs + 1] & 0x02;
+ int flipy = spriteram[offs + 1] & 0x04;
+
+ if (flip_screen())
{
- int sx = buffered_spriteram[offs + 3] - 0x100 * (buffered_spriteram[offs + 1] & 0x01);
- int sy = buffered_spriteram[offs + 2];
- if (sy > 0xf8)
- sy -= 0x100;
- int code = buffered_spriteram[offs] | (buffered_spriteram[offs + 1] & 0xc0) << 2;
- int color = (buffered_spriteram[offs + 1] & 0x38) >> 3;
- int flipx = buffered_spriteram[offs + 1] & 0x02;
- int flipy = buffered_spriteram[offs + 1] & 0x04;
-
- if (flip_screen())
- {
- sx = 240 - sx;
- sy = 240 - sy;
- flipx = !flipx;
- flipy = !flipy;
- }
-
- m_gfxdecode->gfx(2)->transpen(
- bitmap, cliprect,
- code + (m_sprbank * 0x400), color,
- flipx, flipy, sx, sy,
- 15);
+ sx = 240 - sx;
+ sy = 240 - sy;
+ flipx = !flipx;
+ flipy = !flipy;
}
+
+ m_gfxdecode->gfx(2)->transpen(
+ bitmap, cliprect,
+ code + (m_sprbank * 0x400), color,
+ flipx, flipy, sx, sy,
+ 15);
}
}
void lwings_state::trojan_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
- uint8_t const *const buffered_spriteram = m_spriteram->buffer();
+ uint8_t const *const spriteram = m_spriteram->buffer();
for (int offs = m_spriteram->bytes() - 4; offs >= 0; offs -= 4)
{
- if (is_sprite_on(buffered_spriteram, offs))
+ int sx = spriteram[offs + 3] - 0x100 * (spriteram[offs + 1] & 0x01);
+ int sy = spriteram[offs + 2];
+ if (sy > 0xf8)
+ sy -= 0x100;
+ int code = spriteram[offs] | bitswap<3>(spriteram[offs + 1],7,5,6) << 8;
+ int color = (spriteram[offs + 1] & 0x0e) >> 1;
+
+ // flipping differs between horizontal/vertical orientation
+ int flipx, flipy;
+ if ((machine().system().flags & machine_flags::MASK_ORIENTATION) == 0)
+ {
+ // Trojan
+ flipx = spriteram[offs + 1] & 0x10;
+ flipy = 1;
+ }
+ else
+ {
+ // Avengers
+ flipx = 0;
+ flipy = ~spriteram[offs + 1] & 0x10;
+ }
+
+ if (flip_screen())
{
- int sx = buffered_spriteram[offs + 3] - 0x100 * (buffered_spriteram[offs + 1] & 0x01);
- int sy = buffered_spriteram[offs + 2];
- if (sy > 0xf8)
- sy -= 0x100;
- int code = buffered_spriteram[offs] | bitswap<3>(buffered_spriteram[offs + 1],7,5,6) << 8;
- int color = (buffered_spriteram[offs + 1] & 0x0e) >> 1;
-
- // flipping differs between horizontal/vertical orientation
- int flipx, flipy;
- if ((machine().system().flags & machine_flags::MASK_ORIENTATION) == 0)
- {
- // Trojan
- flipx = buffered_spriteram[offs + 1] & 0x10;
- flipy = 1;
- }
- else
- {
- // Avengers
- flipx = 0;
- flipy = ~buffered_spriteram[offs + 1] & 0x10;
- }
-
- if (flip_screen())
- {
- sx = 240 - sx;
- sy = 240 - sy;
- flipx = !flipx;
- flipy = !flipy;
- }
-
- m_gfxdecode->gfx(2)->transpen(
- bitmap, cliprect,
- code, color,
- flipx, flipy, sx, sy,
- 15);
+ sx = 240 - sx;
+ sy = 240 - sy;
+ flipx = !flipx;
+ flipy = !flipy;
}
+
+ m_gfxdecode->gfx(2)->transpen(
+ bitmap, cliprect,
+ code, color,
+ flipx, flipy, sx, sy,
+ 15);
}
}
@@ -440,12 +420,6 @@ void lwings_state::trojan_bg2_image_w(uint8_t data)
}
}
-void lwings_state::sprite_dma_w(uint8_t data)
-{
- if (m_screen->vblank())
- m_spriteram->copy();
-}
-
void lwings_state::lwings_bankswitch_w(uint8_t data)
{
@@ -477,6 +451,30 @@ void lwings_state::msm5205_w(uint8_t data)
m_msm->data_w(data & 0xf);
}
+
+void lwings_state::sprite_dma_trigger_w(uint8_t data)
+{
+ if (m_screen->vblank())
+ m_maincpu->set_input_line(Z80_INPUT_LINE_BUSRQ, ASSERT_LINE);
+}
+
+void lwings_state::sprite_dma_start_w(int state)
+{
+ if (state)
+ {
+ m_spriteram->copy();
+
+ // measured 128.4us on avengers, so 2 6MHz cycles per byte
+ uint32_t clocks = m_spriteram->bytes() * 2;
+ m_sprite_dma_timer->adjust(attotime::from_ticks(clocks, 12_MHz_XTAL / 2));
+ }
+}
+
+TIMER_CALLBACK_MEMBER(lwings_state::sprite_dma_end)
+{
+ m_maincpu->set_input_line(Z80_INPUT_LINE_BUSRQ, CLEAR_LINE);
+}
+
TIMER_DEVICE_CALLBACK_MEMBER(lwings_state::scanline)
{
const int scanline = param;
@@ -568,7 +566,7 @@ uint8_t lwings_state::avengers_soundlatch_ack_r()
*
*************************************/
-void lwings_state::buraikenb_map(address_map &map)
+void lwings_state::lwings_map(address_map &map)
{
map.unmap_value_high();
map(0x0000, 0x7fff).rom();
@@ -580,40 +578,6 @@ void lwings_state::buraikenb_map(address_map &map)
map(0xe800, 0xefff).ram().w(FUNC(lwings_state::lwings_bg1videoram_w)).share("bg1videoram");
map(0xf000, 0xf3ff).writeonly().w(m_palette, FUNC(palette_device::write8_ext)).share("palette_ext");
map(0xf400, 0xf7ff).writeonly().w(m_palette, FUNC(palette_device::write8)).share("palette");
- map(0xf800, 0xf801).w(FUNC(lwings_state::lwings_bg1_scrollx_w));
- map(0xf802, 0xf803).w(FUNC(lwings_state::lwings_bg1_scrolly_w));
- map(0xf804, 0xf804).w(FUNC(lwings_state::trojan_bg2_scrollx_w));
- map(0xf805, 0xf805).w(FUNC(lwings_state::trojan_bg2_image_w));
-
- map(0xf808, 0xf808).portr("SERVICE").w(FUNC(lwings_state::sprite_dma_w));
- map(0xf809, 0xf809).portr("P1");
- map(0xf80a, 0xf80a).portr("P2");
- map(0xf80b, 0xf80b).portr("DSWB");
- map(0xf80c, 0xf80c).portr("DSWA").w(m_soundlatch, FUNC(generic_latch_8_device::write));
- map(0xf80d, 0xf80d).w(FUNC(lwings_state::avengers_adpcm_w));
- map(0xf80e, 0xf80e).w(FUNC(lwings_state::lwings_bankswitch_w));
-}
-
-void lwings_state::avengers_map(address_map &map)
-{
- buraikenb_map(map);
-
- map(0xf809, 0xf809).w(m_mculatch[0], FUNC(generic_latch_8_device::write));
- map(0xf80c, 0xf80c).w(m_mculatch[1], FUNC(generic_latch_8_device::write));
- map(0xf80d, 0xf80d).r(m_mculatch[2], FUNC(generic_latch_8_device::read));
-}
-
-void lwings_state::lwings_map(address_map &map)
-{
- map.unmap_value_high();
- map(0x0000, 0x7fff).rom();
- map(0x8000, 0xbfff).bankr("bank1");
- map(0xc000, 0xddff).ram();
- map(0xde00, 0xdfff).ram().share("spriteram");
- map(0xe000, 0xe7ff).ram().w(FUNC(lwings_state::lwings_fgvideoram_w)).share("fgvideoram");
- map(0xe800, 0xefff).ram().w(FUNC(lwings_state::lwings_bg1videoram_w)).share("bg1videoram");
- map(0xf000, 0xf3ff).writeonly().w(m_palette, FUNC(palette_device::write8_ext)).share("palette_ext");
- map(0xf400, 0xf7ff).writeonly().w(m_palette, FUNC(palette_device::write8)).share("palette");
map(0xf808, 0xf808).portr("SERVICE");
map(0xf809, 0xf809).portr("P1");
@@ -622,10 +586,20 @@ void lwings_state::lwings_map(address_map &map)
map(0xf80b, 0xf80b).portr("DSWA");
map(0xf80a, 0xf80b).w(FUNC(lwings_state::lwings_bg1_scrolly_w));
map(0xf80c, 0xf80c).portr("DSWB").w(m_soundlatch, FUNC(generic_latch_8_device::write));
- map(0xf80d, 0xf80d).w(FUNC(lwings_state::sprite_dma_w));
+ map(0xf80d, 0xf80d).w(FUNC(lwings_state::sprite_dma_trigger_w));
map(0xf80e, 0xf80e).w(FUNC(lwings_state::lwings_bankswitch_w));
}
+void lwings_state::lwings_sound_map(address_map &map)
+{
+ map(0x0000, 0x7fff).rom();
+ map(0xc000, 0xc7ff).ram();
+ map(0xc800, 0xc800).r(m_soundlatch, FUNC(generic_latch_8_device::read));
+ map(0xe000, 0xe001).w("2203a", FUNC(ym2203_device::write));
+ map(0xe002, 0xe003).w("2203b", FUNC(ym2203_device::write));
+ map(0xe006, 0xe006).r(FUNC(lwings_state::avengers_soundlatch_ack_r)).nopw();
+}
+
void lwings_state::trojan_map(address_map &map)
{
map.unmap_value_high();
@@ -638,28 +612,27 @@ void lwings_state::trojan_map(address_map &map)
map(0xe800, 0xefff).ram().w(FUNC(lwings_state::lwings_bg1videoram_w)).share("bg1videoram");
map(0xf000, 0xf3ff).writeonly().w(m_palette, FUNC(palette_device::write8_ext)).share("palette_ext");
map(0xf400, 0xf7ff).writeonly().w(m_palette, FUNC(palette_device::write8)).share("palette");
-
map(0xf800, 0xf801).w(FUNC(lwings_state::lwings_bg1_scrollx_w));
map(0xf802, 0xf803).w(FUNC(lwings_state::lwings_bg1_scrolly_w));
map(0xf804, 0xf804).w(FUNC(lwings_state::trojan_bg2_scrollx_w));
map(0xf805, 0xf805).w(FUNC(lwings_state::trojan_bg2_image_w));
- map(0xf808, 0xf808).portr("SERVICE").w(FUNC(lwings_state::sprite_dma_w));
+
+ map(0xf808, 0xf808).portr("SERVICE").w(FUNC(lwings_state::sprite_dma_trigger_w));
map(0xf809, 0xf809).portr("P1");
map(0xf80a, 0xf80a).portr("P2");
- map(0xf80b, 0xf80b).portr("DSWA");
- map(0xf80c, 0xf80c).portr("DSWB").w(m_soundlatch, FUNC(generic_latch_8_device::write));
+ map(0xf80b, 0xf80b).portr("DSWB");
+ map(0xf80c, 0xf80c).portr("DSWA").w(m_soundlatch, FUNC(generic_latch_8_device::write));
map(0xf80d, 0xf80d).w("soundlatch2", FUNC(generic_latch_8_device::write));
map(0xf80e, 0xf80e).w(FUNC(lwings_state::lwings_bankswitch_w));
}
-void lwings_state::lwings_sound_map(address_map &map)
+void lwings_state::avengers_map(address_map &map)
{
- map(0x0000, 0x7fff).rom();
- map(0xc000, 0xc7ff).ram();
- map(0xc800, 0xc800).r(m_soundlatch, FUNC(generic_latch_8_device::read));
- map(0xe000, 0xe001).w("2203a", FUNC(ym2203_device::write));
- map(0xe002, 0xe003).w("2203b", FUNC(ym2203_device::write));
- map(0xe006, 0xe006).r(FUNC(lwings_state::avengers_soundlatch_ack_r)).nopw();
+ trojan_map(map);
+
+ map(0xf809, 0xf809).w(m_mculatch[0], FUNC(generic_latch_8_device::write));
+ map(0xf80c, 0xf80c).w(m_mculatch[1], FUNC(generic_latch_8_device::write));
+ map(0xf80d, 0xf80d).r(m_mculatch[2], FUNC(generic_latch_8_device::read));
}
@@ -669,7 +642,8 @@ void lwings_state::fball_map(address_map &map)
map(0x0000, 0x7fff).bankr("bank2");
map(0x8000, 0xbfff).bankr("bank1");
map(0xc000, 0xddff).ram();
- map(0xde00, 0xdfff).ram().share("spriteram");
+ map(0xde00, 0xdf7f).ram().share("spriteram");
+ map(0xdf80, 0xdfff).ram();
map(0xe000, 0xe7ff).ram().w(FUNC(lwings_state::lwings_fgvideoram_w)).share("fgvideoram");
map(0xe800, 0xefff).ram().w(FUNC(lwings_state::lwings_bg1videoram_w)).share("bg1videoram");
map(0xf000, 0xf3ff).writeonly().w(m_palette, FUNC(palette_device::write8_ext)).share("palette_ext");
@@ -682,7 +656,7 @@ void lwings_state::fball_map(address_map &map)
map(0xf80b, 0xf80b).portr("DSWA");
map(0xf80a, 0xf80b).w(FUNC(lwings_state::lwings_bg1_scrolly_w));
map(0xf80c, 0xf80c).w(m_soundlatch, FUNC(generic_latch_8_device::write));
- map(0xf80d, 0xf80d).portr("P3").w(FUNC(lwings_state::sprite_dma_w));
+ map(0xf80d, 0xf80d).portr("P3").w(FUNC(lwings_state::sprite_dma_trigger_w));
map(0xf80e, 0xf80e).portr("P4");
map(0xf80e, 0xf80e).w(FUNC(lwings_state::lwings_bankswitch_w));
@@ -716,13 +690,6 @@ void lwings_state::trojan_adpcm_map(address_map &map)
map(0x0000, 0xffff).rom().nopw();
}
-void lwings_state::avengers_adpcm_io_map(address_map &map)
-{
- map.global_mask(0xff);
- map(0x00, 0x00).r(FUNC(lwings_state::avengers_adpcm_r));
- map(0x01, 0x01).w(FUNC(lwings_state::msm5205_w));
-}
-
void lwings_state::trojan_adpcm_io_map(address_map &map)
{
map.global_mask(0xff);
@@ -896,57 +863,6 @@ static INPUT_PORTS_START( lwingsb )
PORT_DIPSETTING( 0x00, "5" )
INPUT_PORTS_END
-
-static INPUT_PORTS_START( fball )
- PORT_INCLUDE( lwings_generic )
-
- PORT_MODIFY("SERVICE")
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START3 )
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START4 )
-
- PORT_START("DSWA") // only one set of dipswitches
- PORT_DIPNAME( 0x01, 0x01, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SWA:1")
- PORT_DIPSETTING( 0x01, DEF_STR( Easy ) )
- PORT_DIPSETTING( 0x00, DEF_STR( Hard ) ) // smaller starting explosion
- PORT_DIPNAME( 0x06, 0x04, DEF_STR( Lives ) ) PORT_DIPLOCATION("SWA:2,3")
- PORT_DIPSETTING( 0x00, "1" )
- PORT_DIPSETTING( 0x02, "2" )
- PORT_DIPSETTING( 0x04, "3" )
- PORT_DIPSETTING( 0x06, "4" )
- PORT_DIPNAME( 0x18, 0x08, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SWA:4,5")
- PORT_DIPSETTING( 0x00, DEF_STR( 2C_1C ) )
- PORT_DIPSETTING( 0x08, DEF_STR( 1C_1C ) )
- PORT_DIPSETTING( 0x10, DEF_STR( 1C_2C ) )
- PORT_DIPSETTING( 0x18, DEF_STR( 1C_4C ) )
- PORT_DIPNAME( 0x20, 0x20, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SWA:6")
- PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x00, DEF_STR( On ) )
- PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unused ) ) PORT_DIPLOCATION("SWA:7") // 'X' in test mode, presumably unused
- PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x00, DEF_STR( On ) )
- PORT_SERVICE_DIPLOC( 0x80, IP_ACTIVE_HIGH, "SWA:8" )
-
- PORT_START("P3")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(3)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(3)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(3)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(3)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(3)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* probably unused */
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* probably unused */
-
- PORT_START("P4")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(4)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(4)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(4)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(4)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(4)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(4)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* probably unused */
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* probably unused */
-INPUT_PORTS_END
-
/* Trojan with level selection - starting level dip switches not used */
static INPUT_PORTS_START( trojanls )
PORT_INCLUDE( lwings_generic )
@@ -959,27 +875,7 @@ static INPUT_PORTS_START( trojanls )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL
- /* DSW tags inverted to use lwings map */
PORT_START("DSWA")
- PORT_DIPNAME( 0x03, 0x00, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("SWB:1,2")
- PORT_DIPSETTING( 0x00, "Upright 1 Player" )
- PORT_DIPSETTING( 0x02, "Upright 2 Players" )
- PORT_DIPSETTING( 0x03, DEF_STR( Cocktail ) )
-/* 0x01 same as 0x02 or 0x03 */
- PORT_DIPNAME( 0x1c, 0x1c, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("SWB:3,4,5")
- PORT_DIPSETTING( 0x10, "20000 60000" )
- PORT_DIPSETTING( 0x0c, "20000 70000" )
- PORT_DIPSETTING( 0x08, "20000 80000" )
- PORT_DIPSETTING( 0x1c, "30000 60000" )
- PORT_DIPSETTING( 0x18, "30000 70000" )
- PORT_DIPSETTING( 0x14, "30000 80000" )
- PORT_DIPSETTING( 0x04, "40000 80000" )
- PORT_DIPSETTING( 0x00, DEF_STR( None ) )
- PORT_DIPUNUSED_DIPLOC( 0x20, 0x20, "SWB:6" )
- PORT_DIPUNUSED_DIPLOC( 0x40, 0x40, "SWB:7" )
- PORT_DIPUNUSED_DIPLOC( 0x80, 0x80, "SWB:8" )
-
- PORT_START("DSWB")
PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SWA:1,2")
PORT_DIPSETTING( 0x00, DEF_STR( 2C_1C ) )
PORT_DIPSETTING( 0x03, DEF_STR( 1C_1C ) )
@@ -1001,12 +897,31 @@ static INPUT_PORTS_START( trojanls )
PORT_DIPNAME( 0x80, 0x80, DEF_STR( Allow_Continue ) ) PORT_DIPLOCATION("SWA:8")
PORT_DIPSETTING( 0x00, DEF_STR( No ) )
PORT_DIPSETTING( 0x80, DEF_STR( Yes ) )
+
+ PORT_START("DSWB")
+ PORT_DIPNAME( 0x03, 0x00, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("SWB:1,2")
+ PORT_DIPSETTING( 0x00, "Upright 1 Player" )
+ PORT_DIPSETTING( 0x02, "Upright 2 Players" )
+ PORT_DIPSETTING( 0x03, DEF_STR( Cocktail ) )
+ // 0x01 same as 0x02 or 0x03
+ PORT_DIPNAME( 0x1c, 0x1c, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("SWB:3,4,5")
+ PORT_DIPSETTING( 0x10, "20000 60000" )
+ PORT_DIPSETTING( 0x0c, "20000 70000" )
+ PORT_DIPSETTING( 0x08, "20000 80000" )
+ PORT_DIPSETTING( 0x1c, "30000 60000" )
+ PORT_DIPSETTING( 0x18, "30000 70000" )
+ PORT_DIPSETTING( 0x14, "30000 80000" )
+ PORT_DIPSETTING( 0x04, "40000 80000" )
+ PORT_DIPSETTING( 0x00, DEF_STR( None ) )
+ PORT_DIPUNUSED_DIPLOC( 0x20, 0x20, "SWB:6" )
+ PORT_DIPUNUSED_DIPLOC( 0x40, 0x40, "SWB:7" )
+ PORT_DIPUNUSED_DIPLOC( 0x80, 0x80, "SWB:8" )
INPUT_PORTS_END
static INPUT_PORTS_START( trojan )
PORT_INCLUDE( trojanls )
- PORT_MODIFY("DSWA")
+ PORT_MODIFY("DSWB")
PORT_DIPNAME( 0xe0, 0xe0, "Starting Level" ) PORT_DIPLOCATION("SWB:6,7,8")
PORT_DIPSETTING( 0xe0, "1" )
PORT_DIPSETTING( 0xc0, "2" )
@@ -1014,7 +929,7 @@ static INPUT_PORTS_START( trojan )
PORT_DIPSETTING( 0x80, "4" )
PORT_DIPSETTING( 0x60, "5" )
PORT_DIPSETTING( 0x40, "6" )
-/* 0x00 and 0x20 start at level 6 */
+ // 0x00 and 0x20 start at level 6
INPUT_PORTS_END
static INPUT_PORTS_START( avengers )
@@ -1068,6 +983,56 @@ static INPUT_PORTS_START( avengers )
PORT_DIPSETTING( 0x00, "6" )
INPUT_PORTS_END
+static INPUT_PORTS_START( fball )
+ PORT_INCLUDE( lwings_generic )
+
+ PORT_MODIFY("SERVICE")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START3 )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START4 )
+
+ PORT_START("DSWA") // only one set of dipswitches
+ PORT_DIPNAME( 0x01, 0x01, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SWA:1")
+ PORT_DIPSETTING( 0x01, DEF_STR( Easy ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( Hard ) ) // smaller starting explosion
+ PORT_DIPNAME( 0x06, 0x04, DEF_STR( Lives ) ) PORT_DIPLOCATION("SWA:2,3")
+ PORT_DIPSETTING( 0x00, "1" )
+ PORT_DIPSETTING( 0x02, "2" )
+ PORT_DIPSETTING( 0x04, "3" )
+ PORT_DIPSETTING( 0x06, "4" )
+ PORT_DIPNAME( 0x18, 0x08, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SWA:4,5")
+ PORT_DIPSETTING( 0x00, DEF_STR( 2C_1C ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( 1C_1C ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( 1C_2C ) )
+ PORT_DIPSETTING( 0x18, DEF_STR( 1C_4C ) )
+ PORT_DIPNAME( 0x20, 0x20, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SWA:6")
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unused ) ) PORT_DIPLOCATION("SWA:7") // 'X' in test mode, presumably unused
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_SERVICE_DIPLOC( 0x80, IP_ACTIVE_HIGH, "SWA:8" )
+
+ PORT_START("P3")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(3)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(3)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(3)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(3)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(3)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* probably unused */
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* probably unused */
+
+ PORT_START("P4")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(4)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(4)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(4)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(4)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(4)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(4)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* probably unused */
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* probably unused */
+INPUT_PORTS_END
+
/*************************************
*
@@ -1149,15 +1114,13 @@ GFXDECODE_END
void lwings_state::machine_start()
{
uint8_t *ROM = memregion("maincpu")->base();
-
m_bank1->configure_entries(0, 4, &ROM[0x10000], 0x4000);
- m_maincpu->space(AS_PROGRAM).specific(m_maincpu_program);
+ m_sprite_dma_timer = timer_alloc(FUNC(lwings_state::sprite_dma_end), this);
save_item(NAME(m_bg2_image));
save_item(NAME(m_scroll_x));
save_item(NAME(m_scroll_y));
- save_item(NAME(m_adpcm));
save_item(NAME(m_nmi_mask));
save_item(NAME(m_sprbank));
@@ -1215,7 +1178,6 @@ void lwings_state::machine_reset()
m_scroll_x[1] = 0;
m_scroll_y[0] = 0;
m_scroll_y[1] = 0;
- m_adpcm = 0;
}
void lwings_state::lwings(machine_config &config)
@@ -1223,6 +1185,7 @@ void lwings_state::lwings(machine_config &config)
// basic machine hardware
Z80(config, m_maincpu, 12_MHz_XTAL / 2); // verified on PCB
m_maincpu->set_addrmap(AS_PROGRAM, &lwings_state::lwings_map);
+ m_maincpu->busack_cb().set(FUNC(lwings_state::sprite_dma_start_w));
Z80(config, m_soundcpu, 12_MHz_XTAL / 4); // verified on PCB
m_soundcpu->set_addrmap(AS_PROGRAM, &lwings_state::lwings_sound_map);
@@ -1266,27 +1229,6 @@ void lwings_state::sectionz(machine_config &config)
m_maincpu->set_clock(12_MHz_XTAL / 4);
}
-void lwings_state::fball(machine_config &config)
-{
- lwings(config);
-
- // basic machine hardware
- m_maincpu->set_addrmap(AS_PROGRAM, &lwings_state::fball_map);
- m_soundcpu->set_addrmap(AS_PROGRAM, &lwings_state::fball_sound_map);
-
- // video hardware: the 16-pixel black border on left edge is correct, test mode actually uses that area
-
- // sound hardware
- m_soundlatch->set_separate_acknowledge(true);
-
- okim6295_device &oki(OKIM6295(config, "oki", 12_MHz_XTAL / 12, okim6295_device::PIN7_HIGH)); // clock frequency & pin 7 not verified
- oki.add_route(ALL_OUTPUTS, "mono", 1.0);
- oki.set_addrmap(0, &lwings_state::fball_oki_map);
-
- config.device_remove("2203a");
- config.device_remove("2203b");
-}
-
void lwings_state::trojan(machine_config &config)
{
lwings(config);
@@ -1321,8 +1263,9 @@ void lwings_state::avengers(machine_config &config)
trojan(config);
// basic machine hardware
- m_maincpu->set_clock(12_MHz_XTAL / 2);
- m_maincpu->z80_set_m1_cycles(4+2); // 2 WAIT states per M1? (needed to keep in sync with MCU)
+ m_maincpu->set_clock(12_MHz_XTAL / 2); // verified on PCB
+ m_maincpu->z80_set_memrq_cycles(3+1); // 1 WAIT state per MREQ (but not with RFSH)
+ m_maincpu->z80_set_m1_cycles(4+1); // "
m_maincpu->set_addrmap(AS_PROGRAM, &lwings_state::avengers_map);
I8751(config, m_mcu, 12_MHz_XTAL / 2);
@@ -1342,21 +1285,35 @@ void lwings_state::avengers(machine_config &config)
GENERIC_LATCH_8(config, m_mculatch[1]);
GENERIC_LATCH_8(config, m_mculatch[2]);
-
- m_adpcmcpu->set_addrmap(AS_IO, &lwings_state::avengers_adpcm_io_map);
}
void lwings_state::buraikenb(machine_config &config)
{
- avengers(config);
+ trojan(config);
+
+ // assume same maincpu clock as avengers (lots of slowdowns otherwise)
+ m_maincpu->set_clock(12_MHz_XTAL / 2);
+}
+
+void lwings_state::fball(machine_config &config)
+{
+ lwings(config);
// basic machine hardware
- m_maincpu->set_addrmap(AS_PROGRAM, &lwings_state::buraikenb_map);
+ m_maincpu->set_addrmap(AS_PROGRAM, &lwings_state::fball_map);
+ m_soundcpu->set_addrmap(AS_PROGRAM, &lwings_state::fball_sound_map);
+
+ // video hardware: the 16-pixel black border on left edge is correct, test mode actually uses that area
- config.device_remove("mcu");
- config.device_remove("mculatch0");
- config.device_remove("mculatch1");
- config.device_remove("mculatch2");
+ // sound hardware
+ m_soundlatch->set_separate_acknowledge(true);
+
+ okim6295_device &oki(OKIM6295(config, "oki", 12_MHz_XTAL / 12, okim6295_device::PIN7_HIGH)); // clock frequency & pin 7 not verified
+ oki.add_route(ALL_OUTPUTS, "mono", 1.0);
+ oki.set_addrmap(0, &lwings_state::fball_oki_map);
+
+ config.device_remove("2203a");
+ config.device_remove("2203b");
}