softlist.c: split the <info> field (added some time ago to handle compatibility requirements) into <info> and <sharedfeat>.

the former stays tied to the whole software entry, the latter gets inherited by each part. 

out of whatsnew 1: Arbee, this change finalizes the xml format once for all. feel free to create an apple II or ||gs list, if you are interested

out of whatsnew 2: 
A bunch of comments about this change: with the latest code, each software entry can store three different kind of 'extrainfo' strings. They are thought to be used in specific cases, so let me briefly explain the big picture behind them.

1. <feature> fields: these are well established in current lists. they belong to a <part> element (i.e. a specific cart or cd disc or floppy disk) and they can be used to store hardware details that belongs to that specific <part>. typically, we have used these to describe the pcb_type of a cart (e.g. the board type in NES carts or in AES carts, to remove the need of specific mappers), so that at loading time they can be checked and the emulation can be setup accordingly. However, some lists (e.g. snes.xml and, in a few months, nes.xml as well) use these more creatively, to e.g. document the exact chip locations on the pcb

examples
<feature name="pcb_type" value="MMC3C"/>
<feature name="u3" value="SRAM-64M"/>

----------
2. <sharedfeat> fields: these are listed in the main <software> entry, but get stored together with the <feature> of each part of this software. E.g. if your software entry consists of 9 floppies, these shared features will be inherited by *all* the disks. The typical usage for this is to list the compatibility requirements of the software entry, e.g. a PAL system, or the presence of an expansion card, or the presence of additional RAM. These compatibility settings have to be manually parsed in the loading code by the driver author, but it makes more sense to define them only once for each software entry than to copy and paste it for each <part> (and believe me, it makes a difference both in terms of avoiding redundant lines and in terms of time necessary to create the xml list itself, when you deal with hundreds of multidisk entries like in the forthcoming pc8801 floppy list). consider this as a shortcut for 1. when you have multidisk software.

