/* Ramtek M79 Ambush */

#include "driver.h"
#include "vidhrdw/generic.h"
/*
 * in
 * 8000 DIP SW
 * 8002 D0=VBlank
 * 8004
 * 8005
 *
 * out
 * 8000
 * 8001 Mask Sel
 * 8002
 * 8003 D0=SelfTest LED
 *
 */

void ramtek_videoram_w(int offset,int data);

int  invaders_interrupt(void);
int  ramtek_vh_start(void);
void ramtek_vh_stop(void);
void ramtek_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh);
void ramtek_sh_update(void);
void ramtek_mask_w(int offset, int data);

extern unsigned char *ramtek_videoram;

/*
 * since these functions aren't used anywhere else, i've made them
 * static, and included them here
 */
static const int ControllerTable[32] = {
    0  , 1  , 3  , 2  , 6  , 7  , 5  , 4  ,
    12 , 13 , 15 , 14 , 10 , 11 , 9  , 8  ,
    24 , 25 , 27 , 26 , 30 , 31 , 29 , 28 ,
    20 , 21 , 23 , 22 , 18 , 19 , 17 , 16
};

static int gray5bit_controller0_r(int offset)
{
    return (input_port_2_r(0) & 0xe0) | (~ControllerTable[input_port_2_r(0) & 0x1f] & 0x1f);
}

static int gray5bit_controller1_r(int offset)
{
    return (input_port_3_r(0) & 0xe0) | (~ControllerTable[input_port_3_r(0) & 0x1f] & 0x1f);
}

static struct MemoryReadAddress readmem[] =
{
	{ 0x0000, 0x1fff, MRA_ROM },
	{ 0x4000, 0x63ff, MRA_RAM },
	{ 0x8000, 0x8000, input_port_0_r},
	{ 0x8002, 0x8002, input_port_1_r},
	{ 0x8004, 0x8004, gray5bit_controller0_r},
	{ 0x8005, 0x8005, gray5bit_controller1_r},
	{ 0xC000, 0xC07f, MRA_RAM},			/* ?? */
	{ 0xC200, 0xC27f, MRA_RAM},			/* ?? */
	{ -1 }  /* end of table */
};

void sound_w(int offset,int data)
{
}

static struct MemoryWriteAddress writemem[] =
{
	{ 0x0000, 0x1fff, MWA_ROM },
	{ 0x4000, 0x43ff, MWA_RAM },
    { 0x4400, 0x5fff, ramtek_videoram_w, &ramtek_videoram },
    { 0x6000, 0x63ff, MWA_RAM },		/* ?? */
	{ 0x8001, 0x8001, ramtek_mask_w},
	{ 0x8000, 0x8000, sound_w },
	{ 0x8002, 0x8003, sound_w },
	{ 0xC000, 0xC07f, MWA_RAM},			/* ?? */
	{ 0xC200, 0xC27f, MWA_RAM},			/* ?? */
	{ -1 }  /* end of table */
};

static struct IOReadPort readport[] =
{
	{ -1 }  /* end of table */
};

static struct IOWritePort writeport[] =
{
	{ -1 }  /* end of table */
};


INPUT_PORTS_START( m79_input_ports )
	PORT_START      /* 8000 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )	/* dip switch */
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
	PORT_BIT( 0x08, IP_ACTIVE_LOW,  IPT_UNUSED )
	PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED )
	PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED )
	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )

	PORT_START      /* 8002 */
	PORT_BIT( 0x01, IP_ACTIVE_LOW,  IPT_VBLANK )
	PORT_BIT( 0x02, IP_ACTIVE_LOW,  IPT_START1 )
	PORT_BIT( 0x04, IP_ACTIVE_LOW,  IPT_COIN1  )
	PORT_BIT( 0x08, IP_ACTIVE_LOW,  IPT_TILT   )
	PORT_BIT( 0x10, IP_ACTIVE_LOW,  IPT_UNUSED )
	PORT_BIT( 0x20, IP_ACTIVE_LOW,  IPT_UNUSED )
	PORT_BIT( 0x40, IP_ACTIVE_LOW,  IPT_UNUSED )
	PORT_BIT( 0x80, IP_ACTIVE_LOW,  IPT_UNUSED )

	PORT_START		/* 8004 */
	PORT_ANALOG ( 0x1f, 0x10, IPT_PADDLE, 25, 10, 0, 0, 0x1f)
	PORT_BIT( 0x20, IP_ACTIVE_LOW,  IPT_BUTTON1 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW,  IPT_UNKNOWN )
	PORT_BIT( 0x80, IP_ACTIVE_LOW,  IPT_UNKNOWN )

	PORT_START      /* 8005 */
	PORT_ANALOG ( 0x1f, 0x10, IPT_PADDLE | IPF_PLAYER2, 25, 10, 0, 0, 0x1f)
	PORT_BIT( 0x20, IP_ACTIVE_LOW,  IPT_BUTTON2 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW,  IPT_UNKNOWN )
	PORT_BIT( 0x80, IP_ACTIVE_LOW,  IPT_UNKNOWN )

