mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-22 03:09:15 +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">
|
<app version="1">
|
||||||
<name> USB Loader GX</name>
|
<name> USB Loader GX</name>
|
||||||
<coder>USB Loader GX Team</coder>
|
<coder>USB Loader GX Team</coder>
|
||||||
<version>2.3 r1136</version>
|
<version>2.3 r1137</version>
|
||||||
<release_date>201112231542</release_date>
|
<release_date>201112232158</release_date>
|
||||||
<!-- // remove this line to enable arguments
|
<!-- // remove this line to enable arguments
|
||||||
<arguments>
|
<arguments>
|
||||||
<arg>--ios=250</arg>
|
<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());
|
ShowProgress(i, gameList.size());
|
||||||
|
|
||||||
vector<string> genreList;
|
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))
|
if(!XML_DB.GetGenreList((const char *) gameList[i]->id, genreList))
|
||||||
continue;
|
continue;
|
||||||
@ -384,6 +393,7 @@ bool CGameCategories::ImportFromGameTDB(const string &xmlpath)
|
|||||||
|
|
||||||
this->SetCategory(gameList[i]->id, CategoryList.getCurrentID());
|
this->SetCategory(gameList[i]->id, CategoryList.getCurrentID());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XML_DB.CloseFile();
|
XML_DB.CloseFile();
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
// Global app entry point
|
// Global app entry point
|
||||||
extern u32 AppEntrypoint;
|
extern u32 AppEntrypoint;
|
||||||
void _unstub_start();
|
|
||||||
|
|
||||||
/* Constants */
|
/* Constants */
|
||||||
#define PTABLE_OFFSET 0x40000
|
#define PTABLE_OFFSET 0x40000
|
||||||
@ -289,32 +288,46 @@ s32 Disc_JumpToEntrypoint(s32 hooktype, u32 dolparameter)
|
|||||||
/* Originally from tueidj - taken from NeoGamme (thx) */
|
/* Originally from tueidj - taken from NeoGamme (thx) */
|
||||||
*(vu32*)0xCC003024 = dolparameter != 0 ? dolparameter : 1;
|
*(vu32*)0xCC003024 = dolparameter != 0 ? dolparameter : 1;
|
||||||
|
|
||||||
if(AppEntrypoint == 0x3400 && hooktype)
|
if(AppEntrypoint == 0x3400)
|
||||||
{
|
{
|
||||||
__asm__(
|
if(hooktype)
|
||||||
"lis %r3, returnpoint@h\n"
|
{
|
||||||
"ori %r3, %r3, returnpoint@l\n"
|
__asm__(
|
||||||
"mtlr %r3\n"
|
"lis %r3, returnpoint@h\n"
|
||||||
"lis %r3, 0x8000\n"
|
"ori %r3, %r3, returnpoint@l\n"
|
||||||
"ori %r3, %r3, 0x18A8\n"
|
"mtlr %r3\n"
|
||||||
"mtctr %r3\n"
|
"lis %r3, 0x8000\n"
|
||||||
"bctr\n"
|
"ori %r3, %r3, 0x18A8\n"
|
||||||
"returnpoint:\n"
|
"mtctr %r3\n"
|
||||||
"bl DCDisable\n"
|
"bctr\n"
|
||||||
"bl ICDisable\n"
|
"returnpoint:\n"
|
||||||
"li %r3, 0\n"
|
"bl DCDisable\n"
|
||||||
"mtsrr1 %r3\n"
|
"bl ICDisable\n"
|
||||||
"lis %r4, AppEntrypoint@h\n"
|
"li %r3, 0\n"
|
||||||
"ori %r4,%r4,AppEntrypoint@l\n"
|
"mtsrr1 %r3\n"
|
||||||
"lwz %r4, 0(%r4)\n"
|
"lis %r4, AppEntrypoint@h\n"
|
||||||
"mtsrr0 %r4\n"
|
"ori %r4,%r4,AppEntrypoint@l\n"
|
||||||
"rfi\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)
|
else if (hooktype)
|
||||||
{
|
{
|
||||||
__asm__(
|
__asm__(
|
||||||
|
@ -390,6 +390,8 @@ bool GameTDB::ParseFile()
|
|||||||
const char * gameNode = NULL;
|
const char * gameNode = NULL;
|
||||||
const char * idNode = NULL;
|
const char * idNode = NULL;
|
||||||
const char * gameEndNode = NULL;
|
const char * gameEndNode = NULL;
|
||||||
|
const char * genreNode = NULL;
|
||||||
|
const char * descriptNode = NULL;
|
||||||
|
|
||||||
while((read = GetData(Line, currentPos, MAXREADSIZE)) > 0)
|
while((read = GetData(Line, currentPos, MAXREADSIZE)) > 0)
|
||||||
{
|
{
|
||||||
@ -399,6 +401,34 @@ bool GameTDB::ParseFile()
|
|||||||
//! Ensure the null termination at the end
|
//! Ensure the null termination at the end
|
||||||
Line[read] = '\0';
|
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)
|
while((gameNode = strstr(gameNode, "<game name=\"")) != NULL)
|
||||||
{
|
{
|
||||||
idNode = strstr(gameNode, "<id>");
|
idNode = strstr(gameNode, "<id>");
|
||||||
@ -670,9 +700,81 @@ bool GameTDB::GetGenreList(const char * id, vector<string> & genre)
|
|||||||
|
|
||||||
delete [] data;
|
delete [] data;
|
||||||
|
|
||||||
|
if(strcmp(LangCode.c_str(), "EN") != 0)
|
||||||
|
TranslateGenres(genre);
|
||||||
|
|
||||||
return true;
|
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)
|
const char * GameTDB::RatingToString(int rating)
|
||||||
{
|
{
|
||||||
switch(rating)
|
switch(rating)
|
||||||
@ -873,9 +975,67 @@ int GameTDB::GetRatingDescriptorList(const char * id, vector<string> & desc_list
|
|||||||
|
|
||||||
delete [] data;
|
delete [] data;
|
||||||
|
|
||||||
|
if(strcmp(LangCode.c_str(), "EN") != 0)
|
||||||
|
TranslateDescriptors(desc_list);
|
||||||
|
|
||||||
return desc_list.size();
|
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 GameTDB::GetWifiPlayers(const char * id)
|
||||||
{
|
{
|
||||||
int players = -1;
|
int players = -1;
|
||||||
@ -896,6 +1056,8 @@ int GameTDB::GetWifiPlayers(const char * id)
|
|||||||
|
|
||||||
players = atoi(PlayersNode);
|
players = atoi(PlayersNode);
|
||||||
|
|
||||||
|
delete [] data;
|
||||||
|
|
||||||
return players;
|
return players;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -968,6 +1130,8 @@ int GameTDB::GetPlayers(const char * id)
|
|||||||
|
|
||||||
players = atoi(PlayersNode);
|
players = atoi(PlayersNode);
|
||||||
|
|
||||||
|
delete [] data;
|
||||||
|
|
||||||
return players;
|
return players;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1051,9 +1215,34 @@ int GameTDB::GetCaseColor(const char * id)
|
|||||||
|
|
||||||
color = strtoul(ColorNode, NULL, 16);
|
color = strtoul(ColorNode, NULL, 16);
|
||||||
|
|
||||||
|
delete [] data;
|
||||||
|
|
||||||
return color;
|
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)
|
bool GameTDB::GetGameXMLInfo(const char * id, GameXMLInfo * gameInfo)
|
||||||
{
|
{
|
||||||
if(!id || !gameInfo)
|
if(!id || !gameInfo)
|
||||||
@ -1072,7 +1261,7 @@ bool GameTDB::GetGameXMLInfo(const char * id, GameXMLInfo * gameInfo)
|
|||||||
GetGenreList(id, gameInfo->GenreList);
|
GetGenreList(id, gameInfo->GenreList);
|
||||||
gameInfo->RatingType = GetRating(id);
|
gameInfo->RatingType = GetRating(id);
|
||||||
GetRatingValue(id, gameInfo->RatingValue);
|
GetRatingValue(id, gameInfo->RatingValue);
|
||||||
GetRatingDescriptorList(id, gameInfo->RatingDescriptorList);
|
//GetRatingDescriptorList(id, gameInfo->RatingDescriptorList); We don't use it yet
|
||||||
gameInfo->WifiPlayers = GetWifiPlayers(id);
|
gameInfo->WifiPlayers = GetWifiPlayers(id);
|
||||||
GetWifiFeatureList(id, gameInfo->WifiFeatureList);
|
GetWifiFeatureList(id, gameInfo->WifiFeatureList);
|
||||||
gameInfo->Players = GetPlayers(id);
|
gameInfo->Players = GetPlayers(id);
|
||||||
|
@ -123,6 +123,12 @@ class GameTDB
|
|||||||
int GetCaseColor(const char * id);
|
int GetCaseColor(const char * id);
|
||||||
//! Get the complete game info in the GameXMLInfo struct
|
//! Get the complete game info in the GameXMLInfo struct
|
||||||
bool GetGameXMLInfo(const char * id, GameXMLInfo * gameInfo);
|
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
|
//! Convert a specific game rating to a string
|
||||||
static const char * RatingToString(int rating);
|
static const char * RatingToString(int rating);
|
||||||
//! Convert a rating string to a rating number
|
//! Convert a rating string to a rating number
|
||||||
|
Loading…
Reference in New Issue
Block a user