*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:
dimok321 2010-12-19 18:20:33 +00:00
parent 3f03d92295
commit 2adc6cc995
30 changed files with 518 additions and 895 deletions

View File

@ -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

View File

@ -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;

View 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;
}

View File

@ -0,0 +1,6 @@
#ifndef LOADCOVERIMAGE_H_
#define LOADCOVERIMAGE_H_
GuiImageData *LoadCoverImage(struct discHdr *header, bool Prefere3D = true, bool noCover = true);
#endif

View File

@ -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;
} }

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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); cant 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)
{ {
LWP_MutexLock(ListLock); for(u32 i = 0; i < List.size(); ++i)
for (std::vector<GuiImageAsync *>::iterator iter = List.begin(); iter != List.end(); iter++)
{ {
if (*iter == Image) if(List[i] == Image)
{ {
List.erase(iter); LWP_MutexLock(ListLock);
List.erase(List.begin()+i);
LWP_MutexUnlock(ListLock); LWP_MutexUnlock(ListLock);
return; break;
} }
} }
if (InUse == Image) }
{
LWP_MutexLock(InUseLock); void GuiImageAsync::ClearQueue()
LWP_MutexUnlock(InUseLock); {
} LWP_MutexLock(ListLock);
List.clear();
LWP_MutexUnlock(ListLock); LWP_MutexUnlock(ListLock);
} }
/** void * GuiImageAsync::GuiImageAsyncThread(void *arg)
* Constructor for the GuiImageAsync class.
*/
GuiImageData *StdImageLoaderCallback(void *arg)
{ {
return new GuiImageData((char*) arg); 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;
} }
GuiImageAsync::GuiImageAsync(const char *Filename, GuiImageData * PreloadImg) : u32 GuiImageAsync::ThreadInit()
GuiImage(PreloadImg), loadet_imgdata(NULL), callback(StdImageLoaderCallback), arg(strdup(Filename))
{ {
GuiImageAsyncThreadInit(); if (Thread == LWP_THREAD_NULL)
GuiImageAsyncThread_AddImage(this); {
} LWP_MutexInit(&ListLock, false);
GuiImageAsync::GuiImageAsync(ImageLoaderCallback Callback, void *Arg, int ArgLen, GuiImageData * PreloadImg) : LWP_CreateThread(&Thread, GuiImageAsyncThread, NULL, NULL, 32768, 80);
GuiImage(PreloadImg), loadet_imgdata(NULL), callback(Callback), arg(memdup(Arg, ArgLen)) }
{ return ++ThreadCount;
DEBUG( "Constructor %p", this ); }
GuiImageAsyncThreadInit();
GuiImageAsyncThread_AddImage(this); u32 GuiImageAsync::ThreadExit()
} {
GuiImageAsync::~GuiImageAsync() //! We don't need to always shutdown and startup the thread, especially
{ //! since this is a nested startup/shutdown from the gui thread.
GuiImageAsyncThread_RemoveImage(this); //! It's fine with being put to suspended only.
GuiImageAsyncThreadExit(); /*
DEBUG( "Deconstructor %p (loadet_imgdata=%p)", this, loadet_imgdata ); if (--ThreadCount == 0)
if (loadet_imgdata) delete loadet_imgdata; {
if (arg) free(arg); 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;
}
*/
return --ThreadCount;
} }

View File

@ -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_*/

View File

@ -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
***************************************************************************/ ***************************************************************************/

View File

@ -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;

View File

@ -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" ));
} }
} }

View File

@ -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();
} }

View File

@ -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)

View File

@ -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

View File

@ -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))
this->SetGameTitle(gameList[i]->id, Title.c_str()); continue;
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");
} }
} }

View File

@ -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

View File

@ -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( Settings.godmode = 1;
tr( "Correct Password" ),
tr( "All the features of USB Loader GX are unlocked." ),
tr( "OK" ));
Settings.godmode = 1;
}
else
WindowPrompt(tr( "Wrong Password" ), tr( "USB Loader GX is protected" ), tr( "OK" ));
} }
else if(result < 0)
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;
} }
} }

View File

@ -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;

View File

@ -155,18 +155,12 @@ 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

View File

@ -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

View File

@ -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())
{ {

View 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;
}

View 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
View 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
View 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 */

View File

@ -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;
}

View File

@ -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