// The Punisher

#include "cps.h"

static struct BurnInputInfo DrvInputList[] =
{
  {"P1 Coin"       , 0, CpsInp018+0, "p1 coin"},
  {"P1 Start"      , 0, CpsInp018+4, "p1 start"},
  {"P1 Up"         , 0, CpsInp001+3, "p1 up"},
  {"P1 Down"       , 0, CpsInp001+2, "p1 down"},
  {"P1 Left"       , 0, CpsInp001+1, "p1 left"},
  {"P1 Right"      , 0, CpsInp001+0, "p1 right"},
  {"P1 Attack"     , 0, CpsInp001+4, "p1 fire 1"},
  {"P1 Jump"       , 0, CpsInp001+5, "p1 fire 2"},

  {"P2 Coin"       , 0, CpsInp018+1, "p2 coin"},
  {"P2 Start"      , 0, CpsInp018+5, "p2 start"},
  {"P2 Up"         , 0, CpsInp000+3, "p2 up"},
  {"P2 Down"       , 0, CpsInp000+2, "p2 down"},
  {"P2 Left"       , 0, CpsInp000+1, "p2 left"},
  {"P2 Right"      , 0, CpsInp000+0, "p2 right"},
  {"P2 Attack"     , 0, CpsInp000+4, "p2 fire 1"},
  {"P2 Jump"       , 0, CpsInp000+5, "p2 fire 2"},

  {"Reset"         , 0, &CpsReset,   "reset"},
  {"Diagnostic"    , 0, CpsInp018+6, "diag"},
  {"Service"       , 0, CpsInp018+2, "service"},
  {"Dip C"         , 2, &Cpi01E    , "dip"},
};

STDINPUTINFO(Drv);

static struct BurnDIPInfo punishDIPList[]=
{
	// Defaults
	{0x13, 0xff, 0xff, 0x00, NULL                },

	// Dip C
	{0   , 0xfe, 0   , 2   , "Freeze"                 },
	{0x13, 0x01, 0x08, 0x00, "Off"                    },
	{0x13, 0x01, 0x08, 0x08, "On"                     },
};

STDDIPINFO(punish);


static int DrvExit()
{

  CpsRunExit();

  CpsExit();
  nCpsQSamLen=0; nCpsZRomLen=0; nCpsGfxLen=0; nCpsRomLen=0;
  Cps=0; Cps1Qs=0;
  return 0;
}

//=============
//Punisher Init
//=============

