* Added a visual mark for new installed games. The first time this revision is started no games will be marked!

* Added a configuration setting to turn this feature off (there you go, pune)
* Changed svnrev.sh, to also update the release date of the meta.xml file, and to set the revision to current + 1
This commit is contained in:
e.bovendeur 2009-11-21 22:59:57 +00:00
parent 31717f020b
commit 68aeb7aafd
14 changed files with 256 additions and 5 deletions

View File

@ -2,8 +2,8 @@
<app version="1"> <app version="1">
<name> USB Loader GX</name> <name> USB Loader GX</name>
<coder>USB Loader GX Team</coder> <coder>USB Loader GX Team</coder>
<version>1.0 r837</version> <version>1.0 r839</version>
<release_date>200910150000</release_date> <release_date>200911212355</release_date>
<short_description>Loads games from USB-devices</short_description> <short_description>Loads games from USB-devices</short_description>
<long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times. <long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times.
The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller. The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller.

View File

@ -537,4 +537,7 @@ extern const u32 usbport_png_size;
extern const u8 dvd_png[]; extern const u8 dvd_png[];
extern const u32 dvd_png_size; extern const u32 dvd_png_size;
extern const u8 new_png[];
extern const u32 new_png_size;
#endif #endif

BIN
source/images/new.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

View File

@ -45,10 +45,13 @@ GuiGameBrowser::GuiGameBrowser(int w, int h, struct discHdr * l, int gameCnt, co
snprintf(imgPath, sizeof(imgPath), "%sbg_options.png", themePath); snprintf(imgPath, sizeof(imgPath), "%sbg_options.png", themePath);
bgGames = new GuiImageData(imgPath, imagebg); bgGames = new GuiImageData(imgPath, imagebg);
snprintf(imgPath, sizeof(imgPath), "%snew.png", themePath);
newGames = new GuiImageData(imgPath, new_png);
bgGameImg = new GuiImage(bgGames); bgGameImg = new GuiImage(bgGames);
bgGameImg->SetParent(this); bgGameImg->SetParent(this);
bgGameImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); bgGameImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
maxTextWidth = bgGameImg->GetWidth() - 24 - 4; maxTextWidth = bgGameImg->GetWidth() - 24 - 4;
snprintf(imgPath, sizeof(imgPath), "%sbg_options_entry.png", themePath); snprintf(imgPath, sizeof(imgPath), "%sbg_options_entry.png", themePath);
@ -121,6 +124,7 @@ GuiGameBrowser::GuiGameBrowser(int w, int h, struct discHdr * l, int gameCnt, co
gameTxt = new GuiText * [pagesize]; gameTxt = new GuiText * [pagesize];
gameTxtOver = new GuiText * [pagesize]; gameTxtOver = new GuiText * [pagesize];
gameBg = new GuiImage * [pagesize]; gameBg = new GuiImage * [pagesize];
newImg = new GuiImage * [pagesize];
for(int i=0; i < pagesize; i++) for(int i=0; i < pagesize; i++)
{ {
@ -137,10 +141,15 @@ GuiGameBrowser::GuiGameBrowser(int w, int h, struct discHdr * l, int gameCnt, co
gameBg[i] = new GuiImage(bgGamesEntry); gameBg[i] = new GuiImage(bgGamesEntry);
newImg[i] = new GuiImage(newGames);
newImg[i]->SetAlignment(ALIGN_RIGHT, ALIGN_MIDDLE);
newImg[i]->SetVisible(false);
game[i] = new GuiButton(width-28,GAMESELECTSIZE); game[i] = new GuiButton(width-28,GAMESELECTSIZE);
game[i]->SetParent(this); game[i]->SetParent(this);
game[i]->SetLabel(gameTxt[i]); game[i]->SetLabel(gameTxt[i]);
game[i]->SetLabelOver(gameTxtOver[i]); game[i]->SetLabelOver(gameTxtOver[i]);
game[i]->SetIcon(newImg[i]);
game[i]->SetImageOver(gameBg[i]); game[i]->SetImageOver(gameBg[i]);
game[i]->SetPosition(5,GAMESELECTSIZE*i+4); game[i]->SetPosition(5,GAMESELECTSIZE*i+4);
game[i]->SetRumble(false); game[i]->SetRumble(false);
@ -177,6 +186,7 @@ GuiGameBrowser::~GuiGameBrowser()
delete bgGameImg; delete bgGameImg;
delete bgGames; delete bgGames;
delete bgGamesEntry; delete bgGamesEntry;
delete newGames;
delete trigA; delete trigA;
delete trigHeldA; delete trigHeldA;
@ -188,6 +198,7 @@ GuiGameBrowser::~GuiGameBrowser()
delete gameTxtOver[i]; delete gameTxtOver[i];
delete gameBg[i]; delete gameBg[i];
delete game[i]; delete game[i];
delete newImg[i];
} }
delete [] gameIndex; delete [] gameIndex;
delete [] game; delete [] game;
@ -329,6 +340,17 @@ void GuiGameBrowser::UpdateListEntries()
gameTxtOver[i]->SetText(get_title(&gameList[next])); gameTxtOver[i]->SetText(get_title(&gameList[next]));
gameTxtOver[i]->SetPosition(24, 0); gameTxtOver[i]->SetPosition(24, 0);
if (Settings.marknewtitles) {
if (gameList[next].isNew) {
gameTxt[i]->SetMaxWidth(maxTextWidth - (newGames->GetWidth() + 1), GuiText::DOTTED);
gameTxtOver[i]->SetMaxWidth(maxTextWidth - (newGames->GetWidth() + 1), GuiText::SCROLL);
} else {
gameTxt[i]->SetMaxWidth(maxTextWidth, GuiText::DOTTED);
gameTxtOver[i]->SetMaxWidth(maxTextWidth, GuiText::SCROLL);
}
newImg[i]->SetVisible(gameList[next].isNew != 0);
}
gameIndex[i] = next; gameIndex[i] = next;
next = this->FindMenuItem(next, 1); next = this->FindMenuItem(next, 1);
} }

