memmap.c 105 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/***********************************************************************************
  Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.

  (c) Copyright 1996 - 2002  Gary Henderson (gary.henderson@ntlworld.com),
                             Jerremy Koot (jkoot@snes9x.com)

  (c) Copyright 2002 - 2004  Matthew Kendora

  (c) Copyright 2002 - 2005  Peter Bortas (peter@bortas.org)

  (c) Copyright 2004 - 2005  Joel Yliluoma (http://iki.fi/bisqwit/)

  (c) Copyright 2001 - 2006  John Weidman (jweidman@slip.net)

  (c) Copyright 2002 - 2006  funkyass (funkyass@spam.shaw.ca),
                             Kris Bleakley (codeviolation@hotmail.com)

  (c) Copyright 2002 - 2010  Brad Jorsch (anomie@users.sourceforge.net),
                             Nach (n-a-c-h@users.sourceforge.net),
                             zones (kasumitokoduck@yahoo.com)

  (c) Copyright 2006 - 2007  nitsuja

  (c) Copyright 2009 - 2010  BearOso,
                             OV2


  BS-X C emulator code
  (c) Copyright 2005 - 2006  Dreamer Nom,
                             zones

  C4 x86 assembler and some C emulation code
  (c) Copyright 2000 - 2003  _Demo_ (_demo_@zsnes.com),
                             Nach,
                             zsKnight (zsknight@zsnes.com)

  C4 C++ code
  (c) Copyright 2003 - 2006  Brad Jorsch,
                             Nach

  DSP-1 emulator code
  (c) Copyright 1998 - 2006  _Demo_,
                             Andreas Naive (andreasnaive@gmail.com),
                             Gary Henderson,
                             Ivar (ivar@snes9x.com),
                             John Weidman,
                             Kris Bleakley,
                             Matthew Kendora,
                             Nach,
                             neviksti (neviksti@hotmail.com)

  DSP-2 emulator code
  (c) Copyright 2003         John Weidman,
                             Kris Bleakley,
                             Lord Nightmare (lord_nightmare@users.sourceforge.net),
                             Matthew Kendora,
                             neviksti

  DSP-3 emulator code
  (c) Copyright 2003 - 2006  John Weidman,
                             Kris Bleakley,
                             Lancer,
                             z80 gaiden

  DSP-4 emulator code
  (c) Copyright 2004 - 2006  Dreamer Nom,
                             John Weidman,
                             Kris Bleakley,
                             Nach,
                             z80 gaiden

  OBC1 emulator code
  (c) Copyright 2001 - 2004  zsKnight,
                             pagefault (pagefault@zsnes.com),
                             Kris Bleakley
                             Ported from x86 assembler to C by sanmaiwashi

  SPC7110 and RTC C++ emulator code used in 1.39-1.51
  (c) Copyright 2002         Matthew Kendora with research by
                             zsKnight,
                             John Weidman,
                             Dark Force

  SPC7110 and RTC C++ emulator code used in 1.52+
  (c) Copyright 2009         byuu,
                             neviksti

  S-DD1 C emulator code
  (c) Copyright 2003         Brad Jorsch with research by
                             Andreas Naive,
                             John Weidman

  S-RTC C emulator code
  (c) Copyright 2001 - 2006  byuu,
                             John Weidman

  ST010 C++ emulator code
  (c) Copyright 2003         Feather,
                             John Weidman,
                             Kris Bleakley,
                             Matthew Kendora

  Super FX x86 assembler emulator code
  (c) Copyright 1998 - 2003  _Demo_,
                             pagefault,
                             zsKnight

  Super FX C emulator code
  (c) Copyright 1997 - 1999  Ivar,
                             Gary Henderson,
                             John Weidman

  Sound emulator code used in 1.5-1.51
  (c) Copyright 1998 - 2003  Brad Martin
  (c) Copyright 1998 - 2006  Charles Bilyue'

  Sound emulator code used in 1.52+
  (c) Copyright 2004 - 2007  Shay Green (gblargg@gmail.com)

  SH assembler code partly based on x86 assembler code
  (c) Copyright 2002 - 2004  Marcus Comstedt (marcus@mc.pp.se)

  2xSaI filter
  (c) Copyright 1999 - 2001  Derek Liauw Kie Fa

  HQ2x, HQ3x, HQ4x filters
  (c) Copyright 2003         Maxim Stepin (maxim@hiend3d.com)

  NTSC filter
  (c) Copyright 2006 - 2007  Shay Green

  GTK+ GUI code
  (c) Copyright 2004 - 2010  BearOso

  Win32 GUI code
  (c) Copyright 2003 - 2006  blip,
                             funkyass,
                             Matthew Kendora,
                             Nach,
                             nitsuja
  (c) Copyright 2009 - 2010  OV2

  Mac OS GUI code
  (c) Copyright 1998 - 2001  John Stiles
  (c) Copyright 2001 - 2010  zones


  Specific ports contains the works of other authors. See headers in
  individual files.


  Snes9x homepage: http://www.snes9x.com/

  Permission to use, copy, modify and/or distribute Snes9x in both binary
  and source form, for non-commercial purposes, is hereby granted without
  fee, providing that this license information and copyright notice appear
  with all copies and any derived work.

  This software is provided 'as-is', without any express or implied
  warranty. In no event shall the authors be held liable for any damages
  arising from the use of this software or it's derivatives.

  Snes9x is freeware for PERSONAL USE only. Commercial users should
  seek permission of the copyright holders first. Commercial use includes,
  but is not limited to, charging money for Snes9x or software derived from
  Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
  using Snes9x as a promotion for your commercial product.

  The copyright holders request that bug fixes and improvements to the code
  should be forwarded to them so everyone can benefit from the modifications
  in future versions.

  Super NES and Super Nintendo Entertainment System are trademarks of
  Nintendo Co., Limited and its subsidiary companies.
 ***********************************************************************************/
176
#include <ctype.h>
177
178
#include <stdlib.h>
#include <string.h>
179
180
181

#include "snes9x.h"
#include "memmap.h"
TwinAphex51224's avatar
TwinAphex51224 committed
182
#include "getset.h"
183
#include "apu.h"
184
#include "fxinst.h"
185
186
187
188
189
190
#include "fxemu.h"
#include "sdd1.h"
#include "srtc.h"
#include "controls.h"
#include "cheats.h"
#include "display.h"
191
#include "spc7110dec.h"
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

#ifndef max
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif

#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif

static const uint32	crc32Table[256] =
{
	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
	0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
	0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
	0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
	0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};

248
/* deinterleave*/
249
250
251

static void S9xDeinterleaveType1 (int size, uint8 *base)
{
252
253
	uint8 *tmp;
	uint8	blocks[256], b;
254
	int nblocks;
255
	int	i, j;
256
257
	
	nblocks = size >> 16;
258

259
	for ( i = 0; i < nblocks; i++)
260
261
262
263
264
	{
		blocks[i * 2] = i + nblocks;
		blocks[i * 2 + 1] = i;
	}

265
	tmp = (uint8 *) malloc(0x8000);
266
267
	if (tmp)
	{
268
		for ( i = 0; i < nblocks * 2; i++)
269
		{
270
			for ( j = i; j < nblocks * 2; j++)
271
272
273
274
275
276
			{
				if (blocks[j] == i)
				{
					memmove(tmp, &base[blocks[j] * 0x8000], 0x8000);
					memmove(&base[blocks[j] * 0x8000], &base[blocks[i] * 0x8000], 0x8000);
					memmove(&base[blocks[i] * 0x8000], tmp, 0x8000);
277
					b = blocks[j];
278
279
280
281
282
283
284
285
286
287
288
289
290
					blocks[j] = blocks[i];
					blocks[i] = b;
					break;
				}
			}
		}

		free(tmp);
	}
}

static void S9xDeinterleaveType2 (int size, uint8 *base)
{
291
	/* for odd Super FX images */
292
293
	uint8 *tmp;
	uint8	blocks[256], b;
294
295
296
297
	int nblocks, step, i, j;

	nblocks = size >> 16;
	step = 64;
298
299
300
301
302

	while (nblocks <= step)
		step >>= 1;
	nblocks = step;

303
	for ( i = 0; i < nblocks * 2; i++)
304
305
		blocks[i] = (i & ~0xf) | ((i & 3) << 2) | ((i & 12) >> 2);

306
	tmp = (uint8 *) malloc(0x10000);
307
308
	if (tmp)
	{
309
		for ( i = 0; i < nblocks * 2; i++)
310
		{
311
			for ( j = i; j < nblocks * 2; j++)
312
313
314
315
316
317
			{
				if (blocks[j] == i)
				{
					memmove(tmp, &base[blocks[j] * 0x10000], 0x10000);
					memmove(&base[blocks[j] * 0x10000], &base[blocks[i] * 0x10000], 0x10000);
					memmove(&base[blocks[i] * 0x10000], tmp, 0x10000);
318
					b = blocks[j];
319
320
321
322
323
324
325
326
327
328
329
330
331
					blocks[j] = blocks[i];
					blocks[i] = b;
					break;
				}
			}
		}

		free(tmp);
	}
}

static void S9xDeinterleaveGD24 (int size, uint8 *base)
{
332
	uint8 *tmp;
333
	/* for 24Mbit images dumped with Game Doctor */
334
335
336
	if (size != 0x300000)
		return;

337
	tmp = (uint8 *) malloc(0x80000);
338
339
340
341
342
343
344
345
346
347
348
349
350
	if (tmp)
	{
		memmove(tmp, &base[0x180000], 0x80000);
		memmove(&base[0x180000], &base[0x200000], 0x80000);
		memmove(&base[0x200000], &base[0x280000], 0x80000);
		memmove(&base[0x280000], tmp, 0x80000);

		free(tmp);

		S9xDeinterleaveType1(size, base);
	}
}

351
/* allocation and deallocation */
352

