Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2e032ca1f | ||
|
|
0585bec6e5 | ||
|
|
11f4f3000a | ||
|
|
474843915c | ||
|
|
3146b951f2 | ||
|
|
2db9b72416 | ||
|
|
9b4710d386 | ||
|
|
ddf5b94f4d | ||
|
|
ecb2567757 | ||
|
|
b59a162473 | ||
|
|
ef5ff520d1 | ||
|
|
433c2e220c | ||
|
|
98ad2f485b | ||
|
|
9966e57e12 | ||
|
|
c11990e1bd | ||
|
|
9b1c0226e1 | ||
|
|
f38a671a7f | ||
|
|
fe952dc9f2 | ||
|
|
d063ffcb20 |
35
.github/workflows/build_presets.yml
vendored
Normal file
35
.github/workflows/build_presets.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
name: build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "master" ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest]
|
||||||
|
preset: [Release, RelWithDebInfo, MinSizeRel, Debug]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
container: devkitpro/devkita64:latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
# fetch latest cmake
|
||||||
|
- uses: lukka/get-cmake@latest
|
||||||
|
|
||||||
|
- name: Configure CMake
|
||||||
|
run: |
|
||||||
|
cmake --preset ${{ matrix.preset }}
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build --preset ${{ matrix.preset }} --parallel 4
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@master
|
||||||
|
with:
|
||||||
|
name: sphaira-${{ matrix.preset }}
|
||||||
|
path: build/${{ matrix.preset }}/sphaira.nro
|
||||||
@@ -51,3 +51,5 @@ see `assets/romfs/assoc/` for more examples of file assoc entries
|
|||||||
- libpulsar
|
- libpulsar
|
||||||
- minIni
|
- minIni
|
||||||
- gbatemp
|
- gbatemp
|
||||||
|
- hb-appstore
|
||||||
|
- everyone who has contributed to this project!
|
||||||
|
|||||||
BIN
assets/icon.jpg
BIN
assets/icon.jpg
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 7.6 KiB |
@@ -14,57 +14,57 @@
|
|||||||
"Info": "Info",
|
"Info": "Info",
|
||||||
"Delete": "Löschen",
|
"Delete": "Löschen",
|
||||||
"Hide Sphaira": "Sphaira verstecken",
|
"Hide Sphaira": "Sphaira verstecken",
|
||||||
"Are you sure you want to delete ": "Sind Sie sicher, dass Sie löschen möchten? ",
|
"Are you sure you want to delete ": "Mit dem Löschvorgang fortfahren?",
|
||||||
"Install Forwarder": "Weiterleitung installieren",
|
"Install Forwarder": "Forwarder installieren",
|
||||||
"WARNING: Installing forwarders will lead to a ban!": "ACHTUNG: Der Einbau von Forwardern führt zu einem Verbot!",
|
"WARNING: Installing forwarders will lead to a ban!": "ACHTUNG: Die Installation von Forwardern führt zu einem Ban!",
|
||||||
"Back": "Zurück",
|
"Back": "Zurück",
|
||||||
"Install": "Installieren",
|
"Install": "Installieren",
|
||||||
"Fs": "Fs",
|
"Fs": "Fs",
|
||||||
"App": "App",
|
"App": "App",
|
||||||
"Menu": "Speisekarte",
|
"Menu": "Menu",
|
||||||
"Homebrew": "Homebrew",
|
"Homebrew": "Homebrew",
|
||||||
"FileBrowser": "DateiBrowser",
|
"FileBrowser": "DateiBrowser",
|
||||||
"Open": "Offen",
|
"Open": "Öffnen",
|
||||||
"Theme Options": "Themenoptionen",
|
"Theme Options": "Themenoptionen",
|
||||||
"Select Theme": "Wählen Sie Thema aus",
|
"Select Theme": "Wählen Sie Theme aus",
|
||||||
"Shuffle": "Shuffle",
|
"Shuffle": "Shuffle",
|
||||||
"Music": "Musik",
|
"Music": "Musik",
|
||||||
"Show Hidden": "Versteckt anzeigen",
|
"Show Hidden": "Versteckte anzeigen",
|
||||||
"Folders First": "Ordner zuerst",
|
"Folders First": "Ordner zuerst",
|
||||||
"Hidden Last": "Zuletzt versteckt",
|
"Hidden Last": "Zuletzt versteckt",
|
||||||
"Yes": "Ja",
|
"Yes": "Ja",
|
||||||
"No": "NEIN",
|
"No": "Nein",
|
||||||
"Network Options": "Netzwerkoptionen",
|
"Network Options": "Netzwerkoptionen",
|
||||||
"Nxlink": "Nxlink",
|
"Nxlink": "Nxlink",
|
||||||
"Check for update": "Suchen Sie nach Updates",
|
"Check for update": "Nach Updates suchen",
|
||||||
"File Options": "Dateioptionen",
|
"File Options": "Dateioptionen",
|
||||||
"Cut": "Schneiden",
|
"Cut": "Ausschneiden",
|
||||||
"Copy": "Kopie",
|
"Copy": "Kopieren",
|
||||||
"Rename": "Umbenennen",
|
"Rename": "Umbenennen",
|
||||||
"Advanced Options": "Datei erstellen",
|
"Advanced Options": "Erweiterte Optionen",
|
||||||
"Create File": "Datei erstellen",
|
"Create File": "Datei erstellen",
|
||||||
"Create Folder": "Ordner erstellen",
|
"Create Folder": "Ordner erstellen",
|
||||||
"View as text": "Als Text anzeigen",
|
"View as text": "Als Text anzeigen",
|
||||||
"View as text (unfinished)": "Als Text anzeigen (unvollendet)",
|
"View as text (unfinished)": "Als Text anzeigen (unfertig)",
|
||||||
"Set Archive Bit": "Archivbit setzen",
|
"Set Archive Bit": "Archivbit setzen",
|
||||||
"AppStore Options": "AppStore-Optionen",
|
"AppStore Options": "AppStore-Optionen",
|
||||||
"All": "Alle",
|
"All": "Alle",
|
||||||
"Games": "Spiele",
|
"Games": "Spiele",
|
||||||
"Emulators": "Emulatoren",
|
"Emulators": "Emulatoren",
|
||||||
"Tools": "Werkzeuge",
|
"Tools": "Werkzeuge",
|
||||||
"Advanced": "Fortschrittlich",
|
"Advanced": "Erweitert",
|
||||||
"Themes": "Themen",
|
"Themes": "Themes",
|
||||||
"Legacy": "Vermächtnis",
|
"Legacy": "Legacy",
|
||||||
"Misc": "Sonstiges",
|
"Misc": "Sonstiges",
|
||||||
"Downloads": "Downloads",
|
"Downloads": "Downloads",
|
||||||
"Filter": "Filter",
|
"Filter": "Filter",
|
||||||
"Search": "Suchen",
|
"Search": "Suchen",
|
||||||
"Menu Options": "Menüoptionen",
|
"Menu Options": "Menüoptionen",
|
||||||
"Header": "Kopfzeile",
|
"Header": "Header",
|
||||||
"Theme": "Thema",
|
"Theme": "Theme",
|
||||||
"Network": "Netzwerk",
|
"Network": "Netzwerk",
|
||||||
"Logging": "Protokollierung",
|
"Logging": "Logging",
|
||||||
"Enabled": "Ermöglicht",
|
"Enabled": "Aktiviert",
|
||||||
"Disabled": "Deaktiviert",
|
"Disabled": "Deaktiviert",
|
||||||
"Replace hbmenu on exit": "Ersetzen Sie hbmenu beim Beenden",
|
"Replace hbmenu on exit": "Ersetzen Sie hbmenu beim Beenden",
|
||||||
"Misc Options": "Verschiedene Optionen",
|
"Misc Options": "Verschiedene Optionen",
|
||||||
@@ -98,16 +98,16 @@
|
|||||||
"80x60": "80x60",
|
"80x60": "80x60",
|
||||||
"40x30": "40x30",
|
"40x30": "40x30",
|
||||||
"20x15": "20x15",
|
"20x15": "20x15",
|
||||||
"Controller": "Regler",
|
"Controller": "Controller",
|
||||||
"Rotation": "Drehung",
|
"Rotation": "Drehung",
|
||||||
"Colour": "Farbe",
|
"Colour": "Farbe",
|
||||||
"Light Target": "Leichtes Ziel",
|
"Light Target": "Leichtes Ziel",
|
||||||
"Gain": "Gewinnen",
|
"Gain": "Gain",
|
||||||
"Negative Image": "Negatives Bild",
|
"Negative Image": "Negatives Bild",
|
||||||
"Format": "Format",
|
"Format": "Format",
|
||||||
"Trimming Format": "Zuschneideformat",
|
"Trimming Format": "Zuschneideformat",
|
||||||
"External Light Filter": "Externer Lichtfilter",
|
"External Light Filter": "Externer Lichtfilter",
|
||||||
"Load Default": "Standard laden",
|
"Load Default": "Standardoptionen laden",
|
||||||
"No Internet": "Kein Internet",
|
"No Internet": "Kein Internet",
|
||||||
"[Applet Mode]": "[Applet-Modus]",
|
"[Applet Mode]": "[Applet-Modus]",
|
||||||
"Language": "Sprache"
|
"Language": "Sprache"
|
||||||
|
|||||||
@@ -1,52 +1,52 @@
|
|||||||
{
|
{
|
||||||
"Launch": "Lancement",
|
"Launch": "Exécuter",
|
||||||
"Options": "Possibilités",
|
"Options": "Options",
|
||||||
"Homebrew Options": "Options de brassage maison",
|
"Homebrew Options": "Options Homebrew",
|
||||||
"Sort By": "Trier par",
|
"Sort By": "Tri Par",
|
||||||
"Sort Options": "Options de tri",
|
"Sort Options": "Options de Tri",
|
||||||
"Updated": "Mis à jour",
|
"Updated": "Mis à jour",
|
||||||
"Size": "Taille",
|
"Size": "Taille",
|
||||||
"Alphabetical": "Alphabétique",
|
"Alphabetical": "Alphabétique",
|
||||||
"Decending": "Décroissant",
|
"Decending": "Décroissant",
|
||||||
"Ascending": "Ascendant",
|
"Ascending": "Croissant",
|
||||||
"Sort": "Trier",
|
"Sort": "Tri",
|
||||||
"Order": "Commande",
|
"Order": "Ordre",
|
||||||
"Info": "Informations",
|
"Info": "Info.",
|
||||||
"Delete": "Supprimer",
|
"Delete": "Supprimer",
|
||||||
"Hide Sphaira": "Masquer Sphaira",
|
"Hide Sphaira": "Masquer Sphaira",
|
||||||
"Are you sure you want to delete ": "Etes-vous sûr de vouloir supprimer ",
|
"Are you sure you want to delete ": "Êtes-vous sûr de vouloir supprimer ",
|
||||||
"Install Forwarder": "Installer le redirecteur",
|
"Install Forwarder": "Installer le Forwarder",
|
||||||
"WARNING: Installing forwarders will lead to a ban!": "ATTENTION : L'installation de transitaires entraînera une interdiction !",
|
"WARNING: Installing forwarders will lead to a ban!": "ATTENTION: L'installation de forwarders entraînera un ban!",
|
||||||
"Back": "Dos",
|
"Back": "Retour",
|
||||||
"Install": "Installer",
|
"Install": "Installer",
|
||||||
"Fs": "Fs",
|
"Fs": "Fs",
|
||||||
"App": "Application",
|
"App": "App.",
|
||||||
"Menu": "Menu",
|
"Menu": "Menu",
|
||||||
"Homebrew": "Homebrew",
|
"Homebrew": "Homebrew",
|
||||||
"FileBrowser": "Navigateur de fichiers",
|
"FileBrowser": "Navigateur de Fichiers",
|
||||||
"Open": "Ouvrir",
|
"Open": "Ouvrir",
|
||||||
"Theme Options": "Options de thème",
|
"Theme Options": "Options de Thème",
|
||||||
"Select Theme": "Sélectionnez un thème",
|
"Select Theme": "Choisir un Thème",
|
||||||
"Shuffle": "Mélanger",
|
"Shuffle": "Aléatoire",
|
||||||
"Music": "Musique",
|
"Music": "Musique",
|
||||||
"Show Hidden": "Afficher masqué",
|
"Show Hidden": "Afficher Masqués",
|
||||||
"Folders First": "Les dossiers d'abord",
|
"Folders First": "Dossiers en Premier",
|
||||||
"Hidden Last": "Dernier caché",
|
"Hidden Last": "Masqués en Dernier",
|
||||||
"Yes": "Oui",
|
"Yes": "Oui",
|
||||||
"No": "Non",
|
"No": "Non",
|
||||||
"Network Options": "Options réseau",
|
"Network Options": "Options Réseau",
|
||||||
"Nxlink": "Nxlien",
|
"Nxlink": "Nxlink",
|
||||||
"Check for update": "Vérifier la mise à jour",
|
"Check for update": "Vérification d'une mise à jour",
|
||||||
"File Options": "Options de fichier",
|
"File Options": "Options de Fichier",
|
||||||
"Cut": "Couper",
|
"Cut": "Couper",
|
||||||
"Copy": "Copie",
|
"Copy": "Copier",
|
||||||
"Rename": "Rebaptiser",
|
"Rename": "Renommer",
|
||||||
"Advanced Options": "Créer un fichier",
|
"Advanced Options": "Options Avancées",
|
||||||
"Create File": "Créer un fichier",
|
"Create File": "Créer un Fichier",
|
||||||
"Create Folder": "Créer un dossier",
|
"Create Folder": "Créer un Dossier",
|
||||||
"View as text": "Afficher sous forme de texte",
|
"View as text": "Afficher sous forme de texte",
|
||||||
"View as text (unfinished)": "Afficher sous forme de texte (inachevé)",
|
"View as text (unfinished)": "Afficher sous forme de texte (inachevé)",
|
||||||
"Set Archive Bit": "Définir le bit d'archive",
|
"Set Archive Bit": "Définir le Bit d'Archive",
|
||||||
"AppStore Options": "Options de l'AppStore",
|
"AppStore Options": "Options de l'AppStore",
|
||||||
"All": "Tous",
|
"All": "Tous",
|
||||||
"Games": "Jeux",
|
"Games": "Jeux",
|
||||||
@@ -54,45 +54,45 @@
|
|||||||
"Tools": "Outils",
|
"Tools": "Outils",
|
||||||
"Advanced": "Avancé",
|
"Advanced": "Avancé",
|
||||||
"Themes": "Thèmes",
|
"Themes": "Thèmes",
|
||||||
"Legacy": "Héritage",
|
"Legacy": "Legacy",
|
||||||
"Misc": "Divers",
|
"Misc": "Divers",
|
||||||
"Downloads": "Téléchargements",
|
"Downloads": "Téléchargements",
|
||||||
"Filter": "Filtre",
|
"Filter": "Filtre",
|
||||||
"Search": "Recherche",
|
"Search": "Recherche",
|
||||||
"Menu Options": "Options des menus",
|
"Menu Options": "Options des Menus",
|
||||||
"Header": "En-tête",
|
"Header": "En-tête",
|
||||||
"Theme": "Thème",
|
"Theme": "Thème",
|
||||||
"Network": "Réseau",
|
"Network": "Réseau",
|
||||||
"Logging": "Enregistrement",
|
"Logging": "Journalisation",
|
||||||
"Enabled": "Activé",
|
"Enabled": "Activé(e)",
|
||||||
"Disabled": "Désactivé",
|
"Disabled": "Désactivé(e)",
|
||||||
"Replace hbmenu on exit": "Remplacer hbmenu à la sortie",
|
"Replace hbmenu on exit": "Remplacer hbmenu en sortie",
|
||||||
"Misc Options": "Diverses options",
|
"Misc Options": "Options Diverses",
|
||||||
"Themezer": "Thème",
|
"Themezer": "Themezer",
|
||||||
"Irs": "Irs",
|
"Irs": "Irs",
|
||||||
"Web": "Web",
|
"Web": "Web",
|
||||||
"Download": "Télécharger",
|
"Download": "Télécharger",
|
||||||
"Next Page": "Page suivante",
|
"Next Page": "Page Suiv.",
|
||||||
"Prev Page": "Page précédente",
|
"Prev Page": "Page Préc.",
|
||||||
"Pad ": "Tampon ",
|
"Pad ": "Manette ",
|
||||||
" (Unconnected)": " (Sans rapport)",
|
" (Unconnected)": " (Non connectée)",
|
||||||
"HandHeld": "Portable",
|
"HandHeld": "Portable",
|
||||||
" (Available)": " (Disponible)",
|
" (Available)": " (Disponible)",
|
||||||
"0 (Sideways)": "0 (latéralement)",
|
"0 (Sideways)": "0 (Paysage)",
|
||||||
"90 (Flat)": "90 (plat)",
|
"90 (Flat)": "90 (Portrait)",
|
||||||
"180 (-Sideways)": "180 (-Côté)",
|
"180 (-Sideways)": "180 (-Paysage)",
|
||||||
"270 (Upside down)": "270 (à l'envers)",
|
"270 (Upside down)": "270 (Inversé)",
|
||||||
"Grey": "Gris",
|
"Grey": "Gris",
|
||||||
"Ironbow": "Arc de fer",
|
"Ironbow": "Ironbow",
|
||||||
"Green": "Vert",
|
"Green": "Vert",
|
||||||
"Red": "Rouge",
|
"Red": "Rouge",
|
||||||
"Blue": "Bleu",
|
"Blue": "Bleu",
|
||||||
"All leds": "Toutes les LED",
|
"All leds": "Toutes les LED",
|
||||||
"Bright group": "Groupe lumineux",
|
"Bright group": "Groupe lumineux",
|
||||||
"Dim group": "Groupe de gradation",
|
"Dim group": "Groupe sombre",
|
||||||
"None": "Aucun",
|
"None": "Aucun",
|
||||||
"Normal image": "Image normale",
|
"Normal image": "Image normale",
|
||||||
"Negative image": "Image négative",
|
"Negative image": "Négatif",
|
||||||
"320x240": "320x240",
|
"320x240": "320x240",
|
||||||
"160x120": "160x120",
|
"160x120": "160x120",
|
||||||
"80x60": "80x60",
|
"80x60": "80x60",
|
||||||
@@ -101,13 +101,13 @@
|
|||||||
"Controller": "Contrôleur",
|
"Controller": "Contrôleur",
|
||||||
"Rotation": "Rotation",
|
"Rotation": "Rotation",
|
||||||
"Colour": "Couleur",
|
"Colour": "Couleur",
|
||||||
"Light Target": "Cible légère",
|
"Light Target": "Luminosité",
|
||||||
"Gain": "Gagner",
|
"Gain": "Gain",
|
||||||
"Negative Image": "Image négative",
|
"Negative Image": "Négatif",
|
||||||
"Format": "Format",
|
"Format": "Format",
|
||||||
"Trimming Format": "Format de découpage",
|
"Trimming Format": "Format de Découpe",
|
||||||
"External Light Filter": "Filtre de lumière externe",
|
"External Light Filter": "Filtre de Lumière Externe",
|
||||||
"Load Default": "Charger par défaut",
|
"Load Default": "Charger par Défaut",
|
||||||
"No Internet": "Pas d'Internet",
|
"No Internet": "Pas d'Internet",
|
||||||
"[Applet Mode]": "[Mode Applet]",
|
"[Applet Mode]": "[Mode Applet]",
|
||||||
"Language": "Langue"
|
"Language": "Langue"
|
||||||
|
|||||||
@@ -1,69 +1,69 @@
|
|||||||
{
|
{
|
||||||
"Launch": "Lancio",
|
"Launch": "Lancia",
|
||||||
"Options": "Opzioni",
|
"Options": "Opzioni",
|
||||||
"Homebrew Options": "Opzioni per l'homebrew",
|
"Homebrew Options": "Opzioni Homebrew",
|
||||||
"Sort By": "Ordina per",
|
"Sort By": "Ordina per",
|
||||||
"Sort Options": "Opzioni di ordinamento",
|
"Sort Options": "Opzioni filtro",
|
||||||
"Updated": "Aggiornato",
|
"Updated": "Aggiornato",
|
||||||
"Size": "Misurare",
|
"Size": "Misurare",
|
||||||
"Alphabetical": "Alfabetico",
|
"Alphabetical": "Alfabetico",
|
||||||
"Decending": "Decrescente",
|
"Decending": "Decrescente",
|
||||||
"Ascending": "Ascendente",
|
"Ascending": "Crescente",
|
||||||
"Sort": "Ordinare",
|
"Sort": "Riordina",
|
||||||
"Order": "Ordine",
|
"Order": "Ordina",
|
||||||
"Info": "Informazioni",
|
"Info": "Informazioni",
|
||||||
"Delete": "Eliminare",
|
"Delete": "Elimina",
|
||||||
"Hide Sphaira": "Nascondi Sphaira",
|
"Hide Sphaira": "Nascondi Sphaira",
|
||||||
"Are you sure you want to delete ": "Sei sicuro di voler eliminare? ",
|
"Are you sure you want to delete ": "Sei sicuro di voler eliminare? ",
|
||||||
"Install Forwarder": "Installa lo spedizioniere",
|
"Install Forwarder": "Installa forwarder",
|
||||||
"WARNING: Installing forwarders will lead to a ban!": "ATTENZIONE: l'installazione di forwarder porterà al ban!",
|
"WARNING: Installing forwarders will lead to a ban!": "ATTENZIONE: l'installazione di forwarder porterà al ban!",
|
||||||
"Back": "Indietro",
|
"Back": "Indietro",
|
||||||
"Install": "Installare",
|
"Install": "Installa",
|
||||||
"Fs": "Fs",
|
"Fs": "Fs",
|
||||||
"App": "App",
|
"App": "App",
|
||||||
"Menu": "Menu",
|
"Menu": "Menu",
|
||||||
"Homebrew": "Birra fatta in casa",
|
"Homebrew": "Homebrew",
|
||||||
"FileBrowser": "FileBrowser",
|
"FileBrowser": "FileBrowser",
|
||||||
"Open": "Aprire",
|
"Open": "Apri",
|
||||||
"Theme Options": "Opzioni del tema",
|
"Theme Options": "Opzioni tema",
|
||||||
"Select Theme": "Seleziona Tema",
|
"Select Theme": "Seleziona tema",
|
||||||
"Shuffle": "Mescola",
|
"Shuffle": "Mescola",
|
||||||
"Music": "Musica",
|
"Music": "Musica",
|
||||||
"Show Hidden": "Mostra nascosto",
|
"Show Hidden": "Mostra nascosto",
|
||||||
"Folders First": "Prima le cartelle",
|
"Folders First": "Prima le cartelle",
|
||||||
"Hidden Last": "Ultimo nascosto",
|
"Hidden Last": "Ultimo nascosto",
|
||||||
"Yes": "SÌ",
|
"Yes": "Sì",
|
||||||
"No": "NO",
|
"No": "No",
|
||||||
"Network Options": "Opzioni di rete",
|
"Network Options": "Opzioni di rete",
|
||||||
"Nxlink": "Nxlink",
|
"Nxlink": "Nxlink",
|
||||||
"Check for update": "Controlla l'aggiornamento",
|
"Check for update": "Controlla aggiornamenti",
|
||||||
"File Options": "Opzioni file",
|
"File Options": "Opzioni file",
|
||||||
"Cut": "Taglio",
|
"Cut": "Taglia",
|
||||||
"Copy": "Copia",
|
"Copy": "Copia",
|
||||||
"Rename": "Rinominare",
|
"Rename": "Rinomina",
|
||||||
"Advanced Options": "Crea file",
|
"Advanced Options": "Opzioni avanzate",
|
||||||
"Create File": "Crea file",
|
"Create File": "Crea file",
|
||||||
"Create Folder": "Crea cartella",
|
"Create Folder": "Crea cartella",
|
||||||
"View as text": "Visualizza come testo",
|
"View as text": "Visualizza come testo",
|
||||||
"View as text (unfinished)": "Visualizza come testo (non finito)",
|
"View as text (unfinished)": "Visualizza come testo (non finito)",
|
||||||
"Set Archive Bit": "Imposta bit di archivio",
|
"Set Archive Bit": "Imposta Archive Bit",
|
||||||
"AppStore Options": "Opzioni dell'App Store",
|
"AppStore Options": "Opzioni dell'App Store",
|
||||||
"All": "Tutto",
|
"All": "Tutto",
|
||||||
"Games": "Giochi",
|
"Games": "Giochi",
|
||||||
"Emulators": "Emulatori",
|
"Emulators": "Emulatori",
|
||||||
"Tools": "Utensili",
|
"Tools": "Strumenti",
|
||||||
"Advanced": "Avanzato",
|
"Advanced": "Avanzato",
|
||||||
"Themes": "Temi",
|
"Themes": "Temi",
|
||||||
"Legacy": "Eredità",
|
"Legacy": "Legacy",
|
||||||
"Misc": "Varie",
|
"Misc": "Varie",
|
||||||
"Downloads": "Download",
|
"Downloads": "Download",
|
||||||
"Filter": "Filtro",
|
"Filter": "Filtro",
|
||||||
"Search": "Ricerca",
|
"Search": "Ricerca",
|
||||||
"Menu Options": "Opzioni del menu",
|
"Menu Options": "Opzioni menu",
|
||||||
"Header": "Intestazione",
|
"Header": "Intestazione",
|
||||||
"Theme": "Tema",
|
"Theme": "Tema",
|
||||||
"Network": "Rete",
|
"Network": "Rete",
|
||||||
"Logging": "Registrazione",
|
"Logging": "Logging",
|
||||||
"Enabled": "Abilitato",
|
"Enabled": "Abilitato",
|
||||||
"Disabled": "Disabilitato",
|
"Disabled": "Disabilitato",
|
||||||
"Replace hbmenu on exit": "Sostituisci hbmenu all'uscita",
|
"Replace hbmenu on exit": "Sostituisci hbmenu all'uscita",
|
||||||
@@ -71,19 +71,19 @@
|
|||||||
"Themezer": "Themezer",
|
"Themezer": "Themezer",
|
||||||
"Irs": "Irs",
|
"Irs": "Irs",
|
||||||
"Web": "Rete",
|
"Web": "Rete",
|
||||||
"Download": "Scaricamento",
|
"Download": "Download",
|
||||||
"Next Page": "Pagina successiva",
|
"Next Page": "Pagina successiva",
|
||||||
"Prev Page": "Pagina precedente",
|
"Prev Page": "Pagina precedente",
|
||||||
"Pad ": "Pad ",
|
"Pad ": "Pad ",
|
||||||
" (Unconnected)": " (Non connesso)",
|
" (Unconnected)": " (Non connesso)",
|
||||||
"HandHeld": "Tenuto in mano",
|
"HandHeld": "HandHeld",
|
||||||
" (Available)": " (Disponibile)",
|
" (Available)": " (Disponibile)",
|
||||||
"0 (Sideways)": "0 (lateralmente)",
|
"0 (Sideways)": "0 (Di lato)",
|
||||||
"90 (Flat)": "90 (Piatto)",
|
"90 (Flat)": "90 (Piatto)",
|
||||||
"180 (-Sideways)": "180 (-lateralmente)",
|
"180 (-Sideways)": "180 (-Di lato)",
|
||||||
"270 (Upside down)": "270 (Capovolto)",
|
"270 (Upside down)": "270 (Capovolto)",
|
||||||
"Grey": "Grigio",
|
"Grey": "Grigio",
|
||||||
"Ironbow": "Arco di ferro",
|
"Ironbow": "Ironbow",
|
||||||
"Green": "Verde",
|
"Green": "Verde",
|
||||||
"Red": "Rosso",
|
"Red": "Rosso",
|
||||||
"Blue": "Blu",
|
"Blue": "Blu",
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
"80x60": "80x60",
|
"80x60": "80x60",
|
||||||
"40x30": "40x30",
|
"40x30": "40x30",
|
||||||
"20x15": "20×15",
|
"20x15": "20×15",
|
||||||
"Controller": "Controllore",
|
"Controller": "Controller",
|
||||||
"Rotation": "Rotazione",
|
"Rotation": "Rotazione",
|
||||||
"Colour": "Colore",
|
"Colour": "Colore",
|
||||||
"Light Target": "Bersaglio leggero",
|
"Light Target": "Bersaglio leggero",
|
||||||
|
|||||||
@@ -1,44 +1,44 @@
|
|||||||
{
|
{
|
||||||
"Launch": "打ち上げ",
|
"Launch": "起動",
|
||||||
"Options": "オプション",
|
"Options": "設定",
|
||||||
"Homebrew Options": "自作オプション",
|
"Homebrew Options": "Homebrew設定",
|
||||||
"Sort By": "並べ替え",
|
"Sort By": "並べ替え",
|
||||||
"Sort Options": "並べ替えオプション",
|
"Sort Options": "並べ替え設定",
|
||||||
"Updated": "更新されました",
|
"Updated": "最近使った順",
|
||||||
"Size": "サイズ",
|
"Size": "ファイルサイズ",
|
||||||
"Alphabetical": "アルファベット順",
|
"Alphabetical": "アルファベット順",
|
||||||
"Decending": "降順",
|
"Decending": "降順",
|
||||||
"Ascending": "上昇",
|
"Ascending": "上昇",
|
||||||
"Sort": "選別",
|
"Sort": "並べ替え",
|
||||||
"Order": "注文",
|
"Order": "順番",
|
||||||
"Info": "情報",
|
"Info": "情報",
|
||||||
"Delete": "消去",
|
"Delete": "消去",
|
||||||
"Hide Sphaira": "ハイド・スファイラ",
|
"Hide Sphaira": "Sphairaを非表示",
|
||||||
"Are you sure you want to delete ": "削除してもよろしいですか ",
|
"Are you sure you want to delete ": "消去してもよろしいですか ",
|
||||||
"Install Forwarder": "フォワーダーのインストール",
|
"Install Forwarder": "Forwarderのインストール",
|
||||||
"WARNING: Installing forwarders will lead to a ban!": "警告: フォワーダーをインストールすると禁止されます。",
|
"WARNING: Installing forwarders will lead to a ban!": "警告: ForwarderをインストールするとBANされます。",
|
||||||
"Back": "戻る",
|
"Back": "戻る",
|
||||||
"Install": "インストール",
|
"Install": "インストール",
|
||||||
"Fs": "Fs",
|
"Fs": "ファイル",
|
||||||
"App": "アプリ",
|
"App": "アプリ",
|
||||||
"Menu": "メニュー",
|
"Menu": "メニュー",
|
||||||
"Homebrew": "自作",
|
"Homebrew": "Homebrew",
|
||||||
"FileBrowser": "ファイルブラウザ",
|
"FileBrowser": "ファイルブラウザ",
|
||||||
"Open": "開ける",
|
"Open": "開く",
|
||||||
"Theme Options": "テーマのオプション",
|
"Theme Options": "テーマ設定",
|
||||||
"Select Theme": "テーマの選択",
|
"Select Theme": "テーマを選ぶ",
|
||||||
"Shuffle": "シャッフル",
|
"Shuffle": "シャッフル",
|
||||||
"Music": "音楽",
|
"Music": "BGM",
|
||||||
"Show Hidden": "非表示を表示",
|
"Show Hidden": "非表示ファイルを表示",
|
||||||
"Folders First": "フォルダーを最初に",
|
"Folders First": "フォルダーを優先",
|
||||||
"Hidden Last": "隠された最後",
|
"Hidden Last": "非表示ファイルを劣後",
|
||||||
"Yes": "はい",
|
"Yes": "はい",
|
||||||
"No": "いいえ",
|
"No": "いいえ",
|
||||||
"Network Options": "ネットワークオプション",
|
"Network Options": "ネットワーク設定",
|
||||||
"Nxlink": "Nxlink",
|
"Nxlink": "Nxlink",
|
||||||
"Check for update": "アップデートを確認する",
|
"Check for update": "アップデートの確認",
|
||||||
"File Options": "ファイルオプション",
|
"File Options": "ファイル設定",
|
||||||
"Cut": "カット",
|
"Cut": "切り取り",
|
||||||
"Copy": "コピー",
|
"Copy": "コピー",
|
||||||
"Rename": "名前の変更",
|
"Rename": "名前の変更",
|
||||||
"Advanced Options": "ファイルの作成",
|
"Advanced Options": "ファイルの作成",
|
||||||
@@ -47,30 +47,30 @@
|
|||||||
"View as text": "テキストとして表示",
|
"View as text": "テキストとして表示",
|
||||||
"View as text (unfinished)": "テキストとして表示 (未完成)",
|
"View as text (unfinished)": "テキストとして表示 (未完成)",
|
||||||
"Set Archive Bit": "アーカイブビットの設定",
|
"Set Archive Bit": "アーカイブビットの設定",
|
||||||
"AppStore Options": "AppStore オプション",
|
"AppStore Options": "AppStoreの設定",
|
||||||
"All": "全て",
|
"All": "全て",
|
||||||
"Games": "ゲーム",
|
"Games": "ゲーム",
|
||||||
"Emulators": "エミュレータ",
|
"Emulators": "エミュレータ",
|
||||||
"Tools": "ツール",
|
"Tools": "ツール",
|
||||||
"Advanced": "高度な",
|
"Advanced": "高度な",
|
||||||
"Themes": "テーマ",
|
"Themes": "テーマ",
|
||||||
"Legacy": "遺産",
|
"Legacy": "レガシー",
|
||||||
"Misc": "その他",
|
"Misc": "その他",
|
||||||
"Downloads": "ダウンロード",
|
"Downloads": "ダウンロード",
|
||||||
"Filter": "フィルター",
|
"Filter": "フィルター",
|
||||||
"Search": "検索",
|
"Search": "検索",
|
||||||
"Menu Options": "メニューオプション",
|
"Menu Options": "メニュー設定",
|
||||||
"Header": "ヘッダ",
|
"Header": "ヘッダー",
|
||||||
"Theme": "テーマ",
|
"Theme": "テーマ",
|
||||||
"Network": "ネットワーク",
|
"Network": "ネットワーク",
|
||||||
"Logging": "ロギング",
|
"Logging": "ログの取得",
|
||||||
"Enabled": "有効",
|
"Enabled": "有効",
|
||||||
"Disabled": "無効",
|
"Disabled": "無効",
|
||||||
"Replace hbmenu on exit": "終了時に hbmenu を置き換える",
|
"Replace hbmenu on exit": "終了時に hbmenu を置き換える",
|
||||||
"Misc Options": "その他のオプション",
|
"Misc Options": "その他",
|
||||||
"Themezer": "テーマ設定者",
|
"Themezer": "Themezer",
|
||||||
"Irs": "イルス",
|
"Irs": "Joy-Con IRカメラ",
|
||||||
"Web": "ウェブ",
|
"Web": "ウェブブラウザ",
|
||||||
"Download": "ダウンロード",
|
"Download": "ダウンロード",
|
||||||
"Next Page": "次のページ",
|
"Next Page": "次のページ",
|
||||||
"Prev Page": "前のページ",
|
"Prev Page": "前のページ",
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
"80x60": "80×60",
|
"80x60": "80×60",
|
||||||
"40x30": "40×30",
|
"40x30": "40×30",
|
||||||
"20x15": "20x15",
|
"20x15": "20x15",
|
||||||
"Controller": "コントローラ",
|
"Controller": "コントローラー",
|
||||||
"Rotation": "回転",
|
"Rotation": "回転",
|
||||||
"Colour": "色",
|
"Colour": "色",
|
||||||
"Light Target": "ライトターゲット",
|
"Light Target": "ライトターゲット",
|
||||||
@@ -109,6 +109,6 @@
|
|||||||
"External Light Filter": "外光フィルター",
|
"External Light Filter": "外光フィルター",
|
||||||
"Load Default": "デフォルトをロード",
|
"Load Default": "デフォルトをロード",
|
||||||
"No Internet": "インターネットなし",
|
"No Internet": "インターネットなし",
|
||||||
"[Applet Mode]": "[アプレットモード]",
|
"[Applet Mode]": "[Appletモード]",
|
||||||
"Language": "言語"
|
"Language": "言語"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,114 +1,114 @@
|
|||||||
{
|
{
|
||||||
"Launch": "시작하다",
|
"Launch": "실행",
|
||||||
"Options": "옵션",
|
"Options": "설정",
|
||||||
"Homebrew Options": "홈브류 옵션",
|
"Homebrew Options": "홈브류 설정",
|
||||||
"Sort By": "정렬 기준",
|
"Sort By": "정렬",
|
||||||
"Sort Options": "정렬 옵션",
|
"Sort Options": "정렬 설정",
|
||||||
"Updated": "업데이트됨",
|
"Updated": "업데이트순",
|
||||||
"Size": "크기",
|
"Size": "크기순",
|
||||||
"Alphabetical": "알파벳순",
|
"Alphabetical": "알파벳순",
|
||||||
"Decending": "내림차순",
|
"Decending": "내림차순",
|
||||||
"Ascending": "오름차순",
|
"Ascending": "오름차순",
|
||||||
"Sort": "종류",
|
"Sort": "분류",
|
||||||
"Order": "주문하다",
|
"Order": "정렬",
|
||||||
"Info": "정보",
|
"Info": "정보",
|
||||||
"Delete": "삭제",
|
"Delete": "삭제",
|
||||||
"Hide Sphaira": "스파이라 숨기기",
|
"Hide Sphaira": "Sphaira 숨기기",
|
||||||
"Are you sure you want to delete ": "삭제하시겠습니까? ",
|
"Are you sure you want to delete ": "정말 삭제하시겠습니까? ",
|
||||||
"Install Forwarder": "포워더 설치",
|
"Install Forwarder": "바로가기 설치",
|
||||||
"WARNING: Installing forwarders will lead to a ban!": "경고: 전달자를 설치하면 금지됩니다!",
|
"WARNING: Installing forwarders will lead to a ban!": "주의: 바로가기 설치시 BAN 위험이 있습니다!",
|
||||||
"Back": "뒤쪽에",
|
"Back": "뒤로",
|
||||||
"Install": "설치하다",
|
"Install": "설치",
|
||||||
"Fs": "Fs",
|
"Fs": "파일 탐색기",
|
||||||
"App": "앱",
|
"App": "앱",
|
||||||
"Menu": "메뉴",
|
"Menu": "메뉴",
|
||||||
"Homebrew": "홈브류",
|
"Homebrew": "홈브류",
|
||||||
"FileBrowser": "파일브라우저",
|
"FileBrowser": "파일 탐색기",
|
||||||
"Open": "열려 있는",
|
"Open": "열기",
|
||||||
"Theme Options": "테마 옵션",
|
"Theme Options": "테마 설정",
|
||||||
"Select Theme": "테마 선택",
|
"Select Theme": "테마 선택",
|
||||||
"Shuffle": "혼합",
|
"Shuffle": "셔플",
|
||||||
"Music": "음악",
|
"Music": "BGM",
|
||||||
"Show Hidden": "숨겨진 표시",
|
"Show Hidden": "숨겨진 항목 표시",
|
||||||
"Folders First": "폴더 먼저",
|
"Folders First": "폴더 우선 정렬",
|
||||||
"Hidden Last": "숨겨진 마지막",
|
"Hidden Last": "숨겨진 항목 후순 정렬",
|
||||||
"Yes": "예",
|
"Yes": "예",
|
||||||
"No": "아니요",
|
"No": "아니요",
|
||||||
"Network Options": "네트워크 옵션",
|
"Network Options": "네트워크 설정",
|
||||||
"Nxlink": "Nxlink",
|
"Nxlink": "Nxlink",
|
||||||
"Check for update": "업데이트 확인",
|
"Check for update": "업데이트 확인",
|
||||||
"File Options": "파일 옵션",
|
"File Options": "파일 설정",
|
||||||
"Cut": "자르다",
|
"Cut": "잘라내기",
|
||||||
"Copy": "복사",
|
"Copy": "복사",
|
||||||
"Rename": "이름 바꾸기",
|
"Rename": "이름 바꾸기",
|
||||||
"Advanced Options": "파일 생성",
|
"Advanced Options": "고급 설정",
|
||||||
"Create File": "파일 생성",
|
"Create File": "파일 생성",
|
||||||
"Create Folder": "폴더 생성",
|
"Create Folder": "새 폴더",
|
||||||
"View as text": "텍스트로 보기",
|
"View as text": "텍스트로 보기",
|
||||||
"View as text (unfinished)": "텍스트로 보기(미완성)",
|
"View as text (unfinished)": "텍스트로 보기 (미완성)",
|
||||||
"Set Archive Bit": "보관 비트 설정",
|
"Set Archive Bit": "아카이브 비트 설정",
|
||||||
"AppStore Options": "앱스토어 옵션",
|
"AppStore Options": "앱스토어 설정",
|
||||||
"All": "모두",
|
"All": "전체",
|
||||||
"Games": "계략",
|
"Games": "게임",
|
||||||
"Emulators": "에뮬레이터",
|
"Emulators": "에뮬레이터",
|
||||||
"Tools": "도구",
|
"Tools": "도구",
|
||||||
"Advanced": "고급의",
|
"Advanced": "고급",
|
||||||
"Themes": "테마",
|
"Themes": "테마",
|
||||||
"Legacy": "유산",
|
"Legacy": "레거시",
|
||||||
"Misc": "기타",
|
"Misc": "기타",
|
||||||
"Downloads": "다운로드",
|
"Downloads": "다운로드순",
|
||||||
"Filter": "필터",
|
"Filter": "필터",
|
||||||
"Search": "찾다",
|
"Search": "검색",
|
||||||
"Menu Options": "메뉴 옵션",
|
"Menu Options": "메뉴",
|
||||||
"Header": "헤더",
|
"Header": "헤더",
|
||||||
"Theme": "주제",
|
"Theme": "테마",
|
||||||
"Network": "회로망",
|
"Network": "네트워크",
|
||||||
"Logging": "벌채 반출",
|
"Logging": "로깅",
|
||||||
"Enabled": "활성화됨",
|
"Enabled": "",
|
||||||
"Disabled": "장애가 있는",
|
"Disabled": "",
|
||||||
"Replace hbmenu on exit": "종료 시 hbmenu 교체",
|
"Replace hbmenu on exit": "종료 시 hbmenu 교체",
|
||||||
"Misc Options": "기타 옵션",
|
"Misc Options": "기타",
|
||||||
"Themezer": "테마저",
|
"Themezer": "Themezer",
|
||||||
"Irs": "국세청",
|
"Irs": "Joy-Con IR 카메라",
|
||||||
"Web": "편물",
|
"Web": "웹 브라우저",
|
||||||
"Download": "다운로드",
|
"Download": "다운로드",
|
||||||
"Next Page": "다음 페이지",
|
"Next Page": "다음 페이지",
|
||||||
"Prev Page": "이전 페이지",
|
"Prev Page": "이전 페이지",
|
||||||
"Pad ": "인주 ",
|
"Pad ": "Joy-Con ",
|
||||||
" (Unconnected)": " (연결되지 않음)",
|
" (Unconnected)": " (연결 없음)",
|
||||||
"HandHeld": "휴대용",
|
"HandHeld": "본체 연결",
|
||||||
" (Available)": " (사용 가능)",
|
" (Available)": " (사용 가능)",
|
||||||
"0 (Sideways)": "0(가로)",
|
"0 (Sideways)": "0 (좌회전)",
|
||||||
"90 (Flat)": "90(플랫)",
|
"90 (Flat)": "90 (정방향)",
|
||||||
"180 (-Sideways)": "180 (-옆으로)",
|
"180 (-Sideways)": "180 (우회전)",
|
||||||
"270 (Upside down)": "270 (거꾸로)",
|
"270 (Upside down)": "270 (역전)",
|
||||||
"Grey": "회색",
|
"Grey": "그레이",
|
||||||
"Ironbow": "아이언보우",
|
"Ironbow": "아이언보우",
|
||||||
"Green": "녹색",
|
"Green": "그린",
|
||||||
"Red": "빨간색",
|
"Red": "레드",
|
||||||
"Blue": "파란색",
|
"Blue": "블루",
|
||||||
"All leds": "모든 LED",
|
"All leds": "모든 LED 켜기",
|
||||||
"Bright group": "밝은 그룹",
|
"Bright group": "Bright LED 켜기",
|
||||||
"Dim group": "희미한 그룹",
|
"Dim group": "Dim LED 켜기",
|
||||||
"None": "없음",
|
"None": "LED 끄기",
|
||||||
"Normal image": "일반 이미지",
|
"Normal image": "일반",
|
||||||
"Negative image": "부정적인 이미지",
|
"Negative image": "반전",
|
||||||
"320x240": "320x240",
|
"320x240": "320×240",
|
||||||
"160x120": "160x120",
|
"160x120": "160×120",
|
||||||
"80x60": "80x60",
|
"80x60": "80×60",
|
||||||
"40x30": "40x30",
|
"40x30": "40×30",
|
||||||
"20x15": "20x15",
|
"20x15": "20×15",
|
||||||
"Controller": "제어 장치",
|
"Controller": "컨트롤러",
|
||||||
"Rotation": "회전",
|
"Rotation": "화면 회전",
|
||||||
"Colour": "색상",
|
"Colour": "팔레트",
|
||||||
"Light Target": "라이트 타겟",
|
"Light Target": "반사 표적",
|
||||||
"Gain": "얻다",
|
"Gain": "대비",
|
||||||
"Negative Image": "네거티브 이미지",
|
"Negative Image": "화상 이미지",
|
||||||
"Format": "체재",
|
"Format": "해상도",
|
||||||
"Trimming Format": "트리밍 형식",
|
"Trimming Format": "트리밍 해상도",
|
||||||
"External Light Filter": "외부 조명 필터",
|
"External Light Filter": "외부 조명 필터",
|
||||||
"Load Default": "기본값 로드",
|
"Load Default": "기본값으로 설정",
|
||||||
"No Internet": "인터넷 없음",
|
"No Internet": "네트워크 연결 없음",
|
||||||
"[Applet Mode]": "[애플릿 모드]",
|
"[Applet Mode]": "[애플릿 모드]",
|
||||||
"Language": "언어"
|
"Language": "언어"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"Launch": "Lançar",
|
"Launch": "Iniciar",
|
||||||
"Options": "Opções",
|
"Options": "Opções",
|
||||||
"Homebrew Options": "Opções de fermentação caseira",
|
"Homebrew Options": "Opções do Homebrew",
|
||||||
"Sort By": "Ordenar por",
|
"Sort By": "Ordenar por",
|
||||||
"Sort Options": "Opções de classificação",
|
"Sort Options": "Opções de classificação",
|
||||||
"Updated": "Atualizado",
|
"Updated": "Atualizado",
|
||||||
@@ -14,19 +14,19 @@
|
|||||||
"Info": "Informações",
|
"Info": "Informações",
|
||||||
"Delete": "Excluir",
|
"Delete": "Excluir",
|
||||||
"Hide Sphaira": "Esconder Sphaira",
|
"Hide Sphaira": "Esconder Sphaira",
|
||||||
"Are you sure you want to delete ": "Tem certeza de que deseja excluir ",
|
"Are you sure you want to delete ": "Excluir ",
|
||||||
"Install Forwarder": "Instalar encaminhador",
|
"Install Forwarder": "Instalar forwarder",
|
||||||
"WARNING: Installing forwarders will lead to a ban!": "AVISO: A instalação de encaminhadores levará ao banimento!",
|
"WARNING: Installing forwarders will lead to a ban!": "AVISO: Isso pode resultar em um banimento!",
|
||||||
"Back": "Voltar",
|
"Back": "Voltar",
|
||||||
"Install": "Instalar",
|
"Install": "Instalar",
|
||||||
"Fs": "Fs",
|
"Fs": "Fs",
|
||||||
"App": "Aplicativo",
|
"App": "Aplicativo",
|
||||||
"Menu": "Menu",
|
"Menu": "Menu",
|
||||||
"Homebrew": "Cerveja caseira",
|
"Homebrew": "Homebrew",
|
||||||
"FileBrowser": "Navegador de arquivos",
|
"FileBrowser": "Navegador de arquivos",
|
||||||
"Open": "Abrir",
|
"Open": "Abrir",
|
||||||
"Theme Options": "Opções de tema",
|
"Theme Options": "Opções de tema",
|
||||||
"Select Theme": "Selecione o tema",
|
"Select Theme": "Selecionar tema",
|
||||||
"Shuffle": "Embaralhar",
|
"Shuffle": "Embaralhar",
|
||||||
"Music": "Música",
|
"Music": "Música",
|
||||||
"Show Hidden": "Mostrar oculto",
|
"Show Hidden": "Mostrar oculto",
|
||||||
@@ -36,10 +36,10 @@
|
|||||||
"No": "Não",
|
"No": "Não",
|
||||||
"Network Options": "Opções de rede",
|
"Network Options": "Opções de rede",
|
||||||
"Nxlink": "Nxlink",
|
"Nxlink": "Nxlink",
|
||||||
"Check for update": "Verifique se há atualização",
|
"Check for update": "Verificar se há atualização",
|
||||||
"File Options": "Opções de arquivo",
|
"File Options": "Opções de arquivo",
|
||||||
"Cut": "Corte",
|
"Cut": "Cortar",
|
||||||
"Copy": "Cópia",
|
"Copy": "Copiar",
|
||||||
"Rename": "Renomear",
|
"Rename": "Renomear",
|
||||||
"Advanced Options": "Criar arquivo",
|
"Advanced Options": "Criar arquivo",
|
||||||
"Create File": "Criar arquivo",
|
"Create File": "Criar arquivo",
|
||||||
@@ -56,39 +56,39 @@
|
|||||||
"Themes": "Temas",
|
"Themes": "Temas",
|
||||||
"Legacy": "Legado",
|
"Legacy": "Legado",
|
||||||
"Misc": "Diversos",
|
"Misc": "Diversos",
|
||||||
"Downloads": "Transferências",
|
"Downloads": "Downloads",
|
||||||
"Filter": "Filtro",
|
"Filter": "Filtro",
|
||||||
"Search": "Procurar",
|
"Search": "Procurar",
|
||||||
"Menu Options": "Opções de cardápio",
|
"Menu Options": "Opções do menu",
|
||||||
"Header": "Cabeçalho",
|
"Header": "Cabeçalho",
|
||||||
"Theme": "Tema",
|
"Theme": "Tema",
|
||||||
"Network": "Rede",
|
"Network": "Rede",
|
||||||
"Logging": "Registro",
|
"Logging": "Logging",
|
||||||
"Enabled": "Habilitado",
|
"Enabled": "Habilitado",
|
||||||
"Disabled": "Desabilitado",
|
"Disabled": "Desabilitado",
|
||||||
"Replace hbmenu on exit": "Substitua hbmenu ao sair",
|
"Replace hbmenu on exit": "Substitua hbmenu ao sair",
|
||||||
"Misc Options": "Opções diversas",
|
"Misc Options": "Opções diversas",
|
||||||
"Themezer": "Temazer",
|
"Themezer": "Themezer",
|
||||||
"Irs": "Receita Federal",
|
"Irs": "Irs",
|
||||||
"Web": "Rede",
|
"Web": "Rede",
|
||||||
"Download": "Download",
|
"Download": "Download",
|
||||||
"Next Page": "Próxima página",
|
"Next Page": "Próxima página",
|
||||||
"Prev Page": "Página anterior",
|
"Prev Page": "Página anterior",
|
||||||
"Pad ": "Almofada ",
|
"Pad ": "Pad ",
|
||||||
" (Unconnected)": " (Desconectado)",
|
" (Unconnected)": " (Desconectado)",
|
||||||
"HandHeld": "Portátil",
|
"HandHeld": "Portátil",
|
||||||
" (Available)": " (Disponível)",
|
" (Available)": " (Disponível)",
|
||||||
"0 (Sideways)": "0 (lateralmente)",
|
"0 (Sideways)": "0 (Lateralmente)",
|
||||||
"90 (Flat)": "90 (plano)",
|
"90 (Flat)": "90 (plano)",
|
||||||
"180 (-Sideways)": "180 (-lateralmente)",
|
"180 (-Sideways)": "180 (-Lateralmente)",
|
||||||
"270 (Upside down)": "270 (de cabeça para baixo)",
|
"270 (Upside down)": "270 (De cabeça para baixo)",
|
||||||
"Grey": "Cinza",
|
"Grey": "Cinza",
|
||||||
"Ironbow": "Arco de Ferro",
|
"Ironbow": "Arco de ferro",
|
||||||
"Green": "Verde",
|
"Green": "Verde",
|
||||||
"Red": "Vermelho",
|
"Red": "Vermelho",
|
||||||
"Blue": "Azul",
|
"Blue": "Azul",
|
||||||
"All leds": "Todos os LEDs",
|
"All leds": "Todos os LEDs",
|
||||||
"Bright group": "Grupo brilhante",
|
"Bright group": "Grupo claro",
|
||||||
"Dim group": "Grupo escuro",
|
"Dim group": "Grupo escuro",
|
||||||
"None": "Nenhum",
|
"None": "Nenhum",
|
||||||
"Normal image": "Imagem normal",
|
"Normal image": "Imagem normal",
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
"80x60": "80x60",
|
"80x60": "80x60",
|
||||||
"40x30": "40x30",
|
"40x30": "40x30",
|
||||||
"20x15": "20x15",
|
"20x15": "20x15",
|
||||||
"Controller": "Controlador",
|
"Controller": "Controle",
|
||||||
"Rotation": "Rotação",
|
"Rotation": "Rotação",
|
||||||
"Colour": "Cor",
|
"Colour": "Cor",
|
||||||
"Light Target": "Alvo leve",
|
"Light Target": "Alvo leve",
|
||||||
@@ -109,6 +109,6 @@
|
|||||||
"External Light Filter": "Filtro de luz externo",
|
"External Light Filter": "Filtro de luz externo",
|
||||||
"Load Default": "Carregar padrão",
|
"Load Default": "Carregar padrão",
|
||||||
"No Internet": "Sem Internet",
|
"No Internet": "Sem Internet",
|
||||||
"[Applet Mode]": "[Modo miniaplicativo]",
|
"[Applet Mode]": "[Modo Applet]",
|
||||||
"Language": "Idioma"
|
"Language": "Idioma"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,98 +1,99 @@
|
|||||||
{
|
{
|
||||||
"Launch": "发射",
|
"Launch": "启动",
|
||||||
"Options": "选项",
|
"Options": "选项",
|
||||||
"Homebrew Options": "自制选项",
|
"Homebrew Options": "插件选项",
|
||||||
"Sort By": "排序方式",
|
"Sort By": "排序方式",
|
||||||
"Sort Options": "排序选项",
|
"Sort Options": "排序选项",
|
||||||
"Updated": "已更新",
|
"Updated": "最近使用",
|
||||||
"Size": "尺寸",
|
"Size": "大小",
|
||||||
"Alphabetical": "按字母顺序",
|
"Alphabetical": "按字母顺序",
|
||||||
"Decending": "降序",
|
"Decending": "降序",
|
||||||
"Ascending": "升序",
|
"Ascending": "升序",
|
||||||
"Sort": "种类",
|
"Sort": "排序",
|
||||||
"Order": "命令",
|
"Order": "顺序",
|
||||||
"Info": "信息",
|
"Info": "信息",
|
||||||
"Delete": "删除",
|
"Delete": "删除",
|
||||||
"Hide Sphaira": "隐藏斯菲拉",
|
"Hide Sphaira": "在插件列表中隐藏Sphaira",
|
||||||
"Are you sure you want to delete ": "您确定要删除吗 ",
|
"Are you sure you want to delete ": "您确定要删除吗 ",
|
||||||
"Install Forwarder": "安装转发器",
|
"Install Forwarder": "安装前端应用",
|
||||||
"WARNING: Installing forwarders will lead to a ban!": "警告:安装转发器将导致禁止!",
|
"WARNING: Installing forwarders will lead to a ban!": "警告:安装前端应用可能导致ban机!",
|
||||||
"Back": "后退",
|
"Back": "返回",
|
||||||
"Install": "安装",
|
"Install": "安装",
|
||||||
"Fs": "FS",
|
"Fs": "文件系统",
|
||||||
"App": "应用程序",
|
"App": "插件",
|
||||||
"Menu": "菜单",
|
"Menu": "菜单",
|
||||||
"Homebrew": "自制",
|
"Homebrew": "插件列表",
|
||||||
"FileBrowser": "文件浏览器",
|
"AppStore": "插件商店",
|
||||||
|
"FileBrowser": "文件浏览",
|
||||||
"Open": "打开",
|
"Open": "打开",
|
||||||
"Theme Options": "主题选项",
|
"Theme Options": "主题选项",
|
||||||
"Select Theme": "选择主题",
|
"Select Theme": "选择主题",
|
||||||
"Shuffle": "随机播放",
|
"Shuffle": "随机播放",
|
||||||
"Music": "音乐",
|
"Music": "音乐",
|
||||||
"Show Hidden": "显示隐藏",
|
"Show Hidden": "显示隐藏项目",
|
||||||
"Folders First": "文件夹优先",
|
"Folders First": "文件夹靠前",
|
||||||
"Hidden Last": "隐藏最后",
|
"Hidden Last": "隐藏项目置后",
|
||||||
"Yes": "是的",
|
"Yes": "是",
|
||||||
"No": "不",
|
"No": "否",
|
||||||
"Network Options": "网络选项",
|
"Network Options": "网络选项",
|
||||||
"Nxlink": "恩克斯联",
|
"Nxlink": "Nxlink开发工具",
|
||||||
"Check for update": "检查更新",
|
"Check for update": "检查更新",
|
||||||
"File Options": "文件选项",
|
"File Options": "文件选项",
|
||||||
"Cut": "切",
|
"Cut": "剪切",
|
||||||
"Copy": "复制",
|
"Copy": "复制",
|
||||||
"Rename": "重命名",
|
"Rename": "重命名",
|
||||||
"Advanced Options": "创建文件",
|
"Advanced Options": "高级选项",
|
||||||
"Create File": "创建文件",
|
"Create File": "新建文件",
|
||||||
"Create Folder": "创建文件夹",
|
"Create Folder": "新建文件夹",
|
||||||
"View as text": "以文本形式查看",
|
"View as text": "以文本形式查看",
|
||||||
"View as text (unfinished)": "以文本形式查看(未完成)",
|
"View as text (unfinished)": "以文本形式查看(未完善)",
|
||||||
"Set Archive Bit": "设置存档位",
|
"Set Archive Bit": "设置存档标志",
|
||||||
"AppStore Options": "应用商店选项",
|
"AppStore Options": "插件商店选项",
|
||||||
"All": "全部",
|
"All": "全部",
|
||||||
"Games": "游戏",
|
"Games": "游戏",
|
||||||
"Emulators": "模拟器",
|
"Emulators": "模拟器",
|
||||||
"Tools": "工具",
|
"Tools": "工具",
|
||||||
"Advanced": "先进的",
|
"Advanced": "高级",
|
||||||
"Themes": "主题",
|
"Themes": "主题",
|
||||||
"Legacy": "遗产",
|
"Legacy": "可更新",
|
||||||
"Misc": "杂项",
|
"Misc": "杂项",
|
||||||
"Downloads": "下载",
|
"Downloads": "下载",
|
||||||
"Filter": "筛选",
|
"Filter": "筛选",
|
||||||
"Search": "搜索",
|
"Search": "搜索",
|
||||||
"Menu Options": "菜单选项",
|
"Menu Options": "菜单选项",
|
||||||
"Header": "标头",
|
"Header": "标题",
|
||||||
"Theme": "主题",
|
"Theme": "主题",
|
||||||
"Network": "网络",
|
"Network": "网络",
|
||||||
"Logging": "记录",
|
"Logging": "日志",
|
||||||
"Enabled": "启用",
|
"Enabled": "启用",
|
||||||
"Disabled": "残疾人",
|
"Disabled": "禁用",
|
||||||
"Replace hbmenu on exit": "退出时替换 hbmenu",
|
"Replace hbmenu on exit": "退出后用Sphaira替换hbmenu",
|
||||||
"Misc Options": "其他选项",
|
"Misc Options": "杂项设置",
|
||||||
"Themezer": "主题器",
|
"Themezer": "在线主题",
|
||||||
"Irs": "国税局",
|
"Irs": "红外成像",
|
||||||
"Web": "网络",
|
"Web": "网页浏览器",
|
||||||
"Download": "下载",
|
"Download": "下载",
|
||||||
"Next Page": "下一页",
|
"Next Page": "下一页",
|
||||||
"Prev Page": "上一页",
|
"Prev Page": "上一页",
|
||||||
"Pad ": "软垫 ",
|
"Pad ": "手柄 ",
|
||||||
" (Unconnected)": " (未连接)",
|
" (Unconnected)": " (未连接)",
|
||||||
"HandHeld": "手持式",
|
"HandHeld": "手持式",
|
||||||
" (Available)": " (可用的)",
|
" (Available)": " (可用的)",
|
||||||
"0 (Sideways)": "0(横向)",
|
"0 (Sideways)": "0度",
|
||||||
"90 (Flat)": "90(平)",
|
"90 (Flat)": "90度",
|
||||||
"180 (-Sideways)": "180(-横向)",
|
"180 (-Sideways)": "180度",
|
||||||
"270 (Upside down)": "270(颠倒)",
|
"270 (Upside down)": "270度",
|
||||||
"Grey": "灰色的",
|
"Grey": "灰色",
|
||||||
"Ironbow": "铁弓",
|
"Ironbow": "紫黄",
|
||||||
"Green": "绿色的",
|
"Green": "绿色",
|
||||||
"Red": "红色的",
|
"Red": "红色",
|
||||||
"Blue": "蓝色的",
|
"Blue": "蓝色",
|
||||||
"All leds": "所有 LED",
|
"All leds": "全部",
|
||||||
"Bright group": "光明集团",
|
"Bright group": "亮色组",
|
||||||
"Dim group": "昏暗组",
|
"Dim group": "暗色组",
|
||||||
"None": "没有任何",
|
"None": "无",
|
||||||
"Normal image": "正常图像",
|
"Normal image": "正常图像",
|
||||||
"Negative image": "负像",
|
"Negative image": "负片图像",
|
||||||
"320x240": "320x240",
|
"320x240": "320x240",
|
||||||
"160x120": "160x120",
|
"160x120": "160x120",
|
||||||
"80x60": "80x60",
|
"80x60": "80x60",
|
||||||
@@ -101,14 +102,14 @@
|
|||||||
"Controller": "控制器",
|
"Controller": "控制器",
|
||||||
"Rotation": "旋转",
|
"Rotation": "旋转",
|
||||||
"Colour": "颜色",
|
"Colour": "颜色",
|
||||||
"Light Target": "光目标",
|
"Light Target": "光源目标",
|
||||||
"Gain": "获得",
|
"Gain": "增益",
|
||||||
"Negative Image": "负面形象",
|
"Negative Image": "负片图像",
|
||||||
"Format": "格式",
|
"Format": "格式",
|
||||||
"Trimming Format": "修剪格式",
|
"Trimming Format": "裁剪格式",
|
||||||
"External Light Filter": "外部滤光片",
|
"External Light Filter": "外部光滤镜",
|
||||||
"Load Default": "加载默认值",
|
"Load Default": "加载默认值",
|
||||||
"No Internet": "没有互联网",
|
"No Internet": "网络未连接",
|
||||||
"[Applet Mode]": "[小程序模式]",
|
"[Applet Mode]": "[小程序模式]",
|
||||||
"Language": "语言"
|
"Language": "语言"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
[meta]
|
[meta]
|
||||||
name="White not finished"
|
name=OLED Black
|
||||||
author=TotalJustice
|
author=iTotalJustice/Sanras
|
||||||
version=1.0.0
|
version=1.0.0
|
||||||
preview=romfs:/theme/preview.jpg
|
preview=romfs:/theme/preview.jpg
|
||||||
|
|
||||||
[theme]
|
[theme]
|
||||||
background=0xEBEBEBff
|
background=0x000000ff
|
||||||
cursor=romfs:/theme/cursor.png
|
cursor=romfs:/theme/cursor.png
|
||||||
cursor_drag=romfs:/theme/cursor_drag.png
|
cursor_drag=romfs:/theme/cursor_drag.png
|
||||||
grid=0x46464630
|
grid=0x46464640
|
||||||
selected=0x464646ff
|
selected=0x323232ff
|
||||||
selected_overlay=0x00ffc8ff
|
selected_overlay=0x00ffc8ff
|
||||||
text=0x2D2D2Dff
|
text=0xfbfbfbff
|
||||||
text_selected=0x3A50F0ff
|
text_selected=0x00ffc8ff
|
||||||
|
|
||||||
icon_audio=romfs:/theme/icon_audio.png
|
icon_audio=romfs:/theme/icon_audio.png
|
||||||
icon_video=romfs:/theme/icon_video.png
|
icon_video=romfs:/theme/icon_video.png
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
set(sphaira_VERSION 0.3.0)
|
set(sphaira_VERSION 0.4.0)
|
||||||
|
|
||||||
project(sphaira
|
project(sphaira
|
||||||
VERSION ${sphaira_VERSION}
|
VERSION ${sphaira_VERSION}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ namespace sphaira::i18n {
|
|||||||
bool init(long index);
|
bool init(long index);
|
||||||
void exit();
|
void exit();
|
||||||
|
|
||||||
|
std::string get(const char* str);
|
||||||
|
|
||||||
} // namespace sphaira::i18n
|
} // namespace sphaira::i18n
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|||||||
@@ -14,20 +14,20 @@ struct Hbini {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct NroEntry {
|
struct NroEntry {
|
||||||
fs::FsPath path;
|
fs::FsPath path{};
|
||||||
s64 size;
|
s64 size{};
|
||||||
NacpStruct nacp;
|
NacpStruct nacp{};
|
||||||
|
|
||||||
std::vector<u8> icon;
|
std::vector<u8> icon{};
|
||||||
u64 icon_size;
|
u64 icon_size{};
|
||||||
u64 icon_offset;
|
u64 icon_offset{};
|
||||||
|
|
||||||
FsTimeStampRaw timestamp;
|
FsTimeStampRaw timestamp{};
|
||||||
Hbini hbini;
|
Hbini hbini{};
|
||||||
|
|
||||||
int image; // nvg image
|
int image{}; // nvg image
|
||||||
int x,y,w,h; // image
|
int x,y,w,h{}; // image
|
||||||
bool is_nacp_valid;
|
bool is_nacp_valid{};
|
||||||
|
|
||||||
auto GetName() const -> const char* {
|
auto GetName() const -> const char* {
|
||||||
return nacp.lang[0].name;
|
return nacp.lang[0].name;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
namespace sphaira::swkbd {
|
namespace sphaira::swkbd {
|
||||||
|
|
||||||
Result ShowText(std::string& out, const char* guide = nullptr, s64 len_min = -1, s64 len_max = -1);
|
Result ShowText(std::string& out, const char* guide = nullptr, const char* initial = nullptr, s64 len_min = -1, s64 len_max = FS_MAX_PATH);
|
||||||
Result ShowNumPad(s64& out, const char* guide = nullptr, s64 len_min = -1, s64 len_max = -1);
|
Result ShowNumPad(s64& out, const char* guide = nullptr, const char* initial = nullptr, s64 len_min = -1, s64 len_max = FS_MAX_PATH);
|
||||||
|
|
||||||
} // namespace sphaira::swkbd
|
} // namespace sphaira::swkbd
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ struct Menu final : MenuBase {
|
|||||||
return m_entries;
|
return m_entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Result InstallHomebrew(const fs::FsPath& path, const NacpStruct& nacp, const std::vector<u8>& icon);
|
||||||
|
static Result InstallHomebrewFromPath(const fs::FsPath& path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr inline const char* INI_SECTION = "homebrew";
|
static constexpr inline const char* INI_SECTION = "homebrew";
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,15 @@
|
|||||||
|
|
||||||
namespace sphaira::ui::menu::main {
|
namespace sphaira::ui::menu::main {
|
||||||
|
|
||||||
|
enum class UpdateState {
|
||||||
|
// still downloading json from github
|
||||||
|
Pending,
|
||||||
|
// no update available.
|
||||||
|
None,
|
||||||
|
// update available!
|
||||||
|
Update,
|
||||||
|
};
|
||||||
|
|
||||||
// this holds 2 menus and allows for switching between them
|
// this holds 2 menus and allows for switching between them
|
||||||
struct MainMenu final : Widget {
|
struct MainMenu final : Widget {
|
||||||
MainMenu();
|
MainMenu();
|
||||||
@@ -31,7 +40,7 @@ private:
|
|||||||
std::string m_update_url{};
|
std::string m_update_url{};
|
||||||
std::string m_update_version{};
|
std::string m_update_version{};
|
||||||
std::string m_update_description{};
|
std::string m_update_description{};
|
||||||
bool m_update_avaliable{};
|
UpdateState m_update_state{UpdateState::Pending};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sphaira::ui::menu::main
|
} // namespace sphaira::ui::menu::main
|
||||||
|
|||||||
@@ -144,10 +144,8 @@ struct ElementEntry {
|
|||||||
|
|
||||||
enum ThemeEntryID {
|
enum ThemeEntryID {
|
||||||
ThemeEntryID_BACKGROUND,
|
ThemeEntryID_BACKGROUND,
|
||||||
ThemeEntryID_LOGO,
|
|
||||||
|
|
||||||
ThemeEntryID_GRID,
|
ThemeEntryID_GRID,
|
||||||
ThemeEntryID_GRID_HOVER,
|
|
||||||
ThemeEntryID_SELECTED,
|
ThemeEntryID_SELECTED,
|
||||||
ThemeEntryID_SELECTED_OVERLAY,
|
ThemeEntryID_SELECTED_OVERLAY,
|
||||||
ThemeEntryID_TEXT,
|
ThemeEntryID_TEXT,
|
||||||
|
|||||||
@@ -26,16 +26,6 @@ struct Widget : public Object {
|
|||||||
return m_focus;
|
return m_focus;
|
||||||
}
|
}
|
||||||
|
|
||||||
// void PushWidget(std::shared_ptr<Widget> widget);
|
|
||||||
// void PopWidget();
|
|
||||||
|
|
||||||
void SetParent(Widget* parent) {
|
|
||||||
m_parent = parent;
|
|
||||||
}
|
|
||||||
auto GetParent() -> Widget* {
|
|
||||||
return m_parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto HasAction(Button button) const -> bool;
|
auto HasAction(Button button) const -> bool;
|
||||||
void SetAction(Button button, Action action);
|
void SetAction(Button button, Action action);
|
||||||
void SetActions(std::same_as<std::pair<Button, Action>> auto ...args) {
|
void SetActions(std::same_as<std::pair<Button, Action>> auto ...args) {
|
||||||
@@ -66,8 +56,6 @@ struct Widget : public Object {
|
|||||||
using Actions = std::map<Button, Action>;
|
using Actions = std::map<Button, Action>;
|
||||||
// using Actions = std::unordered_map<Button, Action>;
|
// using Actions = std::unordered_map<Button, Action>;
|
||||||
Actions m_actions;
|
Actions m_actions;
|
||||||
Widget* m_parent{};
|
|
||||||
// std::vector<std::shared_ptr<Widget>> widgets;
|
|
||||||
bool m_focus{false};
|
bool m_focus{false};
|
||||||
bool m_pop{false};
|
bool m_pop{false};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -524,7 +524,7 @@ void App::Poll() {
|
|||||||
m_touch_info.finger_id = touch_state.touches[0].finger_id;
|
m_touch_info.finger_id = touch_state.touches[0].finger_id;
|
||||||
m_touch_info.is_touching = true;
|
m_touch_info.is_touching = true;
|
||||||
m_touch_info.is_tap = true;
|
m_touch_info.is_tap = true;
|
||||||
PlaySoundEffect(SoundEffect_Limit);
|
// PlaySoundEffect(SoundEffect_Limit);
|
||||||
} else if (touch_state.count >= 1 && m_touch_info.is_touching && m_touch_info.finger_id == touch_state.touches[0].finger_id) {
|
} else if (touch_state.count >= 1 && m_touch_info.is_touching && m_touch_info.finger_id == touch_state.touches[0].finger_id) {
|
||||||
m_touch_info.prev_x = m_touch_info.cur_x;
|
m_touch_info.prev_x = m_touch_info.cur_x;
|
||||||
m_touch_info.prev_y = m_touch_info.cur_y;
|
m_touch_info.prev_y = m_touch_info.cur_y;
|
||||||
@@ -597,39 +597,6 @@ auto App::GetVg() -> NVGcontext* {
|
|||||||
return g_app->vg;
|
return g_app->vg;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void App::UpdateList() {
|
|
||||||
const auto index_copy = this->index;
|
|
||||||
const auto start_copy = this->start;
|
|
||||||
|
|
||||||
else if (controller.down) {
|
|
||||||
// todo: replace with actual focus
|
|
||||||
PlaySoundEffect(SoundEffect_Limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (controller.any_direction()) {
|
|
||||||
if (index_copy != this->index) {
|
|
||||||
PlaySoundEffect(SoundEffect_Focus);
|
|
||||||
if (start_copy != this->start) {
|
|
||||||
// float r = randomGet64() % 100;
|
|
||||||
// float pitch = r / 100.0;
|
|
||||||
// plsrPlayerSetPitch(m_sound_ids[SoundEffect_Scroll], pitch);
|
|
||||||
PlaySoundEffect(SoundEffect_Scroll);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->index == 0 || this->index == this->nro_entries.size() || ((controller.down & HidNpadButton_AnyLeft) && this->index && this->index % 3 == 0) || ((controller.down & HidNpadButton_AnyRight) && this->index && (this->index + 1) % 3 == 0)) {
|
|
||||||
PlaySoundEffect(SoundEffect_Limit);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const auto mask = HidNpadButton_AnyDown | HidNpadButton_AnyUp | HidNpadButton_AnyLeft | HidNpadButton_AnyRight;
|
|
||||||
if (controller.down & mask) {
|
|
||||||
PlaySoundEffect(SoundEffect_Limit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void DrawElement(float x, float y, float w, float h, ThemeEntryID id) {
|
void DrawElement(float x, float y, float w, float h, ThemeEntryID id) {
|
||||||
const auto& e = g_app->m_theme.elements[id];
|
const auto& e = g_app->m_theme.elements[id];
|
||||||
|
|
||||||
@@ -738,12 +705,8 @@ void App::LoadTheme(const fs::FsPath& path) {
|
|||||||
app->PlaySoundEffect(SoundEffect_Music);
|
app->PlaySoundEffect(SoundEffect_Music);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (key == "logo") {
|
|
||||||
theme.elements[ThemeEntryID_LOGO] = app->LoadElement(value);
|
|
||||||
} else if (key == "grid") {
|
} else if (key == "grid") {
|
||||||
theme.elements[ThemeEntryID_GRID] = app->LoadElement(value);
|
theme.elements[ThemeEntryID_GRID] = app->LoadElement(value);
|
||||||
} else if (key == "grid_hover") {
|
|
||||||
theme.elements[ThemeEntryID_GRID_HOVER] = app->LoadElement(value);
|
|
||||||
} else if (key == "selected") {
|
} else if (key == "selected") {
|
||||||
theme.elements[ThemeEntryID_SELECTED] = app->LoadElement(value);
|
theme.elements[ThemeEntryID_SELECTED] = app->LoadElement(value);
|
||||||
} else if (key == "selected_overlay") {
|
} else if (key == "selected_overlay") {
|
||||||
@@ -862,8 +825,8 @@ App::App(const char* argv0) {
|
|||||||
m_app_path = argv0;
|
m_app_path = argv0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set pop-back if applet and we are hbmenu
|
// set if we are hbmenu
|
||||||
if (!IsApplication() && IsHbmenu()) {
|
if (IsHbmenu()) {
|
||||||
__nx_applet_exit_mode = 1;
|
__nx_applet_exit_mode = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1083,6 +1046,29 @@ App::~App() {
|
|||||||
} else {
|
} else {
|
||||||
log_write("success with copying over root file!\n");
|
log_write("success with copying over root file!\n");
|
||||||
}
|
}
|
||||||
|
} else if (IsHbmenu()) {
|
||||||
|
// check we have a version that's newer than current.
|
||||||
|
fs::FsNativeSd fs;
|
||||||
|
NacpStruct sphaira_nacp;
|
||||||
|
fs::FsPath sphaira_path = "/switch/sphaira/sphaira.nro";
|
||||||
|
Result rc;
|
||||||
|
|
||||||
|
rc = nro_get_nacp(sphaira_path, sphaira_nacp);
|
||||||
|
if (R_FAILED(rc) || std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
|
||||||
|
sphaira_path = "/switch/sphaira.nro";
|
||||||
|
rc = nro_get_nacp(sphaira_path, sphaira_nacp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// found sphaira, now lets get compare version
|
||||||
|
if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
|
||||||
|
if (std::strcmp(APP_VERSION, sphaira_nacp.display_version) < 0) {
|
||||||
|
if (R_FAILED(rc = fs.copy_entire_file(GetExePath(), sphaira_path, true))) {
|
||||||
|
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path, rc, R_MODULE(rc), R_DESCRIPTION(rc));
|
||||||
|
} else {
|
||||||
|
log_write("success with updating hbmenu!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (App::GetNxlinkEnable()) {
|
if (App::GetNxlinkEnable()) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ std::vector<u8> g_i18n_data;
|
|||||||
yyjson_doc* json;
|
yyjson_doc* json;
|
||||||
yyjson_val* root;
|
yyjson_val* root;
|
||||||
|
|
||||||
std::string get(const char* str, size_t len) {
|
std::string get_internal(const char* str, size_t len) {
|
||||||
if (!json || !root) {
|
if (!json || !root) {
|
||||||
log_write("no json or root\n");
|
log_write("no json or root\n");
|
||||||
return str;
|
return str;
|
||||||
@@ -78,8 +78,18 @@ bool init(long index) {
|
|||||||
default: lang_name = "en"; break;
|
default: lang_name = "en"; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fs::FsPath path = "romfs:/i18n/" + lang_name + ".json";
|
const fs::FsPath sdmc_path = "/config/sphaira/i18n/" + lang_name + ".json";
|
||||||
if (R_SUCCEEDED(fs::FsStdio().read_entire_file(path, g_i18n_data))) {
|
const fs::FsPath romfs_path = "romfs:/i18n/" + lang_name + ".json";
|
||||||
|
fs::FsPath path = sdmc_path;
|
||||||
|
|
||||||
|
// try and load override translation first
|
||||||
|
Result rc = fs::FsNativeSd().read_entire_file(path, g_i18n_data);
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
path = romfs_path;
|
||||||
|
rc = fs::FsStdio().read_entire_file(path, g_i18n_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
json = yyjson_read((const char*)g_i18n_data.data(), g_i18n_data.size(), YYJSON_READ_ALLOW_TRAILING_COMMAS|YYJSON_READ_ALLOW_COMMENTS|YYJSON_READ_ALLOW_INVALID_UNICODE);
|
json = yyjson_read((const char*)g_i18n_data.data(), g_i18n_data.size(), YYJSON_READ_ALLOW_TRAILING_COMMAS|YYJSON_READ_ALLOW_COMMENTS|YYJSON_READ_ALLOW_INVALID_UNICODE);
|
||||||
if (json) {
|
if (json) {
|
||||||
root = yyjson_doc_get_root(json);
|
root = yyjson_doc_get_root(json);
|
||||||
@@ -107,12 +117,16 @@ void exit() {
|
|||||||
g_i18n_data.clear();
|
g_i18n_data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string get(const char* str) {
|
||||||
|
return get_internal(str, std::strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sphaira::i18n
|
} // namespace sphaira::i18n
|
||||||
|
|
||||||
namespace literals {
|
namespace literals {
|
||||||
|
|
||||||
std::string operator"" _i18n(const char* str, size_t len) {
|
std::string operator"" _i18n(const char* str, size_t len) {
|
||||||
return sphaira::i18n::get(str, len);
|
return sphaira::i18n::get_internal(str, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ auto nro_parse_internal(fs::FsNative& fs, const fs::FsPath& path, NroEntry& entr
|
|||||||
} else {
|
} else {
|
||||||
R_TRY(fsFileRead(&f, data.header.size + asset.nacp.offset, &entry.nacp, sizeof(entry.nacp), FsReadOption_None, &bytes_read));
|
R_TRY(fsFileRead(&f, data.header.size + asset.nacp.offset, &entry.nacp, sizeof(entry.nacp), FsReadOption_None, &bytes_read));
|
||||||
entry.is_nacp_valid = true;
|
entry.is_nacp_valid = true;
|
||||||
log_write("got nacp\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// lazy load the icons
|
// lazy load the icons
|
||||||
@@ -241,7 +240,7 @@ auto nro_get_icon(const fs::FsPath& path) -> std::vector<u8> {
|
|||||||
R_TRY_RESULT(fsFileRead(&f, data.header.size, &asset, sizeof(asset), FsReadOption_None, &bytes_read), {});
|
R_TRY_RESULT(fsFileRead(&f, data.header.size, &asset, sizeof(asset), FsReadOption_None, &bytes_read), {});
|
||||||
R_UNLESS(asset.magic == NROASSETHEADER_MAGIC, {});
|
R_UNLESS(asset.magic == NROASSETHEADER_MAGIC, {});
|
||||||
|
|
||||||
return nro_get_icon_internal(&f, asset.icon.size, asset.icon.offset);
|
return nro_get_icon_internal(&f, asset.icon.size, data.header.size + asset.icon.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nro_get_nacp(const fs::FsPath& path, NacpStruct& nacp) -> Result {
|
auto nro_get_nacp(const fs::FsPath& path, NacpStruct& nacp) -> Result {
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ void loop(void* args) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
while (!g_quit) {
|
while (!g_quit) {
|
||||||
svcSleepThread(33'333'333);
|
svcSleepThread(1000000);
|
||||||
|
|
||||||
if (poll_network_change()) {
|
if (poll_network_change()) {
|
||||||
continue;
|
continue;
|
||||||
@@ -267,7 +267,7 @@ void loop(void* args) {
|
|||||||
sockaddr_in sa_remote{};
|
sockaddr_in sa_remote{};
|
||||||
|
|
||||||
while (!g_quit) {
|
while (!g_quit) {
|
||||||
svcSleepThread(33'333'333);
|
svcSleepThread(10000);
|
||||||
|
|
||||||
if (poll_network_change()) {
|
if (poll_network_change()) {
|
||||||
break;
|
break;
|
||||||
@@ -297,7 +297,7 @@ void loop(void* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fs::FsPath name{};
|
fs::FsPath name{};
|
||||||
if (namelen > sizeof(name)) {
|
if (namelen >= sizeof(name)) {
|
||||||
log_write("namelen is bigger than name: 0x%X\n", socketGetLastResult());
|
log_write("namelen is bigger than name: 0x%X\n", socketGetLastResult());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ struct Config {
|
|||||||
bool numpad{};
|
bool numpad{};
|
||||||
};
|
};
|
||||||
|
|
||||||
Result ShowInternal(Config& cfg, const char* guide, s64 len_min, s64 len_max) {
|
Result ShowInternal(Config& cfg, const char* guide, const char* initial, s64 len_min, s64 len_max) {
|
||||||
SwkbdConfig c;
|
SwkbdConfig c;
|
||||||
R_TRY(swkbdCreate(&c, 0));
|
R_TRY(swkbdCreate(&c, 0));
|
||||||
swkbdConfigMakePresetDefault(&c);
|
swkbdConfigMakePresetDefault(&c);
|
||||||
@@ -24,6 +24,10 @@ Result ShowInternal(Config& cfg, const char* guide, s64 len_min, s64 len_max) {
|
|||||||
swkbdConfigSetGuideText(&c, guide);
|
swkbdConfigSetGuideText(&c, guide);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (initial) {
|
||||||
|
swkbdConfigSetInitialText(&c, initial);
|
||||||
|
}
|
||||||
|
|
||||||
if (len_min >= 0) {
|
if (len_min >= 0) {
|
||||||
swkbdConfigSetStringLenMin(&c, len_min);
|
swkbdConfigSetStringLenMin(&c, len_min);
|
||||||
}
|
}
|
||||||
@@ -37,16 +41,16 @@ Result ShowInternal(Config& cfg, const char* guide, s64 len_min, s64 len_max) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Result ShowText(std::string& out, const char* guide, s64 len_min, s64 len_max) {
|
Result ShowText(std::string& out, const char* guide, const char* initial, s64 len_min, s64 len_max) {
|
||||||
Config cfg;
|
Config cfg;
|
||||||
R_TRY(ShowInternal(cfg, guide, len_min, len_max));
|
R_TRY(ShowInternal(cfg, guide, initial, len_min, len_max));
|
||||||
out = cfg.out_text;
|
out = cfg.out_text;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ShowNumPad(s64& out, const char* guide, s64 len_min, s64 len_max) {
|
Result ShowNumPad(s64& out, const char* guide, const char* initial, s64 len_min, s64 len_max) {
|
||||||
Config cfg;
|
Config cfg;
|
||||||
R_TRY(ShowInternal(cfg, guide, len_min, len_max));
|
R_TRY(ShowInternal(cfg, guide, initial, len_min, len_max));
|
||||||
out = std::atoll(cfg.out_text);
|
out = std::atoll(cfg.out_text);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -661,11 +661,13 @@ EntryMenu::EntryMenu(Entry& entry, const LazyImage& default_icon, Menu& menu)
|
|||||||
std::make_pair(Button::DPAD_DOWN | Button::RS_DOWN, Action{[this](){
|
std::make_pair(Button::DPAD_DOWN | Button::RS_DOWN, Action{[this](){
|
||||||
if (m_index < (m_options.size() - 1)) {
|
if (m_index < (m_options.size() - 1)) {
|
||||||
SetIndex(m_index + 1);
|
SetIndex(m_index + 1);
|
||||||
|
App::PlaySoundEffect(SoundEffect_Focus);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::DPAD_UP | Button::RS_UP, Action{[this](){
|
std::make_pair(Button::DPAD_UP | Button::RS_UP, Action{[this](){
|
||||||
if (m_index != 0) {
|
if (m_index != 0) {
|
||||||
SetIndex(m_index - 1);
|
SetIndex(m_index - 1);
|
||||||
|
App::PlaySoundEffect(SoundEffect_Focus);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::X, Action{"Options"_i18n, [this](){
|
std::make_pair(Button::X, Action{"Options"_i18n, [this](){
|
||||||
@@ -1436,7 +1438,7 @@ void Menu::Sort() {
|
|||||||
|
|
||||||
|
|
||||||
char subheader[128]{};
|
char subheader[128]{};
|
||||||
std::snprintf(subheader, sizeof(subheader), "Sort: %s | Filter: %s | Order: %s", SORT_STR[m_sort], FILTER_STR[m_filter], ORDER_STR[m_order]);
|
std::snprintf(subheader, sizeof(subheader), "Sort: %s | Filter: %s | Order: %s", i18n::get(SORT_STR[m_sort]), i18n::get(FILTER_STR[m_filter]), i18n::get(ORDER_STR[m_order]));
|
||||||
SetTitleSubHeading(subheader);
|
SetTitleSubHeading(subheader);
|
||||||
|
|
||||||
std::sort(m_entries_current.begin(), m_entries_current.end(), sorter);
|
std::sort(m_entries_current.begin(), m_entries_current.end(), sorter);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "ui/menus/filebrowser.hpp"
|
#include "ui/menus/filebrowser.hpp"
|
||||||
|
#include "ui/menus/homebrew.hpp"
|
||||||
#include "ui/sidebar.hpp"
|
#include "ui/sidebar.hpp"
|
||||||
#include "ui/option_box.hpp"
|
#include "ui/option_box.hpp"
|
||||||
#include "ui/popup_list.hpp"
|
#include "ui/popup_list.hpp"
|
||||||
@@ -303,8 +304,6 @@ auto get_collection(fs::FsNative& fs, const fs::FsPath& path, const fs::FsPath&
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
|
||||||
// recursion
|
|
||||||
auto get_collections(fs::FsNative& fs, const fs::FsPath& path, const fs::FsPath& parent_name, FsDirCollections& out) -> Result {
|
auto get_collections(fs::FsNative& fs, const fs::FsPath& path, const fs::FsPath& parent_name, FsDirCollections& out) -> Result {
|
||||||
// get a list of all the files / dirs
|
// get a list of all the files / dirs
|
||||||
FsDirCollection collection;
|
FsDirCollection collection;
|
||||||
@@ -323,48 +322,6 @@ auto get_collections(fs::FsNative& fs, const fs::FsPath& path, const fs::FsPath&
|
|||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
// normal
|
|
||||||
auto get_collections(fs::FsNative& fs, fs::FsPath path, fs::FsPath parent_name, FsDirCollections& out) -> Result {
|
|
||||||
// get a list of all the files / dirs
|
|
||||||
struct StoredStack {
|
|
||||||
fs::FsPath path;
|
|
||||||
fs::FsPath parent_name;
|
|
||||||
s64 index;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::stack<StoredStack> stack;
|
|
||||||
s64 index{};
|
|
||||||
// std::vector<StoredStack> indexes;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
FsDirCollection collection;
|
|
||||||
R_TRY(get_collection(fs, path, parent_name, collection, true, true, false));
|
|
||||||
out.emplace_back(collection);
|
|
||||||
|
|
||||||
if (collection.dirs.size()) {
|
|
||||||
stack.emplace(path, parent_name, index);
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FsDirCollection collection;
|
|
||||||
R_TRY(get_collection(fs, path, parent_name, collection, true, true, false));
|
|
||||||
log_write("got collection: %s parent_name: %s files: %zu dirs: %zu\n", path, parent_name, collection.files.size(), collection.dirs.size());
|
|
||||||
out.emplace_back(collection);
|
|
||||||
|
|
||||||
// for (size_t i = 0; i < collection.dirs.size(); i++) {
|
|
||||||
for (const auto&p : collection.dirs) {
|
|
||||||
// use heap as to not explode the stack
|
|
||||||
const auto new_path = std::make_unique<fs::FsPath>(Menu::GetNewPath(path, p.name));
|
|
||||||
const auto new_parent_name = std::make_unique<fs::FsPath>(Menu::GetNewPath(parent_name, p.name));
|
|
||||||
log_write("trying to get nested collection: %s parent_name: %s\n", *new_path, *new_parent_name);
|
|
||||||
R_TRY(get_collections(fs, *new_path, *new_parent_name, out));
|
|
||||||
}
|
|
||||||
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto get_collections(const fs::FsPath& path, const fs::FsPath& parent_name, FsDirCollections& out) -> Result {
|
auto get_collections(const fs::FsPath& path, const fs::FsPath& parent_name, FsDirCollections& out) -> Result {
|
||||||
fs::FsNativeSd fs;
|
fs::FsNativeSd fs;
|
||||||
@@ -392,6 +349,7 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
|
|||||||
std::make_pair(Button::DOWN, Action{[this](){
|
std::make_pair(Button::DOWN, Action{[this](){
|
||||||
if (m_index < (m_entries_current.size() - 1)) {
|
if (m_index < (m_entries_current.size() - 1)) {
|
||||||
SetIndex(m_index + 1);
|
SetIndex(m_index + 1);
|
||||||
|
App::PlaySoundEffect(SoundEffect_Scroll);
|
||||||
if (m_index - m_index_offset >= 8) {
|
if (m_index - m_index_offset >= 8) {
|
||||||
log_write("moved down\n");
|
log_write("moved down\n");
|
||||||
m_index_offset++;
|
m_index_offset++;
|
||||||
@@ -401,6 +359,7 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
|
|||||||
std::make_pair(Button::UP, Action{[this](){
|
std::make_pair(Button::UP, Action{[this](){
|
||||||
if (m_index != 0) {
|
if (m_index != 0) {
|
||||||
SetIndex(m_index - 1);
|
SetIndex(m_index - 1);
|
||||||
|
App::PlaySoundEffect(SoundEffect_Scroll);
|
||||||
if (m_index < m_index_offset ) {
|
if (m_index < m_index_offset ) {
|
||||||
log_write("moved up\n");
|
log_write("moved up\n");
|
||||||
m_index_offset--;
|
m_index_offset--;
|
||||||
@@ -571,12 +530,13 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
|
|||||||
}
|
}
|
||||||
|
|
||||||
// can't rename more than 1 file
|
// can't rename more than 1 file
|
||||||
if (m_entries_current.size() && m_selected_count < 2) {
|
if (m_entries_current.size() && !m_selected_count) {
|
||||||
options->Add(std::make_shared<SidebarEntryCallback>("Rename"_i18n, [this](){
|
options->Add(std::make_shared<SidebarEntryCallback>("Rename"_i18n, [this](){
|
||||||
std::string out;
|
std::string out;
|
||||||
if (R_SUCCEEDED(swkbd::ShowText(out, "Set New File Name", -1, FS_MAX_PATH)) && !out.empty()) {
|
const auto& entry = GetEntry();
|
||||||
const auto& entry = GetEntry();
|
const auto name = entry.GetName();
|
||||||
const auto src_path = GetNewPathCurrent();
|
if (R_SUCCEEDED(swkbd::ShowText(out, "Set New File Name", name.c_str())) && !out.empty() && out != name) {
|
||||||
|
const auto src_path = GetNewPath(entry);
|
||||||
const auto dst_path = GetNewPath(m_path, out);
|
const auto dst_path = GetNewPath(m_path, out);
|
||||||
|
|
||||||
Result rc;
|
Result rc;
|
||||||
@@ -603,7 +563,7 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
|
|||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryCallback>("Create File"_i18n, [this](){
|
options->Add(std::make_shared<SidebarEntryCallback>("Create File"_i18n, [this](){
|
||||||
std::string out;
|
std::string out;
|
||||||
if (R_SUCCEEDED(swkbd::ShowText(out, "Set File Name", -1, FS_MAX_PATH)) && !out.empty()) {
|
if (R_SUCCEEDED(swkbd::ShowText(out, "Set File Name")) && !out.empty()) {
|
||||||
fs::FsPath full_path;
|
fs::FsPath full_path;
|
||||||
if (out[0] == '/') {
|
if (out[0] == '/') {
|
||||||
full_path = out;
|
full_path = out;
|
||||||
@@ -624,7 +584,7 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
|
|||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryCallback>("Create Folder"_i18n, [this](){
|
options->Add(std::make_shared<SidebarEntryCallback>("Create Folder"_i18n, [this](){
|
||||||
std::string out;
|
std::string out;
|
||||||
if (R_SUCCEEDED(swkbd::ShowText(out, "Set Folder Name", -1, FS_MAX_PATH)) && !out.empty()) {
|
if (R_SUCCEEDED(swkbd::ShowText(out, "Set Folder Name")) && !out.empty()) {
|
||||||
fs::FsPath full_path;
|
fs::FsPath full_path;
|
||||||
if (out[0] == '/') {
|
if (out[0] == '/') {
|
||||||
full_path = out;
|
full_path = out;
|
||||||
@@ -648,18 +608,22 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_entries_current.size()) {
|
if (m_entries_current.size()) {
|
||||||
if (HasTypeInSelectedEntries(FsDirEntryType_File) && m_selected_count < 2 && !FindFileAssocFor().empty()) {
|
if (HasTypeInSelectedEntries(FsDirEntryType_File) && !m_selected_count && (GetEntry().GetExtension() == "nro" || !FindFileAssocFor().empty())) {
|
||||||
options->Add(std::make_shared<SidebarEntryCallback>("Install Forwarder"_i18n, [this](){;
|
options->Add(std::make_shared<SidebarEntryCallback>("Install Forwarder"_i18n, [this](){;
|
||||||
#if 1
|
|
||||||
App::Push(std::make_shared<OptionBox>(
|
App::Push(std::make_shared<OptionBox>(
|
||||||
"WARNING: Installing forwarders will lead to a ban!"_i18n,
|
"WARNING: Installing forwarders will lead to a ban!"_i18n,
|
||||||
"Back"_i18n, "Install"_i18n, 1, [this](auto op_index){
|
"Back"_i18n, "Install"_i18n, 0, [this](auto op_index){
|
||||||
if (op_index && *op_index) {
|
if (op_index && *op_index) {
|
||||||
InstallForwarder();
|
if (GetEntry().GetExtension() == "nro") {
|
||||||
|
if (R_FAILED(homebrew::Menu::InstallHomebrewFromPath(GetNewPathCurrent()))) {
|
||||||
|
log_write("failed to create forwarder\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
InstallForwarder();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
#endif
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,7 +773,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nvgSave(vg);
|
nvgSave(vg);
|
||||||
nvgScissor(vg, x + text_xoffset+65, y, w-(x+text_xoffset+65+50), h);
|
const auto txt_clip = std::min(GetY() + GetH(), y + h) - y;
|
||||||
|
nvgScissor(vg, x + text_xoffset+65, y, w-(x+text_xoffset+65+50), txt_clip);
|
||||||
gfx::drawText(vg, x + text_xoffset+65, y + (h / 2.f), 20.f, e.name, NULL, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE, theme->elements[text_id].colour);
|
gfx::drawText(vg, x + text_xoffset+65, y + (h / 2.f), 20.f, e.name, NULL, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE, theme->elements[text_id].colour);
|
||||||
nvgRestore(vg);
|
nvgRestore(vg);
|
||||||
|
|
||||||
@@ -910,25 +875,6 @@ void Menu::InstallForwarder() {
|
|||||||
title, items, [this, assoc_list](auto op_index){
|
title, items, [this, assoc_list](auto op_index){
|
||||||
if (op_index) {
|
if (op_index) {
|
||||||
const auto assoc = assoc_list[*op_index];
|
const auto assoc = assoc_list[*op_index];
|
||||||
#if 1
|
|
||||||
#if 0
|
|
||||||
NroEntry nro{};
|
|
||||||
log_write("parsing nro\n");
|
|
||||||
if (R_FAILED(nro_parse(assoc.path, nro))) {
|
|
||||||
log_write("failed nro parse\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OwoConfig config{};
|
|
||||||
config.nro_path = nro.path.toString();
|
|
||||||
// config.args = nro_add_arg_file(GetNewPathCurrent());
|
|
||||||
config.name = nro.nacp.lang[0].name;// + std::string{" | "} + file_name;
|
|
||||||
// config.name = file_name;
|
|
||||||
config.nacp = nro.nacp;
|
|
||||||
// config.icon = GetRomIcon(pbox, file_name, extension, database, nro);
|
|
||||||
config.icon = nro.icon;// GetRomIcon(pbox, file_name, extension, database, nro);
|
|
||||||
App::Install(config);
|
|
||||||
#else
|
|
||||||
log_write("pushing it\n");
|
log_write("pushing it\n");
|
||||||
App::Push(std::make_shared<ProgressBox>("Installing Forwarder", [assoc, this](auto pbox) -> bool {
|
App::Push(std::make_shared<ProgressBox>("Installing Forwarder", [assoc, this](auto pbox) -> bool {
|
||||||
log_write("inside callback\n");
|
log_write("inside callback\n");
|
||||||
@@ -961,36 +907,6 @@ void Menu::InstallForwarder() {
|
|||||||
|
|
||||||
return R_SUCCEEDED(App::Install(pbox, config));
|
return R_SUCCEEDED(App::Install(pbox, config));
|
||||||
}));
|
}));
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
|
|
||||||
const auto& assoc = assoc_list[*op_index];
|
|
||||||
log_write("doing nro parse\n");
|
|
||||||
|
|
||||||
NroEntry nro{};
|
|
||||||
if (R_SUCCEEDED(nro_parse(assoc.path.c_str(), nro))) {
|
|
||||||
log_write("got nro data\n");
|
|
||||||
std::string file_name = GetEntry().GetInternalName();
|
|
||||||
std::string extension = GetEntry().GetInternalExtension();
|
|
||||||
|
|
||||||
if (auto pos = file_name.find_last_of('.'); pos != std::string::npos) {
|
|
||||||
log_write("got filename\n");
|
|
||||||
file_name = file_name.substr(0, pos);
|
|
||||||
log_write("got filename2: %s\n\n", file_name.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto database = GetRomDatabaseFromPath(m_path);
|
|
||||||
|
|
||||||
OwoConfig config{};
|
|
||||||
config.nro_path = assoc.path;
|
|
||||||
config.args = nro_add_arg_file(GetNewPathCurrent());
|
|
||||||
config.name = nro.nacp.lang[0].name + std::string{" | "} + file_name;
|
|
||||||
// config.name = file_name;
|
|
||||||
config.nacp = nro.nacp;
|
|
||||||
config.icon = GetRomIcon(file_name, extension, database, nro);
|
|
||||||
App::Install(config);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
log_write("pressed B to skip launch...\n");
|
log_write("pressed B to skip launch...\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,38 +17,6 @@
|
|||||||
namespace sphaira::ui::menu::homebrew {
|
namespace sphaira::ui::menu::homebrew {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr const char* SORT_STR[] = {
|
|
||||||
"Updated",
|
|
||||||
"Size",
|
|
||||||
"Alphabetical",
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr const char* ORDER_STR[] = {
|
|
||||||
"Desc",
|
|
||||||
"Asc",
|
|
||||||
};
|
|
||||||
|
|
||||||
// returns seconds as: hh:mm:ss
|
|
||||||
auto TimeFormat(u64 sec) -> std::string {
|
|
||||||
char buf[9];
|
|
||||||
|
|
||||||
const auto s = sec % 60;
|
|
||||||
const auto h = sec / 60 % 60;
|
|
||||||
const auto d = sec / 60 / 60 % 24;
|
|
||||||
|
|
||||||
if (sec < 60) {
|
|
||||||
if (!sec) {
|
|
||||||
return "00:00:00";
|
|
||||||
}
|
|
||||||
std::snprintf(buf, sizeof(buf), "00:00:%02lu", s);
|
|
||||||
} else if (sec < 3600) {
|
|
||||||
std::snprintf(buf, sizeof(buf), "00:%02lu:%02lu", h, s);
|
|
||||||
} else {
|
|
||||||
std::snprintf(buf, sizeof(buf), "%02lu:%02lu:%02lu", d, h, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string{buf};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@@ -72,11 +40,10 @@ Menu::Menu() : MenuBase{"Homebrew"_i18n} {
|
|||||||
if (m_index < (m_entries.size() - 1)) {
|
if (m_index < (m_entries.size() - 1)) {
|
||||||
if (m_index < (m_entries.size() - 3)) {
|
if (m_index < (m_entries.size() - 3)) {
|
||||||
SetIndex(m_index + 3);
|
SetIndex(m_index + 3);
|
||||||
App::PlaySoundEffect(SoundEffect_Scroll);
|
|
||||||
} else {
|
} else {
|
||||||
SetIndex(m_entries.size() - 1);
|
SetIndex(m_entries.size() - 1);
|
||||||
App::PlaySoundEffect(SoundEffect_Scroll);
|
|
||||||
}
|
}
|
||||||
|
App::PlaySoundEffect(SoundEffect_Scroll);
|
||||||
if (m_index - m_start >= 9) {
|
if (m_index - m_start >= 9) {
|
||||||
log_write("moved down\n");
|
log_write("moved down\n");
|
||||||
m_start += 3;
|
m_start += 3;
|
||||||
@@ -153,7 +120,7 @@ Menu::Menu() : MenuBase{"Homebrew"_i18n} {
|
|||||||
options->Add(std::make_shared<SidebarEntryCallback>("Install Forwarder"_i18n, [this](){
|
options->Add(std::make_shared<SidebarEntryCallback>("Install Forwarder"_i18n, [this](){
|
||||||
App::Push(std::make_shared<OptionBox>(
|
App::Push(std::make_shared<OptionBox>(
|
||||||
"WARNING: Installing forwarders will lead to a ban!"_i18n,
|
"WARNING: Installing forwarders will lead to a ban!"_i18n,
|
||||||
"Back"_i18n, "Install"_i18n, 1, [this](auto op_index){
|
"Back"_i18n, "Install"_i18n, 0, [this](auto op_index){
|
||||||
if (op_index && *op_index) {
|
if (op_index && *op_index) {
|
||||||
InstallHomebrew();
|
InstallHomebrew();
|
||||||
}
|
}
|
||||||
@@ -263,11 +230,7 @@ void Menu::SetIndex(std::size_t index) {
|
|||||||
|
|
||||||
void Menu::InstallHomebrew() {
|
void Menu::InstallHomebrew() {
|
||||||
const auto& nro = m_entries[m_index];
|
const auto& nro = m_entries[m_index];
|
||||||
OwoConfig config{};
|
InstallHomebrew(nro.path, nro.nacp, nro.icon);
|
||||||
config.nro_path = nro.path.toString();
|
|
||||||
config.nacp = nro.nacp;
|
|
||||||
config.icon = nro.icon;
|
|
||||||
App::Install(config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::ScanHomebrew() {
|
void Menu::ScanHomebrew() {
|
||||||
@@ -275,22 +238,11 @@ void Menu::ScanHomebrew() {
|
|||||||
nro_scan("/switch", m_entries, m_hide_sphaira.Get());
|
nro_scan("/switch", m_entries, m_hide_sphaira.Get());
|
||||||
log_write("nros found: %zu time_taken: %.2f\n", m_entries.size(), ts.GetSeconds());
|
log_write("nros found: %zu time_taken: %.2f\n", m_entries.size(), ts.GetSeconds());
|
||||||
|
|
||||||
// todo: optimise this. maybe create a file per entry
|
|
||||||
// which would speed up parsing
|
|
||||||
for (auto& e : m_entries) {
|
|
||||||
if (ini_hassection(e.path, App::PLAYLOG_PATH)) {
|
|
||||||
// log_write("has section for: %s\n", e.path);
|
|
||||||
e.hbini.timestamp = ini_getl(e.path, "timestamp", 0, App::PLAYLOG_PATH);
|
|
||||||
}
|
|
||||||
e.image = 0; // images are lazy loaded
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
struct IniUser {
|
struct IniUser {
|
||||||
std::vector<NroEntry>& entires;
|
std::vector<NroEntry>& entires;
|
||||||
Hbini* ini;
|
Hbini* ini;
|
||||||
std::string last_section;
|
std::string last_section;
|
||||||
} ini_user { m_entries };
|
} ini_user{ m_entries };
|
||||||
|
|
||||||
ini_browse([](const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, void *UserData) -> int {
|
ini_browse([](const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, void *UserData) -> int {
|
||||||
auto user = static_cast<IniUser*>(UserData);
|
auto user = static_cast<IniUser*>(UserData);
|
||||||
@@ -308,14 +260,16 @@ void Menu::ScanHomebrew() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (user->ini) {
|
if (user->ini) {
|
||||||
|
if (!strcmp(Key, "timestamp")) {
|
||||||
|
user->ini->timestamp = atoi(Value);
|
||||||
|
} else if (!strcmp(Key, "launch_count")) {
|
||||||
|
user->ini->launch_count = atoi(Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// app->
|
// log_write("found: %s %s %s\n", Section, Key, Value);
|
||||||
log_write("found: %s %s %s\n", Section, Key, Value);
|
|
||||||
return 1;
|
return 1;
|
||||||
}, &ini_user, App::PLAYLOG_PATH);
|
}, &ini_user, App::PLAYLOG_PATH);
|
||||||
#endif
|
|
||||||
|
|
||||||
this->Sort();
|
this->Sort();
|
||||||
SetIndex(0);
|
SetIndex(0);
|
||||||
@@ -374,4 +328,19 @@ void Menu::SortAndFindLastFile() {
|
|||||||
Sort();
|
Sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result Menu::InstallHomebrew(const fs::FsPath& path, const NacpStruct& nacp, const std::vector<u8>& icon) {
|
||||||
|
OwoConfig config{};
|
||||||
|
config.nro_path = path.toString();
|
||||||
|
config.nacp = nacp;
|
||||||
|
config.icon = icon;
|
||||||
|
return App::Install(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Menu::InstallHomebrewFromPath(const fs::FsPath& path) {
|
||||||
|
NacpStruct nacp;
|
||||||
|
R_TRY(nro_get_nacp(path, nacp))
|
||||||
|
const auto icon = nro_get_icon(path);
|
||||||
|
return InstallHomebrew(path, nacp, icon);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sphaira::ui::menu::homebrew
|
} // namespace sphaira::ui::menu::homebrew
|
||||||
|
|||||||
@@ -1,22 +1,26 @@
|
|||||||
#include "ui/menus/main_menu.hpp"
|
#include "ui/menus/main_menu.hpp"
|
||||||
|
#include "ui/menus/irs_menu.hpp"
|
||||||
|
#include "ui/menus/themezer.hpp"
|
||||||
|
|
||||||
#include "ui/sidebar.hpp"
|
#include "ui/sidebar.hpp"
|
||||||
#include "ui/popup_list.hpp"
|
#include "ui/popup_list.hpp"
|
||||||
#include "ui/option_box.hpp"
|
#include "ui/option_box.hpp"
|
||||||
|
#include "ui/progress_box.hpp"
|
||||||
|
#include "ui/error_box.hpp"
|
||||||
|
|
||||||
#include "app.hpp"
|
#include "app.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "download.hpp"
|
#include "download.hpp"
|
||||||
#include "defines.hpp"
|
#include "defines.hpp"
|
||||||
#include "ui/menus/irs_menu.hpp"
|
|
||||||
#include "ui/menus/themezer.hpp"
|
|
||||||
#include "web.hpp"
|
#include "web.hpp"
|
||||||
#include "i18n.hpp"
|
#include "i18n.hpp"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <minizip/unzip.h>
|
||||||
|
|
||||||
namespace sphaira::ui::menu::main {
|
namespace sphaira::ui::menu::main {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#if 0
|
|
||||||
bool parseSearch(const char *parse_string, const char *filter, char* new_string) {
|
bool parseSearch(const char *parse_string, const char *filter, char* new_string) {
|
||||||
char c;
|
char c;
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
@@ -40,37 +44,159 @@ bool parseSearch(const char *parse_string, const char *filter, char* new_string)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string version) -> bool {
|
||||||
|
static fs::FsPath zip_out{"/switch/sphaira/cache/update.zip"};
|
||||||
|
constexpr auto chunk_size = 1024 * 512; // 512KiB
|
||||||
|
|
||||||
|
fs::FsNativeSd fs;
|
||||||
|
R_TRY_RESULT(fs.GetFsOpenResult(), false);
|
||||||
|
|
||||||
|
// 1. download the zip
|
||||||
|
if (!pbox->ShouldExit()) {
|
||||||
|
pbox->NewTransfer("Downloading "_i18n + version);
|
||||||
|
log_write("starting download: %s\n", url.c_str());
|
||||||
|
|
||||||
|
DownloadClearCache(url);
|
||||||
|
if (!DownloadFile(url, zip_out, "", [pbox](u32 dltotal, u32 dlnow, u32 ultotal, u32 ulnow){
|
||||||
|
if (pbox->ShouldExit()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pbox->UpdateTransfer(dlnow, dltotal);
|
||||||
|
return true;
|
||||||
|
})) {
|
||||||
|
log_write("error with download\n");
|
||||||
|
// push popup error box
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ON_SCOPE_EXIT(fs.DeleteFile(zip_out));
|
||||||
|
|
||||||
|
// 2. extract the zip
|
||||||
|
if (!pbox->ShouldExit()) {
|
||||||
|
auto zfile = unzOpen64(zip_out);
|
||||||
|
if (!zfile) {
|
||||||
|
log_write("failed to open zip: %s\n", zip_out);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ON_SCOPE_EXIT(unzClose(zfile));
|
||||||
|
|
||||||
|
unz_global_info64 pglobal_info;
|
||||||
|
if (UNZ_OK != unzGetGlobalInfo64(zfile, &pglobal_info)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < pglobal_info.number_entry; i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
if (UNZ_OK != unzGoToNextFile(zfile)) {
|
||||||
|
log_write("failed to unzGoToNextFile\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UNZ_OK != unzOpenCurrentFile(zfile)) {
|
||||||
|
log_write("failed to open current file\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ON_SCOPE_EXIT(unzCloseCurrentFile(zfile));
|
||||||
|
|
||||||
|
unz_file_info64 info;
|
||||||
|
fs::FsPath file_path;
|
||||||
|
if (UNZ_OK != unzGetCurrentFileInfo64(zfile, &info, file_path, sizeof(file_path), 0, 0, 0, 0)) {
|
||||||
|
log_write("failed to get current info\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_path[0] != '/') {
|
||||||
|
file_path = fs::AppendPath("/", file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result rc;
|
||||||
|
if (file_path[strlen(file_path) -1] == '/') {
|
||||||
|
if (R_FAILED(rc = fs.CreateDirectoryRecursively(file_path)) && rc != FsError_ResultPathAlreadyExists) {
|
||||||
|
log_write("failed to create folder: %s 0x%04X\n", file_path, rc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Result rc;
|
||||||
|
if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_ResultPathAlreadyExists) {
|
||||||
|
log_write("failed to create file: %s 0x%04X\n", file_path, rc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FsFile f;
|
||||||
|
if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) {
|
||||||
|
log_write("failed to open file: %s 0x%04X\n", file_path, rc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ON_SCOPE_EXIT(fsFileClose(&f));
|
||||||
|
|
||||||
|
if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) {
|
||||||
|
log_write("failed to set file size: %s 0x%04X\n", file_path, rc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<char> buf(chunk_size);
|
||||||
|
u64 offset{};
|
||||||
|
while (offset < info.uncompressed_size) {
|
||||||
|
if (pbox->ShouldExit()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto bytes_read = unzReadCurrentFile(zfile, buf.data(), buf.size());
|
||||||
|
if (bytes_read <= 0) {
|
||||||
|
// log_write("failed to read zip file: %s\n", inzip.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) {
|
||||||
|
log_write("failed to write file: %s 0x%04X\n", file_path, rc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pbox->UpdateTransfer(offset, info.uncompressed_size);
|
||||||
|
offset += bytes_read;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_write("finished update :)\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
MainMenu::MainMenu() {
|
MainMenu::MainMenu() {
|
||||||
#if 0
|
// todo: replace below with yyjson, this is old code from ams updater, lol.
|
||||||
DownloadMemoryAsync("https://api.github.com/repos/ITotalJustice/sys-patch/releases/latest", [this](std::vector<u8>& data, bool success){
|
DownloadMemoryAsync("https://api.github.com/repos/ITotalJustice/sphaira/releases/latest", "", [this](std::vector<u8>& data, bool success){
|
||||||
data.push_back('\0');
|
data.push_back('\0');
|
||||||
auto raw_str = (const char*)data.data();
|
auto raw_str = (const char*)data.data();
|
||||||
char out_str[0x301];
|
char out_str[0x301];
|
||||||
|
|
||||||
if (parseSearch(raw_str, "tag_name\":\"", out_str)) {
|
if (parseSearch(raw_str, "tag_name\":\"", out_str)) {
|
||||||
m_update_version = out_str;
|
m_update_version = out_str;
|
||||||
if (strcasecmp("v1.5.0", m_update_version.c_str())) {
|
if (std::strcmp(APP_VERSION, m_update_version.c_str()) < 0) {
|
||||||
m_update_avaliable = true;
|
m_update_state = UpdateState::Update;
|
||||||
|
App::Notify("Update avaliable: "_i18n + m_update_version);
|
||||||
|
} else {
|
||||||
|
m_update_state = UpdateState::None;
|
||||||
}
|
}
|
||||||
log_write("FOUND IT : %s\n", out_str);
|
log_write("found update tag : %s vs %s\n", APP_VERSION, out_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parseSearch(raw_str, "browser_download_url\":\"", out_str)) {
|
if (parseSearch(raw_str, "browser_download_url\":\"", out_str)) {
|
||||||
m_update_url = out_str;
|
m_update_url = out_str;
|
||||||
log_write("FOUND IT : %s\n", out_str);
|
log_write("found download url : %s\n", out_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parseSearch(raw_str, "body\":\"", out_str)) {
|
if (parseSearch(raw_str, "body\":\"", out_str)) {
|
||||||
m_update_description = out_str;
|
m_update_description = out_str;
|
||||||
// m_update_description.replace("\r\n\r\n", "\n");
|
// m_update_description.replace("\r\n\r\n", "\n");
|
||||||
log_write("FOUND IT : %s\n", out_str);
|
log_write("found description : %s\n", out_str);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
#endif
|
|
||||||
|
|
||||||
AddOnLPress();
|
AddOnLPress();
|
||||||
AddOnRPress();
|
AddOnRPress();
|
||||||
@@ -128,22 +254,26 @@ MainMenu::MainMenu() {
|
|||||||
options->Add(std::make_shared<SidebarEntryBool>("Nxlink"_i18n, App::GetNxlinkEnable(), [this](bool& enable){
|
options->Add(std::make_shared<SidebarEntryBool>("Nxlink"_i18n, App::GetNxlinkEnable(), [this](bool& enable){
|
||||||
App::SetNxlinkEnable(enable);
|
App::SetNxlinkEnable(enable);
|
||||||
}, "Enabled"_i18n, "Disabled"_i18n));
|
}, "Enabled"_i18n, "Disabled"_i18n));
|
||||||
options->Add(std::make_shared<SidebarEntryCallback>("Check for update"_i18n, [this](){
|
|
||||||
App::Notify("Not Implemented"_i18n);
|
if (m_update_state == UpdateState::Update) {
|
||||||
}));
|
options->Add(std::make_shared<SidebarEntryCallback>("Download update: "_i18n + m_update_version, [this](){
|
||||||
|
App::Push(std::make_shared<ProgressBox>("Downloading "_i18n + m_update_version, [this](auto pbox){
|
||||||
|
return InstallUpdate(pbox, m_update_url, m_update_version);
|
||||||
|
}, [this](bool success){
|
||||||
|
if (success) {
|
||||||
|
m_update_state = UpdateState::None;
|
||||||
|
} else {
|
||||||
|
App::Push(std::make_shared<ui::ErrorBox>(MAKERESULT(351, 1), "Failed to download update"));
|
||||||
|
}
|
||||||
|
}, 2));
|
||||||
|
}));
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryArray>("Language"_i18n, language_items, [this, language_items](std::size_t& index_out){
|
options->Add(std::make_shared<SidebarEntryArray>("Language"_i18n, language_items, [this, language_items](std::size_t& index_out){
|
||||||
App::SetLanguage(index_out);
|
App::SetLanguage(index_out);
|
||||||
}, (std::size_t)App::GetLanguage()));
|
}, (std::size_t)App::GetLanguage()));
|
||||||
|
|
||||||
if (m_update_avaliable) {
|
|
||||||
std::string str = "Update avaliable: "_i18n + m_update_version;
|
|
||||||
options->Add(std::make_shared<SidebarEntryCallback>(str, [this](){
|
|
||||||
App::Notify("Not Implemented"_i18n);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryBool>("Logging"_i18n, App::GetLogEnable(), [this](bool& enable){
|
options->Add(std::make_shared<SidebarEntryBool>("Logging"_i18n, App::GetLogEnable(), [this](bool& enable){
|
||||||
App::SetLogEnable(enable);
|
App::SetLogEnable(enable);
|
||||||
}, "Enabled"_i18n, "Disabled"_i18n));
|
}, "Enabled"_i18n, "Disabled"_i18n));
|
||||||
|
|||||||
@@ -32,6 +32,13 @@ void MenuBase::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
u32 strength{};
|
u32 strength{};
|
||||||
u32 ip{};
|
u32 ip{};
|
||||||
|
|
||||||
|
const auto _time = time(NULL);
|
||||||
|
struct tm tm{};
|
||||||
|
const auto gmt = gmtime(&_time);
|
||||||
|
if (gmt) {
|
||||||
|
tm = *gmt;
|
||||||
|
}
|
||||||
|
|
||||||
// todo: app thread poll every 1s and this query the result
|
// todo: app thread poll every 1s and this query the result
|
||||||
psmGetBatteryChargePercentage(&battery_percetange);
|
psmGetBatteryChargePercentage(&battery_percetange);
|
||||||
psmGetChargerType(&charger_type);
|
psmGetChargerType(&charger_type);
|
||||||
@@ -54,7 +61,8 @@ void MenuBase::Draw(NVGcontext* vg, Theme* theme) {
|
|||||||
start_x -= spacing;
|
start_x -= spacing;
|
||||||
|
|
||||||
// draw("version %s", APP_VERSION);
|
// draw("version %s", APP_VERSION);
|
||||||
draw("%u%%", battery_percetange);
|
draw("%u\uFE6A", battery_percetange);
|
||||||
|
draw("%02u:%02u:%02u", tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||||
if (ip) {
|
if (ip) {
|
||||||
draw("%u.%u.%u.%u", ip&0xFF, (ip>>8)&0xFF, (ip>>16)&0xFF, (ip>>24)&0xFF);
|
draw("%u.%u.%u.%u", ip&0xFF, (ip>>8)&0xFF, (ip>>16)&0xFF, (ip>>24)&0xFF);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -508,7 +508,7 @@ Menu::Menu() : MenuBase{"Themezer"_i18n} {
|
|||||||
|
|
||||||
options->Add(std::make_shared<SidebarEntryCallback>("Page"_i18n, [this](){
|
options->Add(std::make_shared<SidebarEntryCallback>("Page"_i18n, [this](){
|
||||||
s64 out;
|
s64 out;
|
||||||
if (R_SUCCEEDED(swkbd::ShowNumPad(out, "Enter Page Number", -1, 3))) {
|
if (R_SUCCEEDED(swkbd::ShowNumPad(out, "Enter Page Number", nullptr, -1, 3))) {
|
||||||
if (out < m_page_index_max) {
|
if (out < m_page_index_max) {
|
||||||
m_page_index = out;
|
m_page_index = out;
|
||||||
PackListDownload();
|
PackListDownload();
|
||||||
|
|||||||
@@ -457,7 +457,7 @@ void drawButton(NVGcontext* vg, float x, float y, float size, Button button) {
|
|||||||
drawText(vg, x, y, size, getButton(button), nullptr, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE, getColour(Colour::WHITE));
|
drawText(vg, x, y, size, getButton(button), nullptr, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE, getColour(Colour::WHITE));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawButtons(NVGcontext* vg, const Widget::Actions& actions, const NVGcolor& c, float start_x) {
|
void drawButtons(NVGcontext* vg, const Widget::Actions& _actions, const NVGcolor& c, float start_x) {
|
||||||
nvgBeginPath(vg);
|
nvgBeginPath(vg);
|
||||||
nvgFontSize(vg, 24.f);
|
nvgFontSize(vg, 24.f);
|
||||||
nvgTextAlign(vg, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP);
|
nvgTextAlign(vg, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP);
|
||||||
@@ -467,6 +467,22 @@ void drawButtons(NVGcontext* vg, const Widget::Actions& actions, const NVGcolor&
|
|||||||
const float y = 675.f;
|
const float y = 675.f;
|
||||||
float bounds[4]{};
|
float bounds[4]{};
|
||||||
|
|
||||||
|
// swaps L/R position, idc how shit this is, it's called once per frame.
|
||||||
|
std::vector<std::pair<Button, Action>> actions;
|
||||||
|
actions.reserve(_actions.size());
|
||||||
|
|
||||||
|
for (const auto a: _actions) {
|
||||||
|
// swap
|
||||||
|
if (a.first == Button::R && actions.size() && actions.back().first == Button::L) {
|
||||||
|
const auto s = actions.back();
|
||||||
|
actions.back() = a;
|
||||||
|
actions.emplace_back(s);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
actions.emplace_back(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& [button, action] : actions) {
|
for (const auto& [button, action] : actions) {
|
||||||
if (action.IsHidden() || action.m_hint.empty()) {
|
if (action.IsHidden() || action.m_hint.empty()) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ auto OptionBox::Setup(std::size_t index) -> void {
|
|||||||
m_entries[m_index].Selected(false);
|
m_entries[m_index].Selected(false);
|
||||||
m_index--;
|
m_index--;
|
||||||
m_entries[m_index].Selected(true);
|
m_entries[m_index].Selected(true);
|
||||||
|
App::PlaySoundEffect(SoundEffect_Focus);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::RIGHT, Action{[this](){
|
std::make_pair(Button::RIGHT, Action{[this](){
|
||||||
@@ -130,6 +131,7 @@ auto OptionBox::Setup(std::size_t index) -> void {
|
|||||||
m_entries[m_index].Selected(false);
|
m_entries[m_index].Selected(false);
|
||||||
m_index++;
|
m_index++;
|
||||||
m_entries[m_index].Selected(true);
|
m_entries[m_index].Selected(true);
|
||||||
|
App::PlaySoundEffect(SoundEffect_Focus);
|
||||||
}
|
}
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::A, Action{[this](){
|
std::make_pair(Button::A, Action{[this](){
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ auto PopupList::Update(Controller* controller, TouchInfo* touch) -> void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto old_index = m_index;
|
||||||
|
|
||||||
if (controller->GotDown(Button::DOWN) && m_index < (m_items.size() - 1)) {
|
if (controller->GotDown(Button::DOWN) && m_index < (m_items.size() - 1)) {
|
||||||
m_index++;
|
m_index++;
|
||||||
m_selected_y += m_block.h;
|
m_selected_y += m_block.h;
|
||||||
@@ -98,7 +100,10 @@ auto PopupList::Update(Controller* controller, TouchInfo* touch) -> void {
|
|||||||
m_selected_y -= m_block.h;
|
m_selected_y -= m_block.h;
|
||||||
}
|
}
|
||||||
|
|
||||||
OnLayoutChange();
|
if (old_index != m_index) {
|
||||||
|
App::PlaySoundEffect(SoundEffect_Scroll);
|
||||||
|
OnLayoutChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PopupList::OnLayoutChange() -> void {
|
auto PopupList::OnLayoutChange() -> void {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ ScrollableText::ScrollableText(const std::string& text, float x, float y, float
|
|||||||
}
|
}
|
||||||
m_y_off -= m_step;
|
m_y_off -= m_step;
|
||||||
m_index++;
|
m_index++;
|
||||||
|
App::PlaySoundEffect(SoundEffect_Scroll);
|
||||||
}}),
|
}}),
|
||||||
std::make_pair(Button::LS_UP, Action{[this](){
|
std::make_pair(Button::LS_UP, Action{[this](){
|
||||||
if (m_y_off == m_y_off_base) {
|
if (m_y_off == m_y_off_base) {
|
||||||
@@ -34,6 +35,7 @@ ScrollableText::ScrollableText(const std::string& text, float x, float y, float
|
|||||||
}
|
}
|
||||||
m_y_off += m_step;
|
m_y_off += m_step;
|
||||||
m_index--;
|
m_index--;
|
||||||
|
App::PlaySoundEffect(SoundEffect_Scroll);
|
||||||
}})
|
}})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -234,6 +234,7 @@ auto Sidebar::Update(Controller* controller, TouchInfo* touch) -> void {
|
|||||||
|
|
||||||
// if we moved
|
// if we moved
|
||||||
if (m_index != old_index) {
|
if (m_index != old_index) {
|
||||||
|
App::PlaySoundEffect(SoundEffect_Scroll);
|
||||||
m_items[old_index]->OnFocusLost();
|
m_items[old_index]->OnFocusLost();
|
||||||
m_items[m_index]->OnFocusGained();
|
m_items[m_index]->OnFocusGained();
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ namespace sphaira::ui {
|
|||||||
void Widget::Update(Controller* controller, TouchInfo* touch) {
|
void Widget::Update(Controller* controller, TouchInfo* touch) {
|
||||||
for (const auto& [button, action] : m_actions) {
|
for (const auto& [button, action] : m_actions) {
|
||||||
if ((action.m_type & ActionType::DOWN) && controller->GotDown(button)) {
|
if ((action.m_type & ActionType::DOWN) && controller->GotDown(button)) {
|
||||||
|
if (static_cast<u64>(button) & static_cast<u64>(Button::ANY_BUTTON)) {
|
||||||
|
App::PlaySoundEffect(SoundEffect_Focus);
|
||||||
|
}
|
||||||
action.Invoke(true);
|
action.Invoke(true);
|
||||||
App::PlaySoundEffect(SoundEffect_Focus);
|
|
||||||
}
|
}
|
||||||
else if ((action.m_type & ActionType::UP) && controller->GotUp(button)) {
|
else if ((action.m_type & ActionType::UP) && controller->GotUp(button)) {
|
||||||
action.Invoke(false);
|
action.Invoke(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user