INPUT_PORTS_END


static unsigned char palette[] = /* V.V */ /* Smoothed pure colors, overlays are not so contrasted */
{
	0x00,0x00,0x00, /* BLACK */
	0xff,0xff,0xff, /* WHITE */
	0xff,0x20,0x20, /* RED */
	0x20,0xff,0x20, /* GREEN */
	0xff,0xff,0x20, /* YELLOW */
	0x20,0xff,0xff, /* CYAN */
	0xff,0x20,0xff  /* PURPLE */
};

static int M79_interrupt(void)
{
                return 0x00cf;  /* RST 08h */
}

static void m79_init(void)
{
  int i;
  /* PROM data is active low */
  for(i=0; i<0x2000; i++)
   ROM[i] = ~ROM[i];
}

static struct MachineDriver machine_driver =
{
        /* basic machine hardware */
        {
                {
                    CPU_8080,
                    1996800,
                    0,
                    readmem,writemem,readport,writeport,
                    M79_interrupt, 1
                }
        },
        60, DEFAULT_REAL_60HZ_VBLANK_DURATION,  /* frames per second, vblank duration */
        1,      /* single CPU, no need for interleaving */
        0,

        /* video hardware */
        32*8, 28*8, { 0*8, 32*8-1, 0*8, 28*8-1 },
        0,      /* no gfxdecodeinfo - bitmapped display */
        sizeof(palette)/3, 0,
        0,

        VIDEO_TYPE_RASTER|VIDEO_SUPPORTS_DIRTY,
        0,
        ramtek_vh_start,
        ramtek_vh_stop,
        ramtek_vh_screenrefresh,

	/* sound hardware */
	0,0,0,0
};



ROM_START( m79_rom )
	ROM_REGION(0x10000)     /* 64k for code */
	ROM_LOAD( "m79.10t",      0x0000, 0x0200, 0xccf30b1e )
	ROM_LOAD( "m79.9t",       0x0200, 0x0200, 0xdaf807dd )
	ROM_LOAD( "m79.8t",       0x0400, 0x0200, 0x79fafa02 )
	ROM_LOAD( "m79.7t",       0x0600, 0x0200, 0x06f511f8 )
	ROM_LOAD( "m79.6t",       0x0800, 0x0200, 0x24634390 )
	ROM_LOAD( "m79.5t",       0x0a00, 0x0200, 0x95252aa6 )
	ROM_LOAD( "m79.4t",       0x0c00, 0x0200, 0x54cffb0f )
	ROM_LOAD( "m79.3ta",      0x0e00, 0x0200, 0x27db5ede )
	ROM_LOAD( "m79.10u",      0x1000, 0x0200, 0xe41d13d2 )
	ROM_LOAD( "m79.9u",       0x1200, 0x0200, 0xe35f5616 )
	ROM_LOAD( "m79.8u",       0x1400, 0x0200, 0x14eafd7c )
	ROM_LOAD( "m79.7u",       0x1600, 0x0200, 0xb9864f25 )
	ROM_LOAD( "m79.6u",       0x1800, 0x0200, 0xdd25197f )
	ROM_LOAD( "m79.5u",       0x1a00, 0x0200, 0x251545e2 )
	ROM_LOAD( "m79.4u",       0x1c00, 0x0200, 0xb5f55c75 )
	ROM_LOAD( "m79.3u",       0x1e00, 0x0200, 0xe968691a )
 ROM_END


static int hiload(void)
{
	static int firsttime =0;
	unsigned char *RAM = Machine->memory_region[Machine->drv->cpu[0].memory_region];

	if (firsttime == 0)
	{
		memset(&RAM[0x4008],0xff,1);	/* high score */
		firsttime = 1;
	}



    /* check if the hi score table has already been initialized */
    if (memcmp(&RAM[0x4008],"\x00",1) == 0 )
    {
        void *f;

        if ((f = osd_fopen(Machine->gamedrv->name,0,OSD_FILETYPE_HIGHSCORE,0)) != 0)
        {
		osd_fread(f,&RAM[0x4008],1);
		osd_fclose(f);
		firsttime = 0;
        }

        return 1;
    }
    else
        return 0;  /* we can't load the hi scores yet */
}

static void hisave(void)
{
    void *f;
	unsigned char *RAM = Machine->memory_region[Machine->drv->cpu[0].memory_region];


    if ((f = osd_fopen(Machine->gamedrv->name,0,OSD_FILETYPE_HIGHSCORE,1)) != 0)
    {
		osd_fwrite(f,&RAM[0x4008],1);
        osd_fclose(f);
    }
}





struct GameDriver m79amb_driver =
{
	__FILE__,
	0,
	"m79amb",
	"M79 Ambush",
	"1977",
	"Ramtek",
	"Space Invaders Team\n",
	0,
	&machine_driver,
	0,

	m79_rom,
	m79_init,
	0,
	0,
	0,      /* sound_prom */

	m79_input_ports,

	0, palette, 0,
	ORIENTATION_DEFAULT,

	hiload,hisave
};
