c62d2810 |
1 | /* FCE Ultra - NES/Famicom Emulator |
2 | * |
3 | * Copyright notice for this file: |
d97315ac |
4 | * Copyright (C) 2002 Xodnizel |
c62d2810 |
5 | * |
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. |
10 | * |
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. |
15 | * |
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 |
19 | */ |
20 | |
21 | #include <string.h> |
22 | #include <stdlib.h> |
d97315ac |
23 | #include <stdio.h> |
c62d2810 |
24 | |
2a6855a3 |
25 | #ifdef GP2X |
26 | #include <unistd.h> // for sync() |
27 | #endif |
28 | |
c62d2810 |
29 | #include "types.h" |
c62d2810 |
30 | #include "fce.h" |
d97315ac |
31 | #include "ppu.h" |
6244011f |
32 | #include "ppu098.h" |
d97315ac |
33 | |
c62d2810 |
34 | #include "cart.h" |
35 | #include "memory.h" |
d97315ac |
36 | #include "x6502.h" |
c62d2810 |
37 | |
38 | #include "general.h" |
d97315ac |
39 | |
c62d2810 |
40 | #include "svga.h" |
d97315ac |
41 | #include "file.h" |
42 | |
937bf65b |
43 | /* |
c62d2810 |
44 | This file contains all code for coordinating the mapping in of the |
45 | address space external to the NES. |
46 | It's also (ab)used by the NSF code. |
47 | */ |
48 | |
49 | uint8 *Page[32],*VPage[8]; |
50 | uint8 **VPageR=VPage; |
51 | uint8 *VPageG[8]; |
52 | uint8 *MMC5SPRVPage[8]; |
53 | uint8 *MMC5BGVPage[8]; |
54 | |
d97315ac |
55 | static uint8 PRGIsRAM[32]; /* This page is/is not PRG RAM. */ |
c62d2810 |
56 | |
d97315ac |
57 | /* 16 are (sort of) reserved for UNIF/iNES and 16 to map other stuff. */ |
c62d2810 |
58 | static int CHRram[32]; |
59 | static int PRGram[32]; |
60 | |
61 | uint8 *PRGptr[32]; |
62 | uint8 *CHRptr[32]; |
63 | |
64 | uint32 PRGsize[32]; |
65 | uint32 CHRsize[32]; |
66 | |
67 | uint32 PRGmask2[32]; |
68 | uint32 PRGmask4[32]; |
69 | uint32 PRGmask8[32]; |
70 | uint32 PRGmask16[32]; |
71 | uint32 PRGmask32[32]; |
72 | |
73 | uint32 CHRmask1[32]; |
74 | uint32 CHRmask2[32]; |
75 | uint32 CHRmask4[32]; |
76 | uint32 CHRmask8[32]; |
77 | |
78 | int geniestage=0; |
79 | |
80 | int modcon; |
81 | |
82 | uint8 genieval[3]; |
83 | uint8 geniech[3]; |
84 | |
85 | uint32 genieaddr[3]; |
86 | |
d97315ac |
87 | static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram) |
c62d2810 |
88 | { |
89 | uint32 AB=A>>11; |
90 | int x; |
91 | |
d97315ac |
92 | if(p) |
93 | for(x=(s>>1)-1;x>=0;x--) |
94 | { |
95 | PRGIsRAM[AB+x]=ram; |
96 | Page[AB+x]=p-A; |
97 | } |
98 | else |
99 | for(x=(s>>1)-1;x>=0;x--) |
100 | { |
101 | PRGIsRAM[AB+x]=0; |
102 | Page[AB+x]=0; |
103 | } |
c62d2810 |
104 | } |
105 | |
d97315ac |
106 | static uint8 nothing[8192]; |
c62d2810 |
107 | void ResetCartMapping(void) |
108 | { |
109 | int x; |
110 | |
111 | for(x=0;x<32;x++) |
112 | { |
d97315ac |
113 | Page[x]=nothing-x*2048; |
c62d2810 |
114 | PRGptr[x]=CHRptr[x]=0; |
115 | PRGsize[x]=CHRsize[x]=0; |
116 | } |
117 | for(x=0;x<8;x++) |
118 | { |
d97315ac |
119 | MMC5SPRVPage[x]=MMC5BGVPage[x]=VPageR[x]=nothing-0x400*x; |
c62d2810 |
120 | } |
121 | |
122 | } |
123 | |
124 | void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram) |
125 | { |
126 | PRGptr[chip]=p; |
127 | PRGsize[chip]=size; |
128 | |
129 | PRGmask2[chip]=(size>>11)-1; |
130 | PRGmask4[chip]=(size>>12)-1; |
131 | PRGmask8[chip]=(size>>13)-1; |
132 | PRGmask16[chip]=(size>>14)-1; |
937bf65b |
133 | PRGmask32[chip]=(size>>15)-1; |
c62d2810 |
134 | |
135 | PRGram[chip]=ram?1:0; |
136 | } |
137 | |
138 | void SetupCartCHRMapping(int chip, uint8 *p, uint32 size, int ram) |
139 | { |
140 | CHRptr[chip]=p; |
141 | CHRsize[chip]=size; |
142 | |
143 | CHRmask1[chip]=(size>>10)-1; |
144 | CHRmask2[chip]=(size>>11)-1; |
145 | CHRmask4[chip]=(size>>12)-1; |
146 | CHRmask8[chip]=(size>>13)-1; |
147 | |
148 | CHRram[chip]=ram; |
149 | } |
150 | |
151 | DECLFR(CartBR) |
152 | { |
153 | return Page[A>>11][A]; |
154 | } |
155 | |
d97315ac |
156 | DECLFW(CartBW) |
c62d2810 |
157 | { |
d97315ac |
158 | //printf("Ok: %04x:%02x, %d\n",A,V,PRGIsRAM[A>>11]); |
159 | if(PRGIsRAM[A>>11] && Page[A>>11]) |
160 | Page[A>>11][A]=V; |
161 | } |
162 | |
163 | DECLFR(CartBROB) |
164 | { |
165 | if(!Page[A>>11]) return(X.DB); |
166 | return Page[A>>11][A]; |
167 | } |
c62d2810 |
168 | |
d97315ac |
169 | void FASTAPASS(3) setprg2r(int r, unsigned int A, unsigned int V) |
170 | { |
171 | V&=PRGmask2[r]; |
172 | setpageptr(2,A,PRGptr[r]?(&PRGptr[r][V<<11]):0,PRGram[r]); |
13624c8f |
173 | X6502_Rebase(); |
c62d2810 |
174 | } |
175 | |
176 | void FASTAPASS(2) setprg2(uint32 A, uint32 V) |
177 | { |
178 | setprg2r(0,A,V); |
179 | } |
180 | |
d97315ac |
181 | void FASTAPASS(3) setprg4r(int r, unsigned int A, unsigned int V) |
c62d2810 |
182 | { |
c62d2810 |
183 | V&=PRGmask4[r]; |
d97315ac |
184 | setpageptr(4,A,PRGptr[r]?(&PRGptr[r][V<<12]):0,PRGram[r]); |
13624c8f |
185 | X6502_Rebase(); |
c62d2810 |
186 | } |
187 | |
188 | void FASTAPASS(2) setprg4(uint32 A, uint32 V) |
189 | { |
190 | setprg4r(0,A,V); |
191 | } |
192 | |
d97315ac |
193 | void FASTAPASS(3) setprg8r(int r, unsigned int A, unsigned int V) |
c62d2810 |
194 | { |
c62d2810 |
195 | if(PRGsize[r]>=8192) |
196 | { |
197 | V&=PRGmask8[r]; |
d97315ac |
198 | setpageptr(8,A,PRGptr[r]?(&PRGptr[r][V<<13]):0,PRGram[r]); |
c62d2810 |
199 | } |
200 | else |
201 | { |
202 | uint32 VA=V<<2; |
203 | int x; |
204 | for(x=0;x<4;x++) |
d97315ac |
205 | setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]); |
c62d2810 |
206 | } |
13624c8f |
207 | X6502_Rebase(); |
c62d2810 |
208 | } |
209 | |
210 | void FASTAPASS(2) setprg8(uint32 A, uint32 V) |
211 | { |
212 | setprg8r(0,A,V); |
213 | } |
214 | |
d97315ac |
215 | void FASTAPASS(3) setprg16r(int r, unsigned int A, unsigned int V) |
c62d2810 |
216 | { |
c62d2810 |
217 | if(PRGsize[r]>=16384) |
218 | { |
219 | V&=PRGmask16[r]; |
d97315ac |
220 | setpageptr(16,A,PRGptr[r]?(&PRGptr[r][V<<14]):0,PRGram[r]); |
c62d2810 |
221 | } |
222 | else |
223 | { |
224 | uint32 VA=V<<3; |
225 | int x; |
226 | |
227 | for(x=0;x<8;x++) |
d97315ac |
228 | setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]); |
c62d2810 |
229 | } |
13624c8f |
230 | X6502_Rebase(); |
c62d2810 |
231 | } |
232 | |
233 | void FASTAPASS(2) setprg16(uint32 A, uint32 V) |
234 | { |
235 | setprg16r(0,A,V); |
236 | } |
237 | |
d97315ac |
238 | void FASTAPASS(3) setprg32r(int r,unsigned int A, unsigned int V) |
c62d2810 |
239 | { |
c62d2810 |
240 | if(PRGsize[r]>=32768) |
241 | { |
242 | V&=PRGmask32[r]; |
d97315ac |
243 | setpageptr(32,A,PRGptr[r]?(&PRGptr[r][V<<15]):0,PRGram[r]); |
c62d2810 |
244 | } |
245 | else |
246 | { |
247 | uint32 VA=V<<4; |
248 | int x; |
249 | |
250 | for(x=0;x<16;x++) |
d97315ac |
251 | setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]); |
c62d2810 |
252 | } |
13624c8f |
253 | X6502_Rebase(); |
c62d2810 |
254 | } |
255 | |
256 | void FASTAPASS(2) setprg32(uint32 A, uint32 V) |
257 | { |
258 | setprg32r(0,A,V); |
259 | } |
260 | |
d97315ac |
261 | void FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int V) |
c62d2810 |
262 | { |
263 | if(!CHRptr[r]) return; |
d97315ac |
264 | FCEUPPU_LineUpdate(); |
c62d2810 |
265 | V&=CHRmask1[r]; |
266 | if(CHRram[r]) |
267 | PPUCHRRAM|=(1<<(A>>10)); |
268 | else |
269 | PPUCHRRAM&=~(1<<(A>>10)); |
270 | VPageR[(A)>>10]=&CHRptr[r][(V)<<10]-(A); |
271 | } |
272 | |
d97315ac |
273 | void FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V) |
c62d2810 |
274 | { |
275 | if(!CHRptr[r]) return; |
d97315ac |
276 | FCEUPPU_LineUpdate(); |
c62d2810 |
277 | V&=CHRmask2[r]; |
278 | VPageR[(A)>>10]=VPageR[((A)>>10)+1]=&CHRptr[r][(V)<<11]-(A); |
279 | if(CHRram[r]) |
280 | PPUCHRRAM|=(3<<(A>>10)); |
281 | else |
282 | PPUCHRRAM&=~(3<<(A>>10)); |
283 | } |
284 | |
d97315ac |
285 | void FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V) |
c62d2810 |
286 | { |
287 | if(!CHRptr[r]) return; |
d97315ac |
288 | FCEUPPU_LineUpdate(); |
c62d2810 |
289 | V&=CHRmask4[r]; |
290 | VPageR[(A)>>10]=VPageR[((A)>>10)+1]= |
291 | VPageR[((A)>>10)+2]=VPageR[((A)>>10)+3]=&CHRptr[r][(V)<<12]-(A); |
292 | if(CHRram[r]) |
293 | PPUCHRRAM|=(15<<(A>>10)); |
294 | else |
295 | PPUCHRRAM&=~(15<<(A>>10)); |
296 | } |
297 | |
d97315ac |
298 | void FASTAPASS(2) setchr8r(int r, unsigned int V) |
c62d2810 |
299 | { |
300 | int x; |
301 | |
302 | if(!CHRptr[r]) return; |
d97315ac |
303 | FCEUPPU_LineUpdate(); |
c62d2810 |
304 | V&=CHRmask8[r]; |
305 | for(x=7;x>=0;x--) |
306 | VPageR[x]=&CHRptr[r][V<<13]; |
307 | if(CHRram[r]) |
308 | PPUCHRRAM|=(255); |
309 | else |
310 | PPUCHRRAM&=~(255); |
311 | } |
312 | |
313 | void FASTAPASS(2) setchr1(unsigned int A, unsigned int V) |
314 | { |
315 | setchr1r(0,A,V); |
316 | } |
317 | |
318 | void FASTAPASS(2) setchr2(unsigned int A, unsigned int V) |
319 | { |
320 | setchr2r(0,A,V); |
321 | } |
322 | |
323 | void FASTAPASS(2) setchr4(unsigned int A, unsigned int V) |
324 | { |
325 | setchr4r(0,A,V); |
326 | } |
327 | |
d97315ac |
328 | void FASTAPASS(1) setchr8(unsigned int V) |
c62d2810 |
329 | { |
330 | setchr8r(0,V); |
331 | } |
332 | |
333 | void FASTAPASS(1) setvram8(uint8 *p) |
334 | { |
335 | int x; |
336 | for(x=7;x>=0;x--) |
337 | VPageR[x]=p; |
338 | PPUCHRRAM|=255; |
339 | } |
340 | |
341 | void FASTAPASS(2) setvram4(uint32 A, uint8 *p) |
342 | { |
343 | int x; |
344 | for(x=3;x>=0;x--) |
345 | VPageR[(A>>10)+x]=p-A; |
346 | PPUCHRRAM|=(15<<(A>>10)); |
347 | } |
348 | |
349 | void FASTAPASS(3) setvramb1(uint8 *p, uint32 A, uint32 b) |
350 | { |
d97315ac |
351 | FCEUPPU_LineUpdate(); |
c62d2810 |
352 | VPageR[A>>10]=p-A+(b<<10); |
353 | PPUCHRRAM|=(1<<(A>>10)); |
354 | } |
355 | |
356 | void FASTAPASS(3) setvramb2(uint8 *p, uint32 A, uint32 b) |
357 | { |
d97315ac |
358 | FCEUPPU_LineUpdate(); |
c62d2810 |
359 | VPageR[(A>>10)]=VPageR[(A>>10)+1]=p-A+(b<<11); |
360 | PPUCHRRAM|=(3<<(A>>10)); |
361 | } |
362 | |
363 | void FASTAPASS(3) setvramb4(uint8 *p, uint32 A, uint32 b) |
364 | { |
365 | int x; |
366 | |
d97315ac |
367 | FCEUPPU_LineUpdate(); |
c62d2810 |
368 | for(x=3;x>=0;x--) |
369 | VPageR[(A>>10)+x]=p-A+(b<<12); |
370 | PPUCHRRAM|=(15<<(A>>10)); |
371 | } |
372 | |
373 | void FASTAPASS(2) setvramb8(uint8 *p, uint32 b) |
374 | { |
375 | int x; |
376 | |
d97315ac |
377 | FCEUPPU_LineUpdate(); |
c62d2810 |
378 | for(x=7;x>=0;x--) |
379 | VPageR[x]=p+(b<<13); |
380 | PPUCHRRAM|=255; |
381 | } |
382 | |
383 | /* This function can be called without calling SetupCartMirroring(). */ |
384 | |
385 | void FASTAPASS(3) setntamem(uint8 *p, int ram, uint32 b) |
386 | { |
d97315ac |
387 | FCEUPPU_LineUpdate(); |
c62d2810 |
388 | vnapage[b]=p; |
389 | PPUNTARAM&=~(1<<b); |
390 | if(ram) |
391 | PPUNTARAM|=1<<b; |
392 | } |
393 | |
394 | static int mirrorhard=0; |
395 | void setmirrorw(int a, int b, int c, int d) |
396 | { |
d97315ac |
397 | FCEUPPU_LineUpdate(); |
c62d2810 |
398 | vnapage[0]=NTARAM+a*0x400; |
399 | vnapage[1]=NTARAM+b*0x400; |
400 | vnapage[2]=NTARAM+c*0x400; |
401 | vnapage[3]=NTARAM+d*0x400; |
402 | } |
403 | |
404 | void FASTAPASS(1) setmirror(int t) |
405 | { |
d97315ac |
406 | FCEUPPU_LineUpdate(); |
c62d2810 |
407 | if(!mirrorhard) |
408 | { |
409 | switch(t) |
410 | { |
411 | case MI_H: |
412 | vnapage[0]=vnapage[1]=NTARAM;vnapage[2]=vnapage[3]=NTARAM+0x400; |
413 | break; |
414 | case MI_V: |
415 | vnapage[0]=vnapage[2]=NTARAM;vnapage[1]=vnapage[3]=NTARAM+0x400; |
416 | break; |
417 | case MI_0: |
418 | vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=NTARAM; |
419 | break; |
420 | case MI_1: |
421 | vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=NTARAM+0x400; |
422 | break; |
423 | } |
424 | PPUNTARAM=0xF; |
425 | } |
426 | } |
427 | |
428 | void SetupCartMirroring(int m, int hard, uint8 *extra) |
429 | { |
430 | if(m<4) |
d97315ac |
431 | { |
432 | mirrorhard = 0; |
c62d2810 |
433 | setmirror(m); |
d97315ac |
434 | } |
c62d2810 |
435 | else |
436 | { |
437 | vnapage[0]=NTARAM; |
438 | vnapage[1]=NTARAM+0x400; |
439 | vnapage[2]=extra; |
440 | vnapage[3]=extra+0x400; |
441 | PPUNTARAM=0xF; |
442 | } |
443 | mirrorhard=hard; |
444 | } |
445 | |
446 | static uint8 *GENIEROM=0; |
447 | |
448 | void FixGenieMap(void); |
449 | |
450 | /* Called when a game(file) is opened successfully. */ |
451 | void OpenGenie(void) |
452 | { |
453 | FILE *fp; |
454 | int x; |
455 | |
456 | if(!GENIEROM) |
457 | { |
d97315ac |
458 | char *fn; |
459 | |
460 | if(!(GENIEROM=(uint8 *)FCEU_malloc(4096+1024))) return; |
c62d2810 |
461 | |
d97315ac |
462 | fn=FCEU_MakeFName(FCEUMKF_GGROM,0,0); |
463 | fp=fopen(fn,"rb"); |
92764e62 |
464 | free(fn); |
d97315ac |
465 | if(!fp) |
c62d2810 |
466 | { |
467 | FCEU_PrintError("Error opening Game Genie ROM image!"); |
468 | free(GENIEROM); |
469 | GENIEROM=0; |
470 | return; |
471 | } |
472 | if(fread(GENIEROM,1,16,fp)!=16) |
473 | { |
474 | grerr: |
475 | FCEU_PrintError("Error reading from Game Genie ROM image!"); |
476 | free(GENIEROM); |
477 | GENIEROM=0; |
478 | fclose(fp); |
479 | return; |
480 | } |
d97315ac |
481 | if(GENIEROM[0]==0x4E) /* iNES ROM image */ |
c62d2810 |
482 | { |
483 | if(fread(GENIEROM,1,4096,fp)!=4096) |
484 | goto grerr; |
485 | if(fseek(fp,16384-4096,SEEK_CUR)) |
486 | goto grerr; |
487 | if(fread(GENIEROM+4096,1,256,fp)!=256) |
488 | goto grerr; |
489 | } |
490 | else |
491 | { |
492 | if(fread(GENIEROM+16,1,4352-16,fp)!=(4352-16)) |
493 | goto grerr; |
494 | } |
495 | fclose(fp); |
937bf65b |
496 | |
c62d2810 |
497 | /* Workaround for the FCE Ultra CHR page size only being 1KB */ |
498 | for(x=0;x<4;x++) |
499 | memcpy(GENIEROM+4096+(x<<8),GENIEROM+4096,256); |
500 | } |
501 | |
502 | geniestage=1; |
503 | } |
504 | |
505 | /* Called when a game is closed. */ |
506 | void CloseGenie(void) |
507 | { |
508 | /* No good reason to free() the Game Genie ROM image data. */ |
509 | geniestage=0; |
510 | FlushGenieRW(); |
511 | VPageR=VPage; |
512 | } |
513 | |
d97315ac |
514 | void FCEU_KillGenie(void) |
515 | { |
516 | if(GENIEROM) |
517 | { |
518 | free(GENIEROM); |
519 | GENIEROM=0; |
520 | } |
521 | } |
522 | |
c62d2810 |
523 | static DECLFR(GenieRead) |
524 | { |
525 | return GENIEROM[A&4095]; |
526 | } |
527 | |
528 | static DECLFW(GenieWrite) |
529 | { |
530 | switch(A) |
531 | { |
532 | case 0x800c: |
533 | case 0x8008: |
534 | case 0x8004:genieval[((A-4)&0xF)>>2]=V;break; |
535 | |
536 | case 0x800b: |
537 | case 0x8007: |
538 | case 0x8003:geniech[((A-3)&0xF)>>2]=V;break; |
539 | |
540 | case 0x800a: |
541 | case 0x8006: |
542 | case 0x8002:genieaddr[((A-2)&0xF)>>2]&=0xFF00;genieaddr[((A-2)&0xF)>>2]|=V;break; |
543 | |
544 | case 0x8009: |
545 | case 0x8005: |
546 | case 0x8001:genieaddr[((A-1)&0xF)>>2]&=0xFF;genieaddr[((A-1)&0xF)>>2]|=(V|0x80)<<8;break; |
547 | |
548 | case 0x8000:if(!V) |
d97315ac |
549 | FixGenieMap(); |
550 | else |
551 | { |
552 | modcon=V^0xFF; |
553 | if(V==0x71) |
554 | modcon=0; |
555 | } |
556 | break; |
c62d2810 |
557 | } |
558 | } |
559 | |
560 | static readfunc GenieBackup[3]; |
561 | |
562 | static DECLFR(GenieFix1) |
563 | { |
564 | uint8 r=GenieBackup[0](A); |
565 | |
d97315ac |
566 | if((modcon>>1)&1) // No check |
c62d2810 |
567 | return genieval[0]; |
568 | else if(r==geniech[0]) |
569 | return genieval[0]; |
570 | |
571 | return r; |
572 | } |
573 | |
574 | static DECLFR(GenieFix2) |
575 | { |
576 | uint8 r=GenieBackup[1](A); |
577 | |
d97315ac |
578 | if((modcon>>2)&1) // No check |
c62d2810 |
579 | return genieval[1]; |
580 | else if(r==geniech[1]) |
581 | return genieval[1]; |
582 | |
583 | return r; |
584 | } |
585 | |
586 | static DECLFR(GenieFix3) |
587 | { |
588 | uint8 r=GenieBackup[2](A); |
589 | |
d97315ac |
590 | if((modcon>>3)&1) // No check |
c62d2810 |
591 | return genieval[2]; |
592 | else if(r==geniech[2]) |
593 | return genieval[2]; |
594 | |
595 | return r; |
596 | } |
597 | |
598 | |
599 | void FixGenieMap(void) |
600 | { |
601 | int x; |
602 | |
603 | geniestage=2; |
604 | |
605 | for(x=0;x<8;x++) |
606 | VPage[x]=VPageG[x]; |
607 | |
608 | VPageR=VPage; |
609 | FlushGenieRW(); |
d97315ac |
610 | //printf("Rightyo\n"); |
c62d2810 |
611 | for(x=0;x<3;x++) |
612 | if((modcon>>(4+x))&1) |
613 | { |
614 | readfunc tmp[3]={GenieFix1,GenieFix2,GenieFix3}; |
615 | GenieBackup[x]=GetReadHandler(genieaddr[x]); |
616 | SetReadHandler(genieaddr[x],genieaddr[x],tmp[x]); |
617 | } |
618 | } |
619 | |
620 | void GeniePower(void) |
621 | { |
622 | uint32 x; |
623 | |
624 | if(!geniestage) |
625 | return; |
626 | |
627 | geniestage=1; |
628 | for(x=0;x<3;x++) |
629 | { |
630 | genieval[x]=0xFF; |
631 | geniech[x]=0xFF; |
632 | genieaddr[x]=0xFFFF; |
633 | } |
634 | modcon=0; |
635 | |
636 | SetWriteHandler(0x8000,0xFFFF,GenieWrite); |
637 | SetReadHandler(0x8000,0xFFFF,GenieRead); |
638 | |
639 | for(x=0;x<8;x++) |
640 | VPage[x]=GENIEROM+4096-0x400*x; |
641 | |
642 | if(AllocGenieRW()) |
643 | VPageR=VPageG; |
644 | else |
645 | geniestage=2; |
646 | } |
647 | |
b8da43fb |
648 | static uint8 *real_pages[16]; |
649 | |
650 | void GenieSetPages(int restore) |
651 | { |
652 | int page; |
653 | if (restore) |
654 | { |
655 | for (page=16; page<32; page++) |
656 | Page[page] = real_pages[page-16]; |
657 | } |
658 | else |
659 | { |
660 | for (page=16; page<32; page++) { |
661 | real_pages[page-16] = Page[page]; |
662 | Page[page]=GENIEROM - (page<<11) + ((page&1)<<11); |
663 | } |
664 | } |
665 | } |
c62d2810 |
666 | |
d97315ac |
667 | void FCEU_SaveGameSave(CartInfo *LocalHWInfo) |
668 | { |
669 | if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0]) |
670 | { |
671 | FILE *sp; |
672 | char *soot; |
673 | |
674 | soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav"); |
675 | if((sp=FCEUD_UTF8fopen(soot,"wb"))==NULL) |
676 | { |
677 | FCEU_PrintError("WRAM file \"%s\" cannot be written to.\n",soot); |
678 | } |
679 | else |
680 | { |
681 | int x; |
682 | |
683 | for(x=0;x<4;x++) |
684 | if(LocalHWInfo->SaveGame[x]) |
685 | { |
686 | fwrite(LocalHWInfo->SaveGame[x],1, |
687 | LocalHWInfo->SaveGameLen[x],sp); |
688 | } |
2a6855a3 |
689 | fclose(sp); |
690 | #ifdef GP2X |
691 | sync(); |
692 | #endif |
d97315ac |
693 | } |
694 | free(soot); |
695 | } |
696 | } |
697 | |
698 | // hack, movie.c has to communicate with this function somehow |
699 | int disableBatteryLoading=0; |
700 | |
701 | void FCEU_LoadGameSave(CartInfo *LocalHWInfo) |
702 | { |
703 | if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0] && !disableBatteryLoading) |
704 | { |
705 | FILE *sp; |
706 | char *soot; |
707 | |
708 | soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav"); |
709 | sp=FCEUD_UTF8fopen(soot,"rb"); |
710 | if(sp!=NULL) |
711 | { |
712 | int x; |
713 | for(x=0;x<4;x++) |
714 | if(LocalHWInfo->SaveGame[x]) |
715 | fread(LocalHWInfo->SaveGame[x],1,LocalHWInfo->SaveGameLen[x],sp); |
2a6855a3 |
716 | fclose(sp); |
d97315ac |
717 | } |
718 | free(soot); |
719 | } |
720 | } |
721 | |
e7f52878 |
722 | void DumpEmptyCartMapping(void) |
723 | { |
724 | int x, st=0, end=-1; |
725 | |
726 | for(x=8;x<32;x++) |
727 | { |
728 | if (Page[x] == (nothing-x*2048) || Page[x] == 0) |
729 | { |
730 | if (end != x) st=x; |
731 | end=x+1; |
732 | } |
733 | if (end == x) |
734 | printf("DumpEmptyCartMapping: %04x-%04x\n", st*2048, end*2048-1); |
735 | } |
736 | if (end==32) |
737 | printf("DumpEmptyCartMapping: %04x-%04x\n", st*2048, end*2048-1); |
738 | } |
739 | |
d97315ac |
740 | |