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

  Coors Light Bowling from Capcom

  Memory Map:

  0000-3fff     3 Graphics ROMS mapped in using 0x4800
  4000          Scan line read or modified (Only 0-244 are displayed)
  4800          Graphics ROM select
  5000-57ff     Static RAM (Saves machine state after shut off)
                No DIP Switches
                Enter setup menu by holding down the F1 key on the
                high score screen
  5800-5842     ???? Might have something to do with video,
                See weird code starting at 0xe102, which is used for animating
                the pins, but pulsates bit 2 of location 0x582d.
                Dunno what it does.
  5b00-5bff     Graphics RAM for one scanline (0x4000)
                First 0x20 bytes provide a 16 color palette for this
                scan line. 2 bytes per color: 0000RRRR GGGGBBBB.

                The 4096 colors of the game is mapped into 256 colors, by
                taking the most significant 3 bits of the Red and Green
                components, and the most significant 2 bits of the blue
                component. This provides for a uniform palette, but I think
                the game uses a lot of colors where the Red component is
                either 0 or 0x0f. So there may be a way to improve the colors.

                Remaining 0xe0 bytes contain 2 pixels each for a total of
                448 pixels, but only 359 seem to be displayed.
                (Each scanline appears vertically on MAME)

  6000          Sound command
  6800
  7000          Input port 1    Bit 0-3 Trackball Vertical,
                                Bit 7   Left Coin
  7800          Input port 2    Bit 0-3 Trackball Horizontal
                                Bit 4   Hook Left
                                Bit 5   Hook Right
                                Bit 6   Start

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

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

void capbowl_vh_screenrefresh(struct osd_bitmap *bitmap);

int capbowl_interrupt(void);

int  capbowl_vh_start(void);
void capbowl_vh_stop(void);

void capbowl_firq_enable_w(int offset,int data);

void capbowl_scanline_w(int offset,int data);

void capbowl_videoram_w(int offset,int data);
int  capbowl_videoram_r(int offset);

void capbowl_rom_select_w(int offset,int data);

int  capbowl_pagedrom_r(int offset);

int  capbowl_service_r(int offset);
void capbowl_service_w(int offset, int data);

int  capbowl_track_y_r(int offset);
int  capbowl_track_x_r(int offset);


void capbowl_sndcmd_w(int offset,int data);
int  capbowl_sndcmd_r(int offset);

void capbowl_sndreg_w(int offset,int data);
int  capbowl_sndreg_r(int offset);

void capbowl_snddata_w(int offset,int data);
int  capbowl_snddata_r(int offset);

int capbowl_sound_interrupt(void);

static struct MemoryReadAddress readmem[] =
{
        { 0x0000, 0x3fff, capbowl_pagedrom_r},
        { 0x5000, 0x50e2, MRA_RAM},
        { 0x50e3, 0x50e3, capbowl_service_r},
        { 0x50e4, 0x57ff, MRA_RAM},
        { 0x5800, 0x5842, MRA_RAM},
        { 0x5b00, 0x5bff, capbowl_videoram_r },
        { 0x7000, 0x7000, capbowl_track_y_r },
        { 0x7800, 0x7800, capbowl_track_x_r },
        { 0x8000, 0xffff, MRA_ROM },
        { -1 }  /* end of table */
};

static struct MemoryWriteAddress writemem[] =
{
        { 0x4000, 0x4000, capbowl_scanline_w },
        { 0x4800, 0x4800, capbowl_rom_select_w },
        { 0x5000, 0x50e2, MWA_RAM},
        { 0x50e3, 0x50e3, capbowl_service_w},
        { 0x50e4, 0x57ff, MWA_RAM},
        { 0x5800, 0x582c, MWA_RAM},
        { 0x582d, 0x582d, capbowl_firq_enable_w},
        { 0x582e, 0x5842, MWA_RAM},
        { 0x5b00, 0x5bff, capbowl_videoram_w, &videoram, &videoram_size },
        { 0x5c00, 0x5c00, MWA_NOP }, /* Off by 1 bug?? */
        { 0x6000, 0x6000, capbowl_sndcmd_w },
        { 0x6800, 0x6800, MWA_NOP },
        { 0x8000, 0xffff, MWA_ROM },
        { -1 }  /* end of table */
};


/* I have no idea how the sound works, but I put debugging messages in
   so maybe someone can figure it out */
static struct MemoryReadAddress sound_readmem[] =
{
        { 0x0000, 0x07ff, MRA_RAM},
        { 0x1000, 0x1000, capbowl_sndreg_r},  /* Sound register */
        { 0x1001, 0x1001, capbowl_snddata_r}, /* Sound data */
        { 0x7000, 0x7000, capbowl_sndcmd_r},  /* Sound command */
        { 0x8000, 0xffff, MRA_ROM },
        { -1 }  /* end of table */
};

static struct MemoryWriteAddress sound_writemem[] =
{
        { 0x0000, 0x07ff, MWA_RAM},
        { 0x1000, 0x1000, capbowl_sndreg_w},  /* Sound register */
        { 0x1001, 0x1001, capbowl_snddata_w}, /* Sound data */
        { 0x2000, 0x2000, MWA_NOP},  /* ????? */
        { -1 }  /* end of table */
};



static struct InputPort input_ports[] =
{
  {       /* IN1 */
          0xff,
          { OSD_KEY_UP, OSD_KEY_DOWN, 0, 0, 0, 0, 0, OSD_KEY_3 },
          { OSD_JOY_UP, OSD_JOY_DOWN, 0, 0, 0, 0, 0, 0 }
  },
  {       /* IN2 */
          0xff,
          { OSD_KEY_LEFT, OSD_KEY_RIGHT, 0, 0, OSD_KEY_Z, OSD_KEY_X, OSD_KEY_1, 0 },
          { OSD_JOY_LEFT, OSD_JOY_RIGHT, 0, 0, OSD_JOY_FIRE1, OSD_JOY_FIRE2, 0, 0 }
  },
        { -1 }  /* end of table */
};


/* This game uses a track ball, but since I don't have one, I'm not going
   to attempt to emulate it */
static struct TrakPort trak_ports[] =
{
        { -1 }
};


static struct KEYSet keys[] =
{
  { 1, 0, "MOVE LEFT" },
  { 1, 1, "MOVE RIGHT"  },
  { 0, 0, "ROLL FASTER" },
  { 0, 1, "ROLL SLOWER" },
  { 1, 4, "HOOK LEFT" },
  { 1, 5, "HOOK RIGHT" },
  { -1 }
};


/* Doesn't use DIP switches. See Memory Map */
static struct DSW capbowl_dsw[] =
{
          { -1 }
};


