1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood
3 /***************************************************************************/
4 /*                                                                         */
5 /*                                 053246                                  */
6 /*                          with 053247 or 055673                          */
7 /*  is the 053247 / 055673 choice just a BPP change like the tilemaps?     */
8 /*                                                                         */
9 /*                                                                         */
10 /***************************************************************************/
11 /* later Konami GX board replaces the 053246 with a 058142 */
12 
13 /*
14 
15 053247/053246
16 -------------
17 Sprite generators. Nothing is known about their external interface.
18 The sprite RAM format is very similar to the 053245.
19 
20 053246 memory map (but the 053247 sees and processes them too):
21 000-001 W  global X offset
22 002-003 W  global Y offset
23 004     W  low 8 bits of the ROM address to read
24 005     W  bit 0 = flip screen X
25            bit 1 = flip screen Y
26            bit 2 = unknown
27            bit 4 = interrupt enable
28            bit 5 = unknown
29 006-007 W  high 16 bits of the ROM address to read
30 
31 ???-??? R  reads data from the gfx ROMs (16 bits in total). The address of the
32            data is determined by the registers above
33 
34 
35 */
36 
37 #include "emu.h"
38 #include "k053246_k053247_k055673.h"
39 #include "konami_helper.h"
40 
41 #include <algorithm>
42 
43 #define VERBOSE 0
44 #include "logmacro.h"
45 
46 
47 /*****************************************************************************
48     DEVICE HANDLERS
49 *****************************************************************************/
50 
51 
clear_all()52 void k053247_device::clear_all()
53 {
54 	m_ram = nullptr;
55 	m_gfx = nullptr;
56 
57 	std::fill(std::begin(m_kx46_regs), std::end(m_kx46_regs), 0);
58 	std::fill(std::begin(m_kx47_regs), std::end(m_kx47_regs), 0);
59 
60 	m_objcha_line = 0;
61 	m_z_rejection = 0;
62 }
63 
k053247_get_ram(u16 ** ram)64 void k053247_device::k053247_get_ram(u16 **ram)
65 {
66 	*ram = m_ram.get();
67 }
68 
k053247_get_dx(void)69 int k053247_device::k053247_get_dx(void)
70 {
71 	return m_dx;
72 }
73 
k053247_get_dy(void)74 int k053247_device::k053247_get_dy(void)
75 {
76 	return m_dy;
77 }
78 
k053246_read_register(offs_t offset)79 u8 k053247_device::k053246_read_register(offs_t offset)
80 {
81 	return m_kx46_regs[offset];
82 }
83 
k053247_read_register(offs_t offset)84 u16 k053247_device::k053247_read_register(offs_t offset)
85 {
86 	return m_kx47_regs[offset];
87 }
88 
89 
k055673_reg_word_w(offs_t offset,u16 data,u16 mem_mask)90 void k053247_device::k055673_reg_word_w(offs_t offset, u16 data, u16 mem_mask) // write-only OBJSET2 registers (see p.43 table 6.1)
91 {
92 	COMBINE_DATA(m_kx47_regs + offset);
93 }
94 
k053247_word_r(offs_t offset)95 u16 k053247_device::k053247_word_r(offs_t offset)
96 {
97 	return m_ram[offset];
98 }
99 
k053247_word_w(offs_t offset,u16 data,u16 mem_mask)100 void k053247_device::k053247_word_w(offs_t offset, u16 data, u16 mem_mask)
101 {
102 	COMBINE_DATA(m_ram.get() + offset);
103 }
104 
k053247_r(offs_t offset)105 u8 k053247_device::k053247_r(offs_t offset)
106 {
107 	int offs = offset >> 1;
108 
109 	if (offset & 1)
110 		return(m_ram[offs] & 0xff);
111 	else
112 		return(m_ram[offs] >> 8);
113 }
114 
k053247_w(offs_t offset,u8 data)115 void k053247_device::k053247_w(offs_t offset, u8 data)
116 {
117 	int offs = offset >> 1;
118 
119 	if (offset & 1)
120 		m_ram[offs] = (m_ram[offs] & 0xff00) | data;
121 	else
122 		m_ram[offs] = (m_ram[offs] & 0x00ff) | (data << 8);
123 }
124 
125 // The K055673 supports a non-objcha based ROM readback
126 // write the address to the 246 as usual, but there's a completely separate ROM
127 // window that works without needing an objcha line.
128 // in this window, +0 = 32 bits from one set of ROMs, and +8 = 32 bits from another set
129 
130 // FIXME: rearrange ROM loading so this can be merged with the 4/6/8bpp version
k055673_5bpp_rom_word_r(offs_t offset)131 u16 k053247_device::k055673_5bpp_rom_word_r(offs_t offset) // 5bpp
132 {
133 	u8 *ROM8 = (u8 *)&m_gfxrom[0];
134 	u16 *ROM = (u16 *)&m_gfxrom[0];
135 	int size4 = (m_gfxrom.length() / (1024 * 1024)) / 5;
136 	int romofs;
137 
138 	size4 *= 4 * 1024 * 1024;   // get offset to 5th bit
139 	ROM8 += size4;
140 
141 	romofs = m_kx46_regs[6] << 16 | m_kx46_regs[7] << 8 | m_kx46_regs[4];
142 
143 	switch (offset)
144 	{
145 		case 0: // 20k / 36u
146 			return ROM[romofs + 2];
147 		case 1: // 17k / 36y
148 			return ROM[romofs + 3];
149 		case 2: // 10k / 32y
150 		case 3:
151 			romofs /= 2;
152 			return ROM8[romofs + 1];
153 		case 4: // 22k / 34u
154 			return ROM[romofs];
155 		case 5: // 19k / 34y
156 			return ROM[romofs + 1];
157 		case 6: // 12k / 29y
158 		case 7:
159 			romofs /= 2;
160 			return ROM8[romofs];
161 		default:
162 			LOG("55673_rom_word_r: Unknown read offset %x\n", offset);
163 			break;
164 	}
165 
166 	return 0;
167 }
168 
k055673_rom_word_r(offs_t offset)169 u16 k053247_device::k055673_rom_word_r(offs_t offset)
170 {
171 	if (m_bpp == 5)
172 		return k055673_5bpp_rom_word_r(offset);
173 
174 	u16 *ROM = (u16 *)&m_gfxrom[0];
175 	int romofs;
176 
177 	romofs = m_kx46_regs[6] << 16 | m_kx46_regs[7] << 8 | m_kx46_regs[4];
178 
179 	romofs = (romofs >> 2) * m_bpp;
180 
181 	if ((offset & 0x4) == 0) romofs += m_bpp >> 1;
182 
183 	return ROM[romofs + (offset & 0x3)];
184 }
185 
k055673_ps_rom_word_r(offs_t offset)186 u16 k053247_device::k055673_ps_rom_word_r(offs_t offset)
187 {
188 	u8 *ROM = (u8 *)&m_gfxrom[0];
189 	int romofs;
190 	int magic = (offset & 1);
191 
192 	romofs = m_kx46_regs[6] << 16 | m_kx46_regs[7] << 8 | m_kx46_regs[4];
193 	offset = ((offset & 4) >> 1);
194 
195 	int finoffs = (romofs * 2) + (offset * 2) + magic;
196 
197 	return ROM[finoffs+2] | (ROM[finoffs]<<8);
198 }
199 
k053246_r(offs_t offset)200 u8 k053247_device::k053246_r(offs_t offset)
201 {
202 	if (m_objcha_line == ASSERT_LINE)
203 	{
204 		int addr;
205 
206 		addr = (m_kx46_regs[6] << 17) | (m_kx46_regs[7] << 9) | (m_kx46_regs[4] << 1) | ((offset & 1) ^ 1);
207 		addr &= m_gfxrom.mask();
208 		return m_gfxrom[addr];
209 	}
210 	else
211 	{
212 		return 0;
213 	}
214 }
215 
k053246_w(offs_t offset,u8 data)216 void k053247_device::k053246_w(offs_t offset, u8 data)
217 {
218 	m_kx46_regs[offset] = data;
219 }
220 
k053246_set_objcha_line(int state)221 void k053247_device::k053246_set_objcha_line(int state)
222 {
223 	m_objcha_line = state;
224 }
225 
k053246_is_irq_enabled(void)226 int k053247_device::k053246_is_irq_enabled(void)
227 {
228 	// This bit enables obj DMA rather than obj IRQ even though the two functions usually coincide.
229 	return m_kx46_regs[5] & 0x10;
230 }
231 
232 /*
233  * Sprite Format
234  * ------------------
235  *
236  * Word | Bit(s)           | Use
237  * -----+-fedcba9876543210-+----------------
238  *   0  | x--------------- | active (show this sprite)
239  *   0  | -x-------------- | maintain aspect ratio (when set, zoom y acts on both axis)
240  *   0  | --x------------- | flip y
241  *   0  | ---x------------ | flip x
242  *   0  | ----xxxx-------- | sprite size (see below)
243  *   0  | --------xxxxxxxx | zcode
244  *   1  | xxxxxxxxxxxxxxxx | sprite code
245  *   2  | ------xxxxxxxxxx | y position
246  *   3  | ------xxxxxxxxxx | x position
247  *   4  | xxxxxxxxxxxxxxxx | zoom y (0x40 = normal, <0x40 = enlarge, >0x40 = reduce)
248  *   5  | xxxxxxxxxxxxxxxx | zoom x (0x40 = normal, <0x40 = enlarge, >0x40 = reduce)
249  *   6  | x--------------- | mirror y (top half is drawn as mirror image of the bottom)
250  *   6  | -x-------------- | mirror x (right half is drawn as mirror image of the left)
251  *   6  | --xx------------ | reserved (sprites with these two bits set don't seem to be graphics data at all)
252  *   6  | ----xx---------- | shadow code: 0=off, 0x400=preset1, 0x800=preset2, 0xc00=preset3
253  *   6  | ------xx-------- | effect code: flicker, upper palette, full shadow...etc. (game dependent)
254  *   6  | --------xxxxxxxx | "color", but depends on external connections (implies priority)
255  *   7  | xxxxxxxxxxxxxxxx | game dependent
256  *
257  * shadow enables transparent shadows. Note that it applies to the last sprite pen ONLY.
258  * The rest of the sprite remains normal.
259  */
260 
261 template<class BitmapClass>
k053247_sprites_draw_common(BitmapClass & bitmap,const rectangle & cliprect)262 void k053247_device::k053247_sprites_draw_common(BitmapClass &bitmap, const rectangle &cliprect)
263 {
264 #define NUM_SPRITES 256
265 
266 	int code, color, x, y, shadow, shdmask, count, temp, primask;
267 
268 	int sortedlist[NUM_SPRITES];
269 	int offs,zcode;
270 
271 	u8 drawmode_table[256];
272 	u8 shadowmode_table[256];
273 
274 	memset(drawmode_table, DRAWMODE_SOURCE, sizeof(drawmode_table));
275 	drawmode_table[0] = DRAWMODE_NONE;
276 	memset(shadowmode_table, DRAWMODE_SHADOW, sizeof(shadowmode_table));
277 	shadowmode_table[0] = DRAWMODE_NONE;
278 
279 	/*
280 	    safeguard older drivers missing any of the following video attributes:
281 
282 	    VIDEO_HAS_SHADOWS | VIDEO_HAS_HIGHLIGHTS
283 	*/
284 	if (palette().shadows_enabled())
285 	{
286 		if (sizeof(typename BitmapClass::pixel_t) == 4 && (palette().hilights_enabled()))
287 			shdmask = 3; // enable all shadows and highlights
288 		else
289 			shdmask = 0; // enable default shadows
290 	}
291 	else
292 		shdmask = -1; // disable everything
293 
294 	/*
295 	    The k053247 does not draw pixels on top of those with equal or smaller Z-values
296 	    regardless of priority. Embedded shadows inherit Z-values from their host sprites
297 	    but do not assume host priorities unless explicitly told. In other words shadows
298 	    can have priorities different from that of normal pens in the same sprite,
299 	    in addition to the ability of masking themselves from specific layers or pixels
300 	    on the other sprites.
301 
302 	    In front-to-back rendering, sprites cannot sandwich between alpha blended layers
303 	    or the draw code will have to figure out the percentage opacities of what is on
304 	    top and beneath each sprite pixel and blend the target accordingly. The process
305 	    is overly demanding for realtime software and is thus another shortcoming of
306 	    pdrawgfx and pixel based mixers. Even mahjong games with straight forward video
307 	    subsystems are feeling the impact by which the girls cannot appear under
308 	    translucent dialogue boxes.
309 
310 	    These are a small part of the k053247's feature set but many games expect them
311 	    to be the minimum compliances. The specification will undoubtedly require
312 	    redesigning the priority system from the ground up. Drawgfx.c and tilemap.c must
313 	    also undergo heavy facelifts but in the end the changes could hurt simpler games
314 	    more than they help complex systems; therefore the new engine should remain
315 	    completely stand alone and self-contained. Implementation details are being
316 	    hammered down but too early to make propositions.
317 	*/
318 
319 	// Prebuild a sorted table by descending Z-order.
320 	zcode = m_z_rejection;
321 	offs = count = 0;
322 
323 	if (zcode == -1)
324 	{
325 		for (; offs < 0x800; offs += 8)
326 			if (m_ram[offs] & 0x8000)
327 				sortedlist[count++] = offs;
328 	}
329 	else
330 	{
331 		for (; offs < 0x800; offs += 8)
332 			if ((m_ram[offs] & 0x8000) && ((m_ram[offs] & 0xff) != zcode))
333 				sortedlist[count++] = offs;
334 	}
335 
336 	int w = count;
337 	count--;
338 	int h = count;
339 
340 	if (!(m_kx47_regs[0xc / 2] & 0x10))
341 	{
342 		// sort objects in decending order(smaller z closer) when OPSET PRI is clear
343 		for (y = 0; y < h; y++)
344 		{
345 			offs = sortedlist[y];
346 			zcode = m_ram[offs] & 0xff;
347 			for (x = y + 1; x < w; x++)
348 			{
349 				temp = sortedlist[x];
350 				code = m_ram[temp] & 0xff;
351 				if (zcode <= code)
352 				{
353 					zcode = code;
354 					sortedlist[x] = offs;
355 					sortedlist[y] = offs = temp;
356 				}
357 			}
358 		}
359 	}
360 	else
361 	{
362 		// sort objects in ascending order(bigger z closer) when OPSET PRI is set
363 		for (y = 0; y < h; y++)
364 		{
365 			offs = sortedlist[y];
366 			zcode = m_ram[offs] & 0xff;
367 			for (x = y + 1; x < w; x++)
368 			{
369 				temp = sortedlist[x];
370 				code = m_ram[temp] & 0xff;
371 				if (zcode >= code)
372 				{
373 					zcode = code;
374 					sortedlist[x] = offs;
375 					sortedlist[y] = offs = temp;
376 				}
377 			}
378 		}
379 	}
380 
381 	for (; count >= 0; count--)
382 	{
383 		offs = sortedlist[count];
384 
385 		code = m_ram[offs + 1];
386 		shadow = color = m_ram[offs + 6];
387 		primask = 0;
388 
389 		m_k053247_cb(&code, &color, &primask);
390 
391 		k053247_draw_single_sprite_gxcore(bitmap, cliprect,
392 				nullptr, nullptr,
393 				code, m_ram.get(), offs,
394 				color,
395 				/* gx only */
396 				0, 0, 0, 0,
397 				/* non-gx only */
398 				primask,shadow,drawmode_table,shadowmode_table,shdmask
399 				);
400 
401 
402 
403 	} // end of sprite-list loop
404 #undef NUM_SPRITES
405 }
406 
k053247_sprites_draw(bitmap_ind16 & bitmap,const rectangle & cliprect)407 void k053247_device::k053247_sprites_draw(bitmap_ind16 &bitmap, const rectangle &cliprect)
408 { k053247_sprites_draw_common(bitmap, cliprect); }
409 
k053247_sprites_draw(bitmap_rgb32 & bitmap,const rectangle & cliprect)410 void k053247_device::k053247_sprites_draw(bitmap_rgb32 &bitmap, const rectangle &cliprect)
411 { k053247_sprites_draw_common(bitmap, cliprect); }
412 
413 
414 /*
415     Parameter Notes
416     ---------------
417     clip    : *caller must supply a pointer to target clip rectangle
418     alpha   : 0 = invisible, 255 = solid
419     drawmode:
420         0 = all pens solid
421         1 = solid pens only
422         2 = all pens solid with alpha blending
423         3 = solid pens only with alpha blending
424         4 = shadow pens only
425         5 = all pens shadow
426     zcode   : 0 = closest, 255 = furthest (pixel z-depth), -1 = disable depth buffers and shadows
427     pri     : 0 = topmost, 255 = backmost (pixel priority)
428 */
429 
zdrawgfxzoom32GP(bitmap_rgb32 & bitmap,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,int sx,int sy,int scalex,int scaley,int alpha,int drawmode,int zcode,int pri,u8 * gx_objzbuf,u8 * gx_shdzbuf)430 void k053247_device::zdrawgfxzoom32GP(
431 		bitmap_rgb32 &bitmap, const rectangle &cliprect,
432 		u32 code, u32 color, int flipx, int flipy, int sx, int sy,
433 		int scalex, int scaley, int alpha, int drawmode, int zcode, int pri, u8* gx_objzbuf, u8* gx_shdzbuf)
434 {
435 #define FP     19
436 #define FPONE  (1<<FP)
437 #define FPHALF (1<<(FP-1))
438 #define FPENT  0
439 
440 	// inner loop
441 	const u8  *src_ptr;
442 	int src_x;
443 	int eax, ecx;
444 	int src_fx, src_fdx;
445 	int shdpen;
446 	u8  z8 = 0, p8 = 0;
447 	u8  *ozbuf_ptr;
448 	u8  *szbuf_ptr;
449 	const pen_t *pal_base;
450 	const pen_t *shd_base;
451 	u32 *dst_ptr;
452 
453 	// outter loop
454 	int src_fby, src_fdy, src_fbx;
455 	const u8 *src_base;
456 	int dst_w, dst_h;
457 
458 	// one-time
459 	int nozoom, granularity;
460 	int src_fw, src_fh;
461 	int dst_minx, dst_maxx, dst_miny, dst_maxy;
462 	int dst_skipx, dst_skipy, dst_x, dst_y, dst_lastx, dst_lasty;
463 	int src_pitch, dst_pitch;
464 
465 
466 	// cull illegal and transparent objects
467 	if (!scalex || !scaley) return;
468 
469 	// find shadow pens and cull invisible shadows
470 	granularity = shdpen = m_gfx->granularity();
471 	shdpen--;
472 
473 	if (zcode >= 0)
474 	{
475 		if (drawmode == 5) { drawmode = 4; shdpen = 1; }
476 	}
477 	else
478 		if (drawmode >= 4) return;
479 
480 	// alpha blend necessary?
481 	if (drawmode & 2)
482 	{
483 		if (alpha <= 0) return;
484 		if (alpha >= 255) drawmode &= ~2;
485 	}
486 
487 	// fill internal data structure with default values
488 	ozbuf_ptr  = gx_objzbuf;
489 	szbuf_ptr  = gx_shdzbuf;
490 
491 	src_pitch = 16;
492 	src_fw    = 16;
493 	src_fh    = 16;
494 	src_base  = m_gfx->get_data(code % m_gfx->elements());
495 
496 	pal_base  = palette().pens() + m_gfx->colorbase() + (color % m_gfx->colors()) * granularity;
497 	shd_base  = palette().shadow_table();
498 
499 	dst_ptr   = &bitmap.pix(0);
500 	dst_pitch = bitmap.rowpixels();
501 	dst_minx  = cliprect.min_x;
502 	dst_maxx  = cliprect.max_x;
503 	dst_miny  = cliprect.min_y;
504 	dst_maxy  = cliprect.max_y;
505 	dst_x     = sx;
506 	dst_y     = sy;
507 
508 	// cull off-screen objects
509 	if (dst_x > dst_maxx || dst_y > dst_maxy) return;
510 	nozoom = (scalex == 0x10000 && scaley == 0x10000);
511 	if (nozoom)
512 	{
513 		dst_h = dst_w = 16;
514 		src_fdy = src_fdx = 1;
515 	}
516 	else
517 	{
518 		dst_w = ((scalex<<4)+0x8000)>>16;
519 		dst_h = ((scaley<<4)+0x8000)>>16;
520 		if (!dst_w || !dst_h) return;
521 
522 		src_fw <<= FP;
523 		src_fh <<= FP;
524 		src_fdx = src_fw / dst_w;
525 		src_fdy = src_fh / dst_h;
526 	}
527 	dst_lastx = dst_x + dst_w - 1;
528 	if (dst_lastx < dst_minx) return;
529 	dst_lasty = dst_y + dst_h - 1;
530 	if (dst_lasty < dst_miny) return;
531 
532 	// clip destination
533 	dst_skipx = 0;
534 	eax = dst_minx;  if ((eax -= dst_x) > 0) { dst_skipx = eax;  dst_w -= eax;  dst_x = dst_minx; }
535 	eax = dst_lastx; if ((eax -= dst_maxx) > 0) dst_w -= eax;
536 	dst_skipy = 0;
537 	eax = dst_miny;  if ((eax -= dst_y) > 0) { dst_skipy = eax;  dst_h -= eax;  dst_y = dst_miny; }
538 	eax = dst_lasty; if ((eax -= dst_maxy) > 0) dst_h -= eax;
539 
540 	// calculate zoom factors and clip source
541 	if (nozoom)
542 	{
543 		if (!flipx) src_fbx = 0; else { src_fbx = src_fw - 1; src_fdx = -src_fdx; }
544 		if (!flipy) src_fby = 0; else { src_fby = src_fh - 1; src_fdy = -src_fdy; src_pitch = -src_pitch; }
545 	}
546 	else
547 	{
548 		if (!flipx) src_fbx = FPENT; else { src_fbx = src_fw - FPENT - 1; src_fdx = -src_fdx; }
549 		if (!flipy) src_fby = FPENT; else { src_fby = src_fh - FPENT - 1; src_fdy = -src_fdy; }
550 	}
551 	src_fbx += dst_skipx * src_fdx;
552 	src_fby += dst_skipy * src_fdy;
553 
554 	// adjust insertion points and pre-entry constants
555 	eax = (dst_y - dst_miny) * GX_ZBUFW + (dst_x - dst_minx) + dst_w;
556 	z8 = (u8)zcode;
557 	p8 = (u8)pri;
558 	ozbuf_ptr += eax;
559 	szbuf_ptr += eax << 1;
560 	dst_ptr += dst_y * dst_pitch + dst_x + dst_w;
561 	dst_w = -dst_w;
562 
563 	if (!nozoom)
564 	{
565 		ecx = src_fby;   src_fby += src_fdy;
566 		ecx >>= FP;      src_fx = src_fbx;
567 		src_x = src_fbx; src_fx += src_fdx;
568 		ecx <<= 4;       src_ptr = src_base;
569 		src_x >>= FP;    src_ptr += ecx;
570 		ecx = dst_w;
571 
572 		if (zcode < 0) // no shadow and z-buffering
573 		{
574 			do {
575 				do {
576 					eax = src_ptr[src_x];
577 					src_x = src_fx;
578 					src_fx += src_fdx;
579 					src_x >>= FP;
580 					if (!eax || eax >= shdpen) continue;
581 					dst_ptr [ecx] = pal_base[eax];
582 				}
583 				while (++ecx);
584 
585 				ecx = src_fby;   src_fby += src_fdy;
586 				dst_ptr += dst_pitch;
587 				ecx >>= FP;      src_fx = src_fbx;
588 				src_x = src_fbx; src_fx += src_fdx;
589 				ecx <<= 4;       src_ptr = src_base;
590 				src_x >>= FP;    src_ptr += ecx;
591 				ecx = dst_w;
592 			}
593 			while (--dst_h);
594 		}
595 		else
596 		{
597 			switch (drawmode)
598 			{
599 				case 0: // all pens solid
600 					do {
601 						do {
602 							eax = src_ptr[src_x];
603 							src_x = src_fx;
604 							src_fx += src_fdx;
605 							src_x >>= FP;
606 							if (!eax || ozbuf_ptr[ecx] < z8) continue;
607 							eax = pal_base[eax];
608 							ozbuf_ptr[ecx] = z8;
609 							dst_ptr [ecx] = eax;
610 						}
611 						while (++ecx);
612 
613 						ecx = src_fby;   src_fby += src_fdy;
614 						ozbuf_ptr += GX_ZBUFW;
615 						dst_ptr += dst_pitch;
616 						ecx >>= FP;      src_fx = src_fbx;
617 						src_x = src_fbx; src_fx += src_fdx;
618 						ecx <<= 4;       src_ptr = src_base;
619 						src_x >>= FP;    src_ptr += ecx;
620 						ecx = dst_w;
621 					}
622 					while (--dst_h);
623 					break;
624 
625 				case 1: // solid pens only
626 					do {
627 						do {
628 							eax = src_ptr[src_x];
629 							src_x = src_fx;
630 							src_fx += src_fdx;
631 							src_x >>= FP;
632 							if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
633 							eax = pal_base[eax];
634 							ozbuf_ptr[ecx] = z8;
635 							dst_ptr [ecx] = eax;
636 						}
637 						while (++ecx);
638 
639 						ecx = src_fby;   src_fby += src_fdy;
640 						ozbuf_ptr += GX_ZBUFW;
641 						dst_ptr += dst_pitch;
642 						ecx >>= FP;      src_fx = src_fbx;
643 						src_x = src_fbx; src_fx += src_fdx;
644 						ecx <<= 4;       src_ptr = src_base;
645 						src_x >>= FP;    src_ptr += ecx;
646 						ecx = dst_w;
647 					}
648 					while (--dst_h);
649 					break;
650 
651 				case 2: // all pens solid with alpha blending
652 					do {
653 						do {
654 							eax = src_ptr[src_x];
655 							src_x = src_fx;
656 							src_fx += src_fdx;
657 							src_x >>= FP;
658 							if (!eax || ozbuf_ptr[ecx] < z8) continue;
659 							ozbuf_ptr[ecx] = z8;
660 
661 							dst_ptr[ecx] = alpha_blend_r32(pal_base[eax], dst_ptr[ecx], alpha);
662 						}
663 						while (++ecx);
664 
665 						ecx = src_fby;   src_fby += src_fdy;
666 						ozbuf_ptr += GX_ZBUFW;
667 						dst_ptr += dst_pitch;
668 						ecx >>= FP;      src_fx = src_fbx;
669 						src_x = src_fbx; src_fx += src_fdx;
670 						ecx <<= 4;       src_ptr = src_base;
671 						src_x >>= FP;    src_ptr += ecx;
672 						ecx = dst_w;
673 					}
674 					while (--dst_h);
675 					break;
676 
677 				case 3: // solid pens only with alpha blending
678 					do {
679 						do {
680 							eax = src_ptr[src_x];
681 							src_x = src_fx;
682 							src_fx += src_fdx;
683 							src_x >>= FP;
684 							if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
685 							ozbuf_ptr[ecx] = z8;
686 
687 							dst_ptr[ecx] = alpha_blend_r32(pal_base[eax], dst_ptr[ecx], alpha);
688 						}
689 						while (++ecx);
690 
691 						ecx = src_fby;   src_fby += src_fdy;
692 						ozbuf_ptr += GX_ZBUFW;
693 						dst_ptr += dst_pitch;
694 						ecx >>= FP;      src_fx = src_fbx;
695 						src_x = src_fbx; src_fx += src_fdx;
696 						ecx <<= 4;       src_ptr = src_base;
697 						src_x >>= FP;    src_ptr += ecx;
698 						ecx = dst_w;
699 					}
700 					while (--dst_h);
701 					break;
702 
703 				case 4: // shadow pens only
704 					do {
705 						do {
706 							eax = src_ptr[src_x];
707 							src_x = src_fx;
708 							src_fx += src_fdx;
709 							src_x >>= FP;
710 							if (eax < shdpen || szbuf_ptr[ecx*2] < z8 || szbuf_ptr[ecx*2+1] <= p8) continue;
711 							rgb_t pix = dst_ptr[ecx];
712 							szbuf_ptr[ecx*2] = z8;
713 							szbuf_ptr[ecx*2+1] = p8;
714 
715 							// the shadow tables are 15-bit lookup tables which accept RGB15... lossy, nasty, yuck!
716 							dst_ptr[ecx] = shd_base[pix.as_rgb15()];
717 							//dst_ptr[ecx] =(eax>>3&0x001f);lend_r32(eax, 0x00000000, 128);
718 						}
719 						while (++ecx);
720 
721 						ecx = src_fby;   src_fby += src_fdy;
722 						szbuf_ptr += (GX_ZBUFW<<1);
723 						dst_ptr += dst_pitch;
724 						ecx >>= FP;      src_fx = src_fbx;
725 						src_x = src_fbx; src_fx += src_fdx;
726 						ecx <<= 4;       src_ptr = src_base;
727 						src_x >>= FP;    src_ptr += ecx;
728 						ecx = dst_w;
729 					}
730 					while (--dst_h);
731 					break;
732 			}   // switch (drawmode)
733 		}   // if (zcode < 0)
734 	}   // if (!nozoom)
735 	else
736 	{
737 		src_ptr = src_base + (src_fby<<4) + src_fbx;
738 		src_fdy = src_fdx * dst_w + src_pitch;
739 		ecx = dst_w;
740 
741 		if (zcode < 0) // no shadow and z-buffering
742 		{
743 			do {
744 				do {
745 					eax = *src_ptr;
746 					src_ptr += src_fdx;
747 					if (!eax || eax >= shdpen) continue;
748 					dst_ptr[ecx] = pal_base[eax];
749 				}
750 				while (++ecx);
751 
752 				src_ptr += src_fdy;
753 				dst_ptr += dst_pitch;
754 				ecx = dst_w;
755 			}
756 			while (--dst_h);
757 		}
758 		else
759 		{
760 			switch (drawmode)
761 			{
762 				case 0: // all pens solid
763 					do {
764 						do {
765 							eax = *src_ptr;
766 							src_ptr += src_fdx;
767 							if (!eax || ozbuf_ptr[ecx] < z8) continue;
768 							eax = pal_base[eax];
769 							ozbuf_ptr[ecx] = z8;
770 							dst_ptr[ecx] = eax;
771 						}
772 						while (++ecx);
773 
774 						src_ptr += src_fdy;
775 						ozbuf_ptr += GX_ZBUFW;
776 						dst_ptr += dst_pitch;
777 						ecx = dst_w;
778 					}
779 					while (--dst_h);
780 					break;
781 
782 				case 1:  // solid pens only
783 					do {
784 						do {
785 							eax = *src_ptr;
786 							src_ptr += src_fdx;
787 							if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
788 							eax = pal_base[eax];
789 							ozbuf_ptr[ecx] = z8;
790 							dst_ptr[ecx] = eax;
791 						}
792 						while (++ecx);
793 
794 						src_ptr += src_fdy;
795 						ozbuf_ptr += GX_ZBUFW;
796 						dst_ptr += dst_pitch;
797 						ecx = dst_w;
798 					}
799 					while (--dst_h);
800 					break;
801 
802 				case 2: // all pens solid with alpha blending
803 					do {
804 						do {
805 							eax = *src_ptr;
806 							src_ptr += src_fdx;
807 							if (!eax || ozbuf_ptr[ecx] < z8) continue;
808 							ozbuf_ptr[ecx] = z8;
809 
810 							dst_ptr[ecx] = alpha_blend_r32(pal_base[eax], dst_ptr[ecx], alpha);
811 						}
812 						while (++ecx);
813 
814 						src_ptr += src_fdy;
815 						ozbuf_ptr += GX_ZBUFW;
816 						dst_ptr += dst_pitch;
817 						ecx = dst_w;
818 					}
819 					while (--dst_h);
820 					break;
821 
822 				case 3: // solid pens only with alpha blending
823 					do {
824 						do {
825 							eax = *src_ptr;
826 							src_ptr += src_fdx;
827 							if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
828 							ozbuf_ptr[ecx] = z8;
829 
830 							dst_ptr[ecx] = alpha_blend_r32(pal_base[eax], dst_ptr[ecx], alpha);
831 						}
832 						while (++ecx);
833 
834 						src_ptr += src_fdy;
835 						ozbuf_ptr += GX_ZBUFW;
836 						dst_ptr += dst_pitch;
837 						ecx = dst_w;
838 					}
839 					while (--dst_h);
840 					break;
841 
842 				case 4: // shadow pens only
843 					do {
844 						do {
845 							eax = *src_ptr;
846 							src_ptr += src_fdx;
847 							if (eax < shdpen || szbuf_ptr[ecx*2] < z8 || szbuf_ptr[ecx*2+1] <= p8) continue;
848 							rgb_t pix = dst_ptr[ecx];
849 							szbuf_ptr[ecx*2] = z8;
850 							szbuf_ptr[ecx*2+1] = p8;
851 
852 							// the shadow tables are 15-bit lookup tables which accept RGB15... lossy, nasty, yuck!
853 							dst_ptr[ecx] = shd_base[pix.as_rgb15()];
854 						}
855 						while (++ecx);
856 
857 						src_ptr += src_fdy;
858 						szbuf_ptr += (GX_ZBUFW<<1);
859 						dst_ptr += dst_pitch;
860 						ecx = dst_w;
861 					}
862 					while (--dst_h);
863 					break;
864 			}
865 		}
866 	}
867 #undef FP
868 #undef FPONE
869 #undef FPHALF
870 #undef FPENT
871 }
872 
873 
zdrawgfxzoom32GP(bitmap_ind16 & bitmap,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,int sx,int sy,int scalex,int scaley,int alpha,int drawmode,int zcode,int pri,u8 * gx_objzbuf,u8 * gx_shdzbuf)874 void k053247_device::zdrawgfxzoom32GP(
875 		bitmap_ind16 &bitmap, const rectangle &cliprect,
876 		u32 code, u32 color, int flipx, int flipy, int sx, int sy,
877 		int scalex, int scaley, int alpha, int drawmode, int zcode, int pri, u8* gx_objzbuf, u8* gx_shdzbuf)
878 {
879 	fatalerror("no zdrawgfxzoom32GP for bitmap_ind16\n");
880 }
881 
882 
883 /*****************************************************************************
884     DEVICE INTERFACE
885 *****************************************************************************/
886 
887 
888 DEFINE_DEVICE_TYPE(K055673, k055673_device, "k055673", "K055673 Sprite Generator")
889 
k055673_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)890 k055673_device::k055673_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
891 	: k053247_device(mconfig, K055673, tag, owner, clock)
892 {
893 }
894 
895 
896 //-------------------------------------------------
897 //  device_start - device-specific startup
898 //-------------------------------------------------
899 
device_start()900 void k055673_device::device_start()
901 {
902 	if (!palette().device().started())
903 		throw device_missing_dependencies();
904 
905 	// resolve callbacks
906 	m_k053247_cb.resolve();
907 
908 	int gfx_index = 0;
909 	u32 total;
910 
911 	static const gfx_layout spritelayout =  /* System GX sprite layout */
912 	{
913 		16,16,
914 		0,
915 		5,
916 		{ 32, 24, 16, 8, 0 },
917 		{ 0, 1, 2, 3, 4, 5, 6, 7, 40, 41, 42, 43, 44, 45, 46, 47 },
918 		{ 0, 10*8, 10*8*2, 10*8*3, 10*8*4, 10*8*5, 10*8*6, 10*8*7, 10*8*8,
919 			10*8*9, 10*8*10, 10*8*11, 10*8*12, 10*8*13, 10*8*14, 10*8*15 },
920 		16*16*5
921 	};
922 	static const gfx_layout spritelayout2 = /* Run and Gun sprite layout */
923 	{
924 		16,16,
925 		0,
926 		4,
927 		{ 24, 16, 8, 0 },
928 		{ 0, 1, 2, 3, 4, 5, 6, 7, 32, 33, 34, 35, 36, 37, 38, 39 },
929 		{ 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 },
930 		16*16*4
931 	};
932 	static const gfx_layout spritelayout3 = /* Lethal Enforcers II sprite layout */
933 	{
934 		16,16,
935 		0,
936 		8,
937 		{ 56, 48, 40, 32, 24, 16, 8, 0 },
938 		{  0,1,2,3,4,5,6,7,64+0,64+1,64+2,64+3,64+4,64+5,64+6,64+7 },
939 		{ 128*0, 128*1, 128*2,  128*3,  128*4,  128*5,  128*6,  128*7,
940 			128*8, 128*9, 128*10, 128*11, 128*12, 128*13, 128*14, 128*15 },
941 		16*16*8
942 	};
943 	static const gfx_layout spritelayout4 = /* System GX 6bpp sprite layout */
944 	{
945 		16,16,
946 		0,
947 		6,
948 		{ 40, 32, 24, 16, 8, 0 },
949 		{ 0, 1, 2, 3, 4, 5, 6, 7, 48, 49, 50, 51, 52, 53, 54, 55 },
950 		{ 0, 12*8, 12*8*2, 12*8*3, 12*8*4, 12*8*5, 12*8*6, 12*8*7, 12*8*8,
951 			12*8*9, 12*8*10, 12*8*11, 12*8*12, 12*8*13, 12*8*14, 12*8*15 },
952 		16*16*6
953 	};
954 	static const gfx_layout spritelayout5 = /* Pirate Ship layout */
955 	{
956 		16,16,
957 		0,
958 		4,
959 		{ 24, 8, 16, 0 },
960 		{ 0, 1, 2, 3, 4, 5, 6, 7, 32, 33, 34, 35, 36, 37, 38, 39 },
961 		{ 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 },
962 		16*16*4
963 	};
964 	u8 *s1, *s2, *d;
965 	long i;
966 	u16 *alt_k055673_rom;
967 	int size4;
968 
969 	alt_k055673_rom = (u16 *)&m_gfxrom[0];
970 
971 	/* decode the graphics */
972 	switch (m_bpp)
973 	{
974 		case K055673_LAYOUT_GX:
975 			size4 = (m_gfxrom.length()/(1024*1024))/5;
976 			size4 *= 4*1024*1024;
977 			/* set the # of tiles based on the 4bpp section */
978 			alt_k055673_rom = auto_alloc_array(machine(), u16, size4 * 5 / 2);
979 			d = (u8 *)alt_k055673_rom;
980 			// now combine the graphics together to form 5bpp
981 			s1 = (u8 *)&m_gfxrom[0]; // 4bpp area
982 			s2 = s1 + (size4);   // 1bpp area
983 			for (i = 0; i < size4; i+= 4)
984 			{
985 				*d++ = *s1++;
986 				*d++ = *s1++;
987 				*d++ = *s1++;
988 				*d++ = *s1++;
989 				*d++ = *s2++;
990 			}
991 
992 			total = size4 / 128;
993 			konami_decode_gfx(*this, gfx_index, (u8 *)alt_k055673_rom, total, &spritelayout, 5);
994 			break;
995 
996 		case K055673_LAYOUT_RNG:
997 			total = m_gfxrom.length() / (16*16/2);
998 			konami_decode_gfx(*this, gfx_index, (u8 *)alt_k055673_rom, total, &spritelayout2, 4);
999 			break;
1000 
1001 		case K055673_LAYOUT_PS:
1002 			total = m_gfxrom.length() / (16*16/2);
1003 			konami_decode_gfx(*this, gfx_index, (u8 *)alt_k055673_rom, total, &spritelayout5, 4);
1004 			break;
1005 
1006 		case K055673_LAYOUT_LE2:
1007 			total = m_gfxrom.length() / (16*16);
1008 			konami_decode_gfx(*this, gfx_index, (u8 *)alt_k055673_rom, total, &spritelayout3, 8);
1009 			break;
1010 
1011 		case K055673_LAYOUT_GX6:
1012 			total = m_gfxrom.length() / (16*16*6/8);
1013 			konami_decode_gfx(*this, gfx_index, (u8 *)alt_k055673_rom, total, &spritelayout4, 6);
1014 			break;
1015 
1016 		default:
1017 			fatalerror("Unsupported layout\n");
1018 	}
1019 
1020 	if (VERBOSE && !(palette().shadows_enabled()))
1021 		popmessage("driver should use VIDEO_HAS_SHADOWS");
1022 
1023 	m_z_rejection = -1;
1024 	m_gfx = gfx(gfx_index);
1025 	m_objcha_line = CLEAR_LINE;
1026 	m_ram = std::make_unique<u16[]>(0x1000/2);
1027 
1028 	memset(m_ram.get(),  0, 0x1000);
1029 	std::fill(std::begin(m_kx46_regs), std::end(m_kx46_regs), 0);
1030 	std::fill(std::begin(m_kx47_regs), std::end(m_kx47_regs), 0);
1031 
1032 	save_pointer(NAME(m_ram), 0x800);
1033 	save_item(NAME(m_kx46_regs));
1034 	save_item(NAME(m_kx47_regs));
1035 	save_item(NAME(m_objcha_line));
1036 }
1037 
1038 //-------------------------------------------------
1039 //  device_reset - device-specific reset
1040 //-------------------------------------------------
1041 
1042 
1043 DEFINE_DEVICE_TYPE(K053247, k053247_device, "k053247", "K053246/K053247 Sprite Generator")
1044 decltype(K053247) K053246 = K053247;
1045 
k053247_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)1046 k053247_device::k053247_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
1047 	: k053247_device(mconfig, K053247, tag, owner, clock)
1048 {
1049 }
1050 
k053247_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,u32 clock)1051 k053247_device::k053247_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
1052 	: device_t(mconfig, type, tag, owner, clock)
1053 	, device_video_interface(mconfig, *this)
1054 	, device_gfx_interface(mconfig, *this, nullptr)
1055 	, m_k053247_cb(*this)
1056 	, m_gfxrom(*this, DEVICE_SELF)
1057 	, m_gfx_num(0)
1058 {
1059 	clear_all();
1060 }
1061 
1062 //-------------------------------------------------
1063 //  device_start - device-specific startup
1064 //-------------------------------------------------
1065 
device_start()1066 void k053247_device::device_start()
1067 {
1068 	if (!palette().device().started())
1069 		throw device_missing_dependencies();
1070 
1071 	// resolve callbacks
1072 	m_k053247_cb.resolve();
1073 
1074 	u32 total;
1075 	static const gfx_layout spritelayout =
1076 	{
1077 		16,16,
1078 		0,
1079 		4,
1080 		{ 0, 1, 2, 3 },
1081 		{ 2*4, 3*4, 0*4, 1*4, 6*4, 7*4, 4*4, 5*4,
1082 				10*4, 11*4, 8*4, 9*4, 14*4, 15*4, 12*4, 13*4 },
1083 		{ 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64,
1084 				8*64, 9*64, 10*64, 11*64, 12*64, 13*64, 14*64, 15*64 },
1085 		128*8
1086 	};
1087 
1088 	/* decode the graphics */
1089 	switch (m_bpp)
1090 	{
1091 	case NORMAL_PLANE_ORDER:
1092 		total = m_gfxrom.length() / 128;
1093 		konami_decode_gfx(*this, m_gfx_num, (u8 *)&m_gfxrom[0], total, &spritelayout, 4);
1094 		break;
1095 
1096 	default:
1097 		fatalerror("Unsupported plane_order\n");
1098 	}
1099 
1100 	if (VERBOSE)
1101 	{
1102 		if (screen().format() == BITMAP_FORMAT_RGB32)
1103 		{
1104 			if (!palette().shadows_enabled() || !palette().hilights_enabled())
1105 				popmessage("driver missing SHADOWS or HIGHLIGHTS flag");
1106 		}
1107 		else
1108 		{
1109 			if (!(palette().shadows_enabled()))
1110 				popmessage("driver should use VIDEO_HAS_SHADOWS");
1111 		}
1112 	}
1113 
1114 	m_gfx = gfx(m_gfx_num);
1115 
1116 	m_ram = make_unique_clear<u16[]>(0x1000 / 2);
1117 
1118 	save_pointer(NAME(m_ram), 0x1000 / 2);
1119 	save_item(NAME(m_kx46_regs));
1120 	save_item(NAME(m_kx47_regs));
1121 	save_item(NAME(m_objcha_line));
1122 	save_item(NAME(m_z_rejection));
1123 }
1124 
1125 //-------------------------------------------------
1126 //  device_reset - device-specific reset
1127 //-------------------------------------------------
1128 
device_reset()1129 void k053247_device::device_reset()
1130 {
1131 	m_z_rejection = -1;
1132 	m_objcha_line = CLEAR_LINE;
1133 
1134 	std::fill(std::begin(m_kx46_regs), std::end(m_kx46_regs), 0);
1135 	std::fill(std::begin(m_kx47_regs), std::end(m_kx47_regs), 0);
1136 }
1137 
1138 
1139 /*
1140     In a K053247+K055555 setup objects with Z-code 0x00 should be ignored
1141     when PRFLIP is cleared, while objects with Z-code 0xff should be
1142     ignored when PRFLIP is set.
1143 
1144     These behaviors can also be seen in older K053245(6)+K053251 setups.
1145     Bucky'O Hare, The Simpsons and Sunset Riders rely on their implications
1146     to prepare and retire sprites. They probably apply to many other Konami
1147     games but it's hard to tell because most artifacts have been filtered
1148     by exclusion sort.
1149 
1150     A driver may call K05324x_set_z_rejection() to set which zcode to ignore.
1151     Parameter:
1152                -1 = accept all(default)
1153         0x00-0xff = zcode to ignore
1154 */
1155 
k053247_set_z_rejection(int zcode)1156 void k053247_device::k053247_set_z_rejection(int zcode)
1157 {
1158 	m_z_rejection = zcode;
1159 }
1160