mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-22 11:19:17 +01:00
*Completely rewrote the asynchron GuiImageData class (problems from switch Carousel<->Grid layour should be fixed now)
*Fixed bug mounting a wbfs partition which was formatted from an ext partition *Rewrote the parental control feature. Removed loading pin or settings from the Wii Settings. Parental control is now completely managed in the loader from the settings selected and the password set. *Saving password in config file is now encrypted *Added loop to wait for usb when reloading the cIOS before game start The parental control feature is filtering games like following when usb loader is locked: level 0 (everyone 0+) > shows only games with lvl 0 level 1 (childs 7+) > shows games with lvl 0, 1 level 2 (teens 12+) > shows games with lvl 0, 1, 2 level 3 (mature 16+) > shows games with lvl 0, 1, 2, 3 level 4 (adults only 18+) > shows all games (lvl 0, 1, 2, 3, 4) level 4 is default when creating new configs
This commit is contained in:
parent
3f03d92295
commit
2adc6cc995
@ -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>1.0 r1010</version>
|
<version>1.0 r1015</version>
|
||||||
<release_date>201012051910</release_date>
|
<release_date>201012181321</release_date>
|
||||||
<short_description>Loads games from USB-devices</short_description>
|
<short_description>Loads games from USB-devices</short_description>
|
||||||
<long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times.
|
<long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times.
|
||||||
The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller.
|
The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller.
|
||||||
|
File diff suppressed because one or more lines are too long
@ -125,7 +125,7 @@ void DirList::AddEntrie(const char * folderpath, const char * filename, u64 file
|
|||||||
|
|
||||||
FileInfo.resize(pos+1);
|
FileInfo.resize(pos+1);
|
||||||
|
|
||||||
FileInfo[pos].FilePath = new (std::nothrow) char[strlen(folderpath)+strlen(filename)+1];
|
FileInfo[pos].FilePath = new (std::nothrow) char[strlen(folderpath)+strlen(filename)+2];
|
||||||
if(FileInfo[pos].FilePath)
|
if(FileInfo[pos].FilePath)
|
||||||
sprintf(FileInfo[pos].FilePath, "%s/%s", folderpath, filename);
|
sprintf(FileInfo[pos].FilePath, "%s/%s", folderpath, filename);
|
||||||
FileInfo[pos].FileSize = filesize;
|
FileInfo[pos].FileSize = filesize;
|
||||||
|
65
source/libwiigui/LoadCoverImage.cpp
Normal file
65
source/libwiigui/LoadCoverImage.cpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#include "libwiigui/gui.h"
|
||||||
|
#include "usbloader/disc.h"
|
||||||
|
#include "FileOperations/fileops.h"
|
||||||
|
#include "settings/CSettings.h"
|
||||||
|
#include "themes/CTheme.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* LoadCoverImage
|
||||||
|
***************************************************************************/
|
||||||
|
GuiImageData *LoadCoverImage(struct discHdr *header, bool Prefere3D, bool noCover)
|
||||||
|
{
|
||||||
|
if (!header) return NULL;
|
||||||
|
GuiImageData *Cover = NULL;
|
||||||
|
char ID3[4];
|
||||||
|
char IDfull[7];
|
||||||
|
char Path[255];
|
||||||
|
bool flag = Prefere3D;
|
||||||
|
|
||||||
|
snprintf(ID3, sizeof(ID3), "%s", (char *) header->id);
|
||||||
|
snprintf(IDfull, sizeof(IDfull), "%s", (char *) header->id);
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
char *coverPath = flag ? Settings.covers_path : Settings.covers2d_path;
|
||||||
|
flag = !flag;
|
||||||
|
//Load full id image
|
||||||
|
snprintf(Path, sizeof(Path), "%s%s.png", coverPath, IDfull);
|
||||||
|
|
||||||
|
if(!CheckFile(Path))
|
||||||
|
{
|
||||||
|
snprintf(Path, sizeof(Path), "%s%s.png", coverPath, ID3);
|
||||||
|
if(!CheckFile(Path))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete Cover;
|
||||||
|
Cover = new (std::nothrow) GuiImageData(Path);
|
||||||
|
//Load short id image
|
||||||
|
if (!Cover || !Cover->GetImage())
|
||||||
|
{
|
||||||
|
snprintf(Path, sizeof(Path), "%s%s.png", coverPath, ID3);
|
||||||
|
delete Cover;
|
||||||
|
Cover = new (std::nothrow) GuiImageData(Path);
|
||||||
|
}
|
||||||
|
if (Cover && Cover->GetImage()) break;
|
||||||
|
}
|
||||||
|
//Load no image
|
||||||
|
if (noCover && (!Cover || !Cover->GetImage()))
|
||||||
|
{
|
||||||
|
flag = Prefere3D;
|
||||||
|
for (int i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
flag = !flag;
|
||||||
|
delete Cover;
|
||||||
|
Cover = Resources::GetImageData(flag ? "nocover.png" : "nocoverFlat.png");
|
||||||
|
if (Cover && Cover->GetImage()) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Cover && !Cover->GetImage())
|
||||||
|
{
|
||||||
|
delete Cover;
|
||||||
|
Cover = NULL;
|
||||||
|
}
|
||||||
|
return Cover;
|
||||||
|
}
|
6
source/libwiigui/LoadCoverImage.h
Normal file
6
source/libwiigui/LoadCoverImage.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef LOADCOVERIMAGE_H_
|
||||||
|
#define LOADCOVERIMAGE_H_
|
||||||
|
|
||||||
|
GuiImageData *LoadCoverImage(struct discHdr *header, bool Prefere3D = true, bool noCover = true);
|
||||||
|
|
||||||
|
#endif
|
@ -7,17 +7,18 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "../wpad.h"
|
#include "wpad.h"
|
||||||
#include "../menu.h"
|
#include "menu.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "gui_image_async.h"
|
#include "gui_image_async.h"
|
||||||
#include "gui_gamecarousel.h"
|
#include "gui_gamecarousel.h"
|
||||||
#include "usbloader/GameList.h"
|
#include "usbloader/GameList.h"
|
||||||
#include "settings/GameTitles.h"
|
#include "settings/GameTitles.h"
|
||||||
#include "../settings/CSettings.h"
|
#include "settings/CSettings.h"
|
||||||
|
#include "libwiigui/LoadCoverImage.h"
|
||||||
#include "themes/CTheme.h"
|
#include "themes/CTheme.h"
|
||||||
#include "../main.h"
|
#include "main.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@ -108,8 +109,8 @@ GuiGameCarousel::GuiGameCarousel(int w, int h, const char *themePath, const u8 *
|
|||||||
gamename->SetMaxWidth(280, DOTTED);
|
gamename->SetMaxWidth(280, DOTTED);
|
||||||
|
|
||||||
gameIndex = new int[pagesize];
|
gameIndex = new int[pagesize];
|
||||||
game = new GuiButton *[pagesize];
|
game.resize(pagesize);
|
||||||
coverImg = new GuiImageAsync *[pagesize];
|
coverImg.resize(pagesize);
|
||||||
|
|
||||||
for (int i = 0; i < pagesize; i++)
|
for (int i = 0; i < pagesize; i++)
|
||||||
{
|
{
|
||||||
@ -163,14 +164,14 @@ GuiGameCarousel::~GuiGameCarousel()
|
|||||||
delete trigMinus;
|
delete trigMinus;
|
||||||
delete gamename;
|
delete gamename;
|
||||||
|
|
||||||
for (int i = 0; i < pagesize; i++)
|
GuiImageAsync::ClearQueue();
|
||||||
{
|
|
||||||
|
for (u32 i = 0; i < game.size(); ++i)
|
||||||
delete coverImg[i];
|
delete coverImg[i];
|
||||||
|
for (u32 i = 0; i < game.size(); ++i)
|
||||||
delete game[i];
|
delete game[i];
|
||||||
}
|
|
||||||
delete[] gameIndex;
|
delete[] gameIndex;
|
||||||
delete[] coverImg;
|
|
||||||
delete[] game;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#ifndef _GUIGAMECAROUSEL_H_
|
#ifndef _GUIGAMECAROUSEL_H_
|
||||||
#define _GUIGAMECAROUSEL_H_
|
#define _GUIGAMECAROUSEL_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "../usbloader/disc.h"
|
#include "usbloader/disc.h"
|
||||||
class GuiImageAsync;
|
class GuiImageAsync;
|
||||||
class GuiGameCarousel: public GuiElement
|
class GuiGameCarousel: public GuiElement
|
||||||
{
|
{
|
||||||
@ -29,8 +30,8 @@ class GuiGameCarousel: public GuiElement
|
|||||||
int clickedItem;
|
int clickedItem;
|
||||||
|
|
||||||
int * gameIndex;
|
int * gameIndex;
|
||||||
GuiButton ** game;
|
std::vector<GuiButton *> game;
|
||||||
GuiImageAsync ** coverImg;
|
std::vector<GuiImageAsync *> coverImg;
|
||||||
|
|
||||||
GuiText * gamename;
|
GuiText * gamename;
|
||||||
|
|
||||||
|
@ -7,18 +7,19 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "../wpad.h"
|
#include "wpad.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "gui_gamegrid.h"
|
#include "gui_gamegrid.h"
|
||||||
#include "gui_image_async.h"
|
#include "gui_image_async.h"
|
||||||
|
#include "libwiigui/LoadCoverImage.h"
|
||||||
#include "usbloader/GameList.h"
|
#include "usbloader/GameList.h"
|
||||||
#include "settings/GameTitles.h"
|
#include "settings/GameTitles.h"
|
||||||
#include "../settings/CSettings.h"
|
#include "settings/CSettings.h"
|
||||||
#include "themes/CTheme.h"
|
#include "themes/CTheme.h"
|
||||||
#include "../prompts/PromptWindows.h"
|
#include "prompts/PromptWindows.h"
|
||||||
#include "../language/gettext.h"
|
#include "language/gettext.h"
|
||||||
#include "../menu.h"
|
#include "menu.h"
|
||||||
#include "fatmounter.h"
|
#include "fatmounter.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -206,23 +207,10 @@ GuiGameGrid::GuiGameGrid(int w, int h, const char *themePath, const u8 *imagebg,
|
|||||||
{
|
{
|
||||||
width = w;
|
width = w;
|
||||||
height = h;
|
height = h;
|
||||||
// gameCnt = count; will be set later in Reload
|
|
||||||
// gameList = l; will be set later in Reload
|
|
||||||
// listOffset = 0; will be set later in Reload
|
|
||||||
// goLeft = 0; will be set later in Reload
|
|
||||||
// goRight = 0; will be set later in Reload
|
|
||||||
|
|
||||||
selectable = true;
|
selectable = true;
|
||||||
focus = 1; // allow focus
|
focus = 1; // allow focus
|
||||||
// selectedItem = -1; will be set later in Reload
|
|
||||||
// clickedItem = -1; will be set later in Reload
|
|
||||||
/* will be set later in Reload
|
|
||||||
rows = Settings.gridRows;
|
|
||||||
if ((count<45)&&(rows==3))rows=2;
|
|
||||||
if ((count<18)&&(rows==2))rows=1;
|
|
||||||
|
|
||||||
pagesize = ROWS2PAGESIZE(rows);
|
|
||||||
*/
|
|
||||||
trigA = new GuiTrigger;
|
trigA = new GuiTrigger;
|
||||||
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
|
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
|
||||||
trigL = new GuiTrigger;
|
trigL = new GuiTrigger;
|
||||||
@ -274,10 +262,6 @@ GuiGameGrid::GuiGameGrid(int w, int h, const char *themePath, const u8 *imagebg,
|
|||||||
|
|
||||||
// Page-Stuff
|
// Page-Stuff
|
||||||
gameIndex = NULL;
|
gameIndex = NULL;
|
||||||
titleTT = NULL;
|
|
||||||
// cover = NULL;
|
|
||||||
coverImg = NULL;
|
|
||||||
game = NULL;
|
|
||||||
|
|
||||||
Reload(Settings.gridRows, 0);
|
Reload(Settings.gridRows, 0);
|
||||||
}
|
}
|
||||||
@ -301,17 +285,22 @@ GuiGameGrid::~GuiGameGrid()
|
|||||||
delete trig1;
|
delete trig1;
|
||||||
delete trig2;
|
delete trig2;
|
||||||
|
|
||||||
for (int i = pagesize - 1; i >= 0; i--)
|
GuiImageAsync::ClearQueue();
|
||||||
{
|
|
||||||
delete game[i];
|
|
||||||
delete coverImg[i];
|
|
||||||
delete titleTT[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] gameIndex;
|
for (u32 i = 0; i < game.size(); ++i)
|
||||||
delete[] game;
|
delete game[i];
|
||||||
delete[] coverImg;
|
|
||||||
delete[] titleTT;
|
for (u32 i = 0; i < coverImg.size(); ++i)
|
||||||
|
delete coverImg[i];
|
||||||
|
|
||||||
|
for (u32 i = 0; i < titleTT.size(); ++i)
|
||||||
|
delete titleTT[i];
|
||||||
|
|
||||||
|
if(gameIndex)
|
||||||
|
delete [] gameIndex;
|
||||||
|
game.clear();
|
||||||
|
coverImg.clear();
|
||||||
|
titleTT.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiGameGrid::SetFocus(int f)
|
void GuiGameGrid::SetFocus(int f)
|
||||||
@ -447,7 +436,6 @@ void GuiGameGrid::Draw()
|
|||||||
*/
|
*/
|
||||||
void GuiGameGrid::ChangeRows(int n)
|
void GuiGameGrid::ChangeRows(int n)
|
||||||
{
|
{
|
||||||
LOCK( this );
|
|
||||||
if (n != rows) Reload(n, -1);
|
if (n != rows) Reload(n, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,10 +477,7 @@ void GuiGameGrid::Update(GuiTrigger * t)
|
|||||||
|
|
||||||
if (btnLeft->GetState() == STATE_CLICKED)
|
if (btnLeft->GetState() == STATE_CLICKED)
|
||||||
{
|
{
|
||||||
WPAD_ScanPads();
|
u32 buttons = t->wpad.btns_h;
|
||||||
u16 buttons = 0;
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
buttons |= WPAD_ButtonsHeld(i);
|
|
||||||
if (!((buttons & WPAD_BUTTON_A) || (buttons & WPAD_BUTTON_MINUS) || t->Left()))
|
if (!((buttons & WPAD_BUTTON_A) || (buttons & WPAD_BUTTON_MINUS) || t->Left()))
|
||||||
{
|
{
|
||||||
btnLeft->ResetState();
|
btnLeft->ResetState();
|
||||||
@ -505,10 +490,7 @@ void GuiGameGrid::Update(GuiTrigger * t)
|
|||||||
}
|
}
|
||||||
else if (btnRight->GetState() == STATE_CLICKED)
|
else if (btnRight->GetState() == STATE_CLICKED)
|
||||||
{
|
{
|
||||||
WPAD_ScanPads();
|
u32 buttons = t->wpad.btns_h;
|
||||||
u16 buttons = 0;
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
buttons |= WPAD_ButtonsHeld(i);
|
|
||||||
if (!((buttons & WPAD_BUTTON_A) || (buttons & WPAD_BUTTON_PLUS) || t->Right()))
|
if (!((buttons & WPAD_BUTTON_A) || (buttons & WPAD_BUTTON_PLUS) || t->Right()))
|
||||||
{
|
{
|
||||||
btnRight->ResetState();
|
btnRight->ResetState();
|
||||||
@ -721,25 +703,24 @@ void GuiGameGrid::Reload(int Rows, int ListOffset)
|
|||||||
{
|
{
|
||||||
LOCK( this );
|
LOCK( this );
|
||||||
|
|
||||||
|
//Prevent to wait before all images are loaded before we can delete them
|
||||||
|
GuiImageAsync::ClearQueue();
|
||||||
|
|
||||||
// CleanUp
|
// CleanUp
|
||||||
if (game) for (int i = pagesize - 1; i >= 0; i--)
|
for (u32 i = 0; i < game.size(); ++i)
|
||||||
delete game[i];
|
delete game[i];
|
||||||
|
|
||||||
if (coverImg) for (int i = pagesize - 1; i >= 0; i--)
|
for (u32 i = 0; i < coverImg.size(); ++i)
|
||||||
delete coverImg[i];
|
delete coverImg[i];
|
||||||
|
|
||||||
// if(cover)
|
for (u32 i = 0; i < titleTT.size(); ++i)
|
||||||
// for(int i=pagesize-1; i>=0; i--)
|
|
||||||
// delete cover[i];
|
|
||||||
|
|
||||||
if (titleTT) for (int i = pagesize - 1; i >= 0; i--)
|
|
||||||
delete titleTT[i];
|
delete titleTT[i];
|
||||||
|
|
||||||
delete[] gameIndex;
|
if(gameIndex)
|
||||||
delete[] game;
|
delete [] gameIndex;
|
||||||
delete[] coverImg;
|
game.clear();
|
||||||
// delete [] cover;
|
coverImg.clear();
|
||||||
delete[] titleTT;
|
titleTT.clear();
|
||||||
|
|
||||||
goLeft = 0;
|
goLeft = 0;
|
||||||
goRight = 0;
|
goRight = 0;
|
||||||
@ -759,10 +740,9 @@ void GuiGameGrid::Reload(int Rows, int ListOffset)
|
|||||||
|
|
||||||
// Page-Stuff
|
// Page-Stuff
|
||||||
gameIndex = new int[pagesize];
|
gameIndex = new int[pagesize];
|
||||||
titleTT = new GuiTooltip *[pagesize];
|
titleTT.resize(pagesize);
|
||||||
// cover = new GuiImageData *[pagesize];
|
coverImg.resize(pagesize);
|
||||||
coverImg = new GuiImageAsync *[pagesize];
|
game.resize(pagesize);
|
||||||
game = new GuiButton *[pagesize];
|
|
||||||
|
|
||||||
int wsi = Settings.widescreen ? 0 : 1;
|
int wsi = Settings.widescreen ? 0 : 1;
|
||||||
int (*Pos)[2][2] = VALUE4ROWS( rows, Pos1, Pos2, Pos3 );
|
int (*Pos)[2][2] = VALUE4ROWS( rows, Pos1, Pos2, Pos3 );
|
||||||
@ -799,8 +779,7 @@ void GuiGameGrid::Reload(int Rows, int ListOffset)
|
|||||||
coverImg[i] = NULL;
|
coverImg[i] = NULL;
|
||||||
if (gameIndex[i] != -1)
|
if (gameIndex[i] != -1)
|
||||||
{
|
{
|
||||||
coverImg[i] = new GuiImageAsync(GameGridLoadCoverImage, gameList[gameIndex[i]], sizeof(struct discHdr),
|
coverImg[i] = new GuiImageAsync(GameGridLoadCoverImage, gameList[gameIndex[i]], sizeof(struct discHdr), &noCover);
|
||||||
&noCover);
|
|
||||||
if (coverImg[i])
|
if (coverImg[i])
|
||||||
{
|
{
|
||||||
coverImg[i]->SetWidescreen(Settings.widescreen);
|
coverImg[i]->SetWidescreen(Settings.widescreen);
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#ifndef _GUIGAMEGRID_H_
|
#ifndef _GUIGAMEGRID_H_
|
||||||
#define _GUIGAMEGRID_H_
|
#define _GUIGAMEGRID_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "../usbloader/disc.h"
|
#include "usbloader/disc.h"
|
||||||
|
|
||||||
class GuiImageAsync;
|
class GuiImageAsync;
|
||||||
class GuiGameGrid: public GuiElement
|
class GuiGameGrid: public GuiElement
|
||||||
{
|
{
|
||||||
@ -30,9 +32,9 @@ class GuiGameGrid: public GuiElement
|
|||||||
int goRight;
|
int goRight;
|
||||||
|
|
||||||
int * gameIndex;
|
int * gameIndex;
|
||||||
GuiButton ** game;
|
std::vector<GuiButton *> game;
|
||||||
GuiTooltip ** titleTT;
|
std::vector<GuiTooltip *> titleTT;
|
||||||
GuiImageAsync ** coverImg;
|
std::vector<GuiImageAsync *> coverImg;
|
||||||
|
|
||||||
GuiButton * btnRight;
|
GuiButton * btnRight;
|
||||||
GuiButton * btnLeft;
|
GuiButton * btnLeft;
|
||||||
|
@ -1,187 +1,149 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* libwiigui
|
* USB Loader GX
|
||||||
*
|
|
||||||
* Tantric 2009
|
|
||||||
*
|
*
|
||||||
* gui_imagea_sync.cpp
|
* gui_imagea_sync.cpp
|
||||||
*
|
|
||||||
* GUI class definitions
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include "gui.h"
|
|
||||||
//#include <string.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "gui_image_async.h"
|
#include "gui_image_async.h"
|
||||||
static mutex_t debugLock = LWP_MUTEX_NULL;
|
|
||||||
|
|
||||||
void debug(int Line, const char* Format, ...)
|
std::vector<GuiImageAsync *> GuiImageAsync::List;
|
||||||
|
lwp_t GuiImageAsync::Thread = LWP_THREAD_NULL;
|
||||||
|
mutex_t GuiImageAsync::ListLock = LWP_THREAD_NULL;
|
||||||
|
GuiImageAsync * GuiImageAsync::InUse = NULL;
|
||||||
|
u32 GuiImageAsync::ThreadCount = 0;
|
||||||
|
bool GuiImageAsync::ThreadSleep = true;
|
||||||
|
bool GuiImageAsync::CloseThread = false;
|
||||||
|
|
||||||
|
static inline void * memdup(const void* src, size_t len)
|
||||||
{
|
{
|
||||||
if (debugLock == 0) LWP_MutexInit(&debugLock, false);
|
if(!src) return NULL;
|
||||||
|
|
||||||
LWP_MutexLock(debugLock);
|
|
||||||
|
|
||||||
FILE *fp = fopen("SD:/debug.txt", "a");
|
|
||||||
if (fp)
|
|
||||||
{
|
|
||||||
char theTime[10];
|
|
||||||
time_t rawtime = time(0); //this fixes code dump caused by the clock
|
|
||||||
struct tm * timeinfo = localtime(&rawtime);
|
|
||||||
strftime(theTime, sizeof(theTime), "%H:%M:%S", timeinfo);
|
|
||||||
char format[10 + strlen(Format) + strlen(theTime)];
|
|
||||||
sprintf(format, "%s %i - %s\n", theTime, Line, Format);
|
|
||||||
va_list va;
|
|
||||||
va_start( va, Format );
|
|
||||||
vfprintf(fp, format, va);
|
|
||||||
va_end( va );
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
LWP_MutexUnlock(debugLock);
|
|
||||||
}
|
|
||||||
//#define DEBUG(format, ...) debug(__LINE__, format, ##__VA_ARGS__)
|
|
||||||
#define DEBUG(format, ...)
|
|
||||||
|
|
||||||
static void *memdup(const void* src, size_t len)
|
|
||||||
{
|
|
||||||
void *dst = malloc(len);
|
void *dst = malloc(len);
|
||||||
if (dst) memcpy(dst, src, len);
|
if (dst) memcpy(dst, src, len);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
static std::vector<GuiImageAsync *> List;
|
|
||||||
static u32 ThreadCount = 0;
|
static GuiImageData * StdImageLoaderCallback(void *arg)
|
||||||
static lwp_t Thread = LWP_THREAD_NULL;
|
|
||||||
static mutex_t ListLock = LWP_MUTEX_NULL;
|
|
||||||
static mutex_t InUseLock = LWP_MUTEX_NULL;
|
|
||||||
static GuiImageAsync *InUse = NULL;
|
|
||||||
static bool Quit = false;
|
|
||||||
static bool CanSleep = true;
|
|
||||||
void *GuiImageAsyncThread(void *arg)
|
|
||||||
{
|
{
|
||||||
while (!Quit)
|
return new GuiImageData((char *) arg);
|
||||||
{
|
|
||||||
LWP_MutexLock(ListLock);
|
|
||||||
if (List.size())
|
|
||||||
{
|
|
||||||
LWP_MutexLock(InUseLock);
|
|
||||||
|
|
||||||
InUse = List.front();
|
|
||||||
List.erase(List.begin());
|
|
||||||
|
|
||||||
LWP_MutexUnlock(ListLock);
|
|
||||||
|
|
||||||
if (InUse)
|
|
||||||
{
|
|
||||||
GuiImageData *data = InUse->callback(InUse->arg);
|
|
||||||
InUse->loadet_imgdata = data;
|
|
||||||
if (InUse->loadet_imgdata && InUse->loadet_imgdata->GetImage())
|
|
||||||
{
|
|
||||||
// InUse->SetImage(InUse->loadet_imgdata); can’t use here. There can occur a deadlock
|
|
||||||
// Sets the image directly without lock. This is not fine, but it prevents a deadlock
|
|
||||||
InUse->image = InUse->loadet_imgdata->GetImage();
|
|
||||||
InUse->width = InUse->loadet_imgdata->GetWidth();
|
|
||||||
InUse->height = InUse->loadet_imgdata->GetHeight();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InUse = NULL;
|
|
||||||
LWP_MutexUnlock(InUseLock);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LWP_MutexUnlock(ListLock);
|
|
||||||
if (!Quit && CanSleep) LWP_SuspendThread(Thread);
|
|
||||||
}
|
|
||||||
CanSleep = true;
|
|
||||||
}
|
|
||||||
Quit = false;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 GuiImageAsyncThreadInit()
|
GuiImageAsync::GuiImageAsync(const char *Filename, GuiImageData * PreloadImg) :
|
||||||
|
GuiImage(PreloadImg), imgData(NULL), callback(StdImageLoaderCallback), arg(strdup(Filename))
|
||||||
{
|
{
|
||||||
if (0 == ThreadCount++)
|
ThreadInit();
|
||||||
{
|
ThreadAddImage(this);
|
||||||
CanSleep = false;
|
|
||||||
LWP_MutexInit(&ListLock, false);
|
|
||||||
LWP_MutexInit(&InUseLock, false);
|
|
||||||
LWP_CreateThread(&Thread, GuiImageAsyncThread, NULL, NULL, 16384, 75);
|
|
||||||
// while(!CanSleep)
|
|
||||||
// usleep(20);
|
|
||||||
}
|
|
||||||
return ThreadCount;
|
|
||||||
}
|
|
||||||
static u32 GuiImageAsyncThreadExit()
|
|
||||||
{
|
|
||||||
if (--ThreadCount == 0)
|
|
||||||
{
|
|
||||||
Quit = true;
|
|
||||||
LWP_ResumeThread(Thread);
|
|
||||||
// while(Quit)
|
|
||||||
// usleep(20);
|
|
||||||
LWP_JoinThread(Thread, NULL);
|
|
||||||
LWP_MutexDestroy(ListLock);
|
|
||||||
LWP_MutexDestroy(InUseLock);
|
|
||||||
Thread = LWP_THREAD_NULL;
|
|
||||||
ListLock = LWP_MUTEX_NULL;
|
|
||||||
InUseLock = LWP_MUTEX_NULL;
|
|
||||||
}
|
|
||||||
return ThreadCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GuiImageAsyncThread_AddImage(GuiImageAsync* Image)
|
GuiImageAsync::GuiImageAsync(ImageLoaderCallback Callback, const void * Arg, int ArgLen, GuiImageData * PreloadImg) :
|
||||||
|
GuiImage(PreloadImg), imgData(NULL), callback(Callback), arg(memdup(Arg, ArgLen))
|
||||||
|
{
|
||||||
|
ThreadInit();
|
||||||
|
ThreadAddImage(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiImageAsync::~GuiImageAsync()
|
||||||
|
{
|
||||||
|
ThreadRemoveImage(this);
|
||||||
|
ThreadExit();
|
||||||
|
while(InUse == this) usleep(100);
|
||||||
|
if (imgData) delete imgData;
|
||||||
|
if (arg) free(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImageAsync::ThreadAddImage(GuiImageAsync *Image)
|
||||||
{
|
{
|
||||||
LWP_MutexLock(ListLock);
|
LWP_MutexLock(ListLock);
|
||||||
List.push_back(Image);
|
List.push_back(Image);
|
||||||
LWP_MutexUnlock(ListLock);
|
LWP_MutexUnlock(ListLock);
|
||||||
CanSleep = false;
|
ThreadSleep = false;
|
||||||
// if(LWP_ThreadIsSuspended(Thread))
|
|
||||||
LWP_ResumeThread(Thread);
|
LWP_ResumeThread(Thread);
|
||||||
}
|
}
|
||||||
static void GuiImageAsyncThread_RemoveImage(GuiImageAsync* Image)
|
|
||||||
|
void GuiImageAsync::ThreadRemoveImage(GuiImageAsync *Image)
|
||||||
|
{
|
||||||
|
for(u32 i = 0; i < List.size(); ++i)
|
||||||
|
{
|
||||||
|
if(List[i] == Image)
|
||||||
|
{
|
||||||
|
LWP_MutexLock(ListLock);
|
||||||
|
List.erase(List.begin()+i);
|
||||||
|
LWP_MutexUnlock(ListLock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImageAsync::ClearQueue()
|
||||||
{
|
{
|
||||||
LWP_MutexLock(ListLock);
|
LWP_MutexLock(ListLock);
|
||||||
for (std::vector<GuiImageAsync *>::iterator iter = List.begin(); iter != List.end(); iter++)
|
List.clear();
|
||||||
{
|
|
||||||
if (*iter == Image)
|
|
||||||
{
|
|
||||||
List.erase(iter);
|
|
||||||
LWP_MutexUnlock(ListLock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (InUse == Image)
|
|
||||||
{
|
|
||||||
LWP_MutexLock(InUseLock);
|
|
||||||
LWP_MutexUnlock(InUseLock);
|
|
||||||
}
|
|
||||||
LWP_MutexUnlock(ListLock);
|
LWP_MutexUnlock(ListLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void * GuiImageAsync::GuiImageAsyncThread(void *arg)
|
||||||
* Constructor for the GuiImageAsync class.
|
{
|
||||||
|
while(!CloseThread)
|
||||||
|
{
|
||||||
|
if(ThreadSleep)
|
||||||
|
LWP_SuspendThread(Thread);
|
||||||
|
|
||||||
|
while(!List.empty() && !CloseThread)
|
||||||
|
{
|
||||||
|
LWP_MutexLock(ListLock);
|
||||||
|
InUse = List.front();
|
||||||
|
List.erase(List.begin());
|
||||||
|
LWP_MutexUnlock(ListLock);
|
||||||
|
|
||||||
|
if (!InUse)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
InUse->imgData = InUse->callback(InUse->arg);
|
||||||
|
|
||||||
|
if (InUse->imgData && InUse->imgData->GetImage())
|
||||||
|
{
|
||||||
|
InUse->width = InUse->imgData->GetWidth();
|
||||||
|
InUse->height = InUse->imgData->GetHeight();
|
||||||
|
InUse->image = InUse->imgData->GetImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
InUse = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadSleep = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GuiImageAsync::ThreadInit()
|
||||||
|
{
|
||||||
|
if (Thread == LWP_THREAD_NULL)
|
||||||
|
{
|
||||||
|
LWP_MutexInit(&ListLock, false);
|
||||||
|
LWP_CreateThread(&Thread, GuiImageAsyncThread, NULL, NULL, 32768, 80);
|
||||||
|
}
|
||||||
|
return ++ThreadCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GuiImageAsync::ThreadExit()
|
||||||
|
{
|
||||||
|
//! We don't need to always shutdown and startup the thread, especially
|
||||||
|
//! since this is a nested startup/shutdown from the gui thread.
|
||||||
|
//! It's fine with being put to suspended only.
|
||||||
|
/*
|
||||||
|
if (--ThreadCount == 0)
|
||||||
|
{
|
||||||
|
CloseThread = true;
|
||||||
|
LWP_ResumeThread(Thread);
|
||||||
|
LWP_JoinThread(Thread, NULL);
|
||||||
|
LWP_MutexUnlock(ListLock);
|
||||||
|
LWP_MutexDestroy(ListLock);
|
||||||
|
Thread = LWP_THREAD_NULL;
|
||||||
|
ListLock = LWP_MUTEX_NULL;
|
||||||
|
ListLock = LWP_MUTEX_NULL;
|
||||||
|
}
|
||||||
*/
|
*/
|
||||||
GuiImageData *StdImageLoaderCallback(void *arg)
|
return --ThreadCount;
|
||||||
{
|
|
||||||
return new GuiImageData((char*) arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
GuiImageAsync::GuiImageAsync(const char *Filename, GuiImageData * PreloadImg) :
|
|
||||||
GuiImage(PreloadImg), loadet_imgdata(NULL), callback(StdImageLoaderCallback), arg(strdup(Filename))
|
|
||||||
{
|
|
||||||
GuiImageAsyncThreadInit();
|
|
||||||
GuiImageAsyncThread_AddImage(this);
|
|
||||||
}
|
|
||||||
GuiImageAsync::GuiImageAsync(ImageLoaderCallback Callback, void *Arg, int ArgLen, GuiImageData * PreloadImg) :
|
|
||||||
GuiImage(PreloadImg), loadet_imgdata(NULL), callback(Callback), arg(memdup(Arg, ArgLen))
|
|
||||||
{
|
|
||||||
DEBUG( "Constructor %p", this );
|
|
||||||
GuiImageAsyncThreadInit();
|
|
||||||
GuiImageAsyncThread_AddImage(this);
|
|
||||||
}
|
|
||||||
GuiImageAsync::~GuiImageAsync()
|
|
||||||
{
|
|
||||||
GuiImageAsyncThread_RemoveImage(this);
|
|
||||||
GuiImageAsyncThreadExit();
|
|
||||||
DEBUG( "Deconstructor %p (loadet_imgdata=%p)", this, loadet_imgdata );
|
|
||||||
if (loadet_imgdata) delete loadet_imgdata;
|
|
||||||
if (arg) free(arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,25 +1,37 @@
|
|||||||
#ifndef _GUIIMAGEASYNC_H_
|
#ifndef _GUIIMAGEASYNC_H_
|
||||||
#define _GUIIMAGEASYNC_H_
|
#define _GUIIMAGEASYNC_H_
|
||||||
|
|
||||||
#// arg is a pointer created with malloc()
|
#include <vector>
|
||||||
// when the image is destroied then will also the arg deleted with free()
|
#include "libwiigui/gui.h"
|
||||||
|
|
||||||
typedef GuiImageData * (*ImageLoaderCallback)(void *arg);
|
typedef GuiImageData * (*ImageLoaderCallback)(void *arg);
|
||||||
|
|
||||||
class GuiImageAsync: public GuiImage
|
class GuiImageAsync: public GuiImage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GuiImageAsync(const char *Filename, GuiImageData * PreloadImg);
|
GuiImageAsync(const char *Filename, GuiImageData * PreloadImg);
|
||||||
GuiImageAsync(ImageLoaderCallback Callback, void *arg, int arglen, GuiImageData * PreloadImg);
|
GuiImageAsync(ImageLoaderCallback Callback, const void *Arg, int ArgLen, GuiImageData * PreloadImg);
|
||||||
~GuiImageAsync();
|
~GuiImageAsync();
|
||||||
|
|
||||||
|
static void ClearQueue();
|
||||||
private:
|
private:
|
||||||
GuiImageData *loadet_imgdata;
|
GuiImageData *imgData;
|
||||||
friend void loader(GuiImageAsync *InUse);
|
|
||||||
|
|
||||||
friend void Setter(GuiImageAsync *InUse);
|
|
||||||
friend void *GuiImageAsyncThread(void *arg);
|
|
||||||
ImageLoaderCallback callback;
|
ImageLoaderCallback callback;
|
||||||
void *arg;
|
void *arg;
|
||||||
|
|
||||||
|
static void * GuiImageAsyncThread(void *arg);
|
||||||
|
static void ThreadAddImage(GuiImageAsync* Image);
|
||||||
|
static void ThreadRemoveImage(GuiImageAsync* Image);
|
||||||
|
static u32 ThreadInit();
|
||||||
|
static u32 ThreadExit();
|
||||||
|
|
||||||
|
static std::vector<GuiImageAsync *> List;
|
||||||
|
static lwp_t Thread;
|
||||||
|
static mutex_t ListLock;
|
||||||
|
static GuiImageAsync * InUse;
|
||||||
|
static u32 ThreadCount;
|
||||||
|
static bool ThreadSleep;
|
||||||
|
static bool CloseThread;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*_GUIIMAGEASYNC_H_*/
|
#endif /*_GUIIMAGEASYNC_H_*/
|
||||||
|
@ -196,58 +196,6 @@ void ExitGUIThreads()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* LoadCoverImage
|
|
||||||
***************************************************************************/
|
|
||||||
GuiImageData *LoadCoverImage(struct discHdr *header, bool Prefere3D, bool noCover)
|
|
||||||
{
|
|
||||||
if (!header) return NULL;
|
|
||||||
GuiImageData *Cover = NULL;
|
|
||||||
char ID[4];
|
|
||||||
char IDfull[7];
|
|
||||||
char Path[100];
|
|
||||||
bool flag = Prefere3D;
|
|
||||||
|
|
||||||
snprintf(ID, sizeof(ID), "%c%c%c", header->id[0], header->id[1], header->id[2]);
|
|
||||||
snprintf(IDfull, sizeof(IDfull), "%s%c%c%c", ID, header->id[3], header->id[4], header->id[5]);
|
|
||||||
|
|
||||||
for (int i = 0; i < 2; ++i)
|
|
||||||
{
|
|
||||||
char *coverPath = flag ? Settings.covers_path : Settings.covers2d_path;
|
|
||||||
flag = !flag;
|
|
||||||
//Load full id image
|
|
||||||
snprintf(Path, sizeof(Path), "%s%s.png", coverPath, IDfull);
|
|
||||||
delete Cover;
|
|
||||||
Cover = new (std::nothrow) GuiImageData(Path);
|
|
||||||
//Load short id image
|
|
||||||
if (!Cover || !Cover->GetImage())
|
|
||||||
{
|
|
||||||
snprintf(Path, sizeof(Path), "%s%s.png", coverPath, ID);
|
|
||||||
delete Cover;
|
|
||||||
Cover = new (std::nothrow) GuiImageData(Path);
|
|
||||||
}
|
|
||||||
if (Cover && Cover->GetImage()) break;
|
|
||||||
}
|
|
||||||
//Load no image
|
|
||||||
if (noCover && (!Cover || !Cover->GetImage()))
|
|
||||||
{
|
|
||||||
flag = Prefere3D;
|
|
||||||
for (int i = 0; i < 2; ++i)
|
|
||||||
{
|
|
||||||
flag = !flag;
|
|
||||||
delete Cover;
|
|
||||||
Cover = Resources::GetImageData(Prefere3D ? "nocover.png" : "nocoverFlat.png");
|
|
||||||
if (Cover && Cover->GetImage()) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Cover && !Cover->GetImage())
|
|
||||||
{
|
|
||||||
delete Cover;
|
|
||||||
Cover = NULL;
|
|
||||||
}
|
|
||||||
return Cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* MainMenu
|
* MainMenu
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
@ -34,7 +34,6 @@ enum
|
|||||||
|
|
||||||
void ResumeGui();
|
void ResumeGui();
|
||||||
void HaltGui();
|
void HaltGui();
|
||||||
GuiImageData *LoadCoverImage(struct discHdr *header, bool Prefere3D = true, bool noCover = true);
|
|
||||||
|
|
||||||
extern GuiImageData *pointer[4];
|
extern GuiImageData *pointer[4];
|
||||||
extern GuiImageData *background;
|
extern GuiImageData *background;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "GameBrowseMenu.hpp"
|
#include "GameBrowseMenu.hpp"
|
||||||
|
#include "libwiigui/LoadCoverImage.h"
|
||||||
#include "prompts/PromptWindows.h"
|
#include "prompts/PromptWindows.h"
|
||||||
#include "prompts/gameinfo.h"
|
#include "prompts/gameinfo.h"
|
||||||
#include "prompts/DiscBrowser.h"
|
#include "prompts/DiscBrowser.h"
|
||||||
@ -22,6 +23,7 @@
|
|||||||
#include "utils/rockout.h"
|
#include "utils/rockout.h"
|
||||||
#include "utils/ShowError.h"
|
#include "utils/ShowError.h"
|
||||||
#include "utils/tools.h"
|
#include "utils/tools.h"
|
||||||
|
#include "utils/PasswordCheck.h"
|
||||||
#include "fatmounter.h"
|
#include "fatmounter.h"
|
||||||
#include "gecko.h"
|
#include "gecko.h"
|
||||||
#include "menus.h"
|
#include "menus.h"
|
||||||
@ -539,18 +541,18 @@ void GameBrowseMenu::ReloadBrowser()
|
|||||||
idBtn->SetToolTip(NULL, 0, 0);
|
idBtn->SetToolTip(NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Settings.parentalcontrol == 0 && Settings.Parental.enabled == 1) && Settings.godmode)
|
if (Settings.godmode)
|
||||||
{
|
{
|
||||||
lockBtn->SetImage(unlockBtnImg);
|
GuiImage * unlockImage = strcmp(Settings.unlockCode, "") == 0 ? unlockBtnImg_g : unlockBtnImg;
|
||||||
lockBtn->SetImageOver(unlockBtnImg);
|
lockBtn->SetImage(unlockImage);
|
||||||
lockBtnTT->SetText(tr( "Unlock Parental Control" ));
|
lockBtn->SetImageOver(unlockImage);
|
||||||
|
lockBtnTT->SetText(tr( "Lock USB Loader GX" ));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GuiImage * lockImage = Settings.Parental.enabled ? lockBtnImg : lockBtnImg_g;
|
lockBtn->SetImage(lockBtnImg);
|
||||||
lockBtn->SetImage(lockImage);
|
lockBtn->SetImageOver(lockBtnImg);
|
||||||
lockBtn->SetImageOver(lockImage);
|
lockBtnTT->SetText(tr( "Unlock USB Loader GX" ));
|
||||||
lockBtnTT->SetText(tr( "Parental Control disabled" ));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetSelectedGame() >= 0)
|
if(GetSelectedGame() >= 0)
|
||||||
@ -948,15 +950,9 @@ int GameBrowseMenu::MainLoop()
|
|||||||
{
|
{
|
||||||
gprintf("\tlockBtn clicked\n");
|
gprintf("\tlockBtn clicked\n");
|
||||||
lockBtn->ResetState();
|
lockBtn->ResetState();
|
||||||
if (!(Settings.parentalcontrol == 0 && Settings.Parental.enabled == 1))
|
|
||||||
{
|
|
||||||
WindowPrompt(tr( "Parental Control" ), tr( "You don't have Parental Control enabled. If you wish to use Parental Control, enable it in the Wii Settings." ), tr( "OK" ));
|
|
||||||
return MENU_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Settings.godmode)
|
if (Settings.godmode)
|
||||||
{
|
{
|
||||||
if(WindowPrompt(tr( "Parental Control" ), tr( "Are you sure you want to enable Parent Control?" ), tr( "Yes" ), tr( "No" )) == 1)
|
if(WindowPrompt(tr( "Parental Control" ), tr( "Are you sure you want to lock USB Loader GX?" ), tr( "Yes" ), tr( "No" )) == 1)
|
||||||
{
|
{
|
||||||
Settings.godmode = 0;
|
Settings.godmode = 0;
|
||||||
wString oldFilter(gameList.GetCurrentFilter());
|
wString oldFilter(gameList.GetCurrentFilter());
|
||||||
@ -966,23 +962,21 @@ int GameBrowseMenu::MainLoop()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Require the user to enter the PIN code
|
//password check to unlock Install,Delete and Format
|
||||||
char pin[5];
|
SetState(STATE_DISABLED);
|
||||||
memset(&pin, 0, 5);
|
int result = PasswordCheck(Settings.unlockCode);
|
||||||
int ret = OnScreenNumpad((char *) &pin, 5);
|
SetState(STATE_DEFAULT);
|
||||||
|
if (result > 0)
|
||||||
if (ret <= 0)
|
|
||||||
return MENU_NONE;
|
|
||||||
|
|
||||||
if (memcmp(pin, Settings.Parental.pin, 4) == 0)
|
|
||||||
{
|
{
|
||||||
|
if(result == 1)
|
||||||
|
WindowPrompt( tr( "Correct Password" ), tr( "All the features of USB Loader GX are unlocked." ), tr( "OK" ));
|
||||||
Settings.godmode = 1;
|
Settings.godmode = 1;
|
||||||
wString oldFilter(gameList.GetCurrentFilter());
|
wString oldFilter(gameList.GetCurrentFilter());
|
||||||
gameList.FilterList(oldFilter.c_str());
|
gameList.FilterList(oldFilter.c_str());
|
||||||
ReloadBrowser();
|
ReloadBrowser();
|
||||||
}
|
}
|
||||||
else
|
else if(result < 0)
|
||||||
WindowPrompt(tr( "Parental Control" ), tr( "Invalid PIN code" ), tr( "OK" ));
|
WindowPrompt(tr( "Wrong Password" ), tr( "USB Loader GX is protected" ), tr( "OK" ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ int MountGamePartition(bool ShowGUI)
|
|||||||
s32 wbfsinit = MountWBFS(ShowGUI);
|
s32 wbfsinit = MountWBFS(ShowGUI);
|
||||||
if (wbfsinit < 0)
|
if (wbfsinit < 0)
|
||||||
{
|
{
|
||||||
WindowPrompt(tr( "Error !" ), tr( "USB Device not found" ), tr( "OK" ));
|
if(ShowGUI) WindowPrompt(tr( "Error !" ), tr( "USB Device not found" ), tr( "OK" ));
|
||||||
Sys_LoadMenu();
|
Sys_LoadMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "language/gettext.h"
|
#include "language/gettext.h"
|
||||||
#include "themes/CTheme.h"
|
#include "themes/CTheme.h"
|
||||||
#include "FileOperations/fileops.h"
|
#include "FileOperations/fileops.h"
|
||||||
|
#include "utils/encrypt.h"
|
||||||
|
|
||||||
CSettings Settings;
|
CSettings Settings;
|
||||||
|
|
||||||
@ -66,7 +67,11 @@ void CSettings::SetDefault()
|
|||||||
strcpy(language_path, "");
|
strcpy(language_path, "");
|
||||||
strcpy(ogg_path, "");
|
strcpy(ogg_path, "");
|
||||||
strcpy(unlockCode, "");
|
strcpy(unlockCode, "");
|
||||||
|
strcpy(db_url, "");
|
||||||
|
strcpy(db_language, "");
|
||||||
|
strcpy(returnTo, "");
|
||||||
|
|
||||||
|
godmode = 1;
|
||||||
videomode = VIDEO_MODE_DISCDEFAULT;
|
videomode = VIDEO_MODE_DISCDEFAULT;
|
||||||
videopatch = OFF;
|
videopatch = OFF;
|
||||||
language = CONSOLE_DEFAULT;
|
language = CONSOLE_DEFAULT;
|
||||||
@ -80,7 +85,7 @@ void CSettings::SetDefault()
|
|||||||
gamesoundvolume = 80;
|
gamesoundvolume = 80;
|
||||||
tooltips = ON;
|
tooltips = ON;
|
||||||
gamesound = 1;
|
gamesound = 1;
|
||||||
parentalcontrol = 0;
|
parentalcontrol = 4;
|
||||||
lockedgames = 0;
|
lockedgames = 0;
|
||||||
cios = 249;
|
cios = 249;
|
||||||
xflip = XFLIP_NO;
|
xflip = XFLIP_NO;
|
||||||
@ -101,28 +106,7 @@ void CSettings::SetDefault()
|
|||||||
InstallPartitions = ONLY_GAME_PARTITION;
|
InstallPartitions = ONLY_GAME_PARTITION;
|
||||||
fullcopy = 0;
|
fullcopy = 0;
|
||||||
beta_upgrades = 0;
|
beta_upgrades = 0;
|
||||||
strcpy(db_url, "");
|
|
||||||
strcpy(db_language, "");
|
|
||||||
strcpy(unlockCode, "");
|
|
||||||
strcpy(returnTo, "");
|
|
||||||
|
|
||||||
memset(&Parental, 0, sizeof(Parental));
|
|
||||||
|
|
||||||
char buf[0x4a];
|
|
||||||
s32 res = CONF_Get("IPL.PC", buf, 0x4A);
|
|
||||||
if (res > 0)
|
|
||||||
{
|
|
||||||
if (buf[2] != 0x14)
|
|
||||||
{
|
|
||||||
Parental.enabled = 1;
|
|
||||||
Parental.rating = buf[2];
|
|
||||||
}
|
|
||||||
Parental.question = buf[7];
|
|
||||||
memcpy(Parental.pin, buf + 3, 4);
|
|
||||||
memcpy(Parental.answer, buf + 8, 32);
|
|
||||||
}
|
|
||||||
widescreen = (CONF_GetAspectRatio() == CONF_ASPECT_16_9);
|
widescreen = (CONF_GetAspectRatio() == CONF_ASPECT_16_9);
|
||||||
godmode = (Parental.enabled == 0) ? 1 : 0;
|
|
||||||
|
|
||||||
Theme.SetDefault(); //! We need to move this later
|
Theme.SetDefault(); //! We need to move this later
|
||||||
}
|
}
|
||||||
@ -187,7 +171,9 @@ bool CSettings::Save()
|
|||||||
fprintf(file, "sfxvolume = %d\n ", sfxvolume);
|
fprintf(file, "sfxvolume = %d\n ", sfxvolume);
|
||||||
fprintf(file, "gamesoundvolume = %d\n ", gamesoundvolume);
|
fprintf(file, "gamesoundvolume = %d\n ", gamesoundvolume);
|
||||||
fprintf(file, "tooltips = %d\n ", tooltips);
|
fprintf(file, "tooltips = %d\n ", tooltips);
|
||||||
fprintf(file, "password = %s\n ", unlockCode);
|
char EncryptedTxt[50];
|
||||||
|
EncryptString(unlockCode, EncryptedTxt);
|
||||||
|
fprintf(file, "password = %s\n ", EncryptedTxt);
|
||||||
fprintf(file, "GameSort = %d\n ", GameSort);
|
fprintf(file, "GameSort = %d\n ", GameSort);
|
||||||
fprintf(file, "cios = %d\n ", cios);
|
fprintf(file, "cios = %d\n ", cios);
|
||||||
fprintf(file, "keyset = %d\n ", keyset);
|
fprintf(file, "keyset = %d\n ", keyset);
|
||||||
@ -243,7 +229,7 @@ bool CSettings::SetSetting(char *name, char *value)
|
|||||||
{
|
{
|
||||||
if (sscanf(value, "%d", &i) == 1)
|
if (sscanf(value, "%d", &i) == 1)
|
||||||
{
|
{
|
||||||
if(Parental.enabled) godmode = i;
|
godmode = i;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -337,7 +323,9 @@ bool CSettings::SetSetting(char *name, char *value)
|
|||||||
}
|
}
|
||||||
else if (strcmp(name, "password") == 0)
|
else if (strcmp(name, "password") == 0)
|
||||||
{
|
{
|
||||||
strcpy(unlockCode, value);
|
char EncryptedTxt[50];
|
||||||
|
strcpy(EncryptedTxt, value);
|
||||||
|
DecryptString(EncryptedTxt, unlockCode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (strcmp(name, "GameSort") == 0)
|
else if (strcmp(name, "GameSort") == 0)
|
||||||
|
@ -110,14 +110,6 @@ class CSettings
|
|||||||
short fullcopy;
|
short fullcopy;
|
||||||
short beta_upgrades;
|
short beta_upgrades;
|
||||||
char returnTo[20];
|
char returnTo[20];
|
||||||
struct
|
|
||||||
{
|
|
||||||
u8 enabled;
|
|
||||||
u8 rating;
|
|
||||||
u8 pin[4];
|
|
||||||
u8 question;
|
|
||||||
wchar_t answer[32]; // IS WCHAR!
|
|
||||||
} Parental;
|
|
||||||
protected:
|
protected:
|
||||||
bool SetSetting(char *name, char *value);
|
bool SetSetting(char *name, char *value);
|
||||||
//!Find the config file in the default paths
|
//!Find the config file in the default paths
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "GameTitles.h"
|
#include "GameTitles.h"
|
||||||
#include "CSettings.h"
|
#include "CSettings.h"
|
||||||
#include "usbloader/GameList.h"
|
#include "usbloader/GameList.h"
|
||||||
|
#include "xml/xml.h"
|
||||||
#include "xml/WiiTDB.hpp"
|
#include "xml/WiiTDB.hpp"
|
||||||
|
|
||||||
CGameTitles GameTitles;
|
CGameTitles GameTitles;
|
||||||
@ -61,6 +62,20 @@ const char * CGameTitles::GetTitle(const struct discHdr *header)
|
|||||||
return header->title;
|
return header->title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CGameTitles::GetParentalRating(const char * id)
|
||||||
|
{
|
||||||
|
if(!id)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for(u32 i = 0; i < TitleList.size(); ++i)
|
||||||
|
{
|
||||||
|
if(strncasecmp(id, TitleList[i].GameID, 6) == 0)
|
||||||
|
return TitleList[i].ParentalRating;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void CGameTitles::SetDefault()
|
void CGameTitles::SetDefault()
|
||||||
{
|
{
|
||||||
TitleList.clear();
|
TitleList.clear();
|
||||||
@ -85,10 +100,25 @@ void CGameTitles::LoadTitlesFromWiiTDB(const char * path)
|
|||||||
|
|
||||||
WiiTDB XML_DB(Filepath.c_str());
|
WiiTDB XML_DB(Filepath.c_str());
|
||||||
XML_DB.SetLanguageCode(Settings.db_language);
|
XML_DB.SetLanguageCode(Settings.db_language);
|
||||||
|
int Rating;
|
||||||
|
std::string RatValTxt;
|
||||||
|
|
||||||
for(int i = 0; i < gameList.GameCount(); ++i)
|
for(int i = 0; i < gameList.GameCount(); ++i)
|
||||||
{
|
{
|
||||||
if(XML_DB.GetTitle((const char *) gameList[i]->id, Title))
|
if(!XML_DB.GetTitle((const char *) gameList[i]->id, Title))
|
||||||
|
continue;
|
||||||
|
|
||||||
this->SetGameTitle(gameList[i]->id, Title.c_str());
|
this->SetGameTitle(gameList[i]->id, Title.c_str());
|
||||||
|
|
||||||
|
TitleList[TitleList.size()-1].ParentalRating = -1;
|
||||||
|
|
||||||
|
Rating = XML_DB.GetRating((const char *) gameList[i]->id);
|
||||||
|
if(Rating < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!XML_DB.GetRatingValue((const char *) gameList[i]->id, RatValTxt))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
TitleList[TitleList.size()-1].ParentalRating = ConvertRating(RatValTxt.c_str(), WiiTDB::RatingToString(Rating), "PEGI");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ typedef struct _GameTitle
|
|||||||
{
|
{
|
||||||
char GameID[7];
|
char GameID[7];
|
||||||
std::string Title;
|
std::string Title;
|
||||||
|
int ParentalRating;
|
||||||
|
|
||||||
} GameTitle;
|
} GameTitle;
|
||||||
|
|
||||||
@ -28,6 +29,9 @@ class CGameTitles
|
|||||||
//! Overload
|
//! Overload
|
||||||
const char * GetTitle(const struct discHdr *header);
|
const char * GetTitle(const struct discHdr *header);
|
||||||
|
|
||||||
|
//! Get game parental rating
|
||||||
|
int GetParentalRating(const char * id);
|
||||||
|
|
||||||
//! Load Game Titles from WiiTDB
|
//! Load Game Titles from WiiTDB
|
||||||
void LoadTitlesFromWiiTDB(const char * path);
|
void LoadTitlesFromWiiTDB(const char * path);
|
||||||
//! Set default game titles
|
//! Set default game titles
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "settings/CSettings.h"
|
#include "settings/CSettings.h"
|
||||||
#include "prompts/PromptWindows.h"
|
#include "prompts/PromptWindows.h"
|
||||||
#include "language/gettext.h"
|
#include "language/gettext.h"
|
||||||
|
#include "utils/PasswordCheck.h"
|
||||||
|
|
||||||
static const char * LockModeText[] =
|
static const char * LockModeText[] =
|
||||||
{
|
{
|
||||||
@ -101,41 +102,27 @@ int ParentalControlSM::GetMenuInternal()
|
|||||||
//! Settings: Console
|
//! Settings: Console
|
||||||
if (ret == ++Idx)
|
if (ret == ++Idx)
|
||||||
{
|
{
|
||||||
if (strcmp(Settings.unlockCode, "") == 0 && !Settings.Parental.enabled)
|
if (!Settings.godmode)
|
||||||
{
|
{
|
||||||
Settings.godmode = !Settings.godmode;
|
|
||||||
}
|
|
||||||
else if (!Settings.godmode)
|
|
||||||
{
|
|
||||||
char entered[20];
|
|
||||||
memset(entered, 0, 20);
|
|
||||||
|
|
||||||
//password check to unlock Install,Delete and Format
|
//password check to unlock Install,Delete and Format
|
||||||
SetState(STATE_DISABLED);
|
SetState(STATE_DISABLED);
|
||||||
int result = Settings.Parental.enabled == 0 ? OnScreenKeyboard(entered, 20, 0) : OnScreenNumpad(entered, 5);
|
int result = PasswordCheck(Settings.unlockCode);
|
||||||
SetState(STATE_DEFAULT);
|
SetState(STATE_DEFAULT);
|
||||||
if (result == 1)
|
if (result > 0)
|
||||||
{
|
{
|
||||||
if (strcmp(entered, Settings.unlockCode) == 0 || !memcmp(entered, Settings.Parental.pin, 4)) //if password correct
|
if(result == 1)
|
||||||
{
|
WindowPrompt( tr( "Correct Password" ), tr( "All the features of USB Loader GX are unlocked." ), tr( "OK" ));
|
||||||
WindowPrompt(
|
|
||||||
tr( "Correct Password" ),
|
|
||||||
tr( "All the features of USB Loader GX are unlocked." ),
|
|
||||||
tr( "OK" ));
|
|
||||||
Settings.godmode = 1;
|
Settings.godmode = 1;
|
||||||
}
|
}
|
||||||
else
|
else if(result < 0)
|
||||||
WindowPrompt(tr( "Wrong Password" ), tr( "USB Loader GX is protected" ), tr( "OK" ));
|
WindowPrompt(tr( "Wrong Password" ), tr( "USB Loader GX is protected" ), tr( "OK" ));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int choice = WindowPrompt(tr( "Lock Console" ), tr( "Are you sure?" ),
|
int choice = WindowPrompt(tr( "Lock Console" ), tr( "Are you sure?" ), tr( "Yes" ), tr( "No" ));
|
||||||
tr( "Yes" ), tr( "No" ));
|
|
||||||
if (choice == 1)
|
if (choice == 1)
|
||||||
{
|
{
|
||||||
WindowPrompt(tr( "Console Locked" ), tr( "USB Loader GX is protected" ),
|
WindowPrompt(tr( "Console Locked" ), tr( "USB Loader GX is protected" ), tr( "OK" ));
|
||||||
tr( "OK" ));
|
|
||||||
Settings.godmode = 0;
|
Settings.godmode = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ s32 IosLoader::LoadGameCios(s32 ios)
|
|||||||
|
|
||||||
// Remount devices after reloading IOS.
|
// Remount devices after reloading IOS.
|
||||||
SDCard_Init();
|
SDCard_Init();
|
||||||
USBDevice_Init();
|
USBDevice_Init_Loop();
|
||||||
Disc_Init();
|
Disc_Init();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -155,19 +155,13 @@ int GameList::FilterList(const wchar_t * gameFilter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Rating based parental control method */
|
/* Rating based parental control method */
|
||||||
if (Settings.parentalcontrol == 0 && Settings.godmode == 0 && Settings.Parental.enabled == 1)
|
if (Settings.parentalcontrol != 4 && Settings.godmode == 0)
|
||||||
{
|
{
|
||||||
// Check game rating in WiiTDB, since the default Wii parental control setting is enabled
|
// Check game rating in WiiTDB, since the default Wii parental control setting is enabled
|
||||||
s32 rating = GetRatingForGame((char *) header->id);
|
int rating = GameTitles.GetParentalRating((char *) header->id);
|
||||||
|
if (rating > Settings.parentalcontrol)
|
||||||
if ((rating != -1 && rating > Settings.Parental.rating) ||
|
|
||||||
(GameConfig && rating == -1 &&
|
|
||||||
CGameSettings::GetPartenalPEGI(GameConfig->parentalcontrol)
|
|
||||||
> Settings.Parental.rating))
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//! Per game lock method
|
//! Per game lock method
|
||||||
if(!Settings.godmode && Settings.lockedgames && GameConfig && GameConfig->Locked)
|
if(!Settings.godmode && Settings.lockedgames && GameConfig && GameConfig->Locked)
|
||||||
|
@ -380,7 +380,7 @@ s32 Partition_GetList(u32 device, PartList *plist)
|
|||||||
//if (!part_is_data(entry->type)) continue;
|
//if (!part_is_data(entry->type)) continue;
|
||||||
if (!Device_ReadSectors(device, entry->sector, 1, buf)) continue;
|
if (!Device_ReadSectors(device, entry->sector, 1, buf)) continue;
|
||||||
pinfo->fs_type = get_fs_type((u8 *) buf);
|
pinfo->fs_type = get_fs_type((u8 *) buf);
|
||||||
if(entry->type == 0x83) pinfo->fs_type = FS_TYPE_EXT;
|
if(entry->type == 0x83 && pinfo->fs_type == FS_TYPE_UNK) pinfo->fs_type = FS_TYPE_EXT;
|
||||||
if (pinfo->fs_type == FS_TYPE_WBFS)
|
if (pinfo->fs_type == FS_TYPE_WBFS)
|
||||||
{
|
{
|
||||||
// multiple wbfs on sdhc not supported
|
// multiple wbfs on sdhc not supported
|
||||||
|
@ -69,32 +69,20 @@ s32 WBFS_OpenPart(u32 part_fs, u32 part_idx, u32 part_lba, u32 part_size, char *
|
|||||||
{
|
{
|
||||||
current = new Wbfs_Fat(wbfsDev, part_lba, part_size);
|
current = new Wbfs_Fat(wbfsDev, part_lba, part_size);
|
||||||
strcpy(wbfs_fs_drive, "USB:");
|
strcpy(wbfs_fs_drive, "USB:");
|
||||||
#ifdef DEBUG_WBFS
|
|
||||||
gprintf("\n\tCreated WBFS_Fat instance at lba: %d of size %d", part_lba, part_size);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else if (part_fs == PART_FS_NTFS)
|
else if (part_fs == PART_FS_NTFS)
|
||||||
{
|
{
|
||||||
current = new Wbfs_Ntfs(wbfsDev, part_lba, part_size);
|
current = new Wbfs_Ntfs(wbfsDev, part_lba, part_size);
|
||||||
strcpy(wbfs_fs_drive, "NTFS:");
|
strcpy(wbfs_fs_drive, "NTFS:");
|
||||||
#ifdef DEBUG_WBFS
|
|
||||||
gprintf("\n\tCreated WBFS_Ntfs instance at lba: %d of size %d", part_lba, part_size);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else if (part_fs == PART_FS_EXT)
|
else if (part_fs == PART_FS_EXT)
|
||||||
{
|
{
|
||||||
current = new Wbfs_Ext(wbfsDev, part_lba, part_size);
|
current = new Wbfs_Ext(wbfsDev, part_lba, part_size);
|
||||||
strcpy(wbfs_fs_drive, "EXT:");
|
strcpy(wbfs_fs_drive, "EXT:");
|
||||||
#ifdef DEBUG_WBFS
|
|
||||||
gprintf("\n\tCreated WBFS_Ext instance at lba: %d of size %d", part_lba, part_size);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
current = new Wbfs_Wbfs(wbfsDev, part_lba, part_size);
|
current = new Wbfs_Wbfs(wbfsDev, part_lba, part_size);
|
||||||
#ifdef DEBUG_WBFS
|
|
||||||
gprintf("\n\tCreated WBFS_Wbfs instance at lba: %d of size %d", part_lba, part_size);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (current->Open())
|
if (current->Open())
|
||||||
{
|
{
|
||||||
|
21
source/utils/PasswordCheck.cpp
Normal file
21
source/utils/PasswordCheck.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include "prompts/PromptWindows.h"
|
||||||
|
|
||||||
|
int PasswordCheck(const char * password)
|
||||||
|
{
|
||||||
|
if(!password || strcmp(password, "") == 0 || strcmp(password, "not set") == 0)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
char entered[100];
|
||||||
|
memset(entered, 0, sizeof(entered));
|
||||||
|
|
||||||
|
int result = OnScreenKeyboard(entered, 20, 0);
|
||||||
|
if (result == 1)
|
||||||
|
{
|
||||||
|
if (strcmp(entered, password) == 0) //if password correct
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
6
source/utils/PasswordCheck.h
Normal file
6
source/utils/PasswordCheck.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef PASSWORD_CHECK_H_
|
||||||
|
#define PASSWORD_CHECK_H_
|
||||||
|
|
||||||
|
int PasswordCheck(const char * password);
|
||||||
|
|
||||||
|
#endif
|
57
source/utils/encrypt.c
Normal file
57
source/utils/encrypt.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010
|
||||||
|
* by dude, Dimok
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any
|
||||||
|
* damages arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any
|
||||||
|
* purpose, including commercial applications, and to alter it and
|
||||||
|
* redistribute it freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you
|
||||||
|
* must not claim that you wrote the original software. If you use
|
||||||
|
* this software in a product, an acknowledgment in the product
|
||||||
|
* documentation would be appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and
|
||||||
|
* must not be misrepresented as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* for WiiXplorer 2010
|
||||||
|
***************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
//! No need for high security crap. It's a simple encrypter/decrypter
|
||||||
|
//! with a constant sid.
|
||||||
|
const char * sid = "USBLoaderGX";
|
||||||
|
|
||||||
|
void EncryptString(const char *src, char *dst)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char tmp[3];
|
||||||
|
dst[0] = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < strlen(src); i++)
|
||||||
|
{
|
||||||
|
sprintf(tmp, "%02x", src[i] ^ sid[i%10]);
|
||||||
|
strcat(dst, tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecryptString(const char *src, char *dst)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < strlen(src); i += 2)
|
||||||
|
{
|
||||||
|
char c = (src[i] >= 'a' ? (src[i] - 'a') + 10 : (src[i] - '0')) << 4;
|
||||||
|
c += (src[i+1] >= 'a' ? (src[i+1] - 'a') + 10 : (src[i+1] - '0'));
|
||||||
|
dst[i>>1] = c ^ sid[(i>>1)%10];
|
||||||
|
}
|
||||||
|
dst[strlen(src)>>1] = 0;
|
||||||
|
}
|
||||||
|
|
41
source/utils/encrypt.h
Normal file
41
source/utils/encrypt.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2010
|
||||||
|
* by dude
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any
|
||||||
|
* damages arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any
|
||||||
|
* purpose, including commercial applications, and to alter it and
|
||||||
|
* redistribute it freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you
|
||||||
|
* must not claim that you wrote the original software. If you use
|
||||||
|
* this software in a product, an acknowledgment in the product
|
||||||
|
* documentation would be appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and
|
||||||
|
* must not be misrepresented as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* for WiiXplorer 2010
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef __ENCRYPT_H
|
||||||
|
#define __ENCRYPT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void EncryptString(const char *src, char *dst);
|
||||||
|
void DecryptString(const char *src, char *dst);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif //__cplusplus
|
||||||
|
|
||||||
|
#endif /* __ENCRYPT_H */
|
||||||
|
|
@ -13,27 +13,10 @@
|
|||||||
|
|
||||||
extern char game_partition[6];
|
extern char game_partition[6];
|
||||||
|
|
||||||
static char * trimcopy(char *dest, char *src, int size)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
while (*src == ' ')
|
|
||||||
src++;
|
|
||||||
len = strlen(src);
|
|
||||||
// trim trailing " \r\n"
|
|
||||||
while (len > 0 && strchr(" \r\n", src[len - 1]))
|
|
||||||
len--;
|
|
||||||
if (len >= size) len = size - 1;
|
|
||||||
strlcpy(dest, src, len + 1);
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
/* config */
|
/* config */
|
||||||
static bool xmldebug = false;
|
|
||||||
static char xmlcfg_filename[100] = "wiitdb";
|
static char xmlcfg_filename[100] = "wiitdb";
|
||||||
static int xmlmaxsize = 1572864;
|
static int xmlmaxsize = 1572864;
|
||||||
|
|
||||||
struct gameXMLinfo gameinfo;
|
|
||||||
struct gameXMLinfo gameinfo_reset;
|
|
||||||
|
|
||||||
static char langlist[11][22] = { { "Console Default" }, { "Japanese" }, { "English" }, { "German" }, { "French" }, {
|
static char langlist[11][22] = { { "Console Default" }, { "Japanese" }, { "English" }, { "German" }, { "French" }, {
|
||||||
"Spanish" }, { "Italian" }, { "Dutch" }, { "S. Chinese" }, { "T. Chinese" }, { "Korean" } };
|
"Spanish" }, { "Italian" }, { "Dutch" }, { "S. Chinese" }, { "T. Chinese" }, { "Korean" } };
|
||||||
|
|
||||||
@ -128,7 +111,6 @@ bool OpenXMLFile(char *filename)
|
|||||||
|
|
||||||
if (xml_loaded) return false;
|
if (xml_loaded) return false;
|
||||||
|
|
||||||
gameinfo = gameinfo_reset;
|
|
||||||
nodedata = NULL;
|
nodedata = NULL;
|
||||||
nodetree = NULL;
|
nodetree = NULL;
|
||||||
nodeid = NULL;
|
nodeid = NULL;
|
||||||
@ -245,40 +227,70 @@ char ConvertRatingToIndex(char *ratingtext)
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConvertRating(char *ratingvalue, char *fromrating, const char *torating, char *destvalue, int destsize)
|
int ConvertRating(const char *ratingvalue, const char *fromrating, const char *torating)
|
||||||
{
|
{
|
||||||
if (!strcmp(fromrating, torating))
|
if (!strcmp(fromrating, torating))
|
||||||
{
|
{
|
||||||
strlcpy(destvalue, ratingvalue, destsize);
|
int ret = atoi(ratingvalue);
|
||||||
return;
|
if(ret < 7)
|
||||||
|
return 0;
|
||||||
|
else if(ret < 12)
|
||||||
|
return 1;
|
||||||
|
else if(ret < 16)
|
||||||
|
return 2;
|
||||||
|
else if(ret < 18)
|
||||||
|
return 3;
|
||||||
|
else
|
||||||
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(destvalue, "");
|
|
||||||
int type = -1;
|
int type = -1;
|
||||||
int desttype = -1;
|
int desttype = -1;
|
||||||
|
|
||||||
type = ConvertRatingToIndex(fromrating);
|
type = ConvertRatingToIndex((char *) fromrating);
|
||||||
desttype = ConvertRatingToIndex((char *) torating);
|
desttype = ConvertRatingToIndex((char *) torating);
|
||||||
if (type == -1 || desttype == -1) return;
|
if (type == -1 || desttype == -1) return -1;
|
||||||
|
|
||||||
/* rating conversion table */
|
/* rating conversion table */
|
||||||
/* the list is ordered to pick the most likely value first: */
|
/* 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 */
|
/* 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 */
|
/* 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" }, {
|
char ratingtable[12][3][5] =
|
||||||
"6" } }, { { "A" }, { "E" }, { "7" } }, { { "A" }, { "EC" }, { "3" } }, { { "A" }, { "E10+" }, { "7" } }, {
|
{
|
||||||
{ "B" }, { "T" }, { "12" } }, { { "D" }, { "M" }, { "18" } }, { { "D" }, { "M" }, { "16" } }, { { "C" }, {
|
{ { "A" }, { "E" }, { "3" } },
|
||||||
"T" }, { "16" } }, { { "C" }, { "T" }, { "15" } }, { { "Z" }, { "AO" }, { "18" } }, };
|
{ { "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;
|
int i;
|
||||||
for (i = 0; i <= 11; i++)
|
for (i = 0; i <= 11; i++)
|
||||||
{
|
{
|
||||||
if (!strcmp(ratingtable[i][type], ratingvalue))
|
if (!strcmp(ratingtable[i][type], ratingvalue))
|
||||||
{
|
{
|
||||||
strlcpy(destvalue, ratingtable[i][desttype], destsize);
|
int ret = atoi(ratingtable[i][desttype]);
|
||||||
return;
|
if(ret < 7)
|
||||||
|
return 0;
|
||||||
|
else if(ret < 12)
|
||||||
|
return 1;
|
||||||
|
else if(ret < 16)
|
||||||
|
return 2;
|
||||||
|
else if(ret < 18)
|
||||||
|
return 3;
|
||||||
|
else
|
||||||
|
return 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadTitlesFromXML(char *langtxt, bool forcejptoen)
|
void LoadTitlesFromXML(char *langtxt, bool forcejptoen)
|
||||||
@ -388,388 +400,6 @@ void GetPublisherFromGameid(char *idtxt, char *dest, int destsize)
|
|||||||
mxmlIndexDelete(nodeindextmp);
|
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 *MemInfo()
|
||||||
{
|
{
|
||||||
char linebuf[300] = "";
|
char linebuf[300] = "";
|
||||||
@ -819,43 +449,3 @@ char * get_nodetext(mxml_node_t *node, char *buffer, int buflen) /* O - Text in
|
|||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
return (buffer);
|
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;
|
|
||||||
}
|
|
||||||
|
@ -6,61 +6,17 @@
|
|||||||
// open database, close database, load info for a game
|
// open database, close database, load info for a game
|
||||||
bool OpenXMLDatabase(char* xmlfilepath, char* argdblang, bool argJPtoEN, bool openfile, bool loadtitles, bool keepopen);
|
bool OpenXMLDatabase(char* xmlfilepath, char* argdblang, bool argJPtoEN, bool openfile, bool loadtitles, bool keepopen);
|
||||||
void CloseXMLDatabase();
|
void CloseXMLDatabase();
|
||||||
bool LoadGameInfoFromXML(char* gameid, char* langcode);
|
|
||||||
|
|
||||||
#define XML_ELEMMAX 15
|
#define XML_ELEMMAX 15
|
||||||
#define XML_SYNOPSISLEN 4000
|
|
||||||
|
|
||||||
struct gameXMLinfo
|
|
||||||
{
|
|
||||||
char id[7];
|
|
||||||
char version[50];
|
|
||||||
char region[7];
|
|
||||||
char title[200];
|
|
||||||
char synopsis[XML_SYNOPSISLEN];
|
|
||||||
char title_EN[200];
|
|
||||||
char synopsis_EN[XML_SYNOPSISLEN];
|
|
||||||
char locales[XML_ELEMMAX + 1][5];
|
|
||||||
int localeCnt;
|
|
||||||
char developer[75];
|
|
||||||
char publisher[75];
|
|
||||||
char publisherfromid[75];
|
|
||||||
char year[5];
|
|
||||||
char month[3];
|
|
||||||
char day[3];
|
|
||||||
char genre[75];
|
|
||||||
char genresplit[XML_ELEMMAX + 1][20];
|
|
||||||
int genreCnt;
|
|
||||||
char ratingtype[5];
|
|
||||||
char ratingvalue[5];
|
|
||||||
char ratingdescriptors[XML_ELEMMAX + 1][40];
|
|
||||||
int descriptorCnt;
|
|
||||||
char ratingvalueCERO[5];
|
|
||||||
char ratingvalueESRB[5];
|
|
||||||
char ratingvaluePEGI[5];
|
|
||||||
char wifiplayers[4];
|
|
||||||
char wififeatures[XML_ELEMMAX + 1][20];
|
|
||||||
int wifiCnt;
|
|
||||||
char players[4];
|
|
||||||
char accessories[XML_ELEMMAX + 1][20];
|
|
||||||
int accessoryCnt;
|
|
||||||
char accessoriesReq[XML_ELEMMAX + 1][20];
|
|
||||||
int accessoryReqCnt;
|
|
||||||
char iso_crc[9];
|
|
||||||
char iso_md5[33];
|
|
||||||
char iso_sha1[41];
|
|
||||||
};
|
|
||||||
|
|
||||||
bool OpenXMLFile(char* filename);
|
bool OpenXMLFile(char* filename);
|
||||||
void LoadTitlesFromXML(char *langcode, bool forcejptoen);
|
void LoadTitlesFromXML(char *langcode, bool forcejptoen);
|
||||||
void GetPublisherFromGameid(char *idtxt, char *dest, int destsize);
|
void GetPublisherFromGameid(char *idtxt, char *dest, int destsize);
|
||||||
const char *ConvertLangTextToCode(char *langtext);
|
const char *ConvertLangTextToCode(char *langtext);
|
||||||
void ConvertRating(char *ratingvalue, char *fromrating, const char *torating, char *destvalue, int destsize);
|
int ConvertRating(const char *ratingvalue, const char *fromrating, const char *torating);
|
||||||
void PrintGameInfo(bool showfullinfo);
|
|
||||||
char *MemInfo();
|
char *MemInfo();
|
||||||
void GetTextFromNode(mxml_node_t *currentnode, mxml_node_t *topnode, const char *nodename, const char *attributename,
|
void GetTextFromNode(mxml_node_t *currentnode, mxml_node_t *topnode, const char *nodename, const char *attributename,
|
||||||
char *value, int descend, char *dest, int destsize);
|
char *value, int descend, char *dest, int destsize);
|
||||||
int GetRatingForGame(char *gameid);
|
|
||||||
char * get_nodetext(mxml_node_t *node, char *buffer, int buflen);
|
char * get_nodetext(mxml_node_t *node, char *buffer, int buflen);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user