1 /* FCE Ultra - NES/Famicom Emulator
3 * Copyright notice for this file:
4 * Copyright (C) 2002 Ben Parnell
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <stdio.h> /* For GG loading code. */
35 This file contains all code for coordinating the mapping in of the
36 address space external to the NES.
37 It's also (ab)used by the NSF code.
40 uint8 *Page[32],*VPage[8];
43 uint8 *MMC5SPRVPage[8];
44 uint8 *MMC5BGVPage[8];
46 /* 16 are (sort of) reserved for UNIF/iNES and 16 to map other stuff. */
48 static int CHRram[32];
49 static int PRGram[32];
77 static INLINE void setpageptr(int s, uint32 A, uint8 *p)
82 for(x=(s>>1)-1;x>=0;x--)
86 static char nothing[8192];
87 void ResetCartMapping(void)
93 Page[x]=(uint8 *)(nothing-x*2048);
94 PRGptr[x]=CHRptr[x]=0;
95 PRGsize[x]=CHRsize[x]=0;
99 MMC5SPRVPage[x]=MMC5BGVPage[x]=VPageR[x]=(uint8 *)(nothing-0x400*x);
104 void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram)
109 PRGmask2[chip]=(size>>11)-1;
110 PRGmask4[chip]=(size>>12)-1;
111 PRGmask8[chip]=(size>>13)-1;
112 PRGmask16[chip]=(size>>14)-1;
113 PRGmask32[chip]=(size>>15)-1;
115 PRGram[chip]=ram?1:0;
118 void SetupCartCHRMapping(int chip, uint8 *p, uint32 size, int ram)
123 CHRmask1[chip]=(size>>10)-1;
124 CHRmask2[chip]=(size>>11)-1;
125 CHRmask4[chip]=(size>>12)-1;
126 CHRmask8[chip]=(size>>13)-1;
133 return Page[A>>11][A];
136 void FASTAPASS(3) GINLINE setprg2r(int r, unsigned int A, unsigned int V)
138 if(!PRGptr[r]) return;
141 setpageptr(2,A,(&PRGptr[r][V<<11]));
144 void FASTAPASS(2) setprg2(uint32 A, uint32 V)
149 void FASTAPASS(3) GINLINE setprg4r(int r, unsigned int A, unsigned int V)
151 if(!PRGptr[r]) return;
153 setpageptr(4,A,(&PRGptr[r][V<<12]));
156 void FASTAPASS(2) setprg4(uint32 A, uint32 V)
161 void FASTAPASS(3) GINLINE setprg8r(int r, unsigned int A, unsigned int V)
163 if(!PRGptr[r]) return;
168 setpageptr(8,A,(&PRGptr[r][V<<13]));
175 setpageptr(2,A+(x<<11),(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]));
179 void FASTAPASS(2) setprg8(uint32 A, uint32 V)
184 void FASTAPASS(3) GINLINE setprg16r(int r, unsigned int A, unsigned int V)
186 if(!PRGptr[r]) return;
188 if(PRGsize[r]>=16384)
191 setpageptr(16,A,(&PRGptr[r][V<<14]));
199 setpageptr(2,A+(x<<11),(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]));
203 void FASTAPASS(2) setprg16(uint32 A, uint32 V)
208 void FASTAPASS(3) GINLINE setprg32r(int r,unsigned int A, unsigned int V)
210 if(!PRGptr[r]) return;
211 if(PRGsize[r]>=32768)
214 setpageptr(32,A,(&PRGptr[r][V<<15]));
222 setpageptr(2,A+(x<<11),(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]));
226 void FASTAPASS(2) setprg32(uint32 A, uint32 V)
231 void GINLINE FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int V)
233 if(!CHRptr[r]) return;
236 PPUCHRRAM|=(1<<(A>>10));
238 PPUCHRRAM&=~(1<<(A>>10));
239 VPageR[(A)>>10]=&CHRptr[r][(V)<<10]-(A);
242 void GINLINE FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V)
244 if(!CHRptr[r]) return;
246 VPageR[(A)>>10]=VPageR[((A)>>10)+1]=&CHRptr[r][(V)<<11]-(A);
248 PPUCHRRAM|=(3<<(A>>10));
250 PPUCHRRAM&=~(3<<(A>>10));
253 void GINLINE FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V)
255 if(!CHRptr[r]) return;
257 VPageR[(A)>>10]=VPageR[((A)>>10)+1]=
258 VPageR[((A)>>10)+2]=VPageR[((A)>>10)+3]=&CHRptr[r][(V)<<12]-(A);
260 PPUCHRRAM|=(15<<(A>>10));
262 PPUCHRRAM&=~(15<<(A>>10));
265 void GINLINE FASTAPASS(2) setchr8r(int r, unsigned int V)
269 if(!CHRptr[r]) return;
272 VPageR[x]=&CHRptr[r][V<<13];
279 void FASTAPASS(2) setchr1(unsigned int A, unsigned int V)
284 void FASTAPASS(2) setchr2(unsigned int A, unsigned int V)
289 void FASTAPASS(2) setchr4(unsigned int A, unsigned int V)
294 void FASTAPASS(2) setchr8(unsigned int V)
299 void FASTAPASS(1) setvram8(uint8 *p)
307 void FASTAPASS(2) setvram4(uint32 A, uint8 *p)
311 VPageR[(A>>10)+x]=p-A;
312 PPUCHRRAM|=(15<<(A>>10));
315 void FASTAPASS(3) setvramb1(uint8 *p, uint32 A, uint32 b)
317 VPageR[A>>10]=p-A+(b<<10);
318 PPUCHRRAM|=(1<<(A>>10));
321 void FASTAPASS(3) setvramb2(uint8 *p, uint32 A, uint32 b)
323 VPageR[(A>>10)]=VPageR[(A>>10)+1]=p-A+(b<<11);
324 PPUCHRRAM|=(3<<(A>>10));
327 void FASTAPASS(3) setvramb4(uint8 *p, uint32 A, uint32 b)
332 VPageR[(A>>10)+x]=p-A+(b<<12);
333 PPUCHRRAM|=(15<<(A>>10));
336 void FASTAPASS(2) setvramb8(uint8 *p, uint32 b)
345 /* This function can be called without calling SetupCartMirroring(). */
347 void FASTAPASS(3) setntamem(uint8 *p, int ram, uint32 b)
355 static int mirrorhard=0;
356 void setmirrorw(int a, int b, int c, int d)
358 vnapage[0]=NTARAM+a*0x400;
359 vnapage[1]=NTARAM+b*0x400;
360 vnapage[2]=NTARAM+c*0x400;
361 vnapage[3]=NTARAM+d*0x400;
364 void FASTAPASS(1) setmirror(int t)
371 vnapage[0]=vnapage[1]=NTARAM;vnapage[2]=vnapage[3]=NTARAM+0x400;
374 vnapage[0]=vnapage[2]=NTARAM;vnapage[1]=vnapage[3]=NTARAM+0x400;
377 vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=NTARAM;
380 vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=NTARAM+0x400;
387 void SetupCartMirroring(int m, int hard, uint8 *extra)
394 vnapage[1]=NTARAM+0x400;
396 vnapage[3]=extra+0x400;
402 static uint8 *GENIEROM=0;
404 void FixGenieMap(void);
406 /* Called when a game(file) is opened successfully. */
414 if(!(GENIEROM=FCEU_malloc(4096+1024))) return;
416 if(!(fp=fopen(FCEU_MakeFName(FCEUMKF_GGROM,0,0),"rb")))
418 FCEU_PrintError("Error opening Game Genie ROM image!");
423 if(fread(GENIEROM,1,16,fp)!=16)
426 FCEU_PrintError("Error reading from Game Genie ROM image!");
432 if(GENIEROM[0]==0x4E) /* iNES ROM image */
434 if(fread(GENIEROM,1,4096,fp)!=4096)
436 if(fseek(fp,16384-4096,SEEK_CUR))
438 if(fread(GENIEROM+4096,1,256,fp)!=256)
443 if(fread(GENIEROM+16,1,4352-16,fp)!=(4352-16))
448 /* Workaround for the FCE Ultra CHR page size only being 1KB */
450 memcpy(GENIEROM+4096+(x<<8),GENIEROM+4096,256);
456 /* Called when a game is closed. */
457 void CloseGenie(void)
459 /* No good reason to free() the Game Genie ROM image data. */
465 static DECLFR(GenieRead)
467 return GENIEROM[A&4095];
470 static DECLFW(GenieWrite)
476 case 0x8004:genieval[((A-4)&0xF)>>2]=V;break;
480 case 0x8003:geniech[((A-3)&0xF)>>2]=V;break;
484 case 0x8002:genieaddr[((A-2)&0xF)>>2]&=0xFF00;genieaddr[((A-2)&0xF)>>2]|=V;break;
488 case 0x8001:genieaddr[((A-1)&0xF)>>2]&=0xFF;genieaddr[((A-1)&0xF)>>2]|=(V|0x80)<<8;break;
502 static readfunc GenieBackup[3];
504 static DECLFR(GenieFix1)
506 uint8 r=GenieBackup[0](A);
508 if((modcon>>1)&1) // No check
510 else if(r==geniech[0])
516 static DECLFR(GenieFix2)
518 uint8 r=GenieBackup[1](A);
520 if((modcon>>2)&1) // No check
522 else if(r==geniech[1])
528 static DECLFR(GenieFix3)
530 uint8 r=GenieBackup[2](A);
532 if((modcon>>3)&1) // No check
534 else if(r==geniech[2])
541 void FixGenieMap(void)
554 if((modcon>>(4+x))&1)
556 readfunc tmp[3]={GenieFix1,GenieFix2,GenieFix3};
557 GenieBackup[x]=GetReadHandler(genieaddr[x]);
558 SetReadHandler(genieaddr[x],genieaddr[x],tmp[x]);
562 void GeniePower(void)
578 SetWriteHandler(0x8000,0xFFFF,GenieWrite);
579 SetReadHandler(0x8000,0xFFFF,GenieRead);
582 VPage[x]=GENIEROM+4096-0x400*x;