~ubuntu-branches/debian/sid/mame/sid

« back to all changes in this revision

Viewing changes to mess/src/emu/validity.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach, Jordi Mallach, Emmanuel Kasper
  • Date: 2011-12-19 22:56:27 UTC
  • mfrom: (0.1.2)
  • Revision ID: package-import@ubuntu.com-20111219225627-ub5oga1oys4ogqzm
Tags: 0.144-1
[ Jordi Mallach ]
* Fix syntax errors in DEP5 copyright file (lintian).
* Use a versioned copyright Format specification field.
* Update Vcs-* URLs.
* Move transitional packages to the new metapackages section, and make
  them priority extra.
* Remove references to GNU/Linux and MESS sources from copyright.
* Add build variables for s390x.
* Use .xz tarballs as it cuts 4MB for the upstream sources.
* Add nplayers.ini as a patch. Update copyright file to add CC-BY-SA-3.0.

[ Emmanuel Kasper ]
* New upstream release. Closes: #651538.
* Add Free Desktop compliant png icons of various sizes taken from
  the hydroxygen iconset
* Mess is now built from a new source package, to avoid possible source
  incompatibilities between mame and the mess overlay.
* Mame-tools are not built from the mame source package anymore, but
  from the mess source package

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
 
3
 
    validity.c
4
 
 
5
 
    Validity checks on internal data structures.
6
 
 
7
 
    Copyright Nicola Salmoria and the MAME Team.
8
 
    Visit http://mamedev.org for licensing and usage restrictions.
9
 
 
10
 
***************************************************************************/
11
 
 
12
 
#include "emu.h"
13
 
#include "hash.h"
14
 
#include "validity.h"
15
 
 
16
 
#include <ctype.h>
17
 
 
18
 
 
19
 
/***************************************************************************
20
 
    DEBUGGING
21
 
***************************************************************************/
22
 
 
23
 
#define REPORT_TIMES                            (0)
24
 
 
25
 
 
26
 
 
27
 
/***************************************************************************
28
 
    COMPILE-TIME VALIDATION
29
 
***************************************************************************/
30
 
 
31
 
/* if the following lines error during compile, your PTR64 switch is set incorrectly in the makefile */
32
 
#ifdef PTR64
33
 
UINT8 your_ptr64_flag_is_wrong[(int)(sizeof(void *) - 7)];
34
 
#else
35
 
UINT8 your_ptr64_flag_is_wrong[(int)(5 - sizeof(void *))];
36
 
#endif
37
 
 
38
 
 
39
 
 
40
 
/***************************************************************************
41
 
    TYPE DEFINITIONS
42
 
***************************************************************************/
43
 
 
44
 
typedef tagmap_t<const game_driver *> game_driver_map;
45
 
 
46
 
typedef tagmap_t<FPTR> int_map;
47
 
 
48
 
class region_entry
49
 
{
50
 
public:
51
 
        region_entry()
52
 
                : length(0) { }
53
 
 
54
 
        astring tag;
55
 
        UINT32 length;
56
 
};
57
 
 
58
 
 
59
 
class region_array
60
 
{
61
 
public:
62
 
        region_entry entries[256];
63
 
};
64
 
 
65
 
 
66
 
 
67
 
/***************************************************************************
68
 
    INLINE FUNCTIONS
69
 
***************************************************************************/
70
 
 
71
 
/*-------------------------------------------------
72
 
    input_port_string_from_index - return an
73
 
    indexed string from the input port system
74
 
-------------------------------------------------*/
75
 
 
76
 
INLINE const char *input_port_string_from_index(UINT32 index)
77
 
{
78
 
        return input_port_string_from_token((const char *)(FPTR)index);
79
 
}
80
 
 
81
 
 
82
 
/*-------------------------------------------------
83
 
    validate_tag - ensure that the given tag
84
 
    meets the general requirements
85
 
-------------------------------------------------*/
86
 
 
87
 
bool validate_tag(const game_driver &driver, const char *object, const char *tag)
88
 
{
89
 
        const char *validchars = "abcdefghijklmnopqrstuvwxyz0123456789_.:";
90
 
        const char *begin = strrchr(tag, ':');
91
 
        const char *p;
92
 
        bool error = false;
93
 
 
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)
100
 
        {
101
 
                mame_printf_error("%s: %s has invalid generic tag '%s'\n", driver.source_file, driver.name, tag);
102
 
                error = true;
103
 
        }
104
 
 
105
 
        for (p = tag; *p != 0; p++)
106
 
        {
107
 
                if (*p != tolower((UINT8)*p))
108
 
                {
109
 
                        mame_printf_error("%s: %s has %s with tag '%s' containing upper-case characters\n", driver.source_file, driver.name, object, tag);
110
 
                        error = true;
111
 
                        break;
112
 
                }
113
 
                if (*p == ' ')
114
 
                {
115
 
                        mame_printf_error("%s: %s has %s with tag '%s' containing spaces\n", driver.source_file, driver.name, object, tag);
116
 
                        error = true;
117
 
                        break;
118
 
                }
119
 
                if (strchr(validchars, *p) == NULL)
120
 
                {
121
 
                        mame_printf_error("%s: %s has %s with tag '%s' containing invalid character '%c'\n", driver.source_file, driver.name, object, tag, *p);
122
 
                        error = true;
123
 
                        break;
124
 
                }
125
 
        }
