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

	Arcade Classics (Prototype)

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


#include "driver.h"
#include "machine/atarigen.h"
#include "vidhrdw/generic.h"


void arcadecl_playfieldram_w(int offset, int data);

int arcadecl_vh_start(void);
void arcadecl_vh_stop(void);
void arcadecl_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh);

void arcadecl_scanline_update(int scanline);



/*************************************
 *
 *	Interrupt handling
 *
 *************************************/

static void update_interrupts(void)
{
	int newstate = 0;

	if (atarigen_scanline_int_state)
		newstate = 4;

	if (newstate)
		cpu_set_irq_line(0, newstate, ASSERT_LINE);
	else
		cpu_set_irq_line(0, 7, CLEAR_LINE);
}


static void scanline_update(int scanline)
{
	/* update video */
	arcadecl_scanline_update(scanline);

	/* generate 32V signals */
	if (scanline % 64 == 0)
		atarigen_scanline_int_gen();
}



/*************************************
 *
 *	Initialization
 *
 *************************************/

static void init_machine(void)
{
	atarigen_eeprom_reset();
	atarigen_interrupt_reset(update_interrupts);
	atarigen_scanline_timer_reset(scanline_update, 8);
}



/*************************************
 *
 *	MSM5295 I/O
 *
 *************************************/

static int adpcm_r(int offset)
{
	return (OKIM6295_status_0_r(offset) << 8) | 0x00ff;
}


static void adpcm_w(int offset, int data)
{
	if (!(data & 0xff000000))
		OKIM6295_data_0_w(offset, (data >> 8) & 0xff);
}



/*************************************
 *
 *	Latch write
 *
 *************************************/

static void latch_w(int offset, int data)
{
	/* bit layout in this register:

		0x0080 == ADPCM bank
		0x001F == volume
	*/

	(void)offset;

	/* lower byte being modified? */
	if (!(data & 0x00ff0000))
	{
		OKIM6295_set_bank_base(0, ALL_VOICES, (data & 0x80) ? 0x40000 : 0x00000);
		atarigen_set_oki6295_vol((data & 0x001f) * 100 / 0x1f);
	}
}



/*************************************
 *
 *	Main CPU memory handlers
 *
 *************************************/

static struct MemoryReadAddress readmem[] =
{
	{ 0x000000, 0x0fffff, MRA_ROM },
	{ 0x200000, 0x21fffe, MRA_BANK1 },
	{ 0x3c0000, 0x3c07ff, MRA_BANK2 },
	{ 0x3e0000, 0x3effff, MRA_BANK3 },
	{ 0x640000, 0x640001, input_port_0_r },
	{ 0x640002, 0x640003, input_port_1_r },
	{ 0x640010, 0x640011, input_port_2_r },
	{ 0x640012, 0x640013, input_port_3_r },
	{ 0x640020, 0x640021, input_port_4_r },
	{ 0x640022, 0x640023, input_port_5_r },
	{ 0x640024, 0x640025, input_port_6_r },
	{ 0x640026, 0x640027, input_port_7_r },
	{ 0x641000, 0x641fff, atarigen_eeprom_r },
	{ 0x642000, 0x642001, adpcm_r },

	{ -1 }  /* end of table */
};


static struct MemoryWriteAddress writemem[] =
{
	{ 0x000000, 0x0fffff, MWA_ROM },
	{ 0x200000, 0x21fffe, arcadecl_playfieldram_w, &atarigen_playfieldram },
	{ 0x3c0000, 0x3c07ff, atarigen_expanded_666_paletteram_w, &paletteram },
	{ 0x3e0000, 0x3effff, MWA_BANK3, &atarigen_spriteram },
	{ 0x640040, 0x64004f, latch_w },
	{ 0x640060, 0x64006f, atarigen_eeprom_enable_w },
	{ 0x641000, 0x641fff, atarigen_eeprom_w, &atarigen_eeprom, &atarigen_eeprom_size },
	{ 0x642000, 0x642001, adpcm_w },
	{ 0x646000, 0x646fff, atarigen_scanline_int_ack_w },
	{ 0x647000, 0x647fff, watchdog_reset_w },
	{ -1 }  /* end of table */
};



/*************************************
 *
 *	Port definitions
 *
 *************************************/

