usbloadergx/source/xml/xml.cpp
dimok321 f3ef9104b1 *Whole lot of cleanup in the cfg.c
*Moved all related global settings to a settings class. one for themes and individual games will follow. Probably broke some settings or theme loading, we can deal with that later and fix when someone discovers bugs.
2010-09-19 20:25:12 +00:00

892 lines
32 KiB
C++

/*
Load game information from XML - Lustar
- Mini-XML by Michael Sweet
- MiniZip adapted by Tantric
*/
#include <malloc.h>
#include "unzip/unzip.h"
#include "settings/CSettings.h"
#include "xml/xml.h"
extern "C" {
extern void title_set( char *id, char *title );
extern char* trimcopy( char *dest, char *src, int size );
extern char game_partition[6];
}
/* config */
static bool xmldebug = false;
static char xmlcfg_filename[100] = "wiitdb";
static int xmlmaxsize = 1572864;
struct gameXMLinfo gameinfo;
struct gameXMLinfo gameinfo_reset;
static char langlist[11][22] = {{"Console Default"},
{"Japanese"},
{"English"},
{"German"},
{"French"},
{"Spanish"},
{"Italian"},
{"Dutch"},
{"S. Chinese"},
{"T. Chinese"},
{"Korean"}
};
static char langcodes[11][5] = {{""},
{"JA"},
{"EN"},
{"DE"},
{"FR"},
{"ES"},
{"IT"},
{"NL"},
{"ZHCN"}, // People's Republic of China
{"ZHTW"}, // Taiwan
{"KO"}
};
static char element_text[5000];
static mxml_node_t *nodetree = NULL;
static mxml_node_t *nodedata = NULL;
static mxml_node_t *nodeid = NULL;
static mxml_node_t *nodeidtmp = NULL;
static mxml_node_t *nodefound = NULL;
static mxml_index_t *nodeindex = NULL;
static mxml_index_t *nodeindextmp = NULL;
int xmlloadtime = 0;
char * get_nodetext( mxml_node_t *node, char *buffer, int buflen );
bool xml_loaded = false;
/* load renamed titles from proper names and game info XML, needs to be after cfg_load_games */
bool OpenXMLDatabase( char* xmlfilepath, char* argdblang, bool argJPtoEN, bool openfile, bool loadtitles, bool keepopen )
{
if ( !xml_loaded )
{
bool opensuccess = false;
char pathname[200];
snprintf( pathname, sizeof( pathname ), "%s", xmlfilepath );
if ( xmlfilepath[strlen( xmlfilepath ) - 1] != '/' ) snprintf( pathname, sizeof( pathname ), "%s/", pathname );
snprintf( pathname, sizeof( pathname ), "%s%s_%s.zip", pathname, xmlcfg_filename, game_partition );
if ( openfile ) opensuccess = OpenXMLFile( pathname );
if ( !opensuccess )
{
snprintf( pathname, sizeof( pathname ), "%s", xmlfilepath );
if ( xmlfilepath[strlen( xmlfilepath ) - 1] != '/' ) snprintf( pathname, sizeof( pathname ), "%s/", pathname );
snprintf( pathname, sizeof( pathname ), "%swiitdb.zip", pathname );
if ( openfile ) opensuccess = OpenXMLFile( pathname );
}
if ( !opensuccess && openfile )
{
CloseXMLDatabase();
return false;
}
if ( loadtitles ) LoadTitlesFromXML( argdblang, argJPtoEN );
if ( !keepopen ) CloseXMLDatabase();
}
else
{
if ( loadtitles ) LoadTitlesFromXML( argdblang, argJPtoEN );
if ( !keepopen ) CloseXMLDatabase();
}
return true;
}
void CloseXMLDatabase()
{
/* free memory */
if ( xml_loaded )
{
mxmlDelete( nodedata );
mxmlDelete( nodetree );
xml_loaded = false;
}
}
void GetTextFromNode( mxml_node_t *currentnode, mxml_node_t *topnode, const char *nodename,
const char *attributename, char *value, int descend, char *dest, int destsize )
{
*element_text = 0;
nodefound = mxmlFindElement( currentnode, topnode, nodename, attributename, value, descend );
if ( nodefound != NULL )
{
if ( attributename != NULL )
{
strlcpy( dest, mxmlElementGetAttr( nodefound, attributename ), destsize );
}
else
{
get_nodetext( nodefound, element_text, sizeof( element_text ) );
strlcpy( dest, element_text, destsize );
}
}
else
{
strcpy( dest, "" );
}
}
bool OpenXMLFile( char *filename )
{
//if (xmldebug) dbg_time1();
if ( xml_loaded )
return false;
gameinfo = gameinfo_reset;
nodedata = NULL;
nodetree = NULL;
nodeid = NULL;
nodeidtmp = NULL;
nodefound = NULL;
char* strresult = strstr( filename, ".zip" );
if ( strresult == NULL )
{
/* Load XML file */
FILE *filexml;
filexml = fopen( filename, "rb" );
if ( !filexml )
return false;
nodetree = mxmlLoadFile( NULL, filexml, MXML_OPAQUE_CALLBACK );
fclose( filexml );
}
else
{
/* load zipped XML file */
unzFile unzfile = unzOpen( filename );
if ( unzfile == NULL )
return false;
unzOpenCurrentFile( unzfile );
unz_file_info zipfileinfo;
unzGetCurrentFileInfo( unzfile, &zipfileinfo, NULL, 0, NULL, 0, NULL, 0 );
int zipfilebuffersize = zipfileinfo.uncompressed_size;
if ( zipfilebuffersize >= xmlmaxsize )
{
unzCloseCurrentFile( unzfile );
unzClose( unzfile );
return false;
}
char * zipfilebuffer = (char *) malloc( zipfilebuffersize );
memset( zipfilebuffer, 0, zipfilebuffersize );
if ( zipfilebuffer == NULL )
{
unzCloseCurrentFile( unzfile );
unzClose( unzfile );
return false;
}
unzReadCurrentFile( unzfile, zipfilebuffer, zipfilebuffersize );
unzCloseCurrentFile( unzfile );
unzClose( unzfile );
nodetree = mxmlLoadString( NULL, zipfilebuffer, MXML_OPAQUE_CALLBACK );
free( zipfilebuffer );
}
if ( nodetree == NULL )
return false;
nodedata = mxmlFindElement( nodetree, nodetree, "datafile", NULL, NULL, MXML_DESCEND );
if ( nodedata == NULL )
{
return false;
}
else
{
//if (xmldebug) xmlloadtime = dbg_time2(NULL);
xml_loaded = true;
return true;
}
}
char *GetLangSettingFromGame( char *gameid )
{
int langcode;
struct Game_CFG *game_cfg = NULL;
game_cfg = CFG_get_game_opt( ( u8* )gameid );
if ( game_cfg )
{
langcode = game_cfg->language;
}
else
{
//langcode = CFG.language; // for Configurable Loader
langcode = Settings.language; // for Loader GX
}
char *langtxt = langlist[langcode];
return langtxt;
}
/* convert language text into ISO 639 two-letter language code (+ZHTW/ZHCN) */
const char *ConvertLangTextToCode( char *languagetxt )
{
// do not convert if languagetext seems to be a language code (can be 2 or 4 letters)
if ( strlen( languagetxt ) <= 4 )
return languagetxt;
int i;
for ( i = 0; i <= 10; i++ )
{
if ( !strcasecmp( languagetxt, langlist[i] ) ) // case insensitive comparison
return langcodes[i];
}
return "";
}
char ConvertRatingToIndex( char *ratingtext )
{
int type = -1;
if ( !strcmp( ratingtext, "CERO" ) )
{
type = 0;
}
if ( !strcmp( ratingtext, "ESRB" ) )
{
type = 1;
}
if ( !strcmp( ratingtext, "PEGI" ) )
{
type = 2;
}
return type;
}
void ConvertRating( char *ratingvalue, char *fromrating, const char *torating, char *destvalue, int destsize )
{
if ( !strcmp( fromrating, torating ) )
{
strlcpy( destvalue, ratingvalue, destsize );
return;
}
strcpy( destvalue, "" );
int type = -1;
int desttype = -1;
type = ConvertRatingToIndex( fromrating );
desttype = ConvertRatingToIndex( (char *) torating );
if ( type == -1 || desttype == -1 )
return;
/* rating conversion table */
/* the list is ordered to pick the most likely value first: */
/* EC and AO are less likely to be used so they are moved down to only be picked up when converting ESRB to PEGI or CERO */
/* the conversion can never be perfect because ratings can differ between regions for the same game */
char ratingtable[12][3][5] =
{
{{"A"}, {"E"}, {"3"}},
{{"A"}, {"E"}, {"4"}},
{{"A"}, {"E"}, {"6"}},
{{"A"}, {"E"}, {"7"}},
{{"A"}, {"EC"}, {"3"}},
{{"A"}, {"E10+"}, {"7"}},
{{"B"}, {"T"}, {"12"}},
{{"D"}, {"M"}, {"18"}},
{{"D"}, {"M"}, {"16"}},
{{"C"}, {"T"}, {"16"}},
{{"C"}, {"T"}, {"15"}},
{{"Z"}, {"AO"}, {"18"}},
};
int i;
for ( i = 0; i <= 11; i++ )
{
if ( !strcmp( ratingtable[i][type], ratingvalue ) )
{
strlcpy( destvalue, ratingtable[i][desttype], destsize );
return;
}
}
}
void LoadTitlesFromXML( char *langtxt, bool forcejptoen )
/* langtxt: set to "English","French","German", to force language for all titles, or "" to load title depending on each game's setting */
/* forcejptoen: set to true to load English title instead of Japanese title when game is set to Japanese */
{
if ( nodedata == NULL )
return;
bool forcelang = false;
if ( strcmp( langtxt, "" ) )
forcelang = true;
char langcode[10] = "";
if ( forcelang )
strcpy( langcode, ConvertLangTextToCode( langtxt ) ); /* convert language text into ISO 639 two-letter language code */
/* create index of <id> elements */
nodeindex = mxmlIndexNew( nodedata, "id", NULL );
nodeid = mxmlIndexReset( nodeindex );
*element_text = 0;
char id_text[10];
char title_text[200] = "";
char title_text_EN[200] = "";
/* search index of id elements, load all id/titles text */
while ( nodeid != NULL )
{
nodeid = mxmlIndexFind( nodeindex, "id", NULL );
if ( nodeid != NULL )
{
strcpy( title_text, "" );
strcpy( title_text_EN, "" );
get_nodetext( nodeid, element_text, sizeof( element_text ) );
snprintf( id_text, 7, "%s", element_text );
// if language is not forced, use game language setting from config
if ( !forcelang )
{
langtxt = GetLangSettingFromGame( id_text );
strcpy( langcode, ConvertLangTextToCode( langtxt ) );
}
/* if enabled, force English title for all games set to Japanese */
if ( forcejptoen && ( !strcmp( langcode, "JA" ) ) )
strcpy( langcode, "EN" );
/* load title from nodes */
nodefound = mxmlFindElement( nodeid, nodedata, "locale", "lang", "EN", MXML_NO_DESCEND );
if ( nodefound != NULL )
{
GetTextFromNode( nodefound, nodedata, "title", NULL, NULL, MXML_DESCEND, title_text_EN, sizeof( title_text_EN ) );
}
nodefound = mxmlFindElement( nodeid, nodedata, "locale", "lang", langcode, MXML_NO_DESCEND );
if ( nodefound != NULL )
{
GetTextFromNode( nodefound, nodedata, "title", NULL, NULL, MXML_DESCEND, title_text, sizeof( title_text ) );
}
/* fall back to English title if prefered language was not found */
if ( !strcmp( title_text, "" ) )
{
strcpy( title_text, title_text_EN );
}
snprintf( id_text, 7, "%s", id_text );
title_set( id_text, title_text );
}
}
// free memory
mxmlIndexDelete( nodeindex );
//if (xmldebug) xmlloadtime = dbg_time2(NULL);
}
void GetPublisherFromGameid( char *idtxt, char *dest, int destsize )
{
/* guess publisher from company list using last two characters from game id */
nodeindextmp = mxmlIndexNew( nodedata, "company", NULL );
nodeidtmp = mxmlIndexReset( nodeindextmp );
*element_text = 0;
char publishercode[3];
sprintf( publishercode, "%c%c", idtxt[4], idtxt[5] );
while ( strcmp( element_text, publishercode ) != 0 )
{
nodeidtmp = mxmlIndexFind( nodeindextmp, "company", NULL );
if ( nodeidtmp != NULL )
{
strlcpy( element_text, mxmlElementGetAttr( nodeidtmp, "code" ), sizeof( element_text ) );
}
else
{
break;
}
}
if ( !strcmp( element_text, publishercode ) )
{
strlcpy( dest, mxmlElementGetAttr( nodeidtmp, "name" ), destsize );
}
else
{
strcpy( dest, "" );
}
// free memory
mxmlIndexDelete( nodeindextmp );
}
bool LoadGameInfoFromXML( char* gameid, char* langtxt )
/* gameid: full game id */
/* langtxt: "English","French","German" */
{
bool exist = false;
if ( !xml_loaded || nodedata == NULL )
return exist;
// load game info using forced language, or game individual setting, or main language setting
char langcode[100] = "";
if ( !strcmp( langtxt, "" ) )
langtxt = GetLangSettingFromGame( gameid );
strlcpy( langcode, ConvertLangTextToCode( langtxt ), sizeof( langcode ) );
/* reset all game info */
gameinfo = gameinfo_reset;
/* index all IDs */
nodeindex = mxmlIndexNew( nodedata, "id", NULL );
nodeid = mxmlIndexReset( nodeindex );
*element_text = 0;
/* search for game matching gameid */
while ( 1 )
{
nodeid = mxmlIndexFind( nodeindex, "id", NULL );
if ( nodeid != NULL )
{
get_nodetext( nodeid, element_text, sizeof( element_text ) );
if ( !strcmp( element_text, gameid ) )
{
break;
}
}
else
{
break;
}
}
if ( !strcmp( element_text, gameid ) )
{
/* text from elements */
strlcpy( gameinfo.id, element_text, sizeof( gameinfo.id ) );
GetTextFromNode( nodeid, nodedata, "region", NULL, NULL, MXML_NO_DESCEND, gameinfo.region, sizeof( gameinfo.region ) );
GetTextFromNode( nodeid, nodedata, "version", NULL, NULL, MXML_NO_DESCEND, gameinfo.version, sizeof( gameinfo.version ) );
GetTextFromNode( nodeid, nodedata, "genre", NULL, NULL, MXML_NO_DESCEND, gameinfo.genre, sizeof( gameinfo.genre ) );
GetTextFromNode( nodeid, nodedata, "developer", NULL, NULL, MXML_NO_DESCEND, gameinfo.developer, sizeof( gameinfo.developer ) );
GetTextFromNode( nodeid, nodedata, "publisher", NULL, NULL, MXML_NO_DESCEND, gameinfo.publisher, sizeof( gameinfo.publisher ) );
GetPublisherFromGameid( gameid, gameinfo.publisherfromid, sizeof( gameinfo.publisherfromid ) );
/* text from attributes */
GetTextFromNode( nodeid, nodedata, "date", "year", NULL, MXML_NO_DESCEND, gameinfo.year, sizeof( gameinfo.year ) );
GetTextFromNode( nodeid, nodedata, "date", "month", NULL, MXML_NO_DESCEND, gameinfo.month, sizeof( gameinfo.month ) );
GetTextFromNode( nodeid, nodedata, "date", "day", NULL, MXML_NO_DESCEND, gameinfo.day, sizeof( gameinfo.day ) );
GetTextFromNode( nodeid, nodedata, "rating", "type", NULL, MXML_NO_DESCEND, gameinfo.ratingtype, sizeof( gameinfo.ratingtype ) );
GetTextFromNode( nodeid, nodedata, "rating", "value", NULL, MXML_NO_DESCEND, gameinfo.ratingvalue, sizeof( gameinfo.ratingvalue ) );
GetTextFromNode( nodeid, nodedata, "rom", "crc", NULL, MXML_NO_DESCEND, gameinfo.iso_crc, sizeof( gameinfo.iso_crc ) );
GetTextFromNode( nodeid, nodedata, "rom", "md5", NULL, MXML_NO_DESCEND, gameinfo.iso_md5, sizeof( gameinfo.iso_md5 ) );
GetTextFromNode( nodeid, nodedata, "rom", "sha1", NULL, MXML_NO_DESCEND, gameinfo.iso_sha1, sizeof( gameinfo.iso_sha1 ) );
/* text from child elements */
nodefound = mxmlFindElement( nodeid, nodedata, "locale", "lang", "EN", MXML_NO_DESCEND );
if ( nodefound != NULL )
{
GetTextFromNode( nodefound, nodedata, "title", NULL, NULL, MXML_DESCEND, gameinfo.title_EN, sizeof( gameinfo.title_EN ) );
GetTextFromNode( nodefound, nodedata, "synopsis", NULL, NULL, MXML_DESCEND, gameinfo.synopsis_EN, sizeof( gameinfo.synopsis_EN ) );
}
nodefound = mxmlFindElement( nodeid, nodedata, "locale", "lang", langcode, MXML_NO_DESCEND );
if ( nodefound != NULL )
{
GetTextFromNode( nodefound, nodedata, "title", NULL, NULL, MXML_DESCEND, gameinfo.title, sizeof( gameinfo.title ) );
GetTextFromNode( nodefound, nodedata, "synopsis", NULL, NULL, MXML_DESCEND, gameinfo.synopsis, sizeof( gameinfo.synopsis ) );
}
// fall back to English title and synopsis if prefered language was not found
if ( !strcmp( gameinfo.title, "" ) )
{
strlcpy( gameinfo.title, gameinfo.title_EN, sizeof( gameinfo.title ) );
}
if ( !strcmp( gameinfo.synopsis, "" ) )
{
strlcpy( gameinfo.synopsis, gameinfo.synopsis_EN, sizeof( gameinfo.synopsis ) );
}
/* list locale lang attributes */
nodefound = mxmlFindElement( nodeid, nodedata, "locale", "lang", NULL, MXML_NO_DESCEND );
if ( nodefound != NULL )
{
int incr = 0;
while ( nodefound != NULL )
{
++incr;
strlcpy( gameinfo.locales[incr], mxmlElementGetAttr( nodefound, "lang" ), sizeof( gameinfo.locales[incr] ) );
nodefound = mxmlWalkNext( nodefound, nodedata, MXML_NO_DESCEND );
if ( nodefound != NULL )
{
nodefound = mxmlFindElement( nodefound, nodedata, "locale", "lang", NULL, MXML_NO_DESCEND );
}
}
}
/* unbounded child elements */
GetTextFromNode( nodeid, nodedata, "wi-fi", "players", NULL, MXML_NO_DESCEND, gameinfo.wifiplayers, sizeof( gameinfo.wifiplayers ) );
nodefound = mxmlFindElement( nodeid, nodedata, "wi-fi", NULL, NULL, MXML_NO_DESCEND );
if ( nodefound != NULL )
{
gameinfo.wifiCnt = 0;
nodeindextmp = mxmlIndexNew( nodefound, "feature", NULL );
nodeidtmp = mxmlIndexReset( nodeindextmp );
while ( nodeidtmp != NULL )
{
nodeidtmp = mxmlIndexFind( nodeindextmp, "feature", NULL );
if ( nodeidtmp != NULL )
{
++gameinfo.wifiCnt;
GetTextFromNode( nodeidtmp, nodedata, "feature", NULL, NULL, MXML_DESCEND, gameinfo.wififeatures[gameinfo.wifiCnt],
sizeof( gameinfo.wififeatures[gameinfo.wifiCnt] ) );
gameinfo.wififeatures[gameinfo.wifiCnt][0] = toupper( ( int )gameinfo.wififeatures[gameinfo.wifiCnt][0] );
if ( gameinfo.wifiCnt == XML_ELEMMAX )
break;
}
}
mxmlIndexDelete( nodeindextmp ); // placed after each mxmlIndexNew to prevent memory leak
}
nodefound = mxmlFindElement( nodeid, nodedata, "rating", NULL, NULL, MXML_NO_DESCEND );
if ( nodefound != NULL )
{
gameinfo.descriptorCnt = 0;
nodeindextmp = mxmlIndexNew( nodefound, "descriptor", NULL );
nodeidtmp = mxmlIndexReset( nodeindextmp );
while ( nodeidtmp != NULL )
{
nodeidtmp = mxmlIndexFind( nodeindextmp, "descriptor", NULL );
if ( nodeidtmp != NULL )
{
++gameinfo.descriptorCnt;
GetTextFromNode( nodeidtmp, nodedata, "descriptor", NULL, NULL, MXML_DESCEND,
gameinfo.ratingdescriptors[gameinfo.descriptorCnt], sizeof( gameinfo.ratingdescriptors[gameinfo.descriptorCnt] ) );
if ( gameinfo.descriptorCnt == XML_ELEMMAX )
break;
}
}
mxmlIndexDelete( nodeindextmp );
}
GetTextFromNode( nodeid, nodedata, "input", "players", NULL, MXML_NO_DESCEND, gameinfo.players, sizeof( gameinfo.players ) );
nodefound = mxmlFindElement( nodeid, nodedata, "input", NULL, NULL, MXML_NO_DESCEND );
if ( nodefound != NULL )
{
gameinfo.accessoryCnt = 0;
gameinfo.accessoryReqCnt = 0;
nodeindextmp = mxmlIndexNew( nodefound, "control", NULL );
nodeidtmp = mxmlIndexReset( nodeindextmp );
while ( nodeidtmp != NULL )
{
nodeidtmp = mxmlIndexFind( nodeindextmp, "control", NULL );
if ( nodeidtmp != NULL )
{
if ( !strcmp( mxmlElementGetAttr( nodeidtmp, "required" ), "true" ) && gameinfo.accessoryReqCnt < XML_ELEMMAX )
{
++gameinfo.accessoryReqCnt;
strlcpy( gameinfo.accessoriesReq[gameinfo.accessoryReqCnt], mxmlElementGetAttr( nodeidtmp, "type" ),
sizeof( gameinfo.accessoriesReq[gameinfo.accessoryReqCnt] ) );
}
else if ( gameinfo.accessoryCnt < XML_ELEMMAX )
{
++gameinfo.accessoryCnt;
strlcpy( gameinfo.accessories[gameinfo.accessoryCnt], mxmlElementGetAttr( nodeidtmp, "type" ),
sizeof( gameinfo.accessories[gameinfo.accessoryCnt] ) );
}
}
}
mxmlIndexDelete( nodeindextmp );
}
/* convert rating value */
ConvertRating( gameinfo.ratingvalue, gameinfo.ratingtype, "CERO", gameinfo.ratingvalueCERO, sizeof( gameinfo.ratingvalueCERO ) );
ConvertRating( gameinfo.ratingvalue, gameinfo.ratingtype, "ESRB", gameinfo.ratingvalueESRB, sizeof( gameinfo.ratingvalueESRB ) );
ConvertRating( gameinfo.ratingvalue, gameinfo.ratingtype, "PEGI", gameinfo.ratingvaluePEGI, sizeof( gameinfo.ratingvaluePEGI ) );
/* provide genre as an array: gameinfo.genresplit */
if ( strcmp( gameinfo.genre, "" ) != 0 )
{
gameinfo.genreCnt = 0;
const char *delimgenre = ",;";
char genretxt[200];
strlcpy( genretxt, gameinfo.genre, sizeof( genretxt ) );
char *splitresult;
splitresult = strtok( genretxt, delimgenre );
if ( splitresult != NULL )
{
++gameinfo.genreCnt;
trimcopy( splitresult, splitresult, strlen( splitresult ) + 1 );
strlcpy( gameinfo.genresplit[gameinfo.genreCnt], splitresult, sizeof( gameinfo.genresplit[gameinfo.genreCnt] ) );
gameinfo.genresplit[gameinfo.genreCnt][0] = toupper( ( int )gameinfo.genresplit[gameinfo.genreCnt][0] );
while ( splitresult != NULL )
{
splitresult = strtok( NULL, delimgenre );
if ( splitresult != NULL && strcmp( splitresult, "" ) != 0 )
{
++gameinfo.genreCnt;
trimcopy( splitresult, splitresult, strlen( splitresult ) + 1 );
strlcpy( gameinfo.genresplit[gameinfo.genreCnt], splitresult, sizeof( gameinfo.genresplit[gameinfo.genreCnt] ) );
gameinfo.genresplit[gameinfo.genreCnt][0] = toupper( ( int )gameinfo.genresplit[gameinfo.genreCnt][0] );
if ( gameinfo.genreCnt == XML_ELEMMAX )
break;
}
}
}
}
exist = true;
}
else
{
/*game not found */
exist = false;
}
// if game was not found or info is missing
// guess publisher from game id in case it is missing
if ( !strcmp( gameinfo.publisher, "" ) )
{
GetPublisherFromGameid( gameid, gameinfo.publisherfromid, sizeof( gameinfo.publisherfromid ) );
strlcpy( gameinfo.publisher, gameinfo.publisherfromid, sizeof( gameinfo.publisher ) );
}
// if missing, get region from game ID
if ( !strcmp( gameinfo.region, "" ) )
{
if ( gameid[3] == 'E' ) strlcpy( gameinfo.region, "NTSC-U", sizeof( gameinfo.region ) );
if ( gameid[3] == 'J' ) strlcpy( gameinfo.region, "NTSC-J", sizeof( gameinfo.region ) );
if ( gameid[3] == 'W' ) strlcpy( gameinfo.region, "NTSC-J", sizeof( gameinfo.region ) );
if ( gameid[3] == 'K' ) strlcpy( gameinfo.region, "NTSC-K", sizeof( gameinfo.region ) );
if ( gameid[3] == 'P' ) strlcpy( gameinfo.region, "PAL", sizeof( gameinfo.region ) );
if ( gameid[3] == 'D' ) strlcpy( gameinfo.region, "PAL", sizeof( gameinfo.region ) );
if ( gameid[3] == 'F' ) strlcpy( gameinfo.region, "PAL", sizeof( gameinfo.region ) );
if ( gameid[3] == 'I' ) strlcpy( gameinfo.region, "PAL", sizeof( gameinfo.region ) );
if ( gameid[3] == 'S' ) strlcpy( gameinfo.region, "PAL", sizeof( gameinfo.region ) );
if ( gameid[3] == 'H' ) strlcpy( gameinfo.region, "PAL", sizeof( gameinfo.region ) );
if ( gameid[3] == 'U' ) strlcpy( gameinfo.region, "PAL", sizeof( gameinfo.region ) );
if ( gameid[3] == 'X' ) strlcpy( gameinfo.region, "PAL", sizeof( gameinfo.region ) );
if ( gameid[3] == 'Y' ) strlcpy( gameinfo.region, "PAL", sizeof( gameinfo.region ) );
if ( gameid[3] == 'Z' ) strlcpy( gameinfo.region, "PAL", sizeof( gameinfo.region ) );
}
// free memory
mxmlIndexDelete( nodeindex );
return exist;
}
void PrintGameInfo( bool showfullinfo )
{
if ( showfullinfo )
{
//Con_Clear();
//printf("id: %s version: %s region: %s",gameinfo.id, gameinfo.version, gameinfo.region);
//printf("title: %s\n",gameinfo.title);
int i;
printf( "languages:" );
for ( i = 1; strcmp( gameinfo.locales[i], "" ) != 0; i++ )
{
printf( " %s", gameinfo.locales[i] );
}
printf( "\n" );
//printf("developer: %s\n",gameinfo.developer);
//printf("publisher: %s\n",gameinfo.publisher);
//printf("publisher from ID: %s\n",gameinfo.publisherfromid);
printf( "year:%s month:%s day:%s\n", gameinfo.year, gameinfo.month, gameinfo.day );
printf( "genre: %s\n", gameinfo.genre );
//printf("rating: %s %s (CERO: %s ESRB: %s PEGI: %s)\n",gameinfo.ratingtype, gameinfo.ratingvalue,
// gameinfo.ratingvalueCERO,gameinfo.ratingvalueESRB,gameinfo.ratingvaluePEGI);
printf( "content descriptors:" );
for ( i = 1; strcmp( gameinfo.wififeatures[i], "" ) != 0; i++ )
{
printf( " %s", gameinfo.ratingdescriptors[i] );
}
printf( "\n" );
printf( "players: %s online: %s\n", gameinfo.players, gameinfo.wifiplayers );
printf( "online features:" );
for ( i = 1; strcmp( gameinfo.wififeatures[i], "" ) != 0; i++ )
{
printf( " %s", gameinfo.wififeatures[i] );
}
printf( "\n" );
printf( "required accessories:" );
for ( i = 1; strcmp( gameinfo.accessoriesReq[i], "" ) != 0; i++ )
{
printf( " %s", gameinfo.accessoriesReq[i] );
}
printf( "\n" );
printf( "accessories:" );
for ( i = 1; strcmp( gameinfo.accessories[i], "" ) != 0; i++ )
{
printf( " %s", gameinfo.accessories[i] );
}
printf( "\n" );
//printf("iso_crc: %s iso_md5: %s\n",gameinfo.iso_crc,gameinfo.iso_md5);
//printf("iso_sha1: %s\n",gameinfo.iso_sha1);
//printf("synopsis: %s\n",gameinfo.synopsis);
}
else
{
char linebuf[1000] = "";
if ( xmldebug )
{
//char xmltime[100];
//sprintf(xmltime,"%d",xmlloadtime);
//printf("xml load time: %s\n",xmltime);
/*
printf("xml forcelang: %s\n",CFG.db_lang);
printf("xml url: %s\n",CFG.db_url);
printf("xml file: %s\n",CFG.db_filename);
char xmljptoen[100];
sprintf(xmljptoen,"%d",CFG.db_JPtoEN);
printf("xml JPtoEN: %s\n",xmljptoen);
*/
printf( MemInfo() ); // guidebug
}
//printf("%s: ",gameidfull);
//printf("%s\n",gameinfo.title);
if ( strcmp( gameinfo.year, "" ) != 0 )
snprintf( linebuf, sizeof( linebuf ), "%s ", gameinfo.year );
if ( strcmp( gameinfo.publisher, "" ) != 0 )
snprintf( linebuf, sizeof( linebuf ), "%s%s", linebuf, gameinfo.publisher );
if ( strcmp( gameinfo.developer, "" ) != 0 && strcmp( gameinfo.developer, gameinfo.publisher ) != 0 )
snprintf( linebuf, sizeof( linebuf ), "%s / %s", linebuf, gameinfo.developer );
if ( strlen( linebuf ) >= 100 )
{
char buffer[200] = "";
strlcpy( buffer, linebuf, 100 );
strcat( buffer, "..." );
snprintf( linebuf, sizeof( linebuf ), "%s", buffer );
}
printf( "%s\n", linebuf );
strcpy( linebuf, "" );
if ( strcmp( gameinfo.ratingvalue, "" ) != 0 )
{
snprintf( linebuf, sizeof( linebuf ), "rated %s", gameinfo.ratingvalue );
if ( !strcmp( gameinfo.ratingtype, "PEGI" ) )
snprintf( linebuf, sizeof( linebuf ), "%s+ ", linebuf );
snprintf( linebuf, sizeof( linebuf ), "%s ", linebuf );
}
if ( strcmp( gameinfo.players, "" ) != 0 )
{
snprintf( linebuf, sizeof( linebuf ), "%sfor %s player", linebuf, gameinfo.players );
if ( atoi( gameinfo.players ) > 1 )
snprintf( linebuf, sizeof( linebuf ), "%ss", linebuf );
if ( atoi( gameinfo.wifiplayers ) > 1 )
snprintf( linebuf, sizeof( linebuf ), "%s (%s online)", linebuf, gameinfo.wifiplayers );
}
printf( "%s\n", linebuf );
strcpy( linebuf, "" );
}
}
char *MemInfo()
{
char linebuf[300] = "";
char memtotal[20];
char memused[20];
char memnotinuse[20];
char memcanbefreed[20];
struct mallinfo mymallinfo = mallinfo();
sprintf( memtotal, "%d", mymallinfo.arena / 1024 );
sprintf( memused, "%d", mymallinfo.uordblks / 1024 );
sprintf( memnotinuse, "%d", mymallinfo.fordblks / 1024 );
sprintf( memcanbefreed, "%d", mymallinfo.keepcost / 1024 );
snprintf( linebuf, sizeof( linebuf ), "all:%sKB used:%sKB notused:%sKB canfree:%sKB", memtotal, memused, memnotinuse, memcanbefreed );
char *minfo[300];
*minfo = linebuf;
return *minfo;
}
/*-------------------------------------------------------------------------------------*/
/* get_nodetext() - Get the text for a node, taken from mini-mxml example mxmldoc.c */
char * get_nodetext( mxml_node_t *node, char *buffer, int buflen ) /* O - Text in node, I - Node to get, I - Buffer, I - Size of buffer */
{
char *ptr, *end; /* Pointer into buffer, End of buffer */
int len; /* Length of node */
mxml_node_t *current; /* Current node */
ptr = buffer;
end = buffer + buflen - 1;
for ( current = node->child; current && ptr < end; current = current->next )
{
if ( current->type == MXML_TEXT )
{
if ( current->value.text.whitespace )
*ptr++ = ' ';
len = ( int )strlen( current->value.text.string );
if ( len > ( int )( end - ptr ) )
len = ( int )( end - ptr );
memcpy( ptr, current->value.text.string, len );
ptr += len;
}
else if ( current->type == MXML_OPAQUE )
{
len = ( int )strlen( current->value.opaque );
if ( len > ( int )( end - ptr ) )
len = ( int )( end - ptr );
memcpy( ptr, current->value.opaque, len );
ptr += len;
}
}
*ptr = '\0';
return ( buffer );
}
int GetRatingForGame( char *gameid )
{
int retval = -1;
if ( !xml_loaded || nodedata == NULL )
return -1;
/* index all IDs */
nodeindex = mxmlIndexNew( nodedata, "id", NULL );
nodeid = mxmlIndexReset( nodeindex );
*element_text = 0;
/* search for game matching gameid */
while ( 1 )
{
nodeid = mxmlIndexFind( nodeindex, "id", NULL );
if ( nodeid != NULL )
{
get_nodetext( nodeid, element_text, sizeof( element_text ) );
if ( !strcmp( element_text, gameid ) )
{
break;
}
}
else
{
break;
}
}
if ( !strcmp( element_text, gameid ) )
{
char type[5], value[5], dest[5];
GetTextFromNode( nodeid, nodedata, "rating", "type", NULL, MXML_NO_DESCEND, type, sizeof( type ) );
GetTextFromNode( nodeid, nodedata, "rating", "value", NULL, MXML_NO_DESCEND, value, sizeof( value ) );
ConvertRating( value, type, "PEGI", dest, sizeof( dest ) );
retval = atoi( dest );
}
return retval;
}