TwinAphex51224's avatar
TwinAphex51224 committed
353
bool8 Init (void)
354
{
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
	Memory.RAM	 = (uint8 *) malloc(0x20000);
	Memory.SRAM = (uint8 *) malloc(0x20000);
	Memory.VRAM = (uint8 *) malloc(0x10000);
	Memory.ROM  = (uint8 *) malloc(MAX_ROM_SIZE + 0x200 + 0x8000);

	IPPU.TileCache[TILE_2BIT]       = (uint8 *) malloc(MAX_2BIT_TILES * 64);
	IPPU.TileCache[TILE_4BIT]       = (uint8 *) malloc(MAX_4BIT_TILES * 64);
	IPPU.TileCache[TILE_8BIT]       = (uint8 *) malloc(MAX_8BIT_TILES * 64);
	IPPU.TileCache[TILE_2BIT_EVEN]  = (uint8 *) malloc(MAX_2BIT_TILES * 64);
	IPPU.TileCache[TILE_2BIT_ODD]   = (uint8 *) malloc(MAX_2BIT_TILES * 64);
	IPPU.TileCache[TILE_4BIT_EVEN]  = (uint8 *) malloc(MAX_4BIT_TILES * 64);
	IPPU.TileCache[TILE_4BIT_ODD]   = (uint8 *) malloc(MAX_4BIT_TILES * 64);

	IPPU.TileCached[TILE_2BIT]      = (uint8 *) malloc(MAX_2BIT_TILES);
	IPPU.TileCached[TILE_4BIT]      = (uint8 *) malloc(MAX_4BIT_TILES);
	IPPU.TileCached[TILE_8BIT]      = (uint8 *) malloc(MAX_8BIT_TILES);
	IPPU.TileCached[TILE_2BIT_EVEN] = (uint8 *) malloc(MAX_2BIT_TILES);
	IPPU.TileCached[TILE_2BIT_ODD]  = (uint8 *) malloc(MAX_2BIT_TILES);
	IPPU.TileCached[TILE_4BIT_EVEN] = (uint8 *) malloc(MAX_4BIT_TILES);
	IPPU.TileCached[TILE_4BIT_ODD]  = (uint8 *) malloc(MAX_4BIT_TILES);
375

376

377
378
379
	/* don't render subscreen speed hack - disable this by default by 
	turning the variable (RenderSub - opposite of don't render sub) on */

380
381
	PPU.RenderSub = TRUE;
	PPU.FullClipping = TRUE;
382
	coldata_update_screen = TRUE;
383

TwinAphex51224's avatar
TwinAphex51224 committed
384
	if (!Memory.RAM || !Memory.SRAM || !Memory.VRAM || !Memory.ROM ||
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
			!IPPU.TileCache[TILE_2BIT]       ||
			!IPPU.TileCache[TILE_4BIT]       ||
			!IPPU.TileCache[TILE_8BIT]       ||
			!IPPU.TileCache[TILE_2BIT_EVEN]  ||
			!IPPU.TileCache[TILE_2BIT_ODD]   ||
			!IPPU.TileCache[TILE_4BIT_EVEN]  ||
			!IPPU.TileCache[TILE_4BIT_ODD]   ||
			!IPPU.TileCached[TILE_2BIT]      ||
			!IPPU.TileCached[TILE_4BIT]      ||
			!IPPU.TileCached[TILE_8BIT]      ||
			!IPPU.TileCached[TILE_2BIT_EVEN] ||
			!IPPU.TileCached[TILE_2BIT_ODD]  ||
			!IPPU.TileCached[TILE_4BIT_EVEN] ||
			!IPPU.TileCached[TILE_4BIT_ODD])
	{
400
401
		Deinit();
		return (FALSE);
402
	}
403

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
	memset(Memory.RAM, 0,  0x20000);
	memset(Memory.SRAM, 0, 0x20000);
	memset(Memory.VRAM, 0, 0x10000);
	memset(Memory.ROM, 0,  MAX_ROM_SIZE + 0x200 + 0x8000);

	memset(IPPU.TileCache[TILE_2BIT], 0, MAX_2BIT_TILES * 64);
	memset(IPPU.TileCache[TILE_4BIT], 0, MAX_4BIT_TILES * 64);
	memset(IPPU.TileCache[TILE_8BIT], 0, MAX_8BIT_TILES * 64);
	memset(IPPU.TileCache[TILE_2BIT_EVEN], 0,  MAX_2BIT_TILES * 64);
	memset(IPPU.TileCache[TILE_2BIT_ODD], 0,   MAX_2BIT_TILES * 64);
	memset(IPPU.TileCache[TILE_4BIT_EVEN], 0,  MAX_4BIT_TILES * 64);
	memset(IPPU.TileCache[TILE_4BIT_ODD], 0,   MAX_4BIT_TILES * 64);

	memset(IPPU.TileCached[TILE_2BIT], 0,      MAX_2BIT_TILES);
	memset(IPPU.TileCached[TILE_4BIT], 0,      MAX_4BIT_TILES);
	memset(IPPU.TileCached[TILE_8BIT], 0,      MAX_8BIT_TILES);
	memset(IPPU.TileCached[TILE_2BIT_EVEN], 0, MAX_2BIT_TILES);
	memset(IPPU.TileCached[TILE_2BIT_ODD], 0,  MAX_2BIT_TILES);
	memset(IPPU.TileCached[TILE_4BIT_EVEN], 0, MAX_4BIT_TILES);
	memset(IPPU.TileCached[TILE_4BIT_ODD], 0,  MAX_4BIT_TILES);
424

425
426
	/* FillRAM uses first 32K of ROM image area, otherwise space just
	wasted. Might be read by the SuperFX code. */
427

TwinAphex51224's avatar
TwinAphex51224 committed
428
	Memory.FillRAM = Memory.ROM;
429

430
431
	/* Add 0x8000 to ROM image pointer to stop SuperFX code accessing
	unallocated memory (can cause crash on some ports). */
432

TwinAphex51224's avatar
TwinAphex51224 committed
433
	Memory.ROM += 0x8000;
434

435
436
437
438
	Memory.C4RAM   = Memory.ROM + 0x400000 + 8192 * 8; /* C4 */
	Memory.OBC1RAM = Memory.ROM + 0x400000; /* OBC1 */
	Memory.BIOSROM = Memory.ROM + 0x300000; /* BS */
	Memory.BSRAM   = Memory.ROM + 0x400000; /* BS */
439

TwinAphex51224's avatar
TwinAphex51224 committed
440
	SuperFX.pvRegisters = Memory.FillRAM + 0x3000;
441
	SuperFX.nRamBanks   = 2; /* Most only use 1.  1=64KB=512Mb, 2=128KB=1024Mb */
TwinAphex51224's avatar
TwinAphex51224 committed
442
	SuperFX.pvRam       = Memory.SRAM;
443
	SuperFX.nRomBanks   = (2 * 1024 * 1024) / (32 * 1024);
TwinAphex51224's avatar
TwinAphex51224 committed
444
	SuperFX.pvRom       = (uint8 *) Memory.ROM;
445
446
447
448

	return (TRUE);
}

449
450
451
452
static char * Safe (const char *s)
{
	static char	*safe = NULL;
	static int	safe_len = 0;
453
	int		i, len;
454
455
456
457
458
459
460
461
462
463
464
465

	if (s == NULL)
	{
		if (safe)
		{
			free(safe);
			safe = NULL;
		}

		return (NULL);
	}

466
	len = strlen(s);
467
468
469
470
471
472
473
474
475
	if (!safe || len + 1 > safe_len)
	{
		if (safe)
			free(safe);

		safe_len = len + 1;
		safe = (char *) malloc(safe_len);
	}

476
	for ( i = 0; i < len; i++)
477
478
479
480
481
482
483
484
485
486
487
488
489
	{
		if (s[i] >= 32 && s[i] < 127)
			safe[i] = s[i];
		else
			safe[i] = '_';
	}

	safe[len] = 0;

	return (safe);
}

