/*

cps1hack driver written by Robbbert, August 2008.

This driver has the 8 games that won't work with the latest cps1 driver,
because of the different palette processing. It is specially written for
MisfitMAME. If you intend to copy it, you must give the proper credits.

*/

#include "driver.h"

#include "machine/eeprom.h"
#include "sound/2151intf.h"
#include "sound/okim6295.h"
#include "sound/qsound.h"
#include "sound/msm5205.h"

/* Offset of each palette entry */
static int palette_basecolor[6];
#define cps1_palette_entries (32*8)  /* Number colour schemes in palette */

static const int cps1_scroll_size =0x4000;	/* scroll1, scroll2, scroll3 */
static const int cps1_obj_size    =0x0800;
static const int cps1_other_size  =0x0800;
static const int cps1_palette_align=0x0800;	/* can't be larger than this, breaks ringdest & batcirc otherwise */
static const int cps1_palette_size=cps1_palette_entries*32; /* Size of palette RAM */

/* Output ports */
#define CPS1_OBJ_BASE			0x00    /* Base address of objects */
#define CPS1_SCROLL1_BASE       0x02    /* Base address of scroll 1 */
#define CPS1_SCROLL2_BASE       0x04    /* Base address of scroll 2 */
#define CPS1_SCROLL3_BASE       0x06    /* Base address of scroll 3 */
#define CPS1_OTHER_BASE			0x08    /* Base address of other video */
#define CPS1_PALETTE_BASE       0x0a    /* Base address of palette */
#define CPS1_SCROLL1_SCROLLX    0x0c    /* Scroll 1 X */
#define CPS1_SCROLL1_SCROLLY    0x0e    /* Scroll 1 Y */
#define CPS1_SCROLL2_SCROLLX    0x10    /* Scroll 2 X */
#define CPS1_SCROLL2_SCROLLY    0x12    /* Scroll 2 Y */
#define CPS1_SCROLL3_SCROLLX    0x14    /* Scroll 3 X */
#define CPS1_SCROLL3_SCROLLY    0x16    /* Scroll 3 Y */
#define CPS1_STARS1_SCROLLX     0x18    /* Stars 1 X */
#define CPS1_STARS1_SCROLLY     0x1a    /* Stars 1 Y */
#define CPS1_STARS2_SCROLLX     0x1c    /* Stars 2 X */
#define CPS1_STARS2_SCROLLY     0x1e    /* Stars 2 Y */

#define CPS1_ROWSCROLL_OFFS     0x20    /* base of row scroll offsets in other RAM */

#define CPS1_SCROLL2_WIDTH      0x40
#define CPS1_SCROLL2_HEIGHT     0x40

/* first 0x4000 of gfx ROM are used, but 0x0000-0x1fff is == 0x2000-0x3fff */
static const int stars_rom_size = 0x2000;

static UINT16 *cps1_gfxram;
static UINT16 *cps1_output;
static size_t cps1_gfxram_size;
static size_t cps1_output_size;
static UINT16 *cps1_scroll1;
static UINT16 *cps1_scroll2;
static UINT16 *cps1_scroll3;
static UINT16 *cps1_obj;
static UINT16 *cps1_buffered_obj;
static UINT16 *cps1_palette;
static UINT16 *cps1_other;
static UINT16 *cps1_old_palette;
static int cps1_last_sprite_offset;     /* Offset of the last sprite */
static int cps1_stars_enabled[2];          /* Layer enabled [Y/N] */
static tilemap *cps1_bg_tilemap[3];
static int cps1_scroll1x, cps1_scroll1y;
static int cps1_scroll2x, cps1_scroll2y;
static int cps1_scroll3x, cps1_scroll3y;
static int stars1x, stars1y, stars2x, stars2y;
static int cps1_scanline1;
static int cps1_scanline2;

static READ16_HANDLER( cps1_dsw_r )
{
	static const char *const dswname[] = { "IN0", "DSWA", "DSWB", "DSWC" };
	int in = input_port_read(machine, dswname[offset]);
	return (in << 8) | in;
}

static READ16_HANDLER( cps1_in2_r )
{
	int in = input_port_read(machine, "IN2");
	return (in << 8) | in;
}

static WRITE8_HANDLER( cps1_snd_bankswitch_w )
{
	UINT8 *RAM = memory_region(machine, "audio");
	int bankaddr;

	bankaddr = ((data & 1) * 0x4000);
	memory_set_bankptr(1,&RAM[0x10000 + bankaddr]);
}

static WRITE8_HANDLER( cps1_oki_pin7_w )
{
	okim6295_set_pin7(0, (data & 1));
}

static WRITE16_HANDLER( cps1_soundlatch_w )
{
	if (ACCESSING_BITS_0_7)
		soundlatch_w(machine,0,data & 0xff);
}

static WRITE16_HANDLER( cps1_soundlatch2_w )
{
	if (ACCESSING_BITS_0_7)
		soundlatch2_w(machine,0,data & 0xff);
}

static WRITE16_HANDLER( cps1_coinctrl_w )
{
	if (ACCESSING_BITS_8_15)
	{
		coin_counter_w(0,data & 0x0100);
		coin_counter_w(1,data & 0x0200);
		coin_lockout_w(0,~data & 0x0400);
		coin_lockout_w(1,~data & 0x0800);

		// bit 15 = CPS-A custom reset?
	}
}

static WRITE16_HANDLER( cpsq_coinctrl2_w )
{
	if (ACCESSING_BITS_0_7)
	{
		coin_counter_w(2,data & 0x01);
		coin_lockout_w(2,~data & 0x02);
		coin_counter_w(3,data & 0x04);
		coin_lockout_w(3,~data & 0x08);
    }
}

static INTERRUPT_GEN( cps1_interrupt )
{
	/* Strider also has a IRQ4 handler. It is input port related, but the game */
	/* works without it. It is the *only* CPS1 game to have that. */
	cpunum_set_input_line(machine, 0, 2, HOLD_LINE);
}

/********************************************************************
*
*  Q Sound
*  =======
*
********************************************************************/

static UINT8 *qsound_sharedram1,*qsound_sharedram2;

static INTERRUPT_GEN( cps1_qsound_interrupt )
{
	cpunum_set_input_line(machine, cpunum, 2, HOLD_LINE);
}

static READ16_HANDLER( qsound_sharedram1_r )
{
	return qsound_sharedram1[offset] | 0xff00;
}

static WRITE16_HANDLER( qsound_sharedram1_w )
{
	if (ACCESSING_BITS_0_7)
		qsound_sharedram1[offset] = data;
}

static READ16_HANDLER( qsound_sharedram2_r )
{
	return qsound_sharedram2[offset] | 0xff00;
}

static WRITE16_HANDLER( qsound_sharedram2_w )
{
	if (ACCESSING_BITS_0_7)
		qsound_sharedram2[offset] = data;
}

static WRITE8_HANDLER( qsound_banksw_w )
{
	UINT8 *RAM = memory_region(machine, "audio");
	int bankaddress=0x10000+((data&0x0f)*0x4000);
	if (bankaddress >= memory_region_length(machine, "audio"))
	{
		logerror("WARNING: Q sound bank overflow (%02x)\n", data);
		bankaddress=0x10000;
	}
	memory_set_bankptr(1, &RAM[bankaddress]);
}


/********************************************************************
*
*  EEPROM
*  ======
*
*   The EEPROM is accessed by a serial protocol using the register
*   0xf1c006
*
********************************************************************/

static const eeprom_interface qsound_eeprom_interface =
{
	7,		/* address bits */
	8,		/* data bits */
	"0110",	/*  read command */
	"0101",	/* write command */
	"0111"	/* erase command */
};

static NVRAM_HANDLER( qsound )
{
	if (read_or_write)
		eeprom_save(file);
	else
	{
		eeprom_init(&qsound_eeprom_interface);

		if (file)
			eeprom_load(file);
	}
}

static READ16_HANDLER( cps1_eeprom_port_r )
{
	return eeprom_read_bit();
}

static WRITE16_HANDLER( cps1_eeprom_port_w )
{
	if (ACCESSING_BITS_0_7)
	{
		/*
        bit 0 = data
        bit 6 = clock
        bit 7 = cs
        */
		eeprom_write_bit(data & 0x01);
		eeprom_set_cs_line((data & 0x80) ? CLEAR_LINE : ASSERT_LINE);
		eeprom_set_clock_line((data & 0x40) ? ASSERT_LINE : CLEAR_LINE);
	}
}

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

		VIDEO for Misfitmame cps1hack.c

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



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

            Configuration table:

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

/* Game specific data */
struct CPS1config
{
	const char *name;             /* game driver name */

	/* Some games interrogate a couple of registers on bootup. */
	/* These are CPS1 board B self test checks. They wander from game to */
	/* game. */
	int cpsb_addr;        /* CPS board B test register address */
	int cpsb_value;       /* CPS board B test register expected value */

	/* some games use as a protection check the ability to do 16-bit multiplies */
	/* with a 32-bit result, by writing the factors to two ports and reading the */
	/* result from two other ports. */
	/* It looks like this feature was introduced with 3wonders (CPSB ID = 08xx) */
	int mult_factor1;
	int mult_factor2;
	int mult_result_lo;
	int mult_result_hi;

	int layer_control;
	int priority[4];
	int control_reg;  /* Control register? seems to be always 0x3f */

	/* ideally, the layer enable masks should consist of only one bit, */
	/* but in many cases it is unknown which bit is which. */
	int layer_enable_mask[5];

	int bank_scroll1;
	int bank_scroll2;
	int bank_scroll3;

	/* Some characters aren't visible */
	const int start_scroll2;
	const int end_scroll2;
	const int start_scroll3;
	const int end_scroll3;

	int kludge;  /* Ghouls n Ghosts sprite kludge */
};

static struct CPS1config *cps1_game_config;

/*                 CPSB ID    multiply protection  ctrl     priority masks   palmask     layer enable masks  */
#define CPS_B_04 0x60,0x0004, 0x00,0x00,0x00,0x00, 0x6e,{0x66,0x70,0x68,0x72},0x6a, {0x02,0x0c,0x0c,0x00,0x00}
#define HACK_B_2 0x00,0x0000, 0x00,0x00,0x00,0x00, 0x60,{0x66,0x68,0x6c,0x6e},0x6a, {0x02,0x04,0x08,0x00,0x00}


static struct CPS1config cps1_config_table[]=
{
	/* name       CPSB    banks        tile limits            kludge */
	{"cps1demo",CPS_B_04, 0,0,0, 0x0001,0xffff,0x0001,0xffff },
	{"cps1frog",CPS_B_04, 0,0,0, 0x0001,0xffff,0x0001,0xffff },
	{"wofh",    HACK_B_2, 0,0,0, 0x0000,0xffff,0x0000,0xffff, 11 },
	{"wofha",   HACK_B_2, 0,0,0, 0x0000,0xffff,0x0000,0xffff, 11 },
	{"wof3sj",  HACK_B_2, 0,0,0, 0x0000,0xffff,0x0000,0xffff, 11 },
	{"wof3sja", HACK_B_2, 0,0,0, 0x0000,0xffff,0x0000,0xffff, 11 },
	{"wofsj",   HACK_B_2, 0,0,0, 0x0000,0xffff,0x0000,0xffff, 11 },
	{"wofsja",  HACK_B_2, 0,0,0, 0x0000,0xffff,0x0000,0xffff, 11 },
	{0}		/* End of table */
};

