mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-18 01:09:16 +01:00
* 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:
parent
31717f020b
commit
68aeb7aafd
@ -2,8 +2,8 @@
|
||||
<app version="1">
|
||||
<name> USB Loader GX</name>
|
||||
<coder>USB Loader GX Team</coder>
|
||||
<version>1.0 r837</version>
|
||||
<release_date>200910150000</release_date>
|
||||
<version>1.0 r839</version>
|
||||
<release_date>200911212355</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.
|
||||
|
@ -537,4 +537,7 @@ extern const u32 usbport_png_size;
|
||||
extern const u8 dvd_png[];
|
||||
extern const u32 dvd_png_size;
|
||||
|
||||
extern const u8 new_png[];
|
||||
extern const u32 new_png_size;
|
||||
|
||||
#endif
|
||||
|
BIN
source/images/new.png
Normal file
BIN
source/images/new.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 522 B |
@ -45,6 +45,9 @@ GuiGameBrowser::GuiGameBrowser(int w, int h, struct discHdr * l, int gameCnt, co
|
||||
snprintf(imgPath, sizeof(imgPath), "%sbg_options.png", themePath);
|
||||
bgGames = new GuiImageData(imgPath, imagebg);
|
||||
|
||||
snprintf(imgPath, sizeof(imgPath), "%snew.png", themePath);
|
||||
newGames = new GuiImageData(imgPath, new_png);
|
||||
|
||||
bgGameImg = new GuiImage(bgGames);
|
||||
bgGameImg->SetParent(this);
|
||||
bgGameImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
|
||||
@ -121,6 +124,7 @@ GuiGameBrowser::GuiGameBrowser(int w, int h, struct discHdr * l, int gameCnt, co
|
||||
gameTxt = new GuiText * [pagesize];
|
||||
gameTxtOver = new GuiText * [pagesize];
|
||||
gameBg = new GuiImage * [pagesize];
|
||||
newImg = new GuiImage * [pagesize];
|
||||
|
||||
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);
|
||||
|
||||
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]->SetParent(this);
|
||||
game[i]->SetLabel(gameTxt[i]);
|
||||
game[i]->SetLabelOver(gameTxtOver[i]);
|
||||
game[i]->SetIcon(newImg[i]);
|
||||
game[i]->SetImageOver(gameBg[i]);
|
||||
game[i]->SetPosition(5,GAMESELECTSIZE*i+4);
|
||||
game[i]->SetRumble(false);
|
||||
@ -177,6 +186,7 @@ GuiGameBrowser::~GuiGameBrowser()
|
||||
delete bgGameImg;
|
||||
delete bgGames;
|
||||
delete bgGamesEntry;
|
||||
delete newGames;
|
||||
|
||||
delete trigA;
|
||||
delete trigHeldA;
|
||||
@ -188,6 +198,7 @@ GuiGameBrowser::~GuiGameBrowser()
|
||||
delete gameTxtOver[i];
|
||||
delete gameBg[i];
|
||||
delete game[i];
|
||||
delete newImg[i];
|
||||
}
|
||||
delete [] gameIndex;
|
||||
delete [] game;
|
||||
@ -329,6 +340,17 @@ void GuiGameBrowser::UpdateListEntries()
|
||||
gameTxtOver[i]->SetText(get_title(&gameList[next]));
|
||||
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;
|
||||
next = this->FindMenuItem(next, 1);
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ class GuiGameBrowser : public GuiElement
|
||||
GuiText ** gameTxt;
|
||||
GuiText ** gameTxtOver;
|
||||
GuiImage ** gameBg;
|
||||
GuiImage ** newImg;
|
||||
|
||||
GuiButton * arrowUpBtn;
|
||||
GuiButton * arrowDownBtn;
|
||||
@ -51,6 +52,7 @@ class GuiGameBrowser : public GuiElement
|
||||
|
||||
GuiImageData * bgGames;
|
||||
GuiImageData * bgGamesEntry;
|
||||
GuiImageData * newGames;
|
||||
GuiImageData * scrollbar;
|
||||
GuiImageData * arrowDown;
|
||||
GuiImageData * arrowDownOver;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "menu.h"
|
||||
#include "sys.h"
|
||||
#include "wpad.h"
|
||||
#include "settings/newtitles.h"
|
||||
|
||||
/*** Variables that are also used extern ***/
|
||||
GuiWindow * mainWindow = NULL;
|
||||
@ -323,6 +324,7 @@ int MainMenu(int menu) {
|
||||
gprintf("\nExiting main GUI");
|
||||
|
||||
CloseXMLDatabase();
|
||||
NewTitles::DestroyInstance();
|
||||
ExitGUIThreads();
|
||||
bgMusic->Stop();
|
||||
delete bgMusic;
|
||||
|
@ -854,6 +854,14 @@ int MenuSettings()
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -355,6 +355,7 @@ void Global_Default(void) {
|
||||
Settings.db_JPtoEN = 0;
|
||||
Settings.screensaver = 3;
|
||||
Settings.partition = -1;
|
||||
Settings.marknewtitles = 1;
|
||||
}
|
||||
|
||||
|
||||
@ -1043,6 +1044,12 @@ void global_cfg_set(char *name, char *val) {
|
||||
Settings.partition = i;
|
||||
}
|
||||
return;
|
||||
} else if (strcmp(name, "marknewtitles") == 0) {
|
||||
int i;
|
||||
if (sscanf(val, "%d", &i) == 1) {
|
||||
Settings.marknewtitles = i;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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, "discart = %d\n ", Settings.discart);
|
||||
fprintf(f, "partition = %d\n", Settings.partition);
|
||||
fprintf(f, "marknewtitles = %d\n", Settings.marknewtitles);
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
@ -421,6 +421,7 @@ extern "C" {
|
||||
u8 autonetwork;
|
||||
u8 discart;
|
||||
short gamesound;
|
||||
u8 marknewtitles;
|
||||
};
|
||||
extern struct SSettings Settings;
|
||||
|
||||
|
156
source/settings/newtitles.cpp
Normal file
156
source/settings/newtitles.cpp
Normal 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);
|
||||
}
|
||||
}
|
34
source/settings/newtitles.h
Normal file
34
source/settings/newtitles.h
Normal 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
|
@ -19,7 +19,8 @@ extern "C" {
|
||||
u8 bufsize;
|
||||
|
||||
/* Padding */
|
||||
u8 unused1[14];
|
||||
u8 isNew; // Use space from the padding below
|
||||
u8 unused1[13];
|
||||
|
||||
/* Magic word */
|
||||
u32 magic;
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "main.h"
|
||||
#include <wctype.h>
|
||||
#include "getentries.h"
|
||||
#include "settings/newtitles.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];
|
||||
|
||||
/* Is new? */
|
||||
header->isNew = NewTitles::Instance()->IsNew(header->id);
|
||||
|
||||
/* Filter Favorite */
|
||||
if (Settings.fave && t==0)
|
||||
{
|
||||
@ -178,6 +182,8 @@ int __Menu_GetPrevFilter(int t, wchar_t* gameFilter, u32 gameFiltered, wchar_t *
|
||||
if(wname) nameList.push_back(wname);
|
||||
}
|
||||
|
||||
NewTitles::Instance()->Save();
|
||||
|
||||
/* delete 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++) {
|
||||
struct discHdr *header = &buffer[i];
|
||||
|
||||
/* Is new? */
|
||||
header->isNew = NewTitles::Instance()->IsNew(header->id);
|
||||
|
||||
/* Filters */
|
||||
if (Settings.fave && t==0) {
|
||||
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];
|
||||
cnt2++;
|
||||
}
|
||||
NewTitles::Instance()->Save();
|
||||
|
||||
if(cnt > cnt2)
|
||||
{
|
||||
cnt = cnt2;
|
||||
|
@ -35,13 +35,16 @@ EOF
|
||||
fi
|
||||
echo >&2
|
||||
|
||||
rev_new=`expr $rev_new + 1`
|
||||
rev_date=`date +%Y%m%d%k%M`
|
||||
|
||||
cat <<EOF > ./HBC/META.XML
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<app version="1">
|
||||
<name> USB Loader GX</name>
|
||||
<coder>USB Loader GX Team</coder>
|
||||
<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>
|
||||
<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.
|
||||
|
Loading…
Reference in New Issue
Block a user