From 90314f2bb4a88af3d4f6e09763de2c7a4de039ec Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 22 Dec 2011 13:01:48 +0000 Subject: [PATCH] Softlist support cleanup and addition of compatibility filtering [Miodrag Milanovic] --- src/emu/clifront.c | 381 +++++++++++++++++++++------------------------ src/emu/info.c | 14 +- src/emu/softlist.c | 346 +++++++++++++++++++--------------------- src/emu/softlist.h | 27 ++-- src/emu/uiswlist.c | 103 ++++++------ src/emu/uiswlist.h | 7 +- 6 files changed, 420 insertions(+), 458 deletions(-) diff --git a/src/emu/clifront.c b/src/emu/clifront.c index c5a5cbdddb8..cdbda539abe 100644 --- a/src/emu/clifront.c +++ b/src/emu/clifront.c @@ -189,55 +189,47 @@ int cli_frontend::execute(int argc, char **argv) for (device_t *swlists = config.devicelist().first(SOFTWARE_LIST); swlists != NULL; swlists = swlists->typenext()) { software_list_config *swlist = (software_list_config *)downcast(swlists)->inline_config(); - - for (int i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++) + software_list *list = software_list_open(m_options, swlist->list_name, FALSE, NULL); + if (list) { - if (swlist->list_name[i] && *swlist->list_name[i]) - { - software_list *list = software_list_open(m_options, swlist->list_name[i], FALSE, NULL); - - if (list) + software_info *swinfo = software_list_find(list, m_options.software_name(), NULL); + if (swinfo!=NULL) { + for (software_part *swpart = software_find_part(swinfo, NULL, NULL); swpart != NULL; swpart = software_part_next(swpart)) { - software_info *swinfo = software_list_find(list, m_options.software_name(), NULL); - if (swinfo!=NULL) { - for (software_part *swpart = software_find_part(swinfo, NULL, NULL); swpart != NULL; swpart = software_part_next(swpart)) + const char *mount = software_part_get_feature(swpart, "automount"); + if (mount==NULL || strcmp(mount,"no")!=0) { + // loop trough all parts + // search for a device with the right interface + const device_image_interface *image = NULL; + for (bool gotone = config.devicelist().first(image); gotone; gotone = image->next(image)) { - const char *mount = software_part_get_feature(swpart, "automount"); - if (mount==NULL || strcmp(mount,"no")!=0) { - // loop trough all parts - // search for a device with the right interface - const device_image_interface *image = NULL; - for (bool gotone = config.devicelist().first(image); gotone; gotone = image->next(image)) + const char *interface = image->image_interface(); + if (interface != NULL) + { + if (!strcmp(interface, swpart->interface_)) { - const char *interface = image->image_interface(); - if (interface != NULL) - { - if (!strcmp(interface, swpart->interface_)) - { - const char *option = m_options.value(image->brief_instance_name()); - // mount only if not already mounted - if (strlen(option)==0) { - astring val; - val.printf("%s:%s:%s",swlist->list_name[i],m_options.software_name(),swpart->name); - // call this in order to set slot devices according to mounting - m_options.parse_slot_devices(argc, argv, option_errors, image->instance_name(), val.cstr()); - } - break; - } + const char *option = m_options.value(image->brief_instance_name()); + // mount only if not already mounted + if (strlen(option)==0) { + astring val; + val.printf("%s:%s:%s",swlist->list_name,m_options.software_name(),swpart->name); + // call this in order to set slot devices according to mounting + m_options.parse_slot_devices(argc, argv, option_errors, image->instance_name(), val.cstr()); } + break; } } } - software_list_close(list); - found = TRUE; - break; } - } software_list_close(list); + found = TRUE; + break; } - if (found) break; + } + software_list_close(list); + if (found) break; } if (!found) { @@ -1000,10 +992,8 @@ void cli_frontend::listsoftware(const char *gamename) for (const device_t *dev = drivlist.config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext()) { software_list_config *swlist = (software_list_config *)downcast(dev)->inline_config(); - - for (int listnum = 0; listnum < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; listnum++) - if (swlist->list_name[listnum] && *swlist->list_name[listnum] && swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) - list_count++; + if (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) + list_count++; } // allocate a list @@ -1088,162 +1078,159 @@ void cli_frontend::listsoftware(const char *gamename) { software_list_config *swlist = (software_list_config *)downcast(dev)->inline_config(); - for (int listnum = 0; listnum < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; listnum++) + if (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) { - if (swlist->list_name[listnum] && *swlist->list_name[listnum] && swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) + software_list *list = software_list_open(m_options, swlist->list_name, FALSE, NULL); + + if ( list ) { - software_list *list = software_list_open(m_options, swlist->list_name[listnum], FALSE, NULL); + /* Verify if we have encountered this list before */ + bool seen_before = false; + for (int seen_index = 0; seen_index < list_count && !seen_before; seen_index++) + if (lists[seen_index] == swlist->list_name) + seen_before = true; - if ( list ) + if (!seen_before) { - /* Verify if we have encountered this list before */ - bool seen_before = false; - for (int seen_index = 0; seen_index < list_count && !seen_before; seen_index++) - if (lists[seen_index] == swlist->list_name[listnum]) - seen_before = true; + lists[list_count++] = swlist->list_name; + software_list_parse( list, NULL, NULL ); - if (!seen_before) + fprintf(out, "\t\n", swlist->list_name, xml_normalize_string(software_list_get_description(list)) ); + + for ( software_info *swinfo = software_list_find( list, "*", NULL ); swinfo != NULL; swinfo = software_list_find( list, "*", swinfo ) ) { - lists[list_count++] = swlist->list_name[listnum]; - software_list_parse( list, NULL, NULL ); + fprintf( out, "\t\tshortname ); + if ( swinfo->parentname != NULL ) + fprintf( out, " cloneof=\"%s\"", swinfo->parentname ); + if ( swinfo->supported == SOFTWARE_SUPPORTED_PARTIAL ) + fprintf( out, " supported=\"partial\"" ); + if ( swinfo->supported == SOFTWARE_SUPPORTED_NO ) + fprintf( out, " supported=\"no\"" ); + fprintf( out, ">\n" ); + fprintf( out, "\t\t\t%s\n", xml_normalize_string(swinfo->longname) ); + fprintf( out, "\t\t\t%s\n", xml_normalize_string( swinfo->year ) ); + fprintf( out, "\t\t\t%s\n", xml_normalize_string( swinfo->publisher ) ); - fprintf(out, "\t\n", swlist->list_name[listnum], xml_normalize_string(software_list_get_description(list)) ); - - for ( software_info *swinfo = software_list_find( list, "*", NULL ); swinfo != NULL; swinfo = software_list_find( list, "*", swinfo ) ) + for ( software_part *part = software_find_part( swinfo, NULL, NULL ); part != NULL; part = software_part_next( part ) ) { - fprintf( out, "\t\tshortname ); - if ( swinfo->parentname != NULL ) - fprintf( out, " cloneof=\"%s\"", swinfo->parentname ); - if ( swinfo->supported == SOFTWARE_SUPPORTED_PARTIAL ) - fprintf( out, " supported=\"partial\"" ); - if ( swinfo->supported == SOFTWARE_SUPPORTED_NO ) - fprintf( out, " supported=\"no\"" ); - fprintf( out, ">\n" ); - fprintf( out, "\t\t\t%s\n", xml_normalize_string(swinfo->longname) ); - fprintf( out, "\t\t\t%s\n", xml_normalize_string( swinfo->year ) ); - fprintf( out, "\t\t\t%s\n", xml_normalize_string( swinfo->publisher ) ); + fprintf( out, "\t\t\tname ); + if ( part->interface_ ) + fprintf( out, " interface=\"%s\"", part->interface_ ); - for ( software_part *part = software_find_part( swinfo, NULL, NULL ); part != NULL; part = software_part_next( part ) ) + fprintf( out, ">\n"); + + if ( part->featurelist ) { - fprintf( out, "\t\t\tname ); - if ( part->interface_ ) - fprintf( out, " interface=\"%s\"", part->interface_ ); + feature_list *flist = part->featurelist; - fprintf( out, ">\n"); - - if ( part->featurelist ) + while( flist ) { - feature_list *flist = part->featurelist; - - while( flist ) - { - fprintf( out, "\t\t\t\t\n", flist->name, flist->value ); - flist = flist->next; - } + fprintf( out, "\t\t\t\t\n", flist->name, flist->value ); + flist = flist->next; } - - /* TODO: display rom region information */ - for ( const rom_entry *region = part->romdata; region; region = rom_next_region( region ) ) - { - int is_disk = ROMREGION_ISDISKDATA(region); - - if (!is_disk) - fprintf( out, "\t\t\t\t\n", ROMREGION_GETTAG(region), ROMREGION_GETLENGTH(region) ); - else - fprintf( out, "\t\t\t\t\n", ROMREGION_GETTAG(region) ); - - for ( const rom_entry *rom = rom_first_file( region ); rom && !ROMENTRY_ISREGIONEND(rom); rom++ ) - { - if ( ROMENTRY_ISFILE(rom) ) - { - if (!is_disk) - fprintf( out, "\t\t\t\t\tnext()) - fprintf(out, " %s=\"%s\"", hash->name(), hash->string(tempstr)); - } - - if (!is_disk) - fprintf( out, " offset=\"0x%x\"", ROM_GETOFFSET(rom) ); - - if ( hashes.flag(hash_collection::FLAG_BAD_DUMP) ) - fprintf( out, " status=\"baddump\"" ); - if ( hashes.flag(hash_collection::FLAG_NO_DUMP) ) - fprintf( out, " status=\"nodump\"" ); - - if (is_disk) - fprintf( out, " writeable=\"%s\"", (ROM_GETFLAGS(rom) & DISK_READONLYMASK) ? "no" : "yes"); - - if ((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(1)) - fprintf( out, " loadflag=\"load16_byte\"" ); - - if ((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(3)) - fprintf( out, " loadflag=\"load32_byte\"" ); - - if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(2)) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD)) - { - if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK)) - fprintf( out, " loadflag=\"load32_word\"" ); - else - fprintf( out, " loadflag=\"load32_word_swap\"" ); - } - - if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(6)) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD)) - { - if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK)) - fprintf( out, " loadflag=\"load64_word\"" ); - else - fprintf( out, " loadflag=\"load64_word_swap\"" ); - } - - if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_NOSKIP) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD)) - { - if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK)) - fprintf( out, " loadflag=\"load32_dword\"" ); - else - fprintf( out, " loadflag=\"load16_word_swap\"" ); - } - - fprintf( out, "/>\n" ); - } - else if ( ROMENTRY_ISRELOAD(rom) ) - { - fprintf( out, "\t\t\t\t\t\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) ); - } - else if ( ROMENTRY_ISCONTINUE(rom) ) - { - fprintf( out, "\t\t\t\t\t\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) ); - } - else if ( ROMENTRY_ISFILL(rom) ) - { - fprintf( out, "\t\t\t\t\t\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) ); - } - } - - if (!is_disk) - fprintf( out, "\t\t\t\t\n" ); - else - fprintf( out, "\t\t\t\t\n" ); - } - - fprintf( out, "\t\t\t\n" ); } - fprintf( out, "\t\t\n" ); + /* TODO: display rom region information */ + for ( const rom_entry *region = part->romdata; region; region = rom_next_region( region ) ) + { + int is_disk = ROMREGION_ISDISKDATA(region); + + if (!is_disk) + fprintf( out, "\t\t\t\t\n", ROMREGION_GETTAG(region), ROMREGION_GETLENGTH(region) ); + else + fprintf( out, "\t\t\t\t\n", ROMREGION_GETTAG(region) ); + + for ( const rom_entry *rom = rom_first_file( region ); rom && !ROMENTRY_ISREGIONEND(rom); rom++ ) + { + if ( ROMENTRY_ISFILE(rom) ) + { + if (!is_disk) + fprintf( out, "\t\t\t\t\tnext()) + fprintf(out, " %s=\"%s\"", hash->name(), hash->string(tempstr)); + } + + if (!is_disk) + fprintf( out, " offset=\"0x%x\"", ROM_GETOFFSET(rom) ); + + if ( hashes.flag(hash_collection::FLAG_BAD_DUMP) ) + fprintf( out, " status=\"baddump\"" ); + if ( hashes.flag(hash_collection::FLAG_NO_DUMP) ) + fprintf( out, " status=\"nodump\"" ); + + if (is_disk) + fprintf( out, " writeable=\"%s\"", (ROM_GETFLAGS(rom) & DISK_READONLYMASK) ? "no" : "yes"); + + if ((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(1)) + fprintf( out, " loadflag=\"load16_byte\"" ); + + if ((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(3)) + fprintf( out, " loadflag=\"load32_byte\"" ); + + if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(2)) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD)) + { + if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK)) + fprintf( out, " loadflag=\"load32_word\"" ); + else + fprintf( out, " loadflag=\"load32_word_swap\"" ); + } + + if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(6)) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD)) + { + if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK)) + fprintf( out, " loadflag=\"load64_word\"" ); + else + fprintf( out, " loadflag=\"load64_word_swap\"" ); + } + + if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_NOSKIP) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD)) + { + if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK)) + fprintf( out, " loadflag=\"load32_dword\"" ); + else + fprintf( out, " loadflag=\"load16_word_swap\"" ); + } + + fprintf( out, "/>\n" ); + } + else if ( ROMENTRY_ISRELOAD(rom) ) + { + fprintf( out, "\t\t\t\t\t\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) ); + } + else if ( ROMENTRY_ISCONTINUE(rom) ) + { + fprintf( out, "\t\t\t\t\t\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) ); + } + else if ( ROMENTRY_ISFILL(rom) ) + { + fprintf( out, "\t\t\t\t\t\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) ); + } + } + + if (!is_disk) + fprintf( out, "\t\t\t\t\n" ); + else + fprintf( out, "\t\t\t\t\n" ); + } + + fprintf( out, "\t\t\t\n" ); } - fprintf(out, "\t\n" ); + fprintf( out, "\t\t\n" ); } - software_list_close( list ); + fprintf(out, "\t\n" ); } + + software_list_close( list ); } } } @@ -1645,32 +1632,26 @@ int media_identifier::find_by_hash(const hash_collection &hashes, int length) for (const device_t *dev = m_drivlist.config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext()) { software_list_config *swlist = (software_list_config *)downcast(dev)->inline_config(); + software_list *list = software_list_open(m_drivlist.options(), swlist->list_name, FALSE, NULL); - for (int listnum = 0; listnum < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; listnum++) - if (swlist->list_name[listnum] != NULL) - { - software_list *list = software_list_open(m_drivlist.options(), swlist->list_name[listnum], FALSE, NULL); + for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) + for (software_part *part = software_find_part(swinfo, NULL, NULL); part != NULL; part = software_part_next(part)) + for (const rom_entry *region = part->romdata; region != NULL; region = rom_next_region(region)) + for (const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom)) + { + hash_collection romhashes(ROM_GETHASHDATA(rom)); + if (hashes == romhashes) + { + bool baddump = romhashes.flag(hash_collection::FLAG_BAD_DUMP); - for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) - for (software_part *part = software_find_part(swinfo, NULL, NULL); part != NULL; part = software_part_next(part)) - for (const rom_entry *region = part->romdata; region != NULL; region = rom_next_region(region)) - for (const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom)) - { - hash_collection romhashes(ROM_GETHASHDATA(rom)); - if (hashes == romhashes) - { - bool baddump = romhashes.flag(hash_collection::FLAG_BAD_DUMP); - - // output information about the match - if (found) - mame_printf_info(" "); - mame_printf_info("= %s%-20s %s:%s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), swlist->list_name[listnum], swinfo->shortname, swinfo->longname); - found++; - } - } - - software_list_close(list); - } + // output information about the match + if (found) + mame_printf_info(" "); + mame_printf_info("= %s%-20s %s:%s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), swlist->list_name, swinfo->shortname, swinfo->longname); + found++; + } + } + software_list_close(list); } } diff --git a/src/emu/info.c b/src/emu/info.c index 698f5d63e3e..6dd67cc9f34 100644 --- a/src/emu/info.c +++ b/src/emu/info.c @@ -181,6 +181,7 @@ const char info_xml_creator::s_dtd_string[] = "\t\t\n" "\t\t\t\n" "\t\t\t\n" +"\t\t\t\n" "\t\t\n" "\t\t\t\n" "]>"; @@ -1229,13 +1230,12 @@ void info_xml_creator::output_software_list() for (const device_t *dev = m_drivlist.config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext()) { software_list_config *swlist = (software_list_config *)downcast(dev)->inline_config(); - - for (int i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++) - if (swlist->list_name[i]) - { - fprintf(m_output, "\t\tlist_name[i]); - fprintf(m_output, "status=\"%s\" />\n", (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) ? "original" : "compatible"); - } + fprintf(m_output, "\t\tlist_name); + fprintf(m_output, "status=\"%s\" ", (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) ? "original" : "compatible"); + if (swlist->filter) { + fprintf(m_output, "filter=\"%s\" ", swlist->filter); + } + fprintf(m_output, "/>\n"); } } diff --git a/src/emu/softlist.c b/src/emu/softlist.c index ce1c3ab2f08..f8d1203b21c 100644 --- a/src/emu/softlist.c +++ b/src/emu/softlist.c @@ -1433,39 +1433,32 @@ void software_display_matches(const device_list &devlist,emu_options &options, c for (device_t *swlists = devlist.first(SOFTWARE_LIST); swlists != NULL; swlists = swlists->typenext()) { software_list_config *swlist = (software_list_config *)downcast(swlists)->inline_config(); + software_list *list = software_list_open(options, swlist->list_name, FALSE, NULL); - for (int i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++) + if (list) { - if (swlist->list_name[i] && *swlist->list_name[i]) + software_info *matches[10] = { 0 }; + int softnum; + + software_list_parse(list, list->error_proc, NULL); + // get the top 5 approximate matches for the selected device interface (i.e. only carts for cartslot, etc.) + software_list_find_approx_matches(list, name, ARRAY_LENGTH(matches), matches, interface); + + if (matches[0] != 0) { - software_list *list = software_list_open(options, swlist->list_name[i], FALSE, NULL); + if (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) + mame_printf_error("* Software list \"%s\" (%s) matches: \n", swlist->list_name, software_list_get_description(list)); + else + mame_printf_error("* Compatible software list \"%s\" (%s) matches: \n", swlist->list_name, software_list_get_description(list)); - if (list) - { - software_info *matches[10] = { 0 }; - int softnum; + // print them out + for (softnum = 0; softnum < ARRAY_LENGTH(matches); softnum++) + if (matches[softnum] != NULL) + mame_printf_error("%-18s%s\n", matches[softnum]->shortname, matches[softnum]->longname); - software_list_parse(list, list->error_proc, NULL); - // get the top 5 approximate matches for the selected device interface (i.e. only carts for cartslot, etc.) - software_list_find_approx_matches(list, name, ARRAY_LENGTH(matches), matches, interface); - - if (matches[0] != 0) - { - if (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) - mame_printf_error("* Software list \"%s\" (%s) matches: \n", swlist->list_name[i], software_list_get_description(list)); - else - mame_printf_error("* Compatible software list \"%s\" (%s) matches: \n", swlist->list_name[i], software_list_get_description(list)); - - // print them out - for (softnum = 0; softnum < ARRAY_LENGTH(matches); softnum++) - if (matches[softnum] != NULL) - mame_printf_error("%-18s%s\n", matches[softnum]->shortname, matches[softnum]->longname); - - mame_printf_error("\n"); - } - software_list_close(list); - } + mame_printf_error("\n"); } + software_list_close(list); } } } @@ -1508,32 +1501,28 @@ static void find_software_item(const device_list &devlist, emu_options &options, { software_list_config *swlist = (software_list_config *)downcast(swlists)->inline_config(); - UINT32 i = DEVINFO_STR_SWLIST_0; + + swlist_name = swlist->list_name; - while ( ! *software_part_ptr && i <= DEVINFO_STR_SWLIST_MAX ) + if (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) { - swlist_name = swlist->list_name[i-DEVINFO_STR_SWLIST_0]; - - if ( swlist_name && *swlist_name && (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM)) + if ( *software_list_ptr ) { - if ( *software_list_ptr ) + software_list_close( *software_list_ptr ); + } + + *software_list_ptr = software_list_open( options, swlist_name, FALSE, NULL ); + + if ( software_list_ptr ) + { + *software_info_ptr = software_list_find( *software_list_ptr, swname, NULL ); + + if ( *software_info_ptr ) { - software_list_close( *software_list_ptr ); - } - - *software_list_ptr = software_list_open( options, swlist_name, FALSE, NULL ); - - if ( software_list_ptr ) - { - *software_info_ptr = software_list_find( *software_list_ptr, swname, NULL ); - - if ( *software_info_ptr ) - { - *software_part_ptr = software_find_part( *software_info_ptr, swpart, interface ); - } + *software_part_ptr = software_find_part( *software_info_ptr, swpart, interface ); + break; } } - i++; } } } @@ -1811,9 +1800,8 @@ void validate_softlists(emu_options &options) { software_list_config *swlist = (software_list_config *)downcast(dev)->inline_config(); - for (int listnum = 0; listnum < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; listnum++) - if (swlist->list_name[listnum] && *swlist->list_name[listnum] && swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) - list_count++; + if (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) + list_count++; } // allocate a list @@ -1832,161 +1820,155 @@ void validate_softlists(emu_options &options) enum { NAME_LEN_PARENT = 8, NAME_LEN_CLONE = 16 }; - for (int i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++) + software_list *list = software_list_open(options, swlist->list_name, FALSE, NULL); + if ( list ) { - if (swlist->list_name[i]) + /* Verify if we have encountered this list before */ + bool seen_before = false; + for (int seen_index = 0; seen_index < list_count && !seen_before; seen_index++) + if (lists[seen_index] == swlist->list_name) + seen_before = true; + + if (!seen_before) { - software_list *list = software_list_open(options, swlist->list_name[i], FALSE, NULL); - if ( list ) + lists[list_count++] = swlist->list_name; + software_list_parse( list, &validate_error_proc, NULL ); + + for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) { - /* Verify if we have encountered this list before */ - bool seen_before = false; - for (int seen_index = 0; seen_index < list_count && !seen_before; seen_index++) - if (lists[seen_index] == swlist->list_name[i]) - seen_before = true; + const char *s; + int is_clone = 0; - if (!seen_before) + /* First, check if the xml got corrupted: */ + + /* Did we lost any description? */ + if (swinfo->longname == NULL) { - lists[list_count++] = swlist->list_name[i]; - software_list_parse( list, &validate_error_proc, NULL ); + mame_printf_error("%s: %s has no description\n", list->file->filename(), swinfo->shortname); + error = TRUE; break; + } - for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) + /* Did we lost any year? */ + if (swinfo->year == NULL) + { + mame_printf_error("%s: %s has no year\n", list->file->filename(), swinfo->shortname); + error = TRUE; break; + } + + /* Did we lost any publisher? */ + if (swinfo->publisher == NULL) + { + mame_printf_error("%s: %s has no publisher\n", list->file->filename(), swinfo->shortname); + error = TRUE; break; + } + + /* Second, since the xml is fine, run additional checks: */ + + /* check for duplicate names */ + if (names.add(swinfo->shortname, swinfo, FALSE) == TMERR_DUPLICATE) + { + software_info *match = names.find(swinfo->shortname); + mame_printf_error("%s: %s is a duplicate name (%s)\n", list->file->filename(), swinfo->shortname, match->shortname); + error = TRUE; + } + + /* check for duplicate descriptions */ + if (descriptions.add(astring(swinfo->longname).tolower().cstr(), swinfo, FALSE) == TMERR_DUPLICATE) + { + mame_printf_error("%s: %s is a duplicate description (%s)\n", list->file->filename(), swinfo->longname, swinfo->shortname); + error = TRUE; + } + + if (swinfo->parentname != NULL) + { + is_clone = 1; + + if (strcmp(swinfo->parentname, swinfo->shortname) == 0) { - const char *s; - int is_clone = 0; + mame_printf_error("%s: %s is set as a clone of itself\n", list->file->filename(), swinfo->shortname); + error = TRUE; + break; + } - /* First, check if the xml got corrupted: */ + /* make sure the parent exists */ + software_info *swinfo2 = software_list_find(list, swinfo->parentname, NULL ); - /* Did we lost any description? */ - if (swinfo->longname == NULL) + if (!swinfo2) + { + mame_printf_error("%s: parent '%s' software for '%s' not found\n", list->file->filename(), swinfo->parentname, swinfo->shortname); + error = TRUE; + } + else + { + if (swinfo2->parentname != NULL) { - mame_printf_error("%s: %s has no description\n", list->file->filename(), swinfo->shortname); - error = TRUE; break; - } - - /* Did we lost any year? */ - if (swinfo->year == NULL) - { - mame_printf_error("%s: %s has no year\n", list->file->filename(), swinfo->shortname); - error = TRUE; break; - } - - /* Did we lost any publisher? */ - if (swinfo->publisher == NULL) - { - mame_printf_error("%s: %s has no publisher\n", list->file->filename(), swinfo->shortname); - error = TRUE; break; - } - - /* Second, since the xml is fine, run additional checks: */ - - /* check for duplicate names */ - if (names.add(swinfo->shortname, swinfo, FALSE) == TMERR_DUPLICATE) - { - software_info *match = names.find(swinfo->shortname); - mame_printf_error("%s: %s is a duplicate name (%s)\n", list->file->filename(), swinfo->shortname, match->shortname); + mame_printf_error("%s: %s is a clone of a clone\n", list->file->filename(), swinfo->shortname); error = TRUE; } + } + } - /* check for duplicate descriptions */ - if (descriptions.add(astring(swinfo->longname).tolower().cstr(), swinfo, FALSE) == TMERR_DUPLICATE) + /* make sure the driver name is 8 chars or less */ + if ((is_clone && strlen(swinfo->shortname) > NAME_LEN_CLONE) || ((!is_clone) && strlen(swinfo->shortname) > NAME_LEN_PARENT)) + { + mame_printf_error("%s: %s %s driver name must be %d characters or less\n", list->file->filename(), swinfo->shortname, + is_clone ? "clone" : "parent", is_clone ? NAME_LEN_CLONE : NAME_LEN_PARENT); + error = TRUE; + } + + /* make sure the year is only digits, '?' or '+' */ + for (s = swinfo->year; *s; s++) + if (!isdigit((UINT8)*s) && *s != '?' && *s != '+') + { + mame_printf_error("%s: %s has an invalid year '%s'\n", list->file->filename(), swinfo->shortname, swinfo->year); + error = TRUE; + break; + } + + for (software_part *swpart = software_find_part(swinfo, NULL, NULL); swpart != NULL; swpart = software_part_next(swpart)) + { + if (swpart->interface_ == NULL) + { + mame_printf_error("%s: %s has a part (%s) without interface\n", list->file->filename(), swinfo->shortname, swpart->name); + error = TRUE; + } + + if (software_find_romdata(swpart, NULL) == NULL) + { + mame_printf_error("%s: %s has a part (%s) with no data\n", list->file->filename(), swinfo->shortname, swpart->name); + error = TRUE; + } + + for (struct rom_entry *swdata = software_find_romdata(swpart, NULL); swdata != NULL; swdata = software_romdata_next(swdata)) + { + struct rom_entry *data = swdata; + + if (data->_name && data->_hashdata) { - mame_printf_error("%s: %s is a duplicate description (%s)\n", list->file->filename(), swinfo->longname, swinfo->shortname); - error = TRUE; - } + const char *str; - if (swinfo->parentname != NULL) - { - is_clone = 1; - - if (strcmp(swinfo->parentname, swinfo->shortname) == 0) - { - mame_printf_error("%s: %s is set as a clone of itself\n", list->file->filename(), swinfo->shortname); - error = TRUE; - break; - } - - /* make sure the parent exists */ - software_info *swinfo2 = software_list_find(list, swinfo->parentname, NULL ); - - if (!swinfo2) - { - mame_printf_error("%s: parent '%s' software for '%s' not found\n", list->file->filename(), swinfo->parentname, swinfo->shortname); - error = TRUE; - } - else - { - if (swinfo2->parentname != NULL) + /* make sure it's all lowercase */ + for (str = data->_name; *str; str++) + if (tolower((UINT8)*str) != *str) { - mame_printf_error("%s: %s is a clone of a clone\n", list->file->filename(), swinfo->shortname); + mame_printf_error("%s: %s has upper case ROM name %s\n", list->file->filename(), swinfo->shortname, data->_name); error = TRUE; + break; } - } - } - /* make sure the driver name is 8 chars or less */ - if ((is_clone && strlen(swinfo->shortname) > NAME_LEN_CLONE) || ((!is_clone) && strlen(swinfo->shortname) > NAME_LEN_PARENT)) - { - mame_printf_error("%s: %s %s driver name must be %d characters or less\n", list->file->filename(), swinfo->shortname, - is_clone ? "clone" : "parent", is_clone ? NAME_LEN_CLONE : NAME_LEN_PARENT); - error = TRUE; - } - - /* make sure the year is only digits, '?' or '+' */ - for (s = swinfo->year; *s; s++) - if (!isdigit((UINT8)*s) && *s != '?' && *s != '+') + /* make sure the hash is valid */ + hash_collection hashes; + if (!hashes.from_internal_string(data->_hashdata)) { - mame_printf_error("%s: %s has an invalid year '%s'\n", list->file->filename(), swinfo->shortname, swinfo->year); + mame_printf_error("%s: %s has rom '%s' with an invalid hash string '%s'\n", list->file->filename(), swinfo->shortname, data->_name, data->_hashdata); error = TRUE; - break; - } - - for (software_part *swpart = software_find_part(swinfo, NULL, NULL); swpart != NULL; swpart = software_part_next(swpart)) - { - if (swpart->interface_ == NULL) - { - mame_printf_error("%s: %s has a part (%s) without interface\n", list->file->filename(), swinfo->shortname, swpart->name); - error = TRUE; - } - - if (software_find_romdata(swpart, NULL) == NULL) - { - mame_printf_error("%s: %s has a part (%s) with no data\n", list->file->filename(), swinfo->shortname, swpart->name); - error = TRUE; - } - - for (struct rom_entry *swdata = software_find_romdata(swpart, NULL); swdata != NULL; swdata = software_romdata_next(swdata)) - { - struct rom_entry *data = swdata; - - if (data->_name && data->_hashdata) - { - const char *str; - - /* make sure it's all lowercase */ - for (str = data->_name; *str; str++) - if (tolower((UINT8)*str) != *str) - { - mame_printf_error("%s: %s has upper case ROM name %s\n", list->file->filename(), swinfo->shortname, data->_name); - error = TRUE; - break; - } - - /* make sure the hash is valid */ - hash_collection hashes; - if (!hashes.from_internal_string(data->_hashdata)) - { - mame_printf_error("%s: %s has rom '%s' with an invalid hash string '%s'\n", list->file->filename(), swinfo->shortname, data->_name, data->_hashdata); - error = TRUE; - } - } } } } } - software_list_close(list); } } + software_list_close(list); } } } @@ -2013,14 +1995,6 @@ DEVICE_GET_INFO( software_list ) case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright MESS Team"); break; } - - if ( state >= DEVINFO_STR_SWLIST_0 && state <= DEVINFO_STR_SWLIST_MAX ) - { - software_list_config *config = (software_list_config *)downcast(device)->inline_config(); - - if ( config->list_name[ state - DEVINFO_STR_SWLIST_0 ] ) - strcpy(info->s, config->list_name[ state - DEVINFO_STR_SWLIST_0 ]); - } } diff --git a/src/emu/softlist.h b/src/emu/softlist.h index ab7c086dbfc..ce4f150cc35 100644 --- a/src/emu/softlist.h +++ b/src/emu/softlist.h @@ -130,44 +130,41 @@ DECLARE_LEGACY_DEVICE(SOFTWARE_LIST, software_list); #define SOFTWARE_SUPPORTED_PARTIAL 1 #define SOFTWARE_SUPPORTED_NO 2 - -#define SOFTWARE_LIST_CONFIG_SIZE 10 - - typedef struct _software_list_config software_list_config; struct _software_list_config { - char *list_name[SOFTWARE_LIST_CONFIG_SIZE]; + char *list_name; UINT32 list_type; + const char *filter; }; - -#define DEVINFO_STR_SWLIST_0 (DEVINFO_STR_DEVICE_SPECIFIC+0) -#define DEVINFO_STR_SWLIST_MAX (DEVINFO_STR_SWLIST_0 + SOFTWARE_LIST_CONFIG_SIZE - 1) - #define SOFTWARE_LIST_ORIGINAL_SYSTEM 0 #define SOFTWARE_LIST_COMPATIBLE_SYSTEM 1 -#define MCFG_SOFTWARE_LIST_CONFIG(_idx,_list,_list_type) \ - MCFG_DEVICE_CONFIG_DATAPTR_ARRAY(software_list_config, list_name, _idx, _list) \ +#define MCFG_SOFTWARE_LIST_CONFIG(_list,_list_type) \ + MCFG_DEVICE_CONFIG_DATAPTR(software_list_config, list_name, _list) \ MCFG_DEVICE_CONFIG_DATA32(software_list_config, list_type, _list_type) #define MCFG_SOFTWARE_LIST_ADD( _tag, _list ) \ MCFG_DEVICE_ADD( _tag, SOFTWARE_LIST, 0 ) \ - MCFG_SOFTWARE_LIST_CONFIG(0,_list, SOFTWARE_LIST_ORIGINAL_SYSTEM) + MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_ORIGINAL_SYSTEM) #define MCFG_SOFTWARE_LIST_COMPATIBLE_ADD( _tag, _list ) \ MCFG_DEVICE_ADD( _tag, SOFTWARE_LIST, 0 ) \ - MCFG_SOFTWARE_LIST_CONFIG(0,_list, SOFTWARE_LIST_COMPATIBLE_SYSTEM) + MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_COMPATIBLE_SYSTEM) #define MCFG_SOFTWARE_LIST_MODIFY( _tag, _list ) \ MCFG_DEVICE_MODIFY( _tag ) \ - MCFG_SOFTWARE_LIST_CONFIG(0,_list, SOFTWARE_LIST_ORIGINAL_SYSTEM) + MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_ORIGINAL_SYSTEM) #define MCFG_SOFTWARE_LIST_COMPATIBLE_MODIFY( _tag, _list ) \ MCFG_DEVICE_MODIFY( _tag ) \ - MCFG_SOFTWARE_LIST_CONFIG(0,_list, SOFTWARE_LIST_COMPATIBLE_SYSTEM) + MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_COMPATIBLE_SYSTEM) + +#define MCFG_SOFTWARE_LIST_FILTER( _tag, _filter ) \ + MCFG_DEVICE_MODIFY( _tag ) \ + MCFG_DEVICE_CONFIG_DATAPTR(software_list_config, filter, _filter) #endif diff --git a/src/emu/uiswlist.c b/src/emu/uiswlist.c index 835ccbf4a3b..309c4bcfcf4 100644 --- a/src/emu/uiswlist.c +++ b/src/emu/uiswlist.c @@ -126,9 +126,23 @@ int ui_menu_software_list::compare_entries(const ui_menu_software_entry_info *e1 return result; } +bool ui_menu_software_list::if_compatible(const char *compatibility, const char *filter) +{ + if ((compatibility==NULL) || (filter==NULL)) return TRUE; + astring comp = astring(compatibility,","); + char *filt = core_strdup(filter); + char *token = strtok(filt,","); + while (token!= NULL) + { + if (comp.find(0,astring(token,","))!=-1) return TRUE; + token = strtok (NULL, ","); + } + return FALSE; +} + /* populate a specific list */ -ui_menu_software_entry_info *ui_menu_software_list::append_software_entry(software_info *swinfo, char *list_name, device_image_interface* image) +ui_menu_software_entry_info *ui_menu_software_list::append_software_entry(software_info *swinfo, device_image_interface* image) { ui_menu_software_entry_info *entry = NULL; ui_menu_software_entry_info **entryptr; @@ -138,7 +152,8 @@ ui_menu_software_entry_info *ui_menu_software_list::append_software_entry(softwa // check if at least one of the parts has the correct interface and add a menu entry only in this case for (software_part *swpart = software_find_part(swinfo, NULL, NULL); swpart != NULL; swpart = software_part_next(swpart)) { - if (strcmp(interface, swpart->interface_) == 0) + const char *compatibility = software_part_get_feature(swpart, "compatibility"); + if ((strcmp(interface, swpart->interface_) == 0) && if_compatible(compatibility, swlist->filter)) { entry_updated = TRUE; // allocate a new entry @@ -147,7 +162,7 @@ ui_menu_software_entry_info *ui_menu_software_list::append_software_entry(softwa entry->short_name = pool_strdup(swinfo->shortname); entry->long_name = pool_strdup(swinfo->longname); - entry->list_name = list_name; + entry->list_name = swlist->list_name; entry->image = image; entry->interface = pool_strdup(swpart->interface_); break; @@ -170,9 +185,9 @@ ui_menu_software_entry_info *ui_menu_software_list::append_software_entry(softwa return entry; } -ui_menu_software_list::ui_menu_software_list(running_machine &machine, render_container *container, char *_list_name, device_image_interface *_image) : ui_menu(machine, container) +ui_menu_software_list::ui_menu_software_list(running_machine &machine, render_container *container, software_list_config *_swlist, device_image_interface *_image) : ui_menu(machine, container) { - list_name = _list_name; + swlist = _swlist; image = _image; entrylist = NULL; ordered_by_shortname = true; @@ -184,13 +199,13 @@ ui_menu_software_list::~ui_menu_software_list() void ui_menu_software_list::populate() { - software_list *list = software_list_open(machine().options(), list_name, false, NULL); + software_list *list = software_list_open(machine().options(), swlist->list_name, false, NULL); // build up the list of entries for the menu if (list) { for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) - append_software_entry(swinfo, list_name, image); + append_software_entry(swinfo, image); software_list_close(list); } @@ -241,7 +256,7 @@ void ui_menu_software_list::handle() else if (event->iptkey == IPT_UI_SELECT) { ui_menu_software_entry_info *entry = (ui_menu_software_entry_info *) event->itemref; - software_list *tmp_list = software_list_open(machine().options(), list_name, false, NULL); + software_list *tmp_list = software_list_open(machine().options(), swlist->list_name, false, NULL); software_info *tmp_info = software_list_find(tmp_list, entry->short_name, NULL); // if the selected software has multiple parts that can be loaded, open the submenu @@ -369,28 +384,25 @@ void ui_menu_software::populate() { software_list_config *swlist = (software_list_config *)downcast(dev)->inline_config(); - for (int i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++) + if (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) { - if (swlist->list_name[i] && (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM)) + software_list *list = software_list_open(machine().options(), swlist->list_name, false, NULL); + + if (list) { - software_list *list = software_list_open(machine().options(), swlist->list_name[i], false, NULL); - - if (list) + bool found = false; + for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) { - bool found = false; - for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) - { - software_part *part = software_find_part(swinfo, NULL, NULL); - if (strcmp(interface,part->interface_)==0) { - found = true; - } + software_part *part = software_find_part(swinfo, NULL, NULL); + if (strcmp(interface,part->interface_)==0) { + found = true; } - if (found) { - item_append(list->description, NULL, 0, swlist->list_name[i]); - } - - software_list_close(list); } + if (found) { + item_append(list->description, NULL, 0, swlist); + } + + software_list_close(list); } } } @@ -400,32 +412,29 @@ void ui_menu_software::populate() { software_list_config *swlist = (software_list_config *)downcast(dev)->inline_config(); - for (int i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++) + if (swlist->list_type == SOFTWARE_LIST_COMPATIBLE_SYSTEM) { - if (swlist->list_name[i] && (swlist->list_type == SOFTWARE_LIST_COMPATIBLE_SYSTEM)) + software_list *list = software_list_open(machine().options(), swlist->list_name, false, NULL); + + if (list) { - software_list *list = software_list_open(machine().options(), swlist->list_name[i], false, NULL); - - if (list) + bool found = false; + for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) { - bool found = false; - for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) - { - software_part *part = software_find_part(swinfo, NULL, NULL); - if (strcmp(interface,part->interface_)==0) { - found = true; - } + software_part *part = software_find_part(swinfo, NULL, NULL); + if (strcmp(interface,part->interface_)==0) { + found = true; } - if (found) { - if (!haveCompatible) { - item_append("[compatible lists]", NULL, MENU_FLAG_DISABLE, NULL); - } - item_append(list->description, NULL, 0, swlist->list_name[i]); - } - - haveCompatible = true; - software_list_close(list); } + if (found) { + if (!haveCompatible) { + item_append("[compatible lists]", NULL, MENU_FLAG_DISABLE, NULL); + } + item_append(list->description, NULL, 0, swlist); + } + + haveCompatible = true; + software_list_close(list); } } } @@ -442,5 +451,5 @@ void ui_menu_software::handle() const ui_menu_event *event = process(0); if (event != NULL && event->iptkey == IPT_UI_SELECT) - ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_software_list(machine(), container, (char *)event->itemref, image))); + ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_software_list(machine(), container, (software_list_config *)event->itemref, image))); } diff --git a/src/emu/uiswlist.h b/src/emu/uiswlist.h index 52795423fa7..25c0dbc2e69 100644 --- a/src/emu/uiswlist.h +++ b/src/emu/uiswlist.h @@ -40,21 +40,22 @@ private: class ui_menu_software_list : public ui_menu { public: - ui_menu_software_list(running_machine &machine, render_container *container, char *list_name, device_image_interface *image); + ui_menu_software_list(running_machine &machine, render_container *container, software_list_config *swlist, device_image_interface *image); virtual ~ui_menu_software_list(); virtual void populate(); virtual void handle(); private: - char *list_name; /* currently selected list */ + software_list_config *swlist; /* currently selected list */ device_image_interface *image; ui_menu_software_entry_info *entrylist; char filename_buffer[1024]; bool ordered_by_shortname; int compare_entries(const ui_menu_software_entry_info *e1, const ui_menu_software_entry_info *e2, bool shortname); - ui_menu_software_entry_info *append_software_entry(software_info *swinfo, char *list_name, device_image_interface* image); + ui_menu_software_entry_info *append_software_entry(software_info *swinfo, device_image_interface* image); bool swinfo_has_multiple_parts(software_info *swinfo, const char *interface); + bool if_compatible(const char *compatibility, const char *filter); }; class ui_menu_software : public ui_menu {