View File

@ -35,6 +35,7 @@ class GuiGameBrowser : public GuiElement
GuiText ** gameTxt; GuiText ** gameTxt;
GuiText ** gameTxtOver; GuiText ** gameTxtOver;
GuiImage ** gameBg; GuiImage ** gameBg;
GuiImage ** newImg;
GuiButton * arrowUpBtn; GuiButton * arrowUpBtn;
GuiButton * arrowDownBtn; GuiButton * arrowDownBtn;
@ -51,6 +52,7 @@ class GuiGameBrowser : public GuiElement
GuiImageData * bgGames; GuiImageData * bgGames;
GuiImageData * bgGamesEntry; GuiImageData * bgGamesEntry;
GuiImageData * newGames;
GuiImageData * scrollbar; GuiImageData * scrollbar;
GuiImageData * arrowDown; GuiImageData * arrowDown;
GuiImageData * arrowDownOver; GuiImageData * arrowDownOver;

View File

@ -28,6 +28,7 @@
#include "menu.h" #include "menu.h"
#include "sys.h" #include "sys.h"
#include "wpad.h" #include "wpad.h"
#include "settings/newtitles.h"
/*** Variables that are also used extern ***/ /*** Variables that are also used extern ***/
GuiWindow * mainWindow = NULL; GuiWindow * mainWindow = NULL;
@ -323,6 +324,7 @@ int MainMenu(int menu) {
gprintf("\nExiting main GUI"); gprintf("\nExiting main GUI");
CloseXMLDatabase(); CloseXMLDatabase();
NewTitles::DestroyInstance();
ExitGUIThreads(); ExitGUIThreads();
bgMusic->Stop(); bgMusic->Stop();
delete bgMusic; delete bgMusic;

View File

@ -853,6 +853,14 @@ int MenuSettings()
static const char *opts[settings_screensaver_max] = {trNOOP("OFF"),trNOOP("3 min"),trNOOP("5 min"),trNOOP("10 min"),trNOOP("20 min"),trNOOP("30 min"),trNOOP("1 hour")}; static const char *opts[settings_screensaver_max] = {trNOOP("OFF"),trNOOP("3 min"),trNOOP("5 min"),trNOOP("10 min"),trNOOP("20 min"),trNOOP("30 min"),trNOOP("1 hour")};
options2.SetValue(Idx,"%s",tr(opts[Settings.screensaver])); options2.SetValue(Idx,"%s",tr(opts[Settings.screensaver]));
} }
if(ret == ++Idx || firstRun)
{
if(firstRun) options2.SetName(Idx, "%s",tr("Mark new games"));
if(ret == Idx && ++Settings.marknewtitles >= settings_off_on_max)
Settings.marknewtitles = 0;
options2.SetValue(Idx,"%s",tr(opts_off_on[Settings.marknewtitles]));
}
firstRun = false; firstRun = false;
} }

View File

