Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/genplus-gx/core/loadrom.c
2 views
1
/***************************************************************************************
2
* Genesis Plus
3
* ROM Loading Support
4
*
5
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
6
* Copyright (C) 2007-2013 Eke-Eke (Genesis Plus GX)
7
*
8
* Redistribution and use of this code or any derivative works are permitted
9
* provided that the following conditions are met:
10
*
11
* - Redistributions may not be sold, nor may they be used in a commercial
12
* product or activity.
13
*
14
* - Redistributions that are modified from the original source must include the
15
* complete source code, including the source code for all components used by a
16
* binary built from the modified sources. However, as a special exception, the
17
* source code distributed need not include anything that is normally distributed
18
* (in either source or binary form) with the major components (compiler, kernel,
19
* and so on) of the operating system on which the executable runs, unless that
20
* component itself accompanies the executable.
21
*
22
* - Redistributions must reproduce the above copyright notice, this list of
23
* conditions and the following disclaimer in the documentation and/or other
24
* materials provided with the distribution.
25
*
26
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36
* POSSIBILITY OF SUCH DAMAGE.
37
*
38
****************************************************************************************/
39
40
#include <ctype.h>
41
#include "shared.h"
42
43
/*** ROM Information ***/
44
#define ROMCONSOLE 256
45
#define ROMCOPYRIGHT 272
46
#define ROMDOMESTIC 288
47
#define ROMWORLD 336
48
#define ROMTYPE 384
49
#define ROMPRODUCT 386
50
#define ROMCHECKSUM 398
51
#define ROMIOSUPPORT 400
52
#define ROMROMSTART 416
53
#define ROMROMEND 420
54
#define ROMRAMINFO 424
55
#define ROMRAMSTART 436
56
#define ROMRAMEND 440
57
#define ROMMODEMINFO 444
58
#define ROMMEMO 456
59
#define ROMCOUNTRY 496
60
61
#define P3BUTTONS 1
62
#define P6BUTTONS 2
63
#define PKEYBOARD 4
64
#define PPRINTER 8
65
#define PBALL 16
66
#define PFLOPPY 32
67
#define PACTIVATOR 64
68
#define PTEAMPLAYER 128
69
#define PMSYSTEMPAD 256
70
#define PSERIAL 512
71
#define PTABLET 1024
72
#define PPADDLE 2048
73
#define PCDROM 4096
74
#define PMOUSE 8192
75
76
#define MAXCOMPANY 64
77
#define MAXPERIPHERALS 15
78
79
typedef struct
80
{
81
char companyid[6];
82
char company[26];
83
} COMPANYINFO;
84
85
typedef struct
86
{
87
char pID[2];
88
char pName[14];
89
} PERIPHERALINFO;
90
91
92
ROMINFO rominfo;
93
uint8 romtype;
94
95
uint8 rom_region;
96
97
/***************************************************************************
98
* Genesis ROM Manufacturers
99
*
100
* Based on the document provided at
101
* http://www.zophar.net/tech/files/Genesis_ROM_Format.txt
102
**************************************************************************/
103
static const COMPANYINFO companyinfo[MAXCOMPANY] =
104
{
105
{"ACLD", "Ballistic"},
106
{"RSI", "Razorsoft"},
107
{"SEGA", "SEGA"},
108
{"TREC", "Treco"},
109
{"VRGN", "Virgin Games"},
110
{"WSTN", "Westone"},
111
{"10", "Takara"},
112
{"11", "Taito or Accolade"},
113
{"12", "Capcom"},
114
{"13", "Data East"},
115
{"14", "Namco or Tengen"},
116
{"15", "Sunsoft"},
117
{"16", "Bandai"},
118
{"17", "Dempa"},
119
{"18", "Technosoft"},
120
{"19", "Technosoft"},
121
{"20", "Asmik"},
122
{"22", "Micronet"},
123
{"23", "Vic Tokai"},
124
{"24", "American Sammy"},
125
{"29", "Kyugo"},
126
{"32", "Wolfteam"},
127
{"33", "Kaneko"},
128
{"35", "Toaplan"},
129
{"36", "Tecmo"},
130
{"40", "Toaplan"},
131
{"42", "UFL Company Limited"},
132
{"43", "Human"},
133
{"45", "Game Arts"},
134
{"47", "Sage's Creation"},
135
{"48", "Tengen"},
136
{"49", "Renovation or Telenet"},
137
{"50", "Electronic Arts"},
138
{"56", "Razorsoft"},
139
{"58", "Mentrix"},
140
{"60", "Victor Musical Ind."},
141
{"69", "Arena"},
142
{"70", "Virgin"},
143
{"73", "Soft Vision"},
144
{"74", "Palsoft"},
145
{"76", "Koei"},
146
{"79", "U.S. Gold"},
147
{"81", "Acclaim/Flying Edge"},
148
{"83", "Gametek"},
149
{"86", "Absolute"},
150
{"87", "Mindscape"},
151
{"93", "Sony"},
152
{"95", "Konami"},
153
{"97", "Tradewest"},
154
{"100", "T*HQ Software"},
155
{"101", "Tecmagik"},
156
{"112", "Designer Software"},
157
{"113", "Psygnosis"},
158
{"119", "Accolade"},
159
{"120", "Code Masters"},
160
{"125", "Interplay"},
161
{"130", "Activision"},
162
{"132", "Shiny & Playmates"},
163
{"144", "Atlus"},
164
{"151", "Infogrames"},
165
{"161", "Fox Interactive"},
166
{"177", "Ubisoft"},
167
{"239", "Disney Interactive"},
168
{"---", "Unknown"}
169
};
170
171
/***************************************************************************
172
* Genesis Peripheral Information
173
*
174
* Based on the document provided at
175
* http://www.zophar.net/tech/files/Genesis_ROM_Format.txt
176
***************************************************************************/
177
static const PERIPHERALINFO peripheralinfo[MAXPERIPHERALS] =
178
{
179
{"J", "3B Joypad"},
180
{"6", "6B Joypad"},
181
{"K", "Keyboard"},
182
{"P", "Printer"},
183
{"B", "Control Ball"},
184
{"F", "Floppy Drive"},
185
{"L", "Activator"},
186
{"4", "Team Player"},
187
{"0", "MS Joypad"},
188
{"R", "RS232C Serial"},
189
{"T", "Tablet"},
190
{"V", "Paddle"},
191
{"C", "CD-ROM"},
192
{"M", "Mega Mouse"},
193
{"G", "Menacer"},
194
};
195
196
/***************************************************************************
197
*
198
* Compute ROM real checksum.
199
***************************************************************************/
200
static uint16 getchecksum(uint8 *rom, int length)
201
{
202
int i;
203
uint16 checksum = 0;
204
205
for (i = 0; i < length; i += 2)
206
{
207
checksum += ((rom[i] << 8) + rom[i + 1]);
208
}
209
210
return checksum;
211
}
212
213
214
/***************************************************************************
215
* deinterleave_block
216
*
217
* Convert interleaved (.smd) ROM files.
218
***************************************************************************/
219
static void deinterleave_block(uint8 * src)
220
{
221
int i;
222
uint8 block[0x4000];
223
memcpy (block, src, 0x4000);
224
for (i = 0; i < 0x2000; i += 1)
225
{
226
src[i * 2 + 0] = block[0x2000 + (i)];
227
src[i * 2 + 1] = block[0x0000 + (i)];
228
}
229
}
230
231
/***************************************************************************
232
*
233
* Pass a pointer to the ROM base address.
234
***************************************************************************/
235
void getrominfo(char *romheader)
236
{
237
/* Clear ROM info structure */
238
memset (&rominfo, 0, sizeof (ROMINFO));
239
240
/* Genesis ROM header support */
241
if (system_hw & SYSTEM_MD)
242
{
243
int i,j;
244
245
memcpy (&rominfo.consoletype, romheader + ROMCONSOLE, 16);
246
memcpy (&rominfo.copyright, romheader + ROMCOPYRIGHT, 16);
247
248
/* Domestic (japanese) name */
249
rominfo.domestic[0] = romheader[ROMDOMESTIC];
250
j = 1;
251
for (i=1; i<48; i++)
252
{
253
if ((rominfo.domestic[j-1] != 32) || (romheader[ROMDOMESTIC + i] != 32))
254
{
255
rominfo.domestic[j] = romheader[ROMDOMESTIC + i];
256
j++;
257
}
258
}
259
rominfo.domestic[j] = 0;
260
261
/* International name */
262
rominfo.international[0] = romheader[ROMWORLD];
263
j=1;
264
for (i=1; i<48; i++)
265
{
266
if ((rominfo.international[j-1] != 32) || (romheader[ROMWORLD + i] != 32))
267
{
268
rominfo.international[j] = romheader[ROMWORLD + i];
269
j++;
270
}
271
}
272
rominfo.international[j] = 0;
273
274
/* ROM informations */
275
memcpy (&rominfo.ROMType, romheader + ROMTYPE, 2);
276
memcpy (&rominfo.product, romheader + ROMPRODUCT, 12);
277
memcpy (&rominfo.checksum, romheader + ROMCHECKSUM, 2);
278
memcpy (&rominfo.romstart, romheader + ROMROMSTART, 4);
279
memcpy (&rominfo.romend, romheader + ROMROMEND, 4);
280
memcpy (&rominfo.country, romheader + ROMCOUNTRY, 16);
281
282
/* Checksums */
283
#ifdef LSB_FIRST
284
rominfo.checksum = (rominfo.checksum >> 8) | ((rominfo.checksum & 0xff) << 8);
285
#endif
286
rominfo.realchecksum = getchecksum(((uint8 *) cart.rom) + 0x200, cart.romsize - 0x200);
287
288
/* Supported peripherals */
289
rominfo.peripherals = 0;
290
for (i = 0; i < 14; i++)
291
for (j=0; j < 14; j++)
292
if (romheader[ROMIOSUPPORT+i] == peripheralinfo[j].pID[0])
293
rominfo.peripherals |= (1 << j);
294
}
295
else
296
{
297
uint16 offset = 0;
298
299
/* detect Master System ROM header */
300
if (!memcmp (&romheader[0x1ff0], "TMR SEGA", 8))
301
{
302
offset = 0x1ff0;
303
}
304
else if (!memcmp (&romheader[0x3ff0], "TMR SEGA", 8))
305
{
306
offset = 0x3ff0;
307
}
308
else if (!memcmp (&romheader[0x7ff0], "TMR SEGA", 8))
309
{
310
offset = 0x7ff0;
311
}
312
313
/* if found, get infos from header */
314
if (offset)
315
{
316
/* checksum */
317
rominfo.checksum = romheader[offset + 0x0a] | (romheader[offset + 0x0b] << 8);
318
319
/* product code & version */
320
sprintf(&rominfo.product[0], "%02d", romheader[offset + 0x0e] >> 4);
321
sprintf(&rominfo.product[2], "%02x", romheader[offset + 0x0d]);
322
sprintf(&rominfo.product[4], "%02x", romheader[offset + 0x0c]);
323
sprintf(&rominfo.product[6], "-%d", romheader[offset + 0x0e] & 0x0F);
324
325
/* region code */
326
switch (romheader[offset + 0x0f] >> 4)
327
{
328
case 3:
329
strcpy(rominfo.country,"SMS Japan");
330
break;
331
case 4:
332
strcpy(rominfo.country,"SMS Export");
333
break;
334
case 5:
335
strcpy(rominfo.country,"GG Japan");
336
break;
337
case 6:
338
strcpy(rominfo.country,"GG Export");
339
break;
340
case 7:
341
strcpy(rominfo.country,"GG International");
342
break;
343
default:
344
sprintf(rominfo.country,"Unknown (%d)", romheader[offset + 0x0f] >> 4);
345
break;
346
}
347
348
/* ROM size */
349
rominfo.romstart = 0;
350
switch (romheader[offset + 0x0f] & 0x0F)
351
{
352
case 0x00:
353
rominfo.romend = 0x3FFFF;
354
break;
355
case 0x01:
356
rominfo.romend = 0x7FFFF;
357
break;
358
case 0x02:
359
rominfo.romend = 0xFFFFF;
360
break;
361
case 0x0a:
362
rominfo.romend = 0x1FFF;
363
break;
364
case 0x0b:
365
rominfo.romend = 0x3FFF;
366
break;
367
case 0x0c:
368
rominfo.romend = 0x7FFF;
369
break;
370
case 0x0d:
371
rominfo.romend = 0xBFFF;
372
break;
373
case 0x0e:
374
rominfo.romend = 0xFFFF;
375
break;
376
case 0x0f:
377
rominfo.romend = 0x1FFFF;
378
break;
379
}
380
}
381
}
382
}
383
384
/***************************************************************************
385
* load_bios
386
*
387
* Load current system BIOS file.
388
*
389
* Return loaded size (-1 if already loaded)
390
*
391
***************************************************************************/
392
int load_bios(void)
393
{
394
int size = 0;
395
396
switch (system_hw)
397
{
398
case SYSTEM_MCD:
399
{
400
/* check if CD BOOTROM is already loaded */
401
if (!(system_bios & 0x10) || ((system_bios & 0x0c) != (region_code >> 4)))
402
{
403
/* load CD BOOTROM (fixed 128KB size) */
404
switch (region_code)
405
{
406
case REGION_USA:
407
size = load_archive(CD_BIOS_US, scd.bootrom, sizeof(scd.bootrom), 0);
408
break;
409
case REGION_EUROPE:
410
size = load_archive(CD_BIOS_EU, scd.bootrom, sizeof(scd.bootrom), 0);
411
break;
412
default:
413
size = load_archive(CD_BIOS_JP, scd.bootrom, sizeof(scd.bootrom), 0);
414
break;
415
}
416
417
/* CD BOOTROM loaded ? */
418
if (size > 0)
419
{
420
#ifdef LSB_FIRST
421
/* Byteswap ROM to optimize 16-bit access */
422
int i;
423
for (i = 0; i < size; i += 2)
424
{
425
uint8 temp = scd.bootrom[i];
426
scd.bootrom[i] = scd.bootrom[i+1];
427
scd.bootrom[i+1] = temp;
428
}
429
#endif
430
/* mark CD BIOS as being loaded */
431
system_bios = system_bios | 0x10;
432
433
/* loaded BIOS region */
434
system_bios = (system_bios & 0xf0) | (region_code >> 4);
435
}
436
437
return size;
438
}
439
440
return -1;
441
}
442
443
case SYSTEM_GG:
444
case SYSTEM_GGMS:
445
{
446
/* check if Game Gear BOOTROM is already loaded */
447
if (!(system_bios & SYSTEM_GG))
448
{
449
/* mark both Master System & Game Gear BOOTROM as unloaded */
450
system_bios &= ~(SYSTEM_SMS | SYSTEM_GG);
451
452
/* BOOTROM is stored above cartridge ROM area (max. 4MB) */
453
if (cart.romsize <= 0x400000)
454
{
455
/* load Game Gear BOOTROM file */
456
size = load_archive(GG_BIOS, cart.rom + 0x400000, 0x100000, 0);
457
458
if (size > 0)
459
{
460
/* mark Game Gear BOOTROM as loaded */
461
system_bios |= SYSTEM_GG;
462
}
463
}
464
465
return size;
466
}
467
468
return -1;
469
}
470
471
case SYSTEM_SMS:
472
case SYSTEM_SMS2:
473
{
474
/* check if Master System BOOTROM is already loaded */
475
if (!(system_bios & SYSTEM_SMS) || ((system_bios & 0x0c) != (region_code >> 4)))
476
{
477
/* mark both Master System & Game Gear BOOTROM as unloaded */
478
system_bios &= ~(SYSTEM_SMS | SYSTEM_GG);
479
480
/* BOOTROM is stored above cartridge ROM area (max. 4MB) */
481
if (cart.romsize <= 0x400000)
482
{
483
/* load Master System BOOTROM file */
484
switch (region_code)
485
{
486
case REGION_USA:
487
size = load_archive(MS_BIOS_US, cart.rom + 0x400000, 0x400000, 0);
488
break;
489
case REGION_EUROPE:
490
size = load_archive(MS_BIOS_EU, cart.rom + 0x400000, 0x400000, 0);
491
break;
492
default:
493
size = load_archive(MS_BIOS_JP, cart.rom + 0x400000, 0x400000, 0);
494
break;
495
}
496
497
if (size > 0)
498
{
499
/* mark Master System BOOTROM as loaded */
500
system_bios |= SYSTEM_SMS;
501
502
/* loaded BOOTROM region */
503
system_bios = (system_bios & 0xf0) | (region_code >> 4);
504
}
505
}
506
507
return size;
508
}
509
510
return -1;
511
}
512
513
default:
514
{
515
return 0;
516
}
517
}
518
}
519
520
/***************************************************************************
521
* load_rom
522
*
523
* Load a new ROM file.
524
*
525
* Return 0 on error, 1 on success
526
*
527
***************************************************************************/
528
int load_rom(const char *filename)
529
{
530
int i, size;
531
532
/* clear any existing patches */
533
ggenie_shutdown();
534
areplay_shutdown();
535
536
/* check previous loaded ROM size */
537
if (cart.romsize > 0x800000)
538
{
539
/* assume no CD is currently loaded */
540
cdd.loaded = 0;
541
}
542
543
/* auto-detect CD image files */
544
size = cdd_load("PRIMARY_CD", (char *)(cart.rom));
545
if (size < 0)
546
{
547
/* error opening file */
548
return 0;
549
}
550
551
if (size > 0)
552
{
553
/* CD image file loaded */
554
system_hw = SYSTEM_MCD;
555
}
556
else
557
{
558
/* load file into ROM buffer */
559
char extension[4];
560
size = load_archive(filename, cart.rom, sizeof(cart.rom), extension);
561
if (!size)
562
{
563
/* mark all BOOTROM as unloaded since they could have been overwritten */
564
system_bios &= ~(0x10 | SYSTEM_SMS | SYSTEM_GG);
565
return 0;
566
}
567
568
/* mark BOOTROM as unloaded if they have been overwritten by cartridge ROM */
569
if (size > 0x800000)
570
{
571
/* CD BIOS ROM are loaded at the start of CD area */
572
system_bios &= ~0x10;
573
}
574
else if (size > 0x400000)
575
{
576
/* Master System or Game Gear BIOS ROM are loaded within $400000-$4FFFFF area */
577
system_bios &= ~(SYSTEM_SMS | SYSTEM_GG);
578
}
579
580
/* convert lower case to upper case */
581
*(uint32 *)(extension) &= 0xdfdfdfdf;
582
583
/* auto-detect system hardware from ROM file extension */
584
if (!memcmp("SMS", &extension[0], 3))
585
{
586
/* Master System II hardware */
587
system_hw = SYSTEM_SMS2;
588
}
589
else if (!memcmp("GG", &extension[1], 2))
590
{
591
/* Game Gear hardware (GG mode) */
592
system_hw = SYSTEM_GG;
593
}
594
else if (!memcmp("SG", &extension[1], 2))
595
{
596
/* SG-1000 hardware */
597
system_hw = SYSTEM_SG;
598
}
599
else
600
{
601
/* Mega Drive hardware (Genesis mode) */
602
system_hw = SYSTEM_MD;
603
604
/* decode .MDX format */
605
if (!memcmp("MDX", &extension[0], 3))
606
{
607
for (i = 4; i < size - 1; i++)
608
{
609
cart.rom[i-4] = cart.rom[i] ^ 0x40;
610
}
611
size = size - 5;
612
}
613
614
/* auto-detect byte-swapped dumps */
615
if (!memcmp((char *)(cart.rom + 0x100),"ESAGM GE ARDVI E", 16) ||
616
!memcmp((char *)(cart.rom + 0x100),"ESAGG NESESI", 12))
617
{
618
for(i = 0; i < size; i += 2)
619
{
620
uint8 temp = cart.rom[i];
621
cart.rom[i] = cart.rom[i+1];
622
cart.rom[i+1] = temp;
623
}
624
}
625
}
626
627
/* auto-detect 512 byte extra header */
628
if (memcmp((char *)(cart.rom + 0x100), "SEGA", 4) && ((size / 512) & 1) && !(size % 512))
629
{
630
/* remove header */
631
size -= 512;
632
memcpy (cart.rom, cart.rom + 512, size);
633
634
/* assume interleaved Genesis ROM format (.smd) */
635
if (system_hw == SYSTEM_MD)
636
{
637
for (i = 0; i < (size / 0x4000); i++)
638
{
639
deinterleave_block (cart.rom + (i * 0x4000));
640
}
641
}
642
}
643
}
644
645
/* initialize ROM size */
646
cart.romsize = size;
647
648
/* get infos from ROM header */
649
getrominfo((char *)(cart.rom));
650
651
/* set console region */
652
get_region((char *)(cart.rom));
653
654
/* CD image file */
655
if (system_hw == SYSTEM_MCD)
656
{
657
/* load CD BOOT ROM */
658
if (!load_bios())
659
{
660
/* unmount CD image */
661
cdd_unload();
662
663
/* error loading CD BOOT ROM */
664
return (0);
665
}
666
667
/* boot from CD */
668
scd.cartridge.boot = 0x00;
669
}
670
671
#ifdef LSB_FIRST
672
/* 16-bit ROM specific */
673
else if (system_hw == SYSTEM_MD)
674
{
675
/* Byteswap ROM to optimize 16-bit access */
676
for (i = 0; i < cart.romsize; i += 2)
677
{
678
uint8 temp = cart.rom[i];
679
cart.rom[i] = cart.rom[i+1];
680
cart.rom[i+1] = temp;
681
}
682
}
683
#endif
684
685
/* Save auto-detected system hardware */
686
romtype = system_hw;
687
688
/* PICO ROM */
689
if (strstr(rominfo.consoletype, "SEGA PICO") != NULL)
690
{
691
/* PICO hardware */
692
system_hw = SYSTEM_PICO;
693
}
694
695
/* CD BOOTROM */
696
else if (strstr(rominfo.ROMType, "BR") != NULL)
697
{
698
/* enable CD hardware */
699
system_hw = SYSTEM_MCD;
700
701
/* boot from CD */
702
scd.cartridge.boot = 0x00;
703
704
/* copy ROM to BOOTROM area */
705
memcpy(scd.bootrom, cart.rom, sizeof(scd.bootrom));
706
707
/* mark CD BIOS as being loaded */
708
system_bios = system_bios | 0x10;
709
710
/* loaded CD BIOS region */
711
system_bios = (system_bios & 0xf0) | (region_code >> 4);
712
}
713
714
/* ROM cartridges with CD support */
715
else if ((strstr(rominfo.domestic,"FLUX") != NULL) ||
716
(strstr(rominfo.domestic,"WONDER LIBRARY") != NULL) ||
717
(strstr(rominfo.product,"T-5740") != NULL))
718
{
719
/* check if console hardware is set to AUTO */
720
if (config.system == 0x00)
721
{
722
/* auto-enable CD hardware */
723
system_hw = SYSTEM_MCD;
724
725
/* try to load CD BOOTROM */
726
if (load_bios())
727
{
728
/* boot from cartridge */
729
scd.cartridge.boot = 0x40;
730
731
/* automatically load associated .iso image */
732
// this will only possibly work if a CD and a ROM are provided at the same time, which the frontend
733
// has no provision for at the moment
734
if (cdd_load("SECONDARY_CD", (char *)cdc.ram) <= 0)
735
// no load, so disable CD hardware
736
system_hw = SYSTEM_MD;
737
}
738
else
739
{
740
/* if not found, disable CD hardware */
741
system_hw = SYSTEM_MD;
742
}
743
}
744
}
745
746
/* Force system hardware if requested */
747
if (config.system == SYSTEM_MD)
748
{
749
if (!(system_hw & SYSTEM_MD))
750
{
751
/* Mega Drive in MS compatibility mode */
752
system_hw = SYSTEM_PBC;
753
}
754
}
755
else if (config.system == SYSTEM_GG)
756
{
757
if (system_hw != SYSTEM_GG)
758
{
759
/* Game Gear in MS compatibility mode */
760
system_hw = SYSTEM_GGMS;
761
}
762
}
763
else if (config.system)
764
{
765
system_hw = config.system;
766
}
767
768
/* restore previous input settings */
769
if (old_system[0] != -1)
770
{
771
input.system[0] = old_system[0];
772
}
773
if (old_system[1] != -1)
774
{
775
input.system[1] = old_system[1];
776
}
777
778
/* default gun settings */
779
input.x_offset = (input.system[1] == SYSTEM_MENACER) ? 64 : 0;
780
input.y_offset = 0;
781
782
/* autodetect gun support */
783
if (strstr(rominfo.international,"MENACER") != NULL)
784
{
785
/* save current setting */
786
if (old_system[0] == -1)
787
{
788
old_system[0] = input.system[0];
789
}
790
if (old_system[1] == -1)
791
{
792
old_system[1] = input.system[1];
793
}
794
795
/* force MENACER configuration */
796
input.system[0] = SYSTEM_MD_GAMEPAD;
797
input.system[1] = SYSTEM_MENACER;
798
input.x_offset = 82;
799
input.y_offset = 0;
800
}
801
else if (strstr(rominfo.international,"T2 ; THE ARCADE GAME") != NULL)
802
{
803
/* save current setting */
804
if (old_system[0] == -1)
805
{
806
old_system[0] = input.system[0];
807
}
808
if (old_system[1] == -1)
809
{
810
old_system[1] = input.system[1];
811
}
812
813
/* force MENACER configuration */
814
input.system[0] = SYSTEM_MD_GAMEPAD;
815
input.system[1] = SYSTEM_MENACER;
816
input.x_offset = 133;
817
input.y_offset = -8;
818
}
819
else if (strstr(rominfo.international,"BODY COUNT") != NULL)
820
{
821
/* save current setting */
822
if (old_system[0] == -1)
823
{
824
old_system[0] = input.system[0];
825
}
826
if (old_system[1] == -1)
827
{
828
old_system[1] = input.system[1];
829
}
830
831
/* force MENACER configuration */
832
input.system[0] = SYSTEM_MD_GAMEPAD;
833
input.system[1] = SYSTEM_MENACER;
834
input.x_offset = 68;
835
input.y_offset = -24;
836
}
837
else if (strstr(rominfo.international,"CORPSE KILLER") != NULL)
838
{
839
/* save current setting */
840
if (old_system[0] == -1)
841
{
842
old_system[0] = input.system[0];
843
}
844
if (old_system[1] == -1)
845
{
846
old_system[1] = input.system[1];
847
}
848
849
/* force MENACER configuration */
850
input.system[0] = SYSTEM_MD_GAMEPAD;
851
input.system[1] = SYSTEM_MENACER;
852
input.x_offset = 64;
853
input.y_offset = -8;
854
}
855
else if (strstr(rominfo.international,"CRIME PATROL") != NULL)
856
{
857
/* save current setting */
858
if (old_system[0] == -1)
859
{
860
old_system[0] = input.system[0];
861
}
862
if (old_system[1] == -1)
863
{
864
old_system[1] = input.system[1];
865
}
866
867
/* force MENACER configuration */
868
input.system[0] = SYSTEM_MD_GAMEPAD;
869
input.system[1] = SYSTEM_MENACER;
870
input.x_offset = 61;
871
input.y_offset = 0;
872
}
873
else if (strstr(rominfo.international,"MAD DOG II THE LOST GOLD") != NULL)
874
{
875
/* save current setting */
876
if (old_system[0] == -1)
877
{
878
old_system[0] = input.system[0];
879
}
880
if (old_system[1] == -1)
881
{
882
old_system[1] = input.system[1];
883
}
884
885
/* force MENACER configuration */
886
input.system[0] = SYSTEM_MD_GAMEPAD;
887
input.system[1] = SYSTEM_MENACER;
888
input.x_offset = 70;
889
input.y_offset = 18;
890
}
891
else if (strstr(rominfo.international,"MAD DOG MCCREE") != NULL)
892
{
893
/* save current setting */
894
if (old_system[0] == -1)
895
{
896
old_system[0] = input.system[0];
897
}
898
if (old_system[1] == -1)
899
{
900
old_system[1] = input.system[1];
901
}
902
903
/* force MENACER configuration */
904
input.system[0] = SYSTEM_MD_GAMEPAD;
905
input.system[1] = SYSTEM_MENACER;
906
input.x_offset = 49;
907
input.y_offset = 0;
908
}
909
else if (strstr(rominfo.international,"WHO SHOT JOHNNY ROCK?") != NULL)
910
{
911
/* save current setting */
912
if (old_system[0] == -1)
913
{
914
old_system[0] = input.system[0];
915
}
916
if (old_system[1] == -1)
917
{
918
old_system[1] = input.system[1];
919
}
920
921
/* force MENACER configuration */
922
input.system[0] = SYSTEM_MD_GAMEPAD;
923
input.system[1] = SYSTEM_MENACER;
924
input.x_offset = 60;
925
input.y_offset = 30;
926
}
927
else if ((strstr(rominfo.international,"LETHAL ENFORCERS") != NULL) ||
928
(strstr(rominfo.international,"SNATCHER") != NULL))
929
{
930
/* save current setting */
931
if (old_system[0] == -1)
932
{
933
old_system[0] = input.system[0];
934
}
935
if (old_system[1] == -1)
936
{
937
old_system[1] = input.system[1];
938
}
939
940
/* force JUSTIFIER configuration */
941
input.system[0] = SYSTEM_MD_GAMEPAD;
942
input.system[1] = SYSTEM_JUSTIFIER;
943
input.x_offset = (strstr(rominfo.international,"GUN FIGHTERS") != NULL) ? 24 : 0;
944
input.y_offset = 0;
945
}
946
947
return(1);
948
}
949
950
/****************************************************************************
951
* get_region
952
*
953
* Set console region from ROM header passed as parameter or
954
* from previous auto-detection (if NULL)
955
*
956
****************************************************************************/
957
void get_region(char *romheader)
958
{
959
/* region auto-detection ? */
960
if (romheader)
961
{
962
/* Mega CD image */
963
if (system_hw == SYSTEM_MCD)
964
{
965
/* security code */
966
switch (romheader[0x20b])
967
{
968
case 0x7a:
969
region_code = REGION_USA;
970
break;
971
972
case 0x64:
973
region_code = REGION_EUROPE;
974
break;
975
976
default:
977
region_code = REGION_JAPAN_NTSC;
978
break;
979
}
980
}
981
982
/* 16-bit cartridge */
983
else if (system_hw & SYSTEM_MD)
984
{
985
/* country codes used to differentiate region */
986
/* 0001 = japan ntsc (1) */
987
/* 0010 = japan pal (2) -> does not exist ? */
988
/* 0100 = usa (4) */
989
/* 1000 = europe (8) */
990
int country = 0;
991
992
/* from Gens */
993
if (!memcmp(rominfo.country, "eur", 3)) country |= 8;
994
else if (!memcmp(rominfo.country, "EUR", 3)) country |= 8;
995
else if (!memcmp(rominfo.country, "jap", 3)) country |= 1;
996
else if (!memcmp(rominfo.country, "JAP", 3)) country |= 1;
997
else if (!memcmp(rominfo.country, "usa", 3)) country |= 4;
998
else if (!memcmp(rominfo.country, "USA", 3)) country |= 4;
999
else
1000
{
1001
int i;
1002
char c;
1003
1004
/* look for each characters */
1005
for(i = 0; i < 4; i++)
1006
{
1007
c = toupper((int)rominfo.country[i]);
1008
1009
if (c == 'U') country |= 4;
1010
else if (c == 'J') country |= 1;
1011
else if (c == 'E') country |= 8;
1012
else if (c == 'K') country |= 1;
1013
else if (c < 16) country |= c;
1014
else if ((c >= '0') && (c <= '9')) country |= c - '0';
1015
else if ((c >= 'A') && (c <= 'F')) country |= c - 'A' + 10;
1016
}
1017
}
1018
1019
/* set default console region (USA > JAPAN > EUROPE) */
1020
if (country & 4) region_code = REGION_USA;
1021
else if (country & 1) region_code = REGION_JAPAN_NTSC;
1022
else if (country & 8) region_code = REGION_EUROPE;
1023
else if (country & 2) region_code = REGION_JAPAN_PAL;
1024
else region_code = REGION_USA;
1025
1026
/* some games need specific region settings but have wrong header*/
1027
if (((strstr(rominfo.product,"T-45033") != NULL) && (rominfo.checksum == 0x0F81)) || /* Alisia Dragon (Europe) */
1028
(strstr(rominfo.product,"T-69046-50") != NULL) || /* Back to the Future III (Europe) */
1029
(strstr(rominfo.product,"T-120106-00") != NULL) || /* Brian Lara Cricket (Europe) */
1030
(strstr(rominfo.product,"T-70096 -00") != NULL)) /* Muhammad Ali Heavyweight Boxing (Europe) */
1031
{
1032
/* need PAL settings */
1033
region_code = REGION_EUROPE;
1034
}
1035
else if ((rominfo.realchecksum == 0x532e) && (strstr(rominfo.product,"1011-00") != NULL))
1036
{
1037
/* On Dal Jang Goon (Korea) needs JAPAN region code */
1038
region_code = REGION_JAPAN_NTSC;
1039
}
1040
}
1041
1042
/* 8-bit cartridge */
1043
else
1044
{
1045
region_code = sms_cart_region_detect();
1046
}
1047
1048
/* save auto-detected region */
1049
rom_region = region_code;
1050
}
1051
else
1052
{
1053
/* restore auto-detected region */
1054
region_code = rom_region;
1055
}
1056
1057
/* force console region if requested */
1058
if (config.region_detect == 1) region_code = REGION_USA;
1059
else if (config.region_detect == 2) region_code = REGION_EUROPE;
1060
else if (config.region_detect == 3) region_code = REGION_JAPAN_NTSC;
1061
else if (config.region_detect == 4) region_code = REGION_JAPAN_PAL;
1062
1063
/* autodetect PAL/NTSC timings */
1064
vdp_pal = (region_code >> 6) & 0x01;
1065
1066
/* autodetect PAL/NTSC master clock */
1067
system_clock = vdp_pal ? MCLOCK_PAL : MCLOCK_NTSC;
1068
1069
/* force PAL/NTSC timings if requested */
1070
if (config.vdp_mode == 1) vdp_pal = 0;
1071
else if (config.vdp_mode == 2) vdp_pal = 1;
1072
1073
/* force PAL/NTSC master clock if requested */
1074
if (config.master_clock == 1) system_clock = MCLOCK_NTSC;
1075
else if (config.master_clock == 2) system_clock = MCLOCK_PAL;
1076
}
1077
1078
1079
/****************************************************************************
1080
* get_company (Softdev - 2006)
1081
*
1082
* Try to determine which company made this rom
1083
*
1084
* Ok, for some reason there's no standard for this.
1085
* It seems that there can be pretty much anything you like following the
1086
* copyright (C) symbol!
1087
****************************************************************************/
1088
char *get_company(void)
1089
{
1090
char *s;
1091
int i;
1092
char company[10];
1093
1094
for (i = 3; i < 8; i++)
1095
{
1096
company[i - 3] = rominfo.copyright[i];
1097
}
1098
company[5] = 0;
1099
1100
/** OK, first look for a hyphen
1101
* Capcom use T-12 for example
1102
*/
1103
s = strstr (company, "-");
1104
if (s != NULL)
1105
{
1106
s++;
1107
strcpy (company, s);
1108
}
1109
1110
/** Strip any trailing spaces **/
1111
for (i = strlen (company) - 1; i >= 0; i--)
1112
if (company[i] == 32)
1113
company[i] = 0;
1114
1115
if (strlen (company) == 0)
1116
return (char *)companyinfo[MAXCOMPANY - 1].company;
1117
1118
for (i = 0; i < MAXCOMPANY - 1; i++)
1119
{
1120
if (!(strncmp (company, companyinfo[i].companyid, strlen (company))))
1121
return (char *)companyinfo[i].company;
1122
}
1123
1124
return (char *)companyinfo[MAXCOMPANY - 1].company;
1125
}
1126
1127
/****************************************************************************
1128
* get_peripheral (Softdev - 2006)
1129
*
1130
* Return peripheral name based on header code
1131
*
1132
****************************************************************************/
1133
char *get_peripheral(int index)
1134
{
1135
if (index < MAXPERIPHERALS)
1136
return (char *)peripheralinfo[index].pName;
1137
return (char *)companyinfo[MAXCOMPANY - 1].company;
1138
}
1139
1140
1141