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.
61 extern struct FxInit_s SuperFX;
64 extern uint8 *SFXPlotTable;
68 static uint8 bytes0x2000 [0x2000];
70 extern char *rom_filename;
71 extern bool8 LoadZip(const char* , int32 *, int32 *);
73 bool8_32 CMemory::AllASCII (uint8 *b, int size)
75 for (int i = 0; i < size; i++)
77 if (b[i] < 32 || b[i] > 126)
83 int CMemory::ScoreHiROM (bool8_32 skip_header)
86 int o = skip_header ? 0xff00 + 0x200 : 0xff00;
88 if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) +
89 Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff)
92 if (Memory.ROM [o + 0xda] == 0x33)
94 if ((Memory.ROM [o + 0xd5] & 0xf) < 4)
96 if (!(Memory.ROM [o + 0xfd] & 0x80))
98 if (CalculatedSize > 1024 * 1024 * 3)
100 if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48)
102 if (!AllASCII (&Memory.ROM [o + 0xb0], 6))
104 if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1))
110 int CMemory::ScoreLoROM (bool8_32 skip_header)
113 int o = skip_header ? 0x7f00 + 0x200 : 0x7f00;
115 if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) +
116 Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff)
119 if (Memory.ROM [o + 0xda] == 0x33)
121 if ((Memory.ROM [o + 0xd5] & 0xf) < 4)
123 if (CalculatedSize <= 1024 * 1024 * 16)
125 if (!(Memory.ROM [o + 0xfd] & 0x80))
127 if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48)
129 if (!AllASCII (&Memory.ROM [o + 0xb0], 6))
131 if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1))
137 char *CMemory::Safe (const char *s)
139 static char *safe = NULL;
140 static int safe_len = 0;
142 int len = strlen (s);
143 if (!safe || len + 1 > safe_len)
146 free ((char *) safe);
147 safe = (char *) malloc (safe_len = len + 1);
150 for (int i = 0; i < len; i++)
152 if (s [i] >= 32 && s [i] < 127)
161 /**********************************************************************************************/
163 /* This function allocates all the memory needed by the emulator */
164 /**********************************************************************************************/
165 bool8_32 CMemory::Init ()
167 RAM = (uint8 *) malloc (0x20000);
168 SRAM = (uint8 *) malloc (0x20000);
169 VRAM = (uint8 *) malloc (0x10000);
170 ROM = (uint8 *) malloc (MAX_ROM_SIZE + 0x200 + 0x8000);
173 IPPU.TileCache [TILE_2BIT] = (uint8 *) malloc (MAX_2BIT_TILES * 128);
174 IPPU.TileCache [TILE_4BIT] = (uint8 *) malloc (MAX_4BIT_TILES * 128);
175 IPPU.TileCache [TILE_8BIT] = (uint8 *) malloc (MAX_8BIT_TILES * 128);
177 IPPU.TileCached [TILE_2BIT] = (uint8 *) malloc (MAX_2BIT_TILES);
178 IPPU.TileCached [TILE_4BIT] = (uint8 *) malloc (MAX_4BIT_TILES);
179 IPPU.TileCached [TILE_8BIT] = (uint8 *) malloc (MAX_8BIT_TILES);
181 if (!RAM || !SRAM || !VRAM || !ROM ||
182 !IPPU.TileCache [TILE_2BIT] || !IPPU.TileCache [TILE_4BIT] ||
183 !IPPU.TileCache [TILE_8BIT] || !IPPU.TileCached [TILE_2BIT] ||
184 !IPPU.TileCached [TILE_4BIT] || !IPPU.TileCached [TILE_8BIT])
190 // FillRAM uses first 32K of ROM image area, otherwise space just
191 // wasted. Might be read by the SuperFX code.
195 // Add 0x8000 to ROM image pointer to stop SuperFX code accessing
196 // unallocated memory (can cause crash on some ports).
199 C4RAM = ROM + 0x400000 + 8192 * 8;
205 SFXPlotTable = ROM + 0x400000;
207 SuperFX.pvRegisters = &Memory.FillRAM [0x3000];
208 SuperFX.nRamBanks = 1;
209 SuperFX.pvRam = ::SRAM;
210 SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024);
211 SuperFX.pvRom = (uint8 *) ROM;
214 ZeroMemory (IPPU.TileCached [TILE_2BIT], MAX_2BIT_TILES);
215 ZeroMemory (IPPU.TileCached [TILE_4BIT], MAX_4BIT_TILES);
216 ZeroMemory (IPPU.TileCached [TILE_8BIT], MAX_8BIT_TILES);
224 void CMemory::Deinit ()
233 free ((char *) SRAM);
238 free ((char *) VRAM);
248 if (IPPU.TileCache [TILE_2BIT])
250 free ((char *) IPPU.TileCache [TILE_2BIT]);
251 IPPU.TileCache [TILE_2BIT] = NULL;
253 if (IPPU.TileCache [TILE_4BIT])
255 free ((char *) IPPU.TileCache [TILE_4BIT]);
256 IPPU.TileCache [TILE_4BIT] = NULL;
258 if (IPPU.TileCache [TILE_8BIT])
260 free ((char *) IPPU.TileCache [TILE_8BIT]);
261 IPPU.TileCache [TILE_8BIT] = NULL;
264 if (IPPU.TileCached [TILE_2BIT])
266 free ((char *) IPPU.TileCached [TILE_2BIT]);
267 IPPU.TileCached [TILE_2BIT] = NULL;
269 if (IPPU.TileCached [TILE_4BIT])
271 free ((char *) IPPU.TileCached [TILE_4BIT]);
272 IPPU.TileCached [TILE_4BIT] = NULL;
274 if (IPPU.TileCached [TILE_8BIT])
276 free ((char *) IPPU.TileCached [TILE_8BIT]);
277 IPPU.TileCached [TILE_8BIT] = NULL;
283 void CMemory::FreeSDD1Data ()
287 free ((char *) SDD1Index);
292 free ((char *) SDD1Data);
297 /**********************************************************************************************/
299 /**********************************************************************************************/
300 int checkzip( char * fn )
302 int cnt = strlen(fn);
303 if( ( (fn[cnt-1] == 'p') || (fn[cnt-1] == 'P') ) &&
304 ( (fn[cnt-2] == 'i') || (fn[cnt-2] == 'I') ) &&
305 ( (fn[cnt-3] == 'z') || (fn[cnt-3] == 'Z') ) ){
312 /**********************************************************************************************/
314 /* This function loads a Snes-Backup image */
315 /**********************************************************************************************/
317 #pragma warning(disable : 4101)
318 #pragma warning(disable : 4700)
320 bool8_32 CMemory::LoadROM (const char *filename)
322 unsigned long FileSize = 0;
325 bool8_32 Interleaved = FALSE;
326 bool8_32 Tales = FALSE;
327 char dir [_MAX_DIR + 1];
328 char drive [_MAX_DRIVE + 1];
329 char name [_MAX_FNAME + 1];
330 char ext [_MAX_EXT + 1];
331 char fname [_MAX_PATH + 1];
334 memset (&SNESGameFixes, 0, sizeof(SNESGameFixes));
335 SNESGameFixes.SRAMInitialValue = 0x60;
337 memset (bytes0x2000, 0, 0x2000);
338 CPU.TriedInterleavedMode2 = FALSE;
343 _splitpath (filename, drive, dir, name, ext);
344 _makepath (fname, drive, dir, name, ext);
346 strcpy(fname, filename);
351 memmove (&ext [0], &ext[1], 4);
354 int32 TotalFileSize = 0;
357 if( checkzip( fname ) )
359 if (!LoadZip (fname, &TotalFileSize, &HeaderCount))
362 strcpy (ROMFilename, fname);
367 if ((ROMFile = OPEN_STREAM (fname, "rb")) == NULL)
370 strcpy (ROMFilename, fname);
374 bool8_32 more = FALSE;
378 FileSize = READ_STREAM (ptr, MAX_ROM_SIZE + 0x200 - (ptr - ROM), ROMFile);
379 CLOSE_STREAM (ROMFile);
380 int calc_size = (FileSize / 0x2000) * 0x2000;
382 if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) ||
383 Settings.ForceHeader)
385 memmove (ptr, ptr + 512, calc_size);
390 TotalFileSize += FileSize;
393 if (ptr - ROM < MAX_ROM_SIZE + 0x200 &&
394 (isdigit (ext [0]) && ext [1] == 0 && ext [0] < '9'))
399 memmove (&ext [1], &ext [0], 4);
403 _makepath (fname, drive, dir, name, ext);
407 if (ptr - ROM < MAX_ROM_SIZE + 0x200 &&
408 (((len = strlen (name)) == 7 || len == 8) &&
409 strncasecmp (name, "sf", 2) == 0 &&
410 isdigit (name [2]) && isdigit (name [3]) && isdigit (name [4]) &&
411 isdigit (name [5]) && isalpha (name [len - 1])))
416 memmove (&ext [1], &ext [0], 4);
420 _makepath (fname, drive, dir, name, ext);
425 } while (more && (ROMFile = OPEN_STREAM (fname, "rb")) != NULL);
428 if (HeaderCount == 0)
429 S9xMessage (S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found.");
432 if (HeaderCount == 1)
433 S9xMessage (S9X_INFO, S9X_HEADERS_INFO,
434 "Found ROM file header (and ignored it).");
436 S9xMessage (S9X_INFO, S9X_HEADERS_INFO,
437 "Found multiple ROM file headers (and ignored them).");
440 CheckForIPSPatch (filename, HeaderCount != 0, TotalFileSize);
441 int orig_hi_score, orig_lo_score;
442 int hi_score, lo_score;
444 orig_hi_score = hi_score = ScoreHiROM (FALSE);
445 orig_lo_score = lo_score = ScoreLoROM (FALSE);
447 if (HeaderCount == 0 && !Settings.ForceNoHeader &&
448 ((hi_score > lo_score && ScoreHiROM (TRUE) > hi_score) ||
449 (hi_score <= lo_score && ScoreLoROM (TRUE) > lo_score)))
451 memmove (Memory.ROM, Memory.ROM + 512, TotalFileSize - 512);
452 TotalFileSize -= 512;
453 S9xMessage (S9X_INFO, S9X_HEADER_WARNING,
454 "Try specifying the -nhd command line option if the game doesn't work\n");
457 CalculatedSize = (TotalFileSize / 0x2000) * 0x2000;
458 ZeroMemory (ROM + CalculatedSize, MAX_ROM_SIZE - CalculatedSize);
460 // Check for cherryroms.com DAIKAIJYUMONOGATARI2
462 if (CalculatedSize == 0x500000 &&
463 strncmp ((const char *)&ROM [0x40ffc0], "DAIKAIJYUMONOGATARI2", 20) == 0 &&
464 strncmp ((const char *)&ROM [0x40ffb0], "18AE6J", 6) == 0 &&
465 memcmp (&ROM[0x40ffb0], &ROM [0xffb0], 0x30))
467 memmove (&ROM[0x100000], ROM, 0x500000);
468 memmove (ROM, &ROM[0x500000], 0x100000);
471 Interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2;
472 if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score))
477 // Ignore map type byte if not 0x2x or 0x3x
478 if ((ROM [0x7fd5] & 0xf0) == 0x20 || (ROM [0x7fd5] & 0xf0) == 0x30)
480 switch (ROM [0x7fd5] & 0xf)
483 if (strncmp ((char *) &ROM [0x7fc0], "TREASURE HUNTER G", 17) != 0)
488 if (!Settings.ForceLoROM &&
489 strncmp ((char *) &ROM [0x7fc0], "SUPER FORMATION SOCCE", 21) != 0 &&
490 strncmp ((char *) &ROM [0x7fc0], "Star Ocean", 10) != 0)
506 if ((ROM [0xffd5] & 0xf0) == 0x20 || (ROM [0xffd5] & 0xf0) == 0x30)
508 switch (ROM [0xffd5] & 0xf)
521 if (!Settings.ForceHiROM && !Settings.ForceLoROM &&
522 !Settings.ForceInterleaved && !Settings.ForceInterleaved2 &&
523 !Settings.ForceNotInterleaved && !Settings.ForcePAL &&
524 !Settings.ForceSuperFX && !Settings.ForceDSP1 &&
525 !Settings.ForceSA1 && !Settings.ForceC4 &&
528 if (strncmp ((char *) &ROM [0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0)
535 if (strncmp ((char *) &ROM [0x7fc0], "SP MOMOTAROU DENTETSU2", 22) == 0)
542 if (CalculatedSize == 0x100000 &&
543 strncmp ((char *) &ROM [0xffc0], "WWF SUPER WRESTLEMANIA", 22) == 0)
547 memmove (&ROM[0x100000] , ROM, 0x100000);
548 for (cvcount = 0; cvcount < 16; cvcount++)
550 memmove (&ROM[0x8000 * cvcount], &ROM[0x10000 * cvcount + 0x100000 + 0x8000], 0x8000);
551 memmove (&ROM[0x8000 * cvcount + 0x80000], &ROM[0x10000 * cvcount + 0x100000], 0x8000);
555 ZeroMemory (ROM + CalculatedSize, MAX_ROM_SIZE - CalculatedSize);
559 if (!Settings.ForceNotInterleaved && Interleaved)
561 CPU.TriedInterleavedMode2 = TRUE;
562 S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO,
563 "ROM image is in interleaved format - converting...");
565 int nblocks = CalculatedSize >> 16;
569 while (nblocks <= step)
579 for (i = 0; i < 0x40; i += 2)
581 blocks [i + 0] = (i >> 1) + 0x20;
582 blocks [i + 1] = (i >> 1) + 0x00;
584 for (i = 0; i < 0x80; i += 2)
586 blocks [i + 0x40] = (i >> 1) + 0x80;
587 blocks [i + 0x41] = (i >> 1) + 0x40;
593 if (Settings.ForceInterleaved2)
595 for (i = 0; i < nblocks * 2; i++)
597 blocks [i] = (i & ~0x1e) | ((i & 2) << 2) | ((i & 4) << 2) |
598 ((i & 8) >> 2) | ((i & 16) >> 2);
608 for (i = 0; i < nblocks; i++)
610 blocks [i * 2] = i + nblocks;
611 blocks [i * 2 + 1] = i;
615 uint8 *tmp = (uint8 *) malloc (0x8000);
618 for (i = 0; i < nblocks * 2; i++)
620 for (int j = i; j < nblocks * 2; j++)
624 memmove (tmp, &ROM [blocks [j] * 0x8000], 0x8000);
625 memmove (&ROM [blocks [j] * 0x8000],
626 &ROM [blocks [i] * 0x8000], 0x8000);
627 memmove (&ROM [blocks [i] * 0x8000], tmp, 0x8000);
628 uint8 b = blocks [j];
629 blocks [j] = blocks [i];
638 hi_score = ScoreHiROM (FALSE);
639 lo_score = ScoreLoROM (FALSE);
642 (lo_score >= hi_score || hi_score < 0)) ||
644 (hi_score > lo_score || lo_score < 0)))
646 if (retry_count == 0)
648 S9xMessage (S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO,
649 "ROM lied about its type! Trying again.");
650 Settings.ForceNotInterleaved = TRUE;
651 Settings.ForceInterleaved = FALSE;
660 S9xLoadCheatFile (S9xGetFilename(".cht"));
669 void S9xDeinterleaveMode2 ()
671 S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO,
672 "ROM image is in interleaved format - converting...");
674 int nblocks = Memory.CalculatedSize >> 15;
677 while (nblocks <= step)
684 for (i = 0; i < nblocks * 2; i++)
686 blocks [i] = (i & ~0x1e) | ((i & 2) << 2) | ((i & 4) << 2) |
687 ((i & 8) >> 2) | ((i & 16) >> 2);
690 uint8 *tmp = (uint8 *) malloc (0x8000);
694 for (i = 0; i < nblocks * 2; i++)
696 for (int j = i; j < nblocks * 2; j++)
700 memmove (tmp, &Memory.ROM [blocks [j] * 0x8000], 0x8000);
701 memmove (&Memory.ROM [blocks [j] * 0x8000],
702 &Memory.ROM [blocks [i] * 0x8000], 0x8000);
703 memmove (&Memory.ROM [blocks [i] * 0x8000], tmp, 0x8000);
704 uint8 b = blocks [j];
705 blocks [j] = blocks [i];
713 Memory.InitROM (FALSE);
717 void CMemory::InitROM (bool8_32 Interleaved)
720 SuperFX.nRomBanks = CalculatedSize >> 15;
722 Settings.MultiPlayer5Master = Settings.MultiPlayer5;
723 Settings.MouseMaster = Settings.Mouse;
724 Settings.SuperScopeMaster = Settings.SuperScope;
725 Settings.DSP1Master = Settings.ForceDSP1;
726 Settings.SuperFX = FALSE;
727 Settings.SA1 = FALSE;
729 Settings.SDD1 = FALSE;
730 Settings.SRTC = FALSE;
732 ZeroMemory (BlockIsRAM, MEMMAP_NUM_BLOCKS);
733 ZeroMemory (BlockIsROM, MEMMAP_NUM_BLOCKS);
736 memset (ROMId, 0, 5);
737 memset (CompanyId, 0, 3);
741 Memory.SRAMSize = ROM [0xffd8];
742 strncpy (ROMName, (char *) &ROM[0xffc0], ROM_NAME_LEN - 1);
743 ROMSpeed = ROM [0xffd5];
744 ROMType = ROM [0xffd6];
745 ROMSize = ROM [0xffd7];
746 ROMChecksum = ROM [0xffde] + (ROM [0xffdf] << 8);
747 ROMComplementChecksum = ROM [0xffdc] + (ROM [0xffdd] << 8);
749 memmove (ROMId, &ROM [0xffb2], 4);
750 memmove (CompanyId, &ROM [0xffb0], 2);
752 // Try to auto-detect the DSP1 chip
753 if (!Settings.ForceNoDSP1 &&
754 (ROMType & 0xf) >= 3 && (ROMType & 0xf0) == 0)
755 Settings.DSP1Master = TRUE;
757 Settings.SDD1 = Settings.ForceSDD1;
758 if ((ROMType & 0xf0) == 0x40)
759 Settings.SDD1 = !Settings.ForceNoSDD1;
764 if ((ROMSpeed & ~0x10) == 0x25)
765 TalesROMMap (Interleaved);
767 if ((ROMSpeed & ~0x10) == 0x22 &&
768 strncmp (ROMName, "Super Street Fighter", 20) != 0)
777 Memory.HiROM = FALSE;
778 Memory.SRAMSize = ROM [0x7fd8];
779 ROMSpeed = ROM [0x7fd5];
780 ROMType = ROM [0x7fd6];
781 ROMSize = ROM [0x7fd7];
782 ROMChecksum = ROM [0x7fde] + (ROM [0x7fdf] << 8);
783 ROMComplementChecksum = ROM [0x7fdc] + (ROM [0x7fdd] << 8);
784 memmove (ROMId, &ROM [0x7fb2], 4);
785 memmove (CompanyId, &ROM [0x7fb0], 2);
787 strncpy (ROMName, (char *) &ROM[0x7fc0], ROM_NAME_LEN - 1);
788 Settings.SuperFX = Settings.ForceSuperFX;
790 if ((ROMType & 0xf0) == 0x10)
791 Settings.SuperFX = !Settings.ForceNoSuperFX;
793 // Try to auto-detect the DSP1 chip
794 if (!Settings.ForceNoDSP1 &&
795 (ROMType & 0xf) >= 3 && (ROMType & 0xf0) == 0)
796 Settings.DSP1Master = TRUE;
798 Settings.SDD1 = Settings.ForceSDD1;
799 if ((ROMType & 0xf0) == 0x40)
800 Settings.SDD1 = !Settings.ForceNoSDD1;
805 Settings.C4 = Settings.ForceC4;
806 if ((ROMType & 0xf0) == 0xf0 &&
807 (strncmp (ROMName, "MEGAMAN X", 9) == 0 ||
808 strncmp (ROMName, "ROCKMAN X", 9) == 0))
810 Settings.C4 = !Settings.ForceNoC4;
813 if (Settings.SuperFX)
815 //::SRAM = ROM + 1024 * 1024 * 4;
817 Settings.MultiPlayer5Master = FALSE;
818 //Settings.MouseMaster = FALSE;
819 //Settings.SuperScopeMaster = FALSE;
820 Settings.DSP1Master = FALSE;
821 Settings.SA1 = FALSE;
823 Settings.SDD1 = FALSE;
826 if (Settings.ForceSA1 ||
827 (!Settings.ForceNoSA1 && (ROMSpeed & ~0x10) == 0x23 &&
828 (ROMType & 0xf) > 3 && (ROMType & 0xf0) == 0x30))
831 Settings.MultiPlayer5Master = FALSE;
832 //Settings.MouseMaster = FALSE;
833 //Settings.SuperScopeMaster = FALSE;
834 Settings.DSP1Master = FALSE;
836 Settings.SDD1 = FALSE;
840 if ((ROMSpeed & ~0x10) == 0x25)
841 TalesROMMap (Interleaved);
843 if (strncmp ((char *) &Memory.ROM [0x7fc0], "SOUND NOVEL-TCOOL", 17) == 0 ||
844 strncmp ((char *) &Memory.ROM [0x7fc0], "DERBY STALLION 96", 17) == 0)
847 Settings.DSP1Master = FALSE;
850 if (strncmp ((char *) &Memory.ROM [0x7fc0], "THOROUGHBRED BREEDER3", 21) == 0 ||
851 strncmp ((char *) &Memory.ROM [0x7fc0], "RPG-TCOOL 2", 11) == 0)
854 Settings.DSP1Master = FALSE;
857 if (strncmp ((char *) &Memory.ROM [0x7fc0], "DEZAEMON ", 10) == 0)
859 Settings.DSP1Master = FALSE;
860 SRAM1024KLoROMMap ();
863 if (strncmp ((char *) &Memory.ROM [0x7fc0], "ADD-ON BASE CASSETE", 19) == 0)
865 Settings.MultiPlayer5Master = FALSE;
866 Settings.MouseMaster = FALSE;
867 Settings.SuperScopeMaster = FALSE;
868 Settings.DSP1Master = FALSE;
869 SufamiTurboLoROMMap();
873 if ((ROMSpeed & ~0x10) == 0x22 &&
874 strncmp (ROMName, "Super Street Fighter", 20) != 0)
883 int size = CalculatedSize;
889 uint32 remainder = CalculatedSize - size;
896 for (i = 0; i < size; i++)
899 for (i = 0; i < (int) remainder; i++)
900 sum2 += ROM [size + i];
905 if (CalculatedSize == 0x500000 && Memory.HiROM &&
906 strncmp ((const char *)&ROM[0xffb0], "18AZ", 4) == 0 &&
907 !memcmp(&ROM[0xffd5], "\x3a\xf9\x0d\x03\x00\x33\x00", 7))
910 sum1 += sum2 * (size / remainder);
915 if (Settings.ForceNTSC)
916 Settings.PAL = FALSE;
918 if (Settings.ForcePAL)
923 Settings.PAL = ROM [0xffd9] >= 2;
925 Settings.PAL = ROM [0x7fd9] >= 2;
929 Settings.FrameTime = Settings.FrameTimePAL;
930 Memory.ROMFramesPerSecond = 50;
934 Settings.FrameTime = Settings.FrameTimeNTSC;
935 Memory.ROMFramesPerSecond = 60;
938 ROMName[ROM_NAME_LEN - 1] = 0;
939 if (strlen (ROMName))
941 char *p = ROMName + strlen (ROMName) - 1;
943 while (p > ROMName && *(p - 1) == ' ')
948 if (Settings.SuperFX)
950 CPU.Memory_SRAMMask = 0xffff;
951 Memory.SRAMSize = 16;
955 CPU.Memory_SRAMMask = Memory.SRAMSize ?
956 ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0;
959 IAPU.OneCycle = ONE_APU_CYCLE;
960 Settings.Shutdown = Settings.ShutdownMaster;
962 SetDSP = &DSP1SetByte;
963 GetDSP = &DSP1GetByte;
966 sprintf (ROMName, "%s", Safe (ROMName));
967 sprintf (ROMId, "%s", Safe (ROMId));
968 sprintf (CompanyId, "%s", Safe (CompanyId));
970 sprintf (String, "\"%s\" [%s] %s, %s, Type: %s, Mode: %s, TV: %s, S-RAM: %s, ROMId: %s Company: %2.2s",
972 (ROMChecksum + ROMComplementChecksum != 0xffff ||
973 ROMChecksum != sum1) ? "bad checksum" : "checksum ok",
983 S9xMessage (S9X_INFO, S9X_ROM_INFO, String);
986 bool8_32 CMemory::LoadSRAM (const char *filename)
988 int size = Memory.SRAMSize ?
989 (1 << (Memory.SRAMSize + 3)) * 128 : 0;
991 memset (SRAM, SNESGameFixes.SRAMInitialValue, 0x20000);
999 if ((file = fopen(filename, "rb")))
1001 int len = fread ((char*) ::SRAM, 1, 0x20000, file);
1003 if (len - size == 512)
1005 // S-RAM file has a header - remove it
1006 memmove (::SRAM, ::SRAM + 512, size);
1008 if (len == size + SRTC_SRAM_PAD)
1010 S9xSRTCPostLoadState ();
1013 rtc.mode = MODE_READ;
1016 S9xHardResetSRTC ();
1020 S9xHardResetSRTC ();
1024 S9xSDD1LoadLoggedData ();
1029 bool8_32 CMemory::SaveSRAM (const char *filename)
1031 int size = Memory.SRAMSize ?
1032 (1 << (Memory.SRAMSize + 3)) * 128 : 0;
1035 size += SRTC_SRAM_PAD;
1036 S9xSRTCPreSaveState ();
1040 S9xSDD1SaveLoggedData ();
1045 if (size && *Memory.ROMFilename)
1048 if ((file = fopen (filename, "wb")))
1050 fwrite ((char *) ::SRAM, size, 1, file);
1052 #if defined(__linux)
1053 chown (filename, getuid (), getgid ());
1061 void CMemory::FixROMSpeed ()
1065 for (c = 0x800; c < 0x1000; c++)
1068 MemorySpeed [c] = (uint8) CPU.FastROMSpeed;
1072 void CMemory::WriteProtectROM ()
1074 memmove ((void *) WriteMap, (void *) Map, sizeof (Map));
1075 for (int c = 0; c < 0x1000; c++)
1078 WriteMap [c] = (uint8 *) MAP_NONE;
1082 void CMemory::MapRAM ()
1086 // Banks 7e->7f, RAM
1087 for (c = 0; c < 16; c++)
1089 Map [c + 0x7e0] = RAM;
1090 Map [c + 0x7f0] = RAM + 0x10000;
1091 BlockIsRAM [c + 0x7e0] = TRUE;
1092 BlockIsRAM [c + 0x7f0] = TRUE;
1093 BlockIsROM [c + 0x7e0] = FALSE;
1094 BlockIsROM [c + 0x7f0] = FALSE;
1097 // Banks 70->77, S-RAM
1098 for (c = 0; c < 0x80; c++)
1100 Map [c + 0x700] = (uint8 *) MAP_LOROM_SRAM;
1101 BlockIsRAM [c + 0x700] = TRUE;
1102 BlockIsROM [c + 0x700] = FALSE;
1106 void CMemory::MapExtraRAM ()
1110 // Banks 7e->7f, RAM
1111 for (c = 0; c < 16; c++)
1113 Map [c + 0x7e0] = RAM;
1114 Map [c + 0x7f0] = RAM + 0x10000;
1115 BlockIsRAM [c + 0x7e0] = TRUE;
1116 BlockIsRAM [c + 0x7f0] = TRUE;
1117 BlockIsROM [c + 0x7e0] = FALSE;
1118 BlockIsROM [c + 0x7f0] = FALSE;
1121 // Banks 70->73, S-RAM
1122 for (c = 0; c < 16; c++)
1124 Map [c + 0x700] = ::SRAM;
1125 Map [c + 0x710] = ::SRAM + 0x8000;
1126 Map [c + 0x720] = ::SRAM + 0x10000;
1127 Map [c + 0x730] = ::SRAM + 0x18000;
1129 BlockIsRAM [c + 0x700] = TRUE;
1130 BlockIsROM [c + 0x700] = FALSE;
1131 BlockIsRAM [c + 0x710] = TRUE;
1132 BlockIsROM [c + 0x710] = FALSE;
1133 BlockIsRAM [c + 0x720] = TRUE;
1134 BlockIsROM [c + 0x720] = FALSE;
1135 BlockIsRAM [c + 0x730] = TRUE;
1136 BlockIsROM [c + 0x730] = FALSE;
1140 void CMemory::LoROMMap ()
1145 // Banks 00->3f and 80->bf
1146 for (c = 0; c < 0x400; c += 16)
1148 Map [c + 0] = Map [c + 0x800] = RAM;
1149 Map [c + 1] = Map [c + 0x801] = RAM;
1150 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1151 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1153 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1154 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1155 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1156 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1157 if (Settings.DSP1Master)
1159 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1160 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1165 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_C4;
1166 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_C4;
1170 Map [c + 6] = Map [c + 0x806] = (uint8 *) bytes0x2000 - 0x6000;
1171 Map [c + 7] = Map [c + 0x807] = (uint8 *) bytes0x2000 - 0x6000;
1174 for (i = c + 8; i < c + 16; i++)
1176 Map [i] = Map [i + 0x800] = &ROM [(c << 11) % CalculatedSize] - 0x8000;
1177 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1180 for (i = c; i < c + 16; i++)
1185 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1189 if (Settings.DSP1Master)
1191 // Banks 30->3f and b0->bf
1192 for (c = 0x300; c < 0x400; c += 16)
1194 for (i = c + 8; i < c + 16; i++)
1196 Map [i] = Map [i + 0x800] = (uint8 *) MAP_DSP;
1197 BlockIsROM [i] = BlockIsROM [i + 0x800] = FALSE;
1202 // Banks 40->7f and c0->ff
1203 for (c = 0; c < 0x400; c += 16)
1205 for (i = c; i < c + 8; i++)
1206 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) % CalculatedSize];
1208 for (i = c + 8; i < c + 16; i++)
1209 Map [i + 0x400] = Map [i + 0xc00] = &ROM [((c << 11) + 0x200000) % CalculatedSize - 0x8000];
1211 for (i = c; i < c + 16; i++)
1213 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1214 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1218 if (Settings.DSP1Master)
1220 for (c = 0; c < 0x100; c++)
1222 Map [c + 0xe00] = (uint8 *) MAP_DSP;
1223 MemorySpeed [c + 0xe00] = SLOW_ONE_CYCLE;
1224 BlockIsROM [c + 0xe00] = FALSE;
1231 void CMemory::HiROMMap ()
1236 // Banks 00->3f and 80->bf
1237 for (c = 0; c < 0x400; c += 16)
1239 Map [c + 0] = Map [c + 0x800] = RAM;
1240 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1241 Map [c + 1] = Map [c + 0x801] = RAM;
1242 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1244 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1245 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1246 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1247 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1248 if (Settings.DSP1Master)
1250 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1251 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1255 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1256 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1259 for (i = c + 8; i < c + 16; i++)
1261 Map [i] = Map [i + 0x800] = &ROM [(c << 12) % CalculatedSize];
1262 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1265 for (i = c; i < c + 16; i++)
1270 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1274 // Banks 30->3f and b0->bf, address ranges 6000->7fff is S-RAM.
1275 for (c = 0; c < 16; c++)
1277 Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1278 Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1279 Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1280 Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1281 BlockIsRAM [0x306 + (c << 4)] = TRUE;
1282 BlockIsRAM [0x307 + (c << 4)] = TRUE;
1283 BlockIsRAM [0xb06 + (c << 4)] = TRUE;
1284 BlockIsRAM [0xb07 + (c << 4)] = TRUE;
1287 // Banks 40->7f and c0->ff
1288 for (c = 0; c < 0x400; c += 16)
1290 for (i = c; i < c + 16; i++)
1292 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1293 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1294 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1302 void CMemory::TalesROMMap (bool8_32 Interleaved)
1307 uint32 OFFSET0 = 0x400000;
1308 uint32 OFFSET1 = 0x400000;
1309 uint32 OFFSET2 = 0x000000;
1318 // Banks 00->3f and 80->bf
1319 for (c = 0; c < 0x400; c += 16)
1321 Map [c + 0] = Map [c + 0x800] = RAM;
1322 Map [c + 1] = Map [c + 0x801] = RAM;
1323 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1324 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1326 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1327 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1328 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1329 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1330 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1331 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1332 for (i = c + 8; i < c + 16; i++)
1334 Map [i] = &ROM [((c << 12) + OFFSET0) % CalculatedSize];
1335 Map [i + 0x800] = &ROM [((c << 12) + OFFSET0) % CalculatedSize];
1336 BlockIsROM [i] = TRUE;
1337 BlockIsROM [i + 0x800] = TRUE;
1340 for (i = c; i < c + 16; i++)
1345 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1349 // Banks 30->3f and b0->bf, address ranges 6000->7ffff is S-RAM.
1350 for (c = 0; c < 16; c++)
1352 Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1353 Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1354 Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1355 Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1356 BlockIsRAM [0x306 + (c << 4)] = TRUE;
1357 BlockIsRAM [0x307 + (c << 4)] = TRUE;
1358 BlockIsRAM [0xb06 + (c << 4)] = TRUE;
1359 BlockIsRAM [0xb07 + (c << 4)] = TRUE;
1362 // Banks 40->7f and c0->ff
1363 for (c = 0; c < 0x400; c += 16)
1365 for (i = c; i < c + 8; i++)
1367 Map [i + 0x400] = &ROM [((c << 12) + OFFSET1) % CalculatedSize];
1368 Map [i + 0x408] = &ROM [((c << 12) + OFFSET1) % CalculatedSize];
1369 Map [i + 0xc00] = &ROM [((c << 12) + OFFSET2) % CalculatedSize];
1370 Map [i + 0xc08] = &ROM [((c << 12) + OFFSET2) % CalculatedSize];
1371 BlockIsROM [i + 0x400] = TRUE;
1372 BlockIsROM [i + 0x408] = TRUE;
1373 BlockIsROM [i + 0xc00] = TRUE;
1374 BlockIsROM [i + 0xc08] = TRUE;
1375 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1376 MemorySpeed [i + 0x408] = MemorySpeed [i + 0xc08] = SLOW_ONE_CYCLE;
1383 void CMemory::AlphaROMMap ()
1388 // Banks 00->3f and 80->bf
1389 for (c = 0; c < 0x400; c += 16)
1391 Map [c + 0] = Map [c + 0x800] = RAM;
1392 Map [c + 1] = Map [c + 0x801] = RAM;
1393 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1394 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1396 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1397 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1398 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1399 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1400 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1401 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1403 for (i = c + 8; i < c + 16; i++)
1405 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1406 BlockIsROM [i] = TRUE;
1409 for (i = c; i < c + 16; i++)
1414 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1418 // Banks 40->7f and c0->ff
1420 for (c = 0; c < 0x400; c += 16)
1422 for (i = c; i < c + 16; i++)
1424 Map [i + 0x400] = &ROM [(c << 12) % CalculatedSize];
1425 Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1426 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1427 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1435 void CMemory::SuperFXROMMap ()
1440 // Banks 00->3f and 80->bf
1441 for (c = 0; c < 0x400; c += 16)
1443 Map [c + 0] = Map [c + 0x800] = RAM;
1444 Map [c + 1] = Map [c + 0x801] = RAM;
1445 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1446 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1448 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1449 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1450 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1451 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1452 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1453 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1454 for (i = c + 8; i < c + 16; i++)
1456 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1457 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1460 for (i = c; i < c + 8; i++)
1465 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1469 // Banks 40->7f and c0->ff
1470 for (c = 0; c < 0x400; c += 16)
1472 for (i = c; i < c + 16; i++)
1474 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1475 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1476 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1480 // Banks 7e->7f, RAM
1481 for (c = 0; c < 16; c++)
1483 Map [c + 0x7e0] = RAM;
1484 Map [c + 0x7f0] = RAM + 0x10000;
1485 BlockIsRAM [c + 0x7e0] = TRUE;
1486 BlockIsRAM [c + 0x7f0] = TRUE;
1487 BlockIsROM [c + 0x7e0] = FALSE;
1488 BlockIsROM [c + 0x7f0] = FALSE;
1491 // Banks 70->71, S-RAM
1492 for (c = 0; c < 32; c++)
1494 Map [c + 0x700] = ::SRAM + (((c >> 4) & 1) << 16);
1495 BlockIsRAM [c + 0x700] = TRUE;
1496 BlockIsROM [c + 0x700] = FALSE;
1499 // Banks 00->3f and 80->bf address ranges 6000->7fff is RAM.
1500 for (c = 0; c < 0x40; c++)
1502 Map [0x006 + (c << 4)] = (uint8 *) ::SRAM - 0x6000;
1503 Map [0x007 + (c << 4)] = (uint8 *) ::SRAM - 0x6000;
1504 Map [0x806 + (c << 4)] = (uint8 *) ::SRAM - 0x6000;
1505 Map [0x807 + (c << 4)] = (uint8 *) ::SRAM - 0x6000;
1506 BlockIsRAM [0x006 + (c << 4)] = TRUE;
1507 BlockIsRAM [0x007 + (c << 4)] = TRUE;
1508 BlockIsRAM [0x806 + (c << 4)] = TRUE;
1509 BlockIsRAM [0x807 + (c << 4)] = TRUE;
1511 // Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K
1512 // block is repeated twice in each 64K block.
1513 for (c = 0; c < 64; c++)
1515 memmove (&ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000);
1516 memmove (&ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000);
1522 void CMemory::SA1ROMMap ()
1527 // Banks 00->3f and 80->bf
1528 for (c = 0; c < 0x400; c += 16)
1530 Map [c + 0] = Map [c + 0x800] = RAM;
1531 Map [c + 1] = Map [c + 0x801] = RAM;
1532 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1533 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1535 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1536 Map [c + 3] = Map [c + 0x803] = (uint8 *) &Memory.FillRAM [0x3000] - 0x3000;
1537 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1538 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1539 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_BWRAM;
1540 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_BWRAM;
1541 for (i = c + 8; i < c + 16; i++)
1543 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1544 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1547 for (i = c; i < c + 16; i++)
1552 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1557 for (c = 0; c < 0x400; c += 16)
1559 for (i = c; i < c + 16; i++)
1560 Map [i + 0x400] = (uint8 *) &SRAM [(c << 12) & 0x1ffff];
1562 for (i = c; i < c + 16; i++)
1564 MemorySpeed [i + 0x400] = SLOW_ONE_CYCLE;
1565 BlockIsROM [i + 0x400] = FALSE;
1570 for (c = 0; c < 0x400; c += 16)
1572 for (i = c; i < c + 16; i++)
1574 Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1575 MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1576 BlockIsROM [i + 0xc00] = TRUE;
1580 for (c = 0; c < 16; c++)
1582 Map [c + 0x7e0] = RAM;
1583 Map [c + 0x7f0] = RAM + 0x10000;
1584 BlockIsRAM [c + 0x7e0] = TRUE;
1585 BlockIsRAM [c + 0x7f0] = TRUE;
1586 BlockIsROM [c + 0x7e0] = FALSE;
1587 BlockIsROM [c + 0x7f0] = FALSE;
1591 // Now copy the map and correct it for the SA1 CPU.
1592 memmove ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap));
1593 memmove ((void *) SA1.Map, (void *) Map, sizeof (Map));
1595 // Banks 00->3f and 80->bf
1596 for (c = 0; c < 0x400; c += 16)
1598 SA1.Map [c + 0] = SA1.Map [c + 0x800] = &Memory.FillRAM [0x3000];
1599 SA1.Map [c + 1] = SA1.Map [c + 0x801] = (uint8 *) MAP_NONE;
1600 SA1.WriteMap [c + 0] = SA1.WriteMap [c + 0x800] = &Memory.FillRAM [0x3000];
1601 SA1.WriteMap [c + 1] = SA1.WriteMap [c + 0x801] = (uint8 *) MAP_NONE;
1605 for (c = 0; c < 0x100; c++)
1606 SA1.Map [c + 0x600] = SA1.WriteMap [c + 0x600] = (uint8 *) MAP_BWRAM_BITMAP;
1611 void CMemory::LoROM24MBSMap ()
1616 // Banks 00->3f and 80->bf
1617 for (c = 0; c < 0x400; c += 16)
1619 Map [c + 0] = Map [c + 0x800] = RAM;
1620 Map [c + 1] = Map [c + 0x801] = RAM;
1621 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1622 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1624 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1625 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1626 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1627 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1628 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1629 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1631 for (i = c + 8; i < c + 16; i++)
1633 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1634 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1637 for (i = c; i < c + 16; i++)
1642 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1646 // Banks 00->3f and 80->bf
1647 for (c = 0; c < 0x200; c += 16)
1649 Map [c + 0x800] = RAM;
1650 Map [c + 0x801] = RAM;
1651 BlockIsRAM [c + 0x800] = TRUE;
1652 BlockIsRAM [c + 0x801] = TRUE;
1654 Map [c + 0x802] = (uint8 *) MAP_PPU;
1655 Map [c + 0x803] = (uint8 *) MAP_PPU;
1656 Map [c + 0x804] = (uint8 *) MAP_CPU;
1657 Map [c + 0x805] = (uint8 *) MAP_CPU;
1658 Map [c + 0x806] = (uint8 *) MAP_NONE;
1659 Map [c + 0x807] = (uint8 *) MAP_NONE;
1661 for (i = c + 8; i < c + 16; i++)
1663 Map [i + 0x800] = &ROM [c << 11] - 0x8000 + 0x200000;
1664 BlockIsROM [i + 0x800] = TRUE;
1667 for (i = c; i < c + 16; i++)
1671 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1675 // Banks 40->7f and c0->ff
1676 for (c = 0; c < 0x400; c += 16)
1678 for (i = c; i < c + 8; i++)
1679 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000];
1681 for (i = c + 8; i < c + 16; i++)
1682 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000];
1684 for (i = c; i < c + 16; i++)
1686 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1687 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1695 void CMemory::SufamiTurboLoROMMap ()
1700 // Banks 00->3f and 80->bf
1701 for (c = 0; c < 0x400; c += 16)
1703 Map [c + 0] = Map [c + 0x800] = RAM;
1704 Map [c + 1] = Map [c + 0x801] = RAM;
1705 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1706 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1708 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1709 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1710 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1711 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1712 if (Settings.DSP1Master)
1714 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1715 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1719 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1720 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1722 for (i = c + 8; i < c + 16; i++)
1724 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1725 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1728 for (i = c; i < c + 16; i++)
1733 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1737 if (Settings.DSP1Master)
1739 // Banks 30->3f and b0->bf
1740 for (c = 0x300; c < 0x400; c += 16)
1742 for (i = c + 8; i < c + 16; i++)
1744 Map [i] = Map [i + 0x800] = (uint8 *) MAP_DSP;
1745 BlockIsROM [i] = BlockIsROM [i + 0x800] = FALSE;
1750 // Banks 40->7f and c0->ff
1751 for (c = 0; c < 0x400; c += 16)
1753 for (i = c; i < c + 8; i++)
1754 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000];
1756 for (i = c + 8; i < c + 16; i++)
1757 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000];
1759 for (i = c; i < c + 16; i++)
1761 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1762 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1766 if (Settings.DSP1Master)
1768 for (c = 0; c < 0x100; c++)
1770 Map [c + 0xe00] = (uint8 *) MAP_DSP;
1771 MemorySpeed [c + 0xe00] = SLOW_ONE_CYCLE;
1772 BlockIsROM [c + 0xe00] = FALSE;
1776 // Banks 7e->7f, RAM
1777 for (c = 0; c < 16; c++)
1779 Map [c + 0x7e0] = RAM;
1780 Map [c + 0x7f0] = RAM + 0x10000;
1781 BlockIsRAM [c + 0x7e0] = TRUE;
1782 BlockIsRAM [c + 0x7f0] = TRUE;
1783 BlockIsROM [c + 0x7e0] = FALSE;
1784 BlockIsROM [c + 0x7f0] = FALSE;
1787 // Banks 60->67, S-RAM
1788 for (c = 0; c < 0x80; c++)
1790 Map [c + 0x600] = (uint8 *) MAP_LOROM_SRAM;
1791 BlockIsRAM [c + 0x600] = TRUE;
1792 BlockIsROM [c + 0x600] = FALSE;
1798 void CMemory::SRAM512KLoROMMap ()
1803 // Banks 00->3f and 80->bf
1804 for (c = 0; c < 0x400; c += 16)
1806 Map [c + 0] = Map [c + 0x800] = RAM;
1807 Map [c + 1] = Map [c + 0x801] = RAM;
1808 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1809 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1811 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1812 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1813 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1814 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1815 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1816 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1818 for (i = c + 8; i < c + 16; i++)
1820 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1821 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1824 for (i = c; i < c + 16; i++)
1829 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1833 // Banks 40->7f and c0->ff
1834 for (c = 0; c < 0x400; c += 16)
1836 for (i = c; i < c + 8; i++)
1837 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000];
1839 for (i = c + 8; i < c + 16; i++)
1840 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000];
1842 for (i = c; i < c + 16; i++)
1844 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1845 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1853 void CMemory::SRAM1024KLoROMMap ()
1858 // Banks 00->3f and 80->bf
1859 for (c = 0; c < 0x400; c += 16)
1861 Map [c + 0] = Map [c + 0x800] = Map [c + 0x400] = Map [c + 0xc00] = RAM;
1862 Map [c + 1] = Map [c + 0x801] = Map [c + 0x401] = Map [c + 0xc01] = RAM;
1863 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = BlockIsRAM [c + 0x400] = BlockIsRAM [c + 0xc00] = TRUE;
1864 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = BlockIsRAM [c + 0x401] = BlockIsRAM [c + 0xc01] = TRUE;
1866 Map [c + 2] = Map [c + 0x802] = Map [c + 0x402] = Map [c + 0xc02] = (uint8 *) MAP_PPU;
1867 Map [c + 3] = Map [c + 0x803] = Map [c + 0x403] = Map [c + 0xc03] = (uint8 *) MAP_PPU;
1868 Map [c + 4] = Map [c + 0x804] = Map [c + 0x404] = Map [c + 0xc04] = (uint8 *) MAP_CPU;
1869 Map [c + 5] = Map [c + 0x805] = Map [c + 0x405] = Map [c + 0xc05] = (uint8 *) MAP_CPU;
1870 Map [c + 6] = Map [c + 0x806] = Map [c + 0x406] = Map [c + 0xc06] = (uint8 *) MAP_NONE;
1871 Map [c + 7] = Map [c + 0x807] = Map [c + 0x407] = Map [c + 0xc07] = (uint8 *) MAP_NONE;
1872 for (i = c + 8; i < c + 16; i++)
1874 Map [i] = Map [i + 0x800] = Map [i + 0x400] = Map [i + 0xc00] = &ROM [c << 11] - 0x8000;
1875 BlockIsROM [i] = BlockIsROM [i + 0x800] = BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1878 for (i = c; i < c + 16; i++)
1882 MemorySpeed [i] = MemorySpeed [i + 0x800] =
1883 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1891 void CMemory::BSHiROMMap ()
1896 // Banks 00->3f and 80->bf
1897 for (c = 0; c < 0x400; c += 16)
1899 Map [c + 0] = Map [c + 0x800] = RAM;
1900 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1901 Map [c + 1] = Map [c + 0x801] = RAM;
1902 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1904 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1905 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1906 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1907 // XXX: How large is SRAM??
1908 Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM;
1909 BlockIsRAM [c + 5] = BlockIsRAM [c + 0x805] = TRUE;
1910 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1911 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1913 for (i = c + 8; i < c + 16; i++)
1915 Map [i] = Map [i + 0x800] = &ROM [(c << 12) % CalculatedSize];
1916 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1919 for (i = c; i < c + 16; i++)
1924 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1928 // Banks 60->7d offset 0000->7fff & 60->7f offset 8000->ffff PSRAM
1929 // XXX: How large is PSRAM?
1930 for (c = 0x600; c < 0x7e0; c += 16)
1932 for (i = c; i < c + 8; i++)
1934 Map [i] = &ROM [0x400000 + (c << 11)];
1935 BlockIsRAM [i] = TRUE;
1937 for (i = c + 8; i < c + 16; i++)
1939 Map [i] = &ROM [0x400000 + (c << 11) - 0x8000];
1940 BlockIsRAM [i] = TRUE;
1944 // Banks 40->7f and c0->ff
1945 for (c = 0; c < 0x400; c += 16)
1947 for (i = c; i < c + 16; i++)
1949 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1950 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1951 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1959 const char *CMemory::TVStandard ()
1961 return (Settings.PAL ? "PAL" : "NTSC");
1964 const char *CMemory::Speed ()
1966 return (ROMSpeed & 0x10 ? "120ns" : "200ns");
1969 const char *CMemory::MapType ()
1971 return (HiROM ? "HiROM" : "LoROM");
1974 const char *CMemory::StaticRAMSize ()
1976 static char tmp [20];
1978 if (Memory.SRAMSize > 16)
1980 sprintf (tmp, "%dKb", (CPU.Memory_SRAMMask + 1) / 1024);
1984 const char *CMemory::Size ()
1986 static char tmp [20];
1988 if (ROMSize < 7 || ROMSize - 7 > 23)
1990 sprintf (tmp, "%dMbits", 1 << (ROMSize - 7));
1994 const char *CMemory::KartContents ()
1996 static char tmp [30];
1997 static const char *CoPro [16] = {
1998 "DSP1", "SuperFX", "OBC1", "SA-1", "S-DD1", "S-RTC", "CoPro#6",
1999 "CoPro#7", "CoPro#8", "CoPro#9", "CoPro#10", "CoPro#11", "CoPro#12",
2000 "CoPro#13", "CoPro#14", "CoPro-Custom"
2002 static const char *Contents [3] = {
2003 "ROM", "ROM+RAM", "ROM+RAM+BAT"
2006 return ("ROM only");
2008 sprintf (tmp, "%s", Contents [(ROMType & 0xf) % 3]);
2010 if ((ROMType & 0xf) >= 3)
2011 sprintf (tmp, "%s+%s", tmp, CoPro [(ROMType & 0xf0) >> 4]);
2016 const char *CMemory::MapMode ()
2018 static char tmp [4];
2019 sprintf (tmp, "%02x", ROMSpeed & ~0x10);
2023 const char *CMemory::ROMID ()
2028 void CMemory::ApplyROMFixes ()
2031 if (strncmp(ROMName, "DUNGEON MASTER", 14) == 0)
2034 SetDSP=&DSP2SetByte;
2035 GetDSP=&DSP2GetByte;
2038 // Enable S-RTC (Real Time Clock) emulation for Dai Kaijyu Monogatari 2
2039 Settings.SRTC = ((ROMType & 0xf0) >> 4) == 5;
2041 Settings.StrikeGunnerOffsetHack = strcmp (ROMName, "STRIKE GUNNER") == 0 ? 7 : 0;
2043 CPU.NMITriggerPoint = 4;
2044 if (strcmp (ROMName, "CACOMA KNIGHT") == 0)
2045 CPU.NMITriggerPoint = 25;
2047 // These games complain if the multi-player adaptor is 'connected'
2048 if (strcmp (ROMName, "TETRIS&Dr.MARIO") == 0 ||
2049 strcmp (ROMName, "JIGSAW PARTY") == 0 ||
2050 strcmp (ROMName, "SUPER PICROSS") == 0 ||
2051 strcmp (ROMName, "KIRBY NO KIRA KIZZU") == 0 ||
2052 strcmp (ROMName, "BLOCK") == 0 ||
2053 strncmp (ROMName, "SUPER BOMBLISS", 14) == 0 ||
2054 strcmp (ROMId, "ABOJ") == 0)
2056 Settings.MultiPlayer5Master = FALSE;
2057 Settings.MouseMaster = FALSE;
2058 Settings.SuperScopeMaster = FALSE;
2061 // Games which spool sound samples between the SNES and sound CPU using
2062 // H-DMA as the sample is playing.
2063 if (strcmp (ROMName, "EARTHWORM JIM 2") == 0 ||
2064 strcmp (ROMName, "PRIMAL RAGE") == 0 ||
2065 strcmp (ROMName, "CLAY FIGHTER") == 0 ||
2066 strcmp (ROMName, "ClayFighter 2") == 0 ||
2067 strncasecmp (ROMName, "MADDEN", 6) == 0 ||
2068 strncmp (ROMName, "NHL", 3) == 0 ||
2069 strcmp (ROMName, "WeaponLord") == 0)
2071 Settings.Shutdown = FALSE;
2076 if (strcmp (ROMId, "CQ ") == 0 ||
2078 strncmp (ROMId, "JG", 2) == 0 ||
2079 strcmp (ROMName, "GAIA GENSOUKI 1 JPN") == 0)
2082 Settings.APUEnabled |= 2;
2083 CPU.APU_APUExecuting |= 2;
2086 // RENDERING RANGER R2
2087 if (strcmp (ROMId, "AVCJ") == 0 ||
2089 strncmp (ROMId, "ARF", 3) == 0 ||
2090 // Tales of Phantasia
2091 strncmp (ROMId, "ATV", 3) == 0 ||
2093 strncasecmp (ROMName, "ActRaiser", 9) == 0 ||
2095 strcmp (ROMName, "SOULBLAZER - 1 USA") == 0 ||
2096 strcmp (ROMName, "SOULBLADER - 1") == 0 ||
2097 strncmp (ROMName, "SOULBLAZER 1",12) == 0 ||
2099 strncmp (ROMId, "AQT", 3) == 0 ||
2101 strncmp (ROMId, "E9 ", 3) == 0 ||
2102 strcmp (ROMName, "SLAP STICK 1 JPN") == 0 ||
2103 // ZENNIHON PURORESU2
2104 strncmp (ROMId, "APR", 3) == 0 ||
2106 strncmp (ROMId, "A4B", 3) == 0 ||
2107 // UFO KAMEN YAKISOBAN
2108 strncmp (ROMId, "Y7 ", 3) == 0 ||
2109 strncmp (ROMId, "Y9 ", 3) == 0 ||
2110 // Panic Bomber World
2111 strncmp (ROMId, "APB", 3) == 0 ||
2112 ((strncmp (ROMName, "Parlor", 6) == 0 ||
2113 strcmp (ROMName, "HEIWA Parlor!Mini8") == 0 ||
2114 strncmp (ROMName, "SANKYO Fever! ̨°ÊÞ°!", 21) == 0) &&
2115 strcmp (CompanyId, "A0") == 0) ||
2116 strcmp (ROMName, "DARK KINGDOM") == 0 ||
2117 strcmp (ROMName, "ZAN3 SFC") == 0 ||
2118 strcmp (ROMName, "HIOUDEN") == 0 ||
2119 strcmp (ROMName, "ÃݼɳÀ") == 0 ||
2120 strcmp (ROMName, "FORTUNE QUEST") == 0 ||
2121 strcmp (ROMName, "FISHING TO BASSING") == 0 ||
2122 strncmp (ROMName, "TokyoDome '95Battle 7", 21) == 0 ||
2123 strcmp (ROMName, "OHMONO BLACKBASS") == 0)
2126 // notaz: strangely enough, these games work properly with my hack enabled
2127 Settings.APUEnabled |= 2;
2128 CPU.APU_APUExecuting |= 2;
2131 if (strcmp (ROMName, "BATMAN--REVENGE JOKER") == 0)
2133 Memory.HiROM = FALSE;
2134 Memory.LoROM = TRUE;
2137 Settings.StarfoxHack = strcmp (ROMName, "STAR FOX") == 0 ||
2138 strcmp (ROMName, "STAR WING") == 0;
2139 Settings.WinterGold = strcmp (ROMName, "FX SKIING NINTENDO 96") == 0 ||
2140 strcmp (ROMName, "DIRT RACER") == 0 ||
2141 strcmp (ROMName, "Stunt Race FX") == 0 ||
2142 Settings.StarfoxHack;
2143 Settings.ChuckRock = strcmp (ROMName, "CHUCK ROCK") == 0;
2144 Settings.Dezaemon = strcmp (ROMName, "DEZAEMON") == 0;
2146 if (strcmp (ROMName, "RADICAL DREAMERS") == 0 ||
2147 strcmp (ROMName, "TREASURE CONFLIX") == 0)
2151 for (c = 0; c < 0x80; c++)
2153 Map [c + 0x700] = ROM + 0x200000 + 0x1000 * (c & 0xf0);
2154 BlockIsRAM [c + 0x700] = TRUE;
2155 BlockIsROM [c + 0x700] = FALSE;
2157 for (c = 0; c < 0x400; c += 16)
2159 Map [c + 5] = Map [c + 0x805] = ROM + 0x300000;
2160 BlockIsRAM [c + 5] = BlockIsRAM [c + 0x805] = TRUE;
2165 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE *
2166 Settings.CyclesPercentage) / 100;
2168 if (strcmp (ROMId, "ASRJ") == 0 && Settings.CyclesPercentage == 100)
2170 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 95) / 100;
2172 // Power Rangers Fight
2173 if (strncmp (ROMId, "A3R", 3) == 0 ||
2175 strncmp (ROMId, "AJE", 3) == 0)
2176 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 103) / 100;
2178 if (strcmp (ROMId, "AWVP") == 0 || strcmp (ROMId, "AWVE") == 0 ||
2179 strcmp (ROMId, "AWVJ") == 0)
2181 // Wrestlemania Arcade
2183 if (Settings.CyclesPercentage == 100)
2184 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 140) / 100; // Fixes sound
2186 Settings.WrestlemaniaArcade = TRUE;
2188 // Theme Park - disable offset-per-tile mode.
2189 if (strcmp (ROMId, "ATQP") == 0)
2190 Settings.WrestlemaniaArcade = TRUE;
2192 if (strncmp (ROMId, "A3M", 3) == 0 && Settings.CyclesPercentage == 100)
2193 // Mortal Kombat 3. Fixes cut off speech sample
2194 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100;
2196 if (strcmp (ROMName, "\x0bd\x0da\x0b2\x0d4\x0b0\x0bd\x0de") == 0 &&
2197 Settings.CyclesPercentage == 100)
2198 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 101) / 100;
2200 if (strcmp (ROMName, "WILD TRAX") == 0 ||
2201 strcmp (ROMName, "YOSSY'S ISLAND") == 0 ||
2202 strcmp (ROMName, "YOSHI'S ISLAND") == 0)
2203 CPU.TriedInterleavedMode2 = TRUE;
2205 // Start Trek: Deep Sleep 9
2206 if (strncmp (ROMId, "A9D", 3) == 0 && Settings.CyclesPercentage == 100)
2207 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100;
2209 Settings.APURAMInitialValue = 0xff;
2211 if (strcmp (ROMName, "·³Ô¸¥Ò¶ÞÐÃݾ²") == 0 ||
2212 strcmp (ROMName, "KENTOUOU WORLDCHAMPIO") == 0 ||
2213 strcmp (ROMName, "TKO SUPERCHAMPIONSHIP") == 0 ||
2214 strcmp (ROMName, "TKO SUPER CHAMPIONSHI") == 0 ||
2215 strcmp (ROMName, "IHATOVO STORY") == 0 ||
2216 strcmp (ROMName, "WANDERERS FROM YS") == 0 ||
2217 strcmp (ROMName, "SUPER GENTYOUHISHI") == 0 ||
2218 // Panic Bomber World
2219 strncmp (ROMId, "APB", 3) == 0)
2221 Settings.APURAMInitialValue = 0;
2224 Settings.DaffyDuck = strcmp (ROMName, "DAFFY DUCK: MARV MISS") == 0;
2225 Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX;
2227 SA1.WaitAddress = NULL;
2228 SA1.WaitByteAddress1 = NULL;
2229 SA1.WaitByteAddress2 = NULL;
2232 if (strcmp (ROMId, "ZBPJ") == 0)
2234 SA1.WaitAddress = SA1.Map [0x0093f1 >> MEMMAP_SHIFT] + 0x93f1;
2235 SA1.WaitByteAddress1 = FillRAM + 0x304a;
2237 /* DAISENRYAKU EXPERTWW2 */
2238 if (strcmp (ROMId, "AEVJ") == 0)
2240 SA1.WaitAddress = SA1.Map [0x0ed18d >> MEMMAP_SHIFT] + 0xd18d;
2241 SA1.WaitByteAddress1 = FillRAM + 0x3000;
2244 if (strcmp (ROMId, "A2DJ") == 0)
2246 SA1.WaitAddress = SA1.Map [0x008b62 >> MEMMAP_SHIFT] + 0x8b62;
2248 /* Dragon Ballz HD */
2249 if (strcmp (ROMId, "AZIJ") == 0)
2251 SA1.WaitAddress = SA1.Map [0x008083 >> MEMMAP_SHIFT] + 0x8083;
2252 SA1.WaitByteAddress1 = FillRAM + 0x3020;
2254 /* SFC SDGUNDAMGNEXT */
2255 if (strcmp (ROMId, "ZX3J") == 0)
2257 SA1.WaitAddress = SA1.Map [0x0087f2 >> MEMMAP_SHIFT] + 0x87f2;
2258 SA1.WaitByteAddress1 = FillRAM + 0x30c4;
2260 /* ShougiNoHanamichi */
2261 if (strcmp (ROMId, "AARJ") == 0)
2263 SA1.WaitAddress = SA1.Map [0xc1f85a >> MEMMAP_SHIFT] + 0xf85a;
2264 SA1.WaitByteAddress1 = SRAM + 0x0c64;
2265 SA1.WaitByteAddress2 = SRAM + 0x0c66;
2267 /* KATO HIFUMI9DAN SYOGI */
2268 if (strcmp (ROMId, "A23J") == 0)
2270 SA1.WaitAddress = SA1.Map [0xc25037 >> MEMMAP_SHIFT] + 0x5037;
2271 SA1.WaitByteAddress1 = SRAM + 0x0c06;
2272 SA1.WaitByteAddress2 = SRAM + 0x0c08;
2275 if (strcmp (ROMId, "AIIJ") == 0)
2277 SA1.WaitAddress = SA1.Map [0xc100be >> MEMMAP_SHIFT] + 0x00be;
2278 SA1.WaitByteAddress1 = SRAM + 0x1002;
2279 SA1.WaitByteAddress2 = SRAM + 0x1004;
2282 if (strcmp (ROMId, "AITJ") == 0)
2284 SA1.WaitAddress = SA1.Map [0x0080b7 >> MEMMAP_SHIFT] + 0x80b7;
2286 /* J96 DREAM STADIUM */
2287 if (strcmp (ROMId, "AJ6J") == 0)
2289 SA1.WaitAddress = SA1.Map [0xc0f74a >> MEMMAP_SHIFT] + 0xf74a;
2292 if (strcmp (ROMId, "AJUJ") == 0)
2294 SA1.WaitAddress = SA1.Map [0x00d926 >> MEMMAP_SHIFT] + 0xd926;
2296 /* JKAKINOKI SHOUGI */
2297 if (strcmp (ROMId, "AKAJ") == 0)
2299 SA1.WaitAddress = SA1.Map [0x00f070 >> MEMMAP_SHIFT] + 0xf070;
2301 /* HOSHI NO KIRBY 3 & KIRBY'S DREAM LAND 3 JAP & US */
2302 if (strcmp (ROMId, "AFJJ") == 0 || strcmp (ROMId, "AFJE") == 0)
2304 SA1.WaitAddress = SA1.Map [0x0082d4 >> MEMMAP_SHIFT] + 0x82d4;
2305 SA1.WaitByteAddress1 = SRAM + 0x72a4;
2307 /* KIRBY SUPER DELUXE JAP */
2308 if (strcmp (ROMId, "AKFJ") == 0)
2310 SA1.WaitAddress = SA1.Map [0x008c93 >> MEMMAP_SHIFT] + 0x8c93;
2311 SA1.WaitByteAddress1 = FillRAM + 0x300a;
2312 SA1.WaitByteAddress2 = FillRAM + 0x300e;
2314 /* KIRBY SUPER DELUXE US */
2315 if (strcmp (ROMId, "AKFE") == 0)
2317 SA1.WaitAddress = SA1.Map [0x008cb8 >> MEMMAP_SHIFT] + 0x8cb8;
2318 SA1.WaitByteAddress1 = FillRAM + 0x300a;
2319 SA1.WaitByteAddress2 = FillRAM + 0x300e;
2321 /* SUPER MARIO RPG JAP & US */
2322 if (strcmp (ROMId, "ARWJ") == 0 || strcmp (ROMId, "ARWE") == 0)
2324 SA1.WaitAddress = SA1.Map [0xc0816f >> MEMMAP_SHIFT] + 0x816f;
2325 SA1.WaitByteAddress1 = FillRAM + 0x3000;
2328 if (strcmp (ROMId, "AVRJ") == 0)
2330 SA1.WaitAddress = SA1.Map [0x0085f2 >> MEMMAP_SHIFT] + 0x85f2;
2331 SA1.WaitByteAddress1 = FillRAM + 0x3024;
2333 /* AUGUSTA3 MASTERS NEW */
2334 if (strcmp (ROMId, "AO3J") == 0)
2336 SA1.WaitAddress = SA1.Map [0x00dddb >> MEMMAP_SHIFT] + 0xdddb;
2337 SA1.WaitByteAddress1 = FillRAM + 0x37b4;
2339 /* OSHABERI PARODIUS */
2340 if (strcmp (ROMId, "AJOJ") == 0)
2342 SA1.WaitAddress = SA1.Map [0x8084e5 >> MEMMAP_SHIFT] + 0x84e5;
2344 /* PANIC BOMBER WORLD */
2345 if (strcmp (ROMId, "APBJ") == 0)
2347 SA1.WaitAddress = SA1.Map [0x00857a >> MEMMAP_SHIFT] + 0x857a;
2349 /* PEBBLE BEACH NEW */
2350 if (strcmp (ROMId, "AONJ") == 0)
2352 SA1.WaitAddress = SA1.Map [0x00df33 >> MEMMAP_SHIFT] + 0xdf33;
2353 SA1.WaitByteAddress1 = FillRAM + 0x37b4;
2355 /* PGA EUROPEAN TOUR */
2356 if (strcmp (ROMId, "AEPE") == 0)
2358 SA1.WaitAddress = SA1.Map [0x003700 >> MEMMAP_SHIFT] + 0x3700;
2359 SA1.WaitByteAddress1 = FillRAM + 0x3102;
2362 if (strcmp (ROMId, "A3GE") == 0)
2364 SA1.WaitAddress = SA1.Map [0x003700 >> MEMMAP_SHIFT] + 0x3700;
2365 SA1.WaitByteAddress1 = FillRAM + 0x3102;
2367 /* POWER RANGERS 4 */
2368 if (strcmp (ROMId, "A4RE") == 0)
2370 SA1.WaitAddress = SA1.Map [0x009899 >> MEMMAP_SHIFT] + 0x9899;
2371 SA1.WaitByteAddress1 = FillRAM + 0x3000;
2373 /* PACHISURO PALUSUPE */
2374 if (strcmp (ROMId, "AGFJ") == 0)
2376 // Never seems to turn on the SA-1!
2378 /* SD F1 GRAND PRIX */
2379 if (strcmp (ROMId, "AGFJ") == 0)
2381 SA1.WaitAddress = SA1.Map [0x0181bc >> MEMMAP_SHIFT] + 0x81bc;
2383 /* SHOUGI MARJONG */
2384 if (strcmp (ROMId, "ASYJ") == 0)
2386 SA1.WaitAddress = SA1.Map [0x00f2cc >> MEMMAP_SHIFT] + 0xf2cc;
2387 SA1.WaitByteAddress1 = SRAM + 0x7ffe;
2388 SA1.WaitByteAddress2 = SRAM + 0x7ffc;
2391 if (strcmp (ROMId, "AX2J") == 0)
2393 SA1.WaitAddress = SA1.Map [0x00d675 >> MEMMAP_SHIFT] + 0xd675;
2396 /* SHINING SCORPION */
2397 if (strcmp (ROMId, "A4WJ") == 0)
2399 SA1.WaitAddress = SA1.Map [0xc048be >> MEMMAP_SHIFT] + 0x48be;
2401 /* SHIN SHOUGI CLUB */
2402 if (strcmp (ROMId, "AHJJ") == 0)
2404 SA1.WaitAddress = SA1.Map [0xc1002a >> MEMMAP_SHIFT] + 0x002a;
2405 SA1.WaitByteAddress1 = SRAM + 0x0806;
2406 SA1.WaitByteAddress2 = SRAM + 0x0808;
2409 // Additional game fixes by sanmaiwashi ...
2410 if (strcmp (ROMName, "SFX ŲĶÞÝÀÞÑÓɶÞÀØ 1") == 0)
2412 bytes0x2000 [0xb18] = 0x4c;
2413 bytes0x2000 [0xb19] = 0x4b;
2414 bytes0x2000 [0xb1a] = 0xea;
2417 if (strcmp (ROMName, "GOGO ACKMAN3") == 0 ||
2418 strcmp (ROMName, "HOME ALONE") == 0)
2420 // Banks 00->3f and 80->bf
2421 for (int c = 0; c < 0x400; c += 16)
2423 Map [c + 6] = Map [c + 0x806] = SRAM;
2424 Map [c + 7] = Map [c + 0x807] = SRAM;
2425 BlockIsROM [c + 6] = BlockIsROM [c + 0x806] = FALSE;
2426 BlockIsROM [c + 7] = BlockIsROM [c + 0x807] = FALSE;
2427 BlockIsRAM [c + 6] = BlockIsRAM [c + 0x806] = TRUE;
2428 BlockIsRAM [c + 7] = BlockIsRAM [c + 0x807] = TRUE;
2433 if (strncmp (ROMName, "SWORD WORLD SFC", 15) == 0 ||
2434 strcmp (ROMName, "SFC ¶ÒÝײÀÞ°") == 0)
2437 SNESGameFixes.NeedInit0x2137 = TRUE;
2438 Settings.APUEnabled |= 2;
2439 CPU.APU_APUExecuting |= 2;
2442 if (strncmp (ROMName, "SHIEN THE BLADE CHASE", 21) == 0)
2443 SNESGameFixes.Old_Read0x4200 = TRUE;
2445 if (strcmp (ROMName, "ºÞ¼Þ× ¶²¼Þ³ÀÞ²¹¯¾Ý") == 0)
2446 SNESGameFixes.NeedInit0x2137 = TRUE;
2448 if (strcmp (ROMName, "UMIHARAKAWASE") == 0)
2449 SNESGameFixes.umiharakawaseFix = TRUE;
2451 if (strcmp (ROMName, "ALIENS vs. PREDATOR") == 0)
2452 SNESGameFixes.alienVSpredetorFix = TRUE;
2454 if (strcmp (ROMName, "demon's blazon") == 0 ||
2455 strcmp (ROMName, "demon's crest") == 0 ||
2456 strcmp (ROMName, "ROCKMAN X") == 0 ||
2457 strcmp (ROMName, "MEGAMAN X") == 0)
2461 // Banks 0x808000, 0x408000 are mirroring.
2462 for (int c = 0; c < 8; c++)
2463 Map [0x408 + c] = ROM - 0x8000;
2466 if (strcmp (ROMName, "½°Ȩ̂߰нÀ") == 0 ||
2467 strcmp (ROMName, "½°Ȩ̂߰нÀ 2") == 0 ||
2468 strcmp (ROMName, "ZENKI TENCHIMEIDOU") == 0 ||
2469 strcmp (ROMName, "GANBA LEAGUE") == 0)
2471 SNESGameFixes.APU_OutPorts_ReturnValueFix = TRUE;
2475 if (strcmp (ROMName, "HITOMI3") == 0)
2477 Memory.SRAMSize = 1;
2478 CPU.Memory_SRAMMask = Memory.SRAMSize ?
2479 ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0;
2482 if (strcmp (ROMName, "goemon 4") == 0)
2483 SNESGameFixes.SRAMInitialValue = 0x00;
2485 if (strcmp (ROMName, "PACHISLO ¹Ý·³") == 0)
2486 SNESGameFixes._0x213E_ReturnValue = 1;
2488 if (strcmp (ROMName, "»Þ Ï°¼Þ¬Ý ijʲÃÞÝ") == 0)
2489 SNESGameFixes.TouhaidenControllerFix = TRUE;
2491 if (strcmp (ROMName, "DRAGON KNIGHT 4") == 0)
2493 // Banks 70->7e, S-RAM
2494 for (int c = 0; c < 0xe0; c++)
2496 Map [c + 0x700] = (uint8 *) MAP_LOROM_SRAM;
2497 BlockIsRAM [c + 0x700] = TRUE;
2498 BlockIsROM [c + 0x700] = FALSE;
2503 if (strncmp (ROMName, "LETs PACHINKO(", 14) == 0)
2506 Settings.APUEnabled |= 2;
2507 CPU.APU_APUExecuting |= 2;
2508 if (!Settings.ForceNTSC && !Settings.ForcePAL)
2510 Settings.PAL = FALSE;
2511 Settings.FrameTime = Settings.FrameTimeNTSC;
2512 Memory.ROMFramesPerSecond = 60;
2516 if (strcmp (ROMName, "FURAI NO SIREN") == 0)
2517 SNESGameFixes.SoundEnvelopeHeightReading2 = TRUE;
2519 if(strcmp (ROMName, "XBAND JAPANESE MODEM") == 0)
2521 for (c = 0x200; c < 0x400; c += 16)
2523 for (int i = c; i < c + 16; i++)
2525 Map [i + 0x400] = Map [i + 0xc00] = &ROM[c * 0x1000];
2526 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = 8;
2527 BlockIsRAM [i + 0x400] = BlockIsRAM [i + 0xc00] = TRUE;
2528 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = FALSE;
2535 #define RomPatch(adr,ov,nv) \
2536 if (ROM [adr] == ov) \
2540 if (strcmp (ROMName, "LOVE QUEST") == 0)
2542 RomPatch (0x1385ec, 0xd0, 0xea);
2543 RomPatch (0x1385ed, 0xb2, 0xea);
2546 // Nangoku Syonen Papuwa Kun
2547 if (strcmp (ROMName, "NANGOKUSYONEN PAPUWA") == 0)
2548 RomPatch (0x1f0d1, 0xa0, 0x6b);
2551 if (strcmp (ROMName, "Tetsuwan Atom") == 0)
2553 RomPatch (0xe24c5, 0x90, 0xea);
2554 RomPatch (0xe24c6, 0xf3, 0xea);
2558 if (strcmp (ROMName, "SFC ODA NOBUNAGA") == 0)
2560 RomPatch (0x7497, 0x80, 0xea);
2561 RomPatch (0x7498, 0xd5, 0xea);
2565 if (strcmp (ROMName, "Super Batter Up") == 0)
2567 RomPatch (0x27ae0, 0xd0, 0xea);
2568 RomPatch (0x27ae1, 0xfa, 0xea);
2571 // Super Professional Baseball 2
2572 if (strcmp (ROMName, "SUPER PRO. BASE BALL2") == 0)
2574 RomPatch (0x1e4, 0x50, 0xea);
2575 RomPatch (0x1e5, 0xfb, 0xea);
2579 // Read variable size MSB int from a file
2580 static long ReadInt (FILE *f, unsigned nbytes)
2588 v = (v << 8) | (c & 0xFF);
2593 #define IPS_EOF 0x00454F46l
2595 void CMemory::CheckForIPSPatch (const char *rom_filename, bool8_32 header,
2598 char dir [_MAX_DIR + 1];
2599 char drive [_MAX_DRIVE + 1];
2600 char name [_MAX_FNAME + 1];
2601 char ext [_MAX_EXT + 1];
2602 char fname [_MAX_PATH + 1];
2603 FILE *patch_file = NULL;
2604 long offset = header ? 512 : 0;
2606 if (!(patch_file = fopen(S9xGetFilename (".ips"), "rb"))) return;
2608 if (fread (fname, 1, 5, patch_file) != 5 || strncmp (fname, "PATCH", 5) != 0)
2610 fclose (patch_file);
2622 ofs = ReadInt (patch_file, 3);
2631 len = ReadInt (patch_file, 2);
2635 /* Apply patch block */
2638 if (ofs + len > MAX_ROM_SIZE)
2643 rchar = fgetc (patch_file);
2646 ROM [ofs++] = (uint8) rchar;
2653 rlen = ReadInt (patch_file, 2);
2657 rchar = fgetc (patch_file);
2661 if (ofs + rlen > MAX_ROM_SIZE)
2665 ROM [ofs++] = (uint8) rchar;
2672 // Check if ROM image needs to be truncated
2673 ofs = ReadInt (patch_file, 3);
2674 if (ofs != -1 && ofs - offset < rom_size)
2676 // Need to truncate ROM image
2677 rom_size = ofs - offset;
2679 fclose (patch_file);
2684 fclose (patch_file);