From 6fd3bfb86b9380b3f9f18537ab08a70c0508154d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 29 May 2022 20:37:10 -0700 Subject: [PATCH 001/102] Qt: Fix preloading for ROM replacing --- CHANGES | 1 + src/platform/qt/CoreController.cpp | 7 ++++++- src/platform/qt/CoreController.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index ff795586a..558807a83 100644 --- a/CHANGES +++ b/CHANGES @@ -49,6 +49,7 @@ Other fixes: - mGUI: Fix FPS counter after closing menu - Qt: Fix some hangs when using the debugger console - Qt: Fix crash when clicking past last tile in viewer + - Qt: Fix preloading for ROM replacing - VFS: Failed file mapping should return NULL on POSIX Misc: - Core: Suspend runloop when a core crashes diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index 4491a0f33..ec0edea11 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -287,6 +287,7 @@ void CoreController::loadConfig(ConfigController* config) { m_fastForwardMute = config->getOption("fastForwardMute", -1).toInt(); mCoreConfigCopyValue(&m_threadContext.core->config, config->config(), "volume"); mCoreConfigCopyValue(&m_threadContext.core->config, config->config(), "mute"); + m_preload = config->getOption("preload").toInt(); int playerId = m_multiplayer->playerId(this) + 1; QVariant savePlayerId = config->getOption("savePlayerId"); @@ -829,7 +830,11 @@ void CoreController::replaceGame(const QString& path) { QString fname = info.canonicalFilePath(); Interrupter interrupter(this); mDirectorySetDetachBase(&m_threadContext.core->dirs); - mCoreLoadFile(m_threadContext.core, fname.toUtf8().constData()); + if (m_preload) { + mCorePreloadFile(m_threadContext.core, fname.toUtf8().constData()); + } else { + mCoreLoadFile(m_threadContext.core, fname.toUtf8().constData()); + } updateROMInfo(); } diff --git a/src/platform/qt/CoreController.h b/src/platform/qt/CoreController.h index 03c929c48..663d0ed96 100644 --- a/src/platform/qt/CoreController.h +++ b/src/platform/qt/CoreController.h @@ -240,6 +240,7 @@ private: mCoreThread m_threadContext{}; bool m_patched = false; + bool m_preload = false; uint32_t m_crc32; QString m_internalTitle; From 82ac857c2c07c8fab2f6f992e2292e03e6e0d54e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 29 May 2022 20:38:57 -0700 Subject: [PATCH 002/102] Qt: Update translations --- src/platform/qt/ts/mgba-de.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-en.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-es.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-fi.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-fr.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-hu.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-it.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-ja.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-ko.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-ms.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-nb_NO.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-nl.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-pl.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-pt_BR.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-ru.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-template.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-tr.ts | 490 ++++++++++++++++------------ src/platform/qt/ts/mgba-zh_CN.ts | 490 ++++++++++++++++------------ 18 files changed, 5076 insertions(+), 3744 deletions(-) diff --git a/src/platform/qt/ts/mgba-de.ts b/src/platform/qt/ts/mgba-de.ts index f389bef06..65eabed81 100644 --- a/src/platform/qt/ts/mgba-de.ts +++ b/src/platform/qt/ts/mgba-de.ts @@ -1269,17 +1269,22 @@ Download-Größe: %3 QGBA::CheatsView - - + + Autodetect (recommended) Automatisch erkennen (empfohlen) - - + + Select cheats file Cheat-Datei auswählen + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1289,43 +1294,43 @@ Download-Größe: %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 Fehler beim Öffnen der Speicherdatei: %1 - + Failed to open game file: %1 Fehler beim Öffnen der Spieldatei: %1 - + Can't yank pack in unexpected platform! Das GamePak kann nur auf unterstützten Plattformen herausgezogen werden! - + Failed to open snapshot file for reading: %1 Konnte Snapshot-Datei %1 nicht zum Lesen öffnen - + Failed to open snapshot file for writing: %1 Konnte Snapshot-Datei %1 nicht zum Schreiben öffnen @@ -3479,47 +3484,47 @@ Download-Größe: %3 QGBA::LogController - + [%1] %2: %3 [%1] %2: %3 - + An error occurred Ein Fehler ist aufgetreten - + DEBUG DEBUG - + STUB STUB - + INFO INFO - + WARN WARN - + ERROR ERROR - + FATAL FATAL - + GAME ERROR GAME ERROR @@ -3643,42 +3648,42 @@ Download-Größe: %3 Laden - + All Alle - + Load TBL TBL laden - + Save selected memory Ausgewählten Speicher abspeichern - + Failed to open output file: %1 Fehler beim Öffnen der Ausgabedatei: %1 - + Load memory Lade Speicher - + Failed to open input file: %1 Fehler beim Laden der Eingabedatei: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3929,97 +3934,123 @@ Download-Größe: %3 Der Spielstand konnte nicht zwischen verschiedenen Plattformen konvertiert werden + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (erzwinge Version 1.x) - + None Keiner - + None (Still Image) Keiner (Standbild) - + Keyboard Tastatur - + Controllers Gamepads - + Shortcuts Tastenkürzel - - + + Shaders Shader - + Select BIOS BIOS auswählen - + Select directory Verzeichnis auswählen - + (%1×%2) (%1×%2) - + Never Nie - + Just now Gerade eben - + Less than an hour ago Vor weniger als einer Stunde - + %n hour(s) ago Vor %n Stunde(n) @@ -4027,7 +4058,7 @@ Download-Größe: %3 - + %n day(s) ago Vor %n Tag(en) @@ -4126,105 +4157,105 @@ Download-Größe: %3 QGBA::Window - + Game Boy Advance ROMs (%1) Game Boy Advance-ROMs (%1) - + Game Boy ROMs (%1) Game Boy-ROMs (%1) - + All ROMs (%1) Alle ROMs (%1) - + %1 Video Logs (*.mvl) %1 Video-Logs (*.mvl) - + Archives (%1) Archive (%1) - - + + Select ROM ROM auswählen - - + + Select save Speicherdatei wählen - + Select patch Patch wählen - + Patches (*.ips *.ups *.bps) Korrekturen (*.ips *.ups *.bps) - + Select e-Reader card images Bilder der Lesegerät-Karte auswählen - + Image file (*.png *.jpg *.jpeg) Bilddatei (*.png *.jpg *.jpeg) - + Conversion finished Konvertierung abgeschlossen - + %1 of %2 e-Reader cards converted successfully. %1 von %2 Lesegerät-Karten erfolgreich konvertiert. - + Select image Bild auswählen - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Bild-Datei (*.png *.gif *.jpg *.jpeg);;Alle Dateien (*) - + GameShark saves (*.sps *.xps) GameShark-Speicherdaten (*.sps *.xps) - + Select video log Video-Log auswählen - + Video logs (*.mvl) Video-Logs (*.mvl) - + Crash Absturz - + The game has crashed with the following error: %1 @@ -4233,669 +4264,674 @@ Download-Größe: %3 %1 - + Unimplemented BIOS call Nicht implementierter BIOS-Aufruf - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Dieses Spiel verwendet einen BIOS-Aufruf, der nicht implementiert ist. Bitte verwenden Sie für die beste Spielerfahrung das offizielle BIOS. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Es konnte kein geeignetes Ausgabegerät erstellt werden, stattdessen wird Software-Rendering als Rückfalloption genutzt. Spiele laufen möglicherweise langsamer, besonders innerhalb großer Fenster. - + Really make portable? Portablen Modus wirklich aktivieren? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Diese Einstellung wird den Emulator so konfigurieren, dass er seine Konfiguration aus dem gleichen Verzeichnis wie die Programmdatei lädt. Möchten Sie fortfahren? - + Restart needed Neustart benötigt - + Some changes will not take effect until the emulator is restarted. Einige Änderungen werden erst übernommen, wenn der Emulator neu gestartet wurde. - + - Player %1 of %2 - Spieler %1 von %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 Bilder/Sekunde) - %4 - + &File &Datei - + Load &ROM... &ROM laden... - + Load ROM in archive... ROM aus Archiv laden... - + Save games Spielstände - + Automatically determine - + Use player %0 save game - + Load &patch... &Patch laden... - + Boot BIOS BIOS booten - + Replace ROM... ROM ersetzen... - + Convert e-Reader card image to raw... Lesegerät-Kartenbild in Rohdaten umwandeln … - + ROM &info... ROM-&Informationen... - + Recent Zuletzt verwendet - + Make portable Portablen Modus aktivieren - + &Load state Savestate (aktueller Zustand) &laden - + Load state file... Savestate-Datei laden... - + &Save state Savestate (aktueller Zustand) &speichern - + Save state file... Savestate-Datei speichern... - + Quick load Schnell laden - + Quick save Schnell speichern - + Load recent Lade zuletzt gespeicherten Savestate - + Save recent Speichere aktuellen Zustand - + Undo load state Laden des Savestate rückgängig machen - + Undo save state Speichern des Savestate rückgängig machen - - + + State &%1 Savestate &%1 - + Load camera image... Lade Kamerabild... - + Convert save game... Spielstand konvertieren... - + Reset needed - + Some changes will not take effect until the game is reset. - + New multiplayer window Neues Multiplayer-Fenster - + Connect to Dolphin... Mit Dolphin verbinden... - + Report bug... Fehler melden... - + E&xit &Beenden - + &Emulation &Emulation - + &Reset Zu&rücksetzen - + Sh&utdown Schli&eßen - + Yank game pak Spielmodul herausziehen - + &Pause &Pause - + &Next frame &Nächstes Bild - + Fast forward (held) Schneller Vorlauf (gehalten) - + &Fast forward Schneller &Vorlauf - + Fast forward speed Vorlauf-Geschwindigkeit - + Unbounded Unbegrenzt - + %0x %0x - + Rewind (held) Zurückspulen (gehalten) - + Re&wind Zur&ückspulen - + Step backwards Schrittweiser Rücklauf - + Solar sensor Sonnen-Sensor - + Increase solar level Sonnen-Level erhöhen - + Decrease solar level Sonnen-Level verringern - + Brightest solar level Hellster Sonnen-Level - + Darkest solar level Dunkelster Sonnen-Level - + Brightness %1 Helligkeit %1 - + BattleChip Gate... BattleChip Gate... - + Audio/&Video Audio/&Video - + Frame size Bildgröße - + Toggle fullscreen Vollbildmodus umschalten - + Lock aspect ratio Seitenverhältnis korrigieren - + Force integer scaling Pixelgenaue Skalierung (Integer scaling) - + Interframe blending Interframe-Überblendung - + Frame&skip Frame&skip - + Mute Stummschalten - + FPS target Bildwiederholrate - + Take &screenshot &Screenshot erstellen - + F12 F12 - + + Scripting... + + + + Clear Leeren - + Game Boy Printer... Game Boy Printer... - + Video layers Video-Ebenen - + Audio channels Audio-Kanäle - + Adjust layer placement... Lage der Bildebenen anpassen... - + &Tools &Werkzeuge - + View &logs... &Logs ansehen... - + Game &overrides... Spiel-&Überschreibungen... - + &Cheats... &Cheats... - + Open debugger console... Debugger-Konsole öffnen... - + Start &GDB server... &GDB-Server starten... - + Settings... Einstellungen... - + Select folder Ordner auswählen - + Save games (%1) Spielstände (%1) - + Select save game Spielstand auswählen - + mGBA save state files (%1) mGBA-Savestates (%1) - - + + Select save state Savestate auswählen - + Select e-Reader dotcode e-Reader-Code auswählen - + e-Reader card (*.raw *.bin *.bmp) e-Reader-Karte (*.raw *.bin *.bmp) - + GameShark saves (*.gsv *.sps *.xps) - + Couldn't Start Konnte nicht gestartet werden - + Could not start game. Spiel konnte nicht gestartet werden. - + Add folder to library... Ordner zur Bibliothek hinzufügen... - + Load alternate save game... Alternativen Spielstand laden... - + Load temporary save game... Temporären Spielstand laden... - + Scan e-Reader dotcodes... e-Reader-Code einlesen... - + Import GameShark Save... GameShare-Speicherstand importieren... - + Export GameShark Save... GameShark-Speicherstand exportieren... - + About... Über... - + %1× %1x - + Bilinear filtering Bilineare Filterung - + Native (59.7275) Nativ (59.7275) - + Record A/V... Audio/Video aufzeichnen... - + Record GIF/WebP/APNG... GIF/WebP/APNG aufzeichnen... - + Game Pak sensors... Spielmodul-Sensoren... - + View &palette... &Palette betrachten... - + View &sprites... &Sprites betrachten... - + View &tiles... &Tiles betrachten... - + View &map... &Map betrachten... - + &Frame inspector... &Bildbetrachter... - + View memory... Speicher betrachten... - + Search memory... Speicher durchsuchen... - + View &I/O registers... &I/O-Register betrachten... - + Record debug video log... Video-Protokoll aufzeichnen... - + Stop debug video log Aufzeichnen des Video-Protokolls beenden - + Exit fullscreen Vollbildmodus beenden - + GameShark Button (held) GameShark-Taste (gehalten) - + Autofire Autofeuer - + Autofire A Autofeuer A - + Autofire B Autofeuer B - + Autofire L Autofeuer L - + Autofire R Autofeuer R - + Autofire Start Autofeuer Start - + Autofire Select Autofeuer Select - + Autofire Up Autofeuer nach oben - + Autofire Right Autofeuer rechts - + Autofire Down Autofeuer nach unten - + Autofire Left Autofeuer links @@ -5141,6 +5177,44 @@ Download-Größe: %3 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + Zu&rücksetzen + + + + 0 + 0 + + SensorView diff --git a/src/platform/qt/ts/mgba-en.ts b/src/platform/qt/ts/mgba-en.ts index 4398dde76..cff78b3e9 100644 --- a/src/platform/qt/ts/mgba-en.ts +++ b/src/platform/qt/ts/mgba-en.ts @@ -1266,17 +1266,22 @@ Download size: %3 QGBA::CheatsView - - + + Autodetect (recommended) - - + + Select cheats file + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1286,43 +1291,43 @@ Download size: %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 - + Failed to open game file: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -3476,47 +3481,47 @@ Download size: %3 QGBA::LogController - + [%1] %2: %3 - + An error occurred - + DEBUG - + STUB - + INFO - + WARN - + ERROR - + FATAL - + GAME ERROR @@ -3640,42 +3645,42 @@ Download size: %3 - + All - + Load TBL - + Save selected memory - + Failed to open output file: %1 - + Load memory - + Failed to open input file: %1 - + TBL - + ISO-8859-1 @@ -3926,97 +3931,123 @@ Download size: %3 + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia - + SDL - + Software (Qt) - + OpenGL - + OpenGL (force version 1.x) - + None - + None (Still Image) - + Keyboard - + Controllers - + Shortcuts - - + + Shaders - + Select BIOS - + Select directory - + (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago @@ -4024,7 +4055,7 @@ Download size: %3 - + %n day(s) ago @@ -4123,774 +4154,779 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) - - + + Select ROM - + Select folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) - - + + Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + + Scripting... + + + + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear @@ -5136,6 +5172,44 @@ Download size: %3 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + + + + + 0 + + + SensorView diff --git a/src/platform/qt/ts/mgba-es.ts b/src/platform/qt/ts/mgba-es.ts index e69dc58af..3e09744c2 100644 --- a/src/platform/qt/ts/mgba-es.ts +++ b/src/platform/qt/ts/mgba-es.ts @@ -1272,17 +1272,22 @@ Tamaño de la descarga: %3 QGBA::CheatsView - - + + Autodetect (recommended) Autodetectar (recomendado) - - + + Select cheats file Seleccionar archivo de trucos + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1292,43 +1297,43 @@ Tamaño de la descarga: %3 Reiniciar r%1-%2 %3 - - + + Rewinding not currently enabled Rebobinado desactivado actualmente - + Reset the game? ¿Reiniciar el juego? - + Most games will require a reset to load the new save. Do you want to reset now? La mayoría de juegos requieren reiniciar para cargar la nueva partida guardada. ¿Quieres reiniciar ahora? - + Failed to open save file: %1 Error al abrir el archivo de guardado: %1 - + Failed to open game file: %1 Error al abrir el archivo del juego: %1 - + Can't yank pack in unexpected platform! ¡No se puede remover el cartucho en esta plataforma! - + Failed to open snapshot file for reading: %1 Error al leer del archivo de captura: %1 - + Failed to open snapshot file for writing: %1 Error al escribir al archivo de captura: %1 @@ -3482,47 +3487,47 @@ Tamaño de la descarga: %3 QGBA::LogController - + [%1] %2: %3 [%1] %2: %3 - + An error occurred Ocurrió un error - + DEBUG DEPURACIÓN - + STUB STUB - + INFO INFORMACIÓN - + WARN ADVERTENCIA - + ERROR ERROR - + FATAL FATAL - + GAME ERROR ERROR DE JUEGO @@ -3646,42 +3651,42 @@ Tamaño de la descarga: %3 Cargar - + All Todo - + Load TBL Cargar TBL - + Save selected memory Guardar memoria seleccionada - + Failed to open output file: %1 Error al abrir el archivo de salida: %1 - + Load memory Cargar memoria - + Failed to open input file: %1 Error al abrir el archivo de entrada: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3932,97 +3937,123 @@ Tamaño de la descarga: %3 No se pueden convertir los estados guardados entre plataformas distintas + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (forzar versión 1.x) - + None Ninguno - + None (Still Image) Nada (imagen estática) - + Keyboard Teclado - + Controllers Controladores - + Shortcuts Atajos de teclado - - + + Shaders Shaders - + Select BIOS Seleccionar BIOS - + Select directory Elegir carpeta - + (%1×%2) - + Never Nunca - + Just now Ahora mismo - + Less than an hour ago Hace menos de una hora - + %n hour(s) ago Hace %n hora @@ -4030,7 +4061,7 @@ Tamaño de la descarga: %3 - + %n day(s) ago Hace %n dia @@ -4129,100 +4160,100 @@ Tamaño de la descarga: %3 QGBA::Window - + Game Boy Advance ROMs (%1) ROMs de Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs de Game Boy (%1) - + All ROMs (%1) Todas las ROMs (%1) - + %1 Video Logs (*.mvl) Video-registros de %1 (*.mvl) - + Archives (%1) Contenedores (%1) - - + + Select ROM Seleccionar ROM - + Select folder Seleccionar carpeta - - + + Select save Seleccionar guardado - + Select patch Seleccionar parche - + Patches (*.ips *.ups *.bps) Parches (*.ips *.ups *.bps) - + Select e-Reader dotcode Seleccionar dotcode del e-Reader - + e-Reader card (*.raw *.bin *.bmp) Tarjeta e-Reader (*.raw *.bin *.bmp) - + Select image Seleccionar imagen - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Archivo de imagen (*.png *.gif *.jpg *.jpeg);;Todos los archivos (*) - + GameShark saves (*.sps *.xps) Guardados de GameShark (*.sps *.xps) - + Select video log Seleccionar video-registro - + Video logs (*.mvl) Video-registros (*.mvl) - + Crash Cierre inesperado - + The game has crashed with the following error: %1 @@ -4231,674 +4262,679 @@ Tamaño de la descarga: %3 %1 - + Unimplemented BIOS call Llamada a BIOS no implementada - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Este juego utiliza una llamada al BIOS que no se ha implementado. Utiliza el BIOS oficial para obtener la mejor experiencia. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. No se pudo crear un dispositivo de pantalla apropiado, recurriendo a software. Los juegos pueden funcionar lentamente, especialmente con ventanas grandes. - + Really make portable? ¿Hacer "portable"? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Esto hará que el emulador cargue su configuración desde el mismo directorio que el ejecutable. ¿Quieres continuar? - + Restart needed Reinicio necesario - + Some changes will not take effect until the emulator is restarted. Algunos cambios no surtirán efecto hasta que se reinicie el emulador. - + - Player %1 of %2 - Jugador %1 de %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Archivo - + Load &ROM... Cargar &ROM... - + Load ROM in archive... Cargar ROM desde contenedor... - + Add folder to library... Agregar carpeta a la biblioteca... - + Save games Datos de guardado - + Automatically determine Determinar automáticamente - + Use player %0 save game Usar la partida guardada del jugador %0 - + Load &patch... Cargar &parche... - + Boot BIOS Arrancar BIOS - + Replace ROM... Reemplazar ROM... - + ROM &info... &Información de la ROM... - + Recent Recientes - + Make portable Hacer "portable" - + &Load state Ca&rgar estado - + Report bug... Reportar bug... - + About... Acerca de... - + Game Pak sensors... Sensores del cartucho... - + Clear Limpiar - + Load state file... Cargar archivo de estado... - + Save games (%1) Juegos guardados (%1) - + Select save game Elegir juego guardado - + mGBA save state files (%1) Archivos estados guardados mGBA (%1) - - + + Select save state Elegir estado guardado - + Select e-Reader card images Elegir imágenes de tarjeta e-Reader - + Image file (*.png *.jpg *.jpeg) Archivo de imagen (*.png *.jpg *.jpeg) - + Conversion finished Conversión terminada - + %1 of %2 e-Reader cards converted successfully. %1 de %2 tarjetas e-Reader convertidas con éxito. - + Load alternate save game... Elegir juego guardado alterno... - + Load temporary save game... Elegir juego guardado temporal... - + Convert e-Reader card image to raw... Convertir imagen de tarjeta e-Reader a raw... - + &Save state Guardar e&stado - + Save state file... Guardar archivo de estado... - + Quick load Cargado rápido - + Quick save Guardado rápido - + Load recent Cargar reciente - + Save recent Guardar reciente - + Undo load state Deshacer cargar estado - + Undo save state Deshacer guardar estado - - + + State &%1 Estado &%1 - + Load camera image... Cargar imagen para la cámara... - + Convert save game... Convertir juego guardado... - + GameShark saves (*.gsv *.sps *.xps) Partidas guardadas de GameShark (*.gsv *.sps *.xps) - + Reset needed Reinicio necesario - + Some changes will not take effect until the game is reset. Algunos cambios no tendrán efecto hasta que se reinicie el juego. - + New multiplayer window Nueva ventana multijugador - + Connect to Dolphin... Conectar a Dolphin... - + E&xit Salir (&X) - + &Emulation &Emulación - + &Reset &Reinicializar - + Sh&utdown Apagar (&U) - + Yank game pak Tirar del cartucho - + &Pause &Pausar - + &Next frame Cuadro siguie&nte - + Fast forward (held) Avance rápido (mantener) - + &Fast forward &Avance rápido - + Fast forward speed Velocidad de avance rápido - + Unbounded Sin límite - + %0x %0x - + Rewind (held) Rebobinar (mantener) - + Re&wind Re&bobinar - + Step backwards Paso hacia atrás - + Solar sensor Sensor solar - + Increase solar level Subir nivel - + Decrease solar level Bajar nivel - + Brightest solar level Más claro - + Darkest solar level Más oscuro - + Brightness %1 Brillo %1 - + Audio/&Video Audio/&video - + Frame size Tamaño del cuadro - + Toggle fullscreen Pantalla completa - + Lock aspect ratio Bloquear proporción de aspecto - + Force integer scaling Forzar escala a enteros - + Bilinear filtering Filtro bilineal - + Frame&skip &Salto de cuadros - + Mute Silenciar - + FPS target Objetivo de FPS - + Native (59.7275) Nativo (59,7275) - + Take &screenshot Tomar pan&tallazo - + F12 F12 - + Game Boy Printer... Game Boy Printer... - + BattleChip Gate... BattleChip Gate... - + %1× %1× - + Interframe blending Mezcla entre cuadros - + Record A/V... Grabar A/V... - + Video layers Capas de video - + Audio channels Canales de audio - + Adjust layer placement... Ajustar ubicación de capas... - + &Tools Herramien&tas - + View &logs... Ver re&gistros... - + Game &overrides... Ajustes específic&os por juego... - + Couldn't Start No se pudo iniciar - + Could not start game. No se pudo iniciar el juego. - + Scan e-Reader dotcodes... Escanear dotcodes del e-Reader... - + Import GameShark Save... Importar desde GameShark... - + Export GameShark Save... Exportar a GameShark... - + Record GIF/WebP/APNG... Grabar GIF/WebP/APNG... - + &Cheats... Tru&cos... - + Settings... Ajustes... - + Open debugger console... Abrir consola de depuración... - + Start &GDB server... Iniciar servidor &GDB... - + + Scripting... + + + + View &palette... Ver &paleta... - + View &sprites... Ver &sprites... - + View &tiles... Ver m&osaicos... - + View &map... Ver &mapa... - + &Frame inspector... Inspec&tor de cuadros... - + View memory... Ver memoria... - + Search memory... Buscar memoria... - + View &I/O registers... Ver registros &I/O... - + Record debug video log... Grabar registro de depuración de video... - + Stop debug video log Detener registro de depuración de video - + Exit fullscreen Salir de pantalla completa - + GameShark Button (held) Botón GameShark (mantener) - + Autofire Disparo automático - + Autofire A Disparo automático A - + Autofire B Disparo automático B - + Autofire L Disparo automático L - + Autofire R Disparo automático R - + Autofire Start Disparo automático Start - + Autofire Select Disparo automático Select - + Autofire Up Disparo automático Arriba - + Autofire Right Disparo automático Derecha - + Autofire Down Disparo automático Abajo - + Autofire Left Disparo automático Izquierda @@ -5144,6 +5180,44 @@ Tamaño de la descarga: %3 %1 GameShark Advance SP %2 partida guardada + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + &Reinicializar + + + + 0 + 0 + + SensorView diff --git a/src/platform/qt/ts/mgba-fi.ts b/src/platform/qt/ts/mgba-fi.ts index a616a917f..89e155475 100644 --- a/src/platform/qt/ts/mgba-fi.ts +++ b/src/platform/qt/ts/mgba-fi.ts @@ -1267,17 +1267,22 @@ Download size: %3 QGBA::CheatsView - - + + Autodetect (recommended) - - + + Select cheats file + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1287,43 +1292,43 @@ Download size: %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 - + Failed to open game file: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -3477,47 +3482,47 @@ Download size: %3 QGBA::LogController - + [%1] %2: %3 - + An error occurred - + DEBUG - + STUB - + INFO - + WARN - + ERROR - + FATAL - + GAME ERROR @@ -3641,42 +3646,42 @@ Download size: %3 Ladata - + All - + Load TBL - + Save selected memory - + Failed to open output file: %1 - + Load memory - + Failed to open input file: %1 - + TBL - + ISO-8859-1 @@ -3927,97 +3932,123 @@ Download size: %3 + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia - + SDL - + Software (Qt) - + OpenGL - + OpenGL (force version 1.x) - + None - + None (Still Image) - + Keyboard - + Controllers - + Shortcuts - - + + Shaders - + Select BIOS - + Select directory - + (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago @@ -4025,7 +4056,7 @@ Download size: %3 - + %n day(s) ago @@ -4124,774 +4155,779 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) - - + + Select ROM - + Select folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) - - + + Select save state - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + GameShark saves (*.gsv *.sps *.xps) - + Convert e-Reader card image to raw... - + Import GameShark Save... - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + + Scripting... + + + + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear @@ -5137,6 +5173,44 @@ Download size: %3 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + + + + + 0 + + + SensorView diff --git a/src/platform/qt/ts/mgba-fr.ts b/src/platform/qt/ts/mgba-fr.ts index d6edc2344..e0f929526 100644 --- a/src/platform/qt/ts/mgba-fr.ts +++ b/src/platform/qt/ts/mgba-fr.ts @@ -1273,17 +1273,22 @@ Taille du téléchargement : %3 QGBA::CheatsView - - + + Autodetect (recommended) Détecter automatiquement (recommandé) - - + + Select cheats file Choisir un fichier de cheats + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1293,43 +1298,43 @@ Taille du téléchargement : %3 Réinitialiser r%1-%2 %3 - - + + Rewinding not currently enabled Le rembobinage n'est pas actuellement activé - + Reset the game? Réinitialiser le jeu ? - + Most games will require a reset to load the new save. Do you want to reset now? La plupart des jeux nécessitent une réinitialisation pour charger la nouvelle sauvegarde. Voulez-vous réinitialiser maintenant ? - + Failed to open save file: %1 Échec de l'ouverture du fichier de sauvegarde : %1 - + Failed to open game file: %1 Échec de l'ouverture du fichier de jeu : %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 Échec de l'ouverture de l'instantané pour lire : %1 - + Failed to open snapshot file for writing: %1 Échec de l'ouverture de l'instantané pour écrire : %1 @@ -3494,53 +3499,53 @@ Taille du téléchargement : %3 QGBA::LogController - + [%1] %2: %3 [%1] %2 : %3 - + An error occurred Une erreur est survenue - + DEBUG There is no need to translate this. DEBUG - + STUB There is no need to translate this. STUB - + INFO There is no need to translate this. INFO - + WARN There is no need to translate this. WARN - + ERROR There is no need to translate this. ERROR - + FATAL There is no need to translate this. FATAL - + GAME ERROR There is no need to translate this. GAME ERROR @@ -3665,42 +3670,42 @@ Taille du téléchargement : %3 Charger - + All Tout - + Load TBL Charger le TBL - + Save selected memory Sauvegarder la mémoire sélectionné - + Failed to open output file: %1 Impossible d'ouvrir le fichier de sortie : %1 - + Load memory Charger la mémoire - + Failed to open input file: %1 Impossible d'ouvrir le fichier d'entrée : %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3951,97 +3956,123 @@ Taille du téléchargement : %3 + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia Qt Multimédia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (version forcée 1.x) - + None Aucun - + None (Still Image) Aucun (Image fixe) - + Keyboard Clavier - + Controllers Contrôleurs - + Shortcuts Raccourcis - - + + Shaders Shaders - + Select BIOS Choisir le BIOS - + Select directory - + (%1×%2) (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago @@ -4049,7 +4080,7 @@ Taille du téléchargement : %3 - + %n day(s) ago @@ -4148,120 +4179,120 @@ Taille du téléchargement : %3 QGBA::Window - + Game Boy Advance ROMs (%1) ROMs de Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs de Game Boy (%1) - + All ROMs (%1) Toutes les ROM (%1) - + %1 Video Logs (*.mvl) %1 Journaux vidéo (*.mvl) - + Archives (%1) Archives (%1) - - + + Select ROM Choisir une ROM - + Select folder Choisir un dossier - - + + Select save Choisir une sauvegarde - + Select patch Sélectionner un correctif - + Patches (*.ips *.ups *.bps) Correctifs/Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode Sélectionnez le numéro de point du e-Reader - + e-Reader card (*.raw *.bin *.bmp) e-Reader carte (*.raw *.bin *.bmp) - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Select image Choisir une image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Image (*.png *.gif *.jpg *.jpeg);;Tous les fichiers (*) - + GameShark saves (*.sps *.xps) Sauvegardes GameShark (*.sps *.xps) - + Select video log Sélectionner un journal vidéo - + Video logs (*.mvl) Journaux vidéo (*.mvl) - + Crash Plantage - + The game has crashed with the following error: %1 @@ -4270,654 +4301,659 @@ Taille du téléchargement : %3 %1 - + Unimplemented BIOS call Requête au BIOS non supporté - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Ce jeu utilise un appel BIOS qui n'est pas implémenté. Veuillez utiliser le BIOS officiel pour une meilleure expérience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Échec de la création d'un périphérique d'affichage approprié, retour à l'affichage du logiciel. Les jeux peuvent fonctionner lentement, en particulier avec des fenêtres plus grandes. - + Really make portable? Vraiment rendre portable ? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Cela amènera l'émulateur à charger sa configuration depuis le même répertoire que l'exécutable. Souhaitez vous continuer ? - + Restart needed Un redémarrage est nécessaire - + Some changes will not take effect until the emulator is restarted. Certains changements ne prendront effet qu'après le redémarrage de l'émulateur. - + - Player %1 of %2 - Joueur %1 of %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Fichier - + Load &ROM... Charger une &ROM… - + Load ROM in archive... Charger la ROM d'une archive… - + Add folder to library... Ajouter un dossier à la bibliothèque… - + Load &patch... Charger un c&orrectif… - + Boot BIOS Démarrer le BIOS - + Replace ROM... Remplacer la ROM… - + Convert e-Reader card image to raw... - + ROM &info... &Infos sur la ROM… - + Recent Récent - + Make portable Rendre portable - + &Load state &Charger un état - + &Save state &Sauvegarder un état - + Quick load Chargement rapide - + Quick save Sauvegarde rapide - + Load recent Charger un fichier récent - + Save recent Sauvegarder un fichier récent - + Undo load state Annuler le chargement de l'état - + Undo save state Annuler la sauvegarde de l'état - - + + State &%1 État &%1 - + Load camera image... Charger une image de la caméra… - + Convert save game... - + New multiplayer window Nouvelle fenêtre multijoueur - + Connect to Dolphin... - + Report bug... Signalement de l'erreur… - + E&xit &Quitter - + &Emulation &Émulation - + &Reset &Réinitialiser - + Sh&utdown Extin&ction - + Yank game pak Yank game pak - + &Pause &Pause - + &Next frame &Image suivante - + Fast forward (held) Avance rapide (maintenir) - + &Fast forward A&vance rapide - + Fast forward speed Vitesse de l'avance rapide - + Unbounded Sans limites - + %0x %0x - + Rewind (held) Rembobiner (maintenir) - + Re&wind Rem&bobiner - + Step backwards Retour en arrière - + Solar sensor Capteur solaire - + Increase solar level Augmenter le niveau solaire - + Decrease solar level Diminuer le niveau solaire - + Brightest solar level Tester le niveau solaire - + Darkest solar level Assombrir le niveau solaire - + Brightness %1 Luminosité %1 - + Audio/&Video Audio/&Vidéo - + Frame size Taille de l'image - + Toggle fullscreen Basculer en plein écran - + Lock aspect ratio Bloquer les proportions - + Force integer scaling Forcer la mise à l'échelle par des nombres entiers - + Bilinear filtering Filtrage bilinèaire - + Frame&skip &Saut d'image - + Mute Muet - + FPS target FPS ciblé - + Take &screenshot Prendre une ca&pture d'écran - + F12 F12 - + Game Boy Printer... Imprimante GameBoy… - + Video layers Couches vidéo - + Audio channels Canaux audio - + Adjust layer placement... Ajuster la disposition… - + &Tools Ou&tils - + View &logs... Voir les &journaux… - + Game &overrides... - + Couldn't Start N'a pas pu démarrer - + Save games (%1) - + Select save game - + mGBA save state files (%1) - - + + Select save state - + GameShark saves (*.gsv *.sps *.xps) - + Could not start game. Impossible de démarrer le jeu. - + Load alternate save game... - + Load temporary save game... - + Scan e-Reader dotcodes... Scanner les dotcodes e-Reader... - + Load state file... Charger le fichier d'état... - + Save state file... Enregistrer le fichier d'état... - + Import GameShark Save... Importer la sauvegarde de GameShark... - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games Sauvegarder les jeux - + Export GameShark Save... Exporter la sauvegarde de GameShark... - + Automatically determine - + Use player %0 save game - + About... À propos de… - + BattleChip Gate... - + %1× %1× - + Interframe blending Mélange d'images - + Native (59.7275) Natif (59.7275) - + Record A/V... Enregistrer A/V... - + Record GIF/WebP/APNG... Enregistrer GIF/WebP/APNG... - + Game Pak sensors... Capteurs de la Game Pak... - + &Cheats... &Cheats… - + Settings... Paramètres… - + Open debugger console... Ouvrir la console de débug… - + Start &GDB server... Démarrer le serveur &GDB… - + + Scripting... + + + + View &palette... Voir la &palette… - + View &sprites... Voir les &sprites… - + View &tiles... Voir les &tiles… - + View &map... Voir la &map… - + &Frame inspector... Inspecteur de &frame... - + View memory... Voir la mémoire… - + Search memory... Recherche dans la mémoire… - + View &I/O registers... Voir les registres d'&E/S... - + Record debug video log... Enregistrer le journal vidéo de débogage... - + Stop debug video log Arrêter le journal vidéo de débogage - + Exit fullscreen Quitter le plein écran - + GameShark Button (held) Bouton GameShark (maintenir) - + Autofire Tir automatique - + Autofire A Tir automatique A - + Autofire B Tir automatique B - + Autofire L Tir automatique L - + Autofire R Tir automatique R - + Autofire Start Tir automatique Start - + Autofire Select Tir automatique Select - + Autofire Up Tir automatique Up - + Autofire Right Tir automatique Right - + Autofire Down Tir automatique Down - + Autofire Left Tir automatique Gauche - + Clear Vider @@ -5163,6 +5199,44 @@ Taille du téléchargement : %3 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + &Réinitialiser + + + + 0 + 0 + + SensorView diff --git a/src/platform/qt/ts/mgba-hu.ts b/src/platform/qt/ts/mgba-hu.ts index af928439c..00f149f95 100644 --- a/src/platform/qt/ts/mgba-hu.ts +++ b/src/platform/qt/ts/mgba-hu.ts @@ -1267,17 +1267,22 @@ Download size: %3 QGBA::CheatsView - - + + Autodetect (recommended) - - + + Select cheats file Csalásfájl kiválasztása + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1287,43 +1292,43 @@ Download size: %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 Nem sikerült a mentésfájl megnyitása: %1 - + Failed to open game file: %1 Nem sikerült a játékfájl megnyitása: %1 - + Can't yank pack in unexpected platform! A játékkazettát nem lehet kirántani ismeretlen platformon! - + Failed to open snapshot file for reading: %1 A pillanatkép fájljának olvasásra való megnyitása sikertelen: %1 - + Failed to open snapshot file for writing: %1 A pillanatkép fájljának írásra való megnyitása sikertelen: %1 @@ -3477,47 +3482,47 @@ Download size: %3 QGBA::LogController - + [%1] %2: %3 - + An error occurred - + DEBUG - + STUB - + INFO - + WARN - + ERROR - + FATAL - + GAME ERROR @@ -3641,42 +3646,42 @@ Download size: %3 Betöltés - + All Mind - + Load TBL TBL betöltése - + Save selected memory - + Failed to open output file: %1 Nem sikerült a kimeneti fájl megnyitása: %1 - + Load memory - + Failed to open input file: %1 - + TBL - + ISO-8859-1 @@ -3927,104 +3932,130 @@ Download size: %3 + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia - + SDL - + Software (Qt) - + OpenGL - + OpenGL (force version 1.x) - + None Nincs - + None (Still Image) - + Keyboard - + Controllers - + Shortcuts - - + + Shaders - + Select BIOS - + Select directory - + (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago - + %n day(s) ago @@ -4122,774 +4153,779 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) - - + + Select ROM - + Select folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) - - + + Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x %0x - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + + Scripting... + + + + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear Napló törlése @@ -5135,6 +5171,44 @@ Download size: %3 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + + + + + 0 + 0 + + SensorView diff --git a/src/platform/qt/ts/mgba-it.ts b/src/platform/qt/ts/mgba-it.ts index a99033108..8dbec5cd8 100644 --- a/src/platform/qt/ts/mgba-it.ts +++ b/src/platform/qt/ts/mgba-it.ts @@ -1272,17 +1272,22 @@ Dimensione del download: %3 QGBA::CheatsView - - + + Autodetect (recommended) Rilevamento automatico (consigliato) - - + + Select cheats file Seleziona il file cheats + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1292,43 +1297,43 @@ Dimensione del download: %3 Reset r%1-%2 %3 - - + + Rewinding not currently enabled Rewind attualmente disattivato - + Reset the game? Resettare il gioco? - + Most games will require a reset to load the new save. Do you want to reset now? La maggior parte dei giochi richiederà un reset per caricare il nuovo salvataggio. Vuoi resettare ora? - + Failed to open save file: %1 Impossibile aprire il file di salvataggio: %1 - + Failed to open game file: %1 Impossibile aprire il file di gioco: %1 - + Can't yank pack in unexpected platform! Non riesco a strappare il pacchetto in una piattaforma inaspettata! - + Failed to open snapshot file for reading: %1 Impossibile aprire il file snapshot per la lettura: %1 - + Failed to open snapshot file for writing: %1 Impossibile aprire il file snapshot per la scrittura: %1 @@ -3482,47 +3487,47 @@ Dimensione del download: %3 QGBA::LogController - + [%1] %2: %3 [%1] %2: %3 - + An error occurred È avvenuto un errore - + DEBUG DEBUG - + STUB STUB - + INFO INFORMAZIONI - + WARN AVVERTENZA - + ERROR ERRORE - + FATAL FATALE - + GAME ERROR ERRORE NEL GIOCO @@ -3646,42 +3651,42 @@ Dimensione del download: %3 Carica - + All Tutto - + Load TBL Carica TBL - + Save selected memory Salva la memoria selezionata - + Failed to open output file: %1 Impossibile aprire il file di output: %1 - + Load memory Carica memoria - + Failed to open input file: %1 Impossibile aprire il file di input: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3932,97 +3937,123 @@ Dimensione del download: %3 Impossibile convertire salvataggi tra piattaforme + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (forza la versione 1.x) - + None Nessuno - + None (Still Image) nessuno (immagine fissa) - + Keyboard Tastiera - + Controllers Controller - + Shortcuts Scorciatoie - - + + Shaders Shader - + Select BIOS Seleziona BIOS - + Select directory Seleziona directory - + (%1×%2) (%1×%2) - + Never Mai - + Just now Solo adesso - + Less than an hour ago Meno di un ora fa - + %n hour(s) ago %n ora fa @@ -4030,7 +4061,7 @@ Dimensione del download: %3 - + %n day(s) ago %n giorno fa @@ -4129,115 +4160,115 @@ Dimensione del download: %3 QGBA::Window - + Game Boy Advance ROMs (%1) ROM per Game Boy Advance (%1) - + Game Boy ROMs (%1) ROM per Game Boy (%1) - + All ROMs (%1) Tutte le ROM (%1) - + %1 Video Logs (*.mvl) %1 log Video (*.mvl) - + Archives (%1) Archivi (%1) - - + + Select ROM Seleziona ROM - - + + Select save Seleziona salvataggio - + Select patch Seleziona patch - + Patches (*.ips *.ups *.bps) Patch (*.ips *.ups *.bps) - + Select e-Reader dotcode Selezione e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) e-Reader card (*.raw *.bin *.bmp) - + Select e-Reader card images Seleziona immagini carte e-Reader - + Image file (*.png *.jpg *.jpeg) File immagine (*.png *.jpg *.jpeg) - + Conversion finished Conversione terminata - + %1 of %2 e-Reader cards converted successfully. %1 di %2 carte e-Reader convertite con successo. - + Select image Seleziona immagine - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) File immagine (*.png *.gif *.jpg *.jpeg);;Tutti i file (*) - + GameShark saves (*.sps *.xps) Salvataggi GameShark (*.sps *.xps) - + Select video log Seleziona log video - + Video logs (*.mvl) Log video (*.mvl) - + Crash Errore fatale - + The game has crashed with the following error: %1 @@ -4246,659 +4277,664 @@ Dimensione del download: %3 %1 - + Unimplemented BIOS call BIOS non implementato - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Questo gioco utilizza una chiamata BIOS non implementata. Utilizza il BIOS ufficiale per una migliore esperienza. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Impossibile creare un dispositivo di visualizzazione appropriato, tornando alla visualizzazione software. I giochi possono funzionare lentamente, specialmente con finestre più grandi. - + Really make portable? Vuoi davvero rendere portatile l'applicazione? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? In questo modo l'emulatore carica la propria configurazione dalla stessa cartella dell'eseguibile. Vuoi continuare? - + Restart needed È necessario riavviare - + Some changes will not take effect until the emulator is restarted. Alcune modifiche non avranno effetto finché l'emulatore non verrà riavviato. - + - Player %1 of %2 - Giocatore %1 di %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File File - + Load &ROM... Carica ROM... - + Load ROM in archive... Carica la ROM in archivio... - + Load &patch... Carica patch... - + Boot BIOS Avvia BIOS - + Replace ROM... Sostituisci la ROM... - + Scan e-Reader dotcodes... Scansiona e-Reader dotcode... - + Convert e-Reader card image to raw... Converti immagini carte e-Reader in raw... - + ROM &info... Informazioni ROM... - + Recent Recenti - + Make portable Rendi portatile - + &Load state Carica stato - + &Save state Salva stato - + Quick load Caricamento rapido - + Quick save Salvataggio rapido - + Load recent Carica recente - + Save recent Salva recente - + Undo load state Annulla il caricamento dello stato - + Undo save state Annulla salvataggio stato - - + + State &%1 Stato %1 - + Load camera image... Carica immagine fotocamera... - + Convert save game... Converti salvataggi... - + GameShark saves (*.gsv *.sps *.xps) Salvataggi GameShark (*.gsv *.sps *.xps) - + Reset needed Reset necessario - + Some changes will not take effect until the game is reset. Alcune modifiche non si applicheranno finché il gioco non viene resettato. - + New multiplayer window Nuova finestra multigiocatore - + Connect to Dolphin... Connessione a Dolphin... - + Report bug... Segnala bug... - + E&xit Esci (&X) - + &Emulation Emulazione - + &Reset Reset - + Sh&utdown Spegni (&U) - + Yank game pak Yank game pak - + &Pause Pausa - + &Next frame Salta il prossimo frame (&N) - + Fast forward (held) Avanzamento rapido (tieni premuto) - + &Fast forward Avanzamento rapido (&F) - + Fast forward speed Velocità di avanzamento rapido - + Unbounded Illimitata - + %0x %0x - + Rewind (held) Riavvolgimento (tieni premuto) - + Re&wind Riavvolgimento (&W) - + Step backwards Torna indietro - + Solar sensor Sensore solare - + Increase solar level Incrementa il livello solare - + Decrease solar level Riduci il livello solare - + Brightest solar level Livello solare massimo - + Darkest solar level Livello solare minimo - + Brightness %1 Luminosità %1 - + Audio/&Video Audio/Video - + Frame size Dimensione frame - + Toggle fullscreen Abilita schermo Intero - + Lock aspect ratio Blocca rapporti aspetto - + Frame&skip Salto frame - + Mute Muto - + FPS target FPS finali - + Take &screenshot Acquisisci schermata - + F12 F12 - + Record GIF/WebP/APNG... Registra GIF / WebP / APNG ... - + Video layers Layers video - + Audio channels Canali audio - + &Tools Strumenti - + View &logs... Visualizza registri (&log)... - + Game &overrides... Valore specifico per il gioco... - + &Cheats... Trucchi... - + Open debugger console... Apri console debugger... - + Start &GDB server... Avvia server GDB... - + Settings... Impostazioni... - + Select folder Seleziona cartella - + Couldn't Start Non è stato possibile avviare - + Could not start game. Non è stato possibile avviare il gioco. - + Add folder to library... Aggiungi cartella alla libreria... - + Load state file... Carica stato di salvataggio... - + Save state file... Salva stato di salvataggio... - + Import GameShark Save... Importa Salvataggio GameShark... - + Export GameShark Save... Esporta Salvataggio GameShark... - + About... Informazioni… - + Force integer scaling Forza ridimensionamento a interi - + Bilinear filtering Filtro bilineare - + Game Boy Printer... Stampante Game Boy... - + Save games (%1) Salvataggi (%1) - + Select save game Seleziona salvataggio - + mGBA save state files (%1) file di stati di salvataggio mGBA (%1) - - + + Select save state Seleziona stato di salvataggio - + Save games Salvataggi - + Load alternate save game... Carica stato di salvataggio alternativo... - + Load temporary save game... Carica salvataggio temporaneo... - + Automatically determine Determina automaticamente - + Use player %0 save game Usa il salvataggio del giocatore %0 - + BattleChip Gate... BattleChip Gate... - + %1× %1x - + Interframe blending Miscelazione dei frame - + Native (59.7275) Nativo (59.7) - + Record A/V... Registra A/V... - + Adjust layer placement... Regola posizionamento layer... - + Game Pak sensors... Sensori Game Pak... - + + Scripting... + + + + View &palette... Mostra palette... - + View &sprites... Mostra sprites... - + View &tiles... Mostra tiles... - + View &map... Mostra mappa... - + &Frame inspector... &Frame inspector... - + View memory... Mostra memoria... - + Search memory... Ricerca memoria... - + View &I/O registers... Mostra registri I/O... - + Record debug video log... Registra video log di debug... - + Stop debug video log Ferma video log di debug - + Exit fullscreen Esci da Schermo Intero - + GameShark Button (held) Pulsante GameShark (tieni premuto) - + Autofire Pulsanti Autofire - + Autofire A Autofire A - + Autofire B Autofire B - + Autofire L Autofire L - + Autofire R Autofire R - + Autofire Start Autofire Start - + Autofire Select Autofire Select - + Autofire Up Autofire Su - + Autofire Right AAutofire Destra - + Autofire Down Autofire Giù - + Autofire Left Autofire Sinistra - + Clear Pulisci @@ -5144,6 +5180,44 @@ Dimensione del download: %3 %1 GameShark Advance SP %2 salvataggio gioco + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + Reset + + + + 0 + 0 + + SensorView diff --git a/src/platform/qt/ts/mgba-ja.ts b/src/platform/qt/ts/mgba-ja.ts index 4b9e82ccf..d230a676a 100644 --- a/src/platform/qt/ts/mgba-ja.ts +++ b/src/platform/qt/ts/mgba-ja.ts @@ -1267,17 +1267,22 @@ Download size: %3 QGBA::CheatsView - - + + Autodetect (recommended) - - + + Select cheats file チートファイルを選択 + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1287,43 +1292,43 @@ Download size: %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 セーブファイルを開けませんでした: %1 - + Failed to open game file: %1 ゲームファイルを開けませんでした: %1 - + Can't yank pack in unexpected platform! 予期しないプラットフォームでパックをヤンクすることはできません! - + Failed to open snapshot file for reading: %1 読み取り用のスナップショットファイルを開けませんでした: %1 - + Failed to open snapshot file for writing: %1 書き込み用のスナップショットファイルを開けませんでした: %1 @@ -3477,47 +3482,47 @@ Download size: %3 QGBA::LogController - + [%1] %2: %3 [%1] %2: %3 - + An error occurred エラーが発生しました - + DEBUG DEBUG - + STUB STUB - + INFO INFO - + WARN WARN - + ERROR ERROR - + FATAL FATAL - + GAME ERROR GAME ERROR @@ -3641,42 +3646,42 @@ Download size: %3 ロード - + All All - + Load TBL TBLをロード - + Save selected memory 選択したメモリを保存 - + Failed to open output file: %1 出力ファイルを開けませんでした: %1 - + Load memory メモリをロード - + Failed to open input file: %1 入力ファイルを開けませんでした: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3927,104 +3932,130 @@ Download size: %3 + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) ソフト(Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL(バージョン1.xを強制) - + None なし - + None (Still Image) なし(静止画) - + Keyboard キーボード - + Controllers コントローラー - + Shortcuts ショートカット - - + + Shaders シェーダー - + Select BIOS BIOSを選択 - + Select directory - + (%1×%2) (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago - + %n day(s) ago @@ -4122,100 +4153,100 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) ゲームボーイアドバンスファイル (%1) - + Game Boy ROMs (%1) ゲームボーイファイル (%1) - + All ROMs (%1) すべてのファイル (%1) - + %1 Video Logs (*.mvl) %1ビデオログ (*.mvl) - + Archives (%1) アーカイブファイル (%1) - - + + Select ROM ROMを開く - + Select folder フォルダを開く - - + + Select save セーブを開く - + Select patch パッチを開く - + Patches (*.ips *.ups *.bps) パッチファイル (*.ips *.ups *.bps) - + Select e-Reader dotcode カードeを開く - + e-Reader card (*.raw *.bin *.bmp) カードe (*.raw *.bin *.bmp) - + Select image 画像を開く - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) 画像ファイル (*.png *.gif *.jpg *.jpeg);;すべてのファイル (*) - + GameShark saves (*.sps *.xps) GameSharkセーブファイル (*.sps *.xps) - + Select video log ビデオログを開く - + Video logs (*.mvl) ビデオログ (*.mvl) - + Crash クラッシュ - + The game has crashed with the following error: %1 @@ -4224,674 +4255,679 @@ Download size: %3 %1 - + Couldn't Start 起動失敗 - + Could not start game. ゲームを起動できませんでした。 - + Unimplemented BIOS call 未実装のBIOS呼び出し - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. このゲームは実装されていないBIOS呼び出しを使用します。最高のエクスペリエンスを得るには公式のBIOSを使用してください。 - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. 適切なディスプレイデバイスの作成に失敗し、ソフトディスプレイにフォールバックしました。特に大きなウィンドウでは、ゲームの実行が遅い場合があります。 - + Really make portable? 本当にポータブルにしますか? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? これによりエミュレータは実行ファイルと同じディレクトリにある設定ファイルをロードします。続けますか? - + Restart needed 再起動が必要 - + Some changes will not take effect until the emulator is restarted. 一部の変更は、エミュレータを再起動するまで有効になりません。 - + - Player %1 of %2 - プレーヤー %1 of %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &ファイル (&F) - + Load &ROM... ROMをロード... - + Load ROM in archive... アーカイブにROMをロード... - + Add folder to library... ライブラリーにフォルダを追加... - + Load &patch... パッチをロード... (&P) - + Boot BIOS BIOSを起動 - + Replace ROM... ROMを交換... - + Scan e-Reader dotcodes... カードeをスキャン... - + ROM &info... ROM情報... (&I) - + Recent 最近開いたROM - + Make portable ポータブル化 - + &Load state ステートをロード (&L) - + Report bug... バグ報告 - + About... バージョン情報... - + Record GIF/WebP/APNG... GIF/WebP/APNGを記録 - + Game Pak sensors... カートリッジセンサー... - + Clear 消去 - + Load state file... ステートファイルをロード... - + Save games (%1) - + Select save game - + mGBA save state files (%1) - - + + Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Convert e-Reader card image to raw... - + &Save state ステートをセーブ (&S) - + Save state file... ステートファイルをセーブ... - + Quick load クイックロード - + Quick save クイックセーブ - + Load recent 最近使ったクイックロットからロード - + Save recent 最近使ったクイックロットにセーブ - + Undo load state クイックロードを元に戻す - + Undo save state クイックセーブを元に戻す - - + + State &%1 クイックスロット &%1 - + Load camera image... カメラ画像をロード... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Import GameShark Save... GameSharkスナップショットを読み込む - + Export GameShark Save... GameSharkスナップショットを書き出す - + New multiplayer window 新しいウィンドウ(マルチプレイ) - + Connect to Dolphin... - + E&xit 終了 (&X) - + &Emulation エミュレーション (&E) - + &Reset リセット (&R) - + Sh&utdown 閉じる (&U) - + Yank game pak ゲームパックをヤンク - + &Pause 一時停止 (&P) - + &Next frame 次のフレーム (&N) - + Fast forward (held) 早送り(押し) - + &Fast forward 早送り (&F) - + Fast forward speed 早送り速度 - + Unbounded 制限なし - + %0x %0x - + Rewind (held) 巻戻し(押し) - + Re&wind 巻戻し (&R) - + Step backwards 1フレーム巻き戻す - + Solar sensor 太陽センサー - + Increase solar level 明るさを上げる - + Decrease solar level 明るさを下げる - + Brightest solar level 明るさ最高 - + Darkest solar level 明るさ最低 - + Brightness %1 明るさ %1 - + Audio/&Video オーディオ/ビデオ (&V) - + Frame size 画面サイズ - + Toggle fullscreen 全画面表示 - + Lock aspect ratio 縦横比を固定 - + Force integer scaling 整数スケーリングを強制 - + Bilinear filtering バイリニアフィルタリング - + Frame&skip フレームスキップ (&S) - + Mute ミュート - + FPS target FPS - + Native (59.7275) ネイティブ(59.7275) - + Take &screenshot スクリーンショット (&S) - + F12 F12 - + Game Boy Printer... ポケットプリンタ... - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games セーブデータ - + Automatically determine - + Use player %0 save game - + BattleChip Gate... チップゲート... - + %1× %1× - + Interframe blending フレーム間混合 - + Record A/V... ビデオ録画... - + Video layers ビデオレイヤー - + Audio channels オーディオチャンネル - + Adjust layer placement... レイヤーの配置を調整... - + &Tools ツール (&T) - + View &logs... ログビューアー... (&L) - + Game &overrides... ゲーム別設定... (&O) - + &Cheats... チート... (&C) - + Settings... 設定... - + Open debugger console... デバッガコンソールを開く... - + Start &GDB server... GDBサーバを起動... (&G) - + + Scripting... + + + + View &palette... パレットビューアー... (&P) - + View &sprites... スプライトビューアー... (&S) - + View &tiles... タイルビューアー... (&T) - + View &map... マップビューアー... (&M) - + &Frame inspector... フレームインスペクタ... (&F) - + View memory... メモリビューアー... - + Search memory... メモリ検索... - + View &I/O registers... IOビューアー... (&I) - + Record debug video log... デバッグビデオログ... - + Stop debug video log デバッグビデオログを停止 - + Exit fullscreen 全画面表示を終了 - + GameShark Button (held) GameSharkボタン(押し) - + Autofire 連打 - + Autofire A 連打 A - + Autofire B 連打 B - + Autofire L 連打 L - + Autofire R 連打 R - + Autofire Start 連打 Start - + Autofire Select 連打 Select - + Autofire Up 連打 上 - + Autofire Right 連打 右 - + Autofire Down 連打 下 - + Autofire Left 連打 左 @@ -5137,6 +5173,44 @@ Download size: %3 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + リセット (&R) + + + + 0 + 0 + + SensorView diff --git a/src/platform/qt/ts/mgba-ko.ts b/src/platform/qt/ts/mgba-ko.ts index 5b18c099a..477f49ea9 100644 --- a/src/platform/qt/ts/mgba-ko.ts +++ b/src/platform/qt/ts/mgba-ko.ts @@ -1267,17 +1267,22 @@ Download size: %3 QGBA::CheatsView - - + + Autodetect (recommended) - - + + Select cheats file 치트 파일 선택 + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1287,43 +1292,43 @@ Download size: %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 저장 파일을 열지 못했습니다: %1 - + Failed to open game file: %1 게임 파일을 열지 못했습니다: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 읽기 용 스냅샷 파일을 열지 못했습니다: %1 - + Failed to open snapshot file for writing: %1 쓰기 용 스냅샷 파일을 열지 못했습니다: %1 @@ -3477,47 +3482,47 @@ Download size: %3 QGBA::LogController - + [%1] %2: %3 - + An error occurred - + DEBUG 디버그 - + STUB 스텁 - + INFO 정보 - + WARN 경고 - + ERROR 오류 - + FATAL 치명적 - + GAME ERROR 게임 오류 @@ -3641,42 +3646,42 @@ Download size: %3 로드 - + All 모두 - + Load TBL 테이블 로드 - + Save selected memory 선택한 메모리 저장 - + Failed to open output file: %1 출력 파일을 열지 못했습니다: %1 - + Load memory 메모리 로드 - + Failed to open input file: %1 입력 파일을 열지 못했습니다: %1 - + TBL 테이블 - + ISO-8859-1 ISO-8859-1 @@ -3927,104 +3932,130 @@ Download size: %3 + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia Qt 멀티미디어 - + SDL SDL - + Software (Qt) 소프트웨어 (Qt) - + OpenGL 오픈GL - + OpenGL (force version 1.x) 오픈GL (버전 1.x 강제) - + None 없음 - + None (Still Image) 없음 (정지 이미지) - + Keyboard 키보드 - + Controllers 컨트롤러 - + Shortcuts 단축키 - - + + Shaders 쉐이더 - + Select BIOS 바이오스 선택 - + Select directory - + (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago - + %n day(s) ago @@ -4122,115 +4153,115 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) 게임 보이 어드밴스 롬 (%1) - + Game Boy ROMs (%1) 게임 보이 (%1) - + All ROMs (%1) 모든 롬 (%1) - + %1 Video Logs (*.mvl) %1 비디오 로그 (*.mvl) - + Archives (%1) 아카이브 (%1) - - + + Select ROM 롬 선택 - - + + Select save 저장 파일 선택 - + Select patch 패치 선택 - + Patches (*.ips *.ups *.bps) 패치 (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Select image 이미지 선택 - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) 이미지 파일 (*.png *.gif *.jpg *.jpeg);;모든 파일 (*) - + GameShark saves (*.sps *.xps) 게임샤크 저장 파일 (*.sps *.xps) - + Select video log 비디오 로그 선택 - + Video logs (*.mvl) 비디오 로그 (*.mvl) - + Crash 치명적인 오류 - + The game has crashed with the following error: %1 @@ -4239,659 +4270,664 @@ Download size: %3 %1 - + Unimplemented BIOS call 구현되지 않은 바이오스 호출 - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. 이 게임은 구현되지 않은 바이오스 호출을 사용합니다. 최상의 성능을 얻으려면 공식 바이오스를 사용하십시오. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? 정말로 휴대용을 만듭니까? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? 이렇게하면 에뮬레이터가 실행 파일과 동일한 디렉토리에서 구성을 로드하게됩니다. 계속 하시겠습니까? - + Restart needed 재시작 필요 - + Some changes will not take effect until the emulator is restarted. 일부 변경 사항은 에뮬레이터가 다시 시작될 때까지 적용되지 않습니다. - + Reset needed - + Some changes will not take effect until the game is reset. - + - Player %1 of %2 - 플레이어 %1 의 %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &파일 - + Load &ROM... 로드 &롬... - + Load ROM in archive... 롬을 아카이브에 로드... - + Save games 게임 저장 - + Automatically determine - + Use player %0 save game - + Load &patch... 로드 &패치... - + Boot BIOS BIOS 부팅 - + Replace ROM... 롬 교체... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... 롬 &정보... - + Recent 최근 실행 - + Make portable 휴대용 만들기 - + &Load state &로드 파일 상태 - + &Save state &저장 파일 상태 - + Quick load 빠른 로드 - + Quick save 빠른 저장 - + Load recent 최근 실행 로드 - + Save recent 최근 실행 저장 - + Undo load state 로드 파일 상태 복원 - + Undo save state 저장 파일 상태 복원 - - + + State &%1 상태 &%1 - + Load camera image... 카메라 이미지 로드... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + New multiplayer window 새로운 멀티 플레이어 창 - + Connect to Dolphin... - + E&xit 종&료 - + &Emulation &에뮬레이션 - + &Reset &재설정 - + Sh&utdown 종&료 - + Yank game pak 양키 게임 팩 - + &Pause &정지 - + &Next frame &다음 프레임 - + Fast forward (held) 빨리 감기 (누름) - + &Fast forward &빨리 감기 - + Fast forward speed 빨리 감기 속도 - + Unbounded 무제한 - + %0x %0x - + Rewind (held) 되김기 (누름) - + Re&wind 리&와인드 - + Step backwards 돌아가기 - + Brightest solar level 가장 밝은 태양 수준 - + Darkest solar level 가장 어두운 태양 수준 - + Brightness %1 밝기 %1 - + Audio/&Video 오디오/&비디오 - + Frame size 프레임 크기 - + Toggle fullscreen 전체화면 전환 - + Lock aspect ratio 화면비 잠금 - + Frame&skip 프레임&건너뛰기 - + Mute 무음 - + FPS target FPS 대상 - + Take &screenshot 스크린샷 &찍기 - + F12 F12 - + Video layers 비디오 레이어 - + Audio channels 오디오 채널 - + &Tools &도구 - + View &logs... 로그 &보기... - + Game &overrides... 게임 &오버라이드... - + &Cheats... &치트.. - + Open debugger console... 디버거 콘솔 열기... - + Start &GDB server... GDB 서버 &시작... - + Settings... 설정... - + Select folder 폴더 선택 - + Couldn't Start - + Could not start game. - + Add folder to library... 라이브러리에 폴더 추가... - + Load state file... - + Save state file... - + Import GameShark Save... - + Export GameShark Save... - + Report bug... - + About... - + Solar sensor - + Increase solar level - + Decrease solar level - + Force integer scaling 정수 스케일링 강제 수행 - + Bilinear filtering 이중선형 필터링 - + Game Boy Printer... 게임 보이 프린터... - + Save games (%1) - + Select save game - + mGBA save state files (%1) - - + + Select save state - + Load alternate save game... - + Load temporary save game... - + BattleChip Gate... - + %1× %1x {1×?} - + Interframe blending - + Native (59.7275) Nativo (59.7) {59.7275)?} - + Record A/V... - + Record GIF/WebP/APNG... - + Adjust layer placement... 레이어 배치 조정... - + Game Pak sensors... - + + Scripting... + + + + View &palette... 팔레트 &보기... - + View &sprites... 스프라이트 &보기... - + View &tiles... 타일 &보기... - + View &map... 지도 &보기... - + &Frame inspector... - + View memory... 메모리 보기... - + Search memory... 메모리 검색... - + View &I/O registers... I/O 레지스터 &보기... - + Record debug video log... - + Stop debug video log - + Exit fullscreen 전체화면 종료 - + GameShark Button (held) 게임샤크 버튼 (누름) - + Autofire 연사 - + Autofire A 연사 A - + Autofire B 연사 B - + Autofire L 연사 L - + Autofire R 연사 R - + Autofire Start 연사 시작 - + Autofire Select - + Clear 정리 - + Autofire Up 연사 위쪽 - + Autofire Right 연사 오른쪽 - + Autofire Down 연사 아래쪽 - + Autofire Left 연사 왼쪽 @@ -5137,6 +5173,44 @@ Download size: %3 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + &재설정 + + + + 0 + 0 + + SensorView diff --git a/src/platform/qt/ts/mgba-ms.ts b/src/platform/qt/ts/mgba-ms.ts index f75a32b1f..494031c44 100644 --- a/src/platform/qt/ts/mgba-ms.ts +++ b/src/platform/qt/ts/mgba-ms.ts @@ -1266,17 +1266,22 @@ Download size: %3 QGBA::CheatsView - - + + Autodetect (recommended) - - + + Select cheats file Pilih fail tipu + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1286,43 +1291,43 @@ Download size: %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 Gagal membuka fail tersimpan: %1 - + Failed to open game file: %1 Gagal membuka fail permainan: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 Gagal membuka fail snapshot untuk baca: %1 - + Failed to open snapshot file for writing: %1 Gagal membuka fail snapshot untuk menulis: %1 @@ -3476,47 +3481,47 @@ Download size: %3 QGBA::LogController - + [%1] %2: %3 [%1] %2: %3 - + An error occurred Ralat dilakukan - + DEBUG NYAHPEPIJAT - + STUB KONTOT - + INFO MAKLUMAT - + WARN AMARAN - + ERROR RALAT - + FATAL - + GAME ERROR RALAT PERMAINAN @@ -3640,42 +3645,42 @@ Download size: %3 Muat - + All Semua - + Load TBL Muat TBL - + Save selected memory Simpan ingatan terpilih - + Failed to open output file: %1 Gagal membuka fail output: %1 - + Load memory Muat ingatan - + Failed to open input file: %1 Gagal membuka fail input: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3926,104 +3931,130 @@ Download size: %3 Tidak boleh menukar simpanan permainan antara platform + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia Multimedia Qt - + SDL SDL - + Software (Qt) Perisian (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (paksa versi 1.x) - + None Tiada - + None (Still Image) Tiada (Gambar Tenang) - + Keyboard Papan Kekunci - + Controllers Pengawal - + Shortcuts Pintas - - + + Shaders - + Select BIOS Pilih BIOS - + Select directory Pilih direktori - + (%1×%2) (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago - + %n day(s) ago @@ -4121,100 +4152,100 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) ROM Game Boy Advance (%1) - + Game Boy ROMs (%1) ROM Game Boy (%1) - + All ROMs (%1) Semua ROM (%1) - + %1 Video Logs (*.mvl) %1 Log Video (*.mvl) - + Archives (%1) Arkib (%1) - - + + Select ROM Pilih ROM - + Select folder Pilih folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image Pilih gambar - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Fail gambar (*.png *.gif *.jpg *.jpeg);;Semua fail (*) - + GameShark saves (*.sps *.xps) Simpanan GameShark (*.sps *.xps) - + Select video log Pilih log video - + Video logs (*.mvl) Log video (*.mvl) - + Crash Nahas - + The game has crashed with the following error: %1 @@ -4223,674 +4254,679 @@ Download size: %3 %1 - + Couldn't Start Tidak dapat memula - + Could not start game. Permainan tidak dapat bermula. - + Unimplemented BIOS call Panggilan BIOS yg belum dilaksanakan - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Permainan ini menggunakan panggilan BIOS yang belum dilaksanakan. Sila pakai BIOS rasmi untuk pengalaman yang lebih baik. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Gagal mencipta peranti paparan yang sesuai, berbalik ke paparan perisian. Permainan mungkin menjadi lembap, terutamanya dengan tetingkap besar. - + Really make portable? Betulkah mahu buat jadi mudah alih? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Ini akan menetapkan pelagak untuk muat konfigurasi dari direktori yang sama dengan fail bolehlakunya. Teruskan? - + Restart needed Mula semula diperlukan - + Some changes will not take effect until the emulator is restarted. Beberapa perubahan tidak akan dilaksanakan sehingga pelagak dimula semula. - + - Player %1 of %2 - Pemain %1 dari %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &File - + Load &ROM... Muat %ROM... - + Load ROM in archive... Muat ROM daripada arkib... - + Add folder to library... Tambah folder ke perpustakaan... - + Save games (%1) Simpanan permainan (%1) - + Select save game Pilih simpanan permainan - + mGBA save state files (%1) mGBA fail keadaan tersimpan (%1) - - + + Select save state Pilih keadaan tersimpan - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) Fail gambar (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... Muat simpanan permainan alternatif... - + Load temporary save game... Muat simpanan permainan sementara... - + Load &patch... - + Boot BIOS But BIOS - + Replace ROM... Ganti ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... &Perihal ROM... - + Recent Terkini - + Make portable Buat jadi mudah alih - + &Load state &Muat keadaan - + Load state file... Muat fail keadaan... - + &Save state &Simpan keadaan - + Save state file... Simpan fail keadaan... - + Quick load - + Quick save - + Load recent Muat terkini - + Save recent Simpan terkini - + Undo load state Buat asal keadaan termuat - + Undo save state Buat asal keadaan tersimpan - - + + State &%1 Keadaan &%1 - + Load camera image... Muat gambar kamera... - + Convert save game... Tukar simpanan permainan... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games Simpanan permainan - + Import GameShark Save... Import Simpanan GameShark... - + Export GameShark Save... Eksport Simpanan GameShark... - + Automatically determine - + Use player %0 save game - + New multiplayer window Tetingkap multipemain baru - + Connect to Dolphin... Sambung ke Dolphin... - + Report bug... Laporkan pepijat... - + About... Perihal... - + E&xit &Keluar - + &Emulation Pe&lagak - + &Reset - + Sh&utdown &Matikan - + Yank game pak Alih keluar Game Pak - + &Pause &Jeda - + &Next frame Bingkai se&terusnya - + Fast forward (held) Mundar laju (pegang) - + &Fast forward Mundar &laju - + Fast forward speed Kelajuan mundar laju - + Unbounded Tidak terbatas - + %0x %0x - + Rewind (held) Putar balik (pegang) - + Re&wind Ma&ndir - + Step backwards Langkah belakang - + Solar sensor Pengesan suria - + Increase solar level Meningkatkan aras suria - + Decrease solar level Mengurangkan aras suria - + Brightest solar level Aras suria paling terang - + Darkest solar level Aras suria paling gelap - + Brightness %1 Kecerahan %1 - + Game Boy Printer... Pencetak Game Boy... - + BattleChip Gate... BattleChip Gate... - + Audio/&Video Audio/&Video - + Frame size Saiz bingkai - + %1× %1× - + Toggle fullscreen Togol skrinpenuh - + Lock aspect ratio Kekalkan nisbah aspek - + Force integer scaling Paksa skala integer - + Interframe blending Persebatian antarabingkai - + Bilinear filtering Penapisan bilinear - + Frame&skip Langkauan &bingkai - + Mute Senyap - + FPS target Sasaran FPS - + Native (59.7275) Asal (59.7275) - + Take &screenshot Ambil &cekupan skrin - + F12 F12 - + Record A/V... Rakam A/V... - + Record GIF/WebP/APNG... Rakam GIF/WebP/APNG... - + Video layers Lapisan video - + Audio channels Saluran audio - + Adjust layer placement... Melaras peletakan lapisan... - + &Tools &Alat - + View &logs... Lihat &log... - + Game &overrides... - + Game Pak sensors... Pengesan Game Pak... - + &Cheats... &Tipu... - + Settings... Tetapan... - + Open debugger console... Buka konsol penyahpepijat... - + Start &GDB server... Mula pelayan &GDB... - + + Scripting... + + + + View &palette... Pelihat &palet... - + View &sprites... - + View &tiles... Pelihat &jubin... - + View &map... Pelihat pe&ta... - + &Frame inspector... Periksa &bingkai... - + View memory... Lihat ingatan... - + Search memory... Cari ingatan... - + View &I/O registers... Lihat daftar &I/O... - + Record debug video log... Rakam log video nyahpepijat... - + Stop debug video log Henti log video nyahpepijat - + Exit fullscreen Keluar skrinpenuh - + GameShark Button (held) Butang GameShark (pegang) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear Kosongkan @@ -5136,6 +5172,44 @@ Download size: %3 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + + + + + 0 + 4K {0?} + + SensorView diff --git a/src/platform/qt/ts/mgba-nb_NO.ts b/src/platform/qt/ts/mgba-nb_NO.ts index 0c002ff5c..a3ed6842b 100644 --- a/src/platform/qt/ts/mgba-nb_NO.ts +++ b/src/platform/qt/ts/mgba-nb_NO.ts @@ -1267,17 +1267,22 @@ Download size: %3 QGBA::CheatsView - - + + Autodetect (recommended) - - + + Select cheats file Velg juksekodefil + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1287,43 +1292,43 @@ Download size: %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 - + Failed to open game file: %1 Klarte ikke å åpne spillfil: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -3477,47 +3482,47 @@ Download size: %3 QGBA::LogController - + [%1] %2: %3 - + An error occurred En feil inntraff - + DEBUG AVLUSING - + STUB - + INFO INFO - + WARN - + ERROR FEIL - + FATAL KRITISK - + GAME ERROR SPILLFEIL @@ -3641,42 +3646,42 @@ Download size: %3 Last inn - + All - + Load TBL - + Save selected memory Lagre valgt minne - + Failed to open output file: %1 Klarte ikke å åpne utdatafil: %1 - + Load memory Last inn minne - + Failed to open input file: %1 Klarte ikke å åpne inndatafil: %1 - + TBL - + ISO-8859-1 @@ -3927,97 +3932,123 @@ Download size: %3 + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia - + SDL SDL - + Software (Qt) Programvare (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) - + None Ingen - + None (Still Image) - + Keyboard Tastatur - + Controllers Kontrollere - + Shortcuts Snarveier - - + + Shaders Skyggeleggere - + Select BIOS Velg BIOS - + Select directory Velg mappe - + (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago @@ -4025,7 +4056,7 @@ Download size: %3 - + %n day(s) ago @@ -4124,774 +4155,779 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) Arkiv (%1) - - + + Select ROM Velg ROM - + Select folder Velg mappe - - + + Select save - + Select patch Velg feilfiks - + Patches (*.ips *.ups *.bps) Feilfikser (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image Velg bilde - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Bildefil (*.png *.gif *.jpg *.jpeg);;All filer (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash Krasj - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) - - + + Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + + Scripting... + + + + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear Tøm @@ -5137,6 +5173,44 @@ Download size: %3 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + + + + + 0 + 0 + + SensorView diff --git a/src/platform/qt/ts/mgba-nl.ts b/src/platform/qt/ts/mgba-nl.ts index 8fa74e37d..3b8435267 100644 --- a/src/platform/qt/ts/mgba-nl.ts +++ b/src/platform/qt/ts/mgba-nl.ts @@ -1266,17 +1266,22 @@ Download size: %3 QGBA::CheatsView - - + + Autodetect (recommended) - - + + Select cheats file + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1286,43 +1291,43 @@ Download size: %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 - + Failed to open game file: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -3476,47 +3481,47 @@ Download size: %3 QGBA::LogController - + [%1] %2: %3 - + An error occurred - + DEBUG - + STUB - + INFO - + WARN - + ERROR - + FATAL - + GAME ERROR @@ -3640,42 +3645,42 @@ Download size: %3 Laden - + All - + Load TBL - + Save selected memory - + Failed to open output file: %1 - + Load memory - + Failed to open input file: %1 - + TBL - + ISO-8859-1 @@ -3926,97 +3931,123 @@ Download size: %3 + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia - + SDL - + Software (Qt) - + OpenGL - + OpenGL (force version 1.x) - + None - + None (Still Image) - + Keyboard - + Controllers - + Shortcuts - - + + Shaders - + Select BIOS - + Select directory - + (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago @@ -4024,7 +4055,7 @@ Download size: %3 - + %n day(s) ago @@ -4123,774 +4154,779 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) - - + + Select ROM - + Select folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) - - + + Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + + Scripting... + + + + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear @@ -5136,6 +5172,44 @@ Download size: %3 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + + + + + 0 + 0 + + SensorView diff --git a/src/platform/qt/ts/mgba-pl.ts b/src/platform/qt/ts/mgba-pl.ts index 0446d7763..12ec17639 100644 --- a/src/platform/qt/ts/mgba-pl.ts +++ b/src/platform/qt/ts/mgba-pl.ts @@ -1272,17 +1272,22 @@ Rozmiar pobierania: %3 QGBA::CheatsView - - + + Autodetect (recommended) Automatyczne wykrywanie (zalecane) - - + + Select cheats file Wybierz plik z kodami + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1292,43 +1297,43 @@ Rozmiar pobierania: %3 Reset r%1-%2 %3 - - + + Rewinding not currently enabled Przewijanie nie jest obecnie włączone - + Reset the game? Zresetować grę? - + Most games will require a reset to load the new save. Do you want to reset now? Większość gier wymaga zresetowania, aby wczytać nowy zapis. Czy chcesz teraz zresetować? - + Failed to open save file: %1 Nie udało się otworzyć pliku zapisu: %1 - + Failed to open game file: %1 Nie udało się otworzyć pliku gry: %1 - + Can't yank pack in unexpected platform! Nie można wyciągnąć pack na nieoczekiwanej platformie! - + Failed to open snapshot file for reading: %1 Nie udało się otworzyć pliku snapshot do odczytu: %1 - + Failed to open snapshot file for writing: %1 Nie udało się otworzyć pliku snapshot do zapisu: %1 @@ -3482,47 +3487,47 @@ Rozmiar pobierania: %3 QGBA::LogController - + [%1] %2: %3 [%1] %2: %3 - + An error occurred Pojawił się błąd - + DEBUG DEBUG - + STUB ZALĄŻEK - + INFO INFO - + WARN OSTRZEC - + ERROR BŁĄD - + FATAL KRYTYCZNY - + GAME ERROR BŁĄD GRY @@ -3646,42 +3651,42 @@ Rozmiar pobierania: %3 Wgraj - + All Wszystko - + Load TBL Załaduj TBL - + Save selected memory Zapisz wybraną pamięć - + Failed to open output file: %1 Nie udało się otworzyć pliku wyjściowego: %1 - + Load memory Załaduj pamięć - + Failed to open input file: %1 Nie udało się otworzyć pliku wejściowego: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3932,97 +3937,123 @@ Rozmiar pobierania: %3 Nie można konwertować zapisanych gier między platformami + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (wymuś wersję 1.x) - + None Nic - + None (Still Image) Brak (Obraz Nieruchomy) - + Keyboard Klawiatura - + Controllers Kontrolery - + Shortcuts Skróty - - + + Shaders Shadery - + Select BIOS Wybierz BIOS - + Select directory Wybierz katalog - + (%1×%2) (%1×%2) - + Never Nigdy - + Just now Właśnie teraz - + Less than an hour ago Mniej niż godzinę temu - + %n hour(s) ago %n godzinę temu @@ -4031,7 +4062,7 @@ Rozmiar pobierania: %3 - + %n day(s) ago %n dzień temu @@ -4131,100 +4162,100 @@ Rozmiar pobierania: %3 QGBA::Window - + Game Boy Advance ROMs (%1) ROMy Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMy Game Boy (%1) - + All ROMs (%1) Wszystkie ROMy (%1) - + %1 Video Logs (*.mvl) Dzienniki wideo %1 (*.mvl) - + Archives (%1) Archiwa (%1) - - + + Select ROM Wybierz ROM - + Select folder Wybierz katalog - - + + Select save Wybierz zapis - + Select patch Wybierz łatkę - + Patches (*.ips *.ups *.bps) Łatki (*.ips *.ups *.bps) - + Select e-Reader dotcode Wybierz kod kropki e-Reader - + e-Reader card (*.raw *.bin *.bmp) Karta e-Reader (*.raw *.bin *.bmp) - + Select image Wybierz obraz - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Plik obrazu (*.png *.gif *.jpg *.jpeg);;Wszystkie pliki (*) - + GameShark saves (*.sps *.xps) Zapisy GameShark (*.sps *.xps) - + Select video log Wybierz dziennik wideo - + Video logs (*.mvl) Dzienniki wideo (*.mvl) - + Crash Crash - + The game has crashed with the following error: %1 @@ -4233,674 +4264,679 @@ Rozmiar pobierania: %3 %1 - + Couldn't Start Nie udało się uruchomić - + Could not start game. Nie udało się rozpocząć gry. - + Unimplemented BIOS call Niewdrożone wywołanie BIOS - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Ta gra używa wywołania BIOS, które nie jest zaimplementowane. Aby uzyskać najlepsze wrażenia, użyj oficjalnego BIOS. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Nie udało się utworzyć odpowiedniego urządzenia wyświetlającego, powracam do wyświetlania programowego. Gry mogą działać wolno, zwłaszcza w przypadku większych okien. - + Really make portable? Naprawdę stworzyć wersję portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? To sprawi, że emulator załaduje swoją konfigurację z tego samego katalogu, co plik wykonywalny. Czy chcesz kontynuować? - + Restart needed Wymagane ponowne uruchomienie - + Some changes will not take effect until the emulator is restarted. Niektóre zmiany nie zaczną obowiązywać, dopóki emulator nie zostanie ponownie uruchomiony. - + - Player %1 of %2 - Gracz %1 z %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 FPS) - %4 - + &File &Plik - + Load &ROM... Załaduj &ROM... - + Load ROM in archive... Załaduj ROM w archiwum... - + Add folder to library... Dodaj folder do biblioteki... - + Save games (%1) Zapisane gry (%1) - + Select save game Wybierz zapis gry - + mGBA save state files (%1) Pliki stanu gry mGBA (%1) - - + + Select save state Wybierz stan - + Select e-Reader card images Wybierz obrazy kart e-Reader - + Image file (*.png *.jpg *.jpeg) Plik graficzny (*.png *.jpg *.jpeg) - + Conversion finished Konwersja zakończona - + %1 of %2 e-Reader cards converted successfully. %1 z %2 kart czytnika e-Reader zostało pomyślnie przekonwertowanych. - + Load alternate save game... Załaduj alternatywny zapis gry... - + Load temporary save game... Załaduj tymczasowy zapis gry... - + Load &patch... Wczytaj &poprawkę... - + Boot BIOS BIOS startowy - + Replace ROM... Wymień ROM... - + Scan e-Reader dotcodes... Skanuj kody kropkowe czytnika e-Reader... - + Convert e-Reader card image to raw... Konwertuj obraz karty czytnika e-Reader na surowy... - + ROM &info... &Informacje o pamięci ROM... - + Recent Ostatnie - + Make portable Stwórz wersję portable - + &Load state &Załaduj stan - + Load state file... Załaduj plik stanu… - + &Save state &Zapisz stan - + Save state file... Zapisz plik stanu... - + Quick load Szybkie załadowanie - + Quick save Szybki zapis - + Load recent Załaduj ostatnie - + Save recent Zapisz ostatnie - + Undo load state Cofnij załadowanie stanu - + Undo save state Cofnij zapisanie stanu - - + + State &%1 Stan &%1 - + Load camera image... Załaduj obraz do kamery... - + Convert save game... Konwertuj zapisaną grę... - + GameShark saves (*.gsv *.sps *.xps) Zapisy GameShark (*.gsv *.sps *.xps) - + Reset needed Wymagane zresetowanie - + Some changes will not take effect until the game is reset. Niektóre zmiany nie zaczną obowiązywać, dopóki gra nie zostanie zresetowana. - + Save games Zapisy gry - + Import GameShark Save... Importuj Zapis GameShark... - + Export GameShark Save... Eksportuj Zapis GameShark... - + Automatically determine Wykryj automatycznie - + Use player %0 save game Użyj zapis gry gracza %0 - + New multiplayer window Nowe okno dla wielu graczy - + Connect to Dolphin... Połącz z Dolphinem... - + Report bug... Zgłoś błąd... - + About... O Aplikacji... - + E&xit Z&akończ - + &Emulation &Emulacja - + &Reset &Resetuj - + Sh&utdown Za&mknij - + Yank game pak Wyciągnij Game Pak - + &Pause &Pauza - + &Next frame &Następna klatka - + Fast forward (held) Przewijanie (przytrzymaj) - + &Fast forward &Przewijanie do przodu - + Fast forward speed Prędkość przewijania do przodu - + Unbounded Bez ograniczeń - + %0x %0x - + Rewind (held) Przewijanie (przytrzymaj) - + Re&wind Pr&zewijanie - + Step backwards Krok w tył - + Solar sensor Czujnik słoneczny - + Increase solar level Zwiększ poziom energii słonecznej - + Decrease solar level Zmniejsz poziom energii słonecznej - + Brightest solar level Najjaśniejszy poziom energii słonecznej - + Darkest solar level Najciemniejszy poziom energii słonecznej - + Brightness %1 Jasność %1 - + Game Boy Printer... Game Boy Printer... - + BattleChip Gate... BattleChip Gate... - + Audio/&Video Dźwięk/&Wideo - + Frame size Rozmiar klatki - + %1× %1× - + Toggle fullscreen Przełącz tryb pełnoekranowy - + Lock aspect ratio Zablokuj proporcje - + Force integer scaling Wymuś skalowanie całkowite - + Interframe blending Blendowanie międzyklatkowe - + Bilinear filtering Filtrowanie dwuliniowe - + Frame&skip Klatko&wanie - + Mute Wycisz - + FPS target Cel KL./S - + Native (59.7275) Natywny (59.7275) - + Take &screenshot Wykonaj &zrzut ekranu - + F12 F12 - + Record A/V... Nagraj A/W... - + Record GIF/WebP/APNG... Nagraj GIF/WebP/APNG... - + Video layers Warstwy wideo - + Audio channels Kanały audio - + Adjust layer placement... Dostosuj położenie warstw... - + &Tools &Narzędzia - + View &logs... Wyświetl &logi... - + Game &overrides... Nadpisania &ustawień gry... - + Game Pak sensors... Czujniki Game Pak... - + &Cheats... &Kody... - + Settings... Ustawienia... - + Open debugger console... Otwórz konsolę debugera... - + Start &GDB server... Uruchom serwer &GDB... - + + Scripting... + + + + View &palette... Wyświetl &paletę... - + View &sprites... Wyświetl &sprite'y... - + View &tiles... Wyświetl &kafelki... - + View &map... Wyświetl &mapę... - + &Frame inspector... Inspektor &klatek... - + View memory... Wyświetl pamięć... - + Search memory... Przeszukaj pamięć... - + View &I/O registers... Wyświetl rejestry &we/wy... - + Record debug video log... Nagraj dziennik wideo debugowania... - + Stop debug video log Zatrzymaj dziennik wideo debugowania - + Exit fullscreen Wyłączyć tryb pełnoekranowy - + GameShark Button (held) Przycisk GameShark (przytrzymany) - + Autofire Turbo - + Autofire A Turbo A - + Autofire B Turbo B - + Autofire L Turbo L - + Autofire R Turbo R - + Autofire Start Turbo Start - + Autofire Select Turbo Select - + Autofire Up Turbo Góra - + Autofire Right Turbo Prawo - + Autofire Down Turbo Dół - + Autofire Left Turbo Lewo - + Clear Wyczyść @@ -5146,6 +5182,44 @@ Rozmiar pobierania: %3 %1 GameShark Advance SP %2 zapis gry + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + &Resetuj + + + + 0 + 0 + + SensorView diff --git a/src/platform/qt/ts/mgba-pt_BR.ts b/src/platform/qt/ts/mgba-pt_BR.ts index 4cbc7b7d0..2a53af1fd 100644 --- a/src/platform/qt/ts/mgba-pt_BR.ts +++ b/src/platform/qt/ts/mgba-pt_BR.ts @@ -1267,17 +1267,22 @@ Download size: %3 QGBA::CheatsView - - + + Autodetect (recommended) - - + + Select cheats file Selecionar arquivo de trapaças + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1287,43 +1292,43 @@ Download size: %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 Falhou em abrir o arquivo do save: %1 - + Failed to open game file: %1 Falhou em abrir o arquivo do jogo: %1 - + Can't yank pack in unexpected platform! Não pode arrancar o pacote numa plataforma inesperada! - + Failed to open snapshot file for reading: %1 Falhou em abrir o arquivo do snapshot pra leitura: %1 - + Failed to open snapshot file for writing: %1 Falhou em abrir o arquivo do snapshot pra gravação: %1 @@ -3477,47 +3482,47 @@ Download size: %3 QGBA::LogController - + [%1] %2: %3 [%1] %2: %3 - + An error occurred Um erro ocorreu - + DEBUG DEBUG - + STUB STUB - + INFO INFO - + WARN AVISAR - + ERROR ERRO - + FATAL FATAL - + GAME ERROR ERRO DO JOGO @@ -3641,42 +3646,42 @@ Download size: %3 Carregar - + All Todos - + Load TBL Carregar TBL - + Save selected memory Salvar memória selecionada - + Failed to open output file: %1 Falhou em abrir o arquivo de saída: %1 - + Load memory Carregar memória - + Failed to open input file: %1 Falhou em abrir o arquivo de entrada: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3927,97 +3932,123 @@ Download size: %3 Não pôde converter os saves do jogo entre as plataformas + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia Multimídia do Qt - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (forçar a versão 1.x) - + None Nenhum - + None (Still Image) Nenhum (Imagem Parada) - + Keyboard Teclado - + Controllers Controles - + Shortcuts Atalhos - - + + Shaders Shaders - + Select BIOS Selecionar BIOS - + Select directory Selecione o diretório - + (%1×%2) (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago @@ -4025,7 +4056,7 @@ Download size: %3 - + %n day(s) ago @@ -4124,100 +4155,100 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) ROMs do Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs do Game Boy (%1) - + All ROMs (%1) Todas as ROMs (%1) - + %1 Video Logs (*.mvl) %1 Registros do Vídeo (*.mvl) - + Archives (%1) Arquivos Compactados (%1) - - + + Select ROM Selecionar ROM - + Select folder Selecionar pasta - - + + Select save Selecionar save - + Select patch Selecionar patch - + Patches (*.ips *.ups *.bps) Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode Selecionar dotcode do e-Reader - + e-Reader card (*.raw *.bin *.bmp) Cartão do e-Reader (*.raw *.bin *.bmp) - + Select image Selecionar imagem - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Arquivo de imagem (*.png *.gif *.jpg *.jpeg);;Todos os arquivos (*) - + GameShark saves (*.sps *.xps) Saves do GameShark (*.sps *.xps) - + Select video log Selecionar registro do vídeo - + Video logs (*.mvl) Registros do vídeo (*.mvl) - + Crash Crash - + The game has crashed with the following error: %1 @@ -4226,674 +4257,679 @@ Download size: %3 %1 - + Unimplemented BIOS call Chamada da BIOS não implementada - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Este jogo usa uma chamada de BIOS que não está implementada. Por favor use a BIOS oficial pra uma melhor experiência. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Falhou em criar um dispositivo de exibição apropriado, voltando a exibição por software. Os jogos podem executar lentamente, especialmente com janelas maiores. - + Really make portable? Realmente tornar portátil? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Isto fará o emulador carregar sua configuração do mesmo diretório que o executável. Você quer continuar? - + Restart needed Reiniciar é necessário - + Some changes will not take effect until the emulator is restarted. Algumas mudanças não terão efeito até que o emulador seja reiniciado. - + - Player %1 of %2 - Jogador %1 de %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Arquivo - + Load &ROM... Carregar &ROM... - + Load ROM in archive... Carregar ROM no arquivo compactado... - + Add folder to library... Adicionar a pasta a biblioteca... - + Save games Saves dos jogos - + Automatically determine - + Use player %0 save game - + Load &patch... Carregar &patch... - + Boot BIOS Dar Boot na BIOS - + Replace ROM... Substituir ROM... - + ROM &info... Informações da &ROM... - + Recent Recentes - + Make portable Tornar portátil - + &Load state &Carregar state - + Report bug... Reportar bug... - + About... Sobre... - + Game Pak sensors... Sensores do Game Pak... - + Clear Limpar - + Load state file... Carregar arquivo do state... - + Save games (%1) Saves dos jogos (%1) - + Select save game Selecione save do jogo - + mGBA save state files (%1) Arquivos do save state do mGBA (%1) - - + + Select save state Selecione save state - + Select e-Reader card images Selecionar imagens do cartão do e-Reader - + Image file (*.png *.jpg *.jpeg) Arquivo da imagem (*.png *.jpg *.jpeg) - + Conversion finished Conversão concluída - + %1 of %2 e-Reader cards converted successfully. %1 de %2 cartões do e-Reader convertidos com sucesso. - + Load alternate save game... Carregar save alternativo do jogo... - + Load temporary save game... Carregar save temporário do jogo... - + Convert e-Reader card image to raw... Converter imagem do cartão do e-Reader pro natural... - + &Save state &Salvar o state - + Save state file... Arquivo do save state... - + Quick load Carregamento rápido - + Quick save Salvamento rápido - + Load recent Carregar recentes - + Save recent Salvar recentes - + Undo load state Desfazer o carregamento do state - + Undo save state Desfazer o salvamento do state - - + + State &%1 State &%1 - + Load camera image... Carregar imagem da câmera... - + Convert save game... Converter save do jogo... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + New multiplayer window Nova janela multi-jogador - + Connect to Dolphin... Conectar ao Dolphin... - + E&xit S&air - + &Emulation &Emulação - + &Reset &Resetar - + Sh&utdown De&sligar - + Yank game pak Arrancar game pak - + &Pause &Pausar - + &Next frame &Próximo frame - + Fast forward (held) Avanço rápido (segurado) - + &Fast forward &Avanço rápido - + Fast forward speed Velocidade do avanço rápido - + Unbounded Ilimitado - + %0x %0x - + Rewind (held) Retroceder (segurado) - + Re&wind Re&troceder - + Step backwards Voltar um passo - + Solar sensor Sensor solar - + Increase solar level Aumentar nível solar - + Decrease solar level Diminuir nível solar - + Brightest solar level Nível solar mais brilhante - + Darkest solar level Nível solar mais escuro - + Brightness %1 Brilho %1 - + Audio/&Video Áudio/&Vídeo - + Frame size Tamanho do frame - + Toggle fullscreen Alternar tela cheia - + Lock aspect ratio Trancar proporção do aspecto - + Force integer scaling Forçar dimensionamento da integral - + Bilinear filtering Filtragem bilinear - + Frame&skip Frame&skip - + Mute Mudo - + FPS target FPS alvo - + Native (59.7275) Nativo (59,7275) - + Take &screenshot Tirar &screenshot - + F12 F12 - + Game Boy Printer... Impressora do Game Boy... - + BattleChip Gate... Portal do BattleChip... - + %1× %1× - + Interframe blending Mistura do interframe - + Record A/V... Gravar A/V... - + Video layers Camadas do vídeo - + Audio channels Canais de áudio - + Adjust layer placement... Ajustar posicionamento da camada... - + &Tools &Ferramentas - + View &logs... Visualizar &registros... - + Game &overrides... Substituições &do jogo... - + Couldn't Start Não Pôde Iniciar - + Could not start game. Não pôde iniciar o jogo. - + Scan e-Reader dotcodes... Escanear dotcodes do e-Reader... - + Import GameShark Save... Importar Save do GameShark... - + Export GameShark Save... Exportar Save do GameShark... - + Record GIF/WebP/APNG... Gravar GIF/WebP/APNG... - + &Cheats... &Trapaças... - + Settings... Configurações... - + Open debugger console... Abrir console do debugger... - + Start &GDB server... Iniciar servidor do &GDB... - + + Scripting... + + + + View &palette... Visualizar &paleta... - + View &sprites... Visualizar &imagens móveis... - + View &tiles... Visualizar &ladrilhos... - + View &map... Visualizar &mapa... - + &Frame inspector... Inspetor dos &frames... - + View memory... Visualizar memória... - + Search memory... Procurar memória... - + View &I/O registers... Visualizar registros de &E/S... - + Record debug video log... Gravar registro do vídeo de debug... - + Stop debug video log Parar log do vídeo de debug - + Exit fullscreen Sair da tela cheia - + GameShark Button (held) Botão do GameShark (segurado) - + Autofire Auto-disparar - + Autofire A Auto-disparar A - + Autofire B Auto-disparar B - + Autofire L Auto-disparar L - + Autofire R Auto-disparar R - + Autofire Start Auto-disparar Start - + Autofire Select Auto-disparar Select - + Autofire Up Auto-disparar Pra Cima - + Autofire Right Auto-disparar Direita - + Autofire Down Auto-disparar Pra Baixo - + Autofire Left Auto-disparar Esquerda @@ -5139,6 +5175,44 @@ Download size: %3 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + &Resetar + + + + 0 + 0 + + SensorView diff --git a/src/platform/qt/ts/mgba-ru.ts b/src/platform/qt/ts/mgba-ru.ts index 062f89450..c68456baa 100644 --- a/src/platform/qt/ts/mgba-ru.ts +++ b/src/platform/qt/ts/mgba-ru.ts @@ -1271,17 +1271,22 @@ Download size: %3 QGBA::CheatsView - - + + Autodetect (recommended) Автоопределение (рекомендовано) - - + + Select cheats file Выберите файл с чит-кодами + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1291,43 +1296,43 @@ Download size: %3 Сброс r%1-%2 %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 Не удалось открыть файл сохранения: %1 - + Failed to open game file: %1 Не удалось открыть файл игры: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 Не удалось открыть файл изображения для считывания: %1 - + Failed to open snapshot file for writing: %1 Не удалось открыть файл изображения для записи: %1 @@ -3481,47 +3486,47 @@ Download size: %3 QGBA::LogController - + [%1] %2: %3 [%1] %2: %3 - + An error occurred Произошла ошибка - + DEBUG - + STUB - + INFO ИНФОРМАЦИЯ - + WARN - + ERROR - + FATAL - + GAME ERROR @@ -3645,42 +3650,42 @@ Download size: %3 Загрузить - + All Все - + Load TBL Загрузить TBL - + Save selected memory Сохранение выделенной памяти - + Failed to open output file: %1 Не удалось открыть выходной файл: %1 - + Load memory Загрузка памяти - + Failed to open input file: %1 Не удалось загрузить входной файл: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3931,97 +3936,123 @@ Download size: %3 Нельзя сконвертировать сохранения для разных платформ + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia - + SDL - + Software (Qt) - + OpenGL - + OpenGL (force version 1.x) - + None Нет - + None (Still Image) Нет (статичное изображение) - + Keyboard Клавиатура - + Controllers Контроллеры - + Shortcuts Сочетания клавиш - - + + Shaders Шейдеры - + Select BIOS Выбор BIOS - + Select directory Выбор папки - + (%1×%2) - + Never Никогда - + Just now Только сейчас - + Less than an hour ago Менее часа назад - + %n hour(s) ago %n час назад @@ -4030,7 +4061,7 @@ Download size: %3 - + %n day(s) ago %n день назад @@ -4130,100 +4161,100 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) Игры Game Boy Advance (%1) - + Game Boy ROMs (%1) Игры Game Boy (%1) - + All ROMs (%1) Все игры (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) Архивы (%1) - - + + Select ROM Выбор игры - + Select folder Выбор папки - - + + Select save Выбор сохранения - + Select patch Выбор патча - + Patches (*.ips *.ups *.bps) Патчи (*.ips *.ups *.bps) - + Select e-Reader dotcode Выбор карточки e-Reader - + e-Reader card (*.raw *.bin *.bmp) Карточка e-Reader (*.raw *.bin *.bmp) - + Select image Выбор изображения - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Файл изображения (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) Сохранения GameShark (*.sps *.xps) - + Select video log Выбор видеолога - + Video logs (*.mvl) Видеологи (*.mvl) - + Crash Сбой - + The game has crashed with the following error: %1 @@ -4232,674 +4263,679 @@ Download size: %3 %1 - + Couldn't Start Запуск не удался - + Could not start game. Не удалось запустить игру. - + Unimplemented BIOS call Неизвестный вызов BIOS - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Игра использует нереализованный вызов BIOS. Пожалуйста, воспользуйтесь официальным BIOS для лучшей совместимости. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Не удалось создать устройство отображения, возврат к программному режиму. Игры могут идти медленнее, особенно в окнах больших размеров. - + Really make portable? Перейти в портативный режим? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? После этого эмулятор будет загружать конфигурацию из папки с исполняемым файлом. Продолжить? - + Restart needed Требуется перезапуск - + Some changes will not take effect until the emulator is restarted. Для применения некоторых изменений требуется перезапустить эмулятор. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File &Файл - + Load &ROM... - + Load ROM in archive... Загрузить игру из архива... - + Add folder to library... Добавить папку в библиотеку... - + Save games (%1) Игровые сохранения (%1) - + Select save game Выбор игрового сохранения - + mGBA save state files (%1) Файл сохранения состояния mGBA (%1) - - + + Select save state Выбор сохранения состояния - + Select e-Reader card images Выбор изображения карточки e-Reader - + Image file (*.png *.jpg *.jpeg) Файл изображения (*.png *.jpg *.jpeg) - + Conversion finished Конвертация завершена - + %1 of %2 e-Reader cards converted successfully. %1 из %2 карточек e-Reader успешно сконвертировано. - + Load alternate save game... Загрузить альтернативное сохранение... - + Load temporary save game... Загрузить временное сохранение... - + Load &patch... Загрузить &патч... - + Boot BIOS Загрузиться в BIOS - + Replace ROM... Заменить ROM... - + Scan e-Reader dotcodes... Сканировать dot-коды e-Reader... - + Convert e-Reader card image to raw... Конвертировать карту e-Reader в raw... - + ROM &info... Информация об &игре... - + Recent Недавние - + Make portable Портативный режим - + &Load state &Загрузить состояние - + Load state file... Загрузить состояние из файла... - + &Save state &Сохранить состояние - + Save state file... Сохранить состояние в файл... - + Quick load Быстрая загрузка - + Quick save Быстрое сохранение - + Load recent Загрузить недавнее - + Save recent Сохранить в недавнее - + Undo load state Отмена загрузки состояния - + Undo save state Отмена сохранения состояния - - + + State &%1 Слот &%1 - + Load camera image... Загрузить изображение с камеры... - + Convert save game... Конвертировать игровое сохранение... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... Импорт сохранения GameShark... - + Export GameShark Save... Экспорт сохранения GameShark... - + Automatically determine - + Use player %0 save game - + New multiplayer window Новое окно мультиплеера - + Connect to Dolphin... Соединение с Dolphin... - + Report bug... Сообщить об ошибке... - + About... О программе... - + E&xit &Выход - + &Emulation &Эмуляция - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x %0x - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + + Scripting... + + + + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear Очистить @@ -5145,6 +5181,44 @@ Download size: %3 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + + + + + 0 + 0 + + SensorView diff --git a/src/platform/qt/ts/mgba-template.ts b/src/platform/qt/ts/mgba-template.ts index cf3eb35d5..087ded6db 100644 --- a/src/platform/qt/ts/mgba-template.ts +++ b/src/platform/qt/ts/mgba-template.ts @@ -1266,17 +1266,22 @@ Download size: %3 QGBA::CheatsView - - + + Autodetect (recommended) - - + + Select cheats file + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1286,43 +1291,43 @@ Download size: %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 - + Failed to open game file: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -3476,47 +3481,47 @@ Download size: %3 QGBA::LogController - + [%1] %2: %3 - + An error occurred - + DEBUG - + STUB - + INFO - + WARN - + ERROR - + FATAL - + GAME ERROR @@ -3640,42 +3645,42 @@ Download size: %3 - + All - + Load TBL - + Save selected memory - + Failed to open output file: %1 - + Load memory - + Failed to open input file: %1 - + TBL - + ISO-8859-1 @@ -3926,104 +3931,130 @@ Download size: %3 + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia - + SDL - + Software (Qt) - + OpenGL - + OpenGL (force version 1.x) - + None - + None (Still Image) - + Keyboard - + Controllers - + Shortcuts - - + + Shaders - + Select BIOS - + Select directory - + (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago - + %n day(s) ago @@ -4121,774 +4152,779 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) - - + + Select ROM - + Select folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) - - + + Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + + Scripting... + + + + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear @@ -5134,6 +5170,44 @@ Download size: %3 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + + + + + 0 + + + SensorView diff --git a/src/platform/qt/ts/mgba-tr.ts b/src/platform/qt/ts/mgba-tr.ts index 040de662b..96e00763b 100644 --- a/src/platform/qt/ts/mgba-tr.ts +++ b/src/platform/qt/ts/mgba-tr.ts @@ -1267,17 +1267,22 @@ Download size: %3 QGBA::CheatsView - - + + Autodetect (recommended) - - + + Select cheats file Oyun hileleri seçin + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1287,43 +1292,43 @@ Download size: %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 Kayıt dosyası açılamadı: %1 - + Failed to open game file: %1 Oyun dosyası açılamadı: %1 - + Can't yank pack in unexpected platform! Beklenmedik bir platformda kartı çıkaramazsın! - + Failed to open snapshot file for reading: %1 Anlık görüntü dosyası okuma için açılamadı: %1 - + Failed to open snapshot file for writing: %1 Anlık görüntü dosyası yazma için açılamadı: %1 @@ -3477,47 +3482,47 @@ Download size: %3 QGBA::LogController - + [%1] %2: %3 - + An error occurred Bir hata meydana geldi - + DEBUG HATA AYIKLAMA - + STUB - + INFO BİLGİ - + WARN UYARI - + ERROR HATA - + FATAL CİDDİ - + GAME ERROR OYUN HATASI @@ -3641,42 +3646,42 @@ Download size: %3 Yükle - + All Hepsi - + Load TBL TBL yükle - + Save selected memory Seçilen hafızayı kaydet - + Failed to open output file: %1 Çıkış dosyası açılamadı:%1 - + Load memory Hafıza yükle - + Failed to open input file: %1 Giriş dosyası açılamadı:%1 - + TBL - + ISO-8859-1 @@ -3927,104 +3932,130 @@ Download size: %3 Kayıtlı oyunlar platformlar arasında dönüştürülemez + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia - + SDL - + Software (Qt) Yazılım - + OpenGL - + OpenGL (force version 1.x) - + None Hiçbiri - + None (Still Image) - + Keyboard Klavye - + Controllers - + Shortcuts Kısayollar - - + + Shaders Gölgelendiricler - + Select BIOS BIOS seç - + Select directory Yolu seç - + (%1×%2) (%1×%2) - + Never - + Just now - + Less than an hour ago - + %n hour(s) ago - + %n day(s) ago @@ -4122,120 +4153,120 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) Game Boy Advance ROMları (%1) - + Game Boy ROMs (%1) Game Boy ROMları (%1) - + All ROMs (%1) Bütün ROMlar (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) Arşivler (%1) - - + + Select ROM ROM seç - + Select folder Klasör seç - - + + Select save Kayıt seç - + Select patch Yama seç - + Patches (*.ips *.ups *.bps) Yamalar (*.ips *.ups *.bps) - + Select e-Reader dotcode e-Okuyucu nokta kodunu seç - + e-Reader card (*.raw *.bin *.bmp) e-Okuyucu kart (*.raw *.bin *.bmp) - + Select e-Reader card images e-Okuyucu kartından görüntüleri seç - + Image file (*.png *.jpg *.jpeg) Görüntü dosyası (*.png *.jpg *.jpeg) - + Conversion finished Dönüştürme tamamlandı - + %1 of %2 e-Reader cards converted successfully. %1 / %2 e-Okuyucu kartları dönüştürme tamamlandı. - + Select image Resim seç - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Resim dosyası (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) GameShark kayıtları (*.sps *.xps) - + Select video log Video günlüğü seç - + Video logs (*.mvl) Video günlükleri (*.mvl) - + Crash Çökme - + The game has crashed with the following error: %1 @@ -4244,654 +4275,659 @@ Download size: %3 %1 - + Unimplemented BIOS call Uygulanmamış BIOS girişi - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Oyun BIOS dosyasına ihtiyacı var. Lütfen en iyi deneyim için resmi BIOS'u kullanın. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Uygun görüntü cihazı oluşturma başarısız, yazılım ekranına dönülüyor. Oyunlar özellikle daha büyük ekranlarda yavaş çalışabilir. - + Really make portable? Taşınabilir yapılsın mı? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Emülatörün yapılandırmasını yürütülebilir dosya ile aynı dizinden yüklemesini sağlar. Devam etmek istiyor musun? - + Restart needed Yeniden başlatma gerekli - + Some changes will not take effect until the emulator is restarted. Bazı değişiklikler emülatör yeniden başlatılıncaya kadar etkili olmaz. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... &ROM yükle... - + Load ROM in archive... ROM'u arşivden yükle ... - + Add folder to library... Kütüphaneye klasör ekle ... - + Save games Oyunları kaydet - + Automatically determine - + Use player %0 save game - + Load &patch... &Patch yükle... - + Boot BIOS BIOS boot et - + Replace ROM... ROM değişti... - + Convert e-Reader card image to raw... e-Okuyucu kart resimlerini rawa dönüştür... - + ROM &info... ROM &info... - + Recent Son kullanılanlar - + Make portable Portatif yap - + &Load state &Kaydedilmiş konum yükle - + Load state file... Kaydedilmiş konum dosyası yükle... - + &Save state &Konumu kaydet - + Save state file... Konum dosyasını kaydet... - + Quick load Hızlı Yükle - + Quick save Hızlı kaydet - + Load recent En son yükle - + Save recent Hızlı kaydet - + Undo load state Kaydedilen konum yüklemeyi geri al - + Undo save state Konum kaydetmeyi geri al - - + + State &%1 Konum &%1 - + Load camera image... Kamera resmini yükle ... - + Convert save game... Kayıtlı oyun dömnüştürülüyor... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + New multiplayer window Yeni çokoyunculu ekranı - + Connect to Dolphin... Dolphin'e Bağlan... - + Report bug... Hata rapor et... - + About... Hakkında... - + E&xit Çıkış - + &Emulation Emülasyon - + &Reset &Reset - + Sh&utdown Kapat - + Yank game pak - + &Pause &Durdur - + &Next frame &Sonraki kare - + Fast forward (held) İleriye sar(basılı tutun) - + &Fast forward &İleriye sar - + Fast forward speed İleriye sarma hızı - + Unbounded - + %0x - + Rewind (held) Geri sar (basılı tutun) - + Re&wind Geri sar - + Step backwards Geriye doğru adım - + Solar sensor - + Increase solar level Solar seviyesini arttır - + Decrease solar level Solar seviyesini düşür - + Brightest solar level En parlak solar seviyesi - + Darkest solar level En karanlık solar seviyesi - + Brightness %1 Parlaklık:%1 - + Game Boy Printer... Game Boy yazıcısı... - + BattleChip Gate... - + Audio/&Video Ses/&Video - + Frame size Çerçeve boyutu - + Toggle fullscreen Tamekranı aç/kapa - + Lock aspect ratio En boy oranını kilitle - + Force integer scaling Tamsayılı ölçeklendirmeyi zorla - + Bilinear filtering Bilinear filtreleme - + Frame&skip Kare atlama - + Mute Sessiz - + FPS target FPS hedefi - + Native (59.7275) - + Take &screenshot Ekran görüntüsü al - + F12 - + Video layers - + Audio channels Ses kanalları - + Adjust layer placement... Katman yerleşimini ayarlayın... - + &Tools &Araçlar - + View &logs... Kayıtları görüntüle... - + Game &overrides... & Oyunun üzerine yazılanlar... - + Couldn't Start Başlatılamadı - + Save games (%1) Kayıtlı oyunlar (%1) - + Select save game Kayıtlı oyun seç - + mGBA save state files (%1) mGBA kayıt durum dosyası (%1) - - + + Select save state Kayıt durumu seç - + Could not start game. Oyun başlatılamadı. - + Load alternate save game... Alternatif kayıtlı oyun yükle... - + Load temporary save game... Geçici kayıtlı oyunu yükle... - + Scan e-Reader dotcodes... e-Okuyucu noktakodları tara... - + Import GameShark Save... GameShark kaydını içeri aktar... - + Export GameShark Save... GameShark kaydını dışarı aktar... - + %1× %1× - + Interframe blending Kareler-arası Karıştırma - + Record A/V... A/V Kayıt... - + Record GIF/WebP/APNG... GIF/WebP/APNG Kayıt... - + Game Pak sensors... Oyun Kartuş sensörleri... - + &Cheats... &Hileler... - + Settings... Ayarlar... - + Open debugger console... Hata ayıklayıcı konsolunu aç ... - + Start &GDB server... &GDB sunucusunu başlat... - + + Scripting... + + + + View &palette... &Renk Paletini gör... - + View &sprites... &Spriteları gör... - + View &tiles... &Desenleri gör... - + View &map... &Haritayı gör - + &Frame inspector... &Kare denetçisi... - + View memory... Hafıza gör... - + Search memory... Hafızada ara... - + View &I/O registers... &I/O kayıtlarını görüntüle - + Record debug video log... Hata ayıklama video günlüğünü kaydet... - + Stop debug video log Hata ayıklama video günlüğünü durdur - + Exit fullscreen Tam ekrandan çık - + GameShark Button (held) GameShark Butonu (basılı tutun) - + Autofire Otomatik basma - + Autofire A Otomatik basma A - + Autofire B Otomatik basma B - + Autofire L Otomatik basma L - + Autofire R Otomatik basma R - + Autofire Start Otomatik basma Start - + Autofire Select Otomatik basma Select - + Autofire Up Otomatik basma Up - + Autofire Right Otomatik basma Right - + Autofire Down Otomatik basma Down - + Autofire Left Otomatik basma Sol - + Clear Temizle @@ -5137,6 +5173,44 @@ Download size: %3 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + &Reset + + + + 0 + 4K {0?} + + SensorView diff --git a/src/platform/qt/ts/mgba-zh_CN.ts b/src/platform/qt/ts/mgba-zh_CN.ts index 893ac7a0d..29bb76796 100644 --- a/src/platform/qt/ts/mgba-zh_CN.ts +++ b/src/platform/qt/ts/mgba-zh_CN.ts @@ -1272,17 +1272,22 @@ Download size: %3 QGBA::CheatsView - - + + Autodetect (recommended) 自动检测(推荐) - - + + Select cheats file 选择作弊码文件 + + + Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. + + QGBA::CoreController @@ -1292,43 +1297,43 @@ Download size: %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 打开存档失败: %1 - + Failed to open game file: %1 打开游戏文件失败: %1 - + Can't yank pack in unexpected platform! 无法在意外平台上抽出卡带! - + Failed to open snapshot file for reading: %1 读取快照文件失败: %1 - + Failed to open snapshot file for writing: %1 写入快照文件失败: %1 @@ -3482,47 +3487,47 @@ Download size: %3 QGBA::LogController - + [%1] %2: %3 [%1] %2: %3 - + An error occurred 发生错误 - + DEBUG DEBUG - + STUB STUB - + INFO INFO - + WARN WARN - + ERROR ERROR - + FATAL FATAL - + GAME ERROR GAME ERROR @@ -3646,42 +3651,42 @@ Download size: %3 载入 - + All 全部 - + Load TBL 载入 TBL - + Save selected memory 保存所选内存 - + Failed to open output file: %1 打开输出文件失败: %1 - + Load memory 载入内存 - + Failed to open input file: %1 打开输入文件失败: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3932,104 +3937,130 @@ Download size: %3 无法在平台之间转换保存游戏 + + QGBA::ScriptingTextBuffer + + + Untitled buffer + + + + + QGBA::ScriptingView + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + + QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) 软件渲染 (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (强制版本 1.x) - + None - + None (Still Image) 无 (静止图像) - + Keyboard 键盘 - + Controllers 控制器 - + Shortcuts 快捷键 - - + + Shaders 着色器 - + Select BIOS 选择 BIOS - + Select directory 选择目录 - + (%1×%2) (%1×%2) - + Never 从不 - + Just now 刚刚 - + Less than an hour ago 不到一小时前 - + %n hour(s) ago %n 小时前 - + %n day(s) ago %n 天前 @@ -4127,100 +4158,100 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) Game Boy Advance ROM (%1) - + Game Boy ROMs (%1) Game Boy ROM (%1) - + All ROMs (%1) 所有 ROM (%1) - + %1 Video Logs (*.mvl) %1 视频日志 (*.mvl) - + Archives (%1) 压缩文件 (%1) - - + + Select ROM 选择 ROM - + Select folder 选择文件夹 - - + + Select save 选择存档 - + Select patch 选择补丁 - + Patches (*.ips *.ups *.bps) 补丁 (*.ips *.ups *.bps) - + Select e-Reader dotcode 选择 e-Reader 点码 - + e-Reader card (*.raw *.bin *.bmp) e-Reader 卡 (*.raw *.bin *.bmp) - + Select image 选择图片 - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) 图像文件 (*.png *.gif *.jpg *.jpeg);;所有文件 (*) - + GameShark saves (*.sps *.xps) GameShark 存档 (*.sps *.xps) - + Select video log 选择视频日志 - + Video logs (*.mvl) 视频日志文件 (*.mvl) - + Crash 崩溃 - + The game has crashed with the following error: %1 @@ -4229,674 +4260,679 @@ Download size: %3 %1 - + Couldn't Start 无法启动 - + Could not start game. 无法启动游戏。 - + Unimplemented BIOS call 未实现的 BIOS 调用 - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. 此游戏使用尚未实现的 BIOS 调用。请使用官方 BIOS 以获得最佳体验。 - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. 无法创建适合的显示设备,正在回滚到软件显示。游戏的运行速度(特别在大窗口的情况下)可能会变慢。 - + Really make portable? 确定进行程序便携化? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? 进行此操作后,模拟器将从其可执行文件所在目录中载入模拟器配置。您想继续吗? - + Restart needed 需要重新启动 - + Some changes will not take effect until the emulator is restarted. 更改将在模拟器下次重新启动时生效。 - + - Player %1 of %2 - 玩家 %1 共 %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2(%3 fps)- %4 - + &File 文件(&F) - + Load &ROM... 载入 ROM(&R)... - + Load ROM in archive... 从压缩文件中载入 ROM... - + Add folder to library... 将文件夹添加到库中... - + Save games (%1) 保存游戏(%1) - + Select save game 选择保存游戏 - + mGBA save state files (%1) mGBA 即时存档文件(%1) - - + + Select save state 选择即时存档 - + Select e-Reader card images 选择 e-Reader 卡片图像 - + Image file (*.png *.jpg *.jpeg) 图像文件(*.png *.jpg *.jpeg) - + Conversion finished 转换完成 - + %1 of %2 e-Reader cards converted successfully. 成功转换了 %1 张(共 %2 张)e-Reader 卡片。 - + Load alternate save game... 加载备用保存游戏... - + Load temporary save game... 加载临时保存游戏... - + Load &patch... 载入补丁(&P)... - + Boot BIOS 引导 BIOS - + Replace ROM... 替换 ROM... - + Scan e-Reader dotcodes... 扫描 e-Reader 点码... - + Convert e-Reader card image to raw... 将 e-Reader 卡片图像转换为原始数据... - + ROM &info... ROM 信息(&I)... - + Recent 最近打开 - + Make portable 程序便携化 - + &Load state 载入即时存档(&L) - + Load state file... 载入即时存档文件... - + &Save state 保存即时存档(&S) - + Save state file... 保存即时存档文件... - + Quick load 快速读档 - + Quick save 快速存档 - + Load recent 载入最近存档 - + Save recent 保存最近存档 - + Undo load state 撤消读档 - + Undo save state 撤消存档 - - + + State &%1 即时存档 (&%1) - + Load camera image... 载入相机图片... - + Convert save game... 转换保存游戏... - + GameShark saves (*.gsv *.sps *.xps) GameShark 存档 (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games 游戏存档 - + Import GameShark Save... 导入 GameShark 存档... - + Export GameShark Save... 导出 GameShark 存档... - + Automatically determine - + Use player %0 save game - + New multiplayer window 新建多人游戏窗口 - + Connect to Dolphin... 连接到 Dolphin... - + Report bug... 报告错误... - + About... 关于... - + E&xit 退出(&X) - + &Emulation 模拟(&E) - + &Reset 重置(&R) - + Sh&utdown 关机(&U) - + Yank game pak 快速抽出游戏卡带 - + &Pause 暂停(&P) - + &Next frame 下一帧(&N) - + Fast forward (held) 快进 (长按) - + &Fast forward 快进(&F) - + Fast forward speed 快进速度 - + Unbounded 不限制 - + %0x %0x - + Rewind (held) 倒带 (长按) - + Re&wind 倒带(&W) - + Step backwards 步退 - + Solar sensor 太阳光传感器 - + Increase solar level 增加太阳光等级 - + Decrease solar level 降低太阳光等级 - + Brightest solar level 太阳光等级为最亮 - + Darkest solar level 太阳光等级为最暗 - + Brightness %1 亮度 %1 - + Game Boy Printer... Game Boy 打印机... - + BattleChip Gate... BattleChip Gate... - + Audio/&Video 音频/视频(&V) - + Frame size 画面大小 - + %1× %1× - + Toggle fullscreen 切换全屏 - + Lock aspect ratio 锁定纵横比 - + Force integer scaling 强制整数缩放 - + Interframe blending 帧间混合 - + Bilinear filtering 双线性过滤 - + Frame&skip 跳帧(&S) - + Mute 静音 - + FPS target 目标 FPS - + Native (59.7275) 原生 (59.7275) - + Take &screenshot 截图(&S) - + F12 F12 - + Record A/V... 录制音频/视频... - + Record GIF/WebP/APNG... 录制 GIF/WebP/APNG... - + Video layers 视频图层 - + Audio channels 音频声道 - + Adjust layer placement... 调整图层布局... - + &Tools 工具(&T) - + View &logs... 查看日志(&L)... - + Game &overrides... 覆写游戏(&O)... - + Game Pak sensors... 游戏卡带传感器... - + &Cheats... 作弊码(&C)... - + Settings... 设置... - + Open debugger console... 打开调试器控制台... - + Start &GDB server... 打开 GDB 服务器(&G)... - + + Scripting... + + + + View &palette... 查看调色板(&P)... - + View &sprites... 查看精灵图(&S)... - + View &tiles... 查看图块(&T)... - + View &map... 查看映射(&M)... - + &Frame inspector... 框架检查器(&F)... - + View memory... 查看内存... - + Search memory... 搜索内存... - + View &I/O registers... 查看 I/O 寄存器(&I)... - + Record debug video log... 记录调试视频日志... - + Stop debug video log 停止记录调试视频日志 - + Exit fullscreen 退出全屏 - + GameShark Button (held) GameShark 键 (长按) - + Autofire 连发 - + Autofire A 连发 A - + Autofire B 连发 B - + Autofire L 连发 L - + Autofire R 连发 R - + Autofire Start 连发 Start - + Autofire Select 连发 Select - + Autofire Up 连发 上 - + Autofire Right 连发 右 - + Autofire Down 连发 下 - + Autofire Left 连发 左 - + Clear 清除 @@ -5142,6 +5178,44 @@ Download size: %3 %1 GameShark Advance SP %2 存档 + + ScriptingView + + + Scripting + + + + + Run + + + + + File + + + + + Load recent script + + + + + Load script... + + + + + &Reset + 重置(&R) + + + + 0 + 0 + + SensorView From 6b5ad35d5b11a3a77b07ca913519514550d19102 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 30 May 2022 18:51:43 -0700 Subject: [PATCH 003/102] Res: pokemon.lua cleanup --- res/scripts/pokemon.lua | 7 ------- 1 file changed, 7 deletions(-) diff --git a/res/scripts/pokemon.lua b/res/scripts/pokemon.lua index 09cd472ef..76a1fcdbe 100644 --- a/res/scripts/pokemon.lua +++ b/res/scripts/pokemon.lua @@ -68,22 +68,16 @@ local GBAGameEn = Game:new{ local Generation1En = GBGameEn:new{ _boxMonSize=33, _partyMonSize=44, - _readBoxMon=readBoxMonGen1, - _readPartyMon=readPartyMonGen1, } local Generation2En = GBGameEn:new{ _boxMonSize=32, _partyMonSize=48, - _readBoxMon=readBoxMonGen2, - _readPartyMon=readPartyMonGen2, } local Generation3En = GBAGameEn:new{ _boxMonSize=80, _partyMonSize=100, - _readBoxMon=readBoxMonGen3, - _readPartyMon=readPartyMonGen3, } GBGameEn._charmap = { [0]= @@ -475,7 +469,6 @@ gameCrc32 = { [0x9f7fdd53] = gameRBEn, -- Red [0xd6da8a1a] = gameRBEn, -- Blue [0x7d527d62] = gameYellowEn, - [0x3358e30a] = gameCrystal, -- Crystal rev 1 [0x84ee4776] = gameFireRedEnR1, [0xdaffecec] = gameLeafGreenEnR1, } From ccbb44e95a1525cef3aecbfa0b1eac452118f55e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 30 May 2022 21:45:48 -0700 Subject: [PATCH 004/102] Updater: Don't link against libmgba --- CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3afbaadc1..6181d63c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -952,8 +952,11 @@ if(BUILD_QT AND (WIN32 OR APPLE)) endif() if(BUILD_UPDATER) - add_executable(updater-stub WIN32 ${CMAKE_CURRENT_SOURCE_DIR}/src/feature/updater-main.c) - target_link_libraries(updater-stub ${OS_LIB} ${PLATFORM_LIBRARY} ${BINARY_NAME}) + add_executable(updater-stub WIN32 ${CORE_VFS_SRC} ${OS_SRC} ${UTIL_SRC} ${THIRD_PARTY_SRC} + ${CMAKE_CURRENT_SOURCE_DIR}/src/core/config.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/feature/updater.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/feature/updater-main.c) + target_link_libraries(updater-stub ${OS_LIB} ${PLATFORM_LIBRARY}) set_target_properties(updater-stub PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FUNCTION_DEFINES}") if(MSVC) set_target_properties(updater-stub PROPERTIES LINK_FLAGS /ENTRY:mainCRTStartup) From 61bc17953bf4de7e2ce551e48f11eb929be43d55 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 30 May 2022 20:38:44 -0700 Subject: [PATCH 005/102] Updater: Add support for appimage --- CMakeLists.txt | 2 +- src/feature/updater-main.c | 64 ++++++++++++++++++--- src/platform/qt/ApplicationUpdatePrompt.cpp | 18 ++++-- src/platform/qt/ApplicationUpdater.cpp | 2 + 4 files changed, 73 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6181d63c8..95e714e81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -947,7 +947,7 @@ if(BUILD_OPENEMU) install(TARGETS ${BINARY_NAME}-openemu LIBRARY DESTINATION ${OE_LIBDIR} COMPONENT ${BINARY_NAME}.oecoreplugin NAMELINK_SKIP) endif() -if(BUILD_QT AND (WIN32 OR APPLE)) +if(BUILD_QT AND (WIN32 OR APPLE OR CMAKE_SYSTEM_NAME STREQUAL "Linux")) set(BUILD_UPDATER ON) endif() diff --git a/src/feature/updater-main.c b/src/feature/updater-main.c index 4c7277203..4b1f216ff 100644 --- a/src/feature/updater-main.c +++ b/src/feature/updater-main.c @@ -173,25 +173,73 @@ int main(int argc, char* argv[]) { prefix = false; needsUnmount = true; #endif - } else { + } else if (strcmp(extension, "appimage") != 0) { archive = VDirOpenArchive(updateArchive); } - if (!archive) { - puts("Cannot open update archive"); - } else { + if (archive) { puts("Extracting update"); if (extractArchive(archive, root, prefix)) { - puts("Complete"); - const char* command = mUpdateGetCommand(&config); - strlcpy(bin, command, sizeof(bin)); ok = 0; - mUpdateDeregister(&config); } else { puts("An error occurred"); } archive->close(archive); unlink(updateArchive); } +#ifdef __linux__ + else if (strcmp(extension, "appimage") == 0) { + const char* command = mUpdateGetCommand(&config); + strlcpy(bin, command, sizeof(bin)); + if (rename(updateArchive, bin) < 0) { + if (errno == EXDEV) { + // Cross-dev, need to copy manually + int infd = open(updateArchive, O_RDONLY); + int outfd = -1; + if (infd >= 0) { + ok = 2; + } else { + outfd = open(bin, O_CREAT | O_WRONLY | O_TRUNC, 0755); + } + if (outfd < 0) { + ok = 2; + } else { + uint8_t buffer[2048]; + ssize_t size; + while ((size = read(infd, buffer, sizeof(buffer))) > 0) { + if (write(outfd, buffer, size) < size) { + ok = 2; + break; + } + } + if (size < 0) { + ok = 2; + } + close(outfd); + close(infd); + } + if (ok == 2) { + puts("Cannot move update over old file"); + } + } else { + puts("Cannot move update over old file"); + } + } else { + ok = 0; + } + if (ok == 0) { + chmod(bin, 0755); + } + } +#endif + else { + puts("Cannot open update archive"); + } + if (ok == 0) { + puts("Complete"); + const char* command = mUpdateGetCommand(&config); + strlcpy(bin, command, sizeof(bin)); + mUpdateDeregister(&config); + } #ifdef __APPLE__ if (needsUnmount) { char* args[] = {"hdiutil", "detach", devpath, NULL}; diff --git a/src/platform/qt/ApplicationUpdatePrompt.cpp b/src/platform/qt/ApplicationUpdatePrompt.cpp index 7f7b375c7..adadbee29 100644 --- a/src/platform/qt/ApplicationUpdatePrompt.cpp +++ b/src/platform/qt/ApplicationUpdatePrompt.cpp @@ -24,13 +24,23 @@ ApplicationUpdatePrompt::ApplicationUpdatePrompt(QWidget* parent) ApplicationUpdater* updater = GBAApp::app()->updater(); ApplicationUpdater::UpdateInfo info = updater->updateInfo(); QString updateText(tr("An update to %1 is available.\n").arg(QLatin1String(projectName))); + bool available; #if defined(Q_OS_WIN) || defined(Q_OS_MAC) - updateText += tr("\nDo you want to download and install it now? You will need to restart the emulator when the download is complete."); - m_okDownload = connect(m_ui.buttonBox, &QDialogButtonBox::accepted, this, &ApplicationUpdatePrompt::startUpdate); + available = true; +#elif defined(Q_OS_LINUX) + QString path = QCoreApplication::applicationDirPath(); + QFileInfo finfo(path + "/../../AppRun"); + available = finfo.exists() && finfo.isExecutable(); #else - updateText += tr("\nAuto-update is not available on this platform. If you wish to update you will need to do it manually."); - connect(m_ui.buttonBox, &QDialogButtonBox::accepted, this, &QWidget::close); + available = false; #endif + if (available) { + updateText += tr("\nDo you want to download and install it now? You will need to restart the emulator when the download is complete."); + m_okDownload = connect(m_ui.buttonBox, &QDialogButtonBox::accepted, this, &ApplicationUpdatePrompt::startUpdate); + } else { + updateText += tr("\nAuto-update is not available on this platform. If you wish to update you will need to do it manually."); + connect(m_ui.buttonBox, &QDialogButtonBox::accepted, this, &QWidget::close); + } m_ui.text->setText(updateText); m_ui.details->setText(tr("Current version: %1\nNew version: %2\nDownload size: %3") .arg(QLatin1String(projectVersion)) diff --git a/src/platform/qt/ApplicationUpdater.cpp b/src/platform/qt/ApplicationUpdater.cpp index 15334361e..c59413c26 100644 --- a/src/platform/qt/ApplicationUpdater.cpp +++ b/src/platform/qt/ApplicationUpdater.cpp @@ -151,6 +151,8 @@ const char* ApplicationUpdater::platform() { #endif #elif defined(Q_OS_MACOS) return "osx"; +#elif defined(Q_OS_LINUX) && defined(__x86_64__) + return "appimage-x64"; #else // Return one that will be up to date, but we can't download return "win64"; From 4f9cfd5a7e6dcc07c8e8c37d21aa869f9da7253a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 30 May 2022 22:02:47 -0700 Subject: [PATCH 006/102] Qt: Attempt to fix build order --- src/platform/qt/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index bf8948573..d6061be69 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -272,6 +272,9 @@ if(BUILD_UPDATER) qt5_add_resources(UPDATER_RESOURCES ${CMAKE_CURRENT_BINARY_DIR}/updater.qrc) endif() set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/updater.qrc PROPERTIES GENERATED ON) + if(BUILD_UPDATER) + set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/updater.qrc PROPERTIES OBJECT_DEPENDS updater-stub) + endif() list(APPEND RESOURCES ${UPDATER_RESOURCES}) endif() if(APPLE) From 14f217963ce427de163c8c188cb73ebe583aec57 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 30 May 2022 22:43:38 -0700 Subject: [PATCH 007/102] Qt: Attempt to fix build order again --- src/platform/qt/CMakeLists.txt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index d6061be69..3aac96cba 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -265,16 +265,20 @@ else() endif() if(BUILD_UPDATER) - file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/updater.qrc INPUT ${CMAKE_CURRENT_SOURCE_DIR}/updater.qrc.in) + if(DEFINED CMAKE_CONFIGURATION_TYPES) + # Required for e.g. MSVC + file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/updater.qrc INPUT ${CMAKE_CURRENT_SOURCE_DIR}/updater.qrc.in) + else() + # Required for qt_add_resources to manage dependencies properly + # TODO: Figure out how to do this with MSVC too + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/updater.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/updater.qrc) + endif() if(TARGET Qt6::Core) qt_add_resources(UPDATER_RESOURCES ${CMAKE_CURRENT_BINARY_DIR}/updater.qrc) else() qt5_add_resources(UPDATER_RESOURCES ${CMAKE_CURRENT_BINARY_DIR}/updater.qrc) endif() set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/updater.qrc PROPERTIES GENERATED ON) - if(BUILD_UPDATER) - set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/updater.qrc PROPERTIES OBJECT_DEPENDS updater-stub) - endif() list(APPEND RESOURCES ${UPDATER_RESOURCES}) endif() if(APPLE) From 39bb4043323c7b1412418227958469d092f37154 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 30 May 2022 22:50:53 -0700 Subject: [PATCH 008/102] Qt: Actually fix the build order this time, except with MSVC, but I'll take it --- src/platform/qt/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 3aac96cba..611f6136b 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -271,7 +271,7 @@ if(BUILD_UPDATER) else() # Required for qt_add_resources to manage dependencies properly # TODO: Figure out how to do this with MSVC too - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/updater.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/updater.qrc) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/updater-config.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/updater.qrc) endif() if(TARGET Qt6::Core) qt_add_resources(UPDATER_RESOURCES ${CMAKE_CURRENT_BINARY_DIR}/updater.qrc) From 5e6d063aa17ef23f7e8a8ab36772c3088615edee Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 30 May 2022 22:53:21 -0700 Subject: [PATCH 009/102] Qt: I'm so tired --- src/platform/qt/updater-config.qrc.in | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/platform/qt/updater-config.qrc.in diff --git a/src/platform/qt/updater-config.qrc.in b/src/platform/qt/updater-config.qrc.in new file mode 100644 index 000000000..edf2cd38e --- /dev/null +++ b/src/platform/qt/updater-config.qrc.in @@ -0,0 +1,5 @@ + + + ${PROJECT_BINARY_DIR}/updater-stub${CMAKE_EXECUTABLE_SUFFIX} + + From 68f628a211773fe478dc38b2689f848f9572d881 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 31 May 2022 20:40:14 -0700 Subject: [PATCH 010/102] GB Audio: Redo channels 1 and 2 --- include/mgba/internal/gb/audio.h | 6 +- include/mgba/internal/gb/serialize.h | 19 ++-- include/mgba/internal/gba/serialize.h | 15 +-- src/gb/audio.c | 145 +++++++++----------------- src/gb/io.c | 1 + src/gb/serialize.c | 2 +- src/gba/serialize.c | 2 +- 7 files changed, 76 insertions(+), 114 deletions(-) diff --git a/include/mgba/internal/gb/audio.h b/include/mgba/internal/gb/audio.h index 4f4fdef32..3e2d4c2f8 100644 --- a/include/mgba/internal/gb/audio.h +++ b/include/mgba/internal/gb/audio.h @@ -87,7 +87,6 @@ struct GBAudioSquareControl { int frequency; int length; bool stop; - int hi; }; struct GBAudioSweep { @@ -104,6 +103,8 @@ struct GBAudioSquareChannel { struct GBAudioSweep sweep; struct GBAudioEnvelope envelope; struct GBAudioSquareControl control; + int32_t lastUpdate; + uint8_t index; int8_t sample; }; @@ -194,8 +195,6 @@ struct GBAudio { enum GBAudioStyle style; struct mTimingEvent frameEvent; - struct mTimingEvent ch1Event; - struct mTimingEvent ch2Event; struct mTimingEvent ch3Event; struct mTimingEvent ch3Fade; struct mTimingEvent ch4Event; @@ -239,6 +238,7 @@ void GBAudioWriteNR50(struct GBAudio* audio, uint8_t); void GBAudioWriteNR51(struct GBAudio* audio, uint8_t); void GBAudioWriteNR52(struct GBAudio* audio, uint8_t); +void GBAudioRun(struct GBAudio* audio, int32_t timestamp); void GBAudioUpdateFrame(struct GBAudio* audio); void GBAudioUpdateChannel4(struct GBAudio* audio); diff --git a/include/mgba/internal/gb/serialize.h b/include/mgba/internal/gb/serialize.h index 6973d4e57..6043cc919 100644 --- a/include/mgba/internal/gb/serialize.h +++ b/include/mgba/internal/gb/serialize.h @@ -19,7 +19,7 @@ extern MGBA_EXPORT const uint32_t GBSavestateVersion; mLOG_DECLARE_CATEGORY(GB_STATE); /* Savestate format: - * 0x00000 - 0x00003: Version Magic (0x01000002) + * 0x00000 - 0x00003: Version Magic (0x00400003) * 0x00004 - 0x00007: ROM CRC32 * 0x00008: Game Boy model * 0x00009 - 0x0000B: Reserved (leave zero) @@ -56,20 +56,23 @@ mLOG_DECLARE_CATEGORY(GB_STATE); * | bits 0 - 6: Remaining length * | bits 7 - 9: Next step * | bits 10 - 20: Shadow frequency register - * | bits 21 - 31: Reserved + * | bits 21 - 23: Duty index + * | bits 24 - 31: Reserved * | 0x0004C - 0x0004F: Next frame * | 0x00050 - 0x00053: Next channel 3 fade * | 0x00054 - 0x00057: Sweep state * | bits 0 - 2: Timesteps * | bits 3 - 31: Reserved - * | 0x00058 - 0x0005B: Next event + * | 0x00058 - 0x0005B: Last update * 0x0005C - 0x0006B: Audio channel 2 state * | 0x0005C - 0x0005F: Envelepe timing * | bits 0 - 2: Remaining length * | bits 3 - 5: Next step - * | bits 6 - 31: Reserved + * | bits 6 - 20: Reserved + * | bits 21 - 23: Duty index + * | bits 24 - 31: Reserved * | 0x00060 - 0x00067: Reserved - * | 0x00068 - 0x0006B: Next event + * | 0x00068 - 0x0006B: Last update * 0x0006C - 0x00093: Audio channel 3 state * | 0x0006C - 0x0008B: Wave banks * | 0x0008C - 0x0008D: Remaining length @@ -208,7 +211,7 @@ DECL_BITFIELD(GBSerializedAudioEnvelope, uint32_t); DECL_BITS(GBSerializedAudioEnvelope, Length, 0, 7); DECL_BITS(GBSerializedAudioEnvelope, NextStep, 7, 3); DECL_BITS(GBSerializedAudioEnvelope, Frequency, 10, 11); - +DECL_BITS(GBSerializedAudioEnvelope, DutyIndex, 21, 3); DECL_BITFIELD(GBSerializedAudioSweep, uint32_t); DECL_BITS(GBSerializedAudioSweep, Time, 0, 3); @@ -219,12 +222,12 @@ struct GBSerializedPSGState { int32_t nextFrame; int32_t nextCh3Fade; GBSerializedAudioSweep sweep; - uint32_t nextEvent; + uint32_t lastUpdate; } ch1; struct { GBSerializedAudioEnvelope envelope; int32_t reserved[2]; - int32_t nextEvent; + uint32_t lastUpdate; } ch2; struct { uint32_t wavebanks[8]; diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index 203c4fb0c..b25b3aec0 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -20,7 +20,7 @@ extern MGBA_EXPORT const uint32_t GBASavestateVersion; mLOG_DECLARE_CATEGORY(GBA_STATE); /* Savestate format: - * 0x00000 - 0x00003: Version Magic (0x01000004) + * 0x00000 - 0x00003: Version Magic (0x01000005) * 0x00004 - 0x00007: BIOS checksum (e.g. 0xBAAE187F for official BIOS) * 0x00008 - 0x0000B: ROM CRC32 * 0x0000C - 0x0000F: Master cycles @@ -39,25 +39,28 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * | bits 0 - 6: Remaining length * | bits 7 - 9: Next step * | bits 10 - 20: Shadow frequency register - * | bits 21 - 31: Reserved + * | bits 21 - 23: Duty index + * | bits 24 - 31: Reserved * | 0x00134 - 0x00137: Next frame * | 0x00138 - 0x0013B: Next channel 3 fade * | 0x0013C - 0x0013F: Sweep state * | bits 0 - 2: Timesteps * | bits 3 - 7: Reserved - * | 0x00140 - 0x00143: Next event + * | 0x00140 - 0x00143: Last update * 0x00144 - 0x00153: Audio channel 2 state * | 0x00144 - 0x00147: Envelepe timing * | bits 0 - 2: Remaining length * | bits 3 - 5: Next step - * | bits 6 - 31: Reserved + * | bits 6 - 20: Reserved + * | bits 21 - 23: Duty index + * | bits 24 - 31: Reserved * | 0x00148 - 0x0014F: Reserved - * | 0x00150 - 0x00153: Next event + * | 0x00150 - 0x00153: Last update * 0x00154 - 0x0017B: Audio channel 3 state * | 0x00154 - 0x00173: Wave banks * | 0x00174 - 0x00175: Remaining length * | 0x00176 - 0x00177: Reserved - * | 0x00178 - 0x0017B: Next event + * | 0x00178 - 0x0017B: Last update * 0x0017C - 0x0018B: Audio channel 4 state * | 0x0017C - 0x0017F: Linear feedback shift register state * | 0x00180 - 0x00183: Envelepe timing diff --git a/src/gb/audio.c b/src/gb/audio.c index 5dc40ac62..e65bd106a 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -35,19 +35,21 @@ static void _updateEnvelopeDead(struct GBAudioEnvelope* envelope); static bool _updateSweep(struct GBAudioSquareChannel* sweep, bool initial); static void _updateSquareSample(struct GBAudioSquareChannel* ch); -static int32_t _updateSquareChannel(struct GBAudioSquareChannel* ch); - -static int32_t _cyclesToInvert(struct GBAudioSquareChannel* ch); static int16_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch); static void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate); -static void _updateChannel1(struct mTiming* timing, void* user, uint32_t cyclesLate); -static void _updateChannel2(struct mTiming* timing, void* user, uint32_t cyclesLate); static void _updateChannel3(struct mTiming* timing, void* user, uint32_t cyclesLate); static void _fadeChannel3(struct mTiming* timing, void* user, uint32_t cyclesLate); static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate); +static const int _squareChannelDuty[4][8] = { + { 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 0, 0, 0, 0, 1, 1, 1 }, + { 0, 1, 1, 1, 1, 1, 1, 0 }, +}; + void GBAudioInit(struct GBAudio* audio, size_t samples, uint8_t* nr52, enum GBAudioStyle style) { audio->samples = samples; audio->left = blip_new(BLIP_BUFFER_SIZE); @@ -73,14 +75,6 @@ void GBAudioInit(struct GBAudio* audio, size_t samples, uint8_t* nr52, enum GBAu audio->frameEvent.name = "GB Audio Frame Sequencer"; audio->frameEvent.callback = _updateFrame; audio->frameEvent.priority = 0x10; - audio->ch1Event.context = audio; - audio->ch1Event.name = "GB Audio Channel 1"; - audio->ch1Event.callback = _updateChannel1; - audio->ch1Event.priority = 0x11; - audio->ch2Event.context = audio; - audio->ch2Event.name = "GB Audio Channel 2"; - audio->ch2Event.callback = _updateChannel2; - audio->ch2Event.priority = 0x12; audio->ch3Event.context = audio; audio->ch3Event.name = "GB Audio Channel 3"; audio->ch3Event.callback = _updateChannel3; @@ -106,8 +100,6 @@ void GBAudioDeinit(struct GBAudio* audio) { void GBAudioReset(struct GBAudio* audio) { mTimingDeschedule(audio->timing, &audio->frameEvent); - mTimingDeschedule(audio->timing, &audio->ch1Event); - mTimingDeschedule(audio->timing, &audio->ch2Event); mTimingDeschedule(audio->timing, &audio->ch3Event); mTimingDeschedule(audio->timing, &audio->ch3Fade); mTimingDeschedule(audio->timing, &audio->ch4Event); @@ -168,32 +160,35 @@ void GBAudioResizeBuffer(struct GBAudio* audio, size_t samples) { } void GBAudioWriteNR10(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); if (!_writeSweep(&audio->ch1.sweep, value)) { - mTimingDeschedule(audio->timing, &audio->ch1Event); audio->playingCh1 = false; *audio->nr52 &= ~0x0001; } } void GBAudioWriteNR11(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); _writeDuty(&audio->ch1.envelope, value); audio->ch1.control.length = 64 - audio->ch1.envelope.length; } void GBAudioWriteNR12(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); if (!_writeEnvelope(&audio->ch1.envelope, value, audio->style)) { - mTimingDeschedule(audio->timing, &audio->ch1Event); audio->playingCh1 = false; *audio->nr52 &= ~0x0001; } } void GBAudioWriteNR13(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); audio->ch1.control.frequency &= 0x700; audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value); } void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); audio->ch1.control.frequency &= 0xFF; audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8); bool wasStop = audio->ch1.control.stop; @@ -201,12 +196,10 @@ void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) { if (!wasStop && audio->ch1.control.stop && audio->ch1.control.length && !(audio->frame & 1)) { --audio->ch1.control.length; if (audio->ch1.control.length == 0) { - mTimingDeschedule(audio->timing, &audio->ch1Event); audio->playingCh1 = false; } } if (GBAudioRegisterControlIsRestart(value << 8)) { - bool wasDead = !audio->playingCh1; audio->playingCh1 = _resetEnvelope(&audio->ch1.envelope); audio->ch1.sweep.realFrequency = audio->ch1.control.frequency; _resetSweep(&audio->ch1.sweep); @@ -220,35 +213,33 @@ void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) { } } _updateSquareSample(&audio->ch1); - if (wasDead && audio->playingCh1) { - mTimingSchedule(audio->timing, &audio->ch1Event, _cyclesToInvert(&audio->ch1)); - } else if (!audio->playingCh1) { - mTimingDeschedule(audio->timing, &audio->ch1Event); - } } *audio->nr52 &= ~0x0001; *audio->nr52 |= audio->playingCh1; } void GBAudioWriteNR21(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); _writeDuty(&audio->ch2.envelope, value); audio->ch2.control.length = 64 - audio->ch2.envelope.length; } void GBAudioWriteNR22(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); if (!_writeEnvelope(&audio->ch2.envelope, value, audio->style)) { - mTimingDeschedule(audio->timing, &audio->ch2Event); audio->playingCh2 = false; *audio->nr52 &= ~0x0002; } } void GBAudioWriteNR23(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); audio->ch2.control.frequency &= 0x700; audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value); } void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); audio->ch2.control.frequency &= 0xFF; audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8); bool wasStop = audio->ch2.control.stop; @@ -256,12 +247,10 @@ void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) { if (!wasStop && audio->ch2.control.stop && audio->ch2.control.length && !(audio->frame & 1)) { --audio->ch2.control.length; if (audio->ch2.control.length == 0) { - mTimingDeschedule(audio->timing, &audio->ch2Event); audio->playingCh2 = false; } } if (GBAudioRegisterControlIsRestart(value << 8)) { - bool wasDead = !audio->playingCh2; audio->playingCh2 = _resetEnvelope(&audio->ch2.envelope); if (!audio->ch2.control.length) { @@ -271,11 +260,6 @@ void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) { } } _updateSquareSample(&audio->ch2); - if (wasDead && audio->playingCh2) { - mTimingSchedule(audio->timing, &audio->ch2Event, _cyclesToInvert(&audio->ch2)); - } else if (!audio->playingCh2) { - mTimingDeschedule(audio->timing, &audio->ch2Event); - } } *audio->nr52 &= ~0x0002; *audio->nr52 |= audio->playingCh2 << 1; @@ -496,6 +480,26 @@ void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate) { } } +void GBAudioRun(struct GBAudio* audio, int32_t timestamp) { + if (!audio->enable) { + return; + } + if (audio->playingCh1) { + int period = 4 * (2048 - audio->ch1.control.frequency) * audio->timingFactor; + int32_t diff = (timestamp - audio->ch1.lastUpdate) / period; + audio->ch1.index = (audio->ch1.index + diff) & 7; + audio->ch1.lastUpdate += diff * period; + _updateSquareSample(&audio->ch1); + } + if (audio->playingCh2) { + int period = 4 * (2048 - audio->ch2.control.frequency) * audio->timingFactor; + int32_t diff = (timestamp - audio->ch2.lastUpdate) / period; + audio->ch2.index = (audio->ch2.index + diff) & 7; + audio->ch2.lastUpdate += diff * period; + _updateSquareSample(&audio->ch2); + } +} + void GBAudioUpdateFrame(struct GBAudio* audio) { if (!audio->enable) { return; @@ -504,6 +508,8 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { audio->skipFrame = false; return; } + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + int frame = (audio->frame + 1) & 7; audio->frame = frame; @@ -516,9 +522,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { audio->playingCh1 = _updateSweep(&audio->ch1, false); *audio->nr52 &= ~0x0001; *audio->nr52 |= audio->playingCh1; - if (!audio->playingCh1) { - mTimingDeschedule(audio->timing, &audio->ch1Event); - } } } // Fall through @@ -527,7 +530,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { if (audio->ch1.control.length && audio->ch1.control.stop) { --audio->ch1.control.length; if (audio->ch1.control.length == 0) { - mTimingDeschedule(audio->timing, &audio->ch1Event); audio->playingCh1 = 0; *audio->nr52 &= ~0x0001; } @@ -536,7 +538,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { if (audio->ch2.control.length && audio->ch2.control.stop) { --audio->ch2.control.length; if (audio->ch2.control.length == 0) { - mTimingDeschedule(audio->timing, &audio->ch2Event); audio->playingCh2 = 0; *audio->nr52 &= ~0x0002; } @@ -565,9 +566,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { --audio->ch1.envelope.nextStep; if (audio->ch1.envelope.nextStep == 0) { _updateEnvelope(&audio->ch1.envelope); - if (audio->ch1.envelope.dead == 2) { - mTimingDeschedule(audio->timing, &audio->ch1Event); - } _updateSquareSample(&audio->ch1); } } @@ -576,9 +574,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { --audio->ch2.envelope.nextStep; if (audio->ch2.envelope.nextStep == 0) { _updateEnvelope(&audio->ch2.envelope); - if (audio->ch2.envelope.dead == 2) { - mTimingDeschedule(audio->timing, &audio->ch2Event); - } _updateSquareSample(&audio->ch2); } } @@ -626,6 +621,7 @@ void GBAudioUpdateChannel4(struct GBAudio* audio) { } void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); int dcOffset = audio->style == GB_AUDIO_GBA ? 0 : -0x8; int sampleLeft = dcOffset; int sampleRight = dcOffset; @@ -775,30 +771,7 @@ bool _writeEnvelope(struct GBAudioEnvelope* envelope, uint8_t value, enum GBAudi } static void _updateSquareSample(struct GBAudioSquareChannel* ch) { - ch->sample = ch->control.hi * ch->envelope.currentVolume; -} - -static int32_t _updateSquareChannel(struct GBAudioSquareChannel* ch) { - ch->control.hi = !ch->control.hi; - _updateSquareSample(ch); - return _cyclesToInvert(ch); -} - -static int32_t _cyclesToInvert(struct GBAudioSquareChannel* ch) { - int period = 4 * (2048 - ch->control.frequency); - switch (ch->envelope.duty) { - case 0: - return ch->control.hi ? period : period * 7; - case 1: - return ch->control.hi ? period * 2 : period * 6; - case 2: - return period * 4; - case 3: - return ch->control.hi ? period * 6 : period * 2; - default: - // This should never be hit - return period * 4; - } + ch->sample = _squareChannelDuty[ch->envelope.duty][ch->index] * ch->envelope.currentVolume; } static int16_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch) { @@ -870,20 +843,6 @@ static bool _updateSweep(struct GBAudioSquareChannel* ch, bool initial) { return true; } -static void _updateChannel1(struct mTiming* timing, void* user, uint32_t cyclesLate) { - struct GBAudio* audio = user; - struct GBAudioSquareChannel* ch = &audio->ch1; - int cycles = _updateSquareChannel(ch); - mTimingSchedule(timing, &audio->ch1Event, audio->timingFactor * cycles - cyclesLate); -} - -static void _updateChannel2(struct mTiming* timing, void* user, uint32_t cyclesLate) { - struct GBAudio* audio = user; - struct GBAudioSquareChannel* ch = &audio->ch2; - int cycles = _updateSquareChannel(ch); - mTimingSchedule(timing, &audio->ch2Event, audio->timingFactor * cycles - cyclesLate); -} - static void _updateChannel3(struct mTiming* timing, void* user, uint32_t cyclesLate) { struct GBAudio* audio = user; struct GBAudioWaveChannel* ch = &audio->ch3; @@ -971,24 +930,24 @@ void GBAudioPSGSerialize(const struct GBAudio* audio, struct GBSerializedPSGStat flags = GBSerializedAudioFlagsSetCh1Volume(flags, audio->ch1.envelope.currentVolume); flags = GBSerializedAudioFlagsSetCh1Dead(flags, audio->ch1.envelope.dead); - flags = GBSerializedAudioFlagsSetCh1Hi(flags, audio->ch1.control.hi); flags = GBSerializedAudioFlagsSetCh1SweepEnabled(flags, audio->ch1.sweep.enable); flags = GBSerializedAudioFlagsSetCh1SweepOccurred(flags, audio->ch1.sweep.occurred); ch1Flags = GBSerializedAudioEnvelopeSetLength(ch1Flags, audio->ch1.control.length); ch1Flags = GBSerializedAudioEnvelopeSetNextStep(ch1Flags, audio->ch1.envelope.nextStep); ch1Flags = GBSerializedAudioEnvelopeSetFrequency(ch1Flags, audio->ch1.sweep.realFrequency); + ch1Flags = GBSerializedAudioEnvelopeSetDutyIndex(ch1Flags, audio->ch1.index); sweep = GBSerializedAudioSweepSetTime(sweep, audio->ch1.sweep.time & 7); STORE_32LE(ch1Flags, 0, &state->ch1.envelope); STORE_32LE(sweep, 0, &state->ch1.sweep); - STORE_32LE(audio->ch1Event.when - mTimingCurrentTime(audio->timing), 0, &state->ch1.nextEvent); + STORE_32LE(audio->ch1.lastUpdate - mTimingCurrentTime(audio->timing), 0, &state->ch1.lastUpdate); flags = GBSerializedAudioFlagsSetCh2Volume(flags, audio->ch2.envelope.currentVolume); flags = GBSerializedAudioFlagsSetCh2Dead(flags, audio->ch2.envelope.dead); - flags = GBSerializedAudioFlagsSetCh2Hi(flags, audio->ch2.control.hi); ch2Flags = GBSerializedAudioEnvelopeSetLength(ch2Flags, audio->ch2.control.length); ch2Flags = GBSerializedAudioEnvelopeSetNextStep(ch2Flags, audio->ch2.envelope.nextStep); + ch2Flags = GBSerializedAudioEnvelopeSetDutyIndex(ch2Flags, audio->ch2.index); STORE_32LE(ch2Flags, 0, &state->ch2.envelope); - STORE_32LE(audio->ch2Event.when - mTimingCurrentTime(audio->timing), 0, &state->ch2.nextEvent); + STORE_32LE(audio->ch2.lastUpdate - mTimingCurrentTime(audio->timing), 0, &state->ch2.lastUpdate); flags = GBSerializedAudioFlagsSetCh3Readable(flags, audio->ch3.readable); memcpy(state->ch3.wavebanks, audio->ch3.wavedata32, sizeof(state->ch3.wavebanks)); @@ -1039,7 +998,6 @@ void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGSt LOAD_32LE(sweep, 0, &state->ch1.sweep); audio->ch1.envelope.currentVolume = GBSerializedAudioFlagsGetCh1Volume(flags); audio->ch1.envelope.dead = GBSerializedAudioFlagsGetCh1Dead(flags); - audio->ch1.control.hi = GBSerializedAudioFlagsGetCh1Hi(flags); audio->ch1.sweep.enable = GBSerializedAudioFlagsGetCh1SweepEnabled(flags); audio->ch1.sweep.occurred = GBSerializedAudioFlagsGetCh1SweepOccurred(flags); audio->ch1.sweep.time = GBSerializedAudioSweepGetTime(sweep); @@ -1049,21 +1007,18 @@ void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGSt audio->ch1.control.length = GBSerializedAudioEnvelopeGetLength(ch1Flags); audio->ch1.envelope.nextStep = GBSerializedAudioEnvelopeGetNextStep(ch1Flags); audio->ch1.sweep.realFrequency = GBSerializedAudioEnvelopeGetFrequency(ch1Flags); - LOAD_32LE(when, 0, &state->ch1.nextEvent); - if (audio->ch1.envelope.dead < 2 && audio->playingCh1) { - mTimingSchedule(audio->timing, &audio->ch1Event, when); - } + audio->ch1.index = GBSerializedAudioEnvelopeGetDutyIndex(ch1Flags); + LOAD_32LE(audio->ch1.lastUpdate, 0, &state->ch1.lastUpdate); + audio->ch1.lastUpdate += mTimingCurrentTime(audio->timing); LOAD_32LE(ch2Flags, 0, &state->ch2.envelope); audio->ch2.envelope.currentVolume = GBSerializedAudioFlagsGetCh2Volume(flags); audio->ch2.envelope.dead = GBSerializedAudioFlagsGetCh2Dead(flags); - audio->ch2.control.hi = GBSerializedAudioFlagsGetCh2Hi(flags); audio->ch2.control.length = GBSerializedAudioEnvelopeGetLength(ch2Flags); audio->ch2.envelope.nextStep = GBSerializedAudioEnvelopeGetNextStep(ch2Flags); - LOAD_32LE(when, 0, &state->ch2.nextEvent); - if (audio->ch2.envelope.dead < 2 && audio->playingCh2) { - mTimingSchedule(audio->timing, &audio->ch2Event, when); - } + audio->ch2.index = GBSerializedAudioEnvelopeGetDutyIndex(ch2Flags); + LOAD_32LE(audio->ch2.lastUpdate, 0, &state->ch2.lastUpdate); + audio->ch2.lastUpdate += mTimingCurrentTime(audio->timing); audio->ch3.readable = GBSerializedAudioFlagsGetCh3Readable(flags); // TODO: Big endian? diff --git a/src/gb/io.c b/src/gb/io.c index deed1153f..a948403ec 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -620,6 +620,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) { if (gb->model < GB_MODEL_CGB) { mLOG(GB_IO, GAME_ERROR, "Reading from CGB register FF%02X in DMG mode", address); } else if (gb->audio.enable) { + GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing)); return (gb->audio.ch1.sample) | (gb->audio.ch2.sample << 4); } break; diff --git a/src/gb/serialize.c b/src/gb/serialize.c index d3fd8f12a..ad7ebe756 100644 --- a/src/gb/serialize.c +++ b/src/gb/serialize.c @@ -14,7 +14,7 @@ mLOG_DEFINE_CATEGORY(GB_STATE, "GB Savestate", "gb.serialize"); MGBA_EXPORT const uint32_t GBSavestateMagic = 0x00400000; -MGBA_EXPORT const uint32_t GBSavestateVersion = 0x00000002; +MGBA_EXPORT const uint32_t GBSavestateVersion = 0x00000003; void GBSerialize(struct GB* gb, struct GBSerializedState* state) { STORE_32LE(GBSavestateMagic + GBSavestateVersion, 0, &state->versionMagic); diff --git a/src/gba/serialize.c b/src/gba/serialize.c index a7294b6b5..d2bd5c5e8 100644 --- a/src/gba/serialize.c +++ b/src/gba/serialize.c @@ -15,7 +15,7 @@ #include MGBA_EXPORT const uint32_t GBASavestateMagic = 0x01000000; -MGBA_EXPORT const uint32_t GBASavestateVersion = 0x00000004; +MGBA_EXPORT const uint32_t GBASavestateVersion = 0x00000005; mLOG_DEFINE_CATEGORY(GBA_STATE, "GBA Savestate", "gba.serialize"); From 779e7bc94b5d46f5c68a9af212555e96cac14be3 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 31 May 2022 21:24:50 -0700 Subject: [PATCH 011/102] GB Audio: Migrate channel 4 into GBRunAudio --- include/mgba/internal/gb/audio.h | 2 -- src/gb/audio.c | 61 ++++++++++++-------------------- src/gb/io.c | 2 +- 3 files changed, 24 insertions(+), 41 deletions(-) diff --git a/include/mgba/internal/gb/audio.h b/include/mgba/internal/gb/audio.h index 3e2d4c2f8..ffcc71744 100644 --- a/include/mgba/internal/gb/audio.h +++ b/include/mgba/internal/gb/audio.h @@ -197,7 +197,6 @@ struct GBAudio { struct mTimingEvent frameEvent; struct mTimingEvent ch3Event; struct mTimingEvent ch3Fade; - struct mTimingEvent ch4Event; struct mTimingEvent sampleEvent; bool enable; @@ -240,7 +239,6 @@ void GBAudioWriteNR52(struct GBAudio* audio, uint8_t); void GBAudioRun(struct GBAudio* audio, int32_t timestamp); void GBAudioUpdateFrame(struct GBAudio* audio); -void GBAudioUpdateChannel4(struct GBAudio* audio); void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right); diff --git a/src/gb/audio.c b/src/gb/audio.c index e65bd106a..a44f6e12a 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -83,10 +83,6 @@ void GBAudioInit(struct GBAudio* audio, size_t samples, uint8_t* nr52, enum GBAu audio->ch3Fade.name = "GB Audio Channel 3 Memory"; audio->ch3Fade.callback = _fadeChannel3; audio->ch3Fade.priority = 0x14; - audio->ch4Event.context = audio; - audio->ch4Event.name = "GB Audio Channel 4"; - audio->ch4Event.callback = NULL; // This is pending removal, so calling it will crash - audio->ch4Event.priority = 0x15; audio->sampleEvent.context = audio; audio->sampleEvent.name = "GB Audio Sample"; audio->sampleEvent.callback = _sample; @@ -102,7 +98,6 @@ void GBAudioReset(struct GBAudio* audio) { mTimingDeschedule(audio->timing, &audio->frameEvent); mTimingDeschedule(audio->timing, &audio->ch3Event); mTimingDeschedule(audio->timing, &audio->ch3Fade); - mTimingDeschedule(audio->timing, &audio->ch4Event); mTimingDeschedule(audio->timing, &audio->sampleEvent); if (audio->style != GB_AUDIO_GBA) { mTimingSchedule(audio->timing, &audio->sampleEvent, 0); @@ -335,13 +330,13 @@ void GBAudioWriteNR34(struct GBAudio* audio, uint8_t value) { } void GBAudioWriteNR41(struct GBAudio* audio, uint8_t value) { - GBAudioUpdateChannel4(audio); + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); _writeDuty(&audio->ch4.envelope, value); audio->ch4.length = 64 - audio->ch4.envelope.length; } void GBAudioWriteNR42(struct GBAudio* audio, uint8_t value) { - GBAudioUpdateChannel4(audio); + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); if (!_writeEnvelope(&audio->ch4.envelope, value, audio->style)) { audio->playingCh4 = false; *audio->nr52 &= ~0x0008; @@ -349,14 +344,14 @@ void GBAudioWriteNR42(struct GBAudio* audio, uint8_t value) { } void GBAudioWriteNR43(struct GBAudio* audio, uint8_t value) { - GBAudioUpdateChannel4(audio); + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); audio->ch4.ratio = GBAudioRegisterNoiseFeedbackGetRatio(value); audio->ch4.frequency = GBAudioRegisterNoiseFeedbackGetFrequency(value); audio->ch4.power = GBAudioRegisterNoiseFeedbackGetPower(value); } void GBAudioWriteNR44(struct GBAudio* audio, uint8_t value) { - GBAudioUpdateChannel4(audio); + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); bool wasStop = audio->ch4.stop; audio->ch4.stop = GBAudioRegisterNoiseControlGetStop(value); if (!wasStop && audio->ch4.stop && audio->ch4.length && !(audio->frame & 1)) { @@ -379,7 +374,7 @@ void GBAudioWriteNR44(struct GBAudio* audio, uint8_t value) { --audio->ch4.length; } } - if (audio->playingCh4 && audio->ch4.envelope.dead != 2) { + if (audio->playingCh4) { audio->ch4.lastEvent = mTimingCurrentTime(audio->timing); } } @@ -498,6 +493,24 @@ void GBAudioRun(struct GBAudio* audio, int32_t timestamp) { audio->ch2.lastUpdate += diff * period; _updateSquareSample(&audio->ch2); } + if (audio->playingCh4) { + int32_t cycles = audio->ch4.ratio ? 2 * audio->ch4.ratio : 1; + cycles <<= audio->ch4.frequency; + cycles *= 8 * audio->timingFactor; + + int32_t last = 0; + int32_t diff = timestamp - audio->ch4.lastEvent; + for (; last + cycles <= diff; last += cycles) { + int lsb = audio->ch4.lfsr & 1; + audio->ch4.sample = lsb * audio->ch4.envelope.currentVolume; + ++audio->ch4.nSamples; + audio->ch4.samples += audio->ch4.sample; + audio->ch4.lfsr >>= 1; + audio->ch4.lfsr ^= (lsb * 0x60) << (audio->ch4.power ? 0 : 8); + } + + audio->ch4.lastEvent += last; + } } void GBAudioUpdateFrame(struct GBAudio* audio) { @@ -555,7 +568,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { if (audio->ch4.length && audio->ch4.stop) { --audio->ch4.length; if (audio->ch4.length == 0) { - GBAudioUpdateChannel4(audio); audio->playingCh4 = 0; *audio->nr52 &= ~0x0008; } @@ -581,7 +593,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { if (audio->playingCh4 && !audio->ch4.envelope.dead) { --audio->ch4.envelope.nextStep; if (audio->ch4.envelope.nextStep == 0) { - GBAudioUpdateChannel4(audio); int8_t sample = audio->ch4.sample; _updateEnvelope(&audio->ch4.envelope); audio->ch4.sample = (sample > 0) * audio->ch4.envelope.currentVolume; @@ -595,31 +606,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { } } -void GBAudioUpdateChannel4(struct GBAudio* audio) { - struct GBAudioNoiseChannel* ch = &audio->ch4; - if (ch->envelope.dead == 2 || !audio->playingCh4) { - return; - } - - int32_t cycles = ch->ratio ? 2 * ch->ratio : 1; - cycles <<= ch->frequency; - cycles *= 8 * audio->timingFactor; - - uint32_t last = 0; - uint32_t now = mTimingCurrentTime(audio->timing) - ch->lastEvent; - - for (; last + cycles <= now; last += cycles) { - int lsb = ch->lfsr & 1; - ch->sample = lsb * ch->envelope.currentVolume; - ++ch->nSamples; - ch->samples += ch->sample; - ch->lfsr >>= 1; - ch->lfsr ^= (lsb * 0x60) << (ch->power ? 0 : 8); - } - - ch->lastEvent += last; -} - void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) { GBAudioRun(audio, mTimingCurrentTime(audio->timing)); int dcOffset = audio->style == GB_AUDIO_GBA ? 0 : -0x8; @@ -660,7 +646,6 @@ void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) { sampleRight <<= 3; if (!audio->forceDisableCh[3]) { - GBAudioUpdateChannel4(audio); int16_t sample = audio->style == GB_AUDIO_GBA ? (audio->ch4.sample << 3) : _coalesceNoiseChannel(&audio->ch4); if (audio->ch4Left) { sampleLeft += sample; diff --git a/src/gb/io.c b/src/gb/io.c index a948403ec..973ff43f7 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -628,7 +628,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) { if (gb->model < GB_MODEL_CGB) { mLOG(GB_IO, GAME_ERROR, "Reading from CGB register FF%02X in DMG mode", address); } else if (gb->audio.enable) { - GBAudioUpdateChannel4(&gb->audio); + GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing)); return (gb->audio.ch3.sample) | (gb->audio.ch4.sample << 4); } break; From 76a8f4da2bb4fc4ef10a64eae5d3da0d7846c73f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 31 May 2022 22:45:00 -0700 Subject: [PATCH 012/102] GB Audio: Migrate channel 3 into GBRunAudio --- include/mgba/internal/gb/audio.h | 5 +- include/mgba/internal/gb/serialize.h | 4 +- include/mgba/internal/gba/serialize.h | 4 +- src/gb/audio.c | 182 ++++++++++++-------------- src/gb/io.c | 2 + src/gba/audio.c | 2 + 6 files changed, 91 insertions(+), 108 deletions(-) diff --git a/include/mgba/internal/gb/audio.h b/include/mgba/internal/gb/audio.h index ffcc71744..93c76d997 100644 --- a/include/mgba/internal/gb/audio.h +++ b/include/mgba/internal/gb/audio.h @@ -113,6 +113,7 @@ struct GBAudioWaveChannel { bool bank; bool enable; + int8_t sample; unsigned length; int volume; @@ -125,7 +126,7 @@ struct GBAudioWaveChannel { uint32_t wavedata32[8]; uint8_t wavedata8[16]; }; - int8_t sample; + int32_t nextUpdate; }; struct GBAudioNoiseChannel { @@ -195,8 +196,6 @@ struct GBAudio { enum GBAudioStyle style; struct mTimingEvent frameEvent; - struct mTimingEvent ch3Event; - struct mTimingEvent ch3Fade; struct mTimingEvent sampleEvent; bool enable; diff --git a/include/mgba/internal/gb/serialize.h b/include/mgba/internal/gb/serialize.h index 6043cc919..11bdf7dc3 100644 --- a/include/mgba/internal/gb/serialize.h +++ b/include/mgba/internal/gb/serialize.h @@ -59,7 +59,7 @@ mLOG_DECLARE_CATEGORY(GB_STATE); * | bits 21 - 23: Duty index * | bits 24 - 31: Reserved * | 0x0004C - 0x0004F: Next frame - * | 0x00050 - 0x00053: Next channel 3 fade + * | 0x00050 - 0x00053: Reserved * | 0x00054 - 0x00057: Sweep state * | bits 0 - 2: Timesteps * | bits 3 - 31: Reserved @@ -220,7 +220,7 @@ struct GBSerializedPSGState { struct { GBSerializedAudioEnvelope envelope; int32_t nextFrame; - int32_t nextCh3Fade; + int32_t reserved; GBSerializedAudioSweep sweep; uint32_t lastUpdate; } ch1; diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index b25b3aec0..364563195 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -42,7 +42,7 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * | bits 21 - 23: Duty index * | bits 24 - 31: Reserved * | 0x00134 - 0x00137: Next frame - * | 0x00138 - 0x0013B: Next channel 3 fade + * | 0x00138 - 0x0013B: Reserved * | 0x0013C - 0x0013F: Sweep state * | bits 0 - 2: Timesteps * | bits 3 - 7: Reserved @@ -60,7 +60,7 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * | 0x00154 - 0x00173: Wave banks * | 0x00174 - 0x00175: Remaining length * | 0x00176 - 0x00177: Reserved - * | 0x00178 - 0x0017B: Last update + * | 0x00178 - 0x0017B: Next event * 0x0017C - 0x0018B: Audio channel 4 state * | 0x0017C - 0x0017F: Linear feedback shift register state * | 0x00180 - 0x00183: Envelepe timing diff --git a/src/gb/audio.c b/src/gb/audio.c index a44f6e12a..9051a3c5d 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -39,8 +39,6 @@ static void _updateSquareSample(struct GBAudioSquareChannel* ch); static int16_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch); static void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate); -static void _updateChannel3(struct mTiming* timing, void* user, uint32_t cyclesLate); -static void _fadeChannel3(struct mTiming* timing, void* user, uint32_t cyclesLate); static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate); static const int _squareChannelDuty[4][8] = { @@ -75,14 +73,6 @@ void GBAudioInit(struct GBAudio* audio, size_t samples, uint8_t* nr52, enum GBAu audio->frameEvent.name = "GB Audio Frame Sequencer"; audio->frameEvent.callback = _updateFrame; audio->frameEvent.priority = 0x10; - audio->ch3Event.context = audio; - audio->ch3Event.name = "GB Audio Channel 3"; - audio->ch3Event.callback = _updateChannel3; - audio->ch3Event.priority = 0x13; - audio->ch3Fade.context = audio; - audio->ch3Fade.name = "GB Audio Channel 3 Memory"; - audio->ch3Fade.callback = _fadeChannel3; - audio->ch3Fade.priority = 0x14; audio->sampleEvent.context = audio; audio->sampleEvent.name = "GB Audio Sample"; audio->sampleEvent.callback = _sample; @@ -96,8 +86,6 @@ void GBAudioDeinit(struct GBAudio* audio) { void GBAudioReset(struct GBAudio* audio) { mTimingDeschedule(audio->timing, &audio->frameEvent); - mTimingDeschedule(audio->timing, &audio->ch3Event); - mTimingDeschedule(audio->timing, &audio->ch3Fade); mTimingDeschedule(audio->timing, &audio->sampleEvent); if (audio->style != GB_AUDIO_GBA) { mTimingSchedule(audio->timing, &audio->sampleEvent, 0); @@ -261,28 +249,32 @@ void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) { } void GBAudioWriteNR30(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); audio->ch3.enable = GBAudioRegisterBankGetEnable(value); if (!audio->ch3.enable) { - mTimingDeschedule(audio->timing, &audio->ch3Event); audio->playingCh3 = false; *audio->nr52 &= ~0x0004; } } void GBAudioWriteNR31(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); audio->ch3.length = 256 - value; } void GBAudioWriteNR32(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); audio->ch3.volume = GBAudioRegisterBankVolumeGetVolumeGB(value); } void GBAudioWriteNR33(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); audio->ch3.rate &= 0x700; audio->ch3.rate |= GBAudioRegisterControlGetRate(value); } void GBAudioWriteNR34(struct GBAudio* audio, uint8_t value) { + GBAudioRun(audio, mTimingCurrentTime(audio->timing)); audio->ch3.rate &= 0xFF; audio->ch3.rate |= GBAudioRegisterControlGetRate(value << 8); bool wasStop = audio->ch3.stop; @@ -318,12 +310,10 @@ void GBAudioWriteNR34(struct GBAudio* audio, uint8_t value) { audio->ch3.sample = 0; } } - mTimingDeschedule(audio->timing, &audio->ch3Fade); - mTimingDeschedule(audio->timing, &audio->ch3Event); if (audio->playingCh3) { audio->ch3.readable = audio->style != GB_AUDIO_DMG; // TODO: Where does this cycle delay come from? - mTimingSchedule(audio->timing, &audio->ch3Event, audio->timingFactor * (4 + 2 * (2048 - audio->ch3.rate))); + audio->ch3.nextUpdate = mTimingCurrentTime(audio->timing) + (6 + 2 * (2048 - audio->ch3.rate)) * audio->timingFactor; } *audio->nr52 &= ~0x0004; *audio->nr52 |= audio->playingCh3 << 2; @@ -493,6 +483,78 @@ void GBAudioRun(struct GBAudio* audio, int32_t timestamp) { audio->ch2.lastUpdate += diff * period; _updateSquareSample(&audio->ch2); } + if (audio->playingCh3) { + int cycles = 2 * (2048 - audio->ch3.rate) * audio->timingFactor; + int32_t diff = timestamp - audio->ch3.nextUpdate; + if (diff >= 0) { + diff = (diff / cycles) + 1; + int volume; + switch (audio->ch3.volume) { + case 0: + volume = 4; + break; + case 1: + volume = 0; + break; + case 2: + volume = 1; + break; + default: + case 3: + volume = 2; + break; + } + int start = 7; + int end = 0; + int mask = 0x1F; + int iter; + switch (audio->style) { + case GB_AUDIO_DMG: + default: + audio->ch3.window += diff; + audio->ch3.window &= 0x1F; + audio->ch3.sample = audio->ch3.wavedata8[audio->ch3.window >> 1]; + if (!(audio->ch3.window & 1)) { + audio->ch3.sample >>= 4; + } + audio->ch3.sample &= 0xF; + break; + case GB_AUDIO_GBA: + if (audio->ch3.size) { + mask = 0x3F; + } else if (audio->ch3.bank) { + end = 4; + } else { + start = 3; + } + for (iter = 0; iter < (diff & mask); ++iter) { + uint32_t bitsCarry = audio->ch3.wavedata32[end] & 0x000000F0; + uint32_t bits; + int i; + for (i = start; i >= end; --i) { + bits = audio->ch3.wavedata32[i] & 0x000000F0; + audio->ch3.wavedata32[i] = ((audio->ch3.wavedata32[i] & 0x0F0F0F0F) << 4) | ((audio->ch3.wavedata32[i] & 0xF0F0F000) >> 12); + audio->ch3.wavedata32[i] |= bitsCarry << 20; + bitsCarry = bits; + } + audio->ch3.sample = bitsCarry >> 4; + } + break; + } + if (audio->ch3.volume > 3) { + audio->ch3.sample += audio->ch3.sample << 1; + } + audio->ch3.sample >>= volume; + audio->ch3.nextUpdate += diff * cycles; + audio->ch3.readable = true; + } + if (audio->style == GB_AUDIO_DMG && audio->ch3.readable) { + diff = timestamp - audio->ch3.nextUpdate + cycles; + if (diff >= 4) { + audio->ch3.readable = false; + } + } + } if (audio->playingCh4) { int32_t cycles = audio->ch4.ratio ? 2 * audio->ch4.ratio : 1; cycles <<= audio->ch4.frequency; @@ -559,7 +621,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { if (audio->ch3.length && audio->ch3.stop) { --audio->ch3.length; if (audio->ch3.length == 0) { - mTimingDeschedule(audio->timing, &audio->ch3Event); audio->playingCh3 = 0; *audio->nr52 &= ~0x0004; } @@ -828,80 +889,6 @@ static bool _updateSweep(struct GBAudioSquareChannel* ch, bool initial) { return true; } -static void _updateChannel3(struct mTiming* timing, void* user, uint32_t cyclesLate) { - struct GBAudio* audio = user; - struct GBAudioWaveChannel* ch = &audio->ch3; - int i; - int volume; - switch (ch->volume) { - case 0: - volume = 4; - break; - case 1: - volume = 0; - break; - case 2: - volume = 1; - break; - default: - case 3: - volume = 2; - break; - } - int start; - int end; - switch (audio->style) { - case GB_AUDIO_DMG: - default: - ++ch->window; - ch->window &= 0x1F; - ch->sample = ch->wavedata8[ch->window >> 1]; - if (!(ch->window & 1)) { - ch->sample >>= 4; - } - ch->sample &= 0xF; - break; - case GB_AUDIO_GBA: - if (ch->size) { - start = 7; - end = 0; - } else if (ch->bank) { - start = 7; - end = 4; - } else { - start = 3; - end = 0; - } - uint32_t bitsCarry = ch->wavedata32[end] & 0x000000F0; - uint32_t bits; - for (i = start; i >= end; --i) { - bits = ch->wavedata32[i] & 0x000000F0; - ch->wavedata32[i] = ((ch->wavedata32[i] & 0x0F0F0F0F) << 4) | ((ch->wavedata32[i] & 0xF0F0F000) >> 12); - ch->wavedata32[i] |= bitsCarry << 20; - bitsCarry = bits; - } - ch->sample = bitsCarry >> 4; - break; - } - if (ch->volume > 3) { - ch->sample += ch->sample << 1; - } - ch->sample >>= volume; - audio->ch3.readable = true; - if (audio->style == GB_AUDIO_DMG) { - mTimingDeschedule(audio->timing, &audio->ch3Fade); - mTimingSchedule(timing, &audio->ch3Fade, 4 - cyclesLate); - } - int cycles = 2 * (2048 - ch->rate); - mTimingSchedule(timing, &audio->ch3Event, audio->timingFactor * cycles - cyclesLate); -} -static void _fadeChannel3(struct mTiming* timing, void* user, uint32_t cyclesLate) { - UNUSED(timing); - UNUSED(cyclesLate); - struct GBAudio* audio = user; - audio->ch3.readable = false; -} - void GBAudioPSGSerialize(const struct GBAudio* audio, struct GBSerializedPSGState* state, uint32_t* flagsOut) { uint32_t flags = 0; uint32_t sweep = 0; @@ -937,8 +924,7 @@ void GBAudioPSGSerialize(const struct GBAudio* audio, struct GBSerializedPSGStat flags = GBSerializedAudioFlagsSetCh3Readable(flags, audio->ch3.readable); memcpy(state->ch3.wavebanks, audio->ch3.wavedata32, sizeof(state->ch3.wavebanks)); STORE_16LE(audio->ch3.length, 0, &state->ch3.length); - STORE_32LE(audio->ch3Event.when - mTimingCurrentTime(audio->timing), 0, &state->ch3.nextEvent); - STORE_32LE(audio->ch3Fade.when - mTimingCurrentTime(audio->timing), 0, &state->ch1.nextCh3Fade); + STORE_32LE(audio->ch3.nextUpdate - mTimingCurrentTime(audio->timing), 0, &state->ch3.nextEvent); flags = GBSerializedAudioFlagsSetCh4Volume(flags, audio->ch4.envelope.currentVolume); flags = GBSerializedAudioFlagsSetCh4Dead(flags, audio->ch4.envelope.dead); @@ -1009,14 +995,8 @@ void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGSt // TODO: Big endian? memcpy(audio->ch3.wavedata32, state->ch3.wavebanks, sizeof(audio->ch3.wavedata32)); LOAD_16LE(audio->ch3.length, 0, &state->ch3.length); - LOAD_32LE(when, 0, &state->ch3.nextEvent); - if (audio->playingCh3) { - mTimingSchedule(audio->timing, &audio->ch3Event, when); - } - LOAD_32LE(when, 0, &state->ch1.nextCh3Fade); - if (audio->ch3.readable && audio->style == GB_AUDIO_DMG) { - mTimingSchedule(audio->timing, &audio->ch3Fade, when); - } + LOAD_32LE(audio->ch3.nextUpdate, 0, &state->ch3.nextEvent); + audio->ch3.nextUpdate += mTimingCurrentTime(audio->timing); LOAD_32LE(ch4Flags, 0, &state->ch4.envelope); audio->ch4.envelope.currentVolume = GBSerializedAudioFlagsGetCh4Volume(flags); diff --git a/src/gb/io.c b/src/gb/io.c index 973ff43f7..d03171bb4 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -403,6 +403,7 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) { case GB_REG_WAVE_D: case GB_REG_WAVE_E: case GB_REG_WAVE_F: + GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing)); if (!gb->audio.playingCh3 || gb->audio.style != GB_AUDIO_DMG) { gb->audio.ch3.wavedata8[address - GB_REG_WAVE_0] = value; } else if(gb->audio.ch3.readable) { @@ -607,6 +608,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) { case GB_REG_WAVE_E: case GB_REG_WAVE_F: if (gb->audio.playingCh3) { + GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing)); if (gb->audio.ch3.readable || gb->audio.style != GB_AUDIO_DMG) { return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1]; } else { diff --git a/src/gba/audio.c b/src/gba/audio.c index fc264349f..4f3cfe3de 100644 --- a/src/gba/audio.c +++ b/src/gba/audio.c @@ -229,6 +229,7 @@ void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value) { bank = 1; } + GBAudioRun(&audio->psg, mTimingCurrentTime(audio->psg.timing)); audio->psg.ch3.wavedata32[address | (bank * 4)] = value; } @@ -241,6 +242,7 @@ uint32_t GBAAudioReadWaveRAM(struct GBAAudio* audio, int address) { bank = 1; } + GBAudioRun(&audio->psg, mTimingCurrentTime(audio->psg.timing)); return audio->psg.ch3.wavedata32[address | (bank * 4)]; } From cdabfd491b714321adbb3bfd687a2b4385249de3 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 31 May 2022 22:59:15 -0700 Subject: [PATCH 013/102] GB Audio: Minor optimizations --- include/mgba/internal/gb/audio.h | 2 +- src/gb/audio.c | 72 +++++++++++++++++--------------- src/gb/io.c | 8 ++-- src/gba/audio.c | 4 +- 4 files changed, 46 insertions(+), 40 deletions(-) diff --git a/include/mgba/internal/gb/audio.h b/include/mgba/internal/gb/audio.h index 93c76d997..3667145e1 100644 --- a/include/mgba/internal/gb/audio.h +++ b/include/mgba/internal/gb/audio.h @@ -236,7 +236,7 @@ void GBAudioWriteNR50(struct GBAudio* audio, uint8_t); void GBAudioWriteNR51(struct GBAudio* audio, uint8_t); void GBAudioWriteNR52(struct GBAudio* audio, uint8_t); -void GBAudioRun(struct GBAudio* audio, int32_t timestamp); +void GBAudioRun(struct GBAudio* audio, int32_t timestamp, int channels); void GBAudioUpdateFrame(struct GBAudio* audio); void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right); diff --git a/src/gb/audio.c b/src/gb/audio.c index 9051a3c5d..1601c734b 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -143,7 +143,7 @@ void GBAudioResizeBuffer(struct GBAudio* audio, size_t samples) { } void GBAudioWriteNR10(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x1); if (!_writeSweep(&audio->ch1.sweep, value)) { audio->playingCh1 = false; *audio->nr52 &= ~0x0001; @@ -151,13 +151,13 @@ void GBAudioWriteNR10(struct GBAudio* audio, uint8_t value) { } void GBAudioWriteNR11(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x1); _writeDuty(&audio->ch1.envelope, value); audio->ch1.control.length = 64 - audio->ch1.envelope.length; } void GBAudioWriteNR12(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x1); if (!_writeEnvelope(&audio->ch1.envelope, value, audio->style)) { audio->playingCh1 = false; *audio->nr52 &= ~0x0001; @@ -165,13 +165,13 @@ void GBAudioWriteNR12(struct GBAudio* audio, uint8_t value) { } void GBAudioWriteNR13(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x1); audio->ch1.control.frequency &= 0x700; audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value); } void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x1); audio->ch1.control.frequency &= 0xFF; audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8); bool wasStop = audio->ch1.control.stop; @@ -202,13 +202,13 @@ void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) { } void GBAudioWriteNR21(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x2); _writeDuty(&audio->ch2.envelope, value); audio->ch2.control.length = 64 - audio->ch2.envelope.length; } void GBAudioWriteNR22(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x2); if (!_writeEnvelope(&audio->ch2.envelope, value, audio->style)) { audio->playingCh2 = false; *audio->nr52 &= ~0x0002; @@ -216,13 +216,13 @@ void GBAudioWriteNR22(struct GBAudio* audio, uint8_t value) { } void GBAudioWriteNR23(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x2); audio->ch2.control.frequency &= 0x700; audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value); } void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x2); audio->ch2.control.frequency &= 0xFF; audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8); bool wasStop = audio->ch2.control.stop; @@ -249,7 +249,7 @@ void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) { } void GBAudioWriteNR30(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x4); audio->ch3.enable = GBAudioRegisterBankGetEnable(value); if (!audio->ch3.enable) { audio->playingCh3 = false; @@ -258,23 +258,23 @@ void GBAudioWriteNR30(struct GBAudio* audio, uint8_t value) { } void GBAudioWriteNR31(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x4); audio->ch3.length = 256 - value; } void GBAudioWriteNR32(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x4); audio->ch3.volume = GBAudioRegisterBankVolumeGetVolumeGB(value); } void GBAudioWriteNR33(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x4); audio->ch3.rate &= 0x700; audio->ch3.rate |= GBAudioRegisterControlGetRate(value); } void GBAudioWriteNR34(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x4); audio->ch3.rate &= 0xFF; audio->ch3.rate |= GBAudioRegisterControlGetRate(value << 8); bool wasStop = audio->ch3.stop; @@ -320,13 +320,13 @@ void GBAudioWriteNR34(struct GBAudio* audio, uint8_t value) { } void GBAudioWriteNR41(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x8); _writeDuty(&audio->ch4.envelope, value); audio->ch4.length = 64 - audio->ch4.envelope.length; } void GBAudioWriteNR42(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x8); if (!_writeEnvelope(&audio->ch4.envelope, value, audio->style)) { audio->playingCh4 = false; *audio->nr52 &= ~0x0008; @@ -334,14 +334,14 @@ void GBAudioWriteNR42(struct GBAudio* audio, uint8_t value) { } void GBAudioWriteNR43(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x8); audio->ch4.ratio = GBAudioRegisterNoiseFeedbackGetRatio(value); audio->ch4.frequency = GBAudioRegisterNoiseFeedbackGetFrequency(value); audio->ch4.power = GBAudioRegisterNoiseFeedbackGetPower(value); } void GBAudioWriteNR44(struct GBAudio* audio, uint8_t value) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x8); bool wasStop = audio->ch4.stop; audio->ch4.stop = GBAudioRegisterNoiseControlGetStop(value); if (!wasStop && audio->ch4.stop && audio->ch4.length && !(audio->frame & 1)) { @@ -465,25 +465,31 @@ void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate) { } } -void GBAudioRun(struct GBAudio* audio, int32_t timestamp) { +void GBAudioRun(struct GBAudio* audio, int32_t timestamp, int channels) { if (!audio->enable) { return; } - if (audio->playingCh1) { + if (audio->playingCh1 && (channels & 0x1)) { int period = 4 * (2048 - audio->ch1.control.frequency) * audio->timingFactor; - int32_t diff = (timestamp - audio->ch1.lastUpdate) / period; - audio->ch1.index = (audio->ch1.index + diff) & 7; - audio->ch1.lastUpdate += diff * period; - _updateSquareSample(&audio->ch1); + int32_t diff = timestamp - audio->ch1.lastUpdate; + if (diff >= period) { + diff /= period; + audio->ch1.index = (audio->ch1.index + diff) & 7; + audio->ch1.lastUpdate += diff * period; + _updateSquareSample(&audio->ch1); + } } - if (audio->playingCh2) { + if (audio->playingCh2 && (channels & 0x2)) { int period = 4 * (2048 - audio->ch2.control.frequency) * audio->timingFactor; - int32_t diff = (timestamp - audio->ch2.lastUpdate) / period; - audio->ch2.index = (audio->ch2.index + diff) & 7; - audio->ch2.lastUpdate += diff * period; - _updateSquareSample(&audio->ch2); + int32_t diff = timestamp - audio->ch2.lastUpdate; + if (diff >= period) { + diff /= period; + audio->ch2.index = (audio->ch2.index + diff) & 7; + audio->ch2.lastUpdate += diff * period; + _updateSquareSample(&audio->ch2); + } } - if (audio->playingCh3) { + if (audio->playingCh3 && (channels & 0x4)) { int cycles = 2 * (2048 - audio->ch3.rate) * audio->timingFactor; int32_t diff = timestamp - audio->ch3.nextUpdate; if (diff >= 0) { @@ -555,7 +561,7 @@ void GBAudioRun(struct GBAudio* audio, int32_t timestamp) { } } } - if (audio->playingCh4) { + if (audio->playingCh4 && (channels & 0x8)) { int32_t cycles = audio->ch4.ratio ? 2 * audio->ch4.ratio : 1; cycles <<= audio->ch4.frequency; cycles *= 8 * audio->timingFactor; @@ -583,7 +589,7 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { audio->skipFrame = false; return; } - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x7); int frame = (audio->frame + 1) & 7; audio->frame = frame; @@ -668,7 +674,7 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { } void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing)); + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0xF); int dcOffset = audio->style == GB_AUDIO_GBA ? 0 : -0x8; int sampleLeft = dcOffset; int sampleRight = dcOffset; diff --git a/src/gb/io.c b/src/gb/io.c index d03171bb4..b427f8729 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -403,7 +403,7 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) { case GB_REG_WAVE_D: case GB_REG_WAVE_E: case GB_REG_WAVE_F: - GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing)); + GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing), 0x4); if (!gb->audio.playingCh3 || gb->audio.style != GB_AUDIO_DMG) { gb->audio.ch3.wavedata8[address - GB_REG_WAVE_0] = value; } else if(gb->audio.ch3.readable) { @@ -608,7 +608,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) { case GB_REG_WAVE_E: case GB_REG_WAVE_F: if (gb->audio.playingCh3) { - GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing)); + GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing), 0x4); if (gb->audio.ch3.readable || gb->audio.style != GB_AUDIO_DMG) { return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1]; } else { @@ -622,7 +622,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) { if (gb->model < GB_MODEL_CGB) { mLOG(GB_IO, GAME_ERROR, "Reading from CGB register FF%02X in DMG mode", address); } else if (gb->audio.enable) { - GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing)); + GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing), 0x3); return (gb->audio.ch1.sample) | (gb->audio.ch2.sample << 4); } break; @@ -630,7 +630,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) { if (gb->model < GB_MODEL_CGB) { mLOG(GB_IO, GAME_ERROR, "Reading from CGB register FF%02X in DMG mode", address); } else if (gb->audio.enable) { - GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing)); + GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing), 0xC); return (gb->audio.ch3.sample) | (gb->audio.ch4.sample << 4); } break; diff --git a/src/gba/audio.c b/src/gba/audio.c index 4f3cfe3de..addac27ef 100644 --- a/src/gba/audio.c +++ b/src/gba/audio.c @@ -229,7 +229,7 @@ void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value) { bank = 1; } - GBAudioRun(&audio->psg, mTimingCurrentTime(audio->psg.timing)); + GBAudioRun(&audio->psg, mTimingCurrentTime(audio->psg.timing), 0x4); audio->psg.ch3.wavedata32[address | (bank * 4)] = value; } @@ -242,7 +242,7 @@ uint32_t GBAAudioReadWaveRAM(struct GBAAudio* audio, int address) { bank = 1; } - GBAudioRun(&audio->psg, mTimingCurrentTime(audio->psg.timing)); + GBAudioRun(&audio->psg, mTimingCurrentTime(audio->psg.timing), 0x4); return audio->psg.ch3.wavedata32[address | (bank * 4)]; } From cbbaa42641ca597124e9ded08cd282bd00c65ed1 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Jun 2022 02:14:47 -0700 Subject: [PATCH 014/102] CHANGES: Update --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 558807a83..25bb5172e 100644 --- a/CHANGES +++ b/CHANGES @@ -21,6 +21,7 @@ Emulation fixes: - GB: Copy logo from ROM if not running the BIOS intro (fixes mgba.io/i/2378) - GB Audio: Fix channel 1/2 reseting edge cases (fixes mgba.io/i/1925) - GB Audio: Properly apply per-model audio differences + - GB Audio: Revamp channel rendering - GB Memory: Add cursory cartridge open bus emulation (fixes mgba.io/i/2032) - GB Serialize: Fix loading MBC1 states that affect bank 0 (fixes mgba.io/i/2402) - GB Video: Draw SGB border pieces that overlap GB graphics (fixes mgba.io/i/1339) From cbbcf7478ebc9532d9e9a02e07c38bed19ef9de4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Jun 2022 02:13:16 -0700 Subject: [PATCH 015/102] GBA Audio: Adjust PSG sampling rate with SOUNDBIAS --- CHANGES | 1 + src/gb/audio.c | 2 +- src/gba/audio.c | 97 +++++++++++++++++++++++++++++-------------------- 3 files changed, 59 insertions(+), 41 deletions(-) diff --git a/CHANGES b/CHANGES index 25bb5172e..d781669d3 100644 --- a/CHANGES +++ b/CHANGES @@ -28,6 +28,7 @@ Emulation fixes: - GBA: Improve timing when not booting from BIOS - GBA: Fix expected entry point for multiboot ELFs (fixes mgba.io/i/2450) - GBA: Fix booting multiboot ROMs with no JOY entrypoint + - GBA Audio: Adjust PSG sampling rate with SOUNDBIAS - GBA BIOS: Work around IRQ handling hiccup in Mario & Luigi (fixes mgba.io/i/1059) - GBA BIOS: Initial HLE timing estimation of UnLz77 functions (fixes mgba.io/i/2141) - GBA DMA: Fix DMA source direction bits being cleared (fixes mgba.io/i/2410) diff --git a/src/gb/audio.c b/src/gb/audio.c index 1601c734b..b1a3f68dd 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -674,7 +674,6 @@ void GBAudioUpdateFrame(struct GBAudio* audio) { } void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) { - GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0xF); int dcOffset = audio->style == GB_AUDIO_GBA ? 0 : -0x8; int sampleLeft = dcOffset; int sampleRight = dcOffset; @@ -731,6 +730,7 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { struct GBAudio* audio = user; int16_t sampleLeft = 0; int16_t sampleRight = 0; + GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0xF); GBAudioSamplePSG(audio, &sampleLeft, &sampleRight); sampleLeft = (sampleLeft * audio->masterVolume * 6) >> 7; sampleRight = (sampleRight * audio->masterVolume * 6) >> 7; diff --git a/src/gba/audio.c b/src/gba/audio.c index addac27ef..05f062719 100644 --- a/src/gba/audio.c +++ b/src/gba/audio.c @@ -25,6 +25,7 @@ mLOG_DEFINE_CATEGORY(GBA_AUDIO, "GBA Audio", "gba.audio"); const unsigned GBA_AUDIO_SAMPLES = 2048; const int GBA_AUDIO_VOLUME_MAX = 0x100; +static const int SAMPLE_INTERVAL = GBA_ARM7TDMI_FREQUENCY / 0x8000; static const int CLOCKS_PER_FRAME = 0x800; static int _applyBias(struct GBAAudio* audio, int sample); @@ -218,6 +219,7 @@ void GBAAudioWriteSOUNDCNT_X(struct GBAAudio* audio, uint16_t value) { void GBAAudioWriteSOUNDBIAS(struct GBAAudio* audio, uint16_t value) { audio->soundbias = value; + audio->sampleInterval = 0x200 >> GBARegisterSOUNDBIASGetResolution(value); } void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value) { @@ -318,59 +320,74 @@ static int _applyBias(struct GBAAudio* audio, int sample) { static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { struct GBAAudio* audio = user; - int16_t sampleLeft = 0; - int16_t sampleRight = 0; - int psgShift = 4 - audio->volume; - GBAudioSamplePSG(&audio->psg, &sampleLeft, &sampleRight); - sampleLeft >>= psgShift; - sampleRight >>= psgShift; + int16_t samplesLeft[8]; + int16_t samplesRight[8]; + int32_t timestamp = mTimingCurrentTime(&audio->p->timing) - cyclesLate - SAMPLE_INTERVAL; + int sample; + for (sample = 0; sample * audio->sampleInterval < (int32_t) SAMPLE_INTERVAL; ++sample) { + int16_t sampleLeft = 0; + int16_t sampleRight = 0; + int psgShift = 4 - audio->volume; + GBAudioRun(&audio->psg, timestamp + (sample + 1) * audio->sampleInterval, 0xF); + GBAudioSamplePSG(&audio->psg, &sampleLeft, &sampleRight); + sampleLeft >>= psgShift; + sampleRight >>= psgShift; - if (audio->mixer) { - audio->mixer->step(audio->mixer); - } - if (!audio->externalMixing) { - if (!audio->forceDisableChA) { - if (audio->chALeft) { - sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA; + if (audio->mixer) { + audio->mixer->step(audio->mixer); + } + if (!audio->externalMixing) { + if (!audio->forceDisableChA) { + if (audio->chALeft) { + sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA; + } + + if (audio->chARight) { + sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA; + } } - if (audio->chARight) { - sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA; + if (!audio->forceDisableChB) { + if (audio->chBLeft) { + sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB; + } + + if (audio->chBRight) { + sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB; + } } } - if (!audio->forceDisableChB) { - if (audio->chBLeft) { - sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB; - } - - if (audio->chBRight) { - sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB; - } - } + sampleLeft = _applyBias(audio, sampleLeft); + sampleRight = _applyBias(audio, sampleRight); + samplesLeft[sample] = sampleLeft; + samplesRight[sample] = sampleRight; } - sampleLeft = _applyBias(audio, sampleLeft); - sampleRight = _applyBias(audio, sampleRight); - mCoreSyncLockAudio(audio->p->sync); unsigned produced; - if ((size_t) blip_samples_avail(audio->psg.left) < audio->samples) { - blip_add_delta(audio->psg.left, audio->clock, sampleLeft - audio->lastLeft); - blip_add_delta(audio->psg.right, audio->clock, sampleRight - audio->lastRight); - audio->lastLeft = sampleLeft; - audio->lastRight = sampleRight; - audio->clock += audio->sampleInterval; - if (audio->clock >= CLOCKS_PER_FRAME) { - blip_end_frame(audio->psg.left, CLOCKS_PER_FRAME); - blip_end_frame(audio->psg.right, CLOCKS_PER_FRAME); - audio->clock -= CLOCKS_PER_FRAME; + int i; + for (i = 0; i < sample; ++i) { + int16_t sampleLeft = samplesLeft[i]; + int16_t sampleRight = samplesRight[i]; + if ((size_t) blip_samples_avail(audio->psg.left) < audio->samples) { + blip_add_delta(audio->psg.left, audio->clock, sampleLeft - audio->lastLeft); + blip_add_delta(audio->psg.right, audio->clock, sampleRight - audio->lastRight); + audio->lastLeft = sampleLeft; + audio->lastRight = sampleRight; + audio->clock += audio->sampleInterval; + if (audio->clock >= CLOCKS_PER_FRAME) { + blip_end_frame(audio->psg.left, CLOCKS_PER_FRAME); + blip_end_frame(audio->psg.right, CLOCKS_PER_FRAME); + audio->clock -= CLOCKS_PER_FRAME; + } } } - produced = blip_samples_avail(audio->psg.left); + // TODO: Post all frames if (audio->p->stream && audio->p->stream->postAudioFrame) { - audio->p->stream->postAudioFrame(audio->p->stream, sampleLeft, sampleRight); + audio->p->stream->postAudioFrame(audio->p->stream, samplesLeft[sample - 1], samplesRight[sample - 1]); } + produced = blip_samples_avail(audio->psg.left); bool wait = produced >= audio->samples; if (!mCoreSyncProduceAudio(audio->p->sync, audio->psg.left, audio->samples)) { // Interrupted @@ -381,7 +398,7 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { audio->p->stream->postAudioBuffer(audio->p->stream, audio->psg.left, audio->psg.right); } - mTimingSchedule(timing, &audio->sampleEvent, audio->sampleInterval - cyclesLate); + mTimingSchedule(timing, &audio->sampleEvent, SAMPLE_INTERVAL - cyclesLate); } void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state) { From 29dbb55c8023c533bc7c97f92b67a4282c08f87f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Jun 2022 02:32:21 -0700 Subject: [PATCH 016/102] GBA I/O: Unstub SOUNDBIAS --- src/gba/io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gba/io.c b/src/gba/io.c index 0cd3c4e25..14c05b0f5 100644 --- a/src/gba/io.c +++ b/src/gba/io.c @@ -416,6 +416,7 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) { value |= gba->memory.io[REG_SOUNDCNT_X >> 1] & 0xF; break; case REG_SOUNDBIAS: + value &= 0xC3FE; GBAAudioWriteSOUNDBIAS(&gba->audio, value); break; @@ -842,7 +843,6 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) { gba->memory.io[REG_JOYSTAT >> 1] &= ~JOYSTAT_RECV; break; - case REG_SOUNDBIAS: case REG_POSTFLG: mLOG(GBA_IO, STUB, "Stub I/O register read: %03x", address); break; @@ -878,6 +878,7 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) { case REG_SOUND4CNT_LO: case REG_SOUND4CNT_HI: case REG_SOUNDCNT_LO: + case REG_SOUNDBIAS: if (!GBAudioEnableIsEnable(gba->memory.io[REG_SOUNDCNT_X >> 1])) { // TODO: Is writing allowed when the circuit is disabled? return 0; From 3c0d9f719718a3f547cbac5d181ec46b9365dbb9 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Jun 2022 18:40:53 -0700 Subject: [PATCH 017/102] GBA Audio: Sample FIFOs at SOUNDBIAS-set frequency --- CHANGES | 1 + include/mgba/internal/gba/audio.h | 2 +- include/mgba/internal/gba/serialize.h | 13 ++++++-- src/gba/audio.c | 46 ++++++++++++++++++++------- 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/CHANGES b/CHANGES index d781669d3..302e1685b 100644 --- a/CHANGES +++ b/CHANGES @@ -29,6 +29,7 @@ Emulation fixes: - GBA: Fix expected entry point for multiboot ELFs (fixes mgba.io/i/2450) - GBA: Fix booting multiboot ROMs with no JOY entrypoint - GBA Audio: Adjust PSG sampling rate with SOUNDBIAS + - GBA Audio: Sample FIFOs at SOUNDBIAS-set frequency - GBA BIOS: Work around IRQ handling hiccup in Mario & Luigi (fixes mgba.io/i/1059) - GBA BIOS: Initial HLE timing estimation of UnLz77 functions (fixes mgba.io/i/2141) - GBA DMA: Fix DMA source direction bits being cleared (fixes mgba.io/i/2410) diff --git a/include/mgba/internal/gba/audio.h b/include/mgba/internal/gba/audio.h index c9fab3ae1..2bf6c14a6 100644 --- a/include/mgba/internal/gba/audio.h +++ b/include/mgba/internal/gba/audio.h @@ -34,7 +34,7 @@ struct GBAAudioFIFO { uint32_t internalSample; int internalRemaining; int dmaSource; - int8_t sample; + int8_t samples[8]; }; DECL_BITFIELD(GBARegisterSOUNDCNT_HI, uint16_t); diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index 364563195..20d0719ab 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -224,7 +224,10 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * 0x00320 - 0x00323: Next IRQ event * 0x00324 - 0x00327: Interruptable BIOS stall cycles * 0x00328 - 0x00367: Matrix memory mapping table - * 0x00368 - 0x003FF: Reserved (leave zero) + * 0x00368 - 0x0036F: Reserved (leave zero) + * 0x00370 - 0x00377: Audio FIFO A samples + * 0x00378 - 0x0037F: Audio FIFO B samples + * 0x00380 - 0x003FF: Reserved (leave zero) * 0x00400 - 0x007FF: I/O memory * 0x00800 - 0x00BFF: Palette * 0x00C00 - 0x00FFF: OAM @@ -381,8 +384,14 @@ struct GBASerializedState { int32_t biosStall; uint32_t matrixMappings[16]; + uint32_t reservedMatrix[2]; - uint32_t reserved[38]; + struct { + int8_t chA[8]; + int8_t chB[8]; + } samples; + + uint32_t reserved[32]; uint16_t io[SIZE_IO >> 1]; uint16_t pram[SIZE_PALETTE_RAM >> 1]; diff --git a/src/gba/audio.c b/src/gba/audio.c index 05f062719..8cd58dc78 100644 --- a/src/gba/audio.c +++ b/src/gba/audio.c @@ -67,13 +67,16 @@ void GBAAudioReset(struct GBAAudio* audio) { audio->chA.internalSample = 0; audio->chA.internalRemaining = 0; memset(audio->chA.fifo, 0, sizeof(audio->chA.fifo)); - audio->chA.sample = 0; audio->chB.fifoWrite = 0; audio->chB.fifoRead = 0; audio->chB.internalSample = 0; audio->chB.internalRemaining = 0; memset(audio->chB.fifo, 0, sizeof(audio->chB.fifo)); - audio->chB.sample = 0; + int i; + for (i = 0; i < 8; ++i) { + audio->chA.samples[i] = 0; + audio->chB.samples[i] = 0; + } audio->sampleRate = 0x8000; audio->soundbias = 0x200; audio->volume = 0; @@ -301,7 +304,17 @@ void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles) { channel->fifoRead = 0; } } - channel->sample = channel->internalSample; + int32_t until = mTimingUntil(&audio->p->timing, &audio->sampleEvent) - 1; + int bits = 1 << GBARegisterSOUNDBIASGetResolution(audio->soundbias); + until += 1 << (9 - GBARegisterSOUNDBIASGetResolution(audio->soundbias)); + until >>= 9 - GBARegisterSOUNDBIASGetResolution(audio->soundbias); + int i; + for (i = bits - until; i < bits; ++i) { + if (i < 0 || i >= bits) { + abort(); + } + channel->samples[i] = channel->internalSample; + } if (channel->internalRemaining) { channel->internalSample >>= 8; --channel->internalRemaining; @@ -339,21 +352,21 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { if (!audio->externalMixing) { if (!audio->forceDisableChA) { if (audio->chALeft) { - sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA; + sampleLeft += (audio->chA.samples[sample] << 2) >> !audio->volumeChA; } if (audio->chARight) { - sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA; + sampleRight += (audio->chA.samples[sample] << 2) >> !audio->volumeChA; } } if (!audio->forceDisableChB) { if (audio->chBLeft) { - sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB; + sampleLeft += (audio->chB.samples[sample] << 2) >> !audio->volumeChB; } if (audio->chBRight) { - sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB; + sampleRight += (audio->chB.samples[sample] << 2) >> !audio->volumeChB; } } } @@ -364,12 +377,19 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { samplesRight[sample] = sampleRight; } + memset(audio->chA.samples, audio->chA.samples[sample - 1], sizeof(audio->chA.samples)); + memset(audio->chB.samples, audio->chB.samples[sample - 1], sizeof(audio->chB.samples)); + mCoreSyncLockAudio(audio->p->sync); unsigned produced; + int32_t sampleSumLeft = 0; + int32_t sampleSumRight = 0; int i; for (i = 0; i < sample; ++i) { int16_t sampleLeft = samplesLeft[i]; int16_t sampleRight = samplesRight[i]; + sampleSumLeft += sampleLeft; + sampleSumRight += sampleRight; if ((size_t) blip_samples_avail(audio->psg.left) < audio->samples) { blip_add_delta(audio->psg.left, audio->clock, sampleLeft - audio->lastLeft); blip_add_delta(audio->psg.right, audio->clock, sampleRight - audio->lastRight); @@ -385,7 +405,9 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { } // TODO: Post all frames if (audio->p->stream && audio->p->stream->postAudioFrame) { - audio->p->stream->postAudioFrame(audio->p->stream, samplesLeft[sample - 1], samplesRight[sample - 1]); + sampleSumLeft /= sample; + sampleSumRight /= sample; + audio->p->stream->postAudioFrame(audio->p->stream, sampleSumLeft, sampleSumRight); } produced = blip_samples_avail(audio->psg.left); bool wait = produced >= audio->samples; @@ -406,8 +428,8 @@ void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* STORE_32(audio->chA.internalSample, 0, &state->audio.internalA); STORE_32(audio->chB.internalSample, 0, &state->audio.internalB); - state->audio.sampleA = audio->chA.sample; - state->audio.sampleB = audio->chB.sample; + memcpy(state->samples.chA, audio->chA.samples, sizeof(audio->chA.samples)); + memcpy(state->samples.chB, audio->chB.samples, sizeof(audio->chB.samples)); int readA = audio->chA.fifoRead; int readB = audio->chB.fifoRead; @@ -453,8 +475,8 @@ void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState LOAD_32(audio->chA.internalSample, 0, &state->audio.internalA); LOAD_32(audio->chB.internalSample, 0, &state->audio.internalB); - audio->chA.sample = state->audio.sampleA; - audio->chB.sample = state->audio.sampleB; + memcpy(audio->chA.samples, state->samples.chA, sizeof(audio->chA.samples)); + memcpy(audio->chB.samples, state->samples.chB, sizeof(audio->chB.samples)); int readA = 0; int readB = 0; From 0a674dd377a091f5d07874c4e0cff58d73fb325c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Jun 2022 20:18:49 -0700 Subject: [PATCH 018/102] Updater: Fix stub MSVC build --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 95e714e81..eafaaf82b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -957,7 +957,7 @@ if(BUILD_UPDATER) ${CMAKE_CURRENT_SOURCE_DIR}/src/feature/updater.c ${CMAKE_CURRENT_SOURCE_DIR}/src/feature/updater-main.c) target_link_libraries(updater-stub ${OS_LIB} ${PLATFORM_LIBRARY}) - set_target_properties(updater-stub PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FUNCTION_DEFINES}") + set_target_properties(updater-stub PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FUNCTION_DEFINES};BUILD_STATIC") if(MSVC) set_target_properties(updater-stub PROPERTIES LINK_FLAGS /ENTRY:mainCRTStartup) else() From 818314a6fd27238eb446b2432069812470dc0694 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Jun 2022 22:13:00 -0700 Subject: [PATCH 019/102] GBA I/O: SOUNDBIAS is readable when sound is off (fixes #2541) --- src/gba/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gba/io.c b/src/gba/io.c index 14c05b0f5..34e7471bb 100644 --- a/src/gba/io.c +++ b/src/gba/io.c @@ -878,7 +878,6 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) { case REG_SOUND4CNT_LO: case REG_SOUND4CNT_HI: case REG_SOUNDCNT_LO: - case REG_SOUNDBIAS: if (!GBAudioEnableIsEnable(gba->memory.io[REG_SOUNDCNT_X >> 1])) { // TODO: Is writing allowed when the circuit is disabled? return 0; @@ -898,6 +897,7 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) { case REG_BLDALPHA: case REG_SOUNDCNT_HI: case REG_SOUNDCNT_X: + case REG_SOUNDBIAS: case REG_DMA0CNT_HI: case REG_DMA1CNT_HI: case REG_DMA2CNT_HI: From c19457aa4b824ced62d87738a9b1b79aee69fe0a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Jun 2022 22:18:05 -0700 Subject: [PATCH 020/102] GBA Overrides: Add Game Boy Wars Advance 1+2 entry (fixes #2540) --- src/gba/overrides.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gba/overrides.c b/src/gba/overrides.c index 2e0ce10de..823957d5c 100644 --- a/src/gba/overrides.c +++ b/src/gba/overrides.c @@ -70,6 +70,9 @@ static const struct GBACartridgeOverride _overrides[] = { { "AI2E", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE, false }, { "AI2P", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE, false }, + // Game Boy Wars Advance 1+2 + { "BGWJ", SAVEDATA_FLASH1M, HW_NONE, IDLE_LOOP_NONE, false }, + // Golden Sun: The Lost Age { "AGFE", SAVEDATA_FLASH512, HW_NONE, 0x801353A, false }, From 46b59268d384f634078352e93ad6a39b7673e6de Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Jun 2022 23:26:15 -0700 Subject: [PATCH 021/102] GB Audio: Optimize channel 4 --- src/gb/audio.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/gb/audio.c b/src/gb/audio.c index b1a3f68dd..7a1fe60bf 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -568,13 +568,24 @@ void GBAudioRun(struct GBAudio* audio, int32_t timestamp, int channels) { int32_t last = 0; int32_t diff = timestamp - audio->ch4.lastEvent; + int samples = 0; + int positiveSamples = 0; + int lsb; + int coeff = 0x60; + if (!audio->ch4.power) { + coeff <<= 8; + } for (; last + cycles <= diff; last += cycles) { - int lsb = audio->ch4.lfsr & 1; - audio->ch4.sample = lsb * audio->ch4.envelope.currentVolume; - ++audio->ch4.nSamples; - audio->ch4.samples += audio->ch4.sample; + lsb = audio->ch4.lfsr & 1; audio->ch4.lfsr >>= 1; - audio->ch4.lfsr ^= (lsb * 0x60) << (audio->ch4.power ? 0 : 8); + audio->ch4.lfsr ^= lsb * coeff; + ++samples; + positiveSamples += lsb; + } + if (samples) { + audio->ch4.sample = lsb * audio->ch4.envelope.currentVolume; + audio->ch4.nSamples += samples; + audio->ch4.samples += positiveSamples * audio->ch4.envelope.currentVolume; } audio->ch4.lastEvent += last; From f4217a7a77d5208f410a8b0eddd9706094e1607c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 3 Jun 2022 15:38:38 -0700 Subject: [PATCH 022/102] GBA Video: Use memset instead of manually assigning --- src/gba/renderers/video-software.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c index 35737a9e3..ef82fec93 100644 --- a/src/gba/renderers/video-software.c +++ b/src/gba/renderers/video-software.c @@ -141,30 +141,11 @@ static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer) { for (i = 0; i < 4; ++i) { struct GBAVideoSoftwareBackground* bg = &softwareRenderer->bg[i]; + memset(bg, 0, sizeof(*bg)); bg->index = i; - bg->enabled = 0; - bg->priority = 0; - bg->charBase = 0; - bg->mosaic = 0; - bg->multipalette = 0; - bg->screenBase = 0; - bg->overflow = 0; - bg->size = 0; - bg->target1 = 0; - bg->target2 = 0; - bg->x = 0; - bg->y = 0; - bg->refx = 0; - bg->refy = 0; bg->dx = 256; - bg->dmx = 0; - bg->dy = 0; bg->dmy = 256; - bg->sx = 0; - bg->sy = 0; bg->yCache = -1; - bg->offsetX = 0; - bg->offsetY = 0; } } From 9f5267e24eda5e74438212ab6918261b62661054 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 3 Jun 2022 22:36:19 -0700 Subject: [PATCH 023/102] GBA Audio: Claw back some performance --- include/mgba/internal/gba/audio.h | 3 ++- include/mgba/internal/gba/serialize.h | 10 ++++---- src/gb/audio.c | 35 +++++++++++++-------------- src/gba/audio.c | 11 +++------ 4 files changed, 28 insertions(+), 31 deletions(-) diff --git a/include/mgba/internal/gba/audio.h b/include/mgba/internal/gba/audio.h index 2bf6c14a6..65336b299 100644 --- a/include/mgba/internal/gba/audio.h +++ b/include/mgba/internal/gba/audio.h @@ -16,6 +16,7 @@ CXX_GUARD_START #include #define GBA_AUDIO_FIFO_SIZE 8 +#define GBA_MAX_SAMPLES 16 #define MP2K_MAGIC 0x68736D53 #define MP2K_MAX_SOUND_CHANNELS 12 @@ -34,7 +35,7 @@ struct GBAAudioFIFO { uint32_t internalSample; int internalRemaining; int dmaSource; - int8_t samples[8]; + int8_t samples[GBA_MAX_SAMPLES]; }; DECL_BITFIELD(GBARegisterSOUNDCNT_HI, uint16_t); diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index 20d0719ab..6ab814859 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -225,8 +225,8 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * 0x00324 - 0x00327: Interruptable BIOS stall cycles * 0x00328 - 0x00367: Matrix memory mapping table * 0x00368 - 0x0036F: Reserved (leave zero) - * 0x00370 - 0x00377: Audio FIFO A samples - * 0x00378 - 0x0037F: Audio FIFO B samples + * 0x00370 - 0x0037F: Audio FIFO A samples + * 0x00380 - 0x0038F: Audio FIFO B samples * 0x00380 - 0x003FF: Reserved (leave zero) * 0x00400 - 0x007FF: I/O memory * 0x00800 - 0x00BFF: Palette @@ -387,11 +387,11 @@ struct GBASerializedState { uint32_t reservedMatrix[2]; struct { - int8_t chA[8]; - int8_t chB[8]; + int8_t chA[16]; + int8_t chB[16]; } samples; - uint32_t reserved[32]; + uint32_t reserved[28]; uint16_t io[SIZE_IO >> 1]; uint16_t pram[SIZE_PALETTE_RAM >> 1]; diff --git a/src/gb/audio.c b/src/gb/audio.c index 7a1fe60bf..19f265c47 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -566,29 +566,28 @@ void GBAudioRun(struct GBAudio* audio, int32_t timestamp, int channels) { cycles <<= audio->ch4.frequency; cycles *= 8 * audio->timingFactor; - int32_t last = 0; int32_t diff = timestamp - audio->ch4.lastEvent; - int samples = 0; - int positiveSamples = 0; - int lsb; - int coeff = 0x60; - if (!audio->ch4.power) { - coeff <<= 8; - } - for (; last + cycles <= diff; last += cycles) { - lsb = audio->ch4.lfsr & 1; - audio->ch4.lfsr >>= 1; - audio->ch4.lfsr ^= lsb * coeff; - ++samples; - positiveSamples += lsb; - } - if (samples) { + if (diff >= cycles) { + int32_t last; + int samples = 0; + int positiveSamples = 0; + int lsb; + int coeff = 0x60; + if (!audio->ch4.power) { + coeff <<= 8; + } + for (last = 0; last + cycles <= diff; last += cycles) { + lsb = audio->ch4.lfsr & 1; + audio->ch4.lfsr >>= 1; + audio->ch4.lfsr ^= lsb * coeff; + ++samples; + positiveSamples += lsb; + } audio->ch4.sample = lsb * audio->ch4.envelope.currentVolume; audio->ch4.nSamples += samples; audio->ch4.samples += positiveSamples * audio->ch4.envelope.currentVolume; + audio->ch4.lastEvent += last; } - - audio->ch4.lastEvent += last; } } diff --git a/src/gba/audio.c b/src/gba/audio.c index 8cd58dc78..00c20bd46 100644 --- a/src/gba/audio.c +++ b/src/gba/audio.c @@ -25,7 +25,7 @@ mLOG_DEFINE_CATEGORY(GBA_AUDIO, "GBA Audio", "gba.audio"); const unsigned GBA_AUDIO_SAMPLES = 2048; const int GBA_AUDIO_VOLUME_MAX = 0x100; -static const int SAMPLE_INTERVAL = GBA_ARM7TDMI_FREQUENCY / 0x8000; +static const int SAMPLE_INTERVAL = GBA_ARM7TDMI_FREQUENCY / 0x4000; static const int CLOCKS_PER_FRAME = 0x800; static int _applyBias(struct GBAAudio* audio, int sample); @@ -305,14 +305,11 @@ void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles) { } } int32_t until = mTimingUntil(&audio->p->timing, &audio->sampleEvent) - 1; - int bits = 1 << GBARegisterSOUNDBIASGetResolution(audio->soundbias); + int bits = 2 << GBARegisterSOUNDBIASGetResolution(audio->soundbias); until += 1 << (9 - GBARegisterSOUNDBIASGetResolution(audio->soundbias)); until >>= 9 - GBARegisterSOUNDBIASGetResolution(audio->soundbias); int i; for (i = bits - until; i < bits; ++i) { - if (i < 0 || i >= bits) { - abort(); - } channel->samples[i] = channel->internalSample; } if (channel->internalRemaining) { @@ -333,8 +330,8 @@ static int _applyBias(struct GBAAudio* audio, int sample) { static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { struct GBAAudio* audio = user; - int16_t samplesLeft[8]; - int16_t samplesRight[8]; + int16_t samplesLeft[GBA_MAX_SAMPLES]; + int16_t samplesRight[GBA_MAX_SAMPLES]; int32_t timestamp = mTimingCurrentTime(&audio->p->timing) - cyclesLate - SAMPLE_INTERVAL; int sample; for (sample = 0; sample * audio->sampleInterval < (int32_t) SAMPLE_INTERVAL; ++sample) { From 3c228dad60a214d5578b5670ff673abd7a07f1e8 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 3 Jun 2022 23:45:34 -0700 Subject: [PATCH 024/102] Qt: Fix games not displaying on macOS after first run --- src/platform/qt/DisplayGL.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 678f9d612..221acffc0 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -203,6 +203,8 @@ void DisplayGL::startDrawing(std::shared_ptr controller) { QMetaObject::invokeMethod(m_painter.get(), "start"); if (!m_gl) { setUpdatesEnabled(false); + } else { + show(); } } @@ -265,6 +267,9 @@ void DisplayGL::stopDrawing() { m_hasStarted = false; CoreController::Interrupter interrupter(m_context); QMetaObject::invokeMethod(m_painter.get(), "stop", Qt::BlockingQueuedConnection); + if (m_gl) { + hide(); + } setUpdatesEnabled(true); } m_context.reset(); @@ -274,9 +279,7 @@ void DisplayGL::pauseDrawing() { if (m_hasStarted) { m_isDrawing = false; QMetaObject::invokeMethod(m_painter.get(), "pause", Qt::BlockingQueuedConnection); -#ifndef Q_OS_MAC setUpdatesEnabled(true); -#endif } } @@ -284,11 +287,9 @@ void DisplayGL::unpauseDrawing() { if (m_hasStarted) { m_isDrawing = true; QMetaObject::invokeMethod(m_painter.get(), "unpause", Qt::BlockingQueuedConnection); -#ifndef Q_OS_MAC if (!m_gl) { setUpdatesEnabled(false); } -#endif } } From e87ba99140fd5580279e45c9d7a18474b704e305 Mon Sep 17 00:00:00 2001 From: Celeste Wouters Date: Fri, 14 May 2021 22:09:43 +0200 Subject: [PATCH 025/102] GBA Memory: update the renderer on rawWrite{16,32}/GBAPatch{16,32} rawWrite{16,32}/GBAPatch{16, 32} is used by the memory editor on Qt, and changes to the VRAM area there were not reflected on the graphical output, palette or OAM writes are. This fixes this inconsistency. --- src/gba/memory.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gba/memory.c b/src/gba/memory.c index fddef9223..8bacf4a79 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -1239,9 +1239,13 @@ void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* o if ((address & 0x0001FFFF) < SIZE_VRAM) { LOAD_32(oldValue, address & 0x0001FFFC, gba->video.vram); STORE_32(value, address & 0x0001FFFC, gba->video.vram); + gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFC); + gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC) | 2); } else { LOAD_32(oldValue, address & 0x00017FFC, gba->video.vram); STORE_32(value, address & 0x00017FFC, gba->video.vram); + gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x00017FFC); + gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC) | 2); } break; case REGION_OAM: @@ -1308,9 +1312,11 @@ void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* o if ((address & 0x0001FFFF) < SIZE_VRAM) { LOAD_16(oldValue, address & 0x0001FFFE, gba->video.vram); STORE_16(value, address & 0x0001FFFE, gba->video.vram); + gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE); } else { LOAD_16(oldValue, address & 0x00017FFE, gba->video.vram); STORE_16(value, address & 0x00017FFE, gba->video.vram); + gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x00017FFE); } break; case REGION_OAM: From d6accc4ef6d8cc040f022d5856005995fb4d4e22 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 5 Jun 2022 01:28:58 -0700 Subject: [PATCH 026/102] Scripting: Add calling functions with lists --- include/mgba/script/types.h | 1 + src/script/engines/lua.c | 99 ++++++++++++++++++++++++++++++++++--- src/script/test/lua.c | 33 +++++++++++++ src/script/test/types.c | 70 +++++++++++++++++++++++++- 4 files changed, 196 insertions(+), 7 deletions(-) diff --git a/include/mgba/script/types.h b/include/mgba/script/types.h index fd7dbe5d8..489b5eee4 100644 --- a/include/mgba/script/types.h +++ b/include/mgba/script/types.h @@ -108,6 +108,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_CMP_F64(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_F64, TYPE) #define mSCRIPT_TYPE_CMP_STR(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_STR, TYPE) #define mSCRIPT_TYPE_CMP_CHARP(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_CHARP, TYPE) +#define mSCRIPT_TYPE_CMP_LIST(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_LIST, TYPE) #define mSCRIPT_TYPE_CMP_PTR(TYPE) ((TYPE)->base >= mSCRIPT_TYPE_OPAQUE) #define mSCRIPT_TYPE_CMP_WRAPPER(TYPE) (true) #define mSCRIPT_TYPE_CMP_S(STRUCT) mSCRIPT_TYPE_MS_S(STRUCT)->name == _mSCRIPT_FIELD_NAME diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index 5c8906531..db1178993 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -30,7 +30,7 @@ static bool _luaPushFrame(struct mScriptEngineContextLua*, struct mScriptList*, static bool _luaPopFrame(struct mScriptEngineContextLua*, struct mScriptList*); static bool _luaInvoke(struct mScriptEngineContextLua*, struct mScriptFrame*); -static struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext); +static struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext, bool pop); static bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue*); static void _luaDeref(struct mScriptValue*); @@ -186,7 +186,7 @@ bool _luaIsScript(struct mScriptEngineContext* ctx, const char* name, struct VFi struct mScriptValue* _luaGetGlobal(struct mScriptEngineContext* ctx, const char* name) { struct mScriptEngineContextLua* luaContext = (struct mScriptEngineContextLua*) ctx; lua_getglobal(luaContext->lua, name); - return _luaCoerce(luaContext); + return _luaCoerce(luaContext, true); } bool _luaSetGlobal(struct mScriptEngineContext* ctx, const char* name, struct mScriptValue* value) { @@ -212,7 +212,83 @@ struct mScriptValue* _luaCoerceFunction(struct mScriptEngineContextLua* luaConte return value; } -struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext) { +struct mScriptValue* _luaCoerceTable(struct mScriptEngineContextLua* luaContext) { + struct mScriptValue* table = mScriptValueAlloc(mSCRIPT_TYPE_MS_TABLE); + bool isList = true; + + lua_pushnil(luaContext->lua); + while (lua_next(luaContext->lua, -2) != 0) { + struct mScriptValue* value = NULL; + int type = lua_type(luaContext->lua, -1); + switch (type) { + case LUA_TNUMBER: + case LUA_TBOOLEAN: + case LUA_TSTRING: + case LUA_TFUNCTION: + value = _luaCoerce(luaContext, true); + break; + default: + // Don't let values be something that could contain themselves + break; + } + if (!value) { + lua_pop(luaContext->lua, 3); + mScriptValueDeref(table); + return false; + } + + struct mScriptValue* key = NULL; + type = lua_type(luaContext->lua, -1); + switch (type) { + case LUA_TBOOLEAN: + case LUA_TSTRING: + isList = false; + // Fall through + case LUA_TNUMBER: + key = _luaCoerce(luaContext, false); + break; + default: + // Limit keys to hashable types + break; + } + + if (!key) { + lua_pop(luaContext->lua, 2); + mScriptValueDeref(table); + return false; + } + mScriptTableInsert(table, key, value); + mScriptValueDeref(key); + mScriptValueDeref(value); + } + lua_pop(luaContext->lua, 1); + + size_t len = mScriptTableSize(table); + if (!isList || !len) { + return table; + } + + struct mScriptValue* list = mScriptValueAlloc(mSCRIPT_TYPE_MS_LIST); + size_t i; + for (i = 1; i <= len; ++i) { + struct mScriptValue* value = mScriptTableLookup(table, &mSCRIPT_MAKE_S64(i)); + if (!value) { + mScriptValueDeref(list); + return table; + } + mScriptValueWrap(value, mScriptListAppend(list->value.list)); + } + if (i != len + 1) { + mScriptValueDeref(list); + mScriptContextFillPool(luaContext->d.context, table); + return table; + } + mScriptValueDeref(table); + mScriptContextFillPool(luaContext->d.context, list); + return list; +} + +struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext, bool pop) { if (lua_isnone(luaContext->lua, -1)) { lua_pop(luaContext->lua, 1); return NULL; @@ -244,7 +320,16 @@ struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext) { break; case LUA_TFUNCTION: // This function pops the value internally via luaL_ref + if (!pop) { + break; + } return _luaCoerceFunction(luaContext); + case LUA_TTABLE: + // This function pops the value internally via luaL_ref + if (!pop) { + break; + } + return _luaCoerceTable(luaContext); case LUA_TUSERDATA: if (!lua_getmetatable(luaContext->lua, -1)) { break; @@ -259,7 +344,9 @@ struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext) { value = mScriptContextAccessWeakref(luaContext->d.context, value); break; } - lua_pop(luaContext->lua, 1); + if (pop) { + lua_pop(luaContext->lua, 1); + } return value; } @@ -467,7 +554,7 @@ bool _luaPopFrame(struct mScriptEngineContextLua* luaContext, struct mScriptList if (frame) { int i; for (i = 0; i < count; ++i) { - struct mScriptValue* value = _luaCoerce(luaContext); + struct mScriptValue* value = _luaCoerce(luaContext, true); if (!value) { ok = false; break; @@ -640,7 +727,7 @@ int _luaSetObject(lua_State* lua) { char key[MAX_KEY_SIZE]; const char* keyPtr = lua_tostring(lua, -2); struct mScriptValue* obj = lua_touserdata(lua, -3); - struct mScriptValue* val = _luaCoerce(luaContext); + struct mScriptValue* val = _luaCoerce(luaContext, true); if (!keyPtr) { lua_pop(lua, 2); diff --git a/src/script/test/lua.c b/src/script/test/lua.c index 71b719966..bf3bf099a 100644 --- a/src/script/test/lua.c +++ b/src/script/test/lua.c @@ -61,8 +61,22 @@ static void testV1(struct Test* a, int b) { a->i += b; } +static int32_t sum(struct mScriptList* list) { + int32_t sum = 0; + size_t i; + for (i = 0; i < mScriptListSize(list); ++i) { + struct mScriptValue value; + if (!mScriptCast(mSCRIPT_TYPE_MS_S32, mScriptListGetPointer(list, i), &value)) { + continue; + } + sum += value.value.s32; + } + return sum; +} + mSCRIPT_BIND_FUNCTION(boundIdentityInt, S32, identityInt, 1, S32, a); mSCRIPT_BIND_FUNCTION(boundAddInts, S32, addInts, 2, S32, a, S32, b); +mSCRIPT_BIND_FUNCTION(boundSum, S32, sum, 1, LIST, list); mSCRIPT_DECLARE_STRUCT(Test); mSCRIPT_DECLARE_STRUCT_D_METHOD(Test, S32, ifn0, 0); @@ -619,6 +633,24 @@ M_TEST_DEFINE(tableIterate) { mScriptContextDeinit(&context); } +M_TEST_DEFINE(callList) { + SETUP_LUA; + + struct mScriptValue a = mSCRIPT_MAKE_S32(6); + struct mScriptValue* val; + + assert_true(lua->setGlobal(lua, "sum", &boundSum)); + TEST_PROGRAM("a = sum({1, 2, 3})"); + assert_null(lua->getError(lua)); + + val = lua->getGlobal(lua, "a"); + assert_non_null(val); + assert_true(mSCRIPT_TYPE_MS_S32->equal(&a, val)); + mScriptValueDeref(val); + + mScriptContextDeinit(&context); +} + M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua, cmocka_unit_test(create), cmocka_unit_test(loadGood), @@ -634,4 +666,5 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptLua, cmocka_unit_test(errorReporting), cmocka_unit_test(tableLookup), cmocka_unit_test(tableIterate), + cmocka_unit_test(callList), ) diff --git a/src/script/test/types.c b/src/script/test/types.c index 45a9a2d25..9fa83a8a5 100644 --- a/src/script/test/types.c +++ b/src/script/test/types.c @@ -52,6 +52,30 @@ static int isHello(const char* str) { return strcmp(str, "hello") == 0; } +static int isSequential(struct mScriptList* list) { + int last; + if (mScriptListSize(list) == 0) { + return true; + } + size_t i; + for (i = 0; i < mScriptListSize(list); ++i) { + struct mScriptValue* value = mScriptListGetPointer(list, i); + struct mScriptValue intValue; + if (!mScriptCast(mSCRIPT_TYPE_MS_S32, value, &intValue)) { + return false; + } + if (!i) { + last = intValue.value.s32; + } else { + if (intValue.value.s32 != last + 1) { + return false; + } + ++last; + } + } + return true; +} + mSCRIPT_BIND_FUNCTION(boundVoidOne, S32, voidOne, 0); mSCRIPT_BIND_VOID_FUNCTION(boundDiscard, discard, 1, S32, ignored); mSCRIPT_BIND_FUNCTION(boundIdentityInt, S32, identityInt, 1, S32, in); @@ -61,6 +85,7 @@ mSCRIPT_BIND_FUNCTION(boundIdentityStruct, S(Test), identityStruct, 1, S(Test), mSCRIPT_BIND_FUNCTION(boundAddInts, S32, addInts, 2, S32, a, S32, b); mSCRIPT_BIND_FUNCTION(boundSubInts, S32, subInts, 2, S32, a, S32, b); mSCRIPT_BIND_FUNCTION(boundIsHello, S32, isHello, 1, CHARP, str); +mSCRIPT_BIND_FUNCTION(boundIsSequential, S32, isSequential, 1, LIST, list); M_TEST_DEFINE(voidArgs) { struct mScriptFrame frame; @@ -919,6 +944,47 @@ M_TEST_DEFINE(stringIsNotHello) { mScriptFrameDeinit(&frame); } +M_TEST_DEFINE(invokeList) { + struct mScriptFrame frame; + struct mScriptList list; + int val; + + mScriptListInit(&list, 0); + + mScriptFrameInit(&frame); + mSCRIPT_PUSH(&frame.arguments, LIST, &list); + assert_true(mScriptInvoke(&boundIsSequential, &frame)); + assert_true(mScriptPopS32(&frame.returnValues, &val)); + assert_int_equal(val, 1); + mScriptFrameDeinit(&frame); + + *mScriptListAppend(&list) = mSCRIPT_MAKE_S32(1); + mScriptFrameInit(&frame); + mSCRIPT_PUSH(&frame.arguments, LIST, &list); + assert_true(mScriptInvoke(&boundIsSequential, &frame)); + assert_true(mScriptPopS32(&frame.returnValues, &val)); + assert_int_equal(val, 1); + mScriptFrameDeinit(&frame); + + *mScriptListAppend(&list) = mSCRIPT_MAKE_S32(2); + mScriptFrameInit(&frame); + mSCRIPT_PUSH(&frame.arguments, LIST, &list); + assert_true(mScriptInvoke(&boundIsSequential, &frame)); + assert_true(mScriptPopS32(&frame.returnValues, &val)); + assert_int_equal(val, 1); + mScriptFrameDeinit(&frame); + + *mScriptListAppend(&list) = mSCRIPT_MAKE_S32(4); + mScriptFrameInit(&frame); + mSCRIPT_PUSH(&frame.arguments, LIST, &list); + assert_true(mScriptInvoke(&boundIsSequential, &frame)); + assert_true(mScriptPopS32(&frame.returnValues, &val)); + assert_int_equal(val, 0); + mScriptFrameDeinit(&frame); + + mScriptListDeinit(&list); +} + M_TEST_SUITE_DEFINE(mScript, cmocka_unit_test(voidArgs), cmocka_unit_test(voidFunc), @@ -948,4 +1014,6 @@ M_TEST_SUITE_DEFINE(mScript, cmocka_unit_test(hashTableBasic), cmocka_unit_test(hashTableString), cmocka_unit_test(stringIsHello), - cmocka_unit_test(stringIsNotHello)) + cmocka_unit_test(stringIsNotHello), + cmocka_unit_test(invokeList), +) From d4c1ab172828045f13279402d2b07ba0cc5c74b4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 5 Jun 2022 01:59:27 -0700 Subject: [PATCH 027/102] Scripting: Fix some Lua memory lifetimes --- src/script/engines/lua.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index db1178993..2770e8898 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -106,6 +106,7 @@ static const luaL_Reg _mSTTable[] = { { "__index", _luaGetTable }, { "__len", _luaLenTable }, { "__pairs", _luaPairsTable }, + { "__gc", _luaGcObject }, { NULL, NULL } }; @@ -412,7 +413,6 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v *newValue = mSCRIPT_MAKE(WEAKREF, weakref); } else { mScriptValueWrap(value, newValue); - mScriptValueDeref(value); } luaL_setmetatable(luaContext->lua, "mSTList"); break; @@ -422,7 +422,6 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v *newValue = mSCRIPT_MAKE(WEAKREF, weakref); } else { mScriptValueWrap(value, newValue); - mScriptValueDeref(value); } luaL_setmetatable(luaContext->lua, "mSTTable"); break; @@ -440,7 +439,6 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v *newValue = mSCRIPT_MAKE(WEAKREF, weakref); } else { mScriptValueWrap(value, newValue); - mScriptValueDeref(value); } luaL_setmetatable(luaContext->lua, "mSTStruct"); break; From 00bd093fe3812fe572ba9d143cce3e6642c59dd5 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 5 Jun 2022 02:04:09 -0700 Subject: [PATCH 028/102] Scripting: Add bitmask handling functions --- include/mgba/script/context.h | 4 +- include/mgba/script/types.h | 5 ++ src/script/CMakeLists.txt | 4 +- src/script/context.c | 12 +++++ src/script/stdlib.c | 48 ++++++++++++++++-- src/script/test/stdlib.c | 91 +++++++++++++++++++++++++++++++++++ src/script/types.c | 9 ++++ 7 files changed, 166 insertions(+), 7 deletions(-) create mode 100644 src/script/test/stdlib.c diff --git a/include/mgba/script/context.h b/include/mgba/script/context.h index 8633e0ed4..780067d83 100644 --- a/include/mgba/script/context.h +++ b/include/mgba/script/context.h @@ -14,8 +14,9 @@ CXX_GUARD_START #include #include +#define mSCRIPT_KV_PAIR(KEY, VALUE) { #KEY, VALUE } #define mSCRIPT_CONSTANT_PAIR(NS, CONST) { #CONST, mScriptValueCreateFromSInt(NS ## _ ## CONST) } -#define mSCRIPT_CONSTANT_SENTINEL { NULL, NULL } +#define mSCRIPT_KV_SENTINEL { NULL, NULL } struct mScriptFrame; struct mScriptFunction; @@ -80,6 +81,7 @@ void mScriptContextClearWeakref(struct mScriptContext*, uint32_t weakref); void mScriptContextAttachStdlib(struct mScriptContext* context); void mScriptContextExportConstants(struct mScriptContext* context, const char* nspace, struct mScriptKVPair* constants); +void mScriptContextExportNamespace(struct mScriptContext* context, const char* nspace, struct mScriptKVPair* value); void mScriptContextTriggerCallback(struct mScriptContext*, const char* callback); void mScriptContextAddCallback(struct mScriptContext*, const char* callback, struct mScriptValue* value); diff --git a/include/mgba/script/types.h b/include/mgba/script/types.h index 489b5eee4..471d78524 100644 --- a/include/mgba/script/types.h +++ b/include/mgba/script/types.h @@ -41,6 +41,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_C_PS(X) void #define mSCRIPT_TYPE_C_PCS(X) void #define mSCRIPT_TYPE_C_WSTR struct mScriptValue* +#define mSCRIPT_TYPE_C_WLIST struct mScriptValue* #define mSCRIPT_TYPE_C_W(X) struct mScriptValue* #define mSCRIPT_TYPE_C_CW(X) const struct mScriptValue* @@ -67,6 +68,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_FIELD_PS(STRUCT) opaque #define mSCRIPT_TYPE_FIELD_PCS(STRUCT) copaque #define mSCRIPT_TYPE_FIELD_WSTR opaque +#define mSCRIPT_TYPE_FIELD_WLIST opaque #define mSCRIPT_TYPE_FIELD_W(TYPE) opaque #define mSCRIPT_TYPE_FIELD_CW(TYPE) opaque @@ -92,6 +94,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_MS_PS(STRUCT) (&mSTStructPtr_ ## STRUCT) #define mSCRIPT_TYPE_MS_PCS(STRUCT) (&mSTStructConstPtr_ ## STRUCT) #define mSCRIPT_TYPE_MS_WSTR (&mSTStringWrapper) +#define mSCRIPT_TYPE_MS_WLIST (&mSTListWrapper) #define mSCRIPT_TYPE_MS_W(TYPE) (&mSTWrapper_ ## TYPE) #define mSCRIPT_TYPE_MS_CW(TYPE) (&mSTWrapperConst_ ## TYPE) @@ -116,6 +119,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_CMP_S_METHOD(STRUCT, NAME) mSCRIPT_TYPE_MS_S_METHOD(STRUCT, NAME)->name == _mSCRIPT_FIELD_NAME #define mSCRIPT_TYPE_CMP(TYPE0, TYPE1) mSCRIPT_TYPE_CMP_ ## TYPE0(TYPE1) #define mSCRIPT_TYPE_CMP_WSTR(TYPE) (mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_STR, TYPE) || mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_CHARP, TYPE)) +#define mSCRIPT_TYPE_CMP_WLIST(TYPE) (mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_LIST, TYPE)) enum mScriptTypeBase { mSCRIPT_TYPE_VOID = 0, @@ -168,6 +172,7 @@ extern const struct mScriptType mSTTable; extern const struct mScriptType mSTWrapper; extern const struct mScriptType mSTWeakref; extern const struct mScriptType mSTStringWrapper; +extern const struct mScriptType mSTListWrapper; struct mScriptType; struct mScriptValue { diff --git a/src/script/CMakeLists.txt b/src/script/CMakeLists.txt index c579ccb9f..e9ecc8c60 100644 --- a/src/script/CMakeLists.txt +++ b/src/script/CMakeLists.txt @@ -10,7 +10,9 @@ set(TEST_FILES if(USE_LUA) list(APPEND SOURCE_FILES engines/lua.c) - list(APPEND TEST_FILES test/lua.c) + list(APPEND TEST_FILES + test/stdlib.c + test/lua.c) endif() source_group("Scripting" FILES ${SOURCE_FILES}) diff --git a/src/script/context.c b/src/script/context.c index f2437dc5b..43f962caf 100644 --- a/src/script/context.c +++ b/src/script/context.c @@ -237,6 +237,18 @@ void mScriptContextExportConstants(struct mScriptContext* context, const char* n mScriptValueDeref(table); } +void mScriptContextExportNamespace(struct mScriptContext* context, const char* nspace, struct mScriptKVPair* values) { + struct mScriptValue* table = mScriptValueAlloc(mSCRIPT_TYPE_MS_TABLE); + size_t i; + for (i = 0; values[i].key; ++i) { + struct mScriptValue* key = mScriptStringCreateFromUTF8(values[i].key); + mScriptTableInsert(table, key, values[i].value); + mScriptValueDeref(key); + mScriptValueDeref(values[i].value); + } + mScriptContextSetGlobal(context, nspace, table); +} + bool mScriptContextLoadVF(struct mScriptContext* context, const char* name, struct VFile* vf) { struct mScriptFileInfo info = { .name = name, diff --git a/src/script/stdlib.c b/src/script/stdlib.c index 35941f6d8..32770a752 100644 --- a/src/script/stdlib.c +++ b/src/script/stdlib.c @@ -30,6 +30,38 @@ static void _mScriptCallbackAdd(struct mScriptCallbackManager* adapter, struct m mSCRIPT_DECLARE_STRUCT(mScriptCallbackManager); mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptCallbackManager, add, _mScriptCallbackAdd, 2, STR, callback, WRAPPER, function); +static uint64_t mScriptMakeBitmask(struct mScriptList* list) { + size_t i; + uint64_t mask = 0; + for (i = 0; i < mScriptListSize(list); ++i) { + struct mScriptValue bit; + struct mScriptValue* value = mScriptListGetPointer(list, i); + if (value->type->base == mSCRIPT_TYPE_WRAPPER) { + value = mScriptValueUnwrap(value); + } + if (!mScriptCast(mSCRIPT_TYPE_MS_U64, value, &bit)) { + continue; + } + mask |= 1ULL << bit.value.u64; + } + return mask; +} + +static struct mScriptValue* mScriptExpandBitmask(uint64_t mask) { + struct mScriptValue* list = mScriptValueAlloc(mSCRIPT_TYPE_MS_LIST); + size_t i; + for (i = 0; mask; ++i, mask >>= 1) { + if (!(mask & 1)) { + continue; + } + *mScriptListAppend(list->value.list) = mSCRIPT_MAKE_U32(i); + } + return list; +} + +mSCRIPT_BIND_FUNCTION(mScriptMakeBitmask_Binding, U64, mScriptMakeBitmask, 1, LIST, bits); +mSCRIPT_BIND_FUNCTION(mScriptExpandBitmask_Binding, WLIST, mScriptExpandBitmask, 1, U64, mask); + mSCRIPT_DEFINE_STRUCT(mScriptCallbackManager) mSCRIPT_DEFINE_CLASS_DOCSTRING( "A global singleton object `callbacks` used for managing callbacks. The following callbacks are defined:\n\n" @@ -66,17 +98,17 @@ void mScriptContextAttachStdlib(struct mScriptContext* context) { mSCRIPT_CONSTANT_PAIR(SAVESTATE, RTC), mSCRIPT_CONSTANT_PAIR(SAVESTATE, METADATA), mSCRIPT_CONSTANT_PAIR(SAVESTATE, ALL), - mSCRIPT_CONSTANT_SENTINEL + mSCRIPT_KV_SENTINEL }); mScriptContextExportConstants(context, "PLATFORM", (struct mScriptKVPair[]) { mSCRIPT_CONSTANT_PAIR(mPLATFORM, NONE), mSCRIPT_CONSTANT_PAIR(mPLATFORM, GBA), mSCRIPT_CONSTANT_PAIR(mPLATFORM, GB), - mSCRIPT_CONSTANT_SENTINEL + mSCRIPT_KV_SENTINEL }); mScriptContextExportConstants(context, "CHECKSUM", (struct mScriptKVPair[]) { mSCRIPT_CONSTANT_PAIR(mCHECKSUM, CRC32), - mSCRIPT_CONSTANT_SENTINEL + mSCRIPT_KV_SENTINEL }); #ifdef M_CORE_GBA mScriptContextExportConstants(context, "GBA_KEY", (struct mScriptKVPair[]) { @@ -90,7 +122,7 @@ void mScriptContextAttachStdlib(struct mScriptContext* context) { mSCRIPT_CONSTANT_PAIR(GBA_KEY, DOWN), mSCRIPT_CONSTANT_PAIR(GBA_KEY, R), mSCRIPT_CONSTANT_PAIR(GBA_KEY, L), - mSCRIPT_CONSTANT_SENTINEL + mSCRIPT_KV_SENTINEL }); #endif #ifdef M_CORE_GB @@ -103,8 +135,14 @@ void mScriptContextAttachStdlib(struct mScriptContext* context) { mSCRIPT_CONSTANT_PAIR(GB_KEY, LEFT), mSCRIPT_CONSTANT_PAIR(GB_KEY, UP), mSCRIPT_CONSTANT_PAIR(GB_KEY, DOWN), - mSCRIPT_CONSTANT_SENTINEL + mSCRIPT_KV_SENTINEL }); #endif mScriptContextSetGlobal(context, "C", context->constants); + + mScriptContextExportNamespace(context, "util", (struct mScriptKVPair[]) { + mSCRIPT_KV_PAIR(makeBitmask, &mScriptMakeBitmask_Binding), + mSCRIPT_KV_PAIR(expandBitmask, &mScriptExpandBitmask_Binding), + mSCRIPT_KV_SENTINEL + }); } diff --git a/src/script/test/stdlib.c b/src/script/test/stdlib.c new file mode 100644 index 000000000..c6e9fd3fe --- /dev/null +++ b/src/script/test/stdlib.c @@ -0,0 +1,91 @@ +/* Copyright (c) 2013-2022 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "util/test/suite.h" + +#include +#include +#include + +#define SETUP_LUA \ + struct mScriptContext context; \ + mScriptContextInit(&context); \ + struct mScriptEngineContext* lua = mScriptContextRegisterEngine(&context, mSCRIPT_ENGINE_LUA); \ + mScriptContextAttachStdlib(&context) + +#define LOAD_PROGRAM(PROG) \ + do { \ + struct VFile* vf = VFileFromConstMemory(PROG, strlen(PROG)); \ + assert_true(lua->load(lua, NULL, vf)); \ + vf->close(vf); \ + } while(0) + +#define TEST_PROGRAM(PROG) \ + LOAD_PROGRAM(PROG); \ + assert_true(lua->run(lua)); \ + +#define TEST_VALUE(TYPE, NAME, VALUE) \ + do { \ + struct mScriptValue val = mSCRIPT_MAKE(TYPE, VALUE); \ + struct mScriptValue* global = lua->getGlobal(lua, NAME); \ + assert_non_null(global); \ + assert_true(global->type->equal(global, &val)); \ + mScriptValueDeref(global); \ + } while(0) + +M_TEST_SUITE_SETUP(mScriptStdlib) { + if (mSCRIPT_ENGINE_LUA->init) { + mSCRIPT_ENGINE_LUA->init(mSCRIPT_ENGINE_LUA); + } + return 0; +} + +M_TEST_SUITE_TEARDOWN(mScriptStdlib) { + if (mSCRIPT_ENGINE_LUA->deinit) { + mSCRIPT_ENGINE_LUA->deinit(mSCRIPT_ENGINE_LUA); + } + return 0; +} + +M_TEST_DEFINE(bitMask) { + SETUP_LUA; + + TEST_PROGRAM("assert(util)"); + TEST_PROGRAM("assert(util.makeBitmask)"); + TEST_PROGRAM("assert(util.makeBitmask{0} == 1)"); + TEST_PROGRAM("assert(util.makeBitmask{1} == 2)"); + TEST_PROGRAM("assert(util.makeBitmask{0, 1} == 3)"); + TEST_PROGRAM("assert(util.makeBitmask{1, 1} == 2)"); + + mScriptContextDeinit(&context); +} + +M_TEST_DEFINE(bitUnmask) { + SETUP_LUA; + + TEST_PROGRAM("assert(util)"); + TEST_PROGRAM("assert(util.expandBitmask)"); + TEST_PROGRAM("assert(#util.expandBitmask(0) == 0)"); + TEST_PROGRAM("assert(#util.expandBitmask(1) == 1)"); + TEST_PROGRAM("assert(util.expandBitmask(1)[1] == 0)"); + TEST_PROGRAM("assert(#util.expandBitmask(2) == 1)"); + TEST_PROGRAM("assert(util.expandBitmask(2)[1] == 1)"); + TEST_PROGRAM("assert(#util.expandBitmask(3) == 2)"); + TEST_PROGRAM("assert(util.expandBitmask(3)[1] == 0 or util.expandBitmask(3)[1] == 1)"); + TEST_PROGRAM("assert(util.expandBitmask(3)[2] == 0 or util.expandBitmask(3)[2] == 1)"); + TEST_PROGRAM("assert(#util.expandBitmask(6) == 2)"); + TEST_PROGRAM("assert(util.expandBitmask(6)[1] == 1 or util.expandBitmask(6)[1] == 2)"); + TEST_PROGRAM("assert(util.expandBitmask(6)[2] == 1 or util.expandBitmask(6)[2] == 2)"); + TEST_PROGRAM("assert(#util.expandBitmask(7) == 3)"); + TEST_PROGRAM("assert(#util.expandBitmask(11) == 3)"); + TEST_PROGRAM("assert(#util.expandBitmask(15) == 4)"); + + mScriptContextDeinit(&context); +} + +M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptStdlib, + cmocka_unit_test(bitMask), + cmocka_unit_test(bitUnmask), +) diff --git a/src/script/types.c b/src/script/types.c index 4ab6653e1..61fcadcd2 100644 --- a/src/script/types.c +++ b/src/script/types.c @@ -221,6 +221,15 @@ const struct mScriptType mSTStringWrapper = { .hash = NULL, }; +const struct mScriptType mSTListWrapper = { + .base = mSCRIPT_TYPE_WRAPPER, + .size = sizeof(struct mScriptValue), + .name = "wrapper list", + .alloc = NULL, + .free = NULL, + .hash = NULL, +}; + const struct mScriptType mSTWeakref = { .base = mSCRIPT_TYPE_WEAKREF, .size = sizeof(uint32_t), From 10eb2b9784266c0024ff050dc2e29203fe89390f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 5 Jun 2022 03:28:15 -0700 Subject: [PATCH 029/102] Scripting: Add root-scope docstrings --- include/mgba/script/context.h | 4 ++++ src/core/scripting.c | 17 ++++++++--------- src/script/context.c | 10 ++++++++++ src/script/docgen.c | 32 ++++++++++++++++++++++++-------- src/script/stdlib.c | 5 +++++ 5 files changed, 51 insertions(+), 17 deletions(-) diff --git a/include/mgba/script/context.h b/include/mgba/script/context.h index 780067d83..80682ee29 100644 --- a/include/mgba/script/context.h +++ b/include/mgba/script/context.h @@ -30,6 +30,7 @@ struct mScriptContext { uint32_t nextWeakref; struct Table callbacks; struct mScriptValue* constants; + struct Table docstrings; }; struct mScriptEngine2 { @@ -86,6 +87,9 @@ void mScriptContextExportNamespace(struct mScriptContext* context, const char* n void mScriptContextTriggerCallback(struct mScriptContext*, const char* callback); void mScriptContextAddCallback(struct mScriptContext*, const char* callback, struct mScriptValue* value); +void mScriptContextSetDocstring(struct mScriptContext*, const char* key, const char* docstring); +const char* mScriptContextGetDocstring(struct mScriptContext*, const char* key); + struct VFile; bool mScriptContextLoadVF(struct mScriptContext*, const char* name, struct VFile* vf); bool mScriptContextLoadFile(struct mScriptContext*, const char* path); diff --git a/src/core/scripting.c b/src/core/scripting.c index d08761bbf..7c14eb08b 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -710,14 +710,20 @@ mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mScriptConsole, createBuffer) mSCRIPT_CHARP(NULL) mSCRIPT_DEFINE_DEFAULTS_END; -void mScriptContextAttachLogger(struct mScriptContext* context, struct mLogger* logger) { +static struct mScriptConsole* _ensureConsole(struct mScriptContext* context) { struct mScriptValue* value = mScriptContextEnsureGlobal(context, "console", mSCRIPT_TYPE_MS_S(mScriptConsole)); struct mScriptConsole* console = value->value.opaque; if (!console) { console = calloc(1, sizeof(*console)); value->value.opaque = console; value->flags = mSCRIPT_VALUE_FLAG_FREE_BUFFER; + mScriptContextSetDocstring(context, "console", "Singleton instance of struct::mScriptConsole"); } + return console; +} + +void mScriptContextAttachLogger(struct mScriptContext* context, struct mLogger* logger) { + struct mScriptConsole* console = _ensureConsole(context); console->logger = logger; } @@ -771,14 +777,7 @@ mSCRIPT_DEFINE_STRUCT(mScriptTextBuffer) mSCRIPT_DEFINE_END; void mScriptContextSetTextBufferFactory(struct mScriptContext* context, mScriptContextBufferFactory factory, void* cbContext) { - struct mScriptValue* value = mScriptContextEnsureGlobal(context, "console", mSCRIPT_TYPE_MS_S(mScriptConsole)); - struct mScriptConsole* console = value->value.opaque; - if (!console) { - console = calloc(1, sizeof(*console)); - console->logger = mLogGetContext(); - value->value.opaque = console; - value->flags = mSCRIPT_VALUE_FLAG_FREE_BUFFER; - } + struct mScriptConsole* console = _ensureConsole(context); console->textBufferFactory = factory; console->textBufferContext = cbContext; } diff --git a/src/script/context.c b/src/script/context.c index 43f962caf..7c9b32dab 100644 --- a/src/script/context.c +++ b/src/script/context.c @@ -57,6 +57,7 @@ void mScriptContextInit(struct mScriptContext* context) { context->nextWeakref = 1; HashTableInit(&context->callbacks, 0, (void (*)(void*)) mScriptValueDeref); context->constants = NULL; + HashTableInit(&context->docstrings, 0, NULL); } void mScriptContextDeinit(struct mScriptContext* context) { @@ -66,6 +67,7 @@ void mScriptContextDeinit(struct mScriptContext* context) { mScriptListDeinit(&context->refPool); HashTableDeinit(&context->callbacks); HashTableDeinit(&context->engines); + HashTableDeinit(&context->docstrings); } void mScriptContextFillPool(struct mScriptContext* context, struct mScriptValue* value) { @@ -249,6 +251,14 @@ void mScriptContextExportNamespace(struct mScriptContext* context, const char* n mScriptContextSetGlobal(context, nspace, table); } +void mScriptContextSetDocstring(struct mScriptContext* context, const char* key, const char* docstring) { + HashTableInsert(&context->docstrings, key, docstring); +} + +const char* mScriptContextGetDocstring(struct mScriptContext* context, const char* key) { + return HashTableLookup(&context->docstrings, key); +} + bool mScriptContextLoadVF(struct mScriptContext* context, const char* name, struct VFile* vf) { struct mScriptFileInfo info = { .name = name, diff --git a/src/script/docgen.c b/src/script/docgen.c index bc16bc9b7..519b73bb2 100644 --- a/src/script/docgen.c +++ b/src/script/docgen.c @@ -12,7 +12,7 @@ struct mScriptContext context; struct Table types; FILE* out; -void explainValue(struct mScriptValue* value, int level); +void explainValue(struct mScriptValue* value, const char* name, int level); void explainType(struct mScriptType* type, int level); void addTypesFromTuple(const struct mScriptTypeTuple*); @@ -154,7 +154,7 @@ bool printval(const struct mScriptValue* value, char* buffer, size_t bufferSize) return false; } -void explainTable(struct mScriptValue* value, int level) { +void explainTable(struct mScriptValue* value, const char* name, int level) { char indent[(level + 1) * 2 + 1]; memset(indent, ' ', sizeof(indent) - 1); indent[sizeof(indent) - 1] = '\0'; @@ -167,7 +167,14 @@ void explainTable(struct mScriptValue* value, int level) { printval(k, keyval, sizeof(keyval)); fprintf(out, "%s- key: %s\n", indent, keyval); struct mScriptValue* v = mScriptTableIteratorGetValue(value, &iter); - explainValue(v, level + 1); + + struct mScriptValue string; + if (mScriptCast(mSCRIPT_TYPE_MS_CHARP, k, &string)) { + snprintf(keyval, sizeof(keyval), "%s.%s", name, (const char*) string.value.opaque); + explainValue(v, keyval, level + 1); + } else { + explainValue(v, NULL, level + 1); + } } while (mScriptTableIteratorNext(value, &iter)); } } @@ -234,15 +241,15 @@ void explainObject(struct mScriptValue* value, int level) { struct mScriptValue* unwrappedMember; if (member.type->base == mSCRIPT_TYPE_WRAPPER) { unwrappedMember = mScriptValueUnwrap(&member); - explainValue(unwrappedMember, level + 2); + explainValue(unwrappedMember, NULL, level + 2); } else { - explainValue(&member, level + 2); + explainValue(&member, NULL, level + 2); } } } } -void explainValue(struct mScriptValue* value, int level) { +void explainValue(struct mScriptValue* value, const char* name, int level) { char valstring[1024]; char indent[(level + 1) * 2 + 1]; memset(indent, ' ', sizeof(indent) - 1); @@ -250,10 +257,19 @@ void explainValue(struct mScriptValue* value, int level) { value = mScriptContextAccessWeakref(&context, value); addType(value->type); fprintf(out, "%stype: %s\n", indent, value->type->name); + + const char* docstring = NULL; + if (name) { + docstring = mScriptContextGetDocstring(&context, name); + } + if (docstring) { + fprintf(out, "%scomment: \"%s\"\n", indent, docstring); + } + switch (value->type->base) { case mSCRIPT_TYPE_TABLE: fprintf(out, "%svalue:\n", indent); - explainTable(value, level); + explainTable(value, name, level); break; case mSCRIPT_TYPE_SINT: case mSCRIPT_TYPE_UINT: @@ -462,7 +478,7 @@ int main(int argc, char* argv[]) { const char* name = HashTableIteratorGetKey(&context.rootScope, &iter); fprintf(out, " %s:\n", name); struct mScriptValue* value = HashTableIteratorGetValue(&context.rootScope, &iter); - explainValue(value, 1); + explainValue(value, name, 1); } while (HashTableIteratorNext(&context.rootScope, &iter)); } fputs("emu:\n", out); diff --git a/src/script/stdlib.c b/src/script/stdlib.c index 32770a752..695946d05 100644 --- a/src/script/stdlib.c +++ b/src/script/stdlib.c @@ -90,6 +90,7 @@ void mScriptContextAttachStdlib(struct mScriptContext* context) { }; lib->flags = mSCRIPT_VALUE_FLAG_FREE_BUFFER; mScriptContextSetGlobal(context, "callbacks", lib); + mScriptContextSetDocstring(context, "callbacks", "Singleton instance of struct::mScriptCallbackManager"); mScriptContextExportConstants(context, "SAVESTATE", (struct mScriptKVPair[]) { mSCRIPT_CONSTANT_PAIR(SAVESTATE, SCREENSHOT), @@ -139,10 +140,14 @@ void mScriptContextAttachStdlib(struct mScriptContext* context) { }); #endif mScriptContextSetGlobal(context, "C", context->constants); + mScriptContextSetDocstring(context, "C", "A table containing the [exported constants](#constants)"); mScriptContextExportNamespace(context, "util", (struct mScriptKVPair[]) { mSCRIPT_KV_PAIR(makeBitmask, &mScriptMakeBitmask_Binding), mSCRIPT_KV_PAIR(expandBitmask, &mScriptExpandBitmask_Binding), mSCRIPT_KV_SENTINEL }); + mScriptContextSetDocstring(context, "util", "Basic utility library"); + mScriptContextSetDocstring(context, "util.makeBitmask", "Compile a list of bit indices into a bitmask"); + mScriptContextSetDocstring(context, "util.expandBitmask", "Expand a bitmask into a list of bit indices"); } From 6289c1a4d128182d26e140cded8d4064ea837eee Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 5 Jun 2022 20:36:26 -0700 Subject: [PATCH 030/102] GBA Serialize: Fix doc error --- include/mgba/internal/gba/serialize.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index 6ab814859..01b4476b3 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -227,7 +227,7 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * 0x00368 - 0x0036F: Reserved (leave zero) * 0x00370 - 0x0037F: Audio FIFO A samples * 0x00380 - 0x0038F: Audio FIFO B samples - * 0x00380 - 0x003FF: Reserved (leave zero) + * 0x00390 - 0x003FF: Reserved (leave zero) * 0x00400 - 0x007FF: I/O memory * 0x00800 - 0x00BFF: Palette * 0x00C00 - 0x00FFF: OAM From 3687863cbca112cbb93b543e6b774e741e7223c5 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 5 Jun 2022 20:36:54 -0700 Subject: [PATCH 031/102] Scripting: Add callback removing --- include/mgba/script/context.h | 5 +++- src/script/context.c | 49 ++++++++++++++++++++++++++++++++--- src/script/stdlib.c | 16 +++++++++--- src/script/test/stdlib.c | 30 +++++++++++++++++++++ src/script/types.c | 3 +++ 5 files changed, 95 insertions(+), 8 deletions(-) diff --git a/include/mgba/script/context.h b/include/mgba/script/context.h index 80682ee29..753c356ba 100644 --- a/include/mgba/script/context.h +++ b/include/mgba/script/context.h @@ -29,6 +29,8 @@ struct mScriptContext { struct Table weakrefs; uint32_t nextWeakref; struct Table callbacks; + struct Table callbackId; + uint32_t nextCallbackId; struct mScriptValue* constants; struct Table docstrings; }; @@ -85,7 +87,8 @@ void mScriptContextExportConstants(struct mScriptContext* context, const char* n void mScriptContextExportNamespace(struct mScriptContext* context, const char* nspace, struct mScriptKVPair* value); void mScriptContextTriggerCallback(struct mScriptContext*, const char* callback); -void mScriptContextAddCallback(struct mScriptContext*, const char* callback, struct mScriptValue* value); +uint32_t mScriptContextAddCallback(struct mScriptContext*, const char* callback, struct mScriptValue* value); +void mScriptContextRemoveCallback(struct mScriptContext*, uint32_t cbid); void mScriptContextSetDocstring(struct mScriptContext*, const char* key, const char* docstring); const char* mScriptContextGetDocstring(struct mScriptContext*, const char* key); diff --git a/src/script/context.c b/src/script/context.c index 7c9b32dab..ad4e445fc 100644 --- a/src/script/context.c +++ b/src/script/context.c @@ -14,6 +14,11 @@ struct mScriptFileInfo { struct mScriptEngineContext* context; }; +struct mScriptCallbackInfo { + const char* callback; + size_t id; +}; + static void _engineContextDestroy(void* ctx) { struct mScriptEngineContext* context = ctx; context->destroy(context); @@ -56,6 +61,8 @@ void mScriptContextInit(struct mScriptContext* context) { TableInit(&context->weakrefs, 0, (void (*)(void*)) mScriptValueDeref); context->nextWeakref = 1; HashTableInit(&context->callbacks, 0, (void (*)(void*)) mScriptValueDeref); + TableInit(&context->callbackId, 0, free); + context->nextCallbackId = 1; context->constants = NULL; HashTableInit(&context->docstrings, 0, NULL); } @@ -66,6 +73,7 @@ void mScriptContextDeinit(struct mScriptContext* context) { mScriptContextDrainPool(context); mScriptListDeinit(&context->refPool); HashTableDeinit(&context->callbacks); + TableDeinit(&context->callbackId); HashTableDeinit(&context->engines); HashTableDeinit(&context->docstrings); } @@ -199,8 +207,11 @@ void mScriptContextTriggerCallback(struct mScriptContext* context, const char* c size_t i; for (i = 0; i < mScriptListSize(list->value.list); ++i) { struct mScriptFrame frame; - mScriptFrameInit(&frame); struct mScriptValue* fn = mScriptListGetPointer(list->value.list, i); + if (!fn->type) { + continue; + } + mScriptFrameInit(&frame); if (fn->type->base == mSCRIPT_TYPE_WRAPPER) { fn = mScriptValueUnwrap(fn); } @@ -209,16 +220,48 @@ void mScriptContextTriggerCallback(struct mScriptContext* context, const char* c } } -void mScriptContextAddCallback(struct mScriptContext* context, const char* callback, struct mScriptValue* fn) { +uint32_t mScriptContextAddCallback(struct mScriptContext* context, const char* callback, struct mScriptValue* fn) { if (fn->type->base != mSCRIPT_TYPE_FUNCTION) { - return; + return 0; } struct mScriptValue* list = HashTableLookup(&context->callbacks, callback); if (!list) { list = mScriptValueAlloc(mSCRIPT_TYPE_MS_LIST); HashTableInsert(&context->callbacks, callback, list); } + struct mScriptCallbackInfo* info = malloc(sizeof(*info)); + // Steal the string from the table key, since it's guaranteed to outlive this struct + struct TableIterator iter; + HashTableIteratorLookup(&context->callbacks, &iter, callback); + info->callback = HashTableIteratorGetKey(&context->callbacks, &iter); + info->id = mScriptListSize(list->value.list); mScriptValueWrap(fn, mScriptListAppend(list->value.list)); + while (true) { + uint32_t id = context->nextCallbackId; + ++context->nextCallbackId; + if (TableLookup(&context->callbackId, id)) { + continue; + } + TableInsert(&context->callbackId, id, info); + return id; + } +} + +void mScriptContextRemoveCallback(struct mScriptContext* context, uint32_t cbid) { + struct mScriptCallbackInfo* info = TableLookup(&context->callbackId, cbid); + if (!info) { + return; + } + struct mScriptValue* list = HashTableLookup(&context->callbacks, info->callback); + if (!list) { + return; + } + if (info->id >= mScriptListSize(list->value.list)) { + return; + } + struct mScriptValue* fn = mScriptValueUnwrap(mScriptListGetPointer(list->value.list, info->id)); + mScriptValueDeref(fn); + mScriptListGetPointer(list->value.list, info->id)->type = NULL; } void mScriptContextExportConstants(struct mScriptContext* context, const char* nspace, struct mScriptKVPair* constants) { diff --git a/src/script/stdlib.c b/src/script/stdlib.c index 695946d05..839673cdb 100644 --- a/src/script/stdlib.c +++ b/src/script/stdlib.c @@ -19,16 +19,22 @@ struct mScriptCallbackManager { struct mScriptContext* context; }; -static void _mScriptCallbackAdd(struct mScriptCallbackManager* adapter, struct mScriptString* name, struct mScriptValue* fn) { +static uint32_t _mScriptCallbackAdd(struct mScriptCallbackManager* adapter, struct mScriptString* name, struct mScriptValue* fn) { if (fn->type->base == mSCRIPT_TYPE_WRAPPER) { fn = mScriptValueUnwrap(fn); } - mScriptContextAddCallback(adapter->context, name->buffer, fn); + uint32_t id = mScriptContextAddCallback(adapter->context, name->buffer, fn); mScriptValueDeref(fn); + return id; +} + +static void _mScriptCallbackRemove(struct mScriptCallbackManager* adapter, uint32_t id) { + mScriptContextRemoveCallback(adapter->context, id); } mSCRIPT_DECLARE_STRUCT(mScriptCallbackManager); -mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptCallbackManager, add, _mScriptCallbackAdd, 2, STR, callback, WRAPPER, function); +mSCRIPT_DECLARE_STRUCT_METHOD(mScriptCallbackManager, U32, add, _mScriptCallbackAdd, 2, STR, callback, WRAPPER, function); +mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptCallbackManager, remove, _mScriptCallbackRemove, 1, U32, cbid); static uint64_t mScriptMakeBitmask(struct mScriptList* list) { size_t i; @@ -76,8 +82,10 @@ mSCRIPT_DEFINE_STRUCT(mScriptCallbackManager) "- **start**: The emulation has started\n" "- **stop**: The emulation has voluntarily shut down\n" ) - mSCRIPT_DEFINE_DOCSTRING("Add a callback of the named type") + mSCRIPT_DEFINE_DOCSTRING("Add a callback of the named type. The returned id can be used to remove it later") mSCRIPT_DEFINE_STRUCT_METHOD(mScriptCallbackManager, add) + mSCRIPT_DEFINE_DOCSTRING("Remove a callback with the previously retuned id") + mSCRIPT_DEFINE_STRUCT_METHOD(mScriptCallbackManager, remove) mSCRIPT_DEFINE_END; void mScriptContextAttachStdlib(struct mScriptContext* context) { diff --git a/src/script/test/stdlib.c b/src/script/test/stdlib.c index c6e9fd3fe..d4c57605b 100644 --- a/src/script/test/stdlib.c +++ b/src/script/test/stdlib.c @@ -7,6 +7,7 @@ #include #include +#include #include #define SETUP_LUA \ @@ -85,7 +86,36 @@ M_TEST_DEFINE(bitUnmask) { mScriptContextDeinit(&context); } +M_TEST_DEFINE(callbacks) { + SETUP_LUA; + + TEST_PROGRAM( + "val = 0\n" + "function cb()\n" + " val = val + 1\n" + "end\n" + "id = callbacks:add('test', cb)\n" + "assert(id)" + ); + + TEST_VALUE(S32, "val", 0); + + mScriptContextTriggerCallback(&context, "test"); + TEST_VALUE(S32, "val", 1); + + mScriptContextTriggerCallback(&context, "test"); + TEST_VALUE(S32, "val", 2); + + TEST_PROGRAM("callbacks:remove(id)"); + + mScriptContextTriggerCallback(&context, "test"); + TEST_VALUE(S32, "val", 2); + + mScriptContextDeinit(&context); +} + M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptStdlib, cmocka_unit_test(bitMask), cmocka_unit_test(bitUnmask), + cmocka_unit_test(callbacks), ) diff --git a/src/script/types.c b/src/script/types.c index 61fcadcd2..52d0425b6 100644 --- a/src/script/types.c +++ b/src/script/types.c @@ -249,6 +249,9 @@ void _allocList(struct mScriptValue* val) { void _freeList(struct mScriptValue* val) { size_t i; for (i = 0; i < mScriptListSize(val->value.list); ++i) { + if (val->type) { + continue; + } struct mScriptValue* unwrapped = mScriptValueUnwrap(mScriptListGetPointer(val->value.list, i)); if (unwrapped) { mScriptValueDeref(unwrapped); From 11837ffc1509bee267b3d073e484d175755dbf1a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 5 Jun 2022 20:59:30 -0700 Subject: [PATCH 032/102] ARM: Disassemble Thumb mov pseudo-instruction properly --- CHANGES | 1 + include/mgba/internal/arm/decoder.h | 2 +- src/arm/decoder.c | 51 ++++++++++++++++------------- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/CHANGES b/CHANGES index 302e1685b..e6b9cf351 100644 --- a/CHANGES +++ b/CHANGES @@ -42,6 +42,7 @@ Emulation fixes: - GBA Video: Fix rare crash in modes 3-5 - GBA Video: Fix sprites with mid-frame palette changes in GL (fixes mgba.io/i/2476) Other fixes: + - ARM: Disassemble Thumb mov pseudo-instruction properly - Core: Don't attempt to restore rewind diffs past start of rewind - Core: Fix the runloop resuming after a game has crashed (fixes mgba.io/i/2451) - Core: Fix crash if library can't be opened diff --git a/include/mgba/internal/arm/decoder.h b/include/mgba/internal/arm/decoder.h index 61226f8c4..c0efb22e8 100644 --- a/include/mgba/internal/arm/decoder.h +++ b/include/mgba/internal/arm/decoder.h @@ -223,7 +223,7 @@ uint32_t ARMResolveMemoryAccess(struct ARMInstructionInfo* info, struct ARMRegis #ifdef USE_DEBUGGERS struct mDebuggerSymbols; -int ARMDisassemble(struct ARMInstructionInfo* info, struct ARMCore* core, const struct mDebuggerSymbols* symbols, uint32_t pc, char* buffer, int blen); +int ARMDisassemble(const struct ARMInstructionInfo* info, struct ARMCore* core, const struct mDebuggerSymbols* symbols, uint32_t pc, char* buffer, int blen); #endif CXX_GUARD_END diff --git a/src/arm/decoder.c b/src/arm/decoder.c index 86583fa2d..8fef6b18f 100644 --- a/src/arm/decoder.c +++ b/src/arm/decoder.c @@ -378,10 +378,11 @@ static const char* _armAccessTypeStrings[] = { "" }; -int ARMDisassemble(struct ARMInstructionInfo* info, struct ARMCore* cpu, const struct mDebuggerSymbols* symbols, uint32_t pc, char* buffer, int blen) { +int ARMDisassemble(const struct ARMInstructionInfo* info, struct ARMCore* cpu, const struct mDebuggerSymbols* symbols, uint32_t pc, char* buffer, int blen) { const char* mnemonic = _armMnemonicStrings[info->mnemonic]; int written; int total = 0; + bool skip3 = false; const char* cond = ""; if (info->condition != ARM_CONDITION_AL && info->condition < ARM_CONDITION_NV) { cond = _armConditions[info->condition]; @@ -398,6 +399,11 @@ int ARMDisassemble(struct ARMInstructionInfo* info, struct ARMCore* cpu, const s flags = _armAccessTypeStrings[info->memory.width]; break; case ARM_MN_ADD: + if ((info->operandFormat & (ARM_OPERAND_3 | ARM_OPERAND_4)) == ARM_OPERAND_IMMEDIATE_3 && info->op3.immediate == 0 && info->execMode == MODE_THUMB) { + skip3 = true; + mnemonic = "mov"; + } + // Fall through case ARM_MN_ADC: case ARM_MN_AND: case ARM_MN_ASR: @@ -406,7 +412,6 @@ int ARMDisassemble(struct ARMInstructionInfo* info, struct ARMCore* cpu, const s case ARM_MN_LSL: case ARM_MN_LSR: case ARM_MN_MLA: - case ARM_MN_MOV: case ARM_MN_MUL: case ARM_MN_MVN: case ARM_MN_ORR: @@ -497,26 +502,28 @@ int ARMDisassemble(struct ARMInstructionInfo* info, struct ARMCore* cpu, const s written = _decodeShift(info->op2, false, buffer, blen); ADVANCE(written); } - if (info->operandFormat & ARM_OPERAND_3) { - strlcpy(buffer, ", ", blen); - ADVANCE(2); - } - if (info->operandFormat & ARM_OPERAND_IMMEDIATE_3) { - written = snprintf(buffer, blen, "#%i", info->op3.immediate); - ADVANCE(written); - } else if (info->operandFormat & ARM_OPERAND_MEMORY_3) { - written = _decodeMemory(info->memory, cpu, symbols, pc, buffer, blen); - ADVANCE(written); - } else if (info->operandFormat & ARM_OPERAND_REGISTER_3) { - written = _decodeRegister(info->op3.reg, buffer, blen); - ADVANCE(written); - } - if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_3) { - written = _decodeShift(info->op3, true, buffer, blen); - ADVANCE(written); - } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_3) { - written = _decodeShift(info->op3, false, buffer, blen); - ADVANCE(written); + if (!skip3) { + if (info->operandFormat & ARM_OPERAND_3) { + strlcpy(buffer, ", ", blen); + ADVANCE(2); + } + if (info->operandFormat & ARM_OPERAND_IMMEDIATE_3) { + written = snprintf(buffer, blen, "#%i", info->op3.immediate); + ADVANCE(written); + } else if (info->operandFormat & ARM_OPERAND_MEMORY_3) { + written = _decodeMemory(info->memory, cpu, symbols, pc, buffer, blen); + ADVANCE(written); + } else if (info->operandFormat & ARM_OPERAND_REGISTER_3) { + written = _decodeRegister(info->op3.reg, buffer, blen); + ADVANCE(written); + } + if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_3) { + written = _decodeShift(info->op3, true, buffer, blen); + ADVANCE(written); + } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_3) { + written = _decodeShift(info->op3, false, buffer, blen); + ADVANCE(written); + } } if (info->operandFormat & ARM_OPERAND_4) { strlcpy(buffer, ", ", blen); From aad78be37f92c294385bef25d78cac37f2925c21 Mon Sep 17 00:00:00 2001 From: shinyoyo Date: Tue, 31 May 2022 20:39:46 +0800 Subject: [PATCH 033/102] Update new translated Simplified Chinese entry --- src/platform/qt/ts/mgba-zh_CN.ts | 218 +++++++++++++++---------------- 1 file changed, 109 insertions(+), 109 deletions(-) diff --git a/src/platform/qt/ts/mgba-zh_CN.ts b/src/platform/qt/ts/mgba-zh_CN.ts index 29bb76796..8076609e4 100644 --- a/src/platform/qt/ts/mgba-zh_CN.ts +++ b/src/platform/qt/ts/mgba-zh_CN.ts @@ -1286,7 +1286,7 @@ Download size: %3 Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. - + 无法添加某些作弊码。请确认它们的格式是否正确并且/或尝试其它的作弊类型。 @@ -1294,23 +1294,23 @@ Download size: %3 Reset r%1-%2 %3 - + 重置 r%1-%2 %3 Rewinding not currently enabled - + 当前未开启倒带 Reset the game? - + 要重置游戏吗? Most games will require a reset to load the new save. Do you want to reset now? - + 大多数游戏需要重置才能加载新的存档。您要立即重启吗? @@ -1353,7 +1353,7 @@ Download size: %3 Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). - 无法打开存档;游戏内存档无法更新。请确保保存目录是可写的,且没有额外权限(例如 Windows 上的 UAC)。 + 无法打开存档;游戏内存档无法更新。请确保保存目录是可写的,且没有额外权限(例如 Windows 上的 UAC)。 @@ -1361,7 +1361,7 @@ Download size: %3 Could not open CLI history for writing - + 无法打开用于写入的 CLI 历史 @@ -1468,22 +1468,22 @@ Download size: %3 Write watchpoints behavior - + 写入监视点行为 Standard GDB - + 标准 GDB Internal change detection - + 内部改动检测 Break on all writes - + 中断所有写入 @@ -1634,7 +1634,7 @@ Download size: %3 Swap green components - 交换绿色组件 + 交换绿色组件 @@ -2533,22 +2533,22 @@ Download size: %3 Source (high) - 源(高) + 源(高) Source (low) - 源(低) + 源(低) Destination (high) - 目的地(高) + 目的地(高) Destination (low) - 目的地(低) + 目的地(低) @@ -3091,12 +3091,12 @@ Download size: %3 Transfer active - 传输处于活动状态 + 传输处于活动状态 Divider - 除数 + 除数 @@ -3107,13 +3107,13 @@ Download size: %3 LCD STAT - LCD 统计 + LCD 统计 Timer - 定时器 + 定时器 @@ -3160,12 +3160,12 @@ Download size: %3 Double-height sprites - 二倍高度精灵 + 二倍高度精灵 Background tile map - 背景图块集 + 背景图块集 @@ -3182,7 +3182,7 @@ Download size: %3 Background tile data - 背景图块数据 + 背景图块数据 @@ -3197,12 +3197,12 @@ Download size: %3 Enable window - 启用窗口 + 启用窗口 Window tile map - 窗口图块集 + 窗口图块集 @@ -3212,7 +3212,7 @@ Download size: %3 Mode - 模式 + 模式 @@ -3227,7 +3227,7 @@ Download size: %3 2: OAM scan - 2:OAM 扫描 + 2:OAM 扫描 @@ -3237,22 +3237,22 @@ Download size: %3 In LYC - 在 LYC 中 + 在 LYC 中 Enable HBlank (mode 0) IRQ - 启用 HBlank(模式 0)IRQ + 启用 HBlank(模式 0)IRQ Enable VBlank (mode 1) IRQ - 启用 VBlank(模式 1)IRQ + 启用 VBlank(模式 1)IRQ Enable OAM (mode 2) IRQ - 启用 OAM(模式 2)IRQ + 启用 OAM(模式 2)IRQ @@ -3267,12 +3267,12 @@ Download size: %3 Comparison Y coordinate - 对比 Y 坐标 + 对比 Y 坐标 Start upper byte - 开始上部字节 + 开始上部字节 @@ -3320,22 +3320,22 @@ Download size: %3 Length - 长度 + 长度 Timing - 定时 + 定时 Write bit - 写位 + 写位 Read bit - 读位 + 读位 @@ -3347,7 +3347,7 @@ Download size: %3 Current index - 当前索引 + 当前索引 @@ -3359,28 +3359,28 @@ Download size: %3 Red - + Blue - + Sprite ordering - 精灵排序 + 精灵排序 OAM order - OAM 顺序 + OAM 顺序 x coordinate sorting - x 坐标排序 + x 坐标排序 @@ -3570,7 +3570,7 @@ Download size: %3 Map Addr. - 映射地址 + 映射地址. @@ -3719,7 +3719,7 @@ Download size: %3 Frame %1 - + 帧 %1 @@ -3879,22 +3879,22 @@ Download size: %3 Save games and save states (%1) - 保存游戏和即时存档(%1) + 保存游戏和即时存档(%1) Select save game or save state - 选择保存游戏或即时存档 + 选择保存游戏或即时存档 Save games (%1) - 保存游戏(%1) + 保存游戏(%1) Select save game - 选择保存游戏 + 选择保存游戏 @@ -3904,12 +3904,12 @@ Download size: %3 Failed to convert the save game. This is probably a bug. - 未能转换保存游戏。这可能是一个错误。 + 未能转换保存游戏。这可能是一个错误。 No file selected - 未选择文件 + 未选择文件 @@ -3929,12 +3929,12 @@ Download size: %3 No valid conversions found - 未发现有效转换 + 未发现有效转换 Cannot convert save games between platforms - 无法在平台之间转换保存游戏 + 无法在平台之间转换保存游戏 @@ -3942,7 +3942,7 @@ Download size: %3 Untitled buffer - + 无标题缓存 @@ -3950,17 +3950,17 @@ Download size: %3 Select script to load - + 选择要载入的脚本 Lua scripts (*.lua) - + Lua 脚本 (*.lua) All files (*.*) - + 所有文件 (*.*) @@ -3994,7 +3994,7 @@ Download size: %3 None - + @@ -4322,7 +4322,7 @@ Download size: %3 %1 - %2 (%3 fps) - %4 - %1 - %2(%3 fps)- %4 + @@ -4352,7 +4352,7 @@ Download size: %3 Select save game - 选择保存游戏 + 选择保存游戏 @@ -4383,17 +4383,17 @@ Download size: %3 %1 of %2 e-Reader cards converted successfully. - 成功转换了 %1 张(共 %2 张)e-Reader 卡片。 + 成功转换了 %1 张(共 %2 张)e-Reader 卡片。 Load alternate save game... - 加载备用保存游戏... + 加载备用保存游戏... Load temporary save game... - 加载临时保存游戏... + 加载临时保存游戏... @@ -4418,7 +4418,7 @@ Download size: %3 Convert e-Reader card image to raw... - 将 e-Reader 卡片图像转换为原始数据... + 将 e-Reader 卡片图像转换为原始数据... @@ -4499,7 +4499,7 @@ Download size: %3 Convert save game... - 转换保存游戏... + 转换保存游戏... @@ -4509,17 +4509,17 @@ Download size: %3 Reset needed - + 需要重启 Some changes will not take effect until the game is reset. - + 某些改动需要重新启动才会生效。 Save games - 游戏存档 + 游戏存档 @@ -4534,12 +4534,12 @@ Download size: %3 Automatically determine - + 自动终止 Use player %0 save game - + 使用玩家 %0 存档 @@ -4814,7 +4814,7 @@ Download size: %3 Scripting... - + 脚本... @@ -4947,7 +4947,7 @@ Download size: %3 %1 kiB - %1 kiB + @@ -5069,7 +5069,7 @@ Download size: %3 Convert/Extract Save Game - 转换或提取保存游戏 + 转换或提取保存游戏 @@ -5080,7 +5080,7 @@ Download size: %3 Browse - 浏览 + 浏览 @@ -5090,17 +5090,17 @@ Download size: %3 %1 %2 save game - %1 %2 保存游戏 + %1 %2 保存游戏 little endian - 小端 + 小端 big endian - 大端 + 大端 @@ -5110,7 +5110,7 @@ Download size: %3 %1 flash - %1 闪存 + %1 闪存 @@ -5130,17 +5130,17 @@ Download size: %3 packed MBC2 - 包装的MBC2 + 包装的 MBC2 unpacked MBC2 - 未包装的 MBC2 + 未包装的 MBC2 MBC6 flash - MBC6 闪存 + MBC6 闪存 @@ -5165,17 +5165,17 @@ Download size: %3 %1 save state with embedded %2 save game - 带嵌入的 %2 保存游戏的 %1 保存状态 + 带嵌入的 %2 保存游戏的 %1 保存状态 %1 SharkPort %2 save game - %1 SharkPort %2 存档 + %1 SharkPort %2 存档 %1 GameShark Advance SP %2 save game - %1 GameShark Advance SP %2 存档 + %1 GameShark Advance SP %2 存档 @@ -5183,32 +5183,32 @@ Download size: %3 Scripting - + 脚本 Run - + 运行 File - + 文件 Load recent script - + 载入历史脚本 Load script... - + 载入脚本... &Reset - 重置(&R) + 重置(&R) @@ -5461,7 +5461,7 @@ Download size: %3 Currently active player window - 当前活跃的玩家窗口 + 当前活跃的玩家窗口 @@ -5527,7 +5527,7 @@ Download size: %3 Show filename instead of ROM name in library view - + 库视图中显示文件名替代 ROM 名 @@ -5538,7 +5538,7 @@ Download size: %3 When inactive: - 不活跃时: + 不活跃时: @@ -5613,12 +5613,12 @@ Download size: %3 Driver: - 驱动: + 驱动: Source: - 来源: + 来源: @@ -5718,12 +5718,12 @@ Download size: %3 Show frame count in OSD - + OSD 中显示帧数 Show emulation info on reset - + 重置时显示模拟信息 @@ -5784,28 +5784,28 @@ Download size: %3 Save state extra data: - 保存存档附加数据: + 保存存档附加数据: Save game - 保存游戏 + 保存游戏 Load state extra data: - 载入存档附加数据: + 载入存档附加数据: Models - 型号 + 型号 GB only: - 仅 GB: + 仅 GB: @@ -5815,7 +5815,7 @@ Download size: %3 GBC only: - 仅 GBC: + 仅 GBC: @@ -5830,7 +5830,7 @@ Download size: %3 Game Boy palette - Game Boy 调色板 + Game Boy 调色板 @@ -6093,7 +6093,7 @@ Download size: %3 Palette - 调色板 + 调色板 @@ -6113,22 +6113,22 @@ Download size: %3 Displayed tiles - + 已显示的图块 Only BG tiles - + 仅 BG 图块 Only OBJ tiles - + 仅 OBJ 图块 Both - 两者 + 两者 From 70a34a58f03b44e5a129cc04b1b51082508f41da Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 6 Jun 2022 16:56:18 -0700 Subject: [PATCH 034/102] Tools: Retry failed server start command --- tools/perf.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tools/perf.py b/tools/perf.py index 2793e53be..172cd989b 100755 --- a/tools/perf.py +++ b/tools/perf.py @@ -71,7 +71,7 @@ class GameClockTest(PerfTest): class PerfServer(object): ITERATIONS_PER_INSTANCE = 50 - RETRIES = 5 + RETRIES = 4 def __init__(self, address, root='/', command=None): s = address.rsplit(':', 1) @@ -100,7 +100,15 @@ class PerfServer(object): server_command.append('-N') elif test.renderer == 'threaded-software': server_command.append('-T') - subprocess.check_call(server_command) + for backoff in range(self.RETRIES): + try: + subprocess.check_call(server_command) + break + except subprocess.CalledProcessError as e: + print("Failed to start server:", e, file=sys.stderr) + if backoff == self.RETRIES - 1: + raise + time.sleep(2 ** backoff) time.sleep(3) for backoff in range(self.RETRIES): try: @@ -108,10 +116,9 @@ class PerfServer(object): break except OSError as e: print("Failed to connect:", e, file=sys.stderr) - if backoff < self.RETRIES - 1: - time.sleep(2 ** backoff) - else: + if backoff == self.RETRIES - 1: raise + time.sleep(2 ** backoff) kwargs = {} if sys.version_info[0] >= 3: kwargs["encoding"] = "utf-8" From 542824e3c077f35f1c559b88d962071182790482 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 6 Jun 2022 21:40:18 -0700 Subject: [PATCH 035/102] CMake: Minor fixes --- CMakeLists.txt | 3 +++ src/platform/qt/CMakeLists.txt | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eafaaf82b..f411449ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -152,6 +152,9 @@ endif() mark_as_advanced(DISTBUILD) set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIBDIR}") +if(${CMAKE_INSTALL_PREFIX} STREQUAL "/usr") + set(CMAKE_SKIP_RPATH ON) +endif() if (NOT DEFINED MANDIR) set(MANDIR ${CMAKE_INSTALL_MANDIR}) diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 611f6136b..9ad0d27f1 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -311,7 +311,6 @@ if(BUILD_GL OR BUILD_GLES2 OR BUILD_EPOXY) install(DIRECTORY ${CMAKE_SOURCE_DIR}/res/shaders DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt) endif() if(ENABLE_SCRIPTING AND USE_LUA) - message(STATUS ${CMAKE_SOURCE_DIR}/res/scripts) install(DIRECTORY ${CMAKE_SOURCE_DIR}/res/scripts DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt) endif() install(FILES ${CMAKE_SOURCE_DIR}/res/nointro.dat DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt) From 00421cd046a60b2ea204c36be4294bcb2f3c415f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 6 Jun 2022 22:35:35 -0700 Subject: [PATCH 036/102] GB Audio: Fix APU re-enable timing glitch --- CHANGES | 1 + .../07-len sweep period sync/baseline_0000.png | Bin 0 -> 788 bytes .../07-len sweep period sync/config.ini | 2 -- .../07-len sweep period sync/xbaseline_0000.png | Bin 1260 -> 0 bytes .../08-len ctr during power/baseline_0000.png | Bin 0 -> 870 bytes .../cgb_sound/08-len ctr during power/config.ini | 2 -- .../08-len ctr during power/xbaseline_0000.png | Bin 968 -> 0 bytes .../07-len sweep period sync/baseline_0000.png | Bin 0 -> 788 bytes .../07-len sweep period sync/config.ini | 2 -- .../07-len sweep period sync/xbaseline_0000.png | Bin 1260 -> 0 bytes .../08-len ctr during power/baseline_0000.png | Bin 0 -> 890 bytes .../dmg_sound/08-len ctr during power/config.ini | 2 -- .../08-len ctr during power/xbaseline_0000.png | Bin 975 -> 0 bytes src/gb/audio.c | 2 +- 14 files changed, 2 insertions(+), 9 deletions(-) create mode 100644 cinema/gb/blargg/cgb_sound/07-len sweep period sync/baseline_0000.png delete mode 100644 cinema/gb/blargg/cgb_sound/07-len sweep period sync/config.ini delete mode 100644 cinema/gb/blargg/cgb_sound/07-len sweep period sync/xbaseline_0000.png create mode 100644 cinema/gb/blargg/cgb_sound/08-len ctr during power/baseline_0000.png delete mode 100644 cinema/gb/blargg/cgb_sound/08-len ctr during power/config.ini delete mode 100644 cinema/gb/blargg/cgb_sound/08-len ctr during power/xbaseline_0000.png create mode 100644 cinema/gb/blargg/dmg_sound/07-len sweep period sync/baseline_0000.png delete mode 100644 cinema/gb/blargg/dmg_sound/07-len sweep period sync/config.ini delete mode 100644 cinema/gb/blargg/dmg_sound/07-len sweep period sync/xbaseline_0000.png create mode 100644 cinema/gb/blargg/dmg_sound/08-len ctr during power/baseline_0000.png delete mode 100644 cinema/gb/blargg/dmg_sound/08-len ctr during power/config.ini delete mode 100644 cinema/gb/blargg/dmg_sound/08-len ctr during power/xbaseline_0000.png diff --git a/CHANGES b/CHANGES index e6b9cf351..6f0f13670 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,7 @@ Emulation fixes: - GB Audio: Fix channel 1/2 reseting edge cases (fixes mgba.io/i/1925) - GB Audio: Properly apply per-model audio differences - GB Audio: Revamp channel rendering + - GB Audio: Fix APU re-enable timing glitch - GB Memory: Add cursory cartridge open bus emulation (fixes mgba.io/i/2032) - GB Serialize: Fix loading MBC1 states that affect bank 0 (fixes mgba.io/i/2402) - GB Video: Draw SGB border pieces that overlap GB graphics (fixes mgba.io/i/1339) diff --git a/cinema/gb/blargg/cgb_sound/07-len sweep period sync/baseline_0000.png b/cinema/gb/blargg/cgb_sound/07-len sweep period sync/baseline_0000.png new file mode 100644 index 0000000000000000000000000000000000000000..c5a976f9bc2a03b3103cc2086317a8670f411efc GIT binary patch literal 788 zcmeAS@N?(olHy`uVBq!ia0vp^3xIe62NRHFxc>b*0|V1-PZ!6KiaBp@Uo2a!AihMu zJ;8$c@Ng3PUh!{oP?Y%7Ij>uf_D5aw-IcxSL(QwS`P<)x^(QTz66E#r=hwQ;R^JxR z`TSs()}0a$n{W5G+?rEexb@qeS&DAo;`4)g-hQ}U^?!PgdPIHM|FtvoQ~qpxE3-## zN9(S!tj&{|f)^pZ~Ms|Hii*a%*l!ZGQcK`Mc*I zrS{xtj(^zq@yMgU|8L#b=>MlBzVk`=E&uZKi+;Zf)<3>`{v-3B#>Pi4AANK4`w`20 z`-UHlQO`G&-afqf+_}j_xyinVr>1dV#V>xx9*p`yZYyu|ANMcdnU1#7pP`i zTIpYl7uUZ2yD+bU{pr*-gr^8CF3t`9l4XB< z+dXBuuJtA_RTpjdRR3q}@c!8Mg9ZEe2`7eipF8{FAG3eU+a!B%bNSVm$|ZSrv-g^( zrTpCaJEqj{)K%M`cYk|CUw(Pw)5P_q3m5)w=3eXXU-tg~-jpM=gnTb5Z(sf9eGbPo zeYv^%n}A&R0`qSVKc)VQS-1Mf#z+hOk^|^za7X^xtX+x@#UH3lc< literal 0 HcmV?d00001 diff --git a/cinema/gb/blargg/cgb_sound/07-len sweep period sync/config.ini b/cinema/gb/blargg/cgb_sound/07-len sweep period sync/config.ini deleted file mode 100644 index 7ddee425b..000000000 --- a/cinema/gb/blargg/cgb_sound/07-len sweep period sync/config.ini +++ /dev/null @@ -1,2 +0,0 @@ -[testinfo] -fail=1 diff --git a/cinema/gb/blargg/cgb_sound/07-len sweep period sync/xbaseline_0000.png b/cinema/gb/blargg/cgb_sound/07-len sweep period sync/xbaseline_0000.png deleted file mode 100644 index ae283b3b6f79a0756a7253e60f0a319a966ad47a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1260 zcmeAS@N?(olHy`uVBq!ia0vp^3xIe62NRHFxc>b*0|U!uPZ!6KiaBrR-Yk2pAi&z% z|NsAVQ~r4;T9#&tMSk+VdfF$2XGW9Tp$RRu_suUnEi7ey5F?<&*L2izg9V2e`@u&F z5i%^@%?X8rN^s8e*YgDq6~6q@edy!SCrhP{NB`J-Wbd9?>$cyW^}b52(}_c|<@*1} z+n;Xge)IdC4=1NOZ)f@+=d))cp09cu(=9OX&*$wbrP}{yJm0^>&h6K|KiLz{2iMR3 zE>pvEr{zxGi4CVMiY%I3{$#z~HTV3-b&W;gSC>z#Q>fql^zEPAd&)O5w@=%2vgSoy zZ}{TP(((^`e%-k7v;K|T)0=*qI#lH~`O5VdZ~VIMT}7Gj{U>I|Hy$o3|0X-*^CPYs ztXH3Hc)a)M%_ZCIj(&;#y76;<+su2vZini&Z{2?~B7a{cvr>di*rp?zYf^HTRvP}V zpJZ{q{YC-%rKvjhKTll`KjT^7d;D9pD0gqtpZU#?w=PUkWqcif*4jn>h~c(xJrPIZ zGMl_N$W3P3$J4O;VDSbE8+PI%&!nuRrXm04s&x6;H?-6xX3fugP?B=}+STtI?`%W2 zb3NDGneFNK?Wj)X_8&Q+MHelWzR=uK_(SKt&ScxX)jUkk56)hfV7y`d?aBUcB_69V z|9yOeCEeuf`p*YVE6<(V^eQGtxAywZ8)~bS!tUiIPn~%tarK<}d2{%;ZO)dPa(ZXI z$-2PbF{|w^*4Q15U3>R=^Y@FNcYIcne{eXas5xo!_IjDxc;yR1Iq!?_ZN9(VXoJ2L z-~M@DjDK&*cGZ7BakbT=yYtTN{*`~rZ1=0echPcZrWNdckZ;LZ7`pw#^k|=*|H?~B zOpoxg2e0)C58V{DZu3j0LM`7S&vn-G^=BWwt?hX3*Ad18^QO%?zq@Q|S9sc~(skMr z#c#th|9_Xs;WoZz-X)(<$0GgoS!UOFqqD!hhiUHLw<;!j!+yK1MYrS4MDjWMYtHk< zoZRI0V`0SnTg5*s&zo_dwp}^tt>ullvjukdbP{u{emIEF(cHdsok6E*Q~xp_tH*)- z+F#}y)>o%LNtM_RN-dGo3@+atH(!71I*NNI4NH%uPEBtZ& z((Q%PdJ7B1@0xN=wvOAu+#Bz<%hGAfXWatMUV+%;|BCgTySFE0g)gnY$-3?k*TvZE z&1F?PxaKtb*0|T?Jr;B4q#hkaZFHUPx5MkK* z`2YV+zc0usiMSlSQur*@{E)Ooq2S>)#2@9q%lDlfe)izYJ=*)z z-yVIiN`GC`!wPk7zg;o2*L65uwS66K*?oy4Z)@FD;h#E_mzi5RRX(g}e}7c+k?V~& zPiJ!FpH+ADcRluf!EE?Z@?iI-^wYb)7Vq40sMJ8F i{zLoX1PiV<6rw(9k&a>7)ZL+={Nw5B=d#Wzp$P!(m8ZV| literal 0 HcmV?d00001 diff --git a/cinema/gb/blargg/cgb_sound/08-len ctr during power/config.ini b/cinema/gb/blargg/cgb_sound/08-len ctr during power/config.ini deleted file mode 100644 index 7ddee425b..000000000 --- a/cinema/gb/blargg/cgb_sound/08-len ctr during power/config.ini +++ /dev/null @@ -1,2 +0,0 @@ -[testinfo] -fail=1 diff --git a/cinema/gb/blargg/cgb_sound/08-len ctr during power/xbaseline_0000.png b/cinema/gb/blargg/cgb_sound/08-len ctr during power/xbaseline_0000.png deleted file mode 100644 index 4dbe59509f81aece289326cc39adf71b2e832d38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 968 zcmeAS@N?(olHy`uVBq!ia0vp^3xIe62NRHFxc>b*0|Rrvr;B4q#hkaZZx^jm5MU@h z{r`XJ`NLs?hkONk=dF7;U1g1=d$gNF`Q7ief_n3p3s0yHG>~CEJTi!z`|Pik^7{VX z*M2|yt?8j}w$l4&zHdAubF`+#`^S-$HJdpnWxeHKTW$2m_)ul_G~IuX_X&rr zVLAD(P0K~s?@qqjWAh}rWBOs6=Dn>BdfW3k_y3Xks)dIWRj#I;%}CiS6Wa8TOYnGS zaPR*!zt8Uc@m81rvAL2=*s06Eb>}_T{nxJIQna;A`$5dp%58P`Vs-Ba^mgYQpB-}~ z+yCI>H^1xdGbH6spMH7qi+L7Xt8aJyIJw-}F#F@@kjdZN{#-tOd-CTCwibKepSo{s zB_Xq`K$PeBR2_?#CA#wkTYb}?t^XvlR<7pipHR6c>9eNjm$ZC4_WyQm{5diILtTfB zMgLv@Gv!50%AU4V*?<0pvsjL23Smb5&1sjiir;D;x-grq|F|d9xjid`crJAmmsjh~ z-&1?`@KrfkIit@~Uj7G)3qP4hq{oS_n!E1eed+c}iF(PM3U(*c-$(A;qcZ=SP}P5? z-_?GnjefYceo1t$JF}QyI_q}-v6<(W*LGf!>;EQf-}5q)|My!Pd(Sz=H~&@Tn%P+O zB=;U$n_I86-}_Ui{)d?sTX`n$-Ew>S{ac@E9(`NlqJI0j-p3_>(rDN4=x9qro@tb0e9M5u7{=DEd_RICR zZ@;T%uw`G(wPid0ZeMjqP4#-=ho_rsuFTuQugh%u=!EZ|s23W3FT38`^Ot@PsJks( zytBDks5X&*^JY7z)h_D7Z%^9Z^p#KKJ-le1Tusu(-TU`WYd-V9Mxu}Z&qED~z9tmn ZoV`@hk}#9)AFhFNsHdx+%Q~loCIF^yuay7* diff --git a/cinema/gb/blargg/dmg_sound/07-len sweep period sync/baseline_0000.png b/cinema/gb/blargg/dmg_sound/07-len sweep period sync/baseline_0000.png new file mode 100644 index 0000000000000000000000000000000000000000..c5a976f9bc2a03b3103cc2086317a8670f411efc GIT binary patch literal 788 zcmeAS@N?(olHy`uVBq!ia0vp^3xIe62NRHFxc>b*0|V1-PZ!6KiaBp@Uo2a!AihMu zJ;8$c@Ng3PUh!{oP?Y%7Ij>uf_D5aw-IcxSL(QwS`P<)x^(QTz66E#r=hwQ;R^JxR z`TSs()}0a$n{W5G+?rEexb@qeS&DAo;`4)g-hQ}U^?!PgdPIHM|FtvoQ~qpxE3-## zN9(S!tj&{|f)^pZ~Ms|Hii*a%*l!ZGQcK`Mc*I zrS{xtj(^zq@yMgU|8L#b=>MlBzVk`=E&uZKi+;Zf)<3>`{v-3B#>Pi4AANK4`w`20 z`-UHlQO`G&-afqf+_}j_xyinVr>1dV#V>xx9*p`yZYyu|ANMcdnU1#7pP`i zTIpYl7uUZ2yD+bU{pr*-gr^8CF3t`9l4XB< z+dXBuuJtA_RTpjdRR3q}@c!8Mg9ZEe2`7eipF8{FAG3eU+a!B%bNSVm$|ZSrv-g^( zrTpCaJEqj{)K%M`cYk|CUw(Pw)5P_q3m5)w=3eXXU-tg~-jpM=gnTb5Z(sf9eGbPo zeYv^%n}A&R0`qSVKc)VQS-1Mf#z+hOk^|^za7X^xtX+x@#UH3lc< literal 0 HcmV?d00001 diff --git a/cinema/gb/blargg/dmg_sound/07-len sweep period sync/config.ini b/cinema/gb/blargg/dmg_sound/07-len sweep period sync/config.ini deleted file mode 100644 index 7ddee425b..000000000 --- a/cinema/gb/blargg/dmg_sound/07-len sweep period sync/config.ini +++ /dev/null @@ -1,2 +0,0 @@ -[testinfo] -fail=1 diff --git a/cinema/gb/blargg/dmg_sound/07-len sweep period sync/xbaseline_0000.png b/cinema/gb/blargg/dmg_sound/07-len sweep period sync/xbaseline_0000.png deleted file mode 100644 index ae283b3b6f79a0756a7253e60f0a319a966ad47a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1260 zcmeAS@N?(olHy`uVBq!ia0vp^3xIe62NRHFxc>b*0|U!uPZ!6KiaBrR-Yk2pAi&z% z|NsAVQ~r4;T9#&tMSk+VdfF$2XGW9Tp$RRu_suUnEi7ey5F?<&*L2izg9V2e`@u&F z5i%^@%?X8rN^s8e*YgDq6~6q@edy!SCrhP{NB`J-Wbd9?>$cyW^}b52(}_c|<@*1} z+n;Xge)IdC4=1NOZ)f@+=d))cp09cu(=9OX&*$wbrP}{yJm0^>&h6K|KiLz{2iMR3 zE>pvEr{zxGi4CVMiY%I3{$#z~HTV3-b&W;gSC>z#Q>fql^zEPAd&)O5w@=%2vgSoy zZ}{TP(((^`e%-k7v;K|T)0=*qI#lH~`O5VdZ~VIMT}7Gj{U>I|Hy$o3|0X-*^CPYs ztXH3Hc)a)M%_ZCIj(&;#y76;<+su2vZini&Z{2?~B7a{cvr>di*rp?zYf^HTRvP}V zpJZ{q{YC-%rKvjhKTll`KjT^7d;D9pD0gqtpZU#?w=PUkWqcif*4jn>h~c(xJrPIZ zGMl_N$W3P3$J4O;VDSbE8+PI%&!nuRrXm04s&x6;H?-6xX3fugP?B=}+STtI?`%W2 zb3NDGneFNK?Wj)X_8&Q+MHelWzR=uK_(SKt&ScxX)jUkk56)hfV7y`d?aBUcB_69V z|9yOeCEeuf`p*YVE6<(V^eQGtxAywZ8)~bS!tUiIPn~%tarK<}d2{%;ZO)dPa(ZXI z$-2PbF{|w^*4Q15U3>R=^Y@FNcYIcne{eXas5xo!_IjDxc;yR1Iq!?_ZN9(VXoJ2L z-~M@DjDK&*cGZ7BakbT=yYtTN{*`~rZ1=0echPcZrWNdckZ;LZ7`pw#^k|=*|H?~B zOpoxg2e0)C58V{DZu3j0LM`7S&vn-G^=BWwt?hX3*Ad18^QO%?zq@Q|S9sc~(skMr z#c#th|9_Xs;WoZz-X)(<$0GgoS!UOFqqD!hhiUHLw<;!j!+yK1MYrS4MDjWMYtHk< zoZRI0V`0SnTg5*s&zo_dwp}^tt>ullvjukdbP{u{emIEF(cHdsok6E*Q~xp_tH*)- z+F#}y)>o%LNtM_RN-dGo3@+atH(!71I*NNI4NH%uPEBtZ& z((Q%PdJ7B1@0xN=wvOAu+#Bz<%hGAfXWatMUV+%;|BCgTySFE0g)gnY$-3?k*TvZE z&1F?PxaKtb*0|T?8r;B4q#hkaZ9Vay_2rw8v z{lEW>+?pazjzx>q=Ds_fr`@;r03o~a; z`|tfx==3*T>3XBjeRFPhf0o?!p=-9$_Oyv1UEvi4^=*k6nGbVyj=zmO_Ty+Nd&X8F zmH6$eou+&`^7mQFKd*CV|E!+6CiVBUWoFN2K3@N0ugd#P(wN&h#*Li)E{!zGl;qP59egwDkXRi;e z{eJVH`J=xH7TTX5xKH`-cXrRr?SWtP&v4iG_O_poI(Jr4+U@G&sWzA9CdP$Iwrh2# z_uE>8{(95cem+Hi>+@#kh3&rY`>l^%UU;=ab!v?7T9@axIg0D{e(d@gWOKt>{?UGy z?Oz`F-dz20!~Yn)y#;bS$EE)ji14@{L?NE@r`~dB*;too56V-Xu6{1-oD!Mb*0|WCkPZ!6KiaBp*-!5uakYGzz zd;kB`HzngKN`D&KXS{oJZ;Rub@U29(d63{!pn_J=fq67=Bw#6fY_+0frVw!4h z)OFLp_io)&dTYPwv-xMciOT7PHV;MSRR-Q$>NzRuHglfM{M1M{uOEh&N_S5W|98Ap ze8nvxk$Cf~PFspTRTUf9pLp{uJbKf_zwTXDGd|z@cg9}3=yImW+OwM!HO?-+F4VJK zpwchy%AfPOdv8vce}D5VztAq-r|;gcje8zm=O7q(XYEVA8`nSGxm_1`H>%D#JLc)t z`%hK&eG|HKZr8f&r3%w_RNlPXEq5~0_IBA5@%etK+dge~)!oMabNBi3C1--qKlrp$ zdw%*hV~f(qS`vNvn;uL#y!CB|#@nitKU(F2S08LXw!TPt|KTNXyZg4-THJf}`{|xf zjuBg{mmR7}P3`NzrU^Gc9XTC){;Xxtzs;ZIw@N>ateGZn zuzSMiz}+vK{xqy~^>p+wO+Q|Fw#d7#v}*gDoE34qSBe&{y?bt!O`dP|JB=F;DxXf) zyZYha$r(!OwfWhs`R3NnmmjVvKUwgY|F&=Ztz7Z0A$?J?H(b=Dqjb-#YnxjXMA8YQMSS<3Q!Tk7S?n z7e$pnH`{;9vDi++FI`4Pp#SrPwfE~)em&njBdq`MQQLUe=kw3+I^VN$dC>%A@sH14 zkC*M4`u$>h{QIXTHMP!bZaXbnGV6tK_Kc}t#TKbm-F|D=boGnav@5z&D-ZrYR@{6$ qI(34w1z+3a7JC`i!+{1U#81WtD%Y838}9rE%BY^MelF{r5}E*7^45d^ diff --git a/src/gb/audio.c b/src/gb/audio.c index 19f265c47..47911f794 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -451,7 +451,7 @@ void GBAudioWriteNR52(struct GBAudio* audio, uint8_t value) { audio->skipFrame = false; audio->frame = 7; - if (audio->p && audio->p->timer.internalDiv & 0x400) { + if (audio->p && audio->p->timer.internalDiv & (0x100 << audio->p->doubleSpeed)) { audio->skipFrame = true; } } From fda7f83855dc3972a3bb682358da243a6554f23e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 6 Jun 2022 22:55:04 -0700 Subject: [PATCH 037/102] GB I/O: Fix writing to WAVE RAM behavior (fixes #1334) --- CHANGES | 1 + .../gb/blargg/cgb_sound/12-wave/baseline_0000.png | Bin 0 -> 628 bytes cinema/gb/blargg/cgb_sound/12-wave/config.ini | 2 -- .../blargg/cgb_sound/12-wave/xbaseline_0000.png | Bin 785 -> 0 bytes src/gb/io.c | 4 ++-- 5 files changed, 3 insertions(+), 4 deletions(-) create mode 100644 cinema/gb/blargg/cgb_sound/12-wave/baseline_0000.png delete mode 100644 cinema/gb/blargg/cgb_sound/12-wave/config.ini delete mode 100644 cinema/gb/blargg/cgb_sound/12-wave/xbaseline_0000.png diff --git a/CHANGES b/CHANGES index 6f0f13670..e644ba15e 100644 --- a/CHANGES +++ b/CHANGES @@ -23,6 +23,7 @@ Emulation fixes: - GB Audio: Properly apply per-model audio differences - GB Audio: Revamp channel rendering - GB Audio: Fix APU re-enable timing glitch + - GB I/O: Fix writing to WAVE RAM behavior (fixes mgba.io/i/1334) - GB Memory: Add cursory cartridge open bus emulation (fixes mgba.io/i/2032) - GB Serialize: Fix loading MBC1 states that affect bank 0 (fixes mgba.io/i/2402) - GB Video: Draw SGB border pieces that overlap GB graphics (fixes mgba.io/i/1339) diff --git a/cinema/gb/blargg/cgb_sound/12-wave/baseline_0000.png b/cinema/gb/blargg/cgb_sound/12-wave/baseline_0000.png new file mode 100644 index 0000000000000000000000000000000000000000..960eda9cea03b235523a6d2707fbd971287b9aee GIT binary patch literal 628 zcmeAS@N?(olHy`uVBq!ia0vp^3xIe62NRHFxc>b*0|S$_r;B4q#hkadFBZ*mU~mY0 z@#Ft~ANey2LL;tZT)t=dT(hw?rD${a<29c*=?KT}ulptbU^7dfu!Y|Pi^j*pnelE* zo$2|{CcdXP#mu*px7lrZwEkf>TYP)W+LPxq&5wWR|2^yA=}mXOS7)8Nr^7J&{=GZj zs?I1st~~g%;>3sb^<_66{JK>+@A%{VL-Kv;4=g_X-Tc$w{ND!gY32Sc+h=?iyL#~8 z-Ri$HpFCaqW2OA58#Wcc>~@Q+PkhJycI*5-RsRk8w_D_w9O0BvFPL+nkm)#1#`4S^ zcOR|a== z&5NqXf9yBTi_*ViZMQ>ozFE|w_vtsX-cROg_BWU@*Z$Ea7ki^-{^WeQ`Sa?heb)Qt hdc1P6GJ1^v<_(?sNG|!Rr4%SNdAjb*0|V0yPZ!6KiaBrZTr6rb5MchbKM3 zg8A@}75YA--b<7B@Py(xI~zTjwQ`rjXY@TtJ#lkRjZbup`~N#7EYIg`|H~)4X*J`5 zAFs1EpDz8jW<6j3H?4>F($)7>M!NG`1h_z(zN(3C)@Sh;I`A&Z_V@X*`K*AJxAQ?0TJPM$E0vk@~$4??0tvU zMNW0yx+T2zfBx;CK^Fz@%<%|~-cfsMp=FrtZOwgGCmZjTjGKGx<+`ns6Sh{CY?a)! z)%5%vrf>VVS6FX1;=TAdj$@fpylKe1a2vhjKRpH*kcJs>od7sa{WtlIUb$ciO{~HhYTwuhAZ8_)nvD1Ipf9{X7zgg^^ z@Z6lE;$_;)w^3gfre9mfS^uKx+n$?G`Q6_K+zoi#R{!~5_VMqVk8GciJ&k>x>-Xxp z&6h8Kdicj=js#ow{TbV%>ViK0U2W(Rzhl2&o|eQS_qxKUKob}C%jH&c?!4r?SbObq z$u<7=`?=eqDvB!K+P-audio, mTimingCurrentTime(gb->audio.timing), 0x4); - if (!gb->audio.playingCh3 || gb->audio.style != GB_AUDIO_DMG) { + if (!gb->audio.playingCh3) { gb->audio.ch3.wavedata8[address - GB_REG_WAVE_0] = value; - } else if(gb->audio.ch3.readable) { + } else if (gb->audio.ch3.readable || gb->audio.style == GB_AUDIO_CGB) { gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1] = value; } break; From 8c83570191f7be6fe4077093ed476411c9a83bcb Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 6 Jun 2022 23:12:25 -0700 Subject: [PATCH 038/102] CInema: Add remaining blargg tests, except for oam_bug (closes #2006) --- cinema/gb/blargg/halt_bug/baseline_0000.png | Bin 0 -> 1313 bytes cinema/gb/blargg/halt_bug/test.gb | Bin 0 -> 32768 bytes .../gb/blargg/interrupt_time/baseline_0000.png | Bin 0 -> 882 bytes cinema/gb/blargg/interrupt_time/test.gb | Bin 0 -> 32768 bytes .../mem_timing/01-read_timing/baseline_0000.png | Bin 0 -> 726 bytes .../gb/blargg/mem_timing/01-read_timing/test.gb | Bin 0 -> 32768 bytes .../02-write_timing/baseline_0000.png | Bin 0 -> 724 bytes .../blargg/mem_timing/02-write_timing/test.gb | Bin 0 -> 32768 bytes .../03-modify_timing/baseline_0000.png | Bin 0 -> 740 bytes .../blargg/mem_timing/03-modify_timing/test.gb | Bin 0 -> 32768 bytes 10 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 cinema/gb/blargg/halt_bug/baseline_0000.png create mode 100644 cinema/gb/blargg/halt_bug/test.gb create mode 100644 cinema/gb/blargg/interrupt_time/baseline_0000.png create mode 100644 cinema/gb/blargg/interrupt_time/test.gb create mode 100644 cinema/gb/blargg/mem_timing/01-read_timing/baseline_0000.png create mode 100644 cinema/gb/blargg/mem_timing/01-read_timing/test.gb create mode 100644 cinema/gb/blargg/mem_timing/02-write_timing/baseline_0000.png create mode 100644 cinema/gb/blargg/mem_timing/02-write_timing/test.gb create mode 100644 cinema/gb/blargg/mem_timing/03-modify_timing/baseline_0000.png create mode 100644 cinema/gb/blargg/mem_timing/03-modify_timing/test.gb diff --git a/cinema/gb/blargg/halt_bug/baseline_0000.png b/cinema/gb/blargg/halt_bug/baseline_0000.png new file mode 100644 index 0000000000000000000000000000000000000000..213cc9a9614b621928b1bb3b2bbbc5bf3afe7e53 GIT binary patch literal 1313 zcmeAS@N?(olHy`uVBq!ia0vp^3xIe62NRHFxc>b*0|UzoPZ!6KiaBrR+%9{qz~fRF z{{R27fd_~q1iaN&Um0SN^f1{NX` zGF&`-tZeN}&CWy$pUdZXXwfI&beZktb=9@us?7z-W#LndcPuznC^P*}iq-z>@h3ec zy+h|_eLVT;=FdI(HE(s#y{xAP{@cBoT>od3SZw(K99G?^%Zn^*I z^qDz(gR9uqnW^@FH>x*wGObH# z#BlGqYF(?HMqgtDbFwsi`zJ@|1@|1+&u`4 zT)Bn2`Qkg72NvDI;x}IXU3@HZj&9JGb9;|gi~iMdE4jUCUg4|_UBaJUneElzzaf^x z?(kvHw#$Ca|8S%F>z%(^>Xmhhb&bYO=JW2i|49B*yT8Um_vmrmf8@rtkJ(v>FRzK=t1Zy}24uF|RdB)RF9*LI6nwUCvy{rd z7Q2W>kQqFm4*C|d{dnNC;*-^^-9HTuv2Q&Fn$xEq(SNe<+9{?r zhb`pSbX-2kZtc6x>e$Z*S07n?-MaS8i{{whx5C_hB&^=IX(4}K{Mx?F@t%eZPu{p3 z`g}cY|CjnV?CX#1?lSubWayuWPKf@0yzYb5jr!da{ytc`VY_G8$%JY1**>4O{`Fvn z?yrNwzt>+?Xg=N??pl4y%%yQ7|GByQXYsG&6HWfrmU7sB+13tSlgRZZ+B!i+ODkR{ z6n($DTHa>am)PU%?{DzGJ8NZkBXiSL!*gnDpEb|@bt|mw%fWTEx!Tk0b`rM;G#&rL^#e9pU_P&idUo?le*xhI;%@qQMC z<=1pO%jYl^l_@=(x`_S9xvRep{(kdfMa|DMN6Ob-d8O#O8!FoOBklB#m)Rt) zuD$rTCjDoHqTlt8C(eJLF;oACb>yYbbALUPtu5$DDckk!>>Y95IEV+A^6MR0$Um=j zDgQa3d**qF%g<@HtFVc!DKO%z{UGw9dFk`Z?7Lg+EDCL;R~L)=%C9*PyiJjd?dJo{ z!lo>@XOF7q>`Uz7pC{`6FuVApU{27a$fav?Wp=LLx{2X+!T(oYKYpFnk$4{F5odh+ z{hld@?{}9y%Z|Qzk$v~Kt!vlp*8la}V&TRvvpw&v6w=j&!v1}dG;G9D7Wgfaw@H1O z+#Y&ZvnK7s*2a={xzlzbvv?=%^;Xqx`}7LTB3!g>^kQXDE8^v2N-SmH0(B zH+}x)VRh3XprX&y)z4*}Q$iB}v7>=_ literal 0 HcmV?d00001 diff --git a/cinema/gb/blargg/halt_bug/test.gb b/cinema/gb/blargg/halt_bug/test.gb new file mode 100644 index 0000000000000000000000000000000000000000..38e36625d805e68cb3b8cbf562d6dff500060bdd GIT binary patch literal 32768 zcmeI)O>7&-6#(Ez{j3$4qD0qdCaz*HrC3o^8)pAp0^Ll7)Uja{snZ@>G>3ZCTB{@= zC`C?XDxw)mN{zI=G{~V*4K%t20h$JA>o^Juu9jrAkjIDt+t>hBLZYF85{^K|*u<6v zvTugA4{6T@jK0PGz1f+0GvChgNPz$I%^8WD|HQJ+b-~uw<1i0F=z@;$u9trep)2PS zSJ&1)SXf#b`$Zyj?cCaxh1ZwPeuIBOEQ4{2DjPku`wPz~Bmoj20TLhq5+DH*AOR8} z0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq61WEi4uv5*w5?aawY^LKJn2C8dIW|; z+npyP_uyn`$Rt1lBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQc9 zjDYj*a&`Fr_p1l$ztcC|06nDIv;39faG)n364?N#bD()2 zmL)yv99Cy+fF(tBE~)eQ6XBn}E?!-B`j^G4w)nk$od=2y4#n;%NERF6Z*H3|b^}a> z+k)WpfLP7)1@ZSR9}{n7Yt?QsV~fAqI11O9bS}3?H+MzheBk{RaL=sx{3BWEQT;O& zG-R`j&61kyr^I{NlQMGu^L4lkc%zsp&KBp2^RA!2RF2Fy4(|QI-XHJ%(?G{+Z1sWF z9lN4EN0aNH9GYH#=g14|^FNtc*LUk54>bBF_dK^}qIAK=9QDqeW{dL<-g5o+wNqV7 z;;8*EpS6nb+Cyjbn>AOQvc;QfE=y`UzOd~(ZSc01_a%<)`bk#yr&-B=fvx#7>;pf= zF8L?f1wWs}YST9Rho67!`|MLcf8YsrO=z~i`fagl*RFQgJ7X<{ErqCa-tqG+=;yIu zYv|b7i@qJ|6uw=E;$U#p+P=0|qMNfvk{C|ArLy1OKUB$hCo8jFsxs%*+_Gq0W-SeT zmp8L6(#u8hkqsO4c!Fkx($auzJ`=f*ZWZm-Ff$_xXohP&2_{N+!mOe9hpIkae zV5`SL*`7g&hJ8`bJvOaH>%TKK%Ay_^wwY-hrTX-vt7TbY8*~HKRTHh ziR+`2ljD;p*FYHFSpnc}m3faZR$lV>hn2u0|8u2fk&jeb7dceg7I~%ui*DK9m`CK7 zys`fMa1!gMu=-bPCrYmPi{qTm_-;7q57}%`)YN4uv5I3^J{n)@QnMp*Gl#>)Gxm}%Z=CiD z9XJE7M_%)^?O$)#H~9k2t%P3{X2oh)9hV#=}%V6r_+V=Nz}Asu8v4aANv0<7iSwAhSMWa~XlDoWeEf|w|<$n7b1(_wvz50K0$5Y&G&Ypu#m!Lpu!4%G;`>#MDP?{`_JfFWlX-Ac`7Fa=fPG!AuVa6f zA%`xX%ONyfFyBtqY$puM*=sG3RB;k|V)4S=_W)4On$g>#p>gbA@#6eJN}F;%T;;{s zN@Ls`O(DB%gXLU96Xe4D3}To8-y`bdHi39?Iscdn4Xl4n0^qe-U-l>G-;7hH>JK}V zvGl-LEb*0|T?Ar;B4q#hkZyFBYvbU|_ho zhbKM3g88td z#JK|ngHUKM({YL99{D>{{0`h}x9|;qY@E!aXk!1jWb5tAx4*?dk+gWb`Lp<*8xt=( zzm~1}yztI@alQHZHqikn~0xAgO+N5$IzuJ7@EZF+v`)9&)J|BaW(Xy7;2I)$1lQ zt!^ye^Z+%0tM9EkbGGZsxoKav$^C8lv&Q3Xj%WVsz=%1Eit{7iM&G<$weRNb@G>+1 zs+~_Q_pW_@dN0#_Q`u`k;W^a&NP3jdYI*UtNJf%+qUy z1#9nA<;1+}EBx^2b#7~R@t*1~>thFVw@a+8?ovE{ux{_BJ06b{)-RI&VaZ-@z{fZB z`Qdx#SZ+zPx1U<*k^eZe^>AUq?Z8Jh1@?W%4{n{q|L)XBiyhNGAB>eOl37z!{rEv! zf6Dqr)sLS`g3RH+&jxgWybMeD&Qh70YY>|^d_E{&a@^v^&j z{6jHc-ihEXr_htxj{6g4_V1oqF0cQ|?B)X#nezwjpK9#fF7s*odj5Rn-Nv!GkK>O% z+1D#`Fa1{eGFI;S(VP7KUVP1Q@8zx!H`FgVzwF%k)Oz)$tKa-CzE;+mIluaO{N59~ z{Bm>UKUuj>mpRzJ(R_OQuk%H7kN!-s$S*m7VSjzush0w~c!OL)dCAk&&t;ucLK6Vk CIj^Hu^8GYbz5V?-{(pN_2Lm_0R+Q__WLv{2GEKasnKZR_ zz4?3M`~3RI^3u|0Ggq#h`1Ocy<@(a+Gk?Bv`N#B;6w)9&?YTWerAO9KL;^?v2_OL^ zfCP{L5ZcVWh8(EkN^@u0!RP}AOR$R1dsp{Kmter2_OL^fCP{L z5%>@YxmrHf_=)J*8XI@ZHR}VjX8LK^B-CLZYatc0 zrfbYh)3n(}Yi28LGPm=w0bITB9T%mmJZIZh`r-%dAmi3e;^jLhq+5rrV-> z*^Ajq*}v?{Zm7JwwxL#Zh~zH2=cRiU{T6#WeSXn%Q*S3__oDla{C0R=ve$RaOW*3? zDX7zw8H5b>&@<+4-6}#NKcElHc1Y%_K(GcY?bLZmdQhn7OijZ&pMW)s`q^-n&hZpL zFRA1QB$DXrdSpGlwH_h)XC>0r6(Qh?wwf(=$u;vyI&HSuC9mrmWYpmc_kQ8czYEUodAm!kDA^&C$H+T$}v=Yzg^H(?LKIL=INEKZxo}hkTYIn|^ zckGeYMuRnhbiD20|+|khPeak+6DRVfNWgSdS8DZaX}pEn}hK}Mz_Ii z)Qjguf|65O_w_f2ikq5XbVvLrdm-IU*uHFg6Z|m$cLc}kFIux+Mib>>B@7FYg;$sPT>1 zD%eV}6WIyAuK)L!ql*M`PnnbElsTx^`s$ul7H`|NUT7K9YYb-_aFrc`3g7 z_0hAd9}k>coqpl`shMYA&OkP62dmi<*v#F=Z%h1Cn1rHNikgNbdviFDP>HQCXGaC%Bbi?_P#1QYox&blGOoy zk-63922Y(DI!+3dsK&y2%7}*C&xHOh`uW=7(UGBtE0f0P`jl}ZIUjlgECB-if_k+k zIjI9ot#aysRi1=*3f}1hy!5R%2;Xfvbw%1 z-fi(Y_-5}uP0SK89LdH&%3$r9;{pk!YA}HFQ@L>)ezBQUoEiRxeB|kt6ANG+A39t zA^EtoBZI@Sq2u5K_&t=Q9&q`Fz2DosE=szar46^VW^4SM2Ok-XNsz+mN#IulJk$gK z?t{8Y(*~U_y=u_gCC4oNu;iSjgQbR9N=mL-nktc5y=bjZ1L{|e6Fq%o0`wE0{=>?d zg3g9C_1T=}*mb`lJ{J#?R=N=27*%oITZQ_E+=|L?=xxryv#ng@tw& zt-y@YTYXJ>qEeMY9`-3Sa2=tLLLX>DNs=$&cCc$C7g~Kuo zlA97CvP_(U7aaDJs4_CHC{ZGEdoc+zUr3UqSM&-n@9m7nk`OB?Cj>4>WjVq1lUywv z27QG;yr+UU!sGI1vkwyAv`=V=9cw1P%p&)?TAc?2o92pLK2F?ADEYA8T`g$ zilW5g5MNHnGUR3VGNH0O0wD>kf|)|1Jbf`r1m3_7Y{tMAO64s{a;w$FTrNkH@njMV zdA`u1c05q9uKPAdj=j%L$Iv0qy%Qo9Z z`g!$&lf-Q~PFfiU>`XFAILlm z|K~y6jBhXiNbs|21E|kKKCsF5`SFQjnA_Rmfy)lkdD+Ke{j`1TGl(FoR-M z-})5ndHg{FNB{{S0VIF~kN^@u0!RP}AOR$R1dsp{Kmter2_OL^fCP{L5b*0|V1sPZ!6KiaBp@T`XFyz`ziA z;>Z8}KJs${l{!{<8d_J!y^C?`Dbp^CO7ha|cy0QN z9Vi&)LcX8v4UeU2ES++GM*J2j(SDn|*i2OI zZO*Cx!Owg&znb4Wb7p@~wYJOoA1lw_O^J(J)i>q7@Y6s4UUT*Tc@{DM;LqOMV%$Gh zYc5SSjCdA)eEPv}f1H1wIlEiR{YK55hkt%Qw>(nC{(XMx`7=d+Uzf>z<(QFwKlt_K z{#kv?Yfi*{`m{~1)K0uFKrg}nGuM0jxYqB-L-)zV?wj=I$J45a*eCimNnc~HmhO1? z=FcC&&pvz4-+j0${^LgV|9|FhIKC5+uI^hoo9~ZiR9zGKGyT;J*edXl;$|HDVu UHL^C<6_j2*UHx3vIVCg!0PFcly#N3J literal 0 HcmV?d00001 diff --git a/cinema/gb/blargg/mem_timing/01-read_timing/test.gb b/cinema/gb/blargg/mem_timing/01-read_timing/test.gb new file mode 100644 index 0000000000000000000000000000000000000000..660298b1ee8ce2fd1128db5921d0312fabc30519 GIT binary patch literal 32768 zcmeI(Uu;v?9S87V;@E&=3@JQZP#Uh27KK2B*)*0>_lUKKXqpODJ29;f?ad&UF?miF zBI1BCPEx9FQ>UUzRZ}FIzD(K+tPg`Sq|VoWGOohuhE$j5-3^U6wU^&F-t3eZYg-nQZ8 zUr_L)E3un5ZhSa>>C(advEZ#MH$Iwv>(a$<3Ug@a-&c`B#Y4^b?l}4TuUC_^u>cFO z01L1H3$OqSumB6N01L1H3$OqSumB6N01L1H3$OqSumB6N01L1H3w#v<{cV))d8l3g zV(m)(ZahorJ0aQ`T$_D5^i^czFr0_cX}OqwFPBbt9k0Eu-^uk78>i>cv!XqBvQcvYq_3a%if) zyLV6TzTUGNm(TUht(#lFA-wv9`21)6zyN8e!gY6bQJ?T zHGl4mB}a2O75dWA?;cC?uJx&-dE{TMo(uZtRa%-GMKe*Ys;zd{fWJCRLAX7 z+3D))siX?WD-(r8WwKDU8+WfxC3(uSF;{i3pB^}Tc<=y~1Z8D*F;$3kdmr!qyS7UG zwreOh_~4g`!qDPm;b8JY_X_j`0>06_R@a+F6S_JJsjbe!1Y!~~wN)+s%UF}C+6$>m z`a=s7f6!MhOk#^HOuegnvaeavpUr-n>A`wiaq&@~pdi!`pgC1_utjFnZ`` zhhhi)eysd8%Ml*A-xBVwl4>8xx6|(Gk=cZM_w)kFbbZ{g#5Y-1qMutYhH1$sD%dA9Ep^43ccghv=8VI*wv(Wx9X_Zx+P8 z%ISg}$!pJr=nY@X*cSc%BVPTU4auMQR>Sg;IDw%59$x*1Xe#a%gdAwI*KWIz_ZfNL z^7U(e+u4b6EU%8oMjp+HQ^lQV@uc{q*q?np?_O#v?yTD9v}TdInZi`mlh*xk*$GV- zdTJ;271f&F?Uz5!JJs{O--?al#i@G9xAK@SzA;L^ym-1WyBsSJdgzUUZ|yg{`h78t zwUyMf=Qc)*>n|6dsM^<54cDJxIfSIQ9(_nUQ(~uWZt^BnE7haM-{J zUf@f`FsRuVz<@g`V#bb`W`s1=UrVB{en?U>pap!m9%zq5lgO1c5&sXXzLwl_jjHxgtG2I9ELzd9YsO|7pw+q+x)hX;Q*8)d$xN!@#)l zsA-zfIPx0_!@#`Uqd~$jVn|8&72QmVsOf7F@~MJ;=rfGIgi%nEG&^6rK07;0=8+f@`5wyRh0B~%ySL3PmH|hz)9S;Mly7E9>Z9LpZB@jei zr4fxI)=v<)o=|($1!!Eyd~lQ9{S(x*ub*0|V1+PZ!6KiaBp@U(9PVkZ?%M zs`wwiPF!Vci>!r#v__@d{%nrk-eFxzx-$>lp!f6uGfeeOqa{I^|f%coSmzVUAE)Du3I z&vV~D>v=kL_3>26v)_Gd=G@!!RcB)9x4Ly#t=50FYHBWJU$3)X{(axw?3}gFRZc&Q z=1Xd*{8RFWY1^AAProjY`*zMw$4-9#J<;jaK3Au1Dqnc3TC30hzK#5~$5%dIi+;2_ z-}+p|y}hsB_*P90{_>*am+-9WKeyyx+3ipCZ8#wHSwE6+?47-A`_J+3bMx)rEl6vxVLBDQMzU0?`HQ@;AY)?f4@JS=HFev=Vji$_r~IeorG7q z^xQ?t^7fHk*Lr8)R_{O8y~e&~Tivd!rSDlQZq@5v58RV0cFw-!0D4N=q3*lG+jzh3 Rws)Y^>gnp|vd$@?2>?8MM~DCb literal 0 HcmV?d00001 diff --git a/cinema/gb/blargg/mem_timing/02-write_timing/test.gb b/cinema/gb/blargg/mem_timing/02-write_timing/test.gb new file mode 100644 index 0000000000000000000000000000000000000000..e92f553331d9d6c097c50a16dc89521e4c0318a0 GIT binary patch literal 32768 zcmeI4Uu;`f8Nff=@lEDBZqilgP-X3PvPEv%sBRF&0`I6AWl@IKR;Z$g3H3%aw*-un zrGMhAj_V`^4aUPJ@vtxid1BfNWfE#vDk1-0uG%xL(i-l>!fco$VY(2nT-Ig5m+xGs zeE?oJ@$enp@1FCW`~5lJ@0@#;7ss|g-3I?}Ek7K5<9%Jf(GFWYr(q8K&<<^#yPo|K z1m3w3Us+y$d;Z$BQ{RpUZr@mbXa1Mhu6~Y(2l|hHZRprnP8=J0a_I128cXtk8}GqO z$3I<~l#K`w0U|&IhyW2F0z`la5CI}U1c(3;AOb{y2oM1xKm>>Y5g-CYfCvx)B0vO) z01@~k2n=>Yrf*x9`tkO5^}|FSGIxS-Ft9y;H26tmqnJd12oM1xKm>>Y5g-CYfCvx) zB0vO)01+SpM1Tko0U|&IhyW2F0z`la5CI}U1eyf$Tk{;s3U4j98df#vwK+^)4*kpG zOtfU{mnJVWfKa_sHxAg~83%AbjWU698s!YiS(Hf>{QbLo8%j6I0Lq_H%3ko)ympK5 zWUAsDIfgcs;O>mLocVp>Vy0)hF{0kd|0Gu(JiKSmo|O1Zt|~5NzX+9t*zXMcp)$2O zRH0I7#&AK!=&Rky^ws`>Vr8ld6vexlY{MH;8g|Id+FB9~pZYfi5*0)EGrawIECnlb zdF@WD&x=3Qx41`^x9+u#{8E0&8{XIzhBsVqE`o7o(c}Tx7oj1%p-o9 z?Yp9WR5!#QvjTF$mlGX1@p9I%km5Zb9M+3gR@~0we1cW2DORzbVawKe_O_K|x2$P) z(<&y=Y%0rMw~CK_m3?3p4?W3li>I>I^)CoDS6|uM@I~CE)>1e>P_T;3ZxwN3OW@?y zx1PuaeBy~*DU6H3RV({iUI=f@97&)$WmKwGPfuShZBEx_%w%oWtQ*bkv!NmmXANAd z-0Y*nr%#WZgbIiJbNThO84Yg>d7C?iq~`bU*-C+ z-Ytn&)ent3`=LCzQVY59^whv~rCNh&Qy6*I1qh~X9N^2+in0|2UzKt%Povo7NBCs< zVUb!Cf6t4dg7}_ueDVK8OiqlR898xg^!uanQ$8P-el#o3o|@&(u@dqiiII#`KBl(B z&-3CBg}S(~m_NH{VUhKQ%Txmr$K%7Jv5}J)13})?)E*4E-`V&r{uU11?dpbC{m8Kx zik}&oh!4lqk%@`12?S{)C+@2O@Rr(~$roxDP5!5vYk~i!=3d~#HO~TvTFU}Y*I>b@ zTI+Mj{GxfP=KxHjeG<+0)F<(kVuie2D7toj>`A;DQq~SNo>wj0&{|;~%$1J9a|Jwq z(}f_+20-Mn|8c;^o^P+so0#BdCcj&I$rRxt`(_YcR9YtYsv8e`)w>3w{EpIrFh}_X z6!_obRhPM|e1rq$K${~*=h>p76_vIf55Cgfjd8MG72g{XDexD{2hrlo{JrvE{#enO z>MS3u8<&`yr&rRr6#1%!9;#Zwd9$za1NDJ=Lk;iSD&sSPXOYVbu<**@S^H~2i(R*^4Xq=05DvAS_f8jtn%?%v%wZ$7l6`#k2j zTe*4v%fVy=2C-Po`I5vMF}wg6*P=?2fgWRFt@K0aI?xpv)4v3Mzu&P7bfI5Y0LCNO zNARnxNA0MNj~Gi~z-9}FH5{ZiH2_Tmx8lcu2O+A*&*^#;nDl2U)a8Q|r2NdU;Jm*p z8cSiWl$KPa9@Vs@v`bEyjz0%ll5>X zFY0;<^{#Ldu}dGE=L#}GT$rCh1T)}1B7JP*2rnk%%z{qbWYZwOo9YzF*01+SpM1Tko0U|&IhyW2F0z`la5CI}U1c(3;AOb{y z2oM1xKm>>Y5g-CYfCvx)B0vO)01+SpM1Tko0U|&IhyW2F0z`la5CI}U1c(3;AOb{y J2>dsJe*@ghw{-vj literal 0 HcmV?d00001 diff --git a/cinema/gb/blargg/mem_timing/03-modify_timing/baseline_0000.png b/cinema/gb/blargg/mem_timing/03-modify_timing/baseline_0000.png new file mode 100644 index 0000000000000000000000000000000000000000..3deadc0bd6aa1d2ae73270447766d0115e801433 GIT binary patch literal 740 zcmeAS@N?(olHy`uVBq!ia0vp^3xIe62NRHFxc>b*0|V1)PZ!6KiaBp@-=4I{fPvxS zkw^dQEk7rS9=XG#JbmNx^QYgrwXsBBn00hU5Z9xsJ9`=Co<2~()@E!lr|}^VPkMp{ z^I=JebHiI`$J3wgJ%zGfnpc~TI=5G!oBDpgoMu?*rKGCQa$El%P4d!=Pb%IiE_3*a z2>ZGx{q2^gCjDP*mwNcz@_##1-{1;?4iJ+*`JPzPGMQx%sh_%#|n3 z>NoE-C-3f0{uA)K_WN!V`<*89KUVX9`{f_eC>X)~PmP;k9PUuP^F{t* zYkiUM>#uQnyQJ@MFVx@KBR_A?{GH!ZJD&YGQ+v_s)VH&3p`WcRi;I7r`Ellc>4LXB zawWPp@xoty|L*;Ga9zo^i>kZq4u}2RYX0BLCEuo^?B0?;pCW&LI3l|;|9->af8UE_ kkKRsu_{WtUBYpj5Jq#M3BqR+Uz!G^^fE=RWy^|ethQ>}w2~LqETz31 z1V`q8<9tAxxP7RSm&!O&%2TB(QXC#);<$3TKYL|`$EvFsZKROisX3~i9K;1}>|lD= zZ}zY&Reep=O5f=A+nwE+`DT9mM}9G-(wAG{f2|~Yyw^X`^=tL8&2<{4zzy|K+pzoG zFTwNSwb07)@(0sbuJrvR!#_Ovy`#sD9*^OYTu_P8 zH~!w2t4Y~NfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14c zz6gOM4KVL}uu;9cvtGR&PQv`U7rHz&62Cjly5-;iNZ0aw+cM}~)FXp*5-hR0;+kb%qavJAhL;Wsk8A;a%vcuR&$ zGF+7*EyHygmSp%yh7}oBW%x{nA_n1_&xt=K82(TDtas16NYA&77vEHGC)X3ADL#6& zMRko`UC15ZdwB2Oy}sh2S|tu7qGCLe6AvYxg6ya`?;P%j?AX>}J7mNEK0AVk!js6B zvs6IV^yQz6`|>}+?Z@$)0^*stcq)DZw;yE9ZmeCNuL>9II_(h!PME?ykA59zdBdw{ zcM<;{fX!V}aih9qCV6V9+P}Hm57#UHya49hg3bRbFFvh)=2S{zG|t~IpDCDjM10)TwF-uAy>Edb6%7ZPGv5}7u#-s^*h1;dVu?mdB5p4p5U(T(E8CH=GF_AQCoiOIgSl-3Pi*s?y8QlZ!c!+^ z6KOwA24}78uX@eDInf=)>WG=m*)1);e9RipPgs%sq*XA>cdrCl@lM>txyrkLqUZGK z-cyj}kX%o0#H>JD_0w&CW83AmLj$4Sdsil`fsIM4FFM!u0QN)#jM%(bQY(1{cD2`H z`|Y&}+$M3G+Ao)We>;#Um}{{s>Vs<&@2T}`lb6-nwW)ViS8^^c9!n5AdC=!EHNk_(o=0c?`Ew=21SJc|@!% zh-Xt`HYNVzEDrx1#q$HF`t^~MFZMs*AL^^C!?n-F<-_+%oIB5zkWZ3$bKY4$=C(yu zN_@*Gh`%o+mlteYWuaJMsUGQZxTinZdkV)u$$K@m1&4HA4s)BkibHd~x>>D$?zA`> zda-vX)Du*DhlU1*P_l$jye<#GtMXG8pUJ;u@sIKqGyLs*M-Y z-k3u4m#n^)4j9Mw5p2GGPIt5tk)#7v66mg&M4-{v1@jwJtJ zIHwviT?O+ZtK_kj7*0jLYi$qbZ11$?EB-=#piorX>clz2E?jDVGBk{zSJ_J#22K|v zj$-6CUboVYr5#kZ{77+Wlz%N#72H)Z32*490H8m6s>cQub; zjyu^K_dgv>7GMwz2Axkyuo%Q20OMLfi7?QE%&(NXj(+JkIH6#KepH9Pwu(m?v#1uZ)@)dnZ?iKTroZV@L2XN=fU-2 z{-1?34h#o~>N-SpUHD-FpT-Nh^FDZoV^BI(?XaM@G5rGAt0yE0-(r( z{jkp<_Qj>j5{2|?aVecngMKC&#g1~mSOQKyY~a+-1UsBMrj+>uavVgIMdrcc_ z2Pv(|^>8OI*7YdX8~qVvmwoU&SI`8xFh7G%%z*b1^|1^hUQn*T)2Rlq{VfTA`*M3Z zo?L&q9?_ifa6nm?9$1$T9^OYO;K8~~!^?YIKcK);L_VtyK>0k*2XC_T{CF7i%YIIJ zbQxsKjnl$*+NW=nA6+~Kzz>Z4c(S5t(!cjefCNZ@1W14cNPq-LfCNZ@1W14cNPq-L zfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@ K1W4fjN#I|aZiWc} literal 0 HcmV?d00001 From f9e03e718238a83ffcb732c8ab7fb012d4489bf0 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 7 Jun 2022 00:05:27 -0700 Subject: [PATCH 039/102] GBA Memory: Implement adjustable EWRAM waitstates (closes #1276) --- CHANGES | 1 + include/mgba/internal/gba/io.h | 7 ++++++ include/mgba/internal/gba/memory.h | 1 + include/mgba/internal/gba/serialize.h | 2 +- src/gba/io.c | 35 ++++++++++++++++++++++----- src/gba/memory.c | 26 ++++++++++++++++++++ src/gba/serialize.c | 2 +- 7 files changed, 66 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index e644ba15e..17b2df376 100644 --- a/CHANGES +++ b/CHANGES @@ -67,6 +67,7 @@ Misc: - GBA: Automatically skip BIOS if ROM has invalid logo - GBA: Refine multiboot detection (fixes mgba.io/i/2192) - GBA Cheats: Implement "never" type codes (closes mgba.io/i/915) + - GBA Memory: Implement adjustable EWRAM waitstates (closes mgba.io/i/1276) - GBA DMA: Enhanced logging (closes mgba.io/i/2454) - GBA Video: Implement layer placement for OpenGL renderer (fixes mgba.io/i/1962) - GBA Video: Fix highlighting for sprites with mid-frame palette changes diff --git a/include/mgba/internal/gba/io.h b/include/mgba/internal/gba/io.h index 9875061f3..fdd480037 100644 --- a/include/mgba/internal/gba/io.h +++ b/include/mgba/internal/gba/io.h @@ -154,6 +154,13 @@ enum GBAIORegisters { REG_POSTFLG = 0x300, REG_HALTCNT = 0x301, + REG_EXWAITCNT_LO = 0x800, + REG_EXWAITCNT_HI = 0x802, + + REG_INTERNAL_EXWAITCNT_LO = 0x210, + REG_INTERNAL_EXWAITCNT_HI = 0x212, + REG_INTERNAL_MAX = 0x214, + REG_DEBUG_STRING = 0xFFF600, REG_DEBUG_FLAGS = 0xFFF700, REG_DEBUG_ENABLE = 0xFFF780, diff --git a/include/mgba/internal/gba/memory.h b/include/mgba/internal/gba/memory.h index 59b22b457..93d565a16 100644 --- a/include/mgba/internal/gba/memory.h +++ b/include/mgba/internal/gba/memory.h @@ -172,6 +172,7 @@ uint32_t GBAStoreMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum int* cycleCounter); void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters); +void GBAAdjustEWRAMWaitstates(struct GBA* gba, uint16_t parameters); struct GBASerializedState; void GBAMemorySerialize(const struct GBAMemory* memory, struct GBASerializedState* state); diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index 01b4476b3..f3ed332dc 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -20,7 +20,7 @@ extern MGBA_EXPORT const uint32_t GBASavestateVersion; mLOG_DECLARE_CATEGORY(GBA_STATE); /* Savestate format: - * 0x00000 - 0x00003: Version Magic (0x01000005) + * 0x00000 - 0x00003: Version Magic (0x01000006) * 0x00004 - 0x00007: BIOS checksum (e.g. 0xBAAE187F for official BIOS) * 0x00008 - 0x0000B: ROM CRC32 * 0x0000C - 0x0000F: Master cycles diff --git a/src/gba/io.c b/src/gba/io.c index 34e7471bb..ca0cbe5b5 100644 --- a/src/gba/io.c +++ b/src/gba/io.c @@ -199,7 +199,7 @@ const char* const GBAIORegisterNames[] = { "IME" }; -static const int _isValidRegister[REG_MAX >> 1] = { +static const int _isValidRegister[REG_INTERNAL_MAX >> 1] = { // Video 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -238,10 +238,12 @@ static const int _isValidRegister[REG_MAX >> 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Interrupts - 1, 1, 1, 0, 1 + 1, 1, 1, 0, 1, 0, 0, 0, + // Internal registers + 1, 1 }; -static const int _isRSpecialRegister[REG_MAX >> 1] = { +static const int _isRSpecialRegister[REG_INTERNAL_MAX >> 1] = { // Video 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, @@ -280,9 +282,12 @@ static const int _isRSpecialRegister[REG_MAX >> 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Interrupts + 0, 0, 0, 0, 0, 0, 0, 0, + // Internal registers + 1, 1 }; -static const int _isWSpecialRegister[REG_MAX >> 1] = { +static const int _isWSpecialRegister[REG_INTERNAL_MAX >> 1] = { // Video 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -321,7 +326,9 @@ static const int _isWSpecialRegister[REG_MAX >> 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Interrupts - 1, 1, 0, 0, 1 + 1, 1, 0, 0, 1, 0, 0, 0, + // Internal registers + 1, 1 }; void GBAIOInit(struct GBA* gba) { @@ -333,6 +340,8 @@ void GBAIOInit(struct GBA* gba) { gba->memory.io[REG_BG2PD >> 1] = 0x100; gba->memory.io[REG_BG3PA >> 1] = 0x100; gba->memory.io[REG_BG3PD >> 1] = 0x100; + gba->memory.io[REG_INTERNAL_EXWAITCNT_LO >> 1] = 0x20; + gba->memory.io[REG_INTERNAL_EXWAITCNT_HI >> 1] = 0xD00; if (!gba->biosVf) { gba->memory.io[REG_VCOUNT >> 1] = 0x7E; @@ -574,6 +583,12 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) { case REG_MAX: // Some bad interrupt libraries will write to this break; + case REG_EXWAITCNT_HI: + // This register sits outside of the normal I/O block, so we need to stash it somewhere unused + address = REG_INTERNAL_EXWAITCNT_HI; + value &= 0xFF00; + GBAAdjustEWRAMWaitstates(gba, value); + break; case REG_DEBUG_ENABLE: gba->debug = value == 0xC0DE; return; @@ -936,6 +951,11 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) { case 0x206: mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address); return 0; + // These registers sit outside of the normal I/O block, so we need to stash them somewhere unused + case REG_EXWAITCNT_LO: + case REG_EXWAITCNT_HI: + address += REG_INTERNAL_EXWAITCNT_LO - REG_EXWAITCNT_LO; + break; case REG_DEBUG_ENABLE: if (gba->debug) { return 0x1DEA; @@ -950,7 +970,7 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) { void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) { int i; - for (i = 0; i < REG_MAX; i += 2) { + for (i = 0; i < REG_INTERNAL_MAX; i += 2) { if (_isRSpecialRegister[i >> 1]) { STORE_16(gba->memory.io[i >> 1], i, state->io); } else if (_isValidRegister[i >> 1]) { @@ -991,6 +1011,9 @@ void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) { GBAIOWrite(gba, i, reg); } } + if (state->versionMagic >= 0x01000006) { + GBAIOWrite(gba, REG_EXWAITCNT_HI, gba->memory.io[REG_INTERNAL_EXWAITCNT_HI >> 1]); + } uint32_t when; for (i = 0; i < 4; ++i) { diff --git a/src/gba/memory.c b/src/gba/memory.c index 8bacf4a79..1878e7bb2 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -127,6 +127,7 @@ void GBAMemoryReset(struct GBA* gba) { memset(gba->memory.io, 0, sizeof(gba->memory.io)); GBAAdjustWaitstates(gba, 0); + GBAAdjustEWRAMWaitstates(gba, 0x0D00); gba->memory.activeRegion = -1; gba->memory.agbPrintProtect = 0; @@ -1714,6 +1715,31 @@ void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) { } } +void GBAAdjustEWRAMWaitstates(struct GBA* gba, uint16_t parameters) { + struct GBAMemory* memory = &gba->memory; + struct ARMCore* cpu = gba->cpu; + + int wait = 15 - ((parameters >> 8) & 0xF); + if (wait) { + memory->waitstatesNonseq16[REGION_WORKING_RAM] = wait; + memory->waitstatesSeq16[REGION_WORKING_RAM] = wait; + memory->waitstatesNonseq32[REGION_WORKING_RAM] = 2 * wait + 1; + memory->waitstatesSeq32[REGION_WORKING_RAM] = 2 * wait + 1; + + cpu->memory.activeSeqCycles32 = memory->waitstatesSeq32[memory->activeRegion]; + cpu->memory.activeSeqCycles16 = memory->waitstatesSeq16[memory->activeRegion]; + + cpu->memory.activeNonseqCycles32 = memory->waitstatesNonseq32[memory->activeRegion]; + cpu->memory.activeNonseqCycles16 = memory->waitstatesNonseq16[memory->activeRegion]; + } else { + if (!gba->hardCrash) { + mLOG(GBA_MEM, GAME_ERROR, "Cannot set EWRAM to 0 waitstates"); + } else { + mLOG(GBA_MEM, FATAL, "Cannot set EWRAM to 0 waitstates"); + } + } +} + int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait) { struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; diff --git a/src/gba/serialize.c b/src/gba/serialize.c index d2bd5c5e8..9c5416e72 100644 --- a/src/gba/serialize.c +++ b/src/gba/serialize.c @@ -15,7 +15,7 @@ #include MGBA_EXPORT const uint32_t GBASavestateMagic = 0x01000000; -MGBA_EXPORT const uint32_t GBASavestateVersion = 0x00000005; +MGBA_EXPORT const uint32_t GBASavestateVersion = 0x00000006; mLOG_DEFINE_CATEGORY(GBA_STATE, "GBA Savestate", "gba.serialize"); From 5ba82aaed074f664ab2210c7cb3ca0561a436e47 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 7 Jun 2022 00:21:16 -0700 Subject: [PATCH 040/102] GB I/O: Windowed WAVE RAM reading only works on CGB, not CGB-on-AGB --- src/gb/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gb/io.c b/src/gb/io.c index 25ca02602..c6ad66c36 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -609,7 +609,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) { case GB_REG_WAVE_F: if (gb->audio.playingCh3) { GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing), 0x4); - if (gb->audio.ch3.readable || gb->audio.style != GB_AUDIO_DMG) { + if (gb->audio.ch3.readable || gb->audio.style == GB_AUDIO_CGB) { return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1]; } else { return 0xFF; From 7a07b148cbd4add45afff1908dd364360f0fb084 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 8 Jun 2022 00:15:49 -0700 Subject: [PATCH 041/102] GBA Video: Fix OBJ tile wrapping with 2D char mapping (fixes #2443) --- CHANGES | 1 + cinema/gba/obj/2d-wrap/baseline_0000.png | Bin 0 -> 253 bytes cinema/gba/obj/2d-wrap/config.ini | 3 +++ cinema/gba/obj/2d-wrap/test.gba | Bin 0 -> 4096 bytes src/gba/renderers/software-obj.c | 18 ++++++++++-------- 5 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 cinema/gba/obj/2d-wrap/baseline_0000.png create mode 100644 cinema/gba/obj/2d-wrap/config.ini create mode 100644 cinema/gba/obj/2d-wrap/test.gba diff --git a/CHANGES b/CHANGES index 17b2df376..10831f0c2 100644 --- a/CHANGES +++ b/CHANGES @@ -43,6 +43,7 @@ Emulation fixes: - GBA Video: Fix Hblank timing (fixes mgba.io/i/2131, mgba.io/i/2310) - GBA Video: Fix rare crash in modes 3-5 - GBA Video: Fix sprites with mid-frame palette changes in GL (fixes mgba.io/i/2476) + - GBA Video: Fix OBJ tile wrapping with 2D char mapping (fixes mgba.io/i/2443) Other fixes: - ARM: Disassemble Thumb mov pseudo-instruction properly - Core: Don't attempt to restore rewind diffs past start of rewind diff --git a/cinema/gba/obj/2d-wrap/baseline_0000.png b/cinema/gba/obj/2d-wrap/baseline_0000.png new file mode 100644 index 0000000000000000000000000000000000000000..c0866f0a8ba8a68c0a7fd9f60dfc3a9e92936e40 GIT binary patch literal 253 zcmeAS@N?(olHy`uVBq!ia0vp^AAooP2NRIoyR*y)NFDKXaSW-L^Y+e0-U9|4u8!8f z-}{IaSgA~Tzx$Htq4jCHKsCgH2mar_Fl4TJ^<&@uu(#|{wwIY5)E$LgFSrPr1hV*w zfS8yD865iiBTete`J&r>8ck|l3p$lD7IDl1GZ`^eV-;!O-t%M*n|$?#vui-|p00i_ I>zopr05;S*xBvhE literal 0 HcmV?d00001 diff --git a/cinema/gba/obj/2d-wrap/config.ini b/cinema/gba/obj/2d-wrap/config.ini new file mode 100644 index 000000000..108616db9 --- /dev/null +++ b/cinema/gba/obj/2d-wrap/config.ini @@ -0,0 +1,3 @@ +[testinfo] +skip=1 +frames=1 diff --git a/cinema/gba/obj/2d-wrap/test.gba b/cinema/gba/obj/2d-wrap/test.gba new file mode 100644 index 0000000000000000000000000000000000000000..3b5998ff375aa2467f0f905a2f312fc5bc3d2b2f GIT binary patch literal 4096 zcmdO6V0fkSe_deatVN2pElpf4PdL{Ks&vmd&{(gyIB1{bWX^L60&ZSjKhzE1L>zx% z-1PX|{?;$|r=0WVJUAt+>ws|4@;~!ie2W*Knw1zaeX;r<<{4$mvd0sdS=NQ^w`gH- zSkCwNf6zbX{HX>Xr~f|CnsBW_b!GBCW=21YM?V*t{NHWI>{7un;dFebQ~gwWdh%$`5vbC$A9K;1C87a1QlzH8-CIW`l{j3=E9S3m!8{EqJ^^z~P|? zUK$-z4#|V`BqcH#J1_g(QObiW=7zF|!{r>-7 z>J0-#?gbXP8&J6`SmcfX<(PnG9>5~E0V=l!i`*Qj+zc#o>?{i&w+H~;2=os-)Gr`E zfc#Pb)K`Ee7YCJ#0m{_@*<5-+wF(CwGVxD<`|scX|F0OB7+C+;gF=mwO;C`5;Q=!v zo01Zc%fiTJYz(A17}*#Z85j<5GqN!;0r@> 1) & 2); -#define SPRITE_YBASE_16(localY) unsigned yBase = (localY & ~0x7) * stride + (localY & 0x7) * 4; +#define SPRITE_YBASE_16(localY) unsigned yBase = (localY & ~0x7) * stride + (localY & 0x7) * 4 + maskHi; #define SPRITE_DRAW_PIXEL_16_NORMAL(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + LOAD_16(tileData, (yBase + ((xBase + charBase) & maskLo)) & 0x7FFE, vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ current = renderer->spriteLayer[outX]; \ if ((current & FLAG_ORDER_MASK) > flags) { \ @@ -86,7 +86,7 @@ } #define SPRITE_DRAW_PIXEL_16_NORMAL_OBJWIN(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + LOAD_16(tileData, (yBase + ((xBase + charBase) & maskLo)) & 0x7FFE, vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ current = renderer->spriteLayer[outX]; \ if ((current & FLAG_ORDER_MASK) > flags) { \ @@ -99,17 +99,17 @@ } #define SPRITE_DRAW_PIXEL_16_OBJWIN(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + LOAD_16(tileData, (yBase + ((xBase + charBase) & maskLo)) & 0x7FFE, vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ if (tileData) { \ renderer->row[outX] |= FLAG_OBJWIN; \ } #define SPRITE_XBASE_256(localX) unsigned xBase = (localX & ~0x7) * 8 + (localX & 6); -#define SPRITE_YBASE_256(localY) unsigned yBase = (localY & ~0x7) * stride + (localY & 0x7) * 8; +#define SPRITE_YBASE_256(localY) unsigned yBase = (localY & ~0x7) * stride + (localY & 0x7) * 8 + maskHi; #define SPRITE_DRAW_PIXEL_256_NORMAL(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + LOAD_16(tileData, (yBase + ((xBase + charBase) & maskLo)) & 0x7FFE, vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ current = renderer->spriteLayer[outX]; \ if ((current & FLAG_ORDER_MASK) > flags) { \ @@ -121,7 +121,7 @@ } #define SPRITE_DRAW_PIXEL_256_NORMAL_OBJWIN(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + LOAD_16(tileData, (yBase + ((xBase + charBase) & maskLo)) & 0x7FFE, vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ current = renderer->spriteLayer[outX]; \ if ((current & FLAG_ORDER_MASK) > flags) { \ @@ -134,7 +134,7 @@ } #define SPRITE_DRAW_PIXEL_256_OBJWIN(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ + LOAD_16(tileData, (yBase + ((xBase + charBase) & maskLo)) & 0x7FFE, vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ if (tileData) { \ renderer->row[outX] |= FLAG_OBJWIN; \ @@ -157,6 +157,8 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1]; unsigned align = GBAObjAttributesAIs256Color(sprite->a) && !GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt); unsigned charBase = (GBAObjAttributesCGetTile(sprite->c) & ~align) * 0x20; + unsigned maskLo = GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt) ? 0x7FFE : 0x3FE; + unsigned maskHi = GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt) ? 0 : charBase & 0x7C00; if (GBARegisterDISPCNTGetMode(renderer->dispcnt) >= 3 && GBAObjAttributesCGetTile(sprite->c) < 512) { return 0; } From 97cb18d3fdb99568f4778194b23f6d51103dc219 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 8 Jun 2022 01:53:35 -0700 Subject: [PATCH 042/102] GBA Video: Fix two sprite boundary conditions in OpenGL --- include/mgba/internal/gba/renderers/gl.h | 1 + src/gba/renderers/gl.c | 36 ++++++++++++++++++++---- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/include/mgba/internal/gba/renderers/gl.h b/include/mgba/internal/gba/renderers/gl.h index 1a972ada8..42068e53f 100644 --- a/include/mgba/internal/gba/renderers/gl.h +++ b/include/mgba/internal/gba/renderers/gl.h @@ -103,6 +103,7 @@ enum { GBA_GL_OBJ_VRAM = 2, GBA_GL_OBJ_PALETTE, GBA_GL_OBJ_CHARBASE, + GBA_GL_OBJ_TILE, GBA_GL_OBJ_STRIDE, GBA_GL_OBJ_LOCALPALETTE, GBA_GL_OBJ_INFLAGS, diff --git a/src/gba/renderers/gl.c b/src/gba/renderers/gl.c index 02374d8e4..0fcd70617 100644 --- a/src/gba/renderers/gl.c +++ b/src/gba/renderers/gl.c @@ -85,25 +85,37 @@ static const char* const _vertexShader = "}"; static const char* const _renderTile16 = + "#ifndef VRAM_MASK\n" + "#define VRAM_MASK\n" + "#endif\n" "int renderTile(int tile, int paletteId, ivec2 localCoord) {\n" " int address = charBase + tile * 16 + (localCoord.x >> 2) + (localCoord.y << 1);\n" - " int halfrow = texelFetch(vram, ivec2(address & 255, address >> 8), 0).r;\n" + " int halfrow = texelFetch(vram, ivec2(address & 255, (address >> 8) VRAM_MASK), 0).r;\n" " int entry = (halfrow >> (4 * (localCoord.x & 3))) & 15;\n" " if (entry == 0) {\n" " discard;\n" " }\n" " return paletteId * 16 + entry;\n" + "}\n" + "int mask(int tile) {\n" + " return tile & 31;\n" "}"; static const char* const _renderTile256 = + "#ifndef VRAM_MASK\n" + "#define VRAM_MASK\n" + "#endif\n" "int renderTile(int tile, int paletteId, ivec2 localCoord) {\n" " int address = charBase + tile * 32 + (localCoord.x >> 1) + (localCoord.y << 2);\n" - " int halfrow = texelFetch(vram, ivec2(address & 255, address >> 8), 0).r;\n" + " int halfrow = texelFetch(vram, ivec2(address & 255, (address >> 8) VRAM_MASK), 0).r;\n" " int entry = (halfrow >> (8 * (localCoord.x & 1))) & 255;\n" " if (entry == 0) {\n" " discard;\n" " }\n" " return entry;\n" + "}" + "int mask(int tile) {\n" + " return tile & 15;\n" "}"; static const struct GBAVideoGLUniform _uniformsMode0[] = { @@ -167,7 +179,7 @@ static const char* const _renderMode0 = " int tile = map & 1023;\n" " int paletteEntry = renderTile(tile, map >> 12, coord & 7);\n" " color = texelFetch(palette, ivec2(paletteEntry, int(texCoord.y)), 0);\n" - "}"; + "}\n"; static const char* const _fetchTileOverflow = "int fetchTile(ivec2 coord) {\n" @@ -415,6 +427,7 @@ static const struct GBAVideoGLUniform _uniformsObj[] = { { "objwin", GBA_GL_OBJ_OBJWIN, }, { "mosaic", GBA_GL_OBJ_MOSAIC, }, { "cyclesRemaining", GBA_GL_OBJ_CYCLES, }, + { "tile", GBA_GL_OBJ_TILE, }, { 0 } }; @@ -424,6 +437,7 @@ static const char* const _renderObj = "uniform isampler2D vram;\n" "uniform sampler2D palette;\n" "uniform int charBase;\n" + "uniform int tile;\n" "uniform int stride;\n" "uniform int localPalette;\n" "uniform ivec4 inflags;\n" @@ -437,6 +451,8 @@ static const char* const _renderObj = "OUT(2) out ivec4 window;\n" "int renderTile(int tile, int paletteId, ivec2 localCoord);\n" + "int mask(int);\n" + "#define VRAM_MASK & 191\n" "void main() {\n" " vec2 incoord = texCoord;\n" @@ -461,12 +477,12 @@ static const char* const _renderObj = " if ((coord & ~(dims.xy - 1)) != ivec2(0, 0)) {\n" " discard;\n" " }\n" - " int paletteEntry = renderTile((coord.x >> 3) + (coord.y >> 3) * stride, localPalette, coord & 7);\n" + " int paletteEntry = renderTile(mask((coord.x >> 3) + tile) + (coord.y >> 3) * stride, localPalette, coord & 7);\n" " color = texelFetch(palette, ivec2(paletteEntry + 256, int(texCoord.y) + mosaic.w), 0);\n" " flags = inflags;\n" " gl_FragDepth = float(flags.x) / 16.;\n" " window = ivec4(objwin, 0);\n" - "}"; + "}\n"; static const struct GBAVideoGLUniform _uniformsObjPriority[] = { { "loc", GBA_GL_VS_LOC, }, @@ -1709,6 +1725,15 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB int align = GBAObjAttributesAIs256Color(sprite->a) && !GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt); unsigned charBase = (BASE_TILE >> 1) + (GBAObjAttributesCGetTile(sprite->c) & ~align) * 0x10; + unsigned tile = 0; + if (!GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt)) { + if (GBAObjAttributesAIs256Color(sprite->a)) { + tile = (charBase >> 5) & 0xF; + } else { + tile = (charBase >> 4) & 0x1F; + } + charBase &= ~0x1FF; + } int stride = GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt) ? (width >> 3) : (0x20 >> GBAObjAttributesAGet256Color(sprite->a)); int totalWidth = width; @@ -1744,6 +1769,7 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB glUniform1i(uniforms[GBA_GL_OBJ_VRAM], 0); glUniform1i(uniforms[GBA_GL_OBJ_PALETTE], 1); glUniform1i(uniforms[GBA_GL_OBJ_CHARBASE], charBase); + glUniform1i(uniforms[GBA_GL_OBJ_TILE], tile); glUniform1i(uniforms[GBA_GL_OBJ_STRIDE], stride); glUniform1i(uniforms[GBA_GL_OBJ_LOCALPALETTE], GBAObjAttributesCGetPalette(sprite->c)); glUniform4i(uniforms[GBA_GL_OBJ_INFLAGS], GBAObjAttributesCGetPriority(sprite->c), From ae0c5e91aa99b0e41b9595d6d9b254a7bb730b7c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 6 Jun 2022 17:21:02 -0700 Subject: [PATCH 043/102] Qt: Simplify Window drawing (fixes #2190) --- CHANGES | 1 + src/platform/qt/DisplayGL.cpp | 29 ++++++------ src/platform/qt/DisplayGL.h | 5 ++- src/platform/qt/LoadSaveState.cpp | 5 +++ src/platform/qt/LoadSaveState.h | 9 ++++ src/platform/qt/Window.cpp | 74 ++++++++++--------------------- src/platform/qt/Window.h | 6 +-- 7 files changed, 59 insertions(+), 70 deletions(-) diff --git a/CHANGES b/CHANGES index 10831f0c2..ae7e136e4 100644 --- a/CHANGES +++ b/CHANGES @@ -57,6 +57,7 @@ Other fixes: - Qt: Fix some hangs when using the debugger console - Qt: Fix crash when clicking past last tile in viewer - Qt: Fix preloading for ROM replacing + - Qt: Fix screen not displaying on Wayland (fixes mgba.io/i/2190) - VFS: Failed file mapping should return NULL on POSIX Misc: - Core: Suspend runloop when a core crashes diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 221acffc0..dd683b781 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -56,10 +56,13 @@ uint qHash(const QSurfaceFormat& format, uint seed) { } void mGLWidget::initializeGL() { - m_vao.create(); - m_program.create(); + m_vao = std::make_unique(); + m_vao->create(); - m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, R"(#version 150 core + m_program = std::make_unique(); + m_program->create(); + + m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, R"(#version 150 core in vec4 position; out vec2 texCoord; void main() { @@ -67,7 +70,7 @@ void mGLWidget::initializeGL() { texCoord = (position.st + 1.0) * 0.5; })"); - m_program.addShaderFromSourceCode(QOpenGLShader::Fragment, R"(#version 150 core + m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, R"(#version 150 core in vec2 texCoord; out vec4 color; uniform sampler2D tex; @@ -75,9 +78,9 @@ void mGLWidget::initializeGL() { color = vec4(texture(tex, texCoord).rgb, 1.0); })"); - m_program.link(); - m_program.setUniformValue("tex", 0); - m_positionLocation = m_program.attributeLocation("position"); + m_program->link(); + m_program->setUniformValue("tex", 0); + m_positionLocation = m_program->attributeLocation("position"); connect(&m_refresh, &QTimer::timeout, this, static_cast(&QWidget::update)); } @@ -85,11 +88,11 @@ void mGLWidget::initializeGL() { void mGLWidget::finalizeVAO() { QOpenGLFunctions_Baseline* fn = context()->versionFunctions(); fn->glGetError(); // Clear the error - m_vao.bind(); + m_vao->bind(); fn->glBindBuffer(GL_ARRAY_BUFFER, m_vbo); fn->glEnableVertexAttribArray(m_positionLocation); fn->glVertexAttribPointer(m_positionLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL); - m_vao.release(); + m_vao->release(); if (fn->glGetError() == GL_NO_ERROR) { m_vaoDone = true; } @@ -100,13 +103,13 @@ void mGLWidget::paintGL() { finalizeVAO(); } QOpenGLFunctions_Baseline* fn = context()->versionFunctions(); - m_program.bind(); - m_vao.bind(); + m_program->bind(); + m_vao->bind(); fn->glBindTexture(GL_TEXTURE_2D, m_tex); fn->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); fn->glBindTexture(GL_TEXTURE_2D, 0); - m_vao.release(); - m_program.release(); + m_vao->release(); + m_program->release(); // TODO: Better timing ++m_refreshResidue; diff --git a/src/platform/qt/DisplayGL.h b/src/platform/qt/DisplayGL.h index 54256ed30..a75f1a8dd 100644 --- a/src/platform/qt/DisplayGL.h +++ b/src/platform/qt/DisplayGL.h @@ -32,6 +32,7 @@ #include #include +#include #include "CoreController.h" #include "VideoProxy.h" @@ -62,8 +63,8 @@ private: GLuint m_vbo; bool m_vaoDone = false; - QOpenGLVertexArrayObject m_vao; - QOpenGLShaderProgram m_program; + std::unique_ptr m_vao; + std::unique_ptr m_program; GLuint m_positionLocation; QTimer m_refresh; diff --git a/src/platform/qt/LoadSaveState.cpp b/src/platform/qt/LoadSaveState.cpp index aa76ed523..3198a4c90 100644 --- a/src/platform/qt/LoadSaveState.cpp +++ b/src/platform/qt/LoadSaveState.cpp @@ -9,6 +9,7 @@ #include "GamepadAxisEvent.h" #include "GamepadButtonEvent.h" #include "VFileDevice.h" +#include "utils.h" #include #include @@ -251,6 +252,10 @@ void LoadSaveState::focusInEvent(QFocusEvent*) { void LoadSaveState::paintEvent(QPaintEvent*) { QPainter painter(this); + + painter.setRenderHint(QPainter::SmoothPixmapTransform, true); QRect full(QPoint(), size()); + painter.fillRect(full, Qt::black); + painter.drawPixmap(clampSize(m_dims, size(), m_lockAspectRatio, m_lockIntegerScaling), m_background); painter.fillRect(full, QColor(0, 0, 0, 128)); } diff --git a/src/platform/qt/LoadSaveState.h b/src/platform/qt/LoadSaveState.h index 5596c1b10..f74e5b24b 100644 --- a/src/platform/qt/LoadSaveState.h +++ b/src/platform/qt/LoadSaveState.h @@ -32,6 +32,10 @@ public: void setInputController(InputController* controller); void setMode(LoadSave mode); + void setBackground(const QPixmap& pixmap) { m_background = pixmap; } + void setDimensions(const QSize& dims) { m_dims = dims; } + void setLockIntegerScaling(bool lockIntegerScaling) { m_lockIntegerScaling = lockIntegerScaling; } + void setLockAspectRatio(bool lockApsectRatio) { m_lockAspectRatio = lockApsectRatio; } signals: void closed(); @@ -54,6 +58,11 @@ private: int m_currentFocus; QPixmap m_currentImage; + QPixmap m_background; + + QSize m_dims; + bool m_lockAspectRatio; + bool m_lockIntegerScaling; }; } diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index c32662fb8..9a2551503 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #ifdef USE_SQLITE3 @@ -58,7 +57,6 @@ #include "TileView.h" #include "VideoProxy.h" #include "VideoView.h" -#include "utils.h" #ifdef USE_DISCORD_RPC #include "DiscordCoordinator.h" @@ -113,14 +111,12 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi m_libraryView = new LibraryController(nullptr, ConfigController::configDir() + "/library.sqlite3", m_config); ConfigOption* showLibrary = m_config->addOption("showLibrary"); showLibrary->connect([this](const QVariant& value) { - if (value.toBool()) { - if (m_controller) { - m_screenWidget->layout()->addWidget(m_libraryView); - } else { + if (!m_controller) { + if (value.toBool()) { attachWidget(m_libraryView); + } else { + attachWidget(m_screenWidget); } - } else { - detachWidget(m_libraryView); } }, this); m_config->updateOption("showLibrary"); @@ -150,7 +146,6 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi resizeFrame(QSize(GB_VIDEO_HORIZONTAL_PIXELS * i, GB_VIDEO_VERTICAL_PIXELS * i)); #endif setLogo(); - setCentralWidget(m_screenWidget); connect(this, &Window::shutdown, m_logView, &QWidget::hide); connect(&m_fpsTimer, &QTimer::timeout, this, &Window::showFPS); @@ -883,7 +878,6 @@ void Window::gameStarted() { action.value()->setEnabled(m_controller->platform() == action.key()); } QSize size = m_controller->screenDimensions(); - m_screenWidget->setDimensions(size.width(), size.height()); m_config->updateOption("lockIntegerScaling"); m_config->updateOption("lockAspectRatio"); m_config->updateOption("interframeBlending"); @@ -977,7 +971,6 @@ void Window::gameStopped() { m_audioProcessor.reset(); } m_display->stopDrawing(); - detachWidget(m_display.get()); setLogo(); if (m_display) { #ifdef M_CORE_GB @@ -988,6 +981,7 @@ void Window::gameStopped() { } m_controller.reset(); + detachWidget(); updateTitle(); if (m_pendingClose) { @@ -1039,7 +1033,7 @@ void Window::unimplementedBiosCall(int) { void Window::reloadDisplayDriver() { if (m_controller) { m_display->stopDrawing(); - detachWidget(m_display.get()); + detachWidget(); } m_display = std::unique_ptr(Display::create(this)); if (!m_display) { @@ -1054,7 +1048,7 @@ void Window::reloadDisplayDriver() { #endif connect(m_display.get(), &QGBA::Display::hideCursor, [this]() { - if (static_cast(m_screenWidget->layout())->currentWidget() == m_display.get()) { + if (centralWidget() == m_display.get()) { m_screenWidget->setCursor(Qt::BlankCursor); } }); @@ -1215,15 +1209,13 @@ void Window::openStateWindow(LoadSave ls) { m_stateWindow = new LoadSaveState(m_controller); connect(this, &Window::shutdown, m_stateWindow, &QWidget::close); connect(m_stateWindow, &LoadSaveState::closed, [this]() { - detachWidget(m_stateWindow); - static_cast(m_screenWidget->layout())->setCurrentWidget(m_display.get()); + attachWidget(m_display.get()); m_stateWindow = nullptr; QMetaObject::invokeMethod(this, "setFocus", Qt::QueuedConnection); }); if (!wasPaused) { m_controller->setPaused(true); connect(m_stateWindow, &LoadSaveState::closed, [this]() { - m_screenWidget->filter(m_config->getOption("resampleVideo").toInt()); if (m_controller) { m_controller->setPaused(false); } @@ -1232,6 +1224,10 @@ void Window::openStateWindow(LoadSave ls) { m_stateWindow->setAttribute(Qt::WA_DeleteOnClose); m_stateWindow->setMode(ls); + m_stateWindow->setDimensions(m_controller->screenDimensions()); + m_config->updateOption("lockAspectRatio"); + m_config->updateOption("lockIntegerScaling"); + QImage still(m_controller->getPixels()); if (still.format() != QImage::Format_RGB888) { still = still.convertToFormat(QImage::Format_RGB888); @@ -1249,8 +1245,7 @@ void Window::openStateWindow(LoadSave ls) { QPixmap pixmap; pixmap.convertFromImage(output); - m_screenWidget->setPixmap(pixmap); - m_screenWidget->filter(true); + m_stateWindow->setBackground(pixmap); #ifndef Q_OS_MAC menuBar()->show(); @@ -1536,8 +1531,8 @@ void Window::setupMenu(QMenuBar* menubar) { if (m_display) { m_display->lockAspectRatio(value.toBool()); } - if (m_controller) { - m_screenWidget->setLockAspectRatio(value.toBool()); + if (m_stateWindow) { + m_stateWindow->setLockAspectRatio(value.toBool()); } }, this); m_config->updateOption("lockAspectRatio"); @@ -1548,8 +1543,8 @@ void Window::setupMenu(QMenuBar* menubar) { if (m_display) { m_display->lockIntegerScaling(value.toBool()); } - if (m_controller) { - m_screenWidget->setLockIntegerScaling(value.toBool()); + if (m_stateWindow) { + m_stateWindow->setLockIntegerScaling(value.toBool()); } }, this); m_config->updateOption("lockIntegerScaling"); @@ -1569,9 +1564,6 @@ void Window::setupMenu(QMenuBar* menubar) { if (m_display) { m_display->filter(value.toBool()); } - if (m_controller) { - m_screenWidget->filter(value.toBool()); - } }, this); m_config->updateOption("resampleVideo"); @@ -1894,13 +1886,12 @@ void Window::setupOptions() { } void Window::attachWidget(QWidget* widget) { - m_screenWidget->layout()->addWidget(widget); - m_screenWidget->unsetCursor(); - static_cast(m_screenWidget->layout())->setCurrentWidget(widget); + takeCentralWidget(); + setCentralWidget(widget); } -void Window::detachWidget(QWidget* widget) { - m_screenWidget->layout()->removeWidget(widget); +void Window::detachWidget() { + m_config->updateOption("showLibrary"); } void Window::appendMRU(const QString& fname) { @@ -1996,7 +1987,7 @@ void Window::focusCheck() { } void Window::updateFrame() { - if (static_cast(m_screenWidget->layout())->currentWidget() != m_display.get()) { + if (!m_controller) { return; } QPixmap pixmap; @@ -2171,17 +2162,12 @@ void Window::updateMute() { void Window::setLogo() { m_screenWidget->setPixmap(m_logo); m_screenWidget->setDimensions(m_logo.width(), m_logo.height()); - m_screenWidget->setLockIntegerScaling(false); - m_screenWidget->setLockAspectRatio(true); - m_screenWidget->filter(true); m_screenWidget->unsetCursor(); } WindowBackground::WindowBackground(QWidget* parent) : QWidget(parent) { - setLayout(new QStackedLayout()); - layout()->setContentsMargins(0, 0, 0, 0); } void WindowBackground::setPixmap(const QPixmap& pmap) { @@ -2202,24 +2188,12 @@ void WindowBackground::setDimensions(int width, int height) { m_aspectHeight = height; } -void WindowBackground::setLockIntegerScaling(bool lock) { - m_lockIntegerScaling = lock; -} - -void WindowBackground::setLockAspectRatio(bool lock) { - m_lockAspectRatio = lock; -} - -void WindowBackground::filter(bool filter) { - m_filter = filter; -} - void WindowBackground::paintEvent(QPaintEvent* event) { QWidget::paintEvent(event); const QPixmap& logo = pixmap(); QPainter painter(this); - painter.setRenderHint(QPainter::SmoothPixmapTransform, m_filter); + painter.setRenderHint(QPainter::SmoothPixmapTransform, true); painter.fillRect(QRect(QPoint(), size()), Qt::black); - QRect full(clampSize(QSize(m_aspectWidth, m_aspectHeight), size(), m_lockAspectRatio, m_lockIntegerScaling)); + QRect full(clampSize(QSize(m_aspectWidth, m_aspectHeight), size(), true, false)); painter.drawPixmap(full, logo); } diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index f129c44e5..696604773 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -167,7 +167,7 @@ private: void openStateWindow(LoadSave); void attachWidget(QWidget* widget); - void detachWidget(QWidget* widget); + void detachWidget(); void appendMRU(const QString& fname); void clearMRU(); @@ -277,7 +277,6 @@ public: void setDimensions(int width, int height); void setLockIntegerScaling(bool lock); void setLockAspectRatio(bool lock); - void filter(bool filter); const QPixmap& pixmap() const { return m_pixmap; } @@ -289,9 +288,6 @@ private: QSize m_sizeHint; int m_aspectWidth; int m_aspectHeight; - bool m_lockAspectRatio; - bool m_lockIntegerScaling; - bool m_filter; }; } From 7b8ba05f885c6b6f228e27e5e8d9de1c71ea16dc Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 6 Jun 2022 17:21:32 -0700 Subject: [PATCH 044/102] Qt: Only disable DisplayGL updates on Windows --- src/platform/qt/DisplayGL.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index dd683b781..4691726bc 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -205,7 +205,9 @@ void DisplayGL::startDrawing(std::shared_ptr controller) { CoreController::Interrupter interrupter(controller); QMetaObject::invokeMethod(m_painter.get(), "start"); if (!m_gl) { - setUpdatesEnabled(false); + if (QGuiApplication::platformName() == "windows") { + setUpdatesEnabled(false); + } } else { show(); } @@ -290,7 +292,7 @@ void DisplayGL::unpauseDrawing() { if (m_hasStarted) { m_isDrawing = true; QMetaObject::invokeMethod(m_painter.get(), "unpause", Qt::BlockingQueuedConnection); - if (!m_gl) { + if (!m_gl && QGuiApplication::platformName() == "windows") { setUpdatesEnabled(false); } } From 6e196748d88b830747e930c65365c9452654ab23 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 8 Jun 2022 17:55:37 -0700 Subject: [PATCH 045/102] Scripting: Hand off full filename to Lua, add directory to DLL search path --- src/script/engines/lua.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index 2770e8898..24e54c88e 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -11,6 +11,10 @@ #include #include +#ifdef _WIN32 +#include +#endif + #define MAX_KEY_SIZE 128 static struct mScriptEngineContext* _luaCreate(struct mScriptEngine2*, struct mScriptContext*); @@ -476,24 +480,27 @@ bool _luaLoad(struct mScriptEngineContext* ctx, const char* filename, struct VFi free(luaContext->lastError); luaContext->lastError = NULL; } - char name[80]; + char name[PATH_MAX + 1]; if (filename) { if (*filename == '*') { snprintf(name, sizeof(name), "=%s", filename + 1); } else { +#ifdef _WIN32 + char dirname[PATH_MAX] = {0}; const char* lastSlash = strrchr(filename, '/'); const char* lastBackslash = strrchr(filename, '\\'); if (lastSlash && lastBackslash) { - if (lastSlash > lastBackslash) { - filename = lastSlash + 1; - } else { - filename = lastBackslash + 1; + if (lastSlash < lastBackslash) { + lastSlash = lastBackslash; } - } else if (lastSlash) { - filename = lastSlash + 1; } else if (lastBackslash) { - filename = lastBackslash + 1; + lastSlash = lastBackslash; } + if (lastSlash) { + strncpy(dirname, filename, lastSlash - filename); + AddDllDirectory(dirname); + } +#endif snprintf(name, sizeof(name), "@%s", filename); } filename = name; From b42b997f00b3b305e42cd1ceaae4f006a64b5fbc Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 8 Jun 2022 18:04:43 -0700 Subject: [PATCH 046/102] Scripting: Why does this function take PCWSTR?? --- src/script/engines/lua.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index 24e54c88e..096532b8d 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -486,7 +486,7 @@ bool _luaLoad(struct mScriptEngineContext* ctx, const char* filename, struct VFi snprintf(name, sizeof(name), "=%s", filename + 1); } else { #ifdef _WIN32 - char dirname[PATH_MAX] = {0}; + wchar_t dirname[PATH_MAX] = {0}; const char* lastSlash = strrchr(filename, '/'); const char* lastBackslash = strrchr(filename, '\\'); if (lastSlash && lastBackslash) { @@ -497,7 +497,7 @@ bool _luaLoad(struct mScriptEngineContext* ctx, const char* filename, struct VFi lastSlash = lastBackslash; } if (lastSlash) { - strncpy(dirname, filename, lastSlash - filename); + MultiByteToWideChar(CP_UTF8, 0, filename, lastSlash - filename, dirname, PATH_MAX); AddDllDirectory(dirname); } #endif From 3e4f1fcb2eb257db679110458521adb0d8e9aace Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 8 Jun 2022 21:44:01 -0700 Subject: [PATCH 047/102] Scripting: Lua requires should be relative to the file they were run from --- src/script/engines/lua.c | 101 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 94 insertions(+), 7 deletions(-) diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index 096532b8d..343b07cb2 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -49,6 +49,8 @@ static int _luaPairsTable(lua_State* lua); static int _luaGetList(lua_State* lua); static int _luaLenList(lua_State* lua); +static int _luaRequireShim(lua_State* lua); + #if LUA_VERSION_NUM < 503 #define lua_pushinteger lua_pushnumber #endif @@ -78,6 +80,8 @@ struct mScriptEngineContextLua { struct mScriptEngineContext d; lua_State* lua; int func; + char lastDirectory[PATH_MAX]; + int require; char* lastError; }; @@ -163,6 +167,9 @@ struct mScriptEngineContext* _luaCreate(struct mScriptEngine2* engine, struct mS #endif lua_pop(luaContext->lua, 1); + lua_getglobal(luaContext->lua, "require"); + luaContext->require = luaL_ref(luaContext->lua, LUA_REGISTRYINDEX); + return &luaContext->d; } @@ -330,7 +337,7 @@ struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext, bool } return _luaCoerceFunction(luaContext); case LUA_TTABLE: - // This function pops the value internally via luaL_ref + // This function pops the value internally if (!pop) { break; } @@ -481,12 +488,11 @@ bool _luaLoad(struct mScriptEngineContext* ctx, const char* filename, struct VFi luaContext->lastError = NULL; } char name[PATH_MAX + 1]; + char dirname[PATH_MAX] = {0}; if (filename) { if (*filename == '*') { snprintf(name, sizeof(name), "=%s", filename + 1); } else { -#ifdef _WIN32 - wchar_t dirname[PATH_MAX] = {0}; const char* lastSlash = strrchr(filename, '/'); const char* lastBackslash = strrchr(filename, '\\'); if (lastSlash && lastBackslash) { @@ -497,10 +503,8 @@ bool _luaLoad(struct mScriptEngineContext* ctx, const char* filename, struct VFi lastSlash = lastBackslash; } if (lastSlash) { - MultiByteToWideChar(CP_UTF8, 0, filename, lastSlash - filename, dirname, PATH_MAX); - AddDllDirectory(dirname); + strncpy(dirname, filename, lastSlash - filename); } -#endif snprintf(name, sizeof(name), "@%s", filename); } filename = name; @@ -509,6 +513,11 @@ bool _luaLoad(struct mScriptEngineContext* ctx, const char* filename, struct VFi switch (ret) { case LUA_OK: luaContext->func = luaL_ref(luaContext->lua, LUA_REGISTRYINDEX); + if (dirname[0]) { + strncpy(luaContext->lastDirectory, dirname, sizeof(luaContext->lastDirectory)); + } else { + memset(luaContext->lastDirectory, 0, sizeof(luaContext->lastDirectory)); + } return true; case LUA_ERRSYNTAX: luaContext->lastError = strdup(lua_tostring(luaContext->lua, -1)); @@ -522,8 +531,21 @@ bool _luaLoad(struct mScriptEngineContext* ctx, const char* filename, struct VFi bool _luaRun(struct mScriptEngineContext* context) { struct mScriptEngineContextLua* luaContext = (struct mScriptEngineContextLua*) context; + + if (luaContext->lastDirectory[0]) { + // Shim require to look in the previous location + lua_pushstring(luaContext->lua, luaContext->lastDirectory); + lua_pushcclosure(luaContext->lua, _luaRequireShim, 1); + lua_setglobal(luaContext->lua, "require"); + } + lua_rawgeti(luaContext->lua, LUA_REGISTRYINDEX, luaContext->func); - return _luaInvoke(luaContext, NULL); + bool ret = _luaInvoke(luaContext, NULL); + + // Restore previous value of require + lua_rawgeti(luaContext->lua, LUA_REGISTRYINDEX, luaContext->require); + lua_setglobal(luaContext->lua, "require"); + return ret; } const char* _luaGetError(struct mScriptEngineContext* context) { @@ -962,3 +984,68 @@ static int _luaLenList(lua_State* lua) { lua_pushinteger(lua, mScriptListSize(list)); return 1; } + +static int _luaRequireShim(lua_State* lua) { + struct mScriptEngineContextLua* luaContext = _luaGetContext(lua); + + const char* path = lua_tostring(lua, lua_upvalueindex(1)); + const char* oldpath; + const char* oldcpath; + + lua_getglobal(luaContext->lua, "package"); + + lua_pushliteral(luaContext->lua, "path"); + lua_pushliteral(luaContext->lua, "path"); + lua_gettable(luaContext->lua, -3); + oldpath = strdup(lua_tostring(luaContext->lua, -1)); + lua_pushliteral(luaContext->lua, ";"); + lua_pushstring(luaContext->lua, path); + lua_pushliteral(luaContext->lua, "/?.lua;"); + lua_pushstring(luaContext->lua, path); + lua_pushliteral(luaContext->lua, "/?/init.lua"); + lua_concat(luaContext->lua, 6); + lua_settable(luaContext->lua, -3); + +#ifdef _WIN32 +#define DLL "dll" +#elif defined(__APPLE__) +#define DLL "dylib" +#else +#define DLL "so" +#endif + lua_pushliteral(luaContext->lua, "cpath"); + lua_pushliteral(luaContext->lua, "cpath"); + lua_gettable(luaContext->lua, -3); + oldcpath = strdup(lua_tostring(luaContext->lua, -1)); + lua_pushliteral(luaContext->lua, ";"); + lua_pushstring(luaContext->lua, path); + lua_pushliteral(luaContext->lua, "/?." DLL ";"); + lua_pushstring(luaContext->lua, path); + lua_pushliteral(luaContext->lua, "/?/init." DLL); + lua_concat(luaContext->lua, 6); + lua_settable(luaContext->lua, -3); + + lua_pop(luaContext->lua, 1); + + lua_rawgeti(luaContext->lua, LUA_REGISTRYINDEX, luaContext->require); + lua_rotate(luaContext->lua, -2, 1); + int ret = lua_pcall(luaContext->lua, 1, 0, 0); + + lua_getglobal(luaContext->lua, "package"); + + lua_pushliteral(luaContext->lua, "path"); + lua_pushstring(luaContext->lua, oldpath); + lua_settable(luaContext->lua, -3); + + lua_pushliteral(luaContext->lua, "cpath"); + lua_pushstring(luaContext->lua, oldcpath); + lua_settable(luaContext->lua, -3); + + lua_pop(luaContext->lua, 1); + + if (ret) { + lua_error(luaContext->lua); + } + + return 0; +} From b43509e705808e6bcc720367124d2db92583d967 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 9 Jun 2022 01:00:46 -0700 Subject: [PATCH 048/102] Scripting: Free memory leak --- src/script/engines/lua.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index 343b07cb2..c101155da 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -989,15 +989,13 @@ static int _luaRequireShim(lua_State* lua) { struct mScriptEngineContextLua* luaContext = _luaGetContext(lua); const char* path = lua_tostring(lua, lua_upvalueindex(1)); - const char* oldpath; - const char* oldcpath; lua_getglobal(luaContext->lua, "package"); lua_pushliteral(luaContext->lua, "path"); lua_pushliteral(luaContext->lua, "path"); lua_gettable(luaContext->lua, -3); - oldpath = strdup(lua_tostring(luaContext->lua, -1)); + char* oldpath = strdup(lua_tostring(luaContext->lua, -1)); lua_pushliteral(luaContext->lua, ";"); lua_pushstring(luaContext->lua, path); lua_pushliteral(luaContext->lua, "/?.lua;"); @@ -1016,7 +1014,7 @@ static int _luaRequireShim(lua_State* lua) { lua_pushliteral(luaContext->lua, "cpath"); lua_pushliteral(luaContext->lua, "cpath"); lua_gettable(luaContext->lua, -3); - oldcpath = strdup(lua_tostring(luaContext->lua, -1)); + char* oldcpath = strdup(lua_tostring(luaContext->lua, -1)); lua_pushliteral(luaContext->lua, ";"); lua_pushstring(luaContext->lua, path); lua_pushliteral(luaContext->lua, "/?." DLL ";"); @@ -1043,6 +1041,8 @@ static int _luaRequireShim(lua_State* lua) { lua_pop(luaContext->lua, 1); + free(oldpath); + free(oldcpath); if (ret) { lua_error(luaContext->lua); } From aee35a4442918fa9faaf4874d9e26a06ad7e7390 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 9 Jun 2022 14:54:30 -0700 Subject: [PATCH 049/102] Scripting: More cleanup --- src/script/engines/lua.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index c101155da..af9a18e77 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -182,6 +182,9 @@ void _luaDestroy(struct mScriptEngineContext* ctx) { if (luaContext->func > 0) { luaL_unref(luaContext->lua, LUA_REGISTRYINDEX, luaContext->func); } + if (luaContext->require > 0) { + luaL_unref(luaContext->lua, LUA_REGISTRYINDEX, luaContext->require); + } lua_close(luaContext->lua); free(luaContext); } @@ -1047,5 +1050,5 @@ static int _luaRequireShim(lua_State* lua) { lua_error(luaContext->lua); } - return 0; + return 1; } From 45b47c32d2090c3e89f8f47150b9b0057272b6a4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 9 Jun 2022 16:18:34 -0700 Subject: [PATCH 050/102] Scripting: Much cleaner require shimming --- src/script/engines/lua.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index af9a18e77..aba42141c 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -80,7 +80,6 @@ struct mScriptEngineContextLua { struct mScriptEngineContext d; lua_State* lua; int func; - char lastDirectory[PATH_MAX]; int require; char* lastError; }; @@ -515,12 +514,15 @@ bool _luaLoad(struct mScriptEngineContext* ctx, const char* filename, struct VFi int ret = lua_load(luaContext->lua, _reader, &data, filename, "t"); switch (ret) { case LUA_OK: - luaContext->func = luaL_ref(luaContext->lua, LUA_REGISTRYINDEX); if (dirname[0]) { - strncpy(luaContext->lastDirectory, dirname, sizeof(luaContext->lastDirectory)); - } else { - memset(luaContext->lastDirectory, 0, sizeof(luaContext->lastDirectory)); + lua_getupvalue(luaContext->lua, -1, 1); + lua_pushliteral(luaContext->lua, "require"); + lua_pushstring(luaContext->lua, dirname); + lua_pushcclosure(luaContext->lua, _luaRequireShim, 1); + lua_rawset(luaContext->lua, -3); + lua_pop(luaContext->lua, 1); } + luaContext->func = luaL_ref(luaContext->lua, LUA_REGISTRYINDEX); return true; case LUA_ERRSYNTAX: luaContext->lastError = strdup(lua_tostring(luaContext->lua, -1)); @@ -535,20 +537,8 @@ bool _luaLoad(struct mScriptEngineContext* ctx, const char* filename, struct VFi bool _luaRun(struct mScriptEngineContext* context) { struct mScriptEngineContextLua* luaContext = (struct mScriptEngineContextLua*) context; - if (luaContext->lastDirectory[0]) { - // Shim require to look in the previous location - lua_pushstring(luaContext->lua, luaContext->lastDirectory); - lua_pushcclosure(luaContext->lua, _luaRequireShim, 1); - lua_setglobal(luaContext->lua, "require"); - } - lua_rawgeti(luaContext->lua, LUA_REGISTRYINDEX, luaContext->func); - bool ret = _luaInvoke(luaContext, NULL); - - // Restore previous value of require - lua_rawgeti(luaContext->lua, LUA_REGISTRYINDEX, luaContext->require); - lua_setglobal(luaContext->lua, "require"); - return ret; + return _luaInvoke(luaContext, NULL); } const char* _luaGetError(struct mScriptEngineContext* context) { From d9092c6acfa586400ecaaa0992daae2bd0b146d7 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 9 Jun 2022 16:37:40 -0700 Subject: [PATCH 051/102] Scripting: Invert search order --- src/script/engines/lua.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index aba42141c..3131f060d 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -986,15 +986,14 @@ static int _luaRequireShim(lua_State* lua) { lua_getglobal(luaContext->lua, "package"); lua_pushliteral(luaContext->lua, "path"); - lua_pushliteral(luaContext->lua, "path"); - lua_gettable(luaContext->lua, -3); - char* oldpath = strdup(lua_tostring(luaContext->lua, -1)); - lua_pushliteral(luaContext->lua, ";"); lua_pushstring(luaContext->lua, path); lua_pushliteral(luaContext->lua, "/?.lua;"); lua_pushstring(luaContext->lua, path); - lua_pushliteral(luaContext->lua, "/?/init.lua"); - lua_concat(luaContext->lua, 6); + lua_pushliteral(luaContext->lua, "/?/init.lua;"); + lua_pushliteral(luaContext->lua, "path"); + lua_gettable(luaContext->lua, -7); + char* oldpath = strdup(lua_tostring(luaContext->lua, -1)); + lua_concat(luaContext->lua, 5); lua_settable(luaContext->lua, -3); #ifdef _WIN32 @@ -1005,15 +1004,14 @@ static int _luaRequireShim(lua_State* lua) { #define DLL "so" #endif lua_pushliteral(luaContext->lua, "cpath"); - lua_pushliteral(luaContext->lua, "cpath"); - lua_gettable(luaContext->lua, -3); - char* oldcpath = strdup(lua_tostring(luaContext->lua, -1)); - lua_pushliteral(luaContext->lua, ";"); lua_pushstring(luaContext->lua, path); lua_pushliteral(luaContext->lua, "/?." DLL ";"); lua_pushstring(luaContext->lua, path); - lua_pushliteral(luaContext->lua, "/?/init." DLL); - lua_concat(luaContext->lua, 6); + lua_pushliteral(luaContext->lua, "/?/init." DLL ";"); + lua_pushliteral(luaContext->lua, "cpath"); + lua_gettable(luaContext->lua, -7); + char* oldcpath = strdup(lua_tostring(luaContext->lua, -1)); + lua_concat(luaContext->lua, 5); lua_settable(luaContext->lua, -3); lua_pop(luaContext->lua, 1); From 9ac6096c3d3be6636aa20d0c4d41fb2ca78cd514 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 9 Jun 2022 21:10:27 -0700 Subject: [PATCH 052/102] GB SIO: Fix bidirectional transfer starting (fixes #2290) --- CHANGES | 1 + src/gb/sio/lockstep.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index ae7e136e4..079ffdb8d 100644 --- a/CHANGES +++ b/CHANGES @@ -26,6 +26,7 @@ Emulation fixes: - GB I/O: Fix writing to WAVE RAM behavior (fixes mgba.io/i/1334) - GB Memory: Add cursory cartridge open bus emulation (fixes mgba.io/i/2032) - GB Serialize: Fix loading MBC1 states that affect bank 0 (fixes mgba.io/i/2402) + - GB SIO: Fix bidirectional transfer starting (fixes mgba.io/i/2290) - GB Video: Draw SGB border pieces that overlap GB graphics (fixes mgba.io/i/1339) - GBA: Improve timing when not booting from BIOS - GBA: Fix expected entry point for multiboot ELFs (fixes mgba.io/i/2450) diff --git a/src/gb/sio/lockstep.c b/src/gb/sio/lockstep.c index d739140e5..4d1f1f549 100644 --- a/src/gb/sio/lockstep.c +++ b/src/gb/sio/lockstep.c @@ -157,7 +157,7 @@ static int32_t _masterUpdate(struct GBSIOLockstepNode* node) { } } // Tell the other GBs they can continue up to where we were - node->p->d.addCycles(&node->p->d, 0, node->eventDiff); + node->p->d.addCycles(&node->p->d, node->id, node->eventDiff); #ifndef NDEBUG node->phase = node->p->d.transferActive; #endif @@ -252,6 +252,12 @@ static uint8_t GBSIOLockstepNodeWriteSC(struct GBSIODriver* driver, uint8_t valu mLockstepLock(&node->p->d); bool claimed = false; if (ATOMIC_CMPXCHG(node->p->masterClaimed, claimed, true)) { + if (node->id != 0) { + node->p->players[0]->id = 1; + node->p->players[1] = node->p->players[0]; + node->p->players[0] = node->p->players[1]; + node->id = 0; + } ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING); ATOMIC_STORE(node->p->d.transferCycles, GBSIOCyclesPerTransfer[(value >> 1) & 1]); mTimingDeschedule(&driver->p->p->timing, &driver->p->event); From 601d025e3017bd56b7c12da842cba1edee5f6e03 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 10 Jun 2022 19:55:45 -0700 Subject: [PATCH 053/102] Scripting: Fix require return values --- src/script/engines/lua.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index 3131f060d..f8d71762e 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -981,6 +981,7 @@ static int _luaLenList(lua_State* lua) { static int _luaRequireShim(lua_State* lua) { struct mScriptEngineContextLua* luaContext = _luaGetContext(lua); + int oldtop = lua_gettop(luaContext->lua); const char* path = lua_tostring(lua, lua_upvalueindex(1)); lua_getglobal(luaContext->lua, "package"); @@ -1018,7 +1019,7 @@ static int _luaRequireShim(lua_State* lua) { lua_rawgeti(luaContext->lua, LUA_REGISTRYINDEX, luaContext->require); lua_rotate(luaContext->lua, -2, 1); - int ret = lua_pcall(luaContext->lua, 1, 0, 0); + int ret = lua_pcall(luaContext->lua, 1, LUA_MULTRET, 0); lua_getglobal(luaContext->lua, "package"); @@ -1038,5 +1039,6 @@ static int _luaRequireShim(lua_State* lua) { lua_error(luaContext->lua); } - return 1; + int newtop = lua_gettop(luaContext->lua); + return newtop - oldtop + 1; } From c12fa581b356bdabd67b8d1a6f6f21a98694197f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 10 Jun 2022 20:51:26 -0700 Subject: [PATCH 054/102] Scripting: Fix build with Lua 5.1 and 5.2 --- src/script/engines/lua.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index f8d71762e..f5adfcdd5 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -55,6 +55,14 @@ static int _luaRequireShim(lua_State* lua); #define lua_pushinteger lua_pushnumber #endif +#ifndef LUA_OK +#define LUA_OK 0 +#endif + +#if LUA_VERSION_NUM < 502 +#define luaL_traceback(L, M, S, level) lua_pushstring(L, S) +#endif + const struct mScriptType mSTLuaFunc = { .base = mSCRIPT_TYPE_FUNCTION, .size = 0, @@ -427,7 +435,8 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v } else { mScriptValueWrap(value, newValue); } - luaL_setmetatable(luaContext->lua, "mSTList"); + lua_getfield(luaContext->lua, LUA_REGISTRYINDEX, "mSTList"); + lua_setmetatable(luaContext->lua, -2); break; case mSCRIPT_TYPE_TABLE: newValue = lua_newuserdata(luaContext->lua, sizeof(*newValue)); @@ -436,7 +445,8 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v } else { mScriptValueWrap(value, newValue); } - luaL_setmetatable(luaContext->lua, "mSTTable"); + lua_getfield(luaContext->lua, LUA_REGISTRYINDEX, "mSTTable"); + lua_setmetatable(luaContext->lua, -2); break; case mSCRIPT_TYPE_FUNCTION: newValue = lua_newuserdata(luaContext->lua, sizeof(*newValue)); @@ -453,7 +463,8 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v } else { mScriptValueWrap(value, newValue); } - luaL_setmetatable(luaContext->lua, "mSTStruct"); + lua_getfield(luaContext->lua, LUA_REGISTRYINDEX, "mSTStruct"); + lua_setmetatable(luaContext->lua, -2); break; default: ok = false; @@ -511,7 +522,11 @@ bool _luaLoad(struct mScriptEngineContext* ctx, const char* filename, struct VFi } filename = name; } +#if LUA_VERSION_NUM >= 502 int ret = lua_load(luaContext->lua, _reader, &data, filename, "t"); +#else + int ret = lua_load(luaContext->lua, _reader, &data, filename); +#endif switch (ret) { case LUA_OK: if (dirname[0]) { @@ -662,8 +677,8 @@ void _luaDeref(struct mScriptValue* value) { static struct mScriptEngineContextLua* _luaGetContext(lua_State* lua) { lua_pushliteral(lua, "mCtx"); - int type = lua_rawget(lua, LUA_REGISTRYINDEX); - if (type != LUA_TLIGHTUSERDATA) { + lua_rawget(lua, LUA_REGISTRYINDEX); + if (lua_type(lua, -1) != LUA_TLIGHTUSERDATA) { lua_pop(lua, 1); lua_pushliteral(lua, "Function called from invalid context"); lua_error(lua); @@ -1018,7 +1033,7 @@ static int _luaRequireShim(lua_State* lua) { lua_pop(luaContext->lua, 1); lua_rawgeti(luaContext->lua, LUA_REGISTRYINDEX, luaContext->require); - lua_rotate(luaContext->lua, -2, 1); + lua_insert(luaContext->lua, -2); int ret = lua_pcall(luaContext->lua, 1, LUA_MULTRET, 0); lua_getglobal(luaContext->lua, "package"); From d2ac7c4ca0e2ff304b745c347ce4eb0c4f1b5507 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 10 Jun 2022 20:59:27 -0700 Subject: [PATCH 055/102] Qt: Add Lua to report view --- src/platform/qt/ReportView.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/platform/qt/ReportView.cpp b/src/platform/qt/ReportView.cpp index edfddd21c..b38483e7f 100644 --- a/src/platform/qt/ReportView.cpp +++ b/src/platform/qt/ReportView.cpp @@ -61,6 +61,10 @@ #include #endif +#ifdef USE_LUA +#include +#endif + #ifdef USE_LZMA #include <7zVersion.h> #endif @@ -168,6 +172,11 @@ void ReportView::generateReport() { #else swReport << QString("libLZMA not linked"); #endif +#ifdef USE_LUA + swReport << QString("Lua version: %1").arg(QLatin1String(LUA_RELEASE)); +#else + swReport << QString("Lua not linked"); +#endif #ifdef USE_MINIZIP swReport << QString("minizip linked"); #else From 7f453ce20294789a50584d5614a3e371dfa411e5 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 14 Jun 2022 00:13:51 -0700 Subject: [PATCH 056/102] GBA Video: Fix horizontal lines in GL when charbase is changed (fixes #1631) --- CHANGES | 1 + include/mgba/internal/gba/renderers/gl.h | 2 ++ src/gba/renderers/gl.c | 26 ++++++++++++++++-------- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index 079ffdb8d..fed10442a 100644 --- a/CHANGES +++ b/CHANGES @@ -45,6 +45,7 @@ Emulation fixes: - GBA Video: Fix rare crash in modes 3-5 - GBA Video: Fix sprites with mid-frame palette changes in GL (fixes mgba.io/i/2476) - GBA Video: Fix OBJ tile wrapping with 2D char mapping (fixes mgba.io/i/2443) + - GBA Video: Fix horizontal lines in GL when charbase is changed (fixes mgba.io/i/1631) Other fixes: - ARM: Disassemble Thumb mov pseudo-instruction properly - Core: Don't attempt to restore rewind diffs past start of rewind diff --git a/include/mgba/internal/gba/renderers/gl.h b/include/mgba/internal/gba/renderers/gl.h index 42068e53f..9e022f6f5 100644 --- a/include/mgba/internal/gba/renderers/gl.h +++ b/include/mgba/internal/gba/renderers/gl.h @@ -49,6 +49,7 @@ struct GBAVideoGLBackground { int enabled; unsigned priority; uint32_t charBase; + uint32_t oldCharBase; int mosaic; int multipalette; uint32_t screenBase; @@ -99,6 +100,7 @@ enum { GBA_GL_BG_TRANSFORM, GBA_GL_BG_RANGE, GBA_GL_BG_MOSAIC, + GBA_GL_BG_OLDCHARBASE, GBA_GL_OBJ_VRAM = 2, GBA_GL_OBJ_PALETTE, diff --git a/src/gba/renderers/gl.c b/src/gba/renderers/gl.c index 0fcd70617..a06b2e4d6 100644 --- a/src/gba/renderers/gl.c +++ b/src/gba/renderers/gl.c @@ -204,6 +204,7 @@ static const struct GBAVideoGLUniform _uniformsMode2[] = { { "vram", GBA_GL_BG_VRAM, }, { "palette", GBA_GL_BG_PALETTE, }, { "screenBase", GBA_GL_BG_SCREENBASE, }, + { "oldCharBase", GBA_GL_BG_OLDCHARBASE, }, { "charBase", GBA_GL_BG_CHARBASE, }, { "size", GBA_GL_BG_SIZE, }, { "offset", GBA_GL_BG_OFFSET, }, @@ -240,6 +241,7 @@ static const char* const _renderMode2 = "uniform isampler2D vram;\n" "uniform sampler2D palette;\n" "uniform int screenBase;\n" + "uniform ivec2 oldCharBase;\n" "uniform int charBase;\n" "uniform int size;\n" "uniform ivec4 transform[160];\n" @@ -256,7 +258,17 @@ static const char* const _renderMode2 = " int mapAddress = screenBase + (map >> 1);\n" " int twomaps = texelFetch(vram, ivec2(mapAddress & 255, mapAddress >> 8), 0).r;\n" " int tile = (twomaps >> (8 * (map & 1))) & 255;\n" - " int address = charBase + tile * 32 + ((coord.x >> 9) & 3) + ((coord.y >> 6) & 0x1C);\n" + " int newCharBase = charBase;\n" + " if (newCharBase != oldCharBase.x) {\n" + " int y = int(texCoord.y);\n" + // If the charbase has changed (and the scale is greater than 1), we might still be drawing + // the tile associated with the pixel above us. If we're still on that tile, we want to use + // the charbase associated with it instead of the new one. Cf. https://mgba.io/i/1631 + " if (y == oldCharBase.y && transform[y - 1].w >> 11 == coord.y >> 11) {\n" + " newCharBase = oldCharBase.x;\n" + " }\n" + " }\n" + " int address = newCharBase + tile * 32 + ((coord.x >> 9) & 3) + ((coord.y >> 6) & 0x1C);\n" " int halfrow = texelFetch(vram, ivec2(address & 255, address >> 8), 0).r;\n" " int entry = (halfrow >> (8 * ((coord.x >> 8) & 1))) & 255;\n" " if (entry == 0) {\n" @@ -1012,42 +1024,34 @@ uint16_t GBAVideoGLRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, case REG_BG0HOFS: value &= 0x01FF; glRenderer->bg[0].x = value; - dirty = false; break; case REG_BG0VOFS: value &= 0x01FF; glRenderer->bg[0].y = value; - dirty = false; break; case REG_BG1HOFS: value &= 0x01FF; glRenderer->bg[1].x = value; - dirty = false; break; case REG_BG1VOFS: value &= 0x01FF; glRenderer->bg[1].y = value; - dirty = false; break; case REG_BG2HOFS: value &= 0x01FF; glRenderer->bg[2].x = value; - dirty = false; break; case REG_BG2VOFS: value &= 0x01FF; glRenderer->bg[2].y = value; - dirty = false; break; case REG_BG3HOFS: value &= 0x01FF; glRenderer->bg[3].x = value; - dirty = false; break; case REG_BG3VOFS: value &= 0x01FF; glRenderer->bg[3].y = value; - dirty = false; break; case REG_BG2PA: glRenderer->bg[2].affine.dx = value; @@ -1346,6 +1350,7 @@ void GBAVideoGLRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) { if (_needsVramUpload(glRenderer, y) || glRenderer->oamDirty || glRenderer->regsDirty) { if (glRenderer->firstY >= 0) { _drawScanlines(glRenderer, y - 1); + glRenderer->firstY = y; glBindVertexArray(0); } } @@ -1620,6 +1625,7 @@ static void GBAVideoGLRendererUpdateDISPCNT(struct GBAVideoGLRenderer* renderer) static void GBAVideoGLRendererWriteBGCNT(struct GBAVideoGLBackground* bg, uint16_t value) { bg->priority = GBARegisterBGCNTGetPriority(value); + bg->oldCharBase = bg->charBase; bg->charBase = GBARegisterBGCNTGetCharBase(value) << 13; bg->mosaic = GBARegisterBGCNTGetMosaic(value); bg->multipalette = GBARegisterBGCNTGet256Color(value); @@ -1898,10 +1904,12 @@ void GBAVideoGLRendererDrawBackgroundMode2(struct GBAVideoGLRenderer* renderer, glBindVertexArray(shader->vao); _prepareTransform(renderer, background, uniforms, y); glUniform1i(uniforms[GBA_GL_BG_SCREENBASE], background->screenBase); + glUniform2i(uniforms[GBA_GL_BG_OLDCHARBASE], background->oldCharBase, renderer->firstY); glUniform1i(uniforms[GBA_GL_BG_CHARBASE], background->charBase); glUniform1i(uniforms[GBA_GL_BG_SIZE], background->size); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 }); + background->oldCharBase = background->charBase; } void GBAVideoGLRendererDrawBackgroundMode3(struct GBAVideoGLRenderer* renderer, struct GBAVideoGLBackground* background, int y) { From 4707368d7fc89ca5c6d49f0770bf4a06ebce9c85 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 14 Jun 2022 00:17:54 -0700 Subject: [PATCH 057/102] Qt: Fix typo --- src/platform/qt/ConfigController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/ConfigController.cpp b/src/platform/qt/ConfigController.cpp index 4fc4037e0..767cd277f 100644 --- a/src/platform/qt/ConfigController.cpp +++ b/src/platform/qt/ConfigController.cpp @@ -136,7 +136,7 @@ ConfigController::ConfigController(QObject* parent) m_subparsers[1].usage = "Frontend options:\n" " --ecard FILE Scan an e-Reader card in the first loaded game\n" - " Can be paassed multiple times for multiple cards\n" + " Can be passed multiple times for multiple cards\n" " --mb FILE Boot a multiboot image with FILE inserted into the ROM slot"; m_subparsers[1].parse = nullptr; m_subparsers[1].parseLong = [](struct mSubParser* parser, const char* option, const char* arg) { From f7d8b77bd47cf0d762496ad3a25aefa9ebd45ac9 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 14 Jun 2022 15:15:11 -0700 Subject: [PATCH 058/102] GB MBC: Fix edge case with Pocket Cam register accesses (fixes #2557) --- CHANGES | 1 + src/gb/mbc.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGES b/CHANGES index fed10442a..390ac425f 100644 --- a/CHANGES +++ b/CHANGES @@ -25,6 +25,7 @@ Emulation fixes: - GB Audio: Fix APU re-enable timing glitch - GB I/O: Fix writing to WAVE RAM behavior (fixes mgba.io/i/1334) - GB Memory: Add cursory cartridge open bus emulation (fixes mgba.io/i/2032) + - GB MBC: Fix edge case with Pocket Cam register accesses (fixes mgba.io/i/2557) - GB Serialize: Fix loading MBC1 states that affect bank 0 (fixes mgba.io/i/2402) - GB SIO: Fix bidirectional transfer starting (fixes mgba.io/i/2290) - GB Video: Draw SGB border pieces that overlap GB graphics (fixes mgba.io/i/1339) diff --git a/src/gb/mbc.c b/src/gb/mbc.c index 9e8724964..282891cfe 100644 --- a/src/gb/mbc.c +++ b/src/gb/mbc.c @@ -1402,11 +1402,16 @@ void _GBPocketCam(struct GB* gb, uint16_t address, uint8_t value) { if (value < 0x10) { GBMBCSwitchSramBank(gb, value); memory->mbcState.pocketCam.registersActive = false; + memory->directSramAccess = true; } else { memory->mbcState.pocketCam.registersActive = true; + memory->directSramAccess = false; } break; case 0x5: + if (!memory->mbcState.pocketCam.registersActive) { + break; + } address &= 0x7F; if (address == 0 && value & 1) { value &= 6; // TODO: Timing From 85737f1103bcde52c33884ab55c05142b4ce82ad Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 14 Jun 2022 20:15:26 -0700 Subject: [PATCH 059/102] SDL: Support exposing an axis directly as the gyro value (closes #2531) --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 390ac425f..891e2ca6f 100644 --- a/CHANGES +++ b/CHANGES @@ -92,6 +92,7 @@ Misc: - Qt: Add e-Card passing to the command line (closes mgba.io/i/2474) - Qt: Boot both a multiboot image and ROM with CLI args (closes mgba.io/i/1941) - Qt: Improve cheat parsing (fixes mgba.io/i/2297) + - SDL: Support exposing an axis directly as the gyro value (closes mgba.io/i/2531) - Windows: Attach to console if present - Vita: Add bilinear filtering option (closes mgba.io/i/344) From a0613e27ab7817dd180835f0900c4b3364b3bb71 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 14 Jun 2022 21:12:53 -0700 Subject: [PATCH 060/102] SDL: Support exposing an axis directly as the gyro value (closes #2531) --- src/platform/qt/InputController.cpp | 10 ++++++++++ src/platform/qt/SensorView.ui | 4 ++-- src/platform/sdl/sdl-events.c | 14 ++++++++++++++ src/platform/sdl/sdl-events.h | 1 + 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp index 9a8458e1d..a0fb91397 100644 --- a/src/platform/qt/InputController.cpp +++ b/src/platform/qt/InputController.cpp @@ -341,6 +341,11 @@ void InputController::registerGyroAxisX(int axis) { #ifdef BUILD_SDL if (m_playerAttached) { m_sdlPlayer.rotation.gyroX = axis; + if (m_sdlPlayer.rotation.gyroY == axis) { + m_sdlPlayer.rotation.gyroZ = axis; + } else { + m_sdlPlayer.rotation.gyroZ = -1; + } } #endif } @@ -349,6 +354,11 @@ void InputController::registerGyroAxisY(int axis) { #ifdef BUILD_SDL if (m_playerAttached) { m_sdlPlayer.rotation.gyroY = axis; + if (m_sdlPlayer.rotation.gyroX == axis) { + m_sdlPlayer.rotation.gyroZ = axis; + } else { + m_sdlPlayer.rotation.gyroZ = -1; + } } #endif } diff --git a/src/platform/qt/SensorView.ui b/src/platform/qt/SensorView.ui index d75b5329d..7d65ba52c 100644 --- a/src/platform/qt/SensorView.ui +++ b/src/platform/qt/SensorView.ui @@ -284,10 +284,10 @@ false - -2147483647 + -1073741823 - 2147483647 + 1073741823 0 diff --git a/src/platform/sdl/sdl-events.c b/src/platform/sdl/sdl-events.c index b7e8b002b..a675ff2c0 100644 --- a/src/platform/sdl/sdl-events.c +++ b/src/platform/sdl/sdl-events.c @@ -199,6 +199,7 @@ bool mSDLAttachPlayer(struct mSDLEvents* events, struct mSDLPlayer* player) { player->rotation.gyroSensitivity = 2.2e9f; player->rotation.gyroX = 0; player->rotation.gyroY = 1; + player->rotation.gyroZ = -1; player->rotation.zDelta = 0; CircleBufferInit(&player->rotation.zHistory, sizeof(float) * GYRO_STEPS); player->rotation.p = player; @@ -327,6 +328,13 @@ void mSDLPlayerLoadConfig(struct mSDLPlayer* context, const struct Configuration context->rotation.gyroY = axis; } } + value = mInputGetCustomValue(config, "gba", SDL_BINDING_BUTTON, "gyroAxisZ", name); + if (value) { + axis = strtol(value, &end, 0); + if (axis >= 0 && axis < numAxes && end && !*end) { + context->rotation.gyroZ = axis; + } + } value = mInputGetCustomValue(config, "gba", SDL_BINDING_BUTTON, "gyroSensitivity", name); if (value) { float sensitivity = strtof_u(value, &end); @@ -357,6 +365,8 @@ void mSDLPlayerSaveConfig(const struct mSDLPlayer* context, struct Configuration mInputSetCustomValue(config, "gba", SDL_BINDING_BUTTON, "gyroAxisX", value, name); snprintf(value, sizeof(value), "%i", context->rotation.gyroY); mInputSetCustomValue(config, "gba", SDL_BINDING_BUTTON, "gyroAxisY", value, name); + snprintf(value, sizeof(value), "%i", context->rotation.gyroZ); + mInputSetCustomValue(config, "gba", SDL_BINDING_BUTTON, "gyroAxisZ", value, name); snprintf(value, sizeof(value), "%g", context->rotation.gyroSensitivity); mInputSetCustomValue(config, "gba", SDL_BINDING_BUTTON, "gyroSensitivity", value, name); } @@ -750,6 +760,10 @@ static void _mSDLRotationSample(struct mRotationSource* source) { } } #endif + if (rotation->gyroZ >= 0) { + rotation->zDelta = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroZ) / 1.e5f; + return; + } int x = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroX); int y = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroY); diff --git a/src/platform/sdl/sdl-events.h b/src/platform/sdl/sdl-events.h index 1763865e2..8bdbd7c0b 100644 --- a/src/platform/sdl/sdl-events.h +++ b/src/platform/sdl/sdl-events.h @@ -95,6 +95,7 @@ struct mSDLPlayer { // Gyro int gyroX; int gyroY; + int gyroZ; float gyroSensitivity; struct CircleBuffer zHistory; int oldX; From 33b3d33da2f4e3c201834420e21b92d7fbffa443 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 15 Jun 2022 18:39:38 -0700 Subject: [PATCH 061/102] Core: Rename GBAStereoSample to mStereoSample --- include/mgba/core/interface.h | 5 +++++ include/mgba/internal/gba/audio.h | 8 ++------ src/gba/extra/audio-mixer.c | 4 ++-- src/platform/psp2/psp2-context.c | 4 ++-- src/platform/qt/AudioDevice.cpp | 8 ++++---- src/platform/switch/main.c | 4 ++-- src/platform/wii/main.c | 6 +++--- 7 files changed, 20 insertions(+), 19 deletions(-) diff --git a/include/mgba/core/interface.h b/include/mgba/core/interface.h index a480db6e5..fadaaa29d 100644 --- a/include/mgba/core/interface.h +++ b/include/mgba/core/interface.h @@ -194,6 +194,11 @@ struct mAVStream { void (*postAudioBuffer)(struct mAVStream*, struct blip_t* left, struct blip_t* right); }; +struct mStereoSample { + int16_t left; + int16_t right; +}; + struct mKeyCallback { uint16_t (*readKeys)(struct mKeyCallback*); bool requireOpposingDirections; diff --git a/include/mgba/internal/gba/audio.h b/include/mgba/internal/gba/audio.h index 65336b299..26fe69992 100644 --- a/include/mgba/internal/gba/audio.h +++ b/include/mgba/internal/gba/audio.h @@ -11,6 +11,7 @@ CXX_GUARD_START #include +#include #include #include #include @@ -94,11 +95,6 @@ struct GBAAudio { struct mTimingEvent sampleEvent; }; -struct GBAStereoSample { - int16_t left; - int16_t right; -}; - struct GBAMP2kADSR { uint8_t attack; uint8_t decay; @@ -278,7 +274,7 @@ struct GBAAudioMixer { double tempo; double frame; - struct GBAStereoSample last; + struct mStereoSample last; }; void GBAAudioInit(struct GBAAudio* audio, size_t samples); diff --git a/src/gba/extra/audio-mixer.c b/src/gba/extra/audio-mixer.c index fe9ed6901..503fdc8ad 100644 --- a/src/gba/extra/audio-mixer.c +++ b/src/gba/extra/audio-mixer.c @@ -125,7 +125,7 @@ static void _stepSample(struct GBAAudioMixer* mixer, struct GBAMP2kTrack* track) for (nSample = 0; nSample < updates; ++nSample) { int8_t sample = memory->load8(cpu, sampleBase + sampleI, 0); - struct GBAStereoSample stereo = { + struct mStereoSample stereo = { (sample * track->channel->leftVolume * track->channel->envelopeV) >> 9, (sample * track->channel->rightVolume * track->channel->envelopeV) >> 9 }; @@ -277,7 +277,7 @@ void _mp2kStep(struct GBAAudioMixer* mixer) { uint32_t interval = mixer->p->sampleInterval / OVERSAMPLE; int i; for (i = 0; i < OVERSAMPLE; ++i) { - struct GBAStereoSample sample = {0}; + struct mStereoSample sample = {0}; size_t track; for (track = 0; track < MP2K_MAX_SOUND_CHANNELS; ++track) { if (!mixer->activeTracks[track].channel->status) { diff --git a/src/platform/psp2/psp2-context.c b/src/platform/psp2/psp2-context.c index 82f0c6029..f860bc4a1 100644 --- a/src/platform/psp2/psp2-context.c +++ b/src/platform/psp2/psp2-context.c @@ -88,7 +88,7 @@ static vita2d_texture* backdrop = 0; #define PSP2_AUDIO_BUFFER_SIZE (PSP2_SAMPLES * 16) static struct mPSP2AudioContext { - struct GBAStereoSample buffer[PSP2_AUDIO_BUFFER_SIZE]; + struct mStereoSample buffer[PSP2_AUDIO_BUFFER_SIZE]; size_t writeOffset; size_t readOffset; size_t samples; @@ -255,7 +255,7 @@ static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* rig } ConditionWait(&audioContext.cond, &audioContext.mutex); } - struct GBAStereoSample* samples = &audioContext.buffer[audioContext.writeOffset]; + struct mStereoSample* samples = &audioContext.buffer[audioContext.writeOffset]; blip_read_samples(left, &samples[0].left, PSP2_SAMPLES, true); blip_read_samples(right, &samples[0].right, PSP2_SAMPLES, true); audioContext.samples += PSP2_SAMPLES; diff --git a/src/platform/qt/AudioDevice.cpp b/src/platform/qt/AudioDevice.cpp index 9baf12712..74f863444 100644 --- a/src/platform/qt/AudioDevice.cpp +++ b/src/platform/qt/AudioDevice.cpp @@ -45,17 +45,17 @@ qint64 AudioDevice::readData(char* data, qint64 maxSize) { return 0; } - maxSize /= sizeof(GBAStereoSample); + maxSize /= sizeof(mStereoSample); mCoreSyncLockAudio(&m_context->impl->sync); int available = std::min({ blip_samples_avail(m_context->core->getAudioChannel(m_context->core, 0)), maxSize, std::numeric_limits::max() }); - blip_read_samples(m_context->core->getAudioChannel(m_context->core, 0), &reinterpret_cast(data)->left, available, true); - blip_read_samples(m_context->core->getAudioChannel(m_context->core, 1), &reinterpret_cast(data)->right, available, true); + blip_read_samples(m_context->core->getAudioChannel(m_context->core, 0), &reinterpret_cast(data)->left, available, true); + blip_read_samples(m_context->core->getAudioChannel(m_context->core, 1), &reinterpret_cast(data)->right, available, true); mCoreSyncConsumeAudio(&m_context->impl->sync); - return available * sizeof(GBAStereoSample); + return available * sizeof(mStereoSample); } qint64 AudioDevice::writeData(const char*, qint64) { diff --git a/src/platform/switch/main.c b/src/platform/switch/main.c index 0a40d3a90..25b6f6eca 100644 --- a/src/platform/switch/main.c +++ b/src/platform/switch/main.c @@ -115,7 +115,7 @@ static float gyroZ = 0; static float tiltX = 0; static float tiltY = 0; -static struct GBAStereoSample audioBuffer[N_BUFFERS][BUFFER_SIZE / 4] __attribute__((__aligned__(0x1000))); +static struct mStereoSample audioBuffer[N_BUFFERS][BUFFER_SIZE / 4] __attribute__((__aligned__(0x1000))); static enum ScreenMode { SM_PA, @@ -584,7 +584,7 @@ static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* rig blip_clear(right); return; } - struct GBAStereoSample* samples = audioBuffer[audioBufferActive]; + struct mStereoSample* samples = audioBuffer[audioBufferActive]; blip_read_samples(left, &samples[0].left, SAMPLES, true); blip_read_samples(right, &samples[0].right, SAMPLES, true); audoutAppendAudioOutBuffer(&audoutBuffer[audioBufferActive]); diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index 8b3ed8226..36bb9abfc 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -141,7 +141,7 @@ static void* framebuffer[2] = { 0, 0 }; static int whichFb = 0; static struct AudioBuffer { - struct GBAStereoSample samples[SAMPLES] __attribute__((__aligned__(32))); + struct mStereoSample samples[SAMPLES] __attribute__((__aligned__(32))); volatile size_t size; } audioBuffer[BUFFERS] = {0}; static volatile int currentAudioBuffer = 0; @@ -685,8 +685,8 @@ static void _audioDMA(void) { if (buffer->size != SAMPLES) { return; } - DCFlushRange(buffer->samples, SAMPLES * sizeof(struct GBAStereoSample)); - AUDIO_InitDMA((u32) buffer->samples, SAMPLES * sizeof(struct GBAStereoSample)); + DCFlushRange(buffer->samples, SAMPLES * sizeof(struct mStereoSample)); + AUDIO_InitDMA((u32) buffer->samples, SAMPLES * sizeof(struct mStereoSample)); buffer->size = 0; currentAudioBuffer = (currentAudioBuffer + 1) % BUFFERS; } From 6159c5a70b6a92cb18948e9e1d7d214b3cdc9a48 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 15 Jun 2022 20:34:06 -0700 Subject: [PATCH 062/102] GBA Audio: Decrunchify GB audio --- include/mgba/internal/gba/audio.h | 8 +- include/mgba/internal/gba/serialize.h | 37 +++++++--- src/gb/audio.c | 19 +++-- src/gba/audio.c | 102 ++++++++++++++++++++------ src/gba/serialize.c | 2 +- src/gba/video.c | 7 +- 6 files changed, 125 insertions(+), 50 deletions(-) diff --git a/include/mgba/internal/gba/audio.h b/include/mgba/internal/gba/audio.h index 26fe69992..8b212dd6a 100644 --- a/include/mgba/internal/gba/audio.h +++ b/include/mgba/internal/gba/audio.h @@ -80,14 +80,16 @@ struct GBAAudio { bool enable; size_t samples; - unsigned sampleRate; - GBARegisterSOUNDBIAS soundbias; struct GBAAudioMixer* mixer; bool externalMixing; int32_t sampleInterval; + int32_t lastSample; + int sampleIndex; + struct mStereoSample currentSamples[GBA_MAX_SAMPLES]; + bool forceDisableChA; bool forceDisableChB; int masterVolume; @@ -305,6 +307,8 @@ uint32_t GBAAudioReadWaveRAM(struct GBAAudio* audio, int address); uint32_t GBAAudioWriteFIFO(struct GBAAudio* audio, int address, uint32_t value); void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles); +void GBAAudioSample(struct GBAAudio* audio, int32_t timestamp); + struct GBASerializedState; void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state); void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState* state); diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index f3ed332dc..07223ea3f 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -71,7 +71,7 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * | 0x00188 - 0x0018B: Next event * 0x0018C - 0x001AB: Audio FIFO 1 * 0x001AC - 0x001CB: Audio FIFO 2 - * 0x001CC - 0x001DF: Audio miscellaneous state + * 0x001CC - 0x001EF: Audio miscellaneous state * | 0x001CC - 0x001CF: Channel A internal audio samples * | 0x001D0 - 0x001D3: Channel B internal audio samples * | 0x001D4 - 0x001D7: Next sample @@ -104,9 +104,13 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * | bit 3: Is channel 3's memory readable? * | bit 4: Skip frame * | bits 5 - 7: Reserved - * 0x001E0 - 0x001FF: Video miscellaneous state - * | 0x001E0 - 0x001E3: Next event - * | 0x001E4 - 0x001F7: Reserved + * | 0x001E0 - 0x001E3: Last sample + * | 0x001E4 - 0x001E7: Additional audio flags + * | bits 0 - 3: Current sample index + * | 0x001E8 - 0x001EF: Reserved + * 0x001F0 - 0x001FF: Video miscellaneous state + * | 0x001F0 - 0x001F3: Reserved + * | 0x001F4 - 0x001F7: Next event * | 0x001F8 - 0x001FB: Miscellaneous flags * | 0x001FC - 0x001FF: Frame counter * 0x00200 - 0x00213: Timer 0 @@ -227,7 +231,8 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * 0x00368 - 0x0036F: Reserved (leave zero) * 0x00370 - 0x0037F: Audio FIFO A samples * 0x00380 - 0x0038F: Audio FIFO B samples - * 0x00390 - 0x003FF: Reserved (leave zero) + * 0x00390 - 0x003CF: Audio rendered samples + * 0x003D0 - 0x003FF: Reserved (leave zero) * 0x00400 - 0x007FF: I/O memory * 0x00800 - 0x00BFF: Palette * 0x00C00 - 0x00FFF: OAM @@ -243,6 +248,9 @@ DECL_BITS(GBASerializedAudioFlags, FIFOSamplesB, 2, 3); // Yay legacy? DECL_BITS(GBASerializedAudioFlags, FIFOInternalSamplesA, 5, 2); DECL_BITS(GBASerializedAudioFlags, FIFOSamplesA, 7, 3); +DECL_BITFIELD(GBASerializedAudioFlags2, uint32_t); +DECL_BITS(GBASerializedAudioFlags2, SampleIndex, 0, 4); + DECL_BITFIELD(GBASerializedVideoFlags, uint32_t); DECL_BITS(GBASerializedVideoFlags, Mode, 0, 2); @@ -303,11 +311,14 @@ struct GBASerializedState { int8_t sampleB; GBASerializedAudioFlags gbaFlags; GBSerializedAudioFlags flags; + int32_t lastSample; + GBASerializedAudioFlags2 gbaFlags2; + int32_t reserved[2]; } audio; struct { + int32_t reserved; int32_t nextEvent; - int32_t reserved[5]; GBASerializedVideoFlags flags; uint32_t frameCounter; } video; @@ -384,14 +395,16 @@ struct GBASerializedState { int32_t biosStall; uint32_t matrixMappings[16]; - uint32_t reservedMatrix[2]; + uint32_t reservedMatrix[2]; - struct { - int8_t chA[16]; - int8_t chB[16]; - } samples; + struct { + int8_t chA[16]; + int8_t chB[16]; + } samples; - uint32_t reserved[28]; + struct mStereoSample currentSamples[16]; + + uint32_t reserved[12]; uint16_t io[SIZE_IO >> 1]; uint16_t pram[SIZE_PALETTE_RAM >> 1]; diff --git a/src/gb/audio.c b/src/gb/audio.c index 47911f794..94a1c40c4 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -11,6 +11,9 @@ #include #include #include +#ifdef M_CORE_GBA +#include +#endif #ifdef __3DS__ #define blip_add_delta blip_add_delta_fast @@ -69,7 +72,6 @@ void GBAudioInit(struct GBAudio* audio, size_t samples, uint8_t* nr52, enum GBAu audio->timingFactor = 2; } - audio->frameEvent.context = audio; audio->frameEvent.name = "GB Audio Frame Sequencer"; audio->frameEvent.callback = _updateFrame; audio->frameEvent.priority = 0x10; @@ -85,14 +87,10 @@ void GBAudioDeinit(struct GBAudio* audio) { } void GBAudioReset(struct GBAudio* audio) { - mTimingDeschedule(audio->timing, &audio->frameEvent); mTimingDeschedule(audio->timing, &audio->sampleEvent); if (audio->style != GB_AUDIO_GBA) { mTimingSchedule(audio->timing, &audio->sampleEvent, 0); } - if (audio->style == GB_AUDIO_GBA) { - mTimingSchedule(audio->timing, &audio->frameEvent, 0); - } audio->ch1 = (struct GBAudioSquareChannel) { .sweep = { .time = 8 }, .envelope = { .dead = 2 } }; audio->ch2 = (struct GBAudioSquareChannel) { .envelope = { .dead = 2 } }; audio->ch3 = (struct GBAudioWaveChannel) { .bank = 0 }; @@ -458,11 +456,12 @@ void GBAudioWriteNR52(struct GBAudio* audio, uint8_t value) { } void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate) { - struct GBAudio* audio = user; - GBAudioUpdateFrame(audio); - if (audio->style == GB_AUDIO_GBA) { - mTimingSchedule(timing, &audio->frameEvent, audio->timingFactor * FRAME_CYCLES - cyclesLate); - } +#ifdef M_CORE_GBA + struct GBAAudio* audio = user; + GBAAudioSample(audio, mTimingCurrentTime(timing)); + mTimingSchedule(timing, &audio->psg.frameEvent, audio->psg.timingFactor * FRAME_CYCLES - cyclesLate); + GBAudioUpdateFrame(&audio->psg); +#endif } void GBAudioRun(struct GBAudio* audio, int32_t timestamp, int channels) { diff --git a/src/gba/audio.c b/src/gba/audio.c index 00c20bd46..c4f989f63 100644 --- a/src/gba/audio.c +++ b/src/gba/audio.c @@ -44,6 +44,7 @@ void GBAAudioInit(struct GBAAudio* audio, size_t samples) { GBAudioInit(&audio->psg, 0, nr52, GB_AUDIO_GBA); audio->psg.timing = &audio->p->timing; audio->psg.clockRate = GBA_ARM7TDMI_FREQUENCY; + audio->psg.frameEvent.context = audio; audio->samples = samples; // Guess too large; we hang producing extra samples if we guess too low blip_set_rates(audio->psg.left, GBA_ARM7TDMI_FREQUENCY, 96000); @@ -58,6 +59,8 @@ void GBAAudioInit(struct GBAAudio* audio, size_t samples) { void GBAAudioReset(struct GBAAudio* audio) { GBAudioReset(&audio->psg); + mTimingDeschedule(&audio->p->timing, &audio->psg.frameEvent); + mTimingSchedule(&audio->p->timing, &audio->psg.frameEvent, 0); mTimingDeschedule(&audio->p->timing, &audio->sampleEvent); mTimingSchedule(&audio->p->timing, &audio->sampleEvent, 0); audio->chA.dmaSource = 1; @@ -77,11 +80,12 @@ void GBAAudioReset(struct GBAAudio* audio) { audio->chA.samples[i] = 0; audio->chB.samples[i] = 0; } - audio->sampleRate = 0x8000; audio->soundbias = 0x200; audio->volume = 0; audio->volumeChA = false; audio->volumeChB = false; + audio->lastSample = 0; + audio->sampleIndex = 0; audio->chARight = false; audio->chALeft = false; audio->chATimer = false; @@ -89,7 +93,7 @@ void GBAAudioReset(struct GBAAudio* audio) { audio->chBLeft = false; audio->chBTimer = false; audio->enable = false; - audio->sampleInterval = GBA_ARM7TDMI_FREQUENCY / audio->sampleRate; + audio->sampleInterval = GBA_ARM7TDMI_FREQUENCY / 0x8000; audio->psg.sampleInterval = audio->sampleInterval; blip_clear(audio->psg.left); @@ -141,56 +145,67 @@ void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* } void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) { + GBAAudioSample(audio, mTimingCurrentTime(&audio->p->timing)); GBAudioWriteNR10(&audio->psg, value); } void GBAAudioWriteSOUND1CNT_HI(struct GBAAudio* audio, uint16_t value) { + GBAAudioSample(audio, mTimingCurrentTime(&audio->p->timing)); GBAudioWriteNR11(&audio->psg, value); GBAudioWriteNR12(&audio->psg, value >> 8); } void GBAAudioWriteSOUND1CNT_X(struct GBAAudio* audio, uint16_t value) { + GBAAudioSample(audio, mTimingCurrentTime(&audio->p->timing)); GBAudioWriteNR13(&audio->psg, value); GBAudioWriteNR14(&audio->psg, value >> 8); } void GBAAudioWriteSOUND2CNT_LO(struct GBAAudio* audio, uint16_t value) { + GBAAudioSample(audio, mTimingCurrentTime(&audio->p->timing)); GBAudioWriteNR21(&audio->psg, value); GBAudioWriteNR22(&audio->psg, value >> 8); } void GBAAudioWriteSOUND2CNT_HI(struct GBAAudio* audio, uint16_t value) { + GBAAudioSample(audio, mTimingCurrentTime(&audio->p->timing)); GBAudioWriteNR23(&audio->psg, value); GBAudioWriteNR24(&audio->psg, value >> 8); } void GBAAudioWriteSOUND3CNT_LO(struct GBAAudio* audio, uint16_t value) { + GBAAudioSample(audio, mTimingCurrentTime(&audio->p->timing)); audio->psg.ch3.size = GBAudioRegisterBankGetSize(value); audio->psg.ch3.bank = GBAudioRegisterBankGetBank(value); GBAudioWriteNR30(&audio->psg, value); } void GBAAudioWriteSOUND3CNT_HI(struct GBAAudio* audio, uint16_t value) { + GBAAudioSample(audio, mTimingCurrentTime(&audio->p->timing)); GBAudioWriteNR31(&audio->psg, value); audio->psg.ch3.volume = GBAudioRegisterBankVolumeGetVolumeGBA(value >> 8); } void GBAAudioWriteSOUND3CNT_X(struct GBAAudio* audio, uint16_t value) { + GBAAudioSample(audio, mTimingCurrentTime(&audio->p->timing)); GBAudioWriteNR33(&audio->psg, value); GBAudioWriteNR34(&audio->psg, value >> 8); } void GBAAudioWriteSOUND4CNT_LO(struct GBAAudio* audio, uint16_t value) { + GBAAudioSample(audio, mTimingCurrentTime(&audio->p->timing)); GBAudioWriteNR41(&audio->psg, value); GBAudioWriteNR42(&audio->psg, value >> 8); } void GBAAudioWriteSOUND4CNT_HI(struct GBAAudio* audio, uint16_t value) { + GBAAudioSample(audio, mTimingCurrentTime(&audio->p->timing)); GBAudioWriteNR43(&audio->psg, value); GBAudioWriteNR44(&audio->psg, value >> 8); } void GBAAudioWriteSOUNDCNT_LO(struct GBAAudio* audio, uint16_t value) { + GBAAudioSample(audio, mTimingCurrentTime(&audio->p->timing)); GBAudioWriteNR50(&audio->psg, value); GBAudioWriteNR51(&audio->psg, value >> 8); } @@ -328,17 +343,17 @@ static int _applyBias(struct GBAAudio* audio, int sample) { return ((sample - GBARegisterSOUNDBIASGetBias(audio->soundbias)) * audio->masterVolume * 3) >> 4; } -static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { - struct GBAAudio* audio = user; - int16_t samplesLeft[GBA_MAX_SAMPLES]; - int16_t samplesRight[GBA_MAX_SAMPLES]; - int32_t timestamp = mTimingCurrentTime(&audio->p->timing) - cyclesLate - SAMPLE_INTERVAL; +void GBAAudioSample(struct GBAAudio* audio, int32_t timestamp) { + timestamp -= audio->lastSample; + timestamp -= audio->sampleIndex * audio->sampleInterval; // TODO: This can break if the interval changes between samples + + int maxSample = 2 << GBARegisterSOUNDBIASGetResolution(audio->soundbias); int sample; - for (sample = 0; sample * audio->sampleInterval < (int32_t) SAMPLE_INTERVAL; ++sample) { + for (sample = audio->sampleIndex; timestamp >= audio->sampleInterval && sample < maxSample; ++sample, timestamp -= audio->sampleInterval) { int16_t sampleLeft = 0; int16_t sampleRight = 0; int psgShift = 4 - audio->volume; - GBAudioRun(&audio->psg, timestamp + (sample + 1) * audio->sampleInterval, 0xF); + GBAudioRun(&audio->psg, sample * audio->sampleInterval + audio->lastSample, 0xF); GBAudioSamplePSG(&audio->psg, &sampleLeft, &sampleRight); sampleLeft >>= psgShift; sampleRight >>= psgShift; @@ -370,21 +385,34 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { sampleLeft = _applyBias(audio, sampleLeft); sampleRight = _applyBias(audio, sampleRight); - samplesLeft[sample] = sampleLeft; - samplesRight[sample] = sampleRight; + audio->currentSamples[sample].left = sampleLeft; + audio->currentSamples[sample].right = sampleRight; } - memset(audio->chA.samples, audio->chA.samples[sample - 1], sizeof(audio->chA.samples)); - memset(audio->chB.samples, audio->chB.samples[sample - 1], sizeof(audio->chB.samples)); + audio->sampleIndex = sample; + if (sample == maxSample) { + audio->lastSample += SAMPLE_INTERVAL; + audio->sampleIndex = 0; + } +} + +static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { + struct GBAAudio* audio = user; + GBAAudioSample(audio, mTimingCurrentTime(&audio->p->timing) - cyclesLate); + + int samples = 2 << GBARegisterSOUNDBIASGetResolution(audio->soundbias); + int sampleMask = 1 << GBARegisterSOUNDBIASGetResolution(audio->soundbias); + memset(audio->chA.samples, audio->chA.samples[samples - 1], sizeof(audio->chA.samples)); + memset(audio->chB.samples, audio->chB.samples[samples - 1], sizeof(audio->chB.samples)); mCoreSyncLockAudio(audio->p->sync); unsigned produced; int32_t sampleSumLeft = 0; int32_t sampleSumRight = 0; int i; - for (i = 0; i < sample; ++i) { - int16_t sampleLeft = samplesLeft[i]; - int16_t sampleRight = samplesRight[i]; + for (i = 0; i < samples; ++i) { + int16_t sampleLeft = audio->currentSamples[i].left; + int16_t sampleRight = audio->currentSamples[i].right; sampleSumLeft += sampleLeft; sampleSumRight += sampleRight; if ((size_t) blip_samples_avail(audio->psg.left) < audio->samples) { @@ -399,12 +427,14 @@ static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) { audio->clock -= CLOCKS_PER_FRAME; } } - } - // TODO: Post all frames - if (audio->p->stream && audio->p->stream->postAudioFrame) { - sampleSumLeft /= sample; - sampleSumRight /= sample; - audio->p->stream->postAudioFrame(audio->p->stream, sampleSumLeft, sampleSumRight); + // TODO: Post all frames + if (audio->p->stream && audio->p->stream->postAudioFrame && (i & (sampleMask - 1)) == sampleMask - 1) { + sampleSumLeft /= sampleMask; + sampleSumRight /= sampleMask; + audio->p->stream->postAudioFrame(audio->p->stream, sampleSumLeft, sampleSumRight); + sampleSumLeft = 0; + sampleSumRight = 0; + } } produced = blip_samples_avail(audio->psg.left); bool wait = produced >= audio->samples; @@ -428,9 +458,15 @@ void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* memcpy(state->samples.chA, audio->chA.samples, sizeof(audio->chA.samples)); memcpy(state->samples.chB, audio->chB.samples, sizeof(audio->chB.samples)); + size_t i; + for (i = 0; i < GBA_MAX_SAMPLES; ++i) { + STORE_16(audio->currentSamples[i].left, 0, &state->currentSamples[i].left); + STORE_16(audio->currentSamples[i].right, 0, &state->currentSamples[i].right); + } + STORE_32(audio->lastSample, 0, &state->audio.lastSample); + int readA = audio->chA.fifoRead; int readB = audio->chB.fifoRead; - size_t i; for (i = 0; i < GBA_AUDIO_FIFO_SIZE; ++i) { STORE_32(audio->chA.fifo[readA], i << 2, state->audio.fifoA); STORE_32(audio->chB.fifo[readB], i << 2, state->audio.fifoB); @@ -464,6 +500,11 @@ void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* flags = GBASerializedAudioFlagsSetFIFOInternalSamplesA(flags, audio->chA.internalRemaining); flags = GBASerializedAudioFlagsSetFIFOInternalSamplesB(flags, audio->chB.internalRemaining); STORE_16(flags, 0, &state->audio.gbaFlags); + + GBASerializedAudioFlags2 flags2 = 0; + flags2 = GBASerializedAudioFlags2SetSampleIndex(flags2, audio->sampleIndex); + STORE_32(flags2, 0, &state->audio.gbaFlags2); + STORE_32(audio->sampleEvent.when - mTimingCurrentTime(&audio->p->timing), 0, &state->audio.nextSample); } @@ -475,9 +516,15 @@ void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState memcpy(audio->chA.samples, state->samples.chA, sizeof(audio->chA.samples)); memcpy(audio->chB.samples, state->samples.chB, sizeof(audio->chB.samples)); + size_t i; + for (i = 0; i < GBA_MAX_SAMPLES; ++i) { + LOAD_16(audio->currentSamples[i].left, 0, &state->currentSamples[i].left); + LOAD_16(audio->currentSamples[i].right, 0, &state->currentSamples[i].right); + } + LOAD_32(audio->lastSample, 0, &state->audio.lastSample); + int readA = 0; int readB = 0; - size_t i; for (i = 0; i < GBA_AUDIO_FIFO_SIZE; ++i) { LOAD_32(audio->chA.fifo[readA], i << 2, state->audio.fifoA); LOAD_32(audio->chB.fifo[readB], i << 2, state->audio.fifoB); @@ -494,8 +541,15 @@ void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState audio->chA.internalRemaining = GBASerializedAudioFlagsGetFIFOInternalSamplesA(flags); audio->chB.internalRemaining = GBASerializedAudioFlagsGetFIFOInternalSamplesB(flags); + GBASerializedAudioFlags2 flags2; + LOAD_32(flags2, 0, &state->audio.gbaFlags2); + audio->sampleIndex = GBASerializedAudioFlags2GetSampleIndex(flags2); + uint32_t when; LOAD_32(when, 0, &state->audio.nextSample); + if (state->versionMagic < 0x01000007) { + audio->lastSample = when - SAMPLE_INTERVAL; + } mTimingSchedule(&audio->p->timing, &audio->sampleEvent, when); } diff --git a/src/gba/serialize.c b/src/gba/serialize.c index 9c5416e72..c64d7c22b 100644 --- a/src/gba/serialize.c +++ b/src/gba/serialize.c @@ -15,7 +15,7 @@ #include MGBA_EXPORT const uint32_t GBASavestateMagic = 0x01000000; -MGBA_EXPORT const uint32_t GBASavestateVersion = 0x00000006; +MGBA_EXPORT const uint32_t GBASavestateVersion = 0x00000007; mLOG_DEFINE_CATEGORY(GBA_STATE, "GBA Savestate", "gba.serialize"); diff --git a/src/gba/video.c b/src/gba/video.c index 659313575..7268f19de 100644 --- a/src/gba/video.c +++ b/src/gba/video.c @@ -377,7 +377,12 @@ void GBAVideoDeserialize(struct GBAVideo* video, const struct GBASerializedState break; } uint32_t when; - LOAD_32(when, 0, &state->video.nextEvent); + if (state->versionMagic < 0x01000007) { + // This field was moved in v7 + LOAD_32(when, 0, &state->audio.lastSample); + } else { + LOAD_32(when, 0, &state->video.nextEvent); + } mTimingSchedule(&video->p->timing, &video->event, when); LOAD_16(video->vcount, REG_VCOUNT, state->io); From fa910fc629751da9c990c8d5fb34405a0e459068 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 15 Jun 2022 23:31:20 -0700 Subject: [PATCH 063/102] Mac: Start bringing up Universal build support --- src/platform/qt/CMakeLists.txt | 5 ++++- src/platform/sdl/CMakeLists.txt | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 9ad0d27f1..57fda3249 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -401,7 +401,10 @@ if(QT_STATIC) find_package(Cups) find_package(${QT}PrintSupport) list(APPEND QT_LIBRARIES Cups ${QT}::PrintSupport ${QT}::QCocoaIntegrationPlugin ${QT}::CoreAudioPlugin ${QT}::AVFServicePlugin ${QT}::QCocoaPrinterSupportPlugin) - list(APPEND QT_LIBRARIES ${QT}AccessibilitySupport ${QT}CglSupport ${QT}ClipboardSupport ${QT}FontDatabaseSupport ${QT}GraphicsSupport ${QT}ThemeSupport) + list(APPEND QT_LIBRARIES ${QT}AccessibilitySupport ${QT}ClipboardSupport ${QT}FontDatabaseSupport ${QT}GraphicsSupport ${QT}ThemeSupport) + if(CMAKE_SYSTEM_VERSION VERSION_LESS "19.0") + list(APPEND QT_LIBRARIES ${QT}CglSupport) + endif() list(APPEND QT_LIBRARIES "-framework AVFoundation" "-framework CoreMedia" "-framework SystemConfiguration" "-framework Security") set_target_properties(${QT}::Core PROPERTIES INTERFACE_LINK_LIBRARIES "${QTPCRE}") elseif(UNIX) diff --git a/src/platform/sdl/CMakeLists.txt b/src/platform/sdl/CMakeLists.txt index 47f05cc4d..cacf0bc48 100644 --- a/src/platform/sdl/CMakeLists.txt +++ b/src/platform/sdl/CMakeLists.txt @@ -56,6 +56,9 @@ elseif(APPLE) if(NOT CMAKE_SYSTEM_VERSION VERSION_LESS "17.0") # Darwin 17.x is macOS 10.13 list(APPEND SDL_LIBRARY "-framework Metal") endif() + if(NOT CMAKE_SYSTEM_VERSION VERSION_LESS "19.0") # Darwin 19.x is macOS 10.15 + list(APPEND SDL_LIBRARY "-framework GameController" "-framework CoreHaptics") + endif() endif() if(NOT SDLMAIN_LIBRARY) From 07221181ea8c47989efcc6eb3dfafff2b9ffb9c2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 16 Jun 2022 15:38:38 -0700 Subject: [PATCH 064/102] Qt: Fix VAO reinitialization --- src/platform/qt/DisplayGL.cpp | 7 +++++++ src/platform/qt/DisplayGL.h | 1 + 2 files changed, 8 insertions(+) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 4691726bc..27183899d 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -82,6 +82,8 @@ void mGLWidget::initializeGL() { m_program->setUniformValue("tex", 0); m_positionLocation = m_program->attributeLocation("position"); + m_vaoDone = false; + connect(&m_refresh, &QTimer::timeout, this, static_cast(&QWidget::update)); } @@ -98,6 +100,10 @@ void mGLWidget::finalizeVAO() { } } +void mGLWidget::reset() { + m_vaoDone = false; +} + void mGLWidget::paintGL() { if (!m_vaoDone) { finalizeVAO(); @@ -210,6 +216,7 @@ void DisplayGL::startDrawing(std::shared_ptr controller) { } } else { show(); + m_gl->reset(); } } diff --git a/src/platform/qt/DisplayGL.h b/src/platform/qt/DisplayGL.h index a75f1a8dd..007cf6165 100644 --- a/src/platform/qt/DisplayGL.h +++ b/src/platform/qt/DisplayGL.h @@ -53,6 +53,7 @@ public: void setTex(GLuint tex) { m_tex = tex; } void setVBO(GLuint vbo) { m_vbo = vbo; } void finalizeVAO(); + void reset(); protected: void initializeGL() override; From ddccbee47b393bf2a99a6307f9c22aecfc04c9f4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 16 Jun 2022 15:41:28 -0700 Subject: [PATCH 065/102] Qt: Show correct channel for modern macOS builds --- src/platform/qt/ApplicationUpdater.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/platform/qt/ApplicationUpdater.cpp b/src/platform/qt/ApplicationUpdater.cpp index c59413c26..ce752ecce 100644 --- a/src/platform/qt/ApplicationUpdater.cpp +++ b/src/platform/qt/ApplicationUpdater.cpp @@ -150,7 +150,13 @@ const char* ApplicationUpdater::platform() { return uninstallInfo.exists() ? "win32-installer" : "win32"; #endif #elif defined(Q_OS_MACOS) +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + // Modern macOS build + return "macos"; +#else + // Legacy "OS X" build return "osx"; +#endif #elif defined(Q_OS_LINUX) && defined(__x86_64__) return "appimage-x64"; #else From a60bc18ad02fda3bb08729c1f5fb682680c09a0b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 16 Jun 2022 16:04:12 -0700 Subject: [PATCH 066/102] CMake: Cleanup and enhance FindFeature, fix static libedit --- CMakeLists.txt | 6 +- src/platform/cmake/FindFeature.cmake | 94 +++++++++++++--------------- 2 files changed, 48 insertions(+), 52 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f411449ae..fce26578a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -501,7 +501,11 @@ if(USE_EDITLINE) list(APPEND FEATURES EDITLINE) include_directories(AFTER ${LIBEDIT_INCLUDE_DIRS}) link_directories(${LIBEDIT_LIBRARY_DIRS}) - set(DEBUGGER_LIB ${LIBEDIT_LIBRARIES}) + if(BUILD_STATIC) + set(DEBUGGER_LIB ${LIBEDIT_STATIC_LIBRARIES}) + else() + set(DEBUGGER_LIB ${LIBEDIT_LIBRARIES}) + endif() set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libedit2") list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/editline/cli-el-backend.c") else() diff --git a/src/platform/cmake/FindFeature.cmake b/src/platform/cmake/FindFeature.cmake index afb2393dd..93aefa2fe 100644 --- a/src/platform/cmake/FindFeature.cmake +++ b/src/platform/cmake/FindFeature.cmake @@ -1,4 +1,34 @@ include(FindPkgConfig) +macro(_export SUFFIX) + if(DEFINED ${REQUIRE}_${SUFFIX}) + set(${UREQUIRE}_${SUFFIX} ${${REQUIRE}_${SUFFIX}} PARENT_SCOPE) + elseif(DEFINED ${UREQUIRE}_${SUFFIX}) + set(${UREQUIRE}_${SUFFIX} ${${UREQUIRE}_${SUFFIX}} PARENT_SCOPE) + endif() +endmacro() + +macro(_exportLibraries SUFFIX) + set(IS_FRAMEWORK OFF) + set(LIBS) + if(DEFINED ${REQUIRE}_${SUFFIX}) + set(PREFIX ${REQUIRE}) + elseif(DEFINED ${UREQUIRE}_${SUFFIX}) + set(PREFIX ${UREQUIRE}) + endif() + foreach(LIB IN LISTS ${PREFIX}_${SUFFIX}) + if(LIB STREQUAL "-framework") + set(IS_FRAMEWORK ON) + elseif(IS_FRAMEWORK) + list(APPEND LIBS "-framework ${LIB}") + set(IS_FRAMEWORK OFF) + else() + list(APPEND LIBS ${LIB}) + endif() + endforeach() + unset(PREFIX) + set(${UREQUIRE}_${SUFFIX} ${LIBS} PARENT_SCOPE) +endmacro() + function(find_feature FEATURE_NAME FEATURE_REQUIRES) if (NOT ${FEATURE_NAME}) return() @@ -28,60 +58,22 @@ function(find_feature FEATURE_NAME FEATURE_REQUIRES) endif() if(${REQUIRE}_FOUND) string(TOUPPER ${REQUIRE} UREQUIRE) - if(DEFINED ${REQUIRE}_CFLAGS_OTHER) - set(${UREQUIRE}_CFLAGS_OTHER ${${REQUIRE}_CFLAGS_OTHER} PARENT_SCOPE) - elseif(DEFINED ${UREQUIRE}_CFLAGS_OTHER) - set(${UREQUIRE}_CFLAGS_OTHER ${${UREQUIRE}_CFLAGS_OTHER} PARENT_SCOPE) - endif() - if(DEFINED ${REQUIRE}_FOUND) - set(${UREQUIRE}_FOUND ${${REQUIRE}_FOUND} PARENT_SCOPE) - elseif(DEFINED ${UREQUIRE}_FOUND) - set(${UREQUIRE}_FOUND ${${UREQUIRE}_FOUND} PARENT_SCOPE) - endif() - if(DEFINED ${REQUIRE}_INCLUDE_DIRS) - set(${UREQUIRE}_INCLUDE_DIRS ${${REQUIRE}_INCLUDE_DIRS} PARENT_SCOPE) - elseif(DEFINED ${UREQUIRE}_INCLUDE_DIRS) - set(${UREQUIRE}_INCLUDE_DIRS ${${UREQUIRE}_INCLUDE_DIRS} PARENT_SCOPE) - endif() - if(DEFINED ${REQUIRE}_INCLUDE_DIR) - set(${UREQUIRE}_INCLUDE_DIR ${${REQUIRE}_INCLUDE_DIR} PARENT_SCOPE) - elseif(DEFINED ${UREQUIRE}_INCLUDE_DIR) - set(${UREQUIRE}_INCLUDE_DIR ${${UREQUIRE}_INCLUDE_DIR} PARENT_SCOPE) - endif() - if(DEFINED ${REQUIRE}_VERSION_STRING) - set(${UREQUIRE}_VERSION_STRING ${${REQUIRE}_VERSION_STRING} PARENT_SCOPE) - elseif(DEFINED ${UREQUIRE}_VERSION_STRING) - set(${UREQUIRE}_VERSION_STRING ${${UREQUIRE}_VERSION_STRING} PARENT_SCOPE) - endif() - if(DEFINED ${REQUIRE}_VERSION_MAJOR) - set(${UREQUIRE}_VERSION_MAJOR ${${REQUIRE}_VERSION_MAJOR} PARENT_SCOPE) - elseif(DEFINED ${UREQUIRE}_VERSION_MAJOR) - set(${UREQUIRE}_VERSION_MAJOR ${${UREQUIRE}_VERSION_MAJOR} PARENT_SCOPE) - endif() - if(DEFINED ${REQUIRE}_VERSION_MINOR) - set(${UREQUIRE}_VERSION_MINOR ${${REQUIRE}_VERSION_MINOR} PARENT_SCOPE) - elseif(DEFINED ${UREQUIRE}_VERSION_MINOR) - set(${UREQUIRE}_VERSION_MINOR ${${UREQUIRE}_VERSION_MINOR} PARENT_SCOPE) - endif() + _export(CFLAGS_OTHER) + _export(FOUND) + _export(INCLUDE_DIRS) + _export(INCLUDE_DIR) + _export(VERSION_STRING) + _export(VERSION_MAJOR) + _export(VERSION_MINOR) if (APPLE) - set(IS_FRAMEWORK OFF) - set(LIBS) - foreach(LIB IN LISTS ${REQUIRE}_LIBRARIES) - if(LIB STREQUAL "-framework") - set(IS_FRAMEWORK ON) - elseif(IS_FRAMEWORK) - list(APPEND LIBS "-framework ${LIB}") - set(IS_FRAMEWORK OFF) - else() - list(APPEND LIBS ${LIB}) - endif() - endforeach() - set(${UREQUIRE}_LIBRARIES ${LIBS} PARENT_SCOPE) + _exportLibraries(LIBRARIES) + _exportLibraries(STATIC_LIBRARIES) else() - set(${UREQUIRE}_LIBRARIES ${${REQUIRE}_LIBRARIES} PARENT_SCOPE) + _export(LIBRARIES) + _export(STATIC_LIBRARIES) endif() - set(${UREQUIRE}_LIBRARY_DIRS ${${REQUIRE}_LIBRARY_DIRS} PARENT_SCOPE) - set(${UREQUIRE}_LDFLAGS_OTHER ${${REQUIRE}_LDFLAGS_OTHER} PARENT_SCOPE) + _export(LIBRARY_DIRS) + _export(LDFLAGS_OTHER) set(FOUND ON) break() endif() From 485110902759a8fad56d334a08c3b862e8a05294 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 16 Jun 2022 21:57:45 -0700 Subject: [PATCH 067/102] Core: Add wallclock offset RTC type --- CHANGES | 1 + include/mgba/core/interface.h | 1 + src/core/interface.c | 3 ++ src/platform/qt/CoreController.cpp | 5 ++ src/platform/qt/CoreController.h | 1 + src/platform/qt/SensorView.cpp | 8 ++++ src/platform/qt/SensorView.ui | 75 +++++++++++++++++++++--------- 7 files changed, 71 insertions(+), 23 deletions(-) diff --git a/CHANGES b/CHANGES index 891e2ca6f..aed3e0c11 100644 --- a/CHANGES +++ b/CHANGES @@ -64,6 +64,7 @@ Other fixes: - VFS: Failed file mapping should return NULL on POSIX Misc: - Core: Suspend runloop when a core crashes + - Core: Add wallclock offset RTC type - Debugger: Save and restore CLI history - Debugger: GDB now works while the game is paused - Debugger: Add command to load external symbol file (fixes mgba.io/i/2480) diff --git a/include/mgba/core/interface.h b/include/mgba/core/interface.h index fadaaa29d..e2625045f 100644 --- a/include/mgba/core/interface.h +++ b/include/mgba/core/interface.h @@ -239,6 +239,7 @@ enum mRTCGenericType { RTC_NO_OVERRIDE, RTC_FIXED, RTC_FAKE_EPOCH, + RTC_WALLCLOCK_OFFSET, RTC_CUSTOM_START = 0x1000 }; diff --git a/src/core/interface.c b/src/core/interface.c index 961b83619..d63754895 100644 --- a/src/core/interface.c +++ b/src/core/interface.c @@ -21,6 +21,7 @@ static void _rtcGenericSample(struct mRTCSource* source) { case RTC_NO_OVERRIDE: case RTC_FIXED: case RTC_FAKE_EPOCH: + case RTC_WALLCLOCK_OFFSET: break; } } @@ -39,6 +40,8 @@ static time_t _rtcGenericCallback(struct mRTCSource* source) { return rtc->value / 1000LL; case RTC_FAKE_EPOCH: return (rtc->value + rtc->p->frameCounter(rtc->p) * (rtc->p->frameCycles(rtc->p) * 1000LL) / rtc->p->frequency(rtc->p)) / 1000LL; + case RTC_WALLCLOCK_OFFSET: + return time(0) + rtc->value / 1000LL; } } diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index ec0edea11..8814f4443 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -898,6 +898,11 @@ void CoreController::setFakeEpoch(const QDateTime& time) { m_threadContext.core->rtc.value = time.toMSecsSinceEpoch(); } +void CoreController::setTimeOffset(qint64 offset) { + m_threadContext.core->rtc.override = RTC_WALLCLOCK_OFFSET; + m_threadContext.core->rtc.value = offset * 1000LL; +} + void CoreController::scanCard(const QString& path) { #ifdef M_CORE_GBA QImage image(path); diff --git a/src/platform/qt/CoreController.h b/src/platform/qt/CoreController.h index 663d0ed96..3e5ca6b4d 100644 --- a/src/platform/qt/CoreController.h +++ b/src/platform/qt/CoreController.h @@ -174,6 +174,7 @@ public slots: void setRealTime(); void setFixedTime(const QDateTime& time); void setFakeEpoch(const QDateTime& time); + void setTimeOffset(qint64 offset); void importSharkport(const QString& path); void exportSharkport(const QString& path); diff --git a/src/platform/qt/SensorView.cpp b/src/platform/qt/SensorView.cpp index 1742a26ee..22c2f5f3f 100644 --- a/src/platform/qt/SensorView.cpp +++ b/src/platform/qt/SensorView.cpp @@ -69,6 +69,14 @@ void SensorView::setController(std::shared_ptr controller) { connect(m_ui.timeFakeEpoch, &QRadioButton::clicked, [controller, this] () { controller->setFakeEpoch(m_ui.time->dateTime().toUTC()); }); + connect(m_ui.timeOffset, &QRadioButton::clicked, [controller, this] () { + controller->setTimeOffset(m_ui.offsetSeconds->value()); + }); + connect(m_ui.offsetSeconds, qOverload(&QSpinBox::valueChanged), [controller, this] (int value) { + if (m_ui.timeOffset->isChecked()) { + controller->setTimeOffset(value); + } + }); m_ui.timeButtons->checkedButton()->clicked(); connect(controller.get(), &CoreController::stopping, [this]() { diff --git a/src/platform/qt/SensorView.ui b/src/platform/qt/SensorView.ui index 7d65ba52c..ac7032e4d 100644 --- a/src/platform/qt/SensorView.ui +++ b/src/platform/qt/SensorView.ui @@ -6,8 +6,8 @@ 0 0 - 434 - 319 + 448 + 332 @@ -19,28 +19,18 @@ Sensors - + QLayout::SetFixedSize - + Realtime clock - - - - Fixed time - - - timeButtons - - - @@ -54,7 +44,53 @@ + + + + Fixed time + + + timeButtons + + + + + + + Now + + + + + + Offset time + + + timeButtons + + + + + + + sec + + + -99999999 + + + 99999999 + + + 1 + + + QAbstractSpinBox::AdaptiveDecimalStepType + + + + Start time at @@ -64,14 +100,7 @@ - - - - Now - - - - + true @@ -143,7 +172,7 @@ - + From 0b2cfb505f5ca3b1403e9ab36475d7257d0d155b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 16 Jun 2022 22:01:03 -0700 Subject: [PATCH 068/102] Qt: Fix build on older Qt --- src/platform/qt/SensorView.ui | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform/qt/SensorView.ui b/src/platform/qt/SensorView.ui index ac7032e4d..e490fd03c 100644 --- a/src/platform/qt/SensorView.ui +++ b/src/platform/qt/SensorView.ui @@ -73,6 +73,9 @@ + + true + sec @@ -85,9 +88,6 @@ 1 - - QAbstractSpinBox::AdaptiveDecimalStepType - From 840e2806b57ced7ffbad40b334bab226de574a67 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 16 Jun 2022 23:40:11 -0700 Subject: [PATCH 069/102] Scripting: Basic void type bringup --- include/mgba/script/types.h | 2 ++ src/script/engines/lua.c | 6 ++++++ src/script/types.c | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/include/mgba/script/types.h b/include/mgba/script/types.h index 471d78524..7acb0c365 100644 --- a/include/mgba/script/types.h +++ b/include/mgba/script/types.h @@ -174,6 +174,8 @@ extern const struct mScriptType mSTWeakref; extern const struct mScriptType mSTStringWrapper; extern const struct mScriptType mSTListWrapper; +extern struct mScriptValue mScriptValueNull; + struct mScriptType; struct mScriptValue { const struct mScriptType* type; diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index f5adfcdd5..24ceefec8 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -320,6 +320,9 @@ struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext, bool const void* buffer; struct mScriptValue* value = NULL; switch (lua_type(luaContext->lua, -1)) { + case LUA_TNIL: + value = &mScriptValueNull; + break; case LUA_TNUMBER: #if LUA_VERSION_NUM >= 503 if (lua_isinteger(luaContext->lua, -1)) { @@ -398,6 +401,9 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v bool ok = true; struct mScriptValue* newValue; switch (value->type->base) { + case mSCRIPT_TYPE_VOID: + lua_pushnil(luaContext->lua); + break; case mSCRIPT_TYPE_SINT: if (value->type->size <= 4) { lua_pushinteger(luaContext->lua, value->value.s32); diff --git a/src/script/types.c b/src/script/types.c index 52d0425b6..ae1108ae1 100644 --- a/src/script/types.c +++ b/src/script/types.c @@ -239,6 +239,11 @@ const struct mScriptType mSTWeakref = { .hash = NULL, }; +struct mScriptValue mScriptValueNull = { + .type = &mSTVoid, + .refs = mSCRIPT_VALUE_UNREF +}; + DEFINE_VECTOR(mScriptList, struct mScriptValue) void _allocList(struct mScriptValue* val) { From 79506cef72304377199dde9ca42ad60a94b28621 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 16 Jun 2022 23:40:37 -0700 Subject: [PATCH 070/102] Scripting: Fix elision of MemoryDomain documentation --- src/script/docgen.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/script/docgen.c b/src/script/docgen.c index 519b73bb2..ecf19a354 100644 --- a/src/script/docgen.c +++ b/src/script/docgen.c @@ -391,6 +391,7 @@ void explainCore(struct mCore* core) { fprintf(out, " %s:\n", name->value.string->buffer); value = mScriptContextAccessWeakref(&context, value); + addType(value->type); struct mScriptFrame frame; uint32_t baseVal; From 0dce8b392a56f70f41196038371e2506724aead4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 16 Jun 2022 23:45:20 -0700 Subject: [PATCH 071/102] Scripting: Fix test fallout --- src/script/test/lua.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/script/test/lua.c b/src/script/test/lua.c index bf3bf099a..7790fed60 100644 --- a/src/script/test/lua.c +++ b/src/script/test/lua.c @@ -254,7 +254,7 @@ M_TEST_DEFINE(setGlobal) { assert_true(lua->setGlobal(lua, "b", NULL)); val = lua->getGlobal(lua, "b"); - assert_null(val); + assert_ptr_equal(val, &mScriptValueNull); mScriptContextDeinit(&context); } From 8d7c040b467fb53c2f0ea4b084767c1335919872 Mon Sep 17 00:00:00 2001 From: ahigerd Date: Tue, 21 Jun 2022 00:48:55 -0500 Subject: [PATCH 072/102] Don't crash when resetting scripting UI (#2564) --- src/platform/qt/ScriptingView.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/platform/qt/ScriptingView.cpp b/src/platform/qt/ScriptingView.cpp index 1252f285c..f568fa6c1 100644 --- a/src/platform/qt/ScriptingView.cpp +++ b/src/platform/qt/ScriptingView.cpp @@ -66,14 +66,19 @@ void ScriptingView::addTextBuffer(ScriptingTextBuffer* buffer) { }); connect(buffer, &QObject::destroyed, this, [this, buffer, item]() { m_textBuffers.removeAll(buffer); - m_ui.buffers->removeItemWidget(item); + delete item; }); m_ui.buffers->addItem(item); m_ui.buffers->setCurrentItem(item); } void ScriptingView::selectBuffer(int index) { - m_ui.buffer->setDocument(m_textBuffers[index]->document()); + if (index < 0 || index >= m_textBuffers.size()) { + // If the selected buffer is out of bounds, clear the document. + m_ui.buffer->setDocument(nullptr); + } else { + m_ui.buffer->setDocument(m_textBuffers[index]->document()); + } } QString ScriptingView::getFilters() const { From c1b1f72005f26c4aaca098c3cb8c860215895dc9 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 21 Jun 2022 16:17:32 -0700 Subject: [PATCH 073/102] Scripting: Fix crashes when functions return null --- src/core/scripting.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/scripting.c b/src/core/scripting.c index 7c14eb08b..480227b99 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -311,7 +311,7 @@ static struct mScriptValue* _mScriptCoreChecksum(const struct mCore* core, int t break; } if (!size) { - return NULL; + return &mScriptValueNull; } void* data = calloc(1, size); core->checksum(core, data, type); @@ -350,7 +350,7 @@ static struct mScriptValue* _mScriptCoreReadRange(struct mCore* core, uint32_t a static struct mScriptValue* _mScriptCoreReadRegister(const struct mCore* core, const char* regName) { int32_t out; if (!core->readRegister(core, regName, &out)) { - return NULL; + return &mScriptValueNull; } struct mScriptValue* value = mScriptValueAlloc(mSCRIPT_TYPE_MS_S32); value->value.s32 = out; @@ -365,7 +365,7 @@ static struct mScriptValue* _mScriptCoreSaveState(struct mCore* core, int32_t fl struct VFile* vf = VFileMemChunk(NULL, 0); if (!mCoreSaveStateNamed(core, vf, flags)) { vf->close(vf); - return NULL; + return &mScriptValueNull; } void* buffer = vf->map(vf, vf->size(vf), MAP_READ); struct mScriptValue* value = mScriptStringCreateFromBytes(buffer, vf->size(vf)); @@ -590,7 +590,7 @@ static struct mScriptValue* _mScriptCoreAdapterGet(struct mScriptCoreAdapter* ad struct mScriptValue val; struct mScriptValue core = mSCRIPT_MAKE(S(mCore), adapter->core); if (!mScriptObjectGet(&core, name, &val)) { - return NULL; + return &mScriptValueNull; } struct mScriptValue* ret = malloc(sizeof(*ret)); From 1bda318531dda1f659fb8e6c5cf32da07d41a697 Mon Sep 17 00:00:00 2001 From: ahigerd Date: Fri, 24 Jun 2022 01:15:35 -0500 Subject: [PATCH 074/102] Qt: Refactor the script buffer list into a model (#2566) --- src/platform/qt/CMakeLists.txt | 1 + src/platform/qt/ScriptingController.cpp | 19 ++--- src/platform/qt/ScriptingController.h | 7 +- src/platform/qt/ScriptingTextBuffer.h | 4 +- src/platform/qt/ScriptingTextBufferModel.cpp | 73 ++++++++++++++++++++ src/platform/qt/ScriptingTextBufferModel.h | 48 +++++++++++++ src/platform/qt/ScriptingView.cpp | 44 ++++++------ src/platform/qt/ScriptingView.h | 6 +- src/platform/qt/ScriptingView.ui | 2 +- 9 files changed, 160 insertions(+), 44 deletions(-) create mode 100644 src/platform/qt/ScriptingTextBufferModel.cpp create mode 100644 src/platform/qt/ScriptingTextBufferModel.h diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 57fda3249..9f0621931 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -252,6 +252,7 @@ if(ENABLE_SCRIPTING) list(APPEND SOURCE_FILES ScriptingController.cpp ScriptingTextBuffer.cpp + ScriptingTextBufferModel.cpp ScriptingView.cpp) list(APPEND UI_FILES diff --git a/src/platform/qt/ScriptingController.cpp b/src/platform/qt/ScriptingController.cpp index 033df225f..450c88842 100644 --- a/src/platform/qt/ScriptingController.cpp +++ b/src/platform/qt/ScriptingController.cpp @@ -7,6 +7,7 @@ #include "CoreController.h" #include "ScriptingTextBuffer.h" +#include "ScriptingTextBufferModel.h" using namespace QGBA; @@ -33,6 +34,9 @@ ScriptingController::ScriptingController(QObject* parent) } }; + m_bufferModel = new ScriptingTextBufferModel(this); + QObject::connect(m_bufferModel, &ScriptingTextBufferModel::textBufferCreated, this, &ScriptingController::textBufferCreated); + init(); } @@ -87,10 +91,7 @@ void ScriptingController::clearController() { void ScriptingController::reset() { CoreController::Interrupter interrupter(m_controller); - for (ScriptingTextBuffer* buffer : m_buffers) { - delete buffer; - } - m_buffers.clear(); + m_bufferModel->reset(); mScriptContextDetachCore(&m_scriptContext); mScriptContextDeinit(&m_scriptContext); m_engines.clear(); @@ -106,21 +107,13 @@ void ScriptingController::runCode(const QString& code) { load(vf, "*prompt"); } -mScriptTextBuffer* ScriptingController::createTextBuffer(void* context) { - ScriptingController* self = static_cast(context); - ScriptingTextBuffer* buffer = new ScriptingTextBuffer(self); - self->m_buffers.append(buffer); - emit self->textBufferCreated(buffer); - return buffer->textBuffer(); -} - void ScriptingController::init() { mScriptContextInit(&m_scriptContext); mScriptContextAttachStdlib(&m_scriptContext); mScriptContextRegisterEngines(&m_scriptContext); mScriptContextAttachLogger(&m_scriptContext, &m_logger); - mScriptContextSetTextBufferFactory(&m_scriptContext, &ScriptingController::createTextBuffer, this); + m_bufferModel->attachToContext(&m_scriptContext); HashTableEnumerate(&m_scriptContext.engines, [](const char* key, void* engine, void* context) { ScriptingController* self = static_cast(context); diff --git a/src/platform/qt/ScriptingController.h b/src/platform/qt/ScriptingController.h index 0981fcab2..03e40f7cf 100644 --- a/src/platform/qt/ScriptingController.h +++ b/src/platform/qt/ScriptingController.h @@ -15,10 +15,13 @@ #include +class QTextDocument; + namespace QGBA { class CoreController; class ScriptingTextBuffer; +class ScriptingTextBufferModel; class ScriptingController : public QObject { Q_OBJECT @@ -33,7 +36,7 @@ public: bool load(VFileDevice& vf, const QString& name); mScriptContext* context() { return &m_scriptContext; } - QList textBuffers() { return m_buffers; } + ScriptingTextBufferModel* textBufferModel() const { return m_bufferModel; } signals: void log(const QString&); @@ -59,7 +62,7 @@ private: mScriptEngineContext* m_activeEngine = nullptr; QHash m_engines; - QList m_buffers; + ScriptingTextBufferModel* m_bufferModel; std::shared_ptr m_controller; }; diff --git a/src/platform/qt/ScriptingTextBuffer.h b/src/platform/qt/ScriptingTextBuffer.h index c771003f2..e2bdb8f30 100644 --- a/src/platform/qt/ScriptingTextBuffer.h +++ b/src/platform/qt/ScriptingTextBuffer.h @@ -47,12 +47,12 @@ private: static void deinit(struct mScriptTextBuffer*); static void setName(struct mScriptTextBuffer*, const char* name); - + static uint32_t getX(const struct mScriptTextBuffer*); static uint32_t getY(const struct mScriptTextBuffer*); static uint32_t cols(const struct mScriptTextBuffer*); static uint32_t rows(const struct mScriptTextBuffer*); - + static void print(struct mScriptTextBuffer*, const char* text); static void clear(struct mScriptTextBuffer*); static void setSize(struct mScriptTextBuffer*, uint32_t cols, uint32_t rows); diff --git a/src/platform/qt/ScriptingTextBufferModel.cpp b/src/platform/qt/ScriptingTextBufferModel.cpp new file mode 100644 index 000000000..0d01b7581 --- /dev/null +++ b/src/platform/qt/ScriptingTextBufferModel.cpp @@ -0,0 +1,73 @@ +/* Copyright (c) 2013-2022 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "ScriptingTextBufferModel.h" + +#include "ScriptingTextBuffer.h" + +#include + +using namespace QGBA; + +ScriptingTextBufferModel::ScriptingTextBufferModel(QObject* parent) + : QAbstractListModel(parent) +{ + // initializers only +} + +void ScriptingTextBufferModel::attachToContext(mScriptContext* context) +{ + mScriptContextSetTextBufferFactory(context, &ScriptingTextBufferModel::createTextBuffer, this); +} + +void ScriptingTextBufferModel::reset() { + beginResetModel(); + QList toDelete = m_buffers; + m_buffers.clear(); + endResetModel(); + for (ScriptingTextBuffer* buffer : toDelete) { + delete buffer; + } +} + +mScriptTextBuffer* ScriptingTextBufferModel::createTextBuffer(void* context) { + ScriptingTextBufferModel* self = static_cast(context); + self->beginInsertRows(QModelIndex(), self->m_buffers.size(), self->m_buffers.size() + 1); + ScriptingTextBuffer* buffer = new ScriptingTextBuffer(self); + QObject::connect(buffer, &ScriptingTextBuffer::bufferNameChanged, self, &ScriptingTextBufferModel::bufferNameChanged); + self->m_buffers.append(buffer); + emit self->textBufferCreated(buffer); + self->endInsertRows(); + return buffer->textBuffer(); +} + +void ScriptingTextBufferModel::bufferNameChanged(const QString&) { + ScriptingTextBuffer* buffer = qobject_cast(sender()); + int row = m_buffers.indexOf(buffer); + if (row < 0) { + return; + } + QModelIndex idx = index(row, 0); + emit dataChanged(idx, idx, { Qt::DisplayRole }); +} + +int ScriptingTextBufferModel::rowCount(const QModelIndex& parent) const { + if (parent.isValid()) { + return 0; + } + return m_buffers.size(); +} + +QVariant ScriptingTextBufferModel::data(const QModelIndex& index, int role) const { + if (index.parent().isValid() || index.row() < 0 || index.row() >= m_buffers.size() || index.column() != 0) { + return QVariant(); + } + if (role == Qt::DisplayRole) { + return m_buffers[index.row()]->document()->metaInformation(QTextDocument::DocumentTitle); + } else if (role == ScriptingTextBufferModel::DocumentRole) { + return QVariant::fromValue(m_buffers[index.row()]->document()); + } + return QVariant(); +} diff --git a/src/platform/qt/ScriptingTextBufferModel.h b/src/platform/qt/ScriptingTextBufferModel.h new file mode 100644 index 000000000..79fee7c49 --- /dev/null +++ b/src/platform/qt/ScriptingTextBufferModel.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2013-2022 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#pragma once + +#include + +#include + +class mScriptTextBuffer; + +namespace QGBA { + +class ScriptingTextBuffer; + +class ScriptingTextBufferModel : public QAbstractListModel { +Q_OBJECT + +public: + enum ItemDataRole { + DocumentRole = Qt::UserRole + 1, + }; + + ScriptingTextBufferModel(QObject* parent = nullptr); + + void attachToContext(mScriptContext* context); + + int rowCount(const QModelIndex& parent = QModelIndex()) const; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; + +signals: + void textBufferCreated(ScriptingTextBuffer*); + +public slots: + void reset(); + +private slots: + void bufferNameChanged(const QString&); + +private: + static mScriptTextBuffer* createTextBuffer(void* context); + + QList m_buffers; +}; + +} diff --git a/src/platform/qt/ScriptingView.cpp b/src/platform/qt/ScriptingView.cpp index f568fa6c1..ccb7c9e20 100644 --- a/src/platform/qt/ScriptingView.cpp +++ b/src/platform/qt/ScriptingView.cpp @@ -9,6 +9,7 @@ #include "ConfigController.h" #include "ScriptingController.h" #include "ScriptingTextBuffer.h" +#include "ScriptingTextBufferModel.h" using namespace QGBA; @@ -19,26 +20,34 @@ ScriptingView::ScriptingView(ScriptingController* controller, ConfigController* { m_ui.setupUi(this); + ScriptingTextBufferModel* bufferModel = controller->textBufferModel(); m_ui.prompt->setFont(GBAApp::app()->monospaceFont()); m_ui.log->setNewlineTerminated(true); + m_ui.buffers->setModel(bufferModel); connect(m_ui.prompt, &QLineEdit::returnPressed, this, &ScriptingView::submitRepl); connect(m_ui.runButton, &QAbstractButton::clicked, this, &ScriptingView::submitRepl); + + connect(bufferModel, &QAbstractItemModel::modelAboutToBeReset, this, &ScriptingView::controllerReset); + connect(bufferModel, &QAbstractItemModel::rowsInserted, this, [this, bufferModel](const QModelIndex&, int row, int) { + m_ui.buffers->setCurrentIndex(bufferModel->index(row, 0)); + }); + connect(m_controller, &ScriptingController::log, m_ui.log, &LogWidget::log); connect(m_controller, &ScriptingController::warn, m_ui.log, &LogWidget::warn); connect(m_controller, &ScriptingController::error, m_ui.log, &LogWidget::error); - connect(m_controller, &ScriptingController::textBufferCreated, this, &ScriptingView::addTextBuffer); - connect(m_ui.buffers, &QListWidget::currentRowChanged, this, &ScriptingView::selectBuffer); + connect(m_ui.buffers->selectionModel(), &QItemSelectionModel::currentChanged, this, &ScriptingView::selectBuffer); connect(m_ui.load, &QAction::triggered, this, &ScriptingView::load); connect(m_ui.reset, &QAction::triggered, controller, &ScriptingController::reset); m_mruFiles = m_config->getMRU(ConfigController::MRU::Script); updateMRU(); - for (ScriptingTextBuffer* buffer : controller->textBuffers()) { - addTextBuffer(buffer); - } + m_blankDocument = new QTextDocument(this); + m_blankDocument->setDocumentLayout(new QPlainTextDocumentLayout(m_blankDocument)); + + m_ui.buffers->setCurrentIndex(bufferModel->index(0, 0)); } void ScriptingView::submitRepl() { @@ -57,27 +66,16 @@ void ScriptingView::load() { } } -void ScriptingView::addTextBuffer(ScriptingTextBuffer* buffer) { - QTextDocument* document = buffer->document(); - m_textBuffers.append(buffer); - QListWidgetItem* item = new QListWidgetItem(document->metaInformation(QTextDocument::DocumentTitle)); - connect(buffer, &ScriptingTextBuffer::bufferNameChanged, this, [item](const QString& name) { - item->setText(name); - }); - connect(buffer, &QObject::destroyed, this, [this, buffer, item]() { - m_textBuffers.removeAll(buffer); - delete item; - }); - m_ui.buffers->addItem(item); - m_ui.buffers->setCurrentItem(item); +void ScriptingView::controllerReset() { + selectBuffer(QModelIndex()); } -void ScriptingView::selectBuffer(int index) { - if (index < 0 || index >= m_textBuffers.size()) { - // If the selected buffer is out of bounds, clear the document. - m_ui.buffer->setDocument(nullptr); +void ScriptingView::selectBuffer(const QModelIndex& current, const QModelIndex&) { + if (current.isValid()) { + m_ui.buffer->setDocument(current.data(ScriptingTextBufferModel::DocumentRole).value()); } else { - m_ui.buffer->setDocument(m_textBuffers[index]->document()); + // If there is no selected buffer, use the blank document. + m_ui.buffer->setDocument(m_blankDocument); } } diff --git a/src/platform/qt/ScriptingView.h b/src/platform/qt/ScriptingView.h index d6fec7847..1f90a3f19 100644 --- a/src/platform/qt/ScriptingView.h +++ b/src/platform/qt/ScriptingView.h @@ -23,8 +23,8 @@ private slots: void submitRepl(); void load(); - void addTextBuffer(ScriptingTextBuffer*); - void selectBuffer(int); + void controllerReset(); + void selectBuffer(const QModelIndex& current, const QModelIndex& = QModelIndex()); private: QString getFilters() const; @@ -36,8 +36,8 @@ private: ConfigController* m_config; ScriptingController* m_controller; - QList m_textBuffers; QStringList m_mruFiles; + QTextDocument* m_blankDocument; }; } diff --git a/src/platform/qt/ScriptingView.ui b/src/platform/qt/ScriptingView.ui index 61afa257f..4e231f2fb 100644 --- a/src/platform/qt/ScriptingView.ui +++ b/src/platform/qt/ScriptingView.ui @@ -16,7 +16,7 @@ - + 0 From 1a61da9f836836b2dd9fa340fa5772ea374d63fc Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 24 Jun 2022 00:53:06 -0700 Subject: [PATCH 075/102] Qt: Fix warning --- src/platform/qt/ScriptingTextBufferModel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/ScriptingTextBufferModel.h b/src/platform/qt/ScriptingTextBufferModel.h index 79fee7c49..52b552049 100644 --- a/src/platform/qt/ScriptingTextBufferModel.h +++ b/src/platform/qt/ScriptingTextBufferModel.h @@ -9,7 +9,7 @@ #include -class mScriptTextBuffer; +struct mScriptTextBuffer; namespace QGBA { From b1f1da4f7dd623652b3db8744bcc443f0f266ff2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 24 Jun 2022 00:53:15 -0700 Subject: [PATCH 076/102] Core: Fix warning --- src/core/library.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/library.c b/src/core/library.c index 06bed44ee..d6cd99a0c 100644 --- a/src/core/library.c +++ b/src/core/library.c @@ -381,9 +381,12 @@ size_t mLibraryGetEntries(struct mLibrary* library, struct mLibraryListing* out, sqlite3_reset(library->select); _bindConstraints(library->select, constraints); + if (numEntries > SSIZE_MAX) { + numEntries = SSIZE_MAX; + } int countIndex = sqlite3_bind_parameter_index(library->select, ":count"); int offsetIndex = sqlite3_bind_parameter_index(library->select, ":offset"); - sqlite3_bind_int64(library->select, countIndex, numEntries ? numEntries : -1); + sqlite3_bind_int64(library->select, countIndex, numEntries ? (ssize_t) numEntries : -1); sqlite3_bind_int64(library->select, offsetIndex, offset); size_t entryIndex; From 5349cab4b258b636c1e2b988d9539243edccfc82 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 24 Jun 2022 01:55:52 -0700 Subject: [PATCH 077/102] Qt: Better error checking in mGLWidget --- src/platform/qt/DisplayGL.cpp | 13 ++++++++++--- src/platform/qt/DisplayGL.h | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 27183899d..21703dd5f 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -87,8 +87,14 @@ void mGLWidget::initializeGL() { connect(&m_refresh, &QTimer::timeout, this, static_cast(&QWidget::update)); } -void mGLWidget::finalizeVAO() { +bool mGLWidget::finalizeVAO() { + if (!context() || !m_vao) { + return false; + } QOpenGLFunctions_Baseline* fn = context()->versionFunctions(); + if (!fn) { + return false; + } fn->glGetError(); // Clear the error m_vao->bind(); fn->glBindBuffer(GL_ARRAY_BUFFER, m_vbo); @@ -98,6 +104,7 @@ void mGLWidget::finalizeVAO() { if (fn->glGetError() == GL_NO_ERROR) { m_vaoDone = true; } + return m_vaoDone; } void mGLWidget::reset() { @@ -105,8 +112,8 @@ void mGLWidget::reset() { } void mGLWidget::paintGL() { - if (!m_vaoDone) { - finalizeVAO(); + if (!m_vaoDone && !finalizeVAO()) { + return; } QOpenGLFunctions_Baseline* fn = context()->versionFunctions(); m_program->bind(); diff --git a/src/platform/qt/DisplayGL.h b/src/platform/qt/DisplayGL.h index 007cf6165..dfaee22f5 100644 --- a/src/platform/qt/DisplayGL.h +++ b/src/platform/qt/DisplayGL.h @@ -52,7 +52,7 @@ Q_OBJECT public: void setTex(GLuint tex) { m_tex = tex; } void setVBO(GLuint vbo) { m_vbo = vbo; } - void finalizeVAO(); + bool finalizeVAO(); void reset(); protected: From f3209e194235d441088d0513c3fa2dd26c93ddbd Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 24 Jun 2022 17:25:53 -0700 Subject: [PATCH 078/102] Qt: Move scripting classes into folder --- src/platform/qt/CMakeLists.txt | 10 +++++----- src/platform/qt/Window.cpp | 2 +- src/platform/qt/Window.h | 2 +- .../qt/{ => scripting}/ScriptingController.cpp | 6 +++--- src/platform/qt/{ => scripting}/ScriptingController.h | 0 .../qt/{ => scripting}/ScriptingTextBuffer.cpp | 0 src/platform/qt/{ => scripting}/ScriptingTextBuffer.h | 0 .../qt/{ => scripting}/ScriptingTextBufferModel.cpp | 0 .../qt/{ => scripting}/ScriptingTextBufferModel.h | 0 src/platform/qt/{ => scripting}/ScriptingView.cpp | 8 ++++---- src/platform/qt/{ => scripting}/ScriptingView.h | 0 src/platform/qt/{ => scripting}/ScriptingView.ui | 0 12 files changed, 14 insertions(+), 14 deletions(-) rename src/platform/qt/{ => scripting}/ScriptingController.cpp (96%) rename src/platform/qt/{ => scripting}/ScriptingController.h (100%) rename src/platform/qt/{ => scripting}/ScriptingTextBuffer.cpp (100%) rename src/platform/qt/{ => scripting}/ScriptingTextBuffer.h (100%) rename src/platform/qt/{ => scripting}/ScriptingTextBufferModel.cpp (100%) rename src/platform/qt/{ => scripting}/ScriptingTextBufferModel.h (100%) rename src/platform/qt/{ => scripting}/ScriptingView.cpp (95%) rename src/platform/qt/{ => scripting}/ScriptingView.h (100%) rename src/platform/qt/{ => scripting}/ScriptingView.ui (100%) diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 9f0621931..6f26c9c5a 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -250,13 +250,13 @@ endif() if(ENABLE_SCRIPTING) list(APPEND SOURCE_FILES - ScriptingController.cpp - ScriptingTextBuffer.cpp - ScriptingTextBufferModel.cpp - ScriptingView.cpp) + scripting/ScriptingController.cpp + scripting/ScriptingTextBuffer.cpp + scripting/ScriptingTextBufferModel.cpp + scripting/ScriptingView.cpp) list(APPEND UI_FILES - ScriptingView.ui) + scripting/ScriptingView.ui) endif() if(TARGET Qt6::Core) diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 9a2551503..2b7ec2cb1 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -50,7 +50,7 @@ #include "ReportView.h" #include "ROMInfo.h" #include "SaveConverter.h" -#include "ScriptingView.h" +#include "scripting/ScriptingView.h" #include "SensorView.h" #include "ShaderSelector.h" #include "ShortcutController.h" diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index 696604773..f30dac4c5 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -24,7 +24,7 @@ #include "LogController.h" #include "SettingsView.h" #ifdef ENABLE_SCRIPTING -#include "ScriptingController.h" +#include "scripting/ScriptingController.h" #endif namespace QGBA { diff --git a/src/platform/qt/ScriptingController.cpp b/src/platform/qt/scripting/ScriptingController.cpp similarity index 96% rename from src/platform/qt/ScriptingController.cpp rename to src/platform/qt/scripting/ScriptingController.cpp index 450c88842..c441592b9 100644 --- a/src/platform/qt/ScriptingController.cpp +++ b/src/platform/qt/scripting/ScriptingController.cpp @@ -3,11 +3,11 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "ScriptingController.h" +#include "scripting/ScriptingController.h" #include "CoreController.h" -#include "ScriptingTextBuffer.h" -#include "ScriptingTextBufferModel.h" +#include "scripting/ScriptingTextBuffer.h" +#include "scripting/ScriptingTextBufferModel.h" using namespace QGBA; diff --git a/src/platform/qt/ScriptingController.h b/src/platform/qt/scripting/ScriptingController.h similarity index 100% rename from src/platform/qt/ScriptingController.h rename to src/platform/qt/scripting/ScriptingController.h diff --git a/src/platform/qt/ScriptingTextBuffer.cpp b/src/platform/qt/scripting/ScriptingTextBuffer.cpp similarity index 100% rename from src/platform/qt/ScriptingTextBuffer.cpp rename to src/platform/qt/scripting/ScriptingTextBuffer.cpp diff --git a/src/platform/qt/ScriptingTextBuffer.h b/src/platform/qt/scripting/ScriptingTextBuffer.h similarity index 100% rename from src/platform/qt/ScriptingTextBuffer.h rename to src/platform/qt/scripting/ScriptingTextBuffer.h diff --git a/src/platform/qt/ScriptingTextBufferModel.cpp b/src/platform/qt/scripting/ScriptingTextBufferModel.cpp similarity index 100% rename from src/platform/qt/ScriptingTextBufferModel.cpp rename to src/platform/qt/scripting/ScriptingTextBufferModel.cpp diff --git a/src/platform/qt/ScriptingTextBufferModel.h b/src/platform/qt/scripting/ScriptingTextBufferModel.h similarity index 100% rename from src/platform/qt/ScriptingTextBufferModel.h rename to src/platform/qt/scripting/ScriptingTextBufferModel.h diff --git a/src/platform/qt/ScriptingView.cpp b/src/platform/qt/scripting/ScriptingView.cpp similarity index 95% rename from src/platform/qt/ScriptingView.cpp rename to src/platform/qt/scripting/ScriptingView.cpp index ccb7c9e20..3878b668a 100644 --- a/src/platform/qt/ScriptingView.cpp +++ b/src/platform/qt/scripting/ScriptingView.cpp @@ -3,13 +3,13 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "ScriptingView.h" +#include "scripting/ScriptingView.h" #include "GBAApp.h" #include "ConfigController.h" -#include "ScriptingController.h" -#include "ScriptingTextBuffer.h" -#include "ScriptingTextBufferModel.h" +#include "scripting/ScriptingController.h" +#include "scripting/ScriptingTextBuffer.h" +#include "scripting/ScriptingTextBufferModel.h" using namespace QGBA; diff --git a/src/platform/qt/ScriptingView.h b/src/platform/qt/scripting/ScriptingView.h similarity index 100% rename from src/platform/qt/ScriptingView.h rename to src/platform/qt/scripting/ScriptingView.h diff --git a/src/platform/qt/ScriptingView.ui b/src/platform/qt/scripting/ScriptingView.ui similarity index 100% rename from src/platform/qt/ScriptingView.ui rename to src/platform/qt/scripting/ScriptingView.ui From e8a39fea95a62fd8bd91b02a0ad7e38877a14ae9 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 24 Jun 2022 17:48:52 -0700 Subject: [PATCH 079/102] All: Clean up some warnings --- include/mgba/internal/gba/sio.h | 2 +- src/core/config.c | 4 ++-- src/platform/qt/IOViewer.cpp | 3 +++ src/platform/qt/Window.cpp | 5 ++++- src/script/types.c | 8 +++++++- 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/include/mgba/internal/gba/sio.h b/include/mgba/internal/gba/sio.h index e0fca7812..260772f55 100644 --- a/include/mgba/internal/gba/sio.h +++ b/include/mgba/internal/gba/sio.h @@ -21,7 +21,7 @@ extern const int GBASIOCyclesPerTransfer[4][MAX_GBAS]; mLOG_DECLARE_CATEGORY(GBA_SIO); enum { - RCNT_INITIAL = 0x8000 + RCNT_INITIAL = -0x8000 }; enum { diff --git a/src/core/config.c b/src/core/config.c index 4308b50ba..6bfcb8e8b 100644 --- a/src/core/config.c +++ b/src/core/config.c @@ -242,7 +242,7 @@ void mCoreConfigDirectory(char* out, size_t outLength) { CreateDirectoryW(wpath, NULL); if (PATH_SEP[0] != '\\') { WCHAR* pathSep; - for (pathSep = wpath; pathSep = wcschr(pathSep, L'\\');) { + for (pathSep = wpath; (pathSep = wcschr(pathSep, L'\\'));) { pathSep[0] = PATH_SEP[0]; } } @@ -284,7 +284,7 @@ void mCoreConfigPortablePath(char* out, size_t outLength) { PathRemoveFileSpecW(wpath); if (PATH_SEP[0] != '\\') { WCHAR* pathSep; - for (pathSep = wpath; pathSep = wcschr(pathSep, L'\\');) { + for (pathSep = wpath; (pathSep = wcschr(pathSep, L'\\'));) { pathSep[0] = PATH_SEP[0]; } } diff --git a/src/platform/qt/IOViewer.cpp b/src/platform/qt/IOViewer.cpp index 0d5d8afa3..46c0d8dbb 100644 --- a/src/platform/qt/IOViewer.cpp +++ b/src/platform/qt/IOViewer.cpp @@ -1584,6 +1584,9 @@ IOViewer::IOViewer(std::shared_ptr controller, QWidget* parent) m_width = 1; break; #endif + case mPLATFORM_NONE: + maxRegs = 0; + break; } for (unsigned i = 0; i < maxRegs; ++i) { diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 2b7ec2cb1..a0ec476f6 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -473,7 +473,7 @@ void Window::parseCard() { QString("oh"), QMessageBox::Ok); dialog->setAttribute(Qt::WA_DeleteOnClose); auto status = std::make_shared>(0, filenames.size()); - GBAApp::app()->submitWorkerJob([filenames, dialog, status]() { + GBAApp::app()->submitWorkerJob([filenames, status]() { int success = 0; for (QString filename : filenames) { if (filename.isEmpty()) { @@ -507,6 +507,9 @@ void Window::parseCard() { } status->first = success; }, [dialog, status]() { + if (status->second == 0) { + return; + } dialog->setText(tr("%1 of %2 e-Reader cards converted successfully.").arg(status->first).arg(status->second)); dialog->show(); }); diff --git a/src/script/types.c b/src/script/types.c index ae1108ae1..a9df515f2 100644 --- a/src/script/types.c +++ b/src/script/types.c @@ -360,13 +360,17 @@ uint32_t _hashScalar(const struct mScriptValue* val) { *T = input->value.s32; \ } else if (input->type->size == 8) { \ *T = input->value.s64; \ - } \ + } else { \ + return false; \ + }\ break; \ case mSCRIPT_TYPE_UINT: \ if (input->type->size <= 4) { \ *T = input->value.u32; \ } else if (input->type->size == 8) { \ *T = input->value.u64; \ + } else { \ + return false; \ } \ break; \ case mSCRIPT_TYPE_FLOAT: \ @@ -374,6 +378,8 @@ uint32_t _hashScalar(const struct mScriptValue* val) { *T = input->value.f32; \ } else if (input->type->size == 8) { \ *T = input->value.f64; \ + } else { \ + return false; \ } \ break; \ default: \ From d21da6df2d52cb8e362525f6c8a578b18fa03a9e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 24 Jun 2022 19:01:10 -0700 Subject: [PATCH 080/102] Qt: Fix crash when calling createBuffer from a callback --- src/platform/qt/scripting/ScriptingTextBuffer.h | 2 +- src/platform/qt/scripting/ScriptingTextBufferModel.cpp | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/platform/qt/scripting/ScriptingTextBuffer.h b/src/platform/qt/scripting/ScriptingTextBuffer.h index e2bdb8f30..b70e9f82a 100644 --- a/src/platform/qt/scripting/ScriptingTextBuffer.h +++ b/src/platform/qt/scripting/ScriptingTextBuffer.h @@ -18,7 +18,7 @@ class ScriptingTextBuffer : public QObject { Q_OBJECT public: - ScriptingTextBuffer(QObject* parent); + ScriptingTextBuffer(QObject* parent = nullptr); QTextDocument* document() { return &m_document; }; mScriptTextBuffer* textBuffer() { return &m_shim; } diff --git a/src/platform/qt/scripting/ScriptingTextBufferModel.cpp b/src/platform/qt/scripting/ScriptingTextBufferModel.cpp index 0d01b7581..d62bb62df 100644 --- a/src/platform/qt/scripting/ScriptingTextBufferModel.cpp +++ b/src/platform/qt/scripting/ScriptingTextBufferModel.cpp @@ -35,7 +35,11 @@ void ScriptingTextBufferModel::reset() { mScriptTextBuffer* ScriptingTextBufferModel::createTextBuffer(void* context) { ScriptingTextBufferModel* self = static_cast(context); self->beginInsertRows(QModelIndex(), self->m_buffers.size(), self->m_buffers.size() + 1); - ScriptingTextBuffer* buffer = new ScriptingTextBuffer(self); + ScriptingTextBuffer* buffer = new ScriptingTextBuffer; + if (buffer->thread() != self->thread()) { + buffer->moveToThread(self->thread()); + } + buffer->setParent(self); QObject::connect(buffer, &ScriptingTextBuffer::bufferNameChanged, self, &ScriptingTextBufferModel::bufferNameChanged); self->m_buffers.append(buffer); emit self->textBufferCreated(buffer); From 7fe043146dd9a94453de2d57b700f464fc5a94b0 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 24 Jun 2022 19:01:33 -0700 Subject: [PATCH 081/102] Res: Auto-register frame callback --- res/scripts/pokemon.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/res/scripts/pokemon.lua b/res/scripts/pokemon.lua index 76a1fcdbe..7ebe54bb8 100644 --- a/res/scripts/pokemon.lua +++ b/res/scripts/pokemon.lua @@ -499,10 +499,21 @@ function detectGame() console:error("Unknown game!") else console:log("Found game: " .. game.name) + if not partyBuffer then + partyBuffer = console:createBuffer("Party") + end end end +function updateBuffer() + if not game or not partyBuffer then + return + end + printPartyStatus(game, partyBuffer) +end + callbacks:add("start", detectGame) +callbacks:add("frame", updateBuffer) if emu then detectGame() end From 6629aeebecb19d7a24782c1ab94735e3ee4fdd06 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 24 Jun 2022 21:46:02 -0700 Subject: [PATCH 082/102] GBA Video: Fix high tiles rendering wrong on macOS --- src/gba/renderers/gl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gba/renderers/gl.c b/src/gba/renderers/gl.c index a06b2e4d6..acd5dad7f 100644 --- a/src/gba/renderers/gl.c +++ b/src/gba/renderers/gl.c @@ -177,7 +177,7 @@ static const char* const _renderMode0 = " coord.y ^= 7;\n" " }\n" " int tile = map & 1023;\n" - " int paletteEntry = renderTile(tile, map >> 12, coord & 7);\n" + " int paletteEntry = renderTile(tile, (map >> 12) & 15, coord & 7);\n" " color = texelFetch(palette, ivec2(paletteEntry, int(texCoord.y)), 0);\n" "}\n"; From 5c80fa67efa8ef8e560a6ffdc5debcd415d1bb69 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 24 Jun 2022 22:24:05 -0700 Subject: [PATCH 083/102] Qt: Fix Quit role --- src/platform/qt/Window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index a0ec476f6..543eb4b2f 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1401,7 +1401,7 @@ void Window::setupMenu(QMenuBar* menubar) { #endif m_actions.addAction(tr("About..."), "about", openTView(), "file")->setRole(Action::Role::ABOUT); - m_actions.addAction(tr("E&xit"), "quit", static_cast(this), &QWidget::close, "file", QKeySequence::Quit)->setRole(Action::Role::SETTINGS); + m_actions.addAction(tr("E&xit"), "quit", static_cast(this), &QWidget::close, "file", QKeySequence::Quit)->setRole(Action::Role::QUIT); m_actions.addMenu(tr("&Emulation"), "emu"); addGameAction(tr("&Reset"), "reset", &CoreController::reset, "emu", QKeySequence("Ctrl+R")); From 99f067e5391f6dc09c23656833d469f8de92baa6 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 27 Jun 2022 20:10:18 -0700 Subject: [PATCH 084/102] Scripting: Fix typo --- include/mgba/script/macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mgba/script/macros.h b/include/mgba/script/macros.h index 79b9ed611..3833f6984 100644 --- a/include/mgba/script/macros.h +++ b/include/mgba/script/macros.h @@ -334,7 +334,7 @@ CXX_GUARD_START mSCRIPT_DECLARE_STRUCT_C_METHOD_WITH_DEFAULTS(TYPE, RETURN, NAME, p0->NAME, NPARAMS, __VA_ARGS__) #define mSCRIPT_DECLARE_STRUCT_VOID_CD_METHOD_WITH_DEFAULTS(TYPE, NAME, NPARAMS, ...) \ - mSCRIPT_DECLARE_STRUCT_VOID_C_METHOD_WITH_DEFAU(TYPE, NAME, p0->NAME, NPARAMS, __VA_ARGS__) + mSCRIPT_DECLARE_STRUCT_VOID_C_METHOD_WITH_DEFAULTS(TYPE, NAME, p0->NAME, NPARAMS, __VA_ARGS__) #define mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(TYPE, NAME) \ static const struct mScriptValue _mSTStructBindingDefaults_ ## TYPE ## _ ## NAME[mSCRIPT_PARAMS_MAX] = { \ From 2969a8bf7a25e00616436b43c7a5e11255f20070 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 27 Jun 2022 21:10:16 -0700 Subject: [PATCH 085/102] Core: Fix cache writes that span multiple tiles --- include/mgba/core/map-cache.h | 1 + src/core/map-cache.c | 17 +++++++++++++---- src/gb/renderers/cache-set.c | 1 + src/gba/renderers/cache-set.c | 2 +- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/include/mgba/core/map-cache.h b/include/mgba/core/map-cache.h index 2bd5934e8..349fc1663 100644 --- a/include/mgba/core/map-cache.h +++ b/include/mgba/core/map-cache.h @@ -23,6 +23,7 @@ DECL_BITS(mMapCacheSystemInfo, TilesWide, 8, 4); DECL_BITS(mMapCacheSystemInfo, TilesHigh, 12, 4); DECL_BITS(mMapCacheSystemInfo, MacroTileSize, 16, 7); DECL_BITS(mMapCacheSystemInfo, MapAlign, 23, 2); +DECL_BITS(mMapCacheSystemInfo, WriteAlign, 25, 2); DECL_BITFIELD(mMapCacheEntryFlags, uint16_t); DECL_BITS(mMapCacheEntryFlags, PaletteId, 0, 4); diff --git a/src/core/map-cache.c b/src/core/map-cache.c index 17df206dd..d51800780 100644 --- a/src/core/map-cache.c +++ b/src/core/map-cache.c @@ -70,11 +70,20 @@ void mMapCacheDeinit(struct mMapCache* cache) { void mMapCacheWriteVRAM(struct mMapCache* cache, uint32_t address) { if (address >= cache->mapStart && address < cache->mapStart + cache->mapSize) { + uint32_t align = 1 << (mMapCacheSystemInfoGetWriteAlign(cache->sysConfig) - mMapCacheSystemInfoGetMapAlign(cache->sysConfig)); address -= cache->mapStart; - struct mMapCacheEntry* status = &cache->status[address >> mMapCacheSystemInfoGetMapAlign(cache->sysConfig)]; - ++status->vramVersion; - status->flags = mMapCacheEntryFlagsClearVramClean(status->flags); - status->tileStatus[mMapCacheEntryFlagsGetPaletteId(status->flags)].vramClean = 0; + address >>= mMapCacheSystemInfoGetMapAlign(cache->sysConfig); + + uint32_t i; + for (i = 0; i < align; ++i) { + if (address + i >= (cache->mapSize >> mMapCacheSystemInfoGetMapAlign(cache->sysConfig))) { + break; + } + struct mMapCacheEntry* status = &cache->status[address + i]; + ++status->vramVersion; + status->flags = mMapCacheEntryFlagsClearVramClean(status->flags); + status->tileStatus[mMapCacheEntryFlagsGetPaletteId(status->flags)].vramClean = 0; + } } } diff --git a/src/gb/renderers/cache-set.c b/src/gb/renderers/cache-set.c index ebd0d0899..bfc56c2a3 100644 --- a/src/gb/renderers/cache-set.c +++ b/src/gb/renderers/cache-set.c @@ -119,6 +119,7 @@ void GBVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint16_t address, u sysconfig = mMapCacheSystemInfoSetMacroTileSize(sysconfig, 5); sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 1); sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 0); + sysconfig = mMapCacheSystemInfoSetWriteAlign(sysconfig, 0); sysconfig = mMapCacheSystemInfoSetTilesHigh(sysconfig, 5); sysconfig = mMapCacheSystemInfoSetTilesWide(sysconfig, 5); mMapCacheConfigureSystem(map, sysconfig); diff --git a/src/gba/renderers/cache-set.c b/src/gba/renderers/cache-set.c index 95093ae9a..51512721d 100644 --- a/src/gba/renderers/cache-set.c +++ b/src/gba/renderers/cache-set.c @@ -160,7 +160,7 @@ static void GBAVideoCacheWriteBGCNT(struct mCacheSet* cache, size_t bg, uint16_t int size = GBARegisterBGCNTGetSize(value); int tilesWide = 0; int tilesHigh = 0; - mMapCacheSystemInfo sysconfig = 0; + mMapCacheSystemInfo sysconfig = mMapCacheSystemInfoSetWriteAlign(0, 1); if (map->mapParser == mapParser0) { map->tileCache = mTileCacheSetGetPointer(&cache->tiles, p); sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 2 + p); From 1bf1a970238ff99d52860c75546fcc91f161c0da Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 28 Jun 2022 02:23:39 -0700 Subject: [PATCH 086/102] GBA Video: Fix sprite layer priority updating in GL --- CHANGES | 1 + src/gba/renderers/gl.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index aed3e0c11..d536343aa 100644 --- a/CHANGES +++ b/CHANGES @@ -47,6 +47,7 @@ Emulation fixes: - GBA Video: Fix sprites with mid-frame palette changes in GL (fixes mgba.io/i/2476) - GBA Video: Fix OBJ tile wrapping with 2D char mapping (fixes mgba.io/i/2443) - GBA Video: Fix horizontal lines in GL when charbase is changed (fixes mgba.io/i/1631) + - GBA Video: Fix sprite layer priority updating in GL Other fixes: - ARM: Disassemble Thumb mov pseudo-instruction properly - Core: Don't attempt to restore rewind diffs past start of rewind diff --git a/src/gba/renderers/gl.c b/src/gba/renderers/gl.c index acd5dad7f..75b7b7ced 100644 --- a/src/gba/renderers/gl.c +++ b/src/gba/renderers/gl.c @@ -1802,9 +1802,9 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB glUniformMatrix2fv(uniforms[GBA_GL_OBJ_TRANSFORM], 1, GL_FALSE, (GLfloat[]) { flipX, 0, 0, flipY }); } glUniform4i(uniforms[GBA_GL_OBJ_DIMS], width, height, totalWidth, totalHeight); - glDisable(GL_STENCIL_TEST); if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_OBJWIN) { // OBJWIN writes do not affect pixel priority + glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glStencilMask(0); @@ -1812,6 +1812,7 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB glUniform3i(uniforms[GBA_GL_OBJ_OBJWIN], window, renderer->bldb, renderer->bldy); glDrawBuffers(3, (GLenum[]) { GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT2 }); } else { + glEnable(GL_STENCIL_TEST); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glStencilMask(1); @@ -1836,7 +1837,6 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB // Update the pixel priority for already-written pixels shader = &renderer->objShader[2]; uniforms = shader->uniforms; - glEnable(GL_STENCIL_TEST); glStencilFunc(GL_EQUAL, 1, 1); glUseProgram(shader->program); glDrawBuffers(2, (GLenum[]) { GL_NONE, GL_COLOR_ATTACHMENT1 }); From 0979380c74569964b9b082a70153a10dde61d927 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 28 Jun 2022 18:43:15 -0700 Subject: [PATCH 087/102] Debugger: Shaving recursive yaks takes a lot of work --- CHANGES | 1 + include/mgba-util/vector.h | 1 + include/mgba/internal/debugger/parser.h | 4 +- src/arm/debugger/debugger.c | 2 - src/debugger/cli-debugger.c | 3 - src/debugger/parser.c | 288 +++++++++++++++++------- src/debugger/test/parser.c | 7 +- src/sm83/debugger/debugger.c | 2 - 8 files changed, 216 insertions(+), 92 deletions(-) diff --git a/CHANGES b/CHANGES index d536343aa..382ce85ad 100644 --- a/CHANGES +++ b/CHANGES @@ -53,6 +53,7 @@ Other fixes: - Core: Don't attempt to restore rewind diffs past start of rewind - Core: Fix the runloop resuming after a game has crashed (fixes mgba.io/i/2451) - Core: Fix crash if library can't be opened + - Debugger: Fix crash with extremely long CLI strings - FFmpeg: Fix crash when encoding audio with some containers - FFmpeg: Fix GIF recording (fixes mgba.io/i/2393) - GB: Fix temporary saves diff --git a/include/mgba-util/vector.h b/include/mgba-util/vector.h index ba412d7da..a4ec71b65 100644 --- a/include/mgba-util/vector.h +++ b/include/mgba-util/vector.h @@ -98,6 +98,7 @@ CXX_GUARD_START } \ DECLARE_VECTOR(StringList, char*); +DECLARE_VECTOR(IntList, int); CXX_GUARD_END diff --git a/include/mgba/internal/debugger/parser.h b/include/mgba/internal/debugger/parser.h index 37f194ddb..0b8f09d4c 100644 --- a/include/mgba/internal/debugger/parser.h +++ b/include/mgba/internal/debugger/parser.h @@ -43,7 +43,7 @@ enum Operation { struct Token { enum TokenType { - TOKEN_ERROR_TYPE, + TOKEN_ERROR_TYPE = 0, TOKEN_UINT_TYPE, TOKEN_IDENTIFIER_TYPE, TOKEN_OPERATOR_TYPE, @@ -60,8 +60,10 @@ struct Token { struct ParseTree { struct Token token; + struct ParseTree* p; struct ParseTree* lhs; struct ParseTree* rhs; + int precedence; }; size_t lexExpression(struct LexVector* lv, const char* string, size_t length, const char* eol); diff --git a/src/arm/debugger/debugger.c b/src/arm/debugger/debugger.c index 99fd4ffb4..afc1e0c49 100644 --- a/src/arm/debugger/debugger.c +++ b/src/arm/debugger/debugger.c @@ -190,14 +190,12 @@ static struct ARMDebugBreakpoint* _lookupBreakpoint(struct ARMDebugBreakpointLis static void _destroyBreakpoint(struct ARMDebugBreakpoint* breakpoint) { if (breakpoint->d.condition) { parseFree(breakpoint->d.condition); - free(breakpoint->d.condition); } } static void _destroyWatchpoint(struct mWatchpoint* watchpoint) { if (watchpoint->condition) { parseFree(watchpoint->condition); - free(watchpoint->condition); } } diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index a89e6db4d..dbc10fe89 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -226,11 +226,9 @@ static bool _parseExpression(struct mDebugger* debugger, struct CLIDebugVector* } if (!mDebuggerEvaluateParseTree(debugger, tree, intValue, segmentValue)) { parseFree(tree); - free(tree); return false; } parseFree(tree); - free(tree); return true; } @@ -599,7 +597,6 @@ static struct ParseTree* _parseTree(const char** string) { if (error) { if (tree) { parseFree(tree); - free(tree); } return NULL; } else { diff --git a/src/debugger/parser.c b/src/debugger/parser.c index 41197b53e..72eae1ed3 100644 --- a/src/debugger/parser.c +++ b/src/debugger/parser.c @@ -11,6 +11,8 @@ DEFINE_VECTOR(LexVector, struct Token); +DEFINE_VECTOR(IntList, int32_t); + enum LexState { LEX_ERROR = -1, LEX_ROOT = 0, @@ -493,16 +495,21 @@ static const int _operatorPrecedence[] = { [OP_DEREFERENCE] = 2, }; -static struct ParseTree* _parseTreeCreate() { +static struct ParseTree* _parseTreeCreate(void) { struct ParseTree* tree = malloc(sizeof(struct ParseTree)); tree->token.type = TOKEN_ERROR_TYPE; - tree->rhs = 0; - tree->lhs = 0; + tree->p = NULL; + tree->rhs = NULL; + tree->lhs = NULL; + tree->precedence = INT_MAX; return tree; } -static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, size_t i, int precedence, int* openParens) { - struct ParseTree* newTree = 0; +static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, int* openParens) { + struct ParseTree* newTree = NULL; + bool pop = false; + int precedence = INT_MAX; + size_t i = 0; while (i < LexVectorSize(lv)) { struct Token* token = LexVectorGetPointer(lv, i); int newPrecedence; @@ -517,27 +524,36 @@ static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, siz ++i; } else { tree->token.type = TOKEN_ERROR_TYPE; - return i + 1; + ++i; + pop = true; } break; case TOKEN_SEGMENT_TYPE: tree->lhs = _parseTreeCreate(); tree->lhs->token.type = TOKEN_UINT_TYPE; tree->lhs->token.uintValue = token->uintValue; + tree->lhs->p = tree; + tree->lhs->precedence = precedence; tree->rhs = _parseTreeCreate(); + tree->rhs->p = tree; + tree->rhs->precedence = precedence; tree->token.type = TOKEN_SEGMENT_TYPE; - i = _parseExpression(tree->rhs, lv, i + 1, precedence, openParens); + tree = tree->rhs; + ++i; break; case TOKEN_OPEN_PAREN_TYPE: ++*openParens; - i = _parseExpression(tree, lv, i + 1, INT_MAX, openParens); + precedence = INT_MAX; + ++i; break; case TOKEN_CLOSE_PAREN_TYPE: if (*openParens <= 0) { tree->token.type = TOKEN_ERROR_TYPE; } --*openParens; - return i + 1; + ++i; + pop = true; + break; case TOKEN_OPERATOR_TYPE: if (tree->token.type == TOKEN_ERROR_TYPE) { switch (token->operatorValue) { @@ -557,21 +573,44 @@ static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, siz newPrecedence = _operatorPrecedence[token->operatorValue]; if (newPrecedence < precedence) { newTree = _parseTreeCreate(); - *newTree = *tree; + memcpy(newTree, tree, sizeof(*tree)); + if (newTree->lhs) { + newTree->lhs->p = newTree; + } + if (newTree->rhs) { + newTree->rhs->p = newTree; + } + newTree->p = tree; tree->lhs = newTree; tree->rhs = _parseTreeCreate(); + tree->rhs->p = tree; + tree->rhs->precedence = newPrecedence; + precedence = newPrecedence; tree->token = *token; - i = _parseExpression(tree->rhs, lv, i + 1, newPrecedence, openParens); - if (tree->token.type == TOKEN_ERROR_TYPE) { - tree->token.type = TOKEN_ERROR_TYPE; - } + tree = tree->rhs; + ++i; } else { - return i; + pop = true; } break; case TOKEN_ERROR_TYPE: tree->token.type = TOKEN_ERROR_TYPE; - return i + 1; + ++i; + pop = true; + break; + } + + if (pop) { + if (tree->token.type == TOKEN_ERROR_TYPE && tree->p) { + tree->p->token.type = TOKEN_ERROR_TYPE; + } + tree = tree->p; + pop = false; + if (!tree) { + break; + } else { + precedence = tree->precedence; + } } } @@ -584,11 +623,13 @@ void parseLexedExpression(struct ParseTree* tree, struct LexVector* lv) { } tree->token.type = TOKEN_ERROR_TYPE; - tree->lhs = 0; - tree->rhs = 0; + tree->lhs = NULL; + tree->rhs = NULL; + tree->p = NULL; + tree->precedence = INT_MAX; int openParens = 0; - _parseExpression(tree, lv, 0, INT_MAX, &openParens); + _parseExpression(tree, lv, &openParens); if (openParens) { if (tree->token.type == TOKEN_IDENTIFIER_TYPE) { free(tree->token.identifierValue); @@ -607,23 +648,40 @@ void lexFree(struct LexVector* lv) { } } -void parseFree(struct ParseTree* tree) { - if (!tree) { - return; - } - - if (tree->lhs) { - parseFree(tree->lhs); - free(tree->lhs); - } - if (tree->rhs) { - parseFree(tree->rhs); - free(tree->rhs); - } - +static void _freeTree(struct ParseTree* tree) { if (tree->token.type == TOKEN_IDENTIFIER_TYPE) { free(tree->token.identifierValue); } + free(tree); +} + +void parseFree(struct ParseTree* tree) { + while (tree) { + if (tree->lhs) { + tree = tree->lhs; + continue; + } + if (tree->rhs) { + tree = tree->rhs; + continue; + } + if (tree->p) { + if (tree->p->lhs == tree) { + tree = tree->p; + _freeTree(tree->lhs); + tree->lhs = NULL; + } else if (tree->p->rhs == tree) { + tree = tree->p; + _freeTree(tree->rhs); + tree->rhs = NULL; + } else { + abort(); + } + } else { + _freeTree(tree); + break; + } + } } static bool _performOperation(struct mDebugger* debugger, enum Operation operation, int32_t current, int32_t next, int32_t* value, int* segment) { @@ -721,56 +779,124 @@ bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tr if (!value) { return false; } - int32_t lhs, rhs; - switch (tree->token.type) { - case TOKEN_UINT_TYPE: - if (segment) { - *segment = -1; - } - *value = tree->token.uintValue; - return true; - case TOKEN_SEGMENT_TYPE: - if (!mDebuggerEvaluateParseTree(debugger, tree->rhs, value, segment)) { - return false; - } - return mDebuggerEvaluateParseTree(debugger, tree->lhs, segment, NULL); - case TOKEN_OPERATOR_TYPE: - switch (tree->token.operatorValue) { - case OP_ASSIGN: - case OP_ADD: - case OP_SUBTRACT: - case OP_MULTIPLY: - case OP_DIVIDE: - case OP_MODULO: - case OP_AND: - case OP_OR: - case OP_XOR: - case OP_LESS: - case OP_GREATER: - case OP_EQUAL: - case OP_NOT_EQUAL: - case OP_LOGICAL_AND: - case OP_LOGICAL_OR: - case OP_LE: - case OP_GE: - case OP_SHIFT_L: - case OP_SHIFT_R: - if (!mDebuggerEvaluateParseTree(debugger, tree->lhs, &lhs, segment)) { - return false; - } - // Fall through - default: - if (!mDebuggerEvaluateParseTree(debugger, tree->rhs, &rhs, segment)) { - return false; + struct IntList stack; + int nextBranch; + bool ok = true; + int32_t tmpVal, tmpSegment; + + IntListInit(&stack, 0); + while (ok) { + switch (tree->token.type) { + case TOKEN_UINT_TYPE: + nextBranch = 2; + tmpSegment = -1; + tmpVal = tree->token.uintValue; + break; + case TOKEN_SEGMENT_TYPE: + nextBranch = 0; + break; + case TOKEN_OPERATOR_TYPE: + switch (tree->token.operatorValue) { + case OP_ASSIGN: + case OP_ADD: + case OP_SUBTRACT: + case OP_MULTIPLY: + case OP_DIVIDE: + case OP_MODULO: + case OP_AND: + case OP_OR: + case OP_XOR: + case OP_LESS: + case OP_GREATER: + case OP_EQUAL: + case OP_NOT_EQUAL: + case OP_LOGICAL_AND: + case OP_LOGICAL_OR: + case OP_LE: + case OP_GE: + case OP_SHIFT_L: + case OP_SHIFT_R: + nextBranch = 0; + break; + default: + nextBranch = 1; + break; } break; + case TOKEN_IDENTIFIER_TYPE: + if (!mDebuggerLookupIdentifier(debugger, tree->token.identifierValue, &tmpVal, &tmpSegment)) { + ok = false; + } + nextBranch = 2; + break; + case TOKEN_ERROR_TYPE: + default: + ok = false; + break; + } + if (!ok) { + break; + } + + bool gotTree = false; + while (!gotTree && tree) { + int32_t lhs, rhs; + + switch (nextBranch) { + case 0: + *IntListAppend(&stack) = tmpVal; + *IntListAppend(&stack) = tmpSegment; + *IntListAppend(&stack) = nextBranch; + tree = tree->lhs; + gotTree = true; + break; + case 1: + *IntListAppend(&stack) = tmpVal; + *IntListAppend(&stack) = tmpSegment; + *IntListAppend(&stack) = nextBranch; + tree = tree->rhs; + gotTree = true; + break; + case 2: + if (!IntListSize(&stack)) { + tree = NULL; + break; + } + nextBranch = *IntListGetPointer(&stack, IntListSize(&stack) - 1); + IntListResize(&stack, -1); + tree = tree->p; + if (nextBranch == 0) { + ++nextBranch; + } else if (tree) { + nextBranch = 2; + switch (tree->token.type) { + case TOKEN_OPERATOR_TYPE: + rhs = tmpVal; + lhs = *IntListGetPointer(&stack, IntListSize(&stack) - 2); + tmpSegment = *IntListGetPointer(&stack, IntListSize(&stack) - 1); + ok = _performOperation(debugger, tree->token.operatorValue, lhs, rhs, &tmpVal, &tmpSegment); + break; + case TOKEN_SEGMENT_TYPE: + tmpSegment = *IntListGetPointer(&stack, IntListSize(&stack) - 2); + break; + default: + break; + } + } + IntListResize(&stack, -2); + break; + } + } + if (!tree) { + break; } - return _performOperation(debugger, tree->token.operatorValue, lhs, rhs, value, segment); - case TOKEN_IDENTIFIER_TYPE: - return mDebuggerLookupIdentifier(debugger, tree->token.identifierValue, value, segment); - case TOKEN_ERROR_TYPE: - default: - break; } - return false; + IntListDeinit(&stack); + if (ok) { + *value = tmpVal; + if (segment) { + *segment = tmpSegment; + } + } + return ok; } diff --git a/src/debugger/test/parser.c b/src/debugger/test/parser.c index c1c2840d2..b25d8a68a 100644 --- a/src/debugger/test/parser.c +++ b/src/debugger/test/parser.c @@ -9,7 +9,7 @@ struct LPTest { struct LexVector lv; - struct ParseTree tree; + struct ParseTree* tree; }; #define PARSE(STR) \ @@ -18,7 +18,8 @@ struct LPTest { LexVectorClear(&lp->lv); \ size_t adjusted = lexExpression(&lp->lv, STR, strlen(STR), ""); \ assert_false(adjusted > strlen(STR)); \ - struct ParseTree* tree = &lp->tree; \ + lp->tree = malloc(sizeof(*lp->tree)); \ + struct ParseTree* tree = lp->tree; \ parseLexedExpression(tree, &lp->lv) static int parseSetup(void** state) { @@ -30,7 +31,7 @@ static int parseSetup(void** state) { static int parseTeardown(void** state) { struct LPTest* lp = *state; - parseFree(&lp->tree); + parseFree(lp->tree); lexFree(&lp->lv); LexVectorDeinit(&lp->lv); free(lp); diff --git a/src/sm83/debugger/debugger.c b/src/sm83/debugger/debugger.c index edf8afc1e..f6a6f690e 100644 --- a/src/sm83/debugger/debugger.c +++ b/src/sm83/debugger/debugger.c @@ -28,14 +28,12 @@ static struct mBreakpoint* _lookupBreakpoint(struct mBreakpointList* breakpoints static void _destroyBreakpoint(struct mBreakpoint* breakpoint) { if (breakpoint->condition) { parseFree(breakpoint->condition); - free(breakpoint->condition); } } static void _destroyWatchpoint(struct mWatchpoint* watchpoint) { if (watchpoint->condition) { parseFree(watchpoint->condition); - free(watchpoint->condition); } } From a851c1e094d748f2ebe16a97d20c7781e65815df Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 29 Jun 2022 01:39:06 -0700 Subject: [PATCH 088/102] Res: Add some stylized icons for future use --- res/gb-icon-128.png | Bin 0 -> 2110 bytes res/gb-icon-256.png | Bin 0 -> 3289 bytes res/gb-icon.svg | 2 ++ res/gba-icon-128.png | Bin 0 -> 3211 bytes res/gba-icon-256.png | Bin 0 -> 5589 bytes res/gba-icon.svg | 2 ++ res/gbc-icon-128.png | Bin 0 -> 1660 bytes res/gbc-icon-256.png | Bin 0 -> 3227 bytes res/gbc-icon.svg | 2 ++ 9 files changed, 6 insertions(+) create mode 100644 res/gb-icon-128.png create mode 100644 res/gb-icon-256.png create mode 100644 res/gb-icon.svg create mode 100644 res/gba-icon-128.png create mode 100644 res/gba-icon-256.png create mode 100644 res/gba-icon.svg create mode 100644 res/gbc-icon-128.png create mode 100644 res/gbc-icon-256.png create mode 100644 res/gbc-icon.svg diff --git a/res/gb-icon-128.png b/res/gb-icon-128.png new file mode 100644 index 0000000000000000000000000000000000000000..4aef63996cae69f4103c7b348d952fdd9fb2e168 GIT binary patch literal 2110 zcmds(*H_aC7RP@fvUHLdLZ2i^fDA+oFiJO}2?Pj85l3aDOJ8aR_oPf5?2%l06@yt z#?tv{)Blzz_{hI5-2VmuLcLD*u2$CJ_D7fh5%gTl)Wisb!I&H$hQr|$3We-!-NdZy zP$p8TR1p!8#Kc6}V~nt{Fpt}3N4A{c^I95eL`6kLhXH#dq^FcU|5tkIo&Fv+ zcd!SEQtIvQD3#Y&l!kH!dd`zbgMFPtgFQW+t&Me+o$ZbH@1~9L`rl6T1=Ay+R|LOa zbpQB%PEk?*LDoIz^G@&PCrM;Wdnc>MIoX#lxCI9Vyy<8|NJH0QIvN@pva+&)Pz*#& z;v@tS1X0yJE}sb3k`@um%YAgg&E*sp>kLJr^pvDonN@Sva|Pfw5P zsuxWSb(sjfCqxA!b==qMs)6>YsqtY51TxI+qeO+bH`NVxw|956uv(aQc6R(x4!eb^ zby8!nmrbL_8=pNL7aN0CL8_@?q@|^Ly4V;s6;m?FjQr0w=cBEG!Xd&iTDdoZ>;%AnekzTpZI-w z;qdVZu1*&!!pI~hJV0Aw z%Fx&{^!9xGUml;@cILOp)zhux5#*YM}}79z?}KEGpckpbdDh0E#`hamN|> z0t)vzwlI{n4xh2(0L|qL)FuL~`$Uuce9^QJp9x@vqf;dVx^mk0ecS-f)6=CoJ{ftr zFNM(F6pQ6wwlg1qbDQeGisrW9U8AVan?Y+v05f3y5Cnn(ASgXk)WBd-@+v#IPIXs^ zj3S_Ooq%J+{|;SjVLnCAbJ?a-uEt;YU5)wTJ~I4=erHU2fWM`C75(bDEmafHnjF>5 zul!+5(S~pFkDD)miw}c#whT>lqiZguj$06DwbxyThdbuF1QP%GT-XI_HPx9{2DKyQ zPbH&(T+cj$`lc-5lF41wg_WFJ5V@Y03;)Q0ZI=F4&4OofB<@k&9ivP=5cIc)`QPZo zmF3P7VO`G-KQ|!qFrHaLe}Ww1-YP)$(f9RTL4AU@@DyX{W^oeau90O$6wP{RcZ9aZ zm%;mRR{8u9pUl9IrKg&oUJo8YWj+LEnPSlmjye9t38{9Y58r0-A1C2!)cm18U58d) zl9e*ZRY(1PV@BsSk5Lr466Zvuj@R0-pMCj8|B_|!H08F#v-Hxt`37l|uhBt&Mz>M- z_}DPH;wqP(3?+Ta0EOyq@x-SOdYkL_Xz6D6HtWm|xTt%F)%Y_404;z58g$qd*I-*B z7A?{>rjeH)Iebh!TTZaq!MTHsc6R1!<5wQmC!@x1je)F(B%)!3j*mRz_maZa4kA1Z zmSZg$c2yutO4`&+|90T_DuR8iR)H_NOTaq~TxR)}mo=k9(;^sOSIunlB2KEP09(ww zB>#iTZXU|d_Tn>7R2Z;(UW*Q5#hnvci`kDfU*uk7uxkB<9!!Ws(IP_jo2z89Q z`cHO}eY2R81Du#wE4BSYGlbwHy8Vvyk#I(JTLpP@&nWady}nhYTn?GWz}u0Lvg+_J z(m+`Sj40mgQXP2u!pB!9y`Fo1<01ezt>9zm{IC4r44N0W-UsF=AcY7!S(PH_z9rC& zfv`Bzf!@5fJnl^v(dsi0oPH`Q>R??Nr|`#QG7Jz*js}XXeh+yMc;i_&5Rr%-)@9-C zFA_*f)ETe4m5!aptxvM0Khesb`5q+ne$P{$_kPW|PZ|6$HA(&b%JjLz?80aVwIwa; zLTylXN=lFWZr`=1GubhuH+#duB`A_x^>aAv8)*a8;W|bv$x_hzy8_r+ku9stJrn*7 D^Bo+{ literal 0 HcmV?d00001 diff --git a/res/gb-icon-256.png b/res/gb-icon-256.png new file mode 100644 index 0000000000000000000000000000000000000000..872eae6f07fd42af487b6d884b198f431543e6ea GIT binary patch literal 3289 zcmcguc{J3G*Z@oM>pR<;r^fovpSM|>pO~2#px4)Q zwKE<)OnLhzJ0v);vZ6#x{O|y~3yDNB>9q~iijvPobZYs~K+o#8$&ta{lP6E)=495> zs&%xrOihe6xrB-e-}8VVG-=d(2|Y$r9ZXQb`aHVeL!OMRRC7ZOtFt-sR>arI!HLm6 zJzbsALDs^|h{r`YCr5`M7*b198FqR<)8EI z?d>2Cu%p9;#`>zdnzF{as_$RN2(#qzVKyP+#^UT~;$8CG)UdI!k%qeZwa^ejFf=-f zSS+P4%fV}DVV0b97XpC1ygamYR8`bY$jZo=pF_DEl6H5)R>KXg&smC!iYO|{>*;H9 zKsivRX9BMJwKmpZU7SxG< zq2mMsp{}+vFyJZzAqR&`Js?DWmC`G6#_vHC@5aTGVj`Ox>;4c``6KC0c?rdXUlxr< zoAQe3a0~nS`C9WyzRrA+k^U%0LMKB^!^hj}=8bC)538wh2{zKH@(OZhRz_AfCYBhJ zDoa-y+PUO{SE-%nppaRvPr#s($+D0-TiGnrH>Bu&_T@`Hcmc#E0Yse0$zgW;O(8{p znEcc*>+IRHPo_edzwc81hP|x=u(&ZSM*njUbh>WEyx^r4XJN?mcLque_wPv^JNfyd z>!D!MAl<+Z7y>9M$v_Y(+;I_*mB-NW+_()T+_f))0O)Vf&XKOT=T|+IeXjb# z4>~b7TIdRKbFSw^Imw>#TEVlX{dMTnP7YcWqhr~}cqSyy0|Q{l3LdBK6{@B3kg$YC zDN+%8wnV_HlPs;xw{)Z-+k*K@d z_s2bEBqlb>dswX4PIX#H?*3b9ojUD#49O_$Q0VIUg@us4xH%+YwSBxcr9loX2mBv_ z>H^k?TzWjMFD^pTj19&CzpRuHlBpd-mzKYh`)E#C%eJY|^V*vaQSVZ5Qs{tVeBb(%pdLZ_K2KpKRf@JzhjpgB0`-2Yu! z+v}+)mq@1+t^2 zU4D0{>83INiz4=pSCxpb21i!Rw|29|bz>XX4aP(EW$jxwnb@szflz_9Uqcdd>&anY zV#j=ElM#&{ zRD7#UpReMM%cZ38;bQ;R-A1QCy|LFJ!A}x?G z$Q>%_TMWY`E}TFG(sn6_0Y%)TZaYzu6U*{|O*;W(&AXHFP#MJ6#4CkD3TVR z9Sn2f+Bez{R+ZE_P{98HMVnUgxnCo_Gmu!*4z$1+<>i_!?%46RX^0Yn*RHZ2qP8~Z zWplSt`9p|`>`#T;a-{rRIBKL|Zgj~@)nW5C_3ECJkMe?e7$9G^3?(c*jSl`xHFj0H zy7H&nhRgjlbgGmOpgsCVWOqR__^pr8?Eto}NDXHXSI(W(S7Q&r5>kAu%x{xR ztKYpBhGYD{YA-%F*k(f3IxjGDT`WP>+(gY0%~u_d43`W}E58fbL?5j+{Hb&_d#=t7 zIDUKU?W=oFH1@=;-5tk~pVM|s@l33n#Jj(Xmaa1gJKr0vlnX+HnPlFdt4dHMm;m1! zWX3k}=A`vldcQ6+21!i2NI==d-jc;kPP);C9~}y^&*JIcP8rF72lA>>=5X6{YN;8* z*e>CzoiO~+uqf`7t2N&q<4mb5j?2kZYuzj9}Ub`y8xhZ=s)#WaxkAe1N&dvL4scux!7T0A9nHbtlXWRP%J? zgyCcSbxFp^`-Xz!?#j8TXuQcO3Aue2mE?5z_3|K~mz}adj|=pRWdB)fDsuS<5S{*U*7!I7%AZk(-Aph9_u!Tv z0&viLz6|pc24_+rVSVRb596&Oee7ppatMzOxXVTVS1OH+RhzhQM6%!*dOIMDoC1;w zgl2sVFVH-OCeAFrIYxIRYB*vvQC}K7fuXB+)e-yFqFkc$JP(_AenG!DQN&5FxY+e% zJdzlF0cw-@Yuu?Q9ljP_7yP@M%OhHlPaufm7!jtj3QERQx}mev33*D*2JhlSqsZ#ub}nEm@d1FXz!(M2Y>_ + diff --git a/res/gba-icon-128.png b/res/gba-icon-128.png new file mode 100644 index 0000000000000000000000000000000000000000..53d17aba2221bffcd03de602de223a7324816809 GIT binary patch literal 3211 zcmdT`cQD-D8vd=iR&UYE>O@&YTTx@JwK|CwT@a#oB38H2WA#qds3Gwo+7}_ZXbB?P z7wr?GWfA4deD~hD_n$j+?|=81Iq!MibKZ02nP=XabFc<_NJ#?C1wE=5jG@h`<>HL)|->GO&f zBV!9PGDsX2R}nQqPtV9m$C8p(P#rT}6g8IP{;nusxGHL@JaVi&d?L?lpaL@qWfgWd zj0m>Lz7|75OiD>kOGHSV;okuQfs|l6m64Mr!K2whT?%4a=^3Rl4=dg8#T%+Rd7CGf zhKxGuhgC*T=KH*V>RzAX)m-R5WUS_5gASAx)hG=edmc8Dr?2c#=sQ?e-mEHZ5b0Ew>)BuSc-#`{Lq&*)|))C4~?Tu5$<93`4ar_ zIJX*@z-<~zdZfIWjjapLzb(qSoPmZV&^m*M?Isf)hc?^_^PspCGt9{>V5RMU?X56W zx;SVg+_5Ohv+0q0V6I0$3k!Q*$Xg%3C;pb{n8+kb3K|srzO7CWLiQdbBXfc8`*goH zNkL^=YDSq`ir9oK6v{x1PvQBfcTL>1qJ(x*N}j8mzq-1XlZ#hzX`{KhouGi|Q@1+H z`;O7EX)4N^dV2TRSh?(x;nhjQ)yYGZ)n&y$VS=2n(8qCHtO9vn{UyO82_6mHYyuME zGAKn$7yalbwk6mH^~OqW8XD-_{AyiAd&Di%IG38tN4-|Rx&d_E{0NlO*);?FjP#6w z+_a+KC<)F$D(>HO&*Q}hR`6$4TQ8U{9i(^+!Tz5=&|5{a20h%1(RyM&bWp!=ce;0c zJzf5i??||rJh6|n6uNZQ>Aep>Jw89&Zz0;V2C?lc4!;xy~jG zrVIns?d0J2NaE0hPCRF*zEq%CuhQ>4qO~}GVRA57NGm;=8-Xx<8j0z|*BkD1BBpfI zL&oFYG`#BLWZRpSh~NHix;&&k6v%D ze*UbX5ZJW6IAC$IIl5D80eHS@eCa0O5@hOYNh4(GYid2UYwPSFIf8}JriLoiYL}VW zKV!(PX&i0?MT08sZpa2uCHckm*?BFUMme>z!W_0`O7Txk!V_E1jZJAZ>vanxi)VJ! z4u4Vwq`p~Liz21WmfP5W_wH2;-+AmrT{gEn<)W&dgWb2)gp`dDHkiwI#nRG08{0Of zBK5fx(e2|BFd{dC7^1VZA7h+~9QgrHc9B+X{dEd?pq~dkv_iF=#Ti? z9t_M>VRzORUh$LaizrvyT4*KCGnMFys}zUeYm7OB^k+4960{vH4DvSBY@ejVg%@7tb{@5*2egGryD_LcjmX8&q359mY4b4^PcNN)C%{R3EI8}0RE3c|% zBF7M`N_AXGojCO>IbKP0wWFJ|C~SLIBUS*mIgtGcL0{^{-r~hGdr#gTuL^2q4U{LN zBES=i5FnR#Hc6UX(;`t-#QbDOyD+`N4p2z&sZ zSDh>aRm;={+8lvcDQJm$l5#N*LYr`tgr*PFSfHXRE0f(NTw5o0q#S3b1}wS&VIU&~ zK>UzYUTbcu#-@DG@nLJLt(l0b4J(FUm54LkL#wM-%DhqH5*y#geF>=b10Mrbdf5tb zE{!~ZFKf>&fa{1x6anckBJWoLec6`}$MEr_+@CuRgIiEDJ>j;5$gO%SC6P?9aI=yY zTR?%;Q^LMAHxJ8|(*z0e82h^ogPCq0J_%#ST5e6SFT+SxslqYr(@Mtz2XA&}`NLl= z1ixAFI~Uo3sor$u*^H2NNL(a_EK_4PUZ0Wn;q?<56Q41mxo(T~x`nksjnQjq?b8Ev z(f;bdxnztd>;A=73iAyPQyVUm3iRvgr^PAz>$+C4P<3FUVKFozKLTul{SZemF&;E% z01AMBRM~1X<0G=NZuJ8$5AkJLeWus$fI+`utR07n3NAzJP|W#ukZ0$LV%IdN&P4}u9wOXk_f0QXm5tZL)$>IUal zF<+@03*HJHxVb?vjBSiwxW;qPZxHtu7BfTOjO|MqGhB#>JLT;rCxC?X5co*&Fc!9n z9z<7Oj!LP4ReKjCJ7;T^*Xpn6C>t>Z%M`X+4BOJKZ5u3JF+dL_D9aiq#Cr@f2N1loC8Uj_Oxx9DOXMfE zjW(SBkvM(2yf=P%PX2Z>CO<>a)-01LclgyVJh7FH;yAlX4l}zP@xc0zxHpCk+J$SD za^WRBcalmU&YgKl+@^S$co6Ctg7E8GE`HU1+U309?yMYKCtAKNWI@Y__c zi?1z+KO0S@pgqo+k@K*590q#9K!DkcO*|Fc))Ab)0L`cP&fsD;(~gI4w2r>;lY#1& zZj~q1mYl|7@i&g12BAKK2v?3*3rJWV(GC$ETZa194#)mJOmx!`u zLwfQat&f|YFig|e{n(L1PEx-gQ}8Z7O&r@$KTO`Zlbf0YJ zu9gkyDzg~+W6?s+#aMqs7Uet~GQq88?ILk^4B3*EO=dEXQ$PZ57K3*)lKS8YcgB?( ze^04f47RPz;mF%865^|0+_A)a9$nFW`r+xmGUs<=5{D Mh0xQeSGSG)8>k=17XSbN literal 0 HcmV?d00001 diff --git a/res/gba-icon-256.png b/res/gba-icon-256.png new file mode 100644 index 0000000000000000000000000000000000000000..bd7fc64ad5297e49ce4af6b22bd47029740bafe1 GIT binary patch literal 5589 zcmdsb;XWmSlo{lO3E-fwq00io4N(KM``WJ!#Y{)-yt2HwM00^L` zWu&a?rS&iKe+Jbt3;(o~RWxV24@gSEUEB~KqUQsHqIscW7!b^ySAzwjMhK#u^Y}!F5l!BNp;Z?(jsQFyaArJ^eh)>Ew`?M-@ z&cigmJYuRed{RNguqbrI#W1QWYSz;%k%^j9f={(Fe6}?BTfWZ-2n5!ZwMRTp$9jSj z=~Rw~LzwLKNn7RxKU6aQRb9AaX`0XHK$~n127!X$!LraP1Gtl$QB3fQJY`W+a}_Vx zQ$@ItJ{={isnVKWQ9-e`mOoDIy+5>E|cz6X249&wMk_wCKbMrsQ$|;ePQ>LaD z#kf{wz3yVC=T}fvb8_~MiOujugmH56(9tneznT4zIxHmxFS(ScDy^$doP2HdmYtm| z!M!1`pgP{})B8i^%7(m(rYu7RXN%|dre-$UI>s;T+-#JB@(XLs<$O|I+e51sRTC4pR2)#X%1(O!>*m zJ(!&}w!I1aPa7{pS2*1K(}Gu3{wqq-ZV8HylysK|08%-1C3&NO<->dzGjdhh;jb^q zp-+ohskg&%ajOz&OMl$3@7o~|sqzRoAr1M@MAq#$KHRtwN_yZo8{sUj(1r?npN{Eg!9-SV_c1jt_2w&jK{AUH#IW2jx3CTaI4*R{dVC>m_N$J_Gtn|Oe zK;46=s3;{RAtB-7oUxCuFP*R>N~2Vzy|c5kZK6 zv#qT&g%;-8hZ3}3T{YUNtz+Qjb$7qJzTdSVc$^+R>khOQe)a0rpTonuaBCAeDXHfx zIo9WEO^7?MHsf`$-L~}0Aq-m+?T`6e?sKZv_Zy?uKtdM>(a<_ct;`cpBCW_Wt=oBB zeiz^vIO#WVbyi8RDagAjRH5ix7XmqM8^0|QRdqbhffWA@j9FIIUHpKhGhQuMlY%YVbJPD#@ z$BFJq;_W;fDq5G-1A>B_Pz(PGPp)cd%X|*OfSWd&D=0m~8d|FL3~k%BGvY0?7G74d zpd5Kyd+hXQ;gAd zfflvoSC?-mtyV$y$sbRfnXc-Olx@0iZ%j<{A_n&Y58^e7rj9#&{=7CkD%fSZups)`P|aQ2aiLM~l=?_C>F<;0A!f6m z``Bf4|Fvs|vO;X#{wZMESuZnkY4Y16xH4=BYu&i8?Bj2Tm(e}Ov)`^dr#DuymOARe z0t;W2Fd~g7ku%o1Vh`q~rC*HLezd+jfG&4V*~0PN4uez_t2~h<3IgBXULi%u-dY*< z{xzJ8PLkPu5jc)hO|-9+&=pHIYxX@v<3FPM%u7Tp=cALtFmp-yD?mLk)(7zNwkv^Bcl2F6ff>ey)V8 zU~0aMkNLj5RMgGtnqu_pc>O}4oeL%?*ur(YS#f{6py~>>M#|PDy|RUMl6*I3X_vJJ z;c1!&zQ;K#Y`Zd0I}0Bx&M#XyrQ-qb;Kq43SieujGBFx#&>6$2mQJPj872Ro7PrIB z3yW;z@|a=E8dCiQ?P6{mbF%SswhA=1j9dR*dx_TAsvcWnuqd~%FP4^(>#$rb<&S#N zXCc=`W?ATMwYNRDRO?^DhR`If7kXQ8-4F~? zjEOM;dM4za#I7^@iGT31A<>_a9R)GBIeV)8fB(A^IaijSUBqkst$#tIjcm?KUId+8 z6(`DwmF*@%)D89BS2AK3G50QeFh=LJ#oYcHW8e=*93$`6+WfHgbDZ)&{xdZNTOl_@ zXp#YMLd5yeMluZjqb*SWVlg6t891J{C&+EebMydQ?xr3;l$LHc3{AR~tN!xG08!%} zYb&@S6X#cfGQprHXtcfRuqGiS!?vVEVOcI_ZGIVr!Mu(>JqZcLvwrx){)=223Gs;N zhSTKQSUZFPsx$OHIkukDIBV^+lb{q)Ih3;qp6OQw9Wam>?O(4@^N_h%i|J{(%-K?G z-iAv_%LDWo1vp__T<%yjb*;BG>noo7G`nxR~Vu?9> z<}Fs~?`R-`M7vB?-YGnzZ^=1x_$G%5g&`Pr(bDJA$GCRQZn2Ysx&@&$okhcN@P3?w zv+h4ldaT0_eBtu5^~zP5ceVP|>`BK%xVYs24=-3xqkk=~i{@ zg@9!bpT;w1VS{NqaZG|fd1*j=`^v9+_uc3JjFNQNKTIqQG%RbJf=4_g6M7o(jH<4^$adV3RGy#AEwI?#399^LE=d8XL6J0~&OVP?HlJFnV z7RU>m2<1Bz+uLN@QxEr`6Q4SXa`XmMgN`K{E*~jf$`79u&)-*_lBQn_pyD8{ne$IMF4@ETW68o9N-a|>F<5<~rGOBevuQ*-^?SEnPCw2DSvQIY zz-y7LuRClz;slzf5{4nng*k#2t^7RPR~@^^brez{0Zrzv|F{g+Orjztyfwi>t&nDA zMo54V!++j?cFQSqTN@#BOyfZmJ($4Ne)^vj8YuzZ0l?nSL8%b4OJ~c5Ngnx#=k#fu zf@4}RB8tbjZ?R9hTN_jYI0OLBic7b+(*ZQr!6)=;3buwt!U=Cd+4`hl&HF-OMhCp( zI0X#mK?uAg=iC+U)cty_6RY1}e_k-|^`b!y4Og*~KYrGyop_w~8H$7%pcyO;z@r>( z(glCr|CJTT=nend>w=Utu8up6-=`XEQ9RTr0!pRT4RcWZ&bV&NL&N?V>W1L$5Ns|lH@jNam=s7p(ykOtG;=k=(5Qkqod!i4Vaf_ z>I2{(L@RnZIW;-lM(_nEGH$b%NG8grDHY}001TI&!^*^QB6wl86xS7wXS@S3D@w}} z5Q2HEQw;5J(r=zIuOZYWS*a7SZSnYl3m*Z>8?pWR!gOCY@u4#n%-H?FegzQuHds$f z_xP9m3d7{!osO625Erma#W>U{97IggCu#|Z{N5zfIN1{Ix@yK(lTaxC9r*SA@mHxU zDENCU9_n?^+FOEtS|%HA^dJ!i=Q#&n&r}{qDEQxH@dE@MPj+085cW0pkbsb zc2*n9dG$sVFCBvlz^N`jl^#uJtYBl(7X+vP;z;MG-LS0}oJL zeY<0TEei}K`yCQ~Z~U&>Jfx=4z#b%yvS1~>y?JAFX5J+NpZGj70N!9;N$CBE;1lsv zhEJV$OM^g?it#(PXP9YIKJj;m$#jZ?TxGY=cd@jNEcPHh2isp`lRe|b(c@X})-DQg z+c%A2ElSPJ!%&mM1^RXE0jv#Od^(zjUkX)ex{(hSu_u77giyN~LcSs6w*KBXiwRi2 zUk+u&!vnN04Cp^18aJ^zq-=ew;sCQ?RKo*N3nud+l9c)0xb;smCZOf;y^*pfV2GHn z2MFhdfo)UufyhJ#d7-PWWB2J2cJw~ytG)?sbW2j$|v^}+%%g;l4CX_ZW zQ_8bLYn%O{NB0w(Og?}11H=M;2w?ku)wDx5jOs7fe{?|A~l6 zW#1}4IUdyu4oIGy*7t@YB_bsTEo*^42L-bNy(WKNLx$w_WVq-EA=T<%uI-M&wu$_# zGf22g@LWHY*S=*e5h}DrP8&UB$!gXqqXBj(`T-1Accl zRYbnKL{@A6(FKL!1Y?41AIV@_Rul4$_or4`I7mt4m)V1hL zsZqnckx45kZqbr#ZHibpo5TAu^EYM&6?MEbpSajZ*f7L+V>sBd2SN7fTl2)2O7iN( zb|i!`tfbiQ>}riz{el4QOb!0DpuLt@#-NdMgL2yA!t(QqA>rn`UZ~^6+T&E-^}}QL z<2~}y>E}$}B&il*en*B)@E~X6xn{2yF7;0bth=5?2TK2J{wF^!3l@ay1XzARWs}9p zZQ%EH>x5mwU!3aD0X27$3pC4i-mw`G-z-PJO=HeV65n{Mw{Jmo?fmIi{Lm0qnv3wx_P^3mSXhdrLQ#d!z?=Lxz2w-Pbf5>L z6yv-2f9fE}LuJc_t2F+JlS%T@5(POd^g$S|lMy`r@3p$5X7*2fK3&qxsUDW<3iM($ z^Nn_vE%e5B{nH>K>RfhwlWTI)<()9Xnjr}1^v5+*&%-1`!zxccc-7=D^#b;l8RV_R z2E`X2@py`k$MD_PC%42qM+~3-L_2iVvprD@jzG_DUp|RU+CahJIT##frR8$A(umMa zn0R-_tB=C-(0`p8c`3sGJS&22(BdN&QCXKm1DzO#iTEzybnKI?6G1- zzN1@G-8I+mb!M@m*`i7rH2AUwM5*9>Dw`iaSHgjP+)3_1XttWz(|VLejh)5+#s5t@ z&hh3Edyb6p>@}kXB}4xxd&azLfxy{PVESL1&Y0Ozjw!6ZTvgSdb@WZ6?8uvV0o=C! z9qbjl(ab&zH{jZ8ba|IJ^d*VHgCijh`RCAZOYF=iA?BHMyQccI7s!>=euryOh9C4j}9#hQ<4O!4TKbB)wspsQMt>&%rO5SN1 zdCGj0^H*Q4tAbm*>2rwO%V$fXZWXC{$6^_k4iw+I4^8L`mG_6X`JiW8Qj0au1^i;3 z1y{PrFG!*o*UdE>b zN~KX@sJ^$MkDA7ZMk!YTT<)G30ga=X=d+4wwIjS)s@&>)^>{FR+Lc9hD}9yGL9+pG zf+(d~0RfxarxRJAha)Wbf&iQ%%t5BFt_66h6Gw;}~ zOmfJJrQ-GE+LM(aNco;XNg`DRcDq^{z2yV(+4ww0c@B*pt{S$0-(3bC!M# zsBZ40?U;4Fc`JScLdJza_hgaNisx%q0d2+d%8yxTEwjB?`BYXFH*Gq~uLHiJ>l3W$ zq83z6cNbHf_*n#oudd}N8K|yyu=tWBKEw$Pbl0A$=DFz%HxIgtb + diff --git a/res/gbc-icon-128.png b/res/gbc-icon-128.png new file mode 100644 index 0000000000000000000000000000000000000000..f22938d1601e4a9a1f278fab07fc38d1e1499758 GIT binary patch literal 1660 zcmc&x`#aNn9RGZ`#j>Wkq_NHB7TVazvP&+T?Tj6yxl}qu9E#9FZllc(9vxkfa+_Rg zNK~g*giu5|&T&f$$wPIzlP*q#qvxFe;k=&b{eC^K*Xx(}^Liik@)V#o3^V`$Xg61$ zXoY3p2MJ%w??T#x>R$#gq(3;D z(pi-{5aK0e+dJhQz6pmTRwGfi=8l|AqTOzXFQgCV#N2=&n4S(cHMF86=04NPwIHFz zk;Se0rC(o%m=$?RDerZ4ao_3`Od=SY6K$%}1|)lnb=G2W>x_&HHd>PG!hO=6ZMPOC zw9+(sq?IWXiCnFvsprEDH!?Qc zOy*@rtCE9?v3mGOzoSQjOAT?x#za%`j$<1Psaa8%N&4ngitRS%P@c0ZYqNt1jvVcO za=kWzZ7nQ4++7ym0|DSb^Ki8B4E9Vm#BQLPu}+Gw(QO$UOe}W(a4^t4zBuU)UY}SZ z>4@<^$*^NvlWDe8`WD)c3Q2oWR3{ujK>!y9@N9r71!TWxao>M$87uPi28bz#Z6C8? zP}^?xvUPO7-If{Uc_7KfDG-trkS_qun4mt2PbxVM*XAFL&;@` zvfj|t=8)g&Kv_qolWJ*mrWx*6_)?CAKvOjV?da2u#shRmUZ^^-n|q8(ygxonLAIGL z8_+BfvR&;&=P5lvB37+=fkKHF-Fc0Mn`H7qtqU@M0WfEfruKIW#j0&~x>Q>-(M8ox zL;M#Y0Yn1dg)IA$;<)SfAT`q0)}L35Z&g5#EnSGq!Ys-;OTdw1pm%H0qgfGn@b&b% zntjg8NC;mN-;d_N%&t-w#Ier(d1{O`gjsC~4m=|LK5r5gS zB|=%Ogki-GDh^yPE%Haes{4$FaQ%wTq|gRmQ_r#CtKnE}B+xa|f6P4IgNX=#xS*Vz z#eE6s_$q@pEc;u4cS(^Nv?^lpa`FOGC($8z?C@L$AJL$c-cy7VcvEcj`oa$`T_`Qc zk5L~$5m<}2)*Hiu+bwi$)LvG2O+4W{)!O5yqw*JU<(WJCn7z=;&<3F${gdCAkkPH& zQ`fS)LKLCw>T4Vx@Xmd=%6{J~3Hn6TYWs8F3fb{p@v{pc(ahv~#}W22gCfgg^NrWf zecqUQ*9Jk$yLNDVeRuCNq3&#LhH?ha5-K5vdMjsB(von$JY;~vp~EcrogPS+PbA6@ zmBiZ{?P`K-c$1bOo%9Os8Zgv~IN9)g2+YgYi zuiI(QAF0A*&}T>h!6VH@@Q^EnH)PyKP1%e6SyH;NU99PITMJD7Jz8}F(C~HYJxC)3 z{O%Ps*(oe21Pv9(A)O{vS~O?`_c}nPfc_;VZ)YI4lI(I9d1MHVISG;28nQu5$=aTK z@bVO3pa6>8y}(P~A~S4QZd5~}tbSL3vJNd}WdxUs!~t9M;ye(w{SCJb3igwqwZwNU zzV^OlKUTc!r<#u^4n|7GcGat}E&DDP-8u7i=Dn(wz-7JsIE>h0g+tdT!01N;viIDw zTkLp0Wh=xgtFI15Kb#A>>8I>{KFe&9mk{PZKY5~1Mfhr%)#i%k%>Q~n+8EPBwNI3W zYp*l8e{IrNl6(5lD;&D2%ktD*_2ji@d03ID63-|o$}e|}buG!sPnvNS=E{xd?LVt~ WSJt#YO;0rhD{$j`@-A@$<^KT2XMUgn literal 0 HcmV?d00001 diff --git a/res/gbc-icon-256.png b/res/gbc-icon-256.png new file mode 100644 index 0000000000000000000000000000000000000000..37659abab78cadef7c453638421253d8d5169c81 GIT binary patch literal 3227 zcmdT`X*AT28va>_!7yVmmSiW(*b>>sHVs4evSrU+Ok_8iG7%ADODK|k&q$^$6CwO9 zVUWE811tar0D!~9*vJ|H=zgtq z01Lyf5m0S!3jp*aOEX(E250t*`F}xiX=7zP4U0CXr)MaQ8+LH?U}j?BjEu~7=S-IHG!4Bi2`NF(wG~Za5MGRi zBZPxf04@Sz28B6iJq&M?JcTqkYg2rC;JgAR$o_t`d#)2EI4`R6X>8xK+XF~hC3Sgp zr0YWi9kl3a@nDBkd2tOnv2$2WXHfy!+{iax7O`+Hfy~fXnn;s4pJGq*7!_$$()F5C ze3HCSp=*~Cq=c2Y*x_nt43rhsWF%$n(Scl?(ER95U+X)eS2C0&wcX7kb(PH@MN%&r z1~daIuBPGq2*LD_my+Vr`l{9vVp3o*85pRESsn0glYg$)_lK)oge^W0~q4{%GH!L zjP#7pt7+@2THWz}rVBuw0e%d?{SY{FACN+;+g;Rg|CPo%?~w6dah$$sZEge5tpr<= z*%%+2gOJ1Yz6avm5d6*n*!bn649D5D+ShJXhu`9}jHHFamlB!yk{C8*Kkc3GpuJf? z`CkXH&f=8>04#GRM*6l9Q{QG2?BEz7&?XvEoY=}`wXTquxSFvf|GvvczKq#WBZ&Y{ zmBopSKt*Moxzb8KHZF*tJ8PAZ;|udVh|QR8Z32O$qI%Y6Z^dr>h(Qib|HOyws*}n6 z9GxOuER6KGBkm$pbFGs}dfQLPEl1rjtn&C!K(_SkQ7Z=8r`(t4aS#*%WhG7sjsX&+ zb{B%zz{7^Qpn5KM4HgY-(WS*XE|+@k%zOU#&e zVMRJD<(WCC{*&kH?%x&nN9Z{M7G99eL(W*;ELCbM>PquwLbVgsl@F;+QlqA}>*y=~ zQTJbyI6OhCYF!|F6a8;T{~^@F0(;L^KA#SCm36IiH3AhHtE{nQzNafE4GM@mF1;(O z8^ii#J=(=9;N>vLAN%py_;2Y>-U)JJjpGI1aVx>xeV>~SN{I$0b*h=UHX%FLCZ3ud zdbg>xe-Dd&Gi&+9!8b9$Op}%y+;k3gd}-T!O$&c`)VrO}?&IPoD~_?rm@P;z({j$7 z|JfmGcof&xqvNwSRIn-^af|Yn>ERSsC;Ug=uHbXlC0dz3Y_Y+~iM-h75AIVNipBO( zrenn50V%)l{YMNkaVbP03zM=%sRCQ@4FL!GYRI{6e*mDi^?tWlnON#tD)$1X<$A=h z%s(Yb>K#H2qC6`fI8T`xyObOO$exUVAz~^=dy$w<{tPhYe3fQb%6SWp)?8x7k=B1o zP6}O;_?F)Y6iwuaIkTq)&cz(@(53gjce9EyJt$!kxuxj+a#be${<%sQg%kE7c0LAM z60aW}SHl$iwL$`Ax`mW>LQ)8)tQU;z(0Gb23XI4NqV}PyX##qi^;@w(8^!0Enva5F zcVjxDYKTp}MS3j>*xU0;FAu7-J=IbxF-t40p?!Wu`{G3c)lShj65k>YURSRfT?(9W z)K{tTry7nd76GUV`6b;Wkw~{!U}1YrK3ycqcY@J)KpKR$i&CWc2O=ig8jcoxV4)Lg zbbU43?1R=7$0E`>ngVA2pG7@J-!F+om_Bgl-Dgjo@Uw}-!; zbfu{-KPb$*TC2Ic(;3%FY`j!o9RMM2_lnCAJU<8Z`&#-$#WrPR%)}5{<2%Y~5{?dd zhZTjzx|VAEv|JyHzTp>*o@Ms~jS*amNE7)BXBsft3+D?Z__ygN3rrt4%>KRm?)v5C ze3^noY+>Y_q3-CXmx zKRf@P;w3!0AbNN)Yr@S8=q zMX!2KDxR=fN^#J*m+Jd@XrJ})L8u0Rg3XBh#S|R(%3!x1$92mV&?e&NgZCw=^K9!Z zf*#oQY#f)cE#S>^hzykhP;*~4m=p40ay$?ZW*#8OeSWnc^NDWK(#E5I^lsc{DZSE? zv-=kTM;nhAU!q||IN0zx%UCdk5fO+@4lggUr$=ZUi_RVH))*!G$6c2r;=hfS>PuL~|>N8d(2UcCS% zJc6BdtEj&^+tmq?OUg=6{F)A0$4$ZG{r4Fs?cw!x%@sOhgQJ}$7rXFr6EAF;_mvtu z!TK$t@ay>O3BdA@q28wd`CXsy=<^!nuQ4^FBe~) zpy|BDv~w5cP>rQ#vMHdHQ{E+iJ(&8mnD{*9gwh&q8Q>?%==_+ zhrzY^^7a!$*ZHb|fHSogl*r|)4*DG_f~-tl(nB+56^em=Rj>E{eyXE*C0!ZU_EK7$ zhCqcD^~m(pP&E5IKaFiAk9A%rdAJNu?+*U_Rv4Lt4on^;PB*Wr&bfLN%sgyCc^+s; z_c?20?KNnztLwcXuE;G)hL7Uk1+Rt^ZXD+G#K>CvrjJm?>4o Vi#e*k#r=09n4ry#Y7N}({1YZqn5_T+ literal 0 HcmV?d00001 diff --git a/res/gbc-icon.svg b/res/gbc-icon.svg new file mode 100644 index 000000000..6286714bf --- /dev/null +++ b/res/gbc-icon.svg @@ -0,0 +1,2 @@ + + From 179d6a723601a825f56e118703fd9528f6617623 Mon Sep 17 00:00:00 2001 From: tom_mai78101 Date: Wed, 29 Jun 2022 23:31:10 -0400 Subject: [PATCH 089/102] Powershell dictates the requirement where automatic variables need to be wrapped around with curly brackets ({}). This is referenced from the documentation here, as quoted below: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_variables?view=powershell-7.2 "To create or display a variable name that includes spaces or special characters, enclose the variable name with the curly braces ({}) characters. The curly braces direct PowerShell to interpret the variable name's characters as literals. For example, the following command creates the variable named 'save-items'. The curly braces ({}) are needed because variable name includes a hyphen (-) special character." --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f027584a9..56c3003a7 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ The recommended way to build for most platforms is to use Docker. Several Docker To use a Docker image to build mGBA, simply run the following command while in the root of an mGBA checkout: - docker run --rm -t -v $PWD:/home/mgba/src mgba/windows:w32 + docker run --rm -t -v ${PWD}:/home/mgba/src mgba/windows:w32 This will produce a `build-win32` directory with the build products. Replace `mgba/windows:w32` with another Docker image for other platforms, which will produce a corresponding other directory. The following Docker images available on Docker Hub: From 68ef5d3a5b32def3a07650d6bf6412ef6d5068ca Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 30 Jun 2022 04:20:30 -0700 Subject: [PATCH 090/102] GB: Fix replacing the ROM crashing when accessing ROM base --- CHANGES | 1 + src/gb/gb.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index 382ce85ad..3855918da 100644 --- a/CHANGES +++ b/CHANGES @@ -57,6 +57,7 @@ Other fixes: - FFmpeg: Fix crash when encoding audio with some containers - FFmpeg: Fix GIF recording (fixes mgba.io/i/2393) - GB: Fix temporary saves + - GB: Fix replacing the ROM crashing when accessing ROM base - GB, GBA: Save writeback-pending masked saves on unload (fixes mgba.io/i/2396) - mGUI: Fix FPS counter after closing menu - Qt: Fix some hangs when using the debugger console diff --git a/src/gb/gb.c b/src/gb/gb.c index edcd548d1..81d059b00 100644 --- a/src/gb/gb.c +++ b/src/gb/gb.c @@ -189,6 +189,9 @@ bool GBLoadROM(struct GB* gb, struct VFile* vf) { if (gb->cpu) { struct SM83Core* cpu = gb->cpu; + if (!gb->memory.romBase) { + GBMBCSwitchBank0(gb, 0); + } cpu->memory.setActiveRegion(cpu, cpu->pc); } From 11589d874f856c8c538ebb905eb2c53d82a6b779 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 30 Jun 2022 04:38:50 -0700 Subject: [PATCH 091/102] Qt: Fix leak when opening a ROM in an archive --- src/platform/qt/CoreManager.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/platform/qt/CoreManager.cpp b/src/platform/qt/CoreManager.cpp index 05fccf1c2..b5fc3e413 100644 --- a/src/platform/qt/CoreManager.cpp +++ b/src/platform/qt/CoreManager.cpp @@ -62,13 +62,16 @@ CoreController* CoreManager::loadGame(const QString& path) { VFile* vfOriginal = VDirFindFirst(archive, [](VFile* vf) { return mCoreIsCompatible(vf) != mPLATFORM_NONE; }); - ssize_t size; - if (vfOriginal && (size = vfOriginal->size(vfOriginal)) > 0) { - void* mem = vfOriginal->map(vfOriginal, size, MAP_READ); - vf = VFileMemChunk(mem, size); - vfOriginal->unmap(vfOriginal, mem, size); + if (vfOriginal) { + ssize_t size = vfOriginal->size(vfOriginal); + if (size > 0) { + void* mem = vfOriginal->map(vfOriginal, size, MAP_READ); + vf = VFileMemChunk(mem, size); + vfOriginal->unmap(vfOriginal, mem, size); + } vfOriginal->close(vfOriginal); } + archive->close(archive); } QDir dir(info.dir()); if (!vf) { From 96c137c1a2f2f7f0f9dd5f54ab92b117e97e2324 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 30 Jun 2022 04:41:50 -0700 Subject: [PATCH 092/102] Core: Fix leaks and clean up mDirectorySet --- src/core/directories.c | 159 ++++++++++++++--------------------------- 1 file changed, 52 insertions(+), 107 deletions(-) diff --git a/src/core/directories.c b/src/core/directories.c index e2e2d2c9f..63c66e564 100644 --- a/src/core/directories.c +++ b/src/core/directories.c @@ -10,92 +10,53 @@ #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 void mDirectorySetInit(struct mDirectorySet* dirs) { - dirs->base = 0; - dirs->archive = 0; - dirs->save = 0; - dirs->patch = 0; - dirs->state = 0; - dirs->screenshot = 0; - dirs->cheats = 0; + dirs->base = NULL; + dirs->archive = NULL; + dirs->save = NULL; + dirs->patch = NULL; + dirs->state = NULL; + dirs->screenshot = NULL; + dirs->cheats = NULL; +} + +static void mDirectorySetDetachDir(struct mDirectorySet* dirs, struct VDir* dir) { + if (!dir) { + return; + } + + if (dirs->base == dir) { + dirs->base = NULL; + } + if (dirs->archive == dir) { + dirs->archive = NULL; + } + if (dirs->save == dir) { + dirs->save = NULL; + } + if (dirs->patch == dir) { + dirs->patch = NULL; + } + if (dirs->state == dir) { + dirs->state = NULL; + } + if (dirs->screenshot == dir) { + dirs->screenshot = NULL; + } + if (dirs->cheats == dir) { + dirs->cheats = NULL; + } + + dir->close(dir); } void mDirectorySetDeinit(struct mDirectorySet* dirs) { mDirectorySetDetachBase(dirs); - - if (dirs->archive) { - if (dirs->archive == dirs->save) { - dirs->save = NULL; - } - if (dirs->archive == dirs->patch) { - dirs->patch = NULL; - } - if (dirs->archive == dirs->state) { - dirs->state = NULL; - } - if (dirs->archive == dirs->screenshot) { - dirs->screenshot = NULL; - } - if (dirs->archive == dirs->cheats) { - dirs->cheats = NULL; - } - dirs->archive->close(dirs->archive); - dirs->archive = NULL; - } - - if (dirs->save) { - if (dirs->save == dirs->patch) { - dirs->patch = NULL; - } - if (dirs->save == dirs->state) { - dirs->state = NULL; - } - if (dirs->save == dirs->screenshot) { - dirs->screenshot = NULL; - } - if (dirs->save == dirs->cheats) { - dirs->cheats = NULL; - } - dirs->save->close(dirs->save); - dirs->save = NULL; - } - - if (dirs->patch) { - if (dirs->patch == dirs->state) { - dirs->state = NULL; - } - if (dirs->patch == dirs->screenshot) { - dirs->screenshot = NULL; - } - if (dirs->patch == dirs->cheats) { - dirs->cheats = NULL; - } - dirs->patch->close(dirs->patch); - dirs->patch = NULL; - } - - if (dirs->state) { - if (dirs->state == dirs->screenshot) { - dirs->state = NULL; - } - if (dirs->state == dirs->cheats) { - dirs->cheats = NULL; - } - dirs->state->close(dirs->state); - dirs->state = NULL; - } - - if (dirs->screenshot) { - if (dirs->screenshot == dirs->cheats) { - dirs->cheats = NULL; - } - dirs->screenshot->close(dirs->screenshot); - dirs->screenshot = NULL; - } - - if (dirs->cheats) { - dirs->cheats->close(dirs->cheats); - dirs->cheats = NULL; - } + mDirectorySetDetachDir(dirs, dirs->archive); + mDirectorySetDetachDir(dirs, dirs->save); + mDirectorySetDetachDir(dirs, dirs->patch); + mDirectorySetDetachDir(dirs, dirs->state); + mDirectorySetDetachDir(dirs, dirs->screenshot); + mDirectorySetDetachDir(dirs, dirs->cheats); } void mDirectorySetAttachBase(struct mDirectorySet* dirs, struct VDir* base) { @@ -118,36 +79,20 @@ void mDirectorySetAttachBase(struct mDirectorySet* dirs, struct VDir* base) { } void mDirectorySetDetachBase(struct mDirectorySet* dirs) { - if (dirs->save == dirs->base) { - dirs->save = NULL; - } - if (dirs->patch == dirs->base) { - dirs->patch = NULL; - } - if (dirs->state == dirs->base) { - dirs->state = NULL; - } - if (dirs->screenshot == dirs->base) { - dirs->screenshot = NULL; - } - if (dirs->cheats == dirs->base) { - dirs->cheats = NULL; - } - - if (dirs->base) { - dirs->base->close(dirs->base); - dirs->base = NULL; - } + mDirectorySetDetachDir(dirs, dirs->archive); + mDirectorySetDetachDir(dirs, dirs->base); } struct VFile* mDirectorySetOpenPath(struct mDirectorySet* dirs, const char* path, bool (*filter)(struct VFile*)) { - dirs->archive = VDirOpenArchive(path); + struct VDir* archive = VDirOpenArchive(path); struct VFile* file; - if (dirs->archive) { - file = VDirFindFirst(dirs->archive, filter); + if (archive) { + file = VDirFindFirst(archive, filter); if (!file) { - dirs->archive->close(dirs->archive); - dirs->archive = 0; + archive->close(archive); + } else { + mDirectorySetDetachDir(dirs, dirs->archive); + dirs->archive = archive; } } else { file = VFileOpen(path, O_RDONLY); From 84e60e99f465022c08b2b3b22f40fec51a8ad437 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 30 Jun 2022 05:55:56 -0700 Subject: [PATCH 093/102] All: More warning burndown --- src/arm/decoder.c | 3 +++ src/core/core.c | 2 ++ src/debugger/parser.c | 3 ++- src/gba/gba.c | 7 ++++--- src/script/context.c | 2 +- src/sm83/decoder.c | 3 +++ 6 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/arm/decoder.c b/src/arm/decoder.c index 8fef6b18f..e75023ba1 100644 --- a/src/arm/decoder.c +++ b/src/arm/decoder.c @@ -190,6 +190,9 @@ static int _decodeMemory(struct ARMMemoryAccess memory, struct ARMCore* cpu, con case 4: value = cpu->memory.load32(cpu, addrBase, NULL); break; + default: + // Should never be reached + abort(); } const char* label = NULL; if (symbols) { diff --git a/src/core/core.c b/src/core/core.c index 0879f9254..931b7feda 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -357,6 +357,8 @@ bool mCoreTakeScreenshotVF(struct mCore* core, struct VFile* vf) { PNGWriteClose(png, info); return success; #else + UNUSED(core); + UNUSED(vf); return false; #endif } diff --git a/src/debugger/parser.c b/src/debugger/parser.c index 72eae1ed3..4af61a14e 100644 --- a/src/debugger/parser.c +++ b/src/debugger/parser.c @@ -782,7 +782,8 @@ bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tr struct IntList stack; int nextBranch; bool ok = true; - int32_t tmpVal, tmpSegment; + int32_t tmpVal = 0; + int32_t tmpSegment = -1; IntListInit(&stack, 0); while (ok) { diff --git a/src/gba/gba.c b/src/gba/gba.c index de79671c5..cee833c5b 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -583,6 +583,10 @@ void GBADebug(struct GBA* gba, uint16_t flags) { } bool GBAIsROM(struct VFile* vf) { + if (!vf) { + return false; + } + #ifdef USE_ELF struct ELF* elf = ELFOpen(vf); if (elf) { @@ -594,9 +598,6 @@ bool GBAIsROM(struct VFile* vf) { return isGBA; } #endif - if (!vf) { - return false; - } uint8_t signature[sizeof(GBA_ROM_MAGIC) + sizeof(GBA_ROM_MAGIC2)]; if (vf->seek(vf, GBA_ROM_MAGIC_OFFSET, SEEK_SET) < 0) { diff --git a/src/script/context.c b/src/script/context.c index ad4e445fc..84847983c 100644 --- a/src/script/context.c +++ b/src/script/context.c @@ -295,7 +295,7 @@ void mScriptContextExportNamespace(struct mScriptContext* context, const char* n } void mScriptContextSetDocstring(struct mScriptContext* context, const char* key, const char* docstring) { - HashTableInsert(&context->docstrings, key, docstring); + HashTableInsert(&context->docstrings, key, (char*) docstring); } const char* mScriptContextGetDocstring(struct mScriptContext* context, const char* key) { diff --git a/src/sm83/decoder.c b/src/sm83/decoder.c index 1240d5841..819576c26 100644 --- a/src/sm83/decoder.c +++ b/src/sm83/decoder.c @@ -413,6 +413,9 @@ size_t SM83Decode(uint8_t opcode, struct SM83InstructionInfo* info) { info->op1.immediate |= opcode << ((info->opcodeSize - 2) * 8); } return 0; + default: + // Should never be reached + abort(); } ++info->opcodeSize; return decoder(opcode, info); From 9515de721287749550ec281746fc135f5fcd1cc3 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 1 Jul 2022 00:34:33 -0700 Subject: [PATCH 094/102] Scripting: Add loading API --- include/mgba/core/core.h | 2 ++ src/core/core.c | 12 ++++++++++++ src/core/scripting.c | 12 ++++++++++++ 3 files changed, 26 insertions(+) diff --git a/include/mgba/core/core.h b/include/mgba/core/core.h index b1440f2fe..7d72c7148 100644 --- a/include/mgba/core/core.h +++ b/include/mgba/core/core.h @@ -181,6 +181,8 @@ bool mCoreAutoloadSave(struct mCore* core); bool mCoreAutoloadPatch(struct mCore* core); bool mCoreAutoloadCheats(struct mCore* core); +bool mCoreLoadSaveFile(struct mCore* core, const char* path, bool temporary); + bool mCoreSaveState(struct mCore* core, int slot, int flags); bool mCoreLoadState(struct mCore* core, int slot, int flags); struct VFile* mCoreGetState(struct mCore* core, int slot, bool write); diff --git a/src/core/core.c b/src/core/core.c index 931b7feda..c4c3a3ce8 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -259,6 +259,18 @@ bool mCoreAutoloadCheats(struct mCore* core) { return success; } +bool mCoreLoadSaveFile(struct mCore* core, const char* path, bool temporary) { + struct VFile* vf = VFileOpen(path, O_CREAT | O_RDWR); + if (!vf) { + return false; + } + if (temporary) { + return core->loadTemporarySave(core, vf); + } else { + return core->loadSave(core, vf); + } +} + bool mCoreSaveState(struct mCore* core, int slot, int flags) { struct VFile* vf = mCoreGetState(core, slot, true); if (!vf) { diff --git a/src/core/scripting.c b/src/core/scripting.c index 480227b99..96f972438 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -393,6 +393,11 @@ static void _mScriptCoreTakeScreenshot(struct mCore* core, const char* filename) } } +// Loading functions +mSCRIPT_DECLARE_STRUCT_METHOD(mCore, S32, loadFile, mCoreLoadFile, 1, CHARP, path); +mSCRIPT_DECLARE_STRUCT_METHOD(mCore, S32, autoloadSave, mCoreAutoloadSave, 0); +mSCRIPT_DECLARE_STRUCT_METHOD(mCore, S32, loadSaveFile, mCoreLoadSaveFile, 2, CHARP, path, S8, temporary); + // Info functions mSCRIPT_DECLARE_STRUCT_CD_METHOD(mCore, S32, platform, 0); mSCRIPT_DECLARE_STRUCT_CD_METHOD(mCore, U32, frameCounter, 0); @@ -442,6 +447,13 @@ mSCRIPT_DEFINE_STRUCT(mCore) mSCRIPT_DEFINE_CLASS_DOCSTRING( "An instance of an emulator core." ) + mSCRIPT_DEFINE_DOCSTRING("Load a ROM file into the current state of this core") + mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadFile) + mSCRIPT_DEFINE_DOCSTRING("Load the save data associated with the currently loaded ROM file") + mSCRIPT_DEFINE_STRUCT_METHOD(mCore, autoloadSave) + mSCRIPT_DEFINE_DOCSTRING("Load save data from the given path. If the `temporary` flag is set, the given save data will not be written back to disk") + mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadSaveFile) + mSCRIPT_DEFINE_DOCSTRING("Get which platform is being emulated. See C.PLATFORM for possible values") mSCRIPT_DEFINE_STRUCT_METHOD(mCore, platform) mSCRIPT_DEFINE_DOCSTRING("Get the number of the current frame") From fa985d579859bf84a58ee9d162589d5d44aedd0d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 1 Jul 2022 00:46:25 -0700 Subject: [PATCH 095/102] Scripting: Add save state file API --- src/core/scripting.c | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/core/scripting.c b/src/core/scripting.c index 96f972438..97c2117d0 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -373,6 +373,16 @@ static struct mScriptValue* _mScriptCoreSaveState(struct mCore* core, int32_t fl return value; } +static int _mScriptCoreSaveStateFile(struct mCore* core, const char* path, int flags) { + struct VFile* vf = VFileOpen(path, O_WRONLY | O_TRUNC | O_CREAT); + if (!vf) { + return false; + } + bool ok = mCoreSaveStateNamed(core, vf, flags); + vf->close(vf); + return ok; +} + static int32_t _mScriptCoreLoadState(struct mCore* core, struct mScriptString* buffer, int32_t flags) { struct VFile* vf = VFileFromConstMemory(buffer->buffer, buffer->size); int ret = mCoreLoadStateNamed(core, vf, flags); @@ -380,6 +390,15 @@ static int32_t _mScriptCoreLoadState(struct mCore* core, struct mScriptString* b return ret; } +static int _mScriptCoreLoadStateFile(struct mCore* core, const char* path, int flags) { + struct VFile* vf = VFileOpen(path, O_RDONLY); + if (!vf) { + return false; + } + bool ok = mCoreLoadStateNamed(core, vf, flags); + vf->close(vf); + return ok; +} static void _mScriptCoreTakeScreenshot(struct mCore* core, const char* filename) { if (filename) { struct VFile* vf = VFileOpen(filename, O_WRONLY | O_CREAT | O_TRUNC); @@ -437,8 +456,10 @@ mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mCore, writeRegister, _mScriptCoreWriteRegist // Savestate functions mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, saveStateSlot, mCoreSaveState, 2, S32, slot, S32, flags); mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, WSTR, saveStateBuffer, _mScriptCoreSaveState, 1, S32, flags); +mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, saveStateFile, _mScriptCoreSaveStateFile, 2, CHARP, path, S32, flags); mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, loadStateSlot, mCoreLoadState, 2, S32, slot, S32, flags); mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, loadStateBuffer, _mScriptCoreLoadState, 2, STR, buffer, S32, flags); +mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, loadStateFile, _mScriptCoreLoadStateFile, 2, CHARP, path, S32, flags); // Miscellaneous functions mSCRIPT_DECLARE_STRUCT_VOID_METHOD_WITH_DEFAULTS(mCore, screenshot, _mScriptCoreTakeScreenshot, 1, CHARP, filename); @@ -516,10 +537,14 @@ mSCRIPT_DEFINE_STRUCT(mCore) mSCRIPT_DEFINE_STRUCT_METHOD(mCore, saveStateSlot) mSCRIPT_DEFINE_DOCSTRING("Save state and return as a buffer. See C.SAVESTATE for possible values for `flags`") mSCRIPT_DEFINE_STRUCT_METHOD(mCore, saveStateBuffer) + mSCRIPT_DEFINE_DOCSTRING("Save state to the given path. See C.SAVESTATE for possible values for `flags`") + mSCRIPT_DEFINE_STRUCT_METHOD(mCore, saveStateFile) mSCRIPT_DEFINE_DOCSTRING("Load state from the slot number. See C.SAVESTATE for possible values for `flags`") mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadStateSlot) - mSCRIPT_DEFINE_DOCSTRING("Load state a buffer. See C.SAVESTATE for possible values for `flags`") + mSCRIPT_DEFINE_DOCSTRING("Load state from a buffer. See C.SAVESTATE for possible values for `flags`") mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadStateBuffer) + mSCRIPT_DEFINE_DOCSTRING("Load state from the given path. See C.SAVESTATE for possible values for `flags`") + mSCRIPT_DEFINE_STRUCT_METHOD(mCore, loadStateFile) mSCRIPT_DEFINE_DOCSTRING("Save a screenshot") mSCRIPT_DEFINE_STRUCT_METHOD(mCore, screenshot) @@ -534,16 +559,26 @@ mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, saveStateSlot) mSCRIPT_S32(SAVESTATE_ALL) mSCRIPT_DEFINE_DEFAULTS_END; +mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, saveStateBuffer) + mSCRIPT_S32(SAVESTATE_ALL) +mSCRIPT_DEFINE_DEFAULTS_END; + +mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, saveStateFile) + mSCRIPT_NO_DEFAULT, + mSCRIPT_S32(SAVESTATE_ALL) +mSCRIPT_DEFINE_DEFAULTS_END; + mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, loadStateSlot) mSCRIPT_NO_DEFAULT, mSCRIPT_S32(SAVESTATE_ALL & ~SAVESTATE_SAVEDATA) mSCRIPT_DEFINE_DEFAULTS_END; -mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, saveStateBuffer) - mSCRIPT_S32(SAVESTATE_ALL) +mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, loadStateBuffer) + mSCRIPT_NO_DEFAULT, + mSCRIPT_S32(SAVESTATE_ALL & ~SAVESTATE_SAVEDATA) mSCRIPT_DEFINE_DEFAULTS_END; -mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, loadStateBuffer) +mSCRIPT_DEFINE_STRUCT_BINDING_DEFAULTS(mCore, loadStateFile) mSCRIPT_NO_DEFAULT, mSCRIPT_S32(SAVESTATE_ALL & ~SAVESTATE_SAVEDATA) mSCRIPT_DEFINE_DEFAULTS_END; From d053058ea37ffaf9b303916599193f49bc143cc1 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 1 Jul 2022 02:02:55 -0700 Subject: [PATCH 096/102] Scripting: Add boolean type --- include/mgba/script/macros.h | 1 + include/mgba/script/types.h | 6 + src/core/scripting.c | 16 +- src/script/engines/lua.c | 8 +- src/script/test/types.c | 279 +++++++++++++++++++++++++++++++++++ src/script/types.c | 74 +++++++++- 6 files changed, 370 insertions(+), 14 deletions(-) diff --git a/include/mgba/script/macros.h b/include/mgba/script/macros.h index 3833f6984..e350b4d5d 100644 --- a/include/mgba/script/macros.h +++ b/include/mgba/script/macros.h @@ -459,6 +459,7 @@ CXX_GUARD_START #define mSCRIPT_MAKE_S64(VALUE) mSCRIPT_MAKE(S64, VALUE) #define mSCRIPT_MAKE_U64(VALUE) mSCRIPT_MAKE(U64, VALUE) #define mSCRIPT_MAKE_F64(VALUE) mSCRIPT_MAKE(F64, VALUE) +#define mSCRIPT_MAKE_BOOL(VALUE) mSCRIPT_MAKE(BOOL, VALUE) #define mSCRIPT_MAKE_CHARP(VALUE) mSCRIPT_MAKE(CHARP, VALUE) #define mSCRIPT_MAKE_S(STRUCT, VALUE) mSCRIPT_MAKE(S(STRUCT), VALUE) #define mSCRIPT_MAKE_CS(STRUCT, VALUE) mSCRIPT_MAKE(CS(STRUCT), VALUE) diff --git a/include/mgba/script/types.h b/include/mgba/script/types.h index 7acb0c365..267f6b775 100644 --- a/include/mgba/script/types.h +++ b/include/mgba/script/types.h @@ -27,6 +27,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_C_S64 int64_t #define mSCRIPT_TYPE_C_U64 uint64_t #define mSCRIPT_TYPE_C_F64 double +#define mSCRIPT_TYPE_C_BOOL bool #define mSCRIPT_TYPE_C_STR struct mScriptString* #define mSCRIPT_TYPE_C_CHARP const char* #define mSCRIPT_TYPE_C_PTR void* @@ -55,6 +56,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_FIELD_S64 s64 #define mSCRIPT_TYPE_FIELD_U64 u64 #define mSCRIPT_TYPE_FIELD_F64 f64 +#define mSCRIPT_TYPE_FIELD_BOOL u32 #define mSCRIPT_TYPE_FIELD_STR string #define mSCRIPT_TYPE_FIELD_CHARP copaque #define mSCRIPT_TYPE_FIELD_PTR opaque @@ -82,6 +84,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_MS_S64 (&mSTSInt64) #define mSCRIPT_TYPE_MS_U64 (&mSTUInt64) #define mSCRIPT_TYPE_MS_F64 (&mSTFloat64) +#define mSCRIPT_TYPE_MS_BOOL (&mSTBool) #define mSCRIPT_TYPE_MS_STR (&mSTString) #define mSCRIPT_TYPE_MS_CHARP (&mSTCharPtr) #define mSCRIPT_TYPE_MS_LIST (&mSTList) @@ -109,6 +112,7 @@ CXX_GUARD_START #define mSCRIPT_TYPE_CMP_U64(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_U64, TYPE) #define mSCRIPT_TYPE_CMP_S64(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_S64, TYPE) #define mSCRIPT_TYPE_CMP_F64(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_F64, TYPE) +#define mSCRIPT_TYPE_CMP_BOOL(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_BOOL, TYPE) #define mSCRIPT_TYPE_CMP_STR(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_STR, TYPE) #define mSCRIPT_TYPE_CMP_CHARP(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_CHARP, TYPE) #define mSCRIPT_TYPE_CMP_LIST(TYPE) mSCRIPT_TYPE_CMP_GENERIC(mSCRIPT_TYPE_MS_LIST, TYPE) @@ -165,6 +169,7 @@ extern const struct mScriptType mSTFloat32; extern const struct mScriptType mSTSInt64; extern const struct mScriptType mSTUInt64; extern const struct mScriptType mSTFloat64; +extern const struct mScriptType mSTBool; extern const struct mScriptType mSTString; extern const struct mScriptType mSTCharPtr; extern const struct mScriptType mSTList; @@ -329,6 +334,7 @@ bool mScriptPopF32(struct mScriptList* list, float* out); bool mScriptPopS64(struct mScriptList* list, int64_t* out); bool mScriptPopU64(struct mScriptList* list, uint64_t* out); bool mScriptPopF64(struct mScriptList* list, double* out); +bool mScriptPopBool(struct mScriptList* list, bool* out); bool mScriptPopPointer(struct mScriptList* list, void** out); bool mScriptCast(const struct mScriptType* type, const struct mScriptValue* input, struct mScriptValue* output); diff --git a/src/core/scripting.c b/src/core/scripting.c index 97c2117d0..122888c1c 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -413,9 +413,9 @@ static void _mScriptCoreTakeScreenshot(struct mCore* core, const char* filename) } // Loading functions -mSCRIPT_DECLARE_STRUCT_METHOD(mCore, S32, loadFile, mCoreLoadFile, 1, CHARP, path); -mSCRIPT_DECLARE_STRUCT_METHOD(mCore, S32, autoloadSave, mCoreAutoloadSave, 0); -mSCRIPT_DECLARE_STRUCT_METHOD(mCore, S32, loadSaveFile, mCoreLoadSaveFile, 2, CHARP, path, S8, temporary); +mSCRIPT_DECLARE_STRUCT_METHOD(mCore, BOOL, loadFile, mCoreLoadFile, 1, CHARP, path); +mSCRIPT_DECLARE_STRUCT_METHOD(mCore, BOOL, autoloadSave, mCoreAutoloadSave, 0); +mSCRIPT_DECLARE_STRUCT_METHOD(mCore, BOOL, loadSaveFile, mCoreLoadSaveFile, 2, CHARP, path, BOOL, temporary); // Info functions mSCRIPT_DECLARE_STRUCT_CD_METHOD(mCore, S32, platform, 0); @@ -454,12 +454,12 @@ mSCRIPT_DECLARE_STRUCT_METHOD(mCore, WSTR, readRegister, _mScriptCoreReadRegiste mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mCore, writeRegister, _mScriptCoreWriteRegister, 2, CHARP, regName, S32, value); // Savestate functions -mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, saveStateSlot, mCoreSaveState, 2, S32, slot, S32, flags); +mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, saveStateSlot, mCoreSaveState, 2, S32, slot, S32, flags); mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, WSTR, saveStateBuffer, _mScriptCoreSaveState, 1, S32, flags); -mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, saveStateFile, _mScriptCoreSaveStateFile, 2, CHARP, path, S32, flags); -mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, loadStateSlot, mCoreLoadState, 2, S32, slot, S32, flags); -mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, loadStateBuffer, _mScriptCoreLoadState, 2, STR, buffer, S32, flags); -mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, S32, loadStateFile, _mScriptCoreLoadStateFile, 2, CHARP, path, S32, flags); +mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, saveStateFile, _mScriptCoreSaveStateFile, 2, CHARP, path, S32, flags); +mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, loadStateSlot, mCoreLoadState, 2, S32, slot, S32, flags); +mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, loadStateBuffer, _mScriptCoreLoadState, 2, STR, buffer, S32, flags); +mSCRIPT_DECLARE_STRUCT_METHOD_WITH_DEFAULTS(mCore, BOOL, loadStateFile, _mScriptCoreLoadStateFile, 2, CHARP, path, S32, flags); // Miscellaneous functions mSCRIPT_DECLARE_STRUCT_VOID_METHOD_WITH_DEFAULTS(mCore, screenshot, _mScriptCoreTakeScreenshot, 1, CHARP, filename); diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index 24ceefec8..90601db94 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -335,8 +335,8 @@ struct mScriptValue* _luaCoerce(struct mScriptEngineContextLua* luaContext, bool value->value.f64 = lua_tonumber(luaContext->lua, -1); break; case LUA_TBOOLEAN: - value = mScriptValueAlloc(mSCRIPT_TYPE_MS_S32); - value->value.s32 = lua_toboolean(luaContext->lua, -1); + value = mScriptValueAlloc(mSCRIPT_TYPE_MS_BOOL); + value->value.u32 = lua_toboolean(luaContext->lua, -1); break; case LUA_TSTRING: buffer = lua_tolstring(luaContext->lua, -1, &size); @@ -414,7 +414,9 @@ bool _luaWrap(struct mScriptEngineContextLua* luaContext, struct mScriptValue* v } break; case mSCRIPT_TYPE_UINT: - if (value->type->size <= 4) { + if (value->type == mSCRIPT_TYPE_MS_BOOL) { + lua_pushboolean(luaContext->lua, !!value->value.u32); + } else if (value->type->size <= 4) { lua_pushinteger(luaContext->lua, value->value.u32); } else if (value->type->size == 8) { lua_pushinteger(luaContext->lua, value->value.u64); diff --git a/src/script/test/types.c b/src/script/test/types.c index 9fa83a8a5..6ad38563a 100644 --- a/src/script/test/types.c +++ b/src/script/test/types.c @@ -206,41 +206,58 @@ M_TEST_DEFINE(wrongPopType) { uint64_t u64; float f32; double f64; + bool b; mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, S32, 0); assert_false(mScriptPopU32(&frame.arguments, &u32)); assert_false(mScriptPopF32(&frame.arguments, &f32)); + assert_false(mScriptPopBool(&frame.arguments, &b)); mScriptFrameDeinit(&frame); mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, S64, 0); assert_false(mScriptPopU64(&frame.arguments, &u64)); assert_false(mScriptPopF64(&frame.arguments, &f64)); + assert_false(mScriptPopBool(&frame.arguments, &b)); mScriptFrameDeinit(&frame); mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, U32, 0); assert_false(mScriptPopS32(&frame.arguments, &s32)); assert_false(mScriptPopF32(&frame.arguments, &f32)); + assert_false(mScriptPopBool(&frame.arguments, &b)); mScriptFrameDeinit(&frame); mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, U64, 0); assert_false(mScriptPopS64(&frame.arguments, &s64)); assert_false(mScriptPopF64(&frame.arguments, &f64)); + assert_false(mScriptPopBool(&frame.arguments, &b)); mScriptFrameDeinit(&frame); mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, F32, 0); assert_false(mScriptPopS32(&frame.arguments, &s32)); assert_false(mScriptPopU32(&frame.arguments, &u32)); + assert_false(mScriptPopBool(&frame.arguments, &b)); mScriptFrameDeinit(&frame); mScriptFrameInit(&frame); mSCRIPT_PUSH(&frame.arguments, F64, 0); assert_false(mScriptPopS64(&frame.arguments, &s64)); assert_false(mScriptPopU64(&frame.arguments, &u64)); + assert_false(mScriptPopBool(&frame.arguments, &b)); + mScriptFrameDeinit(&frame); + + mScriptFrameInit(&frame); + mSCRIPT_PUSH(&frame.arguments, BOOL, 0); + assert_false(mScriptPopS32(&frame.arguments, &s32)); + assert_false(mScriptPopU32(&frame.arguments, &u32)); + assert_false(mScriptPopS64(&frame.arguments, &s64)); + assert_false(mScriptPopU64(&frame.arguments, &u64)); + assert_false(mScriptPopF32(&frame.arguments, &f32)); + assert_false(mScriptPopF64(&frame.arguments, &f64)); mScriptFrameDeinit(&frame); } @@ -382,6 +399,100 @@ M_TEST_DEFINE(coerceFromFloat) { mScriptFrameDeinit(&frame); } +M_TEST_DEFINE(coerceToBool) { + struct mScriptValue a; + struct mScriptValue b; + + a = mSCRIPT_MAKE_S32(0); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + + a = mSCRIPT_MAKE_S32(1); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_S32(-1); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_S32(INT_MAX); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_S32(INT_MIN); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_U32(0); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + + a = mSCRIPT_MAKE_U32(1); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_U32(UINT_MAX); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_F32(0); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + + a = mSCRIPT_MAKE_F32(1); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_F32(1e30f); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); + + a = mSCRIPT_MAKE_F32(1e-30f); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_BOOL, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(true))); + assert_false(mSCRIPT_TYPE_MS_BOOL->equal(&b, &mSCRIPT_MAKE_BOOL(false))); +} + +M_TEST_DEFINE(coerceFromBool) { + struct mScriptValue a; + struct mScriptValue b; + + a = mSCRIPT_MAKE_BOOL(false); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_S32, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_S32->equal(&b, &mSCRIPT_MAKE_S32(0))); + + a = mSCRIPT_MAKE_BOOL(true); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_S32, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_S32->equal(&b, &mSCRIPT_MAKE_S32(1))); + + a = mSCRIPT_MAKE_BOOL(true); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_S32, &a, &b)); + assert_false(mSCRIPT_TYPE_MS_S32->equal(&b, &mSCRIPT_MAKE_S32(-1))); + + a = mSCRIPT_MAKE_BOOL(false); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_U32, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_U32->equal(&b, &mSCRIPT_MAKE_U32(0))); + + a = mSCRIPT_MAKE_BOOL(true); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_U32, &a, &b)); + assert_true(mSCRIPT_TYPE_MS_U32->equal(&b, &mSCRIPT_MAKE_U32(1))); + + a = mSCRIPT_MAKE_BOOL(true); + assert_true(mScriptCast(mSCRIPT_TYPE_MS_U32, &a, &b)); + assert_false(mSCRIPT_TYPE_MS_U32->equal(&b, &mSCRIPT_MAKE_U32(2))); +} + M_TEST_DEFINE(coerceWiden) { struct mScriptFrame frame; mScriptFrameInit(&frame); @@ -471,6 +582,20 @@ M_TEST_DEFINE(s32Equality) { COMPARE_BOOL(false, S32, 0, F64, 0.1); COMPARE_BOOL(true, S32, 0x40000000, F64, 0x40000000); COMPARE_BOOL(true, S32, -0x40000000, F64, -0x40000000); + + // BOOL + COMPARE_BOOL(true, S32, 0, BOOL, false); + COMPARE_BOOL(false, S32, 0, BOOL, true); + COMPARE_BOOL(false, S32, 1, BOOL, false); + COMPARE_BOOL(true, S32, 1, BOOL, true); + COMPARE_BOOL(false, S32, -1, BOOL, false); + COMPARE_BOOL(true, S32, -1, BOOL, true); + COMPARE_BOOL(false, S32, 2, BOOL, false); + COMPARE_BOOL(true, S32, 2, BOOL, true); + COMPARE_BOOL(false, S32, 0x7FFFFFFF, BOOL, false); + COMPARE_BOOL(true, S32, 0x7FFFFFFF, BOOL, true); + COMPARE_BOOL(false, S32, -0x80000000, BOOL, false); + COMPARE_BOOL(true, S32, -0x80000000, BOOL, true); } M_TEST_DEFINE(s64Equality) { @@ -552,6 +677,20 @@ M_TEST_DEFINE(s64Equality) { COMPARE_BOOL(false, S64, 0, F64, 0.1); COMPARE_BOOL(true, S64, 0x4000000000000000LL, F64, 0x4000000000000000LL); COMPARE_BOOL(true, S64, -0x4000000000000000LL, F64, -0x4000000000000000LL); + + // BOOL + COMPARE_BOOL(true, S64, 0, BOOL, false); + COMPARE_BOOL(false, S64, 0, BOOL, true); + COMPARE_BOOL(false, S64, 1, BOOL, false); + COMPARE_BOOL(true, S64, 1, BOOL, true); + COMPARE_BOOL(false, S64, -1, BOOL, false); + COMPARE_BOOL(true, S64, -1, BOOL, true); + COMPARE_BOOL(false, S64, 2, BOOL, false); + COMPARE_BOOL(true, S64, 2, BOOL, true); + COMPARE_BOOL(false, S64, 0x7FFFFFFFFFFFFFFFLL, BOOL, false); + COMPARE_BOOL(true, S64, 0x7FFFFFFFFFFFFFFFLL, BOOL, true); + COMPARE_BOOL(false, S64, -0x8000000000000000LL, BOOL, false); + COMPARE_BOOL(true, S64, -0x8000000000000000LL, BOOL, true); } M_TEST_DEFINE(u32Equality) { @@ -623,6 +762,18 @@ M_TEST_DEFINE(u32Equality) { COMPARE_BOOL(false, U32, 0x80000000U, F64, 0); COMPARE_BOOL(false, U32, 1, F64, 1.1); COMPARE_BOOL(false, U32, 0, F64, 0.1); + + // BOOL + COMPARE_BOOL(true, U32, 0, BOOL, false); + COMPARE_BOOL(false, U32, 0, BOOL, true); + COMPARE_BOOL(false, U32, 1, BOOL, false); + COMPARE_BOOL(true, U32, 1, BOOL, true); + COMPARE_BOOL(false, U32, 2, BOOL, false); + COMPARE_BOOL(true, U32, 2, BOOL, true); + COMPARE_BOOL(false, U32, 0xFFFFFFFFU, BOOL, false); + COMPARE_BOOL(true, U32, 0xFFFFFFFFU, BOOL, true); + COMPARE_BOOL(false, U32, 0x80000000U, BOOL, false); + COMPARE_BOOL(true, U32, 0x80000000U, BOOL, true); } M_TEST_DEFINE(u64Equality) { @@ -701,6 +852,18 @@ M_TEST_DEFINE(u64Equality) { COMPARE_BOOL(false, U64, 0x8000000000000000ULL, F64, 0); COMPARE_BOOL(false, U64, 1, F64, 1.1); COMPARE_BOOL(false, U64, 0, F64, 0.1); + + // BOOL + COMPARE_BOOL(true, U64, 0, BOOL, false); + COMPARE_BOOL(false, U64, 0, BOOL, true); + COMPARE_BOOL(false, U64, 1, BOOL, false); + COMPARE_BOOL(true, U64, 1, BOOL, true); + COMPARE_BOOL(false, U64, 2, BOOL, false); + COMPARE_BOOL(true, U64, 2, BOOL, true); + COMPARE_BOOL(false, U64, 0xFFFFFFFFFFFFFFFFULL, BOOL, false); + COMPARE_BOOL(true, U64, 0xFFFFFFFFFFFFFFFFULL, BOOL, true); + COMPARE_BOOL(false, U64, 0x8000000000000000ULL, BOOL, false); + COMPARE_BOOL(true, U64, 0x8000000000000000ULL, BOOL, true); } M_TEST_DEFINE(f32Equality) { @@ -768,6 +931,18 @@ M_TEST_DEFINE(f32Equality) { COMPARE_BOOL(true, F32, 0x100000000ULL, U64, 0x100000000ULL); COMPARE_BOOL(false, F32, 0x100000000ULL, U64, 0); COMPARE_BOOL(false, F32, 0, U64, 0x100000000ULL); + + // BOOL + COMPARE_BOOL(true, F32, 0, BOOL, false); + COMPARE_BOOL(false, F32, 0, BOOL, true); + COMPARE_BOOL(false, F32, 1, BOOL, false); + COMPARE_BOOL(true, F32, 1, BOOL, true); + COMPARE_BOOL(false, F32, 1.1, BOOL, false); + COMPARE_BOOL(true, F32, 1.1, BOOL, true); + COMPARE_BOOL(false, F32, 0x040000000ULL, BOOL, false); + COMPARE_BOOL(true, F32, 0x040000000ULL, BOOL, true); + COMPARE_BOOL(false, F32, 0x100000000ULL, BOOL, false); + COMPARE_BOOL(true, F32, 0x100000000ULL, BOOL, true); } M_TEST_DEFINE(f64Equality) { @@ -835,6 +1010,107 @@ M_TEST_DEFINE(f64Equality) { COMPARE_BOOL(true, F64, 0x100000000ULL, U64, 0x100000000ULL); COMPARE_BOOL(false, F64, 0x100000000ULL, U64, 0); COMPARE_BOOL(false, F64, 0, U64, 0x100000000ULL); + + // BOOL + COMPARE_BOOL(true, F64, 0, BOOL, false); + COMPARE_BOOL(false, F64, 0, BOOL, true); + COMPARE_BOOL(false, F64, 1, BOOL, false); + COMPARE_BOOL(true, F64, 1, BOOL, true); + COMPARE_BOOL(false, F64, 1.1, BOOL, false); + COMPARE_BOOL(true, F64, 1.1, BOOL, true); + COMPARE_BOOL(false, F64, 0x040000000ULL, BOOL, false); + COMPARE_BOOL(true, F64, 0x040000000ULL, BOOL, true); + COMPARE_BOOL(false, F64, 0x100000000ULL, BOOL, false); + COMPARE_BOOL(true, F64, 0x100000000ULL, BOOL, true); +} + +M_TEST_DEFINE(boolEquality) { + struct mScriptValue a; + struct mScriptValue b; + + // S32 + COMPARE_BOOL(true, BOOL, false, S32, 0); + COMPARE_BOOL(false, BOOL, false, S32, 1); + COMPARE_BOOL(false, BOOL, false, S32, -1); + COMPARE_BOOL(false, BOOL, false, S32, 2); + COMPARE_BOOL(false, BOOL, false, S32, 0x7FFFFFFF); + COMPARE_BOOL(false, BOOL, false, S32, -0x80000000); + COMPARE_BOOL(false, BOOL, true, S32, 0); + COMPARE_BOOL(true, BOOL, true, S32, 1); + COMPARE_BOOL(true, BOOL, true, S32, -1); + COMPARE_BOOL(true, BOOL, true, S32, 2); + COMPARE_BOOL(true, BOOL, true, S32, 0x7FFFFFFF); + COMPARE_BOOL(true, BOOL, true, S32, -0x80000000); + + // S64 + COMPARE_BOOL(true, BOOL, false, S64, 0); + COMPARE_BOOL(false, BOOL, false, S64, 1); + COMPARE_BOOL(false, BOOL, false, S64, -1); + COMPARE_BOOL(false, BOOL, false, S64, 2); + COMPARE_BOOL(false, BOOL, false, S64, INT64_MIN); + COMPARE_BOOL(false, BOOL, false, S64, INT64_MAX); + COMPARE_BOOL(false, BOOL, true, S64, 0); + COMPARE_BOOL(true, BOOL, true, S64, 1); + COMPARE_BOOL(true, BOOL, true, S64, -1); + COMPARE_BOOL(true, BOOL, true, S64, 2); + COMPARE_BOOL(true, BOOL, true, S64, INT64_MIN); + COMPARE_BOOL(true, BOOL, true, S64, INT64_MAX); + + // U32 + COMPARE_BOOL(true, BOOL, false, U32, 0); + COMPARE_BOOL(false, BOOL, false, U32, 1); + COMPARE_BOOL(false, BOOL, false, U32, 2); + COMPARE_BOOL(false, BOOL, false, U32, UINT32_MAX); + COMPARE_BOOL(false, BOOL, true, U32, 0); + COMPARE_BOOL(true, BOOL, true, U32, 1); + COMPARE_BOOL(true, BOOL, true, U32, 2); + COMPARE_BOOL(true, BOOL, true, U32, UINT32_MAX); + + // U64 + COMPARE_BOOL(true, BOOL, false, U64, 0); + COMPARE_BOOL(false, BOOL, false, U64, 1); + COMPARE_BOOL(false, BOOL, false, U64, 2); + COMPARE_BOOL(false, BOOL, false, U64, INT64_MAX); + COMPARE_BOOL(false, BOOL, true, U64, 0); + COMPARE_BOOL(true, BOOL, true, U64, 1); + COMPARE_BOOL(true, BOOL, true, U64, 2); + COMPARE_BOOL(true, BOOL, true, U64, INT64_MAX); + + // F32 + COMPARE_BOOL(true, BOOL, false, F32, 0); + COMPARE_BOOL(false, BOOL, true, F32, 0); + COMPARE_BOOL(false, BOOL, false, F32, 1); + COMPARE_BOOL(true, BOOL, true, F32, 1); + COMPARE_BOOL(false, BOOL, false, F32, 1.1f); + COMPARE_BOOL(true, BOOL, true, F32, 1.1f); + COMPARE_BOOL(false, BOOL, false, F32, 1e30f); + COMPARE_BOOL(true, BOOL, true, F32, 1e30f); + COMPARE_BOOL(false, BOOL, false, F32, -1); + COMPARE_BOOL(true, BOOL, true, F32, -1); + COMPARE_BOOL(false, BOOL, false, F32, -1.1f); + COMPARE_BOOL(true, BOOL, true, F32, -1.1f); + COMPARE_BOOL(false, BOOL, false, F32, -0.1e-30f); + COMPARE_BOOL(true, BOOL, true, F32, -0.1e-30f); + COMPARE_BOOL(false, BOOL, false, F32, -1e30f); + COMPARE_BOOL(true, BOOL, true, F32, -1e30f); + + // F64 + COMPARE_BOOL(true, BOOL, false, F64, 0); + COMPARE_BOOL(false, BOOL, true, F64, 0); + COMPARE_BOOL(false, BOOL, false, F64, 1); + COMPARE_BOOL(true, BOOL, true, F64, 1); + COMPARE_BOOL(false, BOOL, false, F64, 1.1); + COMPARE_BOOL(true, BOOL, true, F64, 1.1); + COMPARE_BOOL(false, BOOL, false, F64, 1e30); + COMPARE_BOOL(true, BOOL, true, F64, 1e30); + COMPARE_BOOL(false, BOOL, false, F64, -1); + COMPARE_BOOL(true, BOOL, true, F64, -1); + COMPARE_BOOL(false, BOOL, false, F64, -1.1); + COMPARE_BOOL(true, BOOL, true, F64, -1.1); + COMPARE_BOOL(false, BOOL, false, F64, -0.1e-300); + COMPARE_BOOL(true, BOOL, true, F64, -0.1e-300); + COMPARE_BOOL(false, BOOL, false, F64, -1e300); + COMPARE_BOOL(true, BOOL, true, F64, -1e300); } M_TEST_DEFINE(stringEquality) { @@ -1002,6 +1278,8 @@ M_TEST_SUITE_DEFINE(mScript, cmocka_unit_test(wrongConst), cmocka_unit_test(coerceToFloat), cmocka_unit_test(coerceFromFloat), + cmocka_unit_test(coerceToBool), + cmocka_unit_test(coerceFromBool), cmocka_unit_test(coerceNarrow), cmocka_unit_test(coerceWiden), cmocka_unit_test(s32Equality), @@ -1010,6 +1288,7 @@ M_TEST_SUITE_DEFINE(mScript, cmocka_unit_test(u64Equality), cmocka_unit_test(f32Equality), cmocka_unit_test(f64Equality), + cmocka_unit_test(boolEquality), cmocka_unit_test(stringEquality), cmocka_unit_test(hashTableBasic), cmocka_unit_test(hashTableString), diff --git a/src/script/types.c b/src/script/types.c index a9df515f2..71d2b7e07 100644 --- a/src/script/types.c +++ b/src/script/types.c @@ -38,6 +38,7 @@ static bool _f32Equal(const struct mScriptValue*, const struct mScriptValue*); static bool _s64Equal(const struct mScriptValue*, const struct mScriptValue*); static bool _u64Equal(const struct mScriptValue*, const struct mScriptValue*); static bool _f64Equal(const struct mScriptValue*, const struct mScriptValue*); +static bool _boolEqual(const struct mScriptValue*, const struct mScriptValue*); static bool _charpEqual(const struct mScriptValue*, const struct mScriptValue*); static bool _stringEqual(const struct mScriptValue*, const struct mScriptValue*); @@ -162,6 +163,17 @@ const struct mScriptType mSTFloat64 = { .cast = _castScalar, }; +const struct mScriptType mSTBool = { + .base = mSCRIPT_TYPE_UINT, + .size = 1, + .name = "bool", + .alloc = NULL, + .free = NULL, + .hash = _hashScalar, + .equal = _boolEqual, + .cast = _castScalar, +}; + const struct mScriptType mSTString = { .base = mSCRIPT_TYPE_STRING, .size = sizeof(struct mScriptString), @@ -394,6 +406,7 @@ AS(Float32, F32); AS(SInt64, S64); AS(UInt64, U64); AS(Float64, F64); +AS(Bool, BOOL); bool _castScalar(const struct mScriptValue* input, const struct mScriptType* type, struct mScriptValue* output) { switch (type->base) { @@ -411,7 +424,13 @@ bool _castScalar(const struct mScriptValue* input, const struct mScriptType* typ } break; case mSCRIPT_TYPE_UINT: - if (type->size <= 4) { + if (type == mSCRIPT_TYPE_MS_BOOL) { + bool b; + if (!_asBool(input, &b)) { + return false; + } + output->value.u32 = b; + } else if (type->size <= 4) { if (!_asUInt32(input, &output->value.u32)) { return false; } @@ -485,6 +504,9 @@ bool _s32Equal(const struct mScriptValue* a, const struct mScriptValue* b) { } break; case mSCRIPT_TYPE_UINT: + if (b->type == mSCRIPT_TYPE_MS_BOOL) { + return !!a->value.s32 == b->value.u32; + } if (a->value.s32 < 0) { return false; } @@ -532,6 +554,9 @@ bool _u32Equal(const struct mScriptValue* a, const struct mScriptValue* b) { } break; case mSCRIPT_TYPE_UINT: + if (b->type == mSCRIPT_TYPE_MS_BOOL) { + return !!a->value.u32 == b->value.u32; + } if (b->type->size <= 4) { val = b->value.u32; } else if (b->type->size == 8) { @@ -554,8 +579,12 @@ bool _u32Equal(const struct mScriptValue* a, const struct mScriptValue* b) { bool _f32Equal(const struct mScriptValue* a, const struct mScriptValue* b) { float val; switch (b->type->base) { - case mSCRIPT_TYPE_SINT: case mSCRIPT_TYPE_UINT: + if (b->type == mSCRIPT_TYPE_MS_BOOL) { + return (!(uint32_t) !a->value.f32)== b->value.u32; + } + // Fall through + case mSCRIPT_TYPE_SINT: case mSCRIPT_TYPE_FLOAT: if (!_asFloat32(b, &val)) { return false; @@ -582,6 +611,9 @@ bool _s64Equal(const struct mScriptValue* a, const struct mScriptValue* b) { } break; case mSCRIPT_TYPE_UINT: + if (b->type == mSCRIPT_TYPE_MS_BOOL) { + return !!a->value.s64 == b->value.u32; + } if (a->value.s64 < 0) { return false; } @@ -629,6 +661,9 @@ bool _u64Equal(const struct mScriptValue* a, const struct mScriptValue* b) { } break; case mSCRIPT_TYPE_UINT: + if (b->type == mSCRIPT_TYPE_MS_BOOL) { + return !!a->value.u64 == b->value.u32; + } if (b->type->size <= 4) { val = b->value.u32; } else if (b->type->size == 8) { @@ -648,8 +683,12 @@ bool _u64Equal(const struct mScriptValue* a, const struct mScriptValue* b) { bool _f64Equal(const struct mScriptValue* a, const struct mScriptValue* b) { double val; switch (b->type->base) { - case mSCRIPT_TYPE_SINT: case mSCRIPT_TYPE_UINT: + if (b->type == mSCRIPT_TYPE_MS_BOOL) { + return (!(uint32_t) !a->value.f64)== b->value.u32; + } + // Fall through + case mSCRIPT_TYPE_SINT: case mSCRIPT_TYPE_FLOAT: if (!_asFloat64(b, &val)) { return false; @@ -663,6 +702,29 @@ bool _f64Equal(const struct mScriptValue* a, const struct mScriptValue* b) { return a->value.f64 == val; } +bool _boolEqual(const struct mScriptValue* a, const struct mScriptValue* b) { + switch (b->type->base) { + case mSCRIPT_TYPE_SINT: + if (b->type->size <= 4) { + return a->value.u32 == !!b->value.s32; + } else if (b->type->size == 8) { + return a->value.u32 == !!b->value.s64; + } + return false; + case mSCRIPT_TYPE_UINT: + if (b->type->size <= 4) { + return a->value.u32 == !!b->value.u32; + } else if (b->type->size == 8) { + return a->value.u32 == !!b->value.u64; + } + return false; + case mSCRIPT_TYPE_VOID: + return false; + default: + return b->type->equal && b->type->equal(b, a); + } +} + bool _charpEqual(const struct mScriptValue* a, const struct mScriptValue* b) { const char* valA = a->value.opaque; const char* valB; @@ -1368,6 +1430,12 @@ bool mScriptPopF64(struct mScriptList* list, double* out) { return true; } +bool mScriptPopBool(struct mScriptList* list, bool* out) { + mSCRIPT_POP(list, BOOL, val); + *out = val; + return true; +} + bool mScriptPopPointer(struct mScriptList* list, void** out) { mSCRIPT_POP(list, PTR, val); *out = val; From dd29e0cad38c40b6af9d914c9ce8d4b3a889ae2d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 1 Jul 2022 20:25:25 -0700 Subject: [PATCH 097/102] Qt: Clean up views --- src/platform/qt/Window.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 543eb4b2f..b01b97a5d 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1316,10 +1316,6 @@ void Window::setupMenu(QMenuBar* menubar) { #ifdef M_CORE_GBA Action* scanCard = addGameAction(tr("Scan e-Reader dotcodes..."), "scanCard", this, &Window::scanCard, "file"); m_platformActions.insert(mPLATFORM_GBA, scanCard); - -#ifdef USE_FFMPEG - m_actions.addAction(tr("Convert e-Reader card image to raw..."), "parseCard", this, &Window::parseCard, "file"); -#endif #endif addGameAction(tr("ROM &info..."), "romInfo", openControllerTView(), "file"); @@ -1646,6 +1642,9 @@ void Window::setupMenu(QMenuBar* menubar) { m_actions.addAction(tr("Game Pak sensors..."), "sensorWindow", openNamedControllerTView(&m_sensorView, &m_inputController), "tools"); addGameAction(tr("&Cheats..."), "cheatsWindow", openControllerTView(), "tools"); +#ifdef ENABLE_SCRIPTING + m_actions.addAction(tr("Scripting..."), "scripting", this, &Window::scriptingOpen, "tools"); +#endif m_actions.addSeparator("tools"); m_actions.addAction(tr("Settings..."), "settings", this, &Window::openSettingsWindow, "tools")->setRole(Action::Role::SETTINGS); @@ -1659,17 +1658,15 @@ void Window::setupMenu(QMenuBar* menubar) { m_platformActions.insert(mPLATFORM_GBA, gdbWindow); #endif #endif -#ifdef ENABLE_SCRIPTING - m_actions.addAction(tr("Scripting..."), "scripting", this, &Window::scriptingOpen, "tools"); -#endif #if defined(USE_DEBUGGERS) || defined(ENABLE_SCRIPTING) m_actions.addSeparator("tools"); #endif - addGameAction(tr("View &palette..."), "paletteWindow", openControllerTView(), "tools"); - addGameAction(tr("View &sprites..."), "spriteWindow", openControllerTView(), "tools"); - addGameAction(tr("View &tiles..."), "tileWindow", openControllerTView(), "tools"); - addGameAction(tr("View &map..."), "mapWindow", openControllerTView(), "tools"); + m_actions.addMenu(tr("Game state views"), "stateViews", "tools"); + addGameAction(tr("View &palette..."), "paletteWindow", openControllerTView(), "stateViews"); + addGameAction(tr("View &sprites..."), "spriteWindow", openControllerTView(), "stateViews"); + addGameAction(tr("View &tiles..."), "tileWindow", openControllerTView(), "stateViews"); + addGameAction(tr("View &map..."), "mapWindow", openControllerTView(), "stateViews"); addGameAction(tr("&Frame inspector..."), "frameWindow", [this]() { if (!m_frameView) { @@ -1685,11 +1682,16 @@ void Window::setupMenu(QMenuBar* menubar) { m_frameView->setAttribute(Qt::WA_DeleteOnClose); } m_frameView->show(); - }, "tools"); + }, "stateViews"); - addGameAction(tr("View memory..."), "memoryView", openControllerTView(), "tools"); - addGameAction(tr("Search memory..."), "memorySearch", openControllerTView(), "tools"); - addGameAction(tr("View &I/O registers..."), "ioViewer", openControllerTView(), "tools"); + addGameAction(tr("View memory..."), "memoryView", openControllerTView(), "stateViews"); + addGameAction(tr("Search memory..."), "memorySearch", openControllerTView(), "stateViews"); + addGameAction(tr("View &I/O registers..."), "ioViewer", openControllerTView(), "stateViews"); + +#if defined(USE_FFMPEG) && defined(M_CORE_GBA) + m_actions.addSeparator("tools"); + m_actions.addAction(tr("Convert e-Reader card image to raw..."), "parseCard", this, &Window::parseCard, "tools"); +#endif m_actions.addSeparator("tools"); addGameAction(tr("Record debug video log..."), "recordVL", this, &Window::startVideoLog, "tools"); From 7f91cfe58d70453de76c2eb25897d7f0a5a6fec1 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 1 Jul 2022 23:37:50 -0700 Subject: [PATCH 098/102] GBA: Fix some ROM buffer handling issues with oddly sized files --- src/gba/gba.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gba/gba.c b/src/gba/gba.c index cee833c5b..1c0de38e4 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -399,14 +399,15 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) { } GBAUnloadROM(gba); gba->romVf = vf; + gba->isPristine = true; gba->pristineRomSize = vf->size(vf); vf->seek(vf, 0, SEEK_SET); if (gba->pristineRomSize > SIZE_CART0) { - gba->isPristine = false; char ident; vf->seek(vf, 0xAC, SEEK_SET); vf->read(vf, &ident, 1); if (ident == 'M') { + gba->isPristine = false; gba->memory.romSize = 0x01000000; #ifdef FIXED_ROM_BUFFER gba->memory.rom = romBuffer; @@ -417,8 +418,8 @@ bool GBALoadROM(struct GBA* gba, struct VFile* vf) { gba->memory.rom = vf->map(vf, SIZE_CART0, MAP_READ); gba->memory.romSize = SIZE_CART0; } + gba->pristineRomSize = SIZE_CART0; } else { - gba->isPristine = true; gba->memory.rom = vf->map(vf, gba->pristineRomSize, MAP_READ); gba->memory.romSize = gba->pristineRomSize; } From ae3350457795c7a1908d6dbc893810ca24ee8127 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 1 Jul 2022 23:42:41 -0700 Subject: [PATCH 099/102] Core: Fix memory leak when refreshing a directory --- src/core/library.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/library.c b/src/core/library.c index d6cd99a0c..44148f7f5 100644 --- a/src/core/library.c +++ b/src/core/library.c @@ -243,9 +243,11 @@ void mLibraryLoadDirectory(struct mLibrary* library, const char* base, bool recu struct VFile* vf = dir->openFile(dir, current->filename, O_RDONLY); _mLibraryDeleteEntry(library, current); if (!vf) { + mLibraryEntryFree(current); continue; } _mLibraryAddEntry(library, current->filename, base, vf); + mLibraryEntryFree(current); } mLibraryListingDeinit(&entries); From dcd63f1ceb003262967c1fd254cca52cfa40b20a Mon Sep 17 00:00:00 2001 From: Lothar Serra Mari Date: Mon, 6 Jun 2022 13:24:12 +0000 Subject: [PATCH 100/102] Qt: Update translation (German) Translation: mGBA/Qt Translate-URL: https://hosted.weblate.org/projects/mgba/mgba-qt/de/ --- src/platform/qt/ts/mgba-de.ts | 69 ++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/src/platform/qt/ts/mgba-de.ts b/src/platform/qt/ts/mgba-de.ts index 65eabed81..7f4589fb6 100644 --- a/src/platform/qt/ts/mgba-de.ts +++ b/src/platform/qt/ts/mgba-de.ts @@ -1181,19 +1181,22 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd. An update to %1 is available. - + Ein Update für %1 ist verfügbar. + Do you want to download and install it now? You will need to restart the emulator when the download is complete. - + +Möchtest Du es jetzt herunterladen und installieren? Du wirst den Emulator nach Abschluss des Downloads neu starten müssen. Auto-update is not available on this platform. If you wish to update you will need to do it manually. - + +Automatische Updates sind für diese Plattform nicht verfügbar. Wenn Du updaten möchtest, musst Du dies manuell tun. @@ -1291,23 +1294,23 @@ Download-Größe: %3 Reset r%1-%2 %3 - + r%1-%2 %3 zurücksetzen Rewinding not currently enabled - + Rücklauf ist derzeit nicht aktiviert Reset the game? - + Spiel zurücksetzen? Most games will require a reset to load the new save. Do you want to reset now? - + Die meisten Spiele müssen zurückgesetzt werden, um einen neuen Spielstand zu laden. Möchtest Du das Spiel jetzt zurücksetzen? @@ -1350,7 +1353,7 @@ Download-Größe: %3 Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). - + Fehler beim Laden der Spielstand-Datei; Speicherdaten können nicht aktualisiert werden. Bitte stelle sicher, dass das Speicherdaten-Verzeichnis ohne zusätzliche Berechtigungen (z.B. UAC in Windows) beschreibbar ist. @@ -1358,7 +1361,7 @@ Download-Größe: %3 Could not open CLI history for writing - + CLI-Verlauf kann nicht gespeichert werden @@ -1465,22 +1468,22 @@ Download-Größe: %3 Write watchpoints behavior - + Watchpoint-Speicherverhalten Standard GDB - + GDB-Standard Internal change detection - + Änderungen erkennen Break on all writes - + Bei jedem Speichervorgang unterbrechen @@ -3716,7 +3719,7 @@ Download-Größe: %3 Frame %1 - + Frame %1 @@ -4053,7 +4056,7 @@ Download-Größe: %3 %n hour(s) ago - Vor %n Stunde(n) + Vor %n Stunde Vor %n Stunde(n) @@ -4061,8 +4064,8 @@ Download-Größe: %3 %n day(s) ago - Vor %n Tag(en) - Vor %n Tag(en) + Vor %n Tag + Vor %n Tagen @@ -4336,17 +4339,17 @@ Download-Größe: %3 Save games - Spielstände + Spielstände Automatically determine - + Automatisch erkennen Use player %0 save game - + Verwende Spielstand von Spieler %0 @@ -4452,12 +4455,12 @@ Download-Größe: %3 Reset needed - + Zurücksetzen erforderlich Some changes will not take effect until the game is reset. - + Einige Änderungen werden erst dann wirksam, wenn das Spiel zurückgesetzt wird. @@ -4743,7 +4746,7 @@ Download-Größe: %3 GameShark saves (*.gsv *.sps *.xps) - + GameShark-Spielstände (*.gsv *.sps *.xps) @@ -5169,12 +5172,12 @@ Download-Größe: %3 %1 SharkPort %2 save game - + SharkPort %1 Spielstand %2 %1 GameShark Advance SP %2 save game - + %1 GameShark Advance SP %2 Spielstand @@ -5516,7 +5519,7 @@ Download-Größe: %3 Show filename instead of ROM name in library view - + Zeige Dateinamen anstelle des ROM-Namens in der Bibliotheksansicht @@ -5647,12 +5650,12 @@ Download-Größe: %3 Show frame count in OSD - + Frame-Anzahl im OSD anzeigen Show emulation info on reset - + Emulations-Informationen bei Reset anzeigen @@ -6092,7 +6095,7 @@ Download-Größe: %3 Palette - Palette + Palette @@ -6112,22 +6115,22 @@ Download-Größe: %3 Displayed tiles - + Angezeigte Tiles Only BG tiles - + Nur BG-Tiles Only OBJ tiles - + Nur OBJ-Tiles Both - Beidseitig + Beide From c71baa0c87c2a635de59df7ac67f6eecc3c653d1 Mon Sep 17 00:00:00 2001 From: Dardo Marasca Date: Mon, 6 Jun 2022 19:39:23 +0000 Subject: [PATCH 101/102] Qt: Update translation (Spanish) Translation: mGBA/Qt Translate-URL: https://hosted.weblate.org/projects/mgba/mgba-qt/es/ --- src/platform/qt/ts/mgba-es.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/qt/ts/mgba-es.ts b/src/platform/qt/ts/mgba-es.ts index 3e09744c2..1131eac18 100644 --- a/src/platform/qt/ts/mgba-es.ts +++ b/src/platform/qt/ts/mgba-es.ts @@ -6120,12 +6120,12 @@ Tamaño de la descarga: %3 Only BG tiles - + Solo BG tiles Only OBJ tiles - + Solo OBJ tiles From 39886c72f5700322c17c50eac9212450b5df4bac Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 1 Jul 2022 23:57:46 -0700 Subject: [PATCH 102/102] Qt: Update translations --- src/platform/qt/ts/mgba-de.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-en.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-es.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-fi.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-fr.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-hu.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-it.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-ja.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-ko.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-ms.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-nb_NO.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-nl.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-pl.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-pt_BR.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-ru.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-template.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-tr.ts | 444 ++++++++++++++-------------- src/platform/qt/ts/mgba-zh_CN.ts | 444 ++++++++++++++-------------- 18 files changed, 4104 insertions(+), 3888 deletions(-) diff --git a/src/platform/qt/ts/mgba-de.ts b/src/platform/qt/ts/mgba-de.ts index 7f4589fb6..67d1c294d 100644 --- a/src/platform/qt/ts/mgba-de.ts +++ b/src/platform/qt/ts/mgba-de.ts @@ -1185,21 +1185,21 @@ Game Boy Advance ist eine eingetragene Marke von Nintendo Co., Ltd. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. Möchtest Du es jetzt herunterladen und installieren? Du wirst den Emulator nach Abschluss des Downloads neu starten müssen. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. Automatische Updates sind für diese Plattform nicht verfügbar. Wenn Du updaten möchtest, musst Du dies manuell tun. - + Current version: %1 New version: %2 Download size: %3 @@ -1208,17 +1208,17 @@ Neue Version: %2 Download-Größe: %3 - + Downloading update... Update wird heruntergeladen... - + Downloading failed. Please update manually. Download fehlgeschlagen. Bitte führe das Update manuell durch. - + Downloading done. Press OK to restart %1 and install the update. Download abgeschlossen. Klicke auf OK, um %1 neuzustarten und das Update zu installieren. @@ -1241,7 +1241,7 @@ Download-Größe: %3 Unbekannt - + (None) (keiner) @@ -1328,12 +1328,12 @@ Download-Größe: %3 Das GamePak kann nur auf unterstützten Plattformen herausgezogen werden! - + Failed to open snapshot file for reading: %1 Konnte Snapshot-Datei %1 nicht zum Lesen öffnen - + Failed to open snapshot file for writing: %1 Konnte Snapshot-Datei %1 nicht zum Schreiben öffnen @@ -1346,12 +1346,12 @@ Download-Größe: %3 Fehler beim Öffnen der Spieldatei: %1 - + Could not load game. Are you sure it's in the correct format? Konnte das Spiel nicht laden. Bist Du sicher, dass es im korrekten Format vorliegt? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). Fehler beim Laden der Spielstand-Datei; Speicherdaten können nicht aktualisiert werden. Bitte stelle sicher, dass das Speicherdaten-Verzeichnis ohne zusätzliche Berechtigungen (z.B. UAC in Windows) beschreibbar ist. @@ -3415,27 +3415,27 @@ Download-Größe: %3 QGBA::LoadSaveState - + Load State Savestate laden - + Save State Savestate speichern - + Empty Leer - + Corrupted Defekt - + Slot %1 Speicherplatz %1 @@ -3864,12 +3864,12 @@ Download-Größe: %3 QGBA::ReportView - + Bug report archive Fehlerbericht speichern - + ZIP archive (*.zip) ZIP-Archiv (*.zip) @@ -3940,29 +3940,11 @@ Download-Größe: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4160,105 +4142,105 @@ Download-Größe: %3 QGBA::Window - + Game Boy Advance ROMs (%1) Game Boy Advance-ROMs (%1) - + Game Boy ROMs (%1) Game Boy-ROMs (%1) - + All ROMs (%1) Alle ROMs (%1) - + %1 Video Logs (*.mvl) %1 Video-Logs (*.mvl) - + Archives (%1) Archive (%1) - - - + + + Select ROM ROM auswählen - - + + Select save Speicherdatei wählen - + Select patch Patch wählen - + Patches (*.ips *.ups *.bps) Korrekturen (*.ips *.ups *.bps) - + Select e-Reader card images Bilder der Lesegerät-Karte auswählen - + Image file (*.png *.jpg *.jpeg) Bilddatei (*.png *.jpg *.jpeg) - + Conversion finished Konvertierung abgeschlossen - + %1 of %2 e-Reader cards converted successfully. %1 von %2 Lesegerät-Karten erfolgreich konvertiert. - + Select image Bild auswählen - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Bild-Datei (*.png *.gif *.jpg *.jpeg);;Alle Dateien (*) - + GameShark saves (*.sps *.xps) GameShark-Speicherdaten (*.sps *.xps) - + Select video log Video-Log auswählen - + Video logs (*.mvl) Video-Logs (*.mvl) - + Crash Absturz - + The game has crashed with the following error: %1 @@ -4267,674 +4249,679 @@ Download-Größe: %3 %1 - + Unimplemented BIOS call Nicht implementierter BIOS-Aufruf - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Dieses Spiel verwendet einen BIOS-Aufruf, der nicht implementiert ist. Bitte verwenden Sie für die beste Spielerfahrung das offizielle BIOS. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Es konnte kein geeignetes Ausgabegerät erstellt werden, stattdessen wird Software-Rendering als Rückfalloption genutzt. Spiele laufen möglicherweise langsamer, besonders innerhalb großer Fenster. - + Really make portable? Portablen Modus wirklich aktivieren? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Diese Einstellung wird den Emulator so konfigurieren, dass er seine Konfiguration aus dem gleichen Verzeichnis wie die Programmdatei lädt. Möchten Sie fortfahren? - + Restart needed Neustart benötigt - + Some changes will not take effect until the emulator is restarted. Einige Änderungen werden erst übernommen, wenn der Emulator neu gestartet wurde. - + - Player %1 of %2 - Spieler %1 von %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 Bilder/Sekunde) - %4 - + &File &Datei - + Load &ROM... &ROM laden... - + Load ROM in archive... ROM aus Archiv laden... - + Save games Spielstände - + Automatically determine Automatisch erkennen - + Use player %0 save game Verwende Spielstand von Spieler %0 - + Load &patch... &Patch laden... - + Boot BIOS BIOS booten - + Replace ROM... ROM ersetzen... - + Convert e-Reader card image to raw... Lesegerät-Kartenbild in Rohdaten umwandeln … - + ROM &info... ROM-&Informationen... - + Recent Zuletzt verwendet - + Make portable Portablen Modus aktivieren - + &Load state Savestate (aktueller Zustand) &laden - + Load state file... Savestate-Datei laden... - + &Save state Savestate (aktueller Zustand) &speichern - + Save state file... Savestate-Datei speichern... - + Quick load Schnell laden - + Quick save Schnell speichern - + Load recent Lade zuletzt gespeicherten Savestate - + Save recent Speichere aktuellen Zustand - + Undo load state Laden des Savestate rückgängig machen - + Undo save state Speichern des Savestate rückgängig machen - - + + State &%1 Savestate &%1 - + Load camera image... Lade Kamerabild... - + Convert save game... Spielstand konvertieren... - + Reset needed Zurücksetzen erforderlich - + Some changes will not take effect until the game is reset. Einige Änderungen werden erst dann wirksam, wenn das Spiel zurückgesetzt wird. - + New multiplayer window Neues Multiplayer-Fenster - + Connect to Dolphin... Mit Dolphin verbinden... - + Report bug... Fehler melden... - + E&xit &Beenden - + &Emulation &Emulation - + &Reset Zu&rücksetzen - + Sh&utdown Schli&eßen - + Yank game pak Spielmodul herausziehen - + &Pause &Pause - + &Next frame &Nächstes Bild - + Fast forward (held) Schneller Vorlauf (gehalten) - + &Fast forward Schneller &Vorlauf - + Fast forward speed Vorlauf-Geschwindigkeit - + Unbounded Unbegrenzt - + %0x %0x - + Rewind (held) Zurückspulen (gehalten) - + Re&wind Zur&ückspulen - + Step backwards Schrittweiser Rücklauf - + Solar sensor Sonnen-Sensor - + Increase solar level Sonnen-Level erhöhen - + Decrease solar level Sonnen-Level verringern - + Brightest solar level Hellster Sonnen-Level - + Darkest solar level Dunkelster Sonnen-Level - + Brightness %1 Helligkeit %1 - + BattleChip Gate... BattleChip Gate... - + Audio/&Video Audio/&Video - + Frame size Bildgröße - + Toggle fullscreen Vollbildmodus umschalten - + Lock aspect ratio Seitenverhältnis korrigieren - + Force integer scaling Pixelgenaue Skalierung (Integer scaling) - + Interframe blending Interframe-Überblendung - + Frame&skip Frame&skip - + Mute Stummschalten - + FPS target Bildwiederholrate - + Take &screenshot &Screenshot erstellen - + F12 F12 - + Scripting... - + + Game state views + + + + Clear Leeren - + Game Boy Printer... Game Boy Printer... - + Video layers Video-Ebenen - + Audio channels Audio-Kanäle - + Adjust layer placement... Lage der Bildebenen anpassen... - + &Tools &Werkzeuge - + View &logs... &Logs ansehen... - + Game &overrides... Spiel-&Überschreibungen... - + &Cheats... &Cheats... - + Open debugger console... Debugger-Konsole öffnen... - + Start &GDB server... &GDB-Server starten... - + Settings... Einstellungen... - + Select folder Ordner auswählen - + Save games (%1) Spielstände (%1) - + Select save game Spielstand auswählen - + mGBA save state files (%1) mGBA-Savestates (%1) + - Select save state Savestate auswählen - + Select e-Reader dotcode e-Reader-Code auswählen - + e-Reader card (*.raw *.bin *.bmp) e-Reader-Karte (*.raw *.bin *.bmp) - + GameShark saves (*.gsv *.sps *.xps) GameShark-Spielstände (*.gsv *.sps *.xps) - + Couldn't Start Konnte nicht gestartet werden - + Could not start game. Spiel konnte nicht gestartet werden. - + Add folder to library... Ordner zur Bibliothek hinzufügen... - + Load alternate save game... Alternativen Spielstand laden... - + Load temporary save game... Temporären Spielstand laden... - + Scan e-Reader dotcodes... e-Reader-Code einlesen... - + Import GameShark Save... GameShare-Speicherstand importieren... - + Export GameShark Save... GameShark-Speicherstand exportieren... - + About... Über... - + %1× %1x - + Bilinear filtering Bilineare Filterung - + Native (59.7275) Nativ (59.7275) - + Record A/V... Audio/Video aufzeichnen... - + Record GIF/WebP/APNG... GIF/WebP/APNG aufzeichnen... - + Game Pak sensors... Spielmodul-Sensoren... - + View &palette... &Palette betrachten... - + View &sprites... &Sprites betrachten... - + View &tiles... &Tiles betrachten... - + View &map... &Map betrachten... - + &Frame inspector... &Bildbetrachter... - + View memory... Speicher betrachten... - + Search memory... Speicher durchsuchen... - + View &I/O registers... &I/O-Register betrachten... - + Record debug video log... Video-Protokoll aufzeichnen... - + Stop debug video log Aufzeichnen des Video-Protokolls beenden - + Exit fullscreen Vollbildmodus beenden - + GameShark Button (held) GameShark-Taste (gehalten) - + Autofire Autofeuer - + Autofire A Autofeuer A - + Autofire B Autofeuer B - + Autofire L Autofeuer L - + Autofire R Autofeuer R - + Autofire Start Autofeuer Start - + Autofire Select Autofeuer Select - + Autofire Up Autofeuer nach oben - + Autofire Right Autofeuer rechts - + Autofire Down Autofeuer nach unten - + Autofire Left Autofeuer links @@ -5183,40 +5170,55 @@ Download-Größe: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset Zu&rücksetzen - + 0 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5231,64 +5233,74 @@ Download-Größe: %3 Echtzeituhr - + Fixed time Feste Zeit - + System time Systemzeit - + Start time at Starte Zeit ab - + Now Jetzt - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP dd.MM.yy HH:mm:ss - + Light sensor Lichtsensor - + Brightness Helligkeit - + Tilt sensor Neigungssensor - - + + Set Y Setze Y - - + + Set X Setze X - + Gyroscope Gyroskop - + Sensitivity Empfindlichkeit diff --git a/src/platform/qt/ts/mgba-en.ts b/src/platform/qt/ts/mgba-en.ts index cff78b3e9..feae91b5a 100644 --- a/src/platform/qt/ts/mgba-en.ts +++ b/src/platform/qt/ts/mgba-en.ts @@ -1183,36 +1183,36 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. - + Current version: %1 New version: %2 Download size: %3 - + Downloading update... - + Downloading failed. Please update manually. - + Downloading done. Press OK to restart %1 and install the update. @@ -1235,7 +1235,7 @@ Download size: %3 - + (None) @@ -1322,12 +1322,12 @@ Download size: %3 - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -1340,12 +1340,12 @@ Download size: %3 - + Could not load game. Are you sure it's in the correct format? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). @@ -3409,27 +3409,27 @@ Download size: %3 QGBA::LoadSaveState - + Load State - + Save State - + Empty - + Corrupted - + Slot %1 @@ -3858,12 +3858,12 @@ Download size: %3 QGBA::ReportView - + Bug report archive - + ZIP archive (*.zip) @@ -3934,29 +3934,11 @@ Download size: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4154,779 +4136,784 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) - - - + + + Select ROM - + Select folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) + - Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + Scripting... - + + Game state views + + + + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear @@ -5175,40 +5162,55 @@ Download size: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset - + 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5223,64 +5225,74 @@ Download size: %3 - + Fixed time - + System time - + Start time at - + Now - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP - + Light sensor - + Brightness - + Tilt sensor - - + + Set Y - - + + Set X - + Gyroscope - + Sensitivity diff --git a/src/platform/qt/ts/mgba-es.ts b/src/platform/qt/ts/mgba-es.ts index 1131eac18..daed1612b 100644 --- a/src/platform/qt/ts/mgba-es.ts +++ b/src/platform/qt/ts/mgba-es.ts @@ -1185,21 +1185,21 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. ¿Quieres descargarlo e instalarlo ahora? Deberá reiniciar el emulador cuando se complete la descarga. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. La actualización automática no está disponible en esta plataforma. Si desea actualizar, deberá hacerlo manualmente. - + Current version: %1 New version: %2 Download size: %3 @@ -1208,17 +1208,17 @@ Nueva versión: %2 Tamaño de la descarga: %3 - + Downloading update... Descargando actualización... - + Downloading failed. Please update manually. La descarga ha fallado. Por favor, actualiza manualmente. - + Downloading done. Press OK to restart %1 and install the update. Descarga finalizada. Presiona OK para reiniciar %1 e instalar la actualización. @@ -1241,7 +1241,7 @@ Tamaño de la descarga: %3 Desconocido - + (None) (Ninguno) @@ -1328,12 +1328,12 @@ Tamaño de la descarga: %3 ¡No se puede remover el cartucho en esta plataforma! - + Failed to open snapshot file for reading: %1 Error al leer del archivo de captura: %1 - + Failed to open snapshot file for writing: %1 Error al escribir al archivo de captura: %1 @@ -1346,12 +1346,12 @@ Tamaño de la descarga: %3 Error al abrir el archivo del juego: %1 - + Could not load game. Are you sure it's in the correct format? No se pudo cargar el juego. ¿Estás seguro de que está en el formato correcto? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). Error al abrir el archivo de guardado; las partidas guardadas no se pueden actualizar. Por favor, asegúrese de que es posible escribir en el directorio de partidas guardadas sin necesidad de privilegios adicionales (Por ejemplo, UAC en Windows). @@ -3415,27 +3415,27 @@ Tamaño de la descarga: %3 QGBA::LoadSaveState - + Load State Cargar estado - + Save State Guardar estado - + Empty Vacío - + Corrupted Dañado - + Slot %1 Espacio %1 @@ -3864,12 +3864,12 @@ Tamaño de la descarga: %3 QGBA::ReportView - + Bug report archive Archivo del reporte de bugs - + ZIP archive (*.zip) Archivo ZIP (*.zip) @@ -3940,29 +3940,11 @@ Tamaño de la descarga: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4160,100 +4142,100 @@ Tamaño de la descarga: %3 QGBA::Window - + Game Boy Advance ROMs (%1) ROMs de Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs de Game Boy (%1) - + All ROMs (%1) Todas las ROMs (%1) - + %1 Video Logs (*.mvl) Video-registros de %1 (*.mvl) - + Archives (%1) Contenedores (%1) - - - + + + Select ROM Seleccionar ROM - + Select folder Seleccionar carpeta - - + + Select save Seleccionar guardado - + Select patch Seleccionar parche - + Patches (*.ips *.ups *.bps) Parches (*.ips *.ups *.bps) - + Select e-Reader dotcode Seleccionar dotcode del e-Reader - + e-Reader card (*.raw *.bin *.bmp) Tarjeta e-Reader (*.raw *.bin *.bmp) - + Select image Seleccionar imagen - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Archivo de imagen (*.png *.gif *.jpg *.jpeg);;Todos los archivos (*) - + GameShark saves (*.sps *.xps) Guardados de GameShark (*.sps *.xps) - + Select video log Seleccionar video-registro - + Video logs (*.mvl) Video-registros (*.mvl) - + Crash Cierre inesperado - + The game has crashed with the following error: %1 @@ -4262,679 +4244,684 @@ Tamaño de la descarga: %3 %1 - + Unimplemented BIOS call Llamada a BIOS no implementada - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Este juego utiliza una llamada al BIOS que no se ha implementado. Utiliza el BIOS oficial para obtener la mejor experiencia. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. No se pudo crear un dispositivo de pantalla apropiado, recurriendo a software. Los juegos pueden funcionar lentamente, especialmente con ventanas grandes. - + Really make portable? ¿Hacer "portable"? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Esto hará que el emulador cargue su configuración desde el mismo directorio que el ejecutable. ¿Quieres continuar? - + Restart needed Reinicio necesario - + Some changes will not take effect until the emulator is restarted. Algunos cambios no surtirán efecto hasta que se reinicie el emulador. - + - Player %1 of %2 - Jugador %1 de %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Archivo - + Load &ROM... Cargar &ROM... - + Load ROM in archive... Cargar ROM desde contenedor... - + Add folder to library... Agregar carpeta a la biblioteca... - + Save games Datos de guardado - + Automatically determine Determinar automáticamente - + Use player %0 save game Usar la partida guardada del jugador %0 - + Load &patch... Cargar &parche... - + Boot BIOS Arrancar BIOS - + Replace ROM... Reemplazar ROM... - + ROM &info... &Información de la ROM... - + Recent Recientes - + Make portable Hacer "portable" - + &Load state Ca&rgar estado - + Report bug... Reportar bug... - + About... Acerca de... - + Game Pak sensors... Sensores del cartucho... - + Clear Limpiar - + Load state file... Cargar archivo de estado... - + Save games (%1) Juegos guardados (%1) - + Select save game Elegir juego guardado - + mGBA save state files (%1) Archivos estados guardados mGBA (%1) + - Select save state Elegir estado guardado - + Select e-Reader card images Elegir imágenes de tarjeta e-Reader - + Image file (*.png *.jpg *.jpeg) Archivo de imagen (*.png *.jpg *.jpeg) - + Conversion finished Conversión terminada - + %1 of %2 e-Reader cards converted successfully. %1 de %2 tarjetas e-Reader convertidas con éxito. - + Load alternate save game... Elegir juego guardado alterno... - + Load temporary save game... Elegir juego guardado temporal... - + Convert e-Reader card image to raw... Convertir imagen de tarjeta e-Reader a raw... - + &Save state Guardar e&stado - + Save state file... Guardar archivo de estado... - + Quick load Cargado rápido - + Quick save Guardado rápido - + Load recent Cargar reciente - + Save recent Guardar reciente - + Undo load state Deshacer cargar estado - + Undo save state Deshacer guardar estado - - + + State &%1 Estado &%1 - + Load camera image... Cargar imagen para la cámara... - + Convert save game... Convertir juego guardado... - + GameShark saves (*.gsv *.sps *.xps) Partidas guardadas de GameShark (*.gsv *.sps *.xps) - + Reset needed Reinicio necesario - + Some changes will not take effect until the game is reset. Algunos cambios no tendrán efecto hasta que se reinicie el juego. - + New multiplayer window Nueva ventana multijugador - + Connect to Dolphin... Conectar a Dolphin... - + E&xit Salir (&X) - + &Emulation &Emulación - + &Reset &Reinicializar - + Sh&utdown Apagar (&U) - + Yank game pak Tirar del cartucho - + &Pause &Pausar - + &Next frame Cuadro siguie&nte - + Fast forward (held) Avance rápido (mantener) - + &Fast forward &Avance rápido - + Fast forward speed Velocidad de avance rápido - + Unbounded Sin límite - + %0x %0x - + Rewind (held) Rebobinar (mantener) - + Re&wind Re&bobinar - + Step backwards Paso hacia atrás - + Solar sensor Sensor solar - + Increase solar level Subir nivel - + Decrease solar level Bajar nivel - + Brightest solar level Más claro - + Darkest solar level Más oscuro - + Brightness %1 Brillo %1 - + Audio/&Video Audio/&video - + Frame size Tamaño del cuadro - + Toggle fullscreen Pantalla completa - + Lock aspect ratio Bloquear proporción de aspecto - + Force integer scaling Forzar escala a enteros - + Bilinear filtering Filtro bilineal - + Frame&skip &Salto de cuadros - + Mute Silenciar - + FPS target Objetivo de FPS - + Native (59.7275) Nativo (59,7275) - + Take &screenshot Tomar pan&tallazo - + F12 F12 - + Game Boy Printer... Game Boy Printer... - + BattleChip Gate... BattleChip Gate... - + %1× %1× - + Interframe blending Mezcla entre cuadros - + Record A/V... Grabar A/V... - + Video layers Capas de video - + Audio channels Canales de audio - + Adjust layer placement... Ajustar ubicación de capas... - + &Tools Herramien&tas - + View &logs... Ver re&gistros... - + Game &overrides... Ajustes específic&os por juego... - + Couldn't Start No se pudo iniciar - + Could not start game. No se pudo iniciar el juego. - + Scan e-Reader dotcodes... Escanear dotcodes del e-Reader... - + Import GameShark Save... Importar desde GameShark... - + Export GameShark Save... Exportar a GameShark... - + Record GIF/WebP/APNG... Grabar GIF/WebP/APNG... - + &Cheats... Tru&cos... - + Settings... Ajustes... - + Open debugger console... Abrir consola de depuración... - + Start &GDB server... Iniciar servidor &GDB... - + Scripting... - + + Game state views + + + + View &palette... Ver &paleta... - + View &sprites... Ver &sprites... - + View &tiles... Ver m&osaicos... - + View &map... Ver &mapa... - + &Frame inspector... Inspec&tor de cuadros... - + View memory... Ver memoria... - + Search memory... Buscar memoria... - + View &I/O registers... Ver registros &I/O... - + Record debug video log... Grabar registro de depuración de video... - + Stop debug video log Detener registro de depuración de video - + Exit fullscreen Salir de pantalla completa - + GameShark Button (held) Botón GameShark (mantener) - + Autofire Disparo automático - + Autofire A Disparo automático A - + Autofire B Disparo automático B - + Autofire L Disparo automático L - + Autofire R Disparo automático R - + Autofire Start Disparo automático Start - + Autofire Select Disparo automático Select - + Autofire Up Disparo automático Arriba - + Autofire Right Disparo automático Derecha - + Autofire Down Disparo automático Abajo - + Autofire Left Disparo automático Izquierda @@ -5183,40 +5170,55 @@ Tamaño de la descarga: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset &Reinicializar - + 0 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5231,64 +5233,74 @@ Tamaño de la descarga: %3 Reloj en tiempo real - + Fixed time Hora fija - + System time Hora del sistema - + Start time at Empezar desde esta hora - + Now Ahora - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP dd/MM/yy HH:mm:ss - + Light sensor Sensor de luz - + Brightness Brillo - + Tilt sensor Sensor de inclinación - - + + Set Y Ajustar Y - - + + Set X Ajustar X - + Gyroscope Giroscopio - + Sensitivity Sensibilidad diff --git a/src/platform/qt/ts/mgba-fi.ts b/src/platform/qt/ts/mgba-fi.ts index 89e155475..4f4f313f1 100644 --- a/src/platform/qt/ts/mgba-fi.ts +++ b/src/platform/qt/ts/mgba-fi.ts @@ -1184,36 +1184,36 @@ Game Boy Advance on Nintendo Co., Ltd rekisteröimä tuotemerkki. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. - + Current version: %1 New version: %2 Download size: %3 - + Downloading update... - + Downloading failed. Please update manually. - + Downloading done. Press OK to restart %1 and install the update. @@ -1236,7 +1236,7 @@ Download size: %3 - + (None) @@ -1323,12 +1323,12 @@ Download size: %3 - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -1341,12 +1341,12 @@ Download size: %3 - + Could not load game. Are you sure it's in the correct format? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). @@ -3410,27 +3410,27 @@ Download size: %3 QGBA::LoadSaveState - + Load State - + Save State - + Empty - + Corrupted - + Slot %1 @@ -3859,12 +3859,12 @@ Download size: %3 QGBA::ReportView - + Bug report archive - + ZIP archive (*.zip) @@ -3935,29 +3935,11 @@ Download size: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4155,779 +4137,784 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) - - - + + + Select ROM - + Select folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) + - Select save state - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + GameShark saves (*.gsv *.sps *.xps) - + Convert e-Reader card image to raw... - + Import GameShark Save... - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + Scripting... - + + Game state views + + + + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear @@ -5176,40 +5163,55 @@ Download size: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset - + 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5224,64 +5226,74 @@ Download size: %3 - + Fixed time - + System time - + Start time at - + Now - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP - + Light sensor - + Brightness - + Tilt sensor - - + + Set Y - - + + Set X - + Gyroscope - + Sensitivity diff --git a/src/platform/qt/ts/mgba-fr.ts b/src/platform/qt/ts/mgba-fr.ts index e0f929526..7be421752 100644 --- a/src/platform/qt/ts/mgba-fr.ts +++ b/src/platform/qt/ts/mgba-fr.ts @@ -1186,21 +1186,21 @@ Game Boy Advance est une marque de fabrique enregistré par Nintendo Co., Ltd. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. Voulez-vous la télécharger et l'installer maintenant ? Vous devrez redémarrer l'émulateur lorsque le téléchargement sera terminé. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. La mise à jour automatique n'est pas disponible sur cette plateforme. Si vous souhaitez effectuer une mise à jour, vous devrez le faire manuellement. - + Current version: %1 New version: %2 Download size: %3 @@ -1209,17 +1209,17 @@ Nouvelle version : %2 Taille du téléchargement : %3 - + Downloading update... Téléchargement de la mise à jour... - + Downloading failed. Please update manually. Le téléchargement a échoué. Veuillez mettre à jour manuellement. - + Downloading done. Press OK to restart %1 and install the update. Téléchargement terminé. Appuyez sur OK pour redémarrer %1 et installer la mise à jour. @@ -1242,7 +1242,7 @@ Taille du téléchargement : %3 Inconnue - + (None) (Aucune) @@ -1329,12 +1329,12 @@ Taille du téléchargement : %3 - + Failed to open snapshot file for reading: %1 Échec de l'ouverture de l'instantané pour lire : %1 - + Failed to open snapshot file for writing: %1 Échec de l'ouverture de l'instantané pour écrire : %1 @@ -1347,12 +1347,12 @@ Taille du téléchargement : %3 Échec de l'ouverture du fichier de jeu : %1 - + Could not load game. Are you sure it's in the correct format? Impossible de charger le jeu. Êtes-vous sûr qu'il est dans le bon format ? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). Impossible d'ouvrir le fichier de sauvegarde ; les sauvegardes en jeu ne peuvent pas être mises à jour. Veuillez vous assurer que le répertoire de sauvegarde est accessible en écriture sans privilèges supplémentaires (par exemple, UAC sous Windows). @@ -3427,27 +3427,27 @@ Taille du téléchargement : %3 QGBA::LoadSaveState - + Load State Charger un état - + Save State Sauvegarder un état - + Empty Vide - + Corrupted Corrompue - + Slot %1 Emplacement %1 @@ -3883,12 +3883,12 @@ Taille du téléchargement : %3 QGBA::ReportView - + Bug report archive Archive de signalement d'erreur - + ZIP archive (*.zip) Archive ZIP (*.zip) @@ -3959,29 +3959,11 @@ Taille du téléchargement : %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4179,120 +4161,120 @@ Taille du téléchargement : %3 QGBA::Window - + Game Boy Advance ROMs (%1) ROMs de Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs de Game Boy (%1) - + All ROMs (%1) Toutes les ROM (%1) - + %1 Video Logs (*.mvl) %1 Journaux vidéo (*.mvl) - + Archives (%1) Archives (%1) - - - + + + Select ROM Choisir une ROM - + Select folder Choisir un dossier - - + + Select save Choisir une sauvegarde - + Select patch Sélectionner un correctif - + Patches (*.ips *.ups *.bps) Correctifs/Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode Sélectionnez le numéro de point du e-Reader - + e-Reader card (*.raw *.bin *.bmp) e-Reader carte (*.raw *.bin *.bmp) - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Select image Choisir une image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Image (*.png *.gif *.jpg *.jpeg);;Tous les fichiers (*) - + GameShark saves (*.sps *.xps) Sauvegardes GameShark (*.sps *.xps) - + Select video log Sélectionner un journal vidéo - + Video logs (*.mvl) Journaux vidéo (*.mvl) - + Crash Plantage - + The game has crashed with the following error: %1 @@ -4301,659 +4283,664 @@ Taille du téléchargement : %3 %1 - + Unimplemented BIOS call Requête au BIOS non supporté - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Ce jeu utilise un appel BIOS qui n'est pas implémenté. Veuillez utiliser le BIOS officiel pour une meilleure expérience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Échec de la création d'un périphérique d'affichage approprié, retour à l'affichage du logiciel. Les jeux peuvent fonctionner lentement, en particulier avec des fenêtres plus grandes. - + Really make portable? Vraiment rendre portable ? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Cela amènera l'émulateur à charger sa configuration depuis le même répertoire que l'exécutable. Souhaitez vous continuer ? - + Restart needed Un redémarrage est nécessaire - + Some changes will not take effect until the emulator is restarted. Certains changements ne prendront effet qu'après le redémarrage de l'émulateur. - + - Player %1 of %2 - Joueur %1 of %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Fichier - + Load &ROM... Charger une &ROM… - + Load ROM in archive... Charger la ROM d'une archive… - + Add folder to library... Ajouter un dossier à la bibliothèque… - + Load &patch... Charger un c&orrectif… - + Boot BIOS Démarrer le BIOS - + Replace ROM... Remplacer la ROM… - + + Game state views + + + + Convert e-Reader card image to raw... - + ROM &info... &Infos sur la ROM… - + Recent Récent - + Make portable Rendre portable - + &Load state &Charger un état - + &Save state &Sauvegarder un état - + Quick load Chargement rapide - + Quick save Sauvegarde rapide - + Load recent Charger un fichier récent - + Save recent Sauvegarder un fichier récent - + Undo load state Annuler le chargement de l'état - + Undo save state Annuler la sauvegarde de l'état - - + + State &%1 État &%1 - + Load camera image... Charger une image de la caméra… - + Convert save game... - + New multiplayer window Nouvelle fenêtre multijoueur - + Connect to Dolphin... - + Report bug... Signalement de l'erreur… - + E&xit &Quitter - + &Emulation &Émulation - + &Reset &Réinitialiser - + Sh&utdown Extin&ction - + Yank game pak Yank game pak - + &Pause &Pause - + &Next frame &Image suivante - + Fast forward (held) Avance rapide (maintenir) - + &Fast forward A&vance rapide - + Fast forward speed Vitesse de l'avance rapide - + Unbounded Sans limites - + %0x %0x - + Rewind (held) Rembobiner (maintenir) - + Re&wind Rem&bobiner - + Step backwards Retour en arrière - + Solar sensor Capteur solaire - + Increase solar level Augmenter le niveau solaire - + Decrease solar level Diminuer le niveau solaire - + Brightest solar level Tester le niveau solaire - + Darkest solar level Assombrir le niveau solaire - + Brightness %1 Luminosité %1 - + Audio/&Video Audio/&Vidéo - + Frame size Taille de l'image - + Toggle fullscreen Basculer en plein écran - + Lock aspect ratio Bloquer les proportions - + Force integer scaling Forcer la mise à l'échelle par des nombres entiers - + Bilinear filtering Filtrage bilinèaire - + Frame&skip &Saut d'image - + Mute Muet - + FPS target FPS ciblé - + Take &screenshot Prendre une ca&pture d'écran - + F12 F12 - + Game Boy Printer... Imprimante GameBoy… - + Video layers Couches vidéo - + Audio channels Canaux audio - + Adjust layer placement... Ajuster la disposition… - + &Tools Ou&tils - + View &logs... Voir les &journaux… - + Game &overrides... - + Couldn't Start N'a pas pu démarrer - + Save games (%1) - + Select save game - + mGBA save state files (%1) + - Select save state - + GameShark saves (*.gsv *.sps *.xps) - + Could not start game. Impossible de démarrer le jeu. - + Load alternate save game... - + Load temporary save game... - + Scan e-Reader dotcodes... Scanner les dotcodes e-Reader... - + Load state file... Charger le fichier d'état... - + Save state file... Enregistrer le fichier d'état... - + Import GameShark Save... Importer la sauvegarde de GameShark... - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games Sauvegarder les jeux - + Export GameShark Save... Exporter la sauvegarde de GameShark... - + Automatically determine - + Use player %0 save game - + About... À propos de… - + BattleChip Gate... - + %1× %1× - + Interframe blending Mélange d'images - + Native (59.7275) Natif (59.7275) - + Record A/V... Enregistrer A/V... - + Record GIF/WebP/APNG... Enregistrer GIF/WebP/APNG... - + Game Pak sensors... Capteurs de la Game Pak... - + &Cheats... &Cheats… - + Settings... Paramètres… - + Open debugger console... Ouvrir la console de débug… - + Start &GDB server... Démarrer le serveur &GDB… - + Scripting... - + View &palette... Voir la &palette… - + View &sprites... Voir les &sprites… - + View &tiles... Voir les &tiles… - + View &map... Voir la &map… - + &Frame inspector... Inspecteur de &frame... - + View memory... Voir la mémoire… - + Search memory... Recherche dans la mémoire… - + View &I/O registers... Voir les registres d'&E/S... - + Record debug video log... Enregistrer le journal vidéo de débogage... - + Stop debug video log Arrêter le journal vidéo de débogage - + Exit fullscreen Quitter le plein écran - + GameShark Button (held) Bouton GameShark (maintenir) - + Autofire Tir automatique - + Autofire A Tir automatique A - + Autofire B Tir automatique B - + Autofire L Tir automatique L - + Autofire R Tir automatique R - + Autofire Start Tir automatique Start - + Autofire Select Tir automatique Select - + Autofire Up Tir automatique Up - + Autofire Right Tir automatique Right - + Autofire Down Tir automatique Down - + Autofire Left Tir automatique Gauche - + Clear Vider @@ -5202,40 +5189,55 @@ Taille du téléchargement : %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset &Réinitialiser - + 0 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5250,65 +5252,75 @@ Taille du téléchargement : %3 Horloge en temps réel - + Fixed time Heure fixe - + System time Heure du système - + Start time at Heure de début à - + Now Maintenant - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP This is the most common format used in the francophile world dd/MM/yy HH:mm:ss - + Light sensor Capteur de lumière - + Brightness Luminosité - + Tilt sensor Capteur d'inclinaison - - + + Set Y Ensemble Y - - + + Set X Ensemble X - + Gyroscope Gyroscope - + Sensitivity Sensibilité diff --git a/src/platform/qt/ts/mgba-hu.ts b/src/platform/qt/ts/mgba-hu.ts index 00f149f95..6f1ab8711 100644 --- a/src/platform/qt/ts/mgba-hu.ts +++ b/src/platform/qt/ts/mgba-hu.ts @@ -1184,36 +1184,36 @@ A Game Boy Advance a Nintendo Co., Ltd. bejegyzett védjegye - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. - + Current version: %1 New version: %2 Download size: %3 - + Downloading update... - + Downloading failed. Please update manually. - + Downloading done. Press OK to restart %1 and install the update. @@ -1236,7 +1236,7 @@ Download size: %3 - + (None) @@ -1323,12 +1323,12 @@ Download size: %3 A játékkazettát nem lehet kirántani ismeretlen platformon! - + Failed to open snapshot file for reading: %1 A pillanatkép fájljának olvasásra való megnyitása sikertelen: %1 - + Failed to open snapshot file for writing: %1 A pillanatkép fájljának írásra való megnyitása sikertelen: %1 @@ -1341,12 +1341,12 @@ Download size: %3 Nem sikerült a játékfájl megnyitása: %1 - + Could not load game. Are you sure it's in the correct format? A játék betöltése nem sikerült. Biztos vagy benne, hogy a megfelelő formátumú? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). @@ -3410,27 +3410,27 @@ Download size: %3 QGBA::LoadSaveState - + Load State - + Save State - + Empty - + Corrupted - + Slot %1 @@ -3859,12 +3859,12 @@ Download size: %3 QGBA::ReportView - + Bug report archive - + ZIP archive (*.zip) @@ -3935,29 +3935,11 @@ Download size: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4153,779 +4135,784 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) - - - + + + Select ROM - + Select folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) + - Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x %0x - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + Scripting... - + + Game state views + + + + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear Napló törlése @@ -5174,40 +5161,55 @@ Download size: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset - + 0 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5222,64 +5224,74 @@ Download size: %3 Valósidejű óra - + Fixed time - + System time - + Start time at - + Now - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP - + Light sensor Fényérzékelő - + Brightness - + Tilt sensor - - + + Set Y - - + + Set X - + Gyroscope Giroszkóp - + Sensitivity diff --git a/src/platform/qt/ts/mgba-it.ts b/src/platform/qt/ts/mgba-it.ts index 8dbec5cd8..11f968726 100644 --- a/src/platform/qt/ts/mgba-it.ts +++ b/src/platform/qt/ts/mgba-it.ts @@ -1185,21 +1185,21 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. Vuoi scaricarlo e installarlo adesso? Dovrai riavviare l'emulatore quando il download sarà completato. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. L'aggiornamento automatico non è disponibile su questa piattaforma. Se vuoi aggiornare dovrai farlo manualmente. - + Current version: %1 New version: %2 Download size: %3 @@ -1208,17 +1208,17 @@ Nuova versione: %2 Dimensione del download: %3 - + Downloading update... Scaricamento aggiornamento in corso... - + Downloading failed. Please update manually. Download fallito. Si prega di aggiornare manualmente. - + Downloading done. Press OK to restart %1 and install the update. Download terminato. Premi OK per riavviare %1 e installare l'aggiornamento. @@ -1241,7 +1241,7 @@ Dimensione del download: %3 Sconosciuto - + (None) (Nessuno) @@ -1328,12 +1328,12 @@ Dimensione del download: %3 Non riesco a strappare il pacchetto in una piattaforma inaspettata! - + Failed to open snapshot file for reading: %1 Impossibile aprire il file snapshot per la lettura: %1 - + Failed to open snapshot file for writing: %1 Impossibile aprire il file snapshot per la scrittura: %1 @@ -1346,12 +1346,12 @@ Dimensione del download: %3 Impossibile aprire il file di gioco: %1 - + Could not load game. Are you sure it's in the correct format? Impossibile caricare il gioco. Sei sicuro che sia nel formato corretto? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). Impossibile aprire il file di salvataggio; i salvataggi in gioco non possono essere aggiornati. Assicurati che la directory di salvataggio sia scrivibile senza privilegi aggiuntivi (ad esempio UAC su Windows). @@ -3415,27 +3415,27 @@ Dimensione del download: %3 QGBA::LoadSaveState - + Load State Carica stato - + Save State Salva stato - + Empty Vuoto - + Corrupted Corrotto - + Slot %1 Slot %1 @@ -3864,12 +3864,12 @@ Dimensione del download: %3 QGBA::ReportView - + Bug report archive Archivio delle segnalazioni di bug - + ZIP archive (*.zip) Archivio ZIP (*.zip) @@ -3940,29 +3940,11 @@ Dimensione del download: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4160,115 +4142,115 @@ Dimensione del download: %3 QGBA::Window - + Game Boy Advance ROMs (%1) ROM per Game Boy Advance (%1) - + Game Boy ROMs (%1) ROM per Game Boy (%1) - + All ROMs (%1) Tutte le ROM (%1) - + %1 Video Logs (*.mvl) %1 log Video (*.mvl) - + Archives (%1) Archivi (%1) - - - + + + Select ROM Seleziona ROM - - + + Select save Seleziona salvataggio - + Select patch Seleziona patch - + Patches (*.ips *.ups *.bps) Patch (*.ips *.ups *.bps) - + Select e-Reader dotcode Selezione e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) e-Reader card (*.raw *.bin *.bmp) - + Select e-Reader card images Seleziona immagini carte e-Reader - + Image file (*.png *.jpg *.jpeg) File immagine (*.png *.jpg *.jpeg) - + Conversion finished Conversione terminata - + %1 of %2 e-Reader cards converted successfully. %1 di %2 carte e-Reader convertite con successo. - + Select image Seleziona immagine - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) File immagine (*.png *.gif *.jpg *.jpeg);;Tutti i file (*) - + GameShark saves (*.sps *.xps) Salvataggi GameShark (*.sps *.xps) - + Select video log Seleziona log video - + Video logs (*.mvl) Log video (*.mvl) - + Crash Errore fatale - + The game has crashed with the following error: %1 @@ -4277,664 +4259,669 @@ Dimensione del download: %3 %1 - + Unimplemented BIOS call BIOS non implementato - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Questo gioco utilizza una chiamata BIOS non implementata. Utilizza il BIOS ufficiale per una migliore esperienza. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Impossibile creare un dispositivo di visualizzazione appropriato, tornando alla visualizzazione software. I giochi possono funzionare lentamente, specialmente con finestre più grandi. - + Really make portable? Vuoi davvero rendere portatile l'applicazione? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? In questo modo l'emulatore carica la propria configurazione dalla stessa cartella dell'eseguibile. Vuoi continuare? - + Restart needed È necessario riavviare - + Some changes will not take effect until the emulator is restarted. Alcune modifiche non avranno effetto finché l'emulatore non verrà riavviato. - + - Player %1 of %2 - Giocatore %1 di %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File File - + Load &ROM... Carica ROM... - + Load ROM in archive... Carica la ROM in archivio... - + Load &patch... Carica patch... - + Boot BIOS Avvia BIOS - + Replace ROM... Sostituisci la ROM... - + Scan e-Reader dotcodes... Scansiona e-Reader dotcode... - + Convert e-Reader card image to raw... Converti immagini carte e-Reader in raw... - + ROM &info... Informazioni ROM... - + Recent Recenti - + Make portable Rendi portatile - + &Load state Carica stato - + &Save state Salva stato - + Quick load Caricamento rapido - + Quick save Salvataggio rapido - + Load recent Carica recente - + Save recent Salva recente - + Undo load state Annulla il caricamento dello stato - + Undo save state Annulla salvataggio stato - - + + State &%1 Stato %1 - + Load camera image... Carica immagine fotocamera... - + Convert save game... Converti salvataggi... - + GameShark saves (*.gsv *.sps *.xps) Salvataggi GameShark (*.gsv *.sps *.xps) - + Reset needed Reset necessario - + Some changes will not take effect until the game is reset. Alcune modifiche non si applicheranno finché il gioco non viene resettato. - + New multiplayer window Nuova finestra multigiocatore - + Connect to Dolphin... Connessione a Dolphin... - + Report bug... Segnala bug... - + E&xit Esci (&X) - + &Emulation Emulazione - + &Reset Reset - + Sh&utdown Spegni (&U) - + Yank game pak Yank game pak - + &Pause Pausa - + &Next frame Salta il prossimo frame (&N) - + Fast forward (held) Avanzamento rapido (tieni premuto) - + &Fast forward Avanzamento rapido (&F) - + Fast forward speed Velocità di avanzamento rapido - + Unbounded Illimitata - + %0x %0x - + Rewind (held) Riavvolgimento (tieni premuto) - + Re&wind Riavvolgimento (&W) - + Step backwards Torna indietro - + Solar sensor Sensore solare - + Increase solar level Incrementa il livello solare - + Decrease solar level Riduci il livello solare - + Brightest solar level Livello solare massimo - + Darkest solar level Livello solare minimo - + Brightness %1 Luminosità %1 - + Audio/&Video Audio/Video - + Frame size Dimensione frame - + Toggle fullscreen Abilita schermo Intero - + Lock aspect ratio Blocca rapporti aspetto - + Frame&skip Salto frame - + Mute Muto - + FPS target FPS finali - + Take &screenshot Acquisisci schermata - + F12 F12 - + Record GIF/WebP/APNG... Registra GIF / WebP / APNG ... - + Video layers Layers video - + Audio channels Canali audio - + &Tools Strumenti - + View &logs... Visualizza registri (&log)... - + Game &overrides... Valore specifico per il gioco... - + &Cheats... Trucchi... - + Open debugger console... Apri console debugger... - + Start &GDB server... Avvia server GDB... - + Settings... Impostazioni... - + Select folder Seleziona cartella - + Couldn't Start Non è stato possibile avviare - + Could not start game. Non è stato possibile avviare il gioco. - + Add folder to library... Aggiungi cartella alla libreria... - + Load state file... Carica stato di salvataggio... - + Save state file... Salva stato di salvataggio... - + Import GameShark Save... Importa Salvataggio GameShark... - + Export GameShark Save... Esporta Salvataggio GameShark... - + About... Informazioni… - + Force integer scaling Forza ridimensionamento a interi - + Bilinear filtering Filtro bilineare - + Game Boy Printer... Stampante Game Boy... - + Save games (%1) Salvataggi (%1) - + Select save game Seleziona salvataggio - + mGBA save state files (%1) file di stati di salvataggio mGBA (%1) + - Select save state Seleziona stato di salvataggio - + Save games Salvataggi - + Load alternate save game... Carica stato di salvataggio alternativo... - + Load temporary save game... Carica salvataggio temporaneo... - + Automatically determine Determina automaticamente - + Use player %0 save game Usa il salvataggio del giocatore %0 - + BattleChip Gate... BattleChip Gate... - + %1× %1x - + Interframe blending Miscelazione dei frame - + Native (59.7275) Nativo (59.7) - + Record A/V... Registra A/V... - + Adjust layer placement... Regola posizionamento layer... - + Game Pak sensors... Sensori Game Pak... - + Scripting... - + + Game state views + + + + View &palette... Mostra palette... - + View &sprites... Mostra sprites... - + View &tiles... Mostra tiles... - + View &map... Mostra mappa... - + &Frame inspector... &Frame inspector... - + View memory... Mostra memoria... - + Search memory... Ricerca memoria... - + View &I/O registers... Mostra registri I/O... - + Record debug video log... Registra video log di debug... - + Stop debug video log Ferma video log di debug - + Exit fullscreen Esci da Schermo Intero - + GameShark Button (held) Pulsante GameShark (tieni premuto) - + Autofire Pulsanti Autofire - + Autofire A Autofire A - + Autofire B Autofire B - + Autofire L Autofire L - + Autofire R Autofire R - + Autofire Start Autofire Start - + Autofire Select Autofire Select - + Autofire Up Autofire Su - + Autofire Right AAutofire Destra - + Autofire Down Autofire Giù - + Autofire Left Autofire Sinistra - + Clear Pulisci @@ -5183,40 +5170,55 @@ Dimensione del download: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset Reset - + 0 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5231,64 +5233,74 @@ Dimensione del download: %3 Clock in tempo reale - + Fixed time Ora fissa - + System time Ora del sistema - + Start time at Avvia tempo a - + Now Adesso - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP dd/MM/yy HH:mm:ss - + Light sensor Sensore di luce - + Brightness Luminosità - + Tilt sensor Sensore di inclinazione - - + + Set Y Config. Y - - + + Set X Config. X - + Gyroscope Giroscopio - + Sensitivity Sensibilità diff --git a/src/platform/qt/ts/mgba-ja.ts b/src/platform/qt/ts/mgba-ja.ts index d230a676a..bb94da436 100644 --- a/src/platform/qt/ts/mgba-ja.ts +++ b/src/platform/qt/ts/mgba-ja.ts @@ -1184,36 +1184,36 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. - + Current version: %1 New version: %2 Download size: %3 - + Downloading update... - + Downloading failed. Please update manually. - + Downloading done. Press OK to restart %1 and install the update. @@ -1236,7 +1236,7 @@ Download size: %3 不明 - + (None) @@ -1323,12 +1323,12 @@ Download size: %3 予期しないプラットフォームでパックをヤンクすることはできません! - + Failed to open snapshot file for reading: %1 読み取り用のスナップショットファイルを開けませんでした: %1 - + Failed to open snapshot file for writing: %1 書き込み用のスナップショットファイルを開けませんでした: %1 @@ -1341,12 +1341,12 @@ Download size: %3 ゲームファイルを開けませんでした: %1 - + Could not load game. Are you sure it's in the correct format? ゲームをロードできませんでした。ゲームのフォーマットが正しいことを確認してください。 - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). @@ -3410,27 +3410,27 @@ Download size: %3 QGBA::LoadSaveState - + Load State ステートをロード - + Save State ステートをセーブ - + Empty - + Corrupted 破損 - + Slot %1 スロット %1 @@ -3859,12 +3859,12 @@ Download size: %3 QGBA::ReportView - + Bug report archive バグレポートアーカイブ - + ZIP archive (*.zip) ZIPアーカイブ (*.zip) @@ -3935,29 +3935,11 @@ Download size: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4153,100 +4135,100 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) ゲームボーイアドバンスファイル (%1) - + Game Boy ROMs (%1) ゲームボーイファイル (%1) - + All ROMs (%1) すべてのファイル (%1) - + %1 Video Logs (*.mvl) %1ビデオログ (*.mvl) - + Archives (%1) アーカイブファイル (%1) - - - + + + Select ROM ROMを開く - + Select folder フォルダを開く - - + + Select save セーブを開く - + Select patch パッチを開く - + Patches (*.ips *.ups *.bps) パッチファイル (*.ips *.ups *.bps) - + Select e-Reader dotcode カードeを開く - + e-Reader card (*.raw *.bin *.bmp) カードe (*.raw *.bin *.bmp) - + Select image 画像を開く - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) 画像ファイル (*.png *.gif *.jpg *.jpeg);;すべてのファイル (*) - + GameShark saves (*.sps *.xps) GameSharkセーブファイル (*.sps *.xps) - + Select video log ビデオログを開く - + Video logs (*.mvl) ビデオログ (*.mvl) - + Crash クラッシュ - + The game has crashed with the following error: %1 @@ -4255,679 +4237,684 @@ Download size: %3 %1 - + Couldn't Start 起動失敗 - + Could not start game. ゲームを起動できませんでした。 - + Unimplemented BIOS call 未実装のBIOS呼び出し - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. このゲームは実装されていないBIOS呼び出しを使用します。最高のエクスペリエンスを得るには公式のBIOSを使用してください。 - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. 適切なディスプレイデバイスの作成に失敗し、ソフトディスプレイにフォールバックしました。特に大きなウィンドウでは、ゲームの実行が遅い場合があります。 - + Really make portable? 本当にポータブルにしますか? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? これによりエミュレータは実行ファイルと同じディレクトリにある設定ファイルをロードします。続けますか? - + Restart needed 再起動が必要 - + Some changes will not take effect until the emulator is restarted. 一部の変更は、エミュレータを再起動するまで有効になりません。 - + - Player %1 of %2 - プレーヤー %1 of %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &ファイル (&F) - + Load &ROM... ROMをロード... - + Load ROM in archive... アーカイブにROMをロード... - + Add folder to library... ライブラリーにフォルダを追加... - + Load &patch... パッチをロード... (&P) - + Boot BIOS BIOSを起動 - + Replace ROM... ROMを交換... - + Scan e-Reader dotcodes... カードeをスキャン... - + ROM &info... ROM情報... (&I) - + Recent 最近開いたROM - + Make portable ポータブル化 - + &Load state ステートをロード (&L) - + Report bug... バグ報告 - + About... バージョン情報... - + Record GIF/WebP/APNG... GIF/WebP/APNGを記録 - + Game Pak sensors... カートリッジセンサー... - + Clear 消去 - + Load state file... ステートファイルをロード... - + Save games (%1) - + Select save game - + mGBA save state files (%1) + - Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Convert e-Reader card image to raw... - + &Save state ステートをセーブ (&S) - + Save state file... ステートファイルをセーブ... - + Quick load クイックロード - + Quick save クイックセーブ - + Load recent 最近使ったクイックロットからロード - + Save recent 最近使ったクイックロットにセーブ - + Undo load state クイックロードを元に戻す - + Undo save state クイックセーブを元に戻す - - + + State &%1 クイックスロット &%1 - + Load camera image... カメラ画像をロード... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Import GameShark Save... GameSharkスナップショットを読み込む - + Export GameShark Save... GameSharkスナップショットを書き出す - + New multiplayer window 新しいウィンドウ(マルチプレイ) - + Connect to Dolphin... - + E&xit 終了 (&X) - + &Emulation エミュレーション (&E) - + &Reset リセット (&R) - + Sh&utdown 閉じる (&U) - + Yank game pak ゲームパックをヤンク - + &Pause 一時停止 (&P) - + &Next frame 次のフレーム (&N) - + Fast forward (held) 早送り(押し) - + &Fast forward 早送り (&F) - + Fast forward speed 早送り速度 - + Unbounded 制限なし - + %0x %0x - + Rewind (held) 巻戻し(押し) - + Re&wind 巻戻し (&R) - + Step backwards 1フレーム巻き戻す - + Solar sensor 太陽センサー - + Increase solar level 明るさを上げる - + Decrease solar level 明るさを下げる - + Brightest solar level 明るさ最高 - + Darkest solar level 明るさ最低 - + Brightness %1 明るさ %1 - + Audio/&Video オーディオ/ビデオ (&V) - + Frame size 画面サイズ - + Toggle fullscreen 全画面表示 - + Lock aspect ratio 縦横比を固定 - + Force integer scaling 整数スケーリングを強制 - + Bilinear filtering バイリニアフィルタリング - + Frame&skip フレームスキップ (&S) - + Mute ミュート - + FPS target FPS - + Native (59.7275) ネイティブ(59.7275) - + Take &screenshot スクリーンショット (&S) - + F12 F12 - + Game Boy Printer... ポケットプリンタ... - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games セーブデータ - + Automatically determine - + Use player %0 save game - + BattleChip Gate... チップゲート... - + %1× %1× - + Interframe blending フレーム間混合 - + Record A/V... ビデオ録画... - + Video layers ビデオレイヤー - + Audio channels オーディオチャンネル - + Adjust layer placement... レイヤーの配置を調整... - + &Tools ツール (&T) - + View &logs... ログビューアー... (&L) - + Game &overrides... ゲーム別設定... (&O) - + &Cheats... チート... (&C) - + Settings... 設定... - + Open debugger console... デバッガコンソールを開く... - + Start &GDB server... GDBサーバを起動... (&G) - + Scripting... - + + Game state views + + + + View &palette... パレットビューアー... (&P) - + View &sprites... スプライトビューアー... (&S) - + View &tiles... タイルビューアー... (&T) - + View &map... マップビューアー... (&M) - + &Frame inspector... フレームインスペクタ... (&F) - + View memory... メモリビューアー... - + Search memory... メモリ検索... - + View &I/O registers... IOビューアー... (&I) - + Record debug video log... デバッグビデオログ... - + Stop debug video log デバッグビデオログを停止 - + Exit fullscreen 全画面表示を終了 - + GameShark Button (held) GameSharkボタン(押し) - + Autofire 連打 - + Autofire A 連打 A - + Autofire B 連打 B - + Autofire L 連打 L - + Autofire R 連打 R - + Autofire Start 連打 Start - + Autofire Select 連打 Select - + Autofire Up 連打 上 - + Autofire Right 連打 右 - + Autofire Down 連打 下 - + Autofire Left 連打 左 @@ -5176,40 +5163,55 @@ Download size: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset リセット (&R) - + 0 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5224,64 +5226,74 @@ Download size: %3 リアルタイムクロック - + Fixed time 定刻 - + System time システム日時 - + Start time at 日時指定 - + Now 現在日時 - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP yyyy/MM/dd HH:mm:ss - + Light sensor 光センサー - + Brightness 明るさ - + Tilt sensor 動きセンサー - - + + Set Y 垂直方向 - - + + Set X 水平方向 - + Gyroscope 回転センサー - + Sensitivity 感度 diff --git a/src/platform/qt/ts/mgba-ko.ts b/src/platform/qt/ts/mgba-ko.ts index 477f49ea9..61bf09771 100644 --- a/src/platform/qt/ts/mgba-ko.ts +++ b/src/platform/qt/ts/mgba-ko.ts @@ -1184,36 +1184,36 @@ Game Boy Advance는 Nintendo Co., Ltd.의 등록 상표입니다. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. - + Current version: %1 New version: %2 Download size: %3 - + Downloading update... - + Downloading failed. Please update manually. - + Downloading done. Press OK to restart %1 and install the update. @@ -1236,7 +1236,7 @@ Download size: %3 - + (None) @@ -1323,12 +1323,12 @@ Download size: %3 - + Failed to open snapshot file for reading: %1 읽기 용 스냅샷 파일을 열지 못했습니다: %1 - + Failed to open snapshot file for writing: %1 쓰기 용 스냅샷 파일을 열지 못했습니다: %1 @@ -1341,12 +1341,12 @@ Download size: %3 게임 파일을 열지 못했습니다: %1 - + Could not load game. Are you sure it's in the correct format? 게임을 로드할 수 없습니다. 올바른 형식인지 확인하십시오. - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). @@ -3410,27 +3410,27 @@ Download size: %3 QGBA::LoadSaveState - + Load State 로드 상태 - + Save State 저장 상태 - + Empty - + Corrupted 손상 - + Slot %1 슬롯 %1 @@ -3859,12 +3859,12 @@ Download size: %3 QGBA::ReportView - + Bug report archive - + ZIP archive (*.zip) @@ -3935,29 +3935,11 @@ Download size: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4153,115 +4135,115 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) 게임 보이 어드밴스 롬 (%1) - + Game Boy ROMs (%1) 게임 보이 (%1) - + All ROMs (%1) 모든 롬 (%1) - + %1 Video Logs (*.mvl) %1 비디오 로그 (*.mvl) - + Archives (%1) 아카이브 (%1) - - - + + + Select ROM 롬 선택 - - + + Select save 저장 파일 선택 - + Select patch 패치 선택 - + Patches (*.ips *.ups *.bps) 패치 (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Select image 이미지 선택 - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) 이미지 파일 (*.png *.gif *.jpg *.jpeg);;모든 파일 (*) - + GameShark saves (*.sps *.xps) 게임샤크 저장 파일 (*.sps *.xps) - + Select video log 비디오 로그 선택 - + Video logs (*.mvl) 비디오 로그 (*.mvl) - + Crash 치명적인 오류 - + The game has crashed with the following error: %1 @@ -4270,664 +4252,669 @@ Download size: %3 %1 - + Unimplemented BIOS call 구현되지 않은 바이오스 호출 - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. 이 게임은 구현되지 않은 바이오스 호출을 사용합니다. 최상의 성능을 얻으려면 공식 바이오스를 사용하십시오. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? 정말로 휴대용을 만듭니까? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? 이렇게하면 에뮬레이터가 실행 파일과 동일한 디렉토리에서 구성을 로드하게됩니다. 계속 하시겠습니까? - + Restart needed 재시작 필요 - + Some changes will not take effect until the emulator is restarted. 일부 변경 사항은 에뮬레이터가 다시 시작될 때까지 적용되지 않습니다. - + Reset needed - + Some changes will not take effect until the game is reset. - + - Player %1 of %2 - 플레이어 %1 의 %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &파일 - + Load &ROM... 로드 &롬... - + Load ROM in archive... 롬을 아카이브에 로드... - + Save games 게임 저장 - + Automatically determine - + Use player %0 save game - + Load &patch... 로드 &패치... - + Boot BIOS BIOS 부팅 - + Replace ROM... 롬 교체... - + Scan e-Reader dotcodes... - + + Game state views + + + + Convert e-Reader card image to raw... - + ROM &info... 롬 &정보... - + Recent 최근 실행 - + Make portable 휴대용 만들기 - + &Load state &로드 파일 상태 - + &Save state &저장 파일 상태 - + Quick load 빠른 로드 - + Quick save 빠른 저장 - + Load recent 최근 실행 로드 - + Save recent 최근 실행 저장 - + Undo load state 로드 파일 상태 복원 - + Undo save state 저장 파일 상태 복원 - - + + State &%1 상태 &%1 - + Load camera image... 카메라 이미지 로드... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + New multiplayer window 새로운 멀티 플레이어 창 - + Connect to Dolphin... - + E&xit 종&료 - + &Emulation &에뮬레이션 - + &Reset &재설정 - + Sh&utdown 종&료 - + Yank game pak 양키 게임 팩 - + &Pause &정지 - + &Next frame &다음 프레임 - + Fast forward (held) 빨리 감기 (누름) - + &Fast forward &빨리 감기 - + Fast forward speed 빨리 감기 속도 - + Unbounded 무제한 - + %0x %0x - + Rewind (held) 되김기 (누름) - + Re&wind 리&와인드 - + Step backwards 돌아가기 - + Brightest solar level 가장 밝은 태양 수준 - + Darkest solar level 가장 어두운 태양 수준 - + Brightness %1 밝기 %1 - + Audio/&Video 오디오/&비디오 - + Frame size 프레임 크기 - + Toggle fullscreen 전체화면 전환 - + Lock aspect ratio 화면비 잠금 - + Frame&skip 프레임&건너뛰기 - + Mute 무음 - + FPS target FPS 대상 - + Take &screenshot 스크린샷 &찍기 - + F12 F12 - + Video layers 비디오 레이어 - + Audio channels 오디오 채널 - + &Tools &도구 - + View &logs... 로그 &보기... - + Game &overrides... 게임 &오버라이드... - + &Cheats... &치트.. - + Open debugger console... 디버거 콘솔 열기... - + Start &GDB server... GDB 서버 &시작... - + Settings... 설정... - + Select folder 폴더 선택 - + Couldn't Start - + Could not start game. - + Add folder to library... 라이브러리에 폴더 추가... - + Load state file... - + Save state file... - + Import GameShark Save... - + Export GameShark Save... - + Report bug... - + About... - + Solar sensor - + Increase solar level - + Decrease solar level - + Force integer scaling 정수 스케일링 강제 수행 - + Bilinear filtering 이중선형 필터링 - + Game Boy Printer... 게임 보이 프린터... - + Save games (%1) - + Select save game - + mGBA save state files (%1) + - Select save state - + Load alternate save game... - + Load temporary save game... - + BattleChip Gate... - + %1× %1x {1×?} - + Interframe blending - + Native (59.7275) Nativo (59.7) {59.7275)?} - + Record A/V... - + Record GIF/WebP/APNG... - + Adjust layer placement... 레이어 배치 조정... - + Game Pak sensors... - + Scripting... - + View &palette... 팔레트 &보기... - + View &sprites... 스프라이트 &보기... - + View &tiles... 타일 &보기... - + View &map... 지도 &보기... - + &Frame inspector... - + View memory... 메모리 보기... - + Search memory... 메모리 검색... - + View &I/O registers... I/O 레지스터 &보기... - + Record debug video log... - + Stop debug video log - + Exit fullscreen 전체화면 종료 - + GameShark Button (held) 게임샤크 버튼 (누름) - + Autofire 연사 - + Autofire A 연사 A - + Autofire B 연사 B - + Autofire L 연사 L - + Autofire R 연사 R - + Autofire Start 연사 시작 - + Autofire Select - + Clear 정리 - + Autofire Up 연사 위쪽 - + Autofire Right 연사 오른쪽 - + Autofire Down 연사 아래쪽 - + Autofire Left 연사 왼쪽 @@ -5176,40 +5163,55 @@ Download size: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset &재설정 - + 0 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5224,64 +5226,74 @@ Download size: %3 실시간 시계 - + Fixed time 수정된 시간 - + System time 시스템 시간 - + Start time at 시작 시간 - + Now 지금 - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP gg/MM/aa OO:mm:ss - + Light sensor 광센서 - + Brightness 밝기 - + Tilt sensor 기울기 센서 - - + + Set Y Y 설정 - - + + Set X X 설정 - + Gyroscope 자이로스코프 - + Sensitivity 감광도 diff --git a/src/platform/qt/ts/mgba-ms.ts b/src/platform/qt/ts/mgba-ms.ts index 494031c44..83e391e03 100644 --- a/src/platform/qt/ts/mgba-ms.ts +++ b/src/platform/qt/ts/mgba-ms.ts @@ -1183,36 +1183,36 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. - + Current version: %1 New version: %2 Download size: %3 - + Downloading update... - + Downloading failed. Please update manually. - + Downloading done. Press OK to restart %1 and install the update. @@ -1235,7 +1235,7 @@ Download size: %3 - + (None) @@ -1322,12 +1322,12 @@ Download size: %3 - + Failed to open snapshot file for reading: %1 Gagal membuka fail snapshot untuk baca: %1 - + Failed to open snapshot file for writing: %1 Gagal membuka fail snapshot untuk menulis: %1 @@ -1340,12 +1340,12 @@ Download size: %3 Gagal membuka fail permainan: %1 - + Could not load game. Are you sure it's in the correct format? Gagal memuat permainan. Adakah ia dalam format betul? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). @@ -3409,27 +3409,27 @@ Download size: %3 QGBA::LoadSaveState - + Load State Keadaan Termuat - + Save State Keadaan Tersimpan - + Empty Kosong - + Corrupted Rosak - + Slot %1 Slot %1 @@ -3858,12 +3858,12 @@ Download size: %3 QGBA::ReportView - + Bug report archive Arkib laporan pepijat - + ZIP archive (*.zip) Arkib ZIP (*.zip) @@ -3934,29 +3934,11 @@ Download size: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4152,100 +4134,100 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) ROM Game Boy Advance (%1) - + Game Boy ROMs (%1) ROM Game Boy (%1) - + All ROMs (%1) Semua ROM (%1) - + %1 Video Logs (*.mvl) %1 Log Video (*.mvl) - + Archives (%1) Arkib (%1) - - - + + + Select ROM Pilih ROM - + Select folder Pilih folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image Pilih gambar - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Fail gambar (*.png *.gif *.jpg *.jpeg);;Semua fail (*) - + GameShark saves (*.sps *.xps) Simpanan GameShark (*.sps *.xps) - + Select video log Pilih log video - + Video logs (*.mvl) Log video (*.mvl) - + Crash Nahas - + The game has crashed with the following error: %1 @@ -4254,679 +4236,684 @@ Download size: %3 %1 - + Couldn't Start Tidak dapat memula - + Could not start game. Permainan tidak dapat bermula. - + Unimplemented BIOS call Panggilan BIOS yg belum dilaksanakan - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Permainan ini menggunakan panggilan BIOS yang belum dilaksanakan. Sila pakai BIOS rasmi untuk pengalaman yang lebih baik. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Gagal mencipta peranti paparan yang sesuai, berbalik ke paparan perisian. Permainan mungkin menjadi lembap, terutamanya dengan tetingkap besar. - + Really make portable? Betulkah mahu buat jadi mudah alih? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Ini akan menetapkan pelagak untuk muat konfigurasi dari direktori yang sama dengan fail bolehlakunya. Teruskan? - + Restart needed Mula semula diperlukan - + Some changes will not take effect until the emulator is restarted. Beberapa perubahan tidak akan dilaksanakan sehingga pelagak dimula semula. - + - Player %1 of %2 - Pemain %1 dari %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &File - + Load &ROM... Muat %ROM... - + Load ROM in archive... Muat ROM daripada arkib... - + Add folder to library... Tambah folder ke perpustakaan... - + Save games (%1) Simpanan permainan (%1) - + Select save game Pilih simpanan permainan - + mGBA save state files (%1) mGBA fail keadaan tersimpan (%1) + - Select save state Pilih keadaan tersimpan - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) Fail gambar (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... Muat simpanan permainan alternatif... - + Load temporary save game... Muat simpanan permainan sementara... - + Load &patch... - + Boot BIOS But BIOS - + Replace ROM... Ganti ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... &Perihal ROM... - + Recent Terkini - + Make portable Buat jadi mudah alih - + &Load state &Muat keadaan - + Load state file... Muat fail keadaan... - + &Save state &Simpan keadaan - + Save state file... Simpan fail keadaan... - + Quick load - + Quick save - + Load recent Muat terkini - + Save recent Simpan terkini - + Undo load state Buat asal keadaan termuat - + Undo save state Buat asal keadaan tersimpan - - + + State &%1 Keadaan &%1 - + Load camera image... Muat gambar kamera... - + Convert save game... Tukar simpanan permainan... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games Simpanan permainan - + Import GameShark Save... Import Simpanan GameShark... - + Export GameShark Save... Eksport Simpanan GameShark... - + Automatically determine - + Use player %0 save game - + New multiplayer window Tetingkap multipemain baru - + Connect to Dolphin... Sambung ke Dolphin... - + Report bug... Laporkan pepijat... - + About... Perihal... - + E&xit &Keluar - + &Emulation Pe&lagak - + &Reset - + Sh&utdown &Matikan - + Yank game pak Alih keluar Game Pak - + &Pause &Jeda - + &Next frame Bingkai se&terusnya - + Fast forward (held) Mundar laju (pegang) - + &Fast forward Mundar &laju - + Fast forward speed Kelajuan mundar laju - + Unbounded Tidak terbatas - + %0x %0x - + Rewind (held) Putar balik (pegang) - + Re&wind Ma&ndir - + Step backwards Langkah belakang - + Solar sensor Pengesan suria - + Increase solar level Meningkatkan aras suria - + Decrease solar level Mengurangkan aras suria - + Brightest solar level Aras suria paling terang - + Darkest solar level Aras suria paling gelap - + Brightness %1 Kecerahan %1 - + Game Boy Printer... Pencetak Game Boy... - + BattleChip Gate... BattleChip Gate... - + Audio/&Video Audio/&Video - + Frame size Saiz bingkai - + %1× %1× - + Toggle fullscreen Togol skrinpenuh - + Lock aspect ratio Kekalkan nisbah aspek - + Force integer scaling Paksa skala integer - + Interframe blending Persebatian antarabingkai - + Bilinear filtering Penapisan bilinear - + Frame&skip Langkauan &bingkai - + Mute Senyap - + FPS target Sasaran FPS - + Native (59.7275) Asal (59.7275) - + Take &screenshot Ambil &cekupan skrin - + F12 F12 - + Record A/V... Rakam A/V... - + Record GIF/WebP/APNG... Rakam GIF/WebP/APNG... - + Video layers Lapisan video - + Audio channels Saluran audio - + Adjust layer placement... Melaras peletakan lapisan... - + &Tools &Alat - + View &logs... Lihat &log... - + Game &overrides... - + Game Pak sensors... Pengesan Game Pak... - + &Cheats... &Tipu... - + Settings... Tetapan... - + Open debugger console... Buka konsol penyahpepijat... - + Start &GDB server... Mula pelayan &GDB... - + Scripting... - + + Game state views + + + + View &palette... Pelihat &palet... - + View &sprites... - + View &tiles... Pelihat &jubin... - + View &map... Pelihat pe&ta... - + &Frame inspector... Periksa &bingkai... - + View memory... Lihat ingatan... - + Search memory... Cari ingatan... - + View &I/O registers... Lihat daftar &I/O... - + Record debug video log... Rakam log video nyahpepijat... - + Stop debug video log Henti log video nyahpepijat - + Exit fullscreen Keluar skrinpenuh - + GameShark Button (held) Butang GameShark (pegang) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear Kosongkan @@ -5175,40 +5162,55 @@ Download size: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset - + 0 4K {0?} + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5223,64 +5225,74 @@ Download size: %3 - + Fixed time - + System time - + Start time at - + Now - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP - + Light sensor - + Brightness - + Tilt sensor - - + + Set Y - - + + Set X - + Gyroscope - + Sensitivity diff --git a/src/platform/qt/ts/mgba-nb_NO.ts b/src/platform/qt/ts/mgba-nb_NO.ts index a3ed6842b..b6ba16304 100644 --- a/src/platform/qt/ts/mgba-nb_NO.ts +++ b/src/platform/qt/ts/mgba-nb_NO.ts @@ -1184,36 +1184,36 @@ Game Boy Advance er et registrert varemerke tilhørende Nintendo Co., Ltd. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. - + Current version: %1 New version: %2 Download size: %3 - + Downloading update... - + Downloading failed. Please update manually. - + Downloading done. Press OK to restart %1 and install the update. @@ -1236,7 +1236,7 @@ Download size: %3 Ukjent - + (None) @@ -1323,12 +1323,12 @@ Download size: %3 - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -1341,12 +1341,12 @@ Download size: %3 Klarte ikke å åpne spillfil: %1 - + Could not load game. Are you sure it's in the correct format? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). @@ -3410,27 +3410,27 @@ Download size: %3 QGBA::LoadSaveState - + Load State - + Save State - + Empty Tom - + Corrupted Skadet - + Slot %1 Plass %1 @@ -3859,12 +3859,12 @@ Download size: %3 QGBA::ReportView - + Bug report archive - + ZIP archive (*.zip) ZIP-arkiv (*.zip) @@ -3935,29 +3935,11 @@ Download size: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4155,779 +4137,784 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) Arkiv (%1) - - - + + + Select ROM Velg ROM - + Select folder Velg mappe - - + + Select save - + Select patch Velg feilfiks - + Patches (*.ips *.ups *.bps) Feilfikser (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image Velg bilde - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Bildefil (*.png *.gif *.jpg *.jpeg);;All filer (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash Krasj - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) + - Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + Scripting... - + + Game state views + + + + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear Tøm @@ -5176,40 +5163,55 @@ Download size: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset - + 0 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5224,64 +5226,74 @@ Download size: %3 Sanntidsklokke - + Fixed time - + System time - + Start time at - + Now - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP - + Light sensor Lyssensor - + Brightness - + Tilt sensor - - + + Set Y - - + + Set X - + Gyroscope Gyroskop - + Sensitivity diff --git a/src/platform/qt/ts/mgba-nl.ts b/src/platform/qt/ts/mgba-nl.ts index 3b8435267..ff7c31276 100644 --- a/src/platform/qt/ts/mgba-nl.ts +++ b/src/platform/qt/ts/mgba-nl.ts @@ -1183,36 +1183,36 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. - + Current version: %1 New version: %2 Download size: %3 - + Downloading update... - + Downloading failed. Please update manually. - + Downloading done. Press OK to restart %1 and install the update. @@ -1235,7 +1235,7 @@ Download size: %3 - + (None) @@ -1322,12 +1322,12 @@ Download size: %3 - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -1340,12 +1340,12 @@ Download size: %3 - + Could not load game. Are you sure it's in the correct format? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). @@ -3409,27 +3409,27 @@ Download size: %3 QGBA::LoadSaveState - + Load State - + Save State - + Empty - + Corrupted - + Slot %1 @@ -3858,12 +3858,12 @@ Download size: %3 QGBA::ReportView - + Bug report archive - + ZIP archive (*.zip) @@ -3934,29 +3934,11 @@ Download size: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4154,779 +4136,784 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) - - - + + + Select ROM - + Select folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) + - Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + Scripting... - + + Game state views + + + + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear @@ -5175,40 +5162,55 @@ Download size: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset - + 0 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5223,64 +5225,74 @@ Download size: %3 - + Fixed time - + System time - + Start time at - + Now - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP - + Light sensor - + Brightness - + Tilt sensor - - + + Set Y - - + + Set X - + Gyroscope - + Sensitivity diff --git a/src/platform/qt/ts/mgba-pl.ts b/src/platform/qt/ts/mgba-pl.ts index 12ec17639..d3b4edc8d 100644 --- a/src/platform/qt/ts/mgba-pl.ts +++ b/src/platform/qt/ts/mgba-pl.ts @@ -1185,21 +1185,21 @@ Game Boy Advance jest zarejestrowanym znakiem towarowym Nintendo Co., Ltd. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. Czy chcesz ją teraz pobrać i zainstalować? Po zakończeniu pobierania konieczne będzie ponowne uruchomienie emulatora. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. Automatyczna aktualizacja nie jest dostępna na tej platformie. Jeśli chcesz zaktualizować, musisz to zrobić ręcznie. - + Current version: %1 New version: %2 Download size: %3 @@ -1208,17 +1208,17 @@ Nowa wersja: %2 Rozmiar pobierania: %3 - + Downloading update... Pobieranie aktualizacji... - + Downloading failed. Please update manually. Pobieranie nie powiodło się. Proszę zaktualizować ręcznie. - + Downloading done. Press OK to restart %1 and install the update. Pobieranie zakończone. Naciśnij OK, aby ponownie uruchomić %1 i zainstalować aktualizację. @@ -1241,7 +1241,7 @@ Rozmiar pobierania: %3 Nieznana - + (None) (Żadna) @@ -1328,12 +1328,12 @@ Rozmiar pobierania: %3 Nie można wyciągnąć pack na nieoczekiwanej platformie! - + Failed to open snapshot file for reading: %1 Nie udało się otworzyć pliku snapshot do odczytu: %1 - + Failed to open snapshot file for writing: %1 Nie udało się otworzyć pliku snapshot do zapisu: %1 @@ -1346,12 +1346,12 @@ Rozmiar pobierania: %3 Nie udało się otworzyć pliku gry: %1 - + Could not load game. Are you sure it's in the correct format? Nie udało się wczytać gry. Czy na pewno jest we właściwym formacie? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). Nie udało się otworzyć pliku zapisu; zapisy w grze nie mogą być aktualizowane. Upewnij się, że katalog zapisu jest zapisywalny bez dodatkowych uprawnień (np. UAC w systemie Windows). @@ -3415,27 +3415,27 @@ Rozmiar pobierania: %3 QGBA::LoadSaveState - + Load State Załaduj Stan - + Save State Zapisz Stan - + Empty Pusty - + Corrupted Uszkodzony - + Slot %1 Slot %1 @@ -3864,12 +3864,12 @@ Rozmiar pobierania: %3 QGBA::ReportView - + Bug report archive Archiwum raportów o błędach - + ZIP archive (*.zip) Archiwum ZIP (*.zip) @@ -3940,29 +3940,11 @@ Rozmiar pobierania: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4162,100 +4144,100 @@ Rozmiar pobierania: %3 QGBA::Window - + Game Boy Advance ROMs (%1) ROMy Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMy Game Boy (%1) - + All ROMs (%1) Wszystkie ROMy (%1) - + %1 Video Logs (*.mvl) Dzienniki wideo %1 (*.mvl) - + Archives (%1) Archiwa (%1) - - - + + + Select ROM Wybierz ROM - + Select folder Wybierz katalog - - + + Select save Wybierz zapis - + Select patch Wybierz łatkę - + Patches (*.ips *.ups *.bps) Łatki (*.ips *.ups *.bps) - + Select e-Reader dotcode Wybierz kod kropki e-Reader - + e-Reader card (*.raw *.bin *.bmp) Karta e-Reader (*.raw *.bin *.bmp) - + Select image Wybierz obraz - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Plik obrazu (*.png *.gif *.jpg *.jpeg);;Wszystkie pliki (*) - + GameShark saves (*.sps *.xps) Zapisy GameShark (*.sps *.xps) - + Select video log Wybierz dziennik wideo - + Video logs (*.mvl) Dzienniki wideo (*.mvl) - + Crash Crash - + The game has crashed with the following error: %1 @@ -4264,679 +4246,684 @@ Rozmiar pobierania: %3 %1 - + Couldn't Start Nie udało się uruchomić - + Could not start game. Nie udało się rozpocząć gry. - + Unimplemented BIOS call Niewdrożone wywołanie BIOS - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Ta gra używa wywołania BIOS, które nie jest zaimplementowane. Aby uzyskać najlepsze wrażenia, użyj oficjalnego BIOS. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Nie udało się utworzyć odpowiedniego urządzenia wyświetlającego, powracam do wyświetlania programowego. Gry mogą działać wolno, zwłaszcza w przypadku większych okien. - + Really make portable? Naprawdę stworzyć wersję portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? To sprawi, że emulator załaduje swoją konfigurację z tego samego katalogu, co plik wykonywalny. Czy chcesz kontynuować? - + Restart needed Wymagane ponowne uruchomienie - + Some changes will not take effect until the emulator is restarted. Niektóre zmiany nie zaczną obowiązywać, dopóki emulator nie zostanie ponownie uruchomiony. - + - Player %1 of %2 - Gracz %1 z %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 FPS) - %4 - + &File &Plik - + Load &ROM... Załaduj &ROM... - + Load ROM in archive... Załaduj ROM w archiwum... - + Add folder to library... Dodaj folder do biblioteki... - + Save games (%1) Zapisane gry (%1) - + Select save game Wybierz zapis gry - + mGBA save state files (%1) Pliki stanu gry mGBA (%1) + - Select save state Wybierz stan - + Select e-Reader card images Wybierz obrazy kart e-Reader - + Image file (*.png *.jpg *.jpeg) Plik graficzny (*.png *.jpg *.jpeg) - + Conversion finished Konwersja zakończona - + %1 of %2 e-Reader cards converted successfully. %1 z %2 kart czytnika e-Reader zostało pomyślnie przekonwertowanych. - + Load alternate save game... Załaduj alternatywny zapis gry... - + Load temporary save game... Załaduj tymczasowy zapis gry... - + Load &patch... Wczytaj &poprawkę... - + Boot BIOS BIOS startowy - + Replace ROM... Wymień ROM... - + Scan e-Reader dotcodes... Skanuj kody kropkowe czytnika e-Reader... - + Convert e-Reader card image to raw... Konwertuj obraz karty czytnika e-Reader na surowy... - + ROM &info... &Informacje o pamięci ROM... - + Recent Ostatnie - + Make portable Stwórz wersję portable - + &Load state &Załaduj stan - + Load state file... Załaduj plik stanu… - + &Save state &Zapisz stan - + Save state file... Zapisz plik stanu... - + Quick load Szybkie załadowanie - + Quick save Szybki zapis - + Load recent Załaduj ostatnie - + Save recent Zapisz ostatnie - + Undo load state Cofnij załadowanie stanu - + Undo save state Cofnij zapisanie stanu - - + + State &%1 Stan &%1 - + Load camera image... Załaduj obraz do kamery... - + Convert save game... Konwertuj zapisaną grę... - + GameShark saves (*.gsv *.sps *.xps) Zapisy GameShark (*.gsv *.sps *.xps) - + Reset needed Wymagane zresetowanie - + Some changes will not take effect until the game is reset. Niektóre zmiany nie zaczną obowiązywać, dopóki gra nie zostanie zresetowana. - + Save games Zapisy gry - + Import GameShark Save... Importuj Zapis GameShark... - + Export GameShark Save... Eksportuj Zapis GameShark... - + Automatically determine Wykryj automatycznie - + Use player %0 save game Użyj zapis gry gracza %0 - + New multiplayer window Nowe okno dla wielu graczy - + Connect to Dolphin... Połącz z Dolphinem... - + Report bug... Zgłoś błąd... - + About... O Aplikacji... - + E&xit Z&akończ - + &Emulation &Emulacja - + &Reset &Resetuj - + Sh&utdown Za&mknij - + Yank game pak Wyciągnij Game Pak - + &Pause &Pauza - + &Next frame &Następna klatka - + Fast forward (held) Przewijanie (przytrzymaj) - + &Fast forward &Przewijanie do przodu - + Fast forward speed Prędkość przewijania do przodu - + Unbounded Bez ograniczeń - + %0x %0x - + Rewind (held) Przewijanie (przytrzymaj) - + Re&wind Pr&zewijanie - + Step backwards Krok w tył - + Solar sensor Czujnik słoneczny - + Increase solar level Zwiększ poziom energii słonecznej - + Decrease solar level Zmniejsz poziom energii słonecznej - + Brightest solar level Najjaśniejszy poziom energii słonecznej - + Darkest solar level Najciemniejszy poziom energii słonecznej - + Brightness %1 Jasność %1 - + Game Boy Printer... Game Boy Printer... - + BattleChip Gate... BattleChip Gate... - + Audio/&Video Dźwięk/&Wideo - + Frame size Rozmiar klatki - + %1× %1× - + Toggle fullscreen Przełącz tryb pełnoekranowy - + Lock aspect ratio Zablokuj proporcje - + Force integer scaling Wymuś skalowanie całkowite - + Interframe blending Blendowanie międzyklatkowe - + Bilinear filtering Filtrowanie dwuliniowe - + Frame&skip Klatko&wanie - + Mute Wycisz - + FPS target Cel KL./S - + Native (59.7275) Natywny (59.7275) - + Take &screenshot Wykonaj &zrzut ekranu - + F12 F12 - + Record A/V... Nagraj A/W... - + Record GIF/WebP/APNG... Nagraj GIF/WebP/APNG... - + Video layers Warstwy wideo - + Audio channels Kanały audio - + Adjust layer placement... Dostosuj położenie warstw... - + &Tools &Narzędzia - + View &logs... Wyświetl &logi... - + Game &overrides... Nadpisania &ustawień gry... - + Game Pak sensors... Czujniki Game Pak... - + &Cheats... &Kody... - + Settings... Ustawienia... - + Open debugger console... Otwórz konsolę debugera... - + Start &GDB server... Uruchom serwer &GDB... - + Scripting... - + + Game state views + + + + View &palette... Wyświetl &paletę... - + View &sprites... Wyświetl &sprite'y... - + View &tiles... Wyświetl &kafelki... - + View &map... Wyświetl &mapę... - + &Frame inspector... Inspektor &klatek... - + View memory... Wyświetl pamięć... - + Search memory... Przeszukaj pamięć... - + View &I/O registers... Wyświetl rejestry &we/wy... - + Record debug video log... Nagraj dziennik wideo debugowania... - + Stop debug video log Zatrzymaj dziennik wideo debugowania - + Exit fullscreen Wyłączyć tryb pełnoekranowy - + GameShark Button (held) Przycisk GameShark (przytrzymany) - + Autofire Turbo - + Autofire A Turbo A - + Autofire B Turbo B - + Autofire L Turbo L - + Autofire R Turbo R - + Autofire Start Turbo Start - + Autofire Select Turbo Select - + Autofire Up Turbo Góra - + Autofire Right Turbo Prawo - + Autofire Down Turbo Dół - + Autofire Left Turbo Lewo - + Clear Wyczyść @@ -5185,40 +5172,55 @@ Rozmiar pobierania: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset &Resetuj - + 0 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5233,64 +5235,74 @@ Rozmiar pobierania: %3 Zegar czasu rzeczywistego - + Fixed time Ustalony czas - + System time Czas systemu - + Start time at Czas rozpoczęcia o - + Now Teraz - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP yy/MM/DD hh:mm:ss AP - + Light sensor Czujnik światła - + Brightness Jasność - + Tilt sensor Czujnik pochylenia - - + + Set Y Ustaw Y - - + + Set X Ustaw X - + Gyroscope Żyroskop - + Sensitivity Czułość diff --git a/src/platform/qt/ts/mgba-pt_BR.ts b/src/platform/qt/ts/mgba-pt_BR.ts index 2a53af1fd..7f1acd044 100644 --- a/src/platform/qt/ts/mgba-pt_BR.ts +++ b/src/platform/qt/ts/mgba-pt_BR.ts @@ -1184,36 +1184,36 @@ Game Boy Advance é uma marca registrada da Nintendo Co., Ltd. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. - + Current version: %1 New version: %2 Download size: %3 - + Downloading update... - + Downloading failed. Please update manually. - + Downloading done. Press OK to restart %1 and install the update. @@ -1236,7 +1236,7 @@ Download size: %3 Desconhecido - + (None) @@ -1323,12 +1323,12 @@ Download size: %3 Não pode arrancar o pacote numa plataforma inesperada! - + Failed to open snapshot file for reading: %1 Falhou em abrir o arquivo do snapshot pra leitura: %1 - + Failed to open snapshot file for writing: %1 Falhou em abrir o arquivo do snapshot pra gravação: %1 @@ -1341,12 +1341,12 @@ Download size: %3 Falhou em abrir o arquivo do jogo: %1 - + Could not load game. Are you sure it's in the correct format? Não pôde carregar o jogo. Você tem certeza que está no formato correto? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). @@ -3410,27 +3410,27 @@ Download size: %3 QGBA::LoadSaveState - + Load State Carregar o State - + Save State Salvar o State - + Empty Vazio - + Corrupted Corrompido - + Slot %1 Slot %1 @@ -3859,12 +3859,12 @@ Download size: %3 QGBA::ReportView - + Bug report archive Arquivo compactado do relatório dos bugs - + ZIP archive (*.zip) Arquivo compactado ZIP (*.zip) @@ -3935,29 +3935,11 @@ Download size: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4155,100 +4137,100 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) ROMs do Game Boy Advance (%1) - + Game Boy ROMs (%1) ROMs do Game Boy (%1) - + All ROMs (%1) Todas as ROMs (%1) - + %1 Video Logs (*.mvl) %1 Registros do Vídeo (*.mvl) - + Archives (%1) Arquivos Compactados (%1) - - - + + + Select ROM Selecionar ROM - + Select folder Selecionar pasta - - + + Select save Selecionar save - + Select patch Selecionar patch - + Patches (*.ips *.ups *.bps) Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode Selecionar dotcode do e-Reader - + e-Reader card (*.raw *.bin *.bmp) Cartão do e-Reader (*.raw *.bin *.bmp) - + Select image Selecionar imagem - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Arquivo de imagem (*.png *.gif *.jpg *.jpeg);;Todos os arquivos (*) - + GameShark saves (*.sps *.xps) Saves do GameShark (*.sps *.xps) - + Select video log Selecionar registro do vídeo - + Video logs (*.mvl) Registros do vídeo (*.mvl) - + Crash Crash - + The game has crashed with the following error: %1 @@ -4257,679 +4239,684 @@ Download size: %3 %1 - + Unimplemented BIOS call Chamada da BIOS não implementada - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Este jogo usa uma chamada de BIOS que não está implementada. Por favor use a BIOS oficial pra uma melhor experiência. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Falhou em criar um dispositivo de exibição apropriado, voltando a exibição por software. Os jogos podem executar lentamente, especialmente com janelas maiores. - + Really make portable? Realmente tornar portátil? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Isto fará o emulador carregar sua configuração do mesmo diretório que o executável. Você quer continuar? - + Restart needed Reiniciar é necessário - + Some changes will not take effect until the emulator is restarted. Algumas mudanças não terão efeito até que o emulador seja reiniciado. - + - Player %1 of %2 - Jogador %1 de %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Arquivo - + Load &ROM... Carregar &ROM... - + Load ROM in archive... Carregar ROM no arquivo compactado... - + Add folder to library... Adicionar a pasta a biblioteca... - + Save games Saves dos jogos - + Automatically determine - + Use player %0 save game - + Load &patch... Carregar &patch... - + Boot BIOS Dar Boot na BIOS - + Replace ROM... Substituir ROM... - + ROM &info... Informações da &ROM... - + Recent Recentes - + Make portable Tornar portátil - + &Load state &Carregar state - + Report bug... Reportar bug... - + About... Sobre... - + Game Pak sensors... Sensores do Game Pak... - + Clear Limpar - + Load state file... Carregar arquivo do state... - + Save games (%1) Saves dos jogos (%1) - + Select save game Selecione save do jogo - + mGBA save state files (%1) Arquivos do save state do mGBA (%1) + - Select save state Selecione save state - + Select e-Reader card images Selecionar imagens do cartão do e-Reader - + Image file (*.png *.jpg *.jpeg) Arquivo da imagem (*.png *.jpg *.jpeg) - + Conversion finished Conversão concluída - + %1 of %2 e-Reader cards converted successfully. %1 de %2 cartões do e-Reader convertidos com sucesso. - + Load alternate save game... Carregar save alternativo do jogo... - + Load temporary save game... Carregar save temporário do jogo... - + Convert e-Reader card image to raw... Converter imagem do cartão do e-Reader pro natural... - + &Save state &Salvar o state - + Save state file... Arquivo do save state... - + Quick load Carregamento rápido - + Quick save Salvamento rápido - + Load recent Carregar recentes - + Save recent Salvar recentes - + Undo load state Desfazer o carregamento do state - + Undo save state Desfazer o salvamento do state - - + + State &%1 State &%1 - + Load camera image... Carregar imagem da câmera... - + Convert save game... Converter save do jogo... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + New multiplayer window Nova janela multi-jogador - + Connect to Dolphin... Conectar ao Dolphin... - + E&xit S&air - + &Emulation &Emulação - + &Reset &Resetar - + Sh&utdown De&sligar - + Yank game pak Arrancar game pak - + &Pause &Pausar - + &Next frame &Próximo frame - + Fast forward (held) Avanço rápido (segurado) - + &Fast forward &Avanço rápido - + Fast forward speed Velocidade do avanço rápido - + Unbounded Ilimitado - + %0x %0x - + Rewind (held) Retroceder (segurado) - + Re&wind Re&troceder - + Step backwards Voltar um passo - + Solar sensor Sensor solar - + Increase solar level Aumentar nível solar - + Decrease solar level Diminuir nível solar - + Brightest solar level Nível solar mais brilhante - + Darkest solar level Nível solar mais escuro - + Brightness %1 Brilho %1 - + Audio/&Video Áudio/&Vídeo - + Frame size Tamanho do frame - + Toggle fullscreen Alternar tela cheia - + Lock aspect ratio Trancar proporção do aspecto - + Force integer scaling Forçar dimensionamento da integral - + Bilinear filtering Filtragem bilinear - + Frame&skip Frame&skip - + Mute Mudo - + FPS target FPS alvo - + Native (59.7275) Nativo (59,7275) - + Take &screenshot Tirar &screenshot - + F12 F12 - + Game Boy Printer... Impressora do Game Boy... - + BattleChip Gate... Portal do BattleChip... - + %1× %1× - + Interframe blending Mistura do interframe - + Record A/V... Gravar A/V... - + Video layers Camadas do vídeo - + Audio channels Canais de áudio - + Adjust layer placement... Ajustar posicionamento da camada... - + &Tools &Ferramentas - + View &logs... Visualizar &registros... - + Game &overrides... Substituições &do jogo... - + Couldn't Start Não Pôde Iniciar - + Could not start game. Não pôde iniciar o jogo. - + Scan e-Reader dotcodes... Escanear dotcodes do e-Reader... - + Import GameShark Save... Importar Save do GameShark... - + Export GameShark Save... Exportar Save do GameShark... - + Record GIF/WebP/APNG... Gravar GIF/WebP/APNG... - + &Cheats... &Trapaças... - + Settings... Configurações... - + Open debugger console... Abrir console do debugger... - + Start &GDB server... Iniciar servidor do &GDB... - + Scripting... - + + Game state views + + + + View &palette... Visualizar &paleta... - + View &sprites... Visualizar &imagens móveis... - + View &tiles... Visualizar &ladrilhos... - + View &map... Visualizar &mapa... - + &Frame inspector... Inspetor dos &frames... - + View memory... Visualizar memória... - + Search memory... Procurar memória... - + View &I/O registers... Visualizar registros de &E/S... - + Record debug video log... Gravar registro do vídeo de debug... - + Stop debug video log Parar log do vídeo de debug - + Exit fullscreen Sair da tela cheia - + GameShark Button (held) Botão do GameShark (segurado) - + Autofire Auto-disparar - + Autofire A Auto-disparar A - + Autofire B Auto-disparar B - + Autofire L Auto-disparar L - + Autofire R Auto-disparar R - + Autofire Start Auto-disparar Start - + Autofire Select Auto-disparar Select - + Autofire Up Auto-disparar Pra Cima - + Autofire Right Auto-disparar Direita - + Autofire Down Auto-disparar Pra Baixo - + Autofire Left Auto-disparar Esquerda @@ -5178,40 +5165,55 @@ Download size: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset &Resetar - + 0 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5226,64 +5228,74 @@ Download size: %3 Relógio em tempo real - + Fixed time Tempo fixo - + System time Horário do sistema - + Start time at Horário do início em - + Now Agora - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP MM/dd/yy hh:mm:ss AP - + Light sensor Sensor de luz - + Brightness Brilho - + Tilt sensor Sensor de inclinação - - + + Set Y Definir Y - - + + Set X Definir X - + Gyroscope Giroscópio - + Sensitivity Sensibilidade diff --git a/src/platform/qt/ts/mgba-ru.ts b/src/platform/qt/ts/mgba-ru.ts index c68456baa..9bc4fb571 100644 --- a/src/platform/qt/ts/mgba-ru.ts +++ b/src/platform/qt/ts/mgba-ru.ts @@ -1184,21 +1184,21 @@ Game Boy Advance - зарегистрированная торговая мар - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. Вы хотите скачать и установить сейчас? Вам надо будет перезагрузить эмулятор когда загрузка закончится. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. Автообновление не доступно на этой платформе. Если вы хотите обновить эмулятор вам нужно сделать это вручную. - + Current version: %1 New version: %2 Download size: %3 @@ -1207,17 +1207,17 @@ Download size: %3 Размер файла: %3 - + Downloading update... Загрузка обновления... - + Downloading failed. Please update manually. Загрузка не удалась. Пожалуйста, загрузите обновление вручную. - + Downloading done. Press OK to restart %1 and install the update. Загрузка завершена. Нажмите OK для перезапуска и установки обновления. @@ -1240,7 +1240,7 @@ Download size: %3 Неизвестно - + (None) (Нет) @@ -1327,12 +1327,12 @@ Download size: %3 - + Failed to open snapshot file for reading: %1 Не удалось открыть файл изображения для считывания: %1 - + Failed to open snapshot file for writing: %1 Не удалось открыть файл изображения для записи: %1 @@ -1345,12 +1345,12 @@ Download size: %3 Не удалось открыть файл игры: %1 - + Could not load game. Are you sure it's in the correct format? Не удалось загрузить игру. Вы уверены, что она в правильном формате? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). @@ -3414,27 +3414,27 @@ Download size: %3 QGBA::LoadSaveState - + Load State Загрузить состояние - + Save State Сохранить состояние - + Empty - + Corrupted Повреждено - + Slot %1 Слот %1 @@ -3863,12 +3863,12 @@ Download size: %3 QGBA::ReportView - + Bug report archive Архив отчётов об ошибках - + ZIP archive (*.zip) ZIP архив (*.zip) @@ -3939,29 +3939,11 @@ Download size: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4161,100 +4143,100 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) Игры Game Boy Advance (%1) - + Game Boy ROMs (%1) Игры Game Boy (%1) - + All ROMs (%1) Все игры (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) Архивы (%1) - - - + + + Select ROM Выбор игры - + Select folder Выбор папки - - + + Select save Выбор сохранения - + Select patch Выбор патча - + Patches (*.ips *.ups *.bps) Патчи (*.ips *.ups *.bps) - + Select e-Reader dotcode Выбор карточки e-Reader - + e-Reader card (*.raw *.bin *.bmp) Карточка e-Reader (*.raw *.bin *.bmp) - + Select image Выбор изображения - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Файл изображения (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) Сохранения GameShark (*.sps *.xps) - + Select video log Выбор видеолога - + Video logs (*.mvl) Видеологи (*.mvl) - + Crash Сбой - + The game has crashed with the following error: %1 @@ -4263,679 +4245,684 @@ Download size: %3 %1 - + Couldn't Start Запуск не удался - + Could not start game. Не удалось запустить игру. - + Unimplemented BIOS call Неизвестный вызов BIOS - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Игра использует нереализованный вызов BIOS. Пожалуйста, воспользуйтесь официальным BIOS для лучшей совместимости. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Не удалось создать устройство отображения, возврат к программному режиму. Игры могут идти медленнее, особенно в окнах больших размеров. - + Really make portable? Перейти в портативный режим? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? После этого эмулятор будет загружать конфигурацию из папки с исполняемым файлом. Продолжить? - + Restart needed Требуется перезапуск - + Some changes will not take effect until the emulator is restarted. Для применения некоторых изменений требуется перезапустить эмулятор. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File &Файл - + Load &ROM... - + Load ROM in archive... Загрузить игру из архива... - + Add folder to library... Добавить папку в библиотеку... - + Save games (%1) Игровые сохранения (%1) - + Select save game Выбор игрового сохранения - + mGBA save state files (%1) Файл сохранения состояния mGBA (%1) + - Select save state Выбор сохранения состояния - + Select e-Reader card images Выбор изображения карточки e-Reader - + Image file (*.png *.jpg *.jpeg) Файл изображения (*.png *.jpg *.jpeg) - + Conversion finished Конвертация завершена - + %1 of %2 e-Reader cards converted successfully. %1 из %2 карточек e-Reader успешно сконвертировано. - + Load alternate save game... Загрузить альтернативное сохранение... - + Load temporary save game... Загрузить временное сохранение... - + Load &patch... Загрузить &патч... - + Boot BIOS Загрузиться в BIOS - + Replace ROM... Заменить ROM... - + Scan e-Reader dotcodes... Сканировать dot-коды e-Reader... - + Convert e-Reader card image to raw... Конвертировать карту e-Reader в raw... - + ROM &info... Информация об &игре... - + Recent Недавние - + Make portable Портативный режим - + &Load state &Загрузить состояние - + Load state file... Загрузить состояние из файла... - + &Save state &Сохранить состояние - + Save state file... Сохранить состояние в файл... - + Quick load Быстрая загрузка - + Quick save Быстрое сохранение - + Load recent Загрузить недавнее - + Save recent Сохранить в недавнее - + Undo load state Отмена загрузки состояния - + Undo save state Отмена сохранения состояния - - + + State &%1 Слот &%1 - + Load camera image... Загрузить изображение с камеры... - + Convert save game... Конвертировать игровое сохранение... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... Импорт сохранения GameShark... - + Export GameShark Save... Экспорт сохранения GameShark... - + Automatically determine - + Use player %0 save game - + New multiplayer window Новое окно мультиплеера - + Connect to Dolphin... Соединение с Dolphin... - + Report bug... Сообщить об ошибке... - + About... О программе... - + E&xit &Выход - + &Emulation &Эмуляция - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x %0x - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + Scripting... - + + Game state views + + + + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear Очистить @@ -5184,40 +5171,55 @@ Download size: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset - + 0 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5232,64 +5234,74 @@ Download size: %3 Реальное время - + Fixed time - + System time - + Start time at - + Now - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP - + Light sensor Датчик света - + Brightness - + Tilt sensor - - + + Set Y - - + + Set X - + Gyroscope Гироскоп - + Sensitivity diff --git a/src/platform/qt/ts/mgba-template.ts b/src/platform/qt/ts/mgba-template.ts index 087ded6db..6540122ad 100644 --- a/src/platform/qt/ts/mgba-template.ts +++ b/src/platform/qt/ts/mgba-template.ts @@ -1183,36 +1183,36 @@ Game Boy Advance is a registered trademark of Nintendo Co., Ltd. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. - + Current version: %1 New version: %2 Download size: %3 - + Downloading update... - + Downloading failed. Please update manually. - + Downloading done. Press OK to restart %1 and install the update. @@ -1235,7 +1235,7 @@ Download size: %3 - + (None) @@ -1322,12 +1322,12 @@ Download size: %3 - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -1340,12 +1340,12 @@ Download size: %3 - + Could not load game. Are you sure it's in the correct format? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). @@ -3409,27 +3409,27 @@ Download size: %3 QGBA::LoadSaveState - + Load State - + Save State - + Empty - + Corrupted - + Slot %1 @@ -3858,12 +3858,12 @@ Download size: %3 QGBA::ReportView - + Bug report archive - + ZIP archive (*.zip) @@ -3934,29 +3934,11 @@ Download size: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4152,779 +4134,784 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) - + Game Boy ROMs (%1) - + All ROMs (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) - - - + + + Select ROM - + Select folder - - + + Select save - + Select patch - + Patches (*.ips *.ups *.bps) - + Select e-Reader dotcode - + e-Reader card (*.raw *.bin *.bmp) - + Select image - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) - + Select video log - + Video logs (*.mvl) - + Crash - + The game has crashed with the following error: %1 - + Couldn't Start - + Could not start game. - + Unimplemented BIOS call - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Really make portable? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - + Restart needed - + Some changes will not take effect until the emulator is restarted. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... - + Load ROM in archive... - + Add folder to library... - + Save games (%1) - + Select save game - + mGBA save state files (%1) + - Select save state - + Select e-Reader card images - + Image file (*.png *.jpg *.jpeg) - + Conversion finished - + %1 of %2 e-Reader cards converted successfully. - + Load alternate save game... - + Load temporary save game... - + Load &patch... - + Boot BIOS - + Replace ROM... - + Scan e-Reader dotcodes... - + Convert e-Reader card image to raw... - + ROM &info... - + Recent - + Make portable - + &Load state - + Load state file... - + &Save state - + Save state file... - + Quick load - + Quick save - + Load recent - + Save recent - + Undo load state - + Undo save state - - + + State &%1 - + Load camera image... - + Convert save game... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + Save games - + Import GameShark Save... - + Export GameShark Save... - + Automatically determine - + Use player %0 save game - + New multiplayer window - + Connect to Dolphin... - + Report bug... - + About... - + E&xit - + &Emulation - + &Reset - + Sh&utdown - + Yank game pak - + &Pause - + &Next frame - + Fast forward (held) - + &Fast forward - + Fast forward speed - + Unbounded - + %0x - + Rewind (held) - + Re&wind - + Step backwards - + Solar sensor - + Increase solar level - + Decrease solar level - + Brightest solar level - + Darkest solar level - + Brightness %1 - + Game Boy Printer... - + BattleChip Gate... - + Audio/&Video - + Frame size - + %1× - + Toggle fullscreen - + Lock aspect ratio - + Force integer scaling - + Interframe blending - + Bilinear filtering - + Frame&skip - + Mute - + FPS target - + Native (59.7275) - + Take &screenshot - + F12 - + Record A/V... - + Record GIF/WebP/APNG... - + Video layers - + Audio channels - + Adjust layer placement... - + &Tools - + View &logs... - + Game &overrides... - + Game Pak sensors... - + &Cheats... - + Settings... - + Open debugger console... - + Start &GDB server... - + Scripting... - + + Game state views + + + + View &palette... - + View &sprites... - + View &tiles... - + View &map... - + &Frame inspector... - + View memory... - + Search memory... - + View &I/O registers... - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear @@ -5173,40 +5160,55 @@ Download size: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset - + 0 + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5221,64 +5223,74 @@ Download size: %3 - + Fixed time - + System time - + Start time at - + Now - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP - + Light sensor - + Brightness - + Tilt sensor - - + + Set Y - - + + Set X - + Gyroscope - + Sensitivity diff --git a/src/platform/qt/ts/mgba-tr.ts b/src/platform/qt/ts/mgba-tr.ts index 96e00763b..8171cdcd4 100644 --- a/src/platform/qt/ts/mgba-tr.ts +++ b/src/platform/qt/ts/mgba-tr.ts @@ -1184,36 +1184,36 @@ Game Boy Advance, Nintendo Co., Ltd.'nin tescilli ticari markasıdır. - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. - + Current version: %1 New version: %2 Download size: %3 - + Downloading update... - + Downloading failed. Please update manually. - + Downloading done. Press OK to restart %1 and install the update. @@ -1236,7 +1236,7 @@ Download size: %3 Bilinmeyen - + (None) @@ -1323,12 +1323,12 @@ Download size: %3 Beklenmedik bir platformda kartı çıkaramazsın! - + Failed to open snapshot file for reading: %1 Anlık görüntü dosyası okuma için açılamadı: %1 - + Failed to open snapshot file for writing: %1 Anlık görüntü dosyası yazma için açılamadı: %1 @@ -1341,12 +1341,12 @@ Download size: %3 Oyun dosyası açılamadı: %1 - + Could not load game. Are you sure it's in the correct format? Oyun yüklenemedi. Doğru formatta olduğundan emin misin? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). @@ -3410,27 +3410,27 @@ Download size: %3 QGBA::LoadSaveState - + Load State Durum yükle - + Save State Durumu Kaydet - + Empty Boş - + Corrupted Bozulmuş - + Slot %1 @@ -3859,12 +3859,12 @@ Download size: %3 QGBA::ReportView - + Bug report archive Hata rapor arşivi - + ZIP archive (*.zip) ZIP arşivi (*.zip) @@ -3935,29 +3935,11 @@ Download size: %3 QGBA::ScriptingTextBuffer - + Untitled buffer - - QGBA::ScriptingView - - - Select script to load - - - - - Lua scripts (*.lua) - - - - - All files (*.*) - - - QGBA::SettingsView @@ -4153,120 +4135,120 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) Game Boy Advance ROMları (%1) - + Game Boy ROMs (%1) Game Boy ROMları (%1) - + All ROMs (%1) Bütün ROMlar (%1) - + %1 Video Logs (*.mvl) - + Archives (%1) Arşivler (%1) - - - + + + Select ROM ROM seç - + Select folder Klasör seç - - + + Select save Kayıt seç - + Select patch Yama seç - + Patches (*.ips *.ups *.bps) Yamalar (*.ips *.ups *.bps) - + Select e-Reader dotcode e-Okuyucu nokta kodunu seç - + e-Reader card (*.raw *.bin *.bmp) e-Okuyucu kart (*.raw *.bin *.bmp) - + Select e-Reader card images e-Okuyucu kartından görüntüleri seç - + Image file (*.png *.jpg *.jpeg) Görüntü dosyası (*.png *.jpg *.jpeg) - + Conversion finished Dönüştürme tamamlandı - + %1 of %2 e-Reader cards converted successfully. %1 / %2 e-Okuyucu kartları dönüştürme tamamlandı. - + Select image Resim seç - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Resim dosyası (*.png *.gif *.jpg *.jpeg);;All files (*) - + GameShark saves (*.sps *.xps) GameShark kayıtları (*.sps *.xps) - + Select video log Video günlüğü seç - + Video logs (*.mvl) Video günlükleri (*.mvl) - + Crash Çökme - + The game has crashed with the following error: %1 @@ -4275,659 +4257,664 @@ Download size: %3 %1 - + Unimplemented BIOS call Uygulanmamış BIOS girişi - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Oyun BIOS dosyasına ihtiyacı var. Lütfen en iyi deneyim için resmi BIOS'u kullanın. - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. Uygun görüntü cihazı oluşturma başarısız, yazılım ekranına dönülüyor. Oyunlar özellikle daha büyük ekranlarda yavaş çalışabilir. - + Really make portable? Taşınabilir yapılsın mı? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Emülatörün yapılandırmasını yürütülebilir dosya ile aynı dizinden yüklemesini sağlar. Devam etmek istiyor musun? - + Restart needed Yeniden başlatma gerekli - + Some changes will not take effect until the emulator is restarted. Bazı değişiklikler emülatör yeniden başlatılıncaya kadar etkili olmaz. - + - Player %1 of %2 - + %1 - %2 - + %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File - + Load &ROM... &ROM yükle... - + Load ROM in archive... ROM'u arşivden yükle ... - + Add folder to library... Kütüphaneye klasör ekle ... - + Save games Oyunları kaydet - + Automatically determine - + Use player %0 save game - + Load &patch... &Patch yükle... - + Boot BIOS BIOS boot et - + Replace ROM... ROM değişti... - + + Game state views + + + + Convert e-Reader card image to raw... e-Okuyucu kart resimlerini rawa dönüştür... - + ROM &info... ROM &info... - + Recent Son kullanılanlar - + Make portable Portatif yap - + &Load state &Kaydedilmiş konum yükle - + Load state file... Kaydedilmiş konum dosyası yükle... - + &Save state &Konumu kaydet - + Save state file... Konum dosyasını kaydet... - + Quick load Hızlı Yükle - + Quick save Hızlı kaydet - + Load recent En son yükle - + Save recent Hızlı kaydet - + Undo load state Kaydedilen konum yüklemeyi geri al - + Undo save state Konum kaydetmeyi geri al - - + + State &%1 Konum &%1 - + Load camera image... Kamera resmini yükle ... - + Convert save game... Kayıtlı oyun dömnüştürülüyor... - + GameShark saves (*.gsv *.sps *.xps) - + Reset needed - + Some changes will not take effect until the game is reset. - + New multiplayer window Yeni çokoyunculu ekranı - + Connect to Dolphin... Dolphin'e Bağlan... - + Report bug... Hata rapor et... - + About... Hakkında... - + E&xit Çıkış - + &Emulation Emülasyon - + &Reset &Reset - + Sh&utdown Kapat - + Yank game pak - + &Pause &Durdur - + &Next frame &Sonraki kare - + Fast forward (held) İleriye sar(basılı tutun) - + &Fast forward &İleriye sar - + Fast forward speed İleriye sarma hızı - + Unbounded - + %0x - + Rewind (held) Geri sar (basılı tutun) - + Re&wind Geri sar - + Step backwards Geriye doğru adım - + Solar sensor - + Increase solar level Solar seviyesini arttır - + Decrease solar level Solar seviyesini düşür - + Brightest solar level En parlak solar seviyesi - + Darkest solar level En karanlık solar seviyesi - + Brightness %1 Parlaklık:%1 - + Game Boy Printer... Game Boy yazıcısı... - + BattleChip Gate... - + Audio/&Video Ses/&Video - + Frame size Çerçeve boyutu - + Toggle fullscreen Tamekranı aç/kapa - + Lock aspect ratio En boy oranını kilitle - + Force integer scaling Tamsayılı ölçeklendirmeyi zorla - + Bilinear filtering Bilinear filtreleme - + Frame&skip Kare atlama - + Mute Sessiz - + FPS target FPS hedefi - + Native (59.7275) - + Take &screenshot Ekran görüntüsü al - + F12 - + Video layers - + Audio channels Ses kanalları - + Adjust layer placement... Katman yerleşimini ayarlayın... - + &Tools &Araçlar - + View &logs... Kayıtları görüntüle... - + Game &overrides... & Oyunun üzerine yazılanlar... - + Couldn't Start Başlatılamadı - + Save games (%1) Kayıtlı oyunlar (%1) - + Select save game Kayıtlı oyun seç - + mGBA save state files (%1) mGBA kayıt durum dosyası (%1) + - Select save state Kayıt durumu seç - + Could not start game. Oyun başlatılamadı. - + Load alternate save game... Alternatif kayıtlı oyun yükle... - + Load temporary save game... Geçici kayıtlı oyunu yükle... - + Scan e-Reader dotcodes... e-Okuyucu noktakodları tara... - + Import GameShark Save... GameShark kaydını içeri aktar... - + Export GameShark Save... GameShark kaydını dışarı aktar... - + %1× %1× - + Interframe blending Kareler-arası Karıştırma - + Record A/V... A/V Kayıt... - + Record GIF/WebP/APNG... GIF/WebP/APNG Kayıt... - + Game Pak sensors... Oyun Kartuş sensörleri... - + &Cheats... &Hileler... - + Settings... Ayarlar... - + Open debugger console... Hata ayıklayıcı konsolunu aç ... - + Start &GDB server... &GDB sunucusunu başlat... - + Scripting... - + View &palette... &Renk Paletini gör... - + View &sprites... &Spriteları gör... - + View &tiles... &Desenleri gör... - + View &map... &Haritayı gör - + &Frame inspector... &Kare denetçisi... - + View memory... Hafıza gör... - + Search memory... Hafızada ara... - + View &I/O registers... &I/O kayıtlarını görüntüle - + Record debug video log... Hata ayıklama video günlüğünü kaydet... - + Stop debug video log Hata ayıklama video günlüğünü durdur - + Exit fullscreen Tam ekrandan çık - + GameShark Button (held) GameShark Butonu (basılı tutun) - + Autofire Otomatik basma - + Autofire A Otomatik basma A - + Autofire B Otomatik basma B - + Autofire L Otomatik basma L - + Autofire R Otomatik basma R - + Autofire Start Otomatik basma Start - + Autofire Select Otomatik basma Select - + Autofire Up Otomatik basma Up - + Autofire Right Otomatik basma Right - + Autofire Down Otomatik basma Down - + Autofire Left Otomatik basma Sol - + Clear Temizle @@ -5176,40 +5163,55 @@ Download size: %3 ScriptingView - + Scripting - + Run - + File - + Load recent script - + Load script... - + &Reset &Reset - + 0 4K {0?} + + + Select script to load + + + + + Lua scripts (*.lua) + + + + + All files (*.*) + + SensorView @@ -5224,64 +5226,74 @@ Download size: %3 Gerçek zaman saati - + Fixed time Sabit zaman - + System time Sistem zamanı - + Start time at Başlangıç zamanı - + Now Şimdi - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP - + Light sensor - + Brightness Parlaklık - + Tilt sensor Eğim sensörü - - + + Set Y - - + + Set X - + Gyroscope Jiroskop - + Sensitivity Hassaslık diff --git a/src/platform/qt/ts/mgba-zh_CN.ts b/src/platform/qt/ts/mgba-zh_CN.ts index 8076609e4..450a9329b 100644 --- a/src/platform/qt/ts/mgba-zh_CN.ts +++ b/src/platform/qt/ts/mgba-zh_CN.ts @@ -1185,21 +1185,21 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 - + Do you want to download and install it now? You will need to restart the emulator when the download is complete. 你想现在下载并安装吗?下载完成后,你需要重新启动模拟器。 - + Auto-update is not available on this platform. If you wish to update you will need to do it manually. 自动更新在此平台上不可用。如果您希望更新,则需要手动进行。 - + Current version: %1 New version: %2 Download size: %3 @@ -1208,17 +1208,17 @@ Download size: %3 更新大小:%3 - + Downloading update... 正在下载更新... - + Downloading failed. Please update manually. 下载失败。请手动更新。 - + Downloading done. Press OK to restart %1 and install the update. 下载完成。按确定按钮以重新启动 %1 并安装更新。 @@ -1241,7 +1241,7 @@ Download size: %3 未知 - + (None) (无) @@ -1328,12 +1328,12 @@ Download size: %3 无法在意外平台上抽出卡带! - + Failed to open snapshot file for reading: %1 读取快照文件失败: %1 - + Failed to open snapshot file for writing: %1 写入快照文件失败: %1 @@ -1346,12 +1346,12 @@ Download size: %3 打开游戏文件失败: %1 - + Could not load game. Are you sure it's in the correct format? 无法载入游戏。请确认游戏格式是否正确? - + Failed to open save file; in-game saves cannot be updated. Please ensure the save directory is writable without additional privileges (e.g. UAC on Windows). 无法打开存档;游戏内存档无法更新。请确保保存目录是可写的,且没有额外权限(例如 Windows 上的 UAC)。 @@ -3415,27 +3415,27 @@ Download size: %3 QGBA::LoadSaveState - + Load State 载入即时存档 - + Save State 即时存档 - + Empty - + Corrupted 已损坏 - + Slot %1 插槽 %1 @@ -3864,12 +3864,12 @@ Download size: %3 QGBA::ReportView - + Bug report archive 错误报告存档 - + ZIP archive (*.zip) ZIP 存档 (*.zip) @@ -3940,29 +3940,11 @@ Download size: %3 QGBA::ScriptingTextBuffer - + Untitled buffer 无标题缓存 - - QGBA::ScriptingView - - - Select script to load - 选择要载入的脚本 - - - - Lua scripts (*.lua) - Lua 脚本 (*.lua) - - - - All files (*.*) - 所有文件 (*.*) - - QGBA::SettingsView @@ -4158,100 +4140,100 @@ Download size: %3 QGBA::Window - + Game Boy Advance ROMs (%1) Game Boy Advance ROM (%1) - + Game Boy ROMs (%1) Game Boy ROM (%1) - + All ROMs (%1) 所有 ROM (%1) - + %1 Video Logs (*.mvl) %1 视频日志 (*.mvl) - + Archives (%1) 压缩文件 (%1) - - - + + + Select ROM 选择 ROM - + Select folder 选择文件夹 - - + + Select save 选择存档 - + Select patch 选择补丁 - + Patches (*.ips *.ups *.bps) 补丁 (*.ips *.ups *.bps) - + Select e-Reader dotcode 选择 e-Reader 点码 - + e-Reader card (*.raw *.bin *.bmp) e-Reader 卡 (*.raw *.bin *.bmp) - + Select image 选择图片 - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) 图像文件 (*.png *.gif *.jpg *.jpeg);;所有文件 (*) - + GameShark saves (*.sps *.xps) GameShark 存档 (*.sps *.xps) - + Select video log 选择视频日志 - + Video logs (*.mvl) 视频日志文件 (*.mvl) - + Crash 崩溃 - + The game has crashed with the following error: %1 @@ -4260,679 +4242,684 @@ Download size: %3 %1 - + Couldn't Start 无法启动 - + Could not start game. 无法启动游戏。 - + Unimplemented BIOS call 未实现的 BIOS 调用 - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. 此游戏使用尚未实现的 BIOS 调用。请使用官方 BIOS 以获得最佳体验。 - + Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. 无法创建适合的显示设备,正在回滚到软件显示。游戏的运行速度(特别在大窗口的情况下)可能会变慢。 - + Really make portable? 确定进行程序便携化? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? 进行此操作后,模拟器将从其可执行文件所在目录中载入模拟器配置。您想继续吗? - + Restart needed 需要重新启动 - + Some changes will not take effect until the emulator is restarted. 更改将在模拟器下次重新启动时生效。 - + - Player %1 of %2 - 玩家 %1 共 %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 - + &File 文件(&F) - + Load &ROM... 载入 ROM(&R)... - + Load ROM in archive... 从压缩文件中载入 ROM... - + Add folder to library... 将文件夹添加到库中... - + Save games (%1) 保存游戏(%1) - + Select save game 选择保存游戏 - + mGBA save state files (%1) mGBA 即时存档文件(%1) + - Select save state 选择即时存档 - + Select e-Reader card images 选择 e-Reader 卡片图像 - + Image file (*.png *.jpg *.jpeg) 图像文件(*.png *.jpg *.jpeg) - + Conversion finished 转换完成 - + %1 of %2 e-Reader cards converted successfully. 成功转换了 %1 张(共 %2 张)e-Reader 卡片。 - + Load alternate save game... 加载备用保存游戏... - + Load temporary save game... 加载临时保存游戏... - + Load &patch... 载入补丁(&P)... - + Boot BIOS 引导 BIOS - + Replace ROM... 替换 ROM... - + Scan e-Reader dotcodes... 扫描 e-Reader 点码... - + Convert e-Reader card image to raw... 将 e-Reader 卡片图像转换为原始数据... - + ROM &info... ROM 信息(&I)... - + Recent 最近打开 - + Make portable 程序便携化 - + &Load state 载入即时存档(&L) - + Load state file... 载入即时存档文件... - + &Save state 保存即时存档(&S) - + Save state file... 保存即时存档文件... - + Quick load 快速读档 - + Quick save 快速存档 - + Load recent 载入最近存档 - + Save recent 保存最近存档 - + Undo load state 撤消读档 - + Undo save state 撤消存档 - - + + State &%1 即时存档 (&%1) - + Load camera image... 载入相机图片... - + Convert save game... 转换保存游戏... - + GameShark saves (*.gsv *.sps *.xps) GameShark 存档 (*.gsv *.sps *.xps) - + Reset needed 需要重启 - + Some changes will not take effect until the game is reset. 某些改动需要重新启动才会生效。 - + Save games 游戏存档 - + Import GameShark Save... 导入 GameShark 存档... - + Export GameShark Save... 导出 GameShark 存档... - + Automatically determine 自动终止 - + Use player %0 save game 使用玩家 %0 存档 - + New multiplayer window 新建多人游戏窗口 - + Connect to Dolphin... 连接到 Dolphin... - + Report bug... 报告错误... - + About... 关于... - + E&xit 退出(&X) - + &Emulation 模拟(&E) - + &Reset 重置(&R) - + Sh&utdown 关机(&U) - + Yank game pak 快速抽出游戏卡带 - + &Pause 暂停(&P) - + &Next frame 下一帧(&N) - + Fast forward (held) 快进 (长按) - + &Fast forward 快进(&F) - + Fast forward speed 快进速度 - + Unbounded 不限制 - + %0x %0x - + Rewind (held) 倒带 (长按) - + Re&wind 倒带(&W) - + Step backwards 步退 - + Solar sensor 太阳光传感器 - + Increase solar level 增加太阳光等级 - + Decrease solar level 降低太阳光等级 - + Brightest solar level 太阳光等级为最亮 - + Darkest solar level 太阳光等级为最暗 - + Brightness %1 亮度 %1 - + Game Boy Printer... Game Boy 打印机... - + BattleChip Gate... BattleChip Gate... - + Audio/&Video 音频/视频(&V) - + Frame size 画面大小 - + %1× %1× - + Toggle fullscreen 切换全屏 - + Lock aspect ratio 锁定纵横比 - + Force integer scaling 强制整数缩放 - + Interframe blending 帧间混合 - + Bilinear filtering 双线性过滤 - + Frame&skip 跳帧(&S) - + Mute 静音 - + FPS target 目标 FPS - + Native (59.7275) 原生 (59.7275) - + Take &screenshot 截图(&S) - + F12 F12 - + Record A/V... 录制音频/视频... - + Record GIF/WebP/APNG... 录制 GIF/WebP/APNG... - + Video layers 视频图层 - + Audio channels 音频声道 - + Adjust layer placement... 调整图层布局... - + &Tools 工具(&T) - + View &logs... 查看日志(&L)... - + Game &overrides... 覆写游戏(&O)... - + Game Pak sensors... 游戏卡带传感器... - + &Cheats... 作弊码(&C)... - + Settings... 设置... - + Open debugger console... 打开调试器控制台... - + Start &GDB server... 打开 GDB 服务器(&G)... - + Scripting... 脚本... - + + Game state views + + + + View &palette... 查看调色板(&P)... - + View &sprites... 查看精灵图(&S)... - + View &tiles... 查看图块(&T)... - + View &map... 查看映射(&M)... - + &Frame inspector... 框架检查器(&F)... - + View memory... 查看内存... - + Search memory... 搜索内存... - + View &I/O registers... 查看 I/O 寄存器(&I)... - + Record debug video log... 记录调试视频日志... - + Stop debug video log 停止记录调试视频日志 - + Exit fullscreen 退出全屏 - + GameShark Button (held) GameShark 键 (长按) - + Autofire 连发 - + Autofire A 连发 A - + Autofire B 连发 B - + Autofire L 连发 L - + Autofire R 连发 R - + Autofire Start 连发 Start - + Autofire Select 连发 Select - + Autofire Up 连发 上 - + Autofire Right 连发 右 - + Autofire Down 连发 下 - + Autofire Left 连发 左 - + Clear 清除 @@ -5181,40 +5168,55 @@ Download size: %3 ScriptingView - + Scripting 脚本 - + Run 运行 - + File 文件 - + Load recent script 载入历史脚本 - + Load script... 载入脚本... - + &Reset 重置(&R) - + 0 0 + + + Select script to load + 选择要载入的脚本 + + + + Lua scripts (*.lua) + Lua 脚本 (*.lua) + + + + All files (*.*) + 所有文件 (*.*) + SensorView @@ -5229,64 +5231,74 @@ Download size: %3 实时时钟 - + Fixed time 定时 - + System time 系统时间 - + Start time at 开始时间 - + Now 现在 - + + Offset time + + + + + sec + + + + MM/dd/yy hh:mm:ss AP yyyy/MM/dd HH:mm:ss - + Light sensor 光线传感器 - + Brightness 亮度 - + Tilt sensor 倾斜传感器 - - + + Set Y 设定 Y 轴 - - + + Set X 设定 X 轴 - + Gyroscope 陀螺仪 - + Sensitivity 灵敏度