static MACHINE_RESET( cps1hack )
{
	const char *gamename = machine->gamedrv->name;
	struct CPS1config *pCFG=&cps1_config_table[0];

	while(pCFG->name)
	{
		if (strcmp(pCFG->name, gamename) == 0)
		{
			break;
		}
		pCFG++;
	}
	cps1_game_config=pCFG;

	if (!cps1_game_config->name)
		printf("That game isn't in the table");
}


static int cps1_port(int offset)
{
	return cps1_output[offset/2];
}

INLINE UINT16 *cps1_base(int offset,int boundary)
{
	int base=cps1_port(offset)*256;
	base &= ~(boundary-1);
	return &cps1_gfxram[(base&0x3ffff)/2];
}



static READ16_HANDLER( cps1_output_r )
{
	if (offset && offset == cps1_game_config->cpsb_addr/2)
		return cps1_game_config->cpsb_value;

	if (offset && offset == cps1_game_config->mult_result_lo/2)
		return (cps1_output[cps1_game_config->mult_factor1/2] *
				cps1_output[cps1_game_config->mult_factor2/2]) & 0xffff;

	if (offset && offset == cps1_game_config->mult_result_hi/2)
		return (cps1_output[cps1_game_config->mult_factor1/2] *
				cps1_output[cps1_game_config->mult_factor2/2]) >> 16;

	return cps1_output[offset];
}

static WRITE16_HANDLER( cps1_output_w )
{
	data = COMBINE_DATA(&cps1_output[offset]);

	/* To mark scanlines for raster effects */
	if(offset == 0x50/2)
		cps1_scanline1 = (data & 0x1ff);
	else
	if(offset == 0x52/2)
		cps1_scanline2 = (data & 0x1ff);
}

static void cps1_gfx_decode(running_machine *machine)
{
	int size=memory_region_length(machine, "gfx");
	int i,j,gfxsize;
	UINT8 *cps1_gfx = memory_region(machine, "gfx");

	gfxsize=size/4;

	for (i = 0;i < gfxsize;i++)
	{
		UINT32 src = cps1_gfx[4*i] + (cps1_gfx[4*i+1]<<8) + (cps1_gfx[4*i+2]<<16) + (cps1_gfx[4*i+3]<<24);
		UINT32 dwval = 0;

		for (j = 0;j < 8;j++)
		{
			int n = 0;
			UINT32 mask = (0x80808080 >> j) & src;

			if (mask & 0x000000ff) n |= 1;
			if (mask & 0x0000ff00) n |= 2;
			if (mask & 0x00ff0000) n |= 4;
			if (mask & 0xff000000) n |= 8;

			dwval |= n << (j * 4);
		}
		cps1_gfx[4*i  ] = dwval>>0;
		cps1_gfx[4*i+1] = dwval>>8;
		cps1_gfx[4*i+2] = dwval>>16;
		cps1_gfx[4*i+3] = dwval>>24;
	}
}

static void unshuffle(UINT64 *buf,int len)
{
	int i;
	UINT64 t;

	if (len == 2) return;

	assert(len % 4 == 0);   /* must not happen */

	len /= 2;

	unshuffle(buf,len);
	unshuffle(buf + len,len);

	for (i = 0;i < len/2;i++)
	{
		t = buf[len/2 + i];
		buf[len/2 + i] = buf[len + i];
		buf[len + i] = t;
	}
}

static DRIVER_INIT( cps1hack )
{
	cps1_gfx_decode(machine);
}

static void cps1_get_video_base(void )
{
	int layercontrol, scroll1xoff, scroll2xoff, scroll3xoff;

	/* Re-calculate the VIDEO RAM base */
	if (cps1_scroll1 != cps1_base(CPS1_SCROLL1_BASE,cps1_scroll_size))
	{
		cps1_scroll1 = cps1_base(CPS1_SCROLL1_BASE,cps1_scroll_size);
		tilemap_mark_all_tiles_dirty(cps1_bg_tilemap[0]);
	}

	if (cps1_scroll2 != cps1_base(CPS1_SCROLL2_BASE,cps1_scroll_size))
	{
		cps1_scroll2 = cps1_base(CPS1_SCROLL2_BASE,cps1_scroll_size);
		tilemap_mark_all_tiles_dirty(cps1_bg_tilemap[1]);
	}

	if (cps1_scroll3 != cps1_base(CPS1_SCROLL3_BASE,cps1_scroll_size))
	{
		cps1_scroll3 = cps1_base(CPS1_SCROLL3_BASE,cps1_scroll_size);
		tilemap_mark_all_tiles_dirty(cps1_bg_tilemap[2]);
	}

	if (cps1_game_config->kludge == 11)
	{
		cps1_obj=cps1_base(CPS1_OBJ_BASE, cps1_obj_size);
		scroll1xoff = 0xffc0;
		scroll2xoff = 0xffc0;
		scroll3xoff = 0xffc0;
	}
	else
	{
		cps1_obj=cps1_base(CPS1_OBJ_BASE, cps1_obj_size);
		scroll1xoff = 0;
		scroll2xoff = 0;
		scroll3xoff = 0;
	}

	cps1_palette=cps1_base(CPS1_PALETTE_BASE,cps1_palette_align);
	cps1_other=cps1_base(CPS1_OTHER_BASE,cps1_other_size);

	/* Get scroll values */
	cps1_scroll1x=cps1_port(CPS1_SCROLL1_SCROLLX) + scroll1xoff;
	cps1_scroll1y=cps1_port(CPS1_SCROLL1_SCROLLY);
	cps1_scroll2x=cps1_port(CPS1_SCROLL2_SCROLLX) + scroll2xoff;
	cps1_scroll2y=cps1_port(CPS1_SCROLL2_SCROLLY);
	cps1_scroll3x=cps1_port(CPS1_SCROLL3_SCROLLX) + scroll3xoff;
	cps1_scroll3y=cps1_port(CPS1_SCROLL3_SCROLLY);
	stars1x =cps1_port(CPS1_STARS1_SCROLLX);
	stars1y =cps1_port(CPS1_STARS1_SCROLLY);
	stars2x =cps1_port(CPS1_STARS2_SCROLLX);
	stars2y =cps1_port(CPS1_STARS2_SCROLLY);

	/* Get layer enable bits */
	layercontrol=cps1_port(cps1_game_config->layer_control);
	tilemap_set_enable(cps1_bg_tilemap[0],layercontrol & cps1_game_config->layer_enable_mask[0]);
	tilemap_set_enable(cps1_bg_tilemap[1],layercontrol & cps1_game_config->layer_enable_mask[1]);
	tilemap_set_enable(cps1_bg_tilemap[2],layercontrol & cps1_game_config->layer_enable_mask[2]);
	cps1_stars_enabled[0] = layercontrol & cps1_game_config->layer_enable_mask[3];
	cps1_stars_enabled[1] = layercontrol & cps1_game_config->layer_enable_mask[4];
}

static WRITE16_HANDLER( cps1_gfxram_w )
{
	int page = (offset >> 7) & 0x3c0;
	COMBINE_DATA(&cps1_gfxram[offset]);

	if (page == (cps1_port(CPS1_SCROLL1_BASE) & 0x3c0))
		tilemap_mark_tile_dirty(cps1_bg_tilemap[0],offset/2 & 0x0fff);
	if (page == (cps1_port(CPS1_SCROLL2_BASE) & 0x3c0))
		tilemap_mark_tile_dirty(cps1_bg_tilemap[1],offset/2 & 0x0fff);
	if (page == (cps1_port(CPS1_SCROLL3_BASE) & 0x3c0))
		tilemap_mark_tile_dirty(cps1_bg_tilemap[2],offset/2 & 0x0fff);
}



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

  Start the video hardware emulation.

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

static TILEMAP_MAPPER( tilemap0_scan )
{
	/* logical (col,row) -> memory offset */
	return (row & 0x1f) + ((col & 0x3f) << 5) + ((row & 0x20) << 6);
}

static TILEMAP_MAPPER( tilemap1_scan )
{
	/* logical (col,row) -> memory offset */
	return (row & 0x0f) + ((col & 0x3f) << 4) + ((row & 0x30) << 6);
}

static TILEMAP_MAPPER( tilemap2_scan )
{
	/* logical (col,row) -> memory offset */
	return (row & 0x07) + ((col & 0x3f) << 3) + ((row & 0x38) << 6);
}

static UINT8 empty_tile[32*32/2];

static TILE_GET_INFO( get_tile0_info )
{
	int base = cps1_game_config->bank_scroll1 * 0x08000;
	int code = cps1_scroll1[2*tile_index];
	int attr = cps1_scroll1[2*tile_index+1];
	int gfxset;

	if (tile_index&0x20) gfxset = 1; else gfxset = 0;

	if (code == 0x0020) { gfxset = 4; code = 0; }

	SET_TILE_INFO(
			gfxset,
			code + base,
			(attr & 0x1f) + palette_basecolor[1],
			TILE_FLIPYX((attr & 0x60) >> 5));
	tileinfo->group = (attr & 0x0180) >> 7;
}

static TILE_GET_INFO( get_tile1_info )
{
	int base = cps1_game_config->bank_scroll2 * 0x04000;
	const int startcode = cps1_game_config->start_scroll2;
	const int endcode   = cps1_game_config->end_scroll2;
	int code = cps1_scroll2[2*tile_index];
	int attr = cps1_scroll2[2*tile_index+1];

	SET_TILE_INFO(
			2,
			code + base,
			(attr & 0x1f) + palette_basecolor[2],
			TILE_FLIPYX((attr & 0x60) >> 5));
	tileinfo->group = (attr & 0x0180) >> 7;

	if (code < startcode || code > endcode)
		tileinfo->pen_data = empty_tile;
}

static TILE_GET_INFO( get_tile2_info )
{
	int base = cps1_game_config->bank_scroll3 * 0x1000;
	const int startcode = cps1_game_config->start_scroll3;
	const int endcode   = cps1_game_config->end_scroll3;
	int code = cps1_scroll3[2*tile_index];
	int attr = cps1_scroll3[2*tile_index+1];

	SET_TILE_INFO(
			3,
			code + base,
			(attr & 0x1f) + palette_basecolor[3],
			TILE_FLIPYX((attr & 0x60) >> 5));
	tileinfo->group = (attr & 0x0180) >> 7;

	if (code < startcode || code > endcode)
		tileinfo->pen_data = empty_tile;
}



static void cps1_update_transmasks(void)
{
	int i;

	for (i = 0;i < 4;i++)
	{
		int mask;

		/* Get transparency registers */
		if (cps1_game_config->priority[i])
			mask = cps1_port(cps1_game_config->priority[i]) ^ 0xffff;
		else mask = 0xffff;	/* completely transparent if priority masks not defined (mercs, qad) */

		tilemap_set_transmask(cps1_bg_tilemap[0],i,mask,0x8000);
		tilemap_set_transmask(cps1_bg_tilemap[1],i,mask,0x8000);
		tilemap_set_transmask(cps1_bg_tilemap[2],i,mask,0x8000);
	}
}

static void cps1_create_empty_8x8_tile(running_machine *machine)
{
	static const gfx_layout empty_layout8x8 =
	{
		8,8,
		1,
		4,
		{ 0, 1, 2, 3 },
		{ 1*4, 0*4, 3*4, 2*4, 5*4, 4*4, 7*4, 6*4 },
		{ 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 },
		64*8
	};

	machine->gfx[4] = allocgfx(&empty_layout8x8);
	decodechar(machine->gfx[4], 0, (UINT8 *)empty_tile);
	machine->gfx[4]->total_colors = 0x100;

}

