1 /***********************************************************************************
2 Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
4 (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com),
5 Jerremy Koot (jkoot@snes9x.com)
6
7 (c) Copyright 2002 - 2004 Matthew Kendora
8
9 (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org)
10
11 (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/)
12
13 (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net)
14
15 (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca),
16 Kris Bleakley (codeviolation@hotmail.com)
17
18 (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
19 Nach (n-a-c-h@users.sourceforge.net),
20 zones (kasumitokoduck@yahoo.com)
21
22 (c) Copyright 2006 - 2007 nitsuja
23
24 (c) Copyright 2009 - 2010 BearOso,
25 OV2
26
27
28 BS-X C emulator code
29 (c) Copyright 2005 - 2006 Dreamer Nom,
30 zones
31
32 C4 x86 assembler and some C emulation code
33 (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com),
34 Nach,
35 zsKnight (zsknight@zsnes.com)
36
37 C4 C++ code
38 (c) Copyright 2003 - 2006 Brad Jorsch,
39 Nach
40
41 DSP-1 emulator code
42 (c) Copyright 1998 - 2006 _Demo_,
43 Andreas Naive (andreasnaive@gmail.com),
44 Gary Henderson,
45 Ivar (ivar@snes9x.com),
46 John Weidman,
47 Kris Bleakley,
48 Matthew Kendora,
49 Nach,
50 neviksti (neviksti@hotmail.com)
51
52 DSP-2 emulator code
53 (c) Copyright 2003 John Weidman,
54 Kris Bleakley,
55 Lord Nightmare (lord_nightmare@users.sourceforge.net),
56 Matthew Kendora,
57 neviksti
58
59 DSP-3 emulator code
60 (c) Copyright 2003 - 2006 John Weidman,
61 Kris Bleakley,
62 Lancer,
63 z80 gaiden
64
65 DSP-4 emulator code
66 (c) Copyright 2004 - 2006 Dreamer Nom,
67 John Weidman,
68 Kris Bleakley,
69 Nach,
70 z80 gaiden
71
72 OBC1 emulator code
73 (c) Copyright 2001 - 2004 zsKnight,
74 pagefault (pagefault@zsnes.com),
75 Kris Bleakley
76 Ported from x86 assembler to C by sanmaiwashi
77
78 SPC7110 and RTC C++ emulator code used in 1.39-1.51
79 (c) Copyright 2002 Matthew Kendora with research by
80 zsKnight,
81 John Weidman,
82 Dark Force
83
84 SPC7110 and RTC C++ emulator code used in 1.52+
85 (c) Copyright 2009 byuu,
86 neviksti
87
88 S-DD1 C emulator code
89 (c) Copyright 2003 Brad Jorsch with research by
90 Andreas Naive,
91 John Weidman
92
93 S-RTC C emulator code
94 (c) Copyright 2001 - 2006 byuu,
95 John Weidman
96
97 ST010 C++ emulator code
98 (c) Copyright 2003 Feather,
99 John Weidman,
100 Kris Bleakley,
101 Matthew Kendora
102
103 Super FX x86 assembler emulator code
104 (c) Copyright 1998 - 2003 _Demo_,
105 pagefault,
106 zsKnight
107
108 Super FX C emulator code
109 (c) Copyright 1997 - 1999 Ivar,
110 Gary Henderson,
111 John Weidman
112
113 Sound emulator code used in 1.5-1.51
114 (c) Copyright 1998 - 2003 Brad Martin
115 (c) Copyright 1998 - 2006 Charles Bilyue'
116
117 Sound emulator code used in 1.52+
118 (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
119
120 SH assembler code partly based on x86 assembler code
121 (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
122
123 2xSaI filter
124 (c) Copyright 1999 - 2001 Derek Liauw Kie Fa
125
126 HQ2x, HQ3x, HQ4x filters
127 (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com)
128
129 NTSC filter
130 (c) Copyright 2006 - 2007 Shay Green
131
132 GTK+ GUI code
133 (c) Copyright 2004 - 2010 BearOso
134
135 Win32 GUI code
136 (c) Copyright 2003 - 2006 blip,
137 funkyass,
138 Matthew Kendora,
139 Nach,
140 nitsuja
141 (c) Copyright 2009 - 2010 OV2
142
143 Mac OS GUI code
144 (c) Copyright 1998 - 2001 John Stiles
145 (c) Copyright 2001 - 2010 zones
146
147 (c) Copyright 2010 - 2016 Daniel De Matteis. (UNDER NO CIRCUMSTANCE
148 WILL COMMERCIAL RIGHTS EVER BE APPROPRIATED TO ANY PARTY)
149
150 Specific ports contains the works of other authors. See headers in
151 individual files.
152
153
154 Snes9x homepage: http://www.snes9x.com/
155
156 Permission to use, copy, modify and/or distribute Snes9x in both binary
157 and source form, for non-commercial purposes, is hereby granted without
158 fee, providing that this license information and copyright notice appear
159 with all copies and any derived work.
160
161 This software is provided 'as-is', without any express or implied
162 warranty. In no event shall the authors be held liable for any damages
163 arising from the use of this software or it's derivatives.
164
165 Snes9x is freeware for PERSONAL USE only. Commercial users should
166 seek permission of the copyright holders first. Commercial use includes,
167 but is not limited to, charging money for Snes9x or software derived from
168 Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
169 using Snes9x as a promotion for your commercial product.
170
171 The copyright holders request that bug fixes and improvements to the code
172 should be forwarded to them so everyone can benefit from the modifications
173 in future versions.
174
175 Super NES and Super Nintendo Entertainment System are trademarks of
176 Nintendo Co., Limited and its subsidiary companies.
177 ***********************************************************************************/
178
179 /* Dreamer Nom wrote:
180 Large thanks to John Weidman for all his initial research
181 Thanks to Seph3 for his modem notes */
182
183 #include <stddef.h>
184 #include <string.h>
185 #include <time.h>
186
187 #include "snes9x.h"
188 #include "memmap.h"
189 #include "bsx.h"
190 #include "display.h"
191
192 #include <streams/file_stream.h>
193
194 extern uint8 OpenBus;
195
196 #define BIOS_SIZE 0x100000
197 #define FLASH_SIZE 0x200000
198 #define PSRAM_SIZE 0x80000
199
200 #define BSXPPUBASE 0x2180
201
202 struct SBSX_RTC
203 {
204 int hours;
205 int minutes;
206 int seconds;
207 int ticks;
208 };
209
210 static struct SBSX_RTC BSX_RTC;
211
212 /* flash card vendor information */
213
214 static const uint8 flashcard[20] =
215 {
216 0x4D, 0x00, 0x50, 0x00, /* vendor id */
217 0x00, 0x00, /* ? */
218 0x2B, 0x00, /* 2MB Flash (1MB = 0x2A) */
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
221 };
222
223 static const uint8 init2192[32] = /* FIXME */
224 {
225 00, 00, 00, 00, 00, /* unknown */
226 01, 01, 00, 00, 00,
227 00, /* seconds (?) */
228 00, /* minutes */
229 00, /* hours */
230 10, 10, 10, 10, 10, /* unknown */
231 10, 10, 10, 10, 10, /* dummy */
232 00, 00, 00, 00, 00, 00, 00, 00, 00
233 };
234
235 static bool8 FlashMode;
236 static uint32 FlashSize;
237 static uint8 *MapROM, *FlashROM;
238
BSX_Map_SNES(void)239 static void BSX_Map_SNES (void)
240 {
241 /* These maps will be partially overwritten */
242
243 int c;
244
245 /* Banks 00->3F and 80->BF */
246 for (c = 0; c < 0x400; c += 16)
247 {
248 Memory.Map[c + 0] = Memory.Map[c + 0x800] = Memory.RAM;
249 Memory.Map[c + 1] = Memory.Map[c + 0x801] = Memory.RAM;
250 Memory.BlockIsRAM[c + 0] = Memory.BlockIsRAM[c + 0x800] = TRUE;
251 Memory.BlockIsRAM[c + 1] = Memory.BlockIsRAM[c + 0x801] = TRUE;
252
253 Memory.Map[c + 2] = Memory.Map[c + 0x802] = (uint8 *) MAP_PPU;
254 Memory.Map[c + 3] = Memory.Map[c + 0x803] = (uint8 *) MAP_PPU;
255 Memory.Map[c + 4] = Memory.Map[c + 0x804] = (uint8 *) MAP_CPU;
256 Memory.Map[c + 5] = Memory.Map[c + 0x805] = (uint8 *) MAP_CPU;
257 Memory.Map[c + 6] = Memory.Map[c + 0x806] = (uint8 *) MAP_NONE;
258 Memory.Map[c + 7] = Memory.Map[c + 0x807] = (uint8 *) MAP_NONE;
259 }
260 }
261
BSX_Map_LoROM(void)262 static void BSX_Map_LoROM (void)
263 {
264 /* These maps will be partially overwritten */
265
266 int i, c;
267
268 /* Banks 00->3F and 80->BF */
269 for (c = 0; c < 0x400; c += 16)
270 {
271 for (i = c + 8; i < c + 16; i++)
272 {
273 Memory.Map[i] = Memory.Map[i + 0x800] = &MapROM[(c << 11) % FlashSize] - 0x8000;
274 Memory.BlockIsRAM[i] = Memory.BlockIsRAM[i + 0x800] = BSX.write_enable;
275 Memory.BlockIsROM[i] = Memory.BlockIsROM[i + 0x800] = !BSX.write_enable;
276 }
277 }
278
279 /* Banks 40->7F and C0->FF */
280 for (c = 0; c < 0x400; c += 16)
281 {
282 for (i = c; i < c + 8; i++)
283 Memory.Map[i + 0x400] = Memory.Map[i + 0xC00] = &MapROM[(c << 11) % FlashSize];
284
285 for (i = c + 8; i < c + 16; i++)
286 Memory.Map[i + 0x400] = Memory.Map[i + 0xC00] = &MapROM[(c << 11) % FlashSize] - 0x8000;
287
288 for (i = c; i < c + 16; i++)
289 {
290 Memory.BlockIsRAM[i + 0x400] = Memory.BlockIsRAM[i + 0xC00] = BSX.write_enable;
291 Memory.BlockIsROM[i + 0x400] = Memory.BlockIsROM[i + 0xC00] = !BSX.write_enable;
292 }
293 }
294 }
295
BSX_Map_HiROM(void)296 static void BSX_Map_HiROM (void)
297 {
298 /* These maps will be partially overwritten */
299
300 int i, c;
301
302 /* Banks 00->3F and 80->BF */
303 for (c = 0; c < 0x400; c += 16)
304 {
305 for (i = c + 8; i < c + 16; i++)
306 {
307 Memory.Map[i] = Memory.Map[i + 0x800] = &MapROM[(c << 12) % FlashSize];
308 Memory.BlockIsRAM[i] = Memory.BlockIsRAM[i + 0x800] = BSX.write_enable;
309 Memory.BlockIsROM[i] = Memory.BlockIsROM[i + 0x800] = !BSX.write_enable;
310 }
311 }
312
313 /* Banks 40->7F and C0->FF */
314 for (c = 0; c < 0x400; c += 16)
315 {
316 for (i = c; i < c + 16; i++)
317 {
318 Memory.Map[i + 0x400] = Memory.Map[i + 0xC00] = &MapROM[(c << 12) % FlashSize];
319 Memory.BlockIsRAM[i + 0x400] = Memory.BlockIsRAM[i + 0xC00] = BSX.write_enable;
320 Memory.BlockIsROM[i + 0x400] = Memory.BlockIsROM[i + 0xC00] = !BSX.write_enable;
321 }
322 }
323 }
324
BSX_Map_MMC(void)325 static void BSX_Map_MMC (void)
326 {
327 int c;
328
329 /* Banks 01->0E:5000-5FFF */
330 for (c = 0x010; c < 0x0F0; c += 16)
331 {
332 Memory.Map[c + 5] = (uint8 *) MAP_BSX;
333 Memory.BlockIsRAM[c + 5] = Memory.BlockIsROM[c + 5] = FALSE;
334 }
335 }
336
BSX_Map_FlashIO(void)337 static void BSX_Map_FlashIO (void)
338 {
339 int c;
340
341 if (BSX.MMC[0x0C] || BSX.MMC[0x0D])
342 {
343 /* Bank C0:0000, 2AAA, 5555, FF00-FF1F */
344 for (c = 0; c < 16; c++)
345 {
346 Memory.Map[c + 0xC00] = (uint8 *) MAP_BSX;
347 Memory.BlockIsRAM[c + 0xC00] = TRUE;
348 Memory.BlockIsROM[c + 0xC00] = FALSE;
349 }
350 }
351 }
352
BSX_Map_SRAM(void)353 static void BSX_Map_SRAM (void)
354 {
355 int c;
356
357 /* Banks 10->17:5000-5FFF */
358 for (c = 0x100; c < 0x180; c += 16)
359 {
360 Memory.Map[c + 5] = (uint8 *) Memory.SRAM + ((c & 0x70) << 8) - 0x5000;
361 Memory.BlockIsRAM[c + 5] = TRUE;
362 Memory.BlockIsROM[c + 5] = FALSE;
363 }
364 }
365
map_psram_mirror_sub(uint32 bank)366 static void map_psram_mirror_sub (uint32 bank)
367 {
368 int i, c;
369
370 bank <<= 4;
371
372 if (BSX.MMC[0x02])
373 {
374 for (c = 0; c < 0x100; c += 16)
375 {
376 for (i = c; i < c + 16; i++)
377 {
378 Memory.Map[i + bank] = &Memory.BSRAM[(c << 12) % PSRAM_SIZE];
379 Memory.BlockIsRAM[i + bank] = TRUE;
380 Memory.BlockIsROM[i + bank] = FALSE;
381 }
382 }
383 }
384 else
385 {
386 for (c = 0; c < 0x100; c += 16)
387 {
388 for (i = c; i < c + 8; i++)
389 Memory.Map[i + bank] = &Memory.BSRAM[(c << 11) % PSRAM_SIZE];
390
391 for (i = c + 8; i < c + 16; i++)
392 Memory.Map[i + bank] = &Memory.BSRAM[(c << 11) % PSRAM_SIZE] - 0x8000;
393
394 for (i = c; i < c + 16; i++)
395 {
396 Memory.BlockIsRAM[i + bank] = TRUE;
397 Memory.BlockIsROM[i + bank] = FALSE;
398 }
399 }
400 }
401 }
402
BSX_Map_PSRAM(void)403 static void BSX_Map_PSRAM (void)
404 {
405 int c;
406
407 /* Banks 70->77:0000-FFFF */
408 /* FIXME: could be toggled by $03 */
409 for (c = 0; c < 0x80; c++)
410 {
411 Memory.Map[c + 0x700] = &Memory.BSRAM[((c & 0x70) << 12) % PSRAM_SIZE];
412 Memory.BlockIsRAM[c + 0x700] = TRUE;
413 Memory.BlockIsROM[c + 0x700] = FALSE;
414 }
415
416 /* Banks 20->3F:6000-7FFF mirrors 70->77:6000-7FFF */
417 for (c = 0x200; c < 0x400; c += 16)
418 {
419 Memory.Map[c + 6] = &Memory.BSRAM[((c & 0x70) << 12) % PSRAM_SIZE];
420 Memory.Map[c + 7] = &Memory.BSRAM[((c & 0x70) << 12) % PSRAM_SIZE];
421 Memory.BlockIsRAM[c + 6] = TRUE;
422 Memory.BlockIsRAM[c + 7] = TRUE;
423 Memory.BlockIsROM[c + 6] = FALSE;
424 Memory.BlockIsROM[c + 7] = FALSE;
425 }
426
427 if (!BSX.MMC[0x05])
428 /* Banks 40->4F:0000-FFFF mirrors 70->77:0000-7FFF */
429 map_psram_mirror_sub(0x40);
430
431 if (!BSX.MMC[0x06])
432 /* Banks 50->5F:0000-FFFF mirrors 70->77:0000-7FFF */
433 map_psram_mirror_sub(0x50);
434
435 /* FIXME */
436 if (!BSX.MMC[0x03])
437 /* Banks 60->6F:0000-FFFF mirrors 70->77:0000-7FFF (?) */
438 map_psram_mirror_sub(0x60);
439 }
440
BSX_Map_BIOS(void)441 static void BSX_Map_BIOS (void)
442 {
443 int i,c;
444
445 /* Banks 00->1F:8000-FFFF */
446 if (BSX.MMC[0x07])
447 {
448 for (c = 0; c < 0x200; c += 16)
449 {
450 for (i = c + 8; i < c + 16; i++)
451 {
452 Memory.Map[i] = &Memory.BIOSROM[(c << 11) % BIOS_SIZE] - 0x8000;
453 Memory.BlockIsRAM[i] = FALSE;
454 Memory.BlockIsROM[i] = TRUE;
455 }
456 }
457 }
458
459 /* Banks 80->9F:8000-FFFF */
460 if (BSX.MMC[0x08])
461 {
462 for (c = 0; c < 0x200; c += 16)
463 {
464 for (i = c + 8; i < c + 16; i++)
465 {
466 Memory.Map[i + 0x800] = &Memory.BIOSROM[(c << 11) % BIOS_SIZE] - 0x8000;
467 Memory.BlockIsRAM[i + 0x800] = FALSE;
468 Memory.BlockIsROM[i + 0x800] = TRUE;
469 }
470 }
471 }
472 }
473
BSX_Map_RAM(void)474 static void BSX_Map_RAM (void)
475 {
476 int c;
477
478 /* Banks 7E->7F */
479 for (c = 0; c < 16; c++)
480 {
481 Memory.Map[c + 0x7E0] = Memory.RAM;
482 Memory.Map[c + 0x7F0] = Memory.RAM + 0x10000;
483 Memory.BlockIsRAM[c + 0x7E0] = TRUE;
484 Memory.BlockIsRAM[c + 0x7F0] = TRUE;
485 Memory.BlockIsROM[c + 0x7E0] = FALSE;
486 Memory.BlockIsROM[c + 0x7F0] = FALSE;
487 }
488 }
489
BSX_Map_Dirty(void)490 static void BSX_Map_Dirty (void)
491 {
492 /* for the quick bank change */
493
494 int i, c;
495
496 /* Banks 00->1F and 80->9F:8000-FFFF */
497 if (BSX.MMC[0x02])
498 {
499 for (c = 0; c < 0x200; c += 16)
500 {
501 for (i = c + 8; i < c + 16; i++)
502 {
503 Memory.Map[i] = Memory.Map[i + 0x800] = &MapROM[(c << 12) % FlashSize];
504 Memory.BlockIsRAM[i] = Memory.BlockIsRAM[i + 0x800] = BSX.write_enable;
505 Memory.BlockIsROM[i] = Memory.BlockIsROM[i + 0x800] = !BSX.write_enable;
506 }
507 }
508 }
509 else
510 {
511 for (c = 0; c < 0x200; c += 16)
512 {
513 for (i = c + 8; i < c + 16; i++)
514 {
515 Memory.Map[i] = Memory.Map[i + 0x800] = &MapROM[(c << 11) % FlashSize] - 0x8000;
516 Memory.BlockIsRAM[i] = Memory.BlockIsRAM[i + 0x800] = BSX.write_enable;
517 Memory.BlockIsROM[i] = Memory.BlockIsROM[i + 0x800] = !BSX.write_enable;
518 }
519 }
520 }
521 }
522
BSX_Map(void)523 static void BSX_Map (void)
524 {
525 memcpy(BSX.prevMMC, BSX.MMC, sizeof(BSX.MMC));
526
527 /* Do a quick bank change */
528 if (BSX.dirty2 && !BSX.dirty)
529 {
530 BSX_Map_Dirty();
531 BSX_Map_BIOS();
532
533 BSX.dirty2 = FALSE;
534
535 map_WriteProtectROM();
536 return;
537 }
538
539 if (BSX.MMC[0x01])
540 {
541 MapROM = Memory.BSRAM;
542 FlashSize = PSRAM_SIZE;
543 }
544 else
545 {
546 MapROM = FlashROM;
547 FlashSize = FLASH_SIZE;
548 }
549
550 BSX_Map_SNES();
551
552 if (BSX.MMC[0x02])
553 BSX_Map_HiROM();
554 else
555 BSX_Map_LoROM();
556
557 BSX_Map_PSRAM();
558 BSX_Map_SRAM();
559 BSX_Map_RAM();
560
561 BSX_Map_BIOS();
562 BSX_Map_FlashIO();
563 BSX_Map_MMC();
564
565 /* Monitor new register changes */
566 BSX.dirty = FALSE;
567 BSX.dirty2 = FALSE;
568
569 map_WriteProtectROM();
570 }
571
BSX_Get_Bypass_FlashIO(uint16 offset)572 static uint8 BSX_Get_Bypass_FlashIO (uint16 offset)
573 {
574 if (BSX.MMC[0x02])
575 return (MapROM[offset]);
576 else
577 {
578 if (offset < 0x8000)
579 return (MapROM[offset]);
580 else
581 return (MapROM[offset - 0x8000]);
582 }
583 }
584
BSX_Set_Bypass_FlashIO(uint16 offset,uint8 byte)585 static void BSX_Set_Bypass_FlashIO (uint16 offset, uint8 byte)
586 {
587 if (BSX.MMC[0x02])
588 MapROM[offset] = byte;
589 else
590 {
591 if (offset < 0x8000)
592 MapROM[offset] = byte;
593 else
594 MapROM[offset - 0x8000] = byte;
595 }
596 }
597
S9xGetBSX(uint32 address)598 uint8 S9xGetBSX (uint32 address)
599 {
600 uint8 bank = (address >> 16) & 0xFF;
601 uint16 offset = address & 0xFFFF;
602 uint8 t = 0;
603
604 /* MMC */
605 if ((bank >= 0x01 && bank <= 0x0E) && (offset == 0x5000))
606 return (BSX.MMC[bank]);
607
608 /* Flash IO */
609 if (bank == 0xC0)
610 {
611 /* default: read-through mode */
612 t = BSX_Get_Bypass_FlashIO(offset);
613
614 /* note: may be more registers, purposes unknown */
615 switch (offset)
616 {
617 case 0x0002:
618 if (BSX.flash_enable)
619 t = 0x80; /* status register? */
620 break;
621
622 case 0x5555:
623 if (BSX.flash_enable)
624 t = 0x80; /* ??? */
625 break;
626
627 case 0xFF00:
628 case 0xFF02:
629 case 0xFF04:
630 case 0xFF06:
631 case 0xFF08:
632 case 0xFF0A:
633 case 0xFF0C:
634 case 0xFF0E:
635 case 0xFF10:
636 case 0xFF12:
637 /* return flash vendor information */
638 if (BSX.read_enable)
639 t = flashcard[offset - 0xFF00];
640 break;
641 }
642 }
643
644 return (t);
645 }
646
S9xSetBSX(uint8 byte,uint32 address)647 void S9xSetBSX (uint8 byte, uint32 address)
648 {
649 uint8 bank = (address >> 16) & 0xFF;
650 uint16 offset = address & 0xFFFF;
651
652 /* MMC */
653 if ((bank >= 0x01 && bank <= 0x0E) && (offset == 0x5000))
654 {
655 switch (bank)
656 {
657 case 0x01:
658 case 0x02:
659 case 0x03:
660 case 0x04:
661 case 0x05:
662 case 0x06:
663 case 0x09:
664 case 0x0A:
665 case 0x0B:
666 case 0x0C:
667 case 0x0D:
668 if (BSX.MMC[bank] != byte)
669 {
670 BSX.MMC[bank] = byte;
671 BSX.dirty = TRUE;
672 }
673 break;
674
675 case 0x07:
676 case 0x08:
677 if (BSX.MMC[bank] != byte)
678 {
679 BSX.MMC[bank] = byte;
680 BSX.dirty2 = TRUE;
681 }
682 break;
683
684 case 0x0E:
685 BSX.MMC[bank] = byte;
686 if (byte && (BSX.dirty || BSX.dirty2))
687 BSX_Map();
688 break;
689 }
690 }
691
692 /* Flash IO */
693 if (bank == 0xC0)
694 {
695 BSX.old_write = BSX.new_write;
696 BSX.new_write = address;
697
698 /* ???: double writes to the desired address will bypass
699 flash registers */
700 if (BSX.old_write == BSX.new_write && BSX.write_enable)
701 {
702 BSX_Set_Bypass_FlashIO(offset, byte);
703 return;
704 }
705
706 /* flash command handling
707 NOTE: incomplete */
708 switch (offset)
709 {
710 case 0x0000:
711 BSX.flash_command <<= 8;
712 BSX.flash_command |= byte;
713 if ((BSX.flash_command & 0xFFFF) == 0x38D0)
714 {
715 /* retrieve information about the flash card */
716 BSX.flash_enable = TRUE;
717 BSX.read_enable = TRUE;
718 }
719 break;
720
721 case 0x2AAA:
722 BSX.flash_command <<= 8;
723 BSX.flash_command |= byte;
724 break;
725
726 case 0x5555:
727 BSX.flash_command <<= 8;
728 BSX.flash_command |= byte;
729
730 switch (BSX.flash_command & 0xFFFFFF)
731 {
732 case 0xAA55F0:
733 /* turn off flash i/o */
734 BSX.flash_enable = FALSE;
735 BSX.write_enable = FALSE;
736 BSX.read_enable = FALSE;
737 break;
738
739 case 0xAA55A0:
740 /* enable writing to flash */
741 BSX.old_write = 0;
742 BSX.new_write = 0;
743 BSX.flash_enable = TRUE;
744 BSX.write_enable = TRUE;
745 BSX_Map();
746 break;
747
748 case 0xAA5570:
749 /* turn on write-protection */
750 BSX.write_enable = FALSE;
751 BSX_Map();
752 break;
753
754 case 0xAA5580:
755 case 0xAA5510:
756 /* ??? */
757 break;
758 }
759
760 break;
761 }
762 }
763 }
764
S9xGetBSXPPU(uint16 address)765 uint8 S9xGetBSXPPU (uint16 address)
766 {
767 uint8 t;
768
769 /* known read registers */
770 switch (address)
771 {
772 /* Test register low? (r/w) */
773 case 0x2188:
774 t = BSX.PPU[0x2188 - BSXPPUBASE];
775 break;
776
777 /* Test register high? (r/w) */
778 case 0x2189:
779 t = BSX.PPU[0x2189 - BSXPPUBASE];
780 break;
781
782 case 0x218A:
783 t = BSX.PPU[0x218A - BSXPPUBASE];
784 break;
785
786 case 0x218C:
787 t = BSX.PPU[0x218C - BSXPPUBASE];
788 break;
789
790 /* Transmission number low? (r/w) */
791 case 0x218E:
792 t = BSX.PPU[0x218E - BSXPPUBASE];
793 break;
794
795 /* Transmission number high? (r/w) */
796 case 0x218F:
797 t = BSX.PPU[0x218F - BSXPPUBASE];
798 break;
799
800 /* Status register? (r) */
801 case 0x2190:
802 t = BSX.PPU[0x2190 - BSXPPUBASE];
803 break;
804
805 /* Data register? (r/w) */
806 case 0x2192:
807 t = BSX.PPU[0x2192 - BSXPPUBASE];
808
809 /* test */
810 t = BSX.test2192[BSX.out_index++];
811 if (BSX.out_index == 32)
812 BSX.out_index = 0;
813
814 BSX_RTC.ticks++;
815 if (BSX_RTC.ticks >= 1000)
816 {
817 BSX_RTC.ticks = 0;
818 BSX_RTC.seconds++;
819 }
820 if (BSX_RTC.seconds >= 60)
821 {
822 BSX_RTC.seconds = 0;
823 BSX_RTC.minutes++;
824 }
825 if (BSX_RTC.minutes >= 60)
826 {
827 BSX_RTC.minutes = 0;
828 BSX_RTC.hours++;
829 }
830 if (BSX_RTC.hours >= 24)
831 BSX_RTC.hours = 0;
832
833 BSX.test2192[10] = BSX_RTC.seconds;
834 BSX.test2192[11] = BSX_RTC.minutes;
835 BSX.test2192[12] = BSX_RTC.hours;
836
837 break;
838
839 /* Transmission status? (r/w) */
840 case 0x2193:
841 /* Data ready when bits 2/3 clear? */
842 t = BSX.PPU[0x2193 - BSXPPUBASE] & ~0x0C;
843 break;
844
845 /* Reset? (r/w) */
846 case 0x2194:
847 t = BSX.PPU[0x2194 - BSXPPUBASE];
848 break;
849
850 /* Unknown (r) */
851 case 0x2196:
852 t = BSX.PPU[0x2196 - BSXPPUBASE];
853 break;
854
855 /* Unknown (r/w) */
856 case 0x2197:
857 t = BSX.PPU[0x2197 - BSXPPUBASE];
858 break;
859
860 /* Modem protocol? (r/w) */
861 case 0x2199:
862 t = BSX.PPU[0x2199 - BSXPPUBASE];
863 break;
864
865 default:
866 t = OpenBus;
867 break;
868 }
869
870 return (t);
871 }
872
S9xSetBSXPPU(uint8 byte,uint16 address)873 void S9xSetBSXPPU (uint8 byte, uint16 address)
874 {
875 /* known write registers */
876 switch (address)
877 {
878 /* Test register low? (r/w) */
879 case 0x2188:
880 BSX.PPU[0x2188 - BSXPPUBASE] = byte;
881 break;
882
883 /* Test register high? (r/w) */
884 case 0x2189:
885 BSX.PPU[0x2189 - BSXPPUBASE] = byte;
886 break;
887
888 case 0x218A:
889 BSX.PPU[0x218A - BSXPPUBASE] = byte;
890 break;
891
892 case 0x218B:
893 BSX.PPU[0x218B - BSXPPUBASE] = byte;
894 break;
895
896 case 0x218C:
897 BSX.PPU[0x218C - BSXPPUBASE] = byte;
898 break;
899
900 /* Transmission number low? (r/w) */
901 case 0x218E:
902 BSX.PPU[0x218E - BSXPPUBASE] = byte;
903 break;
904
905 /* Transmission number high? (r/w) */
906 case 0x218F:
907 BSX.PPU[0x218F - BSXPPUBASE] = byte;
908
909 /* ? */
910 BSX.PPU[0x218E - BSXPPUBASE] >>= 1;
911 BSX.PPU[0x218E - BSXPPUBASE] = BSX.PPU[0x218F - BSXPPUBASE] - BSX.PPU[0x218E - BSXPPUBASE];
912 BSX.PPU[0x218F - BSXPPUBASE] >>= 1;
913
914 /* ? */
915 BSX.PPU[0x2190 - BSXPPUBASE] = 0x80;
916 break;
917
918 /* Strobe assert? (w) */
919 case 0x2191:
920 BSX.PPU[0x2191 - BSXPPUBASE] = byte;
921 BSX.out_index = 0;
922 break;
923
924 /* Data register? (r/w) */
925 case 0x2192:
926 BSX.PPU[0x2192 - BSXPPUBASE] = 0x01; /* ? */
927 BSX.PPU[0x2190 - BSXPPUBASE] = 0x80; /* ? */
928 break;
929
930 /* Transmission status? (r/w) */
931 case 0x2193:
932 BSX.PPU[0x2193 - BSXPPUBASE] = byte;
933 break;
934
935 /* Reset? (r/w) */
936 case 0x2194:
937 BSX.PPU[0x2194 - BSXPPUBASE] = byte;
938 break;
939
940 /* Unknown (r/w) */
941 case 0x2197:
942 BSX.PPU[0x2197 - BSXPPUBASE] = byte;
943 break;
944
945 /* Modem protocol? (r/w) */
946 case 0x2199:
947 /* Lots of modem strings written here when
948 connection is lost or no uplink established */
949 BSX.PPU[0x2199 - BSXPPUBASE] = byte;
950 break;
951 }
952 }
953
S9xGetBasePointerBSX(uint32 address)954 uint8 * S9xGetBasePointerBSX (uint32 address)
955 {
956 return (MapROM);
957 }
958
BSX_LoadBIOS(void)959 static bool8 BSX_LoadBIOS (void)
960 {
961 RFILE *fp = NULL;
962 char path[PATH_MAX + 1], name[PATH_MAX + 1];
963 bool8 r = FALSE;
964
965 strcpy(path, S9xGetDirectory(BIOS_DIR));
966 strcat(path, SLASH_STR);
967 strcpy(name, path);
968 strcat(name, "BS-X.bin");
969
970 fp = filestream_open(name, RETRO_VFS_FILE_ACCESS_READ,
971 RETRO_VFS_FILE_ACCESS_HINT_NONE);
972
973 if (!fp)
974 {
975 strcpy(name, path);
976 strcat(name, "BS-X.bios");
977
978 fp = filestream_open(name, RETRO_VFS_FILE_ACCESS_READ,
979 RETRO_VFS_FILE_ACCESS_HINT_NONE);
980 }
981
982 if (fp)
983 {
984 int64_t size;
985
986 size = filestream_read(fp, (void *)Memory.BIOSROM, BIOS_SIZE);
987 filestream_close(fp);
988
989 if (size == BIOS_SIZE)
990 r = TRUE;
991 }
992
993 return (r);
994 }
995
valid_normal_bank(unsigned char bankbyte)996 static bool8 valid_normal_bank (unsigned char bankbyte)
997 {
998 if(bankbyte == 32 || bankbyte == 33 || bankbyte == 48 || bankbyte == 49)
999 return TRUE;
1000 else
1001 return FALSE;
1002 }
1003
is_bsx(unsigned char * p)1004 static int is_bsx (unsigned char *p)
1005 {
1006 if ((p[26] == 0x33 || p[26] == 0xFF) && (!p[21] || (p[21] & 131) == 128) && valid_normal_bank(p[24]))
1007 {
1008 unsigned char m = p[22];
1009
1010 if (!m && !p[23])
1011 return (2);
1012
1013 if ((m == 0xFF && p[23] == 0xFF) || (!(m & 0xF) && ((m >> 4) - 1 < 12)))
1014 return (1);
1015 }
1016
1017 return (0);
1018 }
1019
S9xInitBSX(void)1020 void S9xInitBSX (void)
1021 {
1022 int r1, r2;
1023 uint8 *header;
1024 time_t t;
1025 struct tm *tmr;
1026
1027 Settings.BS = FALSE;
1028
1029 if (!memcmp(&Memory.ROM[0x7FC0], "Satellaview BS-X ", 21))
1030 {
1031 /* BS-X itself */
1032
1033 Settings.BS = TRUE;
1034 Settings.BSXItself = TRUE;
1035
1036 Memory.LoROM = TRUE;
1037 Memory.HiROM = FALSE;
1038
1039 memcpy(Memory.BIOSROM, Memory.ROM, BIOS_SIZE);
1040
1041 FlashMode = FALSE;
1042 FlashSize = FLASH_SIZE;
1043
1044 BSX.bootup = TRUE;
1045 }
1046 else
1047 {
1048 Settings.BSXItself = FALSE;
1049
1050 r1 = (is_bsx(Memory.ROM + 0x7FC0) == 1);
1051 r2 = (is_bsx(Memory.ROM + 0xFFC0) == 1);
1052 Settings.BS = (r1 | r2) ? TRUE : FALSE;
1053
1054 if (Settings.BS)
1055 {
1056 /* BS games */
1057
1058 Memory.LoROM = r1 ? TRUE : FALSE;
1059 Memory.HiROM = r2 ? TRUE : FALSE;
1060
1061 header = r1 ? Memory.ROM + 0x7FC0 : Memory.ROM + 0xFFC0;
1062
1063 FlashMode = (header[0x18] & 0xEF) == 0x20 ? FALSE : TRUE;
1064 FlashSize = (header[0x19] & 0x20) ? PSRAM_SIZE : FLASH_SIZE;
1065
1066 BSX.bootup = Settings.BSXBootup;
1067
1068 if (!BSX_LoadBIOS())
1069 {
1070 BSX.bootup = FALSE;
1071 memset(Memory.BIOSROM, 0, BIOS_SIZE);
1072 }
1073 }
1074 }
1075
1076 if (Settings.BS)
1077 {
1078 MapROM = NULL;
1079 FlashROM = Memory.ROM;
1080
1081 time(&t);
1082 tmr = localtime(&t);
1083
1084 BSX_RTC.ticks = 0;
1085 memcpy(BSX.test2192, init2192, sizeof(init2192));
1086 BSX.test2192[10] = BSX_RTC.seconds = tmr->tm_sec;
1087 BSX.test2192[11] = BSX_RTC.minutes = tmr->tm_min;
1088 BSX.test2192[12] = BSX_RTC.hours = tmr->tm_hour;
1089 SNESGameFixes.SRAMInitialValue = 0x00;
1090 }
1091 }
1092
S9xResetBSX(void)1093 void S9xResetBSX (void)
1094 {
1095 if (Settings.BSXItself)
1096 memset(Memory.ROM, 0, FLASH_SIZE);
1097
1098 memset(BSX.PPU, 0, sizeof(BSX.PPU));
1099 memset(BSX.MMC, 0, sizeof(BSX.MMC));
1100 memset(BSX.prevMMC, 0, sizeof(BSX.prevMMC));
1101
1102 BSX.dirty = FALSE;
1103 BSX.dirty2 = FALSE;
1104 BSX.flash_enable = FALSE;
1105 BSX.write_enable = FALSE;
1106 BSX.read_enable = FALSE;
1107 BSX.flash_command = 0;
1108 BSX.old_write = 0;
1109 BSX.new_write = 0;
1110
1111 BSX.out_index = 0;
1112 memset(BSX.output, 0, sizeof(BSX.output));
1113
1114 /* starting from the BIOS */
1115 if (BSX.bootup)
1116 BSX.MMC[0x07] = BSX.MMC[0x08] = 0x80;
1117 else
1118 {
1119 BSX.MMC[0x02] = FlashMode ? 0x80: 0;
1120
1121 /* per BIOS: run from psram or flash card */
1122 if (FlashSize == PSRAM_SIZE)
1123 {
1124 memcpy(Memory.BSRAM, FlashROM, PSRAM_SIZE);
1125
1126 BSX.MMC[0x01] = 0x80;
1127 BSX.MMC[0x03] = 0x80;
1128 BSX.MMC[0x04] = 0x80;
1129 BSX.MMC[0x0C] = 0x80;
1130 BSX.MMC[0x0D] = 0x80;
1131 }
1132 else
1133 {
1134 BSX.MMC[0x03] = 0x80;
1135 BSX.MMC[0x05] = 0x80;
1136 BSX.MMC[0x06] = 0x80;
1137 }
1138
1139 BSX.MMC[0x0E] = 0x80;
1140 }
1141
1142 BSX_Map();
1143 }
1144
S9xBSXPostLoadState(void)1145 void S9xBSXPostLoadState (void)
1146 {
1147 uint8 temp[16];
1148 bool8 pd1, pd2;
1149
1150 pd1 = BSX.dirty;
1151 pd2 = BSX.dirty2;
1152 memcpy(temp, BSX.MMC, sizeof(BSX.MMC));
1153
1154 memcpy(BSX.MMC, BSX.prevMMC, sizeof(BSX.MMC));
1155 BSX_Map();
1156
1157 memcpy(BSX.MMC, temp, sizeof(BSX.MMC));
1158 BSX.dirty = pd1;
1159 BSX.dirty2 = pd2;
1160 }
1161