~ubuntu-branches/ubuntu/lucid/sdlmame/lucid

« back to all changes in this revision

Viewing changes to src/emu/validity.c

  • Committer: Bazaar Package Importer
  • Author(s): Cesare Falco
  • Date: 2009-11-03 17:10:15 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20091103171015-6hop4ory5lxnumpn
Tags: 0.135-0ubuntu1
* New upstream release - Closes (LP: #403212)
* debian/watch: unstable releases are no longer detected
* mame.ini: added the cheat subdirectories to cheatpath so zipped
  cheatfiles will be searched too
* renamed crsshair subdirectory to crosshair to reflect upstream change
* mame.ini: renamed references to crosshair subdirectory (see above)

Show diffs side-by-side

added added

removed removed

Lines of Context:
85
85
};
86
86
 
87
87
 
88
 
 
89
 
/***************************************************************************
90
 
    GLOBAL VARIABLES
91
 
***************************************************************************/
92
 
 
93
 
static quark_table *source_table;
94
 
static quark_table *name_table;
95
 
static quark_table *description_table;
96
 
static quark_table *roms_table;
97
 
static quark_table *defstr_table;
 
88
typedef struct _quark_tables quark_tables;
 
89
struct _quark_tables
 
90
{
 
91
        quark_table *source;
 
92
        quark_table *name;
 
93
        quark_table *description;
 
94
        quark_table *roms;
 
95
        quark_table *defstr;
 
96
};
98
97
 
99
98
 
100
99
 
176
175
 
177
176
        for (p = tag; *p != 0; p++)