static int PunisherInit()
{
  int nRet=0; unsigned char *pqs=NULL;
  Cps=1; Cps1Qs=1;
  nCpsRomLen= 3*0x080000;
  nCpsCodeLen=0; // not encrypted
  nCpsGfxLen= 8*0x080000;
  nCpsZRomLen= 2*0x020000;
  nCpsQSamLen= 4*0x080000;
  nRet=CpsInit(); if (nRet!=0) return 1;

  // Load program roms
  nRet=BurnLoadRom(CpsRom+0x000001,0,2); if (nRet!=0) return 1;
  nRet=BurnLoadRom(CpsRom+0x000000,1,2); if (nRet!=0) return 1;
  nRet=BurnLoadRom(CpsRom+0x040001,2,2); if (nRet!=0) return 1;
  nRet=BurnLoadRom(CpsRom+0x040000,3,2); if (nRet!=0) return 1;
  nRet=BurnLoadRom(CpsRom+0x080001,4,2); if (nRet!=0) return 1;
  nRet=BurnLoadRom(CpsRom+0x080000,5,2); if (nRet!=0) return 1;
  nRet=BurnLoadRom(CpsRom+0x0c0001,6,2); if (nRet!=0) return 1;
  nRet=BurnLoadRom(CpsRom+0x0c0000,7,2); if (nRet!=0) return 1;
  nRet=BurnLoadRom(CpsRom+0x100000,8,1); if (nRet!=0) return 1; // Already byteswapped

  // Load graphics roms
  CpsLoadTiles(CpsGfx         , 9);
  CpsLoadTiles(CpsGfx+0x200000, 13);

  nCpsLcReg=0x52; // Layer control register is at 0x52
  CpsLayEn[1]=0x04;
  CpsLayEn[2]=0x02;
  CpsLayEn[3]=0x20;

  // Protection enable code by KEV
  CpsMProt[0]=0x00;
  CpsMProt[1]=0x00;
  CpsMProt[2]=0x00;
  CpsMProt[3]=0x00;

  // Start of Board ID improvments by KEV. 0x4e,0x0c00
  CpsBID[0]=0x4e;
  CpsBID[1]=0x0c;
  CpsBID[2]=0x00;

  MaskAddr[0]=0x54;
  MaskAddr[1]=0x56;
  MaskAddr[2]=0x48;
  MaskAddr[3]=0x4a;

  nRet=BurnLoadRom(CpsZRom,17,1);
  punisher_decode();

  pqs=(unsigned char *)CpsQSam;
  nRet=BurnLoadRom(pqs         ,18,1);
  nRet=BurnLoadRom(pqs+0x080000,19,1);
  nRet=BurnLoadRom(pqs+0x100000,20,1);
  nRet=BurnLoadRom(pqs+0x180000,21,1);


  nRet=CpsRunInit(); if (nRet!=0) return 1;
  // Ready to go
  return 0;
}

//=====================
//Punisher (Japan) Init
//=====================

static int PunishrjInit()
{
  int nRet=0; unsigned char *pqs=NULL;
  Cps=1; Cps1Qs=1;
  nCpsRomLen= 3*0x080000;
  nCpsCodeLen=0; // not encrypted
  nCpsGfxLen= 8*0x080000;
  nCpsZRomLen= 2*0x020000;
  nCpsQSamLen= 4*0x080000;
  nRet=CpsInit(); if (nRet!=0) return 1;

  // Load program roms
  nRet=BurnLoadRom(CpsRom+0x000000,0,1); if (nRet!=0) return 1;
  nRet=BurnLoadRom(CpsRom+0x080000,1,1); if (nRet!=0) return 1;
  nRet=BurnLoadRom(CpsRom+0x100000,2,1); if (nRet!=0) return 1; // Already byteswapped

  // Load graphics roms
  CpsLoadTiles(CpsGfx         , 3);
  CpsLoadTiles(CpsGfx+0x200000, 7);

  nCpsLcReg=0x52; // Layer control register is at 0x52
  CpsLayEn[1]=0x04;
  CpsLayEn[2]=0x02;
  CpsLayEn[3]=0x20;

  // Protection enable code by KEV
  CpsMProt[0]=0x00;
  CpsMProt[1]=0x00;
  CpsMProt[2]=0x00;
  CpsMProt[3]=0x00;

  // Start of Board ID improvments by KEV. 0x4e,0x0c00
  CpsBID[0]=0x4e;
  CpsBID[1]=0x0c;
  CpsBID[2]=0x00;

  MaskAddr[0]=0x54;
  MaskAddr[1]=0x56;
  MaskAddr[2]=0x48;
  MaskAddr[3]=0x4a;

  nRet=BurnLoadRom(CpsZRom,11,1);
  punisher_decode();

  pqs=(unsigned char *)CpsQSam;
  nRet=BurnLoadRom(pqs         ,12,1);
  nRet=BurnLoadRom(pqs+0x080000,13,1);
  nRet=BurnLoadRom(pqs+0x100000,14,1);
  nRet=BurnLoadRom(pqs+0x180000,15,1);


  nRet=CpsRunInit(); if (nRet!=0) return 1;
  // Ready to go
  return 0;
}

//====================
//The Punisher (World)
//====================

// Count possible zip names and (if pszName!=NULL) return them

