/*******************************************
      Seta custom ST-0016 chip based games.
	driver by Tomasz Slanina	
********************************************


Todo:
- sound
   Sound registers - $100 bytes @ $e900 ($20x8)
   8 channels ??
   ---------------------------------
  00-03 | start address  
  04-07 | loop start
  08-0b | loop end
  0c-0f | end address
  10-11 | freq (looks like 16.16 fixed point where 0x10000 = 44100, 0x08000 = 22050, 0x04000 = 11025)
  12-13 | unknown (0)
  14-15 | 2x 8bit channel volumes
  16    | flags.  bit 0 = loop, bits 1 + 2 = active (0x06 written to key on one-shot sounds, 0x07 for loops)
  17-1f | unknown
  ----------------------------------
  The last reg ($ff) is probably sound enable/mode

- find NMI source, and NMI enable/disable (timer ? video hw ?)
- nerate chu - missing text (sprites) in test mode (press down+button for video test)
- nerate chu - dip switches

Not working games :
- Super Real Mahjong P5	
- Super Eagle Shot
- Mayjinsen
- Mayjinsen 2

--
Renjyu Kizoku
Visco, 1994

PCB Layout

E51-00001-A
|------------------------------------|
|AMP       UPD6376    424400  62256  |
|    VOL      RESET   424400  62256  |
|                                    |
| TD62064 74273                      |
|J        74273                      |
|A        74273            42.9545MHz|
|M                                   |
|M        74245         UNKNOWN      |
|A        74245          QFP208      |
|         74245                      |
|         74245                 48MHz|
|                                    |
|  74138  74138                      |
|  74253  74253       RNJ2           |
|                                    |
|  DSW1   DSW2        RENJYU-1  6264 |
|------------------------------------|
*/

#include "driver.h"
#include "cpu/z80/z80.h" 
#include "cpu/mips/r3000.h"

WRITE_HANDLER (st0016_sprite_bank_w);
WRITE_HANDLER (st0016_palette_bank_w);
WRITE_HANDLER (st0016_character_bank_w);
READ_HANDLER  (st0016_sprite_ram_r);
WRITE_HANDLER (st0016_sprite_ram_w);
READ_HANDLER  (st0016_sprite2_ram_r);
WRITE_HANDLER (st0016_sprite2_ram_w);
READ_HANDLER  (st0016_palette_ram_r);
WRITE_HANDLER (st0016_palette_ram_w);
READ_HANDLER  (st0016_character_ram_r);
WRITE_HANDLER (st0016_character_ram_w);
READ_HANDLER(st0016_vregs_r);
WRITE_HANDLER(st0016_vregs_w);

VIDEO_START(st0016);
VIDEO_UPDATE(st0016);
extern int st0016_game;
void st0016_save_init(void);
static int mux_port;
int st0016_rom_bank;

static MEMORY_READ_START( st0016_readmem )
	{ 0x0000, 0x7fff, MRA_ROM },
	{ 0x8000, 0xbfff, MRA_BANK1 },
	{ 0xc000, 0xcfff, st0016_sprite_ram_r },
	{ 0xd000, 0xdfff, st0016_sprite2_ram_r },
	{ 0xe000, 0xe7ff, MRA_RAM },
	{ 0xe800, 0xe87f, MRA_RAM }, /* common ram */
	{ 0xe900, 0xe9ff, MRA_RAM },
	{ 0xea00, 0xebff, st0016_palette_ram_r },
	{ 0xec00, 0xec1f, st0016_character_ram_r },
	{ 0xf000, 0xffff, MRA_RAM }, /* work ram */
MEMORY_END

static MEMORY_WRITE_START( st0016_writemem )
	{ 0x0000, 0x7fff, MWA_ROM },
	{ 0x8000, 0xbfff, MWA_BANK1 },
	{ 0xc000, 0xcfff, st0016_sprite_ram_w },
	{ 0xd000, 0xdfff, st0016_sprite2_ram_w },
	{ 0xe000, 0xe7ff, MWA_RAM },
	{ 0xe800, 0xe87f, MWA_RAM }, /* common ram */
	{ 0xe900, 0xe9ff, st0016_snd_w, &st0016_sound_regs },
	{ 0xea00, 0xebff, st0016_palette_ram_w },
	{ 0xec00, 0xec1f, st0016_character_ram_w },
	{ 0xf000, 0xffff, MWA_RAM }, /* work ram */