unsigned char capbowl_palette[256 * 3] =
{
        0x00, 0x00, 0x00,
        0x00, 0x00, 0x4f,
        0x00, 0x00, 0x8f,
        0x00, 0x00, 0xff,
        0x00, 0x2f, 0x00,
        0x00, 0x2f, 0x4f,
        0x00, 0x2f, 0x8f,
        0x00, 0x2f, 0xff,
        0x00, 0x4f, 0x00,
        0x00, 0x4f, 0x4f,
        0x00, 0x4f, 0x8f,
        0x00, 0x4f, 0xff,
        0x00, 0x6f, 0x00,
        0x00, 0x6f, 0x4f,
        0x00, 0x6f, 0x8f,
        0x00, 0x6f, 0xff,
        0x00, 0x8f, 0x00,
        0x00, 0x8f, 0x4f,
        0x00, 0x8f, 0x8f,
        0x00, 0x8f, 0xff,
        0x00, 0xaf, 0x00,
        0x00, 0xaf, 0x4f,
        0x00, 0xaf, 0x8f,
        0x00, 0xaf, 0xff,
        0x00, 0xcf, 0x00,
        0x00, 0xcf, 0x4f,
        0x00, 0xcf, 0x8f,
        0x00, 0xcf, 0xff,
        0x00, 0xff, 0x00,
        0x00, 0xff, 0x4f,
        0x00, 0xff, 0x8f,
        0x00, 0xff, 0xff,

        0x2f, 0x00, 0x00,
        0x2f, 0x00, 0x4f,
        0x2f, 0x00, 0x8f,
        0x2f, 0x00, 0xff,
        0x2f, 0x2f, 0x00,
        0x2f, 0x2f, 0x4f,
        0x2f, 0x2f, 0x8f,
        0x2f, 0x2f, 0xff,
        0x2f, 0x4f, 0x00,
        0x2f, 0x4f, 0x4f,
        0x2f, 0x4f, 0x8f,
        0x2f, 0x4f, 0xff,
        0x2f, 0x6f, 0x00,
        0x2f, 0x6f, 0x4f,
        0x2f, 0x6f, 0x8f,
        0x2f, 0x6f, 0xff,
        0x2f, 0x8f, 0x00,
        0x2f, 0x8f, 0x4f,
        0x2f, 0x8f, 0x8f,
        0x2f, 0x8f, 0xff,
        0x2f, 0xaf, 0x00,
        0x2f, 0xaf, 0x4f,
        0x2f, 0xaf, 0x8f,
        0x2f, 0xaf, 0xff,
        0x2f, 0xcf, 0x00,
        0x2f, 0xcf, 0x4f,
        0x2f, 0xcf, 0x8f,
        0x2f, 0xcf, 0xff,
        0x2f, 0xff, 0x00,
        0x2f, 0xff, 0x4f,
        0x2f, 0xff, 0x8f,
        0x2f, 0xff, 0xff,

        0x4f, 0x00, 0x00,
        0x4f, 0x00, 0x4f,
        0x4f, 0x00, 0x8f,
        0x4f, 0x00, 0xff,
        0x4f, 0x2f, 0x00,
        0x4f, 0x2f, 0x4f,
        0x4f, 0x2f, 0x8f,
        0x4f, 0x2f, 0xff,
        0x4f, 0x4f, 0x00,
        0x4f, 0x4f, 0x4f,
        0x4f, 0x4f, 0x8f,
        0x4f, 0x4f, 0xff,
        0x4f, 0x6f, 0x00,
        0x4f, 0x6f, 0x4f,
        0x4f, 0x6f, 0x8f,
        0x4f, 0x6f, 0xff,
        0x4f, 0x8f, 0x00,
        0x4f, 0x8f, 0x4f,
        0x4f, 0x8f, 0x8f,
        0x4f, 0x8f, 0xff,
        0x4f, 0xaf, 0x00,
        0x4f, 0xaf, 0x4f,
        0x4f, 0xaf, 0x8f,
        0x4f, 0xaf, 0xff,
        0x4f, 0xcf, 0x00,
        0x4f, 0xcf, 0x4f,
        0x4f, 0xcf, 0x8f,
        0x4f, 0xcf, 0xff,
        0x4f, 0xff, 0x00,
        0x4f, 0xff, 0x4f,
        0x4f, 0xff, 0x8f,
        0x4f, 0xff, 0xff,

        0x6f, 0x00, 0x00,
        0x6f, 0x00, 0x4f,
        0x6f, 0x00, 0x8f,
        0x6f, 0x00, 0xff,
        0x6f, 0x2f, 0x00,
        0x6f, 0x2f, 0x4f,
        0x6f, 0x2f, 0x8f,
        0x6f, 0x2f, 0xff,
        0x6f, 0x4f, 0x00,
        0x6f, 0x4f, 0x4f,
        0x6f, 0x4f, 0x8f,
        0x6f, 0x4f, 0xff,
        0x6f, 0x6f, 0x00,
        0x6f, 0x6f, 0x4f,
        0x6f, 0x6f, 0x8f,
        0x6f, 0x6f, 0xff,
        0x6f, 0x8f, 0x00,
        0x6f, 0x8f, 0x4f,
        0x6f, 0x8f, 0x8f,
        0x6f, 0x8f, 0xff,
        0x6f, 0xaf, 0x00,
        0x6f, 0xaf, 0x4f,
        0x6f, 0xaf, 0x8f,
        0x6f, 0xaf, 0xff,
        0x6f, 0xcf, 0x00,
        0x6f, 0xcf, 0x4f,
        0x6f, 0xcf, 0x8f,
        0x6f, 0xcf, 0xff,
        0x6f, 0xff, 0x00,
        0x6f, 0xff, 0x4f,
        0x6f, 0xff, 0x8f,
        0x6f, 0xff, 0xff,

        0x8f, 0x00, 0x00,
        0x8f, 0x00, 0x4f,
        0x8f, 0x00, 0x8f,
        0x8f, 0x00, 0xff,
        0x8f, 0x2f, 0x00,
        0x8f, 0x2f, 0x4f,
        0x8f, 0x2f, 0x8f,
        0x8f, 0x2f, 0xff,
        0x8f, 0x4f, 0x00,
        0x8f, 0x4f, 0x4f,
        0x8f, 0x4f, 0x8f,
        0x8f, 0x4f, 0xff,
        0x8f, 0x6f, 0x00,
        0x8f, 0x6f, 0x4f,
        0x8f, 0x6f, 0x8f,
        0x8f, 0x6f, 0xff,
        0x8f, 0x8f, 0x00,
        0x8f, 0x8f, 0x4f,
        0x8f, 0x8f, 0x8f,
        0x8f, 0x8f, 0xff,
        0x8f, 0xaf, 0x00,
        0x8f, 0xaf, 0x4f,
        0x8f, 0xaf, 0x8f,
        0x8f, 0xaf, 0xff,
        0x8f, 0xcf, 0x00,
        0x8f, 0xcf, 0x4f,
        0x8f, 0xcf, 0x8f,
        0x8f, 0xcf, 0xff,
        0x8f, 0xff, 0x00,
        0x8f, 0xff, 0x4f,
        0x8f, 0xff, 0x8f,
        0x8f, 0xff, 0xff,

        0xaf, 0x00, 0x00,
        0xaf, 0x00, 0x4f,
        0xaf, 0x00, 0x8f,
        0xaf, 0x00, 0xff,
        0xaf, 0x2f, 0x00,
        0xaf, 0x2f, 0x4f,
        0xaf, 0x2f, 0x8f,
        0xaf, 0x2f, 0xff,
        0xaf, 0x4f, 0x00,
        0xaf, 0x4f, 0x4f,
        0xaf, 0x4f, 0x8f,
        0xaf, 0x4f, 0xff,
        0xaf, 0x6f, 0x00,
        0xaf, 0x6f, 0x4f,
        0xaf, 0x6f, 0x8f,
        0xaf, 0x6f, 0xff,
        0xaf, 0x8f, 0x00,
        0xaf, 0x8f, 0x4f,
        0xaf, 0x8f, 0x8f,
        0xaf, 0x8f, 0xff,
        0xaf, 0xaf, 0x00,
        0xaf, 0xaf, 0x4f,
        0xaf, 0xaf, 0x8f,
        0xaf, 0xaf, 0xff,
        0xaf, 0xcf, 0x00,
        0xaf, 0xcf, 0x4f,
        0xaf, 0xcf, 0x8f,
        0xaf, 0xcf, 0xff,
        0xaf, 0xff, 0x00,
        0xaf, 0xff, 0x4f,
        0xaf, 0xff, 0x8f,
        0xaf, 0xff, 0xff,

        0xcf, 0x00, 0x00,
        0xcf, 0x00, 0x4f,
        0xcf, 0x00, 0x8f,
        0xcf, 0x00, 0xff,
        0xcf, 0x2f, 0x00,
        0xcf, 0x2f, 0x4f,
        0xcf, 0x2f, 0x8f,
        0xcf, 0x2f, 0xff,
        0xcf, 0x4f, 0x00,
        0xcf, 0x4f, 0x4f,
        0xcf, 0x4f, 0x8f,
        0xcf, 0x4f, 0xff,
        0xcf, 0x6f, 0x00,
        0xcf, 0x6f, 0x4f,
        0xcf, 0x6f, 0x8f,
        0xcf, 0x6f, 0xff,
        0xcf, 0x8f, 0x00,
        0xcf, 0x8f, 0x4f,
        0xcf, 0x8f, 0x8f,
        0xcf, 0x8f, 0xff,
        0xcf, 0xaf, 0x00,
        0xcf, 0xaf, 0x4f,
        0xcf, 0xaf, 0x8f,
        0xcf, 0xaf, 0xff,
        0xcf, 0xcf, 0x00,
        0xcf, 0xcf, 0x4f,
        0xcf, 0xcf, 0x8f,
        0xcf, 0xcf, 0xff,
        0xcf, 0xff, 0x00,
        0xcf, 0xff, 0x4f,
        0xcf, 0xff, 0x8f,
        0xcf, 0xff, 0xff,

        0xff, 0x00, 0x00,
        0xff, 0x00, 0x4f,
        0xff, 0x00, 0x8f,
        0xff, 0x00, 0xff,
        0xff, 0x2f, 0x00,
        0xff, 0x2f, 0x4f,
        0xff, 0x2f, 0x8f,
        0xff, 0x2f, 0xff,
        0xff, 0x4f, 0x00,
        0xff, 0x4f, 0x4f,
        0xff, 0x4f, 0x8f,
        0xff, 0x4f, 0xff,
        0xff, 0x6f, 0x00,
        0xff, 0x6f, 0x4f,
        0xff, 0x6f, 0x8f,
        0xff, 0x6f, 0xff,
        0xff, 0x8f, 0x00,
        0xff, 0x8f, 0x4f,
        0xff, 0x8f, 0x8f,
        0xff, 0x8f, 0xff,
        0xff, 0xaf, 0x00,
        0xff, 0xaf, 0x4f,
        0xff, 0xaf, 0x8f,
        0xff, 0xaf, 0xff,
        0xff, 0xcf, 0x00,
        0xff, 0xcf, 0x4f,
        0xff, 0xcf, 0x8f,
        0xff, 0xcf, 0xff,
        0xff, 0xff, 0x00,
        0xff, 0xff, 0x4f,
        0xff, 0xff, 0x8f,
        0xff, 0xff, 0xff
};


