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]);
173 void FASTAPASS(2) setprg2(uint32 A, uint32 V)
178 void FASTAPASS(3) setprg4r(int r, unsigned int A, unsigned int V)
181 setpageptr(4,A,PRGptr[r]?(&PRGptr[r][V<<12]):0,PRGram[r]);
185 void FASTAPASS(2) setprg4(uint32 A, uint32 V)
190 void FASTAPASS(3) setprg8r(int r, unsigned int A, unsigned int V)
195 setpageptr(8,A,PRGptr[r]?(&PRGptr[r][V<<13]):0,PRGram[r]);
202 setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
207 void FASTAPASS(2) setprg8(uint32 A, uint32 V)
212 void FASTAPASS(3) setprg16r(int r, unsigned int A, unsigned int V)
214 if(PRGsize[r]>=16384)
217 setpageptr(16,A,PRGptr[r]?(&PRGptr[r][V<<14]):0,PRGram[r]);
225 setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
230 void FASTAPASS(2) setprg16(uint32 A, uint32 V)
235 void FASTAPASS(3) setprg32r(int r,unsigned int A, unsigned int V)
237 if(PRGsize[r]>=32768)
240 setpageptr(32,A,PRGptr[r]?(&PRGptr[r][V<<15]):0,PRGram[r]);
248 setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
253 void FASTAPASS(2) setprg32(uint32 A, uint32 V)
258 void FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int V)
260 if(!CHRptr[r]) return;
261 FCEUPPU_LineUpdate();
264 PPUCHRRAM|=(1<<(A>>10));
266 PPUCHRRAM&=~(1<<(A>>10));
267 VPageR[(A)>>10]=&CHRptr[r][(V)<<10]-(A);
270 void FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V)
272 if(!CHRptr[r]) return;
273 FCEUPPU_LineUpdate();
275 VPageR[(A)>>10]=VPageR[((A)>>10)+1]=&CHRptr[r][(V)<<11]-(A);
277 PPUCHRRAM|=(3<<(A>>10));
279 PPUCHRRAM&=~(3<<(A>>10));
282 void FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V)
284 if(!CHRptr[r]) return;
285 FCEUPPU_LineUpdate();
287 VPageR[(A)>>10]=VPageR[((A)>>10)+1]=
288 VPageR[((A)>>10)+2]=VPageR[((A)>>10)+3]=&CHRptr[r][(V)<<12]-(A);
290 PPUCHRRAM|=(15<<(A>>10));
292 PPUCHRRAM&=~(15<<(A>>10));
295 void FASTAPASS(2) setchr8r(int r, unsigned int V)
299 if(!CHRptr[r]) return;
300 FCEUPPU_LineUpdate();
303 VPageR[x]=&CHRptr[r][V<<13];
310 void FASTAPASS(2) setchr1(unsigned int A, unsigned int V)
315 void FASTAPASS(2) setchr2(unsigned int A, unsigned int V)
320 void FASTAPASS(2) setchr4(unsigned int A, unsigned int V)
325 void FASTAPASS(1) setchr8(unsigned int V)
330 void FASTAPASS(1) setvram8(uint8 *p)
338 void FASTAPASS(2) setvram4(uint32 A, uint8 *p)
342 VPageR[(A>>10)+x]=p-A;
343 PPUCHRRAM|=(15<<(A>>10));
346 void FASTAPASS(3) setvramb1(uint8 *p, uint32 A, uint32 b)
348 FCEUPPU_LineUpdate();
349 VPageR[A>>10]=p-A+(b<<10);
350 PPUCHRRAM|=(1<<(A>>10));
353 void FASTAPASS(3) setvramb2(uint8 *p, uint32 A, uint32 b)
355 FCEUPPU_LineUpdate();
356 VPageR[(A>>10)]=VPageR[(A>>10)+1]=p-A+(b<<11);
357 PPUCHRRAM|=(3<<(A>>10));
360 void FASTAPASS(3) setvramb4(uint8 *p, uint32 A, uint32 b)
364 FCEUPPU_LineUpdate();
366 VPageR[(A>>10)+x]=p-A+(b<<12);
367 PPUCHRRAM|=(15<<(A>>10));
370 void FASTAPASS(2) setvramb8(uint8 *p, uint32 b)
374 FCEUPPU_LineUpdate();
380 /* This function can be called without calling SetupCartMirroring(). */
382 void FASTAPASS(3) setntamem(uint8 *p, int ram, uint32 b)
384 FCEUPPU_LineUpdate();
391 static int mirrorhard=0;
392 void setmirrorw(int a, int b, int c, int d)
394 FCEUPPU_LineUpdate();
395 vnapage[0]=NTARAM+a*0x400;
396 vnapage[1]=NTARAM+b*0x400;
397 vnapage[2]=NTARAM+c*0x400;
398 vnapage[3]=NTARAM+d*0x400;
401 void FASTAPASS(1) setmirror(int t)
403 FCEUPPU_LineUpdate();
409 vnapage[0]=vnapage[1]=NTARAM;vnapage[2]=vnapage[3]=NTARAM+0x400;
412 vnapage[0]=vnapage[2]=NTARAM;vnapage[1]=vnapage[3]=NTARAM+0x400;
415 vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=NTARAM;
418 vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=NTARAM+0x400;
425 void SetupCartMirroring(int m, int hard, uint8 *extra)
435 vnapage[1]=NTARAM+0x400;
437 vnapage[3]=extra+0x400;
443 static uint8 *GENIEROM=0;
445 void FixGenieMap(void);
447 /* Called when a game(file) is opened successfully. */
457 if(!(GENIEROM=(uint8 *)FCEU_malloc(4096+1024))) return;
459 fn=FCEU_MakeFName(FCEUMKF_GGROM,0,0);
464 FCEU_PrintError("Error opening Game Genie ROM image!");
469 if(fread(GENIEROM,1,16,fp)!=16)
472 FCEU_PrintError("Error reading from Game Genie ROM image!");
478 if(GENIEROM[0]==0x4E) /* iNES ROM image */
480 if(fread(GENIEROM,1,4096,fp)!=4096)
482 if(fseek(fp,16384-4096,SEEK_CUR))
484 if(fread(GENIEROM+4096,1,256,fp)!=256)
489 if(fread(GENIEROM+16,1,4352-16,fp)!=(4352-16))
494 /* Workaround for the FCE Ultra CHR page size only being 1KB */
496 memcpy(GENIEROM+4096+(x<<8),GENIEROM+4096,256);
502 /* Called when a game is closed. */
503 void CloseGenie(void)
505 /* No good reason to free() the Game Genie ROM image data. */
511 void FCEU_KillGenie(void)
520 static DECLFR(GenieRead)
522 return GENIEROM[A&4095];
525 static DECLFW(GenieWrite)
531 case 0x8004:genieval[((A-4)&0xF)>>2]=V;break;
535 case 0x8003:geniech[((A-3)&0xF)>>2]=V;break;
539 case 0x8002:genieaddr[((A-2)&0xF)>>2]&=0xFF00;genieaddr[((A-2)&0xF)>>2]|=V;break;
543 case 0x8001:genieaddr[((A-1)&0xF)>>2]&=0xFF;genieaddr[((A-1)&0xF)>>2]|=(V|0x80)<<8;break;
557 static readfunc GenieBackup[3];
559 static DECLFR(GenieFix1)
561 uint8 r=GenieBackup[0](A);
563 if((modcon>>1)&1) // No check
565 else if(r==geniech[0])
571 static DECLFR(GenieFix2)
573 uint8 r=GenieBackup[1](A);
575 if((modcon>>2)&1) // No check
577 else if(r==geniech[1])
583 static DECLFR(GenieFix3)
585 uint8 r=GenieBackup[2](A);
587 if((modcon>>3)&1) // No check
589 else if(r==geniech[2])
596 void FixGenieMap(void)
607 //printf("Rightyo\n");
609 if((modcon>>(4+x))&1)
611 readfunc tmp[3]={GenieFix1,GenieFix2,GenieFix3};
612 GenieBackup[x]=GetReadHandler(genieaddr[x]);
613 SetReadHandler(genieaddr[x],genieaddr[x],tmp[x]);
617 void GeniePower(void)
633 SetWriteHandler(0x8000,0xFFFF,GenieWrite);
634 SetReadHandler(0x8000,0xFFFF,GenieRead);
637 VPage[x]=GENIEROM+4096-0x400*x;
645 static uint8 *real_pages[16];
647 void GenieSetPages(int restore)
652 for (page=16; page<32; page++)
653 Page[page] = real_pages[page-16];
657 for (page=16; page<32; page++) {
658 real_pages[page-16] = Page[page];
659 Page[page]=GENIEROM - (page<<11) + ((page&1)<<11);
664 void FCEU_SaveGameSave(CartInfo *LocalHWInfo)
666 if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0])
671 soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
672 if((sp=FCEUD_UTF8fopen(soot,"wb"))==NULL)
674 FCEU_PrintError("WRAM file \"%s\" cannot be written to.\n",soot);
681 if(LocalHWInfo->SaveGame[x])
683 fwrite(LocalHWInfo->SaveGame[x],1,
684 LocalHWInfo->SaveGameLen[x],sp);
691 // hack, movie.c has to communicate with this function somehow
692 int disableBatteryLoading=0;
694 void FCEU_LoadGameSave(CartInfo *LocalHWInfo)
696 if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0] && !disableBatteryLoading)
701 soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
702 sp=FCEUD_UTF8fopen(soot,"rb");
707 if(LocalHWInfo->SaveGame[x])
708 fread(LocalHWInfo->SaveGame[x],1,LocalHWInfo->SaveGameLen[x],sp);