Added extra caching options

Thanks to Oddx & geoGolem
This commit is contained in:
wiidev 2020-12-12 21:33:31 +00:00
parent 0114bc2da4
commit c6d2efd765
35 changed files with 1473 additions and 720 deletions

View File

@ -1101,6 +1101,9 @@ msgstr ""
msgid "GameCube Install Menu"
msgstr ""
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "ID hry"
@ -1824,6 +1827,9 @@ msgstr ""
msgid "Reset BG Music"
msgstr "Obnovit hudbu na pozadí"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Vynulovat cítac spuštení"
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Odinstalace"

View File

@ -1101,6 +1101,9 @@ msgstr ""
msgid "GameCube Install Menu"
msgstr ""
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "Spil-ID"
@ -1824,6 +1827,9 @@ msgstr "Nulstil"
msgid "Reset BG Music"
msgstr "Nulstil BG-musik"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Nulstil spiltæller"
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Afinstaller"

View File

@ -1101,6 +1101,9 @@ msgstr "GameCube Spel Verwijderen"
msgid "GameCube Install Menu"
msgstr "GameCube Installatie Menu"
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "Spel ID"
@ -1824,6 +1827,9 @@ msgstr "Resetten"
msgid "Reset BG Music"
msgstr "Reset achtergrond muziek"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Speeltellers resetten"
@ -2253,6 +2259,9 @@ msgstr "USBLoaderGX kon Nintendont config bestand niet schrijven. Nintendont toc
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Verwijderen"

View File

@ -1101,6 +1101,9 @@ msgstr ""
msgid "GameCube Install Menu"
msgstr ""
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr ""
@ -1824,6 +1827,9 @@ msgstr ""
msgid "Reset BG Music"
msgstr ""
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr ""
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr ""

View File

@ -1101,6 +1101,9 @@ msgstr ""
msgid "GameCube Install Menu"
msgstr ""
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "Peli ID"
@ -1824,6 +1827,9 @@ msgstr ""
msgid "Reset BG Music"
msgstr ""
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Resetoi pelauksen määrä"
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Poista"

View File

@ -1101,6 +1101,9 @@ msgstr "Menu de suppression GameCube"
msgid "GameCube Install Menu"
msgstr "Menu d'installation GameCube"
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "ID du jeu"
@ -1824,6 +1827,9 @@ msgstr "Réinitialisation"
msgid "Reset BG Music"
msgstr "Fond sonore par defaut"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Remise à zéro du compteur d'utilisations"
@ -2253,6 +2259,9 @@ msgstr "USBLoaderGX n'a pas pu créer le fichier de configuration de Nintendont.
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr "Nintendont Alpha v0.1 ne fonctionne qu'avec USBLoaderGX r1218. Veuillez mettre à jour votre version de Nintendont."
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Désinstaller"

View File

@ -1101,6 +1101,9 @@ msgstr "GameCube Spiele Löschen"
msgid "GameCube Install Menu"
msgstr "GameCube Installationsmenü"
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "Spiel ID"
@ -1824,6 +1827,9 @@ msgstr "Zurücksetzen"
msgid "Reset BG Music"
msgstr "Musik zurücksetzen"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Spielzähler zurücksetzen"
@ -2253,6 +2259,9 @@ msgstr "USBLoaderGX konnte die Nintendont config Dateien nicht ändern. Nintendo
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr "USBLoaderGX r1218 wird benötigt um Nintendont Alpha v0.1 starten zu können. Bitte aktualisiere deine Nintendont Version."
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Deinstallieren"

View File

@ -1101,6 +1101,9 @@ msgstr "Διαγραφή παιχνιδιών GameCube"
msgid "GameCube Install Menu"
msgstr "menu εγκατάστασης παιχνιδιών GameCube"
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "ID παιχνιδιού"
@ -1824,6 +1827,9 @@ msgstr "Επανεκκίνηση"
msgid "Reset BG Music"
msgstr "Επαναφορά μουσικής υπόκρουσης."
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Επαναφορά του Playcounter"
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Απεγκατάσταση"

View File

@ -1101,6 +1101,9 @@ msgstr ""
msgid "GameCube Install Menu"
msgstr ""
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "Játék ID"
@ -1824,6 +1827,9 @@ msgstr ""
msgid "Reset BG Music"
msgstr ""
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Elindítások nullázása"
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Törlés"

View File

@ -1101,6 +1101,9 @@ msgstr "Menu disinstallazioni GC"
msgid "GameCube Install Menu"
msgstr "Menu installazioni GC"
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "ID gioco"
@ -1824,6 +1827,9 @@ msgstr "Riavvia"
msgid "Reset BG Music"
msgstr "Ripristina musica sottofondo"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Azzera contatore"
@ -2253,6 +2259,9 @@ msgstr "USBLoader GX non può sceivere il file configurazione. Avviare comuqnue
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr "USBLoaderGX r1218 o successivo è richiesto per Nintendont Alpha v0.1. Per favore aggiorna la tua versione di Nintendont"
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Disinstalla"

View File

@ -1101,6 +1101,9 @@ msgstr "GCゲームの削除"
msgid "GameCube Install Menu"
msgstr "GCインストールメニュー"
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "IDのみ"
@ -1824,6 +1827,9 @@ msgstr "リセット"
msgid "Reset BG Music"
msgstr "BGMをリセット"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "プレイ回数をリセット"
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "アンインストール"

View File

@ -1095,12 +1095,15 @@ msgstr ""
msgid "GXFlush"
msgstr ""
msgid "Game Cube Games Delete"
msgid "GameCube Games Delete"
msgstr "게임큐브 게임 삭제"
msgid "Game Cube Install Menu"
msgid "GameCube Install Menu"
msgstr "게임큐브 설치 메뉴"
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "게임 ID"
@ -1824,6 +1827,9 @@ msgstr "리셋"
msgid "Reset BG Music"
msgstr "배경 음악 리셋"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Playcounter 리셋"
@ -2247,6 +2253,9 @@ msgstr "USBloaderGX는 닌텐돈트 구성 파일을 기록할 수 없습니다.
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr "USBloaderGX r1218은 닌텐돈트 알파 v0.1에 필요합니다. 닌텐돈트 boot.dol 버전을 업데이트하십시오."
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "제거"

View File

@ -1101,6 +1101,9 @@ msgstr ""
msgid "GameCube Install Menu"
msgstr ""
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "Spill ID"
@ -1824,6 +1827,9 @@ msgstr "Tilbakestill"
msgid "Reset BG Music"
msgstr "Tilbakestill BG musikk"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Nullstill teller"
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr ""

View File

@ -1101,6 +1101,9 @@ msgstr ""
msgid "GameCube Install Menu"
msgstr ""
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "ID gry"
@ -1824,6 +1827,9 @@ msgstr ""
msgid "Reset BG Music"
msgstr ""
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Zrestartuj licznik"
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Odinstaluj"

View File

@ -1101,6 +1101,9 @@ msgstr "Desinstalar Jogos GameCube"
msgid "GameCube Install Menu"
msgstr "Instalar Jogos GameCube"
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "ID do Jogo"
@ -1824,6 +1827,9 @@ msgstr "Reiniciar"
msgid "Reset BG Music"
msgstr "Música padrão"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Limpar Contagem"
@ -2253,6 +2259,9 @@ msgstr "USB Loader GX não conseguiu gravar configurações do Nintendont. Rodar
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr "USB Loader GX r1218 é exigido para usar o Nintendont Alpha v0.1. Atualize sua versão do Nintendont"
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Desinstalar"

View File

@ -1101,6 +1101,9 @@ msgstr ""
msgid "GameCube Install Menu"
msgstr ""
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "ID do Jogo"
@ -1824,6 +1827,9 @@ msgstr "Reinicializar"
msgid "Reset BG Music"
msgstr "Reinicializar Música de Fundo"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Limpar Contagem"
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr ""

View File

@ -1101,6 +1101,9 @@ msgstr ""
msgid "GameCube Install Menu"
msgstr ""
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "ID игры"
@ -1824,6 +1827,9 @@ msgstr ""
msgid "Reset BG Music"
msgstr ""
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Сбросить счетчик запусков"
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Деинсталлировать"

View File

@ -1101,6 +1101,9 @@ msgstr "GameCube 游戏删除"
msgid "GameCube Install Menu"
msgstr "GameCube 安装菜单"
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "游戏 ID"
@ -1824,6 +1827,9 @@ msgstr "重启"
msgid "Reset BG Music"
msgstr "重置背景音乐"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "重置游戏计数"
@ -2253,6 +2259,9 @@ msgstr "USBloaderGX不能写Nintendont设置文件是否运行Nintendont"
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr "USBloaderGX r1218之针对nintendont Alpha v0.1请更新你的Nintendont boot。dol版本。"
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "删除"

View File

@ -1101,6 +1101,9 @@ msgstr "Borrar Juego de GameCube"
msgid "GameCube Install Menu"
msgstr "Menu de instalación GameCube"
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "ID del Juego"
@ -1824,6 +1827,9 @@ msgstr "Reiniciar"
msgid "Reset BG Music"
msgstr "Reiniciar Música de Fondo"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Reiniciar Partidas"
@ -2253,6 +2259,9 @@ msgstr "No se puede escribir la configuración de Nintendont, ¿desea continuar
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr "Se necesita la versión r1218 para Nintendont Alpha 0.1. Por favor, actualiza el boot.dol de Nintendont."
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Desinstalar"

View File

@ -1101,6 +1101,9 @@ msgstr ""
msgid "GameCube Install Menu"
msgstr ""
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "Spel-ID"
@ -1824,6 +1827,9 @@ msgstr ""
msgid "Reset BG Music"
msgstr "återställ BG musik"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Återställ spelat-räknaren"
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Avinstallera"