static VIDEO_START( cps1hack )
{
	int i;

	MACHINE_RESET_CALL(cps1hack);

	cps1_bg_tilemap[0] = tilemap_create(get_tile0_info,tilemap0_scan, 8, 8,64,64);
	cps1_bg_tilemap[1] = tilemap_create(get_tile1_info,tilemap1_scan,16,16,64,64);
	cps1_bg_tilemap[2] = tilemap_create(get_tile2_info,tilemap2_scan,32,32,64,64);

	/* front masks will change at runtime to handle sprite occluding */
	cps1_update_transmasks();
	memset(empty_tile,0xff,sizeof(empty_tile));

	cps1_create_empty_8x8_tile(machine);

	cps1_old_palette=auto_malloc(cps1_palette_size);
	memset(cps1_old_palette, 0x00, cps1_palette_size);
	for (i = 0;i < cps1_palette_entries*16;i++)
		palette_set_color(machine,i,MAKE_RGB(0,0,0));

	cps1_buffered_obj = auto_malloc (cps1_obj_size);
	memset(cps1_buffered_obj, 0x00, cps1_obj_size);

	memset(cps1_gfxram, 0, cps1_gfxram_size);   /* Clear GFX RAM */
	memset(cps1_output, 0, cps1_output_size);   /* Clear output ports */

	/* Put in some defaults */
	cps1_output[CPS1_OBJ_BASE/2]     = 0x9200;
	cps1_output[CPS1_SCROLL1_BASE/2] = 0x9000;
	cps1_output[CPS1_SCROLL2_BASE/2] = 0x9040;
	cps1_output[CPS1_SCROLL3_BASE/2] = 0x9080;
	cps1_output[CPS1_OTHER_BASE/2]   = 0x9100;
	cps1_output[CPS1_PALETTE_BASE/2] = 0x90c0;

	/* Set up old base */
	cps1_get_video_base();   /* Calculate base pointers */
	cps1_get_video_base();   /* Calculate old base pointers */

	/* set palette banks */
	palette_basecolor[0] = 0*32;	/* obj */
	palette_basecolor[1] = 1*32;	/* scroll1 */
	palette_basecolor[2] = 2*32;	/* scroll2 */
	palette_basecolor[3] = 3*32;	/* scroll3 */
	palette_basecolor[4] = 4*32;	/* stars1 */
	palette_basecolor[5] = 5*32;	/* stars2 */
}


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

  Build palette from palette RAM

  12 bit RGB with a 4 bit brightness value.

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

static void cps1_build_palette(running_machine *machine)
{
	int offset;

	for (offset = 0; offset < cps1_palette_entries*16; offset++)
	{
		int palette = cps1_palette[offset];

		if (palette != cps1_old_palette[offset])
		{
		   	int red, green, blue, bright;

			bright = 0x10 + (palette>>12);

			red   = ((palette>>8)&0x0f) * bright * 0x11 / 0x1f;
			green = ((palette>>4)&0x0f) * bright * 0x11 / 0x1f;
			blue  = ((palette>>0)&0x0f) * bright * 0x11 / 0x1f;

			palette_set_color (machine, offset, MAKE_RGB(red, green, blue));
			cps1_old_palette[offset] = palette;
		}
	}
}


static void cps1_find_last_sprite(void)    /* Find the offset of last sprite */
{
	int offset=0;
	/* Locate the end of table marker */
	while (offset < cps1_obj_size/2)
	{
		int colour=cps1_buffered_obj[offset+3];
		if ((colour & 0xff00) == 0xff00)
		{
			/* Marker found. This is the last sprite. */
			cps1_last_sprite_offset=offset-4;
			return;
		}
	offset+=4;
	}
	/* Sprites must use full sprite RAM */
	cps1_last_sprite_offset=cps1_obj_size/2-4;
}


static void cps1_render_sprites(running_machine *machine, bitmap_t *bitmap, const rectangle *cliprect)
{
#define DRAWSPRITE(CODE,COLOR,FLIPX,FLIPY,SX,SY) \
{						\
	if (flip_screen_get())			\
		pdrawgfx(bitmap,machine->gfx[2], \
				CODE,		\
				COLOR,		\
				!(FLIPX),!(FLIPY), \
				511-16-(SX),255-16-(SY), \
				cliprect,TRANSPARENCY_PEN,15,0x02); \
	else					\
		pdrawgfx(bitmap,machine->gfx[2], \
				CODE,		\
				COLOR,		\
				FLIPX,FLIPY,	\
				SX,SY,		\
				cliprect,TRANSPARENCY_PEN,15,0x02); \
}


	int i, baseadd;
	UINT16 *base=cps1_buffered_obj;

	baseadd = 4;

	for (i=cps1_last_sprite_offset; i>=0; i-=4)
	{
		int x=*(base+0);
		int y=*(base+1);
		int code  =*(base+2);
		int colour=*(base+3);
		int col=colour&0x1f;

		if (code < machine->gfx[1]->total_elements)
		{
			if (colour & 0xff00 )
			{
				/* handle blocked sprites */
				int nx=(colour & 0x0f00) >> 8;
				int ny=(colour & 0xf000) >> 12;
				int nxs,nys,sx,sy;
				nx++;
				ny++;

				if (colour & 0x40)
				{
					/* Y flip */
					if (colour &0x20)
					{
						for (nys=0; nys<ny; nys++)
						{
							for (nxs=0; nxs<nx; nxs++)
							{
								sx = (x+nxs*16) & 0x1ff;
								sy = (y+nys*16) & 0x1ff;

								DRAWSPRITE(
										code+(nx-1)-nxs+0x10*(ny-1-nys),
										(col&0x1f) + palette_basecolor[0],
										1,1,
										sx,sy);
							}
						}
					}
					else
					{
						for (nys=0; nys<ny; nys++)
						{
							for (nxs=0; nxs<nx; nxs++)
							{
								sx = (x+nxs*16) & 0x1ff;
								sy = (y+nys*16) & 0x1ff;

								DRAWSPRITE(
										code+nxs+0x10*(ny-1-nys),
										(col&0x1f) + palette_basecolor[0],
										0,1,
										sx,sy);
							}
						}
					}
				}
				else
				{
					if (colour &0x20)
					{
						for (nys=0; nys<ny; nys++)
						{
							for (nxs=0; nxs<nx; nxs++)
							{
								sx = (x+nxs*16) & 0x1ff;
								sy = (y+nys*16) & 0x1ff;

								DRAWSPRITE(
										code+(nx-1)-nxs+0x10*nys,
										(col&0x1f) + palette_basecolor[0],
										1,0,
										sx,sy);
							}
						}
					}
					else
					{
						for (nys=0; nys<ny; nys++)
						{
							for (nxs=0; nxs<nx; nxs++)
							{
								sx = (x+nxs*16) & 0x1ff;
								sy = (y+nys*16) & 0x1ff;

								DRAWSPRITE(
										code+nxs+0x10*nys,
										(col&0x1f) + palette_basecolor[0],
										0,0,
										sx,sy);
							}
						}
					}
				}
			}
			else
			{
				/* Simple case... 1 sprite */
						DRAWSPRITE(
						code,
						(col&0x1f) + palette_basecolor[0],
						colour&0x20,colour&0x40,
						x & 0x1ff,y & 0x1ff);
			}
		}
		base += baseadd;
	}
#undef DRAWSPRITE
}


static void cps1_render_stars(const device_config *screen,bitmap_t *bitmap,const rectangle *cliprect)
{
	int offs;
	UINT8 *stars_rom = memory_region(screen->machine, "stars");

	if (!stars_rom && (cps1_stars_enabled[0] || cps1_stars_enabled[1]))
		return;

	if (cps1_stars_enabled[0])
	{
		for (offs = 0;offs < stars_rom_size/2;offs++)
		{
			int col = stars_rom[8*offs+4];
			if (col != 0x0f)
			{
				int sx = (offs / 256) * 32;
				int sy = (offs % 256);
				sx = (sx - stars2x + (col & 0x1f)) & 0x1ff;
				sy = (sy - stars2y) & 0xff;
				if (flip_screen_get())
				{
					sx = 511 - sx;
					sy = 255 - sy;
				}

				col = ((col & 0xe0) >> 1) + (video_screen_get_frame_number(screen)/16 & 0x0f);

				if (sx >= cliprect->min_x && sx <= cliprect->max_x &&
					sy >= cliprect->min_y && sy <= cliprect->max_y)
					*BITMAP_ADDR16(bitmap, sy, sx) = 0xa00+col;
			}
		}
	}

	if (cps1_stars_enabled[1])
	{
		for (offs = 0;offs < stars_rom_size/2;offs++)
		{
			int col = stars_rom[8*offs];
			if (col != 0x0f)
			{
				int sx = (offs / 256) * 32;
				int sy = (offs % 256);
				sx = (sx - stars1x + (col & 0x1f)) & 0x1ff;
				sy = (sy - stars1y) & 0xff;
				if (flip_screen_get())
				{
					sx = 511 - sx;
					sy = 255 - sy;
				}

				col = ((col & 0xe0) >> 1) + (video_screen_get_frame_number(screen)/16 & 0x0f);

				if (sx >= cliprect->min_x && sx <= cliprect->max_x &&
					sy >= cliprect->min_y && sy <= cliprect->max_y)
					*BITMAP_ADDR16(bitmap, sy, sx) = 0x800+col;
			}
		}
	}
}


static void cps1_render_layer(running_machine *machine,bitmap_t *bitmap,const rectangle *cliprect,int layer,int primask)
{
	switch (layer)
	{
		case 0:
			cps1_render_sprites(machine,bitmap,cliprect);
			break;
		case 1:
		case 2:
		case 3:
			tilemap_draw(bitmap,cliprect,cps1_bg_tilemap[layer-1],TILEMAP_DRAW_LAYER1,primask);
			break;
	}
}

static void cps1_render_high_layer(bitmap_t *bitmap, const rectangle *cliprect, int layer)
{
	switch (layer)
	{
		case 0:
			/* there are no high priority sprites */
			break;
		case 1:
		case 2:
		case 3:
			tilemap_draw(NULL,cliprect,cps1_bg_tilemap[layer-1],TILEMAP_DRAW_LAYER0,1);
			break;
	}
}


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

    Refresh screen

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

