/***************************************************************************
Video Hardware for Blood Brothers
***************************************************************************/
#include "emu.h"
#include "includes/bloodbro.h"
/***************************************************************************
Callbacks for the TileMap code
***************************************************************************/
static TILE_GET_INFO( get_bg_tile_info )
{
bloodbro_state *state = machine.driver_data<bloodbro_state>();
int code = state->m_bgvideoram[tile_index];
SET_TILE_INFO(
1,
code & 0xfff,
(code >> 12),
0);
}
static TILE_GET_INFO( get_fg_tile_info )
{
bloodbro_state *state = machine.driver_data<bloodbro_state>();
int code = state->m_fgvideoram[tile_index];
SET_TILE_INFO(
2,
(code & 0xfff)+0x1000,
(code >> 12),
0);
}
static TILE_GET_INFO( get_tx_tile_info )
{
bloodbro_state *state = machine.driver_data<bloodbro_state>();
int code = state->m_txvideoram[tile_index];
SET_TILE_INFO(
0,
code & 0xfff,
code >> 12,
0);
}
/***************************************************************************
Start the video hardware emulation.
***************************************************************************/
VIDEO_START( bloodbro )
{
bloodbro_state *state = machine.driver_data<bloodbro_state>();
state->m_bg_tilemap = tilemap_create(machine, get_bg_tile_info,tilemap_scan_rows, 16,16,32,16);
state->m_fg_tilemap = tilemap_create(machine, get_fg_tile_info,tilemap_scan_rows,16,16,32,16);
state->m_tx_tilemap = tilemap_create(machine, get_tx_tile_info,tilemap_scan_rows, 8, 8,32,32);
tilemap_set_transparent_pen(state->m_fg_tilemap,15);
tilemap_set_transparent_pen(state->m_tx_tilemap,15);
}
/***************************************************************************
Memory handlers
***************************************************************************/
WRITE16_HANDLER( bloodbro_bgvideoram_w )
{
bloodbro_state *state = space->machine().driver_data<bloodbro_state>();
COMBINE_DATA(&state->m_bgvideoram[offset]);
tilemap_mark_tile_dirty(state->m_bg_tilemap,offset);
}
WRITE16_HANDLER( bloodbro_fgvideoram_w )
{
bloodbro_state *state = space->machine().driver_data<bloodbro_state>();
COMBINE_DATA(&state->m_fgvideoram[offset]);
tilemap_mark_tile_dirty(state->m_fg_tilemap,offset);
}
WRITE16_HANDLER( bloodbro_txvideoram_w )
{
bloodbro_state *state = space->machine().driver_data<bloodbro_state>();
COMBINE_DATA(&state->m_txvideoram[offset]);
tilemap_mark_tile_dirty(state->m_tx_tilemap,offset);
}
/***************************************************************************
Display refresh
Blood Bros / Skysmash Spriteram
-------------------------------
Slightly more sophisticated successor to the Toki sprite chip.
It has "big sprites" created by setting width or height >0. Tile
numbers are read consecutively.
+0 x....... ........ sprite disabled if set
+0 .x...... ........ Flip y (no evidence for this!!)
+0 ..x..... ........ Flip x
+0 ....x... ........ Priority (1=high)
+0 ......xx x....... Width: do this many tiles horizontally
+0 ........ .xxx.... Height: do this many tiles vertically
+0 ........ ....xxxx Color bank
+1 ...xxxxx xxxxxxxx Tile number
+2 .......x xxxxxxxx X coordinate
+3 .......x xxxxxxxx Y coordinate
Weststry Bootleg Spriteram
--------------------------
Lacks the "big sprite" feature of the original. Needs some
tile number remapping for some reason.
+0 .......x xxxxxxxx Sprite Y coordinate
+1 ...xxxxx xxxxxxxx Sprite tile number
+2 xxxx.... ........ Sprite color bank
+2 ......x. ........ Sprite flip x
+2 ........ x....... Priority ??
+3 .......x xxxxxxxx Sprite X coordinate
***************************************************************************/
/* SPRITE INFO (8 bytes)
D-F?P?SS SSSSCCCC
---TTTTT TTTTTTTT
-------X XXXXXXXX
-------- YYYYYYYY */
static void bloodbro_draw_sprites(running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect)
{
bloodbro_state *state = machine.driver_data<bloodbro_state>();
UINT16 *spriteram16 = state->m_spriteram;
int offs;
for (offs = 0;offs < state->m_spriteram_size/2;offs += 4)
{
int sx,sy,x,y,width,height,attributes,tile_number,color,flipx,flipy,pri_mask;
attributes = spriteram16[offs+0];
if (attributes & 0x8000) continue; /* disabled */
width = ((attributes>>7)&7);
height = ((attributes>>4)&7);
pri_mask = (attributes & 0x0800) ? 0x02 : 0;
tile_number = spriteram16[offs+1]&0x1fff;
sx = spriteram16[offs+2]&0x1ff;
sy = spriteram16[offs+3]&0x1ff;
if (sx >= 256) sx -= 512;
if (sy >= 256) sy -= 512;
flipx = attributes & 0x2000;
flipy = attributes & 0x4000; /* ?? */
color = attributes & 0xf;
for (x = 0;x <= width;x++)
{
for (y = 0;y <= height;y++)
{
pdrawgfx_transpen(bitmap,cliprect,machine.gfx[3],
tile_number++,
color,
flipx,flipy,
flipx ? (sx + 16*(width-x)) : (sx + 16*x),flipy ? (sy + 16*(height-y)) : (sy + 16*y),
machine.priority_bitmap,
pri_mask,15);
}
}
}
}
/* SPRITE INFO (8 bytes)
D------- YYYYYYYY
---TTTTT TTTTTTTT
CCCC--F? -?--???? Priority??
-------X XXXXXXXX
*/
static void weststry_draw_sprites(running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect)
{
bloodbro_state *state = machine.driver_data<bloodbro_state>();
UINT16 *spriteram16 = state->m_spriteram;
int offs;
/* TODO: the last two entries are not sprites - control registers? */
for (offs = 0;offs < state->m_spriteram_size/2 - 8;offs += 4)
{
int data = spriteram16[offs+2];
int data0 = spriteram16[offs+0];
int code = spriteram16[offs+1]&0x1fff;
int sx = spriteram16[offs+3]&0x1ff;
int sy = 0xf0-(data0&0xff);
int flipx = data & 0x200;
int flipy = data & 0x400; /* ??? */
int color = (data&0xf000)>>12;
int pri_mask = (data & 0x0080) ? 0x02 : 0;
if (sx >= 256) sx -= 512;
if (data0 & 0x8000) continue; /* disabled */
/* Remap code 0x800 <-> 0x1000 */
code = (code&0x7ff) | ((code&0x800)<<1) | ((code&0x1000)>>1);
pdrawgfx_transpen(bitmap,cliprect,machine.gfx[3],
code,
color,
flipx,flipy,
sx,sy,
machine.priority_bitmap,
pri_mask,15);
}
}
SCREEN_UPDATE( bloodbro )
{
bloodbro_state *state = screen->machine().driver_data<bloodbro_state>();
tilemap_set_scrollx(state->m_bg_tilemap,0,state->m_scroll[0x10]); /* ? */
tilemap_set_scrolly(state->m_bg_tilemap,0,state->m_scroll[0x11]); /* ? */
tilemap_set_scrollx(state->m_fg_tilemap,0,state->m_scroll[0x12]);
tilemap_set_scrolly(state->m_fg_tilemap,0,state->m_scroll[0x13]);
bitmap_fill(screen->machine().priority_bitmap,cliprect,0);
tilemap_draw(bitmap,cliprect,state->m_bg_tilemap,0,0);
tilemap_draw(bitmap,cliprect,state->m_fg_tilemap,0,1);
bloodbro_draw_sprites(screen->machine(),bitmap,cliprect);
tilemap_draw(bitmap,cliprect,state->m_tx_tilemap,0,0);
return 0;
}
SCREEN_UPDATE( weststry )
{
bloodbro_state *state = screen->machine().driver_data<bloodbro_state>();
// tilemap_set_scrollx(state->m_bg_tilemap,0,state->m_scroll[0x10]); /* ? */
// tilemap_set_scrolly(state->m_bg_tilemap,0,state->m_scroll[0x11]); /* ? */
// tilemap_set_scrollx(state->m_fg_tilemap,0,state->m_scroll[0x12]);
// tilemap_set_scrolly(state->m_fg_tilemap,0,state->m_scroll[0x13]);
bitmap_fill(screen->machine().priority_bitmap,cliprect,0);
tilemap_draw(bitmap,cliprect,state->m_bg_tilemap,0,0);
tilemap_draw(bitmap,cliprect,state->m_fg_tilemap,0,1);
weststry_draw_sprites(screen->machine(),bitmap,cliprect);
tilemap_draw(bitmap,cliprect,state->m_tx_tilemap,0,0);
return 0;
}
SCREEN_UPDATE( skysmash )
{
bloodbro_state *state = screen->machine().driver_data<bloodbro_state>();
tilemap_set_scrollx(state->m_bg_tilemap,0,state->m_scroll[0x08]);
tilemap_set_scrolly(state->m_bg_tilemap,0,state->m_scroll[0x09]); /* ? */
tilemap_set_scrollx(state->m_fg_tilemap,0,state->m_scroll[0x0a]);
tilemap_set_scrolly(state->m_fg_tilemap,0,state->m_scroll[0x0b]); /* ? */
bitmap_fill(screen->machine().priority_bitmap,cliprect,0);
tilemap_draw(bitmap,cliprect,state->m_bg_tilemap,0,0);
tilemap_draw(bitmap,cliprect,state->m_fg_tilemap,0,1);
bloodbro_draw_sprites(screen->machine(),bitmap,cliprect);
tilemap_draw(bitmap,cliprect,state->m_tx_tilemap,0,0);
return 0;
}