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