MEMORY_END

static READ_HANDLER(mux_r)
{
/* 
	76543210
	    xxxx - input port #2
	xxxx     - dip switches (2x8 bits) (multiplexed)
*/	    
	int retval=input_port_2_r(0)&0x0f;
	switch(mux_port&0x30)
	{
		case 0x00: retval|=((input_port_4_r(0)&1)<<4)|((input_port_4_r(0)&0x10)<<1)|((input_port_5_r(0)&1)<<6)|((input_port_5_r(0)&0x10)<<3);break;
		case 0x10: retval|=((input_port_4_r(0)&2)<<3)|((input_port_4_r(0)&0x20)   )|((input_port_5_r(0)&2)<<5)|((input_port_5_r(0)&0x20)<<2);break;
		case 0x20: retval|=((input_port_4_r(0)&4)<<2)|((input_port_4_r(0)&0x40)>>1)|((input_port_5_r(0)&4)<<4)|((input_port_5_r(0)&0x40)<<1);break;
		case 0x30: retval|=((input_port_4_r(0)&8)<<1)|((input_port_4_r(0)&0x80)>>2)|((input_port_5_r(0)&8)<<3)|((input_port_5_r(0)&0x80)   );break;
	}
	return retval;
}

static WRITE_HANDLER(mux_select_w)
{
	mux_port=data;
}

WRITE_HANDLER(st0016_rom_bank_w)
{
	cpu_setbank( 1, memory_region(REGION_CPU1) + (data* 0x4000) + 0x10000 );	
	st0016_rom_bank=data;
}

READ_HANDLER(st0016_dma_r);

static PORT_READ_START( st0016_readport )
	{ 0x00, 0xbf, st0016_vregs_r },
	{ 0xc0, 0xc0, input_port_0_r },
	{ 0xc1, 0xc1, input_port_1_r },
	{ 0xc2, 0xc2, mux_r },
	{ 0xc3, 0xc3, input_port_1_r },
	{ 0xf0, 0xf0, st0016_dma_r },
PORT_END

static PORT_WRITE_START( st0016_writeport )
	{ 0x00, 0xbf, st0016_vregs_w },
	{ 0xc0, 0xc0, mux_select_w },
	{ 0xc1, 0xc1, MWA_NOP },
	{ 0xc2, 0xc2, MWA_NOP },
	{ 0xc3, 0xc3, MWA_NOP },
	{ 0xe0, 0xe0, MWA_NOP }, /* renju = $40, neratte = 0 */
	{ 0xe1, 0xe1, st0016_rom_bank_w },
	{ 0xe2, 0xe2, st0016_sprite_bank_w },
	{ 0xe3, 0xe4, st0016_character_bank_w },
	{ 0xe5, 0xe5, st0016_palette_bank_w },
	{ 0xe6, 0xe6, MWA_NOP }, /* banking ? ram bank ? shared rambank ? */
	{ 0xe7, 0xe7, MWA_NOP }, /* watchdog */
PORT_END

INPUT_PORTS_START( renju )
	PORT_START		
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER1 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER1 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER1 )
	PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* buttons ? */
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START1 )
	
	PORT_START	
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER2 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER2 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER2 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
	PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* buttons ? */
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START2 )
		
	PORT_START
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BITX( 0x04, IP_ACTIVE_LOW, IPT_SERVICE | IPF_TOGGLE, DEF_STR ( Service_Mode ), KEYCODE_F2, IP_JOY_NONE )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
	
	PORT_START
	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* unused ? */		

	PORT_START		/* DSW1 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) 	
	PORT_DIPNAME( 0x02, 0x02, DEF_STR( Flip_Screen ) )
	PORT_DIPSETTING(    0x02, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x04, 0x04, "Test mode" )
	PORT_DIPSETTING(    0x04, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x08, 0x08, DEF_STR( Demo_Sounds ) )
	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x08, DEF_STR( On ) )
	PORT_DIPNAME( 0x30, 0x30, DEF_STR( Coin_A ) )
	PORT_DIPSETTING(      0x20, DEF_STR( 2C_1C ) )
	PORT_DIPSETTING(      0x30, DEF_STR( 1C_1C ) )
	PORT_DIPSETTING(      0x00, DEF_STR( 2C_3C ) )
	PORT_DIPSETTING(      0x10, DEF_STR( 1C_2C ) )
	PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Coin_B ) )
	PORT_DIPSETTING(      0x80, DEF_STR( 2C_1C ) )
	PORT_DIPSETTING(      0xc0, DEF_STR( 1C_1C ) )
	PORT_DIPSETTING(      0x00, DEF_STR( 2C_3C ) )
	PORT_DIPSETTING(      0x80, DEF_STR( 1C_2C ) )

	PORT_START		/* DSW2 */
	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Difficulty ) )
	PORT_DIPSETTING(      0x00, "Very Hard" )
	PORT_DIPSETTING(      0x01, "Hard" )
	PORT_DIPSETTING(      0x02, "Easy" )
	PORT_DIPSETTING(      0x03, "Normal" )
	PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNKNOWN ) 	
