fceugx/source/boards/super24.c
2008-04-03 03:58:35 +00:00

236 lines
5.7 KiB
C

/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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 int32 IRQCount,IRQLatch;
static uint8 IRQa,resetmode,mbia;
static uint8 sizer,bigbank,bigbank2;
static uint8 DRegBuf[8],MMC3_cmd;
static int masko8[8]={63,31,15,1,3,0,0,0};
//static int masko1[8]={511,255,127,7,7,0,0,0};
static void swsetprg8(uint32 A, uint32 V)
{
V&=masko8[sizer&7];
V|=(bigbank*2);
setprg8r((V/64)&15,A,V);
}
static void swsetchr1(uint32 A, uint32 V)
{
if(sizer&0x20)
setchr1r(0x10,A,V);
else
{
// V&=masko1[sizer&7];
V|=bigbank2*8;
setchr1r((V/512)&15,A,V);
}
}
static void swsetchr2(uint32 A, uint32 V)
{
if(sizer&0x20)
setchr2r(0x10,A,V);
else
{
//V&=masko1[sizer&7]>>1;
V|=bigbank2*4;
setchr2r((V/256)&15,A,V);
}
}
static void Sup24_hb(void)
{
resetmode=0;
if(scanline==238) X6502_IRQBegin(FCEU_IQEXT);
if(IRQCount>=0)
{
IRQCount--;
if(IRQCount<0)
{
if(IRQa)
{
resetmode = 1;
X6502_IRQBegin(FCEU_IQEXT);
//printf("IRQ: %d,%d\n",scanline,timestamp);
}
}
}
}
static DECLFW(Sup24IRQWrite)
{
//printf("%04x, $%02x, %d, %d\n",A,V,scanline,timestamp);
switch(A&0xE001)
{
case 0xc000:IRQLatch=V;
if(resetmode==1)
IRQCount=IRQLatch;
break;
case 0xc001:resetmode=1;
IRQCount=IRQLatch;
break;
case 0xE000:IRQa=0;X6502_IRQEnd(FCEU_IQEXT);
if(resetmode==1)
{IRQCount=IRQLatch;}
break;
case 0xE001:IRQa=1;
if(resetmode==1)
{IRQCount=IRQLatch;}
break;
}
}
static INLINE void FixMMC3PRG(int V)
{
swsetprg8(0xA000,DRegBuf[7]);
swsetprg8(0xE000,~0);
if(V&0x40)
{
swsetprg8(0xC000,DRegBuf[6]);
swsetprg8(0x8000,~1);
}
else
{
swsetprg8(0x8000,DRegBuf[6]);
swsetprg8(0xC000,~1);
}
}
static INLINE void FixMMC3CHR(int V)
{
int cbase=(V&0x80)<<5;
swsetchr2((cbase^0x000),DRegBuf[0]>>1);
swsetchr2((cbase^0x800),DRegBuf[1]>>1);
swsetchr1(cbase^0x1000,DRegBuf[2]);
swsetchr1(cbase^0x1400,DRegBuf[3]);
swsetchr1(cbase^0x1800,DRegBuf[4]);
swsetchr1(cbase^0x1c00,DRegBuf[5]);
}
static DECLFW(Super24hiwrite)
{
//printf("$%04x:$%02x, %d\n",A,V,scanline);
switch(A&0xE001)
{
case 0x8000:
if((V&0x40) != (MMC3_cmd&0x40))
FixMMC3PRG(V);
if((V&0x80) != (MMC3_cmd&0x80))
FixMMC3CHR(V);
MMC3_cmd = V;
break;
case 0x8001:
{
int cbase=(MMC3_cmd&0x80)<<5;
DRegBuf[MMC3_cmd&0x7]=V;
switch(MMC3_cmd&0x07)
{
case 0: V>>=1;swsetchr2((cbase^0x000),V);break;
case 1: V>>=1;swsetchr2((cbase^0x800),V);break;
case 2: swsetchr1(cbase^0x1000,V); break;
case 3: swsetchr1(cbase^0x1400,V); break;
case 4: swsetchr1(cbase^0x1800,V); break;
case 5: swsetchr1(cbase^0x1C00,V); break;
case 6: if (MMC3_cmd&0x40) swsetprg8(0xC000,V);
else swsetprg8(0x8000,V);
break;
case 7: swsetprg8(0xA000,V);
break;
}
}
break;
case 0xA000:
mbia=V;
setmirror((V&1)^1);
break;
}
}
static DECLFW(Super24Write)
{
//printf("$%04x:$%02x\n",A,V);
switch(A)
{
case 0x5ff0:sizer=V;
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
break;
case 0x5FF1:
bigbank=V;
FixMMC3PRG(MMC3_cmd);
break;
case 0x5FF2:
bigbank2=V;
FixMMC3CHR(MMC3_cmd);
break;
}
}
static void Super24Reset(void)
{
SetWriteHandler(0x8000,0xBFFF,Super24hiwrite);
SetWriteHandler(0x5000,0x7FFF,Super24Write);
SetWriteHandler(0xC000,0xFFFF,Sup24IRQWrite);
SetReadHandler(0x8000,0xFFFF,CartBR);
GameHBIRQHook=Sup24_hb;
IRQCount=IRQLatch=IRQa=resetmode=0;
sizer=0x24;
bigbank=159;
bigbank2=0;
MMC3_cmd=0;
DRegBuf[6]=0;
DRegBuf[7]=1;
FixMMC3PRG(0);
FixMMC3CHR(0);
}
static void MrRestore(int version)
{
FixMMC3PRG(MMC3_cmd);
FixMMC3CHR(MMC3_cmd);
setmirror((mbia&1)^1);
}
void Super24_Init(CartInfo *info)
{
info->Power=Super24Reset;
SetupCartCHRMapping(0x10, GameMemBlock, 8192, 1);
GameStateRestore=MrRestore;
AddExState(GameMemBlock, 8192, 0, "CHRR");
AddExState(DRegBuf, 8, 0, "DREG");
AddExState(&IRQCount, 4, 1, "IRQC");
AddExState(&IRQLatch, 4, 1, "IQL1");
AddExState(&IRQa, 1, 0, "IRQA");
AddExState(&sizer, 1, 0, "SIZA");
AddExState(&bigbank, 1, 0, "BIG1");
AddExState(&bigbank2, 1, 0, "BIG2");
}