From 2adc6cc995c98830db1aa745198cd894f84da6e9 Mon Sep 17 00:00:00 2001 From: dimok321 <15055714+dimok789@users.noreply.github.com> Date: Sun, 19 Dec 2010 18:20:33 +0000 Subject: [PATCH] *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 --- HBC/META.XML | 4 +- gui.pnproj | 2 +- source/FileOperations/DirList.cpp | 2 +- source/libwiigui/LoadCoverImage.cpp | 65 +++ source/libwiigui/LoadCoverImage.h | 6 + source/libwiigui/gui_gamecarousel.cpp | 23 +- source/libwiigui/gui_gamecarousel.h | 7 +- source/libwiigui/gui_gamegrid.cpp | 97 ++-- source/libwiigui/gui_gamegrid.h | 10 +- source/libwiigui/gui_image_async.cpp | 256 +++++----- source/libwiigui/gui_image_async.h | 28 +- source/menu.cpp | 52 --- source/menu.h | 1 - source/menu/GameBrowseMenu.cpp | 46 +- source/menu/MountGamePartition.cpp | 2 +- source/settings/CSettings.cpp | 38 +- source/settings/CSettings.h | 8 - source/settings/GameTitles.cpp | 34 +- source/settings/GameTitles.h | 4 + source/settings/menus/ParentalControlSM.cpp | 35 +- source/system/IosLoader.cpp | 2 +- source/usbloader/GameList.cpp | 12 +- source/usbloader/partition_usbloader.c | 2 +- source/usbloader/wbfs.cpp | 12 - source/utils/PasswordCheck.cpp | 21 + source/utils/PasswordCheck.h | 6 + source/utils/encrypt.c | 57 +++ source/utils/encrypt.h | 41 ++ source/xml/xml.cpp | 494 ++------------------ source/xml/xml.h | 46 +- 30 files changed, 518 insertions(+), 895 deletions(-) create mode 100644 source/libwiigui/LoadCoverImage.cpp create mode 100644 source/libwiigui/LoadCoverImage.h create mode 100644 source/utils/PasswordCheck.cpp create mode 100644 source/utils/PasswordCheck.h create mode 100644 source/utils/encrypt.c create mode 100644 source/utils/encrypt.h diff --git a/HBC/META.XML b/HBC/META.XML index 50b4f71f..e54d45a5 100644 --- a/HBC/META.XML +++ b/HBC/META.XML @@ -2,8 +2,8 @@ USB Loader GX USB Loader GX Team - 1.0 r1010 - 201012051910 + 1.0 r1015 + 201012181321 Loads games from USB-devices 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. diff --git a/gui.pnproj b/gui.pnproj index 5a167df4..1e690d9b 100644 --- a/gui.pnproj +++ b/gui.pnproj @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/source/FileOperations/DirList.cpp b/source/FileOperations/DirList.cpp index d18bbd00..c6184613 100644 --- a/source/FileOperations/DirList.cpp +++ b/source/FileOperations/DirList.cpp @@ -125,7 +125,7 @@ void DirList::AddEntrie(const char * folderpath, const char * filename, u64 file 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) sprintf(FileInfo[pos].FilePath, "%s/%s", folderpath, filename); FileInfo[pos].FileSize = filesize; diff --git a/source/libwiigui/LoadCoverImage.cpp b/source/libwiigui/LoadCoverImage.cpp new file mode 100644 index 00000000..0d3dde0b --- /dev/null +++ b/source/libwiigui/LoadCoverImage.cpp @@ -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; +} diff --git a/source/libwiigui/LoadCoverImage.h b/source/libwiigui/LoadCoverImage.h new file mode 100644 index 00000000..dae4283c --- /dev/null +++ b/source/libwiigui/LoadCoverImage.h @@ -0,0 +1,6 @@ +#ifndef LOADCOVERIMAGE_H_ +#define LOADCOVERIMAGE_H_ + +GuiImageData *LoadCoverImage(struct discHdr *header, bool Prefere3D = true, bool noCover = true); + +#endif diff --git a/source/libwiigui/gui_gamecarousel.cpp b/source/libwiigui/gui_gamecarousel.cpp index bd8e5ca8..b2435b32 100644 --- a/source/libwiigui/gui_gamecarousel.cpp +++ b/source/libwiigui/gui_gamecarousel.cpp @@ -7,17 +7,18 @@ ***************************************************************************/ #include "gui.h" -#include "../wpad.h" -#include "../menu.h" +#include "wpad.h" +#include "menu.h" #include #include "gui_image_async.h" #include "gui_gamecarousel.h" #include "usbloader/GameList.h" #include "settings/GameTitles.h" -#include "../settings/CSettings.h" +#include "settings/CSettings.h" +#include "libwiigui/LoadCoverImage.h" #include "themes/CTheme.h" -#include "../main.h" +#include "main.h" #include #include @@ -108,8 +109,8 @@ GuiGameCarousel::GuiGameCarousel(int w, int h, const char *themePath, const u8 * gamename->SetMaxWidth(280, DOTTED); gameIndex = new int[pagesize]; - game = new GuiButton *[pagesize]; - coverImg = new GuiImageAsync *[pagesize]; + game.resize(pagesize); + coverImg.resize(pagesize); for (int i = 0; i < pagesize; i++) { @@ -163,14 +164,14 @@ GuiGameCarousel::~GuiGameCarousel() delete trigMinus; delete gamename; - for (int i = 0; i < pagesize; i++) - { + GuiImageAsync::ClearQueue(); + + for (u32 i = 0; i < game.size(); ++i) delete coverImg[i]; + for (u32 i = 0; i < game.size(); ++i) delete game[i]; - } + delete[] gameIndex; - delete[] coverImg; - delete[] game; } diff --git a/source/libwiigui/gui_gamecarousel.h b/source/libwiigui/gui_gamecarousel.h index 8f8320e3..489a98dc 100644 --- a/source/libwiigui/gui_gamecarousel.h +++ b/source/libwiigui/gui_gamecarousel.h @@ -1,8 +1,9 @@ #ifndef _GUIGAMECAROUSEL_H_ #define _GUIGAMECAROUSEL_H_ +#include #include "gui.h" -#include "../usbloader/disc.h" +#include "usbloader/disc.h" class GuiImageAsync; class GuiGameCarousel: public GuiElement { @@ -29,8 +30,8 @@ class GuiGameCarousel: public GuiElement int clickedItem; int * gameIndex; - GuiButton ** game; - GuiImageAsync ** coverImg; + std::vector game; + std::vector coverImg; GuiText * gamename; diff --git a/source/libwiigui/gui_gamegrid.cpp b/source/libwiigui/gui_gamegrid.cpp index b85dbeda..ad31688f 100644 --- a/source/libwiigui/gui_gamegrid.cpp +++ b/source/libwiigui/gui_gamegrid.cpp @@ -7,18 +7,19 @@ ***************************************************************************/ #include "gui.h" -#include "../wpad.h" +#include "wpad.h" #include #include "gui_gamegrid.h" #include "gui_image_async.h" +#include "libwiigui/LoadCoverImage.h" #include "usbloader/GameList.h" #include "settings/GameTitles.h" -#include "../settings/CSettings.h" +#include "settings/CSettings.h" #include "themes/CTheme.h" -#include "../prompts/PromptWindows.h" -#include "../language/gettext.h" -#include "../menu.h" +#include "prompts/PromptWindows.h" +#include "language/gettext.h" +#include "menu.h" #include "fatmounter.h" #include @@ -206,23 +207,10 @@ GuiGameGrid::GuiGameGrid(int w, int h, const char *themePath, const u8 *imagebg, { width = w; 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; 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->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); trigL = new GuiTrigger; @@ -274,10 +262,6 @@ GuiGameGrid::GuiGameGrid(int w, int h, const char *themePath, const u8 *imagebg, // Page-Stuff gameIndex = NULL; - titleTT = NULL; - // cover = NULL; - coverImg = NULL; - game = NULL; Reload(Settings.gridRows, 0); } @@ -301,17 +285,22 @@ GuiGameGrid::~GuiGameGrid() delete trig1; delete trig2; - for (int i = pagesize - 1; i >= 0; i--) - { - delete game[i]; - delete coverImg[i]; - delete titleTT[i]; - } + GuiImageAsync::ClearQueue(); - delete[] gameIndex; - delete[] game; - delete[] coverImg; - delete[] titleTT; + for (u32 i = 0; i < game.size(); ++i) + delete game[i]; + + 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) @@ -447,7 +436,6 @@ void GuiGameGrid::Draw() */ void GuiGameGrid::ChangeRows(int n) { - LOCK( this ); if (n != rows) Reload(n, -1); } @@ -489,10 +477,7 @@ void GuiGameGrid::Update(GuiTrigger * t) if (btnLeft->GetState() == STATE_CLICKED) { - WPAD_ScanPads(); - u16 buttons = 0; - for (int i = 0; i < 4; i++) - buttons |= WPAD_ButtonsHeld(i); + u32 buttons = t->wpad.btns_h; if (!((buttons & WPAD_BUTTON_A) || (buttons & WPAD_BUTTON_MINUS) || t->Left())) { btnLeft->ResetState(); @@ -505,10 +490,7 @@ void GuiGameGrid::Update(GuiTrigger * t) } else if (btnRight->GetState() == STATE_CLICKED) { - WPAD_ScanPads(); - u16 buttons = 0; - for (int i = 0; i < 4; i++) - buttons |= WPAD_ButtonsHeld(i); + u32 buttons = t->wpad.btns_h; if (!((buttons & WPAD_BUTTON_A) || (buttons & WPAD_BUTTON_PLUS) || t->Right())) { btnRight->ResetState(); @@ -721,25 +703,24 @@ void GuiGameGrid::Reload(int Rows, int ListOffset) { LOCK( this ); + //Prevent to wait before all images are loaded before we can delete them + GuiImageAsync::ClearQueue(); + // CleanUp - if (game) for (int i = pagesize - 1; i >= 0; i--) + for (u32 i = 0; i < game.size(); ++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]; - // if(cover) - // for(int i=pagesize-1; i>=0; i--) - // delete cover[i]; - - if (titleTT) for (int i = pagesize - 1; i >= 0; i--) + for (u32 i = 0; i < titleTT.size(); ++i) delete titleTT[i]; - delete[] gameIndex; - delete[] game; - delete[] coverImg; - // delete [] cover; - delete[] titleTT; + if(gameIndex) + delete [] gameIndex; + game.clear(); + coverImg.clear(); + titleTT.clear(); goLeft = 0; goRight = 0; @@ -759,10 +740,9 @@ void GuiGameGrid::Reload(int Rows, int ListOffset) // Page-Stuff gameIndex = new int[pagesize]; - titleTT = new GuiTooltip *[pagesize]; - // cover = new GuiImageData *[pagesize]; - coverImg = new GuiImageAsync *[pagesize]; - game = new GuiButton *[pagesize]; + titleTT.resize(pagesize); + coverImg.resize(pagesize); + game.resize(pagesize); int wsi = Settings.widescreen ? 0 : 1; int (*Pos)[2][2] = VALUE4ROWS( rows, Pos1, Pos2, Pos3 ); @@ -799,8 +779,7 @@ void GuiGameGrid::Reload(int Rows, int ListOffset) coverImg[i] = NULL; if (gameIndex[i] != -1) { - coverImg[i] = new GuiImageAsync(GameGridLoadCoverImage, gameList[gameIndex[i]], sizeof(struct discHdr), - &noCover); + coverImg[i] = new GuiImageAsync(GameGridLoadCoverImage, gameList[gameIndex[i]], sizeof(struct discHdr), &noCover); if (coverImg[i]) { coverImg[i]->SetWidescreen(Settings.widescreen); diff --git a/source/libwiigui/gui_gamegrid.h b/source/libwiigui/gui_gamegrid.h index 4279a0bc..c6ea4d99 100644 --- a/source/libwiigui/gui_gamegrid.h +++ b/source/libwiigui/gui_gamegrid.h @@ -1,8 +1,10 @@ #ifndef _GUIGAMEGRID_H_ #define _GUIGAMEGRID_H_ +#include #include "gui.h" -#include "../usbloader/disc.h" +#include "usbloader/disc.h" + class GuiImageAsync; class GuiGameGrid: public GuiElement { @@ -30,9 +32,9 @@ class GuiGameGrid: public GuiElement int goRight; int * gameIndex; - GuiButton ** game; - GuiTooltip ** titleTT; - GuiImageAsync ** coverImg; + std::vector game; + std::vector titleTT; + std::vector coverImg; GuiButton * btnRight; GuiButton * btnLeft; diff --git a/source/libwiigui/gui_image_async.cpp b/source/libwiigui/gui_image_async.cpp index ff08d800..a2ad15ad 100644 --- a/source/libwiigui/gui_image_async.cpp +++ b/source/libwiigui/gui_image_async.cpp @@ -1,187 +1,149 @@ /**************************************************************************** - * libwiigui - * - * Tantric 2009 + * USB Loader GX * * gui_imagea_sync.cpp - * - * GUI class definitions ***************************************************************************/ - -#include "gui.h" -//#include #include #include "gui_image_async.h" -static mutex_t debugLock = LWP_MUTEX_NULL; -void debug(int Line, const char* Format, ...) +std::vector 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); if (dst) memcpy(dst, src, len); return dst; } -static std::vector List; -static u32 ThreadCount = 0; -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) + +static GuiImageData * StdImageLoaderCallback(void *arg) { - while (!Quit) - { - 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; + return new GuiImageData((char *) arg); } -static u32 GuiImageAsyncThreadInit() +GuiImageAsync::GuiImageAsync(const char *Filename, GuiImageData * PreloadImg) : + GuiImage(PreloadImg), imgData(NULL), callback(StdImageLoaderCallback), arg(strdup(Filename)) { - if (0 == ThreadCount++) - { - 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; + ThreadInit(); + ThreadAddImage(this); } -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); List.push_back(Image); LWP_MutexUnlock(ListLock); - CanSleep = false; - // if(LWP_ThreadIsSuspended(Thread)) + ThreadSleep = false; LWP_ResumeThread(Thread); } -static void GuiImageAsyncThread_RemoveImage(GuiImageAsync* Image) + +void GuiImageAsync::ThreadRemoveImage(GuiImageAsync *Image) { - LWP_MutexLock(ListLock); - for (std::vector::iterator iter = List.begin(); iter != List.end(); iter++) + for(u32 i = 0; i < List.size(); ++i) { - if (*iter == Image) + if(List[i] == Image) { - List.erase(iter); + LWP_MutexLock(ListLock); + List.erase(List.begin()+i); LWP_MutexUnlock(ListLock); - return; + break; } } - if (InUse == Image) - { - LWP_MutexLock(InUseLock); - LWP_MutexUnlock(InUseLock); - } +} + +void GuiImageAsync::ClearQueue() +{ + LWP_MutexLock(ListLock); + List.clear(); LWP_MutexUnlock(ListLock); } -/** - * Constructor for the GuiImageAsync class. - */ -GuiImageData *StdImageLoaderCallback(void *arg) +void * GuiImageAsync::GuiImageAsyncThread(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) : - GuiImage(PreloadImg), loadet_imgdata(NULL), callback(StdImageLoaderCallback), arg(strdup(Filename)) +u32 GuiImageAsync::ThreadInit() { - 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); + 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; + } + */ + return --ThreadCount; } diff --git a/source/libwiigui/gui_image_async.h b/source/libwiigui/gui_image_async.h index b003d5d9..3f440b4a 100644 --- a/source/libwiigui/gui_image_async.h +++ b/source/libwiigui/gui_image_async.h @@ -1,25 +1,37 @@ #ifndef _GUIIMAGEASYNC_H_ #define _GUIIMAGEASYNC_H_ -#// arg is a pointer created with malloc() -// when the image is destroied then will also the arg deleted with free() +#include +#include "libwiigui/gui.h" + typedef GuiImageData * (*ImageLoaderCallback)(void *arg); class GuiImageAsync: public GuiImage { public: 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(); + static void ClearQueue(); private: - GuiImageData *loadet_imgdata; - friend void loader(GuiImageAsync *InUse); - - friend void Setter(GuiImageAsync *InUse); - friend void *GuiImageAsyncThread(void *arg); + GuiImageData *imgData; ImageLoaderCallback callback; 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 List; + static lwp_t Thread; + static mutex_t ListLock; + static GuiImageAsync * InUse; + static u32 ThreadCount; + static bool ThreadSleep; + static bool CloseThread; }; #endif /*_GUIIMAGEASYNC_H_*/ diff --git a/source/menu.cpp b/source/menu.cpp index 42544ba2..1557187e 100644 --- a/source/menu.cpp +++ b/source/menu.cpp @@ -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 ***************************************************************************/ diff --git a/source/menu.h b/source/menu.h index d79f0b05..e9cee0b0 100644 --- a/source/menu.h +++ b/source/menu.h @@ -34,7 +34,6 @@ enum void ResumeGui(); void HaltGui(); -GuiImageData *LoadCoverImage(struct discHdr *header, bool Prefere3D = true, bool noCover = true); extern GuiImageData *pointer[4]; extern GuiImageData *background; diff --git a/source/menu/GameBrowseMenu.cpp b/source/menu/GameBrowseMenu.cpp index 23c34d20..9dca35b1 100644 --- a/source/menu/GameBrowseMenu.cpp +++ b/source/menu/GameBrowseMenu.cpp @@ -1,5 +1,6 @@ #include #include "GameBrowseMenu.hpp" +#include "libwiigui/LoadCoverImage.h" #include "prompts/PromptWindows.h" #include "prompts/gameinfo.h" #include "prompts/DiscBrowser.h" @@ -22,6 +23,7 @@ #include "utils/rockout.h" #include "utils/ShowError.h" #include "utils/tools.h" +#include "utils/PasswordCheck.h" #include "fatmounter.h" #include "gecko.h" #include "menus.h" @@ -539,18 +541,18 @@ void GameBrowseMenu::ReloadBrowser() idBtn->SetToolTip(NULL, 0, 0); } - if ((Settings.parentalcontrol == 0 && Settings.Parental.enabled == 1) && Settings.godmode) + if (Settings.godmode) { - lockBtn->SetImage(unlockBtnImg); - lockBtn->SetImageOver(unlockBtnImg); - lockBtnTT->SetText(tr( "Unlock Parental Control" )); + GuiImage * unlockImage = strcmp(Settings.unlockCode, "") == 0 ? unlockBtnImg_g : unlockBtnImg; + lockBtn->SetImage(unlockImage); + lockBtn->SetImageOver(unlockImage); + lockBtnTT->SetText(tr( "Lock USB Loader GX" )); } else { - GuiImage * lockImage = Settings.Parental.enabled ? lockBtnImg : lockBtnImg_g; - lockBtn->SetImage(lockImage); - lockBtn->SetImageOver(lockImage); - lockBtnTT->SetText(tr( "Parental Control disabled" )); + lockBtn->SetImage(lockBtnImg); + lockBtn->SetImageOver(lockBtnImg); + lockBtnTT->SetText(tr( "Unlock USB Loader GX" )); } if(GetSelectedGame() >= 0) @@ -948,15 +950,9 @@ int GameBrowseMenu::MainLoop() { gprintf("\tlockBtn clicked\n"); 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(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; wString oldFilter(gameList.GetCurrentFilter()); @@ -966,23 +962,21 @@ int GameBrowseMenu::MainLoop() } else { - // Require the user to enter the PIN code - char pin[5]; - memset(&pin, 0, 5); - int ret = OnScreenNumpad((char *) &pin, 5); - - if (ret <= 0) - return MENU_NONE; - - if (memcmp(pin, Settings.Parental.pin, 4) == 0) + //password check to unlock Install,Delete and Format + SetState(STATE_DISABLED); + int result = PasswordCheck(Settings.unlockCode); + SetState(STATE_DEFAULT); + if (result > 0) { + if(result == 1) + WindowPrompt( tr( "Correct Password" ), tr( "All the features of USB Loader GX are unlocked." ), tr( "OK" )); Settings.godmode = 1; wString oldFilter(gameList.GetCurrentFilter()); gameList.FilterList(oldFilter.c_str()); ReloadBrowser(); } - else - WindowPrompt(tr( "Parental Control" ), tr( "Invalid PIN code" ), tr( "OK" )); + else if(result < 0) + WindowPrompt(tr( "Wrong Password" ), tr( "USB Loader GX is protected" ), tr( "OK" )); } } diff --git a/source/menu/MountGamePartition.cpp b/source/menu/MountGamePartition.cpp index dee8df9a..da890fbc 100644 --- a/source/menu/MountGamePartition.cpp +++ b/source/menu/MountGamePartition.cpp @@ -118,7 +118,7 @@ int MountGamePartition(bool ShowGUI) s32 wbfsinit = MountWBFS(ShowGUI); 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(); } diff --git a/source/settings/CSettings.cpp b/source/settings/CSettings.cpp index 600a5c87..059736a6 100644 --- a/source/settings/CSettings.cpp +++ b/source/settings/CSettings.cpp @@ -32,6 +32,7 @@ #include "language/gettext.h" #include "themes/CTheme.h" #include "FileOperations/fileops.h" +#include "utils/encrypt.h" CSettings Settings; @@ -66,7 +67,11 @@ void CSettings::SetDefault() strcpy(language_path, ""); strcpy(ogg_path, ""); strcpy(unlockCode, ""); + strcpy(db_url, ""); + strcpy(db_language, ""); + strcpy(returnTo, ""); + godmode = 1; videomode = VIDEO_MODE_DISCDEFAULT; videopatch = OFF; language = CONSOLE_DEFAULT; @@ -80,7 +85,7 @@ void CSettings::SetDefault() gamesoundvolume = 80; tooltips = ON; gamesound = 1; - parentalcontrol = 0; + parentalcontrol = 4; lockedgames = 0; cios = 249; xflip = XFLIP_NO; @@ -101,28 +106,7 @@ void CSettings::SetDefault() InstallPartitions = ONLY_GAME_PARTITION; fullcopy = 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); - godmode = (Parental.enabled == 0) ? 1 : 0; Theme.SetDefault(); //! We need to move this later } @@ -187,7 +171,9 @@ bool CSettings::Save() fprintf(file, "sfxvolume = %d\n ", sfxvolume); fprintf(file, "gamesoundvolume = %d\n ", gamesoundvolume); 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, "cios = %d\n ", cios); fprintf(file, "keyset = %d\n ", keyset); @@ -243,7 +229,7 @@ bool CSettings::SetSetting(char *name, char *value) { if (sscanf(value, "%d", &i) == 1) { - if(Parental.enabled) godmode = i; + godmode = i; } return true; } @@ -337,7 +323,9 @@ bool CSettings::SetSetting(char *name, char *value) } else if (strcmp(name, "password") == 0) { - strcpy(unlockCode, value); + char EncryptedTxt[50]; + strcpy(EncryptedTxt, value); + DecryptString(EncryptedTxt, unlockCode); return true; } else if (strcmp(name, "GameSort") == 0) diff --git a/source/settings/CSettings.h b/source/settings/CSettings.h index c41c9073..6a979085 100644 --- a/source/settings/CSettings.h +++ b/source/settings/CSettings.h @@ -110,14 +110,6 @@ class CSettings short fullcopy; short beta_upgrades; char returnTo[20]; - struct - { - u8 enabled; - u8 rating; - u8 pin[4]; - u8 question; - wchar_t answer[32]; // IS WCHAR! - } Parental; protected: bool SetSetting(char *name, char *value); //!Find the config file in the default paths diff --git a/source/settings/GameTitles.cpp b/source/settings/GameTitles.cpp index 6c6d9b1b..1396ab5b 100644 --- a/source/settings/GameTitles.cpp +++ b/source/settings/GameTitles.cpp @@ -2,6 +2,7 @@ #include "GameTitles.h" #include "CSettings.h" #include "usbloader/GameList.h" +#include "xml/xml.h" #include "xml/WiiTDB.hpp" CGameTitles GameTitles; @@ -61,6 +62,20 @@ const char * CGameTitles::GetTitle(const struct discHdr *header) 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() { TitleList.clear(); @@ -85,10 +100,25 @@ void CGameTitles::LoadTitlesFromWiiTDB(const char * path) WiiTDB XML_DB(Filepath.c_str()); XML_DB.SetLanguageCode(Settings.db_language); + int Rating; + std::string RatValTxt; for(int i = 0; i < gameList.GameCount(); ++i) { - if(XML_DB.GetTitle((const char *) gameList[i]->id, Title)) - this->SetGameTitle(gameList[i]->id, Title.c_str()); + if(!XML_DB.GetTitle((const char *) gameList[i]->id, Title)) + 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"); } } diff --git a/source/settings/GameTitles.h b/source/settings/GameTitles.h index f27ed95d..ef8f9def 100644 --- a/source/settings/GameTitles.h +++ b/source/settings/GameTitles.h @@ -10,6 +10,7 @@ typedef struct _GameTitle { char GameID[7]; std::string Title; + int ParentalRating; } GameTitle; @@ -28,6 +29,9 @@ class CGameTitles //! Overload const char * GetTitle(const struct discHdr *header); + //! Get game parental rating + int GetParentalRating(const char * id); + //! Load Game Titles from WiiTDB void LoadTitlesFromWiiTDB(const char * path); //! Set default game titles diff --git a/source/settings/menus/ParentalControlSM.cpp b/source/settings/menus/ParentalControlSM.cpp index c665dc1b..6b4dd9a1 100644 --- a/source/settings/menus/ParentalControlSM.cpp +++ b/source/settings/menus/ParentalControlSM.cpp @@ -26,6 +26,7 @@ #include "settings/CSettings.h" #include "prompts/PromptWindows.h" #include "language/gettext.h" +#include "utils/PasswordCheck.h" static const char * LockModeText[] = { @@ -101,41 +102,27 @@ int ParentalControlSM::GetMenuInternal() //! Settings: Console 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 SetState(STATE_DISABLED); - int result = Settings.Parental.enabled == 0 ? OnScreenKeyboard(entered, 20, 0) : OnScreenNumpad(entered, 5); + int result = PasswordCheck(Settings.unlockCode); SetState(STATE_DEFAULT); - if (result == 1) + if (result > 0) { - if (strcmp(entered, Settings.unlockCode) == 0 || !memcmp(entered, Settings.Parental.pin, 4)) //if password correct - { - WindowPrompt( - 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" )); + if(result == 1) + WindowPrompt( tr( "Correct Password" ), tr( "All the features of USB Loader GX are unlocked." ), tr( "OK" )); + Settings.godmode = 1; } + else if(result < 0) + WindowPrompt(tr( "Wrong Password" ), tr( "USB Loader GX is protected" ), tr( "OK" )); } else { - int choice = WindowPrompt(tr( "Lock Console" ), tr( "Are you sure?" ), - tr( "Yes" ), tr( "No" )); + int choice = WindowPrompt(tr( "Lock Console" ), tr( "Are you sure?" ), tr( "Yes" ), tr( "No" )); if (choice == 1) { - WindowPrompt(tr( "Console Locked" ), tr( "USB Loader GX is protected" ), - tr( "OK" )); + WindowPrompt(tr( "Console Locked" ), tr( "USB Loader GX is protected" ), tr( "OK" )); Settings.godmode = 0; } } diff --git a/source/system/IosLoader.cpp b/source/system/IosLoader.cpp index 045b0f66..dafad527 100644 --- a/source/system/IosLoader.cpp +++ b/source/system/IosLoader.cpp @@ -102,7 +102,7 @@ s32 IosLoader::LoadGameCios(s32 ios) // Remount devices after reloading IOS. SDCard_Init(); - USBDevice_Init(); + USBDevice_Init_Loop(); Disc_Init(); return ret; diff --git a/source/usbloader/GameList.cpp b/source/usbloader/GameList.cpp index 74a902e4..ef654b49 100644 --- a/source/usbloader/GameList.cpp +++ b/source/usbloader/GameList.cpp @@ -155,18 +155,12 @@ int GameList::FilterList(const wchar_t * gameFilter) } /* 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 - s32 rating = GetRatingForGame((char *) header->id); - - if ((rating != -1 && rating > Settings.Parental.rating) || - (GameConfig && rating == -1 && - CGameSettings::GetPartenalPEGI(GameConfig->parentalcontrol) - > Settings.Parental.rating)) - { + int rating = GameTitles.GetParentalRating((char *) header->id); + if (rating > Settings.parentalcontrol) continue; - } } //! Per game lock method diff --git a/source/usbloader/partition_usbloader.c b/source/usbloader/partition_usbloader.c index 17dd257a..52974067 100644 --- a/source/usbloader/partition_usbloader.c +++ b/source/usbloader/partition_usbloader.c @@ -380,7 +380,7 @@ s32 Partition_GetList(u32 device, PartList *plist) //if (!part_is_data(entry->type)) continue; if (!Device_ReadSectors(device, entry->sector, 1, buf)) continue; 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) { // multiple wbfs on sdhc not supported diff --git a/source/usbloader/wbfs.cpp b/source/usbloader/wbfs.cpp index 33beca6a..4b0131a2 100644 --- a/source/usbloader/wbfs.cpp +++ b/source/usbloader/wbfs.cpp @@ -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); 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) { current = new Wbfs_Ntfs(wbfsDev, part_lba, part_size); 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) { current = new Wbfs_Ext(wbfsDev, part_lba, part_size); 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 { 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()) { diff --git a/source/utils/PasswordCheck.cpp b/source/utils/PasswordCheck.cpp new file mode 100644 index 00000000..a0ceb595 --- /dev/null +++ b/source/utils/PasswordCheck.cpp @@ -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; +} diff --git a/source/utils/PasswordCheck.h b/source/utils/PasswordCheck.h new file mode 100644 index 00000000..9df6cc22 --- /dev/null +++ b/source/utils/PasswordCheck.h @@ -0,0 +1,6 @@ +#ifndef PASSWORD_CHECK_H_ +#define PASSWORD_CHECK_H_ + +int PasswordCheck(const char * password); + +#endif diff --git a/source/utils/encrypt.c b/source/utils/encrypt.c new file mode 100644 index 00000000..52fbf5f7 --- /dev/null +++ b/source/utils/encrypt.c @@ -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 +#include + +//! 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; +} + diff --git a/source/utils/encrypt.h b/source/utils/encrypt.h new file mode 100644 index 00000000..6c8139de --- /dev/null +++ b/source/utils/encrypt.h @@ -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 */ + diff --git a/source/xml/xml.cpp b/source/xml/xml.cpp index 95ad652c..2d62def1 100644 --- a/source/xml/xml.cpp +++ b/source/xml/xml.cpp @@ -13,27 +13,10 @@ 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 */ -static bool xmldebug = false; static char xmlcfg_filename[100] = "wiitdb"; static int xmlmaxsize = 1572864; -struct gameXMLinfo gameinfo; -struct gameXMLinfo gameinfo_reset; - static char langlist[11][22] = { { "Console Default" }, { "Japanese" }, { "English" }, { "German" }, { "French" }, { "Spanish" }, { "Italian" }, { "Dutch" }, { "S. Chinese" }, { "T. Chinese" }, { "Korean" } }; @@ -128,7 +111,6 @@ bool OpenXMLFile(char *filename) if (xml_loaded) return false; - gameinfo = gameinfo_reset; nodedata = NULL; nodetree = NULL; nodeid = NULL; @@ -245,40 +227,70 @@ char ConvertRatingToIndex(char *ratingtext) 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)) { - strlcpy(destvalue, ratingvalue, destsize); - return; + int ret = atoi(ratingvalue); + 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 desttype = -1; - type = ConvertRatingToIndex(fromrating); + type = ConvertRatingToIndex((char *) fromrating); desttype = ConvertRatingToIndex((char *) torating); - if (type == -1 || desttype == -1) return; + if (type == -1 || desttype == -1) return -1; /* rating conversion table */ /* 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 */ /* 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" }, { - "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" } }, }; + char ratingtable[12][3][5] = + { + { { "A" }, { "E" }, { "3" } }, + { { "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; for (i = 0; i <= 11; i++) { if (!strcmp(ratingtable[i][type], ratingvalue)) { - strlcpy(destvalue, ratingtable[i][desttype], destsize); - return; + int ret = atoi(ratingtable[i][desttype]); + 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) @@ -388,388 +400,6 @@ void GetPublisherFromGameid(char *idtxt, char *dest, int destsize) 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 linebuf[300] = ""; @@ -819,43 +449,3 @@ char * get_nodetext(mxml_node_t *node, char *buffer, int buflen) /* O - Text in *ptr = '\0'; 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; -} diff --git a/source/xml/xml.h b/source/xml/xml.h index 2bb09ee1..cd40b089 100644 --- a/source/xml/xml.h +++ b/source/xml/xml.h @@ -6,61 +6,17 @@ // open database, close database, load info for a game bool OpenXMLDatabase(char* xmlfilepath, char* argdblang, bool argJPtoEN, bool openfile, bool loadtitles, bool keepopen); void CloseXMLDatabase(); -bool LoadGameInfoFromXML(char* gameid, char* langcode); #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); void LoadTitlesFromXML(char *langcode, bool forcejptoen); void GetPublisherFromGameid(char *idtxt, char *dest, int destsize); const char *ConvertLangTextToCode(char *langtext); -void ConvertRating(char *ratingvalue, char *fromrating, const char *torating, char *destvalue, int destsize); -void PrintGameInfo(bool showfullinfo); +int ConvertRating(const char *ratingvalue, const char *fromrating, const char *torating); char *MemInfo(); void GetTextFromNode(mxml_node_t *currentnode, mxml_node_t *topnode, const char *nodename, const char *attributename, char *value, int descend, char *dest, int destsize); -int GetRatingForGame(char *gameid); char * get_nodetext(mxml_node_t *node, char *buffer, int buflen); #endif