/*

 Multi 5 / New Multi Game 5		(c) 1998 Yun Sung
 driver by Pierpaolo Prazzoli

 Press player 2 button 2 in service mode to enable image test

*/

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

static struct tilemap *fg_tilemap,*bg_tilemap;
data16_t *nmg5_bitmap;
static data16_t *fgvideoram,*bgvideoram;

static WRITE16_HANDLER( fgvideoram_w )
{
	int oldword = fgvideoram[offset];
	COMBINE_DATA(&fgvideoram[offset]);
	if (oldword != fgvideoram[offset])
		tilemap_mark_tile_dirty(fg_tilemap,offset);
}

static WRITE16_HANDLER( bgvideoram_w )
{
	int oldword = bgvideoram[offset];
	COMBINE_DATA(&bgvideoram[offset]);
	if (oldword != bgvideoram[offset])
		tilemap_mark_tile_dirty(bg_tilemap,offset);
}

static WRITE16_HANDLER( nmg5_soundlatch_w )
{
	if (ACCESSING_LSB)
	{
		soundlatch_w(0,data & 0xff);
		cpu_set_nmi_line(1, PULSE_LINE);
	}
}

static MEMORY_READ16_START( nmg5_readmem )
	{ 0x000000, 0x0fffff, MRA16_ROM },
	{ 0x120000, 0x1607ff, MRA16_RAM },
	{ 0x180004, 0x180005, MRA16_NOP },
	{ 0x180008, 0x180009, input_port_0_word_r },
	{ 0x18000a, 0x18000b, input_port_1_word_r },
	{ 0x18000c, 0x18000d, input_port_2_word_r },
	{ 0x320000, 0x80ffff, MRA16_RAM },
MEMORY_END

static MEMORY_WRITE16_START( nmg5_writemem )
	{ 0x000000, 0x0fffff, MWA16_ROM },
	{ 0x120000, 0x12ffff, MWA16_RAM },
	{ 0x140000, 0x1407ff, paletteram16_xBBBBBGGGGGRRRRR_word_w, &paletteram16 },
	{ 0x160000, 0x1607ff, MWA16_RAM, &spriteram16, &spriteram_size },
	{ 0x180000, 0x180001, nmg5_soundlatch_w },
	{ 0x180002, 0x180003, MWA16_NOP },
	{ 0x180004, 0x180005, MWA16_NOP },
	{ 0x180006, 0x180007, MWA16_NOP },
	{ 0x300000, 0x300001, MWA16_NOP },
	{ 0x300002, 0x300009, MWA16_NOP },
	{ 0x30000a, 0x30000b, MWA16_NOP },
	{ 0x30000c, 0x30000d, MWA16_NOP },
	{ 0x30000e, 0x30000f, MWA16_NOP },
	{ 0x320000, 0x321fff, bgvideoram_w, &bgvideoram },
	{ 0x322000, 0x323fff, fgvideoram_w, &fgvideoram },
	{ 0x800000, 0x80ffff, MWA16_RAM, &nmg5_bitmap },
MEMORY_END

static MEMORY_READ_START( nmg5_sound_readmem )
	{ 0x0000, 0xcfff, MRA_ROM },
	{ 0xe000, 0xe7ff, MRA_RAM },
MEMORY_END

static MEMORY_WRITE_START( nmg5_sound_writemem )
	{ 0x0000, 0xcfff, MWA_ROM },
	{ 0xe000, 0xe7ff, MWA_RAM },
MEMORY_END

static PORT_READ_START( nmg5_sound_readport )
	{ 0x10, 0x10, YM3812_status_port_0_r },
	{ 0x18, 0x18, soundlatch_r },
	{ 0x1c, 0x1c, OKIM6295_status_0_r },
PORT_END

static PORT_WRITE_START( nmg5_sound_writeport )
	{ 0x10, 0x10, YM3812_control_port_0_w },
	{ 0x11, 0x11, YM3812_write_port_0_w },
	{ 0x1c, 0x1c, OKIM6295_data_0_w },
PORT_END

INPUT_PORTS_START( nmg5 )
	PORT_START
	PORT_DIPNAME( 0x0001, 0x0001, "Game Title" )
	PORT_DIPSETTING(      0x0001, "Multi 5" )
	PORT_DIPSETTING(      0x0000, "New Multi Game 5" )
	PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) )
	PORT_DIPSETTING(      0x0002, DEF_STR( Off ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
	PORT_DIPNAME( 0x0004, 0x0004, DEF_STR( Unknown ) )
	PORT_DIPSETTING(      0x0004, DEF_STR( Off ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
	PORT_DIPNAME( 0x0018, 0x0018, "License" )
	PORT_DIPSETTING(      0x0000, "New Impeuropex Corp. S.R.L." )
	PORT_DIPSETTING(      0x0008, "BNS Enterprises" )
	PORT_DIPSETTING(      0x0010, "Nova Games" )
	PORT_DIPSETTING(      0x0018, "None" )
	PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) )
	PORT_DIPSETTING(      0x0020, DEF_STR( Off ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
	PORT_DIPNAME( 0x00c0, 0x00c0, DEF_STR( Difficulty ) )
	PORT_DIPSETTING(      0x0000, "Hardest" )
	PORT_DIPSETTING(      0x0080, "Hard" )
	PORT_DIPSETTING(      0x00c0, "Normal" )
	PORT_DIPSETTING(      0x0040, "Easy" )
	PORT_DIPNAME( 0x0300, 0x0300, "Coin_B" )
	PORT_DIPSETTING(      0x0000, "2C_3C 1C_6C" )
	PORT_DIPSETTING(      0x0100, "1C_2C 1C_3C" )
	PORT_DIPSETTING(      0x0200, "2C_1C 1C_4C" )
	PORT_DIPSETTING(      0x0300, "1C_1C 1C_1C" )
	PORT_DIPNAME( 0x0c00, 0x0c00, "Coin_A" )
	PORT_DIPSETTING(      0x0800, "2C_1C 3C_1C" )
	PORT_DIPSETTING(      0x0c00, "1C_1C 1C_1C" )
	PORT_DIPSETTING(      0x0000, "2C_3C 4C_1C" )
	PORT_DIPSETTING(      0x0400, "1C_2C 2C_1C" )
	PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Flip_Screen ) ) /* doesn't work */
	PORT_DIPSETTING(      0x1000, DEF_STR( Off ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
	PORT_DIPNAME( 0x2000, 0x0000, DEF_STR( Demo_Sounds ) )
	PORT_DIPSETTING(      0x2000, DEF_STR( Off ) )
	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
	PORT_DIPNAME( 0x4000, 0x4000, "Coin Type" )
	PORT_DIPSETTING(      0x4000, "1" )
	PORT_DIPSETTING(      0x0000, "2" )
	PORT_SERVICE( 0x8000, IP_ACTIVE_LOW )

	PORT_START	/* Coins */
	PORT_BIT( 0x0001, IP_ACTIVE_LOW,  IPT_COIN1 )
	PORT_BIT( 0x0002, IP_ACTIVE_LOW,  IPT_COIN2 )
	PORT_BIT( 0x0050, IP_ACTIVE_HIGH, IPT_SPECIAL ) // otherwise it doesn't boot
	PORT_BIT( 0xffac, IP_ACTIVE_LOW,  IPT_UNUSED )  // tested in service mode

	PORT_START
	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_4WAY | IPF_PLAYER1 )
	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_4WAY | IPF_PLAYER1 )
	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_4WAY | IPF_PLAYER1 )
	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_4WAY | IPF_PLAYER1 )
	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER1 )
	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER1 )
	PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON3 | IPF_PLAYER1 )
	PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_4WAY | IPF_PLAYER2 )
	PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_4WAY | IPF_PLAYER2 )
	PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_4WAY | IPF_PLAYER2 )
	PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_4WAY | IPF_PLAYER2 )
	PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
	PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 | IPF_PLAYER2 )
	PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 | IPF_PLAYER2 )
	PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_START2 )
INPUT_PORTS_END


INLINE void get_tile_info(int tile_index,data16_t *vram,int color)
{
	SET_TILE_INFO(0,vram[tile_index],color,0)
}

static void fg_get_tile_info(int tile_index) { get_tile_info(tile_index,fgvideoram, 0); }
static void bg_get_tile_info(int tile_index) { get_tile_info(tile_index,bgvideoram, 1); }

