// license:BSD-3-Clause
// copyright-holders:Bryan McPhail, Acho A. Tang, Nicola Salmoria
/* SNK68 Sprites */
#include "emu.h"
#include "snk68_spr.h"
DEFINE_DEVICE_TYPE(SNK68_SPR, snk68_spr_device, "snk68_spr", "SNK68 Sprites")
snk68_spr_device::snk68_spr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SNK68_SPR, tag, owner, clock)
, m_gfxdecode(*this, finder_base::DUMMY_TAG)
, m_spriteram(*this, "^spriteram")
, m_screen(*this, "^screen")
, m_flipscreen(0)
, m_partialupdates(1)
{
m_newtilecb = snk68_tile_indirection_delegate(FUNC(snk68_spr_device::tile_callback_noindirect), this);
}
void snk68_spr_device::tile_callback_noindirect(int &tile, int& fx, int& fy, int& region)
{
}
void snk68_spr_device::device_start()
{
// bind our handler
m_newtilecb.bind_relative_to(*owner());
}
void snk68_spr_device::device_reset()
{
}
READ16_MEMBER(snk68_spr_device::spriteram_r)
{
// streetsj expects the MSB of every 32-bit word to be FF. Presumably RAM
// exists only for 3 bytes out of 4 and the fourth is unmapped.
if (!(offset & 1))
return m_spriteram[offset] | 0xff00;
else
return m_spriteram[offset];
}
WRITE16_MEMBER(snk68_spr_device::spriteram_w)
{
uint16_t newword = m_spriteram[offset];
if (!(offset & 1))
data |= 0xff00;
COMBINE_DATA(&newword);
if (m_spriteram[offset] != newword)
{
int vpos = m_screen->vpos();
if (vpos > 0)
if (m_partialupdates) m_screen->update_partial(vpos - 1);
m_spriteram[offset] = newword;
}
}
void snk68_spr_device::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, int group)
{
const uint16_t* tiledata = &m_spriteram[0x800*group];
bool const flip = m_flipscreen;
for (int offs = 0; offs < 0x800; offs += 0x40)
{
int mx = (m_spriteram[offs + 2*group] & 0xff) << 4;
int my = m_spriteram[offs + 2*group + 1];
int i;
mx = mx | (my >> 12);
mx = ((mx + 16) & 0x1ff) - 16;
my = -my;
if (flip)
{
mx = 240 - mx;
my = 240 - my;
}
// every sprite is a column 32 tiles (512 pixels) tall
for (i = 0; i < 0x20; ++i)
{
my &= 0x1ff;
if (my <= cliprect.max_y && my + 15 >= cliprect.min_y)
{
int color = *(tiledata++) & 0x7f;
int tile = *(tiledata++);
int fx = 0,fy = 0;
int region = 0;
m_newtilecb(tile, fx, fy, region);
// the black touch '96 cloned hardware has some tiles
// as 8bpp, we need to shift the colour bits in those cases
int depth = m_gfxdecode->gfx(region)->depth();
if (depth == 256) color >>= 4;
if (flip)
{
fx = !fx;
fy = !fy;
}
m_gfxdecode->gfx(region)->transpen(bitmap,cliprect,
tile,
color,
fx, fy,
mx, my, 0);
}
else
{
tiledata += 2;
}
if (flip)
my -= 16;
else
my += 16;
}
}
}
void snk68_spr_device::draw_sprites_all(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
/* This appears to be the correct priority order */
draw_sprites(bitmap, cliprect, 2);
draw_sprites(bitmap, cliprect, 3);
draw_sprites(bitmap, cliprect, 1);
}
void snk68_spr_device::set_flip(int flip)
{
if (flip) m_flipscreen = 1;
else m_flipscreen = 0;
}