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