1 #define VERBOSE 0
2 #define GX_DEBUG 0
3 
4 /**************************************************************************
5  *
6  * machine/konamigx.c - contains various System GX hardware abstractions
7  *
8  * Currently includes: TMS57002 skipper/simulator to make the sound 68k happy.
9  *
10  */
11 
12 #include "driver.h"
13 #include "state.h"
14 #include "vidhrdw/konamiic.h"
15 #include "machine/konamigx.h"
16 #include "machine/random.h"
17 #include "math.h"
18 
19 
20 static struct
21 {
22 	unsigned char control;
23 	unsigned char program[1024];
24 	unsigned int tables[256];
25 	int curpos;
26 	int bytepos;
27 	unsigned int tmp;
28 } tms57002;
29 
30 static int ldw = 0;
31 
32 
tms57002_init(void)33 void tms57002_init(void)
34 {
35 	tms57002.control = 0;
36 }
37 
chk_ldw(void)38 static void chk_ldw(void)
39 {
40 	ldw = 0;
41 }
42 
WRITE_HANDLER(tms57002_control_w)43 WRITE_HANDLER( tms57002_control_w )
44 {
45 	chk_ldw();
46 
47 	switch(tms57002.control)
48 	{
49 		case 0xf8:
50 		break;
51 		case 0xf0:
52 		break;
53 	}
54 
55 	tms57002.control = data;
56 
57 	switch(data)
58 	{
59 		case 0xf8: // Program write
60 		case 0xf0: // Table write
61 			tms57002.curpos = 0;
62 			tms57002.bytepos = 3;
63 			tms57002.tmp = 0;
64 		break;
65 		case 0xf4: // Entry write
66 			tms57002.curpos = -1;
67 			tms57002.bytepos = 3;
68 			tms57002.tmp = 0;
69 		break;
70 		case 0xfc: // Checksum (?) Status (?)
71 			tms57002.bytepos = 3;
72 			tms57002.tmp = 0;
73 		break;
74 		case 0xff: // Standby
75 		break;
76 		case 0xfe: // Irq
77 			/* (place ack of timer IRQ here) */
78 		break;
79 		default:
80 		break;
81 	}
82 }
83 
READ_HANDLER(tms57002_status_r)84 READ_HANDLER( tms57002_status_r )
85 {
86 	chk_ldw();
87 	return 1;
88 }
89 
WRITE_HANDLER(tms57002_data_w)90 WRITE_HANDLER( tms57002_data_w )
91 {
92 	switch(tms57002.control)
93 	{
94 		case 0xf8:
95 			tms57002.program[tms57002.curpos++] = data;
96 		break;
97 		case 0xf0:
98 			tms57002.tmp |= data << (8*tms57002.bytepos);
99 			tms57002.bytepos--;
100 			if (tms57002.bytepos < 0)
101 			{
102 				tms57002.bytepos = 3;
103 				tms57002.tables[tms57002.curpos++] =  tms57002.tmp;
104 				tms57002.tmp = 0;
105 			}
106 		break;
107 		case 0xf4:
108 			if (tms57002.curpos == -1)
109 	  			tms57002.curpos = data;
110 			else
111 			{
112 				tms57002.tmp |= data << (8*tms57002.bytepos);
113 				tms57002.bytepos--;
114 
115 				if (tms57002.bytepos < 0)
116 				{
117 					tms57002.bytepos = 3;
118 					tms57002.tables[tms57002.curpos] =  tms57002.tmp;
119 					tms57002.tmp = 0;
120 					tms57002.curpos = -1;
121 				}
122 			}
123 		break;
124 		default:
125 			ldw++;
126 		break;
127 	}
128 }
129 
READ_HANDLER(tms57002_data_r)130 READ_HANDLER( tms57002_data_r )
131 {
132 	unsigned char res;
133 
134 	chk_ldw();
135 
136 	switch(tms57002.control)
137 	{
138 		case 0xfc:
139 			res = tms57002.tmp >> (8*tms57002.bytepos);
140 			tms57002.bytepos--;
141 
142 			if(tms57002.bytepos < 0) tms57002.bytepos = 3;
143 		return res;
144 	}
145 
146 	return 0;
147 }
148 
149 
READ16_HANDLER(tms57002_data_word_r)150 READ16_HANDLER( tms57002_data_word_r )
151 {
152 	return(tms57002_data_r(0));
153 }
154 
READ16_HANDLER(tms57002_status_word_r)155 READ16_HANDLER( tms57002_status_word_r )
156 {
157 	return(tms57002_status_r(0));
158 }
159 
WRITE16_HANDLER(tms57002_control_word_w)160 WRITE16_HANDLER( tms57002_control_word_w )
161 {
162 	tms57002_control_w(0, data);
163 }
164 
WRITE16_HANDLER(tms57002_data_word_w)165 WRITE16_HANDLER( tms57002_data_word_w )
166 {
167 	tms57002_data_w(0, data);
168 }
169 
170 
171 
172 /***************************************************************************/
173 /*                                                                         */
174 /*                     2nd-Tier GX/MW Graphics Functions                   */
175 /*                                                                         */
176 /***************************************************************************/
177 
178 // Hardcoded constants and custom z-buffer
179 #define GX_BMPPW (512+32)
180 
181 #if GX_DEBUG
182 	#define GX_ZBUFW     512
183 	#define GX_ZBUFH     384
184 	#define GX_ZPAGESIZE 0x300000
185 	#define GX_ZBUFSIZE  0x600000
186 #else
187 	#define GX_ZBUFW     384
188 	#define GX_ZBUFH     224
189 	#define GX_ZPAGESIZE 0x150000
190 	#define GX_ZBUFSIZE  0x2a0000
191 #endif
192 
193 static UINT8 *gx_objzbuf, *gx_shdzbuf;
194 
195 
196 // Localized K053936/ROZ+
197 #define K053936_MAX_CHIPS 2
198 
199 static struct rectangle K053936_cliprect[K053936_MAX_CHIPS] = {{0,0,0,0},{0,0,0,0}};
200 static int K053936_offset[K053936_MAX_CHIPS][2] = {{0,0},{0,0}};
201 static int K053936_clip_enabled[K053936_MAX_CHIPS] = {0,0};
202 
203 
K053936GP_set_offset(int chip,int xoffs,int yoffs)204 void K053936GP_set_offset(int chip, int xoffs, int yoffs) { K053936_offset[chip][0] = xoffs; K053936_offset[chip][1] = yoffs; }
205 
K053936GP_clip_enable(int chip,int status)206 void K053936GP_clip_enable(int chip, int status) { K053936_clip_enabled[chip] = status; }
207 
K053936GP_set_cliprect(int chip,int minx,int maxx,int miny,int maxy)208 void K053936GP_set_cliprect(int chip, int minx, int maxx, int miny, int maxy)
209 {
210 	struct rectangle *cliprect = &K053936_cliprect[chip];
211 	cliprect->min_x = minx;
212 	cliprect->max_x = maxx;
213 	cliprect->min_y = miny;
214 	cliprect->max_y = maxy;
215 }
216 
217 #define BLEND32_MACRO {  \
218 	eax = pal_base[eax]; \
219 	ebx = eax;           \
220 	edx = eax;           \
221 	eax >>= 8;           \
222 	ebx >>= 16;          \
223 	eax &= 0xff;         \
224 	edx &= 0xff;         \
225 	ebx = esi[ebx];      \
226 	eax = esi[eax];      \
227 	ebx <<= 16;          \
228 	eax <<= 8;           \
229 	ebx |= esi[edx];     \
230 	edx = dst_ptr[ecx];  \
231 	ebx |= eax;          \
232 	eax = edx;           \
233 	ebp = ebx;           \
234 	ebx = edx;           \
235 	edx >>= 8;           \
236 	eax >>= 16;          \
237 	edx &= 0xff;         \
238 	ebx &= 0xff;         \
239 	eax = edi[eax];      \
240 	edx = edi[edx];      \
241 	eax <<= 16;          \
242 	edx <<= 8;           \
243 	eax |= edi[ebx];     \
244 	edx += ebp;          \
245 	edx += eax;          \
246 	dst_ptr[ecx] = edx; }
247 
K053936GP_copyroz32clip(struct mame_bitmap * dst_bitmap,struct mame_bitmap * src_bitmap,const struct rectangle * dst_cliprect,const struct rectangle * src_cliprect,UINT32 _startx,UINT32 _starty,int _incxx,int _incxy,int _incyx,int _incyy,int tilebpp,int blend,int clip)248 static INLINE void K053936GP_copyroz32clip( struct mame_bitmap *dst_bitmap, struct mame_bitmap *src_bitmap,
249 		const struct rectangle *dst_cliprect, const struct rectangle *src_cliprect,
250 		UINT32 _startx,UINT32 _starty,int _incxx,int _incxy,int _incyx,int _incyy,
251 		int tilebpp, int blend, int clip )
252 {
253 	static int colormask[8]={1,3,7,0xf,0x1f,0x3f,0x7f,0xff};
254 
255 	int cy, cx;
256 	register int eax, ebx, edx, ecx;
257 	int src_pitch, incxy, incxx;
258 	int src_minx, src_maxx, src_miny, src_maxy, cmask, ebp;
259 	UINT16 *src_base;
260 	UINT32 *pal_base;
261 	const UINT8  *esi, *edi;
262 	UINT32 *dst_ptr;
263 
264 	int tx, dst_pitch;
265 	UINT32 *dst_base;
266 	int starty, incyy, startx, incyx, ty, sx, sy;
267 
268 	incxy = _incxy; incxx = _incxx; incyy = _incyy; incyx = _incyx;
269 	starty = _starty; startx = _startx;
270 
271 	if (src_cliprect && clip) // set source clip range to some extreme values when disabled
272 	{
273 		src_minx = src_cliprect->min_x;
274 		src_maxx = src_cliprect->max_x;
275 		src_miny = src_cliprect->min_y;
276 		src_maxy = src_cliprect->max_y;
277 	}
278 	else { src_minx = src_miny = -0x10000; src_maxx = src_maxy = 0x10000; }
279 
280 	if (dst_cliprect) // set target clip range
281 	{
282 		sx = dst_cliprect->min_x;
283 		tx = dst_cliprect->max_x - sx + 1;
284 		sy = dst_cliprect->min_y;
285 		ty = dst_cliprect->max_y - sy + 1;
286 
287 		startx += sx * incxx + sy * incyx;
288 		starty += sx * incxy + sy * incyy;
289 	}
290 	else { sx = sy = 0; tx = dst_bitmap->width; ty = dst_bitmap->height; }
291 
292 	// adjust entry points and other loop constants
293 	dst_pitch = dst_bitmap->rowpixels;
294 	dst_base = (UINT32*)dst_bitmap->base + sy * dst_pitch + sx + tx;
295 	ecx = tx = -tx;
296 
297 	tilebpp = (tilebpp-1) & 7;
298 	pal_base = Machine->remapped_colortable;
299 	cmask = colormask[tilebpp];
300 
301 	src_pitch = src_bitmap->rowpixels;
302 	src_base = src_bitmap->base;
303 
304 	src_miny *= src_pitch;
305 	src_maxy *= src_pitch;
306 
307 	dst_ptr = dst_base;
308 	cy = starty;
309 	cx = startx;
310 
311 	if (blend >=0)
312 	{
313 		dst_base += dst_pitch;
314 		starty += incyy;
315 		startx += incyx;
316 
317 		if (!blend)
318 			goto DRAW_SOLID;
319 		else
320 		{
321 			esi = alpha_cache.alphas;
322 			edi = alpha_cache.alphad;
323 			goto DRAW_ALPHA;
324 		}
325 	}
326 	else
327 	{
328 		if ((sy & 1) ^ (blend & 1))
329 		{
330 			if (ty <= 1) return;
331 
332 			dst_ptr += dst_pitch;
333 			cy += incyy;
334 			cx += incyx;
335 		}
336 
337 		if (ty > 1)
338 		{
339 			ty >>= 1;
340 			dst_pitch <<= 1;
341 			incyy <<= 1;
342 			incyx <<= 1;
343 
344 			dst_base = dst_ptr + dst_pitch;
345 			starty = cy + incyy;
346 			startx = cx + incyx;
347 		}
348 	}
349 
350 
351 	DRAW_SOLID:
352 	do {
353 		do {
354 			eax = cy;      ebx = cx;
355 			eax >>= 16;    ebx >>= 16;
356 			eax &= 0x1fff; ebx &= 0x1fff;
357 			eax = (eax<<5) + (eax<<13); //eax *= src_pitch;
358 			cy += incxy;   cx += incxx;
359 			if (ebx < src_minx || ebx > src_maxx || eax < src_miny || eax > src_maxy) continue;
360 
361 			eax = src_base[eax+ebx];
362 			if (!(eax & cmask)) continue;
363 
364 			dst_ptr[ecx] = pal_base[eax];
365 		}
366 		while (++ecx);
367 
368 		ecx = tx;
369 		dst_ptr = dst_base; dst_base += dst_pitch;
370 		cy = starty; starty += incyy;
371 		cx = startx; startx += incyx;
372 	} while (--ty);
373 	return;
374 
375 
376 	DRAW_ALPHA:
377 	do {
378 		do {
379 			eax = cy;      ebx = cx;
380 			eax >>= 16;    ebx >>= 16;
381 			eax &= 0x1fff; ebx &= 0x1fff;
382 			eax = (eax<<5) + (eax<<13); //eax *= src_pitch;
383 			cy += incxy;   cx += incxx;
384 			if (ebx < src_minx || ebx > src_maxx || eax < src_miny || eax > src_maxy) continue;
385 
386 			eax = src_base[eax+ebx];
387 			if (!(eax & cmask)) continue;
388 
389 			BLEND32_MACRO
390 		}
391 		while (++ecx);
392 
393 		ecx = tx;
394 		dst_ptr = dst_base; dst_base += dst_pitch;
395 		cy = starty; starty += incyy;
396 		cx = startx; startx += incyx;
397 	} while (--ty);
398 }
399 
400 // adpoted from generic K053936_zoom_draw()
K053936GP_zoom_draw(int chip,data16_t * ctrl,data16_t * linectrl,struct mame_bitmap * bitmap,const struct rectangle * cliprect,struct tilemap * tilemap,int tilebpp,int blend)401 static void K053936GP_zoom_draw(int chip, data16_t *ctrl, data16_t *linectrl,
402 		struct mame_bitmap *bitmap, const struct rectangle *cliprect, struct tilemap *tilemap,
403 		int tilebpp, int blend)
404 {
405 	struct mame_bitmap *src_bitmap;
406 	struct rectangle *src_cliprect;
407 	data16_t *lineaddr;
408 
409 	struct rectangle my_clip;
410 	UINT32 startx, starty;
411 	int incxx, incxy, incyx, incyy, y, maxy, clip;
412 
413 	src_bitmap = tilemap_get_pixmap(tilemap);
414 	src_cliprect = &K053936_cliprect[chip];
415 	clip = K053936_clip_enabled[chip];
416 
417 	if (ctrl[0x07] & 0x0040)    /* "super" mode */
418 	{
419 		my_clip.min_x = cliprect->min_x;
420 		my_clip.max_x = cliprect->max_x;
421 		y = cliprect->min_y;
422 		maxy = cliprect->max_y;
423 
424 		while (y <= maxy)
425 		{
426 			lineaddr = linectrl + ( ((y - K053936_offset[chip][1]) & 0x1ff) << 2);
427 			my_clip.min_y = my_clip.max_y = y;
428 
429 			startx = (INT16)(lineaddr[0] + ctrl[0x00]) << 8;
430 			starty = (INT16)(lineaddr[1] + ctrl[0x01]) << 8;
431 			incxx  = (INT16)(lineaddr[2]);
432 			incxy  = (INT16)(lineaddr[3]);
433 
434 			if (ctrl[0x06] & 0x8000) incxx <<= 8;
435 			if (ctrl[0x06] & 0x0080) incxy <<= 8;
436 
437 			startx -= K053936_offset[chip][0] * incxx;
438 			starty -= K053936_offset[chip][0] * incxy;
439 
440 			K053936GP_copyroz32clip(bitmap, src_bitmap, &my_clip, src_cliprect,
441 					startx<<5, starty<<5, incxx<<5, incxy<<5, 0, 0,
442 					tilebpp, blend, clip);
443 			y++;
444 		}
445 	}
446 	else    /* "simple" mode */
447 	{
448 		startx = (INT16)(ctrl[0x00]) << 8;
449 		starty = (INT16)(ctrl[0x01]) << 8;
450 		incyx  = (INT16)(ctrl[0x02]);
451 		incyy  = (INT16)(ctrl[0x03]);
452 		incxx  = (INT16)(ctrl[0x04]);
453 		incxy  = (INT16)(ctrl[0x05]);
454 
455 		if (ctrl[0x06] & 0x4000) { incyx <<= 8; incyy <<= 8; }
456 		if (ctrl[0x06] & 0x0040) { incxx <<= 8; incxy <<= 8; }
457 
458 		startx -= K053936_offset[chip][1] * incyx;
459 		starty -= K053936_offset[chip][1] * incyy;
460 
461 		startx -= K053936_offset[chip][0] * incxx;
462 		starty -= K053936_offset[chip][0] * incxy;
463 
464 		K053936GP_copyroz32clip(bitmap, src_bitmap, cliprect, src_cliprect,
465 				startx<<5, starty<<5, incxx<<5, incxy<<5, incyx<<5, incyy<<5,
466 				tilebpp, blend, clip);
467 	}
468 }
469 
K053936GP_0_zoom_draw(struct mame_bitmap * bitmap,const struct rectangle * cliprect,struct tilemap * tilemap,int tilebpp,int blend)470 void K053936GP_0_zoom_draw(struct mame_bitmap *bitmap, const struct rectangle *cliprect,
471 		struct tilemap *tilemap, int tilebpp, int blend)
472 {
473 	K053936GP_zoom_draw(0,K053936_0_ctrl,K053936_0_linectrl,bitmap,cliprect,tilemap,tilebpp,blend);
474 }
475 
K053936GP_1_zoom_draw(struct mame_bitmap * bitmap,const struct rectangle * cliprect,struct tilemap * tilemap,int tilebpp,int blend)476 void K053936GP_1_zoom_draw(struct mame_bitmap *bitmap, const struct rectangle *cliprect,
477 		struct tilemap *tilemap, int tilebpp, int blend)
478 {
479 	K053936GP_zoom_draw(1,K053936_1_ctrl,K053936_1_linectrl,bitmap,cliprect,tilemap,tilebpp,blend);
480 }
481 
482 
483 
484 /*
485 	Parameter Notes
486 	---------------
487 	clip    : *caller must supply a pointer to target clip rectangle
488 	alpha   : 0 = invisible, 255 = solid
489 	drawmode:
490 		0 = all pens solid
491 		1 = solid pens only
492 		2 = all pens solid with alpha blending
493 		3 = solid pens only with alpha blending
494 		4 = shadow pens only
495 		5 = all pens shadow
496 	zcode   : 0 = closest, 255 = furthest (pixel z-depth), -1 = disable depth buffers and shadows
497 	pri     : 0 = topmost, 255 = backmost (pixel priority)
498 */
499 
zdrawgfxzoom32GP(struct mame_bitmap * bitmap,const struct GfxElement * gfx,const struct rectangle * cliprect,unsigned int code,unsigned int color,int flipx,int flipy,int sx,int sy,int scalex,int scaley,int alpha,int drawmode,int zcode,int pri)500 static INLINE void zdrawgfxzoom32GP( struct mame_bitmap *bitmap, const struct GfxElement *gfx, const struct rectangle *cliprect,
501 		unsigned int code, unsigned int color, int flipx, int flipy, int sx, int sy,
502 		int scalex, int scaley, int alpha, int drawmode, int zcode, int pri)
503 {
504 #define FP     19
505 #define FPONE  (1<<FP)
506 #define FPHALF (1<<(FP-1))
507 #define FPENT  0
508 
509 	// inner loop
510 	UINT8  *src_ptr;
511 	int src_x;
512 	register int eax, ebx, edx, ecx;
513 	int src_fx, src_fdx;
514 	int shdpen, ebp;
515 	UINT8  z8, db0, p8, db1;
516 	UINT8  *ozbuf_ptr;
517 	UINT8  *szbuf_ptr;
518 	UINT32 *pal_base;
519 	UINT32 *shd_base;
520 	UINT32 *dst_ptr;
521 	const UINT8  *esi, *edi;
522 
523 	// outter loop
524 	int src_fby, src_fdy, src_fbx;
525 	UINT8 *src_base;
526 	int dst_w, dst_h;
527 
528 	// one-time
529 	int nozoom, granularity;
530 	int src_fw, src_fh;
531 	int dst_minx, dst_maxx, dst_miny, dst_maxy;
532 	int dst_skipx, dst_skipy, dst_x, dst_y, dst_lastx, dst_lasty;
533 	int src_pitch, dst_pitch;
534 
535 
536 	// cull illegal and transparent objects
537 	if (!scalex || !scaley) return;
538 
539 	// find shadow pens and cull invisible shadows
540 	granularity = shdpen = gfx->color_granularity;
541 	shdpen--;
542 
543 	if (zcode >= 0)
544 	{
545 		if (drawmode == 5) { drawmode = 4; shdpen = 1; }
546 	}
547 	else
548 		if (drawmode >= 4) return;
549 
550 	// alpha blend necessary?
551 	if (drawmode & 2)
552 	{
553 		if (alpha <= 0) return;
554 		if (alpha >= 255) drawmode &= ~2;
555 	}
556 
557 	esi = alpha_cache.alphas;
558 	edi = alpha_cache.alphad;
559 
560 	// fill internal data structure with default values
561 	ozbuf_ptr  = gx_objzbuf;
562 	szbuf_ptr  = gx_shdzbuf;
563 
564 	src_pitch = 16;
565 	src_fw    = 16;
566 	src_fh    = 16;
567 	src_base  = gfx->gfxdata + (code % gfx->total_elements) * gfx->char_modulo;
568 
569 	pal_base  = gfx->colortable + (color % gfx->total_colors) * granularity;
570 	shd_base  = (UINT32 *)palette_shadow_table;
571 
572 	dst_ptr   = bitmap->base;
573 	dst_pitch = GX_BMPPW;
574 	dst_minx  = cliprect->min_x;
575 	dst_maxx  = cliprect->max_x;
576 	dst_miny  = cliprect->min_y;
577 	dst_maxy  = cliprect->max_y;
578 	dst_x     = sx;
579 	dst_y     = sy;
580 
581 	// cull off-screen objects
582 	if (dst_x > dst_maxx || dst_y > dst_maxy) return;
583 	if ((nozoom = (scalex == 0x10000 && scaley == 0x10000)))
584 	{
585 		dst_h = dst_w = 16;
586 		src_fdy = src_fdx = 1;
587 	}
588 	else
589 	{
590 		dst_w = ((scalex<<4)+0x8000)>>16;
591 		dst_h = ((scaley<<4)+0x8000)>>16;
592 		if (!dst_w || !dst_h) return;
593 
594 		src_fw <<= FP;
595 		src_fh <<= FP;
596 		src_fdx = src_fw / dst_w;
597 		src_fdy = src_fh / dst_h;
598 	}
599 	dst_lastx = dst_x + dst_w - 1;
600 	if (dst_lastx < dst_minx) return;
601 	dst_lasty = dst_y + dst_h - 1;
602 	if (dst_lasty < dst_miny) return;
603 
604 	// clip destination
605 	dst_skipx = 0;
606 	eax = dst_minx;  if ((eax -= dst_x) > 0) { dst_skipx = eax;  dst_w -= eax;  dst_x = dst_minx; }
607 	eax = dst_lastx; if ((eax -= dst_maxx) > 0) dst_w -= eax;
608 	dst_skipy = 0;
609 	eax = dst_miny;  if ((eax -= dst_y) > 0) { dst_skipy = eax;  dst_h -= eax;  dst_y = dst_miny; }
610 	eax = dst_lasty; if ((eax -= dst_maxy) > 0) dst_h -= eax;
611 
612 	// calculate zoom factors and clip source
613 	if (nozoom)
614 	{
615 		if (!flipx) src_fbx = 0; else { src_fbx = src_fw - 1; src_fdx = -src_fdx; }
616 		if (!flipy) src_fby = 0; else { src_fby = src_fh - 1; src_fdy = -src_fdy; src_pitch = -src_pitch; }
617 	}
618 	else
619 	{
620 		if (!flipx) src_fbx = FPENT; else { src_fbx = src_fw - FPENT - 1; src_fdx = -src_fdx; }
621 		if (!flipy) src_fby = FPENT; else { src_fby = src_fh - FPENT - 1; src_fdy = -src_fdy; }
622 	}
623 	src_fbx += dst_skipx * src_fdx;
624 	src_fby += dst_skipy * src_fdy;
625 
626 	// adjust insertion points and pre-entry constants
627 	eax = (dst_y - dst_miny) * GX_ZBUFW + (dst_x - dst_minx) + dst_w;
628 	db0 = z8 = (UINT8)zcode;
629 	db1 = p8 = (UINT8)pri;
630 	ozbuf_ptr += eax;
631 	szbuf_ptr += eax << 1;
632 	dst_ptr += dst_y * dst_pitch + dst_x + dst_w;
633 	dst_w = -dst_w;
634 
635 	if (!nozoom) goto DRAWZOOM;
636 
637 	src_ptr = src_base + (src_fby<<4) + src_fbx;
638 	src_fdy = src_fdx * dst_w + src_pitch;
639 	ecx = dst_w;
640 
641 	if (zcode < 0) // no shadow and z-buffering
642 	{
643 		do {
644 			do {
645 				eax = *src_ptr;
646 				src_ptr += src_fdx;
647 				if (!eax || eax >= shdpen) continue;
648 				dst_ptr[ecx] = pal_base[eax];
649 			}
650 			while (++ecx);
651 
652 			src_ptr += src_fdy;
653 			dst_ptr += GX_BMPPW;
654 			ecx = dst_w;
655 		}
656 		while (--dst_h);
657 	}
658 	else if (drawmode == 0) // all pens solid
659 	{
660 		do {
661 			do {
662 				eax = *src_ptr;
663 				src_ptr += src_fdx;
664 				if (!eax || ozbuf_ptr[ecx] < z8) continue;
665 				eax = pal_base[eax];
666 				ozbuf_ptr[ecx] = z8;
667 				dst_ptr[ecx] = eax;
668 			}
669 			while (++ecx);
670 
671 			src_ptr += src_fdy;
672 			ozbuf_ptr += GX_ZBUFW;
673 			dst_ptr += GX_BMPPW;
674 			ecx = dst_w;
675 		}
676 		while (--dst_h);
677 	}
678 	else if (drawmode == 1) // solid pens only
679 	{
680 		do {
681 			do {
682 				eax = *src_ptr;
683 				src_ptr += src_fdx;
684 				if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
685 				eax = pal_base[eax];
686 				ozbuf_ptr[ecx] = z8;
687 				dst_ptr[ecx] = eax;
688 			}
689 			while (++ecx);
690 
691 			src_ptr += src_fdy;
692 			ozbuf_ptr += GX_ZBUFW;
693 			dst_ptr += GX_BMPPW;
694 			ecx = dst_w;
695 		}
696 		while (--dst_h);
697 	}
698 	else if (drawmode == 2) // all pens solid with alpha blending
699 	{
700 		do {
701 			do {
702 				eax = *src_ptr;
703 				src_ptr += src_fdx;
704 				if (!eax || ozbuf_ptr[ecx] < z8) continue;
705 				ozbuf_ptr[ecx] = z8;
706 
707 				BLEND32_MACRO
708 			}
709 			while (++ecx);
710 
711 			src_ptr += src_fdy;
712 			ozbuf_ptr += GX_ZBUFW;
713 			dst_ptr += GX_BMPPW;
714 			ecx = dst_w;
715 		}
716 		while (--dst_h);
717 	}
718 	else if (drawmode == 3) // solid pens only with alpha blending
719 	{
720 		do {
721 			do {
722 				eax = *src_ptr;
723 				src_ptr += src_fdx;
724 				if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
725 				ozbuf_ptr[ecx] = z8;
726 
727 				BLEND32_MACRO
728 			}
729 			while (++ecx);
730 
731 			src_ptr += src_fdy;
732 			ozbuf_ptr += GX_ZBUFW;
733 			dst_ptr += GX_BMPPW;
734 			ecx = dst_w;
735 		}
736 		while (--dst_h);
737 	}
738 	else if (drawmode == 4) // shadow pens only
739 	{
740 		do {
741 			do {
742 				eax = *src_ptr;
743 				src_ptr += src_fdx;
744 				if (eax < shdpen || szbuf_ptr[ecx*2] < z8 || szbuf_ptr[ecx*2+1] <= p8) continue;
745 				eax = dst_ptr[ecx];
746 				szbuf_ptr[ecx*2] = z8;
747 				szbuf_ptr[ecx*2+1] = p8;
748 				eax = (eax>>9&0x7c00) | (eax>>6&0x03e0) | (eax>>3&0x001f);
749 				dst_ptr[ecx] = shd_base[eax];
750 			}
751 			while (++ecx);
752 
753 			src_ptr += src_fdy;
754 			szbuf_ptr += (GX_ZBUFW<<1);
755 			dst_ptr += GX_BMPPW;
756 			ecx = dst_w;
757 		}
758 		while (--dst_h);
759 	}
760 	return;
761 
762 	DRAWZOOM:
763 
764 	ecx = src_fby;   src_fby += src_fdy;
765 	ecx >>= FP;      src_fx = src_fbx;
766 	src_x = src_fbx; src_fx += src_fdx;
767 	ecx <<= 4;       src_ptr = src_base;
768 	src_x >>= FP;    src_ptr += ecx;
769 	ecx = dst_w;
770 
771 	if (zcode < 0) // no shadow and z-buffering
772 	{
773 		do {
774 			do {
775 				eax = src_ptr[src_x];
776 				src_x = src_fx;
777 				src_fx += src_fdx;
778 				src_x >>= FP;
779 				if (!eax || eax >= shdpen) continue;
780 				dst_ptr [ecx] = pal_base[eax];
781 			}
782 			while (++ecx);
783 
784 			ecx = src_fby;   src_fby += src_fdy;
785 			dst_ptr += GX_BMPPW;
786 			ecx >>= FP;      src_fx = src_fbx;
787 			src_x = src_fbx; src_fx += src_fdx;
788 			ecx <<= 4;       src_ptr = src_base;
789 			src_x >>= FP;    src_ptr += ecx;
790 			ecx = dst_w;
791 		}
792 		while (--dst_h);
793 	}
794 	else if (drawmode == 0) // all pens solid
795 	{
796 		do {
797 			do {
798 				eax = src_ptr[src_x];
799 				src_x = src_fx;
800 				src_fx += src_fdx;
801 				src_x >>= FP;
802 				if (!eax || ozbuf_ptr[ecx] < z8) continue;
803 				eax = pal_base[eax];
804 				ozbuf_ptr[ecx] = z8;
805 				dst_ptr [ecx] = eax;
806 			}
807 			while (++ecx);
808 
809 			ecx = src_fby;   src_fby += src_fdy;
810 			ozbuf_ptr += GX_ZBUFW;
811 			dst_ptr += GX_BMPPW;
812 			ecx >>= FP;      src_fx = src_fbx;
813 			src_x = src_fbx; src_fx += src_fdx;
814 			ecx <<= 4;       src_ptr = src_base;
815 			src_x >>= FP;    src_ptr += ecx;
816 			ecx = dst_w;
817 		}
818 		while (--dst_h);
819 	}
820 	else if (drawmode == 1) // solid pens only
821 	{
822 		do {
823 			do {
824 				eax = src_ptr[src_x];
825 				src_x = src_fx;
826 				src_fx += src_fdx;
827 				src_x >>= FP;
828 				if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
829 				eax = pal_base[eax];
830 				ozbuf_ptr[ecx] = z8;
831 				dst_ptr [ecx] = eax;
832 			}
833 			while (++ecx);
834 
835 			ecx = src_fby;   src_fby += src_fdy;
836 			ozbuf_ptr += GX_ZBUFW;
837 			dst_ptr += GX_BMPPW;
838 			ecx >>= FP;      src_fx = src_fbx;
839 			src_x = src_fbx; src_fx += src_fdx;
840 			ecx <<= 4;       src_ptr = src_base;
841 			src_x >>= FP;    src_ptr += ecx;
842 			ecx = dst_w;
843 		}
844 		while (--dst_h);
845 	}
846 	else if (drawmode == 2) // all pens solid with alpha blending
847 	{
848 		do {
849 			do {
850 				eax = src_ptr[src_x];
851 				src_x = src_fx;
852 				src_fx += src_fdx;
853 				src_x >>= FP;
854 				if (!eax || ozbuf_ptr[ecx] < z8) continue;
855 				ozbuf_ptr[ecx] = z8;
856 
857 				BLEND32_MACRO
858 			}
859 			while (++ecx);
860 
861 			ecx = src_fby;   src_fby += src_fdy;
862 			ozbuf_ptr += GX_ZBUFW;
863 			dst_ptr += GX_BMPPW;
864 			ecx >>= FP;      src_fx = src_fbx;
865 			src_x = src_fbx; src_fx += src_fdx;
866 			ecx <<= 4;       src_ptr = src_base;
867 			src_x >>= FP;    src_ptr += ecx;
868 			ecx = dst_w;
869 		}
870 		while (--dst_h);
871 	}
872 	else if (drawmode == 3) // solid pens only with alpha blending
873 	{
874 		do {
875 			do {
876 				eax = src_ptr[src_x];
877 				src_x = src_fx;
878 				src_fx += src_fdx;
879 				src_x >>= FP;
880 				if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
881 				ozbuf_ptr[ecx] = z8;
882 
883 				BLEND32_MACRO
884 			}
885 			while (++ecx);
886 
887 			ecx = src_fby;   src_fby += src_fdy;
888 			ozbuf_ptr += GX_ZBUFW;
889 			dst_ptr += GX_BMPPW;
890 			ecx >>= FP;      src_fx = src_fbx;
891 			src_x = src_fbx; src_fx += src_fdx;
892 			ecx <<= 4;       src_ptr = src_base;
893 			src_x >>= FP;    src_ptr += ecx;
894 			ecx = dst_w;
895 		}
896 		while (--dst_h);
897 	}
898 	else if (drawmode == 4) // shadow pens only
899 	{
900 		do {
901 			do {
902 				eax = src_ptr[src_x];
903 				src_x = src_fx;
904 				src_fx += src_fdx;
905 				src_x >>= FP;
906 				if (eax < shdpen || szbuf_ptr[ecx*2] < z8 || szbuf_ptr[ecx*2+1] <= p8) continue;
907 				eax = dst_ptr[ecx];
908 				szbuf_ptr[ecx*2] = z8;
909 				szbuf_ptr[ecx*2+1] = p8;
910 				eax = (eax>>9&0x7c00) | (eax>>6&0x03e0) | (eax>>3&0x001f);
911 				dst_ptr[ecx] = shd_base[eax];
912 			}
913 			while (++ecx);
914 
915 			ecx = src_fby;   src_fby += src_fdy;
916 			szbuf_ptr += (GX_ZBUFW<<1);
917 			dst_ptr += GX_BMPPW;
918 			ecx >>= FP;      src_fx = src_fbx;
919 			src_x = src_fbx; src_fx += src_fdx;
920 			ecx <<= 4;       src_ptr = src_base;
921 			src_x >>= FP;    src_ptr += ecx;
922 			ecx = dst_w;
923 		}
924 		while (--dst_h);
925 	}
926 
927 #undef FP
928 #undef FPONE
929 #undef FPHALF
930 #undef FPENT
931 }
932 
933 
934 
935 /***************************************************************************/
936 /*                                                                         */
937 /*                 1st-Tier GX/MW Variables and Functions                  */
938 /*                                                                         */
939 /***************************************************************************/
940 
941 // global system ports access
942 data8_t  konamigx_wrport1_0, konamigx_wrport1_1;
943 data16_t konamigx_wrport2;
944 
945 // frequently used registers
946 static int K053246_objset1;
947 static int K053247_vrcbk[4];
948 static int K053247_coreg, K053247_coregshift, K053247_opset;
949 static int opri, oinprion;
950 static int vcblk[6], ocblk;
951 static int vinmix, vmixon, osinmix, osmixon;
952 
953 
konamigx_precache_registers(void)954 static void konamigx_precache_registers(void)
955 {
956 	// (see sprite color coding scheme on p.46 & 47)
957 	static int coregmasks[5] = {0xf,0xe,0xc,0x8,0x0};
958 	static int coregshifts[5]= {4,5,6,7,8};
959 	int i;
960 
961 	K053246_objset1 = K053246_read_register(5);
962 
963 	i = K053247_read_register(0x8/2);
964 	K053247_vrcbk[0] = (i & 0x000f) << 14;
965 	K053247_vrcbk[1] = (i & 0x0f00) << 6;
966 	i = K053247_read_register(0xa/2);
967 	K053247_vrcbk[2] = (i & 0x000f) << 14;
968 	K053247_vrcbk[3] = (i & 0x0f00) << 6;
969 
970 	// COREG == OBJSET2+1C == bit8-11 of OPSET ??? (see p.50 last table, needs p.49 to confirm)
971 	K053247_opset = K053247_read_register(0xc/2);
972 
973 	i = K053247_opset & 7; if (i > 4) i = 4;
974 
975 	K053247_coreg = K053247_read_register(0xc/2)>>8 & 0xf;
976 	K053247_coreg =(K053247_coreg & coregmasks[i]) << 12;
977 
978 	K053247_coregshift = coregshifts[i];
979 
980 	opri     = K055555_read_register(K55_PRIINP_8);
981 	oinprion = K055555_read_register(K55_OINPRI_ON);
982 	vcblk[0] = K055555_read_register(K55_PALBASE_A);
983 	vcblk[1] = K055555_read_register(K55_PALBASE_B);
984 	vcblk[2] = K055555_read_register(K55_PALBASE_C);
985 	vcblk[3] = K055555_read_register(K55_PALBASE_D);
986 	vcblk[4] = K055555_read_register(K55_PALBASE_SUB1);
987 	vcblk[5] = K055555_read_register(K55_PALBASE_SUB2);
988 	ocblk    = K055555_read_register(K55_PALBASE_OBJ);
989 	vinmix   = K055555_read_register(K55_BLEND_ENABLES);
990 	vmixon   = K055555_read_register(K55_VINMIX_ON);
991 	osinmix  = K055555_read_register(K55_OSBLEND_ENABLES);
992 	osmixon  = K055555_read_register(K55_OSBLEND_ON);
993 }
994 
K053247GX_combine_c18(int attrib)995 static INLINE int K053247GX_combine_c18(int attrib) // (see p.46)
996 {
997 	int c18;
998 
999 	c18 = (attrib & 0xff)<<K053247_coregshift | K053247_coreg;
1000 
1001 	if (konamigx_wrport2 & 4) c18 &= 0x3fff; else
1002 	if (!(konamigx_wrport2 & 8)) c18 = (c18 & 0x3fff) | (attrib<<6 & 0xc000);
1003 
1004 	return(c18);
1005 }
1006 
K055555GX_decode_objcolor(int c18)1007 static INLINE int K055555GX_decode_objcolor(int c18) // (see p.59 7.2.2)
1008 {
1009 	int ocb, opon;
1010 
1011 	opon  = oinprion<<8 | 0xff;
1012 	ocb   = (ocblk & 7) << 10;
1013 	c18  &= opon;
1014 	ocb  &=~opon;
1015 
1016 	return((ocb | c18) >> K053247_coregshift);
1017 }
1018 
K055555GX_decode_inpri(int c18)1019 static INLINE int K055555GX_decode_inpri(int c18) // (see p.59 7.2.2)
1020 {
1021 	int op = opri;
1022 
1023 	c18 >>= 8;
1024 	op   &= oinprion;
1025 	c18  &=~oinprion;
1026 
1027 	return(c18 | op);
1028 }
1029 
konamigx_type2_sprite_callback(int * code,int * color,int * priority)1030 void konamigx_type2_sprite_callback(int *code, int *color, int *priority)
1031 {
1032 	int num = *code;
1033 	int c18 = *color;
1034 
1035 	*code = K053247_vrcbk[num>>14] | (num & 0x3fff);
1036 	c18 = K053247GX_combine_c18(c18);
1037 	*color = K055555GX_decode_objcolor(c18);
1038 	*priority = K055555GX_decode_inpri(c18);
1039 }
1040 
konamigx_dragoonj_sprite_callback(int * code,int * color,int * priority)1041 void konamigx_dragoonj_sprite_callback(int *code, int *color, int *priority)
1042 {
1043 	int num, op, pri, c18;
1044 
1045 	num = *code;
1046 	*code = K053247_vrcbk[num>>14] | (num & 0x3fff);
1047 
1048 	c18  = pri = *color;
1049 	op   = opri;
1050 	pri  = (pri & 0x200) ? 4 : pri>>4 & 0xf;
1051 	op  &= oinprion;
1052 	pri &=~oinprion;
1053 	*priority = pri | op;
1054 
1055 	c18 = K053247GX_combine_c18(c18);
1056 	*color = K055555GX_decode_objcolor(c18);
1057 }
1058 
konamigx_salmndr2_sprite_callback(int * code,int * color,int * priority)1059 void konamigx_salmndr2_sprite_callback(int *code, int *color, int *priority)
1060 {
1061 	int num, op, pri, c18;
1062 
1063 	num = *code;
1064 	*code = K053247_vrcbk[num>>14] | (num & 0x3fff);
1065 
1066 	c18  = pri = *color;
1067 	op   = opri;
1068 	pri  = pri>>4 & 0x3f;
1069 	op  &= oinprion;
1070 	pri &=~oinprion;
1071 	*priority = pri | op;
1072 
1073 	c18 = K053247GX_combine_c18(c18);
1074 	*color = K055555GX_decode_objcolor(c18);
1075 }
1076 
konamigx_le2_sprite_callback(int * code,int * color,int * priority)1077 void konamigx_le2_sprite_callback(int *code, int *color, int *priority)
1078 {
1079 	int num, op, pri;
1080 
1081 	num = *code;
1082 	*code = K053247_vrcbk[num>>14] | (num & 0x3fff);
1083 
1084 	pri = *color;
1085 	*color &= 0x1f;
1086 
1087 	op   = opri;
1088 	pri &= 0xf0;
1089 	op  &= oinprion;
1090 	pri &=~oinprion;
1091 	*priority = pri | op;
1092 }
1093 
K055555GX_decode_vmixcolor(int layer,int * color)1094 int K055555GX_decode_vmixcolor(int layer, int *color) // (see p.62 7.2.6 and p.27 3.3)
1095 {
1096 	int vcb, shift, pal, vmx, von, pl45, emx;
1097 
1098 	vcb    =  vcblk[layer]<<6;
1099 	shift  =  layer<<1;
1100 	pal    =  *color;
1101 	vmx    =  vinmix>>shift & 3;
1102 	von    =  vmixon>>shift & 3;
1103 	emx    =  pl45 = pal>>4 & 3;
1104 	pal   &=  0xf;
1105 	pl45  &=  von;
1106 	vmx   &=  von;
1107 	pl45 <<=  4;
1108 	emx   &= ~von;
1109 	pal   |=  pl45;
1110 	emx   |=  vmx;
1111 	pal   |=  vcb;
1112 
1113 	if (von == 3) emx = -1; // invalidate external mix code if all bits are from internal
1114 	*color =  pal;
1115 
1116 	return(emx);
1117 }
1118 
K055555GX_decode_osmixcolor(int layer,int * color)1119 int K055555GX_decode_osmixcolor(int layer, int *color) // (see p.63, p.49-50 and p.27 3.3)
1120 {
1121 	int scb, shift, pal, osmx, oson, pl45, emx;
1122 
1123 	shift  =  layer<<1;
1124 	pal    =  *color;
1125 	osmx   =  osinmix>>shift & 3;
1126 	oson   =  osmixon>>shift & 3;
1127 
1128 	if (layer)
1129 	{
1130 		// layer 1-3 are external tile layers
1131 		scb    =  vcblk[layer+3]<<6;
1132 		emx    =  pl45 = pal>>4 & 3;
1133 		pal   &=  0xf;
1134 		pl45  &=  oson;
1135 		osmx  &=  oson;
1136 		pl45 <<=  4;
1137 		emx   &= ~oson;
1138 		pal   |=  pl45;
1139 		emx   |=  osmx;
1140 		pal   |=  scb;
1141 
1142 		if (oson == 3) emx = -1; // invalidate external mix code if all bits are from internal
1143 		*color =  pal;
1144 	}
1145 	else
1146 	{
1147 		// layer 0 is the sprite layer with different attributes decode; detail on p.49 (missing)
1148 		emx   = 0; // K053247_read_register(??)>>? & 3;
1149 		osmx &= oson;
1150 		emx  &=~oson;
1151 		emx  |= osmx;
1152 	}
1153 
1154 	return(emx);
1155 }
1156 
gx_wipezbuf(int noshadow)1157 static void gx_wipezbuf(int noshadow)
1158 {
1159 	UINT8  *zptr;
1160 	int w, h;
1161 	register int ecx;
1162 
1163 	w = Machine->visible_area.max_x - Machine->visible_area.min_x + 1;
1164 	h = Machine->visible_area.max_y - Machine->visible_area.min_y + 1;
1165 
1166 	zptr = gx_objzbuf;
1167 	ecx = h;
1168 	do { memset(zptr, -1, w); zptr += GX_ZBUFW; } while (--ecx);
1169 
1170 	if (!noshadow)
1171 	{
1172 		zptr = gx_shdzbuf;
1173 		w <<= 1;
1174 		ecx = h;
1175 		do { memset(zptr, -1, w); zptr += (GX_ZBUFW<<1); } while (--ecx);
1176 	}
1177 }
1178 
1179 /*
1180  * Sprite Format
1181  * ------------------
1182  *
1183  * Word | Bit(s)           | Use
1184  * -----+-fedcba9876543210-+----------------
1185  *   0  | x--------------- | active (show this sprite)
1186  *   0  | -x-------------- | maintain aspect ratio (when set, zoom y acts on both axis)
1187  *   0  | --x------------- | flip y
1188  *   0  | ---x------------ | flip x
1189  *   0  | ----xxxx-------- | sprite size (see below)
1190  *   0  | --------xxxxxxxx | zcode
1191  *   1  | xxxxxxxxxxxxxxxx | sprite code
1192  *   2  | ------xxxxxxxxxx | y position
1193  *   3  | ------xxxxxxxxxx | x position
1194  *   4  | xxxxxxxxxxxxxxxx | zoom y (0x40 = normal, <0x40 = enlarge, >0x40 = reduce)
1195  *   5  | xxxxxxxxxxxxxxxx | zoom x (0x40 = normal, <0x40 = enlarge, >0x40 = reduce)
1196  *   6  | x--------------- | mirror y (top half is drawn as mirror image of the bottom)
1197  *   6  | -x-------------- | mirror x (right half is drawn as mirror image of the left)
1198  *   6  | --xx------------ | reserved (sprites with these two bits set don't seem to be graphics data at all)
1199  *   6  | ----xx---------- | shadow code: 0=off, 0x400=preset1, 0x800=preset2, 0xc00=preset3
1200  *   6  | ------xx-------- | effect code: flicker, upper palette, full shadow...etc. (game dependent)
1201  *   6  | --------xxxxxxxx | "color", but depends on external connections (implies priority)
1202  *   7  | xxxxxxxxxxxxxxxx | game dependent
1203  *
1204  * shadow enables transparent shadows. Note that it applies to the last sprite pen ONLY.
1205  * The rest of the sprite remains normal.
1206  */
1207 #define GX_MAX_SPRITES 512
1208 #define GX_MAX_LAYERS  6
1209 #define GX_MAX_OBJECTS (GX_MAX_SPRITES + GX_MAX_LAYERS)
1210 
1211 static struct GX_OBJ { int order, offs, code, color; } *gx_objpool;
1212 static data16_t *gx_spriteram;
1213 static int gx_objdma, gx_primode;
1214 
1215 // mirrored K053247 and K054338 settings
1216 static data16_t *K053247_ram;
1217 static struct GfxElement *K053247_gfx;
1218 static void (*K053247_callback)(int *code,int *color,int *priority);
1219 static int K053247_dx, K053247_dy;
1220 
1221 static int *K054338_shdRGB;
1222 
1223 
K053247GP_set_SpriteOffset(int offsx,int offsy)1224 void K053247GP_set_SpriteOffset(int offsx, int offsy)
1225 {
1226 	K053247_dx = offsx;
1227 	K053247_dy = offsy;
1228 }
1229 
konamigx_mixer_init(int objdma)1230 int konamigx_mixer_init(int objdma)
1231 {
1232 	gx_objdma = 0;
1233 	gx_primode = 0;
1234 
1235 	gx_objzbuf = (UINT8 *)priority_bitmap->base;
1236 	if (!(gx_shdzbuf = auto_malloc(GX_ZBUFSIZE))) return(1);
1237 	if (!(gx_objpool = auto_malloc(sizeof(struct GX_OBJ) * (GX_MAX_OBJECTS)))) return(1);
1238 
1239 	K053247_export_config(&K053247_ram, &K053247_gfx, (void**)&K053247_callback, &K053247_dx, &K053247_dy);
1240 	K054338_export_config(&K054338_shdRGB);
1241 
1242 	if (objdma)
1243 	{
1244 		if (!(gx_spriteram = auto_malloc(0x1000))) return(1);
1245 		gx_objdma = 1;
1246 	}
1247 	else
1248 		gx_spriteram = K053247_ram;
1249 
1250 	palette_set_shadow_dRGB32(3,-80,-80,-80, 0);
1251 	K054338_invert_alpha(1);
1252 
1253 	return(0);
1254 }
1255 
konamigx_mixer_primode(int mode)1256 void konamigx_mixer_primode(int mode)
1257 {
1258 	gx_primode = mode;
1259 }
1260 
konamigx_objdma(void)1261 void konamigx_objdma(void)
1262 {
1263 	if (gx_objdma && gx_spriteram && K053247_ram) memcpy(gx_spriteram, K053247_ram, 0x1000);
1264 }
1265 
konamigx_mixer(struct mame_bitmap * bitmap,const struct rectangle * cliprect,struct tilemap * sub1,int sub1flags,struct tilemap * sub2,int sub2flags,int mixerflags)1266 void konamigx_mixer(struct mame_bitmap *bitmap, const struct rectangle *cliprect,
1267 					struct tilemap *sub1, int sub1flags,
1268 					struct tilemap *sub2, int sub2flags,
1269 					int mixerflags)
1270 {
1271 	static int xoffset[8] = { 0, 1, 4, 5, 16, 17, 20, 21 };
1272 	static int yoffset[8] = { 0, 2, 8, 10, 32, 34, 40, 42 };
1273 	static int parity = 0;
1274 
1275 	int objbuf[GX_MAX_OBJECTS];
1276 	int shadowon[3], shdpri[3], layerid[6], layerpri[6];
1277 
1278 	struct GX_OBJ *objpool, *objptr;
1279 	int wrapsize, xwraplim, ywraplim, cltc_shdpri, prflp, disp;
1280 	int xa,ya,ox,oy,zw,zh,flipx,flipy,mirrorx,mirrory,zoomx,zoomy,scalex,scaley,nozoom;
1281 	int screenwidth, flipscreenx, flipscreeny, offx, offy;
1282 	int nobj, i, j, k, l, temp, temp1, temp2, temp3, temp4, count;
1283 	int order, offs, code, color, zcode, pri, spri, spri_min, shdprisel, shadow, alpha, drawmode;
1284 
1285 
1286 	// abort if object database failed to initialize
1287 	if (!(objpool = gx_objpool)) return;
1288 
1289 	// clear screen with backcolor and update flicker pulse
1290 	K054338_fill_backcolor(bitmap, konamigx_wrport1_0 & 0x20);
1291 	parity ^= 1;
1292 
1293 	// abort if video has been disabled
1294 	if (!(disp = K055555_read_register(K55_INPUT_ENABLES))) return;
1295 	cltc_shdpri = K054338_read_register(K338_REG_CONTROL);
1296 	if (!(cltc_shdpri & K338_CTL_KILL)) return;
1297 
1298 	// demote shadows by one layer when this bit is set??? (see p.73 8.6)
1299 	cltc_shdpri &= K338_CTL_SHDPRI;
1300 
1301 	// wipe z-buffer
1302 	if (mixerflags & GXMIX_NOZBUF)
1303 		mixerflags |= GXMIX_NOSHADOW;
1304 	else
1305 		gx_wipezbuf(mixerflags & GXMIX_NOSHADOW);
1306 
1307 	// cache global parameters
1308 	konamigx_precache_registers();
1309 
1310 	// init OBJSET1 parameters (see p.47 6.2)
1311 	flipscreenx = K053246_objset1 & 1;
1312 	flipscreeny = K053246_objset1 & 2;
1313 
1314 	// get "display window" offsets
1315 	offx = (K053246_read_register(0)<<8 | K053246_read_register(1)) & 0x3ff;
1316 	offy = (K053246_read_register(2)<<8 | K053246_read_register(3)) & 0x3ff;
1317 
1318 	// init OBJSET2 and mixer parameters (see p.51 and chapter 7)
1319 	layerid[0] = 0; layerid[1] = 1; layerid[2] = 2; layerid[3] = 3; layerid[4] = 4; layerid[5] = 5;
1320 
1321 	if (K053247_opset & 0x40)
1322 	{
1323 		wrapsize = 512;
1324 		xwraplim = 512 - 64;
1325 		ywraplim = 512 - 128;
1326 	}
1327 	else
1328 	{
1329 		wrapsize  = 1024;
1330 		xwraplim  = 1024 - 384;
1331 		ywraplim  = 1024 - 512;
1332 	}
1333 
1334 	// invert layer priority when this flag is set (not used by any GX game?)
1335 	prflp = K055555_read_register(K55_CONTROL) & K55_CTL_FLIPPRI;
1336 
1337 	layerpri[0] = K055555_read_register(K55_PRIINP_0);
1338 	layerpri[1] = K055555_read_register(K55_PRIINP_3);
1339 	layerpri[3] = K055555_read_register(K55_PRIINP_7);
1340 	layerpri[4] = K055555_read_register(K55_PRIINP_9);
1341 	layerpri[5] = K055555_read_register(K55_PRIINP_10);
1342 
1343 	if (gx_primode == -1)
1344 	{
1345 		// Lethal Enforcer hack (requires pixel color comparison)
1346 		layerpri[2] = K055555_read_register(K55_PRIINP_3) + 0x20;
1347 		shdprisel = 0x3f;
1348 	}
1349 	else
1350 	{
1351 		layerpri[2] = K055555_read_register(K55_PRIINP_6);
1352 		shdprisel = K055555_read_register(K55_SHD_PRI_SEL);
1353 	}
1354 
1355 	// SHDPRISEL filters shadows by different priority comparison methods (UNIMPLEMENTED, see detail on p.66)
1356 	if (!(shdprisel & 0x03)) shadowon[0] = 0;
1357 	if (!(shdprisel & 0x0c)) shadowon[1] = 0;
1358 	if (!(shdprisel & 0x30)) shadowon[2] = 0;
1359 
1360 	shdpri[0]   = K055555_read_register(K55_SHAD1_PRI);
1361 	shdpri[1]   = K055555_read_register(K55_SHAD2_PRI);
1362 	shdpri[2]   = K055555_read_register(K55_SHAD3_PRI);
1363 
1364 	spri_min = 0;
1365 	shadowon[2] = shadowon[1] = shadowon[0] = 0;
1366 
1367 	if (!(mixerflags & GXMIX_NOSHADOW))
1368 	{
1369 		// only enable shadows beyond a +/-7 RGB threshold
1370 		for (j=0,i=0; i<3; j+=3,i++)
1371 		{
1372 			k = K054338_shdRGB[j  ]; if (k < -7 || k > 7) { shadowon[i] = 1; continue; }
1373 			k = K054338_shdRGB[j+1]; if (k < -7 || k > 7) { shadowon[i] = 1; continue; }
1374 			k = K054338_shdRGB[j+2]; if (k < -7 || k > 7) { shadowon[i] = 1; }
1375 		}
1376 
1377 		// SHDON specifies layers on which shadows can be projected (see detail on p.65 7.2.8)
1378 		temp = K055555_read_register(K55_SHD_ON);
1379 		for (i=0; i<4; i++) if (!(temp>>i & 1) && spri_min < layerpri[i]) spri_min = layerpri[i]; // HACK
1380 
1381 		// update shadows status
1382 		K054338_update_all_shadows();
1383 	}
1384 
1385 	// pre-sort layers
1386 	for (j=0; j<5; j++)
1387 	{
1388 		temp1 = layerpri[j];
1389 		for (i=j+1; i<6; i++)
1390 		{
1391 			temp2 = layerpri[i];
1392 			if ((unsigned int)temp1 <= (unsigned int)temp2)
1393 			{
1394 				layerpri[i] = temp1; layerpri[j] = temp1 = temp2;
1395 				temp2 = layerid[i]; layerid[i] = layerid[j]; layerid[j] = temp2;
1396 			}
1397 		}
1398 	}
1399 
1400 	// build object database and create indices
1401 	objptr = objpool;
1402 	nobj = 0;
1403 
1404 	for (i=5; i>=0; i--)
1405 	{
1406 		code = layerid[i];
1407 		switch (code)
1408 		{
1409 			/*
1410 				Background layers are represented by negative offset values as follow:
1411 
1412 				0+ : normal sprites
1413 				-1 : tile layer A - D
1414 				-2 : K053936 ROZ+ layer 1
1415 				-3 : K053936 ROZ+ layer 2
1416 				-4 : K053250 LVC layer 1
1417 				-5 : K053250 LVC layer 2
1418 			*/
1419 			case 4 :
1420 				offs = -128;
1421 				if (sub1flags & 0xf) { if (sub1flags & GXSUB_K053250) offs = -4; else if (sub1) offs = -2; }
1422 			break;
1423 			case 5 :
1424 				offs = -128;
1425 				if (sub2flags & 0xf) { if (sub2flags & GXSUB_K053250) offs = -5; else if (sub2) offs = -3; }
1426 			break;
1427 			default: offs = -1;
1428 		}
1429 
1430 		if (offs != -128)
1431 		{
1432 			objptr->order = layerpri[i]<<24;
1433 			objptr->code  = code;
1434 			objptr->offs = offs;
1435 			objptr++;
1436 
1437 			objbuf[nobj] = nobj;
1438 			nobj++;
1439 		}
1440 	}
1441 
1442 	i = j = 0xff;
1443 
1444 	for (offs=0; offs<0x800; offs+=8)
1445 	{
1446 		if (!(gx_spriteram[offs] & 0x8000)) continue;
1447 
1448 		zcode = gx_spriteram[offs] & 0xff;
1449 
1450 		// invert z-order when opset_pri is set (see p.51 OPSET PRI)
1451 		if (K053247_opset & 0x10) zcode = 0xff - zcode;
1452 
1453 		code  = gx_spriteram[offs+1];
1454 		color = k = gx_spriteram[offs+6];
1455 		l     = gx_spriteram[offs+7];
1456 
1457 		(*K053247_callback)(&code, &color, &pri);
1458 
1459 		/*
1460 			shadow = shadow code
1461 			spri   = shadow priority
1462 			temp1  = add solid object
1463 			temp2  = solid pens draw mode
1464 			temp3  = add shadow object
1465 			temp4  = shadow pens draw mode
1466 		*/
1467 		temp4 = temp3 = temp2 = temp1 = spri = shadow = 0;
1468 
1469 		if (color & K055555_FULLSHADOW)
1470 		{
1471 			shadow = 3; // use default intensity and color
1472 			spri = pri; // retain host priority
1473 			temp3 = 1; // add shadow
1474 			temp4 = 5; // draw full shadow
1475 		}
1476 		else
1477 		{
1478 			if ((shadow = k>>10 & 3)) // object has shadow?
1479 			{
1480 				if (shadow != 1 || K053246_objset1 & 0x20)
1481 				{
1482 					shadow--;
1483 					temp1 = 1; // add solid
1484 					temp2 = 1; // draw partial solid
1485 					if (shadowon[shadow])
1486 					{
1487 						temp3 = 1; // add shadow
1488 						temp4 = 4; // draw partial shadow
1489 					}
1490 				}
1491 				else
1492 				{
1493 					// drop the entire sprite to shadow if its shadow code is 1 and SD0EN is off (see p.48)
1494 					shadow = 0;
1495 					if (!shadowon[0]) continue;
1496 					temp3 = 1; // add shadow
1497 					temp4 = 5; // draw full shadow
1498 				}
1499 			}
1500 			else
1501 			{
1502 				temp1 = 1; // add solid
1503 				temp2 = 0; // draw full solid
1504 			}
1505 
1506 			if (temp1)
1507 			{
1508 				// tag sprite for alpha blending
1509 				if (color>>K055555_MIXSHIFT & 3) temp2 |= 2;
1510 			}
1511 
1512 			if (temp3)
1513 			{
1514 				// determine shadow priority
1515 				spri = (K053247_opset & 0x20) ? pri : shdpri[shadow]; // (see p.51 OPSET SDSEL)
1516 			}
1517 		}
1518 
1519 		switch (gx_primode & 0xf)
1520 		{
1521 			// Dadandarn zcode suppression
1522 			case  1:
1523 				zcode = 0;
1524 			break;
1525 
1526 			// Daisukiss bad shadow filter
1527 			case  4:
1528 				if (k & 0x3000 || k == 0x0800) continue;
1529 
1530 			// Tokkae shadow masking (INACCURATE)
1531 			case  5:
1532 				if (spri < spri_min) spri = spri_min;
1533 			break;
1534 		}
1535 
1536 		/*
1537 			default sort order:
1538 			fedcba9876543210fedcba9876543210
1539 			xxxxxxxx------------------------ (priority)
1540 			--------xxxxxxxx---------------- (zcode)
1541 			----------------xxxxxxxx-------- (offset)
1542 			------------------------xxxx---- (shadow mode)
1543 			----------------------------xxxx (shadow code)
1544 		*/
1545 		if (temp1)
1546 		{
1547 			// add objects with solid or alpha pens
1548 			order = pri<<24 | zcode<<16 | offs<<(8-3) | temp2<<4;
1549 			objptr->order = order;
1550 			objptr->offs  = offs;
1551 			objptr->code  = code;
1552 			objptr->color = color;
1553 			objptr++;
1554 
1555 			objbuf[nobj] = nobj;
1556 			nobj++;
1557 		}
1558 
1559 		if (temp3 && !(color & K055555_SKIPSHADOW) && !(mixerflags & GXMIX_NOSHADOW))
1560 		{
1561 			// add objects with shadows if enabled
1562 			order = spri<<24 | zcode<<16 | offs<<(8-3) | temp4<<4 | shadow;
1563 			objptr->order = order;
1564 			objptr->offs  = offs;
1565 			objptr->code  = code;
1566 			objptr->color = color;
1567 			objptr++;
1568 
1569 			objbuf[nobj] = nobj;
1570 			nobj++;
1571 		}
1572 	}
1573 
1574 	// sort objects in decending order (SLOW)
1575 	k = nobj;
1576 	l = nobj - 1;
1577 
1578 	for (j=0; j<l; j++)
1579 	{
1580 		temp1 = objbuf[j];
1581 		temp2 = objpool[temp1].order;
1582 		for (i=j+1; i<k; i++)
1583 		{
1584 			temp3 = objbuf[i];
1585 			temp4 = objpool[temp3].order;
1586 			if ((unsigned int)temp2 <= (unsigned int)temp4) { temp2 = temp4; objbuf[i] = temp1; objbuf[j] = temp1 = temp3; }
1587 		}
1588 	}
1589 
1590 	// traverse draw list
1591 	screenwidth = Machine->drv->screen_width;
1592 
1593 	for (count=0; count<nobj; count++)
1594 	{
1595 		objptr = objpool + objbuf[count];
1596 		order  = objptr->order;
1597 		offs   = objptr->offs;
1598 		code   = objptr->code;
1599 		color  = objptr->color;
1600 
1601 		if (offs >= 0)
1602 		{
1603 			if (!(disp & K55_INP_OBJ)) continue;
1604 		}
1605 		else
1606 		{
1607 			i = code<<1;
1608 			j = mixerflags>>i & 3;
1609 			k = 0;
1610 
1611 			switch (offs)
1612 			{
1613 				case -1:
1614 				if (disp & (1<<code))
1615 				{
1616 					if (j == GXMIX_BLEND_NONE)  { temp1 = 0xff; temp2 = temp3 = 0; } else
1617 					if (j == GXMIX_BLEND_FORCE) { temp1 = 0x00; temp2 = mixerflags>>(i+16); temp3 = 3; }
1618 					else
1619 					{
1620 						temp1 = vinmix;
1621 						temp2 = vinmix>>i & 3;
1622 						temp3 = vmixon>>i & 3;
1623 					}
1624 
1625 					/* blend layer only when:
1626 						1) vinmix != 0xff
1627 						2) its internal mix code is set
1628 						3) all mix code bits are internal(overriden until tile blending has been implemented)
1629 						4) 0 > alpha < 255;
1630 					*/
1631 					if (temp1!=0xff && temp2 /*&& temp3==3*/)
1632 					{
1633 						temp4 = K054338_set_alpha_level(temp2);
1634 
1635 						if (temp4 <= 0) continue;
1636 						if (temp4 < 255) k = TILEMAP_ALPHA;
1637 					}
1638 
1639 					if (mixerflags & 1<<(code+12)) k |= TILE_LINE_DISABLED;
1640 
1641 					K056832_tilemap_draw(bitmap, cliprect, code, k, 0);
1642 				}
1643 				continue;
1644 				case -2:
1645 				case -4:
1646 				if (disp & K55_INP_SUB1)
1647 				{
1648 					if (j == GXMIX_BLEND_NONE)  { temp1 = 0xff; temp2 = temp3 = 0; } else
1649 					if (j == GXMIX_BLEND_FORCE) { temp1 = 0x00; temp2 = mixerflags>>24; temp3 = 3; }
1650 					else
1651 					{
1652 						temp1 = osinmix;
1653 						temp2 = osinmix>>2 & 3;
1654                         temp3 = osmixon>>2 & 3;
1655 					}
1656 
1657 					if (temp1!=0xff && temp2 /*&& temp3==3*/)
1658 					{
1659 						temp4 = K054338_set_alpha_level(temp2);
1660 
1661 						if (temp4 <= 0) continue;
1662 						if (temp4 < 255) k = (j == GXMIX_BLEND_FAST) ? ~parity : 1;
1663 					}
1664 
1665 					l = sub1flags & 0xf;
1666 
1667 					if (offs == -2)
1668 						K053936GP_0_zoom_draw(bitmap, cliprect, sub1, l, k);
1669 					else
1670 						K053250_draw(bitmap, cliprect, 0, vcblk[4]<<l, 0, 0);
1671 				}
1672 				continue;
1673 				case -3:
1674 				case -5:
1675 				if (disp & K55_INP_SUB2)
1676 				{
1677 					if (j == GXMIX_BLEND_NONE)  { temp1 = 0xff; temp2 = temp3 = 0; } else
1678 					if (j == GXMIX_BLEND_FORCE) { temp1 = 0x00; temp2 = mixerflags>>26; temp3 = 3; }
1679 					else
1680 					{
1681 						temp1 = osinmix;
1682 						temp2 = osinmix>>4 & 3;
1683                         temp3 = osmixon>>4 & 3;
1684 					}
1685 
1686 					if (temp1!=0xff && temp2 /*&& temp3==3*/)
1687 					{
1688 						temp4 = K054338_set_alpha_level(temp2);
1689 
1690 						if (temp4 <= 0) continue;
1691 						if (temp4 < 255) k = (j == GXMIX_BLEND_FAST) ? ~parity : 1;
1692 					}
1693 
1694 					l = sub2flags & 0xf;
1695 
1696 					if (offs == -3)
1697 						K053936GP_1_zoom_draw(bitmap, cliprect, sub2, l, k);
1698 					else
1699 						K053250_draw(bitmap, cliprect, 1, vcblk[5]<<l, 0, 0);
1700 				}
1701 				continue;
1702 			}
1703 			continue;
1704 		}
1705 
1706 		drawmode = order>>4 & 0xf;
1707 
1708 		alpha = 255;
1709 		if (drawmode & 2)
1710 		{
1711 			if ((alpha = color>>K055555_MIXSHIFT & 3)) alpha = K054338_set_alpha_level(alpha);
1712 			if (alpha <= 0) continue;
1713 		}
1714 		color &= K055555_COLORMASK;
1715 
1716 		if (drawmode >= 4) palette_set_shadow_mode(order & 0x0f);
1717 
1718 		if (!(mixerflags & GXMIX_NOZBUF))
1719 		{
1720 			zcode = order>>16 & 0xff;
1721 			pri = order>>24 & 0xff;
1722 		}
1723 		else
1724 			zcode = -1; // negative zcode values turn off z-buffering
1725 
1726 		xa = ya = 0;
1727 		if (code & 0x01) xa += 1;
1728 		if (code & 0x02) ya += 1;
1729 		if (code & 0x04) xa += 2;
1730 		if (code & 0x08) ya += 2;
1731 		if (code & 0x10) xa += 4;
1732 		if (code & 0x20) ya += 4;
1733 		code &= ~0x3f;
1734 
1735 		temp4 = gx_spriteram[offs];
1736 
1737 		// mask off the upper 6 bits of coordinate and zoom registers
1738 		oy = gx_spriteram[offs+2] & 0x3ff;
1739 		ox = gx_spriteram[offs+3] & 0x3ff;
1740 
1741 		scaley = zoomy = gx_spriteram[offs+4] & 0x3ff;
1742 		if (zoomy) zoomy = (0x400000+(zoomy>>1)) / zoomy;
1743 		else zoomy = 0x800000;
1744 		if (!(temp4 & 0x4000))
1745 		{
1746 			scalex = zoomx = gx_spriteram[offs+5] & 0x3ff;
1747 			if (zoomx) zoomx = (0x400000+(zoomx>>1)) / zoomx;
1748 			else zoomx = 0x800000;
1749 		}
1750 		else { zoomx = zoomy; scalex = scaley; }
1751 
1752 		nozoom = (scalex == 0x40 && scaley == 0x40);
1753 
1754 		flipx = temp4 & 0x1000;
1755 		flipy = temp4 & 0x2000;
1756 
1757 		temp = gx_spriteram[offs+6];
1758 		mirrorx = temp & 0x4000;
1759 		if (mirrorx) flipx = 0; // only applies to x mirror, proven
1760 		mirrory = temp & 0x8000;
1761 
1762 		// for Escape Kids (GX975)
1763 		if ( K053246_objset1 & 8 ) // Check only "Bit #3 is '1'?"
1764 		{
1765 			zoomx = zoomx>>1; // Fix sprite width to HALF size
1766 			ox = (ox>>1) + 1; // Fix sprite draw position
1767 
1768 			if (flipscreenx) ox += screenwidth;
1769 		}
1770 
1771 		if (flipscreenx) { ox = -ox; if (!mirrorx) flipx = !flipx; }
1772 		if (flipscreeny) { oy = -oy; if (!mirrory) flipy = !flipy; }
1773 
1774 		// apply wrapping and global offsets
1775 		temp = wrapsize-1;
1776 		ox = ( ox - offx) & temp;
1777 		oy = (-oy - offy) & temp;
1778 		if (ox >= xwraplim) ox -= wrapsize;
1779 		if (oy >= ywraplim) oy -= wrapsize;
1780 		ox += K053247_dx;
1781 		oy += K053247_dy;
1782 
1783 
1784 		temp = temp4>>8 & 0x0f;
1785 		k = 1 << (temp & 3);
1786 		l = 1 << (temp>>2 & 3);
1787 
1788 		ox -= (zoomx * k) >> 13;
1789 		oy -= (zoomy * l) >> 13;
1790 
1791 		// substitutes: i=x, j=y, k=w, l=h, temp=code, temp1=fx, temp2=fy, temp3=sx, temp4=sy;
1792 		for (j=0; j<l; j++)
1793 		{
1794 			temp4 = oy + ((zoomy * j + (1<<11)) >> 12);
1795 			zh = (oy + ((zoomy * (j+1) + (1<<11)) >> 12)) - temp4;
1796 
1797 			for (i=0; i<k; i++)
1798 			{
1799 				temp3 = ox + ((zoomx * i + (1<<11)) >> 12);
1800 				zw = (ox + ((zoomx * (i+1) + (1<<11)) >> 12)) - temp3;
1801 				temp = code;
1802 
1803 				if (mirrorx)
1804 				{
1805 					if ((!flipx)^((i<<1)<k))
1806 					{
1807 						/* mirror left/right */
1808 						temp += xoffset[(k-1-i+xa)&7];
1809 						temp1 = 1;
1810 					}
1811 					else
1812 					{
1813 						temp += xoffset[(i+xa)&7];
1814 						temp1 = 0;
1815 					}
1816 				}
1817 				else
1818 				{
1819 					if (flipx) temp += xoffset[(k-1-i+xa)&7];
1820 					else temp += xoffset[(i+xa)&7];
1821 					temp1 = flipx;
1822 				}
1823 
1824 				if (mirrory)
1825 				{
1826 					if ((!flipy)^((j<<1)>=l))
1827 					{
1828 						/* mirror top/bottom */
1829 						temp += yoffset[(l-1-j+ya)&7];
1830 						temp2 = 1;
1831 					}
1832 					else
1833 					{
1834 						temp += yoffset[(j+ya)&7];
1835 						temp2 = 0;
1836 					}
1837 				}
1838 				else
1839 				{
1840 					if (flipy) temp += yoffset[(l-1-j+ya)&7];
1841 					else temp += yoffset[(j+ya)&7];
1842 					temp2 = flipy;
1843 				}
1844 
1845 				if (nozoom) { scaley = scalex = 0x10000; } else { scalex = zw << 12; scaley = zh << 12; };
1846 
1847 				zdrawgfxzoom32GP(bitmap, K053247_gfx, cliprect,
1848 						temp,
1849 						color,
1850 						temp1,temp2,
1851 						temp3,temp4,
1852 						scalex, scaley, alpha, drawmode, zcode, pri);
1853 			}
1854 		}
1855 	}
1856 }
1857 
1858 
1859 
1860 /***************************************************************************/
1861 /*                                                                         */
1862 /*                           GX/MW Protections                             */
1863 /*                                                                         */
1864 /***************************************************************************/
1865 
1866 // K055550/K053990 protection chips, perform simple memset() and other game logic operations
1867 static UINT16 prot_data[0x20];
1868 
READ16_HANDLER(K055550_word_r)1869 READ16_HANDLER( K055550_word_r )
1870 {
1871 	return(prot_data[offset]);
1872 }
1873 
WRITE16_HANDLER(K055550_word_w)1874 WRITE16_HANDLER( K055550_word_w )
1875 {
1876 	UINT32 adr, bsize, count, i, lim;
1877 	int src, tgt, srcend, tgtend, skip, cx1, sx1, wx1, cy1, sy1, wy1, cz1, sz1, wz1, c2, s2, w2;
1878 	int dx, dy, angle;
1879 
1880 	COMBINE_DATA(prot_data+offset);
1881 
1882 	if (offset == 0 && ACCESSING_MSB)
1883 	{
1884 		data >>= 8;
1885 		switch (data)
1886 		{
1887 			case 0x97: // memset() (Dadandarn at 0x639dc)
1888 			case 0x9f: // memset() (Violent Storm at 0x989c)
1889 				adr   = (prot_data[7] << 16) | prot_data[8];
1890 				bsize = (prot_data[10] << 16) | prot_data[11];
1891 				count = (prot_data[0] & 0xff) + 1;
1892 
1893 				lim = adr+bsize*count;
1894 				for(i=adr; i<lim; i+=2)
1895 					cpu_writemem24bew_word(i, prot_data[0x1a/2]);
1896 			break;
1897 
1898 			// WARNING: The following cases are speculation based with questionable accuracy!(AAT)
1899 
1900 			case 0x87: // unknown memory write (Violent Storm at 0x00b6ea)
1901 				// Violent Storm writes the following data to the 55550 in mode 0x87.
1902 				// All values are hardcoded and the write happens each frame during
1903 				// gameplay. It refers to a 32x8-word list at 0x210e00 and seems to
1904 				// be tied with another 13x128-byte table at 0x205080.
1905 				// Both tables appear "check-only" and have little effect on gameplay.
1906 				count =(prot_data[0] & 0xff) + 1;          // unknown ( byte 0x00)
1907 				i     = prot_data[1] >> 16;                // unknown ( byte 0x1f)
1908 				adr   = prot_data[7]<<16 | prot_data[8];   // address (dword 0x210e00)
1909 				lim   = prot_data[9];                      // unknown ( word 0x0010)
1910 				src   = prot_data[10]<<16 | prot_data[11]; // unknown (dword zero)
1911 				tgt   = prot_data[12]<<16 | prot_data[13]; // unknown (dword zero)
1912 			break;
1913 
1914 			case 0xa0: // update collision detection table (Violent Storm at 0x018b42)
1915 				count = prot_data[0] & 0xff;             // number of objects - 1
1916 				skip  = prot_data[1]>>(8-1);             // words to skip in each entry to reach the "hit list"
1917 				adr   = prot_data[2]<<16 | prot_data[3]; // where the table is located
1918 				bsize = prot_data[5]<<16 | prot_data[6]; // object entry size in bytes
1919 
1920 				srcend = adr + bsize * count;
1921 				tgtend = srcend + bsize;
1922 
1923 				// let's hope GCC will inline the mem24bew calls
1924 				for (src=adr; src<srcend; src+=bsize)
1925 				{
1926 					cx1 = (short)cpu_readmem24bew_word(src);
1927 					sx1 = (short)cpu_readmem24bew_word(src + 2);
1928 					wx1 = (short)cpu_readmem24bew_word(src + 4);
1929 
1930 					cy1 = (short)cpu_readmem24bew_word(src + 6);
1931 					sy1 = (short)cpu_readmem24bew_word(src + 8);
1932 					wy1 = (short)cpu_readmem24bew_word(src +10);
1933 
1934 					cz1 = (short)cpu_readmem24bew_word(src +12);
1935 					sz1 = (short)cpu_readmem24bew_word(src +14);
1936 					wz1 = (short)cpu_readmem24bew_word(src +16);
1937 
1938 					count = i = src + skip;
1939 					tgt = src + bsize;
1940 
1941 					for (; count<tgt; count++) cpu_writemem24bew(count, 0);
1942 
1943 					for (; tgt<tgtend; i++, tgt+=bsize)
1944 					{
1945 						c2 = (short)cpu_readmem24bew_word(tgt);
1946 						s2 = (short)cpu_readmem24bew_word(tgt + 2);
1947 						w2 = (short)cpu_readmem24bew_word(tgt + 4);
1948 						if (abs((cx1+sx1)-(c2+s2))>=wx1+w2) continue; // X rejection
1949 
1950 						c2 = (short)cpu_readmem24bew_word(tgt + 6);
1951 						s2 = (short)cpu_readmem24bew_word(tgt + 8);
1952 						w2 = (short)cpu_readmem24bew_word(tgt +10);
1953 						if (abs((cy1+sy1)-(c2+s2))>=wy1+w2) continue; // Y rejection
1954 
1955 						c2 = (short)cpu_readmem24bew_word(tgt +12);
1956 						s2 = (short)cpu_readmem24bew_word(tgt +14);
1957 						w2 = (short)cpu_readmem24bew_word(tgt +16);
1958 						if (abs((cz1+sz1)-(c2+s2))>=wz1+w2) continue; // Z rejection
1959 
1960 						cpu_writemem24bew(i, 0x80); // collision confirmed
1961 					}
1962 				}
1963 			break;
1964 
1965 			case 0xc0: // calculate object "homes-in" vector (Violent Storm at 0x03da9e)
1966 				dx = (short)prot_data[0xc];
1967 				dy = (short)prot_data[0xd];
1968 
1969 				// it's not necessary to use lookup tables because Violent Storm
1970 				// only calls the service once per enemy per frame.
1971 				if (dx)
1972 				{
1973 					if (dy)
1974 					{
1975 						angle = (atan((double)dy / dx) * 128.0) / 3.1415926535897932384626433832795;
1976 						if (dx < 0) angle += 128;
1977 						i = (angle - 0x40) & 0xff;
1978 					}
1979 					else
1980 						i = (dx > 0) ? 0xc0 : 0x40;
1981 				}
1982 				else
1983 					if (dy > 0) i = 0;
1984 				else
1985 					if (dy < 0) i = 0x80;
1986 				else
1987 					i = mame_rand() & 0xff; // vector direction indeterminate
1988 
1989 				prot_data[0x10] = i;
1990 			break;
1991 
1992 			default:
1993 //              logerror("%06x: unknown K055550 command %02x\n", activecpu_get_pc(), data);
1994 			break;
1995 		}
1996 	}
1997 }
1998 
WRITE16_HANDLER(K053990_martchmp_word_w)1999 WRITE16_HANDLER( K053990_martchmp_word_w )
2000 {
2001 	int src_addr, src_count, src_skip;
2002 	int dst_addr, dst_count, dst_skip;
2003 	int mod_addr, mod_count, mod_skip, mod_offs;
2004 	int mode, i, element_size = 1;
2005 	data16_t mod_val, mod_data;
2006 
2007 	COMBINE_DATA(prot_data+offset);
2008 
2009 	if (offset == 0x0c && ACCESSING_MSB)
2010 	{
2011 		mode  = (prot_data[0x0d]<<8 & 0xff00) | (prot_data[0x0f] & 0xff);
2012 
2013 		switch (mode)
2014 		{
2015 			case 0xffff: // word copy
2016 				element_size = 2;
2017 			case 0xff00: // byte copy
2018 				src_addr  = prot_data[0x0];
2019 				src_addr |= prot_data[0x1]<<16 & 0xff0000;
2020 				dst_addr  = prot_data[0x2];
2021 				dst_addr |= prot_data[0x3]<<16 & 0xff0000;
2022 				src_count = prot_data[0x8]>>8;
2023 				dst_count = prot_data[0x9]>>8;
2024 				src_skip  = prot_data[0xa] & 0xff;
2025 				dst_skip  = prot_data[0xb] & 0xff;
2026 
2027 				if ((prot_data[0x8] & 0xff) == 2) src_count <<= 1;
2028 				src_skip += element_size;
2029 				dst_skip += element_size;
2030 
2031 				if (element_size == 1)
2032 				for (i=src_count; i; i--)
2033 				{
2034 					cpu_writemem24bew(dst_addr, cpu_readmem24bew(src_addr));
2035 					src_addr += src_skip;
2036 					dst_addr += dst_skip;
2037 				}
2038 				else for (i=src_count; i; i--)
2039 				{
2040 					cpu_writemem24bew_word(dst_addr, cpu_readmem24bew_word(src_addr));
2041 					src_addr += src_skip;
2042 					dst_addr += dst_skip;
2043 				}
2044 			break;
2045 
2046 			case 0x00ff: // sprite list modifier
2047 				src_addr  = prot_data[0x0];
2048 				src_addr |= prot_data[0x1]<<16 & 0xff0000;
2049 				src_skip  = prot_data[0x1]>>8;
2050 				dst_addr  = prot_data[0x2];
2051 				dst_addr |= prot_data[0x3]<<16 & 0xff0000;
2052 				dst_skip  = prot_data[0x3]>>8;
2053 				mod_addr  = prot_data[0x4];
2054 				mod_addr |= prot_data[0x5]<<16 & 0xff0000;
2055 				mod_skip  = prot_data[0x5]>>8;
2056 				mod_offs  = prot_data[0x8] & 0xff;
2057 				mod_offs<<= 1;
2058 				mod_count = 0x100;
2059 
2060 				src_addr += mod_offs;
2061 				dst_addr += mod_offs;
2062 
2063 				for (i=mod_count; i; i--)
2064 				{
2065 					mod_val  = cpu_readmem24bew_word(mod_addr);
2066 					mod_addr += mod_skip;
2067 
2068 					mod_data = cpu_readmem24bew_word(src_addr);
2069 					src_addr += src_skip;
2070 
2071 					mod_data += mod_val;
2072 
2073 					cpu_writemem24bew_word(dst_addr, mod_data);
2074 					dst_addr += dst_skip;
2075 				}
2076 			break;
2077 
2078 			default:
2079 			break;
2080 		}
2081 	}
2082 }
2083 
konamigx_esc_alert(UINT32 * srcbase,int srcoffs,int count,int mode)2084 void konamigx_esc_alert(UINT32 *srcbase, int srcoffs, int count, int mode) // (WARNING: assumed big endianess)
2085 {
2086 
2087 // hand-filled but should be close
2088 static UINT8 ztable[7][8] =
2089 {
2090 	{5,4,3,2,1,7,6,0},
2091 	{4,3,2,1,0,7,6,5},
2092 	{4,3,2,1,0,7,6,5},
2093 	{3,2,1,0,5,7,4,6},
2094 	{6,5,1,4,3,7,0,2},
2095 	{5,4,3,2,1,7,6,0},
2096 	{5,4,3,2,1,7,6,0}
2097 };
2098 
2099 static UINT8 ptable[7][8] =
2100 {
2101 	{0x00,0x00,0x00,0x10,0x20,0x00,0x00,0x30},
2102 	{0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x20},
2103 	{0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00},
2104 	{0x10,0x10,0x10,0x20,0x00,0x00,0x10,0x00},
2105 	{0x00,0x00,0x20,0x00,0x10,0x00,0x20,0x20},
2106 	{0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x10},
2107 	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10}
2108 };
2109 
2110 	INT32 data1, data2, i, j, vpos, hpos, voffs, hoffs, vcorr, hcorr, vmask, hmask, magicid;
2111 	UINT32 *src, *srcend, *obj, *objend;
2112 	UINT16 *dst;
2113 	UINT8  *zcode, *pcode;
2114 
2115 	if (!count || !srcbase) return;
2116 
2117 	if (mode == 0)
2118 	{
2119 		src = srcbase + srcoffs;
2120 		dst = K053247_ram;
2121 		data1 = count<<2;
2122 		data2 = count<<3;
2123 		src += data1; dst += data2; i = -data1; j = -data2;
2124 		do
2125 		{
2126 			data1 = src[i];
2127 			data2 = src[i+1];
2128 			i += 2;
2129 			dst[j+1] = data1;
2130 			dst[j+3] = data2;
2131 			data1  >>= 16;
2132 			data2  >>= 16;
2133 			dst[j]   = data1;
2134 			dst[j+2] = data2;
2135 		}
2136 		while (j += 4);
2137 	}
2138 	else
2139 	{
2140 
2141 #define EXTRACT_ODD         \
2142 if((data1=obj[0])&0x8000)   \
2143 {                           \
2144   i      = data1 & 7;       \
2145   data1 &= 0xff00;          \
2146   dst[0] = data1 | zcode[i];\
2147   data1  = obj[1];          \
2148   dst[1] = data1>>16;       \
2149   vpos   = data1 & 0xffff;  \
2150   data1  = obj[2];          \
2151   vpos  += voffs;           \
2152   dst[4] = data1;           \
2153   vpos  &= vmask;           \
2154   hpos   = data1>>16;       \
2155   data1  = obj[3];          \
2156   hpos  += hoffs;           \
2157   dst[2] = vpos;            \
2158   dst[3] = hpos;            \
2159   dst[5] = data1>>16;       \
2160   i      = pcode[i];        \
2161   dst[6] = data1| i<<4;     \
2162   dst += 8;                 \
2163   if (!(--j)) return;       \
2164 }
2165 
2166 #define EXTRACT_EVEN         \
2167 if((data1=obj[0])&0x80000000)\
2168 {                            \
2169   dst[1] = data1;            \
2170   data1>>= 16;               \
2171   i      = data1 & 7;        \
2172   data1 &= 0xff00;           \
2173   dst[0] = data1 | zcode[i]; \
2174   data1  = obj[1];           \
2175   hpos   = data1 & 0xffff;   \
2176   vpos   = data1>>16;        \
2177   hpos  += hoffs;            \
2178   vpos  += voffs;            \
2179   data1  = obj[2];           \
2180   vpos  &= vmask;            \
2181   dst[3] = hpos;             \
2182   dst[2] = vpos;             \
2183   dst[5] = data1;            \
2184   dst[4] = data1>>16;        \
2185   data1  = obj[3]>>16;       \
2186   i      = pcode[i];         \
2187   dst[6] = data1 | i<<4;     \
2188   dst += 8;                  \
2189   if (!(--j)) return;        \
2190 }
2191 
2192 		// These suspecious looking flags might tell the ESC chip what zcode/priority combos to use.
2193 		// At the beginning of each sprite chunk there're at least three pointers to the main ROM but
2194 		// I can't make out anything meaningful.
2195 		magicid = srcbase[0x71f0/4];
2196 
2197 		hmask = vmask = 0x3ff;
2198 		if (magicid != 0x11010111)
2199 		{
2200 			switch (magicid)
2201 			{
2202 				case 0x10010801: i = 6; break;
2203 				case 0x11010010: i = 5; vmask = 0x1ff; break;
2204 				case 0x01111018: i = 4; break;
2205 				case 0x10010011: i = 3;
2206 					if ((srcbase[0x1c75]&0xff)==32) K055555_write_reg(K55_BLEND_ENABLES,36); // (TEMPORARY)
2207 				break;
2208 				case 0x11010811: i = 2; break;
2209 				case 0x10000010: i = 1; break;
2210 				default:         i = 0;
2211 			}
2212 			vcorr = srcbase[0x26a0/4] & 0xffff;
2213 			hcorr = srcbase[0x26a4/4] >> 16;
2214 			hcorr -= 10;
2215 		}
2216 		else
2217 			hcorr = vcorr = i = 0;
2218 
2219 		zcode = ztable[i];
2220 		pcode = ptable[i];
2221 
2222 		dst = K053247_ram;
2223 		j = 256;
2224 
2225 		// decode Vic-Viper
2226 		if (srcbase[0x049c/4] & 0xffff0000)
2227 		{
2228 			hoffs = srcbase[0x0502/4] & 0xffff;
2229 			voffs = srcbase[0x0506/4] & 0xffff;
2230 			hoffs -= hcorr;
2231 			voffs -= vcorr;
2232 			obj = &srcbase[0x049e/4];
2233 			EXTRACT_ODD
2234 			obj = &srcbase[0x04ae/4];
2235 			EXTRACT_ODD
2236 			obj = &srcbase[0x04be/4];
2237 			EXTRACT_ODD
2238 		}
2239 
2240 		// decode Lord British (the designer must be a Richard Garriot fan too:)
2241 		if (srcbase[0x0848/4] & 0x0000ffff)
2242 		{
2243 			hoffs = srcbase[0x08b0/4]>>16;
2244 			voffs = srcbase[0x08b4/4]>>16;
2245 			hoffs -= hcorr;
2246 			voffs -= vcorr;
2247 			obj = &srcbase[0x084c/4];
2248 			EXTRACT_EVEN
2249 			obj = &srcbase[0x085c/4];
2250 			EXTRACT_EVEN
2251 			obj = &srcbase[0x086c/4];
2252 			EXTRACT_EVEN
2253 		}
2254 
2255 		// decode common sprites
2256 		src = srcbase + srcoffs;
2257 		srcend = src + count * 0x30;
2258 		do
2259 		{
2260 			if (!src[0] || !(i = src[7] & 0xf)) continue; // reject retired or zero-element groups
2261 			i <<= 2;
2262 			hoffs = src[5]>>16;
2263 			voffs = src[6]>>16;
2264 			hoffs -= hcorr;
2265 			voffs -= vcorr;
2266 			obj = src + 8;
2267 			objend = obj + i;
2268 
2269 			do
2270 			{
2271 				EXTRACT_EVEN
2272 			}
2273 			while ((obj+=4)<objend);
2274 		}
2275 		while ((src+=0x30)<srcend);
2276 
2277 		// clear residual data
2278 		if (j) do { *dst = 0; dst += 8; } while (--j);
2279 	}
2280 
2281 #undef EXTRACT_ODD
2282 #undef EXTRACT_EVEN
2283 }
2284