examples
<sharedfeat name="compatibility" value="EUR-JPN"/>  (the value can be freely chosen by the driver author as long as he also add the correct values in the loading routine ;) )
<sharedfeat name="addon" value="DVC"/> (this can be of use in cdi titles which won't work without the DigitalVideoCard expansion)

----------
3. <info> fields: these belongs directly to the main <software> entry, like the <sharedfeat>, but they do get stored in the main software entry, not with the <part>. They should be used to store additional info which might be of use for frontends, but that are not strictly necessary for emulation (if you have to describe some fundamental hardware characteristic that has to be checked during emulation, then you should use <sharedfeat> not <info>). Possible examples include the name of the development team, or the serial number of the cart, etc but it's up to the list creator to decide what to use this for and if to use it at all

examples
<info name="developer" value="Treasure"/>
<info name="serial" value="NUS-NSMJ-JPN"/>

As already said, imho the format can now be considered finalized. I cannot really think of anything else that we might want to include in the format, without getting redundant. 

p.s. In fact, some small change is still required in the core to fully support the new fields (e.g. at the moment <info> are not loaded by the core), but the xml format won't be touched.
This commit is contained in:
Fabio Priuli 2011-03-27 00:11:42 +00:00
parent 9ad9840545
commit f25b3a9b88
5 changed files with 88 additions and 24 deletions

View File

@ -1,13 +1,19 @@
<!ELEMENT softwarelist (software+)>
<!ATTLIST softwarelist name CDATA #REQUIRED>
<!ATTLIST softwarelist description CDATA #IMPLIED>
<!ELEMENT software (description, year?, publisher, part*)>
<!ELEMENT software (description, year?, publisher, info*, sharedfeat*, part*)>
<!ATTLIST software name CDATA #REQUIRED>
<!ATTLIST software cloneof CDATA #IMPLIED>
<!ATTLIST software supported (yes|partial|no) "yes">
<!ELEMENT description (#PCDATA)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT publisher (#PCDATA)>
<!ELEMENT info EMPTY>
<!ATTLIST info name CDATA #REQUIRED>
<!ATTLIST info value CDATA #IMPLIED>
<!ELEMENT sharedfeat EMPTY>
<!ATTLIST sharedfeat name CDATA #REQUIRED>
<!ATTLIST sharedfeat value CDATA #IMPLIED>
<!ELEMENT part (feature*, dataarea*, diskarea*, dipswitch*)>
<!ATTLIST part name CDATA #REQUIRED>
<!ATTLIST part interface CDATA #REQUIRED>

View File

@ -826,13 +826,26 @@ static void info_listsoftware(emu_options &options, const char *gamename)
"\t<!ELEMENT softwarelist (software+)>\n"
"\t\t<!ATTLIST softwarelist name CDATA #REQUIRED>\n"
"\t\t<!ATTLIST softwarelist description CDATA #IMPLIED>\n"
"\t\t<!ELEMENT software (description, year?, publisher, part*)>\n"
"\t\t<!ELEMENT software (description, year?, publisher, info*, sharedfeat*, part*)>\n"
"\t\t\t<!ATTLIST software name CDATA #REQUIRED>\n"
"\t\t\t<!ATTLIST software cloneof CDATA #IMPLIED>\n"
"\t\t\t<!ATTLIST software supported (yes|partial|no) \"yes\">\n"
"\t\t\t<!ELEMENT description (#PCDATA)>\n"
"\t\t\t<!ELEMENT year (#PCDATA)>\n"
"\t\t\t<!ELEMENT publisher (#PCDATA)>\n"
// we still do not store the info strings internally, so there is no output here
// TODO: add parsing info in softlist.c and then add output here!
"\t\t\t<!ELEMENT info EMPTY>\n"
"\t\t\t\t<!ATTLIST info name CDATA #REQUIRED>\n"
"\t\t\t\t<!ATTLIST info value CDATA #IMPLIED>\n"
// shared features get stored in the part->feature below and are output there
// this means that we don't output any <sharedfeat> and that -lsoft output will
// be different from the list in hash/ when the list uses sharedfeat. But this
// is by design: sharedfeat is only available to simplify the life to list creators,
// to e.g. avoid manually adding the same feature to each disk of a 9 floppies game!
"\t\t\t<!ELEMENT sharedfeat EMPTY>\n"
"\t\t\t\t<!ATTLIST sharedfeat name CDATA #REQUIRED>\n"
"\t\t\t\t<!ATTLIST sharedfeat value CDATA #IMPLIED>\n"
"\t\t\t<!ELEMENT part (feature*, dataarea*, diskarea*, dipswitch*)>\n"
"\t\t\t\t<!ATTLIST part name CDATA #REQUIRED>\n"
"\t\t\t\t<!ATTLIST part interface CDATA #REQUIRED>\n"
@ -862,7 +875,7 @@ static void info_listsoftware(emu_options &options, const char *gamename)
"\t\t\t\t\t\t<!ATTLIST disk sha1 CDATA #IMPLIED>\n"
"\t\t\t\t\t\t<!ATTLIST disk status (baddump|nodump|good) \"good\">\n"
"\t\t\t\t\t\t<!ATTLIST disk writeable (yes|no) \"no\">\n"
// we still do not store the dipswitch values in softlist, so there is no output here
// we still do not store the dipswitch values internally, so there is no output here
// TODO: add parsing dipsw in softlist.c and then add output here!
"\t\t\t\t<!ELEMENT dipswitch (dipvalue*)>\n"
"\t\t\t\t\t<!ATTLIST dipswitch name CDATA #REQUIRED>\n"

View File

@ -283,7 +283,7 @@ static void add_feature(software_list *swlist, char *feature_name, char *feature
/*-------------------------------------------------
add_info (same as add_feature, but its target
is softinfo->other_info)
is softinfo->shared_info)
-------------------------------------------------*/
static void add_info(software_list *swlist, char *feature_name, char *feature_value)
@ -301,9 +301,9 @@ static void add_info(software_list *swlist, char *feature_name, char *feature_va
new_entry->value = feature_value ? feature_value : feature_name;
/* Add new feature to end of feature list */
if ( info->other_info )
if ( info->shared_info )
{
feature_list *list = info->other_info;
feature_list *list = info->shared_info;
while ( list->next != NULL )
{
list = list->next;
@ -312,7 +312,7 @@ static void add_info(software_list *swlist, char *feature_name, char *feature_va
}
else
{
info->other_info = new_entry;
info->shared_info = new_entry;
}
}
else
@ -445,15 +445,15 @@ static void start_handler(void *data, const char *tagname, const char **attribut
elem->partdata = (software_part *)pool_malloc_lib(swlist->pool, swlist->part_entries * sizeof(software_part) );
if ( !elem->partdata )
return;
elem->other_info = (feature_list *)pool_malloc_lib(swlist->pool, sizeof(feature_list) );
if ( !elem->other_info )
elem->shared_info = (feature_list *)pool_malloc_lib(swlist->pool, sizeof(feature_list) );
if ( !elem->shared_info )
return;
else
{
elem->other_info->next = (feature_list *)pool_malloc_lib(swlist->pool, sizeof(feature_list) );
elem->other_info->next = NULL;
elem->other_info->name = NULL;
elem->other_info->value = NULL;
elem->shared_info->next = (feature_list *)pool_malloc_lib(swlist->pool, sizeof(feature_list) );
elem->shared_info->next = NULL;
elem->shared_info->name = NULL;
elem->shared_info->value = NULL;
}
/* Handle the supported flag */
@ -498,7 +498,12 @@ static void start_handler(void *data, const char *tagname, const char **attribut
text_dest = (char **) &swlist->softinfo->year;
else if (!strcmp(tagname, "publisher"))
text_dest = (char **) &swlist->softinfo->publisher;
else if ( !strcmp(tagname, "info") )
else if (!strcmp(tagname, "info"))
{
// the "info" field (containing info about actual developers, etc.) is not currently stored.
// full support will be added, but for the moment frontend have to get this info from the xml directly
}
else if (!strcmp(tagname, "sharedfeat"))
{
const char *str_feature_name = NULL;
const char *str_feature_value = NULL;
@ -858,10 +863,10 @@ static void end_handler(void *data, const char *name)
break;
case POS_PART:
/* Add other_info inherited from the software_info level, if any */
if ( swlist->softinfo && swlist->softinfo->other_info )
/* Add shared_info inherited from the software_info level, if any */
if ( swlist->softinfo && swlist->softinfo->shared_info )
{
feature_list *list = swlist->softinfo->other_info;
feature_list *list = swlist->softinfo->shared_info;
while( list->next )
{

View File

@ -35,21 +35,20 @@ struct software_part
};
/* The software info struct holds basic software information. Additional,
optional information like local software names, release dates, serial
numbers, etc can be maintained and stored in external recources.
*/
/* The software info struct holds basic software information. */
struct software_info
{
const char *shortname;
const char *longname;
const char *parentname;
const char *year; /* Copyright year on title screen, actual release dates can be tracked in external resources */
const char *year; // Copyright year on title screen, actual release dates can be tracked in external resources
const char *publisher;
feature_list *other_info;
feature_list *other_info; // Here we store info like developer, serial #, etc. which belong to the software entry as a whole
feature_list *shared_info; // Here we store info like TV standard compatibility, or add-on requirements, etc. which get inherited
// by each part of this software entry (after loading these are stored in partdata->featurelist)
UINT32 supported;
software_part *partdata;
struct software_info *next; /* Used internally */
struct software_info *next; // Used internally
};

View File

@ -1831,6 +1831,45 @@ static int megadrive_load_nonlist(device_image_interface &image)
return IMAGE_INIT_PASS;
}
static void megadrive_check_compat_list(device_image_interface &image)
{
const char *compatibility = image.get_feature("compatibility");
const char *chips = image.get_feature("addon");
int md_region = megadrive_region_export + (megadrive_region_pal << 1);
if (chips)
{
if(!strcmp(chips, "SVP") && (image.device().machine->device<cpu_device>("svp") == NULL))
{
mame_printf_warning("This software requires emulation of the SVP CPU to work.\n");
mame_printf_warning("It might not work in the system you are using.\n");
}
}
if (compatibility)
{
if(!strcmp(compatibility, "PAL") && (md_region != 3))
{
mame_printf_warning("This software requires a PAL console to work.\n");
mame_printf_warning("It might not work in the system you are using.\n");
}
if(!strcmp(compatibility, "NTSC-J") && (md_region != 0))
{
mame_printf_warning("This software requires a JPN console to work.\n");
mame_printf_warning("It might not work in the system you are using.\n");
}
if(!strcmp(compatibility, "NTSC-U") && (md_region != 1))
{
mame_printf_warning("This software requires a USA console to work.\n");
mame_printf_warning("It might not work in the system you are using.\n");
}
if(!strcmp(compatibility, "EUR-JPN") && (md_region != 0 && md_region != 3))
{
mame_printf_warning("This software requires a PAL or a JPN console to work.\n");
mame_printf_warning("It might not work in the system you are using.\n");
}
}
}
/*************************************
* Loading a cart image from softlist
@ -1851,6 +1890,8 @@ static int megadrive_load_list(device_image_interface &image)
else
state->md_cart.type = md_get_pcb_id(pcb_name);
megadrive_check_compat_list(image);
memcpy(&ROM[VIRGIN_COPY_GEN], &ROM[0x000000], MAX_MD_CART_SIZE); /* store a copy of data */
return IMAGE_INIT_PASS;