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

  TIA-MC1 video hardware

  driver by Eugene Sandulenko
  special thanks to Shiru for his standalone emulator and documentation

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

#include "emu.h"
#include "includes/tiamc1.h"


WRITE8_HANDLER( tiamc1_videoram_w )
{
	tiamc1_state *state = space->machine().driver_data<tiamc1_state>();
	if(!(state->m_layers_ctrl & 2))
		state->m_charram[offset + 0x0000] = data;
	if(!(state->m_layers_ctrl & 4))
		state->m_charram[offset + 0x0800] = data;
	if(!(state->m_layers_ctrl & 8))
		state->m_charram[offset + 0x1000] = data;
	if(!(state->m_layers_ctrl & 16))
		state->m_charram[offset + 0x1800] = data;

	if ((state->m_layers_ctrl & (16|8|4|2)) != (16|8|4|2))
		gfx_element_mark_dirty(space->machine().gfx[0], (offset / 8) & 0xff);

	if(!(state->m_layers_ctrl & 1)) {
		state->m_tileram[offset] = data;
		if (offset < 1024)
			tilemap_mark_tile_dirty(state->m_bg_tilemap1, offset & 0x3ff);
		else
			tilemap_mark_tile_dirty(state->m_bg_tilemap2, offset & 0x3ff);
	}
}

WRITE8_HANDLER( tiamc1_bankswitch_w )
{
	tiamc1_state *state = space->machine().driver_data<tiamc1_state>();
	if ((data & 128) != (state->m_layers_ctrl & 128))
		tilemap_mark_all_tiles_dirty_all(space->machine());

	state->m_layers_ctrl = data;
}

WRITE8_HANDLER( tiamc1_sprite_x_w )
{
	tiamc1_state *state = space->machine().driver_data<tiamc1_state>();
	state->m_spriteram_x[offset] = data;
}

WRITE8_HANDLER( tiamc1_sprite_y_w )
{
	tiamc1_state *state = space->machine().driver_data<tiamc1_state>();
	state->m_spriteram_y[offset] = data;
}

WRITE8_HANDLER( tiamc1_sprite_a_w )
{
	tiamc1_state *state = space->machine().driver_data<tiamc1_state>();
	state->m_spriteram_a[offset] = data;
}

WRITE8_HANDLER( tiamc1_sprite_n_w )
{
	tiamc1_state *state = space->machine().driver_data<tiamc1_state>();
	state->m_spriteram_n[offset] = data;
}

WRITE8_HANDLER( tiamc1_bg_vshift_w )
{
	tiamc1_state *state = space->machine().driver_data<tiamc1_state>();
	state->m_bg_vshift = data;
}

WRITE8_HANDLER( tiamc1_bg_hshift_w )
{
	tiamc1_state *state = space->machine().driver_data<tiamc1_state>();
	state->m_bg_hshift = data;
}

WRITE8_HANDLER( tiamc1_palette_w )
{
	tiamc1_state *state = space->machine().driver_data<tiamc1_state>();
	palette_set_color(space->machine(), offset, state->m_palette[data]);
}

PALETTE_INIT( tiamc1 )
{
	tiamc1_state *state = machine.driver_data<tiamc1_state>();
	// Voltage computed by Proteus
	//static const float g_v[8]={1.05f,0.87f,0.81f,0.62f,0.44f,0.25f,0.19f,0.00f};
	//static const float r_v[8]={1.37f,1.13f,1.00f,0.75f,0.63f,0.38f,0.25f,0.00f};
	//static const float b_v[4]={1.16f,0.75f,0.42f,0.00f};

	// Voltage adjusted by Shiru
	static const float g_v[8] = { 1.2071f,0.9971f,0.9259f,0.7159f,0.4912f,0.2812f,0.2100f,0.0000f};
	static const float r_v[8] = { 1.5937f,1.3125f,1.1562f,0.8750f,0.7187f,0.4375f,0.2812f,0.0000f};
	static const float b_v[4] = { 1.3523f,0.8750f,0.4773f,0.0000f};

	int col;
	int r, g, b, ir, ig, ib;
	float tcol;

	state->m_palette = auto_alloc_array(machine, rgb_t, 256);

	for (col = 0; col < 256; col++) {
		ir = (col >> 3) & 7;
		ig = col & 7;
		ib = (col >> 6) & 3;
		tcol = 255.0f * r_v[ir] / r_v[0];
		r = 255 - (((int)tcol) & 255);
		tcol = 255.0f * g_v[ig] / g_v[0];
		g = 255 - (((int)tcol) & 255);
		tcol = 255.0f * b_v[ib] / b_v[0];
		b = 255 - (((int)tcol) & 255);

		state->m_palette[col] = MAKE_RGB(r,g,b);
	}
}

