fceugx/source/fceultra/mbshare/90.c
2008-09-02 01:55:12 +00:00

344 lines
6.8 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 int is209;
static uint8 IRQMode; // from $c001
static uint8 IRQPre; // from $c004
static uint8 IRQPreSize; // from $c007
static uint8 IRQCount; // from $c005
static uint8 IRQXOR; // Loaded from $C006
static uint8 IRQa; // $c002, $c003, and $c000
static uint8 mul[2];
static uint8 regie;
static uint8 tkcom[4];
static uint8 prgb[4];
static uint8 chrlow[8];
static uint8 chrhigh[8];
static uint16 names[4];
static uint8 tekker;
static SFORMAT Tek_StateRegs[]={
{&IRQCount, 1, "IRQC"},
{&IRQa, 1, "IRQa"},
{mul, 2, "MUL"},
{&regie, 1, "REGI"},
{tkcom, 4, "TKCO"},
{prgb, 4, "PRGB"},
{chrlow, 4, "CHRL"},
{chrhigh, 8, "CHRH"},
{&names[0], 2|FCEUSTATE_RLSB, "NMS0"},
{&names[1], 2|FCEUSTATE_RLSB, "NMS1"},
{&names[2], 2|FCEUSTATE_RLSB, "NMS2"},
{&names[3], 2|FCEUSTATE_RLSB, "NMS3"},
{&tekker, 1, "TEKR"},
{0}
};
static DECLFR(tekread)
{
//FCEU_printf("READ READ READ: $%04x, $%04x\n",A,X.PC);
switch(A)
{
case 0x5000:return(tekker);
case 0x5800:return(mul[0]*mul[1]);
case 0x5801:return((mul[0]*mul[1])>>8);
case 0x5803:return(regie);
default:break;
}
return(X.DB);
}
static void mira(void)
{
if(tkcom[0]&0x20 && is209)
{
int x;
if(tkcom[0] & 0x40) // Name tables are ROM-only
{
for(x=0;x<4;x++)
setntamem(CHRptr[0]+(((names[x])&CHRmask1[0])<<10), 0, x);
}
else // Name tables can be RAM or ROM.
{
for(x=0;x<4;x++)
{
if((tkcom[2]&0x80) == (names[x]&0x80)) // RAM selected.
setntamem(NTARAM + ((names[x]&0x1)<<10),1,x);
else
setntamem(CHRptr[0]+(((names[x])&CHRmask1[0])<<10), 0, x);
}
}
}
else
{
switch(tkcom[1]&3){
case 0:setmirror(MI_V);break;
case 1:setmirror(MI_H);break;
case 2:setmirror(MI_0);break;
case 3:setmirror(MI_1);break;
}
}
}
static void tekprom(void)
{
switch(tkcom[0]&3)
{
case 1: // 16 KB
setprg16(0x8000,prgb[0]);
setprg16(0xC000,prgb[2]);
break;
case 2: //2 = 8 KB ??
if(tkcom[0]&0x4)
{
setprg8(0x8000,prgb[0]);
setprg8(0xa000,prgb[1]);
setprg8(0xc000,prgb[2]);
setprg8(0xe000,prgb[3]);
}
else
{
if(tkcom[0]&0x80)
setprg8(0x6000,prgb[3]);
setprg8(0x8000,prgb[0]);
setprg8(0xa000,prgb[1]);
setprg8(0xc000,prgb[2]);
setprg8(0xe000,~0);
}
break;
case 0:
case 3:
setprg8(0x8000,prgb[0]);
setprg8(0xa000,prgb[1]);
setprg8(0xc000,prgb[2]);
setprg8(0xe000,prgb[3]);
break;
}
}
static void tekvrom(void)
{
int x;
switch(tkcom[0]&0x18)
{
case 0x00: // 8KB
setchr8(chrlow[0]|(chrhigh[0]<<8));
break;
case 0x08: // 4KB
for(x=0;x<8;x+=4)
setchr4(x<<10,chrlow[x]|(chrhigh[x]<<8));
break;
case 0x10: // 2KB
for(x=0;x<8;x+=2)
setchr2(x<<10,chrlow[x]|(chrhigh[x]<<8));
break;
case 0x18: // 1KB
for(x=0;x<8;x++)
setchr1(x<<10,(chrlow[x]|(chrhigh[x]<<8)));
break;
}
}
static DECLFW(Mapper90_write)
{
//printf("$%04x:$%02x\n",A,V);
if(A==0x5800) mul[0]=V;
else if(A==0x5801) mul[1]=V;
else if(A==0x5803) regie=V;
//if(A>=0xc000 && A<=0xc007)
// FCEU_printf("$%04x:$%02x $%04x, %d, %d\n",A,V,X.PC,scanline,timestamp);
A&=0xF007;
if(A>=0x8000 && A<=0x8003)
{
prgb[A&3]=V;
tekprom();
}
else if(A>=0x9000 && A<=0x9007)
{
chrlow[A&7]=V;
tekvrom();
}
else if(A>=0xa000 && A<=0xa007)
{
chrhigh[A&7]=V;
tekvrom();
}
else if(A>=0xb000 && A<=0xb007)
{
//printf("$%04x:$%02x\n",A,V);
if(A&4)
{
names[A&3]&=0x00FF;
names[A&3]|=V<<8;
}
else
{
names[A&3]&=0xFF00;
names[A&3]|=V;
}
mira();
}
else if(A>=0xd000 && A<=0xdfff)
{
tkcom[A&3]=V;
tekprom();
tekvrom();
mira();
}
else switch(A)
{
case 0xc000: IRQa=V&1;if(!(V&1)) X6502_IRQEnd(FCEU_IQEXT);break;
case 0xc002: IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break;
case 0xc003: IRQa=1;break;
case 0xc001: IRQMode=V;break;
case 0xc004: IRQPre=V^IRQXOR;break;
case 0xc005: IRQCount=V^IRQXOR;break;
case 0xc006: IRQXOR=V;break;
case 0xc007: IRQPreSize=V;break;
}
}
static void CCL(void)
{
if((IRQMode>>6) == 1) // Count Up
{
IRQCount++;
if((IRQCount == 0) && IRQa)
X6502_IRQBegin(FCEU_IQEXT);
}
else if((IRQMode>>6) == 2) // Count down
{
IRQCount--;
if((IRQCount == 0xFF) && IRQa)
X6502_IRQBegin(FCEU_IQEXT);
}
}
static void ClockCounter(void)
{
uint8 premask;
if(IRQMode & 0x4) premask = 0x7;
else premask = 0xFF;
if((IRQMode>>6) == 1) // Count up
{
IRQPre++;
if((IRQPre & premask) == 0)
CCL();
}
else if((IRQMode>>6) == 2) // Count down
{
IRQPre--;
//printf("%d\n",IRQPre);
if((IRQPre & premask) == premask)
CCL();
}
}
static void SLWrap(void)
{
int x;
for(x=0;x<8;x++) ClockCounter(); // 8 PPU A10 0->1 transitions per scanline(usually)
}
/*
static uint32 lasta;
static void FP_FASTAPASS(1) YARGH(uint32 A)
{
if((A&0x1000) && !(lasta & 0x1000))
ClockCounter();
lasta = A;
}
*/
static void togglie()
{
tekker^=0xFF;
}
static void m90rest(int version)
{
mira();
}
static void M90Power(void)
{
SetWriteHandler(0x5000,0xffff,Mapper90_write);
SetReadHandler(0x5000,0x5fff,tekread);
SetReadHandler(0x6000,0xffff,CartBR);
mul[0]=mul[1]=regie=0xFF;
tkcom[0]=tkcom[1]=tkcom[2]=tkcom[3]=0xFF;
memset(prgb,0xff,sizeof(prgb));
memset(chrlow,0xff,sizeof(chrlow));
memset(chrhigh,0xff,sizeof(chrhigh));
memset(names,0x00,sizeof(names));
tekker=0;
prgb[0]=0xFF;
prgb[1]=0xFF;
prgb[2]=0xFF;
prgb[3]=0xFF;
tekprom();
tekvrom();
}
void Mapper90_Init(CartInfo *info)
{
is209=0;
info->Reset=togglie;
info->Power=M90Power;
//PPU_hook = YARGH;
GameHBIRQHook2 = SLWrap;
GameStateRestore=m90rest;
AddExState(Tek_StateRegs, ~0, 0, 0);
}
void Mapper209_Init(CartInfo *info)
{
is209=1;
info->Reset=togglie;
info->Power=M90Power;
//PPU_hook = YARGH;
GameHBIRQHook2 = SLWrap;
GameStateRestore=m90rest;
AddExState(Tek_StateRegs, ~0, 0, 0);
}