static char * SafeANK (uint8 ROMRegion, const char *s)
490
491
492
{
	static char	*safe = NULL;
	static int	safe_len = 0;
493
	int		i, len;
494
495
496
497
498
499
500
501
502
503
504
505

	if (s == NULL)
	{
		if (safe)
		{
			free(safe);
			safe = NULL;
		}

		return (NULL);
	}

506
	len = strlen(s);
507
508
509
510
511
512
513
514
515
	if (!safe || len + 1 > safe_len)
	{
		if (safe)
			free(safe);

		safe_len = len + 1;
		safe = (char *) malloc(safe_len);
	}

516
	for ( i = 0; i < len; i++)
517
	{
518
		if (s[i] >= 32 && s[i] < 127) /* ASCII */
519
520
			safe [i] = s[i];
		else
521
		if (ROMRegion == 0 && ((uint8) s[i] >= 0xa0 && (uint8) s[i] < 0xe0)) /* JIS X 201 - Katakana */
522
523
524
525
526
527
528
529
530
531
			safe [i] = s[i];
		else
			safe [i] = '_';
	}

	safe [len] = 0;

	return (safe);
}

TwinAphex51224's avatar
TwinAphex51224 committed
532
void Deinit (void)
533
{
534
	int t;
TwinAphex51224's avatar
TwinAphex51224 committed
535
	if (Memory.RAM)
536
	{
TwinAphex51224's avatar
TwinAphex51224 committed
537
538
		free(Memory.RAM);
		Memory.RAM = NULL;
539
540
	}

TwinAphex51224's avatar
TwinAphex51224 committed
541
	if (Memory.SRAM)
542
	{
TwinAphex51224's avatar
TwinAphex51224 committed
543
544
		free(Memory.SRAM);
		Memory.SRAM = NULL;
545
546
	}

TwinAphex51224's avatar
TwinAphex51224 committed
547
	if (Memory.VRAM)
548
	{
TwinAphex51224's avatar
TwinAphex51224 committed
549
550
		free(Memory.VRAM);
		Memory.VRAM = NULL;
551
552
	}

TwinAphex51224's avatar
TwinAphex51224 committed
553
	if (Memory.ROM)
554
	{
TwinAphex51224's avatar
TwinAphex51224 committed
555
556
557
		Memory.ROM -= 0x8000;
		free(Memory.ROM);
		Memory.ROM = NULL;
558
559
	}

560
561
562
563
564
	if(Settings.SPC7110 || Settings.SPC7110RTC)
	{
		S9xFreeSPC7110();
	}

565
	for ( t = 0; t < 7; t++)
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
	{
		if (IPPU.TileCache[t])
		{
			free(IPPU.TileCache[t]);
			IPPU.TileCache[t] = NULL;
		}

		if (IPPU.TileCached[t])
		{
			free(IPPU.TileCached[t]);
			IPPU.TileCached[t] = NULL;
		}
	}

	Safe(NULL);
TwinAphex51224's avatar
TwinAphex51224 committed
581
	SafeANK(Memory.ROMRegion, NULL);
582
583
}

584
/* file management and ROM detection */
585
586
587

static bool8 allASCII (uint8 *b, int size)
{
588
589
	int i;
	for ( i = 0; i < size; i++)
590
591
592
593
594
595
596
597
598
599
	{
		if (b[i] < 32 || b[i] > 126)
			return (FALSE);
	}

	return (TRUE);
}

static bool8 is_SufamiTurbo_BIOS (uint8 *data, uint32 size)
{
600
601
	if (size == 0x40000 && strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0
	&& strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) == 0)
602
		return TRUE;
603
	else
604
		return FALSE;
605
606
607
608
}

static bool8 is_SufamiTurbo_Cart (uint8 *data, uint32 size)
{
609
610
	if (size >= 0x80000 && size <= 0x100000 && strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0
	&& strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) != 0)
611
		return TRUE;
612
	else
613
		return FALSE;
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
}

static bool8 is_SameGame_BIOS (uint8 *data, uint32 size)
{
	if (size == 0x100000 && strncmp((char *) (data + 0xffc0), "Same Game Tsume Game", 20) == 0)
		return (TRUE);
	else
		return (FALSE);
}

static bool8 is_SameGame_Add_On (uint8 *data, uint32 size)
{
	if (size == 0x80000)
		return (TRUE);
	else
		return (FALSE);
}

TwinAphex51224's avatar
TwinAphex51224 committed
632
static int ScoreHiROM (uint32 calculated_size, uint8 * rom,  bool8 skip_header, int32 romoff)
633
{
634
635
636
637
638
	uint8	*buf;
	int score;

	score = 0;
	buf = rom + 0xff00 + romoff + (skip_header ? 0x200 : 0);
639
640
641
642

	if (buf[0xd5] & 0x1)
		score += 2;

643
	/* Mode23 is SA-1 */
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
	if (buf[0xd5] == 0x23)
		score -= 2;

	if (buf[0xd4] == 0x20)
		score += 2;

	if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff)
	{
		score += 2;
		if (0 != (buf[0xde] + (buf[0xdf] << 8)))
			score++;
	}

	if (buf[0xda] == 0x33)
		score += 2;

	if ((buf[0xd5] & 0xf) < 4)
		score += 2;

	if (!(buf[0xfd] & 0x80))
		score -= 6;

	if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0)
667
		score -= 2; /* reduced after looking at a scan by Cowering */
668

TwinAphex51224's avatar
TwinAphex51224 committed
669
	if (calculated_size > 1024 * 1024 * 3)