178
177
        {
179
 
                if (*p != tolower(*p))
 
178
                if (*p != tolower((UINT8)*p))
180
179
                {
181
180
                        mame_printf_error("%s: %s has %s with tag '%s' containing upper-case characters\n", driver->source_file, driver->name, object, tag);
182
181
                        error = TRUE;
254
253
    string operations
255
254
-------------------------------------------------*/
256
255
 
257
 
static void quark_tables_create(void)
 
256
static void quark_tables_create(quark_tables *tables)
258
257
{
259
258
        int drivnum = driver_list_get_count(drivers), strnum;
260
259
 
261
260
        /* allocate memory for the quark tables */
262
 
        source_table = quark_table_alloc(drivnum, QUARK_HASH_SIZE);
263
 
        name_table = quark_table_alloc(drivnum, QUARK_HASH_SIZE);
264
 
        description_table = quark_table_alloc(drivnum, QUARK_HASH_SIZE);
265
 
        roms_table = quark_table_alloc(drivnum, QUARK_HASH_SIZE);
 
261
        tables->source = quark_table_alloc(drivnum, QUARK_HASH_SIZE);
 
262
        tables->name = quark_table_alloc(drivnum, QUARK_HASH_SIZE);
 
263
        tables->description = quark_table_alloc(drivnum, QUARK_HASH_SIZE);
 
264
        tables->roms = quark_table_alloc(drivnum, QUARK_HASH_SIZE);
266
265
 
267
266
        /* build the quarks and the hash tables */
268
267
        for (drivnum = 0; drivers[drivnum]; drivnum++)
270
269
                const game_driver *driver = drivers[drivnum];
271
270
 
272
271
                /* fill in the quark with hashes of the strings */
273
 
                quark_add(source_table,      drivnum, quark_string_crc(driver->source_file));
274
 
                quark_add(name_table,        drivnum, quark_string_crc(driver->name));
275
 
                quark_add(description_table, drivnum, quark_string_crc(driver->description));
 
272
                quark_add(tables->source,      drivnum, quark_string_crc(driver->source_file));
 
273
                quark_add(tables->name,        drivnum, quark_string_crc(driver->name));
 
274
                quark_add(tables->description, drivnum, quark_string_crc(driver->description));
276
275
 
277
276
                /* only track actual driver ROM entries */
278
277
                if (driver->rom && (driver->flags & GAME_NO_STANDALONE) == 0)
279
 
                        quark_add(roms_table,    drivnum, (FPTR)driver->rom);
 
278
                        quark_add(tables->roms,    drivnum, (FPTR)driver->rom);
280
279
        }
281
280
 
282
281
        /* allocate memory for a quark table of strings */
283
 
        defstr_table = quark_table_alloc(INPUT_STRING_COUNT, 97);
 
282
        tables->defstr = quark_table_alloc(INPUT_STRING_COUNT, 97);
284
283
 
285
284
        /* add all the default strings */
286
285
        for (strnum = 1; strnum < INPUT_STRING_COUNT; strnum++)
287
286
        {
288
287
                const char *string = input_port_string_from_index(strnum);
289
288
                if (string != NULL)
290
 
                        quark_add(defstr_table, strnum, quark_string_crc(string));
 
289
                        quark_add(tables->defstr, strnum, quark_string_crc(string));
291
290
        }
292
291
}
293
292
 
296
295
    quark_tables_free - free allocated tables
297
296
-------------------------------------------------*/
298
297
 
299
 
static void quark_tables_free(void)
 
298
static void quark_tables_free(quark_tables *tables)
300
299
{
301
 
        if (source_table != NULL)
302
 
                free(source_table);
303
 
        source_table = NULL;
304
 
 
305
 
        if (name_table != NULL)
306
 
                free(name_table);
307
 
        name_table = NULL;
308
 
 
309
 
        if (description_table != NULL)
310
 
                free(description_table);
311
 
        description_table = NULL;
312
 
 
313
 
        if (roms_table != NULL)
314
 
                free(roms_table);
315
 
        roms_table = NULL;
316
 
 
317
 
        if (defstr_table != NULL)
318
 
                free(defstr_table);
319
 
        defstr_table = NULL;
 
300
        if (tables->source != NULL)
 
301
                free(tables->source);
 
302
        tables->source = NULL;
 
303
 
 
304
        if (tables->name != NULL)
 
305
                free(tables->name);
 
306
        tables->name = NULL;
 
307
 
 
308
        if (tables->description != NULL)
 
309
                free(tables->description);
 
310
        tables->description = NULL;
 
311
 
 
312
        if (tables->roms != NULL)
 
313
                free(tables->roms);
 
314
        tables->roms = NULL;
 
315
 
 
316
        if (tables->defstr != NULL)
 
317
                free(tables->defstr);
 
318
        tables->defstr = NULL;
320
319
}
321
320
 
322
321
 
483
482
    information
484
483
-------------------------------------------------*/
485
484
 
486
 
static int validate_driver(int drivnum, const machine_config *config)
 
485
static int validate_driver(int drivnum, const machine_config *config, const quark_tables *tables)
487
486
{
488
487
        const game_driver *driver = drivers[drivnum];
 
488
        quark_table *name_table = tables->name;
 
489
        quark_table *description_table = tables->description;
 
490
#ifndef MESS
 
491
        quark_table *roms_table = tables->roms;
 
492
#endif /* MESS */
489
493
        const game_driver *clone_of;
490
494
        quark_entry *entry;
491
495
        int error = FALSE, is_clone;
532
536
 
533
537
        /* make sure the year is only digits, '?' or '+' */
534
538
        for (s = driver->year; *s; s++)
535
 
                if (!isdigit(*s) && *s != '?' && *s != '+')
 
539
                if (!isdigit((UINT8)*s) && *s != '?' && *s != '+')
536
540
                {
537
541
                        mame_printf_error("%s: %s has an invalid year '%s'\n", driver->source_file, driver->name, driver->year);
538
542
                        error = TRUE;
604
608
{
605
609
        const game_driver *driver = drivers[drivnum];
606
610
        int bios_flags = 0, last_bios = 0;
 
611
        const char *last_rgnname = "???";
607
612
        const char *last_name = "???";
608
613
        region_entry *currgn = NULL;
609
614
        int items_since_region = 1;
625
630
 
626
631
                                /* if we haven't seen any items since the last region, print a warning */
627
632
                                if (items_since_region == 0)
628
 
                                        mame_printf_warning("%s: %s has empty ROM region (warning)\n", driver->source_file, driver->name);
629
 
                                items_since_region = (ROMREGION_ISERASE(romp) || ROMREGION_ISDISPOSE(romp) || ROMREGION_ISDISKDATA(romp)) ? 1 : 0;
 
633
                                        mame_printf_warning("%s: %s has empty ROM region '%s' (warning)\n", driver->source_file, driver->name, last_rgnname);
 
634
                                items_since_region = (ROMREGION_ISERASE(romp) || ROMREGION_ISDISKDATA(romp)) ? 1 : 0;
630
635
                                currgn = NULL;
 
636
                                last_rgnname = regiontag;
631
637
 
632
638
                                /* check for a valid tag */
633
639
                                if (regiontag == NULL)
702
708
 
703
709
                                /* make sure it's all lowercase */
704
710
                                for (s = last_name; *s; s++)
705
 
                                        if (tolower(*s) != *s)
 
711
                                        if (tolower((UINT8)*s) != *s)
706
712
                                        {
707
713
                                                mame_printf_error("%s: %s has upper case ROM name %s\n", driver->source_file, driver->name, last_name);
708
714
                                                error = TRUE;
744
750
    validate_cpu - validate CPUs and memory maps
745
751
-------------------------------------------------*/
746
752
 
747
 
static int validate_cpu(int drivnum, const machine_config *config, const input_port_config *portlist, region_info *rgninfo)
 
753
static int validate_cpu(int drivnum, const machine_config *config)
748
754
{
749
755
        const game_driver *driver = drivers[drivnum];
750
756
        cpu_validity_check_func cpu_validity_check;
755
761
        for (device = cpu_first(config); device != NULL; device = cpu_next(device))
756
762
        {
757
763
                const cpu_config *cpuconfig = (const cpu_config *)device->inline_config;
758
 
                int spacenum;
759
764
 
760
765
                /* check the CPU for incompleteness */
761
766
                if (device_get_info_fct(device, CPUINFO_FCT_RESET) == NULL ||
771
776
                if (cpu_validity_check != NULL && (*cpu_validity_check)(driver, device->static_config))
772
777
                        error = TRUE;
773
778
 
774
 
                /* loop over all address spaces */
775
 
                for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++)
776
 
                {
777
 
#define SPACE_SHIFT(a)          ((addr_shift < 0) ? ((a) << -addr_shift) : ((a) >> addr_shift))
778
 
#define SPACE_SHIFT_END(a)      ((addr_shift < 0) ? (((a) << -addr_shift) | ((1 << -addr_shift) - 1)) : ((a) >> addr_shift))
779
 
                        int databus_width = cpu_get_databus_width(device, spacenum);
780
 
                        int addr_shift = cpu_get_addrbus_shift(device, spacenum);
781
 
                        int alignunit = databus_width/8;
782
 
                        address_map_entry *entry;
783
 
                        address_map *map;
784
 
 
785
 
                        /* construct the maps */
786
 
                        map = address_map_alloc(device, driver, spacenum);
787
 
 
788
 
                        /* if this is an empty map, just skip it */
789
 
                        if (map->entrylist == NULL)
790
 
                        {
791
 
                                address_map_free(map);
792
 
                                continue;
793
 
                        }
794
 
 
795
 
                        /* validate the global map parameters */
796
 
                        if (map->spacenum != spacenum)
797
 
                        {
798
 
                                mame_printf_error("%s: %s CPU '%s' space %d has address space %d handlers!\n", driver->source_file, driver->name, device->tag, spacenum, map->spacenum);
799
 
                                error = TRUE;
800
 
                        }
801
 
                        if (map->databits != databus_width)
802
 
                        {
803
 
                                mame_printf_error("%s: %s cpu '%s' uses wrong memory handlers for %s space! (width = %d, memory = %08x)\n", driver->source_file, driver->name, device->tag, address_space_names[spacenum], databus_width, map->databits);
804
 
                                error = TRUE;
805
 
                        }
806
 
 
807
 
                        /* loop over entries and look for errors */
808
 
                        for (entry = map->entrylist; entry != NULL; entry = entry->next)
809
 
                        {
810
 
                                UINT32 bytestart = SPACE_SHIFT(entry->addrstart);
811
 
                                UINT32 byteend = SPACE_SHIFT_END(entry->addrend);
812
 
 
813
 
                                /* look for inverted start/end pairs */
814
 
                                if (byteend < bytestart)
815
 
                                {
816
 
                                        mame_printf_error("%s: %s wrong %s memory read handler start = %08x > end = %08x\n", driver->source_file, driver->name, address_space_names[spacenum], entry->addrstart, entry->addrend);
817
 
                                        error = TRUE;
818
 
                                }
819
 
 
820
 
                                /* look for misaligned entries */
821
 
                                if ((bytestart & (alignunit - 1)) != 0 || (byteend & (alignunit - 1)) != (alignunit - 1))
822
 
                                {
823
 
                                        mame_printf_error("%s: %s wrong %s memory read handler start = %08x, end = %08x ALIGN = %d\n", driver->source_file, driver->name, address_space_names[spacenum], entry->addrstart, entry->addrend, alignunit);
824
 
                                        error = TRUE;
825
 
                                }
826
 
 
827
 
                                /* if this is a program space, auto-assign implicit ROM entries */
828
 
                                if ((FPTR)entry->read.generic == STATIC_ROM && entry->region == NULL)
829
 
                                {
830
 
                                        entry->region = device->tag;
831
 
                                        entry->rgnoffs = entry->addrstart;
832
 
                                }
833
 
 
834
 
                                /* if this entry references a memory region, validate it */
835
 
                                if (entry->region != NULL && entry->share == 0)
836
 
                                {
837
 
                                        int rgnnum;
838
 
 
839
 
                                        /* loop over entries in the class */
840
 
                                        for (rgnnum = 0; rgnnum < ARRAY_LENGTH(rgninfo->entries); rgnnum++)
841
 
                                        {
842
 
                                                /* stop if we hit an empty */
843
 
                                                if (rgninfo->entries[rgnnum].tag == NULL)
844
 
                                                {
845
 
                                                        mame_printf_error("%s: %s CPU '%s' %s space memory map entry %X-%X references non-existant region '%s'\n", driver->source_file, driver->name, device->tag, address_space_names[spacenum], entry->addrstart, entry->addrend, entry->region);
846
 
                                                        error = TRUE;
847
 
                                                        break;
848
 
                                                }
849
 
 
850
 
                                                /* if we hit a match, check against the length */
851
 
                                                if (astring_cmpc(rgninfo->entries[rgnnum].tag, entry->region) == 0)
852
 
                                                {
853
 
                                                        offs_t length = rgninfo->entries[rgnnum].length;
854
 
                                                        if (entry->rgnoffs + (byteend - bytestart + 1) > length)
855
 
                                                        {
856
 
                                                                mame_printf_error("%s: %s CPU '%s' %s space memory map entry %X-%X extends beyond region '%s' size (%X)\n", driver->source_file, driver->name, device->tag, address_space_names[spacenum], entry->addrstart, entry->addrend, entry->region, length);
857
 
                                                                error = TRUE;
858
 
                                                        }
859
 
                                                        break;
860
 
                                                }
861
 
                                        }
862
 
                                }
863
 
 
864
 
                                /* make sure all devices exist */
865
 
                                if (entry->read_devtag != NULL && device_list_find_by_tag(config->devicelist, entry->read_devtag) == NULL)
866
 
                                {
867
 
                                        mame_printf_error("%s: %s CPU '%s' %s space memory map entry references nonexistant device '%s'\n", driver->source_file, driver->name, device->tag, address_space_names[spacenum], entry->read_devtag);
868
 
                                        error = TRUE;
869
 
                                }
870
 
                                if (entry->write_devtag != NULL && device_list_find_by_tag(config->devicelist, entry->write_devtag) == NULL)
871
 
                                {
872
 
                                        mame_printf_error("%s: %s CPU '%s' %s space memory map entry references nonexistant device '%s'\n", driver->source_file, driver->name, device->tag, address_space_names[spacenum], entry->write_devtag);
873
 
                                        error = TRUE;
874
 
                                }
875
 
 
876
 
                                /* make sure ports exist */
877
 
                                if (entry->read_porttag != NULL && input_port_by_tag(portlist, entry->read_porttag) == NULL)
878
 
                                {
879
 
                                        mame_printf_error("%s: %s CPU '%s' %s space memory map entry references nonexistant port tag '%s'\n", driver->source_file, driver->name, device->tag, address_space_names[spacenum], entry->read_porttag);
880
 
                                        error = TRUE;
881
 
                                }
882
 
                        }
883
 
 
884
 
                        /* release the address map */
885
 
                        address_map_free(map);
886
 
 
887
 
                        /* validate the interrupts */
888
 
                        if (cpuconfig->vblank_interrupt != NULL)
889
 
                        {
890
 
                                if (video_screen_count(config) == 0)
891
 
                                {
892
 
                                        mame_printf_error("%s: %s cpu '%s' has a VBLANK interrupt, but the driver is screenless !\n", driver->source_file, driver->name, device->tag);
893
 
                                        error = TRUE;
894
 
                                }
895
 
                                else if (cpuconfig->vblank_interrupt_screen != NULL && cpuconfig->vblank_interrupts_per_frame != 0)
896
 
                                {
897
 
                                        mame_printf_error("%s: %s cpu '%s' has a new VBLANK interrupt handler with >1 interrupts!\n", driver->source_file, driver->name, device->tag);
898
 
                                        error = TRUE;
899
 
                                }
900
 
                                else if (cpuconfig->vblank_interrupt_screen != NULL && device_list_find_by_tag(config->devicelist, cpuconfig->vblank_interrupt_screen) == NULL)
901
 
                                {
902
 
                                        mame_printf_error("%s: %s cpu '%s' VBLANK interrupt with a non-existant screen tag (%s)!\n", driver->source_file, driver->name, device->tag, cpuconfig->vblank_interrupt_screen);
903
 
                                        error = TRUE;
904
 
                                }
905
 
                                else if (cpuconfig->vblank_interrupt_screen == NULL && cpuconfig->vblank_interrupts_per_frame == 0)
906
 
                                {
907
 
                                        mame_printf_error("%s: %s cpu '%s' has a VBLANK interrupt handler with 0 interrupts!\n", driver->source_file, driver->name, device->tag);
908
 
                                        error = TRUE;
909
 
                                }
910
 
                        }
911
 
                        else if (cpuconfig->vblank_interrupts_per_frame != 0)
912
 
                        {
913
 
                                mame_printf_error("%s: %s cpu '%s' has no VBLANK interrupt handler but a non-0 interrupt count is given!\n", driver->source_file, driver->name, device->tag);
914
 
                                error = TRUE;
915
 
                        }
916
 
 
917
 
                        if (cpuconfig->timed_interrupt != NULL && cpuconfig->timed_interrupt_period == 0)
918
 
                        {
919
 
                                mame_printf_error("%s: %s cpu '%s' has a timer interrupt handler with 0 period!\n", driver->source_file, driver->name, device->tag);
920
 
                                error = TRUE;
921
 
                        }
922
 
                        else if (cpuconfig->timed_interrupt == NULL && cpuconfig->timed_interrupt_period != 0)
923
 
                        {
924
 
                                mame_printf_error("%s: %s cpu '%s' has a no timer interrupt handler but has a non-0 period given!\n", driver->source_file, driver->name, device->tag);
925
 
                                error = TRUE;
926
 
                        }
 
779
                /* validate the interrupts */
 
780
                if (cpuconfig->vblank_interrupt != NULL)
 
781
                {
 
782
                        if (video_screen_count(config) == 0)
 
783
                        {
 
784
                                mame_printf_error("%s: %s cpu '%s' has a VBLANK interrupt, but the driver is screenless !\n", driver->source_file, driver->name, device->tag);
 
785
                                error = TRUE;
 
786
                        }
 
787
                        else if (cpuconfig->vblank_interrupt_screen != NULL && cpuconfig->vblank_interrupts_per_frame != 0)
 
788
                        {
 
789
                                mame_printf_error("%s: %s cpu '%s' has a new VBLANK interrupt handler with >1 interrupts!\n", driver->source_file, driver->name, device->tag);
 
790
                                error = TRUE;
 
791
                        }
 
792
                        else if (cpuconfig->vblank_interrupt_screen != NULL && device_list_find_by_tag(config->devicelist, cpuconfig->vblank_interrupt_screen) == NULL)
 
793
                        {
 
794
                                mame_printf_error("%s: %s cpu '%s' VBLANK interrupt with a non-existant screen tag (%s)!\n", driver->source_file, driver->name, device->tag, cpuconfig->vblank_interrupt_screen);
 
795
                                error = TRUE;
 
796
                        }
 
797
                        else if (cpuconfig->vblank_interrupt_screen == NULL && cpuconfig->vblank_interrupts_per_frame == 0)
 
798
                        {
 
799
                                mame_printf_error("%s: %s cpu '%s' has a VBLANK interrupt handler with 0 interrupts!\n", driver->source_file, driver->name, device->tag);
 
800
                                error = TRUE;
 
801
                        }
 
802
                }
 
803
                else if (cpuconfig->vblank_interrupts_per_frame != 0)
 
804
                {
 
805
                        mame_printf_error("%s: %s cpu '%s' has no VBLANK interrupt handler but a non-0 interrupt count is given!\n", driver->source_file, driver->name, device->tag);
 
806
                        error = TRUE;
 
807
                }
 
808
 
 
809
                if (cpuconfig->timed_interrupt != NULL && cpuconfig->timed_interrupt_period == 0)
 
810
                {
 
811
                        mame_printf_error("%s: %s cpu '%s' has a timer interrupt handler with 0 period!\n", driver->source_file, driver->name, device->tag);
 
812
                        error = TRUE;
 
813
                }
 
814
                else if (cpuconfig->timed_interrupt == NULL && cpuconfig->timed_interrupt_period != 0)
 
815
                {
 
816
                        mame_printf_error("%s: %s cpu '%s' has a no timer interrupt handler but has a non-0 period given!\n", driver->source_file, driver->name, device->tag);
 
817
                        error = TRUE;
927
818
                }
928
819
        }
929
820
 
1118
1009
    strings
1119
1010
-------------------------------------------------*/
1120
1011
 
1121
 
static int get_defstr_index(const char *name, const game_driver *driver, int *error)
 
1012
static int get_defstr_index(quark_table *defstr_table, const char *name, const game_driver *driver, int *error)
1122
1013
{
1123
1014
        UINT32 crc = quark_string_crc(name);
1124
1015
        quark_entry *entry;
1257
1148
    setting
1258
1149
-------------------------------------------------*/
1259
1150
 
1260
 
static void validate_dip_settings(const input_field_config *field, const game_driver *driver, int *error)
 
1151
static void validate_dip_settings(const input_field_config *field, const game_driver *driver, quark_table *defstr_table, int *error)
1261
1152
{
1262
1153
        const char *demo_sounds = input_port_string_from_index(INPUT_STRING_Demo_Sounds);
1263
1154
        const char *flipscreen = input_port_string_from_index(INPUT_STRING_Flip_Screen);
1268
1159
        /* iterate through the settings */
1269
1160
        for (setting = field->settinglist; setting != NULL; setting = setting->next)
1270
1161
        {
1271
 
                int strindex = get_defstr_index(setting->name, driver, error);
 
1162
                int strindex = get_defstr_index(defstr_table, setting->name, driver, error);
1272
1163
 
1273
1164
                /* note any coinage strings */
1274
1165
                if (strindex >= INPUT_STRING_9C_1C && strindex <= INPUT_STRING_1C_9C)
1298
1189
                /* if we have a neighbor, compare ourselves to him */
1299
1190
                if (setting->next != NULL)
1300
1191
                {
1301
 
                        int next_strindex = get_defstr_index(setting->next->name, driver, error);
 
1192
                        int next_strindex = get_defstr_index(defstr_table, setting->next->name, driver, error);
1302
1193
 
1303
1194
                        /* check for inverted off/on dispswitch order */
1304
1195
                        if (strindex == INPUT_STRING_On && next_strindex == INPUT_STRING_Off)
1348
1239
    validate_inputs - validate input configuration
1349
1240
-------------------------------------------------*/
1350
1241
 
1351
 
static int validate_inputs(int drivnum, const machine_config *config, const input_port_config **portlistptr)
 
1242
static int validate_inputs(int drivnum, const machine_config *config, quark_table *defstr_table, const input_port_config **portlistptr)
1352
1243
{
1353
1244
        const input_port_config *scanport;
1354
1245
        const input_port_config *port;
1402
1293
                                }
1403
1294
 
1404
1295
                                /* verify the settings list */
1405
 
                                validate_dip_settings(field, driver, &error);
 
1296
                                validate_dip_settings(field, driver, defstr_table, &error);
1406
1297
                        }
1407
1298
 
1408
1299
                        /* look for invalid (0) types which should be mapped to IPT_OTHER */
1437
1328
                                }
1438
1329
 
1439
1330
                                /* look up the string and print an error if default strings are not used */
1440
 
                                /*strindex = */get_defstr_index(field->name, driver, &error);
 
1331
                                /*strindex = */get_defstr_index(defstr_table, field->name, driver, &error);
1441
1332
                        }
1442
1333
 
1443
1334
                        /* verify conditions on the field */
1555
1446
    checks
1556
1447
-------------------------------------------------*/
1557
1448
 
1558
 
static int validate_devices(int drivnum, const machine_config *config)
 
1449
static int validate_devices(int drivnum, const machine_config *config, const input_port_config *portlist, region_info *rgninfo)
1559
1450
{
1560
1451
        int error = FALSE;
1561
1452
        const game_driver *driver = drivers[drivnum];
1565
1456
        {
1566
1457
                device_validity_check_func validity_check = (device_validity_check_func) device_get_info_fct(device, DEVINFO_FCT_VALIDITY_CHECK);
1567
1458
                const device_config *scandevice;
 
1459
                int spacenum;
1568
1460
 
1569
1461
                /* validate the device tag */
1570
1462
                error |= validate_tag(driver, device_get_info_string(device, DEVINFO_STR_NAME), device->tag);
1580
1472
                /* call the device-specific validity check */
1581
1473
                if (validity_check != NULL && (*validity_check)(driver, device))
1582
1474
                        error = TRUE;
 
1475
 
 
1476
                /* loop over all address spaces */
 
1477
                for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++)
 
1478
                {
 
1479
#define SPACE_SHIFT(a)          ((addr_shift < 0) ? ((a) << -addr_shift) : ((a) >> addr_shift))
 
1480
#define SPACE_SHIFT_END(a)      ((addr_shift < 0) ? (((a) << -addr_shift) | ((1 << -addr_shift) - 1)) : ((a) >> addr_shift))
 
1481
                        int databus_width = device_get_databus_width(device, spacenum);
 
1482
                        int addr_shift = device_get_addrbus_shift(device, spacenum);
 
1483
                        int alignunit = databus_width/8;
 
1484
                        address_map_entry *entry;
 
1485
                        address_map *map;
 
1486
 
 
1487
                        /* construct the maps */
 
1488
                        map = address_map_alloc(device, driver, spacenum);
 
1489
 
 
1490
                        /* if this is an empty map, just skip it */
 
1491
                        if (map->entrylist == NULL)
 
1492
                        {
 
1493
                                address_map_free(map);
 
1494
                                continue;
 
1495
                        }
 
1496
 
 
1497
                        /* validate the global map parameters */
 
1498
                        if (map->spacenum != spacenum)
 
1499
                        {
 
1500
                                mame_printf_error("%s: %s device '%s' space %d has address space %d handlers!\n", driver->source_file, driver->name, device->tag, spacenum, map->spacenum);
 
1501
                                error = TRUE;
 
1502
                        }
 
1503
                        if (map->databits != databus_width)
 
1504
                        {
 
1505
                                mame_printf_error("%s: %s device '%s' uses wrong memory handlers for %s space! (width = %d, memory = %08x)\n", driver->source_file, driver->name, device->tag, address_space_names[spacenum], databus_width, map->databits);
 
1506
                                error = TRUE;
 
1507
                        }
 
1508
 
 
1509
                        /* loop over entries and look for errors */
 
1510
                        for (entry = map->entrylist; entry != NULL; entry = entry->next)
 
1511
                        {
 
1512
                                UINT32 bytestart = SPACE_SHIFT(entry->addrstart);
 
1513
                                UINT32 byteend = SPACE_SHIFT_END(entry->addrend);
 
1514
 
 
1515
                                /* look for inverted start/end pairs */
 
1516
                                if (byteend < bytestart)
 
1517
                                {
 
1518
                                        mame_printf_error("%s: %s wrong %s memory read handler start = %08x > end = %08x\n", driver->source_file, driver->name, address_space_names[spacenum], entry->addrstart, entry->addrend);
 
1519
                                        error = TRUE;
 
1520
                                }
 
1521
 
 
1522
                                /* look for misaligned entries */
 
1523
                                if ((bytestart & (alignunit - 1)) != 0 || (byteend & (alignunit - 1)) != (alignunit - 1))
 
1524
                                {
 
1525
                                        mame_printf_error("%s: %s wrong %s memory read handler start = %08x, end = %08x ALIGN = %d\n", driver->source_file, driver->name, address_space_names[spacenum], entry->addrstart, entry->addrend, alignunit);
 
1526
                                        error = TRUE;
 
1527
                                }
 
1528
 
 
1529
                                /* if this is a program space, auto-assign implicit ROM entries */
 
1530
                                if ((FPTR)entry->read.generic == STATIC_ROM && entry->region == NULL)
 
1531
                                {
 
1532
                                        entry->region = device->tag;
 
1533
                                        entry->rgnoffs = entry->addrstart;
 
1534
                                }
 
1535
 
 
1536
                                /* if this entry references a memory region, validate it */
 
1537
                                if (entry->region != NULL && entry->share == 0)
 
1538
                                {
 
1539
                                        int rgnnum;
 
1540
 
 
1541
                                        /* loop over entries in the class */
 
1542
                                        for (rgnnum = 0; rgnnum < ARRAY_LENGTH(rgninfo->entries); rgnnum++)
 
1543
                                        {
 
1544
                                                /* stop if we hit an empty */
 
1545
                                                if (rgninfo->entries[rgnnum].tag == NULL)
 
1546
                                                {
 
1547
                                                        mame_printf_error("%s: %s device '%s' %s space memory map entry %X-%X references non-existant region '%s'\n", driver->source_file, driver->name, device->tag, address_space_names[spacenum], entry->addrstart, entry->addrend, entry->region);
 
1548
                                                        error = TRUE;
 
1549
                                                        break;
 
1550
                                                }
 
1551
 
 
1552
                                                /* if we hit a match, check against the length */
 
1553
                                                if (astring_cmpc(rgninfo->entries[rgnnum].tag, entry->region) == 0)
 
1554
                                                {
 
1555
                                                        offs_t length = rgninfo->entries[rgnnum].length;
 
1556
                                                        if (entry->rgnoffs + (byteend - bytestart + 1) > length)
 
1557
                                                        {
 
1558
                                                                mame_printf_error("%s: %s device '%s' %s space memory map entry %X-%X extends beyond region '%s' size (%X)\n", driver->source_file, driver->name, device->tag, address_space_names[spacenum], entry->addrstart, entry->addrend, entry->region, length);
 
1559
                                                                error = TRUE;
 
1560
                                                        }
 
1561
                                                        break;
 
1562
                                                }
 
1563
                                        }
 
1564
                                }
 
1565
 
 
1566
                                /* make sure all devices exist */
 
1567
                                if (entry->read_devtag != NULL && device_list_find_by_tag(config->devicelist, entry->read_devtag) == NULL)
 
1568
                                {
 
1569
                                        mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant device '%s'\n", driver->source_file, driver->name, device->tag, address_space_names[spacenum], entry->read_devtag);
 
1570
                                        error = TRUE;
 
1571
                                }
 
1572
                                if (entry->write_devtag != NULL && device_list_find_by_tag(config->devicelist, entry->write_devtag) == NULL)
 
1573
                                {
 
1574
                                        mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant device '%s'\n", driver->source_file, driver->name, device->tag, address_space_names[spacenum], entry->write_devtag);
 
1575
                                        error = TRUE;
 
1576
                                }
 
1577
 
 
1578
                                /* make sure ports exist */
 
1579
                                if (entry->read_porttag != NULL && input_port_by_tag(portlist, entry->read_porttag) == NULL)
 
1580
                                {
 
1581
                                        mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant port tag '%s'\n", driver->source_file, driver->name, device->tag, address_space_names[spacenum], entry->read_porttag);
 
1582
                                        error = TRUE;
 
1583
                                }
 
1584
                        }
 
1585
 
 
1586
                        /* release the address map */
 
1587
                        address_map_free(map);
 
1588
                }
1583
1589
        }
1584
1590
        return error;
1585
1591
}
1591
1597
 
1592
1598
int mame_validitychecks(const game_driver *curdriver)
1593
1599
{
 
1600
        quark_tables tables;
1594
1601
        osd_ticks_t prep = 0;
1595
1602
        osd_ticks_t expansion = 0;
1596
1603
        osd_ticks_t driver_checks = 0;
1641
1648
 
1642
1649
        init_resource_tracking();
1643
1650
        begin_resource_tracking();
1644
 
        osd_profiling_ticks();
 
1651
        get_profile_ticks();
1645
1652
 
1646
1653
        /* prepare by pre-scanning all the drivers and adding their info to hash tables */
1647
 
        prep -= osd_profiling_ticks();
1648
 
        quark_tables_create();
1649
 
        prep += osd_profiling_ticks();
 
1654
        prep -= get_profile_ticks();
 
1655
        quark_tables_create(&tables);
 
1656
        prep += get_profile_ticks();
1650
1657
 
1651
1658
        /* iterate over all drivers */
1652
1659
        for (drivnum = 0; drivers[drivnum]; drivnum++)
1663
1670
                memset(&rgninfo, 0, sizeof(rgninfo));
1664
1671
 
1665
1672
                /* expand the machine driver */
1666
 
                expansion -= osd_profiling_ticks();
 
1673
                expansion -= get_profile_ticks();
1667
1674
                config = machine_config_alloc(driver->machine_config);
1668
 
                expansion += osd_profiling_ticks();
 
1675
                expansion += get_profile_ticks();
1669
1676
 
1670
1677
                /* validate the driver entry */
1671
 
                driver_checks -= osd_profiling_ticks();
1672
 
                error = validate_driver(drivnum, config) || error;
1673
 
                driver_checks += osd_profiling_ticks();
 
1678
                driver_checks -= get_profile_ticks();
 
1679
                error = validate_driver(drivnum, config, &tables) || error;
 
1680
                driver_checks += get_profile_ticks();
1674
1681
 
1675
1682
                /* validate the ROM information */
1676
 
                rom_checks -= osd_profiling_ticks();
 
1683
                rom_checks -= get_profile_ticks();
1677
1684
                error = validate_roms(drivnum, config, &rgninfo) || error;
1678
 
                rom_checks += osd_profiling_ticks();
 
1685
                rom_checks += get_profile_ticks();
1679
1686
 
1680
1687
                /* validate input ports */
1681
 
                input_checks -= osd_profiling_ticks();
1682
 
                error = validate_inputs(drivnum, config, &portlist) || error;
1683
 
                input_checks += osd_profiling_ticks();
 
1688
                input_checks -= get_profile_ticks();
 
1689
                error = validate_inputs(drivnum, config, tables.defstr, &portlist) || error;
 
1690
                input_checks += get_profile_ticks();
1684
1691
 
1685
1692
                /* validate the CPU information */
1686
 
                cpu_checks -= osd_profiling_ticks();
1687
 
                error = validate_cpu(drivnum, config, portlist, &rgninfo) || error;
1688
 
                cpu_checks += osd_profiling_ticks();
 
1693
                cpu_checks -= get_profile_ticks();
 
1694
                error = validate_cpu(drivnum, config) || error;
 
1695
                cpu_checks += get_profile_ticks();
1689
1696
 
1690
1697
                /* validate the display */
1691
 
                display_checks -= osd_profiling_ticks();
 
1698
                display_checks -= get_profile_ticks();
1692
1699
                error = validate_display(drivnum, config) || error;
1693
 
                display_checks += osd_profiling_ticks();
 
1700
                display_checks += get_profile_ticks();
1694
1701
 
1695
1702
                /* validate the graphics decoding */
1696
 
                gfx_checks -= osd_profiling_ticks();
 
1703
                gfx_checks -= get_profile_ticks();
1697
1704
                error = validate_gfx(drivnum, config, &rgninfo) || error;
1698
 
                gfx_checks += osd_profiling_ticks();
 
1705
                gfx_checks += get_profile_ticks();
1699
1706
 
1700
1707
                /* validate sounds and speakers */
1701
 
                sound_checks -= osd_profiling_ticks();
 
1708
                sound_checks -= get_profile_ticks();
1702
1709
                error = validate_sound(drivnum, config) || error;
1703
 
                sound_checks += osd_profiling_ticks();
 
1710
                sound_checks += get_profile_ticks();
1704
1711
 
1705
1712
                /* validate devices */
1706
 
                device_checks -= osd_profiling_ticks();
1707
 
                error = validate_devices(drivnum, config) || error;
1708
 
                device_checks += osd_profiling_ticks();
 
1713
                device_checks -= get_profile_ticks();
 
1714
                error = validate_devices(drivnum, config, portlist, &rgninfo) || error;
 
1715
                device_checks += get_profile_ticks();
1709
1716
 
1710
1717
                for (rgnnum = 0; rgnnum < ARRAY_LENGTH(rgninfo.entries); rgnnum++)
1711
1718
                        if (rgninfo.entries[rgnnum].tag != NULL)
1716
1723
        }
1717
1724
 
1718
1725
#ifdef MESS
1719
 
        mess_checks -= osd_profiling_ticks();
 
1726
        mess_checks -= get_profile_ticks();
1720
1727
        if (mess_validitychecks())
1721
1728
                error = TRUE;
1722
 
        mess_checks += osd_profiling_ticks();
 
1729
        mess_checks += get_profile_ticks();
1723
1730
#endif /* MESS */
1724
1731
 
1725
1732
#if (REPORT_TIMES)
1739
1746
 
1740
1747
        end_resource_tracking();
1741
1748
        exit_resource_tracking();
1742
 
        quark_tables_free();
 
1749
        quark_tables_free(&tables);
1743
1750
 
1744
1751
        return error;
1745
1752
}