1
/***************************************************************************
5
Validity checks on internal data structures.
7
Copyright Nicola Salmoria and the MAME Team.
8
Visit http://mamedev.org for licensing and usage restrictions.
10
***************************************************************************/
19
/***************************************************************************
21
***************************************************************************/
23
#define REPORT_TIMES (0)
27
/***************************************************************************
28
COMPILE-TIME VALIDATION
29
***************************************************************************/
31
/* if the following lines error during compile, your PTR64 switch is set incorrectly in the makefile */
33
UINT8 your_ptr64_flag_is_wrong[(int)(sizeof(void *) - 7)];
35
UINT8 your_ptr64_flag_is_wrong[(int)(5 - sizeof(void *))];
40
/***************************************************************************
42
***************************************************************************/
44
typedef tagmap_t<const game_driver *> game_driver_map;
46
typedef tagmap_t<FPTR> int_map;
62
region_entry entries[256];
67
/***************************************************************************
69
***************************************************************************/
71
/*-------------------------------------------------
72
input_port_string_from_index - return an
73
indexed string from the input port system
74
-------------------------------------------------*/
76
INLINE const char *input_port_string_from_index(UINT32 index)
78
return input_port_string_from_token((const char *)(FPTR)index);
82
/*-------------------------------------------------
83
validate_tag - ensure that the given tag
84
meets the general requirements
85
-------------------------------------------------*/
87
bool validate_tag(const game_driver &driver, const char *object, const char *tag)
89
const char *validchars = "abcdefghijklmnopqrstuvwxyz0123456789_.:";
90
const char *begin = strrchr(tag, ':');
94
/* some common names that are now deprecated */
95
if (strcmp(tag, "main") == 0 ||
96
strcmp(tag, "audio") == 0 ||
97
strcmp(tag, "sound") == 0 ||
98
strcmp(tag, "left") == 0 ||
99
strcmp(tag, "right") == 0)
101
mame_printf_error("%s: %s has invalid generic tag '%s'\n", driver.source_file, driver.name, tag);
105
for (p = tag; *p != 0; p++)
107
if (*p != tolower((UINT8)*p))
109
mame_printf_error("%s: %s has %s with tag '%s' containing upper-case characters\n", driver.source_file, driver.name, object, tag);
115
mame_printf_error("%s: %s has %s with tag '%s' containing spaces\n", driver.source_file, driver.name, object, tag);
119
if (strchr(validchars, *p) == NULL)
121
mame_printf_error("%s: %s has %s with tag '%s' containing invalid character '%c'\n", driver.source_file, driver.name, object, tag, *p);
132
if (strlen(begin) == 0)
134
mame_printf_error("%s: %s has %s with 0-length tag\n", driver.source_file, driver.name, object);
137
if (strlen(begin) < MIN_TAG_LENGTH)
139
mame_printf_error("%s: %s has %s with tag '%s' < %d characters\n", driver.source_file, driver.name, object, tag, MIN_TAG_LENGTH);
142
if (strlen(begin) > MAX_TAG_LENGTH)
144
mame_printf_error("%s: %s has %s with tag '%s' > %d characters\n", driver.source_file, driver.name, object, tag, MAX_TAG_LENGTH);
153
/***************************************************************************
155
***************************************************************************/
157
/*-------------------------------------------------
158
validate_inlines - validate inline function
160
-------------------------------------------------*/
162
static bool validate_inlines(void)
165
volatile UINT64 testu64a = rand() ^ (rand() << 15) ^ ((UINT64)rand() << 30) ^ ((UINT64)rand() << 45);
166
volatile INT64 testi64a = rand() ^ (rand() << 15) ^ ((INT64)rand() << 30) ^ ((INT64)rand() << 45);
168
volatile INT64 testi64b = rand() ^ (rand() << 15) ^ ((INT64)rand() << 30) ^ ((INT64)rand() << 45);
170
volatile UINT32 testu32a = rand() ^ (rand() << 15);
171
volatile UINT32 testu32b = rand() ^ (rand() << 15);
172
volatile INT32 testi32a = rand() ^ (rand() << 15);
173
volatile INT32 testi32b = rand() ^ (rand() << 15);
174
INT32 resulti32, expectedi32;
175
UINT32 resultu32, expectedu32;
176
INT64 resulti64, expectedi64;
177
UINT64 resultu64, expectedu64;
178
INT32 remainder, expremainder;
179
UINT32 uremainder, expuremainder, bigu32 = 0xffffffff;
182
/* use only non-zero, positive numbers */
183
if (testu64a == 0) testu64a++;
184
if (testi64a == 0) testi64a++;
185
else if (testi64a < 0) testi64a = -testi64a;
187
if (testi64b == 0) testi64b++;
188
else if (testi64b < 0) testi64b = -testi64b;
190
if (testu32a == 0) testu32a++;
191
if (testu32b == 0) testu32b++;
192
if (testi32a == 0) testi32a++;
193
else if (testi32a < 0) testi32a = -testi32a;
194
if (testi32b == 0) testi32b++;
195
else if (testi32b < 0) testi32b = -testi32b;
197
resulti64 = mul_32x32(testi32a, testi32b);
198
expectedi64 = (INT64)testi32a * (INT64)testi32b;
199
if (resulti64 != expectedi64)
200
{ mame_printf_error("Error testing mul_32x32 (%08X x %08X) = %08X%08X (expected %08X%08X)\n", testi32a, testi32b, (UINT32)(resulti64 >> 32), (UINT32)resulti64, (UINT32)(expectedi64 >> 32), (UINT32)expectedi64); error = true; }
202
resultu64 = mulu_32x32(testu32a, testu32b);
203
expectedu64 = (UINT64)testu32a * (UINT64)testu32b;
204
if (resultu64 != expectedu64)
205
{ mame_printf_error("Error testing mulu_32x32 (%08X x %08X) = %08X%08X (expected %08X%08X)\n", testu32a, testu32b, (UINT32)(resultu64 >> 32), (UINT32)resultu64, (UINT32)(expectedu64 >> 32), (UINT32)expectedu64); error = true; }
207
resulti32 = mul_32x32_hi(testi32a, testi32b);
208
expectedi32 = ((INT64)testi32a * (INT64)testi32b) >> 32;
209
if (resulti32 != expectedi32)
210
{ mame_printf_error("Error testing mul_32x32_hi (%08X x %08X) = %08X (expected %08X)\n", testi32a, testi32b, resulti32, expectedi32); error = true; }
212
resultu32 = mulu_32x32_hi(testu32a, testu32b);
213
expectedu32 = ((INT64)testu32a * (INT64)testu32b) >> 32;
214
if (resultu32 != expectedu32)
215
{ mame_printf_error("Error testing mulu_32x32_hi (%08X x %08X) = %08X (expected %08X)\n", testu32a, testu32b, resultu32, expectedu32); error = true; }
217
resulti32 = mul_32x32_shift(testi32a, testi32b, 7);
218
expectedi32 = ((INT64)testi32a * (INT64)testi32b) >> 7;
219
if (resulti32 != expectedi32)
220
{ mame_printf_error("Error testing mul_32x32_shift (%08X x %08X) >> 7 = %08X (expected %08X)\n", testi32a, testi32b, resulti32, expectedi32); error = true; }
222
resultu32 = mulu_32x32_shift(testu32a, testu32b, 7);
223
expectedu32 = ((INT64)testu32a * (INT64)testu32b) >> 7;
224
if (resultu32 != expectedu32)
225
{ mame_printf_error("Error testing mulu_32x32_shift (%08X x %08X) >> 7 = %08X (expected %08X)\n", testu32a, testu32b, resultu32, expectedu32); error = true; }
227
while ((INT64)testi32a * (INT64)0x7fffffff < testi64a)
229
while ((UINT64)testu32a * (UINT64)bigu32 < testu64a)
232
resulti32 = div_64x32(testi64a, testi32a);
233
expectedi32 = testi64a / (INT64)testi32a;
234
if (resulti32 != expectedi32)
235
{ mame_printf_error("Error testing div_64x32 (%08X%08X / %08X) = %08X (expected %08X)\n", (UINT32)(testi64a >> 32), (UINT32)testi64a, testi32a, resulti32, expectedi32); error = true; }
237
resultu32 = divu_64x32(testu64a, testu32a);
238
expectedu32 = testu64a / (UINT64)testu32a;
239
if (resultu32 != expectedu32)
240
{ mame_printf_error("Error testing divu_64x32 (%08X%08X / %08X) = %08X (expected %08X)\n", (UINT32)(testu64a >> 32), (UINT32)testu64a, testu32a, resultu32, expectedu32); error = true; }
242
resulti32 = div_64x32_rem(testi64a, testi32a, &remainder);
243
expectedi32 = testi64a / (INT64)testi32a;
244
expremainder = testi64a % (INT64)testi32a;
245
if (resulti32 != expectedi32 || remainder != expremainder)
246
{ mame_printf_error("Error testing div_64x32_rem (%08X%08X / %08X) = %08X,%08X (expected %08X,%08X)\n", (UINT32)(testi64a >> 32), (UINT32)testi64a, testi32a, resulti32, remainder, expectedi32, expremainder); error = true; }
248
resultu32 = divu_64x32_rem(testu64a, testu32a, &uremainder);
249
expectedu32 = testu64a / (UINT64)testu32a;
250
expuremainder = testu64a % (UINT64)testu32a;
251
if (resultu32 != expectedu32 || uremainder != expuremainder)
252
{ mame_printf_error("Error testing divu_64x32_rem (%08X%08X / %08X) = %08X,%08X (expected %08X,%08X)\n", (UINT32)(testu64a >> 32), (UINT32)testu64a, testu32a, resultu32, uremainder, expectedu32, expuremainder); error = true; }
254
resulti32 = mod_64x32(testi64a, testi32a);
255
expectedi32 = testi64a % (INT64)testi32a;
256
if (resulti32 != expectedi32)
257
{ mame_printf_error("Error testing mod_64x32 (%08X%08X / %08X) = %08X (expected %08X)\n", (UINT32)(testi64a >> 32), (UINT32)testi64a, testi32a, resulti32, expectedi32); error = true; }
259
resultu32 = modu_64x32(testu64a, testu32a);
260
expectedu32 = testu64a % (UINT64)testu32a;
261
if (resultu32 != expectedu32)
262
{ mame_printf_error("Error testing modu_64x32 (%08X%08X / %08X) = %08X (expected %08X)\n", (UINT32)(testu64a >> 32), (UINT32)testu64a, testu32a, resultu32, expectedu32); error = true; }
264
while ((INT64)testi32a * (INT64)0x7fffffff < ((INT32)testi64a << 3))
266
while ((UINT64)testu32a * (UINT64)0xffffffff < ((UINT32)testu64a << 3))
269
resulti32 = div_32x32_shift((INT32)testi64a, testi32a, 3);
270
expectedi32 = ((INT64)(INT32)testi64a << 3) / (INT64)testi32a;
271
if (resulti32 != expectedi32)
272
{ mame_printf_error("Error testing div_32x32_shift (%08X << 3) / %08X = %08X (expected %08X)\n", (INT32)testi64a, testi32a, resulti32, expectedi32); error = true; }
274
resultu32 = divu_32x32_shift((UINT32)testu64a, testu32a, 3);
275
expectedu32 = ((UINT64)(UINT32)testu64a << 3) / (UINT64)testu32a;
276
if (resultu32 != expectedu32)
277
{ mame_printf_error("Error testing divu_32x32_shift (%08X << 3) / %08X = %08X (expected %08X)\n", (UINT32)testu64a, testu32a, resultu32, expectedu32); error = true; }
279
if (fabs(recip_approx(100.0) - 0.01) > 0.0001)
280
{ mame_printf_error("Error testing recip_approx\n"); error = true; }
282
testi32a = (testi32a & 0x0000ffff) | 0x400000;
283
if (count_leading_zeros(testi32a) != 9)
284
{ mame_printf_error("Error testing count_leading_zeros\n"); error = true; }
285
testi32a = (testi32a | 0xffff0000) & ~0x400000;
286
if (count_leading_ones(testi32a) != 9)
287
{ mame_printf_error("Error testing count_leading_ones\n"); error = true; }
290
if (compare_exchange32(&testi32a, testi32b, 1000) != testi32b || testi32a != 1000)
291
{ mame_printf_error("Error testing compare_exchange32\n"); error = true; }
294
if (compare_exchange64(&testi64a, testi64b, 1000) != testi64b || testi64a != 1000)
295
{ mame_printf_error("Error testing compare_exchange64\n"); error = true; }
297
if (atomic_exchange32(&testi32a, testi32b) != 1000)
298
{ mame_printf_error("Error testing atomic_exchange32\n"); error = true; }
299
if (atomic_add32(&testi32a, 45) != testi32b + 45)
300
{ mame_printf_error("Error testing atomic_add32\n"); error = true; }
301
if (atomic_increment32(&testi32a) != testi32b + 46)
302
{ mame_printf_error("Error testing atomic_increment32\n"); error = true; }
303
if (atomic_decrement32(&testi32a) != testi32b + 45)
304
{ mame_printf_error("Error testing atomic_decrement32\n"); error = true; }
310
/*-------------------------------------------------
311
validate_driver - validate basic driver
313
-------------------------------------------------*/
315
static bool validate_driver(driver_enumerator &drivlist, game_driver_map &names, game_driver_map &descriptions)
317
const game_driver &driver = drivlist.driver();
318
const machine_config &config = drivlist.config();
319
const char *compatible_with;
320
bool error = FALSE, is_clone;
323
enum { NAME_LEN_PARENT = 8, NAME_LEN_CLONE = 16 };
325
/* check for duplicate names */
326
if (names.add(driver.name, &driver, FALSE) == TMERR_DUPLICATE)
328
const game_driver *match = names.find(driver.name);
329
mame_printf_error("%s: %s is a duplicate name (%s, %s)\n", driver.source_file, driver.name, match->source_file, match->name);
333
/* check for duplicate descriptions */
334
if (descriptions.add(driver.description, &driver, FALSE) == TMERR_DUPLICATE)
336
const game_driver *match = descriptions.find(driver.description);
337
mame_printf_error("%s: %s is a duplicate description (%s, %s)\n", driver.source_file, driver.description, match->source_file, match->description);
341
/* determine the clone */
342
is_clone = (strcmp(driver.parent, "0") != 0);
343
int clone_of = drivlist.clone(driver);
344
if (clone_of != -1 && (drivlist.driver(clone_of).flags & GAME_IS_BIOS_ROOT))
347
/* if we have at least 100 drivers, validate the clone */
348
/* (100 is arbitrary, but tries to avoid tiny.mak dependencies) */
349
if (driver_list::total() > 100 && clone_of == -1 && is_clone)
351
mame_printf_error("%s: %s is a non-existant clone\n", driver.source_file, driver.parent);
355
/* look for recursive cloning */
356
if (clone_of != -1 && &drivlist.driver(clone_of) == &driver)
358
mame_printf_error("%s: %s is set as a clone of itself\n", driver.source_file, driver.name);
362
/* look for clones that are too deep */
363
if (clone_of != -1 && (clone_of = drivlist.non_bios_clone(clone_of)) != -1)
365
mame_printf_error("%s: %s is a clone of a clone\n", driver.source_file, driver.name);
369
/* make sure the driver name is 8 chars or less */
370
if ((is_clone && strlen(driver.name) > NAME_LEN_CLONE) || ((!is_clone) && strlen(driver.name) > NAME_LEN_PARENT))
372
mame_printf_error("%s: %s %s driver name must be %d characters or less\n", driver.source_file, driver.name,
373
is_clone ? "clone" : "parent", is_clone ? NAME_LEN_CLONE : NAME_LEN_PARENT);
377
/* make sure the year is only digits, '?' or '+' */
378
for (s = driver.year; *s; s++)
379
if (!isdigit((UINT8)*s) && *s != '?' && *s != '+')
381
mame_printf_error("%s: %s has an invalid year '%s'\n", driver.source_file, driver.name, driver.year);
386
/* normalize driver->compatible_with */
387
compatible_with = driver.compatible_with;
388
if ((compatible_with != NULL) && !strcmp(compatible_with, "0"))
389
compatible_with = NULL;
391
/* check for this driver being compatible with a non-existant driver */
392
if ((compatible_with != NULL) && (drivlist.find(driver.compatible_with) == -1))
394
mame_printf_error("%s: is compatible with %s, which is not in drivers[]\n", driver.name, driver.compatible_with);
398
/* check for clone_of and compatible_with being specified at the same time */
399
if ((drivlist.clone(driver) != -1) && (compatible_with != NULL))
401
mame_printf_error("%s: both compatible_with and clone_of are specified\n", driver.name);
405
/* find any recursive dependencies on the current driver */
406
for (int other_drv = drivlist.compatible_with(driver); other_drv != -1; other_drv = drivlist.compatible_with(other_drv))
408
if (&driver == &drivlist.driver(other_drv))
410
mame_printf_error("%s: recursive compatibility\n", driver.name);
416
/* make sure sound-less drivers are flagged */
417
const device_sound_interface *sound;
418
if ((driver.flags & GAME_IS_BIOS_ROOT) == 0 && !config.devicelist().first(sound) && (driver.flags & GAME_NO_SOUND) == 0 && (driver.flags & GAME_NO_SOUND_HW) == 0)
420
mame_printf_error("%s: %s missing GAME_NO_SOUND flag\n", driver.source_file, driver.name);
428
/*-------------------------------------------------
429
validate_roms - validate ROM definitions
430
-------------------------------------------------*/
432
static bool validate_roms(driver_enumerator &drivlist, region_array *rgninfo, game_driver_map &roms)
434
const game_driver &driver = drivlist.driver();
435
const machine_config &config = drivlist.config();
436
int bios_flags = 0, last_bios = 0;
437
const char *last_rgnname = "???";
438
const char *last_name = "???";
439
region_entry *currgn = NULL;
440
int items_since_region = 1;
443
/* iterate, starting with the driver's ROMs and continuing with device ROMs */
444
for (const rom_source *source = rom_first_source(config); source != NULL; source = rom_next_source(*source))
446
/* scan the ROM entries */
447
for (const rom_entry *romp = rom_first_region(*source); !ROMENTRY_ISEND(romp); romp++)
449
/* if this is a region, make sure it's valid, and record the length */
450
if (ROMENTRY_ISREGION(romp))
452
const char *regiontag = ROMREGION_GETTAG(romp);
454
/* if we haven't seen any items since the last region, print a warning */
455
if (items_since_region == 0)
456
mame_printf_warning("%s: %s has empty ROM region '%s' (warning)\n", driver.source_file, driver.name, last_rgnname);
457
items_since_region = (ROMREGION_ISERASE(romp) || ROMREGION_ISDISKDATA(romp)) ? 1 : 0;
459
last_rgnname = regiontag;
461
/* check for a valid tag */
462
if (regiontag == NULL)
464
mame_printf_error("%s: %s has NULL ROM_REGION tag\n", driver.source_file, driver.name);
468
/* load by name entries must be 8 characters or less */
469
else if (ROMREGION_ISLOADBYNAME(romp) && strlen(regiontag) > 8)
471
mame_printf_error("%s: %s has load-by-name region '%s' with name >8 characters\n", driver.source_file, driver.name, regiontag);
475
/* find any empty entry, checking for duplicates */
480
/* iterate over all regions found so far */
481
rom_region_name(fulltag, &driver, source, romp);
482
for (int rgnnum = 0; rgnnum < ARRAY_LENGTH(rgninfo->entries); rgnnum++)
484
/* stop when we hit an empty */
485
if (!rgninfo->entries[rgnnum].tag)
487
currgn = &rgninfo->entries[rgnnum];
488
currgn->tag = fulltag;
489
currgn->length = ROMREGION_GETLENGTH(romp);
493
/* fail if we hit a duplicate */
494
if (fulltag == rgninfo->entries[rgnnum].tag)
496
mame_printf_error("%s: %s has duplicate ROM_REGION tag '%s'\n", driver.source_file, driver.name, fulltag.cstr());
503
/* validate the region tag */
504
if (!validate_tag(driver, "region", regiontag))
508
/* If this is a system bios, make sure it is using the next available bios number */
509
else if (ROMENTRY_ISSYSTEM_BIOS(romp))
511
bios_flags = ROM_GETBIOSFLAGS(romp);
512
if (last_bios+1 != bios_flags)
514
const char *name = ROM_GETNAME(romp);
515
mame_printf_error("%s: %s has non-sequential bios %s\n", driver.source_file, driver.name, name);
518
last_bios = bios_flags;
521
/* if this is a file, make sure it is properly formatted */
522
else if (ROMENTRY_ISFILE(romp))
526
items_since_region++;
528
/* track the last filename we found */
529
last_name = ROM_GETNAME(romp);
531
/* make sure it's all lowercase */
532
for (s = last_name; *s; s++)
533
if (tolower((UINT8)*s) != *s)
535
mame_printf_error("%s: %s has upper case ROM name %s\n", driver.source_file, driver.name, last_name);
540
/* make sure the hash is valid */
541
hash_collection hashes;
542
if (!hashes.from_internal_string(ROM_GETHASHDATA(romp)))
544
mame_printf_error("%s: rom '%s' has an invalid hash string '%s'\n", driver.name, last_name, ROM_GETHASHDATA(romp));
549
// count copies/fills as valid items
550
else if (ROMENTRY_ISCOPY(romp) || ROMENTRY_ISFILL(romp))
551
items_since_region++;
553
/* for any non-region ending entries, make sure they don't extend past the end */
554
if (!ROMENTRY_ISREGIONEND(romp) && currgn != NULL)
556
items_since_region++;
558
if (ROM_GETOFFSET(romp) + ROM_GETLENGTH(romp) > currgn->length)
560
mame_printf_error("%s: %s has ROM %s extending past the defined memory region\n", driver.source_file, driver.name, last_name);
566
/* final check for empty regions */
567
if (items_since_region == 0)
568
mame_printf_warning("%s: %s has empty ROM region (warning)\n", driver.source_file, driver.name);
575
/*-------------------------------------------------
576
validate_display - validate display
578
-------------------------------------------------*/
580
static bool validate_display(driver_enumerator &drivlist)
582
const game_driver &driver = drivlist.driver();
583
const machine_config &config = drivlist.config();
584
bool palette_modes = false;
587
for (const screen_device *scrconfig = config.first_screen(); scrconfig != NULL; scrconfig = scrconfig->next_screen())
588
if (scrconfig->format() == BITMAP_FORMAT_INDEXED16)
589
palette_modes = true;
591
/* check for empty palette */
592
if (palette_modes && config.m_total_colors == 0)
594
mame_printf_error("%s: %s has zero palette entries\n", driver.source_file, driver.name);
602
/*-------------------------------------------------
603
validate_gfx - validate graphics decoding
605
-------------------------------------------------*/
607
static bool validate_gfx(driver_enumerator &drivlist, region_array *rgninfo)
609
const game_driver &driver = drivlist.driver();
610
const machine_config &config = drivlist.config();
615
if (!config.m_gfxdecodeinfo)
618
/* iterate over graphics decoding entries */
619
for (gfxnum = 0; gfxnum < MAX_GFX_ELEMENTS && config.m_gfxdecodeinfo[gfxnum].gfxlayout != NULL; gfxnum++)
621
const gfx_decode_entry *gfx = &config.m_gfxdecodeinfo[gfxnum];
622
const char *region = gfx->memory_region;
623
int xscale = (config.m_gfxdecodeinfo[gfxnum].xscale == 0) ? 1 : config.m_gfxdecodeinfo[gfxnum].xscale;
624
int yscale = (config.m_gfxdecodeinfo[gfxnum].yscale == 0) ? 1 : config.m_gfxdecodeinfo[gfxnum].yscale;
625
const gfx_layout *gl = gfx->gfxlayout;
626
int israw = (gl->planeoffset[0] == GFX_RAW);
627
int planes = gl->planes;
628
UINT16 width = gl->width;
629
UINT16 height = gl->height;
630
UINT32 total = gl->total;
632
/* make sure the region exists */
637
/* loop over gfx regions */
638
for (rgnnum = 0; rgnnum < ARRAY_LENGTH(rgninfo->entries); rgnnum++)
640
/* stop if we hit an empty */
641
if (!rgninfo->entries[rgnnum].tag)
643
mame_printf_error("%s: %s has gfx[%d] referencing non-existent region '%s'\n", driver.source_file, driver.name, gfxnum, region);
648
/* if we hit a match, check against the length */
649
if (rgninfo->entries[rgnnum].tag == region)
651
/* if we have a valid region, and we're not using auto-sizing, check the decode against the region length */
654
int len, avail, plane, start;
655
UINT32 charincrement = gl->charincrement;
656
const UINT32 *poffset = gl->planeoffset;
658
/* determine which plane is the largest */
660
for (plane = 0; plane < planes; plane++)
661
if (poffset[plane] > start)
662
start = poffset[plane];
663
start &= ~(charincrement - 1);
665
/* determine the total length based on this info */
666
len = total * charincrement;
668
/* do we have enough space in the region to cover the whole decode? */
669
avail = rgninfo->entries[rgnnum].length - (gfx->start & ~(charincrement/8-1));
671
/* if not, this is an error */
672
if ((start + len) / 8 > avail)
674
mame_printf_error("%s: %s has gfx[%d] extending past allocated memory of region '%s'\n", driver.source_file, driver.name, gfxnum, region);
685
if (total != RGN_FRAC(1,1))
687
mame_printf_error("%s: %s has gfx[%d] with unsupported layout total\n", driver.source_file, driver.name, gfxnum);
691
if (xscale != 1 || yscale != 1)
693
mame_printf_error("%s: %s has gfx[%d] with unsupported xscale/yscale\n", driver.source_file, driver.name, gfxnum);
699
if (planes > MAX_GFX_PLANES)
701
mame_printf_error("%s: %s has gfx[%d] with invalid planes\n", driver.source_file, driver.name, gfxnum);
705
if (xscale * width > MAX_ABS_GFX_SIZE || yscale * height > MAX_ABS_GFX_SIZE)
707
mame_printf_error("%s: %s has gfx[%d] with invalid xscale/yscale\n", driver.source_file, driver.name, gfxnum);
717
/*-------------------------------------------------
718
get_defstr_index - return the index of the
719
string assuming it is one of the default
721
-------------------------------------------------*/
723
static int get_defstr_index(int_map &defstr_map, const char *name, const game_driver &driver, bool *error)
725
/* check for strings that should be DEF_STR */
726
int strindex = defstr_map.find(name);
727
if (strindex != 0 && name != input_port_string_from_index(strindex) && error != NULL)
729
mame_printf_error("%s: %s must use DEF_STR( %s )\n", driver.source_file, driver.name, name);
737
/*-------------------------------------------------
738
validate_analog_input_field - validate an
740
-------------------------------------------------*/
742
static void validate_analog_input_field(input_field_config *field, const game_driver &driver, bool *error)
744
INT32 analog_max = field->max;
745
INT32 analog_min = field->min;
748
if (field->type == IPT_POSITIONAL || field->type == IPT_POSITIONAL_V)
750
for (shift = 0; (shift <= 31) && (~field->mask & (1 << shift)); shift++) ;
751
/* convert the positional max value to be in the bitmask for testing */
752
analog_max = (analog_max - 1) << shift;
754
/* positional port size must fit in bits used */
755
if (((field->mask >> shift) + 1) < field->max)
757
mame_printf_error("%s: %s has an analog port with a positional port size bigger then the mask size\n", driver.source_file, driver.name);
763
/* only positional controls use PORT_WRAPS */
764
if (field->flags & ANALOG_FLAG_WRAPS)
766
mame_printf_error("%s: %s only positional analog ports use PORT_WRAPS\n", driver.source_file, driver.name);
771
/* analog ports must have a valid sensitivity */
772
if (field->sensitivity == 0)
774
mame_printf_error("%s: %s has an analog port with zero sensitivity\n", driver.source_file, driver.name);
778
/* check that the default falls in the bitmask range */
779
if (field->defvalue & ~field->mask)
781
mame_printf_error("%s: %s has an analog port with a default value out of the bitmask range\n", driver.source_file, driver.name);
785
/* tests for absolute devices */
786
if (field->type >= __ipt_analog_absolute_start && field->type <= __ipt_analog_absolute_end)
788
INT32 default_value = field->defvalue;
790
/* adjust for signed values */
791
if (analog_min > analog_max)
793
analog_min = -analog_min;
794
if (default_value > analog_max)
795
default_value = -default_value;
798
/* check that the default falls in the MINMAX range */
799
if (default_value < analog_min || default_value > analog_max)
801
mame_printf_error("%s: %s has an analog port with a default value out PORT_MINMAX range\n", driver.source_file, driver.name);
805
/* check that the MINMAX falls in the bitmask range */
806
/* we use the unadjusted min for testing */
807
if (field->min & ~field->mask || analog_max & ~field->mask)
809
mame_printf_error("%s: %s has an analog port with a PORT_MINMAX value out of the bitmask range\n", driver.source_file, driver.name);
813
/* absolute analog ports do not use PORT_RESET */
814
if (field->flags & ANALOG_FLAG_RESET)
816
mame_printf_error("%s: %s - absolute analog ports do not use PORT_RESET\n", driver.source_file, driver.name);
821
/* tests for relative devices */
824
/* tests for non IPT_POSITIONAL relative devices */
825
if (field->type != IPT_POSITIONAL && field->type != IPT_POSITIONAL_V)
827
/* relative devices do not use PORT_MINMAX */
828
if (field->min != 0 || field->max != field->mask)
830
mame_printf_error("%s: %s - relative ports do not use PORT_MINMAX\n", driver.source_file, driver.name);
834
/* relative devices do not use a default value */
835
/* the counter is at 0 on power up */
836
if (field->defvalue != 0)
838
mame_printf_error("%s: %s - relative ports do not use a default value other then 0\n", driver.source_file, driver.name);
846
/*-------------------------------------------------
847
validate_dip_settings - validate a DIP switch
849
-------------------------------------------------*/
851
static void validate_dip_settings(input_field_config *field, const game_driver &driver, int_map &defstr_map, bool *error)
853
const char *demo_sounds = input_port_string_from_index(INPUT_STRING_Demo_Sounds);
854
const char *flipscreen = input_port_string_from_index(INPUT_STRING_Flip_Screen);
855
UINT8 coin_list[INPUT_STRING_1C_9C + 1 - INPUT_STRING_9C_1C] = { 0 };
856
const input_setting_config *setting;
857
int coin_error = FALSE;
859
/* iterate through the settings */
860
for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
862
int strindex = get_defstr_index(defstr_map, setting->name, driver, error);
864
/* note any coinage strings */
865
if (strindex >= INPUT_STRING_9C_1C && strindex <= INPUT_STRING_1C_9C)
866
coin_list[strindex - INPUT_STRING_9C_1C] = 1;
868
/* make sure demo sounds default to on */
869
if (field->name == demo_sounds && strindex == INPUT_STRING_On && field->defvalue != setting->value)
871
mame_printf_error("%s: %s Demo Sounds must default to On\n", driver.source_file, driver.name);
875
/* check for bad demo sounds options */
876
if (field->name == demo_sounds && (strindex == INPUT_STRING_Yes || strindex == INPUT_STRING_No))
878
mame_printf_error("%s: %s has wrong Demo Sounds option %s (must be Off/On)\n", driver.source_file, driver.name, setting->name);
882
/* check for bad flip screen options */
883
if (field->name == flipscreen && (strindex == INPUT_STRING_Yes || strindex == INPUT_STRING_No))
885
mame_printf_error("%s: %s has wrong Flip Screen option %s (must be Off/On)\n", driver.source_file, driver.name, setting->name);
889
/* if we have a neighbor, compare ourselves to him */
890
if (setting->next() != NULL)
892
int next_strindex = get_defstr_index(defstr_map, setting->next()->name, driver, error);
894
/* check for inverted off/on dispswitch order */
895
if (strindex == INPUT_STRING_On && next_strindex == INPUT_STRING_Off)
897
mame_printf_error("%s: %s has inverted Off/On dipswitch order\n", driver.source_file, driver.name);
901
/* check for inverted yes/no dispswitch order */
902
else if (strindex == INPUT_STRING_Yes && next_strindex == INPUT_STRING_No)
904
mame_printf_error("%s: %s has inverted No/Yes dipswitch order\n", driver.source_file, driver.name);
908
/* check for inverted upright/cocktail dispswitch order */
909
else if (strindex == INPUT_STRING_Cocktail && next_strindex == INPUT_STRING_Upright)
911
mame_printf_error("%s: %s has inverted Upright/Cocktail dipswitch order\n", driver.source_file, driver.name);
915
/* check for proper coin ordering */
916
else if (strindex >= INPUT_STRING_9C_1C && strindex <= INPUT_STRING_1C_9C && next_strindex >= INPUT_STRING_9C_1C && next_strindex <= INPUT_STRING_1C_9C &&
917
strindex >= next_strindex && memcmp(&setting->condition, &setting->next()->condition, sizeof(setting->condition)) == 0)
919
mame_printf_error("%s: %s has unsorted coinage %s > %s\n", driver.source_file, driver.name, setting->name, setting->next()->name);
920
coin_error = *error = true;
925
/* if we have a coin error, demonstrate the correct way */
930
mame_printf_error("%s: %s proper coin sort order should be:\n", driver.source_file, driver.name);
931
for (entry = 0; entry < ARRAY_LENGTH(coin_list); entry++)
932
if (coin_list[entry])
933
mame_printf_error("%s\n", input_port_string_from_index(INPUT_STRING_9C_1C + entry));
938
/*-------------------------------------------------
939
validate_inputs - validate input configuration
940
-------------------------------------------------*/
942
static bool validate_inputs(driver_enumerator &drivlist, int_map &defstr_map, ioport_list &portlist)
944
input_port_config *scanport;
945
input_port_config *port;
946
input_field_config *field;
947
const game_driver &driver = drivlist.driver();
948
const machine_config &config = drivlist.config();
949
int empty_string_found = FALSE;
953
/* skip if no ports */
954
if (driver.ipt == NULL)
957
/* allocate the input ports */
958
for (device_t *cfg = config.devicelist().first(); cfg != NULL; cfg = cfg->next())
960
input_port_list_init(*cfg, portlist, errorbuf);
963
mame_printf_error("%s: %s has input port errors:\n%s\n", driver.source_file, driver.name, errorbuf.cstr());
968
/* check for duplicate tags */
969
for (port = portlist.first(); port != NULL; port = port->next())
970
for (scanport = port->next(); scanport != NULL; scanport = scanport->next())
971
if (strcmp(port->tag(), scanport->tag()) == 0)
973
mame_printf_error("%s: %s has a duplicate input port tag '%s'\n", driver.source_file, driver.name, port->tag());
977
/* iterate over the results */
978
for (port = portlist.first(); port != NULL; port = port->next())
979
for (field = port->fieldlist().first(); field != NULL; field = field->next())
981
input_setting_config *setting;
984
/* verify analog inputs */
985
if (input_type_is_analog(field->type))
986
validate_analog_input_field(field, driver, &error);
988
/* verify dip switches */
989
if (field->type == IPT_DIPSWITCH)
991
/* dip switch fields must have a name */
992
if (field->name == NULL)
994
mame_printf_error("%s: %s has a DIP switch name or setting with no name\n", driver.source_file, driver.name);
998
/* verify the settings list */
999
validate_dip_settings(field, driver, defstr_map, &error);
1002
/* look for invalid (0) types which should be mapped to IPT_OTHER */
1003
if (field->type == IPT_INVALID)
1005
mame_printf_error("%s: %s has an input port with an invalid type (0); use IPT_OTHER instead\n", driver.source_file, driver.name);
1010
if (field->name != NULL)
1012
/* check for empty string */
1013
if (field->name[0] == 0 && !empty_string_found)
1015
mame_printf_error("%s: %s has an input with an empty string\n", driver.source_file, driver.name);
1016
empty_string_found = error = true;
1019
/* check for trailing spaces */
1020
if (field->name[0] != 0 && field->name[strlen(field->name) - 1] == ' ')
1022
mame_printf_error("%s: %s input '%s' has trailing spaces\n", driver.source_file, driver.name, field->name);
1026
/* check for invalid UTF-8 */
1027
if (!utf8_is_valid_string(field->name))
1029
mame_printf_error("%s: %s input '%s' has invalid characters\n", driver.source_file, driver.name, field->name);
1033
/* look up the string and print an error if default strings are not used */
1034
/*strindex = */get_defstr_index(defstr_map, field->name, driver, &error);
1037
/* verify conditions on the field */
1038
if (field->condition.tag != NULL)
1040
/* find a matching port */
1041
for (scanport = portlist.first(); scanport != NULL; scanport = scanport->next()) {
1043
port->owner().subtag(porttag, field->condition.tag);
1044
if (strcmp(porttag.cstr(), scanport->tag()) == 0)
1047
/* if none, error */
1048
if (scanport == NULL)
1050
mame_printf_error("%s: %s has a condition referencing non-existent input port tag '%s'\n", driver.source_file, driver.name, field->condition.tag);
1055
/* verify conditions on the settings */
1056
for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
1057
if (setting->condition.tag != NULL)
1059
/* find a matching port */
1060
for (scanport = portlist.first(); scanport != NULL; scanport = scanport->next()) {
1062
port->owner().subtag(porttag, setting->condition.tag);
1063
if (strcmp(porttag.cstr(), scanport->tag()) == 0)
1066
/* if none, error */
1067
if (scanport == NULL)
1069
mame_printf_error("%s: %s has a condition referencing non-existent input port tag '%s'\n", driver.source_file, driver.name, setting->condition.tag);
1075
error = error || validate_natural_keyboard_statics();
1081
/*-------------------------------------------------
1082
validate_devices - run per-device validity
1084
-------------------------------------------------*/
1086
static bool validate_devices(driver_enumerator &drivlist, const ioport_list &portlist, region_array *rgninfo)
1089
const game_driver &driver = drivlist.driver();
1090
const machine_config &config = drivlist.config();
1092
for (const device_t *device = config.devicelist().first(); device != NULL; device = device->next())
1094
/* validate the device tag */
1095
if (!validate_tag(driver, device->name(), device->tag()))
1098
/* look for duplicates */
1099
for (const device_t *scandevice = config.devicelist().first(); scandevice != device; scandevice = scandevice->next())
1100
if (strcmp(scandevice->tag(), device->tag()) == 0)
1102
mame_printf_warning("%s: %s has multiple devices with the tag '%s'\n", driver.source_file, driver.name, device->tag());
1106
if (device->rom_region() != NULL && (strcmp(device->shortname(),"") == 0)) {
1107
mame_printf_warning("Device %s does not have short name defined\n", device->name());
1109
/* check for device-specific validity check */
1110
if (device->validity_check(config.options(), driver))
1118
/*-------------------------------------------------
1119
validate_drivers - master validity checker
1120
-------------------------------------------------*/
1122
void validate_drivers(emu_options &options, const game_driver *curdriver)
1124
osd_ticks_t prep = 0;
1125
osd_ticks_t driver_checks = 0;
1126
osd_ticks_t rom_checks = 0;
1127
osd_ticks_t gfx_checks = 0;
1128
osd_ticks_t display_checks = 0;
1129
osd_ticks_t input_checks = 0;
1130
osd_ticks_t device_checks = 0;
1137
game_driver_map names;
1138
game_driver_map descriptions;
1139
game_driver_map roms;
1142
/* basic system checks */
1145
if (b > a) { mame_printf_error("UINT8 must be 8 bits\n"); error = true; }
1147
if (sizeof(INT8) != 1) { mame_printf_error("INT8 must be 8 bits\n"); error = true; }
1148
if (sizeof(UINT8) != 1) { mame_printf_error("UINT8 must be 8 bits\n"); error = true; }
1149
if (sizeof(INT16) != 2) { mame_printf_error("INT16 must be 16 bits\n"); error = true; }
1150
if (sizeof(UINT16) != 2) { mame_printf_error("UINT16 must be 16 bits\n"); error = true; }
1151
if (sizeof(INT32) != 4) { mame_printf_error("INT32 must be 32 bits\n"); error = true; }
1152
if (sizeof(UINT32) != 4) { mame_printf_error("UINT32 must be 32 bits\n"); error = true; }
1153
if (sizeof(INT64) != 8) { mame_printf_error("INT64 must be 64 bits\n"); error = true; }
1154
if (sizeof(UINT64) != 8) { mame_printf_error("UINT64 must be 64 bits\n"); error = true; }
1156
if (sizeof(void *) != 8) { mame_printf_error("PTR64 flag enabled, but was compiled for 32-bit target\n"); error = true; }
1158
if (sizeof(void *) != 4) { mame_printf_error("PTR64 flag not enabled, but was compiled for 64-bit target\n"); error = true; }
1161
*(UINT8 *)&lsbtest = 0xff;
1163
if (lsbtest == 0xff00) { mame_printf_error("LSB_FIRST specified, but running on a big-endian machine\n"); error = true; }
1165
if (lsbtest == 0x00ff) { mame_printf_error("LSB_FIRST not specified, but running on a little-endian machine\n"); error = true; }
1168
/* validate inline function behavior */
1169
error = validate_inlines() || error;
1171
get_profile_ticks();
1173
/* pre-populate the defstr tagmap with all the default strings */
1174
prep -= get_profile_ticks();
1175
for (strnum = 1; strnum < INPUT_STRING_COUNT; strnum++)
1177
const char *string = input_port_string_from_index(strnum);
1179
defstr.add(string, strnum, FALSE);
1181
prep += get_profile_ticks();
1183
/* iterate over all drivers */
1184
driver_enumerator drivlist(options);
1185
while (drivlist.next())
1187
const game_driver &driver = drivlist.driver();
1188
ioport_list portlist;
1189
region_array rgninfo;
1191
/* non-debug builds only care about games in the same driver */
1192
if (curdriver != NULL && strcmp(curdriver->source_file, driver.source_file) != 0)
1197
/* validate the driver entry */
1198
driver_checks -= get_profile_ticks();
1199
error = validate_driver(drivlist, names, descriptions) || error;
1200
driver_checks += get_profile_ticks();
1202
/* validate the ROM information */
1203
rom_checks -= get_profile_ticks();
1204
error = validate_roms(drivlist, &rgninfo, roms) || error;
1205
rom_checks += get_profile_ticks();
1207
/* validate input ports */
1208
input_checks -= get_profile_ticks();
1209
error = validate_inputs(drivlist, defstr, portlist) || error;
1210
input_checks += get_profile_ticks();
1212
/* validate the display */
1213
display_checks -= get_profile_ticks();
1214
error = validate_display(drivlist) || error;
1215
display_checks += get_profile_ticks();
1217
/* validate the graphics decoding */
1218
gfx_checks -= get_profile_ticks();
1219
error = validate_gfx(drivlist, &rgninfo) || error;
1220
gfx_checks += get_profile_ticks();
1222
/* validate devices */
1223
device_checks -= get_profile_ticks();
1224
error = validate_devices(drivlist, portlist, &rgninfo) || error;
1225
device_checks += get_profile_ticks();
1227
catch (emu_fatalerror &err)
1229
throw emu_fatalerror("Validating %s (%s): %s", driver.name, driver.source_file, err.string());
1234
mame_printf_info("Prep: %8dm\n", (int)(prep / 1000000));
1235
mame_printf_info("Driver: %8dm\n", (int)(driver_checks / 1000000));
1236
mame_printf_info("ROM: %8dm\n", (int)(rom_checks / 1000000));
1237
mame_printf_info("CPU: %8dm\n", (int)(cpu_checks / 1000000));
1238
mame_printf_info("Display: %8dm\n", (int)(display_checks / 1000000));
1239
mame_printf_info("Graphics: %8dm\n", (int)(gfx_checks / 1000000));
1240
mame_printf_info("Input: %8dm\n", (int)(input_checks / 1000000));
1243
// on a general error, throw rather than return
1245
throw emu_fatalerror(MAMERR_FAILED_VALIDITY, "Validity checks failed");