static struct MachineDriver capbowl_machine_driver =
{
	/* basic machine hardware */
	{
			{
					CPU_M6809,
					1000000,        /* 1 Mhz ??? */
					0,
					readmem,writemem,0,0,
					capbowl_interrupt,2
			},
			{
					CPU_M6809 | CPU_AUDIO_CPU,
					1000000,
					2,
					sound_readmem,sound_writemem,0,0,
					capbowl_sound_interrupt,12
			}
	},
	60,
	10,	/* 10 CPU slices per frame - enough for the sound CPU to read all commands */
	0,

	/* video hardware */
	/* The visible region is 245x359 */
	512, 512, { 0, 128+245-1, 89, 512-64-1 },
	0,
	sizeof(capbowl_palette)/3, 0,
	0,

	VIDEO_TYPE_RASTER,
	0,
	capbowl_vh_start,
	capbowl_vh_stop,
	capbowl_vh_screenrefresh,

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



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

  Game driver(s)

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

ROM_START( capbowl_rom )
        ROM_REGION(0x28000)   /* 160k for code and graphics */
        ROM_LOAD( "u6",  0x8000 , 0x8000, 0x99fede6e )
        ROM_LOAD( "gr0", 0x10000, 0x8000, 0x64039867 )
        ROM_LOAD( "gr1", 0x18000, 0x8000, 0x3a758375 )
        ROM_LOAD( "gr2", 0x20000, 0x8000, 0xb63eb4f2 )
        ROM_REGION(0x1000)    /* Dummy area */
        ROM_REGION(0x10000)   /* 64k for sound */
        ROM_LOAD( "sound", 0x8000, 0x8000, 0xe27c494a )
ROM_END


static int hiload(void)
{
  void *f;
  /* get RAM pointer (this game is multiCPU, we can't assume the global */
  /* RAM pointer is pointing to the right place) */
  unsigned char *RAM = Machine->memory_region[0];

  /* Try loading static RAM */

  if ((f = osd_fopen(Machine->gamedrv->name,0,OSD_FILETYPE_HIGHSCORE,0)) != 0)
  {
     osd_fread(f,&RAM[0x5000],0x800);
     osd_fclose(f);
  }
  else
  {
    /* Force reseting to factory settings */
    Machine->memory_region[0][0x55c1] = 0x01;
    Machine->memory_region[0][0x5625] = 0x01;
    Machine->memory_region[0][0x56af] = 0x01;
    Machine->memory_region[0][0x5739] = 0x01;
    Machine->memory_region[0][0x57c3] = 0x01;
  }

  return 1;
}



static void hisave(void)
{
        void *f;
        /* get RAM pointer (this game is multiCPU, we can't assume the global */
        /* RAM pointer is pointing to the right place) */
        unsigned char *RAM = Machine->memory_region[0];


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


struct GameDriver capbowl_driver =
{
        "Capcom Bowling",
        "capbowl",
        "ZSOLT VASVARI\nMIRKO BUFFONI",
        &capbowl_machine_driver,

        capbowl_rom,
        0, 0,
        0,

        input_ports, 0, trak_ports, capbowl_dsw, keys,

        0, capbowl_palette, 0,

        ORIENTATION_DEFAULT,

        hiload, hisave
};