INPUT_PORTS_END

INPUT_PORTS_START( koikois )
	PORT_START		
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER1 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER1 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START1 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* buttons ? */
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN1 )
	
	PORT_START	
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER2 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER2 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER2 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* buttons ? */
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN2 )
		
	PORT_START
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BITX( 0x04, IP_ACTIVE_LOW, IPT_SERVICE | IPF_TOGGLE, DEF_STR ( Service_Mode ), KEYCODE_F2, IP_JOY_NONE )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
	
	PORT_START
	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* unused ? */		

	PORT_START		/* DSW1 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) 	
	PORT_DIPNAME( 0x02, 0x02, DEF_STR( Flip_Screen ) )
	PORT_DIPSETTING(    0x02, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x04, 0x04, "Test mode" )
	PORT_DIPSETTING(    0x04, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x08, 0x08, DEF_STR( Demo_Sounds ) )
	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x08, DEF_STR( On ) )
	PORT_DIPNAME( 0x30, 0x30, DEF_STR( Coin_A ) )
	PORT_DIPSETTING(      0x20, DEF_STR( 2C_1C ) )
	PORT_DIPSETTING(      0x30, DEF_STR( 1C_1C ) )
	PORT_DIPSETTING(      0x00, DEF_STR( 2C_3C ) )
	PORT_DIPSETTING(      0x10, DEF_STR( 1C_2C ) )
	PORT_DIPNAME( 0x40, 0x40,  "Controls" )
	PORT_DIPSETTING(    0x00, "Majyan Panel" )
	PORT_DIPSETTING(    0x40, "Joystick" )

	PORT_START		/* DSW2 */
	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Difficulty ) )
	PORT_DIPSETTING(      0x00, "Very Hard" )
	PORT_DIPSETTING(      0x01, "Hard" )
	PORT_DIPSETTING(      0x02, "Easy" )
	PORT_DIPSETTING(      0x03, "Normal" )
	PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNKNOWN ) 	
INPUT_PORTS_END


INPUT_PORTS_START( nratechu )
	PORT_START		
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER1 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER1 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER1 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER1 )
	PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* buttons ? */
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START1 )
	
	PORT_START		
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP | IPF_PLAYER2 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN | IPF_PLAYER2 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT | IPF_PLAYER2 )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT | IPF_PLAYER2 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
	PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* buttons ? */
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START2 )
		
	PORT_START		
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BITX( 0x04, IP_ACTIVE_LOW, IPT_SERVICE | IPF_TOGGLE, DEF_STR ( Service_Mode ), KEYCODE_F2, IP_JOY_NONE )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) 

	PORT_START		
	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* read in test mode */
	
	PORT_START		/* DSW1 */
	PORT_BIT( 0x7f, IP_ACTIVE_LOW, IPT_UNKNOWN ) 
	PORT_DIPNAME( 0x80, 0x80, "Language" )
	PORT_DIPSETTING(    0x00, "English" )
	PORT_DIPSETTING(    0x80, "Japanese" )
		
	PORT_START		/* DSW2 */
	PORT_BIT( 0x7f, IP_ACTIVE_LOW, IPT_UNKNOWN ) 
	PORT_DIPNAME( 0x80, 0x80, "Test mode" )
	PORT_DIPSETTING(    0x80, DEF_STR( Off ) )
	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
