1 /* FCE Ultra - NES/Famicom Emulator
3 * Copyright notice for this file:
4 * Copyright (C) 2002 Xodnizel
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
38 #define FCEUPPU_LineUpdate(...)
41 This file contains all code for coordinating the mapping in of the
42 address space external to the NES.
43 It's also (ab)used by the NSF code.
46 uint8 *Page[32],*VPage[8];
49 uint8 *MMC5SPRVPage[8];
50 uint8 *MMC5BGVPage[8];
52 static uint8 PRGIsRAM[32]; /* This page is/is not PRG RAM. */
54 /* 16 are (sort of) reserved for UNIF/iNES and 16 to map other stuff. */
55 static int CHRram[32];
56 static int PRGram[32];
84 static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram)
90 for(x=(s>>1)-1;x>=0;x--)
96 for(x=(s>>1)-1;x>=0;x--)
103 static uint8 nothing[8192];
104 void ResetCartMapping(void)
110 Page[x]=nothing-x*2048;
111 PRGptr[x]=CHRptr[x]=0;
112 PRGsize[x]=CHRsize[x]=0;
116 MMC5SPRVPage[x]=MMC5BGVPage[x]=VPageR[x]=nothing-0x400*x;
121 void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram)
126 PRGmask2[chip]=(size>>11)-1;
127 PRGmask4[chip]=(size>>12)-1;
128 PRGmask8[chip]=(size>>13)-1;
129 PRGmask16[chip]=(size>>14)-1;
130 PRGmask32[chip]=(size>>15)-1;
132 PRGram[chip]=ram?1:0;
135 void SetupCartCHRMapping(int chip, uint8 *p, uint32 size, int ram)
140 CHRmask1[chip]=(size>>10)-1;
141 CHRmask2[chip]=(size>>11)-1;
142 CHRmask4[chip]=(size>>12)-1;
143 CHRmask8[chip]=(size>>13)-1;
150 return Page[A>>11][A];
155 //printf("Ok: %04x:%02x, %d\n",A,V,PRGIsRAM[A>>11]);
156 if(PRGIsRAM[A>>11] && Page[A>>11])
162 if(!Page[A>>11]) return(X.DB);
163 return Page[A>>11][A];
166 void FASTAPASS(3) setprg2r(int r, unsigned int A, unsigned int V)
169 setpageptr(2,A,PRGptr[r]?(&PRGptr[r][V<<11]):0,PRGram[r]);
172 void FASTAPASS(2) setprg2(uint32 A, uint32 V)
177 void FASTAPASS(3) setprg4r(int r, unsigned int A, unsigned int V)
180 setpageptr(4,A,PRGptr[r]?(&PRGptr[r][V<<12]):0,PRGram[r]);
183 void FASTAPASS(2) setprg4(uint32 A, uint32 V)
188 void FASTAPASS(3) setprg8r(int r, unsigned int A, unsigned int V)
193 setpageptr(8,A,PRGptr[r]?(&PRGptr[r][V<<13]):0,PRGram[r]);
200 setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
204 void FASTAPASS(2) setprg8(uint32 A, uint32 V)
209 void FASTAPASS(3) setprg16r(int r, unsigned int A, unsigned int V)
211 if(PRGsize[r]>=16384)
214 setpageptr(16,A,PRGptr[r]?(&PRGptr[r][V<<14]):0,PRGram[r]);
222 setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
226 void FASTAPASS(2) setprg16(uint32 A, uint32 V)
231 void FASTAPASS(3) setprg32r(int r,unsigned int A, unsigned int V)
233 if(PRGsize[r]>=32768)
236 setpageptr(32,A,PRGptr[r]?(&PRGptr[r][V<<15]):0,PRGram[r]);
244 setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
248 void FASTAPASS(2) setprg32(uint32 A, uint32 V)
253 void FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int V)
255 if(!CHRptr[r]) return;
256 FCEUPPU_LineUpdate();
259 PPUCHRRAM|=(1<<(A>>10));
261 PPUCHRRAM&=~(1<<(A>>10));
262 VPageR[(A)>>10]=&CHRptr[r][(V)<<10]-(A);
265 void FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V)
267 if(!CHRptr[r]) return;
268 FCEUPPU_LineUpdate();
270 VPageR[(A)>>10]=VPageR[((A)>>10)+1]=&CHRptr[r][(V)<<11]-(A);
272 PPUCHRRAM|=(3<<(A>>10));
274 PPUCHRRAM&=~(3<<(A>>10));
277 void FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V)
279 if(!CHRptr[r]) return;
280 FCEUPPU_LineUpdate();
282 VPageR[(A)>>10]=VPageR[((A)>>10)+1]=
283 VPageR[((A)>>10)+2]=VPageR[((A)>>10)+3]=&CHRptr[r][(V)<<12]-(A);
285 PPUCHRRAM|=(15<<(A>>10));
287 PPUCHRRAM&=~(15<<(A>>10));
290 void FASTAPASS(2) setchr8r(int r, unsigned int V)
294 if(!CHRptr[r]) return;
295 FCEUPPU_LineUpdate();
298 VPageR[x]=&CHRptr[r][V<<13];
305 void FASTAPASS(2) setchr1(unsigned int A, unsigned int V)
310 void FASTAPASS(2) setchr2(unsigned int A, unsigned int V)
315 void FASTAPASS(2) setchr4(unsigned int A, unsigned int V)
320 void FASTAPASS(1) setchr8(unsigned int V)
325 void FASTAPASS(1) setvram8(uint8 *p)
333 void FASTAPASS(2) setvram4(uint32 A, uint8 *p)
337 VPageR[(A>>10)+x]=p-A;
338 PPUCHRRAM|=(15<<(A>>10));
341 void FASTAPASS(3) setvramb1(uint8 *p, uint32 A, uint32 b)
343 FCEUPPU_LineUpdate();
344 VPageR[A>>10]=p-A+(b<<10);
345 PPUCHRRAM|=(1<<(A>>10));
348 void FASTAPASS(3) setvramb2(uint8 *p, uint32 A, uint32 b)
350 FCEUPPU_LineUpdate();
351 VPageR[(A>>10)]=VPageR[(A>>10)+1]=p-A+(b<<11);
352 PPUCHRRAM|=(3<<(A>>10));
355 void FASTAPASS(3) setvramb4(uint8 *p, uint32 A, uint32 b)
359 FCEUPPU_LineUpdate();
361 VPageR[(A>>10)+x]=p-A+(b<<12);
362 PPUCHRRAM|=(15<<(A>>10));
365 void FASTAPASS(2) setvramb8(uint8 *p, uint32 b)
369 FCEUPPU_LineUpdate();
375 /* This function can be called without calling SetupCartMirroring(). */
377 void FASTAPASS(3) setntamem(uint8 *p, int ram, uint32 b)
379 FCEUPPU_LineUpdate();
386 static int mirrorhard=0;
387 void setmirrorw(int a, int b, int c, int d)
389 FCEUPPU_LineUpdate();
390 vnapage[0]=NTARAM+a*0x400;
391 vnapage[1]=NTARAM+b*0x400;
392 vnapage[2]=NTARAM+c*0x400;
393 vnapage[3]=NTARAM+d*0x400;
396 void FASTAPASS(1) setmirror(int t)
398 FCEUPPU_LineUpdate();
404 vnapage[0]=vnapage[1]=NTARAM;vnapage[2]=vnapage[3]=NTARAM+0x400;
407 vnapage[0]=vnapage[2]=NTARAM;vnapage[1]=vnapage[3]=NTARAM+0x400;
410 vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=NTARAM;
413 vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=NTARAM+0x400;
420 void SetupCartMirroring(int m, int hard, uint8 *extra)
430 vnapage[1]=NTARAM+0x400;
432 vnapage[3]=extra+0x400;
438 static uint8 *GENIEROM=0;
440 void FixGenieMap(void);
442 /* Called when a game(file) is opened successfully. */
452 if(!(GENIEROM=(uint8 *)FCEU_malloc(4096+1024))) return;
454 fn=FCEU_MakeFName(FCEUMKF_GGROM,0,0);
459 FCEU_PrintError("Error opening Game Genie ROM image!");
464 if(fread(GENIEROM,1,16,fp)!=16)
467 FCEU_PrintError("Error reading from Game Genie ROM image!");
473 if(GENIEROM[0]==0x4E) /* iNES ROM image */
475 if(fread(GENIEROM,1,4096,fp)!=4096)
477 if(fseek(fp,16384-4096,SEEK_CUR))
479 if(fread(GENIEROM+4096,1,256,fp)!=256)
484 if(fread(GENIEROM+16,1,4352-16,fp)!=(4352-16))
489 /* Workaround for the FCE Ultra CHR page size only being 1KB */
491 memcpy(GENIEROM+4096+(x<<8),GENIEROM+4096,256);
497 /* Called when a game is closed. */
498 void CloseGenie(void)
500 /* No good reason to free() the Game Genie ROM image data. */
506 void FCEU_KillGenie(void)
515 static DECLFR(GenieRead)
517 return GENIEROM[A&4095];
520 static DECLFW(GenieWrite)
526 case 0x8004:genieval[((A-4)&0xF)>>2]=V;break;
530 case 0x8003:geniech[((A-3)&0xF)>>2]=V;break;
534 case 0x8002:genieaddr[((A-2)&0xF)>>2]&=0xFF00;genieaddr[((A-2)&0xF)>>2]|=V;break;
538 case 0x8001:genieaddr[((A-1)&0xF)>>2]&=0xFF;genieaddr[((A-1)&0xF)>>2]|=(V|0x80)<<8;break;
552 static readfunc GenieBackup[3];
554 static DECLFR(GenieFix1)
556 uint8 r=GenieBackup[0](A);
558 if((modcon>>1)&1) // No check
560 else if(r==geniech[0])
566 static DECLFR(GenieFix2)
568 uint8 r=GenieBackup[1](A);
570 if((modcon>>2)&1) // No check
572 else if(r==geniech[1])
578 static DECLFR(GenieFix3)
580 uint8 r=GenieBackup[2](A);
582 if((modcon>>3)&1) // No check
584 else if(r==geniech[2])
591 void FixGenieMap(void)
602 //printf("Rightyo\n");
604 if((modcon>>(4+x))&1)
606 readfunc tmp[3]={GenieFix1,GenieFix2,GenieFix3};
607 GenieBackup[x]=GetReadHandler(genieaddr[x]);
608 SetReadHandler(genieaddr[x],genieaddr[x],tmp[x]);
612 void GeniePower(void)
628 SetWriteHandler(0x8000,0xFFFF,GenieWrite);
629 SetReadHandler(0x8000,0xFFFF,GenieRead);
632 VPage[x]=GENIEROM+4096-0x400*x;
641 void FCEU_SaveGameSave(CartInfo *LocalHWInfo)
643 if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0])
648 soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
649 if((sp=FCEUD_UTF8fopen(soot,"wb"))==NULL)
651 FCEU_PrintError("WRAM file \"%s\" cannot be written to.\n",soot);
658 if(LocalHWInfo->SaveGame[x])
660 fwrite(LocalHWInfo->SaveGame[x],1,
661 LocalHWInfo->SaveGameLen[x],sp);
668 // hack, movie.c has to communicate with this function somehow
669 int disableBatteryLoading=0;
671 void FCEU_LoadGameSave(CartInfo *LocalHWInfo)
673 if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0] && !disableBatteryLoading)
678 soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
679 sp=FCEUD_UTF8fopen(soot,"rb");
684 if(LocalHWInfo->SaveGame[x])
685 fread(LocalHWInfo->SaveGame[x],1,LocalHWInfo->SaveGameLen[x],sp);