2 * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
4 * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5 * Jerremy Koot (jkoot@snes9x.com)
7 * Super FX C emulator code
8 * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
10 * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
12 * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
13 * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
14 * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
16 * DOS port code contains the works of other authors. See headers in
19 * Snes9x homepage: http://www.snes9x.com
21 * Permission to use, copy, modify and distribute Snes9x in both binary and
22 * source form, for non-commercial purposes, is hereby granted without fee,
23 * providing that this license information and copyright notice appear with
24 * all copies and any derived work.
26 * This software is provided 'as-is', without any express or implied
27 * warranty. In no event shall the authors be held liable for any damages
28 * arising from the use of this software.
30 * Snes9x is freeware for PERSONAL USE only. Commercial users should
31 * seek permission of the copyright holders first. Commercial use includes
32 * charging money for Snes9x or software derived from Snes9x.
34 * The copyright holders request that bug fixes and improvements to the code
35 * should be forwarded to them so everyone can benefit from the modifications
38 * Super NES and Super Nintendo Entertainment System are trademarks of
39 * Nintendo Co., Limited and its subsidiary companies.
62 extern struct FxInit_s SuperFX;
65 extern uint8 *SFXPlotTable;
69 static uint8 bytes0x2000 [0x2000];
71 extern char *rom_filename;
72 extern bool8 LoadZip(const char* , int32 *, int32 *);
74 bool8_32 CMemory::AllASCII (uint8 *b, int size)
76 for (int i = 0; i < size; i++)
78 if (b[i] < 32 || b[i] > 126)
84 int CMemory::ScoreHiROM (bool8_32 skip_header)
87 int o = skip_header ? 0xff00 + 0x200 : 0xff00;
89 if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) +
90 Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff)
93 if (Memory.ROM [o + 0xda] == 0x33)
95 if ((Memory.ROM [o + 0xd5] & 0xf) < 4)
97 if (!(Memory.ROM [o + 0xfd] & 0x80))
99 if (CalculatedSize > 1024 * 1024 * 3)
101 if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48)
103 if (!AllASCII (&Memory.ROM [o + 0xb0], 6))
105 if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1))
111 int CMemory::ScoreLoROM (bool8_32 skip_header)
114 int o = skip_header ? 0x7f00 + 0x200 : 0x7f00;
116 if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) +
117 Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff)
120 if (Memory.ROM [o + 0xda] == 0x33)
122 if ((Memory.ROM [o + 0xd5] & 0xf) < 4)
124 if (CalculatedSize <= 1024 * 1024 * 16)
126 if (!(Memory.ROM [o + 0xfd] & 0x80))
128 if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48)
130 if (!AllASCII (&Memory.ROM [o + 0xb0], 6))
132 if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1))
138 char *CMemory::Safe (const char *s)
140 static char *safe = NULL;
141 static int safe_len = 0;
143 int len = strlen (s);
144 if (!safe || len + 1 > safe_len)
147 free ((char *) safe);
148 safe = (char *) malloc (safe_len = len + 1);
151 for (int i = 0; i < len; i++)
153 if (s [i] >= 32 && s [i] < 127)
162 /**********************************************************************************************/
164 /* This function allocates all the memory needed by the emulator */
165 /**********************************************************************************************/
166 bool8_32 CMemory::Init ()
168 RAM = (uint8 *) malloc (0x20000);
169 SRAM = (uint8 *) malloc (0x20000);
170 VRAM = (uint8 *) malloc (0x10000);
171 ROM = (uint8 *) malloc (MAX_ROM_SIZE + 0x200 + 0x8000);
174 IPPU.TileCache [TILE_2BIT] = (uint8 *) malloc (MAX_2BIT_TILES * 128);
175 IPPU.TileCache [TILE_4BIT] = (uint8 *) malloc (MAX_4BIT_TILES * 128);
176 IPPU.TileCache [TILE_8BIT] = (uint8 *) malloc (MAX_8BIT_TILES * 128);
178 IPPU.TileCached [TILE_2BIT] = (uint8 *) malloc (MAX_2BIT_TILES);
179 IPPU.TileCached [TILE_4BIT] = (uint8 *) malloc (MAX_4BIT_TILES);
180 IPPU.TileCached [TILE_8BIT] = (uint8 *) malloc (MAX_8BIT_TILES);
182 if (!RAM || !SRAM || !VRAM || !ROM ||
183 !IPPU.TileCache [TILE_2BIT] || !IPPU.TileCache [TILE_4BIT] ||
184 !IPPU.TileCache [TILE_8BIT] || !IPPU.TileCached [TILE_2BIT] ||
185 !IPPU.TileCached [TILE_4BIT] || !IPPU.TileCached [TILE_8BIT])
191 // FillRAM uses first 32K of ROM image area, otherwise space just
192 // wasted. Might be read by the SuperFX code.
196 // Add 0x8000 to ROM image pointer to stop SuperFX code accessing
197 // unallocated memory (can cause crash on some ports).
200 C4RAM = ROM + 0x400000 + 8192 * 8;
206 SFXPlotTable = ROM + 0x400000;
208 SuperFX.pvRegisters = &Memory.FillRAM [0x3000];
209 SuperFX.nRamBanks = 1;
210 SuperFX.pvRam = ::SRAM;
211 SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024);
212 SuperFX.pvRom = (uint8 *) ROM;
215 ZeroMemory (IPPU.TileCached [TILE_2BIT], MAX_2BIT_TILES);
216 ZeroMemory (IPPU.TileCached [TILE_4BIT], MAX_4BIT_TILES);
217 ZeroMemory (IPPU.TileCached [TILE_8BIT], MAX_8BIT_TILES);
225 void CMemory::Deinit ()
234 free ((char *) SRAM);
239 free ((char *) VRAM);
249 if (IPPU.TileCache [TILE_2BIT])
251 free ((char *) IPPU.TileCache [TILE_2BIT]);
252 IPPU.TileCache [TILE_2BIT] = NULL;
254 if (IPPU.TileCache [TILE_4BIT])
256 free ((char *) IPPU.TileCache [TILE_4BIT]);
257 IPPU.TileCache [TILE_4BIT] = NULL;
259 if (IPPU.TileCache [TILE_8BIT])
261 free ((char *) IPPU.TileCache [TILE_8BIT]);
262 IPPU.TileCache [TILE_8BIT] = NULL;
265 if (IPPU.TileCached [TILE_2BIT])
267 free ((char *) IPPU.TileCached [TILE_2BIT]);
268 IPPU.TileCached [TILE_2BIT] = NULL;
270 if (IPPU.TileCached [TILE_4BIT])
272 free ((char *) IPPU.TileCached [TILE_4BIT]);
273 IPPU.TileCached [TILE_4BIT] = NULL;
275 if (IPPU.TileCached [TILE_8BIT])
277 free ((char *) IPPU.TileCached [TILE_8BIT]);
278 IPPU.TileCached [TILE_8BIT] = NULL;
284 void CMemory::FreeSDD1Data ()
288 free ((char *) SDD1Index);
293 free ((char *) SDD1Data);
298 /**********************************************************************************************/
300 /**********************************************************************************************/
301 int checkzip( char * fn )
303 int cnt = strlen(fn);
304 if( ( (fn[cnt-1] == 'p') || (fn[cnt-1] == 'P') ) &&
305 ( (fn[cnt-2] == 'i') || (fn[cnt-2] == 'I') ) &&
306 ( (fn[cnt-3] == 'z') || (fn[cnt-3] == 'Z') ) ){
313 /**********************************************************************************************/
315 /* This function loads a Snes-Backup image */
316 /**********************************************************************************************/
318 #pragma warning(disable : 4101)
319 #pragma warning(disable : 4700)
321 bool8_32 CMemory::LoadROM (const char *filename)
323 unsigned long FileSize = 0;
326 bool8_32 Interleaved = FALSE;
327 bool8_32 Tales = FALSE;
328 char dir [_MAX_DIR + 1];
329 char drive [_MAX_DRIVE + 1];
330 char name [_MAX_FNAME + 1];
331 char ext [_MAX_EXT + 1];
332 char fname [_MAX_PATH + 1];
335 memset (&SNESGameFixes, 0, sizeof(SNESGameFixes));
336 SNESGameFixes.SRAMInitialValue = 0x60;
338 memset (bytes0x2000, 0, 0x2000);
339 CPU.TriedInterleavedMode2 = FALSE;
343 PathSplit(filename, drive, dir, name, ext);
344 PathMake(fname, drive, dir, name, ext);
346 int32 TotalFileSize = 0;
349 if( checkzip( fname ) )
351 if (!LoadZip (fname, &TotalFileSize, &HeaderCount))
354 strcpy (ROMFilename, fname);
359 if ((ROMFile = OPEN_STREAM (fname, "rb")) == NULL)
362 strcpy (ROMFilename, fname);
366 bool8_32 more = FALSE;
370 FileSize = READ_STREAM (ptr, MAX_ROM_SIZE + 0x200 - (ptr - ROM), ROMFile);
371 CLOSE_STREAM (ROMFile);
372 int calc_size = (FileSize / 0x2000) * 0x2000;
374 if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) ||
375 Settings.ForceHeader)
377 memmove (ptr, ptr + 512, calc_size);
382 TotalFileSize += FileSize;
385 if (ptr - ROM < MAX_ROM_SIZE + 0x200 &&
386 (isdigit (ext [0]) && ext [1] == 0 && ext [0] < '9'))
390 PathMake(fname, drive, dir, name, ext);
393 if (ptr - ROM < MAX_ROM_SIZE + 0x200 &&
394 (((len = strlen (name)) == 7 || len == 8) &&
395 strncasecmp (name, "sf", 2) == 0 &&
396 isdigit (name [2]) && isdigit (name [3]) && isdigit (name [4]) &&
397 isdigit (name [5]) && isalpha (name [len - 1])))
401 PathMake(fname, drive, dir, name, ext);
405 } while (more && (ROMFile = OPEN_STREAM (fname, "rb")) != NULL);
408 if (HeaderCount == 0)
409 S9xMessage (S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found.");
412 if (HeaderCount == 1)
413 S9xMessage (S9X_INFO, S9X_HEADERS_INFO,
414 "Found ROM file header (and ignored it).");
416 S9xMessage (S9X_INFO, S9X_HEADERS_INFO,
417 "Found multiple ROM file headers (and ignored them).");
420 CheckForIPSPatch (filename, HeaderCount != 0, TotalFileSize);
421 int orig_hi_score, orig_lo_score;
422 int hi_score, lo_score;
424 orig_hi_score = hi_score = ScoreHiROM (FALSE);
425 orig_lo_score = lo_score = ScoreLoROM (FALSE);
427 if (HeaderCount == 0 && !Settings.ForceNoHeader &&
428 ((hi_score > lo_score && ScoreHiROM (TRUE) > hi_score) ||
429 (hi_score <= lo_score && ScoreLoROM (TRUE) > lo_score)))
431 memmove (Memory.ROM, Memory.ROM + 512, TotalFileSize - 512);
432 TotalFileSize -= 512;
433 S9xMessage (S9X_INFO, S9X_HEADER_WARNING,
434 "Try specifying the -nhd command line option if the game doesn't work\n");
437 CalculatedSize = (TotalFileSize / 0x2000) * 0x2000;
438 ZeroMemory (ROM + CalculatedSize, MAX_ROM_SIZE - CalculatedSize);
440 // Check for cherryroms.com DAIKAIJYUMONOGATARI2
442 if (CalculatedSize == 0x500000 &&
443 strncmp ((const char *)&ROM [0x40ffc0], "DAIKAIJYUMONOGATARI2", 20) == 0 &&
444 strncmp ((const char *)&ROM [0x40ffb0], "18AE6J", 6) == 0 &&
445 memcmp (&ROM[0x40ffb0], &ROM [0xffb0], 0x30))
447 memmove (&ROM[0x100000], ROM, 0x500000);
448 memmove (ROM, &ROM[0x500000], 0x100000);
451 Interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2;
452 if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score))
457 // Ignore map type byte if not 0x2x or 0x3x
458 if ((ROM [0x7fd5] & 0xf0) == 0x20 || (ROM [0x7fd5] & 0xf0) == 0x30)
460 switch (ROM [0x7fd5] & 0xf)
463 if (strncmp ((char *) &ROM [0x7fc0], "TREASURE HUNTER G", 17) != 0)
468 if (!Settings.ForceLoROM &&
469 strncmp ((char *) &ROM [0x7fc0], "SUPER FORMATION SOCCE", 21) != 0 &&
470 strncmp ((char *) &ROM [0x7fc0], "Star Ocean", 10) != 0)
486 if ((ROM [0xffd5] & 0xf0) == 0x20 || (ROM [0xffd5] & 0xf0) == 0x30)
488 switch (ROM [0xffd5] & 0xf)
501 if (!Settings.ForceHiROM && !Settings.ForceLoROM &&
502 !Settings.ForceInterleaved && !Settings.ForceInterleaved2 &&
503 !Settings.ForceNotInterleaved && !Settings.ForcePAL &&
504 !Settings.ForceSuperFX && !Settings.ForceDSP1 &&
505 !Settings.ForceSA1 && !Settings.ForceC4 &&
508 if (strncmp ((char *) &ROM [0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0)
515 if (strncmp ((char *) &ROM [0x7fc0], "SP MOMOTAROU DENTETSU2", 22) == 0)
522 if (CalculatedSize == 0x100000 &&
523 strncmp ((char *) &ROM [0xffc0], "WWF SUPER WRESTLEMANIA", 22) == 0)
527 memmove (&ROM[0x100000] , ROM, 0x100000);
528 for (cvcount = 0; cvcount < 16; cvcount++)
530 memmove (&ROM[0x8000 * cvcount], &ROM[0x10000 * cvcount + 0x100000 + 0x8000], 0x8000);
531 memmove (&ROM[0x8000 * cvcount + 0x80000], &ROM[0x10000 * cvcount + 0x100000], 0x8000);
535 ZeroMemory (ROM + CalculatedSize, MAX_ROM_SIZE - CalculatedSize);
539 if (!Settings.ForceNotInterleaved && Interleaved)
541 CPU.TriedInterleavedMode2 = TRUE;
542 S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO,
543 "ROM image is in interleaved format - converting...");
545 int nblocks = CalculatedSize >> 16;
549 while (nblocks <= step)
559 for (i = 0; i < 0x40; i += 2)
561 blocks [i + 0] = (i >> 1) + 0x20;
562 blocks [i + 1] = (i >> 1) + 0x00;
564 for (i = 0; i < 0x80; i += 2)
566 blocks [i + 0x40] = (i >> 1) + 0x80;
567 blocks [i + 0x41] = (i >> 1) + 0x40;
573 if (Settings.ForceInterleaved2)
575 for (i = 0; i < nblocks * 2; i++)
577 blocks [i] = (i & ~0x1e) | ((i & 2) << 2) | ((i & 4) << 2) |
578 ((i & 8) >> 2) | ((i & 16) >> 2);
588 for (i = 0; i < nblocks; i++)
590 blocks [i * 2] = i + nblocks;
591 blocks [i * 2 + 1] = i;
595 uint8 *tmp = (uint8 *) malloc (0x8000);
598 for (i = 0; i < nblocks * 2; i++)
600 for (int j = i; j < nblocks * 2; j++)
604 memmove (tmp, &ROM [blocks [j] * 0x8000], 0x8000);
605 memmove (&ROM [blocks [j] * 0x8000],
606 &ROM [blocks [i] * 0x8000], 0x8000);
607 memmove (&ROM [blocks [i] * 0x8000], tmp, 0x8000);
608 uint8 b = blocks [j];
609 blocks [j] = blocks [i];
618 hi_score = ScoreHiROM (FALSE);
619 lo_score = ScoreLoROM (FALSE);
622 (lo_score >= hi_score || hi_score < 0)) ||
624 (hi_score > lo_score || lo_score < 0)))
626 if (retry_count == 0)
628 S9xMessage (S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO,
629 "ROM lied about its type! Trying again.");
630 Settings.ForceNotInterleaved = TRUE;
631 Settings.ForceInterleaved = FALSE;
640 S9xLoadCheatFile (S9xGetFilename(FILE_CHT));
649 void S9xDeinterleaveMode2 ()
651 S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO,
652 "ROM image is in interleaved format - converting...");
654 int nblocks = Memory.CalculatedSize >> 15;
657 while (nblocks <= step)
664 for (i = 0; i < nblocks * 2; i++)
666 blocks [i] = (i & ~0x1e) | ((i & 2) << 2) | ((i & 4) << 2) |
667 ((i & 8) >> 2) | ((i & 16) >> 2);
670 uint8 *tmp = (uint8 *) malloc (0x8000);
674 for (i = 0; i < nblocks * 2; i++)
676 for (int j = i; j < nblocks * 2; j++)
680 memmove (tmp, &Memory.ROM [blocks [j] * 0x8000], 0x8000);
681 memmove (&Memory.ROM [blocks [j] * 0x8000],
682 &Memory.ROM [blocks [i] * 0x8000], 0x8000);
683 memmove (&Memory.ROM [blocks [i] * 0x8000], tmp, 0x8000);
684 uint8 b = blocks [j];
685 blocks [j] = blocks [i];
693 Memory.InitROM (FALSE);
697 void CMemory::InitROM (bool8_32 Interleaved)
700 SuperFX.nRomBanks = CalculatedSize >> 15;
702 Settings.MultiPlayer5Master = Settings.MultiPlayer5;
703 Settings.MouseMaster = Settings.Mouse;
704 Settings.SuperScopeMaster = Settings.SuperScope;
705 Settings.DSP1Master = Settings.ForceDSP1;
706 Settings.SuperFX = FALSE;
707 Settings.SA1 = FALSE;
709 Settings.SDD1 = FALSE;
710 Settings.SRTC = FALSE;
712 ZeroMemory (BlockIsRAM, MEMMAP_NUM_BLOCKS);
713 ZeroMemory (BlockIsROM, MEMMAP_NUM_BLOCKS);
716 memset (ROMId, 0, 5);
717 memset (CompanyId, 0, 3);
721 Memory.SRAMSize = ROM [0xffd8];
722 strncpy (ROMName, (char *) &ROM[0xffc0], ROM_NAME_LEN - 1);
723 ROMSpeed = ROM [0xffd5];
724 ROMType = ROM [0xffd6];
725 ROMSize = ROM [0xffd7];
726 ROMChecksum = ROM [0xffde] + (ROM [0xffdf] << 8);
727 ROMComplementChecksum = ROM [0xffdc] + (ROM [0xffdd] << 8);
729 memmove (ROMId, &ROM [0xffb2], 4);
730 memmove (CompanyId, &ROM [0xffb0], 2);
732 // Try to auto-detect the DSP1 chip
733 if (!Settings.ForceNoDSP1 &&
734 (ROMType & 0xf) >= 3 && (ROMType & 0xf0) == 0)
735 Settings.DSP1Master = TRUE;
737 Settings.SDD1 = Settings.ForceSDD1;
738 if ((ROMType & 0xf0) == 0x40)
739 Settings.SDD1 = !Settings.ForceNoSDD1;
744 if ((ROMSpeed & ~0x10) == 0x25)
745 TalesROMMap (Interleaved);
747 if ((ROMSpeed & ~0x10) == 0x22 &&
748 strncmp (ROMName, "Super Street Fighter", 20) != 0)
757 Memory.HiROM = FALSE;
758 Memory.SRAMSize = ROM [0x7fd8];
759 ROMSpeed = ROM [0x7fd5];
760 ROMType = ROM [0x7fd6];
761 ROMSize = ROM [0x7fd7];
762 ROMChecksum = ROM [0x7fde] + (ROM [0x7fdf] << 8);
763 ROMComplementChecksum = ROM [0x7fdc] + (ROM [0x7fdd] << 8);
764 memmove (ROMId, &ROM [0x7fb2], 4);
765 memmove (CompanyId, &ROM [0x7fb0], 2);
767 strncpy (ROMName, (char *) &ROM[0x7fc0], ROM_NAME_LEN - 1);
768 Settings.SuperFX = Settings.ForceSuperFX;
770 if ((ROMType & 0xf0) == 0x10)
771 Settings.SuperFX = !Settings.ForceNoSuperFX;
773 // Try to auto-detect the DSP1 chip
774 if (!Settings.ForceNoDSP1 &&
775 (ROMType & 0xf) >= 3 && (ROMType & 0xf0) == 0)
776 Settings.DSP1Master = TRUE;
778 Settings.SDD1 = Settings.ForceSDD1;
779 if ((ROMType & 0xf0) == 0x40)
780 Settings.SDD1 = !Settings.ForceNoSDD1;
785 Settings.C4 = Settings.ForceC4;
786 if ((ROMType & 0xf0) == 0xf0 &&
787 (strncmp (ROMName, "MEGAMAN X", 9) == 0 ||
788 strncmp (ROMName, "ROCKMAN X", 9) == 0))
790 Settings.C4 = !Settings.ForceNoC4;
793 if (Settings.SuperFX)
795 //::SRAM = ROM + 1024 * 1024 * 4;
797 Settings.MultiPlayer5Master = FALSE;
798 //Settings.MouseMaster = FALSE;
799 //Settings.SuperScopeMaster = FALSE;
800 Settings.DSP1Master = FALSE;
801 Settings.SA1 = FALSE;
803 Settings.SDD1 = FALSE;
806 if (Settings.ForceSA1 ||
807 (!Settings.ForceNoSA1 && (ROMSpeed & ~0x10) == 0x23 &&
808 (ROMType & 0xf) > 3 && (ROMType & 0xf0) == 0x30))
811 Settings.MultiPlayer5Master = FALSE;
812 //Settings.MouseMaster = FALSE;
813 //Settings.SuperScopeMaster = FALSE;
814 Settings.DSP1Master = FALSE;
816 Settings.SDD1 = FALSE;
820 if ((ROMSpeed & ~0x10) == 0x25)
821 TalesROMMap (Interleaved);
823 if (strncmp ((char *) &Memory.ROM [0x7fc0], "SOUND NOVEL-TCOOL", 17) == 0 ||
824 strncmp ((char *) &Memory.ROM [0x7fc0], "DERBY STALLION 96", 17) == 0)
827 Settings.DSP1Master = FALSE;
830 if (strncmp ((char *) &Memory.ROM [0x7fc0], "THOROUGHBRED BREEDER3", 21) == 0 ||
831 strncmp ((char *) &Memory.ROM [0x7fc0], "RPG-TCOOL 2", 11) == 0)
834 Settings.DSP1Master = FALSE;
837 if (strncmp ((char *) &Memory.ROM [0x7fc0], "DEZAEMON ", 10) == 0)
839 Settings.DSP1Master = FALSE;
840 SRAM1024KLoROMMap ();
843 if (strncmp ((char *) &Memory.ROM [0x7fc0], "ADD-ON BASE CASSETE", 19) == 0)
845 Settings.MultiPlayer5Master = FALSE;
846 Settings.MouseMaster = FALSE;
847 Settings.SuperScopeMaster = FALSE;
848 Settings.DSP1Master = FALSE;
849 SufamiTurboLoROMMap();
853 if ((ROMSpeed & ~0x10) == 0x22 &&
854 strncmp (ROMName, "Super Street Fighter", 20) != 0)
863 int size = CalculatedSize;
869 uint32 remainder = CalculatedSize - size;
876 for (i = 0; i < size; i++)
879 for (i = 0; i < (int) remainder; i++)
880 sum2 += ROM [size + i];
885 if (CalculatedSize == 0x500000 && Memory.HiROM &&
886 strncmp ((const char *)&ROM[0xffb0], "18AZ", 4) == 0 &&
887 !memcmp(&ROM[0xffd5], "\x3a\xf9\x0d\x03\x00\x33\x00", 7))
890 sum1 += sum2 * (size / remainder);
895 if (Settings.ForceNTSC)
896 Settings.PAL = FALSE;
898 if (Settings.ForcePAL)
903 Settings.PAL = ROM [0xffd9] >= 2;
905 Settings.PAL = ROM [0x7fd9] >= 2;
909 Settings.FrameTime = Settings.FrameTimePAL;
910 Memory.ROMFramesPerSecond = 50;
914 Settings.FrameTime = Settings.FrameTimeNTSC;
915 Memory.ROMFramesPerSecond = 60;
918 ROMName[ROM_NAME_LEN - 1] = 0;
919 if (strlen (ROMName))
921 char *p = ROMName + strlen (ROMName) - 1;
923 while (p > ROMName && *(p - 1) == ' ')
928 if (Settings.SuperFX)
930 CPU.Memory_SRAMMask = 0xffff;
931 Memory.SRAMSize = 16;
935 CPU.Memory_SRAMMask = Memory.SRAMSize ?
936 ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0;
939 IAPU.OneCycle = ONE_APU_CYCLE;
940 Settings.Shutdown = Settings.ShutdownMaster;
942 SetDSP = &DSP1SetByte;
943 GetDSP = &DSP1GetByte;
946 sprintf (ROMName, "%s", Safe (ROMName));
947 sprintf (ROMId, "%s", Safe (ROMId));
948 sprintf (CompanyId, "%s", Safe (CompanyId));
950 sprintf (String, "\"%s\" [%s] %s, %s, Type: %s, Mode: %s, TV: %s, S-RAM: %s, ROMId: %s Company: %2.2s",
952 (ROMChecksum + ROMComplementChecksum != 0xffff ||
953 ROMChecksum != sum1) ? "bad checksum" : "checksum ok",
963 S9xMessage (S9X_INFO, S9X_ROM_INFO, String);
966 bool8_32 CMemory::LoadSRAM (const char *filename)
968 int size = Memory.SRAMSize ?
969 (1 << (Memory.SRAMSize + 3)) * 128 : 0;
971 memset (SRAM, SNESGameFixes.SRAMInitialValue, 0x20000);
979 if ((file = fopen(filename, "rb")))
981 int len = fread ((char*) ::SRAM, 1, 0x20000, file);
983 if (len - size == 512)
985 // S-RAM file has a header - remove it
986 memmove (::SRAM, ::SRAM + 512, size);
988 if (len == size + SRTC_SRAM_PAD)
990 S9xSRTCPostLoadState ();
993 rtc.mode = MODE_READ;
1000 S9xHardResetSRTC ();
1004 S9xSDD1LoadLoggedData ();
1009 bool8_32 CMemory::SaveSRAM (const char *filename)
1011 int size = Memory.SRAMSize ?
1012 (1 << (Memory.SRAMSize + 3)) * 128 : 0;
1015 size += SRTC_SRAM_PAD;
1016 S9xSRTCPreSaveState ();
1020 S9xSDD1SaveLoggedData ();
1025 if (size && *Memory.ROMFilename)
1028 if ((file = fopen (filename, "wb")))
1030 fwrite ((char *) ::SRAM, size, 1, file);
1032 #if defined(__linux)
1033 chown (filename, getuid (), getgid ());
1041 void CMemory::FixROMSpeed ()
1045 for (c = 0x800; c < 0x1000; c++)
1048 MemorySpeed [c] = (uint8) CPU.FastROMSpeed;
1052 void CMemory::WriteProtectROM ()
1054 memmove ((void *) WriteMap, (void *) Map, sizeof (Map));
1055 for (int c = 0; c < 0x1000; c++)
1058 WriteMap [c] = (uint8 *) MAP_NONE;
1062 void CMemory::MapRAM ()
1066 // Banks 7e->7f, RAM
1067 for (c = 0; c < 16; c++)
1069 Map [c + 0x7e0] = RAM;
1070 Map [c + 0x7f0] = RAM + 0x10000;
1071 BlockIsRAM [c + 0x7e0] = TRUE;
1072 BlockIsRAM [c + 0x7f0] = TRUE;
1073 BlockIsROM [c + 0x7e0] = FALSE;
1074 BlockIsROM [c + 0x7f0] = FALSE;
1077 // Banks 70->77, S-RAM
1078 for (c = 0; c < 0x80; c++)
1080 Map [c + 0x700] = (uint8 *) MAP_LOROM_SRAM;
1081 BlockIsRAM [c + 0x700] = TRUE;
1082 BlockIsROM [c + 0x700] = FALSE;
1086 void CMemory::MapExtraRAM ()
1090 // Banks 7e->7f, RAM
1091 for (c = 0; c < 16; c++)
1093 Map [c + 0x7e0] = RAM;
1094 Map [c + 0x7f0] = RAM + 0x10000;
1095 BlockIsRAM [c + 0x7e0] = TRUE;
1096 BlockIsRAM [c + 0x7f0] = TRUE;
1097 BlockIsROM [c + 0x7e0] = FALSE;
1098 BlockIsROM [c + 0x7f0] = FALSE;
1101 // Banks 70->73, S-RAM
1102 for (c = 0; c < 16; c++)
1104 Map [c + 0x700] = ::SRAM;
1105 Map [c + 0x710] = ::SRAM + 0x8000;
1106 Map [c + 0x720] = ::SRAM + 0x10000;
1107 Map [c + 0x730] = ::SRAM + 0x18000;
1109 BlockIsRAM [c + 0x700] = TRUE;
1110 BlockIsROM [c + 0x700] = FALSE;
1111 BlockIsRAM [c + 0x710] = TRUE;
1112 BlockIsROM [c + 0x710] = FALSE;
1113 BlockIsRAM [c + 0x720] = TRUE;
1114 BlockIsROM [c + 0x720] = FALSE;
1115 BlockIsRAM [c + 0x730] = TRUE;
1116 BlockIsROM [c + 0x730] = FALSE;
1120 void CMemory::LoROMMap ()
1125 // Banks 00->3f and 80->bf
1126 for (c = 0; c < 0x400; c += 16)
1128 Map [c + 0] = Map [c + 0x800] = RAM;
1129 Map [c + 1] = Map [c + 0x801] = RAM;
1130 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1131 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1133 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1134 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1135 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1136 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1137 if (Settings.DSP1Master)
1139 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1140 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1145 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_C4;
1146 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_C4;
1150 Map [c + 6] = Map [c + 0x806] = (uint8 *) bytes0x2000 - 0x6000;
1151 Map [c + 7] = Map [c + 0x807] = (uint8 *) bytes0x2000 - 0x6000;
1154 for (i = c + 8; i < c + 16; i++)
1156 Map [i] = Map [i + 0x800] = &ROM [(c << 11) % CalculatedSize] - 0x8000;
1157 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1160 for (i = c; i < c + 16; i++)
1165 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1169 if (Settings.DSP1Master)
1171 // Banks 30->3f and b0->bf
1172 for (c = 0x300; c < 0x400; c += 16)
1174 for (i = c + 8; i < c + 16; i++)
1176 Map [i] = Map [i + 0x800] = (uint8 *) MAP_DSP;
1177 BlockIsROM [i] = BlockIsROM [i + 0x800] = FALSE;
1182 // Banks 40->7f and c0->ff
1183 for (c = 0; c < 0x400; c += 16)
1185 for (i = c; i < c + 8; i++)
1186 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) % CalculatedSize];
1188 for (i = c + 8; i < c + 16; i++)
1189 Map [i + 0x400] = Map [i + 0xc00] = &ROM [((c << 11) + 0x200000) % CalculatedSize - 0x8000];
1191 for (i = c; i < c + 16; i++)
1193 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1194 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1198 if (Settings.DSP1Master)
1200 for (c = 0; c < 0x100; c++)
1202 Map [c + 0xe00] = (uint8 *) MAP_DSP;
1203 MemorySpeed [c + 0xe00] = SLOW_ONE_CYCLE;
1204 BlockIsROM [c + 0xe00] = FALSE;
1211 void CMemory::HiROMMap ()
1216 // Banks 00->3f and 80->bf
1217 for (c = 0; c < 0x400; c += 16)
1219 Map [c + 0] = Map [c + 0x800] = RAM;
1220 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1221 Map [c + 1] = Map [c + 0x801] = RAM;
1222 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1224 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1225 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1226 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1227 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1228 if (Settings.DSP1Master)
1230 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1231 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1235 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1236 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1239 for (i = c + 8; i < c + 16; i++)
1241 Map [i] = Map [i + 0x800] = &ROM [(c << 12) % CalculatedSize];
1242 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1245 for (i = c; i < c + 16; i++)
1250 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1254 // Banks 30->3f and b0->bf, address ranges 6000->7fff is S-RAM.
1255 for (c = 0; c < 16; c++)
1257 Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1258 Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1259 Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1260 Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1261 BlockIsRAM [0x306 + (c << 4)] = TRUE;
1262 BlockIsRAM [0x307 + (c << 4)] = TRUE;
1263 BlockIsRAM [0xb06 + (c << 4)] = TRUE;
1264 BlockIsRAM [0xb07 + (c << 4)] = TRUE;
1267 // Banks 40->7f and c0->ff
1268 for (c = 0; c < 0x400; c += 16)
1270 for (i = c; i < c + 16; i++)
1272 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1273 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1274 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1282 void CMemory::TalesROMMap (bool8_32 Interleaved)
1287 uint32 OFFSET0 = 0x400000;
1288 uint32 OFFSET1 = 0x400000;
1289 uint32 OFFSET2 = 0x000000;
1298 // Banks 00->3f and 80->bf
1299 for (c = 0; c < 0x400; c += 16)
1301 Map [c + 0] = Map [c + 0x800] = RAM;
1302 Map [c + 1] = Map [c + 0x801] = RAM;
1303 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1304 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1306 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1307 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1308 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1309 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1310 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1311 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1312 for (i = c + 8; i < c + 16; i++)
1314 Map [i] = &ROM [((c << 12) + OFFSET0) % CalculatedSize];
1315 Map [i + 0x800] = &ROM [((c << 12) + OFFSET0) % CalculatedSize];
1316 BlockIsROM [i] = TRUE;
1317 BlockIsROM [i + 0x800] = TRUE;
1320 for (i = c; i < c + 16; i++)
1325 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1329 // Banks 30->3f and b0->bf, address ranges 6000->7ffff is S-RAM.
1330 for (c = 0; c < 16; c++)
1332 Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1333 Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1334 Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1335 Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1336 BlockIsRAM [0x306 + (c << 4)] = TRUE;
1337 BlockIsRAM [0x307 + (c << 4)] = TRUE;
1338 BlockIsRAM [0xb06 + (c << 4)] = TRUE;
1339 BlockIsRAM [0xb07 + (c << 4)] = TRUE;
1342 // Banks 40->7f and c0->ff
1343 for (c = 0; c < 0x400; c += 16)
1345 for (i = c; i < c + 8; i++)
1347 Map [i + 0x400] = &ROM [((c << 12) + OFFSET1) % CalculatedSize];
1348 Map [i + 0x408] = &ROM [((c << 12) + OFFSET1) % CalculatedSize];
1349 Map [i + 0xc00] = &ROM [((c << 12) + OFFSET2) % CalculatedSize];
1350 Map [i + 0xc08] = &ROM [((c << 12) + OFFSET2) % CalculatedSize];
1351 BlockIsROM [i + 0x400] = TRUE;
1352 BlockIsROM [i + 0x408] = TRUE;
1353 BlockIsROM [i + 0xc00] = TRUE;
1354 BlockIsROM [i + 0xc08] = TRUE;
1355 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1356 MemorySpeed [i + 0x408] = MemorySpeed [i + 0xc08] = SLOW_ONE_CYCLE;
1363 void CMemory::AlphaROMMap ()
1368 // Banks 00->3f and 80->bf
1369 for (c = 0; c < 0x400; c += 16)
1371 Map [c + 0] = Map [c + 0x800] = RAM;
1372 Map [c + 1] = Map [c + 0x801] = RAM;
1373 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1374 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1376 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1377 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1378 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1379 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1380 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1381 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1383 for (i = c + 8; i < c + 16; i++)
1385 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1386 BlockIsROM [i] = TRUE;
1389 for (i = c; i < c + 16; i++)
1394 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1398 // Banks 40->7f and c0->ff
1400 for (c = 0; c < 0x400; c += 16)
1402 for (i = c; i < c + 16; i++)
1404 Map [i + 0x400] = &ROM [(c << 12) % CalculatedSize];
1405 Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1406 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1407 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1415 void CMemory::SuperFXROMMap ()
1420 // Banks 00->3f and 80->bf
1421 for (c = 0; c < 0x400; c += 16)
1423 Map [c + 0] = Map [c + 0x800] = RAM;
1424 Map [c + 1] = Map [c + 0x801] = RAM;
1425 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1426 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1428 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1429 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1430 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1431 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1432 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1433 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1434 for (i = c + 8; i < c + 16; i++)
1436 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1437 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1440 for (i = c; i < c + 8; i++)
1445 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1449 // Banks 40->7f and c0->ff
1450 for (c = 0; c < 0x400; c += 16)
1452 for (i = c; i < c + 16; i++)
1454 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1455 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1456 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1460 // Banks 7e->7f, RAM
1461 for (c = 0; c < 16; c++)
1463 Map [c + 0x7e0] = RAM;
1464 Map [c + 0x7f0] = RAM + 0x10000;
1465 BlockIsRAM [c + 0x7e0] = TRUE;
1466 BlockIsRAM [c + 0x7f0] = TRUE;
1467 BlockIsROM [c + 0x7e0] = FALSE;
1468 BlockIsROM [c + 0x7f0] = FALSE;
1471 // Banks 70->71, S-RAM
1472 for (c = 0; c < 32; c++)
1474 Map [c + 0x700] = ::SRAM + (((c >> 4) & 1) << 16);
1475 BlockIsRAM [c + 0x700] = TRUE;
1476 BlockIsROM [c + 0x700] = FALSE;
1479 // Banks 00->3f and 80->bf address ranges 6000->7fff is RAM.
1480 for (c = 0; c < 0x40; c++)
1482 Map [0x006 + (c << 4)] = (uint8 *) ::SRAM - 0x6000;
1483 Map [0x007 + (c << 4)] = (uint8 *) ::SRAM - 0x6000;
1484 Map [0x806 + (c << 4)] = (uint8 *) ::SRAM - 0x6000;
1485 Map [0x807 + (c << 4)] = (uint8 *) ::SRAM - 0x6000;
1486 BlockIsRAM [0x006 + (c << 4)] = TRUE;
1487 BlockIsRAM [0x007 + (c << 4)] = TRUE;
1488 BlockIsRAM [0x806 + (c << 4)] = TRUE;
1489 BlockIsRAM [0x807 + (c << 4)] = TRUE;
1491 // Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K
1492 // block is repeated twice in each 64K block.
1493 for (c = 0; c < 64; c++)
1495 memmove (&ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000);
1496 memmove (&ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000);
1502 void CMemory::SA1ROMMap ()
1507 // Banks 00->3f and 80->bf
1508 for (c = 0; c < 0x400; c += 16)
1510 Map [c + 0] = Map [c + 0x800] = RAM;
1511 Map [c + 1] = Map [c + 0x801] = RAM;
1512 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1513 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1515 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1516 Map [c + 3] = Map [c + 0x803] = (uint8 *) &Memory.FillRAM [0x3000] - 0x3000;
1517 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1518 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1519 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_BWRAM;
1520 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_BWRAM;
1521 for (i = c + 8; i < c + 16; i++)
1523 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1524 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1527 for (i = c; i < c + 16; i++)
1532 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1537 for (c = 0; c < 0x400; c += 16)
1539 for (i = c; i < c + 16; i++)
1540 Map [i + 0x400] = (uint8 *) &SRAM [(c << 12) & 0x1ffff];
1542 for (i = c; i < c + 16; i++)
1544 MemorySpeed [i + 0x400] = SLOW_ONE_CYCLE;
1545 BlockIsROM [i + 0x400] = FALSE;
1550 for (c = 0; c < 0x400; c += 16)
1552 for (i = c; i < c + 16; i++)
1554 Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1555 MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1556 BlockIsROM [i + 0xc00] = TRUE;
1560 for (c = 0; c < 16; c++)
1562 Map [c + 0x7e0] = RAM;
1563 Map [c + 0x7f0] = RAM + 0x10000;
1564 BlockIsRAM [c + 0x7e0] = TRUE;
1565 BlockIsRAM [c + 0x7f0] = TRUE;
1566 BlockIsROM [c + 0x7e0] = FALSE;
1567 BlockIsROM [c + 0x7f0] = FALSE;
1571 // Now copy the map and correct it for the SA1 CPU.
1572 memmove ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap));
1573 memmove ((void *) SA1.Map, (void *) Map, sizeof (Map));
1575 // Banks 00->3f and 80->bf
1576 for (c = 0; c < 0x400; c += 16)
1578 SA1.Map [c + 0] = SA1.Map [c + 0x800] = &Memory.FillRAM [0x3000];
1579 SA1.Map [c + 1] = SA1.Map [c + 0x801] = (uint8 *) MAP_NONE;
1580 SA1.WriteMap [c + 0] = SA1.WriteMap [c + 0x800] = &Memory.FillRAM [0x3000];
1581 SA1.WriteMap [c + 1] = SA1.WriteMap [c + 0x801] = (uint8 *) MAP_NONE;
1585 for (c = 0; c < 0x100; c++)
1586 SA1.Map [c + 0x600] = SA1.WriteMap [c + 0x600] = (uint8 *) MAP_BWRAM_BITMAP;
1591 void CMemory::LoROM24MBSMap ()
1596 // Banks 00->3f and 80->bf
1597 for (c = 0; c < 0x400; c += 16)
1599 Map [c + 0] = Map [c + 0x800] = RAM;
1600 Map [c + 1] = Map [c + 0x801] = RAM;
1601 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1602 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1604 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1605 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1606 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1607 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1608 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1609 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1611 for (i = c + 8; i < c + 16; i++)
1613 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1614 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1617 for (i = c; i < c + 16; i++)
1622 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1626 // Banks 00->3f and 80->bf
1627 for (c = 0; c < 0x200; c += 16)
1629 Map [c + 0x800] = RAM;
1630 Map [c + 0x801] = RAM;
1631 BlockIsRAM [c + 0x800] = TRUE;
1632 BlockIsRAM [c + 0x801] = TRUE;
1634 Map [c + 0x802] = (uint8 *) MAP_PPU;
1635 Map [c + 0x803] = (uint8 *) MAP_PPU;
1636 Map [c + 0x804] = (uint8 *) MAP_CPU;
1637 Map [c + 0x805] = (uint8 *) MAP_CPU;
1638 Map [c + 0x806] = (uint8 *) MAP_NONE;
1639 Map [c + 0x807] = (uint8 *) MAP_NONE;
1641 for (i = c + 8; i < c + 16; i++)
1643 Map [i + 0x800] = &ROM [c << 11] - 0x8000 + 0x200000;
1644 BlockIsROM [i + 0x800] = TRUE;
1647 for (i = c; i < c + 16; i++)
1651 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1655 // Banks 40->7f and c0->ff
1656 for (c = 0; c < 0x400; c += 16)
1658 for (i = c; i < c + 8; i++)
1659 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000];
1661 for (i = c + 8; i < c + 16; i++)
1662 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000];
1664 for (i = c; i < c + 16; i++)
1666 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1667 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1675 void CMemory::SufamiTurboLoROMMap ()
1680 // Banks 00->3f and 80->bf
1681 for (c = 0; c < 0x400; c += 16)
1683 Map [c + 0] = Map [c + 0x800] = RAM;
1684 Map [c + 1] = Map [c + 0x801] = RAM;
1685 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1686 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1688 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1689 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1690 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1691 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1692 if (Settings.DSP1Master)
1694 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1695 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1699 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1700 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1702 for (i = c + 8; i < c + 16; i++)
1704 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1705 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1708 for (i = c; i < c + 16; i++)
1713 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1717 if (Settings.DSP1Master)
1719 // Banks 30->3f and b0->bf
1720 for (c = 0x300; c < 0x400; c += 16)
1722 for (i = c + 8; i < c + 16; i++)
1724 Map [i] = Map [i + 0x800] = (uint8 *) MAP_DSP;
1725 BlockIsROM [i] = BlockIsROM [i + 0x800] = FALSE;
1730 // Banks 40->7f and c0->ff
1731 for (c = 0; c < 0x400; c += 16)
1733 for (i = c; i < c + 8; i++)
1734 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000];
1736 for (i = c + 8; i < c + 16; i++)
1737 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000];
1739 for (i = c; i < c + 16; i++)
1741 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1742 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1746 if (Settings.DSP1Master)
1748 for (c = 0; c < 0x100; c++)
1750 Map [c + 0xe00] = (uint8 *) MAP_DSP;
1751 MemorySpeed [c + 0xe00] = SLOW_ONE_CYCLE;
1752 BlockIsROM [c + 0xe00] = FALSE;
1756 // Banks 7e->7f, RAM
1757 for (c = 0; c < 16; c++)
1759 Map [c + 0x7e0] = RAM;
1760 Map [c + 0x7f0] = RAM + 0x10000;
1761 BlockIsRAM [c + 0x7e0] = TRUE;
1762 BlockIsRAM [c + 0x7f0] = TRUE;
1763 BlockIsROM [c + 0x7e0] = FALSE;
1764 BlockIsROM [c + 0x7f0] = FALSE;
1767 // Banks 60->67, S-RAM
1768 for (c = 0; c < 0x80; c++)
1770 Map [c + 0x600] = (uint8 *) MAP_LOROM_SRAM;
1771 BlockIsRAM [c + 0x600] = TRUE;
1772 BlockIsROM [c + 0x600] = FALSE;
1778 void CMemory::SRAM512KLoROMMap ()
1783 // Banks 00->3f and 80->bf
1784 for (c = 0; c < 0x400; c += 16)
1786 Map [c + 0] = Map [c + 0x800] = RAM;
1787 Map [c + 1] = Map [c + 0x801] = RAM;
1788 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1789 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1791 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1792 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1793 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1794 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1795 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1796 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1798 for (i = c + 8; i < c + 16; i++)
1800 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1801 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1804 for (i = c; i < c + 16; i++)
1809 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1813 // Banks 40->7f and c0->ff
1814 for (c = 0; c < 0x400; c += 16)
1816 for (i = c; i < c + 8; i++)
1817 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000];
1819 for (i = c + 8; i < c + 16; i++)
1820 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000];
1822 for (i = c; i < c + 16; i++)
1824 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1825 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1833 void CMemory::SRAM1024KLoROMMap ()
1838 // Banks 00->3f and 80->bf
1839 for (c = 0; c < 0x400; c += 16)
1841 Map [c + 0] = Map [c + 0x800] = Map [c + 0x400] = Map [c + 0xc00] = RAM;
1842 Map [c + 1] = Map [c + 0x801] = Map [c + 0x401] = Map [c + 0xc01] = RAM;
1843 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = BlockIsRAM [c + 0x400] = BlockIsRAM [c + 0xc00] = TRUE;
1844 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = BlockIsRAM [c + 0x401] = BlockIsRAM [c + 0xc01] = TRUE;
1846 Map [c + 2] = Map [c + 0x802] = Map [c + 0x402] = Map [c + 0xc02] = (uint8 *) MAP_PPU;
1847 Map [c + 3] = Map [c + 0x803] = Map [c + 0x403] = Map [c + 0xc03] = (uint8 *) MAP_PPU;
1848 Map [c + 4] = Map [c + 0x804] = Map [c + 0x404] = Map [c + 0xc04] = (uint8 *) MAP_CPU;
1849 Map [c + 5] = Map [c + 0x805] = Map [c + 0x405] = Map [c + 0xc05] = (uint8 *) MAP_CPU;
1850 Map [c + 6] = Map [c + 0x806] = Map [c + 0x406] = Map [c + 0xc06] = (uint8 *) MAP_NONE;
1851 Map [c + 7] = Map [c + 0x807] = Map [c + 0x407] = Map [c + 0xc07] = (uint8 *) MAP_NONE;
1852 for (i = c + 8; i < c + 16; i++)
1854 Map [i] = Map [i + 0x800] = Map [i + 0x400] = Map [i + 0xc00] = &ROM [c << 11] - 0x8000;
1855 BlockIsROM [i] = BlockIsROM [i + 0x800] = BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1858 for (i = c; i < c + 16; i++)
1862 MemorySpeed [i] = MemorySpeed [i + 0x800] =
1863 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1871 void CMemory::BSHiROMMap ()
1876 // Banks 00->3f and 80->bf
1877 for (c = 0; c < 0x400; c += 16)
1879 Map [c + 0] = Map [c + 0x800] = RAM;
1880 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1881 Map [c + 1] = Map [c + 0x801] = RAM;
1882 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1884 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1885 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1886 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1887 // XXX: How large is SRAM??
1888 Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM;
1889 BlockIsRAM [c + 5] = BlockIsRAM [c + 0x805] = TRUE;
1890 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1891 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1893 for (i = c + 8; i < c + 16; i++)
1895 Map [i] = Map [i + 0x800] = &ROM [(c << 12) % CalculatedSize];
1896 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1899 for (i = c; i < c + 16; i++)
1904 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1908 // Banks 60->7d offset 0000->7fff & 60->7f offset 8000->ffff PSRAM
1909 // XXX: How large is PSRAM?
1910 for (c = 0x600; c < 0x7e0; c += 16)
1912 for (i = c; i < c + 8; i++)
1914 Map [i] = &ROM [0x400000 + (c << 11)];
1915 BlockIsRAM [i] = TRUE;
1917 for (i = c + 8; i < c + 16; i++)
1919 Map [i] = &ROM [0x400000 + (c << 11) - 0x8000];
1920 BlockIsRAM [i] = TRUE;
1924 // Banks 40->7f and c0->ff
1925 for (c = 0; c < 0x400; c += 16)
1927 for (i = c; i < c + 16; i++)
1929 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1930 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1931 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1939 const char *CMemory::TVStandard ()
1941 return (Settings.PAL ? "PAL" : "NTSC");
1944 const char *CMemory::Speed ()
1946 return (ROMSpeed & 0x10 ? "120ns" : "200ns");
1949 const char *CMemory::MapType ()
1951 return (HiROM ? "HiROM" : "LoROM");
1954 const char *CMemory::StaticRAMSize ()
1956 static char tmp [20];
1958 if (Memory.SRAMSize > 16)
1960 sprintf (tmp, "%dKb", (CPU.Memory_SRAMMask + 1) / 1024);
1964 const char *CMemory::Size ()
1966 static char tmp [20];
1968 if (ROMSize < 7 || ROMSize - 7 > 23)
1970 sprintf (tmp, "%dMbits", 1 << (ROMSize - 7));
1974 const char *CMemory::KartContents ()
1976 static char tmp [30];
1977 static const char *CoPro [16] = {
1978 "DSP1", "SuperFX", "OBC1", "SA-1", "S-DD1", "S-RTC", "CoPro#6",
1979 "CoPro#7", "CoPro#8", "CoPro#9", "CoPro#10", "CoPro#11", "CoPro#12",
1980 "CoPro#13", "CoPro#14", "CoPro-Custom"
1982 static const char *Contents [3] = {
1983 "ROM", "ROM+RAM", "ROM+RAM+BAT"
1986 return ("ROM only");
1988 sprintf (tmp, "%s", Contents [(ROMType & 0xf) % 3]);
1990 if ((ROMType & 0xf) >= 3)
1991 sprintf (tmp, "%s+%s", tmp, CoPro [(ROMType & 0xf0) >> 4]);
1996 const char *CMemory::MapMode ()
1998 static char tmp [4];
1999 sprintf (tmp, "%02x", ROMSpeed & ~0x10);
2003 const char *CMemory::ROMID ()
2008 void CMemory::ApplyROMFixes ()
2011 if (strncmp(ROMName, "DUNGEON MASTER", 14) == 0)
2014 SetDSP=&DSP2SetByte;
2015 GetDSP=&DSP2GetByte;
2018 // Enable S-RTC (Real Time Clock) emulation for Dai Kaijyu Monogatari 2
2019 Settings.SRTC = ((ROMType & 0xf0) >> 4) == 5;
2021 Settings.StrikeGunnerOffsetHack = strcmp (ROMName, "STRIKE GUNNER") == 0 ? 7 : 0;
2023 CPU.NMITriggerPoint = 4;
2024 if (strcmp (ROMName, "CACOMA KNIGHT") == 0)
2025 CPU.NMITriggerPoint = 25;
2027 // These games complain if the multi-player adaptor is 'connected'
2028 if (strcmp (ROMName, "TETRIS&Dr.MARIO") == 0 ||
2029 strcmp (ROMName, "JIGSAW PARTY") == 0 ||
2030 strcmp (ROMName, "SUPER PICROSS") == 0 ||
2031 strcmp (ROMName, "KIRBY NO KIRA KIZZU") == 0 ||
2032 strcmp (ROMName, "BLOCK") == 0 ||
2033 strncmp (ROMName, "SUPER BOMBLISS", 14) == 0 ||
2034 strcmp (ROMId, "ABOJ") == 0)
2036 Settings.MultiPlayer5Master = FALSE;
2037 Settings.MouseMaster = FALSE;
2038 Settings.SuperScopeMaster = FALSE;
2041 // Games which spool sound samples between the SNES and sound CPU using
2042 // H-DMA as the sample is playing.
2043 if (strcmp (ROMName, "EARTHWORM JIM 2") == 0 ||
2044 strcmp (ROMName, "PRIMAL RAGE") == 0 ||
2045 strcmp (ROMName, "CLAY FIGHTER") == 0 ||
2046 strcmp (ROMName, "ClayFighter 2") == 0 ||
2047 strncasecmp (ROMName, "MADDEN", 6) == 0 ||
2048 strncmp (ROMName, "NHL", 3) == 0 ||
2049 strcmp (ROMName, "WeaponLord") == 0)
2051 Settings.Shutdown = FALSE;
2056 if (strcmp (ROMId, "CQ ") == 0 ||
2058 strncmp (ROMId, "JG", 2) == 0 ||
2059 strcmp (ROMName, "GAIA GENSOUKI 1 JPN") == 0)
2062 Settings.APUEnabled |= 2;
2063 CPU.APU_APUExecuting |= 2;
2066 // RENDERING RANGER R2
2067 if (strcmp (ROMId, "AVCJ") == 0 ||
2069 strncmp (ROMId, "ARF", 3) == 0 ||
2070 // Tales of Phantasia
2071 strncmp (ROMId, "ATV", 3) == 0 ||
2073 strncasecmp (ROMName, "ActRaiser", 9) == 0 ||
2075 strcmp (ROMName, "SOULBLAZER - 1 USA") == 0 ||
2076 strcmp (ROMName, "SOULBLADER - 1") == 0 ||
2077 strncmp (ROMName, "SOULBLAZER 1",12) == 0 ||
2079 strncmp (ROMId, "AQT", 3) == 0 ||
2081 strncmp (ROMId, "E9 ", 3) == 0 ||
2082 strcmp (ROMName, "SLAP STICK 1 JPN") == 0 ||
2083 // ZENNIHON PURORESU2
2084 strncmp (ROMId, "APR", 3) == 0 ||
2086 strncmp (ROMId, "A4B", 3) == 0 ||
2087 // UFO KAMEN YAKISOBAN
2088 strncmp (ROMId, "Y7 ", 3) == 0 ||
2089 strncmp (ROMId, "Y9 ", 3) == 0 ||
2090 // Panic Bomber World
2091 strncmp (ROMId, "APB", 3) == 0 ||
2092 ((strncmp (ROMName, "Parlor", 6) == 0 ||
2093 strcmp (ROMName, "HEIWA Parlor!Mini8") == 0 ||
2094 strncmp (ROMName, "SANKYO Fever! ̨°ÊÞ°!", 21) == 0) &&
2095 strcmp (CompanyId, "A0") == 0) ||
2096 strcmp (ROMName, "DARK KINGDOM") == 0 ||
2097 strcmp (ROMName, "ZAN3 SFC") == 0 ||
2098 strcmp (ROMName, "HIOUDEN") == 0 ||
2099 strcmp (ROMName, "ÃݼɳÀ") == 0 ||
2100 strcmp (ROMName, "FORTUNE QUEST") == 0 ||
2101 strcmp (ROMName, "FISHING TO BASSING") == 0 ||
2102 strncmp (ROMName, "TokyoDome '95Battle 7", 21) == 0 ||
2103 strcmp (ROMName, "OHMONO BLACKBASS") == 0)
2106 // notaz: strangely enough, these games work properly with my hack enabled
2107 Settings.APUEnabled |= 2;
2108 CPU.APU_APUExecuting |= 2;
2111 if (strcmp (ROMName, "BATMAN--REVENGE JOKER") == 0)
2113 Memory.HiROM = FALSE;
2114 Memory.LoROM = TRUE;
2117 Settings.StarfoxHack = strcmp (ROMName, "STAR FOX") == 0 ||
2118 strcmp (ROMName, "STAR WING") == 0;
2119 Settings.WinterGold = strcmp (ROMName, "FX SKIING NINTENDO 96") == 0 ||
2120 strcmp (ROMName, "DIRT RACER") == 0 ||
2121 strcmp (ROMName, "Stunt Race FX") == 0 ||
2122 Settings.StarfoxHack;
2123 Settings.ChuckRock = strcmp (ROMName, "CHUCK ROCK") == 0;
2124 Settings.Dezaemon = strcmp (ROMName, "DEZAEMON") == 0;
2126 if (strcmp (ROMName, "RADICAL DREAMERS") == 0 ||
2127 strcmp (ROMName, "TREASURE CONFLIX") == 0)
2131 for (c = 0; c < 0x80; c++)
2133 Map [c + 0x700] = ROM + 0x200000 + 0x1000 * (c & 0xf0);
2134 BlockIsRAM [c + 0x700] = TRUE;
2135 BlockIsROM [c + 0x700] = FALSE;
2137 for (c = 0; c < 0x400; c += 16)
2139 Map [c + 5] = Map [c + 0x805] = ROM + 0x300000;
2140 BlockIsRAM [c + 5] = BlockIsRAM [c + 0x805] = TRUE;
2145 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE *
2146 Settings.CyclesPercentage) / 100;
2148 if (strcmp (ROMId, "ASRJ") == 0 && Settings.CyclesPercentage == 100)
2150 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 95) / 100;
2152 // Power Rangers Fight
2153 if (strncmp (ROMId, "A3R", 3) == 0 ||
2155 strncmp (ROMId, "AJE", 3) == 0)
2156 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 103) / 100;
2158 if (strcmp (ROMId, "AWVP") == 0 || strcmp (ROMId, "AWVE") == 0 ||
2159 strcmp (ROMId, "AWVJ") == 0)
2161 // Wrestlemania Arcade
2163 if (Settings.CyclesPercentage == 100)
2164 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 140) / 100; // Fixes sound
2166 Settings.WrestlemaniaArcade = TRUE;
2168 // Theme Park - disable offset-per-tile mode.
2169 if (strcmp (ROMId, "ATQP") == 0)
2170 Settings.WrestlemaniaArcade = TRUE;
2172 if (strncmp (ROMId, "A3M", 3) == 0 && Settings.CyclesPercentage == 100)
2173 // Mortal Kombat 3. Fixes cut off speech sample
2174 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100;
2176 if (strcmp (ROMName, "\x0bd\x0da\x0b2\x0d4\x0b0\x0bd\x0de") == 0 &&
2177 Settings.CyclesPercentage == 100)
2178 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 101) / 100;
2180 if (strcmp (ROMName, "WILD TRAX") == 0 ||
2181 strcmp (ROMName, "YOSSY'S ISLAND") == 0 ||
2182 strcmp (ROMName, "YOSHI'S ISLAND") == 0)
2183 CPU.TriedInterleavedMode2 = TRUE;
2185 // Start Trek: Deep Sleep 9
2186 if (strncmp (ROMId, "A9D", 3) == 0 && Settings.CyclesPercentage == 100)
2187 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100;
2189 Settings.APURAMInitialValue = 0xff;
2191 if (strcmp (ROMName, "·³Ô¸¥Ò¶ÞÐÃݾ²") == 0 ||
2192 strcmp (ROMName, "KENTOUOU WORLDCHAMPIO") == 0 ||
2193 strcmp (ROMName, "TKO SUPERCHAMPIONSHIP") == 0 ||
2194 strcmp (ROMName, "TKO SUPER CHAMPIONSHI") == 0 ||
2195 strcmp (ROMName, "IHATOVO STORY") == 0 ||
2196 strcmp (ROMName, "WANDERERS FROM YS") == 0 ||
2197 strcmp (ROMName, "SUPER GENTYOUHISHI") == 0 ||
2198 // Panic Bomber World
2199 strncmp (ROMId, "APB", 3) == 0)
2201 Settings.APURAMInitialValue = 0;
2204 Settings.DaffyDuck = strcmp (ROMName, "DAFFY DUCK: MARV MISS") == 0;
2205 Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX;
2207 SA1.WaitAddress = NULL;
2208 SA1.WaitByteAddress1 = NULL;
2209 SA1.WaitByteAddress2 = NULL;
2212 if (strcmp (ROMId, "ZBPJ") == 0)
2214 SA1.WaitAddress = SA1.Map [0x0093f1 >> MEMMAP_SHIFT] + 0x93f1;
2215 SA1.WaitByteAddress1 = FillRAM + 0x304a;
2217 /* DAISENRYAKU EXPERTWW2 */
2218 if (strcmp (ROMId, "AEVJ") == 0)
2220 SA1.WaitAddress = SA1.Map [0x0ed18d >> MEMMAP_SHIFT] + 0xd18d;
2221 SA1.WaitByteAddress1 = FillRAM + 0x3000;
2224 if (strcmp (ROMId, "A2DJ") == 0)
2226 SA1.WaitAddress = SA1.Map [0x008b62 >> MEMMAP_SHIFT] + 0x8b62;
2228 /* Dragon Ballz HD */
2229 if (strcmp (ROMId, "AZIJ") == 0)
2231 SA1.WaitAddress = SA1.Map [0x008083 >> MEMMAP_SHIFT] + 0x8083;
2232 SA1.WaitByteAddress1 = FillRAM + 0x3020;
2234 /* SFC SDGUNDAMGNEXT */
2235 if (strcmp (ROMId, "ZX3J") == 0)
2237 SA1.WaitAddress = SA1.Map [0x0087f2 >> MEMMAP_SHIFT] + 0x87f2;
2238 SA1.WaitByteAddress1 = FillRAM + 0x30c4;
2240 /* ShougiNoHanamichi */
2241 if (strcmp (ROMId, "AARJ") == 0)
2243 SA1.WaitAddress = SA1.Map [0xc1f85a >> MEMMAP_SHIFT] + 0xf85a;
2244 SA1.WaitByteAddress1 = SRAM + 0x0c64;
2245 SA1.WaitByteAddress2 = SRAM + 0x0c66;
2247 /* KATO HIFUMI9DAN SYOGI */
2248 if (strcmp (ROMId, "A23J") == 0)
2250 SA1.WaitAddress = SA1.Map [0xc25037 >> MEMMAP_SHIFT] + 0x5037;
2251 SA1.WaitByteAddress1 = SRAM + 0x0c06;
2252 SA1.WaitByteAddress2 = SRAM + 0x0c08;
2255 if (strcmp (ROMId, "AIIJ") == 0)
2257 SA1.WaitAddress = SA1.Map [0xc100be >> MEMMAP_SHIFT] + 0x00be;
2258 SA1.WaitByteAddress1 = SRAM + 0x1002;
2259 SA1.WaitByteAddress2 = SRAM + 0x1004;
2262 if (strcmp (ROMId, "AITJ") == 0)
2264 SA1.WaitAddress = SA1.Map [0x0080b7 >> MEMMAP_SHIFT] + 0x80b7;
2266 /* J96 DREAM STADIUM */
2267 if (strcmp (ROMId, "AJ6J") == 0)
2269 SA1.WaitAddress = SA1.Map [0xc0f74a >> MEMMAP_SHIFT] + 0xf74a;
2272 if (strcmp (ROMId, "AJUJ") == 0)
2274 SA1.WaitAddress = SA1.Map [0x00d926 >> MEMMAP_SHIFT] + 0xd926;
2276 /* JKAKINOKI SHOUGI */
2277 if (strcmp (ROMId, "AKAJ") == 0)
2279 SA1.WaitAddress = SA1.Map [0x00f070 >> MEMMAP_SHIFT] + 0xf070;
2281 /* HOSHI NO KIRBY 3 & KIRBY'S DREAM LAND 3 JAP & US */
2282 if (strcmp (ROMId, "AFJJ") == 0 || strcmp (ROMId, "AFJE") == 0)
2284 SA1.WaitAddress = SA1.Map [0x0082d4 >> MEMMAP_SHIFT] + 0x82d4;
2285 SA1.WaitByteAddress1 = SRAM + 0x72a4;
2287 /* KIRBY SUPER DELUXE JAP */
2288 if (strcmp (ROMId, "AKFJ") == 0)
2290 SA1.WaitAddress = SA1.Map [0x008c93 >> MEMMAP_SHIFT] + 0x8c93;
2291 SA1.WaitByteAddress1 = FillRAM + 0x300a;
2292 SA1.WaitByteAddress2 = FillRAM + 0x300e;
2294 /* KIRBY SUPER DELUXE US */
2295 if (strcmp (ROMId, "AKFE") == 0)
2297 SA1.WaitAddress = SA1.Map [0x008cb8 >> MEMMAP_SHIFT] + 0x8cb8;
2298 SA1.WaitByteAddress1 = FillRAM + 0x300a;
2299 SA1.WaitByteAddress2 = FillRAM + 0x300e;
2301 /* SUPER MARIO RPG JAP & US */
2302 if (strcmp (ROMId, "ARWJ") == 0 || strcmp (ROMId, "ARWE") == 0)
2304 SA1.WaitAddress = SA1.Map [0xc0816f >> MEMMAP_SHIFT] + 0x816f;
2305 SA1.WaitByteAddress1 = FillRAM + 0x3000;
2308 if (strcmp (ROMId, "AVRJ") == 0)
2310 SA1.WaitAddress = SA1.Map [0x0085f2 >> MEMMAP_SHIFT] + 0x85f2;
2311 SA1.WaitByteAddress1 = FillRAM + 0x3024;
2313 /* AUGUSTA3 MASTERS NEW */
2314 if (strcmp (ROMId, "AO3J") == 0)
2316 SA1.WaitAddress = SA1.Map [0x00dddb >> MEMMAP_SHIFT] + 0xdddb;
2317 SA1.WaitByteAddress1 = FillRAM + 0x37b4;
2319 /* OSHABERI PARODIUS */
2320 if (strcmp (ROMId, "AJOJ") == 0)
2322 SA1.WaitAddress = SA1.Map [0x8084e5 >> MEMMAP_SHIFT] + 0x84e5;
2324 /* PANIC BOMBER WORLD */
2325 if (strcmp (ROMId, "APBJ") == 0)
2327 SA1.WaitAddress = SA1.Map [0x00857a >> MEMMAP_SHIFT] + 0x857a;
2329 /* PEBBLE BEACH NEW */
2330 if (strcmp (ROMId, "AONJ") == 0)
2332 SA1.WaitAddress = SA1.Map [0x00df33 >> MEMMAP_SHIFT] + 0xdf33;
2333 SA1.WaitByteAddress1 = FillRAM + 0x37b4;
2335 /* PGA EUROPEAN TOUR */
2336 if (strcmp (ROMId, "AEPE") == 0)
2338 SA1.WaitAddress = SA1.Map [0x003700 >> MEMMAP_SHIFT] + 0x3700;
2339 SA1.WaitByteAddress1 = FillRAM + 0x3102;
2342 if (strcmp (ROMId, "A3GE") == 0)
2344 SA1.WaitAddress = SA1.Map [0x003700 >> MEMMAP_SHIFT] + 0x3700;
2345 SA1.WaitByteAddress1 = FillRAM + 0x3102;
2347 /* POWER RANGERS 4 */
2348 if (strcmp (ROMId, "A4RE") == 0)
2350 SA1.WaitAddress = SA1.Map [0x009899 >> MEMMAP_SHIFT] + 0x9899;
2351 SA1.WaitByteAddress1 = FillRAM + 0x3000;
2353 /* PACHISURO PALUSUPE */
2354 if (strcmp (ROMId, "AGFJ") == 0)
2356 // Never seems to turn on the SA-1!
2358 /* SD F1 GRAND PRIX */
2359 if (strcmp (ROMId, "AGFJ") == 0)
2361 SA1.WaitAddress = SA1.Map [0x0181bc >> MEMMAP_SHIFT] + 0x81bc;
2363 /* SHOUGI MARJONG */
2364 if (strcmp (ROMId, "ASYJ") == 0)
2366 SA1.WaitAddress = SA1.Map [0x00f2cc >> MEMMAP_SHIFT] + 0xf2cc;
2367 SA1.WaitByteAddress1 = SRAM + 0x7ffe;
2368 SA1.WaitByteAddress2 = SRAM + 0x7ffc;
2371 if (strcmp (ROMId, "AX2J") == 0)
2373 SA1.WaitAddress = SA1.Map [0x00d675 >> MEMMAP_SHIFT] + 0xd675;
2376 /* SHINING SCORPION */
2377 if (strcmp (ROMId, "A4WJ") == 0)
2379 SA1.WaitAddress = SA1.Map [0xc048be >> MEMMAP_SHIFT] + 0x48be;
2381 /* SHIN SHOUGI CLUB */
2382 if (strcmp (ROMId, "AHJJ") == 0)
2384 SA1.WaitAddress = SA1.Map [0xc1002a >> MEMMAP_SHIFT] + 0x002a;
2385 SA1.WaitByteAddress1 = SRAM + 0x0806;
2386 SA1.WaitByteAddress2 = SRAM + 0x0808;
2389 // Additional game fixes by sanmaiwashi ...
2390 if (strcmp (ROMName, "SFX ŲĶÞÝÀÞÑÓɶÞÀØ 1") == 0)
2392 bytes0x2000 [0xb18] = 0x4c;
2393 bytes0x2000 [0xb19] = 0x4b;
2394 bytes0x2000 [0xb1a] = 0xea;
2397 if (strcmp (ROMName, "GOGO ACKMAN3") == 0 ||
2398 strcmp (ROMName, "HOME ALONE") == 0)
2400 // Banks 00->3f and 80->bf
2401 for (int c = 0; c < 0x400; c += 16)
2403 Map [c + 6] = Map [c + 0x806] = SRAM;
2404 Map [c + 7] = Map [c + 0x807] = SRAM;
2405 BlockIsROM [c + 6] = BlockIsROM [c + 0x806] = FALSE;
2406 BlockIsROM [c + 7] = BlockIsROM [c + 0x807] = FALSE;
2407 BlockIsRAM [c + 6] = BlockIsRAM [c + 0x806] = TRUE;
2408 BlockIsRAM [c + 7] = BlockIsRAM [c + 0x807] = TRUE;
2413 if (strncmp (ROMName, "SWORD WORLD SFC", 15) == 0 ||
2414 strcmp (ROMName, "SFC ¶ÒÝײÀÞ°") == 0)
2417 SNESGameFixes.NeedInit0x2137 = TRUE;
2418 Settings.APUEnabled |= 2;
2419 CPU.APU_APUExecuting |= 2;
2422 if (strncmp (ROMName, "SHIEN THE BLADE CHASE", 21) == 0)
2423 SNESGameFixes.Old_Read0x4200 = TRUE;
2425 if (strcmp (ROMName, "ºÞ¼Þ× ¶²¼Þ³ÀÞ²¹¯¾Ý") == 0)
2426 SNESGameFixes.NeedInit0x2137 = TRUE;
2428 if (strcmp (ROMName, "UMIHARAKAWASE") == 0)
2429 SNESGameFixes.umiharakawaseFix = TRUE;
2431 if (strcmp (ROMName, "ALIENS vs. PREDATOR") == 0)
2432 SNESGameFixes.alienVSpredetorFix = TRUE;
2434 if (strcmp (ROMName, "demon's blazon") == 0 ||
2435 strcmp (ROMName, "demon's crest") == 0 ||
2436 strcmp (ROMName, "ROCKMAN X") == 0 ||
2437 strcmp (ROMName, "MEGAMAN X") == 0)
2441 // Banks 0x808000, 0x408000 are mirroring.
2442 for (int c = 0; c < 8; c++)
2443 Map [0x408 + c] = ROM - 0x8000;
2446 if (strcmp (ROMName, "½°Ȩ̂߰нÀ") == 0 ||
2447 strcmp (ROMName, "½°Ȩ̂߰нÀ 2") == 0 ||
2448 strcmp (ROMName, "ZENKI TENCHIMEIDOU") == 0 ||
2449 strcmp (ROMName, "GANBA LEAGUE") == 0)
2451 SNESGameFixes.APU_OutPorts_ReturnValueFix = TRUE;
2455 if (strcmp (ROMName, "HITOMI3") == 0)
2457 Memory.SRAMSize = 1;
2458 CPU.Memory_SRAMMask = Memory.SRAMSize ?
2459 ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0;
2462 if (strcmp (ROMName, "goemon 4") == 0)
2463 SNESGameFixes.SRAMInitialValue = 0x00;
2465 if (strcmp (ROMName, "PACHISLO ¹Ý·³") == 0)
2466 SNESGameFixes._0x213E_ReturnValue = 1;
2468 if (strcmp (ROMName, "»Þ Ï°¼Þ¬Ý ijʲÃÞÝ") == 0)
2469 SNESGameFixes.TouhaidenControllerFix = TRUE;
2471 if (strcmp (ROMName, "DRAGON KNIGHT 4") == 0)
2473 // Banks 70->7e, S-RAM
2474 for (int c = 0; c < 0xe0; c++)
2476 Map [c + 0x700] = (uint8 *) MAP_LOROM_SRAM;
2477 BlockIsRAM [c + 0x700] = TRUE;
2478 BlockIsROM [c + 0x700] = FALSE;
2483 if (strncmp (ROMName, "LETs PACHINKO(", 14) == 0)
2486 Settings.APUEnabled |= 2;
2487 CPU.APU_APUExecuting |= 2;
2488 if (!Settings.ForceNTSC && !Settings.ForcePAL)
2490 Settings.PAL = FALSE;
2491 Settings.FrameTime = Settings.FrameTimeNTSC;
2492 Memory.ROMFramesPerSecond = 60;
2496 if (strcmp (ROMName, "FURAI NO SIREN") == 0)
2497 SNESGameFixes.SoundEnvelopeHeightReading2 = TRUE;
2499 if(strcmp (ROMName, "XBAND JAPANESE MODEM") == 0)
2501 for (c = 0x200; c < 0x400; c += 16)
2503 for (int i = c; i < c + 16; i++)
2505 Map [i + 0x400] = Map [i + 0xc00] = &ROM[c * 0x1000];
2506 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = 8;
2507 BlockIsRAM [i + 0x400] = BlockIsRAM [i + 0xc00] = TRUE;
2508 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = FALSE;
2515 #define RomPatch(adr,ov,nv) \
2516 if (ROM [adr] == ov) \
2520 if (strcmp (ROMName, "LOVE QUEST") == 0)
2522 RomPatch (0x1385ec, 0xd0, 0xea);
2523 RomPatch (0x1385ed, 0xb2, 0xea);
2526 // Nangoku Syonen Papuwa Kun
2527 if (strcmp (ROMName, "NANGOKUSYONEN PAPUWA") == 0)
2528 RomPatch (0x1f0d1, 0xa0, 0x6b);
2531 if (strcmp (ROMName, "Tetsuwan Atom") == 0)
2533 RomPatch (0xe24c5, 0x90, 0xea);
2534 RomPatch (0xe24c6, 0xf3, 0xea);
2538 if (strcmp (ROMName, "SFC ODA NOBUNAGA") == 0)
2540 RomPatch (0x7497, 0x80, 0xea);
2541 RomPatch (0x7498, 0xd5, 0xea);
2545 if (strcmp (ROMName, "Super Batter Up") == 0)
2547 RomPatch (0x27ae0, 0xd0, 0xea);
2548 RomPatch (0x27ae1, 0xfa, 0xea);
2551 // Super Professional Baseball 2
2552 if (strcmp (ROMName, "SUPER PRO. BASE BALL2") == 0)
2554 RomPatch (0x1e4, 0x50, 0xea);
2555 RomPatch (0x1e5, 0xfb, 0xea);
2559 // Read variable size MSB int from a file
2560 static long ReadInt (FILE *f, unsigned nbytes)
2568 v = (v << 8) | (c & 0xFF);
2573 #define IPS_EOF 0x00454F46l
2575 void CMemory::CheckForIPSPatch (const char *rom_filename, bool8_32 header,
2578 char fname [_MAX_PATH + 1];
2579 FILE *patch_file = NULL;
2580 long offset = header ? 512 : 0;
2582 if (!(patch_file = fopen(S9xGetFilename(FILE_IPS), "rb"))) return;
2584 if (fread (fname, 1, 5, patch_file) != 5 || strncmp (fname, "PATCH", 5) != 0)
2586 fclose (patch_file);
2598 ofs = ReadInt (patch_file, 3);
2607 len = ReadInt (patch_file, 2);
2611 /* Apply patch block */
2614 if (ofs + len > MAX_ROM_SIZE)
2619 rchar = fgetc (patch_file);
2622 ROM [ofs++] = (uint8) rchar;
2629 rlen = ReadInt (patch_file, 2);
2633 rchar = fgetc (patch_file);
2637 if (ofs + rlen > MAX_ROM_SIZE)
2641 ROM [ofs++] = (uint8) rchar;
2648 // Check if ROM image needs to be truncated
2649 ofs = ReadInt (patch_file, 3);
2650 if (ofs != -1 && ofs - offset < rom_size)
2652 // Need to truncate ROM image
2653 rom_size = ofs - offset;
2655 fclose (patch_file);
2660 fclose (patch_file);