summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/kan_pand.cpp
blob: 6687edeccc0350485de288f4b2ccdde847296173 (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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
// license:BSD-3-Clause
// copyright-holders:David Haywood, Luca Elia
/***********************************************************************

    Kaneko Pandora Sprite Chip
    GFX processor - PX79C480FP-3 (KANEKO, Pandora-Chip)

    This emulates the Kaneko Pandora Sprite Chip
    which is found on several Kaneko boards.

    there several bootleg variants of this chip,
    these are emulated in kan_panb.c instead.

    Original Games using this Chip

    Snow Bros
    Air Buster
    DJ Boy
    Heavy Unit
    Sand Scorpion
    Gals Panic (1st release)

    The SemiCom games are also using this because
    their bootleg chip appears to function in an
    identical way.

    Rendering appears to be done to a framebuffer
    and the video system can be instructed not to
    clear this, allowing for 'sprite trail' effects
    as used by Air Buster.

    The chip appears to be an 8-bit chip, and
    when used on 16-bit CPUs only the MSB or LSB
    of the data lines are connected.  Address Lines
    also appear to be swapped around on one of the
    hookups.

    to use this in a driver you must hook functions to
    VIDEO_UPDATE  (copies framebuffer to screen)
    and
    VIDEO_EOF  (renders the sprites to the framebuffer)

    also, you have to add the correspondent device in MACHINE_DRIVER

    spriteram should be accessed only with the
    pandora_spriteram_r / pandora_spriteram_w or
    pandora_spriteram_LSB_r / pandora_spriteram_LSB_w
    handlers, depending on the CPU being used with it.

***********************************************************************/

#include "emu.h"
#include "video/kan_pand.h"
#include "screen.h"

DEFINE_DEVICE_TYPE(KANEKO_PANDORA, kaneko_pandora_device, "kaneko_pandora", "Kaneko PANDORA GFX")

kaneko_pandora_device::kaneko_pandora_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, KANEKO_PANDORA, tag, owner, clock)
	, device_video_interface(mconfig, *this)
	, m_gfx_region(0)
	, m_xoffset(0)
	, m_yoffset(0)
	, m_gfxdecode(*this, finder_base::DUMMY_TAG)
{
}

//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void kaneko_pandora_device::device_start()
{
	m_bg_pen = 0;
	m_flip_screen = false;

	m_spriteram = std::make_unique<uint8_t[]>(0x1000);

	m_sprites_bitmap = std::make_unique<bitmap_ind16>(screen().width(), screen().height());

	save_item(NAME(m_clear_bitmap));
	save_item(NAME(m_bg_pen));
	save_item(NAME(m_flip_screen));
	save_pointer(NAME(m_spriteram), 0x1000);
	save_item(NAME(*m_sprites_bitmap));
}

//-------------------------------------------------
//  device_reset - device-specific reset
//-------------------------------------------------

void kaneko_pandora_device::device_reset()
{
	memset(m_spriteram.get(), 0x00, 0x1000);

	m_clear_bitmap = 1;
}


/*****************************************************************************
    IMPLEMENTATION
*****************************************************************************/

void kaneko_pandora_device::set_bg_pen( int pen )
{
	m_bg_pen = pen;
}

void kaneko_pandora_device::set_clear_bitmap( int clear )
{
	m_clear_bitmap = clear;
}

void kaneko_pandora_device::update( bitmap_ind16 &bitmap, const rectangle &cliprect )
{
	if (!m_sprites_bitmap)
	{
		printf("ERROR: pandora_update with no pandora_sprites_bitmap\n");
		return;
	}

	copybitmap_trans(bitmap, *m_sprites_bitmap, 0, 0, 0, 0, cliprect, 0);
}