@ -355,6 +355,7 @@ void Global_Default(void) {
Settings.db_JPtoEN = 0; Settings.db_JPtoEN = 0;
Settings.screensaver = 3; Settings.screensaver = 3;
Settings.partition = -1; Settings.partition = -1;
Settings.marknewtitles = 1;
} }
@ -1043,6 +1044,12 @@ void global_cfg_set(char *name, char *val) {
Settings.partition = i; Settings.partition = i;
} }
return; return;
} else if (strcmp(name, "marknewtitles") == 0) {
int i;
if (sscanf(val, "%d", &i) == 1) {
Settings.marknewtitles = i;
}
return;
} }
cfg_bool("godmode", &Settings.godmode); cfg_bool("godmode", &Settings.godmode);
@ -1287,6 +1294,7 @@ bool cfg_save_global() { // save global settings
fprintf(f, "autonetwork = %d\n ", Settings.autonetwork); fprintf(f, "autonetwork = %d\n ", Settings.autonetwork);
fprintf(f, "discart = %d\n ", Settings.discart); fprintf(f, "discart = %d\n ", Settings.discart);
fprintf(f, "partition = %d\n", Settings.partition); fprintf(f, "partition = %d\n", Settings.partition);
fprintf(f, "marknewtitles = %d\n", Settings.marknewtitles);
fclose(f); fclose(f);
return true; return true;
} }

View File

@ -421,6 +421,7 @@ extern "C" {
u8 autonetwork; u8 autonetwork;
u8 discart; u8 discart;
short gamesound; short gamesound;
u8 marknewtitles;
}; };
extern struct SSettings Settings; extern struct SSettings Settings;

View File

@ -0,0 +1,156 @@
#include <stdio.h>
#include <string.h>
#include "cfg.h"
#include "newtitles.h"
#define NEW_SECONDS 24 * 60 * 60
#define GAMETITLES "gametitles.txt"
NewTitles *NewTitles::instance = NULL;
NewTitles* NewTitles::Instance()
{
if (instance == NULL) {
instance = new NewTitles();
}
return instance;
}
void NewTitles::DestroyInstance()
{
if (instance != NULL)
{
delete instance;
instance = NULL;
}
}
NewTitles::NewTitles()
{
firstTitle = lastTitle = NULL;
isDirty = isNewFile = false;
// Read the text file
char path[255];
strcpy(path, Settings.titlestxt_path);
path[strlen(Settings.titlestxt_path) - 1] = '/';
strcat(path, GAMETITLES);
char line[20];
FILE *fp = fopen(path, "r");
if (fp != NULL) {
while (fgets(line, sizeof(line), fp)) {
// This is one line
if (line[0] != '#' || line[0] != ';') {
Title *title = new Title();
if (sscanf(line, "%6c:%ld", (u8 *) &title->titleId, &title->timestamp) == 2) {
if (firstTitle == NULL) {
firstTitle = title;
lastTitle = title;
} else {
lastTitle->next = title;
lastTitle = title;
}
}
else {
delete title; // Invalid title entry, ignore
}
}
}
fclose(fp);
} else {
isNewFile = true;
}
}
NewTitles::~NewTitles()
{
Save();
Title *t = firstTitle;
while (t != NULL) {
Title *temp = (Title *) t->next;
delete t;
t = temp;
}
firstTitle = lastTitle = NULL;
}
bool NewTitles::IsNew(u8 *titleid)
{
Title *t = firstTitle;
while (t != NULL) {
// Loop all titles, search for the correct titleid
if (strcmp((const char *) titleid, (const char *) t->titleId) == 0) {
// This title is less than 24 hours old
if ((time(NULL) - t->timestamp) < NEW_SECONDS) {
// Only count the game as new when it's never been played through GX
return CFG_get_game_num(titleid)->count == 0;
}
return false;
}
t = (Title *) t->next;
}
// Not found, add it
t = new Title();
strncpy((char *) t->titleId, (char *) titleid, 6);
t->timestamp = time(NULL);
if (isNewFile) {
t->timestamp -= (NEW_SECONDS + 1); // Mark all games as not new if this is a new file
}
if (firstTitle == NULL) {
firstTitle = t;
lastTitle = t;
} else {
lastTitle -> next = t;
lastTitle = t;
}
isDirty = true;
return !isNewFile; // If this is a new file, return false
}
void NewTitles::Remove(u8 *titleid)
{
Title *t = firstTitle, *prev = NULL;
while (t != NULL) {
if (strcmp((const char *) titleid, (const char *) t->titleId) == 0) {
if (prev == NULL) {
firstTitle = (Title *) t->next;
} else {
prev->next = t->next;
}
delete t;
isDirty = true;
return;
}
prev = t;
t = (Title *) t->next;
}
}
void NewTitles::Save()
{
if (!isDirty) return;
char path[255];
strcpy(path, Settings.titlestxt_path);
path[strlen(Settings.titlestxt_path) - 1] = '/';
strcat(path, GAMETITLES);
FILE *fp = fopen(path, "w");
if (fp != NULL) {
Title *t = firstTitle;
while (t != NULL) {
fprintf(fp, "%s:%ld\n", t->titleId, t->timestamp);
t = (Title *) t->next;
}
fclose(fp);
}
}

