/***************************************************************************
Atari Jaguar object processor
****************************************************************************/
#ifndef INCLUDE_OBJECT_PROCESSOR
#error jagobj.c is not directly compilable!
#endif
#define LOG_OBJECTS 0
static UINT16 *scanline;
static UINT16 *clutbase;
static UINT8 *blend_y, *blend_cc;
/*************************************
*
* Object processor init
*
*************************************/
void jagobj_init(running_machine &machine)
{
int i;
/* allocate memory for tables */
blend_y = auto_alloc_array(machine, UINT8, 256 * 256);
blend_cc = auto_alloc_array(machine, UINT8, 256 * 256);
/* fill tables */
for (i = 0; i < 256 * 256; i++)
{
int y = (i >> 8) & 0xff;
int dy = (INT8)i;
int c1 = (i >> 8) & 0x0f;
int dc1 = (INT8)(i << 4) >> 4;
int c2 = (i >> 12) & 0x0f;
int dc2 = (INT8)(i & 0xf0) >> 4;
y += dy;
if (y < 0) y = 0;
else if (y > 0xff) y = 0xff;
blend_y[i] = y;
c1 += dc1;
if (c1 < 0) c1 = 0;
else if (c1 > 0x0f) c1 = 0x0f;
c2 += dc2;
if (c2 < 0) c2 = 0;
else if (c2 > 0x0f) c2 = 0x0f;
blend_cc[i] = (c2 << 4) | c1;
}
}
/*************************************
*
* Blending function
*
*************************************/
#define BLEND(dst, src) \
(dst) = (blend_cc[((dst) & 0xff00) | (((src) >> 8) & 0xff)] << 8) | blend_y[(((dst) & 0xff) << 8) | ((src) & 0xff)];
/*************************************
*
* 4bpp bitmap renderers
*
*************************************/
INLINE void bitmap_4_draw(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos, UINT8 flags, INT32 dxpos)
{
if (firstpix & 7)
{
UINT32 pixsrc = src[firstpix >> 3];
while (firstpix & 7)
{
int pix = (pixsrc >> ((~firstpix & 7) << 2)) & 0x0f;
if ((!(flags & 4) || pix) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = clutbase[BYTE_XOR_BE(pix)];
else
BLEND(scanline[xpos], clutbase[BYTE_XOR_BE(pix)]);
}
xpos += dxpos;
firstpix++;
}
}
firstpix >>= 3;
iwidth >>= 3;
iwidth -= firstpix;
while (iwidth-- > 0)
{
UINT32 pix = src[firstpix++];
if (!(flags & 4) || pix)
{
if ((!(flags & 4) || (pix & 0xf0000000)) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = clutbase[BYTE_XOR_BE(pix >> 28)];
else
BLEND(scanline[xpos], clutbase[BYTE_XOR_BE(pix >> 28)]);
}
xpos += dxpos;
if ((!(flags & 4) || (pix & 0x0f000000)) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = clutbase[BYTE_XOR_BE((pix >> 24) & 0x0f)];
else
BLEND(scanline[xpos], clutbase[BYTE_XOR_BE((pix >> 24) & 0x0f)]);
}
xpos += dxpos;
if ((!(flags & 4) || (pix & 0x00f00000)) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = clutbase[BYTE_XOR_BE((pix >> 20) & 0x0f)];
else
BLEND(scanline[xpos], clutbase[BYTE_XOR_BE((pix >> 20) & 0x0f)]);
}
xpos += dxpos;
if ((!(flags & 4) || (pix & 0x000f0000)) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = clutbase[BYTE_XOR_BE((pix >> 16) & 0x0f)];
else
BLEND(scanline[xpos], clutbase[BYTE_XOR_BE((pix >> 16) & 0x0f)]);
}
xpos += dxpos;
if ((!(flags & 4) || (pix & 0x0000f000)) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = clutbase[BYTE_XOR_BE((pix >> 12) & 0x0f)];
else
BLEND(scanline[xpos], clutbase[BYTE_XOR_BE((pix >> 12) & 0x0f)]);
}
xpos += dxpos;
if ((!(flags & 4) || (pix & 0x00000f00)) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = clutbase[BYTE_XOR_BE((pix >> 8) & 0x0f)];
else
BLEND(scanline[xpos], clutbase[BYTE_XOR_BE((pix >> 8) & 0x0f)]);
}
xpos += dxpos;
if ((!(flags & 4) || (pix & 0x000000f0)) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = clutbase[BYTE_XOR_BE((pix >> 4) & 0x0f)];
else
BLEND(scanline[xpos], clutbase[BYTE_XOR_BE((pix >> 4) & 0x0f)]);
}
xpos += dxpos;
if ((!(flags & 4) || (pix & 0x0000000f)) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = clutbase[BYTE_XOR_BE(pix & 0x0f)];
else
BLEND(scanline[xpos], clutbase[BYTE_XOR_BE(pix & 0x0f)]);
}
xpos += dxpos;
}
else
xpos += dxpos << 3;
}
}
static void bitmap_4_0(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_4_draw(firstpix, iwidth, src, xpos, 0, 1);
}
static void bitmap_4_1(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_4_draw(firstpix, iwidth, src, xpos, 1, -1);
}
static void bitmap_4_2(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_4_draw(firstpix, iwidth, src, xpos, 2, 1);
}
static void bitmap_4_3(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_4_draw(firstpix, iwidth, src, xpos, 3, -1);
}
static void bitmap_4_4(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_4_draw(firstpix, iwidth, src, xpos, 4, 1);
}
static void bitmap_4_5(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_4_draw(firstpix, iwidth, src, xpos, 5, -1);
}
static void bitmap_4_6(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_4_draw(firstpix, iwidth, src, xpos, 6, 1);
}
static void bitmap_4_7(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_4_draw(firstpix, iwidth, src, xpos, 7, -1);
}
static void (*const bitmap4[8])(INT32, INT32, UINT32 *, INT32) =
{
bitmap_4_0,
bitmap_4_1,
bitmap_4_2,
bitmap_4_3,
bitmap_4_4,
bitmap_4_5,
bitmap_4_6,
bitmap_4_7
};
/*************************************
*
* 8bpp bitmap renderers
*
*************************************/
INLINE void bitmap_8_draw(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos, UINT8 flags, INT32 dxpos)
{
if (firstpix & 3)
{
UINT32 pixsrc = src[firstpix >> 2];
while (firstpix & 3)
{
UINT8 pix = pixsrc >> ((~firstpix & 3) << 3);
if ((!(flags & 4) || pix) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = clutbase[BYTE_XOR_BE(pix)];
else
BLEND(scanline[xpos], clutbase[BYTE_XOR_BE(pix)]);
}
xpos += dxpos;
firstpix++;
}
}
firstpix >>= 2;
iwidth >>= 2;
iwidth -= firstpix;
while (iwidth-- > 0)
{
UINT32 pix = src[firstpix++];
if (!(flags & 4) || pix)
{
if ((!(flags & 4) || (pix & 0xff000000)) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = clutbase[BYTE_XOR_BE(pix >> 24)];
else
BLEND(scanline[xpos], clutbase[BYTE_XOR_BE(pix >> 24)]);
}
xpos += dxpos;
if ((!(flags & 4) || (pix & 0x00ff0000)) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = clutbase[BYTE_XOR_BE((pix >> 16) & 0xff)];
else
BLEND(scanline[xpos], clutbase[BYTE_XOR_BE((pix >> 16) & 0xff)]);
}
xpos += dxpos;
if ((!(flags & 4) || (pix & 0x0000ff00)) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = clutbase[BYTE_XOR_BE((pix >> 8) & 0xff)];
else
BLEND(scanline[xpos], clutbase[BYTE_XOR_BE((pix >> 8) & 0xff)]);
}
xpos += dxpos;
if ((!(flags & 4) || (pix & 0x000000ff)) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = clutbase[BYTE_XOR_BE(pix & 0xff)];
else
BLEND(scanline[xpos], clutbase[BYTE_XOR_BE(pix & 0xff)]);
}
xpos += dxpos;
}
else
xpos += dxpos << 2;
}
}
static void bitmap_8_0(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_8_draw(firstpix, iwidth, src, xpos, 0, 1);
}
static void bitmap_8_1(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_8_draw(firstpix, iwidth, src, xpos, 1, -1);
}
static void bitmap_8_2(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_8_draw(firstpix, iwidth, src, xpos, 2, 1);
}
static void bitmap_8_3(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_8_draw(firstpix, iwidth, src, xpos, 3, -1);
}
static void bitmap_8_4(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_8_draw(firstpix, iwidth, src, xpos, 4, 1);
}
static void bitmap_8_5(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_8_draw(firstpix, iwidth, src, xpos, 5, -1);
}
static void bitmap_8_6(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_8_draw(firstpix, iwidth, src, xpos, 6, 1);
}
static void bitmap_8_7(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_8_draw(firstpix, iwidth, src, xpos, 7, -1);
}
static void (*const bitmap8[8])(INT32, INT32, UINT32 *, INT32) =
{
bitmap_8_0,
bitmap_8_1,
bitmap_8_2,
bitmap_8_3,
bitmap_8_4,
bitmap_8_5,
bitmap_8_6,
bitmap_8_7
};
/*************************************
*
* 16bpp bitmap renderers
*
*************************************/
INLINE void bitmap_16_draw(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos, UINT8 flags, INT32 dxpos)
{
if (firstpix & 1)
{
UINT16 pix = src[firstpix >> 1];
if ((!(flags & 4) || pix) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = pix;
else
BLEND(scanline[xpos], pix);
}
xpos += dxpos;
}
firstpix >>= 1;
iwidth >>= 1;
iwidth -= firstpix;
while (iwidth-- > 0)
{
UINT32 pix = src[firstpix++];
if (!(flags & 4) || pix)
{
if ((!(flags & 4) || (pix >> 16)) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = pix >> 16;
else
BLEND(scanline[xpos], pix >> 16);
}
xpos += dxpos;
if ((!(flags & 4) || (pix & 0xffff)) && (UINT32)xpos < 760)
{
if (!(flags & 2))
scanline[xpos] = pix;
else
BLEND(scanline[xpos], pix);
}
xpos += dxpos;
}
else
xpos += dxpos << 1;
}
}
static void bitmap_16_0(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_16_draw(firstpix, iwidth, src, xpos, 0, 1);
}
static void bitmap_16_1(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_16_draw(firstpix, iwidth, src, xpos, 1, -1);
}
static void bitmap_16_2(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_16_draw(firstpix, iwidth, src, xpos, 2, 1);
}
static void bitmap_16_3(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_16_draw(firstpix, iwidth, src, xpos, 3, -1);
}
static void bitmap_16_4(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_16_draw(firstpix, iwidth, src, xpos, 4, 1);
}
static void bitmap_16_5(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_16_draw(firstpix, iwidth, src, xpos, 5, -1);
}
static void bitmap_16_6(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_16_draw(firstpix, iwidth, src, xpos, 6, 1);
}
static void bitmap_16_7(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_16_draw(firstpix, iwidth, src, xpos, 7, -1);
}
static void (*const bitmap16[8])(INT32, INT32, UINT32 *, INT32) =
{
bitmap_16_0,
bitmap_16_1,
bitmap_16_2,
bitmap_16_3,
bitmap_16_4,
bitmap_16_5,
bitmap_16_6,
bitmap_16_7
};
/*************************************
*
* 32bpp bitmap renderers - needs to be verified
*
*************************************/
INLINE void bitmap_32_draw(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos, UINT8 flags, INT32 dxpos)
{
iwidth -= firstpix;
while (iwidth-- > 0)
{
UINT32 pix = src[firstpix++];
if (xpos < 760)
{
scanline[xpos++] = (pix&0xffff0000)>>16;
scanline[xpos++] = pix&0xffff;
}
}
}
static void bitmap_32_0(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_32_draw(firstpix, iwidth, src, xpos, 0, 1);
}
static void bitmap_32_1(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_32_draw(firstpix, iwidth, src, xpos, 1, -1);
}
static void bitmap_32_2(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_32_draw(firstpix, iwidth, src, xpos, 2, 1);
}
static void bitmap_32_3(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_32_draw(firstpix, iwidth, src, xpos, 3, -1);
}
static void bitmap_32_4(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_32_draw(firstpix, iwidth, src, xpos, 4, 1);
}
static void bitmap_32_5(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_32_draw(firstpix, iwidth, src, xpos, 5, -1);
}
static void bitmap_32_6(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_32_draw(firstpix, iwidth, src, xpos, 6, 1);
}
static void bitmap_32_7(INT32 firstpix, INT32 iwidth, UINT32 *src, INT32 xpos)
{
bitmap_32_draw(firstpix, iwidth, src, xpos, 7, -1);
}
static void (*const bitmap32[8])(INT32, INT32, UINT32 *, INT32) =
{
bitmap_32_0,
bitmap_32_1,
bitmap_32_2,
bitmap_32_3,
bitmap_32_4,
bitmap_32_5,
bitmap_32_6,
bitmap_32_7
};
INLINE UINT8 lookup_pixel(const UINT32 *src, int i, int pitch, int depth)
{
int ppl = 32 / depth;
UINT32 data = src[((i & ppl) / ppl) + ((i / (ppl<<1)) * (pitch<<1))];
UINT8 pix = (data >> ((~i & (ppl-1)) * depth)) & ((1 << depth) - 1);
return pix;
}
/*************************************
*
* Standard bitmap processor
*
*************************************/
static UINT32 *process_bitmap(running_machine &machine, UINT32 *objdata, int vc, int logit)
{
/* extract minimal data */
UINT32 upper = objdata[0];
UINT32 lower = objdata[1];
UINT32 ypos = (lower >> 3) & 0x7ff;
UINT32 height = (lower >> 14) & 0x3ff;
UINT32 link = (lower >> 24) | ((upper & 0x7ff) << 8);
UINT32 data = (upper >> 11);
UINT32 *src = (UINT32 *)get_jaguar_memory(machine, data << 3);
if (logit)
{
/* second phrase */
UINT32 upper2 = objdata[2];
UINT32 lower2 = objdata[3];
/* extract data */
INT32 xpos = (INT32)(lower2 << 20) >> 20;
UINT8 depth = 1 << ((lower2 >> 12) & 7);
UINT8 pitch = (lower2 >> 15) & 7;
UINT32 dwidth = (lower2 >> 18) & 0x3ff;
INT32 iwidth = (lower2 >> 28) | ((upper2 & 0x3f) << 4);
UINT8 _index = (upper2 >> 6) & 0x3f;
UINT8 flags = (upper2 >> 13) & 0x0f;
UINT8 firstpix = (upper2 >> 17) & 0x3f;
logerror(" ypos=%X height=%X link=%06X data=%06X\n", ypos, height, link << 3, data << 3);
logerror(" xpos=%X depth=%X pitch=%X dwidth=%X iwidth=%X index=%X flags=%X firstpix=%X\n", xpos, depth, pitch, dwidth, iwidth, _index, flags, firstpix);
}
/* only render if valid */
if (vc >= ypos && height > 0 && src)
{
/* second phrase */
UINT32 upper2 = objdata[2];
UINT32 lower2 = objdata[3];
/* extract data */
INT32 xpos = (INT32)(lower2 << 20) >> 20;
UINT8 depthlog = (lower2 >> 12) & 7;
UINT8 pitch = (lower2 >> 15) & 7;
UINT32 dwidth = (lower2 >> 18) & 0x3ff;
UINT32 iwidth = ((lower2 >> 28) | ((upper2 & 0x3f) << 4)) << (6 - depthlog);
UINT8 _index = (upper2 >> 5) & 0xfe;
UINT8 flags = (upper2 >> 13) & 0x07;
UINT8 firstpix = ((upper2 >> 17) & 0x3f) >> depthlog;
int i, dxpos = (flags & 1) ? -1 : 1;
/* preadjust for firstpix */
xpos += firstpix * dxpos;
/* switch off the depth */
switch (depthlog)
{
/* 1bpp case */
case 0:
{
UINT16 *clut = (UINT16 *)jaguar_gpu_clut + _index;
/* non-blending */
if (!(flags & 2))
{
for (i = firstpix; i < iwidth; i++)
{
UINT8 pix = lookup_pixel(src, i, pitch, 1);
if (xpos >= 0 && xpos < 760 && (pix || !(flags & 4)))
scanline[xpos] = clut[BYTE_XOR_BE(pix)];
xpos += dxpos;
}
}
/* blending */
else
{
for (i = firstpix; i < iwidth; i++)
{
UINT8 pix = lookup_pixel(src, i, pitch, 1);
if (xpos >= 0 && xpos < 760 && (pix || !(flags & 4)))
BLEND(scanline[xpos], clut[BYTE_XOR_BE(pix)]);
xpos += dxpos;
}
}
break;
}
/* 2bpp case */
case 1:
{
UINT16 *clut = (UINT16 *)jaguar_gpu_clut + (_index & 0xfc);
/* non-blending */
if (!(flags & 2))
{
for (i = firstpix; i < iwidth; i++)
{
UINT8 pix = lookup_pixel(src, i, pitch, 2);
if (xpos >= 0 && xpos < 760 && (pix || !(flags & 4)))
scanline[xpos] = clut[BYTE_XOR_BE(pix)];
xpos += dxpos;
}
}
/* blending */
else
{
for (i = firstpix; i < iwidth; i++)
{
UINT8 pix = lookup_pixel(src, i, pitch, 2);
if (xpos >= 0 && xpos < 760 && (pix || !(flags & 4)))
BLEND(scanline[xpos], clut[BYTE_XOR_BE(pix)]);
xpos += dxpos;
}
}
break;
}
/* 4bpp case */
case 2:
/* only handle pitch=1 for now */
if (pitch != 1)
logerror("Unhandled pitch = %d\n", pitch);
clutbase = (UINT16 *)jaguar_gpu_clut + (_index & 0xf8);
(*bitmap4[flags])(firstpix, iwidth, src, xpos);
break;
/* 8bpp case */
case 3:
/* only handle pitch=1 for now */
if (pitch != 1)
logerror("Unhandled pitch = %d\n", pitch);
clutbase = (UINT16 *)jaguar_gpu_clut;
(*bitmap8[flags])(firstpix, iwidth, src, xpos);
break;
/* 16bpp case */
case 4:
/* only handle pitch=1 for now */
if (pitch != 1)
logerror("Unhandled pitch = %d\n", pitch);
(*bitmap16[flags])(firstpix, iwidth, src, xpos);
break;
/* 32bpp case */
case 5:
/* only handle pitch=1 for now */
if (pitch != 1)
logerror("Unhandled pitch = %d\n", pitch);
(*bitmap32[flags])(firstpix, iwidth, src, xpos);
break;
default:
fprintf(stderr, "Unhandled bitmap source depth = %d\n", depthlog);
break;
}
/* decrement the height and add to the source data offset */
objdata[0] = upper + (dwidth << 11);
objdata[1] = lower - (1 << 14);
}
return (UINT32 *)get_jaguar_memory(machine, link << 3);
}
/*************************************
*
* Scaled bitmap object processor
*
*************************************/
static UINT32 *process_scaled_bitmap(running_machine &machine, UINT32 *objdata, int vc, int logit)
{
/* extract data */
UINT32 upper = objdata[0];
UINT32 lower = objdata[1];
UINT32 ypos = (lower >> 3) & 0x7ff;
UINT32 height = (lower >> 14) & 0x3ff;
UINT32 link = (lower >> 24) | ((upper & 0x7ff) << 8);
UINT32 data = (upper >> 11);
UINT32 *src = (UINT32 *)get_jaguar_memory(machine, data << 3);
/* third phrase */
UINT32 lower3 = objdata[5];
INT32 remainder = (lower3 >> 16) & 0xff;
if (logit)
{
/* second phrase */
UINT32 upper2 = objdata[2];
UINT32 lower2 = objdata[3];
/* extract data */
INT32 xpos = (INT32)(lower2 << 20) >> 20;
UINT8 depth = 1 << ((lower2 >> 12) & 7);
UINT8 pitch = (lower2 >> 15) & 7;
UINT32 dwidth = (lower2 >> 18) & 0x3ff;
INT32 iwidth = (lower2 >> 28) | ((upper2 & 0x3f) << 4);
UINT8 _index = (upper2 >> 6) & 0x3f;
UINT8 flags = (upper2 >> 13) & 0x0f;
UINT8 firstpix = (upper2 >> 17) & 0x3f;
INT32 hscale = lower3 & 0xff;
INT32 vscale = (lower3 >> 8) & 0xff;
logerror(" ypos=%X height=%X link=%06X data=%06X\n", ypos, height, link << 3, data << 3);
logerror(" xpos=%X depth=%X pitch=%X dwidth=%X iwidth=%X index=%X flags=%X firstpix=%X\n", xpos, depth, pitch, dwidth, iwidth, _index, flags, firstpix);
logerror(" hscale=%X vscale=%X remainder=%X\n", hscale, vscale, remainder);
}
/* only render if valid */
if (vc >= ypos && (height > 0 || remainder > 0) && src)
{
/* second phrase */
UINT32 upper2 = objdata[2];
UINT32 lower2 = objdata[3];
/* extract data */
INT32 xpos = (INT32)(lower2 << 20) >> 20;
UINT8 depthlog = (lower2 >> 12) & 7;
UINT8 pitch = (lower2 >> 15) & 7;
UINT32 dwidth = (lower2 >> 18) & 0x3ff;
INT32 iwidth = ((lower2 >> 28) | ((upper2 & 0x3f) << 4)) << (6 - depthlog);
UINT8 _index = (upper2 >> 5) & 0xfe;
UINT8 flags = (upper2 >> 13) & 0x07;
UINT8 firstpix = ((upper2 >> 17) & 0x3f) >> depthlog;
INT32 hscale = lower3 & 0xff;
INT32 vscale = (lower3 >> 8) & 0xff;
INT32 xleft = hscale;
int dxpos = (flags & 1) ? -1 : 1;
int xpix = firstpix, yinc;
/* only handle pitch=1 (sequential data) for now */
if (pitch != 1)
logerror("Unhandled pitch = %d\n", pitch);
if (flags & 2)
{
mame_printf_debug("Unhandled blend mode in scaled bitmap case\n");
logerror("Unhandled blend mode in scaled bitmap case\n");
}
/* preadjust for firstpix */
xpos += firstpix * dxpos;
/* ignore hscale = 0 */
if (hscale != 0)
{
/* switch off the depth */
switch (depthlog)
{
case 0:
{
UINT16 *clut = (UINT16 *)jaguar_gpu_clut + _index;
/* render in phrases */
while (xpix < iwidth)
{
UINT16 pix = (src[xpix >> 5] >> (~xpix & 31)) & 0x01;
while (xleft > 0)
{
if (xpos >= 0 && xpos < 760 && (pix || !(flags & 4)))
scanline[xpos] = clut[BYTE_XOR_BE(pix)];
xpos += dxpos;
xleft -= 0x20;
}
while (xleft <= 0)
xleft += hscale, xpix++;
}
break;
}
case 1:
{
UINT16 *clut = (UINT16 *)jaguar_gpu_clut + (_index & 0xfc);
/* render in phrases */
while (xpix < iwidth)
{
UINT16 pix = (src[xpix >> 4] >> ((~xpix & 15) << 1)) & 0x03;
while (xleft > 0)
{
if (xpos >= 0 && xpos < 760 && (pix || !(flags & 4)))
scanline[xpos] = clut[BYTE_XOR_BE(pix)];
xpos += dxpos;
xleft -= 0x20;
}
while (xleft <= 0)
xleft += hscale, xpix++;
}
break;
}
case 2:
{
UINT16 *clut = (UINT16 *)jaguar_gpu_clut + (_index & 0xf8);
/* render in phrases */
while (xpix < iwidth)
{
UINT16 pix = (src[xpix >> 3] >> ((~xpix & 7) << 2)) & 0x0f;
while (xleft > 0)
{
if (xpos >= 0 && xpos < 760 && (pix || !(flags & 4)))
scanline[xpos] = clut[BYTE_XOR_BE(pix)];
xpos += dxpos;
xleft -= 0x20;
}
while (xleft <= 0)
xleft += hscale, xpix++;
}
break;
}
case 3:
{
UINT16 *clut = (UINT16 *)jaguar_gpu_clut;
/* render in phrases */
while (xpix < iwidth)
{
UINT16 pix = (src[xpix >> 2] >> ((~xpix & 3) << 3)) & 0xff;
while (xleft > 0)
{
if (xpos >= 0 && xpos < 760 && (pix || !(flags & 4)))
scanline[xpos] = clut[BYTE_XOR_BE(pix)];
xpos += dxpos;
xleft -= 0x20;
}
while (xleft <= 0)
xleft += hscale, xpix++;
}
break;
}
case 4:
while (xpix < iwidth)
{
UINT16 pix = src[xpix >> 1] >> ((~xpix & 1) << 4);
while (xleft > 0)
{
if (xpos >= 0 && xpos < 760 && (pix || !(flags & 4)))
scanline[xpos] = pix;
xpos += dxpos;
xleft -= 0x20;
}
while (xleft <= 0)
xleft += hscale, xpix++;
}
break;
default:
fprintf(stderr, "Unhandled scaled bitmap source depth = %d\n", depthlog);
break;
}
}
/* handle Y scale */
remainder -= 0x20;
yinc = 0;
while (remainder <= 0 && vscale != 0)
remainder += vscale, yinc++;
if (yinc > height)
yinc = height, remainder = 0;
/* decrement the height and add to the source data offset */
objdata[0] = upper + yinc * (dwidth << 11);
objdata[1] = lower - yinc * (1 << 14);
objdata[5] = (lower3 & ~0xff0000) | ((remainder & 0xff) << 16);
}
return (UINT32 *)get_jaguar_memory(machine, link << 3);
}
/*************************************
*
* Branch object processor
*
*************************************/
static UINT32 *process_branch(running_machine &machine, UINT32 *objdata, int vc, int logit)
{
UINT32 upper = objdata[0];
UINT32 lower = objdata[1];
UINT32 ypos = (lower >> 3) & 0x7ff;
UINT32 cc = (lower >> 14) & 7;
UINT32 link = (lower >> 24) | ((upper & 0x7ff) << 8);
int taken = 0;
#ifndef MESS
if ((ypos & 1) && ypos != 0x7ff)
fprintf(stderr, " branch cc=%d ypos=%X link=%06X - \n", cc, ypos, link << 3);
#endif
switch (cc)
{
/* 0: branch if ypos == vc or ypos == 0x7ff */
case 0:
if (logit) logerror(" branch if %X == vc or %X == 0x7ff to %06X\n", ypos, ypos, link << 3);
taken = (ypos == vc) || (ypos == 0x7ff);
break;
/* 1: branch if ypos > vc */
case 1:
if (logit) logerror(" branch if %X > vc to %06X\n", ypos, link << 3);
taken = (ypos > vc);
break;
/* 2: branch if ypos < vc */
case 2:
if (logit) logerror(" branch if %X < vc to %06X\n", ypos, link << 3);
taken = (ypos < vc);
break;
/* 3: branch if object processor flag is set */
case 3:
if (logit) logerror(" branch if object flag set to %06X\n", link << 3);
taken = gpu_regs[OBF] & 1;
break;
/* 4: branch on second half of display line */
case 4:
if (logit) logerror(" branch if second half of line to %06X\n", link << 3);
taken = (vc & 1);
break;
default:
fprintf(stderr, "Invalid branch!\n");
link = 0; taken = 1;
break;
}
/* handle the branch */
return taken ? (UINT32 *)get_jaguar_memory(machine, link << 3) : (objdata + 2);
}
/*************************************
*
* Process object list
*
*************************************/
static void process_object_list(running_machine &machine, int vc, UINT16 *_scanline)
{
int done = 0, count = 0;
UINT32 *objdata;
int logit;
int x;
/* erase the scanline first */
scanline = _scanline;
for (x = 0; x < 760; x++)
scanline[x] = gpu_regs[BG];
logit = LOG_OBJECTS;
/* fetch the object pointer */
objdata = (UINT32 *)get_jaguar_memory(machine, (gpu_regs[OLP_H] << 16) | gpu_regs[OLP_L]);
while (!done && objdata && count++ < 100)
{
/* the low 3 bits determine the command */
switch (objdata[1] & 7)
{
/* bitmap object */
case 0:
if (logit)
logerror("bitmap = %08X-%08X %08X-%08X\n", objdata[0], objdata[1], objdata[2], objdata[3]);
objdata = process_bitmap(machine, objdata, vc, logit);
break;
/* scaled bitmap object */
case 1:
if (logit)
logerror("scaled = %08X-%08X %08X-%08X %08X-%08X\n", objdata[0], objdata[1], objdata[2], objdata[3], objdata[4], objdata[5]);
objdata = process_scaled_bitmap(machine, objdata, vc, logit);
break;
/* GPU interrupt */
case 2:
gpu_regs[OB_HH]=(objdata[1]&0xffff0000)>>16;
gpu_regs[OB_HL]=objdata[1]&0xffff;
gpu_regs[OB_LH]=(objdata[0]&0xffff0000)>>16;
gpu_regs[OB_LL]=objdata[0]&0xffff;
cpu_irq_state |= 2;
update_cpu_irq(machine);
done=1;
break;
/* branch */
case 3:
if (logit)
logerror("branch = %08X-%08X\n", objdata[0], objdata[1]);
objdata = process_branch(machine, objdata, vc, logit);
break;
/* stop */
case 4:
{
int interrupt = (objdata[1] >> 3) & 1;
done = 1;
if (logit)
logerror("stop = %08X-%08X\n", objdata[0], objdata[1]);
if (interrupt)
{
#ifndef MESS
fprintf(stderr, "stop int=%d\n", interrupt);
#endif
cpu_irq_state |= 4;
update_cpu_irq(machine);
}
break;
}
default:
fprintf(stderr, "%08X %08X\n", objdata[0], objdata[1]);
done = 1;
break;
}
}
}