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.
44 /* Do not reencode this file. There are special chars on it. */
60 extern struct FxInit_s SuperFX;
63 extern uint8 *SFXPlotTable;
67 static uint8 bytes0x2000 [0x2000];
69 extern char *rom_filename;
70 extern bool8 LoadZip(const char* , int32 *, int32 *);
72 bool8_32 CMemory::AllASCII (uint8 *b, int size)
74 for (int i = 0; i < size; i++)
76 if (b[i] < 32 || b[i] > 126)
82 int CMemory::ScoreHiROM (bool8_32 skip_header)
85 int o = skip_header ? 0xff00 + 0x200 : 0xff00;
87 if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) +
88 Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff)
91 if (Memory.ROM [o + 0xda] == 0x33)
93 if ((Memory.ROM [o + 0xd5] & 0xf) < 4)
95 if (!(Memory.ROM [o + 0xfd] & 0x80))
97 if (CalculatedSize > 1024 * 1024 * 3)
99 if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48)
101 if (!AllASCII (&Memory.ROM [o + 0xb0], 6))
103 if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1))
109 int CMemory::ScoreLoROM (bool8_32 skip_header)
112 int o = skip_header ? 0x7f00 + 0x200 : 0x7f00;
114 if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) +
115 Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff)
118 if (Memory.ROM [o + 0xda] == 0x33)
120 if ((Memory.ROM [o + 0xd5] & 0xf) < 4)
122 if (CalculatedSize <= 1024 * 1024 * 16)
124 if (!(Memory.ROM [o + 0xfd] & 0x80))
126 if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48)
128 if (!AllASCII (&Memory.ROM [o + 0xb0], 6))
130 if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1))
136 char *CMemory::Safe (const char *s)
138 static char *safe = NULL;
139 static int safe_len = 0;
141 int len = strlen (s);
142 if (!safe || len + 1 > safe_len)
145 free ((char *) safe);
146 safe = (char *) malloc (safe_len = len + 1);
149 for (int i = 0; i < len; i++)
151 if (s [i] >= 32 && s [i] < 127)
160 /**********************************************************************************************/
162 /* This function allocates all the memory needed by the emulator */
163 /**********************************************************************************************/
164 bool8_32 CMemory::Init ()
166 RAM = (uint8 *) malloc (0x20000);
167 SRAM = (uint8 *) malloc (0x20000);
168 VRAM = (uint8 *) malloc (0x10000);
169 ROM = (uint8 *) malloc (MAX_ROM_SIZE + 0x200 + 0x8000);
172 IPPU.TileCache [TILE_2BIT] = (uint8 *) malloc (MAX_2BIT_TILES * 128);
173 IPPU.TileCache [TILE_4BIT] = (uint8 *) malloc (MAX_4BIT_TILES * 128);
174 IPPU.TileCache [TILE_8BIT] = (uint8 *) malloc (MAX_8BIT_TILES * 128);
176 IPPU.TileCached [TILE_2BIT] = (uint8 *) malloc (MAX_2BIT_TILES);
177 IPPU.TileCached [TILE_4BIT] = (uint8 *) malloc (MAX_4BIT_TILES);
178 IPPU.TileCached [TILE_8BIT] = (uint8 *) malloc (MAX_8BIT_TILES);
180 if (!RAM || !SRAM || !VRAM || !ROM ||
181 !IPPU.TileCache [TILE_2BIT] || !IPPU.TileCache [TILE_4BIT] ||
182 !IPPU.TileCache [TILE_8BIT] || !IPPU.TileCached [TILE_2BIT] ||
183 !IPPU.TileCached [TILE_4BIT] || !IPPU.TileCached [TILE_8BIT])
189 // FillRAM uses first 32K of ROM image area, otherwise space just
190 // wasted. Might be read by the SuperFX code.
194 // Add 0x8000 to ROM image pointer to stop SuperFX code accessing
195 // unallocated memory (can cause crash on some ports).
198 C4RAM = ROM + 0x400000 + 8192 * 8;
204 SFXPlotTable = ROM + 0x400000;
206 SuperFX.pvRegisters = &Memory.FillRAM [0x3000];
207 SuperFX.nRamBanks = 1;
208 SuperFX.pvRam = ::SRAM;
209 SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024);
210 SuperFX.pvRom = (uint8 *) ROM;
213 ZeroMemory (IPPU.TileCached [TILE_2BIT], MAX_2BIT_TILES);
214 ZeroMemory (IPPU.TileCached [TILE_4BIT], MAX_4BIT_TILES);
215 ZeroMemory (IPPU.TileCached [TILE_8BIT], MAX_8BIT_TILES);
223 void CMemory::Deinit ()
232 free ((char *) SRAM);
237 free ((char *) VRAM);
247 if (IPPU.TileCache [TILE_2BIT])
249 free ((char *) IPPU.TileCache [TILE_2BIT]);
250 IPPU.TileCache [TILE_2BIT] = NULL;
252 if (IPPU.TileCache [TILE_4BIT])
254 free ((char *) IPPU.TileCache [TILE_4BIT]);
255 IPPU.TileCache [TILE_4BIT] = NULL;
257 if (IPPU.TileCache [TILE_8BIT])
259 free ((char *) IPPU.TileCache [TILE_8BIT]);
260 IPPU.TileCache [TILE_8BIT] = NULL;
263 if (IPPU.TileCached [TILE_2BIT])
265 free ((char *) IPPU.TileCached [TILE_2BIT]);
266 IPPU.TileCached [TILE_2BIT] = NULL;
268 if (IPPU.TileCached [TILE_4BIT])
270 free ((char *) IPPU.TileCached [TILE_4BIT]);
271 IPPU.TileCached [TILE_4BIT] = NULL;
273 if (IPPU.TileCached [TILE_8BIT])
275 free ((char *) IPPU.TileCached [TILE_8BIT]);
276 IPPU.TileCached [TILE_8BIT] = NULL;
282 void CMemory::FreeSDD1Data ()
286 free ((char *) SDD1Index);
291 free ((char *) SDD1Data);
296 /**********************************************************************************************/
298 /**********************************************************************************************/
299 int checkzip( char * fn )
301 int cnt = strlen(fn);
302 if( ( (fn[cnt-1] == 'p') || (fn[cnt-1] == 'P') ) &&
303 ( (fn[cnt-2] == 'i') || (fn[cnt-2] == 'I') ) &&
304 ( (fn[cnt-3] == 'z') || (fn[cnt-3] == 'Z') ) ){
311 /**********************************************************************************************/
313 /* This function loads a Snes-Backup image */
314 /**********************************************************************************************/
316 #pragma warning(disable : 4101)
317 #pragma warning(disable : 4700)
319 bool8_32 CMemory::LoadROM (const char *filename)
321 unsigned long FileSize = 0;
324 bool8_32 Interleaved = FALSE;
325 bool8_32 Tales = FALSE;
326 char dir [_MAX_DIR + 1];
327 char drive [_MAX_DRIVE + 1];
328 char name [_MAX_FNAME + 1];
329 char ext [_MAX_EXT + 1];
330 char fname [_MAX_PATH + 1];
333 memset (&SNESGameFixes, 0, sizeof(SNESGameFixes));
334 SNESGameFixes.SRAMInitialValue = 0x60;
336 memset (bytes0x2000, 0, 0x2000);
337 CPU.TriedInterleavedMode2 = FALSE;
341 PathSplit(filename, drive, dir, name, ext);
342 PathMake(fname, drive, dir, name, ext);
344 int32 TotalFileSize = 0;
347 if( checkzip( fname ) )
349 if (!LoadZip (fname, &TotalFileSize, &HeaderCount))
352 strcpy (ROMFilename, fname);
357 if ((ROMFile = OPEN_STREAM (fname, "rb")) == NULL)
360 strcpy (ROMFilename, fname);
364 bool8_32 more = FALSE;
368 FileSize = READ_STREAM (ptr, MAX_ROM_SIZE + 0x200 - (ptr - ROM), ROMFile);
369 CLOSE_STREAM (ROMFile);
370 int calc_size = (FileSize / 0x2000) * 0x2000;
372 if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) ||
373 Settings.ForceHeader)
375 memmove (ptr, ptr + 512, calc_size);
380 TotalFileSize += FileSize;
383 if (ptr - ROM < MAX_ROM_SIZE + 0x200 &&
384 (isdigit (ext [0]) && ext [1] == 0 && ext [0] < '9'))
388 PathMake(fname, drive, dir, name, ext);
391 if (ptr - ROM < MAX_ROM_SIZE + 0x200 &&
392 (((len = strlen (name)) == 7 || len == 8) &&
393 strncasecmp (name, "sf", 2) == 0 &&
394 isdigit (name [2]) && isdigit (name [3]) && isdigit (name [4]) &&
395 isdigit (name [5]) && isalpha (name [len - 1])))
399 PathMake(fname, drive, dir, name, ext);
403 } while (more && (ROMFile = OPEN_STREAM (fname, "rb")) != NULL);
406 if (HeaderCount == 0)
407 S9xMessage (S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found.");
410 if (HeaderCount == 1)
411 S9xMessage (S9X_INFO, S9X_HEADERS_INFO,
412 "Found ROM file header (and ignored it).");
414 S9xMessage (S9X_INFO, S9X_HEADERS_INFO,
415 "Found multiple ROM file headers (and ignored them).");
418 CheckForIPSPatch (filename, HeaderCount != 0, TotalFileSize);
419 int orig_hi_score, orig_lo_score;
420 int hi_score, lo_score;
422 orig_hi_score = hi_score = ScoreHiROM (FALSE);
423 orig_lo_score = lo_score = ScoreLoROM (FALSE);
425 if (HeaderCount == 0 && !Settings.ForceNoHeader &&
426 ((hi_score > lo_score && ScoreHiROM (TRUE) > hi_score) ||
427 (hi_score <= lo_score && ScoreLoROM (TRUE) > lo_score)))
429 memmove (Memory.ROM, Memory.ROM + 512, TotalFileSize - 512);
430 TotalFileSize -= 512;
431 S9xMessage (S9X_INFO, S9X_HEADER_WARNING,
432 "Try specifying the -nhd command line option if the game doesn't work\n");
435 CalculatedSize = (TotalFileSize / 0x2000) * 0x2000;
436 ZeroMemory (ROM + CalculatedSize, MAX_ROM_SIZE - CalculatedSize);
438 // Check for cherryroms.com DAIKAIJYUMONOGATARI2
440 if (CalculatedSize == 0x500000 &&
441 strncmp ((const char *)&ROM [0x40ffc0], "DAIKAIJYUMONOGATARI2", 20) == 0 &&
442 strncmp ((const char *)&ROM [0x40ffb0], "18AE6J", 6) == 0 &&
443 memcmp (&ROM[0x40ffb0], &ROM [0xffb0], 0x30))
445 memmove (&ROM[0x100000], ROM, 0x500000);
446 memmove (ROM, &ROM[0x500000], 0x100000);
449 Interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2;
450 if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score))
455 // Ignore map type byte if not 0x2x or 0x3x
456 if ((ROM [0x7fd5] & 0xf0) == 0x20 || (ROM [0x7fd5] & 0xf0) == 0x30)
458 switch (ROM [0x7fd5] & 0xf)
461 if (strncmp ((char *) &ROM [0x7fc0], "TREASURE HUNTER G", 17) != 0)
466 if (!Settings.ForceLoROM &&
467 strncmp ((char *) &ROM [0x7fc0], "SUPER FORMATION SOCCE", 21) != 0 &&
468 strncmp ((char *) &ROM [0x7fc0], "Star Ocean", 10) != 0)
484 if ((ROM [0xffd5] & 0xf0) == 0x20 || (ROM [0xffd5] & 0xf0) == 0x30)
486 switch (ROM [0xffd5] & 0xf)
499 if (!Settings.ForceHiROM && !Settings.ForceLoROM &&
500 !Settings.ForceInterleaved && !Settings.ForceInterleaved2 &&
501 !Settings.ForceNotInterleaved && !Settings.ForcePAL &&
502 !Settings.ForceSuperFX && !Settings.ForceDSP1 &&
503 !Settings.ForceSA1 && !Settings.ForceC4 &&
506 if (strncmp ((char *) &ROM [0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0)
513 if (strncmp ((char *) &ROM [0x7fc0], "SP MOMOTAROU DENTETSU2", 22) == 0)
520 if (CalculatedSize == 0x100000 &&
521 strncmp ((char *) &ROM [0xffc0], "WWF SUPER WRESTLEMANIA", 22) == 0)
525 memmove (&ROM[0x100000] , ROM, 0x100000);
526 for (cvcount = 0; cvcount < 16; cvcount++)
528 memmove (&ROM[0x8000 * cvcount], &ROM[0x10000 * cvcount + 0x100000 + 0x8000], 0x8000);
529 memmove (&ROM[0x8000 * cvcount + 0x80000], &ROM[0x10000 * cvcount + 0x100000], 0x8000);
533 ZeroMemory (ROM + CalculatedSize, MAX_ROM_SIZE - CalculatedSize);
537 if (!Settings.ForceNotInterleaved && Interleaved)
539 CPU.TriedInterleavedMode2 = TRUE;
540 S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO,
541 "ROM image is in interleaved format - converting...");
543 int nblocks = CalculatedSize >> 16;
547 while (nblocks <= step)
557 for (i = 0; i < 0x40; i += 2)
559 blocks [i + 0] = (i >> 1) + 0x20;
560 blocks [i + 1] = (i >> 1) + 0x00;
562 for (i = 0; i < 0x80; i += 2)
564 blocks [i + 0x40] = (i >> 1) + 0x80;
565 blocks [i + 0x41] = (i >> 1) + 0x40;
571 if (Settings.ForceInterleaved2)
573 for (i = 0; i < nblocks * 2; i++)
575 blocks [i] = (i & ~0x1e) | ((i & 2) << 2) | ((i & 4) << 2) |
576 ((i & 8) >> 2) | ((i & 16) >> 2);
586 for (i = 0; i < nblocks; i++)
588 blocks [i * 2] = i + nblocks;
589 blocks [i * 2 + 1] = i;
593 uint8 *tmp = (uint8 *) malloc (0x8000);
596 for (i = 0; i < nblocks * 2; i++)
598 for (int j = i; j < nblocks * 2; j++)
602 memmove (tmp, &ROM [blocks [j] * 0x8000], 0x8000);
603 memmove (&ROM [blocks [j] * 0x8000],
604 &ROM [blocks [i] * 0x8000], 0x8000);
605 memmove (&ROM [blocks [i] * 0x8000], tmp, 0x8000);
606 uint8 b = blocks [j];
607 blocks [j] = blocks [i];
616 hi_score = ScoreHiROM (FALSE);
617 lo_score = ScoreLoROM (FALSE);
620 (lo_score >= hi_score || hi_score < 0)) ||
622 (hi_score > lo_score || lo_score < 0)))
624 if (retry_count == 0)
626 S9xMessage (S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO,
627 "ROM lied about its type! Trying again.");
628 Settings.ForceNotInterleaved = TRUE;
629 Settings.ForceInterleaved = FALSE;
638 S9xLoadCheatFile (S9xGetFilename(FILE_CHT));
647 void S9xDeinterleaveMode2 ()
649 S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO,
650 "ROM image is in interleaved format - converting...");
652 int nblocks = Memory.CalculatedSize >> 15;
655 while (nblocks <= step)
662 for (i = 0; i < nblocks * 2; i++)
664 blocks [i] = (i & ~0x1e) | ((i & 2) << 2) | ((i & 4) << 2) |
665 ((i & 8) >> 2) | ((i & 16) >> 2);
668 uint8 *tmp = (uint8 *) malloc (0x8000);
672 for (i = 0; i < nblocks * 2; i++)
674 for (int j = i; j < nblocks * 2; j++)
678 memmove (tmp, &Memory.ROM [blocks [j] * 0x8000], 0x8000);
679 memmove (&Memory.ROM [blocks [j] * 0x8000],
680 &Memory.ROM [blocks [i] * 0x8000], 0x8000);
681 memmove (&Memory.ROM [blocks [i] * 0x8000], tmp, 0x8000);
682 uint8 b = blocks [j];
683 blocks [j] = blocks [i];
691 Memory.InitROM (FALSE);
695 void CMemory::InitROM (bool8_32 Interleaved)
698 SuperFX.nRomBanks = CalculatedSize >> 15;
700 Settings.MultiPlayer5Master = Settings.MultiPlayer5;
701 Settings.MouseMaster = Settings.Mouse;
702 Settings.SuperScopeMaster = Settings.SuperScope;
703 Settings.DSP1Master = Settings.ForceDSP1;
704 Settings.SuperFX = FALSE;
705 Settings.SA1 = FALSE;
707 Settings.SDD1 = FALSE;
708 Settings.SRTC = FALSE;
710 ZeroMemory (BlockIsRAM, MEMMAP_NUM_BLOCKS);
711 ZeroMemory (BlockIsROM, MEMMAP_NUM_BLOCKS);
714 memset (ROMId, 0, 5);
715 memset (CompanyId, 0, 3);
719 Memory.SRAMSize = ROM [0xffd8];
720 strncpy (ROMName, (char *) &ROM[0xffc0], ROM_NAME_LEN - 1);
721 ROMSpeed = ROM [0xffd5];
722 ROMType = ROM [0xffd6];
723 ROMSize = ROM [0xffd7];
724 ROMChecksum = ROM [0xffde] + (ROM [0xffdf] << 8);
725 ROMComplementChecksum = ROM [0xffdc] + (ROM [0xffdd] << 8);
727 memmove (ROMId, &ROM [0xffb2], 4);
728 memmove (CompanyId, &ROM [0xffb0], 2);
730 // Try to auto-detect the DSP1 chip
731 if (!Settings.ForceNoDSP1 &&
732 (ROMType & 0xf) >= 3 && (ROMType & 0xf0) == 0)
733 Settings.DSP1Master = TRUE;
735 Settings.SDD1 = Settings.ForceSDD1;
736 if ((ROMType & 0xf0) == 0x40)
737 Settings.SDD1 = !Settings.ForceNoSDD1;
742 if ((ROMSpeed & ~0x10) == 0x25)
743 TalesROMMap (Interleaved);
745 if ((ROMSpeed & ~0x10) == 0x22 &&
746 strncmp (ROMName, "Super Street Fighter", 20) != 0)
755 Memory.HiROM = FALSE;
756 Memory.SRAMSize = ROM [0x7fd8];
757 ROMSpeed = ROM [0x7fd5];
758 ROMType = ROM [0x7fd6];
759 ROMSize = ROM [0x7fd7];
760 ROMChecksum = ROM [0x7fde] + (ROM [0x7fdf] << 8);
761 ROMComplementChecksum = ROM [0x7fdc] + (ROM [0x7fdd] << 8);
762 memmove (ROMId, &ROM [0x7fb2], 4);
763 memmove (CompanyId, &ROM [0x7fb0], 2);
765 strncpy (ROMName, (char *) &ROM[0x7fc0], ROM_NAME_LEN - 1);
766 Settings.SuperFX = Settings.ForceSuperFX;
768 if ((ROMType & 0xf0) == 0x10)
769 Settings.SuperFX = !Settings.ForceNoSuperFX;
771 // Try to auto-detect the DSP1 chip
772 if (!Settings.ForceNoDSP1 &&
773 (ROMType & 0xf) >= 3 && (ROMType & 0xf0) == 0)
774 Settings.DSP1Master = TRUE;
776 Settings.SDD1 = Settings.ForceSDD1;
777 if ((ROMType & 0xf0) == 0x40)
778 Settings.SDD1 = !Settings.ForceNoSDD1;
783 Settings.C4 = Settings.ForceC4;
784 if ((ROMType & 0xf0) == 0xf0 &&
785 (strncmp (ROMName, "MEGAMAN X", 9) == 0 ||
786 strncmp (ROMName, "ROCKMAN X", 9) == 0))
788 Settings.C4 = !Settings.ForceNoC4;
791 if (Settings.SuperFX)
793 //::SRAM = ROM + 1024 * 1024 * 4;
795 Settings.MultiPlayer5Master = FALSE;
796 //Settings.MouseMaster = FALSE;
797 //Settings.SuperScopeMaster = FALSE;
798 Settings.DSP1Master = FALSE;
799 Settings.SA1 = FALSE;
801 Settings.SDD1 = FALSE;
804 if (Settings.ForceSA1 ||
805 (!Settings.ForceNoSA1 && (ROMSpeed & ~0x10) == 0x23 &&
806 (ROMType & 0xf) > 3 && (ROMType & 0xf0) == 0x30))
809 Settings.MultiPlayer5Master = FALSE;
810 //Settings.MouseMaster = FALSE;
811 //Settings.SuperScopeMaster = FALSE;
812 Settings.DSP1Master = FALSE;
814 Settings.SDD1 = FALSE;
818 if ((ROMSpeed & ~0x10) == 0x25)
819 TalesROMMap (Interleaved);
821 if (strncmp ((char *) &Memory.ROM [0x7fc0], "SOUND NOVEL-TCOOL", 17) == 0 ||
822 strncmp ((char *) &Memory.ROM [0x7fc0], "DERBY STALLION 96", 17) == 0)
825 Settings.DSP1Master = FALSE;
828 if (strncmp ((char *) &Memory.ROM [0x7fc0], "THOROUGHBRED BREEDER3", 21) == 0 ||
829 strncmp ((char *) &Memory.ROM [0x7fc0], "RPG-TCOOL 2", 11) == 0)
832 Settings.DSP1Master = FALSE;
835 if (strncmp ((char *) &Memory.ROM [0x7fc0], "DEZAEMON ", 10) == 0)
837 Settings.DSP1Master = FALSE;
838 SRAM1024KLoROMMap ();
841 if (strncmp ((char *) &Memory.ROM [0x7fc0], "ADD-ON BASE CASSETE", 19) == 0)
843 Settings.MultiPlayer5Master = FALSE;
844 Settings.MouseMaster = FALSE;
845 Settings.SuperScopeMaster = FALSE;
846 Settings.DSP1Master = FALSE;
847 SufamiTurboLoROMMap();
851 if ((ROMSpeed & ~0x10) == 0x22 &&
852 strncmp (ROMName, "Super Street Fighter", 20) != 0)
861 int size = CalculatedSize;
867 uint32 remainder = CalculatedSize - size;
874 for (i = 0; i < size; i++)
877 for (i = 0; i < (int) remainder; i++)
878 sum2 += ROM [size + i];
883 if (CalculatedSize == 0x500000 && Memory.HiROM &&
884 strncmp ((const char *)&ROM[0xffb0], "18AZ", 4) == 0 &&
885 !memcmp(&ROM[0xffd5], "\x3a\xf9\x0d\x03\x00\x33\x00", 7))
888 sum1 += sum2 * (size / remainder);
893 if (Settings.ForceNTSC)
894 Settings.PAL = FALSE;
896 if (Settings.ForcePAL)
901 Settings.PAL = ROM [0xffd9] >= 2;
903 Settings.PAL = ROM [0x7fd9] >= 2;
907 Settings.FrameTime = Settings.FrameTimePAL;
908 Memory.ROMFramesPerSecond = 50;
912 Settings.FrameTime = Settings.FrameTimeNTSC;
913 Memory.ROMFramesPerSecond = 60;
916 ROMName[ROM_NAME_LEN - 1] = 0;
917 if (strlen (ROMName))
919 char *p = ROMName + strlen (ROMName) - 1;
921 while (p > ROMName && *(p - 1) == ' ')
926 if (Settings.SuperFX)
928 CPU.Memory_SRAMMask = 0xffff;
929 Memory.SRAMSize = 16;
933 CPU.Memory_SRAMMask = Memory.SRAMSize ?
934 ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0;
937 IAPU.OneCycle = ONE_APU_CYCLE;
938 Settings.Shutdown = Settings.ShutdownMaster;
940 SetDSP = &DSP1SetByte;
941 GetDSP = &DSP1GetByte;
944 sprintf (ROMName, "%s", Safe (ROMName));
945 sprintf (ROMId, "%s", Safe (ROMId));
946 sprintf (CompanyId, "%s", Safe (CompanyId));
948 sprintf (String, "\"%s\" [%s] %s, %s, Type: %s, Mode: %s, TV: %s, S-RAM: %s, ROMId: %s Company: %2.2s",
950 (ROMChecksum + ROMComplementChecksum != 0xffff ||
951 ROMChecksum != sum1) ? "bad checksum" : "checksum ok",
961 S9xMessage (S9X_INFO, S9X_ROM_INFO, String);
964 bool8_32 CMemory::LoadSRAM (const char *filename)
966 int size = Memory.SRAMSize ?
967 (1 << (Memory.SRAMSize + 3)) * 128 : 0;
969 memset (SRAM, SNESGameFixes.SRAMInitialValue, 0x20000);
977 if ((file = fopen(filename, "rb")))
979 int len = fread ((char*) ::SRAM, 1, 0x20000, file);
981 if (len - size == 512)
983 // S-RAM file has a header - remove it
984 memmove (::SRAM, ::SRAM + 512, size);
986 if (len == size + SRTC_SRAM_PAD)
988 S9xSRTCPostLoadState ();
991 rtc.mode = MODE_READ;
1002 S9xSDD1LoadLoggedData ();
1007 bool8_32 CMemory::SaveSRAM (const char *filename)
1009 size_t size = Memory.SRAMSize ?
1010 (1 << (Memory.SRAMSize + 3)) * 128 : 0;
1014 size += SRTC_SRAM_PAD;
1015 S9xSRTCPreSaveState ();
1018 if (Settings.SDD1) S9xSDD1SaveLoggedData ();
1020 if (size > 0x20000) size = 0x20000;
1022 if (size && *Memory.ROMFilename)
1025 if ((file = fopen (filename, "wb")))
1027 if (fwrite((char *) ::SRAM, size, 1, file) == size) {
1039 void CMemory::FixROMSpeed ()
1043 for (c = 0x800; c < 0x1000; c++)
1046 MemorySpeed [c] = (uint8) CPU.FastROMSpeed;
1050 void CMemory::WriteProtectROM ()
1052 memmove ((void *) WriteMap, (void *) Map, sizeof (Map));
1053 for (int c = 0; c < 0x1000; c++)
1056 WriteMap [c] = (uint8 *) MAP_NONE;
1060 void CMemory::MapRAM ()
1064 // Banks 7e->7f, RAM
1065 for (c = 0; c < 16; c++)
1067 Map [c + 0x7e0] = RAM;
1068 Map [c + 0x7f0] = RAM + 0x10000;
1069 BlockIsRAM [c + 0x7e0] = TRUE;
1070 BlockIsRAM [c + 0x7f0] = TRUE;
1071 BlockIsROM [c + 0x7e0] = FALSE;
1072 BlockIsROM [c + 0x7f0] = FALSE;
1075 // Banks 70->77, S-RAM
1076 for (c = 0; c < 0x80; c++)
1078 Map [c + 0x700] = (uint8 *) MAP_LOROM_SRAM;
1079 BlockIsRAM [c + 0x700] = TRUE;
1080 BlockIsROM [c + 0x700] = FALSE;
1084 void CMemory::MapExtraRAM ()
1088 // Banks 7e->7f, RAM
1089 for (c = 0; c < 16; c++)
1091 Map [c + 0x7e0] = RAM;
1092 Map [c + 0x7f0] = RAM + 0x10000;
1093 BlockIsRAM [c + 0x7e0] = TRUE;
1094 BlockIsRAM [c + 0x7f0] = TRUE;
1095 BlockIsROM [c + 0x7e0] = FALSE;
1096 BlockIsROM [c + 0x7f0] = FALSE;
1099 // Banks 70->73, S-RAM
1100 for (c = 0; c < 16; c++)
1102 Map [c + 0x700] = ::SRAM;
1103 Map [c + 0x710] = ::SRAM + 0x8000;
1104 Map [c + 0x720] = ::SRAM + 0x10000;
1105 Map [c + 0x730] = ::SRAM + 0x18000;
1107 BlockIsRAM [c + 0x700] = TRUE;
1108 BlockIsROM [c + 0x700] = FALSE;
1109 BlockIsRAM [c + 0x710] = TRUE;
1110 BlockIsROM [c + 0x710] = FALSE;
1111 BlockIsRAM [c + 0x720] = TRUE;
1112 BlockIsROM [c + 0x720] = FALSE;
1113 BlockIsRAM [c + 0x730] = TRUE;
1114 BlockIsROM [c + 0x730] = FALSE;
1118 void CMemory::LoROMMap ()
1123 // Banks 00->3f and 80->bf
1124 for (c = 0; c < 0x400; c += 16)
1126 Map [c + 0] = Map [c + 0x800] = RAM;
1127 Map [c + 1] = Map [c + 0x801] = RAM;
1128 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1129 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1131 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1132 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1133 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1134 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1135 if (Settings.DSP1Master)
1137 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1138 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1143 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_C4;
1144 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_C4;
1148 Map [c + 6] = Map [c + 0x806] = (uint8 *) bytes0x2000 - 0x6000;
1149 Map [c + 7] = Map [c + 0x807] = (uint8 *) bytes0x2000 - 0x6000;
1152 for (i = c + 8; i < c + 16; i++)
1154 Map [i] = Map [i + 0x800] = &ROM [(c << 11) % CalculatedSize] - 0x8000;
1155 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1158 for (i = c; i < c + 16; i++)
1163 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1167 if (Settings.DSP1Master)
1169 // Banks 30->3f and b0->bf
1170 for (c = 0x300; c < 0x400; c += 16)
1172 for (i = c + 8; i < c + 16; i++)
1174 Map [i] = Map [i + 0x800] = (uint8 *) MAP_DSP;
1175 BlockIsROM [i] = BlockIsROM [i + 0x800] = FALSE;
1180 // Banks 40->7f and c0->ff
1181 for (c = 0; c < 0x400; c += 16)
1183 for (i = c; i < c + 8; i++)
1184 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) % CalculatedSize];
1186 for (i = c + 8; i < c + 16; i++)
1187 Map [i + 0x400] = Map [i + 0xc00] = &ROM [((c << 11) + 0x200000) % CalculatedSize - 0x8000];
1189 for (i = c; i < c + 16; i++)
1191 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1192 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1196 if (Settings.DSP1Master)
1198 for (c = 0; c < 0x100; c++)
1200 Map [c + 0xe00] = (uint8 *) MAP_DSP;
1201 MemorySpeed [c + 0xe00] = SLOW_ONE_CYCLE;
1202 BlockIsROM [c + 0xe00] = FALSE;
1209 void CMemory::HiROMMap ()
1214 // Banks 00->3f and 80->bf
1215 for (c = 0; c < 0x400; c += 16)
1217 Map [c + 0] = Map [c + 0x800] = RAM;
1218 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1219 Map [c + 1] = Map [c + 0x801] = RAM;
1220 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1222 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1223 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1224 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1225 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1226 if (Settings.DSP1Master)
1228 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1229 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1233 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1234 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1237 for (i = c + 8; i < c + 16; i++)
1239 Map [i] = Map [i + 0x800] = &ROM [(c << 12) % CalculatedSize];
1240 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1243 for (i = c; i < c + 16; i++)
1248 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1252 // Banks 30->3f and b0->bf, address ranges 6000->7fff is S-RAM.
1253 for (c = 0; c < 16; c++)
1255 Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1256 Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1257 Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1258 Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1259 BlockIsRAM [0x306 + (c << 4)] = TRUE;
1260 BlockIsRAM [0x307 + (c << 4)] = TRUE;
1261 BlockIsRAM [0xb06 + (c << 4)] = TRUE;
1262 BlockIsRAM [0xb07 + (c << 4)] = TRUE;
1265 // Banks 40->7f and c0->ff
1266 for (c = 0; c < 0x400; c += 16)
1268 for (i = c; i < c + 16; i++)
1270 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1271 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1272 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1280 void CMemory::TalesROMMap (bool8_32 Interleaved)
1285 uint32 OFFSET0 = 0x400000;
1286 uint32 OFFSET1 = 0x400000;
1287 uint32 OFFSET2 = 0x000000;
1296 // Banks 00->3f and 80->bf
1297 for (c = 0; c < 0x400; c += 16)
1299 Map [c + 0] = Map [c + 0x800] = RAM;
1300 Map [c + 1] = Map [c + 0x801] = RAM;
1301 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1302 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1304 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1305 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1306 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1307 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1308 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1309 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1310 for (i = c + 8; i < c + 16; i++)
1312 Map [i] = &ROM [((c << 12) + OFFSET0) % CalculatedSize];
1313 Map [i + 0x800] = &ROM [((c << 12) + OFFSET0) % CalculatedSize];
1314 BlockIsROM [i] = TRUE;
1315 BlockIsROM [i + 0x800] = TRUE;
1318 for (i = c; i < c + 16; i++)
1323 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1327 // Banks 30->3f and b0->bf, address ranges 6000->7ffff is S-RAM.
1328 for (c = 0; c < 16; c++)
1330 Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1331 Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1332 Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1333 Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM;
1334 BlockIsRAM [0x306 + (c << 4)] = TRUE;
1335 BlockIsRAM [0x307 + (c << 4)] = TRUE;
1336 BlockIsRAM [0xb06 + (c << 4)] = TRUE;
1337 BlockIsRAM [0xb07 + (c << 4)] = TRUE;
1340 // Banks 40->7f and c0->ff
1341 for (c = 0; c < 0x400; c += 16)
1343 for (i = c; i < c + 8; i++)
1345 Map [i + 0x400] = &ROM [((c << 12) + OFFSET1) % CalculatedSize];
1346 Map [i + 0x408] = &ROM [((c << 12) + OFFSET1) % CalculatedSize];
1347 Map [i + 0xc00] = &ROM [((c << 12) + OFFSET2) % CalculatedSize];
1348 Map [i + 0xc08] = &ROM [((c << 12) + OFFSET2) % CalculatedSize];
1349 BlockIsROM [i + 0x400] = TRUE;
1350 BlockIsROM [i + 0x408] = TRUE;
1351 BlockIsROM [i + 0xc00] = TRUE;
1352 BlockIsROM [i + 0xc08] = TRUE;
1353 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1354 MemorySpeed [i + 0x408] = MemorySpeed [i + 0xc08] = SLOW_ONE_CYCLE;
1361 void CMemory::AlphaROMMap ()
1366 // Banks 00->3f and 80->bf
1367 for (c = 0; c < 0x400; c += 16)
1369 Map [c + 0] = Map [c + 0x800] = RAM;
1370 Map [c + 1] = Map [c + 0x801] = RAM;
1371 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1372 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1374 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1375 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1376 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1377 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1378 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1379 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1381 for (i = c + 8; i < c + 16; i++)
1383 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1384 BlockIsROM [i] = TRUE;
1387 for (i = c; i < c + 16; i++)
1392 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1396 // Banks 40->7f and c0->ff
1398 for (c = 0; c < 0x400; c += 16)
1400 for (i = c; i < c + 16; i++)
1402 Map [i + 0x400] = &ROM [(c << 12) % CalculatedSize];
1403 Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1404 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1405 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1413 void CMemory::SuperFXROMMap ()
1418 // Banks 00->3f and 80->bf
1419 for (c = 0; c < 0x400; c += 16)
1421 Map [c + 0] = Map [c + 0x800] = RAM;
1422 Map [c + 1] = Map [c + 0x801] = RAM;
1423 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1424 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1426 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1427 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1428 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1429 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1430 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1431 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1432 for (i = c + 8; i < c + 16; i++)
1434 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1435 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1438 for (i = c; i < c + 8; i++)
1443 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1447 // Banks 40->7f and c0->ff
1448 for (c = 0; c < 0x400; c += 16)
1450 for (i = c; i < c + 16; i++)
1452 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1453 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1454 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1458 // Banks 7e->7f, RAM
1459 for (c = 0; c < 16; c++)
1461 Map [c + 0x7e0] = RAM;
1462 Map [c + 0x7f0] = RAM + 0x10000;
1463 BlockIsRAM [c + 0x7e0] = TRUE;
1464 BlockIsRAM [c + 0x7f0] = TRUE;
1465 BlockIsROM [c + 0x7e0] = FALSE;
1466 BlockIsROM [c + 0x7f0] = FALSE;
1469 // Banks 70->71, S-RAM
1470 for (c = 0; c < 32; c++)
1472 Map [c + 0x700] = ::SRAM + (((c >> 4) & 1) << 16);
1473 BlockIsRAM [c + 0x700] = TRUE;
1474 BlockIsROM [c + 0x700] = FALSE;
1477 // Banks 00->3f and 80->bf address ranges 6000->7fff is RAM.
1478 for (c = 0; c < 0x40; c++)
1480 Map [0x006 + (c << 4)] = (uint8 *) ::SRAM - 0x6000;
1481 Map [0x007 + (c << 4)] = (uint8 *) ::SRAM - 0x6000;
1482 Map [0x806 + (c << 4)] = (uint8 *) ::SRAM - 0x6000;
1483 Map [0x807 + (c << 4)] = (uint8 *) ::SRAM - 0x6000;
1484 BlockIsRAM [0x006 + (c << 4)] = TRUE;
1485 BlockIsRAM [0x007 + (c << 4)] = TRUE;
1486 BlockIsRAM [0x806 + (c << 4)] = TRUE;
1487 BlockIsRAM [0x807 + (c << 4)] = TRUE;
1489 // Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K
1490 // block is repeated twice in each 64K block.
1491 for (c = 0; c < 64; c++)
1493 memmove (&ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000);
1494 memmove (&ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000);
1500 void CMemory::SA1ROMMap ()
1505 // Banks 00->3f and 80->bf
1506 for (c = 0; c < 0x400; c += 16)
1508 Map [c + 0] = Map [c + 0x800] = RAM;
1509 Map [c + 1] = Map [c + 0x801] = RAM;
1510 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1511 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1513 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1514 Map [c + 3] = Map [c + 0x803] = (uint8 *) &Memory.FillRAM [0x3000] - 0x3000;
1515 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1516 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1517 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_BWRAM;
1518 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_BWRAM;
1519 for (i = c + 8; i < c + 16; i++)
1521 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1522 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1525 for (i = c; i < c + 16; i++)
1530 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1535 for (c = 0; c < 0x400; c += 16)
1537 for (i = c; i < c + 16; i++)
1538 Map [i + 0x400] = (uint8 *) &SRAM [(c << 12) & 0x1ffff];
1540 for (i = c; i < c + 16; i++)
1542 MemorySpeed [i + 0x400] = SLOW_ONE_CYCLE;
1543 BlockIsROM [i + 0x400] = FALSE;
1548 for (c = 0; c < 0x400; c += 16)
1550 for (i = c; i < c + 16; i++)
1552 Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1553 MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1554 BlockIsROM [i + 0xc00] = TRUE;
1558 for (c = 0; c < 16; c++)
1560 Map [c + 0x7e0] = RAM;
1561 Map [c + 0x7f0] = RAM + 0x10000;
1562 BlockIsRAM [c + 0x7e0] = TRUE;
1563 BlockIsRAM [c + 0x7f0] = TRUE;
1564 BlockIsROM [c + 0x7e0] = FALSE;
1565 BlockIsROM [c + 0x7f0] = FALSE;
1569 // Now copy the map and correct it for the SA1 CPU.
1570 memmove ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap));
1571 memmove ((void *) SA1.Map, (void *) Map, sizeof (Map));
1573 // Banks 00->3f and 80->bf
1574 for (c = 0; c < 0x400; c += 16)
1576 SA1.Map [c + 0] = SA1.Map [c + 0x800] = &Memory.FillRAM [0x3000];
1577 SA1.Map [c + 1] = SA1.Map [c + 0x801] = (uint8 *) MAP_NONE;
1578 SA1.WriteMap [c + 0] = SA1.WriteMap [c + 0x800] = &Memory.FillRAM [0x3000];
1579 SA1.WriteMap [c + 1] = SA1.WriteMap [c + 0x801] = (uint8 *) MAP_NONE;
1583 for (c = 0; c < 0x100; c++)
1584 SA1.Map [c + 0x600] = SA1.WriteMap [c + 0x600] = (uint8 *) MAP_BWRAM_BITMAP;
1589 void CMemory::LoROM24MBSMap ()
1594 // Banks 00->3f and 80->bf
1595 for (c = 0; c < 0x400; c += 16)
1597 Map [c + 0] = Map [c + 0x800] = RAM;
1598 Map [c + 1] = Map [c + 0x801] = RAM;
1599 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1600 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1602 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1603 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1604 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1605 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1606 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1607 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1609 for (i = c + 8; i < c + 16; i++)
1611 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1612 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1615 for (i = c; i < c + 16; i++)
1620 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1624 // Banks 00->3f and 80->bf
1625 for (c = 0; c < 0x200; c += 16)
1627 Map [c + 0x800] = RAM;
1628 Map [c + 0x801] = RAM;
1629 BlockIsRAM [c + 0x800] = TRUE;
1630 BlockIsRAM [c + 0x801] = TRUE;
1632 Map [c + 0x802] = (uint8 *) MAP_PPU;
1633 Map [c + 0x803] = (uint8 *) MAP_PPU;
1634 Map [c + 0x804] = (uint8 *) MAP_CPU;
1635 Map [c + 0x805] = (uint8 *) MAP_CPU;
1636 Map [c + 0x806] = (uint8 *) MAP_NONE;
1637 Map [c + 0x807] = (uint8 *) MAP_NONE;
1639 for (i = c + 8; i < c + 16; i++)
1641 Map [i + 0x800] = &ROM [c << 11] - 0x8000 + 0x200000;
1642 BlockIsROM [i + 0x800] = TRUE;
1645 for (i = c; i < c + 16; i++)
1649 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1653 // Banks 40->7f and c0->ff
1654 for (c = 0; c < 0x400; c += 16)
1656 for (i = c; i < c + 8; i++)
1657 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000];
1659 for (i = c + 8; i < c + 16; i++)
1660 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000];
1662 for (i = c; i < c + 16; i++)
1664 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1665 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1673 void CMemory::SufamiTurboLoROMMap ()
1678 // Banks 00->3f and 80->bf
1679 for (c = 0; c < 0x400; c += 16)
1681 Map [c + 0] = Map [c + 0x800] = RAM;
1682 Map [c + 1] = Map [c + 0x801] = RAM;
1683 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1684 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1686 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1687 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1688 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1689 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1690 if (Settings.DSP1Master)
1692 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP;
1693 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP;
1697 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1698 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1700 for (i = c + 8; i < c + 16; i++)
1702 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1703 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1706 for (i = c; i < c + 16; i++)
1711 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1715 if (Settings.DSP1Master)
1717 // Banks 30->3f and b0->bf
1718 for (c = 0x300; c < 0x400; c += 16)
1720 for (i = c + 8; i < c + 16; i++)
1722 Map [i] = Map [i + 0x800] = (uint8 *) MAP_DSP;
1723 BlockIsROM [i] = BlockIsROM [i + 0x800] = FALSE;
1728 // Banks 40->7f and c0->ff
1729 for (c = 0; c < 0x400; c += 16)
1731 for (i = c; i < c + 8; i++)
1732 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000];
1734 for (i = c + 8; i < c + 16; i++)
1735 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000];
1737 for (i = c; i < c + 16; i++)
1739 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1740 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1744 if (Settings.DSP1Master)
1746 for (c = 0; c < 0x100; c++)
1748 Map [c + 0xe00] = (uint8 *) MAP_DSP;
1749 MemorySpeed [c + 0xe00] = SLOW_ONE_CYCLE;
1750 BlockIsROM [c + 0xe00] = FALSE;
1754 // Banks 7e->7f, RAM
1755 for (c = 0; c < 16; c++)
1757 Map [c + 0x7e0] = RAM;
1758 Map [c + 0x7f0] = RAM + 0x10000;
1759 BlockIsRAM [c + 0x7e0] = TRUE;
1760 BlockIsRAM [c + 0x7f0] = TRUE;
1761 BlockIsROM [c + 0x7e0] = FALSE;
1762 BlockIsROM [c + 0x7f0] = FALSE;
1765 // Banks 60->67, S-RAM
1766 for (c = 0; c < 0x80; c++)
1768 Map [c + 0x600] = (uint8 *) MAP_LOROM_SRAM;
1769 BlockIsRAM [c + 0x600] = TRUE;
1770 BlockIsROM [c + 0x600] = FALSE;
1776 void CMemory::SRAM512KLoROMMap ()
1781 // Banks 00->3f and 80->bf
1782 for (c = 0; c < 0x400; c += 16)
1784 Map [c + 0] = Map [c + 0x800] = RAM;
1785 Map [c + 1] = Map [c + 0x801] = RAM;
1786 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1787 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1789 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1790 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1791 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1792 Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU;
1793 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1794 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1796 for (i = c + 8; i < c + 16; i++)
1798 Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000;
1799 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1802 for (i = c; i < c + 16; i++)
1807 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1811 // Banks 40->7f and c0->ff
1812 for (c = 0; c < 0x400; c += 16)
1814 for (i = c; i < c + 8; i++)
1815 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000];
1817 for (i = c + 8; i < c + 16; i++)
1818 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000];
1820 for (i = c; i < c + 16; i++)
1822 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1823 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1831 void CMemory::SRAM1024KLoROMMap ()
1836 // Banks 00->3f and 80->bf
1837 for (c = 0; c < 0x400; c += 16)
1839 Map [c + 0] = Map [c + 0x800] = Map [c + 0x400] = Map [c + 0xc00] = RAM;
1840 Map [c + 1] = Map [c + 0x801] = Map [c + 0x401] = Map [c + 0xc01] = RAM;
1841 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = BlockIsRAM [c + 0x400] = BlockIsRAM [c + 0xc00] = TRUE;
1842 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = BlockIsRAM [c + 0x401] = BlockIsRAM [c + 0xc01] = TRUE;
1844 Map [c + 2] = Map [c + 0x802] = Map [c + 0x402] = Map [c + 0xc02] = (uint8 *) MAP_PPU;
1845 Map [c + 3] = Map [c + 0x803] = Map [c + 0x403] = Map [c + 0xc03] = (uint8 *) MAP_PPU;
1846 Map [c + 4] = Map [c + 0x804] = Map [c + 0x404] = Map [c + 0xc04] = (uint8 *) MAP_CPU;
1847 Map [c + 5] = Map [c + 0x805] = Map [c + 0x405] = Map [c + 0xc05] = (uint8 *) MAP_CPU;
1848 Map [c + 6] = Map [c + 0x806] = Map [c + 0x406] = Map [c + 0xc06] = (uint8 *) MAP_NONE;
1849 Map [c + 7] = Map [c + 0x807] = Map [c + 0x407] = Map [c + 0xc07] = (uint8 *) MAP_NONE;
1850 for (i = c + 8; i < c + 16; i++)
1852 Map [i] = Map [i + 0x800] = Map [i + 0x400] = Map [i + 0xc00] = &ROM [c << 11] - 0x8000;
1853 BlockIsROM [i] = BlockIsROM [i + 0x800] = BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1856 for (i = c; i < c + 16; i++)
1860 MemorySpeed [i] = MemorySpeed [i + 0x800] =
1861 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1869 void CMemory::BSHiROMMap ()
1874 // Banks 00->3f and 80->bf
1875 for (c = 0; c < 0x400; c += 16)
1877 Map [c + 0] = Map [c + 0x800] = RAM;
1878 BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE;
1879 Map [c + 1] = Map [c + 0x801] = RAM;
1880 BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE;
1882 Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU;
1883 Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU;
1884 Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU;
1885 // XXX: How large is SRAM??
1886 Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM;
1887 BlockIsRAM [c + 5] = BlockIsRAM [c + 0x805] = TRUE;
1888 Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE;
1889 Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE;
1891 for (i = c + 8; i < c + 16; i++)
1893 Map [i] = Map [i + 0x800] = &ROM [(c << 12) % CalculatedSize];
1894 BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE;
1897 for (i = c; i < c + 16; i++)
1902 MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE;
1906 // Banks 60->7d offset 0000->7fff & 60->7f offset 8000->ffff PSRAM
1907 // XXX: How large is PSRAM?
1908 for (c = 0x600; c < 0x7e0; c += 16)
1910 for (i = c; i < c + 8; i++)
1912 Map [i] = &ROM [0x400000 + (c << 11)];
1913 BlockIsRAM [i] = TRUE;
1915 for (i = c + 8; i < c + 16; i++)
1917 Map [i] = &ROM [0x400000 + (c << 11) - 0x8000];
1918 BlockIsRAM [i] = TRUE;
1922 // Banks 40->7f and c0->ff
1923 for (c = 0; c < 0x400; c += 16)
1925 for (i = c; i < c + 16; i++)
1927 Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize];
1928 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE;
1929 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE;
1937 const char *CMemory::TVStandard ()
1939 return (Settings.PAL ? "PAL" : "NTSC");
1942 const char *CMemory::Speed ()
1944 return (ROMSpeed & 0x10 ? "120ns" : "200ns");
1947 const char *CMemory::MapType ()
1949 return (HiROM ? "HiROM" : "LoROM");
1952 const char *CMemory::StaticRAMSize ()
1954 static char tmp [20];
1956 if (Memory.SRAMSize > 16)
1958 sprintf (tmp, "%dKb", (CPU.Memory_SRAMMask + 1) / 1024);
1962 const char *CMemory::Size ()
1964 static char tmp [20];
1966 if (ROMSize < 7 || ROMSize - 7 > 23)
1968 sprintf (tmp, "%dMbits", 1 << (ROMSize - 7));
1972 const char *CMemory::KartContents ()
1974 static char tmp [30];
1975 static const char *CoPro [16] = {
1976 "DSP1", "SuperFX", "OBC1", "SA-1", "S-DD1", "S-RTC", "CoPro#6",
1977 "CoPro#7", "CoPro#8", "CoPro#9", "CoPro#10", "CoPro#11", "CoPro#12",
1978 "CoPro#13", "CoPro#14", "CoPro-Custom"
1980 static const char *Contents [3] = {
1981 "ROM", "ROM+RAM", "ROM+RAM+BAT"
1984 return ("ROM only");
1986 sprintf (tmp, "%s", Contents [(ROMType & 0xf) % 3]);
1988 if ((ROMType & 0xf) >= 3)
1989 sprintf (tmp, "%s+%s", tmp, CoPro [(ROMType & 0xf0) >> 4]);
1994 const char *CMemory::MapMode ()
1996 static char tmp [4];
1997 sprintf (tmp, "%02x", ROMSpeed & ~0x10);
2001 const char *CMemory::ROMID ()
2006 void CMemory::ApplyROMFixes ()
2009 if (strncmp(ROMName, "DUNGEON MASTER", 14) == 0)
2012 SetDSP=&DSP2SetByte;
2013 GetDSP=&DSP2GetByte;
2016 // Enable S-RTC (Real Time Clock) emulation for Dai Kaijyu Monogatari 2
2017 Settings.SRTC = ((ROMType & 0xf0) >> 4) == 5;
2019 Settings.StrikeGunnerOffsetHack = strcmp (ROMName, "STRIKE GUNNER") == 0 ? 7 : 0;
2021 CPU.NMITriggerPoint = 4;
2022 if (strcmp (ROMName, "CACOMA KNIGHT") == 0)
2023 CPU.NMITriggerPoint = 25;
2025 // These games complain if the multi-player adaptor is 'connected'
2026 if (strcmp (ROMName, "TETRIS&Dr.MARIO") == 0 ||
2027 strcmp (ROMName, "JIGSAW PARTY") == 0 ||
2028 strcmp (ROMName, "SUPER PICROSS") == 0 ||
2029 strcmp (ROMName, "KIRBY NO KIRA KIZZU") == 0 ||
2030 strcmp (ROMName, "BLOCK") == 0 ||
2031 strncmp (ROMName, "SUPER BOMBLISS", 14) == 0 ||
2032 strcmp (ROMId, "ABOJ") == 0)
2034 Settings.MultiPlayer5Master = FALSE;
2035 Settings.MouseMaster = FALSE;
2036 Settings.SuperScopeMaster = FALSE;
2039 // Games which spool sound samples between the SNES and sound CPU using
2040 // H-DMA as the sample is playing.
2041 if (strcmp (ROMName, "EARTHWORM JIM 2") == 0 ||
2042 strcmp (ROMName, "PRIMAL RAGE") == 0 ||
2043 strcmp (ROMName, "CLAY FIGHTER") == 0 ||
2044 strcmp (ROMName, "ClayFighter 2") == 0 ||
2045 strncasecmp (ROMName, "MADDEN", 6) == 0 ||
2046 strncmp (ROMName, "NHL", 3) == 0 ||
2047 strcmp (ROMName, "WeaponLord") == 0)
2049 Settings.Shutdown = FALSE;
2054 if (strcmp (ROMId, "CQ ") == 0 ||
2056 strncmp (ROMId, "JG", 2) == 0 ||
2057 strcmp (ROMName, "GAIA GENSOUKI 1 JPN") == 0)
2060 Settings.APUEnabled |= 2;
2061 CPU.APU_APUExecuting |= 2;
2064 // RENDERING RANGER R2
2065 if (strcmp (ROMId, "AVCJ") == 0 ||
2067 strncmp (ROMId, "ARF", 3) == 0 ||
2068 // Tales of Phantasia
2069 strncmp (ROMId, "ATV", 3) == 0 ||
2071 strncasecmp (ROMName, "ActRaiser", 9) == 0 ||
2073 strcmp (ROMName, "SOULBLAZER - 1 USA") == 0 ||
2074 strcmp (ROMName, "SOULBLADER - 1") == 0 ||
2075 strncmp (ROMName, "SOULBLAZER 1",12) == 0 ||
2077 strncmp (ROMId, "AQT", 3) == 0 ||
2079 strncmp (ROMId, "E9 ", 3) == 0 ||
2080 strcmp (ROMName, "SLAP STICK 1 JPN") == 0 ||
2081 // ZENNIHON PURORESU2
2082 strncmp (ROMId, "APR", 3) == 0 ||
2084 strncmp (ROMId, "A4B", 3) == 0 ||
2085 // UFO KAMEN YAKISOBAN
2086 strncmp (ROMId, "Y7 ", 3) == 0 ||
2087 strncmp (ROMId, "Y9 ", 3) == 0 ||
2088 // Panic Bomber World
2089 strncmp (ROMId, "APB", 3) == 0 ||
2090 ((strncmp (ROMName, "Parlor", 6) == 0 ||
2091 strcmp (ROMName, "HEIWA Parlor!Mini8") == 0 ||
2092 strncmp (ROMName, "SANKYO Fever! ̨°ÊÞ°!", 21) == 0) &&
2093 strcmp (CompanyId, "A0") == 0) ||
2094 strcmp (ROMName, "DARK KINGDOM") == 0 ||
2095 strcmp (ROMName, "ZAN3 SFC") == 0 ||
2096 strcmp (ROMName, "HIOUDEN") == 0 ||
2097 strcmp (ROMName, "ÃݼɳÀ") == 0 ||
2098 strcmp (ROMName, "FORTUNE QUEST") == 0 ||
2099 strcmp (ROMName, "FISHING TO BASSING") == 0 ||
2100 strncmp (ROMName, "TokyoDome '95Battle 7", 21) == 0 ||
2101 strcmp (ROMName, "OHMONO BLACKBASS") == 0)
2104 // notaz: strangely enough, these games work properly with my hack enabled
2105 Settings.APUEnabled |= 2;
2106 CPU.APU_APUExecuting |= 2;
2109 if (strcmp (ROMName, "BATMAN--REVENGE JOKER") == 0)
2111 Memory.HiROM = FALSE;
2112 Memory.LoROM = TRUE;
2115 Settings.StarfoxHack = strcmp (ROMName, "STAR FOX") == 0 ||
2116 strcmp (ROMName, "STAR WING") == 0;
2117 Settings.WinterGold = strcmp (ROMName, "FX SKIING NINTENDO 96") == 0 ||
2118 strcmp (ROMName, "DIRT RACER") == 0 ||
2119 strcmp (ROMName, "Stunt Race FX") == 0 ||
2120 Settings.StarfoxHack;
2121 Settings.ChuckRock = strcmp (ROMName, "CHUCK ROCK") == 0;
2122 Settings.Dezaemon = strcmp (ROMName, "DEZAEMON") == 0;
2124 if (strcmp (ROMName, "RADICAL DREAMERS") == 0 ||
2125 strcmp (ROMName, "TREASURE CONFLIX") == 0)
2129 for (c = 0; c < 0x80; c++)
2131 Map [c + 0x700] = ROM + 0x200000 + 0x1000 * (c & 0xf0);
2132 BlockIsRAM [c + 0x700] = TRUE;
2133 BlockIsROM [c + 0x700] = FALSE;
2135 for (c = 0; c < 0x400; c += 16)
2137 Map [c + 5] = Map [c + 0x805] = ROM + 0x300000;
2138 BlockIsRAM [c + 5] = BlockIsRAM [c + 0x805] = TRUE;
2143 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE *
2144 Settings.CyclesPercentage) / 100;
2146 if (strcmp (ROMId, "ASRJ") == 0 && Settings.CyclesPercentage == 100)
2148 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 95) / 100;
2150 // Power Rangers Fight
2151 if (strncmp (ROMId, "A3R", 3) == 0 ||
2153 strncmp (ROMId, "AJE", 3) == 0)
2154 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 103) / 100;
2156 if (strcmp (ROMId, "AWVP") == 0 || strcmp (ROMId, "AWVE") == 0 ||
2157 strcmp (ROMId, "AWVJ") == 0)
2159 // Wrestlemania Arcade
2161 if (Settings.CyclesPercentage == 100)
2162 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 140) / 100; // Fixes sound
2164 Settings.WrestlemaniaArcade = TRUE;
2166 // Theme Park - disable offset-per-tile mode.
2167 if (strcmp (ROMId, "ATQP") == 0)
2168 Settings.WrestlemaniaArcade = TRUE;
2170 if (strncmp (ROMId, "A3M", 3) == 0 && Settings.CyclesPercentage == 100)
2171 // Mortal Kombat 3. Fixes cut off speech sample
2172 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100;
2174 if (strcmp (ROMName, "\x0bd\x0da\x0b2\x0d4\x0b0\x0bd\x0de") == 0 &&
2175 Settings.CyclesPercentage == 100)
2176 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 101) / 100;
2178 if (strcmp (ROMName, "WILD TRAX") == 0 ||
2179 strcmp (ROMName, "YOSSY'S ISLAND") == 0 ||
2180 strcmp (ROMName, "YOSHI'S ISLAND") == 0)
2181 CPU.TriedInterleavedMode2 = TRUE;
2183 // Start Trek: Deep Sleep 9
2184 if (strncmp (ROMId, "A9D", 3) == 0 && Settings.CyclesPercentage == 100)
2185 Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100;
2187 Settings.APURAMInitialValue = 0xff;
2189 if (strcmp (ROMName, "·³Ô¸¥Ò¶ÞÐÃݾ²") == 0 ||
2190 strcmp (ROMName, "KENTOUOU WORLDCHAMPIO") == 0 ||
2191 strcmp (ROMName, "TKO SUPERCHAMPIONSHIP") == 0 ||
2192 strcmp (ROMName, "TKO SUPER CHAMPIONSHI") == 0 ||
2193 strcmp (ROMName, "IHATOVO STORY") == 0 ||
2194 strcmp (ROMName, "WANDERERS FROM YS") == 0 ||
2195 strcmp (ROMName, "SUPER GENTYOUHISHI") == 0 ||
2196 // Panic Bomber World
2197 strncmp (ROMId, "APB", 3) == 0)
2199 Settings.APURAMInitialValue = 0;
2202 Settings.DaffyDuck = strcmp (ROMName, "DAFFY DUCK: MARV MISS") == 0;
2203 Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX;
2205 SA1.WaitAddress = NULL;
2206 SA1.WaitByteAddress1 = NULL;
2207 SA1.WaitByteAddress2 = NULL;
2210 if (strcmp (ROMId, "ZBPJ") == 0)
2212 SA1.WaitAddress = SA1.Map [0x0093f1 >> MEMMAP_SHIFT] + 0x93f1;
2213 SA1.WaitByteAddress1 = FillRAM + 0x304a;
2215 /* DAISENRYAKU EXPERTWW2 */
2216 if (strcmp (ROMId, "AEVJ") == 0)
2218 SA1.WaitAddress = SA1.Map [0x0ed18d >> MEMMAP_SHIFT] + 0xd18d;
2219 SA1.WaitByteAddress1 = FillRAM + 0x3000;
2222 if (strcmp (ROMId, "A2DJ") == 0)
2224 SA1.WaitAddress = SA1.Map [0x008b62 >> MEMMAP_SHIFT] + 0x8b62;
2226 /* Dragon Ballz HD */
2227 if (strcmp (ROMId, "AZIJ") == 0)
2229 SA1.WaitAddress = SA1.Map [0x008083 >> MEMMAP_SHIFT] + 0x8083;
2230 SA1.WaitByteAddress1 = FillRAM + 0x3020;
2232 /* SFC SDGUNDAMGNEXT */
2233 if (strcmp (ROMId, "ZX3J") == 0)
2235 SA1.WaitAddress = SA1.Map [0x0087f2 >> MEMMAP_SHIFT] + 0x87f2;
2236 SA1.WaitByteAddress1 = FillRAM + 0x30c4;
2238 /* ShougiNoHanamichi */
2239 if (strcmp (ROMId, "AARJ") == 0)
2241 SA1.WaitAddress = SA1.Map [0xc1f85a >> MEMMAP_SHIFT] + 0xf85a;
2242 SA1.WaitByteAddress1 = SRAM + 0x0c64;
2243 SA1.WaitByteAddress2 = SRAM + 0x0c66;
2245 /* KATO HIFUMI9DAN SYOGI */
2246 if (strcmp (ROMId, "A23J") == 0)
2248 SA1.WaitAddress = SA1.Map [0xc25037 >> MEMMAP_SHIFT] + 0x5037;
2249 SA1.WaitByteAddress1 = SRAM + 0x0c06;
2250 SA1.WaitByteAddress2 = SRAM + 0x0c08;
2253 if (strcmp (ROMId, "AIIJ") == 0)
2255 SA1.WaitAddress = SA1.Map [0xc100be >> MEMMAP_SHIFT] + 0x00be;
2256 SA1.WaitByteAddress1 = SRAM + 0x1002;
2257 SA1.WaitByteAddress2 = SRAM + 0x1004;
2260 if (strcmp (ROMId, "AITJ") == 0)
2262 SA1.WaitAddress = SA1.Map [0x0080b7 >> MEMMAP_SHIFT] + 0x80b7;
2264 /* J96 DREAM STADIUM */
2265 if (strcmp (ROMId, "AJ6J") == 0)
2267 SA1.WaitAddress = SA1.Map [0xc0f74a >> MEMMAP_SHIFT] + 0xf74a;
2270 if (strcmp (ROMId, "AJUJ") == 0)
2272 SA1.WaitAddress = SA1.Map [0x00d926 >> MEMMAP_SHIFT] + 0xd926;
2274 /* JKAKINOKI SHOUGI */
2275 if (strcmp (ROMId, "AKAJ") == 0)
2277 SA1.WaitAddress = SA1.Map [0x00f070 >> MEMMAP_SHIFT] + 0xf070;
2279 /* HOSHI NO KIRBY 3 & KIRBY'S DREAM LAND 3 JAP & US */
2280 if (strcmp (ROMId, "AFJJ") == 0 || strcmp (ROMId, "AFJE") == 0)
2282 SA1.WaitAddress = SA1.Map [0x0082d4 >> MEMMAP_SHIFT] + 0x82d4;
2283 SA1.WaitByteAddress1 = SRAM + 0x72a4;
2285 /* KIRBY SUPER DELUXE JAP */
2286 if (strcmp (ROMId, "AKFJ") == 0)
2288 SA1.WaitAddress = SA1.Map [0x008c93 >> MEMMAP_SHIFT] + 0x8c93;
2289 SA1.WaitByteAddress1 = FillRAM + 0x300a;
2290 SA1.WaitByteAddress2 = FillRAM + 0x300e;
2292 /* KIRBY SUPER DELUXE US */
2293 if (strcmp (ROMId, "AKFE") == 0)
2295 SA1.WaitAddress = SA1.Map [0x008cb8 >> MEMMAP_SHIFT] + 0x8cb8;
2296 SA1.WaitByteAddress1 = FillRAM + 0x300a;
2297 SA1.WaitByteAddress2 = FillRAM + 0x300e;
2299 /* SUPER MARIO RPG JAP & US */
2300 if (strcmp (ROMId, "ARWJ") == 0 || strcmp (ROMId, "ARWE") == 0)
2302 SA1.WaitAddress = SA1.Map [0xc0816f >> MEMMAP_SHIFT] + 0x816f;
2303 SA1.WaitByteAddress1 = FillRAM + 0x3000;
2306 if (strcmp (ROMId, "AVRJ") == 0)
2308 SA1.WaitAddress = SA1.Map [0x0085f2 >> MEMMAP_SHIFT] + 0x85f2;
2309 SA1.WaitByteAddress1 = FillRAM + 0x3024;
2311 /* AUGUSTA3 MASTERS NEW */
2312 if (strcmp (ROMId, "AO3J") == 0)
2314 SA1.WaitAddress = SA1.Map [0x00dddb >> MEMMAP_SHIFT] + 0xdddb;
2315 SA1.WaitByteAddress1 = FillRAM + 0x37b4;
2317 /* OSHABERI PARODIUS */
2318 if (strcmp (ROMId, "AJOJ") == 0)
2320 SA1.WaitAddress = SA1.Map [0x8084e5 >> MEMMAP_SHIFT] + 0x84e5;
2322 /* PANIC BOMBER WORLD */
2323 if (strcmp (ROMId, "APBJ") == 0)
2325 SA1.WaitAddress = SA1.Map [0x00857a >> MEMMAP_SHIFT] + 0x857a;
2327 /* PEBBLE BEACH NEW */
2328 if (strcmp (ROMId, "AONJ") == 0)
2330 SA1.WaitAddress = SA1.Map [0x00df33 >> MEMMAP_SHIFT] + 0xdf33;
2331 SA1.WaitByteAddress1 = FillRAM + 0x37b4;
2333 /* PGA EUROPEAN TOUR */
2334 if (strcmp (ROMId, "AEPE") == 0)
2336 SA1.WaitAddress = SA1.Map [0x003700 >> MEMMAP_SHIFT] + 0x3700;
2337 SA1.WaitByteAddress1 = FillRAM + 0x3102;
2340 if (strcmp (ROMId, "A3GE") == 0)
2342 SA1.WaitAddress = SA1.Map [0x003700 >> MEMMAP_SHIFT] + 0x3700;
2343 SA1.WaitByteAddress1 = FillRAM + 0x3102;
2345 /* POWER RANGERS 4 */
2346 if (strcmp (ROMId, "A4RE") == 0)
2348 SA1.WaitAddress = SA1.Map [0x009899 >> MEMMAP_SHIFT] + 0x9899;
2349 SA1.WaitByteAddress1 = FillRAM + 0x3000;
2351 /* PACHISURO PALUSUPE */
2352 if (strcmp (ROMId, "AGFJ") == 0)
2354 // Never seems to turn on the SA-1!
2356 /* SD F1 GRAND PRIX */
2357 if (strcmp (ROMId, "AGFJ") == 0)
2359 SA1.WaitAddress = SA1.Map [0x0181bc >> MEMMAP_SHIFT] + 0x81bc;
2361 /* SHOUGI MARJONG */
2362 if (strcmp (ROMId, "ASYJ") == 0)
2364 SA1.WaitAddress = SA1.Map [0x00f2cc >> MEMMAP_SHIFT] + 0xf2cc;
2365 SA1.WaitByteAddress1 = SRAM + 0x7ffe;
2366 SA1.WaitByteAddress2 = SRAM + 0x7ffc;
2369 if (strcmp (ROMId, "AX2J") == 0)
2371 SA1.WaitAddress = SA1.Map [0x00d675 >> MEMMAP_SHIFT] + 0xd675;
2374 /* SHINING SCORPION */
2375 if (strcmp (ROMId, "A4WJ") == 0)
2377 SA1.WaitAddress = SA1.Map [0xc048be >> MEMMAP_SHIFT] + 0x48be;
2379 /* SHIN SHOUGI CLUB */
2380 if (strcmp (ROMId, "AHJJ") == 0)
2382 SA1.WaitAddress = SA1.Map [0xc1002a >> MEMMAP_SHIFT] + 0x002a;
2383 SA1.WaitByteAddress1 = SRAM + 0x0806;
2384 SA1.WaitByteAddress2 = SRAM + 0x0808;
2387 // Additional game fixes by sanmaiwashi ...
2388 if (strcmp (ROMName, "SFX ŲĶÞÝÀÞÑÓɶÞÀØ 1") == 0)
2390 bytes0x2000 [0xb18] = 0x4c;
2391 bytes0x2000 [0xb19] = 0x4b;
2392 bytes0x2000 [0xb1a] = 0xea;
2395 if (strcmp (ROMName, "GOGO ACKMAN3") == 0 ||
2396 strcmp (ROMName, "HOME ALONE") == 0)
2398 // Banks 00->3f and 80->bf
2399 for (int c = 0; c < 0x400; c += 16)
2401 Map [c + 6] = Map [c + 0x806] = SRAM;
2402 Map [c + 7] = Map [c + 0x807] = SRAM;
2403 BlockIsROM [c + 6] = BlockIsROM [c + 0x806] = FALSE;
2404 BlockIsROM [c + 7] = BlockIsROM [c + 0x807] = FALSE;
2405 BlockIsRAM [c + 6] = BlockIsRAM [c + 0x806] = TRUE;
2406 BlockIsRAM [c + 7] = BlockIsRAM [c + 0x807] = TRUE;
2411 if (strncmp (ROMName, "SWORD WORLD SFC", 15) == 0 ||
2412 strcmp (ROMName, "SFC ¶ÒÝײÀÞ°") == 0)
2415 SNESGameFixes.NeedInit0x2137 = TRUE;
2416 Settings.APUEnabled |= 2;
2417 CPU.APU_APUExecuting |= 2;
2420 if (strncmp (ROMName, "SHIEN THE BLADE CHASE", 21) == 0)
2421 SNESGameFixes.Old_Read0x4200 = TRUE;
2423 if (strcmp (ROMName, "ºÞ¼Þ× ¶²¼Þ³ÀÞ²¹¯¾Ý") == 0)
2424 SNESGameFixes.NeedInit0x2137 = TRUE;
2426 if (strcmp (ROMName, "UMIHARAKAWASE") == 0)
2427 SNESGameFixes.umiharakawaseFix = TRUE;
2429 if (strcmp (ROMName, "ALIENS vs. PREDATOR") == 0)
2430 SNESGameFixes.alienVSpredetorFix = TRUE;
2432 if (strcmp (ROMName, "demon's blazon") == 0 ||
2433 strcmp (ROMName, "demon's crest") == 0 ||
2434 strcmp (ROMName, "ROCKMAN X") == 0 ||
2435 strcmp (ROMName, "MEGAMAN X") == 0)
2439 // Banks 0x808000, 0x408000 are mirroring.
2440 for (int c = 0; c < 8; c++)
2441 Map [0x408 + c] = ROM - 0x8000;
2444 if (strcmp (ROMName, "½°Ȩ̂߰нÀ") == 0 ||
2445 strcmp (ROMName, "½°Ȩ̂߰нÀ 2") == 0 ||
2446 strcmp (ROMName, "ZENKI TENCHIMEIDOU") == 0 ||
2447 strcmp (ROMName, "GANBA LEAGUE") == 0)
2449 SNESGameFixes.APU_OutPorts_ReturnValueFix = TRUE;
2453 if (strcmp (ROMName, "HITOMI3") == 0)
2455 Memory.SRAMSize = 1;
2456 CPU.Memory_SRAMMask = Memory.SRAMSize ?
2457 ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0;
2460 if (strcmp (ROMName, "goemon 4") == 0)
2461 SNESGameFixes.SRAMInitialValue = 0x00;
2463 if (strcmp (ROMName, "PACHISLO ¹Ý·³") == 0)
2464 SNESGameFixes._0x213E_ReturnValue = 1;
2466 if (strcmp (ROMName, "»Þ Ï°¼Þ¬Ý ijʲÃÞÝ") == 0)
2467 SNESGameFixes.TouhaidenControllerFix = TRUE;
2469 if (strcmp (ROMName, "DRAGON KNIGHT 4") == 0)
2471 // Banks 70->7e, S-RAM
2472 for (int c = 0; c < 0xe0; c++)
2474 Map [c + 0x700] = (uint8 *) MAP_LOROM_SRAM;
2475 BlockIsRAM [c + 0x700] = TRUE;
2476 BlockIsROM [c + 0x700] = FALSE;
2481 if (strncmp (ROMName, "LETs PACHINKO(", 14) == 0)
2484 Settings.APUEnabled |= 2;
2485 CPU.APU_APUExecuting |= 2;
2486 if (!Settings.ForceNTSC && !Settings.ForcePAL)
2488 Settings.PAL = FALSE;
2489 Settings.FrameTime = Settings.FrameTimeNTSC;
2490 Memory.ROMFramesPerSecond = 60;
2494 if (strcmp (ROMName, "FURAI NO SIREN") == 0)
2495 SNESGameFixes.SoundEnvelopeHeightReading2 = TRUE;
2497 if(strcmp (ROMName, "XBAND JAPANESE MODEM") == 0)
2499 for (c = 0x200; c < 0x400; c += 16)
2501 for (int i = c; i < c + 16; i++)
2503 Map [i + 0x400] = Map [i + 0xc00] = &ROM[c * 0x1000];
2504 MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = 8;
2505 BlockIsRAM [i + 0x400] = BlockIsRAM [i + 0xc00] = TRUE;
2506 BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = FALSE;
2513 #define RomPatch(adr,ov,nv) \
2514 if (ROM [adr] == ov) \
2518 if (strcmp (ROMName, "LOVE QUEST") == 0)
2520 RomPatch (0x1385ec, 0xd0, 0xea);
2521 RomPatch (0x1385ed, 0xb2, 0xea);
2524 // Nangoku Syonen Papuwa Kun
2525 if (strcmp (ROMName, "NANGOKUSYONEN PAPUWA") == 0)
2526 RomPatch (0x1f0d1, 0xa0, 0x6b);
2529 if (strcmp (ROMName, "Tetsuwan Atom") == 0)
2531 RomPatch (0xe24c5, 0x90, 0xea);
2532 RomPatch (0xe24c6, 0xf3, 0xea);
2536 if (strcmp (ROMName, "SFC ODA NOBUNAGA") == 0)
2538 RomPatch (0x7497, 0x80, 0xea);
2539 RomPatch (0x7498, 0xd5, 0xea);
2543 if (strcmp (ROMName, "Super Batter Up") == 0)
2545 RomPatch (0x27ae0, 0xd0, 0xea);
2546 RomPatch (0x27ae1, 0xfa, 0xea);
2549 // Super Professional Baseball 2
2550 if (strcmp (ROMName, "SUPER PRO. BASE BALL2") == 0)
2552 RomPatch (0x1e4, 0x50, 0xea);
2553 RomPatch (0x1e5, 0xfb, 0xea);
2557 // Read variable size MSB int from a file
2558 static long ReadInt (FILE *f, unsigned nbytes)
2566 v = (v << 8) | (c & 0xFF);
2571 #define IPS_EOF 0x00454F46l
2573 void CMemory::CheckForIPSPatch (const char *rom_filename, bool8_32 header,
2576 char fname [_MAX_PATH + 1];
2577 FILE *patch_file = NULL;
2578 long offset = header ? 512 : 0;
2580 if (!(patch_file = fopen(S9xGetFilename(FILE_IPS), "rb"))) return;
2582 if (fread (fname, 1, 5, patch_file) != 5 || strncmp (fname, "PATCH", 5) != 0)
2584 fclose (patch_file);
2596 ofs = ReadInt (patch_file, 3);
2605 len = ReadInt (patch_file, 2);
2609 /* Apply patch block */
2612 if (ofs + len > MAX_ROM_SIZE)
2617 rchar = fgetc (patch_file);
2620 ROM [ofs++] = (uint8) rchar;
2627 rlen = ReadInt (patch_file, 2);
2631 rchar = fgetc (patch_file);
2635 if (ofs + rlen > MAX_ROM_SIZE)
2639 ROM [ofs++] = (uint8) rchar;
2646 // Check if ROM image needs to be truncated
2647 ofs = ReadInt (patch_file, 3);
2648 if (ofs != -1 && ofs - offset < rom_size)
2650 // Need to truncate ROM image
2651 rom_size = ofs - offset;
2653 fclose (patch_file);
2658 fclose (patch_file);