/* FCE Ultra - NES/Famicom Emulator
 *
 * Copyright notice for this file:
 *  Copyright (C) 2002 Ben Parnell
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "mapinc.h"

static uint8 reg1, reg2, reg3, reg4, whichmirror ;
static uint32 lastA;
//#define reg1 mapbyte1[0]
//#define reg2 mapbyte1[1]
//#define reg3 mapbyte1[2]
//#define reg4 mapbyte1[3]

DECLFR(A255in1read)
{
switch(A&0x3)
 {
  case 0:return reg1;break;
  case 1:return reg2;break;
  case 2:return reg3;break;
  case 3:return reg4;break;
 }
return 0xF;
}
DECLFW(A255in1regwr)
{
switch(A&0x3)
 {
  case 0:reg1=V&0xF;break;
  case 1:reg2=V&0xF;break;
  case 2:reg3=V&0xF;break;
  case 3:reg4=V&0xF;break;
 }
}

static DECLFW(Mapper255_write)
{
 uint32 pbank=(A>>7)&0x1F;
 uint32 cbank=A&0x3F;
 uint32 rbank=(A>>14)&1;

 lastA = A ;
// printf("$%04x:$%02x\n",A,V);
// printf("%2x:%2x:%2x,%2x\n",pbank,cbank,rbank,(A&0x40)>>6);

 if(A&0x1000)
 {
  setprg16(0x8000,((pbank|(rbank<<5))<<1)|((A&0x40)>>6));
  setprg16(0xc000,((pbank|(rbank<<5))<<1)|((A&0x40)>>6));
 }
 else
 {
  setprg32(0x8000, pbank|(rbank<<5));
 }
 setmirror((A>>13)&1 ? MI_H : MI_V );
 setchr8((rbank<<6)|cbank);
}

#if 0
DECLFW(Mapper255_write)
{
 int banks=0;

 lastA = A ;

 //if ( whichmirror )
	setmirror((A>>13)&1 ? MI_H : MI_V);
 //else
	//setmirror((A>>13)&1 ? MI_V : MI_H);

 if(A&0x4000)
  banks=1;
 else
  banks=0;

  setchr8(((A&0x003f)+(banks<<6)));
 if(A&0x1000)
  {
   if(A&0x40)
    {
     setprg16(0x8000,((((((A>>7)&0x1F)+(banks<<5)))<<1)+1));
     setprg16(0xC000,((((((A>>7)&0x1F)+(banks<<5)))<<1)+1));
     //setprg16(0x8000,((((((A>>7)&0x1F)+(banks<<5)))<<1)+1));
     //setprg16(0xC000,((((((A>>7)&0x1F)+(banks<<5)))<<1)+1));
    }
    else
    {
     setprg16(0x8000,(((((A>>7)&0x1F)+(banks<<5)))<<1));
     setprg16(0xC000,(((((A>>7)&0x1F)+(banks<<5)))<<1));
     //setprg16(0x8000,(((((A>>7)&0x1F)+(banks<<5)))<<1));
     //setprg16(0xC000,(((((A>>7)&0x1F)+(banks<<5)))<<1));
     //ROM_BANK16(0x8000,(((((A>>7)&0x1F)+(banks<<5)))<<1));
     //ROM_BANK16(0xC000,(((((A>>7)&0x1F)+(banks<<5)))<<1));
    }
  }
  else
  {
	setprg32(0x8000, ((((A>>6)&0x3F)+(banks<<5))));
	//ROM_BANK32(((((A>>7)&0x1F)+(banks<<5))));
  }
}
#endif

static int StateAction(StateMem *sm, int load, int data_only)
{
 SFORMAT StateRegs[] =
 {
  SFVAR(reg1),
  SFVAR(reg2),
  SFVAR(reg3),
  SFVAR(reg4),
  SFVAR(lastA),
  SFVAR(whichmirror),
  SFEND
 };

 int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "MAPR");

 if(load)
  Mapper255_write( lastA, 0 ) ;
 return(ret);
}

static void Power(CartInfo *info)
{
 reg1=reg2=0x0F ;
 reg3=reg4=0;
 lastA = 0 ;
 whichmirror = info->mirror ;
	setprg16(0x8000,0);
	setprg16(0xC000,~0);
 //DoBS();
	//if ( whichmirror )
		setmirror(MI_V);
	//else
		//setmirror(MI_H);
}

int Mapper255_Init(CartInfo *info)
{
	info->Power = Power ;
	info->StateAction = StateAction;
	info->Reset = Power ;

	whichmirror = info->mirror ;

	//setprg8r(1,0x6000,0);
	setprg16(0x8000,0);
	setprg16(0xC000,~0);
	//setchr8(0);
	SetReadHandler(0x8000,0xFFFF,CartBR);

  SetWriteHandler(0x8000,0xffff,Mapper255_write);
  SetReadHandler(0x5800,0x5fff,A255in1read);
  SetWriteHandler(0x5800,0x5fff,A255in1regwr);
  return 1 ;
}

