#include "driver.h"


// how the starfield ROM is interpreted: 0=256x256x1 linear bitmap, 1=8x8x1x1024 tilemap
#define STARS_LAYOUT 1

// scroll speed of the stars: 1=normal, 2=half, 3=one-third...etc.(possitive integers only)
#define SCROLL_SPEED 1


UINT8 *aeroboto_videoram;
UINT8 *aeroboto_hscroll, *aeroboto_vscroll, *aeroboto_tilecolor;
UINT8 *aeroboto_starx, *aeroboto_stary, *aeroboto_bgcolor;

static int aeroboto_charbank, aeroboto_starsoff;

static tilemap *bg_tilemap;

/***************************************************************************

  Callbacks for the TileMap code

***************************************************************************/

static TILE_GET_INFO( get_tile_info )
{
	UINT8 code = aeroboto_videoram[tile_index];
	SET_TILE_INFO(
			0,
			code + (aeroboto_charbank << 8),
			aeroboto_tilecolor[code],
			(aeroboto_tilecolor[code] >= 0x33) ? 0 : TILE_FORCE_LAYER0);
}
// transparency should only affect tiles with color 0x33 or higher


/***************************************************************************

  Start the video hardware emulation.

***************************************************************************/

VIDEO_START( aeroboto )
{
	bg_tilemap = tilemap_create(machine, get_tile_info,tilemap_scan_rows,8,8,32,64);

	tilemap_set_transparent_pen(bg_tilemap,0);

	tilemap_set_scroll_rows(bg_tilemap,64);

    state_save_register_global(machine, aeroboto_charbank);
    state_save_register_global(machine, aeroboto_starsoff);

	#if STARS_LAYOUT
	{
		UINT8 *rom, *temp;
		int i, length;

		rom = memory_region(machine, "gfx2");
		length = memory_region_length(machine, "gfx2");
		temp = malloc_or_die(length);
		memcpy(temp, rom, length);

		for (i=0; i<length; i++) rom[(i&~0xff)+(i<<5&0xe0)+(i>>3&0x1f)] = temp[i];

		free(temp);
	}
	#endif
}



/***************************************************************************

  Memory handlers

***************************************************************************/

READ8_HANDLER( aeroboto_in0_r )
{
	return input_port_read(space->machine, flip_screen_get(space->machine) ? "P2" : "P1");
}

WRITE8_HANDLER( aeroboto_3000_w )
{
	/* bit 0 selects both flip screen and player1/player2 controls */
	flip_screen_set(space->machine, data & 0x01);

	/* bit 1 = char bank select */
	if (aeroboto_charbank != ((data & 0x02) >> 1))
	{
		tilemap_mark_all_tiles_dirty(bg_tilemap);
		aeroboto_charbank = (data & 0x02) >> 1;
	}

	/* bit 2 = disable star field? */
	aeroboto_starsoff = data & 0x4;
}

WRITE8_HANDLER( aeroboto_videoram_w )
{
	aeroboto_videoram[offset] = data;
	tilemap_mark_tile_dirty(bg_tilemap,offset);
}

WRITE8_HANDLER( aeroboto_tilecolor_w )
{
	if (aeroboto_tilecolor[offset] != data)
	{
		aeroboto_tilecolor[offset] = data;
		tilemap_mark_all_tiles_dirty(bg_tilemap);
	}
}



/***************************************************************************

  Display refresh

***************************************************************************/

static void draw_sprites(running_machine *machine, bitmap_t *bitmap, const rectangle *cliprect)
{
	int offs;

	for (offs = 0;offs < spriteram_size;offs += 4)
	{
		int x = spriteram[offs+3];
		int y = 240 - spriteram[offs];

		if (flip_screen_get(machine))
		{
			x = 248 - x;
			y = 240 - y;
		}

		drawgfx(bitmap, machine->gfx[1],
				spriteram[offs+1],
				spriteram[offs+2] & 0x07,
				flip_screen_get(machine), flip_screen_get(machine),
				((x + 8) & 0xff) - 8, y,
				cliprect, TRANSPARENCY_PEN, 0);
	}
}


VIDEO_UPDATE( aeroboto )
{
	static const rectangle splitrect1 = { 0, 255, 0, 39 };
	static const rectangle splitrect2 = { 0, 255, 40, 255 };
	static int sx=0, sy=0;
	static UINT8 ox=0, oy=0;
	UINT8 *src_base, *src_colptr, *src_rowptr;
	int src_offsx, src_colmask, sky_color, star_color, x, y, i, j, pen;

	sky_color = star_color = *aeroboto_bgcolor << 2;

	// the star field is supposed to be seen through tile pen 0 when active
	if (!aeroboto_starsoff)
	{
		if (star_color < 0xd0) { star_color = 0xd0; sky_color = 0; }
		star_color += 2;

		bitmap_fill(bitmap, cliprect, sky_color);

		// actual scroll speed is unknown but it can be adjusted by changing the SCROLL_SPEED constant
		sx += (char)(*aeroboto_starx - ox);
		ox = *aeroboto_starx;
		x = sx / SCROLL_SPEED;

		if (*aeroboto_vscroll != 0xff) sy += (char)(*aeroboto_stary - oy);
		oy = *aeroboto_stary;
		y = sy / SCROLL_SPEED;

		src_base = memory_region(screen->machine, "gfx2");

		for (i=0; i<256; i++)
		{
			src_offsx = (x + i) & 0xff;
			src_colmask = 1 << (src_offsx & 7);
			src_offsx >>= 3;
			src_colptr = src_base + src_offsx;
			pen = star_color + ((i + 8) >> 4 & 1);

			for (j=0; j<256; j++)
			{
				src_rowptr = src_colptr + (((y + j) & 0xff) << 5 );
				if (!((unsigned)*src_rowptr & src_colmask)) *BITMAP_ADDR16(bitmap, j, i) = pen;
			}
		}
	}
	else
	{
		sx = ox = *aeroboto_starx;
		sy = oy = *aeroboto_stary;
		bitmap_fill(bitmap, cliprect, sky_color);
	}

	for (y = 0;y < 64; y++)
		tilemap_set_scrollx(bg_tilemap,y,aeroboto_hscroll[y]);

	// the playfield is part of a splitscreen and should not overlap with status display
	tilemap_set_scrolly(bg_tilemap,0,*aeroboto_vscroll);
	tilemap_draw(bitmap,&splitrect2,bg_tilemap,0,0);

	draw_sprites(screen->machine,bitmap,cliprect);

	// the status display behaves more closely to a 40-line splitscreen than an overlay
	tilemap_set_scrolly(bg_tilemap,0,0);
	tilemap_draw(bitmap,&splitrect1,bg_tilemap,0,0);
	return 0;
}
