*added import of channel type on category import from GameTDB (VC-N64, WiiWare.....)

*added translations parse for rating descriptors (not used yet) and for genres. requires one time update of wiitdb.xml for cache rebuild.
*fixed a few mem leaks in GameTDB parser
This commit is contained in:
strtoul 2011-12-23 22:04:27 +00:00
parent 54fc7320f9
commit 26c0ee7ce9
6 changed files with 246 additions and 46 deletions

View File

@ -2,8 +2,8 @@
<app version="1">
<name> USB Loader GX</name>
<coder>USB Loader GX Team</coder>
<version>2.3 r1136</version>
<release_date>201112231542</release_date>
<version>2.3 r1137</version>
<release_date>201112232158</release_date>
<!-- // remove this line to enable arguments
<arguments>
<arg>--ios=250</arg>

View File

@ -1,18 +0,0 @@
#define STUB 0x3400
.text
.section .text
.globl _unstub_start
_unstub_start:
isync
// set MSR[DR:IR] = 00, jump to STUB
lis 3,STUB@h
ori 3,3,STUB@l
mtsrr0 3
mfmsr 3
li 4,0x30
andc 3,3,4
mtsrr1 3
rfi

View File

@ -373,6 +373,15 @@ bool CGameCategories::ImportFromGameTDB(const string &xmlpath)
ShowProgress(i, gameList.size());
vector<string> genreList;
string GameType;
if(XML_DB.GetGameType((const char *) gameList[i]->id, GameType))
{
if(!CategoryList.findCategory(GameType))
CategoryList.AddCategory(GameType);
this->SetCategory(gameList[i]->id, CategoryList.getCurrentID());
}
if(!XML_DB.GetGenreList((const char *) gameList[i]->id, genreList))
continue;
@ -384,6 +393,7 @@ bool CGameCategories::ImportFromGameTDB(const string &xmlpath)
this->SetCategory(gameList[i]->id, CategoryList.getCurrentID());
}
}
XML_DB.CloseFile();

View File