126
 
 
127
 
        if (begin == NULL)
128
 
                begin = tag;
129
 
        else
130
 
                begin += 1;
131
 
 
132
 
        if (strlen(begin) == 0)
133
 
        {
134
 
                mame_printf_error("%s: %s has %s with 0-length tag\n", driver.source_file, driver.name, object);
135
 
                error = true;
136
 
        }
137
 
        if (strlen(begin) < MIN_TAG_LENGTH)
138
 
        {
139
 
                mame_printf_error("%s: %s has %s with tag '%s' < %d characters\n", driver.source_file, driver.name, object, tag, MIN_TAG_LENGTH);
140
 
                error = true;
141
 
        }
142
 
        if (strlen(begin) > MAX_TAG_LENGTH)
143
 
        {
144
 
                mame_printf_error("%s: %s has %s with tag '%s' > %d characters\n", driver.source_file, driver.name, object, tag, MAX_TAG_LENGTH);
145
 
                error = true;
146
 
        }
147
 
 
148
 
        return !error;
149
 
}
150
 
 
151
 
 
152
 
 
153
 
/***************************************************************************
154
 
    VALIDATION FUNCTIONS
155
 
***************************************************************************/
156
 
 
157
 
/*-------------------------------------------------
158
 
    validate_inlines - validate inline function
159
 
    behaviors
160
 
-------------------------------------------------*/
161
 
 
162
 
static bool validate_inlines(void)
163
 
{
164
 
#undef rand
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);
167
 
#ifdef PTR64
168
 
        volatile INT64 testi64b = rand() ^ (rand() << 15) ^ ((INT64)rand() << 30) ^ ((INT64)rand() << 45);
169
 
#endif
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;
180
 
        bool error = false;
181
 
 
182
 
        /* use only non-zero, positive numbers */
183
 
        if (testu64a == 0) testu64a++;
184
 
        if (testi64a == 0) testi64a++;
185
 
        else if (testi64a < 0) testi64a = -testi64a;
186
 
#ifdef PTR64
187
 
        if (testi64b == 0) testi64b++;
188
 
        else if (testi64b < 0) testi64b = -testi64b;
189
 
#endif
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;
196
 
 
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; }
201
 
 
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; }
206
 
 
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; }
211
 
 
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; }
216
 
 
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; }
221
 
 
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; }
226
 
 
227
 
        while ((INT64)testi32a * (INT64)0x7fffffff < testi64a)
228
 
                testi64a /= 2;
229
 
        while ((UINT64)testu32a * (UINT64)bigu32 < testu64a)
230
 
                testu64a /= 2;
231
 
 
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; }
236
 
 
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; }
241
 
 
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; }
247
 
 
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; }
253
 
 
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; }
258
 
 
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; }
263
 
 
264
 
        while ((INT64)testi32a * (INT64)0x7fffffff < ((INT32)testi64a << 3))
265
 
                testi64a /= 2;
266
 
        while ((UINT64)testu32a * (UINT64)0xffffffff < ((UINT32)testu64a << 3))
267
 
                testu64a /= 2;
268
 
 
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; }
273
 
 
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; }
278
 
 
279
 
        if (fabs(recip_approx(100.0) - 0.01) > 0.0001)
280
 
                { mame_printf_error("Error testing recip_approx\n"); error = true; }
281
 
 
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; }
288
 
 
289
 
        testi32b = testi32a;
290
 
        if (compare_exchange32(&testi32a, testi32b, 1000) != testi32b || testi32a != 1000)
291
 
                { mame_printf_error("Error testing compare_exchange32\n"); error = true; }
292
 
#ifdef PTR64
293
 
        testi64b = testi64a;
294
 
        if (compare_exchange64(&testi64a, testi64b, 1000) != testi64b || testi64a != 1000)
295
 
                { mame_printf_error("Error testing compare_exchange64\n"); error = true; }
296
 
#endif
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; }
305
 
 
306
 
        return error;
307
 
}
308
 
 
309
 
 
310
 
/*-------------------------------------------------
311
 
    validate_driver - validate basic driver
312
 
    information
313
 
-------------------------------------------------*/
314
 
 
315
 
static bool validate_driver(driver_enumerator &drivlist, game_driver_map &names, game_driver_map &descriptions)
316
 
{
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;
321
 
        const char *s;
322
 
 
323
 
        enum { NAME_LEN_PARENT = 8, NAME_LEN_CLONE = 16 };
324
 
 
325
 
        /* check for duplicate names */
326
 
        if (names.add(driver.name, &driver, FALSE) == TMERR_DUPLICATE)
327
 
        {
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);
330
 
                error = true;
331
 
        }
332
 
 
333
 
        /* check for duplicate descriptions */
334
 
        if (descriptions.add(driver.description, &driver, FALSE) == TMERR_DUPLICATE)
335
 
        {
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);
338
 
                error = true;
339
 
        }
340
 
 
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))
345
 
                is_clone = false;
346
 
 
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)
350
 
        {
351
 
                mame_printf_error("%s: %s is a non-existant clone\n", driver.source_file, driver.parent);
352
 
                error = true;
353
 
        }
354
 
 
355
 
        /* look for recursive cloning */
356
 
        if (clone_of != -1 && &drivlist.driver(clone_of) == &driver)
