1 | /*****************************************************************************\ |
2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. |
3 | This file is licensed under the Snes9x License. |
4 | For further information, consult the LICENSE file in the root directory. |
5 | \*****************************************************************************/ |
6 | |
7 | // Dreamer Nom wrote: |
8 | // Large thanks to John Weidman for all his initial research |
9 | // Thanks to Seph3 for his modem notes |
10 | |
11 | |
12 | #include "snes9x.h" |
13 | #include "memmap.h" |
14 | #include "display.h" |
15 | #include <math.h> |
16 | |
17 | //#define BSX_DEBUG |
18 | |
19 | #define BIOS_SIZE 0x100000 |
20 | #define FLASH_SIZE 0x100000 |
21 | #define PSRAM_SIZE 0x80000 |
22 | |
23 | #define Map Memory.Map |
24 | #define BlockIsRAM Memory.BlockIsRAM |
25 | #define BlockIsROM Memory.BlockIsROM |
26 | #define RAM Memory.RAM |
27 | #define SRAM Memory.SRAM |
28 | #define PSRAM Memory.BSRAM |
29 | #define BIOSROM Memory.BIOSROM |
30 | #define MAP_BSX Memory.MAP_BSX |
31 | #define MAP_CPU Memory.MAP_CPU |
32 | #define MAP_PPU Memory.MAP_PPU |
33 | #define MAP_NONE Memory.MAP_NONE |
34 | |
35 | #define BSXPPUBASE 0x2180 |
36 | |
37 | struct SBSX_RTC |
38 | { |
39 | int year; |
40 | int month; |
41 | int dayweek; |
42 | int day; |
43 | int hours; |
44 | int minutes; |
45 | int seconds; |
46 | int ticks; |
47 | }; |
48 | |
49 | static struct SBSX_RTC BSX_RTC; |
50 | |
51 | // flash card vendor information |
52 | static const uint8 flashcard[20] = |
53 | { |
54 | 0x4D, 0x00, 0x50, 0x00, // vendor id |
55 | 0x00, 0x00, // ? |
56 | 0x1A, 0x00, // 2MB Flash (1MB = 0x2A) |
57 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
58 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
59 | }; |
60 | |
61 | #if 0 |
62 | static const uint8 init2192[32] = // FIXME |
63 | { |
64 | 00, 00, 00, 00, 00, // unknown |
65 | 01, 01, 00, 00, 00, |
66 | 00, // seconds (?) |
67 | 00, // minutes |
68 | 00, // hours |
69 | 10, 10, 10, 10, 10, // unknown |
70 | 10, 10, 10, 10, 10, // dummy |
71 | 00, 00, 00, 00, 00, 00, 00, 00, 00 |
72 | }; |
73 | #endif |
74 | |
75 | static bool8 FlashMode; |
76 | static uint32 FlashSize; |
77 | static uint8 *MapROM, *FlashROM; |
78 | |
79 | static void BSX_Map_SNES (void); |
80 | static void BSX_Map_LoROM (void); |
81 | static void BSX_Map_HiROM (void); |
82 | static void BSX_Map_MMC (void); |
83 | static void BSX_Map_FlashIO (void); |
84 | static void BSX_Map_SRAM (void); |
85 | static void BSX_Map_PSRAM (void); |
86 | static void BSX_Map_BIOS (void); |
87 | static void BSX_Map_RAM (void); |
88 | static void BSX_Map (void); |
89 | static bool8 BSX_LoadBIOS (void); |
90 | static void map_psram_mirror_sub (uint32); |
91 | static int is_bsx (unsigned char *); |
92 | |
93 | |
94 | static void BSX_Map_SNES (void) |
95 | { |
96 | // These maps will be partially overwritten |
97 | |
98 | int c; |
99 | |
100 | // Banks 00->3F and 80->BF |
101 | for (c = 0; c < 0x400; c += 16) |
102 | { |
103 | Map[c + 0] = Map[c + 0x800] = RAM; |
104 | Map[c + 1] = Map[c + 0x801] = RAM; |
105 | BlockIsRAM[c + 0] = BlockIsRAM[c + 0x800] = TRUE; |
106 | BlockIsRAM[c + 1] = BlockIsRAM[c + 0x801] = TRUE; |
107 | |
108 | Map[c + 2] = Map[c + 0x802] = (uint8 *) MAP_PPU; |
109 | Map[c + 3] = Map[c + 0x803] = (uint8 *) MAP_PPU; |
110 | Map[c + 4] = Map[c + 0x804] = (uint8 *) MAP_CPU; |
111 | Map[c + 5] = Map[c + 0x805] = (uint8 *) MAP_CPU; |
112 | Map[c + 6] = Map[c + 0x806] = (uint8 *) MAP_NONE; |
113 | Map[c + 7] = Map[c + 0x807] = (uint8 *) MAP_NONE; |
114 | } |
115 | } |
116 | |
117 | static void BSX_Map_LoROM (void) |
118 | { |
119 | // These maps will be partially overwritten |
120 | |
121 | int i, c; |
122 | |
123 | // Banks 00->3F and 80->BF |
124 | for (c = 0; c < 0x400; c += 16) |
125 | { |
126 | for (i = c + 8; i < c + 16; i++) |
127 | { |
128 | Map[i] = Map[i + 0x800] = &MapROM[(c << 11) % FlashSize] - 0x8000; |
129 | BlockIsRAM[i] = BlockIsRAM[i + 0x800] = BSX.write_enable; |
130 | BlockIsROM[i] = BlockIsROM[i + 0x800] = !BSX.write_enable; |
131 | } |
132 | } |
133 | |
134 | // Banks 40->7F and C0->FF |
135 | for (c = 0; c < 0x400; c += 16) |
136 | { |
137 | for (i = c; i < c + 8; i++) |
138 | Map[i + 0x400] = Map[i + 0xC00] = &MapROM[(c << 11) % FlashSize]; |
139 | |
140 | for (i = c + 8; i < c + 16; i++) |
141 | Map[i + 0x400] = Map[i + 0xC00] = &MapROM[(c << 11) % FlashSize] - 0x8000; |
142 | |
143 | for (i = c; i < c + 16; i++) |
144 | { |
145 | BlockIsRAM[i + 0x400] = BlockIsRAM[i + 0xC00] = BSX.write_enable; |
146 | BlockIsROM[i + 0x400] = BlockIsROM[i + 0xC00] = !BSX.write_enable; |
147 | } |
148 | } |
149 | } |
150 | |
151 | static void BSX_Map_HiROM (void) |
152 | { |
153 | // These maps will be partially overwritten |
154 | |
155 | int i, c; |
156 | |
157 | // Banks 00->3F and 80->BF |
158 | for (c = 0; c < 0x400; c += 16) |
159 | { |
160 | for (i = c + 8; i < c + 16; i++) |
161 | { |
162 | Map[i] = Map[i + 0x800] = &MapROM[(c << 12) % FlashSize]; |
163 | BlockIsRAM[i] = BlockIsRAM[i + 0x800] = BSX.write_enable; |
164 | BlockIsROM[i] = BlockIsROM[i + 0x800] = !BSX.write_enable; |
165 | } |
166 | } |
167 | |
168 | // Banks 40->7F and C0->FF |
169 | for (c = 0; c < 0x400; c += 16) |
170 | { |
171 | for (i = c; i < c + 16; i++) |
172 | { |
173 | Map[i + 0x400] = Map[i + 0xC00] = &MapROM[(c << 12) % FlashSize]; |
174 | BlockIsRAM[i + 0x400] = BlockIsRAM[i + 0xC00] = BSX.write_enable; |
175 | BlockIsROM[i + 0x400] = BlockIsROM[i + 0xC00] = !BSX.write_enable; |
176 | } |
177 | } |
178 | } |
179 | |
180 | static void BSX_Map_MMC (void) |
181 | { |
182 | int c; |
183 | |
184 | // Banks 01->0E:5000-5FFF |
185 | for (c = 0x010; c < 0x0F0; c += 16) |
186 | { |
187 | Map[c + 5] = (uint8 *) MAP_BSX; |
188 | BlockIsRAM[c + 5] = BlockIsROM[c + 5] = FALSE; |
189 | } |
190 | } |
191 | |
192 | static void BSX_Map_FlashIO (void) |
193 | { |
194 | int i, c; |
195 | |
196 | if (BSX.prevMMC[0x0C]) |
197 | { |
198 | // Banks 00->3F and 80->BF |
199 | for (c = 0; c < 0x400; c += 16) |
200 | { |
201 | for (i = c + 8; i < c + 16; i++) |
202 | { |
203 | Map[i] = Map[i + 0x800] = (uint8 *)MAP_BSX; |
204 | BlockIsRAM[i] = BlockIsRAM[i + 0x800] = TRUE; |
205 | BlockIsROM[i] = BlockIsROM[i + 0x800] = FALSE; |
206 | } |
207 | } |
208 | |
209 | // Banks 40->7F and C0->FF |
210 | for (c = 0; c < 0x400; c += 16) |
211 | { |
212 | for (i = c; i < c + 16; i++) |
213 | { |
214 | Map[i + 0x400] = Map[i + 0xC00] = (uint8 *)MAP_BSX; |
215 | BlockIsRAM[i + 0x400] = BlockIsRAM[i + 0xC00] = TRUE; |
216 | BlockIsROM[i + 0x400] = BlockIsROM[i + 0xC00] = FALSE; |
217 | } |
218 | } |
219 | } |
220 | } |
221 | |
222 | static void BSX_Map_SRAM (void) |
223 | { |
224 | int c; |
225 | |
226 | // Banks 10->17:5000-5FFF |
227 | for (c = 0x100; c < 0x180; c += 16) |
228 | { |
229 | Map[c + 5] = (uint8 *) SRAM + ((c & 0x70) << 8) - 0x5000; |
230 | BlockIsRAM[c + 5] = TRUE; |
231 | BlockIsROM[c + 5] = FALSE; |
232 | } |
233 | } |
234 | |
235 | static void map_psram_mirror_sub (uint32 bank) |
236 | { |
237 | int i, c; |
238 | |
239 | bank <<= 4; |
240 | |
241 | if (BSX.prevMMC[0x02]) |
242 | { |
243 | //HiROM |
244 | for (c = 0; c < 0x80; c += 16) |
245 | { |
246 | if ((bank & 0x7F0) >= 0x400) |
247 | { |
248 | for (i = c; i < c + 16; i++) |
249 | { |
250 | Map[i + bank] = &PSRAM[(c << 12) % PSRAM_SIZE]; |
251 | BlockIsRAM[i + bank] = TRUE; |
252 | BlockIsROM[i + bank] = FALSE; |
253 | } |
254 | } |
255 | else |
256 | { |
257 | for (i = c + 8; i < c + 16; i++) |
258 | { |
259 | Map[i + bank] = &PSRAM[(c << 12) % PSRAM_SIZE]; |
260 | BlockIsRAM[i + bank] = TRUE; |
261 | BlockIsROM[i + bank] = FALSE; |
262 | } |
263 | } |
264 | } |
265 | } |
266 | else |
267 | { |
268 | //LoROM |
269 | for (c = 0; c < 0x100; c += 16) |
270 | { |
271 | if ((bank & 0x7F0) >= 0x400) |
272 | { |
273 | for (i = c; i < c + 8; i++) |
274 | { |
275 | Map[i + bank] = &PSRAM[(c << 11) % PSRAM_SIZE]; |
276 | BlockIsRAM[i + bank] = TRUE; |
277 | BlockIsROM[i + bank] = FALSE; |
278 | } |
279 | } |
280 | |
281 | for (i = c + 8; i < c + 16; i++) |
282 | { |
283 | Map[i + bank] = &PSRAM[(c << 11) % PSRAM_SIZE] - 0x8000; |
284 | BlockIsRAM[i + bank] = TRUE; |
285 | BlockIsROM[i + bank] = FALSE; |
286 | } |
287 | } |
288 | } |
289 | } |
290 | |
291 | static void BSX_Map_PSRAM(void) |
292 | { |
293 | int c; |
294 | |
295 | if (!BSX.prevMMC[0x02]) |
296 | { |
297 | //LoROM Mode |
298 | if (!BSX.prevMMC[0x05] && !BSX.prevMMC[0x06]) |
299 | { |
300 | //Map PSRAM to 00-0F/80-8F |
301 | if (BSX.prevMMC[0x03]) |
302 | map_psram_mirror_sub(0x00); |
303 | |
304 | if (BSX.prevMMC[0x04]) |
305 | map_psram_mirror_sub(0x80); |
306 | } |
307 | else if (BSX.prevMMC[0x05] && !BSX.prevMMC[0x06]) |
308 | { |
309 | //Map PSRAM to 20-2F/A0-AF |
310 | if (BSX.prevMMC[0x03]) |
311 | map_psram_mirror_sub(0x20); |
312 | |
313 | if (BSX.prevMMC[0x04]) |
314 | map_psram_mirror_sub(0xA0); |
315 | } |
316 | else if (!BSX.prevMMC[0x05] && BSX.prevMMC[0x06]) |
317 | { |
318 | //Map PSRAM to 40-4F/C0-CF |
319 | if (BSX.prevMMC[0x03]) |
320 | map_psram_mirror_sub(0x40); |
321 | |
322 | if (BSX.prevMMC[0x04]) |
323 | map_psram_mirror_sub(0xC0); |
324 | } |
325 | else |
326 | { |
327 | //Map PSRAM to 60-6F/E0-EF |
328 | if (BSX.prevMMC[0x03]) |
329 | map_psram_mirror_sub(0x60); |
330 | |
331 | if (BSX.prevMMC[0x04]) |
332 | map_psram_mirror_sub(0xE0); |
333 | } |
334 | |
335 | //Map PSRAM to 70-7D/F0-FF |
336 | if (BSX.prevMMC[0x03]) |
337 | map_psram_mirror_sub(0x70); |
338 | |
339 | if (BSX.prevMMC[0x04]) |
340 | map_psram_mirror_sub(0xF0); |
341 | } |
342 | else |
343 | { |
344 | //HiROM Mode |
345 | if (!BSX.prevMMC[0x05] && !BSX.prevMMC[0x06]) |
346 | { |
347 | //Map PSRAM to 00-07/40-47 / 80-87/C0-C7 |
348 | if (BSX.prevMMC[0x03]) |
349 | { |
350 | map_psram_mirror_sub(0x00); |
351 | map_psram_mirror_sub(0x40); |
352 | } |
353 | |
354 | if (BSX.prevMMC[0x04]) |
355 | { |
356 | map_psram_mirror_sub(0x80); |
357 | map_psram_mirror_sub(0xC0); |
358 | } |
359 | } |
360 | else if (BSX.prevMMC[0x05] && !BSX.prevMMC[0x06]) |
361 | { |
362 | //Map PSRAM to 10-17/50-57 / 90-97-D0-D7 |
363 | if (BSX.prevMMC[0x03]) |
364 | { |
365 | map_psram_mirror_sub(0x10); |
366 | map_psram_mirror_sub(0x50); |
367 | } |
368 | |
369 | if (BSX.prevMMC[0x04]) |
370 | { |
371 | map_psram_mirror_sub(0x90); |
372 | map_psram_mirror_sub(0xD0); |
373 | } |
374 | } |
375 | else if (!BSX.prevMMC[0x05] && BSX.prevMMC[0x06]) |
376 | { |
377 | //Map PSRAM to 20-27/60-67 / A0-A7/E0-E7 |
378 | if (BSX.prevMMC[0x03]) |
379 | { |
380 | map_psram_mirror_sub(0x20); |
381 | map_psram_mirror_sub(0x60); |
382 | } |
383 | |
384 | if (BSX.prevMMC[0x04]) |
385 | { |
386 | map_psram_mirror_sub(0xA0); |
387 | map_psram_mirror_sub(0xE0); |
388 | } |
389 | } |
390 | else |
391 | { |
392 | //Map PSRAM to 30-37/70-77 / B0-B7/F0-F7 |
393 | if (BSX.prevMMC[0x03]) |
394 | { |
395 | map_psram_mirror_sub(0x30); |
396 | map_psram_mirror_sub(0x70); |
397 | } |
398 | |
399 | if (BSX.prevMMC[0x04]) |
400 | { |
401 | map_psram_mirror_sub(0xB0); |
402 | map_psram_mirror_sub(0xF0); |
403 | } |
404 | } |
405 | |
406 | if (BSX.prevMMC[0x03]) |
407 | { |
408 | //Map PSRAM to 20->3F:6000-7FFF |
409 | for (c = 0x200; c < 0x400; c += 16) |
410 | { |
411 | Map[c + 6] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; |
412 | Map[c + 7] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; |
413 | BlockIsRAM[c + 6] = TRUE; |
414 | BlockIsRAM[c + 7] = TRUE; |
415 | BlockIsROM[c + 6] = FALSE; |
416 | BlockIsROM[c + 7] = FALSE; |
417 | } |
418 | } |
419 | |
420 | if (BSX.prevMMC[0x04]) |
421 | { |
422 | //Map PSRAM to A0->BF:6000-7FFF |
423 | for (c = 0xA00; c < 0xC00; c += 16) |
424 | { |
425 | Map[c + 6] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; |
426 | Map[c + 7] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; |
427 | BlockIsRAM[c + 6] = TRUE; |
428 | BlockIsRAM[c + 7] = TRUE; |
429 | BlockIsROM[c + 6] = FALSE; |
430 | BlockIsROM[c + 7] = FALSE; |
431 | } |
432 | } |
433 | } |
434 | } |
435 | |
436 | static void BSX_Map_BIOS (void) |
437 | { |
438 | int i,c; |
439 | |
440 | // Banks 00->1F:8000-FFFF |
441 | if (BSX.prevMMC[0x07]) |
442 | { |
443 | for (c = 0; c < 0x200; c += 16) |
444 | { |
445 | for (i = c + 8; i < c + 16; i++) |
446 | { |
447 | Map[i] = &BIOSROM[(c << 11) % BIOS_SIZE] - 0x8000; |
448 | BlockIsRAM[i] = FALSE; |
449 | BlockIsROM[i] = TRUE; |
450 | } |
451 | } |
452 | } |
453 | |
454 | // Banks 80->9F:8000-FFFF |
455 | if (BSX.prevMMC[0x08]) |
456 | { |
457 | for (c = 0; c < 0x200; c += 16) |
458 | { |
459 | for (i = c + 8; i < c + 16; i++) |
460 | { |
461 | Map[i + 0x800] = &BIOSROM[(c << 11) % BIOS_SIZE] - 0x8000; |
462 | BlockIsRAM[i + 0x800] = FALSE; |
463 | BlockIsROM[i + 0x800] = TRUE; |
464 | } |
465 | } |
466 | } |
467 | } |
468 | |
469 | static void BSX_Map_RAM (void) |
470 | { |
471 | int c; |
472 | |
473 | // Banks 7E->7F |
474 | for (c = 0; c < 16; c++) |
475 | { |
476 | Map[c + 0x7E0] = RAM; |
477 | Map[c + 0x7F0] = RAM + 0x10000; |
478 | BlockIsRAM[c + 0x7E0] = TRUE; |
479 | BlockIsRAM[c + 0x7F0] = TRUE; |
480 | BlockIsROM[c + 0x7E0] = FALSE; |
481 | BlockIsROM[c + 0x7F0] = FALSE; |
482 | } |
483 | } |
484 | |
485 | static void BSX_Map (void) |
486 | { |
487 | #ifdef BSX_DEBUG |
488 | printf("BS: Remapping\n" ); |
489 | for (int i = 0; i < 32; i++) |
490 | printf("BS: MMC %02X: %d\n" , i, BSX.MMC[i]); |
491 | #endif |
492 | |
493 | memcpy(BSX.prevMMC, BSX.MMC, sizeof(BSX.MMC)); |
494 | |
495 | MapROM = FlashROM; |
496 | FlashSize = FLASH_SIZE; |
497 | |
498 | if (BSX.prevMMC[0x02]) |
499 | BSX_Map_HiROM(); |
500 | else |
501 | BSX_Map_LoROM(); |
502 | |
503 | BSX_Map_FlashIO(); |
504 | BSX_Map_PSRAM(); |
505 | |
506 | BSX_Map_SNES(); |
507 | BSX_Map_SRAM(); |
508 | BSX_Map_RAM(); |
509 | |
510 | BSX_Map_BIOS(); |
511 | BSX_Map_MMC(); |
512 | |
513 | // Monitor new register changes |
514 | BSX.dirty = FALSE; |
515 | BSX.dirty2 = FALSE; |
516 | |
517 | Memory.map_WriteProtectROM(); |
518 | } |
519 | |
520 | static uint8 BSX_Get_Bypass_FlashIO (uint32 offset) |
521 | { |
522 | //For games other than BS-X |
523 | FlashROM = Memory.ROM + Multi.cartOffsetB; |
524 | |
525 | if (BSX.prevMMC[0x02]) |
526 | return (FlashROM[offset & 0x0FFFFF]); |
527 | else |
528 | return (FlashROM[(offset & 0x1F0000) >> 1 | (offset & 0x7FFF)]); |
529 | } |
530 | |
531 | static void BSX_Set_Bypass_FlashIO (uint32 offset, uint8 byte) |
532 | { |
533 | //For games other than BS-X |
534 | FlashROM = Memory.ROM + Multi.cartOffsetB; |
535 | |
536 | if (BSX.prevMMC[0x02]) |
537 | FlashROM[offset & 0x0FFFFF] = FlashROM[offset & 0x0FFFFF] & byte; |
538 | else |
539 | FlashROM[(offset & 0x1F0000) >> 1 | (offset & 0x7FFF)] = FlashROM[(offset & 0x1F0000) >> 1 | (offset & 0x7FFF)] & byte; |
540 | } |
541 | |
542 | uint8 S9xGetBSX (uint32 address) |
543 | { |
544 | uint8 bank = (address >> 16) & 0xFF; |
545 | uint16 offset = address & 0xFFFF; |
546 | uint8 t = 0; |
547 | |
548 | // MMC |
549 | if ((bank >= 0x01 && bank <= 0x0E) && ((address & 0xF000) == 0x5000)) |
550 | return (BSX.MMC[bank]); |
551 | |
552 | // Flash Mapping |
553 | |
554 | // default: read-through mode |
555 | t = BSX_Get_Bypass_FlashIO(address); |
556 | |
557 | // note: may be more registers, purposes unknown |
558 | switch (offset) |
559 | { |
560 | case 0x0002: |
561 | case 0x8002: |
562 | if (BSX.flash_bsr) |
563 | t = 0xC0; // Page Status Register |
564 | break; |
565 | |
566 | case 0x0004: |
567 | case 0x8004: |
568 | if (BSX.flash_gsr) |
569 | t = 0x82; // Global Status Register |
570 | break; |
571 | |
572 | case 0x5555: |
573 | if (BSX.flash_enable) |
574 | t = 0x80; // ??? |
575 | break; |
576 | |
577 | case 0xFF00: |
578 | case 0xFF02: |
579 | case 0xFF04: |
580 | case 0xFF06: |
581 | case 0xFF08: |
582 | case 0xFF0A: |
583 | case 0xFF0C: |
584 | case 0xFF0E: |
585 | case 0xFF10: |
586 | case 0xFF12: |
587 | // return flash vendor information |
588 | if (BSX.read_enable) |
589 | t = flashcard[offset - 0xFF00]; |
590 | break; |
591 | } |
592 | |
593 | if (BSX.flash_csr) |
594 | { |
595 | t = 0x80; // Compatible Status Register |
596 | BSX.flash_csr = false; |
597 | } |
598 | |
599 | return (t); |
600 | } |
601 | |
602 | void S9xSetBSX (uint8 byte, uint32 address) |
603 | { |
604 | uint8 bank = (address >> 16) & 0xFF; |
605 | |
606 | // MMC |
607 | if ((bank >= 0x01 && bank <= 0x0E) && ((address & 0xF000) == 0x5000)) |
608 | { |
609 | //Avoid updating the memory map when it is not needed |
610 | if (bank == 0x0E && BSX.dirty) |
611 | { |
612 | BSX_Map(); |
613 | BSX.dirty = FALSE; |
614 | } |
615 | else if (bank != 0x0E && BSX.MMC[bank] != byte) |
616 | { |
617 | BSX.dirty = TRUE; |
618 | } |
619 | |
620 | BSX.MMC[bank] = byte; |
621 | } |
622 | |
623 | // Flash IO |
624 | |
625 | // Write to Flash |
626 | if (BSX.write_enable) |
627 | { |
628 | BSX_Set_Bypass_FlashIO(address, byte); |
629 | BSX.write_enable = false; |
630 | return; |
631 | } |
632 | |
633 | // Flash Command Handling |
634 | |
635 | //Memory Pack Type 1 & 3 & 4 |
636 | BSX.flash_command <<= 8; |
637 | BSX.flash_command |= byte; |
638 | |
639 | switch (BSX.flash_command & 0xFF) |
640 | { |
641 | case 0x00: |
642 | case 0xFF: |
643 | //Reset to normal |
644 | BSX.flash_enable = false; |
645 | BSX.flash_bsr = false; |
646 | BSX.flash_csr = false; |
647 | BSX.flash_gsr = false; |
648 | BSX.read_enable = false; |
649 | BSX.write_enable = false; |
650 | BSX.flash_cmd_done = true; |
651 | break; |
652 | |
653 | case 0x10: |
654 | case 0x40: |
655 | //Write Byte |
656 | BSX.flash_enable = false; |
657 | BSX.flash_bsr = false; |
658 | BSX.flash_csr = true; |
659 | BSX.flash_gsr = false; |
660 | BSX.read_enable = false; |
661 | BSX.write_enable = true; |
662 | BSX.flash_cmd_done = true; |
663 | break; |
664 | |
665 | case 0x50: |
666 | //Clear Status Register |
667 | BSX.flash_enable = false; |
668 | BSX.flash_bsr = false; |
669 | BSX.flash_csr = false; |
670 | BSX.flash_gsr = false; |
671 | BSX.flash_cmd_done = true; |
672 | break; |
673 | |
674 | case 0x70: |
675 | //Read CSR |
676 | BSX.flash_enable = false; |
677 | BSX.flash_bsr = false; |
678 | BSX.flash_csr = true; |
679 | BSX.flash_gsr = false; |
680 | BSX.read_enable = false; |
681 | BSX.write_enable = false; |
682 | BSX.flash_cmd_done = true; |
683 | break; |
684 | |
685 | case 0x71: |
686 | //Read Extended Status Registers (Page and Global) |
687 | BSX.flash_enable = false; |
688 | BSX.flash_bsr = true; |
689 | BSX.flash_csr = false; |
690 | BSX.flash_gsr = true; |
691 | BSX.read_enable = false; |
692 | BSX.write_enable = false; |
693 | BSX.flash_cmd_done = true; |
694 | break; |
695 | |
696 | case 0x75: |
697 | //Show Page Buffer / Vendor Info |
698 | BSX.flash_csr = false; |
699 | BSX.read_enable = true; |
700 | BSX.flash_cmd_done = true; |
701 | break; |
702 | |
703 | case 0xD0: |
704 | //DO COMMAND |
705 | switch (BSX.flash_command & 0xFFFF) |
706 | { |
707 | case 0x20D0: //Block Erase |
708 | uint32 x; |
709 | for (x = 0; x < 0x10000; x++) { |
710 | //BSX_Set_Bypass_FlashIO(((address & 0xFF0000) + x), 0xFF); |
711 | if (BSX.MMC[0x02]) |
712 | FlashROM[(address & 0x0F0000) + x] = 0xFF; |
713 | else |
714 | FlashROM[((address & 0x1E0000) >> 1) + x] = 0xFF; |
715 | } |
716 | break; |
717 | |
718 | case 0xA7D0: //Chip Erase (ONLY IN TYPE 1 AND 4) |
719 | if ((flashcard[6] & 0xF0) == 0x10 || (flashcard[6] & 0xF0) == 0x40) |
720 | { |
721 | uint32 x; |
722 | for (x = 0; x < FLASH_SIZE; x++) { |
723 | //BSX_Set_Bypass_FlashIO(x, 0xFF); |
724 | FlashROM[x] = 0xFF; |
725 | } |
726 | } |
727 | break; |
728 | |
729 | case 0x38D0: //Flashcart Reset |
730 | break; |
731 | } |
732 | break; |
733 | } |
734 | } |
735 | |
736 | void S9xBSXSetStream1 (uint8 count) |
737 | { |
738 | if (BSX.sat_stream1.is_open()) |
739 | BSX.sat_stream1.close(); //If Stream already opened for one file: Close it. |
740 | |
741 | char path[PATH_MAX + 1], name[PATH_MAX + 1]; |
742 | |
743 | strcpy(path, S9xGetDirectory(SAT_DIR)); |
744 | strcat(path, SLASH_STR); |
745 | |
746 | snprintf(name, PATH_MAX + 1, "BSX%04X-%d.bin" , (BSX.PPU[0x2188 - BSXPPUBASE] | (BSX.PPU[0x2189 - BSXPPUBASE] * 256)), count); //BSXHHHH-DDD.bin |
747 | strcat(path, name); |
748 | |
749 | BSX.sat_stream1.clear(); |
750 | BSX.sat_stream1.open(path, std::ios::in | std::ios::binary); |
751 | if (BSX.sat_stream1.good()) |
752 | { |
753 | BSX.sat_stream1.seekg(0, BSX.sat_stream1.end); |
754 | long str1size = BSX.sat_stream1.tellg(); |
755 | BSX.sat_stream1.seekg(0, BSX.sat_stream1.beg); |
756 | float QueueSize = str1size / 22.; |
757 | BSX.sat_stream1_queue = (uint16)(ceil(QueueSize)); |
758 | BSX.PPU[0x218D - BSXPPUBASE] = 0; |
759 | BSX.sat_stream1_first = TRUE; |
760 | BSX.sat_stream1_loaded = TRUE; |
761 | } |
762 | else |
763 | { |
764 | BSX.sat_stream1_loaded = FALSE; |
765 | } |
766 | } |
767 | |
768 | void S9xBSXSetStream2 (uint8 count) |
769 | { |
770 | if (BSX.sat_stream2.is_open()) |
771 | BSX.sat_stream2.close(); //If Stream already opened for one file: Close it. |
772 | |
773 | char path[PATH_MAX + 1], name[PATH_MAX + 1]; |
774 | |
775 | strcpy(path, S9xGetDirectory(SAT_DIR)); |
776 | strcat(path, SLASH_STR); |
777 | |
778 | snprintf(name, PATH_MAX + 1, "BSX%04X-%d.bin" , (BSX.PPU[0x218E - BSXPPUBASE] | (BSX.PPU[0x218F - BSXPPUBASE] * 256)), count); //BSXHHHH-DDD.bin |
779 | strcat(path, name); |
780 | |
781 | BSX.sat_stream2.clear(); |
782 | BSX.sat_stream2.open(path, std::ios::in | std::ios::binary); |
783 | if (BSX.sat_stream2.good()) |
784 | { |
785 | BSX.sat_stream2.seekg(0, BSX.sat_stream2.end); |
786 | long str2size = BSX.sat_stream2.tellg(); |
787 | BSX.sat_stream2.seekg(0, BSX.sat_stream2.beg); |
788 | float QueueSize = str2size / 22.; |
789 | BSX.sat_stream2_queue = (uint16)(ceil(QueueSize)); |
790 | BSX.PPU[0x2193 - BSXPPUBASE] = 0; |
791 | BSX.sat_stream2_first = TRUE; |
792 | BSX.sat_stream2_loaded = TRUE; |
793 | } |
794 | else |
795 | { |
796 | BSX.sat_stream2_loaded = FALSE; |
797 | } |
798 | } |
799 | |
800 | uint8 S9xBSXGetRTC (void) |
801 | { |
802 | //Get Time |
803 | time_t t; |
804 | struct tm *tmr; |
805 | |
806 | time(&t); |
807 | tmr = localtime(&t); |
808 | |
809 | BSX.test2192[0] = 0x00; |
810 | BSX.test2192[1] = 0x00; |
811 | BSX.test2192[2] = 0x00; |
812 | BSX.test2192[3] = 0x00; |
813 | BSX.test2192[4] = 0x10; |
814 | BSX.test2192[5] = 0x01; |
815 | BSX.test2192[6] = 0x01; |
816 | BSX.test2192[7] = 0x00; |
817 | BSX.test2192[8] = 0x00; |
818 | BSX.test2192[9] = 0x00; |
819 | BSX.test2192[10] = BSX_RTC.seconds = tmr->tm_sec; |
820 | BSX.test2192[11] = BSX_RTC.minutes = tmr->tm_min; |
821 | BSX.test2192[12] = BSX_RTC.hours = tmr->tm_hour; |
822 | BSX.test2192[13] = BSX_RTC.dayweek = (tmr->tm_wday) + 1; |
823 | BSX.test2192[14] = BSX_RTC.day = tmr->tm_mday; |
824 | BSX.test2192[15] = BSX_RTC.month = (tmr->tm_mon) + 1; |
825 | BSX_RTC.year = tmr->tm_year + 1900; |
826 | BSX.test2192[16] = (BSX_RTC.year) & 0xFF; |
827 | BSX.test2192[17] = (BSX_RTC.year) >> 8; |
828 | |
829 | t = BSX.test2192[BSX.out_index++]; |
830 | |
831 | if (BSX.out_index > 22) |
832 | BSX.out_index = 0; |
833 | |
834 | return t; |
835 | } |
836 | |
837 | uint8 S9xGetBSXPPU (uint16 address) |
838 | { |
839 | uint8 t; |
840 | |
841 | // known read registers |
842 | switch (address) |
843 | { |
844 | //Stream 1 |
845 | // Logical Channel 1 + Data Structure (R/W) |
846 | case 0x2188: |
847 | t = BSX.PPU[0x2188 - BSXPPUBASE]; |
848 | break; |
849 | |
850 | // Logical Channel 2 (R/W) [6bit] |
851 | case 0x2189: |
852 | t = BSX.PPU[0x2189 - BSXPPUBASE]; |
853 | break; |
854 | |
855 | // Prefix Count (R) |
856 | case 0x218A: |
857 | if (!BSX.sat_pf_latch1_enable || !BSX.sat_dt_latch1_enable) |
858 | { |
859 | t = 0; |
860 | break; |
861 | } |
862 | |
863 | if (BSX.PPU[0x2188 - BSXPPUBASE] == 0 && BSX.PPU[0x2189 - BSXPPUBASE] == 0) |
864 | { |
865 | t = 1; |
866 | break; |
867 | } |
868 | |
869 | if (BSX.sat_stream1_queue <= 0) |
870 | { |
871 | BSX.sat_stream1_count++; |
872 | S9xBSXSetStream1(BSX.sat_stream1_count - 1); |
873 | } |
874 | |
875 | if (!BSX.sat_stream1_loaded && (BSX.sat_stream1_count - 1) > 0) |
876 | { |
877 | BSX.sat_stream1_count = 1; |
878 | S9xBSXSetStream1(BSX.sat_stream1_count - 1); |
879 | } |
880 | |
881 | if (BSX.sat_stream1_loaded) |
882 | { |
883 | //Lock at 0x7F for bigger packets |
884 | if (BSX.sat_stream1_queue >= 128) |
885 | BSX.PPU[0x218A - BSXPPUBASE] = 0x7F; |
886 | else |
887 | BSX.PPU[0x218A - BSXPPUBASE] = BSX.sat_stream1_queue; |
888 | t = BSX.PPU[0x218A - BSXPPUBASE]; |
889 | } |
890 | else |
891 | t = 0; |
892 | break; |
893 | |
894 | // Prefix Latch (R/W) |
895 | case 0x218B: |
896 | if (BSX.sat_pf_latch1_enable) |
897 | { |
898 | if (BSX.PPU[0x2188 - BSXPPUBASE] == 0 && BSX.PPU[0x2189 - BSXPPUBASE] == 0) |
899 | { |
900 | BSX.PPU[0x218B - BSXPPUBASE] = 0x90; |
901 | } |
902 | |
903 | if (BSX.sat_stream1_loaded) |
904 | { |
905 | uint8 temp = 0; |
906 | if (BSX.sat_stream1_first) |
907 | { |
908 | // First packet |
909 | temp |= 0x10; |
910 | BSX.sat_stream1_first = FALSE; |
911 | } |
912 | |
913 | BSX.sat_stream1_queue--; |
914 | |
915 | if (BSX.sat_stream1_queue == 0) |
916 | { |
917 | //Last packet |
918 | temp |= 0x80; |
919 | } |
920 | |
921 | BSX.PPU[0x218B - BSXPPUBASE] = temp; |
922 | } |
923 | |
924 | BSX.PPU[0x218D - BSXPPUBASE] |= BSX.PPU[0x218B - BSXPPUBASE]; |
925 | t = BSX.PPU[0x218B - BSXPPUBASE]; |
926 | } |
927 | else |
928 | { |
929 | t = 0; |
930 | } |
931 | break; |
932 | |
933 | // Data Latch (R/W) |
934 | case 0x218C: |
935 | if (BSX.sat_dt_latch1_enable) |
936 | { |
937 | if (BSX.PPU[0x2188 - BSXPPUBASE] == 0 && BSX.PPU[0x2189 - BSXPPUBASE] == 0) |
938 | { |
939 | BSX.PPU[0x218C - BSXPPUBASE] = S9xBSXGetRTC(); |
940 | } |
941 | else if (BSX.sat_stream1_loaded) |
942 | { |
943 | if (BSX.sat_stream1.eof()) |
944 | BSX.PPU[0x218C - BSXPPUBASE] = 0xFF; |
945 | else |
946 | BSX.PPU[0x218C - BSXPPUBASE] = BSX.sat_stream1.get(); |
947 | } |
948 | t = BSX.PPU[0x218C - BSXPPUBASE]; |
949 | } |
950 | else |
951 | { |
952 | t = 0; |
953 | } |
954 | break; |
955 | |
956 | // OR gate (R) |
957 | case 0x218D: |
958 | t = BSX.PPU[0x218D - BSXPPUBASE]; |
959 | BSX.PPU[0x218D - BSXPPUBASE] = 0; |
960 | break; |
961 | |
962 | //Stream 2 |
963 | // Logical Channel 1 + Data Structure (R/W) |
964 | case 0x218E: |
965 | t = BSX.PPU[0x218E - BSXPPUBASE]; |
966 | break; |
967 | |
968 | // Logical Channel 2 (R/W) [6bit] |
969 | case 0x218F: |
970 | t = BSX.PPU[0x218F - BSXPPUBASE]; |
971 | break; |
972 | |
973 | // Prefix Count (R) |
974 | case 0x2190: |
975 | if (!BSX.sat_pf_latch2_enable || !BSX.sat_dt_latch2_enable) |
976 | { |
977 | t = 0; |
978 | break; |
979 | } |
980 | |
981 | if (BSX.PPU[0x218E - BSXPPUBASE] == 0 && BSX.PPU[0x218F - BSXPPUBASE] == 0) |
982 | { |
983 | t = 1; |
984 | break; |
985 | } |
986 | |
987 | if (BSX.sat_stream2_queue <= 0) |
988 | { |
989 | BSX.sat_stream2_count++; |
990 | S9xBSXSetStream2(BSX.sat_stream2_count - 1); |
991 | } |
992 | |
993 | if (!BSX.sat_stream2_loaded && (BSX.sat_stream2_count - 1) > 0) |
994 | { |
995 | BSX.sat_stream2_count = 1; |
996 | S9xBSXSetStream2(BSX.sat_stream2_count - 1); |
997 | } |
998 | |
999 | if (BSX.sat_stream2_loaded) |
1000 | { |
1001 | if (BSX.sat_stream2_queue >= 128) |
1002 | BSX.PPU[0x2190 - BSXPPUBASE] = 0x7F; |
1003 | else |
1004 | BSX.PPU[0x2190 - BSXPPUBASE] = BSX.sat_stream2_queue; |
1005 | t = BSX.PPU[0x2190 - BSXPPUBASE]; |
1006 | } |
1007 | else |
1008 | t = 0; |
1009 | break; |
1010 | |
1011 | // Prefix Latch (R/W) |
1012 | case 0x2191: |
1013 | if (BSX.sat_pf_latch2_enable) |
1014 | { |
1015 | if (BSX.PPU[0x218E - BSXPPUBASE] == 0 && BSX.PPU[0x218F - BSXPPUBASE] == 0) |
1016 | { |
1017 | BSX.PPU[0x2191 - BSXPPUBASE] = 0x90; |
1018 | } |
1019 | |
1020 | if (BSX.sat_stream2_loaded) |
1021 | { |
1022 | uint8 temp = 0; |
1023 | if (BSX.sat_stream2_first) |
1024 | { |
1025 | // First packet |
1026 | temp |= 0x10; |
1027 | BSX.sat_stream2_first = FALSE; |
1028 | } |
1029 | |
1030 | BSX.sat_stream2_queue--; |
1031 | |
1032 | if (BSX.sat_stream2_queue == 0) |
1033 | { |
1034 | //Last packet |
1035 | temp |= 0x80; |
1036 | } |
1037 | |
1038 | BSX.PPU[0x2191 - BSXPPUBASE] = temp; |
1039 | } |
1040 | |
1041 | BSX.PPU[0x2193 - BSXPPUBASE] |= BSX.PPU[0x2191 - BSXPPUBASE]; |
1042 | t = BSX.PPU[0x2191 - BSXPPUBASE]; |
1043 | } |
1044 | else |
1045 | { |
1046 | t = 0; |
1047 | } |
1048 | break; |
1049 | |
1050 | // Data Latch (R/W) |
1051 | case 0x2192: |
1052 | if (BSX.sat_dt_latch2_enable) |
1053 | { |
1054 | if (BSX.PPU[0x218E - BSXPPUBASE] == 0 && BSX.PPU[0x218F - BSXPPUBASE] == 0) |
1055 | { |
1056 | BSX.PPU[0x2192 - BSXPPUBASE] = S9xBSXGetRTC(); |
1057 | } |
1058 | else if (BSX.sat_stream2_loaded) |
1059 | { |
1060 | if (BSX.sat_stream2.eof()) |
1061 | BSX.PPU[0x2192 - BSXPPUBASE] = 0xFF; |
1062 | else |
1063 | BSX.PPU[0x2192 - BSXPPUBASE] = BSX.sat_stream2.get(); |
1064 | } |
1065 | t = BSX.PPU[0x2192 - BSXPPUBASE]; |
1066 | } |
1067 | else |
1068 | { |
1069 | t = 0; |
1070 | } |
1071 | break; |
1072 | |
1073 | // OR gate (R) |
1074 | case 0x2193: |
1075 | t = BSX.PPU[0x2193 - BSXPPUBASE]; |
1076 | BSX.PPU[0x2193 - BSXPPUBASE] = 0; |
1077 | break; |
1078 | |
1079 | //Other |
1080 | // Satellaview LED / Stream Enable (R/W) [4bit] |
1081 | case 0x2194: |
1082 | t = BSX.PPU[0x2194 - BSXPPUBASE]; |
1083 | break; |
1084 | |
1085 | // Unknown |
1086 | case 0x2195: |
1087 | t = BSX.PPU[0x2195 - BSXPPUBASE]; |
1088 | break; |
1089 | |
1090 | // Satellaview Status (R) |
1091 | case 0x2196: |
1092 | t = BSX.PPU[0x2196 - BSXPPUBASE]; |
1093 | break; |
1094 | |
1095 | // Soundlink Settings (R/W) |
1096 | case 0x2197: |
1097 | t = BSX.PPU[0x2197 - BSXPPUBASE]; |
1098 | break; |
1099 | |
1100 | // Serial I/O - Serial Number (R/W) |
1101 | case 0x2198: |
1102 | t = BSX.PPU[0x2198 - BSXPPUBASE]; |
1103 | break; |
1104 | |
1105 | // Serial I/O - Unknown (R/W) |
1106 | case 0x2199: |
1107 | t = BSX.PPU[0x2199 - BSXPPUBASE]; |
1108 | break; |
1109 | |
1110 | default: |
1111 | t = OpenBus; |
1112 | break; |
1113 | } |
1114 | |
1115 | return (t); |
1116 | } |
1117 | |
1118 | void S9xSetBSXPPU (uint8 byte, uint16 address) |
1119 | { |
1120 | // known write registers |
1121 | switch (address) |
1122 | { |
1123 | //Stream 1 |
1124 | // Logical Channel 1 + Data Structure (R/W) |
1125 | case 0x2188: |
1126 | if (BSX.PPU[0x2188 - BSXPPUBASE] == byte) |
1127 | { |
1128 | BSX.sat_stream1_count = 0; |
1129 | } |
1130 | BSX.PPU[0x2188 - BSXPPUBASE] = byte; |
1131 | break; |
1132 | |
1133 | // Logical Channel 2 (R/W) [6bit] |
1134 | case 0x2189: |
1135 | if (BSX.PPU[0x2188 - BSXPPUBASE] == (byte & 0x3F)) |
1136 | { |
1137 | BSX.sat_stream1_count = 0; |
1138 | } |
1139 | BSX.PPU[0x2189 - BSXPPUBASE] = byte & 0x3F; |
1140 | break; |
1141 | |
1142 | // Prefix Latch (R/W) |
1143 | case 0x218B: |
1144 | BSX.sat_pf_latch1_enable = (byte != 0); |
1145 | break; |
1146 | |
1147 | // Data Latch (R/W) |
1148 | case 0x218C: |
1149 | if (BSX.PPU[0x2188 - BSXPPUBASE] == 0 && BSX.PPU[0x2189 - BSXPPUBASE] == 0) |
1150 | { |
1151 | BSX.out_index = 0; |
1152 | } |
1153 | BSX.sat_dt_latch1_enable = (byte != 0); |
1154 | break; |
1155 | |
1156 | //Stream 2 |
1157 | // Logical Channel 1 + Data Structure (R/W) |
1158 | case 0x218E: |
1159 | if (BSX.PPU[0x218E - BSXPPUBASE] == byte) |
1160 | { |
1161 | BSX.sat_stream2_count = 0; |
1162 | } |
1163 | BSX.PPU[0x218E - BSXPPUBASE] = byte; |
1164 | break; |
1165 | |
1166 | // Logical Channel 2 (R/W) [6bit] |
1167 | case 0x218F: |
1168 | if (BSX.PPU[0x218F - BSXPPUBASE] == (byte & 0x3F)) |
1169 | { |
1170 | BSX.sat_stream2_count = 0; |
1171 | } |
1172 | BSX.PPU[0x218F - BSXPPUBASE] = byte & 0x3F; |
1173 | break; |
1174 | |
1175 | // Prefix Latch (R/W) |
1176 | case 0x2191: |
1177 | BSX.sat_pf_latch2_enable = (byte != 0); |
1178 | break; |
1179 | |
1180 | // Data Latch (R/W) |
1181 | case 0x2192: |
1182 | if (BSX.PPU[0x218E - BSXPPUBASE] == 0 && BSX.PPU[0x218F - BSXPPUBASE] == 0) |
1183 | { |
1184 | BSX.out_index = 0; |
1185 | } |
1186 | BSX.sat_dt_latch2_enable = (byte != 0); |
1187 | break; |
1188 | |
1189 | //Other |
1190 | // Satellaview LED / Stream Enable (R/W) [4bit] |
1191 | case 0x2194: |
1192 | BSX.PPU[0x2194 - BSXPPUBASE] = byte & 0x0F; |
1193 | break; |
1194 | |
1195 | // Soundlink Settings (R/W) |
1196 | case 0x2197: |
1197 | BSX.PPU[0x2197 - BSXPPUBASE] = byte; |
1198 | break; |
1199 | } |
1200 | } |
1201 | |
1202 | uint8 * S9xGetBasePointerBSX (uint32 address) |
1203 | { |
1204 | return (MapROM); |
1205 | } |
1206 | |
1207 | static bool8 BSX_LoadBIOS (void) |
1208 | { |
1209 | FILE *fp; |
1210 | char path[PATH_MAX + 1], name[PATH_MAX + 1]; |
1211 | bool8 r = FALSE; |
1212 | |
1213 | strcpy(path, S9xGetDirectory(BIOS_DIR)); |
1214 | strcat(path, SLASH_STR); |
1215 | strcpy(name, path); |
1216 | strcat(name, "BS-X.bin" ); |
1217 | |
1218 | fp = fopen(name, "rb" ); |
1219 | if (!fp) |
1220 | { |
1221 | strcpy(name, path); |
1222 | strcat(name, "BS-X.bios" ); |
1223 | fp = fopen(name, "rb" ); |
1224 | } |
1225 | |
1226 | if (fp) |
1227 | { |
1228 | size_t size; |
1229 | |
1230 | size = fread((void *) BIOSROM, 1, BIOS_SIZE, fp); |
1231 | fclose(fp); |
1232 | if (size == BIOS_SIZE) |
1233 | r = TRUE; |
1234 | } |
1235 | |
1236 | #ifdef BSX_DEBUG |
1237 | if (r) |
1238 | printf("BS: BIOS found.\n" ); |
1239 | else |
1240 | printf("BS: BIOS not found!\n" ); |
1241 | #endif |
1242 | |
1243 | return (r); |
1244 | } |
1245 | |
1246 | static bool8 is_BSX_BIOS (const uint8 *data, uint32 size) |
1247 | { |
1248 | if (size == BIOS_SIZE && strncmp((char *) (data + 0x7FC0), "Satellaview BS-X " , 21) == 0) |
1249 | return (TRUE); |
1250 | else |
1251 | return (FALSE); |
1252 | } |
1253 | |
1254 | void S9xInitBSX (void) |
1255 | { |
1256 | Settings.BS = FALSE; |
1257 | |
1258 | if (is_BSX_BIOS(Memory.ROM,Memory.CalculatedSize)) |
1259 | { |
1260 | // BS-X itself |
1261 | |
1262 | Settings.BS = TRUE; |
1263 | Settings.BSXItself = TRUE; |
1264 | |
1265 | Memory.LoROM = TRUE; |
1266 | Memory.HiROM = FALSE; |
1267 | |
1268 | memmove(BIOSROM, Memory.ROM, BIOS_SIZE); |
1269 | |
1270 | FlashMode = FALSE; |
1271 | FlashSize = FLASH_SIZE; |
1272 | |
1273 | BSX.bootup = TRUE; |
1274 | } |
1275 | else |
1276 | { |
1277 | Settings.BSXItself = FALSE; |
1278 | |
1279 | int r1, r2; |
1280 | |
1281 | r1 = (is_bsx(Memory.ROM + 0x7FC0) == 1); |
1282 | r2 = (is_bsx(Memory.ROM + 0xFFC0) == 1); |
1283 | Settings.BS = (r1 | r2) ? TRUE : FALSE; |
1284 | |
1285 | if (Settings.BS) |
1286 | { |
1287 | // BS games |
1288 | |
1289 | Memory.LoROM = r1 ? TRUE : FALSE; |
1290 | Memory.HiROM = r2 ? TRUE : FALSE; |
1291 | |
1292 | uint8 * = r1 ? Memory.ROM + 0x7FC0 : Memory.ROM + 0xFFC0; |
1293 | |
1294 | FlashMode = (header[0x18] & 0xEF) == 0x20 ? FALSE : TRUE; |
1295 | FlashSize = FLASH_SIZE; |
1296 | |
1297 | // Fix Block Allocation Flags |
1298 | // (for games that don't have it setup properly, |
1299 | // for exemple when taken seperately from the upper memory of the Memory Pack, |
1300 | // else the game will error out on BS-X) |
1301 | for (; (((header[0x10] & 1) == 0) && header[0x10] != 0); (header[0x10] >>= 1)); |
1302 | |
1303 | #ifdef BSX_DEBUG |
1304 | for (int i = 0; i <= 0x1F; i++) |
1305 | printf("BS: ROM Header %02X: %02X\n" , i, header[i]); |
1306 | printf("BS: FlashMode: %d, FlashSize: %x\n" , FlashMode, FlashSize); |
1307 | #endif |
1308 | |
1309 | BSX.bootup = Settings.BSXBootup; |
1310 | |
1311 | if (!BSX_LoadBIOS() && !is_BSX_BIOS(BIOSROM,BIOS_SIZE)) |
1312 | { |
1313 | BSX.bootup = FALSE; |
1314 | memset(BIOSROM, 0, BIOS_SIZE); |
1315 | } |
1316 | } |
1317 | } |
1318 | |
1319 | if (Settings.BS) |
1320 | { |
1321 | MapROM = NULL; |
1322 | FlashROM = Memory.ROM; |
1323 | /* |
1324 | time_t t; |
1325 | struct tm *tmr; |
1326 | |
1327 | time(&t); |
1328 | tmr = localtime(&t); |
1329 | |
1330 | BSX_RTC.ticks = 0; |
1331 | memcpy(BSX.test2192, init2192, sizeof(init2192)); |
1332 | BSX.test2192[10] = BSX_RTC.seconds = tmr->tm_sec; |
1333 | BSX.test2192[11] = BSX_RTC.minutes = tmr->tm_min; |
1334 | BSX.test2192[12] = BSX_RTC.hours = tmr->tm_hour; |
1335 | #ifdef BSX_DEBUG |
1336 | printf("BS: Current Time: %02d:%02d:%02d\n", BSX_RTC.hours, BSX_RTC.minutes, BSX_RTC.seconds); |
1337 | #endif |
1338 | */ |
1339 | SNESGameFixes.SRAMInitialValue = 0x00; |
1340 | } |
1341 | } |
1342 | |
1343 | void S9xResetBSX (void) |
1344 | { |
1345 | if (Settings.BSXItself) |
1346 | memset(Memory.ROM, 0, FLASH_SIZE); |
1347 | |
1348 | memset(BSX.PPU, 0, sizeof(BSX.PPU)); |
1349 | memset(BSX.MMC, 0, sizeof(BSX.MMC)); |
1350 | memset(BSX.prevMMC, 0, sizeof(BSX.prevMMC)); |
1351 | |
1352 | BSX.dirty = FALSE; |
1353 | BSX.dirty2 = FALSE; |
1354 | BSX.flash_enable = FALSE; |
1355 | BSX.write_enable = FALSE; |
1356 | BSX.read_enable = FALSE; |
1357 | BSX.flash_command = 0; |
1358 | BSX.old_write = 0; |
1359 | BSX.new_write = 0; |
1360 | |
1361 | BSX.out_index = 0; |
1362 | memset(BSX.output, 0, sizeof(BSX.output)); |
1363 | |
1364 | // starting from the bios |
1365 | BSX.MMC[0x02] = BSX.MMC[0x03] = BSX.MMC[0x05] = BSX.MMC[0x06] = 0x80; |
1366 | BSX.MMC[0x09] = BSX.MMC[0x0B] = 0x80; |
1367 | |
1368 | BSX.MMC[0x07] = BSX.MMC[0x08] = 0x80; |
1369 | BSX.MMC[0x0E] = 0x80; |
1370 | |
1371 | // default register values |
1372 | BSX.PPU[0x2196 - BSXPPUBASE] = 0x10; |
1373 | BSX.PPU[0x2197 - BSXPPUBASE] = 0x80; |
1374 | |
1375 | // stream reset |
1376 | BSX.sat_pf_latch1_enable = BSX.sat_dt_latch1_enable = FALSE; |
1377 | BSX.sat_pf_latch2_enable = BSX.sat_dt_latch2_enable = FALSE; |
1378 | |
1379 | BSX.sat_stream1_loaded = BSX.sat_stream2_loaded = FALSE; |
1380 | BSX.sat_stream1_first = BSX.sat_stream2_first = FALSE; |
1381 | BSX.sat_stream1_count = BSX.sat_stream2_count = 0; |
1382 | |
1383 | if (BSX.sat_stream1.is_open()) |
1384 | BSX.sat_stream1.close(); |
1385 | |
1386 | if (BSX.sat_stream2.is_open()) |
1387 | BSX.sat_stream2.close(); |
1388 | |
1389 | if (Settings.BS) |
1390 | BSX_Map(); |
1391 | } |
1392 | |
1393 | void S9xBSXPostLoadState (void) |
1394 | { |
1395 | uint8 temp[16]; |
1396 | bool8 pd1, pd2; |
1397 | |
1398 | pd1 = BSX.dirty; |
1399 | pd2 = BSX.dirty2; |
1400 | memcpy(temp, BSX.MMC, sizeof(BSX.MMC)); |
1401 | |
1402 | memcpy(BSX.MMC, BSX.prevMMC, sizeof(BSX.MMC)); |
1403 | BSX_Map(); |
1404 | |
1405 | memcpy(BSX.MMC, temp, sizeof(BSX.MMC)); |
1406 | BSX.dirty = pd1; |
1407 | BSX.dirty2 = pd2; |
1408 | } |
1409 | |
1410 | static bool valid_normal_bank (unsigned char bankbyte) |
1411 | { |
1412 | switch (bankbyte) |
1413 | { |
1414 | case 32: case 33: case 48: case 49: |
1415 | return (true); |
1416 | break; |
1417 | } |
1418 | |
1419 | return (false); |
1420 | } |
1421 | |
1422 | static int is_bsx (unsigned char *p) |
1423 | { |
1424 | if ((p[26] == 0x33 || p[26] == 0xFF) && (!p[21] || (p[21] & 131) == 128) && valid_normal_bank(p[24])) |
1425 | { |
1426 | unsigned char m = p[22]; |
1427 | |
1428 | if (!m && !p[23]) |
1429 | return (2); |
1430 | |
1431 | if ((m == 0xFF && p[23] == 0xFF) || (!(m & 0xF) && ((m >> 4) - 1 < 12))) |
1432 | return (1); |
1433 | } |
1434 | |
1435 | return (0); |
1436 | } |
1437 | |