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);
458 FCEU_PrintError("Error opening Game Genie ROM image!");
463 if(fread(GENIEROM,1,16,fp)!=16)
466 FCEU_PrintError("Error reading from Game Genie ROM image!");
472 if(GENIEROM[0]==0x4E) /* iNES ROM image */
474 if(fread(GENIEROM,1,4096,fp)!=4096)
476 if(fseek(fp,16384-4096,SEEK_CUR))
478 if(fread(GENIEROM+4096,1,256,fp)!=256)
483 if(fread(GENIEROM+16,1,4352-16,fp)!=(4352-16))
488 /* Workaround for the FCE Ultra CHR page size only being 1KB */
490 memcpy(GENIEROM+4096+(x<<8),GENIEROM+4096,256);
496 /* Called when a game is closed. */
497 void CloseGenie(void)
499 /* No good reason to free() the Game Genie ROM image data. */
505 void FCEU_KillGenie(void)
514 static DECLFR(GenieRead)
516 return GENIEROM[A&4095];
519 static DECLFW(GenieWrite)
525 case 0x8004:genieval[((A-4)&0xF)>>2]=V;break;
529 case 0x8003:geniech[((A-3)&0xF)>>2]=V;break;
533 case 0x8002:genieaddr[((A-2)&0xF)>>2]&=0xFF00;genieaddr[((A-2)&0xF)>>2]|=V;break;
537 case 0x8001:genieaddr[((A-1)&0xF)>>2]&=0xFF;genieaddr[((A-1)&0xF)>>2]|=(V|0x80)<<8;break;
551 static readfunc GenieBackup[3];
553 static DECLFR(GenieFix1)
555 uint8 r=GenieBackup[0](A);
557 if((modcon>>1)&1) // No check
559 else if(r==geniech[0])
565 static DECLFR(GenieFix2)
567 uint8 r=GenieBackup[1](A);
569 if((modcon>>2)&1) // No check
571 else if(r==geniech[1])
577 static DECLFR(GenieFix3)
579 uint8 r=GenieBackup[2](A);
581 if((modcon>>3)&1) // No check
583 else if(r==geniech[2])
590 void FixGenieMap(void)
601 //printf("Rightyo\n");
603 if((modcon>>(4+x))&1)
605 readfunc tmp[3]={GenieFix1,GenieFix2,GenieFix3};
606 GenieBackup[x]=GetReadHandler(genieaddr[x]);
607 SetReadHandler(genieaddr[x],genieaddr[x],tmp[x]);
611 void GeniePower(void)
627 SetWriteHandler(0x8000,0xFFFF,GenieWrite);
628 SetReadHandler(0x8000,0xFFFF,GenieRead);
631 VPage[x]=GENIEROM+4096-0x400*x;
640 void FCEU_SaveGameSave(CartInfo *LocalHWInfo)
642 if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0])
647 soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
648 if((sp=FCEUD_UTF8fopen(soot,"wb"))==NULL)
650 FCEU_PrintError("WRAM file \"%s\" cannot be written to.\n",soot);
657 if(LocalHWInfo->SaveGame[x])
659 fwrite(LocalHWInfo->SaveGame[x],1,
660 LocalHWInfo->SaveGameLen[x],sp);
667 // hack, movie.c has to communicate with this function somehow
668 int disableBatteryLoading=0;
670 void FCEU_LoadGameSave(CartInfo *LocalHWInfo)
672 if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0] && !disableBatteryLoading)
677 soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
678 sp=FCEUD_UTF8fopen(soot,"rb");
683 if(LocalHWInfo->SaveGame[x])
684 fread(LocalHWInfo->SaveGame[x],1,LocalHWInfo->SaveGameLen[x],sp);