357
 
        {
358
 
                mame_printf_error("%s: %s is set as a clone of itself\n", driver.source_file, driver.name);
359
 
                error = true;
360
 
        }
361
 
 
362
 
        /* look for clones that are too deep */
363
 
        if (clone_of != -1 && (clone_of = drivlist.non_bios_clone(clone_of)) != -1)
364
 
        {
365
 
                mame_printf_error("%s: %s is a clone of a clone\n", driver.source_file, driver.name);
366
 
                error = true;
367
 
        }
368
 
 
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))
371
 
        {
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);
374
 
                error = true;
375
 
        }
376
 
 
377
 
        /* make sure the year is only digits, '?' or '+' */
378
 
        for (s = driver.year; *s; s++)
379
 
                if (!isdigit((UINT8)*s) && *s != '?' && *s != '+')
380
 
                {
381
 
                        mame_printf_error("%s: %s has an invalid year '%s'\n", driver.source_file, driver.name, driver.year);
382
 
                        error = true;
383
 
                        break;
384
 
                }
385
 
 
386
 
        /* normalize driver->compatible_with */
387
 
        compatible_with = driver.compatible_with;
388
 
        if ((compatible_with != NULL) && !strcmp(compatible_with, "0"))
389
 
                compatible_with = NULL;
390
 
 
391
 
        /* check for this driver being compatible with a non-existant driver */
392
 
        if ((compatible_with != NULL) && (drivlist.find(driver.compatible_with) == -1))
393
 
        {
394
 
                mame_printf_error("%s: is compatible with %s, which is not in drivers[]\n", driver.name, driver.compatible_with);
395
 
                error = true;
396
 
        }
397
 
 
398
 
        /* check for clone_of and compatible_with being specified at the same time */
399
 
        if ((drivlist.clone(driver) != -1) && (compatible_with != NULL))
400
 
        {
401
 
                mame_printf_error("%s: both compatible_with and clone_of are specified\n", driver.name);
402
 
                error = true;
403
 
        }
404
 
 
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))
407
 
        {
408
 
                if (&driver == &drivlist.driver(other_drv))
409
 
                {
410
 
                        mame_printf_error("%s: recursive compatibility\n", driver.name);
411
 
                        error = true;
412
 
                        break;
413
 
                }
414
 
        }
415
 
 
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)
419
 
        {
420
 
                mame_printf_error("%s: %s missing GAME_NO_SOUND flag\n", driver.source_file, driver.name);
421
 
                error = true;
422
 
        }
423
 
 
424
 
        return error;
425
 
}
426
 
 
427
 
 
428
 
/*-------------------------------------------------
429
 
    validate_roms - validate ROM definitions
430
 
-------------------------------------------------*/
431
 
 
432
 
static bool validate_roms(driver_enumerator &drivlist, region_array *rgninfo, game_driver_map &roms)
433
 
{
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;
441
 
        bool error = false;
442
 
 
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))
445
 
        {
446
 
                /* scan the ROM entries */
447
 
                for (const rom_entry *romp = rom_first_region(*source); !ROMENTRY_ISEND(romp); romp++)
448
 
                {
449
 
                        /* if this is a region, make sure it's valid, and record the length */
450
 
                        if (ROMENTRY_ISREGION(romp))
451
 
                        {
452
 
                                const char *regiontag = ROMREGION_GETTAG(romp);
453
 
 
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;
458
 
                                currgn = NULL;
459
 
                                last_rgnname = regiontag;
460
 
 
461
 
                                /* check for a valid tag */
462
 
                                if (regiontag == NULL)
463
 
                                {
464
 
                                        mame_printf_error("%s: %s has NULL ROM_REGION tag\n", driver.source_file, driver.name);
465
 
                                        error = true;
466
 
                                }
467
 
 
468
 
                                /* load by name entries must be 8 characters or less */
469
 
                                else if (ROMREGION_ISLOADBYNAME(romp) && strlen(regiontag) > 8)
470
 
                                {
471
 
                                        mame_printf_error("%s: %s has load-by-name region '%s' with name >8 characters\n", driver.source_file, driver.name, regiontag);
472
 
                                        error = true;
473
 
                                }
474
 
 
475
 
                                /* find any empty entry, checking for duplicates */
476
 
                                else
477
 
                                {
478
 
                                        astring fulltag;
479
 
 
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++)
483
 
                                        {
484
 
                                                /* stop when we hit an empty */
485
 
                                                if (!rgninfo->entries[rgnnum].tag)
486
 
                                                {
487
 
                                                        currgn = &rgninfo->entries[rgnnum];
488
 
                                                        currgn->tag = fulltag;
489
 
                                                        currgn->length = ROMREGION_GETLENGTH(romp);
490
 
                                                        break;
491
 
                                                }
492
 
 
493
 
                                                /* fail if we hit a duplicate */
494
 
                                                if (fulltag == rgninfo->entries[rgnnum].tag)
495
 
                                                {
496
 
                                                        mame_printf_error("%s: %s has duplicate ROM_REGION tag '%s'\n", driver.source_file, driver.name, fulltag.cstr());
497
 
                                                        error = true;
498
 
                                                        break;
499
 
                                                }
500
 
                                        }
501
 
                                }
502
 
 
503
 
                                /* validate the region tag */
504
 
                                if (!validate_tag(driver, "region", regiontag))
505
 
                                        error = true;
506
 
                        }
507
 
 
508
 
                        /* If this is a system bios, make sure it is using the next available bios number */
509
 
                        else if (ROMENTRY_ISSYSTEM_BIOS(romp))
510
 
                        {
511
 
                                bios_flags = ROM_GETBIOSFLAGS(romp);
512
 
                                if (last_bios+1 != bios_flags)
513
 
                                {
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);
516
 
                                        error = true;
517
 
                                }
518
 
                                last_bios = bios_flags;
519
 
                        }
