summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/fuukifg2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/fuukifg2.c')
-rw-r--r--src/mame/video/fuukifg2.c353
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;
+}