Browse code

Update snes9x code from 1.53 to 1.6.0.

Notable differences from upstream:
* Did not use the same #include setup for the new byuu apu and instead chose to do things more traditionally, as the latter is also much easier to deal with in Visual Studio than just including .cpp files into other .cpp files...
* MSU1 support not included (I see no need for this in a plugin meant to be used for original SNES music).
* The dynamic rate control on the APU not included (I also see no need for it in this plugin).
* The extra resamplers I added in were removed as the original hermite resampler was folded into a single non-inhertiable resampler.
* Bits of cleanup.

Naram Qashat authored on 2021/04/19 21:20:36
Showing 1 changed files
... ...
@@ -1,179 +1,8 @@
1
-/***********************************************************************************
1
+/*****************************************************************************\
2 2
   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
-
4
-  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
-                             Jerremy Koot (jkoot@snes9x.com)
6
-
7
-  (c) Copyright 2002 - 2004  Matthew Kendora
8
-
9
-  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
-
11
-  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
-
13
-  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
-
15
-  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
-                             Kris Bleakley (codeviolation@hotmail.com)
17
-
18
-  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
-                             Nach (n-a-c-h@users.sourceforge.net),
20
-
21
-  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
-
23
-  (c) Copyright 2006 - 2007  nitsuja
24
-
25
-  (c) Copyright 2009 - 2011  BearOso,
26
-                             OV2
27
-
28
-
29
-  BS-X C emulator code
30
-  (c) Copyright 2005 - 2006  Dreamer Nom,
31
-                             zones
32
-
33
-  C4 x86 assembler and some C emulation code
34
-  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
-                             Nach,
36
-                             zsKnight (zsknight@zsnes.com)
37
-
38
-  C4 C++ code
39
-  (c) Copyright 2003 - 2006  Brad Jorsch,
40
-                             Nach
41
-
42
-  DSP-1 emulator code
43
-  (c) Copyright 1998 - 2006  _Demo_,
44
-                             Andreas Naive (andreasnaive@gmail.com),
45
-                             Gary Henderson,
46
-                             Ivar (ivar@snes9x.com),
47
-                             John Weidman,
48
-                             Kris Bleakley,
49
-                             Matthew Kendora,
50
-                             Nach,
51
-                             neviksti (neviksti@hotmail.com)
52
-
53
-  DSP-2 emulator code
54
-  (c) Copyright 2003         John Weidman,
55
-                             Kris Bleakley,
56
-                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
-                             Matthew Kendora,
58
-                             neviksti
59
-
60
-  DSP-3 emulator code
61
-  (c) Copyright 2003 - 2006  John Weidman,
62
-                             Kris Bleakley,
63
-                             Lancer,
64
-                             z80 gaiden
65
-
66
-  DSP-4 emulator code
67
-  (c) Copyright 2004 - 2006  Dreamer Nom,
68
-                             John Weidman,
69
-                             Kris Bleakley,
70
-                             Nach,
71
-                             z80 gaiden
72
-
73
-  OBC1 emulator code
74
-  (c) Copyright 2001 - 2004  zsKnight,
75
-                             pagefault (pagefault@zsnes.com),
76
-                             Kris Bleakley
77
-                             Ported from x86 assembler to C by sanmaiwashi
78
-
79
-  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
-  (c) Copyright 2002         Matthew Kendora with research by
81
-                             zsKnight,
82
-                             John Weidman,
83
-                             Dark Force
84
-
85
-  SPC7110 and RTC C++ emulator code used in 1.52+
86
-  (c) Copyright 2009         byuu,
87
-                             neviksti
88
-
89
-  S-DD1 C emulator code
90
-  (c) Copyright 2003         Brad Jorsch with research by
91
-                             Andreas Naive,
92
-                             John Weidman
93
-
94
-  S-RTC C emulator code
95
-  (c) Copyright 2001 - 2006  byuu,
96
-                             John Weidman
97
-
98
-  ST010 C++ emulator code
99
-  (c) Copyright 2003         Feather,
100
-                             John Weidman,
101
-                             Kris Bleakley,
102
-                             Matthew Kendora
103
-
104
-  Super FX x86 assembler emulator code
105
-  (c) Copyright 1998 - 2003  _Demo_,
106
-                             pagefault,
107
-                             zsKnight
108
-
109
-  Super FX C emulator code
110
-  (c) Copyright 1997 - 1999  Ivar,
111
-                             Gary Henderson,
112
-                             John Weidman
113
-
114
-  Sound emulator code used in 1.5-1.51
115
-  (c) Copyright 1998 - 2003  Brad Martin
116
-  (c) Copyright 1998 - 2006  Charles Bilyue'
117
-
118
-  Sound emulator code used in 1.52+
119
-  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
-
121
-  SH assembler code partly based on x86 assembler code
122
-  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
-
124
-  2xSaI filter
125
-  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
-
127
-  HQ2x, HQ3x, HQ4x filters
128
-  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
-
130
-  NTSC filter
131
-  (c) Copyright 2006 - 2007  Shay Green
132
-
133
-  GTK+ GUI code
134
-  (c) Copyright 2004 - 2011  BearOso
135
-
136
-  Win32 GUI code
137
-  (c) Copyright 2003 - 2006  blip,
138
-                             funkyass,
139
-                             Matthew Kendora,
140
-                             Nach,
141
-                             nitsuja
142
-  (c) Copyright 2009 - 2011  OV2
143
-
144
-  Mac OS GUI code
145
-  (c) Copyright 1998 - 2001  John Stiles
146
-  (c) Copyright 2001 - 2011  zones
147
-
148
-
149
-  Specific ports contains the works of other authors. See headers in
150
-  individual files.
151
-
152
-
153
-  Snes9x homepage: http://www.snes9x.com/
154
-
155
-  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
-  and source form, for non-commercial purposes, is hereby granted without
157
-  fee, providing that this license information and copyright notice appear
158
-  with all copies and any derived work.
159
-
160
-  This software is provided 'as-is', without any express or implied
161
-  warranty. In no event shall the authors be held liable for any damages
162
-  arising from the use of this software or it's derivatives.
163
-
164
-  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
-  seek permission of the copyright holders first. Commercial use includes,
166
-  but is not limited to, charging money for Snes9x or software derived from
167
-  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
-  using Snes9x as a promotion for your commercial product.
169
-
170
-  The copyright holders request that bug fixes and improvements to the code
171
-  should be forwarded to them so everyone can benefit from the modifications
172
-  in future versions.
173
-
174
-  Super NES and Super Nintendo Entertainment System are trademarks of
175
-  Nintendo Co., Limited and its subsidiary companies.
176
- ***********************************************************************************/
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
177 6
 
178 7
 #include <vector>
179 8
 #include <algorithm>
... ...
@@ -358,13 +187,20 @@ int CMemory::ScoreLoROM(bool skip_header, int32_t romoff)
358 187
 	return score;
359 188
 }
360 189
 
361
-bool CMemory::LoadROMSNSF(const uint8_t *lrombuf, int32_t lromsize, const uint8_t *srambuf, int32_t sramsize)
190
+int CMemory::First512BytesCountZeroes() const
362 191
 {
363
-	int retry_count = 0;
192
+	const uint8_t *buf = ROM;
193
+	int zeroCount = 0;
194
+	for (int i = 0; i < 512; ++i)
195
+		if (buf[i] == 0)
196
+			++zeroCount;
197
+	return zeroCount;
198
+}
364 199
 
200
+bool CMemory::LoadROMSNSF(const uint8_t *lrombuf, int32_t lromsize, const uint8_t *srambuf, int32_t sramsize)
201
+{
365 202
 	std::fill_n(&this->ROM[0], static_cast<int>(MAX_ROM_SIZE), 0);
366 203
 
367
-again:
368 204
 	this->CalculatedSize = 0;
369 205
 	this->ExtendedFormat = NOPE;
370 206
 
... ...
@@ -378,8 +214,22 @@ again:
378 214
 
379 215
 	int hi_score = this->ScoreHiROM(false);
380 216
 	int lo_score = this->ScoreLoROM(false);
217
+	int score_nonheadered = std::max(hi_score, lo_score);
218
+	int score_headered = std::max(this->ScoreHiROM(TRUE), this->ScoreLoROM(TRUE));
219
+
220
+	bool size_is_likely_headered = !((totalFileSize - 512) & 0xFFFF);
221
+	if (size_is_likely_headered)
222
+		score_headered += 2;
223
+	else
224
+		score_headered -= 2;
225
+	if (this->First512BytesCountZeroes() >= 0x1E0)
226
+		score_headered += 2;
227
+	else
228
+		score_headered -= 2;
229
+
230
+	bool headered_score_highest = score_headered > score_nonheadered;
381 231
 
382
-	if (((hi_score > lo_score && this->ScoreHiROM(true) > hi_score) || (hi_score <= lo_score && this->ScoreLoROM(true) > lo_score)))
232
+	if (headered_score_highest)
383 233
 	{
384 234
 		std::copy_n(&this->ROM[512], totalFileSize - 512, &this->ROM[0]);
385 235
 		totalFileSize -= 512;
... ...
@@ -388,9 +238,11 @@ again:
388 238
 		lo_score = this->ScoreLoROM(false);
389 239
 	}
390 240
 
391
-	this->CalculatedSize = (totalFileSize / 0x2000) * 0x2000;
241
+	this->CalculatedSize = ((totalFileSize + 0x1fff) / 0x2000) * 0x2000;
392 242
 
393 243
 	if (this->CalculatedSize > 0x400000 &&
244
+		this->ROM[0x7fd5] + (this->ROM[0x7fd6] << 8) != 0x3423 && // exclude SA-1
245
+		this->ROM[0x7fd5] + (this->ROM[0x7fd6] << 8) != 0x3523 &&
394 246
 		this->ROM[0x7fd5] + (this->ROM[0x7fd6] << 8) != 0x4332 && // exclude S-DD1
395 247
 		this->ROM[0x7fd5] + (this->ROM[0x7fd6] << 8) != 0x4532 &&
396 248
 		this->ROM[0xffd5] + (this->ROM[0xffd6] << 8) != 0xF93a && // exclude SPC7110
... ...
@@ -496,11 +348,10 @@ again:
496 348
 		hi_score = this->ScoreHiROM(false);
497 349
 		lo_score = this->ScoreLoROM(false);
498 350
 
499
-		if (((this->HiROM && (lo_score >= hi_score || hi_score < 0)) || (this->LoROM && (hi_score > lo_score || lo_score < 0))) && !retry_count)
351
+		if ((this->HiROM && (lo_score >= hi_score || hi_score < 0)) || (this->LoROM && (hi_score > lo_score || lo_score < 0)))
500 352
 		{
501 353
 			Settings.ForceNotInterleaved = true;
502
-			++retry_count;
503
-			goto again;
354
+			return false;
504 355
 		}
505 356
 	}
506 357
 
... ...
@@ -661,7 +512,6 @@ void CMemory::InitROM()
661 512
 	   and the NMI handler, time enough for an instruction or two. */
662 513
 	// Wild Guns, Mighty Morphin Power Rangers - The Fighting Edition
663 514
 	Timings.NMIDMADelay = 24;
664
-	Timings.IRQPendCount = 0;
665 515
 
666 516
 	//// Hack games
667 517
 
... ...
@@ -765,7 +615,7 @@ void CMemory::map_index(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint3
765 615
 		for (uint32_t i = addr_s; i <= addr_e; i += 0x1000)
766 616
 		{
767 617
 			uint32_t p = (c << 4) | (i >> 12);
768
-			this->Map[p] = reinterpret_cast<uint8_t *>(index);
618
+			this->Map[p] = reinterpret_cast<uint8_t *>(static_cast<intptr_t>(index));
769 619
 			this->BlockIsROM[p] = false;
770 620
 			this->BlockIsRAM[p] = isRAM;
771 621
 		}
... ...
@@ -791,8 +641,13 @@ void CMemory::map_WRAM()
791 641
 
792 642
 void CMemory::map_LoROMSRAM()
793 643
 {
794
-	this->map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
795
-	this->map_index(0xf0, 0xff, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
644
+	if (!this->SRAMSize)
645
+		return;
646
+
647
+	uint32_t hi = this->SRAMSize > 5 ? 0x7fff : 0xffff;
648
+
649
+	this->map_index(0x70, 0x7d, 0x0000, hi, MAP_LOROM_SRAM, MAP_TYPE_RAM);
650
+	this->map_index(0xf0, 0xff, 0x0000, hi, MAP_LOROM_SRAM, MAP_TYPE_RAM);
796 651
 }
797 652
 
798 653
 void CMemory::map_HiROMSRAM()
... ...
@@ -857,7 +712,7 @@ void CMemory::Map_JumboLoROMMap()
857 712
 	this->map_System();
858 713
 
859 714
 	this->map_lorom_offset(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize - 0x400000, 0x400000);
860
-	this->map_lorom_offset(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize - 0x400000, 0x400000);
715
+	this->map_lorom_offset(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize - 0x600000, 0x600000);
861 716
 	this->map_lorom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0);
862 717
 	this->map_lorom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0x200000);
863 718
 
... ...
@@ -909,10 +764,11 @@ void CMemory::Map_SDD1LoROMMap()
909 764
 	this->map_lorom(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize);
910 765
 	this->map_lorom(0x80, 0xbf, 0x8000, 0xffff, this->CalculatedSize);
911 766
 
912
-	this->map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize, 0);
767
+	this->map_hirom_offset(0x60, 0x7f, 0x0000, 0xffff, this->CalculatedSize, 0);
913 768
 	this->map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, this->CalculatedSize, 0); // will be overwritten dynamically
914 769
 
915 770
 	this->map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
771
+	this->map_index(0xa0, 0xbf, 0x6000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
916 772
 
917 773
 	this->map_WRAM();
918 774
 
... ...
@@ -973,66 +829,22 @@ void CMemory::ApplyROMFixes()
973 829
 	//// APU timing hacks :(
974 830
 
975 831
 	Timings.APUSpeedup = 0;
976
-	Timings.APUAllowTimeOverflow = false;
977 832
 
978 833
 	if (!Settings.DisableGameSpecificHacks)
979 834
 	{
980
-		if (this->match_id("AVCJ")) // Rendering Ranger R2
981
-			Timings.APUSpeedup = 4;
982
-
983
-		if (this->match_na("GAIA GENSOUKI 1 JPN") || // Gaia Gensouki
984
-			this->match_id("JG  ") || // Illusion of Gaia
985
-			this->match_id("CQ  ") || // Stunt Race FX
986
-			this->match_na("SOULBLADER - 1") || // Soul Blader
987
-			this->match_na("SOULBLAZER - 1 USA") || // Soul Blazer
988
-			this->match_na("SLAP STICK 1 JPN") || // Slap Stick
989
-			this->match_id("E9 ") || // Robotrek
990
-			this->match_nn("ACTRAISER") || // Actraiser
991
-			this->match_nn("ActRaiser-2") || // Actraiser 2
992
-			this->match_id("AQT") || // Tenchi Souzou, Terranigma
993
-			this->match_id("ATV") || // Tales of Phantasia
994
-			this->match_id("ARF") || // Star Ocean
995
-			this->match_id("APR") || // Zen-Nippon Pro Wrestling 2 - 3-4 Budoukan
996
-			this->match_id("A4B") || // Super Bomberman 4
997
-			this->match_id("Y7 ") || // U.F.O. Kamen Yakisoban - Present Ban
998
-			this->match_id("Y9 ") || // U.F.O. Kamen Yakisoban - Shihan Ban
999
-			this->match_id("APB") || // Super Bomberman - Panic Bomber W
1000
-			this->match_na("DARK KINGDOM") || // Dark Kingdom
1001
-			this->match_na("ZAN3 SFC") || // Zan III Spirits
1002
-			this->match_na("HIOUDEN") || // Hiouden - Mamono-tachi Tono Chikai
1003
-			this->match_na("\xC3\xDD\xBC\xC9\xB3\xC0") || // Tenshi no Uta
1004
-			this->match_na("FORTUNE QUEST") || // Fortune Quest - Dice wo Korogase
1005
-			this->match_na("FISHING TO BASSING") || // Shimono Masaki no Fishing To Bassing
1006
-			this->match_na("OHMONO BLACKBASS") || // Oomono Black Bass Fishing - Jinzouko Hen
1007
-			this->match_na("MASTERS") || // Harukanaru Augusta 2 - Masters
1008
-			this->match_na("SFC \xB6\xD2\xDD\xD7\xB2\xC0\xDE\xB0") || // Kamen Rider
1009
-			this->match_na("ZENKI TENCHIMEIDOU") || // Kishin Douji Zenki - Tenchi Meidou
1010
-			this->match_nn("TokyoDome '95Battle 7") || // Shin Nippon Pro Wrestling Kounin '95 - Tokyo Dome Battle 7
1011
-			this->match_nn("SWORD WORLD SFC") || // Sword World SFC/2
1012
-			this->match_nn("LETs PACHINKO(") || // BS Lets Pachinko Nante Gindama 1/2/3/4
1013
-			this->match_nn("THE FISHING MASTER") || // Mark Davis The Fishing Master
1014
-			this->match_nn("Parlor") || // Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5
1015
-			this->match_na("HEIWA Parlor!Mini8") || // Parlor mini 8
1016
-			this->match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!")) // SANKYO Fever! Fever!
1017
-			Timings.APUSpeedup = 1;
1018
-
1019
-		if (this->match_na("EARTHWORM JIM 2") || // Earthworm Jim 2
1020
-			this->match_na("NBA Hangtime") || // NBA Hang Time
1021
-			this->match_na("MSPACMAN") || // Ms Pacman
1022
-			this->match_na("THE MASK") || // The Mask
1023
-			this->match_na("PRIMAL RAGE") || // Primal Rage
1024
-			this->match_na("DOOM TROOPERS")) // Doom Troopers
1025
-			Timings.APUAllowTimeOverflow = true;
835
+		//if (this->match_id("AVCJ")) // Rendering Ranger R2
836
+		//	Timings.APUSpeedup = 2;
837
+		if (this->match_na("CIRCUIT USA"))
838
+			Timings.APUSpeedup = 3;
1026 839
 	}
1027 840
 
1028 841
 	S9xAPUTimingSetSpeedup(Timings.APUSpeedup);
1029
-	S9xAPUAllowTimeOverflow(Timings.APUAllowTimeOverflow);
1030 842
 
1031 843
 	//// Other timing hacks :(
1032 844
 
1033 845
 	Timings.HDMAStart = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100;
1034 846
 	Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC;
1035
-	Timings.IRQTriggerCycles = 10;
847
+	Timings.IRQTriggerCycles = 14;
1036 848
 
1037 849
 	if (!Settings.DisableGameSpecificHacks)
1038 850
 	{
... ...
@@ -1040,17 +852,10 @@ void CMemory::ApplyROMFixes()
1040 852
 		// Some games need really severe delay timing...
1041 853
 		if (this->match_na("BATTLE GRANDPRIX")) // Battle Grandprix
1042 854
 			Timings.DMACPUSync = 20;
1043
-
1044
-		// An infinite loop reads $4212 and waits V-blank end, whereas VIRQ is set V=0.
1045
-		// If Snes9x succeeds to escape from the loop before jumping into the IRQ handler, the game goes further.
1046
-		// If Snes9x jumps into the IRQ handler before escaping from the loop,
1047
-		// Snes9x cannot escape from the loop permanently because the RTI is in the next V-blank.
1048
-		if (this->match_na("Aero the AcroBat 2"))
1049
-			Timings.IRQPendCount = 2;
1050
-
1051
-		// XXX: What's happening?
1052
-		if (this->match_na("X-MEN")) // Spider-Man and the X-Men
1053
-			Settings.BlockInvalidVRAMAccess = false;
855
+		else if (match_na("KORYU NO MIMI ENG")) // Koryu no Mimi translation by rpgone)
856
+			// An infinite loop reads $4210 and checks NMI flag. This only works if LDA instruction executes before the NMI triggers,
857
+			// which doesn't work very well with s9x's default DMA timing.
858
+			Timings.DMACPUSync = 20;
1054 859
 
1055 860
 		//// SRAM initial value
1056 861
 
Browse code

* Fixes for gcc and clang (while they can compile the code, the DLLs made aren't functional, but oh well).

* [2SF] Used more up-to-date asmjit, despite the ugly looking code.

Naram Qashat authored on 2014/09/17 19:51:45
Showing 1 changed files
... ...
@@ -185,53 +185,6 @@
185 185
 #include "apu/apu.h"
186 186
 #include "sdd1.h"
187 187
 
188
-static const uint32_t crc32Table[] =
189
-{
190
-	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
191
-	0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
192
-	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
193
-	0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
194
-	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
195
-	0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
196
-	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
197
-	0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
198
-	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
199
-	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
200
-	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
201
-	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
202
-	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
203
-	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
204
-	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
205
-	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
206
-	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
207
-	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
208
-	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
209
-	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
210
-	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
211
-	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
212
-	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
213
-	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
214
-	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
215
-	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
216
-	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
217
-	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
218
-	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
219
-	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
220
-	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
221
-	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
222
-	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
223
-	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
224
-	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
225
-	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
226
-	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
227
-	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
228
-	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
229
-	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
230
-	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
231
-	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
232
-	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
233
-};
234
-
235 188
 // deinterleave
236 189
 
237 190
 static void S9xDeinterleaveType1(int size, uint8_t *base)
Browse code

[SNSF] Replaced most uses of fill/copy with fill_n/copy_n, and a few other minor code cleanups.

Naram Qashat authored on 2013/05/27 22:34:22
Showing 1 changed files
... ...
@@ -270,10 +270,10 @@ bool CMemory::Init()
270 270
 		return false;
271 271
 	}
272 272
 
273
-	std::fill(&this->RAM[0], &this->RAM[0x20000], 0);
274
-	std::fill(&this->SRAM[0], &this->SRAM[0x20000], 0);
275
-	std::fill(&this->VRAM[0], &this->VRAM[0x10000], 0);
276
-	std::fill(&this->RealROM[0], &this->RealROM[MAX_ROM_SIZE + 0x200 + 0x8000], 0);
273
+	std::fill_n(&this->RAM[0], 0x20000, 0);
274
+	std::fill_n(&this->SRAM[0], 0x20000, 0);
275
+	std::fill_n(&this->VRAM[0], 0x10000, 0);
276
+	std::fill_n(&this->RealROM[0], MAX_ROM_SIZE + 0x200 + 0x8000, 0);
277 277
 
278 278
 	// FillRAM uses first 32K of ROM image area, otherwise space just
279 279
 	// wasted. Might be read by the SuperFX code.
... ...
@@ -409,7 +409,7 @@ bool CMemory::LoadROMSNSF(const uint8_t *lrombuf, int32_t lromsize, const uint8_
409 409
 {
410 410
 	int retry_count = 0;
411 411
 
412
-	std::fill(&this->ROM[0], &this->ROM[MAX_ROM_SIZE], 0);
412
+	std::fill_n(&this->ROM[0], static_cast<int>(MAX_ROM_SIZE), 0);
413 413
 
414 414
 again:
415 415
 	this->CalculatedSize = 0;
... ...
@@ -418,18 +418,17 @@ again:
418 418
 	int32_t totalFileSize = std::min<int32_t>(MAX_ROM_SIZE, lromsize);
419 419
 	if (!totalFileSize)
420 420
 		return false;
421
-	std::copy(&lrombuf[0], &lrombuf[totalFileSize], &this->ROM[0]);
422
-	SNESGameFixes.SRAMInitialValue = 0xff;
423
-	std::fill(&this->SRAM[0], &this->SRAM[0x20000], SNESGameFixes.SRAMInitialValue);
421
+	std::copy_n(&lrombuf[0], totalFileSize, &this->ROM[0]);
422
+	std::fill_n(&this->SRAM[0], 0x20000, 0xff);
424 423
 	if (srambuf && sramsize)
425
-		std::copy(&srambuf[0], &srambuf[sramsize], &this->SRAM[0]);
424
+		std::copy_n(&srambuf[0], sramsize, &this->SRAM[0]);
426 425
 
427 426
 	int hi_score = this->ScoreHiROM(false);
428 427
 	int lo_score = this->ScoreLoROM(false);
429 428
 
430 429
 	if (((hi_score > lo_score && this->ScoreHiROM(true) > hi_score) || (hi_score <= lo_score && this->ScoreLoROM(true) > lo_score)))
431 430
 	{
432
-		memmove(&this->ROM[0], &this->ROM[512], totalFileSize - 512);
431
+		std::copy_n(&this->ROM[512], totalFileSize - 512, &this->ROM[0]);
433 432
 		totalFileSize -= 512;
434 433
 		// modifying ROM, so we need to rescore
435 434
 		hi_score = this->ScoreHiROM(false);
... ...
@@ -486,7 +485,6 @@ again:
486 485
 
487 486
 		// ignore map type byte if not 0x2x or 0x3x
488 487
 		if ((RomHeader[0x7fd5] & 0xf0) == 0x20 || (RomHeader[0x7fd5] & 0xf0) == 0x30)
489
-		{
490 488
 			switch (RomHeader[0x7fd5] & 0xf)
491 489
 			{
492 490
 				case 1:
... ...
@@ -494,11 +492,8 @@ again:
494 492
 					break;
495 493
 
496 494
 				case 5:
497
-					interleaved = true;
498
-					tales = true;
499
-					break;
495
+					interleaved = tales = true;
500 496
 			}
501
-		}
502 497
 	}
503 498
 	else
504 499
 	{
... ...
@@ -506,24 +501,19 @@ again:
506 501
 		this->HiROM = true;
507 502
 
508 503
 		if ((RomHeader[0xffd5] & 0xf0) == 0x20 || (RomHeader[0xffd5] & 0xf0) == 0x30)
509
-		{
510 504
 			switch (RomHeader[0xffd5] & 0xf)
511 505
 			{
512 506
 				case 0:
513 507
 				case 3:
514 508
 					interleaved = true;
515
-					break;
516 509
 			}
517
-		}
518 510
 	}
519 511
 
520 512
 	// this two games fail to be detected
521 513
 	if (!strncmp(reinterpret_cast<char *>(&this->ROM[0x7fc0]), "YUYU NO QUIZ DE GO!GO!", 22) || !strncmp(reinterpret_cast<char *>(&this->ROM[0xffc0]), "BATMAN--REVENGE JOKER",  21))
522 514
 	{
523 515
 		this->LoROM = true;
524
-		this->HiROM = false;
525
-		interleaved = false;
526
-		tales = false;
516
+		this->HiROM = interleaved = tales = false;
527 517
 	}
528 518
 
529 519
 	if (!Settings.ForceNotInterleaved && interleaved)
... ...
@@ -567,13 +557,12 @@ again:
567 557
 	if (tales)
568 558
 	{
569 559
 		auto tmp = std::vector<uint8_t>(this->CalculatedSize - 0x400000);
570
-		memmove(&tmp[0], &this->ROM[0], this->CalculatedSize - 0x400000);
571
-		memmove(&this->ROM[0], &this->ROM[this->CalculatedSize - 0x400000], 0x400000);
572
-		memmove(&this->ROM[0x400000], &tmp[0], this->CalculatedSize - 0x400000);
560
+		std::copy_n(&this->ROM[0], this->CalculatedSize - 0x400000, &tmp[0]);
561
+		std::copy_n(&this->ROM[this->CalculatedSize - 0x400000], 0x400000, &this->ROM[0]);
562
+		std::copy_n(&tmp[0], this->CalculatedSize - 0x400000, &this->ROM[0x400000]);
573 563
 	}
574 564
 
575 565
 	memset(&SNESGameFixes, 0, sizeof(SNESGameFixes));
576
-	SNESGameFixes.SRAMInitialValue = 0x60;
577 566
 
578 567
 	this->InitROM();
579 568
 
... ...
@@ -626,14 +615,14 @@ void CMemory::ParseSNESHeader(uint8_t *RomHeader)
626 615
 	this->ROMType = RomHeader[0x26];
627 616
 	this->ROMRegion = RomHeader[0x29];
628 617
 
629
-	std::copy(&RomHeader[0x02], &RomHeader[0x06], &this->ROMId[0]);
618
+	std::copy_n(&RomHeader[0x02], 4, &this->ROMId[0]);
630 619
 }
631 620
 
632 621
 void CMemory::InitROM()
633 622
 {
634 623
 	//// Parse ROM header and read ROM informatoin
635 624
 
636
-	std::fill(&this->ROMId[0], &this->ROMId[5], 0);
625
+	std::fill_n(&this->ROMId[0], 5, 0);
637 626
 
638 627
 	uint8_t *RomHeader = &this->ROM[0x7FB0];
639 628
 	if (this->ExtendedFormat == BIGFIRST)
... ...
@@ -817,7 +806,6 @@ void CMemory::map_space(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint3
817 806
 
818 807
 void CMemory::map_index(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, int index, int type)
819 808
 {
820
-	bool isROM = !(type == MAP_TYPE_I_O || type == MAP_TYPE_RAM);
821 809
 	bool isRAM = type != MAP_TYPE_I_O;
822 810
 
823 811
 	for (uint32_t c = bank_s; c <= bank_e; ++c)
... ...
@@ -825,7 +813,7 @@ void CMemory::map_index(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint3
825 813
 		{
826 814
 			uint32_t p = (c << 4) | (i >> 12);
827 815
 			this->Map[p] = reinterpret_cast<uint8_t *>(index);
828
-			this->BlockIsROM[p] = isROM;
816
+			this->BlockIsROM[p] = false;
829 817
 			this->BlockIsRAM[p] = isRAM;
830 818
 		}
831 819
 }
... ...
@@ -862,7 +850,7 @@ void CMemory::map_HiROMSRAM()
862 850
 
863 851
 void CMemory::map_WriteProtectROM()
864 852
 {
865
-	std::copy(&this->Map[0], &this->Map[0x1000], &this->WriteMap[0]);
853
+	std::copy_n(&this->Map[0], 0x1000, &this->WriteMap[0]);
866 854
 
867 855
 	for (int c = 0; c < 0x1000; ++c)
868 856
 		if (this->BlockIsROM[c])
... ...
@@ -1119,17 +1107,6 @@ void CMemory::ApplyROMFixes()
1119 1107
 			SRAMMask = ((1 << (SRAMSize + 3)) * 128) - 1;
1120 1108
 		}
1121 1109
 
1122
-		// SRAM value fixes
1123
-		if (this->match_na("SUPER DRIFT OUT") || // Super Drift Out
1124
-			this->match_na("SATAN IS OUR FATHER!") ||
1125
-			this->match_na("goemon 4")) // Ganbare Goemon Kirakira Douchuu
1126
-			SNESGameFixes.SRAMInitialValue = 0x00;
1127
-
1128
-		// Additional game fixes by sanmaiwashi ...
1129
-		// XXX: unnecessary?
1130
-		if (this->match_na("SFX \xC5\xB2\xC4\xB6\xDE\xDD\xC0\xDE\xD1\xD3\xC9\xB6\xDE\xC0\xD8 1")) // SD Gundam Gaiden - Knight Gundam Monogatari
1131
-			SNESGameFixes.SRAMInitialValue = 0x6b;
1132
-
1133 1110
 		// others: BS and ST-01x games are 0x00.
1134 1111
 
1135 1112
 		//// OAM hacks :(
Browse code

[SNSF] Massive code cleanup, as well as removing as much unused code/variables as possible.

Naram Qashat authored on 2013/05/23 06:02:16
Showing 1 changed files
... ...
@@ -175,718 +175,17 @@
175 175
   Nintendo Co., Limited and its subsidiary companies.
176 176
  ***********************************************************************************/
177 177
 
178
+#include <vector>
178 179
 #include <algorithm>
179 180
 #include <string>
180 181
 #include <numeric>
181
-#include <assert.h>
182
-
183
-#ifdef UNZIP_SUPPORT
184
-#include "unzip/unzip.h"
185
-#endif
186
-
187
-#ifdef JMA_SUPPORT
188
-#include "jma/s9x-jma.h"
189
-#endif
190
-
182
+#include <cassert>
191 183
 #include "snes9x.h"
192 184
 #include "memmap.h"
193 185
 #include "apu/apu.h"
194
-//#include "fxemu.h"
195 186
 #include "sdd1.h"
196
-//#include "srtc.h"
197
-//#include "controls.h"
198
-//#include "cheats.h"
199
-//#include "movie.h"
200
-//#include "reader.h"
201
-//#include "display.h"
202
-
203
-/*#ifndef SET_UI_COLOR
204
-#define SET_UI_COLOR(r, g, b) ;
205
-#endif*/
206
-
207
-/*#ifndef max
208
-#define max(a, b) (((a) > (b)) ? (a) : (b))
209
-#endif*/
210
-
211
-/*#ifndef min
212
-#define min(a, b) (((a) < (b)) ? (a) : (b))
213
-#endif*/
214
-
215
-//static bool	stopMovie = true;
216
-//static char		LastRomFilename[PATH_MAX + 1] = "";
217
-
218
-// from NSRT
219
-/*static const char	*nintendo_licensees[] =
220
-{
221
-	"Unlicensed",
222
-	"Nintendo",
223
-	"Rocket Games/Ajinomoto",
224
-	"Imagineer-Zoom",
225
-	"Gray Matter",
226
-	"Zamuse",
227
-	"Falcom",
228
-	NULL,
229
-	"Capcom",
230
-	"Hot B Co.",
231
-	"Jaleco",
232
-	"Coconuts Japan",
233
-	"Coconuts Japan/G.X.Media",
234
-	"Micronet",
235
-	"Technos",
236
-	"Mebio Software",
237
-	"Shouei System",
238
-	"Starfish",
239
-	NULL,
240
-	"Mitsui Fudosan/Dentsu",
241
-	NULL,
242
-	"Warashi Inc.",
243
-	NULL,
244
-	"Nowpro",
245
-	NULL,
246
-	"Game Village",
247
-	"IE Institute",
248
-	NULL,
249
-	NULL,
250
-	NULL,
251
-	NULL,
252
-	NULL,
253
-	NULL,
254
-	NULL,
255
-	NULL,
256
-	NULL,
257
-	"Banarex",
258
-	"Starfish",
259
-	"Infocom",
260
-	"Electronic Arts Japan",
261
-	NULL,
262
-	"Cobra Team",
263
-	"Human/Field",
264
-	"KOEI",
265
-	"Hudson Soft",
266
-	"S.C.P./Game Village",
267
-	"Yanoman",
268
-	NULL,
269
-	"Tecmo Products",
270
-	"Japan Glary Business",
271
-	"Forum/OpenSystem",
272
-	"Virgin Games (Japan)",
273
-	"SMDE",
274
-	"Yojigen",
275
-	NULL,
276
-	"Daikokudenki",
277
-	NULL,
278
-	NULL,
279
-	NULL,
280
-	NULL,
281
-	NULL,
282
-	"Creatures Inc.",
283
-	"TDK Deep Impresion",
284
-	NULL,
285
-	NULL,
286
-	NULL,
287
-	NULL,
288
-	NULL,
289
-	NULL,
290
-	NULL,
291
-	NULL,
292
-	NULL,
293
-	"Destination Software/KSS",
294
-	"Sunsoft/Tokai Engineering",
295
-	"POW (Planning Office Wada)/VR 1 Japan",
296
-	"Micro World",
297
-	NULL,
298
-	"San-X",
299
-	"Enix",
300
-	"Loriciel/Electro Brain",
301
-	"Kemco Japan",
302
-	"Seta Co.,Ltd.",
303
-	"Culture Brain",
304
-	"Irem Corp.",
305
-	"Palsoft",
306
-	"Visit Co., Ltd.",
307
-	"Intec",
308
-	"System Sacom",
309
-	"Poppo",
310
-	"Ubisoft Japan",
311
-	NULL,
312
-	"Media Works",
313
-	"NEC InterChannel",
314
-	"Tam",
315
-	"Gajin/Jordan",
316
-	"Smilesoft",
317
-	NULL,
318
-	NULL,
319
-	"Mediakite",
320
-	NULL,
321
-	NULL,
322
-	NULL,
323
-	NULL,
324
-	NULL,
325
-	NULL,
326
-	NULL,
327
-	NULL,
328
-	NULL,
329
-	"Viacom",
330
-	"Carrozzeria",
331
-	"Dynamic",
332
-	NULL,
333
-	"Magifact",
334
-	"Hect",
335
-	"Codemasters",
336
-	"Taito/GAGA Communications",
337
-	"Laguna",
338
-	"Telstar Fun & Games/Event/Taito",
339
-	NULL,
340
-	"Arcade Zone Ltd.",
341
-	"Entertainment International/Empire Software",
342
-	"Loriciel",
343
-	"Gremlin Graphics",
344
-	NULL,
345
-	NULL,
346
-	NULL,
347
-	NULL,
348
-	NULL,
349
-	NULL,
350
-	NULL,
351
-	NULL,
352
-	NULL,
353
-	NULL,
354
-	NULL,
355
-	NULL,
356
-	NULL,
357
-	NULL,
358
-	NULL,
359
-	NULL,
360
-	NULL,
361
-	NULL,
362
-	NULL,
363
-	NULL,
364
-	NULL,
365
-	"Seika Corp.",
366
-	"UBI SOFT Entertainment Software",
367
-	"Sunsoft US",
368
-	NULL,
369
-	"Life Fitness",
370
-	NULL,
371
-	"System 3",
372
-	"Spectrum Holobyte",
373
-	NULL,
374
-	"Irem",
375
-	NULL,
376
-	"Raya Systems",
377
-	"Renovation Products",
378
-	"Malibu Games",
379
-	NULL,
380
-	"Eidos/U.S. Gold",
381
-	"Playmates Interactive",
382
-	NULL,
383
-	NULL,
384
-	"Fox Interactive",
385
-	"Time Warner Interactive",
386
-	NULL,
387
-	NULL,
388
-	NULL,
389
-	NULL,
390
-	NULL,
391
-	"Disney Interactive",
392
-	NULL,
393
-	"Black Pearl",
394
-	NULL,
395
-	"Advanced Productions",
396
-	NULL,
397
-	NULL,
398
-	"GT Interactive",
399
-	"RARE",
400
-	"Crave Entertainment",
401
-	"Absolute Entertainment",
402
-	"Acclaim",
403
-	"Activision",
404
-	"American Sammy",
405
-	"Take 2/GameTek",
406
-	"Hi Tech",
407
-	"LJN Ltd.",
408
-	NULL,
409
-	"Mattel",
410
-	NULL,
411
-	"Mindscape/Red Orb Entertainment",
412
-	"Romstar",
413
-	"Taxan",
414
-	"Midway/Tradewest",
415
-	NULL,
416
-	"American Softworks Corp.",
417
-	"Majesco Sales Inc.",
418
-	"3DO",
419
-	NULL,
420
-	NULL,
421
-	"Hasbro",
422
-	"NewKidCo",
423
-	"Telegames",
424
-	"Metro3D",
425
-	NULL,
426
-	"Vatical Entertainment",
427
-	"LEGO Media",
428
-	NULL,
429
-	"Xicat Interactive",
430
-	"Cryo Interactive",
431
-	NULL,
432
-	NULL,
433
-	"Red Storm Entertainment",
434
-	"Microids",
435
-	NULL,
436
-	"Conspiracy/Swing",
437
-	"Titus",
438
-	"Virgin Interactive",
439
-	"Maxis",
440
-	NULL,
441
-	"LucasArts Entertainment",
442
-	NULL,
443
-	NULL,
444
-	"Ocean",
445
-	NULL,
446
-	"Electronic Arts",
447
-	NULL,
448
-	"Laser Beam",
449
-	NULL,
450
-	NULL,
451
-	"Elite Systems",
452
-	"Electro Brain",
453
-	"The Learning Company",
454
-	"BBC",
455
-	NULL,
456
-	"Software 2000",
457
-	NULL,
458
-	"BAM! Entertainment",
459
-	"Studio 3",
460
-	NULL,
461
-	NULL,
462
-	NULL,
463
-	"Classified Games",
464
-	NULL,
465
-	"TDK Mediactive",
466
-	NULL,
467
-	"DreamCatcher",
468
-	"JoWood Produtions",
469
-	"SEGA",
470
-	"Wannado Edition",
471
-	"LSP (Light & Shadow Prod.)",
472
-	"ITE Media",
473
-	"Infogrames",
474
-	"Interplay",
475
-	"JVC (US)",
476
-	"Parker Brothers",
477
-	NULL,
478
-	"SCI (Sales Curve Interactive)/Storm",
479
-	NULL,
480
-	NULL,
481
-	"THQ Software",
482
-	"Accolade Inc.",
483
-	"Triffix Entertainment",
484
-	NULL,
485
-	"Microprose Software",
486
-	"Universal Interactive/Sierra/Simon & Schuster",
487
-	NULL,
488
-	"Kemco",
489
-	"Rage Software",
490
-	"Encore",
491
-	NULL,
492
-	"Zoo",
493
-	"Kiddinx",
494
-	"Simon & Schuster Interactive",
495
-	"Asmik Ace Entertainment Inc./AIA",
496
-	"Empire Interactive",
497
-	NULL,
498
-	NULL,
499
-	"Jester Interactive",
500
-	NULL,
501
-	"Rockstar Games",
502
-	"Scholastic",
503
-	"Ignition Entertainment",
504
-	"Summitsoft",
505
-	"Stadlbauer",
506
-	NULL,
507
-	NULL,
508
-	NULL,
509
-	"Misawa",
510
-	"Teichiku",
511
-	"Namco Ltd.",
512
-	"LOZC",
513
-	"KOEI",
514
-	NULL,
515
-	"Tokuma Shoten Intermedia",
516
-	"Tsukuda Original",
517
-	"DATAM-Polystar",
518
-	NULL,
519
-	NULL,
520
-	"Bullet-Proof Software",
521
-	"Vic Tokai Inc.",
522
-	NULL,
523
-	"Character Soft",
524
-	"I'Max",
525
-	"Saurus",
526
-	NULL,
527
-	NULL,
528
-	"General Entertainment",
529
-	NULL,
530
-	NULL,
531
-	"I'Max",
532
-	"Success",
533
-	NULL,
534
-	"SEGA Japan",
535
-	NULL,
536
-	NULL,
537
-	NULL,
538
-	NULL,
539
-	NULL,
540
-	NULL,
541
-	NULL,
542
-	NULL,
543
-	NULL,
544
-	NULL,
545
-	"Takara",
546
-	"Chun Soft",
547
-	"Video System Co., Ltd./McO'River",
548
-	"BEC",
549
-	NULL,
550
-	"Varie",
551
-	"Yonezawa/S'pal",
552
-	"Kaneko",
553
-	NULL,
554
-	"Victor Interactive Software/Pack-in-Video",
555
-	"Nichibutsu/Nihon Bussan",
556
-	"Tecmo",
557
-	"Imagineer",
558
-	NULL,
559
-	NULL,
560
-	"Nova",
561
-	"Den'Z",
562
-	"Bottom Up",
563
-	NULL,
564
-	"TGL (Technical Group Laboratory)",
565
-	NULL,
566
-	"Hasbro Japan",
567
-	NULL,
568
-	"Marvelous Entertainment",
569
-	NULL,
570
-	"Keynet Inc.",
571
-	"Hands-On Entertainment",
572
-	NULL,
573
-	NULL,
574
-	NULL,
575
-	NULL,
576
-	NULL,
577
-	NULL,
578
-	NULL,
579
-	NULL,
580
-	NULL,
581
-	"Telenet",
582
-	"Hori",
583
-	NULL,
584
-	NULL,
585
-	"Konami",
586
-	"K.Amusement Leasing Co.",
587
-	"Kawada",
588
-	"Takara",
589
-	NULL,
590
-	"Technos Japan Corp.",
591
-	"JVC (Europe/Japan)/Victor Musical Industries",
592
-	NULL,
593
-	"Toei Animation",
594
-	"Toho",
595
-	NULL,
596
-	"Namco",
597
-	"Media Rings Corp.",
598
-	"J-Wing",
599
-	NULL,
600
-	"Pioneer LDC",
601
-	"KID",
602
-	"Mediafactory",
603
-	NULL,
604
-	NULL,
605
-	NULL,
606
-	"Infogrames Hudson",
607
-	NULL,
608
-	NULL,
609
-	NULL,
610
-	NULL,
611
-	NULL,
612
-	NULL,
613
-	NULL,
614
-	NULL,
615
-	NULL,
616
-	NULL,
617
-	"Acclaim Japan",
618
-	"ASCII Co./Nexoft",
619
-	"Bandai",
620
-	NULL,
621
-	"Enix",
622
-	NULL,
623
-	"HAL Laboratory/Halken",
624
-	"SNK",
625
-	NULL,
626
-	"Pony Canyon Hanbai",
627
-	"Culture Brain",
628
-	"Sunsoft",
629
-	"Toshiba EMI",
630
-	"Sony Imagesoft",
631
-	NULL,
632
-	"Sammy",
633
-	"Magical",
634
-	"Visco",
635
-	NULL,
636
-	"Compile",
637
-	NULL,
638
-	"MTO Inc.",
639
-	NULL,
640
-	"Sunrise Interactive",
641
-	NULL,
642
-	"Global A Entertainment",
643
-	"Fuuki",
644
-	NULL,
645
-	NULL,
646
-	NULL,
647
-	NULL,
648
-	NULL,
649
-	NULL,
650
-	NULL,
651
-	NULL,
652
-	NULL,
653
-	"Taito",
654
-	NULL,
655
-	"Kemco",
656
-	"Square",
657
-	"Tokuma Shoten",
658
-	"Data East",
659
-	"Tonkin House",
660
-	NULL,
661
-	"KOEI",
662
-	NULL,
663
-	"Konami/Ultra/Palcom",
664
-	"NTVIC/VAP",
665
-	"Use Co., Ltd.",
666
-	"Meldac",
667
-	"Pony Canyon (Japan)/FCI (US)",
668
-	"Angel/Sotsu Agency/Sunrise",
669
-	"Yumedia/Aroma Co., Ltd.",
670
-	NULL,
671
-	NULL,
672
-	"Boss",
673
-	"Axela/Crea-Tech",
674
-	"Sekaibunka-Sha/Sumire kobo/Marigul Management Inc.",
675
-	"Konami Computer Entertainment Osaka",
676
-	NULL,
677
-	NULL,
678
-	"Enterbrain",
679
-	NULL,
680
-	NULL,
681
-	NULL,
682
-	NULL,
683
-	NULL,
684
-	NULL,
685
-	NULL,
686
-	NULL,
687
-	NULL,
688
-	NULL,
689
-	"Taito/Disco",
690
-	"Sofel",
691
-	"Quest Corp.",
692
-	"Sigma",
693
-	"Ask Kodansha",
694
-	NULL,
695
-	"Naxat",
696
-	"Copya System",
697
-	"Capcom Co., Ltd.",
698
-	"Banpresto",
699
-	"TOMY",
700
-	"Acclaim/LJN Japan",
701
-	NULL,
702
-	"NCS",
703
-	"Human Entertainment",
704
-	"Altron",
705
-	"Jaleco",
706
-	"Gaps Inc.",
707
-	NULL,
708
-	NULL,
709
-	NULL,
710
-	NULL,
711
-	NULL,
712
-	"Elf",
713
-	NULL,
714
-	NULL,
715
-	NULL,
716
-	NULL,
717
-	NULL,
718
-	NULL,
719
-	NULL,
720
-	NULL,
721
-	NULL,
722
-	NULL,
723
-	NULL,
724
-	NULL,
725
-	"Jaleco",
726
-	NULL,
727
-	"Yutaka",
728
-	"Varie",
729
-	"T&ESoft",
730
-	"Epoch Co., Ltd.",
731
-	NULL,
732
-	"Athena",
733
-	"Asmik",
734
-	"Natsume",
735
-	"King Records",
736
-	"Atlus",
737
-	"Epic/Sony Records (Japan)",
738
-	NULL,
739
-	"IGS (Information Global Service)",
740
-	NULL,
741
-	"Chatnoir",
742
-	"Right Stuff",
743
-	NULL,
744
-	"NTT COMWARE",
745
-	NULL,
746
-	"Spike",
747
-	"Konami Computer Entertainment Tokyo",
748
-	"Alphadream Corp.",
749
-	NULL,
750
-	"Sting",
751
-	NULL,
752
-	NULL,
753
-	NULL,
754
-	NULL,
755
-	NULL,
756
-	NULL,
757
-	NULL,
758
-	NULL,
759
-	NULL,
760
-	NULL,
761
-	"A Wave",
762
-	"Motown Software",
763
-	"Left Field Entertainment",
764
-	"Extreme Entertainment Group",
765
-	"TecMagik",
766
-	NULL,
767
-	NULL,
768
-	NULL,
769
-	NULL,
770
-	"Cybersoft",
771
-	NULL,
772
-	"Psygnosis",
773
-	NULL,
774
-	NULL,
775
-	"Davidson/Western Tech.",
776
-	"Unlicensed",
777
-	NULL,
778
-	NULL,
779
-	NULL,
780
-	NULL,
781
-	"The Game Factory Europe",
782
-	"Hip Games",
783
-	"Aspyr",
784
-	NULL,
785
-	NULL,
786
-	"Mastiff",
787
-	"iQue",
788
-	"Digital Tainment Pool",
789
-	"XS Games",
790
-	"Daiwon",
791
-	NULL,
792
-	NULL,
793
-	NULL,
794
-	NULL,
795
-	NULL,
796
-	NULL,
797
-	NULL,
798
-	"PCCW Japan",
799
-	NULL,
800
-	NULL,
801
-	"KiKi Co. Ltd.",
802
-	"Open Sesame Inc.",
803
-	"Sims",
804
-	"Broccoli",
805
-	"Avex",
806
-	"D3 Publisher",
807
-	NULL,
808
-	"Konami Computer Entertainment Japan",
809
-	NULL,
810
-	"Square-Enix",
811
-	"KSG",
812
-	"Micott & Basara Inc.",
813
-	NULL,
814
-	"Orbital Media",
815
-	NULL,
816
-	NULL,
817
-	NULL,
818
-	NULL,
819
-	NULL,
820
-	NULL,
821
-	NULL,
822
-	NULL,
823
-	NULL,
824
-	NULL,
825
-	NULL,
826
-	NULL,
827
-	NULL,
828
-	NULL,
829
-	NULL,
830
-	NULL,
831
-	"The Game Factory USA",
832
-	NULL,
833
-	NULL,
834
-	"Treasure",
835
-	"Aruze",
836
-	"Ertain",
837
-	"SNK Playmore",
838
-	NULL,
839
-	NULL,
840
-	NULL,
841
-	NULL,
842
-	NULL,
843
-	NULL,
844
-	NULL,
845
-	NULL,
846
-	NULL,
847
-	NULL,
848
-	NULL,
849
-	NULL,
850
-	NULL,
851
-	NULL,
852
-	NULL,
853
-	NULL,
854
-	NULL,
855
-	NULL,
856
-	NULL,
857
-	NULL,
858
-	NULL,
859
-	NULL,
860
-	NULL,
861
-	NULL,
862
-	NULL,
863
-	NULL,
864
-	NULL,
865
-	NULL,
866
-	NULL,
867
-	NULL,
868
-	NULL,
869
-	NULL,
870
-	NULL,
871
-	NULL,
872
-	NULL,
873
-	NULL,
874
-	NULL,
875
-	NULL,
876
-	NULL,
877
-	NULL,
878
-	NULL,
879
-	NULL,
880
-	NULL,
881
-	NULL,
882
-	NULL,
883
-	NULL,
884
-	NULL,
885
-	NULL,
886
-	"Yojigen"
887
-};*/
888
-
889
-static const uint32_t	crc32Table[256] =
187
+
188
+static const uint32_t crc32Table[] =
890 189
 {
891 190
 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
892 191
 	0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
... ...
@@ -933,316 +232,88 @@ static const uint32_t	crc32Table[256] =
933 232
 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
934 233
 };
935 234
 
936
-//static void S9xDeinterleaveType1 (int, uint8_t *);
937
-//static void S9xDeinterleaveType2 (int, uint8_t *);
938
-//static void S9xDeinterleaveGD24 (int, uint8_t *);
939
-//static bool allASCII (uint8_t *, int);
940
-//static bool is_SufamiTurbo_BIOS (uint8_t *, uint32_t);
941
-//static bool is_SufamiTurbo_Cart (uint8_t *, uint32_t);
942
-//static bool is_SameGame_BIOS (uint8_t *, uint32_t);
943
-//static bool is_SameGame_Add_On (uint8_t *, uint32_t);
944
-//static uint32_t caCRC32 (uint8_t *, uint32_t, uint32_t crc32 = 0xffffffff);
945
-/*static uint32_t ReadUPSPointer (const uint8_t *, unsigned &, unsigned);
946
-static bool ReadUPSPatch (Reader *, long, int32_t &);
947
-static long ReadInt (Reader *, unsigned);
948
-static bool ReadIPSPatch (Reader *, long, int32_t &);*/
949
-#ifdef UNZIP_SUPPORT
950
-static int unzFindExtension (unzFile &, const char *, bool restart = true, bool print = true);
951
-#endif
952
-
953 235
 // deinterleave
954 236
 
955
-static void S9xDeinterleaveType1 (int size, uint8_t *base)
237
+static void S9xDeinterleaveType1(int size, uint8_t *base)
956 238
 {
957
-	//Settings.DisplayColor = BUILD_PIXEL(0, 31, 0);
958
-	//SET_UI_COLOR(0, 255, 0);
239
+	uint8_t blocks[256];
240
+	int nblocks = size >> 16;
959 241
 
960
-	uint8_t	blocks[256];
961
-	int		nblocks = size >> 16;
962
-
963
-	for (int i = 0; i < nblocks; i++)
242
+	for (int i = 0; i < nblocks; ++i)
964 243
 	{
965 244
 		blocks[i * 2] = i + nblocks;
966 245
 		blocks[i * 2 + 1] = i;
967 246
 	}
968 247
 
969
-	uint8_t	*tmp = (uint8_t *) malloc(0x8000);
970
-	if (tmp)
971
-	{
972
-		for (int i = 0; i < nblocks * 2; i++)
973
-		{
974
-			for (int j = i; j < nblocks * 2; j++)
248
+	for (int i = 0; i < nblocks * 2; ++i)
249
+		for (int j = i; j < nblocks * 2; ++j)
250
+			if (blocks[j] == i)
975 251
 			{
976
-				if (blocks[j] == i)
977
-				{
978
-					memmove(tmp, &base[blocks[j] * 0x8000], 0x8000);
979
-					memmove(&base[blocks[j] * 0x8000], &base[blocks[i] * 0x8000], 0x8000);
980
-					memmove(&base[blocks[i] * 0x8000], tmp, 0x8000);
981
-					uint8_t	b = blocks[j];
982
-					blocks[j] = blocks[i];
983
-					blocks[i] = b;
984
-					break;
985
-				}
252
+				std::swap_ranges(&base[blocks[i] * 0x8000], &base[(blocks[i] + 1) * 0x8000], &base[blocks[j] * 0x8000]);
253
+				std::swap(blocks[i], blocks[j]);
254
+				break;
986 255
 			}
987
-		}
988
-
989
-		free(tmp);
990
-	}
991 256
 }
992 257
 
993
-static void S9xDeinterleaveType2 (int size, uint8_t *base)
994
-{
995
-	// for odd Super FX images
996
-	//Settings.DisplayColor = BUILD_PIXEL(31, 14, 6);
997
-	//SET_UI_COLOR(255, 119, 25);
998
-
999
-	uint8_t	blocks[256];
1000
-	int		nblocks = size >> 16;
1001
-	int		step = 64;
1002
-
1003
-	while (nblocks <= step)
1004
-		step >>= 1;
1005
-	nblocks = step;
1006
-
1007
-	for (int i = 0; i < nblocks * 2; i++)
1008
-		blocks[i] = (i & ~0xf) | ((i & 3) << 2) | ((i & 12) >> 2);
1009
-
1010
-	uint8_t	*tmp = (uint8_t *) malloc(0x10000);
1011
-	if (tmp)
1012
-	{
1013
-		for (int i = 0; i < nblocks * 2; i++)
1014
-		{
1015
-			for (int j = i; j < nblocks * 2; j++)
1016
-			{
1017
-				if (blocks[j] == i)
1018
-				{
1019
-					memmove(tmp, &base[blocks[j] * 0x10000], 0x10000);
1020
-					memmove(&base[blocks[j] * 0x10000], &base[blocks[i] * 0x10000], 0x10000);
1021
-					memmove(&base[blocks[i] * 0x10000], tmp, 0x10000);
1022
-					uint8_t	b = blocks[j];
1023
-					blocks[j] = blocks[i];
1024
-					blocks[i] = b;
1025
-					break;
1026
-				}
1027
-			}
1028
-		}
1029
-
1030
-		free(tmp);
1031
-	}
1032
-}
258
+// allocation and deallocation
1033 259
 
1034
-static void S9xDeinterleaveGD24 (int size, uint8_t *base)
260
+bool CMemory::Init()
1035 261
 {
1036
-	// for 24Mb images dumped with Game Doctor
1037
-	if (size != 0x300000)
1038
-		return;
262
+	this->RAM.reset(new uint8_t[0x20000]);
263
+	this->SRAM.reset(new uint8_t[0x20000]);
264
+	this->VRAM.reset(new uint8_t[0x10000]);
265
+	this->RealROM.reset(new uint8_t[MAX_ROM_SIZE + 0x200 + 0x8000]);
1039 266
 
1040
-	//Settings.DisplayColor = BUILD_PIXEL(0, 31, 31);
1041
-	//SET_UI_COLOR(0, 255, 255);
1042
-
1043
-	uint8_t	*tmp = (uint8_t *) malloc(0x80000);
1044
-	if (tmp)
267
+	if (!this->RAM || !this->SRAM || !this->VRAM || !this->RealROM)
1045 268
 	{
1046
-		memmove(tmp, &base[0x180000], 0x80000);
1047
-		memmove(&base[0x180000], &base[0x200000], 0x80000);
1048
-		memmove(&base[0x200000], &base[0x280000], 0x80000);
1049
-		memmove(&base[0x280000], tmp, 0x80000);
1050
-
1051
-		free(tmp);
1052
-
1053
-		S9xDeinterleaveType1(size, base);
269
+		this->Deinit();
270
+		return false;
1054 271
 	}
1055
-}
1056
-
1057
-// allocation and deallocation
1058 272
 
1059
-bool CMemory::Init()
1060
-{
1061
-    RAM	 = (uint8_t *) malloc(0x20000);
1062
-    SRAM = (uint8_t *) malloc(0x20000);
1063
-    VRAM = (uint8_t *) malloc(0x10000);
1064
-    ROM  = (uint8_t *) malloc(MAX_ROM_SIZE + 0x200 + 0x8000);
1065
-
1066
-	IPPU.TileCache[TILE_2BIT]       = (uint8_t *) malloc(MAX_2BIT_TILES * 64);
1067
-	IPPU.TileCache[TILE_4BIT]       = (uint8_t *) malloc(MAX_4BIT_TILES * 64);
1068
-	IPPU.TileCache[TILE_8BIT]       = (uint8_t *) malloc(MAX_8BIT_TILES * 64);
1069
-	IPPU.TileCache[TILE_2BIT_EVEN]  = (uint8_t *) malloc(MAX_2BIT_TILES * 64);
1070
-	IPPU.TileCache[TILE_2BIT_ODD]   = (uint8_t *) malloc(MAX_2BIT_TILES * 64);
1071
-	IPPU.TileCache[TILE_4BIT_EVEN]  = (uint8_t *) malloc(MAX_4BIT_TILES * 64);
1072
-	IPPU.TileCache[TILE_4BIT_ODD]   = (uint8_t *) malloc(MAX_4BIT_TILES * 64);
1073
-
1074
-	IPPU.TileCached[TILE_2BIT]      = (uint8_t *) malloc(MAX_2BIT_TILES);
1075
-	IPPU.TileCached[TILE_4BIT]      = (uint8_t *) malloc(MAX_4BIT_TILES);
1076
-	IPPU.TileCached[TILE_8BIT]      = (uint8_t *) malloc(MAX_8BIT_TILES);
1077
-	IPPU.TileCached[TILE_2BIT_EVEN] = (uint8_t *) malloc(MAX_2BIT_TILES);
1078
-	IPPU.TileCached[TILE_2BIT_ODD]  = (uint8_t *) malloc(MAX_2BIT_TILES);
1079
-	IPPU.TileCached[TILE_4BIT_EVEN] = (uint8_t *) malloc(MAX_4BIT_TILES);
1080
-	IPPU.TileCached[TILE_4BIT_ODD]  = (uint8_t *) malloc(MAX_4BIT_TILES);
1081
-
1082
-	if (!RAM || !SRAM || !VRAM || !ROM ||
1083
-		!IPPU.TileCache[TILE_2BIT]       ||
1084
-		!IPPU.TileCache[TILE_4BIT]       ||
1085
-		!IPPU.TileCache[TILE_8BIT]       ||
1086
-		!IPPU.TileCache[TILE_2BIT_EVEN]  ||
1087
-		!IPPU.TileCache[TILE_2BIT_ODD]   ||
1088
-		!IPPU.TileCache[TILE_4BIT_EVEN]  ||
1089
-		!IPPU.TileCache[TILE_4BIT_ODD]   ||
1090
-		!IPPU.TileCached[TILE_2BIT]      ||
1091
-		!IPPU.TileCached[TILE_4BIT]      ||
1092
-		!IPPU.TileCached[TILE_8BIT]      ||
1093
-		!IPPU.TileCached[TILE_2BIT_EVEN] ||
1094
-		!IPPU.TileCached[TILE_2BIT_ODD]  ||
1095
-		!IPPU.TileCached[TILE_4BIT_EVEN] ||
1096
-		!IPPU.TileCached[TILE_4BIT_ODD])
1097
-    {
1098
-		Deinit();
1099
-		return false;
1100
-    }
1101
-
1102
-	ZeroMemory(RAM,  0x20000);
1103
-	ZeroMemory(SRAM, 0x20000);
1104
-	ZeroMemory(VRAM, 0x10000);
1105
-	ZeroMemory(ROM,  MAX_ROM_SIZE + 0x200 + 0x8000);
1106
-
1107
-	ZeroMemory(IPPU.TileCache[TILE_2BIT],       MAX_2BIT_TILES * 64);
1108
-	ZeroMemory(IPPU.TileCache[TILE_4BIT],       MAX_4BIT_TILES * 64);
1109
-	ZeroMemory(IPPU.TileCache[TILE_8BIT],       MAX_8BIT_TILES * 64);
1110
-	ZeroMemory(IPPU.TileCache[TILE_2BIT_EVEN],  MAX_2BIT_TILES * 64);
1111
-	ZeroMemory(IPPU.TileCache[TILE_2BIT_ODD],   MAX_2BIT_TILES * 64);
1112
-	ZeroMemory(IPPU.TileCache[TILE_4BIT_EVEN],  MAX_4BIT_TILES * 64);
1113
-	ZeroMemory(IPPU.TileCache[TILE_4BIT_ODD],   MAX_4BIT_TILES * 64);
1114
-
1115
-	ZeroMemory(IPPU.TileCached[TILE_2BIT],      MAX_2BIT_TILES);
1116
-	ZeroMemory(IPPU.TileCached[TILE_4BIT],      MAX_4BIT_TILES);
1117
-	ZeroMemory(IPPU.TileCached[TILE_8BIT],      MAX_8BIT_TILES);
1118
-	ZeroMemory(IPPU.TileCached[TILE_2BIT_EVEN], MAX_2BIT_TILES);
1119
-	ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD],  MAX_2BIT_TILES);
1120
-	ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES);
1121
-	ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD],  MAX_4BIT_TILES);
273
+	std::fill(&this->RAM[0], &this->RAM[0x20000], 0);
274
+	std::fill(&this->SRAM[0], &this->SRAM[0x20000], 0);
275
+	std::fill(&this->VRAM[0], &this->VRAM[0x10000], 0);
276
+	std::fill(&this->RealROM[0], &this->RealROM[MAX_ROM_SIZE + 0x200 + 0x8000], 0);
1122 277
 
1123 278
 	// FillRAM uses first 32K of ROM image area, otherwise space just
1124 279
 	// wasted. Might be read by the SuperFX code.
1125 280
 
1126
-	FillRAM = ROM;
281
+	this->FillRAM = &this->RealROM[0];
1127 282
 
1128 283
 	// Add 0x8000 to ROM image pointer to stop SuperFX code accessing
1129 284
 	// unallocated memory (can cause crash on some ports).
1130 285
 
1131
-	ROM += 0x8000;
1132
-
1133
-	C4RAM   = ROM + 0x400000 + 8192 * 8; // C4
1134
-	OBC1RAM = ROM + 0x400000; // OBC1
1135
-	BIOSROM = ROM + 0x300000; // BS
1136
-	BSRAM   = ROM + 0x400000; // BS
1137
-
1138
-	/*SuperFX.pvRegisters = FillRAM + 0x3000;
1139
-	SuperFX.nRamBanks   = 2; // Most only use 1.  1=64KB=512Mb, 2=128KB=1024Mb
1140
-	SuperFX.pvRam       = SRAM;
1141
-	SuperFX.nRomBanks   = (2 * 1024 * 1024) / (32 * 1024);
1142
-	SuperFX.pvRom       = (uint8_t *) ROM;*/
1143
-
1144
-	PostRomInitFunc = NULL;
286
+	this->ROM = &this->RealROM[0x8000];
1145 287
 
1146 288
 	return true;
1147 289
 }
1148 290
 
1149 291
 void CMemory::Deinit()
1150 292
 {
1151
-	if (RAM)
1152
-	{
1153
-		free(RAM);
1154
-		RAM = NULL;
1155
-	}
1156
-
1157
-	if (SRAM)
1158
-	{
1159
-		free(SRAM);
1160
-		SRAM = NULL;
1161
-	}
293
+	this->RAM.reset();
294
+	this->SRAM.reset();
295
+	this->VRAM.reset();
296
+	this->ROM = nullptr;
297
+	this->RealROM.reset();
1162 298
 
1163
-	if (VRAM)
1164
-	{
1165
-		free(VRAM);
1166
-		VRAM = NULL;
1167
-	}
1168
-
1169
-	if (ROM)
1170
-	{
1171
-		ROM -= 0x8000;
1172
-		free(ROM);
1173
-		ROM = NULL;
1174
-	}
1175
-
1176
-	for (int t = 0; t < 7; t++)
1177
-	{
1178
-		if (IPPU.TileCache[t])
1179
-		{
1180
-			free(IPPU.TileCache[t]);
1181
-			IPPU.TileCache[t] = NULL;
1182
-		}
1183
-
1184
-		if (IPPU.TileCached[t])
1185
-		{
1186
-			free(IPPU.TileCached[t]);
1187
-			IPPU.TileCached[t] = NULL;
1188
-		}
1189
-	}
1190
-
1191
-	Safe(NULL);
1192
-	SafeANK(NULL);
299
+	this->Safe(nullptr);
1193 300
 }
1194 301
 
1195 302
 // file management and ROM detection
1196 303
 
1197
-static bool allASCII (uint8_t *b, int size)
304
+static bool allASCII(uint8_t *b, int size)
1198 305
 {
1199
-	for (int i = 0; i < size; i++)
1200
-	{
306
+	for (int i = 0; i < size; ++i)
1201 307
 		if (b[i] < 32 || b[i] > 126)
1202 308
 			return false;
1203
-	}
1204 309
 
1205 310
 	return true;
1206 311
 }
1207 312
 
1208
-/*static bool is_SufamiTurbo_BIOS (uint8_t *data, uint32_t size)
313
+int CMemory::ScoreHiROM(bool skip_header, int32_t romoff)
1209 314
 {
1210
-	if (size == 0x40000 &&
1211
-		strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) == 0)
1212
-		return true;
1213
-	else
1214
-		return false;
1215
-}*/
1216
-
1217
-/*static bool is_SufamiTurbo_Cart (uint8_t *data, uint32_t size)
1218
-{
1219
-	if (size >= 0x80000 && size <= 0x100000 &&
1220
-		strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) != 0)
1221
-		return true;
1222
-	else
1223
-		return false;
1224
-}*/
1225
-
1226
-/*static bool is_SameGame_BIOS (uint8_t *data, uint32_t size)
1227
-{
1228
-	if (size == 0x100000 && strncmp((char *) (data + 0xffc0), "Same Game Tsume Game", 20) == 0)
1229
-		return true;
1230
-	else
1231
-		return false;
1232
-}*/
1233
-
1234
-/*static bool is_SameGame_Add_On (uint8_t *data, uint32_t size)
1235
-{
1236
-	if (size == 0x80000)
1237
-		return true;
1238
-	else
1239
-		return false;
1240
-}*/
1241
-
1242
-int CMemory::ScoreHiROM (bool skip_header, int32_t romoff)
1243
-{
1244
-	uint8_t	*buf = ROM + 0xff00 + romoff + (skip_header ? 0x200 : 0);
1245
-	int		score = 0;
315
+	uint8_t *buf = &this->ROM[0xff00 + romoff + (skip_header ? 0x200 : 0)];
316
+	int score = 0;
1246 317
 
1247 318
 	if (buf[0xd5] & 0x1)
1248 319
 		score += 2;
... ...
@@ -1257,8 +328,8 @@ int CMemory::ScoreHiROM (bool skip_header, int32_t romoff)
1257 328
 	if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff)
1258 329
 	{
1259 330
 		score += 2;
1260
-		if (0 != (buf[0xde] + (buf[0xdf] << 8)))
1261
-			score++;
331
+		if (buf[0xde] + (buf[0xdf] << 8))
332
+			++score;
1262 333
 	}
1263 334
 
1264 335
 	if (buf[0xda] == 0x33)
... ...
@@ -1273,25 +344,25 @@ int CMemory::ScoreHiROM (bool skip_header, int32_t romoff)
1273 344
 	if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0)
1274 345
 		score -= 2; // reduced after looking at a scan by Cowering
1275 346
 
1276
-	if (CalculatedSize > 1024 * 1024 * 3)
347
+	if (this->CalculatedSize > 1024 * 1024 * 3)
1277 348
 		score += 4;
1278 349
 
1279 350
 	if ((1 << (buf[0xd7] - 7)) > 48)
1280
-		score -= 1;
351
+		--score;
1281 352
 
1282 353
 	if (!allASCII(&buf[0xb0], 6))
1283
-		score -= 1;
354
+		--score;
1284 355
 
1285 356
 	if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1))
1286
-		score -= 1;
357
+		--score;
1287 358
 
1288 359
 	return score;
1289 360
 }
1290 361
 
1291
-int CMemory::ScoreLoROM (bool skip_header, int32_t romoff)
362
+int CMemory::ScoreLoROM(bool skip_header, int32_t romoff)
1292 363
 {
1293
-	uint8_t	*buf = ROM + 0x7f00 + romoff + (skip_header ? 0x200 : 0);
1294
-	int		score = 0;
364
+	uint8_t *buf = &this->ROM[0x7f00 + romoff + (skip_header ? 0x200 : 0)];
365
+	int score = 0;
1295 366
 
1296 367
 	if (!(buf[0xd5] & 0x1))
1297 368
 		score += 3;
... ...
@@ -1303,8 +374,8 @@ int CMemory::ScoreLoROM (bool skip_header, int32_t romoff)
1303 374
 	if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff)
1304 375
 	{
1305 376
 		score += 2;
1306
-		if (0 != (buf[0xde] + (buf[0xdf] << 8)))
1307
-			score++;
377
+		if (buf[0xde] + (buf[0xdf] << 8))
378
+			++score;
1308 379
 	}
1309 380
 
1310 381
 	if (buf[0xda] == 0x33)
... ...
@@ -1319,281 +390,99 @@ int CMemory::ScoreLoROM (bool skip_header, int32_t romoff)
1319 390
 	if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0)
1320 391
 		score -= 2; // reduced per Cowering suggestion
1321 392
 
1322
-	if (CalculatedSize <= 1024 * 1024 * 16)
393
+	if (this->CalculatedSize <= 1024 * 1024 * 16)
1323 394
 		score += 2;
1324 395
 
1325 396
 	if ((1 << (buf[0xd7] - 7)) > 48)
1326
-		score -= 1;
397
+		--score;
1327 398
 
1328 399
 	if (!allASCII(&buf[0xb0], 6))
1329
-		score -= 1;
400
+		--score;
1330 401
 
1331 402
 	if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1))
1332
-		score -= 1;
403
+		--score;
1333 404
 
1334 405
 	return score;
1335 406
 }
1336 407
 
1337
-/*uint32_t CMemory::HeaderRemove (uint32_t size, int32_t &headerCount, uint8_t *buf)
1338
-{
1339
-	uint32_t	calc_size = (size / 0x2000) * 0x2000;
1340
-
1341
-	if ((size - calc_size == 512 && !Settings.ForceNoHeader) || Settings.ForceHeader)
1342
-	{
1343
-		uint8_t	*NSRTHead = buf + 0x1D0; // NSRT Header Location
1344
-
1345
-		// detect NSRT header
1346
-		if (!strncmp("NSRT", (char *) &NSRTHead[24], 4))
1347
-		{
1348
-			if (NSRTHead[28] == 22)
1349
-			{
1350
-				if (((std::accumulate(NSRTHead, NSRTHead + sizeof(NSRTHeader), 0) & 0xFF) == NSRTHead[30]) &&
1351
-					(NSRTHead[30] + NSRTHead[31] == 255) && ((NSRTHead[0] & 0x0F) <= 13) &&
1352
-					(((NSRTHead[0] & 0xF0) >> 4) <= 3) && ((NSRTHead[0] & 0xF0) >> 4))
1353
-					memcpy(NSRTHeader, NSRTHead, sizeof(NSRTHeader));
1354
-			}
1355
-		}
1356
-
1357
-		memmove(buf, buf + 512, calc_size);
1358
-		headerCount++;
1359
-		size -= 512;
1360
-	}
1361
-
1362
-	return size;
1363
-}*/
1364
-
1365
-/*uint32_t CMemory::FileLoader (uint8_t *buffer, const char *filename, int32_t maxsize)
1366
-{
1367
-	// <- ROM size without header
1368
-	// ** Memory.HeaderCount
1369
-	// ** Memory.ROMFilename
1370
-
1371
-	int32_t	totalSize = 0;
1372
-    char	fname[PATH_MAX + 1];
1373
-    char	drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], name[_MAX_FNAME + 1], exts[_MAX_EXT + 1];
1374
-	char	*ext;
1375
-
1376
-#if defined(_WIN32) || defined(__MACOSX__)
1377
-	ext = &exts[1];
1378
-#else
1379
-	ext = &exts[0];
1380
-#endif
1381
-
1382
-	memset(NSRTHeader, 0, sizeof(NSRTHeader));
1383
-	HeaderCount = 0;
1384
-
1385
-	_splitpath(filename, drive, dir, name, exts);
1386
-	_makepath(fname, drive, dir, name, exts);
1387
-
1388
-	int	nFormat = FILE_DEFAULT;
1389
-	if (strcasecmp(ext, "zip") == 0)
1390
-		nFormat = FILE_ZIP;
1391
-	else
1392
-	if (strcasecmp(ext, "jma") == 0)
1393
-		nFormat = FILE_JMA;
1394
-
1395
-	switch (nFormat)
1396
-	{
1397
-		case FILE_ZIP:
1398
-		{
1399
-		#ifdef UNZIP_SUPPORT
1400
-			if (!LoadZip(fname, &totalSize, &HeaderCount, buffer))
1401
-			{
1402
-			 	S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid Zip archive.");
1403
-				return 0;
1404
-			}
1405
-
1406
-			strcpy(ROMFilename, fname);
1407
-		#else
1408
-			//S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with Zip support.");
1409
-			return 0;
1410
-		#endif
1411
-			break;
1412
-		}
1413
-
1414
-		case FILE_JMA:
1415
-		{
1416
-		#ifdef JMA_SUPPORT
1417
-			size_t	size = load_jma_file(fname, buffer);
1418
-			if (!size)
1419
-			{
1420
-			 	S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid JMA archive.");
1421
-				return 0;
1422
-			}
1423
-
1424
-			totalSize = HeaderRemove(size, HeaderCount, buffer);
1425
-
1426
-			strcpy(ROMFilename, fname);
1427
-		#else
1428
-			//S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with JMA support.");
1429
-			return 0;
1430
-		#endif
1431
-			break;
1432
-		}
1433
-
1434
-		case FILE_DEFAULT:
1435
-		default:
1436
-		{
1437
-			STREAM	fp = OPEN_STREAM(fname, "rb");
1438
-			if (!fp)
1439
-				return 0;
1440
-
1441
-			strcpy(ROMFilename, fname);
1442
-
1443
-			int 	len  = 0;
1444
-			uint32_t	size = 0;
1445
-			bool	more = false;
1446
-			uint8_t	*ptr = buffer;
1447
-
1448
-			do
1449
-			{
1450
-				size = READ_STREAM(ptr, maxsize + 0x200 - (ptr - buffer), fp);
1451
-				CLOSE_STREAM(fp);
1452
-
1453
-				size = HeaderRemove(size, HeaderCount, ptr);
1454
-				totalSize += size;
1455
-				ptr += size;
1456
-
1457
-				// check for multi file roms
1458
-				if (ptr - buffer < maxsize + 0x200 &&
1459
-					(isdigit(ext[0]) && ext[1] == 0 && ext[0] < '9'))
1460
-				{
1461
-					more = true;
1462
-					ext[0]++;
1463
-					_makepath(fname, drive, dir, name, exts);
1464
-				}
1465
-				else
1466
-				if (ptr - buffer < maxsize + 0x200 &&
1467
-					(((len = strlen(name)) == 7 || len == 8) &&
1468
-					strncasecmp(name, "sf", 2) == 0 &&
1469
-					isdigit(name[2]) && isdigit(name[3]) && isdigit(name[4]) && isdigit(name[5]) &&
1470
-					isalpha(name[len - 1])))
1471
-				{
1472
-					more = true;
1473
-					name[len - 1]++;
1474
-					_makepath(fname, drive, dir, name, exts);
1475
-				}
1476
-				else
1477
-					more = false;
1478
-
1479
-			}	while (more && (fp = OPEN_STREAM(fname, "rb")) != NULL);
1480
-
1481
-			break;
1482
-		}
1483
-	}
1484
-
1485
-    if (HeaderCount == 0)
1486
-		S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found.");
1487
-    else
1488
-    if (HeaderCount == 1)
1489
-		S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found ROM file header (and ignored it).");
1490
-	else
1491
-		S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found multiple ROM file headers (and ignored them).");
1492
-
1493
-	return (uint32_t) totalSize;
1494
-}*/
1495
-
1496
-//bool CMemory::LoadROM (const char *filename)
1497
-bool CMemory::LoadROMSNSF(const unsigned char *lrombuf, int32_t lromsize, const unsigned char *srambuf, int32_t sramsize)
408
+bool CMemory::LoadROMSNSF(const uint8_t *lrombuf, int32_t lromsize, const uint8_t *srambuf, int32_t sramsize)
1498 409
 {
1499
-	int	retry_count = 0;
410
+	int retry_count = 0;
1500 411
 
1501
-	/*if (!filename || !*filename)
1502
-		return false;*/
1503
-
1504
-	ZeroMemory(ROM, MAX_ROM_SIZE);
1505
-	ZeroMemory(&Multi, sizeof(Multi));
412
+	std::fill(&this->ROM[0], &this->ROM[MAX_ROM_SIZE], 0);
1506 413
 
1507 414
 again:
1508
-	//Settings.DisplayColor = BUILD_PIXEL(31, 31, 31);
1509
-	//SET_UI_COLOR(255, 255, 255);
1510
-
1511
-	CalculatedSize = 0;
1512
-	ExtendedFormat = NOPE;
415
+	this->CalculatedSize = 0;
416
+	this->ExtendedFormat = NOPE;
1513 417
 
1514
-	int32_t totalFileSize;
1515
-
1516
-	//totalFileSize = FileLoader(ROM, filename, MAX_ROM_SIZE);
1517
-	totalFileSize  = std::min<int32_t>(MAX_ROM_SIZE, lromsize);
418
+	int32_t totalFileSize = std::min<int32_t>(MAX_ROM_SIZE, lromsize);
1518 419
 	if (!totalFileSize)
1519 420
 		return false;
1520
-	memcpy(ROM, lrombuf, totalFileSize);
421
+	std::copy(&lrombuf[0], &lrombuf[totalFileSize], &this->ROM[0]);
1521 422
 	SNESGameFixes.SRAMInitialValue = 0xff;
1522
-	memset(SRAM, SNESGameFixes.SRAMInitialValue, 0x20000);
423
+	std::fill(&this->SRAM[0], &this->SRAM[0x20000], SNESGameFixes.SRAMInitialValue);
1523 424
 	if (srambuf && sramsize)
1524
-		memcpy(SRAM, srambuf, sramsize);
1525
-
1526
-	/*if (!Settings.NoPatch)
1527
-		CheckForAnyPatch(filename, HeaderCount != 0, totalFileSize);*/
425
+		std::copy(&srambuf[0], &srambuf[sramsize], &this->SRAM[0]);
1528 426
 
1529
-	int	hi_score, lo_score;
427
+	int hi_score = this->ScoreHiROM(false);
428
+	int lo_score = this->ScoreLoROM(false);
1530 429
 
1531
-	hi_score = ScoreHiROM(false);
1532
-	lo_score = ScoreLoROM(false);
1533
-
1534
-	if (HeaderCount == 0 && !Settings.ForceNoHeader &&
1535
-		((hi_score >  lo_score && ScoreHiROM(true) > hi_score) ||
1536
-		 (hi_score <= lo_score && ScoreLoROM(true) > lo_score)))
430
+	if (((hi_score > lo_score && this->ScoreHiROM(true) > hi_score) || (hi_score <= lo_score && this->ScoreLoROM(true) > lo_score)))
1537 431
 	{
1538
-		memmove(ROM, ROM + 512, totalFileSize - 512);
432
+		memmove(&this->ROM[0], &this->ROM[512], totalFileSize - 512);
1539 433
 		totalFileSize -= 512;
1540
-		//S9xMessage(S9X_INFO, S9X_HEADER_WARNING, "Try 'force no-header' option if the game doesn't work");
1541 434
 		// modifying ROM, so we need to rescore
1542
-		hi_score = ScoreHiROM(false);
1543
-		lo_score = ScoreLoROM(false);
435
+		hi_score = this->ScoreHiROM(false);
436
+		lo_score = this->ScoreLoROM(false);
1544 437
 	}
1545 438
 
1546
-	CalculatedSize = (totalFileSize / 0x2000) * 0x2000;
439
+	this->CalculatedSize = (totalFileSize / 0x2000) * 0x2000;
1547 440
 
1548
-	if (CalculatedSize > 0x400000 &&
1549
-		(ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x4332 && // exclude S-DD1
1550
-		(ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x4532 &&
1551
-		(ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF93a && // exclude SPC7110
1552
-		(ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF53a)
1553
-		ExtendedFormat = YEAH;
441
+	if (this->CalculatedSize > 0x400000 &&
442
+		this->ROM[0x7fd5] + (this->ROM[0x7fd6] << 8) != 0x4332 && // exclude S-DD1
443
+		this->ROM[0x7fd5] + (this->ROM[0x7fd6] << 8) != 0x4532 &&
444
+		this->ROM[0xffd5] + (this->ROM[0xffd6] << 8) != 0xF93a && // exclude SPC7110
445
+		this->ROM[0xffd5] + (this->ROM[0xffd6] << 8) != 0xF53a)
446
+		this->ExtendedFormat = YEAH;
1554 447
 
1555 448
 	// if both vectors are invalid, it's type 1 interleaved LoROM
1556
-	if (ExtendedFormat == NOPE &&
1557
-		((ROM[0x7ffc] + (ROM[0x7ffd] << 8)) < 0x8000) &&
1558
-		((ROM[0xfffc] + (ROM[0xfffd] << 8)) < 0x8000))
449
+	if (this->ExtendedFormat == NOPE && this->ROM[0x7ffc] + (this->ROM[0x7ffd] << 8) < 0x8000 && this->ROM[0xfffc] + (this->ROM[0xfffd] << 8) < 0x8000)
1559 450
 	{
1560
-		if (!Settings.ForceInterleaved && !Settings.ForceNotInterleaved)
1561
-			S9xDeinterleaveType1(totalFileSize, ROM);
451
+		if (!Settings.ForceNotInterleaved)
452
+			S9xDeinterleaveType1(totalFileSize, &this->ROM[0]);
1562 453
 	}
1563 454
 
1564 455
 	// CalculatedSize is now set, so rescore
1565
-	hi_score = ScoreHiROM(false);
1566
-	lo_score = ScoreLoROM(false);
456
+	hi_score = this->ScoreHiROM(false);
457
+	lo_score = this->ScoreLoROM(false);
1567 458
 
1568
-	uint8_t	*RomHeader = ROM;
459
+	uint8_t *RomHeader = &this->ROM[0];
1569 460
 
1570
-	if (ExtendedFormat != NOPE)
461
+	if (this->ExtendedFormat != NOPE)
1571 462
 	{
1572
-		int	swappedhirom, swappedlorom;
1573
-
1574
-		swappedhirom = ScoreHiROM(false, 0x400000);
1575
-		swappedlorom = ScoreLoROM(false, 0x400000);
463
+		int swappedhirom = this->ScoreHiROM(false, 0x400000);
464
+		int swappedlorom = this->ScoreLoROM(false, 0x400000);
1576 465
 
1577 466
 		// set swapped here
1578 467
 		if (std::max(swappedlorom, swappedhirom) >= std::max(lo_score, hi_score))
1579 468
 		{
1580
-			ExtendedFormat = BIGFIRST;
469
+			this->ExtendedFormat = BIGFIRST;
1581 470
 			hi_score = swappedhirom;
1582 471
 			lo_score = swappedlorom;
1583 472
 			RomHeader += 0x400000;
1584 473
 		}
1585 474
 		else
1586
-			ExtendedFormat = SMALLFIRST;
475
+			this->ExtendedFormat = SMALLFIRST;
1587 476
 	}
1588 477
 
1589
-	bool	interleaved, tales = false;
478
+	bool tales = false;
1590 479
 
1591
-    interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2 || Settings.ForceInterleaveGD24;
480
+	bool interleaved = false;
1592 481
 
1593
-	if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score))
482
+	if (lo_score >= hi_score)
1594 483
 	{
1595
-		LoROM = true;
1596
-		HiROM = false;
484
+		this->LoROM = true;
485
+		this->HiROM = false;
1597 486
 
1598 487
 		// ignore map type byte if not 0x2x or 0x3x
1599 488
 		if ((RomHeader[0x7fd5] & 0xf0) == 0x20 || (RomHeader[0x7fd5] & 0xf0) == 0x30)
... ...
@@ -1613,8 +502,8 @@ again:
1613 502
 	}
1614 503
 	else
1615 504
 	{
1616
-		LoROM = false;
1617
-		HiROM = true;
505
+		this->LoROM = false;
506
+		this->HiROM = true;
1618 507
 
1619 508
 		if ((RomHeader[0xffd5] & 0xf0) == 0x20 || (RomHeader[0xffd5] & 0xf0) == 0x30)
1620 509
 		{
... ...
@@ -1629,2698 +518,626 @@ again:
1629 518
 	}
1630 519
 
1631 520
 	// this two games fail to be detected
1632
-	if (!Settings.ForceHiROM && !Settings.ForceLoROM)
521
+	if (!strncmp(reinterpret_cast<char *>(&this->ROM[0x7fc0]), "YUYU NO QUIZ DE GO!GO!", 22) || !strncmp(reinterpret_cast<char *>(&this->ROM[0xffc0]), "BATMAN--REVENGE JOKER",  21))
1633 522
 	{
1634
-		if (strncmp((char *) &ROM[0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0 ||
1635
-		   (strncmp((char *) &ROM[0xffc0], "BATMAN--REVENGE JOKER",  21) == 0))
1636
-		{
1637
-			LoROM = true;
1638
-			HiROM = false;
1639
-			interleaved = false;
1640
-			tales = false;
1641
-		}
523
+		this->LoROM = true;
524
+		this->HiROM = false;
525
+		interleaved = false;
526
+		tales = false;
1642 527
 	}
1643 528
 
1644 529
 	if (!Settings.ForceNotInterleaved && interleaved)
1645 530
 	{
1646
-		//S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "ROM image is in interleaved format - converting...");
1647
-
1648 531
 		if (tales)
1649 532
 		{
1650
-			if (ExtendedFormat == BIGFIRST)
533
+			if (this->ExtendedFormat == BIGFIRST)
1651 534
 			{
1652
-				S9xDeinterleaveType1(0x400000, ROM);
1653
-				S9xDeinterleaveType1(CalculatedSize - 0x400000, ROM + 0x400000);
535
+				S9xDeinterleaveType1(0x400000, &this->ROM[0]);
536
+				S9xDeinterleaveType1(this->CalculatedSize - 0x400000, &this->ROM[0x400000]);
1654 537
 			}
1655 538
 			else
1656 539
 			{
1657
-				S9xDeinterleaveType1(CalculatedSize - 0x400000, ROM);
1658
-				S9xDeinterleaveType1(0x400000, ROM + CalculatedSize - 0x400000);
540
+				S9xDeinterleaveType1(this->CalculatedSize - 0x400000, &this->ROM[0]);
541
+				S9xDeinterleaveType1(0x400000, &this->ROM[this->CalculatedSize - 0x400000]);
1659 542
 			}
1660 543
 
1661
-			LoROM = false;
1662
-			HiROM = true;
1663
-		}
1664
-		else
1665
-		if (Settings.ForceInterleaveGD24 && CalculatedSize == 0x300000)
1666
-		{
1667
-			bool	t = LoROM;
1668
-			LoROM = HiROM;
1669
-			HiROM = t;
1670
-			S9xDeinterleaveGD24(CalculatedSize, ROM);
544
+			this->LoROM = false;
545
+			this->HiROM = true;
1671 546
 		}
1672 547
 		else
1673
-		if (Settings.ForceInterleaved2)
1674
-			S9xDeinterleaveType2(CalculatedSize, ROM);
1675
-		else
1676 548
 		{
1677
-			bool	t = LoROM;
1678
-			LoROM = HiROM;
1679
-			HiROM = t;
1680
-			S9xDeinterleaveType1(CalculatedSize, ROM);
549
+			std::swap(this->LoROM, this->HiROM);
550
+			S9xDeinterleaveType1(this->CalculatedSize, &this->ROM[0]);
1681 551
 		}
1682 552
 
1683
-		hi_score = ScoreHiROM(false);
1684
-		lo_score = ScoreLoROM(false);
553
+		hi_score = this->ScoreHiROM(false);
554
+		lo_score = this->ScoreLoROM(false);
1685 555
 
1686
-		if ((HiROM && (lo_score >= hi_score || hi_score < 0)) ||
1687
-			(LoROM && (hi_score >  lo_score || lo_score < 0)))
556
+		if (((this->HiROM && (lo_score >= hi_score || hi_score < 0)) || (this->LoROM && (hi_score > lo_score || lo_score < 0))) && !retry_count)
1688 557
 		{
1689
-			if (retry_count == 0)
1690
-			{
1691
-				//S9xMessage(S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO, "ROM lied about its type! Trying again.");
1692
-				Settings.ForceNotInterleaved = true;
1693
-				Settings.ForceInterleaved = false;
1694
-				retry_count++;
1695
-				goto again;
1696
-			}
558
+			Settings.ForceNotInterleaved = true;
559
+			++retry_count;
560
+			goto again;
1697 561
 		}
1698
-    }
562
+	}
1699 563
 
1700
-	if (ExtendedFormat == SMALLFIRST)
564
+	if (this->ExtendedFormat == SMALLFIRST)
1701 565
 		tales = true;
1702 566
 
1703 567
 	if (tales)
1704 568
 	{
1705
-		uint8_t	*tmp = (uint8_t *) malloc(CalculatedSize - 0x400000);
1706
-		if (tmp)
1707
-		{
1708
-			//S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "Fixing swapped ExHiROM...");
1709
-			memmove(tmp, ROM, CalculatedSize - 0x400000);
1710
-			memmove(ROM, ROM + CalculatedSize - 0x400000, 0x400000);
1711
-			memmove(ROM + 0x400000, tmp, CalculatedSize - 0x400000);
1712
-			free(tmp);
1713
-		}
569
+		auto tmp = std::vector<uint8_t>(this->CalculatedSize - 0x400000);
570
+		memmove(&tmp[0], &this->ROM[0], this->CalculatedSize - 0x400000);
571
+		memmove(&this->ROM[0], &this->ROM[this->CalculatedSize - 0x400000], 0x400000);
572
+		memmove(&this->ROM[0x400000], &tmp[0], this->CalculatedSize - 0x400000);
1714 573
 	}
1715 574
 
1716
-	/*if (strncmp(LastRomFilename, filename, PATH_MAX + 1))
1717
-	{
1718
-		strncpy(LastRomFilename, filename, PATH_MAX + 1);
1719
-		LastRomFilename[PATH_MAX] = 0;
1720
-	}*/
1721
-
1722
-	ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes));
575
+	memset(&SNESGameFixes, 0, sizeof(SNESGameFixes));
1723 576
 	SNESGameFixes.SRAMInitialValue = 0x60;
1724 577
 
1725
-	//S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
1726
-
1727
-	InitROM();
1728
-
1729
-	/*S9xInitCheatData();
1730
-	S9xApplyCheats();*/
578
+	this->InitROM();
1731 579
 
1732 580
 	S9xReset();
1733 581
 
1734
-    return true;
582
+	return true;
1735 583
 }
1736 584
 
1737
-/*bool CMemory::LoadMultiCart (const char *cartA, const char *cartB)
1738
-{
1739
-	bool	r = true;
1740
-
1741
-	ZeroMemory(ROM, MAX_ROM_SIZE);
1742
-	ZeroMemory(&Multi, sizeof(Multi));
1743
-
1744
-	Settings.DisplayColor = BUILD_PIXEL(31, 31, 31);
1745
-	SET_UI_COLOR(255, 255, 255);
1746
-
1747
-	CalculatedSize = 0;
1748
-	ExtendedFormat = NOPE;
585
+// initialization
1749 586
 
1750
-	if (cartA && cartA[0])
1751
-		Multi.cartSizeA = FileLoader(ROM, cartA, MAX_ROM_SIZE);
587
+char *CMemory::Safe(const char *s)
588
+{
589
+	static std::unique_ptr<char[]> safe;
590
+	static int safe_len = 0;
1752 591
 
1753
-	if (Multi.cartSizeA == 0)
592
+	if (!s)
1754 593
 	{
1755
-		if (cartB && cartB[0])
1756
-			Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE);
1757
-	}
594
+		if (safe)
595
+			safe.reset();
1758 596
 
1759
-	if (Multi.cartSizeA)
1760
-	{
1761
-		if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeA))
1762
-			Multi.cartType = 4;
1763
-		else
1764
-		if (is_SameGame_BIOS(ROM, Multi.cartSizeA))
1765
-			Multi.cartType = 3;
1766
-	}
1767
-	else
1768
-	if (Multi.cartSizeB)
1769
-	{
1770
-		if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeB))
1771
-			Multi.cartType = 4;
597
+		return nullptr;
1772 598
 	}
1773
-	else
1774
-		Multi.cartType = 4; // assuming BIOS only
1775 599
 
1776
-	switch (Multi.cartType)
600
+	int len = strlen(s);
601
+	if (!safe || len + 1 > safe_len)
1777 602
 	{
1778
-		case 4:
1779
-			r = LoadSufamiTurbo(cartA, cartB);
1780
-			break;
1781
-
1782
-		case 3:
1783
-			r = LoadSameGame(cartA, cartB);
1784
-			break;
1785
-
1786
-		default:
1787
-			r = false;
603
+		safe_len = len + 1;
604
+		safe.reset(new char[safe_len]);
1788 605
 	}
1789 606
 
1790
-	if (!r)
607
+	for (int i = 0; i < len; ++i)
1791 608
 	{
1792
-		ZeroMemory(&Multi, sizeof(Multi));
1793
-		return false;
609
+		if (s[i] >= 32 && s[i] < 127)
610
+			safe[i] = s[i];
611
+		else
612
+			safe[i] = '_';
1794 613
 	}
1795 614
 
1796
-	ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes));
1797
-	SNESGameFixes.SRAMInitialValue = 0x60;
1798
-
1799
-	S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
615
+	safe[len] = 0;
1800 616
 
1801
-	InitROM();
617
+	return safe.get();
618
+}
1802 619
 
1803
-	S9xInitCheatData();
1804
-	S9xApplyCheats();
620
+void CMemory::ParseSNESHeader(uint8_t *RomHeader)
621
+{
622
+	strncpy(this->ROMName, reinterpret_cast<char *>(&RomHeader[0x10]), ROM_NAME_LEN - 1);
1805 623
 
1806
-	S9xReset();
624
+	this->SRAMSize = RomHeader[0x28];
625
+	this->ROMSpeed = RomHeader[0x25];
626
+	this->ROMType = RomHeader[0x26];
627
+	this->ROMRegion = RomHeader[0x29];
1807 628
 
1808
-	return true;
629
+	std::copy(&RomHeader[0x02], &RomHeader[0x06], &this->ROMId[0]);
1809 630
 }
1810 631
 
1811
-bool CMemory::LoadSufamiTurbo (const char *cartA, const char *cartB)
632
+void CMemory::InitROM()
1812 633
 {
1813
-	Multi.cartOffsetA = 0x100000;
1814
-	Multi.cartOffsetB = 0x200000;
1815
-	Multi.sramA = SRAM;
1816
-	Multi.sramB = SRAM + 0x10000;
1817
-
1818
-	if (Multi.cartSizeA)
1819
-	{
1820
-		Multi.sramSizeA = 4; // ROM[0x37]?
1821
-		Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0;
1822
-
1823
-		if (!Settings.NoPatch)
1824
-			CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA);
634
+	//// Parse ROM header and read ROM informatoin
1825 635
 
1826
-		strcpy(Multi.fileNameA, cartA);
1827
-		memcpy(ROM + Multi.cartOffsetA, ROM, Multi.cartSizeA);
1828
-	}
636
+	std::fill(&this->ROMId[0], &this->ROMId[5], 0);
1829 637
 
1830
-	if (Multi.cartSizeA && !Multi.cartSizeB)
1831
-	{
1832
-		if (cartB && cartB[0])
1833
-			Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE);
638
+	uint8_t *RomHeader = &this->ROM[0x7FB0];
639
+	if (this->ExtendedFormat == BIGFIRST)
640
+		RomHeader += 0x400000;
641
+	if (this->HiROM)
642
+		RomHeader += 0x8000;
1834 643
 
1835
-		if (Multi.cartSizeB)
1836
-		{
1837
-			if (!is_SufamiTurbo_Cart(ROM, Multi.cartSizeB))
1838
-				Multi.cartSizeB = 0;
1839
-		}
1840
-	}
644
+	this->ParseSNESHeader(RomHeader);
1841 645
 
1842
-	if (Multi.cartSizeB)
1843
-	{
1844
-		Multi.sramSizeB = 4; // ROM[0x37]?
1845
-		Multi.sramMaskB = Multi.sramSizeB ? ((1 << (Multi.sramSizeB + 3)) * 128 - 1) : 0;
646
+	//// Detect and initialize chips
647
+	//// detection codes are compatible with NSRT
1846 648
 
1847
-		if (!Settings.NoPatch)
1848
-			CheckForAnyPatch(cartB, HeaderCount != 0, Multi.cartSizeB);
649
+	uint32_t identifier = ((this->ROMType & 0xff) << 8) + (this->ROMSpeed & 0xff);
1849 650
 
1850
-		strcpy(Multi.fileNameB, cartB);
1851
-		memcpy(ROM + Multi.cartOffsetB, ROM, Multi.cartSizeB);
1852
-	}
651
+	Settings.SDD1 = identifier == 0x4332 || identifier == 0x4532;
1853 652
 
1854
-	FILE	*fp;
1855
-	size_t	size;
1856
-	char	path[PATH_MAX + 1];
653
+	//// Map memory and calculate checksum
1857 654
 
1858
-	strcpy(path, S9xGetDirectory(BIOS_DIR));
1859
-	strcat(path, SLASH_STR);
1860
-	strcat(path, "STBIOS.bin");
655
+	this->Map_Initialize();
1861 656
 
1862
-	fp = fopen(path, "rb");
1863
-	if (fp)
657
+	if (this->HiROM)
1864 658
 	{
1865
-		size = fread((void *) ROM, 1, 0x40000, fp);
1866
-		fclose(fp);
1867
-		if (!is_SufamiTurbo_BIOS(ROM, size))
1868
-			return false;
659
+		if (this->ExtendedFormat != NOPE)
660
+			this->Map_ExtendedHiROMMap();
661
+		else
662
+			this->Map_HiROMMap();
1869 663
 	}
1870 664
 	else
1871
-		return false;
1872
-
1873
-	if (Multi.cartSizeA)
1874
-		strcpy(ROMFilename, Multi.fileNameA);
1875
-	else
1876
-	if (Multi.cartSizeB)
1877
-		strcpy(ROMFilename, Multi.fileNameB);
1878
-	else
1879
-		strcpy(ROMFilename, path);
1880
-
1881
-	LoROM = true;
1882
-	HiROM = false;
1883
-	CalculatedSize = 0x40000;
665
+	{
666
+		if (Settings.SDD1)
667
+			this->Map_SDD1LoROMMap();
668
+		else if (this->ExtendedFormat != NOPE)
669
+			this->Map_JumboLoROMMap();
670
+		else if (!strncmp(this->ROMName, "WANDERERS FROM YS", 17))
671
+			this->Map_NoMAD1LoROMMap();
672
+		else if (!strncmp(this->ROMName, "SOUND NOVEL-TCOOL", 17) || !strncmp(this->ROMName, "DERBY STALLION 96", 17))
673
+			this->Map_ROM24MBSLoROMMap();
674
+		else if (!strncmp(this->ROMName, "THOROUGHBRED BREEDER3", 21) || !strncmp(this->ROMName, "RPG-TCOOL 2", 11))
675
+			this->Map_SRAM512KLoROMMap();
676
+		else
677
+			this->Map_LoROMMap();
678
+	}
1884 679
 
1885
-	return true;
1886
-}
680
+	//// Build more ROM information
1887 681
 
1888
-bool CMemory::LoadSameGame (const char *cartA, const char *cartB)
1889
-{
1890
-	Multi.cartOffsetA = 0;
1891
-	Multi.cartOffsetB = 0x200000;
1892
-	Multi.sramA = SRAM;
1893
-	Multi.sramB = NULL;
682
+	// NTSC/PAL
683
+	Settings.PAL = this->ROMRegion >= 2 && this->ROMRegion <= 12;
1894 684
 
1895
-	Multi.sramSizeA = ROM[0xffd8];
1896
-	Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0;
1897
-	Multi.sramSizeB = 0;
1898
-	Multi.sramMaskB = 0;
685
+	// truncate cart name
686
+	this->ROMName[ROM_NAME_LEN - 1] = 0;
687
+	if (strlen(this->ROMName))
688
+	{
689
+		char *p = this->ROMName + strlen(this->ROMName);
690
+		if (p > this->ROMName + 21 && this->ROMName[20] == ' ')
691
+			p = this->ROMName + 21;
692
+		while (p > this->ROMName && *(p - 1) == ' ')
693
+			--p;
694
+		*p = 0;
695
+	}
1899 696
 
1900
-	if (!Settings.NoPatch)
1901
-		CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA);
697
+	// SRAM size
698
+	this->SRAMMask = this->SRAMSize ? ((1 << (this->SRAMSize + 3)) * 128) - 1 : 0;
1902 699
 
1903
-	strcpy(Multi.fileNameA, cartA);
700
+	//// Initialize emulation
1904 701
 
1905
-	if (cartB && cartB[0])
1906
-		Multi.cartSizeB = FileLoader(ROM + Multi.cartOffsetB, cartB, MAX_ROM_SIZE - Multi.cartOffsetB);
702
+	Timings.H_Max_Master = SNES_CYCLES_PER_SCANLINE;
703
+	Timings.H_Max = Timings.H_Max_Master;
704
+	Timings.HBlankStart = SNES_HBLANK_START_HC;
705
+	Timings.HBlankEnd = SNES_HBLANK_END_HC;
706
+	Timings.HDMAInit = SNES_HDMA_INIT_HC;
707
+	Timings.HDMAStart = SNES_HDMA_START_HC;
708
+	Timings.RenderPos = SNES_RENDER_START_HC;
709
+	Timings.V_Max_Master = Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER;
710
+	Timings.V_Max = Timings.V_Max_Master;
711
+	/* From byuu: The total delay time for both the initial (H)DMA sync (to the DMA clock),
712
+	   and the end (H)DMA sync (back to the last CPU cycle's mcycle rate (6, 8, or 12)) always takes between 12-24 mcycles.
713
+	   Possible delays: { 12, 14, 16, 18, 20, 22, 24 }
714
+	   XXX: Snes9x can't emulate this timing :( so let's use the average value... */
715
+	Timings.DMACPUSync = 18;
716
+	/* If the CPU is halted (i.e. for DMA) while /NMI goes low, the NMI will trigger
717
+	   after the DMA completes (even if /NMI goes high again before the DMA
718
+	   completes). In this case, there is a 24-30 cycle delay between the end of DMA
719
+	   and the NMI handler, time enough for an instruction or two. */
720
+	// Wild Guns, Mighty Morphin Power Rangers - The Fighting Edition
721
+	Timings.NMIDMADelay = 24;
722
+	Timings.IRQPendCount = 0;
1907 723
 
1908
-	if (Multi.cartSizeB)
1909
-	{
1910
-		if (!is_SameGame_Add_On(ROM + Multi.cartOffsetB, Multi.cartSizeB))
1911
-			Multi.cartSizeB = 0;
1912
-		else
1913
-			strcpy(Multi.fileNameB, cartB);
1914
-	}
724
+	//// Hack games
1915 725
 
1916
-	strcpy(ROMFilename, Multi.fileNameA);
726
+	this->ApplyROMFixes();
1917 727
 
1918
-	LoROM = false;
1919
-	HiROM = true;
1920
-	CalculatedSize = Multi.cartSizeA;
728
+	sprintf(this->ROMName, "%s", Safe(this->ROMName));
729
+	sprintf(this->ROMId, "%s", Safe(this->ROMId));
1921 730
 
1922
-	return true;
731
+	Settings.ForceNotInterleaved = false;
1923 732
 }
1924 733
 
1925
-bool CMemory::LoadSRTC()
1926
-{
1927
-	FILE	*fp;
1928
-	size_t	ignore;
734
+// memory map
1929 735
 
1930
-	fp = fopen(S9xGetFilename(".rtc", SRAM_DIR), "rb");
1931
-	if (!fp)
1932
-		return false;
736
+uint32_t CMemory::map_mirror(uint32_t size, uint32_t pos)
737
+{
738
+	// from bsnes
739
+	if (!size)
740
+		return 0;
741
+	if (pos < size)
742
+		return pos;
1933 743
 
1934
-	ignore = fread(RTCData.reg, 1, 20, fp);
1935
-	fclose(fp);
744
+	uint32_t mask = 1 << 31;
745
+	while (!(pos & mask))
746
+		mask >>= 1;
1936 747
 
1937
-	return true;
748
+	if (size <= (pos & mask))
749
+		return this->map_mirror(size, pos - mask);
750
+	else
751
+		return mask + this->map_mirror(size - mask, pos - mask);
1938 752
 }
1939 753
 
1940
-bool CMemory::SaveSRTC()
754
+void CMemory::map_lorom(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size)
1941 755
 {
1942
-	FILE	*fp;
1943
-	size_t	ignore;
1944
-
1945
-	fp = fopen(S9xGetFilename(".rtc", SRAM_DIR), "wb");
1946
-	if (!fp)
1947
-		return false;
1948
-
1949
-	ignore = fwrite(RTCData.reg, 1, 20, fp);
1950
-	fclose(fp);
1951
-
1952
-	return true;
756
+	for (uint32_t c = bank_s; c <= bank_e; ++c)
757
+		for (uint32_t i = addr_s; i <= addr_e; i += 0x1000)
758
+		{
759
+			uint32_t p = (c << 4) | (i >> 12);
760
+			uint32_t addr = (c & 0x7f) * 0x8000;
761
+			this->Map[p] = &this->ROM[this->map_mirror(size, addr) - (i & 0x8000)];
762
+			this->BlockIsROM[p] = true;
763
+			this->BlockIsRAM[p] = false;
764
+		}
1953 765
 }
1954 766
 
1955
-void CMemory::ClearSRAM (bool onlyNonSavedSRAM)
767
+void CMemory::map_hirom(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size)
1956 768
 {
1957
-	if (onlyNonSavedSRAM)
1958
-		if (!(Settings.SuperFX && ROMType < 0x15) && !(Settings.SA1 && ROMType == 0x34)) // can have SRAM
1959
-			return;
1960
-
1961
-	memset(SRAM, SNESGameFixes.SRAMInitialValue, 0x20000);
769
+	for (uint32_t c = bank_s; c <= bank_e; ++c)
770
+		for (uint32_t i = addr_s; i <= addr_e; i += 0x1000)
771
+		{
772
+			uint32_t p = (c << 4) | (i >> 12);
773
+			uint32_t addr = c << 16;
774
+			this->Map[p] = &this->ROM[this->map_mirror(size, addr)];
775
+			this->BlockIsROM[p] = true;
776
+			this->BlockIsRAM[p] = false;
777
+		}
1962 778
 }
1963 779
 
1964
-bool CMemory::LoadSRAM (const char *filename)
780
+void CMemory::map_lorom_offset(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size, uint32_t offset)
1965 781
 {
1966
-	FILE	*file;
1967
-	int		size, len;
1968
-	char	sramName[PATH_MAX + 1];
1969
-
1970
-	strcpy(sramName, filename);
782
+	for (uint32_t c = bank_s; c <= bank_e; ++c)
783
+		for (uint32_t i = addr_s; i <= addr_e; i += 0x1000)
784
+		{
785
+			uint32_t p = (c << 4) | (i >> 12);
786
+			uint32_t addr = ((c - bank_s) & 0x7f) * 0x8000;
787
+			this->Map[p] = &this->ROM[offset + this->map_mirror(size, addr) - (i & 0x8000)];
788
+			this->BlockIsROM[p] = true;
789
+			this->BlockIsRAM[p] = false;
790
+		}
791
+}
1971 792
 
1972
-	ClearSRAM();
1973
-
1974
-	if (Multi.cartType && Multi.sramSizeB)
1975
-	{
1976
-		char	temp[PATH_MAX + 1];
1977
-
1978
-		strcpy(temp, ROMFilename);
1979
-		strcpy(ROMFilename, Multi.fileNameB);
1980
-
1981
-		size = (1 << (Multi.sramSizeB + 3)) * 128;
1982
-
1983
-		file = fopen(S9xGetFilename(".srm", SRAM_DIR), "rb");
1984
-		if (file)
1985
-		{
1986
-			len = fread((char *) Multi.sramB, 1, 0x10000, file);
1987
-			fclose(file);
1988
-			if (len - size == 512)
1989
-				memmove(Multi.sramB, Multi.sramB + 512, size);
1990
-		}
1991
-
1992
-		strcpy(ROMFilename, temp);
1993
-	}
1994
-
1995
-	size = SRAMSize ? (1 << (SRAMSize + 3)) * 128 : 0;
1996
-	if (size > 0x20000)
1997
-		size = 0x20000;
1998
-
1999
-	if (size)
2000
-	{
2001
-		file = fopen(sramName, "rb");
2002
-		if (file)
2003
-		{
2004
-			len = fread((char *) SRAM, 1, 0x20000, file);
2005
-			fclose(file);
2006
-			if (len - size == 512)
2007
-				memmove(SRAM, SRAM + 512, size);
2008
-
2009
-			if (Settings.SRTC || Settings.SPC7110RTC)
2010
-				LoadSRTC();
2011
-
2012
-			return true;
2013
-		}
2014
-		else
2015
-		if (Settings.BS && !Settings.BSXItself)
2016
-		{
2017
-			// The BS game's SRAM was not found
2018
-			// Try to read BS-X.srm instead
2019
-			char	path[PATH_MAX + 1];
2020
-
2021
-			strcpy(path, S9xGetDirectory(SRAM_DIR));
2022
-			strcat(path, SLASH_STR);
2023
-			strcat(path, "BS-X.srm");
2024
-
2025
-			file = fopen(path, "rb");
2026
-			if (file)
2027
-			{
2028
-				len = fread((char *) SRAM, 1, 0x20000, file);
2029
-				fclose(file);
2030
-				if (len - size == 512)
2031
-					memmove(SRAM, SRAM + 512, size);
2032
-
2033
-				S9xMessage(S9X_INFO, S9X_ROM_INFO, "The SRAM file wasn't found: BS-X.srm was read instead.");
2034
-				return true;
2035
-			}
2036
-			else
2037
-			{
2038
-				S9xMessage(S9X_INFO, S9X_ROM_INFO, "The SRAM file wasn't found, BS-X.srm wasn't found either.");
2039
-				return false;
2040
-			}
2041
-		}
2042
-
2043
-		return false;
2044
-	}
2045
-
2046
-	return true;
2047
-}
2048
-
2049
-bool CMemory::SaveSRAM (const char *filename)
2050
-{
2051
-	if (Settings.SuperFX && ROMType < 0x15) // doesn't have SRAM
2052
-		return true;
2053
-
2054
-	if (Settings.SA1 && ROMType == 0x34)    // doesn't have SRAM
2055
-		return true;
2056
-
2057
-	FILE	*file;
2058
-	int		size;
2059
-	char	sramName[PATH_MAX + 1];
2060
-
2061
-	strcpy(sramName, filename);
2062
-
2063
-	if (Multi.cartType && Multi.sramSizeB)
2064
-	{
2065
-		char	name[PATH_MAX + 1], temp[PATH_MAX + 1];
2066
-
2067
-		strcpy(temp, ROMFilename);
2068
-		strcpy(ROMFilename, Multi.fileNameB);
2069
-		strcpy(name, S9xGetFilename(".srm", SRAM_DIR));
2070
-
2071
-		size = (1 << (Multi.sramSizeB + 3)) * 128;
2072
-
2073
-		file = fopen(name, "wb");
2074
-		if (file)
2075
-		{
2076
-			size_t	ignore;
2077
-			ignore = fwrite((char *) Multi.sramB, size, 1, file);
2078
-			fclose(file);
2079
-		#ifdef __linux
2080
-			ignore = chown(name, getuid(), getgid());
2081
-		#endif
2082
-		}
2083
-
2084
-		strcpy(ROMFilename, temp);
2085
-    }
2086
-
2087
-    size = SRAMSize ? (1 << (SRAMSize + 3)) * 128 : 0;
2088
-	if (size > 0x20000)
2089
-		size = 0x20000;
2090
-
2091
-	if (size)
2092
-	{
2093
-		file = fopen(sramName, "wb");
2094
-		if (file)
2095
-		{
2096
-			size_t	ignore;
2097
-			ignore = fwrite((char *) SRAM, size, 1, file);
2098
-			fclose(file);
2099
-		#ifdef __linux
2100
-			ignore = chown(sramName, getuid(), getgid());
2101
-		#endif
2102
-
2103
-			if (Settings.SRTC || Settings.SPC7110RTC)
2104
-				SaveSRTC();
2105
-
2106
-			return true;
2107
-		}
2108
-	}
2109
-
2110
-	return false;
2111
-}*/
2112
-
2113
-// initialization
2114
-
2115
-static uint32_t caCRC32 (uint8_t *array, uint32_t size, uint32_t crc32 = 0xffffffff)
2116
-{
2117
-	for (uint32_t i = 0; i < size; i++)
2118
-		crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ array[i]) & 0xFF];
2119
-
2120
-	return ~crc32;
2121
-}
2122
-
2123
-char * CMemory::Safe (const char *s)
2124
-{
2125
-	static char	*safe = NULL;
2126
-	static int	safe_len = 0;
2127
-
2128
-	if (s == NULL)
2129
-	{
2130
-		if (safe)
2131
-		{
2132
-			free(safe);
2133
-			safe = NULL;
2134
-		}
2135
-
2136
-		return NULL;
2137
-	}
2138
-
2139
-	int	len = strlen(s);
2140
-	if (!safe || len + 1 > safe_len)
2141
-	{
2142
-		if (safe)
2143
-			free(safe);
2144
-
2145
-		safe_len = len + 1;
2146
-		safe = (char *) malloc(safe_len);
2147
-	}
2148
-
2149
-	for (int i = 0; i < len; i++)
2150
-	{
2151
-		if (s[i] >= 32 && s[i] < 127)
2152
-			safe[i] = s[i];
2153
-		else
2154
-			safe[i] = '_';
2155
-	}
2156
-
2157
-	safe[len] = 0;
2158
-
2159
-	return safe;
2160
-}
2161
-
2162
-char * CMemory::SafeANK (const char *s)
2163
-{
2164
-	static char	*safe = NULL;
2165
-	static int	safe_len = 0;
2166
-
2167
-	if (s == NULL)
2168
-	{
2169
-		if (safe)
2170
-		{
2171
-			free(safe);
2172
-			safe = NULL;
2173
-		}
2174
-
2175
-		return NULL;
2176
-	}
2177
-
2178
-	int	len = strlen(s);
2179
-	if (!safe || len + 1 > safe_len)
2180
-	{
2181
-		if (safe)
2182
-			free(safe);
2183
-
2184
-		safe_len = len + 1;
2185
-		safe = (char *) malloc(safe_len);
2186
-	}
2187
-
2188
-	for (int i = 0; i < len; i++)
2189
-	{
2190
-		if (s[i] >= 32 && s[i] < 127) // ASCII
2191
-			safe [i] = s[i];
2192
-		else
2193
-		if (ROMRegion == 0 && ((uint8_t) s[i] >= 0xa0 && (uint8_t) s[i] < 0xe0)) // JIS X 201 - Katakana
2194
-			safe [i] = s[i];
2195
-		else
2196
-			safe [i] = '_';
2197
-	}
2198
-
2199
-	safe [len] = 0;
2200
-
2201
-	return safe;
2202
-}
2203
-
2204
-void CMemory::ParseSNESHeader (uint8_t *RomHeader)
2205
-{
2206
-	bool	bs = Settings.BS & !Settings.BSXItself;
2207
-
2208
-	strncpy(ROMName, (char *) &RomHeader[0x10], ROM_NAME_LEN - 1);
2209
-	if (bs)
2210
-		memset(ROMName + 16, 0x20, ROM_NAME_LEN - 17);
2211
-
2212
-	if (bs)
2213
-	{
2214
-		if (!(((RomHeader[0x29] & 0x20) && CalculatedSize <  0x100000) ||
2215
-			 (!(RomHeader[0x29] & 0x20) && CalculatedSize == 0x100000)))
2216
-			printf("BS: Size mismatch\n");
2217
-
2218
-		// FIXME
2219
-		int	p = 0;
2220
-		while ((1 << p) < (int) CalculatedSize)
2221
-			p++;
2222
-		ROMSize = p - 10;
2223
-	}
2224
-	else
2225
-		ROMSize = RomHeader[0x27];
2226
-
2227
-	SRAMSize  = bs ? 5 /* BS-X */    : RomHeader[0x28];
2228
-	ROMSpeed  = bs ? RomHeader[0x28] : RomHeader[0x25];
2229
-	ROMType   = bs ? 0xE5 /* BS-X */ : RomHeader[0x26];
2230
-	ROMRegion = bs ? 0               : RomHeader[0x29];
2231
-
2232
-	ROMChecksum           = RomHeader[0x2E] + (RomHeader[0x2F] << 8);
2233
-	ROMComplementChecksum = RomHeader[0x2C] + (RomHeader[0x2D] << 8);
2234
-
2235
-	memmove(ROMId, &RomHeader[0x02], 4);
2236
-
2237
-	if (RomHeader[0x2A] != 0x33)
2238
-		CompanyId = ((RomHeader[0x2A] >> 4) & 0x0F) * 36 + (RomHeader[0x2A] & 0x0F);
2239
-	else
2240
-	if (isalnum(RomHeader[0x00]) && isalnum(RomHeader[0x01]))
2241
-	{
2242
-		int	l, r, l2, r2;
2243
-		l = toupper(RomHeader[0x00]);
2244
-		r = toupper(RomHeader[0x01]);
2245
-		l2 = (l > '9') ? l - '7' : l - '0';
2246
-		r2 = (r > '9') ? r - '7' : r - '0';
2247
-		CompanyId = l2 * 36 + r2;
2248
-	}
2249
-}
2250
-
2251
-void CMemory::InitROM()
2252
-{
2253
-	Settings.SuperFX = false;
2254
-	Settings.DSP = 0;
2255
-	Settings.SA1 = false;
2256
-	Settings.C4 = false;
2257
-	Settings.SDD1 = false;
2258
-	Settings.SPC7110 = false;
2259
-	Settings.SPC7110RTC = false;
2260
-	Settings.OBC1 = false;
2261
-	Settings.SETA = 0;
2262
-	Settings.SRTC = false;
2263
-	Settings.BS = false;
2264
-
2265
-	//SuperFX.nRomBanks = CalculatedSize >> 15;
2266
-
2267
-	//// Parse ROM header and read ROM informatoin
2268
-
2269
-	CompanyId = -1;
2270
-	memset(ROMId, 0, 5);
2271
-
2272
-	uint8_t	*RomHeader = ROM + 0x7FB0;
2273
-	if (ExtendedFormat == BIGFIRST)
2274
-		RomHeader += 0x400000;
2275
-	if (HiROM)
2276
-		RomHeader += 0x8000;
2277
-
2278
-	//S9xInitBSX(); // Set BS header before parsing
2279
-
2280
-	ParseSNESHeader(RomHeader);
2281
-
2282
-	//// Detect and initialize chips
2283
-	//// detection codes are compatible with NSRT
2284
-
2285
-	// DSP1/2/3/4
2286
-	if (ROMType == 0x03)
2287
-	{
2288
-		if (ROMSpeed == 0x30)
2289
-			Settings.DSP = 4; // DSP4
2290
-		else
2291
-			Settings.DSP = 1; // DSP1
2292
-	}
2293
-	else
2294
-	if (ROMType == 0x05)
2295
-	{
2296
-		if (ROMSpeed == 0x20)
2297
-			Settings.DSP = 2; // DSP2
2298
-		else
2299
-		if (ROMSpeed == 0x30 && RomHeader[0x2a] == 0xb2)
2300
-			Settings.DSP = 3; // DSP3
2301
-		else
2302
-			Settings.DSP = 1; // DSP1
2303
-	}
2304
-
2305
-	/*switch (Settings.DSP)
2306
-	{
2307
-		case 1:	// DSP1
2308
-			if (HiROM)
2309
-			{
2310
-				DSP0.boundary = 0x7000;
2311
-				DSP0.maptype = M_DSP1_HIROM;
2312
-			}
2313
-			else
2314
-			if (CalculatedSize > 0x100000)
2315
-			{
2316
-				DSP0.boundary = 0x4000;
2317
-				DSP0.maptype = M_DSP1_LOROM_L;
2318
-			}
2319
-			else
2320
-			{
2321
-				DSP0.boundary = 0xc000;
2322
-				DSP0.maptype = M_DSP1_LOROM_S;
2323
-			}
2324
-
2325
-			SetDSP = &DSP1SetByte;
2326
-			GetDSP = &DSP1GetByte;
2327
-			break;
2328
-
2329
-		case 2: // DSP2
2330
-			DSP0.boundary = 0x10000;
2331
-			DSP0.maptype = M_DSP2_LOROM;
2332
-			SetDSP = &DSP2SetByte;
2333
-			GetDSP = &DSP2GetByte;
2334
-			break;
2335
-
2336
-		case 3: // DSP3
2337
-			DSP0.boundary = 0xc000;
2338
-			DSP0.maptype = M_DSP3_LOROM;
2339
-			SetDSP = &DSP3SetByte;
2340
-			GetDSP = &DSP3GetByte;
2341
-			break;
2342
-
2343
-		case 4: // DSP4
2344
-			DSP0.boundary = 0xc000;
2345
-			DSP0.maptype = M_DSP4_LOROM;
2346
-			SetDSP = &DSP4SetByte;
2347
-			GetDSP = &DSP4GetByte;
2348
-			break;
2349
-
2350
-		default:
2351
-			SetDSP = NULL;
2352
-			GetDSP = NULL;
2353
-			break;
2354
-	}*/
2355
-
2356
-	uint32_t	identifier = ((ROMType & 0xff) << 8) + (ROMSpeed & 0xff);
2357
-
2358
-	switch (identifier)
2359
-	{
2360
-	    // SRTC
2361
-		/*case 0x5535:
2362
-			Settings.SRTC = true;
2363
-			S9xInitSRTC();
2364
-			break;
2365
-
2366
-		// SPC7110
2367
-		case 0xF93A:
2368
-			Settings.SPC7110RTC = true;
2369
-		case 0xF53A:
2370
-			Settings.SPC7110 = true;
2371
-			S9xInitSPC7110();
2372
-			break;
2373
-
2374
-		// OBC1
2375
-		case 0x2530:
2376
-			Settings.OBC1 = true;
2377
-			break;
2378
-
2379
-		// SA1
2380
-		case 0x3423:
2381
-		case 0x3523:
2382
-			Settings.SA1 = true;
2383
-			break;
2384
-
2385
-		// SuperFX
2386
-		case 0x1320:
2387
-		case 0x1420:
2388
-		case 0x1520:
2389
-		case 0x1A20:
2390
-			Settings.SuperFX = true;
2391
-			S9xInitSuperFX();
2392
-			if (ROM[0x7FDA] == 0x33)
2393
-				SRAMSize = ROM[0x7FBD];
2394
-			else
2395
-				SRAMSize = 5;
2396
-			break;*/
2397
-
2398
-		// SDD1
2399
-		case 0x4332:
2400
-		case 0x4532:
2401
-			Settings.SDD1 = true;
2402
-			break;
2403
-
2404
-		// ST018
2405
-		/*case 0xF530:
2406
-			Settings.SETA = ST_018;
2407
-			SetSETA = NULL;
2408
-			GetSETA = NULL;
2409
-			SRAMSize = 2;
2410
-			SNESGameFixes.SRAMInitialValue = 0x00;
2411
-			break;
2412
-
2413
-		// ST010/011
2414
-		case 0xF630:
2415
-			if (ROM[0x7FD7] == 0x09)
2416
-			{
2417
-				Settings.SETA = ST_011;
2418
-				SetSETA = &S9xSetST011;
2419
-				GetSETA = &S9xGetST011;
2420
-			}
2421
-			else
2422
-			{
2423
-				Settings.SETA = ST_010;
2424
-				SetSETA = &S9xSetST010;
2425
-				GetSETA = &S9xGetST010;
2426
-			}
2427
-
2428
-			SRAMSize = 2;
2429
-			SNESGameFixes.SRAMInitialValue = 0x00;
2430
-			break;
2431
-
2432
-		// C4
2433
-		case 0xF320:
2434
-			Settings.C4 = true;
2435
-			break;*/
2436
-	}
2437
-
2438
-	//// Map memory and calculate checksum
2439
-
2440
-	Map_Initialize();
2441
-	CalculatedChecksum = 0;
2442
-
2443
-	if (HiROM)
2444
-    {
2445
-		if (Settings.BS)
2446
-			/* Do nothing */;
2447
-		else
2448
-		/*if (Settings.SPC7110)
2449
-			Map_SPC7110HiROMMap();
2450
-		else*/
2451
-		if (ExtendedFormat != NOPE)
2452
-			Map_ExtendedHiROMMap();
2453
-		/*else
2454
-		if (Multi.cartType == 3)
2455
-			Map_SameGameHiROMMap();*/
2456
-		else
2457
-			Map_HiROMMap();
2458
-    }
2459
-    else
2460
-    {
2461
-		if (Settings.BS)
2462
-			/* Do nothing */;
2463
-		else
2464
-		/*if (Settings.SETA && Settings.SETA != ST_018)
2465
-			Map_SetaDSPLoROMMap();
2466
-		else
2467
-		if (Settings.SuperFX)
2468
-			Map_SuperFXLoROMMap();
2469
-		else
2470
-		if (Settings.SA1)
2471
-			Map_SA1LoROMMap();
2472
-		else*/
2473
-		if (Settings.SDD1)
2474
-			Map_SDD1LoROMMap();
2475
-		else
2476
-		if (ExtendedFormat != NOPE)
2477
-			Map_JumboLoROMMap();
2478
-		else
2479
-		if (strncmp(ROMName, "WANDERERS FROM YS", 17) == 0)
2480
-			Map_NoMAD1LoROMMap();
2481
-		else
2482
-		if (strncmp(ROMName, "SOUND NOVEL-TCOOL", 17) == 0 ||
2483
-			strncmp(ROMName, "DERBY STALLION 96", 17) == 0)
2484
-			Map_ROM24MBSLoROMMap();
2485
-		else
2486
-		if (strncmp(ROMName, "THOROUGHBRED BREEDER3", 21) == 0 ||
2487
-			strncmp(ROMName, "RPG-TCOOL 2", 11) == 0)
2488
-			Map_SRAM512KLoROMMap();
2489
-		/*else
2490
-		if (strncmp(ROMName, "ADD-ON BASE CASSETE", 19) == 0)
2491
-		{
2492
-			if (Multi.cartType == 4)
2493
-			{
2494
-				SRAMSize = Multi.sramSizeA;
2495
-				Map_SufamiTurboLoROMMap();
2496
-			}
2497
-			else
2498
-			{
2499
-				SRAMSize = 5;
2500
-				Map_SufamiTurboPseudoLoROMMap();
2501
-			}
2502
-		}*/
2503
-		else
2504
-			Map_LoROMMap();
2505
-    }
2506
-
2507
-	Checksum_Calculate();
2508
-
2509
-	/*bool isChecksumOK = (ROMChecksum + ROMComplementChecksum == 0xffff) &
2510
-						 (ROMChecksum == CalculatedChecksum);*/
2511
-
2512
-	//// Build more ROM information
2513
-
2514
-	// CRC32
2515
-	if (!Settings.BS || Settings.BSXItself) // Not BS Dump
2516
-		ROMCRC32 = caCRC32(ROM, CalculatedSize);
2517
-	else // Convert to correct format before scan
2518
-	{
2519
-		int offset = HiROM ? 0xffc0 : 0x7fc0;
2520
-		// Backup
2521
-		uint8_t BSMagic0 = ROM[offset + 22],
2522
-			  BSMagic1 = ROM[offset + 23];
2523
-		// uCONSRT standard
2524
-		ROM[offset + 22] = 0x42;
2525
-		ROM[offset + 23] = 0x00;
2526
-		// Calc
2527
-		ROMCRC32 = caCRC32(ROM, CalculatedSize);
2528
-		// Convert back
2529
-		ROM[offset + 22] = BSMagic0;
2530
-		ROM[offset + 23] = BSMagic1;
2531
-	}
2532
-
2533
-	// NTSC/PAL
2534
-	if (Settings.ForceNTSC)
2535
-		Settings.PAL = false;
2536
-	else
2537
-	if (Settings.ForcePAL)
2538
-		Settings.PAL = true;
2539
-	else
2540
-	if (!Settings.BS && (ROMRegion >= 2) && (ROMRegion <= 12))
2541
-		Settings.PAL = true;
2542
-	else
2543
-		Settings.PAL = false;
2544
-
2545
-	if (Settings.PAL)
2546
-	{
2547
-		Settings.FrameTime = Settings.FrameTimePAL;
2548
-		ROMFramesPerSecond = 50;
2549
-	}
2550
-	else
2551
-	{
2552
-		Settings.FrameTime = Settings.FrameTimeNTSC;
2553
-		ROMFramesPerSecond = 60;
2554
-	}
2555
-
2556
-	// truncate cart name
2557
-	ROMName[ROM_NAME_LEN - 1] = 0;
2558
-	if (strlen(ROMName))
2559
-	{
2560
-		char *p = ROMName + strlen(ROMName);
2561
-		if (p > ROMName + 21 && ROMName[20] == ' ')
2562
-			p = ROMName + 21;
2563
-		while (p > ROMName && *(p - 1) == ' ')
2564
-			p--;
2565
-		*p = 0;
2566
-	}
2567
-
2568
-	// SRAM size
2569
-	SRAMMask = SRAMSize ? ((1 << (SRAMSize + 3)) * 128) - 1 : 0;
2570
-
2571
-	// checksum
2572
-	/*if (!isChecksumOK || ((uint32_t) CalculatedSize > (uint32_t) (((1 << (ROMSize - 7)) * 128) * 1024)))
2573
-	{
2574
-		Settings.DisplayColor = BUILD_PIXEL(31, 31, 0);
2575
-		SET_UI_COLOR(255, 255, 0);
2576
-	}*/
2577
-
2578
-	/*if (Multi.cartType == 4)
2579
-	{
2580
-		Settings.DisplayColor = BUILD_PIXEL(0, 16, 31);
2581
-		SET_UI_COLOR(0, 128, 255);
2582
-	}*/
2583
-
2584
-	//// Initialize emulation
2585
-
2586
-	Timings.H_Max_Master = SNES_CYCLES_PER_SCANLINE;
2587
-	Timings.H_Max        = Timings.H_Max_Master;
2588
-	Timings.HBlankStart  = SNES_HBLANK_START_HC;
2589
-	Timings.HBlankEnd    = SNES_HBLANK_END_HC;
2590
-	Timings.HDMAInit     = SNES_HDMA_INIT_HC;
2591
-	Timings.HDMAStart    = SNES_HDMA_START_HC;
2592
-	Timings.RenderPos    = SNES_RENDER_START_HC;
2593
-	Timings.V_Max_Master = Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER;
2594
-	Timings.V_Max        = Timings.V_Max_Master;
2595
-	/* From byuu: The total delay time for both the initial (H)DMA sync (to the DMA clock),
2596
-	   and the end (H)DMA sync (back to the last CPU cycle's mcycle rate (6, 8, or 12)) always takes between 12-24 mcycles.
2597
-	   Possible delays: { 12, 14, 16, 18, 20, 22, 24 }
2598
-	   XXX: Snes9x can't emulate this timing :( so let's use the average value... */
2599
-	Timings.DMACPUSync   = 18;
2600
-	/* If the CPU is halted (i.e. for DMA) while /NMI goes low, the NMI will trigger
2601
-	   after the DMA completes (even if /NMI goes high again before the DMA
2602
-	   completes). In this case, there is a 24-30 cycle delay between the end of DMA
2603
-	   and the NMI handler, time enough for an instruction or two. */
2604
-	// Wild Guns, Mighty Morphin Power Rangers - The Fighting Edition
2605
-	Timings.NMIDMADelay  = 24;
2606
-	Timings.IRQPendCount = 0;
2607
-
2608
-	IPPU.TotalEmulatedFrames = 0;
2609
-
2610
-	//// Hack games
2611
-
2612
-	ApplyROMFixes();
2613
-
2614
-	//// Show ROM information
2615
-	//char displayName[ROM_NAME_LEN];
2616
-
2617
-	strcpy(RawROMName, ROMName);
2618
-	//sprintf(displayName, "%s", SafeANK(ROMName));
2619
-	sprintf(ROMName, "%s", Safe(ROMName));
2620
-	sprintf(ROMId, "%s", Safe(ROMId));
2621
-
2622
-	/*sprintf(String, "\"%s\" [%s] %s, %s, %s, %s, SRAM:%s, ID:%s, CRC32:%08X",
2623
-		displayName, isChecksumOK ? "checksum ok" : ((Multi.cartType == 4) ? "no checksum" : "bad checksum"),
2624
-		MapType(), Size(), KartContents(), Settings.PAL ? "PAL" : "NTSC", StaticRAMSize(), ROMId, ROMCRC32);*/
2625
-	//S9xMessage(S9X_INFO, S9X_ROM_INFO, String);
2626
-
2627
-	Settings.ForceLoROM = false;
2628
-	Settings.ForceHiROM = false;
2629
-	Settings.ForceHeader = false;
2630
-	Settings.ForceNoHeader = false;
2631
-	Settings.ForceInterleaved = false;
2632
-	Settings.ForceInterleaved2 = false;
2633
-	Settings.ForceInterleaveGD24 = false;
2634
-	Settings.ForceNotInterleaved = false;
2635
-	Settings.ForcePAL = false;
2636
-	Settings.ForceNTSC = false;
2637
-
2638
-	Settings.TakeScreenshot = false;
2639
-
2640
-	/*if (stopMovie)
2641
-		S9xMovieStop(true);*/
2642
-
2643
-	if (PostRomInitFunc)
2644
-		PostRomInitFunc();
2645
-
2646
-    //S9xVerifyControllers();
2647
-}
2648
-
2649
-// memory map
2650
-
2651
-uint32_t CMemory::map_mirror (uint32_t size, uint32_t pos)
2652
-{
2653
-	// from bsnes
2654
-	if (size == 0)
2655
-		return 0;
2656
-	if (pos < size)
2657
-		return pos;
2658
-
2659
-	uint32_t	mask = 1 << 31;
2660
-	while (!(pos & mask))
2661
-		mask >>= 1;
2662
-
2663
-	if (size <= (pos & mask))
2664
-		return map_mirror(size, pos - mask);
2665
-	else
2666
-		return mask + map_mirror(size - mask, pos - mask);
2667
-}
2668
-
2669
-void CMemory::map_lorom (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size)
2670
-{
2671
-	uint32_t	c, i, p, addr;
2672
-
2673
-	for (c = bank_s; c <= bank_e; c++)
2674
-	{
2675
-		for (i = addr_s; i <= addr_e; i += 0x1000)
2676
-		{
2677
-			p = (c << 4) | (i >> 12);
2678
-			addr = (c & 0x7f) * 0x8000;
2679
-			Map[p] = ROM + map_mirror(size, addr) - (i & 0x8000);
2680
-			BlockIsROM[p] = true;
2681
-			BlockIsRAM[p] = false;
2682
-		}
2683
-	}
2684
-}
2685
-
2686
-void CMemory::map_hirom (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size)
2687
-{
2688
-	uint32_t	c, i, p, addr;
2689
-
2690
-	for (c = bank_s; c <= bank_e; c++)
2691
-	{
2692
-		for (i = addr_s; i <= addr_e; i += 0x1000)
2693
-		{
2694
-			p = (c << 4) | (i >> 12);
2695
-			addr = c << 16;
2696
-			Map[p] = ROM + map_mirror(size, addr);
2697
-			BlockIsROM[p] = true;
2698
-			BlockIsRAM[p] = false;
2699
-		}
2700
-	}
2701
-}
2702
-
2703
-void CMemory::map_lorom_offset (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size, uint32_t offset)
2704
-{
2705
-	uint32_t	c, i, p, addr;
2706
-
2707
-	for (c = bank_s; c <= bank_e; c++)
2708
-	{
2709
-		for (i = addr_s; i <= addr_e; i += 0x1000)
2710
-		{
2711
-			p = (c << 4) | (i >> 12);
2712
-			addr = ((c - bank_s) & 0x7f) * 0x8000;
2713
-			Map[p] = ROM + offset + map_mirror(size, addr) - (i & 0x8000);
2714
-			BlockIsROM[p] = true;
2715
-			BlockIsRAM[p] = false;
2716
-		}
2717
-	}
2718
-}
2719
-
2720
-void CMemory::map_hirom_offset (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size, uint32_t offset)
2721
-{
2722
-	uint32_t	c, i, p, addr;
2723
-
2724
-	for (c = bank_s; c <= bank_e; c++)
2725
-	{
2726
-		for (i = addr_s; i <= addr_e; i += 0x1000)
2727
-		{
2728
-			p = (c << 4) | (i >> 12);
2729
-			addr = (c - bank_s) << 16;
2730
-			Map[p] = ROM + offset + map_mirror(size, addr);
2731
-			BlockIsROM[p] = true;
2732
-			BlockIsRAM[p] = false;
2733
-		}
2734
-	}
2735
-}
2736
-
2737
-void CMemory::map_space (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint8_t *data)
2738
-{
2739
-	uint32_t	c, i, p;
2740
-
2741
-	for (c = bank_s; c <= bank_e; c++)
2742
-	{
2743
-		for (i = addr_s; i <= addr_e; i += 0x1000)
2744
-		{
2745
-			p = (c << 4) | (i >> 12);
2746
-			Map[p] = data;
2747
-			BlockIsROM[p] = false;
2748
-			BlockIsRAM[p] = true;
2749
-		}
2750
-	}
2751
-}
2752
-
2753
-void CMemory::map_index (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, int index, int type)
2754
-{
2755
-	uint32_t	c, i, p;
2756
-	bool	isROM, isRAM;
2757
-
2758
-	isROM = ((type == MAP_TYPE_I_O) || (type == MAP_TYPE_RAM)) ? false : true;
2759
-	isRAM = ((type == MAP_TYPE_I_O) || (type == MAP_TYPE_ROM)) ? false : true;
2760
-
2761
-	for (c = bank_s; c <= bank_e; c++)
2762
-	{
2763
-		for (i = addr_s; i <= addr_e; i += 0x1000)
2764
-		{
2765
-			p = (c << 4) | (i >> 12);
2766
-			Map[p] = (uint8_t *) index;
2767
-			BlockIsROM[p] = isROM;
2768
-			BlockIsRAM[p] = isRAM;
2769
-		}
2770
-	}
2771
-}
2772
-
2773
-void CMemory::map_System()
2774
-{
2775
-	// will be overwritten
2776
-	map_space(0x00, 0x3f, 0x0000, 0x1fff, RAM);
2777
-	map_index(0x00, 0x3f, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O);
2778
-	map_index(0x00, 0x3f, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O);
2779
-	map_space(0x80, 0xbf, 0x0000, 0x1fff, RAM);
2780
-	map_index(0x80, 0xbf, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O);
2781
-	map_index(0x80, 0xbf, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O);
2782
-}
2783
-
2784
-void CMemory::map_WRAM()
2785
-{
2786
-	// will overwrite others
2787
-	map_space(0x7e, 0x7e, 0x0000, 0xffff, RAM);
2788
-	map_space(0x7f, 0x7f, 0x0000, 0xffff, RAM + 0x10000);
2789
-}
2790
-
2791
-void CMemory::map_LoROMSRAM()
2792
-{
2793
-	map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
2794
-	map_index(0xf0, 0xff, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
2795
-}
2796
-
2797
-void CMemory::map_HiROMSRAM()
2798
-{
2799
-	map_index(0x20, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
2800
-	map_index(0xa0, 0xbf, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
2801
-}
2802
-
2803
-/*void CMemory::map_DSP()
2804
-{
2805
-	switch (DSP0.maptype)
2806
-	{
2807
-		case M_DSP1_LOROM_S:
2808
-			map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
2809
-			map_index(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
2810
-			break;
2811
-
2812
-		case M_DSP1_LOROM_L:
2813
-			map_index(0x60, 0x6f, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
2814
-			map_index(0xe0, 0xef, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
2815
-			break;
2816
-
2817
-		case M_DSP1_HIROM:
2818
-			map_index(0x00, 0x1f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
2819
-			map_index(0x80, 0x9f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
2820
-			break;
2821
-
2822
-		case M_DSP2_LOROM:
2823
-			map_index(0x20, 0x3f, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O);
2824
-			map_index(0x20, 0x3f, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O);
2825
-			map_index(0xa0, 0xbf, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O);
2826
-			map_index(0xa0, 0xbf, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O);
2827
-			break;
2828
-
2829
-		case M_DSP3_LOROM:
2830
-			map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
2831
-			map_index(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
2832
-			break;
2833
-
2834
-		case M_DSP4_LOROM:
2835
-			map_index(0x30, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
2836
-			map_index(0xb0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
2837
-			break;
2838
-	}
2839
-}*/
2840
-
2841
-/*void CMemory::map_C4()
2842
-{
2843
-	map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_C4, MAP_TYPE_I_O);
2844
-	map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_C4, MAP_TYPE_I_O);
2845
-}*/
2846
-
2847
-/*void CMemory::map_OBC1()
2848
-{
2849
-	map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_OBC_RAM, MAP_TYPE_I_O);
2850
-	map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_OBC_RAM, MAP_TYPE_I_O);
2851
-}*/
2852
-
2853
-/*void CMemory::map_SetaRISC()
2854
-{
2855
-	map_index(0x00, 0x3f, 0x3000, 0x3fff, MAP_SETA_RISC, MAP_TYPE_I_O);
2856
-	map_index(0x80, 0xbf, 0x3000, 0x3fff, MAP_SETA_RISC, MAP_TYPE_I_O);
2857
-}*/
2858
-
2859
-/*void CMemory::map_SetaDSP()
2860
-{
2861
-	// where does the SETA chip access, anyway?
2862
-	// please confirm this?
2863
-	map_index(0x68, 0x6f, 0x0000, 0x7fff, MAP_SETA_DSP, MAP_TYPE_RAM);
2864
-	// and this!
2865
-	map_index(0x60, 0x67, 0x0000, 0x3fff, MAP_SETA_DSP, MAP_TYPE_I_O);
2866
-
2867
-	// ST-0010:
2868
-	// map_index(0x68, 0x6f, 0x0000, 0x0fff, MAP_SETA_DSP, ?);
2869
-}*/
2870
-
2871
-void CMemory::map_WriteProtectROM()
2872
-{
2873
-	memmove((void *) WriteMap, (void *) Map, sizeof(Map));
2874
-
2875
-	for (int c = 0; c < 0x1000; c++)
2876
-	{
2877
-		if (BlockIsROM[c])
2878
-			WriteMap[c] = (uint8_t *) MAP_NONE;
2879
-	}
2880
-}
2881
-
2882
-void CMemory::Map_Initialize()
2883
-{
2884
-	for (int c = 0; c < 0x1000; c++)
2885
-	{
2886
-		Map[c]      = (uint8_t *) MAP_NONE;
2887
-		WriteMap[c] = (uint8_t *) MAP_NONE;
2888
-		BlockIsROM[c] = false;
2889
-		BlockIsRAM[c] = false;
2890
-	}
2891
-}
2892
-
2893
-void CMemory::Map_LoROMMap()
2894
-{
2895
-	printf("Map_LoROMMap\n");
2896
-	map_System();
2897
-
2898
-	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
2899
-	map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize);
2900
-	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
2901
-	map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
2902
-
2903
-	/*if (Settings.DSP)
2904
-		map_DSP();
2905
-	else
2906
-	if (Settings.C4)
2907
-		map_C4();
2908
-	else
2909
-	if (Settings.OBC1)
2910
-		map_OBC1();
2911
-	else
2912
-	if (Settings.SETA == ST_018)
2913
-		map_SetaRISC();*/
2914
-
2915
-    map_LoROMSRAM();
2916
-	map_WRAM();
2917
-
2918
-	map_WriteProtectROM();
2919
-}
2920
-
2921
-void CMemory::Map_NoMAD1LoROMMap()
2922
-{
2923
-	printf("Map_NoMAD1LoROMMap\n");
2924
-	map_System();
2925
-
2926
-	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
2927
-	map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize);
2928
-	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
2929
-	map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
2930
-
2931
-	map_index(0x70, 0x7f, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
2932
-	map_index(0xf0, 0xff, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
2933
-
2934
-	map_WRAM();
2935
-
2936
-	map_WriteProtectROM();
2937
-}
2938
-
2939
-void CMemory::Map_JumboLoROMMap()
2940
-{
2941
-	// XXX: Which game uses this?
2942
-	printf("Map_JumboLoROMMap\n");
2943
-	map_System();
2944
-
2945
-	map_lorom_offset(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize - 0x400000, 0x400000);
2946
-	map_lorom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize - 0x400000, 0x400000);
2947
-	map_lorom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0);
2948
-	map_lorom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0x200000);
2949
-
2950
-	map_LoROMSRAM();
2951
-	map_WRAM();
2952
-
2953
-	map_WriteProtectROM();
2954
-}
2955
-
2956
-void CMemory::Map_ROM24MBSLoROMMap()
2957
-{
2958
-	// PCB: BSC-1A5M-01, BSC-1A7M-10
2959
-	printf("Map_ROM24MBSLoROMMap\n");
2960
-	map_System();
2961
-
2962
-	map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x100000, 0);
2963
-	map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000);
2964
-	map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x100000, 0x200000);
2965
-	map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000);
2966
-
2967
-	map_LoROMSRAM();
2968
-	map_WRAM();
2969
-
2970
-	map_WriteProtectROM();
2971
-}
2972
-
2973
-void CMemory::Map_SRAM512KLoROMMap()
2974
-{
2975
-	printf("Map_SRAM512KLoROMMap\n");
2976
-	map_System();
2977
-
2978
-	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
2979
-	map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize);
2980
-	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
2981
-	map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
2982
-
2983
-	map_space(0x70, 0x70, 0x0000, 0xffff, SRAM);
2984
-	map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x8000);
2985
-	map_space(0x72, 0x72, 0x0000, 0xffff, SRAM + 0x10000);
2986
-	map_space(0x73, 0x73, 0x0000, 0xffff, SRAM + 0x18000);
2987
-
2988
-	map_WRAM();
2989
-
2990
-	map_WriteProtectROM();
2991
-}
2992
-
2993
-/*void CMemory::Map_SufamiTurboLoROMMap()
2994
-{
2995
-	printf("Map_SufamiTurboLoROMMap\n");
2996
-	map_System();
2997
-
2998
-	map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0);
2999
-	map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
3000
-	map_lorom_offset(0x40, 0x5f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
3001
-	map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x40000, 0);
3002
-	map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
3003
-	map_lorom_offset(0xc0, 0xdf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
3004
-
3005
-	if (Multi.sramSizeA)
3006
-	{
3007
-		map_index(0x60, 0x63, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
3008
-		map_index(0xe0, 0xe3, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
3009
-	}
3010
-
3011
-	if (Multi.sramSizeB)
3012
-	{
3013
-		map_index(0x70, 0x73, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM);
3014
-		map_index(0xf0, 0xf3, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM);
3015
-	}
3016
-
3017
-	map_WRAM();
3018
-
3019
-	map_WriteProtectROM();
3020
-}*/
3021
-
3022
-/*void CMemory::Map_SufamiTurboPseudoLoROMMap()
3023
-{
3024
-	// for combined images
3025
-	printf("Map_SufamiTurboPseudoLoROMMap\n");
3026
-	map_System();
3027
-
3028
-	map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0);
3029
-	map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000);
3030
-	map_lorom_offset(0x40, 0x5f, 0x8000, 0xffff, 0x100000, 0x200000);
3031
-	map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x40000, 0);
3032
-	map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000);
3033
-	map_lorom_offset(0xc0, 0xdf, 0x8000, 0xffff, 0x100000, 0x200000);
3034
-
3035
-	// I don't care :P
3036
-	map_space(0x60, 0x63, 0x8000, 0xffff, SRAM - 0x8000);
3037
-	map_space(0xe0, 0xe3, 0x8000, 0xffff, SRAM - 0x8000);
3038
-	map_space(0x70, 0x73, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000);
3039
-	map_space(0xf0, 0xf3, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000);
3040
-
3041
-	map_WRAM();
3042
-
3043
-	map_WriteProtectROM();
3044
-}*/
3045
-
3046
-/*void CMemory::Map_SuperFXLoROMMap()
3047
-{
3048
-	printf("Map_SuperFXLoROMMap\n");
3049
-	map_System();
3050
-
3051
-	// Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K
3052
-	// block is repeated twice in each 64K block.
3053
-	for (int c = 0; c < 64; c++)
3054
-	{
3055
-		memmove(&ROM[0x200000 + c * 0x10000], &ROM[c * 0x8000], 0x8000);
3056
-		memmove(&ROM[0x208000 + c * 0x10000], &ROM[c * 0x8000], 0x8000);
3057
-	}
3058
-
3059
-	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
3060
-	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
3061
-
3062
-	map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize, 0);
3063
-	map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0);
3064
-
3065
-	map_space(0x00, 0x3f, 0x6000, 0x7fff, SRAM - 0x6000);
3066
-	map_space(0x80, 0xbf, 0x6000, 0x7fff, SRAM - 0x6000);
3067
-	map_space(0x70, 0x70, 0x0000, 0xffff, SRAM);
3068
-	map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x10000);
3069
-
3070
-	map_WRAM();
3071
-
3072
-	map_WriteProtectROM();
3073
-}*/
3074
-
3075
-/*void CMemory::Map_SetaDSPLoROMMap()
3076
-{
3077
-	printf("Map_SetaDSPLoROMMap\n");
3078
-	map_System();
3079
-
3080
-	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
3081
-	map_lorom(0x40, 0x7f, 0x8000, 0xffff, CalculatedSize);
3082
-	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
3083
-	map_lorom(0xc0, 0xff, 0x8000, 0xffff, CalculatedSize);
3084
-
3085
-	map_SetaDSP();
3086
-
3087
-    map_LoROMSRAM();
3088
-	map_WRAM();
3089
-
3090
-	map_WriteProtectROM();
3091
-}*/
3092
-
3093
-void CMemory::Map_SDD1LoROMMap()
3094
-{
3095
-	printf("Map_SDD1LoROMMap\n");
3096
-	map_System();
3097
-
3098
-	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
3099
-	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
3100
-
3101
-	map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize, 0);
3102
-	map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0); // will be overwritten dynamically
3103
-
3104
-	map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
3105
-
3106
-	map_WRAM();
3107
-
3108
-	map_WriteProtectROM();
3109
-}
3110
-
3111
-/*void CMemory::Map_SA1LoROMMap()
3112
-{
3113
-	printf("Map_SA1LoROMMap\n");
3114
-	map_System();
3115
-
3116
-	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
3117
-	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
3118
-
3119
-	map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0);
3120
-
3121
-	map_space(0x00, 0x3f, 0x3000, 0x3fff, FillRAM);
3122
-	map_space(0x80, 0xbf, 0x3000, 0x3fff, FillRAM);
3123
-	map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O);
3124
-	map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O);
3125
-
3126
-	for (int c = 0x40; c < 0x80; c++)
3127
-		map_space(c, c, 0x0000, 0xffff, SRAM + (c & 1) * 0x10000);
3128
-
3129
-	map_WRAM();
3130
-
3131
-	map_WriteProtectROM();
3132
-
3133
-	// Now copy the map and correct it for the SA1 CPU.
3134
-	memmove((void *) SA1.Map, (void *) Map, sizeof(Map));
3135
-	memmove((void *) SA1.WriteMap, (void *) WriteMap, sizeof(WriteMap));
3136
-
3137
-	// SA-1 Banks 00->3f and 80->bf
3138
-	for (int c = 0x000; c < 0x400; c += 0x10)
3139
-	{
3140
-		SA1.Map[c + 0] = SA1.Map[c + 0x800] = FillRAM + 0x3000;
3141
-		SA1.Map[c + 1] = SA1.Map[c + 0x801] = (uint8_t *) MAP_NONE;
3142
-		SA1.WriteMap[c + 0] = SA1.WriteMap[c + 0x800] = FillRAM + 0x3000;
3143
-		SA1.WriteMap[c + 1] = SA1.WriteMap[c + 0x801] = (uint8_t *) MAP_NONE;
3144
-	}
3145
-
3146
-	// SA-1 Banks 60->6f
3147
-	for (int c = 0x600; c < 0x700; c++)
3148
-		SA1.Map[c] = SA1.WriteMap[c] = (uint8_t *) MAP_BWRAM_BITMAP;
3149
-
3150
-	BWRAM = SRAM;
3151
-}*/
3152
-
3153
-void CMemory::Map_HiROMMap()
3154
-{
3155
-	printf("Map_HiROMMap\n");
3156
-	map_System();
3157
-
3158
-	map_hirom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
3159
-	map_hirom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize);
3160
-	map_hirom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
3161
-	map_hirom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
3162
-
3163
-	/*if (Settings.DSP)
3164
-		map_DSP();*/
3165
-
3166
-	map_HiROMSRAM();
3167
-	map_WRAM();
3168
-
3169
-	map_WriteProtectROM();
3170
-}
3171
-
3172
-void CMemory::Map_ExtendedHiROMMap()
3173
-{
3174
-	printf("Map_ExtendedHiROMMap\n");
3175
-	map_System();
3176
-
3177
-	map_hirom_offset(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize - 0x400000, 0x400000);
3178
-	map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize - 0x400000, 0x400000);
3179
-	map_hirom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0);
3180
-	map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0);
3181
-
3182
-	map_HiROMSRAM();
3183
-	map_WRAM();
3184
-
3185
-	map_WriteProtectROM();
3186
-}
3187
-
3188
-/*void CMemory::Map_SameGameHiROMMap()
3189
-{
3190
-	printf("Map_SameGameHiROMMap\n");
3191
-	map_System();
3192
-
3193
-	map_hirom_offset(0x00, 0x1f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
3194
-	map_hirom_offset(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
3195
-	map_hirom_offset(0x40, 0x5f, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
3196
-	map_hirom_offset(0x60, 0x7f, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
3197
-	map_hirom_offset(0x80, 0x9f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
3198
-	map_hirom_offset(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
3199
-	map_hirom_offset(0xc0, 0xdf, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
3200
-	map_hirom_offset(0xe0, 0xff, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
3201
-
3202
-	map_HiROMSRAM();
3203
-	map_WRAM();
3204
-
3205
-	map_WriteProtectROM();
3206
-}*/
3207
-
3208
-/*void CMemory::Map_SPC7110HiROMMap()
3209
-{
3210
-	printf("Map_SPC7110HiROMMap\n");
3211
-	map_System();
3212
-
3213
-	map_index(0x00, 0x00, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
3214
-	map_hirom(0x00, 0x0f, 0x8000, 0xffff, CalculatedSize);
3215
-	map_index(0x30, 0x30, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
3216
-	map_index(0x50, 0x50, 0x0000, 0xffff, MAP_SPC7110_DRAM, MAP_TYPE_ROM);
3217
-	map_hirom(0x80, 0x8f, 0x8000, 0xffff, CalculatedSize);
3218
-	map_hirom_offset(0xc0, 0xcf, 0x0000, 0xffff, CalculatedSize, 0);
3219
-	map_index(0xd0, 0xff, 0x0000, 0xffff, MAP_SPC7110_ROM,  MAP_TYPE_ROM);
3220
-
3221
-	map_WRAM();
3222
-
3223
-	map_WriteProtectROM();
3224
-}*/
3225
-
3226
-// checksum
3227
-
3228
-uint16_t CMemory::checksum_calc_sum (uint8_t *data, uint32_t length)
3229
-{
3230
-	uint16_t	sum = 0;
3231
-
3232
-	for (uint32_t i = 0; i < length; i++)
3233
-		sum += data[i];
3234
-
3235
-	return sum;
3236
-}
3237
-
3238
-uint16_t CMemory::checksum_mirror_sum (uint8_t *start, uint32_t &length, uint32_t mask)
3239
-{
3240
-	// from NSRT
3241
-	while (!(length & mask))
3242
-		mask >>= 1;
3243
-
3244
-	uint16_t	part1 = checksum_calc_sum(start, mask);
3245
-	uint16_t	part2 = 0;
3246
-
3247
-	uint32_t	next_length = length - mask;
3248
-	if (next_length)
3249
-	{
3250
-		part2 = checksum_mirror_sum(start + mask, next_length, mask >> 1);
3251
-
3252
-		while (next_length < mask)
3253
-		{
3254
-			next_length += next_length;
3255
-			part2 += part2;
3256
-		}
3257
-
3258
-		length = mask + mask;
3259
-	}
3260
-
3261
-	return part1 + part2;
3262
-}
3263
-
3264
-void CMemory::Checksum_Calculate()
3265
-{
3266
-	// from NSRT
3267
-	uint16_t	sum = 0;
3268
-
3269
-	if (Settings.BS && !Settings.BSXItself)
3270
-		sum = checksum_calc_sum(ROM, CalculatedSize) - checksum_calc_sum(ROM + (HiROM ? 0xffb0 : 0x7fb0), 48);
3271
-	else
3272
-	if (Settings.SPC7110)
3273
-	{
3274
-		sum = checksum_calc_sum(ROM, CalculatedSize);
3275
-		if (CalculatedSize == 0x300000)
3276
-			sum += sum;
3277
-	}
3278
-	else
3279
-	{
3280
-		if (CalculatedSize & 0x7fff)
3281
-			sum = checksum_calc_sum(ROM, CalculatedSize);
3282
-		else
3283
-		{
3284
-			uint32_t	length = CalculatedSize;
3285
-			sum = checksum_mirror_sum(ROM, length);
3286
-		}
3287
-	}
3288
-
3289
-	CalculatedChecksum = sum;
3290
-}
3291
-
3292
-// information
3293
-
3294
-/*const char * CMemory::MapType()
3295
-{
3296
-	return HiROM ? ((ExtendedFormat != NOPE) ? "ExHiROM": "HiROM") : "LoROM";
3297
-}*/
3298
-
3299
-/*const char * CMemory::StaticRAMSize()
3300
-{
3301
-	static char	str[20];
3302
-
3303
-	if (SRAMSize > 16)
3304
-		strcpy(str, "Corrupt");
3305
-	else
3306
-		sprintf(str, "%dKbits", 8 * (SRAMMask + 1) / 1024);
3307
-
3308
-	return str;
3309
-}*/
3310
-
3311
-/*const char * CMemory::Size()
3312
-{
3313
-	static char	str[20];
3314
-
3315
-	if (Multi.cartType == 4)
3316
-		strcpy(str, "N/A");
3317
-	else
3318
-	if (ROMSize < 7 || ROMSize - 7 > 23)
3319
-		strcpy(str, "Corrupt");
3320
-	else
3321
-		sprintf(str, "%dMbits", 1 << (ROMSize - 7));
3322
-
3323
-	return str;
3324
-}*/
3325
-
3326
-/*const char * CMemory::Revision()
3327
-{
3328
-	static char	str[20];
3329
-
3330
-	sprintf(str, "1.%d", HiROM ? ((ExtendedFormat != NOPE) ? ROM[0x40ffdb] : ROM[0xffdb]) : ROM[0x7fdb]);
3331
-
3332
-	return str;
3333
-}*/
3334
-
3335
-/*const char * CMemory::KartContents()
3336
-{
3337
-	static char			str[64];
3338
-	static const char	*contents[3] = { "ROM", "ROM+RAM", "ROM+RAM+BAT" };
3339
-
3340
-	char	chip[16];
3341
-
3342
-	if (ROMType == 0 && !Settings.BS)
3343
-		return "ROM";
3344
-
3345
-	if (Settings.BS)
3346
-		strcpy(chip, "+BS");
3347
-	else
3348
-	if (Settings.SuperFX)
3349
-		strcpy(chip, "+Super FX");
3350
-	else
3351
-	if (Settings.SDD1)
3352
-		strcpy(chip, "+S-DD1");
3353
-	else
3354
-	if (Settings.OBC1)
3355
-		strcpy(chip, "+OBC1");
3356
-	else
3357
-	if (Settings.SA1)
3358
-		strcpy(chip, "+SA-1");
3359
-	else
3360
-	if (Settings.SPC7110RTC)
3361
-		strcpy(chip, "+SPC7110+RTC");
3362
-	else
3363
-	if (Settings.SPC7110)
3364
-		strcpy(chip, "+SPC7110");
3365
-	else
3366
-	if (Settings.SRTC)
3367
-		strcpy(chip, "+S-RTC");
3368
-	else
3369
-	if (Settings.C4)
3370
-		strcpy(chip, "+C4");
3371
-	else
3372
-	if (Settings.SETA == ST_010)
3373
-		strcpy(chip, "+ST-010");
3374
-	else
3375
-	if (Settings.SETA == ST_011)
3376
-		strcpy(chip, "+ST-011");
3377
-	else
3378
-	if (Settings.SETA == ST_018)
3379
-		strcpy(chip, "+ST-018");
3380
-	else
3381
-	if (Settings.DSP)
3382
-		sprintf(chip, "+DSP-%d", Settings.DSP);
3383
-	else
3384
-		strcpy(chip, "");
3385
-
3386
-	sprintf(str, "%s%s", contents[(ROMType & 0xf) % 3], chip);
3387
-
3388
-	return str;
3389
-}*/
3390
-
3391
-/*const char * CMemory::Country()
3392
-{
3393
-	switch (ROMRegion)
3394
-	{
3395
-		case 0:		return "Japan";
3396
-		case 1:		return "USA and Canada";
3397
-		case 2:		return "Oceania, Europe and Asia";
3398
-		case 3:		return "Sweden";
3399
-		case 4:		return "Finland";
3400
-		case 5:		return "Denmark";
3401
-		case 6:		return "France";
3402
-		case 7:		return "Holland";
3403
-		case 8:		return "Spain";
3404
-		case 9:		return "Germany, Austria and Switzerland";
3405
-		case 10:	return "Italy";
3406
-		case 11:	return "Hong Kong and China";
3407
-		case 12:	return "Indonesia";
3408
-		case 13:	return "South Korea";
3409
-		default:	return "Unknown";
3410
-	}
3411
-}*/
3412
-
3413
-/*const char * CMemory::PublishingCompany()
3414
-{
3415
-	if (CompanyId >= (int) (sizeof(nintendo_licensees) / sizeof(nintendo_licensees[0])) || CompanyId < 0)
3416
-		return "Unknown";
3417
-
3418
-	if (nintendo_licensees[CompanyId] == NULL)
3419
-		return "Unknown";
3420
-
3421
-	return nintendo_licensees[CompanyId];
3422
-}*/
3423
-
3424
-/*void CMemory::MakeRomInfoText (char *romtext)
3425
-{
3426
-	char	temp[256];
3427
-
3428
-	romtext[0] = 0;
3429
-
3430
-	sprintf(temp,   "            Cart Name: %s", ROMName);
3431
-	strcat(romtext, temp);
3432
-	sprintf(temp, "\n            Game Code: %s", ROMId);
3433
-	strcat(romtext, temp);
3434
-	sprintf(temp, "\n             Contents: %s", KartContents());
3435
-	strcat(romtext, temp);
3436
-	sprintf(temp, "\n                  Map: %s", MapType());
3437
-	strcat(romtext, temp);
3438
-	sprintf(temp, "\n                Speed: 0x%02X (%s)", ROMSpeed, (ROMSpeed & 0x10) ? "FastROM" : "SlowROM");
3439
-	strcat(romtext, temp);
3440
-	sprintf(temp, "\n                 Type: 0x%02X", ROMType);
3441
-	strcat(romtext, temp);
3442
-	sprintf(temp, "\n    Size (calculated): %dMbits", CalculatedSize / 0x20000);
3443
-	strcat(romtext, temp);
3444
-	sprintf(temp, "\n        Size (header): %s", Size());
3445
-	strcat(romtext, temp);
3446
-	sprintf(temp, "\n            SRAM size: %s", StaticRAMSize());
3447
-	strcat(romtext, temp);
3448
-	sprintf(temp, "\nChecksum (calculated): 0x%04X", CalculatedChecksum);
3449
-	strcat(romtext, temp);
3450
-	sprintf(temp, "\n    Checksum (header): 0x%04X", ROMChecksum);
3451
-	strcat(romtext, temp);
3452
-	sprintf(temp, "\n  Complement (header): 0x%04X", ROMComplementChecksum);
3453
-	strcat(romtext, temp);
3454
-	sprintf(temp, "\n         Video Output: %s", (ROMRegion > 12 || ROMRegion < 2) ? "NTSC 60Hz" : "PAL 50Hz");
3455
-	strcat(romtext, temp);
3456
-	sprintf(temp, "\n             Revision: %s", Revision());
3457
-	strcat(romtext, temp);
3458
-	sprintf(temp, "\n             Licensee: %s", PublishingCompany());
3459
-	strcat(romtext, temp);
3460
-	sprintf(temp, "\n               Region: %s", Country());
3461
-	strcat(romtext, temp);
3462
-	sprintf(temp, "\n                CRC32: 0x%08X", ROMCRC32);
3463
-	strcat(romtext, temp);
3464
-}*/
3465
-
3466
-// hack
3467
-
3468
-bool CMemory::match_na (const char *str)
3469
-{
3470
-	return strcmp(ROMName, str) == 0;
3471
-}
3472
-
3473
-bool CMemory::match_nn (const char *str)
3474
-{
3475
-	return strncmp(ROMName, str, strlen(str)) == 0;
3476
-}
3477
-
3478
-/*bool CMemory::match_nc (const char *str)
3479
-{
3480
-	return strncasecmp(ROMName, str, strlen(str)) == 0;
3481
-}*/
3482
-
3483
-bool CMemory::match_id (const char *str)
3484
-{
3485
-	return strncmp(ROMId, str, strlen(str)) == 0;
3486
-}
3487
-
3488
-void CMemory::ApplyROMFixes()
3489
-{
3490
-	Settings.BlockInvalidVRAMAccess = Settings.BlockInvalidVRAMAccessMaster;
3491
-
3492
-	//// Warnings
3493
-
3494
-	// Reject strange hacked games
3495
-	/*if ((ROMCRC32 == 0x6810aa95) ||
3496
-		(ROMCRC32 == 0x340f23e5) ||
3497
-		(ROMCRC32 == 0x77fd806a) ||
3498
-		(match_nn("HIGHWAY BATTLE 2")) ||
3499
-		(match_na("FX SKIING NINTENDO 96") && (ROM[0x7fda] == 0)) ||
3500
-		(match_nn("HONKAKUHA IGO GOSEI")   && (ROM[0xffd5] != 0x31)))
3501
-	{
3502
-		Settings.DisplayColor = BUILD_PIXEL(31, 0, 0);
3503
-		SET_UI_COLOR(255, 0, 0);
3504
-	}*/
3505
-
3506
-	//// APU timing hacks :(
3507
-
3508
-	Timings.APUSpeedup = 0;
3509
-	Timings.APUAllowTimeOverflow = false;
3510
-
3511
-	if (!Settings.DisableGameSpecificHacks)
3512
-	{
3513
-		if (match_id("AVCJ"))                                      // Rendering Ranger R2
3514
-			Timings.APUSpeedup = 4;
3515
-
3516
-		if (match_na("GAIA GENSOUKI 1 JPN")                     || // Gaia Gensouki
3517
-			match_id("JG  ")                                    || // Illusion of Gaia
3518
-			match_id("CQ  ")                                    || // Stunt Race FX
3519
-			match_na("SOULBLADER - 1")                          || // Soul Blader
3520
-			match_na("SOULBLAZER - 1 USA")                      || // Soul Blazer
3521
-			match_na("SLAP STICK 1 JPN")                        || // Slap Stick
3522
-			match_id("E9 ")                                     || // Robotrek
3523
-			match_nn("ACTRAISER")                               || // Actraiser
3524
-			match_nn("ActRaiser-2")                             || // Actraiser 2
3525
-			match_id("AQT")                                     || // Tenchi Souzou, Terranigma
3526
-			match_id("ATV")                                     || // Tales of Phantasia
3527
-			match_id("ARF")                                     || // Star Ocean
3528
-			match_id("APR")                                     || // Zen-Nippon Pro Wrestling 2 - 3-4 Budoukan
3529
-			match_id("A4B")                                     || // Super Bomberman 4
3530
-			match_id("Y7 ")                                     || // U.F.O. Kamen Yakisoban - Present Ban
3531
-			match_id("Y9 ")                                     || // U.F.O. Kamen Yakisoban - Shihan Ban
3532
-			match_id("APB")                                     || // Super Bomberman - Panic Bomber W
3533
-			match_na("DARK KINGDOM")                            || // Dark Kingdom
3534
-			match_na("ZAN3 SFC")                                || // Zan III Spirits
3535
-			match_na("HIOUDEN")                                 || // Hiouden - Mamono-tachi Tono Chikai
3536
-			match_na("\xC3\xDD\xBC\xC9\xB3\xC0")                || // Tenshi no Uta
3537
-			match_na("FORTUNE QUEST")                           || // Fortune Quest - Dice wo Korogase
3538
-			match_na("FISHING TO BASSING")                      || // Shimono Masaki no Fishing To Bassing
3539
-			match_na("OHMONO BLACKBASS")                        || // Oomono Black Bass Fishing - Jinzouko Hen
3540
-			match_na("MASTERS")                                 || // Harukanaru Augusta 2 - Masters
3541
-			match_na("SFC \xB6\xD2\xDD\xD7\xB2\xC0\xDE\xB0")    || // Kamen Rider
3542
-			match_na("ZENKI TENCHIMEIDOU")					    || // Kishin Douji Zenki - Tenchi Meidou
3543
-			match_nn("TokyoDome '95Battle 7")                   || // Shin Nippon Pro Wrestling Kounin '95 - Tokyo Dome Battle 7
3544
-			match_nn("SWORD WORLD SFC")                         || // Sword World SFC/2
3545
-			match_nn("LETs PACHINKO(")                          || // BS Lets Pachinko Nante Gindama 1/2/3/4
3546
-			match_nn("THE FISHING MASTER")                      || // Mark Davis The Fishing Master
3547
-			match_nn("Parlor")                                  || // Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5
3548
-			match_na("HEIWA Parlor!Mini8")                      || // Parlor mini 8
3549
-			match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!"))   // SANKYO Fever! Fever!
3550
-			Timings.APUSpeedup = 1;
3551
-
3552
-		if (match_na ("EARTHWORM JIM 2")						|| // Earthworm Jim 2
3553
-			match_na ("NBA Hangtime")							|| // NBA Hang Time
3554
-			match_na ("MSPACMAN")								|| // Ms Pacman
3555
-			match_na ("THE MASK")								|| // The Mask
3556
-			match_na ("PRIMAL RAGE")							|| // Primal Rage
3557
-			match_na ("DOOM TROOPERS"))							   // Doom Troopers
3558
-			Timings.APUAllowTimeOverflow = true;
3559
-	}
3560
-
3561
-	S9xAPUTimingSetSpeedup(Timings.APUSpeedup);
3562
-	S9xAPUAllowTimeOverflow(Timings.APUAllowTimeOverflow);
3563
-
3564
-	//// Other timing hacks :(
3565
-
3566
-	Timings.HDMAStart   = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100;
3567
-	Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC;
3568
-	Timings.IRQTriggerCycles = 10;
3569
-
3570
-	if (!Settings.DisableGameSpecificHacks)
3571
-	{
3572
-		// The delay to sync CPU and DMA which Snes9x cannot emulate.
3573
-		// Some games need really severe delay timing...
3574
-		if (match_na("BATTLE GRANDPRIX")) // Battle Grandprix
3575
-		{
3576
-			Timings.DMACPUSync = 20;
3577
-			printf("DMA sync: %d\n", Timings.DMACPUSync);
3578
-		}
3579
-	}
3580
-
3581
-	if (!Settings.DisableGameSpecificHacks)
3582
-	{
3583
-		// An infinite loop reads $4212 and waits V-blank end, whereas VIRQ is set V=0.
3584
-		// If Snes9x succeeds to escape from the loop before jumping into the IRQ handler, the game goes further.
3585
-		// If Snes9x jumps into the IRQ handler before escaping from the loop,
3586
-		// Snes9x cannot escape from the loop permanently because the RTI is in the next V-blank.
3587
-		if (match_na("Aero the AcroBat 2"))
3588
-		{
3589
-			Timings.IRQPendCount = 2;
3590
-			printf("IRQ count hack: %d\n", Timings.IRQPendCount);
3591
-		}
3592
-	}
3593
-
3594
-	if (!Settings.DisableGameSpecificHacks)
3595
-	{
3596
-		// XXX: What's happening?
3597
-		if (match_na("X-MEN")) // Spider-Man and the X-Men
3598
-		{
3599
-			Settings.BlockInvalidVRAMAccess = false;
3600
-			printf("Invalid VRAM access hack\n");
3601
-		}
3602
-	}
3603
-
3604
-	//// SRAM initial value
3605
-
3606
-	if (!Settings.DisableGameSpecificHacks)
3607
-	{
3608
-		if (match_na("HITOMI3"))
3609
-		{
3610
-			SRAMSize = 1;
3611
-			SRAMMask = ((1 << (SRAMSize + 3)) * 128) - 1;
3612
-		}
3613
-
3614
-		// SRAM value fixes
3615
-		if (match_na("SUPER DRIFT OUT")      || // Super Drift Out
3616
-			match_na("SATAN IS OUR FATHER!") ||
3617
-			match_na("goemon 4"))               // Ganbare Goemon Kirakira Douchuu
3618
-			SNESGameFixes.SRAMInitialValue = 0x00;
3619
-
3620
-		// Additional game fixes by sanmaiwashi ...
3621
-		// XXX: unnecessary?
3622
-		if (match_na("SFX \xC5\xB2\xC4\xB6\xDE\xDD\xC0\xDE\xD1\xD3\xC9\xB6\xDE\xC0\xD8 1")) // SD Gundam Gaiden - Knight Gundam Monogatari
3623
-			SNESGameFixes.SRAMInitialValue = 0x6b;
3624
-
3625
-		// others: BS and ST-01x games are 0x00.
3626
-	}
3627
-
3628
-	//// OAM hacks :(
3629
-
3630
-	if (!Settings.DisableGameSpecificHacks)
3631
-	{
3632
-		// OAM hacks because we don't fully understand the behavior of the SNES.
3633
-		// Totally wacky display in 2P mode...
3634
-		// seems to need a disproven behavior, so we're definitely overlooking some other bug?
3635
-		if (match_nn("UNIRACERS")) // Uniracers
793
+void CMemory::map_hirom_offset(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size, uint32_t offset)
794
+{
795
+	for (uint32_t c = bank_s; c <= bank_e; ++c)
796
+		for (uint32_t i = addr_s; i <= addr_e; i += 0x1000)
3636 797
 		{
3637
-			SNESGameFixes.Uniracers = true;
3638
-			printf("Applied Uniracers hack.\n");
798
+			uint32_t p = (c << 4) | (i >> 12);
799
+			uint32_t addr = (c - bank_s) << 16;
800
+			this->Map[p] = &this->ROM[offset + this->map_mirror(size, addr)];
801
+			this->BlockIsROM[p] = true;
802
+			this->BlockIsRAM[p] = false;
3639 803
 		}
3640
-	}
3641 804
 }
3642 805
 
3643
-// UPS % IPS
3644
-
3645
-/*static uint32_t ReadUPSPointer (const uint8_t *data, unsigned &addr, unsigned size)
806
+void CMemory::map_space(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint8_t *data)
3646 807
 {
3647
-	uint32_t offset = 0, shift = 1;
3648
-	while(addr < size) {
3649
-		uint8_t x = data[addr++];
3650
-		offset += (x & 0x7f) * shift;
3651
-		if(x & 0x80) break;
3652
-		shift <<= 7;
3653
-		offset += shift;
3654
-	}
3655
-	return offset;
808
+	for (uint32_t c = bank_s; c <= bank_e; ++c)
809
+		for (uint32_t i = addr_s; i <= addr_e; i += 0x1000)
810
+		{
811
+			uint32_t p = (c << 4) | (i >> 12);
812
+			this->Map[p] = data;
813
+			this->BlockIsROM[p] = false;
814
+			this->BlockIsRAM[p] = true;
815
+		}
3656 816
 }
3657 817
 
3658
-//NOTE: UPS patches are *never* created against a headered ROM!
3659
-//this is per the UPS file specification. however, do note that it is
3660
-//technically possible for a non-compliant patcher to ignore this requirement.
3661
-//therefore, it is *imperative* that no emulator support such patches.
3662
-//thusly, we ignore the "long offset" parameter below. failure to do so would
3663
-//completely invalidate the purpose of UPS; which is to avoid header vs
3664
-//no-header patching errors that result in IPS patches having a 50/50 chance of
3665
-//being applied correctly.
3666
-
3667
-static bool ReadUPSPatch (Reader *r, long, int32_t &rom_size)
818
+void CMemory::map_index(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, int index, int type)
3668 819
 {
3669
-	//Reader lacks size() and rewind(), so we need to read in the file to get its size
3670
-	uint8_t *data = new uint8_t[8 * 1024 * 1024];  //allocate a lot of memory, better safe than sorry ...
3671
-	uint32_t size = 0;
3672
-	while(true) {
3673
-		int value = r->get_char();
3674
-		if(value == EOF) break;
3675
-		data[size++] = value;
3676
-		if(size >= 8 * 1024 * 1024) {
3677
-			//prevent buffer overflow: SNES-made UPS patches should never be this big anyway ...
3678
-			delete[] data;
3679
-			return false;
3680
-		}
3681
-	}
3682
-
3683
-	//4-byte header + 1-byte input size + 1-byte output size + 4-byte patch CRC32 + 4-byte unpatched CRC32 + 4-byte patched CRC32
3684
-	if(size < 18) { delete[] data; return false; }  //patch is too small
3685
-
3686
-	uint32_t addr = 0;
3687
-	if(data[addr++] != 'U') { delete[] data; return false; }  //patch has an invalid header
3688
-	if(data[addr++] != 'P') { delete[] data; return false; }  //...
3689
-	if(data[addr++] != 'S') { delete[] data; return false; }  //...
3690
-	if(data[addr++] != '1') { delete[] data; return false; }  //...
3691
-
3692
-	uint32_t patch_crc32 = caCRC32(data, size - 4);  //don't include patch CRC32 itself in CRC32 calculation
3693
-	uint32_t rom_crc32 = caCRC32(Memory.ROM, rom_size);
3694
-	uint32_t px_crc32 = (data[size - 12] << 0) + (data[size - 11] << 8) + (data[size - 10] << 16) + (data[size -  9] << 24);
3695
-	uint32_t py_crc32 = (data[size -  8] << 0) + (data[size -  7] << 8) + (data[size -  6] << 16) + (data[size -  5] << 24);
3696
-	uint32_t pp_crc32 = (data[size -  4] << 0) + (data[size -  3] << 8) + (data[size -  2] << 16) + (data[size -  1] << 24);
3697
-	if(patch_crc32 != pp_crc32) { delete[] data; return false; }  //patch is corrupted
3698
-	if((rom_crc32 != px_crc32) && (rom_crc32 != py_crc32)) { delete[] data; return false; }  //patch is for a different ROM
3699
-
3700
-	uint32_t px_size = ReadUPSPointer(data, addr, size);
3701
-	uint32_t py_size = ReadUPSPointer(data, addr, size);
3702
-	uint32_t out_size = ((uint32_t) rom_size == px_size) ? py_size : px_size;
3703
-	if(out_size > CMemory::MAX_ROM_SIZE) { delete[] data; return false; }  //applying this patch will overflow Memory.ROM buffer
3704
-
3705
-	//fill expanded area with 0x00s; so that XORing works as expected below.
3706
-	//note that this is needed (and works) whether output ROM is larger or smaller than pre-patched ROM
3707
-	for(unsigned i = min((uint32_t) rom_size, out_size); i < max((uint32_t) rom_size, out_size); i++) {
3708
-		Memory.ROM[i] = 0x00;
3709
-	}
820
+	bool isROM = !(type == MAP_TYPE_I_O || type == MAP_TYPE_RAM);
821
+	bool isRAM = type != MAP_TYPE_I_O;
3710 822
 
3711
-	uint32_t relative = 0;
3712
-	while(addr < size - 12) {
3713
-		relative += ReadUPSPointer(data, addr, size);
3714
-		while(addr < size - 12) {
3715
-			uint8_t x = data[addr++];
3716
-			Memory.ROM[relative++] ^= x;
3717
-			if(!x) break;
823
+	for (uint32_t c = bank_s; c <= bank_e; ++c)
824
+		for (uint32_t i = addr_s; i <= addr_e; i += 0x1000)
825
+		{
826
+			uint32_t p = (c << 4) | (i >> 12);
827
+			this->Map[p] = reinterpret_cast<uint8_t *>(index);
828
+			this->BlockIsROM[p] = isROM;
829
+			this->BlockIsRAM[p] = isRAM;
3718 830
 		}
3719
-	}
3720
-
3721
-	rom_size = out_size;
3722
-	delete[] data;
3723
-
3724
-	uint32_t out_crc32 = caCRC32(Memory.ROM, rom_size);
3725
-	if(((rom_crc32 == px_crc32) && (out_crc32 == py_crc32))
3726
-	|| ((rom_crc32 == py_crc32) && (out_crc32 == px_crc32))
3727
-	) {
3728
-		return true;
3729
-	} else {
3730
-		//technically, reaching here means that patching has failed.
3731
-		//we should return false, but unfortunately Memory.ROM has already
3732
-		//been modified above and cannot be undone. to do this properly, we
3733
-		//would need to make a copy of Memory.ROM, apply the patch, and then
3734
-		//copy that back to Memory.ROM.
3735
-		//
3736
-		//however, the only way for this case to happen is if the UPS patch file
3737
-		//itself is corrupted, which should be detected by the patch CRC32 check
3738
-		//above anyway. errors due to the wrong ROM or patch file being used are
3739
-		//already caught above.
3740
-		fprintf(stderr, "WARNING: UPS patching appears to have failed.\nGame may not be playable.\n");
3741
-		return true;
3742
-	}
3743 831
 }
3744 832
 
3745
-static long ReadInt (Reader *r, unsigned nbytes)
833
+void CMemory::map_System()
3746 834
 {
3747
-	long	v = 0;
3748
-
3749
-	while (nbytes--)
3750
-	{
3751
-		int	c = r->get_char();
3752
-		if (c == EOF)
3753
-			return -1;
3754
-		v = (v << 8) | (c & 0xFF);
3755
-	}
3756
-
3757
-	return v;
835
+	// will be overwritten
836
+	this->map_space(0x00, 0x3f, 0x0000, 0x1fff, &this->RAM[0]);
837
+	this->map_index(0x00, 0x3f, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O);
838
+	this->map_index(0x00, 0x3f, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O);
839
+	this->map_space(0x80, 0xbf, 0x0000, 0x1fff, &this->RAM[0]);
840
+	this->map_index(0x80, 0xbf, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O);
841
+	this->map_index(0x80, 0xbf, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O);
3758 842
 }
3759 843
 
3760
-static bool ReadIPSPatch (Reader *r, long offset, int32_t &rom_size)
844
+void CMemory::map_WRAM()
3761 845
 {
3762
-	const int32_t	IPS_EOF = 0x00454F46l;
3763
-	int32_t		ofs;
3764
-	char		fname[6];
3765
-
3766
-	fname[5] = 0;
3767
-	for (int i = 0; i < 5; i++)
3768
-	{
3769
-		int	c = r->get_char();
3770
-		if (c == EOF)
3771
-			return 0;
3772
-		fname[i] = (char) c;
3773
-	}
3774
-
3775
-	if (strncmp(fname, "PATCH", 5))
3776
-		return 0;
3777
-
3778
-	for (;;)
3779
-	{
3780
-		long	len, rlen;
3781
-		int		rchar;
3782
-
3783
-		ofs = ReadInt(r, 3);
3784
-		if (ofs == -1)
3785
-			return 0;
3786
-
3787
-		if (ofs == IPS_EOF)
3788
-			break;
3789
-
3790
-		ofs -= offset;
3791
-
3792
-		len = ReadInt(r, 2);
3793
-		if (len == -1)
3794
-			return 0;
3795
-
3796
-		if (len)
3797
-		{
3798
-			if (ofs + len > CMemory::MAX_ROM_SIZE)
3799
-				return 0;
3800
-
3801
-			while (len--)
3802
-			{
3803
-				rchar = r->get_char();
3804
-				if (rchar == EOF)
3805
-					return 0;
3806
-				Memory.ROM[ofs++] = (uint8_t) rchar;
3807
-			}
3808
-
3809
-			if (ofs > rom_size)
3810
-				rom_size = ofs;
3811
-		}
3812
-		else
3813
-		{
3814
-			rlen = ReadInt(r, 2);
3815
-			if (rlen == -1)
3816
-				return 0;
3817
-
3818
-			rchar = r->get_char();
3819
-			if (rchar == EOF)
3820
-				return 0;
3821
-
3822
-			if (ofs + rlen > CMemory::MAX_ROM_SIZE)
3823
-				return 0;
3824
-
3825
-			while (rlen--)
3826
-				Memory.ROM[ofs++] = (uint8_t) rchar;
3827
-
3828
-			if (ofs > rom_size)
3829
-				rom_size = ofs;
3830
-		}
3831
-	}
3832
-
3833
-	ofs = ReadInt(r, 3);
3834
-	if (ofs != -1 && ofs - offset < rom_size)
3835
-		rom_size = ofs - offset;
3836
-
3837
-	return 1;
3838
-}*/
846
+	// will overwrite others
847
+	this->map_space(0x7e, 0x7e, 0x0000, 0xffff, &this->RAM[0]);
848
+	this->map_space(0x7f, 0x7f, 0x0000, 0xffff, &this->RAM[0x10000]);
849
+}
3839 850
 
3840
-#ifdef UNZIP_SUPPORT
3841
-static int unzFindExtension (unzFile &file, const char *ext, bool restart, bool print)
851
+void CMemory::map_LoROMSRAM()
3842 852
 {
3843
-	unz_file_info	info;
3844
-	int				port, l = strlen(ext);
3845
-
3846
-	if (restart)
3847
-		port = unzGoToFirstFile(file);
3848
-	else
3849
-		port = unzGoToNextFile(file);
3850
-
3851
-	while (port == UNZ_OK)
3852
-	{
3853
-		int		len;
3854
-		char	name[132];
3855
-
3856
-		unzGetCurrentFileInfo(file, &info, name, 128, NULL, 0, NULL, 0);
3857
-		len = strlen(name);
3858
-
3859
-		if (len >= l + 1 && name[len - l - 1] == '.' && strcasecmp(name + len - l, ext) == 0 && unzOpenCurrentFile(file) == UNZ_OK)
3860
-		{
3861
-			if (print)
3862
-				printf("Using IPS or UPS patch %s", name);
3863
-
3864
-			return port;
3865
-		}
3866
-
3867
-		port = unzGoToNextFile(file);
3868
-	}
3869
-
3870
-	return port;
853
+	this->map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
854
+	this->map_index(0xf0, 0xff, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
3871 855
 }
3872
-#endif
3873 856
 
3874
-/*void CMemory::CheckForAnyPatch (const char *rom_filename, bool header, int32_t &rom_size)
857
+void CMemory::map_HiROMSRAM()
3875 858
 {
3876
-	if (Settings.NoPatch)
3877
-		return;
3878
-
3879
-	STREAM		patch_file  = NULL;
3880
-	uint32_t		i;
3881
-	long		offset = header ? 512 : 0;
3882
-	int			ret;
3883
-	bool		flag;
3884
-	char		dir[_MAX_DIR + 1], drive[_MAX_DRIVE + 1], name[_MAX_FNAME + 1], ext[_MAX_EXT + 1], ips[_MAX_EXT + 3], fname[PATH_MAX + 1];
3885
-	const char	*n;
859
+	this->map_index(0x20, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
860
+	this->map_index(0xa0, 0xbf, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
861
+}
3886 862
 
3887
-	// UPS
863
+void CMemory::map_WriteProtectROM()
864
+{
865
+	std::copy(&this->Map[0], &this->Map[0x1000], &this->WriteMap[0]);
3888 866
 
3889
-	_splitpath(rom_filename, drive, dir, name, ext);
3890
-	_makepath(fname, drive, dir, name, "ups");
867
+	for (int c = 0; c < 0x1000; ++c)
868
+		if (this->BlockIsROM[c])
869
+			this->WriteMap[c] = reinterpret_cast<uint8_t *>(MAP_NONE);
870
+}
3891 871
 
3892
-	if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL)
872
+void CMemory::Map_Initialize()
873
+{
874
+	for (int c = 0; c < 0x1000; ++c)
3893 875
 	{
3894
-		printf("Using UPS patch %s", fname);
3895
-
3896
-		ret = ReadUPSPatch(new fReader(patch_file), 0, rom_size);
3897
-		CLOSE_STREAM(patch_file);
3898
-
3899
-		if (ret)
3900
-		{
3901
-			printf("!\n");
3902
-			return;
3903
-		}
3904
-		else
3905
-			printf(" failed!\n");
876
+		this->Map[c] = this->WriteMap[c] = reinterpret_cast<uint8_t *>(MAP_NONE);
877
+		this->BlockIsROM[c] = this->BlockIsRAM[c] = false;
3906 878
 	}
879
+}
3907 880
 
3908
-#ifdef UNZIP_SUPPORT
3909
-	if (!strcasecmp(ext, "zip") || !strcasecmp(ext, ".zip"))
3910
-	{
3911
-		unzFile	file = unzOpen(rom_filename);
3912
-		if (file)
3913
-		{
3914
-			int	port = unzFindExtension(file, "ups");
3915
-			if (port == UNZ_OK)
3916
-			{
3917
-				printf(" in %s", rom_filename);
881
+void CMemory::Map_LoROMMap()
882
+{
883
+	this->map_System();
3918 884
 
3919
-				ret = ReadUPSPatch(new unzReader(file), offset, rom_size);
3920
-				unzCloseCurrentFile(file);
885
+	this->map_lorom(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize);
886
+	this->map_lorom(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize);
887
+	this->map_lorom(0x80, 0xbf, 0x8000, 0xffff, this->CalculatedSize);
888
+	this->map_lorom(0xc0, 0xff, 0x0000, 0xffff, this->CalculatedSize);
3921 889
 
3922
-				if (ret)
3923
-					printf("!\n");
3924
-				else
3925
-					printf(" failed!\n");
3926
-			}
3927
-		}
3928
-	}
3929
-#endif
890
+	this->map_LoROMSRAM();
891
+	this->map_WRAM();
3930 892
 
3931
-	n = S9xGetFilename(".ups", IPS_DIR);
893
+	this->map_WriteProtectROM();
894
+}
3932 895
 
3933
-	if ((patch_file = OPEN_STREAM(n, "rb")) != NULL)
3934
-	{
3935
-		printf("Using UPS patch %s", n);
896
+void CMemory::Map_NoMAD1LoROMMap()
897
+{
898
+	this->map_System();
3936 899
 
3937
-		ret = ReadUPSPatch(new fReader(patch_file), 0, rom_size);
3938
-		CLOSE_STREAM(patch_file);
900
+	this->map_lorom(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize);
901
+	this->map_lorom(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize);
902
+	this->map_lorom(0x80, 0xbf, 0x8000, 0xffff, this->CalculatedSize);
903
+	this->map_lorom(0xc0, 0xff, 0x0000, 0xffff, this->CalculatedSize);
3939 904
 
3940
-		if (ret)
3941
-		{
3942
-			printf("!\n");
3943
-			return;
3944
-		}
3945
-		else
3946
-			printf(" failed!\n");
3947
-	}
905
+	this->map_index(0x70, 0x7f, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
906
+	this->map_index(0xf0, 0xff, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
3948 907
 
3949
-	// IPS
908
+	this->map_WRAM();
3950 909
 
3951
-	_splitpath(rom_filename, drive, dir, name, ext);
3952
-	_makepath(fname, drive, dir, name, "ips");
910
+	this->map_WriteProtectROM();
911
+}
3953 912
 
3954
-	if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL)
3955
-	{
3956
-		printf("Using IPS patch %s", fname);
913
+void CMemory::Map_JumboLoROMMap()
914
+{
915
+	// XXX: Which game uses this?
916
+	this->map_System();
3957 917
 
3958
-		ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
3959
-		CLOSE_STREAM(patch_file);
918
+	this->map_lorom_offset(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize - 0x400000, 0x400000);
919
+	this->map_lorom_offset(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize - 0x400000, 0x400000);
920
+	this->map_lorom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0);
921
+	this->map_lorom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0x200000);
3960 922
 
3961
-		if (ret)
3962
-		{
3963
-			printf("!\n");
3964
-			return;
3965
-		}
3966
-		else
3967
-			printf(" failed!\n");
3968
-	}
923
+	this->map_LoROMSRAM();
924
+	this->map_WRAM();
3969 925
 
3970
-	if (_MAX_EXT > 6)
3971
-	{
3972
-		i = 0;
3973
-		flag = false;
926
+	this->map_WriteProtectROM();
927
+}
3974 928
 
3975
-		do
3976
-		{
3977
-			snprintf(ips, 8, "%03d.ips", i);
3978
-			_makepath(fname, drive, dir, name, ips);
929
+void CMemory::Map_ROM24MBSLoROMMap()
930
+{
931
+	// PCB: BSC-1A5M-01, BSC-1A7M-10
932
+	this->map_System();
3979 933
 
3980
-			if (!(patch_file = OPEN_STREAM(fname, "rb")))
3981
-				break;
934
+	this->map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x100000, 0);
935
+	this->map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000);
936
+	this->map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x100000, 0x200000);
937
+	this->map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000);
3982 938
 
3983
-			printf("Using IPS patch %s", fname);
939
+	this->map_LoROMSRAM();
940
+	this->map_WRAM();
3984 941
 
3985
-			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
3986
-			CLOSE_STREAM(patch_file);
942
+	this->map_WriteProtectROM();
943
+}
3987 944
 
3988
-			if (ret)
3989
-			{
3990
-				printf("!\n");
3991
-				flag = true;
3992
-			}
3993
-			else
3994
-			{
3995
-				printf(" failed!\n");
3996
-				break;
3997
-			}
3998
-		} while (++i < 1000);
945
+void CMemory::Map_SRAM512KLoROMMap()
946
+{
947
+	this->map_System();
3999 948
 
4000
-		if (flag)
4001
-			return;
4002
-	}
949
+	this->map_lorom(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize);
950
+	this->map_lorom(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize);
951
+	this->map_lorom(0x80, 0xbf, 0x8000, 0xffff, this->CalculatedSize);
952
+	this->map_lorom(0xc0, 0xff, 0x0000, 0xffff, this->CalculatedSize);
4003 953
 
4004
-	if (_MAX_EXT > 3)
4005
-	{
4006
-		i = 0;
4007
-		flag = false;
954
+	this->map_space(0x70, 0x70, 0x0000, 0xffff, &this->SRAM[0]);
955
+	this->map_space(0x71, 0x71, 0x0000, 0xffff, &this->SRAM[0x8000]);
956
+	this->map_space(0x72, 0x72, 0x0000, 0xffff, &this->SRAM[0x10000]);
957
+	this->map_space(0x73, 0x73, 0x0000, 0xffff, &this->SRAM[0x18000]);
4008 958
 
4009
-		do
4010
-		{
4011
-			snprintf(ips, _MAX_EXT + 2, "ips%d", i);
4012
-			if (strlen(ips) > _MAX_EXT)
4013
-				break;
4014
-			_makepath(fname, drive, dir, name, ips);
959
+	this->map_WRAM();
4015 960
 
4016
-			if (!(patch_file = OPEN_STREAM(fname, "rb")))
4017
-				break;
961
+	this->map_WriteProtectROM();
962
+}
4018 963
 
4019
-			printf("Using IPS patch %s", fname);
964
+void CMemory::Map_SDD1LoROMMap()
965
+{
966
+	this->map_System();
4020 967
 
4021
-			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
4022
-			CLOSE_STREAM(patch_file);
968
+	this->map_lorom(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize);
969
+	this->map_lorom(0x80, 0xbf, 0x8000, 0xffff, this->CalculatedSize);
4023 970
 
4024
-			if (ret)
4025
-			{
4026
-				printf("!\n");
4027
-				flag = true;
4028
-			}
4029
-			else
4030
-			{
4031
-				printf(" failed!\n");
4032
-				break;
4033
-			}
4034
-		} while (++i != 0);
971
+	this->map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize, 0);
972
+	this->map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, this->CalculatedSize, 0); // will be overwritten dynamically
4035 973
 
4036
-		if (flag)
4037
-			return;
4038
-	}
974
+	this->map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
4039 975
 
4040
-	if (_MAX_EXT > 2)
4041
-	{
4042
-		i = 0;
4043
-		flag = false;
976
+	this->map_WRAM();
4044 977
 
4045
-		do
4046
-		{
4047
-			snprintf(ips, 4, "ip%d", i);
4048
-			_makepath(fname, drive, dir, name, ips);
978
+	this->map_WriteProtectROM();
979
+}
4049 980
 
4050
-			if (!(patch_file = OPEN_STREAM(fname, "rb")))
4051
-				break;
981
+void CMemory::Map_HiROMMap()
982
+{
983
+	this->map_System();
4052 984
 
4053
-			printf("Using IPS patch %s", fname);
985
+	this->map_hirom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
986
+	this->map_hirom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize);
987
+	this->map_hirom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
988
+	this->map_hirom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
4054 989
 
4055
-			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
4056
-			CLOSE_STREAM(patch_file);
990
+	this->map_HiROMSRAM();
991
+	this->map_WRAM();
4057 992
 
4058
-			if (ret)
4059
-			{
4060
-				printf("!\n");
4061
-				flag = true;
4062
-			}
4063
-			else
4064
-			{
4065
-				printf(" failed!\n");
4066
-				break;
4067
-			}
4068
-		} while (++i < 10);
993
+	this->map_WriteProtectROM();
994
+}
4069 995
 
4070
-		if (flag)
4071
-			return;
4072
-	}
996
+void CMemory::Map_ExtendedHiROMMap()
997
+{
998
+	this->map_System();
4073 999
 
4074
-#ifdef UNZIP_SUPPORT
4075
-	if (!strcasecmp(ext, "zip") || !strcasecmp(ext, ".zip"))
4076
-	{
4077
-		unzFile	file = unzOpen(rom_filename);
4078
-		if (file)
4079
-		{
4080
-			int	port = unzFindExtension(file, "ips");
4081
-			while (port == UNZ_OK)
4082
-			{
4083
-				printf(" in %s", rom_filename);
1000
+	this->map_hirom_offset(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize - 0x400000, 0x400000);
1001
+	this->map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize - 0x400000, 0x400000);
1002
+	this->map_hirom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0);
1003
+	this->map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0);
4084 1004
 
4085
-				ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
4086
-				unzCloseCurrentFile(file);
1005
+	this->map_HiROMSRAM();
1006
+	this->map_WRAM();
4087 1007
 
4088
-				if (ret)
4089
-				{
4090
-					printf("!\n");
4091
-					flag = true;
4092
-				}
4093
-				else
4094
-					printf(" failed!\n");
1008
+	this->map_WriteProtectROM();
1009
+}
4095 1010
 
4096
-				port = unzFindExtension(file, "ips", false);
4097
-			}
1011
+// hack
4098 1012
 
4099
-			if (!flag)
4100
-			{
4101
-				i = 0;
4102
-
4103
-				do
4104
-				{
4105
-					snprintf(ips, 8, "%03d.ips", i);
4106
-
4107
-					if (unzFindExtension(file, ips) != UNZ_OK)
4108
-						break;
4109
-
4110
-					printf(" in %s", rom_filename);
4111
-
4112
-					ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
4113
-					unzCloseCurrentFile(file);
4114
-
4115
-					if (ret)
4116
-					{
4117
-						printf("!\n");
4118
-						flag = true;
4119
-					}
4120
-					else
4121
-					{
4122
-						printf(" failed!\n");
4123
-						break;
4124
-					}
4125
-
4126
-					if (unzFindExtension(file, ips, false, false) == UNZ_OK)
4127
-						printf("WARNING: Ignoring extra .%s files!\n", ips);
4128
-				} while (++i < 1000);
4129
-			}
1013
+bool CMemory::match_na(const char *str)
1014
+{
1015
+	return !strcmp(this->ROMName, str);
1016
+}
4130 1017
 
4131
-			if (!flag)
4132
-			{
4133
-				i = 0;
4134
-
4135
-				do
4136
-				{
4137
-					snprintf(ips, _MAX_EXT + 2, "ips%d", i);
4138
-					if (strlen(ips) > _MAX_EXT)
4139
-						break;
4140
-
4141
-					if (unzFindExtension(file, ips) != UNZ_OK)
4142
-						break;
4143
-
4144
-					printf(" in %s", rom_filename);
4145
-
4146
-					ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
4147
-					unzCloseCurrentFile(file);
4148
-
4149
-					if (ret)
4150
-					{
4151
-						printf("!\n");
4152
-						flag = true;
4153
-					}
4154
-					else
4155
-					{
4156
-						printf(" failed!\n");
4157
-						break;
4158
-					}
4159
-
4160
-					if (unzFindExtension(file, ips, false, false) == UNZ_OK)
4161
-						printf("WARNING: Ignoring extra .%s files!\n", ips);
4162
-				} while (++i != 0);
4163
-			}
1018
+bool CMemory::match_nn(const char *str)
1019
+{
1020
+	return !strncmp(this->ROMName, str, strlen(str));
1021
+}
4164 1022
 
4165
-			if (!flag)
4166
-			{
4167
-				i = 0;
4168
-
4169
-				do
4170
-				{
4171
-					snprintf(ips, 4, "ip%d", i);
4172
-
4173
-					if (unzFindExtension(file, ips) != UNZ_OK)
4174
-						break;
4175
-
4176
-					printf(" in %s", rom_filename);
4177
-
4178
-					ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
4179
-					unzCloseCurrentFile(file);
4180
-
4181
-					if (ret)
4182
-					{
4183
-						printf("!\n");
4184
-						flag = true;
4185
-					}
4186
-					else
4187
-					{
4188
-						printf(" failed!\n");
4189
-						break;
4190
-					}
4191
-
4192
-					if (unzFindExtension(file, ips, false, false) == UNZ_OK)
4193
-						printf("WARNING: Ignoring extra .%s files!\n", ips);
4194
-				} while (++i < 10);
4195
-			}
1023
+bool CMemory::match_id(const char *str)
1024
+{
1025
+	return !strncmp(this->ROMId, str, strlen(str));
1026
+}
4196 1027
 
4197
-			assert(unzClose(file) == UNZ_OK);
1028
+void CMemory::ApplyROMFixes()
1029
+{
1030
+	Settings.BlockInvalidVRAMAccess = Settings.BlockInvalidVRAMAccessMaster;
4198 1031
 
4199
-			if (flag)
4200
-				return;
4201
-		}
4202
-	}
4203
-#endif
1032
+	//// APU timing hacks :(
4204 1033
 
4205
-	n = S9xGetFilename(".ips", IPS_DIR);
1034
+	Timings.APUSpeedup = 0;
1035
+	Timings.APUAllowTimeOverflow = false;
4206 1036
 
4207
-	if ((patch_file = OPEN_STREAM(n, "rb")) != NULL)
1037
+	if (!Settings.DisableGameSpecificHacks)
4208 1038
 	{
4209
-		printf("Using IPS patch %s", n);
1039
+		if (this->match_id("AVCJ")) // Rendering Ranger R2
1040
+			Timings.APUSpeedup = 4;
4210 1041
 
4211
-		ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
4212
-		CLOSE_STREAM(patch_file);
1042
+		if (this->match_na("GAIA GENSOUKI 1 JPN") || // Gaia Gensouki
1043
+			this->match_id("JG  ") || // Illusion of Gaia
1044
+			this->match_id("CQ  ") || // Stunt Race FX
1045
+			this->match_na("SOULBLADER - 1") || // Soul Blader
1046
+			this->match_na("SOULBLAZER - 1 USA") || // Soul Blazer
1047
+			this->match_na("SLAP STICK 1 JPN") || // Slap Stick
1048
+			this->match_id("E9 ") || // Robotrek
1049
+			this->match_nn("ACTRAISER") || // Actraiser
1050
+			this->match_nn("ActRaiser-2") || // Actraiser 2
1051
+			this->match_id("AQT") || // Tenchi Souzou, Terranigma
1052
+			this->match_id("ATV") || // Tales of Phantasia
1053
+			this->match_id("ARF") || // Star Ocean
1054
+			this->match_id("APR") || // Zen-Nippon Pro Wrestling 2 - 3-4 Budoukan
1055
+			this->match_id("A4B") || // Super Bomberman 4
1056
+			this->match_id("Y7 ") || // U.F.O. Kamen Yakisoban - Present Ban
1057
+			this->match_id("Y9 ") || // U.F.O. Kamen Yakisoban - Shihan Ban
1058
+			this->match_id("APB") || // Super Bomberman - Panic Bomber W
1059
+			this->match_na("DARK KINGDOM") || // Dark Kingdom
1060
+			this->match_na("ZAN3 SFC") || // Zan III Spirits
1061
+			this->match_na("HIOUDEN") || // Hiouden - Mamono-tachi Tono Chikai
1062
+			this->match_na("\xC3\xDD\xBC\xC9\xB3\xC0") || // Tenshi no Uta
1063
+			this->match_na("FORTUNE QUEST") || // Fortune Quest - Dice wo Korogase
1064
+			this->match_na("FISHING TO BASSING") || // Shimono Masaki no Fishing To Bassing
1065
+			this->match_na("OHMONO BLACKBASS") || // Oomono Black Bass Fishing - Jinzouko Hen
1066
+			this->match_na("MASTERS") || // Harukanaru Augusta 2 - Masters
1067
+			this->match_na("SFC \xB6\xD2\xDD\xD7\xB2\xC0\xDE\xB0") || // Kamen Rider
1068
+			this->match_na("ZENKI TENCHIMEIDOU") || // Kishin Douji Zenki - Tenchi Meidou
1069
+			this->match_nn("TokyoDome '95Battle 7") || // Shin Nippon Pro Wrestling Kounin '95 - Tokyo Dome Battle 7
1070
+			this->match_nn("SWORD WORLD SFC") || // Sword World SFC/2
1071
+			this->match_nn("LETs PACHINKO(") || // BS Lets Pachinko Nante Gindama 1/2/3/4
1072
+			this->match_nn("THE FISHING MASTER") || // Mark Davis The Fishing Master
1073
+			this->match_nn("Parlor") || // Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5
1074
+			this->match_na("HEIWA Parlor!Mini8") || // Parlor mini 8
1075
+			this->match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!")) // SANKYO Fever! Fever!
1076
+			Timings.APUSpeedup = 1;
4213 1077
 
4214
-		if (ret)
4215
-		{
4216
-			printf("!\n");
4217
-			return;
4218
-		}
4219
-		else
4220
-			printf(" failed!\n");
1078
+		if (this->match_na("EARTHWORM JIM 2") || // Earthworm Jim 2
1079
+			this->match_na("NBA Hangtime") || // NBA Hang Time
1080
+			this->match_na("MSPACMAN") || // Ms Pacman
1081
+			this->match_na("THE MASK") || // The Mask
1082
+			this->match_na("PRIMAL RAGE") || // Primal Rage
1083
+			this->match_na("DOOM TROOPERS")) // Doom Troopers
1084
+			Timings.APUAllowTimeOverflow = true;
4221 1085
 	}
4222 1086
 
4223
-	if (_MAX_EXT > 6)
4224
-	{
4225
-		i = 0;
4226
-		flag = false;
4227
-
4228
-		do
4229
-		{
4230
-			snprintf(ips, 9, ".%03d.ips", i);
4231
-			n = S9xGetFilename(ips, IPS_DIR);
4232
-
4233
-			if (!(patch_file = OPEN_STREAM(n, "rb")))
4234
-				break;
4235
-
4236
-			printf("Using IPS patch %s", n);
4237
-
4238
-			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
4239
-			CLOSE_STREAM(patch_file);
1087
+	S9xAPUTimingSetSpeedup(Timings.APUSpeedup);
1088
+	S9xAPUAllowTimeOverflow(Timings.APUAllowTimeOverflow);
4240 1089
 
4241
-			if (ret)
4242
-			{
4243
-				printf("!\n");
4244
-				flag = true;
4245
-			}
4246
-			else
4247
-			{
4248
-				printf(" failed!\n");
4249
-				break;
4250
-			}
4251
-		} while (++i < 1000);
1090
+	//// Other timing hacks :(
4252 1091
 
4253
-		if (flag)
4254
-			return;
4255
-	}
1092
+	Timings.HDMAStart = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100;
1093
+	Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC;
1094
+	Timings.IRQTriggerCycles = 10;
4256 1095
 
4257
-	if (_MAX_EXT > 3)
1096
+	if (!Settings.DisableGameSpecificHacks)
4258 1097
 	{
4259
-		i = 0;
4260
-		flag = false;
4261
-
4262
-		do
4263
-		{
4264
-			snprintf(ips, _MAX_EXT + 3, ".ips%d", i);
4265
-			if (strlen(ips) > _MAX_EXT + 1)
4266
-				break;
4267
-			n = S9xGetFilename(ips, IPS_DIR);
4268
-
4269
-			if (!(patch_file = OPEN_STREAM(n, "rb")))
4270
-				break;
4271
-
4272
-			printf("Using IPS patch %s", n);
4273
-
4274
-			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
4275
-			CLOSE_STREAM(patch_file);
1098
+		// The delay to sync CPU and DMA which Snes9x cannot emulate.
1099
+		// Some games need really severe delay timing...
1100
+		if (this->match_na("BATTLE GRANDPRIX")) // Battle Grandprix
1101
+			Timings.DMACPUSync = 20;
4276 1102
 
4277
-			if (ret)
4278
-			{
4279
-				printf("!\n");
4280
-				flag = true;
4281
-			}
4282
-			else
4283
-			{
4284
-				printf(" failed!\n");
4285
-				break;
4286
-			}
4287
-		} while (++i != 0);
1103
+		// An infinite loop reads $4212 and waits V-blank end, whereas VIRQ is set V=0.
1104
+		// If Snes9x succeeds to escape from the loop before jumping into the IRQ handler, the game goes further.
1105
+		// If Snes9x jumps into the IRQ handler before escaping from the loop,
1106
+		// Snes9x cannot escape from the loop permanently because the RTI is in the next V-blank.
1107
+		if (this->match_na("Aero the AcroBat 2"))
1108
+			Timings.IRQPendCount = 2;
4288 1109
 
4289
-		if (flag)
4290
-			return;
4291
-	}
1110
+		// XXX: What's happening?
1111
+		if (this->match_na("X-MEN")) // Spider-Man and the X-Men
1112
+			Settings.BlockInvalidVRAMAccess = false;
4292 1113
 
4293
-	if (_MAX_EXT > 2)
4294
-	{
4295
-		i = 0;
4296
-		flag = false;
1114
+		//// SRAM initial value
4297 1115
 
4298
-		do
1116
+		if (this->match_na("HITOMI3"))
4299 1117
 		{
4300
-			snprintf(ips, 5, ".ip%d", i);
4301
-			n = S9xGetFilename(ips, IPS_DIR);
1118
+			SRAMSize = 1;
1119
+			SRAMMask = ((1 << (SRAMSize + 3)) * 128) - 1;
1120
+		}
4302 1121
 
4303
-			if (!(patch_file = OPEN_STREAM(n, "rb")))
4304
-				break;
1122
+		// SRAM value fixes
1123
+		if (this->match_na("SUPER DRIFT OUT") || // Super Drift Out
1124
+			this->match_na("SATAN IS OUR FATHER!") ||
1125
+			this->match_na("goemon 4")) // Ganbare Goemon Kirakira Douchuu
1126
+			SNESGameFixes.SRAMInitialValue = 0x00;
4305 1127
 
4306
-			printf("Using IPS patch %s", n);
1128
+		// Additional game fixes by sanmaiwashi ...
1129
+		// XXX: unnecessary?
1130
+		if (this->match_na("SFX \xC5\xB2\xC4\xB6\xDE\xDD\xC0\xDE\xD1\xD3\xC9\xB6\xDE\xC0\xD8 1")) // SD Gundam Gaiden - Knight Gundam Monogatari
1131
+			SNESGameFixes.SRAMInitialValue = 0x6b;
4307 1132
 
4308
-			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
4309
-			CLOSE_STREAM(patch_file);
1133
+		// others: BS and ST-01x games are 0x00.
4310 1134
 
4311
-			if (ret)
4312
-			{
4313
-				printf("!\n");
4314
-				flag = true;
4315
-			}
4316
-			else
4317
-			{
4318
-				printf(" failed!\n");
4319
-				break;
4320
-			}
4321
-		} while (++i < 10);
1135
+		//// OAM hacks :(
4322 1136
 
4323
-		if (flag)
4324
-			return;
1137
+		// OAM hacks because we don't fully understand the behavior of the SNES.
1138
+		// Totally wacky display in 2P mode...
1139
+		// seems to need a disproven behavior, so we're definitely overlooking some other bug?
1140
+		if (match_nn("UNIRACERS")) // Uniracers
1141
+			SNESGameFixes.Uniracers = true;
4325 1142
 	}
4326
-}*/
1143
+}
Browse code

Cleanup of some warnings, updating modification dates, using nullptr instead of NULL in some cases.

Naram Qashat authored on 2013/03/30 16:17:42
Showing 1 changed files
... ...
@@ -2506,8 +2506,8 @@ void CMemory::InitROM()
2506 2506
 
2507 2507
 	Checksum_Calculate();
2508 2508
 
2509
-	bool isChecksumOK = (ROMChecksum + ROMComplementChecksum == 0xffff) &
2510
-						 (ROMChecksum == CalculatedChecksum);
2509
+	/*bool isChecksumOK = (ROMChecksum + ROMComplementChecksum == 0xffff) &
2510
+						 (ROMChecksum == CalculatedChecksum);*/
2511 2511
 
2512 2512
 	//// Build more ROM information
2513 2513
 
Browse code

Import actual code.

Naram Qashat authored on 2013/03/26 02:41:19
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,4326 @@
1
+/***********************************************************************************
2
+  Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
+
4
+  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
5
+                             Jerremy Koot (jkoot@snes9x.com)
6
+
7
+  (c) Copyright 2002 - 2004  Matthew Kendora
8
+
9
+  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)
10
+
11
+  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)
12
+
13
+  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)
14
+
15
+  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
16
+                             Kris Bleakley (codeviolation@hotmail.com)
17
+
18
+  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
19
+                             Nach (n-a-c-h@users.sourceforge.net),
20
+
21
+  (c) Copyright 2002 - 2011  zones (kasumitokoduck@yahoo.com)
22
+
23
+  (c) Copyright 2006 - 2007  nitsuja
24
+
25
+  (c) Copyright 2009 - 2011  BearOso,
26
+                             OV2
27
+
28
+
29
+  BS-X C emulator code
30
+  (c) Copyright 2005 - 2006  Dreamer Nom,
31
+                             zones
32
+
33
+  C4 x86 assembler and some C emulation code
34
+  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
35
+                             Nach,
36
+                             zsKnight (zsknight@zsnes.com)
37
+
38
+  C4 C++ code
39
+  (c) Copyright 2003 - 2006  Brad Jorsch,
40
+                             Nach
41
+
42
+  DSP-1 emulator code
43
+  (c) Copyright 1998 - 2006  _Demo_,
44
+                             Andreas Naive (andreasnaive@gmail.com),
45
+                             Gary Henderson,
46
+                             Ivar (ivar@snes9x.com),
47
+                             John Weidman,
48
+                             Kris Bleakley,
49
+                             Matthew Kendora,
50
+                             Nach,
51
+                             neviksti (neviksti@hotmail.com)
52
+
53
+  DSP-2 emulator code
54
+  (c) Copyright 2003         John Weidman,
55
+                             Kris Bleakley,
56
+                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
57
+                             Matthew Kendora,
58
+                             neviksti
59
+
60
+  DSP-3 emulator code
61
+  (c) Copyright 2003 - 2006  John Weidman,
62
+                             Kris Bleakley,
63
+                             Lancer,
64
+                             z80 gaiden
65
+
66
+  DSP-4 emulator code
67
+  (c) Copyright 2004 - 2006  Dreamer Nom,
68
+                             John Weidman,
69
+                             Kris Bleakley,
70
+                             Nach,
71
+                             z80 gaiden
72
+
73
+  OBC1 emulator code
74
+  (c) Copyright 2001 - 2004  zsKnight,
75
+                             pagefault (pagefault@zsnes.com),
76
+                             Kris Bleakley
77
+                             Ported from x86 assembler to C by sanmaiwashi
78
+
79
+  SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
+  (c) Copyright 2002         Matthew Kendora with research by
81
+                             zsKnight,
82
+                             John Weidman,
83
+                             Dark Force
84
+
85
+  SPC7110 and RTC C++ emulator code used in 1.52+
86
+  (c) Copyright 2009         byuu,
87
+                             neviksti
88
+
89
+  S-DD1 C emulator code
90
+  (c) Copyright 2003         Brad Jorsch with research by
91
+                             Andreas Naive,
92
+                             John Weidman
93
+
94
+  S-RTC C emulator code
95
+  (c) Copyright 2001 - 2006  byuu,
96
+                             John Weidman
97
+
98
+  ST010 C++ emulator code
99
+  (c) Copyright 2003         Feather,
100
+                             John Weidman,
101
+                             Kris Bleakley,
102
+                             Matthew Kendora
103
+
104
+  Super FX x86 assembler emulator code
105
+  (c) Copyright 1998 - 2003  _Demo_,
106
+                             pagefault,
107
+                             zsKnight
108
+
109
+  Super FX C emulator code
110
+  (c) Copyright 1997 - 1999  Ivar,
111
+                             Gary Henderson,
112
+                             John Weidman
113
+
114
+  Sound emulator code used in 1.5-1.51
115
+  (c) Copyright 1998 - 2003  Brad Martin
116
+  (c) Copyright 1998 - 2006  Charles Bilyue'
117
+
118
+  Sound emulator code used in 1.52+
119
+  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
120
+
121
+  SH assembler code partly based on x86 assembler code
122
+  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
123
+
124
+  2xSaI filter
125
+  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
126
+
127
+  HQ2x, HQ3x, HQ4x filters
128
+  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
129
+
130
+  NTSC filter
131
+  (c) Copyright 2006 - 2007  Shay Green
132
+
133
+  GTK+ GUI code
134
+  (c) Copyright 2004 - 2011  BearOso
135
+
136
+  Win32 GUI code
137
+  (c) Copyright 2003 - 2006  blip,
138
+                             funkyass,
139
+                             Matthew Kendora,
140
+                             Nach,
141
+                             nitsuja
142
+  (c) Copyright 2009 - 2011  OV2
143
+
144
+  Mac OS GUI code
145
+  (c) Copyright 1998 - 2001  John Stiles
146
+  (c) Copyright 2001 - 2011  zones
147
+
148
+
149
+  Specific ports contains the works of other authors. See headers in
150
+  individual files.
151
+
152
+
153
+  Snes9x homepage: http://www.snes9x.com/
154
+
155
+  Permission to use, copy, modify and/or distribute Snes9x in both binary
156
+  and source form, for non-commercial purposes, is hereby granted without
157
+  fee, providing that this license information and copyright notice appear
158
+  with all copies and any derived work.
159
+
160
+  This software is provided 'as-is', without any express or implied
161
+  warranty. In no event shall the authors be held liable for any damages
162
+  arising from the use of this software or it's derivatives.
163
+
164
+  Snes9x is freeware for PERSONAL USE only. Commercial users should
165
+  seek permission of the copyright holders first. Commercial use includes,
166
+  but is not limited to, charging money for Snes9x or software derived from
167
+  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
+  using Snes9x as a promotion for your commercial product.
169
+
170
+  The copyright holders request that bug fixes and improvements to the code
171
+  should be forwarded to them so everyone can benefit from the modifications
172
+  in future versions.
173
+
174
+  Super NES and Super Nintendo Entertainment System are trademarks of
175
+  Nintendo Co., Limited and its subsidiary companies.
176
+ ***********************************************************************************/
177
+
178
+#include <algorithm>
179
+#include <string>
180
+#include <numeric>
181
+#include <assert.h>
182
+
183
+#ifdef UNZIP_SUPPORT
184
+#include "unzip/unzip.h"
185
+#endif
186
+
187
+#ifdef JMA_SUPPORT
188
+#include "jma/s9x-jma.h"
189
+#endif
190
+
191
+#include "snes9x.h"
192
+#include "memmap.h"
193
+#include "apu/apu.h"
194
+//#include "fxemu.h"
195
+#include "sdd1.h"
196
+//#include "srtc.h"
197
+//#include "controls.h"
198
+//#include "cheats.h"
199
+//#include "movie.h"
200
+//#include "reader.h"
201
+//#include "display.h"
202
+
203
+/*#ifndef SET_UI_COLOR
204
+#define SET_UI_COLOR(r, g, b) ;
205
+#endif*/
206
+
207
+/*#ifndef max
208
+#define max(a, b) (((a) > (b)) ? (a) : (b))
209
+#endif*/
210
+
211
+/*#ifndef min
212
+#define min(a, b) (((a) < (b)) ? (a) : (b))
213
+#endif*/
214
+
215
+//static bool	stopMovie = true;
216
+//static char		LastRomFilename[PATH_MAX + 1] = "";
217
+
218
+// from NSRT
219
+/*static const char	*nintendo_licensees[] =
220
+{
221
+	"Unlicensed",
222
+	"Nintendo",
223
+	"Rocket Games/Ajinomoto",
224
+	"Imagineer-Zoom",
225
+	"Gray Matter",
226
+	"Zamuse",
227
+	"Falcom",
228
+	NULL,
229
+	"Capcom",
230
+	"Hot B Co.",
231
+	"Jaleco",
232
+	"Coconuts Japan",
233
+	"Coconuts Japan/G.X.Media",
234
+	"Micronet",
235
+	"Technos",
236
+	"Mebio Software",
237
+	"Shouei System",
238
+	"Starfish",
239
+	NULL,
240
+	"Mitsui Fudosan/Dentsu",
241
+	NULL,
242
+	"Warashi Inc.",
243
+	NULL,
244
+	"Nowpro",
245
+	NULL,
246
+	"Game Village",
247
+	"IE Institute",
248
+	NULL,
249
+	NULL,
250
+	NULL,
251
+	NULL,
252
+	NULL,
253
+	NULL,
254
+	NULL,
255
+	NULL,
256
+	NULL,
257
+	"Banarex",
258
+	"Starfish",
259
+	"Infocom",
260
+	"Electronic Arts Japan",
261
+	NULL,
262
+	"Cobra Team",
263
+	"Human/Field",
264
+	"KOEI",
265
+	"Hudson Soft",
266
+	"S.C.P./Game Village",
267
+	"Yanoman",
268
+	NULL,
269
+	"Tecmo Products",
270
+	"Japan Glary Business",
271
+	"Forum/OpenSystem",
272
+	"Virgin Games (Japan)",
273
+	"SMDE",
274
+	"Yojigen",
275
+	NULL,
276
+	"Daikokudenki",
277
+	NULL,
278
+	NULL,
279
+	NULL,
280
+	NULL,
281
+	NULL,
282
+	"Creatures Inc.",
283
+	"TDK Deep Impresion",
284
+	NULL,
285
+	NULL,
286
+	NULL,
287
+	NULL,
288
+	NULL,
289
+	NULL,
290
+	NULL,
291
+	NULL,
292
+	NULL,
293
+	"Destination Software/KSS",
294
+	"Sunsoft/Tokai Engineering",
295
+	"POW (Planning Office Wada)/VR 1 Japan",
296
+	"Micro World",
297
+	NULL,
298
+	"San-X",
299
+	"Enix",
300
+	"Loriciel/Electro Brain",
301
+	"Kemco Japan",
302
+	"Seta Co.,Ltd.",
303
+	"Culture Brain",
304
+	"Irem Corp.",
305
+	"Palsoft",
306
+	"Visit Co., Ltd.",
307
+	"Intec",
308
+	"System Sacom",
309
+	"Poppo",
310
+	"Ubisoft Japan",
311
+	NULL,
312
+	"Media Works",
313
+	"NEC InterChannel",
314
+	"Tam",
315
+	"Gajin/Jordan",
316
+	"Smilesoft",
317
+	NULL,
318
+	NULL,
319
+	"Mediakite",
320
+	NULL,
321
+	NULL,
322
+	NULL,
323
+	NULL,
324
+	NULL,
325
+	NULL,
326
+	NULL,
327
+	NULL,
328
+	NULL,
329
+	"Viacom",
330
+	"Carrozzeria",
331
+	"Dynamic",
332
+	NULL,
333
+	"Magifact",
334
+	"Hect",
335
+	"Codemasters",
336
+	"Taito/GAGA Communications",
337
+	"Laguna",
338
+	"Telstar Fun & Games/Event/Taito",
339
+	NULL,
340
+	"Arcade Zone Ltd.",
341
+	"Entertainment International/Empire Software",
342
+	"Loriciel",
343
+	"Gremlin Graphics",
344
+	NULL,
345
+	NULL,
346
+	NULL,
347
+	NULL,
348
+	NULL,
349
+	NULL,
350
+	NULL,
351
+	NULL,
352
+	NULL,
353
+	NULL,
354
+	NULL,
355
+	NULL,
356
+	NULL,
357
+	NULL,
358
+	NULL,
359
+	NULL,
360
+	NULL,
361
+	NULL,
362
+	NULL,
363
+	NULL,
364
+	NULL,
365
+	"Seika Corp.",
366
+	"UBI SOFT Entertainment Software",
367
+	"Sunsoft US",
368
+	NULL,
369
+	"Life Fitness",
370
+	NULL,
371
+	"System 3",
372
+	"Spectrum Holobyte",
373
+	NULL,
374
+	"Irem",
375
+	NULL,
376
+	"Raya Systems",
377
+	"Renovation Products",
378
+	"Malibu Games",
379
+	NULL,
380
+	"Eidos/U.S. Gold",
381
+	"Playmates Interactive",
382
+	NULL,
383
+	NULL,
384
+	"Fox Interactive",
385
+	"Time Warner Interactive",
386
+	NULL,
387
+	NULL,
388
+	NULL,
389
+	NULL,
390
+	NULL,
391
+	"Disney Interactive",
392
+	NULL,
393
+	"Black Pearl",
394
+	NULL,
395
+	"Advanced Productions",
396
+	NULL,
397
+	NULL,
398
+	"GT Interactive",
399
+	"RARE",
400
+	"Crave Entertainment",
401
+	"Absolute Entertainment",
402
+	"Acclaim",
403
+	"Activision",
404
+	"American Sammy",
405
+	"Take 2/GameTek",
406
+	"Hi Tech",
407
+	"LJN Ltd.",
408
+	NULL,
409
+	"Mattel",
410
+	NULL,
411
+	"Mindscape/Red Orb Entertainment",
412
+	"Romstar",
413
+	"Taxan",
414
+	"Midway/Tradewest",
415
+	NULL,
416
+	"American Softworks Corp.",
417
+	"Majesco Sales Inc.",
418
+	"3DO",
419
+	NULL,
420
+	NULL,
421
+	"Hasbro",
422
+	"NewKidCo",
423
+	"Telegames",
424
+	"Metro3D",
425
+	NULL,
426
+	"Vatical Entertainment",
427
+	"LEGO Media",
428
+	NULL,
429
+	"Xicat Interactive",
430
+	"Cryo Interactive",
431
+	NULL,
432
+	NULL,
433
+	"Red Storm Entertainment",
434
+	"Microids",
435
+	NULL,
436
+	"Conspiracy/Swing",
437
+	"Titus",
438
+	"Virgin Interactive",
439
+	"Maxis",
440
+	NULL,
441
+	"LucasArts Entertainment",
442
+	NULL,
443
+	NULL,
444
+	"Ocean",
445
+	NULL,
446
+	"Electronic Arts",
447
+	NULL,
448
+	"Laser Beam",
449
+	NULL,
450
+	NULL,
451
+	"Elite Systems",
452
+	"Electro Brain",
453
+	"The Learning Company",
454
+	"BBC",
455
+	NULL,
456
+	"Software 2000",
457
+	NULL,
458
+	"BAM! Entertainment",
459
+	"Studio 3",
460
+	NULL,
461
+	NULL,
462
+	NULL,
463
+	"Classified Games",
464
+	NULL,
465
+	"TDK Mediactive",
466
+	NULL,
467
+	"DreamCatcher",
468
+	"JoWood Produtions",
469
+	"SEGA",
470
+	"Wannado Edition",
471
+	"LSP (Light & Shadow Prod.)",
472
+	"ITE Media",
473
+	"Infogrames",
474
+	"Interplay",
475
+	"JVC (US)",
476
+	"Parker Brothers",
477
+	NULL,
478
+	"SCI (Sales Curve Interactive)/Storm",
479
+	NULL,
480
+	NULL,
481
+	"THQ Software",
482
+	"Accolade Inc.",
483
+	"Triffix Entertainment",
484
+	NULL,
485
+	"Microprose Software",
486
+	"Universal Interactive/Sierra/Simon & Schuster",
487
+	NULL,
488
+	"Kemco",
489
+	"Rage Software",
490
+	"Encore",
491
+	NULL,
492
+	"Zoo",
493
+	"Kiddinx",
494
+	"Simon & Schuster Interactive",
495
+	"Asmik Ace Entertainment Inc./AIA",
496
+	"Empire Interactive",
497
+	NULL,
498
+	NULL,
499
+	"Jester Interactive",
500
+	NULL,
501
+	"Rockstar Games",
502
+	"Scholastic",
503
+	"Ignition Entertainment",
504
+	"Summitsoft",
505
+	"Stadlbauer",
506
+	NULL,
507
+	NULL,
508
+	NULL,
509
+	"Misawa",
510
+	"Teichiku",
511
+	"Namco Ltd.",
512
+	"LOZC",
513
+	"KOEI",
514
+	NULL,
515
+	"Tokuma Shoten Intermedia",
516
+	"Tsukuda Original",
517
+	"DATAM-Polystar",
518
+	NULL,
519
+	NULL,
520
+	"Bullet-Proof Software",
521
+	"Vic Tokai Inc.",
522
+	NULL,
523
+	"Character Soft",
524
+	"I'Max",
525
+	"Saurus",
526
+	NULL,
527
+	NULL,
528
+	"General Entertainment",
529
+	NULL,
530
+	NULL,
531
+	"I'Max",
532
+	"Success",
533
+	NULL,
534
+	"SEGA Japan",
535
+	NULL,
536
+	NULL,
537
+	NULL,
538
+	NULL,
539
+	NULL,
540
+	NULL,
541
+	NULL,
542
+	NULL,
543
+	NULL,
544
+	NULL,
545
+	"Takara",
546
+	"Chun Soft",
547
+	"Video System Co., Ltd./McO'River",
548
+	"BEC",
549
+	NULL,
550
+	"Varie",
551
+	"Yonezawa/S'pal",
552
+	"Kaneko",
553
+	NULL,
554
+	"Victor Interactive Software/Pack-in-Video",
555
+	"Nichibutsu/Nihon Bussan",
556
+	"Tecmo",
557
+	"Imagineer",
558
+	NULL,
559
+	NULL,
560
+	"Nova",
561
+	"Den'Z",
562
+	"Bottom Up",
563
+	NULL,
564
+	"TGL (Technical Group Laboratory)",
565
+	NULL,
566
+	"Hasbro Japan",
567
+	NULL,
568
+	"Marvelous Entertainment",
569
+	NULL,
570
+	"Keynet Inc.",
571
+	"Hands-On Entertainment",
572
+	NULL,
573
+	NULL,
574
+	NULL,
575
+	NULL,
576
+	NULL,
577
+	NULL,
578
+	NULL,
579
+	NULL,
580
+	NULL,
581
+	"Telenet",
582
+	"Hori",
583
+	NULL,
584
+	NULL,
585
+	"Konami",
586
+	"K.Amusement Leasing Co.",
587
+	"Kawada",
588
+	"Takara",
589
+	NULL,
590
+	"Technos Japan Corp.",
591
+	"JVC (Europe/Japan)/Victor Musical Industries",
592
+	NULL,
593
+	"Toei Animation",
594
+	"Toho",
595
+	NULL,
596
+	"Namco",
597
+	"Media Rings Corp.",
598
+	"J-Wing",
599
+	NULL,
600
+	"Pioneer LDC",
601
+	"KID",
602
+	"Mediafactory",
603
+	NULL,
604
+	NULL,
605
+	NULL,
606
+	"Infogrames Hudson",
607
+	NULL,
608
+	NULL,
609
+	NULL,
610
+	NULL,
611
+	NULL,
612
+	NULL,
613
+	NULL,
614
+	NULL,
615
+	NULL,
616
+	NULL,
617
+	"Acclaim Japan",
618
+	"ASCII Co./Nexoft",
619
+	"Bandai",
620
+	NULL,
621
+	"Enix",
622
+	NULL,
623
+	"HAL Laboratory/Halken",
624
+	"SNK",
625
+	NULL,
626
+	"Pony Canyon Hanbai",
627
+	"Culture Brain",
628
+	"Sunsoft",
629
+	"Toshiba EMI",
630
+	"Sony Imagesoft",
631
+	NULL,
632
+	"Sammy",
633
+	"Magical",
634
+	"Visco",
635
+	NULL,
636
+	"Compile",
637
+	NULL,
638
+	"MTO Inc.",
639
+	NULL,
640
+	"Sunrise Interactive",
641
+	NULL,
642
+	"Global A Entertainment",
643
+	"Fuuki",
644
+	NULL,
645
+	NULL,
646
+	NULL,
647
+	NULL,
648
+	NULL,
649
+	NULL,
650
+	NULL,
651
+	NULL,
652
+	NULL,
653
+	"Taito",
654
+	NULL,
655
+	"Kemco",
656
+	"Square",
657
+	"Tokuma Shoten",
658
+	"Data East",
659
+	"Tonkin House",
660
+	NULL,
661
+	"KOEI",
662
+	NULL,
663
+	"Konami/Ultra/Palcom",
664
+	"NTVIC/VAP",
665
+	"Use Co., Ltd.",
666
+	"Meldac",
667
+	"Pony Canyon (Japan)/FCI (US)",
668
+	"Angel/Sotsu Agency/Sunrise",
669
+	"Yumedia/Aroma Co., Ltd.",
670
+	NULL,
671
+	NULL,
672
+	"Boss",
673
+	"Axela/Crea-Tech",
674
+	"Sekaibunka-Sha/Sumire kobo/Marigul Management Inc.",
675
+	"Konami Computer Entertainment Osaka",
676
+	NULL,
677
+	NULL,
678
+	"Enterbrain",
679
+	NULL,
680
+	NULL,
681
+	NULL,
682
+	NULL,
683
+	NULL,
684
+	NULL,
685
+	NULL,
686
+	NULL,
687
+	NULL,
688
+	NULL,
689
+	"Taito/Disco",
690
+	"Sofel",
691
+	"Quest Corp.",
692
+	"Sigma",
693
+	"Ask Kodansha",
694
+	NULL,
695
+	"Naxat",
696
+	"Copya System",
697
+	"Capcom Co., Ltd.",
698
+	"Banpresto",
699
+	"TOMY",
700
+	"Acclaim/LJN Japan",
701
+	NULL,
702
+	"NCS",
703
+	"Human Entertainment",
704
+	"Altron",
705
+	"Jaleco",
706
+	"Gaps Inc.",
707
+	NULL,
708
+	NULL,
709
+	NULL,
710
+	NULL,
711
+	NULL,
712
+	"Elf",
713
+	NULL,
714
+	NULL,
715
+	NULL,
716
+	NULL,
717
+	NULL,
718
+	NULL,
719
+	NULL,
720
+	NULL,
721
+	NULL,
722
+	NULL,
723
+	NULL,
724
+	NULL,
725
+	"Jaleco",
726
+	NULL,
727
+	"Yutaka",
728
+	"Varie",
729
+	"T&ESoft",
730
+	"Epoch Co., Ltd.",
731
+	NULL,
732
+	"Athena",
733
+	"Asmik",
734
+	"Natsume",
735
+	"King Records",
736
+	"Atlus",
737
+	"Epic/Sony Records (Japan)",
738
+	NULL,
739
+	"IGS (Information Global Service)",
740
+	NULL,
741
+	"Chatnoir",
742
+	"Right Stuff",
743
+	NULL,
744
+	"NTT COMWARE",
745
+	NULL,
746
+	"Spike",
747
+	"Konami Computer Entertainment Tokyo",
748
+	"Alphadream Corp.",
749
+	NULL,
750
+	"Sting",
751
+	NULL,
752
+	NULL,
753
+	NULL,
754
+	NULL,
755
+	NULL,
756
+	NULL,
757
+	NULL,
758
+	NULL,
759
+	NULL,
760
+	NULL,
761
+	"A Wave",
762
+	"Motown Software",
763
+	"Left Field Entertainment",
764
+	"Extreme Entertainment Group",
765
+	"TecMagik",
766
+	NULL,
767
+	NULL,
768
+	NULL,
769
+	NULL,
770
+	"Cybersoft",
771
+	NULL,
772
+	"Psygnosis",
773
+	NULL,
774
+	NULL,
775
+	"Davidson/Western Tech.",
776
+	"Unlicensed",
777
+	NULL,
778
+	NULL,
779
+	NULL,
780
+	NULL,
781
+	"The Game Factory Europe",
782
+	"Hip Games",
783
+	"Aspyr",
784
+	NULL,
785
+	NULL,
786
+	"Mastiff",
787
+	"iQue",
788
+	"Digital Tainment Pool",
789
+	"XS Games",
790
+	"Daiwon",
791
+	NULL,
792
+	NULL,
793
+	NULL,
794
+	NULL,
795
+	NULL,
796
+	NULL,
797
+	NULL,
798
+	"PCCW Japan",
799
+	NULL,
800
+	NULL,
801
+	"KiKi Co. Ltd.",
802
+	"Open Sesame Inc.",
803
+	"Sims",
804
+	"Broccoli",
805
+	"Avex",
806
+	"D3 Publisher",
807
+	NULL,
808
+	"Konami Computer Entertainment Japan",
809
+	NULL,
810
+	"Square-Enix",
811
+	"KSG",
812
+	"Micott & Basara Inc.",
813
+	NULL,
814
+	"Orbital Media",
815
+	NULL,
816
+	NULL,
817
+	NULL,
818
+	NULL,
819
+	NULL,
820
+	NULL,
821
+	NULL,
822
+	NULL,
823
+	NULL,
824
+	NULL,
825
+	NULL,
826
+	NULL,
827
+	NULL,
828
+	NULL,
829
+	NULL,
830
+	NULL,
831
+	"The Game Factory USA",
832
+	NULL,
833
+	NULL,
834
+	"Treasure",
835
+	"Aruze",
836
+	"Ertain",
837
+	"SNK Playmore",
838
+	NULL,
839
+	NULL,
840
+	NULL,
841
+	NULL,
842
+	NULL,
843
+	NULL,
844
+	NULL,
845
+	NULL,
846
+	NULL,
847
+	NULL,
848
+	NULL,
849
+	NULL,
850
+	NULL,
851
+	NULL,
852
+	NULL,
853
+	NULL,
854
+	NULL,
855
+	NULL,
856
+	NULL,
857
+	NULL,
858
+	NULL,
859
+	NULL,
860
+	NULL,
861
+	NULL,
862
+	NULL,
863
+	NULL,
864
+	NULL,
865
+	NULL,
866
+	NULL,
867
+	NULL,
868
+	NULL,
869
+	NULL,
870
+	NULL,
871
+	NULL,
872
+	NULL,
873
+	NULL,
874
+	NULL,
875
+	NULL,
876
+	NULL,
877
+	NULL,
878
+	NULL,
879
+	NULL,
880
+	NULL,
881
+	NULL,
882
+	NULL,
883
+	NULL,
884
+	NULL,
885
+	NULL,
886
+	"Yojigen"
887
+};*/
888
+
889
+static const uint32_t	crc32Table[256] =
890
+{
891
+	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
892
+	0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
893
+	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
894
+	0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
895
+	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
896
+	0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
897
+	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
898
+	0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
899
+	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
900
+	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
901
+	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
902
+	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
903
+	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
904
+	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
905
+	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
906
+	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
907
+	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
908
+	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
909
+	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
910
+	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
911
+	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
912
+	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
913
+	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
914
+	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
915
+	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
916
+	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
917
+	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
918
+	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
919
+	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
920
+	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
921
+	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
922
+	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
923
+	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
924
+	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
925
+	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
926
+	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
927
+	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
928
+	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
929
+	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
930
+	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
931
+	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
932
+	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
933
+	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
934
+};
935
+
936
+//static void S9xDeinterleaveType1 (int, uint8_t *);
937
+//static void S9xDeinterleaveType2 (int, uint8_t *);
938
+//static void S9xDeinterleaveGD24 (int, uint8_t *);
939
+//static bool allASCII (uint8_t *, int);
940
+//static bool is_SufamiTurbo_BIOS (uint8_t *, uint32_t);
941
+//static bool is_SufamiTurbo_Cart (uint8_t *, uint32_t);
942
+//static bool is_SameGame_BIOS (uint8_t *, uint32_t);
943
+//static bool is_SameGame_Add_On (uint8_t *, uint32_t);
944
+//static uint32_t caCRC32 (uint8_t *, uint32_t, uint32_t crc32 = 0xffffffff);
945
+/*static uint32_t ReadUPSPointer (const uint8_t *, unsigned &, unsigned);
946
+static bool ReadUPSPatch (Reader *, long, int32_t &);
947
+static long ReadInt (Reader *, unsigned);
948
+static bool ReadIPSPatch (Reader *, long, int32_t &);*/
949
+#ifdef UNZIP_SUPPORT
950
+static int unzFindExtension (unzFile &, const char *, bool restart = true, bool print = true);
951
+#endif
952
+
953
+// deinterleave
954
+
955
+static void S9xDeinterleaveType1 (int size, uint8_t *base)
956
+{
957
+	//Settings.DisplayColor = BUILD_PIXEL(0, 31, 0);
958
+	//SET_UI_COLOR(0, 255, 0);
959
+
960
+	uint8_t	blocks[256];
961
+	int		nblocks = size >> 16;
962
+
963
+	for (int i = 0; i < nblocks; i++)
964
+	{
965
+		blocks[i * 2] = i + nblocks;
966
+		blocks[i * 2 + 1] = i;
967
+	}
968
+
969
+	uint8_t	*tmp = (uint8_t *) malloc(0x8000);
970
+	if (tmp)
971
+	{
972
+		for (int i = 0; i < nblocks * 2; i++)
973
+		{
974
+			for (int j = i; j < nblocks * 2; j++)
975
+			{
976
+				if (blocks[j] == i)
977
+				{
978
+					memmove(tmp, &base[blocks[j] * 0x8000], 0x8000);
979
+					memmove(&base[blocks[j] * 0x8000], &base[blocks[i] * 0x8000], 0x8000);
980
+					memmove(&base[blocks[i] * 0x8000], tmp, 0x8000);
981
+					uint8_t	b = blocks[j];
982
+					blocks[j] = blocks[i];
983
+					blocks[i] = b;
984
+					break;
985
+				}
986
+			}
987
+		}
988
+
989
+		free(tmp);
990
+	}
991
+}
992
+
993
+static void S9xDeinterleaveType2 (int size, uint8_t *base)
994
+{
995
+	// for odd Super FX images
996
+	//Settings.DisplayColor = BUILD_PIXEL(31, 14, 6);
997
+	//SET_UI_COLOR(255, 119, 25);
998
+
999
+	uint8_t	blocks[256];
1000
+	int		nblocks = size >> 16;
1001
+	int		step = 64;
1002
+
1003
+	while (nblocks <= step)
1004
+		step >>= 1;
1005
+	nblocks = step;
1006
+
1007
+	for (int i = 0; i < nblocks * 2; i++)
1008
+		blocks[i] = (i & ~0xf) | ((i & 3) << 2) | ((i & 12) >> 2);
1009
+
1010
+	uint8_t	*tmp = (uint8_t *) malloc(0x10000);
1011
+	if (tmp)
1012
+	{
1013
+		for (int i = 0; i < nblocks * 2; i++)
1014
+		{
1015
+			for (int j = i; j < nblocks * 2; j++)
1016
+			{
1017
+				if (blocks[j] == i)
1018
+				{
1019
+					memmove(tmp, &base[blocks[j] * 0x10000], 0x10000);
1020
+					memmove(&base[blocks[j] * 0x10000], &base[blocks[i] * 0x10000], 0x10000);
1021
+					memmove(&base[blocks[i] * 0x10000], tmp, 0x10000);
1022
+					uint8_t	b = blocks[j];
1023
+					blocks[j] = blocks[i];
1024
+					blocks[i] = b;
1025
+					break;
1026
+				}
1027
+			}
1028
+		}
1029
+
1030
+		free(tmp);
1031
+	}
1032
+}
1033
+
1034
+static void S9xDeinterleaveGD24 (int size, uint8_t *base)
1035
+{
1036
+	// for 24Mb images dumped with Game Doctor
1037
+	if (size != 0x300000)
1038
+		return;
1039
+
1040
+	//Settings.DisplayColor = BUILD_PIXEL(0, 31, 31);
1041
+	//SET_UI_COLOR(0, 255, 255);
1042
+
1043
+	uint8_t	*tmp = (uint8_t *) malloc(0x80000);
1044
+	if (tmp)
1045
+	{
1046
+		memmove(tmp, &base[0x180000], 0x80000);
1047
+		memmove(&base[0x180000], &base[0x200000], 0x80000);
1048
+		memmove(&base[0x200000], &base[0x280000], 0x80000);
1049
+		memmove(&base[0x280000], tmp, 0x80000);
1050
+
1051
+		free(tmp);
1052
+
1053
+		S9xDeinterleaveType1(size, base);
1054
+	}
1055
+}
1056
+
1057
+// allocation and deallocation
1058
+
1059
+bool CMemory::Init()
1060
+{
1061
+    RAM	 = (uint8_t *) malloc(0x20000);
1062
+    SRAM = (uint8_t *) malloc(0x20000);
1063
+    VRAM = (uint8_t *) malloc(0x10000);
1064
+    ROM  = (uint8_t *) malloc(MAX_ROM_SIZE + 0x200 + 0x8000);
1065
+
1066
+	IPPU.TileCache[TILE_2BIT]       = (uint8_t *) malloc(MAX_2BIT_TILES * 64);
1067
+	IPPU.TileCache[TILE_4BIT]       = (uint8_t *) malloc(MAX_4BIT_TILES * 64);
1068
+	IPPU.TileCache[TILE_8BIT]       = (uint8_t *) malloc(MAX_8BIT_TILES * 64);
1069
+	IPPU.TileCache[TILE_2BIT_EVEN]  = (uint8_t *) malloc(MAX_2BIT_TILES * 64);
1070
+	IPPU.TileCache[TILE_2BIT_ODD]   = (uint8_t *) malloc(MAX_2BIT_TILES * 64);
1071
+	IPPU.TileCache[TILE_4BIT_EVEN]  = (uint8_t *) malloc(MAX_4BIT_TILES * 64);
1072
+	IPPU.TileCache[TILE_4BIT_ODD]   = (uint8_t *) malloc(MAX_4BIT_TILES * 64);
1073
+
1074
+	IPPU.TileCached[TILE_2BIT]      = (uint8_t *) malloc(MAX_2BIT_TILES);
1075
+	IPPU.TileCached[TILE_4BIT]      = (uint8_t *) malloc(MAX_4BIT_TILES);
1076
+	IPPU.TileCached[TILE_8BIT]      = (uint8_t *) malloc(MAX_8BIT_TILES);
1077
+	IPPU.TileCached[TILE_2BIT_EVEN] = (uint8_t *) malloc(MAX_2BIT_TILES);
1078
+	IPPU.TileCached[TILE_2BIT_ODD]  = (uint8_t *) malloc(MAX_2BIT_TILES);
1079
+	IPPU.TileCached[TILE_4BIT_EVEN] = (uint8_t *) malloc(MAX_4BIT_TILES);
1080
+	IPPU.TileCached[TILE_4BIT_ODD]  = (uint8_t *) malloc(MAX_4BIT_TILES);
1081
+
1082
+	if (!RAM || !SRAM || !VRAM || !ROM ||
1083
+		!IPPU.TileCache[TILE_2BIT]       ||
1084
+		!IPPU.TileCache[TILE_4BIT]       ||
1085
+		!IPPU.TileCache[TILE_8BIT]       ||
1086
+		!IPPU.TileCache[TILE_2BIT_EVEN]  ||
1087
+		!IPPU.TileCache[TILE_2BIT_ODD]   ||
1088
+		!IPPU.TileCache[TILE_4BIT_EVEN]  ||
1089
+		!IPPU.TileCache[TILE_4BIT_ODD]   ||
1090
+		!IPPU.TileCached[TILE_2BIT]      ||
1091
+		!IPPU.TileCached[TILE_4BIT]      ||
1092
+		!IPPU.TileCached[TILE_8BIT]      ||
1093
+		!IPPU.TileCached[TILE_2BIT_EVEN] ||
1094
+		!IPPU.TileCached[TILE_2BIT_ODD]  ||
1095
+		!IPPU.TileCached[TILE_4BIT_EVEN] ||
1096
+		!IPPU.TileCached[TILE_4BIT_ODD])
1097
+    {
1098
+		Deinit();
1099
+		return false;
1100
+    }
1101
+
1102
+	ZeroMemory(RAM,  0x20000);
1103
+	ZeroMemory(SRAM, 0x20000);
1104
+	ZeroMemory(VRAM, 0x10000);
1105
+	ZeroMemory(ROM,  MAX_ROM_SIZE + 0x200 + 0x8000);
1106
+
1107
+	ZeroMemory(IPPU.TileCache[TILE_2BIT],       MAX_2BIT_TILES * 64);
1108
+	ZeroMemory(IPPU.TileCache[TILE_4BIT],       MAX_4BIT_TILES * 64);
1109
+	ZeroMemory(IPPU.TileCache[TILE_8BIT],       MAX_8BIT_TILES * 64);
1110
+	ZeroMemory(IPPU.TileCache[TILE_2BIT_EVEN],  MAX_2BIT_TILES * 64);
1111
+	ZeroMemory(IPPU.TileCache[TILE_2BIT_ODD],   MAX_2BIT_TILES * 64);
1112
+	ZeroMemory(IPPU.TileCache[TILE_4BIT_EVEN],  MAX_4BIT_TILES * 64);
1113
+	ZeroMemory(IPPU.TileCache[TILE_4BIT_ODD],   MAX_4BIT_TILES * 64);
1114
+
1115
+	ZeroMemory(IPPU.TileCached[TILE_2BIT],      MAX_2BIT_TILES);
1116
+	ZeroMemory(IPPU.TileCached[TILE_4BIT],      MAX_4BIT_TILES);
1117
+	ZeroMemory(IPPU.TileCached[TILE_8BIT],      MAX_8BIT_TILES);
1118
+	ZeroMemory(IPPU.TileCached[TILE_2BIT_EVEN], MAX_2BIT_TILES);
1119
+	ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD],  MAX_2BIT_TILES);
1120
+	ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES);
1121
+	ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD],  MAX_4BIT_TILES);
1122
+
1123
+	// FillRAM uses first 32K of ROM image area, otherwise space just
1124
+	// wasted. Might be read by the SuperFX code.
1125
+
1126
+	FillRAM = ROM;
1127
+
1128
+	// Add 0x8000 to ROM image pointer to stop SuperFX code accessing
1129
+	// unallocated memory (can cause crash on some ports).
1130
+
1131
+	ROM += 0x8000;
1132
+
1133
+	C4RAM   = ROM + 0x400000 + 8192 * 8; // C4
1134
+	OBC1RAM = ROM + 0x400000; // OBC1
1135
+	BIOSROM = ROM + 0x300000; // BS
1136
+	BSRAM   = ROM + 0x400000; // BS
1137
+
1138
+	/*SuperFX.pvRegisters = FillRAM + 0x3000;
1139
+	SuperFX.nRamBanks   = 2; // Most only use 1.  1=64KB=512Mb, 2=128KB=1024Mb
1140
+	SuperFX.pvRam       = SRAM;
1141
+	SuperFX.nRomBanks   = (2 * 1024 * 1024) / (32 * 1024);
1142
+	SuperFX.pvRom       = (uint8_t *) ROM;*/
1143
+
1144
+	PostRomInitFunc = NULL;
1145
+
1146
+	return true;
1147
+}
1148
+
1149
+void CMemory::Deinit()
1150
+{
1151
+	if (RAM)
1152
+	{
1153
+		free(RAM);
1154
+		RAM = NULL;
1155
+	}
1156
+
1157
+	if (SRAM)
1158
+	{
1159
+		free(SRAM);
1160
+		SRAM = NULL;
1161
+	}
1162
+
1163
+	if (VRAM)
1164
+	{
1165
+		free(VRAM);
1166
+		VRAM = NULL;
1167
+	}
1168
+
1169
+	if (ROM)
1170
+	{
1171
+		ROM -= 0x8000;
1172
+		free(ROM);
1173
+		ROM = NULL;
1174
+	}
1175
+
1176
+	for (int t = 0; t < 7; t++)
1177
+	{
1178
+		if (IPPU.TileCache[t])
1179
+		{
1180
+			free(IPPU.TileCache[t]);
1181
+			IPPU.TileCache[t] = NULL;
1182
+		}
1183
+
1184
+		if (IPPU.TileCached[t])
1185
+		{
1186
+			free(IPPU.TileCached[t]);
1187
+			IPPU.TileCached[t] = NULL;
1188
+		}
1189
+	}
1190
+
1191
+	Safe(NULL);
1192
+	SafeANK(NULL);
1193
+}
1194
+
1195
+// file management and ROM detection
1196
+
1197
+static bool allASCII (uint8_t *b, int size)
1198
+{
1199
+	for (int i = 0; i < size; i++)
1200
+	{
1201
+		if (b[i] < 32 || b[i] > 126)
1202
+			return false;
1203
+	}
1204
+
1205
+	return true;
1206
+}
1207
+
1208
+/*static bool is_SufamiTurbo_BIOS (uint8_t *data, uint32_t size)
1209
+{
1210
+	if (size == 0x40000 &&
1211
+		strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) == 0)
1212
+		return true;
1213
+	else
1214
+		return false;
1215
+}*/
1216
+
1217
+/*static bool is_SufamiTurbo_Cart (uint8_t *data, uint32_t size)
1218
+{
1219
+	if (size >= 0x80000 && size <= 0x100000 &&
1220
+		strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) != 0)
1221
+		return true;
1222
+	else
1223
+		return false;
1224
+}*/
1225
+
1226
+/*static bool is_SameGame_BIOS (uint8_t *data, uint32_t size)
1227
+{
1228
+	if (size == 0x100000 && strncmp((char *) (data + 0xffc0), "Same Game Tsume Game", 20) == 0)
1229
+		return true;
1230
+	else
1231
+		return false;
1232
+}*/
1233
+
1234
+/*static bool is_SameGame_Add_On (uint8_t *data, uint32_t size)
1235
+{
1236
+	if (size == 0x80000)
1237
+		return true;
1238
+	else
1239
+		return false;
1240
+}*/
1241
+
1242
+int CMemory::ScoreHiROM (bool skip_header, int32_t romoff)
1243
+{
1244
+	uint8_t	*buf = ROM + 0xff00 + romoff + (skip_header ? 0x200 : 0);
1245
+	int		score = 0;
1246
+
1247
+	if (buf[0xd5] & 0x1)
1248
+		score += 2;
1249
+
1250
+	// Mode23 is SA-1
1251
+	if (buf[0xd5] == 0x23)
1252
+		score -= 2;
1253
+
1254
+	if (buf[0xd4] == 0x20)
1255
+		score += 2;
1256
+
1257
+	if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff)
1258
+	{
1259
+		score += 2;
1260
+		if (0 != (buf[0xde] + (buf[0xdf] << 8)))
1261
+			score++;
1262
+	}
1263
+
1264
+	if (buf[0xda] == 0x33)
1265
+		score += 2;
1266
+
1267
+	if ((buf[0xd5] & 0xf) < 4)
1268
+		score += 2;
1269
+
1270
+	if (!(buf[0xfd] & 0x80))
1271
+		score -= 6;
1272
+
1273
+	if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0)
1274
+		score -= 2; // reduced after looking at a scan by Cowering
1275
+
1276
+	if (CalculatedSize > 1024 * 1024 * 3)
1277
+		score += 4;
1278
+
1279
+	if ((1 << (buf[0xd7] - 7)) > 48)
1280
+		score -= 1;
1281
+
1282
+	if (!allASCII(&buf[0xb0], 6))
1283
+		score -= 1;
1284
+
1285
+	if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1))
1286
+		score -= 1;
1287
+
1288
+	return score;
1289
+}
1290
+
1291
+int CMemory::ScoreLoROM (bool skip_header, int32_t romoff)
1292
+{
1293
+	uint8_t	*buf = ROM + 0x7f00 + romoff + (skip_header ? 0x200 : 0);
1294
+	int		score = 0;
1295
+
1296
+	if (!(buf[0xd5] & 0x1))
1297
+		score += 3;
1298
+
1299
+	// Mode23 is SA-1
1300
+	if (buf[0xd5] == 0x23)
1301
+		score += 2;
1302
+
1303
+	if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff)
1304
+	{
1305
+		score += 2;
1306
+		if (0 != (buf[0xde] + (buf[0xdf] << 8)))
1307
+			score++;
1308
+	}
1309
+
1310
+	if (buf[0xda] == 0x33)
1311
+		score += 2;
1312
+
1313
+	if ((buf[0xd5] & 0xf) < 4)
1314
+		score += 2;
1315
+
1316
+	if (!(buf[0xfd] & 0x80))
1317
+		score -= 6;
1318
+
1319
+	if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0)
1320
+		score -= 2; // reduced per Cowering suggestion
1321
+
1322
+	if (CalculatedSize <= 1024 * 1024 * 16)
1323
+		score += 2;
1324
+
1325
+	if ((1 << (buf[0xd7] - 7)) > 48)
1326
+		score -= 1;
1327
+
1328
+	if (!allASCII(&buf[0xb0], 6))
1329
+		score -= 1;
1330
+
1331
+	if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1))
1332
+		score -= 1;
1333
+
1334
+	return score;
1335
+}
1336
+
1337
+/*uint32_t CMemory::HeaderRemove (uint32_t size, int32_t &headerCount, uint8_t *buf)
1338
+{
1339
+	uint32_t	calc_size = (size / 0x2000) * 0x2000;
1340
+
1341
+	if ((size - calc_size == 512 && !Settings.ForceNoHeader) || Settings.ForceHeader)
1342
+	{
1343
+		uint8_t	*NSRTHead = buf + 0x1D0; // NSRT Header Location
1344
+
1345
+		// detect NSRT header
1346
+		if (!strncmp("NSRT", (char *) &NSRTHead[24], 4))
1347
+		{
1348
+			if (NSRTHead[28] == 22)
1349
+			{
1350
+				if (((std::accumulate(NSRTHead, NSRTHead + sizeof(NSRTHeader), 0) & 0xFF) == NSRTHead[30]) &&
1351
+					(NSRTHead[30] + NSRTHead[31] == 255) && ((NSRTHead[0] & 0x0F) <= 13) &&
1352
+					(((NSRTHead[0] & 0xF0) >> 4) <= 3) && ((NSRTHead[0] & 0xF0) >> 4))
1353
+					memcpy(NSRTHeader, NSRTHead, sizeof(NSRTHeader));
1354
+			}
1355
+		}
1356
+
1357
+		memmove(buf, buf + 512, calc_size);
1358
+		headerCount++;
1359
+		size -= 512;
1360
+	}
1361
+
1362
+	return size;
1363
+}*/
1364
+
1365
+/*uint32_t CMemory::FileLoader (uint8_t *buffer, const char *filename, int32_t maxsize)
1366
+{
1367
+	// <- ROM size without header
1368
+	// ** Memory.HeaderCount
1369
+	// ** Memory.ROMFilename
1370
+
1371
+	int32_t	totalSize = 0;
1372
+    char	fname[PATH_MAX + 1];
1373
+    char	drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], name[_MAX_FNAME + 1], exts[_MAX_EXT + 1];
1374
+	char	*ext;
1375
+
1376
+#if defined(_WIN32) || defined(__MACOSX__)
1377
+	ext = &exts[1];
1378
+#else
1379
+	ext = &exts[0];
1380
+#endif
1381
+
1382
+	memset(NSRTHeader, 0, sizeof(NSRTHeader));
1383
+	HeaderCount = 0;
1384
+
1385
+	_splitpath(filename, drive, dir, name, exts);
1386
+	_makepath(fname, drive, dir, name, exts);
1387
+
1388
+	int	nFormat = FILE_DEFAULT;
1389
+	if (strcasecmp(ext, "zip") == 0)
1390
+		nFormat = FILE_ZIP;
1391
+	else
1392
+	if (strcasecmp(ext, "jma") == 0)
1393
+		nFormat = FILE_JMA;
1394
+
1395
+	switch (nFormat)
1396
+	{
1397
+		case FILE_ZIP:
1398
+		{
1399
+		#ifdef UNZIP_SUPPORT
1400
+			if (!LoadZip(fname, &totalSize, &HeaderCount, buffer))
1401
+			{
1402
+			 	S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid Zip archive.");
1403
+				return 0;
1404
+			}
1405
+
1406
+			strcpy(ROMFilename, fname);
1407
+		#else
1408
+			//S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with Zip support.");
1409
+			return 0;
1410
+		#endif
1411
+			break;
1412
+		}
1413
+
1414
+		case FILE_JMA:
1415
+		{
1416
+		#ifdef JMA_SUPPORT
1417
+			size_t	size = load_jma_file(fname, buffer);
1418
+			if (!size)
1419
+			{
1420
+			 	S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid JMA archive.");
1421
+				return 0;
1422
+			}
1423
+
1424
+			totalSize = HeaderRemove(size, HeaderCount, buffer);
1425
+
1426
+			strcpy(ROMFilename, fname);
1427
+		#else
1428
+			//S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with JMA support.");
1429
+			return 0;
1430
+		#endif
1431
+			break;
1432
+		}
1433
+
1434
+		case FILE_DEFAULT:
1435
+		default:
1436
+		{
1437
+			STREAM	fp = OPEN_STREAM(fname, "rb");
1438
+			if (!fp)
1439
+				return 0;
1440
+
1441
+			strcpy(ROMFilename, fname);
1442
+
1443
+			int 	len  = 0;
1444
+			uint32_t	size = 0;
1445
+			bool	more = false;
1446
+			uint8_t	*ptr = buffer;
1447
+
1448
+			do
1449
+			{
1450
+				size = READ_STREAM(ptr, maxsize + 0x200 - (ptr - buffer), fp);
1451
+				CLOSE_STREAM(fp);
1452
+
1453
+				size = HeaderRemove(size, HeaderCount, ptr);
1454
+				totalSize += size;
1455
+				ptr += size;
1456
+
1457
+				// check for multi file roms
1458
+				if (ptr - buffer < maxsize + 0x200 &&
1459
+					(isdigit(ext[0]) && ext[1] == 0 && ext[0] < '9'))
1460
+				{
1461
+					more = true;
1462
+					ext[0]++;
1463
+					_makepath(fname, drive, dir, name, exts);
1464
+				}
1465
+				else
1466
+				if (ptr - buffer < maxsize + 0x200 &&
1467
+					(((len = strlen(name)) == 7 || len == 8) &&
1468
+					strncasecmp(name, "sf", 2) == 0 &&
1469
+					isdigit(name[2]) && isdigit(name[3]) && isdigit(name[4]) && isdigit(name[5]) &&
1470
+					isalpha(name[len - 1])))
1471
+				{
1472
+					more = true;
1473
+					name[len - 1]++;
1474
+					_makepath(fname, drive, dir, name, exts);
1475
+				}
1476
+				else
1477
+					more = false;
1478
+
1479
+			}	while (more && (fp = OPEN_STREAM(fname, "rb")) != NULL);
1480
+
1481
+			break;
1482
+		}
1483
+	}
1484
+
1485
+    if (HeaderCount == 0)
1486
+		S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found.");
1487
+    else
1488
+    if (HeaderCount == 1)
1489
+		S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found ROM file header (and ignored it).");
1490
+	else
1491
+		S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found multiple ROM file headers (and ignored them).");
1492
+
1493
+	return (uint32_t) totalSize;
1494
+}*/
1495
+
1496
+//bool CMemory::LoadROM (const char *filename)
1497
+bool CMemory::LoadROMSNSF(const unsigned char *lrombuf, int32_t lromsize, const unsigned char *srambuf, int32_t sramsize)
1498
+{
1499
+	int	retry_count = 0;
1500
+
1501
+	/*if (!filename || !*filename)
1502
+		return false;*/
1503
+
1504
+	ZeroMemory(ROM, MAX_ROM_SIZE);
1505
+	ZeroMemory(&Multi, sizeof(Multi));
1506
+
1507
+again:
1508
+	//Settings.DisplayColor = BUILD_PIXEL(31, 31, 31);
1509
+	//SET_UI_COLOR(255, 255, 255);
1510
+
1511
+	CalculatedSize = 0;
1512
+	ExtendedFormat = NOPE;
1513
+
1514
+	int32_t totalFileSize;
1515
+
1516
+	//totalFileSize = FileLoader(ROM, filename, MAX_ROM_SIZE);
1517
+	totalFileSize  = std::min<int32_t>(MAX_ROM_SIZE, lromsize);
1518
+	if (!totalFileSize)
1519
+		return false;
1520
+	memcpy(ROM, lrombuf, totalFileSize);
1521
+	SNESGameFixes.SRAMInitialValue = 0xff;
1522
+	memset(SRAM, SNESGameFixes.SRAMInitialValue, 0x20000);
1523
+	if (srambuf && sramsize)
1524
+		memcpy(SRAM, srambuf, sramsize);
1525
+
1526
+	/*if (!Settings.NoPatch)
1527
+		CheckForAnyPatch(filename, HeaderCount != 0, totalFileSize);*/
1528
+
1529
+	int	hi_score, lo_score;
1530
+
1531
+	hi_score = ScoreHiROM(false);
1532
+	lo_score = ScoreLoROM(false);
1533
+
1534
+	if (HeaderCount == 0 && !Settings.ForceNoHeader &&
1535
+		((hi_score >  lo_score && ScoreHiROM(true) > hi_score) ||
1536
+		 (hi_score <= lo_score && ScoreLoROM(true) > lo_score)))
1537
+	{
1538
+		memmove(ROM, ROM + 512, totalFileSize - 512);
1539
+		totalFileSize -= 512;
1540
+		//S9xMessage(S9X_INFO, S9X_HEADER_WARNING, "Try 'force no-header' option if the game doesn't work");
1541
+		// modifying ROM, so we need to rescore
1542
+		hi_score = ScoreHiROM(false);
1543
+		lo_score = ScoreLoROM(false);
1544
+	}
1545
+
1546
+	CalculatedSize = (totalFileSize / 0x2000) * 0x2000;
1547
+
1548
+	if (CalculatedSize > 0x400000 &&
1549
+		(ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x4332 && // exclude S-DD1
1550
+		(ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x4532 &&
1551
+		(ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF93a && // exclude SPC7110
1552
+		(ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF53a)
1553
+		ExtendedFormat = YEAH;
1554
+
1555
+	// if both vectors are invalid, it's type 1 interleaved LoROM
1556
+	if (ExtendedFormat == NOPE &&
1557
+		((ROM[0x7ffc] + (ROM[0x7ffd] << 8)) < 0x8000) &&
1558
+		((ROM[0xfffc] + (ROM[0xfffd] << 8)) < 0x8000))
1559
+	{
1560
+		if (!Settings.ForceInterleaved && !Settings.ForceNotInterleaved)
1561
+			S9xDeinterleaveType1(totalFileSize, ROM);
1562
+	}
1563
+
1564
+	// CalculatedSize is now set, so rescore
1565
+	hi_score = ScoreHiROM(false);
1566
+	lo_score = ScoreLoROM(false);
1567
+
1568
+	uint8_t	*RomHeader = ROM;
1569
+
1570
+	if (ExtendedFormat != NOPE)
1571
+	{
1572
+		int	swappedhirom, swappedlorom;
1573
+
1574
+		swappedhirom = ScoreHiROM(false, 0x400000);
1575
+		swappedlorom = ScoreLoROM(false, 0x400000);
1576
+
1577
+		// set swapped here
1578
+		if (std::max(swappedlorom, swappedhirom) >= std::max(lo_score, hi_score))
1579
+		{
1580
+			ExtendedFormat = BIGFIRST;
1581
+			hi_score = swappedhirom;
1582
+			lo_score = swappedlorom;
1583
+			RomHeader += 0x400000;
1584
+		}
1585
+		else
1586
+			ExtendedFormat = SMALLFIRST;
1587
+	}
1588
+
1589
+	bool	interleaved, tales = false;
1590
+
1591
+    interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2 || Settings.ForceInterleaveGD24;
1592
+
1593
+	if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score))
1594
+	{
1595
+		LoROM = true;
1596
+		HiROM = false;
1597
+
1598
+		// ignore map type byte if not 0x2x or 0x3x
1599
+		if ((RomHeader[0x7fd5] & 0xf0) == 0x20 || (RomHeader[0x7fd5] & 0xf0) == 0x30)
1600
+		{
1601
+			switch (RomHeader[0x7fd5] & 0xf)
1602
+			{
1603
+				case 1:
1604
+					interleaved = true;
1605
+					break;
1606
+
1607
+				case 5:
1608
+					interleaved = true;
1609
+					tales = true;
1610
+					break;
1611
+			}
1612
+		}
1613
+	}
1614
+	else
1615
+	{
1616
+		LoROM = false;
1617
+		HiROM = true;
1618
+
1619
+		if ((RomHeader[0xffd5] & 0xf0) == 0x20 || (RomHeader[0xffd5] & 0xf0) == 0x30)
1620
+		{
1621
+			switch (RomHeader[0xffd5] & 0xf)
1622
+			{
1623
+				case 0:
1624
+				case 3:
1625
+					interleaved = true;
1626
+					break;
1627
+			}
1628
+		}
1629
+	}
1630
+
1631
+	// this two games fail to be detected
1632
+	if (!Settings.ForceHiROM && !Settings.ForceLoROM)
1633
+	{
1634
+		if (strncmp((char *) &ROM[0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0 ||
1635
+		   (strncmp((char *) &ROM[0xffc0], "BATMAN--REVENGE JOKER",  21) == 0))
1636
+		{
1637
+			LoROM = true;
1638
+			HiROM = false;
1639
+			interleaved = false;
1640
+			tales = false;
1641
+		}
1642
+	}
1643
+
1644
+	if (!Settings.ForceNotInterleaved && interleaved)
1645
+	{
1646
+		//S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "ROM image is in interleaved format - converting...");
1647
+
1648
+		if (tales)
1649
+		{
1650
+			if (ExtendedFormat == BIGFIRST)
1651
+			{
1652
+				S9xDeinterleaveType1(0x400000, ROM);
1653
+				S9xDeinterleaveType1(CalculatedSize - 0x400000, ROM + 0x400000);
1654
+			}
1655
+			else
1656
+			{
1657
+				S9xDeinterleaveType1(CalculatedSize - 0x400000, ROM);
1658
+				S9xDeinterleaveType1(0x400000, ROM + CalculatedSize - 0x400000);
1659
+			}
1660
+
1661
+			LoROM = false;
1662
+			HiROM = true;
1663
+		}
1664
+		else
1665
+		if (Settings.ForceInterleaveGD24 && CalculatedSize == 0x300000)
1666
+		{
1667
+			bool	t = LoROM;
1668
+			LoROM = HiROM;
1669
+			HiROM = t;
1670
+			S9xDeinterleaveGD24(CalculatedSize, ROM);
1671
+		}
1672
+		else
1673
+		if (Settings.ForceInterleaved2)
1674
+			S9xDeinterleaveType2(CalculatedSize, ROM);
1675
+		else
1676
+		{
1677
+			bool	t = LoROM;
1678
+			LoROM = HiROM;
1679
+			HiROM = t;
1680
+			S9xDeinterleaveType1(CalculatedSize, ROM);
1681
+		}
1682
+
1683
+		hi_score = ScoreHiROM(false);
1684
+		lo_score = ScoreLoROM(false);
1685
+
1686
+		if ((HiROM && (lo_score >= hi_score || hi_score < 0)) ||
1687
+			(LoROM && (hi_score >  lo_score || lo_score < 0)))
1688
+		{
1689
+			if (retry_count == 0)
1690
+			{
1691
+				//S9xMessage(S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO, "ROM lied about its type! Trying again.");
1692
+				Settings.ForceNotInterleaved = true;
1693
+				Settings.ForceInterleaved = false;
1694
+				retry_count++;
1695
+				goto again;
1696
+			}
1697
+		}
1698
+    }
1699
+
1700
+	if (ExtendedFormat == SMALLFIRST)
1701
+		tales = true;
1702
+
1703
+	if (tales)
1704
+	{
1705
+		uint8_t	*tmp = (uint8_t *) malloc(CalculatedSize - 0x400000);
1706
+		if (tmp)
1707
+		{
1708
+			//S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "Fixing swapped ExHiROM...");
1709
+			memmove(tmp, ROM, CalculatedSize - 0x400000);
1710
+			memmove(ROM, ROM + CalculatedSize - 0x400000, 0x400000);
1711
+			memmove(ROM + 0x400000, tmp, CalculatedSize - 0x400000);
1712
+			free(tmp);
1713
+		}
1714
+	}
1715
+
1716
+	/*if (strncmp(LastRomFilename, filename, PATH_MAX + 1))
1717
+	{
1718
+		strncpy(LastRomFilename, filename, PATH_MAX + 1);
1719
+		LastRomFilename[PATH_MAX] = 0;
1720
+	}*/
1721
+
1722
+	ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes));
1723
+	SNESGameFixes.SRAMInitialValue = 0x60;
1724
+
1725
+	//S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
1726
+
1727
+	InitROM();
1728
+
1729
+	/*S9xInitCheatData();
1730
+	S9xApplyCheats();*/
1731
+
1732
+	S9xReset();
1733
+
1734
+    return true;
1735
+}
1736
+
1737
+/*bool CMemory::LoadMultiCart (const char *cartA, const char *cartB)
1738
+{
1739
+	bool	r = true;
1740
+
1741
+	ZeroMemory(ROM, MAX_ROM_SIZE);
1742
+	ZeroMemory(&Multi, sizeof(Multi));
1743
+
1744
+	Settings.DisplayColor = BUILD_PIXEL(31, 31, 31);
1745
+	SET_UI_COLOR(255, 255, 255);
1746
+
1747
+	CalculatedSize = 0;
1748
+	ExtendedFormat = NOPE;
1749
+
1750
+	if (cartA && cartA[0])
1751
+		Multi.cartSizeA = FileLoader(ROM, cartA, MAX_ROM_SIZE);
1752
+
1753
+	if (Multi.cartSizeA == 0)
1754
+	{
1755
+		if (cartB && cartB[0])
1756
+			Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE);
1757
+	}
1758
+
1759
+	if (Multi.cartSizeA)
1760
+	{
1761
+		if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeA))
1762
+			Multi.cartType = 4;
1763
+		else
1764
+		if (is_SameGame_BIOS(ROM, Multi.cartSizeA))
1765
+			Multi.cartType = 3;
1766
+	}
1767
+	else
1768
+	if (Multi.cartSizeB)
1769
+	{
1770
+		if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeB))
1771
+			Multi.cartType = 4;
1772
+	}
1773
+	else
1774
+		Multi.cartType = 4; // assuming BIOS only
1775
+
1776
+	switch (Multi.cartType)
1777
+	{
1778
+		case 4:
1779
+			r = LoadSufamiTurbo(cartA, cartB);
1780
+			break;
1781
+
1782
+		case 3:
1783
+			r = LoadSameGame(cartA, cartB);
1784
+			break;
1785
+
1786
+		default:
1787
+			r = false;
1788
+	}
1789
+
1790
+	if (!r)
1791
+	{
1792
+		ZeroMemory(&Multi, sizeof(Multi));
1793
+		return false;
1794
+	}
1795
+
1796
+	ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes));
1797
+	SNESGameFixes.SRAMInitialValue = 0x60;
1798
+
1799
+	S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
1800
+
1801
+	InitROM();
1802
+
1803
+	S9xInitCheatData();
1804
+	S9xApplyCheats();
1805
+
1806
+	S9xReset();
1807
+
1808
+	return true;
1809
+}
1810
+
1811
+bool CMemory::LoadSufamiTurbo (const char *cartA, const char *cartB)
1812
+{
1813
+	Multi.cartOffsetA = 0x100000;
1814
+	Multi.cartOffsetB = 0x200000;
1815
+	Multi.sramA = SRAM;
1816
+	Multi.sramB = SRAM + 0x10000;
1817
+
1818
+	if (Multi.cartSizeA)
1819
+	{
1820
+		Multi.sramSizeA = 4; // ROM[0x37]?
1821
+		Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0;
1822
+
1823
+		if (!Settings.NoPatch)
1824
+			CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA);
1825
+
1826
+		strcpy(Multi.fileNameA, cartA);
1827
+		memcpy(ROM + Multi.cartOffsetA, ROM, Multi.cartSizeA);
1828
+	}
1829
+
1830
+	if (Multi.cartSizeA && !Multi.cartSizeB)
1831
+	{
1832
+		if (cartB && cartB[0])
1833
+			Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE);
1834
+
1835
+		if (Multi.cartSizeB)
1836
+		{
1837
+			if (!is_SufamiTurbo_Cart(ROM, Multi.cartSizeB))
1838
+				Multi.cartSizeB = 0;
1839
+		}
1840
+	}
1841
+
1842
+	if (Multi.cartSizeB)
1843
+	{
1844
+		Multi.sramSizeB = 4; // ROM[0x37]?
1845
+		Multi.sramMaskB = Multi.sramSizeB ? ((1 << (Multi.sramSizeB + 3)) * 128 - 1) : 0;
1846
+
1847
+		if (!Settings.NoPatch)
1848
+			CheckForAnyPatch(cartB, HeaderCount != 0, Multi.cartSizeB);
1849
+
1850
+		strcpy(Multi.fileNameB, cartB);
1851
+		memcpy(ROM + Multi.cartOffsetB, ROM, Multi.cartSizeB);
1852
+	}
1853
+
1854
+	FILE	*fp;
1855
+	size_t	size;
1856
+	char	path[PATH_MAX + 1];
1857
+
1858
+	strcpy(path, S9xGetDirectory(BIOS_DIR));
1859
+	strcat(path, SLASH_STR);
1860
+	strcat(path, "STBIOS.bin");
1861
+
1862
+	fp = fopen(path, "rb");
1863
+	if (fp)
1864
+	{
1865
+		size = fread((void *) ROM, 1, 0x40000, fp);
1866
+		fclose(fp);
1867
+		if (!is_SufamiTurbo_BIOS(ROM, size))
1868
+			return false;
1869
+	}
1870
+	else
1871
+		return false;
1872
+
1873
+	if (Multi.cartSizeA)
1874
+		strcpy(ROMFilename, Multi.fileNameA);
1875
+	else
1876
+	if (Multi.cartSizeB)
1877
+		strcpy(ROMFilename, Multi.fileNameB);
1878
+	else
1879
+		strcpy(ROMFilename, path);
1880
+
1881
+	LoROM = true;
1882
+	HiROM = false;
1883
+	CalculatedSize = 0x40000;
1884
+
1885
+	return true;
1886
+}
1887
+
1888
+bool CMemory::LoadSameGame (const char *cartA, const char *cartB)
1889
+{
1890
+	Multi.cartOffsetA = 0;
1891
+	Multi.cartOffsetB = 0x200000;
1892
+	Multi.sramA = SRAM;
1893
+	Multi.sramB = NULL;
1894
+
1895
+	Multi.sramSizeA = ROM[0xffd8];
1896
+	Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0;
1897
+	Multi.sramSizeB = 0;
1898
+	Multi.sramMaskB = 0;
1899
+
1900
+	if (!Settings.NoPatch)
1901
+		CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA);
1902
+
1903
+	strcpy(Multi.fileNameA, cartA);
1904
+
1905
+	if (cartB && cartB[0])
1906
+		Multi.cartSizeB = FileLoader(ROM + Multi.cartOffsetB, cartB, MAX_ROM_SIZE - Multi.cartOffsetB);
1907
+
1908
+	if (Multi.cartSizeB)
1909
+	{
1910
+		if (!is_SameGame_Add_On(ROM + Multi.cartOffsetB, Multi.cartSizeB))
1911
+			Multi.cartSizeB = 0;
1912
+		else
1913
+			strcpy(Multi.fileNameB, cartB);
1914
+	}
1915
+
1916
+	strcpy(ROMFilename, Multi.fileNameA);
1917
+
1918
+	LoROM = false;
1919
+	HiROM = true;
1920
+	CalculatedSize = Multi.cartSizeA;
1921
+
1922
+	return true;
1923
+}
1924
+
1925
+bool CMemory::LoadSRTC()
1926
+{
1927
+	FILE	*fp;
1928
+	size_t	ignore;
1929
+
1930
+	fp = fopen(S9xGetFilename(".rtc", SRAM_DIR), "rb");
1931
+	if (!fp)
1932
+		return false;
1933
+
1934
+	ignore = fread(RTCData.reg, 1, 20, fp);
1935
+	fclose(fp);
1936
+
1937
+	return true;
1938
+}
1939
+
1940
+bool CMemory::SaveSRTC()
1941
+{
1942
+	FILE	*fp;
1943
+	size_t	ignore;
1944
+
1945
+	fp = fopen(S9xGetFilename(".rtc", SRAM_DIR), "wb");
1946
+	if (!fp)
1947
+		return false;
1948
+
1949
+	ignore = fwrite(RTCData.reg, 1, 20, fp);
1950
+	fclose(fp);
1951
+
1952
+	return true;
1953
+}
1954
+
1955
+void CMemory::ClearSRAM (bool onlyNonSavedSRAM)
1956
+{
1957
+	if (onlyNonSavedSRAM)
1958
+		if (!(Settings.SuperFX && ROMType < 0x15) && !(Settings.SA1 && ROMType == 0x34)) // can have SRAM
1959
+			return;
1960
+
1961
+	memset(SRAM, SNESGameFixes.SRAMInitialValue, 0x20000);
1962
+}
1963
+
1964
+bool CMemory::LoadSRAM (const char *filename)
1965
+{
1966
+	FILE	*file;
1967
+	int		size, len;
1968
+	char	sramName[PATH_MAX + 1];
1969
+
1970
+	strcpy(sramName, filename);
1971
+
1972
+	ClearSRAM();
1973
+
1974
+	if (Multi.cartType && Multi.sramSizeB)
1975
+	{
1976
+		char	temp[PATH_MAX + 1];
1977
+
1978
+		strcpy(temp, ROMFilename);
1979
+		strcpy(ROMFilename, Multi.fileNameB);
1980
+
1981
+		size = (1 << (Multi.sramSizeB + 3)) * 128;
1982
+
1983
+		file = fopen(S9xGetFilename(".srm", SRAM_DIR), "rb");
1984
+		if (file)
1985
+		{
1986
+			len = fread((char *) Multi.sramB, 1, 0x10000, file);
1987
+			fclose(file);
1988
+			if (len - size == 512)
1989
+				memmove(Multi.sramB, Multi.sramB + 512, size);
1990
+		}
1991
+
1992
+		strcpy(ROMFilename, temp);
1993
+	}
1994
+
1995
+	size = SRAMSize ? (1 << (SRAMSize + 3)) * 128 : 0;
1996
+	if (size > 0x20000)
1997
+		size = 0x20000;
1998
+
1999
+	if (size)
2000
+	{
2001
+		file = fopen(sramName, "rb");
2002
+		if (file)
2003
+		{
2004
+			len = fread((char *) SRAM, 1, 0x20000, file);
2005
+			fclose(file);
2006
+			if (len - size == 512)
2007
+				memmove(SRAM, SRAM + 512, size);
2008
+
2009
+			if (Settings.SRTC || Settings.SPC7110RTC)
2010
+				LoadSRTC();
2011
+
2012
+			return true;
2013
+		}
2014
+		else
2015
+		if (Settings.BS && !Settings.BSXItself)
2016
+		{
2017
+			// The BS game's SRAM was not found
2018
+			// Try to read BS-X.srm instead
2019
+			char	path[PATH_MAX + 1];
2020
+
2021
+			strcpy(path, S9xGetDirectory(SRAM_DIR));
2022
+			strcat(path, SLASH_STR);
2023
+			strcat(path, "BS-X.srm");
2024
+
2025
+			file = fopen(path, "rb");
2026
+			if (file)
2027
+			{
2028
+				len = fread((char *) SRAM, 1, 0x20000, file);
2029
+				fclose(file);
2030
+				if (len - size == 512)
2031
+					memmove(SRAM, SRAM + 512, size);
2032
+
2033
+				S9xMessage(S9X_INFO, S9X_ROM_INFO, "The SRAM file wasn't found: BS-X.srm was read instead.");
2034
+				return true;
2035
+			}
2036
+			else
2037
+			{
2038
+				S9xMessage(S9X_INFO, S9X_ROM_INFO, "The SRAM file wasn't found, BS-X.srm wasn't found either.");
2039
+				return false;
2040
+			}
2041
+		}
2042
+
2043
+		return false;
2044
+	}
2045
+
2046
+	return true;
2047
+}
2048
+
2049
+bool CMemory::SaveSRAM (const char *filename)
2050
+{
2051
+	if (Settings.SuperFX && ROMType < 0x15) // doesn't have SRAM
2052
+		return true;
2053
+
2054
+	if (Settings.SA1 && ROMType == 0x34)    // doesn't have SRAM
2055
+		return true;
2056
+
2057
+	FILE	*file;
2058
+	int		size;
2059
+	char	sramName[PATH_MAX + 1];
2060
+
2061
+	strcpy(sramName, filename);
2062
+
2063
+	if (Multi.cartType && Multi.sramSizeB)
2064
+	{
2065
+		char	name[PATH_MAX + 1], temp[PATH_MAX + 1];
2066
+
2067
+		strcpy(temp, ROMFilename);
2068
+		strcpy(ROMFilename, Multi.fileNameB);
2069
+		strcpy(name, S9xGetFilename(".srm", SRAM_DIR));
2070
+
2071
+		size = (1 << (Multi.sramSizeB + 3)) * 128;
2072
+
2073
+		file = fopen(name, "wb");
2074
+		if (file)
2075
+		{
2076
+			size_t	ignore;
2077
+			ignore = fwrite((char *) Multi.sramB, size, 1, file);
2078
+			fclose(file);
2079
+		#ifdef __linux
2080
+			ignore = chown(name, getuid(), getgid());
2081
+		#endif
2082
+		}
2083
+
2084
+		strcpy(ROMFilename, temp);
2085
+    }
2086
+
2087
+    size = SRAMSize ? (1 << (SRAMSize + 3)) * 128 : 0;
2088
+	if (size > 0x20000)
2089
+		size = 0x20000;
2090
+
2091
+	if (size)
2092
+	{
2093
+		file = fopen(sramName, "wb");
2094
+		if (file)
2095
+		{
2096
+			size_t	ignore;
2097
+			ignore = fwrite((char *) SRAM, size, 1, file);
2098
+			fclose(file);
2099
+		#ifdef __linux
2100
+			ignore = chown(sramName, getuid(), getgid());
2101
+		#endif
2102
+
2103
+			if (Settings.SRTC || Settings.SPC7110RTC)
2104
+				SaveSRTC();
2105
+
2106
+			return true;
2107
+		}
2108
+	}
2109
+
2110
+	return false;
2111
+}*/
2112
+
2113
+// initialization
2114
+
2115
+static uint32_t caCRC32 (uint8_t *array, uint32_t size, uint32_t crc32 = 0xffffffff)
2116
+{
2117
+	for (uint32_t i = 0; i < size; i++)
2118
+		crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ array[i]) & 0xFF];
2119
+
2120
+	return ~crc32;
2121
+}
2122
+
2123
+char * CMemory::Safe (const char *s)
2124
+{
2125
+	static char	*safe = NULL;
2126
+	static int	safe_len = 0;
2127
+
2128
+	if (s == NULL)
2129
+	{
2130
+		if (safe)
2131
+		{
2132
+			free(safe);
2133
+			safe = NULL;
2134
+		}
2135
+
2136
+		return NULL;
2137
+	}
2138
+
2139
+	int	len = strlen(s);
2140
+	if (!safe || len + 1 > safe_len)
2141
+	{
2142
+		if (safe)
2143
+			free(safe);
2144
+
2145
+		safe_len = len + 1;
2146
+		safe = (char *) malloc(safe_len);
2147
+	}
2148
+
2149
+	for (int i = 0; i < len; i++)
2150
+	{
2151
+		if (s[i] >= 32 && s[i] < 127)
2152
+			safe[i] = s[i];
2153
+		else
2154
+			safe[i] = '_';
2155
+	}
2156
+
2157
+	safe[len] = 0;
2158
+
2159
+	return safe;
2160
+}
2161
+
2162
+char * CMemory::SafeANK (const char *s)
2163
+{
2164
+	static char	*safe = NULL;
2165
+	static int	safe_len = 0;
2166
+
2167
+	if (s == NULL)
2168
+	{
2169
+		if (safe)
2170
+		{
2171
+			free(safe);
2172
+			safe = NULL;
2173
+		}
2174
+
2175
+		return NULL;
2176
+	}
2177
+
2178
+	int	len = strlen(s);
2179
+	if (!safe || len + 1 > safe_len)
2180
+	{
2181
+		if (safe)
2182
+			free(safe);
2183
+
2184
+		safe_len = len + 1;
2185
+		safe = (char *) malloc(safe_len);
2186
+	}
2187
+
2188
+	for (int i = 0; i < len; i++)
2189
+	{
2190
+		if (s[i] >= 32 && s[i] < 127) // ASCII
2191
+			safe [i] = s[i];
2192
+		else
2193
+		if (ROMRegion == 0 && ((uint8_t) s[i] >= 0xa0 && (uint8_t) s[i] < 0xe0)) // JIS X 201 - Katakana
2194
+			safe [i] = s[i];
2195
+		else
2196
+			safe [i] = '_';
2197
+	}
2198
+
2199
+	safe [len] = 0;
2200
+
2201
+	return safe;
2202
+}
2203
+
2204
+void CMemory::ParseSNESHeader (uint8_t *RomHeader)
2205
+{
2206
+	bool	bs = Settings.BS & !Settings.BSXItself;
2207
+
2208
+	strncpy(ROMName, (char *) &RomHeader[0x10], ROM_NAME_LEN - 1);
2209
+	if (bs)
2210
+		memset(ROMName + 16, 0x20, ROM_NAME_LEN - 17);
2211
+
2212
+	if (bs)
2213
+	{
2214
+		if (!(((RomHeader[0x29] & 0x20) && CalculatedSize <  0x100000) ||
2215
+			 (!(RomHeader[0x29] & 0x20) && CalculatedSize == 0x100000)))
2216
+			printf("BS: Size mismatch\n");
2217
+
2218
+		// FIXME
2219
+		int	p = 0;
2220
+		while ((1 << p) < (int) CalculatedSize)
2221
+			p++;
2222
+		ROMSize = p - 10;
2223
+	}
2224
+	else
2225
+		ROMSize = RomHeader[0x27];
2226
+
2227
+	SRAMSize  = bs ? 5 /* BS-X */    : RomHeader[0x28];
2228
+	ROMSpeed  = bs ? RomHeader[0x28] : RomHeader[0x25];
2229
+	ROMType   = bs ? 0xE5 /* BS-X */ : RomHeader[0x26];
2230
+	ROMRegion = bs ? 0               : RomHeader[0x29];
2231
+
2232
+	ROMChecksum           = RomHeader[0x2E] + (RomHeader[0x2F] << 8);
2233
+	ROMComplementChecksum = RomHeader[0x2C] + (RomHeader[0x2D] << 8);
2234
+
2235
+	memmove(ROMId, &RomHeader[0x02], 4);
2236
+
2237
+	if (RomHeader[0x2A] != 0x33)
2238
+		CompanyId = ((RomHeader[0x2A] >> 4) & 0x0F) * 36 + (RomHeader[0x2A] & 0x0F);
2239
+	else
2240
+	if (isalnum(RomHeader[0x00]) && isalnum(RomHeader[0x01]))
2241
+	{
2242
+		int	l, r, l2, r2;
2243
+		l = toupper(RomHeader[0x00]);
2244
+		r = toupper(RomHeader[0x01]);
2245
+		l2 = (l > '9') ? l - '7' : l - '0';
2246
+		r2 = (r > '9') ? r - '7' : r - '0';
2247
+		CompanyId = l2 * 36 + r2;
2248
+	}
2249
+}
2250
+
2251
+void CMemory::InitROM()
2252
+{
2253
+	Settings.SuperFX = false;
2254
+	Settings.DSP = 0;
2255
+	Settings.SA1 = false;
2256
+	Settings.C4 = false;
2257
+	Settings.SDD1 = false;
2258
+	Settings.SPC7110 = false;
2259
+	Settings.SPC7110RTC = false;
2260
+	Settings.OBC1 = false;
2261
+	Settings.SETA = 0;
2262
+	Settings.SRTC = false;
2263
+	Settings.BS = false;
2264
+
2265
+	//SuperFX.nRomBanks = CalculatedSize >> 15;
2266
+
2267
+	//// Parse ROM header and read ROM informatoin
2268
+
2269
+	CompanyId = -1;
2270
+	memset(ROMId, 0, 5);
2271
+
2272
+	uint8_t	*RomHeader = ROM + 0x7FB0;
2273
+	if (ExtendedFormat == BIGFIRST)
2274
+		RomHeader += 0x400000;
2275
+	if (HiROM)
2276
+		RomHeader += 0x8000;
2277
+
2278
+	//S9xInitBSX(); // Set BS header before parsing
2279
+
2280
+	ParseSNESHeader(RomHeader);
2281
+
2282
+	//// Detect and initialize chips
2283
+	//// detection codes are compatible with NSRT
2284
+
2285
+	// DSP1/2/3/4
2286
+	if (ROMType == 0x03)
2287
+	{
2288
+		if (ROMSpeed == 0x30)
2289
+			Settings.DSP = 4; // DSP4
2290
+		else
2291
+			Settings.DSP = 1; // DSP1
2292
+	}
2293
+	else
2294
+	if (ROMType == 0x05)
2295
+	{
2296
+		if (ROMSpeed == 0x20)
2297
+			Settings.DSP = 2; // DSP2
2298
+		else
2299
+		if (ROMSpeed == 0x30 && RomHeader[0x2a] == 0xb2)
2300
+			Settings.DSP = 3; // DSP3
2301
+		else
2302
+			Settings.DSP = 1; // DSP1
2303
+	}
2304
+
2305
+	/*switch (Settings.DSP)
2306
+	{
2307
+		case 1:	// DSP1
2308
+			if (HiROM)
2309
+			{
2310
+				DSP0.boundary = 0x7000;
2311
+				DSP0.maptype = M_DSP1_HIROM;
2312
+			}
2313
+			else
2314
+			if (CalculatedSize > 0x100000)
2315
+			{
2316
+				DSP0.boundary = 0x4000;
2317
+				DSP0.maptype = M_DSP1_LOROM_L;
2318
+			}
2319
+			else
2320
+			{
2321
+				DSP0.boundary = 0xc000;
2322
+				DSP0.maptype = M_DSP1_LOROM_S;
2323
+			}
2324
+
2325
+			SetDSP = &DSP1SetByte;
2326
+			GetDSP = &DSP1GetByte;
2327
+			break;
2328
+
2329
+		case 2: // DSP2
2330
+			DSP0.boundary = 0x10000;
2331
+			DSP0.maptype = M_DSP2_LOROM;
2332
+			SetDSP = &DSP2SetByte;
2333
+			GetDSP = &DSP2GetByte;
2334
+			break;
2335
+
2336
+		case 3: // DSP3
2337
+			DSP0.boundary = 0xc000;
2338
+			DSP0.maptype = M_DSP3_LOROM;
2339
+			SetDSP = &DSP3SetByte;
2340
+			GetDSP = &DSP3GetByte;
2341
+			break;
2342
+
2343
+		case 4: // DSP4
2344
+			DSP0.boundary = 0xc000;
2345
+			DSP0.maptype = M_DSP4_LOROM;
2346
+			SetDSP = &DSP4SetByte;
2347
+			GetDSP = &DSP4GetByte;
2348
+			break;
2349
+
2350
+		default:
2351
+			SetDSP = NULL;
2352
+			GetDSP = NULL;
2353
+			break;
2354
+	}*/
2355
+
2356
+	uint32_t	identifier = ((ROMType & 0xff) << 8) + (ROMSpeed & 0xff);
2357
+
2358
+	switch (identifier)
2359
+	{
2360
+	    // SRTC
2361
+		/*case 0x5535:
2362
+			Settings.SRTC = true;
2363
+			S9xInitSRTC();
2364
+			break;
2365
+
2366
+		// SPC7110
2367
+		case 0xF93A:
2368
+			Settings.SPC7110RTC = true;
2369
+		case 0xF53A:
2370
+			Settings.SPC7110 = true;
2371
+			S9xInitSPC7110();
2372
+			break;
2373
+
2374
+		// OBC1
2375
+		case 0x2530:
2376
+			Settings.OBC1 = true;
2377
+			break;
2378
+
2379
+		// SA1
2380
+		case 0x3423:
2381
+		case 0x3523:
2382
+			Settings.SA1 = true;
2383
+			break;
2384
+
2385
+		// SuperFX
2386
+		case 0x1320:
2387
+		case 0x1420:
2388
+		case 0x1520:
2389
+		case 0x1A20:
2390
+			Settings.SuperFX = true;
2391
+			S9xInitSuperFX();
2392
+			if (ROM[0x7FDA] == 0x33)
2393
+				SRAMSize = ROM[0x7FBD];
2394
+			else
2395
+				SRAMSize = 5;
2396
+			break;*/
2397
+
2398
+		// SDD1
2399
+		case 0x4332:
2400
+		case 0x4532:
2401
+			Settings.SDD1 = true;
2402
+			break;
2403
+
2404
+		// ST018
2405
+		/*case 0xF530:
2406
+			Settings.SETA = ST_018;
2407
+			SetSETA = NULL;
2408
+			GetSETA = NULL;
2409
+			SRAMSize = 2;
2410
+			SNESGameFixes.SRAMInitialValue = 0x00;
2411
+			break;
2412
+
2413
+		// ST010/011
2414
+		case 0xF630:
2415
+			if (ROM[0x7FD7] == 0x09)
2416
+			{
2417
+				Settings.SETA = ST_011;
2418
+				SetSETA = &S9xSetST011;
2419
+				GetSETA = &S9xGetST011;
2420
+			}
2421
+			else
2422
+			{
2423
+				Settings.SETA = ST_010;
2424
+				SetSETA = &S9xSetST010;
2425
+				GetSETA = &S9xGetST010;
2426
+			}
2427
+
2428
+			SRAMSize = 2;
2429
+			SNESGameFixes.SRAMInitialValue = 0x00;
2430
+			break;
2431
+
2432
+		// C4
2433
+		case 0xF320:
2434
+			Settings.C4 = true;
2435
+			break;*/
2436
+	}
2437
+
2438
+	//// Map memory and calculate checksum
2439
+
2440
+	Map_Initialize();
2441
+	CalculatedChecksum = 0;
2442
+
2443
+	if (HiROM)
2444
+    {
2445
+		if (Settings.BS)
2446
+			/* Do nothing */;
2447
+		else
2448
+		/*if (Settings.SPC7110)
2449
+			Map_SPC7110HiROMMap();
2450
+		else*/
2451
+		if (ExtendedFormat != NOPE)
2452
+			Map_ExtendedHiROMMap();
2453
+		/*else
2454
+		if (Multi.cartType == 3)
2455
+			Map_SameGameHiROMMap();*/
2456
+		else
2457
+			Map_HiROMMap();
2458
+    }
2459
+    else
2460
+    {
2461
+		if (Settings.BS)
2462
+			/* Do nothing */;
2463
+		else
2464
+		/*if (Settings.SETA && Settings.SETA != ST_018)
2465
+			Map_SetaDSPLoROMMap();
2466
+		else
2467
+		if (Settings.SuperFX)
2468
+			Map_SuperFXLoROMMap();
2469
+		else
2470
+		if (Settings.SA1)
2471
+			Map_SA1LoROMMap();
2472
+		else*/
2473
+		if (Settings.SDD1)
2474
+			Map_SDD1LoROMMap();
2475
+		else
2476
+		if (ExtendedFormat != NOPE)
2477
+			Map_JumboLoROMMap();
2478
+		else
2479
+		if (strncmp(ROMName, "WANDERERS FROM YS", 17) == 0)
2480
+			Map_NoMAD1LoROMMap();
2481
+		else
2482
+		if (strncmp(ROMName, "SOUND NOVEL-TCOOL", 17) == 0 ||
2483
+			strncmp(ROMName, "DERBY STALLION 96", 17) == 0)
2484
+			Map_ROM24MBSLoROMMap();
2485
+		else
2486
+		if (strncmp(ROMName, "THOROUGHBRED BREEDER3", 21) == 0 ||
2487
+			strncmp(ROMName, "RPG-TCOOL 2", 11) == 0)
2488
+			Map_SRAM512KLoROMMap();
2489
+		/*else
2490
+		if (strncmp(ROMName, "ADD-ON BASE CASSETE", 19) == 0)
2491
+		{
2492
+			if (Multi.cartType == 4)
2493
+			{
2494
+				SRAMSize = Multi.sramSizeA;
2495
+				Map_SufamiTurboLoROMMap();
2496
+			}
2497
+			else
2498
+			{
2499
+				SRAMSize = 5;
2500
+				Map_SufamiTurboPseudoLoROMMap();
2501
+			}
2502
+		}*/
2503
+		else
2504
+			Map_LoROMMap();
2505
+    }
2506
+
2507
+	Checksum_Calculate();
2508
+
2509
+	bool isChecksumOK = (ROMChecksum + ROMComplementChecksum == 0xffff) &
2510
+						 (ROMChecksum == CalculatedChecksum);
2511
+
2512
+	//// Build more ROM information
2513
+
2514
+	// CRC32
2515
+	if (!Settings.BS || Settings.BSXItself) // Not BS Dump
2516
+		ROMCRC32 = caCRC32(ROM, CalculatedSize);
2517
+	else // Convert to correct format before scan
2518
+	{
2519
+		int offset = HiROM ? 0xffc0 : 0x7fc0;
2520
+		// Backup
2521
+		uint8_t BSMagic0 = ROM[offset + 22],
2522
+			  BSMagic1 = ROM[offset + 23];
2523
+		// uCONSRT standard
2524
+		ROM[offset + 22] = 0x42;
2525
+		ROM[offset + 23] = 0x00;
2526
+		// Calc
2527
+		ROMCRC32 = caCRC32(ROM, CalculatedSize);
2528
+		// Convert back
2529
+		ROM[offset + 22] = BSMagic0;
2530
+		ROM[offset + 23] = BSMagic1;
2531
+	}
2532
+
2533
+	// NTSC/PAL
2534
+	if (Settings.ForceNTSC)
2535
+		Settings.PAL = false;
2536
+	else
2537
+	if (Settings.ForcePAL)
2538
+		Settings.PAL = true;
2539
+	else
2540
+	if (!Settings.BS && (ROMRegion >= 2) && (ROMRegion <= 12))
2541
+		Settings.PAL = true;
2542
+	else
2543
+		Settings.PAL = false;
2544
+
2545
+	if (Settings.PAL)
2546
+	{
2547
+		Settings.FrameTime = Settings.FrameTimePAL;
2548
+		ROMFramesPerSecond = 50;
2549
+	}
2550
+	else
2551
+	{
2552
+		Settings.FrameTime = Settings.FrameTimeNTSC;
2553
+		ROMFramesPerSecond = 60;
2554
+	}
2555
+
2556
+	// truncate cart name
2557
+	ROMName[ROM_NAME_LEN - 1] = 0;
2558
+	if (strlen(ROMName))
2559
+	{
2560
+		char *p = ROMName + strlen(ROMName);
2561
+		if (p > ROMName + 21 && ROMName[20] == ' ')
2562
+			p = ROMName + 21;
2563
+		while (p > ROMName && *(p - 1) == ' ')
2564
+			p--;
2565
+		*p = 0;
2566
+	}
2567
+
2568
+	// SRAM size
2569
+	SRAMMask = SRAMSize ? ((1 << (SRAMSize + 3)) * 128) - 1 : 0;
2570
+
2571
+	// checksum
2572
+	/*if (!isChecksumOK || ((uint32_t) CalculatedSize > (uint32_t) (((1 << (ROMSize - 7)) * 128) * 1024)))
2573
+	{
2574
+		Settings.DisplayColor = BUILD_PIXEL(31, 31, 0);
2575
+		SET_UI_COLOR(255, 255, 0);
2576
+	}*/
2577
+
2578
+	/*if (Multi.cartType == 4)
2579
+	{
2580
+		Settings.DisplayColor = BUILD_PIXEL(0, 16, 31);
2581
+		SET_UI_COLOR(0, 128, 255);
2582
+	}*/
2583
+
2584
+	//// Initialize emulation
2585
+
2586
+	Timings.H_Max_Master = SNES_CYCLES_PER_SCANLINE;
2587
+	Timings.H_Max        = Timings.H_Max_Master;
2588
+	Timings.HBlankStart  = SNES_HBLANK_START_HC;
2589
+	Timings.HBlankEnd    = SNES_HBLANK_END_HC;
2590
+	Timings.HDMAInit     = SNES_HDMA_INIT_HC;
2591
+	Timings.HDMAStart    = SNES_HDMA_START_HC;
2592
+	Timings.RenderPos    = SNES_RENDER_START_HC;
2593
+	Timings.V_Max_Master = Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER;
2594
+	Timings.V_Max        = Timings.V_Max_Master;
2595
+	/* From byuu: The total delay time for both the initial (H)DMA sync (to the DMA clock),
2596
+	   and the end (H)DMA sync (back to the last CPU cycle's mcycle rate (6, 8, or 12)) always takes between 12-24 mcycles.
2597
+	   Possible delays: { 12, 14, 16, 18, 20, 22, 24 }
2598
+	   XXX: Snes9x can't emulate this timing :( so let's use the average value... */
2599
+	Timings.DMACPUSync   = 18;
2600
+	/* If the CPU is halted (i.e. for DMA) while /NMI goes low, the NMI will trigger
2601
+	   after the DMA completes (even if /NMI goes high again before the DMA
2602
+	   completes). In this case, there is a 24-30 cycle delay between the end of DMA
2603
+	   and the NMI handler, time enough for an instruction or two. */
2604
+	// Wild Guns, Mighty Morphin Power Rangers - The Fighting Edition
2605
+	Timings.NMIDMADelay  = 24;
2606
+	Timings.IRQPendCount = 0;
2607
+
2608
+	IPPU.TotalEmulatedFrames = 0;
2609
+
2610
+	//// Hack games
2611
+
2612
+	ApplyROMFixes();
2613
+
2614
+	//// Show ROM information
2615
+	//char displayName[ROM_NAME_LEN];
2616
+
2617
+	strcpy(RawROMName, ROMName);
2618
+	//sprintf(displayName, "%s", SafeANK(ROMName));
2619
+	sprintf(ROMName, "%s", Safe(ROMName));
2620
+	sprintf(ROMId, "%s", Safe(ROMId));
2621
+
2622
+	/*sprintf(String, "\"%s\" [%s] %s, %s, %s, %s, SRAM:%s, ID:%s, CRC32:%08X",
2623
+		displayName, isChecksumOK ? "checksum ok" : ((Multi.cartType == 4) ? "no checksum" : "bad checksum"),
2624
+		MapType(), Size(), KartContents(), Settings.PAL ? "PAL" : "NTSC", StaticRAMSize(), ROMId, ROMCRC32);*/
2625
+	//S9xMessage(S9X_INFO, S9X_ROM_INFO, String);
2626
+
2627
+	Settings.ForceLoROM = false;
2628
+	Settings.ForceHiROM = false;
2629
+	Settings.ForceHeader = false;
2630
+	Settings.ForceNoHeader = false;
2631
+	Settings.ForceInterleaved = false;
2632
+	Settings.ForceInterleaved2 = false;
2633
+	Settings.ForceInterleaveGD24 = false;
2634
+	Settings.ForceNotInterleaved = false;
2635
+	Settings.ForcePAL = false;
2636
+	Settings.ForceNTSC = false;
2637
+
2638
+	Settings.TakeScreenshot = false;
2639
+
2640
+	/*if (stopMovie)
2641
+		S9xMovieStop(true);*/
2642
+
2643
+	if (PostRomInitFunc)
2644
+		PostRomInitFunc();
2645
+
2646
+    //S9xVerifyControllers();
2647
+}
2648
+
2649
+// memory map
2650
+
2651
+uint32_t CMemory::map_mirror (uint32_t size, uint32_t pos)
2652
+{
2653
+	// from bsnes
2654
+	if (size == 0)
2655
+		return 0;
2656
+	if (pos < size)
2657
+		return pos;
2658
+
2659
+	uint32_t	mask = 1 << 31;
2660
+	while (!(pos & mask))
2661
+		mask >>= 1;
2662
+
2663
+	if (size <= (pos & mask))
2664
+		return map_mirror(size, pos - mask);
2665
+	else
2666
+		return mask + map_mirror(size - mask, pos - mask);
2667
+}
2668
+
2669
+void CMemory::map_lorom (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size)
2670
+{
2671
+	uint32_t	c, i, p, addr;
2672
+
2673
+	for (c = bank_s; c <= bank_e; c++)
2674
+	{
2675
+		for (i = addr_s; i <= addr_e; i += 0x1000)
2676
+		{
2677
+			p = (c << 4) | (i >> 12);
2678
+			addr = (c & 0x7f) * 0x8000;
2679
+			Map[p] = ROM + map_mirror(size, addr) - (i & 0x8000);
2680
+			BlockIsROM[p] = true;
2681
+			BlockIsRAM[p] = false;
2682
+		}
2683
+	}
2684
+}
2685
+
2686
+void CMemory::map_hirom (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size)
2687
+{
2688
+	uint32_t	c, i, p, addr;
2689
+
2690
+	for (c = bank_s; c <= bank_e; c++)
2691
+	{
2692
+		for (i = addr_s; i <= addr_e; i += 0x1000)
2693
+		{
2694
+			p = (c << 4) | (i >> 12);
2695
+			addr = c << 16;
2696
+			Map[p] = ROM + map_mirror(size, addr);
2697
+			BlockIsROM[p] = true;
2698
+			BlockIsRAM[p] = false;
2699
+		}
2700
+	}
2701
+}
2702
+
2703
+void CMemory::map_lorom_offset (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size, uint32_t offset)
2704
+{
2705
+	uint32_t	c, i, p, addr;
2706
+
2707
+	for (c = bank_s; c <= bank_e; c++)
2708
+	{
2709
+		for (i = addr_s; i <= addr_e; i += 0x1000)
2710
+		{
2711
+			p = (c << 4) | (i >> 12);
2712
+			addr = ((c - bank_s) & 0x7f) * 0x8000;
2713
+			Map[p] = ROM + offset + map_mirror(size, addr) - (i & 0x8000);
2714
+			BlockIsROM[p] = true;
2715
+			BlockIsRAM[p] = false;
2716
+		}
2717
+	}
2718
+}
2719
+
2720
+void CMemory::map_hirom_offset (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size, uint32_t offset)
2721
+{
2722
+	uint32_t	c, i, p, addr;
2723
+
2724
+	for (c = bank_s; c <= bank_e; c++)
2725
+	{
2726
+		for (i = addr_s; i <= addr_e; i += 0x1000)
2727
+		{
2728
+			p = (c << 4) | (i >> 12);
2729
+			addr = (c - bank_s) << 16;
2730
+			Map[p] = ROM + offset + map_mirror(size, addr);
2731
+			BlockIsROM[p] = true;
2732
+			BlockIsRAM[p] = false;
2733
+		}
2734
+	}
2735
+}
2736
+
2737
+void CMemory::map_space (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint8_t *data)
2738
+{
2739
+	uint32_t	c, i, p;
2740
+
2741
+	for (c = bank_s; c <= bank_e; c++)
2742
+	{
2743
+		for (i = addr_s; i <= addr_e; i += 0x1000)
2744
+		{
2745
+			p = (c << 4) | (i >> 12);
2746
+			Map[p] = data;
2747
+			BlockIsROM[p] = false;
2748
+			BlockIsRAM[p] = true;
2749
+		}
2750
+	}
2751
+}
2752
+
2753
+void CMemory::map_index (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, int index, int type)
2754
+{
2755
+	uint32_t	c, i, p;
2756
+	bool	isROM, isRAM;
2757
+
2758
+	isROM = ((type == MAP_TYPE_I_O) || (type == MAP_TYPE_RAM)) ? false : true;
2759
+	isRAM = ((type == MAP_TYPE_I_O) || (type == MAP_TYPE_ROM)) ? false : true;
2760
+
2761
+	for (c = bank_s; c <= bank_e; c++)
2762
+	{
2763
+		for (i = addr_s; i <= addr_e; i += 0x1000)
2764
+		{
2765
+			p = (c << 4) | (i >> 12);
2766
+			Map[p] = (uint8_t *) index;
2767
+			BlockIsROM[p] = isROM;
2768
+			BlockIsRAM[p] = isRAM;
2769
+		}
2770
+	}
2771
+}
2772
+
2773
+void CMemory::map_System()
2774
+{
2775
+	// will be overwritten
2776
+	map_space(0x00, 0x3f, 0x0000, 0x1fff, RAM);
2777
+	map_index(0x00, 0x3f, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O);
2778
+	map_index(0x00, 0x3f, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O);
2779
+	map_space(0x80, 0xbf, 0x0000, 0x1fff, RAM);
2780
+	map_index(0x80, 0xbf, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O);
2781
+	map_index(0x80, 0xbf, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O);
2782
+}
2783
+
2784
+void CMemory::map_WRAM()
2785
+{
2786
+	// will overwrite others
2787
+	map_space(0x7e, 0x7e, 0x0000, 0xffff, RAM);
2788
+	map_space(0x7f, 0x7f, 0x0000, 0xffff, RAM + 0x10000);
2789
+}
2790
+
2791
+void CMemory::map_LoROMSRAM()
2792
+{
2793
+	map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
2794
+	map_index(0xf0, 0xff, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
2795
+}
2796
+
2797
+void CMemory::map_HiROMSRAM()
2798
+{
2799
+	map_index(0x20, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
2800
+	map_index(0xa0, 0xbf, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
2801
+}
2802
+
2803
+/*void CMemory::map_DSP()
2804
+{
2805
+	switch (DSP0.maptype)
2806
+	{
2807
+		case M_DSP1_LOROM_S:
2808
+			map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
2809
+			map_index(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
2810
+			break;
2811
+
2812
+		case M_DSP1_LOROM_L:
2813
+			map_index(0x60, 0x6f, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
2814
+			map_index(0xe0, 0xef, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
2815
+			break;
2816
+
2817
+		case M_DSP1_HIROM:
2818
+			map_index(0x00, 0x1f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
2819
+			map_index(0x80, 0x9f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
2820
+			break;
2821
+
2822
+		case M_DSP2_LOROM:
2823
+			map_index(0x20, 0x3f, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O);
2824
+			map_index(0x20, 0x3f, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O);
2825
+			map_index(0xa0, 0xbf, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O);
2826
+			map_index(0xa0, 0xbf, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O);
2827
+			break;
2828
+
2829
+		case M_DSP3_LOROM:
2830
+			map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
2831
+			map_index(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
2832
+			break;
2833
+
2834
+		case M_DSP4_LOROM:
2835
+			map_index(0x30, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
2836
+			map_index(0xb0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
2837
+			break;
2838
+	}
2839
+}*/
2840
+
2841
+/*void CMemory::map_C4()
2842
+{
2843
+	map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_C4, MAP_TYPE_I_O);
2844
+	map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_C4, MAP_TYPE_I_O);
2845
+}*/
2846
+
2847
+/*void CMemory::map_OBC1()
2848
+{
2849
+	map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_OBC_RAM, MAP_TYPE_I_O);
2850
+	map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_OBC_RAM, MAP_TYPE_I_O);
2851
+}*/
2852
+
2853
+/*void CMemory::map_SetaRISC()
2854
+{
2855
+	map_index(0x00, 0x3f, 0x3000, 0x3fff, MAP_SETA_RISC, MAP_TYPE_I_O);
2856
+	map_index(0x80, 0xbf, 0x3000, 0x3fff, MAP_SETA_RISC, MAP_TYPE_I_O);
2857
+}*/
2858
+
2859
+/*void CMemory::map_SetaDSP()
2860
+{
2861
+	// where does the SETA chip access, anyway?
2862
+	// please confirm this?
2863
+	map_index(0x68, 0x6f, 0x0000, 0x7fff, MAP_SETA_DSP, MAP_TYPE_RAM);
2864
+	// and this!
2865
+	map_index(0x60, 0x67, 0x0000, 0x3fff, MAP_SETA_DSP, MAP_TYPE_I_O);
2866
+
2867
+	// ST-0010:
2868
+	// map_index(0x68, 0x6f, 0x0000, 0x0fff, MAP_SETA_DSP, ?);
2869
+}*/
2870
+
2871
+void CMemory::map_WriteProtectROM()
2872
+{
2873
+	memmove((void *) WriteMap, (void *) Map, sizeof(Map));
2874
+
2875
+	for (int c = 0; c < 0x1000; c++)
2876
+	{
2877
+		if (BlockIsROM[c])
2878
+			WriteMap[c] = (uint8_t *) MAP_NONE;
2879
+	}
2880
+}
2881
+
2882
+void CMemory::Map_Initialize()
2883
+{
2884
+	for (int c = 0; c < 0x1000; c++)
2885
+	{
2886
+		Map[c]      = (uint8_t *) MAP_NONE;
2887
+		WriteMap[c] = (uint8_t *) MAP_NONE;
2888
+		BlockIsROM[c] = false;
2889
+		BlockIsRAM[c] = false;
2890
+	}
2891
+}
2892
+
2893
+void CMemory::Map_LoROMMap()
2894
+{
2895
+	printf("Map_LoROMMap\n");
2896
+	map_System();
2897
+
2898
+	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
2899
+	map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize);
2900
+	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
2901
+	map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
2902
+
2903
+	/*if (Settings.DSP)
2904
+		map_DSP();
2905
+	else
2906
+	if (Settings.C4)
2907
+		map_C4();
2908
+	else
2909
+	if (Settings.OBC1)
2910
+		map_OBC1();
2911
+	else
2912
+	if (Settings.SETA == ST_018)
2913
+		map_SetaRISC();*/
2914
+
2915
+    map_LoROMSRAM();
2916
+	map_WRAM();
2917
+
2918
+	map_WriteProtectROM();
2919
+}
2920
+
2921
+void CMemory::Map_NoMAD1LoROMMap()
2922
+{
2923
+	printf("Map_NoMAD1LoROMMap\n");
2924
+	map_System();
2925
+
2926
+	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
2927
+	map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize);
2928
+	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
2929
+	map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
2930
+
2931
+	map_index(0x70, 0x7f, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
2932
+	map_index(0xf0, 0xff, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
2933
+
2934
+	map_WRAM();
2935
+
2936
+	map_WriteProtectROM();
2937
+}
2938
+
2939
+void CMemory::Map_JumboLoROMMap()
2940
+{
2941
+	// XXX: Which game uses this?
2942
+	printf("Map_JumboLoROMMap\n");
2943
+	map_System();
2944
+
2945
+	map_lorom_offset(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize - 0x400000, 0x400000);
2946
+	map_lorom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize - 0x400000, 0x400000);
2947
+	map_lorom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0);
2948
+	map_lorom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0x200000);
2949
+
2950
+	map_LoROMSRAM();
2951
+	map_WRAM();
2952
+
2953
+	map_WriteProtectROM();
2954
+}
2955
+
2956
+void CMemory::Map_ROM24MBSLoROMMap()
2957
+{
2958
+	// PCB: BSC-1A5M-01, BSC-1A7M-10
2959
+	printf("Map_ROM24MBSLoROMMap\n");
2960
+	map_System();
2961
+
2962
+	map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x100000, 0);
2963
+	map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000);
2964
+	map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x100000, 0x200000);
2965
+	map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000);
2966
+
2967
+	map_LoROMSRAM();
2968
+	map_WRAM();
2969
+
2970
+	map_WriteProtectROM();
2971
+}
2972
+
2973
+void CMemory::Map_SRAM512KLoROMMap()
2974
+{
2975
+	printf("Map_SRAM512KLoROMMap\n");
2976
+	map_System();
2977
+
2978
+	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
2979
+	map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize);
2980
+	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
2981
+	map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
2982
+
2983
+	map_space(0x70, 0x70, 0x0000, 0xffff, SRAM);
2984
+	map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x8000);
2985
+	map_space(0x72, 0x72, 0x0000, 0xffff, SRAM + 0x10000);
2986
+	map_space(0x73, 0x73, 0x0000, 0xffff, SRAM + 0x18000);
2987
+
2988
+	map_WRAM();
2989
+
2990
+	map_WriteProtectROM();
2991
+}
2992
+
2993
+/*void CMemory::Map_SufamiTurboLoROMMap()
2994
+{
2995
+	printf("Map_SufamiTurboLoROMMap\n");
2996
+	map_System();
2997
+
2998
+	map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0);
2999
+	map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
3000
+	map_lorom_offset(0x40, 0x5f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
3001
+	map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x40000, 0);
3002
+	map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
3003
+	map_lorom_offset(0xc0, 0xdf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
3004
+
3005
+	if (Multi.sramSizeA)
3006
+	{
3007
+		map_index(0x60, 0x63, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
3008
+		map_index(0xe0, 0xe3, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
3009
+	}
3010
+
3011
+	if (Multi.sramSizeB)
3012
+	{
3013
+		map_index(0x70, 0x73, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM);
3014
+		map_index(0xf0, 0xf3, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM);
3015
+	}
3016
+
3017
+	map_WRAM();
3018
+
3019
+	map_WriteProtectROM();
3020
+}*/
3021
+
3022
+/*void CMemory::Map_SufamiTurboPseudoLoROMMap()
3023
+{
3024
+	// for combined images
3025
+	printf("Map_SufamiTurboPseudoLoROMMap\n");
3026
+	map_System();
3027
+
3028
+	map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0);
3029
+	map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000);
3030
+	map_lorom_offset(0x40, 0x5f, 0x8000, 0xffff, 0x100000, 0x200000);
3031
+	map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x40000, 0);
3032
+	map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000);
3033
+	map_lorom_offset(0xc0, 0xdf, 0x8000, 0xffff, 0x100000, 0x200000);
3034
+
3035
+	// I don't care :P
3036
+	map_space(0x60, 0x63, 0x8000, 0xffff, SRAM - 0x8000);
3037
+	map_space(0xe0, 0xe3, 0x8000, 0xffff, SRAM - 0x8000);
3038
+	map_space(0x70, 0x73, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000);
3039
+	map_space(0xf0, 0xf3, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000);
3040
+
3041
+	map_WRAM();
3042
+
3043
+	map_WriteProtectROM();
3044
+}*/
3045
+
3046
+/*void CMemory::Map_SuperFXLoROMMap()
3047
+{
3048
+	printf("Map_SuperFXLoROMMap\n");
3049
+	map_System();
3050
+
3051
+	// Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K
3052
+	// block is repeated twice in each 64K block.
3053
+	for (int c = 0; c < 64; c++)
3054
+	{
3055
+		memmove(&ROM[0x200000 + c * 0x10000], &ROM[c * 0x8000], 0x8000);
3056
+		memmove(&ROM[0x208000 + c * 0x10000], &ROM[c * 0x8000], 0x8000);
3057
+	}
3058
+
3059
+	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
3060
+	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
3061
+
3062
+	map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize, 0);
3063
+	map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0);
3064
+
3065
+	map_space(0x00, 0x3f, 0x6000, 0x7fff, SRAM - 0x6000);
3066
+	map_space(0x80, 0xbf, 0x6000, 0x7fff, SRAM - 0x6000);
3067
+	map_space(0x70, 0x70, 0x0000, 0xffff, SRAM);
3068
+	map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x10000);
3069
+
3070
+	map_WRAM();
3071
+
3072
+	map_WriteProtectROM();
3073
+}*/
3074
+
3075
+/*void CMemory::Map_SetaDSPLoROMMap()
3076
+{
3077
+	printf("Map_SetaDSPLoROMMap\n");
3078
+	map_System();
3079
+
3080
+	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
3081
+	map_lorom(0x40, 0x7f, 0x8000, 0xffff, CalculatedSize);
3082
+	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
3083
+	map_lorom(0xc0, 0xff, 0x8000, 0xffff, CalculatedSize);
3084
+
3085
+	map_SetaDSP();
3086
+
3087
+    map_LoROMSRAM();
3088
+	map_WRAM();
3089
+
3090
+	map_WriteProtectROM();
3091
+}*/
3092
+
3093
+void CMemory::Map_SDD1LoROMMap()
3094
+{
3095
+	printf("Map_SDD1LoROMMap\n");
3096
+	map_System();
3097
+
3098
+	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
3099
+	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
3100
+
3101
+	map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize, 0);
3102
+	map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0); // will be overwritten dynamically
3103
+
3104
+	map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
3105
+
3106
+	map_WRAM();
3107
+
3108
+	map_WriteProtectROM();
3109
+}
3110
+
3111
+/*void CMemory::Map_SA1LoROMMap()
3112
+{
3113
+	printf("Map_SA1LoROMMap\n");
3114
+	map_System();
3115
+
3116
+	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
3117
+	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
3118
+
3119
+	map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0);
3120
+
3121
+	map_space(0x00, 0x3f, 0x3000, 0x3fff, FillRAM);
3122
+	map_space(0x80, 0xbf, 0x3000, 0x3fff, FillRAM);
3123
+	map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O);
3124
+	map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O);
3125
+
3126
+	for (int c = 0x40; c < 0x80; c++)
3127
+		map_space(c, c, 0x0000, 0xffff, SRAM + (c & 1) * 0x10000);
3128
+
3129
+	map_WRAM();
3130
+
3131
+	map_WriteProtectROM();
3132
+
3133
+	// Now copy the map and correct it for the SA1 CPU.
3134
+	memmove((void *) SA1.Map, (void *) Map, sizeof(Map));
3135
+	memmove((void *) SA1.WriteMap, (void *) WriteMap, sizeof(WriteMap));
3136
+
3137
+	// SA-1 Banks 00->3f and 80->bf
3138
+	for (int c = 0x000; c < 0x400; c += 0x10)
3139
+	{
3140
+		SA1.Map[c + 0] = SA1.Map[c + 0x800] = FillRAM + 0x3000;
3141
+		SA1.Map[c + 1] = SA1.Map[c + 0x801] = (uint8_t *) MAP_NONE;
3142
+		SA1.WriteMap[c + 0] = SA1.WriteMap[c + 0x800] = FillRAM + 0x3000;
3143
+		SA1.WriteMap[c + 1] = SA1.WriteMap[c + 0x801] = (uint8_t *) MAP_NONE;
3144
+	}
3145
+
3146
+	// SA-1 Banks 60->6f
3147
+	for (int c = 0x600; c < 0x700; c++)
3148
+		SA1.Map[c] = SA1.WriteMap[c] = (uint8_t *) MAP_BWRAM_BITMAP;
3149
+
3150
+	BWRAM = SRAM;
3151
+}*/
3152
+
3153
+void CMemory::Map_HiROMMap()
3154
+{
3155
+	printf("Map_HiROMMap\n");
3156
+	map_System();
3157
+
3158
+	map_hirom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
3159
+	map_hirom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize);
3160
+	map_hirom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
3161
+	map_hirom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
3162
+
3163
+	/*if (Settings.DSP)
3164
+		map_DSP();*/
3165
+
3166
+	map_HiROMSRAM();
3167
+	map_WRAM();
3168
+
3169
+	map_WriteProtectROM();
3170
+}
3171
+
3172
+void CMemory::Map_ExtendedHiROMMap()
3173
+{
3174
+	printf("Map_ExtendedHiROMMap\n");
3175
+	map_System();
3176
+
3177
+	map_hirom_offset(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize - 0x400000, 0x400000);
3178
+	map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize - 0x400000, 0x400000);
3179
+	map_hirom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0);
3180
+	map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0);
3181
+
3182
+	map_HiROMSRAM();
3183
+	map_WRAM();
3184
+
3185
+	map_WriteProtectROM();
3186
+}
3187
+
3188
+/*void CMemory::Map_SameGameHiROMMap()
3189
+{
3190
+	printf("Map_SameGameHiROMMap\n");
3191
+	map_System();
3192
+
3193
+	map_hirom_offset(0x00, 0x1f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
3194
+	map_hirom_offset(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
3195
+	map_hirom_offset(0x40, 0x5f, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
3196
+	map_hirom_offset(0x60, 0x7f, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
3197
+	map_hirom_offset(0x80, 0x9f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
3198
+	map_hirom_offset(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
3199
+	map_hirom_offset(0xc0, 0xdf, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
3200
+	map_hirom_offset(0xe0, 0xff, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
3201
+
3202
+	map_HiROMSRAM();
3203
+	map_WRAM();
3204
+
3205
+	map_WriteProtectROM();
3206
+}*/
3207
+
3208
+/*void CMemory::Map_SPC7110HiROMMap()
3209
+{
3210
+	printf("Map_SPC7110HiROMMap\n");
3211
+	map_System();
3212
+
3213
+	map_index(0x00, 0x00, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
3214
+	map_hirom(0x00, 0x0f, 0x8000, 0xffff, CalculatedSize);
3215
+	map_index(0x30, 0x30, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
3216
+	map_index(0x50, 0x50, 0x0000, 0xffff, MAP_SPC7110_DRAM, MAP_TYPE_ROM);
3217
+	map_hirom(0x80, 0x8f, 0x8000, 0xffff, CalculatedSize);
3218
+	map_hirom_offset(0xc0, 0xcf, 0x0000, 0xffff, CalculatedSize, 0);
3219
+	map_index(0xd0, 0xff, 0x0000, 0xffff, MAP_SPC7110_ROM,  MAP_TYPE_ROM);
3220
+
3221
+	map_WRAM();
3222
+
3223
+	map_WriteProtectROM();
3224
+}*/
3225
+
3226
+// checksum
3227
+
3228
+uint16_t CMemory::checksum_calc_sum (uint8_t *data, uint32_t length)
3229
+{
3230
+	uint16_t	sum = 0;
3231
+
3232
+	for (uint32_t i = 0; i < length; i++)
3233
+		sum += data[i];
3234
+
3235
+	return sum;
3236
+}
3237
+
3238
+uint16_t CMemory::checksum_mirror_sum (uint8_t *start, uint32_t &length, uint32_t mask)
3239
+{
3240
+	// from NSRT
3241
+	while (!(length & mask))
3242
+		mask >>= 1;
3243
+
3244
+	uint16_t	part1 = checksum_calc_sum(start, mask);
3245
+	uint16_t	part2 = 0;
3246
+
3247
+	uint32_t	next_length = length - mask;
3248
+	if (next_length)
3249
+	{
3250
+		part2 = checksum_mirror_sum(start + mask, next_length, mask >> 1);
3251
+
3252
+		while (next_length < mask)
3253
+		{
3254
+			next_length += next_length;
3255
+			part2 += part2;
3256
+		}
3257
+
3258
+		length = mask + mask;
3259
+	}
3260
+
3261
+	return part1 + part2;
3262
+}
3263
+
3264
+void CMemory::Checksum_Calculate()
3265
+{
3266
+	// from NSRT
3267
+	uint16_t	sum = 0;
3268
+
3269
+	if (Settings.BS && !Settings.BSXItself)
3270
+		sum = checksum_calc_sum(ROM, CalculatedSize) - checksum_calc_sum(ROM + (HiROM ? 0xffb0 : 0x7fb0), 48);
3271
+	else
3272
+	if (Settings.SPC7110)
3273
+	{
3274
+		sum = checksum_calc_sum(ROM, CalculatedSize);
3275
+		if (CalculatedSize == 0x300000)
3276
+			sum += sum;
3277
+	}
3278
+	else
3279
+	{
3280
+		if (CalculatedSize & 0x7fff)
3281
+			sum = checksum_calc_sum(ROM, CalculatedSize);
3282
+		else
3283
+		{
3284
+			uint32_t	length = CalculatedSize;
3285
+			sum = checksum_mirror_sum(ROM, length);
3286
+		}
3287
+	}
3288
+
3289
+	CalculatedChecksum = sum;
3290
+}
3291
+
3292
+// information
3293
+
3294
+/*const char * CMemory::MapType()
3295
+{
3296
+	return HiROM ? ((ExtendedFormat != NOPE) ? "ExHiROM": "HiROM") : "LoROM";
3297
+}*/
3298
+
3299
+/*const char * CMemory::StaticRAMSize()
3300
+{
3301
+	static char	str[20];
3302
+
3303
+	if (SRAMSize > 16)
3304
+		strcpy(str, "Corrupt");
3305
+	else
3306
+		sprintf(str, "%dKbits", 8 * (SRAMMask + 1) / 1024);
3307
+
3308
+	return str;
3309
+}*/
3310
+
3311
+/*const char * CMemory::Size()
3312
+{
3313
+	static char	str[20];
3314
+
3315
+	if (Multi.cartType == 4)
3316
+		strcpy(str, "N/A");
3317
+	else
3318
+	if (ROMSize < 7 || ROMSize - 7 > 23)
3319
+		strcpy(str, "Corrupt");
3320
+	else
3321
+		sprintf(str, "%dMbits", 1 << (ROMSize - 7));
3322
+
3323
+	return str;
3324
+}*/
3325
+
3326
+/*const char * CMemory::Revision()
3327
+{
3328
+	static char	str[20];
3329
+
3330
+	sprintf(str, "1.%d", HiROM ? ((ExtendedFormat != NOPE) ? ROM[0x40ffdb] : ROM[0xffdb]) : ROM[0x7fdb]);
3331
+
3332
+	return str;
3333
+}*/
3334
+
3335
+/*const char * CMemory::KartContents()
3336
+{
3337
+	static char			str[64];
3338
+	static const char	*contents[3] = { "ROM", "ROM+RAM", "ROM+RAM+BAT" };
3339
+
3340
+	char	chip[16];
3341
+
3342
+	if (ROMType == 0 && !Settings.BS)
3343
+		return "ROM";
3344
+
3345
+	if (Settings.BS)
3346
+		strcpy(chip, "+BS");
3347
+	else
3348
+	if (Settings.SuperFX)
3349
+		strcpy(chip, "+Super FX");
3350
+	else
3351
+	if (Settings.SDD1)
3352
+		strcpy(chip, "+S-DD1");
3353
+	else
3354
+	if (Settings.OBC1)
3355
+		strcpy(chip, "+OBC1");
3356
+	else
3357
+	if (Settings.SA1)
3358
+		strcpy(chip, "+SA-1");
3359
+	else
3360
+	if (Settings.SPC7110RTC)
3361
+		strcpy(chip, "+SPC7110+RTC");
3362
+	else
3363
+	if (Settings.SPC7110)
3364
+		strcpy(chip, "+SPC7110");
3365
+	else
3366
+	if (Settings.SRTC)
3367
+		strcpy(chip, "+S-RTC");
3368
+	else
3369
+	if (Settings.C4)
3370
+		strcpy(chip, "+C4");
3371
+	else
3372
+	if (Settings.SETA == ST_010)
3373
+		strcpy(chip, "+ST-010");
3374
+	else
3375
+	if (Settings.SETA == ST_011)
3376
+		strcpy(chip, "+ST-011");
3377
+	else
3378
+	if (Settings.SETA == ST_018)
3379
+		strcpy(chip, "+ST-018");
3380
+	else
3381
+	if (Settings.DSP)
3382
+		sprintf(chip, "+DSP-%d", Settings.DSP);
3383
+	else
3384
+		strcpy(chip, "");
3385
+
3386
+	sprintf(str, "%s%s", contents[(ROMType & 0xf) % 3], chip);
3387
+
3388
+	return str;
3389
+}*/
3390
+
3391
+/*const char * CMemory::Country()
3392
+{
3393
+	switch (ROMRegion)
3394
+	{
3395
+		case 0:		return "Japan";
3396
+		case 1:		return "USA and Canada";
3397
+		case 2:		return "Oceania, Europe and Asia";
3398
+		case 3:		return "Sweden";
3399
+		case 4:		return "Finland";
3400
+		case 5:		return "Denmark";
3401
+		case 6:		return "France";
3402
+		case 7:		return "Holland";
3403
+		case 8:		return "Spain";
3404
+		case 9:		return "Germany, Austria and Switzerland";
3405
+		case 10:	return "Italy";
3406
+		case 11:	return "Hong Kong and China";
3407
+		case 12:	return "Indonesia";
3408
+		case 13:	return "South Korea";
3409
+		default:	return "Unknown";
3410
+	}
3411
+}*/
3412
+
3413
+/*const char * CMemory::PublishingCompany()
3414
+{
3415
+	if (CompanyId >= (int) (sizeof(nintendo_licensees) / sizeof(nintendo_licensees[0])) || CompanyId < 0)
3416
+		return "Unknown";
3417
+
3418
+	if (nintendo_licensees[CompanyId] == NULL)
3419
+		return "Unknown";
3420
+
3421
+	return nintendo_licensees[CompanyId];
3422
+}*/
3423
+
3424
+/*void CMemory::MakeRomInfoText (char *romtext)
3425
+{
3426
+	char	temp[256];
3427
+
3428
+	romtext[0] = 0;
3429
+
3430
+	sprintf(temp,   "            Cart Name: %s", ROMName);
3431
+	strcat(romtext, temp);
3432
+	sprintf(temp, "\n            Game Code: %s", ROMId);
3433
+	strcat(romtext, temp);
3434
+	sprintf(temp, "\n             Contents: %s", KartContents());
3435
+	strcat(romtext, temp);
3436
+	sprintf(temp, "\n                  Map: %s", MapType());
3437
+	strcat(romtext, temp);
3438
+	sprintf(temp, "\n                Speed: 0x%02X (%s)", ROMSpeed, (ROMSpeed & 0x10) ? "FastROM" : "SlowROM");
3439
+	strcat(romtext, temp);
3440
+	sprintf(temp, "\n                 Type: 0x%02X", ROMType);
3441
+	strcat(romtext, temp);
3442
+	sprintf(temp, "\n    Size (calculated): %dMbits", CalculatedSize / 0x20000);
3443
+	strcat(romtext, temp);
3444
+	sprintf(temp, "\n        Size (header): %s", Size());
3445
+	strcat(romtext, temp);
3446
+	sprintf(temp, "\n            SRAM size: %s", StaticRAMSize());
3447
+	strcat(romtext, temp);
3448
+	sprintf(temp, "\nChecksum (calculated): 0x%04X", CalculatedChecksum);
3449
+	strcat(romtext, temp);
3450
+	sprintf(temp, "\n    Checksum (header): 0x%04X", ROMChecksum);
3451
+	strcat(romtext, temp);
3452
+	sprintf(temp, "\n  Complement (header): 0x%04X", ROMComplementChecksum);
3453
+	strcat(romtext, temp);
3454
+	sprintf(temp, "\n         Video Output: %s", (ROMRegion > 12 || ROMRegion < 2) ? "NTSC 60Hz" : "PAL 50Hz");
3455
+	strcat(romtext, temp);
3456
+	sprintf(temp, "\n             Revision: %s", Revision());
3457
+	strcat(romtext, temp);
3458
+	sprintf(temp, "\n             Licensee: %s", PublishingCompany());
3459
+	strcat(romtext, temp);
3460
+	sprintf(temp, "\n               Region: %s", Country());
3461
+	strcat(romtext, temp);
3462
+	sprintf(temp, "\n                CRC32: 0x%08X", ROMCRC32);
3463
+	strcat(romtext, temp);
3464
+}*/
3465
+
3466
+// hack
3467
+
3468
+bool CMemory::match_na (const char *str)
3469
+{
3470
+	return strcmp(ROMName, str) == 0;
3471
+}
3472
+
3473
+bool CMemory::match_nn (const char *str)
3474
+{
3475
+	return strncmp(ROMName, str, strlen(str)) == 0;
3476
+}
3477
+
3478
+/*bool CMemory::match_nc (const char *str)
3479
+{
3480
+	return strncasecmp(ROMName, str, strlen(str)) == 0;
3481
+}*/
3482
+
3483
+bool CMemory::match_id (const char *str)
3484
+{
3485
+	return strncmp(ROMId, str, strlen(str)) == 0;
3486
+}
3487
+
3488
+void CMemory::ApplyROMFixes()
3489
+{
3490
+	Settings.BlockInvalidVRAMAccess = Settings.BlockInvalidVRAMAccessMaster;
3491
+
3492
+	//// Warnings
3493
+
3494
+	// Reject strange hacked games
3495
+	/*if ((ROMCRC32 == 0x6810aa95) ||
3496
+		(ROMCRC32 == 0x340f23e5) ||
3497
+		(ROMCRC32 == 0x77fd806a) ||
3498
+		(match_nn("HIGHWAY BATTLE 2")) ||
3499
+		(match_na("FX SKIING NINTENDO 96") && (ROM[0x7fda] == 0)) ||
3500
+		(match_nn("HONKAKUHA IGO GOSEI")   && (ROM[0xffd5] != 0x31)))
3501
+	{
3502
+		Settings.DisplayColor = BUILD_PIXEL(31, 0, 0);
3503
+		SET_UI_COLOR(255, 0, 0);
3504
+	}*/
3505
+
3506
+	//// APU timing hacks :(
3507
+
3508
+	Timings.APUSpeedup = 0;
3509
+	Timings.APUAllowTimeOverflow = false;
3510
+
3511
+	if (!Settings.DisableGameSpecificHacks)
3512
+	{
3513
+		if (match_id("AVCJ"))                                      // Rendering Ranger R2
3514
+			Timings.APUSpeedup = 4;
3515
+
3516
+		if (match_na("GAIA GENSOUKI 1 JPN")                     || // Gaia Gensouki
3517
+			match_id("JG  ")                                    || // Illusion of Gaia
3518
+			match_id("CQ  ")                                    || // Stunt Race FX
3519
+			match_na("SOULBLADER - 1")                          || // Soul Blader
3520
+			match_na("SOULBLAZER - 1 USA")                      || // Soul Blazer
3521
+			match_na("SLAP STICK 1 JPN")                        || // Slap Stick
3522
+			match_id("E9 ")                                     || // Robotrek
3523
+			match_nn("ACTRAISER")                               || // Actraiser
3524
+			match_nn("ActRaiser-2")                             || // Actraiser 2
3525
+			match_id("AQT")                                     || // Tenchi Souzou, Terranigma
3526
+			match_id("ATV")                                     || // Tales of Phantasia
3527
+			match_id("ARF")                                     || // Star Ocean
3528
+			match_id("APR")                                     || // Zen-Nippon Pro Wrestling 2 - 3-4 Budoukan
3529
+			match_id("A4B")                                     || // Super Bomberman 4
3530
+			match_id("Y7 ")                                     || // U.F.O. Kamen Yakisoban - Present Ban
3531
+			match_id("Y9 ")                                     || // U.F.O. Kamen Yakisoban - Shihan Ban
3532
+			match_id("APB")                                     || // Super Bomberman - Panic Bomber W
3533
+			match_na("DARK KINGDOM")                            || // Dark Kingdom
3534
+			match_na("ZAN3 SFC")                                || // Zan III Spirits
3535
+			match_na("HIOUDEN")                                 || // Hiouden - Mamono-tachi Tono Chikai
3536
+			match_na("\xC3\xDD\xBC\xC9\xB3\xC0")                || // Tenshi no Uta
3537
+			match_na("FORTUNE QUEST")                           || // Fortune Quest - Dice wo Korogase
3538
+			match_na("FISHING TO BASSING")                      || // Shimono Masaki no Fishing To Bassing
3539
+			match_na("OHMONO BLACKBASS")                        || // Oomono Black Bass Fishing - Jinzouko Hen
3540
+			match_na("MASTERS")                                 || // Harukanaru Augusta 2 - Masters
3541
+			match_na("SFC \xB6\xD2\xDD\xD7\xB2\xC0\xDE\xB0")    || // Kamen Rider
3542
+			match_na("ZENKI TENCHIMEIDOU")					    || // Kishin Douji Zenki - Tenchi Meidou
3543
+			match_nn("TokyoDome '95Battle 7")                   || // Shin Nippon Pro Wrestling Kounin '95 - Tokyo Dome Battle 7
3544
+			match_nn("SWORD WORLD SFC")                         || // Sword World SFC/2
3545
+			match_nn("LETs PACHINKO(")                          || // BS Lets Pachinko Nante Gindama 1/2/3/4
3546
+			match_nn("THE FISHING MASTER")                      || // Mark Davis The Fishing Master
3547
+			match_nn("Parlor")                                  || // Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5
3548
+			match_na("HEIWA Parlor!Mini8")                      || // Parlor mini 8
3549
+			match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!"))   // SANKYO Fever! Fever!
3550
+			Timings.APUSpeedup = 1;
3551
+
3552
+		if (match_na ("EARTHWORM JIM 2")						|| // Earthworm Jim 2
3553
+			match_na ("NBA Hangtime")							|| // NBA Hang Time
3554
+			match_na ("MSPACMAN")								|| // Ms Pacman
3555
+			match_na ("THE MASK")								|| // The Mask
3556
+			match_na ("PRIMAL RAGE")							|| // Primal Rage
3557
+			match_na ("DOOM TROOPERS"))							   // Doom Troopers
3558
+			Timings.APUAllowTimeOverflow = true;
3559
+	}
3560
+
3561
+	S9xAPUTimingSetSpeedup(Timings.APUSpeedup);
3562
+	S9xAPUAllowTimeOverflow(Timings.APUAllowTimeOverflow);
3563
+
3564
+	//// Other timing hacks :(
3565
+
3566
+	Timings.HDMAStart   = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100;
3567
+	Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC;
3568
+	Timings.IRQTriggerCycles = 10;
3569
+
3570
+	if (!Settings.DisableGameSpecificHacks)
3571
+	{
3572
+		// The delay to sync CPU and DMA which Snes9x cannot emulate.
3573
+		// Some games need really severe delay timing...
3574
+		if (match_na("BATTLE GRANDPRIX")) // Battle Grandprix
3575
+		{
3576
+			Timings.DMACPUSync = 20;
3577
+			printf("DMA sync: %d\n", Timings.DMACPUSync);
3578
+		}
3579
+	}
3580
+
3581
+	if (!Settings.DisableGameSpecificHacks)
3582
+	{
3583
+		// An infinite loop reads $4212 and waits V-blank end, whereas VIRQ is set V=0.
3584
+		// If Snes9x succeeds to escape from the loop before jumping into the IRQ handler, the game goes further.
3585
+		// If Snes9x jumps into the IRQ handler before escaping from the loop,
3586
+		// Snes9x cannot escape from the loop permanently because the RTI is in the next V-blank.
3587
+		if (match_na("Aero the AcroBat 2"))
3588
+		{
3589
+			Timings.IRQPendCount = 2;
3590
+			printf("IRQ count hack: %d\n", Timings.IRQPendCount);
3591
+		}
3592
+	}
3593
+
3594
+	if (!Settings.DisableGameSpecificHacks)
3595
+	{
3596
+		// XXX: What's happening?
3597
+		if (match_na("X-MEN")) // Spider-Man and the X-Men
3598
+		{
3599
+			Settings.BlockInvalidVRAMAccess = false;
3600
+			printf("Invalid VRAM access hack\n");
3601
+		}
3602
+	}
3603
+
3604
+	//// SRAM initial value
3605
+
3606
+	if (!Settings.DisableGameSpecificHacks)
3607
+	{
3608
+		if (match_na("HITOMI3"))
3609
+		{
3610
+			SRAMSize = 1;
3611
+			SRAMMask = ((1 << (SRAMSize + 3)) * 128) - 1;
3612
+		}
3613
+
3614
+		// SRAM value fixes
3615
+		if (match_na("SUPER DRIFT OUT")      || // Super Drift Out
3616
+			match_na("SATAN IS OUR FATHER!") ||
3617
+			match_na("goemon 4"))               // Ganbare Goemon Kirakira Douchuu
3618
+			SNESGameFixes.SRAMInitialValue = 0x00;
3619
+
3620
+		// Additional game fixes by sanmaiwashi ...
3621
+		// XXX: unnecessary?
3622
+		if (match_na("SFX \xC5\xB2\xC4\xB6\xDE\xDD\xC0\xDE\xD1\xD3\xC9\xB6\xDE\xC0\xD8 1")) // SD Gundam Gaiden - Knight Gundam Monogatari
3623
+			SNESGameFixes.SRAMInitialValue = 0x6b;
3624
+
3625
+		// others: BS and ST-01x games are 0x00.
3626
+	}
3627
+
3628
+	//// OAM hacks :(
3629
+
3630
+	if (!Settings.DisableGameSpecificHacks)
3631
+	{
3632
+		// OAM hacks because we don't fully understand the behavior of the SNES.
3633
+		// Totally wacky display in 2P mode...
3634
+		// seems to need a disproven behavior, so we're definitely overlooking some other bug?
3635
+		if (match_nn("UNIRACERS")) // Uniracers
3636
+		{
3637
+			SNESGameFixes.Uniracers = true;
3638
+			printf("Applied Uniracers hack.\n");
3639
+		}
3640
+	}
3641
+}
3642
+
3643
+// UPS % IPS
3644
+
3645
+/*static uint32_t ReadUPSPointer (const uint8_t *data, unsigned &addr, unsigned size)
3646
+{
3647
+	uint32_t offset = 0, shift = 1;
3648
+	while(addr < size) {
3649
+		uint8_t x = data[addr++];
3650
+		offset += (x & 0x7f) * shift;
3651
+		if(x & 0x80) break;
3652
+		shift <<= 7;
3653
+		offset += shift;
3654
+	}
3655
+	return offset;
3656
+}
3657
+
3658
+//NOTE: UPS patches are *never* created against a headered ROM!
3659
+//this is per the UPS file specification. however, do note that it is
3660
+//technically possible for a non-compliant patcher to ignore this requirement.
3661
+//therefore, it is *imperative* that no emulator support such patches.
3662
+//thusly, we ignore the "long offset" parameter below. failure to do so would
3663
+//completely invalidate the purpose of UPS; which is to avoid header vs
3664
+//no-header patching errors that result in IPS patches having a 50/50 chance of
3665
+//being applied correctly.
3666
+
3667
+static bool ReadUPSPatch (Reader *r, long, int32_t &rom_size)
3668
+{
3669
+	//Reader lacks size() and rewind(), so we need to read in the file to get its size
3670
+	uint8_t *data = new uint8_t[8 * 1024 * 1024];  //allocate a lot of memory, better safe than sorry ...
3671
+	uint32_t size = 0;
3672
+	while(true) {
3673
+		int value = r->get_char();
3674
+		if(value == EOF) break;
3675
+		data[size++] = value;
3676
+		if(size >= 8 * 1024 * 1024) {
3677
+			//prevent buffer overflow: SNES-made UPS patches should never be this big anyway ...
3678
+			delete[] data;
3679
+			return false;
3680
+		}
3681
+	}
3682
+
3683
+	//4-byte header + 1-byte input size + 1-byte output size + 4-byte patch CRC32 + 4-byte unpatched CRC32 + 4-byte patched CRC32
3684
+	if(size < 18) { delete[] data; return false; }  //patch is too small
3685
+
3686
+	uint32_t addr = 0;
3687
+	if(data[addr++] != 'U') { delete[] data; return false; }  //patch has an invalid header
3688
+	if(data[addr++] != 'P') { delete[] data; return false; }  //...
3689
+	if(data[addr++] != 'S') { delete[] data; return false; }  //...
3690
+	if(data[addr++] != '1') { delete[] data; return false; }  //...
3691
+
3692
+	uint32_t patch_crc32 = caCRC32(data, size - 4);  //don't include patch CRC32 itself in CRC32 calculation
3693
+	uint32_t rom_crc32 = caCRC32(Memory.ROM, rom_size);
3694
+	uint32_t px_crc32 = (data[size - 12] << 0) + (data[size - 11] << 8) + (data[size - 10] << 16) + (data[size -  9] << 24);
3695
+	uint32_t py_crc32 = (data[size -  8] << 0) + (data[size -  7] << 8) + (data[size -  6] << 16) + (data[size -  5] << 24);
3696
+	uint32_t pp_crc32 = (data[size -  4] << 0) + (data[size -  3] << 8) + (data[size -  2] << 16) + (data[size -  1] << 24);
3697
+	if(patch_crc32 != pp_crc32) { delete[] data; return false; }  //patch is corrupted
3698
+	if((rom_crc32 != px_crc32) && (rom_crc32 != py_crc32)) { delete[] data; return false; }  //patch is for a different ROM
3699
+
3700
+	uint32_t px_size = ReadUPSPointer(data, addr, size);
3701
+	uint32_t py_size = ReadUPSPointer(data, addr, size);
3702
+	uint32_t out_size = ((uint32_t) rom_size == px_size) ? py_size : px_size;
3703
+	if(out_size > CMemory::MAX_ROM_SIZE) { delete[] data; return false; }  //applying this patch will overflow Memory.ROM buffer
3704
+
3705
+	//fill expanded area with 0x00s; so that XORing works as expected below.
3706
+	//note that this is needed (and works) whether output ROM is larger or smaller than pre-patched ROM
3707
+	for(unsigned i = min((uint32_t) rom_size, out_size); i < max((uint32_t) rom_size, out_size); i++) {
3708
+		Memory.ROM[i] = 0x00;
3709
+	}
3710
+
3711
+	uint32_t relative = 0;
3712
+	while(addr < size - 12) {
3713
+		relative += ReadUPSPointer(data, addr, size);
3714
+		while(addr < size - 12) {
3715
+			uint8_t x = data[addr++];
3716
+			Memory.ROM[relative++] ^= x;
3717
+			if(!x) break;
3718
+		}
3719
+	}
3720
+
3721
+	rom_size = out_size;
3722
+	delete[] data;
3723
+
3724
+	uint32_t out_crc32 = caCRC32(Memory.ROM, rom_size);
3725
+	if(((rom_crc32 == px_crc32) && (out_crc32 == py_crc32))
3726
+	|| ((rom_crc32 == py_crc32) && (out_crc32 == px_crc32))
3727
+	) {
3728
+		return true;
3729
+	} else {
3730
+		//technically, reaching here means that patching has failed.
3731
+		//we should return false, but unfortunately Memory.ROM has already
3732
+		//been modified above and cannot be undone. to do this properly, we
3733
+		//would need to make a copy of Memory.ROM, apply the patch, and then
3734
+		//copy that back to Memory.ROM.
3735
+		//
3736
+		//however, the only way for this case to happen is if the UPS patch file
3737
+		//itself is corrupted, which should be detected by the patch CRC32 check
3738
+		//above anyway. errors due to the wrong ROM or patch file being used are
3739
+		//already caught above.
3740
+		fprintf(stderr, "WARNING: UPS patching appears to have failed.\nGame may not be playable.\n");
3741
+		return true;
3742
+	}
3743
+}
3744
+
3745
+static long ReadInt (Reader *r, unsigned nbytes)
3746
+{
3747
+	long	v = 0;
3748
+
3749
+	while (nbytes--)
3750
+	{
3751
+		int	c = r->get_char();
3752
+		if (c == EOF)
3753
+			return -1;
3754
+		v = (v << 8) | (c & 0xFF);
3755
+	}
3756
+
3757
+	return v;
3758
+}
3759
+
3760
+static bool ReadIPSPatch (Reader *r, long offset, int32_t &rom_size)
3761
+{
3762
+	const int32_t	IPS_EOF = 0x00454F46l;
3763
+	int32_t		ofs;
3764
+	char		fname[6];
3765
+
3766
+	fname[5] = 0;
3767
+	for (int i = 0; i < 5; i++)
3768
+	{
3769
+		int	c = r->get_char();
3770
+		if (c == EOF)
3771
+			return 0;
3772
+		fname[i] = (char) c;
3773
+	}
3774
+
3775
+	if (strncmp(fname, "PATCH", 5))
3776
+		return 0;
3777
+
3778
+	for (;;)
3779
+	{
3780
+		long	len, rlen;
3781
+		int		rchar;
3782
+
3783
+		ofs = ReadInt(r, 3);
3784
+		if (ofs == -1)
3785
+			return 0;
3786
+
3787
+		if (ofs == IPS_EOF)
3788
+			break;
3789
+
3790
+		ofs -= offset;
3791
+
3792
+		len = ReadInt(r, 2);
3793
+		if (len == -1)
3794
+			return 0;
3795
+
3796
+		if (len)
3797
+		{
3798
+			if (ofs + len > CMemory::MAX_ROM_SIZE)
3799
+				return 0;
3800
+
3801
+			while (len--)
3802
+			{
3803
+				rchar = r->get_char();
3804
+				if (rchar == EOF)
3805
+					return 0;
3806
+				Memory.ROM[ofs++] = (uint8_t) rchar;
3807
+			}
3808
+
3809
+			if (ofs > rom_size)
3810
+				rom_size = ofs;
3811
+		}
3812
+		else
3813
+		{
3814
+			rlen = ReadInt(r, 2);
3815
+			if (rlen == -1)
3816
+				return 0;
3817
+
3818
+			rchar = r->get_char();
3819
+			if (rchar == EOF)
3820
+				return 0;
3821
+
3822
+			if (ofs + rlen > CMemory::MAX_ROM_SIZE)
3823
+				return 0;
3824
+
3825
+			while (rlen--)
3826
+				Memory.ROM[ofs++] = (uint8_t) rchar;
3827
+
3828
+			if (ofs > rom_size)
3829
+				rom_size = ofs;
3830
+		}
3831
+	}
3832
+
3833
+	ofs = ReadInt(r, 3);
3834
+	if (ofs != -1 && ofs - offset < rom_size)
3835
+		rom_size = ofs - offset;
3836
+
3837
+	return 1;
3838
+}*/
3839
+
3840
+#ifdef UNZIP_SUPPORT
3841
+static int unzFindExtension (unzFile &file, const char *ext, bool restart, bool print)
3842
+{
3843
+	unz_file_info	info;
3844
+	int				port, l = strlen(ext);
3845
+
3846
+	if (restart)
3847
+		port = unzGoToFirstFile(file);
3848
+	else
3849
+		port = unzGoToNextFile(file);
3850
+
3851
+	while (port == UNZ_OK)
3852
+	{
3853
+		int		len;
3854
+		char	name[132];
3855
+
3856
+		unzGetCurrentFileInfo(file, &info, name, 128, NULL, 0, NULL, 0);
3857
+		len = strlen(name);
3858
+
3859
+		if (len >= l + 1 && name[len - l - 1] == '.' && strcasecmp(name + len - l, ext) == 0 && unzOpenCurrentFile(file) == UNZ_OK)
3860
+		{
3861
+			if (print)
3862
+				printf("Using IPS or UPS patch %s", name);
3863
+
3864
+			return port;
3865
+		}
3866
+
3867
+		port = unzGoToNextFile(file);
3868
+	}
3869
+
3870
+	return port;
3871
+}
3872
+#endif
3873
+
3874
+/*void CMemory::CheckForAnyPatch (const char *rom_filename, bool header, int32_t &rom_size)
3875
+{
3876
+	if (Settings.NoPatch)
3877
+		return;
3878
+
3879
+	STREAM		patch_file  = NULL;
3880
+	uint32_t		i;
3881
+	long		offset = header ? 512 : 0;
3882
+	int			ret;
3883
+	bool		flag;
3884
+	char		dir[_MAX_DIR + 1], drive[_MAX_DRIVE + 1], name[_MAX_FNAME + 1], ext[_MAX_EXT + 1], ips[_MAX_EXT + 3], fname[PATH_MAX + 1];
3885
+	const char	*n;
3886
+
3887
+	// UPS
3888
+
3889
+	_splitpath(rom_filename, drive, dir, name, ext);
3890
+	_makepath(fname, drive, dir, name, "ups");
3891
+
3892
+	if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL)
3893
+	{
3894
+		printf("Using UPS patch %s", fname);
3895
+
3896
+		ret = ReadUPSPatch(new fReader(patch_file), 0, rom_size);
3897
+		CLOSE_STREAM(patch_file);
3898
+
3899
+		if (ret)
3900
+		{
3901
+			printf("!\n");
3902
+			return;
3903
+		}
3904
+		else
3905
+			printf(" failed!\n");
3906
+	}
3907
+
3908
+#ifdef UNZIP_SUPPORT
3909
+	if (!strcasecmp(ext, "zip") || !strcasecmp(ext, ".zip"))
3910
+	{
3911
+		unzFile	file = unzOpen(rom_filename);
3912
+		if (file)
3913
+		{
3914
+			int	port = unzFindExtension(file, "ups");
3915
+			if (port == UNZ_OK)
3916
+			{
3917
+				printf(" in %s", rom_filename);
3918
+
3919
+				ret = ReadUPSPatch(new unzReader(file), offset, rom_size);
3920
+				unzCloseCurrentFile(file);
3921
+
3922
+				if (ret)
3923
+					printf("!\n");
3924
+				else
3925
+					printf(" failed!\n");
3926
+			}
3927
+		}
3928
+	}
3929
+#endif
3930
+
3931
+	n = S9xGetFilename(".ups", IPS_DIR);
3932
+
3933
+	if ((patch_file = OPEN_STREAM(n, "rb")) != NULL)
3934
+	{
3935
+		printf("Using UPS patch %s", n);
3936
+
3937
+		ret = ReadUPSPatch(new fReader(patch_file), 0, rom_size);
3938
+		CLOSE_STREAM(patch_file);
3939
+
3940
+		if (ret)
3941
+		{
3942
+			printf("!\n");
3943
+			return;
3944
+		}
3945
+		else
3946
+			printf(" failed!\n");
3947
+	}
3948
+
3949
+	// IPS
3950
+
3951
+	_splitpath(rom_filename, drive, dir, name, ext);
3952
+	_makepath(fname, drive, dir, name, "ips");
3953
+
3954
+	if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL)
3955
+	{
3956
+		printf("Using IPS patch %s", fname);
3957
+
3958
+		ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
3959
+		CLOSE_STREAM(patch_file);
3960
+
3961
+		if (ret)
3962
+		{
3963
+			printf("!\n");
3964
+			return;
3965
+		}
3966
+		else
3967
+			printf(" failed!\n");
3968
+	}
3969
+
3970
+	if (_MAX_EXT > 6)
3971
+	{
3972
+		i = 0;
3973
+		flag = false;
3974
+
3975
+		do
3976
+		{
3977
+			snprintf(ips, 8, "%03d.ips", i);
3978
+			_makepath(fname, drive, dir, name, ips);
3979
+
3980
+			if (!(patch_file = OPEN_STREAM(fname, "rb")))
3981
+				break;
3982
+
3983
+			printf("Using IPS patch %s", fname);
3984
+
3985
+			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
3986
+			CLOSE_STREAM(patch_file);
3987
+
3988
+			if (ret)
3989
+			{
3990
+				printf("!\n");
3991
+				flag = true;
3992
+			}
3993
+			else
3994
+			{
3995
+				printf(" failed!\n");
3996
+				break;
3997
+			}
3998
+		} while (++i < 1000);
3999
+
4000
+		if (flag)
4001
+			return;
4002
+	}
4003
+
4004
+	if (_MAX_EXT > 3)
4005
+	{
4006
+		i = 0;
4007
+		flag = false;
4008
+
4009
+		do
4010
+		{
4011
+			snprintf(ips, _MAX_EXT + 2, "ips%d", i);
4012
+			if (strlen(ips) > _MAX_EXT)
4013
+				break;
4014
+			_makepath(fname, drive, dir, name, ips);
4015
+
4016
+			if (!(patch_file = OPEN_STREAM(fname, "rb")))
4017
+				break;
4018
+
4019
+			printf("Using IPS patch %s", fname);
4020
+
4021
+			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
4022
+			CLOSE_STREAM(patch_file);
4023
+
4024
+			if (ret)
4025
+			{
4026
+				printf("!\n");
4027
+				flag = true;
4028
+			}
4029
+			else
4030
+			{
4031
+				printf(" failed!\n");
4032
+				break;
4033
+			}
4034
+		} while (++i != 0);
4035
+
4036
+		if (flag)
4037
+			return;
4038
+	}
4039
+
4040
+	if (_MAX_EXT > 2)
4041
+	{
4042
+		i = 0;
4043
+		flag = false;
4044
+
4045
+		do
4046
+		{
4047
+			snprintf(ips, 4, "ip%d", i);
4048
+			_makepath(fname, drive, dir, name, ips);
4049
+
4050
+			if (!(patch_file = OPEN_STREAM(fname, "rb")))
4051
+				break;
4052
+
4053
+			printf("Using IPS patch %s", fname);
4054
+
4055
+			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
4056
+			CLOSE_STREAM(patch_file);
4057
+
4058
+			if (ret)
4059
+			{
4060
+				printf("!\n");
4061
+				flag = true;
4062
+			}
4063
+			else
4064
+			{
4065
+				printf(" failed!\n");
4066
+				break;
4067
+			}
4068
+		} while (++i < 10);
4069
+
4070
+		if (flag)
4071
+			return;
4072
+	}
4073
+
4074
+#ifdef UNZIP_SUPPORT
4075
+	if (!strcasecmp(ext, "zip") || !strcasecmp(ext, ".zip"))
4076
+	{
4077
+		unzFile	file = unzOpen(rom_filename);
4078
+		if (file)
4079
+		{
4080
+			int	port = unzFindExtension(file, "ips");
4081
+			while (port == UNZ_OK)
4082
+			{
4083
+				printf(" in %s", rom_filename);
4084
+
4085
+				ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
4086
+				unzCloseCurrentFile(file);
4087
+
4088
+				if (ret)
4089
+				{
4090
+					printf("!\n");
4091
+					flag = true;
4092
+				}
4093
+				else
4094
+					printf(" failed!\n");
4095
+
4096
+				port = unzFindExtension(file, "ips", false);
4097
+			}
4098
+
4099
+			if (!flag)
4100
+			{
4101
+				i = 0;
4102
+
4103
+				do
4104
+				{
4105
+					snprintf(ips, 8, "%03d.ips", i);
4106
+
4107
+					if (unzFindExtension(file, ips) != UNZ_OK)
4108
+						break;
4109
+
4110
+					printf(" in %s", rom_filename);
4111
+
4112
+					ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
4113
+					unzCloseCurrentFile(file);
4114
+
4115
+					if (ret)
4116
+					{
4117
+						printf("!\n");
4118
+						flag = true;
4119
+					}
4120
+					else
4121
+					{
4122
+						printf(" failed!\n");
4123
+						break;
4124
+					}
4125
+
4126
+					if (unzFindExtension(file, ips, false, false) == UNZ_OK)
4127
+						printf("WARNING: Ignoring extra .%s files!\n", ips);
4128
+				} while (++i < 1000);
4129
+			}
4130
+
4131
+			if (!flag)
4132
+			{
4133
+				i = 0;
4134
+
4135
+				do
4136
+				{
4137
+					snprintf(ips, _MAX_EXT + 2, "ips%d", i);
4138
+					if (strlen(ips) > _MAX_EXT)
4139
+						break;
4140
+
4141
+					if (unzFindExtension(file, ips) != UNZ_OK)
4142
+						break;
4143
+
4144
+					printf(" in %s", rom_filename);
4145
+
4146
+					ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
4147
+					unzCloseCurrentFile(file);
4148
+
4149
+					if (ret)
4150
+					{
4151
+						printf("!\n");
4152
+						flag = true;
4153
+					}
4154
+					else
4155
+					{
4156
+						printf(" failed!\n");
4157
+						break;
4158
+					}
4159
+
4160
+					if (unzFindExtension(file, ips, false, false) == UNZ_OK)
4161
+						printf("WARNING: Ignoring extra .%s files!\n", ips);
4162
+				} while (++i != 0);
4163
+			}
4164
+
4165
+			if (!flag)
4166
+			{
4167
+				i = 0;
4168
+
4169
+				do
4170
+				{
4171
+					snprintf(ips, 4, "ip%d", i);
4172
+
4173
+					if (unzFindExtension(file, ips) != UNZ_OK)
4174
+						break;
4175
+
4176
+					printf(" in %s", rom_filename);
4177
+
4178
+					ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
4179
+					unzCloseCurrentFile(file);
4180
+
4181
+					if (ret)
4182
+					{
4183
+						printf("!\n");
4184
+						flag = true;
4185
+					}
4186
+					else
4187
+					{
4188
+						printf(" failed!\n");
4189
+						break;
4190
+					}
4191
+
4192
+					if (unzFindExtension(file, ips, false, false) == UNZ_OK)
4193
+						printf("WARNING: Ignoring extra .%s files!\n", ips);
4194
+				} while (++i < 10);
4195
+			}
4196
+
4197
+			assert(unzClose(file) == UNZ_OK);
4198
+
4199
+			if (flag)
4200
+				return;
4201
+		}
4202
+	}
4203
+#endif
4204
+
4205
+	n = S9xGetFilename(".ips", IPS_DIR);
4206
+
4207
+	if ((patch_file = OPEN_STREAM(n, "rb")) != NULL)
4208
+	{
4209
+		printf("Using IPS patch %s", n);
4210
+
4211
+		ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
4212
+		CLOSE_STREAM(patch_file);
4213
+
4214
+		if (ret)
4215
+		{
4216
+			printf("!\n");
4217
+			return;
4218
+		}
4219
+		else
4220
+			printf(" failed!\n");
4221
+	}
4222
+
4223
+	if (_MAX_EXT > 6)
4224
+	{
4225
+		i = 0;
4226
+		flag = false;
4227
+
4228
+		do
4229
+		{
4230
+			snprintf(ips, 9, ".%03d.ips", i);
4231
+			n = S9xGetFilename(ips, IPS_DIR);
4232
+
4233
+			if (!(patch_file = OPEN_STREAM(n, "rb")))
4234
+				break;
4235
+
4236
+			printf("Using IPS patch %s", n);
4237
+
4238
+			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
4239
+			CLOSE_STREAM(patch_file);
4240
+
4241
+			if (ret)
4242
+			{
4243
+				printf("!\n");
4244
+				flag = true;
4245
+			}
4246
+			else
4247
+			{
4248
+				printf(" failed!\n");
4249
+				break;
4250
+			}
4251
+		} while (++i < 1000);
4252
+
4253
+		if (flag)
4254
+			return;
4255
+	}
4256
+
4257
+	if (_MAX_EXT > 3)
4258
+	{
4259
+		i = 0;
4260
+		flag = false;
4261
+
4262
+		do
4263
+		{
4264
+			snprintf(ips, _MAX_EXT + 3, ".ips%d", i);
4265
+			if (strlen(ips) > _MAX_EXT + 1)
4266
+				break;
4267
+			n = S9xGetFilename(ips, IPS_DIR);
4268
+
4269
+			if (!(patch_file = OPEN_STREAM(n, "rb")))
4270
+				break;
4271
+
4272
+			printf("Using IPS patch %s", n);
4273
+
4274
+			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
4275
+			CLOSE_STREAM(patch_file);
4276
+
4277
+			if (ret)
4278
+			{
4279
+				printf("!\n");
4280
+				flag = true;
4281
+			}
4282
+			else
4283
+			{
4284
+				printf(" failed!\n");
4285
+				break;
4286
+			}
4287
+		} while (++i != 0);
4288
+
4289
+		if (flag)
4290
+			return;
4291
+	}
4292
+
4293
+	if (_MAX_EXT > 2)
4294
+	{
4295
+		i = 0;
4296
+		flag = false;
4297
+
4298
+		do
4299
+		{
4300
+			snprintf(ips, 5, ".ip%d", i);
4301
+			n = S9xGetFilename(ips, IPS_DIR);
4302
+
4303
+			if (!(patch_file = OPEN_STREAM(n, "rb")))
4304
+				break;
4305
+
4306
+			printf("Using IPS patch %s", n);
4307
+
4308
+			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
4309
+			CLOSE_STREAM(patch_file);
4310
+
4311
+			if (ret)
4312
+			{
4313
+				printf("!\n");
4314
+				flag = true;
4315
+			}
4316
+			else
4317
+			{
4318
+				printf(" failed!\n");
4319
+				break;
4320
+			}
4321
+		} while (++i < 10);
4322
+
4323
+		if (flag)
4324
+			return;
4325
+	}
4326
+}*/