📄 mappers.h
字号:
void LoopROM5(void){ if(MM.M5.Count==NCURLINE) if(MM.M5.IRQ) NES_CPU.IRequest=NES_INT_IRQ;}/** LoopROM16() **********************************************//** Loop handler for Bandai hardware. **//*************************************************************/void LoopROM16(void){ if(MM.M16.IRQ) { MM.M16.Count-=ines->HPeriod; if(MM.M16.Count<=0) { NES_CPU.IRequest=NES_INT_IRQ; MM.M16.IRQ=0; } }}/** LoopROMX() ***********************************************//** Generic loop handler for many mappers. **//*************************************************************/void LoopROMX(void){ if(MM.Count&&MM.IRQ) if(!--MM.Count) NES_CPU.IRequest=NES_INT_IRQ;}#endif /*CD_GAME*/#endif/** Mapper #1 ************************************************//** This mapper is known as MMC1 chip from Nintendo. It may **//** have up to 16x16kB (or 32x16kB) NES_ROM and 32x8kB VROM. **//** MMC1 is controlled via 4 5-bit registers, written **//** sequentially. **//** **//** Bomberman2, Megaman2, OperationWolf, SilkWorm, **//** Airwolf, Yoshi, BreakThru, etc. **//*************************************************************/int SelectROM1(int A,int V){ register int J,N0,N1; /* We are only interested in writes into $8000-$FFFF */ if(A<0x8000) return(0); /* If 7th bit set, reset the mapper */ if(V&0x80) { /* Reset bit counters and buffers */ MM.M1.C[0]=MM.M1.C[1]=MM.M1.C[2]=MM.M1.C[3]=0x01; MM.M1.S[0]=MM.M1.S[1]=MM.M1.S[2]=MM.M1.S[3]=0x00; /* Reset R0 register but leave bit 0x10 */ MM.M1.R[0]=(MM.M1.R[0]&0x10)|0x0C; /* Make it look like R0 has been updated */ A=0; } else { /* Get register number */ A=(A&0x6000)>>13; /* Accumulate bits */ V=0-(V&0x01); J=MM.M1.C[A]; V=MM.M1.S[A]|=(V&J); /* Shift bit counter */ J<<=1; /* If not enough bits, done */ if(J<0x20) { MM.M1.C[A]=J;return(1); } /* 5 bits accumulated, reset bit counter, */ /* reset bit buffer, and write to a register */ MM.M1.C[A]=0x01; MM.M1.S[A]=0x00; MM.M1.R[A]=V; } /* V = R0 */ V=MM.M1.R[0]; /* R0: Select screen buffers */ if(!A) if(V&0x02) SetMirror(~V&0x01); else ines->VPage[8]=ines->VPage[9]=ines->VPage[10]=ines->VPage[11]=NES_VRAM+(V&0x01? 0x2400:0x2000); /* R0,R1,R3: Select NES_ROM pages */ if(A!=2) { if(V&0x08) if(V&0x04) { N0=MM.M1.R[3]&0x0F;N1=0x0F; } else { N0=0;N1=MM.M1.R[3]&0x0F; } else { J=MM.M1.R[3]&0x0E;N0=J;N1=J+1; } /* Adjust for the 256kB bank number */ if(ines->ROMPages>16) { J=MM.M1.R[1]&0x10;N0|=J;N1|=J; } /* Set memory to selected NES_ROM pages */ NES_Page[4]=PAGE(N0); NES_Page[5]=NES_Page[4]+0x2000; NES_Page[6]=PAGE(N1); NES_Page[7]=NES_Page[6]+0x2000; } /* R0,R1,R2: Select VROM pages */ if(A!=3) { if(V&0x10) { N0=MM.M1.R[1];N1=MM.M1.R[2]; } else { N0=MM.M1.R[1]&0xFE;N1=N0+1; } /* Set memory to selected VROM pages */ SetVPages(0,3,VROM? VPAGE(N0>>1)+(N0&0x01? 0x1000:0):NES_VRAM); SetVPages(4,7,VROM? VPAGE(N1>>1)+(N1&0x01? 0x1000:0):NES_VRAM+0x1000); /* Set PPU tables */ SetTables(); } /* Done with the mapper */ return(1);}/** Mapper #2 ************************************************//** This mapper is known as UN-NES_ROM from Nintendo. It is a **//** generic NES_ROM switch used by many games. The original **//** hardware only switched on writes to $C000-$FFFF, had **//** NES_VRAM instead of VROM, and allowed up to 8x16kB NES_ROM **//** pages. There are many variations though. **//** **//** LifeForce, Castlevania, etc. **//*************************************************************/int SelectROM2(int A,int V){ /* We are only interested in writes into $8000-$FFFF */ if(A<0x8000) return(0); /* Select NES_ROM page */ NES_Page[4]=PAGE(V); NES_Page[5]=NES_Page[4]+0x2000; /* Done with the mapper */ return(1);}/** Mapper #3 ************************************************//** This mapper is known as CN-NES_ROM from Nintendo. It is a **//** generic VROM switch used by many games. The original **//** hardware only switched on writes to $C000-$FFFF, and **//** allowed up to 4x8kB VROM pages. There are many clones **//** though, some of them use addresses as low as $4100. **//** **//** Goonies, etc. **//*************************************************************/int SelectROM3(int A,int V){ /* We are only interested in writes into $5000-$FFFF */ if(A<0x4100) return(0); /* Select VROM page */ SetVPages(0,7,VROM? VPAGE(V):NES_VRAM); SetTables(); /* Done with the mapper */ return(1);}/** Mapper #4 ************************************************//** This mapper is known as MMC3 chip from Nintendo. There **//** is also its functional analog called 5202 chip. It may **/ /** have up to 32x16kB NES_ROM and 256x1kB VROM and contains **//** hardware to generate timed IRQ signals. **//** **//** Megaman3, Megaman5, SilverSurfer, Immortal, Toki, **//** HeavyBarrel, TopGun2, MadMax, Magician, etc. **//*************************************************************/#ifdef MULTI_MAPPERSint SelectROM4(int A,int V){ register byte *P; int J, N; /* We are only interested in certain writes */ if((A&0x9FFE)!=0x8000) return(0); switch(A) { case 0xA000: /* Mirroring: .......M */ SetMirror(~V&0x01); return(1); case 0xA001: /* RAM Protect: SW...... */ return(1); case 0xC000: /* Timer Buffer: TTTTTTTT */ MM.M4.RC000=V; /* This apparently has to happen (see Gunnac) */ MM.M4.Count=V; MM.M4.Carry=0; return(1); case 0xC001: /* Timer Set and Start */ MM.M4.Count=MM.M4.RC000; MM.M4.Carry=0; return(1); case 0xE000: /* Timer IRQ Disable */ NES_CPU.IRequest=NES_INT_NONE; MM.M4.IRQ=0; return(1); case 0xE001: /* Timer IRQ Enable */ MM.M4.IRQ=1; return(1); case 0x8000: /* Mode/Pointer: CM...PPP */ /* Set NES_ROM pages */ if((MM.M4.R8000^V)&0x40) if(V&0x40) { NES_Page[4]=PAGE(ines->ROMPages-1); J=MM.M4.R[7]; NES_Page[5]=PAGE(J>>1)+(J&0x01? 0x2000:0); J=MM.M4.R[6]; NES_Page[6]=PAGE(J>>1)+(J&0x01? 0x2000:0); NES_Page[7]=NES_Page[4]+0x2000; } else { J=MM.M4.R[6]; NES_Page[4]=PAGE(J>>1)+(J&0x01? 0x2000:0); J=MM.M4.R[7]; NES_Page[5]=PAGE(J>>1)+(J&0x01? 0x2000:0); NES_Page[6]=PAGE(ines->ROMPages-1); NES_Page[7]=NES_Page [6]+0x2000; } /* Set VROM pages */ if((MM.M4.R8000^V)&0x80) { if(V&0x80) { SetVPages(0,3,NES_VRAM+0x1000);SetVPages(4,7,NES_VRAM); } else SetVPages(0,7,NES_VRAM); /* Adjust PPU tables */ SetTables(); } /* Store last value written */ MM.M4.R8000=V; return(1); case 0x8001: /* Get register number */ A=MM.M4.R8000&0x07; /* Perform NES_ROM/VROM switch */ /* Select lower VROM page */ if ( A == 0 || A == 1 ) { V&=(ines->VROMMask<<3)|0x06; if((V!=MM.M4.R[A])&&VPAGE(V>>3)) memcpy(NES_VRAM+A*0x800,VPAGE(V>>3)+(V&0x07)*0x400,0x800); } else if ( A >= 2 && A <= 5 ) { /* Select upper VROM page */ V&=(ines->VROMMask<<3)|0x07; if((V!=MM.M4.R[A])&&VPAGE(V>>3)) memcpy(NES_VRAM+(A+2)*0x400,VPAGE(V>>3)+(V&0x07)*0x400,0x400); } else if ( A == 6 || A == 7 ) { /* Select NES_ROM page */ N=(A==7)? 5:(MM.M4.R8000&0x40? 6:4); NES_Page[N]=PAGE(V>>1)+(V&0x01? 0x2000:0); } /* Store last value written */ MM.M4.R[A]=V; return(1); } /* Unknown address */ return(0);}#ifndef CD_GAME/** Mapper #5 ************************************************//** This is a Nintendo MMC5 chip. The only game where it **//** has been used appears to be Castlevania3. **//*************************************************************/int SelectROM5(int A,int V){ register int J; switch(A) { case 0x5128: case 0x5129: case 0x512A: case 0x512B: A=(A-4)&0x07; V&=(ines->VROMMask<<3)|0x07; if((V!=MM.M5.R[A])&&VPAGE(V>>3)) { memcpy(ines->VPage[A],VPAGE(V>>3)+(V&0x07)*0x0400,0x0400); MM.M5.R[A]=V; } return(1); case 0x5120: case 0x5121: case 0x5122: case 0x5123: A&=0x07; V&=(ines->VROMMask<<3)|0x07; if((V!=MM.M5.R[A])&&VPAGE(V>>3)) { memcpy(ines->VPage[A],VPAGE(V>>3)+(V&0x07)*0x0400,0x0400); MM.M5.R[A]=V; } return(1); case 0x5105: ines->VPage[8]=NES_VRAM+0x2000+(V&0x03)*0x0400; ines->VPage[9]=NES_VRAM+0x2000+((V>>2)&0x03)*0x0400; ines->VPage[10]=NES_VRAM+0x2000+((V>>4)&0x03)*0x0400; ines->VPage[11]=NES_VRAM+0x2000+(V>>6)*0x0400; return(1); case 0x5115: NES_Page[4]=PAGE(V>>1); NES_Page[5]=NES_Page[4]+0x2000; return(1); case 0x5116: case 0x5117: A-=0x5110; NES_Page[A]=PAGE(V>>1)+(V&0x01? 0x2000:0); return(1); case 0x5203: MM.M5.Count=V; return(1); case 0x5204: if(V&0x80) MM.M5.IRQ=1; else { NES_CPU.IRequest=NES_INT_NONE; MM.M5.IRQ=0; } return(1); } /* Unknown address */ return(0);}/** Mapper #6 ************************************************//** This is a mapper used by the FrontFarEast copier when **//** running trained games from the F4xxx group. **//*************************************************************/int SelectROM6(int A,int V){ register int J; if( A == 0x8000) { if(V&0x20) MM.Latch=V&0x1C; else { NES_Page[4]=PAGE(V>>2); NES_Page[5]=NES_Page[4]+0x2000; V=(V&0x03)+MM.Latch; SetVPages(0,7,VROM? VPAGE(V>>1):NES_VRAM); } return(1); } /* Unknown address */ return(0);}/** Mapper #7 ************************************************//** This mapper will satisfy WizardsAndWarriors, Solstice, **//** SuperOffRoad, and other games. It switches 32kB NES_ROM **//** at $8000. No VROM. Peculiar screen buffer switch! **//*************************************************************/int SelectROM7(int A,int V){ register int J; /* To switch NES_ROM, write should be to $8000..$FFFF */ if(A<0x8000) return(0); /* Screen buffers */ ines->VPage[8]=ines->VPage[9]=ines->VPage[10]=ines->VPage[11]=NES_VRAM+(V&0x10? 0x2400:0x2000); SetTables(); /* Switch 32kB NES_ROM at $8000 */ V<<=1; NES_Page[4]=PAGE(V); NES_Page[5]=NES_Page[4]+0x2000; V++; NES_Page[6]=PAGE(V); NES_Page[7]=NES_Page[6]+0x2000; return(1);}/** Mapper #8 ************************************************//** This is a mapper used by the FrontFarEast copier when **//** running trained games from the F3xxx group. **//*************************************************************/int SelectROM8(int A,int V){ register int J; /* We are only interested in writes into $8000-$FFFF */ if(A<0x8000) return(0); SetVPages(0,7,VROM? VPAGE(V):NES_VRAM); SetTables(); NES_Page[4]=PAGE(V>>3); NES_Page[5]=NES_Page[4]+0x2000; return(1);}/** Mapper #10 ***********************************************//** This mapper is known as MMC4. It's used in Punchout. **//*************************************************************/int SelectROM10(int A,int V){ register int J; /* We are only interested in certain writes */ if(A<0x8000) return(0); A = A&0xF000; if ( A == 0xF000 ) { SetMirror(~V&0x01); return(1); } else if ( A == 0xA000 ){ NES_Page[4]=PAGE(V>>1); return(1); } else if ( A == 0xB000 || A == 0xC000 ){ SetVPages(0,3,VROM? VPAGE(V>>1)+(V&0x01? 0x1000:0x0000):NES_VRAM); return(1); } else if ( A == 0xD000 || A == 0xE000 ) { SetVPages(4,7,VROM? VPAGE(V>>1)+(V&0x01? 0x1000:0x0000):NES_VRAM+0x1000); return(1); } /* Unknown address */ return(0);}/** Mapper #11 ***********************************************//** Mapper used by the ColorDreams and WisdomTree carts. **//** **//** FirdayFunday, Robodemons, TaginDragon, etc. **//*************************************************************/int SelectROM11(int A,int V){ if(A>0xBFFF) { NES_Page[4]=PAGE(V); NES_Page[5]=NES_Page[4]+0x2000; return(1); } if(A>0x7FFF) { SetVPages(0,7,VROM? VPAGE(V>>4):NES_VRAM); SetTables(); return(1); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -