X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=boards%2F90.c;h=074f560d9c672282dd16967f23781809210911d4;hb=3ac1cc0b221c10cd9a82ba3c12d111597dc554e7;hp=489a540cf1a532a5e401ca2381c4648a6552d8c8;hpb=d97315ac0bca825d2d50a44453bc5652946e2c67;p=fceu.git diff --git a/boards/90.c b/boards/90.c index 489a540..074f560 100644 --- a/boards/90.c +++ b/boards/90.c @@ -2,6 +2,7 @@ * * Copyright notice for this file: * Copyright (C) 2002 Xodnizel + * Copyright (C) 2005 CaH4e3 * * 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 @@ -19,8 +20,14 @@ */ #include "mapinc.h" +//#define DEBUG90 -static int is209; +// Mapper 090 is simpliest mapper hardware and have not extended nametable control and latched chr banks in 4k mode +// Mapper 209 much compicated hardware with decribed above features disabled by default and switchable by command +// Mapper 211 the same mapper 209 but with forced nametable control + +static int is209; +static int is211; static uint8 IRQMode; // from $c001 static uint8 IRQPre; // from $c004 @@ -37,20 +44,23 @@ static uint8 prgb[4]; static uint8 chrlow[8]; static uint8 chrhigh[8]; +static uint8 chr[2]; + static uint16 names[4]; static uint8 tekker; static SFORMAT Tek_StateRegs[]={ - {&IRQMode, 1, "IRQMODE"}, - {&IRQPre, 1, "IRQPRE"}, - {&IRQPreSize, 1, "IRQPRESIZE"}, + {&IRQMode, 1, "IRQM"}, + {&IRQPre, 1, "IRQP"}, + {&IRQPreSize, 1, "IRQR"}, {&IRQCount, 1, "IRQC"}, - {&IRQXOR, 1, "IRQXOR"}, - {&IRQa, 1, "IRQa"}, + {&IRQXOR, 1, "IRQX"}, + {&IRQa, 1, "IRQA"}, {mul, 2, "MUL"}, {®ie, 1, "REGI"}, {tkcom, 4, "TKCO"}, {prgb, 4, "PRGB"}, + {chr, 2, "CLTC"}, {chrlow, 4, "CHRL"}, {chrhigh, 8, "CHRH"}, {&names[0], 2|FCEUSTATE_RLSB, "NMS0"}, @@ -61,20 +71,9 @@ static SFORMAT Tek_StateRegs[]={ {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) + if((tkcom[0]&0x20&&is209)||is211) { int x; if(tkcom[0]&0x40) // Name tables are ROM-only @@ -86,7 +85,7 @@ static void mira(void) { for(x=0;x<4;x++) { - if((tkcom[2]&0x80)==(names[x]&0x80)) // RAM selected. + if((tkcom[1]&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); @@ -105,40 +104,48 @@ static void mira(void) } } -static void tekprom(void) +static void tekprom(void) // TODO: verify for single, small multi and large multi { uint32 bankmode=((tkcom[3]&6)<<5); - switch(tkcom[0]&3) + switch(tkcom[0]&7) { - 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; + case 00: if(tkcom[0]&0x80) + setprg8(0x6000,(((prgb[3]<<2)+3)&0x3F)|bankmode); + setprg32(0x8000,(prgb[3]&7)|((tkcom[3]&7)<<3)); + break; + case 01: if(tkcom[0]&0x80) + setprg8(0x6000,(((prgb[3]<<1)+1)&0x3F)|bankmode); + setprg16(0x8000,(prgb[1]&0x0F)|((tkcom[3]&7)<<4)); + setprg16(0xC000,0x0F|((tkcom[3]&7)<<4)); + break; + case 03: // bit reversion + case 02: + if(tkcom[0]&0x80) + setprg8(0x6000,(prgb[3]&0x1F)|((tkcom[3]&7)<<5)); // 45in1 multy has different bits, seems board was hacked to support big data banks + setprg8(0x8000,(prgb[0]&0x1F)|((tkcom[3]&7)<<5)); + setprg8(0xa000,(prgb[1]&0x1F)|((tkcom[3]&7)<<5)); + setprg8(0xc000,(prgb[2]&0x1F)|((tkcom[3]&7)<<5)); + setprg8(0xe000,0x1F|((tkcom[3]&7)<<5)); +// setprg8(0xe000,(prgb[3]&0x0F)|((tkcom[3]&6)<<3)); +// setprg32(0x8000,((prgb[0]&0x0F)>>2)|((tkcom[3]&6)<<3)); + break; + case 04: if(tkcom[0]&0x80) + setprg8(0x6000,(((prgb[3]<<2)+3)&0x3F)|bankmode); + setprg32(0x8000,(prgb[3]&0x0F)|((tkcom[3]&6)<<3)); + break; + case 05: if(tkcom[0]&0x80) + setprg8(0x6000,(((prgb[3]<<1)+1)&0x3F)|bankmode); + setprg16(0x8000,(prgb[1]&0x1F)|((tkcom[3]&6)<<4)); + setprg16(0xC000,(prgb[3]&0x1F)|((tkcom[3]&6)<<4)); + break; + case 07: // bit reversion + case 06: 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,(prgb[3]&0x3F)|bankmode); + break; } } @@ -162,8 +169,10 @@ static void tekvrom(void) 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); +// for(x=0;x<8;x+=4) +// setchr4(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank); + setchr4(0x0000,((chrlow[chr[0]]|(chrhigh[chr[0]]<<8))&mask)|bank); + setchr4(0x1000,((chrlow[chr[1]]|(chrhigh[chr[1]]<<8))&mask)|bank); break; case 0x10: // 2KB for(x=0;x<8;x+=2) @@ -176,49 +185,113 @@ static void tekvrom(void) } } -static DECLFW(M90Write) +static DECLFW(M90TekWrite) { - 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) + switch(A&0x5C03) { - prgb[A&3]=V; - tekprom(); + case 0x5800: mul[0]=V; break; + case 0x5801: mul[1]=V; break; + case 0x5803: regie=V; break; } - else if(A>=0x9000 && A<=0x9007) +} + +static DECLFR(M90TekRead) +{ + switch(A&0x5C03) { - chrlow[A&7]=V; - tekvrom(); + case 0x5800: return (mul[0]*mul[1]); + case 0x5801: return((mul[0]*mul[1])>>8); + case 0x5803: return (regie); + default: return tekker; } - else if(A>=0xa000 && A<=0xa007) + return(0xff); +} + +static DECLFW(M90PRGWrite) +{ +// FCEU_printf("bs %04x %02x\n",A,V); + prgb[A&3]=V; + tekprom(); +} + +static DECLFW(M90CHRlowWrite) +{ +// FCEU_printf("bs %04x %02x\n",A,V); + chrlow[A&7]=V; + tekvrom(); +} + +static DECLFW(M90CHRhiWrite) +{ +// FCEU_printf("bs %04x %02x\n",A,V); + chrhigh[A&7]=V; + tekvrom(); +} + +static DECLFW(M90NTWrite) +{ +// FCEU_printf("bs %04x %02x\n",A,V); + if(A&4) { - chrhigh[A&7]=V; - tekvrom(); + names[A&3]&=0x00FF; + names[A&3]|=V<<8; } - else if(A>=0xb000 && A<=0xb007) + else { - if(A&4) - { - names[A&3]&=0x00FF; - names[A&3]|=V<<8; - } - else - { - names[A&3]&=0xFF00; - names[A&3]|=V; - } - mira(); + names[A&3]&=0xFF00; + names[A&3]|=V; } - else if(A>=0xd000 && A<=0xdfff) + mira(); +} + +static DECLFW(M90IRQWrite) +{ +// FCEU_printf("bs %04x %02x\n",A,V); + switch(A&7) { + case 00: //FCEU_printf("%s IRQ (C000)\n",V&1?"Enable":"Disable"); + IRQa=V&1;if(!(V&1)) X6502_IRQEnd(FCEU_IQEXT);break; + case 02: //FCEU_printf("Disable IRQ (C002) scanline=%d\n", scanline); + IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break; + case 03: //FCEU_printf("Enable IRQ (C003) scanline=%d\n", scanline); + IRQa=1;break; + case 01: 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 04: //FCEU_printf("Pre Counter Loaded and Xored wiht C006: %d\n",V^IRQXOR); + IRQPre=V^IRQXOR;break; + case 05: //FCEU_printf("Main Counter Loaded and Xored wiht C006: %d\n",V^IRQXOR); + IRQCount=V^IRQXOR;break; + case 06: //FCEU_printf("Xor Value: %d\n",V); + IRQXOR=V;break; + case 07: //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 DECLFW(M90ModeWrite) +{ +// FCEU_printf("bs %04x %02x\n",A,V); tkcom[A&3]=V; tekprom(); tekvrom(); mira(); -/* + +#ifdef DEBUG90 switch (A&3) { case 00: FCEU_printf("Main Control Register:\n"); @@ -232,10 +305,10 @@ static DECLFW(M90Write) 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; + case 0: FCEU_printf("Vertical\n");break; + case 1: FCEU_printf("Horizontal\n");break; + case 2: FCEU_printf("Nametable 0 only\n");break; + case 3: FCEU_printf("Nametable 1 only\n");break; } FCEU_printf("Mirroring flag: %s\n",(V&0x80)?"On":"Off"); break; @@ -248,42 +321,12 @@ static DECLFW(M90Write) 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; - } +#endif +} + +static DECLFW(M90DummyWrite) +{ +// FCEU_printf("bs %04x %02x\n",A,V); } static void CCL(void) @@ -292,13 +335,17 @@ static void CCL(void) { 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); + } } } @@ -322,36 +369,63 @@ static void ClockCounter(void) } } +void FP_FASTAPASS(1) CPUWrap(int a) +{ + int x; + if((IRQMode&3)==0) for(x=0;x>8; + if(h<0x20&&((h&0x0F)==0xF)) + { + l=A&0xF0; + if(l==0xD0) + { + chr[(h&0x10)>>4]=((h&0x10)>>2); + tekvrom(); + } + else if(l==0xE0) + { + chr[(h&0x10)>>4]=((h&0x10)>>2)|2; + tekvrom(); + } + } + } + else + { + chr[0]=0; + chr[1]=4; } } 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)); + tekker+=0x40; + tekker&=0xC0; + FCEU_printf("tekker=%02x\n",tekker); + memset(tkcom,0x00,sizeof(tkcom)); memset(prgb,0xff,sizeof(prgb)); tekprom(); tekvrom(); @@ -366,19 +440,30 @@ static void M90Restore(int version) static void M90Power(void) { - SetWriteHandler(0x5000,0xffff,M90Write); - SetReadHandler(0x5000,0x5fff,M90Read); + SetWriteHandler(0x5000,0x5fff,M90TekWrite); + SetWriteHandler(0x8000,0x8ff0,M90PRGWrite); + SetWriteHandler(0x9000,0x9fff,M90CHRlowWrite); + SetWriteHandler(0xA000,0xAfff,M90CHRhiWrite); + SetWriteHandler(0xB000,0xBfff,M90NTWrite); + SetWriteHandler(0xC000,0xCfff,M90IRQWrite); + SetWriteHandler(0xD000,0xD5ff,M90ModeWrite); + SetWriteHandler(0xE000,0xFfff,M90DummyWrite); + + SetReadHandler(0x5000,0x5fff,M90TekRead); SetReadHandler(0x6000,0xffff,CartBR); mul[0]=mul[1]=regie=0xFF; - memset(tkcom,0xff,sizeof(tkcom)); + memset(tkcom,0x00,sizeof(tkcom)); memset(prgb,0xff,sizeof(prgb)); memset(chrlow,0xff,sizeof(chrlow)); memset(chrhigh,0xff,sizeof(chrhigh)); memset(names,0x00,sizeof(names)); - tekker=0; + if(is211) + tekker=0xC0; + else + tekker=0x00; tekprom(); tekvrom(); @@ -387,22 +472,38 @@ static void M90Power(void) void Mapper90_Init(CartInfo *info) { + is211=0; is209=0; info->Reset=togglie; info->Power=M90Power; - PPU_hook = M90PPU; - GameHBIRQHook2 = SLWrap; + PPU_hook=M90PPU; + MapIRQHook=CPUWrap; + GameHBIRQHook2=SLWrap; GameStateRestore=M90Restore; AddExState(Tek_StateRegs, ~0, 0, 0); } void Mapper209_Init(CartInfo *info) { + is211=0; is209=1; info->Reset=togglie; info->Power=M90Power; - PPU_hook = M90PPU; - GameHBIRQHook2 = SLWrap; + PPU_hook=M90PPU; + MapIRQHook=CPUWrap; + GameHBIRQHook2=SLWrap; + GameStateRestore=M90Restore; + AddExState(Tek_StateRegs, ~0, 0, 0); +} + +void Mapper211_Init(CartInfo *info) +{ + is211=1; + info->Reset=togglie; + info->Power=M90Power; + PPU_hook=M90PPU; + MapIRQHook=CPUWrap; + GameHBIRQHook2=SLWrap; GameStateRestore=M90Restore; AddExState(Tek_StateRegs, ~0, 0, 0); }