* rewind

* more
This commit is contained in:
Logan McNaughton
2026-05-30 21:00:33 +02:00
committed by GitHub
parent 7fc2412c9c
commit 864175fae6
22 changed files with 468 additions and 313 deletions
+26 -21
View File
@@ -2,7 +2,7 @@
msgid ""
msgstr ""
"Project-Id-Version: gopher64\n"
"POT-Creation-Date: 2026-05-25 08:28+0000\n"
"POT-Creation-Date: 2026-05-30 16:03+0000\n"
"PO-Revision-Date: 2026-05-11 12:00+0000\n"
"Last-Translator: \n"
"Language-Team: German\n"
@@ -47,37 +47,37 @@ msgctxt "About"
msgid "Donate (via GitHub)"
msgstr "Spenden (über GitHub)"
#: src/ui/gui/appwindow.slint:151
#: src/ui/gui/appwindow.slint:152
msgctxt "Menu"
msgid "Local Game"
msgstr "Lokales Spiel"
#: src/ui/gui/appwindow.slint:155
#: src/ui/gui/appwindow.slint:156
msgctxt "Menu"
msgid "Controller Config"
msgstr "Controller-Konfiguration"
#: src/ui/gui/appwindow.slint:159
#: src/ui/gui/appwindow.slint:160
msgctxt "Menu"
msgid "Netplay"
msgstr "Netplay"
#: src/ui/gui/appwindow.slint:163
#: src/ui/gui/appwindow.slint:164
msgctxt "Menu"
msgid "Cheats"
msgstr "Cheats"
#: src/ui/gui/appwindow.slint:167
#: src/ui/gui/appwindow.slint:168
msgctxt "Menu"
msgid "RetroAchievements"
msgstr "RetroAchievements"
#: src/ui/gui/appwindow.slint:171
#: src/ui/gui/appwindow.slint:172
msgctxt "Menu"
msgid "Settings"
msgstr "Einstellungen"
#: src/ui/gui/appwindow.slint:175
#: src/ui/gui/appwindow.slint:176
msgctxt "Menu"
msgid "About"
msgstr "Über"
@@ -97,7 +97,7 @@ msgctxt "Cheats"
msgid "Clear Cheats For All ROMs"
msgstr "Cheats für alle ROMs löschen"
#: src/ui/gui/cheat_page.slint:88
#: src/ui/gui/cheat_page.slint:83
msgctxt "Cheats"
msgid "No Cheats Available"
msgstr "Keine Cheats verfügbar"
@@ -485,62 +485,67 @@ msgctxt "RetroAchievements"
msgid "View Supported Games"
msgstr "Unterstützte Spiele anzeigen"
#: src/ui/gui/settings_page.slint:23
#: src/ui/gui/settings_page.slint:24
msgctxt "Settings"
msgid "Settings"
msgstr "Einstellungen"
#: src/ui/gui/settings_page.slint:34
#: src/ui/gui/settings_page.slint:35
msgctxt "Settings"
msgid "Resolution:"
msgstr "Auflösung:"
#: src/ui/gui/settings_page.slint:48
#: src/ui/gui/settings_page.slint:49
msgctxt "Settings"
msgid "SSAA downscaling"
msgstr "SSAA-Herunterskalierung"
#: src/ui/gui/settings_page.slint:56
#: src/ui/gui/settings_page.slint:57
msgctxt "Settings"
msgid "Integer Scaling"
msgstr "Pixelgenaue Skalierung"
#: src/ui/gui/settings_page.slint:64
#: src/ui/gui/settings_page.slint:65
msgctxt "Settings"
msgid "Fullscreen"
msgstr "Vollbild"
#: src/ui/gui/settings_page.slint:72
#: src/ui/gui/settings_page.slint:73
msgctxt "Settings"
msgid "Widescreen (stretch)"
msgstr "16:9 (gestreckt)"
#: src/ui/gui/settings_page.slint:80
#: src/ui/gui/settings_page.slint:81
msgctxt "Settings"
msgid "VSync"
msgstr "VSync"
#: src/ui/gui/settings_page.slint:88
#: src/ui/gui/settings_page.slint:89
msgctxt "Settings"
msgid "Apply CRT shader"
msgstr "CRT-Shader anwenden"
#: src/ui/gui/settings_page.slint:100
#: src/ui/gui/settings_page.slint:101
msgctxt "Settings"
msgid "Overclock N64 CPU (may cause bugs)"
msgstr "N64-CPU übertakten (kann Fehler verursachen)"
#: src/ui/gui/settings_page.slint:108
#: src/ui/gui/settings_page.slint:109
msgctxt "Settings"
msgid "Disable Expansion Pak"
msgstr "Expansion Pak deaktivieren"
#: src/ui/gui/settings_page.slint:116
#: src/ui/gui/settings_page.slint:117
msgctxt "Settings"
msgid "Enable Rewind"
msgstr "Rewind aktivieren"
#: src/ui/gui/settings_page.slint:125
msgctxt "Settings"
msgid "Emulate UNFLoader"
msgstr "UNFLoader emulieren"
#: src/ui/gui/settings_page.slint:124
#: src/ui/gui/settings_page.slint:133
msgctxt "Settings"
msgid "Emulate VRU"
msgstr "VRU emulieren"
+26 -21
View File
@@ -2,7 +2,7 @@
msgid ""
msgstr ""
"Project-Id-Version: gopher64\n"
"POT-Creation-Date: 2026-05-25 08:28+0000\n"
"POT-Creation-Date: 2026-05-30 16:03+0000\n"
"PO-Revision-Date: 2026-05-11 12:00+0000\n"
"Last-Translator: Gemini\n"
"Language-Team: Spanish (Spain)\n"
@@ -47,37 +47,37 @@ msgctxt "About"
msgid "Donate (via GitHub)"
msgstr "Donar (a través de GitHub)"
#: src/ui/gui/appwindow.slint:151
#: src/ui/gui/appwindow.slint:152
msgctxt "Menu"
msgid "Local Game"
msgstr "Juego local"
#: src/ui/gui/appwindow.slint:155
#: src/ui/gui/appwindow.slint:156
msgctxt "Menu"
msgid "Controller Config"
msgstr "Config. del mando"
#: src/ui/gui/appwindow.slint:159
#: src/ui/gui/appwindow.slint:160
msgctxt "Menu"
msgid "Netplay"
msgstr "Netplay"
#: src/ui/gui/appwindow.slint:163
#: src/ui/gui/appwindow.slint:164
msgctxt "Menu"
msgid "Cheats"
msgstr "Trucos"
#: src/ui/gui/appwindow.slint:167
#: src/ui/gui/appwindow.slint:168
msgctxt "Menu"
msgid "RetroAchievements"
msgstr "RetroAchievements"
#: src/ui/gui/appwindow.slint:171
#: src/ui/gui/appwindow.slint:172
msgctxt "Menu"
msgid "Settings"
msgstr "Ajustes"
#: src/ui/gui/appwindow.slint:175
#: src/ui/gui/appwindow.slint:176
msgctxt "Menu"
msgid "About"
msgstr "Acerca de"
@@ -97,7 +97,7 @@ msgctxt "Cheats"
msgid "Clear Cheats For All ROMs"
msgstr "Borrar trucos de todas las ROMs"
#: src/ui/gui/cheat_page.slint:88
#: src/ui/gui/cheat_page.slint:83
msgctxt "Cheats"
msgid "No Cheats Available"
msgstr "No hay trucos disponibles"
@@ -485,62 +485,67 @@ msgctxt "RetroAchievements"
msgid "View Supported Games"
msgstr "Ver juegos compatibles"
#: src/ui/gui/settings_page.slint:23
#: src/ui/gui/settings_page.slint:24
msgctxt "Settings"
msgid "Settings"
msgstr "Ajustes"
#: src/ui/gui/settings_page.slint:34
#: src/ui/gui/settings_page.slint:35
msgctxt "Settings"
msgid "Resolution:"
msgstr "Resolución:"
#: src/ui/gui/settings_page.slint:48
#: src/ui/gui/settings_page.slint:49
msgctxt "Settings"
msgid "SSAA downscaling"
msgstr "Reducción de escala SSAA"
#: src/ui/gui/settings_page.slint:56
#: src/ui/gui/settings_page.slint:57
msgctxt "Settings"
msgid "Integer Scaling"
msgstr "Escalado por enteros"
#: src/ui/gui/settings_page.slint:64
#: src/ui/gui/settings_page.slint:65
msgctxt "Settings"
msgid "Fullscreen"
msgstr "Pantalla completa"
#: src/ui/gui/settings_page.slint:72
#: src/ui/gui/settings_page.slint:73
msgctxt "Settings"
msgid "Widescreen (stretch)"
msgstr "Pantalla ancha (estirado)"
#: src/ui/gui/settings_page.slint:80
#: src/ui/gui/settings_page.slint:81
msgctxt "Settings"
msgid "VSync"
msgstr "Sincronización vertical (VSync)"
#: src/ui/gui/settings_page.slint:88
#: src/ui/gui/settings_page.slint:89
msgctxt "Settings"
msgid "Apply CRT shader"
msgstr "Aplicar sombreador CRT"
#: src/ui/gui/settings_page.slint:100
#: src/ui/gui/settings_page.slint:101
msgctxt "Settings"
msgid "Overclock N64 CPU (may cause bugs)"
msgstr "Overclock CPU N64 (puede causar errores)"
#: src/ui/gui/settings_page.slint:108
#: src/ui/gui/settings_page.slint:109
msgctxt "Settings"
msgid "Disable Expansion Pak"
msgstr "Desactivar Expansion Pak"
#: src/ui/gui/settings_page.slint:116
#: src/ui/gui/settings_page.slint:117
msgctxt "Settings"
msgid "Enable Rewind"
msgstr "Activar rebobinado"
#: src/ui/gui/settings_page.slint:125
msgctxt "Settings"
msgid "Emulate UNFLoader"
msgstr "Emular UNFLoader"
#: src/ui/gui/settings_page.slint:124
#: src/ui/gui/settings_page.slint:133
msgctxt "Settings"
msgid "Emulate VRU"
msgstr "Emular VRU"
+26 -21
View File
@@ -2,7 +2,7 @@
msgid ""
msgstr ""
"Project-Id-Version: gopher64\n"
"POT-Creation-Date: 2026-05-25 08:28+0000\n"
"POT-Creation-Date: 2026-05-30 16:03+0000\n"
"PO-Revision-Date: 2026-05-11 12:00+0000\n"
"Last-Translator: \n"
"Language-Team: French (France)\n"
@@ -47,37 +47,37 @@ msgctxt "About"
msgid "Donate (via GitHub)"
msgstr "Faire un don (via GitHub)"
#: src/ui/gui/appwindow.slint:151
#: src/ui/gui/appwindow.slint:152
msgctxt "Menu"
msgid "Local Game"
msgstr "Jeu local"
#: src/ui/gui/appwindow.slint:155
#: src/ui/gui/appwindow.slint:156
msgctxt "Menu"
msgid "Controller Config"
msgstr "Configuration manette"
#: src/ui/gui/appwindow.slint:159
#: src/ui/gui/appwindow.slint:160
msgctxt "Menu"
msgid "Netplay"
msgstr "Netplay"
#: src/ui/gui/appwindow.slint:163
#: src/ui/gui/appwindow.slint:164
msgctxt "Menu"
msgid "Cheats"
msgstr "Triche"
#: src/ui/gui/appwindow.slint:167
#: src/ui/gui/appwindow.slint:168
msgctxt "Menu"
msgid "RetroAchievements"
msgstr "RetroAchievements"
#: src/ui/gui/appwindow.slint:171
#: src/ui/gui/appwindow.slint:172
msgctxt "Menu"
msgid "Settings"
msgstr "Paramètres"
#: src/ui/gui/appwindow.slint:175
#: src/ui/gui/appwindow.slint:176
msgctxt "Menu"
msgid "About"
msgstr "À propos"
@@ -97,7 +97,7 @@ msgctxt "Cheats"
msgid "Clear Cheats For All ROMs"
msgstr "Effacer la triche pour toutes les ROMs"
#: src/ui/gui/cheat_page.slint:88
#: src/ui/gui/cheat_page.slint:83
msgctxt "Cheats"
msgid "No Cheats Available"
msgstr "Aucune triche disponible"
@@ -486,62 +486,67 @@ msgctxt "RetroAchievements"
msgid "View Supported Games"
msgstr "Voir les jeux pris en charge"
#: src/ui/gui/settings_page.slint:23
#: src/ui/gui/settings_page.slint:24
msgctxt "Settings"
msgid "Settings"
msgstr "Paramètres"
#: src/ui/gui/settings_page.slint:34
#: src/ui/gui/settings_page.slint:35
msgctxt "Settings"
msgid "Resolution:"
msgstr "Résolution :"
#: src/ui/gui/settings_page.slint:48
#: src/ui/gui/settings_page.slint:49
msgctxt "Settings"
msgid "SSAA downscaling"
msgstr "Réduction SSAA"
#: src/ui/gui/settings_page.slint:56
#: src/ui/gui/settings_page.slint:57
msgctxt "Settings"
msgid "Integer Scaling"
msgstr "Mise à l'échelle par entiers"
#: src/ui/gui/settings_page.slint:64
#: src/ui/gui/settings_page.slint:65
msgctxt "Settings"
msgid "Fullscreen"
msgstr "Plein écran"
#: src/ui/gui/settings_page.slint:72
#: src/ui/gui/settings_page.slint:73
msgctxt "Settings"
msgid "Widescreen (stretch)"
msgstr "Écran large (étiré)"
#: src/ui/gui/settings_page.slint:80
#: src/ui/gui/settings_page.slint:81
msgctxt "Settings"
msgid "VSync"
msgstr "Synchro verticale"
#: src/ui/gui/settings_page.slint:88
#: src/ui/gui/settings_page.slint:89
msgctxt "Settings"
msgid "Apply CRT shader"
msgstr "Appliquer le filtre CRT"
#: src/ui/gui/settings_page.slint:100
#: src/ui/gui/settings_page.slint:101
msgctxt "Settings"
msgid "Overclock N64 CPU (may cause bugs)"
msgstr "Surcharger le CPU N64 (risque de bugs)"
#: src/ui/gui/settings_page.slint:108
#: src/ui/gui/settings_page.slint:109
msgctxt "Settings"
msgid "Disable Expansion Pak"
msgstr "Désactiver l'Expansion Pak"
#: src/ui/gui/settings_page.slint:116
#: src/ui/gui/settings_page.slint:117
msgctxt "Settings"
msgid "Enable Rewind"
msgstr "Activer le rembobinage"
#: src/ui/gui/settings_page.slint:125
msgctxt "Settings"
msgid "Emulate UNFLoader"
msgstr "Émuler UNFLoader"
#: src/ui/gui/settings_page.slint:124
#: src/ui/gui/settings_page.slint:133
msgctxt "Settings"
msgid "Emulate VRU"
msgstr "Émuler le VRU"
+26 -21
View File
@@ -2,7 +2,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2026-05-25 08:28+0000\n"
"POT-Creation-Date: 2026-05-30 16:03+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -47,37 +47,37 @@ msgctxt "About"
msgid "Donate (via GitHub)"
msgstr ""
#: src/ui/gui/appwindow.slint:151
#: src/ui/gui/appwindow.slint:152
msgctxt "Menu"
msgid "Local Game"
msgstr ""
#: src/ui/gui/appwindow.slint:155
#: src/ui/gui/appwindow.slint:156
msgctxt "Menu"
msgid "Controller Config"
msgstr ""
#: src/ui/gui/appwindow.slint:159
#: src/ui/gui/appwindow.slint:160
msgctxt "Menu"
msgid "Netplay"
msgstr ""
#: src/ui/gui/appwindow.slint:163
#: src/ui/gui/appwindow.slint:164
msgctxt "Menu"
msgid "Cheats"
msgstr ""
#: src/ui/gui/appwindow.slint:167
#: src/ui/gui/appwindow.slint:168
msgctxt "Menu"
msgid "RetroAchievements"
msgstr ""
#: src/ui/gui/appwindow.slint:171
#: src/ui/gui/appwindow.slint:172
msgctxt "Menu"
msgid "Settings"
msgstr ""
#: src/ui/gui/appwindow.slint:175
#: src/ui/gui/appwindow.slint:176
msgctxt "Menu"
msgid "About"
msgstr ""
@@ -97,7 +97,7 @@ msgctxt "Cheats"
msgid "Clear Cheats For All ROMs"
msgstr ""
#: src/ui/gui/cheat_page.slint:88
#: src/ui/gui/cheat_page.slint:83
msgctxt "Cheats"
msgid "No Cheats Available"
msgstr ""
@@ -483,62 +483,67 @@ msgctxt "RetroAchievements"
msgid "View Supported Games"
msgstr ""
#: src/ui/gui/settings_page.slint:23
#: src/ui/gui/settings_page.slint:24
msgctxt "Settings"
msgid "Settings"
msgstr ""
#: src/ui/gui/settings_page.slint:34
#: src/ui/gui/settings_page.slint:35
msgctxt "Settings"
msgid "Resolution:"
msgstr ""
#: src/ui/gui/settings_page.slint:48
#: src/ui/gui/settings_page.slint:49
msgctxt "Settings"
msgid "SSAA downscaling"
msgstr ""
#: src/ui/gui/settings_page.slint:56
#: src/ui/gui/settings_page.slint:57
msgctxt "Settings"
msgid "Integer Scaling"
msgstr ""
#: src/ui/gui/settings_page.slint:64
#: src/ui/gui/settings_page.slint:65
msgctxt "Settings"
msgid "Fullscreen"
msgstr ""
#: src/ui/gui/settings_page.slint:72
#: src/ui/gui/settings_page.slint:73
msgctxt "Settings"
msgid "Widescreen (stretch)"
msgstr ""
#: src/ui/gui/settings_page.slint:80
#: src/ui/gui/settings_page.slint:81
msgctxt "Settings"
msgid "VSync"
msgstr ""
#: src/ui/gui/settings_page.slint:88
#: src/ui/gui/settings_page.slint:89
msgctxt "Settings"
msgid "Apply CRT shader"
msgstr ""
#: src/ui/gui/settings_page.slint:100
#: src/ui/gui/settings_page.slint:101
msgctxt "Settings"
msgid "Overclock N64 CPU (may cause bugs)"
msgstr ""
#: src/ui/gui/settings_page.slint:108
#: src/ui/gui/settings_page.slint:109
msgctxt "Settings"
msgid "Disable Expansion Pak"
msgstr ""
#: src/ui/gui/settings_page.slint:116
#: src/ui/gui/settings_page.slint:117
msgctxt "Settings"
msgid "Enable Rewind"
msgstr ""
#: src/ui/gui/settings_page.slint:125
msgctxt "Settings"
msgid "Emulate UNFLoader"
msgstr ""
#: src/ui/gui/settings_page.slint:124
#: src/ui/gui/settings_page.slint:133
msgctxt "Settings"
msgid "Emulate VRU"
msgstr ""
+26 -21
View File
@@ -2,7 +2,7 @@
msgid ""
msgstr ""
"Project-Id-Version: gopher64\n"
"POT-Creation-Date: 2026-05-25 08:28+0000\n"
"POT-Creation-Date: 2026-05-30 16:03+0000\n"
"PO-Revision-Date: 2026-05-11 12:00+0000\n"
"Last-Translator: \n"
"Language-Team: Japanese\n"
@@ -47,37 +47,37 @@ msgctxt "About"
msgid "Donate (via GitHub)"
msgstr "GitHubで寄付"
#: src/ui/gui/appwindow.slint:151
#: src/ui/gui/appwindow.slint:152
msgctxt "Menu"
msgid "Local Game"
msgstr "ローカルゲーム"
#: src/ui/gui/appwindow.slint:155
#: src/ui/gui/appwindow.slint:156
msgctxt "Menu"
msgid "Controller Config"
msgstr "コントローラー設定"
#: src/ui/gui/appwindow.slint:159
#: src/ui/gui/appwindow.slint:160
msgctxt "Menu"
msgid "Netplay"
msgstr "ネットプレイ"
#: src/ui/gui/appwindow.slint:163
#: src/ui/gui/appwindow.slint:164
msgctxt "Menu"
msgid "Cheats"
msgstr "チート"
#: src/ui/gui/appwindow.slint:167
#: src/ui/gui/appwindow.slint:168
msgctxt "Menu"
msgid "RetroAchievements"
msgstr "RetroAchievements"
#: src/ui/gui/appwindow.slint:171
#: src/ui/gui/appwindow.slint:172
msgctxt "Menu"
msgid "Settings"
msgstr "設定"
#: src/ui/gui/appwindow.slint:175
#: src/ui/gui/appwindow.slint:176
msgctxt "Menu"
msgid "About"
msgstr "バージョン情報"
@@ -97,7 +97,7 @@ msgctxt "Cheats"
msgid "Clear Cheats For All ROMs"
msgstr "すべてのROMのチートをクリア"
#: src/ui/gui/cheat_page.slint:88
#: src/ui/gui/cheat_page.slint:83
msgctxt "Cheats"
msgid "No Cheats Available"
msgstr "利用できるチートはありません"
@@ -483,62 +483,67 @@ msgctxt "RetroAchievements"
msgid "View Supported Games"
msgstr "対応ゲームを表示"
#: src/ui/gui/settings_page.slint:23
#: src/ui/gui/settings_page.slint:24
msgctxt "Settings"
msgid "Settings"
msgstr "設定"
#: src/ui/gui/settings_page.slint:34
#: src/ui/gui/settings_page.slint:35
msgctxt "Settings"
msgid "Resolution:"
msgstr "解像度:"
#: src/ui/gui/settings_page.slint:48
#: src/ui/gui/settings_page.slint:49
msgctxt "Settings"
msgid "SSAA downscaling"
msgstr "SSAAダウンスケール"
#: src/ui/gui/settings_page.slint:56
#: src/ui/gui/settings_page.slint:57
msgctxt "Settings"
msgid "Integer Scaling"
msgstr "整数倍スケーリング"
#: src/ui/gui/settings_page.slint:64
#: src/ui/gui/settings_page.slint:65
msgctxt "Settings"
msgid "Fullscreen"
msgstr "全画面表示"
#: src/ui/gui/settings_page.slint:72
#: src/ui/gui/settings_page.slint:73
msgctxt "Settings"
msgid "Widescreen (stretch)"
msgstr "ワイド画面(伸ばす)"
#: src/ui/gui/settings_page.slint:80
#: src/ui/gui/settings_page.slint:81
msgctxt "Settings"
msgid "VSync"
msgstr "垂直同期(VSync"
#: src/ui/gui/settings_page.slint:88
#: src/ui/gui/settings_page.slint:89
msgctxt "Settings"
msgid "Apply CRT shader"
msgstr "CRTシェーダーを適用"
#: src/ui/gui/settings_page.slint:100
#: src/ui/gui/settings_page.slint:101
msgctxt "Settings"
msgid "Overclock N64 CPU (may cause bugs)"
msgstr "N64のCPUをオーバークロック(不具合の原因になることがあります)"
#: src/ui/gui/settings_page.slint:108
#: src/ui/gui/settings_page.slint:109
msgctxt "Settings"
msgid "Disable Expansion Pak"
msgstr "拡張パックを無効にする"
#: src/ui/gui/settings_page.slint:116
#: src/ui/gui/settings_page.slint:117
msgctxt "Settings"
msgid "Enable Rewind"
msgstr "巻き戻しを有効にする"
#: src/ui/gui/settings_page.slint:125
msgctxt "Settings"
msgid "Emulate UNFLoader"
msgstr "UNFLoaderをエミュレート"
#: src/ui/gui/settings_page.slint:124
#: src/ui/gui/settings_page.slint:133
msgctxt "Settings"
msgid "Emulate VRU"
msgstr "VRUをエミュレート"
+26 -21
View File
@@ -2,7 +2,7 @@
msgid ""
msgstr ""
"Project-Id-Version: gopher64\n"
"POT-Creation-Date: 2026-05-25 08:28+0000\n"
"POT-Creation-Date: 2026-05-30 16:03+0000\n"
"PO-Revision-Date: 2026-05-11 12:00+0000\n"
"Last-Translator: \n"
"Language-Team: Dutch (Netherlands)\n"
@@ -47,37 +47,37 @@ msgctxt "About"
msgid "Donate (via GitHub)"
msgstr "Doneren (via GitHub)"
#: src/ui/gui/appwindow.slint:151
#: src/ui/gui/appwindow.slint:152
msgctxt "Menu"
msgid "Local Game"
msgstr "Lokaal spel"
#: src/ui/gui/appwindow.slint:155
#: src/ui/gui/appwindow.slint:156
msgctxt "Menu"
msgid "Controller Config"
msgstr "Controllerconfiguratie"
#: src/ui/gui/appwindow.slint:159
#: src/ui/gui/appwindow.slint:160
msgctxt "Menu"
msgid "Netplay"
msgstr "Netplay"
#: src/ui/gui/appwindow.slint:163
#: src/ui/gui/appwindow.slint:164
msgctxt "Menu"
msgid "Cheats"
msgstr "Cheats"
#: src/ui/gui/appwindow.slint:167
#: src/ui/gui/appwindow.slint:168
msgctxt "Menu"
msgid "RetroAchievements"
msgstr "RetroAchievements"
#: src/ui/gui/appwindow.slint:171
#: src/ui/gui/appwindow.slint:172
msgctxt "Menu"
msgid "Settings"
msgstr "Instellingen"
#: src/ui/gui/appwindow.slint:175
#: src/ui/gui/appwindow.slint:176
msgctxt "Menu"
msgid "About"
msgstr "Over"
@@ -97,7 +97,7 @@ msgctxt "Cheats"
msgid "Clear Cheats For All ROMs"
msgstr "Cheats wissen voor alle ROM's"
#: src/ui/gui/cheat_page.slint:88
#: src/ui/gui/cheat_page.slint:83
msgctxt "Cheats"
msgid "No Cheats Available"
msgstr "Geen cheats beschikbaar"
@@ -485,62 +485,67 @@ msgctxt "RetroAchievements"
msgid "View Supported Games"
msgstr "Ondersteunde spellen bekijken"
#: src/ui/gui/settings_page.slint:23
#: src/ui/gui/settings_page.slint:24
msgctxt "Settings"
msgid "Settings"
msgstr "Instellingen"
#: src/ui/gui/settings_page.slint:34
#: src/ui/gui/settings_page.slint:35
msgctxt "Settings"
msgid "Resolution:"
msgstr "Resolutie:"
#: src/ui/gui/settings_page.slint:48
#: src/ui/gui/settings_page.slint:49
msgctxt "Settings"
msgid "SSAA downscaling"
msgstr "SSAA-downscaling"
#: src/ui/gui/settings_page.slint:56
#: src/ui/gui/settings_page.slint:57
msgctxt "Settings"
msgid "Integer Scaling"
msgstr "Schalen in hele getallen"
#: src/ui/gui/settings_page.slint:64
#: src/ui/gui/settings_page.slint:65
msgctxt "Settings"
msgid "Fullscreen"
msgstr "Volledig scherm"
#: src/ui/gui/settings_page.slint:72
#: src/ui/gui/settings_page.slint:73
msgctxt "Settings"
msgid "Widescreen (stretch)"
msgstr "Breedbeeld (uitgerekt)"
#: src/ui/gui/settings_page.slint:80
#: src/ui/gui/settings_page.slint:81
msgctxt "Settings"
msgid "VSync"
msgstr "VSync"
#: src/ui/gui/settings_page.slint:88
#: src/ui/gui/settings_page.slint:89
msgctxt "Settings"
msgid "Apply CRT shader"
msgstr "CRT-shader toepassen"
#: src/ui/gui/settings_page.slint:100
#: src/ui/gui/settings_page.slint:101
msgctxt "Settings"
msgid "Overclock N64 CPU (may cause bugs)"
msgstr "N64-CPU overklokken (kan bugs veroorzaken)"
#: src/ui/gui/settings_page.slint:108
#: src/ui/gui/settings_page.slint:109
msgctxt "Settings"
msgid "Disable Expansion Pak"
msgstr "Expansion Pak uitschakelen"
#: src/ui/gui/settings_page.slint:116
#: src/ui/gui/settings_page.slint:117
msgctxt "Settings"
msgid "Enable Rewind"
msgstr "Terugspoelen inschakelen"
#: src/ui/gui/settings_page.slint:125
msgctxt "Settings"
msgid "Emulate UNFLoader"
msgstr "UNFLoader emuleren"
#: src/ui/gui/settings_page.slint:124
#: src/ui/gui/settings_page.slint:133
msgctxt "Settings"
msgid "Emulate VRU"
msgstr "VRU emuleren"
+26 -21
View File
@@ -2,7 +2,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2026-05-25 08:28+0000\n"
"POT-Creation-Date: 2026-05-30 16:03+0000\n"
"PO-Revision-Date: 2026-05-11 18:11-3000\n"
"Last-Translator: EDUARDO CARVALHO <eduardotcarvalho@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -47,37 +47,37 @@ msgctxt "About"
msgid "Donate (via GitHub)"
msgstr "Doações (via GitHub)"
#: src/ui/gui/appwindow.slint:151
#: src/ui/gui/appwindow.slint:152
msgctxt "Menu"
msgid "Local Game"
msgstr "Jogo Local"
#: src/ui/gui/appwindow.slint:155
#: src/ui/gui/appwindow.slint:156
msgctxt "Menu"
msgid "Controller Config"
msgstr "Configurar Controle"
#: src/ui/gui/appwindow.slint:159
#: src/ui/gui/appwindow.slint:160
msgctxt "Menu"
msgid "Netplay"
msgstr "Netplay"
#: src/ui/gui/appwindow.slint:163
#: src/ui/gui/appwindow.slint:164
msgctxt "Menu"
msgid "Cheats"
msgstr "Trapaças"
#: src/ui/gui/appwindow.slint:167
#: src/ui/gui/appwindow.slint:168
msgctxt "Menu"
msgid "RetroAchievements"
msgstr "RetroAchievements"
#: src/ui/gui/appwindow.slint:171
#: src/ui/gui/appwindow.slint:172
msgctxt "Menu"
msgid "Settings"
msgstr "Configurações"
#: src/ui/gui/appwindow.slint:175
#: src/ui/gui/appwindow.slint:176
msgctxt "Menu"
msgid "About"
msgstr "Sobre"
@@ -97,7 +97,7 @@ msgctxt "Cheats"
msgid "Clear Cheats For All ROMs"
msgstr "Limpar Trapaças para todas as ROMs"
#: src/ui/gui/cheat_page.slint:88
#: src/ui/gui/cheat_page.slint:83
msgctxt "Cheats"
msgid "No Cheats Available"
msgstr "Sem trapaças disponíveis"
@@ -486,62 +486,67 @@ msgctxt "RetroAchievements"
msgid "View Supported Games"
msgstr "Ver Jogos com Suporte"
#: src/ui/gui/settings_page.slint:23
#: src/ui/gui/settings_page.slint:24
msgctxt "Settings"
msgid "Settings"
msgstr "Configurações"
#: src/ui/gui/settings_page.slint:34
#: src/ui/gui/settings_page.slint:35
msgctxt "Settings"
msgid "Resolution:"
msgstr "Resolução:"
#: src/ui/gui/settings_page.slint:48
#: src/ui/gui/settings_page.slint:49
msgctxt "Settings"
msgid "SSAA downscaling"
msgstr "Redução de SSAA"
#: src/ui/gui/settings_page.slint:56
#: src/ui/gui/settings_page.slint:57
msgctxt "Settings"
msgid "Integer Scaling"
msgstr "Proporção Íntegra"
#: src/ui/gui/settings_page.slint:64
#: src/ui/gui/settings_page.slint:65
msgctxt "Settings"
msgid "Fullscreen"
msgstr "Tela Cheia"
#: src/ui/gui/settings_page.slint:72
#: src/ui/gui/settings_page.slint:73
msgctxt "Settings"
msgid "Widescreen (stretch)"
msgstr "Widescreen (esticar)"
#: src/ui/gui/settings_page.slint:80
#: src/ui/gui/settings_page.slint:81
msgctxt "Settings"
msgid "VSync"
msgstr "VSync"
#: src/ui/gui/settings_page.slint:88
#: src/ui/gui/settings_page.slint:89
msgctxt "Settings"
msgid "Apply CRT shader"
msgstr "Aplicar filtro de CRT"
#: src/ui/gui/settings_page.slint:100
#: src/ui/gui/settings_page.slint:101
msgctxt "Settings"
msgid "Overclock N64 CPU (may cause bugs)"
msgstr "Overclock da CPU do N64 (pode causar bugs)"
#: src/ui/gui/settings_page.slint:108
#: src/ui/gui/settings_page.slint:109
msgctxt "Settings"
msgid "Disable Expansion Pak"
msgstr "Desabilitar Expansion Pak"
#: src/ui/gui/settings_page.slint:116
#: src/ui/gui/settings_page.slint:117
msgctxt "Settings"
msgid "Enable Rewind"
msgstr "Habilitar rebobinamento"
#: src/ui/gui/settings_page.slint:125
msgctxt "Settings"
msgid "Emulate UNFLoader"
msgstr "Emular UNFLoader"
#: src/ui/gui/settings_page.slint:124
#: src/ui/gui/settings_page.slint:133
msgctxt "Settings"
msgid "Emulate VRU"
msgstr "Emular VRU"
+26 -21
View File
@@ -2,7 +2,7 @@
msgid ""
msgstr ""
"Project-Id-Version: gopher64\n"
"POT-Creation-Date: 2026-05-25 08:28+0000\n"
"POT-Creation-Date: 2026-05-30 16:03+0000\n"
"PO-Revision-Date: 2026-05-11 12:00+0000\n"
"Last-Translator: \n"
"Language-Team: Russian\n"
@@ -47,37 +47,37 @@ msgctxt "About"
msgid "Donate (via GitHub)"
msgstr "Пожертвовать (через GitHub)"
#: src/ui/gui/appwindow.slint:151
#: src/ui/gui/appwindow.slint:152
msgctxt "Menu"
msgid "Local Game"
msgstr "Локальная игра"
#: src/ui/gui/appwindow.slint:155
#: src/ui/gui/appwindow.slint:156
msgctxt "Menu"
msgid "Controller Config"
msgstr "Настройка контроллера"
#: src/ui/gui/appwindow.slint:159
#: src/ui/gui/appwindow.slint:160
msgctxt "Menu"
msgid "Netplay"
msgstr "Сетевая игра"
#: src/ui/gui/appwindow.slint:163
#: src/ui/gui/appwindow.slint:164
msgctxt "Menu"
msgid "Cheats"
msgstr "Читы"
#: src/ui/gui/appwindow.slint:167
#: src/ui/gui/appwindow.slint:168
msgctxt "Menu"
msgid "RetroAchievements"
msgstr "RetroAchievements"
#: src/ui/gui/appwindow.slint:171
#: src/ui/gui/appwindow.slint:172
msgctxt "Menu"
msgid "Settings"
msgstr "Настройки"
#: src/ui/gui/appwindow.slint:175
#: src/ui/gui/appwindow.slint:176
msgctxt "Menu"
msgid "About"
msgstr "О программе"
@@ -97,7 +97,7 @@ msgctxt "Cheats"
msgid "Clear Cheats For All ROMs"
msgstr "Очистить читы для всех ROMов"
#: src/ui/gui/cheat_page.slint:88
#: src/ui/gui/cheat_page.slint:83
msgctxt "Cheats"
msgid "No Cheats Available"
msgstr "Читы недоступны"
@@ -484,62 +484,67 @@ msgctxt "RetroAchievements"
msgid "View Supported Games"
msgstr "Просмотреть поддерживаемые игры"
#: src/ui/gui/settings_page.slint:23
#: src/ui/gui/settings_page.slint:24
msgctxt "Settings"
msgid "Settings"
msgstr "Настройки"
#: src/ui/gui/settings_page.slint:34
#: src/ui/gui/settings_page.slint:35
msgctxt "Settings"
msgid "Resolution:"
msgstr "Разрешение:"
#: src/ui/gui/settings_page.slint:48
#: src/ui/gui/settings_page.slint:49
msgctxt "Settings"
msgid "SSAA downscaling"
msgstr "SSAA даунскейлинг"
#: src/ui/gui/settings_page.slint:56
#: src/ui/gui/settings_page.slint:57
msgctxt "Settings"
msgid "Integer Scaling"
msgstr "Целочисленное масштабирование"
#: src/ui/gui/settings_page.slint:64
#: src/ui/gui/settings_page.slint:65
msgctxt "Settings"
msgid "Fullscreen"
msgstr "Полноэкранный режим"
#: src/ui/gui/settings_page.slint:72
#: src/ui/gui/settings_page.slint:73
msgctxt "Settings"
msgid "Widescreen (stretch)"
msgstr "Широкоэкранный режим (растянуто)"
#: src/ui/gui/settings_page.slint:80
#: src/ui/gui/settings_page.slint:81
msgctxt "Settings"
msgid "VSync"
msgstr "Вертикальная синхронизация"
#: src/ui/gui/settings_page.slint:88
#: src/ui/gui/settings_page.slint:89
msgctxt "Settings"
msgid "Apply CRT shader"
msgstr "Применить шейдер ЭЛТ"
#: src/ui/gui/settings_page.slint:100
#: src/ui/gui/settings_page.slint:101
msgctxt "Settings"
msgid "Overclock N64 CPU (may cause bugs)"
msgstr "Разгон процессора N64 (может вызвать ошибки)"
#: src/ui/gui/settings_page.slint:108
#: src/ui/gui/settings_page.slint:109
msgctxt "Settings"
msgid "Disable Expansion Pak"
msgstr "Отключить Expansion Pak"
#: src/ui/gui/settings_page.slint:116
#: src/ui/gui/settings_page.slint:117
msgctxt "Settings"
msgid "Enable Rewind"
msgstr "Включить перемотку назад"
#: src/ui/gui/settings_page.slint:125
msgctxt "Settings"
msgid "Emulate UNFLoader"
msgstr "Эмулировать UNFLoader"
#: src/ui/gui/settings_page.slint:124
#: src/ui/gui/settings_page.slint:133
msgctxt "Settings"
msgid "Emulate VRU"
msgstr "Эмулировать VRU"
+12
View File
@@ -59,6 +59,7 @@ enum user_event_codes {
USER_EVENT_LOAD_STATE = 2,
USER_EVENT_EXIT_GAME = 3,
USER_EVENT_FAST_FORWARD = 4,
USER_EVENT_LOAD_REWIND = 5,
};
typedef struct {
@@ -189,6 +190,12 @@ bool sdl_event_filter(void *userdata, SDL_Event *event) {
user_event.user.code = USER_EVENT_SAVE_STATE;
SDL_PushEvent(&user_event);
break;
case SDL_SCANCODE_F6:
SDL_zero(user_event);
user_event.type = SDL_EVENT_USER;
user_event.user.code = USER_EVENT_LOAD_REWIND;
SDL_PushEvent(&user_event);
break;
case SDL_SCANCODE_F7:
SDL_zero(user_event);
user_event.type = SDL_EVENT_USER;
@@ -244,6 +251,9 @@ bool sdl_event_filter(void *userdata, SDL_Event *event) {
case USER_EVENT_SAVE_STATE:
callback.save_state = true;
break;
case USER_EVENT_LOAD_REWIND:
callback.load_rewind = true;
break;
case USER_EVENT_LOAD_STATE:
callback.load_state = true;
break;
@@ -330,6 +340,7 @@ static ImageHandle create_message_image(Vulkan::Device &device, int width,
void rdp_init(void *_window, GFX_INFO _gfx_info, const void *font,
size_t font_size, uint32_t save_state_slot) {
memset(&rdp_device, 0, sizeof(RDP_DEVICE));
memset(&callback, 0, sizeof(CALL_BACK));
window = (SDL_Window *)_window;
SDL_SyncWindow(window);
@@ -659,6 +670,7 @@ void rdp_update_screen() {
CALL_BACK rdp_check_callback() {
CALL_BACK return_value = callback;
callback.save_state = false;
callback.load_rewind = false;
callback.load_state = false;
callback.reset_game = false;
callback.lower_volume = false;
+1
View File
@@ -29,6 +29,7 @@ typedef struct {
bool emu_running;
bool save_state;
bool load_state;
bool load_rewind;
bool reset_game;
bool enable_speedlimiter;
bool lower_volume;
+14 -8
View File
@@ -15,7 +15,7 @@ const N64_EXTENSIONS_UNCOMPRESSED: [&str; 8] =
use rand::{Rng, SeedableRng};
use crate::{cheats, netplay, retroachievements, ui};
use crate::{cheats, netplay, retroachievements, savestates, ui};
use std::{collections::HashMap, io::Read};
pub mod ai;
@@ -59,7 +59,7 @@ pub async fn run_game(
}
if let Some(slot) = game_settings.load_savestate_slot {
device.ui.storage.save_state_slot = slot;
device.load_state = true;
device.savestate.load_state = true;
}
init_rng(device);
@@ -229,8 +229,7 @@ pub struct Device {
#[serde(skip)]
pub ui: ui::Ui,
pub byte_swap: usize,
pub save_state: bool,
pub load_state: bool,
pub savestate: savestates::Savestate,
pub cpu: cpu::Cpu,
pub pif: pif::Pif,
pub cart: cart::Cart,
@@ -261,8 +260,7 @@ impl Device {
netplay: None,
ui: ui::Ui::default(),
byte_swap: self.byte_swap,
save_state: self.save_state,
load_state: self.load_state,
savestate: self.savestate.clone(),
cpu: self.cpu.clone(),
pif: self.pif.clone(),
cart: self.cart.clone(),
@@ -294,8 +292,16 @@ impl Device {
netplay: None,
ui: ui::Ui::new(),
byte_swap,
save_state: false,
load_state: false,
savestate: savestates::Savestate {
save_state: false,
load_state: false,
save_rewind: false,
load_rewind: false,
last_rewind_saved: 0.0,
rewind_pool: std::sync::Arc::new(std::sync::Mutex::new(
std::collections::VecDeque::new(),
)),
},
cpu: cpu::Cpu {
cop0: cop0::Cop0 {
regs: [0; cop0::COP0_REGS_COUNT],
+12 -6
View File
@@ -120,14 +120,20 @@ fn run_rdp(device: &mut device::Device) {
device.rdp.regs_dpc[DPC_PIPEBUSY_REG] = 0xFFFFFF;
if timer != 0 {
if device.save_state {
if device.savestate.save_state || device.savestate.save_rewind {
// Right after full sync, good time for save state
device.save_state = false;
savestates::create_savestate(device);
} else if device.load_state {
let rewind = device.savestate.save_rewind && !device.savestate.save_state;
if rewind {
device.savestate.save_rewind = false;
}
device.savestate.save_state = false;
savestates::create_savestate(device, rewind);
} else if device.savestate.load_state || device.savestate.load_rewind {
// Right after full sync, good time for save state
device.load_state = false;
savestates::load_savestate(device);
device.savestate.load_state = false;
let rewind = device.savestate.load_rewind;
device.savestate.load_rewind = false;
savestates::load_savestate(device, rewind);
}
device::events::create_event(device, device::events::EVENT_TYPE_DP, timer)
}
+8 -2
View File
@@ -122,6 +122,8 @@ pub fn write_regs(device: &mut device::Device, address: u64, value: u32, mask: u
}
pub fn vertical_interrupt_event(device: &mut device::Device) {
device.vi.elapsed_time += device.vi.frame_time;
if device.cheats.enabled {
cheats::execute_cheats(device, device.cheats.cheats.clone());
}
@@ -139,6 +141,11 @@ pub fn vertical_interrupt_event(device: &mut device::Device) {
speed_limiter_toggled = true;
device.vi.enable_speed_limiter = !netplay.fast_forward;
}
} else if device.ui.config.emulation.rewind
&& device.vi.elapsed_time - device.savestate.last_rewind_saved > 1.0
{
device.savestate.save_rewind = true;
device.savestate.last_rewind_saved = device.vi.elapsed_time;
}
if speed_limiter_toggled {
@@ -153,7 +160,6 @@ pub fn vertical_interrupt_event(device: &mut device::Device) {
ui::video::update_screen();
device.vi.vi_counter += 1;
device.vi.elapsed_time += device.vi.frame_time;
if device.netplay.is_none() && paused {
if retroachievements::get_hardcore() {
@@ -162,7 +168,7 @@ pub fn vertical_interrupt_event(device: &mut device::Device) {
ui::video::MESSAGE_LENGTH_MESSAGE_SHORT,
);
} else {
ui::video::pause_loop(device.vi.frame_time);
ui::video::pause_loop(&mut device.ui, device.vi.frame_time);
}
}
+2
View File
@@ -104,6 +104,8 @@ pub async fn run(args: Args, arg_count: usize) -> std::io::Result<()> {
ui::sdl_hints();
if let Some(game) = args.game {
ui::disable_auto_update_joysticks();
let file_path = std::path::Path::new(&game).to_path_buf();
let Some(rom_contents) = device::get_rom_contents(&file_path) else {
return Err(Error::other(format!(
+172 -126
View File
@@ -69,7 +69,25 @@ where
seq.end()
}
pub fn create_savestate(device: &device::Device) {
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Savestate {
pub save_state: bool,
pub load_state: bool,
pub save_rewind: bool,
pub load_rewind: bool,
pub last_rewind_saved: f64,
#[serde(skip)]
pub rewind_pool: std::sync::Arc<std::sync::Mutex<std::collections::VecDeque<SavestateData>>>,
}
pub struct SavestateData {
device_data: Vec<u8>,
saves_data: Vec<u8>,
rdp_state: Vec<u8>,
ra_state: Vec<u8>,
}
pub fn create_savestate(device: &mut device::Device, rewind: bool) {
let mut rdp_state: Vec<u8> = vec![0; ui::video::state_size()];
ui::video::save_state(rdp_state.as_mut_ptr());
@@ -80,24 +98,39 @@ pub fn create_savestate(device: &device::Device) {
let device_clone = device.clone_without_ui();
let save_state_slot = device.ui.storage.save_state_slot;
let rewind_pool = device.savestate.rewind_pool.clone();
tokio::spawn(async move {
let mut error = false;
if let Ok(device_data) = postcard::to_stdvec(&device_clone)
&& let Ok(saves_data) = postcard::to_stdvec(&device_clone.ui.storage.saves)
{
if let Ok(compressed_file) = ui::storage::compress_file(&[
(&device_data, "device"),
(&saves_data, "saves"),
(&rdp_state, "rdp_state"),
(&ra_state, "ra_state"),
]) {
if let Err(e) = tokio::fs::write(save_path, compressed_file).await {
eprintln!("Error writing savestate: {}", e);
error = true;
if rewind {
if let Ok(mut pool) = rewind_pool.lock() {
pool.push_back(SavestateData {
device_data,
saves_data,
rdp_state,
ra_state,
});
if pool.len() > 30 {
pool.pop_front();
}
}
} else {
eprintln!("Error compressing savestate");
error = true;
if let Ok(compressed_file) = ui::storage::compress_file(&[
(&device_data, "device"),
(&saves_data, "saves"),
(&rdp_state, "rdp_state"),
(&ra_state, "ra_state"),
]) {
if let Err(e) = tokio::fs::write(save_path, compressed_file).await {
eprintln!("Error writing savestate: {}", e);
error = true;
}
} else {
eprintln!("Error compressing savestate");
error = true;
}
}
} else {
error = true;
@@ -107,7 +140,7 @@ pub fn create_savestate(device: &device::Device) {
&format!("Failed to create savestate in slot {}", save_state_slot),
ui::video::MESSAGE_LENGTH_MESSAGE_SHORT,
);
} else {
} else if !rewind {
ui::video::onscreen_message(
&format!("Savestate created in slot {}", save_state_slot),
ui::video::MESSAGE_LENGTH_MESSAGE_VERY_SHORT,
@@ -116,7 +149,7 @@ pub fn create_savestate(device: &device::Device) {
});
}
pub fn load_savestate(device: &mut device::Device) {
pub fn load_savestate(device: &mut device::Device, rewind: bool) {
if retroachievements::get_hardcore() {
ui::video::onscreen_message(
"Cannot load savestate in RA hardcore mode",
@@ -124,119 +157,138 @@ pub fn load_savestate(device: &mut device::Device) {
);
return;
}
let savestate = std::fs::read(&device.ui.storage.paths.savestate_file_path);
if let Ok(savestate) = &savestate {
if let Ok(device_bytes) = ui::storage::decompress_file(savestate, "device")
&& let Ok(save_bytes) = ui::storage::decompress_file(savestate, "saves")
&& let Ok(rdp_state) = ui::storage::decompress_file(savestate, "rdp_state")
&& let Ok(ra_state) = ui::storage::decompress_file(savestate, "ra_state")
&& let Ok(mut state) = postcard::from_bytes::<device::Device>(&device_bytes)
&& let Ok(saves) = postcard::from_bytes(&save_bytes)
&& device.rdram.size == state.rdram.size
{
device.ui.storage.saves = saves;
std::mem::swap(&mut device.cpu, &mut state.cpu);
std::mem::swap(&mut device.pif, &mut state.pif);
let state_data = if rewind {
if let Ok(mut pool) = device.savestate.rewind_pool.lock() {
pool.pop_back()
} else {
None
}
} else if let savestate = std::fs::read(&device.ui.storage.paths.savestate_file_path)
&& let Ok(savestate) = &savestate
&& let Ok(device_data) = ui::storage::decompress_file(savestate, "device")
&& let Ok(saves_data) = ui::storage::decompress_file(savestate, "saves")
&& let Ok(rdp_state) = ui::storage::decompress_file(savestate, "rdp_state")
&& let Ok(ra_state) = ui::storage::decompress_file(savestate, "ra_state")
{
Some(SavestateData {
device_data,
saves_data,
rdp_state,
ra_state,
})
} else {
None
};
if let Some(state_data) = state_data
&& let Ok(mut state) = postcard::from_bytes::<device::Device>(&state_data.device_data)
&& let Ok(saves) = postcard::from_bytes(&state_data.saves_data)
&& device.rdram.size == state.rdram.size
{
device.savestate.last_rewind_saved = state.vi.elapsed_time;
let rom = device.cart.rom.clone();
std::mem::swap(&mut device.cart, &mut state.cart);
device.cart.rom = rom;
device.ui.storage.saves = saves;
std::mem::swap(&mut device.memory, &mut state.memory);
std::mem::swap(&mut device.rsp, &mut state.rsp);
std::mem::swap(&mut device.rdp, &mut state.rdp);
std::mem::swap(&mut device.cpu, &mut state.cpu);
std::mem::swap(&mut device.pif, &mut state.pif);
device.rdram.mem.clone_from(&state.rdram.mem);
device.rdram.regs = state.rdram.regs;
let rom = device.cart.rom.clone();
std::mem::swap(&mut device.cart, &mut state.cart);
device.cart.rom = rom;
std::mem::swap(&mut device.mi, &mut state.mi);
std::mem::swap(&mut device.pi, &mut state.pi);
std::mem::swap(&mut device.vi, &mut state.vi);
std::mem::swap(&mut device.ai, &mut state.ai);
std::mem::swap(&mut device.si, &mut state.si);
std::mem::swap(&mut device.ri, &mut state.ri);
std::mem::swap(&mut device.vru, &mut state.vru);
std::mem::swap(&mut device.cheats, &mut state.cheats);
std::mem::swap(&mut device.memory, &mut state.memory);
std::mem::swap(&mut device.rsp, &mut state.rsp);
std::mem::swap(&mut device.rdp, &mut state.rdp);
let mut tpak_rom = [vec![], vec![], vec![], vec![]];
for (i, item) in tpak_rom.iter_mut().enumerate() {
*item = device.transferpaks[i].cart.rom.clone();
}
std::mem::swap(&mut device.transferpaks, &mut state.transferpaks);
for (i, item) in tpak_rom.iter().enumerate() {
device.transferpaks[i].cart.rom = item.clone();
device.rdram.mem.clone_from(&state.rdram.mem);
device.rdram.regs = state.rdram.regs;
std::mem::swap(&mut device.mi, &mut state.mi);
std::mem::swap(&mut device.pi, &mut state.pi);
std::mem::swap(&mut device.vi, &mut state.vi);
std::mem::swap(&mut device.ai, &mut state.ai);
std::mem::swap(&mut device.si, &mut state.si);
std::mem::swap(&mut device.ri, &mut state.ri);
std::mem::swap(&mut device.vru, &mut state.vru);
std::mem::swap(&mut device.cheats, &mut state.cheats);
let mut tpak_rom = [vec![], vec![], vec![], vec![]];
for (i, item) in tpak_rom.iter_mut().enumerate() {
*item = device.transferpaks[i].cart.rom.clone();
}
std::mem::swap(&mut device.transferpaks, &mut state.transferpaks);
for (i, item) in tpak_rom.iter().enumerate() {
device.transferpaks[i].cart.rom = item.clone();
}
device::memory::init(device);
device::vi::set_expected_refresh_rate(device);
device::cpu::map_instructions(device);
device::cop0::map_instructions(device);
device::cop1::map_instructions(device);
device::cop2::map_instructions(device);
device::rsp_cpu::map_instructions(device);
let mut mem_addr = 0x1000;
while mem_addr < 0x2000 {
let data =
u32::from_be_bytes(device.rsp.mem[mem_addr..mem_addr + 4].try_into().unwrap());
device.rsp.cpu.instructions[(mem_addr & 0xFFF) / 4].func =
device::rsp_cpu::decode_opcode(device, data);
device.rsp.cpu.instructions[(mem_addr & 0xFFF) / 4].opcode = data;
mem_addr += 4;
}
for line_index in 0..512 {
for i in 0..8 {
device.memory.icache[line_index].instruction[i] =
device::cpu::decode_opcode(device, device.memory.icache[line_index].words[i]);
}
}
device::memory::init(device);
device::vi::set_expected_refresh_rate(device);
device::cpu::map_instructions(device);
device::cop0::map_instructions(device);
device::cop1::map_instructions(device);
device::cop2::map_instructions(device);
device::rsp_cpu::map_instructions(device);
let mut mem_addr = 0x1000;
while mem_addr < 0x2000 {
let data =
u32::from_be_bytes(device.rsp.mem[mem_addr..mem_addr + 4].try_into().unwrap());
device.rsp.cpu.instructions[(mem_addr & 0xFFF) / 4].func =
device::rsp_cpu::decode_opcode(device, data);
device.rsp.cpu.instructions[(mem_addr & 0xFFF) / 4].opcode = data;
mem_addr += 4;
}
for line_index in 0..512 {
for i in 0..8 {
device.memory.icache[line_index].instruction[i] = device::cpu::decode_opcode(
device,
device.memory.icache[line_index].words[i],
);
device::pif::connect_pif_channels(device);
for i in 0..4 {
if let Some(handler) = device.pif.channels[i].pak_handler {
if handler.pak_type == device::controller::PakType::RumblePak {
let rumblepak_handler = device::controller::PakHandler {
read: device::controller::rumble::read,
write: device::controller::rumble::write,
pak_type: device::controller::PakType::RumblePak,
};
device.pif.channels[i].pak_handler = Some(rumblepak_handler);
} else if handler.pak_type == device::controller::PakType::MemPak {
let mempak_handler = device::controller::PakHandler {
read: device::controller::mempak::read,
write: device::controller::mempak::write,
pak_type: device::controller::PakType::MemPak,
};
device.pif.channels[i].pak_handler = Some(mempak_handler);
} else if handler.pak_type == device::controller::PakType::TransferPak {
let tpak_handler = device::controller::PakHandler {
read: device::controller::transferpak::read,
write: device::controller::transferpak::write,
pak_type: device::controller::PakType::TransferPak,
};
device.pif.channels[i].pak_handler = Some(tpak_handler);
}
}
}
device::pif::connect_pif_channels(device);
for i in 0..4 {
if let Some(handler) = device.pif.channels[i].pak_handler {
if handler.pak_type == device::controller::PakType::RumblePak {
let rumblepak_handler = device::controller::PakHandler {
read: device::controller::rumble::read,
write: device::controller::rumble::write,
pak_type: device::controller::PakType::RumblePak,
};
device.pif.channels[i].pak_handler = Some(rumblepak_handler);
} else if handler.pak_type == device::controller::PakType::MemPak {
let mempak_handler = device::controller::PakHandler {
read: device::controller::mempak::read,
write: device::controller::mempak::write,
pak_type: device::controller::PakType::MemPak,
};
device.pif.channels[i].pak_handler = Some(mempak_handler);
} else if handler.pak_type == device::controller::PakType::TransferPak {
let tpak_handler = device::controller::PakHandler {
read: device::controller::transferpak::read,
write: device::controller::transferpak::write,
pak_type: device::controller::PakType::TransferPak,
};
device.pif.channels[i].pak_handler = Some(tpak_handler);
}
}
}
ui::audio::update_freq(device);
ui::video::load_state(device, state_data.rdp_state.as_ptr());
ui::audio::update_freq(device);
ui::video::load_state(device, rdp_state.as_ptr());
retroachievements::set_rdram(device.rdram.mem.as_ptr(), device.rdram.size as usize);
if !state_data.ra_state.is_empty() {
retroachievements::load_state(state_data.ra_state.as_ptr(), state_data.ra_state.len());
} else {
retroachievements::load_state(std::ptr::null(), 0);
}
retroachievements::set_rdram(device.rdram.mem.as_ptr(), device.rdram.size as usize);
if !ra_state.is_empty() {
retroachievements::load_state(ra_state.as_ptr(), ra_state.len());
} else {
retroachievements::load_state(std::ptr::null(), 0);
}
if device.cheats.enabled {
cheats::execute_cheats(device, device.cheats.cheats.clone());
}
if device.cheats.enabled {
cheats::execute_cheats(device, device.cheats.cheats.clone());
}
if !rewind {
ui::video::onscreen_message(
&format!(
"Savestate loaded from slot {}",
@@ -244,23 +296,17 @@ pub fn load_savestate(device: &mut device::Device) {
),
ui::video::MESSAGE_LENGTH_MESSAGE_VERY_SHORT,
);
} else {
ui::video::onscreen_message(
&format!(
"Failed to load savestate from slot {}",
device.ui.storage.save_state_slot
),
ui::video::MESSAGE_LENGTH_MESSAGE_SHORT,
);
}
} else {
ui::video::onscreen_message(
let message = if !rewind {
&format!(
"Could not find savestate in slot {}",
"Failed to load savestate from slot {}",
device.ui.storage.save_state_slot
),
ui::video::MESSAGE_LENGTH_MESSAGE_SHORT,
);
)
} else {
"Failed to rewind"
};
ui::video::onscreen_message(message, ui::video::MESSAGE_LENGTH_MESSAGE_SHORT);
}
}
+5
View File
@@ -113,6 +113,11 @@ pub fn sdl_hints() {
sdl3_sys::everything::SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY,
hint.as_ptr(),
);
}
}
pub fn disable_auto_update_joysticks() {
unsafe {
let hint = std::ffi::CString::new("0").unwrap();
sdl3_sys::everything::SDL_SetHint(
sdl3_sys::everything::SDL_HINT_AUTO_UPDATE_JOYSTICKS,
+2
View File
@@ -61,6 +61,7 @@ pub struct Emulation {
pub overclock: bool,
pub disable_expansion_pak: bool,
pub usb: bool,
pub rewind: bool,
}
#[derive(serde::Serialize, serde::Deserialize)]
@@ -174,6 +175,7 @@ impl Config {
overclock: false,
disable_expansion_pak: false,
usb: false,
rewind: false,
},
rom_dir: std::path::PathBuf::new(),
recent_roms: Vec::new(),
+2
View File
@@ -175,6 +175,7 @@ fn settings_window(app: &AppWindow, config: &ui::config::Config) {
app.set_overclock_n64_cpu(config.emulation.overclock);
app.set_disable_expansion_pak(config.emulation.disable_expansion_pak);
app.set_emulate_usb(config.emulation.usb);
app.set_rewind(config.emulation.rewind);
let combobox_value = match config.video.upscale {
1 => 0,
2 => 1,
@@ -446,6 +447,7 @@ pub fn save_settings(app: &AppWindow) {
config.emulation.overclock = app.get_overclock_n64_cpu();
config.emulation.disable_expansion_pak = app.get_disable_expansion_pak();
config.emulation.usb = app.get_emulate_usb();
config.emulation.rewind = app.get_rewind();
let upscale_values = [1, 2, 4, 8];
config.video.upscale = upscale_values[app.get_resolution() as usize];
+1
View File
@@ -74,6 +74,7 @@ export component AppWindow inherits Window {
in-out property disable_expansion_pak <=> SettingsData.disable_expansion_pak;
in-out property resolution <=> SettingsData.resolution;
in-out property emulate_usb <=> SettingsData.emulate_usb;
in-out property rewind <=> SettingsData.rewind;
in-out property emulate_vru <=> SettingsData.emulate_vru;
in-out property rom_dir <=> SettingsData.rom_dir;
in-out property controller_enabled <=> ControllerData.controller_enabled;
+9
View File
@@ -15,6 +15,7 @@ export global SettingsData {
in-out property <bool> disable_expansion_pak;
in-out property <int> resolution;
in-out property <bool> emulate_usb;
in-out property <bool> rewind;
in-out property <bool> emulate_vru;
in-out property <string> rom_dir;
}
@@ -112,6 +113,14 @@ export component Settings inherits Page {
}
}
Switch {
text: @tr("Enable Rewind");
checked: SettingsData.rewind;
toggled => {
SettingsData.rewind = self.checked;
}
}
Switch {
text: @tr("Emulate UNFLoader");
checked: SettingsData.emulate_usb;
+11
View File
@@ -489,6 +489,17 @@ fn handle_hotkeys(keys: u32, last_key_state: u32) {
})
};
}
if keys & (1 << L_CBUTTON) != 0 && last_key_state & (1 << L_CBUTTON) == 0 {
unsafe {
sdl3_sys::events::SDL_PushEvent(&mut sdl3_sys::events::SDL_Event {
user: sdl3_sys::events::SDL_UserEvent {
r#type: u32::from(sdl3_sys::events::SDL_EVENT_USER),
code: 5, //load rewind
..Default::default()
},
})
};
}
}
pub fn get(ui: &mut ui::Ui, channel: usize, vi_counter: u64) -> InputData {
+9 -3
View File
@@ -175,16 +175,19 @@ pub fn load_state(device: &mut device::Device, rdp_state: *const u8) {
}
}
pub fn pause_loop(frame_time: f64) {
pub fn pause_loop(ui: &mut ui::Ui, frame_time: f64) {
let mut paused = true;
let mut frame_advance = false;
let mut pause_counter = 0;
while paused && !frame_advance {
std::thread::sleep(std::time::Duration::from_secs_f64(frame_time));
ui::input::get(ui, 0, pause_counter); // to gather hotkey input
unsafe { sdl3_sys::events::SDL_PumpEvents() };
retroachievements::do_idle();
let callback = unsafe { rdp_check_callback() };
paused = callback.paused;
frame_advance = callback.frame_advance;
pause_counter += 1;
}
}
@@ -194,9 +197,12 @@ pub fn check_callback(device: &mut device::Device) -> (bool, bool) {
device.cpu.running = callback.emu_running;
if device.netplay.is_none() {
if callback.save_state {
device.save_state = true;
device.savestate.save_state = true;
} else if callback.load_state {
device.load_state = true;
device.savestate.load_state = true;
}
if callback.load_rewind && device.ui.config.emulation.rewind {
device.savestate.load_rewind = true;
}
if callback.reset_game {
device.cpu.cop0.regs[device::cop0::COP0_CAUSE_REG] |= device::cop0::COP0_CAUSE_IP4;