static VIDEO_UPDATE( cps1hack )
{
	int layercontrol,l0,l1,l2,l3;
	int videocontrol=cps1_port(0x22);

	flip_screen_set(videocontrol & 0x8000);

	layercontrol = cps1_output[cps1_game_config->layer_control/2];

	/* Get video memory base registers */
	cps1_get_video_base();

	/* Find the offset of the last sprite in the sprite table */
	cps1_find_last_sprite();

	/* Build palette */
	cps1_build_palette(screen->machine);

	cps1_update_transmasks();

	tilemap_set_scrollx(cps1_bg_tilemap[0],0,cps1_scroll1x);
	tilemap_set_scrolly(cps1_bg_tilemap[0],0,cps1_scroll1y);
	if (videocontrol & 0x01)	/* linescroll enable */
	{
		int scrly=-cps1_scroll2y;
		int i;
		int otheroffs;

		tilemap_set_scroll_rows(cps1_bg_tilemap[1],1024);

		otheroffs = cps1_port(CPS1_ROWSCROLL_OFFS);

		for (i = 0;i < 256;i++)
			tilemap_set_scrollx(cps1_bg_tilemap[1],(i - scrly) & 0x3ff,cps1_scroll2x + cps1_other[(i + otheroffs) & 0x3ff]);
	}
	else
	{
		tilemap_set_scroll_rows(cps1_bg_tilemap[1],1);
		tilemap_set_scrollx(cps1_bg_tilemap[1],0,cps1_scroll2x);
	}
	tilemap_set_scrolly(cps1_bg_tilemap[1],0,cps1_scroll2y);
	tilemap_set_scrollx(cps1_bg_tilemap[2],0,cps1_scroll3x);
	tilemap_set_scrolly(cps1_bg_tilemap[2],0,cps1_scroll3y);


	/* Blank screen */
	fillbitmap(bitmap,4095,cliprect);

	cps1_render_stars(screen,bitmap,cliprect);

	/* Draw layers (0 = sprites, 1-3 = tilemaps) */
	l0 = (layercontrol >> 0x06) & 03;
	l1 = (layercontrol >> 0x08) & 03;
	l2 = (layercontrol >> 0x0a) & 03;
	l3 = (layercontrol >> 0x0c) & 03;
	fillbitmap(priority_bitmap,0,cliprect);

	cps1_render_layer(screen->machine,bitmap,cliprect,l0,0);
	if (l1 == 0) cps1_render_high_layer(bitmap,cliprect,l0); /* prepare mask for sprites */
	cps1_render_layer(screen->machine,bitmap,cliprect,l1,0);
	if (l2 == 0) cps1_render_high_layer(bitmap,cliprect,l1); /* prepare mask for sprites */
	cps1_render_layer(screen->machine,bitmap,cliprect,l2,0);
	if (l3 == 0) cps1_render_high_layer(bitmap,cliprect,l2); /* prepare mask for sprites */
	cps1_render_layer(screen->machine,bitmap,cliprect,l3,0);

	return 0;
}

static VIDEO_EOF( cps1hack )
{
	/* Get video memory base registers */
	cps1_get_video_base();

	memcpy(cps1_buffered_obj, cps1_obj, cps1_obj_size);
}


static ADDRESS_MAP_START( cps1frog_map, ADDRESS_SPACE_PROGRAM, 16 )
	AM_RANGE(0x000000, 0x1fffff) AM_ROM
	AM_RANGE(0x800000, 0x800001) AM_READ_PORT("IN1")            /* Player input ports */
	AM_RANGE(0x800030, 0x800031) AM_WRITE(cps1_coinctrl_w)
	AM_RANGE(0x800180, 0x800187) AM_WRITE(cps1_soundlatch_w) 	/* Sound command */
	AM_RANGE(0x800188, 0x80018f) AM_WRITE(cps1_soundlatch2_w)	/* Sound timer fade */
	AM_RANGE(0x800100, 0x8001ff) AM_READWRITE(cps1_output_r,cps1_output_w) AM_BASE(&cps1_output) AM_SIZE(&cps1_output_size)  /* Output ports */
	AM_RANGE(0x900000, 0x92ffff) AM_RAM_WRITE(cps1_gfxram_w) AM_BASE(&cps1_gfxram) AM_SIZE(&cps1_gfxram_size)	/* SF2CE executes code from here */
	AM_RANGE(0xff0000, 0xffffff) AM_RAM
ADDRESS_MAP_END

static ADDRESS_MAP_START( sub_map, ADDRESS_SPACE_PROGRAM, 8 )
	AM_RANGE(0x0000, 0x7fff) AM_ROM
	AM_RANGE(0x8000, 0xbfff) AM_ROMBANK(1)
	AM_RANGE(0xd000, 0xd7ff) AM_RAM
	AM_RANGE(0xf000, 0xf000) AM_WRITE(ym2151_register_port_0_w)
	AM_RANGE(0xf001, 0xf001) AM_READWRITE(ym2151_status_port_0_r, ym2151_data_port_0_w)
	AM_RANGE(0xf002, 0xf002) AM_READWRITE(okim6295_status_0_r, okim6295_data_0_w)
	AM_RANGE(0xf004, 0xf004) AM_WRITE(cps1_snd_bankswitch_w)
	AM_RANGE(0xf006, 0xf006) AM_WRITE(cps1_oki_pin7_w) /* controls pin 7 of OKI chip */
	AM_RANGE(0xf008, 0xf008) AM_READ(soundlatch_r)	/* Sound command */
	AM_RANGE(0xf00a, 0xf00a) AM_READ(soundlatch2_r) /* Sound timer fade */
ADDRESS_MAP_END

static ADDRESS_MAP_START( qsound_sub_map, ADDRESS_SPACE_PROGRAM, 8 )	// used by cps2.c too
	AM_RANGE(0x0000, 0x7fff) AM_ROM
	AM_RANGE(0x8000, 0xbfff) AM_ROMBANK(1)	/* banked (contains music data) */
	AM_RANGE(0xc000, 0xcfff) AM_RAM AM_BASE(&qsound_sharedram1)
	AM_RANGE(0xd000, 0xd000) AM_WRITE(qsound_data_h_w)
	AM_RANGE(0xd001, 0xd001) AM_WRITE(qsound_data_l_w)
	AM_RANGE(0xd002, 0xd002) AM_WRITE(qsound_cmd_w)
	AM_RANGE(0xd003, 0xd003) AM_WRITE(qsound_banksw_w)
	AM_RANGE(0xd007, 0xd007) AM_READ(qsound_status_r)
	AM_RANGE(0xf000, 0xffff) AM_RAM AM_BASE(&qsound_sharedram2)
ADDRESS_MAP_END

static ADDRESS_MAP_START( wofh_map, ADDRESS_SPACE_PROGRAM, 16 )
	AM_RANGE(0x000000, 0x1fffff) AM_ROM
	AM_RANGE(0x800030, 0x800031) AM_WRITE(cps1_coinctrl_w)
	AM_RANGE(0x800100, 0x8001ff) AM_READWRITE(cps1_output_r,cps1_output_w) AM_BASE(&cps1_output) AM_SIZE(&cps1_output_size)  /* Output ports */
	AM_RANGE(0x880000, 0x880001) AM_READ_PORT("IN1")            /* Player input ports */
	AM_RANGE(0x880006, 0x88000d) AM_READ(cps1_dsw_r)            /* System input ports / Dip Switches */
	AM_RANGE(0x88000e, 0x88000f) AM_WRITENOP		/* unknown */
	AM_RANGE(0x880e78, 0x880e79) AM_READ(cps1_in2_r)            /* Player 3 controls (later games) */
	AM_RANGE(0x890000, 0x890001) AM_WRITENOP		/* unknown */
	AM_RANGE(0x8bfff6, 0x8bfff9) AM_READNOP			/* unknown */
	AM_RANGE(0x900000, 0x92ffff) AM_RAM_WRITE(cps1_gfxram_w) AM_BASE(&cps1_gfxram) AM_SIZE(&cps1_gfxram_size)	/* SF2CE executes code from here */
	AM_RANGE(0xf18000, 0xf19fff) AM_READWRITE(qsound_sharedram1_r, qsound_sharedram1_w)  /* Q RAM */
	AM_RANGE(0xf1c004, 0xf1c005) AM_WRITE(cpsq_coinctrl2_w)     /* Coin control2 (later games) */
	AM_RANGE(0xf1c006, 0xf1c007) AM_READWRITE(cps1_eeprom_port_r, cps1_eeprom_port_w)
	AM_RANGE(0xf1e000, 0xf1ffff) AM_READWRITE(qsound_sharedram2_r, qsound_sharedram2_w)  /* Q RAM */
	AM_RANGE(0xff0000, 0xffffff) AM_RAM
ADDRESS_MAP_END

static ADDRESS_MAP_START( wof3sj_map, ADDRESS_SPACE_PROGRAM, 16 )
	AM_RANGE(0x000000, 0x1fffff) AM_ROM
	AM_RANGE(0x800030, 0x800031) AM_WRITE(cps1_coinctrl_w)
	AM_RANGE(0x800100, 0x800171) AM_READWRITE(cps1_output_r,cps1_output_w) AM_BASE(&cps1_output) AM_SIZE(&cps1_output_size)  /* Output ports */
	AM_RANGE(0x880000, 0x880001) AM_READ_PORT("IN1")            /* Player input ports */
	AM_RANGE(0x880006, 0x880007) AM_WRITENOP		/* unknown */
	AM_RANGE(0x880008, 0x88000f) AM_READ(cps1_dsw_r)            /* System input ports / Dip Switches */
	AM_RANGE(0x880e7e, 0x880e7f) AM_READ(cps1_in2_r)            /* Player 3 controls (later games) */
	AM_RANGE(0x890000, 0x890001) AM_WRITENOP		/* unknown */
	AM_RANGE(0x8bfff6, 0x8bfff9) AM_READNOP			/* unknown */
	AM_RANGE(0x900000, 0x92ffff) AM_RAM_WRITE(cps1_gfxram_w) AM_BASE(&cps1_gfxram) AM_SIZE(&cps1_gfxram_size)	/* SF2CE executes code from here */
	AM_RANGE(0xf18000, 0xf19fff) AM_READWRITE(qsound_sharedram1_r, qsound_sharedram1_w)  /* Q RAM */
	AM_RANGE(0xf1c004, 0xf1c005) AM_WRITE(cpsq_coinctrl2_w)     /* Coin control2 (later games) */
	AM_RANGE(0xf1c006, 0xf1c007) AM_READWRITE(cps1_eeprom_port_r, cps1_eeprom_port_w)
	AM_RANGE(0xf1e000, 0xf1ffff) AM_READWRITE(qsound_sharedram2_r, qsound_sharedram2_w)  /* Q RAM */
	AM_RANGE(0xff0000, 0xffffff) AM_RAM
ADDRESS_MAP_END


/***********************************************************
             INPUT PORTS, DIPs
***********************************************************/

static INPUT_PORTS_START( cps1frog )
	PORT_START ("IN0")
	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN )

	PORT_START ("DSWA")
	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN )

	PORT_START ("DSWB")
	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN )

	PORT_START ("DSWC")
	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN )

	PORT_START ("IN1")
	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
	PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
INPUT_PORTS_END

