// license:GPL-2.0+
// copyright-holders:Jarek Burczynski
/*
* Video Driver for Tank Busters
*/
#include "emu.h"
#include "includes/tankbust.h"
/***************************************************************************
Callbacks for the TileMap code
***************************************************************************/
/* background tilemap :
0xc000-0xc7ff: xxxx xxxx tile code: 8 lsb bits
0xc800-0xcfff: .... .xxx tile code: 3 msb bits
.... x... tile priority ON TOP of sprites (roofs and part of the rails)
.xxx .... tile color code
x... .... ?? set on *all* roofs (a different bg/sprite priority ?)
note:
- seems that the only way to get color test right is to swap bit 1 and bit 0 of color code
*/
TILE_GET_INFO_MEMBER(tankbust_state::get_bg_tile_info)
{
int code = m_videoram[tile_index];
int attr = m_colorram[tile_index];
int color = ((attr>>4) & 0x07);
code |= (attr&0x07) * 256;
#if 0
if (attr&0x08) //priority bg/sprites (1 = this bg tile on top of sprites)
{
color = ((int)machine().rand()) & 0x0f;
}
if (attr&0x80) //all the roofs of all buildings have this bit set. What's this ???
{
color = ((int)machine().rand()) & 0x0f;
}
#endif
/* priority bg/sprites (1 = this bg tile on top of sprites) */
tileinfo.category = (attr & 0x08) >> 3;
SET_TILE_INFO_MEMBER(1,
code,
(color&4) | ((color&2)>>1) | ((color&1)<<1),
0);
}
TILE_GET_INFO_MEMBER(tankbust_state::get_txt_tile_info)
{
int code = m_txtram[tile_index];
int color = ((code>>6) & 0x03);
SET_TILE_INFO_MEMBER(2,
code & 0x3f,
((color&2)>>1) | ((color&1)<<1),
0);
}
/***************************************************************************
Start the video hardware emulation.
***************************************************************************/
void tankbust_state::video_start()
{
/* not scrollable */
m_txt_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tankbust_state::get_txt_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
/* scrollable */
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tankbust_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
m_txt_tilemap->set_transparent_pen(0);
save_item(NAME(m_xscroll));
save_item(NAME(m_yscroll));
}
/***************************************************************************
Memory handlers
***************************************************************************/
WRITE8_MEMBER(tankbust_state::background_videoram_w)
{
m_videoram[offset] = data;
m_bg_tilemap->mark_tile_dirty(offset);
}
WRITE8_MEMBER(tankbust_state::background_colorram_w)
{
m_colorram[offset] = data;
m_bg_tilemap->mark_tile_dirty(offset);
}
WRITE8_MEMBER(tankbust_state::txtram_w)
{
m_txtram[offset] = data;
m_txt_tilemap->mark_tile_dirty(offset);
}
WRITE8_MEMBER(tankbust_state::xscroll_w)
{
if( m_xscroll[offset] != data )
{
int x;
m_xscroll[offset] = data;
x = m_xscroll[0] + 256 * (m_xscroll[1]&1);
if (x>=0x100) x-=0x200;
m_bg_tilemap->set_scrollx(0, x );
}
//popmessage("x=%02x %02x", m_xscroll[0], m_xscroll[1]);
}
WRITE8_MEMBER(tankbust_state::yscroll_w)
{
if( m_yscroll[offset] != data )
{
int y;
m_yscroll[offset] = data;
y = m_yscroll[0];
if (y>=0x80) y-=0x100;
m_bg_tilemap->set_scrolly(0, y );
}
//popmessage("y=%02x %02x", m_yscroll[0], m_yscroll[1]);
}
/***************************************************************************
Display refresh
***************************************************************************/
/*
spriteram format (4 bytes per sprite):
offset 0 x....... flip X
offset 0 .x...... flip Y
offset 0 ..xxxxxx gfx code (6 bits)
offset 1 xxxxxxxx y position
offset 2 ??????.. not used ?
offset 2 ......?. used but unknown ??? (color code ? or x ?)
offset 2 .......x x position (1 MSB bit)
offset 3 xxxxxxxx x position (8 LSB bits)
*/
void tankbust_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
for (int offs = 0; offs < m_spriteram.bytes(); offs += 4)
{
int code,color,sx,sy,flipx,flipy;
code = m_spriteram[offs+0] & 0x3f;
flipy = m_spriteram[offs+0] & 0x40;
flipx = m_spriteram[offs+0] & 0x80;
sy = (240- m_spriteram[offs+1]) - 14;
sx = (m_spriteram[offs+2] & 0x01) * 256 + m_spriteram[offs+3] - 7;
color = 0;
//0x02 - don't know (most of the time this bit is set in tank sprite and others but not all and not always)
//0x04 - not used
//0x08 - not used
//0x10 - not used
//0x20 - not used
//0x40 - not used
//0x80 - not used
#if 0
if ((m_spriteram[offs+2] & 0x02))
{
code = ((int)machine().rand()) & 63;
}
#endif
if ((m_spriteram[offs+1]!=4)) //otherwise - ghost sprites
{
m_gfxdecode->gfx(0)->transpen(bitmap,cliprect,
code, color,
flipx,flipy,
sx,sy,0);
}
}
}
uint32_t tankbust_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
#if 0
for (int i=0; i<0x800; i++)
{
int tile_attrib = m_colorram[i];
if ( (tile_attrib&8) || (tile_attrib&0x80) )
{
m_bg_tilemap->mark_tile_dirty(i);
}
}
#endif
m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
draw_sprites(bitmap, cliprect);
m_bg_tilemap->draw(screen, bitmap, cliprect, 1, 0);
m_txt_tilemap->draw(screen, bitmap, cliprect, 0,0);
return 0;
}