1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood
3
4 // k053247
5
6 #include "tiles_generic.h"
7 #include "konamiic.h"
8
9 #define K053247_CUSTOMSHADOW 0x20000000
10 #define K053247_SHDSHIFT 20
11
12 static UINT8 K053246Regs[8];
13 static UINT8 K053246_OBJCHA_line;
14 UINT8 *K053247Ram;
15 static UINT16 K053247Regs[16];
16
17 static UINT8 *K053246Gfx;
18 static UINT32 K053246Mask;
19 static UINT8 *K053246GfxExp;
20 static UINT32 K053246MaskExp;
21
22 static INT32 K053247_dx;
23 static INT32 K053247_dy;
24 static INT32 K053247_wraparound;
25
26 static INT32 nBpp = 4;
27
28 static INT32 K053247Flags;
29
30 void (*K053247Callback)(INT32 *code, INT32 *color, INT32 *priority);
31
K053247Reset()32 void K053247Reset()
33 {
34 memset (K053247Ram, 0, 0x1000);
35 memset (K053247Regs, 0, 16 * sizeof (UINT16));
36 memset (K053246Regs, 0, 8);
37
38 K053246_OBJCHA_line = 0; // clear
39 }
40
K053247Scan(INT32 nAction)41 void K053247Scan(INT32 nAction)
42 {
43 struct BurnArea ba;
44
45 if (nAction & ACB_MEMORY_RAM) {
46 memset(&ba, 0, sizeof(ba));
47 ba.Data = K053247Ram;
48 ba.nLen = 0x1000;
49 ba.szName = "K053247 Ram";
50 BurnAcb(&ba);
51
52 ba.Data = K053247Regs;
53 ba.nLen = 0x0010 * sizeof(UINT16);
54 ba.szName = "K053247 Regs";
55 BurnAcb(&ba);
56
57 ba.Data = K053246Regs;
58 ba.nLen = 0x0008;
59 ba.szName = "K053246 Regs";
60 BurnAcb(&ba);
61
62 SCAN_VAR(K053246_OBJCHA_line);
63 SCAN_VAR(K053247_wraparound);
64 }
65 }
66
K053247Init(UINT8 * gfxrom,UINT8 * gfxromexp,INT32 gfxlen,void (* Callback)(INT32 * code,INT32 * color,INT32 * priority),INT32 flags)67 void K053247Init(UINT8 *gfxrom, UINT8 *gfxromexp, INT32 gfxlen, void (*Callback)(INT32 *code, INT32 *color, INT32 *priority), INT32 flags)
68 {
69 K053247Ram = (UINT8*)BurnMalloc(0x1000);
70
71 K053246Gfx = gfxrom;
72 K053246Mask = gfxlen;
73
74 K053246GfxExp = gfxromexp;
75 K053246MaskExp = ((gfxlen * 2) + 1) / 0x100;
76
77 K053247Callback = Callback;
78
79 K053247_dx = 0;
80 K053247_dy = 0;
81 K053247_wraparound = 1;
82
83 KonamiAllocateBitmaps();
84
85 K053247Flags = flags; // 0x02 highlight, 0x01 shadow
86
87 KonamiIC_K053247InUse = 1;
88
89 nBpp = 4;
90 }
91
K053247SetBpp(INT32 bpp)92 void K053247SetBpp(INT32 bpp)
93 {
94 nBpp = bpp;
95 }
96
K053247Exit()97 void K053247Exit()
98 {
99 BurnFree (K053247Ram);
100
101 K053247Flags = 0;
102
103 memset (K053247Regs, 0, 16 * sizeof(UINT16));
104 }
105
K053247Export(UINT8 ** ram,UINT8 ** gfx,void (** callback)(INT32 *,INT32 *,INT32 *),INT32 * dx,INT32 * dy)106 void K053247Export(UINT8 **ram, UINT8 **gfx, void (**callback)(INT32 *, INT32 *, INT32 *), INT32 *dx, INT32 *dy)
107 {
108 if (ram) *ram = K053247Ram;
109 if (gfx) *gfx = K053246Gfx;
110
111 if (dx) *dx = K053247_dx;
112 if (dy) *dy = K053247_dy;
113
114 if(callback) *callback = K053247Callback;
115 }
116
K053247GfxDecode(UINT8 * src,UINT8 * dst,INT32 len)117 void K053247GfxDecode(UINT8 *src, UINT8 *dst, INT32 len) // 16x16
118 {
119 for (INT32 i = 0; i < len; i++)
120 {
121 INT32 t = src[i^1];
122 dst[(i << 1) + 0] = t >> 4;
123 dst[(i << 1) + 1] = t & 0x0f;
124 }
125 }
126
K053247SetSpriteOffset(INT32 offsx,INT32 offsy)127 void K053247SetSpriteOffset(INT32 offsx, INT32 offsy)
128 {
129 K053247_dx = offsx;
130 K053247_dy = offsy;
131 }
132
K053247WrapEnable(INT32 status)133 void K053247WrapEnable(INT32 status)
134 {
135 K053247_wraparound = status;
136 }
137
K053247Read(INT32 offset)138 UINT8 K053247Read(INT32 offset)
139 {
140 return K053247Ram[offset & 0xfff];
141 }
142
K053247ReadWord(INT32 offset)143 UINT16 K053247ReadWord(INT32 offset)
144 {
145 return *((UINT16*)(K053247Ram + (offset & 0xffe)));
146 }
147
K053247WriteWord(INT32 offset,UINT16 data)148 void K053247WriteWord(INT32 offset, UINT16 data)
149 {
150 *((UINT16*)(K053247Ram + (offset & 0xffe))) = BURN_ENDIAN_SWAP_INT16(data);
151 }
152
K053247Write(INT32 offset,INT32 data)153 void K053247Write(INT32 offset, INT32 data)
154 {
155 if (data & 0x10000) { // use word
156 *((UINT16*)(K053247Ram + (offset & 0xffe))) = BURN_ENDIAN_SWAP_INT16(data);
157 } else {
158 K053247Ram[offset & 0xfff] = data;
159 }
160 }
161
K053247WriteRegsByte(INT32 offset,UINT8 data)162 void K053247WriteRegsByte(INT32 offset, UINT8 data)
163 {
164 UINT8 *regs = (UINT8*)&K053247Regs;
165
166 regs[(offset & 0x1f)^1] = data;
167 }
168
K053247WriteRegsWord(INT32 offset,UINT16 data)169 void K053247WriteRegsWord(INT32 offset, UINT16 data)
170 {
171 K053247Regs[(offset & 0x1e) / 2] = data;
172 }
173
K053247ReadRegs(INT32 offset)174 UINT16 K053247ReadRegs(INT32 offset)
175 {
176 return K053247Regs[offset & 0xf];
177 }
178
K053246ReadRegs(INT32 offset)179 UINT16 K053246ReadRegs(INT32 offset)
180 {
181 return K053246Regs[offset & 7];
182 }
183
K053246Read(INT32 offset)184 UINT8 K053246Read(INT32 offset)
185 {
186 if (K053246_OBJCHA_line) // assert_line
187 {
188 INT32 addr;
189
190 addr = (K053246Regs[6] << 17) | (K053246Regs[7] << 9) | (K053246Regs[4] << 1) | ((offset & 1) ^ 1);
191 addr &= K053246Mask;
192
193 return K053246Gfx[addr];
194 }
195 else
196 {
197 return 0;
198 }
199 }
200
K053246Write(INT32 offset,INT32 data)201 void K053246Write(INT32 offset, INT32 data)
202 {
203 if (data & 0x10000) { // handle it as a word
204 *((UINT16*)(K053246Regs + (offset & 6))) = BURN_ENDIAN_SWAP_INT16(data);
205 } else {
206 K053246Regs[offset & 7] = data;
207 }
208 }
209
K053246_set_OBJCHA_line(INT32 state)210 void K053246_set_OBJCHA_line(INT32 state)
211 {
212 K053246_OBJCHA_line = state;
213 }
214
K053246_is_IRQ_enabled()215 INT32 K053246_is_IRQ_enabled()
216 {
217 return K053246Regs[5] & 0x10;
218 }
219
K053247SpritesRender()220 void K053247SpritesRender()
221 {
222 #define NUM_SPRITES 256
223
224
225 UINT8 dtable[256];
226 UINT8 stable[256];
227 UINT8 *wtable;
228
229 memset(dtable, 1, 256);
230 dtable[0] = 0;
231 memset(stable, 2, 256);
232 stable[0] = 0;
233
234 static const INT32 xoffset[8] = { 0, 1, 4, 5, 16, 17, 20, 21 };
235 static const INT32 yoffset[8] = { 0, 2, 8, 10, 32, 34, 40, 42 };
236
237 INT32 sortedlist[NUM_SPRITES];
238 INT32 offs,zcode;
239 INT32 ox,oy,color,code,size,w,h,x,y,xa,ya,flipx,flipy,mirrorx,mirrory,shadow,zoomx,zoomy,primask;
240 INT32 nozoom,count,temp,shdmask;
241
242 INT32 flipscreenx = K053246Regs[5] & 0x01;
243 INT32 flipscreeny = K053246Regs[5] & 0x02;
244 INT32 offx = (INT16)((K053246Regs[0] << 8) | K053246Regs[1]);
245 INT32 offy = (INT16)((K053246Regs[2] << 8) | K053246Regs[3]);
246
247 UINT16 *SprRam = (UINT16*)K053247Ram;
248
249 UINT8 *gfxbase = K053246GfxExp;
250
251 INT32 screen_width = nScreenWidth-1;
252
253 if (K053247Flags & 1) {
254 if (K053247Flags & 2) {
255 shdmask = 3;
256 } else {
257 shdmask = 0;
258 }
259 } else {
260 shdmask = -1;
261 }
262
263 // Prebuild a sorted table by descending Z-order.
264 zcode = K05324xZRejection;
265 offs = count = 0;
266
267 if (zcode == -1)
268 {
269 for (; offs<0x800; offs+=8)
270 if (BURN_ENDIAN_SWAP_INT16(SprRam[offs]) & 0x8000) sortedlist[count++] = offs;
271 }
272 else
273 {
274 for (; offs<0x800; offs+=8)
275 if ((BURN_ENDIAN_SWAP_INT16(SprRam[offs]) & 0x8000) && ((BURN_ENDIAN_SWAP_INT16(SprRam[offs]) & 0xff) != zcode)) sortedlist[count++] = offs;
276 }
277
278 w = count;
279 count--;
280 h = count;
281
282 if (!(K053247Regs[0xc/2] & 0x10))
283 {
284 // sort objects in decending order(smaller z closer) when OPSET PRI is clear
285 for (y=0; y<h; y++)
286 {
287 offs = sortedlist[y];
288 zcode = BURN_ENDIAN_SWAP_INT16(SprRam[offs]) & 0xff;
289 for (x=y+1; x<w; x++)
290 {
291 temp = sortedlist[x];
292 code = BURN_ENDIAN_SWAP_INT16(SprRam[temp]) & 0xff;
293 if (zcode <= code) { zcode = code; sortedlist[x] = offs; sortedlist[y] = offs = temp; }
294 }
295 }
296 }
297 else
298 {
299 // sort objects in ascending order(bigger z closer) when OPSET PRI is set
300 for (y=0; y<h; y++)
301 {
302 offs = sortedlist[y];
303 zcode = BURN_ENDIAN_SWAP_INT16(SprRam[offs]) & 0xff;
304 for (x=y+1; x<w; x++)
305 {
306 temp = sortedlist[x];
307 code = BURN_ENDIAN_SWAP_INT16(SprRam[temp]) & 0xff;
308 if (zcode >= code) { zcode = code; sortedlist[x] = offs; sortedlist[y] = offs = temp; }
309 }
310 }
311 }
312
313 for (INT32 i = count; i >= 0; i--)
314 {
315 offs = sortedlist[i];
316
317 code = BURN_ENDIAN_SWAP_INT16(SprRam[offs+1]);
318 shadow = color = BURN_ENDIAN_SWAP_INT16(SprRam[offs+6]);
319 primask = 0;
320
321 (*K053247Callback)(&code,&color,&primask);
322
323 temp = BURN_ENDIAN_SWAP_INT16(SprRam[offs]);
324
325 size = (temp & 0x0f00) >> 8;
326 w = 1 << (size & 0x03);
327 h = 1 << ((size >> 2) & 0x03);
328
329 /* the sprite can start at any point in the 8x8 grid. We have to */
330 /* adjust the offsets to draw it correctly. Simpsons does this all the time. */
331 xa = 0;
332 ya = 0;
333 if (code & 0x01) xa += 1;
334 if (code & 0x02) ya += 1;
335 if (code & 0x04) xa += 2;
336 if (code & 0x08) ya += 2;
337 if (code & 0x10) xa += 4;
338 if (code & 0x20) ya += 4;
339 code &= ~0x3f;
340
341 oy = (INT16)BURN_ENDIAN_SWAP_INT16(SprRam[offs+2]);
342 ox = (INT16)BURN_ENDIAN_SWAP_INT16(SprRam[offs+3]);
343
344 ox += K053247_dx;
345 oy -= K053247_dy;
346
347 if (K053247_wraparound)
348 {
349 offx &= 0x3ff;
350 offy &= 0x3ff;
351 oy &= 0x3ff;
352 ox &= 0x3ff;
353 }
354
355 y = zoomy = BURN_ENDIAN_SWAP_INT16(SprRam[offs+4]) & 0x3ff;
356 if (zoomy) zoomy = (0x400000+(zoomy>>1)) / zoomy; else zoomy = 0x800000;
357 if (!(temp & 0x4000))
358 {
359 x = zoomx = BURN_ENDIAN_SWAP_INT16(SprRam[offs+5]) & 0x3ff;
360 if (zoomx) zoomx = (0x400000+(zoomx>>1)) / zoomx;
361 else zoomx = 0x800000;
362 }
363 else { zoomx = zoomy; x = y; }
364
365 if ( K053246Regs[5] & 0x08 ) // Check only "Bit #3 is '1'?" (NOTE: good guess)
366 {
367 zoomx >>= 1; // Fix sprite width to HALF size
368 ox = (ox >> 1) + 1; // Fix sprite draw position
369 if (flipscreenx) ox += screen_width;
370 nozoom = 0;
371 }
372 else
373 nozoom = (x == 0x40 && y == 0x40);
374
375 flipx = temp & 0x1000;
376 flipy = temp & 0x2000;
377 mirrorx = shadow & 0x4000;
378 if (mirrorx) flipx = 0; // documented and confirmed
379 mirrory = shadow & 0x8000;
380
381 INT32 highlight = 0;
382
383 wtable = dtable;
384
385 if (color == -1)
386 {
387 // drop the entire sprite to shadow unconditionally
388 if (shdmask < 0) continue;
389 color = 0;
390 shadow = -1;
391
392 wtable = stable;
393 }
394 else
395 {
396 if (shdmask >= 0)
397 {
398 shadow = (color & 0x20000000) ? (color >> 20) : (shadow >> 10);
399
400 if (shadow &= 3) {
401 if (((shadow-1) & shdmask) == 1) highlight = 1;
402 }
403 }
404 else
405 shadow = 0;
406 }
407
408 color &= 0xffff; // strip attribute flags
409
410 if (flipscreenx)
411 {
412 ox = -ox;
413 if (!mirrorx) flipx = !flipx;
414 }
415 if (flipscreeny)
416 {
417 oy = -oy;
418 if (!mirrory) flipy = !flipy;
419 }
420
421 // apply wrapping and global offsets
422 if (K053247_wraparound)
423 {
424 ox = ( ox - offx) & 0x3ff;
425 oy = (-oy - offy) & 0x3ff;
426 if (ox >= 0x300) ox -= 0x400;
427 if (oy >= 0x280) oy -= 0x400;
428 }
429 else
430 {
431 ox = ox - offx;
432 oy = -oy - offy;
433 }
434
435 // apply global and display window offsets
436
437 /* the coordinates given are for the *center* of the sprite */
438 ox -= (zoomx * w) >> 13;
439 oy -= (zoomy * h) >> 13;
440
441 dtable[15] = shadow ? 2 : 1;
442
443 for (y = 0;y < h;y++)
444 {
445 INT32 sx,sy,zw,zh;
446
447 sy = oy + ((zoomy * y + (1<<11)) >> 12);
448 zh = (oy + ((zoomy * (y+1) + (1<<11)) >> 12)) - sy;
449
450 for (x = 0;x < w;x++)
451 {
452 INT32 c,fx,fy;
453
454 sx = ox + ((zoomx * x + (1<<11)) >> 12);
455 zw = (ox + ((zoomx * (x+1) + (1<<11)) >> 12)) - sx;
456 c = code;
457 if (mirrorx)
458 {
459 if ((flipx == 0) ^ ((x<<1) < w))
460 {
461 /* mirror left/right */
462 c += xoffset[(w-1-x+xa)&7];
463 fx = 1;
464 }
465 else
466 {
467 c += xoffset[(x+xa)&7];
468 fx = 0;
469 }
470 }
471 else
472 {
473 if (flipx) c += xoffset[(w-1-x+xa)&7];
474 else c += xoffset[(x+xa)&7];
475 fx = flipx;
476 }
477
478 if (mirrory)
479 {
480 if ((flipy == 0) ^ ((y<<1) >= h))
481 {
482 /* mirror top/bottom */
483 c += yoffset[(h-1-y+ya)&7];
484 fy = 1;
485 }
486 else
487 {
488 c += yoffset[(y+ya)&7];
489 fy = 0;
490 }
491 }
492 else
493 {
494 if (flipy) c += yoffset[(h-1-y+ya)&7];
495 else c += yoffset[(y+ya)&7];
496 fy = flipy;
497 }
498
499 c &= K053246MaskExp;
500
501 if (shadow || wtable == stable) {
502 if (mirrory && h == 1)
503 konami_render_zoom_shadow_tile(gfxbase, c, nBpp, color, sx, sy, fx, !fy, 16, 16, zw << 12, zh << 12, primask, highlight);
504
505 konami_render_zoom_shadow_tile(gfxbase, c, nBpp, color, sx, sy, fx, fy, 16, 16, zw << 12, zh << 12, primask, highlight);
506 continue;
507 }
508
509 if (mirrory && h == 1)
510 {
511 if (nozoom) {
512 konami_draw_16x16_prio_tile(gfxbase, c, nBpp, color, sx, sy, fx, !fy, primask);
513 } else {
514 konami_draw_16x16_priozoom_tile(gfxbase, c, nBpp, color, 0, sx, sy, fx, !fy, 16, 16, zw<<12, zh<<12, primask);
515 }
516 }
517
518 if (nozoom) {
519 konami_draw_16x16_prio_tile(gfxbase, c, nBpp, color, sx, sy, fx, fy, primask);
520 } else {
521 konami_draw_16x16_priozoom_tile(gfxbase, c, nBpp, color, 0, sx, sy, fx, fy, 16, 16, zw<<12, zh<<12, primask);
522 }
523 } // end of X loop
524 } // end of Y loop
525
526 } // end of sprite-list loop
527 #undef NUM_SPRITES
528 }
529
alpha_blend_r32(UINT32 d,UINT32 s,UINT32 p)530 static inline UINT32 alpha_blend_r32(UINT32 d, UINT32 s, UINT32 p)
531 {
532 if (p == 0) return d;
533
534 INT32 a = 256 - p;
535
536 return (((((s & 0xff00ff) * p) + ((d & 0xff00ff) * a)) & 0xff00ff00) |
537 ((((s & 0x00ff00) * p) + ((d & 0x00ff00) * a)) & 0x00ff0000)) >> 8;
538 }
539
shadow_blend_338(UINT32 d,INT32 shadow_bank)540 static inline UINT32 shadow_blend_338(UINT32 d, INT32 shadow_bank) // for k054338
541 {
542 INT32 r = ((d&0xff0000) >> 16) + m_shd_rgb[0 + (shadow_bank * 3)];
543 if (r > 0xff) r = 0xff;
544 if (r < 0) r = 0;
545 r = r << 16;
546
547 INT32 g = ((d&0x00ff00) >> 8) + m_shd_rgb[1 + (shadow_bank * 3)];
548 if (g > 0xff) g = 0xff;
549 if (g < 0) g = 0;
550 g = g << 8;
551
552 INT32 b = ((d&0x0000ff) >> 0) + m_shd_rgb[2 + (shadow_bank * 3)];
553 if (b > 0xff) b = 0xff;
554 if (b < 0) b = 0;
555 return r|g|b;
556 }
557
shadow_blend(UINT32 d,INT32 shadow_bank)558 static inline UINT32 shadow_blend(UINT32 d, INT32 shadow_bank)
559 {
560 if (KonamiIC_K054338InUse) return shadow_blend_338(d, shadow_bank);
561 return ((((d & 0xff00ff) * 0x9d) & 0xff00ff00) + (((d & 0x00ff00) * 0x9d) & 0x00ff0000)) / 0x100;
562 }
563
highlight_blend(UINT32 d)564 static inline UINT32 highlight_blend(UINT32 d)
565 {
566 INT32 r = ((d&0xff0000)+0x220000);
567 if (r > 0xff0000) r = 0xff0000;
568
569 INT32 g = ((d&0x00ff00)+0x002200);
570 if (g > 0x00ff00) g = 0x00ff00;
571
572 INT32 b = ((d&0x0000ff)+0x000022);
573 if (b > 0x0000ff) b = 0x0000ff;
574 return r|g|b;
575 }
576
577 #define GX_ZBUFW 512
578 #define GX_ZBUFH 256
579
zdrawgfxzoom32GP(UINT32 code,UINT32 color,INT32 flipx,INT32 flipy,INT32 sx,INT32 sy,INT32 scalex,INT32 scaley,INT32 alpha,INT32 drawmode,INT32 zcode,INT32 pri,UINT8 * gx_objzbuf,UINT8 * gx_shdzbuf)580 void zdrawgfxzoom32GP(UINT32 code, UINT32 color, INT32 flipx, INT32 flipy, INT32 sx, INT32 sy,
581 INT32 scalex, INT32 scaley, INT32 alpha, INT32 drawmode, INT32 zcode, INT32 pri, UINT8* gx_objzbuf, UINT8* gx_shdzbuf)
582 {
583 #define FP 19
584 #define FPONE (1<<FP)
585 #define FPHALF (1<<(FP-1))
586 #define FPENT 0
587
588 // inner loop
589 const UINT8 *src_ptr;
590 INT32 src_x;
591 INT32 eax, ecx;
592 INT32 src_fx, src_fdx;
593 INT32 shdpen;
594 UINT8 z8 = 0, p8 = 0;
595 UINT8 *ozbuf_ptr;
596 UINT8 *szbuf_ptr;
597 const UINT32 *pal_base;
598 const UINT32 *shd_base;
599 UINT32 *dst_ptr;
600
601 // outter loop
602 INT32 src_fby, src_fdy, src_fbx;
603 const UINT8 *src_base;
604 INT32 dst_w, dst_h;
605
606 // one-time
607 INT32 nozoom, granularity;
608 INT32 src_fw, src_fh;
609 INT32 dst_minx, dst_maxx, dst_miny, dst_maxy;
610 INT32 dst_skipx, dst_skipy, dst_x, dst_y, dst_lastx, dst_lasty;
611 INT32 src_pitch, dst_pitch;
612
613 INT32 highlight_enable = (drawmode >> 4) && (K053247Flags & 2);// for fba
614 if (highlight_enable) highlight_enable = (drawmode >> 4) & 0x7;
615 //INT32 highlight_enable = drawmode >> 4;// for fba
616 drawmode &= 0xf;
617
618 // cull illegal and transparent objects
619 if (!scalex || !scaley) return;
620
621 // find shadow pens and cull invisible shadows
622 granularity = shdpen = ((1 << nBpp) /*- 1*/);
623 shdpen--;
624
625 if (zcode >= 0)
626 {
627 if (drawmode == 5) { drawmode = 4; shdpen = 1; }
628 }
629 else
630 if (drawmode >= 4) return;
631
632 // alpha blend necessary?
633 if (drawmode & 2)
634 {
635 if (alpha <= 0) return;
636 if (alpha >= 255) drawmode &= ~2;
637 }
638
639 // fill internal data structure with default values
640 ozbuf_ptr = gx_objzbuf;
641 szbuf_ptr = gx_shdzbuf;
642
643 src_pitch = 16;
644 src_fw = 16;
645 src_fh = 16;
646 src_base = K053246GfxExp + (code * 0x100);
647
648 pal_base = konami_palette32 + (color << nBpp);
649 shd_base = konami_palette32; // m_palette->shadow_table(); // iq_132
650
651 dst_ptr = konami_bitmap32;
652 dst_pitch = nScreenWidth;
653 dst_minx = 0;
654 dst_maxx = (nScreenWidth - 1);
655 dst_miny = 0;
656 dst_maxy = (nScreenHeight - 1);
657 dst_x = sx;
658 dst_y = sy;
659
660 // cull off-screen objects
661 if (dst_x > dst_maxx || dst_y > dst_maxy) return;
662 nozoom = (scalex == 0x10000 && scaley == 0x10000);
663 if (nozoom)
664 {
665 dst_h = dst_w = 16;
666 src_fdy = src_fdx = 1;
667 }
668 else
669 {
670 dst_w = ((scalex<<4)+0x8000)>>16;
671 dst_h = ((scaley<<4)+0x8000)>>16;
672 if (!dst_w || !dst_h) return;
673
674 src_fw <<= FP;
675 src_fh <<= FP;
676 src_fdx = src_fw / dst_w;
677 src_fdy = src_fh / dst_h;
678 }
679 dst_lastx = dst_x + dst_w - 1;
680 if (dst_lastx < dst_minx) return;
681 dst_lasty = dst_y + dst_h - 1;
682 if (dst_lasty < dst_miny) return;
683
684 // clip destination
685 dst_skipx = 0;
686 eax = dst_minx; if ((eax -= dst_x) > 0) { dst_skipx = eax; dst_w -= eax; dst_x = dst_minx; }
687 eax = dst_lastx; if ((eax -= dst_maxx) > 0) dst_w -= eax;
688 dst_skipy = 0;
689 eax = dst_miny; if ((eax -= dst_y) > 0) { dst_skipy = eax; dst_h -= eax; dst_y = dst_miny; }
690 eax = dst_lasty; if ((eax -= dst_maxy) > 0) dst_h -= eax;
691
692 // calculate zoom factors and clip source
693 if (nozoom)
694 {
695 if (!flipx) src_fbx = 0; else { src_fbx = src_fw - 1; src_fdx = -src_fdx; }
696 if (!flipy) src_fby = 0; else { src_fby = src_fh - 1; src_fdy = -src_fdy; src_pitch = -src_pitch; }
697 }
698 else
699 {
700 if (!flipx) src_fbx = FPENT; else { src_fbx = src_fw - FPENT - 1; src_fdx = -src_fdx; }
701 if (!flipy) src_fby = FPENT; else { src_fby = src_fh - FPENT - 1; src_fdy = -src_fdy; }
702 }
703 src_fbx += dst_skipx * src_fdx;
704 src_fby += dst_skipy * src_fdy;
705
706 // adjust insertion points and pre-entry constants
707 eax = (dst_y - dst_miny) * GX_ZBUFW + (dst_x - dst_minx) + dst_w;
708 z8 = (UINT8)zcode;
709 p8 = (UINT8)pri;
710 ozbuf_ptr += eax;
711 szbuf_ptr += eax << 1;
712 dst_ptr += dst_y * dst_pitch + dst_x + dst_w;
713 dst_w = -dst_w;
714
715 if (!nozoom)
716 {
717 ecx = src_fby; src_fby += src_fdy;
718 ecx >>= FP; src_fx = src_fbx;
719 src_x = src_fbx; src_fx += src_fdx;
720 ecx <<= 4; src_ptr = src_base;
721 src_x >>= FP; src_ptr += ecx;
722 ecx = dst_w;
723
724 if (zcode < 0) // no shadow and z-buffering
725 {
726 do {
727 do {
728 eax = src_ptr[src_x];
729 src_x = src_fx;
730 src_fx += src_fdx;
731 src_x >>= FP;
732 if (!eax || eax >= shdpen) continue;
733 dst_ptr [ecx] = pal_base[eax];
734 }
735 while (++ecx);
736
737 ecx = src_fby; src_fby += src_fdy;
738 dst_ptr += dst_pitch;
739 ecx >>= FP; src_fx = src_fbx;
740 src_x = src_fbx; src_fx += src_fdx;
741 ecx <<= 4; src_ptr = src_base;
742 src_x >>= FP; src_ptr += ecx;
743 ecx = dst_w;
744 }
745 while (--dst_h);
746 }
747 else
748 {
749 switch (drawmode)
750 {
751 case 0: // all pens solid
752 do {
753 do {
754 eax = src_ptr[src_x];
755 src_x = src_fx;
756 src_fx += src_fdx;
757 src_x >>= FP;
758 if (!eax || ozbuf_ptr[ecx] < z8) continue;
759 eax = pal_base[eax];
760 ozbuf_ptr[ecx] = z8;
761 dst_ptr [ecx] = eax;
762 }
763 while (++ecx);
764
765 ecx = src_fby; src_fby += src_fdy;
766 ozbuf_ptr += GX_ZBUFW;
767 dst_ptr += dst_pitch;
768 ecx >>= FP; src_fx = src_fbx;
769 src_x = src_fbx; src_fx += src_fdx;
770 ecx <<= 4; src_ptr = src_base;
771 src_x >>= FP; src_ptr += ecx;
772 ecx = dst_w;
773 }
774 while (--dst_h);
775 break;
776
777 case 1: // solid pens only
778 do {
779 do {
780 eax = src_ptr[src_x];
781 src_x = src_fx;
782 src_fx += src_fdx;
783 src_x >>= FP;
784 if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
785 eax = pal_base[eax];
786 ozbuf_ptr[ecx] = z8;
787 dst_ptr [ecx] = eax;
788 }
789 while (++ecx);
790
791 ecx = src_fby; src_fby += src_fdy;
792 ozbuf_ptr += GX_ZBUFW;
793 dst_ptr += dst_pitch;
794 ecx >>= FP; src_fx = src_fbx;
795 src_x = src_fbx; src_fx += src_fdx;
796 ecx <<= 4; src_ptr = src_base;
797 src_x >>= FP; src_ptr += ecx;
798 ecx = dst_w;
799 }
800 while (--dst_h);
801 break;
802
803 case 2: // all pens solid with alpha blending
804 do {
805 do {
806 eax = src_ptr[src_x];
807 src_x = src_fx;
808 src_fx += src_fdx;
809 src_x >>= FP;
810 if (!eax || ozbuf_ptr[ecx] < z8) continue;
811 ozbuf_ptr[ecx] = z8;
812
813 dst_ptr[ecx] = alpha_blend_r32(pal_base[eax], dst_ptr[ecx], alpha);
814 }
815 while (++ecx);
816
817 ecx = src_fby; src_fby += src_fdy;
818 ozbuf_ptr += GX_ZBUFW;
819 dst_ptr += dst_pitch;
820 ecx >>= FP; src_fx = src_fbx;
821 src_x = src_fbx; src_fx += src_fdx;
822 ecx <<= 4; src_ptr = src_base;
823 src_x >>= FP; src_ptr += ecx;
824 ecx = dst_w;
825 }
826 while (--dst_h);
827 break;
828
829 case 3: // solid pens only with alpha blending
830 do {
831 do {
832 eax = src_ptr[src_x];
833 src_x = src_fx;
834 src_fx += src_fdx;
835 src_x >>= FP;
836 if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
837 ozbuf_ptr[ecx] = z8;
838
839 dst_ptr[ecx] = alpha_blend_r32(pal_base[eax], dst_ptr[ecx], alpha);
840 }
841 while (++ecx);
842
843 ecx = src_fby; src_fby += src_fdy;
844 ozbuf_ptr += GX_ZBUFW;
845 dst_ptr += dst_pitch;
846 ecx >>= FP; src_fx = src_fbx;
847 src_x = src_fbx; src_fx += src_fdx;
848 ecx <<= 4; src_ptr = src_base;
849 src_x >>= FP; src_ptr += ecx;
850 ecx = dst_w;
851 }
852 while (--dst_h);
853 break;
854
855 case 4: // shadow pens only
856 do {
857 do {
858 eax = src_ptr[src_x];
859 src_x = src_fx;
860 src_fx += src_fdx;
861 src_x >>= FP;
862 if (eax < shdpen || szbuf_ptr[ecx*2] < z8 || szbuf_ptr[ecx*2+1] <= p8) continue;
863 //UINT32 pix = dst_ptr[ecx];
864 szbuf_ptr[ecx*2] = z8;
865 szbuf_ptr[ecx*2+1] = p8;
866
867 // the shadow tables are 15-bit lookup tables which accept RGB15... lossy, nasty, yuck!
868 if (highlight_enable) {
869 dst_ptr[ecx] = highlight_blend(dst_ptr[ecx]);
870 } else {
871 dst_ptr[ecx] = shadow_blend(dst_ptr[ecx], highlight_enable); //shd_base[pix.as_rgb15()];
872 }
873 //dst_ptr[ecx] =(eax>>3&0x001f);lend_r32( eax, 0x00000000, 128);
874 }
875 while (++ecx);
876
877 ecx = src_fby; src_fby += src_fdy;
878 szbuf_ptr += (GX_ZBUFW<<1);
879 dst_ptr += dst_pitch;
880 ecx >>= FP; src_fx = src_fbx;
881 src_x = src_fbx; src_fx += src_fdx;
882 ecx <<= 4; src_ptr = src_base;
883 src_x >>= FP; src_ptr += ecx;
884 ecx = dst_w;
885 }
886 while (--dst_h);
887 break;
888 } // switch (drawmode)
889 } // if (zcode < 0)
890 } // if (!nozoom)
891 else
892 {
893 src_ptr = src_base + (src_fby<<4) + src_fbx;
894 src_fdy = src_fdx * dst_w + src_pitch;
895 ecx = dst_w;
896
897 if (zcode < 0) // no shadow and z-buffering
898 {
899 do {
900 do {
901 eax = *src_ptr;
902 src_ptr += src_fdx;
903 if (!eax || eax >= shdpen) continue;
904 dst_ptr[ecx] = pal_base[eax];
905 }
906 while (++ecx);
907
908 src_ptr += src_fdy;
909 dst_ptr += dst_pitch;
910 ecx = dst_w;
911 }
912 while (--dst_h);
913 }
914 else
915 {
916 switch (drawmode)
917 {
918 case 0: // all pens solid
919 do {
920 do {
921 eax = *src_ptr;
922 src_ptr += src_fdx;
923 if (!eax || ozbuf_ptr[ecx] < z8) continue;
924 eax = pal_base[eax];
925 ozbuf_ptr[ecx] = z8;
926 dst_ptr[ecx] = eax;
927 }
928 while (++ecx);
929
930 src_ptr += src_fdy;
931 ozbuf_ptr += GX_ZBUFW;
932 dst_ptr += dst_pitch;
933 ecx = dst_w;
934 }
935 while (--dst_h);
936 break;
937
938 case 1: // solid pens only
939 do {
940 do {
941 eax = *src_ptr;
942 src_ptr += src_fdx;
943 if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
944 eax = pal_base[eax];
945 ozbuf_ptr[ecx] = z8;
946 dst_ptr[ecx] = eax;
947 }
948 while (++ecx);
949
950 src_ptr += src_fdy;
951 ozbuf_ptr += GX_ZBUFW;
952 dst_ptr += dst_pitch;
953 ecx = dst_w;
954 }
955 while (--dst_h);
956 break;
957
958 case 2: // all pens solid with alpha blending
959 do {
960 do {
961 eax = *src_ptr;
962 src_ptr += src_fdx;
963 if (!eax || ozbuf_ptr[ecx] < z8) continue;
964 ozbuf_ptr[ecx] = z8;
965
966 dst_ptr[ecx] = alpha_blend_r32(pal_base[eax], dst_ptr[ecx], alpha);
967 }
968 while (++ecx);
969
970 src_ptr += src_fdy;
971 ozbuf_ptr += GX_ZBUFW;
972 dst_ptr += dst_pitch;
973 ecx = dst_w;
974 }
975 while (--dst_h);
976 break;
977
978 case 3: // solid pens only with alpha blending
979 do {
980 do {
981 eax = *src_ptr;
982 src_ptr += src_fdx;
983 if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
984 ozbuf_ptr[ecx] = z8;
985
986 dst_ptr[ecx] = alpha_blend_r32(pal_base[eax], dst_ptr[ecx], alpha);
987 }
988 while (++ecx);
989
990 src_ptr += src_fdy;
991 ozbuf_ptr += GX_ZBUFW;
992 dst_ptr += dst_pitch;
993 ecx = dst_w;
994 }
995 while (--dst_h);
996 break;
997
998 case 4: // shadow pens only
999 do {
1000 do {
1001 eax = *src_ptr;
1002 src_ptr += src_fdx;
1003 if (eax < shdpen || szbuf_ptr[ecx*2] < z8 || szbuf_ptr[ecx*2+1] <= p8) continue;
1004 //UINT32 pix = dst_ptr[ecx];
1005 szbuf_ptr[ecx*2] = z8;
1006 szbuf_ptr[ecx*2+1] = p8;
1007
1008 // the shadow tables are 15-bit lookup tables which accept RGB15... lossy, nasty, yuck!
1009 if (highlight_enable) {
1010 dst_ptr[ecx] = highlight_blend(dst_ptr[ecx]);
1011 } else {
1012 dst_ptr[ecx] = shadow_blend(dst_ptr[ecx], highlight_enable); //shd_base[pix.as_rgb15()];
1013 }
1014 }
1015 while (++ecx);
1016
1017 src_ptr += src_fdy;
1018 szbuf_ptr += (GX_ZBUFW<<1);
1019 dst_ptr += dst_pitch;
1020 ecx = dst_w;
1021 }
1022 while (--dst_h);
1023 break;
1024 }
1025 }
1026 }
1027 #undef FP
1028 #undef FPONE
1029 #undef FPHALF
1030 #undef FPENT
1031 }
1032
1033
1034
1035
1036
k053247_draw_yxloop_gx(INT32 code,INT32 color,INT32 height,INT32 width,INT32 zoomx,INT32 zoomy,INT32 flipx,INT32 flipy,INT32 ox,INT32 oy,INT32 xa,INT32 ya,INT32 mirrorx,INT32 mirrory,INT32 nozoom,INT32 pri,INT32 zcode,INT32 alpha,INT32 drawmode,UINT8 * gx_objzbuf,UINT8 * gx_shdzbuf,INT32,UINT8 *)1037 void k053247_draw_yxloop_gx(
1038 INT32 code,
1039 INT32 color,
1040 INT32 height, INT32 width,
1041 INT32 zoomx, INT32 zoomy, INT32 flipx, INT32 flipy,
1042 INT32 ox, INT32 oy,
1043 INT32 xa, INT32 ya,
1044 INT32 mirrorx, INT32 mirrory,
1045 INT32 nozoom,
1046 /* gx specifics */
1047 INT32 pri,
1048 INT32 zcode, INT32 alpha, INT32 drawmode,
1049 UINT8* gx_objzbuf, UINT8* gx_shdzbuf,
1050 /* non-gx specifics */
1051 INT32 /*primask*/,
1052 UINT8* /*whichtable*/
1053 )
1054 {
1055 static const INT32 xoffset[8] = { 0, 1, 4, 5, 16, 17, 20, 21 };
1056 static const INT32 yoffset[8] = { 0, 2, 8, 10, 32, 34, 40, 42 };
1057 INT32 zw,zh;
1058 INT32 fx, fy, sx, sy;
1059 INT32 tempcode;
1060
1061 for (INT32 y=0; y<height; y++)
1062 {
1063 sy = oy + ((zoomy * y + (1<<11)) >> 12);
1064 zh = (oy + ((zoomy * (y+1) + (1<<11)) >> 12)) - sy;
1065
1066 for (INT32 x=0; x<width; x++)
1067 {
1068 sx = ox + ((zoomx * x + (1<<11)) >> 12);
1069 zw = (ox + ((zoomx * (x+1) + (1<<11)) >> 12)) - sx;
1070 tempcode = code;
1071
1072 if (mirrorx)
1073 {
1074 if ((!flipx)^((x<<1)<width))
1075 {
1076 /* mirror left/right */
1077 tempcode += xoffset[(width-1-x+xa)&7];
1078 fx = 1;
1079 }
1080 else
1081 {
1082 tempcode += xoffset[(x+xa)&7];
1083 fx = 0;
1084 }
1085 }
1086 else
1087 {
1088 if (flipx) tempcode += xoffset[(width-1-x+xa)&7];
1089 else tempcode += xoffset[(x+xa)&7];
1090 fx = flipx;
1091 }
1092
1093 if (mirrory)
1094 {
1095 if ((!flipy)^((y<<1)>=height))
1096 {
1097 /* mirror top/bottom */
1098 tempcode += yoffset[(height-1-y+ya)&7];
1099 fy = 1;
1100 }
1101 else
1102 {
1103 tempcode += yoffset[(y+ya)&7];
1104 fy = 0;
1105 }
1106 }
1107 else
1108 {
1109 if (flipy) tempcode += yoffset[(height-1-y+ya)&7];
1110 else tempcode += yoffset[(y+ya)&7];
1111 fy = flipy;
1112 }
1113
1114 {
1115 if (nozoom) { zw = zh = 0x10; }
1116
1117 zdrawgfxzoom32GP(
1118 tempcode,
1119 color,
1120 fx,fy,
1121 sx,sy,
1122 zw << 12, zh << 12, alpha, drawmode, zcode, pri,
1123 gx_objzbuf, gx_shdzbuf
1124 );
1125
1126 }
1127 } // end of X loop
1128 } // end of Y loop
1129 }
1130
1131
1132
1133
k053247_draw_single_sprite_gxcore(UINT8 * gx_objzbuf,UINT8 * gx_shdzbuf,INT32 code,UINT16 * gx_spriteram,INT32 offs,INT32 color,INT32 alpha,INT32 drawmode,INT32 zcode,INT32 pri,INT32,INT32,UINT8 *,UINT8 *,INT32)1134 void k053247_draw_single_sprite_gxcore(UINT8 *gx_objzbuf, UINT8 *gx_shdzbuf, INT32 code, UINT16 *gx_spriteram, INT32 offs,
1135 INT32 color, INT32 alpha, INT32 drawmode, INT32 zcode, INT32 pri,
1136 INT32 /*primask*/, INT32 /*shadow*/, UINT8 */*drawmode_table*/, UINT8 */*shadowmode_table*/, INT32 /*shdmask*/)
1137 {
1138 INT32 xa,ya,ox,oy,flipx,flipy,mirrorx,mirrory,zoomx,zoomy,scalex,scaley,nozoom;
1139 INT32 temp, temp4;
1140 INT32 flipscreenx = K053246Regs[5] & 0x01;
1141 INT32 flipscreeny = K053246Regs[5] & 0x02;
1142
1143 xa = ya = 0;
1144 if (code & 0x01) xa += 1;
1145 if (code & 0x02) ya += 1;
1146 if (code & 0x04) xa += 2;
1147 if (code & 0x08) ya += 2;
1148 if (code & 0x10) xa += 4;
1149 if (code & 0x20) ya += 4;
1150 code &= ~0x3f;
1151
1152 temp4 = gx_spriteram[offs];
1153
1154 // mask off the upper 6 bits of coordinate and zoom registers
1155 oy = gx_spriteram[offs+2] & 0x3ff;
1156 ox = gx_spriteram[offs+3] & 0x3ff;
1157
1158 scaley = zoomy = gx_spriteram[offs+4] & 0x3ff;
1159 if (zoomy) zoomy = (0x400000+(zoomy>>1)) / zoomy;
1160 else zoomy = 0x800000;
1161 if (!(temp4 & 0x4000))
1162 {
1163 scalex = zoomx = gx_spriteram[offs+5] & 0x3ff;
1164 if (zoomx) zoomx = (0x400000+(zoomx>>1)) / zoomx;
1165 else zoomx = 0x800000;
1166 }
1167 else { zoomx = zoomy; scalex = scaley; }
1168
1169 nozoom = (scalex == 0x40 && scaley == 0x40);
1170
1171 flipx = temp4 & 0x1000;
1172 flipy = temp4 & 0x2000;
1173
1174 temp = gx_spriteram[offs+6];
1175 mirrorx = temp & 0x4000;
1176 if (mirrorx) flipx = 0; // only applies to x mirror, proven
1177 mirrory = temp & 0x8000;
1178
1179 INT32 objset1 = K053246ReadRegs(5);
1180 // for Escape Kids (GX975)
1181 if ( objset1 & 8 ) // Check only "Bit #3 is '1'?"
1182 {
1183 INT32 screenwidth = nScreenWidth-1;
1184
1185 zoomx = zoomx>>1; // Fix sprite width to HALF size
1186 ox = (ox>>1) + 1; // Fix sprite draw position
1187
1188 if (flipscreenx) ox += screenwidth;
1189 nozoom = 0;
1190 }
1191
1192 if (flipscreenx) { ox = -ox; if (!mirrorx) flipx = !flipx; }
1193 if (flipscreeny) { oy = -oy; if (!mirrory) flipy = !flipy; }
1194
1195 INT32 k053247_opset = K053247ReadRegs(0xc/2);
1196 INT32 wrapsize, xwraplim, ywraplim;
1197 if (k053247_opset & 0x40)
1198 {
1199 wrapsize = 512;
1200 xwraplim = 512 - 64;
1201 ywraplim = 512 - 128;
1202 }
1203 else
1204 {
1205 wrapsize = 1024;
1206 xwraplim = 1024 - 384;
1207 ywraplim = 1024 - 512;
1208 }
1209
1210 // get "display window" offsets
1211 INT32 offx = (INT16)((K053246Regs[0] << 8) | K053246Regs[1]);
1212 INT32 offy = (INT16)((K053246Regs[2] << 8) | K053246Regs[3]);
1213
1214 // apply wrapping and global offsets
1215 temp = wrapsize-1;
1216
1217 ox += K053247_dx;
1218 oy -= K053247_dy;
1219
1220 ox = ( ox - offx) & temp;
1221 oy = (-oy - offy) & temp;
1222 if (ox >= xwraplim) ox -= wrapsize;
1223 if (oy >= ywraplim) oy -= wrapsize;
1224
1225 temp = temp4>>8 & 0x0f;
1226 INT32 width = 1 << (temp & 3);
1227 INT32 height = 1 << (temp>>2 & 3);
1228
1229 ox -= (zoomx * width) >> 13;
1230 oy -= (zoomy * height) >> 13;
1231
1232 k053247_draw_yxloop_gx( code,
1233 color,
1234 height, width,
1235 zoomx, zoomy, flipx, flipy,
1236 ox, oy,
1237 xa, ya,
1238 mirrorx, mirrory,
1239 nozoom,
1240 pri,
1241 zcode, alpha, drawmode,
1242 gx_objzbuf, gx_shdzbuf,
1243 0,NULL
1244 );
1245 }
1246