VIDEO_START( nmg5 )
{
	bg_tilemap = tilemap_create(bg_get_tile_info,tilemap_scan_rows,TILEMAP_OPAQUE,     8,8,64,64);
	fg_tilemap = tilemap_create(fg_get_tile_info,tilemap_scan_rows,TILEMAP_TRANSPARENT,8,8,64,64);

	if (!bg_tilemap || !fg_tilemap)
		return 1;

	tilemap_set_transparent_pen(fg_tilemap,0);

	return 0;
}

static void draw_sprites(struct mame_bitmap *bitmap,const struct rectangle *cliprect)
{
	int offs;

	for (offs = 0;offs < spriteram_size/2;offs += 4)
	{
		int sx,sy,code,color,flipx,flipy,height,y;

		sx = spriteram16[offs + 2];
		sy = spriteram16[offs + 0];
		code = spriteram16[offs + 1];
		color = (spriteram16[offs + 2] >> 9)&0xf;
		height = 1 << ((spriteram16[offs + 0] & 0x0600) >> 9);
		flipx = spriteram16[offs + 0] & 0x2000;
		flipy = spriteram16[offs + 0] & 0x4000;

		for (y = 0;y < height;y++)
		{
			drawgfx(bitmap,Machine->gfx[1],
					code + (flipy ? height-1 - y : y),
					color,
					flipx,flipy,
					sx & 0x1ff,248 - ((sy + 0x10 * (height - y)) & 0x1ff),
					cliprect,TRANSPARENCY_PEN,0);

			/* wrap around */
			drawgfx(bitmap,Machine->gfx[1],
					code + (flipy ? height-1 - y : y),
					color,
					flipx,flipy,
					(sx & 0x1ff) - 512,248 - ((sy + 0x10 * (height - y)) & 0x1ff),
					cliprect,TRANSPARENCY_PEN,0);
		}
	}
}

void draw_bitmap(struct mame_bitmap *bitmap)
{
	int yyy=256;
	int xxx=512/4;
	UINT16 x,y,count;
	int xoff=-12;
	int yoff=-9;
	int pix;

	count=0;
	for (y=0;y<yyy;y++)
	{
		for(x=0;x<xxx;x++)
		{
			pix = (nmg5_bitmap[count]&0xf000)>>12;
			if (pix) plot_pixel(bitmap, x*4+xoff,y+yoff, pix);
			pix = (nmg5_bitmap[count]&0x0f00)>>8;
			if (pix) plot_pixel(bitmap, x*4+1+xoff,y+yoff, pix);
			pix = (nmg5_bitmap[count]&0x00f0)>>4;
			if (pix) plot_pixel(bitmap, x*4+2+xoff,y+yoff, pix);
			pix = (nmg5_bitmap[count]&0x000f)>>0;
			if (pix) plot_pixel(bitmap, x*4+3+xoff,y+yoff, pix);

			count++;
		}
	}
}


VIDEO_UPDATE( nmg5 )
{
	tilemap_draw(bitmap,cliprect,bg_tilemap,0,0);
	tilemap_draw(bitmap,cliprect,fg_tilemap,0,0);
	draw_bitmap(bitmap);
	draw_sprites(bitmap,cliprect);
}


