summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/snk68_spr.cpp
blob: 7181022d130841592e54c41df0a949ffb1225d3a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// 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;
}