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

 Pang Video Hardware

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

#include "driver.h"
#include "sound/okim6295.h"


/* Globals */
size_t pang_videoram_size;
UINT8 *pang_videoram;
UINT8 *pang_colorram;

/* Private */
static UINT8 *pang_objram;           /* Sprite RAM */

static tilemap *bg_tilemap;
static int flipscreen;



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

  Callbacks for the TileMap code

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

static TILE_GET_INFO( get_tile_info )
{
	UINT8 attr = pang_colorram[tile_index];
	int code = pang_videoram[2*tile_index] + (pang_videoram[2*tile_index+1] << 8);
	SET_TILE_INFO(
			0,
			code,
			attr & 0x7f,
			(attr & 0x80) ? TILE_FLIPX : 0);
}



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

  Start the video hardware emulation.

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

VIDEO_START( pang )
{
	pang_objram=NULL;
	paletteram=NULL;


	bg_tilemap = tilemap_create(get_tile_info,tilemap_scan_rows,TILEMAP_TYPE_PEN,8,8,64,32);

	tilemap_set_transparent_pen(bg_tilemap,15);

	/*
        OBJ RAM
    */
	pang_objram=auto_malloc(pang_videoram_size);
	memset(pang_objram, 0, pang_videoram_size);

	/*
        Palette RAM
    */
	paletteram = auto_malloc(2*machine->drv->total_colors);
	memset(paletteram, 0, 2*machine->drv->total_colors);
}



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

  Memory handlers

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

/***************************************************************************
  OBJ / CHAR RAM HANDLERS (BANK 0 = CHAR, BANK 1=OBJ)
***************************************************************************/

static int video_bank;

WRITE8_HANDLER( pang_video_bank_w )
{
	/* Bank handler (sets base pointers for video write) (doesn't apply to mgakuen) */
	video_bank = data;
}

WRITE8_HANDLER( mstworld_video_bank_w )
{
	/* Monsters World seems to freak out if more bits are used.. */
	video_bank = data&1;
}


WRITE8_HANDLER( mgakuen_videoram_w )
{
	pang_videoram[offset] = data;
	tilemap_mark_tile_dirty(bg_tilemap,offset/2);
}

READ8_HANDLER( mgakuen_videoram_r )
{
	return pang_videoram[offset];
}

WRITE8_HANDLER( mgakuen_objram_w )
{
	pang_objram[offset]=data;
}

READ8_HANDLER( mgakuen_objram_r )
{
	return pang_objram[offset];
}

WRITE8_HANDLER( pang_videoram_w )
{
	if (video_bank) mgakuen_objram_w(offset,data);
	else mgakuen_videoram_w(offset,data);
}

READ8_HANDLER( pang_videoram_r )
{
	if (video_bank) return mgakuen_objram_r(offset);
	else return mgakuen_videoram_r(offset);
}

/***************************************************************************
  COLOUR RAM
****************************************************************************/

WRITE8_HANDLER( pang_colorram_w )
{
	pang_colorram[offset] = data;
	tilemap_mark_tile_dirty(bg_tilemap,offset);
}

READ8_HANDLER( pang_colorram_r )
{
	return pang_colorram[offset];
}

/***************************************************************************
  PALETTE HANDLERS (COLOURS: BANK 0 = 0x00-0x3f BANK 1=0x40-0xff)
****************************************************************************/

static int paletteram_bank;