void kaneko_pandora_device::draw( bitmap_ind16 &bitmap, const rectangle &cliprect )
{
	int sx = 0, sy = 0, x = 0, y = 0, offs;


	/*
	 * Sprite Tile Format
	 * ------------------
	 *
	 * Byte | Bit(s)   | Use
	 * -----+-76543210-+----------------
	 *  0-2 | -------- | unused
	 *  3   | xxxx.... | Palette Bank
	 *  3   | .......x | XPos - Sign Bit
	 *  3   | ......x. | YPos - Sign Bit
	 *  3   | .....x.. | Use Relative offsets
	 *  4   | xxxxxxxx | XPos
	 *  5   | xxxxxxxx | YPos
	 *  6   | xxxxxxxx | Sprite Number (low 8 bits)
	 *  7   | ....xxxx | Sprite Number (high 4 bits)
	 *  7   | x....... | Flip Sprite Y-Axis
	 *  7   | .x...... | Flip Sprite X-Axis
	 */

	for (offs = 0; offs < 0x1000; offs += 8)
	{
		int dx = m_spriteram[offs + 4];
		int dy = m_spriteram[offs + 5];
		int tilecolour = m_spriteram[offs + 3];
		int attr = m_spriteram[offs + 7];
		int flipx =   attr & 0x80;
		int flipy =  (attr & 0x40) << 1;
		int tile  = ((attr & 0x3f) << 8) + (m_spriteram[offs + 6] & 0xff);

		if (tilecolour & 1)
			dx |= 0x100;
		if (tilecolour & 2)
			dy |= 0x100;

		if (tilecolour & 4)
		{
			x += dx;
			y += dy;
		}
		else
		{
			x = dx;
			y = dy;
		}

		if (m_flip_screen)
		{
			sx = 240 - x;
			sy = 240 - y;
			flipx = !flipx;
			flipy = !flipy;
		}
		else
		{
			sx = x;
			sy = y;
		}

		/* global offset */
		sx += m_xoffset;
		sy += m_yoffset;

		sx &= 0x1ff;
		sy &= 0x1ff;

		if (sx & 0x100)
			sx -= 0x200;
		if (sy & 0x100)
			sy -= 0x200;

		m_gfxdecode->gfx(m_gfx_region)->transpen(bitmap,cliprect,
				tile,
				(tilecolour & 0xf0) >> 4,
				flipx, flipy,
				sx,sy,0);
	}
}

void kaneko_pandora_device::eof( )
{
	assert(m_spriteram != nullptr);

	// the games can disable the clearing of the sprite bitmap, to leave sprite trails
	if (m_clear_bitmap)
		m_sprites_bitmap->fill(m_bg_pen, screen().visible_area());

	kaneko_pandora_device::draw(*m_sprites_bitmap, screen().visible_area());
}

/*****************************************************************************
    DEVICE HANDLERS
*****************************************************************************/

WRITE8_MEMBER ( kaneko_pandora_device::spriteram_w )
{
	// it's either hooked up oddly on this, or on the 16-bit games
	// either way, we swap the address lines so that the spriteram is in the same format
	offset = bitswap<16>(offset,  15,14,13,12, 11,   7,6,5,4,3,2,1,0,   10,9,8  );

	if (!m_spriteram)
	{
		printf("ERROR: spriteram_w with no m__spriteram\n");
		return;
	}

	if (offset >= 0x1000)
	{
		logerror("spriteram_w write past spriteram, offset %04x %02x\n", offset, data);
		return;
	}

	m_spriteram[offset] = data;
}

READ8_MEMBER( kaneko_pandora_device::spriteram_r )
{
	// it's either hooked up oddly on this, or on the 16-bit games
	// either way, we swap the address lines so that the spriteram is in the same format
	offset = bitswap<16>(offset,  15,14,13,12, 11,  7,6,5,4,3,2,1,0,  10,9,8  );

	if (!m_spriteram)
	{
		printf("ERROR: spriteram_r with no m_spriteram\n");
		return 0x00;
	}

	if (offset >= 0x1000)
	{
		logerror("spriteram_r read past spriteram, offset %04x\n", offset);
		return 0x00;
	}
	return m_spriteram[offset];
}

/* I don't know if this MSB/LSB mirroring is correct, or if there is twice as much ram, with half of it unused */
WRITE16_MEMBER( kaneko_pandora_device::spriteram_LSB_w )
{
	if (!m_spriteram)
	{
		printf("ERROR: m_spriteram_LSB_w with no m_spriteram\n");
		return;
	}

	if (ACCESSING_BITS_8_15)
	{
		m_spriteram[offset] = (data >> 8) & 0xff;
	}

	if (ACCESSING_BITS_0_7)
	{
		m_spriteram[offset] = data & 0xff;
	}
}

READ16_MEMBER( kaneko_pandora_device::spriteram_LSB_r )
{
	if (!m_spriteram)
	{
		printf("ERROR: spriteram_LSB_r with no m_spriteram\n");
		return 0x0000;
	}

	return m_spriteram[offset] | (m_spriteram[offset] << 8);
}