670
671
672
673
674
675
676
677
678
679
680
681
682
683
		score += 4;

	if ((1 << (buf[0xd7] - 7)) > 48)
		score -= 1;

	if (!allASCII(&buf[0xb0], 6))
		score -= 1;

	if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1))
		score -= 1;

	return (score);
}

TwinAphex51224's avatar
TwinAphex51224 committed
684
static int ScoreLoROM (uint32 calculated_size, uint8 * rom, bool8 skip_header, int32 romoff)
685
{
686
687
688
689
690
	uint8	*buf;
	int score;

	score = 0;
	buf = rom + 0x7f00 + romoff + (skip_header ? 0x200 : 0);
691
692
693
694

	if (!(buf[0xd5] & 0x1))
		score += 3;

695
	/* Mode23 is SA-1 */
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
	if (buf[0xd5] == 0x23)
		score += 2;

	if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff)
	{
		score += 2;
		if (0 != (buf[0xde] + (buf[0xdf] << 8)))
			score++;
	}

	if (buf[0xda] == 0x33)
		score += 2;

	if ((buf[0xd5] & 0xf) < 4)
		score += 2;

	if (!(buf[0xfd] & 0x80))
		score -= 6;

	if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0)
716
		score -= 2; /* reduced per Cowering suggestion */
717

TwinAphex51224's avatar
TwinAphex51224 committed
718
	if (calculated_size <= 1024 * 1024 * 16)
719
720
721
722
723
724
725
726
727
728
729
730
731
732
		score += 2;

	if ((1 << (buf[0xd7] - 7)) > 48)
		score -= 1;

	if (!allASCII(&buf[0xb0], 6))
		score -= 1;

	if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1))
		score -= 1;

	return (score);
}

733
uint32 HeaderRemove (uint32 size, int32 * headerCount, uint8 *buf)
734
{
735
736
737
	uint32 calc_size;

	calc_size = (size / 0x2000) * 0x2000;
738

739
	if (size - calc_size == 512)
740
741
	{
		memmove(buf, buf + 512, calc_size);
742
		*(headerCount)++;
743
744
745
746
747
748
		size -= 512;
	}

	return (size);
}

TwinAphex51224's avatar
TwinAphex51224 committed
749
static uint32 FileLoader (uint8 *buffer, const char *filename, int32 maxsize)
750
{
751
752
753
	/* <- ROM size without header */
	/* ** Memory.HeaderCount */
	/* ** Memory.ROMFilename */
754

755
	bool8	more;
756
	int32	totalSize;
757
	uint32	size;
758
	char	fname[PATH_MAX + 1], drive[_MAX_DRIVE + 1], dir[PATH_MAX + 1], name[PATH_MAX + 1], exts[PATH_MAX + 1];
759
	char	*ext;
760
	int	len;
761
	uint8	*ptr;
762
	STREAM	fp;
763

764
765
	totalSize = 0;

766
767
	ext = &exts[0];

TwinAphex51224's avatar
TwinAphex51224 committed
768
	Memory.HeaderCount = 0;
769
770
771
772

	_splitpath(filename, drive, dir, name, exts);
	_makepath(fname, drive, dir, name, exts);

773
774
775
	fp = OPEN_STREAM(fname, "rb");
	if (!fp)
		return (0);
776

777
	strcpy(Memory.ROMFilename, fname);
TwinAphex51224's avatar
TwinAphex51224 committed
778

779
780
781
782
	len  = 0;
	size = 0;
	more = FALSE;
	ptr = buffer;
783

784
785
786
787
	do
	{
		size = READ_STREAM(ptr, maxsize + 0x200 - (ptr - buffer), fp);
		CLOSE_STREAM(fp);
788

789
790
791
		size = HeaderRemove(size, &Memory.HeaderCount, ptr);
		totalSize += size;
		ptr += size;
792

793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
		/* check for multi file roms*/
		if (ptr - buffer < maxsize + 0x200 &&
				(isdigit(ext[0]) && ext[1] == 0 && ext[0] < '9'))
		{
			more = TRUE;
			ext[0]++;
			_makepath(fname, drive, dir, name, exts);
		}
		else
			if (ptr - buffer < maxsize + 0x200 &&
					(((len = strlen(name)) == 7 || len == 8) &&
						strncasecmp(name, "sf", 2) == 0 &&
						isdigit(name[2]) && isdigit(name[3]) && isdigit(name[4]) && isdigit(name[5]) &&
						isalpha(name[len - 1])))
			{
				more = TRUE;
				name[len - 1]++;
				_makepath(fname, drive, dir, name, exts);
TwinAphex51224's avatar
TwinAphex51224 committed
811
			}
812
813
814
815
			else
				more = FALSE;

	}	while (more && (fp = OPEN_STREAM(fname, "rb")) != NULL);
816

TwinAphex51224's avatar
TwinAphex51224 committed
817
	if (Memory.HeaderCount == 0)
818
819
		S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found.");
	else
TwinAphex51224's avatar
TwinAphex51224 committed
820
821
822
823
		if (Memory.HeaderCount == 1)
			S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found ROM file header (and ignored it).");
		else
			S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found multiple ROM file headers (and ignored them).");
824
825
826
827

	return ((uint32) totalSize);
}

TwinAphex51224's avatar
TwinAphex51224 committed
828
static uint32 caCRC32 (uint8 *array, uint32 size, uint32 crc32)
829
{
830
	uint32 i;
831

832
	for ( i = 0; i < size; i++)
TwinAphex51224's avatar
TwinAphex51224 committed
833
		crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ array[i]) & 0xFF];
834

TwinAphex51224's avatar
TwinAphex51224 committed
835
836
	return (~crc32);
}
837