@ -19,7 +19,6 @@
// Global app entry point
extern u32 AppEntrypoint;
void _unstub_start();
/* Constants */
#define PTABLE_OFFSET 0x40000
@ -289,32 +288,46 @@ s32 Disc_JumpToEntrypoint(s32 hooktype, u32 dolparameter)
/* Originally from tueidj - taken from NeoGamme (thx) */
*(vu32*)0xCC003024 = dolparameter != 0 ? dolparameter : 1;
if(AppEntrypoint == 0x3400 && hooktype)
if(AppEntrypoint == 0x3400)
{
__asm__(
"lis %r3, returnpoint@h\n"
"ori %r3, %r3, returnpoint@l\n"
"mtlr %r3\n"
"lis %r3, 0x8000\n"
"ori %r3, %r3, 0x18A8\n"
"mtctr %r3\n"
"bctr\n"
"returnpoint:\n"
"bl DCDisable\n"
"bl ICDisable\n"
"li %r3, 0\n"
"mtsrr1 %r3\n"
"lis %r4, AppEntrypoint@h\n"
"ori %r4,%r4,AppEntrypoint@l\n"
"lwz %r4, 0(%r4)\n"
"mtsrr0 %r4\n"
"rfi\n"
);
if(hooktype)
{
__asm__(
"lis %r3, returnpoint@h\n"
"ori %r3, %r3, returnpoint@l\n"
"mtlr %r3\n"
"lis %r3, 0x8000\n"
"ori %r3, %r3, 0x18A8\n"
"mtctr %r3\n"
"bctr\n"
"returnpoint:\n"
"bl DCDisable\n"
"bl ICDisable\n"
"li %r3, 0\n"
"mtsrr1 %r3\n"
"lis %r4, AppEntrypoint@h\n"
"ori %r4,%r4,AppEntrypoint@l\n"
"lwz %r4, 0(%r4)\n"
"mtsrr0 %r4\n"
"rfi\n"
);
}
else
{
__asm__(
"isync\n"
"lis %r3, AppEntrypoint@h\n"
"ori %r3, %r3, AppEntrypoint@l\n"
"lwz %r3, 0(%r3)\n"
"mtsrr0 %r3\n"
"mfmsr %r3\n"
"li %r4, 0x30\n"
"andc %r3, %r3, %r4\n"
"mtsrr1 %r3\n"
"rfi\n"
);
}
}
else if(AppEntrypoint == 0x3400)
{
_unstub_start();
}
else if (hooktype)
{
__asm__(

View File

@ -390,6 +390,8 @@ bool GameTDB::ParseFile()
const char * gameNode = NULL;
const char * idNode = NULL;
const char * gameEndNode = NULL;
const char * genreNode = NULL;
const char * descriptNode = NULL;
while((read = GetData(Line, currentPos, MAXREADSIZE)) > 0)
{
@ -399,6 +401,34 @@ bool GameTDB::ParseFile()
//! Ensure the null termination at the end
Line[read] = '\0';
//! Try to find genre translation map
if(!genreNode && (genreNode = strstr(gameNode, "<genres>")) != NULL)
{
const char *genreNodeEnd = strstr(genreNode, "</genres>");
if(genreNodeEnd)
{
int size = OffsetMap.size();
OffsetMap.resize(size+1);
strcpy(OffsetMap[size].gameID, "gnrmap");
OffsetMap[size].gamenode = currentPos+(genreNode-Line);
OffsetMap[size].nodesize = (genreNodeEnd-genreNode);
}
}
//! Try to find description translation map
if(!descriptNode && (descriptNode = strstr(gameNode, "<descriptors>")) != NULL)
{
const char *descriptNodeEnd = strstr(descriptNode, "</descriptors>");
if(descriptNodeEnd)
{
int size = OffsetMap.size();
OffsetMap.resize(size+1);
strcpy(OffsetMap[size].gameID, "dscmap");
OffsetMap[size].gamenode = currentPos+(descriptNode-Line);
OffsetMap[size].nodesize = (descriptNodeEnd-descriptNode);
}
}
while((gameNode = strstr(gameNode, "<game name=\"")) != NULL)
{
idNode = strstr(gameNode, "<id>");
@ -670,9 +700,81 @@ bool GameTDB::GetGenreList(const char * id, vector<string> & genre)
delete [] data;
if(strcmp(LangCode.c_str(), "EN") != 0)
TranslateGenres(genre);
return true;
}
void GameTDB::TranslateGenres(vector<string> &GenreList)
{
char * data = GetGameNode("gnrmap");
if(!data)
return;
for(unsigned int i = 0; i < GenreList.size(); ++i)
{
for(unsigned int n = 0; n < 2; n++)
{
string nodeStart;
if(n == 0)
nodeStart = "<genre name=\"";
else
nodeStart = "<subgenre name=\"";
nodeStart += GenreList[i];
const char *genreNode = strcasestr(data, nodeStart.c_str());
if(!genreNode)
continue;
genreNode += nodeStart.size();
const char *genreNodeEnd = strstr(genreNode, "</genre>");
const char *subNodeStart = strstr(genreNode, "<subgenre name=");
if(!genreNodeEnd || (subNodeStart && subNodeStart < genreNodeEnd))
genreNodeEnd = subNodeStart;
if(!genreNodeEnd)
continue;
string localStr = "<locale lang=\"";
localStr += LangCode;
localStr += "\">";
const char *langPtr = strcasestr(genreNode, localStr.c_str());
if(langPtr && langPtr < genreNodeEnd)
{
bool firstLetter = true;
GenreList[i].clear();
langPtr += localStr.size();
while(*langPtr == ' ')
langPtr++;
while(*langPtr != 0 && !(langPtr[0] == '<' && langPtr[1] == '/'))
{
if(firstLetter)
{
GenreList[i].push_back(toupper((int)*langPtr));
firstLetter = false;
}
else
GenreList[i].push_back(*langPtr);
langPtr++;
}
while(GenreList[i].size() > 0 && GenreList[i][GenreList[i].size()-1] == ' ')
GenreList[i].erase(GenreList[i].size()-1);
}
break;
}
}
delete [] data;
}
const char * GameTDB::RatingToString(int rating)
{
switch(rating)
@ -873,9 +975,67 @@ int GameTDB::GetRatingDescriptorList(const char * id, vector<string> & desc_list
delete [] data;
if(strcmp(LangCode.c_str(), "EN") != 0)
TranslateDescriptors(desc_list);
return desc_list.size();
}
void GameTDB::TranslateDescriptors(vector<string> &DescList)
{
char * data = GetGameNode("dscmap");
if(!data)
return;
for(unsigned int i = 0; i < DescList.size(); ++i)
{
string nodeStart = "<descriptor name=\"";
nodeStart += DescList[i];
const char *genreNode = strcasestr(data, nodeStart.c_str());
if(!genreNode)
continue;
genreNode += nodeStart.size();
const char *genreNodeEnd = strstr(genreNode, "</descriptor>");
if(!genreNodeEnd)
continue;
string localStr = "<locale lang=\"";
localStr += LangCode;
localStr += "\">";
const char *langPtr = strcasestr(genreNode, localStr.c_str());
if(langPtr && langPtr < genreNodeEnd)
{
bool firstLetter = true;
DescList[i].clear();
langPtr += localStr.size();
while(*langPtr == ' ')
langPtr++;
while(*langPtr != 0 && !(langPtr[0] == '<' && langPtr[1] == '/'))
{
if(firstLetter)
{
DescList[i].push_back(toupper((int)*langPtr));
firstLetter = false;
}
else
DescList[i].push_back(*langPtr);
langPtr++;
}
while(DescList[i].size() > 0 && DescList[i][DescList[i].size()-1] == ' ')
DescList[i].erase(DescList[i].size()-1);
}
}
delete [] data;
}
int GameTDB::GetWifiPlayers(const char * id)
{
int players = -1;
@ -896,6 +1056,8 @@ int GameTDB::GetWifiPlayers(const char * id)
players = atoi(PlayersNode);
delete [] data;
return players;
}
@ -968,6 +1130,8 @@ int GameTDB::GetPlayers(const char * id)
players = atoi(PlayersNode);
delete [] data;
return players;
}
@ -1051,9 +1215,34 @@ int GameTDB::GetCaseColor(const char * id)
color = strtoul(ColorNode, NULL, 16);
delete [] data;
return color;
}
bool GameTDB::GetGameType(const char * id, string &GameType)
{
if(!id)
return false;
char * data = GetGameNode(id);
if(!data)
return false;
char * TypeNode = GetNodeText(data, "<type>", "</type>");
if(!TypeNode)
{
delete [] data;
return false;
}
GameType = TypeNode;
delete [] data;
return true;
}
bool GameTDB::GetGameXMLInfo(const char * id, GameXMLInfo * gameInfo)
{
if(!id || !gameInfo)
@ -1072,7 +1261,7 @@ bool GameTDB::GetGameXMLInfo(const char * id, GameXMLInfo * gameInfo)
GetGenreList(id, gameInfo->GenreList);
gameInfo->RatingType = GetRating(id);
GetRatingValue(id, gameInfo->RatingValue);
GetRatingDescriptorList(id, gameInfo->RatingDescriptorList);
//GetRatingDescriptorList(id, gameInfo->RatingDescriptorList); We don't use it yet
gameInfo->WifiPlayers = GetWifiPlayers(id);
GetWifiFeatureList(id, gameInfo->WifiFeatureList);
gameInfo->Players = GetPlayers(id);

View File

@ -123,6 +123,12 @@ class GameTDB
int GetCaseColor(const char * id);
//! Get the complete game info in the GameXMLInfo struct
bool GetGameXMLInfo(const char * id, GameXMLInfo * gameInfo);
//! Get the type of the game. If blank the game is a Wii game.
bool GetGameType(const char * id, string &GameType);
//! Translate genre list to configure language code
void TranslateGenres(vector<string> &GenreList);
//! Translate descriptors list to configure language code
void TranslateDescriptors(vector<string> &DescList);
//! Convert a specific game rating to a string
static const char * RatingToString(int rating);
//! Convert a rating string to a rating number