// license:BSD-3-Clause
// copyright-holders:Phil Stroffolino

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


TILE_GET_INFO_MEMBER(chinhero_state::get_bg_tile_info)
{
	int attributes = m_videoram[tile_index + 0x800];
	int tile_number = m_videoram[tile_index] + 0x100 * (attributes & 0x3);
	int color;

	if (m_gfx_type== 1)
	{
		/* Shanghai Kid:
		    ------xx    bank
		    -----x--    flipx
		    xxxxx---    color
		*/
		color = attributes >> 3;
		color = (color & 0x03) | ((color & 0x1c) << 1);
		tileinfo.set(0,
				tile_number,
				color,
				(attributes & 0x04) ? TILE_FLIPX : 0);
	}
	else
	{
		/* Chinese Hero:
		    ------xx    bank
		    -xxxxx--    color
		    x-------    flipx?
		*/
		color = (attributes >> 2) & 0x1f;
		tileinfo.set(0,
				tile_number,
				color,
				(attributes & 0x80) ? TILE_FLIPX : 0);
	}

	tileinfo.category = (memregion( "proms" )->base()[0x800 + color * 4] == 2) ? 1 : 0;
}

void chinhero_state::video_start()
{
	m_background = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(chinhero_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
}

void chinhero_state::videoram_w(offs_t offset, uint8_t data)
{
	m_videoram[offset] = data;
	m_background->mark_tile_dirty(offset & 0x7ff);
}

void chinhero_state::draw_sprite(const uint8_t *source, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	int transparent_pen;
	int bank_index;

	int ypos        = 209 - source[0];
	int tile        = source[1] & 0x3f;
	int xflip       = (source[1] & 0x40) ? 1 : 0;
	int yflip       = (source[1] & 0x80) ? 1 : 0;
	int bank        = source[2] & 0x3f;
	int xsize       = (source[2] & 0x40) ? 1 : 0;
	int ysize       = (source[2] & 0x80) ? 1 : 0;
	int yscale      = source[3] & 0x07;   // 0x0 = smallest; 0x7 = biggest
	int xpos        = ((source[4] + source[5] * 255) & 0x1ff) - 23;
	int color       = source[6] & 0x3f;
	int xscale      = source[7] & 0x07;   // 0x0 = smallest; 0x7 = biggest

	// adjust placement for small sprites
	if (xsize == 0 && xflip) xpos -= 16;
	if (ysize == 0 && yflip == 0) ypos += 16;

	if(m_gfx_type == 1)
	{
		// Shanghai Kid
		switch (bank & 0x30)
		{
		case 0x00:
		case 0x10:
			tile += 0x40 * (bank & 0xf);
			break;

		case 0x20:
			tile += 0x40 * ((bank & 0x3) | 0x10);
			break;

		case 0x30:
			tile += 0x40 * ((bank & 0x3) | 0x14);
			break;
		}
		bank_index = 0;
		transparent_pen = 3;
	}
	else
	{
		// Chinese Hero
		color >>= 1;

		// It's needed in level 7 to hide "bogus" sprites. Is it a sprite disable flag or an end sprite list flag?
		if (color == 0)
			return;

		switch (bank >> 2)
		{
		case 0x0: bank_index = 0; break;
		case 0x9: bank_index = 1; break;
		case 0x6: bank_index = 2; break;
		case 0xf: bank_index = 3; break;
		default:
			bank_index = 0;
			break;
		}

		if (bank & 0x01) tile += 0x40;

		transparent_pen = 7;
	}

	gfx_element *gfx = m_gfxdecode->gfx(1+bank_index);

	int width = (xscale + 1) * 2;
	int height = (yscale + 1) * 2;

	// center zoomed sprites
	xpos += (16 - width) * (xsize + 1) / 2;
	ypos += (16 - height) * (ysize + 1) / 2;

	for (int r = 0; r <= ysize; r++)
	{
		for (int c = 0; c <= xsize; c++)
		{
			int sx = xpos + (c ^ xflip) * width;
			int sy = ypos + (r ^ yflip) * height;

				gfx->zoom_transpen(
				bitmap,
				cliprect,
				tile + c * 8 + r,
				color,
				xflip,yflip,
				sx, sy,
				(width << 16) / 16, (height << 16) / 16, transparent_pen);

			// wrap around y

				gfx->zoom_transpen(
				bitmap,
				cliprect,
				tile + c * 8 + r,
				color,
				xflip, yflip,
				sx, sy + 256,
				(width << 16) / 16, (height << 16) / 16, transparent_pen);
		}
	}
}

void chinhero_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	const uint8_t *finish = m_spriteram;
	const uint8_t *source = &m_spriteram[0x200];
	while (source > finish)
	{
		source -= 8;
		draw_sprite(source, bitmap,cliprect);
	}
}