520
 
 
521
 
                        /* if this is a file, make sure it is properly formatted */
522
 
                        else if (ROMENTRY_ISFILE(romp))
523
 
                        {
524
 
                                const char *s;
525
 
 
526
 
                                items_since_region++;
527
 
 
528
 
                                /* track the last filename we found */
529
 
                                last_name = ROM_GETNAME(romp);
530
 
 
531
 
                                /* make sure it's all lowercase */
532
 
                                for (s = last_name; *s; s++)
533
 
                                        if (tolower((UINT8)*s) != *s)
534
 
                                        {
535
 
                                                mame_printf_error("%s: %s has upper case ROM name %s\n", driver.source_file, driver.name, last_name);
536
 
                                                error = true;
537
 
                                                break;
538
 
                                        }
539
 
 
540
 
                                /* make sure the hash is valid */
541
 
                                hash_collection hashes;
542
 
                                if (!hashes.from_internal_string(ROM_GETHASHDATA(romp)))
543
 
                                {
544
 
                                        mame_printf_error("%s: rom '%s' has an invalid hash string '%s'\n", driver.name, last_name, ROM_GETHASHDATA(romp));
545
 
                                        error = true;
546
 
                                }
547
 
                        }
548
 
 
549
 
                        // count copies/fills as valid items
550
 
                        else if (ROMENTRY_ISCOPY(romp) || ROMENTRY_ISFILL(romp))
551
 
                                items_since_region++;
552
 
 
553
 
                        /* for any non-region ending entries, make sure they don't extend past the end */
554
 
                        if (!ROMENTRY_ISREGIONEND(romp) && currgn != NULL)
555
 
                        {
556
 
                                items_since_region++;
557
 
 
558
 
                                if (ROM_GETOFFSET(romp) + ROM_GETLENGTH(romp) > currgn->length)
559
 
                                {
560
 
                                        mame_printf_error("%s: %s has ROM %s extending past the defined memory region\n", driver.source_file, driver.name, last_name);
561
 
                                        error = true;
562
 
                                }
563
 
                        }
564
 
                }
565
 
 
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);
569
 
        }
570
 
 
571
 
        return error;
572
 
}
573
 
 
574
 
 
575
 
/*-------------------------------------------------
576
 
    validate_display - validate display
577
 
    configurations
578
 
-------------------------------------------------*/
579
 
 
580
 
static bool validate_display(driver_enumerator &drivlist)
581
 
{
582
 
        const game_driver &driver = drivlist.driver();
583
 
        const machine_config &config = drivlist.config();
584
 
        bool palette_modes = false;
585
 
        bool error = false;
586
 
 
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;
590
 
 
591
 
        /* check for empty palette */
592
 
        if (palette_modes && config.m_total_colors == 0)
593
 
        {
594
 
                mame_printf_error("%s: %s has zero palette entries\n", driver.source_file, driver.name);
595
 
                error = true;
596
 
        }
597
 
 
598
 
        return error;
599
 
}
600
 
 
601
 
 
602
 
/*-------------------------------------------------
603
 
    validate_gfx - validate graphics decoding
604
 
    configuration
605
 
-------------------------------------------------*/
606
 
 
607
 
static bool validate_gfx(driver_enumerator &drivlist, region_array *rgninfo)
608
 
{
609
 
        const game_driver &driver = drivlist.driver();
610
 
        const machine_config &config = drivlist.config();
611
 
        bool error = false;
612
 
        int gfxnum;
613
 
 
614
 
        /* bail if no gfx */
615
 
        if (!config.m_gfxdecodeinfo)
616
 
                return false;
617
 
 
618
 
        /* iterate over graphics decoding entries */
619
 
        for (gfxnum = 0; gfxnum < MAX_GFX_ELEMENTS && config.m_gfxdecodeinfo[gfxnum].gfxlayout != NULL; gfxnum++)
620
 
        {
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;
631
 
 
632
 
                /* make sure the region exists */
633
 
                if (region != NULL)
634
 
                {
635
 
                        int rgnnum;
636
 
 
637
 
                        /* loop over gfx regions */
638
 
                        for (rgnnum = 0; rgnnum < ARRAY_LENGTH(rgninfo->entries); rgnnum++)
639
 
                        {
640
 
                                /* stop if we hit an empty */
641
 
                                if (!rgninfo->entries[rgnnum].tag)
642
 
                                {
643
 
                                        mame_printf_error("%s: %s has gfx[%d] referencing non-existent region '%s'\n", driver.source_file, driver.name, gfxnum, region);
644
 
                                        error = true;
645
 
                                        break;
646
 
                                }
647
 
 
648
 
                                /* if we hit a match, check against the length */
649
 
                                if (rgninfo->entries[rgnnum].tag == region)
650
 
                                {
651
 
                                        /* if we have a valid region, and we're not using auto-sizing, check the decode against the region length */
652
 
                                        if (!IS_FRAC(total))
653
 
                                        {
654
 
                                                int len, avail, plane, start;
655
 
                                                UINT32 charincrement = gl->charincrement;
656
 
                                                const UINT32 *poffset = gl->planeoffset;
657
 
 
658
 
                                                /* determine which plane is the largest */
659
 
                                                start = 0;
660
 
                                                for (plane = 0; plane < planes; plane++)
661
 
                                                        if (poffset[plane] > start)
662
 
                                                                start = poffset[plane];
663
 
                                                start &= ~(charincrement - 1);
664
 
 
665
 
                                                /* determine the total length based on this info */
666
 
                                                len = total * charincrement;
667
 
 
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));
670
 
 
671
 
                                                /* if not, this is an error */
672
 
                                                if ((start + len) / 8 > avail)
673
 
                                                {
674
 
                                                        mame_printf_error("%s: %s has gfx[%d] extending past allocated memory of region '%s'\n", driver.source_file, driver.name, gfxnum, region);
675
 
                                                        error = true;
676
 
                                                }
677
 
                                        }
678
 
                                        break;
679
 
                                }
680
 
                        }
681
 
                }