static TILE_GET_INFO( get_bg1_tile_info )
{
	tiamc1_state *state = machine.driver_data<tiamc1_state>();
	SET_TILE_INFO(0, state->m_tileram[tile_index], 0, 0);
}

static TILE_GET_INFO( get_bg2_tile_info )
{
	tiamc1_state *state = machine.driver_data<tiamc1_state>();
	SET_TILE_INFO(0, state->m_tileram[tile_index + 1024], 0, 0);
}

VIDEO_START( tiamc1 )
{
	tiamc1_state *state = machine.driver_data<tiamc1_state>();
	UINT8 *video_ram;

	video_ram = auto_alloc_array_clear(machine, UINT8, 0x3040);

        state->m_charram = video_ram + 0x0800;     /* Ram is banked */
        state->m_tileram = video_ram + 0x0000;

	state->m_spriteram_y = video_ram + 0x3000;
	state->m_spriteram_x = video_ram + 0x3010;
	state->m_spriteram_n = video_ram + 0x3020;
	state->m_spriteram_a = video_ram + 0x3030;

	state_save_register_global_pointer(machine, video_ram, 0x3040);

	state->m_bg_tilemap1 = tilemap_create(machine, get_bg1_tile_info, tilemap_scan_rows,
		 8, 8, 32, 32);

	state->m_bg_tilemap2 = tilemap_create(machine, get_bg2_tile_info, tilemap_scan_rows,
		 8, 8, 32, 32);

	state->m_bg_vshift = 0;
	state->m_bg_hshift = 0;

	state_save_register_global(machine, state->m_layers_ctrl);
	state_save_register_global(machine, state->m_bg_vshift);
	state_save_register_global(machine, state->m_bg_hshift);

	gfx_element_set_source(machine.gfx[0], state->m_charram);
}

static void draw_sprites(running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect)
{
	tiamc1_state *state = machine.driver_data<tiamc1_state>();
	int offs;

	for (offs = 0; offs < 16; offs++)
	{
		int flipx, flipy, sx, sy, spritecode;

		sx = state->m_spriteram_x[offs] ^ 0xff;
		sy = state->m_spriteram_y[offs] ^ 0xff;
		flipx = !(state->m_spriteram_a[offs] & 0x08);
		flipy = !(state->m_spriteram_a[offs] & 0x02);
		spritecode = state->m_spriteram_n[offs] ^ 0xff;

		if (!(state->m_spriteram_a[offs] & 0x01))
			drawgfx_transpen(bitmap, cliprect, machine.gfx[1],
				spritecode,
				0,
				flipx, flipy,
				sx, sy, 15);
	}
}

SCREEN_UPDATE( tiamc1 )
{
	tiamc1_state *state = screen->machine().driver_data<tiamc1_state>();
#if 0
	int i;

	for (i = 0; i < 32; i++)
	{
		tilemap_set_scrolly(state->m_bg_tilemap1, i, state->m_bg_vshift ^ 0xff);
		tilemap_set_scrolly(state->m_bg_tilemap2, i, state->m_bg_vshift ^ 0xff);
	}

	for (i = 0; i < 32; i++)
	{
		tilemap_set_scrollx(state->m_bg_tilemap1, i, state->m_bg_hshift ^ 0xff);
		tilemap_set_scrollx(state->m_bg_tilemap2, i, state->m_bg_hshift ^ 0xff);
	}
#endif

	if (state->m_layers_ctrl & 0x80)
		tilemap_draw(bitmap, cliprect, state->m_bg_tilemap2, 0, 0);
	else
		tilemap_draw(bitmap, cliprect, state->m_bg_tilemap1, 0, 0);


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

	return 0;
}

