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

    Sega System 16C hardware

    modyfied from drivers/segas16b.c
    modyfied by unnamed.

****************************************************************************/
#include "driver.h"
#include "system16.h"
#include "machine/segaic16.h"
#include "machine/fd1094.h"
#include "sound/2151intf.h"
#include "sound/upd7759.h"


/*************************************
 *
 *  Constants
 *
 *************************************/
#define MASTER_CLOCK_10MHz		(10000000)
#define MASTER_CLOCK_8MHz		(8000000)
#define MASTER_CLOCK_25MHz		(25174800)

#define ROM_BOARD_171_5704custom		(0)		/* 171-5358 */


/*************************************
 *
 *  Statics
 *
 *************************************/
static UINT16 *workram;
static UINT8 has_sound_cpu;
static read16_handler custom_io_r;
static write16_handler custom_io_w;
static UINT8 disable_screen_blanking;
static void (*i8751_vblank_hook)(void);
static const UINT8 *i8751_initial_config;



/*************************************
 *
 *  Prototypes
 *
 *************************************/
extern void fd1094_machine_init(void);

static READ16_HANDLER( misc_io_r );
static WRITE16_HANDLER( misc_io_w );
static WRITE16_HANDLER( rom_5704_bank_w );
static READ16_HANDLER( unknown_rgn2_r );
static WRITE16_HANDLER( unknown_rgn2_w );



/*************************************
 *
 *  Memory mapping tables
 *
 *************************************/
static const struct segaic16_memory_map_entry rom_5704_custom_info[] =
{
	{ 0x3d/2, 0x00000, 0x04000, 0xffc000,      ~0, misc_io_r,             misc_io_w,             NULL,                  "I/O space" },
	{ 0x39/2, 0x00000, 0x01000, 0xfff000,      ~0, MRA16_BANK10,          segaic16_paletteram_w, &paletteram16,         "color RAM" },
	{ 0x35/2, 0x00000, 0x10000, 0xfe0000,      ~0, MRA16_BANK11,          segaic16_tileram_0_w,  &segaic16_tileram_0,   "tile RAM" },
	{ 0x35/2, 0x10000, 0x01000, 0xfef000,      ~0, MRA16_BANK12,          segaic16_textram_0_w,  &segaic16_textram_0,   "text RAM" }, 
	{ 0x31/2, 0x00000, 0x02000, 0xffe000,      ~0, MRA16_BANK13,          MWA16_BANK13,          &segaic16_spriteram_0, "object RAM" },
	{ 0x2d/2, 0x00000, 0x40000, 0xfc0000,      ~0, MRA16_BANK14,          MWA16_BANK14,          &workram,              "work RAM" },
	{ 0x29/2, 0x00000, 0x10000, 0xff0000,      ~0, NULL,                  rom_5704_bank_w,       NULL,                  "tile bank" },
	{ 0x25/2, 0x00000, 0x80000, 0xfc0000, 0x80000, MRA16_BANK16,          MWA16_ROM,             NULL,                  "ROM 1" },
	{ 0x21/2, 0x00000, 0x80000, 0xfc0000, 0x00000, MRA16_BANK17,          MWA16_ROM,             NULL,                  "ROM 0" },
	{ 0 }
};

/*************************************
 *
 *  Configuration
 *
 *************************************/
static void sound_w(UINT8 data)
{
	if (has_sound_cpu)
	{
		soundlatch_w(0, data & 0xff);
		cpunum_set_input_line(1, 0, HOLD_LINE);
	}
}


static void system16c_generic_init(void)
{
	/* allocate memory for regions not autmatically assigned */
	segaic16_spriteram_0 = auto_malloc(0x02000);	// 8KB (system16b = 2KB)
	paletteram16         = auto_malloc(0x01000);
	segaic16_tileram_0   = auto_malloc(0x10000);
	segaic16_textram_0   = auto_malloc(0x01000);
	workram              = auto_malloc(0x40000);	// 256KB (system16b = 16KB)

	/* init the memory mapper */
	segaic16_memory_mapper_init(0, rom_5704_custom_info, sound_w, NULL);

	/* reset the custom handlers and other pointers */
	custom_io_r = NULL;
	custom_io_w = NULL;
	i8751_vblank_hook = NULL;
	i8751_initial_config = NULL;
	disable_screen_blanking = 0;

	/* see if we have a sound CPU and a UPD7759 chip */
	has_sound_cpu = (mame_find_cpu_index("sound") != -1);
}