TwinAphex51224's avatar
TwinAphex51224 committed
838
bool8 LoadROM (const char *filename)
839
{
840
	int	hi_score, lo_score, retry_count;
841
842
843
	bool8 interleaved, tales;
	uint8 * RomHeader;
	int32 totalFileSize;
844

845
846
	retry_count = 0;

Themaister's avatar
Themaister committed
847
	if (!filename)
848
		return FALSE;
849

850
851
	memset(Memory.ROM, 0, MAX_ROM_SIZE);
	memset(&Multi, 0, sizeof(Multi));
852

TwinAphex51224's avatar
TwinAphex51224 committed
853
again:
TwinAphex51224's avatar
TwinAphex51224 committed
854
855
	Memory.CalculatedSize = 0;
	Memory.ExtendedFormat = NOPE;
856

TwinAphex51224's avatar
TwinAphex51224 committed
857
	totalFileSize = FileLoader(Memory.ROM, filename, MAX_ROM_SIZE);
TwinAphex51224's avatar
TwinAphex51224 committed
858
	if (!totalFileSize)
859
		return FALSE;
860

TwinAphex51224's avatar
TwinAphex51224 committed
861
862
	hi_score = ScoreHiROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
	lo_score = ScoreLoROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
863

TwinAphex51224's avatar
TwinAphex51224 committed
864
865
866
	if (Memory.HeaderCount == 0 && !Settings.ForceNoHeader &&
		((hi_score >  lo_score && ScoreHiROM(Memory.CalculatedSize, Memory.ROM, TRUE, 0) > hi_score) ||
		 (hi_score <= lo_score && ScoreLoROM(Memory.CalculatedSize, Memory.ROM, TRUE, 0) > lo_score)))
867
	{
TwinAphex51224's avatar
TwinAphex51224 committed
868
		memmove(Memory.ROM, Memory.ROM + 512, totalFileSize - 512);
TwinAphex51224's avatar
TwinAphex51224 committed
869
870
		totalFileSize -= 512;
		S9xMessage(S9X_INFO, S9X_HEADER_WARNING, "Try 'force no-header' option if the game doesn't work");
871
		/* modifying ROM, so we need to rescore */
TwinAphex51224's avatar
TwinAphex51224 committed
872
873
		hi_score = ScoreHiROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
		lo_score = ScoreLoROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
874
875
	}

TwinAphex51224's avatar
TwinAphex51224 committed
876
	Memory.CalculatedSize = (totalFileSize / 0x2000) * 0x2000;
877

TwinAphex51224's avatar
TwinAphex51224 committed
878
	if (Memory.CalculatedSize > 0x400000 &&
879
		(Memory.ROM[0x7fd5] + (Memory.ROM[0x7fd6] << 8)) != 0x4332 && /* exclude S-DD1 */
TwinAphex51224's avatar
TwinAphex51224 committed
880
		(Memory.ROM[0x7fd5] + (Memory.ROM[0x7fd6] << 8)) != 0x4532 &&
881
		(Memory.ROM[0xffd5] + (Memory.ROM[0xffd6] << 8)) != 0xF93a && /* exclude SPC7110 */
TwinAphex51224's avatar
TwinAphex51224 committed
882
883
		(Memory.ROM[0xffd5] + (Memory.ROM[0xffd6] << 8)) != 0xF53a)
		Memory.ExtendedFormat = YEAH;
884

885
	/* if both vectors are invalid, it's type 1 interleaved LoROM */
TwinAphex51224's avatar
TwinAphex51224 committed
886
887
888
	if (Memory.ExtendedFormat == NOPE &&
		((Memory.ROM[0x7ffc] + (Memory.ROM[0x7ffd] << 8)) < 0x8000) &&
		((Memory.ROM[0xfffc] + (Memory.ROM[0xfffd] << 8)) < 0x8000))
889
	{
TwinAphex51224's avatar
TwinAphex51224 committed
890
		if (!Settings.ForceInterleaved && !Settings.ForceNotInterleaved)
TwinAphex51224's avatar
TwinAphex51224 committed
891
			S9xDeinterleaveType1(totalFileSize, Memory.ROM);
892
893
	}

894
	/* CalculatedSize is now set, so rescore */
TwinAphex51224's avatar
TwinAphex51224 committed
895
896
	hi_score = ScoreHiROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
	lo_score = ScoreLoROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
897

898
	RomHeader = Memory.ROM;
899

TwinAphex51224's avatar
TwinAphex51224 committed
900
	if (Memory.ExtendedFormat != NOPE)
901
	{
TwinAphex51224's avatar
TwinAphex51224 committed
902
		int	swappedhirom, swappedlorom;
903

TwinAphex51224's avatar
TwinAphex51224 committed
904
905
		swappedhirom = ScoreHiROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0x400000);
		swappedlorom = ScoreLoROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0x400000);
906

907
		/* set swapped here */
TwinAphex51224's avatar
TwinAphex51224 committed
908
909
		if (max(swappedlorom, swappedhirom) >= max(lo_score, hi_score))
		{
TwinAphex51224's avatar
TwinAphex51224 committed
910
			Memory.ExtendedFormat = BIGFIRST;
TwinAphex51224's avatar
TwinAphex51224 committed
911
912
913
914
915
			hi_score = swappedhirom;
			lo_score = swappedlorom;
			RomHeader += 0x400000;
		}
		else
TwinAphex51224's avatar
TwinAphex51224 committed
916
			Memory.ExtendedFormat = SMALLFIRST;
TwinAphex51224's avatar
TwinAphex51224 committed
917
	}
918

919
920
	interleaved = FALSE;
	tales = FALSE;
921

922
	interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2 || Settings.ForceInterleaveGD24;
923