uint32_t chinhero_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	int flipscreen = m_videoreg[1] & 0x80;
	m_background->set_flip(flipscreen ? (TILEMAP_FLIPX | TILEMAP_FLIPY) : 0);
	m_background->set_scrollx(0, m_videoreg[0] - 40);
	m_background->set_scrolly(0, m_videoreg[2] + 0x10);

	m_background->draw(screen, bitmap, cliprect, 0, 0);
	draw_sprites(bitmap,cliprect);
	m_background->draw(screen, bitmap, cliprect, 1, 0); // high priority tiles
	return 0;
}


void dynamski_state::palette(palette_device &palette) const
{
	const uint8_t *color_prom = memregion("proms")->base();

	// create a lookup table for the palette
	for (int i = 0; i < 0x20; i++)
	{
		uint16_t const data = (color_prom[i | 0x20] << 8) | color_prom[i];
		rgb_t const color(pal5bit(data >> 1), pal5bit(data >> 6), pal5bit(data >> 11));

		palette.set_indirect_color(i, color);
	}

	// color_prom now points to the beginning of the lookup table
	color_prom += 0x40;

	// characters
	for (int i = 0; i < 0x40; i++)
	{
		uint8_t const ctabentry = color_prom[i] & 0x0f;
		palette.set_pen_indirect(i, ctabentry);
	}

	// sprites
	for (int i = 0; i < 0x40; i++)
	{
		uint8_t ctabentry = (color_prom[i + 0x100] & 0x0f) | 0x10;
		palette.set_pen_indirect(i + 0x40, ctabentry);
	}
}


void dynamski_state::draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect, int pri)
{
	for (int i = 0; i < 0x400; i++)
	{
		int sx = (i % 32) * 8;
		int sy = (i / 32) * 8;
		int temp;

		if (sy < 16)
		{
			temp = sx;
			sx = sy + 256 + 16;
			sy = temp;
		}
		else if (sy >= 256 - 16)
		{
			temp = sx;
			sx = sy - 256 + 16;
			sy = temp;
		}
		else
		{
			sx += 16;
		}

		int tile = m_videoram[i];
		int attr = m_videoram[i + 0x400];
		/*
		    x---.----   priority?
		    -xx-.----   bank
		*/
		if (pri == 0 || (attr >> 7) == pri)
		{
			tile += ((attr >> 5) & 0x3) * 256;

				m_gfxdecode->gfx(0)->transpen(
				bitmap,
				cliprect,
				tile,
				attr & 0x0f,
				0,0,//xflip, yflip,
				sx, sy,
				pri ? 3 : -1);
		}
	}
}

void dynamski_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	for (int i = 0x7e; i >= 0x00; i -= 2)
	{
		int bank = m_spriteram[0xb80 + i];
		int attr = m_spriteram[0xb81 + i];
		int tile = m_videoram[0xb80 + i];
		int color = m_videoram[0xb81 + i];
		int sy = 240 - m_spriteram[0x380 + i];

		int sx = m_spriteram[0x381 + i] - 64 + 8 + 16;
		if (attr & 1) sx += 0x100;


		m_gfxdecode->gfx(1)->transpen(
		bitmap,
		cliprect,
		bank * 0x40 + (tile & 0x3f),
		color,
		tile & 0x80, tile & 0x40, // flipx, flipy
		sx, sy, 3);
	}
}

uint32_t dynamski_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	draw_background(bitmap, cliprect, 0);
	draw_sprites(bitmap, cliprect);
	draw_background(bitmap, cliprect, 1);
	return 0;
}
