/*************************************************************************** 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(); /* 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(); /* 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(); /* 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(); 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(); 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(); 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; }