/***************************************************************************
-= Afega Games =-
driver by Luca Elia (l.elia@tin.it)
Note: if MAME_DEBUG is defined, pressing Z with:
Q / W Shows Layer 0 / 1
A Shows Sprites
Keys can be used together!
[ 2 Layers ]
[ Layer 0 ] [ Layer 1 ]
Tile Size: 16 x 16 x 4/8 8 x 8 x 4
Layer Size (pixels): 1024 x 1024 256 x 256
Layer Size (tiles): 64 x 64 32 x 32
Scrolling: Yes No
The layout is a bit weird. 16 consecutive tile codes define a
vertical column. 16 columns form a page (256 x 256).
Layer 0 is made of 4 x 4 pages. Layer 1 of just 1 page.
[ 256 Sprites ]
Sprites are made of 16 x 16 x 4 tiles. Size can vary from 1 to 16
tiles both horizontally and vertically.
Is there zooming ?
[ Priorities ]
The game only uses this scheme:
Back -> Front: Layer 0, Sprites, Layer 1
***************************************************************************/
#include "driver.h"
#ifdef MAME_DEBUG
#include "ui.h"
#endif
/* Variables needed by drivers: */
UINT16 *afega_vram_0, *afega_scroll_0;
UINT16 *afega_vram_1, *afega_scroll_1;
/***************************************************************************
Palette - RRRRGGGGBBBB????
***************************************************************************/
WRITE16_HANDLER( afega_palette_w )
{
int r,g,b;
data = COMBINE_DATA(&paletteram16[offset]);
b = ((data & 0x00F0) >> 3 ) + ((data & 0x0002) >> 1);
g = ((data & 0x0F00) >> 7 ) + ((data & 0x0004) >> 2);
r = ((data & 0xF000) >> 11) + ((data & 0x0008) >> 3);
palette_set_color_rgb( Machine, offset, pal5bit(r) , pal5bit(g) , pal5bit(b) );
}
/* This game uses 8 bit tiles, so it ignores the color codes and just
uses the same 256 colors for every tile */
PALETTE_INIT( grdnstrm )
{
int color, pen;
for( color = 0; color < 16; color++ )
for( pen = 0; pen < 256; pen++ )
colortable[color * 256 + pen + 256*3] = 256*0 + pen;
}
/***************************************************************************
Tilemaps
Offset: Bits: Value:
2.w fedc ---- ---- ---- Color
---- ba98 7654 3210 Code
***************************************************************************/
#define TILES_PER_PAGE_X (0x10)
#define TILES_PER_PAGE_Y (0x10)
#define PAGES_PER_TMAP_X (0x4)
#define PAGES_PER_TMAP_Y (0x4)
#define FIREHAWK_PAGES_PER_TMAP_X (0x1)
#define FIREHAWK_PAGES_PER_TMAP_Y (0x1)
#define TWINACTN_TILES_PER_PAGE_X (0x100)
#define TWINACTN_TILES_PER_PAGE_Y (0x10)
#define TWINACTN_PAGES_PER_TMAP_X (0x1)
#define TWINACTN_PAGES_PER_TMAP_Y (0x1)
static TILEMAP_MAPPER( afega_tilemap_scan_pages )
{
return (row / TILES_PER_PAGE_Y) * TILES_PER_PAGE_X * TILES_PER_PAGE_Y * PAGES_PER_TMAP_X +
(row % TILES_PER_PAGE_Y) +
(col / TILES_PER_PAGE_X) * TILES_PER_PAGE_X * TILES_PER_PAGE_Y +
(col % TILES_PER_PAGE_X) * TILES_PER_PAGE_Y;
}
static TILEMAP_MAPPER( twinactn_tilemap_scan_pages )
{
return (row / TWINACTN_TILES_PER_PAGE_Y) * TWINACTN_TILES_PER_PAGE_X * TWINACTN_TILES_PER_PAGE_Y * TWINACTN_PAGES_PER_TMAP_X +
(row % TWINACTN_TILES_PER_PAGE_Y) +
(col / TWINACTN_TILES_PER_PAGE_X) * TWINACTN_TILES_PER_PAGE_X * TWINACTN_TILES_PER_PAGE_Y +
(col % TWINACTN_TILES_PER_PAGE_X) * TWINACTN_TILES_PER_PAGE_Y;
}
static TILEMAP_MAPPER( firehawk_tilemap_scan_pages )
{
return (row / TILES_PER_PAGE_Y) * TILES_PER_PAGE_X * TILES_PER_PAGE_Y * FIREHAWK_PAGES_PER_TMAP_X +
(row % TILES_PER_PAGE_Y) +
(col / TILES_PER_PAGE_X) * TILES_PER_PAGE_X * TILES_PER_PAGE_Y +
(col % TILES_PER_PAGE_X) * TILES_PER_PAGE_Y;
}
static tilemap *tilemap_0, *tilemap_1;
static TILE_GET_INFO( get_tile_info_0 )
{
UINT16 code = afega_vram_0[tile_index];
SET_TILE_INFO(
1,
code,
(code & 0xf000) >> 12,
0);
}
static TILE_GET_INFO( get_tile_info_1 )
{
UINT16 code = afega_vram_1[tile_index];
SET_TILE_INFO(
2,
code,
(code & 0xf000) >> 12,
0);
}
WRITE16_HANDLER( afega_vram_0_w )
{
COMBINE_DATA(&afega_vram_0[offset]);
tilemap_mark_tile_dirty(tilemap_0,offset);
}
WRITE16_HANDLER( afega_vram_1_w )
{
COMBINE_DATA(&afega_vram_1[offset]);
tilemap_mark_tile_dirty(tilemap_1,offset);
}
/***************************************************************************
Video Hardware Init
***************************************************************************/
VIDEO_START( afega )
{
tilemap_0 = tilemap_create( get_tile_info_0, afega_tilemap_scan_pages,
TILEMAP_TYPE_PEN,
16,16,
TILES_PER_PAGE_X*PAGES_PER_TMAP_X,TILES_PER_PAGE_Y*PAGES_PER_TMAP_Y);
tilemap_1 = tilemap_create( get_tile_info_1, tilemap_scan_cols,
TILEMAP_TYPE_PEN,
8,8,
32,32);
tilemap_set_transparent_pen(tilemap_1,0xf);
}
VIDEO_START( twinactn )
{
tilemap_0 = tilemap_create( get_tile_info_0, twinactn_tilemap_scan_pages,
TILEMAP_TYPE_PEN,
16,16,
TWINACTN_TILES_PER_PAGE_X*TWINACTN_PAGES_PER_TMAP_X,TWINACTN_TILES_PER_PAGE_Y*TWINACTN_PAGES_PER_TMAP_Y);
tilemap_1 = tilemap_create( get_tile_info_1, tilemap_scan_cols,
TILEMAP_TYPE_PEN,
8,8,
32,32);
tilemap_set_transparent_pen(tilemap_1,0xf);
}
VIDEO_START( firehawk )
{
tilemap_0 = tilemap_create( get_tile_info_0, firehawk_tilemap_scan_pages,
TILEMAP_TYPE_PEN,
16,16,
TILES_PER_PAGE_X*FIREHAWK_PAGES_PER_TMAP_X,TILES_PER_PAGE_Y*FIREHAWK_PAGES_PER_TMAP_Y);
tilemap_1 = tilemap_create( get_tile_info_1, tilemap_scan_cols,
TILEMAP_TYPE_PEN,
8,8,
32,32);
tilemap_set_transparent_pen(tilemap_1,0xf);
}
/***************************************************************************
Sprites Drawing
Offset: Bits: Value:
0.w fedc ba-- ---- ----
---- --9- ---- ---- Flip Y?
---- ---8 7654 3---
---- --------- -21- Priority?
---- ---- ---- ---0 1 = Draw This Sprite
2.w fedc ba98 ---- ----
---- ---- 7654 ---- Number Of Tiles Along Y - 1
---- ---- ---- 3210 Number Of Tiles Along X - 1
4.w
6.w Code
8.w fedc ba98 ---- ----
---- ---- 7654 3210 X (Signed)
A.w
C.w fedc ba98 ---- ----
---- ---- 7654 3210 Y (Signed)
E.w fedc ba98 7654 ----
---- ---- ---- 3210 Color
***************************************************************************/
static void draw_sprites(running_machine *machine, mame_bitmap *bitmap,const rectangle *cliprect, UINT16 attr_mask)
{
int offs;
int max_x = machine->screen[0].width;
int max_y = machine->screen[0].height;
for ( offs = 0; offs < spriteram_size/2; offs += 16/2 )
{
int attr, dim, code, sx, sy, color, flipx, flipy;
int x, xnum, xstart, xend, xinc;
int y, ynum, ystart, yend, yinc;
attr = spriteram16[offs + 0x0/2];
if (!(attr & attr_mask)) continue;
dim = spriteram16[offs + 0x2/2];
code = spriteram16[offs + 0x6/2];
sx = spriteram16[offs + 0x8/2];
sy = spriteram16[offs + 0xc/2];
color = spriteram16[offs + 0xe/2];
flipx = attr & 0x000; // ?
flipy = attr & 0x000; // ?
xnum = ((dim >> 0) & 0xf) + 1;
ynum = ((dim >> 4) & 0xf) + 1;
sx = (sx & 0xff) - (sx & 0x100);
sy = (sy & 0xff) - (sy & 0x100);
if (flip_screen_x) { flipx = !flipx; sx = max_x - sx - xnum * 16; }
if (flip_screen_y) { 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)
{
drawgfx( bitmap,machine->gfx[0],
code++,
color,
flipx, flipy,
sx + x * 16, sy + y * 16,
cliprect,TRANSPARENCY_PEN,15 );
}
}
#ifdef MAME_DEBUG
#if 1
if (input_code_pressed(KEYCODE_X))
{ /* Display some info on each sprite */
char buf[10];
sprintf(buf, "%X",(spriteram16[offs + 0x0/2]&6)/2);
ui_draw_text(buf, sy, sx);
}
#endif
#endif
}
}
/***************************************************************************
Screen Drawing
***************************************************************************/
static void video_update(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect,
int dsw_flipscreen, // 1 = Horizontal and vertical screen flip are hardwired to 2 dip switches
int xoffset, int yoffset, // tilemap_0 offsets
int attr_mask // "sprite active" mask
)
{
int layers_ctrl = -1;
if (dsw_flipscreen)
{
flip_screen_x_set(~readinputport(2) & 0x0100);
flip_screen_y_set(~readinputport(2) & 0x0200);
}
tilemap_set_scrollx(tilemap_0, 0, afega_scroll_0[1] + xoffset);
tilemap_set_scrolly(tilemap_0, 0, afega_scroll_0[0] + yoffset);
tilemap_set_scrollx(tilemap_1, 0, afega_scroll_1[1]);
tilemap_set_scrolly(tilemap_1, 0, afega_scroll_1[0]);
#ifdef MAME_DEBUG
if ( input_code_pressed(KEYCODE_Z) )
{ int msk = 0;
if (input_code_pressed(KEYCODE_Q)) msk |= 1;
if (input_code_pressed(KEYCODE_W)) msk |= 2;
if (input_code_pressed(KEYCODE_A)) msk |= 4;
if (msk != 0) layers_ctrl &= msk; }
#endif
if (layers_ctrl & 1) tilemap_draw(bitmap,cliprect,tilemap_0,0,0);
else fillbitmap(bitmap,get_black_pen(machine),cliprect);
if (layers_ctrl & 4) draw_sprites(machine,bitmap,cliprect, attr_mask);
if (layers_ctrl & 2) tilemap_draw(bitmap,cliprect,tilemap_1,0,0);
}
VIDEO_UPDATE( afega ) { video_update(machine,bitmap,cliprect, 1, -0x100,+0x000, 0x0001); return 0; }
VIDEO_UPDATE( bubl2000 ) { video_update(machine,bitmap,cliprect, 0, -0x100,+0x000, 0x0001); return 0; } // no flipscreen support, I really would confirmation from the schematics
VIDEO_UPDATE( redhawkb ) { video_update(machine,bitmap,cliprect, 0, +0x000,+0x100, 0x0001); return 0; }
VIDEO_UPDATE( twinactn ) { video_update(machine,bitmap,cliprect, 0, +0x000,+0x000, 0x0100); return 0; }
VIDEO_UPDATE( firehawk )
{
tilemap_set_scrolly(tilemap_0, 0, afega_scroll_1[1] + 0x100);
tilemap_set_scrollx(tilemap_0, 0, afega_scroll_1[0]);
tilemap_draw(bitmap,cliprect,tilemap_0,0,0);
draw_sprites(machine,bitmap,cliprect,1);
tilemap_draw(bitmap,cliprect,tilemap_1,0,0);
return 0;
}