/*************************************
 *
 *  Initialization & interrupts
 *
 *************************************/
static MACHINE_RESET( system16c )
{
	static const UINT8 default_banklist[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
	int i;

	segaic16_memory_mapper_reset();
	if (i8751_initial_config != NULL)
		segaic16_memory_mapper_config(i8751_initial_config);
	segaic16_tilemap_reset(0);

	fd1094_machine_init();

	/* if we have a fake i8751 handler, disable the actual 8751 */
	if (i8751_vblank_hook != NULL)
		cpunum_suspend(2, SUSPEND_REASON_DISABLE, 1);

	/* configure sprite banks */
	for (i = 0; i < 16; i++)
		segaic16_sprites_set_bank(0, i, default_banklist[i]);
}


/*************************************
 *
 *  I/O space
 *
 *************************************/
static READ16_HANDLER( standard_io_r )
{
	offset &= 0x1fff;
	switch (offset & (0x3000/2))
	{
		case 0x1000/2:
			return readinputport(offset & 3);

		case 0x2000/2:
			return readinputport(4 + (offset & 1));
	}
	logerror("%06X:standard_io_r - unknown read access to address %04X\n", activecpu_get_pc(), offset * 2);
	return segaic16_open_bus_r(0,0);
}


static WRITE16_HANDLER( standard_io_w )
{
	offset &= 0x1fff;
	switch (offset & (0x3000/2))
	{
		case 0x0000/2:
			/*
				D7 : 1 for most games, 0 for ddux, sdi, wb3
				D6 : 1= Screen flip, 0= Normal screen display
				D5 : 1= Display on, 0= Display off
				D4 : 0 for most games, 1 for eswat
				D3 : Output to lamp 2 (1= On, 0= Off)
				D2 : Output to lamp 1 (1= On, 0= Off)
				D1 : (Output to coin counter 2?)
				D0 : Output to coin counter 1
			*/
			segaic16_tilemap_set_flip(0, data & 0x40);
			segaic16_sprites_set_flip(0, data & 0x40);
			if (!disable_screen_blanking)
				segaic16_set_display_enable(data & 0x20);
			set_led_status(1, data & 0x08);
			set_led_status(0, data & 0x04);
			coin_counter_w(1, data & 0x02);
			coin_counter_w(0, data & 0x01);
			return;
	}
	logerror("%06X:standard_io_w - unknown write access to address %04X = %04X & %04X\n", activecpu_get_pc(), offset * 2, data, mem_mask ^ 0xffff);
}


static READ16_HANDLER( misc_io_r )
{
	if (custom_io_r)
		return (*custom_io_r)(offset, mem_mask);
	else
		return standard_io_r(offset, mem_mask);
}


static WRITE16_HANDLER( misc_io_w )
{
	if (custom_io_w)
		(*custom_io_w)(offset, data, mem_mask);
	else
		standard_io_w(offset, data, mem_mask);
}



/*************************************
 *
 *  Tile banking/math chips
 *
 *************************************/
static WRITE16_HANDLER( rom_5704_bank_w )
{
	if (ACCESSING_LSB)
		segaic16_tilemap_set_bank(0, offset & 1, data & 7);
}


static READ16_HANDLER( unknown_rgn2_r )
{
	logerror("Region 2: read from %04X\n", offset * 2);
	return segaic16_compare_timer_1_r(offset & 7, mem_mask);
}


static WRITE16_HANDLER( unknown_rgn2_w )
{
	logerror("Region 2: write to %04X = %04X & %04X\n", offset * 2, data, mem_mask ^ 0xffff);
	segaic16_compare_timer_1_w(offset & 7, data, mem_mask);
}



/*************************************
 *
 *  Sound interaction
 *
 *************************************/
static WRITE8_HANDLER( upd7759_control_w )
{
	int size = memory_region_length(REGION_CPU2) - 0x10000;
	if (size > 0)
	{
		int bankoffs = 0;

		/* it is important to write in this order: if the /START line goes low
           at the same time /RESET goes low, no sample should be started */
		upd7759_start_w(0, data & 0x80);
		upd7759_reset_w(0, data & 0x40);

		/*
			D5 : Unused
			D4 : Unused
			D3 : ROM select 0=A11, 1=A12
			D2 : A16 for all ROMs
			D1 : A15 for all ROMs
			D0 : A14 for all ROMs
		*/
		bankoffs = ((data & 0x08) >> 3) * 0x20000;
		bankoffs += (data & 0x07) * 0x4000;

		memory_set_bankptr(1, memory_region(REGION_CPU2) + 0x10000 + (bankoffs % size));
	}
}


static READ8_HANDLER( upd7759_status_r )
{
	return upd7759_busy_r(0) << 7;
}


static void upd7759_generate_nmi(int state)
{
	if (state)
		cpunum_set_input_line(1, INPUT_LINE_NMI, PULSE_LINE);
}


#if 0
static WRITE8_HANDLER( mcu_data_w )
{
	mcu_data = data;
	cpunum_set_input_line(2, 1, PULSE_LINE);
}
#endif



/*************************************
 *
 *  I8751 interrupt generation
 *
 *************************************/
static INTERRUPT_GEN( i8751_main_cpu_vblank )
{
	/* if we have a fake 8751 handler, call it on VBLANK */
	if (i8751_vblank_hook != NULL)
		(*i8751_vblank_hook)();
}



/*************************************
 *
 *  Per-game I8751 workarounds
 *
 *************************************/
static void fz2dx_i8751_sim(void)
{
	/* signal a VBLANK to the main CPU */
	cpunum_set_input_line(0, 4, HOLD_LINE);
}


/*************************************
 *
 *  Capacitor-backed RAM
 *
 *************************************/
static NVRAM_HANDLER( system16c )
{
	if (read_or_write)
		mame_fwrite(file, workram, 0x40000);
	else if (file)
		mame_fread(file, workram, 0x40000);
}



/*************************************
 *
 *  Main CPU memory handlers
 *
 *************************************/
static ADDRESS_MAP_START( system16c_map, ADDRESS_SPACE_PROGRAM, 16 )
	ADDRESS_MAP_FLAGS( AMEF_UNMAP(1) )
	AM_RANGE(0x000000, 0xffffff) AM_READWRITE(segaic16_memory_mapper_lsb_r, segaic16_memory_mapper_lsb_w)
ADDRESS_MAP_END



/*************************************
 *
 *  Sound CPU memory handlers
 *
 *************************************/
static ADDRESS_MAP_START( sound_map, ADDRESS_SPACE_PROGRAM, 8 )
	ADDRESS_MAP_FLAGS( AMEF_UNMAP(1) )
	AM_RANGE(0x0000, 0x7fff) AM_ROM
	AM_RANGE(0x8000, 0xdfff) AM_ROMBANK(1)
	AM_RANGE(0xe800, 0xe800) AM_READ(soundlatch_r)
	AM_RANGE(0xf800, 0xffff) AM_RAM
ADDRESS_MAP_END


static ADDRESS_MAP_START( sound_portmap, ADDRESS_SPACE_IO, 8 )
	ADDRESS_MAP_FLAGS( AMEF_UNMAP(1) | AMEF_ABITS(8) )
	AM_RANGE(0x00, 0x00) AM_MIRROR(0x3e) AM_WRITE(YM2151_register_port_0_w)
	AM_RANGE(0x01, 0x01) AM_MIRROR(0x3e) AM_READWRITE(YM2151_status_port_0_r, YM2151_data_port_0_w)
	AM_RANGE(0x40, 0x40) AM_MIRROR(0x3f) AM_WRITE(upd7759_control_w)
	AM_RANGE(0x80, 0x80) AM_MIRROR(0x3f) AM_READWRITE(upd7759_status_r, upd7759_0_port_w)
	AM_RANGE(0xc0, 0xc0) AM_MIRROR(0x3f) AM_READ(soundlatch_r)
ADDRESS_MAP_END



/*************************************
 *
 *  i8751 MCU memory handlers
 *
 *************************************/
static ADDRESS_MAP_START( mcu_map, ADDRESS_SPACE_PROGRAM, 8 )
	ADDRESS_MAP_FLAGS( AMEF_UNMAP(1) )
	AM_RANGE(0x0000, 0x0fff) AM_ROM
ADDRESS_MAP_END


static ADDRESS_MAP_START( mcu_data_map, ADDRESS_SPACE_DATA, 8 )
	ADDRESS_MAP_FLAGS( AMEF_UNMAP(1) )
	AM_RANGE(0x0000, 0x001f) AM_READWRITE(segaic16_memory_mapper_r, segaic16_memory_mapper_w)
ADDRESS_MAP_END



/*************************************
 *
 *  Generic port definitions
 *
 *************************************/
static INPUT_PORTS_START( system16c_generic )
	PORT_START_TAG("SERVICE")
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_SERVICE_NO_TOGGLE( 0x04, IP_ACTIVE_LOW )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE1 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )

	PORT_START_TAG("P1")
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY

	PORT_START_TAG("UNUSED")
	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START_TAG("P2")
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_COCKTAIL
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_COCKTAIL
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_COCKTAIL
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_COCKTAIL
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_COCKTAIL

	PORT_START_TAG("DSW1")
	PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWB:1")
	PORT_DIPSETTING(    0x01, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWB:2")
	PORT_DIPSETTING(    0x02, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWB:3")
	PORT_DIPSETTING(    0x04, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWB:4")
	PORT_DIPSETTING(    0x08, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWB:5")
	PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWB:6")
	PORT_DIPSETTING(    0x20, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWB:7")
	PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWB:8")
	PORT_DIPSETTING(    0x80, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )

	PORT_START_TAG("DSW2")
	PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWA:1")
	PORT_DIPSETTING(    0x01, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWA:2")
	PORT_DIPSETTING(    0x02, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWA:3")
	PORT_DIPSETTING(    0x04, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWA:4")
	PORT_DIPSETTING(    0x08, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWA:5")
	PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWA:6")
	PORT_DIPSETTING(    0x20, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWA:7")
	PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWA:8")
	PORT_DIPSETTING(    0x80, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
INPUT_PORTS_END



/*************************************
 *
 *  Game-specific port definitions
 *
 *************************************/
static INPUT_PORTS_START( fz2dx )
	PORT_INCLUDE( system16c_generic )

	PORT_MODIFY("DSW1")
	PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWB:1")
	PORT_DIPSETTING(    0x01, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWB:2")
	PORT_DIPSETTING(    0x02, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x0c, 0x0c, DEF_STR( Lives ) ) PORT_DIPLOCATION("SWB:3,4")
	PORT_DIPSETTING(    0x08, "2" )
	PORT_DIPSETTING(    0x0c, "3" )
	PORT_DIPSETTING(    0x04, "4" )
	PORT_DIPSETTING(    0x00, "Unlimited" )
	PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWB:5")
	PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SWB:6")
	PORT_DIPSETTING(    0x20, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SWB:7,8")
	PORT_DIPSETTING(    0x80, DEF_STR( Easy ) )
	PORT_DIPSETTING(    0xc0, DEF_STR( Normal ) )
	PORT_DIPSETTING(    0x40, DEF_STR( Hard ) )
	PORT_DIPSETTING(    0x00, DEF_STR( Hardest ) )
INPUT_PORTS_END



/*************************************
 *
 *  Sound definitions
 *
 *************************************/
static struct upd7759_interface upd7759_interface =
{
	0,
	upd7759_generate_nmi
};



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

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


static const gfx_decode gfxdecodeinfo[] =
{
	{ REGION_GFX1, 0, &charlayout,	0, 1024 },
	{ -1 }
};



/*************************************
 *
 *  Generic machine drivers
 *
 *************************************/
static MACHINE_DRIVER_START( system16c )
	/* basic machine hardware */
	MDRV_CPU_ADD_TAG("main", M68000, MASTER_CLOCK_10MHz)
	MDRV_CPU_PROGRAM_MAP(system16c_map,0)
	MDRV_CPU_VBLANK_INT(irq4_line_hold,1)

	MDRV_CPU_ADD_TAG("sound", Z80, MASTER_CLOCK_10MHz/2)
	MDRV_CPU_PROGRAM_MAP(sound_map,0)
	MDRV_CPU_IO_MAP(sound_portmap,0)

	MDRV_FRAMES_PER_SECOND(60)
	MDRV_VBLANK_DURATION(1000000 * (262 - 224) / (262 * 60))

	MDRV_MACHINE_RESET(system16c)
	MDRV_NVRAM_HANDLER(system16c)

	/* video hardware */
	MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
	MDRV_SCREEN_SIZE(40*8, 28*8)
	MDRV_VISIBLE_AREA(0*8, 40*8-1, 0*8, 28*8-1)
	MDRV_GFXDECODE(gfxdecodeinfo)
	MDRV_PALETTE_LENGTH(2048*3)

	MDRV_VIDEO_START(system16b)
	MDRV_VIDEO_UPDATE(system16b)

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

	MDRV_SOUND_ADD_TAG("2151", YM2151, MASTER_CLOCK_8MHz/2)
	MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.43)

	MDRV_SOUND_ADD_TAG("7759", UPD7759, UPD7759_STANDARD_CLOCK)
	MDRV_SOUND_CONFIG(upd7759_interface)
	MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.48)
MACHINE_DRIVER_END


static MACHINE_DRIVER_START( system16c_8751 )
	MDRV_IMPORT_FROM(system16c)
	MDRV_CPU_MODIFY("main")
	MDRV_CPU_VBLANK_INT(i8751_main_cpu_vblank,1)

	MDRV_CPU_ADD_TAG("mcu", I8751, MASTER_CLOCK_8MHz)
	MDRV_CPU_PROGRAM_MAP(mcu_map,0)
	MDRV_CPU_DATA_MAP(mcu_data_map,0)
	MDRV_CPU_VBLANK_INT(irq0_line_pulse,1)
MACHINE_DRIVER_END



/*************************************
 *
 *  ROM definition(s)
 *
 *************************************/
/**************************************************************************************************************************
    Fantasy Zone II System16C
    CPU: 68000
    ROM Board: 171-5704 custom
*/
ROM_START( fz2dx )
	ROM_REGION( 0xc0000, REGION_CPU1, 0 )					/* 68000 code */
	ROM_LOAD16_WORD_SWAP( "fz2_s16c.p00", 0x00000, 0x40000, CRC(B7D16C1D) SHA1(7587A0E4FA64664F53D7BA48D711B6D26ADD6220) )
	ROM_LOAD16_WORD_SWAP( "fz2_s16c.p01", 0x80000, 0x40000, CRC(2C47487C) SHA1(0E3A524DAE50E5B099396EF712CE45EA147B424B) )

	ROM_REGION( 0x60000, REGION_GFX1, ROMREGION_DISPOSE )	/* tiles */
	ROM_LOAD( "fz2_s16c.bg",  0x00000, 0x60000, CRC(C092DC23) SHA1(CC7980B8AF9FED7A1CDF70CBBE6A2A67BB79594F) )

	ROM_REGION16_BE( 0x200000, REGION_GFX2, 0 )				/* sprites */
	ROM_LOAD( "fz2_s16c.obj", 0x000000, 0x200000, CRC(57753F79) SHA1(7566CEF4344FBE7FB7ADC476113CD6E8780AEEF4) )

	ROM_REGION( 0x50000, REGION_CPU2, 0 )					/* sound CPU */
	ROM_LOAD( "fz2_s16c.snd", 0x00000, 0x30000, CRC(0ED30EC1) SHA1(EDF2DBD6A35394849E0419C518C6FB0F4ACCB9D1) )
ROM_END



/*************************************
 *
 *  Generic driver initialization
 *
 *************************************/
static DRIVER_INIT( system16c_generic )
{
	system16c_generic_init();
}



/*************************************
 *
 *  Game-specific driver inits
 *
 *************************************/
static DRIVER_INIT( fz2dx_8751 )
{
	init_system16c_generic();
	i8751_vblank_hook = fz2dx_i8751_sim;
}



/*************************************
 *
 *  Game driver(s)
 *
 *************************************/
GAME( 1987, fz2dx, 0, system16c_8751, fz2dx, fz2dx_8751, ROT0, "Sega / M2", "Fantasy Zone II DX", 0 )

