// license:BSD-3-Clause // copyright-holders:Paul Leaman /*************************************************************************** video.c Functions to emulate the video hardware of the machine. ***************************************************************************/ #include "emu.h" #include "includes/lwings.h" /*************************************************************************** Callbacks for the TileMap code ***************************************************************************/ TILEMAP_MAPPER_MEMBER(lwings_state::get_bg2_memory_offset) { return (row * 0x800) | (col * 2); } TILE_GET_INFO_MEMBER(lwings_state::get_fg_tile_info) { int code = m_fgvideoram[tile_index]; int color = m_fgvideoram[tile_index + 0x400]; SET_TILE_INFO_MEMBER(0, code + ((color & 0xc0) << 2), color & 0x0f, TILE_FLIPYX((color & 0x30) >> 4)); } TILE_GET_INFO_MEMBER(lwings_state::lwings_get_bg1_tile_info) { int code = m_bg1videoram[tile_index]; int color = m_bg1videoram[tile_index + 0x400]; SET_TILE_INFO_MEMBER(1, code + ((color & 0xe0) << 3), color & 0x07, TILE_FLIPYX((color & 0x18) >> 3)); } TILE_GET_INFO_MEMBER(lwings_state::trojan_get_bg1_tile_info) { int code = m_bg1videoram[tile_index]; int color = m_bg1videoram[tile_index + 0x400]; code += (color & 0xe0)<<3; SET_TILE_INFO_MEMBER(1, code, m_bg2_avenger_hw ? ((color & 7) ^ 6) : (color & 7), ((color & 0x10) ? TILE_FLIPX : 0)); tileinfo.group = (color & 0x08) >> 3; } TILE_GET_INFO_MEMBER(lwings_state::get_bg2_tile_info) { int code, color; uint8_t *rom = memregion("gfx5")->base(); int mask = memregion("gfx5")->bytes() - 1; tile_index = (tile_index + m_bg2_image * 0x20) & mask; code = rom[tile_index]; color = rom[tile_index + 1]; SET_TILE_INFO_MEMBER(3, code + ((color & 0x80) << 1), color & 0x07, TILE_FLIPYX((color & 0x30) >> 4)); } /*************************************************************************** Start the video hardware emulation. ***************************************************************************/ void lwings_state::video_start() { m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(lwings_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32); m_bg1_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(lwings_state::lwings_get_bg1_tile_info)), TILEMAP_SCAN_COLS, 16, 16, 32, 32); m_fg_tilemap->set_transparent_pen(3); } VIDEO_START_MEMBER(lwings_state,trojan) { m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(lwings_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32); m_bg1_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(lwings_state::trojan_get_bg1_tile_info)),TILEMAP_SCAN_COLS, 16, 16, 32, 32); m_bg2_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(lwings_state::get_bg2_tile_info)), tilemap_mapper_delegate(*this, FUNC(lwings_state::get_bg2_memory_offset)), 16, 16, 32, 16); m_fg_tilemap->set_transparent_pen(3); m_bg1_tilemap->set_transmask(0, 0xffff, 0x0001); // split type 0 is totally transparent in front half m_bg1_tilemap->set_transmask(1, 0xf07f, 0x0f81); // split type 1 has pens 7-11 opaque in front half m_bg2_avenger_hw = 0; m_spr_avenger_hw = 0; } VIDEO_START_MEMBER(lwings_state,avengers) { VIDEO_START_CALL_MEMBER(trojan); m_bg2_avenger_hw = 1; m_spr_avenger_hw = 1; } VIDEO_START_MEMBER(lwings_state,avengersb) { VIDEO_START_CALL_MEMBER(trojan); m_bg2_avenger_hw = 0; m_spr_avenger_hw = 1; } /*************************************************************************** Memory handlers ***************************************************************************/ WRITE8_MEMBER(lwings_state::lwings_fgvideoram_w) { m_fgvideoram[offset] = data; m_fg_tilemap->mark_tile_dirty(offset & 0x3ff); } WRITE8_MEMBER(lwings_state::lwings_bg1videoram_w) { m_bg1videoram[offset] = data; m_bg1_tilemap->mark_tile_dirty(offset & 0x3ff); } WRITE8_MEMBER(lwings_state::lwings_bg1_scrollx_w) { m_scroll_x[offset] = data; m_bg1_tilemap->set_scrollx(0, m_scroll_x[0] | (m_scroll_x[1] << 8)); } WRITE8_MEMBER(lwings_state::lwings_bg1_scrolly_w) { m_scroll_y[offset] = data; m_bg1_tilemap->set_scrolly(0, m_scroll_y[0] | (m_scroll_y[1] << 8)); } WRITE8_MEMBER(lwings_state::trojan_bg2_scrollx_w) { m_bg2_tilemap->set_scrollx(0, data); } WRITE8_MEMBER(lwings_state::trojan_bg2_image_w) { if (m_bg2_image != data) { m_bg2_image = data; m_bg2_tilemap->mark_all_dirty(); } } /*************************************************************************** Display refresh ***************************************************************************/ inline int lwings_state::is_sprite_on( uint8_t *buffered_spriteram, int offs ) { int sx, sy; sx = buffered_spriteram[offs + 3] - 0x100 * (buffered_spriteram[offs + 1] & 0x01); sy = buffered_spriteram[offs + 2]; return sx || sy; } void lwings_state::lwings_draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect ) { uint8_t *buffered_spriteram = m_spriteram->buffer(); int offs; for (offs = m_spriteram->bytes() - 4; offs >= 0; offs -= 4) { if (is_sprite_on(buffered_spriteram, offs)) { int code, color, sx, sy, flipx, flipy; sx = buffered_spriteram[offs + 3] - 0x100 * (buffered_spriteram[offs + 1] & 0x01); sy = buffered_spriteram[offs + 2]; if (sy > 0xf8) sy -= 0x100; code = buffered_spriteram[offs] | (buffered_spriteram[offs + 1] & 0xc0) << 2; color = (buffered_spriteram[offs + 1] & 0x38) >> 3; flipx = buffered_spriteram[offs + 1] & 0x02; 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); } } } void lwings_state::trojan_draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect ) { uint8_t *buffered_spriteram = m_spriteram->buffer(); int offs; for (offs = m_spriteram->bytes() - 4; offs >= 0; offs -= 4) { if (is_sprite_on(buffered_spriteram, offs)) { int code, color, sx, sy, flipx, flipy; sx = buffered_spriteram[offs + 3] - 0x100 * (buffered_spriteram[offs + 1] & 0x01); sy = buffered_spriteram[offs + 2]; if (sy > 0xf8) sy -= 0x100; code = buffered_spriteram[offs] | ((buffered_spriteram[offs + 1] & 0x20) << 4) | ((buffered_spriteram[offs + 1] & 0x40) << 2) | ((buffered_spriteram[offs + 1] & 0x80) << 3); color = (buffered_spriteram[offs + 1] & 0x0e) >> 1; if (m_spr_avenger_hw) { flipx = 0; /* Avengers */ flipy = ~buffered_spriteram[offs + 1] & 0x10; } else { flipx = buffered_spriteram[offs + 1] & 0x10; /* Trojan */ flipy = 1; } 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); } } } uint32_t lwings_state::screen_update_lwings(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { m_bg1_tilemap->draw(screen, bitmap, cliprect, 0, 0); lwings_draw_sprites(bitmap, cliprect); m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0); return 0; } uint32_t lwings_state::screen_update_trojan(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { m_bg2_tilemap->draw(screen, bitmap, cliprect, 0, 0); m_bg1_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1, 0); trojan_draw_sprites(bitmap, cliprect); m_bg1_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0, 0); m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0); return 0; }