Supermodel/core/romparse.c
Ville Linde a1c9f6cf92
2006-07-12 13:53:14 +00:00

604 lines
14 KiB
C

#include "model3.h"
#include "expat.h"
enum
{
ELEMENT_NONE = 1,
ELEMENT_GAMELIST,
ELEMENT_GAME,
ELEMENT_DESCRIPTION,
ELEMENT_YEAR,
ELEMENT_MANUFACTURER,
ELEMENT_STEP,
ELEMENT_CROMSIZE,
ELEMENT_ROM,
ELEMENT_PATCH,
ELEMENT_BRIDGE,
ELEMENT_INPUT,
};
enum
{
ATTR_ROM_TYPE = 1,
ATTR_ROM_NAME,
ATTR_ROM_SIZE,
ATTR_ROM_CRC,
ATTR_ROM_SHA1,
ATTR_GAME_NAME,
ATTR_GAME_PARENT,
ATTR_PATCH_SIZE,
ATTR_PATCH_ADDRESS,
ATTR_PATCH_DATA,
ATTR_INPUT_TYPE,
ATTR_INPUT_CENTER,
ATTR_INPUT_MAPPING,
};
static STRING_ID element_id[] =
{
{ "gamelist", ELEMENT_GAMELIST },
{ "game", ELEMENT_GAME },
{ "description", ELEMENT_DESCRIPTION },
{ "year", ELEMENT_YEAR },
{ "manufacturer", ELEMENT_MANUFACTURER },
{ "step", ELEMENT_STEP },
{ "cromsize", ELEMENT_CROMSIZE },
{ "rom", ELEMENT_ROM },
{ "patch", ELEMENT_PATCH },
{ "bridge", ELEMENT_BRIDGE },
{ "input", ELEMENT_INPUT },
{ "", 0 },
};
static STRING_ID rom_attr_id[] =
{
{ "type", ATTR_ROM_TYPE },
{ "name", ATTR_ROM_NAME },
{ "size", ATTR_ROM_SIZE },
{ "crc", ATTR_ROM_CRC },
{ "sha1", ATTR_ROM_SHA1 },
{ "", 0 },
};
static STRING_ID game_attr_id[] =
{
{ "name", ATTR_GAME_NAME },
{ "parent", ATTR_GAME_PARENT },
{ "", 0 },
};
static STRING_ID patch_attr_id[] =
{
{ "size", ATTR_PATCH_SIZE },
{ "address", ATTR_PATCH_ADDRESS },
{ "data", ATTR_PATCH_DATA },
{ "", 0 },
};
static STRING_ID input_attr_id[] =
{
{ "type", ATTR_INPUT_TYPE },
{ "center", ATTR_INPUT_CENTER },
{ "mapping", ATTR_INPUT_MAPPING },
{ "", 0 },
};
static STRING_ID step_id[] =
{
{ "1.0", 0x10 },
{ "1.5", 0x15 },
{ "2.0", 0x20 },
{ "2.1", 0x21 },
{ "", 0 },
};
static STRING_ID rom_id[] =
{
{ "prog0", ROMTYPE_PROG0 },
{ "prog1", ROMTYPE_PROG1 },
{ "prog2", ROMTYPE_PROG2 },
{ "prog3", ROMTYPE_PROG3 },
{ "crom00", ROMTYPE_CROM00 },
{ "crom01", ROMTYPE_CROM01 },
{ "crom02", ROMTYPE_CROM02 },
{ "crom03", ROMTYPE_CROM03 },
{ "crom10", ROMTYPE_CROM10 },
{ "crom11", ROMTYPE_CROM11 },
{ "crom12", ROMTYPE_CROM12 },
{ "crom13", ROMTYPE_CROM13 },
{ "crom20", ROMTYPE_CROM20 },
{ "crom21", ROMTYPE_CROM21 },
{ "crom22", ROMTYPE_CROM22 },
{ "crom23", ROMTYPE_CROM23 },
{ "crom30", ROMTYPE_CROM30 },
{ "crom31", ROMTYPE_CROM31 },
{ "crom32", ROMTYPE_CROM32 },
{ "crom33", ROMTYPE_CROM33 },
{ "vrom00", ROMTYPE_VROM00 },
{ "vrom01", ROMTYPE_VROM01 },
{ "vrom02", ROMTYPE_VROM02 },
{ "vrom03", ROMTYPE_VROM03 },
{ "vrom04", ROMTYPE_VROM04 },
{ "vrom05", ROMTYPE_VROM05 },
{ "vrom06", ROMTYPE_VROM06 },
{ "vrom07", ROMTYPE_VROM07 },
{ "vrom10", ROMTYPE_VROM10 },
{ "vrom11", ROMTYPE_VROM11 },
{ "vrom12", ROMTYPE_VROM12 },
{ "vrom13", ROMTYPE_VROM13 },
{ "vrom14", ROMTYPE_VROM14 },
{ "vrom15", ROMTYPE_VROM15 },
{ "vrom16", ROMTYPE_VROM16 },
{ "vrom17", ROMTYPE_VROM17 },
{ "sprog", ROMTYPE_SPROG },
{ "srom0", ROMTYPE_SROM0 },
{ "srom1", ROMTYPE_SROM1 },
{ "srom2", ROMTYPE_SROM2 },
{ "srom3", ROMTYPE_SROM3 },
{ "dsbprog", ROMTYPE_DSBPROG },
{ "dsbrom0", ROMTYPE_DSBROM0 },
{ "dsbrom1", ROMTYPE_DSBROM1 },
{ "dsbrom2", ROMTYPE_DSBROM2 },
{ "dsbrom3", ROMTYPE_DSBROM3 },
{ "", 0 },
};
#define INPUT_TYPE_BUTTON 0x10000
#define INPUT_TYPE_ANALOG 0x20000
static STRING_ID input_id[] =
{
{ "button01", INPUT_TYPE_BUTTON | 0 },
{ "button02", INPUT_TYPE_BUTTON | 1 },
{ "button03", INPUT_TYPE_BUTTON | 2 },
{ "button04", INPUT_TYPE_BUTTON | 3 },
{ "button05", INPUT_TYPE_BUTTON | 4 },
{ "button06", INPUT_TYPE_BUTTON | 5 },
{ "button07", INPUT_TYPE_BUTTON | 6 },
{ "button08", INPUT_TYPE_BUTTON | 7 },
{ "button11", INPUT_TYPE_BUTTON | 8 },
{ "button12", INPUT_TYPE_BUTTON | 9 },
{ "button13", INPUT_TYPE_BUTTON | 10 },
{ "button14", INPUT_TYPE_BUTTON | 11 },
{ "button15", INPUT_TYPE_BUTTON | 12 },
{ "button16", INPUT_TYPE_BUTTON | 13 },
{ "button17", INPUT_TYPE_BUTTON | 14 },
{ "button18", INPUT_TYPE_BUTTON | 15 },
{ "analog1", INPUT_TYPE_ANALOG | 0 },
{ "analog2", INPUT_TYPE_ANALOG | 1 },
{ "analog3", INPUT_TYPE_ANALOG | 2 },
{ "analog4", INPUT_TYPE_ANALOG | 3 },
{ "analog5", INPUT_TYPE_ANALOG | 4 },
{ "analog6", INPUT_TYPE_ANALOG | 5 },
{ "analog7", INPUT_TYPE_ANALOG | 6 },
{ "analog8", INPUT_TYPE_ANALOG | 7 },
{ "", 0 },
};
static STRING_ID input_mapping_id[] =
{
{ "p1_button_1", P1_BUTTON_1 },
{ "p1_button_2", P1_BUTTON_2 },
{ "p1_button_3", P1_BUTTON_3 },
{ "p1_button_4", P1_BUTTON_4 },
{ "p1_button_5", P1_BUTTON_5 },
{ "p1_button_6", P1_BUTTON_6 },
{ "p1_button_7", P1_BUTTON_7 },
{ "p1_button_8", P1_BUTTON_8 },
{ "p2_button_1", P2_BUTTON_1 },
{ "p2_button_2", P2_BUTTON_2 },
{ "p2_button_3", P2_BUTTON_3 },
{ "p2_button_4", P2_BUTTON_4 },
{ "p2_button_5", P2_BUTTON_5 },
{ "p2_button_6", P2_BUTTON_6 },
{ "p2_button_7", P2_BUTTON_7 },
{ "p2_button_8", P2_BUTTON_8 },
{ "analog_axis_1", ANALOG_AXIS_1 },
{ "analog_axis_2", ANALOG_AXIS_2 },
{ "analog_axis_3", ANALOG_AXIS_3 },
{ "analog_axis_4", ANALOG_AXIS_4 },
{ "analog_axis_5", ANALOG_AXIS_5 },
{ "analog_axis_6", ANALOG_AXIS_6 },
{ "analog_axis_7", ANALOG_AXIS_7 },
{ "analog_axis_8", ANALOG_AXIS_8 },
{ "p1_joystick_up", P1_JOYSTICK_UP },
{ "p1_joystick_down", P1_JOYSTICK_DOWN },
{ "p1_joystick_left", P1_JOYSTICK_LEFT },
{ "p1_joystick_right", P1_JOYSTICK_RIGHT },
{ "p2_joystick_up", P2_JOYSTICK_UP },
{ "p2_joystick_down", P2_JOYSTICK_DOWN },
{ "p2_joystick_left", P2_JOYSTICK_LEFT },
{ "p2_joystick_right", P2_JOYSTICK_RIGHT },
{ "", 0 },
};
static UINT8 *romlist;
static ROMSET *romset;
static int current_attr;
static int current_element;
static int current_rom;
static int current_romset;
static int current_patch;
static int current_input;
static void XMLCALL element_start(void *data, const char *el, const char **attr)
{
int element = get_string_id(el, element_id);
if (element < 0)
{
message(0, "Unknown element %s while parsing XML file\n", el);
}
else
{
current_element = element;
switch (element)
{
case ELEMENT_ROM:
{
int i=0;
// handle ROM types
while (attr[i] != NULL)
{
int id = get_string_id(attr[i], rom_attr_id);
if (id >= 0)
{
current_attr = id;
}
else
{
// not a type
switch (current_attr)
{
case ATTR_ROM_TYPE:
{
int romtype = get_string_id(attr[i], rom_id);
romset[current_romset].rom[current_rom].type = romtype;
break;
}
case ATTR_ROM_NAME:
{
strcpy(romset[current_romset].rom[current_rom].name, attr[i]);
break;
}
case ATTR_ROM_SIZE:
{
int romsize;
sscanf(attr[i], "%d", &romsize);
romset[current_romset].rom[current_rom].size = romsize;
break;
}
case ATTR_ROM_CRC:
{
UINT32 romcrc;
sscanf(attr[i], "%X", &romcrc);
romset[current_romset].rom[current_rom].crc32 = romcrc;
break;
}
case ATTR_ROM_SHA1:
{
// not handled
break;
}
}
}
i++;
};
break;
}
case ELEMENT_GAME:
{
int i=0;
while (attr[i] != NULL)
{
int id = get_string_id(attr[i], game_attr_id);
if (id >= 0)
{
current_attr = id;
}
else
{
switch (current_attr)
{
case ATTR_GAME_NAME:
{
strcpy(romset[current_romset].game, attr[i]);
break;
}
case ATTR_GAME_PARENT:
{
strcpy(romset[current_romset].parent, attr[i]);
break;
}
}
}
i++;
};
break;
}
case ELEMENT_PATCH:
{
int i=0;
while (attr[i] != NULL)
{
int id = get_string_id(attr[i], patch_attr_id);
if (id >= 0)
{
current_attr = id;
}
else
{
switch (current_attr)
{
case ATTR_PATCH_SIZE:
{
int patch_size;
sscanf(attr[i], "%d", &patch_size);
romset[current_romset].patch[current_patch].size = patch_size;
break;
}
case ATTR_PATCH_ADDRESS:
{
UINT32 address;
sscanf(attr[i], "%X", &address);
romset[current_romset].patch[current_patch].address = address;
break;
}
case ATTR_PATCH_DATA:
{
UINT32 data;
sscanf(attr[i], "%X", &data);
romset[current_romset].patch[current_patch].data = data;
break;
}
}
}
i++;
};
break;
}
case ELEMENT_INPUT:
{
int i=0;
while (attr[i] != NULL)
{
int id = get_string_id(attr[i], input_attr_id);
if (id >= 0)
{
current_attr = id;
}
else
{
switch (current_attr)
{
case ATTR_INPUT_TYPE:
{
current_input = get_string_id(attr[i], input_id);
if (current_input & INPUT_TYPE_BUTTON)
{
int button = current_input & 0xffff;
int set = (button / 8) & 1;
int bit = 1 << (button % 8);
romset[current_romset].controls.button[button].enabled = 1;
romset[current_romset].controls.button[button].control_set = set;
romset[current_romset].controls.button[button].control_bit = bit;
}
else if (current_input & INPUT_TYPE_ANALOG)
{
int axis = current_input & 0xffff;
romset[current_romset].controls.analog_axis[axis].enabled = 1;
}
break;
}
case ATTR_INPUT_CENTER:
{
if (current_input & INPUT_TYPE_ANALOG)
{
int axis = current_input & 0xffff;
int center;
sscanf(attr[i], "%d", &center);
romset[current_romset].controls.analog_axis[axis].center = center;
}
break;
}
case ATTR_INPUT_MAPPING:
{
int mapping = get_string_id(attr[i], input_mapping_id);
if (current_input & INPUT_TYPE_BUTTON)
{
int button = current_input & 0xffff;
romset[current_romset].controls.button[button].mapping = mapping;
}
else if (current_input & INPUT_TYPE_ANALOG)
{
int axis = current_input & 0xffff;
romset[current_romset].controls.analog_axis[axis].mapping = mapping;
}
break;
}
}
}
i++;
};
break;
}
}
}
}
static void XMLCALL element_end(void *data, const char *el)
{
int element = get_string_id(el, element_id);
if (element < 0)
{
message(0, "Unknown element %s while parsing XML\n", el);
}
else
{
switch (element)
{
case ELEMENT_ROM:
{
current_rom++;
current_element = ELEMENT_GAMELIST;
break;
}
case ELEMENT_GAME:
{
romset[current_romset].num_patches = current_patch;
current_romset++;
current_rom = 0;
current_patch = 0;
current_element = ELEMENT_GAMELIST;
break;
}
case ELEMENT_DESCRIPTION:
case ELEMENT_YEAR:
case ELEMENT_MANUFACTURER:
case ELEMENT_STEP:
case ELEMENT_BRIDGE:
case ELEMENT_CROMSIZE:
{
current_element = ELEMENT_GAMELIST;
break;
}
case ELEMENT_PATCH:
{
current_patch++;
current_element = ELEMENT_GAMELIST;
break;
}
}
}
}
static void XMLCALL character_data(void *data, const char *s, int len)
{
char temp[2000];
memcpy(temp, s, len);
temp[len] = 0;
switch (current_element)
{
case ELEMENT_DESCRIPTION:
{
strcpy(romset[current_romset].title, temp);
break;
}
case ELEMENT_YEAR:
{
int year;
sscanf(temp, "%d", &year);
romset[current_romset].year = year;
break;
}
case ELEMENT_MANUFACTURER:
{
strcpy(romset[current_romset].manufacturer, temp);
break;
}
case ELEMENT_STEP:
{
int step = get_string_id(temp, step_id);
if (step >= 0)
{
romset[current_romset].step = step;
}
else
{
message(0, "Invalid step %s while parsing XML file\n", temp);
}
break;
}
case ELEMENT_BRIDGE:
{
if (_stricmp(temp, "mpc106") == 0)
{
romset[current_romset].bridge = 2;
}
else
{
message(0, "Unknown bridge %s while parsing XML file\n", temp);
}
break;
}
case ELEMENT_CROMSIZE:
{
if (_stricmp(temp, "64M") == 0)
{
romset[current_romset].cromsize = 1;
}
else
{
message(0, "Unknown cromsize %s while parsing XML file\n", temp);
}
break;
}
}
}
int parse_romlist(char *romlist_name, ROMSET *_romset)
{
XML_Parser parser;
int length;
FILE *file;
file = open_file(FILE_READ|FILE_BINARY, "%s", romlist_name);
if (file == NULL)
{
message(0, "Couldn't open %s", romlist_name);
return 0;
}
length = (int)get_open_file_size(file);
romlist = (UINT8*)malloc(length);
if (!read_from_file(file, romlist, length))
{
message(0, "I/O error while reading %s", romlist_name);
return 0;
}
close_file(file);
romset = _romset;
// parse the XML file
parser = XML_ParserCreate(NULL);
XML_SetElementHandler(parser, element_start, element_end);
XML_SetCharacterDataHandler(parser, character_data);
if (XML_Parse(parser, romlist, length, 1) != XML_STATUS_OK)
{
message(0, "Error while parsing the XML file %s", romlist_name);
return 0;
}
XML_ParserFree(parser);
return current_romset;
}