/***************************************************************************
HD63484 ACRTC
Advanced CRT Controller.
This chip is used in:
- shanghai.c
- adp.c
- sigmab52.c
ACRTC memory map:
00000-3ffff = RAM
40000-7ffff = ROM handled with a hack in the drivers
80000-bffff = unused
c0000-fffff = unused
***************************************************************************/
#include "emu.h"
#include "video/hd63484.h"
#define LOG_COMMANDS 0
/* the on-chip FIFO is 16 bytes long, but we use a larger one to simplify */
/* decoding of long commands. Commands can be up to 64KB long... but Shanghai */
/* doesn't reach that length. */
#define FIFO_LENGTH 256
typedef struct _hd63484_state hd63484_state;
struct _hd63484_state
{
UINT16 * ram;
UINT16 reg[256/2];
int fifo_counter;
UINT16 fifo[FIFO_LENGTH];
UINT16 readfifo;
UINT16 pattern[16];
int org, org_dpd, rwp;
UINT16 cl0, cl1, ccmp, edg, mask, ppy, pzcy, ppx, pzcx, psy, psx, pey, pzy, pex, pzx, xmin, ymin, xmax, ymax, rwp_dn;
INT16 cpx, cpy;
int regno;
int skattva_hack;
};
/*****************************************************************************
INLINE FUNCTIONS
*****************************************************************************/
INLINE hd63484_state *get_safe_token( device_t *device )
{
assert(device != NULL);
assert(device->type() == HD63484);
return (hd63484_state *)downcast<legacy_device_base *>(device)->token();
}
INLINE const hd63484_interface *get_interface( device_t *device )
{
assert(device != NULL);
assert(device->type() == HD63484);
return (const hd63484_interface *) device->static_config();
}
/*****************************************************************************
IMPLEMENTATION
*****************************************************************************/
static int get_pixel(device_t *device, int x, int y);
static const int instruction_length[64] =
{
0, 3, 2, 1, /* 0x */
0, 0,-1, 2, /* 1x */
0, 3, 3, 3, /* 2x */
0, 0, 0, 0, /* 3x */
0, 1, 2, 2, /* 4x */
0, 0, 4, 4, /* 5x */
5, 5, 5, 5, /* 6x */
5, 5, 5, 5, /* 7x */
3, 3, 3, 3, /* 8x */
3, 3,-2,-2, /* 9x */
-2,-2, 2, 4, /* Ax */
5, 5, 7, 7, /* Bx */
3, 3, 1, 1, /* Cx */
2, 2, 2, 2, /* Dx */
5, 5, 5, 5, /* Ex */
5, 5, 5, 5 /* Fx */
};
static const char *const instruction_name[64] =
{
"undef","ORG ","WPR ","RPR ", /* 0x */
"undef","undef","WPTN ","RPTN ", /* 1x */
"undef","DRD ","DWT ","DMOD ", /* 2x */
"undef","undef","undef","undef", /* 3x */
"undef","RD ","WT ","MOD ", /* 4x */
"undef","undef","CLR ","SCLR ", /* 5x */
"CPY ","CPY ","CPY ","CPY ", /* 6x */
"SCPY ","SCPY ","SCPY ","SCPY ", /* 7x */
"AMOVE","RMOVE","ALINE","RLINE", /* 8x */
"ARCT ","RRCT ","APLL ","RPLL ", /* 9x */
"APLG ","RPLG ","CRCL ","ELPS ", /* Ax */
"AARC ","RARC ","AEARC","REARC", /* Bx */
"AFRCT","RFRCT","PAINT","DOT ", /* Cx */
"PTN ","PTN ","PTN ","PTN ", /* Dx */
"AGCPY","AGCPY","AGCPY","AGCPY", /* Ex */
"RGCPY","RGCPY","RGCPY","RGCPY" /* Fx */
};
static void doclr16( device_t *device, int opcode, UINT16 fill, int *dst, INT16 _ax, INT16 _ay )
{
hd63484_state *hd63484 = get_safe_token(device);
INT16 ax,ay;
ax = _ax;
ay = _ay;
for (;;)
{
for (;;)
{
switch (opcode & 0x0003)
{
case 0:
hd63484->ram[*dst] = fill;
break;
case 1:
hd63484->ram[*dst] |= fill;
break;
case 2:
hd63484->ram[*dst] &= fill;
break;
case 3:
hd63484->ram[*dst] ^= fill;
break;
}
if (ax == 0)
break;
else if (ax > 0)
{
*dst = (*dst + 1) & (HD63484_RAM_SIZE - 1);
ax--;
}
else
{
*dst = (*dst - 1) & (HD63484_RAM_SIZE - 1);
ax++;
}
}
ax = _ax;
if (_ay < 0)
{
*dst = (*dst + (hd63484->reg[0xca/2] & 0x0fff) - ax) & (HD63484_RAM_SIZE - 1);
if (ay == 0)
break;
ay++;
}
else
{
*dst = (*dst - (hd63484->reg[0xca/2] & 0x0fff) - ax) & (HD63484_RAM_SIZE - 1);
if (ay == 0)
break;
ay--;
}
}
}
static void docpy16( device_t *device, int opcode, int src, int *dst, INT16 _ax, INT16 _ay )
{
hd63484_state *hd63484 = get_safe_token(device);
int dstep1,dstep2;
int ax = _ax;
int ay = _ay;
switch (opcode & 0x0700)
{
default:
case 0x0000: dstep1 = 1; dstep2 = -1 * (hd63484->reg[0xca/2] & 0x0fff) - ax * dstep1; break;
case 0x0100: dstep1 = 1; dstep2 = (hd63484->reg[0xca/2] & 0x0fff) - ax * dstep1; break;
case 0x0200: dstep1 = -1; dstep2 = -1 * (hd63484->reg[0xca/2] & 0x0fff) + ax * dstep1; break;
case 0x0300: dstep1 = -1; dstep2 = (hd63484->reg[0xca/2] & 0x0fff) + ax * dstep1; break;
case 0x0400: dstep1 = -1 * (hd63484->reg[0xca/2] & 0x0fff); dstep2 = 1 - ay * dstep1; break;
case 0x0500: dstep1 = (hd63484->reg[0xca/2] & 0x0fff); dstep2 = 1 - ay * dstep1; break;
case 0x0600: dstep1 = -1 * (hd63484->reg[0xca/2] & 0x0fff); dstep2 = -1 + ay * dstep1; break;
case 0x0700: dstep1 = (hd63484->reg[0xca/2] & 0x0fff); dstep2 = -1 + ay * dstep1; break;
}
for (;;)
{
for (;;)
{
switch (opcode & 0x0007)
{
case 0:
hd63484->ram[*dst] = hd63484->ram[src];
break;
case 1:
hd63484->ram[*dst] |= hd63484->ram[src];
break;
case 2:
hd63484->ram[*dst] &= hd63484->ram[src];
break;
case 3:
hd63484->ram[*dst] ^= hd63484->ram[src];
break;
case 4:
if (hd63484->ram[*dst] == (hd63484->ccmp & 0xff))
hd63484->ram[*dst] = hd63484->ram[src];
break;
case 5:
if (hd63484->ram[*dst] != (hd63484->ccmp & 0xff))
hd63484->ram[*dst] = hd63484->ram[src];
break;
case 6:
if (hd63484->ram[*dst] < hd63484->ram[src])
hd63484->ram[*dst] = hd63484->ram[src];
break;
case 7:
if (hd63484->ram[*dst] > hd63484->ram[src])
hd63484->ram[*dst] = hd63484->ram[src];
break;
}
if (opcode & 0x0800)
{
if (ay == 0) break;
if (_ay > 0)
{
src = (src - (hd63484->reg[0xca/2] & 0x0fff)) & (HD63484_RAM_SIZE - 1);
*dst = (*dst + dstep1) & (HD63484_RAM_SIZE - 1);
ay--;
}
else
{
src = (src + (hd63484->reg[0xca/2] & 0x0fff)) & (HD63484_RAM_SIZE - 1);
*dst = (*dst + dstep1) & (HD63484_RAM_SIZE - 1);
ay++;
}
}
else
{
if (ax == 0) break;
else if (ax > 0)
{
src = (src + 1) & (HD63484_RAM_SIZE - 1);
*dst = (*dst + dstep1) & (HD63484_RAM_SIZE - 1);
ax--;
}
else
{
src = (src - 1) & (HD63484_RAM_SIZE - 1);
*dst = (*dst + dstep1) & (HD63484_RAM_SIZE - 1);
ax++;
}
}
}
if (opcode & 0x0800)
{
ay = _ay;
if (_ax < 0)
{
src = (src - 1 + ay * (hd63484->reg[0xca/2] & 0x0fff)) & (HD63484_RAM_SIZE - 1);
*dst = (*dst + dstep2) & (HD63484_RAM_SIZE - 1);
if (ax == 0) break;
ax++;
}
else
{
src = (src + 1 - ay * (hd63484->reg[0xca/2] & 0x0fff)) & (HD63484_RAM_SIZE - 1);
*dst = (*dst + dstep2) & (HD63484_RAM_SIZE - 1);
if (ax == 0) break;
ax--;
}
}
else
{
ax = _ax;
if (_ay < 0)
{
src = (src + (hd63484->reg[0xca/2] & 0x0fff) - ax) & (HD63484_RAM_SIZE - 1);
*dst = (*dst + dstep2) & (HD63484_RAM_SIZE - 1);
if (ay == 0) break;
ay++;
}
else
{
src = (src - (hd63484->reg[0xca/2] & 0x0fff) - ax) & (HD63484_RAM_SIZE - 1);
*dst = (*dst + dstep2) & (HD63484_RAM_SIZE - 1);
if (ay == 0) break;
ay--;
}
}
}
}
static int org_first_pixel( device_t *device, int _org_dpd )
{
hd63484_state *hd63484 = get_safe_token(device);
int gbm = (hd63484->reg[0x02/2] & 0x700) >> 8;
switch (gbm)
{
case 0:
return (_org_dpd & 0x0f);
case 1:
return (_org_dpd & 0x0e) >> 1;
case 2:
return (_org_dpd & 0x0c) >> 2;
case 3:
return (_org_dpd & 0x08) >> 3;
case 4:
return 0;
default:
logerror ("Graphic bit mode not supported\n");
return 0;
}
}
static void dot( device_t *device, int x, int y, int opm, UINT16 color )
{
hd63484_state *hd63484 = get_safe_token(device);
int dst, x_int, x_mod, bpp;
UINT16 color_shifted, bitmask, bitmask_shifted;
x += org_first_pixel(device, hd63484->org_dpd);
switch ((hd63484->reg[0x02/2] & 0x700) >> 8)
{
case 0:
bpp = 1;
bitmask = 0x0001;
break;
case 1:
bpp = 2;
bitmask = 0x0003;
break;
case 2:
bpp = 4;
bitmask = 0x000f;
break;
case 3:
bpp = 8;
bitmask = 0x00ff;
break;
case 4:
bpp = 16;
bitmask = 0xffff;
break;
default:
bpp = 0;
bitmask = 0x0000;
logerror ("Graphic bit mode not supported\n");
}
// bpp = 4; // for skattva
// bitmask = 0x000f; // for skattva
if (x >= 0)
{
x_int = x / (16 / bpp);
x_mod = x % (16 / bpp);
}
else
{
x_int = x / (16 / bpp);
x_mod = -1 * (x % (16 / bpp));
if (x_mod) {
x_int--;
x_mod = (16 / bpp) - x_mod;
}
}
color &= bitmask;
bitmask_shifted = bitmask << (x_mod * bpp);
color_shifted = color << (x_mod * bpp);
dst = (hd63484->org + x_int - y * (hd63484->reg[0xca/2] & 0x0fff)) & (HD63484_RAM_SIZE - 1);
switch (opm)
{
case 0:
hd63484->ram[dst] = (hd63484->ram[dst] & ~bitmask_shifted) | color_shifted;
break;
case 1:
hd63484->ram[dst] = hd63484->ram[dst] | color_shifted;
break;
case 2:
hd63484->ram[dst] = hd63484->ram[dst] & ((hd63484->ram[dst] & ~bitmask_shifted) | color_shifted);
break;
case 3:
hd63484->ram[dst] = hd63484->ram[dst] ^ color_shifted;
break;
case 4:
if (get_pixel(device, x, y) == (hd63484->ccmp & bitmask))
hd63484->ram[dst] = (hd63484->ram[dst] & ~bitmask_shifted) | color_shifted;
break;
case 5:
if (get_pixel(device, x, y) != (hd63484->ccmp & bitmask))
hd63484->ram[dst] = (hd63484->ram[dst] & ~bitmask_shifted) | color_shifted;
break;
case 6:
if (get_pixel(device, x, y) < (hd63484->cl0 & bitmask))
hd63484->ram[dst] = (hd63484->ram[dst] & ~bitmask_shifted) | color_shifted;
break;
case 7:
if (get_pixel(device, x, y) > (hd63484->cl0 & bitmask))
hd63484->ram[dst] = (hd63484->ram[dst] & ~bitmask_shifted) | color_shifted;
break;
}
}
static int get_pixel( device_t *device, int x, int y )
{
hd63484_state *hd63484 = get_safe_token(device);
int dst, x_int, x_mod, bpp;
UINT16 bitmask, bitmask_shifted;
switch ((hd63484->reg[0x02/2] & 0x700) >> 8)
{
case 0:
bpp = 1;
bitmask = 0x0001;
break;
case 1:
bpp = 2;
bitmask = 0x0003;
break;
case 2:
bpp = 4;
bitmask = 0x000f;
break;
case 3:
bpp = 8;
bitmask = 0x00ff;
break;
case 4:
bpp = 16;
bitmask = 0xffff;
break;
default:
bpp = 0;
bitmask = 0x0000;
logerror ("Graphic bit mode not supported\n");
}
if (x >= 0)
{
x_int = x / (16 / bpp);
x_mod = x % (16 / bpp);
}
else
{
x_int = x / (16 / bpp);
x_mod = -1 * (x % (16 / bpp));
if (x_mod) {
x_int--;
x_mod = (16 / bpp) - x_mod;
}
}
bitmask_shifted = bitmask << (x_mod * bpp);
dst = (hd63484->org + x_int - y * (hd63484->reg[0xca/2] & 0x0fff)) & (HD63484_RAM_SIZE - 1);
return ((hd63484->ram[dst] & bitmask_shifted) >> (x_mod * bpp));
}
static int get_pixel_ptn( device_t *device, int x, int y )
{
hd63484_state *hd63484 = get_safe_token(device);
int dst, x_int, x_mod, bpp;
UINT16 bitmask, bitmask_shifted;
bpp = 1;
bitmask = 0x0001;
if (x >= 0)
{
x_int = x / (16 / bpp);
x_mod = x % (16 / bpp);
}
else
{
x_int = x / (16 / bpp);
x_mod = -1 * (x % (16 / bpp));
if (x_mod) {
x_int--;
x_mod = (16 / bpp) - x_mod;
}
}
bitmask_shifted = bitmask << (x_mod * bpp);
dst = (x_int + y * 1);
if ((hd63484->pattern[dst] & bitmask_shifted) >> (x_mod * bpp))
return 1;
else
return 0;
}
static void agcpy( device_t *device, int opcode, int src_x, int src_y, int dst_x, int dst_y, INT16 _ax, INT16 _ay )
{
int dst_step1_x,dst_step1_y,dst_step2_x,dst_step2_y;
int src_step1_x,src_step1_y,src_step2_x,src_step2_y;
int ax_neg,ay_neg;
int ax = _ax;
int ay = _ay;
int xxs = src_x;
int yys = src_y;
int xxd = dst_x;
int yyd = dst_y;
if (ax < 0)
ax_neg = -1;
else
ax_neg = 1;
if (ay < 0)
ay_neg = -1;
else
ay_neg = 1;
if (opcode & 0x0800)
switch (opcode & 0x0700)
{
default:
case 0x0000: dst_step1_x = 1; dst_step1_y = 0; dst_step2_x = -ay_neg*ay; dst_step2_y = 1; break;
case 0x0100: dst_step1_x = 1; dst_step1_y = 0; dst_step2_x = -ay_neg*ay; dst_step2_y = -1; break;
case 0x0200: dst_step1_x = -1; dst_step1_y = 0; dst_step2_x = ay_neg*ay; dst_step2_y = 1; break;
case 0x0300: dst_step1_x = -1; dst_step1_y = 0; dst_step2_x = ay_neg*ay; dst_step2_y = -1; break;
case 0x0400: dst_step1_x = 0; dst_step1_y = 1; dst_step2_x = 1; dst_step2_y = -ay_neg*ay; break;
case 0x0500: dst_step1_x = 0; dst_step1_y = -1; dst_step2_x = 1; dst_step2_y = ay_neg*ay; break;
case 0x0600: dst_step1_x = 0; dst_step1_y = 1; dst_step2_x = -1; dst_step2_y = -ay_neg*ay; break;
case 0x0700: dst_step1_x = 0; dst_step1_y = -1; dst_step2_x = -1; dst_step2_y = ay_neg*ay; break;
}
else
switch (opcode & 0x0700)
{
default:
case 0x0000: dst_step1_x = 1; dst_step1_y = 0; dst_step2_x = -ax_neg*ax; dst_step2_y = 1; break;
case 0x0100: dst_step1_x = 1; dst_step1_y = 0; dst_step2_x = -ax_neg*ax; dst_step2_y = -1; break;
case 0x0200: dst_step1_x = -1; dst_step1_y = 0; dst_step2_x = ax_neg*ax; dst_step2_y = 1; break;
case 0x0300: dst_step1_x = -1; dst_step1_y = 0; dst_step2_x = ax_neg*ax; dst_step2_y = -1; break;
case 0x0400: dst_step1_x = 0; dst_step1_y = 1; dst_step2_x = 1; dst_step2_y = ax_neg*ax; break;
case 0x0500: dst_step1_x = 0; dst_step1_y = -1; dst_step2_x = 1; dst_step2_y = -ax_neg*ax; break;
case 0x0600: dst_step1_x = 0; dst_step1_y = 1; dst_step2_x = -1; dst_step2_y = ax_neg*ax; break;
case 0x0700: dst_step1_x = 0; dst_step1_y = -1; dst_step2_x = -1; dst_step2_y = -ax_neg*ax; break;
}
if ((_ax >= 0) && (_ay >= 0) && ((opcode & 0x0800) == 0x0000))
{ src_step1_x = 1; src_step1_y = 0; src_step2_x = -ax; src_step2_y = 1; }
else if ((_ax >= 0) && (_ay < 0) && ((opcode & 0x0800) == 0x0000))
{ src_step1_x = 1; src_step1_y = 0; src_step2_x = -ax; src_step2_y = -1; }
else if ((_ax < 0) && (_ay >= 0) && ((opcode & 0x0800) == 0x0000))
{ src_step1_x = -1; src_step1_y = 0; src_step2_x = -ax; src_step2_y = 1; }
else if ((_ax < 0) && (_ay < 0) && ((opcode & 0x0800) == 0x0000))
{ src_step1_x = -1; src_step1_y = 0; src_step2_x = -ax; src_step2_y = -1; }
else if ((_ax >= 0) && (_ay >= 0) && ((opcode & 0x0800) == 0x0800))
{ src_step1_x = 0; src_step1_y = 1; src_step2_x = 1; src_step2_y = -ay; }
else if ((_ax >= 0) && (_ay < 0) && ((opcode & 0x0800) == 0x0800))
{ src_step1_x = 0; src_step1_y = -1; src_step2_x = 1; src_step2_y = -ay; }
else if ((_ax < 0) && (_ay >= 0) && ((opcode & 0x0800) == 0x0800))
{ src_step1_x = 0; src_step1_y = 1; src_step2_x = -1; src_step2_y = -ay; }
else // ((_ax < 0) && (_ay < 0) && ((opcode & 0x0800) == 0x0800))
{ src_step1_x = 0; src_step1_y = -1; src_step2_x = -1; src_step2_y = -ay; }
for (;;)
{
for (;;)
{
dot(device, xxd, yyd, opcode & 0x0007, get_pixel(device, xxs, yys));
if (opcode & 0x0800)
{
if (ay == 0) break;
if (_ay > 0)
{
xxs += src_step1_x;
yys += src_step1_y;
xxd += dst_step1_x;
yyd += dst_step1_y;
ay--;
}
else
{
xxs += src_step1_x;
yys += src_step1_y;
xxd += dst_step1_x;
yyd += dst_step1_y;
ay++;
}
}
else
{
if (ax == 0) break;
else if (ax > 0)
{
xxs += src_step1_x;
yys += src_step1_y;
xxd += dst_step1_x;
yyd += dst_step1_y;
ax--;
}
else
{
xxs += src_step1_x;
yys += src_step1_y;
xxd += dst_step1_x;
yyd += dst_step1_y;
ax++;
}
}
}
if (opcode & 0x0800)
{
ay = _ay;
if (_ax < 0)
{
xxs += src_step2_x;
yys += src_step2_y;
xxd += dst_step2_x;
yyd += dst_step2_y;
if (ax == 0) break;
ax++;
}
else
{
xxs += src_step2_x;
yys += src_step2_y;
xxd += dst_step2_x;
yyd += dst_step2_y;
if (ax == 0) break;
ax--;
}
}
else
{
ax = _ax;
if (_ay < 0)
{
xxs += src_step2_x;
yys += src_step2_y;
xxd += dst_step2_x;
yyd += dst_step2_y;
if (ay == 0) break;
ay++;
}
else
{
xxs += src_step2_x;
yys += src_step2_y;
xxd += dst_step2_x;
yyd += dst_step2_y;
if (ay == 0) break;
ay--;
}
}
}
}
static void ptn( device_t *device, int opcode, int src_x, int src_y, INT16 _ax, INT16 _ay )
{
hd63484_state *hd63484 = get_safe_token(device);
int dst_step1_x = 0,dst_step1_y = 0,dst_step2_x = 0,dst_step2_y = 0;
int src_step1_x,src_step1_y,src_step2_x,src_step2_y;
int ax = _ax;
int ay = _ay;
int ax_neg; //,ay_neg;
int xxs = src_x;
int yys = src_y;
int xxd = hd63484->cpx;
int yyd = hd63484->cpy;
int getpixel;
if (ax < 0)
ax_neg = -1;
else
ax_neg = 1;
/* if (ay < 0)
ay_neg = -1;
else
ay_neg = 1;*/
if (opcode & 0x0800)
switch (opcode & 0x0700)
{
default:
case 0x0000: logerror("PTN: not supported"); break;
case 0x0100: logerror("PTN: not supported"); break;
case 0x0200: logerror("PTN: not supported"); break;
case 0x0300: logerror("PTN: not supported"); break;
case 0x0400: logerror("PTN: not supported"); break;
case 0x0500: logerror("PTN: not supported"); break;
case 0x0600: logerror("PTN: not supported"); break;
case 0x0700: logerror("PTN: not supported"); break;
}
else
switch (opcode & 0x0700)
{
default:
case 0x0000: dst_step1_x = 1; dst_step1_y = 0; dst_step2_x = -ax_neg*ax; dst_step2_y = 1; break;
case 0x0100: logerror("PTN: not supported"); break;
case 0x0200: dst_step1_x = 0; dst_step1_y = 1; dst_step2_x = -1; dst_step2_y = -ax_neg*ax; break;
case 0x0300: logerror("PTN: not supported"); break;
case 0x0400: dst_step1_x = -1; dst_step1_y = 0; dst_step2_x = ax_neg*ax; dst_step2_y = -1; break;
case 0x0500: logerror("PTN: not supported"); break;
case 0x0600: dst_step1_x = 0; dst_step1_y = -1; dst_step2_x = 1; dst_step2_y = ax_neg*ax; break;
case 0x0700: logerror("PTN: not supported"); break;
}
src_step1_x = 1; src_step1_y = 0; src_step2_x = -ax; src_step2_y = 1;
for (;;)
{
for (;;)
{
getpixel = get_pixel_ptn(device, xxs, yys);
switch ((opcode & 0x0018) >> 3)
{
case 0x0000:
if (getpixel)
dot(device, xxd, yyd, opcode & 0x0007, hd63484->cl1);
else
dot(device, xxd, yyd, opcode & 0x0007, hd63484->cl0);
break;
case 0x0001:
if (getpixel)
dot(device, xxd, yyd, opcode & 0x0007, hd63484->cl1);
break;
case 0x0002:
if (getpixel == 0)
dot(device, xxd, yyd, opcode & 0x0007, hd63484->cl0);
break;
case 0x0003:
logerror("PTN: not supported"); break;
break;
}
if (opcode & 0x0800)
{
if (ay == 0) break;
if (_ay > 0)
{
xxs += src_step1_x;
yys += src_step1_y;
xxd += dst_step1_x;
yyd += dst_step1_y;
ay--;
}
else
{
xxs += src_step1_x;
yys += src_step1_y;
xxd += dst_step1_x;
yyd += dst_step1_y;
ay++;
}
}
else
{
if (ax == 0) break;
else if (ax > 0)
{
xxs += src_step1_x;
yys += src_step1_y;
xxd += dst_step1_x;
yyd += dst_step1_y;
ax--;
}
else
{
xxs += src_step1_x;
yys += src_step1_y;
xxd += dst_step1_x;
yyd += dst_step1_y;
ax++;
}
}
}
if (opcode & 0x0800)
{
ay = _ay;
if (_ax < 0)
{
xxs += src_step2_x;
yys += src_step2_y;
xxd += dst_step2_x;
yyd += dst_step2_y;
if (ax == 0) break;
ax++;
}
else
{
xxs += src_step2_x;
yys += src_step2_y;
xxd += dst_step2_x;
yyd += dst_step2_y;
if (ax == 0) break;
ax--;
}
}
else
{
ax = _ax;
if (_ay < 0)
{
xxs += src_step2_x;
yys += src_step2_y;
xxd += dst_step2_x;
yyd += dst_step2_y;
if (ay == 0) break;
ay++;
}
else
{
xxs += src_step2_x;
yys += src_step2_y;
xxd += dst_step2_x;
yyd += dst_step2_y;
if (ay == 0) break;
ay--;
}
}
}
}
static void line( device_t *device, INT16 sx, INT16 sy, INT16 ex, INT16 ey, INT16 col )
{
hd63484_state *hd63484 = get_safe_token(device);
INT16 ax,ay;
int cpx_t = sx;
int cpy_t = sy;
ax = ex - sx;
ay = ey - sy;
if (abs(ax) >= abs(ay))
{
while (ax)
{
dot(device, cpx_t, cpy_t, col & 7, hd63484->cl0);
if (ax > 0)
{
cpx_t++;
ax--;
}
else
{
cpx_t--;
ax++;
}
cpy_t = sy + ay * (cpx_t - sx) / (ex - sx);
}
}
else
{
while (ay)
{
dot(device, cpx_t, cpy_t, col & 7, hd63484->cl0);
if (ay > 0)
{
cpy_t++;
ay--;
}
else
{
cpy_t--;
ay++;
}
cpx_t = sx + ax * (cpy_t - sy) / (ey - sy);
}
}
}
static void circle( device_t *device, INT16 sx, INT16 sy, UINT16 r, INT16 col )
{
const float DEG2RAD = 3.14159f/180;
hd63484_state *hd63484 = get_safe_token(device);
int i;
for (i = 0; i < 360 * (r / 10); i++)
{
float degInRad = i * DEG2RAD / (r / 10);
dot(device, sx + cos(degInRad) * r,sy + sin(degInRad) * r, col & 7, hd63484->cl0);
}
}
static void paint( device_t *device, int sx, int sy, int col )
{
hd63484_state *hd63484 = get_safe_token(device);
int getpixel;
dot(device, sx, sy, 0, col);
getpixel = get_pixel(device, sx+1,sy);
switch ((hd63484->reg[0x02/2] & 0x700) >> 8)
{
case 0:
break;
case 1:
break;
case 2:
getpixel = (getpixel << 12) | (getpixel << 8) | (getpixel << 4) | (getpixel << 0);
break;
case 3:
getpixel = (getpixel << 8) | (getpixel << 0);
break;
case 4:
break;
default:
logerror ("Graphic bit mode not supported\n");
}
if ((getpixel != col) && (getpixel != hd63484->edg))
{
sx++;
paint(device, sx, sy, col);
sx--;
}
getpixel = get_pixel(device, sx - 1, sy);
switch ((hd63484->reg[0x02/2] & 0x700) >> 8)
{
case 0:
break;
case 1:
break;
case 2:
getpixel = (getpixel << 12) | (getpixel << 8) | (getpixel << 4) | (getpixel << 0);
break;
case 3:
getpixel = (getpixel << 8) | (getpixel << 0);
break;
case 4:
break;
default:
logerror ("Graphic bit mode not supported\n");
}
if ((getpixel != col) && (getpixel != hd63484->edg))
{
sx--;
paint(device, sx, sy, col);
sx++;
}
getpixel = get_pixel(device, sx, sy + 1);
switch ((hd63484->reg[0x02/2] & 0x700) >> 8)
{
case 0:
break;
case 1:
break;
case 2:
getpixel = (getpixel << 12) | (getpixel << 8) | (getpixel << 4) | (getpixel << 0);
break;
case 3:
getpixel = (getpixel << 8) | (getpixel << 0);
break;
case 4:
break;
default:
logerror ("Graphic bit mode not supported\n");
}
if ((getpixel != col) && (getpixel != hd63484->edg))
{
sy++;
paint(device, sx, sy, col);
sy--;
}
getpixel = get_pixel(device, sx, sy - 1);
switch ((hd63484->reg[0x02/2] & 0x700) >> 8)
{
case 0:
break;
case 1:
break;
case 2:
getpixel = (getpixel << 12) | (getpixel << 8) | (getpixel << 4) | (getpixel << 0);
break;
case 3:
getpixel = (getpixel << 8) | (getpixel << 0);
break;
case 4:
break;
default:
logerror ("Graphic bit mode not supported\n");
}
if ((getpixel != col) && (getpixel != hd63484->edg))
{
sy--;
paint(device, sx, sy, col);
sy++;
}
}
static void hd63484_command_w(device_t *device, UINT16 cmd)
{
hd63484_state *hd63484 = get_safe_token(device);
int len;
hd63484->fifo[hd63484->fifo_counter++] = cmd;
len = instruction_length[hd63484->fifo[0] >> 10];
if (len == -1)
{
if (hd63484->fifo_counter < 2) return;
else len = hd63484->fifo[1] + 2;
}
else if (len == -2)
{
if (hd63484->fifo_counter < 2) return;
else len = 2 * hd63484->fifo[1] + 2;
}
if (hd63484->fifo_counter >= len)
{
#if LOG_COMMANDS
int i;
logerror("%s: HD63484 command %s (%04x) ", device->machine().describe_context(), instruction_name[hd63484->fifo[0] >> 10], hd63484->fifo[0]);
for (i = 1; i < hd63484->fifo_counter; i++)
logerror("%04x ", hd63484->fifo[i]);
logerror("\n");
#endif
if (hd63484->fifo[0] == 0x0400) { /* ORG */
hd63484->org = ((hd63484->fifo[1] & 0x00ff) << 12) | ((hd63484->fifo[2] & 0xfff0) >> 4);
hd63484->org_dpd = hd63484->fifo[2] & 0x000f;
}
else if ((hd63484->fifo[0] & 0xffe0) == 0x0800) /* WPR */
{
if (hd63484->fifo[0] == 0x0800)
hd63484->cl0 = hd63484->fifo[1];
else if (hd63484->fifo[0] == 0x0801)
hd63484->cl1 = hd63484->fifo[1];
else if (hd63484->fifo[0] == 0x0802)
hd63484->ccmp = hd63484->fifo[1];
else if (hd63484->fifo[0] == 0x0803)
hd63484->edg = hd63484->fifo[1];
else if (hd63484->fifo[0] == 0x0804)
hd63484->mask = hd63484->fifo[1];
else if (hd63484->fifo[0] == 0x0805)
{
hd63484->ppy = (hd63484->fifo[1] & 0xf000) >> 12;
hd63484->pzcy = (hd63484->fifo[1] & 0x0f00) >> 8;
hd63484->ppx = (hd63484->fifo[1] & 0x00f0) >> 4;
hd63484->pzcx = (hd63484->fifo[1] & 0x000f) >> 0;
}
else if (hd63484->fifo[0] == 0x0806)
{
hd63484->psy = (hd63484->fifo[1] & 0xf000) >> 12;
hd63484->psx = (hd63484->fifo[1] & 0x00f0) >> 4;
}
else if (hd63484->fifo[0] == 0x0807)
{
hd63484->pey = (hd63484->fifo[1] & 0xf000) >> 12;
hd63484->pzy = (hd63484->fifo[1] & 0x0f00) >> 8;
hd63484->pex = (hd63484->fifo[1] & 0x00f0) >> 4;
hd63484->pzx = (hd63484->fifo[1] & 0x000f) >> 0;
}
else if (hd63484->fifo[0] == 0x0808)
hd63484->xmin = hd63484->fifo[1];
else if (hd63484->fifo[0] == 0x0809)
hd63484->ymin = hd63484->fifo[1];
else if (hd63484->fifo[0] == 0x080a)
hd63484->xmax = hd63484->fifo[1];
else if (hd63484->fifo[0] == 0x080b)
hd63484->ymax = hd63484->fifo[1];
else if (hd63484->fifo[0] == 0x080c)
{
hd63484->rwp = (hd63484->rwp & 0x00fff) | ((hd63484->fifo[1] & 0x00ff) << 12);
hd63484->rwp_dn = (hd63484->fifo[1] & 0xc000) >> 14;
}
else if (hd63484->fifo[0] == 0x080d)
{
hd63484->rwp = (hd63484->rwp & 0xff000) | ((hd63484->fifo[1] & 0xfff0) >> 4);
}
else
logerror("unsupported register\n");
}
else if ((hd63484->fifo[0] & 0xffe0) == 0x0c00) /* RPR */
{
if (hd63484->fifo[0] == 0x0c00)
hd63484->fifo[1] = hd63484->cl0;
else if (hd63484->fifo[0] == 0x0c01)
hd63484->fifo[1] = hd63484->cl1;
else if (hd63484->fifo[0] == 0x0c02)
hd63484->fifo[1] = hd63484->ccmp;
else if (hd63484->fifo[0] == 0x0c03)
hd63484->fifo[1] = hd63484->edg;
else if (hd63484->fifo[0] == 0x0c04)
hd63484->fifo[1] = hd63484->mask;
else if (hd63484->fifo[0] == 0x0c05)
{
hd63484->fifo[1] = (hd63484->ppy << 12) | (hd63484->pzcy << 8) | (hd63484->ppx << 4) | hd63484->pzcx;
}
else if (hd63484->fifo[0] == 0x0c06)
{
hd63484->fifo[1] = (hd63484->psx << 12) | (hd63484->psx << 4);
}
else if (hd63484->fifo[0] == 0x0c07)
{
hd63484->fifo[1] = (hd63484->pey << 12) | (hd63484->pzy << 8) | (hd63484->pex << 4) | hd63484->pzx;
}
else if (hd63484->fifo[0] == 0x0c08)
hd63484->fifo[1] = hd63484->xmin;
else if (hd63484->fifo[0] == 0x0c09)
hd63484->fifo[1] = hd63484->ymin;
else if (hd63484->fifo[0] == 0x0c0a)
hd63484->fifo[1] = hd63484->xmax;
else if (hd63484->fifo[0] == 0x0c0b)
hd63484->fifo[1] = hd63484->ymax;
else if (hd63484->fifo[0] == 0x0c0c)
{
hd63484->fifo[1] = (hd63484->rwp_dn << 14) | ((hd63484->rwp >> 12) & 0xff);
}
else if (hd63484->fifo[0] == 0x0c0d)
{
hd63484->fifo[1] = (hd63484->rwp & 0x0fff) << 4;
}
else if (hd63484->fifo[0] == 0x0c10)
{
// TODO
}
else if (hd63484->fifo[0] == 0x0c11)
{
// TODO
}
else if (hd63484->fifo[0] == 0x0c12)
{
hd63484->fifo[1] = hd63484->cpx;
}
else if (hd63484->fifo[0] == 0x0c13)
{
hd63484->fifo[1] = hd63484->cpy;
}
else
logerror("unsupported register\n");
}
else if ((hd63484->fifo[0] & 0xfff0) == 0x1800) /* WPTN */
{
int i;
int start = hd63484->fifo[0] & 0x000f;
int n = hd63484->fifo[1];
for (i = 0; i < n; i++)
hd63484->pattern[start + i] = hd63484->fifo[2 + i];
}
else if (hd63484->fifo[0] == 0x4400) /* RD */
{
hd63484->readfifo = hd63484->ram[hd63484->rwp];
hd63484->rwp = (hd63484->rwp + 1) & (HD63484_RAM_SIZE - 1);
}
else if (hd63484->fifo[0] == 0x4800) /* WT */
{
hd63484->ram[hd63484->rwp] = hd63484->fifo[1];
hd63484->rwp = (hd63484->rwp + 1) & (HD63484_RAM_SIZE - 1);
}
else if (hd63484->fifo[0] == 0x5800) /* CLR */
{
doclr16(device, hd63484->fifo[0], hd63484->fifo[1], &hd63484->rwp, hd63484->fifo[2], hd63484->fifo[3]);
{
int fifo2 = (int)hd63484->fifo[2], fifo3 = (int)hd63484->fifo[3];
if (fifo2 < 0) fifo2 *= -1;
if (fifo3 < 0) fifo3 *= -1;
hd63484->rwp += ((fifo2 + 1) * (fifo3 + 1));
}
}
else if ((hd63484->fifo[0] & 0xfffc) == 0x5c00) /* SCLR */
{
doclr16(device, hd63484->fifo[0], hd63484->fifo[1], &hd63484->rwp, hd63484->fifo[2], hd63484->fifo[3]);
{
int fifo2 = (int)hd63484->fifo[2], fifo3 = (int)hd63484->fifo[3];
if (fifo2 < 0) fifo2 *= -1;
if (fifo3 < 0) fifo3 *= -1;
hd63484->rwp += ((fifo2 + 1) * (fifo3 + 1));
}
}
else if ((hd63484->fifo[0] & 0xf0ff) == 0x6000) /* hd63484->cpy */
{
docpy16(device, hd63484->fifo[0], ((hd63484->fifo[1] & 0x00ff) << 12) | ((hd63484->fifo[2] & 0xfff0) >> 4), &hd63484->rwp, hd63484->fifo[3], hd63484->fifo[4]);
{
int fifo2 = (int)hd63484->fifo[2], fifo3 = (int)hd63484->fifo[3];
if (fifo2 < 0) fifo2 *= -1;
if (fifo3 < 0) fifo3 *= -1;
hd63484->rwp += ((fifo2 + 1) * (fifo3 + 1));
}
}
else if ((hd63484->fifo[0] & 0xf0fc) == 0x7000) /* Shd63484->cpy */
{
docpy16(device, hd63484->fifo[0], ((hd63484->fifo[1] & 0x00ff) << 12) | ((hd63484->fifo[2] & 0xfff0) >> 4), &hd63484->rwp, hd63484->fifo[3], hd63484->fifo[4]);
{
int fifo2 = (int)hd63484->fifo[2], fifo3 = (int)hd63484->fifo[3];
if (fifo2 < 0) fifo2 *= -1;
if (fifo3 < 0) fifo3 *= -1;
hd63484->rwp += ((fifo2 + 1) * (fifo3 + 1));
}
}
else if (hd63484->fifo[0] == 0x8000) /* AMOVE */
{
hd63484->cpx = hd63484->fifo[1];
hd63484->cpy = hd63484->fifo[2];
}
else if (hd63484->fifo[0] == 0x8400) /* RMOVE */
{
hd63484->cpx += (INT16)hd63484->fifo[1];
hd63484->cpy += (INT16)hd63484->fifo[2];
}
else if ((hd63484->fifo[0] & 0xff00) == 0x8800) /* ALINE */
{
line(device, hd63484->cpx, hd63484->cpy, hd63484->fifo[1], hd63484->fifo[2], hd63484->fifo[0] & 0xff);
hd63484->cpx = (INT16)hd63484->fifo[1];
hd63484->cpy = (INT16)hd63484->fifo[2];
}
else if ((hd63484->fifo[0] & 0xff00) == 0x8c00) /* RLINE */
{
line(device, hd63484->cpx, hd63484->cpy, hd63484->cpx + (INT16)hd63484->fifo[1], hd63484->cpy + (INT16)hd63484->fifo[2], hd63484->fifo[0] & 0xff);
hd63484->cpx += (INT16)hd63484->fifo[1];
hd63484->cpy += (INT16)hd63484->fifo[2];
}
else if ((hd63484->fifo[0] & 0xfff8) == 0x9000) /* ARCT */
{
line(device, hd63484->cpx, hd63484->cpy, (INT16)hd63484->fifo[1], hd63484->cpy, hd63484->fifo[0] & 0xff);
line(device, (INT16)hd63484->fifo[1], hd63484->cpy, (INT16)hd63484->fifo[1], (INT16)hd63484->fifo[2], hd63484->fifo[0] & 0xff);
line(device, (INT16)hd63484->fifo[1], (INT16)hd63484->fifo[2], hd63484->cpx, (INT16)hd63484->fifo[2], hd63484->fifo[0] & 0xff);
line(device, hd63484->cpx, (INT16)hd63484->fifo[2], hd63484->cpx, hd63484->cpy, hd63484->fifo[0] & 0xff);
hd63484->cpx = (INT16)hd63484->fifo[1];
hd63484->cpy = (INT16)hd63484->fifo[2];
}
else if ((hd63484->fifo[0] & 0xfff8) == 0x9400) /* RRCT added*/
{
line(device, hd63484->cpx, hd63484->cpy, hd63484->cpx + (INT16)hd63484->fifo[1], hd63484->cpy, hd63484->fifo[0] & 0xff);
line(device, hd63484->cpx + (INT16)hd63484->fifo[1], hd63484->cpy, hd63484->cpx + (INT16)hd63484->fifo[1], hd63484->cpy + (INT16)hd63484->fifo[2], hd63484->fifo[0] & 0xff);
line(device, hd63484->cpx + (INT16)hd63484->fifo[1], hd63484->cpy + (INT16)hd63484->fifo[2], hd63484->cpx, hd63484->cpy + (INT16)hd63484->fifo[2], hd63484->fifo[0] & 0xff);
line(device, hd63484->cpx, hd63484->cpy + (INT16)hd63484->fifo[2], hd63484->cpx, hd63484->cpy, hd63484->fifo[0] & 0xff);
hd63484->cpx += (INT16)hd63484->fifo[1];
hd63484->cpy += (INT16)hd63484->fifo[2];
}
else if ((hd63484->fifo[0] & 0xfff8) == 0xa400) /* RPLG added*/
{
int nseg, sx, sy, ex, ey;
sx = hd63484->cpx;
sy = hd63484->cpy;
for (nseg = 0; nseg < hd63484->fifo[1]; nseg++)
{
ex = sx + (INT16)hd63484->fifo[2 + nseg * 2];
ey = sy + (INT16)hd63484->fifo[2 + nseg * 2 + 1];
line(device, sx, sy, ex, ey, hd63484->fifo[0] & 7);
sx = ex;
sy = ey;
}
line(device, sx, sy, hd63484->cpx, hd63484->cpy, hd63484->fifo[0] & 7);
}
else if ((hd63484->fifo[0] & 0xfe00) == 0xa800) /* CRCL added*/
{
circle(device, hd63484->cpx, hd63484->cpy, hd63484->fifo[1] & 0x1fff, hd63484->fifo[0] & 7); // only 13 bit are used for the radius
}
else if ((hd63484->fifo[0] & 0xfff8) == 0xc000) /* AFRCT */
{
INT16 pcx, pcy;
INT16 ax, ay, xx, yy;
pcx = hd63484->fifo[1];
pcy = hd63484->fifo[2];
ax = pcx - hd63484->cpx;
ay = pcy - hd63484->cpy;
xx = hd63484->cpx;
yy = hd63484->cpy;
for (;;)
{
for (;;)
{
dot(device, xx, yy, hd63484->fifo[0] & 0x07, hd63484->cl0);
if (ax == 0) break;
else if (ax > 0)
{
xx++;
ax--;
}
else
{
xx--;
ax++;
}
}
ax = pcx - hd63484->cpx;
if (pcy < hd63484->cpy)
{
yy--;
xx -= ax;
if (ay == 0) break;
ay++;
}
else
{
yy++;
xx -= ax;
if (ay == 0) break;
ay--;
}
}
}
else if ((hd63484->fifo[0] & 0xfff8) == 0xc400) /* RFRCT added TODO*/
{
line(device, hd63484->cpx, hd63484->cpy, hd63484->cpx + (INT16)hd63484->fifo[1], hd63484->cpy, hd63484->fifo[0] & 0xff);
line(device, hd63484->cpx + hd63484->fifo[1], hd63484->cpy, hd63484->cpx + hd63484->fifo[1], hd63484->cpy + hd63484->fifo[2], hd63484->fifo[0] & 0xff);
line(device, hd63484->cpx + hd63484->fifo[1], hd63484->cpy + hd63484->fifo[2], hd63484->cpx, hd63484->cpy + hd63484->fifo[2], hd63484->fifo[0] & 0xff);
line(device, hd63484->cpx, hd63484->cpy + hd63484->fifo[2], hd63484->cpx, hd63484->cpy, hd63484->fifo[0] & 0xff);
hd63484->cpx = hd63484->cpx + (INT16)hd63484->fifo[1];
hd63484->cpy = hd63484->cpy + (INT16)hd63484->fifo[2];
}
else if (hd63484->fifo[0] == 0xc800) /* PAINT */
{
paint(device, hd63484->cpx, hd63484->cpy, hd63484->cl0);
}
else if ((hd63484->fifo[0] & 0xfff8) == 0xcc00) /* DOT */
{
dot(device, hd63484->cpx, hd63484->cpy, hd63484->fifo[0] & 0xff, hd63484->cl0);
}
else if ((hd63484->fifo[0] & 0xf000) == 0xd000) /* PTN (to do) */
{
ptn(device, hd63484->fifo[0], hd63484->psx, hd63484->psy, hd63484->pex - hd63484->psx, hd63484->pey - hd63484->psy);
if ((hd63484->fifo[0] & 0x0800) == 0x0000)
switch (hd63484->fifo[0] & 0x0700)
{
case 0x0000:
if ((hd63484->pey - hd63484->psy) > 0)
hd63484->cpy += (hd63484->pey - hd63484->psy);
else
hd63484->cpy -= (hd63484->pey - hd63484->psy);
break;
case 0x0100:
// missing
break;
case 0x0200:
if ((hd63484->pey - hd63484->psy) > 0)
hd63484->cpx += (hd63484->pey - hd63484->psy);
else
hd63484->cpx -= (hd63484->pey - hd63484->psy);
break;
case 0x0300:
// missing
break;
case 0x0400:
if ((hd63484->pey - hd63484->psy) > 0)
hd63484->cpy -= (hd63484->pey - hd63484->psy);
else
hd63484->cpy += (hd63484->pey - hd63484->psy);
break;
case 0x0500:
// missing
break;
case 0x0600:
if ((hd63484->pey - hd63484->psy) > 0)
hd63484->cpx -= (hd63484->pey - hd63484->psy);
else
hd63484->cpx += (hd63484->pey - hd63484->psy);
break;
case 0x0700:
// missing
break;
}
else
{
// missing
}
}
else if ((hd63484->fifo[0] & 0xf018) == 0xe000) /* agcpy */
{
agcpy(device, hd63484->fifo[0], (INT16)hd63484->fifo[1], (INT16)hd63484->fifo[2], hd63484->cpx, hd63484->cpy, hd63484->fifo[3], hd63484->fifo[4]);
switch (hd63484->fifo[0] & 0x0700)
{
case 0x0000:
if (hd63484->fifo[4] > 0)
hd63484->cpy += hd63484->fifo[4];
else
hd63484->cpy -= hd63484->fifo[4];
break;
case 0x0100:
if (hd63484->fifo[4] > 0)
hd63484->cpy -= hd63484->fifo[4];
else
hd63484->cpy += hd63484->fifo[4];
break;
case 0x0200:
if (hd63484->fifo[4] > 0)
hd63484->cpy += hd63484->fifo[4];
else
hd63484->cpy -= hd63484->fifo[4];
break;
case 0x0300:
if (hd63484->fifo[4] > 0)
hd63484->cpy -= hd63484->fifo[4];
else
hd63484->cpy += hd63484->fifo[4];
break;
case 0x0400:
if (hd63484->fifo[3] > 0)
hd63484->cpx += hd63484->fifo[3];
else
hd63484->cpx -= hd63484->fifo[3];
break;
case 0x0500:
if (hd63484->fifo[3] > 0)
hd63484->cpx += hd63484->fifo[3];
else
hd63484->cpx -= hd63484->fifo[3];
break;
case 0x0600:
if (hd63484->fifo[3] > 0)
hd63484->cpx -= hd63484->fifo[3];
else
hd63484->cpx += hd63484->fifo[3];
break;
case 0x0700:
if (hd63484->fifo[3] > 0)
hd63484->cpx -= hd63484->fifo[3];
else
hd63484->cpx += hd63484->fifo[3];
break;
}
}
else
{
logerror("unsupported command\n");
popmessage("unsupported command %s (%04x)", instruction_name[hd63484->fifo[0] >> 10], hd63484->fifo[0]);
}
hd63484->fifo_counter = 0;
}
}
READ16_DEVICE_HANDLER( hd63484_status_r )
{
// if (cpu_get_pc(&space->device()) != 0xfced6 && cpu_get_pc(&space->device()) != 0xfe1d6)
// logerror("%05x: HD63484 status read\n",cpu_get_pc(&space->device()));
return 0xff22 | (device->machine().rand() & 0x0004); /* write FIFO ready + command end + (read FIFO ready or read FIFO not ready) */
}
WRITE16_DEVICE_HANDLER( hd63484_address_w )
{
hd63484_state *hd63484 = get_safe_token(device);
/* only low 8 bits are used */
if (ACCESSING_BITS_0_7)
hd63484->regno = data;
}
WRITE16_DEVICE_HANDLER( hd63484_data_w )
{
hd63484_state *hd63484 = get_safe_token(device);
COMBINE_DATA(&hd63484->reg[hd63484->regno/2]);
if (hd63484->skattva_hack)
hd63484->reg[2/2] = (hd63484->reg[2/2] & 0xf8ff) | 0x0200; // hack to set proper color depth in skattva
if (hd63484->regno & 0x80)
hd63484->regno += 2; /* autoincrement */
#if LOG_COMMANDS
// logerror("PC %05x: HD63484 register %02x write %04x\n", cpu_get_pc(&space->device()), hd63484->regno, hd63484->reg[hd63484->regno/2]);
#endif
if (hd63484->regno == 0) /* FIFO */
hd63484_command_w(device, hd63484->reg[0]);
}
READ16_DEVICE_HANDLER( hd63484_data_r )
{
hd63484_state *hd63484 = get_safe_token(device);
int res;
if (hd63484->regno == 0x80)
res = device->machine().primary_screen->vpos();
else if (hd63484->regno == 0)
{
#if LOG_COMMANDS
// logerror("%05x: HD63484 read FIFO\n", cpu_get_pc(&space->device()));
#endif
res = hd63484->readfifo;
}
else
{
#if LOG_COMMANDS
// logerror("%05x: HD63484 read register %02x\n", cpu_get_pc(&space->device()), hd63484->regno);
#endif
res = 0;
}
return res;
}
READ16_DEVICE_HANDLER( hd63484_ram_r )
{
hd63484_state *hd63484 = get_safe_token(device);
return hd63484->ram[offset];
}
READ16_DEVICE_HANDLER( hd63484_regs_r )
{
hd63484_state *hd63484 = get_safe_token(device);
return hd63484->reg[offset];
}
WRITE16_DEVICE_HANDLER( hd63484_ram_w )
{
hd63484_state *hd63484 = get_safe_token(device);
COMBINE_DATA(&hd63484->ram[offset]);
}
WRITE16_DEVICE_HANDLER( hd63484_regs_w )
{
hd63484_state *hd63484 = get_safe_token(device);
COMBINE_DATA(&hd63484->reg[offset]);
}
static DEVICE_START( hd63484 )
{
hd63484_state *hd63484 = get_safe_token(device);
const hd63484_interface *intf = get_interface(device);
hd63484->skattva_hack = intf->skattva_hack;
hd63484->ram = auto_alloc_array_clear(device->machine(), UINT16, HD63484_RAM_SIZE);
// device->save_item(NAME(hd63484->clear_bitmap));
// device->save_pointer(NAME(hd63484->spriteram), 0x1000);
// device->save_item(NAME(*hd63484->sprites_bitmap));
}
static DEVICE_RESET( hd63484 )
{
hd63484_state *hd63484 = get_safe_token(device);
hd63484->fifo_counter = 0;
}
static const char DEVTEMPLATE_SOURCE[] = __FILE__;
#define DEVTEMPLATE_ID( p, s ) p##hd63484##s
#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET
#define DEVTEMPLATE_NAME "HD63484"
#define DEVTEMPLATE_FAMILY "HD63484 Video Controller"
#include "devtempl.h"
DEFINE_LEGACY_DEVICE(HD63484, hd63484);