TwinAphex51224's avatar
TwinAphex51224 committed
924
925
	if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score))
	{
TwinAphex51224's avatar
TwinAphex51224 committed
926
927
		Memory.LoROM = TRUE;
		Memory.HiROM = FALSE;
928

929
		/* ignore map type byte if not 0x2x or 0x3x */
TwinAphex51224's avatar
TwinAphex51224 committed
930
931
932
933
934
935
936
		if ((RomHeader[0x7fd5] & 0xf0) == 0x20 || (RomHeader[0x7fd5] & 0xf0) == 0x30)
		{
			switch (RomHeader[0x7fd5] & 0xf)
			{
				case 1:
					interleaved = TRUE;
					break;
937

TwinAphex51224's avatar
TwinAphex51224 committed
938
939
940
941
942
943
944
945
				case 5:
					interleaved = TRUE;
					tales = TRUE;
					break;
			}
		}
	}
	else
946
	{
TwinAphex51224's avatar
TwinAphex51224 committed
947
948
		Memory.LoROM = FALSE;
		Memory.HiROM = TRUE;
949

TwinAphex51224's avatar
TwinAphex51224 committed
950
		if ((RomHeader[0xffd5] & 0xf0) == 0x20 || (RomHeader[0xffd5] & 0xf0) == 0x30)
951
		{
TwinAphex51224's avatar
TwinAphex51224 committed
952
953
954
955
956
957
958
			switch (RomHeader[0xffd5] & 0xf)
			{
				case 0:
				case 3:
					interleaved = TRUE;
					break;
			}
959
960
961
		}
	}

962
	/* these two games fail to be detected otherwise */
TwinAphex51224's avatar
TwinAphex51224 committed
963
964
	if (!Settings.ForceHiROM && !Settings.ForceLoROM)
	{
TwinAphex51224's avatar
TwinAphex51224 committed
965
966
		if (strncmp((char *) &Memory.ROM[0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0 ||
		   (strncmp((char *) &Memory.ROM[0xffc0], "BATMAN--REVENGE JOKER",  21) == 0))
TwinAphex51224's avatar
TwinAphex51224 committed
967
		{
TwinAphex51224's avatar
TwinAphex51224 committed
968
969
			Memory.LoROM = TRUE;
			Memory.HiROM = FALSE;
TwinAphex51224's avatar
TwinAphex51224 committed
970
971
972
973
			interleaved = FALSE;
			tales = FALSE;
		}
	}
974

TwinAphex51224's avatar
TwinAphex51224 committed
975
976
977
	if (!Settings.ForceNotInterleaved && interleaved)
	{
		S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "ROM image is in interleaved format - converting...");
978

TwinAphex51224's avatar
TwinAphex51224 committed
979
980
		if (tales)
		{
TwinAphex51224's avatar
TwinAphex51224 committed
981
			if (Memory.ExtendedFormat == BIGFIRST)
TwinAphex51224's avatar
TwinAphex51224 committed
982
			{
TwinAphex51224's avatar
TwinAphex51224 committed
983
984
				S9xDeinterleaveType1(0x400000, Memory.ROM);
				S9xDeinterleaveType1(Memory.CalculatedSize - 0x400000, Memory.ROM + 0x400000);
TwinAphex51224's avatar
TwinAphex51224 committed
985
986
987
			}
			else
			{
TwinAphex51224's avatar
TwinAphex51224 committed
988
989
				S9xDeinterleaveType1(Memory.CalculatedSize - 0x400000, Memory.ROM);
				S9xDeinterleaveType1(0x400000, Memory.ROM + Memory.CalculatedSize - 0x400000);
TwinAphex51224's avatar
TwinAphex51224 committed
990
			}
991

TwinAphex51224's avatar
TwinAphex51224 committed
992
993
			Memory.LoROM = FALSE;
			Memory.HiROM = TRUE;
TwinAphex51224's avatar
TwinAphex51224 committed
994
995
		}
		else
TwinAphex51224's avatar
TwinAphex51224 committed
996
		if (Settings.ForceInterleaveGD24 && Memory.CalculatedSize == 0x300000)
TwinAphex51224's avatar
TwinAphex51224 committed
997
		{
TwinAphex51224's avatar
TwinAphex51224 committed
998
999
1000
1001
			bool8	t = Memory.LoROM;
			Memory.LoROM = Memory.HiROM;
			Memory.HiROM = t;
			S9xDeinterleaveGD24(Memory.CalculatedSize, Memory.ROM);
TwinAphex51224's avatar
TwinAphex51224 committed
1002
1003
1004
		}
		else
		if (Settings.ForceInterleaved2)
TwinAphex51224's avatar
TwinAphex51224 committed
1005
			S9xDeinterleaveType2(Memory.CalculatedSize, Memory.ROM);
TwinAphex51224's avatar
TwinAphex51224 committed
1006
1007
		else
		{
TwinAphex51224's avatar
TwinAphex51224 committed
1008
1009
1010
1011
			bool8	t = Memory.LoROM;
			Memory.LoROM = Memory.HiROM;
			Memory.HiROM = t;
			S9xDeinterleaveType1(Memory.CalculatedSize, Memory.ROM);
TwinAphex51224's avatar
TwinAphex51224 committed
1012
		}
1013

TwinAphex51224's avatar
TwinAphex51224 committed
1014
1015
		hi_score = ScoreHiROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
		lo_score = ScoreLoROM(Memory.CalculatedSize, Memory.ROM, FALSE, 0);
1016

TwinAphex51224's avatar
TwinAphex51224 committed
1017
1018
		if ((Memory.HiROM && (lo_score >= hi_score || hi_score < 0)) ||
			(Memory.LoROM && (hi_score >  lo_score || lo_score < 0)))
TwinAphex51224's avatar
TwinAphex51224 committed
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
		{
			if (retry_count == 0)
			{
				S9xMessage(S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO, "ROM lied about its type! Trying again.");
				Settings.ForceNotInterleaved = TRUE;
				Settings.ForceInterleaved = FALSE;
				retry_count++;
				goto again;
			}
		}
    }
1030

TwinAphex51224's avatar
TwinAphex51224 committed
1031
	if (Memory.ExtendedFormat == SMALLFIRST)
TwinAphex51224's avatar
TwinAphex51224 committed
1032
		tales = TRUE;
1033

TwinAphex51224's avatar
TwinAphex51224 committed
1034
1035
	if (tales)
	{
TwinAphex51224's avatar
TwinAphex51224 committed
1036
		uint8	*tmp = (uint8 *) malloc(Memory.CalculatedSize - 0x400000);
TwinAphex51224's avatar
TwinAphex51224 committed
1037
1038
1039
		if (tmp)
		{
			S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "Fixing swapped ExHiROM...");
TwinAphex51224's avatar
TwinAphex51224 committed
1040
1041
1042
			memmove(tmp, Memory.ROM, Memory.CalculatedSize - 0x400000);
			memmove(Memory.ROM, Memory.ROM + Memory.CalculatedSize - 0x400000, 0x400000);
			memmove(Memory.ROM + 0x400000, tmp, Memory.CalculatedSize - 0x400000);
TwinAphex51224's avatar
TwinAphex51224 committed
1043
1044
			free(tmp);
		}
1045
1046
	}

