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                              zones (kasumitokoduck@yahoo.com)
21 
22   (c) Copyright 2006 - 2007  nitsuja
23 
24   (c) Copyright 2009 - 2010  BearOso,
25                              OV2
26 
27 
28   BS-X C emulator code
29   (c) Copyright 2005 - 2006  Dreamer Nom,
30                              zones
31 
32   C4 x86 assembler and some C emulation code
33   (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
34                              Nach,
35                              zsKnight (zsknight@zsnes.com)
36 
37   C4 C++ code
38   (c) Copyright 2003 - 2006  Brad Jorsch,
39                              Nach
40 
41   DSP-1 emulator code
42   (c) Copyright 1998 - 2006  _Demo_,
43                              Andreas Naive (andreasnaive@gmail.com),
44                              Gary Henderson,
45                              Ivar (ivar@snes9x.com),
46                              John Weidman,
47                              Kris Bleakley,
48                              Matthew Kendora,
49                              Nach,
50                              neviksti (neviksti@hotmail.com)
51 
52   DSP-2 emulator code
53   (c) Copyright 2003         John Weidman,
54                              Kris Bleakley,
55                              Lord Nightmare (lord_nightmare@users.sourceforge.net),
56                              Matthew Kendora,
57                              neviksti
58 
59   DSP-3 emulator code
60   (c) Copyright 2003 - 2006  John Weidman,
61                              Kris Bleakley,
62                              Lancer,
63                              z80 gaiden
64 
65   DSP-4 emulator code
66   (c) Copyright 2004 - 2006  Dreamer Nom,
67                              John Weidman,
68                              Kris Bleakley,
69                              Nach,
70                              z80 gaiden
71 
72   OBC1 emulator code
73   (c) Copyright 2001 - 2004  zsKnight,
74                              pagefault (pagefault@zsnes.com),
75                              Kris Bleakley
76                              Ported from x86 assembler to C by sanmaiwashi
77 
78   SPC7110 and RTC C++ emulator code used in 1.39-1.51
79   (c) Copyright 2002         Matthew Kendora with research by
80                              zsKnight,
81                              John Weidman,
82                              Dark Force
83 
84   SPC7110 and RTC C++ emulator code used in 1.52+
85   (c) Copyright 2009         byuu,
86                              neviksti
87 
88   S-DD1 C emulator code
89   (c) Copyright 2003         Brad Jorsch with research by
90                              Andreas Naive,
91                              John Weidman
92 
93   S-RTC C emulator code
94   (c) Copyright 2001 - 2006  byuu,
95                              John Weidman
96 
97   ST010 C++ emulator code
98   (c) Copyright 2003         Feather,
99                              John Weidman,
100                              Kris Bleakley,
101                              Matthew Kendora
102 
103   Super FX x86 assembler emulator code
104   (c) Copyright 1998 - 2003  _Demo_,
105                              pagefault,
106                              zsKnight
107 
108   Super FX C emulator code
109   (c) Copyright 1997 - 1999  Ivar,
110                              Gary Henderson,
111                              John Weidman
112 
113   Sound emulator code used in 1.5-1.51
114   (c) Copyright 1998 - 2003  Brad Martin
115   (c) Copyright 1998 - 2006  Charles Bilyue'
116 
117   Sound emulator code used in 1.52+
118   (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)
119 
120   SH assembler code partly based on x86 assembler code
121   (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)
122 
123   2xSaI filter
124   (c) Copyright 1999 - 2001  Derek Liauw Kie Fa
125 
126   HQ2x, HQ3x, HQ4x filters
127   (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)
128 
129   NTSC filter
130   (c) Copyright 2006 - 2007  Shay Green
131 
132   GTK+ GUI code
133   (c) Copyright 2004 - 2010  BearOso
134 
135   Win32 GUI code
136   (c) Copyright 2003 - 2006  blip,
137                              funkyass,
138                              Matthew Kendora,
139                              Nach,
140                              nitsuja
141   (c) Copyright 2009 - 2010  OV2
142 
143   Mac OS GUI code
144   (c) Copyright 1998 - 2001  John Stiles
145   (c) Copyright 2001 - 2010  zones
146 
147   (c) Copyright 2010 - 2016 Daniel De Matteis. (UNDER NO CIRCUMSTANCE
148   WILL COMMERCIAL RIGHTS EVER BE APPROPRIATED TO ANY PARTY)
149 
150   Specific ports contains the works of other authors. See headers in
151   individual files.
152 
153 
154   Snes9x homepage: http://www.snes9x.com/
155 
156   Permission to use, copy, modify and/or distribute Snes9x in both binary
157   and source form, for non-commercial purposes, is hereby granted without
158   fee, providing that this license information and copyright notice appear
159   with all copies and any derived work.
160 
161   This software is provided 'as-is', without any express or implied
162   warranty. In no event shall the authors be held liable for any damages
163   arising from the use of this software or it's derivatives.
164 
165   Snes9x is freeware for PERSONAL USE only. Commercial users should
166   seek permission of the copyright holders first. Commercial use includes,
167   but is not limited to, charging money for Snes9x or software derived from
168   Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
169   using Snes9x as a promotion for your commercial product.
170 
171   The copyright holders request that bug fixes and improvements to the code
172   should be forwarded to them so everyone can benefit from the modifications
173   in future versions.
174 
175   Super NES and Super Nintendo Entertainment System are trademarks of
176   Nintendo Co., Limited and its subsidiary companies.
177  ***********************************************************************************/
178 #include <ctype.h>
179 #include <stdlib.h>
180 #include <string.h>
181 
182 #include "snes9x.h"
183 #include "memmap.h"
184 #include "getset.h"
185 #include "apu.h"
186 #include "fxinst.h"
187 #include "fxemu.h"
188 #include "sdd1.h"
189 #include "srtc.h"
190 #include "controls.h"
191 #include "cheats.h"
192 #include "display.h"
193 #include "spc7110dec.h"
194 
195 #include <streams/file_stream.h>
196 #include <libretro.h>
197 
198 void S9xAppendMapping(struct retro_memory_descriptor *desc);
199 
200 /* Forward declarations. */
201 static bool8 InitROM (void);
202 
203 #define MAP_LIBRETRO_RAW(flags, ptr, offset, start, select, disconnect, len) \
204 	do { \
205 		struct retro_memory_descriptor desc={flags, ptr, offset, start, select, disconnect, len, NULL}; \
206 		S9xAppendMapping(&desc); \
207 	} while(0)
208 
209 #define MAP_LIBRETRO(flags, ptr, offset, disconnect, len, bank_s,bank_e,addr_s,addr_e) \
210 	MAP_LIBRETRO_RAW(flags, ptr, offset, \
211 		(bank_s<<16 | addr_s), ((bank_s<<16 | addr_s) ^ (bank_e<<16 | addr_e) ^ 0xFFFFFF), \
212 		disconnect, len)
213 
214 
215 static const uint32	crc32Table[256] =
216 {
217 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
218 	0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
219 	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
220 	0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
221 	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
222 	0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
223 	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
224 	0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
225 	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
226 	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
227 	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
228 	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
229 	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
230 	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
231 	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
232 	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
233 	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
234 	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
235 	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
236 	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
237 	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
238 	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
239 	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
240 	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
241 	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
242 	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
243 	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
244 	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
245 	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
246 	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
247 	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
248 	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
249 	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
250 	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
251 	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
252 	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
253 	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
254 	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
255 	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
256 	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
257 	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
258 	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
259 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
260 };
261 
262 /* deinterleave*/
263 
S9xDeinterleaveType1(int size,uint8 * base)264 static void S9xDeinterleaveType1 (int size, uint8 *base)
265 {
266 	uint8 *tmp;
267 	uint8	blocks[256], b;
268 	int nblocks;
269 	int	i, j;
270 
271 	nblocks = size >> 16;
272 
273 	for ( i = 0; i < nblocks; i++)
274 	{
275 		blocks[i * 2] = i + nblocks;
276 		blocks[i * 2 + 1] = i;
277 	}
278 
279 	tmp = (uint8 *) malloc(0x8000);
280 	if (tmp)
281 	{
282 		for ( i = 0; i < nblocks * 2; i++)
283 		{
284 			for ( j = i; j < nblocks * 2; j++)
285 			{
286 				if (blocks[j] == i)
287 				{
288 					memcpy(tmp, &base[blocks[j] * 0x8000], 0x8000);
289 					memmove(&base[blocks[j] * 0x8000], &base[blocks[i] * 0x8000], 0x8000);
290 					memcpy(&base[blocks[i] * 0x8000], tmp, 0x8000);
291 					b = blocks[j];
292 					blocks[j] = blocks[i];
293 					blocks[i] = b;
294 					break;
295 				}
296 			}
297 		}
298 
299 		free(tmp);
300 	}
301 }
302 
S9xDeinterleaveType2(int size,uint8 * base)303 static void S9xDeinterleaveType2 (int size, uint8 *base)
304 {
305 	/* for odd Super FX images */
306 	uint8 *tmp;
307 	uint8	blocks[256], b;
308 	int nblocks, step, i, j;
309 
310 	nblocks = size >> 16;
311 	step = 64;
312 
313 	while (nblocks <= step)
314 		step >>= 1;
315 	nblocks = step;
316 
317 	for ( i = 0; i < nblocks * 2; i++)
318 		blocks[i] = (i & ~0xf) | ((i & 3) << 2) | ((i & 12) >> 2);
319 
320 	tmp = (uint8 *) malloc(0x10000);
321 	if (tmp)
322 	{
323 		for ( i = 0; i < nblocks * 2; i++)
324 		{
325 			for ( j = i; j < nblocks * 2; j++)
326 			{
327 				if (blocks[j] == i)
328 				{
329 					memcpy(tmp, &base[blocks[j] * 0x10000], 0x10000);
330 					memmove(&base[blocks[j] * 0x10000], &base[blocks[i] * 0x10000], 0x10000);
331 					memcpy(&base[blocks[i] * 0x10000], tmp, 0x10000);
332 					b = blocks[j];
333 					blocks[j] = blocks[i];
334 					blocks[i] = b;
335 					break;
336 				}
337 			}
338 		}
339 
340 		free(tmp);
341 	}
342 }
343 
S9xDeinterleaveGD24(int size,uint8 * base)344 static void S9xDeinterleaveGD24 (int size, uint8 *base)
345 {
346 	uint8 *tmp;
347 	/* for 24Mbit images dumped with Game Doctor */
348 	if (size != 0x300000)
349 		return;
350 
351 	tmp = (uint8 *) malloc(0x80000);
352 	if (tmp)
353 	{
354 		memcpy(tmp, &base[0x180000], 0x80000);
355 		memcpy(&base[0x180000], &base[0x200000], 0x80000);
356 		memcpy(&base[0x200000], &base[0x280000], 0x80000);
357 		memcpy(&base[0x280000], tmp, 0x80000);
358 
359 		free(tmp);
360 
361 		S9xDeinterleaveType1(size, base);
362 	}
363 }
364 
365 /* allocation and deallocation */
366 
Init(void)367 bool8 Init (void)
368 {
369 	Memory.RAM	 = (uint8 *) malloc(0x20000);
370 	Memory.SRAM = (uint8 *) malloc(0x80000);
371 	Memory.VRAM = (uint8 *) malloc(0x10000);
372 	Memory.ROM  = (uint8 *) malloc(MAX_ROM_SIZE + 0x200 + 0x8000);
373 
374 	IPPU.TileCache[TILE_2BIT]       = (uint8 *) malloc(MAX_2BIT_TILES * 64);
375 	IPPU.TileCache[TILE_4BIT]       = (uint8 *) malloc(MAX_4BIT_TILES * 64);
376 	IPPU.TileCache[TILE_8BIT]       = (uint8 *) malloc(MAX_8BIT_TILES * 64);
377 	IPPU.TileCache[TILE_2BIT_EVEN]  = (uint8 *) malloc(MAX_2BIT_TILES * 64);
378 	IPPU.TileCache[TILE_2BIT_ODD]   = (uint8 *) malloc(MAX_2BIT_TILES * 64);
379 	IPPU.TileCache[TILE_4BIT_EVEN]  = (uint8 *) malloc(MAX_4BIT_TILES * 64);
380 	IPPU.TileCache[TILE_4BIT_ODD]   = (uint8 *) malloc(MAX_4BIT_TILES * 64);
381 
382 	IPPU.TileCached[TILE_2BIT]      = (uint8 *) malloc(MAX_2BIT_TILES);
383 	IPPU.TileCached[TILE_4BIT]      = (uint8 *) malloc(MAX_4BIT_TILES);
384 	IPPU.TileCached[TILE_8BIT]      = (uint8 *) malloc(MAX_8BIT_TILES);
385 	IPPU.TileCached[TILE_2BIT_EVEN] = (uint8 *) malloc(MAX_2BIT_TILES);
386 	IPPU.TileCached[TILE_2BIT_ODD]  = (uint8 *) malloc(MAX_2BIT_TILES);
387 	IPPU.TileCached[TILE_4BIT_EVEN] = (uint8 *) malloc(MAX_4BIT_TILES);
388 	IPPU.TileCached[TILE_4BIT_ODD]  = (uint8 *) malloc(MAX_4BIT_TILES);
389 
390 
391 	/* don't render subscreen speed hack - disable this by default by
392 	turning the variable (RenderSub - opposite of don't render sub) on */
393 
394 	PPU.RenderSub = TRUE;
395 	PPU.FullClipping = TRUE;
396 	coldata_update_screen = TRUE;
397 
398 	if (!Memory.RAM || !Memory.SRAM || !Memory.VRAM || !Memory.ROM ||
399 			!IPPU.TileCache[TILE_2BIT]       ||
400 			!IPPU.TileCache[TILE_4BIT]       ||
401 			!IPPU.TileCache[TILE_8BIT]       ||
402 			!IPPU.TileCache[TILE_2BIT_EVEN]  ||
403 			!IPPU.TileCache[TILE_2BIT_ODD]   ||
404 			!IPPU.TileCache[TILE_4BIT_EVEN]  ||
405 			!IPPU.TileCache[TILE_4BIT_ODD]   ||
406 			!IPPU.TileCached[TILE_2BIT]      ||
407 			!IPPU.TileCached[TILE_4BIT]      ||
408 			!IPPU.TileCached[TILE_8BIT]      ||
409 			!IPPU.TileCached[TILE_2BIT_EVEN] ||
410 			!IPPU.TileCached[TILE_2BIT_ODD]  ||
411 			!IPPU.TileCached[TILE_4BIT_EVEN] ||
412 			!IPPU.TileCached[TILE_4BIT_ODD])
413 	{
414 		Deinit();
415 		return (FALSE);
416 	}
417 
418 	memset(Memory.RAM, 0,  0x20000);
419 	memset(Memory.SRAM, 0, 0x80000);
420 	memset(Memory.VRAM, 0, 0x10000);
421 	memset(Memory.ROM, 0,  MAX_ROM_SIZE + 0x200 + 0x8000);
422 
423 	memset(IPPU.TileCache[TILE_2BIT], 0, MAX_2BIT_TILES * 64);
424 	memset(IPPU.TileCache[TILE_4BIT], 0, MAX_4BIT_TILES * 64);
425 	memset(IPPU.TileCache[TILE_8BIT], 0, MAX_8BIT_TILES * 64);
426 	memset(IPPU.TileCache[TILE_2BIT_EVEN], 0,  MAX_2BIT_TILES * 64);
427 	memset(IPPU.TileCache[TILE_2BIT_ODD], 0,   MAX_2BIT_TILES * 64);
428 	memset(IPPU.TileCache[TILE_4BIT_EVEN], 0,  MAX_4BIT_TILES * 64);
429 	memset(IPPU.TileCache[TILE_4BIT_ODD], 0,   MAX_4BIT_TILES * 64);
430 
431 	memset(IPPU.TileCached[TILE_2BIT], 0,      MAX_2BIT_TILES);
432 	memset(IPPU.TileCached[TILE_4BIT], 0,      MAX_4BIT_TILES);
433 	memset(IPPU.TileCached[TILE_8BIT], 0,      MAX_8BIT_TILES);
434 	memset(IPPU.TileCached[TILE_2BIT_EVEN], 0, MAX_2BIT_TILES);
435 	memset(IPPU.TileCached[TILE_2BIT_ODD], 0,  MAX_2BIT_TILES);
436 	memset(IPPU.TileCached[TILE_4BIT_EVEN], 0, MAX_4BIT_TILES);
437 	memset(IPPU.TileCached[TILE_4BIT_ODD], 0,  MAX_4BIT_TILES);
438 
439 	/* FillRAM uses first 32K of ROM image area, otherwise space just
440 	wasted. Might be read by the SuperFX code. */
441 
442 	Memory.FillRAM = Memory.ROM;
443 
444 	/* Add 0x8000 to ROM image pointer to stop SuperFX code accessing
445 	unallocated memory (can cause crash on some ports). */
446 
447 	Memory.ROM += 0x8000;
448 
449 	Memory.C4RAM   = Memory.ROM + 0x400000 + 8192 * 8; /* C4 */
450 	Memory.OBC1RAM = Memory.ROM + 0x400000; /* OBC1 */
451 	Memory.BIOSROM = Memory.ROM + 0x300000; /* BS */
452 	Memory.BSRAM   = Memory.ROM + 0x400000; /* BS */
453 
454 	SuperFX.pvRegisters = Memory.FillRAM + 0x3000;
455 	SuperFX.nRamBanks   = 2; /* Most only use 1.  1=64KB=512Mb, 2=128KB=1024Mb */
456 	SuperFX.pvRam       = Memory.SRAM;
457 	SuperFX.nRomBanks   = (2 * 1024 * 1024) / (32 * 1024);
458 	SuperFX.pvRom       = (uint8 *) Memory.ROM;
459 
460 	return (TRUE);
461 }
462 
Safe(const char * s)463 static char * Safe (const char *s)
464 {
465 	static char	*safe = NULL;
466 	static int	safe_len = 0;
467 	int		i, len;
468 
469 	if (s == NULL)
470 	{
471 		if (safe)
472 		{
473 			free(safe);
474 			safe = NULL;
475 		}
476 
477 		return (NULL);
478 	}
479 
480 	len = strlen(s);
481 	if (!safe || len + 1 > safe_len)
482 	{
483 		if (safe)
484 			free(safe);
485 
486 		safe_len = len + 1;
487 		safe = (char *) malloc(safe_len);
488 	}
489 
490 	for ( i = 0; i < len; i++)
491 	{
492 		if (s[i] >= 32 && s[i] < 127)
493 			safe[i] = s[i];
494 		else
495 			safe[i] = '_';
496 	}
497 
498 	safe[len] = 0;
499 
500 	return (safe);
501 }
502 
SafeANK(uint8 ROMRegion,const char * s)503 static char * SafeANK (uint8 ROMRegion, const char *s)
504 {
505 	static char	*safe = NULL;
506 	static int	safe_len = 0;
507 	int		i, len;
508 
509 	if (s == NULL)
510 	{
511 		if (safe)
512 		{
513 			free(safe);
514 			safe = NULL;
515 		}
516 
517 		return (NULL);
518 	}
519 
520 	len = strlen(s);
521 	if (!safe || len + 1 > safe_len)
522 	{
523 		if (safe)
524 			free(safe);
525 
526 		safe_len = len + 1;
527 		safe = (char *) malloc(safe_len);
528 	}
529 
530 	for ( i = 0; i < len; i++)
531 	{
532 		if (s[i] >= 32 && s[i] < 127) /* ASCII */
533 			safe [i] = s[i];
534 		else
535 		if (ROMRegion == 0 && ((uint8) s[i] >= 0xa0 && (uint8) s[i] < 0xe0)) /* JIS X 201 - Katakana */
536 			safe [i] = s[i];
537 		else
538 			safe [i] = '_';
539 	}
540 
541 	safe [len] = 0;
542 
543 	return (safe);
544 }
545 
Deinit(void)546 void Deinit (void)
547 {
548 	int t;
549 	if (Memory.RAM)
550 	{
551 		free(Memory.RAM);
552 		Memory.RAM = NULL;
553 	}
554 
555 	if (Memory.SRAM)
556 	{
557 		free(Memory.SRAM);
558 		Memory.SRAM = NULL;
559 	}
560 
561 	if (Memory.VRAM)
562 	{
563 		free(Memory.VRAM);
564 		Memory.VRAM = NULL;
565 	}
566 
567 	if (Memory.ROM)
568 	{
569 		Memory.ROM -= 0x8000;
570 		free(Memory.ROM);
571 		Memory.ROM = NULL;
572 	}
573 
574 	if(Settings.SPC7110 || Settings.SPC7110RTC)
575 	{
576 		S9xFreeSPC7110();
577 	}
578 
579 	for ( t = 0; t < 7; t++)
580 	{
581 		if (IPPU.TileCache[t])
582 		{
583 			free(IPPU.TileCache[t]);
584 			IPPU.TileCache[t] = NULL;
585 		}
586 
587 		if (IPPU.TileCached[t])
588 		{
589 			free(IPPU.TileCached[t]);
590 			IPPU.TileCached[t] = NULL;
591 		}
592 	}
593 
594 	Safe(NULL);
595 	SafeANK(Memory.ROMRegion, NULL);
596 }
597 
598 /* file management and ROM detection */
599 
allASCII(uint8 * b,int size)600 static bool8 allASCII (uint8 *b, int size)
601 {
602 	int i;
603 	for ( i = 0; i < size; i++)
604 	{
605 		if (b[i] < 32 || b[i] > 126)
606 			return (FALSE);
607 	}
608 
609 	return (TRUE);
610 }
611 
612 #if SNES_SUPPORT_MULTI_CART
is_SufamiTurbo_BIOS(uint8 * data,uint32 size)613 static bool8 is_SufamiTurbo_BIOS (uint8 *data, uint32 size)
614 {
615 	if (size == 0x40000 && strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0
616 	&& strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) == 0)
617 		return TRUE;
618    return FALSE;
619 }
620 
is_SufamiTurbo_Cart(uint8 * data,uint32 size)621 static bool8 is_SufamiTurbo_Cart (uint8 *data, uint32 size)
622 {
623 	if (size >= 0x80000 && size <= 0x100000 && strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0
624 	&& strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) != 0)
625 		return TRUE;
626    return FALSE;
627 }
628 
is_SameGame_BIOS(uint8 * data,uint32 size)629 static bool8 is_SameGame_BIOS (uint8 *data, uint32 size)
630 {
631 	if (size == 0x100000 && strncmp((char *) (data + 0xffc0), "Same Game Tsume Game", 20) == 0)
632 		return (TRUE);
633    return (FALSE);
634 }
635 
is_SameGame_Add_On(uint8 * data,uint32 size)636 static bool8 is_SameGame_Add_On (uint8 *data, uint32 size)
637 {
638 	if (size == 0x80000)
639 		return (TRUE);
640    return (FALSE);
641 }
642 #endif
643 
ScoreHiROM(uint32 calculated_size,uint8 * rom,bool8 skip_header,int32 romoff)644 static int ScoreHiROM (uint32 calculated_size, uint8 * rom,  bool8 skip_header, int32 romoff)
645 {
646 	uint8	*buf;
647 	int score;
648 
649 	score = 0;
650 	buf = rom + 0xff00 + romoff + (skip_header ? 0x200 : 0);
651 
652 	if (buf[0xd5] & 0x1)
653 		score += 2;
654 
655 	/* Mode23 is SA-1 */
656 	if (buf[0xd5] == 0x23)
657 		score -= 2;
658 
659 	if (buf[0xd4] == 0x20)
660 		score += 2;
661 
662 	if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff)
663 	{
664 		score += 2;
665 		if (0 != (buf[0xde] + (buf[0xdf] << 8)))
666 			score++;
667 	}
668 
669 	if (buf[0xda] == 0x33)
670 		score += 2;
671 
672 	if ((buf[0xd5] & 0xf) < 4)
673 		score += 2;
674 
675 	if (!(buf[0xfd] & 0x80))
676 		score -= 6;
677 
678 	if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0)
679 		score -= 2; /* reduced after looking at a scan by Cowering */
680 
681 	if (calculated_size > 1024 * 1024 * 3)
682 		score += 4;
683 
684 	if ((1 << (buf[0xd7] - 7)) > 48)
685 		score -= 1;
686 
687 	if (!allASCII(&buf[0xb0], 6))
688 		score -= 1;
689 
690 	if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1))
691 		score -= 1;
692 
693 	return (score);
694 }
695 
ScoreLoROM(uint32 calculated_size,uint8 * rom,bool8 skip_header,int32 romoff)696 static int ScoreLoROM (uint32 calculated_size, uint8 * rom, bool8 skip_header, int32 romoff)
697 {
698 	uint8	*buf;
699 	int score;
700 
701 	score = 0;
702 	buf = rom + 0x7f00 + romoff + (skip_header ? 0x200 : 0);
703 
704 	if (!(buf[0xd5] & 0x1))
705 		score += 3;
706 
707 	/* Mode23 is SA-1 */
708 	if (buf[0xd5] == 0x23)
709 		score += 2;
710 
711 	if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff)
712 	{
713 		score += 2;
714 		if (0 != (buf[0xde] + (buf[0xdf] << 8)))
715 			score++;
716 	}
717 
718 	if (buf[0xda] == 0x33)
719 		score += 2;
720 
721 	if ((buf[0xd5] & 0xf) < 4)
722 		score += 2;
723 
724 	if (!(buf[0xfd] & 0x80))
725 		score -= 6;
726 
727 	if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0)
728 		score -= 2; /* reduced per Cowering suggestion */
729 
730 	if (calculated_size <= 1024 * 1024 * 16)
731 		score += 2;
732 
733 	if ((1 << (buf[0xd7] - 7)) > 48)
734 		score -= 1;
735 
736 	if (!allASCII(&buf[0xb0], 6))
737 		score -= 1;
738 
739 	if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1))
740 		score -= 1;
741 
742 	return (score);
743 }
744 
HeaderRemove(uint32 size,int32 * headerCount,uint8 * buf)745 static uint32 HeaderRemove (uint32 size, int32 * headerCount, uint8 *buf)
746 {
747 	uint32 calc_size = (size / 0x2000) * 0x2000;
748 
749 	if (size - calc_size == 512)
750 	{
751 		memmove(buf, buf + 512, calc_size);
752 		(*headerCount)++;
753 		size -= 512;
754 	}
755 
756 	return (size);
757 }
758 
FileLoader(uint8 * buffer,int32 maxsize)759 static uint32 FileLoader (uint8 *buffer, int32 maxsize)
760 {
761 	/* <- ROM size without header */
762 	/* ** Memory.HeaderCount */
763 	/* ** Memory.ROMFilename */
764 
765 	uint8	*ptr;
766 	uint64_t	size      = 0;
767 	STREAM fp          = OPEN_STREAM();
768 
769 	Memory.HeaderCount = 0;
770 	if (!fp)
771 		return (0);
772 
773 	ptr                = buffer;
774 
775    size               = READ_STREAM(ptr, (uint64_t)(
776             maxsize + 0x200), fp);
777    CLOSE_STREAM(fp);
778 
779    return HeaderRemove(size, &Memory.HeaderCount, ptr);
780 }
781 
caCRC32(uint8 * array,uint32 size,uint32 crc32)782 static uint32 caCRC32 (uint8 *array, uint32 size, uint32 crc32)
783 {
784 	uint32 i;
785 
786 	for ( i = 0; i < size; i++)
787 		crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ array[i]) & 0xFF];
788 
789 	return (~crc32);
790 }
791 
LoadROM(void)792 bool8 LoadROM (void)
793 {
794 	int	hi_score, lo_score, retry_count;
795 	bool8 interleaved, tales;
796 	uint8 * RomHeader;
797 	int32 totalFileSize;
798 
799 	retry_count = 0;
800 
801 	memset(Memory.ROM, 0, MAX_ROM_SIZE);
802 	memset(&Multi, 0, sizeof(Multi));
803 
804 again:
805 	Memory.CalculatedSize = 0;
806 	Memory.ExtendedFormat = NOPE;
807 
808 	totalFileSize = FileLoader(Memory.ROM, MAX_ROM_SIZE);
809 	if (!totalFileSize)
810 	{
811 		S9xMessage(S9X_MSG_ERROR, S9X_CATEGORY_ROM,
812 				"Unable to load ROM");
813 		return FALSE;
814 	}
815 
816 	hi_score = ScoreHiROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
817 	lo_score = ScoreLoROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
818 
819 	if (Memory.HeaderCount == 0 && !Settings.ForceNoHeader &&
820 		((hi_score >  lo_score && ScoreHiROM(Memory.CalculatedSize, Memory.ROM, TRUE, 0) > hi_score) ||
821 		 (hi_score <= lo_score && ScoreLoROM(Memory.CalculatedSize, Memory.ROM, TRUE, 0) > lo_score)))
822 	{
823 		memmove(Memory.ROM, Memory.ROM + 512, totalFileSize - 512);
824 		totalFileSize -= 512;
825 		S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_ROM, "Try 'force no-header' option if the game doesn't work");
826 		/* modifying ROM, so we need to rescore */
827 		hi_score = ScoreHiROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
828 		lo_score = ScoreLoROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
829 	}
830 
831 	Memory.CalculatedSize = (totalFileSize / 0x2000) * 0x2000;
832 
833 	if (Memory.CalculatedSize > 0x400000 &&
834 		(Memory.ROM[0x7fd5] + (Memory.ROM[0x7fd6] << 8)) != 0x4332 && /* exclude S-DD1 */
835 		(Memory.ROM[0x7fd5] + (Memory.ROM[0x7fd6] << 8)) != 0x4532 &&
836 		(Memory.ROM[0xffd5] + (Memory.ROM[0xffd6] << 8)) != 0xF93a && /* exclude SPC7110 */
837 		(Memory.ROM[0xffd5] + (Memory.ROM[0xffd6] << 8)) != 0xF53a)
838 		Memory.ExtendedFormat = YEAH;
839 
840 	/* if both vectors are invalid, it's type 1 interleaved LoROM */
841 	if (Memory.ExtendedFormat == NOPE &&
842 		((Memory.ROM[0x7ffc] + (Memory.ROM[0x7ffd] << 8)) < 0x8000) &&
843 		((Memory.ROM[0xfffc] + (Memory.ROM[0xfffd] << 8)) < 0x8000))
844 	{
845 		if (!Settings.ForceInterleaved && !Settings.ForceNotInterleaved)
846 			S9xDeinterleaveType1(totalFileSize, Memory.ROM);
847 	}
848 
849 	/* CalculatedSize is now set, so rescore */
850 	hi_score = ScoreHiROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
851 	lo_score = ScoreLoROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
852 
853 	RomHeader = Memory.ROM;
854 
855 	if (Memory.ExtendedFormat != NOPE)
856 	{
857 		int	swappedhirom, swappedlorom;
858 
859 		swappedhirom = ScoreHiROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0x400000);
860 		swappedlorom = ScoreLoROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0x400000);
861 
862 		/* set swapped here */
863 		if (max(swappedlorom, swappedhirom) >= max(lo_score, hi_score))
864 		{
865 			Memory.ExtendedFormat = BIGFIRST;
866 			hi_score = swappedhirom;
867 			lo_score = swappedlorom;
868 			RomHeader += 0x400000;
869 		}
870 		else
871 			Memory.ExtendedFormat = SMALLFIRST;
872 	}
873 
874 	interleaved = FALSE;
875 	tales = FALSE;
876 
877 	interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2 || Settings.ForceInterleaveGD24;
878 
879 	if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score))
880 	{
881 		Memory.LoROM = TRUE;
882 		Memory.HiROM = FALSE;
883 
884 		/* ignore map type byte if not 0x2x or 0x3x */
885 		if ((RomHeader[0x7fd5] & 0xf0) == 0x20 || (RomHeader[0x7fd5] & 0xf0) == 0x30)
886 		{
887 			switch (RomHeader[0x7fd5] & 0xf)
888 			{
889 				case 1:
890 					interleaved = TRUE;
891 					break;
892 
893 				case 5:
894 					interleaved = TRUE;
895 					tales = TRUE;
896 					break;
897 			}
898 		}
899 	}
900 	else
901 	{
902 		Memory.LoROM = FALSE;
903 		Memory.HiROM = TRUE;
904 
905 		if ((RomHeader[0xffd5] & 0xf0) == 0x20 || (RomHeader[0xffd5] & 0xf0) == 0x30)
906 		{
907 			switch (RomHeader[0xffd5] & 0xf)
908 			{
909 				case 0:
910 				case 3:
911 					interleaved = TRUE;
912 					break;
913 			}
914 		}
915 	}
916 
917 	/* these two games fail to be detected otherwise */
918 	if (!Settings.ForceHiROM && !Settings.ForceLoROM)
919 	{
920 		if (strncmp((char *) &Memory.ROM[0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0 ||
921 		   (strncmp((char *) &Memory.ROM[0xffc0], "BATMAN--REVENGE JOKER",  21) == 0))
922 		{
923 			Memory.LoROM = TRUE;
924 			Memory.HiROM = FALSE;
925 			interleaved = FALSE;
926 			tales = FALSE;
927 		}
928 	}
929 
930 	if (!Settings.ForceNotInterleaved && interleaved)
931 	{
932 		S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_ROM, "ROM image is in interleaved format - converting...");
933 
934 		if (tales)
935 		{
936 			if (Memory.ExtendedFormat == BIGFIRST)
937 			{
938 				S9xDeinterleaveType1(0x400000, Memory.ROM);
939 				S9xDeinterleaveType1(Memory.CalculatedSize - 0x400000, Memory.ROM + 0x400000);
940 			}
941 			else
942 			{
943 				S9xDeinterleaveType1(Memory.CalculatedSize - 0x400000, Memory.ROM);
944 				S9xDeinterleaveType1(0x400000, Memory.ROM + Memory.CalculatedSize - 0x400000);
945 			}
946 
947 			Memory.LoROM = FALSE;
948 			Memory.HiROM = TRUE;
949 		}
950 		else
951 		if (Settings.ForceInterleaveGD24 && Memory.CalculatedSize == 0x300000)
952 		{
953 			bool8	t = Memory.LoROM;
954 			Memory.LoROM = Memory.HiROM;
955 			Memory.HiROM = t;
956 			S9xDeinterleaveGD24(Memory.CalculatedSize, Memory.ROM);
957 		}
958 		else
959 		if (Settings.ForceInterleaved2)
960 			S9xDeinterleaveType2(Memory.CalculatedSize, Memory.ROM);
961 		else
962 		{
963 			bool8	t = Memory.LoROM;
964 			Memory.LoROM = Memory.HiROM;
965 			Memory.HiROM = t;
966 			S9xDeinterleaveType1(Memory.CalculatedSize, Memory.ROM);
967 		}
968 
969 		hi_score = ScoreHiROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
970 		lo_score = ScoreLoROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
971 
972 		if ((Memory.HiROM && (lo_score >= hi_score || hi_score < 0)) ||
973 			(Memory.LoROM && (hi_score >  lo_score || lo_score < 0)))
974 		{
975 			if (retry_count == 0)
976 			{
977 				S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_ROM, "ROM lied about its type! Trying again.");
978 				Settings.ForceNotInterleaved = TRUE;
979 				Settings.ForceInterleaved = FALSE;
980 				retry_count++;
981 				goto again;
982 			}
983 		}
984     }
985 
986 	if (Memory.ExtendedFormat == SMALLFIRST)
987 		tales = TRUE;
988 
989 	if (tales)
990 	{
991 		uint8	*tmp = (uint8 *) malloc(Memory.CalculatedSize - 0x400000);
992 		if (tmp)
993 		{
994 			S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_ROM, "Fixing swapped ExHiROM...");
995 			memcpy(tmp, Memory.ROM, Memory.CalculatedSize - 0x400000);
996 			memmove(Memory.ROM, Memory.ROM + Memory.CalculatedSize - 0x400000, 0x400000);
997 			memcpy(Memory.ROM + 0x400000, tmp, Memory.CalculatedSize - 0x400000);
998 			free(tmp);
999 		}
1000 	}
1001 
1002 	memset(&SNESGameFixes, 0, sizeof(SNESGameFixes));
1003 	SNESGameFixes.SRAMInitialValue = 0x60;
1004 
1005 	if(InitROM() != TRUE)
1006 		return (FALSE);
1007 
1008 	S9xInitCheatData();
1009 	S9xApplyCheats();
1010 
1011 	S9xReset();
1012 
1013     return (TRUE);
1014 }
1015 
1016 #if SNES_SUPPORT_MULTI_CART
LoadMultiCart(const char * cartA,const char * cartB)1017 bool8 LoadMultiCart (const char *cartA, const char *cartB)
1018 {
1019 	bool8 r;
1020 
1021 	r = TRUE;
1022 
1023 	memset(Memory.ROM, 0, MAX_ROM_SIZE);
1024 	memset(&Multi, 0, sizeof(Multi));
1025 
1026 	Memory.CalculatedSize = 0;
1027 	Memory.ExtendedFormat = NOPE;
1028 
1029 	if (cartA && cartA[0])
1030 		Multi.cartSizeA = FileLoader(Memory.ROM, cartA, MAX_ROM_SIZE);
1031 
1032 	if (Multi.cartSizeA == 0)
1033 	{
1034 		if (cartB && cartB[0])
1035 			Multi.cartSizeB = FileLoader(Memory.ROM, cartB, MAX_ROM_SIZE);
1036 	}
1037 
1038 	if (Multi.cartSizeA)
1039 	{
1040 		if (is_SufamiTurbo_Cart(Memory.ROM, Multi.cartSizeA))
1041 			Multi.cartType = 4;
1042 		else
1043 		if (is_SameGame_BIOS(Memory.ROM, Multi.cartSizeA))
1044 			Multi.cartType = 3;
1045 	}
1046 	else
1047 	if (Multi.cartSizeB)
1048 	{
1049 		if (is_SufamiTurbo_Cart(Memory.ROM, Multi.cartSizeB))
1050 			Multi.cartType = 4;
1051 	}
1052 	else
1053 		Multi.cartType = 4; /* assuming BIOS only */
1054 
1055 	switch (Multi.cartType)
1056 	{
1057 		case 4:
1058 			r = LoadSufamiTurbo(cartA, cartB);
1059 			break;
1060 
1061 		case 3:
1062 			r = LoadSameGame(cartA, cartB);
1063 			break;
1064 
1065 		default:
1066 			r = FALSE;
1067 	}
1068 
1069 	if (!r)
1070 	{
1071 		memset(&Multi, 0, sizeof(Multi));
1072 		return (FALSE);
1073 	}
1074 
1075 	memset(&SNESGameFixes, 0, sizeof(SNESGameFixes));
1076 	SNESGameFixes.SRAMInitialValue = 0x60;
1077 
1078 	if(InitROM() != TRUE)
1079 		return (FALSE);
1080 
1081 	S9xInitCheatData();
1082 	S9xApplyCheats();
1083 
1084 	S9xReset();
1085 
1086 	return (TRUE);
1087 }
1088 
LoadSufamiTurbo(const char * cartA,const char * cartB)1089 bool8 LoadSufamiTurbo (const char *cartA, const char *cartB)
1090 {
1091 	RFILE *fp = NULL;
1092 	int64_t	size;
1093 	char	path[PATH_MAX + 1];
1094 
1095 	Multi.cartOffsetA = 0x100000;
1096 	Multi.cartOffsetB = 0x200000;
1097 	Multi.sramA = Memory.SRAM;
1098 	Multi.sramB = Memory.SRAM + 0x10000;
1099 
1100 	if (Multi.cartSizeA)
1101 	{
1102 		Multi.sramSizeA = 4; /* ROM[0x37]? */
1103 		Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0;
1104 
1105 		strcpy(Multi.fileNameA, cartA);
1106 		memcpy(Memory.ROM + Multi.cartOffsetA, Memory.ROM, Multi.cartSizeA);
1107 	}
1108 
1109 	if (Multi.cartSizeA && !Multi.cartSizeB)
1110 	{
1111 		if (cartB && cartB[0])
1112 			Multi.cartSizeB = FileLoader(Memory.ROM, cartB, MAX_ROM_SIZE);
1113 
1114 		if (Multi.cartSizeB)
1115 		{
1116 			if (!is_SufamiTurbo_Cart(Memory.ROM, Multi.cartSizeB))
1117 				Multi.cartSizeB = 0;
1118 		}
1119 	}
1120 
1121 	if (Multi.cartSizeB)
1122 	{
1123 		Multi.sramSizeB = 4; /* ROM[0x37]? */
1124 		Multi.sramMaskB = Multi.sramSizeB ? ((1 << (Multi.sramSizeB + 3)) * 128 - 1) : 0;
1125 
1126 		strcpy(Multi.fileNameB, cartB);
1127 		memcpy(Memory.ROM + Multi.cartOffsetB, Memory.ROM, Multi.cartSizeB);
1128 	}
1129 
1130 	strcpy(path, S9xGetDirectory(BIOS_DIR));
1131 	strcat(path, SLASH_STR);
1132 	strcat(path, "STBIOS.bin");
1133 
1134 	fp = filestream_open(path, RETRO_VFS_FILE_ACCESS_READ,
1135 			RETRO_VFS_FILE_ACCESS_HINT_NONE);
1136 
1137 	if (fp)
1138 	{
1139 		size = filestream_read(fp, (void *)Memory.ROM, 0x40000);
1140 		filestream_close(fp);
1141 
1142 		if ((size <= 0) || !is_SufamiTurbo_BIOS(Memory.ROM, (size_t)size))
1143 			return (FALSE);
1144 	}
1145 	else
1146 		return (FALSE);
1147 
1148 	Memory.LoROM = TRUE;
1149 	Memory.HiROM = FALSE;
1150 	Memory.CalculatedSize = 0x40000;
1151 
1152 	return (TRUE);
1153 }
1154 
LoadSameGame(const char * cartA,const char * cartB)1155 bool8 LoadSameGame (const char *cartA, const char *cartB)
1156 {
1157 	Multi.cartOffsetA = 0;
1158 	Multi.cartOffsetB = 0x200000;
1159 	Multi.sramA = Memory.SRAM;
1160 	Multi.sramB = NULL;
1161 
1162 	Multi.sramSizeA = Memory.ROM[0xffd8];
1163 	Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0;
1164 	Multi.sramSizeB = 0;
1165 	Multi.sramMaskB = 0;
1166 
1167 	strcpy(Multi.fileNameA, cartA);
1168 
1169 	if (cartB && cartB[0])
1170 		Multi.cartSizeB = FileLoader(Memory.ROM + Multi.cartOffsetB, cartB, MAX_ROM_SIZE - Multi.cartOffsetB);
1171 
1172 	if (Multi.cartSizeB)
1173 	{
1174 		if (!is_SameGame_Add_On(Memory.ROM + Multi.cartOffsetB, Multi.cartSizeB))
1175 			Multi.cartSizeB = 0;
1176 		else
1177 			strcpy(Multi.fileNameB, cartB);
1178 	}
1179 
1180 	Memory.LoROM = FALSE;
1181 	Memory.HiROM = TRUE;
1182 	Memory.CalculatedSize = Multi.cartSizeA;
1183 
1184 	return (TRUE);
1185 }
1186 #endif /* SNES_SUPPORT_MULTI_CART */
1187 
1188 #define MAP_INITIALIZE() \
1189 { \
1190 	int c; \
1191 	for ( c = 0; c < 0x1000; c++) \
1192 	{ \
1193 		Memory.Map[c]      = (uint8 *) MAP_NONE; \
1194 		Memory.WriteMap[c] = (uint8 *) MAP_NONE; \
1195 		Memory.BlockIsROM[c] = FALSE; \
1196 		Memory.BlockIsRAM[c] = FALSE; \
1197 	} \
1198 }
1199 
checksum_calc_sum(uint8 * data,uint32 length)1200 static uint16 checksum_calc_sum (uint8 *data, uint32 length)
1201 {
1202 	uint32 i;
1203 	uint16 sum;
1204 
1205 	sum = 0;
1206 
1207 	for ( i = 0; i < length; i++)
1208 		sum += data[i];
1209 
1210 	return (sum);
1211 }
1212 
checksum_mirror_sum(uint8 * start,uint32 * length,uint32 mask)1213 static uint16 checksum_mirror_sum (uint8 *start, uint32 * length, uint32 mask)
1214 {
1215 	uint16 part1, part2;
1216 	uint32 next_length;
1217 
1218 	/* from NSRT */
1219 	while (!(*length & mask))
1220 		mask >>= 1;
1221 
1222 	part1 = checksum_calc_sum(start, mask);
1223 	part2 = 0;
1224 
1225 	next_length = *length - mask;
1226 	if (next_length)
1227 	{
1228 		part2 = checksum_mirror_sum(start + mask, &next_length, mask >> 1);
1229 
1230 		while (next_length < mask)
1231 		{
1232 			next_length += next_length;
1233 			part2 += part2;
1234 		}
1235 
1236 		*length = mask + mask;
1237 	}
1238 
1239 	return (part1 + part2);
1240 }
1241 
map_mirror(uint32 size,uint32 pos)1242 static uint32 map_mirror (uint32 size, uint32 pos)
1243 {
1244 	uint32 mask;
1245 	/* from bsnes */
1246 	if (size == 0)
1247 		return (0);
1248 	if (pos < size)
1249 		return (pos);
1250 
1251 	mask = UINT32_C(1) << 31;
1252 	while (!(pos & mask))
1253 		mask >>= 1;
1254 
1255 	if (size <= (pos & mask))
1256 		return (map_mirror(size, pos - mask));
1257    return (mask + map_mirror(size - mask, pos - mask));
1258 }
1259 
1260 #define MATCH_NA(str) (strcmp(Memory.ROMName, str) == 0)
1261 #define MATCH_NN(str) (strncmp(Memory.ROMName, str, strlen(str)) == 0)
1262 #define MATCH_NC(str) (strncasecmp(Memory.ROMName, str, strlen(str)) == 0)
1263 #define MATCH_ID(str) (strncmp(Memory.ROMId, str, strlen(str)) == 0)
1264 
1265 #define MAP_HIROM(bank_s, bank_e, addr_s, addr_e, size, auto_export_map) \
1266 { \
1267 	uint32 i, c; \
1268 	for ( c = bank_s; c <= bank_e; c++) \
1269 	{ \
1270 		for ( i = addr_s; i <= addr_e; i += 0x1000) \
1271 		{ \
1272 			uint32 p = (c << 4) | (i >> 12); \
1273 			uint32 addr = c << 16; \
1274 			Memory.Map[p] = Memory.ROM + map_mirror(size, addr); \
1275 			Memory.BlockIsROM[p] = TRUE; \
1276 			Memory.BlockIsRAM[p] = FALSE; \
1277 		} \
1278 	} \
1279 	if (auto_export_map) \
1280 	{ \
1281 		MAP_LIBRETRO(RETRO_MEMDESC_CONST, Memory.ROM, map_mirror(size, addr_s), 0, \
1282 			size - map_mirror(size, addr_s), bank_s,bank_e,addr_s,addr_e); \
1283 	} \
1284 }
1285 
1286 #define MAP_INDEX(bank_s, bank_e, addr_s, addr_e, index, type, auto_export_map) \
1287 { \
1288 	uint32 i, c; \
1289 	for ( c = bank_s; c <= bank_e; c++) \
1290 	{ \
1291 		for ( i = addr_s; i <= addr_e; i += 0x1000) \
1292 		{ \
1293 			uint32 p = (c << 4) | (i >> 12); \
1294 			Memory.Map[p] = (uint8 *) index; \
1295 			Memory.BlockIsROM[p] = ((type == MAP_TYPE_I_O) || (type == MAP_TYPE_RAM)) ? FALSE : TRUE; \
1296 			Memory.BlockIsRAM[p] = ((type == MAP_TYPE_I_O) || (type == MAP_TYPE_ROM)) ? FALSE : TRUE; \
1297 		} \
1298 	} \
1299 	if (auto_export_map) \
1300 	{ \
1301 		if (type==MAP_LOROM_SRAM || type==MAP_SA1RAM) \
1302 			MAP_LIBRETRO(0, Memory.SRAM, 0, 0x8000, Memory.SRAMMask+1, bank_s,bank_e,addr_s,addr_e); \
1303 		if (type==MAP_LOROM_SRAM_B) \
1304 			MAP_LIBRETRO(0, Multi.sramB, 0, 0x8000, Multi.sramMaskB+1, bank_s,bank_e,addr_s,addr_e); \
1305 		if (type==MAP_HIROM_SRAM || type==MAP_RONLY_SRAM) \
1306 			MAP_LIBRETRO(0, Memory.SRAM, 0, 0xE000, Memory.SRAMMask+1, bank_s,bank_e,addr_s,addr_e); \
1307 	} \
1308 }
1309 
1310 #define MAP_SPACE(bank_s, bank_e, addr_s, addr_e, data, auto_export_map) \
1311 { \
1312 	uint32 i,x; \
1313 	for ( x = bank_s; x <= bank_e; x++) \
1314 	{ \
1315 		for ( i = addr_s; i <= addr_e; i += 0x1000) \
1316 		{ \
1317 			uint32 p = (x << 4) | (i >> 12); \
1318 			Memory.Map[p] = data; \
1319 			Memory.BlockIsROM[p] = FALSE; \
1320 			Memory.BlockIsRAM[p] = TRUE; \
1321 		} \
1322 	} \
1323 	if (auto_export_map) \
1324 	{ \
1325 		MAP_LIBRETRO(0, data, 0, 0xFF0000, 0, bank_s,bank_e,addr_s,addr_e); \
1326 	} \
1327 }
1328 
1329 #define MAP_LOROM_OFFSET(bank_s, bank_e, addr_s, addr_e, size, offset, auto_export_map) \
1330 { \
1331 	uint32 i, c; \
1332 	for ( c = bank_s; c <= bank_e; c++) \
1333 	{ \
1334 		for ( i = addr_s; i <= addr_e; i += 0x1000) \
1335 		{ \
1336 			uint32 p = (c << 4) | (i >> 12); \
1337 			uint32 addr = ((c - bank_s) & 0x7f) * 0x8000; \
1338 			Memory.Map[p] = Memory.ROM + offset + map_mirror(size, addr) - (i & 0x8000); \
1339 			Memory.BlockIsROM[p] = TRUE; \
1340 			Memory.BlockIsRAM[p] = FALSE; \
1341 		} \
1342 	} \
1343 	if (auto_export_map) \
1344 	{ \
1345 		MAP_LIBRETRO(RETRO_MEMDESC_CONST, Memory.ROM, offset, 0x8000, size, bank_s,bank_e,addr_s,addr_e); \
1346 	} \
1347 }
1348 
1349 #define MAP_HIROM_OFFSET(bank_s, bank_e, addr_s, addr_e, size, offset, auto_export_map) \
1350 { \
1351 	uint32 i, c; \
1352 	for ( c = bank_s; c <= bank_e; c++) \
1353 	{ \
1354 		for ( i = addr_s; i <= addr_e; i += 0x1000) \
1355 		{ \
1356 			uint32 p = (c << 4) | (i >> 12); \
1357 			uint32 addr = (c - bank_s) << 16; \
1358 			Memory.Map[p] = Memory.ROM + offset + map_mirror(size, addr); \
1359 			Memory.BlockIsROM[p] = TRUE; \
1360 			Memory.BlockIsRAM[p] = FALSE; \
1361 		} \
1362 	} \
1363 	if (auto_export_map) \
1364 	{ \
1365 		MAP_LIBRETRO(RETRO_MEMDESC_CONST, Memory.ROM, map_mirror(size, offset + addr_s), 0, size, bank_s,bank_e,addr_s,addr_e); \
1366 	} \
1367 }
1368 
1369 #define MAP_LOROMSRAM() \
1370 	MAP_INDEX(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM, true); \
1371 	MAP_INDEX(0xf0, 0xff, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM, true);
1372 
1373 #define MAP_WRAM() \
1374 	/* will overwrite others */ \
1375 	MAP_SPACE(0x7e, 0x7e, 0x0000, 0xffff, Memory.RAM, true); \
1376 	MAP_SPACE(0x7f, 0x7f, 0x0000, 0xffff, Memory.RAM + 0x10000, true);
1377 
1378 #define MAP_SYSTEM() \
1379 	/* will be overwritten */ \
1380 	MAP_SPACE(0x00, 0x3f, 0x0000, 0x1fff, Memory.RAM, true); \
1381 	MAP_INDEX(0x00, 0x3f, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O, true); \
1382 	MAP_INDEX(0x00, 0x3f, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O, true); \
1383 	MAP_SPACE(0x80, 0xbf, 0x0000, 0x1fff, Memory.RAM, true); \
1384 	MAP_INDEX(0x80, 0xbf, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O, true); \
1385 	MAP_INDEX(0x80, 0xbf, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O, true);
1386 
map_WriteProtectROM(void)1387 void map_WriteProtectROM (void)
1388 {
1389 	int c;
1390 	memcpy((void *) Memory.WriteMap, (void *)Memory.Map, sizeof(Memory.Map));
1391 
1392 	for ( c = 0; c < 0x1000; c++)
1393 	{
1394 		if (Memory.BlockIsROM[c])
1395 			Memory.WriteMap[c] = (uint8 *) MAP_NONE;
1396 	}
1397 }
1398 
1399 #define MAP_JUMBOLOROMMAP() \
1400 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, "Map_JumboLoROMMap"); \
1401 	MAP_SYSTEM(); \
1402 	MAP_LOROM_OFFSET(0x00, 0x3f, 0x8000, 0xffff, Memory.CalculatedSize - 0x400000, 0x400000, true); \
1403 	MAP_LOROM_OFFSET(0x40, 0x7f, 0x0000, 0xffff, Memory.CalculatedSize - 0x600000, 0x600000, true); \
1404 	MAP_LOROM_OFFSET(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0, true); \
1405 	MAP_LOROM_OFFSET(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0x200000, true); \
1406 	MAP_LOROMSRAM(); \
1407 	MAP_WRAM(); \
1408 	map_WriteProtectROM();
1409 
1410 #define MAP_LOROM(bank_s, bank_e, addr_s, addr_e, size, auto_export_map) \
1411 { \
1412 	uint32 i, c; \
1413 	for ( c = bank_s; c <= bank_e; c++) \
1414 	{ \
1415 		for ( i = addr_s; i <= addr_e; i += 0x1000) \
1416 		{ \
1417 			uint32 p = (c << 4) | (i >> 12); \
1418 			uint32 addr = (c & 0x7f) * 0x8000; \
1419 			Memory.Map[p] = Memory.ROM + map_mirror(size, addr) - (i & 0x8000); \
1420 			Memory.BlockIsROM[p] = TRUE; \
1421 			Memory.BlockIsRAM[p] = FALSE; \
1422 		} \
1423 	} \
1424 	if (auto_export_map) \
1425 	{ \
1426 		MAP_LIBRETRO(RETRO_MEMDESC_CONST, Memory.ROM, 0, 0x8000, size, bank_s,bank_e,addr_s,addr_e); \
1427 	} \
1428 }
1429 
1430 #define MAP_SRAM512KLOROMMAP() \
1431 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, "Map_SRAM512KLoROMMap"); \
1432 	MAP_SYSTEM(); \
1433 	MAP_LOROM(0x00, 0x3f, 0x8000, 0xffff, Memory.CalculatedSize, true); \
1434 	MAP_LOROM(0x40, 0x7f, 0x0000, 0xffff, Memory.CalculatedSize, true); \
1435 	MAP_LOROM(0x80, 0xbf, 0x8000, 0xffff, Memory.CalculatedSize, true); \
1436 	MAP_LOROM(0xc0, 0xff, 0x0000, 0xffff, Memory.CalculatedSize, true); \
1437 	MAP_SPACE(0x70, 0x70, 0x0000, 0xffff, Memory.SRAM, true); \
1438 	MAP_SPACE(0x71, 0x71, 0x0000, 0xffff, Memory.SRAM + 0x8000, true); \
1439 	MAP_SPACE(0x72, 0x72, 0x0000, 0xffff, Memory.SRAM + 0x10000, true); \
1440 	MAP_SPACE(0x73, 0x73, 0x0000, 0xffff, Memory.SRAM + 0x18000, true); \
1441 	MAP_WRAM(); \
1442 	map_WriteProtectROM();
1443 
1444 #define MAP_DSP_() \
1445 	switch (DSP0.maptype) \
1446 	{ \
1447 		case M_DSP1_LOROM_S: \
1448 			MAP_INDEX(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O, true); \
1449 			MAP_INDEX(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O, true); \
1450 			break; \
1451 		case M_DSP1_LOROM_L: \
1452 			MAP_INDEX(0x60, 0x6f, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O, true); \
1453 			MAP_INDEX(0xe0, 0xef, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O, true); \
1454 			break; \
1455 		case M_DSP1_HIROM: \
1456 			MAP_INDEX(0x00, 0x1f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O, true); \
1457 			MAP_INDEX(0x80, 0x9f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O, true); \
1458 			break; \
1459 		case M_DSP2_LOROM: \
1460 			MAP_INDEX(0x20, 0x3f, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O, true); \
1461 			MAP_INDEX(0x20, 0x3f, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O, true); \
1462 			MAP_INDEX(0xa0, 0xbf, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O, true); \
1463 			MAP_INDEX(0xa0, 0xbf, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O, true); \
1464 			break; \
1465 		case M_DSP3_LOROM: \
1466 			MAP_INDEX(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O, true); \
1467 			MAP_INDEX(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O, true); \
1468 			break; \
1469 		case M_DSP4_LOROM: \
1470 			MAP_INDEX(0x30, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O, true); \
1471 			MAP_INDEX(0xb0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O, true); \
1472 			break; \
1473 	}
1474 
1475 #define MAP_C4_() \
1476 	MAP_INDEX(0x00, 0x3f, 0x6000, 0x7fff, MAP_C4, MAP_TYPE_I_O, true); \
1477 	MAP_INDEX(0x80, 0xbf, 0x6000, 0x7fff, MAP_C4, MAP_TYPE_I_O, true);
1478 
1479 #define MAP_OBC1() \
1480 	MAP_INDEX(0x00, 0x3f, 0x6000, 0x7fff, MAP_OBC_RAM, MAP_TYPE_I_O, true); \
1481 	MAP_INDEX(0x80, 0xbf, 0x6000, 0x7fff, MAP_OBC_RAM, MAP_TYPE_I_O, true);
1482 
1483 #define MAP_SETARISC() \
1484 	MAP_INDEX(0x00, 0x3f, 0x3000, 0x3fff, MAP_SETA_RISC, MAP_TYPE_I_O, true); \
1485 	MAP_INDEX(0x80, 0xbf, 0x3000, 0x3fff, MAP_SETA_RISC, MAP_TYPE_I_O, true);
1486 
1487 #define MAP_LOROMMAP() \
1488 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, "Map_LoROMMap"); \
1489 	MAP_SYSTEM(); \
1490 	\
1491 	MAP_LOROM(0x00, 0x3f, 0x8000, 0xffff, Memory.CalculatedSize, true); \
1492 	MAP_LOROM(0x40, 0x7f, 0x0000, 0xffff, Memory.CalculatedSize, true); \
1493 	MAP_LOROM(0x80, 0xbf, 0x8000, 0xffff, Memory.CalculatedSize, true); \
1494 	MAP_LOROM(0xc0, 0xff, 0x0000, 0xffff, Memory.CalculatedSize, true); \
1495 	if (Settings.DSP) \
1496 	{ \
1497 		MAP_DSP_(); \
1498 	} \
1499 	else if (Settings.C4) \
1500 	{ \
1501 		MAP_C4_(); \
1502 	} \
1503 	else if (Settings.OBC1) \
1504 	{ \
1505 		MAP_OBC1(); \
1506 	} \
1507 	else if (Settings.SETA == ST_018) \
1508 	{ \
1509 		MAP_SETARISC(); \
1510 	} \
1511 	MAP_LOROMSRAM(); \
1512 	MAP_WRAM(); \
1513 	map_WriteProtectROM();
1514 
1515 #define MAP_HIROMSRAM() \
1516 	MAP_INDEX(0x20, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM, true); \
1517 	MAP_INDEX(0xa0, 0xbf, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM, true);
1518 
1519 #define MAP_HIROMMAP() \
1520 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_ROM, "Map_HiROMMap"); \
1521 	MAP_SYSTEM(); \
1522 	MAP_HIROM(0x00, 0x3f, 0x8000, 0xffff, Memory.CalculatedSize, true); \
1523 	MAP_HIROM(0x40, 0x7f, 0x0000, 0xffff, Memory.CalculatedSize, true); \
1524 	MAP_HIROM(0x80, 0xbf, 0x8000, 0xffff, Memory.CalculatedSize, true); \
1525 	MAP_HIROM(0xc0, 0xff, 0x0000, 0xffff, Memory.CalculatedSize, true); \
1526 	\
1527 	if (Settings.DSP) \
1528 	{ \
1529 		MAP_DSP_(); \
1530 	} \
1531 	MAP_HIROMSRAM(); \
1532 	MAP_WRAM(); \
1533 	map_WriteProtectROM();
1534 
KartContents(uint8 ROMType)1535 static const char * KartContents (uint8 ROMType)
1536 {
1537 	static char			str[64];
1538 	static const char	*contents[3] = { "ROM", "ROM+RAM", "ROM+RAM+BAT" };
1539 	char	chip[16];
1540 
1541 	if (ROMType == 0 && !Settings.BS)
1542 		return ("ROM");
1543 
1544 	if (Settings.BS)
1545 		strcpy(chip, "+BS");
1546 	else
1547 	if (Settings.SuperFX)
1548 		strcpy(chip, "+Super FX");
1549 	else
1550 	if (Settings.SDD1)
1551 		strcpy(chip, "+S-DD1");
1552 	else
1553 	if (Settings.OBC1)
1554 		strcpy(chip, "+OBC1");
1555 	else
1556 	if (Settings.SA1)
1557    {
1558 		strcpy(chip, "+SA-1");
1559    }
1560 	else
1561 	if (Settings.SPC7110RTC)
1562 		strcpy(chip, "+SPC7110+RTC");
1563 	else
1564 	if (Settings.SPC7110)
1565 		strcpy(chip, "+SPC7110");
1566 	else
1567 	if (Settings.SRTC)
1568 		strcpy(chip, "+S-RTC");
1569 	else
1570 	if (Settings.C4)
1571 		strcpy(chip, "+C4");
1572 	else
1573 	if (Settings.SETA == ST_010)
1574 		strcpy(chip, "+ST-010");
1575 	else
1576 	if (Settings.SETA == ST_011)
1577 		strcpy(chip, "+ST-011");
1578 	else
1579 	if (Settings.SETA == ST_018)
1580 		strcpy(chip, "+ST-018");
1581 	else
1582 	if (Settings.DSP)
1583 		snprintf(chip, sizeof(chip), "+DSP-%d", Settings.DSP);
1584 	else
1585 		strcpy(chip, "");
1586 
1587 	snprintf(str, sizeof(str), "%s%s", contents[(ROMType & 0xf) % 3], chip);
1588 
1589 	return (str);
1590 }
1591 
Map_NoMAD1LoROMMap(void)1592 static void Map_NoMAD1LoROMMap (void)
1593 {
1594 	printf("Map_NoMAD1LoROMMap\n");
1595 	MAP_SYSTEM();
1596 
1597 	MAP_LOROM(0x00, 0x3f, 0x8000, 0xffff, Memory.CalculatedSize, true);
1598 	MAP_LOROM(0x40, 0x7f, 0x0000, 0xffff, Memory.CalculatedSize, true);
1599 	MAP_LOROM(0x80, 0xbf, 0x8000, 0xffff, Memory.CalculatedSize, true);
1600 	MAP_LOROM(0xc0, 0xff, 0x0000, 0xffff, Memory.CalculatedSize, true);
1601 
1602 	MAP_INDEX(0x70, 0x7f, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM, true);
1603 	MAP_INDEX(0xf0, 0xff, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM, true);
1604 
1605 	MAP_WRAM();
1606 
1607 	map_WriteProtectROM();
1608 }
1609 
Map_ROM24MBSLoROMMap(void)1610 static void Map_ROM24MBSLoROMMap (void)
1611 {
1612 	/* PCB: BSC-1A5M-01, BSC-1A7M-10*/
1613 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, "Map_ROM24MBSLoROMMap");
1614 	MAP_SYSTEM();
1615 
1616 	MAP_LOROM_OFFSET(0x00, 0x1f, 0x8000, 0xffff, 0x100000, 0, true);
1617 	MAP_LOROM_OFFSET(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000, true);
1618 	MAP_LOROM_OFFSET(0x80, 0x9f, 0x8000, 0xffff, 0x100000, 0x200000, true);
1619 	MAP_LOROM_OFFSET(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000, true);
1620 
1621 	MAP_LOROMSRAM();
1622 	MAP_WRAM();
1623 
1624 	map_WriteProtectROM();
1625 }
1626 
Map_SufamiTurboLoROMMap(void)1627 static void Map_SufamiTurboLoROMMap (void)
1628 {
1629 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, "Map_SufamiTurboLoROMMap");
1630 	MAP_SYSTEM();
1631 
1632 	MAP_LOROM_OFFSET(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0, true);
1633 	MAP_LOROM_OFFSET(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA, true);
1634 	MAP_LOROM_OFFSET(0x40, 0x5f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB, true);
1635 	MAP_LOROM_OFFSET(0x80, 0x9f, 0x8000, 0xffff, 0x40000, 0, true);
1636 	MAP_LOROM_OFFSET(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA, true);
1637 	MAP_LOROM_OFFSET(0xc0, 0xdf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB, true);
1638 
1639 	if (Multi.sramSizeA)
1640 	{
1641 		MAP_INDEX(0x60, 0x63, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM, true);
1642 		MAP_INDEX(0xe0, 0xe3, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM, true);
1643 	}
1644 
1645 	if (Multi.sramSizeB)
1646 	{
1647 		MAP_INDEX(0x70, 0x73, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM, true);
1648 		MAP_INDEX(0xf0, 0xf3, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM, true);
1649 	}
1650 
1651 	MAP_WRAM();
1652 
1653 	map_WriteProtectROM();
1654 }
1655 
Map_SufamiTurboPseudoLoROMMap(void)1656 static void Map_SufamiTurboPseudoLoROMMap (void)
1657 {
1658 	/* for combined images */
1659 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, "Map_SufamiTurboPseudoLoROMMap");
1660 	MAP_SYSTEM();
1661 
1662 	MAP_LOROM_OFFSET(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0, true);
1663 	MAP_LOROM_OFFSET(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000, true);
1664 	MAP_LOROM_OFFSET(0x40, 0x5f, 0x8000, 0xffff, 0x100000, 0x200000, true);
1665 	MAP_LOROM_OFFSET(0x80, 0x9f, 0x8000, 0xffff, 0x40000, 0, true);
1666 	MAP_LOROM_OFFSET(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000, true);
1667 	MAP_LOROM_OFFSET(0xc0, 0xdf, 0x8000, 0xffff, 0x100000, 0x200000, true);
1668 
1669 	/* I don't care :P */
1670 	MAP_SPACE(0x60, 0x63, 0x8000, 0xffff, Memory.SRAM - 0x8000, true);
1671 	MAP_SPACE(0xe0, 0xe3, 0x8000, 0xffff, Memory.SRAM - 0x8000, true);
1672 	MAP_SPACE(0x70, 0x73, 0x8000, 0xffff, Memory.SRAM + 0x4000 - 0x8000, false);//these two seem to duplicate the above ones in
1673 	MAP_SPACE(0xf0, 0xf3, 0x8000, 0xffff, Memory.SRAM + 0x4000 - 0x8000, false);//way that makes the duplicates hard to find.
1674 
1675 	MAP_WRAM();
1676 
1677 	map_WriteProtectROM();
1678 }
1679 
Map_SuperFXLoROMMap(void)1680 static void Map_SuperFXLoROMMap (void)
1681 {
1682 	int c;
1683 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, "Map_SuperFXLoROMMap");
1684 	MAP_SYSTEM();
1685 
1686 	/* Replicate the first 2Mbit of the ROM at ROM + 2Mbit such that each 32K
1687 	   block is repeated twice in each 64K block. */
1688 	for ( c = 0; c < 64; c++)
1689 	{
1690 		memcpy(&Memory.ROM[0x200000 + c * 0x10000], &Memory.ROM[c * 0x8000], 0x8000);
1691 		memcpy(&Memory.ROM[0x208000 + c * 0x10000], &Memory.ROM[c * 0x8000], 0x8000);
1692 	}
1693 
1694 	MAP_LOROM(0x00, 0x3f, 0x8000, 0xffff, Memory.CalculatedSize, true);
1695 	MAP_LOROM(0x80, 0xbf, 0x8000, 0xffff, Memory.CalculatedSize, true);
1696 
1697 	MAP_HIROM_OFFSET(0x40, 0x7f, 0x0000, 0xffff, Memory.CalculatedSize, 0, true);
1698 	MAP_HIROM_OFFSET(0xc0, 0xff, 0x0000, 0xffff, Memory.CalculatedSize, 0, true);
1699 
1700 	MAP_SPACE(0x00, 0x3f, 0x6000, 0x7fff, Memory.SRAM - 0x6000, true);
1701 	MAP_SPACE(0x80, 0xbf, 0x6000, 0x7fff, Memory.SRAM - 0x6000, true);
1702 	MAP_SPACE(0x70, 0x70, 0x0000, 0xffff, Memory.SRAM, true);
1703 	MAP_SPACE(0x71, 0x71, 0x0000, 0xffff, Memory.SRAM + 0x10000, true);
1704 
1705 	MAP_WRAM();
1706 
1707 	map_WriteProtectROM();
1708 }
1709 
Map_SetaDSPLoROMMap(void)1710 static void Map_SetaDSPLoROMMap (void)
1711 {
1712 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, "Map_SetaDSPLoROMMap");
1713 	MAP_SYSTEM();
1714 
1715 	MAP_LOROM(0x00, 0x3f, 0x8000, 0xffff, Memory.CalculatedSize, true);
1716 	MAP_LOROM(0x40, 0x7f, 0x8000, 0xffff, Memory.CalculatedSize, true);
1717 	MAP_LOROM(0x80, 0xbf, 0x8000, 0xffff, Memory.CalculatedSize, true);
1718 	MAP_LOROM(0xc0, 0xff, 0x8000, 0xffff, Memory.CalculatedSize, true);
1719 
1720 	/* where does the SETA chip access, anyway? */
1721 	/* please confirm this? */
1722 	MAP_INDEX(0x68, 0x6f, 0x0000, 0x7fff, MAP_SETA_DSP, MAP_TYPE_RAM, true);
1723 	/* and this! */
1724 	MAP_INDEX(0x60, 0x67, 0x0000, 0x3fff, MAP_SETA_DSP, MAP_TYPE_I_O, true);
1725 	/* ST-0010: */
1726 	/* MAP_INDEX(0x68, 0x6f, 0x0000, 0x0fff, MAP_SETA_DSP, ?); */
1727 
1728 	MAP_LOROMSRAM();
1729 	MAP_WRAM();
1730 
1731 	map_WriteProtectROM();
1732 }
1733 
Map_SDD1LoROMMap(void)1734 static void Map_SDD1LoROMMap (void)
1735 {
1736 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, "Map_SDD1LoROMMap");
1737 	MAP_SYSTEM();
1738 
1739 	MAP_LOROM(0x00, 0x3f, 0x8000, 0xffff, Memory.CalculatedSize, true);
1740 	MAP_LOROM(0x80, 0xbf, 0x8000, 0xffff, Memory.CalculatedSize, true);
1741 
1742 	MAP_HIROM_OFFSET(0x40, 0x7f, 0x0000, 0xffff, Memory.CalculatedSize, 0, true);
1743 	MAP_HIROM_OFFSET(0xc0, 0xff, 0x0000, 0xffff, Memory.CalculatedSize, 0, true); /* will be overwritten dynamically*/
1744 
1745 	MAP_INDEX(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM, true);
1746 
1747 	MAP_WRAM();
1748 
1749 	map_WriteProtectROM();
1750 }
1751 
Map_SA1LoROMMap(void)1752 static void Map_SA1LoROMMap (void)
1753 {
1754 	int c;
1755 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, "Map_SA1LoROMMap");
1756 	MAP_SYSTEM();
1757 
1758 	MAP_LOROM(0x00, 0x3f, 0x8000, 0xffff, Memory.CalculatedSize, true);
1759 	MAP_LOROM(0x80, 0xbf, 0x8000, 0xffff, Memory.CalculatedSize, true);
1760 
1761 	MAP_HIROM_OFFSET(0xc0, 0xff, 0x0000, 0xffff, Memory.CalculatedSize, 0, true);
1762 
1763 	MAP_SPACE(0x00, 0x3f, 0x3000, 0x3fff, Memory.FillRAM, true);
1764 	MAP_SPACE(0x80, 0xbf, 0x3000, 0x3fff, Memory.FillRAM, true);
1765 	MAP_INDEX(0x00, 0x3f, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O, true);
1766 	MAP_INDEX(0x80, 0xbf, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O, true);
1767 
1768 	for ( c = 0x40; c < 0x80; c++)
1769 	{
1770 		MAP_SPACE(c, c, 0x0000, 0xffff, Memory.SRAM + (c & 1) * 0x10000, false);
1771 	}
1772 
1773 	MAP_LIBRETRO_RAW(0, Memory.SRAM, 0, 0x400000, 0xC00000, 0xFE0000, 0x20000);
1774 
1775 	MAP_WRAM();
1776 
1777 	map_WriteProtectROM();
1778 
1779 	/* Now copy the map and correct it for the SA1 CPU. */
1780 	memcpy((void *) SA1.Map, (void *) Memory.Map, sizeof(Memory.Map));
1781 	memcpy((void *) SA1.WriteMap, (void *) Memory.WriteMap, sizeof(Memory.WriteMap));
1782 
1783 	/* SA-1 Banks 00->3f and 80->bf */
1784 	for ( c = 0x000; c < 0x400; c += 0x10)
1785 	{
1786 		SA1.Map[c + 0] = SA1.Map[c + 0x800] = Memory.FillRAM + 0x3000;
1787 		SA1.Map[c + 1] = SA1.Map[c + 0x801] = (uint8 *) MAP_NONE;
1788 		SA1.WriteMap[c + 0] = SA1.WriteMap[c + 0x800] = Memory.FillRAM + 0x3000;
1789 		SA1.WriteMap[c + 1] = SA1.WriteMap[c + 0x801] = (uint8 *) MAP_NONE;
1790 	}
1791 
1792 	/* SA-1 Banks 60->6f */
1793 	for ( c = 0x600; c < 0x700; c++)
1794 		SA1.Map[c] = SA1.WriteMap[c] = (uint8 *) MAP_BWRAM_BITMAP;
1795 
1796 	Memory.BWRAM = Memory.SRAM;
1797 }
1798 
Map_ExtendedHiROMMap(void)1799 static void Map_ExtendedHiROMMap (void)
1800 {
1801 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, "Map_ExtendedHiROMMap");
1802 	MAP_SYSTEM();
1803 
1804 	MAP_HIROM_OFFSET(0x00, 0x3f, 0x8000, 0xffff, Memory.CalculatedSize - 0x400000, 0x400000, true);
1805 	MAP_HIROM_OFFSET(0x40, 0x7f, 0x0000, 0xffff, Memory.CalculatedSize - 0x400000, 0x400000, true);
1806 	MAP_HIROM_OFFSET(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0, true);
1807 	MAP_HIROM_OFFSET(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0, true);
1808 
1809 	MAP_HIROMSRAM();
1810 	MAP_WRAM();
1811 
1812 	map_WriteProtectROM();
1813 }
1814 
Map_SameGameHiROMMap(void)1815 static void Map_SameGameHiROMMap (void)
1816 {
1817 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, "Map_SameGameHiROMMap");
1818 	MAP_SYSTEM();
1819 
1820 	MAP_HIROM_OFFSET(0x00, 0x1f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA, true);
1821 	MAP_HIROM_OFFSET(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB, true);
1822 	MAP_HIROM_OFFSET(0x40, 0x5f, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA, true);
1823 	MAP_HIROM_OFFSET(0x60, 0x7f, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB, true);
1824 	MAP_HIROM_OFFSET(0x80, 0x9f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA, true);
1825 	MAP_HIROM_OFFSET(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB, true);
1826 	MAP_HIROM_OFFSET(0xc0, 0xdf, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA, true);
1827 	MAP_HIROM_OFFSET(0xe0, 0xff, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB, true);
1828 
1829 	MAP_HIROMSRAM();
1830 	MAP_WRAM();
1831 
1832 	map_WriteProtectROM();
1833 }
1834 
Map_SPC7110HiROMMap(void)1835 static void Map_SPC7110HiROMMap (void)
1836 {
1837 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, "Map_SPC7110HiROMMap");
1838 	MAP_SYSTEM();
1839 
1840 	MAP_INDEX(0x00, 0x00, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM, true);
1841 	MAP_HIROM(0x00, 0x0f, 0x8000, 0xffff, Memory.CalculatedSize, true);
1842 	MAP_INDEX(0x30, 0x30, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM, true);
1843 	MAP_INDEX(0x50, 0x50, 0x0000, 0xffff, MAP_SPC7110_DRAM, MAP_TYPE_ROM, true);
1844 	MAP_HIROM(0x80, 0x8f, 0x8000, 0xffff, Memory.CalculatedSize, true);
1845 	MAP_HIROM_OFFSET(0xc0, 0xcf, 0x0000, 0xffff, Memory.CalculatedSize, 0, true);
1846 	MAP_INDEX(0xd0, 0xff, 0x0000, 0xffff, MAP_SPC7110_ROM,  MAP_TYPE_ROM, true);
1847 
1848 	MAP_WRAM();
1849 
1850 	map_WriteProtectROM();
1851 }
1852 
StaticRAMSize(void)1853 static const char * StaticRAMSize (void)
1854 {
1855 	static char	str[20];
1856 
1857 	if (Memory.SRAMSize > 16)
1858 		strcpy(str, "Corrupt");
1859 	else
1860 		snprintf(str, sizeof(str), "%dKbits", 8 * (Memory.SRAMMask + 1) / 1024);
1861 
1862 	return (str);
1863 }
1864 
Size(void)1865 static const char * Size (void)
1866 {
1867 	static char	str[20];
1868 
1869 	if (Multi.cartType == 4)
1870 		strcpy(str, "N/A");
1871 	else
1872 	if (Memory.ROMSize < 7 || Memory.ROMSize - 7 > 23)
1873 		strcpy(str, "Corrupt");
1874 	else
1875 		snprintf(str, sizeof(str), "%dMbits", 1 << (Memory.ROMSize - 7));
1876 
1877 	return (str);
1878 }
1879 
InitROM(void)1880 static bool8 InitROM (void)
1881 {
1882 	int p;
1883 	bool8 bs, isChecksumOK;
1884 	uint8 *RomHeader;
1885 	uint16 sum;
1886 	uint32 identifier;
1887 	char displayName[ROM_NAME_LEN], String[513];
1888 
1889 	Settings.SuperFX = FALSE;
1890 	Settings.DSP = 0;
1891 	Settings.SA1 = FALSE;
1892 	Settings.C4 = FALSE;
1893 	Settings.SDD1 = FALSE;
1894 	Settings.SPC7110 = FALSE;
1895 	Settings.SPC7110RTC = FALSE;
1896 	Settings.OBC1 = FALSE;
1897 	Settings.SETA = 0;
1898 	Settings.SRTC = FALSE;
1899 	Settings.BS = FALSE;
1900 	SuperFX.nRomBanks = Memory.CalculatedSize >> 15;
1901 
1902    Settings.SupportHiRes = TRUE;
1903 
1904 	/* Parse ROM header and read ROM information */
1905 
1906 	Memory.CompanyId = -1;
1907 	memset(Memory.ROMId, 0, 5);
1908 
1909 	RomHeader = Memory.ROM + 0x7FB0;
1910 	if (Memory.ExtendedFormat == BIGFIRST)
1911 		RomHeader += 0x400000;
1912 	if (Memory.HiROM)
1913 		RomHeader += 0x8000;
1914 
1915 	S9xInitBSX(); /* Set BS header before parsing */
1916 
1917 	/* Parse SNES Header */
1918 
1919 	bs = Settings.BS & !Settings.BSXItself;
1920 
1921 	strncpy(Memory.ROMName, (char *) &RomHeader[0x10], ROM_NAME_LEN - 1);
1922 	if (bs)
1923 		memset(Memory.ROMName + 16, 0x20, ROM_NAME_LEN - 17);
1924 
1925 	if (bs)
1926 	{
1927 		if (!(((RomHeader[0x29] & 0x20) && Memory.CalculatedSize <  0x100000) ||
1928 			 (!(RomHeader[0x29] & 0x20) && Memory.CalculatedSize == 0x100000)))
1929 			S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, "BS: Size mismatch");
1930 
1931 		/* FIXME*/
1932 		p = 0;
1933 		while ((1 << p) < (int) Memory.CalculatedSize)
1934 			p++;
1935 		Memory.ROMSize = p - 10;
1936 	}
1937 	else
1938 		Memory.ROMSize = RomHeader[0x27];
1939 
1940 	Memory.SRAMSize  = bs ? 5 /* BS-X */    : RomHeader[0x28];
1941 	Memory.ROMSpeed  = bs ? RomHeader[0x28] : RomHeader[0x25];
1942 	Memory.ROMType   = bs ? 0xE5 /* BS-X */ : RomHeader[0x26];
1943 	Memory.ROMRegion = bs ? 0               : RomHeader[0x29];
1944 
1945 	Memory.ROMChecksum           = RomHeader[0x2E] + (RomHeader[0x2F] << 8);
1946 	Memory.ROMComplementChecksum = RomHeader[0x2C] + (RomHeader[0x2D] << 8);
1947 
1948 	memcpy(Memory.ROMId, &RomHeader[0x02], 4);
1949 
1950 	if (RomHeader[0x2A] != 0x33)
1951 		Memory.CompanyId = ((RomHeader[0x2A] >> 4) & 0x0F) * 36 + (RomHeader[0x2A] & 0x0F);
1952 	else
1953 	if (isalnum(RomHeader[0x00]) && isalnum(RomHeader[0x01]))
1954 	{
1955 		int	l, r, l2, r2;
1956 		l = toupper(RomHeader[0x00]);
1957 		r = toupper(RomHeader[0x01]);
1958 		l2 = (l > '9') ? l - '7' : l - '0';
1959 		r2 = (r > '9') ? r - '7' : r - '0';
1960 		Memory.CompanyId = l2 * 36 + r2;
1961 	}
1962 
1963 	if (Memory.SRAMSize > 16 || Memory.ROMSize < 7 || Memory.ROMSize - 7 > 23)
1964 	{
1965 		S9xMessage(S9X_MSG_ERROR, S9X_CATEGORY_ROM,
1966 				"ROM is corrupt or invalid");
1967 		return (FALSE);
1968 	}
1969 
1970 	/* End of Parse SNES Header */
1971 
1972 	/* Detect and initialize chips
1973 	   detection codes are compatible with NSRT */
1974 
1975 	/* DSP1/2/3/4 */
1976 	if (Memory.ROMType == 0x03)
1977 	{
1978 		if (Memory.ROMSpeed == 0x30)
1979 			Settings.DSP = 4; /* DSP4 */
1980 		else
1981 			Settings.DSP = 1; /* DSP1 */
1982 	}
1983 	else if (Memory.ROMType == 0x05)
1984 	{
1985 		if (Memory.ROMSpeed == 0x20)
1986 			Settings.DSP = 2; /* DSP2 */
1987 		else
1988 		if (Memory.ROMSpeed == 0x30 && RomHeader[0x2a] == 0xb2)
1989 			Settings.DSP = 3; /* DSP3 */
1990 		else
1991 			Settings.DSP = 1; /* DSP1 */
1992 	}
1993 
1994 	switch (Settings.DSP)
1995 	{
1996 		case 1:	/* DSP1 */
1997 			if (Memory.HiROM)
1998 			{
1999 				DSP0.boundary = 0x7000;
2000 				DSP0.maptype = M_DSP1_HIROM;
2001 			}
2002 			else
2003 			if (Memory.CalculatedSize > 0x100000)
2004 			{
2005 				DSP0.boundary = 0x4000;
2006 				DSP0.maptype = M_DSP1_LOROM_L;
2007 			}
2008 			else
2009 			{
2010 				DSP0.boundary = 0xc000;
2011 				DSP0.maptype = M_DSP1_LOROM_S;
2012 			}
2013 
2014 			SetDSP = &DSP1SetByte;
2015 			GetDSP = &DSP1GetByte;
2016 			break;
2017 
2018 		case 2: /* DSP2 */
2019 			DSP0.boundary = 0x10000;
2020 			DSP0.maptype = M_DSP2_LOROM;
2021 			SetDSP = &DSP2SetByte;
2022 			GetDSP = &DSP2GetByte;
2023 			break;
2024 
2025 		case 3: /* DSP3 */
2026 			DSP0.boundary = 0xc000;
2027 			DSP0.maptype = M_DSP3_LOROM;
2028 			SetDSP = &DSP3SetByte;
2029 			GetDSP = &DSP3GetByte;
2030 			break;
2031 
2032 		case 4: /* DSP4 */
2033 			DSP0.boundary = 0xc000;
2034 			DSP0.maptype = M_DSP4_LOROM;
2035 			SetDSP = &DSP4SetByte;
2036 			GetDSP = &DSP4GetByte;
2037 			break;
2038 
2039 		default:
2040 			SetDSP = NULL;
2041 			GetDSP = NULL;
2042 			break;
2043 	}
2044 
2045 	identifier = ((Memory.ROMType & 0xff) << 8) + (Memory.ROMSpeed & 0xff);
2046 
2047 	switch (identifier)
2048 	{
2049 	    /* SRTC*/
2050 		case 0x5535:
2051 			Settings.SRTC = TRUE;
2052 			S9xInitSRTC();
2053 			break;
2054 
2055 		/* SPC7110*/
2056 		case 0xF93A:
2057 			Settings.SPC7110RTC = TRUE;
2058 			Settings.SPC7110    = TRUE;
2059 			S9xInitSPC7110();
2060 			break;
2061 		case 0xF53A:
2062 			Settings.SPC7110 = TRUE;
2063 			S9xInitSPC7110();
2064 			break;
2065 
2066 		/* OBC1*/
2067 		case 0x2530:
2068 			Settings.OBC1 = TRUE;
2069 			break;
2070 
2071 		/* SA1*/
2072 		case 0x3423:
2073 		case 0x3523:
2074 			Settings.SA1 = TRUE;
2075 			break;
2076 
2077 		/* SuperFX*/
2078 		case 0x1320:
2079 		case 0x1420:
2080 		case 0x1520:
2081 		case 0x1A20:
2082 			Settings.SuperFX = TRUE;
2083 			memset((uint8 *) &GSU, 0, sizeof(struct FxRegs_s));
2084 			if (Memory.ROM[0x7FDA] == 0x33)
2085 				Memory.SRAMSize = Memory.ROM[0x7FBD];
2086 			else
2087 				Memory.SRAMSize = 5;
2088 			break;
2089 
2090 		/* SDD1*/
2091 		case 0x4332:
2092 		case 0x4532:
2093 			Settings.SDD1 = TRUE;
2094 			break;
2095 
2096 		/* ST018*/
2097 		case 0xF530:
2098 			Settings.SETA = ST_018;
2099 			SetSETA = NULL;
2100 			GetSETA = NULL;
2101 			Memory.SRAMSize = 2;
2102 			SNESGameFixes.SRAMInitialValue = 0x00;
2103 			break;
2104 
2105 		/* ST010/011*/
2106 		case 0xF630:
2107 			if (Memory.ROM[0x7FD7] == 0x09)
2108 			{
2109 				Settings.SETA = ST_011;
2110 				SetSETA = &S9xSetST011;
2111 				GetSETA = &S9xGetST011;
2112 			}
2113 			else
2114 			{
2115 				Settings.SETA = ST_010;
2116 				SetSETA = &S9xSetST010;
2117 				GetSETA = &S9xGetST010;
2118 			}
2119 
2120 			Memory.SRAMSize = 2;
2121 			SNESGameFixes.SRAMInitialValue = 0x00;
2122 			break;
2123 
2124 		/* C4*/
2125 		case 0xF320:
2126 			Settings.C4 = TRUE;
2127 			break;
2128 	}
2129 
2130 	/* Map memory and calculate checksum */
2131 
2132 	MAP_INITIALIZE();
2133 	Memory.CalculatedChecksum = 0;
2134 
2135 	/* SRAM size */
2136 	Memory.SRAMMask = Memory.SRAMSize ? ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0;
2137 
2138 	if (Memory.HiROM)
2139 	{
2140 		if (Settings.BS)
2141 			/* Do nothing */;
2142 		else
2143 			if (Settings.SPC7110)
2144 				Map_SPC7110HiROMMap();
2145 			else
2146 				if (Memory.ExtendedFormat != NOPE)
2147 					Map_ExtendedHiROMMap();
2148 				else
2149 					if (Multi.cartType == 3)
2150 						Map_SameGameHiROMMap();
2151 					else
2152 					{
2153 						MAP_HIROMMAP();
2154 					}
2155 	}
2156 	else
2157 	{
2158 		if (Settings.BS)
2159 			/* Do nothing */;
2160 		else if (Settings.SETA && Settings.SETA != ST_018)
2161 			Map_SetaDSPLoROMMap();
2162 		else if (Settings.SuperFX)
2163 			Map_SuperFXLoROMMap();
2164 		else if (Settings.SA1)
2165 			Map_SA1LoROMMap();
2166 		else if (Settings.SDD1)
2167 			Map_SDD1LoROMMap();
2168 		else if (Memory.ExtendedFormat != NOPE)
2169 		{
2170 			MAP_JUMBOLOROMMAP();
2171 		}
2172 		else if (strncmp(Memory.ROMName, "WANDERERS FROM YS", 17) == 0)
2173 			Map_NoMAD1LoROMMap();
2174 		else if (strncmp(Memory.ROMName, "SOUND NOVEL-TCOOL", 17) == 0 ||
2175 				strncmp(Memory.ROMName, "DERBY STALLION 96", 17) == 0)
2176 			Map_ROM24MBSLoROMMap();
2177 		else if (strncmp(Memory.ROMName, "THOROUGHBRED BREEDER3", 21) == 0 ||
2178 				strncmp(Memory.ROMName, "RPG-TCOOL 2", 11) == 0)
2179 		{
2180 			MAP_SRAM512KLOROMMAP();
2181 		}
2182 		else if (strncmp(Memory.ROMName, "ADD-ON BASE CASSETE", 19) == 0)
2183 		{
2184 			if (Multi.cartType == 4)
2185 			{
2186 				Memory.SRAMSize = Multi.sramSizeA;
2187 				Map_SufamiTurboLoROMMap();
2188 			}
2189 			else
2190 			{
2191 				Memory.SRAMSize = 5;
2192 				Map_SufamiTurboPseudoLoROMMap();
2193 			}
2194 		}
2195 		else
2196 		{
2197 			MAP_LOROMMAP();
2198 		}
2199 	}
2200 
2201 	/* from NSRT */
2202 	sum = 0;
2203 
2204 	if (Settings.BS && !Settings.BSXItself)
2205 		sum = checksum_calc_sum(Memory.ROM, Memory.CalculatedSize) - checksum_calc_sum(Memory.ROM + (Memory.HiROM ? 0xffb0 : 0x7fb0), 48);
2206 	else
2207 	if (Settings.SPC7110)
2208 	{
2209 		sum = checksum_calc_sum(Memory.ROM, Memory.CalculatedSize);
2210 		if (Memory.CalculatedSize == 0x300000)
2211 			sum += sum;
2212 	}
2213 	else
2214 	{
2215 		if (Memory.CalculatedSize & 0x7fff)
2216 			sum = checksum_calc_sum(Memory.ROM, Memory.CalculatedSize);
2217 		else
2218 		{
2219 			uint32	length = Memory.CalculatedSize;
2220 			sum = checksum_mirror_sum(Memory.ROM, &length, 0x800000);
2221 		}
2222 	}
2223 
2224 	Memory.CalculatedChecksum = sum;
2225 
2226 	isChecksumOK = (Memory.ROMChecksum + Memory.ROMComplementChecksum == 0xffff) &
2227 						 (Memory.ROMChecksum == Memory.CalculatedChecksum);
2228 
2229 	/* Build more ROM information */
2230 
2231 	/* CRC32 */
2232 	if (!Settings.BS || Settings.BSXItself) /* Not BS Dump */
2233 		Memory.ROMCRC32 = caCRC32(Memory.ROM, Memory.CalculatedSize, 0xffffffff);
2234 	else /* Convert to correct format before scan */
2235 	{
2236 		int offset = Memory.HiROM ? 0xffc0 : 0x7fc0;
2237 		/* Backup */
2238 		uint8 BSMagic0 = Memory.ROM[offset + 22];
2239 		uint8 BSMagic1 = Memory.ROM[offset + 23];
2240 
2241 		/* uCONSRT standard */
2242 		Memory.ROM[offset + 22] = 0x42;
2243 		Memory.ROM[offset + 23] = 0x00;
2244 
2245 		/* Calc */
2246 		Memory.ROMCRC32 = caCRC32(Memory.ROM, Memory.CalculatedSize, 0xffffffff);
2247 
2248 		/* Convert back */
2249 		Memory.ROM[offset + 22] = BSMagic0;
2250 		Memory.ROM[offset + 23] = BSMagic1;
2251 	}
2252 
2253 	/* NTSC/PAL */
2254 	if (Settings.ForceNTSC)
2255 		Settings.PAL = FALSE;
2256 	else if (Settings.ForcePAL)
2257 		Settings.PAL = TRUE;
2258 	else if (!Settings.BS && (Memory.ROMRegion >= 2) && (Memory.ROMRegion <= 12))
2259 		Settings.PAL = TRUE;
2260 	else
2261 		Settings.PAL = FALSE;
2262 
2263 	/* truncate cart name */
2264 	Memory.ROMName[ROM_NAME_LEN - 1] = 0;
2265 	if (strlen(Memory.ROMName))
2266 	{
2267 		char *p = Memory.ROMName + strlen(Memory.ROMName);
2268 		if (p > Memory.ROMName + 21 && Memory.ROMName[20] == ' ')
2269 			p = Memory.ROMName + 21;
2270 		while (p > Memory.ROMName && *(p - 1) == ' ')
2271 			p--;
2272 		*p = 0;
2273 	}
2274 
2275 	/* checksum */
2276 	if (!isChecksumOK || ((uint32) Memory.CalculatedSize > (uint32) (((1 << (Memory.ROMSize - 7)) * 128) * 1024)))
2277 	{
2278 	}
2279 
2280 	if (Multi.cartType == 4)
2281 	{
2282 	}
2283 
2284 	/* Initialize emulation */
2285 
2286 	Timings.H_Max_Master = SNES_CYCLES_PER_SCANLINE;
2287 	Timings.H_Max        = Timings.H_Max_Master;
2288 	Timings.HBlankStart  = SNES_HBLANK_START_HC;
2289 	Timings.HBlankEnd    = SNES_HBLANK_END_HC;
2290 	Timings.HDMAInit     = SNES_HDMA_INIT_HC;
2291 	Timings.HDMAStart    = SNES_HDMA_START_HC;
2292 	Timings.RenderPos    = SNES_RENDER_START_HC;
2293 	Timings.V_Max_Master = Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER;
2294 	Timings.V_Max        = Timings.V_Max_Master;
2295 
2296 	/* From byuu: The total delay time for both the initial (H)DMA sync (to the DMA clock),
2297 	   and the end (H)DMA sync (back to the last CPU cycle's mcycle rate (6, 8, or 12))
2298 	   always takes between 12-24 mcycles.
2299 
2300 	   Possible delays: { 12, 14, 16, 18, 20, 22, 24 }
2301 	   XXX: Snes9x can't emulate this timing :( so let's use the average value... */
2302 
2303 	Timings.DMACPUSync   = 18;
2304 
2305 	/* If the CPU is halted (i.e. for DMA) while /NMI goes low, the NMI will trigger
2306 	   after the DMA completes (even if /NMI goes high again before the DMA
2307 	   completes). In this case, there is a 24-30 cycle delay between the end of DMA
2308 	   and the NMI handler, time enough for an instruction or two.
2309 
2310 	   Examples: Wild Guns, Mighty Morphin Power Rangers - The Fighting Edition */
2311 
2312 	Timings.NMIDMADelay  = 24;
2313 	Timings.IRQPendCount = 0;
2314 
2315 	/* Hack games */
2316 
2317 	Settings.BlockInvalidVRAMAccess = Settings.BlockInvalidVRAMAccessMaster;
2318 
2319 	/* Warnings */
2320 
2321 	/* Reject strange hacked games */
2322 	if ((Memory.ROMCRC32 == 0x6810aa95) ||
2323 		(Memory.ROMCRC32 == 0x340f23e5) ||
2324 		(Memory.ROMCRC32 == 0x77fd806a) ||
2325 		(MATCH_NN("HIGHWAY BATTLE 2")) ||
2326 		(MATCH_NA("FX SKIING NINTENDO 96") && (Memory.ROM[0x7fda] == 0)) ||
2327 		(MATCH_NN("HONKAKUHA IGO GOSEI")   && (Memory.ROM[0xffd5] != 0x31)))
2328 	{
2329 	}
2330 
2331 	/* APU timing hacks */
2332 
2333 	Timings.APUSpeedup = 0;
2334 	Timings.APUAllowTimeOverflow = FALSE;
2335 
2336 	if (!Settings.DisableGameSpecificHacks)
2337 	{
2338 		if (MATCH_ID("AVCJ"))                                      /* Rendering Ranger R2*/
2339 			Timings.APUSpeedup = 4;
2340 
2341 		if (MATCH_NA("GAIA GENSOUKI 1 JPN")                     || /* Gaia Gensouki*/
2342 			MATCH_ID("JG  ")                                    || /* Illusion of Gaia*/
2343 			MATCH_ID("CQ  ")                                    || /* Stunt Race FX*/
2344 			MATCH_NA("SOULBLADER - 1")                          || /* Soul Blader*/
2345 			MATCH_NA("SOULBLAZER - 1 USA")                      || /* Soul Blazer*/
2346 			MATCH_NA("SLAP STICK 1 JPN")                        || /* Slap Stick*/
2347 			MATCH_ID("E9 ")                                     || /* Robotrek*/
2348 			MATCH_NN("ACTRAISER")                               || /* Actraiser*/
2349 			MATCH_NN("ActRaiser-2")                             || /* Actraiser 2*/
2350 			MATCH_ID("AQT")                                     || /* Tenchi Souzou, Terranigma*/
2351 			MATCH_ID("ATV")                                     || /* Tales of Phantasia*/
2352 			MATCH_ID("ARF")                                     || /* Star Ocean*/
2353 			MATCH_ID("APR")                                     || /* Zen-Nippon Pro Wrestling 2 - 3-4 Budoukan*/
2354 			MATCH_ID("A4B")                                     || /* Super Bomberman 4*/
2355 			MATCH_ID("Y7 ")                                     || /* U.F.O. Kamen Yakisoban - Present Ban*/
2356 			MATCH_ID("Y9 ")                                     || /* U.F.O. Kamen Yakisoban - Shihan Ban*/
2357 			MATCH_ID("APB")                                     || /* Super Bomberman - Panic Bomber W*/
2358 			MATCH_NA("DARK KINGDOM")                            || /* Dark Kingdom*/
2359 			MATCH_NA("ZAN3 SFC")                                || /* Zan III Spirits*/
2360 			MATCH_NA("HIOUDEN")                                 || /* Hiouden - Mamono-tachi Tono Chikai*/
2361 			MATCH_NA("\xC3\xDD\xBC\xC9\xB3\xC0")                || /* Tenshi no Uta*/
2362 			MATCH_NA("FORTUNE QUEST")                           || /* Fortune Quest - Dice wo Korogase*/
2363 			MATCH_NA("FISHING TO BASSING")                      || /* Shimono Masaki no Fishing To Bassing*/
2364 			MATCH_NA("OHMONO BLACKBASS")                        || /* Oomono Black Bass Fishing - Jinzouko Hen*/
2365 			MATCH_NA("MASTERS")                                 || /* Harukanaru Augusta 2 - Masters*/
2366 			MATCH_NA("SFC \xB6\xD2\xDD\xD7\xB2\xC0\xDE\xB0")    || /* Kamen Rider*/
2367 			MATCH_NA("ZENKI TENCHIMEIDOU")					    || /* Kishin Douji Zenki - Tenchi Meidou*/
2368 			MATCH_NN("TokyoDome '95Battle 7")                   || /* Shin Nippon Pro Wrestling Kounin '95 - Tokyo Dome Battle 7*/
2369 			MATCH_NN("SWORD WORLD SFC")                         || /* Sword World SFC/2*/
2370 			MATCH_NN("LETs PACHINKO(")                          || /* BS Lets Pachinko Nante Gindama 1/2/3/4*/
2371 			MATCH_NN("THE FISHING MASTER")                      || /* Mark Davis The Fishing Master*/
2372 			MATCH_NN("Parlor")                                  || /* Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5*/
2373 			MATCH_NA("HEIWA Parlor!Mini8")                      || /* Parlor mini 8*/
2374 			MATCH_NN("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!"))   /* SANKYO Fever! Fever!*/
2375 			Timings.APUSpeedup = 1;
2376 
2377 		if (MATCH_NA ("EARTHWORM JIM 2")			|| /* Earthworm Jim 2*/
2378 			MATCH_NA ("NBA Hangtime")			|| /* NBA Hang Time*/
2379 			MATCH_NA ("MSPACMAN")				|| /* Ms Pacman*/
2380 			MATCH_NA ("THE MASK")				|| /* The Mask*/
2381 			MATCH_NA ("PRIMAL RAGE")			|| /* Primal Rage*/
2382 			MATCH_NA ("DOOM TROOPERS")			|| /* Doom Troopers*/
2383 			MATCH_NA ("PORKY PIGS HAUNTED")			|| /* Porky Pig's Haunted Holiday*/
2384 			MATCH_NA ("Big Sky Trooper")			|| /* Big Sky Trooper*/
2385 			MATCH_NA ("A35"))				/* Mechwarrior 3050/Battle Tech 3050*/
2386 			Timings.APUAllowTimeOverflow = TRUE;
2387 
2388 		/* SWAP MOSAIC HI-RES WITH HI-RES
2389 
2390 		   We don't want Seiken Densetsu 3/Romancing Saga 3 unbearably
2391 		   slow in hi-res mosaic mode - no difference with these games
2392 		   between normal hi-res renderer and mosaic version - only double the FPS */
2393 
2394 		if (
2395 				MATCH_NN("SeikenDensetsu3") ||
2396 				MATCH_NA("SeikenDensetsu3Sample1") ||	/* Seiken Densetsu 3 */
2397 				MATCH_NA("ROMANCING SAGA3"))		/* Romancing Saga 3 */
2398       {
2399 			PPU.DisableMosaicHack = FALSE;
2400       }
2401 		else
2402 			PPU.DisableMosaicHack = TRUE;
2403 
2404 		/* Speedup hack for Star Fox 2/Vortex */
2405 		if (
2406             MATCH_NA("VORTEX") ||			/* Vortex */
2407             MATCH_NA("Super Street Fighter21") ||	/* Super Street Fighter II */
2408             MATCH_NA("STAR FOX") ||			/* Star Fox (US/JP)*/
2409             MATCH_NA("STAR WING") ||			/* Star Wing (EU)*/
2410             MATCH_NA("STAR FOX 2") ||			/* Star Fox 2 (Beta) */
2411             MATCH_NA("STARFOX2"))			/* Star Fox 2 (SNES Classic) */
2412 					PPU.SFXSpeedupHack = TRUE;
2413 				else
2414 					PPU.SFXSpeedupHack = FALSE;
2415 
2416 
2417 	/* FORCIBLY DISABLE HIGH-RES */
2418 
2419             if (
2420                   MATCH_NA("DONKEY KONG COUNTRY")		/* Donkey Kong Country */
2421                   //|| MATCH_ID("ADNE")			/* Donkey Kong Country 2 (US) */
2422                   || MATCH_ID("AD8")			/* Doom */
2423                )
2424                Settings.SupportHiRes = FALSE;
2425 
2426 
2427 		/* DON'T RENDER SUBSCREEN */
2428 
2429 		/* Don't render subscreen for games that don't switch to high-res mode
2430 		   in-game or don't use hi-res at all - and yet still need to do stuff
2431 		   with the subscreen FPS improvement ranges from 7/10fps to 20/25fps
2432 		   depending on the game ( +25/30fps in some occassions - benchmarked
2433 		   on PC).
2434 
2435 			TODO: This glitches with rewind enabled (RetroArch), force-disable it
2436 			when rewind is active */
2437 		if(
2438 				MATCH_NA("Super Metroid") 	/* Super Metroid*/
2439 				|| MATCH_NA("DONKEY KONG COUNTRY") /* Donkey Kong Country 1 */
2440 				|| MATCH_NA("AREA88")		/* Area 88 */
2441 				|| MATCH_NA("U.N.Squadron")	/* UN Squadron */
2442 				|| MATCH_NA("Perfect Eleven")	/* Perfect Eleven - ISS1 */
2443 				//|| MATCH_ID("ADNE")			/* Donkey Kong Country 2 (US) */
2444 				|| MATCH_ID("AWJ")		/* ISS Deluxe / World Soccer 2 Fighting Eleven */
2445 				|| MATCH_NA("JIM POWER THE LOST DIO") /* Jim Power The Lost Dimension */
2446 				|| MATCH_ID("A3C")		/* Donkey Kong Country 3*/
2447 				|| MATCH_NA("Secret of MANA") /* Secret of Mana */
2448 				|| MATCH_NA("Street Fighter2 Turbo1") /* Street Fighter II Turbo */
2449 				|| MATCH_NA("Super Street Fighter21") /* Super Street Fighter II (US) */
2450 				|| MATCH_ID("A2J")		/* Jurassic Park 2 */
2451 				|| MATCH_ID("AJL")		/* Justice League */
2452 				|| MATCH_NA("JOE AND MAC")	/* Joe and Mac */
2453 				|| MATCH_NA("JOE & MAC 2")	/* Joe & Mac 2 */
2454 				|| MATCH_ID("J3")		/* Joe & Mac 3 EU) */
2455 			|| MATCH_NA("JYUTEI SENKI")	/* Jyutei Senki */
2456 			|| MATCH_ID("CQ  ")		/* Stunt Race FX */
2457 #if defined(_XBOX1) || defined(GEKKO)
2458 			|| MATCH_ID("AD8")		/* Doom */
2459 #endif
2460 			|| MATCH_NA("T.M.H.T.4")	/* Teenage Mutant Hero Turtles 4 - Turtles In Time (E) */
2461 			|| MATCH_NA("T.M.N.T.")		/* Teenage Mutant Ninja Turtles 4 - Turtles In Time (J) */
2462 			|| MATCH_NA("T.M.N.T.4")	/* Teenage Mutant Ninja Turtles 4 - Turtles In Time (AU) */
2463 			|| MATCH_NA("T.M.N.T. 4")	/* Teenage Mutant Ninja Turtles 4 - Turtles In Time (US) */
2464 			|| MATCH_NA("T.M.N.T. MW")	/* Teenage Mutant Ninja Turtles - Mutant Warriors (J) */
2465 			|| MATCH_NA("T.M.H.T TF")	/* Teenage Mutant Hero Turtles - Tour Fighters (EU) */
2466 			|| MATCH_NA("T.M.N.T. TF")	/* Teenage Mutant Ninja Turtles - Tour Fighters (AU) */
2467 			|| MATCH_NA("T.M.N.T.5")	/* Teenage Mutant Ninja Turtles - Tour Fighters (U) */
2468 			|| MATCH_NA("SUPER CASTLEVANIA 4") /* Super Castlevania IV */
2469 			|| MATCH_NA("AKUMAJO DRACULA") /* Super Castlevania IV */
2470 			|| MATCH_ID("ATVE")		/* Tales of Phantasia (EN) (DeJap)*/
2471 			|| MATCH_NA("MEGAMAN X")		/* Mega Man X (US) */
2472 			|| MATCH_ID("A7R")		/* Rockman / Mega Man 7 */
2473 			|| MATCH_NA("F-ZERO")		/* Rockman / Mega Man 7 */
2474 			|| MATCH_NA("EQUINOX")		/* Equinox */
2475 			|| MATCH_NA("SUPER MARIO KART") /* Super Mario Kart */
2476 			|| MATCH_ID("AR3")		/* Mega Man X3 (JP/US) */
2477 			|| MATCH_NA("SECRET OF EVERMORE") 	/* Secret of Evermore*/
2478 			|| MATCH_ID("AKL")		/* Killer Instinct*/
2479 			|| MATCH_NA("NBA JAM")		/* NBA Jam */
2480 			|| MATCH_NA("PILOTWINGS")	/* Pilotwings */
2481 			|| MATCH_NA("FINAL FIGHT")	/* Final Fight */
2482 			|| MATCH_NA("FINAL FANTASY 6")	/* Final Fantasy VI (JP)*/
2483 			|| MATCH_NA("FINAL FANTASY 3")	/* Final Fantasy III (US)*/
2484 			|| MATCH_NA("ILLUSION OF GAIA USA") /* Illusion of Gaia (US)*/
2485 			|| MATCH_NA("GAIA GENSOUKI 1 JPN")	/* Gaia Gensouki (JPN)*/
2486 			|| MATCH_ID("AEJ") 		/* Earthworm Jim*/
2487 			|| MATCH_ID("YI")		/* Yoshi's Island*/
2488 			|| MATCH_NA("SUPER MARIOWORLD")	/* Super Mario World*/
2489 			|| MATCH_NA("THE LEGEND OF ZELDA")	/* Zelda 3*/
2490 			|| MATCH_NA("LA LEGENDE DE ZELDA")	/* Zelda 3 (FR)*/
2491 			|| MATCH_NA("ZELDANODENSETSU")		/* Zelda 3 (JPN)*/
2492 			|| MATCH_NA("SPARKSTER")		/* Sparkster*/
2493 			|| MATCH_NA("SIMCITY")		/* Sim City */
2494 			|| MATCH_NA("T2 ARCADE")	/* T2 Arcade */
2495 			|| MATCH_NA("PLOK")		/* Plok!*/
2496 			|| MATCH_NA("ALADDIN")		/* Aladdin */
2497 			|| MATCH_NA("ActRaiser-2 JPN")	/* ActRaiser 2 (JPN) */
2498 			|| MATCH_NA("ActRaiser-2 USA")	/* ActRaiser 2 (US) */
2499 			|| MATCH_ID("A8")		/* ActRaiser 2 (EU) */
2500 			|| MATCH_ID("APT")		/* Pac In Time */
2501 			|| MATCH_ID("AXG")		/*NBA Hangtime */
2502 			|| MATCH_NA("THE CHAOS ENGINE")	/* Chaos Engine */
2503 			|| MATCH_ID("AWD")		/* Weaponlord */
2504 			|| MATCH_NA("TALES OF PHANTASIA")       /* Tales of Phantasia */
2505 			|| MATCH_NA("GS MIKAMI")		/* GS Mikami - Joreishi wa Nice Body*/
2506 			|| MATCH_ID("ATQ")		/* Theme Park */
2507 			|| MATCH_NA("TOTAL CARNAGE")	/* Total Carnage */
2508 			|| MATCH_ID("AJOJ")		/* Jikkyou Oshaberi Parodius*/
2509 			|| MATCH_NA("ROCK N' ROLL RACING") /* Rock 'n Roll Racing */
2510 			|| MATCH_NA("RISE OF THE ROBOTS")	/* Rise Of The Robots*/
2511 			|| MATCH_ID("A3T")		/* Top Gear 3000 */
2512 			|| MATCH_NA("MORTAL KOMBAT")	/* Mortal Kombat I*/
2513 			|| MATCH_NA("MORTAL KOMBAT II")	/* Mortal Kombat II*/
2514 			|| MATCH_NA("STAR FOX")		/* Star Fox (US/JP)*/
2515 			|| MATCH_ID("ST2")		/* Star Fox 2 */
2516 			|| MATCH_NA("STAR WING")		/* Star Wing (EU)*/
2517 			|| MATCH_NA("TINYTOON adventures") /* Buster Busts Loose */
2518 			|| MATCH_ID("3Z")		/* Demon's Crest*/
2519 			|| MATCH_NA("AXELAY")		/* Axelay*/
2520 			|| MATCH_NA("JAKI CRUSH")	/* Jaki Crush */
2521 			|| MATCH_NA("ZOMBIES")		/* Zombies (EU)*/
2522 			|| MATCH_NA("THE JUNGLE BOOK")	/* Jungle Book */
2523 			|| MATCH_NA("ZOMBIES ATE MY NEIGHB")	/* Zombies Ate My Neighbors*/
2524 			|| MATCH_NA("UNIRACERS")		/* Uniracers*/
2525 			|| MATCH_NA("UNIRALLY")		/* Unirally*/
2526 			|| MATCH_NA("CHRONO TRIGGER")	/* Chrono Trigger*/
2527 			|| MATCH_NA("JURASSIC PARK")	/* Jurassic Park*/
2528 			|| MATCH_NA("THE MAGICAL QUEST")	/* The Magical Quest*/
2529 			|| MATCH_NA("SOULBLAZER - 1 USA")	/* Soul Blazer (US)*/
2530 			|| MATCH_NA("SOULBLAZER - 1 ENG")	/* Soul Blazer (PAL)*/
2531 			|| MATCH_NA("SOULBLADER - 1")		/* Soul Blader*/
2532 			|| MATCH_NA("GOKUJYOU PARODIUS")		/* Gokujou Parodius*/
2533 			|| MATCH_ID("ABT")		/* Adventures of Batman and Robin*/
2534 			|| MATCH_ID("5M")		/* Mario All-Stars + World*/
2535 			|| MATCH_NA("SUPER MARIO ALL_STARS") /* Super Mario All-Stars (EU/US)*/
2536 			|| MATCH_NA("SUPERMARIO COLLECTION") /* Super Mario Collection (JP)*/
2537 			|| MATCH_ID("4Q")		/* Super Punch-Out*/
2538 			|| MATCH_NA("HARVEST MOON")	/* Harvest Moon*/
2539 			|| MATCH_ID("ADZ")		/* Dracula X*/
2540 			|| MATCH_ID("A3M")		/* Mortal Kombat 3*/
2541 			|| MATCH_ID("AM4J")		/* Do-Re-Mi Fantasy - Milon no Dokidoki Daibouken*/
2542 			|| MATCH_NA("BT IN BATTLEMANIACS")	/* Battletoads in Battlemaniacs*/
2543 			|| MATCH_NA("SPACE MEGAFORCE")	/* Space Megaforce (US)*/
2544 			|| MATCH_ID("ARX")		/* Mega Man X2 */
2545 			|| MATCH_NA("SUPER ALESTE")	/* Super Aleste (EU/JP)*/
2546 			|| MATCH_NA("VALKEN")		/* Assault Suits Valken (JP)*/
2547 			|| MATCH_NA("CYBERNATOR")	/* Cybernator (EU/US)*/
2548 			|| MATCH_NA("SUPER BOMBERMAN")	/* Super Bomberman 1*/
2549 			|| MATCH_NA("SUPER BOMBERMAN2")	/* Super Bomberman 2*/
2550 			|| MATCH_ID("AS6")		/* Super Bomberman 3*/
2551 			|| MATCH_ID("A4B")		/* Super Bomberman 4*/
2552 			|| MATCH_ID("AYL")		/* Tetris Attack*/
2553 			|| MATCH_NA("POCKY ROCKY")	/* Pocky & Rocky (US/EU)*/
2554 			|| MATCH_NA("KIKIKAIKAI")	/* Kiki Kaikai (JP)*/
2555 			|| MATCH_ID("ANI")		/* Lufia 2 / Estpolis Denki 2*/
2556 			|| MATCH_ID("AQT")		/* Terranigma*/
2557 			|| MATCH_NA("twinbee")		/* Twinbee Rainbow Bell Adventures*/
2558 			|| MATCH_ID("AO7")		/* Tactics Ogre*/
2559 			|| MATCH_NA("Ogre Battle USA")	/* Ogre Battle (US)*/
2560 			|| MATCH_ID("AQ3")		/* Dragon Quest 3*/
2561 			|| MATCH_NA("DRAGONQUEST5")	/* Dragon Quest 5*/
2562 			|| MATCH_ID("AQ6J")		/* Dragon Quest 6*/
2563 			|| MATCH_NA("DARIUS FORCE")	/* Darius Force*/
2564 			|| MATCH_ID("AGC")		/* Front Mission*/
2565 			|| MATCH_ID("AZGJ")		/* Front Mission Gun Hazard*/
2566 			|| MATCH_NA("GANBARE GOEMON")	/* Ganbare Goemon (JP)*/
2567 			|| MATCH_NA("GANBARE GOEMON 2")	/* Ganbare Goemon 2*/
2568 			|| MATCH_NA("mystical ninja")	/* Legend of Mystical Ninja (US/EU)*/
2569 			|| MATCH_NA("NOSFERATU")		/* Nosferatu*/
2570 			|| MATCH_NA("PAC ATTACK")	/* Pac Attack*/
2571 			|| MATCH_NA("PARODIUS")		/* Parodius 1*/
2572 			|| MATCH_NA("PRINCE OF PERSIA")	/* Prince of Persia*/
2573 			|| MATCH_NA("FINAL FANTASY 5")	/* Final Fantasy 5*/
2574 			|| MATCH_NA("OUT OF THIS WORLD") /* Out Of This World (US)*/
2575 			|| MATCH_NA("OUTER WORLD")	/* Outer World (JP)*/
2576 			|| MATCH_NA("ANOTHER WORLD")	/* Another World (EU)*/
2577 			|| MATCH_ID("ABZE")		/* Ballz 3D*/
2578 			|| MATCH_ID("AXSP")		/* Winter Gold*/
2579 			|| MATCH_ID("APJJ")		/* Wonder Project J*/
2580 			|| MATCH_NA("KRUSTYS SUPER FUNHOUSE")	/* Krustys Super Fun House*/
2581 			|| MATCH_NA("KRUSTYS SUPERFUNHOUSE")	/* Krustys Super Fun House*/
2582 			|| MATCH_NA("LEMMINGS")		/* Lemmings 1*/
2583 			|| MATCH_ID("A3Z")		/* Ultimate Mortal Kombat 3*/
2584 			|| MATCH_ID("ARFJ")		/* Star Ocean*/
2585 			|| MATCH_ID("AXBE")		/* Bahamut Lagoon*/
2586 			|| MATCH_ID("ARQ")		/* Realm */
2587 			|| MATCH_NA("S O S")		/* SOS */
2588 			|| MATCH_NA("SUPER DONKEY KONG") /* Super Donkey Kong */
2589 			|| MATCH_ID("AC6J")		/* Cu-On-Pa*/
2590 			|| MATCH_ID("ASR")		/* Street Racer*/
2591 			|| MATCH_NA("SUPER WIDGET")	/* Super Widget*/
2592 			|| MATCH_NA("WILD GUNS")	/* Wild Guns */
2593 			|| MATCH_NA("R-TYPE 3")		/* R-Type 3*/
2594 			|| MATCH_NA("THE NINJAWARRIORS") /* Ninja Warriors */
2595 			|| MATCH_ID("ARW")		/* Super Mario RPG*/
2596 			|| MATCH_NA("SHVC FIREEMBLEM")	/* Fire Emblem - Monshou no Nazo*/
2597 			|| MATCH_ID("BFRJ")		/* Fire Emblem - Thracia 776*/
2598 			|| MATCH_ID("A32J")		/* Fire Emblem - Seisen no Keifu*/
2599 			|| MATCH_ID("AR9")		/* Primal Rage*/
2600 			|| MATCH_ID("APUE")		/* Prehistorik Man*/
2601 			|| MATCH_ID("ALSJ")		/* Lady Stalker*/
2602 			|| MATCH_NA("ROCKMAN&FORTE")	/* Rockman & Forte*/
2603 			|| MATCH_NA("SUPER SWIV")	/* Super SWIV*/
2604 			|| MATCH_NA("CONTRA3 THE ALIEN WARS")	/* Contra 3 The Alien Wars*/
2605 			|| MATCH_NA("EARTHWORM JIM 2")	/* Earthworm Jim 2*/
2606 			|| MATCH_NA("CHOHMAKAIMURA")	/* Chou Makai Mura*/
2607 			|| MATCH_NA("SUPER GHOULS'N GHOSTS")	/* Super Ghouls 'n Ghosts*/
2608 			|| MATCH_NA("X-KALIBER 2097")	/* X-Kaliber 2097*/
2609 			|| MATCH_NA("PHALANX")		/* Phalanx */
2610 			|| MATCH_NA("FINAL FIGHT 2")	/* Final Fight 2*/
2611 			|| MATCH_NA("SUPER TURRICAN 2")	/* Super Turrican 2*/
2612 			|| MATCH_NA("DUNGEON MASTER")	/* Dungeon Master*/
2613 			|| MATCH_NA("DOOM TROOPERS")	/* Doom Troopers*/
2614 			|| MATCH_NA("DOOM")		/* Doom */
2615 			|| MATCH_NA("XAK 1")		/* Xak 1*/
2616 			|| MATCH_NA("XARDION")		/* Xardion*/
2617 			)
2618 		  	PPU.RenderSub = FALSE;
2619 		else
2620 			PPU.RenderSub = TRUE;
2621 
2622 		if(
2623 				//MATCH_NA("Super Metroid") 	/* Super Metroid*/
2624 				//|| MATCH_NA("DONKEY KONG COUNTRY") /* Donkey Kong Country 1 */
2625 				//|| MATCH_NA("AREA88")		/* Area 88 */
2626 				//|| MATCH_NA("U.N.Squadron")	/* UN Squadron */
2627 				//|| MATCH_NA("Perfect Eleven")	/* Perfect Eleven - ISS1 */
2628 				//MATCH_ID("ADNE")			/* Donkey Kong Country 2 (US) */
2629 				//|| MATCH_ID("AWJ")		/* ISS Deluxe / World Soccer 2 Fighting Eleven */
2630 				//|| MATCH_NA("JIM POWER THE LOST DIO") /* Jim Power The Lost Dimension */
2631 				//|| MATCH_ID("A3C")		/* Donkey Kong Country 3*/
2632 				//|| MATCH_NA("Secret of MANA") /* Secret of Mana */
2633 				//|| MATCH_ID("A2J")		/* Jurassic Park 2 */
2634 				//|| MATCH_ID("AJL")		/* Justice League */
2635 				//|| MATCH_NA("JOE AND MAC")	/* Joe and Mac */
2636 				//|| MATCH_NA("JOE & MAC 2")	/* Joe & Mac 2 */
2637 				//|| MATCH_ID("J3")		/* Joe & Mac 3 EU) */
2638 			//|| MATCH_NA("JYUTEI SENKI")	/* Jyutei Senki */
2639 			//|| MATCH_ID("CQ  ")		/* Stunt Race FX */
2640 #if defined(_XBOX1) || defined(GEKKO)
2641 			//|| MATCH_ID("AD8")		/* Doom */
2642 			//|| MATCH_ID("A3D")			/* Seiken Densetsu 3 */
2643 			//|| MATCH_NA("SeikenDensetsu3Sample1")	/* Seiken Densetsu 3 */
2644 			//|| MATCH_NA("ROMANCING SAGA3")		/* Romancing Saga 3 */
2645 #endif
2646 			//|| MATCH_NA("T.M.H.T.4")	/* Teenage Mutant Hero Turtles 4 - Turtles In Time (E) */
2647 			//|| MATCH_NA("T.M.N.T.")		/* Teenage Mutant Ninja Turtles 4 - Turtles In Time (J) */
2648 			//|| MATCH_NA("T.M.N.T.4")	/* Teenage Mutant Ninja Turtles 4 - Turtles In Time (AU) */
2649 			//|| MATCH_NA("T.M.N.T. 4")	/* Teenage Mutant Ninja Turtles 4 - Turtles In Time (US) */
2650 			MATCH_NA("T.M.N.T. MW")	/* Teenage Mutant Ninja Turtles - Mutant Warriors (J) */
2651 			|| MATCH_NA("T.M.H.T TF")	/* Teenage Mutant Hero Turtles - Tour Fighters (EU) */
2652 			|| MATCH_NA("T.M.N.T. TF")	/* Teenage Mutant Ninja Turtles - Tour Fighters (AU) */
2653 			|| MATCH_NA("T.M.N.T.5")	/* Teenage Mutant Ninja Turtles - Tour Fighters (U) */
2654 			//|| MATCH_NA("SUPER CASTLEVANIA 4") /* Super Castlevania IV */
2655 			//|| MATCH_NA("AKUMAJO DRACULA") /* Super Castlevania IV */
2656 			//|| MATCH_ID("ATVE")		/* Tales of Phantasia (EN) (DeJap)*/
2657 			//|| MATCH_NA("MEGAMAN X")		/* Mega Man X (US) */
2658 			//|| MATCH_ID("A7R")		/* Rockman / Mega Man 7 */
2659 			//|| MATCH_NA("F-ZERO")		/* Rockman / Mega Man 7 */
2660 			//|| MATCH_NA("EQUINOX")		/* Equinox */
2661 			//|| MATCH_NA("SUPER MARIO KART") /* Super Mario Kart */
2662 			//|| MATCH_ID("AR3")		/* Mega Man X3 (JP/US) */
2663 			//|| MATCH_NA("SECRET OF EVERMORE") 	/* Secret of Evermore*/
2664 			|| MATCH_ID("AKL")		/* Killer Instinct*/
2665 			//|| MATCH_NA("NBA JAM")		/* NBA Jam */
2666 			//|| MATCH_NA("PILOTWINGS")	/* Pilotwings */
2667 			//|| MATCH_NA("FINAL FIGHT")	/* Final Fight */
2668 			//|| MATCH_NA("FINAL FANTASY 6")	/* Final Fantasy VI (JP)*/
2669 			//|| MATCH_NA("FINAL FANTASY 3")	/* Final Fantasy III (US)*/
2670 			//|| MATCH_NA("ILLUSION OF GAIA USA") /* Illusion of Gaia (US)*/
2671 			//|| MATCH_NA("GAIA GENSOUKI 1 JPN")	/* Gaia Gensouki (JPN)*/
2672 			//|| MATCH_ID("AEJ") 		/* Earthworm Jim*/
2673 			//|| MATCH_ID("AFJ")		/* Kirby's Dreamland 3 */
2674 			|| MATCH_NA("SUPER MARIOWORLD")	/* Super Mario World*/
2675 			//|| MATCH_NA("THE LEGEND OF ZELDA")	/* Zelda 3*/
2676 			//|| MATCH_NA("LA LEGENDE DE ZELDA")	/* Zelda 3 (FR)*/
2677 			//|| MATCH_NA("ZELDANODENSETSU")		/* Zelda 3 (JPN)*/
2678 			//|| MATCH_NA("SPARKSTER")		/* Sparkster*/
2679 			//|| MATCH_NA("SIMCITY")		/* Sim City */
2680 			//|| MATCH_NA("T2 ARCADE")	/* T2 Arcade */
2681 			//|| MATCH_NA("PLOK")		/* Plok!*/
2682 			//|| MATCH_NA("ALADDIN")		/* Aladdin */
2683 			//|| MATCH_NA("ActRaiser-2 JPN")	/* ActRaiser 2 (JPN) */
2684 			//|| MATCH_NA("ActRaiser-2 USA")	/* ActRaiser 2 (US) */
2685 			//|| MATCH_ID("A8")		/* ActRaiser 2 (EU) */
2686 			//|| MATCH_ID("APT")		/* Pac In Time */
2687 			//|| MATCH_ID("AXG")		/*NBA Hangtime */
2688 			//|| MATCH_NA("THE CHAOS ENGINE")	/* Chaos Engine */
2689 			//|| MATCH_ID("AWD")		/* Weaponlord */
2690 			//|| MATCH_NA("TALES OF PHANTASIA")       /* Tales of Phantasia */
2691 			//|| MATCH_NA("GS MIKAMI")		/* GS Mikami - Joreishi wa Nice Body*/
2692 			//|| MATCH_ID("ATQ")		/* Theme Park */
2693 			//|| MATCH_NA("TOTAL CARNAGE")	/* Total Carnage */
2694 			|| MATCH_ID("AJOJ")		/* Jikkyou Oshaberi Parodius*/
2695 			//|| MATCH_NA("ROCK N' ROLL RACING") /* Rock 'n Roll Racing */
2696 			//|| MATCH_NA("RISE OF THE ROBOTS")	/* Rise Of The Robots*/
2697 			//|| MATCH_ID("A3T")		/* Top Gear 3000 */
2698 			//|| MATCH_NA("MORTAL KOMBAT")	/* Mortal Kombat I*/
2699 			//|| MATCH_NA("MORTAL KOMBAT II")	/* Mortal Kombat II*/
2700 			//|| MATCH_NA("STAR FOX")		/* Star Fox (US/JP)*/
2701 			//|| MATCH_ID("ST2")		/* Star Fox 2 */
2702 			//|| MATCH_NA("STAR WING")		/* Star Wing (EU)*/
2703 			//|| MATCH_NA("TINYTOON adventures") /* Buster Busts Loose */
2704 			//|| MATCH_ID("3Z")		/* Demon's Crest*/
2705 			//|| MATCH_NA("AXELAY")		/* Axelay*/
2706 			//|| MATCH_NA("JAKI CRUSH")	/* Jaki Crush */
2707 			//|| MATCH_NA("ZOMBIES")		/* Zombies (EU)*/
2708 			//|| MATCH_NA("THE JUNGLE BOOK")	/* Jungle Book */
2709 			//|| MATCH_NA("ZOMBIES ATE MY NEIGHB")	/* Zombies Ate My Neighbors*/
2710 			//|| MATCH_NA("UNIRACERS")		/* Uniracers*/
2711 			//|| MATCH_NA("UNIRALLY")		/* Unirally*/
2712 			//|| MATCH_NA("CHRONO TRIGGER")	/* Chrono Trigger*/
2713 			//|| MATCH_NA("JURASSIC PARK")	/* Jurassic Park*/
2714 			//|| MATCH_NA("THE MAGICAL QUEST")	/* The Magical Quest*/
2715 			//|| MATCH_NA("SOULBLAZER - 1 USA")	/* Soul Blazer (US)*/
2716 			//|| MATCH_NA("SOULBLAZER - 1 ENG")	/* Soul Blazer (PAL)*/
2717 			//|| MATCH_NA("SOULBLADER - 1")		/* Soul Blader*/
2718 			//|| MATCH_NA("GOKUJYOU PARODIUS")		/* Gokujou Parodius*/
2719 			//|| MATCH_ID("ABT")		/* Adventures of Batman and Robin*/
2720 			//|| MATCH_ID("5M")		/* Mario All-Stars + World*/
2721 			//|| MATCH_NA("SUPER MARIO ALL_STARS") /* Super Mario All-Stars (EU/US)*/
2722 			//|| MATCH_NA("SUPERMARIO COLLECTION") /* Super Mario Collection (JP)*/
2723 			//|| MATCH_ID("4Q")		/* Super Punch-Out*/
2724 			//|| MATCH_NA("HARVEST MOON")	/* Harvest Moon*/
2725 			//|| MATCH_ID("ADZ")		/* Dracula X*/
2726 			//|| MATCH_ID("A3M")		/* Mortal Kombat 3*/
2727 			//|| MATCH_ID("AM4J")		/* Do-Re-Mi Fantasy - Milon no Dokidoki Daibouken*/
2728 			//|| MATCH_NA("BT IN BATTLEMANIACS")	/* Battletoads in Battlemaniacs*/
2729 			//|| MATCH_NA("SPACE MEGAFORCE")	/* Space Megaforce (US)*/
2730 			//|| MATCH_ID("ARX")		/* Mega Man X2 */
2731 			//|| MATCH_NA("SUPER ALESTE")	/* Super Aleste (EU/JP)*/
2732 			//|| MATCH_NA("VALKEN")		/* Assault Suits Valken (JP)*/
2733 			//|| MATCH_NA("CYBERNATOR")	/* Cybernator (EU/US)*/
2734 			//|| MATCH_NA("SUPER BOMBERMAN")	/* Super Bomberman 1*/
2735 			//|| MATCH_NA("SUPER BOMBERMAN2")	/* Super Bomberman 2*/
2736 			//|| MATCH_ID("AS6")		/* Super Bomberman 3*/
2737 			//|| MATCH_ID("A4B")		/* Super Bomberman 4*/
2738 			//|| MATCH_ID("AYL")		/* Tetris Attack*/
2739 			//|| MATCH_NA("POCKY ROCKY")	/* Pocky & Rocky (US/EU)*/
2740 			//|| MATCH_NA("KIKIKAIKAI")	/* Kiki Kaikai (JP)*/
2741 			//|| MATCH_ID("ANI")		/* Lufia 2 / Estpolis Denki 2*/
2742 			//|| MATCH_ID("AQT")		/* Terranigma*/
2743 			//|| MATCH_NA("twinbee")		/* Twinbee Rainbow Bell Adventures*/
2744 			//|| MATCH_ID("AO7")		/* Tactics Ogre*/
2745 			//|| MATCH_NA("Ogre Battle USA")	/* Ogre Battle (US)*/
2746 			//|| MATCH_ID("AQ3")		/* Dragon Quest 3*/
2747 			//|| MATCH_NA("DRAGONQUEST5")	/* Dragon Quest 5*/
2748 			//|| MATCH_ID("AQ6J")		/* Dragon Quest 6*/
2749 			//|| MATCH_NA("DARIUS FORCE")	/* Darius Force*/
2750 			//|| MATCH_ID("AZGJ")		/* Front Mission Gun Hazard*/
2751 			//|| MATCH_NA("GANBARE GOEMON")	/* Ganbare Goemon (JP)*/
2752 			//|| MATCH_NA("GANBARE GOEMON 2")	/* Ganbare Goemon 2*/
2753 			//|| MATCH_NA("mystical ninja")	/* Legend of Mystical Ninja (US/EU)*/
2754 			//|| MATCH_NA("NOSFERATU")		/* Nosferatu*/
2755 			//|| MATCH_NA("PAC ATTACK")	/* Pac Attack*/
2756 			//|| MATCH_NA("PARODIUS")		/* Parodius 1*/
2757 			//|| MATCH_NA("PRINCE OF PERSIA")	/* Prince of Persia*/
2758 			//|| MATCH_NA("FINAL FANTASY 5")	/* Final Fantasy 5*/
2759 			//|| MATCH_NA("OUT OF THIS WORLD") /* Out Of This World (US)*/
2760 			//|| MATCH_NA("OUTER WORLD")	/* Outer World (JP)*/
2761 			//|| MATCH_NA("ANOTHER WORLD")	/* Another World (EU)*/
2762 			//|| MATCH_ID("ABZE")		/* Ballz 3D*/
2763 			//|| MATCH_ID("AXSP")		/* Winter Gold*/
2764 			//|| MATCH_ID("APJJ")		/* Wonder Project J*/
2765 			//|| MATCH_NA("KRUSTYS SUPER FUNHOUSE")	/* Krustys Super Fun House*/
2766 			//|| MATCH_NA("KRUSTYS SUPERFUNHOUSE")	/* Krustys Super Fun House*/
2767 			//|| MATCH_NA("LEMMINGS")		/* Lemmings 1*/
2768 			//|| MATCH_ID("A3Z")		/* Ultimate Mortal Kombat 3*/
2769 			//|| MATCH_ID("ARFJ")		/* Star Ocean*/
2770 			//|| MATCH_ID("AXBE")		/* Bahamut Lagoon*/
2771 			//|| MATCH_ID("ARQ")		/* Realm */
2772 			//|| MATCH_NA("S O S")		/* SOS */
2773 			//|| MATCH_NA("SUPER DONKEY KONG") /* Super Donkey Kong */
2774 			//|| MATCH_ID("AC6J")		/* Cu-On-Pa*/
2775 			//|| MATCH_ID("ASR")		/* Street Racer*/
2776 			//|| MATCH_NA("SUPER WIDGET")	/* Super Widget*/
2777 			//|| MATCH_NA("WILD GUNS")	/* Wild Guns */
2778 			//|| MATCH_NA("R-TYPE 3")		/* R-Type 3*/
2779 			//|| MATCH_NA("THE NINJAWARRIORS") /* Ninja Warriors */
2780 			//|| MATCH_ID("ARW")		/* Super Mario RPG*/
2781 			//|| MATCH_NA("SHVC FIREEMBLEM")	/* Fire Emblem - Monshou no Nazo*/
2782 			//|| MATCH_ID("BFRJ")		/* Fire Emblem - Thracia 776*/
2783 			//|| MATCH_ID("A32J")		/* Fire Emblem - Seisen no Keifu*/
2784 			//|| MATCH_ID("AR9")		/* Primal Rage*/
2785 			//|| MATCH_ID("APUE")		/* Prehistorik Man*/
2786 			//|| MATCH_ID("ALSJ")		/* Lady Stalker*/
2787 			//|| MATCH_NA("ROCKMAN&FORTE")	/* Rockman & Forte*/
2788 			//|| MATCH_NA("SUPER SWIV")	/* Super SWIV*/
2789 			//|| MATCH_NA("CONTRA3 THE ALIEN WARS")	/* Contra 3 The Alien Wars*/
2790 			//|| MATCH_NA("EARTHWORM JIM 2")	/* Earthworm Jim 2*/
2791 			//|| MATCH_NA("CHOHMAKAIMURA")	/* Chou Makai Mura*/
2792 			//|| MATCH_NA("SUPER GHOULS'N GHOSTS")	/* Super Ghouls 'n Ghosts*/
2793 			//|| MATCH_NA("X-KALIBER 2097")	/* X-Kaliber 2097*/
2794 			//|| MATCH_NA("PHALANX")		/* Phalanx */
2795 			//|| MATCH_NA("FINAL FIGHT 2")	/* Final Fight 2*/
2796 			//|| MATCH_NA("SUPER TURRICAN 2")	/* Super Turrican 2*/
2797 			//|| MATCH_NA("DUNGEON MASTER")	/* Dungeon Master*/
2798 			//|| MATCH_NA("DOOM TROOPERS")	/* Doom Troopers*/
2799 			//|| MATCH_NA("DOOM")		/* Doom */
2800 			//|| MATCH_NA("XAK 1")		/* Xak 1*/
2801 			//|| MATCH_NA("XARDION")		/* Xardion*/
2802 			)
2803 		  	coldata_update_screen = FALSE;
2804 		else
2805 			coldata_update_screen = TRUE;
2806 
2807 		Settings.SpeedhackGameID = SPEEDHACK_NONE;
2808 
2809 		/* Clipping hack - gains around 5-7 extra fps - only use it
2810 		   for specific games where nothing breaks with this hack on */
2811 
2812 		if(
2813 			MATCH_NA("FINAL FANTASY 6")	/* Final Fantasy VI (JP) */
2814 			|| MATCH_NA("FINAL FANTASY 3")	/* Final Fantasy III (US) */
2815 		)
2816 			PPU.FullClipping = FALSE;
2817 		else
2818 			PPU.FullClipping = TRUE;
2819 
2820 		/* SPEED HACK PATHS */
2821 		if(
2822 				MATCH_NA("DONKEY KONG COUNTRY") /* Donkey Kong Country 1 */
2823 		)
2824 			Settings.SpeedhackGameID = SPEEDHACK_DKC1;
2825 
2826 		if(
2827 			MATCH_NA("FINAL FANTASY 6")	/* Final Fantasy VI (JP) */
2828 			|| MATCH_NA("FINAL FANTASY 3")	/* Final Fantasy III (US) */
2829 		)
2830 			Settings.SpeedhackGameID = SPEEDHACK_FF6;
2831 
2832 		/* Check if Chrono Trigger is loaded, if so, we need to set a variable to
2833 		   true to get rid of an annoying mid-frame resolution switch to 256x239
2834 		   which can cause an undesirable flicker/breakup of the screen for a
2835 		   split second - this happens whenever the game switches from normal
2836 		   mode to battle mode and vice versa */
2837 		if(	MATCH_NC("CHRONO TRIGGER") ||	/* Chrono Trigger */
2838 			MATCH_ID("ACT") ||
2839 			MATCH_ID("AC9J")		/* Chrono Trigger (Sample) */
2840 		  )
2841 			Settings.SpeedhackGameID = SPEEDHACK_CT;
2842 
2843       if(
2844             MATCH_NA("STAR FOX") ||		/* Star Fox (US/JP)*/
2845             MATCH_NA("STAR WING"))		/* Star Wing (EU)*/
2846          Settings.SpeedhackGameID = SPEEDHACK_STAR_FOX_1;
2847 
2848 		#if 0
2849 		if(MATCH_ID("AKL"))		/* Killer Instinct*/
2850 			Settings.SpeedhackGameID = SPEEDHACK_KILLER_INSTINCT;
2851 		else if(
2852 				MATCH_NA("Super Metroid") 	/* Super Metroid*/
2853 		)
2854 			Settings.SpeedhackGameID = SPEEDHACK_SUPER_METROID;
2855 		#endif
2856 
2857 		if( MATCH_NA("SUPER MARIOWORLD"))	/* Super Mario World*/
2858          Settings.SpeedhackGameID = SPEEDHACK_SUPER_MARIO_WORLD;
2859 
2860 	}
2861 
2862 	{
2863 		unsigned i;
2864 		const struct {
2865 			const char *fmt;
2866 			int val;
2867 		} fmt_val[6] = {
2868 			{ "PPU.RenderSub = %d", PPU.RenderSub },
2869 			{ "PPU.FullClipping = %d", PPU.FullClipping },
2870 			{ "Settings.Transparency = %d", Settings.Transparency },
2871 			{ "Settings.SpeedhackGameID = %d", Settings.SpeedhackGameID },
2872 			{ "PPU.SFXSpeedupHack = %d", PPU.SFXSpeedupHack },
2873 			{ "coldata_update_screen = %d", coldata_update_screen }
2874 		};
2875 
2876 		for (i = 0; i < 6; i++)
2877 		{
2878 			snprintf(String, sizeof(String), fmt_val[i].fmt, fmt_val[i].val);
2879 			S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, String);
2880 		}
2881 	}
2882 
2883 	if (Settings.AccessoryAutoDetection == ACCESSORY_AUTODETECTION_CONFIRM)
2884 	{
2885 		/* Multitap accessory detection */
2886 		if(
2887 				MATCH_NN("BARKLEY") ||				/* Barkley Shut Up and Jam!*/
2888 				MATCH_ID("ABCJ") ||				/* Battle Cross*/
2889 				MATCH_NA("Bill Walsh College FB1") ||		/* Bill Walsh College Football*/
2890 				MATCH_ID("ANYE") ||				/* College Slam*/
2891 				MATCH_ID("AC3J") ||				/* Crystal Beans from Dungeon Explorer*/
2892 				MATCH_NC("Bruce Lee") ||				/* Dragon - Bruce Lee Story*/
2893 				MATCH_ID("AVS") ||				/* Fever Pitch Soccer (EU) (*)*/
2894 				/* Head-On Soccer (US) (*)*/
2895 				MATCH_NA("FURI-FURI GIRLS") ||			/* Furi-Furi Girls*/
2896 				MATCH_NA("HAT TRICK HERO 2") ||			/* Hat Trick Hero 2*/
2897 				MATCH_NA("HEBEREKE NO PUZZLE") ||		/* Hebereke no Oishii Puzzle wa Irimasenka*/
2898 				MATCH_ID("AWJ") ||				/* International Superstar Soccer Deluxe (EU/US) (*)*/
2899 				/* Jikkyou World Soccer 2 - Fighting Eleven (JP) (*)*/
2900 				MATCH_NA("J-LEAGUE SUPER SOCCER0") ||		/* J-League Super Soccer (JP)*/
2901 				/* Virtual Soccer (EU)*/
2902 				MATCH_NA("JIGSAW PARTY") ||			/* Jigsaw Party (US) (*)*/
2903 				/* Pieces (JP)*/
2904 				MATCH_NA("JIMMY CONNORS TENNIS") ||		/* Jimmy Connors Pro Tennis Tour*/
2905 				MATCH_NA("LAS VEGAS DREAM") ||			/* Las Vegas Dream in Golden Paradise (JP) (*)*/
2906 				/* Vegas Stakes (EU/US)*/
2907 				MATCH_ID("ALT") ||				/* Looney Tunes B-Ball (US) (*)*/
2908 				/* Looney Tunes Basketball (EU) (*)*/
2909 				MATCH_ID("AYHJ") ||				/* Mizuki Shigeru no Youkai Hyakkiyakou*/
2910 				MATCH_ID("A3VJ") ||				/* Multi Play Volleyball*/
2911 				MATCH_NA("MUSCLE BOMBER") ||			/* Muscle Bomber: The Body Explosion (JP) (*)*/
2912 				/* Saturday Night Slam Masters (US)*/
2913 				MATCH_ID("CHAMP WRESTLING") ||			/* Natsume Championship Wrestling*/
2914 				MATCH_ID("ANJ") || 				/* NBA Give 'n Go*/
2915 				MATCH_ID("AXG") || 				/* NBA Hangtime*/
2916 				MATCH_ID("AJT") || 				/* NBA Jam Tournament Edition (EU/US/JP)*/
2917 				MATCH_NA("NBA JAM")   || 			/* NBA Jam*/
2918 				MATCH_ID("AFIE") ||				/* NCAA Final Four Basketball*/
2919 				MATCH_ID("AFBE") ||				/* NCAA Football*/
2920 				MATCH_ID("Q9") ||				/* NFL Quarterback Club / NFL Quarterback Club '95*/
2921 				MATCH_ID("AQB") ||				/* NFL Quarterback Club '96*/
2922 				MATCH_NA("PIECES") ||
2923 				MATCH_ID("Z5") ||				/* Pieces (JP) (*)*/
2924 				/* Jigsaw Party (US)*/
2925 				MATCH_ID("ARVE") ||				/* Rap Jam - Volume One*/
2926 				MATCH_NA("RUSHING BEAT SYURA") ||		/* Rushing Beat Shura (JP) (*)*/
2927 				/* The Peace Keepers (US)*/
2928 				MATCH_NA("S.Night SLAM MASTERS") ||		/* Saturday Night Slam Masters (US) (*)*/
2929 				/* Muscle Bomber: The Body Explosion (JP)*/
2930 				MATCH_NA("Secret of MANA") ||			/* Secret of Mana (EU/US) (*)*/
2931 				/* Seiken Densetsu 2 (JP)*/
2932 				MATCH_NA("SeikenDensetsu 2") ||			/* Seiken Densetsu 2 (JP) (*) / */
2933 				/* Secret of Mana (EU/US)*/
2934 				MATCH_NN("SeikenDensetsu3") ||			/* Seiken Densetsu 3 (in case you use*/
2935 				/* 3-player IPS patch)*/
2936 				MATCH_NA("SMASH TENNIS") ||			/* Smash Tennis (EU) (*) / */
2937 				/* Super Family Tennis (JP)*/
2938 				/*FIXME: TODO - Add CRC32 for Super Family Tennis - CRC32: 2BCBFF26*/
2939 				MATCH_ID("ASR") ||				/* Street Racer*/
2940 				MATCH_NA("SUGOI HEBEREKE") ||			/* Sugoi Hebereke*/
2941 				MATCH_NA("Sugoro Quest++") ||			/* Sugoro Quest++: Dicenics*/
2942 				MATCH_ID("AO9") ||				/* Summer Olympics*/
2943 				MATCH_ID("AS6") ||				/* Super Bomberman 3*/
2944 				MATCH_ID("A4BJ") || 				/* Super Bomberman 4*/
2945 				MATCH_ID("A5SJ") ||				/* Super Bomberman 5*/
2946 				MATCH_ID("AK8J") ||				/* Super Bomberman 5 - Caravan Event Ban*/
2947 				MATCH_ID("APBJ") ||				/* Super Bomberman Panic Bomber W*/
2948 				MATCH_ID("AF5J") ||				/* Super Fire Pro Wrestling X*/
2949 				MATCH_ID("AP4J") ||				/* Super Fire Pro Wrestling Special*/
2950 				MATCH_ID("AQQJ") ||				/* Super Fire Pro Wrestling - Queen's Special*/
2951 				MATCH_ID("A7PJ") ||				/* Super Puyo Puyo Tsuu Remix*/
2952 				MATCH_ID("AT3J") ||				/* Super Tetris 3*/
2953 				MATCH_ID("AFY") ||				/* Syndicate*/
2954 				MATCH_NA("THE PEACE KEEPERS") ||			/* The Peace Keepers (US) (*)*/
2955 				/* Rushing Beat Shura (JP)*/
2956 				MATCH_NA("Tiny Toon Sports") ||			/* Tiny Toon Adventures: Dotabata Daiundoukai (JP) (*)*/
2957 				/* Tiny Toon Adventures: Wacky Sports Challenge (US) (*)*/
2958 				/* Tiny Toon Adventures: Wild & Wacky Sports (EU) (*)*/
2959 				MATCH_ID("A3T") ||				/* Top Gear 3000 (EU/US) (*)*/
2960 				/* Planet's Champ TG 3000 (JP) (*)*/
2961 				MATCH_NA("VEGAS STAKES") ||			/* Vegas Stakes (EU/US) (*)*/
2962 				/* Las Vegas Dream in Golden Paradise (JP)*/
2963 				MATCH_NA("Virtual Soccer") ||			/* Virtual Soccer (EU) (*)*/
2964 				/* J-League Super Soccer (JP)*/
2965 				MATCH_ID("AWF") ||				/* WWF RAW*/
2966 
2967 				/*Catch-alls*/
2968 				MATCH_NC("SUPER BOMBERMAN") ||			/* All Bomberman games (FIXME: remove*/
2969 				/* individual two Bomberman entries if this works)*/
2970 				MATCH_NC("FIFA") ||				/* All FIFA games*/
2971 				MATCH_NN("NHL") ||				/* All NHL games*/
2972 				MATCH_NC("MADDEN") ||				/* All Madden games*/
2973 				MATCH_NC("MICRO MACHINES") ||			/* All Micro Machines games*/
2974 				MATCH_ID("Q4")					/* ?*/
2975 				)
2976 				Settings.CurrentROMisMultitapCompatible = TRUE;
2977 		else
2978 			Settings.CurrentROMisMultitapCompatible = FALSE;
2979 
2980 		/* Mouse accessory detection */
2981 		if	(
2982 				MATCH_NC("ACME ANIMATION FACTOR") ||	/* ACME Animation Factory*/
2983 				MATCH_ID("ACM") ||
2984 				MATCH_NC("ALICE PAINT") ||		/* Alice no Paint Adventure*/
2985 				MATCH_ID("AALJ") ||
2986 				MATCH_NC("ARKANOID DOH IT AGAIN0") ||	/* Arkanoid: Doh It Again*/
2987 				MATCH_ID("A6") ||
2988 				MATCH_NA("SFC SAILORMOON S") ||	/* Bishojou Senshi Sailor Moon S: Kondowa Puzzle de*/
2989 				/* Oshiokiyo!*/
2990 				MATCH_NA("BRANDISH2 EXPERT") ||		/* Brandish 2: Expert*/
2991 				MATCH_ID("AQIJ") ||
2992 				MATCH_NA("BREAKTRHU!") ||		/* BreakThru!*/
2993 				MATCH_ID("ABXE") ||
2994 				MATCH_NA("CIVILIZATION") ||		/* Civilization*/
2995 				MATCH_ID("EQ") ||
2996 				MATCH_NA("CAMELTRY") ||			/* Cameltry (JP) (*)*/
2997 				/* On The Ball (EU/US)*/
2998 				MATCH_NA("CANNON FODDER") ||		/* Cannon Fodder*/
2999 				MATCH_ID("ACNP") ||
3000 				MATCH_ID("M Ve") ||			/* Dai-3-ji Super Robot Taisen*/
3001 				MATCH_ID("AR4J") ||				/* Dai-4-ji Super Robot Taisen*/
3002 				MATCH_NA("SUPER ROBOT WARS 4") ||
3003 				MATCH_NA("DOOM") ||			/* Doom*/
3004 				MATCH_ID("AD8") ||
3005 				MATCH_ID("A88J") ||			/* Doukyuusei 2 (JP) (NP)*/
3006 				MATCH_NA("DRAGON KNIGHT 4") ||		/* Dragon Knight 4*/
3007 				MATCH_ID("A87J") ||
3008 				MATCH_NA("Eye of the Beholder") ||	/* Eye of the Beholder*/
3009 				MATCH_NA("FARLANDSTORY2") ||		/* Farland Story 2*/
3010 				MATCH_ID("A2FJ") ||
3011 				MATCH_NA("Fun 'N Games") ||		/* Fun 'N Games (EU/US)*/
3012 				MATCH_NA("GALAXY ROBO") ||		/* Galaxy Robo*/
3013 				MATCH_NA("HIOUDEN") ||			/* Hiouden: Mamono-tachi tono Chikai*/
3014 				MATCH_NA("JIGSAW PARTY") ||		/* Jigsaw Party (US) (*)*/
3015 				/* Pieces (JP)*/
3016 				/*MATCH_NA("JURASSIC PARK") ||		// Jurassic Park*/
3017 				MATCH_NA("King Arthurs World") ||	/* King Arthur's World (EU/US) (*)*/
3018 				/* Royal Conquest (JP)*/
3019 				MATCH_NA("KOUTETSU-NO KISHI") ||		/* Koutetsu No Kishi*/
3020 				MATCH_NA("KOUTETSU-NO KISHI 2") ||	/* Koutetsu No Kishi 2*/
3021 				MATCH_NA("KOUTETSU-NO KISHI 3") ||	/* Koutetsu No Kishi 3*/
3022 				MATCH_ID("APZJ") ||
3023 				MATCH_NA("LAMBORGHINI AMERICAN") ||	/* Lamborghini American Challenge (EU/US)*/
3024 				MATCH_NA("LAS VEGAS DREAM") ||		/* Las Vegas Dream in Golden Paradise (JP) (*)*/
3025 				/* Vegas Stakes (EU/US)*/
3026 				MATCH_NA("Lemmings 2,The Tribes") ||	/* Lemmings 2: The Tribes*/
3027 				MATCH_ID("L2") ||
3028 				MATCH_NA("LORD MONARCH") ||		/* Lord Monarch*/
3029 				MATCH_NA("Mario&Wario") ||		/* Mario & Wario*/
3030 				MATCH_NA("SUPER PICROSS") ||		/* Mario no Super Picross*/
3031 				MATCH_ID("ACXJ") ||
3032 				MATCH_NC("MARIOPAINT") ||		/* Mario Paint*/
3033 				MATCH_NA("MEY  Preschool Fun") ||	/* Mario's Early Years: Preschool Fun*/
3034 				MATCH_ID("AMEE") ||
3035 				MATCH_NA("MEGA LO MANIA") ||		/* Mega-Lo Mania*/
3036 				MATCH_NA("MIGHT  AND MAGIC III") ||	/* Might And Magic III - Isles of Terra*/
3037 				MATCH_NA("WONDER KITCHEN") ||		/* Motoko-chan no Wonder Kitchen*/
3038 				MATCH_NA("Nobunaga's Ambition") ||	/* Nobunaga's Ambition (US) (*)*/
3039 				/* Super Nobunaga no Yabou: Zenkokuban (JP)*/
3040 				MATCH_NA("ON THE BALL") ||		/* On The Ball (EU/US) (*)*/
3041 				/* Cameltry (JP)*/
3042 				MATCH_NA("OPERATION THUNDERBOLT1") ||	/* Operation Thunderbolt*/
3043 				MATCH_NA("PIECES") ||
3044 				MATCH_ID("Z5") ||			/* Pieces (JP) (*)*/
3045 				/* Jigsaw Party (US)*/
3046 				MATCH_NC("POPULOUS II") ||		/* Populous II*/
3047 				MATCH_NA("POWERMONGER") ||		/* Power Monger*/
3048 				MATCH_NA("Revolution X") ||		/* Revolution X*/
3049 				MATCH_ID("AXR") ||
3050 				MATCH_NA("Royal Conquest") ||		/* Royal Conquest (JP) (*)*/
3051 				/* King Arthur's World (EU/US)*/
3052 				MATCH_NA("TENBU SPIRIT") ||		/* San Goku Shi Seishi: Tenbu Spirits*/
3053 				MATCH_NA("SHIEN THE BLADE CHASE0") ||	/* Shien The Blade Chaser (JP) (*)*/
3054 				MATCH_NA("SHIEN'S REVENGE") ||		/* Shien's Revenge (*)*/
3055 				MATCH_NC("SimAnt") ||			/* SimAnt*/
3056 				MATCH_NA("SNOOPY CONCERT") ||		/* Snoopy Concert*/
3057 				MATCH_NA("SUPER CAESARS PALACE") ||	/* Super Caesar's Palace*/
3058 				MATCH_NA("SUPER CASTLES") ||		/* Super Castles*/
3059 				MATCH_ID("AVIJ") ||
3060 				/*FIXME: TODO: Super Noah's Ark 3D: - bad checksum - CRC32: A2315A14*/
3061 				MATCH_NA("SuperPachiSlotMahjong") ||	/* Super Pachi Slot Mahjong*/
3062 				MATCH_NA("SUPER SOLITAIRE") ||		/* Super Solitaire*/
3063 				MATCH_NA("SUPER ZENKOKUBAN") ||		/* Super Nobunaga no Yabou: Zenkokuban (JP) (*)*/
3064 				/* Nobunaga's Ambition (US)*/
3065 				MATCH_NA("TERMINATOR2 THE MOVIE0") ||	/* Terminator 2: The Arcade Game*/
3066 				MATCH_NA("TINSTAR") ||			/* Tin Star*/
3067 				MATCH_ID("9N") ||
3068 				MATCH_NA("TOKIMEKI MEMORIAL") ||		/* Tokimeki Memorial*/
3069 				MATCH_ID("AM8J") ||
3070 				MATCH_NA("Troddlers") ||			/* Troddlers*/
3071 				MATCH_NA("UTOPIA") ||			/* Utopia*/
3072 				MATCH_NA("VEGAS STAKES") ||		/* Vegas Stakes (EU/US) (*)*/
3073 				/* Las Vegas Dream in Golden Paradise (JP)*/
3074 				MATCH_NC("WOLFENSTEIN 3D") ||		/* Wolfenstein 3D*/
3075 				MATCH_NA("WONDERPROJECT J") ||		/* Wonder Project J*/
3076 				MATCH_ID("APJJ") ||
3077 				MATCH_NA("ZAN2 SPIRITS") ||		/* Zan 2: Spirits*/
3078 				MATCH_NA("ZAN3 SFC")			/* Zan 3: Spirits*/
3079 				)
3080 				Settings.CurrentROMisMouseCompatible = TRUE;
3081 		else
3082 			Settings.CurrentROMisMouseCompatible = FALSE;
3083 
3084 		/* Super Scope accessory detection */
3085 		if	(
3086 				MATCH_NA("BATTLE CLASH") ||		/* Battle Clash (EU/US) (*)*/
3087 										/* Space Bazooka (JP)*/
3088 				MATCH_NA("SPACE BAZOOKA") ||		/* Space Bazooka (JP) (*)*/
3089 										/* Battle Clash (EU/US)*/
3090 				/*FIXME: TODO: Add The Hunt for Red October - used for bonus game*/
3091 				/*FIXME: TODO: Add Lamborghini American Challenge - if needed*/
3092 				MATCH_NA("METAL COMBAT") ||		/* Metal Combat: Falcon's Revenge*/
3093 				MATCH_NA("OPERATION THUNDERBOLT1") ||	/* Operation Thunderbolt*/
3094 				MATCH_NA("SUPER SCOPE 6") ||		/* Super Scope 6*/
3095 				/*MATCH_NA("TERMINATOR2 THE MOVIE0") ||	// Terminator 2: The Arcade Game*/
3096 				MATCH_NA("TINSTAR") ||			/* Tin Star*/
3097 				MATCH_ID("9N") ||
3098 				MATCH_NA("X ZONE") ||			/* X-Zone*/
3099 				/*FIXME: TODO: Add Yoshi no Road Hunting - CRC32: 52948F3C*/
3100 				MATCH_NA("YOSHI'S SAFARI")		/* Yoshi's Safari*/
3101 			)
3102 			Settings.CurrentROMisSuperScopeCompatible = TRUE;
3103 		else
3104 			Settings.CurrentROMisSuperScopeCompatible = FALSE;
3105 	}
3106 
3107 	S9xAPUTimingSetSpeedup(Timings.APUSpeedup);
3108 	S9xAPUAllowTimeOverflow(Timings.APUAllowTimeOverflow);
3109 
3110 	/* Other timing hacks */
3111 
3112 	Timings.HDMAStart   = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100;
3113 	Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC;
3114 
3115 	if (!Settings.DisableGameSpecificHacks)
3116 	{
3117 		/* The delay to sync CPU and DMA which Snes9x cannot emulate.
3118 		   Some games need really severe delay timing... */
3119 
3120 		/* Battle Grandprix */
3121 		if (MATCH_NA("BATTLE GRANDPRIX"))
3122 		{
3123 			Timings.DMACPUSync = 20;
3124 			snprintf(String, sizeof(String),
3125 				 "DMA sync: %d", Timings.DMACPUSync);
3126 			S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, String);
3127 		}
3128 	}
3129 
3130 	if (!Settings.DisableGameSpecificHacks)
3131 	{
3132 		/* Opcode-based emulators cannot escape from "reading $4211/BPL" infinite loop...
3133 		   The true IRQ can be triggered inside an opcode. */
3134 		if (MATCH_NA("TRAVERSE")) /* Traverse - Starlight & Prairie*/
3135 		{
3136 			Timings.IRQPendCount = 1;
3137 			snprintf(String, sizeof(String),
3138 				 "IRQ count hack: %d", Timings.IRQPendCount);
3139 			S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, String);
3140 		}
3141 
3142 		/* An infinite loop reads $4212 and waits V-blank end, whereas
3143 		   VIRQ is set V=0.
3144 
3145 		   If Snes9x succeeds to escape from the loop before jumping
3146 		   into the IRQ handler, the game goes further.
3147 
3148 		   If Snes9x jumps into the IRQ handler before escaping from
3149 		   the loop, Snes9x cannot escape from the loop permanently
3150 		   because the RTI is in the next V-blank. */
3151 
3152 		if (MATCH_NA("Aero the AcroBat 2"))
3153 		{
3154 			Timings.IRQPendCount = 2;
3155 			snprintf(String, sizeof(String),
3156 				"IRQ count hack: %d", Timings.IRQPendCount);
3157 			S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, String);
3158 		}
3159 
3160 		if (MATCH_NA("BATTLE BLAZE"))
3161 		{
3162 			Timings.IRQPendCount = 1;
3163 			snprintf(String, sizeof(String),
3164 				 "IRQ count hack: %d", Timings.IRQPendCount);
3165 			S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP, String);
3166 		}
3167 	}
3168 
3169 	if (!Settings.DisableGameSpecificHacks)
3170 	{
3171 		/* XXX: What's happening? */
3172 
3173 		/* Spider-Man and the X-Men */
3174 		if (MATCH_NA("X-MEN"))
3175 		{
3176 			Settings.BlockInvalidVRAMAccess = FALSE;
3177 			S9xMessage(S9X_MSG_WARN, S9X_CATEGORY_MAP,
3178 				   "Invalid VRAM access hack");
3179 		}
3180 	}
3181 
3182 	/* SRAM initial value */
3183 
3184 	if (!Settings.DisableGameSpecificHacks)
3185 	{
3186 		if (MATCH_NA("HITOMI3"))
3187 		{
3188 			Memory.SRAMSize = 1;
3189 			Memory.SRAMMask = ((1 << (Memory.SRAMSize + 3)) * 128) - 1;
3190 		}
3191 
3192 		/* SRAM value fixes */
3193 		if (MATCH_NA("SUPER DRIFT OUT")      || /* Super Drift Out*/
3194 			MATCH_NA("SATAN IS OUR FATHER!") ||
3195 			MATCH_NA("goemon 4"))               /* Ganbare Goemon Kirakira Douchuu*/
3196 			SNESGameFixes.SRAMInitialValue = 0x00;
3197 
3198 		/* Additional game fixes by sanmaiwashi ...*/
3199 		/* XXX: unnecessary?*/
3200 		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*/
3201 			SNESGameFixes.SRAMInitialValue = 0x6b;
3202 
3203 		/* others: BS and ST-01x games are 0x00.*/
3204 	}
3205 
3206 	/* OAM hacks */
3207 
3208 	if (!Settings.DisableGameSpecificHacks)
3209 	{
3210 		/* OAM hacks because we don't fully understand the behavior of
3211 		   the SNES.
3212 
3213 		   Totally wacky display in 2P mode...
3214 
3215 		   seems to need a disproven behavior, so we're definitely
3216 		   overlooking some other bug? */
3217 
3218 		/* Uniracers */
3219 		if (MATCH_NN("UNIRACERS"))
3220 		{
3221 			SNESGameFixes.Uniracers = TRUE;
3222 			S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_MAP,
3223 				   "Applied Uniracers hack.");
3224 		}
3225 	}
3226 
3227 	/* Show ROM information */
3228 
3229 	strcpy(Memory.RawROMName, Memory.ROMName);
3230 	snprintf(displayName, sizeof(displayName), "%s",
3231 		 SafeANK(Memory.ROMRegion, Memory.ROMName));
3232 	snprintf(Memory.ROMName, sizeof(Memory.ROMName),
3233 		 "%s", Safe(Memory.ROMName));
3234 	snprintf(Memory.ROMId, sizeof(Memory.ROMId), "%s", Safe(Memory.ROMId));
3235 
3236 	snprintf(String, sizeof(String), "\"%s\" [%s] %s, %s, %s, %s, SRAM:%s, ID:%s, CRC32:%08X",
3237 		displayName, isChecksumOK ? "checksum ok" : ((Multi.cartType == 4) ? "no checksum" : "bad checksum"),
3238 		(Memory.HiROM ? ((Memory.ExtendedFormat != NOPE) ? "ExHiROM": "HiROM") : "LoROM"), Size(), KartContents(Memory.ROMType), Settings.PAL ? "PAL" : "NTSC", StaticRAMSize(), Memory.ROMId, Memory.ROMCRC32);
3239 	S9xMessage(S9X_MSG_INFO, S9X_CATEGORY_ROM, String);
3240 
3241 	Settings.ForceLoROM = FALSE;
3242 	Settings.ForceHiROM = FALSE;
3243 	Settings.ForceHeader = FALSE;
3244 	Settings.ForceNoHeader = FALSE;
3245 	Settings.ForceInterleaved = FALSE;
3246 	Settings.ForceInterleaved2 = FALSE;
3247 	Settings.ForceInterleaveGD24 = FALSE;
3248 	Settings.ForceNotInterleaved = FALSE;
3249 	Settings.ForcePAL = FALSE;
3250 	Settings.ForceNTSC = FALSE;
3251 
3252 	S9xVerifyControllers();
3253 
3254 	return (TRUE);
3255 }
3256