X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=boards%2F90.c;fp=boards%2F90.c;h=489a540cf1a532a5e401ca2381c4648a6552d8c8;hb=d97315ac0bca825d2d50a44453bc5652946e2c67;hp=0000000000000000000000000000000000000000;hpb=890e37ba2b8ea1c7593dc05926d7431e3bd00bfb;p=fceu.git diff --git a/boards/90.c b/boards/90.c new file mode 100644 index 0000000..489a540 --- /dev/null +++ b/boards/90.c @@ -0,0 +1,408 @@ +/* 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[]={ + {&IRQMode, 1, "IRQMODE"}, + {&IRQPre, 1, "IRQPRE"}, + {&IRQPreSize, 1, "IRQPRESIZE"}, + {&IRQCount, 1, "IRQC"}, + {&IRQXOR, 1, "IRQXOR"}, + {&IRQa, 1, "IRQa"}, + {mul, 2, "MUL"}, + {®ie, 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(M90Read) +{ + switch(A) + { + case 0x5800: return (mul[0]*mul[1]); + case 0x5801: return((mul[0]*mul[1])>>8); + case 0x5803: return (regie); + default: return(tekker); + } +} + +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) +{ + uint32 bankmode=((tkcom[3]&6)<<5); + switch(tkcom[0]&3) + { + case 1: // 16 KB + setprg16(0x8000,(prgb[0]&0x1F)|((tkcom[3]&6)<<4)); + setprg16(0xC000,(prgb[2]&0x1F)|((tkcom[3]&6)<<4)); + break; + case 2: //2 = 8 KB ?? + if(tkcom[0]&0x4) + { + setprg8(0x8000,(prgb[0]&0x3F)|bankmode); + setprg8(0xa000,(prgb[1]&0x3F)|bankmode); + setprg8(0xc000,(prgb[2]&0x3F)|bankmode); + setprg8(0xe000,(prgb[3]&0x3F)|bankmode); + } + else + { + if(tkcom[0]&0x80) + setprg8(0x6000,(prgb[3]&0x3F)|bankmode); + setprg8(0x8000,(prgb[0]&0x3F)|bankmode); + setprg8(0xa000,(prgb[1]&0x3F)|bankmode); + setprg8(0xc000,(prgb[2]&0x3F)|bankmode); + setprg8(0xe000,((~0)&0x3F)|bankmode); + } + break; + case 0: + case 3: + setprg8(0x8000,(prgb[0]&0x3F)|bankmode); + setprg8(0xa000,(prgb[1]&0x3F)|bankmode); + setprg8(0xc000,(prgb[2]&0x3F)|bankmode); + setprg8(0xe000,(prgb[3]&0x3F)|bankmode); + break; + } +} + +static void tekvrom(void) +{ + int x, bank=0, mask=0xFFFF; + if(!(tkcom[3]&0x20)) + { + bank=(tkcom[3]&1)|((tkcom[3]&0x18)>>2); + switch (tkcom[0]&0x18) + { + case 0x00: bank<<=5; mask=0x1F; break; + case 0x08: bank<<=6; mask=0x3F; break; + case 0x10: bank<<=7; mask=0x7F; break; + case 0x18: bank<<=8; mask=0xFF; break; + } + } + switch(tkcom[0]&0x18) + { + case 0x00: // 8KB + setchr8(((chrlow[0]|(chrhigh[0]<<8))&mask)|bank); + break; + case 0x08: // 4KB + for(x=0;x<8;x+=4) + setchr4(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank); + break; + case 0x10: // 2KB + for(x=0;x<8;x+=2) + setchr2(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank); + break; + case 0x18: // 1KB + for(x=0;x<8;x++) + setchr1(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank); + break; + } +} + +static DECLFW(M90Write) +{ + if(A==0x5800) mul[0]=V; + else if(A==0x5801) mul[1]=V; + else if(A==0x5803) regie=V; + + 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) + { + 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(); +/* + switch (A&3) + { + case 00: FCEU_printf("Main Control Register:\n"); + FCEU_printf(" PGR Banking mode: %d\n",V&7); + FCEU_printf(" CHR Banking mode: %d\n",(V>>3)&3); + FCEU_printf(" 6000-7FFF addresses mapping: %s\n",(V&0x80)?"Yes":"No"); + FCEU_printf(" Nametable control: %s\n",(V&0x20)?"Enabled":"Disabled"); + if(V&0x20) + FCEU_printf(" Nametable can be: %s\n",(V&0x40)?"ROM Only":"RAM or ROM"); + break; + case 01: FCEU_printf("Mirroring mode: "); + switch (V&3) + { + case 00: FCEU_printf("Vertical\n");break; + case 01: FCEU_printf("Horizontal\n");break; + case 02: FCEU_printf("Nametable 0 only\n");break; + case 03: FCEU_printf("Nametable 1 only\n");break; + } + FCEU_printf("Mirroring flag: %s\n",(V&0x80)?"On":"Off"); + break; + case 02: if((((tkcom[0])>>5)&3)==1) + FCEU_printf("Nametable ROM/RAM select mode: %d\n",V>>7); + break; + case 03: + FCEU_printf("CHR Banking mode: %s\n",(V&0x20)?"Entire CHR ROM":"256Kb Switching mode"); + if(!(V&0x20)) FCEU_printf("256K CHR bank number: %02x\n",(V&1)|((V&0x18)>>2)); + FCEU_printf("512K PRG bank number: %d\n",(V&6)>>1); + FCEU_printf("CHR Bank mirroring: %s\n",(V&0x80)?"Swapped":"Normal operate"); + } +*/ + } + else switch(A) + { + case 0xc000: //FCEU_printf("%s IRQ (C000)\n",V&1?"Enable":"Disable"); + IRQa=V&1;if(!(V&1)) X6502_IRQEnd(FCEU_IQEXT);break; + case 0xc002: //FCEU_printf("Disable IRQ (C002) scanline=%d\n", scanline); + IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break; + case 0xc003: //FCEU_printf("Enable IRQ (C003) scanline=%d\n", scanline); + IRQa=1;break; + case 0xc001: IRQMode=V; +/* FCEU_printf("IRQ Count method: "); + switch (IRQMode&3) + { + case 00: FCEU_printf("M2 cycles\n");break; + case 01: FCEU_printf("PPU A12 toggles\n");break; + case 02: FCEU_printf("PPU reads\n");break; + case 03: FCEU_printf("Writes to CPU space\n");break; + } + FCEU_printf("Counter prescaler size: %s\n",(IRQMode&4)?"3 bits":"8 bits"); + FCEU_printf("Counter prescaler size adjust: %s\n",(IRQMode&8)?"Used C007":"Normal Operation"); + if((IRQMode>>6)==2) FCEU_printf("Counter Down\n"); + else if((IRQMode>>6)==1) FCEU_printf("Counter Up\n"); + else FCEU_printf("Counter Stopped\n"); +*/ break; + case 0xc004: //FCEU_printf("Pre Counter Loaded and Xored wiht C006: %d\n",V^IRQXOR); + IRQPre=V^IRQXOR;break; + case 0xc005: //FCEU_printf("Main Counter Loaded and Xored wiht C006: %d\n",V^IRQXOR); + IRQCount=V^IRQXOR;break; + case 0xc006: //FCEU_printf("Xor Value: %d\n",V); + IRQXOR=V;break; + case 0xc007: //if(!(IRQMode&8)) FCEU_printf("C001 is clear, no effect applied\n"); + // else if(V==0xFF) FCEU_printf("Prescaler is changed for 12bits\n"); + // else FCEU_printf("Counter Stopped\n"); + 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--; + if((IRQPre & premask) == premask) CCL(); + } +} + +static void SLWrap(void) +{ + int x; + if((IRQMode&3)!=2) for(x=0;x<8;x++) ClockCounter(); +} + +static uint32 lastread; +static void FP_FASTAPASS(1) M90PPU(uint32 A) +{ + if(lastread!=A) + { + lastread=A; + if((IRQMode&3)==2) + { + ClockCounter(); + ClockCounter(); + } + } +} + +static void togglie() +{ + tekker>>=6; + if(tekker>3) + tekker=0; + else + tekker++; + tekker<<=6; + FCEU_printf("tekker=%04x\n",tekker); + memset(tkcom,0xff,sizeof(tkcom)); + memset(prgb,0xff,sizeof(prgb)); + tekprom(); + tekvrom(); +} + +static void M90Restore(int version) +{ + tekprom(); + tekvrom(); + mira(); +} + +static void M90Power(void) +{ + SetWriteHandler(0x5000,0xffff,M90Write); + SetReadHandler(0x5000,0x5fff,M90Read); + SetReadHandler(0x6000,0xffff,CartBR); + + mul[0]=mul[1]=regie=0xFF; + + memset(tkcom,0xff,sizeof(tkcom)); + memset(prgb,0xff,sizeof(prgb)); + memset(chrlow,0xff,sizeof(chrlow)); + memset(chrhigh,0xff,sizeof(chrhigh)); + memset(names,0x00,sizeof(names)); + + tekker=0; + + tekprom(); + tekvrom(); +} + + +void Mapper90_Init(CartInfo *info) +{ + is209=0; + info->Reset=togglie; + info->Power=M90Power; + PPU_hook = M90PPU; + GameHBIRQHook2 = SLWrap; + GameStateRestore=M90Restore; + AddExState(Tek_StateRegs, ~0, 0, 0); +} + +void Mapper209_Init(CartInfo *info) +{ + is209=1; + info->Reset=togglie; + info->Power=M90Power; + PPU_hook = M90PPU; + GameHBIRQHook2 = SLWrap; + GameStateRestore=M90Restore; + AddExState(Tek_StateRegs, ~0, 0, 0); +}