682
 
 
683
 
                if (israw)
684
 
                {
685
 
                        if (total != RGN_FRAC(1,1))
686
 
                        {
687
 
                                mame_printf_error("%s: %s has gfx[%d] with unsupported layout total\n", driver.source_file, driver.name, gfxnum);
688
 
                                error = true;
689
 
                        }
690
 
 
691
 
                        if (xscale != 1 || yscale != 1)
692
 
                        {
693
 
                                mame_printf_error("%s: %s has gfx[%d] with unsupported xscale/yscale\n", driver.source_file, driver.name, gfxnum);
694
 
                                error = true;
695
 
                        }
696
 
                }
697
 
                else
698
 
                {
699
 
                        if (planes > MAX_GFX_PLANES)
700
 
                        {
701
 
                                mame_printf_error("%s: %s has gfx[%d] with invalid planes\n", driver.source_file, driver.name, gfxnum);
702
 
                                error = true;
703
 
                        }
704
 
 
705
 
                        if (xscale * width > MAX_ABS_GFX_SIZE || yscale * height > MAX_ABS_GFX_SIZE)
706
 
                        {
707
 
                                mame_printf_error("%s: %s has gfx[%d] with invalid xscale/yscale\n", driver.source_file, driver.name, gfxnum);
708
 
                                error = true;
709
 
                        }
710
 
                }
711
 
        }
712
 
 
713
 
        return error;
714
 
}
715
 
 
716
 
 
717
 
/*-------------------------------------------------
718
 
    get_defstr_index - return the index of the
719
 
    string assuming it is one of the default
720
 
    strings
721
 
-------------------------------------------------*/
722
 
 
723
 
static int get_defstr_index(int_map &defstr_map, const char *name, const game_driver &driver, bool *error)
724
 
{
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)
728
 
        {
729
 
                mame_printf_error("%s: %s must use DEF_STR( %s )\n", driver.source_file, driver.name, name);
730
 
                *error = true;
731
 
        }
732
 
 
733
 
        return strindex;
734
 
}
735
 
 
736
 
 
737
 
/*-------------------------------------------------
738
 
    validate_analog_input_field - validate an
739
 
    analog input field
740
 
-------------------------------------------------*/
741
 
 
742
 
static void validate_analog_input_field(input_field_config *field, const game_driver &driver, bool *error)
743
 
{
744
 
        INT32 analog_max = field->max;
745
 
        INT32 analog_min = field->min;
746
 
        int shift;
747
 
 
748
 
        if (field->type == IPT_POSITIONAL || field->type == IPT_POSITIONAL_V)
749
 
        {
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;
753
 
 
754
 
                /* positional port size must fit in bits used */
755
 
                if (((field->mask >> shift) + 1) < field->max)
756
 
                {
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);
758
 
                        *error = true;
759
 
                }
760
 
        }
761
 
        else
762
 
        {
763
 
                /* only positional controls use PORT_WRAPS */
764
 
                if (field->flags & ANALOG_FLAG_WRAPS)
765
 
                {
766
 
                        mame_printf_error("%s: %s only positional analog ports use PORT_WRAPS\n", driver.source_file, driver.name);
767
 
                        *error = true;
768
 
                }
769
 
        }
770
 
 
771
 
        /* analog ports must have a valid sensitivity */
772
 
        if (field->sensitivity == 0)
773
 
        {
774
 
                mame_printf_error("%s: %s has an analog port with zero sensitivity\n", driver.source_file, driver.name);
775
 
                *error = true;
776
 
        }
777
 
 
778
 
        /* check that the default falls in the bitmask range */
779
 
        if (field->defvalue & ~field->mask)
780
 
        {
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);
782
 
                *error = true;
783
 
        }
784
 
 
785
 
        /* tests for absolute devices */
786
 
        if (field->type >= __ipt_analog_absolute_start && field->type <= __ipt_analog_absolute_end)
787
 
        {
788
 
                INT32 default_value = field->defvalue;
789
 
 
790
 
                /* adjust for signed values */
791
 
                if (analog_min > analog_max)
792
 
                {
793
 
                        analog_min = -analog_min;
794
 
                        if (default_value > analog_max)
795
 
                                default_value = -default_value;
796
 
                }
797
 
 
798
 
                /* check that the default falls in the MINMAX range */
799
 
                if (default_value < analog_min || default_value > analog_max)
800
 
                {
801
 
                        mame_printf_error("%s: %s has an analog port with a default value out PORT_MINMAX range\n", driver.source_file, driver.name);
802
 
                        *error = true;
803
 
                }
804
 
 
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)
808
 
                {
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);
810
 
                        *error = true;
