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