mirror of
https://github.com/dborth/fceugx.git
synced 2024-12-26 00:21:53 +01:00
236 lines
5.7 KiB
C
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");
|
|
}
|