811
 
                }
812
 
 
813
 
                /* absolute analog ports do not use PORT_RESET */
814
 
                if (field->flags & ANALOG_FLAG_RESET)
815
 
                {
816
 
                        mame_printf_error("%s: %s - absolute analog ports do not use PORT_RESET\n", driver.source_file, driver.name);
817
 
                        *error = true;
818
 
                }
819
 
        }
820
 
 
821
 
        /* tests for relative devices */
822
 
        else
823
 
        {
824
 
                /* tests for non IPT_POSITIONAL relative devices */
825
 
                if (field->type != IPT_POSITIONAL && field->type != IPT_POSITIONAL_V)
826
 
                {
827
 
                        /* relative devices do not use PORT_MINMAX */
828
 
                        if (field->min != 0 || field->max != field->mask)
829
 
                        {
830
 
                                mame_printf_error("%s: %s - relative ports do not use PORT_MINMAX\n", driver.source_file, driver.name);
831
 
                                *error = true;
832
 
                        }
833
 
 
834
 
                        /* relative devices do not use a default value */
835
 
                        /* the counter is at 0 on power up */
836
 
                        if (field->defvalue != 0)
837
 
                        {
838
 
                                mame_printf_error("%s: %s - relative ports do not use a default value other then 0\n", driver.source_file, driver.name);
839
 
                                *error = true;
840
 
                        }
841
 
                }
842
 
        }
843
 
}
844
 
 
845
 
 
846
 
/*-------------------------------------------------
847
 
    validate_dip_settings - validate a DIP switch
848
 
    setting
849
 
-------------------------------------------------*/
850
 
 
851
 
static void validate_dip_settings(input_field_config *field, const game_driver &driver, int_map &defstr_map, bool *error)
852
 
{
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;
858
 
 
859
 
        /* iterate through the settings */
860
 
        for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
861
 
        {
862
 
                int strindex = get_defstr_index(defstr_map, setting->name, driver, error);
863
 
 
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;
867
 
 
868
 
                /* make sure demo sounds default to on */
869
 
                if (field->name == demo_sounds && strindex == INPUT_STRING_On && field->defvalue != setting->value)
870
 
                {
871
 
                        mame_printf_error("%s: %s Demo Sounds must default to On\n", driver.source_file, driver.name);
872
 
                        *error = true;
873
 
                }
874
 
 
875
 
                /* check for bad demo sounds options */
876
 
                if (field->name == demo_sounds && (strindex == INPUT_STRING_Yes || strindex == INPUT_STRING_No))
877
 
                {
878
 
                        mame_printf_error("%s: %s has wrong Demo Sounds option %s (must be Off/On)\n", driver.source_file, driver.name, setting->name);
879
 
                        *error = true;
880
 
                }
881
 
 
882
 
                /* check for bad flip screen options */
883
 
                if (field->name == flipscreen && (strindex == INPUT_STRING_Yes || strindex == INPUT_STRING_No))
884
 
                {
885
 
                        mame_printf_error("%s: %s has wrong Flip Screen option %s (must be Off/On)\n", driver.source_file, driver.name, setting->name);
886
 
                        *error = true;
887
 
                }
888
 
 
889
 
                /* if we have a neighbor, compare ourselves to him */
890
 
                if (setting->next() != NULL)
891
 
                {
892
 
                        int next_strindex = get_defstr_index(defstr_map, setting->next()->name, driver, error);
893
 
 
894
 
                        /* check for inverted off/on dispswitch order */
895
 
                        if (strindex == INPUT_STRING_On && next_strindex == INPUT_STRING_Off)
896
 
                        {
897
 
                                mame_printf_error("%s: %s has inverted Off/On dipswitch order\n", driver.source_file, driver.name);
898
 
                                *error = true;
899
 
                        }
900
 
 
901
 
                        /* check for inverted yes/no dispswitch order */
902
 
                        else if (strindex == INPUT_STRING_Yes && next_strindex == INPUT_STRING_No)
903
 
                        {
904
 
                                mame_printf_error("%s: %s has inverted No/Yes dipswitch order\n", driver.source_file, driver.name);
905
 
                                *error = true;
906
 
                        }
907
 
 
908
 
                        /* check for inverted upright/cocktail dispswitch order */
909
 
                        else if (strindex == INPUT_STRING_Cocktail && next_strindex == INPUT_STRING_Upright)
910
 
                        {
911
 
                                mame_printf_error("%s: %s has inverted Upright/Cocktail dipswitch order\n", driver.source_file, driver.name);
912
 
                                *error = true;
913
 
                        }
914
 
 
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)
918
 
                        {
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;
921
 
                        }
922
 
                }
923
 
        }
924
 
 
925
 
        /* if we have a coin error, demonstrate the correct way */
926
 
        if (coin_error)
927
 
        {
928
 
                int entry;
929
 
 
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));
934
 
        }
935
 
}
936
 
 
937
 
 
938
 
/*-------------------------------------------------
939
 
    validate_inputs - validate input configuration
940
 
-------------------------------------------------*/
941
 
 
942
 
