diff options
Diffstat (limited to 'src/mame/video/fuukifg2.c')
-rw-r--r-- | src/mame/video/fuukifg2.c | 353 |
1 files changed, 353 insertions, 0 deletions
diff --git a/src/mame/video/fuukifg2.c b/src/mame/video/fuukifg2.c new file mode 100644 index 00000000000..a86f99aa31e --- /dev/null +++ b/src/mame/video/fuukifg2.c @@ -0,0 +1,353 @@ +/*************************************************************************** + + -= Fuuki 16 Bit Games (FG-2) =- + + driver by Luca Elia (l.elia@tin.it) + c.f. Fuuki FG-3 + + + [ 4 Scrolling Layers ] + + [ Layer 0 ] [ Layer 1 ] [ Layers 2&3 (double-buffered) ] + + Tile Size: 16 x 16 x 4 16 x 16 x 8 8 x 8 x 4 + Layer Size (tiles): 64 x 32 64 x 32 64 x 32 + + [ 1024? Zooming Sprites ] + + Sprites are made of 16 x 16 x 4 tiles. Size can vary from 1 to 16 + tiles both horizontally and vertically. + There is zooming (from full size to half size) and 4 levels of + priority (wrt layers) + + * Note: the game does hardware assisted raster effects * + +***************************************************************************/ + +#include "driver.h" + +/* Variables that driver has access to: */ + +UINT16 *fuuki16_vram_0, *fuuki16_vram_1; +UINT16 *fuuki16_vram_2, *fuuki16_vram_3; +UINT16 *fuuki16_vregs, *fuuki16_priority, *fuuki16_unknown; + + +/*************************************************************************** + + + Tilemaps + + Offset: Bits: Value: + + 0.w Code + + 2.w fedc ba98 ---- ---- + ---- ---- 7--- ---- Flip Y + ---- ---- -6-- ---- Flip X + ---- ---- --54 3210 Color + + +***************************************************************************/ + +#define LAYER( _N_ ) \ +\ +static tilemap *tilemap_##_N_; \ +\ +static TILE_GET_INFO( get_tile_info_##_N_ ) \ +{ \ + UINT16 code = fuuki16_vram_##_N_[ 2 * tile_index + 0 ]; \ + UINT16 attr = fuuki16_vram_##_N_[ 2 * tile_index + 1 ]; \ + SET_TILE_INFO(1 + _N_, code, attr & 0x3f,TILE_FLIPYX( (attr >> 6) & 3 )); \ +} \ +\ +WRITE16_HANDLER( fuuki16_vram_##_N_##_w ) \ +{ \ + COMBINE_DATA(&fuuki16_vram_##_N_[offset]); \ + tilemap_mark_tile_dirty(tilemap_##_N_,offset/2); \ +} + +LAYER( 0 ) +LAYER( 1 ) +LAYER( 2 ) +LAYER( 3 ) + + +/*************************************************************************** + + + Video Hardware Init + + +***************************************************************************/ + +/* Not used atm, seems to be fine without clearing pens? */ +#if 0 +PALETTE_INIT( fuuki16 ) +{ + int pen; + + /* The game does not initialise the palette at startup. It should + be totally black */ + for (pen = 0; pen < machine->drv->total_colors; pen++) + palette_set_color(machine,pen,MAKE_RGB(0,0,0)); +} +#endif + +VIDEO_START( fuuki16 ) +{ + tilemap_0 = tilemap_create( get_tile_info_0, tilemap_scan_rows, + TILEMAP_TYPE_PEN, 16, 16, 64,32); + + tilemap_1 = tilemap_create( get_tile_info_1, tilemap_scan_rows, + TILEMAP_TYPE_PEN, 16, 16, 64,32); + + tilemap_2 = tilemap_create( get_tile_info_2, tilemap_scan_rows, + TILEMAP_TYPE_PEN, 8, 8, 64,32); + + tilemap_3 = tilemap_create( get_tile_info_3, tilemap_scan_rows, + TILEMAP_TYPE_PEN, 8, 8, 64,32); + + tilemap_set_transparent_pen(tilemap_0,0x0f); // 4 bits + tilemap_set_transparent_pen(tilemap_1,0xff); // 8 bits + tilemap_set_transparent_pen(tilemap_2,0x0f); // 4 bits + tilemap_set_transparent_pen(tilemap_3,0x0f); // 4 bits + + machine->gfx[2]->color_granularity=16; /* 256 colour tiles with palette selectable on 16 colour boundaries */ +} + + +/*************************************************************************** + + + Sprites Drawing + + Offset: Bits: Value: + + 0.w fedc ---- ---- ---- Number Of Tiles Along X - 1 + ---- b--- ---- ---- Flip X + ---- -a-- ---- ---- 1 = Don't Draw This Sprite + ---- --98 7654 3210 X (Signed) + + 2.w fedc ---- ---- ---- Number Of Tiles Along Y - 1 + ---- b--- ---- ---- Flip Y + ---- -a-- ---- ---- + ---- --98 7654 3210 Y (Signed) + + 4.w fedc ---- ---- ---- Zoom X ($0 = Full Size, $F = Half Size) + ---- ba98 ---- ---- Zoom Y "" + ---- ---- 76-- ---- Priority + ---- ---- --54 3210 Color + + 6.w Code + + +***************************************************************************/ + +static void draw_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect) +{ + int offs; + + int max_x = machine->screen[0].visarea.max_x+1; + int max_y = machine->screen[0].visarea.max_y+1; + + /* Draw them backwards, for pdrawgfx */ + for ( offs = (spriteram_size-8)/2; offs >=0; offs -= 8/2 ) + { + int x, y, xstart, ystart, xend, yend, xinc, yinc; + int xnum, ynum, xzoom, yzoom, flipx, flipy; + int pri_mask; + + int sx = spriteram16[offs + 0]; + int sy = spriteram16[offs + 1]; + int attr = spriteram16[offs + 2]; + int code = spriteram16[offs + 3]; + + if (sx & 0x400) continue; + + flipx = sx & 0x0800; + flipy = sy & 0x0800; + + xnum = ((sx >> 12) & 0xf) + 1; + ynum = ((sy >> 12) & 0xf) + 1; + + xzoom = 16*8 - (8 * ((attr >> 12) & 0xf))/2; + yzoom = 16*8 - (8 * ((attr >> 8) & 0xf))/2; + + switch( (attr >> 6) & 3 ) + { + case 3: pri_mask = 0xf0|0xcc|0xaa; break; // behind all layers + case 2: pri_mask = 0xf0|0xcc; break; // behind fg + middle layer + case 1: pri_mask = 0xf0; break; // behind fg layer + case 0: + default: pri_mask = 0; // above all + } + + sx = (sx & 0x1ff) - (sx & 0x200); + sy = (sy & 0x1ff) - (sy & 0x200); + + if (flip_screen) + { flipx = !flipx; sx = max_x - sx - xnum * 16; + flipy = !flipy; sy = max_y - sy - ynum * 16; } + + if (flipx) { xstart = xnum-1; xend = -1; xinc = -1; } + else { xstart = 0; xend = xnum; xinc = +1; } + + if (flipy) { ystart = ynum-1; yend = -1; yinc = -1; } + else { ystart = 0; yend = ynum; yinc = +1; } + + for (y = ystart; y != yend; y += yinc) + { + for (x = xstart; x != xend; x += xinc) + { + if (xzoom == (16*8) && yzoom == (16*8)) + pdrawgfx( bitmap,machine->gfx[0], + code++, + attr & 0x3f, + flipx, flipy, + sx + x * 16, sy + y * 16, + cliprect,TRANSPARENCY_PEN,15, + pri_mask ); + else + pdrawgfxzoom( bitmap,machine->gfx[0], + code++, + attr & 0x3f, + flipx, flipy, + sx + (x * xzoom) / 8, sy + (y * yzoom) / 8, + cliprect,TRANSPARENCY_PEN,15, + (0x10000/0x10/8) * (xzoom + 8),(0x10000/0x10/8) * (yzoom + 8), // nearest greater integer value to avoid holes + pri_mask ); + } + } + +#ifdef MAME_DEBUG +#if 0 +if (input_code_pressed(KEYCODE_X)) +{ /* Display some info on each sprite */ + char buf[10]; + sprintf(buf, "%Xx%X %X",xnum,ynum,(attr>>6)&3); + ui_draw_text(buf, sx, sy); +} +#endif +#endif + } +} + + +/*************************************************************************** + + + Screen Drawing + + Video Registers (fuuki16_vregs): + + 00.w Layer 0 Scroll Y + 02.w Layer 0 Scroll X + 04.w Layer 1 Scroll Y + 06.w Layer 1 Scroll X + 08.w Layer 2 Scroll Y + 0a.w Layer 2 Scroll X + 0c.w Layers Y Offset + 0e.w Layers X Offset + + 10-1a.w ? 0 + 1c.w Trigger a level 5 irq on this raster line + 1e.w ? $3390/$3393 (Flip Screen Off/On), $0040 is buffer for tilemap 2 or 3 + + Priority Register (fuuki16_priority): + + fedc ba98 7654 3--- + ---- ---- ---- -210 Layer Order + + + Unknown Registers (fuuki16_unknown): + + 00.w ? $0200/$0201 (Flip Screen Off/On) + 02.w ? $f300/$0330 + +***************************************************************************/ + +/* Wrapper to handle bg and bg2 ttogether */ +static void fuuki16_draw_layer(mame_bitmap *bitmap, const rectangle *cliprect, int i, int flag, int pri) +{ + int buffer = (fuuki16_vregs[0x1e/2] & 0x40); + + switch( i ) + { + case 2: if (buffer) tilemap_draw(bitmap,cliprect,tilemap_3,flag,pri); + else tilemap_draw(bitmap,cliprect,tilemap_2,flag,pri); + return; + case 1: tilemap_draw(bitmap,cliprect,tilemap_1,flag,pri); + return; + case 0: tilemap_draw(bitmap,cliprect,tilemap_0,flag,pri); + return; + } +} + +VIDEO_UPDATE( fuuki16 ) +{ + UINT16 layer0_scrollx, layer0_scrolly; + UINT16 layer1_scrollx, layer1_scrolly; + UINT16 layer2_scrollx, layer2_scrolly; + UINT16 scrollx_offs, scrolly_offs; + + /* + It's not independant bits causing layers to switch, that wouldn't make sense with 3 bits. + See fuukifg3 for more justification + */ + + int tm_back, tm_middle, tm_front; + static const int pri_table[6][3] = { + { 0, 1, 2 }, + { 0, 2, 1 }, + { 1, 0, 2 }, + { 1, 2, 0 }, + { 2, 0, 1 }, + { 2, 1, 0 }}; + + tm_front = pri_table[ fuuki16_priority[0] & 0x0f ][0]; + tm_middle = pri_table[ fuuki16_priority[0] & 0x0f ][1]; + tm_back = pri_table[ fuuki16_priority[0] & 0x0f ][2]; + + flip_screen_set(fuuki16_vregs[0x1e/2] & 1); + + /* Layers scrolling */ + + scrolly_offs = fuuki16_vregs[0xc/2] - (flip_screen ? 0x103 : 0x1f3); + scrollx_offs = fuuki16_vregs[0xe/2] - (flip_screen ? 0x2a7 : 0x3f6); + + layer0_scrolly = fuuki16_vregs[0x0/2] + scrolly_offs; + layer0_scrollx = fuuki16_vregs[0x2/2] + scrollx_offs; + layer1_scrolly = fuuki16_vregs[0x4/2] + scrolly_offs; + layer1_scrollx = fuuki16_vregs[0x6/2] + scrollx_offs; + + layer2_scrolly = fuuki16_vregs[0x8/2]; + layer2_scrollx = fuuki16_vregs[0xa/2]; + + tilemap_set_scrollx(tilemap_0, 0, layer0_scrollx); + tilemap_set_scrolly(tilemap_0, 0, layer0_scrolly); + tilemap_set_scrollx(tilemap_1, 0, layer1_scrollx); + tilemap_set_scrolly(tilemap_1, 0, layer1_scrolly); + + tilemap_set_scrollx(tilemap_2, 0, layer2_scrollx + 0x10); + tilemap_set_scrolly(tilemap_2, 0, layer2_scrolly /*+ 0x02*/); + tilemap_set_scrollx(tilemap_3, 0, layer2_scrollx + 0x10); + tilemap_set_scrolly(tilemap_3, 0, layer2_scrolly /*+ 0x02*/); + + /* The backmost tilemap decides the background color(s) but sprites can + go below the opaque pixels of that tilemap. We thus need to mark the + transparent pixels of this layer with a different priority value */ +// fuuki16_draw_layer(bitmap,cliprect, tm_back, TILEMAP_DRAW_OPAQUE, 0); + + /* Actually, bg colour is simply the last pen i.e. 0x1fff -pjp */ + fillbitmap(bitmap,(0x800*4)-1,cliprect); + fillbitmap(priority_bitmap,0,cliprect); + + fuuki16_draw_layer(bitmap,cliprect, tm_back, 0, 1); + fuuki16_draw_layer(bitmap,cliprect, tm_middle, 0, 2); + fuuki16_draw_layer(bitmap,cliprect, tm_front, 0, 4); + + draw_sprites(machine, bitmap, cliprect); + + return 0; +} |