/***************************************************************************
video/balsente.c
Functions to emulate the video hardware of the machine.
****************************************************************************/
#include "emu.h"
#include "includes/balsente.h"
/*************************************
*
* Video system start
*
*************************************/
VIDEO_START( balsente )
{
balsente_state *state = machine.driver_data<balsente_state>();
/* reset the system */
state->m_palettebank_vis = 0;
state->m_sprite_bank[0] = machine.region("gfx1")->base();
state->m_sprite_bank[1] = machine.region("gfx1")->base() + 0x10000;
/* determine sprite size */
state->m_sprite_data = machine.region("gfx1")->base();
state->m_sprite_mask = machine.region("gfx1")->bytes() - 1;
/* register for saving */
state->save_item(NAME(state->m_expanded_videoram));
state->save_item(NAME(state->m_palettebank_vis));
}
/*************************************
*
* Video RAM write
*
*************************************/
WRITE8_HANDLER( balsente_videoram_w )
{
balsente_state *state = space->machine().driver_data<balsente_state>();
/* expand the two pixel values into two bytes */
state->m_videoram[offset] = data;
state->m_expanded_videoram[offset * 2 + 0] = data >> 4;
state->m_expanded_videoram[offset * 2 + 1] = data & 15;
}
/*************************************
*
* Palette banking
*
*************************************/
WRITE8_HANDLER( balsente_palette_select_w )
{
balsente_state *state = space->machine().driver_data<balsente_state>();
/* only update if changed */
if (state->m_palettebank_vis != (data & 3))
{
/* update the scanline palette */
space->machine().primary_screen->update_partial(space->machine().primary_screen->vpos() - 1 + BALSENTE_VBEND);
state->m_palettebank_vis = data & 3;
}
logerror("balsente_palette_select_w(%d) scanline=%d\n", data & 3, space->machine().primary_screen->vpos());
}
/*************************************
*
* Palette RAM write
*
*************************************/
WRITE8_HANDLER( balsente_paletteram_w )
{
int r, g, b;
space->machine().generic.paletteram.u8[offset] = data & 0x0f;
r = space->machine().generic.paletteram.u8[(offset & ~3) + 0];
g = space->machine().generic.paletteram.u8[(offset & ~3) + 1];
b = space->machine().generic.paletteram.u8[(offset & ~3) + 2];
palette_set_color_rgb(space->machine(), offset / 4, pal4bit(r), pal4bit(g), pal4bit(b));
}
/*************************************
*
* Sprite banking
*
*************************************/
WRITE8_HANDLER( shrike_sprite_select_w )
{
balsente_state *state = space->machine().driver_data<balsente_state>();
if( state->m_sprite_data != state->m_sprite_bank[(data & 0x80 >> 7) ^ 1 ])
{
logerror( "shrike_sprite_select_w( 0x%02x )\n", data );
space->machine().primary_screen->update_partial(space->machine().primary_screen->vpos() - 1 + BALSENTE_VBEND);
state->m_sprite_data = state->m_sprite_bank[(data & 0x80 >> 7) ^ 1];
}
shrike_shared_6809_w( space, 1, data );
}
/*************************************
*
* Sprite drawing
*
*************************************/
static void draw_one_sprite(running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect, UINT8 *sprite)
{
balsente_state *state = machine.driver_data<balsente_state>();
int flags = sprite[0];
int image = sprite[1] | ((flags & 7) << 8);
int ypos = sprite[2] + 17 + BALSENTE_VBEND;
int xpos = sprite[3];
UINT8 *src;
int x, y;
/* get a pointer to the source image */
src = &state->m_sprite_data[(64 * image) & state->m_sprite_mask];
if (flags & 0x80) src += 4 * 15;
/* loop over y */
for (y = 0; y < 16; y++, ypos = (ypos + 1) & 255)
{
if (ypos >= (16 + BALSENTE_VBEND) && ypos >= cliprect->min_y && ypos <= cliprect->max_y)
{
const pen_t *pens = &machine.pens[state->m_palettebank_vis * 256];
UINT8 *old = &state->m_expanded_videoram[(ypos - BALSENTE_VBEND) * 256 + xpos];
int currx = xpos;
/* standard case */
if (!(flags & 0x40))
{
/* loop over x */
for (x = 0; x < 4; x++, old += 2)
{
int ipixel = *src++;
int left = ipixel & 0xf0;
int right = (ipixel << 4) & 0xf0;
/* left pixel, combine with the background */
if (left && currx >= 0 && currx < 256)
*BITMAP_ADDR16(bitmap, ypos, currx) = pens[left | old[0]];
currx++;
/* right pixel, combine with the background */
if (right && currx >= 0 && currx < 256)
*BITMAP_ADDR16(bitmap, ypos, currx) = pens[right | old[1]];
currx++;
}
}
/* hflip case */
else
{
src += 4;
/* loop over x */
for (x = 0; x < 4; x++, old += 2)
{
int ipixel = *--src;
int left = (ipixel << 4) & 0xf0;
int right = ipixel & 0xf0;
/* left pixel, combine with the background */
if (left && currx >= 0 && currx < 256)
*BITMAP_ADDR16(bitmap, ypos, currx) = pens[left | old[0]];
currx++;
/* right pixel, combine with the background */
if (right && currx >= 0 && currx < 256)
*BITMAP_ADDR16(bitmap, ypos, currx) = pens[right | old[1]];
currx++;
}
src += 4;
}
}
else
src += 4;
if (flags & 0x80) src -= 2 * 4;
}
}
/*************************************
*
* Main screen refresh
*
*************************************/
SCREEN_UPDATE( balsente )
{
balsente_state *state = screen->machine().driver_data<balsente_state>();
const pen_t *pens = &screen->machine().pens[state->m_palettebank_vis * 256];
int y, i;
/* draw scanlines from the VRAM directly */
for (y = cliprect->min_y; y <= cliprect->max_y; y++)
draw_scanline8(bitmap, 0, y, 256, &state->m_expanded_videoram[(y - BALSENTE_VBEND) * 256], pens);
/* draw the sprite images */
for (i = 0; i < 40; i++)
draw_one_sprite(screen->machine(), bitmap, cliprect, &state->m_spriteram[(0xe0 + i * 4) & 0xff]);
return 0;
}