static bool validate_inputs(driver_enumerator &drivlist, int_map &defstr_map, ioport_list &portlist)
943
 
{
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;
950
 
        bool error = false;
951
 
        astring errorbuf;
952
 
 
953
 
        /* skip if no ports */
954
 
        if (driver.ipt == NULL)
955
 
                return FALSE;
956
 
 
957
 
        /* allocate the input ports */
958
 
        for (device_t *cfg = config.devicelist().first(); cfg != NULL; cfg = cfg->next())
959
 
        {
960
 
                input_port_list_init(*cfg, portlist, errorbuf);
961
 
                if (errorbuf)
962
 
                {
963
 
                        mame_printf_error("%s: %s has input port errors:\n%s\n", driver.source_file, driver.name, errorbuf.cstr());
964
 
                        error = true;
965
 
                }
966
 
        }
967
 
 
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)
972
 
                        {
973
 
                                mame_printf_error("%s: %s has a duplicate input port tag '%s'\n", driver.source_file, driver.name, port->tag());
974
 
                                error = true;
975
 
                        }
976
 
 
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())
980
 
                {
981
 
                        input_setting_config *setting;
982
 
                        //int strindex = 0;
983
 
 
984
 
                        /* verify analog inputs */
985
 
                        if (input_type_is_analog(field->type))
986
 
                                validate_analog_input_field(field, driver, &error);
987
 
 
988
 
                        /* verify dip switches */
989
 
                        if (field->type == IPT_DIPSWITCH)
990
 
                        {
991
 
                                /* dip switch fields must have a name */
992
 
                                if (field->name == NULL)
993
 
                                {
994
 
                                        mame_printf_error("%s: %s has a DIP switch name or setting with no name\n", driver.source_file, driver.name);
995
 
                                        error = true;
996
 
                                }
997
 
 
998
 
                                /* verify the settings list */
999
 
                                validate_dip_settings(field, driver, defstr_map, &error);
1000
 
                        }
1001
 
 
1002
 
                        /* look for invalid (0) types which should be mapped to IPT_OTHER */
1003
 
                        if (field->type == IPT_INVALID)
1004
 
                        {
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);
1006
 
                                error = true;
1007
 
                        }
1008
 
 
1009
 
                        /* verify names */
1010
 
                        if (field->name != NULL)
1011
 
                        {
1012
 
                                /* check for empty string */
1013
 
                                if (field->name[0] == 0 && !empty_string_found)
1014
 
                                {
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;
1017
 
                                }
1018
 
 
1019
 
                                /* check for trailing spaces */
1020
 
                                if (field->name[0] != 0 && field->name[strlen(field->name) - 1] == ' ')
1021
 
                                {
1022
 
                                        mame_printf_error("%s: %s input '%s' has trailing spaces\n", driver.source_file, driver.name, field->name);
1023
 
                                        error = true;
1024
 
                                }
1025
 
 
1026
 
                                /* check for invalid UTF-8 */
1027
 
                                if (!utf8_is_valid_string(field->name))
1028
 
                                {
1029
 
                                        mame_printf_error("%s: %s input '%s' has invalid characters\n", driver.source_file, driver.name, field->name);
1030
 
                                        error = true;
1031
 
                                }
1032
 
 
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);
1035
 
                        }
1036
 
 
1037
 
                        /* verify conditions on the field */
1038
 
                        if (field->condition.tag != NULL)
1039
 
                        {
1040
 
                                /* find a matching port */
1041
 
                                for (scanport = portlist.first(); scanport != NULL; scanport = scanport->next()) {
1042
 
                                        astring porttag;
1043
 
                                        port->owner().subtag(porttag, field->condition.tag);
1044
 
                                        if (strcmp(porttag.cstr(), scanport->tag()) == 0)
1045
 
                                                break;
1046
 
                                }
1047
 
                                /* if none, error */
1048
 
                                if (scanport == NULL)
1049
 
                                {
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);
1051
 
                                        error = true;
1052
 
                                }
1053
 
                        }
1054
 
 
1055
 
                        /* verify conditions on the settings */
1056
 
                        for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
1057
 
                                if (setting->condition.tag != NULL)
1058
 
                                {
1059
 
                                        /* find a matching port */
1060
 
                                        for (scanport = portlist.first(); scanport != NULL; scanport = scanport->next()) {
1061
 
                                                astring porttag;
1062
 
                                                port->owner().subtag(porttag, setting->condition.tag);
1063
 
                                                if (strcmp(porttag.cstr(), scanport->tag()) == 0)
1064
 
                                                        break;
1065
 
                                        }
1066
 
                                        /* if none, error */
1067
 
                                        if (scanport == NULL)
1068
 
                                        {
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);
1070
 
                                                error = true;
1071
 
                                        }
1072
 
                                }
1073
 
                }
1074
 
 
1075
 
        error = error || validate_natural_keyboard_statics();
1076
 
 
1077
 
        return error;
1078
 
}
1079
 
 
1080
 
 
1081
 
/*-------------------------------------------------
1082
 
    validate_devices - run per-device validity
1083
 
    checks
1084
 
-------------------------------------------------*/
1085
 
 
1086
 
static bool validate_devices(driver_enumerator &drivlist, const ioport_list &portlist, region_array *rgninfo)
1087
 