INPUT_PORTS_START( arcadecl )
	PORT_START	/* 640000 */
	PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON3 | IPF_PLAYER1 )
	PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER1 )
	PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER1 )
	PORT_BIT( 0xf000, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START	/* 640002 */
	PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON3 | IPF_PLAYER2 )
	PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER2 )
	PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
	PORT_BIT( 0xf000, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START	/* 640010 */
	PORT_BIT(  0x0001, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT(  0x0002, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT(  0x0004, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT(  0x0008, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT(  0x0010, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT(  0x0020, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_SERVICE( 0x0040, IP_ACTIVE_LOW )
	PORT_BIT(  0x0080, IP_ACTIVE_HIGH, IPT_VBLANK )
	PORT_BIT(  0xff00, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START	/* 640012 */
	PORT_BIT(  0x0001, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_BIT(  0x0002, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT(  0x000c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT(  0x0010, IP_ACTIVE_LOW, IPT_SERVICE )
	PORT_BIT(  0x0020, IP_ACTIVE_LOW, IPT_SERVICE )
	PORT_BIT(  0xffc0, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START	/* 640020 */
    PORT_ANALOGX ( 0x00ff, 0, IPT_TRACKBALL_X | IPF_REVERSE | IPF_PLAYER2, 200, 0x7f, 0, 0, KEYCODE_UP, KEYCODE_DOWN, JOYCODE_2_UP, JOYCODE_2_DOWN, 32 )
	PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START	/* 640022 */
    PORT_ANALOG ( 0x00ff, 0, IPT_TRACKBALL_Y | IPF_PLAYER2, 200, 32, 0x7f, 0, 0 )
	PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START	/* 640024 */
    PORT_ANALOG ( 0x00ff, 0, IPT_TRACKBALL_X | IPF_REVERSE | IPF_PLAYER1, 200, 32, 0x7f, 0, 0 )
	PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START	/* 640026 */
    PORT_ANALOG ( 0x00ff, 0, IPT_TRACKBALL_Y | IPF_PLAYER1, 200, 32, 0x7f, 0, 0 )
	PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END


INPUT_PORTS_START( sparkz )
	PORT_START	/* 640000 */
	PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON3 | IPF_PLAYER1 )
	PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER1 )
	PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER1 )
	PORT_BIT(  0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER1 )
	PORT_BIT(  0x2000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER1 )
	PORT_BIT(  0x4000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER1 )
	PORT_BIT(  0x8000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER1 )

	PORT_START	/* 640002 */
	PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON3 | IPF_PLAYER2 )
	PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER2 )
	PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
	PORT_BIT(  0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER2 )
	PORT_BIT(  0x2000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER2 )
	PORT_BIT(  0x4000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER2 )
	PORT_BIT(  0x8000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER2 )

	PORT_START	/* 640010 */
	PORT_BIT(  0x0001, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT(  0x0002, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT(  0x0004, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT(  0x0008, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT(  0x0010, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT(  0x0020, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_SERVICE( 0x0040, IP_ACTIVE_LOW )
	PORT_BIT(  0x0080, IP_ACTIVE_HIGH, IPT_VBLANK )
	PORT_BIT(  0xff00, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START	/* 640012 */
	PORT_BIT(  0x0001, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_BIT(  0x0002, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT(  0x000c, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT(  0x0010, IP_ACTIVE_LOW, IPT_SERVICE )
	PORT_BIT(  0x0020, IP_ACTIVE_LOW, IPT_SERVICE )
	PORT_BIT(  0xffc0, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START	/* 640020 */
	PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START	/* 640022 */
	PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START	/* 640024 */
	PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START	/* 640026 */
	PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END



/*************************************
 *
 *	Graphics definitions
 *
 *************************************/

static struct GfxLayout molayout =
{
	8,8,	/* 8*8 sprites */
	16384,	/* 16384 of them */
	4,		/* 4 bits per pixel */
	{ 0, 1, 2, 3 },
	{ 0, 4, 8, 12, 16, 20, 24, 28 },
	{ 0*8, 4*8, 8*8, 12*8, 16*8, 20*8, 24*8, 28*8 },
	32*8	/* every sprite takes 32 consecutive bytes */
};


static struct GfxDecodeInfo gfxdecodeinfo[] =
{
	{ 1, 0x000000, &molayout,  256, 16 },		/* motion objects */
	{ -1 } /* end of array */
};



/*************************************
 *
 *	Sound definitions
 *
 *************************************/

static struct OKIM6295interface okim6295_interface =
{
	1,					/* 1 chip */
	{ 7159160 / 1024 },	/* ~7000 Hz */
	{ 2 },       		/* memory region 2 */
	{ 100 }
};



/*************************************
 *
 *	Machine driver
 *
 *************************************/

static struct MachineDriver machine_driver =
{
	/* basic machine hardware */
	{
		{
			CPU_M68000,		/* verified */
			7159160,		/* 7.159 Mhz */
			0,
			readmem,writemem,0,0,
			atarigen_video_int_gen,1
		}
	},
	60, DEFAULT_REAL_60HZ_VBLANK_DURATION,	/* frames per second, vblank duration */
	1,
	init_machine,

	/* video hardware */
	43*8, 30*8, { 0*8+4, 43*8-1-4, 0*8, 30*8-1 },
	gfxdecodeinfo,
	512,512,
	0,

	VIDEO_TYPE_RASTER | VIDEO_MODIFIES_PALETTE | VIDEO_UPDATE_BEFORE_VBLANK | VIDEO_SUPPORTS_DIRTY,
	0,
	arcadecl_vh_start,
	arcadecl_vh_stop,
	arcadecl_vh_screenrefresh,

	/* sound hardware */
	0,0,0,0,
	{
		{
			SOUND_OKIM6295,
			&okim6295_interface
		}
	}
};



/*************************************
 *
 *	ROM decoding
 *
 *************************************/

static void arcadecl_rom_decode(void)
{
	int i;

	for (i = 0; i < Machine->memory_region_length[1]; i++)
		Machine->memory_region[1][i] ^= 0xff;
}


static void sparkz_rom_decode(void)
{
	memset(Machine->memory_region[1], 0, Machine->memory_region_length[1]);
}



/*************************************
 *
 *	ROM definition(s)
 *
 *************************************/

ROM_START( arcadecl )
	ROM_REGION(0x100000)
	ROM_LOAD_EVEN( "pgm0",  0x00000, 0x80000, 0xb5b93623 )
	ROM_LOAD_ODD ( "prog1", 0x00000, 0x80000, 0xe7efef85 )

	ROM_REGION_DISPOSE(0x80000)	/* temporary space for graphics (disposed after conversion) */
	ROM_LOAD( "atcl_mob",   0x00000, 0x80000, 0x0e9b3930 )

	ROM_REGION(0x80000)	/* ADPCM data */
	ROM_LOAD( "adpcm",      0x00000, 0x80000, 0x03ca7f03 )
ROM_END


ROM_START( sparkz )
	ROM_REGION(0x100000)
	ROM_LOAD_EVEN( "sparkzpg.0", 0x00000, 0x80000, 0xa75c331c )
	ROM_LOAD_ODD ( "sparkzpg.1", 0x00000, 0x80000, 0x1af1fc04 )

	ROM_REGION_DISPOSE(0x80000)	/* temporary space for graphics (disposed after conversion) */

	ROM_REGION(0x80000)	/* ADPCM data */
	ROM_LOAD( "sparkzsn",      0x00000, 0x80000, 0x87097ce2 )
ROM_END



/*************************************
 *
 *	Driver initialization
 *
 *************************************/

static void arcadecl_init(void)
{
	atarigen_eeprom_default = NULL;
}


static void sparkz_init(void)
{
	atarigen_eeprom_default = NULL;
}



/*************************************
 *
 *	Game driver(s)
 *
 *************************************/

struct GameDriver driver_arcadecl =
{
	__FILE__,
	0,
	"arcadecl",
	"Arcade Classics (prototype)",
	"1992",
	"Atari Games",
	"Aaron Giles (MAME driver)",
	0,
	&machine_driver,
	arcadecl_init,

	rom_arcadecl,
	arcadecl_rom_decode,
	0,
	0,
	0,

	input_ports_arcadecl,

	0, 0, 0,   /* colors, palette, colortable */
	ORIENTATION_DEFAULT | GAME_REQUIRES_16BIT,
	atarigen_hiload, atarigen_hisave
};


struct GameDriver driver_sparkz =
{
	__FILE__,
	0,
	"sparkz",
	"Sparkz (prototype)",
	"1992",
	"Atari Games",
	"Aaron Giles (MAME driver)",
	0,
	&machine_driver,
	sparkz_init,

	rom_sparkz,
	sparkz_rom_decode,
	0,
	0,
	0,

	input_ports_sparkz,

	0, 0, 0,   /* colors, palette, colortable */
	ORIENTATION_DEFAULT | GAME_REQUIRES_16BIT,
	atarigen_hiload, atarigen_hisave
};
