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