View File

@ -1101,6 +1101,9 @@ msgstr "GameCube 遊戲刪除"
msgid "GameCube Install Menu"
msgstr "GameCube 安裝畫面"
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "遊戲 ID"
@ -1824,6 +1827,9 @@ msgstr "重新啟動"
msgid "Reset BG Music"
msgstr "重設背景音樂"
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "重設執行次數"
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "移除"

View File

@ -1101,6 +1101,9 @@ msgstr ""
msgid "GameCube Install Menu"
msgstr ""
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "เกมส์ ID"
@ -1824,6 +1827,9 @@ msgstr ""
msgid "Reset BG Music"
msgstr ""
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "เคลียร์การนับจำนวนที่เล่น"
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "ถอนการติดตั้ง"

View File

@ -1101,6 +1101,9 @@ msgstr ""
msgid "GameCube Install Menu"
msgstr ""
msgid "Game Header Cache Files Path"
msgstr ""
msgid "Game ID"
msgstr "Oyun ID"
@ -1824,6 +1827,9 @@ msgstr ""
msgid "Reset BG Music"
msgstr ""
msgid "Reset Game Header Cache"
msgstr ""
msgid "Reset Playcounter"
msgstr "Sayacı sıfırla"
@ -2253,6 +2259,9 @@ msgstr ""
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
msgstr ""
msgid "Use Game Header Cache"
msgstr ""
msgid "Uninstall"
msgstr "Kaldır"

View File