static INPUT_PORTS_START( wofh )
	PORT_START ("IN0")
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START2 )
	PORT_SERVICE_NO_TOGGLE( 0x40, IP_ACTIVE_LOW )
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )

	PORT_START ("DSWA")
	PORT_DIPNAME( 0x03, 0x00, "Play Mode" )
	PORT_DIPSETTING(    0x00, DEF_STR( Normal ) )
	PORT_DIPSETTING(    0x03, "Tournament" )
	PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNKNOWN )

	PORT_START ("DSWB")
	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ) )
	PORT_DIPSETTING(    0x03, DEF_STR( 1C_1C ) )
	PORT_DIPSETTING(    0x02, DEF_STR( 1C_2C ) )
	PORT_DIPSETTING(    0x01, DEF_STR( 1C_3C ) )
	PORT_DIPSETTING(    0x00, DEF_STR( 1C_4C ) )
	PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNKNOWN )

	PORT_START ("DSWC")
	PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNKNOWN )

	PORT_START ("IN1")
	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
	PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1)
	PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
	PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
	PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
	PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )

	PORT_START ("IN2")      /* Player 3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(3)
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(3)
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(3)
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(3)
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(3)
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3)
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN3 )
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START3 )
INPUT_PORTS_END

static INPUT_PORTS_START( wof3sj )
	PORT_START ("IN0")
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START2 )
	PORT_SERVICE_NO_TOGGLE( 0x40, IP_ACTIVE_LOW )
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )

	PORT_START ("DSWA")	/* there are lots of other combinations, but this covers the useful ones */
	PORT_DIPNAME( 0xff, 0xff, DEF_STR( Coinage ) )
	PORT_DIPSETTING(    0xde, DEF_STR( 2C_1C ) )
	PORT_DIPSETTING(    0xff, DEF_STR( 1C_1C ) )
	PORT_DIPSETTING(    0xfe, DEF_STR( 1C_2C ) )
	PORT_DIPSETTING(    0xfd, DEF_STR( 1C_3C ) )
	PORT_DIPSETTING(    0xfc, DEF_STR( 1C_4C ) )
	PORT_DIPSETTING(    0x7f, DEF_STR( 1C_7C ) )
	PORT_DIPSETTING(    0xdf, DEF_STR( 1C_8C ) )

	PORT_START ("DSWB")      /* (not used, EEPROM) */
	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN )

	PORT_START ("DSWC")      /* (not used, EEPROM) */
	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN )

	PORT_START ("IN1")
	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1)
	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
	PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2)
	PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
	PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
	PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )

	PORT_START ("IN2")      /* Player 3 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(3)
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(3)
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(3)
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(3)
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(3)
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3)
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN3 )
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START3 )
INPUT_PORTS_END


static const gfx_layout cps1_layout8x8 =
{
	8,8,
	RGN_FRAC(1,1),
	4,
	{ 0, 1, 2, 3 },
	{ 1*4, 0*4, 3*4, 2*4, 5*4, 4*4, 7*4, 6*4 },
	{ 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 },
	64*8
};

static const gfx_layout cps1_layout8x8_2 =
{
	8,8,
	RGN_FRAC(1,1),
	4,
	{ 0, 1, 2, 3 },
	{ 9*4, 8*4, 11*4, 10*4, 13*4, 12*4, 15*4, 14*4 },
	{ 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 },
	64*8
};

static const gfx_layout cps1_layout16x16 =
{
	16,16,
	RGN_FRAC(1,1),
	4,
	{ GFX_RAW },
	{ 0 },		/* org displacement */
	{ 8*8 },	/* line modulo */
	128*8		/* char modulo */
};

static const gfx_layout cps1_layout32x32 =
{
	32,32,
	RGN_FRAC(1,1),
	4,
	{ GFX_RAW },
	{ 0 },		/* org displacement */
	{ 16*8 },	/* line modulo */
	512*8		/* char modulo */
};

GFXDECODE_START( cps1hack )
	GFXDECODE_ENTRY( "gfx", 0, cps1_layout8x8,   0, 0x100 )
	GFXDECODE_ENTRY( "gfx", 0, cps1_layout8x8_2, 0, 0x100 )
	GFXDECODE_ENTRY( "gfx", 0, cps1_layout16x16, 0, 0x100 )
	GFXDECODE_ENTRY( "gfx", 0, cps1_layout32x32, 0, 0x100 )
GFXDECODE_END



static void cps1_irq_handler_mus(running_machine *machine, int irq)
{
	cpunum_set_input_line(machine, 1,0,irq ? ASSERT_LINE : CLEAR_LINE);
}

static const ym2151_interface ym2151_config =
{
	cps1_irq_handler_mus
};



/********************************************************************
*
*  Machine Driver macro
*  ====================
*
********************************************************************/

static MACHINE_DRIVER_START( cps1frog )

	/* basic machine hardware */
	MDRV_CPU_ADD ("main", M68000, 10000000)
	MDRV_CPU_PROGRAM_MAP(cps1frog_map,0)
	MDRV_CPU_VBLANK_INT("main", cps1_interrupt)

	/* audio CPU */
	MDRV_CPU_ADD ("audio", Z80, 3579545)
	MDRV_CPU_PROGRAM_MAP(sub_map,0)

	/* video hardware */
	MDRV_SCREEN_ADD("main", RASTER)
	MDRV_SCREEN_REFRESH_RATE(59.61)
	MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
	MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
	MDRV_SCREEN_SIZE(64*8, 32*8)
	MDRV_SCREEN_VISIBLE_AREA(8*8, (64-8)*8-1, 2*8, 30*8-1 )

	MDRV_GFXDECODE(cps1hack)
	MDRV_PALETTE_LENGTH(0xc00)

	MDRV_VIDEO_START(cps1hack)
	MDRV_VIDEO_EOF(cps1hack)
	MDRV_VIDEO_UPDATE(cps1hack)

	/* sound hardware */
	MDRV_SPEAKER_STANDARD_MONO("mono")

	MDRV_SOUND_ADD ("2151", YM2151, 3579545)
	MDRV_SOUND_CONFIG(ym2151_config)
	MDRV_SOUND_ROUTE(0, "mono", 0.35)
	MDRV_SOUND_ROUTE(1, "mono", 0.35)

	MDRV_SOUND_ADD ("oki", OKIM6295, 1000000)
	MDRV_SOUND_CONFIG(okim6295_interface_pin7high) // pin 7 can be changed by the game code, see f006 on z80
	MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.30)
MACHINE_DRIVER_END

static MACHINE_DRIVER_START( wofh )

	/* basic machine hardware */
	MDRV_IMPORT_FROM(cps1frog)

	MDRV_CPU_REPLACE("main", M68000, 12000000)
	MDRV_CPU_PROGRAM_MAP(wofh_map,0)
	MDRV_CPU_VBLANK_INT("main", cps1_qsound_interrupt)

	MDRV_CPU_REPLACE("audio", Z80, 8000000)
	MDRV_CPU_PROGRAM_MAP(qsound_sub_map,0)
	MDRV_CPU_PERIODIC_INT(irq0_line_hold, 250)

	MDRV_NVRAM_HANDLER(qsound)

	/* sound hardware */
	MDRV_SPEAKER_REMOVE("mono")
	MDRV_SPEAKER_STANDARD_STEREO("left", "right")

	MDRV_SOUND_REMOVE("2151")
	MDRV_SOUND_REMOVE("oki")

	MDRV_SOUND_ADD("qsound", QSOUND, QSOUND_CLOCK)
	MDRV_SOUND_ROUTE(0, "left", 1.0)
	MDRV_SOUND_ROUTE(1, "right", 1.0)
MACHINE_DRIVER_END

static MACHINE_DRIVER_START( wof3sj )
	MDRV_IMPORT_FROM(wofh)
	MDRV_CPU_REPLACE("main", M68000, 12000000)
	MDRV_CPU_PROGRAM_MAP(wof3sj_map,0)
MACHINE_DRIVER_END

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

  Game driver(s)

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

#define CODE_SIZE 0x200000

ROM_START( cps1demo )
	ROM_REGION( CODE_SIZE, "main", 0 )      /* 68000 code */
	ROM_LOAD16_BYTE( "cd30-36.bin",  0x00000, 0x20000, CRC(5eb617d6) SHA1(9d4656d2b29244eb2a01058f5b80752d94065a6e) )
	ROM_LOAD16_BYTE( "cd35-42.bin",  0x00001, 0x20000, CRC(1f1c0a62) SHA1(12d1950921fff6d52ae969a4c7357f4e7bc28d1e) )
	ROM_LOAD16_WORD_SWAP( "ff32-32m.bin", 0x80000, 0x80000, CRC(c747696e) SHA1(d3362dadded31ccb7eaf71ef282d698d18edd722) )

	ROM_REGION( 0x200000, "gfx", 0 )
	ROMX_LOAD( "cd05-05m.bin", 0x000000, 0x80000, CRC(35dc6153) SHA1(7b7747d4e6a78c0933b6ea96fa6027c2c2c50682) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "cd07-07m.bin", 0x000002, 0x80000, CRC(baf08a38) SHA1(82559384399c5dfb8979a2e91d585549357ebb52) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "cd01-01m.bin", 0x000004, 0x80000, CRC(3ad8e790) SHA1(a371edc81a48903d13ed8938dca450dab986b413) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "cd03-03m.bin", 0x000006, 0x80000, CRC(fb5186f3) SHA1(b20031c01b6be2a4987553c0ab19105714bf9299) , ROM_GROUPWORD | ROM_SKIP(6) )

	ROM_REGION( 0x8000, "stars", 0 )
	ROM_COPY( "gfx", 0x000000, 0x000000, 0x8000 )	/* stars */

	ROM_REGION( 0x18000, "audio", 0 ) /* 64k for the audio CPU (+banks) */
	ROM_LOAD( "ff09-09.bin",   0x00000, 0x08000, CRC(b8367eb5) SHA1(ec3db29fdd6200e9a8f4f8073a7e34aef731354f) )
	ROM_CONTINUE(              0x10000, 0x08000 )

	ROM_REGION( 0x40000, "oki", 0 )	/* Samples */
	ROM_LOAD( "ff18-18.bin",  0x00000, 0x20000, CRC(375c66e7) SHA1(36189e23209ce4ae5d9cbabd1574540d0591e7b3) )
	ROM_LOAD( "ff19-19.bin",  0x20000, 0x20000, CRC(1ef137f9) SHA1(974b5e72aa28b87ebfa7438efbdfeda769dedf5e) )
ROM_END

ROM_START( cps1frog )
	ROM_REGION( CODE_SIZE, "main", 0 )      /* 68000 code */
	ROM_LOAD16_BYTE( "frog30-36.bin",  0x00000, 0x20000, CRC(8eb8ddbe) SHA1(298c72b3eb6f2721f204cf80ec4a7c52dc8b23fd) )
	ROM_LOAD16_BYTE( "frog35-42.bin",  0x00001, 0x20000, CRC(acb5a988) SHA1(7264bb94f7bacef9bf03713d0a6d32e81ca1f8e2) )
	ROM_LOAD16_WORD_SWAP( "frog32-32m.bin", 0x80000, 0x80000, CRC(75660aac) SHA1(6a521e1d2a632c26e53b83d2cc4b0edecfc1e68c) )

	ROM_REGION( 0x200000, "gfx", 0 )
	ROMX_LOAD( "frog05-05m.bin", 0x000000, 0x80000, CRC(7bbc4b54) SHA1(5a40bd85ce71dc733071732a8306d648b3e6dd39) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "frog07-07m.bin", 0x000002, 0x80000, CRC(0beadd80) SHA1(f43d6ad936b8ffa242c17d8da26bf2e2a12d85a8) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "frog01-01m.bin", 0x000004, 0x80000, CRC(f84d02bb) SHA1(b89322ab65a3b3e8202c27af62de2b182a4ed2e9) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "frog03-03m.bin", 0x000006, 0x80000, CRC(d784a5b0) SHA1(8891bb8fc39f51db200c51e2a65961c351d655c2) , ROM_GROUPWORD | ROM_SKIP(6) )

	ROM_REGION( 0x8000, "stars", 0 )
	ROM_COPY( "gfx", 0x000000, 0x000000, 0x8000 )	/* stars */

	ROM_REGION( 0x18000, "audio", 0 ) /* 64k for the audio CPU (+banks) */
	ROM_LOAD( "frog09-09.bin",   0x00000, 0x08000, CRC(3ac7fb5c) SHA1(01057078b67dc82d80403533a3dca3deb95f166c) )
	ROM_CONTINUE(              0x10000, 0x08000 )

	ROM_REGION( 0x40000, "oki", 0 )	/* Samples */
	ROM_LOAD( "frog18-18.bin",  0x00000, 0x20000, CRC(65d1ef07) SHA1(0bc2dbf5053430f659d64d1b287799bb5cc4db65) )
	ROM_LOAD( "frog19-19.bin",  0x20000, 0x20000, CRC(7ee8cdcd) SHA1(67dfd19f3eb3649d6f3f6631e44d0bd36b8d8d19) )