// Rom information
static struct BurnRomInfo PunisherRomDesc[]=
{
  {"pse_26.rom" ,0x20000,0x389a99d2,0x10}, // 0 even 68000 code
  {"pse_30.rom" ,0x20000,0x68fb06ac,0x10}, // 1 odd
  {"pse_27.rom" ,0x20000,0x3eb181c3,0x10}, // 2 even 68000 code
  {"pse_31.rom" ,0x20000,0x37108e7b,0x10}, // 3 odd
  {"pse_24.rom" ,0x20000,0x0f434414,0x10}, // 4 even 68000 code
  {"pse_28.rom" ,0x20000,0xb732345d,0x10}, // 5 odd
  {"pse_25.rom" ,0x20000,0xb77102e2,0x10}, // 6 even 68000 code
  {"pse_29.rom" ,0x20000,0xec037bce,0x10}, // 7 odd
  {"ps_21.rom" ,0x80000,0x8affa5a9,0x10}, // 8 swapped

  // graphics:
  {"ps_gfx1.rom",0x80000,0x77b7ccab,   1}, // 9
  {"ps_gfx3.rom",0x80000,0x0122720b,   1},
  {"ps_gfx2.rom",0x80000,0x64fa58d4,   1},
  {"ps_gfx4.rom",0x80000,0x60da42c8,   1},
  {"ps_gfx5.rom",0x80000,0xc54ea839,   1}, // 13
  {"ps_gfx7.rom",0x80000,0x04c5acbd,   1},
  {"ps_gfx6.rom",0x80000,0xa544f4cc,   1},
  {"ps_gfx8.rom",0x80000,0x8f02f436,   1},

  // z80 rom
  {"ps_q.rom" ,0x20000,0x49ff4446,   2}, // 17
  // samples
  {"ps_q1.rom" ,0x80000,0x31fd8726,   2},
  {"ps_q2.rom" ,0x80000,0x980a9eef,   2},
  {"ps_q3.rom" ,0x80000,0x0dd44491,   2},
  {"ps_q4.rom" ,0x80000,0xbed42f03,   2},
};

// Make The RomInfo/Name functions for the game
STD_ROM_PICK(Punisher) STD_ROM_FN(Punisher)

struct BurnDriver BurnDrvCpsPunisher=
{
  {"punisher","The Punisher (World)","","Capcom","CPS1","1993",NULL, NULL},
  1,2,HARDWARE_CAPCOM_CPS1_QSOUND,
  NULL,PunisherRomInfo,PunisherRomName,DrvInputInfo, punishDIPInfo,
  PunisherInit,DrvExit,Cps1Frame,CpsRedraw,CpsAreaScan,
  &CpsRecalcPal,384,224,4,3
};

//==================
//The Punisher (USA)
//==================

// Count possible zip names and (if pszName!=NULL) return them

// Rom information
static struct BurnRomInfo PunishruRomDesc[]=
{
  {"psu26.rom" ,0x20000,0x9236d121,0x10}, // 0 even 68000 code
  {"psu30.rom" ,0x20000,0x8320e501,0x10}, // 1 odd
  {"psu27.rom" ,0x20000,0x61c960a1,0x10}, // 2 even 68000 code
  {"psu31.rom" ,0x20000,0x78d4c298,0x10}, // 3 odd
  {"psu24.rom" ,0x20000,0x1cfecad7,0x10}, // 4 even 68000 code
  {"psu28.rom" ,0x20000,0xbdf921c1,0x10}, // 5 odd
  {"psu25.rom" ,0x20000,0xc51acc94,0x10}, // 6 even 68000 code
  {"psu29.rom" ,0x20000,0x52dce1ca,0x10}, // 7 odd
  {"ps_21.rom" ,0x80000,0x8affa5a9,0x10}, // 8 swapped

