mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-12-22 18:01:54 +01:00
*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:
parent
54fc7320f9
commit
26c0ee7ce9
@ -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>
|
||||
|
@ -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
|
@ -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();
|
||||
|
@ -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__(
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user