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