ROM_END

ROM_START( wofh )
	ROM_REGION( CODE_SIZE, "main", 0 )      /* 68000 code */
	ROM_LOAD16_WORD_SWAP( "sgyx.800",  0x000000, 0x100000, CRC(3703a650) SHA1(6cb8d6f99df5e2e5cf04aee8737bb585f9328ffd) )

	ROM_REGION( 0x400000, "gfx", 0 )
	ROMX_LOAD( "sgyx-1.160",   0x000000, 0x80000, CRC(a60be9f6) SHA1(2298a4b6a2c83b76dc106a1efa19606b298d378a) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROM_CONTINUE(              0x000004, 0x80000 )
	ROM_CONTINUE(              0x200000, 0x80000 )
	ROM_CONTINUE(              0x200004, 0x80000 )
	ROMX_LOAD( "sgyx-2.160",   0x000002, 0x80000, CRC(6ad9d048) SHA1(d47212d28d0a1ce349e4c59e5d0d99c541b3458e) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROM_CONTINUE(              0x000006, 0x80000 )
	ROM_CONTINUE(              0x200002, 0x80000 )
	ROM_CONTINUE(              0x200006, 0x80000 )

	ROM_REGION( 0x8000, "stars", 0 )
	ROM_COPY( "gfx", 0x000000, 0x000000, 0x8000 )	/* stars */

	ROM_REGION( 0x28000, "audio", 0 ) /* QSound Z80 code + space for decrypted opcodes */
	ROM_LOAD( "tk2_qa.rom",     0x00000, 0x08000, CRC(c9183a0d) SHA1(d8b1d41c572f08581f8ab9eb878de77d6ea8615d) )
	ROM_CONTINUE(               0x10000, 0x18000 )

	ROM_REGION( 0x200000, "qsound", 0 ) /* QSound samples */
	ROM_LOAD( "tk2_q1.rom",     0x000000, 0x80000, CRC(611268cf) SHA1(83ab059f2110fb25fdcff928d56b790fc1f5c975) )
	ROM_LOAD( "tk2_q2.rom",     0x080000, 0x80000, CRC(20f55ca9) SHA1(90134e9a9c4749bb65c728b66ea4dac1fd4d88a4) )
	ROM_LOAD( "tk2_q3.rom",     0x100000, 0x80000, CRC(bfcf6f52) SHA1(2a85ff3fc89b4cbabd20779ec12da2e116333c7c) )
	ROM_LOAD( "tk2_q4.rom",     0x180000, 0x80000, CRC(36642e88) SHA1(8ab25b19e2b67215a5cb1f3aa81b9d26009cfeb8) )
ROM_END
	
ROM_START( wofha )
	ROM_REGION( CODE_SIZE, "main", 0 )      /* 68000 code */
	ROM_LOAD16_BYTE( "fg-c.040",  0x000000, 0x80000, CRC(d046fc86) SHA1(0ae0b9310e3a122cb69df4bb23672149794242f0) )
	ROM_LOAD16_BYTE( "fg-a.040",  0x000001, 0x80000, CRC(f176ee8f) SHA1(fba357c31774aeecef88f70df4294514585df3a0) )

	ROM_REGION( 0x400000, "gfx", 0 )
	ROMX_LOAD( "sgyx-1.160",   0x000000, 0x80000, CRC(a60be9f6) SHA1(2298a4b6a2c83b76dc106a1efa19606b298d378a) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROM_CONTINUE(              0x000004, 0x80000 )
	ROM_CONTINUE(              0x200000, 0x80000 )
	ROM_CONTINUE(              0x200004, 0x80000 )
	ROMX_LOAD( "sgyx-2.160",   0x000002, 0x80000, CRC(6ad9d048) SHA1(d47212d28d0a1ce349e4c59e5d0d99c541b3458e) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROM_CONTINUE(              0x000006, 0x80000 )
	ROM_CONTINUE(              0x200002, 0x80000 )
	ROM_CONTINUE(              0x200006, 0x80000 )

	ROM_REGION( 0x8000, "stars", 0 )
	ROM_COPY( "gfx", 0x000000, 0x000000, 0x8000 )	/* stars */

	ROM_REGION( 0x28000, "audio", 0 ) /* QSound Z80 code + space for decrypted opcodes */
	ROM_LOAD( "tk2_qa.rom",     0x00000, 0x08000, CRC(c9183a0d) SHA1(d8b1d41c572f08581f8ab9eb878de77d6ea8615d) )
	ROM_CONTINUE(               0x10000, 0x18000 )

	ROM_REGION( 0x200000, "qsound", 0 ) /* QSound samples */
	ROM_LOAD( "tk2_q1.rom",     0x000000, 0x80000, CRC(611268cf) SHA1(83ab059f2110fb25fdcff928d56b790fc1f5c975) )
	ROM_LOAD( "tk2_q2.rom",     0x080000, 0x80000, CRC(20f55ca9) SHA1(90134e9a9c4749bb65c728b66ea4dac1fd4d88a4) )
	ROM_LOAD( "tk2_q3.rom",     0x100000, 0x80000, CRC(bfcf6f52) SHA1(2a85ff3fc89b4cbabd20779ec12da2e116333c7c) )
	ROM_LOAD( "tk2_q4.rom",     0x180000, 0x80000, CRC(36642e88) SHA1(8ab25b19e2b67215a5cb1f3aa81b9d26009cfeb8) )
ROM_END

ROM_START( wof3sj )
	ROM_REGION( CODE_SIZE, "main", 0 )      /* 68000 code */
	ROM_LOAD16_BYTE( "k6b.040",  0x000000, 0x80000, CRC(7b365108) SHA1(e4ef6e7267ecf36d8b15c7df0351b38777cd559d) )
	ROM_LOAD16_BYTE( "k6a.040",  0x000001, 0x80000, CRC(10488a51) SHA1(061d5139f4289cbca9e0a743954d9c65a9384c06) )

	ROM_REGION( 0x400000, "gfx", 0 )
	ROMX_LOAD( "k6a.160",   0x000000, 0x80000, CRC(a121180d) SHA1(9501399479a5892db0c818637459f77540794b85) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROM_CONTINUE(              0x000004, 0x80000 )
	ROM_CONTINUE(              0x200000, 0x80000 )
	ROM_CONTINUE(              0x200004, 0x80000 )
	ROMX_LOAD( "k6b.160",   0x000002, 0x80000, CRC(a4db96c4) SHA1(6798c0cbd9a1f8f4704c5cb9e19e8873149d3c33) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROM_CONTINUE(              0x000006, 0x80000 )
	ROM_CONTINUE(              0x200002, 0x80000 )
	ROM_CONTINUE(              0x200006, 0x80000 )

	ROM_REGION( 0x8000, "stars", 0 )
	ROM_COPY( "gfx", 0x000000, 0x000000, 0x8000 )	/* stars */

	ROM_REGION( 2*0x28000, "audio", 0 ) /* QSound Z80 code + space for decrypted opcodes */
	ROM_LOAD( "tk2_qa.rom",     0x00000, 0x08000, CRC(c9183a0d) SHA1(d8b1d41c572f08581f8ab9eb878de77d6ea8615d) )
	ROM_CONTINUE(               0x10000, 0x18000 )

	ROM_REGION( 0x200000, "qsound", 0 ) /* QSound samples */
	ROM_LOAD( "tk2_q1.rom",     0x000000, 0x80000, CRC(611268cf) SHA1(83ab059f2110fb25fdcff928d56b790fc1f5c975) )
	ROM_LOAD( "tk2_q2.rom",     0x080000, 0x80000, CRC(20f55ca9) SHA1(90134e9a9c4749bb65c728b66ea4dac1fd4d88a4) )
	ROM_LOAD( "tk2_q3.rom",     0x100000, 0x80000, CRC(bfcf6f52) SHA1(2a85ff3fc89b4cbabd20779ec12da2e116333c7c) )
	ROM_LOAD( "tk2_q4.rom",     0x180000, 0x80000, CRC(36642e88) SHA1(8ab25b19e2b67215a5cb1f3aa81b9d26009cfeb8) )
ROM_END

ROM_START( wof3sja )
	ROM_REGION( CODE_SIZE, "main", 0 )      /* 68000 code */
	ROM_LOAD16_WORD_SWAP( "3js.800",  0x000000, 0x100000, CRC(812f9200) SHA1(ddf4261c21762e8168d83393a59aa1450762a89a) )

	ROM_REGION( 0x400000, "gfx", 0 )
	ROMX_LOAD( "k6a.160",   0x000000, 0x80000, CRC(a121180d) SHA1(9501399479a5892db0c818637459f77540794b85) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROM_CONTINUE(              0x000004, 0x80000 )
	ROM_CONTINUE(              0x200000, 0x80000 )
	ROM_CONTINUE(              0x200004, 0x80000 )
	ROMX_LOAD( "k6b.160",   0x000002, 0x80000, CRC(a4db96c4) SHA1(6798c0cbd9a1f8f4704c5cb9e19e8873149d3c33) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROM_CONTINUE(              0x000006, 0x80000 )
	ROM_CONTINUE(              0x200002, 0x80000 )
	ROM_CONTINUE(              0x200006, 0x80000 )

	ROM_REGION( 0x8000, "stars", 0 )
	ROM_COPY( "gfx", 0x000000, 0x000000, 0x8000 )	/* stars */

	ROM_REGION( 0x28000, "audio", 0 ) /* QSound Z80 code + space for decrypted opcodes */
	ROM_LOAD( "tk2_qa.rom",     0x00000, 0x08000, CRC(c9183a0d) SHA1(d8b1d41c572f08581f8ab9eb878de77d6ea8615d) )
	ROM_CONTINUE(               0x10000, 0x18000 )

	ROM_REGION( 0x200000, "qsound", 0 ) /* QSound samples */
	ROM_LOAD( "tk2_q1.rom",     0x000000, 0x80000, CRC(611268cf) SHA1(83ab059f2110fb25fdcff928d56b790fc1f5c975) )
	ROM_LOAD( "tk2_q2.rom",     0x080000, 0x80000, CRC(20f55ca9) SHA1(90134e9a9c4749bb65c728b66ea4dac1fd4d88a4) )
	ROM_LOAD( "tk2_q3.rom",     0x100000, 0x80000, CRC(bfcf6f52) SHA1(2a85ff3fc89b4cbabd20779ec12da2e116333c7c) )
	ROM_LOAD( "tk2_q4.rom",     0x180000, 0x80000, CRC(36642e88) SHA1(8ab25b19e2b67215a5cb1f3aa81b9d26009cfeb8) )
ROM_END

ROM_START( wofsj )
	ROM_REGION( CODE_SIZE, "main", 0 )      /* 68000 code */
	ROM_LOAD16_BYTE( "c-c47b.040",  0x000000, 0x80000, CRC(b1809761) SHA1(99a17ed193654f61622eb721e20b69894c96d3d8) )
	ROM_LOAD16_BYTE( "a-2402.040",  0x000001, 0x80000, CRC(4fab4232) SHA1(d8ffd06cce73e1c4bc6abb69a2e81277ce901563) )

	ROM_REGION( 0x400000, "gfx", 0 )
	ROMX_LOAD( "tk2_gfx1.rom",   0x000000, 0x80000, CRC(0d9cb9bf) SHA1(cc7140e9a01a14b252cb1090bcea32b0de461928) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "tk2_gfx3.rom",   0x000002, 0x80000, CRC(45227027) SHA1(b21afc593f0d4d8909dfa621d659cbb40507d1b2) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "tk2_gfx2.rom",   0x000004, 0x80000, CRC(c5ca2460) SHA1(cbe14867f7b94b638ca80db7c8e0c60881183469) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "tk2_gfx4.rom",   0x000006, 0x80000, CRC(e349551c) SHA1(1d977bdf256accf750ad9930ec4a0a19bbf86964) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "tk2_gfx5.rom",   0x200000, 0x80000, CRC(291f0f0b) SHA1(094baf0f960f25fc2525b3b1cc378a49d9a0955d) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "tk2_gfx7.rom",   0x200002, 0x80000, CRC(3edeb949) SHA1(c155698dd9ee9eb24bbc97a21118ef2e897ea82f) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "tk2_gfx6.rom",   0x200004, 0x80000, CRC(1abd14d6) SHA1(dffff3126f102b4ec028a81405fc5b9bd7bb65b3) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "tk2_gfx8.rom",   0x200006, 0x80000, CRC(b27948e3) SHA1(870d5d23f56798831c641e877ea94217058b2ddc) , ROM_GROUPWORD | ROM_SKIP(6) )

	ROM_REGION( 0x8000, "stars", 0 )
	ROM_COPY( "gfx", 0x000000, 0x000000, 0x8000 )	/* stars */

	ROM_REGION( 0x28000, "audio", 0 ) /* QSound Z80 code + space for decrypted opcodes */
	ROM_LOAD( "tk2_qa.rom",     0x00000, 0x08000, CRC(c9183a0d) SHA1(d8b1d41c572f08581f8ab9eb878de77d6ea8615d) )
	ROM_CONTINUE(               0x10000, 0x18000 )

	ROM_REGION( 0x200000, "qsound", 0 ) /* QSound samples */
	ROM_LOAD( "tk2_q1.rom",     0x000000, 0x80000, CRC(611268cf) SHA1(83ab059f2110fb25fdcff928d56b790fc1f5c975) )
	ROM_LOAD( "tk2_q2.rom",     0x080000, 0x80000, CRC(20f55ca9) SHA1(90134e9a9c4749bb65c728b66ea4dac1fd4d88a4) )
	ROM_LOAD( "tk2_q3.rom",     0x100000, 0x80000, CRC(bfcf6f52) SHA1(2a85ff3fc89b4cbabd20779ec12da2e116333c7c) )
	ROM_LOAD( "tk2_q4.rom",     0x180000, 0x80000, CRC(36642e88) SHA1(8ab25b19e2b67215a5cb1f3aa81b9d26009cfeb8) )
ROM_END

ROM_START( wofsja )
	ROM_REGION( CODE_SIZE, "main", 0 )      /* 68000 code */
	ROM_LOAD16_WORD_SWAP( "one.800",  0x000000, 0x100000, CRC(0507584d) SHA1(5a9df64b7c2c54c5aa0d4c9486c7404157c6119e) )

	ROM_REGION( 0x400000, "gfx", 0 )
	ROMX_LOAD( "tk2_gfx1.rom",   0x000000, 0x80000, CRC(0d9cb9bf) SHA1(cc7140e9a01a14b252cb1090bcea32b0de461928) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "tk2_gfx3.rom",   0x000002, 0x80000, CRC(45227027) SHA1(b21afc593f0d4d8909dfa621d659cbb40507d1b2) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "tk2_gfx2.rom",   0x000004, 0x80000, CRC(c5ca2460) SHA1(cbe14867f7b94b638ca80db7c8e0c60881183469) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "tk2_gfx4.rom",   0x000006, 0x80000, CRC(e349551c) SHA1(1d977bdf256accf750ad9930ec4a0a19bbf86964) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "tk2_gfx5.rom",   0x200000, 0x80000, CRC(291f0f0b) SHA1(094baf0f960f25fc2525b3b1cc378a49d9a0955d) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "tk2_gfx7.rom",   0x200002, 0x80000, CRC(3edeb949) SHA1(c155698dd9ee9eb24bbc97a21118ef2e897ea82f) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "tk2_gfx6.rom",   0x200004, 0x80000, CRC(1abd14d6) SHA1(dffff3126f102b4ec028a81405fc5b9bd7bb65b3) , ROM_GROUPWORD | ROM_SKIP(6) )
	ROMX_LOAD( "tk2_gfx8.rom",   0x200006, 0x80000, CRC(b27948e3) SHA1(870d5d23f56798831c641e877ea94217058b2ddc) , ROM_GROUPWORD | ROM_SKIP(6) )

	ROM_REGION( 0x8000, "stars", 0 )
	ROM_COPY( "gfx", 0x000000, 0x000000, 0x8000 )	/* stars */

	ROM_REGION( 0x28000, "audio", 0 ) /* QSound Z80 code + space for decrypted opcodes */
	ROM_LOAD( "tk2_qa.rom",     0x00000, 0x08000, CRC(c9183a0d) SHA1(d8b1d41c572f08581f8ab9eb878de77d6ea8615d) )
	ROM_CONTINUE(               0x10000, 0x18000 )

	ROM_REGION( 0x200000, "qsound", 0 ) /* QSound samples */
	ROM_LOAD( "tk2_q1.rom",     0x000000, 0x80000, CRC(611268cf) SHA1(83ab059f2110fb25fdcff928d56b790fc1f5c975) )
	ROM_LOAD( "tk2_q2.rom",     0x080000, 0x80000, CRC(20f55ca9) SHA1(90134e9a9c4749bb65c728b66ea4dac1fd4d88a4) )
	ROM_LOAD( "tk2_q3.rom",     0x100000, 0x80000, CRC(bfcf6f52) SHA1(2a85ff3fc89b4cbabd20779ec12da2e116333c7c) )
	ROM_LOAD( "tk2_q4.rom",     0x180000, 0x80000, CRC(36642e88) SHA1(8ab25b19e2b67215a5cb1f3aa81b9d26009cfeb8) )
ROM_END

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

	Kabuki decoding for wof

	Done here because kabuki.c includes cps1.h, causing all sorts of problems

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

static int bitswap1(int src,int key,int select)
{
	if (select & (1 << ((key >> 0) & 7)))
		src = (src & 0xfc) | ((src & 0x01) << 1) | ((src & 0x02) >> 1);
	if (select & (1 << ((key >> 4) & 7)))
		src = (src & 0xf3) | ((src & 0x04) << 1) | ((src & 0x08) >> 1);
	if (select & (1 << ((key >> 8) & 7)))
		src = (src & 0xcf) | ((src & 0x10) << 1) | ((src & 0x20) >> 1);
	if (select & (1 << ((key >>12) & 7)))
		src = (src & 0x3f) | ((src & 0x40) << 1) | ((src & 0x80) >> 1);

	return src;
}

static int bitswap2(int src,int key,int select)
{
	if (select & (1 << ((key >>12) & 7)))
		src = (src & 0xfc) | ((src & 0x01) << 1) | ((src & 0x02) >> 1);
	if (select & (1 << ((key >> 8) & 7)))
		src = (src & 0xf3) | ((src & 0x04) << 1) | ((src & 0x08) >> 1);
	if (select & (1 << ((key >> 4) & 7)))
		src = (src & 0xcf) | ((src & 0x10) << 1) | ((src & 0x20) >> 1);
	if (select & (1 << ((key >> 0) & 7)))
		src = (src & 0x3f) | ((src & 0x40) << 1) | ((src & 0x80) >> 1);

	return src;
}

static int bytedecode(int src,int swap_key1,int swap_key2,int xor_key,int select)
{
	src = bitswap1(src,swap_key1 & 0xffff,select & 0xff);
	src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
	src = bitswap2(src,swap_key1 >> 16,select & 0xff);
	src ^= xor_key;
	src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
	src = bitswap2(src,swap_key2 & 0xffff,select >> 8);
	src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
	src = bitswap1(src,swap_key2 >> 16,select >> 8);
	return src;
}

static void kabuki_decode(UINT8 *src,UINT8 *dest_op,UINT8 *dest_data,
		int base_addr,int length,int swap_key1,int swap_key2,int addr_key,int xor_key)
{
	int A;
	int select;

	for (A = 0;A < length;A++)
	{
		/* decode opcodes */
		select = (A + base_addr) + addr_key;
		dest_op[A] = bytedecode(src[A],swap_key1,swap_key2,xor_key,select);

		/* decode data */
		select = ((A + base_addr) ^ 0x1fc0) + addr_key + 1;
		dest_data[A] = bytedecode(src[A],swap_key1,swap_key2,xor_key,select);
	}
}

static void cps1_decode(running_machine *machine,int swap_key1,int swap_key2,int addr_key,int xor_key)
{
	UINT8 *decrypt = auto_malloc(0x8000);
	UINT8 *rom = memory_region(machine, "audio");

	memory_set_decrypted_region(1, 0x0000, 0x7fff, decrypt);
	kabuki_decode(rom,decrypt,rom,0x0000,0x8000, swap_key1,swap_key2,addr_key,xor_key);
}

static void wof_decode(running_machine *machine)      { cps1_decode(machine,0x01234567,0x54163072,0x5151,0x51); }

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

	Driver Initialisation

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

static DRIVER_INIT( wofh )
{
	UINT8 *mem8 = memory_region(machine, "main");
	// Stage Order
	mem8[0x72a6] = 0x00;
	// Disable Sprite Recoding
	mem8[0x5d858] = 0x00;
	mem8[0x5d859] = 0x61;
	mem8[0x5d85a] = 0xe6;
	mem8[0x5d85b] = 0x01;
	mem8[0x5d890] = 0x6d;
	mem8[0x5d891] = 0x0c;
	mem8[0x5d892] = 0x00;
	mem8[0x5d893] = 0x90;
	mem8[0x5d894] = 0xd2;
	mem8[0x5d895] = 0xe3;
	mem8[0x5d8e8] = 0x90;
	mem8[0x5d8e9] = 0x00;
	mem8[0x5d8ea] = 0x00;
	mem8[0x5d8eb] = 0x00;
	mem8[0x5d8f8] = 0x90;
	mem8[0x5d8f9] = 0x00;
	mem8[0x5d8fa] = 0x00;
	mem8[0x5d8fb] = 0x40;
	// Patch protection? check
	mem8[0xf11ec] = 0x71;
	mem8[0xf11ed] = 0x4e;
	mem8[0xf11ee] = 0x71;
	mem8[0xf11ef] = 0x4e;
	// Patch Q sound protection? check
	mem8[0x5A0E] = 0x39;
	mem8[0x5A0F] = 0x30;
	mem8[0x5A10] = 0xF1;
	mem8[0x5A12] = 0xFE;
	mem8[0x5A13] = 0x9F;
	mem8[0x5A14] = 0x00;
	mem8[0x5A15] = 0x0C;
	mem8[0x5A16] = 0x77;
	mem8[0x5A17] = 0x00;
	mem8[0x5A18] = 0xF4;
	mem8[0x5A19] = 0x66;
	mem8[0x5A1A] = 0xF9;
	mem8[0x5A1B] = 0x4E;
	mem8[0x5A1C] = 0x00;
	mem8[0x5A1E] = 0xB2;
	mem8[0x5A1F] = 0x72;
	mem8[0x5A20] = 0x7C;
	mem8[0x5A21] = 0x20;
	mem8[0x5A22] = 0xF1;
	mem8[0x5A23] = 0x00;
	mem8[0x5A24] = 0x00;
	mem8[0x5A25] = 0x80;
	mem8[0x5A26] = 0x7C;
	mem8[0x5A27] = 0x11;
	mem8[0x5A29] = 0x00;
	mem8[0x5A2A] = 0x01;
	mem8[0x5A2C] = 0x7C;
	mem8[0x5A2D] = 0x11;
	mem8[0x5A2E] = 0x10;
	mem8[0x5A2F] = 0x00;
	mem8[0x5A30] = 0x0F;
	mem8[0x5A31] = 0x00;
	mem8[0x5A32] = 0x7C;
	mem8[0x5A33] = 0x11;
	mem8[0x5A34] = 0x00;
	mem8[0x5A35] = 0x00;
	mem8[0x5A36] = 0x07;
	mem8[0x5A38] = 0x7C;
	mem8[0x5A39] = 0x11;
	mem8[0x5A3A] = 0x00;
	mem8[0x5A3B] = 0x00;
	mem8[0x5A3C] = 0x09;
	mem8[0x5A3D] = 0x00;
	mem8[0x5A3E] = 0x7C;
	mem8[0x5A3F] = 0x11;
	mem8[0x5A40] = 0x00;
	mem8[0x5A41] = 0x00;
	mem8[0x5A42] = 0x0C;
	mem8[0x5A44] = 0x41;
	mem8[0x5A48] = 0x7C;
	mem8[0x5A4A] = 0x00;
	mem8[0x5A4C] = 0x11;
	mem8[0x5A4D] = 0x00;
	mem8[0x5A4E] = 0x7C;
	mem8[0x5A4F] = 0x11;
	mem8[0x5A50] = 0x00;
	mem8[0x5A51] = 0x00;
	mem8[0x5A52] = 0x17;
	mem8[0x5A54] = 0x7C;
	mem8[0x5A56] = 0x00;
	mem8[0x5A58] = 0x19;
	mem8[0x5A59] = 0x00;
	mem8[0x5A5A] = 0x7C;
	mem8[0x5A5B] = 0x11;
	mem8[0x5A5C] = 0x00;
	mem8[0x5A5D] = 0x00;
	mem8[0x5A5E] = 0x13;
	mem8[0x5A60] = 0x7C;
	mem8[0x5A62] = 0x00;
	mem8[0x5A64] = 0x15;
	mem8[0x5A65] = 0x00;
	mem8[0x5A66] = 0x7C;
	mem8[0x5A67] = 0x11;
	mem8[0x5A68] = 0x00;
	mem8[0x5A69] = 0x00;
	mem8[0x5A6A] = 0x1F;
	mem8[0x5A6C] = 0xF9;
	mem8[0x5A6D] = 0x4E;
	mem8[0x5A6E] = 0x05;
	mem8[0x5A70] = 0x2C;
	mem8[0x5A71] = 0xE8;
	mem8[0x729A] = 0xF9;
	mem8[0x729C] = 0x00;
	mem8[0x729D] = 0x00;
	mem8[0x729E] = 0x0E;
	mem8[0x729F] = 0x5A;
	mem8[0x5E826] = 0xF9;
	mem8[0x5E827] = 0x4E;
	mem8[0x5E828] = 0x00;
	mem8[0x5E82A] = 0x20;
	mem8[0x5E82B] = 0x5A;
	wof_decode(machine);
	DRIVER_INIT_CALL(cps1hack);
}

static DRIVER_INIT( wof3sj )
{
	UINT8 *mem8 = memory_region(machine, "main");
	// Disable Sprite Recoding
	mem8[0x5de96] = 0x00;
	mem8[0x5de97] = 0x61;
	mem8[0x5de98] = 0xe6;
	mem8[0x5de99] = 0x01;
	mem8[0x5dece] = 0x6d;
	mem8[0x5decf] = 0x0c;
	mem8[0x5ded0] = 0x00;
	mem8[0x5ded1] = 0x90;
	mem8[0x5ded2] = 0xd2;
	mem8[0x5ded3] = 0xe3;
	mem8[0x5df26] = 0x90;
	mem8[0x5df27] = 0x00;
	mem8[0x5df28] = 0x00;
	mem8[0x5df29] = 0x00;
	mem8[0x5df36] = 0x90;
	mem8[0x5df37] = 0x00;
	mem8[0x5df38] = 0x00;
	mem8[0x5df39] = 0x40;
	// Patch Q sound protection? check
	mem8[0x5A0E] = 0x39;
	mem8[0x5A0F] = 0x30;
	mem8[0x5A10] = 0xF1;
	mem8[0x5A12] = 0xFE;
	mem8[0x5A13] = 0x9F;
	mem8[0x5A14] = 0x00;
	mem8[0x5A15] = 0x0C;
	mem8[0x5A16] = 0x77;
	mem8[0x5A17] = 0x00;
	mem8[0x5A18] = 0xF4;
	mem8[0x5A19] = 0x66;
	mem8[0x5A1A] = 0xF9;
	mem8[0x5A1B] = 0x4E;
	mem8[0x5A1C] = 0x00;
	mem8[0x5A1E] = 0xBE;
	mem8[0x5A1F] = 0x72;
	mem8[0x5A20] = 0x7C;
	mem8[0x5A21] = 0x20;
	mem8[0x5A22] = 0xF1;
	mem8[0x5A23] = 0x00;
	mem8[0x5A24] = 0x00;
	mem8[0x5A25] = 0x80;
	mem8[0x5A26] = 0x7C;
	mem8[0x5A27] = 0x11;
	mem8[0x5A29] = 0x00;
	mem8[0x5A2A] = 0x01;
	mem8[0x5A2C] = 0x7C;
	mem8[0x5A2D] = 0x11;
	mem8[0x5A2E] = 0x10;
	mem8[0x5A2F] = 0x00;
	mem8[0x5A30] = 0x0F;
	mem8[0x5A31] = 0x00;
	mem8[0x5A32] = 0x7C;
	mem8[0x5A33] = 0x11;
	mem8[0x5A34] = 0x00;
	mem8[0x5A35] = 0x00;
	mem8[0x5A36] = 0x07;
	mem8[0x5A38] = 0x7C;
	mem8[0x5A39] = 0x11;
	mem8[0x5A3A] = 0x00;
	mem8[0x5A3B] = 0x00;
	mem8[0x5A3C] = 0x09;
	mem8[0x5A3D] = 0x00;
	mem8[0x5A3E] = 0x7C;
	mem8[0x5A3F] = 0x11;
	mem8[0x5A40] = 0x00;
	mem8[0x5A41] = 0x00;
	mem8[0x5A42] = 0x0C;
	mem8[0x5A44] = 0x41;
	mem8[0x5A48] = 0x7C;
	mem8[0x5A4A] = 0x00;
	mem8[0x5A4C] = 0x11;
	mem8[0x5A4D] = 0x00;
	mem8[0x5A4E] = 0x7C;
	mem8[0x5A4F] = 0x11;
	mem8[0x5A50] = 0x00;
	mem8[0x5A51] = 0x00;
	mem8[0x5A52] = 0x17;
	mem8[0x5A54] = 0x7C;
	mem8[0x5A56] = 0x00;
	mem8[0x5A58] = 0x19;
	mem8[0x5A59] = 0x00;
	mem8[0x5A5A] = 0x7C;
	mem8[0x5A5B] = 0x11;
	mem8[0x5A5C] = 0x00;
	mem8[0x5A5D] = 0x00;
	mem8[0x5A5E] = 0x13;
	mem8[0x5A60] = 0x7C;
	mem8[0x5A62] = 0x00;
	mem8[0x5A64] = 0x15;
	mem8[0x5A65] = 0x00;
	mem8[0x5A66] = 0x7C;
	mem8[0x5A67] = 0x11;
	mem8[0x5A68] = 0x00;
	mem8[0x5A69] = 0x00;
	mem8[0x5A6A] = 0x1F;
	mem8[0x5A6C] = 0xF9;
	mem8[0x5A6D] = 0x4E;
	mem8[0x5A6E] = 0x05;
	mem8[0x5A70] = 0x6A;
	mem8[0x5A71] = 0xEE;
	mem8[0x72A6] = 0xF9;
	mem8[0x72A8] = 0x00;
	mem8[0x72A9] = 0x00;
	mem8[0x72AA] = 0x0E;
	mem8[0x72AB] = 0x5A;
	mem8[0x5EE64] = 0xF9;
	mem8[0x5EE65] = 0x4E;
	mem8[0x5EE66] = 0x00;
	mem8[0x5EE68] = 0x20;
	mem8[0x5EE69] = 0x5A;
	wof_decode(machine);
	DRIVER_INIT_CALL(cps1hack);
}

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

	Game Drivers

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

GAME( 2000, cps1demo, 0,    cps1frog, cps1frog, cps1hack, ROT0,   "Charles Doty", "Demo - CPS1", 0 ) // has no sound
GAME( 2006, cps1frog, 0,    cps1frog, cps1frog, cps1hack, ROT0,   "Rastersoft", "Frog Feast (CPS1)", 0 )	// misfitmame
GAME( 1999, wofh,     wof,  wofh,     wofh,     wofh,     ROT0,   "Hack",    "Legend of Three Kingdoms' Heroes / Sanguo Yingxiong Zhuan (set 1)", GAME_IMPERFECT_GRAPHICS )
GAME( 1999, wofha,    wof,  wofh,     wofh,     wofh,     ROT0,   "Hack",    "Legend of Three Kingdoms' Heroes / Sanguo Yingxiong Zhuan (set 2)", GAME_IMPERFECT_GRAPHICS )
GAME( 1997, wof3sj,   wof,  wof3sj,   wof3sj,   wof3sj,   ROT0,   "Hack",    "Three Holy Swords / San Sheng Jian (set 1)", GAME_IMPERFECT_GRAPHICS )
GAME( 1997, wof3sja,  wof,  wof3sj,   wof3sj,   wof3sj,   ROT0,   "Hack",    "Three Holy Swords / San Sheng Jian (set 2)", GAME_IMPERFECT_GRAPHICS )
GAME( 1995, wofsj,    wof,  wof3sj,   wof3sj,   wof3sj,   ROT0,   "Hack",    "Holy Sword Three Kingdoms / Sheng Jian San Guo (set 1)", GAME_IMPERFECT_GRAPHICS )
GAME( 1995, wofsja,   wof,  wof3sj,   wof3sj,   wof3sj,   ROT0,   "Hack",    "Holy Sword Three Kingdoms / Sheng Jian San Guo (set 2)", GAME_IMPERFECT_GRAPHICS )