WRITE8_HANDLER( pang_gfxctrl_w )
{
logerror("PC %04x: pang_gfxctrl_w %02x\n",activecpu_get_pc(),data);
{
	char baf[40];
	sprintf(baf,"%02x",data);
//  popmessage(baf);
}

	/* bit 0 is unknown (used, maybe back color enable?) */

	/* bit 1 is coin counter */
	coin_counter_w(0,data & 2);

	/* bit 2 is flip screen */
	if (flipscreen != (data & 0x04))
	{
		flipscreen = data & 0x04;
		tilemap_set_flip(ALL_TILEMAPS,flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
	}

	/* bit 3 is unknown (used, e.g. marukin pulses it on the title screen) */

	/* bit 4 selects OKI M6295 bank */
	if (sndti_exists(SOUND_OKIM6295,0)) OKIM6295_set_bank_base(0, (data & 0x10) ? 0x40000 : 0x00000);

	/* bit 5 is palette RAM bank selector (doesn't apply to mgakuen) */
	paletteram_bank = data & 0x20;

	/* bits 6 and 7 are unknown, used in several places. At first I thought */
	/* they were bg and sprites enable, but this screws up spang (screen flickers */
	/* every time you pop a bubble). However, not using them as enable bits screws */
	/* up marukin - you can see partially built up screens during attract mode. */
}

WRITE8_HANDLER( mstworld_gfxctrl_w )
{
logerror("PC %04x: pang_gfxctrl_w %02x\n",activecpu_get_pc(),data);
{
	char baf[40];
	sprintf(baf,"%02x",data);
//  popmessage(baf);
}

	/* bit 0 is unknown (used, maybe back color enable?) */

	/* bit 1 is coin counter */
	coin_counter_w(0,data & 2);

	/* bit 2 is flip screen */
	if (flipscreen != (data & 0x04))
	{
		flipscreen = data & 0x04;
		tilemap_set_flip(ALL_TILEMAPS,flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
	}

	/* bit 3 is unknown (used, e.g. marukin pulses it on the title screen) */

	/* bit 4 selects OKI M6295 bank */
//  OKIM6295_set_bank_base(0, (data & 0x10) ? 0x40000 : 0x00000);
	/* not here.. it has its own z80 + sound banking */

	/* bit 5 is palette RAM bank selector (doesn't apply to mgakuen) */
	paletteram_bank = data & 0x20;

	/* bits 6 and 7 are unknown, used in several places. At first I thought */
	/* they were bg and sprites enable, but this screws up spang (screen flickers */
	/* every time you pop a bubble). However, not using them as enable bits screws */
	/* up marukin - you can see partially built up screens during attract mode. */
}

WRITE8_HANDLER( pang_paletteram_w )
{
	if (paletteram_bank) paletteram_xxxxRRRRGGGGBBBB_le_w(offset + 0x800,data);
	else paletteram_xxxxRRRRGGGGBBBB_le_w(offset,data);
}

READ8_HANDLER( pang_paletteram_r )
{
	if (paletteram_bank) return paletteram_r(offset + 0x800);
	return paletteram_r(offset);
}

WRITE8_HANDLER( mgakuen_paletteram_w )
{
	paletteram_xxxxRRRRGGGGBBBB_le_w(offset,data);
}

READ8_HANDLER( mgakuen_paletteram_r )
{
	return paletteram_r(offset);
}



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

  Display refresh

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

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

	/* the last entry is not a sprite, we skip it otherwise spang shows a bubble */
	/* moving diagonally across the screen */
	for (offs = 0x1000-0x40;offs >= 0;offs -= 0x20)
	{
		int code = pang_objram[offs];
		int attr = pang_objram[offs+1];
		int color = attr & 0x0f;
		sx = pang_objram[offs+3] + ((attr & 0x10) << 4);
		sy = ((pang_objram[offs+2] + 8) & 0xff) - 8;
		code += (attr & 0xe0) << 3;
		if (flipscreen)
		{
			sx = 496 - sx;
			sy = 240 - sy;
		}
		drawgfx(bitmap,machine->gfx[1],
				 code,
				 color,
				 flipscreen,flipscreen,
				 sx,sy,
				 cliprect,TRANSPARENCY_PEN,15);
	}
}

VIDEO_UPDATE( pang )
{
	fillbitmap(bitmap,machine->pens[0],cliprect);
	tilemap_draw(bitmap,cliprect,bg_tilemap,0,0);
	draw_sprites(machine, bitmap,cliprect);
	return 0;
}