INPUT_PORTS_END

static struct GfxDecodeInfo gfxdecodeinfo[] =
{
//	{ 0, 0, &charlayout,      0, 16*4  },
	{ -1 }	/* end of array */
};

INTERRUPT_GEN(st0016_int)
{
	if(!cpu_getiloops())
		cpu_set_irq_line(0,0,HOLD_LINE);
	else
		if(activecpu_get_reg(Z80_IFF1)) /* dirty hack ... */
			cpu_set_nmi_line( 0, PULSE_LINE );
}

static struct ST0016interface st0016_interface =
{
	YM3012_VOL(100, MIXER_PAN_LEFT, 100, MIXER_PAN_RIGHT),
};

static MACHINE_DRIVER_START( st0016 )
	/* basic machine hardware */
	MDRV_CPU_ADD_TAG("main",Z80,8000000) /* 8 MHz ? */
	MDRV_CPU_MEMORY(st0016_readmem,st0016_writemem)
	MDRV_CPU_PORTS(st0016_readport,st0016_writeport)

	MDRV_CPU_VBLANK_INT(st0016_int,5) /*  4*nmi + int0 */

	MDRV_FRAMES_PER_SECOND(60)
	MDRV_VBLANK_DURATION(DEFAULT_60HZ_VBLANK_DURATION)

	/* video hardware */
	MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
	MDRV_SCREEN_SIZE(48*8, 48*8)
	MDRV_VISIBLE_AREA(0*8, 48*8-1, 0*8, 48*8-1)
	MDRV_GFXDECODE(gfxdecodeinfo)
	MDRV_PALETTE_LENGTH(16*16*4+1)

	MDRV_VIDEO_START(st0016)
	MDRV_VIDEO_UPDATE(st0016)

	MDRV_SOUND_ATTRIBUTES(SOUND_SUPPORTS_STEREO)
	MDRV_SOUND_ADD(ST0016, st0016_interface)
MACHINE_DRIVER_END

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

ROM_START( renju )
	ROM_REGION( 0x290000, REGION_CPU1, 0 )
	ROM_LOAD( "renjyu-1.u31",0x010000, 0x200000, 0xe0fdbe9b )
	ROM_LOAD( "rnj2.u32",    0x210000, 0x080000, 0x2015289c )
	ROM_COPY( REGION_CPU1,   0x210000, 0x000000, 0x08000 )
ROM_END

ROM_START( nratechu )
	ROM_REGION( 0x210000, REGION_CPU1, 0 )
	ROM_LOAD( "sx012-01",   0x10000, 0x80000,   0x6ca01d57 )
	ROM_LOAD( "sx012-02",   0x110000, 0x100000, 0x40a4e354 )
	ROM_COPY( REGION_CPU1,  0x10000, 0x00000, 0x08000 )
ROM_END

ROM_START( koikois )
	ROM_REGION( 0x410000, REGION_CPU1, 0 )
	ROM_LOAD16_BYTE( "koi-2.6c", 0x010001, 0x080000, 0x2722be71 )
	ROM_LOAD16_BYTE( "koi-1.4c", 0x010000, 0x080000, 0xc79e2b43 )
	ROM_LOAD16_BYTE( "koi-4.8c", 0x110001, 0x080000, 0xace236df )
	ROM_LOAD16_BYTE( "koi-3.5c", 0x110000, 0x080000, 0x6fd88149 )
	ROM_LOAD( "koi-5.2c", 0x210000, 0x200000, 0x561e12c8 )
	ROM_COPY( REGION_CPU1,  0x10000, 0x00000, 0x08000 )
ROM_END

static DRIVER_INIT(renju)
{
	st0016_game=0;
}

static DRIVER_INIT(nratechu)
{
	st0016_game=1;
}

GAME( 1994, renju,     0,     	  st0016,   renju,     renju,    ROT0, "Visco", "Renju Kizoku")
GAME( 1996, nratechu,  0,     	  st0016,   nratechu,  nratechu, ROT0, "Seta",  "Neratte Chu")
GAMEX(1995, koikois,   0,	  	  st0016,   koikois,   renju,    ROT0, "Visco",  "Koi Koi Shimasho", GAME_IMPERFECT_GRAPHICS)
