mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-22 11:19:17 +01:00
Added extra caching options
Thanks to Oddx & geoGolem
This commit is contained in:
parent
0114bc2da4
commit
c6d2efd765
@ -1101,6 +1101,9 @@ msgstr ""
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "ID hry"
|
msgstr "ID hry"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr ""
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "Obnovit hudbu na pozadí"
|
msgstr "Obnovit hudbu na pozadí"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Vynulovat cítac spuštení"
|
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."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "Odinstalace"
|
msgstr "Odinstalace"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr ""
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "Spil-ID"
|
msgstr "Spil-ID"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr "Nulstil"
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "Nulstil BG-musik"
|
msgstr "Nulstil BG-musik"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Nulstil spiltæller"
|
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."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "Afinstaller"
|
msgstr "Afinstaller"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr "GameCube Spel Verwijderen"
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr "GameCube Installatie Menu"
|
msgstr "GameCube Installatie Menu"
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "Spel ID"
|
msgstr "Spel ID"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr "Resetten"
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "Reset achtergrond muziek"
|
msgstr "Reset achtergrond muziek"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Speeltellers resetten"
|
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."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "Verwijderen"
|
msgstr "Verwijderen"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr ""
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr ""
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2253,6 +2259,9 @@ msgstr ""
|
|||||||
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr ""
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "Peli ID"
|
msgstr "Peli ID"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr ""
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Resetoi pelauksen määrä"
|
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."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "Poista"
|
msgstr "Poista"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr "Menu de suppression GameCube"
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr "Menu d'installation GameCube"
|
msgstr "Menu d'installation GameCube"
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "ID du jeu"
|
msgstr "ID du jeu"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr "Réinitialisation"
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "Fond sonore par defaut"
|
msgstr "Fond sonore par defaut"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Remise à zéro du compteur d'utilisations"
|
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."
|
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."
|
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"
|
msgid "Uninstall"
|
||||||
msgstr "Désinstaller"
|
msgstr "Désinstaller"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr "GameCube Spiele Löschen"
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr "GameCube Installationsmenü"
|
msgstr "GameCube Installationsmenü"
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "Spiel ID"
|
msgstr "Spiel ID"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr "Zurücksetzen"
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "Musik zurücksetzen"
|
msgstr "Musik zurücksetzen"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Spielzähler zurücksetzen"
|
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."
|
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."
|
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"
|
msgid "Uninstall"
|
||||||
msgstr "Deinstallieren"
|
msgstr "Deinstallieren"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr "Διαγραφή παιχνιδιών GameCube"
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr "menu εγκατάστασης παιχνιδιών GameCube"
|
msgstr "menu εγκατάστασης παιχνιδιών GameCube"
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "ID παιχνιδιού"
|
msgstr "ID παιχνιδιού"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr "Επανεκκίνηση"
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "Επαναφορά μουσικής υπόκρουσης."
|
msgstr "Επαναφορά μουσικής υπόκρουσης."
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Επαναφορά του 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."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "Απεγκατάσταση"
|
msgstr "Απεγκατάσταση"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr ""
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "Játék ID"
|
msgstr "Játék ID"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr ""
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Elindítások nullázása"
|
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."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "Törlés"
|
msgstr "Törlés"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr "Menu disinstallazioni GC"
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr "Menu installazioni GC"
|
msgstr "Menu installazioni GC"
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "ID gioco"
|
msgstr "ID gioco"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr "Riavvia"
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "Ripristina musica sottofondo"
|
msgstr "Ripristina musica sottofondo"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Azzera contatore"
|
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."
|
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"
|
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"
|
msgid "Uninstall"
|
||||||
msgstr "Disinstalla"
|
msgstr "Disinstalla"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr "GCゲームの削除"
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr "GCインストールメニュー"
|
msgstr "GCインストールメニュー"
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "IDのみ"
|
msgstr "IDのみ"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr "リセット"
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "BGMをリセット"
|
msgstr "BGMをリセット"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "プレイ回数をリセット"
|
msgstr "プレイ回数をリセット"
|
||||||
|
|
||||||
@ -2253,6 +2259,9 @@ msgstr ""
|
|||||||
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "アンインストール"
|
msgstr "アンインストール"
|
||||||
|
|
||||||
|
@ -1095,12 +1095,15 @@ msgstr ""
|
|||||||
msgid "GXFlush"
|
msgid "GXFlush"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game Cube Games Delete"
|
msgid "GameCube Games Delete"
|
||||||
msgstr "게임큐브 게임 삭제"
|
msgstr "게임큐브 게임 삭제"
|
||||||
|
|
||||||
msgid "Game Cube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr "게임큐브 설치 메뉴"
|
msgstr "게임큐브 설치 메뉴"
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "게임 ID"
|
msgstr "게임 ID"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr "리셋"
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "배경 음악 리셋"
|
msgstr "배경 음악 리셋"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "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."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr "USBloaderGX r1218은 닌텐돈트 알파 v0.1에 필요합니다. 닌텐돈트 boot.dol 버전을 업데이트하십시오."
|
msgstr "USBloaderGX r1218은 닌텐돈트 알파 v0.1에 필요합니다. 닌텐돈트 boot.dol 버전을 업데이트하십시오."
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "제거"
|
msgstr "제거"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr ""
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "Spill ID"
|
msgstr "Spill ID"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr "Tilbakestill"
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "Tilbakestill BG musikk"
|
msgstr "Tilbakestill BG musikk"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Nullstill teller"
|
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."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr ""
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "ID gry"
|
msgstr "ID gry"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr ""
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Zrestartuj licznik"
|
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."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "Odinstaluj"
|
msgstr "Odinstaluj"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr "Desinstalar Jogos GameCube"
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr "Instalar Jogos GameCube"
|
msgstr "Instalar Jogos GameCube"
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "ID do Jogo"
|
msgstr "ID do Jogo"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr "Reiniciar"
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "Música padrão"
|
msgstr "Música padrão"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Limpar Contagem"
|
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."
|
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"
|
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"
|
msgid "Uninstall"
|
||||||
msgstr "Desinstalar"
|
msgstr "Desinstalar"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr ""
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "ID do Jogo"
|
msgstr "ID do Jogo"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr "Reinicializar"
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "Reinicializar Música de Fundo"
|
msgstr "Reinicializar Música de Fundo"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Limpar Contagem"
|
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."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr ""
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "ID игры"
|
msgstr "ID игры"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr ""
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Сбросить счетчик запусков"
|
msgstr "Сбросить счетчик запусков"
|
||||||
|
|
||||||
@ -2253,6 +2259,9 @@ msgstr ""
|
|||||||
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "Деинсталлировать"
|
msgstr "Деинсталлировать"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr "GameCube 游戏删除"
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr "GameCube 安装菜单"
|
msgstr "GameCube 安装菜单"
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "游戏 ID"
|
msgstr "游戏 ID"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr "重启"
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "重置背景音乐"
|
msgstr "重置背景音乐"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "重置游戏计数"
|
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."
|
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版本。"
|
msgstr "USBloaderGX r1218之针对nintendont Alpha v0.1,请更新你的Nintendont boot。dol版本。"
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "删除"
|
msgstr "删除"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr "Borrar Juego de GameCube"
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr "Menu de instalación GameCube"
|
msgstr "Menu de instalación GameCube"
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "ID del Juego"
|
msgstr "ID del Juego"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr "Reiniciar"
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "Reiniciar Música de Fondo"
|
msgstr "Reiniciar Música de Fondo"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Reiniciar Partidas"
|
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."
|
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."
|
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"
|
msgid "Uninstall"
|
||||||
msgstr "Desinstalar"
|
msgstr "Desinstalar"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr ""
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "Spel-ID"
|
msgstr "Spel-ID"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr ""
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "återställ BG musik"
|
msgstr "återställ BG musik"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Återställ spelat-räknaren"
|
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."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "Avinstallera"
|
msgstr "Avinstallera"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr "GameCube 遊戲刪除"
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr "GameCube 安裝畫面"
|
msgstr "GameCube 安裝畫面"
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "遊戲 ID"
|
msgstr "遊戲 ID"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr "重新啟動"
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr "重設背景音樂"
|
msgstr "重設背景音樂"
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "重設執行次數"
|
msgstr "重設執行次數"
|
||||||
|
|
||||||
@ -2253,6 +2259,9 @@ msgstr ""
|
|||||||
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "移除"
|
msgstr "移除"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr ""
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "เกมส์ ID"
|
msgstr "เกมส์ ID"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr ""
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "เคลียร์การนับจำนวนที่เล่น"
|
msgstr "เคลียร์การนับจำนวนที่เล่น"
|
||||||
|
|
||||||
@ -2253,6 +2259,9 @@ msgstr ""
|
|||||||
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "ถอนการติดตั้ง"
|
msgstr "ถอนการติดตั้ง"
|
||||||
|
|
||||||
|
@ -1101,6 +1101,9 @@ msgstr ""
|
|||||||
msgid "GameCube Install Menu"
|
msgid "GameCube Install Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Game Header Cache Files Path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Game ID"
|
msgid "Game ID"
|
||||||
msgstr "Oyun ID"
|
msgstr "Oyun ID"
|
||||||
|
|
||||||
@ -1824,6 +1827,9 @@ msgstr ""
|
|||||||
msgid "Reset BG Music"
|
msgid "Reset BG Music"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Reset Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Reset Playcounter"
|
msgid "Reset Playcounter"
|
||||||
msgstr "Sayacı sıfırla"
|
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."
|
msgid "USBloaderGX r1218 is required for Nintendont Alpha v0.1. Please update your Nintendont boot.dol version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Use Game Header Cache"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Uninstall"
|
msgid "Uninstall"
|
||||||
msgstr "Kaldır"
|
msgstr "Kaldır"
|
||||||
|
|
||||||
|
3
Makefile
3
Makefile
@ -47,7 +47,8 @@ SOURCES := source \
|
|||||||
source/SystemMenu \
|
source/SystemMenu \
|
||||||
source/utils \
|
source/utils \
|
||||||
source/utils/minizip \
|
source/utils/minizip \
|
||||||
source/usbloader/wbfs
|
source/usbloader/wbfs \
|
||||||
|
source/cache
|
||||||
DATA := data \
|
DATA := data \
|
||||||
data/images \
|
data/images \
|
||||||
data/fonts \
|
data/fonts \
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sys/dirent.h>
|
#include <sys/dirent.h>
|
||||||
|
|
||||||
#include "FileOperations/fileops.h"
|
#include "FileOperations/fileops.h"
|
||||||
#include "Controls/DeviceHandler.hpp"
|
#include "Controls/DeviceHandler.hpp"
|
||||||
#include "settings/CSettings.h"
|
#include "settings/CSettings.h"
|
||||||
@ -35,10 +36,11 @@
|
|||||||
#include "memory/memory.h"
|
#include "memory/memory.h"
|
||||||
#include "utils/lz77.h"
|
#include "utils/lz77.h"
|
||||||
#include "gecko.h"
|
#include "gecko.h"
|
||||||
|
#include "cache/cache.hpp"
|
||||||
#include "channels.h"
|
#include "channels.h"
|
||||||
|
|
||||||
typedef struct _dolheader{
|
typedef struct _dolheader
|
||||||
|
{
|
||||||
u32 section_pos[18];
|
u32 section_pos[18];
|
||||||
u32 section_start[18];
|
u32 section_start[18];
|
||||||
u32 section_size[18];
|
u32 section_size[18];
|
||||||
@ -89,7 +91,7 @@ void Channels::InternalGetNandChannelList(u32 type)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
//these can't be booted anyways
|
//these can't be booted anyways
|
||||||
if (TITLE_LOWER( tid ) == 0x48414741 || TITLE_LOWER( tid ) == 0x48414141 || TITLE_LOWER( tid ) == 0x48414641)
|
if (TITLE_LOWER(tid) == 0x48414741 || TITLE_LOWER(tid) == 0x48414141 || TITLE_LOWER(tid) == 0x48414641)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//these aren't installed on the nand
|
//these aren't installed on the nand
|
||||||
@ -100,17 +102,17 @@ void Channels::InternalGetNandChannelList(u32 type)
|
|||||||
NandTitles.AsciiTID(tid, id);
|
NandTitles.AsciiTID(tid, id);
|
||||||
|
|
||||||
// Force old and new format to be "JODI" which is known by GameTDB
|
// Force old and new format to be "JODI" which is known by GameTDB
|
||||||
if(tid == 0x000100014c554c5aLL || tid == 0x00010001AF1BF516LL || tid == 0x0001000148415858LL)
|
if (tid == 0x000100014c554c5aLL || tid == 0x00010001AF1BF516LL || tid == 0x0001000148415858LL)
|
||||||
strcpy(id, "JODI");
|
strcpy(id, "JODI");
|
||||||
|
|
||||||
const char *name = GameTitles.GetTitle(id);
|
const char *name = GameTitles.GetTitle(id);
|
||||||
std::string TitleName;
|
std::string TitleName;
|
||||||
|
|
||||||
if(!name || *name == '\0')
|
if (!name || *name == '\0')
|
||||||
{
|
{
|
||||||
name = NandTitles.NameOf(tid);
|
name = NandTitles.NameOf(tid);
|
||||||
// Set title for caching
|
// Set title for caching
|
||||||
if(name)
|
if (name)
|
||||||
GameTitles.SetGameTitle(id, name);
|
GameTitles.SetGameTitle(id, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,27 +122,38 @@ void Channels::InternalGetNandChannelList(u32 type)
|
|||||||
memcpy(NandChannels[s].id, id, 4);
|
memcpy(NandChannels[s].id, id, 4);
|
||||||
NandChannels[s].tid = tid;
|
NandChannels[s].tid = tid;
|
||||||
NandChannels[s].type = TYPE_GAME_NANDCHAN;
|
NandChannels[s].type = TYPE_GAME_NANDCHAN;
|
||||||
strncpy(NandChannels[s].title, name ? name : "", sizeof(NandChannels[s].title)-1);
|
strncpy(NandChannels[s].title, name ? name : "", sizeof(NandChannels[s].title) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<struct discHdr> & Channels::GetNandHeaders(void)
|
vector<struct discHdr> &Channels::GetNandHeaders(void)
|
||||||
{
|
{
|
||||||
if(NandChannels.empty())
|
if (NandChannels.empty())
|
||||||
this->GetChannelList();
|
this->GetChannelList();
|
||||||
|
|
||||||
return NandChannels;
|
return NandChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<struct discHdr> & Channels::GetEmuHeaders(void)
|
vector<struct discHdr> &Channels::GetEmuHeaders(void)
|
||||||
{
|
{
|
||||||
if(EmuChannels.empty())
|
if (Settings.UseGameHeaderCache && isCacheFile(EMUNAND_HEADER_CACHE_FILE))
|
||||||
|
{
|
||||||
|
if (EmuChannels.empty())
|
||||||
|
LoadGameHeaderCache(EmuChannels);
|
||||||
|
if (!EmuChannels.empty())
|
||||||
|
return EmuChannels;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EmuChannels.empty())
|
||||||
this->GetEmuChannelList();
|
this->GetEmuChannelList();
|
||||||
|
|
||||||
|
if (Settings.UseGameHeaderCache && !EmuChannels.empty())
|
||||||
|
SaveGameHeaderCache(EmuChannels);
|
||||||
|
|
||||||
return EmuChannels;
|
return EmuChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 * Channels::GetDol(const u64 &title, u8 *tmdBuffer)
|
u8 *Channels::GetDol(const u64 &title, u8 *tmdBuffer)
|
||||||
{
|
{
|
||||||
static const u8 dolsign[6] = {0x00, 0x00, 0x01, 0x00, 0x00, 0x00};
|
static const u8 dolsign[6] = {0x00, 0x00, 0x01, 0x00, 0x00, 0x00};
|
||||||
static u8 dolhead[32] ATTRIBUTE_ALIGN(32);
|
static u8 dolhead[32] ATTRIBUTE_ALIGN(32);
|
||||||
@ -150,32 +163,32 @@ u8 * Channels::GetDol(const u64 &title, u8 *tmdBuffer)
|
|||||||
u32 high = TITLE_UPPER(title);
|
u32 high = TITLE_UPPER(title);
|
||||||
u32 low = TITLE_LOWER(title);
|
u32 low = TITLE_LOWER(title);
|
||||||
|
|
||||||
char *filepath = (char *) memalign(32, ISFS_MAXPATH);
|
char *filepath = (char *)memalign(32, ISFS_MAXPATH);
|
||||||
if(!filepath)
|
if (!filepath)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
_tmd * tmd_file = (_tmd *) SIGNATURE_PAYLOAD((u32 *)tmdBuffer);
|
_tmd *tmd_file = (_tmd *)SIGNATURE_PAYLOAD((u32 *)tmdBuffer);
|
||||||
|
|
||||||
if(!Settings.UseChanLauncher)
|
if (!Settings.UseChanLauncher)
|
||||||
{
|
{
|
||||||
for(u32 i = 0; i < tmd_file->num_contents; ++i)
|
for (u32 i = 0; i < tmd_file->num_contents; ++i)
|
||||||
{
|
{
|
||||||
if(tmd_file->contents[i].index == tmd_file->boot_index)
|
if (tmd_file->contents[i].index == tmd_file->boot_index)
|
||||||
continue; // Skip loader
|
continue; // Skip loader
|
||||||
|
|
||||||
snprintf(filepath, ISFS_MAXPATH, "/title/%08x/%08x/content/%08x.app", (unsigned int)high, (unsigned int)low, (unsigned int)tmd_file->contents[i].cid);
|
snprintf(filepath, ISFS_MAXPATH, "/title/%08x/%08x/content/%08x.app", (unsigned int)high, (unsigned int)low, (unsigned int)tmd_file->contents[i].cid);
|
||||||
|
|
||||||
s32 fd = ISFS_Open(filepath, ISFS_OPEN_READ);
|
s32 fd = ISFS_Open(filepath, ISFS_OPEN_READ);
|
||||||
if(fd < 0)
|
if (fd < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
s32 ret = ISFS_Read(fd, dolhead, 32);
|
s32 ret = ISFS_Read(fd, dolhead, 32);
|
||||||
ISFS_Close(fd);
|
ISFS_Close(fd);
|
||||||
|
|
||||||
if(ret != 32)
|
if (ret != 32)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(memcmp(dolhead, dolsign, sizeof(dolsign)) == 0)
|
if (memcmp(dolhead, dolsign, sizeof(dolsign)) == 0)
|
||||||
{
|
{
|
||||||
bootcontent = tmd_file->contents[i].cid;
|
bootcontent = tmd_file->contents[i].cid;
|
||||||
break;
|
break;
|
||||||
@ -184,10 +197,11 @@ u8 * Channels::GetDol(const u64 &title, u8 *tmdBuffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Fall back to boot content if dol is not found
|
//! Fall back to boot content if dol is not found
|
||||||
if(bootcontent == 0xDEADBEAF)
|
if (bootcontent == 0xDEADBEAF)
|
||||||
{
|
{
|
||||||
bootcontent = tmd_file->contents[tmd_file->boot_index].cid;
|
bootcontent = tmd_file->contents[tmd_file->boot_index].cid;
|
||||||
if(!Settings.UseChanLauncher) gprintf("Main dol not found -> ");
|
if (!Settings.UseChanLauncher)
|
||||||
|
gprintf("Main dol not found -> ");
|
||||||
gprintf("Loading boot content index\n");
|
gprintf("Loading boot content index\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,8 +233,8 @@ u8 * Channels::GetDol(const u64 &title, u8 *tmdBuffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// move dol to mem2
|
// move dol to mem2
|
||||||
u8 *outBuf = (u8 *) MEM2_alloc(filesize);
|
u8 *outBuf = (u8 *)MEM2_alloc(filesize);
|
||||||
if(!outBuf)
|
if (!outBuf)
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
||||||
memcpy(outBuf, buffer, filesize);
|
memcpy(outBuf, buffer, filesize);
|
||||||
@ -238,7 +252,7 @@ u8 Channels::GetRequestedIOS(const u64 &title)
|
|||||||
if (!titleTMD)
|
if (!titleTMD)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if(tmdSize > 0x18B)
|
if (tmdSize > 0x18B)
|
||||||
IOS = titleTMD[0x18B];
|
IOS = titleTMD[0x18B];
|
||||||
|
|
||||||
free(titleTMD);
|
free(titleTMD);
|
||||||
@ -248,11 +262,11 @@ u8 Channels::GetRequestedIOS(const u64 &title)
|
|||||||
|
|
||||||
u8 *Channels::GetTMD(const u64 &tid, u32 *size, const char *prefix)
|
u8 *Channels::GetTMD(const u64 &tid, u32 *size, const char *prefix)
|
||||||
{
|
{
|
||||||
char *filepath = (char *) memalign(32, ISFS_MAXPATH);
|
char *filepath = (char *)memalign(32, ISFS_MAXPATH);
|
||||||
if(!filepath)
|
if (!filepath)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if(!prefix)
|
if (!prefix)
|
||||||
prefix = "";
|
prefix = "";
|
||||||
|
|
||||||
snprintf(filepath, ISFS_MAXPATH, "%s/title/%08x/%08x/content/title.tmd", prefix, (unsigned int)TITLE_UPPER(tid), (unsigned int)TITLE_LOWER(tid));
|
snprintf(filepath, ISFS_MAXPATH, "%s/title/%08x/%08x/content/title.tmd", prefix, (unsigned int)TITLE_UPPER(tid), (unsigned int)TITLE_LOWER(tid));
|
||||||
@ -262,7 +276,7 @@ u8 *Channels::GetTMD(const u64 &tid, u32 *size, const char *prefix)
|
|||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if(*prefix != '\0')
|
if (*prefix != '\0')
|
||||||
ret = LoadFileToMem(filepath, &tmdBuffer, &tmdSize);
|
ret = LoadFileToMem(filepath, &tmdBuffer, &tmdSize);
|
||||||
else
|
else
|
||||||
ret = NandTitle::LoadFileFromNand(filepath, &tmdBuffer, &tmdSize);
|
ret = NandTitle::LoadFileFromNand(filepath, &tmdBuffer, &tmdSize);
|
||||||
@ -272,12 +286,12 @@ u8 *Channels::GetTMD(const u64 &tid, u32 *size, const char *prefix)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
gprintf("Reading TMD...Failed!\n");
|
gprintf("Reading TMD...Failed!\n");
|
||||||
if(tmdBuffer)
|
if (tmdBuffer)
|
||||||
free(tmdBuffer);
|
free(tmdBuffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(size)
|
if (size)
|
||||||
*size = tmdSize;
|
*size = tmdSize;
|
||||||
|
|
||||||
return tmdBuffer;
|
return tmdBuffer;
|
||||||
@ -290,21 +304,21 @@ u32 Channels::LoadChannel(const u64 &chantitle)
|
|||||||
u32 ios = 0;
|
u32 ios = 0;
|
||||||
u32 tmdSize = 0;
|
u32 tmdSize = 0;
|
||||||
u8 *tmdBuffer = GetTMD(chantitle, &tmdSize, "");
|
u8 *tmdBuffer = GetTMD(chantitle, &tmdSize, "");
|
||||||
if(!tmdBuffer)
|
if (!tmdBuffer)
|
||||||
{
|
{
|
||||||
ISFS_Deinitialize();
|
ISFS_Deinitialize();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 *chanDOL = GetDol(chantitle, tmdBuffer);
|
u8 *chanDOL = GetDol(chantitle, tmdBuffer);
|
||||||
if(!chanDOL)
|
if (!chanDOL)
|
||||||
{
|
{
|
||||||
ISFS_Deinitialize();
|
ISFS_Deinitialize();
|
||||||
free(tmdBuffer);
|
free(tmdBuffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tmdSize > 0x18B)
|
if (tmdSize > 0x18B)
|
||||||
ios = tmdBuffer[0x18B];
|
ios = tmdBuffer[0x18B];
|
||||||
|
|
||||||
Identify(chantitle, tmdBuffer, tmdSize);
|
Identify(chantitle, tmdBuffer, tmdSize);
|
||||||
@ -313,14 +327,14 @@ u32 Channels::LoadChannel(const u64 &chantitle)
|
|||||||
|
|
||||||
dolheader *dolfile = (dolheader *)chanDOL;
|
dolheader *dolfile = (dolheader *)chanDOL;
|
||||||
|
|
||||||
if(dolfile->bss_start)
|
if (dolfile->bss_start)
|
||||||
{
|
{
|
||||||
dolfile->bss_start |= 0x80000000;
|
dolfile->bss_start |= 0x80000000;
|
||||||
|
|
||||||
if(dolfile->bss_start < 0x81800000)
|
if (dolfile->bss_start < 0x81800000)
|
||||||
{
|
{
|
||||||
// For homebrews...not all have it clean.
|
// For homebrews...not all have it clean.
|
||||||
if(dolfile->bss_start + dolfile->bss_size >= 0x81800000)
|
if (dolfile->bss_start + dolfile->bss_size >= 0x81800000)
|
||||||
dolfile->bss_size = 0x81800000 - dolfile->bss_start;
|
dolfile->bss_size = 0x81800000 - dolfile->bss_start;
|
||||||
|
|
||||||
memset((void *)dolfile->bss_start, 0, dolfile->bss_size);
|
memset((void *)dolfile->bss_start, 0, dolfile->bss_size);
|
||||||
@ -330,17 +344,19 @@ u32 Channels::LoadChannel(const u64 &chantitle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < 18; i++)
|
for (i = 0; i < 18; i++)
|
||||||
{
|
{
|
||||||
if (!dolfile->section_size[i]) continue;
|
if (!dolfile->section_size[i])
|
||||||
if (dolfile->section_pos[i] < sizeof(dolheader)) continue;
|
continue;
|
||||||
if(!(dolfile->section_start[i] & 0x80000000))
|
if (dolfile->section_pos[i] < sizeof(dolheader))
|
||||||
|
continue;
|
||||||
|
if (!(dolfile->section_start[i] & 0x80000000))
|
||||||
dolfile->section_start[i] |= 0x80000000;
|
dolfile->section_start[i] |= 0x80000000;
|
||||||
|
|
||||||
u8 *dolChunkOffset = (u8 *)dolfile->section_start[i];
|
u8 *dolChunkOffset = (u8 *)dolfile->section_start[i];
|
||||||
u32 dolChunkSize = dolfile->section_size[i];
|
u32 dolChunkSize = dolfile->section_size[i];
|
||||||
|
|
||||||
memmove (dolChunkOffset, chanDOL + dolfile->section_pos[i], dolChunkSize);
|
memmove(dolChunkOffset, chanDOL + dolfile->section_pos[i], dolChunkSize);
|
||||||
DCFlushRange(dolChunkOffset, dolChunkSize);
|
DCFlushRange(dolChunkOffset, dolChunkSize);
|
||||||
ICInvalidateRange(dolChunkOffset, dolChunkSize);
|
ICInvalidateRange(dolChunkOffset, dolChunkSize);
|
||||||
|
|
||||||
@ -359,14 +375,14 @@ u32 Channels::LoadChannel(const u64 &chantitle)
|
|||||||
*Bus_Speed = 0x0E7BE2C0; // bus speed
|
*Bus_Speed = 0x0E7BE2C0; // bus speed
|
||||||
*CPU_Speed = 0x2B73A840; // cpu speed
|
*CPU_Speed = 0x2B73A840; // cpu speed
|
||||||
*GameID_Address = 0x81000000; // Game id address, while there's all 0s at 0x81000000 when using the apploader...
|
*GameID_Address = 0x81000000; // Game id address, while there's all 0s at 0x81000000 when using the apploader...
|
||||||
memcpy((void *)Online_Check, (void *)Disc_ID, 4);// online check
|
memcpy((void *)Online_Check, (void *)Disc_ID, 4); // online check
|
||||||
|
|
||||||
memset((void *)0x817FE000, 0, 0x2000); // Clearing BI2
|
memset((void *)0x817FE000, 0, 0x2000); // Clearing BI2
|
||||||
DCFlushRange((void*)0x817FE000, 0x2000);
|
DCFlushRange((void *)0x817FE000, 0x2000);
|
||||||
|
|
||||||
// IOS Version Check
|
// IOS Version Check
|
||||||
*(vu32*)0x80003140 = ((ios << 16)) | 0xFFFF;
|
*(vu32 *)0x80003140 = ((ios << 16)) | 0xFFFF;
|
||||||
*(vu32*)0x80003188 = ((ios << 16)) | 0xFFFF;
|
*(vu32 *)0x80003188 = ((ios << 16)) | 0xFFFF;
|
||||||
|
|
||||||
ISFS_Deinitialize();
|
ISFS_Deinitialize();
|
||||||
|
|
||||||
@ -376,7 +392,8 @@ u32 Channels::LoadChannel(const u64 &chantitle)
|
|||||||
static bool Identify_GenerateTik(signed_blob **outbuf, u32 *outlen)
|
static bool Identify_GenerateTik(signed_blob **outbuf, u32 *outlen)
|
||||||
{
|
{
|
||||||
signed_blob *buffer = (signed_blob *)memalign(32, STD_SIGNED_TIK_SIZE);
|
signed_blob *buffer = (signed_blob *)memalign(32, STD_SIGNED_TIK_SIZE);
|
||||||
if (!buffer) return false;
|
if (!buffer)
|
||||||
|
return false;
|
||||||
memset(buffer, 0, STD_SIGNED_TIK_SIZE);
|
memset(buffer, 0, STD_SIGNED_TIK_SIZE);
|
||||||
|
|
||||||
sig_rsa2048 *signature = (sig_rsa2048 *)buffer;
|
sig_rsa2048 *signature = (sig_rsa2048 *)buffer;
|
||||||
@ -394,14 +411,14 @@ static bool Identify_GenerateTik(signed_blob **outbuf, u32 *outlen)
|
|||||||
|
|
||||||
bool Channels::Identify(const u64 &titleid, u8 *tmdBuffer, u32 tmdSize)
|
bool Channels::Identify(const u64 &titleid, u8 *tmdBuffer, u32 tmdSize)
|
||||||
{
|
{
|
||||||
char *filepath = (char *) memalign(32, ISFS_MAXPATH);
|
char *filepath = (char *)memalign(32, ISFS_MAXPATH);
|
||||||
if(!filepath)
|
if (!filepath)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
u32 tikSize;
|
u32 tikSize;
|
||||||
signed_blob *tikBuffer = NULL;
|
signed_blob *tikBuffer = NULL;
|
||||||
|
|
||||||
if(!Identify_GenerateTik(&tikBuffer,&tikSize))
|
if (!Identify_GenerateTik(&tikBuffer, &tikSize))
|
||||||
{
|
{
|
||||||
free(filepath);
|
free(filepath);
|
||||||
gprintf("Generating fake ticket...Failed!");
|
gprintf("Generating fake ticket...Failed!");
|
||||||
@ -418,10 +435,10 @@ bool Channels::Identify(const u64 &titleid, u8 *tmdBuffer, u32 tmdSize)
|
|||||||
free(filepath);
|
free(filepath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
s32 ret = ES_Identify((signed_blob*)certBuffer, certSize, (signed_blob*)tmdBuffer, tmdSize, tikBuffer, tikSize, NULL);
|
s32 ret = ES_Identify((signed_blob *)certBuffer, certSize, (signed_blob *)tmdBuffer, tmdSize, tikBuffer, tikSize, NULL);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
switch(ret)
|
switch (ret)
|
||||||
{
|
{
|
||||||
case ES_EINVAL:
|
case ES_EINVAL:
|
||||||
gprintf("Error! ES_Identify (ret = %d;) Data invalid!\n", ret);
|
gprintf("Error! ES_Identify (ret = %d;) Data invalid!\n", ret);
|
||||||
@ -453,19 +470,19 @@ bool Channels::emuExists(char *tmdpath)
|
|||||||
u8 *buffer = NULL;
|
u8 *buffer = NULL;
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
|
|
||||||
if(LoadFileToMem(tmdpath, &buffer, &size) < 0)
|
if (LoadFileToMem(tmdpath, &buffer, &size) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
signed_blob *s_tmd = (signed_blob *) buffer;
|
signed_blob *s_tmd = (signed_blob *)buffer;
|
||||||
|
|
||||||
u32 i;
|
u32 i;
|
||||||
tmd *titleTmd = (tmd *) SIGNATURE_PAYLOAD(s_tmd);
|
tmd *titleTmd = (tmd *)SIGNATURE_PAYLOAD(s_tmd);
|
||||||
|
|
||||||
for (i = 0; i < titleTmd->num_contents; i++)
|
for (i = 0; i < titleTmd->num_contents; i++)
|
||||||
if (!titleTmd->contents[i].index)
|
if (!titleTmd->contents[i].index)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(i == titleTmd->num_contents)
|
if (i == titleTmd->num_contents)
|
||||||
{
|
{
|
||||||
free(buffer);
|
free(buffer);
|
||||||
return false;
|
return false;
|
||||||
@ -476,14 +493,14 @@ bool Channels::emuExists(char *tmdpath)
|
|||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
char *ptr = strrchr(tmdpath, '/');
|
char *ptr = strrchr(tmdpath, '/');
|
||||||
if(!ptr)
|
if (!ptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//! tmdpath has length of 1024
|
//! tmdpath has length of 1024
|
||||||
snprintf(ptr+1, 1024-(ptr+1-tmdpath), "%08x.app", (unsigned int)cid);
|
snprintf(ptr + 1, 1024 - (ptr + 1 - tmdpath), "%08x.app", (unsigned int)cid);
|
||||||
|
|
||||||
FILE *f = fopen(tmdpath, "rb");
|
FILE *f = fopen(tmdpath, "rb");
|
||||||
if(!f)
|
if (!f)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
@ -493,18 +510,18 @@ bool Channels::emuExists(char *tmdpath)
|
|||||||
|
|
||||||
bool Channels::ParseTitleDir(char *path, int language)
|
bool Channels::ParseTitleDir(char *path, int language)
|
||||||
{
|
{
|
||||||
if(!path)
|
if (!path)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const char *tidPtr = strrchr(path, '/');
|
const char *tidPtr = strrchr(path, '/');
|
||||||
if(!tidPtr)
|
if (!tidPtr)
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
tidPtr++;
|
tidPtr++;
|
||||||
|
|
||||||
struct dirent *dirent = NULL;
|
struct dirent *dirent = NULL;
|
||||||
DIR *dir = opendir(path);
|
DIR *dir = opendir(path);
|
||||||
if(!dir)
|
if (!dir)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
char *pathEndPtr = path + strlen(path);
|
char *pathEndPtr = path + strlen(path);
|
||||||
@ -514,22 +531,22 @@ bool Channels::ParseTitleDir(char *path, int language)
|
|||||||
|
|
||||||
while ((dirent = readdir(dir)) != 0)
|
while ((dirent = readdir(dir)) != 0)
|
||||||
{
|
{
|
||||||
if(!dirent->d_name)
|
if (!dirent->d_name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//these can't be booted anyways
|
//these can't be booted anyways
|
||||||
if(*dirent->d_name == '.' || strcmp(dirent->d_name, "48414141") == 0 || strcmp(dirent->d_name, "48414641") == 0)
|
if (*dirent->d_name == '.' || strcmp(dirent->d_name, "48414141") == 0 || strcmp(dirent->d_name, "48414641") == 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(pathEndPtr, 1024-(pathEndPtr-path), "/%s/content/title.tmd", dirent->d_name);
|
snprintf(pathEndPtr, 1024 - (pathEndPtr - path), "/%s/content/title.tmd", dirent->d_name);
|
||||||
|
|
||||||
if(stat(path, &st) != 0)
|
if (stat(path, &st) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// check if content in tmd exists
|
// check if content in tmd exists
|
||||||
if(!emuExists(path))
|
if (!emuExists(path))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
u32 tidLow = strtoul(dirent->d_name, NULL, 16);
|
u32 tidLow = strtoul(dirent->d_name, NULL, 16);
|
||||||
@ -537,20 +554,20 @@ bool Channels::ParseTitleDir(char *path, int language)
|
|||||||
memset(id, 0, sizeof(id));
|
memset(id, 0, sizeof(id));
|
||||||
memcpy(id, &tidLow, 4);
|
memcpy(id, &tidLow, 4);
|
||||||
|
|
||||||
u64 tid = ((u64)tidHigh << 32) | ((u64) tidLow);
|
u64 tid = ((u64)tidHigh << 32) | ((u64)tidLow);
|
||||||
|
|
||||||
// Force old and new format to be "JODI" which is known by GameTDB
|
// Force old and new format to be "JODI" which is known by GameTDB
|
||||||
if(tid == 0x000100014c554c5aLL || tid == 0x00010001AF1BF516LL || tid == 0x0001000148415858LL)
|
if (tid == 0x000100014c554c5aLL || tid == 0x00010001AF1BF516LL || tid == 0x0001000148415858LL)
|
||||||
strcpy(id, "JODI");
|
strcpy(id, "JODI");
|
||||||
|
|
||||||
std::string TitleName;
|
std::string TitleName;
|
||||||
|
|
||||||
const char *title = GameTitles.GetTitle(id);
|
const char *title = GameTitles.GetTitle(id);
|
||||||
if(title && *title != '\0')
|
if (title && *title != '\0')
|
||||||
{
|
{
|
||||||
TitleName = title;
|
TitleName = title;
|
||||||
}
|
}
|
||||||
else if(GetEmuChanTitle(path, language, TitleName))
|
else if (GetEmuChanTitle(path, language, TitleName))
|
||||||
{
|
{
|
||||||
GameTitles.SetGameTitle(id, TitleName.c_str());
|
GameTitles.SetGameTitle(id, TitleName.c_str());
|
||||||
}
|
}
|
||||||
@ -565,7 +582,7 @@ bool Channels::ParseTitleDir(char *path, int language)
|
|||||||
memcpy(EmuChannels[s].id, id, 4);
|
memcpy(EmuChannels[s].id, id, 4);
|
||||||
EmuChannels[s].tid = tid;
|
EmuChannels[s].tid = tid;
|
||||||
EmuChannels[s].type = TYPE_GAME_EMUNANDCHAN;
|
EmuChannels[s].type = TYPE_GAME_EMUNANDCHAN;
|
||||||
strncpy(EmuChannels[s].title, TitleName.c_str(), sizeof(EmuChannels[s].title)-1);
|
strncpy(EmuChannels[s].title, TitleName.c_str(), sizeof(EmuChannels[s].title) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
@ -578,19 +595,19 @@ bool Channels::GetEmuChanTitle(char *tmdpath, int language, std::string &Title)
|
|||||||
u8 *buffer = NULL;
|
u8 *buffer = NULL;
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
|
|
||||||
if(LoadFileToMem(tmdpath, &buffer, &size) < 0)
|
if (LoadFileToMem(tmdpath, &buffer, &size) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
signed_blob *s_tmd = (signed_blob *) buffer;
|
signed_blob *s_tmd = (signed_blob *)buffer;
|
||||||
|
|
||||||
u32 i;
|
u32 i;
|
||||||
tmd *titleTmd = (tmd *) SIGNATURE_PAYLOAD(s_tmd);
|
tmd *titleTmd = (tmd *)SIGNATURE_PAYLOAD(s_tmd);
|
||||||
|
|
||||||
for (i = 0; i < titleTmd->num_contents; i++)
|
for (i = 0; i < titleTmd->num_contents; i++)
|
||||||
if (!titleTmd->contents[i].index)
|
if (!titleTmd->contents[i].index)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(i == titleTmd->num_contents)
|
if (i == titleTmd->num_contents)
|
||||||
{
|
{
|
||||||
free(buffer);
|
free(buffer);
|
||||||
return false;
|
return false;
|
||||||
@ -601,30 +618,30 @@ bool Channels::GetEmuChanTitle(char *tmdpath, int language, std::string &Title)
|
|||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
char *ptr = strrchr(tmdpath, '/');
|
char *ptr = strrchr(tmdpath, '/');
|
||||||
if(!ptr)
|
if (!ptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//! tmdpath has length of 1024
|
//! tmdpath has length of 1024
|
||||||
snprintf(ptr+1, 1024-(ptr+1-tmdpath), "%08x.app", (unsigned int)cid);
|
snprintf(ptr + 1, 1024 - (ptr + 1 - tmdpath), "%08x.app", (unsigned int)cid);
|
||||||
|
|
||||||
FILE *f = fopen(tmdpath, "rb");
|
FILE *f = fopen(tmdpath, "rb");
|
||||||
if(!f)
|
if (!f)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(fseek(f, IMET_OFFSET, SEEK_SET) != 0)
|
if (fseek(f, IMET_OFFSET, SEEK_SET) != 0)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMET *imet = (IMET*) malloc(sizeof(IMET));
|
IMET *imet = (IMET *)malloc(sizeof(IMET));
|
||||||
if(!imet)
|
if (!imet)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fread(imet, 1, sizeof(IMET), f) != sizeof(IMET))
|
if (fread(imet, 1, sizeof(IMET), f) != sizeof(IMET))
|
||||||
{
|
{
|
||||||
free(imet);
|
free(imet);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
@ -642,7 +659,7 @@ bool Channels::GetEmuChanTitle(char *tmdpath, int language, std::string &Title)
|
|||||||
// names not available
|
// names not available
|
||||||
if (imet->name_japanese[language * IMET_MAX_NAME_LEN] == 0)
|
if (imet->name_japanese[language * IMET_MAX_NAME_LEN] == 0)
|
||||||
{
|
{
|
||||||
if(imet->name_english[0] != 0)
|
if (imet->name_english[0] != 0)
|
||||||
language = CONF_LANG_ENGLISH;
|
language = CONF_LANG_ENGLISH;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -665,14 +682,14 @@ bool Channels::GetEmuChanTitle(char *tmdpath, int language, std::string &Title)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 *Channels::GetOpeningBnr(const u64 &title, u32 * outsize, const char *pathPrefix)
|
u8 *Channels::GetOpeningBnr(const u64 &title, u32 *outsize, const char *pathPrefix)
|
||||||
{
|
{
|
||||||
u8 *banner = NULL;
|
u8 *banner = NULL;
|
||||||
u32 high = TITLE_UPPER(title);
|
u32 high = TITLE_UPPER(title);
|
||||||
u32 low = TITLE_LOWER(title);
|
u32 low = TITLE_LOWER(title);
|
||||||
|
|
||||||
char *filepath = (char *) memalign(32, ISFS_MAXPATH + strlen(pathPrefix));
|
char *filepath = (char *)memalign(32, ISFS_MAXPATH + strlen(pathPrefix));
|
||||||
if(!filepath)
|
if (!filepath)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -684,7 +701,7 @@ u8 *Channels::GetOpeningBnr(const u64 &title, u32 * outsize, const char *pathPre
|
|||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if(pathPrefix && *pathPrefix != 0)
|
if (pathPrefix && *pathPrefix != 0)
|
||||||
ret = LoadFileToMem(filepath, &buffer, &filesize);
|
ret = LoadFileToMem(filepath, &buffer, &filesize);
|
||||||
else
|
else
|
||||||
ret = NandTitle::LoadFileFromNand(filepath, &buffer, &filesize);
|
ret = NandTitle::LoadFileFromNand(filepath, &buffer, &filesize);
|
||||||
@ -692,12 +709,12 @@ u8 *Channels::GetOpeningBnr(const u64 &title, u32 * outsize, const char *pathPre
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
_tmd * tmd_file = (_tmd *) SIGNATURE_PAYLOAD((u32 *)buffer);
|
_tmd *tmd_file = (_tmd *)SIGNATURE_PAYLOAD((u32 *)buffer);
|
||||||
bool found = false;
|
bool found = false;
|
||||||
u32 bootcontent = 0;
|
u32 bootcontent = 0;
|
||||||
for(u32 i = 0; i < tmd_file->num_contents; ++i)
|
for (u32 i = 0; i < tmd_file->num_contents; ++i)
|
||||||
{
|
{
|
||||||
if(tmd_file->contents[i].index == 0)
|
if (tmd_file->contents[i].index == 0)
|
||||||
{
|
{
|
||||||
bootcontent = tmd_file->contents[i].cid;
|
bootcontent = tmd_file->contents[i].cid;
|
||||||
found = true;
|
found = true;
|
||||||
@ -709,12 +726,12 @@ u8 *Channels::GetOpeningBnr(const u64 &title, u32 * outsize, const char *pathPre
|
|||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
filesize = 0;
|
filesize = 0;
|
||||||
|
|
||||||
if(!found)
|
if (!found)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
snprintf(filepath, ISFS_MAXPATH, "%s/title/%08x/%08x/content/%08x.app", pathPrefix, (unsigned int)high, (unsigned int)low, (unsigned int)bootcontent);
|
snprintf(filepath, ISFS_MAXPATH, "%s/title/%08x/%08x/content/%08x.app", pathPrefix, (unsigned int)high, (unsigned int)low, (unsigned int)bootcontent);
|
||||||
|
|
||||||
if(pathPrefix && *pathPrefix != 0)
|
if (pathPrefix && *pathPrefix != 0)
|
||||||
ret = LoadFileToMem(filepath, &buffer, &filesize);
|
ret = LoadFileToMem(filepath, &buffer, &filesize);
|
||||||
else
|
else
|
||||||
ret = NandTitle::LoadFileFromNand(filepath, &buffer, &filesize);
|
ret = NandTitle::LoadFileFromNand(filepath, &buffer, &filesize);
|
||||||
@ -722,8 +739,8 @@ u8 *Channels::GetOpeningBnr(const u64 &title, u32 * outsize, const char *pathPre
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
IMET *imet = (IMET *) (buffer + IMET_OFFSET);
|
IMET *imet = (IMET *)(buffer + IMET_OFFSET);
|
||||||
if(imet->sig != 'IMET')
|
if (imet->sig != 'IMET')
|
||||||
{
|
{
|
||||||
free(buffer);
|
free(buffer);
|
||||||
break;
|
break;
|
||||||
@ -732,8 +749,8 @@ u8 *Channels::GetOpeningBnr(const u64 &title, u32 * outsize, const char *pathPre
|
|||||||
// move IMET_OFFSET bytes back
|
// move IMET_OFFSET bytes back
|
||||||
filesize -= IMET_OFFSET;
|
filesize -= IMET_OFFSET;
|
||||||
|
|
||||||
banner = (u8 *) memalign(32, filesize);
|
banner = (u8 *)memalign(32, filesize);
|
||||||
if(!banner)
|
if (!banner)
|
||||||
{
|
{
|
||||||
free(buffer);
|
free(buffer);
|
||||||
break;
|
break;
|
||||||
@ -743,10 +760,9 @@ u8 *Channels::GetOpeningBnr(const u64 &title, u32 * outsize, const char *pathPre
|
|||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
if(outsize)
|
if (outsize)
|
||||||
*outsize = filesize;
|
*outsize = filesize;
|
||||||
}
|
} while (0);
|
||||||
while(0);
|
|
||||||
|
|
||||||
free(filepath);
|
free(filepath);
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "GCGames.h"
|
#include "GCGames.h"
|
||||||
#include "FileOperations/fileops.h"
|
#include "FileOperations/fileops.h"
|
||||||
#include "settings/GameTitles.h"
|
#include "settings/GameTitles.h"
|
||||||
@ -30,13 +31,14 @@
|
|||||||
#include "system/IosLoader.h"
|
#include "system/IosLoader.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "gecko.h"
|
#include "gecko.h"
|
||||||
|
#include "cache/cache.hpp"
|
||||||
|
|
||||||
GCGames *GCGames::instance = NULL;
|
GCGames *GCGames::instance = NULL;
|
||||||
|
|
||||||
inline bool isGameID(const u8 *id)
|
inline bool isGameID(const u8 *id)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
if (!isalnum((int) id[i]))
|
if (!isalnum((int)id[i]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -44,12 +46,12 @@ inline bool isGameID(const u8 *id)
|
|||||||
|
|
||||||
const char *GCGames::GetPath(const char *gameID) const
|
const char *GCGames::GetPath(const char *gameID) const
|
||||||
{
|
{
|
||||||
if(!gameID)
|
if (!gameID)
|
||||||
return "";
|
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();
|
return PathList[i].c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,15 +70,17 @@ void GCGames::LoadGameList(const string &path, vector<struct discHdr> &headerLis
|
|||||||
struct dirent *dirent;
|
struct dirent *dirent;
|
||||||
|
|
||||||
dir_iter = opendir(path.c_str());
|
dir_iter = opendir(path.c_str());
|
||||||
if (!dir_iter) return;
|
if (!dir_iter)
|
||||||
|
return;
|
||||||
|
|
||||||
while ((dirent = readdir(dir_iter)) != 0)
|
while ((dirent = readdir(dir_iter)) != 0)
|
||||||
{
|
{
|
||||||
const char *dirname = dirent->d_name;
|
const char *dirname = dirent->d_name;
|
||||||
if(!dirname)
|
if (!dirname)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (dirname[0] == '.') continue;
|
if (dirname[0] == '.')
|
||||||
|
continue;
|
||||||
|
|
||||||
// reset id and title
|
// reset id and title
|
||||||
memset(id, 0, sizeof(id));
|
memset(id, 0, sizeof(id));
|
||||||
@ -87,7 +91,7 @@ void GCGames::LoadGameList(const string &path, vector<struct discHdr> &headerLis
|
|||||||
int len = strlen(dirname);
|
int len = strlen(dirname);
|
||||||
if (len >= 8)
|
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
|
// path/TITLE[GAMEID]/game.iso
|
||||||
lay_b = true;
|
lay_b = true;
|
||||||
@ -97,42 +101,43 @@ void GCGames::LoadGameList(const string &path, vector<struct discHdr> &headerLis
|
|||||||
// path/GAMEID_TITLE/game.iso
|
// path/GAMEID_TITLE/game.iso
|
||||||
memcpy(id, dirname, 6);
|
memcpy(id, dirname, 6);
|
||||||
|
|
||||||
if(isGameID(id))
|
if (isGameID(id))
|
||||||
{
|
{
|
||||||
lay_a = true;
|
lay_a = true;
|
||||||
snprintf(fname_title, sizeof(fname_title), "%s", &dirname[7]);
|
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);
|
memcpy(id, dirname, 6);
|
||||||
lay_a = true;
|
lay_a = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!lay_a && !lay_b)
|
if (!lay_a && !lay_b)
|
||||||
memset(id, 0, sizeof(id));
|
memset(id, 0, sizeof(id));
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
bool extracted = false;
|
bool extracted = false;
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
char name[50];
|
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);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if only disc2.iso is present
|
// 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];
|
char name[50];
|
||||||
snprintf(name, sizeof(name), "disc2.%s", (i % 2) == 0 ? "gcm" : "iso"); // allow gcm, though DM(L) require "disc2.iso" filename
|
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);
|
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;
|
disc_number = 1;
|
||||||
break;
|
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);
|
snprintf(fpath, sizeof(fpath), "%s%s/sys/boot.bin", path.c_str(), dirname);
|
||||||
if(stat(fpath, &st) != 0)
|
if (stat(fpath, &st) != 0)
|
||||||
continue;
|
continue;
|
||||||
// this game is extracted
|
// this game is extracted
|
||||||
extracted = true;
|
extracted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! GAMEID was not found
|
//! GAMEID was not found
|
||||||
if(!lay_a && !lay_b) {
|
if (!lay_a && !lay_b)
|
||||||
|
{
|
||||||
// read game ID and title from disc header
|
// read game ID and title from disc header
|
||||||
// iso file
|
// iso file
|
||||||
FILE *fp = fopen(fpath, "rb");
|
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, '/'));
|
string gamePath = string(path) + dirname + (extracted ? "/" : strrchr(fpath, '/'));
|
||||||
memset(&tmpHdr, 0, sizeof(tmpHdr));
|
memset(&tmpHdr, 0, sizeof(tmpHdr));
|
||||||
memcpy(tmpHdr.id, id, 6);
|
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.magic = GCGames::MAGIC;
|
||||||
tmpHdr.type = extracted ? TYPE_GAME_GC_EXTRACTED : TYPE_GAME_GC_IMG;
|
tmpHdr.type = extracted ? TYPE_GAME_GC_EXTRACTED : TYPE_GAME_GC_IMG;
|
||||||
tmpHdr.disc_no = disc_number;
|
tmpHdr.disc_no = disc_number;
|
||||||
@ -217,29 +223,37 @@ void GCGames::LoadGameList(const string &path, vector<struct discHdr> &headerLis
|
|||||||
|
|
||||||
u32 GCGames::LoadAllGames(void)
|
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();
|
PathList.clear();
|
||||||
HeaderList.clear();
|
HeaderList.clear();
|
||||||
sdGCList.clear();
|
sdGCList.clear();
|
||||||
sdGCPathList.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);
|
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);
|
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;
|
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.
|
//! 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) ||
|
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
|
(Settings.GameCubeSource == GC_SOURCE_AUTO && (IosLoader::GetMIOSInfo() == DIOS_MIOS || IosLoader::GetMIOSInfo() == QUADFORCE_USB))) // DIOS MIOS - Show the game on USB in priority
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@ -254,7 +268,8 @@ u32 GCGames::LoadAllGames(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Not available in the main GC path
|
// Not available in the main GC path
|
||||||
if(n == HeaderList.size()) {
|
if (n == HeaderList.size())
|
||||||
|
{
|
||||||
HeaderList.push_back(sdGCList[i]);
|
HeaderList.push_back(sdGCList[i]);
|
||||||
PathList.push_back(sdGCPathList[i]);
|
PathList.push_back(sdGCPathList[i]);
|
||||||
}
|
}
|
||||||
@ -267,30 +282,33 @@ u32 GCGames::LoadAllGames(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Settings.UseGameHeaderCache && !HeaderList.empty() && !PathList.empty())
|
||||||
|
SaveGameHeaderCache(HeaderList, PathList);
|
||||||
|
|
||||||
return HeaderList.size();
|
return HeaderList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GCGames::RemoveGame(const char *gameID)
|
bool GCGames::RemoveGame(const char *gameID)
|
||||||
{
|
{
|
||||||
const char *path = GetPath(gameID);
|
const char *path = GetPath(gameID);
|
||||||
if(*path == 0)
|
if (*path == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
RemoveSDGame(gameID);
|
RemoveSDGame(gameID);
|
||||||
|
|
||||||
if(strcmp(Settings.GameCubePath, Settings.GameCubeSDPath) == 0)
|
if (strcmp(Settings.GameCubePath, Settings.GameCubeSDPath) == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
struct discHdr *header = NULL;
|
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];
|
header = &HeaderList[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!header)
|
if (!header)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
char filepath[512];
|
char filepath[512];
|
||||||
@ -300,24 +318,25 @@ bool GCGames::RemoveGame(const char *gameID)
|
|||||||
char cIsoPath[256];
|
char cIsoPath[256];
|
||||||
snprintf(cIsoPath, sizeof(cIsoPath), "%s", path + strlen(Settings.GameCubeSDPath));
|
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
|
// Remove game iso
|
||||||
snprintf(filepath, sizeof(filepath), "%s%s", Settings.GameCubePath, cIsoPath);
|
snprintf(filepath, sizeof(filepath), "%s%s", Settings.GameCubePath, cIsoPath);
|
||||||
if(!RemoveFile(filepath))
|
if (!RemoveFile(filepath))
|
||||||
result = -1;
|
result = -1;
|
||||||
|
|
||||||
// Remove path
|
// Remove path
|
||||||
char *pathPtr = strrchr(filepath, '/');
|
char *pathPtr = strrchr(filepath, '/');
|
||||||
if(pathPtr) *pathPtr = 0;
|
if (pathPtr)
|
||||||
if(!RemoveFile(filepath))
|
*pathPtr = 0;
|
||||||
|
if (!RemoveFile(filepath))
|
||||||
result = -1;
|
result = -1;
|
||||||
}
|
}
|
||||||
else if(header->type == TYPE_GAME_GC_EXTRACTED)
|
else if (header->type == TYPE_GAME_GC_EXTRACTED)
|
||||||
{
|
{
|
||||||
//! remove extracted gamecube game
|
//! remove extracted gamecube game
|
||||||
snprintf(filepath, sizeof(filepath), "%s%s", Settings.GameCubePath, cIsoPath);
|
snprintf(filepath, sizeof(filepath), "%s%s", Settings.GameCubePath, cIsoPath);
|
||||||
if(!RemoveDirectory(path))
|
if (!RemoveDirectory(path))
|
||||||
result = -1;
|
result = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,45 +346,46 @@ bool GCGames::RemoveGame(const char *gameID)
|
|||||||
bool GCGames::RemoveSDGame(const char *gameID)
|
bool GCGames::RemoveSDGame(const char *gameID)
|
||||||
{
|
{
|
||||||
const char *path = GetPath(gameID);
|
const char *path = GetPath(gameID);
|
||||||
if(*path == 0)
|
if (*path == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
struct discHdr *header = NULL;
|
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];
|
header = &HeaderList[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!header)
|
if (!header)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
char filepath[512];
|
char filepath[512];
|
||||||
int result = 0;
|
int result = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if(header->type == TYPE_GAME_GC_IMG)
|
if (header->type == TYPE_GAME_GC_IMG)
|
||||||
{
|
{
|
||||||
// Remove game iso
|
// Remove game iso
|
||||||
snprintf(filepath, sizeof(filepath), "%s", path);
|
snprintf(filepath, sizeof(filepath), "%s", path);
|
||||||
ret = RemoveFile(filepath);
|
ret = RemoveFile(filepath);
|
||||||
if(ret != 0)
|
if (ret != 0)
|
||||||
result = -1;
|
result = -1;
|
||||||
|
|
||||||
// Remove path
|
// Remove path
|
||||||
char *pathPtr = strrchr(filepath, '/');
|
char *pathPtr = strrchr(filepath, '/');
|
||||||
if(pathPtr) *pathPtr = 0;
|
if (pathPtr)
|
||||||
|
*pathPtr = 0;
|
||||||
ret = RemoveFile(filepath);
|
ret = RemoveFile(filepath);
|
||||||
if(ret != 0)
|
if (ret != 0)
|
||||||
result = -1;
|
result = -1;
|
||||||
}
|
}
|
||||||
else if(header->type == TYPE_GAME_GC_EXTRACTED)
|
else if (header->type == TYPE_GAME_GC_EXTRACTED)
|
||||||
{
|
{
|
||||||
//! remove extracted gamecube game
|
//! remove extracted gamecube game
|
||||||
ret = RemoveDirectory(path);
|
ret = RemoveDirectory(path);
|
||||||
if(ret < 0)
|
if (ret < 0)
|
||||||
result = -1;
|
result = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,39 +395,39 @@ bool GCGames::RemoveSDGame(const char *gameID)
|
|||||||
float GCGames::GetGameSize(const char *gameID)
|
float GCGames::GetGameSize(const char *gameID)
|
||||||
{
|
{
|
||||||
const char *path = GetPath(gameID);
|
const char *path = GetPath(gameID);
|
||||||
if(*path == 0)
|
if (*path == 0)
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if(stat(path, &st) != 0)
|
if (stat(path, &st) != 0)
|
||||||
return 0.0f;
|
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
|
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.
|
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;
|
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];
|
char filepath[512];
|
||||||
int n = snprintf(filepath, sizeof(filepath), "%s", GetPath(gameID));
|
int n = snprintf(filepath, sizeof(filepath), "%s", GetPath(gameID));
|
||||||
char *pathPtr = strrchr(filepath, '/');
|
char *pathPtr = strrchr(filepath, '/');
|
||||||
if(pathPtr) *pathPtr = 0;
|
if (pathPtr)
|
||||||
|
*pathPtr = 0;
|
||||||
snprintf(filepath + n, sizeof(filepath) - n, "/disc2.iso");
|
snprintf(filepath + n, sizeof(filepath) - n, "/disc2.iso");
|
||||||
|
if (CheckFile(filepath))
|
||||||
if(CheckFile(filepath))
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -417,18 +437,18 @@ bool GCGames::IsInstalled(const char *gameID, u8 disc_number) const
|
|||||||
|
|
||||||
bool GCGames::CopyUSB2SD(const struct discHdr *header)
|
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;
|
int oldGameCubeSource = Settings.GameCubeSource;
|
||||||
if(*path == 0)
|
if (*path == 0)
|
||||||
return false;
|
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"));
|
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;
|
return false;
|
||||||
|
|
||||||
const char *cpTitle = GameTitles.GetTitle(header);
|
const char *cpTitle = GameTitles.GetTitle(header);
|
||||||
|
|
||||||
if(choice == 2)
|
if (choice == 2)
|
||||||
{
|
{
|
||||||
// Load Games from SD card only
|
// Load Games from SD card only
|
||||||
Settings.GameCubeSource = GC_SOURCE_SD;
|
Settings.GameCubeSource = GC_SOURCE_SD;
|
||||||
@ -443,7 +463,8 @@ bool GCGames::CopyUSB2SD(const struct discHdr *header)
|
|||||||
gcDeleteMenu.Show();
|
gcDeleteMenu.Show();
|
||||||
|
|
||||||
gcDeleteMenu.SetEffect(EFFECT_FADE, -20);
|
gcDeleteMenu.SetEffect(EFFECT_FADE, -20);
|
||||||
while(gcDeleteMenu.GetEffect() > 0) usleep(1000);
|
while (gcDeleteMenu.GetEffect() > 0)
|
||||||
|
usleep(1000);
|
||||||
|
|
||||||
mainWindow->Remove(&gcDeleteMenu);
|
mainWindow->Remove(&gcDeleteMenu);
|
||||||
mainWindow->SetState(STATE_DEFAULT);
|
mainWindow->SetState(STATE_DEFAULT);
|
||||||
@ -452,12 +473,12 @@ bool GCGames::CopyUSB2SD(const struct discHdr *header)
|
|||||||
Settings.GameCubeSource = oldGameCubeSource;
|
Settings.GameCubeSource = oldGameCubeSource;
|
||||||
GCGames::Instance()->LoadAllGames();
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct statvfs sd_vfs;
|
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"));
|
WindowPrompt(tr("Error:"), tr("SD Card could not be accessed."), tr("OK"));
|
||||||
return false;
|
return false;
|
||||||
@ -465,20 +486,22 @@ bool GCGames::CopyUSB2SD(const struct discHdr *header)
|
|||||||
|
|
||||||
u64 filesize = 0;
|
u64 filesize = 0;
|
||||||
|
|
||||||
if(header->type == TYPE_GAME_GC_IMG) {
|
if (header->type == TYPE_GAME_GC_IMG)
|
||||||
|
{
|
||||||
filesize = FileSize(path);
|
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);
|
StartProgress(tr("Getting game folder size..."), tr("Please wait"), 0, true, true);
|
||||||
ShowProgress(0, 1);
|
ShowProgress(0, 1);
|
||||||
filesize = FileSize(path);
|
filesize = FileSize(path);
|
||||||
ProgressStop();
|
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"));
|
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;
|
return false;
|
||||||
|
|
||||||
GCDeleteMenu gcDeleteMenu;
|
GCDeleteMenu gcDeleteMenu;
|
||||||
@ -490,7 +513,8 @@ bool GCGames::CopyUSB2SD(const struct discHdr *header)
|
|||||||
gcDeleteMenu.Show();
|
gcDeleteMenu.Show();
|
||||||
|
|
||||||
gcDeleteMenu.SetEffect(EFFECT_FADE, -20);
|
gcDeleteMenu.SetEffect(EFFECT_FADE, -20);
|
||||||
while(gcDeleteMenu.GetEffect() > 0) usleep(1000);
|
while (gcDeleteMenu.GetEffect() > 0)
|
||||||
|
usleep(1000);
|
||||||
|
|
||||||
mainWindow->Remove(&gcDeleteMenu);
|
mainWindow->Remove(&gcDeleteMenu);
|
||||||
mainWindow->SetState(STATE_DEFAULT);
|
mainWindow->SetState(STATE_DEFAULT);
|
||||||
@ -504,13 +528,14 @@ bool GCGames::CopyUSB2SD(const struct discHdr *header)
|
|||||||
|
|
||||||
int res = -1;
|
int res = -1;
|
||||||
|
|
||||||
if(header->type == TYPE_GAME_GC_IMG)
|
if (header->type == TYPE_GAME_GC_IMG)
|
||||||
{
|
{
|
||||||
ProgressCancelEnable(true);
|
ProgressCancelEnable(true);
|
||||||
StartProgress(tr("Copying GC game..."), cpTitle, 0, true, true);
|
StartProgress(tr("Copying GC game..."), cpTitle, 0, true, true);
|
||||||
|
|
||||||
char *ptr = strrchr(destPath, '/');
|
char *ptr = strrchr(destPath, '/');
|
||||||
if(ptr) *ptr = 0;
|
if (ptr)
|
||||||
|
*ptr = 0;
|
||||||
|
|
||||||
CreateSubfolder(destPath);
|
CreateSubfolder(destPath);
|
||||||
|
|
||||||
@ -518,7 +543,7 @@ bool GCGames::CopyUSB2SD(const struct discHdr *header)
|
|||||||
|
|
||||||
res = CopyFile(path, destPath);
|
res = CopyFile(path, destPath);
|
||||||
}
|
}
|
||||||
else if(header->type == TYPE_GAME_GC_EXTRACTED)
|
else if (header->type == TYPE_GAME_GC_EXTRACTED)
|
||||||
{
|
{
|
||||||
res = CopyDirectory(path, destPath);
|
res = CopyDirectory(path, destPath);
|
||||||
}
|
}
|
||||||
@ -529,28 +554,30 @@ bool GCGames::CopyUSB2SD(const struct discHdr *header)
|
|||||||
ProgressStop();
|
ProgressStop();
|
||||||
ProgressCancelEnable(false);
|
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
|
// remove file and path
|
||||||
RemoveFile(destPath);
|
RemoveFile(destPath);
|
||||||
char *ptr = strrchr(destPath, '/');
|
char *ptr = strrchr(destPath, '/');
|
||||||
if(ptr) *ptr = 0;
|
if (ptr)
|
||||||
|
*ptr = 0;
|
||||||
RemoveFile(destPath);
|
RemoveFile(destPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowPrompt(tr("Copying Canceled"), 0, tr("OK"));
|
WindowPrompt(tr("Copying Canceled"), 0, tr("OK"));
|
||||||
return false;
|
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
|
// remove file and path
|
||||||
RemoveFile(destPath);
|
RemoveFile(destPath);
|
||||||
char *ptr = strrchr(destPath, '/');
|
char *ptr = strrchr(destPath, '/');
|
||||||
if(ptr) *ptr = 0;
|
if (ptr)
|
||||||
|
*ptr = 0;
|
||||||
RemoveFile(destPath);
|
RemoveFile(destPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,36 +595,36 @@ int nintendontBuildDate(const char *NIN_loader_path, char *NINBuildDate)
|
|||||||
|
|
||||||
char NIN_loader[100];
|
char NIN_loader[100];
|
||||||
snprintf(NIN_loader, sizeof(NIN_loader), "%sboot.dol", NIN_loader_path);
|
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);
|
snprintf(NIN_loader, sizeof(NIN_loader), "%sloader.dol", NIN_loader_path);
|
||||||
if(CheckFile(NIN_loader))
|
if (CheckFile(NIN_loader))
|
||||||
{
|
{
|
||||||
u8 *buffer = NULL;
|
u8 *buffer = NULL;
|
||||||
u32 filesize = 0;
|
u32 filesize = 0;
|
||||||
const char* str = "Nintendont Loader";
|
const char *str = "Nintendont Loader";
|
||||||
bool found = false;
|
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
|
// Write buffer in NINheader
|
||||||
char NINHeader[100];
|
char NINHeader[100];
|
||||||
for(u8 j = 0 ; j < 99 ; j++)
|
for (u8 j = 0; j < 99; j++)
|
||||||
NINHeader[j] = *(u8*)(buffer+i+j) == 0 ? ' ' : *(u8*)(buffer+i+j); // replace \0 with a space.
|
NINHeader[j] = *(u8 *)(buffer + i + j) == 0 ? ' ' : *(u8 *)(buffer + i + j); // replace \0 with a space.
|
||||||
NINHeader[99] = '\0';
|
NINHeader[99] = '\0';
|
||||||
|
|
||||||
// Search month string start position in header
|
// Search month string start position in header
|
||||||
char *dateStart = NULL;
|
char *dateStart = NULL;
|
||||||
const char *month[] = {"Jan ", "Feb ", "Mar ", "Apr ", "May ", "Jun ", "Jui ", "Aug ", "Sep ", "Oct ", "Nov ", "Dec "};
|
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]);
|
dateStart = strstr(NINHeader, month[m]);
|
||||||
if(dateStart != NULL)
|
if (dateStart != NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(dateStart == NULL)
|
if (dateStart == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
dateStart[20] = '\0';
|
dateStart[20] = '\0';
|
||||||
@ -611,7 +638,7 @@ int nintendontBuildDate(const char *NIN_loader_path, char *NINBuildDate)
|
|||||||
}
|
}
|
||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
if(found)
|
if (found)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,22 +650,22 @@ int nintendontVersion(const char *NIN_loader_path, char *NINVersion, int len)
|
|||||||
char NIN_loader[100];
|
char NIN_loader[100];
|
||||||
u32 NINRev = 0;
|
u32 NINRev = 0;
|
||||||
snprintf(NIN_loader, sizeof(NIN_loader), "%sboot.dol", NIN_loader_path);
|
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);
|
snprintf(NIN_loader, sizeof(NIN_loader), "%sloader.dol", NIN_loader_path);
|
||||||
if(CheckFile(NIN_loader))
|
if (CheckFile(NIN_loader))
|
||||||
{
|
{
|
||||||
u8 *buffer = NULL;
|
u8 *buffer = NULL;
|
||||||
u32 filesize = 0;
|
u32 filesize = 0;
|
||||||
const char* str = "$$Version:";
|
const char *str = "$$Version:";
|
||||||
if(LoadFileToMem(NIN_loader, &buffer, &filesize))
|
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
|
// Write buffer in NINVersion
|
||||||
snprintf(NINVersion, len, "%s", buffer+i+strlen(str));
|
snprintf(NINVersion, len, "%s", buffer + i + strlen(str));
|
||||||
NINRev = atoi(strchr(NINVersion, '.')+1);
|
NINRev = atoi(strchr(NINVersion, '.') + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
338
source/cache/cache.cpp
vendored
Normal file
338
source/cache/cache.cpp
vendored
Normal 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(>mp, 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(>mp, 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
54
source/cache/cache.hpp
vendored
Normal 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);
|
@ -11,6 +11,7 @@
|
|||||||
#include "themes/CTheme.h"
|
#include "themes/CTheme.h"
|
||||||
#include "utils/tools.h"
|
#include "utils/tools.h"
|
||||||
#include "system/IosLoader.h"
|
#include "system/IosLoader.h"
|
||||||
|
#include "cache/cache.hpp"
|
||||||
|
|
||||||
#define WII_MAGIC 0x5D1C9EA3
|
#define WII_MAGIC 0x5D1C9EA3
|
||||||
|
|
||||||
@ -287,6 +288,7 @@ int MenuInstall()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ShowProgress(tr("Install finished"), headerdisc.title, tr("Reloading game list now, please wait..."), gamesize, gamesize, true, true);
|
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.ReadGameList(); //get the entries again
|
||||||
gameList.FilterList();
|
gameList.FilterList();
|
||||||
bgMusic->Pause();
|
bgMusic->Pause();
|
||||||
|
@ -63,6 +63,7 @@ void CSettings::SetDefault()
|
|||||||
snprintf(languagefiles_path, sizeof(languagefiles_path), "%slanguage/", ConfigPath);
|
snprintf(languagefiles_path, sizeof(languagefiles_path), "%slanguage/", ConfigPath);
|
||||||
snprintf(update_path, sizeof(update_path), "%s/apps/usbloader_gx/", BootDevice);
|
snprintf(update_path, sizeof(update_path), "%s/apps/usbloader_gx/", BootDevice);
|
||||||
snprintf(BNRCachePath, sizeof(BNRCachePath), "%s/apps/usbloader_gx/cache_bnr/", 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(homebrewapps_path, sizeof(homebrewapps_path), "%s/apps/", BootDevice);
|
||||||
snprintf(Cheatcodespath, sizeof(Cheatcodespath), "%s/codes/", BootDevice);
|
snprintf(Cheatcodespath, sizeof(Cheatcodespath), "%s/codes/", BootDevice);
|
||||||
snprintf(TxtCheatcodespath, sizeof(TxtCheatcodespath), "%s/txtcodes/", BootDevice);
|
snprintf(TxtCheatcodespath, sizeof(TxtCheatcodespath), "%s/txtcodes/", BootDevice);
|
||||||
@ -135,6 +136,7 @@ void CSettings::SetDefault()
|
|||||||
musicloopmode = ON;
|
musicloopmode = ON;
|
||||||
marknewtitles = ON;
|
marknewtitles = ON;
|
||||||
ShowFreeSpace = ON;
|
ShowFreeSpace = ON;
|
||||||
|
UseGameHeaderCache = OFF;
|
||||||
PlaylogUpdate = OFF;
|
PlaylogUpdate = OFF;
|
||||||
ParentalBlocks = BLOCK_ALL;
|
ParentalBlocks = BLOCK_ALL;
|
||||||
InstallToDir = INSTALL_TO_NAME_GAMEID;
|
InstallToDir = INSTALL_TO_NAME_GAMEID;
|
||||||
@ -359,6 +361,7 @@ bool CSettings::Save()
|
|||||||
fprintf(file, "update_path = %s\n", update_path);
|
fprintf(file, "update_path = %s\n", update_path);
|
||||||
fprintf(file, "homebrewapps_path = %s\n", homebrewapps_path);
|
fprintf(file, "homebrewapps_path = %s\n", homebrewapps_path);
|
||||||
fprintf(file, "BNRCachePath = %s\n", BNRCachePath);
|
fprintf(file, "BNRCachePath = %s\n", BNRCachePath);
|
||||||
|
fprintf(file, "GameHeaderCachePath = %s\n", GameHeaderCachePath);
|
||||||
fprintf(file, "Cheatcodespath = %s\n", Cheatcodespath);
|
fprintf(file, "Cheatcodespath = %s\n", Cheatcodespath);
|
||||||
fprintf(file, "BcaCodepath = %s\n", BcaCodepath);
|
fprintf(file, "BcaCodepath = %s\n", BcaCodepath);
|
||||||
fprintf(file, "WipCodepath = %s\n", WipCodepath);
|
fprintf(file, "WipCodepath = %s\n", WipCodepath);
|
||||||
@ -374,6 +377,7 @@ bool CSettings::Save()
|
|||||||
fprintf(file, "partition = %d\n", partition);
|
fprintf(file, "partition = %d\n", partition);
|
||||||
fprintf(file, "marknewtitles = %d\n", marknewtitles);
|
fprintf(file, "marknewtitles = %d\n", marknewtitles);
|
||||||
fprintf(file, "ShowFreeSpace = %d\n", ShowFreeSpace);
|
fprintf(file, "ShowFreeSpace = %d\n", ShowFreeSpace);
|
||||||
|
fprintf(file, "UseGameHeaderCache = %d\n", UseGameHeaderCache);
|
||||||
fprintf(file, "InstallToDir = %d\n", InstallToDir);
|
fprintf(file, "InstallToDir = %d\n", InstallToDir);
|
||||||
fprintf(file, "GameSplit = %d\n", GameSplit);
|
fprintf(file, "GameSplit = %d\n", GameSplit);
|
||||||
fprintf(file, "InstallPartitions = %08X\n", (unsigned int)InstallPartitions);
|
fprintf(file, "InstallPartitions = %08X\n", (unsigned int)InstallPartitions);
|
||||||
@ -724,6 +728,11 @@ bool CSettings::SetSetting(char *name, char *value)
|
|||||||
ShowFreeSpace = atoi(value);
|
ShowFreeSpace = atoi(value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(name, "UseGameHeaderCache") == 0)
|
||||||
|
{
|
||||||
|
UseGameHeaderCache = atoi(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else if (strcmp(name, "HomeMenu") == 0)
|
else if (strcmp(name, "HomeMenu") == 0)
|
||||||
{
|
{
|
||||||
HomeMenu = atoi(value);
|
HomeMenu = atoi(value);
|
||||||
@ -1238,6 +1247,11 @@ bool CSettings::SetSetting(char *name, char *value)
|
|||||||
strlcpy(BNRCachePath, value, sizeof(BNRCachePath));
|
strlcpy(BNRCachePath, value, sizeof(BNRCachePath));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(name, "GameHeaderCachePath") == 0)
|
||||||
|
{
|
||||||
|
strlcpy(GameHeaderCachePath, value, sizeof(GameHeaderCachePath));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else if (strcmp(name, "Cheatcodespath") == 0)
|
else if (strcmp(name, "Cheatcodespath") == 0)
|
||||||
{
|
{
|
||||||
strlcpy(Cheatcodespath, value, sizeof(Cheatcodespath));
|
strlcpy(Cheatcodespath, value, sizeof(Cheatcodespath));
|
||||||
|
@ -85,6 +85,7 @@ class CSettings
|
|||||||
char NandEmuPath[50];
|
char NandEmuPath[50];
|
||||||
char NandEmuChanPath[50];
|
char NandEmuChanPath[50];
|
||||||
char BNRCachePath[50];
|
char BNRCachePath[50];
|
||||||
|
char GameHeaderCachePath[50];
|
||||||
char GameCubePath[100];
|
char GameCubePath[100];
|
||||||
char GameCubeSDPath[100];
|
char GameCubeSDPath[100];
|
||||||
char DEVOLoaderPath[100];
|
char DEVOLoaderPath[100];
|
||||||
@ -142,6 +143,7 @@ class CSettings
|
|||||||
short GameSplit;
|
short GameSplit;
|
||||||
short PlaylogUpdate;
|
short PlaylogUpdate;
|
||||||
short ShowFreeSpace;
|
short ShowFreeSpace;
|
||||||
|
short UseGameHeaderCache;
|
||||||
short HomeMenu;
|
short HomeMenu;
|
||||||
short MultiplePartitions;
|
short MultiplePartitions;
|
||||||
short USBPort;
|
short USBPort;
|
||||||
|
@ -65,6 +65,7 @@ CustomPathsSM::CustomPathsSM()
|
|||||||
Options->SetName(Idx++, tr("Devolution Loader Path"));
|
Options->SetName(Idx++, tr("Devolution Loader Path"));
|
||||||
Options->SetName(Idx++, tr("Nintendont Loader Path"));
|
Options->SetName(Idx++, tr("Nintendont Loader Path"));
|
||||||
Options->SetName(Idx++, tr("Cache BNR Files Path"));
|
Options->SetName(Idx++, tr("Cache BNR Files Path"));
|
||||||
|
Options->SetName(Idx++, tr("Game Header Cache Files Path"));
|
||||||
|
|
||||||
SetOptionValues();
|
SetOptionValues();
|
||||||
}
|
}
|
||||||
@ -141,6 +142,9 @@ void CustomPathsSM::SetOptionValues()
|
|||||||
|
|
||||||
//! Settings: Cache BNR Files Path
|
//! Settings: Cache BNR Files Path
|
||||||
Options->SetValue(Idx++, Settings.BNRCachePath);
|
Options->SetValue(Idx++, Settings.BNRCachePath);
|
||||||
|
|
||||||
|
//! Settings: Game Header Cache Files Path
|
||||||
|
Options->SetValue(Idx++, Settings.GameHeaderCachePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CustomPathsSM::GetMenuInternal()
|
int CustomPathsSM::GetMenuInternal()
|
||||||
@ -368,6 +372,13 @@ int CustomPathsSM::GetMenuInternal()
|
|||||||
ChangePath(Settings.BNRCachePath, sizeof(Settings.BNRCachePath));
|
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
|
//! Global set back of the titleTxt after a change
|
||||||
titleTxt->SetText(tr( "Custom Paths" ));
|
titleTxt->SetText(tr( "Custom Paths" ));
|
||||||
SetOptionValues();
|
SetOptionValues();
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
#include <ogc/machine/processor.h>
|
#include <ogc/machine/processor.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "FeatureSettingsMenu.hpp"
|
#include "FeatureSettingsMenu.hpp"
|
||||||
#include "Channels/channels.h"
|
#include "Channels/channels.h"
|
||||||
#include "settings/CGameCategories.hpp"
|
#include "settings/CGameCategories.hpp"
|
||||||
@ -44,6 +45,7 @@
|
|||||||
#include "wad/nandtitle.h"
|
#include "wad/nandtitle.h"
|
||||||
#include "wad/wad.h"
|
#include "wad/wad.h"
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
|
#include "cache/cache.hpp"
|
||||||
|
|
||||||
static const char * OnOffText[] =
|
static const char * OnOffText[] =
|
||||||
{
|
{
|
||||||
@ -64,6 +66,7 @@ FeatureSettingsMenu::FeatureSettingsMenu()
|
|||||||
int Idx = 0;
|
int Idx = 0;
|
||||||
Options->SetName(Idx++, "%s", tr( "Titles from GameTDB" ));
|
Options->SetName(Idx++, "%s", tr( "Titles from GameTDB" ));
|
||||||
Options->SetName(Idx++, "%s", tr( "Cache Titles" ));
|
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( "Force Titles from Disc" ));
|
||||||
Options->SetName(Idx++, "%s", tr( "Wiilight" ));
|
Options->SetName(Idx++, "%s", tr( "Wiilight" ));
|
||||||
Options->SetName(Idx++, "%s", tr( "Rumble" ));
|
Options->SetName(Idx++, "%s", tr( "Rumble" ));
|
||||||
@ -80,6 +83,7 @@ FeatureSettingsMenu::FeatureSettingsMenu()
|
|||||||
// Options->SetName(Idx++, "%s", tr( "Update Nintendont" ));
|
// Options->SetName(Idx++, "%s", tr( "Update Nintendont" ));
|
||||||
Options->SetName(Idx++, "%s", tr( "WiiU Widescreen" ));
|
Options->SetName(Idx++, "%s", tr( "WiiU Widescreen" ));
|
||||||
Options->SetName(Idx++, "%s", tr( "Boot Neek System Menu" ));
|
Options->SetName(Idx++, "%s", tr( "Boot Neek System Menu" ));
|
||||||
|
Options->SetName(Idx++, "%s", tr( "Reset Game Header Cache" ));
|
||||||
|
|
||||||
OldTitlesOverride = Settings.titlesOverride;
|
OldTitlesOverride = Settings.titlesOverride;
|
||||||
OldCacheTitles = Settings.CacheTitles;
|
OldCacheTitles = Settings.CacheTitles;
|
||||||
@ -121,6 +125,9 @@ void FeatureSettingsMenu::SetOptionValues()
|
|||||||
//! Settings: Cache Titles
|
//! Settings: Cache Titles
|
||||||
Options->SetValue(Idx++, "%s", tr( OnOffText[Settings.CacheTitles] ));
|
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
|
//! Settings: Force Titles from Disc
|
||||||
Options->SetValue(Idx++, "%s", tr( OnOffText[Settings.ForceDiscTitles] ));
|
Options->SetValue(Idx++, "%s", tr( OnOffText[Settings.ForceDiscTitles] ));
|
||||||
|
|
||||||
@ -193,6 +200,12 @@ int FeatureSettingsMenu::GetMenuInternal()
|
|||||||
if (++Settings.CacheTitles >= MAX_ON_OFF) Settings.CacheTitles = 0;
|
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
|
//! Settings: Force Titles from Disc
|
||||||
else if (ret == ++Idx)
|
else if (ret == ++Idx)
|
||||||
{
|
{
|
||||||
@ -532,6 +545,7 @@ int FeatureSettingsMenu::GetMenuInternal()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Refresh new EmuNAND content
|
// Refresh new EmuNAND content
|
||||||
|
ResetGameHeaderCache();
|
||||||
Channels::Instance()->GetEmuChannelList();
|
Channels::Instance()->GetEmuChannelList();
|
||||||
GameTitles.LoadTitlesFromGameTDB(Settings.titlestxt_path);
|
GameTitles.LoadTitlesFromGameTDB(Settings.titlestxt_path);
|
||||||
}
|
}
|
||||||
@ -622,6 +636,7 @@ int FeatureSettingsMenu::GetMenuInternal()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Refresh new EmuNAND content
|
// Refresh new EmuNAND content
|
||||||
|
ResetGameHeaderCache();
|
||||||
Channels::Instance()->GetEmuChannelList();
|
Channels::Instance()->GetEmuChannelList();
|
||||||
GameTitles.LoadTitlesFromGameTDB(Settings.titlestxt_path);
|
GameTitles.LoadTitlesFromGameTDB(Settings.titlestxt_path);
|
||||||
}
|
}
|
||||||
@ -744,6 +759,17 @@ int FeatureSettingsMenu::GetMenuInternal()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! 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();
|
SetOptionValues();
|
||||||
|
|
||||||
return MENU_NONE;
|
return MENU_NONE;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
* distribution.
|
* distribution.
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "UninstallSM.hpp"
|
#include "UninstallSM.hpp"
|
||||||
#include "FileOperations/fileops.h"
|
#include "FileOperations/fileops.h"
|
||||||
#include "GameCube/GCGames.h"
|
#include "GameCube/GCGames.h"
|
||||||
@ -35,6 +36,7 @@
|
|||||||
#include "usbloader/wbfs.h"
|
#include "usbloader/wbfs.h"
|
||||||
#include "usbloader/GameList.h"
|
#include "usbloader/GameList.h"
|
||||||
#include "wstring.hpp"
|
#include "wstring.hpp"
|
||||||
|
#include "cache/cache.hpp"
|
||||||
|
|
||||||
UninstallSM::UninstallSM(struct discHdr * header)
|
UninstallSM::UninstallSM(struct discHdr * header)
|
||||||
: SettingsMenu(tr("Uninstall Menu"), &GuiOptions, MENU_NONE)
|
: SettingsMenu(tr("Uninstall Menu"), &GuiOptions, MENU_NONE)
|
||||||
@ -127,6 +129,7 @@ int UninstallSM::GetMenuInternal()
|
|||||||
if(ret >= 0)
|
if(ret >= 0)
|
||||||
{
|
{
|
||||||
wString oldFilter(gameList.GetCurrentFilter());
|
wString oldFilter(gameList.GetCurrentFilter());
|
||||||
|
ResetGameHeaderCache();
|
||||||
gameList.ReadGameList();
|
gameList.ReadGameList();
|
||||||
gameList.FilterList(oldFilter.c_str());
|
gameList.FilterList(oldFilter.c_str());
|
||||||
}
|
}
|
||||||
@ -134,6 +137,7 @@ int UninstallSM::GetMenuInternal()
|
|||||||
else if(DiscHeader->type == TYPE_GAME_GC_IMG)
|
else if(DiscHeader->type == TYPE_GAME_GC_IMG)
|
||||||
{
|
{
|
||||||
GCGames::Instance()->RemoveGame(GameID);
|
GCGames::Instance()->RemoveGame(GameID);
|
||||||
|
ResetGameHeaderCache();
|
||||||
// Reload list
|
// Reload list
|
||||||
GCGames::Instance()->LoadAllGames();
|
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);
|
snprintf(filepath, sizeof(filepath), "%s/title/%08x/%08x/", Settings.NandEmuChanPath, (unsigned int) (DiscHeader->tid >> 32), (unsigned int) DiscHeader->tid);
|
||||||
RemoveDirectory(filepath);
|
RemoveDirectory(filepath);
|
||||||
|
|
||||||
|
ResetGameHeaderCache();
|
||||||
Channels::Instance()->GetEmuChannelList();
|
Channels::Instance()->GetEmuChannelList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
|
||||||
#include "GUI/gui_searchbar.h"
|
#include "GUI/gui_searchbar.h"
|
||||||
#include "usbloader/wbfs.h"
|
#include "usbloader/wbfs.h"
|
||||||
#include "GameCube/GCGames.h"
|
#include "GameCube/GCGames.h"
|
||||||
@ -37,8 +38,14 @@
|
|||||||
#include "GameList.h"
|
#include "GameList.h"
|
||||||
#include "memory/memory.h"
|
#include "memory/memory.h"
|
||||||
#include "Channels/channels.h"
|
#include "Channels/channels.h"
|
||||||
|
#include "cache/cache.hpp"
|
||||||
|
|
||||||
enum { DISABLED, ENABLED, HIDEFORBIDDEN };
|
enum
|
||||||
|
{
|
||||||
|
DISABLED,
|
||||||
|
ENABLED,
|
||||||
|
HIDEFORBIDDEN
|
||||||
|
};
|
||||||
|
|
||||||
GameList gameList;
|
GameList gameList;
|
||||||
|
|
||||||
@ -54,13 +61,14 @@ void GameList::clear()
|
|||||||
std::vector<int>().swap(GamePartitionList);
|
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)
|
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];
|
return FilteredList[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,11 +77,12 @@ struct discHdr * GameList::GetDiscHeader(const char * gameID) const
|
|||||||
|
|
||||||
int GameList::GetPartitionNumber(const u8 *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)
|
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];
|
return GamePartitionList[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,17 +91,17 @@ int GameList::GetPartitionNumber(const u8 *gameID) const
|
|||||||
|
|
||||||
void GameList::RemovePartition(int part)
|
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);
|
FullGameList.erase(FullGameList.begin() + i);
|
||||||
GamePartitionList.erase(GamePartitionList.begin()+i);
|
GamePartitionList.erase(GamePartitionList.begin() + i);
|
||||||
--i;
|
--i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(FullGameList.size() > 0)
|
if (FullGameList.size() > 0)
|
||||||
FilterList();
|
FilterList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,18 +111,20 @@ int GameList::InternalReadList(int part)
|
|||||||
u32 cnt = 0;
|
u32 cnt = 0;
|
||||||
|
|
||||||
int ret = WBFS_GetCount(part, &cnt);
|
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
|
// We are done here if no games are there
|
||||||
if(cnt == 0)
|
if (cnt == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Buffer length */
|
/* Buffer length */
|
||||||
u32 len = sizeof(struct discHdr) * cnt;
|
u32 len = sizeof(struct discHdr) * cnt;
|
||||||
|
|
||||||
/* Allocate memory */
|
/* Allocate memory */
|
||||||
struct discHdr *buffer = (struct discHdr *) allocate_memory( len );
|
struct discHdr *buffer = (struct discHdr *)allocate_memory(len);
|
||||||
if (!buffer) return -1;
|
if (!buffer)
|
||||||
|
return -1;
|
||||||
|
|
||||||
/* Clear buffer */
|
/* Clear buffer */
|
||||||
memset(buffer, 0, len);
|
memset(buffer, 0, len);
|
||||||
@ -133,22 +144,22 @@ int GameList::InternalReadList(int part)
|
|||||||
|
|
||||||
for (u32 i = 0; i < PartGameList.size(); i++)
|
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;
|
--i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FullGameList.resize(oldSize+PartGameList.size());
|
FullGameList.resize(oldSize + PartGameList.size());
|
||||||
memcpy(&FullGameList[oldSize], &PartGameList[0], PartGameList.size()*sizeof(struct discHdr));
|
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;
|
GamePartitionList[i] = part;
|
||||||
|
|
||||||
return PartGameList.size();
|
return PartGameList.size();
|
||||||
@ -156,6 +167,13 @@ int GameList::InternalReadList(int part)
|
|||||||
|
|
||||||
int GameList::ReadGameList()
|
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
|
// Clear list
|
||||||
FullGameList.clear();
|
FullGameList.clear();
|
||||||
GamePartitionList.clear();
|
GamePartitionList.clear();
|
||||||
@ -165,7 +183,7 @@ int GameList::ReadGameList()
|
|||||||
|
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
||||||
if(!Settings.MultiplePartitions)
|
if (!Settings.MultiplePartitions)
|
||||||
{
|
{
|
||||||
cnt = InternalReadList(Settings.partition);
|
cnt = InternalReadList(Settings.partition);
|
||||||
}
|
}
|
||||||
@ -173,13 +191,17 @@ int GameList::ReadGameList()
|
|||||||
{
|
{
|
||||||
int partitions = DeviceHandler::GetUSBPartitionCount();
|
int partitions = DeviceHandler::GetUSBPartitionCount();
|
||||||
|
|
||||||
for(int part = 0; part < partitions; ++part)
|
for (int part = 0; part < partitions; ++part)
|
||||||
{
|
{
|
||||||
int ret = InternalReadList(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;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,23 +217,25 @@ void GameList::InternalFilterList(std::vector<struct discHdr> &FullList)
|
|||||||
/* Filters */
|
/* Filters */
|
||||||
if (Settings.GameSort & SORT_FAVORITE)
|
if (Settings.GameSort & SORT_FAVORITE)
|
||||||
{
|
{
|
||||||
GameStatus * GameStats = GameStatistics.GetGameStatus(header->id);
|
GameStatus *GameStats = GameStatistics.GetGameStatus(header->id);
|
||||||
if (Settings.marknewtitles)
|
if (Settings.marknewtitles)
|
||||||
{
|
{
|
||||||
bool isNew = NewTitles::Instance()->IsNew(header->id);
|
bool isNew = NewTitles::Instance()->IsNew(header->id);
|
||||||
if (!isNew && (!GameStats || GameStats->FavoriteRank == 0)) continue;
|
if (!isNew && (!GameStats || GameStats->FavoriteRank == 0))
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else
|
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
|
//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;
|
continue;
|
||||||
|
|
||||||
GameCFG * GameConfig = GameSettings.GetGameCFG(header);
|
GameCFG *GameConfig = GameSettings.GetGameCFG(header);
|
||||||
|
|
||||||
/* Rating based parental control method */
|
/* Rating based parental control method */
|
||||||
if (Settings.parentalcontrol != PARENTAL_LVL_ADULT && !Settings.godmode)
|
if (Settings.parentalcontrol != PARENTAL_LVL_ADULT && !Settings.godmode)
|
||||||
@ -220,79 +244,79 @@ void GameList::InternalFilterList(std::vector<struct discHdr> &FullList)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check game rating in GameTDB, since the default Wii parental control setting is enabled
|
// 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)
|
if (rating > Settings.parentalcontrol)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Per game lock method
|
//! Per game lock method
|
||||||
if(!Settings.godmode && GameConfig && GameConfig->Locked)
|
if (!Settings.godmode && GameConfig && GameConfig->Locked)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//! Category filter
|
//! Category filter
|
||||||
u32 n;
|
u32 n;
|
||||||
int allType = DISABLED;
|
int allType = DISABLED;
|
||||||
// verify the display mode for category "All"
|
// 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
|
allType = ENABLED; // All = Enabled
|
||||||
break;
|
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
|
allType = HIDEFORBIDDEN; // All = Enabled but hide Forbidden categories
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(allType == DISABLED)
|
if (allType == DISABLED)
|
||||||
{
|
{
|
||||||
// Remove TitleID if it contains a forbidden categories
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
if(n < Settings.ForbiddenCategories.size())
|
if (n < Settings.ForbiddenCategories.size())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Remove TitleID is it doesn't contain a required categories
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
if(n < Settings.RequiredCategories.size())
|
if (n < Settings.RequiredCategories.size())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If there's no required categories, verify if the TitleID should be kept or removed
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
if(n == Settings.EnabledCategories.size())
|
if (n == Settings.EnabledCategories.size())
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(allType == HIDEFORBIDDEN)
|
if (allType == HIDEFORBIDDEN)
|
||||||
{
|
{
|
||||||
// Remove TitleID if it contains a forbidden categories
|
// 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]))
|
||||||
if(Settings.ForbiddenCategories[n] >0)
|
if (Settings.ForbiddenCategories[n] > 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(n < Settings.ForbiddenCategories.size())
|
if (n < Settings.ForbiddenCategories.size())
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,9 +324,9 @@ void GameList::InternalFilterList(std::vector<struct discHdr> &FullList)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
ReadGameList();
|
||||||
|
|
||||||
if (gameFilter)
|
if (gameFilter)
|
||||||
@ -310,20 +334,28 @@ int GameList::FilterList(const wchar_t * gameFilter)
|
|||||||
|
|
||||||
FilteredList.clear();
|
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
|
// Filter current game list if selected
|
||||||
if(Settings.LoaderMode & MODE_WIIGAMES)
|
if (Settings.LoaderMode & MODE_WIIGAMES)
|
||||||
InternalFilterList(FullGameList);
|
InternalFilterList(FullGameList);
|
||||||
|
|
||||||
// Filter gc game list if selected
|
// Filter gc game list if selected
|
||||||
if(Settings.LoaderMode & MODE_GCGAMES)
|
if (Settings.LoaderMode & MODE_GCGAMES)
|
||||||
InternalFilterList(GCGames::Instance()->GetHeaders());
|
InternalFilterList(GCGames::Instance()->GetHeaders());
|
||||||
|
|
||||||
// Filter nand channel list if selected
|
// Filter nand channel list if selected
|
||||||
if(Settings.LoaderMode & MODE_NANDCHANNELS)
|
if (Settings.LoaderMode & MODE_NANDCHANNELS)
|
||||||
InternalFilterList(Channels::Instance()->GetNandHeaders());
|
InternalFilterList(Channels::Instance()->GetNandHeaders());
|
||||||
|
|
||||||
// Filter emu nand channel list if selected
|
// Filter emu nand channel list if selected
|
||||||
if(Settings.LoaderMode & MODE_EMUCHANNELS)
|
if (Settings.LoaderMode & MODE_EMUCHANNELS)
|
||||||
InternalFilterList(Channels::Instance()->GetEmuHeaders());
|
InternalFilterList(Channels::Instance()->GetEmuHeaders());
|
||||||
|
|
||||||
NewTitles::Instance()->Save();
|
NewTitles::Instance()->Save();
|
||||||
@ -331,6 +363,9 @@ int GameList::FilterList(const wchar_t * gameFilter)
|
|||||||
|
|
||||||
SortList();
|
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();
|
return FilteredList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,26 +384,34 @@ void GameList::InternalLoadUnfiltered(std::vector<struct discHdr> &FullList)
|
|||||||
|
|
||||||
int GameList::LoadUnfiltered()
|
int GameList::LoadUnfiltered()
|
||||||
{
|
{
|
||||||
if((Settings.LoaderMode & MODE_WIIGAMES) && (FullGameList.size() == 0))
|
if ((Settings.LoaderMode & MODE_WIIGAMES) && (FullGameList.size() == 0))
|
||||||
ReadGameList();
|
ReadGameList();
|
||||||
|
|
||||||
GameFilter.clear();
|
GameFilter.clear();
|
||||||
FilteredList.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
|
// Filter current game list if selected
|
||||||
if(Settings.LoaderMode & MODE_WIIGAMES)
|
if (Settings.LoaderMode & MODE_WIIGAMES)
|
||||||
InternalLoadUnfiltered(FullGameList);
|
InternalLoadUnfiltered(FullGameList);
|
||||||
|
|
||||||
// Filter gc game list if selected
|
// Filter gc game list if selected
|
||||||
if(Settings.LoaderMode & MODE_GCGAMES)
|
if (Settings.LoaderMode & MODE_GCGAMES)
|
||||||
InternalLoadUnfiltered(GCGames::Instance()->GetHeaders());
|
InternalLoadUnfiltered(GCGames::Instance()->GetHeaders());
|
||||||
|
|
||||||
// Filter nand channel list if selected
|
// Filter nand channel list if selected
|
||||||
if(Settings.LoaderMode & MODE_NANDCHANNELS)
|
if (Settings.LoaderMode & MODE_NANDCHANNELS)
|
||||||
InternalLoadUnfiltered(Channels::Instance()->GetNandHeaders());
|
InternalLoadUnfiltered(Channels::Instance()->GetNandHeaders());
|
||||||
|
|
||||||
// Filter emu nand channel list if selected
|
// Filter emu nand channel list if selected
|
||||||
if(Settings.LoaderMode & MODE_EMUCHANNELS)
|
if (Settings.LoaderMode & MODE_EMUCHANNELS)
|
||||||
InternalLoadUnfiltered(Channels::Instance()->GetEmuHeaders());
|
InternalLoadUnfiltered(Channels::Instance()->GetEmuHeaders());
|
||||||
|
|
||||||
NewTitles::Instance()->Save();
|
NewTitles::Instance()->Save();
|
||||||
@ -376,22 +419,26 @@ int GameList::LoadUnfiltered()
|
|||||||
|
|
||||||
SortList();
|
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();
|
return FilteredList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameList::SortList()
|
void GameList::SortList()
|
||||||
{
|
{
|
||||||
if (FilteredList.size() < 2) return;
|
if (FilteredList.size() < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
if (Settings.GameSort & SORT_PLAYCOUNT)
|
if (Settings.GameSort & SORT_PLAYCOUNT)
|
||||||
{
|
{
|
||||||
std::sort(FilteredList.begin(), FilteredList.end(), PlaycountSortCallback);
|
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);
|
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);
|
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)
|
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)
|
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 count1 = GameStatistics.GetPlayCount(a->id);
|
||||||
int count2 = GameStatistics.GetPlayCount(b->id);
|
int count2 = GameStatistics.GetPlayCount(b->id);
|
||||||
|
|
||||||
if (count1 == count2) return NameSortCallback(a, b);
|
if (count1 == count2)
|
||||||
|
return NameSortCallback(a, b);
|
||||||
|
|
||||||
return (count1 > count2);
|
return (count1 > count2);
|
||||||
}
|
}
|
||||||
@ -421,17 +469,19 @@ bool GameList::RankingSortCallback(const struct discHdr *a, const struct discHdr
|
|||||||
int fav1 = GameStatistics.GetFavoriteRank(a->id);
|
int fav1 = GameStatistics.GetFavoriteRank(a->id);
|
||||||
int fav2 = GameStatistics.GetFavoriteRank(b->id);
|
int fav2 = GameStatistics.GetFavoriteRank(b->id);
|
||||||
|
|
||||||
if (fav1 == fav2) return NameSortCallback(a, b);
|
if (fav1 == fav2)
|
||||||
|
return NameSortCallback(a, b);
|
||||||
|
|
||||||
return (fav1 > fav2);
|
return (fav1 > fav2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameList::PlayersSortCallback(const struct discHdr *a, const struct discHdr *b)
|
bool GameList::PlayersSortCallback(const struct discHdr *a, const struct discHdr *b)
|
||||||
{
|
{
|
||||||
int count1 = GameTitles.GetPlayersCount((const char *) a->id);
|
int count1 = GameTitles.GetPlayersCount((const char *)a->id);
|
||||||
int count2 = GameTitles.GetPlayersCount((const char *) b->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);
|
return (count1 > count2);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user