mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-12-22 18:01:54 +01:00
*Reworked the whole WiiTDB.xml parsing. This is now done with mxml due to a lack of memory the file is now streamed. Now the full wiitdb.xml file with all languages is always used. The update of WiiTDB is also changed. It is now only updated if the version of the wiitdb.xml file does not match the version of the online file.
*WiiTDB now falls back to english if the locale language is not found for Titles/Synopsis *Some clean up and memory leak fixes in game info prompt and adjusted the info get to the new WiiTDB reading method. *Added a few new useful functions from WiiXplorer (DownloadToFileWithProgress, ShowError,...) *Disabled the console output after the GUI is started up. The info is only output to gecko in GUI mode now.
This commit is contained in:
parent
4c07b6db74
commit
500dc4020f
@ -2,8 +2,8 @@
|
||||
<app version="1">
|
||||
<name> USB Loader GX</name>
|
||||
<coder>USB Loader GX Team</coder>
|
||||
<version>1.0 r1006</version>
|
||||
<release_date>201011300400</release_date>
|
||||
<version>1.0 r1007</version>
|
||||
<release_date>201012031819</release_date>
|
||||
<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.
|
||||
The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller.
|
||||
|
File diff suppressed because one or more lines are too long
@ -2,6 +2,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <sys/iosupport.h>
|
||||
|
||||
/* init-globals */
|
||||
static bool geckoinit = false;
|
||||
@ -75,4 +76,46 @@ void hexdump(void *d, int len)
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t __out_write(struct _reent *r, int fd, const char *ptr, size_t len)
|
||||
{
|
||||
if(geckoinit && ptr)
|
||||
{
|
||||
u32 level;
|
||||
level = IRQ_Disable();
|
||||
usb_sendbuffer(1, ptr, len);
|
||||
IRQ_Restore(level);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static const devoptab_t gecko_out = {
|
||||
"stdout", // device name
|
||||
0, // size of file structure
|
||||
NULL, // device open
|
||||
NULL, // device close
|
||||
__out_write,// device write
|
||||
NULL, // device read
|
||||
NULL, // device seek
|
||||
NULL, // device fstat
|
||||
NULL, // device stat
|
||||
NULL, // device link
|
||||
NULL, // device unlink
|
||||
NULL, // device chdir
|
||||
NULL, // device rename
|
||||
NULL, // device mkdir
|
||||
0, // dirStateSize
|
||||
NULL, // device diropen_r
|
||||
NULL, // device dirreset_r
|
||||
NULL, // device dirnext_r
|
||||
NULL, // device dirclose_r
|
||||
NULL // device statvfs_r
|
||||
};
|
||||
|
||||
void USBGeckoOutput()
|
||||
{
|
||||
devoptab_list[STD_OUT] = &gecko_out;
|
||||
devoptab_list[STD_ERR] = &gecko_out;
|
||||
}
|
||||
|
||||
#endif /* NO_DEBUG */
|
||||
|
@ -14,6 +14,7 @@ extern "C"
|
||||
void gprintf(const char *str, ...);
|
||||
bool InitGecko();
|
||||
void hexdump(void *d, int len);
|
||||
void USBGeckoOutput();
|
||||
#else
|
||||
#define gprintf(...)
|
||||
#define InitGecko() false
|
||||
|
@ -37,6 +37,7 @@
|
||||
extern u32 infilesize;
|
||||
extern u32 uncfilesize;
|
||||
extern char wiiloadVersion[2];
|
||||
extern int connection;
|
||||
|
||||
HomebrewBrowser::HomebrewBrowser()
|
||||
: FlyingButtonsMenu(tr( "Homebrew Launcher" ))
|
||||
@ -293,7 +294,7 @@ int HomebrewBrowser::ReceiveFile()
|
||||
len = infilesize - read;
|
||||
else len = NETWORKBLOCKSIZE;
|
||||
|
||||
int result = network_read(buffer+read, len);
|
||||
int result = network_read(connection, buffer+read, len);
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
@ -310,7 +311,7 @@ int HomebrewBrowser::ReceiveFile()
|
||||
}
|
||||
|
||||
char filename[101];
|
||||
network_read((u8*) &filename, 100);
|
||||
network_read(connection, (u8*) &filename, 100);
|
||||
|
||||
// Do we need to unzip this thing?
|
||||
if (wiiloadVersion[0] > 0 || wiiloadVersion[1] > 4)
|
||||
|
@ -17,7 +17,7 @@
|
||||
int updateLanguageFiles()
|
||||
{
|
||||
char languageFiles[50][MAXLANGUAGEFILES];
|
||||
|
||||
|
||||
DirList Dir(Settings.languagefiles_path);
|
||||
|
||||
//give up now if we didn't find any
|
||||
@ -48,7 +48,7 @@ int updateLanguageFiles()
|
||||
char codeurl[200];
|
||||
snprintf(codeurl, sizeof(codeurl), "http://usbloader-gui.googlecode.com/svn/trunk/Languages/%s",
|
||||
languageFiles[j]);
|
||||
snprintf(savepath, sizeof(savepath), "%s%s", Settings.languagefiles_path, languageFiles[j]);
|
||||
snprintf(savepath, sizeof(savepath), "%s/%s", Settings.languagefiles_path, languageFiles[j]);
|
||||
|
||||
struct block file = downloadfile(codeurl);
|
||||
|
||||
|
@ -118,6 +118,9 @@ int main(int argc, char *argv[])
|
||||
return BootGame(argv[1]);
|
||||
}
|
||||
|
||||
//! Now we startup the GUI so no need for console prints. Output only to gecko.
|
||||
USBGeckoOutput();
|
||||
|
||||
//! Init the rest of the System
|
||||
Sys_Init();
|
||||
SetupPads();
|
||||
|
@ -8,7 +8,9 @@
|
||||
#include "wpad.h"
|
||||
#include "fatmounter.h"
|
||||
#include "usbloader/wbfs.h"
|
||||
#include "xml/xml.h"
|
||||
#include "usbloader/GameList.h"
|
||||
#include "settings/GameTitles.h"
|
||||
#include "xml/WiiTDB.hpp"
|
||||
|
||||
extern int load_from_fs;
|
||||
extern char game_partition[6];
|
||||
@ -163,11 +165,8 @@ int MountGamePartition(bool ShowGUI)
|
||||
}
|
||||
|
||||
gprintf("\tOpenXMLDatabase\n");
|
||||
// open database if needed, load titles if needed
|
||||
if (CheckFile(Settings.titlestxt_path))
|
||||
OpenXMLDatabase(Settings.titlestxt_path, Settings.db_language, Settings.db_JPtoEN, true, Settings.titlesOverride, true);
|
||||
|
||||
gprintf("MountGamePartition() return: %i\n", ret);
|
||||
GameTitles.LoadTitlesFromWiiTDB(Settings.titlestxt_path);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
280
source/network/FileDownloader.cpp
Normal file
280
source/network/FileDownloader.cpp
Normal file
@ -0,0 +1,280 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2010
|
||||
* by 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 <ogcsys.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "language/gettext.h"
|
||||
#include "networkops.h"
|
||||
#include "http.h"
|
||||
#include "FileOperations/fileops.h"
|
||||
#include "prompts/PromptWindows.h"
|
||||
#include "prompts/ProgressWindow.h"
|
||||
#include "utils/ShowError.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Download a file from a given url with a Progressbar
|
||||
****************************************************************************/
|
||||
int DownloadFileToMem(const char *url, u8 **inbuffer, u32 *size)
|
||||
{
|
||||
if(strncasecmp(url, "http://", strlen("http://")) != 0)
|
||||
{
|
||||
ShowError(tr("Not a valid URL"));
|
||||
return -1;
|
||||
}
|
||||
char *path = strchr(url + strlen("http://"), '/');
|
||||
|
||||
if(!path)
|
||||
{
|
||||
ShowError(tr("Not a valid URL path"));
|
||||
return -2;
|
||||
}
|
||||
|
||||
int domainlength = path - url - strlen("http://");
|
||||
|
||||
if(domainlength == 0)
|
||||
{
|
||||
ShowError(tr("Not a valid domain"));
|
||||
return -3;
|
||||
}
|
||||
|
||||
char domain[domainlength + 1];
|
||||
strncpy(domain, url + strlen("http://"), domainlength);
|
||||
domain[domainlength] = '\0';
|
||||
|
||||
int connection = GetConnection(domain);
|
||||
|
||||
if(connection < 0)
|
||||
{
|
||||
ShowError(tr("Could not connect to the server."));
|
||||
return -4;
|
||||
}
|
||||
|
||||
char header[1024];
|
||||
char * ptr = header;
|
||||
ptr += sprintf(ptr, "GET %s HTTP/1.1\r\n", path);
|
||||
ptr += sprintf(ptr, "Host: %s\r\n", domain);
|
||||
ptr += sprintf(ptr, "Referer: %s\r\n", domain);
|
||||
ptr += sprintf(ptr, "User-Agent: USB Loader GX\r\n");
|
||||
ptr += sprintf(ptr, "Pragma: no-cache\r\n");
|
||||
ptr += sprintf(ptr, "Cache-Control: no-cache\r\n");
|
||||
ptr += sprintf(ptr, "Connection: close\r\n\r\n");
|
||||
|
||||
char filename[255];
|
||||
memset(filename, 0, sizeof(filename));
|
||||
|
||||
u32 filesize = network_request(connection, header, (char *) &filename);
|
||||
|
||||
if(!filesize)
|
||||
{
|
||||
net_close(connection);
|
||||
ShowError(tr("Filesize is 0 Byte."));
|
||||
return -5;
|
||||
}
|
||||
|
||||
u32 blocksize = 10*1024;
|
||||
|
||||
u8 * buffer = (u8 *) malloc(filesize);
|
||||
if(!buffer)
|
||||
{
|
||||
net_close(connection);
|
||||
ShowError(tr("Not enough memory."));
|
||||
return -6;
|
||||
}
|
||||
|
||||
u32 done = 0;
|
||||
|
||||
while(done < filesize)
|
||||
{
|
||||
ShowProgress(tr("Downloading file..."), 0, filename, (f32) done, (f32) filesize, true, true);
|
||||
|
||||
if(blocksize > filesize - done)
|
||||
blocksize = filesize - done;
|
||||
|
||||
|
||||
s32 read = network_read(connection, buffer+done, blocksize);
|
||||
|
||||
if(read < 0)
|
||||
{
|
||||
free(buffer);
|
||||
ProgressStop();
|
||||
net_close(connection);
|
||||
ShowError(tr("Transfer failed"));
|
||||
return -8;
|
||||
}
|
||||
else if(!read)
|
||||
break;
|
||||
|
||||
done += read;
|
||||
}
|
||||
|
||||
ProgressStop();
|
||||
net_close(connection);
|
||||
|
||||
*inbuffer = buffer;
|
||||
*size = filesize;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Download a file from a given url to a given path with a Progressbar
|
||||
****************************************************************************/
|
||||
int DownloadFileToPath(const char *orig_url, const char *dest, bool UseFilename)
|
||||
{
|
||||
if(!orig_url || !dest)
|
||||
{
|
||||
ShowError(tr("No URL or Path specified."));
|
||||
return -2;
|
||||
}
|
||||
|
||||
bool addhttp = false;
|
||||
|
||||
if(strncasecmp(orig_url, "http://", strlen("http://")) != 0)
|
||||
{
|
||||
addhttp = true;
|
||||
}
|
||||
|
||||
char url[strlen(orig_url) + (addhttp ? strlen("http://") : 0) + 1];
|
||||
|
||||
if(addhttp)
|
||||
snprintf(url, sizeof(url), "http://%s", orig_url);
|
||||
else
|
||||
strcpy(url, orig_url);
|
||||
|
||||
char *path = strchr(url + strlen("http://"), '/');
|
||||
|
||||
if(!path)
|
||||
{
|
||||
ShowError(tr("Not a valid URL path"));
|
||||
return -2;
|
||||
}
|
||||
|
||||
int domainlength = path - url - strlen("http://");
|
||||
|
||||
if(domainlength == 0)
|
||||
{
|
||||
ShowError(tr("Not a valid domain"));
|
||||
return -3;
|
||||
}
|
||||
|
||||
char domain[domainlength + 1];
|
||||
strncpy(domain, url + strlen("http://"), domainlength);
|
||||
domain[domainlength] = '\0';
|
||||
|
||||
int connection = GetConnection(domain);
|
||||
|
||||
if(connection < 0)
|
||||
{
|
||||
ShowError(tr("Could not connect to the server."));
|
||||
return -4;
|
||||
}
|
||||
|
||||
char header[1024];
|
||||
char * ptr = header;
|
||||
ptr += sprintf(ptr, "GET %s HTTP/1.1\r\n", path);
|
||||
ptr += sprintf(ptr, "Host: %s\r\n", domain);
|
||||
ptr += sprintf(ptr, "Referer: %s\r\n", domain);
|
||||
ptr += sprintf(ptr, "User-Agent: WiiXplorer\r\n");
|
||||
ptr += sprintf(ptr, "Pragma: no-cache\r\n");
|
||||
ptr += sprintf(ptr, "Cache-Control: no-cache\r\n");
|
||||
ptr += sprintf(ptr, "Connection: close\r\n\r\n");
|
||||
|
||||
char filename[255];
|
||||
memset(filename, 0, sizeof(filename));
|
||||
|
||||
u32 filesize = network_request(connection, header, (char *) &filename);
|
||||
|
||||
if(!filesize)
|
||||
{
|
||||
net_close(connection);
|
||||
ShowError(tr("Filesize is 0 Byte."));
|
||||
return -5;
|
||||
}
|
||||
|
||||
u32 blocksize = 10*1024;
|
||||
|
||||
u8 *buffer = (u8 *) malloc(blocksize);
|
||||
if(!buffer)
|
||||
{
|
||||
net_close(connection);
|
||||
ShowError(tr("Not enough memory."));
|
||||
return -6;
|
||||
}
|
||||
|
||||
if(UseFilename)
|
||||
{
|
||||
if(dest[strlen(dest)-1] != '/')
|
||||
strcat((char *) dest, "/");
|
||||
|
||||
CreateSubfolder(dest);
|
||||
|
||||
strcat((char *) dest, filename);
|
||||
}
|
||||
|
||||
FILE *file = fopen(dest, "wb");
|
||||
if(!file)
|
||||
{
|
||||
net_close(connection);
|
||||
free(buffer);
|
||||
ShowError(tr("Cannot write to destination."));
|
||||
return -7;
|
||||
}
|
||||
|
||||
u32 done = 0;
|
||||
|
||||
while(done < filesize)
|
||||
{
|
||||
ShowProgress(tr("Downloading file..."), 0, filename, (f32) done, (f32) filesize, true, true);
|
||||
|
||||
if(blocksize > filesize - done)
|
||||
blocksize = filesize - done;
|
||||
|
||||
s32 read = network_read(connection, buffer, blocksize);
|
||||
|
||||
if(read < 0)
|
||||
{
|
||||
free(buffer);
|
||||
ProgressStop();
|
||||
net_close(connection);
|
||||
fclose(file);
|
||||
ShowError(tr("Transfer failed"));
|
||||
return -8;
|
||||
}
|
||||
else if(!read)
|
||||
break;
|
||||
|
||||
fwrite(buffer, 1, read, file);
|
||||
|
||||
done += read;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
ProgressStop();
|
||||
net_close(connection);
|
||||
fclose(file);
|
||||
|
||||
return done;
|
||||
}
|
32
source/network/FileDownloader.h
Normal file
32
source/network/FileDownloader.h
Normal file
@ -0,0 +1,32 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2010
|
||||
* by 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
|
||||
***************************************************************************/
|
||||
#ifndef FILE_DOWNLOADER_H_
|
||||
#define FILE_DOWNLOADER_H_
|
||||
|
||||
int DownloadFileToMem(const char *url, u8 **inbuffer, u32 *size);
|
||||
int DownloadFileToPath(const char *url, const char *dest, bool UseFilename = true);
|
||||
|
||||
#endif
|
@ -14,10 +14,12 @@
|
||||
#include "prompts/PromptWindows.h"
|
||||
#include "language/gettext.h"
|
||||
#include "settings/CSettings.h"
|
||||
#include "networkops.h"
|
||||
#include "main.h"
|
||||
#include "http.h"
|
||||
#include "svnrev.h"
|
||||
#include "buildtype.h"
|
||||
#include "gecko.h"
|
||||
#include "update.h"
|
||||
|
||||
#define PORT 4299
|
||||
@ -110,7 +112,7 @@ bool ShutdownWC24()
|
||||
return onlinefix;
|
||||
}
|
||||
|
||||
s32 network_request(const char * request, char * filename)
|
||||
s32 network_request(s32 connect, const char * request, char * filename)
|
||||
{
|
||||
char buf[1024];
|
||||
char *ptr = NULL;
|
||||
@ -119,7 +121,7 @@ s32 network_request(const char * request, char * filename)
|
||||
s32 ret;
|
||||
|
||||
/* Send request */
|
||||
ret = net_send(connection, request, strlen(request), 0);
|
||||
ret = net_send(connect, request, strlen(request), 0);
|
||||
if (ret < 0) return ret;
|
||||
|
||||
/* Clear buffer */
|
||||
@ -127,7 +129,7 @@ s32 network_request(const char * request, char * filename)
|
||||
|
||||
/* Read HTTP header */
|
||||
for (cnt = 0; !strstr(buf, "\r\n\r\n"); cnt++)
|
||||
if (net_recv(connection, buf + cnt, 1, 0) <= 0) return -1;
|
||||
if (net_recv(connect, buf + cnt, 1, 0) <= 0) return -1;
|
||||
|
||||
/* HTTP request OK? */
|
||||
if (!strstr(buf, "HTTP/1.1 200 OK")) return -1;
|
||||
@ -157,7 +159,7 @@ s32 network_request(const char * request, char * filename)
|
||||
return size;
|
||||
}
|
||||
|
||||
s32 network_read(u8 *buf, u32 len)
|
||||
s32 network_read(s32 connect, u8 *buf, u32 len)
|
||||
{
|
||||
u32 read = 0;
|
||||
s32 ret = -1;
|
||||
@ -166,7 +168,7 @@ s32 network_read(u8 *buf, u32 len)
|
||||
while (read < len)
|
||||
{
|
||||
/* Read network data */
|
||||
ret = net_read(connection, buf + read, len - read);
|
||||
ret = net_read(connect, buf + read, len - read);
|
||||
if (ret < 0) return ret;
|
||||
|
||||
/* Read finished */
|
||||
@ -221,11 +223,78 @@ s32 download_request(const char * url, char * filename)
|
||||
char header[strlen(path) + strlen(domain) + strlen(url) + 100];
|
||||
sprintf(header, "GET %s HTTP/1.1\r\nHost: %s\r\nReferer: %s\r\nConnection: close\r\n\r\n", path, domain, url);
|
||||
|
||||
s32 filesize = network_request(header, filename);
|
||||
s32 filesize = network_request(connection, header, filename);
|
||||
|
||||
return filesize;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* HTML HEAD request
|
||||
***************************************************************************/
|
||||
char * HEAD_Request(const char * url)
|
||||
{
|
||||
if(strncmp(url, "http://", strlen("http://")) != 0)
|
||||
{
|
||||
gprintf("Not a valid URL");
|
||||
return NULL;
|
||||
}
|
||||
char *path = strchr(url + strlen("http://"), '/');
|
||||
|
||||
if(!path)
|
||||
{
|
||||
gprintf("Not a valid URL path");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int domainlength = path - url - strlen("http://");
|
||||
|
||||
if(domainlength == 0)
|
||||
{
|
||||
gprintf("Not a valid domain");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char domain[domainlength + 1];
|
||||
strncpy(domain, url + strlen("http://"), domainlength);
|
||||
domain[domainlength] = '\0';
|
||||
|
||||
connection = GetConnection(domain);
|
||||
if(connection < 0)
|
||||
{
|
||||
gprintf("Could not connect to the server.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char header[strlen(path)+strlen(domain)*2+150];
|
||||
sprintf(header, "HEAD %s HTTP/1.1\r\nHost: %s\r\nReferer: %s\r\nUser-Agent: USB Loader GX\r\nConnection: close\r\n\r\n", path, domain, domain);
|
||||
|
||||
/* Send request */
|
||||
s32 ret = net_send(connection, header, strlen(header), 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
CloseConnection();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u32 cnt = 0;
|
||||
char * buf = (char *) malloc(1024);
|
||||
memset(buf, 0, 1024);
|
||||
|
||||
for (cnt = 0; !strstr(buf, "\r\n\r\n") && cnt < 1024; cnt++)
|
||||
{
|
||||
if(net_recv(connection, buf + cnt, 1, 0) <= 0)
|
||||
{
|
||||
CloseConnection();
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CloseConnection();
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void CloseConnection()
|
||||
{
|
||||
|
||||
|
@ -14,12 +14,12 @@ bool IsNetworkInit(void);
|
||||
char * GetNetworkIP(void);
|
||||
char * GetIncommingIP(void);
|
||||
bool ShutdownWC24();
|
||||
s32 network_request(const char * request, char * filename);
|
||||
s32 network_read(u8 *buf, u32 len);
|
||||
s32 network_request(s32 connection, const char * request, char * filename);
|
||||
s32 network_read(s32 connection, u8 *buf, u32 len);
|
||||
s32 download_request(const char * url, char * filename = NULL);
|
||||
void CloseConnection();
|
||||
int CheckUpdate();
|
||||
|
||||
char * HEAD_Request(const char * url);
|
||||
void HaltNetworkThread();
|
||||
void ResumeNetworkWait();
|
||||
void ResumeNetworkThread();
|
||||
|
@ -29,10 +29,19 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ogcsys.h>
|
||||
#include <string>
|
||||
|
||||
#include "gecko.h"
|
||||
#include "ZipFile.h"
|
||||
#include "http.h"
|
||||
#include "networkops.h"
|
||||
#include "HTML_Stream.h"
|
||||
#include "FileDownloader.h"
|
||||
#include "settings/CSettings.h"
|
||||
#include "settings/GameTitles.h"
|
||||
#include "xml/WiiTDB.hpp"
|
||||
|
||||
static const char * WiiTDB_URL = "http://wiitdb.com/wiitdb.zip";
|
||||
|
||||
/****************************************************************************
|
||||
* Checking if an Update is available
|
||||
@ -76,3 +85,72 @@ int CheckForBetaUpdate()
|
||||
|
||||
return revnumber;
|
||||
}
|
||||
|
||||
static bool CheckNewWiiTDBVersion(const char *url)
|
||||
{
|
||||
u64 Version = 0;
|
||||
|
||||
char * HEAD_Responde = HEAD_Request(url);
|
||||
if(!HEAD_Responde)
|
||||
return false;
|
||||
|
||||
char * version_ptr = strstr(HEAD_Responde, "X-WiiTDB-Timestamp: ");
|
||||
if(version_ptr)
|
||||
{
|
||||
version_ptr += strlen("X-WiiTDB-Timestamp: ");
|
||||
Version = strtoull(version_ptr, NULL, 10);
|
||||
}
|
||||
|
||||
free(HEAD_Responde);
|
||||
|
||||
std::string Title;
|
||||
std::string Filepath = Settings.titlestxt_path;
|
||||
if(Settings.titlestxt_path[Filepath.size()-1] != '/')
|
||||
Filepath += '/';
|
||||
Filepath += "wiitdb.xml";
|
||||
|
||||
WiiTDB XML_DB;
|
||||
|
||||
if(!XML_DB.OpenFile((Filepath.c_str())))
|
||||
return true; //! If no file exists we need the file
|
||||
|
||||
u64 ExistingVersion = XML_DB.GetWiiTDBVersion();
|
||||
|
||||
gprintf("Existing WiiTDB Version: %llu Online WiiTDB Version: %llu\n", ExistingVersion, Version);
|
||||
|
||||
return (ExistingVersion != Version);
|
||||
}
|
||||
|
||||
int UpdateWiiTDB()
|
||||
{
|
||||
if(CheckNewWiiTDBVersion(WiiTDB_URL) == false)
|
||||
{
|
||||
gprintf("Not updating WiiTDB: Version is the same\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gprintf("Updating WiiTDB...\n");
|
||||
|
||||
string ZipPath = Settings.titlestxt_path;
|
||||
if(Settings.titlestxt_path[ZipPath.size()-1] != '/')
|
||||
ZipPath += '/';
|
||||
|
||||
ZipPath += "wiitdb.zip";
|
||||
|
||||
int filesize = DownloadFileToPath(WiiTDB_URL, ZipPath.c_str(), false);
|
||||
|
||||
if(filesize <= 0)
|
||||
return -1;
|
||||
|
||||
ZipFile zFile(ZipPath.c_str());
|
||||
|
||||
bool result = zFile.ExtractAll(Settings.titlestxt_path);
|
||||
|
||||
//! The zip file is not needed anymore so we can remove it
|
||||
remove(ZipPath.c_str());
|
||||
|
||||
//! Reload all titles because the file changed now.
|
||||
GameTitles.LoadTitlesFromWiiTDB(Settings.titlestxt_path);
|
||||
|
||||
return (result ? filesize : -1);
|
||||
}
|
||||
|
@ -1,34 +1,35 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009
|
||||
* by 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.
|
||||
*
|
||||
* update.h
|
||||
*
|
||||
* Update operations
|
||||
* for Wii-Xplorer 2009
|
||||
***************************************************************************/
|
||||
#ifndef _UPDATEOPS_H_
|
||||
#define _UPDATEOPS_H_
|
||||
|
||||
int CheckForBetaUpdate();
|
||||
|
||||
#endif
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009
|
||||
* by 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.
|
||||
*
|
||||
* update.h
|
||||
*
|
||||
* Update operations
|
||||
* for Wii-Xplorer 2009
|
||||
***************************************************************************/
|
||||
#ifndef _UPDATEOPS_H_
|
||||
#define _UPDATEOPS_H_
|
||||
|
||||
int CheckForBetaUpdate();
|
||||
int UpdateWiiTDB();
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "settings/CGameStatistics.h"
|
||||
#include "settings/GameTitles.h"
|
||||
#include "network/networkops.h"
|
||||
#include "network/update.h"
|
||||
#include "network/http.h"
|
||||
#include "prompts/PromptWindows.h"
|
||||
#include "prompts/gameinfo.h"
|
||||
@ -58,6 +59,7 @@ extern u8 reset;
|
||||
extern u8 mountMethod;
|
||||
extern struct discHdr *dvdheader;
|
||||
extern char game_partition[6];
|
||||
extern int connection;
|
||||
|
||||
/****************************************************************************
|
||||
* OnScreenNumpad
|
||||
@ -2663,60 +2665,6 @@ int ProgressDownloadWindow(int choice2)
|
||||
}
|
||||
}
|
||||
|
||||
/**Temporary redownloading 1st image because of a fucking corruption bug **/
|
||||
#if 0 // is no longer necessary, since libfat is fixed
|
||||
char URLFile[100];
|
||||
struct block file = downloadfile( URLFile );
|
||||
if ( choice2 == 2 )
|
||||
{
|
||||
while ( tries < serverCnt3d )
|
||||
{
|
||||
sprintf( URLFile, "%s%s", server3d, missingFiles[0] );
|
||||
sprintf( imgPath, "%s%s", Settings.covers_path, missingFiles[0] );
|
||||
file = downloadfile( URLFile );
|
||||
if ( !( file.size == 36864 || file.size <= 1024 || file.size <= 1174 || file.size == 7386 || file.size == 4446 || file.data == NULL ) )break;
|
||||
tries++;
|
||||
}
|
||||
|
||||
}
|
||||
if ( choice2 == 3 )
|
||||
{
|
||||
while ( tries < serverCntDisc )
|
||||
{
|
||||
sprintf( URLFile, "%s%s", serverDisc, missingFiles[0] );
|
||||
sprintf( imgPath, "%s%s", Settings.disc_path, missingFiles[0] );
|
||||
file = downloadfile( URLFile );
|
||||
if ( !( file.size == 36864 || file.size <= 1024 || file.size <= 1174 || file.size == 7386 || file.size == 4446 || file.data == NULL ) )break;
|
||||
tries++;
|
||||
}
|
||||
}
|
||||
if ( choice2 == 1 )
|
||||
{
|
||||
while ( tries < serverCnt2d )
|
||||
{
|
||||
sprintf( URLFile, "%s%s", server2d, missingFiles[0] );
|
||||
sprintf( imgPath, "%s%s", Settings.covers2d_path, missingFiles[0] );
|
||||
file = downloadfile( URLFile );
|
||||
if ( !( file.size == 36864 || file.size <= 1024 || file.size <= 1174 || file.size == 7386 || file.size == 4446 || file.data == NULL ) )break;
|
||||
tries++;
|
||||
}
|
||||
}
|
||||
if ( file.size == 36864 || file.size <= 1024 || file.size == 7386 || file.size <= 1174 || file.size == 4446 || file.data == NULL )
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( file.data != NULL )
|
||||
{
|
||||
// save png to sd card
|
||||
FILE *pfile;
|
||||
pfile = fopen( imgPath, "wb" );
|
||||
fwrite( file.data, 1, file.size, pfile );
|
||||
fclose ( pfile );
|
||||
free( file.data );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
HaltGui();
|
||||
mainWindow->Remove(&promptWindow);
|
||||
mainWindow->SetState(STATE_DEFAULT);
|
||||
@ -2886,12 +2834,6 @@ int ProgressUpdateWindow()
|
||||
}
|
||||
}
|
||||
|
||||
//make the URL to get XML based on our games
|
||||
//std::string allocates the memory and does not depend on stack
|
||||
std::string XMLurl;
|
||||
XMLurl.resize(4096);
|
||||
build_XML_URL(&XMLurl[0], XMLurl.size());
|
||||
|
||||
char dolpath[150];
|
||||
// char dolpathsuccess[150];//use coverspath as a folder for the update wad so we dont make a new folder and have to delete it
|
||||
snprintf( dolpath, sizeof( dolpath ), "%sULNR.wad", Settings.covers_path );
|
||||
@ -2937,33 +2879,7 @@ int ProgressUpdateWindow()
|
||||
titleTxt.SetTextf( "%s USB Loader GX", tr( "Updating" ) );
|
||||
msgTxt.SetPosition( 0, 100 );
|
||||
msgTxt.SetTextf( "%s", tr( "Updating WiiTDB.zip" ) );
|
||||
|
||||
char wiitdbpath[200];
|
||||
char wiitdbpathtmp[200];
|
||||
struct block file = downloadfile( XMLurl.c_str() );
|
||||
if ( file.data != NULL )
|
||||
{
|
||||
snprintf( wiitdbpath, sizeof( wiitdbpath ), "%swiitdb_%s.zip", Settings.titlestxt_path, game_partition );
|
||||
snprintf( wiitdbpathtmp, sizeof( wiitdbpathtmp ), "%swiitmp_%s.zip", Settings.titlestxt_path, game_partition );
|
||||
rename( wiitdbpath, wiitdbpathtmp );
|
||||
pfile = fopen( wiitdbpath, "wb" );
|
||||
fwrite( file.data, 1, file.size, pfile );
|
||||
fclose( pfile );
|
||||
free( file.data );
|
||||
CloseXMLDatabase();
|
||||
if ( OpenXMLDatabase( Settings.titlestxt_path, Settings.db_language, Settings.db_JPtoEN, true, Settings.titlesOverride == 1 ? true : false, true ) ) // open file, reload titles, keep in memory
|
||||
|
||||
{
|
||||
remove( wiitdbpathtmp );
|
||||
}
|
||||
else
|
||||
{
|
||||
remove( wiitdbpath );
|
||||
rename( wiitdbpathtmp, wiitdbpath );
|
||||
OpenXMLDatabase( Settings.titlestxt_path, Settings.db_language, Settings.db_JPtoEN, true, Settings.titlesOverride == 1 ? true : false, true ); // open file, reload titles, keep in memory
|
||||
}
|
||||
}
|
||||
|
||||
UpdateWiiTDB();
|
||||
msgTxt.SetTextf( "%s", tr( "Updating Language Files:" ) );
|
||||
updateLanguageFiles();
|
||||
promptWindow.Append( &progressbarEmptyImg );
|
||||
@ -3271,8 +3187,7 @@ int ProgressUpdateWindow()
|
||||
if (IsNetworkInit() && ret >= 0)
|
||||
{
|
||||
|
||||
updatemode = WindowPrompt(tr( "What do you want to update?" ), 0, "USB Loader GX", tr( "WiiTDB Files" ),
|
||||
tr( "Language File" ), tr( "Cancel" ));
|
||||
updatemode = WindowPrompt(tr( "What do you want to update?" ), 0, "USB Loader GX", tr( "WiiTDB Files" ), tr( "Language File" ), tr( "Cancel" ));
|
||||
mainWindow->SetState(STATE_DISABLED);
|
||||
promptWindow.SetState(STATE_DEFAULT);
|
||||
mainWindow->ChangeFocus(&promptWindow);
|
||||
@ -3344,7 +3259,7 @@ int ProgressUpdateWindow()
|
||||
blksize = (u32) (filesize - i);
|
||||
if (blksize > BLOCKSIZE) blksize = BLOCKSIZE;
|
||||
|
||||
ret = network_read(blockbuffer, blksize);
|
||||
ret = network_read(connection, blockbuffer, blksize);
|
||||
if (ret != (s32) blksize)
|
||||
{
|
||||
failed = -1;
|
||||
@ -3390,36 +3305,7 @@ int ProgressUpdateWindow()
|
||||
free(file.data);
|
||||
}
|
||||
msgTxt.SetTextf("%s", tr( "Updating WiiTDB.zip" ));
|
||||
char wiitdbpath[200];
|
||||
char wiitdbpathtmp[200];
|
||||
file = downloadfile(XMLurl.c_str());
|
||||
if (file.data != NULL)
|
||||
{
|
||||
CreateSubfolder(Settings.titlestxt_path);
|
||||
snprintf(wiitdbpath, sizeof(wiitdbpath), "%swiitdb_%s.zip",
|
||||
Settings.titlestxt_path, game_partition);
|
||||
snprintf(wiitdbpathtmp, sizeof(wiitdbpathtmp), "%swiitmp_%s.zip",
|
||||
Settings.titlestxt_path, game_partition);
|
||||
rename(wiitdbpath, wiitdbpathtmp);
|
||||
pfile = fopen(wiitdbpath, "wb");
|
||||
fwrite(file.data, 1, file.size, pfile);
|
||||
fclose(pfile);
|
||||
free(file.data);
|
||||
CloseXMLDatabase();
|
||||
if (OpenXMLDatabase(Settings.titlestxt_path, Settings.db_language,
|
||||
Settings.db_JPtoEN, true, Settings.titlesOverride == 1 ? true : false, true)) // open file, reload titles, keep in memory
|
||||
{
|
||||
remove(wiitdbpathtmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
remove(wiitdbpath);
|
||||
rename(wiitdbpathtmp, wiitdbpath);
|
||||
OpenXMLDatabase(Settings.titlestxt_path, Settings.db_language,
|
||||
Settings.db_JPtoEN, true, Settings.titlesOverride == 1 ? true : false,
|
||||
true); // open file, reload titles, keep in memory
|
||||
}
|
||||
}
|
||||
UpdateWiiTDB();
|
||||
msgTxt.SetTextf("%s", tr( "Updating Language Files:" ));
|
||||
updateLanguageFiles();
|
||||
}
|
||||
@ -3445,33 +3331,10 @@ int ProgressUpdateWindow()
|
||||
else if (updatemode == 2)
|
||||
{
|
||||
msgTxt.SetTextf("%s", tr( "Updating WiiTDB.zip" ));
|
||||
char wiitdbpath[200];
|
||||
char wiitdbpathtmp[200];
|
||||
struct block file = downloadfile(XMLurl.c_str());
|
||||
if (file.data != NULL)
|
||||
if(UpdateWiiTDB() < 0)
|
||||
{
|
||||
CreateSubfolder(Settings.titlestxt_path);
|
||||
snprintf(wiitdbpath, sizeof(wiitdbpath), "%swiitdb_%s.zip", Settings.titlestxt_path, game_partition);
|
||||
snprintf(wiitdbpathtmp, sizeof(wiitdbpathtmp), "%swiitmp_%s.zip", Settings.titlestxt_path,
|
||||
game_partition);
|
||||
rename(wiitdbpath, wiitdbpathtmp);
|
||||
FILE *pfile = fopen(wiitdbpath, "wb");
|
||||
fwrite(file.data, 1, file.size, pfile);
|
||||
fclose(pfile);
|
||||
free(file.data);
|
||||
CloseXMLDatabase();
|
||||
if (OpenXMLDatabase(Settings.titlestxt_path, Settings.db_language, Settings.db_JPtoEN, true,
|
||||
Settings.titlesOverride == 1 ? true : false, true)) // open file, reload titles, keep in memory
|
||||
{
|
||||
remove(wiitdbpathtmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
remove(wiitdbpath);
|
||||
rename(wiitdbpathtmp, wiitdbpath);
|
||||
OpenXMLDatabase(Settings.titlestxt_path, Settings.db_language, Settings.db_JPtoEN, true,
|
||||
Settings.titlesOverride == 1 ? true : false, true); // open file, reload titles, keep in memory
|
||||
}
|
||||
msgTxt.SetTextf("%s", tr( "WiiTDB is up to date." ));
|
||||
sleep(3);
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,8 @@
|
||||
#include <string.h>
|
||||
#include "GameTitles.h"
|
||||
#include "CSettings.h"
|
||||
#include "usbloader/GameList.h"
|
||||
#include "xml/WiiTDB.hpp"
|
||||
|
||||
CGameTitles GameTitles;
|
||||
|
||||
@ -64,3 +67,28 @@ void CGameTitles::SetDefault()
|
||||
//! Free vector memory
|
||||
std::vector<GameTitle>().swap(TitleList);
|
||||
}
|
||||
|
||||
void CGameTitles::LoadTitlesFromWiiTDB(const char * path)
|
||||
{
|
||||
this->SetDefault();
|
||||
|
||||
if(!path || !Settings.titlesOverride)
|
||||
return;
|
||||
|
||||
gameList.LoadUnfiltered();
|
||||
|
||||
std::string Title;
|
||||
std::string Filepath = path;
|
||||
if(path[strlen(path)-1] != '/')
|
||||
Filepath += '/';
|
||||
Filepath += "wiitdb.xml";
|
||||
|
||||
WiiTDB XML_DB(Filepath.c_str());
|
||||
XML_DB.SetLanguageCode(Settings.db_language);
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ class CGameTitles
|
||||
//! Overload
|
||||
const char * GetTitle(const struct discHdr *header);
|
||||
|
||||
//! Load Game Titles from WiiTDB
|
||||
void LoadTitlesFromWiiTDB(const char * path);
|
||||
//! Set default game titles
|
||||
void SetDefault();
|
||||
protected:
|
||||
|
@ -123,13 +123,7 @@ GuiSettingsMenu::GuiSettingsMenu()
|
||||
GuiSettingsMenu::~GuiSettingsMenu()
|
||||
{
|
||||
if (Settings.titlesOverride != OldTitlesOverride)
|
||||
{
|
||||
CloseXMLDatabase();
|
||||
GameTitles.SetDefault();
|
||||
if(Settings.titlesOverride)
|
||||
OpenXMLDatabase(Settings.titlestxt_path, Settings.db_language, Settings.db_JPtoEN, true, Settings.titlesOverride, true);
|
||||
}
|
||||
|
||||
GameTitles.LoadTitlesFromWiiTDB(Settings.titlestxt_path);
|
||||
}
|
||||
|
||||
void GuiSettingsMenu::SetOptionValues()
|
||||
|
@ -131,17 +131,17 @@ GameLoadSM::GameLoadSM()
|
||||
|
||||
GameLoadSM::~GameLoadSM()
|
||||
{
|
||||
// if partition has changed, Reinitialize it
|
||||
//! if partition has changed, Reinitialize it
|
||||
if (Settings.partition != OldSettingsPartition)
|
||||
{
|
||||
PartInfo pinfo = partitions.pinfo[Settings.partition];
|
||||
partitionEntry pentry = partitions.pentry[Settings.partition];
|
||||
WBFS_OpenPart(pinfo.part_fs, pinfo.index, pentry.sector, pentry.size, (char *) &game_partition);
|
||||
load_from_fs = pinfo.part_fs;
|
||||
CloseXMLDatabase();
|
||||
GameTitles.SetDefault();
|
||||
OpenXMLDatabase(Settings.titlestxt_path, Settings.db_language, Settings.db_JPtoEN, true, Settings.titlesOverride, true);
|
||||
|
||||
//! Reload the new game titles
|
||||
gameList.ReadGameList();
|
||||
GameTitles.LoadTitlesFromWiiTDB(Settings.titlestxt_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
/*** Extern variables ***/
|
||||
extern u8 shutdown;
|
||||
extern u8 reset;
|
||||
extern int connection;
|
||||
|
||||
int DownloadTheme(const char *url, const char *title)
|
||||
{
|
||||
@ -72,7 +73,7 @@ int DownloadTheme(const char *url, const char *title)
|
||||
|
||||
ShowProgress(tr( "Downloading file" ), 0, (char*) filename, done, filesize, true);
|
||||
|
||||
int ret = network_read(buffer, blocksize);
|
||||
int ret = network_read(connection, buffer, blocksize);
|
||||
if (ret < 0)
|
||||
{
|
||||
free(buffer);
|
||||
|
21
source/utils/ShowError.cpp
Normal file
21
source/utils/ShowError.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "language/gettext.h"
|
||||
#include "prompts/PromptWindows.h"
|
||||
|
||||
extern "C" void ShowError(const char * format, ...)
|
||||
{
|
||||
char *tmp=0;
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
if((vasprintf(&tmp, format, va)>=0) && tmp)
|
||||
{
|
||||
WindowPrompt(tr("Error:"), tmp, tr("OK"));
|
||||
}
|
||||
va_end(va);
|
||||
|
||||
if(tmp)
|
||||
free(tmp);
|
||||
}
|
14
source/utils/ShowError.h
Normal file
14
source/utils/ShowError.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef SHOWERROR_H_
|
||||
#define SHOWERROR_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ShowError(const char * format, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
998
source/xml/WiiTDB.cpp
Normal file
998
source/xml/WiiTDB.cpp
Normal file
@ -0,0 +1,998 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2010
|
||||
* by 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.
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include "WiiTDB.hpp"
|
||||
|
||||
#define NAME_OFFSET_DB "wiitdb_offsets.bin"
|
||||
#define MAXREADSIZE 1024*1024 // Cache size only for parsing the offsets: 1MB
|
||||
|
||||
typedef struct _ReplaceStruct
|
||||
{
|
||||
const char * orig;
|
||||
char replace;
|
||||
short size;
|
||||
} ReplaceStruct;
|
||||
|
||||
//! More replacements can be added if needed
|
||||
static const ReplaceStruct Replacements[] =
|
||||
{
|
||||
{ ">", '>', 4 },
|
||||
{ "<", '<', 4 },
|
||||
{ """, '\"', 6 },
|
||||
{ "'", '\'', 6 },
|
||||
{ "&", '&', 5 },
|
||||
{ NULL, '\0', 0 }
|
||||
};
|
||||
|
||||
WiiTDB::WiiTDB()
|
||||
: file(0), LangCode("EN"), GameNodeCache(0)
|
||||
{
|
||||
}
|
||||
|
||||
WiiTDB::WiiTDB(const char * filepath)
|
||||
: file(0), LangCode("EN"), GameNodeCache(0)
|
||||
{
|
||||
OpenFile(filepath);
|
||||
}
|
||||
|
||||
WiiTDB::~WiiTDB()
|
||||
{
|
||||
CloseFile();
|
||||
}
|
||||
|
||||
bool WiiTDB::OpenFile(const char * filepath)
|
||||
{
|
||||
if(!filepath)
|
||||
return false;
|
||||
|
||||
file = fopen(filepath, "rb");
|
||||
if(file)
|
||||
{
|
||||
int pos;
|
||||
string OffsetsPath = filepath;
|
||||
if((pos = OffsetsPath.find_last_of('/')) != (int) string::npos)
|
||||
OffsetsPath[pos] = '\0';
|
||||
else
|
||||
OffsetsPath.clear(); //! Relative path
|
||||
|
||||
LoadGameOffsets(OffsetsPath.c_str());
|
||||
}
|
||||
|
||||
return (file != NULL);
|
||||
}
|
||||
|
||||
void WiiTDB::CloseFile()
|
||||
{
|
||||
OffsetMap.clear();
|
||||
vector<GameOffsets>().swap(OffsetMap);
|
||||
|
||||
if(GameNodeCache)
|
||||
delete [] GameNodeCache;
|
||||
GameNodeCache = NULL;
|
||||
|
||||
if(file)
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
bool WiiTDB::LoadGameOffsets(const char * path)
|
||||
{
|
||||
if(!path)
|
||||
return false;
|
||||
|
||||
string OffsetDBPath = path;
|
||||
if(strlen(path) > 0 && path[strlen(path)-1] != '/')
|
||||
OffsetDBPath += '/';
|
||||
OffsetDBPath += NAME_OFFSET_DB;
|
||||
|
||||
FILE * fp = fopen(OffsetDBPath.c_str(), "rb");
|
||||
if(!fp)
|
||||
{
|
||||
bool result = ParseFile();
|
||||
if(result)
|
||||
SaveGameOffsets(OffsetDBPath.c_str());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned long long ExistingVersion = GetWiiTDBVersion();
|
||||
unsigned long long Version = 0;
|
||||
unsigned int NodeCount = 0;
|
||||
|
||||
fread(&Version, 1, sizeof(Version), fp);
|
||||
|
||||
if(ExistingVersion != Version)
|
||||
{
|
||||
fclose(fp);
|
||||
bool result = ParseFile();
|
||||
if(result)
|
||||
SaveGameOffsets(OffsetDBPath.c_str());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fread(&NodeCount, 1, sizeof(NodeCount), fp);
|
||||
|
||||
if(NodeCount == 0)
|
||||
{
|
||||
fclose(fp);
|
||||
bool result = ParseFile();
|
||||
if(result)
|
||||
SaveGameOffsets(OffsetDBPath.c_str());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
OffsetMap.resize(NodeCount);
|
||||
|
||||
if(fread(&OffsetMap[0], 1, NodeCount*sizeof(GameOffsets), fp) != NodeCount*sizeof(GameOffsets))
|
||||
{
|
||||
fclose(fp);
|
||||
bool result = ParseFile();
|
||||
if(result)
|
||||
SaveGameOffsets(OffsetDBPath.c_str());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiiTDB::SaveGameOffsets(const char * path)
|
||||
{
|
||||
if(OffsetMap.size() == 0 || !path)
|
||||
return false;
|
||||
|
||||
FILE * fp = fopen(path, "wb");
|
||||
if(!fp)
|
||||
return false;
|
||||
|
||||
unsigned long long ExistingVersion = GetWiiTDBVersion();
|
||||
unsigned int NodeCount = OffsetMap.size();
|
||||
|
||||
if(fwrite(&ExistingVersion, 1, sizeof(ExistingVersion), fp) < 0)
|
||||
{
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(fwrite(&NodeCount, 1, sizeof(NodeCount), fp) < 0)
|
||||
{
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(fwrite(&OffsetMap[0], 1, NodeCount*sizeof(GameOffsets), fp) < 0)
|
||||
{
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long long WiiTDB::GetWiiTDBVersion()
|
||||
{
|
||||
if(!file)
|
||||
return 0;
|
||||
|
||||
char TmpText[1024];
|
||||
|
||||
if(GetData(TmpText, 0, sizeof(TmpText)) < 0)
|
||||
return 0;
|
||||
|
||||
char * VersionText = GetNodeText(TmpText, "<WiiTDB version=\"", "/>");
|
||||
if(!VersionText)
|
||||
return 0;
|
||||
|
||||
return strtoull(VersionText, NULL, 10);
|
||||
}
|
||||
|
||||
size_t WiiTDB::GetData(char * data, int offset, int size)
|
||||
{
|
||||
if(!file || !data)
|
||||
return -1;
|
||||
|
||||
fseek(file, offset, SEEK_SET);
|
||||
|
||||
return fread(data, 1, size, file);
|
||||
}
|
||||
|
||||
char * WiiTDB::LoadGameNode(const char * id)
|
||||
{
|
||||
unsigned int read = 0;
|
||||
|
||||
GameOffsets * offset = this->GetGameOffset(id);
|
||||
if(!offset)
|
||||
return NULL;
|
||||
|
||||
char * data = new (std::nothrow) char[offset->nodesize+1];
|
||||
if(!data)
|
||||
return NULL;
|
||||
|
||||
if((read = GetData(data, offset->gamenode, offset->nodesize)) != offset->nodesize)
|
||||
{
|
||||
delete [] data;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data[read] = '\0';
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
char * WiiTDB::GetGameNode(const char * id)
|
||||
{
|
||||
char * data = NULL;
|
||||
|
||||
if(GameNodeCache != 0 && strncmp(id, GameIDCache, strlen(GameIDCache)) == 0)
|
||||
{
|
||||
data = new (std::nothrow) char[strlen(GameNodeCache)+1];
|
||||
if(data)
|
||||
strcpy(data, GameNodeCache);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(GameNodeCache)
|
||||
delete [] GameNodeCache;
|
||||
|
||||
GameNodeCache = LoadGameNode(id);
|
||||
|
||||
if(GameNodeCache)
|
||||
{
|
||||
snprintf(GameIDCache, sizeof(GameIDCache), id);
|
||||
data = new (std::nothrow) char[strlen(GameNodeCache)+1];
|
||||
if(data)
|
||||
strcpy(data, GameNodeCache);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
GameOffsets * WiiTDB::GetGameOffset(const char * gameID)
|
||||
{
|
||||
for(unsigned int i = 0; i < OffsetMap.size(); ++i)
|
||||
{
|
||||
if(strncmp(gameID, OffsetMap[i].gameID, strlen(OffsetMap[i].gameID)) == 0)
|
||||
return &OffsetMap[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline char * CleanText(char * in_text)
|
||||
{
|
||||
if(!in_text)
|
||||
return NULL;
|
||||
|
||||
const char * ptr = in_text;
|
||||
char * text = in_text;
|
||||
|
||||
while(*ptr != '\0')
|
||||
{
|
||||
for(int i = 0; Replacements[i].orig != 0; ++i)
|
||||
{
|
||||
if(strncmp(ptr, Replacements[i].orig, Replacements[i].size) == 0)
|
||||
{
|
||||
ptr += Replacements[i].size;
|
||||
*text = Replacements[i].replace;
|
||||
++text;
|
||||
i = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(*ptr == '\r')
|
||||
{
|
||||
++ptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
*text = *ptr;
|
||||
++ptr;
|
||||
++text;
|
||||
}
|
||||
|
||||
*text = '\0';
|
||||
|
||||
return in_text;
|
||||
}
|
||||
|
||||
char * WiiTDB::GetNodeText(char * data, const char * nodestart, const char * nodeend)
|
||||
{
|
||||
if(!data || !nodestart || !nodeend)
|
||||
return NULL;
|
||||
|
||||
char * position = strstr(data, nodestart);
|
||||
if(!position)
|
||||
return NULL;
|
||||
|
||||
position += strlen(nodestart);
|
||||
|
||||
char * end = strstr(position, nodeend);
|
||||
if(!end)
|
||||
return NULL;
|
||||
|
||||
*end = '\0';
|
||||
|
||||
return CleanText(position);
|
||||
}
|
||||
|
||||
char * WiiTDB::SeekLang(char * text, const char * langcode)
|
||||
{
|
||||
if(!text || !langcode) return NULL;
|
||||
|
||||
char * ptr = text;
|
||||
while((ptr = strstr(ptr, "<locale lang=")) != NULL)
|
||||
{
|
||||
ptr += strlen("<locale lang=\"");
|
||||
|
||||
if(strncmp(ptr, langcode, strlen(langcode)) == 0)
|
||||
{
|
||||
//! Cut off all the other languages
|
||||
char * end = strstr(ptr, "</locale>");
|
||||
if(!end)
|
||||
return NULL;
|
||||
|
||||
end += strlen("</locale>");
|
||||
*end = '\0';
|
||||
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool WiiTDB::ParseFile()
|
||||
{
|
||||
OffsetMap.clear();
|
||||
|
||||
if(!file)
|
||||
return false;
|
||||
|
||||
char * Line = new (std::nothrow) char[MAXREADSIZE+1];
|
||||
if(!Line)
|
||||
return false;
|
||||
|
||||
bool readnew = false;
|
||||
int i, currentPos = 0;
|
||||
int read = 0;
|
||||
const char * gameNode = NULL;
|
||||
const char * idNode = NULL;
|
||||
const char * gameEndNode = NULL;
|
||||
|
||||
while((read = GetData(Line, currentPos, MAXREADSIZE)) > 0)
|
||||
{
|
||||
gameNode = Line;
|
||||
readnew = false;
|
||||
|
||||
//! Ensure the null termination at the end
|
||||
Line[read] = '\0';
|
||||
|
||||
while((gameNode = strstr(gameNode, "<game name=\"")) != NULL)
|
||||
{
|
||||
idNode = strstr(gameNode, "<id>");
|
||||
gameEndNode = strstr(gameNode, "</game>");
|
||||
if(!idNode || !gameEndNode)
|
||||
{
|
||||
//! We are in the middle of the game node, reread complete node and more
|
||||
currentPos += (gameNode-Line);
|
||||
fseek(file, currentPos, SEEK_SET);
|
||||
readnew = true;
|
||||
break;
|
||||
}
|
||||
|
||||
idNode += strlen("<id>");
|
||||
gameEndNode += strlen("</game>");
|
||||
|
||||
int size = OffsetMap.size();
|
||||
OffsetMap.resize(size+1);
|
||||
|
||||
for(i = 0; i < 7 && *idNode != '<'; ++i, ++idNode)
|
||||
OffsetMap[size].gameID[i] = *idNode;
|
||||
OffsetMap[size].gameID[i] = '\0';
|
||||
OffsetMap[size].gamenode = currentPos+(gameNode-Line);
|
||||
OffsetMap[size].nodesize = (gameEndNode-gameNode);
|
||||
gameNode = gameEndNode;
|
||||
}
|
||||
|
||||
if(readnew)
|
||||
continue;
|
||||
|
||||
currentPos += read;
|
||||
}
|
||||
|
||||
delete [] Line;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiiTDB::GetTitle(const char * id, string & title)
|
||||
{
|
||||
if(!id)
|
||||
return false;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return false;
|
||||
|
||||
char * language = SeekLang(data, LangCode.c_str());
|
||||
if(!language)
|
||||
{
|
||||
language = SeekLang(data, "EN");
|
||||
if(!language)
|
||||
{
|
||||
delete [] data;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
char * the_title = GetNodeText(language, "<title>", "</title>");
|
||||
if(!the_title)
|
||||
{
|
||||
delete [] data;
|
||||
return false;
|
||||
}
|
||||
|
||||
title = the_title;
|
||||
|
||||
delete [] data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiiTDB::GetSynopsis(const char * id, string & synopsis)
|
||||
{
|
||||
if(!id)
|
||||
return false;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return false;
|
||||
|
||||
char * language = SeekLang(data, LangCode.c_str());
|
||||
if(!language)
|
||||
{
|
||||
language = SeekLang(data, "EN");
|
||||
if(!language)
|
||||
{
|
||||
delete [] data;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
char * the_synopsis = GetNodeText(language, "<synopsis>", "</synopsis>");
|
||||
if(!the_synopsis)
|
||||
{
|
||||
delete [] data;
|
||||
return false;
|
||||
}
|
||||
|
||||
synopsis = the_synopsis;
|
||||
|
||||
delete [] data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiiTDB::GetRegion(const char * id, string & region)
|
||||
{
|
||||
if(!id)
|
||||
return false;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return false;
|
||||
|
||||
char * the_region = GetNodeText(data, "<region>", "</region>");
|
||||
if(!the_region)
|
||||
{
|
||||
delete [] data;
|
||||
return false;
|
||||
}
|
||||
|
||||
region = the_region;
|
||||
|
||||
delete [] data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiiTDB::GetDeveloper(const char * id, string & dev)
|
||||
{
|
||||
if(!id)
|
||||
return false;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return false;
|
||||
|
||||
char * the_dev = GetNodeText(data, "<developer>", "</developer>");
|
||||
if(!the_dev)
|
||||
{
|
||||
delete [] data;
|
||||
return false;
|
||||
}
|
||||
|
||||
dev = the_dev;
|
||||
|
||||
delete [] data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiiTDB::GetPublisher(const char * id, string & pub)
|
||||
{
|
||||
if(!id)
|
||||
return false;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return false;
|
||||
|
||||
char * the_pub = GetNodeText(data, "<publisher>", "</publisher>");
|
||||
if(!the_pub)
|
||||
{
|
||||
delete [] data;
|
||||
return false;
|
||||
}
|
||||
|
||||
pub = the_pub;
|
||||
|
||||
delete [] data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int WiiTDB::GetPublishDate(const char * id)
|
||||
{
|
||||
if(!id)
|
||||
return 0;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return 0;
|
||||
|
||||
char * year_string = GetNodeText(data, "<date year=\"", "/>");
|
||||
if(!year_string)
|
||||
{
|
||||
delete [] data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int year, day, month;
|
||||
|
||||
year = atoi(year_string);
|
||||
|
||||
char * month_string = strstr(year_string, "month=\"");
|
||||
if(!month_string)
|
||||
{
|
||||
delete [] data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
month_string += strlen("month=\"");
|
||||
|
||||
month = atoi(month_string);
|
||||
|
||||
char * day_string = strstr(month_string, "day=\"");
|
||||
if(!day_string)
|
||||
{
|
||||
delete [] data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
day_string += strlen("day=\"");
|
||||
|
||||
day = atoi(day_string);
|
||||
|
||||
delete [] data;
|
||||
|
||||
return ((year & 0xFFFF) << 16 | (month & 0xFF) << 8 | (day & 0xFF));
|
||||
}
|
||||
|
||||
bool WiiTDB::GetGenreList(const char * id, vector<string> & genre)
|
||||
{
|
||||
if(!id)
|
||||
return false;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return false;
|
||||
|
||||
char * the_genre = GetNodeText(data, "<genre>", "</genre>");
|
||||
if(!the_genre)
|
||||
{
|
||||
delete [] data;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int genre_num = 0;
|
||||
const char * ptr = the_genre;
|
||||
|
||||
while(*ptr != '\0')
|
||||
{
|
||||
if(genre_num >= genre.size())
|
||||
genre.resize(genre_num+1);
|
||||
|
||||
if(*ptr == ',' || *ptr == '/' || *ptr == ';')
|
||||
{
|
||||
ptr++;
|
||||
while(*ptr == ' ') ptr++;
|
||||
genre[genre_num].push_back('\0');
|
||||
genre_num++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(genre[genre_num].size() == 0)
|
||||
genre[genre_num].push_back(toupper((int)*ptr));
|
||||
else
|
||||
genre[genre_num].push_back(*ptr);
|
||||
|
||||
++ptr;
|
||||
}
|
||||
genre[genre_num].push_back('\0');
|
||||
|
||||
delete [] data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char * WiiTDB::RatingToString(int rating)
|
||||
{
|
||||
switch(rating)
|
||||
{
|
||||
case 0:
|
||||
return "CERO";
|
||||
case 1:
|
||||
return "ESRB";
|
||||
case 2:
|
||||
return "PEGI";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int WiiTDB::GetRating(const char * id)
|
||||
{
|
||||
int rating = -1;
|
||||
|
||||
if(!id)
|
||||
return rating;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return rating;
|
||||
|
||||
char * rating_text = GetNodeText(data, "<rating type=\"", "/>");
|
||||
if(!rating_text)
|
||||
{
|
||||
delete [] data;
|
||||
return rating;
|
||||
}
|
||||
|
||||
if(strncmp(rating_text, "CERO", 4) == 0)
|
||||
rating = 0;
|
||||
|
||||
else if(strncmp(rating_text, "ESRB", 4) == 0)
|
||||
rating = 1;
|
||||
|
||||
else if(strncmp(rating_text, "PEGI", 4) == 0)
|
||||
rating = 2;
|
||||
|
||||
delete [] data;
|
||||
|
||||
return rating;
|
||||
}
|
||||
|
||||
bool WiiTDB::GetRatingValue(const char * id, string & rating_value)
|
||||
{
|
||||
if(!id)
|
||||
return false;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return false;
|
||||
|
||||
char * rating_text = GetNodeText(data, "<rating type=\"", "/>");
|
||||
if(!rating_text)
|
||||
{
|
||||
delete [] data;
|
||||
return false;
|
||||
}
|
||||
|
||||
char * value_text = GetNodeText(rating_text, "value=\"", "\"");
|
||||
if(!value_text)
|
||||
{
|
||||
delete [] data;
|
||||
return false;
|
||||
}
|
||||
|
||||
rating_value = value_text;
|
||||
|
||||
delete [] data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int WiiTDB::GetRatingDescriptorList(const char * id, vector<string> & desc_list)
|
||||
{
|
||||
if(!id)
|
||||
return -1;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return -1;
|
||||
|
||||
char * descriptor_text = GetNodeText(data, "<descriptor>", "</rating>");
|
||||
if(!descriptor_text)
|
||||
{
|
||||
delete [] data;
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int list_num = 0;
|
||||
desc_list.clear();
|
||||
|
||||
while(*descriptor_text != '\0')
|
||||
{
|
||||
if(strncmp(descriptor_text, "</descriptor>", strlen("</descriptor>")) == 0)
|
||||
{
|
||||
desc_list[list_num].push_back('\0');
|
||||
descriptor_text = strstr(descriptor_text, "<descriptor>");
|
||||
if(!descriptor_text)
|
||||
break;
|
||||
|
||||
descriptor_text += strlen("<descriptor>");
|
||||
list_num++;
|
||||
}
|
||||
|
||||
if(list_num >= desc_list.size())
|
||||
desc_list.resize(list_num+1);
|
||||
|
||||
desc_list[list_num].push_back(*descriptor_text);
|
||||
++descriptor_text;
|
||||
}
|
||||
|
||||
delete [] data;
|
||||
|
||||
return desc_list.size();
|
||||
}
|
||||
|
||||
int WiiTDB::GetWifiPlayers(const char * id)
|
||||
{
|
||||
int players = -1;
|
||||
|
||||
if(!id)
|
||||
return players;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return players;
|
||||
|
||||
char * PlayersNode = GetNodeText(data, "<wi-fi players=\"", "\">");
|
||||
if(!PlayersNode)
|
||||
{
|
||||
delete [] data;
|
||||
return players;
|
||||
}
|
||||
|
||||
players = atoi(PlayersNode);
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
int WiiTDB::GetWifiFeatureList(const char * id, vector<string> & feat_list)
|
||||
{
|
||||
if(!id)
|
||||
return -1;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return -1;
|
||||
|
||||
char * feature_text = GetNodeText(data, "<feature>", "</wi-fi>");
|
||||
if(!feature_text)
|
||||
{
|
||||
delete [] data;
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int list_num = 0;
|
||||
feat_list.clear();
|
||||
|
||||
while(*feature_text != '\0')
|
||||
{
|
||||
if(strncmp(feature_text, "</feature>", strlen("</feature>")) == 0)
|
||||
{
|
||||
feat_list[list_num].push_back('\0');
|
||||
feature_text = strstr(feature_text, "<feature>");
|
||||
if(!feature_text)
|
||||
break;
|
||||
|
||||
feature_text += strlen("<feature>");
|
||||
list_num++;
|
||||
}
|
||||
|
||||
if(list_num >= feat_list.size())
|
||||
feat_list.resize(list_num+1);
|
||||
|
||||
|
||||
if(feat_list[list_num].size() == 0)
|
||||
feat_list[list_num].push_back(toupper((int)*feature_text));
|
||||
else
|
||||
feat_list[list_num].push_back(*feature_text);
|
||||
|
||||
++feature_text;
|
||||
}
|
||||
|
||||
delete [] data;
|
||||
|
||||
return feat_list.size();
|
||||
}
|
||||
|
||||
int WiiTDB::GetPlayers(const char * id)
|
||||
{
|
||||
int players = -1;
|
||||
|
||||
if(!id)
|
||||
return players;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return players;
|
||||
|
||||
char * PlayersNode = GetNodeText(data, "<input players=\"", "\">");
|
||||
if(!PlayersNode)
|
||||
{
|
||||
delete [] data;
|
||||
return players;
|
||||
}
|
||||
|
||||
players = atoi(PlayersNode);
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
int WiiTDB::GetAccessoirList(const char * id, vector<Accessoir> & acc_list)
|
||||
{
|
||||
if(!id)
|
||||
return -1;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return -1;
|
||||
|
||||
char * ControlsNode = GetNodeText(data, "<control type=\"", "</input>");
|
||||
if(!ControlsNode)
|
||||
{
|
||||
delete [] data;
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int list_num = 0;
|
||||
acc_list.clear();
|
||||
|
||||
while(ControlsNode && *ControlsNode != '\0')
|
||||
{
|
||||
if(list_num >= acc_list.size())
|
||||
acc_list.resize(list_num+1);
|
||||
|
||||
for(const char * ptr = ControlsNode; *ptr != '"' && *ptr != '\0'; ptr++)
|
||||
{
|
||||
acc_list[list_num].Name.push_back(*ptr);
|
||||
}
|
||||
acc_list[list_num].Name.push_back('\0');
|
||||
|
||||
char * requiredField = strstr(ControlsNode, "required=\"");
|
||||
if(!requiredField)
|
||||
{
|
||||
delete [] data;
|
||||
return -1;
|
||||
}
|
||||
|
||||
requiredField += strlen("required=\"");
|
||||
|
||||
if(strncmp(requiredField, "true", 4) == 0)
|
||||
{
|
||||
acc_list[list_num].Required = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
acc_list[list_num].Required = false;
|
||||
}
|
||||
|
||||
ControlsNode = strstr(requiredField, "<control type=\"");
|
||||
if(ControlsNode)
|
||||
ControlsNode += strlen("<control type=\"");
|
||||
|
||||
list_num++;
|
||||
}
|
||||
|
||||
delete [] data;
|
||||
|
||||
return acc_list.size();
|
||||
}
|
||||
|
||||
int WiiTDB::GetCaseColor(const char * id)
|
||||
{
|
||||
int color = -1;
|
||||
|
||||
if(!id)
|
||||
return color;
|
||||
|
||||
char * data = GetGameNode(id);
|
||||
if(!data)
|
||||
return color;
|
||||
|
||||
char * ColorNode = GetNodeText(data, "<case color=\"", "\"/>");
|
||||
if(!ColorNode)
|
||||
{
|
||||
delete [] data;
|
||||
return color;
|
||||
}
|
||||
|
||||
color = strtoul(ColorNode, NULL, 16);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
bool WiiTDB::GetGameXMLInfo(const char * id, GameXMLInfo * gameInfo)
|
||||
{
|
||||
if(!id || !gameInfo)
|
||||
return false;
|
||||
|
||||
for(int i = 0; i < 6 && id[i] != 0; ++i)
|
||||
gameInfo->GameID.push_back(id[i]);
|
||||
gameInfo->GameID.push_back('\0');
|
||||
|
||||
GetTitle(id, gameInfo->Title);
|
||||
GetSynopsis(id, gameInfo->Synopsis);
|
||||
GetRegion(id, gameInfo->Region);
|
||||
GetDeveloper(id, gameInfo->Developer);
|
||||
GetPublisher(id, gameInfo->Publisher);
|
||||
gameInfo->PublishDate = GetPublishDate(id);
|
||||
GetGenreList(id, gameInfo->GenreList);
|
||||
gameInfo->RatingType = GetRating(id);
|
||||
GetRatingValue(id, gameInfo->RatingValue);
|
||||
GetRatingDescriptorList(id, gameInfo->RatingDescriptorList);
|
||||
gameInfo->WifiPlayers = GetWifiPlayers(id);
|
||||
GetWifiFeatureList(id, gameInfo->WifiFeatureList);
|
||||
gameInfo->Players = GetPlayers(id);
|
||||
GetAccessoirList(id, gameInfo->AccessoirList);
|
||||
gameInfo->CaseColor = GetCaseColor(id);
|
||||
|
||||
return true;
|
||||
}
|
150
source/xml/WiiTDB.hpp
Normal file
150
source/xml/WiiTDB.hpp
Normal file
@ -0,0 +1,150 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2010
|
||||
* by 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.
|
||||
***************************************************************************/
|
||||
#ifndef WIITDB_HPP_
|
||||
#define WIITDB_HPP_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef struct _Accessoir
|
||||
{
|
||||
string Name;
|
||||
bool Required;
|
||||
} Accessoir;
|
||||
|
||||
typedef struct _GameXMLInfo
|
||||
{
|
||||
string GameID;
|
||||
string Region;
|
||||
string Title;
|
||||
string Synopsis;
|
||||
string Developer;
|
||||
string Publisher;
|
||||
unsigned int PublishDate;
|
||||
vector<string> GenreList;
|
||||
int RatingType;
|
||||
string RatingValue;
|
||||
vector<string> RatingDescriptorList;
|
||||
int WifiPlayers;
|
||||
vector<string> WifiFeatureList;
|
||||
int Players;
|
||||
vector<Accessoir> AccessoirList;
|
||||
long CaseColor;
|
||||
|
||||
} GameXMLInfo;
|
||||
|
||||
typedef struct _GameOffsets
|
||||
{
|
||||
char gameID[7];
|
||||
unsigned int gamenode;
|
||||
unsigned int nodesize;
|
||||
} __attribute__((__packed__)) GameOffsets;
|
||||
|
||||
class WiiTDB
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
WiiTDB();
|
||||
//! Constructor
|
||||
//! If filepath is passed the xml file is opened and the node offsets are loaded
|
||||
WiiTDB(const char * filepath);
|
||||
//! Destructor
|
||||
~WiiTDB();
|
||||
//! If filepath is passed the xml file is opened and the node offsets are loaded
|
||||
bool OpenFile(const char * filepath);
|
||||
//! Closes the WiiTDB xml file
|
||||
void CloseFile();
|
||||
//! Set the language code which should be use to find the appropriate language
|
||||
//! If the language code is not found, the language code defaults to EN
|
||||
void SetLanguageCode(const char * code) { if(code) LangCode = code; };
|
||||
//! Get the current set language code
|
||||
const char * GetLanguageCode() { return LangCode.c_str(); };
|
||||
//! Get the title of a specific game id in the language defined in LangCode
|
||||
bool GetTitle(const char * id, string & title);
|
||||
//! Get the synopsis of a specific game id in the language defined in LangCode
|
||||
bool GetSynopsis(const char * id, string & synopsis);
|
||||
//! Get the region of a game for a specific game id
|
||||
bool GetRegion(const char * id, string & region);
|
||||
//! Get the developer of a game for a specific game id
|
||||
bool GetDeveloper(const char * id, string & dev);
|
||||
//! Get the publisher of a game for a specific game id
|
||||
bool GetPublisher(const char * id, string & pub);
|
||||
//! Get the publish date of a game for a specific game id
|
||||
//! First 1 byte is the day, than 1 byte month and last 2 bytes is the year
|
||||
//! year = (return >> 16), month = (return >> 8) & 0xFF, day = return & 0xFF
|
||||
unsigned int GetPublishDate(const char * id);
|
||||
//! Get the genre list of a game for a specific game id
|
||||
bool GetGenreList(const char * id, vector<string> & genre);
|
||||
//! Get the rating type for a specific game id
|
||||
//! The rating type can be converted to a string with WiiTDB::RatingToString(rating)
|
||||
int GetRating(const char * id);
|
||||
//! Get the rating value for a specific game id
|
||||
bool GetRatingValue(const char * id, string & rating_value);
|
||||
//! Get the rating descriptor list inside a vector for a specific game id
|
||||
//! Returns the amount of descriptors found or -1 if failed
|
||||
int GetRatingDescriptorList(const char * id, vector<string> & desc_list);
|
||||
//! Get the wifi player count for a specific game id
|
||||
//! Returns the amount of wifi players or -1 if failed
|
||||
int GetWifiPlayers(const char * id);
|
||||
//! Get the wifi feature list inside a vector for a specific game id
|
||||
//! Returns the amount of wifi features found or -1 if failed
|
||||
int GetWifiFeatureList(const char * id, vector<string> & feat_list);
|
||||
//! Get the player count for a specific game id
|
||||
//! Returns the amount of players or -1 if failed
|
||||
int GetPlayers(const char * id);
|
||||
//! Returns the amount of accessoirs found or -1 if failed
|
||||
//! Get the accessoir (inputs) list inside a vector for a specific game id
|
||||
int GetAccessoirList(const char * id, vector<Accessoir> & acc_list);
|
||||
//! Get the box (case) color for a specific game id
|
||||
//! Returns the color in RGB (first 3 bytes)
|
||||
int GetCaseColor(const char * id);
|
||||
//! Get the complete game info in the GameXMLInfo struct
|
||||
bool GetGameXMLInfo(const char * id, GameXMLInfo * gameInfo);
|
||||
//! Convert a specific game rating to a string
|
||||
static const char * RatingToString(int rating);
|
||||
//! Get the version of the wiitdb xml database
|
||||
unsigned long long GetWiiTDBVersion();
|
||||
//! Get the entry count in the xml database
|
||||
inline size_t GetEntryCount() { return OffsetMap.size(); };
|
||||
private:
|
||||
bool ParseFile();
|
||||
bool LoadGameOffsets(const char * path);
|
||||
bool SaveGameOffsets(const char * path);
|
||||
inline size_t GetData(char * data, int offset, int size);
|
||||
inline char * LoadGameNode(const char * id);
|
||||
inline char * GetGameNode(const char * id);
|
||||
inline GameOffsets * GetGameOffset(const char * id);
|
||||
inline char * SeekLang(char * text, const char * langcode);
|
||||
inline char * GetNodeText(char * data, const char * nodestart, const char * nodeend);
|
||||
|
||||
vector<GameOffsets> OffsetMap;
|
||||
FILE * file;
|
||||
string LangCode;
|
||||
char * GameNodeCache;
|
||||
char GameIDCache[7];
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user