/*************************************************************************** info.c Dumps the MAME internal data as an XML file. Copyright Nicola Salmoria and the MAME Team. Visit http://mamedev.org for licensing and usage restrictions. ***************************************************************************/ #include #include "driver.h" #include "sound/samples.h" #include "info.h" #include "xmlfile.h" #include "hash.h" /* MESS/MAME configuration */ #ifdef MESS #define XML_ROOT "mess" #define XML_TOP "machine" #else #define XML_ROOT "mame" #define XML_TOP "game" #endif #ifdef MESS void print_game_device(FILE* out, const game_driver* game); void print_game_ramoptions(FILE* out, const game_driver* game); #endif /* MESS */ /*------------------------------------------------- print_game_switches - print the DIP switch settings for a game -------------------------------------------------*/ static void print_game_switches(FILE *out, const game_driver *game, const input_port_entry *input) { /* iterate over input entries until we run out */ while (input->type != IPT_END) { /* once we hit a name entry, start outputting */ if (input->type == IPT_DIPSWITCH_NAME) { int def = input->default_value; /* output the switch name information */ fprintf(out, "\t\t\n", xml_normalize_string(input->name)); /* loop over settings */ for (input++; input->type == IPT_DIPSWITCH_SETTING; input++) { fprintf(out, "\t\t\tname)); if (def == input->default_value) fprintf(out, " default=\"yes\""); fprintf(out, "/>\n"); } /* terminate the switch entry */ fprintf(out, "\t\t\n"); } else ++input; } } /*------------------------------------------------- print_game_input - print a summary of a game's input -------------------------------------------------*/ static void print_game_input(FILE *out, const game_driver *game, const input_port_entry *input) { /* fix me -- this needs to be cleaned up to match the core style */ enum {cjoy, cdoublejoy, cAD_stick, cdial, ctrackball, cpaddle, clightgun, cpedal, ENDCONTROLTYPES}; int nplayer = 0; int nbutton = 0; int ncoin = 0; int controlsyes = 0; int analogcontrol = 0; int i; const char* service = 0; const char* tilt = 0; const char* control_types[] = {"joy", "doublejoy", "stick", "dial", "trackball", "paddle", "lightgun", "pedal"}; static struct _input_info { const char * type; /* general type of input */ const char * Xway; /* 2, 4, or 8 way */ int analog; int min; /* analog minimum value */ int max; /* analog maximum value */ int sensitivity; /* default analog sensitivity */ int keydelta; /* default analog keydelta */ int reverse; /* default analog reverse setting */ } control[ENDCONTROLTYPES]; for (i=0;itype != IPT_END) { if (nplayer < input->player+1) nplayer = input->player+1; switch (input->type) { case IPT_JOYSTICK_LEFT: case IPT_JOYSTICK_RIGHT: /* if control not defined, start it off as horizontal 2-way */ if (control[cjoy].Xway == NULL) control[cjoy].Xway = "joy2way"; else if (strcmp(control[cjoy].Xway,"joy2way") == 0) ; /* if already defined as vertical, make it 4 or 8 way */ else if (strcmp(control[cjoy].Xway,"vjoy2way") == 0) { if (input->way == 4) control[cjoy].Xway = "joy4way"; else control[cjoy].Xway = "joy8way"; } controlsyes = 1; break; case IPT_JOYSTICK_UP: case IPT_JOYSTICK_DOWN: /* if control not defined, start it off as vertical 2-way */ if (control[cjoy].Xway == NULL) control[cjoy].Xway = "vjoy2way"; else if (strcmp(control[cjoy].Xway,"vjoy2way") == 0) ; /* if already defined as horiz, make it 4 or 8way */ else if (strcmp(control[cjoy].Xway,"joy2way") == 0) { if (input->way == 4) control[cjoy].Xway = "joy4way"; else control[cjoy].Xway = "joy8way"; } controlsyes = 1; break; case IPT_JOYSTICKRIGHT_UP: case IPT_JOYSTICKRIGHT_DOWN: case IPT_JOYSTICKLEFT_UP: case IPT_JOYSTICKLEFT_DOWN: /* if control not defined, start it off as vertical 2way */ if (control[cdoublejoy].Xway == NULL) control[cdoublejoy].Xway = "vdoublejoy2way"; else if (strcmp(control[cdoublejoy].Xway,"vdoublejoy2way") == 0) ; /* if already defined as horiz, make it 4 or 8 way */ else if (strcmp(control[cdoublejoy].Xway,"doublejoy2way") == 0) { if (input->way == 4) control[cdoublejoy].Xway = "doublejoy4way"; else control[cdoublejoy].Xway = "doublejoy8way"; } controlsyes = 1; break; case IPT_JOYSTICKRIGHT_LEFT: case IPT_JOYSTICKRIGHT_RIGHT: case IPT_JOYSTICKLEFT_LEFT: case IPT_JOYSTICKLEFT_RIGHT: /* if control not defined, start it off as horiz 2-way */ if (control[cdoublejoy].Xway == NULL) control[cdoublejoy].Xway = "doublejoy2way"; else if (strcmp(control[cdoublejoy].Xway,"doublejoy2way") == 0) ; /* if already defined as vertical, make it 4 or 8 way */ else if (strcmp(control[cdoublejoy].Xway,"vdoublejoy2way") == 0) { if (input->way == 4) control[cdoublejoy].Xway = "doublejoy4way"; else control[cdoublejoy].Xway = "doublejoy8way"; } controlsyes = 1; break; /* mark as an analog input, and get analog stats after switch */ case IPT_PADDLE: analogcontrol = cpaddle; break; case IPT_DIAL: analogcontrol = cdial; break; case IPT_TRACKBALL_X: case IPT_TRACKBALL_Y: analogcontrol = ctrackball; break; case IPT_AD_STICK_X: case IPT_AD_STICK_Y: analogcontrol = cAD_stick; break; case IPT_LIGHTGUN_X: case IPT_LIGHTGUN_Y: analogcontrol = clightgun; break; case IPT_PEDAL: case IPT_PEDAL2: case IPT_PEDAL3: analogcontrol = cpedal; break; case IPT_BUTTON1: if (nbutton<1) nbutton = 1; break; case IPT_BUTTON2: if (nbutton<2) nbutton = 2; break; case IPT_BUTTON3: if (nbutton<3) nbutton = 3; break; case IPT_BUTTON4: if (nbutton<4) nbutton = 4; break; case IPT_BUTTON5: if (nbutton<5) nbutton = 5; break; case IPT_BUTTON6: if (nbutton<6) nbutton = 6; break; case IPT_BUTTON7: if (nbutton<7) nbutton = 7; break; case IPT_BUTTON8: if (nbutton<8) nbutton = 8; break; case IPT_BUTTON9: if (nbutton<9) nbutton = 9; break; case IPT_BUTTON10: if (nbutton<10) nbutton = 10; break; case IPT_COIN1: if (ncoin < 1) ncoin = 1; break; case IPT_COIN2: if (ncoin < 2) ncoin = 2; break; case IPT_COIN3: if (ncoin < 3) ncoin = 3; break; case IPT_COIN4: if (ncoin < 4) ncoin = 4; break; case IPT_COIN5: if (ncoin < 5) ncoin = 5; break; case IPT_COIN6: if (ncoin < 6) ncoin = 6; break; case IPT_COIN7: if (ncoin < 7) ncoin = 7; break; case IPT_COIN8: if (ncoin < 8) ncoin = 8; break; case IPT_SERVICE : service = "yes"; break; case IPT_TILT : tilt = "yes"; break; } /* get the analog stats */ if (analogcontrol) { controlsyes = 1; control[analogcontrol].analog = 1; if (input->analog.min) control[analogcontrol].min = input->analog.min; if (input->analog.max) control[analogcontrol].max = input->analog.max; if (input->analog.sensitivity) control[analogcontrol].sensitivity = input->analog.sensitivity; if (input->analog.delta) control[analogcontrol].keydelta = input->analog.delta; if (input->analog.reverse) control[analogcontrol].reverse = 1; analogcontrol = 0; } ++input; } fprintf(out, "\t\t\n"); for (i = 0; i < ENDCONTROLTYPES; i++) { if (control[i].Xway != NULL) fprintf(out, "\t\t\t\n", xml_normalize_string(control[i].Xway)); if (control[i].analog) { fprintf(out, "\t\t\t\n"); } } fprintf(out, "\t\t\n"); } /*------------------------------------------------- print_game_bios - print the BIOS set for a game -------------------------------------------------*/ static void print_game_bios(FILE *out, const game_driver *game) { const rom_entry *rom; /* skip if no ROMs */ if (game->rom == NULL) return; /* iterate over ROM entries and look for BIOSes */ for (rom = game->rom; !ROMENTRY_ISEND(rom); rom++) if (ROMENTRY_ISSYSTEM_BIOS(rom)) { const char *name = ROM_GETHASHDATA(rom); const char *description = name + strlen(name) + 1; /* output extracted name and descriptions */ fprintf(out, "\t\t\n"); } } /*------------------------------------------------- print_game_rom - print the roms section of the XML output -------------------------------------------------*/ static void print_game_rom(FILE *out, const game_driver *game) { const game_driver *clone_of = driver_get_clone(game); int rom_type; /* if no roms, just exit early */ if (game->rom == NULL) return; /* iterate over 3 different ROM "types": BIOS, ROMs, DISKs */ for (rom_type = 0; rom_type < 3; rom_type++) { const rom_entry *region; /* iterate first through regions */ for (region = rom_first_region(game); region != NULL; region = rom_next_region(region)) { int is_disk = ROMREGION_ISDISKDATA(region); const rom_entry *rom; /* disk regions only work for disks */ if ((is_disk && rom_type != 2) || (!is_disk && rom_type == 2)) continue; /* iterate through ROM entries */ for (rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom)) { int is_bios = ROM_GETBIOSFLAGS(rom); const char *name = ROM_GETNAME(rom); int offset = ROM_GETOFFSET(rom); const rom_entry *parent_rom = NULL; const rom_entry *chunk; char bios_name[100]; int length; /* BIOS ROMs only apply to bioses */ if ((is_bios && rom_type != 0) || (!is_bios && rom_type == 0)) continue; /* compute the total length of all chunks */ length = 0; for (chunk = rom_first_chunk(rom); chunk; chunk = rom_next_chunk(chunk)) length += ROM_GETLENGTH(chunk); /* if we have a valid ROM and we are a clone, see if we can find the parent ROM */ if (!ROM_NOGOODDUMP(rom) && clone_of != NULL) { const rom_entry *pregion, *prom; /* scan the clone_of ROM for a matching ROM entry */ for (pregion = rom_first_region(clone_of); pregion != NULL; pregion = rom_next_region(pregion)) for (prom = rom_first_file(pregion); prom != NULL; prom = rom_next_file(prom)) if (hash_data_is_equal(ROM_GETHASHDATA(rom), ROM_GETHASHDATA(prom), 0)) { parent_rom = prom; break; } } /* scan for a BIOS name */ bios_name[0] = 0; if (!is_disk && is_bios) { const rom_entry *brom; /* scan backwards through the ROM entries */ for (brom = rom - 1; brom != game->rom; brom--) if (ROMENTRY_ISSYSTEM_BIOS(brom)) { strcpy(bios_name, ROM_GETHASHDATA(brom)); break; } } /* opening tag */ if (!is_disk) fprintf(out, "\t\t\n"); } } } } /*------------------------------------------------- print_game_sampleof - print the 'sampleof' attribute, if appropriate -------------------------------------------------*/ static void print_game_sampleof(FILE *out, const game_driver *game, const machine_config *config) { #if (HAS_SAMPLES) int sndnum; for (sndnum = 0; sndnum < ARRAY_LENGTH(config->sound) && config->sound[sndnum].type != SOUND_DUMMY; sndnum++) if (config->sound[sndnum].type == SOUND_SAMPLES) { const char *const *samplenames = ((const struct Samplesinterface *)config->sound[sndnum].config)->samplenames; if (samplenames != NULL) { int sampnum; /* iterate over sample names */ for (sampnum = 0; samplenames[sampnum] != NULL; sampnum++) { const char *cursampname = samplenames[sampnum]; /* only output sampleof if different from the game name */ if (cursampname[0] == '*' && strcmp(cursampname + 1, game->name) != 0) fprintf(out, " sampleof=\"%s\"", xml_normalize_string(cursampname + 1)); } } } #endif } /*------------------------------------------------- print_game_sample - print a list of all samples referenced by a game_driver -------------------------------------------------*/ static void print_game_sample(FILE *out, const game_driver *game, const machine_config *config) { #if (HAS_SAMPLES) int sndnum; /* iterate over sound chips looking for samples */ for (sndnum = 0; sndnum < ARRAY_LENGTH(config->sound) && config->sound[sndnum].type != SOUND_DUMMY; sndnum++) if (config->sound[sndnum].type == SOUND_SAMPLES) { const char *const *samplenames = ((const struct Samplesinterface *)config->sound[sndnum].config)->samplenames; if (samplenames != NULL) { int sampnum; /* iterate over sample names */ for (sampnum = 0; samplenames[sampnum] != NULL; sampnum++) { const char *cursampname = samplenames[sampnum]; int dupnum; /* ignore the special '*' samplename */ if (sampnum == 0 && cursampname[0] == '*') continue; /* filter out duplicates */ for (dupnum = 0; dupnum < sampnum; dupnum++) if (strcmp(samplenames[dupnum], cursampname) == 0) break; if (dupnum < sampnum) continue; /* output the sample name */ fprintf(out, "\t\t\n", xml_normalize_string(cursampname)); } } } #endif } /*------------------------------------------------- print_game_chips - print a list of CPU and sound chips used by a game -------------------------------------------------*/ static void print_game_chips(FILE *out, const game_driver *game, const machine_config *config) { int chipnum; /* iterate over CPUs */ for (chipnum = 0; chipnum < ARRAY_LENGTH(config->cpu); chipnum++) if (config->cpu[chipnum].type != CPU_DUMMY) { fprintf(out, "\t\tcpu[chipnum].type))); fprintf(out, " clock=\"%d\"", config->cpu[chipnum].clock); fprintf(out, "/>\n"); } /* iterate over sound chips */ for (chipnum = 0; chipnum < ARRAY_LENGTH(config->sound); chipnum++) if (config->sound[chipnum].type != SOUND_DUMMY) { fprintf(out, "\t\tsound[chipnum].type))); if (config->sound[chipnum].clock != 0) fprintf(out, " clock=\"%d\"", config->sound[chipnum].clock); fprintf(out, "/>\n"); } } /*------------------------------------------------- print_game_display - print a list of all the displays -------------------------------------------------*/ static void print_game_display(FILE *out, const game_driver *game, const machine_config *config) { const device_config *screen; /* iterate over screens */ for (screen = video_screen_first(config); screen != NULL; screen = video_screen_next(screen)) { const screen_config *scrconfig = screen->inline_config; fprintf(out, "\t\ttype) { case SCREEN_TYPE_RASTER: fprintf(out, " type=\"raster\""); break; case SCREEN_TYPE_VECTOR: fprintf(out, " type=\"vector\""); break; case SCREEN_TYPE_LCD: fprintf(out, " type=\"lcd\""); break; default: fprintf(out, " type=\"unknown\""); break; } /* output the orientation as a string */ switch (game->flags & ORIENTATION_MASK) { case ORIENTATION_FLIP_X: fprintf(out, " rotate=\"0\" flipx=\"yes\""); break; case ORIENTATION_FLIP_Y: fprintf(out, " rotate=\"180\" flipx=\"yes\""); break; case ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y: fprintf(out, " rotate=\"180\""); break; case ORIENTATION_SWAP_XY: fprintf(out, " rotate=\"90\" flipx=\"yes\""); break; case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X: fprintf(out, " rotate=\"90\""); break; case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_Y: fprintf(out, " rotate=\"270\""); break; case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y: fprintf(out, " rotate=\"270\" flipx=\"yes\""); break; default: fprintf(out, " rotate=\"0\""); break; } /* output width and height only for games that are not vector */ if (scrconfig->type != SCREEN_TYPE_VECTOR) { int dx = scrconfig->defstate.visarea.max_x - scrconfig->defstate.visarea.min_x + 1; int dy = scrconfig->defstate.visarea.max_y - scrconfig->defstate.visarea.min_y + 1; fprintf(out, " width=\"%d\"", dx); fprintf(out, " height=\"%d\"", dy); } /* output refresh rate */ fprintf(out, " refresh=\"%f\"", ATTOSECONDS_TO_HZ(scrconfig->defstate.refresh)); /* output raw video parameters only for games that are not vector */ /* and had raw parameters specified */ if ((scrconfig->type != SCREEN_TYPE_VECTOR) && !scrconfig->defstate.oldstyle_vblank_supplied) { int pixclock = scrconfig->defstate.width * scrconfig->defstate.height * ATTOSECONDS_TO_HZ(scrconfig->defstate.refresh); fprintf(out, " pixclock=\"%d\"", pixclock); fprintf(out, " htotal=\"%d\"", scrconfig->defstate.width); fprintf(out, " hbend=\"%d\"", scrconfig->defstate.visarea.min_x); fprintf(out, " hbstart=\"%d\"", scrconfig->defstate.visarea.max_x+1); fprintf(out, " vtotal=\"%d\"", scrconfig->defstate.height); fprintf(out, " vbend=\"%d\"", scrconfig->defstate.visarea.min_y); fprintf(out, " vbstart=\"%d\"", scrconfig->defstate.visarea.max_y+1); } fprintf(out, " />\n"); } } /*------------------------------------------------- print_game_sound - print a list of all the displays -------------------------------------------------*/ static void print_game_sound(FILE *out, const game_driver *game, const machine_config *config) { int speakers = speaker_output_count(config); int has_sound = FALSE; int sndnum; /* see if we have any sound chips to report */ for (sndnum = 0; sndnum < ARRAY_LENGTH(config->sound); sndnum++) if (config->sound[sndnum].type != SOUND_DUMMY) { has_sound = TRUE; break; } /* if we have sound, count the number of speakers */ if (!has_sound) speakers = 0; fprintf(out, "\t\t\n", speakers); } /*------------------------------------------------- print_game_driver - print driver status -------------------------------------------------*/ static void print_game_driver(FILE *out, const game_driver *game, const machine_config *config) { fprintf(out, "\t\tflags & (GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_NO_SOUND | GAME_WRONG_COLORS)) fprintf(out, " status=\"preliminary\""); else if (game->flags & (GAME_IMPERFECT_COLORS | GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS)) fprintf(out, " status=\"imperfect\""); else fprintf(out, " status=\"good\""); if (game->flags & GAME_NOT_WORKING) fprintf(out, " emulation=\"preliminary\""); else fprintf(out, " emulation=\"good\""); if (game->flags & GAME_WRONG_COLORS) fprintf(out, " color=\"preliminary\""); else if (game->flags & GAME_IMPERFECT_COLORS) fprintf(out, " color=\"imperfect\""); else fprintf(out, " color=\"good\""); if (game->flags & GAME_NO_SOUND) fprintf(out, " sound=\"preliminary\""); else if (game->flags & GAME_IMPERFECT_SOUND) fprintf(out, " sound=\"imperfect\""); else fprintf(out, " sound=\"good\""); if (game->flags & GAME_IMPERFECT_GRAPHICS) fprintf(out, " graphic=\"imperfect\""); else fprintf(out, " graphic=\"good\""); if (game->flags & GAME_NO_COCKTAIL) fprintf(out, " cocktail=\"preliminary\""); if (game->flags & GAME_UNEMULATED_PROTECTION) fprintf(out, " protection=\"preliminary\""); if (game->flags & GAME_SUPPORTS_SAVE) fprintf(out, " savestate=\"supported\""); else fprintf(out, " savestate=\"unsupported\""); fprintf(out, " palettesize=\"%d\"", config->total_colors); fprintf(out, "/>\n"); } /*------------------------------------------------- print_game_info - print the XML information for one particular game driver -------------------------------------------------*/ static void print_game_info(FILE *out, const game_driver *game) { const input_port_entry *input; const game_driver *clone_of; machine_config *config; const char *start; /* no action if not a game */ if (game->flags & GAME_NO_STANDALONE) return; /* start tracking resources and allocate the machine and input configs */ begin_resource_tracking(); config = machine_config_alloc(game->machine_config); input = input_port_allocate(game->ipt, NULL); /* print the header and the game name */ fprintf(out, "\t<" XML_TOP); fprintf(out, " name=\"%s\"", xml_normalize_string(game->name) ); /* strip away any path information from the source_file and output it */ start = strrchr(game->source_file, '/'); if (start == NULL) start = strrchr(game->source_file, '\\'); if (start == NULL) start = game->source_file - 1; fprintf(out, " sourcefile=\"%s\"", xml_normalize_string(start + 1)); /* append bios and runnable flags */ if (game->flags & GAME_IS_BIOS_ROOT) fprintf(out, " isbios=\"yes\""); if (game->flags & GAME_NO_STANDALONE) fprintf(out, " runnable=\"no\""); /* display clone information */ clone_of = driver_get_clone(game); if (clone_of != NULL && !(clone_of->flags & GAME_IS_BIOS_ROOT)) fprintf(out, " cloneof=\"%s\"", xml_normalize_string(clone_of->name)); if (clone_of != NULL) fprintf(out, " romof=\"%s\"", xml_normalize_string(clone_of->name)); /* display sample information and close the game tag */ print_game_sampleof(out, game, config); fprintf(out, ">\n"); /* output game description */ if (game->description != NULL) fprintf(out, "\t\t%s\n", xml_normalize_string(game->description)); /* print the year only if is a number */ if (game->year != NULL && strspn(game->year, "0123456789") == strlen(game->year)) fprintf(out, "\t\t%s\n", xml_normalize_string(game->year)); /* print the manufacturer information */ if (game->manufacturer != NULL) fprintf(out, "\t\t%s\n", xml_normalize_string(game->manufacturer)); /* now print various additional information */ print_game_bios(out, game); print_game_rom(out, game); print_game_sample(out, game, config); print_game_chips(out, game, config); print_game_display(out, game, config); print_game_sound(out, game, config); print_game_input(out, game, input); print_game_switches(out, game, input); print_game_driver(out, game, config); #ifdef MESS print_game_device(out, game); print_game_ramoptions(out, game); #endif /* close the topmost tag */ fprintf(out, "\t\n"); /* release resources */ end_resource_tracking(); machine_config_free(config); } /*------------------------------------------------- print_mame_xml - print the XML information for all known games -------------------------------------------------*/ void print_mame_xml(FILE *out, const game_driver *const games[], const char *gamename) { int drvnum; fprintf(out, "\n" "\n" "\t\n" "\t\n" #ifdef MESS "\t\n" #else "\t\n" #endif "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" #ifdef MESS "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\n" "\t\t\t\n" #endif "]>\n\n" "<" XML_ROOT " build=\"%s\" debug=\"" #ifdef MAME_DEBUG "yes" #else "no" #endif "\">\n", xml_normalize_string(build_version) ); for (drvnum = 0; games[drvnum] != NULL; drvnum++) if (mame_strwildcmp(gamename, games[drvnum]->name) == 0) print_game_info(out, games[drvnum]); fprintf(out, "\n"); }