  // graphics:
  {"ps_gfx1.rom",0x80000,0x77b7ccab,   1}, // 9
  {"ps_gfx3.rom",0x80000,0x0122720b,   1},
  {"ps_gfx2.rom",0x80000,0x64fa58d4,   1},
  {"ps_gfx4.rom",0x80000,0x60da42c8,   1},
  {"ps_gfx5.rom",0x80000,0xc54ea839,   1}, // 13
  {"ps_gfx7.rom",0x80000,0x04c5acbd,   1},
  {"ps_gfx6.rom",0x80000,0xa544f4cc,   1},
  {"ps_gfx8.rom",0x80000,0x8f02f436,   1},

  // z80 rom
  {"ps_q.rom" ,0x20000,0x49ff4446,   2}, // 17
  // samples
  {"ps_q1.rom" ,0x80000,0x31fd8726,   2},
  {"ps_q2.rom" ,0x80000,0x980a9eef,   2},
  {"ps_q3.rom" ,0x80000,0x0dd44491,   2},
  {"ps_q4.rom" ,0x80000,0xbed42f03,   2},
};

// Make The RomInfo/Name functions for the game
STD_ROM_PICK(Punishru) STD_ROM_FN(Punishru)

struct BurnDriver BurnDrvCpsPunishru=
{
  {"punishru","The Punisher (US)","","Capcom","CPS1","1993","punisher", NULL},
  1,2,HARDWARE_CAPCOM_CPS1_QSOUND,
  NULL,PunishruRomInfo,PunishruRomName,DrvInputInfo, punishDIPInfo,
  PunisherInit,DrvExit,Cps1Frame,CpsRedraw,CpsAreaScan,
  &CpsRecalcPal,384,224,4,3
};

//====================
//The Punisher (Japan)
//====================

// Count possible zip names and (if pszName!=NULL) return them

// Rom information
static struct BurnRomInfo PunishrjRomDesc[]=
{
  {"psj23.bin" ,0x80000,0x6b2fda52,0x10}, // 0 swapped 68000 code
  {"psj22.bin" ,0x80000,0xe01036bc,0x10}, // 1 swapped
  {"ps_21.rom" ,0x80000,0x8affa5a9,0x10}, // 2 swapped

  // graphics:
  {"ps_gfx1.rom",0x80000,0x77b7ccab,   1}, // 3
  {"ps_gfx3.rom",0x80000,0x0122720b,   1},
  {"ps_gfx2.rom",0x80000,0x64fa58d4,   1},
  {"ps_gfx4.rom",0x80000,0x60da42c8,   1},
  {"ps_gfx5.rom",0x80000,0xc54ea839,   1}, // 7
  {"ps_gfx7.rom",0x80000,0x04c5acbd,   1},
  {"ps_gfx6.rom",0x80000,0xa544f4cc,   1},
  {"ps_gfx8.rom",0x80000,0x8f02f436,   1},

  // z80 rom
  {"ps_q.rom" ,0x20000,0x49ff4446,   2}, // 11
  // samples
  {"ps_q1.rom" ,0x80000,0x31fd8726,   2},
  {"ps_q2.rom" ,0x80000,0x980a9eef,   2},
  {"ps_q3.rom" ,0x80000,0x0dd44491,   2},
  {"ps_q4.rom" ,0x80000,0xbed42f03,   2},
};

// Make The RomInfo/Name functions for the game
STD_ROM_PICK(Punishrj) STD_ROM_FN(Punishrj)

struct BurnDriver BurnDrvCpsPunishrj=
{
  {"punishrj","The Punisher (Japan)","","Capcom","CPS1","1993","punisher", NULL},
  1,2,HARDWARE_CAPCOM_CPS1_QSOUND,
  NULL,PunishrjRomInfo,PunishrjRomName,DrvInputInfo, punishDIPInfo,
  PunishrjInit,DrvExit,Cps1Frame,CpsRedraw,CpsAreaScan,
  &CpsRecalcPal,384,224,4,3
};