View File

@ -0,0 +1,34 @@
#ifndef _NEWTITLES_H
#define _NEWTITLES_H
#include <time.h>
class NewTitles
{
public:
static NewTitles *Instance();
static void DestroyInstance();
void Save();
bool IsNew(u8 *titleid);
void Remove(u8 *titleid);
private:
NewTitles();
~NewTitles();
static NewTitles *instance;
class Title {
public:
u8 titleId[6];
time_t timestamp;
void *next;
};
Title *firstTitle;
Title *lastTitle;
bool isDirty;
bool isNewFile;
};
#endif //_NEWTITLES_H

View File

@ -19,7 +19,8 @@ extern "C" {
u8 bufsize; u8 bufsize;
/* Padding */ /* Padding */
u8 unused1[14]; u8 isNew; // Use space from the padding below
u8 unused1[13];
/* Magic word */ /* Magic word */
u32 magic; u32 magic;

View File

@ -5,6 +5,7 @@
#include "main.h" #include "main.h"
#include <wctype.h> #include <wctype.h>
#include "getentries.h" #include "getentries.h"
#include "settings/newtitles.h"
#include "../prompts/TitleBrowser.h" #include "../prompts/TitleBrowser.h"
@ -162,6 +163,9 @@ int __Menu_GetPrevFilter(int t, wchar_t* gameFilter, u32 gameFiltered, wchar_t *
{ {
struct discHdr *header = &buffer[i]; struct discHdr *header = &buffer[i];
/* Is new? */
header->isNew = NewTitles::Instance()->IsNew(header->id);
/* Filter Favorite */ /* Filter Favorite */
if (Settings.fave && t==0) if (Settings.fave && t==0)
{ {
@ -177,6 +181,8 @@ int __Menu_GetPrevFilter(int t, wchar_t* gameFilter, u32 gameFiltered, wchar_t *
wchar_t *wname = FreeTypeGX::charToWideChar(get_title(header)); wchar_t *wname = FreeTypeGX::charToWideChar(get_title(header));
if(wname) nameList.push_back(wname); if(wname) nameList.push_back(wname);
} }
NewTitles::Instance()->Save();
/* delete buffer */ /* delete buffer */
if(buffer) free(buffer); if(buffer) free(buffer);
@ -473,6 +479,9 @@ int __Menu_GetGameList(int t, wchar_t* gameFilter, discHdr ** PgameList, u32 *Pg
for (u32 i = 0; i < cnt; i++) { for (u32 i = 0; i < cnt; i++) {
struct discHdr *header = &buffer[i]; struct discHdr *header = &buffer[i];
/* Is new? */
header->isNew = NewTitles::Instance()->IsNew(header->id);
/* Filters */ /* Filters */
if (Settings.fave && t==0) { if (Settings.fave && t==0) {
struct Game_NUM* game_num = CFG_get_game_num(header->id); struct Game_NUM* game_num = CFG_get_game_num(header->id);
@ -497,6 +506,8 @@ int __Menu_GetGameList(int t, wchar_t* gameFilter, discHdr ** PgameList, u32 *Pg
buffer[cnt2] = buffer[i]; buffer[cnt2] = buffer[i];
cnt2++; cnt2++;
} }
NewTitles::Instance()->Save();
if(cnt > cnt2) if(cnt > cnt2)
{ {
cnt = cnt2; cnt = cnt2;

View File

@ -34,6 +34,9 @@ EOF
echo "svnrev.c created" >&2 echo "svnrev.c created" >&2
fi fi
echo >&2 echo >&2
rev_new=`expr $rev_new + 1`
rev_date=`date +%Y%m%d%k%M`
cat <<EOF > ./HBC/META.XML cat <<EOF > ./HBC/META.XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@ -41,7 +44,7 @@ EOF
<name> USB Loader GX</name> <name> USB Loader GX</name>
<coder>USB Loader GX Team</coder> <coder>USB Loader GX Team</coder>
<version>1.0 r$rev_new</version> <version>1.0 r$rev_new</version>
<release_date>200910150000</release_date> <release_date>$rev_date</release_date>
<short_description>Loads games from USB-devices</short_description> <short_description>Loads games from USB-devices</short_description>
<long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times. <long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times.
The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller. The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller.