// license:BSD-3-Clause
// copyright-holders:Nathan Woods,Frank Palazzolo
/**********************************************************************
General Instruments AY-3-8900-1 a.k.a. Standard Television Interface Chip
(STIC) emulation for Mattel Intellivision
*********************************************************************/
#include "emu.h"
#include "video/stic.h"
#include "screen.h"
/****************************************************************************
* *
* MXR 0000[..0007] MOB X REGISTER RW *
* *
* (MSB) (LSB) *
* +-+-+-+-+-+-----+---+---+--+--+--+--+--+--+--+--+ *
* | | | | | |XSIZE|VIS|COL|X7|X6|X5|X4|X3|X2|X1|X0| *
* +-+-+-+-+-+-----+---+---+--+--+--+--+--+--+--+--+ *
* *
* Xn x-position [0..255] *
* COL collision detection [1=enable] *
* VIS visibility [1=visible] *
* XSIZE double width [1=double] *
* *
****************************************************************************
* *
* NOTES *
* *
* 1. If X=0, the sprite is not visible and does not register collisions. *
* 2. The horizontal handle is 8 pixels from the left of the sprite, *
* regardless of width. *
* *
****************************************************************************/
#define STIC_MXR 0x0000
#define STIC_MXR_XSIZE 0x0400
#define STIC_MXR_VIS 0x0200
#define STIC_MXR_COL 0x0100
#define STIC_MXR_X 0x00FF
/****************************************************************************
* *
* MYR 0008[..000F] MOB Y REGISTER RW *
* *
* (MSB) (LSB) *
* +-+-+-+-+-----+-----+-----+-----+----+--+--+--+--+--+--+--+ *
* | | | | |YFLIP|XFLIP|YSIZE|YFULL|YRES|Y6|Y5|Y4|Y3|Y2|Y1|Y0| *
* +-+-+-+-+-----+-----+-----+-----+----+--+--+--+--+--+--+--+ *
* *
* Yn y-position [0..127] *
* YRES y-resolution [0=8 scanlines,1=16 scanlines] *
* YFULL double scanline height [1=double] *
* YSIZE quadruple scanline height [1=quadruple] *
* XFLIP horizontally flip image [1=flip] *
* YFLIP vertically flip image [1=flip] *
* *
****************************************************************************
* *
* NOTES *
* *
* 1. A sprite with YRES=1 will display two cards. *
* 2. A sprite with YFULL=0 and YSIZE=0 will have scanlines half the *
* height of a background card. *
* 3, The minimum size of a sprite is 8x8 (XSIZE=YRES=YSIZE=YFULL=0). *
* 4. The maximum size of a sprite is 16x128 (XSIZE=YRES=YSIZE=YFULL=1). *
* 5. The Y-position is measured in double height scanlines. *
* 6. The vertical handle is 8 double height scanlines from the top of the *
* sprite, regardless of height. *
* *
****************************************************************************/
#define STIC_MYR 0x0008
#define STIC_MYR_YFLIP 0x0800
#define STIC_MYR_XFLIP 0x0400
#define STIC_MYR_YSIZE 0x0200
#define STIC_MYR_YFULL 0x0100
#define STIC_MYR_YRES 0x0080
#define STIC_MYR_Y 0x007F
/****************************************************************************
* *
* SAR 0010[..0017] MOB ATTRIBUTE REGISTER RW *
* *
* (MSB) (LSB) *
* +-+-+---+---+---+-+-+--+--+--+--+--+--+---+---+---+ *
* | | |PRI|FG3|SEL| | |C5|C4|C3|C2|C1|C0|FG2|FG1|FG0| *
* +-+-+---+---+---+-+-+--+--+--+--+--+--+---+---+---+ *
* *
* FGn foreground color [0..15] *
* Cn card # [0..63] *
* SEL card memory select [0=GROM, 1=GRAM] *
* PRI sprite priority [1=behind set background bit] *
* *
****************************************************************************/
#define STIC_MAR 0x0010
#define STIC_MAR_PRI 0x2000
#define STIC_MAR_FG3 0x1000
#define STIC_MAR_SEL 0x0800
#define STIC_MAR_C 0x07F8
#define STIC_MAR_FG20 0x0007
/****************************************************************************
* *
* SCR 0018[..001F] MOB COLLISION REGISTER RW *
* *
* (MSB) (LSB) *
* +-+-+-+-+-+-+----+----+----+----+----+----+----+----+----+----+ *
* | | | | | | |BRDR|BKGD|SPR7|SPR6|SPR5|SPR4|SPR3|SPR2|SPR1|SPR0| *
* +-+-+-+-+-+-+----+----+----+----+----+----+----+----+----+----+ *
* *
* SPRn 1=collision with sprite #n *
* BKGD 1=collision with set background bit *
* BRDR 1=collision with screen border *
* *
****************************************************************************
* *
* NOTES *
* *
* 1. All collisions are latched. Successive reads read from the latch. *
* A write will reset the latch. *
* 2. Sprites with VIS=0 register collisions. *
* 3. Sprites with X=0 do not register collisions. *
* 4. Two overlapping sprites with different priorities, one completely *
* hidden behind the background, still register a collision. *
* *
****************************************************************************/
#define STIC_MCR 0x0018
#define STIC_MCR_BRDR 0x0200
#define STIC_MCR_BKGD 0x0100
#define STIC_MCR_SPR7 0x0080
#define STIC_MCR_SPR6 0x0040
#define STIC_MCR_SPR5 0x0020
#define STIC_MCR_SPR4 0x0010
#define STIC_MCR_SPR3 0x0008
#define STIC_MCR_SPR2 0x0004
#define STIC_MCR_SPR1 0x0002
#define STIC_MCR_SPR0 0x0001
/****************************************************************************
* *
* DER 0021 DISPLAY ENABLE REGISTER W *
* *
* (MSB) (LSB) *
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *
* | | | | | | | | | | | | | | | | | *
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *
* *
****************************************************************************
* *
* NOTES *
* *
* 1. Any write during VBLANK enables STIC output. *
* *
****************************************************************************/
#define STIC_DER 0x0020
/****************************************************************************
* *
* GMR 0021 GRAPHICS MODE REGISTER RW *
* *
* (MSB) (LSB) *
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *
* | | | | | | | | | | | | | | | | | *
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *
* *
****************************************************************************
* *
* NOTES *
* *
* 1. Any write during VBLANK enables FOREGROUND/BACKGROUND mode. *
* 2. Any read during VBLANK enables COLOR STACK/COLORED SQUARES mode. *
* *
****************************************************************************/
#define STIC_GMR 0x0021
/****************************************************************************
* *
* CSR 0028 COLOR STACK REGISTER RW *
* *
* (MSB) (LSB) *
* +-+-+-+-+-+-+-+-+-+-+-+-+---+---+---+---+ *
* | | | | | | | | | | | | |BG3|BG2|BG1|BG0| *
* +-+-+-+-+-+-+-+-+-+-+-+-+---+---+---+---+ *
* *
* BGn background color [0..15] *
* *
****************************************************************************/
#define STIC_CSR 0x0028
#define STIC_CSR_BG 0x000F
/****************************************************************************
* *
* BCR 002C BORDER COLOR REGISTER RW *
* *
* (MSB) (LSB) *
* +-+-+-+-+-+-+-+-+-+-+-+-+---+---+---+---+ *
* | | | | | | | | | | | | |BC3|BC2|BC1|BC0| *
* +-+-+-+-+-+-+-+-+-+-+-+-+---+---+---+---+ *
* *
* BCn border color [0..15] *
* *
****************************************************************************
* *
* NOTES *
* *
* 1. Affects overscan, and column and row blockouts. *
* *
****************************************************************************/
#define STIC_BCR 0x002C
#define STIC_BCR_BC 0x000F
/****************************************************************************
* *
* HDR 0030 HORIZONTAL DELAY REGISTER RW *
* *
* (MSB) (LSB) *
* +-+-+-+-+-+-+-+-+-+-+-+-+-+----+----+----+ *
* | | | | | | | | | | | | | |DEL2|DEL1|DEL0| *
* +-+-+-+-+-+-+-+-+-+-+-+-+-+----+----+----+ *
* *
* DELn horizontal delay [0..7] *
* *
****************************************************************************
* *
* NOTES *
* *
* 1. Affects both BACKTAB and MOBs. *
* *
****************************************************************************/
#define STIC_HDR 0x0030
#define STIC_HDR_DEL 0x0007
/****************************************************************************
* *
* STIC_VDR 0030 VERTICAL DELAY REGISTER RW *
* *
* (MSB) (LSB) *
* +-+-+-+-+-+-+-+-+-+-+-+-+-+----+----+----+ *
* | | | | | | | | | | | | | |DEL2|DEL1|DEL0| *
* +-+-+-+-+-+-+-+-+-+-+-+-+-+----+----+----+ *
* *
* DELn vertical delay [0..7] *
* *
****************************************************************************
* *
* NOTES *
* *
* 1. Affects both BACKTAB and MOBs. *
* *
****************************************************************************/
#define STIC_VDR 0x0031
#define STIC_VDR_DEL 0x0007
/****************************************************************************
* *
* STIC_CBR 0032 CARD BLOCKOUT REGISTER RW *
* *
* (MSB) (LSB) *
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+---+---+ *
* | | | | | | | | | | | | | | |ROW|COL| *
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+---+---+ *
* *
* COL blockout first card column [1=blockout] *
* ROW blockout first card row [1=blockout] *
* *
****************************************************************************
* *
* NOTES *
* *
* 1. Generally used in conjunction with HDR and VDR registers, to achieve *
* smooth scrolling. *
* *
****************************************************************************/
#define STIC_CBR 0x0032
#define STIC_CBR_ROW 0x0002
#define STIC_CBR_COL 0x0001
/****************************************************************************
* *
* FOREGROUND/BACKGROUND MODE *
* *
* (MSB) (LSB) *
* +-+-+---+---+---+---+---+--+--+--+--+--+--+---+---+---+ *
* | | |BG2|BG3|SEL|BG1|BG0|C5|C4|C3|C2|C1|C0|FG2|FG1|FG0| *
* +-+-+---+---+---+---+---+--+--+--+--+--+--+---+---+---+ *
* *
* FGn foreground color [0..7] *
* Cn card # [0..63] *
* SEL card memory select [0=GROM, 1=GRAM] *
* BGn background color [0..15] *
* *
****************************************************************************/
#define STIC_FBM_BG2 0x2000
#define STIC_FBM_BG310 0x1600
#define STIC_FBM_SEL 0x0800
#define STIC_FBM_C 0x01F8
#define STIC_FBM_FG 0x0007
/****************************************************************************
* *
* COLOR STACK MODE *
* *
* (MSB) (LSB) *
* +-+-+---+---+---+--+--+--+--+--+--+--+--+---+---+---+ *
* | | |ADV|FG3|SEL|C7|C6|C5|C4|C3|C2|C1|C0|FG2|FG1|FG0| *
* +-+-+---+---+---+--+--+--+--+--+--+--+--+---+---+---+ *
* *
* FGn foreground color [0..15] *
* Cn card # [GROM=0..212, GRAM=0..63] *
* SEL card memory select [0=GROM, 1=GRAM] *
* ADV advance color stack index [1=advance] *
* *
****************************************************************************
* *
* NOTES: *
* *
* 1. When FG3=1 and SEL=0, COLORED SQUARES MODE is enabled. *
* 2. When SEL=1, C7 and C6 can be used as user-defined flags. *
* *
****************************************************************************/
#define STIC_CSTM_ADV 0x2000
#define STIC_CSTM_FG3 0x1000
#define STIC_CSTM_SEL 0x0800
#define STIC_CSTM_C7 0x0400
#define STIC_CSTM_C6 0x0200
#define STIC_CSTM_C50 0x01F8
#define STIC_CSTM_FG20 0x0007
#define STIC_CSTM_C (STIC_CSTM_C7|STIC_CSTM_C6|STIC_CSTM_C50)
/****************************************************************************
* *
* COLORED SQUARES MODE *
* *
* (MSB) (LSB) *
* +-+-+--+-+-+--+--+--+--+--+--+--+--+--+--+--+ *
* | | |D2|1|0|D1|D0|C2|C1|C0|B2|B1|B0|A2|A1|A0| *
* +-+-+--+-+-+--+--+--+--+--+--+--+--+--+--+--+ *
* *
* An color a [0..7] *
* Bn color b [0..7] *
* Cn color c [0..7] *
* Dn color d [0..7] *
* *
****************************************************************************
* *
* NOTES: *
* *
* 1. Each color corresponds to one of the following 4 x 4 squares: *
* *
* +---+---+ *
* | a | b | *
* +---+---+ *
* | c | d | *
* +---+---+ *
* *
* 2. When color 7 is specified, the color is taken from the color stack. *
* *
****************************************************************************/
#define STIC_CSQM_D2 0x2000
#define STIC_CSQM_D10 0x0600
#define STIC_CSQM_C 0x01C0
#define STIC_CSQM_B 0x0038
#define STIC_CSQM_A 0x0007
#define STIC_CSQM_WIDTH (CARD_WIDTH / 2)
#define STIC_CSQM_HEIGHT (CARD_HEIGHT / 2)
DEFINE_DEVICE_TYPE(STIC, stic_device, "stic", "AY-3-8900-1 STIC");
//-------------------------------------------------
// stic_device - constructor
//-------------------------------------------------
stic_device::stic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, STIC, tag, owner, clock),
device_video_interface(mconfig, *this),
m_grom(*this, "grom"),
m_x_scale(1),
m_y_scale(1)
{
}
//-------------------------------------------------
// ~stic_device - destructor
//-------------------------------------------------
stic_device::~stic_device()
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void stic_device::device_start()
{
screen().register_screen_bitmap(m_bitmap);
save_item(NAME(m_stic_registers));
save_item(NAME(m_gramdirty));
save_item(NAME(m_gram));
save_item(NAME(m_gramdirtybytes));
save_item(NAME(m_color_stack_mode));
save_item(NAME(m_color_stack_offset));
save_item(NAME(m_stic_handshake));
save_item(NAME(m_border_color));
save_item(NAME(m_col_delay));
save_item(NAME(m_row_delay));
save_item(NAME(m_left_edge_inhibit));
save_item(NAME(m_top_edge_inhibit));
save_item(NAME(m_backtab_buffer));
for (int sp = 0; sp < MOBS; sp++)
{
save_item(m_sprite[sp].visible, "STIC sprite/m_sprite[sp].visible", sp);
save_item(m_sprite[sp].xpos, "STIC sprite/m_sprite[sp].xpos", sp);
save_item(m_sprite[sp].ypos, "STIC sprite/m_sprite[sp].ypos", sp);
save_item(m_sprite[sp].coll, "STIC sprite/m_sprite[sp].coll", sp);
save_item(m_sprite[sp].collision, "STIC sprite/m_sprite[sp].collision", sp);
save_item(m_sprite[sp].doublex, "STIC sprite/m_sprite[sp].doublex", sp);
save_item(m_sprite[sp].doubley, "STIC sprite/m_sprite[sp].doubley", sp);
save_item(m_sprite[sp].quady, "STIC sprite/m_sprite[sp].quady", sp);
save_item(m_sprite[sp].xflip, "STIC sprite/m_sprite[sp].xflip", sp);
save_item(m_sprite[sp].yflip, "STIC sprite/m_sprite[sp].yflip", sp);
save_item(m_sprite[sp].behind_foreground, "STIC sprite/m_sprite[sp].behind_foreground", sp);
save_item(m_sprite[sp].grom, "STIC sprite/m_sprite[sp].grom", sp);
save_item(m_sprite[sp].card, "STIC sprite/m_sprite[sp].card", sp);
save_item(m_sprite[sp].color, "STIC sprite/m_sprite[sp].color", sp);
save_item(m_sprite[sp].doubleyres, "STIC sprite/m_sprite[sp].doubleyres", sp);
save_item(m_sprite[sp].dirty, "STIC sprite/m_sprite[sp].dirty", sp);
save_item(m_sprite_buffers[sp], "STIC sprite/m_sprite[sp].sprite_buffers", sp);
}
}
void stic_device::device_reset()
{
for (int i = 0; i < MOBS; i++)
{
intv_sprite_type* s = &m_sprite[i];
s->visible = 0;
s->xpos = 0;
s->ypos = 0;
s->coll = 0;
s->collision = 0;
s->doublex = 0;
s->doubley = 0;
s->quady = 0;
s->xflip = 0;
s->yflip = 0;
s->behind_foreground = 0;
s->grom = 0;
s->card = 0;
s->color = 0;
s->doubleyres = 0;
s->dirty = 1;
for (int j = 0; j < 16; j++)
{
for (int k = 0; k < 128; k++)
{
m_sprite_buffers[i][j][k] = 0;
}
}
}
memset(m_stic_registers, 0, sizeof(m_stic_registers));
m_gramdirty = 1;
for (int i = 0; i < 64; i++)
{
m_gram[i] = 0;
m_gramdirtybytes[i] = 1;
}
m_color_stack_mode = 0;
m_color_stack_offset = 0;
m_stic_handshake = 0;
m_border_color = 0;
m_col_delay = 0;
m_row_delay = 0;
m_left_edge_inhibit = 0;
m_top_edge_inhibit = 0;
}
ROM_START( stic_grom )
ROM_REGION( 0x800, "grom", ROMREGION_ERASEFF )
ROM_LOAD( "ro-3-9503-003.u21", 0, 0x0800, CRC(683a4158) SHA1(f9608bb4ad1cfe3640d02844c7ad8e0bcd974917))
ROM_END
const tiny_rom_entry *stic_device::device_rom_region() const
{
return ROM_NAME( stic_grom );
}
#define FOREGROUND_BIT 0x0010
// conversion from Intellivision color to internal representation
#define SET_COLOR(c) ((c * 2) + 1)
#define GET_COLOR(c) ((c - 1) / 2)
/* initialized to non-zero, because we divide by it */
void stic_device::intv_set_pixel(bitmap_ind16 &bitmap, int x, int y, uint32_t color)
{
int w, h;
// output scaling
x *= m_x_scale;
y *= m_y_scale;
color = SET_COLOR(color);
for (h = 0; h < m_y_scale; h++)
for (w = 0; w < m_x_scale; w++)
bitmap.pix16(y + h, x + w) = color;
}
uint32_t stic_device::intv_get_pixel(bitmap_ind16 &bitmap, int x, int y)
{
return GET_COLOR(bitmap.pix16(y * m_y_scale, x * m_x_scale));
}
void stic_device::intv_plot_box(bitmap_ind16 &bitmap, int x, int y, int w, int h, int color)
{
bitmap.plot_box(x * m_x_scale, y * m_y_scale, w * m_x_scale, h * m_y_scale, SET_COLOR(color));
}
bool stic_device::sprites_collide(int spriteNum1, int spriteNum2)
{
int16_t x0, y0, w0, h0, x1, y1, w1, h1, x2, y2, w2, h2;
intv_sprite_type* s1 = &m_sprite[spriteNum1];
intv_sprite_type* s2 = &m_sprite[spriteNum2];
x0 = OVERSCAN_LEFT_WIDTH + m_col_delay - CARD_WIDTH;
y0 = OVERSCAN_TOP_HEIGHT + m_row_delay - CARD_HEIGHT;
x1 = (s1->xpos + x0) * X_SCALE; y1 = (s1->ypos + y0) * Y_SCALE;
x2 = (s2->xpos + x0) * X_SCALE; y2 = (s2->ypos + y0) * Y_SCALE;
w1 = (s1->doublex ? 2 : 1) * CARD_WIDTH;
w2 = (s2->doublex ? 2 : 1) * CARD_WIDTH;
h1 = (s1->quady ? 4 : 1) * (s1->doubley ? 2 : 1) * (s1->doubleyres ? 2 : 1) * CARD_HEIGHT;
h2 = (s2->quady ? 4 : 1) * (s2->doubley ? 2 : 1) * (s2->doubleyres ? 2 : 1) * CARD_HEIGHT;
if ((x1 >= x2 + w2) || (y1 >= y2 + h2) ||
(x2 >= x1 + w1) || (y2 >= y1 + h1))
return false;
// iterate over the intersecting bits to see if any touch
x0 = std::max(x1, x2);
y0 = std::max(y1, y2);
w0 = std::min(x1 + w1, x2 + w2) - x0;
h0 = std::min(y1 + h1, y2 + h2) - y0;
x1 = x0 - x1;
y1 = y0 - y1;
x2 = x0 - x2;
y2 = y0 - y2;
for (x0 = 0; x0 < w0; x0++)
{
for (y0 = 0; y0 < h0; y0++)
{
if (m_sprite_buffers[spriteNum1][x0 + x1][y0 + y1] &&
m_sprite_buffers[spriteNum2][x0 + x2][y0 + y2])
return true;
}
}
return false;
}
void stic_device::determine_sprite_collisions()
{
// check sprite to sprite collisions
for (int i = 0; i < MOBS - 1; i++)
{
intv_sprite_type* s1 = &m_sprite[i];
if (s1->xpos == 0 || !s1->coll)
continue;
for (int j = i + 1; j < MOBS; j++)
{
intv_sprite_type* s2 = &m_sprite[j];
if (s2->xpos == 0 || !s2->coll)
continue;
if (sprites_collide(i, j))
{
s1->collision |= (1 << j);
s2->collision |= (1 << i);
}
}
}
}
void stic_device::render_sprites()
{
int32_t cardMemoryLocation, pixelSize;
int32_t spritePixelHeight;
int32_t nextMemoryLocation;
int32_t nextData;
int32_t nextX;
int32_t nextY;
int32_t xInc;
for (int i = 0; i < MOBS; i++)
{
intv_sprite_type* s = &m_sprite[i];
if (s->grom)
cardMemoryLocation = (s->card * CARD_HEIGHT);
else
cardMemoryLocation = ((s->card & 0x003F) * CARD_HEIGHT);
pixelSize = (s->quady ? 4 : 1) * (s->doubley ? 2 : 1);
spritePixelHeight = pixelSize * (s->doubleyres ? 2 : 1) * CARD_HEIGHT;
for (int j = 0; j < spritePixelHeight; j++)
{
nextMemoryLocation = (cardMemoryLocation + (j/pixelSize));
if (s->grom)
nextData = m_grom[nextMemoryLocation];
else if (nextMemoryLocation < 0x200)
nextData = m_gram[nextMemoryLocation];
else
nextData = 0xFFFF;
nextX = (s->xflip ? ((s->doublex ? 2 : 1) * CARD_WIDTH - 1) : 0);
nextY = (s->yflip ? (spritePixelHeight - j - 1) : j);
xInc = (s->xflip ? -1: 1);
for (int k = 0; k < CARD_WIDTH * (1 + s->doublex); k++)
{
m_sprite_buffers[i][nextX + k * xInc][nextY] = (nextData & (1 << ((CARD_WIDTH - 1) - k / (1 + s->doublex)))) != 0;
}
}
}
}
void stic_device::render_line(bitmap_ind16 &bitmap, uint8_t nextByte, uint16_t x, uint16_t y, uint8_t fgcolor, uint8_t bgcolor)
{
uint32_t color;
for (int i = 0; i < CARD_WIDTH; i++)
{
color = (nextByte & (1 << ((CARD_WIDTH - 1) - i)) ? fgcolor : bgcolor);
intv_set_pixel(bitmap, x+i, y, color);
intv_set_pixel(bitmap, x+i, y+1, color);
}
}
void stic_device::render_colored_squares(bitmap_ind16 &bitmap, uint16_t x, uint16_t y, uint8_t color0, uint8_t color1, uint8_t color2, uint8_t color3)
{
intv_plot_box(bitmap, x, y, STIC_CSQM_WIDTH * X_SCALE, STIC_CSQM_HEIGHT * Y_SCALE, color0);
intv_plot_box(bitmap, x + STIC_CSQM_WIDTH * X_SCALE, y, STIC_CSQM_WIDTH * X_SCALE, STIC_CSQM_HEIGHT * Y_SCALE, color1);
intv_plot_box(bitmap, x, y + STIC_CSQM_HEIGHT * Y_SCALE, STIC_CSQM_WIDTH * X_SCALE, STIC_CSQM_HEIGHT * Y_SCALE, color2);
intv_plot_box(bitmap, x + STIC_CSQM_WIDTH * X_SCALE, y + STIC_CSQM_HEIGHT * Y_SCALE, STIC_CSQM_WIDTH * X_SCALE, STIC_CSQM_HEIGHT * Y_SCALE, color3);
}
void stic_device::render_color_stack_mode(bitmap_ind16 &bitmap)
{
int16_t w, h, nextx, nexty;
uint8_t csPtr = 0;
uint16_t nextCard;
for (h = 0, nexty = (OVERSCAN_TOP_HEIGHT + m_row_delay) * Y_SCALE;
h < BACKTAB_HEIGHT;
h++, nexty += CARD_HEIGHT * Y_SCALE)
{
for (w = 0, nextx = (OVERSCAN_LEFT_WIDTH + m_col_delay) * X_SCALE;
w < BACKTAB_WIDTH;
w++, nextx += CARD_WIDTH * X_SCALE)
{
nextCard = m_backtab_buffer[h][w];
// colored squares mode
if ((nextCard & (STIC_CSTM_FG3|STIC_CSTM_SEL)) == STIC_CSTM_FG3)
{
uint8_t csColor = m_stic_registers[STIC_CSR + csPtr];
uint8_t color0 = nextCard & STIC_CSQM_A;
uint8_t color1 = (nextCard & STIC_CSQM_B) >> 3;
uint8_t color2 = (nextCard & STIC_CSQM_C) >> 6;
uint8_t color3 = ((nextCard & STIC_CSQM_D2) >> 11) |
((nextCard & (STIC_CSQM_D10)) >> 9);
render_colored_squares(bitmap, nextx, nexty,
(color0 == 7 ? csColor : (color0 | FOREGROUND_BIT)),
(color1 == 7 ? csColor : (color1 | FOREGROUND_BIT)),
(color2 == 7 ? csColor : (color2 | FOREGROUND_BIT)),
(color3 == 7 ? csColor : (color3 | FOREGROUND_BIT)));
}
//color stack mode
else
{
uint8_t isGrom;
uint16_t memoryLocation, fgcolor, bgcolor;
uint8_t* memory;
//advance the color pointer, if necessary
if (nextCard & STIC_CSTM_ADV)
csPtr = (csPtr+1) & (CSRS - 1);
fgcolor = ((nextCard & STIC_CSTM_FG3) >> 9) |
(nextCard & (STIC_CSTM_FG20)) | FOREGROUND_BIT;
bgcolor = m_stic_registers[STIC_CSR + csPtr] & STIC_CSR_BG;
isGrom = !(nextCard & STIC_CSTM_SEL);
if (isGrom)
{
memoryLocation = nextCard & STIC_CSTM_C;
memory = m_grom;
for (int j = 0; j < CARD_HEIGHT; j++)
render_line(bitmap, memory[memoryLocation + j],
nextx, nexty + j * Y_SCALE, fgcolor, bgcolor);
}
else
{
memoryLocation = nextCard & STIC_CSTM_C50;
memory = m_gram;
for (int j = 0; j < CARD_HEIGHT; j++)
render_line(bitmap, memory[memoryLocation + j],
nextx, nexty + j * Y_SCALE, fgcolor, bgcolor);
}
}
}
}
}
void stic_device::render_fg_bg_mode(bitmap_ind16 &bitmap)
{
int16_t w, h, nextx, nexty;
uint8_t isGrom, fgcolor, bgcolor;
uint16_t nextCard, memoryLocation;
uint8_t* memory;
for (h = 0, nexty = (OVERSCAN_TOP_HEIGHT + m_row_delay) * Y_SCALE;
h < BACKTAB_HEIGHT;
h++, nexty += CARD_HEIGHT * Y_SCALE)
{
for (w = 0, nextx = (OVERSCAN_LEFT_WIDTH + m_col_delay) * X_SCALE;
w < BACKTAB_WIDTH;
w++, nextx += CARD_WIDTH * X_SCALE)
{
nextCard = m_backtab_buffer[h][w];
fgcolor = (nextCard & STIC_FBM_FG) | FOREGROUND_BIT;
bgcolor = ((nextCard & STIC_FBM_BG2) >> 11) |
((nextCard & STIC_FBM_BG310) >> 9);
isGrom = !(nextCard & STIC_FBM_SEL);
if (isGrom)
{
memoryLocation = nextCard & STIC_FBM_C;
memory = m_grom;
for (int j = 0; j < CARD_HEIGHT; j++)
render_line(bitmap, memory[memoryLocation + j],
nextx, nexty + j * Y_SCALE, fgcolor, bgcolor);
}
else
{
memoryLocation = nextCard & STIC_FBM_C;
memory = m_gram;
for (int j = 0; j < CARD_HEIGHT; j++)
render_line(bitmap, memory[memoryLocation + j],
nextx, nexty + j * Y_SCALE, fgcolor, bgcolor);
}
}
}
}
void stic_device::copy_sprites_to_background(bitmap_ind16 &bitmap)
{
uint8_t width, currentPixel;
uint8_t borderCollision, foregroundCollision;
uint8_t spritePixelHeight, x, y;
int16_t leftX, nextY;
int16_t leftBorder, rightBorder, topBorder, bottomBorder;
int32_t nextX;
for (int i = MOBS - 1; i >= 0; i--)
{
intv_sprite_type *s = &m_sprite[i];
if (s->xpos == 0 || (!s->coll && !s->visible))
continue;
borderCollision = false;
foregroundCollision = false;
spritePixelHeight = (s->quady ? 4 : 1) * (s->doubley ? 2 : 1) * (s->doubleyres ? 2 : 1) * CARD_HEIGHT;
width = (s->doublex ? 2 : 1) * CARD_WIDTH;
leftX = (s->xpos - CARD_WIDTH + OVERSCAN_LEFT_WIDTH + m_col_delay) * X_SCALE;
nextY = (s->ypos - CARD_HEIGHT + OVERSCAN_TOP_HEIGHT + m_row_delay) * Y_SCALE;
leftBorder = (OVERSCAN_LEFT_WIDTH + (m_left_edge_inhibit ? CARD_WIDTH : 0)) * X_SCALE;
rightBorder = (OVERSCAN_LEFT_WIDTH + BACKTAB_WIDTH * CARD_WIDTH - 1 - 1) * X_SCALE;
topBorder = (OVERSCAN_TOP_HEIGHT + (m_top_edge_inhibit ? CARD_HEIGHT : 0)) * Y_SCALE;
bottomBorder = (OVERSCAN_TOP_HEIGHT + BACKTAB_HEIGHT * CARD_HEIGHT) * Y_SCALE - 1;
for (y = 0; y < spritePixelHeight; y++)
{
for (x = 0; x < width; x++)
{
//if this sprite pixel is not on, then don't paint it
if (!m_sprite_buffers[i][x][y])
continue;
nextX = leftX + x;
//if the next pixel location is on the border, then we
//have a border collision and we can ignore painting it
if ((nextX < leftBorder) || (nextX > rightBorder) ||
(nextY < topBorder) || (nextY > bottomBorder))
{
borderCollision = true;
continue;
}
currentPixel = intv_get_pixel(bitmap, nextX, nextY);
//check for foreground collision
if (currentPixel & FOREGROUND_BIT)
{
foregroundCollision = true;
if (s->behind_foreground)
continue;
}
if (s->visible)
{
intv_set_pixel(bitmap, nextX, nextY, s->color | (currentPixel & FOREGROUND_BIT));
}
}
nextY++;
}
//update the collision bits
if (s->coll)
{
if (foregroundCollision)
s->collision |= STIC_MCR_BKGD;
if (borderCollision)
s->collision |= STIC_MCR_BRDR;
}
}
}
void stic_device::render_background(bitmap_ind16 &bitmap)
{
if (m_color_stack_mode)
render_color_stack_mode(bitmap);
else
render_fg_bg_mode(bitmap);
}
#ifdef UNUSED_CODE
void stic_device::draw_background(bitmap_ind16 &bitmap, int transparency)
{
// First, draw the background
int offs = 0;
int value = 0;
int row,col;
int fgcolor,bgcolor = 0;
int code;
int colora, colorb, colorc, colord;
int n_bit;
int p_bit;
int g_bit;
int j;
int x0 = OVERSCAN_LEFT_WIDTH + m_col_delay;
int y0 = OVERSCAN_TOP_HEIGHT + m_row_delay;
if (m_color_stack_mode == 1)
{
m_color_stack_offset = 0;
for(row = 0; row < BACKTAB_HEIGHT; row++)
{
for(col = 0; col < BACKTAB_WIDTH; col++)
{
value = m_ram16[offs];
n_bit = value & STIC_CSTM_ADV;
p_bit = value & STIC_CSTM_FG3;
g_bit = value & STIC_CSTM_SEL;
if (p_bit && (!g_bit)) // colored squares mode
{
colora = value & STIC_CSQM_A;
colorb = (value & STIC_CSQM_B) >> 3;
colorc = (value & STIC_CSQM_C) >> 6;
colord = ((n_bit & STIC_CSQM_D2) >> 11) + ((value & STIC_CSQM_D10) >> 9);
// color 7 if the top of the color stack in this mode
if (colora == 7) colora = m_stic_registers[STIC_CSR + CSR3];
if (colorb == 7) colorb = m_stic_registers[STIC_CSR + CSR3];
if (colorc == 7) colorc = m_stic_registers[STIC_CSR + CSR3];
if (colord == 7) colord = m_stic_registers[STIC_CSR + CSR3];
intv_plot_box(bitmap, (x0 + col * CARD_WIDTH) * X_SCALE, (y0 + row * CARD_HEIGHT) * Y_SCALE, STIC_CSQM_WIDTH * X_SCALE, STIC_CSQM_HEIGHT * Y_SCALE, colora);
intv_plot_box(bitmap, (x0 + col * CARD_WIDTH + STIC_CSQM_WIDTH)) * X_SCALE, (y0 + row * CARD_HEIGHT) * Y_SCALE, STIC_CSQM_WIDTH * X_SCALE, STIC_CSQM_HEIGHT * Y_SCALE, colorb);
intv_plot_box(bitmap, (x0 + col * CARD_WIDTH) * X_SCALE, (y0 + row * CARD_HEIGHT + STIC_CSQM_HEIGHT) * Y_SCALE, STIC_CSQM_WIDTH * X_SCALE, STIC_CSQM_HEIGHT * Y_SCALE, colorc);
intv_plot_box(bitmap, (x0 + col * CARD_WIDTH + STIC_CSQM_WIDTH) * X_SCALE, (y0 + row * CARD_HEIGHT + STIC_CSQM_HEIGHT) * Y_SCALE, STIC_CSQM_WIDTH * X_SCALE, STIC_CSQM_HEIGHT * Y_SCALE, colord);
}
else // normal color stack mode
{
if (n_bit) // next color
{
m_color_stack_offset += 1;
m_color_stack_offset &= (CSRS - 1);
}
if (p_bit) // pastel color set
fgcolor = (value & STIC_CSTM_FG20) + 8;
else
fgcolor = value & STIC_CSTM_FG20;
bgcolor = m_stic_registers[STIC_CSR + m_color_stack_offset];
code = (value & STIC_CSTM_C)>>3;
if (g_bit) // read from gram
{
code &= (STIC_CSTM_C50 >> 3); // keep from going outside the array
//if (m_gramdirtybytes[code] == 1)
{
decodechar(m_gfxdecode->gfx(1),
code,
m_gram,
machine().config()->gfxdecodeinfo[1].gfxlayout);
m_gramdirtybytes[code] = 0;
}
// Draw GRAM char
drawgfx(bitmap,m_gfxdecode->gfx(1),
code,
bgcolor*16+fgcolor,
0,0, (x0 + col * CARD_WIDTH) * X_SCALE, (y0 + row * CARD_HEIGHT) * Y_SCALE,
0,transparency,bgcolor);
for(j=0;j<8;j++)
{
//intv_set_pixel(bitmap, (x0 + col * CARD_WIDTH + j) * X_SCALE, (y0 + row * CARD_HEIGHT + 7) * Y_SCALE + 1, 1);
}
}
else // read from grom
{
drawgfx(bitmap,m_gfxdecode->gfx(0),
code,
bgcolor*16+fgcolor,
0,0, (x0 + col * CARD_WIDTH) * X_SCALE, (y0 + row * CARD_HEIGHT) * Y_SCALE,
0,transparency,bgcolor);
for(j=0;j<8;j++)
{
//intv_set_pixel(bitmap, (x0 + col * CARD_WIDTH + j) * X_SCALE, (y0 + row * CARD_HEIGHT + 7) * Y_SCALE + 1, 2);
}
}
}
offs++;
} // next col
} // next row
}
else
{
// fg/bg mode goes here
for(row = 0; row < BACKTAB_HEIGHT; row++)
{
for(col = 0; col < BACKTAB_WIDTH; col++)
{
value = m_ram16[offs];
fgcolor = value & STIC_FBM_FG;
bgcolor = ((value & STIC_FBM_BG2) >> 11) + ((value & STIC_FBM_BG310) >> 9);
code = (value & STIC_FBM_C) >> 3;
if (value & STIC_FBM_SEL) // read for GRAM
{
//if (m_gramdirtybytes[code] == 1)
{
decodechar(m_gfxdecode->gfx(1),
code,
m_gram,
machine().config()->gfxdecodeinfo[1].gfxlayout);
m_gramdirtybytes[code] = 0;
}
// Draw GRAM char
drawgfx(bitmap,m_gfxdecode->gfx(1),
code,
bgcolor*16+fgcolor,
0,0, (x0 + col * CARD_WIDTH) * X_SCALE, (y0 + row * CARD_HEIGHT) * Y_SCALE,
0,transparency,bgcolor);
}
else // read from GROM
{
drawgfx(bitmap,m_gfxdecode->gfx(0),
code,
bgcolor*16+fgcolor,
0,0, (x0 + col * CARD_WIDTH) * X_SCALE, (y0 + row * CARD_HEIGHT) * Y_SCALE,
0,transparency,bgcolor);
}
offs++;
} // next col
} // next row
}
}
#endif
/* TBD: need to handle sprites behind foreground? */
#ifdef UNUSED_FUNCTION
void stic_device::draw_sprites(bitmap_ind16 &bitmap, int behind_foreground)
{
int code;
int x0 = OVERSCAN_LEFT_WIDTH + m_col_delay - CARD_WIDTH;
int y0 = OVERSCAN_TOP_HEIGHT + m_row_delay - CARD_HEIGHT;
for (int i = MOBS - 1; i >= 0; --i)
{
intv_sprite_type *s = &m_sprite[i];
if (s->visible && (s->behind_foreground == behind_foreground))
{
code = s->card;
if (!s->grom)
{
code %= 64; // keep from going outside the array
if (s->yres == 1)
{
//if (m_gramdirtybytes[code] == 1)
{
decodechar(m_gfxdecode->gfx(1),
code,
m_gram,
machine().config()->gfxdecodeinfo[1].gfxlayout);
m_gramdirtybytes[code] = 0;
}
// Draw GRAM char
m_gfxdecode->gfx(1)->zoom_transpen(bitmap,&machine().screen[0].visarea,
code,
s->color,
s->xflip,s->yflip,
(s->xpos + x0) * X_SCALE, (s->ypos + y0) * Y_SCALE,
0x8000 * s->xsize, 0x8000 * s->ysize,0);
}
else
{
//if ((m_gramdirtybytes[code] == 1) || (m_gramdirtybytes[code+1] == 1))
{
decodechar(m_gfxdecode->gfx(1),
code,
m_gram,
machine().config()->gfxdecodeinfo[1].gfxlayout);
decodechar(m_gfxdecode->gfx(1),
code+1,
m_gram,
machine().config()->gfxdecodeinfo[1].gfxlayout);
m_gramdirtybytes[code] = 0;
m_gramdirtybytes[code+1] = 0;
}
// Draw GRAM char
m_gfxdecode->gfx(1)->zoom_transpen(bitmap,&machine().screen[0].visarea,
code,
s->color,
s->xflip,s->yflip,
(s->xpos + x0) * X_SCALE, (s->ypos + y0) * Y_SCALE + s->yflip * s->ysize * CARD_HEIGHT,
0x8000*s->xsize, 0x8000*s->ysize,0);
m_gfxdecode->gfx(1)->zoom_transpen(bitmap,&machine().screen[0].visarea,
code+1,
s->color,
s->xflip,s->yflip,
(s->xpos + x0) * X_SCALE, (s->ypos + y0) * Y_SCALE + (1 - s->yflip) * s->ysize * CARD_HEIGHT,
0x8000*s->xsize, 0x8000*s->ysize,0);
}
}
else
{
if (s->yres == 1)
{
// Draw GROM char
m_gfxdecode->gfx(0)->zoom_transpen(bitmap,&machine().screen[0].visarea,
code,
s->color,
s->xflip,s->yflip,
(s->xpos + x0) * X_SCALE, (s->ypos + y0) * Y_SCALE,
0x8000*s->xsize, 0x8000*s->ysize,0);
}
else
{
m_gfxdecode->gfx(0)->zoom_transpen(bitmap,&machine().screen[0].visarea,
code,
s->color,
s->xflip,s->yflip,
(s->xpos + x0) * X_SCALE, (s->ypos + y0) * Y_SCALE + s->yflip * s->ysize * CARD_HEIGHT,
0x8000*s->xsize, 0x8000*s->ysize,0);
m_gfxdecode->gfx(0)->zoom_transpen(bitmap,&machine().screen[0].visarea,
code+1,
s->color,
s->xflip,s->yflip,
(s->xpos + x0) * X_SCALE, (s->ypos + y0) * Y_SCALE + (1 - s->yflip) * s->ysize * CARD_HEIGHT,
0x8000*s->xsize, 0x8000*s->ysize,0);
}
}
}
}
}
#endif
void stic_device::draw_borders(bitmap_ind16 &bitmap)
{
intv_plot_box(bitmap, 0, 0, (OVERSCAN_LEFT_WIDTH + (m_left_edge_inhibit ? CARD_WIDTH : m_col_delay)) * X_SCALE, (OVERSCAN_TOP_HEIGHT + BACKTAB_HEIGHT * CARD_HEIGHT + OVERSCAN_BOTTOM_HEIGHT) * Y_SCALE, m_border_color);
intv_plot_box(bitmap, (OVERSCAN_LEFT_WIDTH + BACKTAB_WIDTH * CARD_WIDTH - 1) * X_SCALE, 0, OVERSCAN_RIGHT_WIDTH, (OVERSCAN_TOP_HEIGHT + BACKTAB_HEIGHT * CARD_HEIGHT + OVERSCAN_BOTTOM_HEIGHT) * Y_SCALE, m_border_color);
intv_plot_box(bitmap, 0, 0, (OVERSCAN_LEFT_WIDTH + BACKTAB_WIDTH * CARD_WIDTH - 1 + OVERSCAN_RIGHT_WIDTH) * X_SCALE, (OVERSCAN_TOP_HEIGHT + (m_top_edge_inhibit ? CARD_HEIGHT : m_row_delay)) * Y_SCALE, m_border_color);
intv_plot_box(bitmap, 0, (OVERSCAN_TOP_HEIGHT + BACKTAB_HEIGHT * CARD_HEIGHT) * Y_SCALE, (OVERSCAN_LEFT_WIDTH + BACKTAB_WIDTH * CARD_WIDTH - 1 + OVERSCAN_RIGHT_WIDTH) * X_SCALE, OVERSCAN_BOTTOM_HEIGHT * Y_SCALE, m_border_color);
}
void stic_device::screenrefresh()
{
if (m_stic_handshake != 0)
{
m_stic_handshake = 0;
// Render the background
render_background(m_bitmap);
// Render the sprites into their buffers
render_sprites();
for (auto & elem : m_sprite)
elem.collision = 0;
// Copy the sprites to the background
copy_sprites_to_background(m_bitmap);
determine_sprite_collisions();
for (int i = 0; i < MOBS; i++)
m_stic_registers[STIC_MCR + i] |= m_sprite[i].collision;
/* draw the screen borders if enabled */
draw_borders(m_bitmap);
}
else
{
/* STIC disabled, just fill with border color */
m_bitmap.fill(SET_COLOR(m_border_color));
}
}
READ16_MEMBER( stic_device::read )
{
//logerror("%x = stic_r(%x)\n",0,offset);
switch (offset)
{
case STIC_MXR + MOB0:
case STIC_MXR + MOB1:
case STIC_MXR + MOB2:
case STIC_MXR + MOB3:
case STIC_MXR + MOB4:
case STIC_MXR + MOB5:
case STIC_MXR + MOB6:
case STIC_MXR + MOB7:
return 0x3800 | (m_stic_registers[offset] & 0x07FF);
case STIC_MYR + MOB0:
case STIC_MYR + MOB1:
case STIC_MYR + MOB2:
case STIC_MYR + MOB3:
case STIC_MYR + MOB4:
case STIC_MYR + MOB5:
case STIC_MYR + MOB6:
case STIC_MYR + MOB7:
return 0x3000 | (m_stic_registers[offset] & 0x0FFF);
case STIC_MAR + MOB0:
case STIC_MAR + MOB1:
case STIC_MAR + MOB2:
case STIC_MAR + MOB3:
case STIC_MAR + MOB4:
case STIC_MAR + MOB5:
case STIC_MAR + MOB6:
case STIC_MAR + MOB7:
return m_stic_registers[offset] & 0x3FFF;
case STIC_MCR + MOB0:
case STIC_MCR + MOB1:
case STIC_MCR + MOB2:
case STIC_MCR + MOB3:
case STIC_MCR + MOB4:
case STIC_MCR + MOB5:
case STIC_MCR + MOB6:
case STIC_MCR + MOB7:
return 0x3C00 | (m_stic_registers[offset] & 0x03FF);
case STIC_GMR:
m_color_stack_mode = 1;
//logerror("Setting color stack mode\n");
/*** fall through ***/
case STIC_DER:
return 0x3FFF;
case STIC_CSR + CSR0:
case STIC_CSR + CSR1:
case STIC_CSR + CSR2:
case STIC_CSR + CSR3:
case STIC_BCR:
return 0x3FF0 | (m_stic_registers[offset] & 0x000F);
case STIC_HDR:
case STIC_VDR:
return 0x3FF8 | (m_stic_registers[offset] & 0x0007);
case STIC_CBR:
return 0x3FFC | (m_stic_registers[offset] & 0x0003);
default:
//logerror("unmapped read from STIC register %02X\n", offset);
return 0x3FFF;
}
}
WRITE16_MEMBER( stic_device::write )
{
intv_sprite_type *s;
//logerror("stic_w(%x) = %x\n",offset,data);
switch (offset)
{
// X Positions
case STIC_MXR + MOB0:
case STIC_MXR + MOB1:
case STIC_MXR + MOB2:
case STIC_MXR + MOB3:
case STIC_MXR + MOB4:
case STIC_MXR + MOB5:
case STIC_MXR + MOB6:
case STIC_MXR + MOB7:
s = &m_sprite[offset & (MOBS - 1)];
s->doublex = !!(data & STIC_MXR_XSIZE);
s->visible = !!(data & STIC_MXR_VIS);
s->coll = !!(data & STIC_MXR_COL);
s->xpos = (data & STIC_MXR_X);
break;
// Y Positions
case STIC_MYR + MOB0:
case STIC_MYR + MOB1:
case STIC_MYR + MOB2:
case STIC_MYR + MOB3:
case STIC_MYR + MOB4:
case STIC_MYR + MOB5:
case STIC_MYR + MOB6:
case STIC_MYR + MOB7:
s = &m_sprite[offset & (MOBS - 1)];
s->yflip = !!(data & STIC_MYR_YFLIP);
s->xflip = !!(data & STIC_MYR_XFLIP);
s->quady = !!(data & STIC_MYR_YSIZE);
s->doubley = !!(data & STIC_MYR_YFULL);
s->doubleyres = !!(data & STIC_MYR_YRES);
s->ypos = (data & STIC_MYR_Y);
break;
// Attributes
case STIC_MAR + MOB0:
case STIC_MAR + MOB1:
case STIC_MAR + MOB2:
case STIC_MAR + MOB3:
case STIC_MAR + MOB4:
case STIC_MAR + MOB5:
case STIC_MAR + MOB6:
case STIC_MAR + MOB7:
s = &m_sprite[offset & (MOBS - 1)];
s->behind_foreground = !!(data & STIC_MAR_PRI);
s->grom = !(data & STIC_MAR_SEL);
s->card = ((data & STIC_MAR_C) >> 3);
s->color = ((data & STIC_MAR_FG3) >> 9) | (data & STIC_MAR_FG20);
break;
// Collision Detection - TBD
case STIC_MCR + MOB0:
case STIC_MCR + MOB1:
case STIC_MCR + MOB2:
case STIC_MCR + MOB3:
case STIC_MCR + MOB4:
case STIC_MCR + MOB5:
case STIC_MCR + MOB6:
case STIC_MCR + MOB7:
// a MOB's own collision bit is *always* zero, even if a
// one is poked into it
data &= ~(1 << (offset & (MOBS - 1)));
break;
// Display enable
case STIC_DER:
//logerror("***Writing a %x to the STIC handshake\n",data);
m_stic_handshake = 1;
break;
// Graphics Mode
case STIC_GMR:
m_color_stack_mode = 0;
break;
// Color Stack
case STIC_CSR + CSR0:
case STIC_CSR + CSR1:
case STIC_CSR + CSR2:
case STIC_CSR + CSR3:
//logerror("Setting color_stack[%x] = %x (%s)\n", offset & (CSRS - 1),data & STIC_CSR_BG, m_maincpu->pc());
break;
// Border Color
case STIC_BCR:
//logerror("***Writing a %x to the border color\n",data);
m_border_color = data & STIC_BCR_BC;
break;
// Framing
case STIC_HDR:
m_col_delay = data & STIC_HDR_DEL;
break;
case STIC_VDR:
m_row_delay = data & STIC_VDR_DEL;
break;
case STIC_CBR:
m_left_edge_inhibit = (data & STIC_CBR_COL);
m_top_edge_inhibit = (data & STIC_CBR_ROW) >> 1;
break;
default:
//logerror("unmapped write to STIC register %02X: %04X\n", offset, data);
break;
}
if (offset < ARRAY_LENGTH(m_stic_registers))
m_stic_registers[offset] = data;
}
READ16_MEMBER( stic_device::gram_read )
{
return m_gram[offset];
}
WRITE16_MEMBER( stic_device::gram_write )
{
data &= 0xff;
m_gram[offset] = data;
m_gramdirtybytes[offset] = 1;
m_gramdirty = 1;
}
uint32_t stic_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
return 0;
}