@ -47,7 +47,8 @@ SOURCES := source \
source/SystemMenu \
source/utils \
source/utils/minizip \
source/usbloader/wbfs
source/usbloader/wbfs \
source/cache
DATA := data \
data/images \
data/fonts \

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,7 @@
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include "GCGames.h"
#include "FileOperations/fileops.h"
#include "settings/GameTitles.h"
@ -30,13 +31,14 @@
#include "system/IosLoader.h"
#include "menu.h"
#include "gecko.h"
#include "cache/cache.hpp"
GCGames *GCGames::instance = NULL;
inline bool isGameID(const u8 *id)
{
for (int i = 0; i < 6; i++)
if (!isalnum((int) id[i]))
if (!isalnum((int)id[i]))
return false;
return true;
@ -44,12 +46,12 @@ inline bool isGameID(const u8 *id)
const char *GCGames::GetPath(const char *gameID) const
{
if(!gameID)
if (!gameID)
return "";
for(u32 i = 0; i < HeaderList.size(); i++)
for (u32 i = 0; i < HeaderList.size(); i++)
{
if(strncasecmp((const char *) HeaderList[i].id, gameID, 6) == 0)
if (strncasecmp((const char *)HeaderList[i].id, gameID, 6) == 0)
return PathList[i].c_str();
}
@ -68,15 +70,17 @@ void GCGames::LoadGameList(const string &path, vector<struct discHdr> &headerLis
struct dirent *dirent;
dir_iter = opendir(path.c_str());
if (!dir_iter) return;
if (!dir_iter)
return;
while ((dirent = readdir(dir_iter)) != 0)
{
const char *dirname = dirent->d_name;
if(!dirname)
if (!dirname)
continue;
if (dirname[0] == '.') continue;
if (dirname[0] == '.')
continue;
// reset id and title
memset(id, 0, sizeof(id));
@ -87,7 +91,7 @@ void GCGames::LoadGameList(const string &path, vector<struct discHdr> &headerLis
int len = strlen(dirname);
if (len >= 8)
{
if (Wbfs_Fat::CheckLayoutB((char *) dirname, len, id, fname_title))
if (Wbfs_Fat::CheckLayoutB((char *)dirname, len, id, fname_title))
{
// path/TITLE[GAMEID]/game.iso
lay_b = true;
@ -97,42 +101,43 @@ void GCGames::LoadGameList(const string &path, vector<struct discHdr> &headerLis
// path/GAMEID_TITLE/game.iso
memcpy(id, dirname, 6);
if(isGameID(id))
if (isGameID(id))
{
lay_a = true;
snprintf(fname_title, sizeof(fname_title), "%s", &dirname[7]);
}
}
}
else if(len == 6 && isGameID((u8*)dirname)) {
else if (len == 6 && isGameID((u8 *)dirname))
{
memcpy(id, dirname, 6);
lay_a = true;
}
if(!lay_a && !lay_b)
if (!lay_a && !lay_b)
memset(id, 0, sizeof(id));
bool found = false;
bool extracted = false;
for(int i = 0; i < 4; i++)
for (int i = 0; i < 4; i++)
{
char name[50];
snprintf(name, sizeof(name), "%.6s.%s", (i % 2) == 0 ? "game" : (char *) id, i >= 2 ? "gcm" : "iso");
snprintf(name, sizeof(name), "%.6s.%s", (i % 2) == 0 ? "game" : (char *)id, i >= 2 ? "gcm" : "iso");
snprintf(fpath, sizeof(fpath), "%s%s/%s", path.c_str(), dirname, name);
if((found = (stat(fpath, &st) == 0)) == true)
if ((found = (stat(fpath, &st) == 0)) == true)
break;
}
// Check if only disc2.iso is present
if(!found)
if (!found)
{
for(int i = 0; i < 2; i++)
for (int i = 0; i < 2; i++)
{
char name[50];
snprintf(name, sizeof(name), "disc2.%s", (i % 2) == 0 ? "gcm" : "iso"); // allow gcm, though DM(L) require "disc2.iso" filename
snprintf(fpath, sizeof(fpath), "%s%s/%s", path.c_str(), dirname, name);
if((found = (stat(fpath, &st) == 0)) == true)
if ((found = (stat(fpath, &st) == 0)) == true)
{
disc_number = 1;
break;
@ -140,17 +145,18 @@ void GCGames::LoadGameList(const string &path, vector<struct discHdr> &headerLis
}
}
if(!found)
if (!found)
{
snprintf(fpath, sizeof(fpath), "%s%s/sys/boot.bin", path.c_str(), dirname);
if(stat(fpath, &st) != 0)
if (stat(fpath, &st) != 0)
continue;
// this game is extracted
extracted = true;
}
//! GAMEID was not found
if(!lay_a && !lay_b) {
if (!lay_a && !lay_b)
{
// read game ID and title from disc header
// iso file
FILE *fp = fopen(fpath, "rb");
@ -180,7 +186,7 @@ void GCGames::LoadGameList(const string &path, vector<struct discHdr> &headerLis
string gamePath = string(path) + dirname + (extracted ? "/" : strrchr(fpath, '/'));
memset(&tmpHdr, 0, sizeof(tmpHdr));
memcpy(tmpHdr.id, id, 6);
strncpy(tmpHdr.title, title, sizeof(tmpHdr.title)-1);
strncpy(tmpHdr.title, title, sizeof(tmpHdr.title) - 1);
tmpHdr.magic = GCGames::MAGIC;
tmpHdr.type = extracted ? TYPE_GAME_GC_EXTRACTED : TYPE_GAME_GC_IMG;
tmpHdr.disc_no = disc_number;
@ -217,30 +223,38 @@ void GCGames::LoadGameList(const string &path, vector<struct discHdr> &headerLis
u32 GCGames::LoadAllGames(void)
{
if (Settings.UseGameHeaderCache && isCacheFile(GAMECUBE_HEADER_CACHE_FILE))
{
if (HeaderList.empty() && PathList.empty())
LoadGameHeaderCache(HeaderList, PathList);
if (!HeaderList.empty())
return (int)HeaderList.size();
}
PathList.clear();
HeaderList.clear();
sdGCList.clear();
sdGCPathList.clear();
if(strcmp(Settings.GameCubePath, Settings.GameCubeSDPath) == 0 || Settings.GameCubeSource != GC_SOURCE_SD)
if (strcmp(Settings.GameCubePath, Settings.GameCubeSDPath) == 0 || Settings.GameCubeSource != GC_SOURCE_SD)
LoadGameList(Settings.GameCubePath, HeaderList, PathList);
if(strcmp(Settings.GameCubePath, Settings.GameCubeSDPath) != 0 && (Settings.GameCubeSource != GC_SOURCE_MAIN))
if (strcmp(Settings.GameCubePath, Settings.GameCubeSDPath) != 0 && (Settings.GameCubeSource != GC_SOURCE_MAIN))
{
LoadGameList(Settings.GameCubeSDPath, sdGCList, sdGCPathList);
for(u32 i = 0; i < sdGCList.size(); ++i)
for (u32 i = 0; i < sdGCList.size(); ++i)
{
if(Settings.GameCubeSource != GC_SOURCE_SD)
if (Settings.GameCubeSource != GC_SOURCE_SD)
{
u32 n;
for(n = 0; n < HeaderList.size(); ++n)
for (n = 0; n < HeaderList.size(); ++n)
{
//! Display only one game if it is present on both SD and USB.
if(memcmp(HeaderList[n].id, sdGCList[i].id, 6) == 0)
if (memcmp(HeaderList[n].id, sdGCList[i].id, 6) == 0)
{
if((Settings.GameCubeSource == GC_SOURCE_MAIN_SD) ||
(Settings.GameCubeSource == GC_SOURCE_AUTO && (IosLoader::GetMIOSInfo() == DIOS_MIOS || IosLoader::GetMIOSInfo() == QUADFORCE_USB))) // DIOS MIOS - Show the game on USB in priority
if ((Settings.GameCubeSource == GC_SOURCE_MAIN_SD) ||
(Settings.GameCubeSource == GC_SOURCE_AUTO && (IosLoader::GetMIOSInfo() == DIOS_MIOS || IosLoader::GetMIOSInfo() == QUADFORCE_USB))) // DIOS MIOS - Show the game on USB in priority
{
break;
}
@ -254,43 +268,47 @@ u32 GCGames::LoadAllGames(void)
}
// Not available in the main GC path
if(n == HeaderList.size()) {
if (n == HeaderList.size())
{
HeaderList.push_back(sdGCList[i]);
PathList.push_back(sdGCPathList[i]);
}
}
else // GC_SOURCE_SD
{
HeaderList.push_back(sdGCList[i]);
PathList.push_back(sdGCPathList[i]);
}
HeaderList.push_back(sdGCList[i]);
PathList.push_back(sdGCPathList[i]);
}
}
}
if (Settings.UseGameHeaderCache && !HeaderList.empty() && !PathList.empty())
SaveGameHeaderCache(HeaderList, PathList);
return HeaderList.size();
}
bool GCGames::RemoveGame(const char *gameID)
{
const char *path = GetPath(gameID);
if(*path == 0)
if (*path == 0)
return false;
RemoveSDGame(gameID);
if(strcmp(Settings.GameCubePath, Settings.GameCubeSDPath) == 0)
if (strcmp(Settings.GameCubePath, Settings.GameCubeSDPath) == 0)
return true;
struct discHdr *header = NULL;
for(u32 i = 0; i < HeaderList.size(); ++i)
for (u32 i = 0; i < HeaderList.size(); ++i)
{
if(strncmp(gameID, (char*)HeaderList[i].id, 6) == 0)
if (strncmp(gameID, (char *)HeaderList[i].id, 6) == 0)
{
header = &HeaderList[i];
break;
}
}
if(!header)
if (!header)
return false;
char filepath[512];
@ -300,24 +318,25 @@ bool GCGames::RemoveGame(const char *gameID)
char cIsoPath[256];
snprintf(cIsoPath, sizeof(cIsoPath), "%s", path + strlen(Settings.GameCubeSDPath));
if(header->type == TYPE_GAME_GC_IMG)
if (header->type == TYPE_GAME_GC_IMG)
{
// Remove game iso
snprintf(filepath, sizeof(filepath), "%s%s", Settings.GameCubePath, cIsoPath);
if(!RemoveFile(filepath))
if (!RemoveFile(filepath))
result = -1;
// Remove path
char *pathPtr = strrchr(filepath, '/');
if(pathPtr) *pathPtr = 0;
if(!RemoveFile(filepath))
if (pathPtr)
*pathPtr = 0;
if (!RemoveFile(filepath))
result = -1;
}
else if(header->type == TYPE_GAME_GC_EXTRACTED)
else if (header->type == TYPE_GAME_GC_EXTRACTED)
{
//! remove extracted gamecube game
snprintf(filepath, sizeof(filepath), "%s%s", Settings.GameCubePath, cIsoPath);
if(!RemoveDirectory(path))
if (!RemoveDirectory(path))
result = -1;
}
@ -327,45 +346,46 @@ bool GCGames::RemoveGame(const char *gameID)
bool GCGames::RemoveSDGame(const char *gameID)
{
const char *path = GetPath(gameID);
if(*path == 0)
if (*path == 0)
return false;
struct discHdr *header = NULL;
for(u32 i = 0; i < HeaderList.size(); ++i)
for (u32 i = 0; i < HeaderList.size(); ++i)
{
if(strncmp(gameID, (char*)HeaderList[i].id, 6) == 0)
if (strncmp(gameID, (char *)HeaderList[i].id, 6) == 0)
{
header = &HeaderList[i];
break;
}
}
if(!header)
if (!header)
return false;
char filepath[512];
int result = 0;
int ret;
if(header->type == TYPE_GAME_GC_IMG)
if (header->type == TYPE_GAME_GC_IMG)
{
// Remove game iso
snprintf(filepath, sizeof(filepath), "%s", path);
ret = RemoveFile(filepath);
if(ret != 0)
if (ret != 0)
result = -1;
// Remove path
char *pathPtr = strrchr(filepath, '/');
if(pathPtr) *pathPtr = 0;
if (pathPtr)
*pathPtr = 0;
ret = RemoveFile(filepath);
if(ret != 0)
if (ret != 0)
result = -1;
}
else if(header->type == TYPE_GAME_GC_EXTRACTED)
else if (header->type == TYPE_GAME_GC_EXTRACTED)
{
//! remove extracted gamecube game
ret = RemoveDirectory(path);
if(ret < 0)
if (ret < 0)
result = -1;
}
@ -375,39 +395,39 @@ bool GCGames::RemoveSDGame(const char *gameID)
float GCGames::GetGameSize(const char *gameID)
{
const char *path = GetPath(gameID);
if(*path == 0)
if (*path == 0)
return 0.0f;
struct stat st;
if(stat(path, &st) != 0)
if (stat(path, &st) != 0)
return 0.0f;
return ((float) st.st_size / GB_SIZE);
return ((float)st.st_size / GB_SIZE);
}
bool GCGames::IsInstalled(const char *gameID, u8 disc_number) const
{
for(u32 n = 0; n < HeaderList.size(); n++)
for (u32 n = 0; n < HeaderList.size(); n++)
{
if(memcmp(HeaderList[n].id, gameID, 6) == 0)
if (memcmp(HeaderList[n].id, gameID, 6) == 0)
{
if(HeaderList[n].type == TYPE_GAME_GC_EXTRACTED || Settings.GCInstallCompressed)
if (HeaderList[n].type == TYPE_GAME_GC_EXTRACTED || Settings.GCInstallCompressed)
return true; // Multi-disc games in extracted form are currently unsupported by DML, no need to check further.
if(HeaderList[n].disc_no == disc_number) // Disc number already in headerList. If Disc2 is loaded in headerList, then Disc1 is not installed yet
if (HeaderList[n].disc_no == disc_number) // Disc number already in headerList. If Disc2 is loaded in headerList, then Disc1 is not installed yet
{
return true;
}
else if(disc_number == 1) // Check if the second Game Disc exists in the same folder than Disc1.
else if (disc_number == 1) // Check if the second Game Disc exists in the same folder than Disc1.
{
char filepath[512];
int n = snprintf(filepath, sizeof(filepath), "%s", GetPath(gameID));
char *pathPtr = strrchr(filepath, '/');
if(pathPtr) *pathPtr = 0;
if (pathPtr)
*pathPtr = 0;
snprintf(filepath + n, sizeof(filepath) - n, "/disc2.iso");
if(CheckFile(filepath))
if (CheckFile(filepath))
return true;
}
}
@ -417,18 +437,18 @@ bool GCGames::IsInstalled(const char *gameID, u8 disc_number) const
bool GCGames::CopyUSB2SD(const struct discHdr *header)
{
const char *path = GetPath((char*)header->id);
const char *path = GetPath((char *)header->id);
int oldGameCubeSource = Settings.GameCubeSource;
if(*path == 0)
if (*path == 0)
return false;
int choice = WindowPrompt(tr("The game is on USB."), tr("Do you want to copy the game to SD or delete a game on SD?"), tr("Copy"), tr("Show SD"), tr("Cancel"));
if(choice == 0)
if (choice == 0)
return false;
const char *cpTitle = GameTitles.GetTitle(header);
if(choice == 2)
if (choice == 2)
{
// Load Games from SD card only
Settings.GameCubeSource = GC_SOURCE_SD;
@ -443,7 +463,8 @@ bool GCGames::CopyUSB2SD(const struct discHdr *header)
gcDeleteMenu.Show();
gcDeleteMenu.SetEffect(EFFECT_FADE, -20);
while(gcDeleteMenu.GetEffect() > 0) usleep(1000);
while (gcDeleteMenu.GetEffect() > 0)
usleep(1000);
mainWindow->Remove(&gcDeleteMenu);
mainWindow->SetState(STATE_DEFAULT);
@ -452,12 +473,12 @@ bool GCGames::CopyUSB2SD(const struct discHdr *header)
Settings.GameCubeSource = oldGameCubeSource;
GCGames::Instance()->LoadAllGames();
if(!WindowPrompt(tr("Do you want to copy now?"), cpTitle, tr("Yes"), tr("Cancel")))
if (!WindowPrompt(tr("Do you want to copy now?"), cpTitle, tr("Yes"), tr("Cancel")))
return false;
}
struct statvfs sd_vfs;
if(statvfs(Settings.GameCubeSDPath, &sd_vfs) != 0)
if (statvfs(Settings.GameCubeSDPath, &sd_vfs) != 0)
{
WindowPrompt(tr("Error:"), tr("SD Card could not be accessed."), tr("OK"));
return false;
@ -465,20 +486,22 @@ bool GCGames::CopyUSB2SD(const struct discHdr *header)
u64 filesize = 0;
if(header->type == TYPE_GAME_GC_IMG) {
if (header->type == TYPE_GAME_GC_IMG)
{
filesize = FileSize(path);
}
else if(header->type == TYPE_GAME_GC_EXTRACTED) {
else if (header->type == TYPE_GAME_GC_EXTRACTED)
{
StartProgress(tr("Getting game folder size..."), tr("Please wait"), 0, true, true);
ShowProgress(0, 1);
filesize = FileSize(path);
ProgressStop();
}
while(((u64)sd_vfs.f_frsize * (u64)sd_vfs.f_bfree) < filesize)
while (((u64)sd_vfs.f_frsize * (u64)sd_vfs.f_bfree) < filesize)
{
choice = WindowPrompt(tr("Error: Not enough space on SD."), tr("Do you want to delete a game on SD?"), tr("Yes"), tr("Cancel"));
if(choice == 0)
if (choice == 0)
return false;
GCDeleteMenu gcDeleteMenu;
@ -490,7 +513,8 @@ bool GCGames::CopyUSB2SD(const struct discHdr *header)
gcDeleteMenu.Show();
gcDeleteMenu.SetEffect(EFFECT_FADE, -20);
while(gcDeleteMenu.GetEffect() > 0) usleep(1000);
while (gcDeleteMenu.GetEffect() > 0)
usleep(1000);
mainWindow->Remove(&gcDeleteMenu);
mainWindow->SetState(STATE_DEFAULT);
@ -504,13 +528,14 @@ bool GCGames::CopyUSB2SD(const struct discHdr *header)
int res = -1;
if(header->type == TYPE_GAME_GC_IMG)
if (header->type == TYPE_GAME_GC_IMG)
{
ProgressCancelEnable(true);
StartProgress(tr("Copying GC game..."), cpTitle, 0, true, true);
char *ptr = strrchr(destPath, '/');
if(ptr) *ptr = 0;
if (ptr)
*ptr = 0;
CreateSubfolder(destPath);
@ -518,7 +543,7 @@ bool GCGames::CopyUSB2SD(const struct discHdr *header)
res = CopyFile(path, destPath);
}
else if(header->type == TYPE_GAME_GC_EXTRACTED)
else if (header->type == TYPE_GAME_GC_EXTRACTED)
{
res = CopyDirectory(path, destPath);
}
@ -529,28 +554,30 @@ bool GCGames::CopyUSB2SD(const struct discHdr *header)
ProgressStop();
ProgressCancelEnable(false);
if(res == PROGRESS_CANCELED)
if (res == PROGRESS_CANCELED)
{
if(header->type == TYPE_GAME_GC_IMG)
if (header->type == TYPE_GAME_GC_IMG)
{
// remove file and path
RemoveFile(destPath);
char *ptr = strrchr(destPath, '/');
if(ptr) *ptr = 0;
if (ptr)
*ptr = 0;
RemoveFile(destPath);
}
WindowPrompt(tr("Copying Canceled"), 0, tr("OK"));
return false;
}
else if(res < 0)
else if (res < 0)
{
if(header->type == TYPE_GAME_GC_IMG)
if (header->type == TYPE_GAME_GC_IMG)
{
// remove file and path
RemoveFile(destPath);
char *ptr = strrchr(destPath, '/');
if(ptr) *ptr = 0;
if (ptr)
*ptr = 0;
RemoveFile(destPath);
}
@ -568,53 +595,53 @@ int nintendontBuildDate(const char *NIN_loader_path, char *NINBuildDate)
char NIN_loader[100];
snprintf(NIN_loader, sizeof(NIN_loader), "%sboot.dol", NIN_loader_path);
if(!CheckFile(NIN_loader))
if (!CheckFile(NIN_loader))
snprintf(NIN_loader, sizeof(NIN_loader), "%sloader.dol", NIN_loader_path);
if(CheckFile(NIN_loader))
if (CheckFile(NIN_loader))
{
u8 *buffer = NULL;
u32 filesize = 0;
const char* str = "Nintendont Loader";
const char *str = "Nintendont Loader";
bool found = false;
if(LoadFileToMem(NIN_loader, &buffer, &filesize))
if (LoadFileToMem(NIN_loader, &buffer, &filesize))
{
for(u32 i = 0; i < filesize-100; ++i)
for (u32 i = 0; i < filesize - 100; ++i)
{
if( memcmp(buffer+i, str, strlen(str)) == 0)
if (memcmp(buffer + i, str, strlen(str)) == 0)
{
// Write buffer in NINheader
char NINHeader[100];
for(u8 j = 0 ; j < 99 ; j++)
NINHeader[j] = *(u8*)(buffer+i+j) == 0 ? ' ' : *(u8*)(buffer+i+j); // replace \0 with a space.
for (u8 j = 0; j < 99; j++)
NINHeader[j] = *(u8 *)(buffer + i + j) == 0 ? ' ' : *(u8 *)(buffer + i + j); // replace \0 with a space.
NINHeader[99] = '\0';
// Search month string start position in header
char *dateStart = NULL;
const char *month[] = {"Jan ", "Feb ", "Mar ", "Apr ", "May ", "Jun ", "Jui ", "Aug ", "Sep ", "Oct ", "Nov ", "Dec "};
for(u8 m = 0 ; m < 12 ; m++)
for (u8 m = 0; m < 12; m++)
{
dateStart = strstr(NINHeader, month[m]);
if(dateStart != NULL)
if (dateStart != NULL)
break;
}
if(dateStart == NULL)
if (dateStart == NULL)
break;
dateStart[20] = '\0';
sprintf(NINBuildDate, "%.20s", dateStart);
gprintf("Nintendont Build date : %.20s \n", dateStart);
found = true;
break;
}
}
free(buffer);
}
if(found)
if (found)
return 1;
}
return 0;
}
@ -623,28 +650,28 @@ int nintendontVersion(const char *NIN_loader_path, char *NINVersion, int len)
char NIN_loader[100];
u32 NINRev = 0;
snprintf(NIN_loader, sizeof(NIN_loader), "%sboot.dol", NIN_loader_path);
if(!CheckFile(NIN_loader))
if (!CheckFile(NIN_loader))
snprintf(NIN_loader, sizeof(NIN_loader), "%sloader.dol", NIN_loader_path);
if(CheckFile(NIN_loader))
if (CheckFile(NIN_loader))
{
u8 *buffer = NULL;
u32 filesize = 0;
const char* str = "$$Version:";
if(LoadFileToMem(NIN_loader, &buffer, &filesize))
const char *str = "$$Version:";
if (LoadFileToMem(NIN_loader, &buffer, &filesize))
{
for(u32 i = 0; i < filesize; i += 32)
for (u32 i = 0; i < filesize; i += 32)
{
if(memcmp( buffer+i, str, strlen(str)) == 0)
if (memcmp(buffer + i, str, strlen(str)) == 0)
{
// Write buffer in NINVersion
snprintf(NINVersion, len, "%s", buffer+i+strlen(str));
NINRev = atoi(strchr(NINVersion, '.')+1);
snprintf(NINVersion, len, "%s", buffer + i + strlen(str));
NINRev = atoi(strchr(NINVersion, '.') + 1);
break;
}
}
free(buffer);
}
}
return NINRev;
}

338
source/cache/cache.cpp vendored Normal file
View File

@ -0,0 +1,338 @@
/*
Code by Oddx @ GBAtemp.net
Loosely based on emuNAND caching by geoGolem.
*/
#include <fstream>
#include <dirent.h>
#include "cache.hpp"
#include "usbloader/disc.h"
#include "settings/CSettings.h"
#include "FileOperations/fileops.h"
#include "memory/memory.h"
#include "Channels/channels.h"
#include "usbloader/GameList.h"
#include "GameCube/GCGames.h"
void ResetGameHeaderCache()
{
RemoveDirectory(Settings.GameHeaderCachePath);
return;
}
// emuNAND
void SaveGameHeaderCache(vector<struct discHdr> &list)
{
string path = string(Settings.GameHeaderCachePath) + EMUNAND_HEADER_CACHE_FILE;
if (!CheckFile(Settings.GameHeaderCachePath))
CreateSubfolder(Settings.GameHeaderCachePath);
FILE *cache = fopen(path.c_str(), "wb");
if (!cache)
return;
fwrite((void *)&list[0], 1, list.size() * sizeof(struct discHdr), cache);
fclose(cache);
}
void LoadGameHeaderCache(vector<struct discHdr> &list)
{
string path = string(Settings.GameHeaderCachePath) + EMUNAND_HEADER_CACHE_FILE;
FILE *cache = fopen(path.c_str(), "rb");
if (!cache)
return;
struct discHdr tmp;
fseek(cache, 0, SEEK_END);
u64 fileSize = ftell(cache);
fseek(cache, 0, SEEK_SET);
u32 count = (u32)(fileSize / sizeof(struct discHdr));
list.reserve(count + list.size());
for (u32 i = 0; i < count; i++)
{
fseek(cache, i * sizeof(struct discHdr), SEEK_SET);
fread((void *)&tmp, 1, sizeof(struct discHdr), cache);
list.push_back(tmp);
}
fclose(cache);
}
// Wii
void SaveGameHeaderCache(vector<struct discHdr> &list, vector<int> &plist)
{
vector<struct wiiCache> wiictmp;
struct wiiCache gtmp;
for (u32 i = 0; i < list.size(); ++i)
{
memset(&gtmp, 0, sizeof(struct wiiCache));
gtmp.header = list[i];
gtmp.part = plist[i];
wiictmp.push_back(gtmp);
}
string path = string(Settings.GameHeaderCachePath) + WII_HEADER_CACHE_FILE;
if (!CheckFile(Settings.GameHeaderCachePath))
CreateSubfolder(Settings.GameHeaderCachePath);
FILE *cache = fopen(path.c_str(), "wb");
if (!cache)
return;
fwrite((void *)&wiictmp[0], 1, wiictmp.size() * sizeof(struct wiiCache), cache);
fclose(cache);
}
void LoadGameHeaderCache(vector<struct discHdr> &list, vector<int> &plist)
{
string path = string(Settings.GameHeaderCachePath) + WII_HEADER_CACHE_FILE;
FILE *cache = fopen(path.c_str(), "rb");
if (!cache)
return;
struct wiiCache wiictmp;
fseek(cache, 0, SEEK_END);
u64 fileSize = ftell(cache);
fseek(cache, 0, SEEK_SET);
u32 count = (u32)(fileSize / sizeof(struct wiiCache));
list.reserve(count + list.size());
plist.reserve(count + plist.size());
for (u32 i = 0; i < count; i++)
{
fseek(cache, i * sizeof(struct wiiCache), SEEK_SET);
fread((void *)&wiictmp, 1, sizeof(struct wiiCache), cache);
list.push_back(wiictmp.header);
plist.push_back(wiictmp.part);
}
fclose(cache);
}
// GameCube
void SaveGameHeaderCache(vector<struct discHdr> &list, vector<string> &plist)
{
vector<struct gcCache> gcctmp;
struct gcCache gtmp;
for (u32 i = 0; i < list.size(); ++i)
{
memset(&gtmp, 0, sizeof(gcCache));
gtmp.header = list[i];
strcpy((char *)gtmp.path, plist[i].c_str());
gcctmp.push_back(gtmp);
}
string path = string(Settings.GameHeaderCachePath) + GAMECUBE_HEADER_CACHE_FILE;
if (!CheckFile(Settings.GameHeaderCachePath))
CreateSubfolder(Settings.GameHeaderCachePath);
FILE *cache = fopen(path.c_str(), "wb");
if (!cache)
return;
fwrite((void *)&gcctmp[0], 1, gcctmp.size() * sizeof(struct gcCache), cache);
fclose(cache);
}
void LoadGameHeaderCache(vector<struct discHdr> &list, vector<string> &plist)
{
string path = string(Settings.GameHeaderCachePath) + GAMECUBE_HEADER_CACHE_FILE;
FILE *cache = fopen(path.c_str(), "rb");
if (!cache)
return;
struct gcCache gcctmp;
fseek(cache, 0, SEEK_END);
u64 fileSize = ftell(cache);
fseek(cache, 0, SEEK_SET);
u32 count = (u32)(fileSize / sizeof(struct gcCache));
list.reserve(count + list.size());
plist.reserve(count + plist.size());
for (u32 i = 0; i < count; i++)
{
fseek(cache, i * sizeof(struct gcCache), SEEK_SET);
fread((void *)&gcctmp, 1, sizeof(struct gcCache), cache);
list.push_back(gcctmp.header);
string tmp((char *)gcctmp.path);
plist.push_back(tmp);
}
fclose(cache);
}
void SaveFilteredListCache(vector<struct discHdr *> &list, const wchar_t *gameFilter)
{
string path = string(Settings.GameHeaderCachePath) + FilteredListCacheFileName(gameFilter);
if (!CheckFile(Settings.GameHeaderCachePath))
CreateSubfolder(Settings.GameHeaderCachePath);
FILE *cache = fopen(path.c_str(), "wb");
if (!cache)
return;
vector<struct gameHdr> tmplist;
struct gameHdr tmp;
for (u32 i = 0; i < list.size(); ++i)
{
memcpy(tmp.id, list[i]->id, 6);
tmplist.push_back(tmp);
}
fwrite((void *)&tmplist[0], 1, tmplist.size() * sizeof(struct gameHdr), cache);
fclose(cache);
}
void LoadFilteredListCache(vector<struct discHdr *> &list, const wchar_t *gameFilter)
{
string path = string(Settings.GameHeaderCachePath) + FilteredListCacheFileName(gameFilter);
if (!CheckFile(Settings.GameHeaderCachePath))
CreateSubfolder(Settings.GameHeaderCachePath);
FILE *cache = fopen(path.c_str(), "rb");
if (!cache)
return;
struct gameHdr tmp;
fseek(cache, 0, SEEK_END);
u64 fileSize = ftell(cache);
fseek(cache, 0, SEEK_SET);
u32 count = (u32)(fileSize / sizeof(struct gameHdr));
list.reserve(count + list.size());
for (u32 i = 0; i < count; i++)
{
bool found = false;
fseek(cache, i * sizeof(struct gameHdr), SEEK_SET);
fread((void *)&tmp, 1, sizeof(struct gameHdr), cache);
if (!found)
{
vector<struct discHdr> &tmplist = gameList.GetFullGameList();
for (u32 c = 0; c < tmplist.size(); ++c)
{
struct discHdr *header = &tmplist[c];
if (strncasecmp((const char *)tmp.id, (const char *)header->id, 6) == 0)
{
list.push_back(header);
found = true;
break;
}
}
}
if (!found)
{
vector<struct discHdr> &tmplist = GCGames::Instance()->GetHeaders();
for (u32 c = 0; c < tmplist.size(); ++c)
{
struct discHdr *header = &tmplist[c];
if (strncasecmp((const char *)tmp.id, (const char *)header->id, 6) == 0)
{
list.push_back(header);
found = true;
break;
}
}
}
if (!found)
{
vector<struct discHdr> &tmplist = Channels::Instance()->GetNandHeaders();
for (u32 c = 0; c < tmplist.size(); ++c)
{
struct discHdr *header = &tmplist[c];
if (strncasecmp((const char *)tmp.id, (const char *)header->id, 6) == 0)
{
list.push_back(header);
found = true;
break;
}
}
}
if (!found)
{
vector<struct discHdr> &tmplist = Channels::Instance()->GetEmuHeaders();
for (u32 c = 0; c < tmplist.size(); ++c)
{
struct discHdr *header = &tmplist[c];
if (strncasecmp((const char *)tmp.id, (const char *)header->id, 6) == 0)
{
list.push_back(header);
found = true;
break;
}
}
}
}
fclose(cache);
}
string FilteredListCacheFileName(const wchar_t *gameFilter)
{
string tmp;
tmp = "FL";
tmp += "_" + to_string(Settings.LoaderMode);
tmp += "_" + to_string(Settings.GameSort);
if (gameFilter)
{
wstring ws(gameFilter);
string gf(ws.begin(), ws.end());
if ((gf.length()) > 0)
tmp += "_" + gf;
}
tmp += ".cache";
return tmp;
}
string FilteredListCacheFileName()
{
string tmp;
tmp = "FL";
tmp += "_" + to_string(Settings.LoaderMode);
tmp += "_" + to_string(Settings.GameSort);
tmp += ".cache";
return tmp;
}
bool isCacheFile(string filename)
{
string path = string(Settings.GameHeaderCachePath) + filename;
if (CheckFile(path.c_str()))
return true;
return false;
}

54
source/cache/cache.hpp vendored Normal file
View File

@ -0,0 +1,54 @@
/*
Code by Oddx @ GBAtemp.net
Loosely based on emuNAND caching by geoGolem.
*/
#include "usbloader/disc.h"
#include "settings/CSettings.h"
#define WII_HEADER_CACHE_FILE "WII.cache"
#define GAMECUBE_HEADER_CACHE_FILE "GAMECUBE.cache"
#define EMUNAND_HEADER_CACHE_FILE "EMUNAND.cache"
using namespace std;
struct gameHdr
{
/* Game ID */
u8 id[6];
/* Padding */
u8 unused3[2];
};
struct wiiCache
{
struct discHdr header;
int part;
};
struct gcCache
{
struct discHdr header;
u8 path[200];
};
// emuNAND
void SaveGameHeaderCache(vector<struct discHdr> &list);
void LoadGameHeaderCache(vector<struct discHdr> &list);
// Wii
void SaveGameHeaderCache(vector<struct discHdr> &list, vector<int> &plist);
void LoadGameHeaderCache(vector<struct discHdr> &list, vector<int> &plist);
// GameCube
void SaveGameHeaderCache(vector<struct discHdr> &list, vector<string> &plist);
void LoadGameHeaderCache(vector<struct discHdr> &list, vector<string> &plist);
void ResetGameHeaderCache();
void SaveFilteredListCache(vector<struct discHdr *> &list, const wchar_t *gameFilter);
void LoadFilteredListCache(vector<struct discHdr *> &list, const wchar_t *gameFilter);
string FilteredListCacheFileName(const wchar_t *gameFilter);
string FilteredListCacheFileName();
bool isCacheFile(string filename);

View File

@ -11,6 +11,7 @@
#include "themes/CTheme.h"
#include "utils/tools.h"
#include "system/IosLoader.h"
#include "cache/cache.hpp"
#define WII_MAGIC 0x5D1C9EA3
@ -287,6 +288,7 @@ int MenuInstall()
else
{
ShowProgress(tr("Install finished"), headerdisc.title, tr("Reloading game list now, please wait..."), gamesize, gamesize, true, true);
ResetGameHeaderCache();
gameList.ReadGameList(); //get the entries again
gameList.FilterList();
bgMusic->Pause();

View File

@ -63,6 +63,7 @@ void CSettings::SetDefault()
snprintf(languagefiles_path, sizeof(languagefiles_path), "%slanguage/", ConfigPath);
snprintf(update_path, sizeof(update_path), "%s/apps/usbloader_gx/", BootDevice);
snprintf(BNRCachePath, sizeof(BNRCachePath), "%s/apps/usbloader_gx/cache_bnr/", BootDevice);
snprintf(GameHeaderCachePath, sizeof(GameHeaderCachePath), "%s/apps/usbloader_gx/cache/", BootDevice);
snprintf(homebrewapps_path, sizeof(homebrewapps_path), "%s/apps/", BootDevice);
snprintf(Cheatcodespath, sizeof(Cheatcodespath), "%s/codes/", BootDevice);
snprintf(TxtCheatcodespath, sizeof(TxtCheatcodespath), "%s/txtcodes/", BootDevice);
@ -135,6 +136,7 @@ void CSettings::SetDefault()
musicloopmode = ON;
marknewtitles = ON;
ShowFreeSpace = ON;
UseGameHeaderCache = OFF;
PlaylogUpdate = OFF;
ParentalBlocks = BLOCK_ALL;
InstallToDir = INSTALL_TO_NAME_GAMEID;
@ -359,6 +361,7 @@ bool CSettings::Save()
fprintf(file, "update_path = %s\n", update_path);
fprintf(file, "homebrewapps_path = %s\n", homebrewapps_path);
fprintf(file, "BNRCachePath = %s\n", BNRCachePath);
fprintf(file, "GameHeaderCachePath = %s\n", GameHeaderCachePath);
fprintf(file, "Cheatcodespath = %s\n", Cheatcodespath);
fprintf(file, "BcaCodepath = %s\n", BcaCodepath);
fprintf(file, "WipCodepath = %s\n", WipCodepath);
@ -374,6 +377,7 @@ bool CSettings::Save()
fprintf(file, "partition = %d\n", partition);
fprintf(file, "marknewtitles = %d\n", marknewtitles);
fprintf(file, "ShowFreeSpace = %d\n", ShowFreeSpace);
fprintf(file, "UseGameHeaderCache = %d\n", UseGameHeaderCache);
fprintf(file, "InstallToDir = %d\n", InstallToDir);
fprintf(file, "GameSplit = %d\n", GameSplit);
fprintf(file, "InstallPartitions = %08X\n", (unsigned int)InstallPartitions);
@ -724,6 +728,11 @@ bool CSettings::SetSetting(char *name, char *value)
ShowFreeSpace = atoi(value);
return true;
}
else if (strcmp(name, "UseGameHeaderCache") == 0)
{
UseGameHeaderCache = atoi(value);
return true;
}
else if (strcmp(name, "HomeMenu") == 0)
{
HomeMenu = atoi(value);
@ -1238,6 +1247,11 @@ bool CSettings::SetSetting(char *name, char *value)
strlcpy(BNRCachePath, value, sizeof(BNRCachePath));
return true;
}
else if (strcmp(name, "GameHeaderCachePath") == 0)
{
strlcpy(GameHeaderCachePath, value, sizeof(GameHeaderCachePath));
return true;
}
else if (strcmp(name, "Cheatcodespath") == 0)
{
strlcpy(Cheatcodespath, value, sizeof(Cheatcodespath));

View File

@ -85,6 +85,7 @@ class CSettings
char NandEmuPath[50];
char NandEmuChanPath[50];
char BNRCachePath[50];
char GameHeaderCachePath[50];
char GameCubePath[100];
char GameCubeSDPath[100];
char DEVOLoaderPath[100];
@ -142,6 +143,7 @@ class CSettings
short GameSplit;
short PlaylogUpdate;
short ShowFreeSpace;
short UseGameHeaderCache;
short HomeMenu;
short MultiplePartitions;
short USBPort;

View File

@ -65,6 +65,7 @@ CustomPathsSM::CustomPathsSM()
Options->SetName(Idx++, tr("Devolution Loader Path"));
Options->SetName(Idx++, tr("Nintendont Loader Path"));
Options->SetName(Idx++, tr("Cache BNR Files Path"));
Options->SetName(Idx++, tr("Game Header Cache Files Path"));
SetOptionValues();
}
@ -141,6 +142,9 @@ void CustomPathsSM::SetOptionValues()
//! Settings: Cache BNR Files Path
Options->SetValue(Idx++, Settings.BNRCachePath);
//! Settings: Game Header Cache Files Path
Options->SetValue(Idx++, Settings.GameHeaderCachePath);
}
int CustomPathsSM::GetMenuInternal()
@ -368,6 +372,13 @@ int CustomPathsSM::GetMenuInternal()
ChangePath(Settings.BNRCachePath, sizeof(Settings.BNRCachePath));
}
//! Settings: Game Header Cache Files Path
else if (ret == ++Idx)
{
titleTxt->SetText(tr( "Game Header Cache Files Path" ));
ChangePath(Settings.GameHeaderCachePath, sizeof(Settings.GameHeaderCachePath));
}
//! Global set back of the titleTxt after a change
titleTxt->SetText(tr( "Custom Paths" ));
SetOptionValues();

View File

@ -24,6 +24,7 @@
#include <gccore.h>
#include <ogc/machine/processor.h>
#include <unistd.h>
#include "FeatureSettingsMenu.hpp"
#include "Channels/channels.h"
#include "settings/CGameCategories.hpp"
@ -44,6 +45,7 @@
#include "wad/nandtitle.h"
#include "wad/wad.h"
#include "sys.h"
#include "cache/cache.hpp"
static const char * OnOffText[] =
{
@ -64,6 +66,7 @@ FeatureSettingsMenu::FeatureSettingsMenu()
int Idx = 0;
Options->SetName(Idx++, "%s", tr( "Titles from GameTDB" ));
Options->SetName(Idx++, "%s", tr( "Cache Titles" ));
Options->SetName(Idx++, "%s", tr( "Use Game Header Cache" ));
Options->SetName(Idx++, "%s", tr( "Force Titles from Disc" ));
Options->SetName(Idx++, "%s", tr( "Wiilight" ));
Options->SetName(Idx++, "%s", tr( "Rumble" ));
@ -80,6 +83,7 @@ FeatureSettingsMenu::FeatureSettingsMenu()
// Options->SetName(Idx++, "%s", tr( "Update Nintendont" ));
Options->SetName(Idx++, "%s", tr( "WiiU Widescreen" ));
Options->SetName(Idx++, "%s", tr( "Boot Neek System Menu" ));
Options->SetName(Idx++, "%s", tr( "Reset Game Header Cache" ));
OldTitlesOverride = Settings.titlesOverride;
OldCacheTitles = Settings.CacheTitles;
@ -121,6 +125,9 @@ void FeatureSettingsMenu::SetOptionValues()
//! Settings: Cache Titles
Options->SetValue(Idx++, "%s", tr( OnOffText[Settings.CacheTitles] ));
//! Settings: Use Game Header Cache
Options->SetValue(Idx++, "%s", tr( OnOffText[Settings.UseGameHeaderCache] ));
//! Settings: Force Titles from Disc
Options->SetValue(Idx++, "%s", tr( OnOffText[Settings.ForceDiscTitles] ));
@ -193,6 +200,12 @@ int FeatureSettingsMenu::GetMenuInternal()
if (++Settings.CacheTitles >= MAX_ON_OFF) Settings.CacheTitles = 0;
}
//! Settings: Use Game Header Cache
else if (ret == ++Idx)
{
if (++Settings.UseGameHeaderCache >= MAX_ON_OFF) Settings.UseGameHeaderCache = 0;
}
//! Settings: Force Titles from Disc
else if (ret == ++Idx)
{
@ -506,7 +519,7 @@ int FeatureSettingsMenu::GetMenuInternal()
char wadpath[150];
snprintf(wadpath, sizeof(wadpath), "%s/wad/", Settings.BootDevice);
int choice = WindowPrompt(tr("EmuNAND Wad Manager"), tr("Which mode do you want to use?"), tr("File"), tr("Folder"), tr("Cancel"));
if(choice == 1) // File mode
{
@ -530,8 +543,9 @@ int FeatureSettingsMenu::GetMenuInternal()
Wad wadFile(wadpath);
wadFile.UnInstall(Settings.NandEmuChanPath);
}
// Refresh new EmuNAND content
ResetGameHeaderCache();
Channels::Instance()->GetEmuChannelList();
GameTitles.LoadTitlesFromGameTDB(Settings.titlestxt_path);
}
@ -618,10 +632,11 @@ int FeatureSettingsMenu::GetMenuInternal()
else
WindowPrompt(tr( "EmuNAND Wad Manager" ), tr("Error writing the data."), tr( "OK" ));
}
}
}
}
// Refresh new EmuNAND content
ResetGameHeaderCache();
Channels::Instance()->GetEmuChannelList();
GameTitles.LoadTitlesFromGameTDB(Settings.titlestxt_path);
}
@ -629,7 +644,7 @@ int FeatureSettingsMenu::GetMenuInternal()
{
WindowPrompt(tr( "EmuNAND Wad Manager" ), tr("No wad file found in this folder."), tr( "OK" ));
}
delete wadList;
}
}
@ -646,7 +661,7 @@ int FeatureSettingsMenu::GetMenuInternal()
snprintf(NINUpdatePath, sizeof(NINUpdatePath), "%sboot.dol", Settings.NINLoaderPath);
char NINUpdatePathBak[100];
snprintf(NINUpdatePathBak, sizeof(NINUpdatePathBak), "%sboot.bak", Settings.NINLoaderPath);
int choice = WindowPrompt(tr( "Do you want to update this file?" ), NINUpdatePath, tr( "Yes" ), tr( "Cancel" ));
if (choice == 1)
{
@ -659,7 +674,7 @@ int FeatureSettingsMenu::GetMenuInternal()
// Rename existing boot.dol file to boot.bak
if(CheckFile(NINUpdatePath))
RenameFile(NINUpdatePath, NINUpdatePathBak);
// Download latest loader.dol as boot.dol
bool success = false;
struct download file = {};
@ -677,10 +692,10 @@ int FeatureSettingsMenu::GetMenuInternal()
}
else
WindowPrompt(tr( "Update failed" ), 0, tr( "OK" ));
MEM2_free(file.data);
}
if(success)
{
//remove existing loader.dol file if found as it has priority over boot.dol, and boot.bak
@ -737,13 +752,24 @@ int FeatureSettingsMenu::GetMenuInternal()
ExitApp();
NEEK_CFG *neek_config = (NEEK_CFG *) NEEK_CONFIG_ADDRESS;
neek2oSetBootSettings(neek_config, 0 /* TitleID */ , 0 /* Magic */, 0 /* Returnto TitleID */, Settings.NandEmuChanPath /* Full EmuNAND path */);
if(neekBoot() == -1)
Sys_BackToLoader();
return MENU_NONE;
}
}
}
//! Reset Game Header Cache
else if(ret == ++Idx)
{
int choice = WindowPrompt(tr( "Are you sure you want to reset?" ), 0, tr( "Yes" ), tr( "Cancel" ));
if (choice == 1)
{
ResetGameHeaderCache();
gameList.ReadGameList();
}
}
SetOptionValues();
return MENU_NONE;

View File

@ -22,6 +22,7 @@
* distribution.
***************************************************************************/
#include <unistd.h>
#include "UninstallSM.hpp"
#include "FileOperations/fileops.h"
#include "GameCube/GCGames.h"
@ -35,6 +36,7 @@
#include "usbloader/wbfs.h"
#include "usbloader/GameList.h"
#include "wstring.hpp"
#include "cache/cache.hpp"
UninstallSM::UninstallSM(struct discHdr * header)
: SettingsMenu(tr("Uninstall Menu"), &GuiOptions, MENU_NONE)
@ -127,6 +129,7 @@ int UninstallSM::GetMenuInternal()
if(ret >= 0)
{
wString oldFilter(gameList.GetCurrentFilter());
ResetGameHeaderCache();
gameList.ReadGameList();
gameList.FilterList(oldFilter.c_str());
}
@ -134,6 +137,7 @@ int UninstallSM::GetMenuInternal()
else if(DiscHeader->type == TYPE_GAME_GC_IMG)
{
GCGames::Instance()->RemoveGame(GameID);
ResetGameHeaderCache();
// Reload list
GCGames::Instance()->LoadAllGames();
}
@ -147,6 +151,7 @@ int UninstallSM::GetMenuInternal()
snprintf(filepath, sizeof(filepath), "%s/title/%08x/%08x/", Settings.NandEmuChanPath, (unsigned int) (DiscHeader->tid >> 32), (unsigned int) DiscHeader->tid);
RemoveDirectory(filepath);
ResetGameHeaderCache();
Channels::Instance()->GetEmuChannelList();
}

View File

@ -24,6 +24,7 @@
#include <algorithm>
#include <string>
#include <malloc.h>
#include "GUI/gui_searchbar.h"
#include "usbloader/wbfs.h"
#include "GameCube/GCGames.h"
@ -37,8 +38,14 @@
#include "GameList.h"
#include "memory/memory.h"
#include "Channels/channels.h"
#include "cache/cache.hpp"
enum { DISABLED, ENABLED, HIDEFORBIDDEN };
enum
{
DISABLED,
ENABLED,
HIDEFORBIDDEN
};
GameList gameList;
@ -54,13 +61,14 @@ void GameList::clear()
std::vector<int>().swap(GamePartitionList);
}
struct discHdr * GameList::GetDiscHeader(const char * gameID) const
struct discHdr *GameList::GetDiscHeader(const char *gameID) const
{
if(!gameID) return NULL;
if (!gameID)
return NULL;
for (u32 i = 0; i < FilteredList.size(); ++i)
{
if(strncasecmp(gameID, (const char *) FilteredList[i]->id, 6) == 0)
if (strncasecmp(gameID, (const char *)FilteredList[i]->id, 6) == 0)
return FilteredList[i];
}
@ -69,11 +77,12 @@ struct discHdr * GameList::GetDiscHeader(const char * gameID) const
int GameList::GetPartitionNumber(const u8 *gameID) const
{
if(!gameID) return -1;
if (!gameID)
return -1;
for (u32 i = 0; i < FullGameList.size(); ++i)
{
if(strncasecmp((const char *) gameID, (const char *) FullGameList[i].id, 6) == 0)
if (strncasecmp((const char *)gameID, (const char *)FullGameList[i].id, 6) == 0)
return GamePartitionList[i];
}
@ -82,17 +91,17 @@ int GameList::GetPartitionNumber(const u8 *gameID) const
void GameList::RemovePartition(int part)
{
for(u32 i = 0; i < GamePartitionList.size(); ++i)
for (u32 i = 0; i < GamePartitionList.size(); ++i)
{
if(GamePartitionList[i] == part)
if (GamePartitionList[i] == part)
{
FullGameList.erase(FullGameList.begin()+i);
GamePartitionList.erase(GamePartitionList.begin()+i);
FullGameList.erase(FullGameList.begin() + i);
GamePartitionList.erase(GamePartitionList.begin() + i);
--i;
}
}
if(FullGameList.size() > 0)
if (FullGameList.size() > 0)
FilterList();
}
@ -102,18 +111,20 @@ int GameList::InternalReadList(int part)
u32 cnt = 0;
int ret = WBFS_GetCount(part, &cnt);
if (ret < 0) return -1;
if (ret < 0)
return -1;
// We are done here if no games are there
if(cnt == 0)
if (cnt == 0)
return 0;
/* Buffer length */
u32 len = sizeof(struct discHdr) * cnt;
/* Allocate memory */
struct discHdr *buffer = (struct discHdr *) allocate_memory( len );
if (!buffer) return -1;
struct discHdr *buffer = (struct discHdr *)allocate_memory(len);
if (!buffer)
return -1;
/* Clear buffer */
memset(buffer, 0, len);
@ -133,22 +144,22 @@ int GameList::InternalReadList(int part)
for (u32 i = 0; i < PartGameList.size(); i++)
{
for(u32 j = 0; j < FullGameList.size(); j++)
for (u32 j = 0; j < FullGameList.size(); j++)
{
if(strncasecmp((const char *) PartGameList[i].id, (const char *) FullGameList[j].id, 6) == 0)
if (strncasecmp((const char *)PartGameList[i].id, (const char *)FullGameList[j].id, 6) == 0)
{
PartGameList.erase(PartGameList.begin()+i);
PartGameList.erase(PartGameList.begin() + i);
--i;
break;
}
}
}
FullGameList.resize(oldSize+PartGameList.size());
memcpy(&FullGameList[oldSize], &PartGameList[0], PartGameList.size()*sizeof(struct discHdr));
FullGameList.resize(oldSize + PartGameList.size());
memcpy(&FullGameList[oldSize], &PartGameList[0], PartGameList.size() * sizeof(struct discHdr));
GamePartitionList.resize(oldSize+PartGameList.size());
GamePartitionList.resize(oldSize + PartGameList.size());
for(u32 i = oldSize; i < GamePartitionList.size(); ++i)
for (u32 i = oldSize; i < GamePartitionList.size(); ++i)
GamePartitionList[i] = part;
return PartGameList.size();
@ -156,6 +167,13 @@ int GameList::InternalReadList(int part)
int GameList::ReadGameList()
{
if (Settings.UseGameHeaderCache && isCacheFile(WII_HEADER_CACHE_FILE))
{
if (FullGameList.empty() && GamePartitionList.empty())
LoadGameHeaderCache(FullGameList, GamePartitionList);
if (!FullGameList.empty())
return (int)FullGameList.size();
}
// Clear list
FullGameList.clear();
GamePartitionList.clear();
@ -165,7 +183,7 @@ int GameList::ReadGameList()
int cnt = 0;
if(!Settings.MultiplePartitions)
if (!Settings.MultiplePartitions)
{
cnt = InternalReadList(Settings.partition);
}
@ -173,13 +191,17 @@ int GameList::ReadGameList()
{
int partitions = DeviceHandler::GetUSBPartitionCount();
for(int part = 0; part < partitions; ++part)
for (int part = 0; part < partitions; ++part)
{
int ret = InternalReadList(part);
if(ret > 0) cnt += ret;
if (ret > 0)
cnt += ret;
}
}
if (Settings.UseGameHeaderCache && !FullGameList.empty() && !GamePartitionList.empty())
SaveGameHeaderCache(FullGameList, GamePartitionList);
return cnt;
}
@ -195,23 +217,25 @@ void GameList::InternalFilterList(std::vector<struct discHdr> &FullList)
/* Filters */
if (Settings.GameSort & SORT_FAVORITE)
{
GameStatus * GameStats = GameStatistics.GetGameStatus(header->id);
GameStatus *GameStats = GameStatistics.GetGameStatus(header->id);
if (Settings.marknewtitles)
{
bool isNew = NewTitles::Instance()->IsNew(header->id);
if (!isNew && (!GameStats || GameStats->FavoriteRank == 0)) continue;
if (!isNew && (!GameStats || GameStats->FavoriteRank == 0))
continue;
}
else
{
if (!GameStats || GameStats->FavoriteRank == 0) continue;
if (!GameStats || GameStats->FavoriteRank == 0)
continue;
}
}
//ignore uLoader cfg "iso". i was told it is "__CFG_" but not confirmed
if (strncasecmp((char*) header->id, "__CFG_", 6) == 0)
if (strncasecmp((char *)header->id, "__CFG_", 6) == 0)
continue;
GameCFG * GameConfig = GameSettings.GetGameCFG(header);
GameCFG *GameConfig = GameSettings.GetGameCFG(header);
/* Rating based parental control method */
if (Settings.parentalcontrol != PARENTAL_LVL_ADULT && !Settings.godmode)
@ -220,89 +244,89 @@ void GameList::InternalFilterList(std::vector<struct discHdr> &FullList)
continue;
// Check game rating in GameTDB, since the default Wii parental control setting is enabled
int rating = GameTitles.GetParentalRating((char *) header->id);
int rating = GameTitles.GetParentalRating((char *)header->id);
if (rating > Settings.parentalcontrol)
continue;
}
//! Per game lock method
if(!Settings.godmode && GameConfig && GameConfig->Locked)
if (!Settings.godmode && GameConfig && GameConfig->Locked)
continue;
//! Category filter
u32 n;
int allType = DISABLED;
// verify the display mode for category "All"
for(n = 0; n < Settings.EnabledCategories.size(); ++n)
for (n = 0; n < Settings.EnabledCategories.size(); ++n)
{
if(Settings.EnabledCategories[n] == 0)
if (Settings.EnabledCategories[n] == 0)
{
allType = ENABLED; // All = Enabled
break;
}
}
for(n = 0; n < Settings.ForbiddenCategories.size(); ++n)
for (n = 0; n < Settings.ForbiddenCategories.size(); ++n)
{
if(Settings.ForbiddenCategories[n] == 0)
if (Settings.ForbiddenCategories[n] == 0)
{
allType = HIDEFORBIDDEN; // All = Enabled but hide Forbidden categories
break;
}
}
if(allType == DISABLED)
if (allType == DISABLED)
{
// Remove TitleID if it contains a forbidden categories
for(n = 0; n < Settings.ForbiddenCategories.size(); ++n)
for (n = 0; n < Settings.ForbiddenCategories.size(); ++n)
{
if(GameCategories.isInCategory((char *) header->id, Settings.ForbiddenCategories[n]))
if (GameCategories.isInCategory((char *)header->id, Settings.ForbiddenCategories[n]))
break;
}
if(n < Settings.ForbiddenCategories.size())
if (n < Settings.ForbiddenCategories.size())
continue;
// Remove TitleID is it doesn't contain a required categories
for(n = 0; n < Settings.RequiredCategories.size(); ++n)
for (n = 0; n < Settings.RequiredCategories.size(); ++n)
{
if(!GameCategories.isInCategory((char *) header->id, Settings.RequiredCategories[n]))
if (!GameCategories.isInCategory((char *)header->id, Settings.RequiredCategories[n]))
break;
}
if(n < Settings.RequiredCategories.size())
if (n < Settings.RequiredCategories.size())
continue;
// If there's no required categories, verify if the TitleID should be kept or removed
if(Settings.RequiredCategories.size() == 0)
if (Settings.RequiredCategories.size() == 0)
{
for(n = 0; n < Settings.EnabledCategories.size(); ++n)
for (n = 0; n < Settings.EnabledCategories.size(); ++n)
{
if(GameCategories.isInCategory((char *) header->id, Settings.EnabledCategories[n]))
if (GameCategories.isInCategory((char *)header->id, Settings.EnabledCategories[n]))
break;
}
if(n == Settings.EnabledCategories.size())
if (n == Settings.EnabledCategories.size())
continue;
}
}
if(allType == HIDEFORBIDDEN)
if (allType == HIDEFORBIDDEN)
{
// Remove TitleID if it contains a forbidden categories
for(n = 0; n < Settings.ForbiddenCategories.size(); ++n)
for (n = 0; n < Settings.ForbiddenCategories.size(); ++n)
{
if(GameCategories.isInCategory((char *) header->id, Settings.ForbiddenCategories[n]))
if(Settings.ForbiddenCategories[n] >0)
if (GameCategories.isInCategory((char *)header->id, Settings.ForbiddenCategories[n]))
if (Settings.ForbiddenCategories[n] > 0)
break;
}
if(n < Settings.ForbiddenCategories.size())
if (n < Settings.ForbiddenCategories.size())
continue;
}
}
FilteredList.push_back(header);
}
}
int GameList::FilterList(const wchar_t * gameFilter)
int GameList::FilterList(const wchar_t *gameFilter)
{
if((Settings.LoaderMode & MODE_WIIGAMES) && (FullGameList.size() == 0))
if ((Settings.LoaderMode & MODE_WIIGAMES) && (FullGameList.size() == 0))
ReadGameList();
if (gameFilter)
@ -310,20 +334,28 @@ int GameList::FilterList(const wchar_t * gameFilter)
FilteredList.clear();
if (Settings.UseGameHeaderCache && isCacheFile(FilteredListCacheFileName(gameFilter)))
{
LoadFilteredListCache(FilteredList, GameFilter.c_str());
GuiSearchBar::FilterList(FilteredList, GameFilter);
if (!FilteredList.empty())
return FilteredList.size();
}
// Filter current game list if selected
if(Settings.LoaderMode & MODE_WIIGAMES)
if (Settings.LoaderMode & MODE_WIIGAMES)
InternalFilterList(FullGameList);
// Filter gc game list if selected
if(Settings.LoaderMode & MODE_GCGAMES)
if (Settings.LoaderMode & MODE_GCGAMES)
InternalFilterList(GCGames::Instance()->GetHeaders());
// Filter nand channel list if selected
if(Settings.LoaderMode & MODE_NANDCHANNELS)
if (Settings.LoaderMode & MODE_NANDCHANNELS)
InternalFilterList(Channels::Instance()->GetNandHeaders());
// Filter emu nand channel list if selected
if(Settings.LoaderMode & MODE_EMUCHANNELS)
if (Settings.LoaderMode & MODE_EMUCHANNELS)
InternalFilterList(Channels::Instance()->GetEmuHeaders());
NewTitles::Instance()->Save();
@ -331,6 +363,9 @@ int GameList::FilterList(const wchar_t * gameFilter)
SortList();
if (Settings.UseGameHeaderCache && !FilteredList.empty() && (Settings.GameSort & SORT_RANKING) == 0 && (Settings.GameSort & SORT_PLAYCOUNT) == 0 && (Settings.GameSort & SORT_FAVORITE) == 0)
SaveFilteredListCache(FilteredList, GameFilter.c_str());
return FilteredList.size();
}
@ -349,26 +384,34 @@ void GameList::InternalLoadUnfiltered(std::vector<struct discHdr> &FullList)
int GameList::LoadUnfiltered()
{
if((Settings.LoaderMode & MODE_WIIGAMES) && (FullGameList.size() == 0))
if ((Settings.LoaderMode & MODE_WIIGAMES) && (FullGameList.size() == 0))
ReadGameList();
GameFilter.clear();
FilteredList.clear();
if (Settings.UseGameHeaderCache && isCacheFile(FilteredListCacheFileName()))
{
LoadFilteredListCache(FilteredList, GameFilter.c_str());
GuiSearchBar::FilterList(FilteredList, GameFilter);
if (!FilteredList.empty())
return FilteredList.size();
}
// Filter current game list if selected
if(Settings.LoaderMode & MODE_WIIGAMES)
if (Settings.LoaderMode & MODE_WIIGAMES)
InternalLoadUnfiltered(FullGameList);
// Filter gc game list if selected
if(Settings.LoaderMode & MODE_GCGAMES)
if (Settings.LoaderMode & MODE_GCGAMES)
InternalLoadUnfiltered(GCGames::Instance()->GetHeaders());
// Filter nand channel list if selected
if(Settings.LoaderMode & MODE_NANDCHANNELS)
if (Settings.LoaderMode & MODE_NANDCHANNELS)
InternalLoadUnfiltered(Channels::Instance()->GetNandHeaders());
// Filter emu nand channel list if selected
if(Settings.LoaderMode & MODE_EMUCHANNELS)
if (Settings.LoaderMode & MODE_EMUCHANNELS)
InternalLoadUnfiltered(Channels::Instance()->GetEmuHeaders());
NewTitles::Instance()->Save();
@ -376,22 +419,26 @@ int GameList::LoadUnfiltered()
SortList();
if (Settings.UseGameHeaderCache && !FilteredList.empty() && (Settings.GameSort & SORT_RANKING) == 0 && (Settings.GameSort & SORT_PLAYCOUNT) == 0 && (Settings.GameSort & SORT_FAVORITE) == 0)
SaveFilteredListCache(FilteredList, GameFilter.c_str());
return FilteredList.size();
}
void GameList::SortList()
{
if (FilteredList.size() < 2) return;
if (FilteredList.size() < 2)
return;
if (Settings.GameSort & SORT_PLAYCOUNT)
{
std::sort(FilteredList.begin(), FilteredList.end(), PlaycountSortCallback);
}
else if(Settings.GameSort & SORT_RANKING)
else if (Settings.GameSort & SORT_RANKING)
{
std::sort(FilteredList.begin(), FilteredList.end(), RankingSortCallback);
}
else if(Settings.GameSort & SORT_PLAYERS)
else if (Settings.GameSort & SORT_PLAYERS)
{
std::sort(FilteredList.begin(), FilteredList.end(), PlayersSortCallback);
}
@ -403,7 +450,7 @@ void GameList::SortList()
bool GameList::NameSortCallback(const struct discHdr *a, const struct discHdr *b)
{
return (strcasecmp(GameTitles.GetTitle((struct discHdr *) a), GameTitles.GetTitle((struct discHdr *) b)) < 0);
return (strcasecmp(GameTitles.GetTitle((struct discHdr *)a), GameTitles.GetTitle((struct discHdr *)b)) < 0);
}
bool GameList::PlaycountSortCallback(const struct discHdr *a, const struct discHdr *b)
@ -411,7 +458,8 @@ bool GameList::PlaycountSortCallback(const struct discHdr *a, const struct discH
int count1 = GameStatistics.GetPlayCount(a->id);
int count2 = GameStatistics.GetPlayCount(b->id);
if (count1 == count2) return NameSortCallback(a, b);
if (count1 == count2)
return NameSortCallback(a, b);
return (count1 > count2);
}
@ -421,17 +469,19 @@ bool GameList::RankingSortCallback(const struct discHdr *a, const struct discHdr
int fav1 = GameStatistics.GetFavoriteRank(a->id);
int fav2 = GameStatistics.GetFavoriteRank(b->id);
if (fav1 == fav2) return NameSortCallback(a, b);
if (fav1 == fav2)
return NameSortCallback(a, b);
return (fav1 > fav2);
}
bool GameList::PlayersSortCallback(const struct discHdr *a, const struct discHdr *b)
{
int count1 = GameTitles.GetPlayersCount((const char *) a->id);
int count2 = GameTitles.GetPlayersCount((const char *) b->id);
int count1 = GameTitles.GetPlayersCount((const char *)a->id);
int count2 = GameTitles.GetPlayersCount((const char *)b->id);
if (count1 == count2) return NameSortCallback(a, b);
if (count1 == count2)
return NameSortCallback(a, b);
return (count1 > count2);
}