/*
Preliminary WIP for:

	Dark Adventure (also known as "Devil's World")
	(C) Konami 1987; board code is GX687

	Vulcan Venture

"Konami Twin 16" hardware

The main processors are a pair of 68000 CPUs.
The sounds are generated by a Z80, a Yamaha 2151 and 3012, a Konami custom IC and a UPD7759C.

        DARK ADVENTURE   CHIP PLACEMENT

USES 68000 CPU & Z80 W/YM2151 SOUND

CHIP #  POSITION  TYPE
----------------------
N03      10A      27256    CONN BD (32k) Z80: sound
N08      4R        "        " 64k (sound samples?)

N04      4N       27512     " CPUA
N05      6N        "        " CPUA
N06      8N        "        " CPUB
N07      10N       "        " CPUB

N10      8R        "        " 64k (tiles)
N11      10R       "        " 64k (tiles)
N12      8S        "        " 64k (sprites?)
N13      10S       "        " 64k (sprites?)

N14      3F       27128    BOTTOM BD (alphanumerics)

Preliminary Memory Map:
	address range		type	label/desc (from Dark Adventure ROM test screen)
	0x000000..0x03ffff	ROM
	0x040000..0x043fff	RAM		(10G, 10E)	shared working RAM
	0x060000..0x063fff	RAM		(4S, 6S)
	0x080000..0x080fff	RAM		(1U)		palette RAM? 8 bit bus
	0x081000..0x09ffff	ROM		(?)
	0x0a0000..0x0a0001						interrupt
	0x100000..0x103fff	RAM		(3a, 3b)	videoram: text layer
	0x120000..0x123fff	RAM		(?)
	0x140000..0x143fff	RAM		(?)
	0x400000..0x403fff	RAM		(3L, 3M)	shared
	0x480000..0x483fff	RAM		(8A, 8B)	shared vram? CPUB writes exception text here
	0x500000..0x53ffff	RAM		("ZIP3,4,2,5")
	0x600000..0x77ffff	ROM
	0x780000..0x79ffff	RAM		(8L, 8M)
*/

#include "driver.h"
#include "vidhrdw/generic.h"
#include "cpu/m68000/m68000.h"

static struct YM2151interface ym2151_interface = {
	1,			/* 1 chip */
	7159160/2,	/* 3.58 MHZ ? */
	{ YM3012_VOL(50,MIXER_PAN_LEFT,50,MIXER_PAN_RIGHT) },
	{ 0 }
};

static unsigned char *working_ram;

/* for now, just use one huge slab of RAM */
static int rmem( int offset ){
	return READ_WORD(&working_ram[offset]);
}
static void wmem( int offset, int data ){
	COMBINE_WORD_MEM(&working_ram[offset],data);
}

static int vh_start( void ){
/* uncomment following to patch out ROM checksum failure for Dark Adventure;
	it'll proceed a bit further before locking up*/

/*
	UINT16 *mem = (UINT16 *)Machine->memory_region[0];
	mem[0x0F3E/2] = 0x4e71;
	mem[0x0F40/2] = 0x4e71;
	mem[0x0F6A/2] = 0x4e71;
	mem[0x0F6C/2] = 0x4e71;
*/
	return 0;
}

static void vh_stop( void ){
}

static void vh_screenrefresh( struct osd_bitmap *bitmap, int fullrefresh ){
	const struct rectangle *clip = &Machine->drv->visible_area;
	static int offs;
	UINT16 *source = offs*0x1000 + (UINT16 *)(0x100000-0x040000+working_ram);//videoram;
	int i;

	palette_recalc();

	/* draw fixed text layer */
	for( i=0; i<64*64; i++ ){
		int sx = (i%64)*8;
		int sy = (32 - i/64)*8;
		int code = source[i];
		if( code==0 ) code = 0x1ff;
		drawgfx( bitmap, Machine->gfx[0],
			code,4,
			0,0,
			sx,sy,
			clip,TRANSPARENCY_NONE,0);
	}
}

static struct GfxLayout alpha_layout = {
	8,8,
	0x200,
	4,
	{ 0,1,2,3 },
	{ 0*4,1*4,2*4,3*4,4*4,5*4,6*4,7*4 },
	{ 0*32,1*32,2*32,3*32,4*32,5*32,6*32,7*32 },
	8*32
};

static struct GfxLayout tile_layout = {
	8,8,
	0x1000,
	4,
	{ 0,1,2,3 },
	{ 0*4,1*4,2*4,3*4,4*4,5*4,6*4,7*4 },
	{ 7*32,6*32,5*32,4*32,3*32,2*32,1*32,0*32 },
	8*32
};

static struct GfxDecodeInfo gfxdecodeinfo[] = {
	{ 2, 0x00000, &alpha_layout, 0, 64 },
	{ 2, 0x04000, &tile_layout,	0, 64 },
	{ -1 }
};

static int port1_r( int offset ){
	static int k;
	k = 1-k;
	return k;
}

int darkadv_interrupt( void ){
	return MC68000_IRQ_5; /* ? */
	/*
		IRQ_6 is a triggered interrupt, from the other CPU
		IRQ_5 looks to be reset-related; it's normally masked out
	*/
}

static void CPUA_int_trigger( int offset, int data ){
	static UINT16 reg;
	UINT16 new_reg = COMBINE_WORD( reg, data );
	if( (reg&0x01)==0 && (new_reg&0x01) ){ // 0->1 transition
		cpu_cause_interrupt( 0, MC68000_IRQ_6 );
	}
	new_reg = reg;
}
static void CPUB_int_trigger( int offset, int data ){
	static UINT16 reg;
	UINT16 new_reg = COMBINE_WORD( reg, data );
	if( (reg&0x10)==0 && (new_reg&0x10) ){ // 0->1 transition
		cpu_cause_interrupt( 1, MC68000_IRQ_6 );
	}
	new_reg = reg;
}

static struct MemoryReadAddress readmem[] = {
	{ 0x000000, 0x03ffff, MRA_ROM },
	{ 0x0c000e, 0x0c000f, port1_r }, /* vblank? ack? - CPUA expects this to toggle */
	{ 0x040000, 0x79ffff, rmem, &working_ram },
	{ -1 }
};

static struct MemoryWriteAddress writemem[] = {
	{ 0x000000, 0x03ffff, MWA_ROM },
	{ 0x0a0000, 0x0a0001, CPUB_int_trigger },
//	{ 0x100000, 0x100001, MWA_NOP },
//	{ 0x0a0010, 0x0a0011, MWA_NOP }, /* watchdog? */
	{ 0x040000, 0x79ffff, wmem },
	{ -1 }
};

static struct MemoryReadAddress readmem_sub[] = {
	{ 0x000000, 0x03ffff, MRA_ROM },
	{ 0x040000, 0x79ffff, rmem },
	{ -1 }
};

static struct MemoryWriteAddress writemem_sub[] = {
	{ 0x000000, 0x03ffff, MWA_ROM },
	{ 0x810000, 0x810001, MWA_NOP },
	{ 0x0a0000, 0x0a0001, CPUA_int_trigger },
	{ 0x040000, 0x79ffff, wmem },
	{ -1 }
};

static struct MemoryReadAddress readmem_sound[] = {
	{ 0x0000, 0x7fff, MRA_ROM },
	{ 0x8000, 0x8fff, MRA_RAM },
	{ 0xa000, 0xa000, soundlatch_r },
	{ 0xc001, 0xc001, YM2151_status_port_0_r },
	{ -1 }
};

static struct MemoryWriteAddress writemem_sound[] = {
	{ 0x0000, 0x7fff, MWA_ROM },
	{ 0x8000, 0x8fff, MWA_RAM },
	{ 0x9000, 0x9000, MWA_NOP },
	{ 0xb000, 0xb00f, MWA_NOP },
	{ 0xc000, 0xc000, YM2151_register_port_0_w },
	{ 0xc001, 0xc001, YM2151_data_port_0_w },
	{ 0xd000, 0xd000, MWA_NOP },
	{ 0xe000, 0xe000, MWA_NOP },
	{ -1 }
};

static struct MachineDriver machine_driver =
{
	{
		{
			CPU_M68010,
			6000000,
			0,
			readmem,writemem,0,0,
			darkadv_interrupt,1
		},
		{
			CPU_M68010,
			6000000,
			1,
			readmem_sub,writemem_sub,0,0,
			darkadv_interrupt,1
		},
		{
			CPU_Z80 | CPU_AUDIO_CPU,
			4000000,
			3,
			readmem_sound,writemem_sound,0,0,
			interrupt,1
		},
	},
	60, DEFAULT_REAL_60HZ_VBLANK_DURATION,
	100, /* CPU slices */
	0, /* init machine */

	/* video hardware */
	320, 256, { 0, 319, 0, 255 },
	gfxdecodeinfo,
	2048,2048, /* ? */
	0,

	VIDEO_TYPE_RASTER | VIDEO_MODIFIES_PALETTE,
	0,
	vh_start,
	vh_stop,
	vh_screenrefresh,

	/* sound hardware */
	0,0,0,0,
	{
		{
			SOUND_YM2151,
			&ym2151_interface
		}
	}
};