{
1088
 
        bool error = false;
1089
 
        const game_driver &driver = drivlist.driver();
1090
 
        const machine_config &config = drivlist.config();
1091
 
 
1092
 
        for (const device_t *device = config.devicelist().first(); device != NULL; device = device->next())
1093
 
        {
1094
 
                /* validate the device tag */
1095
 
                if (!validate_tag(driver, device->name(), device->tag()))
1096
 
                        error = true;
1097
 
 
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)
1101
 
                        {
1102
 
                                mame_printf_warning("%s: %s has multiple devices with the tag '%s'\n", driver.source_file, driver.name, device->tag());
1103
 
                                break;
1104
 
                        }
1105
 
 
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());
1108
 
                }
1109
 
                /* check for device-specific validity check */
1110
 
                if (device->validity_check(config.options(), driver))
1111
 
                        error = true;
1112
 
 
1113
 
        }
1114
 
        return error;
1115
 
}
1116
 
 
1117
 
 
1118
 
/*-------------------------------------------------
1119
 
    validate_drivers - master validity checker
1120
 
-------------------------------------------------*/
1121
 
 
1122
 
void validate_drivers(emu_options &options, const game_driver *curdriver)
1123
 
{
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;
1131
 
 
1132
 
        int strnum;
1133
 
        bool error = false;
1134
 
        UINT16 lsbtest;
1135
 
        UINT8 a, b;
1136
 
 
1137
 
        game_driver_map names;
1138
 
        game_driver_map descriptions;
1139
 
        game_driver_map roms;
1140
 
        int_map defstr;
1141
 
 
1142
 
        /* basic system checks */
1143
 
        a = 0xff;
1144
 
        b = a + 1;
1145
 
        if (b > a)      { mame_printf_error("UINT8 must be 8 bits\n"); error = true; }
1146
 
 
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; }
1155
 
#ifdef PTR64
1156
 
        if (sizeof(void *) != 8)        { mame_printf_error("PTR64 flag enabled, but was compiled for 32-bit target\n"); error = true; }
1157
 
#else
1158
 
        if (sizeof(void *) != 4)        { mame_printf_error("PTR64 flag not enabled, but was compiled for 64-bit target\n"); error = true; }
1159
 
#endif
1160
 
        lsbtest = 0;
1161
 
        *(UINT8 *)&lsbtest = 0xff;
1162
 
#ifdef LSB_FIRST
1163
 
        if (lsbtest == 0xff00)          { mame_printf_error("LSB_FIRST specified, but running on a big-endian machine\n"); error = true; }
1164
 
#else
1165
 
        if (lsbtest == 0x00ff)          { mame_printf_error("LSB_FIRST not specified, but running on a little-endian machine\n"); error = true; }
1166
 
#endif
1167
 
 
1168
 
        /* validate inline function behavior */
1169
 
        error = validate_inlines() || error;
1170
 
 
1171
 
        get_profile_ticks();
1172
 
 
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++)
1176
 
        {
1177
 
                const char *string = input_port_string_from_index(strnum);
1178
 
                if (string != NULL)
1179
 
                        defstr.add(string, strnum, FALSE);
1180
 
        }
1181
 
        prep += get_profile_ticks();
1182
 
 
1183
 
        /* iterate over all drivers */
1184
 
        driver_enumerator drivlist(options);
1185
 
        while (drivlist.next())
1186
 
        {
1187
 
                const game_driver &driver = drivlist.driver();
1188
 
                ioport_list portlist;
1189
 
                region_array rgninfo;
1190
 
 
1191
 
                /* non-debug builds only care about games in the same driver */
1192
 
                if (curdriver != NULL && strcmp(curdriver->source_file, driver.source_file) != 0)
1193
 
                        continue;
1194
 
 
1195
 
                try
1196
 
                {
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();
1201
 
 
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();
1206
 
 
1207
 
                        /* validate input ports */
1208
 
                        input_checks -= get_profile_ticks();
1209
 
                        error = validate_inputs(drivlist, defstr, portlist) || error;
1210
 
                        input_checks += get_profile_ticks();
1211
 
 
1212
 
                        /* validate the display */
1213
 
                        display_checks -= get_profile_ticks();
1214
 
                        error = validate_display(drivlist) || error;
1215
 
                        display_checks += get_profile_ticks();
1216
 
 
1217
 
                        /* validate the graphics decoding */
1218
 
                        gfx_checks -= get_profile_ticks();
1219
 
                        error = validate_gfx(drivlist, &rgninfo) || error;
1220
 
                        gfx_checks += get_profile_ticks();
1221
 
 
1222
 
                        /* validate devices */
1223
 
                        device_checks -= get_profile_ticks();
1224
 
                        error = validate_devices(drivlist, portlist, &rgninfo) || error;
1225
 
                        device_checks += get_profile_ticks();
1226
 
                }
1227
 
                catch (emu_fatalerror &err)
1228
 
                {
1229
 
                        throw emu_fatalerror("Validating %s (%s): %s", driver.name, driver.source_file, err.string());
1230
 
                }
1231
 
        }
1232
 
 
1233
 
#if (REPORT_TIMES)
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));
1241
 
#endif
1242
 
 
1243
 
        // on a general error, throw rather than return
1244
 
        if (error)
1245
 
                throw emu_fatalerror(MAMERR_FAILED_VALIDITY, "Validity checks failed");
1246
 
}