1047
	memset(&SNESGameFixes, 0, sizeof(SNESGameFixes));
TwinAphex51224's avatar
TwinAphex51224 committed
1048
	SNESGameFixes.SRAMInitialValue = 0x60;
1049

TwinAphex51224's avatar
TwinAphex51224 committed
1050
	S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
1051

TwinAphex51224's avatar
TwinAphex51224 committed
1052
	InitROM();
1053

TwinAphex51224's avatar
TwinAphex51224 committed
1054
1055
	S9xInitCheatData();
	S9xApplyCheats();
1056

TwinAphex51224's avatar
TwinAphex51224 committed
1057
	S9xReset();
1058

TwinAphex51224's avatar
TwinAphex51224 committed
1059
1060
    return (TRUE);
}
1061

TwinAphex51224's avatar
TwinAphex51224 committed
1062
bool8 LoadMultiCart (const char *cartA, const char *cartB)
1063
{
1064
1065
1066
	bool8 r;

	r = TRUE;
1067

1068
1069
	memset(Memory.ROM, 0, MAX_ROM_SIZE);
	memset(&Multi, 0, sizeof(Multi));
1070

TwinAphex51224's avatar
TwinAphex51224 committed
1071
1072
	Memory.CalculatedSize = 0;
	Memory.ExtendedFormat = NOPE;
1073

TwinAphex51224's avatar
TwinAphex51224 committed
1074
	if (cartA && cartA[0])
TwinAphex51224's avatar
TwinAphex51224 committed
1075
		Multi.cartSizeA = FileLoader(Memory.ROM, cartA, MAX_ROM_SIZE);
1076

TwinAphex51224's avatar
TwinAphex51224 committed
1077
1078
1079
	if (Multi.cartSizeA == 0)
	{
		if (cartB && cartB[0])
TwinAphex51224's avatar
TwinAphex51224 committed
1080
			Multi.cartSizeB = FileLoader(Memory.ROM, cartB, MAX_ROM_SIZE);
TwinAphex51224's avatar
TwinAphex51224 committed
1081
	}
1082

TwinAphex51224's avatar
TwinAphex51224 committed
1083
	if (Multi.cartSizeA)
1084
	{
TwinAphex51224's avatar
TwinAphex51224 committed
1085
		if (is_SufamiTurbo_Cart(Memory.ROM, Multi.cartSizeA))
TwinAphex51224's avatar
TwinAphex51224 committed
1086
			Multi.cartType = 4;
1087
		else
TwinAphex51224's avatar
TwinAphex51224 committed
1088
		if (is_SameGame_BIOS(Memory.ROM, Multi.cartSizeA))
TwinAphex51224's avatar
TwinAphex51224 committed
1089
			Multi.cartType = 3;
1090
1091
	}
	else
TwinAphex51224's avatar
TwinAphex51224 committed
1092
	if (Multi.cartSizeB)
1093
	{
TwinAphex51224's avatar
TwinAphex51224 committed
1094
		if (is_SufamiTurbo_Cart(Memory.ROM, Multi.cartSizeB))
TwinAphex51224's avatar
TwinAphex51224 committed
1095
			Multi.cartType = 4;
1096
	}
TwinAphex51224's avatar
TwinAphex51224 committed
1097
	else
1098
		Multi.cartType = 4; /* assuming BIOS only */
1099

TwinAphex51224's avatar
TwinAphex51224 committed
1100
	switch (Multi.cartType)
1101
	{
TwinAphex51224's avatar
TwinAphex51224 committed
1102
1103
		case 4:
			r = LoadSufamiTurbo(cartA, cartB);
1104
1105
			break;

TwinAphex51224's avatar
TwinAphex51224 committed
1106
1107
		case 3:
			r = LoadSameGame(cartA, cartB);
1108
1109
			break;

TwinAphex51224's avatar
TwinAphex51224 committed
1110
1111
1112
		default:
			r = FALSE;
	}
1113

TwinAphex51224's avatar
TwinAphex51224 committed
1114
1115
	if (!r)
	{
1116
		memset(&Multi, 0, sizeof(Multi));
TwinAphex51224's avatar
TwinAphex51224 committed
1117
		return (FALSE);
1118
1119
	}

1120
	memset(&SNESGameFixes, 0, sizeof(SNESGameFixes));
TwinAphex51224's avatar
TwinAphex51224 committed
1121
	SNESGameFixes.SRAMInitialValue = 0x60;
1122

TwinAphex51224's avatar
TwinAphex51224 committed
1123
	S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
1124

TwinAphex51224's avatar
TwinAphex51224 committed
1125
	InitROM();
1126

TwinAphex51224's avatar
TwinAphex51224 committed
1127
1128
	S9xInitCheatData();
	S9xApplyCheats();
1129

TwinAphex51224's avatar
TwinAphex51224 committed
1130
	S9xReset();
1131

TwinAphex51224's avatar
TwinAphex51224 committed
1132
1133
	return (TRUE);
}