/* the following Dark Adventure set is almost certainly incomplete */
ROM_START( darkadv_rom )
	ROM_REGION( 0x40000 ) /* 68000 code (CPU A) */
	ROM_LOAD_ODD(	"n04.4n",	0x00000, 0x10000, 0x65b55105 )
	ROM_LOAD_EVEN(	"n05.6n",	0x00000, 0x10000, 0xa9195b0b )

	ROM_LOAD_ODD(	"n06.8n",	0x00000, 0x10000, 0x37a72e8b )
	ROM_LOAD_EVEN(	"n07.10n",	0x00000, 0x10000, 0x6154322a )

	ROM_REGION( 0x24000 )
	ROM_LOAD(			"n14.3f",	0x0000,  0x4000, 0xc76ac6d2 ) /* characters */

	/* note: the following tiles form recognizable pictures if you lay them out in rows of 128 pixels */
	ROM_LOAD_GFX_ODD(	"n10.8r",	0x04000, 0x10000, 0x117c91ee ) /* tiles */
	ROM_LOAD_GFX_EVEN(	"n11.10r",	0x04000, 0x10000, 0x399deee8 )
/*
	ROM_LOAD( "n08.4r",		0x00000, 0x10000, 0xa9603196 )
	ROM_LOAD_ODD(	"n12.8s",	0x20000, 0x10000, 0xda221944 ) (gfx?)
	ROM_LOAD_EVEN(	"n13.10s",	0x20000, 0x10000, 0xf1c252af )
*/
	ROM_REGION( 0x20000 ) /* Z80 code (sound CPU) */
	ROM_LOAD( "n03.10a",	0x00000,  0x8000, 0xa24c682f )
ROM_END

ROM_START( vulcan_rom )
	ROM_REGION( 0x40000 ) /* 68000 code (CPU A) */
	ROM_LOAD_ODD(	"vulcan.w04", 0x00000, 0x10000, 0x23ec74ca )
	ROM_LOAD_EVEN(	"vulcan.w05", 0x00000, 0x10000, 0x6e0e99cd )
	ROM_LOAD_ODD(	"vulcan.w08", 0x20000, 0x10000, 0x813d41ea )
	ROM_LOAD_EVEN(	"vulcan.w09", 0x20000, 0x10000, 0x377e4f28 )

	ROM_REGION( 0x40000 ) /* 68000 code (CPU B) */
	ROM_LOAD_ODD(	"vulcan.p06", 0x00000, 0x10000, 0x70c94bee )
	ROM_LOAD_EVEN(	"vulcan.p07", 0x00000, 0x10000, 0x686d549d )
	ROM_LOAD_ODD(	"vulcan.p12", 0x20000, 0x10000, 0x38ea402a )
	ROM_LOAD_EVEN(	"vulcan.p13", 0x20000, 0x10000, 0x478fdb0a )

	ROM_REGION( 0x24000 )
	ROM_LOAD(		"vulcan.h14",	0x00000,  0x4000, 0x02f4b16f ) /* characters */

/* graphics, to be unpacked
	ROM_LOAD_ODD(	"vulcan.f01",	0x00000, 0x20000, 0xa0d8d69e )
	ROM_LOAD_EVEN(	"vulcan.f02",	0x00000, 0x20000, 0xc39f5ca4 )

	ROM_LOAD_ODD(	"vulcan.f15",	0x00000, 0x80000, 0xaf96aef3 )
	ROM_LOAD_EVEN(	"vulcan.f16",	0x00000, 0x80000, 0xb858df1f )
	ROM_LOAD_ODD(	"vulcan.f17",	0x00000, 0x80000, 0x8fbec1a4 )
	ROM_LOAD_EVEN(	"vulcan.f18",	0x00000, 0x80000, 0x50d61e38 )
*/

	ROM_REGION( 0x20000 ) /* Z80 code (sound CPU) */
	ROM_LOAD( "vulcan.g03",	0x00000,  0x8000, 0x67a3b50d )
ROM_END



INPUT_PORTS_START( darkadv_input_ports ) /* fake */
	PORT_START
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN  | IPF_PLAYER1 | IPF_8WAY )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_UP    | IPF_PLAYER1 | IPF_8WAY )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER1 | IPF_8WAY )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT  | IPF_PLAYER1 | IPF_8WAY )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER1 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 | IPF_PLAYER1 )
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
INPUT_PORTS_END

struct GameDriver darkadv_driver =  {
	__FILE__,
	0,
	"darkadv",
	"Dark Adventure",
	"1987",
	"Konami",
	"CREDITS",
	GAME_NOT_WORKING,
	&machine_driver,
	0,
	darkadv_rom,
	0,
	0,
	0,
	0,	/* sound_prom */

	darkadv_input_ports,

	0, 0, 0, /* colors, palette, colortable */
	ORIENTATION_DEFAULT,
	0,0
};


struct GameDriver vulcan_driver =  {
	__FILE__,
	0,
	"vulcan",
	"Vulcan Venture",
	"????",
	"Konami",
	"CREDITS",
	GAME_NOT_WORKING,
	&machine_driver,
	0,
	vulcan_rom,
	0,
	0,
	0,
	0,	/* sound_prom */

	darkadv_input_ports,

	0, 0, 0, /* colors, palette, colortable */
	ORIENTATION_DEFAULT,
	0,0
};