static struct GfxLayout layout_8x8x8 =
{
	8,8,
	RGN_FRAC(1,8),
	8,
	{ RGN_FRAC(7,8),RGN_FRAC(6,8),RGN_FRAC(5,8),RGN_FRAC(4,8),RGN_FRAC(3,8),RGN_FRAC(2,8),RGN_FRAC(1,8),RGN_FRAC(0,8) },
	{ 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 struct GfxLayout layout_16x16x5 =
{
	16,16,
	RGN_FRAC(1,5),
	5,
	{ RGN_FRAC(2,5),RGN_FRAC(3,5),RGN_FRAC(1,5),RGN_FRAC(4,5),RGN_FRAC(0,5) },
	{ 7,6,5,4,3,2,1,0,135,134,133,132,131,130,129,128 },
	{ 0*8,1*8,2*8,3*8,4*8,5*8,6*8,7*8,8*8,9*8,10*8,11*8,12*8,13*8,14*8,15*8 },
	32*8
};

static struct GfxDecodeInfo nmg5_gfxdecodeinfo[] =
{
	{ REGION_GFX1, 0, &layout_8x8x8,   0x000,  2 },
	{ REGION_GFX2, 0, &layout_16x16x5, 0x200, 16 },
	{ -1 }
};


static void soundirq(int state)
{
	cpu_set_irq_line(1, 0, state);
}

static struct YM3812interface ym3812_intf =
{
	1,
	4000000,		/* ? */
	{ 100 },
	{ soundirq },	/* IRQ Line */
};

static struct OKIM6295interface okim6295_intf =
{
	1,
	{ 8000 },	/* ? */
	{ REGION_SOUND1 },
	{ 100 }
};

static MACHINE_DRIVER_START( nmg5 )

	/* basic machine hardware */
	MDRV_CPU_ADD(M68000, 16000000)	/* 16 MHz ? */
	MDRV_CPU_MEMORY(nmg5_readmem,nmg5_writemem)
	MDRV_CPU_VBLANK_INT(irq6_line_hold,1)

	MDRV_CPU_ADD(Z80, 3000000)		/* 3 MHz ? */
	MDRV_CPU_FLAGS(CPU_AUDIO_CPU)
	MDRV_CPU_MEMORY(nmg5_sound_readmem,nmg5_sound_writemem)
	MDRV_CPU_PORTS(nmg5_sound_readport,nmg5_sound_writeport)

	MDRV_FRAMES_PER_SECOND(60)
	MDRV_VBLANK_DURATION(DEFAULT_60HZ_VBLANK_DURATION)

	/* video hardware */
	MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
	MDRV_SCREEN_SIZE(320, 256)
	MDRV_VISIBLE_AREA(0, 319, 0, 239)
	MDRV_GFXDECODE(nmg5_gfxdecodeinfo)
	MDRV_PALETTE_LENGTH(0x400)

	MDRV_VIDEO_START(nmg5)
	MDRV_VIDEO_UPDATE(nmg5)

	/* sound hardware */
	MDRV_SOUND_ADD(YM3812, ym3812_intf)
	MDRV_SOUND_ADD(OKIM6295, okim6295_intf)
MACHINE_DRIVER_END


ROM_START( nmg5 )
	ROM_REGION( 0x100000, REGION_CPU1, 0 )		/* 68000 Code */
	ROM_LOAD16_BYTE( "ub15.bin", 0x000000, 0x80000, 0x36af3e2f )
	ROM_LOAD16_BYTE( "ub16.bin", 0x000001, 0x80000, 0x2d9923d4 )

	ROM_REGION( 0x10000, REGION_CPU2, 0 )		/* Z80 Code */
	ROM_LOAD( "xh15.bin", 0x00000, 0x10000, 0x12d047c4 )

	ROM_REGION( 0x400000, REGION_GFX1, ROMREGION_DISPOSE )	/* 8x8x8 */
	ROM_LOAD( "srom1.bin", 0x000000, 0x80000, 0x6771b694 )
	ROM_LOAD( "srom2.bin", 0x080000, 0x80000, 0x362d33af )
	ROM_LOAD( "srom3.bin", 0x100000, 0x80000, 0x8bad69d1 )
	ROM_LOAD( "srom4.bin", 0x180000, 0x80000, 0xe73a7fcb )
	ROM_LOAD( "srom5.bin", 0x200000, 0x80000, 0x7300494e )
	ROM_LOAD( "srom6.bin", 0x280000, 0x80000, 0x74b5fdf9 )
	ROM_LOAD( "srom7.bin", 0x300000, 0x80000, 0xbd2b9036 )
	ROM_LOAD( "srom8.bin", 0x380000, 0x80000, 0xdd38360e )

	ROM_REGION( 0x140000, REGION_GFX2, ROMREGION_DISPOSE )	/* 16x16x5 */
	ROM_LOAD( "uf1.bin", 0x000000, 0x40000, 0x9a9fb6f4 )
	ROM_LOAD( "uf2.bin", 0x040000, 0x40000, 0x66954d63 )
	ROM_LOAD( "ufa1.bin",0x080000, 0x40000, 0xba73ed2d )
	ROM_LOAD( "uh1.bin", 0x0c0000, 0x40000, 0xf7726e8e )
	ROM_LOAD( "uj1.bin", 0x100000, 0x40000, 0x54f7486e )

	ROM_REGION( 0x20000, REGION_SOUND1, ROMREGION_SOUNDONLY )	/* Samples */
	ROM_LOAD( "xra1.bin", 0x00000, 0x20000, 0xc74a4f3e )
ROM_END

GAME( 1998, nmg5, 0, nmg5, nmg5, 0, ROT0, "Yun Sung", "Multi 5 / New Multi Game 5" )
